Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 15 Apr 2015 01:25:15 +0000 (18:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 15 Apr 2015 01:25:15 +0000 (18:25 -0700)
Pull input subsystem updates from Dmitry Torokhov:
 "You will get the following new drivers:

   - Qualcomm PM8941 power key drver
   - ChipOne icn8318 touchscreen controller driver
   - Broadcom iProc touchscreen and keypad drivers
   - Semtech SX8654 I2C touchscreen controller driver

  ALPS driver now supports newer SS4 devices; Elantech got a fix that
  should make it work on some ASUS laptops; and a slew of other
  enhancements and random fixes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (51 commits)
  Input: alps - non interleaved V2 dualpoint has separate stick button bits
  Input: alps - fix touchpad buttons getting stuck when used with trackpoint
  Input: atkbd - document "no new force-release quirks" policy
  Input: ALPS - make alps_get_pkt_id_ss4_v2() and others static
  Input: ALPS - V7 devices can report 5-finger taps
  Input: ALPS - add support for SS4 touchpad devices
  Input: ALPS - refactor alps_set_abs_params_mt()
  Input: elantech - fix absolute mode setting on some ASUS laptops
  Input: atmel_mxt_ts - split out touchpad initialisation logic
  Input: atmel_mxt_ts - implement support for T100 touch object
  Input: cros_ec_keyb - fix clearing keyboard state on wakeup
  Input: gscps2 - drop pci_ids dependency
  Input: synaptics - allocate 3 slots to keep stability in image sensors
  Input: Revert "Revert "synaptics - use dmax in input_mt_assign_slots""
  Input: MT - make slot assignment work for overcovered solutions
  mfd: tc3589x: enforce device-tree only mode
  Input: tc3589x - localize platform data
  Input: tsc2007 - Convert msecs to jiffies only once
  Input: edt-ft5x06 - remove EV_SYN event report
  Input: edt-ft5x06 - allow to setting the maximum axes value through the DT
  ...

2965 files changed:
CREDITS
Documentation/ABI/stable/sysfs-devices [new file with mode: 0644]
Documentation/ABI/testing/configfs-usb-gadget-printer [new file with mode: 0644]
Documentation/ABI/testing/sysfs-bus-iio
Documentation/ABI/testing/sysfs-driver-hid
Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
Documentation/PCI/pci.txt
Documentation/acpi/apei/einj.txt
Documentation/atomic_ops.txt
Documentation/cgroups/cpusets.txt
Documentation/cma/debugfs.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/freescale/fsl,vf610-mscm-cpucfg.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/freescale/fsl,vf610-mscm-ir.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/gic.txt
Documentation/devicetree/bindings/arm/omap/crossbar.txt
Documentation/devicetree/bindings/arm/samsung/pmu.txt
Documentation/devicetree/bindings/ata/ahci-st.txt
Documentation/devicetree/bindings/gpio/gpio-fan.txt
Documentation/devicetree/bindings/i2c/i2c-davinci.txt
Documentation/devicetree/bindings/i2c/i2c-digicolor.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/i2c-jz4780.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/i2c-xlp9xx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/trivial-devices.txt
Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/iio/adc/mcp320x.txt [new file with mode: 0644]
Documentation/devicetree/bindings/iio/adc/mcp3422.txt [new file with mode: 0644]
Documentation/devicetree/bindings/iio/adc/ti-adc128s052.txt [new file with mode: 0644]
Documentation/devicetree/bindings/iio/st-sensors.txt
Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt [new file with mode: 0644]
Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt
Documentation/devicetree/bindings/interrupt-controller/st,sti-irq-syscfg.txt [new file with mode: 0644]
Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/arizona.txt
Documentation/devicetree/bindings/mfd/axp20x.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/da9150.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/mt6397.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.txt
Documentation/devicetree/bindings/mfd/qcom-rpm.txt
Documentation/devicetree/bindings/mfd/sky81452.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
Documentation/devicetree/bindings/mmc/mmc-card.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/sdhci-st.txt
Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt [new file with mode: 0644]
Documentation/devicetree/bindings/phy/dm816x-phy.txt [new file with mode: 0644]
Documentation/devicetree/bindings/phy/phy-miphy365x.txt
Documentation/devicetree/bindings/phy/samsung-phy.txt
Documentation/devicetree/bindings/phy/sun9i-usb-phy.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/brcm,cygnus-gpio.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinmux.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/marvell,armada-39x-pinctrl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt
Documentation/devicetree/bindings/pinctrl/qcom,pmic-mpp.txt
Documentation/devicetree/bindings/power/da9150-charger.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/reset/syscon-poweroff.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/act8865-regulator.txt
Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
Documentation/devicetree/bindings/spi/spi-img-spfi.txt
Documentation/devicetree/bindings/spi/spi-rockchip.txt
Documentation/devicetree/bindings/thermal/rcar-thermal.txt
Documentation/devicetree/bindings/usb/dwc3.txt
Documentation/devicetree/bindings/usb/renesas_usbhs.txt
Documentation/devicetree/bindings/usb/usbmisc-imx.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/devicetree/bindings/video/backlight/sky81452-backlight.txt [new file with mode: 0644]
Documentation/hid/hid-sensor.txt
Documentation/hwmon/it87
Documentation/hwmon/jc42
Documentation/hwmon/nct7904 [new file with mode: 0644]
Documentation/i2c/slave-eeprom-backend [new file with mode: 0644]
Documentation/i2c/slave-interface [new file with mode: 0644]
Documentation/i2c/summary
Documentation/kernel-parameters.txt
Documentation/kernel-per-CPU-kthreads.txt
Documentation/memory-barriers.txt
Documentation/pinctrl.txt
Documentation/power/regulator/consumer.txt
Documentation/rtc.txt
Documentation/scsi/ncr53c8xx.txt
Documentation/scsi/tmscsim.txt
Documentation/spi/spi-summary
Documentation/spi/spidev_test.c
Documentation/stable_kernel_rules.txt
Documentation/sysctl/kernel.txt
Documentation/timers/NO_HZ.txt
Documentation/usb/chipidea.txt
Documentation/usb/gadget-testing.txt
Documentation/virtual/kvm/api.txt
Documentation/virtual/kvm/devices/s390_flic.txt
Documentation/vm/cleancache.txt
Documentation/vm/unevictable-lru.txt
Documentation/x86/boot.txt
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/Kconfig
arch/alpha/kernel/pci.c
arch/alpha/kernel/rtc.c
arch/alpha/kernel/sys_nautilus.c
arch/arc/kernel/process.c
arch/arc/kernel/unwind.c
arch/arm/Kconfig
arch/arm/boot/dts/am4372.dtsi
arch/arm/boot/dts/am437x-gp-evm.dts
arch/arm/boot/dts/am437x-sk-evm.dts
arch/arm/boot/dts/am43x-epos-evm.dts
arch/arm/boot/dts/am57xx-beagle-x15.dts
arch/arm/boot/dts/dra7-evm.dts
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/dra72-evm.dts
arch/arm/boot/dts/dra72x.dtsi
arch/arm/boot/dts/dra74x.dtsi
arch/arm/boot/dts/exynos3250.dtsi
arch/arm/boot/dts/exynos4.dtsi
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/exynos5420.dtsi
arch/arm/boot/dts/omap4-duovero.dtsi
arch/arm/boot/dts/omap4-panda-common.dtsi
arch/arm/boot/dts/omap4-sdp.dts
arch/arm/boot/dts/omap4-var-som-om44.dtsi
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/omap5-cm-t54.dts
arch/arm/boot/dts/omap5-uevm.dts
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/stih416.dtsi
arch/arm/boot/dts/tegra114.dtsi
arch/arm/boot/dts/tegra124.dtsi
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/common/bL_switcher.c
arch/arm/include/asm/elf.h
arch/arm/include/asm/jump_label.h
arch/arm/include/asm/kvm_arm.h
arch/arm/include/asm/kvm_host.h
arch/arm/include/asm/kvm_mmio.h
arch/arm/include/asm/mach/time.h
arch/arm/include/uapi/asm/kvm.h
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/time.c
arch/arm/kvm/Kconfig
arch/arm/kvm/Makefile
arch/arm/kvm/arm.c
arch/arm/kvm/guest.c
arch/arm/kvm/interrupts_head.S
arch/arm/kvm/mmio.c
arch/arm/kvm/mmu.c
arch/arm/kvm/trace.h
arch/arm/mach-dove/pcie.c
arch/arm/mach-exynos/exynos.c
arch/arm/mach-exynos/suspend.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-mv78xx0/pcie.c
arch/arm/mach-omap2/cpuidle44xx.c
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/omap-wakeupgen.c
arch/arm/mach-omap2/omap-wakeupgen.h
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-orion5x/pci.c
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-shmobile/intc-sh73a0.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-tegra/cpuidle-tegra114.c
arch/arm/mach-tegra/cpuidle-tegra20.c
arch/arm/mach-tegra/cpuidle-tegra30.c
arch/arm/mach-tegra/iomap.h
arch/arm/mach-tegra/irq.c
arch/arm/mach-tegra/irq.h
arch/arm/mach-tegra/tegra.c
arch/arm/mach-ux500/cpu.c
arch/arm/mach-zynq/common.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/init.c
arch/arm/mm/mmap.c
arch/arm/plat-omap/counter_32k.c
arch/arm64/Kconfig
arch/arm64/include/asm/elf.h
arch/arm64/include/asm/esr.h
arch/arm64/include/asm/jump_label.h
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_mmio.h
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/include/asm/page.h
arch/arm64/include/asm/pgalloc.h
arch/arm64/include/asm/pgtable-hwdef.h
arch/arm64/include/asm/pgtable-types.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/tlb.h
arch/arm64/include/uapi/asm/kvm.h
arch/arm64/kernel/hw_breakpoint.c
arch/arm64/kernel/vdso.c
arch/arm64/kvm/Kconfig
arch/arm64/kvm/Makefile
arch/arm64/mm/init.c
arch/arm64/mm/mmap.c
arch/arm64/mm/mmu.c
arch/avr32/include/asm/elf.h
arch/blackfin/mach-common/smp.c
arch/c6x/kernel/process.c
arch/frv/kernel/signal.c
arch/frv/mb93090-mb00/pci-vdk.c
arch/hexagon/kernel/process.c
arch/ia64/Kconfig
arch/ia64/include/asm/page.h
arch/ia64/include/asm/pgalloc.h
arch/ia64/include/asm/pgtable.h
arch/ia64/kernel/ivt.S
arch/ia64/kernel/machine_kexec.c
arch/ia64/sn/kernel/io_init.c
arch/m32r/kernel/signal.c
arch/m68k/Kconfig
arch/m68k/coldfire/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/include/asm/mcfqspi.h
arch/m68k/kernel/pcibios.c
arch/m68k/lib/ashldi3.c
arch/m68k/lib/ashrdi3.c
arch/m68k/lib/divsi3.S
arch/m68k/lib/lshrdi3.c
arch/m68k/lib/modsi3.S
arch/m68k/lib/muldi3.c
arch/m68k/lib/mulsi3.S
arch/m68k/lib/udivsi3.S
arch/m68k/lib/umodsi3.S
arch/m68k/mac/oss.c
arch/metag/include/asm/processor.h
arch/metag/kernel/smp.c
arch/microblaze/kernel/signal.c
arch/microblaze/pci/pci-common.c
arch/mips/Kconfig
arch/mips/include/asm/asmmacro-32.h
arch/mips/include/asm/asmmacro.h
arch/mips/include/asm/elf.h
arch/mips/include/asm/fpu.h
arch/mips/include/asm/jump_label.h
arch/mips/include/asm/kdebug.h
arch/mips/include/asm/kvm_host.h
arch/mips/include/asm/processor.h
arch/mips/include/uapi/asm/kvm.h
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/genex.S
arch/mips/kernel/ptrace.c
arch/mips/kernel/r4k_fpu.S
arch/mips/kernel/traps.c
arch/mips/kvm/Makefile
arch/mips/kvm/emulate.c
arch/mips/kvm/fpu.S [new file with mode: 0644]
arch/mips/kvm/locore.S
arch/mips/kvm/mips.c
arch/mips/kvm/msa.S [new file with mode: 0644]
arch/mips/kvm/stats.c
arch/mips/kvm/tlb.c
arch/mips/kvm/trap_emul.c
arch/mips/lasat/sysctl.c
arch/mips/loongson/loongson-3/hpet.c
arch/mips/mm/mmap.c
arch/mips/pci/pci.c
arch/mn10300/unit-asb2305/pci.c
arch/nios2/include/asm/thread_info.h
arch/nios2/include/uapi/asm/ptrace.h
arch/nios2/kernel/entry.S
arch/nios2/kernel/process.c
arch/nios2/kernel/signal.c
arch/nios2/mm/cacheflush.c
arch/openrisc/kernel/process.c
arch/parisc/Kconfig
arch/parisc/include/asm/pgalloc.h
arch/parisc/include/asm/pgtable.h
arch/parisc/kernel/entry.S
arch/parisc/kernel/head.S
arch/parisc/mm/init.c
arch/powerpc/Kconfig
arch/powerpc/include/asm/elf.h
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/smu.h
arch/powerpc/kernel/prom.c
arch/powerpc/kvm/mpic.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/mm/mmap.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/perf/hv-24x7.c
arch/powerpc/platforms/85xx/p1022_rdk.c
arch/powerpc/platforms/powernv/opal-wrappers.S
arch/powerpc/platforms/pseries/hvCall.S
arch/powerpc/platforms/pseries/lpar.c
arch/s390/Kconfig
arch/s390/hypfs/inode.c
arch/s390/include/asm/elf.h
arch/s390/include/asm/jump_label.h
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/livepatch.h [new file with mode: 0644]
arch/s390/include/uapi/asm/kvm.h
arch/s390/include/uapi/asm/sie.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/time.c
arch/s390/kvm/diag.c
arch/s390/kvm/gaccess.c
arch/s390/kvm/gaccess.h
arch/s390/kvm/guestdbg.c
arch/s390/kvm/intercept.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/kvm-s390.h
arch/s390/kvm/priv.c
arch/s390/kvm/sigp.c
arch/s390/kvm/trace-s390.h
arch/s390/mm/mmap.c
arch/s390/pci/pci.c
arch/sh/Kconfig
arch/sh/drivers/pci/pci.c
arch/sh/kernel/dwarf.c
arch/sh/kernel/signal_32.c
arch/sh/kernel/signal_64.c
arch/sparc/Kconfig
arch/sparc/include/asm/jump_label.h
arch/sparc/kernel/leon_pci.c
arch/sparc/kernel/mdesc.c
arch/sparc/kernel/pci.c
arch/sparc/kernel/pcic.c
arch/sparc/kernel/time_32.c
arch/tile/Kconfig
arch/tile/kernel/pci.c
arch/tile/kernel/pci_gx.c
arch/tile/kernel/time.c
arch/um/Kconfig.um
arch/unicore32/kernel/pci.c
arch/x86/Kconfig
arch/x86/boot/compressed/aslr.c
arch/x86/boot/compressed/head_32.S
arch/x86/boot/compressed/head_64.S
arch/x86/boot/compressed/misc.c
arch/x86/boot/compressed/misc.h
arch/x86/boot/string.c
arch/x86/boot/video-mode.c
arch/x86/boot/video.c
arch/x86/boot/video.h
arch/x86/configs/i386_defconfig
arch/x86/configs/x86_64_defconfig
arch/x86/crypto/crc32c-pcl-intel-asm_64.S
arch/x86/crypto/twofish-x86_64-asm_64.S
arch/x86/ia32/Makefile
arch/x86/ia32/ia32_signal.c
arch/x86/ia32/ia32entry.S
arch/x86/ia32/nosyscall.c [deleted file]
arch/x86/ia32/sys_ia32.c
arch/x86/ia32/syscall_ia32.c [deleted file]
arch/x86/include/asm/alternative-asm.h
arch/x86/include/asm/alternative.h
arch/x86/include/asm/apic.h
arch/x86/include/asm/barrier.h
arch/x86/include/asm/calling.h
arch/x86/include/asm/compat.h
arch/x86/include/asm/cpu.h
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/desc.h
arch/x86/include/asm/dwarf2.h
arch/x86/include/asm/e820.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/elf.h
arch/x86/include/asm/fpu-internal.h
arch/x86/include/asm/hw_irq.h
arch/x86/include/asm/insn.h
arch/x86/include/asm/iommu_table.h
arch/x86/include/asm/irqflags.h
arch/x86/include/asm/jump_label.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/kvm_para.h
arch/x86/include/asm/livepatch.h
arch/x86/include/asm/mce.h
arch/x86/include/asm/microcode.h
arch/x86/include/asm/microcode_intel.h
arch/x86/include/asm/mwait.h
arch/x86/include/asm/page_types.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/pgalloc.h
arch/x86/include/asm/pgtable-2level_types.h
arch/x86/include/asm/pgtable-3level_types.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/pgtable_64_types.h
arch/x86/include/asm/pgtable_types.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/ptrace.h
arch/x86/include/asm/pvclock.h
arch/x86/include/asm/segment.h
arch/x86/include/asm/setup.h
arch/x86/include/asm/sigcontext.h
arch/x86/include/asm/sighandling.h
arch/x86/include/asm/smap.h
arch/x86/include/asm/smp.h
arch/x86/include/asm/special_insns.h
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/uaccess_64.h
arch/x86/include/uapi/asm/bootparam.h
arch/x86/include/uapi/asm/msr-index.h
arch/x86/include/uapi/asm/ptrace-abi.h
arch/x86/include/uapi/asm/ptrace.h
arch/x86/include/uapi/asm/sigcontext.h
arch/x86/include/uapi/asm/vmx.h
arch/x86/kernel/Makefile
arch/x86/kernel/alternative.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/x2apic_cluster.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/asm-offsets_32.c
arch/x86/kernel/asm-offsets_64.c
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/cpu/intel_pt.h [new file with mode: 0644]
arch/x86/kernel/cpu/mcheck/mce-internal.h
arch/x86/kernel/cpu/mcheck/mce-severity.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/cpu/mcheck/mce_intel.c
arch/x86/kernel/cpu/microcode/amd.c
arch/x86/kernel/cpu/microcode/core_early.c
arch/x86/kernel/cpu/microcode/intel.c
arch/x86/kernel/cpu/microcode/intel_early.c
arch/x86/kernel/cpu/microcode/intel_lib.c
arch/x86/kernel/cpu/mkcapflags.sh
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_amd.c
arch/x86/kernel/cpu/perf_event_amd_ibs.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_bts.c [new file with mode: 0644]
arch/x86/kernel/cpu/perf_event_intel_cqm.c [new file with mode: 0644]
arch/x86/kernel/cpu/perf_event_intel_ds.c
arch/x86/kernel/cpu/perf_event_intel_lbr.c
arch/x86/kernel/cpu/perf_event_intel_pt.c [new file with mode: 0644]
arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c
arch/x86/kernel/cpu/scattered.c
arch/x86/kernel/crash.c
arch/x86/kernel/devicetree.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/dumpstack_32.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/e820.c
arch/x86/kernel/early_printk.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/head64.c
arch/x86/kernel/head_32.S
arch/x86/kernel/head_64.S
arch/x86/kernel/i387.c
arch/x86/kernel/ioport.c
arch/x86/kernel/irq.c
arch/x86/kernel/irq_32.c
arch/x86/kernel/irq_64.c
arch/x86/kernel/irqinit.c
arch/x86/kernel/kgdb.c
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/kvm.c
arch/x86/kernel/module.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/perf_regs.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/pvclock.c
arch/x86/kernel/relocate_kernel_32.S
arch/x86/kernel/relocate_kernel_64.S
arch/x86/kernel/setup.c
arch/x86/kernel/signal.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/sys_x86_64.c
arch/x86/kernel/syscall_32.c
arch/x86/kernel/test_rodata.c
arch/x86/kernel/time.c
arch/x86/kernel/traps.c
arch/x86/kernel/uprobes.c
arch/x86/kernel/vm86_32.c
arch/x86/kernel/vsyscall_gtod.c
arch/x86/kernel/xsave.c
arch/x86/kvm/Makefile
arch/x86/kvm/cpuid.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/emulate.c
arch/x86/kvm/i8254.c
arch/x86/kvm/i8254.h
arch/x86/kvm/i8259.c
arch/x86/kvm/ioapic.c
arch/x86/kvm/ioapic.h
arch/x86/kvm/irq.h
arch/x86/kvm/lapic.c
arch/x86/kvm/lapic.h
arch/x86/kvm/mmu.c
arch/x86/kvm/pmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lguest/boot.c
arch/x86/lib/atomic64_cx8_32.S
arch/x86/lib/checksum_32.S
arch/x86/lib/clear_page_64.S
arch/x86/lib/copy_page_64.S
arch/x86/lib/copy_user_64.S
arch/x86/lib/csum-copy_64.S
arch/x86/lib/insn.c
arch/x86/lib/memcpy_64.S
arch/x86/lib/memmove_64.S
arch/x86/lib/memset_64.S
arch/x86/lib/msr-reg.S
arch/x86/lib/rwsem.S
arch/x86/lib/thunk_32.S
arch/x86/lib/thunk_64.S
arch/x86/lib/usercopy_64.c
arch/x86/lib/x86-opcode-map.txt
arch/x86/mm/Makefile
arch/x86/mm/fault.c
arch/x86/mm/init.c
arch/x86/mm/init_64.c
arch/x86/mm/ioremap.c
arch/x86/mm/memtest.c [deleted file]
arch/x86/mm/mmap.c
arch/x86/mm/numa.c
arch/x86/mm/pageattr.c
arch/x86/mm/pat.c
arch/x86/mm/pgtable.c
arch/x86/oprofile/backtrace.c
arch/x86/pci/common.c
arch/x86/platform/efi/efi-bgrt.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_32.c
arch/x86/platform/efi/efi_64.c
arch/x86/platform/intel-quark/imr_selftest.c
arch/x86/platform/olpc/olpc-xo1-sci.c
arch/x86/platform/olpc/olpc-xo15-sci.c
arch/x86/platform/uv/tlb_uv.c
arch/x86/power/cpu.c
arch/x86/syscalls/syscall_32.tbl
arch/x86/syscalls/syscall_64.tbl
arch/x86/um/asm/barrier.h
arch/x86/um/sys_call_table_64.c
arch/x86/vdso/Makefile
arch/x86/vdso/vclock_gettime.c
arch/x86/vdso/vdso32/syscall.S
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/smp.c
arch/x86/xen/suspend.c
arch/x86/xen/xen-asm_64.S
arch/xtensa/kernel/pci.c
arch/xtensa/kernel/signal.c
block/blk-map.c
block/blk-mq.c
block/scsi_ioctl.c
drivers/acpi/ac.c
drivers/acpi/acpi_pad.c
drivers/acpi/battery.c
drivers/acpi/pci_root.c
drivers/acpi/processor_idle.c
drivers/acpi/sbs.c
drivers/ata/Makefile
drivers/ata/acard-ahci.c
drivers/ata/ahci.c
drivers/ata/ahci_st.c
drivers/ata/ahci_xgene.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/libata-trace.c [new file with mode: 0644]
drivers/ata/libata.h
drivers/ata/pata_atp867x.c
drivers/ata/pata_cs5520.c
drivers/ata/pata_hpt3x3.c
drivers/ata/pata_ninja32.c
drivers/ata/pata_pdc2027x.c
drivers/ata/pata_scc.c
drivers/ata/pata_sil680.c
drivers/ata/pdc_adma.c
drivers/ata/sata_dwc_460ex.c
drivers/ata/sata_inic162x.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/ata/sata_promise.c
drivers/ata/sata_qstor.c
drivers/ata/sata_sil.c
drivers/ata/sata_sil24.c
drivers/ata/sata_svw.c
drivers/ata/sata_sx4.c
drivers/ata/sata_via.c
drivers/ata/sata_vsc.c
drivers/base/attribute_container.c
drivers/base/bus.c
drivers/base/cacheinfo.c
drivers/base/class.c
drivers/base/core.c
drivers/base/dd.c
drivers/base/dma-mapping.c
drivers/base/driver.c
drivers/base/firmware_class.c
drivers/base/map.c
drivers/base/memory.c
drivers/base/node.c
drivers/base/platform.c
drivers/base/property.c
drivers/base/regmap/Makefile
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap.c
drivers/base/regmap/trace.h [new file with mode: 0644]
drivers/base/soc.c
drivers/block/cpqarray.c
drivers/bus/omap_l3_noc.c
drivers/bus/omap_l3_smx.c
drivers/char/ipmi/ipmi_powernv.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ipmi/ipmi_ssif.c
drivers/char/mem.c
drivers/char/tile-srom.c
drivers/clocksource/arm_arch_timer.c
drivers/clocksource/dw_apb_timer_of.c
drivers/clocksource/em_sti.c
drivers/clocksource/sh_cmt.c
drivers/clocksource/sh_tmu.c
drivers/clocksource/sun4i_timer.c
drivers/clocksource/tegra20_timer.c
drivers/clocksource/time-efm32.c
drivers/clocksource/timer-atmel-pit.c
drivers/clocksource/timer-sun5i.c
drivers/cpufreq/cpufreq.c
drivers/cpuidle/cpuidle.c
drivers/cpuidle/driver.c
drivers/cpuidle/sysfs.c
drivers/dma/Kconfig
drivers/dma/Makefile
drivers/dma/cppi41.c
drivers/dma/dmaengine.c
drivers/dma/intel_mid_dma.c [deleted file]
drivers/dma/intel_mid_dma_regs.h [deleted file]
drivers/dma/ste_dma40.c
drivers/edac/amd64_edac.c
drivers/edac/amd64_edac.h
drivers/edac/amd64_edac_dbg.c
drivers/edac/amd64_edac_inj.c
drivers/edac/edac_core.h
drivers/edac/edac_mc.c
drivers/edac/edac_mc_sysfs.c
drivers/edac/edac_module.c
drivers/edac/edac_module.h
drivers/edac/highbank_mc_edac.c
drivers/edac/i7core_edac.c
drivers/edac/i82443bxgx_edac.c
drivers/edac/i82860_edac.c
drivers/edac/i82875p_edac.c
drivers/edac/i82975x_edac.c
drivers/edac/mpc85xx_edac.c
drivers/edac/octeon_edac-lmc.c
drivers/edac/ppc4xx_edac.c
drivers/edac/synopsys_edac.c
drivers/extcon/extcon-arizona.c
drivers/firmware/dmi_scan.c
drivers/firmware/efi/libstub/arm-stub.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/fdt.c
drivers/gpio/gpio-arizona.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_trace.h
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_trace.h
drivers/gpu/drm/msm/edp/edp_ctrl.c
drivers/gpu/drm/radeon/radeon_trace.h
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-core.c
drivers/hid/hid-debug.c
drivers/hid/hid-huion.c [deleted file]
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-kye.c
drivers/hid/hid-lg.c
drivers/hid/hid-lg.h
drivers/hid/hid-lg4ff.c
drivers/hid/hid-lg4ff.h [new file with mode: 0644]
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-rmi.c
drivers/hid/hid-sensor-custom.c [new file with mode: 0644]
drivers/hid/hid-sensor-hub.c
drivers/hid/hid-sony.c
drivers/hid/hid-steelseries.c
drivers/hid/hid-uclogic.c
drivers/hid/hid-wiimote-modules.c
drivers/hid/hid-wiimote.h
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-pidff.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/wacom.h
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
drivers/hid/wacom_wac.h
drivers/hsi/clients/Kconfig
drivers/hsi/clients/Makefile
drivers/hsi/clients/cmt_speech.c [new file with mode: 0644]
drivers/hsi/clients/nokia-modem.c
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/coretemp.c
drivers/hwmon/gpio-fan.c
drivers/hwmon/ibmpex.c
drivers/hwmon/ibmpowernv.c
drivers/hwmon/it87.c
drivers/hwmon/jc42.c
drivers/hwmon/nct6775.c
drivers/hwmon/nct7904.c [new file with mode: 0644]
drivers/hwmon/pwm-fan.c
drivers/hwmon/vexpress.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-at91.c
drivers/i2c/busses/i2c-axxia.c
drivers/i2c/busses/i2c-bcm-iproc.c
drivers/i2c/busses/i2c-bcm2835.c
drivers/i2c/busses/i2c-cadence.c
drivers/i2c/busses/i2c-cpm.c
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-digicolor.c [new file with mode: 0644]
drivers/i2c/busses/i2c-dln2.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-img-scb.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-ismt.c
drivers/i2c/busses/i2c-jz4780.c [new file with mode: 0644]
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-nomadik.c
drivers/i2c/busses/i2c-opal.c
drivers/i2c/busses/i2c-pmcmsp.c
drivers/i2c/busses/i2c-powermac.c
drivers/i2c/busses/i2c-qup.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/busses/i2c-viperboard.c
drivers/i2c/busses/i2c-wmt.c
drivers/i2c/busses/i2c-xlp9xx.c [new file with mode: 0644]
drivers/i2c/i2c-core.c
drivers/i2c/i2c-slave-eeprom.c
drivers/i2c/muxes/i2c-mux-gpio.c
drivers/i2c/muxes/i2c-mux-pca954x.c
drivers/ide/ide-lib.c
drivers/ide/ide-probe.c
drivers/idle/intel_idle.c
drivers/iio/accel/bmc150-accel.c
drivers/iio/accel/hid-sensor-accel-3d.c
drivers/iio/accel/kxcjk-1013.c
drivers/iio/accel/mma9551.c
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/adc/Kconfig
drivers/iio/adc/Makefile
drivers/iio/adc/ad7793.c
drivers/iio/adc/da9150-gpadc.c [new file with mode: 0644]
drivers/iio/adc/max1027.c
drivers/iio/adc/vf610_adc.c
drivers/iio/common/hid-sensors/hid-sensor-attributes.c
drivers/iio/common/hid-sensors/hid-sensor-trigger.c
drivers/iio/common/ssp_sensors/ssp_dev.c
drivers/iio/dac/Kconfig
drivers/iio/dac/max517.c
drivers/iio/gyro/bmg160.c
drivers/iio/gyro/hid-sensor-gyro-3d.c
drivers/iio/gyro/itg3200_core.c
drivers/iio/gyro/st_gyro_core.c
drivers/iio/imu/inv_mpu6050/Makefile
drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c [new file with mode: 0644]
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
drivers/iio/imu/kmx61.c
drivers/iio/industrialio-buffer.c
drivers/iio/kfifo_buf.c
drivers/iio/light/Kconfig
drivers/iio/light/Makefile
drivers/iio/light/cm3232.c
drivers/iio/light/cm3323.c [new file with mode: 0644]
drivers/iio/light/gp2ap020a00f.c
drivers/iio/light/hid-sensor-als.c
drivers/iio/light/hid-sensor-prox.c
drivers/iio/light/jsa1212.c
drivers/iio/light/ltr501.c
drivers/iio/magnetometer/hid-sensor-magn-3d.c
drivers/iio/magnetometer/mag3110.c
drivers/iio/orientation/hid-sensor-incl-3d.c
drivers/iio/pressure/Kconfig
drivers/iio/pressure/Makefile
drivers/iio/pressure/hid-sensor-press.c
drivers/iio/pressure/ms5611.h [new file with mode: 0644]
drivers/iio/pressure/ms5611_core.c [new file with mode: 0644]
drivers/iio/pressure/ms5611_i2c.c [new file with mode: 0644]
drivers/iio/pressure/ms5611_spi.c [new file with mode: 0644]
drivers/iio/proximity/sx9500.c
drivers/iio/temperature/mlx90614.c
drivers/infiniband/hw/ipath/ipath_file_ops.c
drivers/infiniband/hw/qib/qib_file_ops.c
drivers/input/input-mt.c
drivers/iommu/of_iommu.c
drivers/irqchip/Kconfig
drivers/irqchip/Makefile
drivers/irqchip/irq-armada-370-xp.c
drivers/irqchip/irq-crossbar.c
drivers/irqchip/irq-digicolor.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-mips-gic.c
drivers/irqchip/irq-renesas-irqc.c
drivers/irqchip/irq-st.c [new file with mode: 0644]
drivers/irqchip/irq-tegra.c [new file with mode: 0644]
drivers/irqchip/irq-vf610-mscm-ir.c [new file with mode: 0644]
drivers/isdn/hardware/mISDN/mISDNinfineon.c
drivers/isdn/mISDN/dsp_cmx.c
drivers/isdn/mISDN/dsp_core.c
drivers/md/md.c
drivers/md/raid0.c
drivers/media/dvb-frontends/m88ds3103.c
drivers/media/dvb-frontends/rtl2832.c
drivers/media/dvb-frontends/si2168_priv.h
drivers/media/dvb-frontends/tda10071_priv.h
drivers/media/pci/cx23885/cx23885-417.c
drivers/media/platform/s5p-jpeg/jpeg-core.c
drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/platform/s5p-mfc/s5p_mfc_common.h
drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
drivers/media/platform/s5p-tv/Kconfig
drivers/media/platform/sh_veu.c
drivers/media/platform/soc_camera/atmel-isi.c
drivers/media/platform/soc_camera/soc_camera.c
drivers/media/tuners/msi001.c
drivers/media/usb/dvb-usb-v2/rtl28xxu.c
drivers/media/usb/gspca/Kconfig
drivers/media/v4l2-core/videobuf2-core.c
drivers/media/v4l2-core/videobuf2-dma-contig.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/ab8500-debugfs.c
drivers/mfd/ab8500-sysctrl.c
drivers/mfd/arizona-core.c
drivers/mfd/arizona-i2c.c
drivers/mfd/arizona-irq.c
drivers/mfd/arizona-spi.c
drivers/mfd/axp20x.c
drivers/mfd/da9052-irq.c
drivers/mfd/da9052-spi.c
drivers/mfd/da9150-core.c
drivers/mfd/dln2.c
drivers/mfd/hi6421-pmic-core.c
drivers/mfd/intel_quark_i2c_gpio.c [new file with mode: 0644]
drivers/mfd/intel_soc_pmic_core.c
drivers/mfd/kempld-core.c
drivers/mfd/lpc_ich.c
drivers/mfd/max77693.c
drivers/mfd/max77843.c [new file with mode: 0644]
drivers/mfd/mc13xxx-core.c
drivers/mfd/menelaus.c
drivers/mfd/mfd-core.c
drivers/mfd/mt6397-core.c [new file with mode: 0644]
drivers/mfd/qcom-spmi-pmic.c
drivers/mfd/qcom_rpm.c
drivers/mfd/rk808.c
drivers/mfd/rtl8411.c
drivers/mfd/rts5209.c
drivers/mfd/rts5227.c
drivers/mfd/rts5229.c
drivers/mfd/rts5249.c
drivers/mfd/rtsx_gops.c [deleted file]
drivers/mfd/rtsx_pcr.c
drivers/mfd/rtsx_pcr.h
drivers/mfd/sec-core.c
drivers/mfd/sec-irq.c
drivers/mfd/si476x-i2c.c
drivers/mfd/sky81452.c [new file with mode: 0644]
drivers/mfd/ti_am335x_tscadc.c
drivers/mfd/tps65010.c
drivers/mfd/twl4030-power.c
drivers/mfd/twl6040.c
drivers/mfd/vexpress-sysreg.c
drivers/mfd/wm5102-tables.c
drivers/misc/enclosure.c
drivers/misc/mei/amthif.c
drivers/misc/mei/main.c
drivers/misc/mei/pci-me.c
drivers/misc/sgi-xp/xpc_main.c
drivers/mmc/core/core.c
drivers/mmc/core/mmc.c
drivers/mmc/core/pwrseq.c
drivers/mmc/core/pwrseq.h
drivers/mmc/core/pwrseq_emmc.c
drivers/mmc/core/pwrseq_simple.c
drivers/mmc/core/sd.c
drivers/mmc/core/sdio.c
drivers/mmc/host/Kconfig
drivers/mmc/host/Makefile
drivers/mmc/host/atmel-mci-regs.h
drivers/mmc/host/dw_mmc-exynos.c
drivers/mmc/host/dw_mmc-exynos.h
drivers/mmc/host/dw_mmc-rockchip.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/dw_mmc.h
drivers/mmc/host/mmc_spi.c
drivers/mmc/host/mmci.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/sdhci-acpi.c
drivers/mmc/host/sdhci-bcm-kona.c
drivers/mmc/host/sdhci-bcm2835.c
drivers/mmc/host/sdhci-cns3xxx.c
drivers/mmc/host/sdhci-dove.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-iproc.c [new file with mode: 0644]
drivers/mmc/host/sdhci-msm.c
drivers/mmc/host/sdhci-of-arasan.c
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-of-hlwd.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-pltfm.c
drivers/mmc/host/sdhci-sirf.c
drivers/mmc/host/sdhci-spear.c
drivers/mmc/host/sdhci-st.c
drivers/mmc/host/sdhci-tegra.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/sh_mmcif.c
drivers/mmc/host/sunxi-mmc.c
drivers/mmc/host/tmio_mmc_pio.c
drivers/mmc/host/wmt-sdmmc.c
drivers/mtd/nand/gpmi-nand/gpmi-lib.c
drivers/mtd/nand/hisi504_nand.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
drivers/net/phy/dp83640.c
drivers/net/wireless/airo.c
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/wcn36xx/smd.c
drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_brcmsmac.h [new file with mode: 0644]
drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h [new file with mode: 0644]
drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_brcmsmac_tx.h [new file with mode: 0644]
drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h
drivers/net/wireless/iwlwifi/iwl-devtrace-data.h [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-devtrace-io.h [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-devtrace-iwlwifi.h [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-devtrace-msg.h [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-devtrace-ucode.h [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-devtrace.h
drivers/net/wireless/rtlwifi/rtl8723be/dm.c
drivers/net/wireless/rtlwifi/rtl8821ae/dm.c
drivers/of/base.c
drivers/of/device.c
drivers/of/of_pci.c
drivers/of/platform.c
drivers/parisc/eisa_enumerator.c
drivers/pci/host-bridge.c
drivers/pci/host/Kconfig
drivers/pci/host/Makefile
drivers/pci/host/pci-exynos.c
drivers/pci/host/pci-keystone-dw.c
drivers/pci/host/pci-layerscape.c
drivers/pci/host/pci-mvebu.c
drivers/pci/host/pci-rcar-gen2.c
drivers/pci/host/pci-versatile.c
drivers/pci/host/pcie-designware.c
drivers/pci/host/pcie-iproc-platform.c [new file with mode: 0644]
drivers/pci/host/pcie-iproc.c [new file with mode: 0644]
drivers/pci/host/pcie-iproc.h [new file with mode: 0644]
drivers/pci/host/pcie-rcar.c
drivers/pci/host/pcie-spear13xx.c
drivers/pci/hotplug/cpci_hotplug_pci.c
drivers/pci/hotplug/ibmphp_core.c
drivers/pci/pci-acpi.c
drivers/pci/pci-label.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aer/aerdrv_errprint.c
drivers/pci/pcie/aspm.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/remove.c
drivers/pci/setup-bus.c
drivers/pci/setup-irq.c
drivers/pci/setup-res.c
drivers/phy/Kconfig
drivers/phy/Makefile
drivers/phy/phy-berlin-sata.c
drivers/phy/phy-berlin-usb.c
drivers/phy/phy-dm816x-usb.c [new file with mode: 0644]
drivers/phy/phy-exynos5-usbdrd.c
drivers/phy/phy-miphy28lp.c
drivers/phy/phy-miphy365x.c
drivers/phy/phy-omap-control.c
drivers/phy/phy-omap-usb2.c
drivers/phy/phy-qcom-ufs.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-sun9i-usb.c [new file with mode: 0644]
drivers/phy/phy-ti-pipe3.c
drivers/phy/phy-xgene.c
drivers/pinctrl/Kconfig
drivers/pinctrl/Makefile
drivers/pinctrl/bcm/Kconfig [new file with mode: 0644]
drivers/pinctrl/bcm/Makefile [new file with mode: 0644]
drivers/pinctrl/bcm/pinctrl-bcm281xx.c [new file with mode: 0644]
drivers/pinctrl/bcm/pinctrl-bcm2835.c [new file with mode: 0644]
drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c [new file with mode: 0644]
drivers/pinctrl/bcm/pinctrl-cygnus-mux.c [new file with mode: 0644]
drivers/pinctrl/freescale/pinctrl-imx.c
drivers/pinctrl/freescale/pinctrl-vf610.c
drivers/pinctrl/intel/Kconfig
drivers/pinctrl/intel/Makefile
drivers/pinctrl/intel/pinctrl-intel.c [new file with mode: 0644]
drivers/pinctrl/intel/pinctrl-intel.h [new file with mode: 0644]
drivers/pinctrl/intel/pinctrl-sunrisepoint.c [new file with mode: 0644]
drivers/pinctrl/mediatek/Kconfig [new file with mode: 0644]
drivers/pinctrl/mediatek/Makefile [new file with mode: 0644]
drivers/pinctrl/mediatek/pinctrl-mt8135.c [new file with mode: 0644]
drivers/pinctrl/mediatek/pinctrl-mt8173.c [new file with mode: 0644]
drivers/pinctrl/mediatek/pinctrl-mtk-common.c [new file with mode: 0644]
drivers/pinctrl/mediatek/pinctrl-mtk-common.h [new file with mode: 0644]
drivers/pinctrl/mediatek/pinctrl-mtk-mt8135.h [new file with mode: 0644]
drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h [new file with mode: 0644]
drivers/pinctrl/meson/Makefile
drivers/pinctrl/meson/pinctrl-meson.c
drivers/pinctrl/meson/pinctrl-meson.h
drivers/pinctrl/meson/pinctrl-meson8.c
drivers/pinctrl/meson/pinctrl-meson8b.c [new file with mode: 0644]
drivers/pinctrl/mvebu/Kconfig
drivers/pinctrl/mvebu/Makefile
drivers/pinctrl/mvebu/pinctrl-armada-370.c
drivers/pinctrl/mvebu/pinctrl-armada-375.c
drivers/pinctrl/mvebu/pinctrl-armada-38x.c
drivers/pinctrl/mvebu/pinctrl-armada-39x.c [new file with mode: 0644]
drivers/pinctrl/mvebu/pinctrl-armada-xp.c
drivers/pinctrl/mvebu/pinctrl-kirkwood.c
drivers/pinctrl/mvebu/pinctrl-orion.c
drivers/pinctrl/nomadik/pinctrl-abx500.c
drivers/pinctrl/pinconf-generic.c
drivers/pinctrl/pinctrl-amd.c [new file with mode: 0644]
drivers/pinctrl/pinctrl-amd.h [new file with mode: 0644]
drivers/pinctrl/pinctrl-as3722.c
drivers/pinctrl/pinctrl-at91.c
drivers/pinctrl/pinctrl-bcm281xx.c [deleted file]
drivers/pinctrl/pinctrl-bcm2835.c [deleted file]
drivers/pinctrl/pinctrl-lantiq.h
drivers/pinctrl/pinctrl-palmas.c
drivers/pinctrl/pinctrl-single.c
drivers/pinctrl/pinctrl-st.c
drivers/pinctrl/pinctrl-tegra.c
drivers/pinctrl/pinctrl-tegra.h
drivers/pinctrl/pinctrl-tegra114.c
drivers/pinctrl/pinctrl-tegra124.c
drivers/pinctrl/pinctrl-tegra20.c
drivers/pinctrl/pinctrl-tegra210.c [new file with mode: 0644]
drivers/pinctrl/pinctrl-tegra30.c
drivers/pinctrl/pinctrl-tz1090-pdc.c
drivers/pinctrl/pinctrl-tz1090.c
drivers/pinctrl/qcom/pinctrl-msm.c
drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
drivers/pinctrl/samsung/pinctrl-exynos.c
drivers/pinctrl/samsung/pinctrl-samsung.c
drivers/pinctrl/samsung/pinctrl-samsung.h
drivers/pinctrl/sh-pfc/core.c
drivers/pinctrl/sh-pfc/core.h
drivers/pinctrl/sh-pfc/gpio.c
drivers/pinctrl/sh-pfc/pfc-r8a7790.c
drivers/pinctrl/sh-pfc/sh_pfc.h
drivers/pinctrl/sirf/pinctrl-sirf.c
drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c
drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c
drivers/pinctrl/sunxi/pinctrl-sun6i-a31s.c
drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c
drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c
drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c
drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c
drivers/pinctrl/vt8500/pinctrl-vt8500.c
drivers/pinctrl/vt8500/pinctrl-wm8505.c
drivers/pinctrl/vt8500/pinctrl-wm8650.c
drivers/pinctrl/vt8500/pinctrl-wm8750.c
drivers/pinctrl/vt8500/pinctrl-wm8850.c
drivers/platform/x86/compal-laptop.c
drivers/pnp/quirks.c
drivers/power/88pm860x_battery.c
drivers/power/88pm860x_charger.c
drivers/power/Kconfig
drivers/power/Makefile
drivers/power/ab8500_btemp.c
drivers/power/ab8500_charger.c
drivers/power/ab8500_fg.c
drivers/power/abx500_chargalg.c
drivers/power/apm_power.c
drivers/power/axp288_fuel_gauge.c [new file with mode: 0644]
drivers/power/bq2415x_charger.c
drivers/power/bq24190_charger.c
drivers/power/bq24735-charger.c
drivers/power/bq27x00_battery.c
drivers/power/charger-manager.c
drivers/power/collie_battery.c
drivers/power/da9030_battery.c
drivers/power/da9052-battery.c
drivers/power/da9150-charger.c [new file with mode: 0644]
drivers/power/ds2760_battery.c
drivers/power/ds2780_battery.c
drivers/power/ds2781_battery.c
drivers/power/ds2782_battery.c
drivers/power/generic-adc-battery.c
drivers/power/goldfish_battery.c
drivers/power/gpio-charger.c
drivers/power/intel_mid_battery.c
drivers/power/ipaq_micro_battery.c
drivers/power/isp1704_charger.c
drivers/power/jz4740-battery.c
drivers/power/lp8727_charger.c
drivers/power/lp8788-charger.c
drivers/power/ltc2941-battery-gauge.c
drivers/power/max14577_charger.c
drivers/power/max17040_battery.c
drivers/power/max17042_battery.c
drivers/power/max77693_charger.c
drivers/power/max8903_charger.c
drivers/power/max8925_power.c
drivers/power/max8997_charger.c
drivers/power/max8998_charger.c
drivers/power/olpc_battery.c
drivers/power/pcf50633-charger.c
drivers/power/pda_power.c
drivers/power/pm2301_charger.c
drivers/power/pm2301_charger.h
drivers/power/pmu_battery.c
drivers/power/power_supply_core.c
drivers/power/power_supply_leds.c
drivers/power/power_supply_sysfs.c
drivers/power/reset/Kconfig
drivers/power/reset/Makefile
drivers/power/reset/at91-poweroff.c
drivers/power/reset/at91-reset.c
drivers/power/reset/hisi-reboot.c
drivers/power/reset/keystone-reset.c
drivers/power/reset/st-poweroff.c
drivers/power/reset/syscon-poweroff.c [new file with mode: 0644]
drivers/power/reset/syscon-reboot.c
drivers/power/reset/vexpress-poweroff.c
drivers/power/reset/xgene-reboot.c
drivers/power/rt5033_battery.c
drivers/power/rx51_battery.c
drivers/power/s3c_adc_battery.c
drivers/power/sbs-battery.c
drivers/power/smb347-charger.c
drivers/power/test_power.c
drivers/power/tosa_battery.c
drivers/power/tps65090-charger.c
drivers/power/twl4030_charger.c
drivers/power/twl4030_madc_battery.c
drivers/power/wm831x_backup.c
drivers/power/wm831x_power.c
drivers/power/wm8350_power.c
drivers/power/wm97xx_battery.c
drivers/power/z2_battery.c
drivers/regulator/act8865-regulator.c
drivers/regulator/arizona-ldo1.c
drivers/regulator/arizona-micsupp.c
drivers/regulator/core.c
drivers/regulator/da9211-regulator.c
drivers/regulator/dbx500-prcmu.c
drivers/regulator/devres.c
drivers/regulator/max77693.c
drivers/regulator/max8660.c
drivers/regulator/palmas-regulator.c
drivers/regulator/qcom_rpm-regulator.c
drivers/regulator/stw481x-vmmc.c
drivers/regulator/wm8350-regulator.c
drivers/rtc/class.c
drivers/rtc/interface.c
drivers/rtc/rtc-ab3100.c
drivers/rtc/rtc-hid-sensor-time.c
drivers/rtc/rtc-mc13xxx.c
drivers/rtc/rtc-mxc.c
drivers/rtc/rtc-s5m.c
drivers/rtc/rtc-test.c
drivers/rtc/systohc.c
drivers/s390/scsi/zfcp_erp.c
drivers/scsi/be2iscsi/be_cmds.c
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/ch.c
drivers/scsi/osd/osd_initiator.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_nx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/sg.c
drivers/scsi/ufs/ufshcd.c
drivers/spi/Kconfig
drivers/spi/spi-atmel.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-bcm53xx.c
drivers/spi/spi-bfin5xx.c
drivers/spi/spi-bitbang-txrx.h
drivers/spi/spi-dw-mid.c
drivers/spi/spi-dw.c
drivers/spi/spi-dw.h
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi-img-spfi.c
drivers/spi/spi-imx.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-octeon.c
drivers/spi/spi-omap-100k.c
drivers/spi/spi-omap-uwire.c
drivers/spi/spi-pl022.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-qup.c
drivers/spi/spi-rockchip.c
drivers/spi/spi-rspi.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-sc18is602.c
drivers/spi/spi-st-ssc4.c
drivers/spi/spi.c
drivers/spi/spidev.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/android/ion/ion.c
drivers/staging/android/ion/ion_test.c
drivers/staging/android/sync.c
drivers/staging/comedi/Kconfig
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/comedi_internal.h
drivers/staging/comedi/comedi_pci.c
drivers/staging/comedi/comedi_pci.h [new file with mode: 0644]
drivers/staging/comedi/comedidev.h
drivers/staging/comedi/drivers.c
drivers/staging/comedi/drivers/8253.h [deleted file]
drivers/staging/comedi/drivers/8255.c
drivers/staging/comedi/drivers/8255_pci.c
drivers/staging/comedi/drivers/Makefile
drivers/staging/comedi/drivers/addi_apci_1032.c
drivers/staging/comedi/drivers/addi_apci_1500.c
drivers/staging/comedi/drivers/addi_apci_1516.c
drivers/staging/comedi/drivers/addi_apci_1564.c
drivers/staging/comedi/drivers/addi_apci_16xx.c
drivers/staging/comedi/drivers/addi_apci_2032.c
drivers/staging/comedi/drivers/addi_apci_2200.c
drivers/staging/comedi/drivers/addi_apci_3120.c
drivers/staging/comedi/drivers/addi_apci_3501.c
drivers/staging/comedi/drivers/addi_apci_3xxx.c
drivers/staging/comedi/drivers/addi_watchdog.c
drivers/staging/comedi/drivers/adl_pci6208.c
drivers/staging/comedi/drivers/adl_pci7x3x.c
drivers/staging/comedi/drivers/adl_pci8164.c
drivers/staging/comedi/drivers/adl_pci9111.c
drivers/staging/comedi/drivers/adl_pci9118.c
drivers/staging/comedi/drivers/adq12b.c
drivers/staging/comedi/drivers/adv_pci1710.c
drivers/staging/comedi/drivers/adv_pci1723.c
drivers/staging/comedi/drivers/adv_pci1724.c
drivers/staging/comedi/drivers/adv_pci_dio.c
drivers/staging/comedi/drivers/aio_iiro_16.c
drivers/staging/comedi/drivers/amplc_dio200_common.c
drivers/staging/comedi/drivers/amplc_dio200_pci.c
drivers/staging/comedi/drivers/amplc_pc236_common.c
drivers/staging/comedi/drivers/amplc_pci224.c
drivers/staging/comedi/drivers/amplc_pci230.c
drivers/staging/comedi/drivers/amplc_pci236.c
drivers/staging/comedi/drivers/amplc_pci263.c
drivers/staging/comedi/drivers/cb_das16_cs.c
drivers/staging/comedi/drivers/cb_pcidas.c
drivers/staging/comedi/drivers/cb_pcidas64.c
drivers/staging/comedi/drivers/cb_pcidda.c
drivers/staging/comedi/drivers/cb_pcimdas.c
drivers/staging/comedi/drivers/cb_pcimdda.c
drivers/staging/comedi/drivers/comedi_8254.c [new file with mode: 0644]
drivers/staging/comedi/drivers/comedi_8254.h [new file with mode: 0644]
drivers/staging/comedi/drivers/comedi_bond.c
drivers/staging/comedi/drivers/comedi_fc.h [deleted file]
drivers/staging/comedi/drivers/comedi_isadma.c
drivers/staging/comedi/drivers/comedi_parport.c
drivers/staging/comedi/drivers/comedi_test.c
drivers/staging/comedi/drivers/contec_pci_dio.c
drivers/staging/comedi/drivers/daqboard2000.c
drivers/staging/comedi/drivers/das08.c
drivers/staging/comedi/drivers/das08_pci.c
drivers/staging/comedi/drivers/das16.c
drivers/staging/comedi/drivers/das16m1.c
drivers/staging/comedi/drivers/das1800.c
drivers/staging/comedi/drivers/das6402.c
drivers/staging/comedi/drivers/das800.c
drivers/staging/comedi/drivers/dmm32at.c
drivers/staging/comedi/drivers/dt2801.c
drivers/staging/comedi/drivers/dt2811.c
drivers/staging/comedi/drivers/dt2814.c
drivers/staging/comedi/drivers/dt2815.c
drivers/staging/comedi/drivers/dt282x.c
drivers/staging/comedi/drivers/dt3000.c
drivers/staging/comedi/drivers/dyna_pci10xx.c
drivers/staging/comedi/drivers/gsc_hpdi.c
drivers/staging/comedi/drivers/icp_multi.c
drivers/staging/comedi/drivers/jr3_pci.c
drivers/staging/comedi/drivers/ke_counter.c
drivers/staging/comedi/drivers/me4000.c
drivers/staging/comedi/drivers/me_daq.c
drivers/staging/comedi/drivers/mf6x4.c
drivers/staging/comedi/drivers/mite.c
drivers/staging/comedi/drivers/mite.h
drivers/staging/comedi/drivers/mpc624.c
drivers/staging/comedi/drivers/ni_6527.c
drivers/staging/comedi/drivers/ni_65xx.c
drivers/staging/comedi/drivers/ni_660x.c
drivers/staging/comedi/drivers/ni_670x.c
drivers/staging/comedi/drivers/ni_at_a2150.c
drivers/staging/comedi/drivers/ni_at_ao.c
drivers/staging/comedi/drivers/ni_atmio.c
drivers/staging/comedi/drivers/ni_atmio16d.c
drivers/staging/comedi/drivers/ni_labpc.c
drivers/staging/comedi/drivers/ni_labpc.h
drivers/staging/comedi/drivers/ni_labpc_common.c
drivers/staging/comedi/drivers/ni_labpc_cs.c
drivers/staging/comedi/drivers/ni_labpc_isadma.c
drivers/staging/comedi/drivers/ni_labpc_pci.c
drivers/staging/comedi/drivers/ni_mio_common.c
drivers/staging/comedi/drivers/ni_pcidio.c
drivers/staging/comedi/drivers/ni_pcimio.c
drivers/staging/comedi/drivers/ni_tiocmd.c
drivers/staging/comedi/drivers/pcl711.c
drivers/staging/comedi/drivers/pcl726.c
drivers/staging/comedi/drivers/pcl812.c
drivers/staging/comedi/drivers/pcl816.c
drivers/staging/comedi/drivers/pcl818.c
drivers/staging/comedi/drivers/pcmmio.c
drivers/staging/comedi/drivers/pcmuio.c
drivers/staging/comedi/drivers/quatech_daqp_cs.c
drivers/staging/comedi/drivers/rtd520.c
drivers/staging/comedi/drivers/s626.c
drivers/staging/comedi/drivers/serial2002.c
drivers/staging/comedi/drivers/ssv_dnp.c
drivers/staging/comedi/drivers/unioxx5.c
drivers/staging/comedi/drivers/usbdux.c
drivers/staging/comedi/drivers/usbduxfast.c
drivers/staging/comedi/drivers/usbduxsigma.c
drivers/staging/comedi/kcomedilib/kcomedilib_main.c
drivers/staging/dgap/dgap.c
drivers/staging/dgap/dgap.h
drivers/staging/dgnc/Makefile
drivers/staging/dgnc/TODO
drivers/staging/dgnc/dgnc_cls.c
drivers/staging/dgnc/dgnc_cls.h
drivers/staging/dgnc/dgnc_driver.c
drivers/staging/dgnc/dgnc_driver.h
drivers/staging/dgnc/dgnc_kcompat.h [deleted file]
drivers/staging/dgnc/dgnc_mgmt.c
drivers/staging/dgnc/dgnc_mgmt.h
drivers/staging/dgnc/dgnc_neo.c
drivers/staging/dgnc/dgnc_neo.h
drivers/staging/dgnc/dgnc_pci.h
drivers/staging/dgnc/dgnc_sysfs.c
drivers/staging/dgnc/dgnc_sysfs.h
drivers/staging/dgnc/dgnc_tty.c
drivers/staging/dgnc/dgnc_tty.h
drivers/staging/dgnc/dgnc_types.h [deleted file]
drivers/staging/dgnc/dgnc_utils.c
drivers/staging/dgnc/dgnc_utils.h
drivers/staging/dgnc/digi.h
drivers/staging/dgnc/dpacompat.h [deleted file]
drivers/staging/emxx_udc/emxx_udc.c
drivers/staging/emxx_udc/emxx_udc.h
drivers/staging/fbtft/Kconfig
drivers/staging/fbtft/Makefile
drivers/staging/fbtft/README
drivers/staging/fbtft/fb_agm1264k-fl.c
drivers/staging/fbtft/fb_bd663474.c
drivers/staging/fbtft/fb_hx8340bn.c
drivers/staging/fbtft/fb_hx8347d.c
drivers/staging/fbtft/fb_hx8353d.c
drivers/staging/fbtft/fb_ili9163.c [new file with mode: 0644]
drivers/staging/fbtft/fb_ili9320.c
drivers/staging/fbtft/fb_ili9325.c
drivers/staging/fbtft/fb_ili9340.c
drivers/staging/fbtft/fb_ili9341.c
drivers/staging/fbtft/fb_ili9481.c
drivers/staging/fbtft/fb_ili9486.c
drivers/staging/fbtft/fb_pcd8544.c
drivers/staging/fbtft/fb_ra8875.c
drivers/staging/fbtft/fb_s6d02a1.c
drivers/staging/fbtft/fb_s6d1121.c
drivers/staging/fbtft/fb_ssd1289.c
drivers/staging/fbtft/fb_ssd1306.c
drivers/staging/fbtft/fb_ssd1331.c
drivers/staging/fbtft/fb_ssd1351.c
drivers/staging/fbtft/fb_st7735r.c
drivers/staging/fbtft/fb_tinylcd.c
drivers/staging/fbtft/fb_tls8204.c
drivers/staging/fbtft/fb_uc1701.c
drivers/staging/fbtft/fb_upd161704.c
drivers/staging/fbtft/fb_watterott.c
drivers/staging/fbtft/fbtft-bus.c
drivers/staging/fbtft/fbtft-core.c
drivers/staging/fbtft/fbtft-io.c
drivers/staging/fbtft/fbtft-sysfs.c
drivers/staging/fbtft/fbtft.h
drivers/staging/fbtft/fbtft_device.c
drivers/staging/fbtft/flexfb.c
drivers/staging/fbtft/internal.h [new file with mode: 0644]
drivers/staging/fsl-mc/Kconfig [new file with mode: 0644]
drivers/staging/fsl-mc/Makefile [new file with mode: 0644]
drivers/staging/fsl-mc/TODO [new file with mode: 0644]
drivers/staging/fsl-mc/bus/Kconfig [new file with mode: 0644]
drivers/staging/fsl-mc/bus/Makefile [new file with mode: 0644]
drivers/staging/fsl-mc/bus/dpbp.c [new file with mode: 0644]
drivers/staging/fsl-mc/bus/dpmcp-cmd.h [new file with mode: 0644]
drivers/staging/fsl-mc/bus/dpmcp.c [new file with mode: 0644]
drivers/staging/fsl-mc/bus/dpmcp.h [new file with mode: 0644]
drivers/staging/fsl-mc/bus/dpmng-cmd.h [new file with mode: 0644]
drivers/staging/fsl-mc/bus/dpmng.c [new file with mode: 0644]
drivers/staging/fsl-mc/bus/dprc-cmd.h [new file with mode: 0644]
drivers/staging/fsl-mc/bus/dprc-driver.c [new file with mode: 0644]
drivers/staging/fsl-mc/bus/dprc.c [new file with mode: 0644]
drivers/staging/fsl-mc/bus/mc-allocator.c [new file with mode: 0644]
drivers/staging/fsl-mc/bus/mc-bus.c [new file with mode: 0644]
drivers/staging/fsl-mc/bus/mc-sys.c [new file with mode: 0644]
drivers/staging/fsl-mc/include/dpbp-cmd.h [new file with mode: 0644]
drivers/staging/fsl-mc/include/dpbp.h [new file with mode: 0644]
drivers/staging/fsl-mc/include/dpcon-cmd.h [new file with mode: 0644]
drivers/staging/fsl-mc/include/dpmng.h [new file with mode: 0644]
drivers/staging/fsl-mc/include/dprc.h [new file with mode: 0644]
drivers/staging/fsl-mc/include/mc-cmd.h [new file with mode: 0644]
drivers/staging/fsl-mc/include/mc-private.h [new file with mode: 0644]
drivers/staging/fsl-mc/include/mc-sys.h [new file with mode: 0644]
drivers/staging/fsl-mc/include/mc.h [new file with mode: 0644]
drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
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.c
drivers/staging/fwserial/fwserial.c
drivers/staging/gdm724x/gdm_lte.c
drivers/staging/gdm724x/gdm_mux.c
drivers/staging/gdm724x/gdm_usb.c
drivers/staging/gdm72xx/gdm_qos.c
drivers/staging/gdm72xx/gdm_sdio.c
drivers/staging/gdm72xx/gdm_wimax.c
drivers/staging/goldfish/goldfish_audio.c
drivers/staging/goldfish/goldfish_nand.c
drivers/staging/gs_fpgaboot/gs_fpgaboot.c
drivers/staging/i2o/bus-osm.c
drivers/staging/i2o/config-osm.c
drivers/staging/i2o/debug.c
drivers/staging/i2o/device.c
drivers/staging/i2o/driver.c
drivers/staging/i2o/exec-osm.c
drivers/staging/i2o/i2o_block.c
drivers/staging/i2o/i2o_config.c
drivers/staging/i2o/i2o_proc.c
drivers/staging/i2o/iop.c
drivers/staging/i2o/memory.c
drivers/staging/i2o/pci.c
drivers/staging/iio/Documentation/generic_buffer.c [deleted file]
drivers/staging/iio/Documentation/iio_event_monitor.c [deleted file]
drivers/staging/iio/Documentation/iio_utils.h [deleted file]
drivers/staging/iio/Documentation/lsiio.c [deleted file]
drivers/staging/iio/accel/adis16201.h
drivers/staging/iio/accel/adis16201_core.c
drivers/staging/iio/accel/adis16203.h
drivers/staging/iio/accel/adis16203_core.c
drivers/staging/iio/accel/adis16204.h
drivers/staging/iio/accel/adis16204_core.c
drivers/staging/iio/accel/adis16209.h
drivers/staging/iio/accel/adis16209_core.c
drivers/staging/iio/accel/adis16220.h
drivers/staging/iio/accel/adis16220_core.c
drivers/staging/iio/accel/adis16240.h
drivers/staging/iio/accel/adis16240_core.c
drivers/staging/iio/accel/lis3l02dq.h
drivers/staging/iio/accel/lis3l02dq_core.c
drivers/staging/iio/accel/lis3l02dq_ring.c
drivers/staging/iio/accel/sca3000.h
drivers/staging/iio/accel/sca3000_core.c
drivers/staging/iio/accel/sca3000_ring.c
drivers/staging/iio/adc/ad7192.c
drivers/staging/iio/adc/ad7280a.c
drivers/staging/iio/adc/ad7280a.h
drivers/staging/iio/adc/ad7606_ring.c
drivers/staging/iio/adc/ad7780.c
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/iio/adc/spear_adc.c
drivers/staging/iio/frequency/ad9832.c
drivers/staging/iio/frequency/ad9832.h
drivers/staging/iio/frequency/ad9834.c
drivers/staging/iio/frequency/ad9834.h
drivers/staging/iio/frequency/dds.h
drivers/staging/iio/iio_dummy_evgen.c
drivers/staging/iio/iio_simple_dummy.c
drivers/staging/iio/iio_simple_dummy_buffer.c
drivers/staging/iio/impedance-analyzer/ad5933.c
drivers/staging/iio/light/isl29028.c
drivers/staging/iio/light/tsl2583.c
drivers/staging/iio/light/tsl2x7x_core.c
drivers/staging/iio/magnetometer/hmc5843.h
drivers/staging/iio/magnetometer/hmc5843_core.c
drivers/staging/iio/magnetometer/hmc5843_i2c.c
drivers/staging/iio/magnetometer/hmc5843_spi.c
drivers/staging/iio/meter/ade7753.c
drivers/staging/iio/meter/ade7754.c
drivers/staging/iio/meter/ade7758_core.c
drivers/staging/iio/meter/ade7758_ring.c
drivers/staging/iio/meter/ade7758_trigger.c
drivers/staging/iio/meter/ade7759.c
drivers/staging/iio/meter/ade7854-i2c.c
drivers/staging/iio/meter/ade7854-spi.c
drivers/staging/iio/meter/meter.h
drivers/staging/iio/resolver/ad2s1210.c
drivers/staging/iio/resolver/ad2s1210.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_debug.h
drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h
drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h
drivers/staging/lustre/include/linux/libcfs/libcfs_private.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/klnds/socklnd/socklnd_lib-linux.c
drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h
drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c
drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c
drivers/staging/lustre/lnet/lnet/api-ni.c
drivers/staging/lustre/lnet/lnet/config.c
drivers/staging/lustre/lnet/lnet/lib-eq.c
drivers/staging/lustre/lnet/lnet/lib-md.c
drivers/staging/lustre/lnet/lnet/lib-move.c
drivers/staging/lustre/lnet/lnet/peer.c
drivers/staging/lustre/lnet/lnet/router.c
drivers/staging/lustre/lnet/selftest/brw_test.c
drivers/staging/lustre/lnet/selftest/conctl.c
drivers/staging/lustre/lnet/selftest/console.c
drivers/staging/lustre/lnet/selftest/console.h
drivers/staging/lustre/lnet/selftest/framework.c
drivers/staging/lustre/lnet/selftest/module.c
drivers/staging/lustre/lnet/selftest/ping_test.c
drivers/staging/lustre/lnet/selftest/rpc.c
drivers/staging/lustre/lustre/fid/lproc_fid.c
drivers/staging/lustre/lustre/fld/fld_internal.h
drivers/staging/lustre/lustre/fld/fld_request.c
drivers/staging/lustre/lustre/fld/lproc_fld.c
drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h
drivers/staging/lustre/lustre/include/lprocfs_status.h
drivers/staging/lustre/lustre/include/lu_object.h
drivers/staging/lustre/lustre/include/lustre_dlm.h
drivers/staging/lustre/lustre/include/lustre_import.h
drivers/staging/lustre/lustre/include/lustre_net.h
drivers/staging/lustre/lustre/include/obd_class.h
drivers/staging/lustre/lustre/lclient/lcommon_cl.c
drivers/staging/lustre/lustre/ldlm/ldlm_extent.c
drivers/staging/lustre/lustre/ldlm/ldlm_internal.h
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_request.c
drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
drivers/staging/lustre/lustre/libcfs/Makefile
drivers/staging/lustre/lustre/libcfs/debug.c
drivers/staging/lustre/lustre/libcfs/hash.c
drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c
drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c
drivers/staging/lustre/lustre/libcfs/linux/linux-module.c
drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c
drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c [deleted file]
drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c
drivers/staging/lustre/lustre/libcfs/module.c
drivers/staging/lustre/lustre/libcfs/tracefile.c
drivers/staging/lustre/lustre/libcfs/workitem.c
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_close.c
drivers/staging/lustre/lustre/llite/llite_lib.c
drivers/staging/lustre/lustre/llite/llite_mmap.c
drivers/staging/lustre/lustre/llite/lloop.c
drivers/staging/lustre/lustre/llite/lproc_llite.c
drivers/staging/lustre/lustre/llite/namei.c
drivers/staging/lustre/lustre/llite/rw.c
drivers/staging/lustre/lustre/llite/rw26.c
drivers/staging/lustre/lustre/llite/statahead.c
drivers/staging/lustre/lustre/llite/super25.c
drivers/staging/lustre/lustre/llite/vvp_dev.c
drivers/staging/lustre/lustre/llite/xattr_cache.c
drivers/staging/lustre/lustre/lmv/lmv_obd.c
drivers/staging/lustre/lustre/lmv/lproc_lmv.c
drivers/staging/lustre/lustre/lov/lov_dev.c
drivers/staging/lustre/lustre/lov/lov_ea.c
drivers/staging/lustre/lustre/lov/lov_internal.h
drivers/staging/lustre/lustre/lov/lov_io.c
drivers/staging/lustre/lustre/lov/lov_lock.c
drivers/staging/lustre/lustre/lov/lov_obd.c
drivers/staging/lustre/lustre/lov/lov_object.c
drivers/staging/lustre/lustre/lov/lov_pool.c
drivers/staging/lustre/lustre/lov/lov_request.c
drivers/staging/lustre/lustre/lov/lproc_lov.c
drivers/staging/lustre/lustre/mdc/lproc_mdc.c
drivers/staging/lustre/lustre/mdc/mdc_request.c
drivers/staging/lustre/lustre/mgc/mgc_request.c
drivers/staging/lustre/lustre/obdclass/class_obd.c
drivers/staging/lustre/lustre/obdclass/dt_object.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_cat.c
drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
drivers/staging/lustre/lustre/obdclass/lu_object.c
drivers/staging/lustre/lustre/obdclass/obd_mount.c
drivers/staging/lustre/lustre/obdecho/echo_client.c
drivers/staging/lustre/lustre/obdecho/lproc_echo.c
drivers/staging/lustre/lustre/osc/lproc_osc.c
drivers/staging/lustre/lustre/osc/osc_cache.c
drivers/staging/lustre/lustre/osc/osc_io.c
drivers/staging/lustre/lustre/osc/osc_lock.c
drivers/staging/lustre/lustre/osc/osc_request.c
drivers/staging/lustre/lustre/ptlrpc/client.c
drivers/staging/lustre/lustre/ptlrpc/connection.c
drivers/staging/lustre/lustre/ptlrpc/import.c
drivers/staging/lustre/lustre/ptlrpc/layout.c
drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
drivers/staging/lustre/lustre/ptlrpc/niobuf.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_internal.h
drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
drivers/staging/lustre/lustre/ptlrpc/service.c
drivers/staging/media/bcm2048/radio-bcm2048.c
drivers/staging/media/cxd2099/cxd2099.c
drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
drivers/staging/media/davinci_vpfe/dm365_resizer.c
drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
drivers/staging/media/lirc/lirc_imon.c
drivers/staging/media/lirc/lirc_parallel.c
drivers/staging/media/lirc/lirc_sasem.c
drivers/staging/media/lirc/lirc_serial.c
drivers/staging/media/lirc/lirc_sir.c
drivers/staging/media/lirc/lirc_zilog.c
drivers/staging/media/mn88472/mn88472.c
drivers/staging/media/mn88473/mn88473.c
drivers/staging/media/omap4iss/iss.c
drivers/staging/media/omap4iss/iss_video.c
drivers/staging/mt29f_spinand/mt29f_spinand.c
drivers/staging/netlogic/xlr_net.c
drivers/staging/nvec/Kconfig
drivers/staging/nvec/nvec.c
drivers/staging/nvec/nvec_paz00.c
drivers/staging/nvec/nvec_power.c
drivers/staging/nvec/nvec_ps2.c
drivers/staging/octeon-usb/octeon-hcd.c
drivers/staging/octeon-usb/octeon-hcd.h
drivers/staging/octeon/ethernet-mdio.c
drivers/staging/octeon/ethernet-mdio.h
drivers/staging/octeon/ethernet.c
drivers/staging/olpc_dcon/olpc_dcon.c
drivers/staging/ozwpan/ozhcd.c
drivers/staging/ozwpan/ozmain.c
drivers/staging/ozwpan/ozpd.c
drivers/staging/ozwpan/ozproto.c
drivers/staging/panel/panel.c
drivers/staging/rtl8188eu/core/rtw_ap.c
drivers/staging/rtl8188eu/core/rtw_cmd.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_led.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_sreset.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/fw.c
drivers/staging/rtl8188eu/hal/odm.c
drivers/staging/rtl8188eu/hal/odm_HWConfig.c
drivers/staging/rtl8188eu/hal/phy.c
drivers/staging/rtl8188eu/hal/pwrseqcmd.c
drivers/staging/rtl8188eu/hal/rf.c
drivers/staging/rtl8188eu/hal/rf_cfg.c
drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c
drivers/staging/rtl8188eu/hal/usb_halinit.c
drivers/staging/rtl8188eu/include/ieee80211.h
drivers/staging/rtl8188eu/include/osdep_service.h
drivers/staging/rtl8188eu/include/rtw_led.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/rtw_recv.h
drivers/staging/rtl8188eu/include/rtw_security.h
drivers/staging/rtl8188eu/include/wifi.h
drivers/staging/rtl8188eu/include/wlan_bssdef.h
drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
drivers/staging/rtl8188eu/os_dep/mlme_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/rtl8188eu/os_dep/usb_ops_linux.c
drivers/staging/rtl8192e/dot11d.h
drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
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_firmware.c
drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.h
drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
drivers/staging/rtl8192e/rtl8192e/r819xE_phyreg.h
drivers/staging/rtl8192e/rtl8192e/rtl_cam.c
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_pci.c
drivers/staging/rtl8192e/rtl8192e/rtl_pm.c
drivers/staging/rtl8192e/rtl8192e/rtl_ps.c
drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
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_TSProc.c
drivers/staging/rtl8192e/rtllib.h
drivers/staging/rtl8192e/rtllib_crypt.c
drivers/staging/rtl8192e/rtllib_crypt.h
drivers/staging/rtl8192e/rtllib_crypt_ccmp.c
drivers/staging/rtl8192e/rtllib_crypt_tkip.c
drivers/staging/rtl8192e/rtllib_crypt_wep.c
drivers/staging/rtl8192e/rtllib_debug.h
drivers/staging/rtl8192e/rtllib_endianfree.h [deleted file]
drivers/staging/rtl8192e/rtllib_module.c
drivers/staging/rtl8192e/rtllib_rx.c
drivers/staging/rtl8192e/rtllib_softmac.c
drivers/staging/rtl8192e/rtllib_softmac_wx.c
drivers/staging/rtl8192e/rtllib_tx.c
drivers/staging/rtl8192e/rtllib_wx.c
drivers/staging/rtl8192u/ieee80211/dot11d.c
drivers/staging/rtl8192u/ieee80211/dot11d.h
drivers/staging/rtl8192u/ieee80211/ieee80211.h
drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c
drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c
drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
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_TS.h
drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
drivers/staging/rtl8192u/r8190_rtl8256.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.c
drivers/staging/rtl8192u/r8192U_wx.h
drivers/staging/rtl8192u/r819xU_firmware.c
drivers/staging/rtl8192u/r819xU_phy.c
drivers/staging/rtl8712/hal_init.c
drivers/staging/rtl8712/mlme_linux.c
drivers/staging/rtl8712/os_intfs.c
drivers/staging/rtl8712/osdep_service.h
drivers/staging/rtl8712/recv_linux.c
drivers/staging/rtl8712/rtl8712_cmd.c
drivers/staging/rtl8712/rtl8712_led.c
drivers/staging/rtl8712/rtl8712_recv.c
drivers/staging/rtl8712/rtl871x_cmd.c
drivers/staging/rtl8712/rtl871x_eeprom.c
drivers/staging/rtl8712/rtl871x_ioctl_linux.c
drivers/staging/rtl8712/rtl871x_ioctl_set.c
drivers/staging/rtl8712/rtl871x_mlme.c
drivers/staging/rtl8712/rtl871x_mp.c
drivers/staging/rtl8712/rtl871x_pwrctrl.c
drivers/staging/rtl8712/rtl871x_recv.c
drivers/staging/rtl8712/rtl871x_security.c
drivers/staging/rtl8712/rtl871x_security.h
drivers/staging/rtl8712/rtl871x_sta_mgt.c
drivers/staging/rtl8712/rtl871x_xmit.c
drivers/staging/rtl8712/wifi.h
drivers/staging/rtl8712/xmit_linux.c
drivers/staging/rtl8723au/core/rtw_ap.c
drivers/staging/rtl8723au/core/rtw_cmd.c
drivers/staging/rtl8723au/core/rtw_efuse.c
drivers/staging/rtl8723au/core/rtw_ieee80211.c
drivers/staging/rtl8723au/core/rtw_mlme.c
drivers/staging/rtl8723au/core/rtw_mlme_ext.c
drivers/staging/rtl8723au/core/rtw_pwrctrl.c
drivers/staging/rtl8723au/core/rtw_recv.c
drivers/staging/rtl8723au/core/rtw_security.c
drivers/staging/rtl8723au/core/rtw_sta_mgt.c
drivers/staging/rtl8723au/core/rtw_wlan_util.c
drivers/staging/rtl8723au/core/rtw_xmit.c
drivers/staging/rtl8723au/hal/HalDMOutSrc8723A_CE.c
drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c
drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c
drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c
drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c
drivers/staging/rtl8723au/hal/hal_com.c
drivers/staging/rtl8723au/hal/odm.c
drivers/staging/rtl8723au/hal/odm_HWConfig.c
drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c
drivers/staging/rtl8723au/hal/odm_debug.c
drivers/staging/rtl8723au/hal/odm_interface.c
drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c
drivers/staging/rtl8723au/hal/rtl8723a_cmd.c
drivers/staging/rtl8723au/hal/rtl8723a_dm.c
drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c
drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c
drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c
drivers/staging/rtl8723au/hal/rtl8723au_recv.c
drivers/staging/rtl8723au/hal/rtl8723au_xmit.c
drivers/staging/rtl8723au/hal/usb_halinit.c
drivers/staging/rtl8723au/hal/usb_ops_linux.c
drivers/staging/rtl8723au/include/Hal8723APhyCfg.h
drivers/staging/rtl8723au/include/HalVerDef.h
drivers/staging/rtl8723au/include/hal_com.h
drivers/staging/rtl8723au/include/hal_intf.h
drivers/staging/rtl8723au/include/ieee80211.h
drivers/staging/rtl8723au/include/odm.h
drivers/staging/rtl8723au/include/odm_RegConfig8723A.h
drivers/staging/rtl8723au/include/odm_interface.h
drivers/staging/rtl8723au/include/rtl8723a_hal.h
drivers/staging/rtl8723au/include/rtw_debug.h
drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
drivers/staging/rtl8723au/os_dep/os_intfs.c
drivers/staging/rtl8723au/os_dep/recv_linux.c
drivers/staging/rtl8723au/os_dep/usb_intf.c
drivers/staging/rtl8723au/os_dep/usb_ops_linux.c
drivers/staging/rtl8723au/os_dep/xmit_linux.c
drivers/staging/rts5208/Makefile
drivers/staging/rts5208/ms.c
drivers/staging/rts5208/ms.h
drivers/staging/rts5208/rtsx.c
drivers/staging/rts5208/rtsx.h
drivers/staging/rts5208/rtsx_card.c
drivers/staging/rts5208/rtsx_card.h
drivers/staging/rts5208/rtsx_chip.c
drivers/staging/rts5208/rtsx_chip.h
drivers/staging/rts5208/rtsx_scsi.c
drivers/staging/rts5208/rtsx_transport.c
drivers/staging/rts5208/sd.c
drivers/staging/rts5208/sd.h
drivers/staging/rts5208/spi.c
drivers/staging/rts5208/trace.c [new file with mode: 0644]
drivers/staging/rts5208/trace.h
drivers/staging/rts5208/xd.c
drivers/staging/skein/skein_block.c
drivers/staging/slicoss/slicoss.c
drivers/staging/sm750fb/Kconfig [new file with mode: 0644]
drivers/staging/sm750fb/Makefile [new file with mode: 0644]
drivers/staging/sm750fb/TODO [new file with mode: 0644]
drivers/staging/sm750fb/ddk750.h [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_chip.c [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_chip.h [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_display.c [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_display.h [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_dvi.c [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_dvi.h [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_help.c [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_help.h [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_hwi2c.c [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_hwi2c.h [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_mode.c [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_mode.h [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_power.c [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_power.h [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_reg.h [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_sii164.c [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_sii164.h [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_swi2c.c [new file with mode: 0644]
drivers/staging/sm750fb/ddk750_swi2c.h [new file with mode: 0644]
drivers/staging/sm750fb/modedb.h [new file with mode: 0644]
drivers/staging/sm750fb/readme [new file with mode: 0644]
drivers/staging/sm750fb/sm750.c [new file with mode: 0644]
drivers/staging/sm750fb/sm750.h [new file with mode: 0644]
drivers/staging/sm750fb/sm750_accel.c [new file with mode: 0644]
drivers/staging/sm750fb/sm750_accel.h [new file with mode: 0644]
drivers/staging/sm750fb/sm750_cursor.c [new file with mode: 0644]
drivers/staging/sm750fb/sm750_cursor.h [new file with mode: 0644]
drivers/staging/sm750fb/sm750_help.h [new file with mode: 0644]
drivers/staging/sm750fb/sm750_hw.c [new file with mode: 0644]
drivers/staging/sm750fb/sm750_hw.h [new file with mode: 0644]
drivers/staging/sm7xxfb/sm7xx.h
drivers/staging/sm7xxfb/sm7xxfb.c
drivers/staging/speakup/kobjects.c
drivers/staging/speakup/main.c
drivers/staging/speakup/serialio.h
drivers/staging/speakup/speakup.h
drivers/staging/speakup/speakup_acntpc.c
drivers/staging/speakup/speakup_acntsa.c
drivers/staging/speakup/speakup_apollo.c
drivers/staging/speakup/speakup_audptr.c
drivers/staging/speakup/speakup_bns.c
drivers/staging/speakup/speakup_decext.c
drivers/staging/speakup/speakup_decpc.c
drivers/staging/speakup/speakup_dectlk.c
drivers/staging/speakup/speakup_dtlk.c
drivers/staging/speakup/speakup_dummy.c
drivers/staging/speakup/speakup_keypc.c
drivers/staging/speakup/speakup_ltlk.c
drivers/staging/speakup/speakup_soft.c
drivers/staging/speakup/speakup_spkout.c
drivers/staging/speakup/speakup_txprt.c
drivers/staging/speakup/spk_priv.h
drivers/staging/speakup/spk_types.h
drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
drivers/staging/unisys/common-spar/include/channels/iochannel.h
drivers/staging/unisys/common-spar/include/vmcallinterface.h
drivers/staging/unisys/include/procobjecttree.h
drivers/staging/unisys/include/timskmod.h
drivers/staging/unisys/include/uisqueue.h
drivers/staging/unisys/include/uisthread.h
drivers/staging/unisys/include/uisutils.h
drivers/staging/unisys/include/uniklog.h [deleted file]
drivers/staging/unisys/uislib/Kconfig
drivers/staging/unisys/uislib/Makefile
drivers/staging/unisys/uislib/uislib.c
drivers/staging/unisys/uislib/uisqueue.c
drivers/staging/unisys/uislib/uisthread.c
drivers/staging/unisys/uislib/uisutils.c
drivers/staging/unisys/virthba/Kconfig
drivers/staging/unisys/virthba/Makefile
drivers/staging/unisys/virthba/virthba.c
drivers/staging/unisys/virtpci/Kconfig
drivers/staging/unisys/virtpci/virtpci.c
drivers/staging/unisys/visorchannel/Kconfig
drivers/staging/unisys/visorchannel/globals.h
drivers/staging/unisys/visorchannel/visorchannel_funcs.c
drivers/staging/unisys/visorchannel/visorchannel_main.c
drivers/staging/unisys/visorchipset/Kconfig
drivers/staging/unisys/visorchipset/file.c
drivers/staging/unisys/visorchipset/file.h
drivers/staging/unisys/visorchipset/globals.h
drivers/staging/unisys/visorchipset/parser.c
drivers/staging/unisys/visorchipset/parser.h
drivers/staging/unisys/visorchipset/visorchipset.h
drivers/staging/unisys/visorchipset/visorchipset_main.c
drivers/staging/unisys/visorutil/Kconfig
drivers/staging/unisys/visorutil/Makefile
drivers/staging/unisys/visorutil/charqueue.c
drivers/staging/unisys/visorutil/charqueue.h
drivers/staging/unisys/visorutil/easyproc.c [deleted file]
drivers/staging/unisys/visorutil/easyproc.h [deleted file]
drivers/staging/unisys/visorutil/memregion_direct.c
drivers/staging/unisys/visorutil/periodic_work.c
drivers/staging/unisys/visorutil/procobjecttree.c [deleted file]
drivers/staging/unisys/visorutil/visorkmodutils.c
drivers/staging/vme/devices/vme_pio2_core.c
drivers/staging/vme/devices/vme_pio2_gpio.c
drivers/staging/vme/devices/vme_user.c
drivers/staging/vt6655/baseband.c
drivers/staging/vt6655/channel.c
drivers/staging/vt6655/device_main.c
drivers/staging/vt6655/dpc.c
drivers/staging/vt6655/key.h
drivers/staging/vt6655/mac.c
drivers/staging/vt6655/mib.c
drivers/staging/vt6655/rxtx.c
drivers/staging/vt6655/srom.h
drivers/staging/vt6655/tmacro.h
drivers/staging/vt6656/firmware.c
drivers/staging/vt6656/mac.c
drivers/staging/vt6656/main_usb.c
drivers/staging/vt6656/rxtx.c
drivers/staging/wlan-ng/hfa384x.h
drivers/staging/wlan-ng/hfa384x_usb.c
drivers/staging/wlan-ng/prism2mib.c
drivers/staging/wlan-ng/prism2sta.c
drivers/staging/xgifb/XGI_main_26.c
drivers/staging/xgifb/vb_setmode.c
drivers/target/iscsi/iscsi_target.c
drivers/target/target_core_device.c
drivers/thermal/st/st_thermal.c
drivers/thermal/st/st_thermal_memmap.c
drivers/thermal/st/st_thermal_syscfg.c
drivers/thermal/thermal_core.c
drivers/tty/goldfish.c
drivers/tty/ipwireless/hardware.c
drivers/tty/sysrq.c
drivers/usb/Makefile
drivers/usb/atm/ueagle-atm.c
drivers/usb/c67x00/c67x00-hcd.c
drivers/usb/chipidea/Kconfig
drivers/usb/chipidea/Makefile
drivers/usb/chipidea/bits.h
drivers/usb/chipidea/ci.h
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/chipidea/ci_hdrc_imx.h
drivers/usb/chipidea/ci_hdrc_pci.c
drivers/usb/chipidea/ci_hdrc_zevio.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/debug.c
drivers/usb/chipidea/host.c
drivers/usb/chipidea/otg.c
drivers/usb/chipidea/otg_fsm.c
drivers/usb/chipidea/otg_fsm.h
drivers/usb/chipidea/udc.c
drivers/usb/chipidea/usbmisc_imx.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/devio.c
drivers/usb/core/hub.c
drivers/usb/core/usb.c
drivers/usb/dwc2/Kconfig
drivers/usb/dwc2/Makefile
drivers/usb/dwc2/core.h
drivers/usb/dwc2/hcd.c
drivers/usb/dwc2/pci.c
drivers/usb/dwc2/platform.c
drivers/usb/dwc3/Kconfig
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/dwc3-omap.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/gadget.c
drivers/usb/dwc3/host.c
drivers/usb/dwc3/platform_data.h
drivers/usb/gadget/Kconfig
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/Makefile
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_hid.c
drivers/usb/gadget/function/f_mass_storage.c
drivers/usb/gadget/function/f_printer.c [new file with mode: 0644]
drivers/usb/gadget/function/u_printer.h [new file with mode: 0644]
drivers/usb/gadget/function/u_serial.c
drivers/usb/gadget/legacy/Kconfig
drivers/usb/gadget/legacy/inode.c
drivers/usb/gadget/legacy/printer.c
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/gadget/udc/atmel_usba_udc.h
drivers/usb/gadget/udc/dummy_hcd.c
drivers/usb/gadget/udc/goku_udc.c
drivers/usb/gadget/udc/lpc32xx_udc.c
drivers/usb/gadget/udc/net2280.c
drivers/usb/gadget/udc/net2280.h
drivers/usb/gadget/udc/pxa27x_udc.c
drivers/usb/gadget/udc/udc-core.c
drivers/usb/host/Kconfig
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-orion.c
drivers/usb/host/fhci-hub.c
drivers/usb/host/fotg210-hcd.c
drivers/usb/host/fusbh200-hcd.c
drivers/usb/host/imx21-hcd.c
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/isp1362-hcd.c
drivers/usb/host/max3421-hcd.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/oxu210hp-hcd.c
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/sl811-hcd.c
drivers/usb/host/u132-hcd.c
drivers/usb/host/uhci-hub.c
drivers/usb/host/whci/hcd.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci-trace.h
drivers/usb/image/mdc800.c
drivers/usb/isp1760/isp1760-hcd.c
drivers/usb/misc/Kconfig
drivers/usb/misc/Makefile
drivers/usb/misc/appledisplay.c
drivers/usb/misc/chaoskey.c [new file with mode: 0644]
drivers/usb/misc/legousbtower.c
drivers/usb/misc/usb3503.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_cppi41.c
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_virthub.c
drivers/usb/phy/Kconfig
drivers/usb/phy/of.c
drivers/usb/phy/phy-ab8500-usb.c
drivers/usb/phy/phy-generic.c
drivers/usb/phy/phy-msm-usb.c
drivers/usb/phy/phy-rcar-gen2-usb.c
drivers/usb/phy/phy.c
drivers/usb/renesas_usbhs/common.c
drivers/usb/renesas_usbhs/common.h
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/fifo.h
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/renesas_usbhs/mod_host.c
drivers/usb/renesas_usbhs/pipe.c
drivers/usb/renesas_usbhs/pipe.h
drivers/usb/serial/ch341.c
drivers/usb/serial/f81232.c
drivers/usb/storage/alauda.c
drivers/usb/storage/cypress_atacb.c
drivers/usb/storage/isd200.c
drivers/usb/usbip/vhci_hcd.c
drivers/usb/wusbcore/rh.c
drivers/uwb/umc-bus.c
drivers/uwb/whci.c
drivers/vfio/Kconfig
drivers/vfio/Makefile
drivers/vfio/pci/Kconfig
drivers/vfio/pci/vfio_pci.c
drivers/vfio/pci/vfio_pci_intrs.c
drivers/vfio/pci/vfio_pci_private.h
drivers/vfio/platform/Kconfig [new file with mode: 0644]
drivers/vfio/platform/Makefile [new file with mode: 0644]
drivers/vfio/platform/vfio_amba.c [new file with mode: 0644]
drivers/vfio/platform/vfio_platform.c [new file with mode: 0644]
drivers/vfio/platform/vfio_platform_common.c [new file with mode: 0644]
drivers/vfio/platform/vfio_platform_irq.c [new file with mode: 0644]
drivers/vfio/platform/vfio_platform_private.h [new file with mode: 0644]
drivers/vfio/vfio.c
drivers/vfio/virqfd.c [new file with mode: 0644]
drivers/video/backlight/88pm860x_bl.c
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/da9052_bl.c
drivers/video/backlight/sky81452-backlight.c [new file with mode: 0644]
drivers/vme/bridges/vme_tsi148.c
drivers/vme/vme.c
drivers/xen/tmem.c
fs/9p/vfs_addr.c
fs/Kconfig.binfmt
fs/Makefile
fs/affs/file.c
fs/afs/write.c
fs/aio.c
fs/bfs/inode.c
fs/binfmt_elf.c
fs/block_dev.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/buffer.c
fs/ceph/file.c
fs/cifs/connect.c
fs/dcache.c
fs/debugfs/inode.c
fs/direct-io.c
fs/ecryptfs/file.c
fs/ext2/inode.c
fs/ext3/inode.c
fs/ext4/file.c
fs/ext4/indirect.c
fs/ext4/inode.c
fs/ext4/page-io.c
fs/f2fs/data.c
fs/fat/inode.c
fs/fuse/cuse.c
fs/fuse/dev.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/gfs2/acl.c
fs/gfs2/aops.c
fs/gfs2/bmap.c
fs/gfs2/file.c
fs/gfs2/glock.c
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/quota.c
fs/gfs2/quota.h
fs/gfs2/rgrp.c
fs/gfs2/rgrp.h
fs/gfs2/xattr.c
fs/hfs/inode.c
fs/hfsplus/inode.c
fs/hugetlbfs/inode.c
fs/jffs2/xattr.c
fs/jfs/inode.c
fs/jfs/super.c
fs/namei.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/write.c
fs/nilfs2/inode.c
fs/ntfs/Makefile
fs/ntfs/file.c
fs/ntfs/inode.c
fs/ocfs2/alloc.c
fs/ocfs2/aops.c
fs/ocfs2/aops.h
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/masklog.h
fs/ocfs2/dir.c
fs/ocfs2/dlmglue.c
fs/ocfs2/export.c
fs/ocfs2/file.c
fs/ocfs2/inode.c
fs/ocfs2/localalloc.c
fs/ocfs2/namei.c
fs/ocfs2/refcounttree.c
fs/ocfs2/slot_map.c
fs/ocfs2/stack_o2cb.c
fs/ocfs2/stack_user.c
fs/ocfs2/suballoc.c
fs/ocfs2/super.c
fs/ocfs2/xattr.c
fs/open.c
fs/pipe.c
fs/pstore/ram.c
fs/read_write.c
fs/reiserfs/inode.c
fs/splice.c
fs/stat.c
fs/super.c
fs/sysfs/group.c
fs/tracefs/Makefile [new file with mode: 0644]
fs/tracefs/inode.c [new file with mode: 0644]
fs/ubifs/file.c
fs/udf/file.c
fs/udf/inode.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_file.c
include/asm-generic/pgtable.h
include/asm-generic/vmlinux.lds.h
include/dt-bindings/gpio/meson8b-gpio.h [new file with mode: 0644]
include/dt-bindings/interrupt-controller/irq-st.h [new file with mode: 0644]
include/dt-bindings/mfd/arizona.h [new file with mode: 0644]
include/dt-bindings/mfd/qcom-rpm.h
include/dt-bindings/phy/phy-miphy365x.h [deleted file]
include/dt-bindings/pinctrl/mt65xx.h [new file with mode: 0644]
include/dt-bindings/pinctrl/qcom,pmic-gpio.h
include/dt-bindings/pinctrl/qcom,pmic-mpp.h
include/kvm/arm_arch_timer.h
include/kvm/arm_vgic.h
include/kvm/iodev.h [new file with mode: 0644]
include/linux/aio.h
include/linux/ata.h
include/linux/blk_types.h
include/linux/bpf.h
include/linux/cleancache.h
include/linux/clockchips.h
include/linux/clocksource.h
include/linux/cma.h
include/linux/compiler.h
include/linux/context_tracking.h
include/linux/context_tracking_state.h
include/linux/cpu.h
include/linux/cpuidle.h
include/linux/device.h
include/linux/dmapool.h
include/linux/efi.h
include/linux/elf-randomize.h [new file with mode: 0644]
include/linux/fs.h
include/linux/ftrace_event.h
include/linux/gfp.h
include/linux/hardirq.h
include/linux/hid-sensor-hub.h
include/linux/hid-sensor-ids.h
include/linux/hid.h
include/linux/i2c.h
include/linux/iio/buffer.h
include/linux/iio/dac/max517.h
include/linux/iio/events.h
include/linux/iio/iio.h
include/linux/iio/types.h
include/linux/init.h
include/linux/intel_mid_dma.h [deleted file]
include/linux/interrupt.h
include/linux/io.h
include/linux/irq.h
include/linux/irq_work.h
include/linux/irqchip/arm-gic.h
include/linux/irqchip/irq-crossbar.h [deleted file]
include/linux/irqchip/mips-gic.h
include/linux/irqflags.h
include/linux/jump_label.h
include/linux/kvm_host.h
include/linux/libata.h
include/linux/livepatch.h
include/linux/lockdep.h
include/linux/memblock.h
include/linux/memory_hotplug.h
include/linux/mempool.h
include/linux/mfd/abx500/ux500_chargalg.h
include/linux/mfd/arizona/core.h
include/linux/mfd/arizona/gpio.h [deleted file]
include/linux/mfd/arizona/pdata.h
include/linux/mfd/max77693-private.h
include/linux/mfd/max77693.h
include/linux/mfd/max77843-private.h [new file with mode: 0644]
include/linux/mfd/menelaus.h
include/linux/mfd/mt6397/core.h [new file with mode: 0644]
include/linux/mfd/mt6397/registers.h [new file with mode: 0644]
include/linux/mfd/palmas.h
include/linux/mfd/rk808.h
include/linux/mfd/rt5033.h
include/linux/mfd/rtsx_pci.h
include/linux/mfd/samsung/core.h
include/linux/mfd/samsung/irq.h
include/linux/mfd/sky81452.h [new file with mode: 0644]
include/linux/mfd/stw481x.h
include/linux/mfd/syscon/exynos5-pmu.h
include/linux/mfd/ti_am335x_tscadc.h
include/linux/mfd/wm8350/supply.h
include/linux/migrate.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/mmc/core.h
include/linux/mmc/dw_mmc.h
include/linux/mmc/host.h
include/linux/mmc/sdhci-spear.h [deleted file]
include/linux/mmc/sdhci.h [deleted file]
include/linux/mmzone.h
include/linux/module.h
include/linux/nmi.h
include/linux/of.h
include/linux/of_device.h
include/linux/of_iommu.h
include/linux/of_pci.h
include/linux/oom.h
include/linux/page-flags.h
include/linux/pci-acpi.h
include/linux/pci-aspm.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/perf_event.h
include/linux/platform_data/hsmmc-omap.h
include/linux/platform_data/i2c-davinci.h
include/linux/platform_data/sky81452-backlight.h [new file with mode: 0644]
include/linux/power/charger-manager.h
include/linux/power/max17042_battery.h
include/linux/power_supply.h
include/linux/rcupdate.h
include/linux/regulator/act8865.h
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/rtc.h
include/linux/sched.h
include/linux/security.h
include/linux/seqlock.h
include/linux/slab.h
include/linux/smpboot.h
include/linux/spi/spi.h
include/linux/srcu.h
include/linux/stacktrace.h
include/linux/stddef.h
include/linux/sysfs.h
include/linux/tick.h
include/linux/timekeeper_internal.h
include/linux/timekeeping.h
include/linux/tracefs.h [new file with mode: 0644]
include/linux/tracepoint.h
include/linux/uio.h
include/linux/usb.h
include/linux/usb/chipidea.h
include/linux/usb/composite.h
include/linux/usb/gadget.h
include/linux/usb/msm_hsusb.h
include/linux/usb/otg-fsm.h
include/linux/usb/renesas_usbhs.h
include/linux/uwb/umc.h
include/linux/vfio.h
include/linux/vgaarb.h
include/linux/vme.h
include/linux/watchdog.h
include/linux/workqueue.h
include/media/atmel-isi.h
include/net/sock.h
include/scsi/scsi_eh.h
include/trace/events/9p.h
include/trace/events/btrfs.h
include/trace/events/ext3.h
include/trace/events/ext4.h
include/trace/events/f2fs.h
include/trace/events/intel-sst.h
include/trace/events/irq.h
include/trace/events/libata.h [new file with mode: 0644]
include/trace/events/migrate.h
include/trace/events/module.h
include/trace/events/random.h
include/trace/events/regmap.h [deleted file]
include/trace/events/sunrpc.h
include/trace/events/tlb.h
include/trace/events/v4l2.h
include/trace/events/writeback.h
include/trace/events/xen.h
include/trace/ftrace.h
include/uapi/linux/Kbuild
include/uapi/linux/bpf.h
include/uapi/linux/hsi/Kbuild
include/uapi/linux/hsi/cs-protocol.h [new file with mode: 0644]
include/uapi/linux/iio/Kbuild [new file with mode: 0644]
include/uapi/linux/iio/events.h [new file with mode: 0644]
include/uapi/linux/iio/types.h [new file with mode: 0644]
include/uapi/linux/input.h
include/uapi/linux/kvm.h
include/uapi/linux/magic.h
include/uapi/linux/perf_event.h
include/uapi/linux/vfio.h
init/Kconfig
init/main.c
kernel/bpf/syscall.c
kernel/cgroup.c
kernel/context_tracking.c
kernel/cpu.c
kernel/cpuset.c
kernel/events/core.c
kernel/events/hw_breakpoint.c
kernel/events/internal.h
kernel/events/ring_buffer.c
kernel/futex.c
kernel/irq/chip.c
kernel/irq/manage.c
kernel/irq/msi.c
kernel/livepatch/core.c
kernel/locking/mcs_spinlock.h
kernel/locking/mutex.c
kernel/locking/osq_lock.c
kernel/locking/rtmutex.c
kernel/locking/rwsem-spinlock.c
kernel/locking/rwsem-xadd.c
kernel/locking/rwsem.c
kernel/locking/rwsem.h [new file with mode: 0644]
kernel/module.c
kernel/power/snapshot.c
kernel/printk/printk.c
kernel/rcu/rcutorture.c
kernel/rcu/srcu.c
kernel/rcu/tiny.c
kernel/rcu/tree.c
kernel/rcu/tree.h
kernel/rcu/tree_plugin.h
kernel/rcu/tree_trace.c
kernel/rcu/update.c
kernel/sched/core.c
kernel/sched/deadline.c
kernel/sched/debug.c
kernel/sched/fair.c
kernel/sched/features.h
kernel/sched/idle.c
kernel/sched/rt.c
kernel/sched/sched.h
kernel/smpboot.c
kernel/sysctl.c
kernel/time/Kconfig
kernel/time/Makefile
kernel/time/clockevents.c
kernel/time/clocksource.c
kernel/time/hrtimer.c
kernel/time/jiffies.c
kernel/time/ntp.c
kernel/time/sched_clock.c
kernel/time/tick-broadcast.c
kernel/time/tick-common.c
kernel/time/tick-internal.h
kernel/time/tick-oneshot.c
kernel/time/tick-sched.c
kernel/time/tick-sched.h [new file with mode: 0644]
kernel/time/timekeeping.c
kernel/time/timekeeping.h
kernel/time/timer.c
kernel/time/timer_list.c
kernel/trace/Kconfig
kernel/trace/Makefile
kernel/trace/bpf_trace.c [new file with mode: 0644]
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_entries.h
kernel/trace/trace_events.c
kernel/trace/trace_export.c
kernel/trace/trace_functions_graph.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_probe.c
kernel/trace/trace_probe.h
kernel/trace/trace_stat.c
kernel/trace/trace_uprobe.c
kernel/watchdog.c
kernel/workqueue.c
lib/Kconfig.debug
lib/div64.c
lib/ioremap.c
lib/iov_iter.c
lib/kobject.c
lib/lockref.c
lib/lz4/lz4_decompress.c
mm/Kconfig
mm/Makefile
mm/cleancache.c
mm/cma.c
mm/cma.h [new file with mode: 0644]
mm/cma_debug.c [new file with mode: 0644]
mm/compaction.c
mm/filemap.c
mm/gup.c
mm/huge_memory.c
mm/hugetlb.c
mm/internal.h
mm/memblock.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/mempool.c
mm/memtest.c [new file with mode: 0644]
mm/migrate.c
mm/mlock.c
mm/mmap.c
mm/mremap.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/page_io.c
mm/percpu.c
mm/process_vm_access.c
mm/shmem.c
mm/slab.c
mm/slob.c
mm/slub.c
mm/truncate.c
mm/vmalloc.c
net/atm/mpoa_proc.c
net/ceph/messenger.c
net/ipv4/raw.c
net/mac80211/trace.c
net/mac80211/trace.h
net/mac80211/trace_msg.h [new file with mode: 0644]
net/openvswitch/flow.c
net/socket.c
net/sunrpc/xprtrdma/verbs.c
samples/bpf/Makefile
samples/bpf/bpf_helpers.h
samples/bpf/bpf_load.c
samples/bpf/bpf_load.h
samples/bpf/libbpf.c
samples/bpf/libbpf.h
samples/bpf/sock_example.c
samples/bpf/test_verifier.c
samples/bpf/tracex1_kern.c [new file with mode: 0644]
samples/bpf/tracex1_user.c [new file with mode: 0644]
samples/bpf/tracex2_kern.c [new file with mode: 0644]
samples/bpf/tracex2_user.c [new file with mode: 0644]
samples/bpf/tracex3_kern.c [new file with mode: 0644]
samples/bpf/tracex3_user.c [new file with mode: 0644]
samples/bpf/tracex4_kern.c [new file with mode: 0644]
samples/bpf/tracex4_user.c [new file with mode: 0644]
samples/hidraw/Makefile
samples/hidraw/hid-example.c
samples/kobject/kobject-example.c
samples/kobject/kset-example.c
samples/trace_events/trace-events-sample.h
scripts/coccinelle/misc/bugon.cocci
security/apparmor/lsm.c
security/capability.c
security/keys/compat.c
security/keys/internal.h
security/keys/keyctl.c
security/security.c
security/selinux/hooks.c
security/smack/smack_lsm.c
security/tomoyo/common.h
security/tomoyo/file.c
security/tomoyo/realpath.c
security/tomoyo/tomoyo.c
sound/core/pcm_native.c
sound/firewire/bebob/bebob_maudio.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/arizona.c
sound/soc/codecs/pcm512x.c
sound/soc/soc-core.c
sound/usb/mixer_quirks.c
sound/usb/quirks.c
tools/build/Build.include [new file with mode: 0644]
tools/build/Documentation/Build.txt [new file with mode: 0644]
tools/build/Makefile.build [new file with mode: 0644]
tools/build/Makefile.feature [new file with mode: 0644]
tools/build/feature/.gitignore [new file with mode: 0644]
tools/build/feature/Makefile [new file with mode: 0644]
tools/build/feature/test-all.c [new file with mode: 0644]
tools/build/feature/test-backtrace.c [new file with mode: 0644]
tools/build/feature/test-bionic.c [new file with mode: 0644]
tools/build/feature/test-compile.c [new file with mode: 0644]
tools/build/feature/test-cplus-demangle.c [new file with mode: 0644]
tools/build/feature/test-dwarf.c [new file with mode: 0644]
tools/build/feature/test-fortify-source.c [new file with mode: 0644]
tools/build/feature/test-glibc.c [new file with mode: 0644]
tools/build/feature/test-gtk2-infobar.c [new file with mode: 0644]
tools/build/feature/test-gtk2.c [new file with mode: 0644]
tools/build/feature/test-hello.c [new file with mode: 0644]
tools/build/feature/test-libaudit.c [new file with mode: 0644]
tools/build/feature/test-libbabeltrace.c [new file with mode: 0644]
tools/build/feature/test-libbfd.c [new file with mode: 0644]
tools/build/feature/test-libdw-dwarf-unwind.c [new file with mode: 0644]
tools/build/feature/test-libelf-getphdrnum.c [new file with mode: 0644]
tools/build/feature/test-libelf-mmap.c [new file with mode: 0644]
tools/build/feature/test-libelf.c [new file with mode: 0644]
tools/build/feature/test-libnuma.c [new file with mode: 0644]
tools/build/feature/test-libperl.c [new file with mode: 0644]
tools/build/feature/test-libpython-version.c [new file with mode: 0644]
tools/build/feature/test-libpython.c [new file with mode: 0644]
tools/build/feature/test-libslang.c [new file with mode: 0644]
tools/build/feature/test-libunwind-debug-frame.c [new file with mode: 0644]
tools/build/feature/test-libunwind.c [new file with mode: 0644]
tools/build/feature/test-lzma.c [new file with mode: 0644]
tools/build/feature/test-pthread-attr-setaffinity-np.c [new file with mode: 0644]
tools/build/feature/test-stackprotector-all.c [new file with mode: 0644]
tools/build/feature/test-sync-compare-and-swap.c [new file with mode: 0644]
tools/build/feature/test-timerfd.c [new file with mode: 0644]
tools/build/feature/test-zlib.c [new file with mode: 0644]
tools/build/tests/ex/Build [new file with mode: 0644]
tools/build/tests/ex/Makefile [new file with mode: 0644]
tools/build/tests/ex/a.c [new file with mode: 0644]
tools/build/tests/ex/arch/Build [new file with mode: 0644]
tools/build/tests/ex/arch/e.c [new file with mode: 0644]
tools/build/tests/ex/arch/f.c [new file with mode: 0644]
tools/build/tests/ex/b.c [new file with mode: 0644]
tools/build/tests/ex/c.c [new file with mode: 0644]
tools/build/tests/ex/d.c [new file with mode: 0644]
tools/build/tests/ex/empty/Build [new file with mode: 0644]
tools/build/tests/ex/ex.c [new file with mode: 0644]
tools/build/tests/run.sh [new file with mode: 0755]
tools/iio/Makefile [new file with mode: 0644]
tools/iio/generic_buffer.c [new file with mode: 0644]
tools/iio/iio_event_monitor.c [new file with mode: 0644]
tools/iio/iio_utils.c [new file with mode: 0644]
tools/iio/iio_utils.h [new file with mode: 0644]
tools/iio/lsiio.c [new file with mode: 0644]
tools/lib/api/Build [new file with mode: 0644]
tools/lib/api/Makefile
tools/lib/api/fd/Build [new file with mode: 0644]
tools/lib/api/fs/Build [new file with mode: 0644]
tools/lib/api/fs/debugfs.c
tools/lib/api/fs/debugfs.h
tools/lib/api/fs/findfs.c [new file with mode: 0644]
tools/lib/api/fs/findfs.h [new file with mode: 0644]
tools/lib/api/fs/tracefs.c [new file with mode: 0644]
tools/lib/api/fs/tracefs.h [new file with mode: 0644]
tools/lib/lockdep/Build [new file with mode: 0644]
tools/lib/lockdep/Makefile
tools/lib/traceevent/Build [new file with mode: 0644]
tools/lib/traceevent/Makefile
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/event-parse.h
tools/lib/traceevent/event-plugin.c
tools/lib/traceevent/kbuffer-parse.c
tools/lib/traceevent/kbuffer.h
tools/lib/traceevent/parse-filter.c
tools/lib/traceevent/trace-seq.c
tools/perf/.gitignore
tools/perf/Build [new file with mode: 0644]
tools/perf/Documentation/Build.txt [new file with mode: 0644]
tools/perf/Documentation/perf-buildid-cache.txt
tools/perf/Documentation/perf-data.txt [new file with mode: 0644]
tools/perf/Documentation/perf-diff.txt
tools/perf/Documentation/perf-kmem.txt
tools/perf/Documentation/perf-list.txt
tools/perf/Documentation/perf-probe.txt
tools/perf/Documentation/perf-record.txt
tools/perf/Documentation/perf-report.txt
tools/perf/Documentation/perf-script.txt
tools/perf/Documentation/perf-trace.txt
tools/perf/Documentation/perf.txt
tools/perf/MANIFEST
tools/perf/Makefile
tools/perf/Makefile.perf
tools/perf/arch/Build [new file with mode: 0644]
tools/perf/arch/arm/Build [new file with mode: 0644]
tools/perf/arch/arm/Makefile
tools/perf/arch/arm/tests/Build [new file with mode: 0644]
tools/perf/arch/arm/util/Build [new file with mode: 0644]
tools/perf/arch/arm64/Build [new file with mode: 0644]
tools/perf/arch/arm64/Makefile
tools/perf/arch/arm64/util/Build [new file with mode: 0644]
tools/perf/arch/powerpc/Build [new file with mode: 0644]
tools/perf/arch/powerpc/Makefile
tools/perf/arch/powerpc/util/Build [new file with mode: 0644]
tools/perf/arch/s390/Build [new file with mode: 0644]
tools/perf/arch/s390/Makefile
tools/perf/arch/s390/util/Build [new file with mode: 0644]
tools/perf/arch/sh/Build [new file with mode: 0644]
tools/perf/arch/sh/Makefile
tools/perf/arch/sh/util/Build [new file with mode: 0644]
tools/perf/arch/sparc/Build [new file with mode: 0644]
tools/perf/arch/sparc/Makefile
tools/perf/arch/sparc/util/Build [new file with mode: 0644]
tools/perf/arch/x86/Build [new file with mode: 0644]
tools/perf/arch/x86/Makefile
tools/perf/arch/x86/tests/Build [new file with mode: 0644]
tools/perf/arch/x86/util/Build [new file with mode: 0644]
tools/perf/bench/Build [new file with mode: 0644]
tools/perf/bench/mem-memcpy-x86-64-asm-def.h
tools/perf/bench/mem-memcpy-x86-64-asm.S
tools/perf/bench/mem-memcpy.c
tools/perf/bench/mem-memset-x86-64-asm-def.h
tools/perf/bench/mem-memset-x86-64-asm.S
tools/perf/builtin-annotate.c
tools/perf/builtin-buildid-cache.c
tools/perf/builtin-buildid-list.c
tools/perf/builtin-data.c [new file with mode: 0644]
tools/perf/builtin-diff.c
tools/perf/builtin-evlist.c
tools/perf/builtin-help.c
tools/perf/builtin-inject.c
tools/perf/builtin-kmem.c
tools/perf/builtin-kvm.c
tools/perf/builtin-list.c
tools/perf/builtin-lock.c
tools/perf/builtin-mem.c
tools/perf/builtin-probe.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-timechart.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/builtin.h
tools/perf/command-list.txt
tools/perf/config/Makefile
tools/perf/config/Makefile.arch
tools/perf/config/feature-checks/.gitignore [deleted file]
tools/perf/config/feature-checks/Makefile [deleted file]
tools/perf/config/feature-checks/test-all.c [deleted file]
tools/perf/config/feature-checks/test-backtrace.c [deleted file]
tools/perf/config/feature-checks/test-bionic.c [deleted file]
tools/perf/config/feature-checks/test-compile.c [deleted file]
tools/perf/config/feature-checks/test-cplus-demangle.c [deleted file]
tools/perf/config/feature-checks/test-dwarf.c [deleted file]
tools/perf/config/feature-checks/test-fortify-source.c [deleted file]
tools/perf/config/feature-checks/test-glibc.c [deleted file]
tools/perf/config/feature-checks/test-gtk2-infobar.c [deleted file]
tools/perf/config/feature-checks/test-gtk2.c [deleted file]
tools/perf/config/feature-checks/test-hello.c [deleted file]
tools/perf/config/feature-checks/test-libaudit.c [deleted file]
tools/perf/config/feature-checks/test-libbfd.c [deleted file]
tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c [deleted file]
tools/perf/config/feature-checks/test-libelf-getphdrnum.c [deleted file]
tools/perf/config/feature-checks/test-libelf-mmap.c [deleted file]
tools/perf/config/feature-checks/test-libelf.c [deleted file]
tools/perf/config/feature-checks/test-libnuma.c [deleted file]
tools/perf/config/feature-checks/test-libperl.c [deleted file]
tools/perf/config/feature-checks/test-libpython-version.c [deleted file]
tools/perf/config/feature-checks/test-libpython.c [deleted file]
tools/perf/config/feature-checks/test-libslang.c [deleted file]
tools/perf/config/feature-checks/test-libunwind-debug-frame.c [deleted file]
tools/perf/config/feature-checks/test-libunwind.c [deleted file]
tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c [deleted file]
tools/perf/config/feature-checks/test-stackprotector-all.c [deleted file]
tools/perf/config/feature-checks/test-sync-compare-and-swap.c [deleted file]
tools/perf/config/feature-checks/test-timerfd.c [deleted file]
tools/perf/config/feature-checks/test-zlib.c [deleted file]
tools/perf/config/utilities.mak
tools/perf/perf-completion.sh
tools/perf/perf.c
tools/perf/perf.h
tools/perf/scripts/Build [new file with mode: 0644]
tools/perf/scripts/perl/Perf-Trace-Util/Build [new file with mode: 0644]
tools/perf/scripts/python/Perf-Trace-Util/Build [new file with mode: 0644]
tools/perf/tests/Build [new file with mode: 0644]
tools/perf/tests/attr/base-record
tools/perf/tests/attr/base-stat
tools/perf/tests/builtin-test.c
tools/perf/tests/dso-data.c
tools/perf/tests/kmod-path.c [new file with mode: 0644]
tools/perf/tests/make
tools/perf/tests/open-syscall-all-cpus.c
tools/perf/tests/open-syscall.c
tools/perf/tests/parse-events.c
tools/perf/tests/tests.h
tools/perf/ui/Build [new file with mode: 0644]
tools/perf/ui/browsers/Build [new file with mode: 0644]
tools/perf/ui/browsers/annotate.c
tools/perf/ui/browsers/hists.c
tools/perf/ui/gtk/Build [new file with mode: 0644]
tools/perf/ui/tui/Build [new file with mode: 0644]
tools/perf/util/Build [new file with mode: 0644]
tools/perf/util/annotate.c
tools/perf/util/build-id.c
tools/perf/util/build-id.h
tools/perf/util/cache.h
tools/perf/util/callchain.c
tools/perf/util/callchain.h
tools/perf/util/cloexec.c
tools/perf/util/cloexec.h
tools/perf/util/data-convert-bt.c [new file with mode: 0644]
tools/perf/util/data-convert-bt.h [new file with mode: 0644]
tools/perf/util/db-export.c
tools/perf/util/db-export.h
tools/perf/util/debug.c
tools/perf/util/debug.h
tools/perf/util/dso.c
tools/perf/util/dso.h
tools/perf/util/dwarf-aux.c
tools/perf/util/dwarf-aux.h
tools/perf/util/event.c
tools/perf/util/event.h
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/header.c
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/include/asm/alternative-asm.h
tools/perf/util/kvm-stat.h
tools/perf/util/lzma.c [new file with mode: 0644]
tools/perf/util/machine.c
tools/perf/util/machine.h
tools/perf/util/map.c
tools/perf/util/map.h
tools/perf/util/ordered-events.c
tools/perf/util/ordered-events.h
tools/perf/util/parse-events.c
tools/perf/util/parse-events.h
tools/perf/util/parse-events.l
tools/perf/util/parse-options.c
tools/perf/util/parse-options.h
tools/perf/util/probe-event.c
tools/perf/util/probe-event.h
tools/perf/util/probe-finder.c
tools/perf/util/python-ext-sources
tools/perf/util/scripting-engines/Build [new file with mode: 0644]
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/session.c
tools/perf/util/session.h
tools/perf/util/setup.py
tools/perf/util/sort.c
tools/perf/util/sort.h
tools/perf/util/symbol-elf.c
tools/perf/util/symbol-minimal.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/target.c
tools/perf/util/thread.c
tools/perf/util/thread.h
tools/perf/util/tool.h
tools/perf/util/trace-event-parse.c
tools/perf/util/trace-event-scripting.c
tools/perf/util/trace-event.h
tools/perf/util/unwind-libunwind.c
tools/perf/util/util.c
tools/perf/util/util.h
tools/testing/selftests/Makefile
tools/testing/selftests/breakpoints/Makefile
tools/testing/selftests/cpu-hotplug/Makefile
tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh [new file with mode: 0755]
tools/testing/selftests/cpu-hotplug/on-off-test.sh [deleted file]
tools/testing/selftests/efivarfs/Makefile
tools/testing/selftests/efivarfs/efivarfs.sh [changed mode: 0644->0755]
tools/testing/selftests/exec/Makefile
tools/testing/selftests/firmware/Makefile
tools/testing/selftests/firmware/fw_filesystem.sh [changed mode: 0644->0755]
tools/testing/selftests/firmware/fw_userhelper.sh [changed mode: 0644->0755]
tools/testing/selftests/ftrace/Makefile
tools/testing/selftests/ftrace/test.d/00basic/basic4.tc
tools/testing/selftests/ftrace/test.d/event/event-enable.tc
tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc
tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc
tools/testing/selftests/gen_kselftest_tar.sh [new file with mode: 0755]
tools/testing/selftests/ipc/Makefile
tools/testing/selftests/kcmp/Makefile
tools/testing/selftests/kselftest_install.sh [new file with mode: 0755]
tools/testing/selftests/lib.mk [new file with mode: 0644]
tools/testing/selftests/memfd/Makefile
tools/testing/selftests/memory-hotplug/Makefile
tools/testing/selftests/memory-hotplug/mem-on-off-test.sh [new file with mode: 0755]
tools/testing/selftests/memory-hotplug/on-off-test.sh [deleted file]
tools/testing/selftests/mount/.gitignore [new file with mode: 0644]
tools/testing/selftests/mount/Makefile
tools/testing/selftests/mqueue/Makefile
tools/testing/selftests/net/Makefile
tools/testing/selftests/net/run_afpackettests [changed mode: 0644->0755]
tools/testing/selftests/net/run_netsocktests [changed mode: 0644->0755]
tools/testing/selftests/powerpc/Makefile
tools/testing/selftests/powerpc/copyloops/Makefile
tools/testing/selftests/powerpc/mm/Makefile
tools/testing/selftests/powerpc/pmu/Makefile
tools/testing/selftests/powerpc/pmu/ebb/Makefile
tools/testing/selftests/powerpc/primitives/Makefile
tools/testing/selftests/powerpc/stringloops/Makefile
tools/testing/selftests/powerpc/tm/Makefile
tools/testing/selftests/ptrace/Makefile
tools/testing/selftests/rcutorture/bin/kvm.sh
tools/testing/selftests/rcutorture/configs/rcu/CFcommon
tools/testing/selftests/size/Makefile
tools/testing/selftests/sysctl/Makefile
tools/testing/selftests/sysctl/run_numerictests [changed mode: 0644->0755]
tools/testing/selftests/sysctl/run_stringtests [changed mode: 0644->0755]
tools/testing/selftests/timers/Makefile
tools/testing/selftests/timers/alarmtimer-suspend.c [new file with mode: 0644]
tools/testing/selftests/timers/change_skew.c [new file with mode: 0644]
tools/testing/selftests/timers/clocksource-switch.c [new file with mode: 0644]
tools/testing/selftests/timers/inconsistency-check.c [new file with mode: 0644]
tools/testing/selftests/timers/leap-a-day.c [new file with mode: 0644]
tools/testing/selftests/timers/leapcrash.c [new file with mode: 0644]
tools/testing/selftests/timers/mqueue-lat.c [new file with mode: 0644]
tools/testing/selftests/timers/nanosleep.c [new file with mode: 0644]
tools/testing/selftests/timers/nsleep-lat.c [new file with mode: 0644]
tools/testing/selftests/timers/posix_timers.c
tools/testing/selftests/timers/raw_skew.c [new file with mode: 0644]
tools/testing/selftests/timers/rtctest.c [new file with mode: 0644]
tools/testing/selftests/timers/set-2038.c [new file with mode: 0644]
tools/testing/selftests/timers/set-tai.c [new file with mode: 0644]
tools/testing/selftests/timers/set-timer-lat.c [new file with mode: 0644]
tools/testing/selftests/timers/skew_consistency.c [new file with mode: 0644]
tools/testing/selftests/timers/threadtest.c [new file with mode: 0644]
tools/testing/selftests/timers/valid-adjtimex.c [new file with mode: 0644]
tools/testing/selftests/user/Makefile
tools/testing/selftests/vm/Makefile
tools/testing/selftests/vm/run_vmtests [changed mode: 0644->0755]
tools/testing/selftests/x86/.gitignore [new file with mode: 0644]
tools/testing/selftests/x86/Makefile [new file with mode: 0644]
tools/testing/selftests/x86/run_x86_tests.sh [new file with mode: 0644]
tools/testing/selftests/x86/sigreturn.c [new file with mode: 0644]
tools/testing/selftests/x86/trivial_32bit_program.c [new file with mode: 0644]
virt/kvm/arm/arch_timer.c
virt/kvm/arm/vgic-v2-emul.c
virt/kvm/arm/vgic-v3-emul.c
virt/kvm/arm/vgic.c
virt/kvm/arm/vgic.h
virt/kvm/coalesced_mmio.c
virt/kvm/eventfd.c
virt/kvm/iodev.h [deleted file]
virt/kvm/irqchip.c
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index 96935df0b6fe5d10cf1558c8ed6a15af89fb0cac..843e17647f3b72bfda48632d67ba089307b15602 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -187,6 +187,10 @@ N: Krishna Balasubramanian
 E: balasub@cis.ohio-state.edu
 D: Wrote SYS V IPC (part of standard kernel since 0.99.10)
 
+N: Chris Ball
+E: chris@printf.net
+D: Former maintainer of the MMC/SD/SDIO subsystem.
+
 N: Dario Ballabio
 E: ballabio_dario@emc.com
 E: dario.ballabio@tiscalinet.it
diff --git a/Documentation/ABI/stable/sysfs-devices b/Documentation/ABI/stable/sysfs-devices
new file mode 100644 (file)
index 0000000..43f78b8
--- /dev/null
@@ -0,0 +1,10 @@
+# Note: This documents additional properties of any device beyond what
+# is documented in Documentation/sysfs-rules.txt
+
+What:          /sys/devices/*/of_path
+Date:          February 2015
+Contact:       Device Tree mailing list <devicetree@vger.kernel.org>
+Description:
+               Any device associated with a device-tree node will have
+               an of_path symlink pointing to the corresponding device
+               node in /sys/firmware/devicetree/
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-printer b/Documentation/ABI/testing/configfs-usb-gadget-printer
new file mode 100644 (file)
index 0000000..6b0714e
--- /dev/null
@@ -0,0 +1,9 @@
+What:          /config/usb-gadget/gadget/functions/printer.name
+Date:          Apr 2015
+KernelVersion: 4.1
+Description:
+               The attributes:
+
+               pnp_string      - Data to be passed to the host in pnp string
+               q_len           - Number of requests per endpoint
+
index 9a70c31619ea8a72e3d756413e4b24f65c7aab4b..3befcb19f41415393e56a6ef496675ab31c4bc2a 100644 (file)
@@ -253,6 +253,8 @@ What:               /sys/bus/iio/devices/iio:deviceX/in_temp_offset
 What:          /sys/bus/iio/devices/iio:deviceX/in_pressureY_offset
 What:          /sys/bus/iio/devices/iio:deviceX/in_pressure_offset
 What:          /sys/bus/iio/devices/iio:deviceX/in_humidityrelative_offset
+What:          /sys/bus/iio/devices/iio:deviceX/in_magn_offset
+What:          /sys/bus/iio/devices/iio:deviceX/in_rot_offset
 KernelVersion: 2.6.35
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -296,6 +298,7 @@ What:               /sys/bus/iio/devices/iio:deviceX/in_pressureY_scale
 What:          /sys/bus/iio/devices/iio:deviceX/in_pressure_scale
 What:          /sys/bus/iio/devices/iio:deviceX/in_humidityrelative_scale
 What:          /sys/bus/iio/devices/iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_scale
+What:          /sys/bus/iio/devices/iio:deviceX/in_illuminance_scale
 KernelVersion: 2.6.35
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -336,6 +339,7 @@ what                /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale
 what           /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale
 What:          /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibscale
 What:          /sys/bus/iio/devices/iio:deviceX/in_pressure_calibscale
+What:          /sys/bus/iio/devices/iio:deviceX/in_illuminance_calibscale
 KernelVersion: 2.6.35
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -347,7 +351,7 @@ What:               /sys/bus/iio/devices/iio:deviceX/in_activity_calibgender
 What:          /sys/bus/iio/devices/iio:deviceX/in_energy_calibgender
 What:          /sys/bus/iio/devices/iio:deviceX/in_distance_calibgender
 What:          /sys/bus/iio/devices/iio:deviceX/in_velocity_calibgender
-KernelVersion: 3.20
+KernelVersion: 4.0
 Contact:       linux-iio@vger.kernel.org
 Description:
                Gender of the user (e.g.: male, female) used by some pedometers
@@ -358,7 +362,7 @@ What:               /sys/bus/iio/devices/iio:deviceX/in_activity_calibgender_available
 What:          /sys/bus/iio/devices/iio:deviceX/in_energy_calibgender_available
 What:          /sys/bus/iio/devices/iio:deviceX/in_distance_calibgender_available
 What:          /sys/bus/iio/devices/iio:deviceX/in_velocity_calibgender_available
-KernelVersion: 3.20
+KernelVersion: 4.0
 Contact:       linux-iio@vger.kernel.org
 Description:
                Lists all available gender values (e.g.: male, female).
@@ -375,7 +379,7 @@ Description:
                type.
 
 What:          /sys/bus/iio/devices/iio:deviceX/in_energy_calibweight
-KernelVersion: 3.20
+KernelVersion: 4.0
 Contact:       linux-iio@vger.kernel.org
 Description:
                Weight of the user (in kg). It is needed by some pedometers
@@ -612,6 +616,8 @@ Description:
                a given event type is enabled a future point (and not those for
                whatever event was previously enabled).
 
+What:          /sys/.../events/in_accel_thresh_rising_value
+What:          /sys/.../events/in_accel_thresh_falling_value
 What:          /sys/.../events/in_accel_x_raw_thresh_rising_value
 What:          /sys/.../events/in_accel_x_raw_thresh_falling_value
 What:          /sys/.../events/in_accel_y_raw_thresh_rising_value
@@ -661,6 +667,24 @@ Description:
                value is in raw device units or in processed units (as _raw
                and _input do on sysfs direct channel read attributes).
 
+What:          /sys/.../events/in_accel_scale
+What:          /sys/.../events/in_accel_peak_scale
+What:          /sys/.../events/in_anglvel_scale
+What:          /sys/.../events/in_magn_scale
+What:          /sys/.../events/in_rot_from_north_magnetic_scale
+What:          /sys/.../events/in_rot_from_north_true_scale
+What:          /sys/.../events/in_voltage_scale
+What:          /sys/.../events/in_voltage_supply_scale
+What:          /sys/.../events/in_temp_scale
+What:          /sys/.../events/in_illuminance_scale
+What:          /sys/.../events/in_proximity_scale
+KernelVersion: 3.21
+Contact:       linux-iio@vger.kernel.org
+Description:
+                Specifies the conversion factor from the standard units
+                to device specific units used to set the event trigger
+                threshold.
+
 What:          /sys/.../events/in_accel_x_thresh_rising_hysteresis
 What:          /sys/.../events/in_accel_x_thresh_falling_hysteresis
 What:          /sys/.../events/in_accel_x_thresh_either_hysteresis
@@ -776,7 +800,7 @@ Description:
 
 What:          /sys/.../events/in_accel_x_thresh_rising_period
 What:          /sys/.../events/in_accel_x_thresh_falling_period
-hat:           /sys/.../events/in_accel_x_roc_rising_period
+What:          /sys/.../events/in_accel_x_roc_rising_period
 What:          /sys/.../events/in_accel_x_roc_falling_period
 What:          /sys/.../events/in_accel_y_thresh_rising_period
 What:          /sys/.../events/in_accel_y_thresh_falling_period
@@ -923,7 +947,7 @@ Description:
                this type.
 
 What:          /sys/.../events/in_steps_change_en
-KernelVersion: 3.20
+KernelVersion: 4.0
 Contact:       linux-iio@vger.kernel.org
 Description:
                Event generated when channel passes a threshold on the absolute
@@ -932,7 +956,7 @@ Description:
                in_steps_change_value.
 
 What:          /sys/.../events/in_steps_change_value
-KernelVersion: 3.20
+KernelVersion: 4.0
 Contact:       linux-iio@vger.kernel.org
 Description:
                Specifies the value of change threshold that the
@@ -997,6 +1021,7 @@ What:              /sys/.../iio:deviceX/scan_elements/in_incli_y_en
 What:          /sys/.../iio:deviceX/scan_elements/in_pressureY_en
 What:          /sys/.../iio:deviceX/scan_elements/in_pressure_en
 What:          /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_en
+What:          /sys/.../iio:deviceX/scan_elements/in_proximity_en
 KernelVersion: 2.6.37
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -1013,6 +1038,7 @@ What:             /sys/.../iio:deviceX/scan_elements/in_timestamp_type
 What:          /sys/.../iio:deviceX/scan_elements/in_pressureY_type
 What:          /sys/.../iio:deviceX/scan_elements/in_pressure_type
 What:          /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_type
+What:          /sys/.../iio:deviceX/scan_elements/in_proximity_type
 KernelVersion: 2.6.37
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -1064,6 +1090,7 @@ What:             /sys/.../iio:deviceX/scan_elements/in_timestamp_index
 What:          /sys/.../iio:deviceX/scan_elements/in_pressureY_index
 What:          /sys/.../iio:deviceX/scan_elements/in_pressure_index
 What:          /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_index
+What:          /sys/.../iio:deviceX/scan_elements/in_proximity_index
 KernelVersion: 2.6.37
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -1104,7 +1131,7 @@ Description:
 
 What:          /sys/.../iio:deviceX/in_energy_input
 What:          /sys/.../iio:deviceX/in_energy_raw
-KernelVersion: 3.20
+KernelVersion: 4.0
 Contact:       linux-iio@vger.kernel.org
 Description:
                This attribute is used to read the energy value reported by the
@@ -1113,7 +1140,7 @@ Description:
 
 What:          /sys/.../iio:deviceX/in_distance_input
 What:          /sys/.../iio:deviceX/in_distance_raw
-KernelVersion: 3.20
+KernelVersion: 4.0
 Contact:       linux-iio@vger.kernel.org
 Description:
                This attribute is used to read the distance covered by the user
@@ -1143,9 +1170,13 @@ Description:
                values should behave in the same way as a distance, i.e. lower
                values indicate something is closer to the sensor.
 
+What:          /sys/.../iio:deviceX/in_illuminance_input
+What:          /sys/.../iio:deviceX/in_illuminance_raw
 What:          /sys/.../iio:deviceX/in_illuminanceY_input
 What:          /sys/.../iio:deviceX/in_illuminanceY_raw
 What:          /sys/.../iio:deviceX/in_illuminanceY_mean_raw
+What:          /sys/.../iio:deviceX/in_illuminance_ir_raw
+What:          /sys/.../iio:deviceX/in_illuminance_clear_raw
 KernelVersion: 3.4
 Contact:       linux-iio@vger.kernel.org
 Description:
@@ -1174,7 +1205,7 @@ Description:
                seconds.
 
 What:          /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_integration_time
-KernelVersion: 3.20
+KernelVersion: 4.0
 Contact:       linux-iio@vger.kernel.org
 Description:
                Number of seconds in which to compute speed.
@@ -1236,7 +1267,7 @@ Description:
                Units after application of scale are m/s.
 
 What:          /sys/.../iio:deviceX/in_steps_debounce_count
-KernelVersion: 3.20
+KernelVersion: 4.0
 Contact:       linux-iio@vger.kernel.org
 Description:
                Specifies the number of steps that must occur within
@@ -1244,8 +1275,92 @@ Description:
                consumer is making steps.
 
 What:          /sys/.../iio:deviceX/in_steps_debounce_time
-KernelVersion: 3.20
+KernelVersion: 4.0
 Contact:       linux-iio@vger.kernel.org
 Description:
                Specifies number of seconds in which we compute the steps
                that occur in order to decide if the consumer is making steps.
+
+What:          /sys/bus/iio/devices/iio:deviceX/buffer/watermark
+KernelVersion: 4.2
+Contact:       linux-iio@vger.kernel.org
+Description:
+               A single positive integer specifying the maximum number of scan
+               elements to wait for.
+               Poll will block until the watermark is reached.
+               Blocking read will wait until the minimum between the requested
+               read amount or the low water mark is available.
+               Non-blocking read will retrieve the available samples from the
+               buffer even if there are less samples then watermark level. This
+               allows the application to block on poll with a timeout and read
+               the available samples after the timeout expires and thus have a
+               maximum delay guarantee.
+
+What:          /sys/bus/iio/devices/iio:deviceX/buffer/hwfifo_enabled
+KernelVersion: 4.2
+Contact:       linux-iio@vger.kernel.org
+Description:
+               A read-only boolean value that indicates if the hardware fifo is
+               currently enabled or disabled. If the device does not have a
+               hardware fifo this entry is not present.
+               The hardware fifo is enabled when the buffer is enabled if the
+               current hardware fifo watermark level is set and other current
+               device settings allows it (e.g. if a trigger is set that samples
+               data differently that the hardware fifo does then hardware fifo
+               will not enabled).
+               If the hardware fifo is enabled and the level of the hardware
+               fifo reaches the hardware fifo watermark level the device will
+               flush its hardware fifo to the device buffer. Doing a non
+               blocking read on the device when no samples are present in the
+               device buffer will also force a flush.
+               When the hardware fifo is enabled there is no need to use a
+               trigger to use buffer mode since the watermark settings
+               guarantees that the hardware fifo is flushed to the device
+               buffer.
+
+What:          /sys/bus/iio/devices/iio:deviceX/buffer/hwfifo_watermark
+KernelVersion: 4.2
+Contact:       linux-iio@vger.kernel.org
+Description:
+               Read-only entry that contains a single integer specifying the
+               current watermark level for the hardware fifo. If the device
+               does not have a hardware fifo this entry is not present.
+               The watermark level for the hardware fifo is set by the driver
+               based on the value set by the user in buffer/watermark but
+               taking into account hardware limitations (e.g. most hardware
+               buffers are limited to 32-64 samples, some hardware buffers
+               watermarks are fixed or have minimum levels).  A value of 0
+               means that the hardware watermark is unset.
+
+What:          /sys/bus/iio/devices/iio:deviceX/buffer/hwfifo_watermark_min
+KernelVersion: 4.2
+Contact:       linux-iio@vger.kernel.org
+Description:
+               A single positive integer specifying the minimum watermark level
+               for the hardware fifo of this device. If the device does not
+               have a hardware fifo this entry is not present.
+               If the user sets buffer/watermark to a value less than this one,
+               then the hardware watermark will remain unset.
+
+What:         /sys/bus/iio/devices/iio:deviceX/buffer/hwfifo_watermark_max
+KernelVersion: 4.2
+Contact:       linux-iio@vger.kernel.org
+Description:
+               A single positive integer specifying the maximum watermark level
+               for the hardware fifo of this device. If the device does not
+               have a hardware fifo this entry is not present.
+               If the user sets buffer/watermark to a value greater than this
+               one, then the hardware watermark will be capped at this value.
+
+What:         /sys/bus/iio/devices/iio:deviceX/buffer/hwfifo_watermark_available
+KernelVersion: 4.2
+Contact:       linux-iio@vger.kernel.org
+Description:
+               A list of positive integers specifying the available watermark
+               levels for the hardware fifo. This entry is optional and if it
+               is not present it means that all the values between
+               hwfifo_watermark_min and hwfifo_watermark_max are supported.
+               If the user sets buffer/watermark to a value greater than
+               hwfifo_watermak_min but not equal to any of the values in this
+               list, the driver will chose an appropriate value for the
+               hardware fifo watermark level.
index b6490e14fe83e8862f47b45152e5f1409d9d3bac..48942cacb0bf490ef7da785536702bff0d7b2a90 100644 (file)
@@ -8,3 +8,13 @@ Description:   When read, this file returns the device's raw binary HID
                report descriptor.
                This file cannot be written.
 Users:         HIDAPI library (http://www.signal11.us/oss/hidapi)
+
+What:          For USB devices : /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/country
+               For BT devices  : /sys/class/bluetooth/hci<addr>/<hid-bus>:<vendor-id>:<product-id>.<num>/country
+               Symlink         : /sys/class/hidraw/hidraw<num>/device/country
+Date:          February 2015
+KernelVersion: 3.19
+Contact:       Olivier Gay <ogay@logitech.com>
+Description:   When read, this file returns the hex integer value in ASCII
+               of the device's HID country code (e.g. 21 for US).
+               This file cannot be written.
index 167d9032b970a762617eab93fc6803bcda23bd2f..b3f6a2ac5007896b82ee09d4e96e9392d8fb6888 100644 (file)
@@ -5,3 +5,48 @@ Contact:       Michal Malý <madcatxster@gmail.com>
 Description:   Display minimum, maximum and current range of the steering
                wheel. Writing a value within min and max boundaries sets the
                range of the wheel.
+
+What:          /sys/bus/hid/drivers/logitech/<dev>/alternate_modes
+Date:          Feb 2015
+KernelVersion: 4.1
+Contact:       Michal Malý <madcatxster@gmail.com>
+Description:   Displays a set of alternate modes supported by a wheel. Each
+               mode is listed as follows:
+                 Tag: Mode Name
+               Currently active mode is marked with an asterisk. List also
+               contains an abstract item "native" which always denotes the
+               native mode of the wheel. Echoing the mode tag switches the
+               wheel into the corresponding mode. Depending on the exact model
+               of the wheel not all listed modes might always be selectable.
+               If a wheel cannot be switched into the desired mode, -EINVAL
+               is returned accompanied with an explanatory message in the
+               kernel log.
+               This entry is not created for devices that have only one mode.
+
+               Currently supported mode switches:
+               Driving Force Pro:
+                 DF-EX --> DFP
+
+               G25:
+                 DF-EX --> DFP --> G25
+
+               G27:
+                 DF-EX <*> DFP <-> G25 <-> G27
+                 DF-EX <*--------> G25 <-> G27
+                 DF-EX <*----------------> G27
+
+               DFGT:
+                 DF-EX <*> DFP <-> DFGT
+                 DF-EX <*--------> DFGT
+
+               * hid_logitech module must be loaded with lg4ff_no_autoswitch=1
+                 parameter set in order for the switch to DF-EX mode to work.
+
+What:          /sys/bus/hid/drivers/logitech/<dev>/real_id
+Date:          Feb 2015
+KernelVersion: 4.1
+Contact:       Michal Malý <madcatxster@gmail.com>
+Description:   Displays the real model of the wheel regardless of any
+               alternate mode the wheel might be switched to.
+               It is a read-only value.
+               This entry is not created for devices that have only one mode.
index 9518006f66759fa0540c7156cde630cc13489e23..123881f62219d444303b047154b25d39363fb9f8 100644 (file)
@@ -564,14 +564,14 @@ to be handled by platform and generic code, not individual drivers.
 8. Vendor and device identifications
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-One is not required to add new device ids to include/linux/pci_ids.h.
-Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids.
+Do not add new device or vendor IDs to include/linux/pci_ids.h unless they
+are shared across multiple drivers.  You can add private definitions in
+your driver if they're helpful, or just use plain hex constants.
 
-PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary
-hex numbers (vendor controlled) and normally used only in a single
-location, the pci_device_id table.
+The device IDs are arbitrary hex numbers (vendor controlled) and normally used
+only in a single location, the pci_device_id table.
 
-Please DO submit new vendor/device ids to pciids.sourceforge.net project.
+Please DO submit new vendor/device IDs to http://pciids.sourceforge.net/.
 
 
 
index f51861bcb07bbbc226e0d1af2897f6b49bcf82c5..e550c8b98139974343de5e4890c94f642f0a53d3 100644 (file)
                        APEI Error INJection
                        ~~~~~~~~~~~~~~~~~~~~
 
-EINJ provides a hardware error injection mechanism
-It is very useful for debugging and testing of other APEI and RAS features.
+EINJ provides a hardware error injection mechanism. It is very useful
+for debugging and testing APEI and RAS features in general.
 
-To use EINJ, make sure the following are enabled in your kernel
+You need to check whether your BIOS supports EINJ first. For that, look
+for early boot messages similar to this one:
+
+ACPI: EINJ 0x000000007370A000 000150 (v01 INTEL           00000001 INTL 00000001)
+
+which shows that the BIOS is exposing an EINJ table - it is the
+mechanism through which the injection is done.
+
+Alternatively, look in /sys/firmware/acpi/tables for an "EINJ" file,
+which is a different representation of the same thing.
+
+It doesn't necessarily mean that EINJ is not supported if those above
+don't exist: before you give up, go into BIOS setup to see if the BIOS
+has an option to enable error injection. Look for something called WHEA
+or similar. Often, you need to enable an ACPI5 support option prior, in
+order to see the APEI,EINJ,... functionality supported and exposed by
+the BIOS menu.
+
+To use EINJ, make sure the following are options enabled in your kernel
 configuration:
 
 CONFIG_DEBUG_FS
 CONFIG_ACPI_APEI
 CONFIG_ACPI_APEI_EINJ
 
-The user interface of EINJ is debug file system, under the
-directory apei/einj. The following files are provided.
+The EINJ user interface is in <debugfs mount point>/apei/einj.
+
+The following files belong to it:
 
 - available_error_type
-  Reading this file returns the error injection capability of the
-  platform, that is, which error types are supported. The error type
-  definition is as follow, the left field is the error type value, the
-  right field is error description.
-
-    0x00000001 Processor Correctable
-    0x00000002 Processor Uncorrectable non-fatal
-    0x00000004 Processor Uncorrectable fatal
-    0x00000008  Memory Correctable
-    0x00000010  Memory Uncorrectable non-fatal
-    0x00000020  Memory Uncorrectable fatal
-    0x00000040 PCI Express Correctable
-    0x00000080 PCI Express Uncorrectable fatal
-    0x00000100 PCI Express Uncorrectable non-fatal
-    0x00000200 Platform Correctable
-    0x00000400 Platform Uncorrectable non-fatal
-    0x00000800 Platform Uncorrectable fatal
-
-  The format of file contents are as above, except there are only the
-  available error type lines.
+
+  This file shows which error types are supported:
+
+  Error Type Value     Error Description
+  ================     =================
+  0x00000001           Processor Correctable
+  0x00000002           Processor Uncorrectable non-fatal
+  0x00000004           Processor Uncorrectable fatal
+  0x00000008           Memory Correctable
+  0x00000010           Memory Uncorrectable non-fatal
+  0x00000020           Memory Uncorrectable fatal
+  0x00000040           PCI Express Correctable
+  0x00000080           PCI Express Uncorrectable fatal
+  0x00000100           PCI Express Uncorrectable non-fatal
+  0x00000200           Platform Correctable
+  0x00000400           Platform Uncorrectable non-fatal
+  0x00000800           Platform Uncorrectable fatal
+
+  The format of the file contents are as above, except present are only
+  the available error types.
 
 - error_type
-  This file is used to set the error type value. The error type value
-  is defined in "available_error_type" description.
+
+  Set the value of the error type being injected. Possible error types
+  are defined in the file available_error_type above.
 
 - error_inject
-  Write any integer to this file to trigger the error
-  injection. Before this, please specify all necessary error
-  parameters.
+
+  Write any integer to this file to trigger the error injection. Make
+  sure you have specified all necessary error parameters, i.e. this
+  write should be the last step when injecting errors.
 
 - flags
-  Present for kernel version 3.13 and above. Used to specify which
-  of param{1..4} are valid and should be used by BIOS during injection.
-  Value is a bitmask as specified in ACPI5.0 spec for the
+
+  Present for kernel versions 3.13 and above. Used to specify which
+  of param{1..4} are valid and should be used by the firmware during
+  injection. Value is a bitmask as specified in ACPI5.0 spec for the
   SET_ERROR_TYPE_WITH_ADDRESS data structure:
-       Bit 0 - Processor APIC field valid (see param3 below)
-       Bit 1 - Memory address and mask valid (param1 and param2)
-       Bit 2 - PCIe (seg,bus,dev,fn) valid (param4 below)
-  If set to zero, legacy behaviour is used where the type of injection
-  specifies just one bit set, and param1 is multiplexed.
+
+       Bit 0 - Processor APIC field valid (see param3 below).
+       Bit 1 - Memory address and mask valid (param1 and param2).
+       Bit 2 - PCIe (seg,bus,dev,fn) valid (see param4 below).
+
+  If set to zero, legacy behavior is mimicked where the type of
+  injection specifies just one bit set, and param1 is multiplexed.
 
 - param1
-  This file is used to set the first error parameter value. Effect of
-  parameter depends on error_type specified. For example, if error
-  type is memory related type, the param1 should be a valid physical
-  memory address. [Unless "flag" is set - see above]
+
+  This file is used to set the first error parameter value. Its effect
+  depends on the error type specified in error_type. For example, if
+  error type is memory related type, the param1 should be a valid
+  physical memory address. [Unless "flag" is set - see above]
 
 - param2
-  This file is used to set the second error parameter value. Effect of
-  parameter depends on error_type specified. For example, if error
-  type is memory related type, the param2 should be a physical memory
-  address mask. Linux requires page or narrower granularity, say,
-  0xfffffffffffff000.
+
+  Same use as param1 above. For example, if error type is of memory
+  related type, then param2 should be a physical memory address mask.
+  Linux requires page or narrower granularity, say, 0xfffffffffffff000.
 
 - param3
-  Used when the 0x1 bit is set in "flag" to specify the APIC id
+
+  Used when the 0x1 bit is set in "flags" to specify the APIC id
 
 - param4
-  Used when the 0x4 bit is set in "flag" to specify target PCIe device
+  Used when the 0x4 bit is set in "flags" to specify target PCIe device
 
 - notrigger
-  The EINJ mechanism is a two step process. First inject the error, then
-  perform some actions to trigger it. Setting "notrigger" to 1 skips the
-  trigger phase, which *may* allow the user to cause the error in some other
-  context by a simple access to the cpu, memory location, or device that is
-  the target of the error injection. Whether this actually works depends
-  on what operations the BIOS actually includes in the trigger phase.
-
-BIOS versions based in the ACPI 4.0 specification have limited options
-to control where the errors are injected.  Your BIOS may support an
-extension (enabled with the param_extension=1 module parameter, or
-boot command line einj.param_extension=1). This allows the address
-and mask for memory injections to be specified by the param1 and
-param2 files in apei/einj.
-
-BIOS versions using the ACPI 5.0 specification have more control over
-the target of the injection. For processor related errors (type 0x1,
-0x2 and 0x4) the APICID of the target should be provided using the
-param1 file in apei/einj. For memory errors (type 0x8, 0x10 and 0x20)
-the address is set using param1 with a mask in param2 (0x0 is equivalent
-to all ones). For PCI express errors (type 0x40, 0x80 and 0x100) the
-segment, bus, device and function are specified using param1:
+
+  The error injection mechanism is a two-step process. First inject the
+  error, then perform some actions to trigger it. Setting "notrigger"
+  to 1 skips the trigger phase, which *may* allow the user to cause the
+  error in some other context by a simple access to the CPU, memory
+  location, or device that is the target of the error injection. Whether
+  this actually works depends on what operations the BIOS actually
+  includes in the trigger phase.
+
+BIOS versions based on the ACPI 4.0 specification have limited options
+in controlling where the errors are injected. Your BIOS may support an
+extension (enabled with the param_extension=1 module parameter, or boot
+command line einj.param_extension=1). This allows the address and mask
+for memory injections to be specified by the param1 and param2 files in
+apei/einj.
+
+BIOS versions based on the ACPI 5.0 specification have more control over
+the target of the injection. For processor-related errors (type 0x1, 0x2
+and 0x4), you can set flags to 0x3 (param3 for bit 0, and param1 and
+param2 for bit 1) so that you have more information added to the error
+signature being injected. The actual data passed is this:
+
+       memory_address = param1;
+       memory_address_range = param2;
+       apicid = param3;
+       pcie_sbdf = param4;
+
+For memory errors (type 0x8, 0x10 and 0x20) the address is set using
+param1 with a mask in param2 (0x0 is equivalent to all ones). For PCI
+express errors (type 0x40, 0x80 and 0x100) the segment, bus, device and
+function are specified using param1:
 
          31     24 23    16 15    11 10      8  7        0
        +-------------------------------------------------+
        | segment |   bus  | device | function | reserved |
        +-------------------------------------------------+
 
-An ACPI 5.0 BIOS may also allow vendor specific errors to be injected.
+Anyway, you get the idea, if there's doubt just take a look at the code
+in drivers/acpi/apei/einj.c.
+
+An ACPI 5.0 BIOS may also allow vendor-specific errors to be injected.
 In this case a file named vendor will contain identifying information
 from the BIOS that hopefully will allow an application wishing to use
-the vendor specific extension to tell that they are running on a BIOS
+the vendor-specific extension to tell that they are running on a BIOS
 that supports it. All vendor extensions have the 0x80000000 bit set in
 error_type. A file vendor_flags controls the interpretation of param1
 and param2 (1 = PROCESSOR, 2 = MEMORY, 4 = PCI). See your BIOS vendor
 documentation for details (and expect changes to this API if vendors
 creativity in using this feature expands beyond our expectations).
 
-Example:
+
+An error injection example:
+
 # cd /sys/kernel/debug/apei/einj
 # cat available_error_type             # See which errors can be injected
 0x00000002     Processor Uncorrectable non-fatal
 0x00000008     Memory Correctable
 0x00000010     Memory Uncorrectable non-fatal
 # echo 0x12345000 > param1             # Set memory address for injection
-# echo 0xfffffffffffff000 > param2     # Mask - anywhere in this page
+# echo $((-1 << 12)) > param2          # Mask 0xfffffffffffff000 - anywhere in this page
 # echo 0x8 > error_type                        # Choose correctable memory error
 # echo 1 > error_inject                        # Inject now
 
+You should see something like this in dmesg:
+
+[22715.830801] EDAC sbridge MC3: HANDLING MCE MEMORY ERROR
+[22715.834759] EDAC sbridge MC3: CPU 0: Machine Check Event: 0 Bank 7: 8c00004000010090
+[22715.834759] EDAC sbridge MC3: TSC 0
+[22715.834759] EDAC sbridge MC3: ADDR 12345000 EDAC sbridge MC3: MISC 144780c86
+[22715.834759] EDAC sbridge MC3: PROCESSOR 0:306e7 TIME 1422553404 SOCKET 0 APIC 0
+[22716.616173] EDAC MC3: 1 CE memory read error on CPU_SrcID#0_Channel#0_DIMM#0 (channel:0 slot:0 page:0x12345 offset:0x0 grain:32 syndrome:0x0 -  area:DRAM err_code:0001:0090 socket:0 channel_mask:1 rank:0)
 
 For more information about EINJ, please refer to ACPI specification
 version 4.0, section 17.5 and ACPI 5.0, section 18.6.
index 183e41bdcb69b5e05224cfe46dfaa427907482bf..dab6da3382d9f0b5f3c1e9f6e3fafc0cc2535de2 100644 (file)
@@ -201,11 +201,11 @@ These routines add 1 and subtract 1, respectively, from the given
 atomic_t and return the new counter value after the operation is
 performed.
 
-Unlike the above routines, it is required that explicit memory
-barriers are performed before and after the operation.  It must be
-done such that all memory operations before and after the atomic
-operation calls are strongly ordered with respect to the atomic
-operation itself.
+Unlike the above routines, it is required that these primitives
+include explicit memory barriers that are performed before and after
+the operation.  It must be done such that all memory operations before
+and after the atomic operation calls are strongly ordered with respect
+to the atomic operation itself.
 
 For example, it should behave as if a smp_mb() call existed both
 before and after the atomic operation.
@@ -233,21 +233,21 @@ These two routines increment and decrement by 1, respectively, the
 given atomic counter.  They return a boolean indicating whether the
 resulting counter value was zero or not.
 
-It requires explicit memory barrier semantics around the operation as
-above.
+Again, these primitives provide explicit memory barrier semantics around
+the atomic operation.
 
        int atomic_sub_and_test(int i, atomic_t *v);
 
 This is identical to atomic_dec_and_test() except that an explicit
-decrement is given instead of the implicit "1".  It requires explicit
-memory barrier semantics around the operation.
+decrement is given instead of the implicit "1".  This primitive must
+provide explicit memory barrier semantics around the operation.
 
        int atomic_add_negative(int i, atomic_t *v);
 
-The given increment is added to the given atomic counter value.  A
-boolean is return which indicates whether the resulting counter value
-is negative.  It requires explicit memory barrier semantics around the
-operation.
+The given increment is added to the given atomic counter value.  A boolean
+is return which indicates whether the resulting counter value is negative.
+This primitive must provide explicit memory barrier semantics around
+the operation.
 
 Then:
 
@@ -257,7 +257,7 @@ This performs an atomic exchange operation on the atomic variable v, setting
 the given new value.  It returns the old value that the atomic variable v had
 just before the operation.
 
-atomic_xchg requires explicit memory barriers around the operation.
+atomic_xchg must provide explicit memory barriers around the operation.
 
        int atomic_cmpxchg(atomic_t *v, int old, int new);
 
@@ -266,7 +266,7 @@ with the given old and new values. Like all atomic_xxx operations,
 atomic_cmpxchg will only satisfy its atomicity semantics as long as all
 other accesses of *v are performed through atomic_xxx operations.
 
-atomic_cmpxchg requires explicit memory barriers around the operation.
+atomic_cmpxchg must provide explicit memory barriers around the operation.
 
 The semantics for atomic_cmpxchg are the same as those defined for 'cas'
 below.
@@ -279,8 +279,8 @@ If the atomic value v is not equal to u, this function adds a to v, and
 returns non zero. If v is equal to u then it returns zero. This is done as
 an atomic operation.
 
-atomic_add_unless requires explicit memory barriers around the operation
-unless it fails (returns 0).
+atomic_add_unless must provide explicit memory barriers around the
+operation unless it fails (returns 0).
 
 atomic_inc_not_zero, equivalent to atomic_add_unless(v, 1, 0)
 
@@ -460,9 +460,9 @@ the return value into an int.  There are other places where things
 like this occur as well.
 
 These routines, like the atomic_t counter operations returning values,
-require explicit memory barrier semantics around their execution.  All
-memory operations before the atomic bit operation call must be made
-visible globally before the atomic bit operation is made visible.
+must provide explicit memory barrier semantics around their execution.
+All memory operations before the atomic bit operation call must be
+made visible globally before the atomic bit operation is made visible.
 Likewise, the atomic bit operation must be visible globally before any
 subsequent memory operation is made visible.  For example:
 
@@ -536,8 +536,9 @@ except that two underscores are prefixed to the interface name.
 These non-atomic variants also do not require any special memory
 barrier semantics.
 
-The routines xchg() and cmpxchg() need the same exact memory barriers
-as the atomic and bit operations returning values.
+The routines xchg() and cmpxchg() must provide the same exact
+memory-barrier semantics as the atomic and bit operations returning
+values.
 
 Spinlocks and rwlocks have memory barrier expectations as well.
 The rule to follow is simple:
index f2235a16252951c32b2a2ad151d92ac814b18e02..fdf7dff3f607d96bd03a896d92ba585b2a2d5ab0 100644 (file)
@@ -392,8 +392,10 @@ Put simply, it costs less to balance between two smaller sched domains
 than one big one, but doing so means that overloads in one of the
 two domains won't be load balanced to the other one.
 
-By default, there is one sched domain covering all CPUs, except those
-marked isolated using the kernel boot time "isolcpus=" argument.
+By default, there is one sched domain covering all CPUs, including those
+marked isolated using the kernel boot time "isolcpus=" argument. However,
+the isolated CPUs will not participate in load balancing, and will not
+have tasks running on them unless explicitly assigned.
 
 This default load balancing across all CPUs is not well suited for
 the following two situations:
@@ -465,6 +467,10 @@ such partially load balanced cpusets, as they may be artificially
 constrained to some subset of the CPUs allowed to them, for lack of
 load balancing to the other CPUs.
 
+CPUs in "cpuset.isolcpus" were excluded from load balancing by the
+isolcpus= kernel boot option, and will never be load balanced regardless
+of the value of "cpuset.sched_load_balance" in any cpuset.
+
 1.7.1 sched_load_balance implementation details.
 ------------------------------------------------
 
diff --git a/Documentation/cma/debugfs.txt b/Documentation/cma/debugfs.txt
new file mode 100644 (file)
index 0000000..6cef20a
--- /dev/null
@@ -0,0 +1,21 @@
+The CMA debugfs interface is useful to retrieve basic information out of the
+different CMA areas and to test allocation/release in each of the areas.
+
+Each CMA zone represents a directory under <debugfs>/cma/, indexed by the
+kernel's CMA index. So the first CMA zone would be:
+
+       <debugfs>/cma/cma-0
+
+The structure of the files created under that directory is as follows:
+
+ - [RO] base_pfn: The base PFN (Page Frame Number) of the zone.
+ - [RO] count: Amount of memory in the CMA area.
+ - [RO] order_per_bit: Order of pages represented by one bit.
+ - [RO] bitmap: The bitmap of page states in the zone.
+ - [WO] alloc: Allocate N pages from that CMA area. For example:
+
+       echo 5 > <debugfs>/cma/cma-2/alloc
+
+would try to allocate 5 pages from the cma-2 area.
+
+ - [WO] free: Free N pages from that CMA area, similar to the above.
diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-mscm-cpucfg.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-mscm-cpucfg.txt
new file mode 100644 (file)
index 0000000..44aa3c4
--- /dev/null
@@ -0,0 +1,14 @@
+Freescale Vybrid Miscellaneous System Control - CPU Configuration
+
+The MSCM IP contains multiple sub modules, this binding describes the first
+block of registers which contains CPU configuration information.
+
+Required properties:
+- compatible:  "fsl,vf610-mscm-cpucfg", "syscon"
+- reg:         the register range of the MSCM CPU configuration registers
+
+Example:
+       mscm_cpucfg: cpucfg@40001000 {
+               compatible = "fsl,vf610-mscm-cpucfg", "syscon";
+               reg = <0x40001000 0x800>;
+       }
diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-mscm-ir.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-mscm-ir.txt
new file mode 100644 (file)
index 0000000..669808b
--- /dev/null
@@ -0,0 +1,33 @@
+Freescale Vybrid Miscellaneous System Control - Interrupt Router
+
+The MSCM IP contains multiple sub modules, this binding describes the second
+block of registers which control the interrupt router. The interrupt router
+allows to configure the recipient of each peripheral interrupt. Furthermore
+it controls the directed processor interrupts. The module is available in all
+Vybrid SoC's but is only really useful in dual core configurations (VF6xx
+which comes with a Cortex-A5/Cortex-M4 combination).
+
+Required properties:
+- compatible:          "fsl,vf610-mscm-ir"
+- reg:                 the register range of the MSCM Interrupt Router
+- fsl,cpucfg:          The handle to the MSCM CPU configuration node, required
+                       to get the current CPU ID
+- interrupt-controller:        Identifies the node as an interrupt controller
+- #interrupt-cells:    Two cells, interrupt number and cells.
+                       The hardware interrupt number according to interrupt
+                       assignment of the interrupt router is required.
+                       Flags get passed only when using GIC as parent. Flags
+                       encoding as documented by the GIC bindings.
+- interrupt-parent:    Should be the phandle for the interrupt controller of
+                       the CPU the device tree is intended to be used on. This
+                       is either the node of the GIC or NVIC controller.
+
+Example:
+       mscm_ir: interrupt-controller@40001800 {
+               compatible = "fsl,vf610-mscm-ir";
+               reg = <0x40001800 0x400>;
+               fsl,cpucfg = <&mscm_cpucfg>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               interrupt-parent = <&intc>;
+       }
index c97484b73e7249692d6bd752af3745919f2fe9d0..1e0d21201d3aa7a02390fac92013bc3905d88b12 100644 (file)
@@ -56,11 +56,6 @@ Optional
   regions, used when the GIC doesn't have banked registers. The offset is
   cpu-offset * cpu-nr.
 
-- arm,routable-irqs : Total number of gic irq inputs which are not directly
-                 connected from the peripherals, but are routed dynamically
-                 by a crossbar/multiplexer preceding the GIC. The GIC irq
-                 input line is assigned dynamically when the corresponding
-                 peripheral's crossbar line is mapped.
 Example:
 
        intc: interrupt-controller@fff11000 {
@@ -68,7 +63,6 @@ Example:
                #interrupt-cells = <3>;
                #address-cells = <1>;
                interrupt-controller;
-               arm,routable-irqs = <160>;
                reg = <0xfff11000 0x1000>,
                      <0xfff10100 0x100>;
        };
index 4139db353d0a9846bd88d0f442988a2d8a2f53b7..a9b28d74d9023ebddc131742f9815ff9f9673dc0 100644 (file)
@@ -9,7 +9,9 @@ inputs.
 Required properties:
 - compatible : Should be "ti,irq-crossbar"
 - reg: Base address and the size of the crossbar registers.
-- ti,max-irqs: Total number of irqs available at the interrupt controller.
+- interrupt-controller: indicates that this block is an interrupt controller.
+- interrupt-parent: the interrupt controller this block is connected to.
+- ti,max-irqs: Total number of irqs available at the parent interrupt controller.
 - ti,max-crossbar-sources: Maximum number of crossbar sources that can be routed.
 - ti,reg-size: Size of a individual register in bytes. Every individual
            register is assumed to be of same size. Valid sizes are 1, 2, 4.
@@ -27,13 +29,13 @@ Optional properties:
   when the interrupt controller irq is unused (when not provided, default is 0)
 
 Examples:
-               crossbar_mpu: @4a020000 {
+               crossbar_mpu: crossbar@4a002a48 {
                        compatible = "ti,irq-crossbar";
                        reg = <0x4a002a48 0x130>;
                        ti,max-irqs = <160>;
                        ti,max-crossbar-sources = <400>;
                        ti,reg-size = <2>;
-                       ti,irqs-reserved = <0 1 2 3 5 6 131 132 139 140>;
+                       ti,irqs-reserved = <0 1 2 3 5 6 131 132>;
                        ti,irqs-skip = <10 133 139 140>;
                };
 
@@ -44,10 +46,6 @@ Documentation/devicetree/bindings/arm/gic.txt for further details.
 
 An interrupt consumer on an SoC using crossbar will use:
        interrupts = <GIC_SPI request_number interrupt_level>
-When the request number is between 0 to that described by
-"ti,max-crossbar-sources", it is assumed to be a crossbar mapping. If the
-request_number is greater than "ti,max-crossbar-sources", then it is mapped as a
-quirky hardware mapping direct to GIC.
 
 Example:
        device_x@0x4a023000 {
@@ -55,9 +53,3 @@ Example:
                interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
                ...
        };
-
-       device_y@0x4a033000 {
-               /* Direct mapped GIC SPI 1 used */
-               interrupts = <GIC_SPI DIRECT_IRQ(1) IRQ_TYPE_LEVEL_HIGH>;
-               ...
-       };
index 67b211381f2bd6d79ad60a042e4086981f4fd322..2d6356d8daf4b3838e601159ae24f8399c0f8d31 100644 (file)
@@ -29,10 +29,27 @@ Properties:
  - clocks : list of phandles and specifiers to all input clocks listed in
                clock-names property.
 
+Optional properties:
+
+Some PMUs are capable of behaving as an interrupt controller (mostly
+to wake up a suspended PMU). In which case, they can have the
+following properties:
+
+- interrupt-controller: indicate that said PMU is an interrupt controller
+
+- #interrupt-cells: must be identical to the that of the parent interrupt
+  controller.
+
+- interrupt-parent: a phandle indicating which interrupt controller
+  this PMU signals interrupts to.
+
 Example :
 pmu_system_controller: system-controller@10040000 {
        compatible = "samsung,exynos5250-pmu", "syscon";
        reg = <0x10040000 0x5000>;
+       interrupt-controller;
+       #interrupt-cells = <3>;
+       interrupt-parent = <&gic>;
        #clock-cells = <1>;
        clock-names = "clkout0", "clkout1", "clkout2", "clkout3",
                        "clkout4", "clkout8", "clkout9";
index 0574a77a0b9f67d9f39ab5599f9acd63c1eaac7f..e1d01df8e3c13cf95a83039e00db4cfbf7d56d78 100644 (file)
@@ -3,29 +3,48 @@ STMicroelectronics STi SATA controller
 This binding describes a SATA device.
 
 Required properties:
- - compatible     : Must be "st,sti-ahci"
+ - compatible     : Must be "st,ahci"
  - reg            : Physical base addresses and length of register sets
  - interrupts     : Interrupt associated with the SATA device
  - interrupt-names :   Associated name must be; "hostc"
- - resets         : The power-down and soft-reset lines of SATA IP
- - reset-names    :   Associated names must be; "pwr-dwn" and "sw-rst"
  - clocks         : The phandle for the clock
  - clock-names    :   Associated name must be; "ahci_clk"
- - phys                   : The phandle for the PHY device
+ - phys                   : The phandle for the PHY port
  - phy-names      :   Associated name must be; "ahci_phy"
 
+Optional properties:
+ - resets         : The power-down, soft-reset and power-reset lines of SATA IP
+ - reset-names    :   Associated names must be; "pwr-dwn", "sw-rst" and "pwr-rst"
+
 Example:
 
+       /* Example for stih416 */
        sata0: sata@fe380000 {
-               compatible      = "st,sti-ahci";
-               reg             = <0xfe380000 0x1000>;
-               interrupts      = <GIC_SPI 157 IRQ_TYPE_NONE>;
-               interrupt-names = "hostc";
-               phys            = <&miphy365x_phy MIPHY_PORT_0 MIPHY_TYPE_SATA>;
-               phy-names       = "ahci_phy";
-               resets          = <&powerdown STIH416_SATA0_POWERDOWN>,
+               compatible      = "st,ahci";
+               reg             = <0xfe380000 0x1000>;
+               interrupts      = <GIC_SPI 157 IRQ_TYPE_NONE>;
+               interrupt-names = "hostc";
+               phys            = <&phy_port0 PHY_TYPE_SATA>;
+               phy-names       = "ahci_phy";
+               resets          = <&powerdown STIH416_SATA0_POWERDOWN>,
                                  <&softreset STIH416_SATA0_SOFTRESET>;
-               reset-names     = "pwr-dwn", "sw-rst";
-               clocks          = <&clk_s_a0_ls CLK_ICN_REG>;
-               clock-names     = "ahci_clk";
+               reset-names     = "pwr-dwn", "sw-rst";
+               clocks          = <&clk_s_a0_ls CLK_ICN_REG>;
+               clock-names     = "ahci_clk";
+       };
+
+       /* Example for stih407 family silicon */
+       sata0: sata@9b20000 {
+               compatible      = "st,ahci";
+               reg             = <0x9b20000 0x1000>;
+               interrupts      = <GIC_SPI 159 IRQ_TYPE_NONE>;
+               interrupt-names = "hostc";
+               phys            = <&phy_port0 PHY_TYPE_SATA>;
+               phy-names       = "ahci_phy";
+               resets          = <&powerdown STIH407_SATA0_POWERDOWN>,
+                                 <&softreset STIH407_SATA0_SOFTRESET>,
+                                 <&softreset STIH407_SATA0_PWR_SOFTRESET>;
+               reset-names     = "pwr-dwn", "sw-rst", "pwr-rst";
+               clocks          = <&clk_s_c0_flexgen CLK_ICN_REG>;
+               clock-names     = "ahci_clk";
        };
index 2dd457a3469af94baa89534c79aaacdf56e2d75e..439a7430fc6827e15b79811b8cfcc176fed205f7 100644 (file)
@@ -2,15 +2,20 @@ Bindings for fan connected to GPIO lines
 
 Required properties:
 - compatible : "gpio-fan"
+
+Optional properties:
 - gpios: Specifies the pins that map to bits in the control value,
   ordered MSB-->LSB.
 - gpio-fan,speed-map: A mapping of possible fan RPM speeds and the
   control value that should be set to achieve them. This array
   must have the RPM values in ascending order.
-
-Optional properties:
 - alarm-gpios: This pin going active indicates something is wrong with
   the fan, and a udev event will be fired.
+- cooling-cells: If used as a cooling device, must be <2>
+  Also see: Documentation/devicetree/bindings/thermal/thermal.txt
+  min and max states are derived from the speed-map of the fan.
+
+Note: At least one the "gpios" or "alarm-gpios" properties must be set.
 
 Examples:
 
@@ -23,3 +28,13 @@ Examples:
                                      6000 2>;
                alarm-gpios = <&gpio1 15 1>;
        };
+       gpio_fan_cool: gpio_fan {
+               compatible = "gpio-fan";
+               gpios = <&gpio2 14 1
+                        &gpio2 13 1>;
+               gpio-fan,speed-map =    <0    0>,
+                                       <3000 1>,
+                                       <6000 2>;
+               alarm-gpios = <&gpio2 15 1>;
+               #cooling-cells = <2>; /* min followed by max */
+       };
index 2dc935b4113d22e4bd0c80f533d3c9caefb7be44..a4e1cbc810c19e43f83a273bdb2f11e334bb5fe0 100644 (file)
@@ -10,6 +10,9 @@ Required properties:
 Recommended properties :
 - interrupts : standard interrupt property.
 - clock-frequency : desired I2C bus clock frequency in Hz.
+- ti,has-pfunc: boolean; if defined, it indicates that SoC supports PFUNC
+       registers. PFUNC registers allow to switch I2C pins to function as
+       GPIOs, so they can by toggled manually.
 
 Example (enbw_cmc board):
        i2c@1c22000 {
diff --git a/Documentation/devicetree/bindings/i2c/i2c-digicolor.txt b/Documentation/devicetree/bindings/i2c/i2c-digicolor.txt
new file mode 100644 (file)
index 0000000..457a098
--- /dev/null
@@ -0,0 +1,25 @@
+Conexant Digicolor I2C controller
+
+Required properties:
+ - compatible: must be "cnxt,cx92755-i2c"
+ - reg: physical address and length of the device registers
+ - interrupts: a single interrupt specifier
+ - clocks: clock for the device
+ - #address-cells: should be <1>
+ - #size-cells: should be <0>
+
+Optional properties:
+- clock-frequency: the desired I2C bus clock frequency in Hz; in
+  absence of this property the default value is used (100 kHz).
+
+Example:
+
+       i2c: i2c@f0000120 {
+               compatible = "cnxt,cx92755-i2c";
+               reg = <0xf0000120 0x10>;
+               interrupts = <28>;
+               clocks = <&main_clk>;
+               clock-frequency = <100000>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
diff --git a/Documentation/devicetree/bindings/i2c/i2c-jz4780.txt b/Documentation/devicetree/bindings/i2c/i2c-jz4780.txt
new file mode 100644 (file)
index 0000000..231e4cc
--- /dev/null
@@ -0,0 +1,35 @@
+* Ingenic JZ4780 I2C Bus controller
+
+Required properties:
+- compatible: should be "ingenic,jz4780-i2c"
+- reg: Should contain the address & size of the I2C controller registers.
+- interrupts: Should specify the interrupt provided by parent.
+- clocks: Should contain a single clock specifier for the JZ4780 I2C clock.
+- clock-frequency: desired I2C bus clock frequency in Hz.
+
+Recommended properties:
+- pinctrl-names: should be "default";
+- pinctrl-0: phandle to pinctrl function
+
+Optional properties:
+- interrupt-parent: Should be the phandle of the interrupt controller that
+  delivers interrupts to the I2C block.
+
+Example
+
+/ {
+       i2c4: i2c4@0x10054000 {
+               compatible = "ingenic,jz4780-i2c";
+               reg = <0x10054000 0x1000>;
+
+               interrupt-parent = <&intc>;
+               interrupts = <56>;
+
+               clocks = <&cgu JZ4780_CLK_SMB4>;
+               clock-frequency = <100000>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pins_i2c4_data>;
+
+       };
+};
+
diff --git a/Documentation/devicetree/bindings/i2c/i2c-xlp9xx.txt b/Documentation/devicetree/bindings/i2c/i2c-xlp9xx.txt
new file mode 100644 (file)
index 0000000..f818ef5
--- /dev/null
@@ -0,0 +1,22 @@
+Device tree configuration for the I2C controller on the XLP9xx/5xx SoC
+
+Required properties:
+- compatible      : should be "netlogic,xlp980-i2c"
+- reg             : bus address start and address range size of device
+- interrupts      : interrupt number
+
+Optional properties:
+- clock-frequency : frequency of bus clock in Hz
+                    Defaults to 100 KHz when the property is not specified
+
+Example:
+
+i2c0: i2c@113100 {
+       compatible = "netlogic,xlp980-i2c";
+       #address-cells = <1>;
+       #size-cells = <0>;
+       reg = <0 0x113100 0x100>;
+       clock-frequency = <400000>;
+       interrupts = <30>;
+       interrupt-parent = <&pic>;
+};
index aaa8325004d23ae6313223594817f392c1a31359..003bd77b4595f515bd35a5ad6f9419f50abf8579 100644 (file)
@@ -89,6 +89,7 @@ ricoh,rv5c386         I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
 ricoh,rv5c387a         I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
 samsung,24ad0xd1       S524AD0XF1 (128K/256K-bit Serial EEPROM for Low Power)
 sii,s35390a            2-wire CMOS real-time clock
+skyworks,sky81452      Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
 st-micro,24c256                i2c serial eeprom  (24cxx)
 stm,m41t00             Serial Access TIMEKEEPER
 stm,m41t62             Serial real-time clock (RTC) with alarm
diff --git a/Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt b/Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt
new file mode 100644 (file)
index 0000000..c07228d
--- /dev/null
@@ -0,0 +1,16 @@
+Dialog Semiconductor DA9150 IIO GPADC bindings
+
+Required properties:
+- compatible: "dlg,da9150-gpadc" for DA9150 IIO GPADC
+- #io-channel-cells: Should be set to <1>
+  (See Documentation/devicetree/bindings/iio/iio-bindings.txt for further info)
+
+For further information on GPADC channels, see device datasheet.
+
+
+Example:
+
+       gpadc: da9150-gpadc {
+               compatible = "dlg,da9150-gpadc";
+               #io-channel-cells = <1>;
+       };
diff --git a/Documentation/devicetree/bindings/iio/adc/mcp320x.txt b/Documentation/devicetree/bindings/iio/adc/mcp320x.txt
new file mode 100644 (file)
index 0000000..b851843
--- /dev/null
@@ -0,0 +1,30 @@
+* Microchip Analog to Digital Converter (ADC)
+
+The node for this driver must be a child node of a SPI controller, hence
+all mandatory properties described in
+
+        Documentation/devicetree/bindings/spi/spi-bus.txt
+
+must be specified.
+
+Required properties:
+       - compatible:   Must be one of the following, depending on the
+                       model:
+                               "mcp3001"
+                               "mcp3002"
+                               "mcp3004"
+                               "mcp3008"
+                               "mcp3201"
+                               "mcp3202"
+                               "mcp3204"
+                               "mcp3208"
+
+
+Examples:
+spi_controller {
+       mcp3x0x@0 {
+               compatible = "mcp3002";
+               reg = <0>;
+               spi-max-frequency = <1000000>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/iio/adc/mcp3422.txt b/Documentation/devicetree/bindings/iio/adc/mcp3422.txt
new file mode 100644 (file)
index 0000000..333139c
--- /dev/null
@@ -0,0 +1,17 @@
+* Microchip mcp3422/3/4/6/7/8 chip family (ADC)
+
+Required properties:
+ - compatible: Should be
+       "microchip,mcp3422" or
+       "microchip,mcp3423" or
+       "microchip,mcp3424" or
+       "microchip,mcp3426" or
+       "microchip,mcp3427" or
+       "microchip,mcp3428"
+ - reg: I2C address for the device
+
+Example:
+adc@0 {
+       compatible = "microchip,mcp3424";
+       reg = <0x68>;
+};
diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc128s052.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc128s052.txt
new file mode 100644 (file)
index 0000000..42ca7de
--- /dev/null
@@ -0,0 +1,18 @@
+* Texas Instruments' ADC128S052 ADC chip
+
+Required properties:
+ - compatible: Should be "ti,adc128s052"
+ - reg: spi chip select number for the device
+ - vref-supply: The regulator supply for ADC reference voltage
+
+Recommended properties:
+ - spi-max-frequency: Definition as per
+               Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Example:
+adc@0 {
+       compatible = "ti,adc128s052";
+       reg = <0>;
+       vref-supply = <&vdd_supply>;
+       spi-max-frequency = <1000000>;
+};
index a7a0a15913ad21727c71f4a40ec5cc7a01044e61..d2aaca97453196cc351fe0f6a2e067cc8403a9b3 100644 (file)
@@ -23,6 +23,7 @@ standard bindings from pinctrl/pinctrl-bindings.txt.
 Valid compatible strings:
 
 Accelerometers:
+- st,lis3lv02dl-accel
 - st,lsm303dlh-accel
 - st,lsm303dlhc-accel
 - st,lis3dh-accel
diff --git a/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
new file mode 100644 (file)
index 0000000..1099fe0
--- /dev/null
@@ -0,0 +1,43 @@
+NVIDIA Legacy Interrupt Controller
+
+All Tegra SoCs contain a legacy interrupt controller that routes
+interrupts to the GIC, and also serves as a wakeup source. It is also
+referred to as "ictlr", hence the name of the binding.
+
+The HW block exposes a number of interrupt controllers, each
+implementing a set of 32 interrupts.
+
+Required properties:
+
+- compatible : should be: "nvidia,tegra<chip>-ictlr". The LIC on
+  subsequent SoCs remained backwards-compatible with Tegra30, so on
+  Tegra generations later than Tegra30 the compatible value should
+  include "nvidia,tegra30-ictlr".      
+- reg : Specifies base physical address and size of the registers.
+  Each controller must be described separately (Tegra20 has 4 of them,
+  whereas Tegra30 and later have 5"  
+- interrupt-controller : Identifies the node as an interrupt controller.
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value must be 3.
+- interrupt-parent : a phandle to the GIC these interrupts are routed
+  to.
+
+Notes:
+
+- Because this HW ultimately routes interrupts to the GIC, the
+  interrupt specifier must be that of the GIC.
+- Only SPIs can use the ictlr as an interrupt parent. SGIs and PPIs
+  are explicitly forbidden.
+
+Example:
+
+       ictlr: interrupt-controller@60004000 {
+               compatible = "nvidia,tegra20-ictlr", "nvidia,tegra-ictlr";
+               reg = <0x60004000 64>,
+                     <0x60004100 64>,
+                     <0x60004200 64>,
+                     <0x60004300 64>;
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               interrupt-parent = <&intc>;
+       };
index 1a88e62228e59631c2c53ea4280d94b346b57d7d..63633bdea7e40ea84aca7954a2d671a5d9163ad8 100644 (file)
@@ -4,7 +4,7 @@ Required properties:
 
 - compatible: has to be "renesas,irqc-<soctype>", "renesas,irqc" as fallback.
   Examples with soctypes are:
-    - "renesas,irqc-r8a73a4" (R-Mobile AP6)
+    - "renesas,irqc-r8a73a4" (R-Mobile APE6)
     - "renesas,irqc-r8a7790" (R-Car H2)
     - "renesas,irqc-r8a7791" (R-Car M2-W)
     - "renesas,irqc-r8a7792" (R-Car V2H)
@@ -12,6 +12,7 @@ Required properties:
     - "renesas,irqc-r8a7794" (R-Car E2)
 - #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in
   interrupts.txt in this directory
+- clocks: Must contain a reference to the functional clock.
 
 Optional properties:
 
@@ -29,4 +30,5 @@ Example:
                             <0 1 IRQ_TYPE_LEVEL_HIGH>,
                             <0 2 IRQ_TYPE_LEVEL_HIGH>,
                             <0 3 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp4_clks R8A7790_CLK_IRQC>;
        };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/st,sti-irq-syscfg.txt b/Documentation/devicetree/bindings/interrupt-controller/st,sti-irq-syscfg.txt
new file mode 100644 (file)
index 0000000..ced6014
--- /dev/null
@@ -0,0 +1,35 @@
+STMicroelectronics STi System Configuration Controlled IRQs
+-----------------------------------------------------------
+
+On STi based systems; External, CTI (Core Sight), PMU (Performance Management),
+and PL310 L2 Cache IRQs are controlled using System Configuration registers.
+This driver is used to unmask them prior to use.
+
+Required properties:
+- compatible   : Should be set to one of:
+                       "st,stih415-irq-syscfg"
+                       "st,stih416-irq-syscfg"
+                       "st,stih407-irq-syscfg"
+                       "st,stid127-irq-syscfg"
+- st,syscfg    : Phandle to Cortex-A9 IRQ system config registers
+- st,irq-device        : Array of IRQs to enable - should be 2 in length
+- st,fiq-device        : Array of FIQs to enable - should be 2 in length
+
+Optional properties:
+- st,invert-ext        : External IRQs can be inverted at will.  This property inverts
+                 these IRQs using bitwise logic.  A number of defines have been
+                 provided for convenience:
+                       ST_IRQ_SYSCFG_EXT_1_INV
+                       ST_IRQ_SYSCFG_EXT_2_INV
+                       ST_IRQ_SYSCFG_EXT_3_INV
+Example:
+
+irq-syscfg {
+       compatible    = "st,stih416-irq-syscfg";
+       st,syscfg     = <&syscfg_cpu>;
+       st,irq-device = <ST_IRQ_SYSCFG_PMU_0>,
+                       <ST_IRQ_SYSCFG_PMU_1>;
+       st,fiq-device = <ST_IRQ_SYSCFG_DISABLED>,
+                       <ST_IRQ_SYSCFG_DISABLED>;
+       st,invert-ext = <(ST_IRQ_SYSCFG_EXT_1_INV | ST_IRQ_SYSCFG_EXT_3_INV)>;
+};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
new file mode 100644 (file)
index 0000000..43effa0
--- /dev/null
@@ -0,0 +1,33 @@
+TI OMAP4 Wake-up Generator
+
+All TI OMAP4/5 (and their derivatives) an interrupt controller that
+routes interrupts to the GIC, and also serves as a wakeup source. It
+is also referred to as "WUGEN-MPU", hence the name of the binding.
+
+Reguired properties:
+
+- compatible : should contain at least "ti,omap4-wugen-mpu" or
+  "ti,omap5-wugen-mpu"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-controller : Identifies the node as an interrupt controller.
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value must be 3.
+- interrupt-parent : a phandle to the GIC these interrupts are routed
+  to.
+
+Notes:
+
+- Because this HW ultimately routes interrupts to the GIC, the
+  interrupt specifier must be that of the GIC.
+- Only SPIs can use the WUGEN as an interrupt parent. SGIs and PPIs
+  are explicitly forbiden.
+
+Example:
+
+       wakeupgen: interrupt-controller@48281000 {
+               compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x48281000 0x1000>;
+               interrupt-parent = <&gic>;
+       };
index 7bd1273f571a40fa46b7c5c0540a4fe7c9370c4a..7665aa95979f0b57d8036c51e3b4a0fa71807d1a 100644 (file)
@@ -8,6 +8,7 @@ Required properties:
   - compatible : One of the following chip-specific strings:
         "wlf,wm5102"
         "wlf,wm5110"
+        "wlf,wm8280"
         "wlf,wm8997"
   - reg : I2C slave address when connected using I2C, chip select number when
     using SPI.
@@ -26,21 +27,27 @@ Required properties:
   - #gpio-cells : Must be 2. The first cell is the pin number and the
     second cell is used to specify optional parameters (currently unused).
 
-  - AVDD-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply (wm5102, wm5110),
-    CPVDD-supply, SPKVDDL-supply (wm5102, wm5110), SPKVDDR-supply (wm5102,
-    wm5110), SPKVDD-supply (wm8997) : Power supplies for the device, as covered
-    in Documentation/devicetree/bindings/regulator/regulator.txt
+  - AVDD-supply, DBVDD1-supply, CPVDD-supply : Power supplies for the device,
+    as covered in Documentation/devicetree/bindings/regulator/regulator.txt
+
+  - DBVDD2-supply, DBVDD3-supply : Additional databus power supplies (wm5102,
+    wm5110, wm8280)
+
+  - SPKVDDL-supply, SPKVDDR-supply : Speaker driver power supplies (wm5102,
+    wm5110, wm8280)
+
+  - SPKVDD-supply : Speaker driver power supply (wm8997)
 
 Optional properties:
 
   - wlf,reset : GPIO specifier for the GPIO controlling /RESET
   - wlf,ldoena : GPIO specifier for the GPIO controlling LDOENA
 
-  - wlf,gpio-defaults : A list of GPIO configuration register values. If
-    absent, no configuration of these registers is performed. If any
-    entry has a value that is out of range for a 16 bit register then
-    the chip default will be used.  If present exactly five values must
-    be specified.
+  - wlf,gpio-defaults : A list of GPIO configuration register values. Defines
+    for the appropriate values can found in <dt-bindings/mfd/arizona.txt>. If
+    absent, no configuration of these registers is performed. If any entry has
+    a value that is out of range for a 16 bit register then the chip default
+    will be used. If present exactly five values must be specified.
 
   - wlf,inmode : A list of INn_MODE register values, where n is the number
     of input signals. Valid values are 0 (Differential), 1 (Single-ended) and
@@ -49,6 +56,12 @@ Optional properties:
     input singals. If values less than the number of input signals, elements
     that has not been specifed are set to 0 by default.
 
+  - wlf,dmic-ref : DMIC reference voltage source for each input, can be
+    selected from either MICVDD or one of the MICBIAS's, defines
+    (ARIZONA_DMIC_xxxx) are provided in <dt-bindings/mfd/arizona.txt>. If
+    present, the number of values should be less than or equal to the
+    number of inputs, unspecified inputs will use the chip default.
+
   - DCVDD-supply, MICVDD-supply : Power supplies, only need to be specified if
     they are being externally supplied. As covered in
     Documentation/devicetree/bindings/regulator/regulator.txt
@@ -73,10 +86,10 @@ codec: wm5102@1a {
        #gpio-cells = <2>;
 
        wlf,gpio-defaults = <
-               0x00000000 /* AIF1TXLRCLK */
-               0xffffffff
-               0xffffffff
-               0xffffffff
-               0xffffffff
+               ARIZONA_GP_FN_TXLRCLK
+               ARIZONA_GP_DEFAULT
+               ARIZONA_GP_DEFAULT
+               ARIZONA_GP_DEFAULT
+               ARIZONA_GP_DEFAULT
        >;
 };
diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
new file mode 100644 (file)
index 0000000..98685f2
--- /dev/null
@@ -0,0 +1,96 @@
+AXP202/AXP209 device tree bindings
+
+The axp20x family current members :
+axp202 (X-Powers)
+axp209 (X-Powers)
+
+Required properties:
+- compatible: "x-powers,axp202" or "x-powers,axp209"
+- reg: The I2C slave address for the AXP chip
+- interrupt-parent: The parent interrupt controller
+- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
+- interrupt-controller: axp20x has its own internal IRQs
+- #interrupt-cells: Should be set to 1
+
+Optional properties:
+- x-powers,dcdc-freq: defines the work frequency of DC-DC in KHz
+                     (range: 750-1875). Default: 1.5MHz
+- <input>-supply: a phandle to the regulator supply node. May be omitted if
+                 inputs are unregulated, such as using the IPSOUT output
+                 from the PMIC.
+
+- regulators: A node that houses a sub-node for each regulator. Regulators
+             not used but preferred to be managed by the OS should be
+             listed as well.
+             See Documentation/devicetree/bindings/regulator/regulator.txt
+             for more information on standard regulator bindings.
+
+Optional properties for DCDC regulators:
+- x-powers,dcdc-workmode: 1 for PWM mode, 0 for AUTO (PWM/PFM) mode
+                         Default: Current hardware setting
+                         The DCDC regulators work in a mixed PWM/PFM mode,
+                         using PFM under light loads and switching to PWM
+                         for heavier loads. Forcing PWM mode trades efficiency
+                         under light loads for lower output noise. This
+                         probably makes sense for HiFi audio related
+                         applications that aren't battery constrained.
+
+
+AXP202/AXP209 regulators, type, and corresponding input supply names:
+
+Regulator        Type            Supply Name             Notes
+---------        ----            -----------             -----
+DCDC2          : DC-DC buck    : vin2-supply
+DCDC3          : DC-DC buck    : vin3-supply
+LDO1           : LDO           : acin-supply           : always on
+LDO2           : LDO           : ldo24in-supply        : shared supply
+LDO3           : LDO           : ldo3in-supply
+LDO4           : LDO           : ldo24in-supply        : shared supply
+LDO5           : LDO           : ldo5in-supply
+
+Example:
+
+axp209: pmic@34 {
+       compatible = "x-powers,axp209";
+       reg = <0x34>;
+       interrupt-parent = <&nmi_intc>;
+       interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+       interrupt-controller;
+       #interrupt-cells = <1>;
+
+       regulators {
+               x-powers,dcdc-freq = <1500>;
+
+               vdd_cpu: dcdc2 {
+                       regulator-always-on;
+                       regulator-min-microvolt = <1000000>;
+                       regulator-max-microvolt = <1450000>;
+                       regulator-name = "vdd-cpu";
+               };
+
+               vdd_int_dll: dcdc3 {
+                       regulator-always-on;
+                       regulator-min-microvolt = <1000000>;
+                       regulator-max-microvolt = <1400000>;
+                       regulator-name = "vdd-int-dll";
+               };
+
+               vdd_rtc: ldo1 {
+                       regulator-always-on;
+                       regulator-min-microvolt = <1200000>;
+                       regulator-max-microvolt = <1400000>;
+                       regulator-name = "vdd-rtc";
+               };
+
+               avcc: ldo2 {
+                       regulator-always-on;
+                       regulator-min-microvolt = <2700000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-name = "avcc";
+               };
+
+               ldo3 {
+                       /* unused but preferred to be managed by OS */
+               };
+       };
+};
diff --git a/Documentation/devicetree/bindings/mfd/da9150.txt b/Documentation/devicetree/bindings/mfd/da9150.txt
new file mode 100644 (file)
index 0000000..d0588ea
--- /dev/null
@@ -0,0 +1,43 @@
+Dialog Semiconductor DA9150 Combined Charger/Fuel-Gauge MFD bindings
+
+DA9150 consists of a group of sub-devices:
+
+Device                  Description
+------                  -----------
+da9150-gpadc           : General Purpose ADC
+da9150-charger         : Battery Charger
+
+======
+
+Required properties:
+- compatible : Should be "dlg,da9150"
+- reg: Specifies the I2C slave address
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+  the IRQs from da9150 are delivered to.
+- interrupts: IRQ line info for da9150 chip.
+- interrupt-controller: da9150 has internal IRQs (own IRQ domain).
+  (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for
+   further information relating to interrupt properties)
+
+Sub-devices:
+- da9150-gpadc: See Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt
+- da9150-charger: See Documentation/devicetree/bindings/power/da9150-charger.txt
+
+
+Example:
+
+       charger_fg: da9150@58 {
+               compatible = "dlg,da9150";
+               reg = <0x58>;
+               interrupt-parent = <&gpio6>;
+               interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+
+               gpadc: da9150-gpadc {
+                       ...
+               };
+
+               da9150-charger {
+                       ...
+               };
+       };
diff --git a/Documentation/devicetree/bindings/mfd/mt6397.txt b/Documentation/devicetree/bindings/mfd/mt6397.txt
new file mode 100644 (file)
index 0000000..15043e6
--- /dev/null
@@ -0,0 +1,70 @@
+MediaTek MT6397 Multifunction Device Driver
+
+MT6397 is a multifunction device with the following sub modules:
+- Regulator
+- RTC
+- Audio codec
+- GPIO
+- Clock
+
+It is interfaced to host controller using SPI interface by a proprietary hardware
+called PMIC wrapper or pwrap. MT6397 MFD is a child device of pwrap.
+See the following for pwarp node definitions:
+Documentation/devicetree/bindings/soc/pwrap.txt
+
+This document describes the binding for MFD device and its sub module.
+
+Required properties:
+compatible: "mediatek,mt6397"
+
+Optional subnodes:
+
+- rtc
+       Required properties:
+               - compatible: "mediatek,mt6397-rtc"
+- regulators
+       Required properties:
+               - compatible: "mediatek,mt6397-regulator"
+       see Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
+- codec
+       Required properties:
+               - compatible: "mediatek,mt6397-codec"
+- clk
+       Required properties:
+               - compatible: "mediatek,mt6397-clk"
+
+Example:
+       pwrap: pwrap@1000f000 {
+               compatible = "mediatek,mt8135-pwrap";
+
+               ...
+
+               pmic {
+                       compatible = "mediatek,mt6397";
+
+                       codec: mt6397codec {
+                               compatible = "mediatek,mt6397-codec";
+                       };
+
+                       regulators {
+                               compatible = "mediatek,mt6397-regulator";
+
+                               mt6397_vpca15_reg: buck_vpca15 {
+                                       regulator-compatible = "buck_vpca15";
+                                       regulator-name = "vpca15";
+                                       regulator-min-microvolt = <850000>;
+                                       regulator-max-microvolt = <1400000>;
+                                       regulator-ramp-delay = <12500>;
+                                       regulator-always-on;
+                               };
+
+                               mt6397_vgp4_reg: ldo_vgp4 {
+                                       regulator-compatible = "ldo_vgp4";
+                                       regulator-name = "vgp4";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <3300000>;
+                                       regulator-enable-ramp-delay = <218>;
+                               };
+                       };
+               };
+       };
index 7182b8857f57f39889a3afaec5b2366bc6f40050..6ac06c1b9aec8908095c0b2fc22af1882334293c 100644 (file)
@@ -15,10 +15,21 @@ each. A function can consume one or more of these fixed-size register regions.
 
 Required properties:
 - compatible:      Should contain one of:
-                     "qcom,pm8941"
-                     "qcom,pm8841"
-                     "qcom,pma8084"
-                     or generalized "qcom,spmi-pmic".
+                   "qcom,pm8941",
+                   "qcom,pm8841",
+                   "qcom,pma8084",
+                   "qcom,pm8019",
+                   "qcom,pm8226",
+                   "qcom,pm8110",
+                   "qcom,pma8084",
+                   "qcom,pmi8962",
+                   "qcom,pmd9635",
+                   "qcom,pm8994",
+                   "qcom,pmi8994",
+                   "qcom,pm8916",
+                   "qcom,pm8004",
+                   "qcom,pm8909",
+                   or generalized "qcom,spmi-pmic".
 - reg:             Specifies the SPMI USID slave address for this device.
                    For more information see:
                    Documentation/devicetree/bindings/spmi/spmi.txt
index 85e31980017aa9e0730410b020130c0b941c0755..5e97a9593ad71bbca2c1edf3199cbf53fb7ff45f 100644 (file)
@@ -12,6 +12,7 @@ frequencies.
                    "qcom,rpm-apq8064"
                    "qcom,rpm-msm8660"
                    "qcom,rpm-msm8960"
+                   "qcom,rpm-ipq8064"
 
 - reg:
        Usage: required
@@ -31,16 +32,6 @@ frequencies.
        Value type: <string-array>
        Definition: must be the three strings "ack", "err" and "wakeup", in order
 
-- #address-cells:
-       Usage: required
-       Value type: <u32>
-       Definition: must be 1
-
-- #size-cells:
-       Usage: required
-       Value type: <u32>
-       Definition: must be 0
-
 - qcom,ipc:
        Usage: required
        Value type: <prop-encoded-array>
@@ -52,6 +43,188 @@ frequencies.
                    - u32 representing the ipc bit within the register
 
 
+= SUBNODES
+
+The RPM exposes resources to its subnodes. The below bindings specify the set
+of valid subnodes that can operate on these resources.
+
+== Regulators
+
+Regulator nodes are identified by their compatible:
+
+- compatible:
+       Usage: required
+       Value type: <string>
+       Definition: must be one of:
+                   "qcom,rpm-pm8058-regulators"
+                   "qcom,rpm-pm8901-regulators"
+                   "qcom,rpm-pm8921-regulators"
+
+- vdd_l0_l1_lvs-supply:
+- vdd_l2_l11_l12-supply:
+- vdd_l3_l4_l5-supply:
+- vdd_l6_l7-supply:
+- vdd_l8-supply:
+- vdd_l9-supply:
+- vdd_l10-supply:
+- vdd_l13_l16-supply:
+- vdd_l14_l15-supply:
+- vdd_l17_l18-supply:
+- vdd_l19_l20-supply:
+- vdd_l21-supply:
+- vdd_l22-supply:
+- vdd_l23_l24_l25-supply:
+- vdd_ncp-supply:
+- vdd_s0-supply:
+- vdd_s1-supply:
+- vdd_s2-supply:
+- vdd_s3-supply:
+- vdd_s4-supply:
+       Usage: optional (pm8058 only)
+       Value type: <phandle>
+       Definition: reference to regulator supplying the input pin, as
+                   described in the data sheet
+
+- lvs0_in-supply:
+- lvs1_in-supply:
+- lvs2_in-supply:
+- lvs3_in-supply:
+- mvs_in-supply:
+- vdd_l0-supply:
+- vdd_l1-supply:
+- vdd_l2-supply:
+- vdd_l3-supply:
+- vdd_l4-supply:
+- vdd_l5-supply:
+- vdd_l6-supply:
+- vdd_s0-supply:
+- vdd_s1-supply:
+- vdd_s2-supply:
+- vdd_s3-supply:
+- vdd_s4-supply:
+       Usage: optional (pm8901 only)
+       Value type: <phandle>
+       Definition: reference to regulator supplying the input pin, as
+                   described in the data sheet
+
+- vdd_l1_l2_l12_l18-supply:
+- vdd_l3_l15_l17-supply:
+- vdd_l4_l14-supply:
+- vdd_l5_l8_l16-supply:
+- vdd_l6_l7-supply:
+- vdd_l9_l11-supply:
+- vdd_l10_l22-supply:
+- vdd_l21_l23_l29-supply:
+- vdd_l24-supply:
+- vdd_l25-supply:
+- vdd_l26-supply:
+- vdd_l27-supply:
+- vdd_l28-supply:
+- vdd_ncp-supply:
+- vdd_s1-supply:
+- vdd_s2-supply:
+- vdd_s4-supply:
+- vdd_s5-supply:
+- vdd_s6-supply:
+- vdd_s7-supply:
+- vdd_s8-supply:
+- vin_5vs-supply:
+- vin_lvs1_3_6-supply:
+- vin_lvs2-supply:
+- vin_lvs4_5_7-supply:
+       Usage: optional (pm8921 only)
+       Value type: <phandle>
+       Definition: reference to regulator supplying the input pin, as
+                   described in the data sheet
+
+The regulator node houses sub-nodes for each regulator within the device. Each
+sub-node is identified using the node's name, with valid values listed for each
+of the pmics below.
+
+pm8058:
+       l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15,
+       l16, l17, l18, l19, l20, l21, l22, l23, l24, l25, s0, s1, s2, s3, s4,
+       lvs0, lvs1, ncp
+
+pm8901:
+       l0, l1, l2, l3, l4, l5, l6, s0, s1, s2, s3, s4, lvs0, lvs1, lvs2, lvs3,
+       mvs
+
+pm8921:
+       s1, s2, s3, s4, s7, s8, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11,
+       l12, l14, l15, l16, l17, l18, l21, l22, l23, l24, l25, l26, l27, l28,
+       l29, lvs1, lvs2, lvs3, lvs4, lvs5, lvs6, lvs7, usb-switch, hdmi-switch,
+       ncp
+
+The content of each sub-node is defined by the standard binding for regulators -
+see regulator.txt - with additional custom properties described below:
+
+=== Switch-mode Power Supply regulator custom properties
+
+- bias-pull-down:
+       Usage: optional
+       Value type: <empty>
+       Definition: enable pull down of the regulator when inactive
+
+- qcom,switch-mode-frequency:
+       Usage: required
+       Value type: <u32>
+       Definition: Frequency (Hz) of the switch-mode power supply;
+                   must be one of:
+                   19200000, 9600000, 6400000, 4800000, 3840000, 3200000,
+                   2740000, 2400000, 2130000, 1920000, 1750000, 1600000,
+                   1480000, 1370000, 1280000, 1200000
+
+- qcom,force-mode:
+       Usage: optional (default if no other qcom,force-mode is specified)
+       Value type: <u32>
+       Defintion: indicates that the regulator should be forced to a
+                  particular mode, valid values are:
+                  QCOM_RPM_FORCE_MODE_NONE - do not force any mode
+                  QCOM_RPM_FORCE_MODE_LPM - force into low power mode
+                  QCOM_RPM_FORCE_MODE_HPM - force into high power mode
+                  QCOM_RPM_FORCE_MODE_AUTO - allow regulator to automatically
+                                             select its own mode based on
+                                             realtime current draw, only for:
+                                             pm8921 smps and ftsmps
+
+- qcom,power-mode-hysteretic:
+       Usage: optional
+       Value type: <empty>
+       Definition: select that the power supply should operate in hysteretic
+                   mode, instead of the default pwm mode
+
+=== Low-dropout regulator custom properties
+
+- bias-pull-down:
+       Usage: optional
+       Value type: <empty>
+       Definition: enable pull down of the regulator when inactive
+
+- qcom,force-mode:
+       Usage: optional
+       Value type: <u32>
+       Defintion: indicates that the regulator should not be forced to any
+                  particular mode, valid values are:
+                  QCOM_RPM_FORCE_MODE_NONE - do not force any mode
+                  QCOM_RPM_FORCE_MODE_LPM - force into low power mode
+                  QCOM_RPM_FORCE_MODE_HPM - force into high power mode
+                  QCOM_RPM_FORCE_MODE_BYPASS - set regulator to use bypass
+                                               mode, i.e.  to act as a switch
+                                               and not regulate, only for:
+                                               pm8921 pldo, nldo and nldo1200
+
+=== Negative Charge Pump custom properties
+
+- qcom,switch-mode-frequency:
+       Usage: required
+       Value type: <u32>
+       Definition: Frequency (Hz) of the swith mode power supply;
+                   must be one of:
+                   19200000, 9600000, 6400000, 4800000, 3840000, 3200000,
+                   2740000, 2400000, 2130000, 1920000, 1750000, 1600000,
+                   1480000, 1370000, 1280000, 1200000
+
 = EXAMPLE
 
        #include <dt-bindings/mfd/qcom-rpm.h>
@@ -64,7 +237,28 @@ frequencies.
                interrupts = <0 19 0>, <0 21 0>, <0 22 0>;
                interrupt-names = "ack", "err", "wakeup";
 
-               #address-cells = <1>;
-               #size-cells = <0>;
+               regulators {
+                       compatible = "qcom,rpm-pm8921-regulators";
+                       vdd_l1_l2_l12_l18-supply = <&pm8921_s4>;
+
+                       s1 {
+                               regulator-min-microvolt = <1225000>;
+                               regulator-max-microvolt = <1225000>;
+
+                               bias-pull-down;
+
+                               qcom,switch-mode-frequency = <3200000>;
+                       };
+
+                       pm8921_s4: s4 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+
+                               qcom,switch-mode-frequency = <1600000>;
+                               bias-pull-down;
+
+                               qcom,force-mode = <QCOM_RPM_FORCE_MODE_AUTO>;
+                       };
+               };
        };
 
diff --git a/Documentation/devicetree/bindings/mfd/sky81452.txt b/Documentation/devicetree/bindings/mfd/sky81452.txt
new file mode 100644 (file)
index 0000000..3518179
--- /dev/null
@@ -0,0 +1,35 @@
+SKY81452 bindings
+
+Required properties:
+- compatible   : Must be "skyworks,sky81452"
+- reg          : I2C slave address
+
+Required child nodes:
+- backlight    : container node for backlight following the binding
+               in video/backlight/sky81452-backlight.txt
+- regulator    : container node for regulators following the binding
+               in regulator/sky81452-regulator.txt
+
+Example:
+
+       sky81452@2c {
+               compatible = "skyworks,sky81452";
+               reg = <0x2c>;
+
+               backlight {
+                       compatible = "skyworks,sky81452-backlight";
+                       name = "pwm-backlight";
+                       led-sources = <0 1 2 3 6>;
+                       skyworks,ignore-pwm;
+                       skyworks,phase-shift;
+                       skyworks,current-limit = <2300>;
+               };
+
+               regulator {
+                       lout {
+                               regulator-name = "sky81452-lout";
+                               regulator-min-microvolt = <4500000>;
+                               regulator-max-microvolt = <8000000>;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt b/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt
new file mode 100644 (file)
index 0000000..72cc9cc
--- /dev/null
@@ -0,0 +1,23 @@
+Broadcom IPROC SDHCI controller
+
+This file documents differences between the core properties described
+by mmc.txt and the properties that represent the IPROC SDHCI controller.
+
+Required properties:
+- compatible : Should be "brcm,sdhci-iproc-cygnus".
+- clocks : The clock feeding the SDHCI controller.
+
+Optional properties:
+  - sdhci,auto-cmd12: specifies that controller should use auto CMD12.
+
+Example:
+
+sdhci0: sdhci@0x18041000 {
+       compatible = "brcm,sdhci-iproc-cygnus";
+       reg = <0x18041000 0x100>;
+       interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+       clocks = <&lcpll0_clks BCM_CYGNUS_LCPLL0_SDIO_CLK>;
+       bus-width = <4>;
+       sdhci,auto-cmd12;
+       no-1-8-v;
+};
index ee4fc0576c7d866b318eda917066e76e920b4f53..aad98442788bc386366b019a6166e6145b2f0017 100644 (file)
@@ -36,6 +36,8 @@ Required Properties:
   in transmit mode and CIU clock phase shift value in receive mode for double
   data rate mode operation. Refer notes below for the order of the cells and the
   valid values.
+* samsung,dw-mshc-hs400-timing: Specifies the value of CIU TX and RX clock phase
+  shift value for hs400 mode operation.
 
   Notes for the sdr-timing and ddr-timing values:
 
@@ -50,6 +52,9 @@ Required Properties:
       - if CIU clock divider value is 0 (that is divide by 1), both tx and rx
         phase shift clocks should be 0.
 
+* samsung,read-strobe-delay: RCLK (Data strobe) delay to control HS400 mode
+  (Latency value for delay line in Read path)
+
 Required properties for a slot (Deprecated - Recommend to use one slot per host):
 
 * gpios: specifies a list of gpios used for command, clock and data bus. The
@@ -82,5 +87,7 @@ Example:
                samsung,dw-mshc-ciu-div = <3>;
                samsung,dw-mshc-sdr-timing = <2 3>;
                samsung,dw-mshc-ddr-timing = <1 2>;
+               samsung,dw-mshc-hs400-timing = <0 2>;
+               samsung,read-strobe-delay = <90>;
                bus-width = <8>;
        };
index 9046ba06c47ab63570f99769455dcfeeea020e10..415c5575cbf7a1394439f3ba807e0f8547167231 100644 (file)
@@ -17,6 +17,10 @@ Optional properties:
   to select a proper data sampling window in case the clock quality is not good
   due to signal path is too long on the board. Please refer to eSDHC/uSDHC
   chapter, DLL (Delay Line) section in RM for details.
+- voltage-ranges : Specify the voltage range in case there are software
+  transparent level shifters on the outputs of the controller. Two cells are
+  required, first cell specifies minimum slot voltage (mV), second cell
+  specifies maximum slot voltage (mV). Several ranges could be specified.
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/mmc/mmc-card.txt b/Documentation/devicetree/bindings/mmc/mmc-card.txt
new file mode 100644 (file)
index 0000000..a70fcd6
--- /dev/null
@@ -0,0 +1,31 @@
+mmc-card / eMMC bindings
+------------------------
+
+This documents describes the devicetree bindings for a mmc-host controller
+child node describing a mmc-card / an eMMC, see "Use of Function subnodes"
+in mmc.txt
+
+Required properties:
+-compatible : Must be "mmc-card"
+-reg        : Must be <0>
+
+Optional properties:
+-broken-hpi : Use this to indicate that the mmc-card has a broken hpi
+              implementation, and that hpi should not be used
+
+Example:
+
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins_a>;
+       vmmc-supply = <&reg_vcc3v3>;
+       bus-width = <8>;
+       non-removable;
+       status = "okay";
+
+       mmccard: mmccard@0 {
+               reg = <0>;
+               compatible = "mmc-card";
+               broken-hpi;
+       };
+};
index 7527db447a35b1ed92c79611852f1f365b8900e3..18d950df2749cbf3964f52f6718ff14d21c88348 100644 (file)
@@ -5,20 +5,62 @@ Documentation/devicetree/bindings/mmc/mmc.txt and the properties
 used by the sdhci-st driver.
 
 Required properties:
-- compatible :  Must be "st,sdhci"
-- clock-names : Should be "mmc"
-                See: Documentation/devicetree/bindings/resource-names.txt
-- clocks :      Phandle of the clock used by the sdhci controler
-                See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+- compatible:          Must be "st,sdhci" and it can be compatible to "st,sdhci-stih407"
+                       to set the internal glue logic used for configuring the MMC
+                       subsystem (mmcss) inside the FlashSS (available in STiH407 SoC
+                       family).
+
+- clock-names:         Should be "mmc".
+                       See: Documentation/devicetree/bindings/resource-names.txt
+- clocks:              Phandle to the clock.
+                       See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+- interrupts:          One mmc interrupt should be described here.
+- interrupt-names:     Should be "mmcirq".
+
+- pinctrl-names:       A pinctrl state names "default" must be defined.
+- pinctrl-0:           Phandle referencing pin configuration of the sd/emmc controller.
+                       See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+
+- reg:                 This must provide the host controller base address and it can also
+                       contain the FlashSS Top register for TX/RX delay used by the driver
+                       to configure DLL inside the flashSS, if so reg-names must also be
+                       specified.
 
 Optional properties:
-- non-removable: non-removable slot
-                 See: Documentation/devicetree/bindings/mmc/mmc.txt
-- bus-width: Number of data lines
-                 See: Documentation/devicetree/bindings/mmc/mmc.txt
+- reg-names:           Should be "mmc" and "top-mmc-delay". "top-mmc-delay" is optional
+                       for eMMC on stih407 family silicon to configure DLL inside FlashSS.
+
+- non-removable:       Non-removable slot. Also used for configuring mmcss in STiH407 SoC
+                       family.
+                       See:  Documentation/devicetree/bindings/mmc/mmc.txt.
+
+- bus-width:           Number of data lines.
+                       See:  Documentation/devicetree/bindings/mmc/mmc.txt.
+
+- max-frequency:       Can be 200MHz, 100Mz or 50MHz (default) and used for
+                       configuring the CCONFIG3 in the mmcss.
+                       See:  Documentation/devicetree/bindings/mmc/mmc.txt.
+
+- resets:              Phandle and reset specifier pair to softreset line of HC IP.
+                       See: Documentation/devicetree/bindings/reset/reset.txt
+
+- vqmmc-supply:                Phandle to the regulator dt node, mentioned as the vcc/vdd
+                       supply in eMMC/SD specs.
+
+- sd-uhs--sdr50:       To enable the SDR50 in the mmcss.
+                       See:  Documentation/devicetree/bindings/mmc/mmc.txt.
+
+- sd-uhs-sdr104:       To enable the SDR104 in the mmcss.
+                       See:  Documentation/devicetree/bindings/mmc/mmc.txt.
+
+- sd-uhs-ddr50:                To enable the DDR50 in the mmcss.
+                       See:  Documentation/devicetree/bindings/mmc/mmc.txt.
 
 Example:
 
+/* Example stih416e eMMC configuration */
+
 mmc0: sdhci@fe81e000 {
        compatible      = "st,sdhci";
        status          = "disabled";
@@ -29,5 +71,43 @@ mmc0: sdhci@fe81e000 {
        pinctrl-0       = <&pinctrl_mmc0>;
        clock-names     = "mmc";
        clocks          = <&clk_s_a1_ls 1>;
-       bus-width       = <8>
+       bus-width       = <8>
+
+/* Example SD stih407 family configuration */
+
+mmc1: sdhci@09080000 {
+       compatible      = "st,sdhci-stih407", "st,sdhci";
+       status          = "disabled";
+       reg             = <0x09080000 0x7ff>;
+       reg-names       = "mmc";
+       interrupts      = <GIC_SPI 90 IRQ_TYPE_NONE>;
+       interrupt-names = "mmcirq";
+       pinctrl-names   = "default";
+       pinctrl-0       = <&pinctrl_sd1>;
+       clock-names     = "mmc";
+       clocks          = <&clk_s_c0_flexgen CLK_MMC_1>;
+       resets          = <&softreset STIH407_MMC1_SOFTRESET>;
+       bus-width       = <4>;
+};
+
+/* Example eMMC stih407 family configuration */
+
+mmc0: sdhci@09060000 {
+       compatible      = "st,sdhci-stih407", "st,sdhci";
+       status          = "disabled";
+       reg             = <0x09060000 0x7ff>, <0x9061008 0x20>;
+       reg-names       = "mmc", "top-mmc-delay";
+       interrupts      = <GIC_SPI 92 IRQ_TYPE_NONE>;
+       interrupt-names = "mmcirq";
+       pinctrl-names   = "default";
+       pinctrl-0       = <&pinctrl_mmc0>;
+       clock-names     = "mmc";
+       clocks          = <&clk_s_c0_flexgen CLK_MMC_0>;
+       vqmmc-supply    = <&vmmc_reg>;
+       max-frequency   = <200000000>;
+       bus-width       = <8>;
+       non-removable;
+       sd-uhs-sdr50;
+       sd-uhs-sdr104;
+       sd-uhs-ddr50;
 };
diff --git a/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt b/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt
new file mode 100644 (file)
index 0000000..f7ce50e
--- /dev/null
@@ -0,0 +1,63 @@
+* Broadcom iProc PCIe controller with the platform bus interface
+
+Required properties:
+- compatible: Must be "brcm,iproc-pcie"
+- reg: base address and length of the PCIe controller I/O register space
+- #interrupt-cells: set to <1>
+- interrupt-map-mask and interrupt-map, standard PCI properties to define the
+  mapping of the PCIe interface to interrupt numbers
+- linux,pci-domain: PCI domain ID. Should be unique for each host controller
+- bus-range: PCI bus numbers covered
+- #address-cells: set to <3>
+- #size-cells: set to <2>
+- device_type: set to "pci"
+- ranges: ranges for the PCI memory and I/O regions
+
+Optional properties:
+- phys: phandle of the PCIe PHY device
+- phy-names: must be "pcie-phy"
+
+Example:
+       pcie0: pcie@18012000 {
+               compatible = "brcm,iproc-pcie";
+               reg = <0x18012000 0x1000>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 0 0>;
+               interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_NONE>;
+
+               linux,pci-domain = <0>;
+
+               bus-range = <0x00 0xff>;
+
+               #address-cells = <3>;
+               #size-cells = <2>;
+               device_type = "pci";
+               ranges = <0x81000000 0 0          0x28000000 0 0x00010000
+                         0x82000000 0 0x20000000 0x20000000 0 0x04000000>;
+
+               phys = <&phy 0 5>;
+               phy-names = "pcie-phy";
+       };
+
+       pcie1: pcie@18013000 {
+               compatible = "brcm,iproc-pcie";
+               reg = <0x18013000 0x1000>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 0 0>;
+               interrupt-map = <0 0 0 0 &gic GIC_SPI 106 IRQ_TYPE_NONE>;
+
+               linux,pci-domain = <1>;
+
+               bus-range = <0x00 0xff>;
+
+               #address-cells = <3>;
+               #size-cells = <2>;
+               device_type = "pci";
+               ranges = <0x81000000 0 0          0x48000000 0 0x00010000
+                         0x82000000 0 0x40000000 0x40000000 0 0x04000000>;
+
+               phys = <&phy 1 6>;
+               phy-names = "pcie-phy";
+       };
diff --git a/Documentation/devicetree/bindings/phy/dm816x-phy.txt b/Documentation/devicetree/bindings/phy/dm816x-phy.txt
new file mode 100644 (file)
index 0000000..2fe3d11
--- /dev/null
@@ -0,0 +1,24 @@
+Device tree binding documentation for am816x USB PHY
+=========================
+
+Required properties:
+- compatible : should be "ti,dm816x-usb-phy"
+- reg : offset and length of the PHY register set.
+- reg-names : name for the phy registers
+- clocks : phandle to the clock
+- clock-names : name of the clock
+- syscon: phandle for the syscon node to access misc registers
+- #phy-cells : from the generic PHY bindings, must be 1
+- syscon: phandle for the syscon node to access misc registers
+
+Example:
+
+usb_phy0: usb-phy@20 {
+       compatible = "ti,dm8168-usb-phy";
+       reg = <0x20 0x8>;
+       reg-names = "phy";
+       clocks = <&main_fapll 6>;
+       clock-names = "refclk";
+       #phy-cells = <0>;
+       syscon = <&scm_conf>;
+};
index 9802d5d911aa677d656bda23e4b4f4cafd89ea84..8772900e056a06cd71579a2e6cf005993e38a472 100644 (file)
@@ -20,8 +20,8 @@ Required nodes        :  A sub-node is required for each channel the controller
 Required properties (port (child) node):
 - #phy-cells   : Should be 1 (See second example)
                  Cell after port phandle is device type from:
-                       - MIPHY_TYPE_SATA
-                       - MIPHY_TYPE_PCI
+                       - PHY_TYPE_SATA
+                       - PHY_TYPE_PCI
 - reg          : Address and length of register sets for each device in
                  "reg-names"
 - reg-names     : The names of the register addresses corresponding to the
@@ -68,10 +68,10 @@ property, containing a phandle to the phy port node and a device type.
 
 Example:
 
-#include <dt-bindings/phy/phy-miphy365x.h>
+#include <dt-bindings/phy/phy.h>
 
        sata0: sata@fe380000 {
                ...
-               phys      = <&phy_port0 MIPHY_TYPE_SATA>;
+               phys      = <&phy_port0 PHY_TYPE_SATA>;
                ...
        };
index 91e38cfe1f8fb22b6d23d25079f59f77f5541690..60c6f2a633e02d7b7179ec45c7b31bcda378f802 100644 (file)
@@ -128,6 +128,7 @@ Required properties:
 - compatible : Should be set to one of the following supported values:
        - "samsung,exynos5250-usbdrd-phy" - for exynos5250 SoC,
        - "samsung,exynos5420-usbdrd-phy" - for exynos5420 SoC.
+       - "samsung,exynos5433-usbdrd-phy" - for exynos5433 SoC.
        - "samsung,exynos7-usbdrd-phy" - for exynos7 SoC.
 - reg : Register offset and length of USB DRD PHY register set;
 - clocks: Clock IDs array as required by the controller
@@ -139,7 +140,7 @@ Required properties:
               PHY operations, associated by phy name. It is used to
               determine bit values for clock settings register.
               For Exynos5420 this is given as 'sclk_usbphy30' in CMU.
-       - optional clocks: Exynos7 SoC has now following additional
+       - optional clocks: Exynos5433 & Exynos7 SoC has now following additional
                           gate clocks available:
                           - phy_pipe: for PIPE3 phy
                           - phy_utmi: for UTMI+ phy
diff --git a/Documentation/devicetree/bindings/phy/sun9i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun9i-usb-phy.txt
new file mode 100644 (file)
index 0000000..1cca85c
--- /dev/null
@@ -0,0 +1,38 @@
+Allwinner sun9i USB PHY
+-----------------------
+
+Required properties:
+- compatible : should be one of
+  * allwinner,sun9i-a80-usb-phy
+- reg : a list of offset + length pairs
+- #phy-cells : from the generic phy bindings, must be 0
+- phy_type : "hsic" for HSIC usage;
+            other values or absence of this property indicates normal USB
+- clocks : phandle + clock specifier for the phy clocks
+- clock-names : depending on the "phy_type" property,
+  * "phy" for normal USB
+  * "hsic_480M", "hsic_12M" for HSIC
+- resets : a list of phandle + reset specifier pairs
+- reset-names : depending on the "phy_type" property,
+  * "phy" for normal USB
+  * "hsic" for HSIC
+
+Optional Properties:
+- phy-supply : from the generic phy bindings, a phandle to a regulator that
+              provides power to VBUS.
+
+It is recommended to list all clocks and resets available.
+The driver will only use those matching the phy_type.
+
+Example:
+       usbphy1: phy@00a01800 {
+               compatible = "allwinner,sun9i-a80-usb-phy";
+               reg = <0x00a01800 0x4>;
+               clocks = <&usb_phy_clk 2>, <&usb_phy_clk 10>,
+                      <&usb_phy_clk 3>;
+               clock-names = "hsic_480M", "hsic_12M", "phy";
+               resets = <&usb_phy_clk 18>, <&usb_phy_clk 19>;
+               reset-names = "hsic", "phy";
+               status = "disabled";
+               #phy-cells = <0>;
+       };
diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,cygnus-gpio.txt b/Documentation/devicetree/bindings/pinctrl/brcm,cygnus-gpio.txt
new file mode 100644 (file)
index 0000000..6540ca5
--- /dev/null
@@ -0,0 +1,98 @@
+Broadcom Cygnus GPIO/PINCONF Controller
+
+Required properties:
+
+- compatible:
+    Must be "brcm,cygnus-ccm-gpio", "brcm,cygnus-asiu-gpio", or
+    "brcm,cygnus-crmu-gpio"
+
+- reg:
+    Define the base and range of the I/O address space that contains the Cygnus
+GPIO/PINCONF controller registers
+
+- #gpio-cells:
+    Must be two. The first cell is the GPIO pin number (within the
+controller's pin space) and the second cell is used for the following:
+    bit[0]: polarity (0 for active high and 1 for active low)
+
+- gpio-controller:
+    Specifies that the node is a GPIO controller
+
+Optional properties:
+
+- interrupts:
+    Interrupt ID
+
+- interrupt-controller:
+    Specifies that the node is an interrupt controller
+
+- pinmux:
+    Specifies the phandle to the IOMUX device, where pins can be individually
+muxed to GPIO
+
+Supported generic PINCONF properties in child nodes:
+
+- pins:
+    The list of pins (within the controller's own pin space) that properties
+in the node apply to. Pin names are "gpio-<pin>"
+
+- bias-disable:
+    Disable pin bias
+
+- bias-pull-up:
+    Enable internal pull up resistor
+
+- bias-pull-down:
+    Enable internal pull down resistor
+
+- drive-strength:
+    Valid drive strength values include 2, 4, 6, 8, 10, 12, 14, 16 (mA)
+
+Example:
+       gpio_ccm: gpio@1800a000 {
+               compatible = "brcm,cygnus-ccm-gpio";
+               reg = <0x1800a000 0x50>,
+                     <0x0301d164 0x20>;
+               #gpio-cells = <2>;
+               gpio-controller;
+               interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-controller;
+
+               touch_pins: touch_pins {
+                       pwr: pwr {
+                               pins = "gpio-0";
+                               drive-strength = <16>;
+                       };
+
+                       event: event {
+                               pins = "gpio-1";
+                               bias-pull-up;
+                       };
+               };
+       };
+
+       gpio_asiu: gpio@180a5000 {
+               compatible = "brcm,cygnus-asiu-gpio";
+               reg = <0x180a5000 0x668>;
+               #gpio-cells = <2>;
+               gpio-controller;
+               interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-controller;
+       };
+
+       /*
+        * Touchscreen that uses the CCM GPIO 0 and 1
+        */
+       tsc {
+               ...
+               ...
+               gpio-pwr = <&gpio_ccm 0 0>;
+               gpio-event = <&gpio_ccm 1 0>;
+       };
+
+       /* Bluetooth that uses the ASIU GPIO 5, with polarity inverted */
+       bluetooth {
+               ...
+               ...
+               bcm,rfkill-bank-sel = <&gpio_asiu 5 1>
+       }
diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinmux.txt
new file mode 100644 (file)
index 0000000..3600d5c
--- /dev/null
@@ -0,0 +1,132 @@
+Broadcom Cygnus IOMUX Controller
+
+The Cygnus IOMUX controller supports group based mux configuration. In
+addition, certain pins can be muxed to GPIO function individually.
+
+Required properties:
+
+- compatible:
+    Must be "brcm,cygnus-pinmux"
+
+- reg:
+    Define the base and range of the I/O address space that contains the Cygnus
+IOMUX registers
+
+Properties in subnodes:
+
+- function:
+    The mux function to select
+
+- groups:
+    The list of groups to select with a given function
+
+For more details, refer to
+Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+
+For example:
+
+       pinmux: pinmux@0x0301d0c8 {
+               compatible = "brcm,cygnus-pinmux";
+               reg = <0x0301d0c8 0x1b0>;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2s0_default>;
+
+               i2s0_default: i2s0_default {
+                       mux {
+                               function = "i2s0";
+                               groups = "i2s0_0_grp", "i2s0_1_grp";
+                       };
+               };
+       };
+
+List of supported functions and groups in Cygnus:
+
+"i2s0": "i2s0_0_grp", "i2s0_1_grp"
+
+"i2s1": "i2s1_0_grp", "i2s1_1_grp"
+
+"i2s2": "i2s2_0_grp", "i2s2_1_grp", "i2s2_2_grp", "i2s2_3_grp", "i2s2_4_grp"
+
+"spdif": "spdif_grp"
+
+"pwm0": "pwm0_grp"
+
+"pwm1": "pwm1_grp"
+
+"pwm2": "pwm2_grp"
+
+"pwm3": "pwm3_grp"
+
+"pwm4": "pwm4_grp"
+
+"pwm5": "pwm5_grp"
+
+"key": "key0_grp", "key1_grp", "key2_grp", "key3_grp", "key4_grp", "key5_grp",
+"key6_grp", "key7_grp", "key8_grp", "key9_grp", "key10_grp", "key11_grp",
+"key12_grp", "key13_grp", "key14_grp", "key15_grp"
+
+"audio_dte": "audio_dte0_grp", "audio_dte1_grp", "audio_dte2_grp", "audio_dte3_grp"
+
+"smart_card0": "smart_card0_grp", "smart_card0_fcb_grp"
+
+"smart_card1": "smart_card1_grp", "smart_card1_fcb_grp"
+
+"spi0": "spi0_grp"
+
+"spi1": "spi1_grp"
+
+"spi2": "spi2_grp"
+
+"spi3": "spi3_grp"
+
+"spi4": "spi4_0_grp", "spi4_1_grp"
+
+"spi5": "spi5_grp"
+
+"sw_led0": "sw_led0_0_grp", "sw_led0_1_grp"
+
+"sw_led1": "sw_led1_grp"
+
+"sw_led2": "sw_led2_0_grp", "sw_led2_1_grp"
+
+"d1w": "d1w_grp"
+
+"lcd": "lcd_grp"
+
+"sram": "sram_0_grp", "sram_1_grp"
+
+"uart0": "uart0_grp"
+
+"uart1": "uart1_grp", "uart1_dte_grp"
+
+"uart2": "uart2_grp"
+
+"uart3": "uart3_grp"
+
+"uart4": "uart4_grp"
+
+"qspi": "qspi_0_grp", "qspi_1_grp"
+
+"nand": "nand_grp"
+
+"sdio0": "sdio0_grp", "sdio0_cd_grp", "sdio0_mmc_grp"
+
+"sdio1": "sdio1_data_0_grp", "sdio1_data_1_grp", "sdio1_cd_grp",
+"sdio1_led_grp", "sdio1_mmc_grp"
+
+"can0": "can0_grp"
+
+"can1": "can1_grp"
+
+"cam": "cam_led_grp", "cam_0_grp", "cam_1_grp"
+
+"bsc1": "bsc1_grp"
+
+"pcie_clkreq": "pcie_clkreq_grp"
+
+"usb0_oc": "usb0_oc_grp"
+
+"usb1_oc": "usb1_oc_grp"
+
+"usb2_oc": "usb2_oc_grp"
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-39x-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-39x-pinctrl.txt
new file mode 100644 (file)
index 0000000..5b1a9dc
--- /dev/null
@@ -0,0 +1,78 @@
+* Marvell Armada 39x SoC pinctrl driver for mpp
+
+Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
+part and usage.
+
+Required properties:
+- compatible: "marvell,88f6920-pinctrl", "marvell,88f6928-pinctrl"
+  depending on the specific variant of the SoC being used.
+- reg: register specifier of MPP registers
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+name    pins    functions
+================================================================================
+mpp0   0       gpio, ua0(rxd)
+mpp1   1       gpio, ua0(txd)
+mpp2   2       gpio, i2c0(sck)
+mpp3   3       gpio, i2c0(sda)
+mpp4   4       gpio, ua1(txd), ua0(rts), smi(mdc)
+mpp5   5       gpio, ua1(rxd), ua0(cts), smi(mdio)
+mpp6   6       gpio, dev(cs3), xsmi(mdio)
+mpp7   7       gpio, dev(ad9), xsmi(mdc)
+mpp8   8       gpio, dev(ad10), ptp(trig)
+mpp9   9       gpio, dev(ad11), ptp(clk)
+mpp10  10      gpio, dev(ad12), ptp(event)
+mpp11  11      gpio, dev(ad13), led(clk)
+mpp12  12      gpio, pcie0(rstout), dev(ad14), led(stb)
+mpp13  13      gpio, dev(ad15), led(data)
+mpp14  14      gpio, m(vtt), dev(wen1), ua1(txd)
+mpp15  15      gpio, pcie0(rstout), spi0(mosi), i2c1(sck)
+mpp16  16      gpio, m(decc), spi0(miso), i2c1(sda)
+mpp17  17      gpio, ua1(rxd), spi0(sck), smi(mdio)
+mpp18  18      gpio, ua1(txd), spi0(cs0), i2c2(sck)
+mpp19  19      gpio, sata1(present) [1], ua0(cts), ua1(rxd), i2c2(sda)
+mpp20  20      gpio, sata0(present) [1], ua0(rts), ua1(txd), smi(mdc)
+mpp21  21      gpio, spi0(cs1), sata0(present) [1], sd(cmd), dev(bootcs), ge(rxd0)
+mpp22  22      gpio, spi0(mosi), dev(ad0)
+mpp23  23      gpio, spi0(sck), dev(ad2)
+mpp24  24      gpio, spi0(miso), ua0(cts), ua1(rxd), sd(d4), dev(readyn)
+mpp25  25      gpio, spi0(cs0), ua0(rts), ua1(txd), sd(d5), dev(cs0)
+mpp26  26      gpio, spi0(cs2), i2c1(sck), sd(d6), dev(cs1)
+mpp27  27      gpio, spi0(cs3), i2c1(sda), sd(d7), dev(cs2), ge(txclkout)
+mpp28  28      gpio, sd(clk), dev(ad5), ge(txd0)
+mpp29  29      gpio, dev(ale0), ge(txd1)
+mpp30  30      gpio, dev(oen), ge(txd2)
+mpp31  31      gpio, dev(ale1), ge(txd3)
+mpp32  32      gpio, dev(wen0), ge(txctl)
+mpp33  33      gpio, m(decc), dev(ad3)
+mpp34  34      gpio, dev(ad1)
+mpp35  35      gpio, ref(clk), dev(a1)
+mpp36  36      gpio, dev(a0)
+mpp37  37      gpio, sd(d3), dev(ad8), ge(rxclk)
+mpp38  38      gpio, ref(clk), sd(d0), dev(ad4), ge(rxd1)
+mpp39  39      gpio, i2c1(sck), ua0(cts), sd(d1), dev(a2), ge(rxd2)
+mpp40  40      gpio, i2c1(sda), ua0(rts), sd(d2), dev(ad6), ge(rxd3)
+mpp41  41      gpio, ua1(rxd), ua0(cts), spi1(cs3), dev(burstn), nd(rbn0), ge(rxctl)
+mpp42  42      gpio, ua1(txd), ua0(rts), dev(ad7)
+mpp43  43      gpio, pcie0(clkreq), m(vtt), m(decc), spi1(cs2), dev(clkout), nd(rbn1)
+mpp44  44      gpio, sata0(present) [1], sata1(present) [1], led(clk)
+mpp45  45      gpio, ref(clk), pcie0(rstout), ua1(rxd)
+mpp46  46      gpio, ref(clk), pcie0(rstout), ua1(txd), led(stb)
+mpp47  47      gpio, sata0(present) [1], sata1(present) [1], led(data)
+mpp48  48      gpio, sata0(present) [1], m(vtt), tdm(pclk) [1], audio(mclk) [1], sd(d4), pcie0(clkreq), ua1(txd)
+mpp49  49      gpio, tdm(fsync) [1], audio(lrclk) [1], sd(d5), ua2(rxd)
+mpp50  50      gpio, pcie0(rstout), tdm(drx) [1], audio(extclk) [1], sd(cmd), ua2(rxd)
+mpp51  51      gpio, tdm(dtx) [1], audio(sdo) [1], m(decc), ua2(txd)
+mpp52  52      gpio, pcie0(rstout), tdm(intn) [1], audio(sdi) [1], sd(d6), i2c3(sck)
+mpp53  53      gpio, sata1(present) [1], sata0(present) [1], tdm(rstn) [1], audio(bclk) [1], sd(d7), i2c3(sda)
+mpp54  54      gpio, sata0(present) [1], sata1(present) [1], pcie0(rstout), sd(d3), ua3(txd)
+mpp55  55      gpio, ua1(cts), spi1(cs1), sd(d0), ua1(rxd), ua3(rxd)
+mpp56  56      gpio, ua1(rts), m(decc), spi1(mosi), ua1(txd)
+mpp57  57      gpio, spi1(sck), sd(clk), ua1(txd)
+mpp58  58      gpio, i2c1(sck), pcie2(clkreq), spi1(miso), sd(d1), ua1(rxd)
+mpp59  59      gpio, pcie0(rstout), i2c1(sda), spi1(cs0), sd(d2)
+
+[1]: only available on 88F6928
index 17e7240c6998791d81a3683bad27e26f2d00e5c2..3f6a524cc5ffce28dddb0f2d9e0717098ec6a5a9 100644 (file)
@@ -1,7 +1,7 @@
 == Amlogic Meson pinmux controller ==
 
 Required properties for the root node:
- - compatible: "amlogic,meson8-pinctrl"
+ - compatible: "amlogic,meson8-pinctrl" or "amlogic,meson8b-pinctrl"
  - reg: address and size of registers controlling irq functionality
 
 === GPIO sub-nodes ===
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.txt
new file mode 100644 (file)
index 0000000..a62d82d
--- /dev/null
@@ -0,0 +1,166 @@
+NVIDIA Tegra210 pinmux controller
+
+Required properties:
+- compatible: "nvidia,tegra210-pinmux"
+- reg: Should contain a list of base address and size pairs for:
+  - first entry: The APB_MISC_GP_*_PADCTRL registers (pad control)
+  - second entry: The PINMUX_AUX_* registers (pinmux)
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+Tegra's pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, tristate, drive strength, etc.
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function or tristate parameter. For this
+reason, even seemingly boolean values are actually tristates in this binding:
+unspecified, off, or on. Unspecified is represented as an absent property,
+and off/on are represented as integer values 0 and 1.
+
+See the TRM to determine which properties and values apply to each pin/group.
+Macro values for property values are defined in
+include/dt-binding/pinctrl/pinctrl-tegra.h.
+
+Required subnode-properties:
+- nvidia,pins : An array of strings. Each string contains the name of a pin or
+    group. Valid values for these names are listed below.
+
+Optional subnode-properties:
+- nvidia,function: A string containing the name of the function to mux to the
+    pin or group.
+- nvidia,pull: Integer, representing the pull-down/up to apply to the pin.
+    0: none, 1: down, 2: up.
+- nvidia,tristate: Integer.
+    0: drive, 1: tristate.
+- nvidia,enable-input: Integer. Enable the pin's input path.
+    enable :TEGRA_PIN_ENABLE0 and
+    disable or output only: TEGRA_PIN_DISABLE.
+- nvidia,open-drain: Integer.
+    enable: TEGRA_PIN_ENABLE.
+    disable: TEGRA_PIN_DISABLE.
+- nvidia,lock: Integer. Lock the pin configuration against further changes
+    until reset.
+    enable: TEGRA_PIN_ENABLE.
+    disable: TEGRA_PIN_DISABLE.
+- nvidia,io-hv: Integer. Select high-voltage receivers.
+    normal: TEGRA_PIN_DISABLE
+    high: TEGRA_PIN_ENABLE
+- nvidia,high-speed-mode: Integer. Enable high speed mode the pins.
+    normal: TEGRA_PIN_DISABLE
+    high: TEGRA_PIN_ENABLE
+- nvidia,schmitt: Integer. Enables Schmitt Trigger on the input.
+    normal: TEGRA_PIN_DISABLE
+    high: TEGRA_PIN_ENABLE
+- nvidia,drive-type: Integer. Valid range 0...3.
+- nvidia,pull-down-strength: Integer. Controls drive strength. 0 is weakest.
+    The range of valid values depends on the pingroup. See "CAL_DRVDN" in the
+    Tegra TRM.
+- nvidia,pull-up-strength: Integer. Controls drive strength. 0 is weakest.
+    The range of valid values depends on the pingroup. See "CAL_DRVUP" in the
+    Tegra TRM.
+- nvidia,slew-rate-rising: Integer. Controls rising signal slew rate. 0 is
+    fastest. The range of valid values depends on the pingroup. See
+    "DRVDN_SLWR" in the Tegra TRM.
+- nvidia,slew-rate-falling: Integer. Controls falling signal slew rate. 0 is
+    fastest. The range of valid values depends on the pingroup. See
+    "DRVUP_SLWF" in the Tegra TRM.
+
+Valid values for pin and group names (nvidia,pin) are:
+
+  Mux groups:
+
+    These correspond to Tegra PINMUX_AUX_* (pinmux) registers. Any property
+    that exists in those registers may be set for the following pin names.
+
+    In Tegra210, many pins also have a dedicated APB_MISC_GP_*_PADCTRL
+    register. Where that is true, and property that exists in that register
+    may also be set on the following pin names.
+
+    als_prox_int_px3, ap_ready_pv5, ap_wake_bt_ph3, ap_wake_nfc_ph7,
+    aud_mclk_pbb0, batt_bcl, bt_rst_ph4, bt_wake_ap_ph5, button_home_py1,
+    button_power_on_px5, button_slide_sw_py0, button_vol_down_px7,
+    button_vol_up_px6, cam1_mclk_ps0, cam1_pwdn_ps7, cam1_strobe_pt1,
+    cam2_mclk_ps1, cam2_pwdn_pt0, cam_af_en_ps5, cam_flash_en_ps6,
+    cam_i2c_scl_ps2, cam_i2c_sda_ps3, cam_rst_ps4cam_rst_ps4, clk_32k_in,
+    clk_32k_out_py5, clk_req, core_pwr_req, cpu_pwr_req, dap1_din_pb1,
+    dap1_dout_pb2, dap1_fs_pb0, dap1_sclk_pb3, dap2_din_paa2, dap2_dout_paa3,
+    dap2_fs_paa0, dap2_sclk_paa1, dap4_din_pj5, dap4_dout_pj6, dap4_fs_pj4,
+    dap4_sclk_pj7, dmic1_clk_pe0, dmic1_dat_pe1, dmic2_clk_pe2, dmic2_dat_pe3,
+    dmic3_clk_pe4, dmic3_dat_pe5, dp_hpd0_pcc6, dvfs_clk_pbb2, dvfs_pwm_pbb1,
+    gen1_i2c_scl_pj1, gen1_i2c_sda_pj0, gen2_i2c_scl_pj2, gen2_i2c_sda_pj3,
+    gen3_i2c_scl_pf0, gen3_i2c_sda_pf1, gpio_x1_aud_pbb3, gpio_x3_aud_pbb4,
+    gps_en_pi2, gps_rst_pi3, hdmi_cec_pcc0, hdmi_int_dp_hpd_pcc1, jtag_rtck,
+    lcd_bl_en_pv1, lcd_bl_pwm_pv0, lcd_gpio1_pv3, lcd_gpio2_pv4, lcd_rst_pv2,
+    lcd_te_py2, modem_wake_ap_px0, motion_int_px2, nfc_en_pi0, nfc_int_pi1,
+    pa6, pcc7, pe6, pe7, pex_l0_clkreq_n_pa1, pex_l0_rst_n_pa0,
+    pex_l1_clkreq_n_pa4, pex_l1_rst_n_pa3, pex_wake_n_pa2, ph6, pk0, pk1, pk2,
+    pk3, pk4, pk5, pk6, pk7, pl0, pl1, pwr_i2c_scl_py3, pwr_i2c_sda_py4,
+    pwr_int_n, pz0, pz1, pz2, pz3, pz4, pz5, qspi_cs_n_pee1, qspi_io0_pee2,
+    qspi_io1_pee3, qspi_io2_pee4, qspi_io3_pee5, qspi_sck_pee0,
+    sata_led_active_pa5, sdmmc1_clk_pm0, sdmmc1_cmd_pm1, sdmmc1_dat0_pm5,
+    sdmmc1_dat1_pm4, sdmmc1_dat2_pm3, sdmmc1_dat3_pm2, sdmmc3_clk_pp0,
+    sdmmc3_cmd_pp1, sdmmc3_dat0_pp5, sdmmc3_dat1_pp4, sdmmc3_dat2_pp3,
+    sdmmc3_dat3_pp2, shutdown, spdif_in_pcc3, spdif_out_pcc2, spi1_cs0_pc3,
+    spi1_cs1_pc4, spi1_miso_pc1, spi1_mosi_pc0, spi1_sck_pc2, spi2_cs0_pb7,
+    spi2_cs1_pdd0, spi2_miso_pb5, spi2_mosi_pb4, spi2_sck_pb6, spi4_cs0_pc6,
+    spi4_miso_pd0, spi4_mosi_pc7, spi4_sck_pc5, temp_alert_px4, touch_clk_pv7,
+    touch_int_px1, touch_rst_pv6, uart1_cts_pu3, uart1_rts_pu2, uart1_rx_pu1,
+    uart1_tx_pu0, uart2_cts_pg3, uart2_rts_pg2, uart2_rx_pg1, uart2_tx_pg0,
+    uart3_cts_pd4, uart3_rts_pd3, uart3_rx_pd2, uart3_tx_pd1, uart4_cts_pi7,
+    uart4_rts_pi6, uart4_rx_pi5, uart4_tx_pi4, usb_vbus_en0_pcc4,
+    usb_vbus_en1_pcc5, wifi_en_ph0, wifi_rst_ph1, wifi_wake_ap_ph2
+
+  Drive groups:
+
+    These correspond to the Tegra APB_MISC_GP_*_PADCTRL (pad control)
+    registers. Note that where one of these registers controls a single pin
+    for which a PINMUX_AUX_* exists, see the list above for the pin name to
+    use when configuring the pinmux.
+
+    pa6, pcc7, pe6, pe7, ph6, pk0, pk1, pk2, pk3, pk4, pk5, pk6, pk7, pl0, pl1,
+    pz0, pz1, pz2, pz3, pz4, pz5, sdmmc1, sdmmc2, sdmmc3, sdmmc4
+
+Valid values for nvidia,functions are:
+
+    aud, bcl, blink, ccla, cec, cldvfs, clk, core, cpu, displaya, displayb,
+    dmic1, dmic2, dmic3, dp, dtv, extperiph3, i2c1, i2c2, i2c3, i2cpmu, i2cvi,
+    i2s1, i2s2, i2s3, i2s4a, i2s4b, i2s5a, i2s5b, iqc0, iqc1, jtag, pe, pe0,
+    pe1, pmi, pwm0, pwm1, pwm2, pwm3, qspi, rsvd0, rsvd1, rsvd2, rsvd3, sata,
+    sdmmc1, sdmmc3, shutdown, soc, sor0, sor1, spdif, spi1, spi2, spi3, spi4,
+    sys, touch, uart, uarta, uartb, uartc, uartd, usb, vgp1, vgp2, vgp3, vgp4,
+    vgp5, vgp6, vimclk, vimclk2
+
+Example:
+
+       pinmux: pinmux@70000800 {
+               compatible = "nvidia,tegra210-pinmux";
+               reg = <0x0 0x700008d4 0x0 0x2a8>, /* Pad control registers */
+                     <0x0 0x70003000 0x0 0x1000>; /* Mux registers */
+
+               pinctrl-names = "boot";
+               pinctrl-0 = <&state_boot>;
+
+               state_boot: pinmux {
+                       gen1_i2c_scl_pj1 {
+                               nvidia,pins = "gen1_i2c_scl_pj1",
+                               nvidia,function = "i2c1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                               nvidia,io-hv = <TEGRA_PIN_ENABLE>;
+                       };
+               };
+       };
+};
index 47d84b6ee91b96a07218afd9fd84ea509334baca..b73c96d24f59247da9d0ecbe51225e6f54271619 100644 (file)
@@ -38,7 +38,7 @@ property exists to define the pin configuration. Each state may also be
 assigned a name. When names are used, another property exists to map from
 those names to the integer IDs.
 
-Each client device's own binding determines the set of states the must be
+Each client device's own binding determines the set of states that must be
 defined in its device tree node, and whether to define the set of state
 IDs that must be provided, or whether to define the set of state names that
 must be provided.
@@ -133,16 +133,27 @@ pin multiplexing nodes:
 
 function               - the mux function to select
 groups                 - the list of groups to select with this function
+                         (either this or "pins" must be specified)
+pins                   - the list of pins to select with this function (either
+                         this or "groups" must be specified)
 
 Example:
 
 state_0_node_a {
-       function = "uart0";
-       groups = "u0rxtx", "u0rtscts";
+       uart0 {
+               function = "uart0";
+               groups = "u0rxtx", "u0rtscts";
+       };
 };
 state_1_node_a {
-       function = "spi0";
-       groups = "spi0pins";
+       spi0 {
+               function = "spi0";
+               groups = "spi0pins";
+       };
+};
+state_2_node_a {
+       function = "i2c0";
+       pins = "mfio29", "mfio30";
 };
 
 == Generic pin configuration node content ==
@@ -188,16 +199,22 @@ slew-rate         - set the slew rate
 For example:
 
 state_0_node_a {
-       pins = "GPIO0_AJ5", "GPIO2_AH4"; /* CTS+RXD */
-       bias-pull-up;
+       cts_rxd {
+               pins = "GPIO0_AJ5", "GPIO2_AH4"; /* CTS+RXD */
+               bias-pull-up;
+       };
 };
 state_1_node_a {
-       pins = "GPIO1_AJ3", "GPIO3_AH3"; /* RTS+TXD */
-       output-high;
+       rts_txd {
+               pins = "GPIO1_AJ3", "GPIO3_AH3"; /* RTS+TXD */
+               output-high;
+       };
 };
 state_2_node_a {
-       group = "foo-group";
-       bias-pull-up;
+       foo {
+               group = "foo-group";
+               bias-pull-up;
+       };
 };
 
 Some of the generic properties take arguments. For those that do, the
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
new file mode 100644 (file)
index 0000000..5868a0f
--- /dev/null
@@ -0,0 +1,145 @@
+* Mediatek MT65XX Pin Controller
+
+The Mediatek's Pin controller is used to control SoC pins.
+
+Required properties:
+- compatible: value should be either of the following.
+    (a) "mediatek,mt8135-pinctrl", compatible with mt8135 pinctrl.
+- mediatek,pctl-regmap: Should be a phandle of the syscfg node.
+- pins-are-numbered: Specify the subnodes are using numbered pinmux to
+  specify pins.
+- gpio-controller : Marks the device node as a gpio controller.
+- #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO
+  binding is used, the amount of cells must be specified as 2. See the below
+  mentioned gpio binding representation for description of particular cells.
+
+       Eg: <&pio 6 0>
+       <[phandle of the gpio controller node]
+       [line number within the gpio controller]
+       [flags]>
+
+       Values for gpio specifier:
+       - Line number: is a value between 0 to 202.
+       - Flags:  bit field of flags, as defined in <dt-bindings/gpio/gpio.h>.
+            Only the following flags are supported:
+            0 - GPIO_ACTIVE_HIGH
+            1 - GPIO_ACTIVE_LOW
+- reg: physicall address base for EINT registers
+- interrupt-controller: Marks the device node as an interrupt controller
+- #interrupt-cells: Should be two.
+- interrupts : The interrupt outputs from the controller.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices.
+
+Subnode format
+A pinctrl node should contain at least one subnodes representing the
+pinctrl groups available on the machine. Each subnode will list the
+pins it needs, and how they should be configured, with regard to muxer
+configuration, pullups, drive strength, input enable/disable and input schmitt.
+
+    node {
+       pinmux = <PIN_NUMBER_PINMUX>;
+       GENERIC_PINCONFIG;
+    };
+
+Required properties:
+- pinmux: integer array, represents gpio pin number and mux setting.
+    Supported pin number and mux varies for different SoCs, and are defined
+    as macros in boot/dts/<soc>-pinfunc.h directly.
+
+Optional properties:
+- GENERIC_PINCONFIG: is the generic pinconfig options to use, bias-disable,
+    bias-pull-down, bias-pull-up, input-enable, input-disable, output-low, output-high,
+    input-schmitt-enable, input-schmitt-disable and drive-strength are valid.
+
+    Some special pins have extra pull up strength, there are R0 and R1 pull-up
+    resistors available, but for user, it's only need to set R1R0 as 00, 01, 10 or 11.
+    So when config bias-pull-up, it support arguments for those special pins.
+    Some macros have been defined for this usage, such as MTK_PUPD_SET_R1R0_00.
+    See dt-bindings/pinctrl/mt65xx.h.
+
+    When config drive-strength, it can support some arguments, such as
+    MTK_DRIVE_4mA, MTK_DRIVE_6mA, etc. See dt-bindings/pinctrl/mt65xx.h.
+
+Examples:
+
+#include "mt8135-pinfunc.h"
+
+...
+{
+       syscfg_pctl_a: syscfg_pctl_a@10005000 {
+               compatible = "mediatek,mt8135-pctl-a-syscfg", "syscon";
+               reg = <0 0x10005000 0 0x1000>;
+       };
+
+       syscfg_pctl_b: syscfg_pctl_b@1020C020 {
+               compatible = "mediatek,mt8135-pctl-b-syscfg", "syscon";
+               reg = <0 0x1020C020 0 0x1000>;
+       };
+
+       pinctrl@01c20800 {
+               compatible = "mediatek,mt8135-pinctrl";
+               reg = <0 0x1000B000 0 0x1000>;
+               mediatek,pctl-regmap = <&syscfg_pctl_a &syscfg_pctl_b>;
+               pins-are-numbered;
+               gpio-controller;
+               #gpio-cells = <2>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+
+               i2c0_pins_a: i2c0@0 {
+                       pins1 {
+                               pinmux = <MT8135_PIN_100_SDA0__FUNC_SDA0>,
+                                        <MT8135_PIN_101_SCL0__FUNC_SCL0>;
+                               bias-disable;
+                       };
+               };
+
+               i2c1_pins_a: i2c1@0 {
+                       pins {
+                               pinmux = <MT8135_PIN_195_SDA1__FUNC_SDA1>,
+                                        <MT8135_PIN_196_SCL1__FUNC_SCL1>;
+                               bias-pull-up = <55>;
+                       };
+               };
+
+               i2c2_pins_a: i2c2@0 {
+                       pins1 {
+                               pinmux = <MT8135_PIN_193_SDA2__FUNC_SDA2>;
+                               bias-pull-down;
+                       };
+
+                       pins2 {
+                               pinmux = <MT8135_PIN_49_WATCHDOG__FUNC_GPIO49>;
+                               bias-pull-up;
+                       };
+               };
+
+               i2c3_pins_a: i2c3@0 {
+                       pins1 {
+                               pinmux = <MT8135_PIN_40_DAC_CLK__FUNC_GPIO40>,
+                                        <MT8135_PIN_41_DAC_WS__FUNC_GPIO41>;
+                               bias-pull-up = <55>;
+                       };
+
+                       pins2 {
+                               pinmux = <MT8135_PIN_35_SCL3__FUNC_SCL3>,
+                                        <MT8135_PIN_36_SDA3__FUNC_SDA3>;
+                               output-low;
+                               bias-pull-up = <55>;
+                       };
+
+                       pins3 {
+                               pinmux = <MT8135_PIN_57_JTCK__FUNC_GPIO57>,
+                                        <MT8135_PIN_60_JTDI__FUNC_JTDI>;
+                               drive-strength = <32>;
+                       };
+               };
+
+               ...
+       }
+};
index 7ed08048516a9c9815913602fdd1c252689c1315..1ae63c0acd40b2609e173380d6785d7174248525 100644 (file)
@@ -10,6 +10,7 @@ PMIC's from Qualcomm.
                    "qcom,pm8018-gpio"
                    "qcom,pm8038-gpio"
                    "qcom,pm8058-gpio"
+                   "qcom,pm8916-gpio"
                    "qcom,pm8917-gpio"
                    "qcom,pm8921-gpio"
                    "qcom,pm8941-gpio"
@@ -74,6 +75,7 @@ to specify in a pin configuration subnode:
                    gpio1-gpio6 for pm8018
                    gpio1-gpio12 for pm8038
                    gpio1-gpio40 for pm8058
+                   gpio1-gpio4 for pm8916
                    gpio1-gpio38 for pm8917
                    gpio1-gpio44 for pm8921
                    gpio1-gpio36 for pm8941
index 854774b194ed7064bb0c29705fd6f9fcf2af2c34..ed19991aad35e2e5556b39f632c0607e5cdde5b9 100644 (file)
@@ -8,6 +8,7 @@ of PMIC's from Qualcomm.
        Value type: <string>
        Definition: Should contain one of:
                    "qcom,pm8841-mpp",
+                   "qcom,pm8916-mpp",
                    "qcom,pm8941-mpp",
                    "qcom,pma8084-mpp",
 
@@ -67,6 +68,7 @@ to specify in a pin configuration subnode:
        Definition: List of MPP pins affected by the properties specified in
                    this subnode.  Valid pins are:
                    mpp1-mpp4 for pm8841
+                   mpp1-mpp4 for pm8916
                    mpp1-mpp8 for pm8941
                    mpp1-mpp4 for pma8084
 
diff --git a/Documentation/devicetree/bindings/power/da9150-charger.txt b/Documentation/devicetree/bindings/power/da9150-charger.txt
new file mode 100644 (file)
index 0000000..f390666
--- /dev/null
@@ -0,0 +1,26 @@
+Dialog Semiconductor DA9150 Charger Power Supply bindings
+
+Required properties:
+- compatible: "dlg,da9150-charger" for DA9150 Charger Power Supply
+
+Optional properties:
+- io-channels: List of phandle and IIO specifier pairs
+- io-channel-names: List of channel names used by charger
+      ["CHAN_IBUS", "CHAN_VBUS", "CHAN_TJUNC", "CHAN_VBAT"]
+  (See Documentation/devicetree/bindings/iio/iio-bindings.txt for further info)
+
+
+Example:
+
+       da9150-charger {
+               compatible = "dlg,da9150-charger";
+
+               io-channels = <&gpadc 0>,
+                             <&gpadc 2>,
+                             <&gpadc 8>,
+                             <&gpadc 5>;
+               io-channel-names = "CHAN_IBUS",
+                                  "CHAN_VBUS",
+                                  "CHAN_TJUNC",
+                                  "CHAN_VBAT";
+       };
diff --git a/Documentation/devicetree/bindings/power/reset/syscon-poweroff.txt b/Documentation/devicetree/bindings/power/reset/syscon-poweroff.txt
new file mode 100644 (file)
index 0000000..1e2546f
--- /dev/null
@@ -0,0 +1,23 @@
+Generic SYSCON mapped register poweroff driver
+
+This is a generic poweroff driver using syscon to map the poweroff register.
+The poweroff is generally performed with a write to the poweroff register
+defined by the register map pointed by syscon reference plus the offset
+with the mask defined in the poweroff node.
+
+Required properties:
+- compatible: should contain "syscon-poweroff"
+- regmap: this is phandle to the register map node
+- offset: offset in the register map for the poweroff register (in bytes)
+- mask: the poweroff value written to the poweroff register (32 bit access)
+
+Default will be little endian mode, 32 bit access only.
+
+Examples:
+
+       poweroff {
+          compatible = "syscon-poweroff";
+          regmap = <&regmapnode>;
+          offset = <0x0>;
+          mask = <0x7a>;
+       };
index dad6358074ac51bbd4d73b102650d038053b9cf3..e91485d1124175b807c1930b87a3d1237fe42a33 100644 (file)
@@ -2,13 +2,35 @@ ACT88xx regulators
 -------------------
 
 Required properties:
-- compatible: "active-semi,act8846" or "active-semi,act8865"
+- compatible: "active-semi,act8846" or "active-semi,act8865" or "active-semi,act8600"
 - reg: I2C slave address
 
 Optional properties:
 - system-power-controller: Telling whether or not this pmic is controlling
   the system power. See Documentation/devicetree/bindings/power/power-controller.txt .
 
+Optional input supply properties:
+- for act8600:
+  - vp1-supply: The input supply for DCDC_REG1
+  - vp2-supply: The input supply for DCDC_REG2
+  - vp3-supply: The input supply for DCDC_REG3
+  - inl-supply: The input supply for LDO_REG5, LDO_REG6, LDO_REG7 and LDO_REG8
+  SUDCDC_REG4, LDO_REG9 and LDO_REG10 do not have separate supplies.
+- for act8846:
+  - vp1-supply: The input supply for REG1
+  - vp2-supply: The input supply for REG2
+  - vp3-supply: The input supply for REG3
+  - vp4-supply: The input supply for REG4
+  - inl1-supply: The input supply for REG5, REG6 and REG7
+  - inl2-supply: The input supply for REG8 and LDO_REG9
+  - inl3-supply: The input supply for REG10, REG11 and REG12
+- for act8865:
+  - vp1-supply: The input supply for DCDC_REG1
+  - vp2-supply: The input supply for DCDC_REG2
+  - vp3-supply: The input supply for DCDC_REG3
+  - inl45-supply: The input supply for LDO_REG1 and LDO_REG2
+  - inl67-supply: The input supply for LDO_REG3 and LDO_REG4
+
 Any standard regulator properties can be used to configure the single regulator.
 
 The valid names for regulators are:
@@ -16,6 +38,9 @@ The valid names for regulators are:
        REG1, REG2, REG3, REG4, REG5, REG6, REG7, REG8, REG9, REG10, REG11, REG12
        - for act8865:
        DCDC_REG1, DCDC_REG2, DCDC_REG3, LDO_REG1, LDO_REG2, LDO_REG3, LDO_REG4.
+       - for act8600:
+       DCDC_REG1, DCDC_REG2, DCDC_REG3, SUDCDC_REG4, LDO_REG5, LDO_REG6, LDO_REG7,
+       LDO_REG8, LDO_REG9, LDO_REG10,
 
 Example:
 --------
index aad527b357a0473cc4527868843a8de1d5385965..523341a0e1131a3e7b51878632b4040fb3a428c9 100644 (file)
@@ -2,11 +2,21 @@
   (CSPI/eCSPI) for i.MX
 
 Required properties:
-- compatible : Should be "fsl,<soc>-cspi" or "fsl,<soc>-ecspi"
+- compatible :
+  - "fsl,imx1-cspi" for SPI compatible with the one integrated on i.MX1
+  - "fsl,imx21-cspi" for SPI compatible with the one integrated on i.MX21
+  - "fsl,imx27-cspi" for SPI compatible with the one integrated on i.MX27
+  - "fsl,imx31-cspi" for SPI compatible with the one integrated on i.MX31
+  - "fsl,imx35-cspi" for SPI compatible with the one integrated on i.MX35
+  - "fsl,imx51-ecspi" for SPI compatible with the one integrated on i.MX51
 - reg : Offset and length of the register set for the device
 - interrupts : Should contain CSPI/eCSPI interrupt
 - fsl,spi-num-chipselects : Contains the number of the chipselect
 - cs-gpios : Specifies the gpio pins to be used for chipselects.
+- clocks : Clock specifiers for both ipg and per clocks.
+- clock-names : Clock names should include both "ipg" and "per"
+See the clock consumer binding,
+       Documentation/devicetree/bindings/clock/clock-bindings.txt
 - dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
                Documentation/devicetree/bindings/dma/dma.txt
 - dma-names: DMA request names should include "tx" and "rx" if present.
index e2c88df2cc15ae75677b0562d3a1a9bf4d102bd9..5c090771c016cd22f38ebeaa4a4158ee7da20ccf 100644 (file)
@@ -33,6 +33,11 @@ Optional properties:
                nodes.  If unspecified, a single SPI device without a chip
                select can be used.
 
+- dmas:         Two DMA channel specifiers following the convention outlined
+                in bindings/dma/dma.txt
+- dma-names:    Names for the dma channels, if present. There must be at
+                least one channel named "tx" for transmit and named "rx" for
+                receive.
 
 SPI slave nodes must be children of the SPI master node and can contain
 properties described in Documentation/devicetree/bindings/spi/spi-bus.txt
@@ -51,6 +56,9 @@ Example:
                clocks = <&gcc GCC_BLSP2_QUP2_SPI_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>;
                clock-names = "core", "iface";
 
+               dmas = <&blsp1_bam 13>, <&blsp1_bam 12>;
+               dma-names = "rx", "tx";
+
                pinctrl-names = "default";
                pinctrl-0 = <&spi8_default>;
 
index cbbe16ed3874f88c1902b90253afc756a01acb0d..70af78a9185e9b04bc8e24d30b6d9bc3bf705520 100644 (file)
@@ -16,6 +16,12 @@ Optional property:
   in big endian mode, otherwise in native mode(same with CPU), for more
   detail please see: Documentation/devicetree/bindings/regmap/regmap.txt.
 
+Optional SPI slave node properties:
+- fsl,spi-cs-sck-delay: a delay in nanoseconds between activating chip
+  select and the start of clock signal, at the start of a transfer.
+- fsl,spi-sck-cs-delay: a delay in nanoseconds between stopping the clock
+  signal and deactivating chip select, at the end of a transfer.
+
 Example:
 
 dspi0@4002c000 {
@@ -43,6 +49,8 @@ dspi0@4002c000 {
                reg = <0>;
                linux,modalias = "m25p80";
                modal = "at26df081a";
+               fsl,spi-cs-sck-delay = <100>;
+               fsl,spi-sck-cs-delay = <50>;
        };
 };
 
index c7dd50fb8eb29c7650bba9fa50c67d72de46fc90..e02fbf18c82cecad21a355cfacd3ae84c1676ac9 100644 (file)
@@ -14,6 +14,7 @@ Required properties:
 - dma-names: Must include the following entries:
   - rx
   - tx
+- cs-gpios: Must specify the GPIOs used for chipselect lines.
 - #address-cells: Must be 1.
 - #size-cells: Must be 0.
 
index 467dec441c62a545f3d011f45c8707f35287ded4..0c491bda4c65f9bace70c051fc06389261d82cad 100644 (file)
@@ -24,6 +24,9 @@ Optional Properties:
 - dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
                Documentation/devicetree/bindings/dma/dma.txt
 - dma-names: DMA request names should include "tx" and "rx" if present.
+- rx-sample-delay-ns: nanoseconds to delay after the SCLK edge before sampling
+               Rx data (may need to be fine tuned for high capacitance lines).
+               No delay (0) by default.
 
 
 Example:
@@ -33,6 +36,7 @@ Example:
                reg = <0xff110000 0x1000>;
                dmas = <&pdma1 11>, <&pdma1 12>;
                dma-names = "tx", "rx";
+               rx-sample-delay-ns = <10>;
                #address-cells = <1>;
                #size-cells = <0>;
                interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
index 43404b197933262859e79686d5a8fa25ab12e5f3..332e625f6ed01cb4e442c0ea530ab29eb92f2a77 100644 (file)
@@ -4,7 +4,7 @@ Required properties:
 - compatible           : "renesas,thermal-<soctype>", "renesas,rcar-thermal"
                          as fallback.
                          Examples with soctypes are:
-                           - "renesas,thermal-r8a73a4" (R-Mobile AP6)
+                           - "renesas,thermal-r8a73a4" (R-Mobile APE6)
                            - "renesas,thermal-r8a7779" (R-Car H1)
                            - "renesas,thermal-r8a7790" (R-Car H2)
                            - "renesas,thermal-r8a7791" (R-Car M2-W)
index cd7f0454e13a9227ad512228e9c12bc76e2c7c07..5cc364309edbaa7fd1972172b8817a103739e8f5 100644 (file)
@@ -14,6 +14,7 @@ Optional properties:
  - phys: from the *Generic PHY* bindings
  - phy-names: from the *Generic PHY* bindings
  - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
+ - snps,usb3_lpm_capable: determines if platform is USB3 LPM capable
  - snps,disable_scramble_quirk: true when SW should disable data scrambling.
        Only really useful for FPGA builds.
  - snps,has-lpm-erratum: true when DWC3 was configured with LPM Erratum enabled
index 61b045b6d50e56ae139b31468f2b95f85e8f1651..dc2a18f0b3a10a9e1bd5814fc429fe9246b82ec7 100644 (file)
@@ -15,7 +15,10 @@ Optional properties:
   - phys: phandle + phy specifier pair
   - phy-names: must be "usb"
   - dmas: Must contain a list of references to DMA specifiers.
-  - dma-names : Must contain a list of DMA names, "tx" or "rx".
+  - dma-names : Must contain a list of DMA names:
+   - tx0 ... tx<n>
+   - rx0 ... rx<n>
+    - This <n> means DnFIFO in USBHS module.
 
 Example:
        usbhs: usb@e6590000 {
index c101a4b1713185a026d9ee12d8bfac6623082f39..3539d4e7d23e1a1e0b5a4625f285f138d5d39071 100644 (file)
@@ -5,6 +5,7 @@ Required properties:
 - compatible: Should be one of below:
        "fsl,imx6q-usbmisc" for imx6q
        "fsl,vf610-usbmisc" for Vybrid vf610
+       "fsl,imx6sx-usbmisc" for imx6sx
 - reg: Should contain registers location and length
 
 Examples:
index 728cd0e1b306452f13a136cc31d348098524c9f6..b13aa55b7a6f71fdc6d325426ca3ed5bfece7ad2 100644 (file)
@@ -127,6 +127,7 @@ mxicy       Macronix International Co., Ltd.
 national       National Semiconductor
 neonode                Neonode Inc.
 netgear        NETGEAR
+netlogic       Broadcom Corporation (formerly NetLogic Microsystems)
 newhaven       Newhaven Display International
 nintendo       Nintendo
 nokia  Nokia
@@ -169,6 +170,7 @@ sii Seiko Instruments, Inc.
 silergy        Silergy Corp.
 sirf   SiRF Technology, Inc.
 sitronix       Sitronix Technology Corporation
+skyworks       Skyworks Solutions, Inc.
 smsc   Standard Microsystems Corporation
 snps   Synopsys, Inc.
 solidrun       SolidRun
@@ -196,6 +198,7 @@ voipac      Voipac Technologies s.r.o.
 winbond Winbond Electronics corp.
 wlf    Wolfson Microelectronics
 wm     Wondermedia Technologies, Inc.
+x-powers       X-Powers
 xes    Extreme Engineering Solutions (X-ES)
 xillybus       Xillybus Ltd.
 xlnx   Xilinx
diff --git a/Documentation/devicetree/bindings/video/backlight/sky81452-backlight.txt b/Documentation/devicetree/bindings/video/backlight/sky81452-backlight.txt
new file mode 100644 (file)
index 0000000..8bf2940
--- /dev/null
@@ -0,0 +1,29 @@
+SKY81452-backlight bindings
+
+Required properties:
+- compatible           : Must be "skyworks,sky81452-backlight"
+
+Optional properties:
+- name                 : Name of backlight device. Default is 'lcd-backlight'.
+- gpios                        : GPIO to use to EN pin.
+                       See Documentation/devicetree/bindings/gpio/gpio.txt
+- led-sources          : List of enabled channels from 0 to 5.
+                       See Documentation/devicetree/bindings/leds/common.txt
+- skyworks,ignore-pwm  : Ignore both PWM input
+- skyworks,dpwm-mode   : Enable DPWM dimming mode, otherwise Analog dimming.
+- skyworks,phase-shift : Enable phase shift mode
+- skyworks,short-detection-threshold-volt
+                       : It should be one of 4, 5, 6 and 7V.
+- skyworks,current-limit-mA
+                       : It should be 2300mA or 2750mA.
+
+Example:
+
+       backlight {
+               compatible = "skyworks,sky81452-backlight";
+               name = "pwm-backlight";
+               led-sources = <0 1 2 5>;
+               skyworks,ignore-pwm;
+               skyworks,phase-shift;
+               skyworks,current-limit-mA = <2300>;
+       };
index 948b0989c4335c408cd220cd64d58133d4b1a906..b287752a31cd561f1b2770e3ac5cbb36ceeefce2 100644 (file)
@@ -138,3 +138,87 @@ accelerometer wants to poll X axis value, then it can call this function with
 the usage id of X axis. HID sensors can provide events, so this is not necessary
 to poll for any field. If there is some new sample, the core driver will call
 registered callback function to process the sample.
+
+
+----------
+
+HID Custom and generic Sensors
+
+HID Sensor specification defines two special sensor usage types. Since they
+don't represent a standard sensor, it is not possible to define using Linux IIO
+type interfaces.
+The purpose of these sensors is to extend the functionality or provide a
+way to obfuscate the data being communicated by a sensor. Without knowing the
+mapping between the data and its encapsulated form, it is difficult for
+an application/driver to determine what data is being communicated by the sensor.
+This allows some differentiating use cases, where vendor can provide applications.
+Some common use cases are debug other sensors or to provide some events like
+keyboard attached/detached or lid open/close.
+
+To allow application to utilize these sensors, here they are exported uses sysfs
+attribute groups, attributes and misc device interface.
+
+An example of this representation on sysfs:
+/sys/devices/pci0000:00/INT33C2:00/i2c-0/i2c-INT33D1:00/0018:8086:09FA.0001/HID-SENSOR-2000e1.6.auto$ tree -R
+.
+????????? enable_sensor
+????????? feature-0-200316
+??????? ????????? feature-0-200316-maximum
+??????? ????????? feature-0-200316-minimum
+??????? ????????? feature-0-200316-name
+??????? ????????? feature-0-200316-size
+??????? ????????? feature-0-200316-unit-expo
+??????? ????????? feature-0-200316-units
+??????? ????????? feature-0-200316-value
+????????? feature-1-200201
+??????? ????????? feature-1-200201-maximum
+??????? ????????? feature-1-200201-minimum
+??????? ????????? feature-1-200201-name
+??????? ????????? feature-1-200201-size
+??????? ????????? feature-1-200201-unit-expo
+??????? ????????? feature-1-200201-units
+??????? ????????? feature-1-200201-value
+????????? input-0-200201
+??????? ????????? input-0-200201-maximum
+??????? ????????? input-0-200201-minimum
+??????? ????????? input-0-200201-name
+??????? ????????? input-0-200201-size
+??????? ????????? input-0-200201-unit-expo
+??????? ????????? input-0-200201-units
+??????? ????????? input-0-200201-value
+????????? input-1-200202
+??????? ????????? input-1-200202-maximum
+??????? ????????? input-1-200202-minimum
+??????? ????????? input-1-200202-name
+??????? ????????? input-1-200202-size
+??????? ????????? input-1-200202-unit-expo
+??????? ????????? input-1-200202-units
+??????? ????????? input-1-200202-value
+
+Here there is a custom sensors with four fields, two feature and two inputs.
+Each field is represented by a set of attributes. All fields except the "value"
+are read only. The value field is a RW field.
+Example
+/sys/bus/platform/devices/HID-SENSOR-2000e1.6.auto/feature-0-200316$ grep -r . *
+feature-0-200316-maximum:6
+feature-0-200316-minimum:0
+feature-0-200316-name:property-reporting-state
+feature-0-200316-size:1
+feature-0-200316-unit-expo:0
+feature-0-200316-units:25
+feature-0-200316-value:1
+
+How to enable such sensor?
+By default sensor can be power gated. To enable sysfs attribute "enable" can be
+used.
+$ echo 1 > enable_sensor
+
+Once enabled and powered on, sensor can report value using HID reports.
+These reports are pushed using misc device interface in a FIFO order.
+/dev$ tree | grep HID-SENSOR-2000e1.6.auto
+??????? ????????? 10:53 -> ../HID-SENSOR-2000e1.6.auto
+????????? HID-SENSOR-2000e1.6.auto
+
+Each reports can be of variable length preceded by a header. This header
+consist of a 32 bit usage id, 64 bit time stamp and 32 bit length field of raw
+data.
index fe80e9adebfa452d184cf8ec75491cb4d26785b4..e87294878334d92af5af6420a8eae3d4222aaafc 100644 (file)
@@ -6,6 +6,10 @@ Supported chips:
     Prefix: 'it8603'
     Addresses scanned: from Super I/O config space (8 I/O ports)
     Datasheet: Not publicly available
+  * IT8620E
+    Prefix: 'it8620'
+    Addresses scanned: from Super I/O config space (8 I/O ports)
+    Datasheet: Not publicly available
   * IT8705F
     Prefix: 'it87'
     Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -42,6 +46,10 @@ Supported chips:
     Prefix: 'it8772'
     Addresses scanned: from Super I/O config space (8 I/O ports)
     Datasheet: Not publicly available
+  * IT8781F
+    Prefix: 'it8781'
+    Addresses scanned: from Super I/O config space (8 I/O ports)
+    Datasheet: Not publicly available
   * IT8782F
     Prefix: 'it8782'
     Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -50,6 +58,14 @@ Supported chips:
     Prefix: 'it8783'
     Addresses scanned: from Super I/O config space (8 I/O ports)
     Datasheet: Not publicly available
+  * IT8786E
+    Prefix: 'it8786'
+    Addresses scanned: from Super I/O config space (8 I/O ports)
+    Datasheet: Not publicly available
+  * IT8790E
+    Prefix: 'it8790'
+    Addresses scanned: from Super I/O config space (8 I/O ports)
+    Datasheet: Not publicly available
   * SiS950   [clone of IT8705F]
     Prefix: 'it87'
     Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -94,9 +110,10 @@ motherboard models.
 Description
 -----------
 
-This driver implements support for the IT8603E, IT8623E, IT8705F, IT8712F,
-IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E, IT8771E,
-IT8772E, IT8782F, IT8783E/F, and SiS950 chips.
+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.
 
 These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
 joysticks and other miscellaneous stuff. For hardware monitoring, they
@@ -120,11 +137,11 @@ 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, 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 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
+is enabled by the driver when one of the above chips is detected.
 
 The IT8726F is just bit enhanced IT8716F with additional hardware
 for AMD power sequencing. Therefore the chip will appear as IT8716F
@@ -134,8 +151,13 @@ The IT8728F, IT8771E, and IT8772E are considered compatible with the IT8721F,
 until a datasheet becomes available (hopefully.)
 
 The IT8603E/IT8623E is a custom design, hardware monitoring part is similar to
-IT8728F. It only supports 16-bit fan mode, the full speed mode of the
-fan is not supported (value 0 of pwmX_enable).
+IT8728F. It only supports 3 fans, 16-bit fan mode, and the full speed mode
+of the fan is not supported (value 0 of pwmX_enable).
+
+The IT8620E is another custom design, hardware monitoring part is similar to
+IT8728F. It only supports 16-bit fan mode.
+
+The IT8790E supports up to 3 fans. 16-bit fan mode is always enabled.
 
 Temperatures are measured in degrees Celsius. An alarm is triggered once
 when the Overtemperature Shutdown limit is crossed.
@@ -156,10 +178,10 @@ 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, IT8782F, and IT8783E/F, some voltage inputs
-are internal and scaled inside the chip:
+On the IT8603E, IT8721F/IT8758E, IT8781F, IT8782F, and IT8783E/F, some
+voltage inputs are internal and scaled inside the chip:
 * in3 (optional)
-* in7 (optional for IT8782F and IT8783E/F)
+* in7 (optional for IT8781F, IT8782F, and IT8783E/F)
 * in8 (always)
 * in9 (relevant for IT8603E only)
 The driver handles this transparently so user-space doesn't have to care.
index f3893f7440def4e6038bc2263709bacda9d15ff3..f7f1830a25663c6273812abe9cbddf8245a050d4 100644 (file)
@@ -11,12 +11,10 @@ Supported chips:
        http://www.atmel.com/Images/doc8711.pdf
        http://www.atmel.com/Images/Atmel-8852-SEEPROM-AT30TSE002A-Datasheet.pdf
        http://www.atmel.com/Images/Atmel-8868-DTS-AT30TSE004A-Datasheet.pdf
-  * IDT TSE2002B3, TSE2002GB2, TS3000B3, TS3000GB2
+  * IDT TSE2002B3, TSE2002GB2, TSE2004GB2, TS3000B3, TS3000GB0, TS3000GB2,
+       TS3001GB2
     Datasheets:
-       http://www.idt.com/sites/default/files/documents/IDT_TSE2002B3C_DST_20100512_120303152056.pdf
-       http://www.idt.com/sites/default/files/documents/IDT_TSE2002GB2A1_DST_20111107_120303145914.pdf
-       http://www.idt.com/sites/default/files/documents/IDT_TS3000B3A_DST_20101129_120303152013.pdf
-       http://www.idt.com/sites/default/files/documents/IDT_TS3000GB2A1_DST_20111104_120303151012.pdf
+       Available from IDT web site
   * Maxim MAX6604
     Datasheets:
        http://datasheets.maxim-ic.com/en/ds/MAX6604.pdf
diff --git a/Documentation/hwmon/nct7904 b/Documentation/hwmon/nct7904
new file mode 100644 (file)
index 0000000..014f112
--- /dev/null
@@ -0,0 +1,60 @@
+Kernel driver nct7904
+====================
+
+Supported chip:
+  * Nuvoton NCT7904D
+    Prefix: nct7904
+    Addresses: I2C 0x2d, 0x2e
+    Datasheet: Publicly available at Nuvoton website
+       http://www.nuvoton.com/
+
+Author: Vadim V. Vlasov <vvlasov@dev.rtsoft.ru>
+
+
+Description
+-----------
+
+The NCT7904D is a hardware monitor supporting up to 20 voltage sensors,
+internal temperature sensor, Intel PECI and AMD SB-TSI CPU temperature
+interface, up to 12 fan tachometer inputs, up to 4 fan control channels
+with SmartFan.
+
+
+Sysfs entries
+-------------
+
+Currently, the driver supports only the following features:
+
+in[1-20]_input         Input voltage measurements (mV)
+
+fan[1-12]_input                Fan tachometer measurements (rpm)
+
+temp1_input            Local temperature (1/1000 degree,
+                       0.125 degree resolution)
+
+temp[2-9]_input                CPU temperatures (1/1000 degree,
+                       0.125 degree resolution)
+
+fan[1-4]_mode          R/W, 0/1 for manual or SmartFan mode
+                       Setting SmartFan mode is supported only if it has been
+                       previously configured by BIOS (or configuration EEPROM)
+
+fan[1-4]_pwm           R/O in SmartFan mode, R/W in manual control mode
+
+The driver checks sensor control registers and does not export the sensors
+that are not enabled. Anyway, a sensor that is enabled may actually be not
+connected and thus provide zero readings.
+
+
+Limitations
+-----------
+
+The following features are not supported in current version:
+
+ - SmartFan control
+ - Watchdog
+ - GPIO
+ - external temperature sensors
+ - SMI
+ - min/max values
+ - many other...
diff --git a/Documentation/i2c/slave-eeprom-backend b/Documentation/i2c/slave-eeprom-backend
new file mode 100644 (file)
index 0000000..c8444ef
--- /dev/null
@@ -0,0 +1,14 @@
+Linux I2C slave eeprom backend
+==============================
+
+by Wolfram Sang <wsa@sang-engineering.com> in 2014-15
+
+This is a proof-of-concept backend which acts like an EEPROM on the connected
+I2C bus. The memory contents can be modified from userspace via this file
+located in sysfs:
+
+       /sys/bus/i2c/devices/<device-direcory>/slave-eeprom
+
+As of 2015, Linux doesn't support poll on binary sysfs files, so there is no
+notfication when another master changed the content.
+
diff --git a/Documentation/i2c/slave-interface b/Documentation/i2c/slave-interface
new file mode 100644 (file)
index 0000000..389bb5d
--- /dev/null
@@ -0,0 +1,179 @@
+Linux I2C slave interface description
+=====================================
+
+by Wolfram Sang <wsa@sang-engineering.com> in 2014-15
+
+Linux can also be an I2C slave in case I2C controllers have slave support.
+Besides this HW requirement, one also needs a software backend providing the
+actual functionality. An example for this is the slave-eeprom driver, which
+acts as a dual memory driver. While another I2C master on the bus can access it
+like a regular EEPROM, the Linux I2C slave can access the content via sysfs and
+retrieve/provide information as needed. The software backend driver and the I2C
+bus driver communicate via events. Here is a small graph visualizing the data
+flow and the means by which data is transported. The dotted line marks only one
+example. The backend could also use e.g. a character device, be in-kernel
+only, or something completely different:
+
+
+              e.g. sysfs        I2C slave events        I/O registers
+  +-----------+   v    +---------+     v     +--------+  v  +------------+
+  | Userspace +........+ Backend +-----------+ Driver +-----+ Controller |
+  +-----------+        +---------+           +--------+     +------------+
+                                                                | |
+  ----------------------------------------------------------------+--  I2C
+  --------------------------------------------------------------+----  Bus
+
+Note: Technically, there is also the I2C core between the backend and the
+driver. However, at this time of writing, the layer is transparent.
+
+
+User manual
+===========
+
+I2C slave backends behave like standard I2C clients. So, you can instantiate
+them like described in the document 'instantiating-devices'. A quick example
+for instantiating the slave-eeprom driver from userspace:
+
+  # echo 0-0064 > /sys/bus/i2c/drivers/i2c-slave-eeprom/bind
+
+Each backend should come with separate documentation to describe its specific
+behaviour and setup.
+
+
+Developer manual
+================
+
+I2C slave events
+----------------
+
+The bus driver sends an event to the backend using the following function:
+
+       ret = i2c_slave_event(client, event, &val)
+
+'client' describes the i2c slave device. 'event' is one of the special event
+types described hereafter. 'val' holds an u8 value for the data byte to be
+read/written and is thus bidirectional. The pointer to val must always be
+provided even if val is not used for an event, i.e. don't use NULL here. 'ret'
+is the return value from the backend. Mandatory events must be provided by the
+bus drivers and must be checked for by backend drivers.
+
+Event types:
+
+* I2C_SLAVE_WRITE_REQUESTED (mandatory)
+
+'val': unused
+'ret': always 0
+
+Another I2C master wants to write data to us. This event should be sent once
+our own address and the write bit was detected. The data did not arrive yet, so
+there is nothing to process or return. Wakeup or initialization probably needs
+to be done, though.
+
+* I2C_SLAVE_READ_REQUESTED (mandatory)
+
+'val': backend returns first byte to be sent
+'ret': always 0
+
+Another I2C master wants to read data from us. This event should be sent once
+our own address and the read bit was detected. After returning, the bus driver
+should transmit the first byte.
+
+* I2C_SLAVE_WRITE_RECEIVED (mandatory)
+
+'val': bus driver delivers received byte
+'ret': 0 if the byte should be acked, some errno if the byte should be nacked
+
+Another I2C master has sent a byte to us which needs to be set in 'val'. If 'ret'
+is zero, the bus driver should ack this byte. If 'ret' is an errno, then the byte
+should be nacked.
+
+* I2C_SLAVE_READ_PROCESSED (mandatory)
+
+'val': backend returns next byte to be sent
+'ret': always 0
+
+The bus driver requests the next byte to be sent to another I2C master in
+'val'. Important: This does not mean that the previous byte has been acked, it
+only means that the previous byte is shifted out to the bus! To ensure seamless
+transmission, most hardware requests the next byte when the previous one is
+still shifted out. If the master sends NACK and stops reading after the byte
+currently shifted out, this byte requested here is never used. It very likely
+needs to be sent again on the next I2C_SLAVE_READ_REQUEST, depending a bit on
+your backend, though.
+
+* I2C_SLAVE_STOP (mandatory)
+
+'val': unused
+'ret': always 0
+
+A stop condition was received. This can happen anytime and the backend should
+reset its state machine for I2C transfers to be able to receive new requests.
+
+
+Software backends
+-----------------
+
+If you want to write a software backend:
+
+* use a standard i2c_driver and its matching mechanisms
+* write the slave_callback which handles the above slave events
+  (best using a state machine)
+* register this callback via i2c_slave_register()
+
+Check the i2c-slave-eeprom driver as an example.
+
+
+Bus driver support
+------------------
+
+If you want to add slave support to the bus driver:
+
+* implement calls to register/unregister the slave and add those to the
+  struct i2c_algorithm. When registering, you probably need to set the i2c
+  slave address and enable slave specific interrupts. If you use runtime pm, you
+  should use pm_runtime_forbid() because your device usually needs to be powered
+  on always to be able to detect its slave address. When unregistering, do the
+  inverse of the above.
+
+* Catch the slave interrupts and send appropriate i2c_slave_events to the backend.
+
+Check the i2c-rcar driver as an example.
+
+
+About ACK/NACK
+--------------
+
+It is good behaviour to always ACK the address phase, so the master knows if a
+device is basically present or if it mysteriously disappeared. Using NACK to
+state being busy is troublesome. SMBus demands to always ACK the address phase,
+while the I2C specification is more loose on that. Most I2C controllers also
+automatically ACK when detecting their slave addresses, so there is no option
+to NACK them. For those reasons, this API does not support NACK in the address
+phase.
+
+Currently, there is no slave event to report if the master did ACK or NACK a
+byte when it reads from us. We could make this an optional event if the need
+arises. However, cases should be extremely rare because the master is expected
+to send STOP after that and we have an event for that. Also, keep in mind not
+all I2C controllers have the possibility to report that event.
+
+
+About buffers
+-------------
+
+During development of this API, the question of using buffers instead of just
+bytes came up. Such an extension might be possible, usefulness is unclear at
+this time of writing. Some points to keep in mind when using buffers:
+
+* Buffers should be opt-in and slave drivers will always have to support
+  byte-based transactions as the ultimate fallback because this is how the
+  majority of HW works.
+
+* For backends simulating hardware registers, buffers are not helpful because
+  on writes an action should be immediately triggered. For reads, the data in
+  the buffer might get stale.
+
+* A master can send STOP at any time. For partially transferred buffers, this
+  means additional code to handle this exception. Such code tends to be
+  error-prone.
+
index 13ab076dcd92484149eec9ef9e8bc1fc33031397..809541ab352f03a6a9c3cb8570f52157f1d73054 100644 (file)
@@ -41,7 +41,3 @@ integrated than Algorithm and Adapter.
 
 For a given configuration, you will need a driver for your I2C bus, and
 drivers for your I2C devices (usually one driver for each device).
-
-At this time, Linux only operates I2C (or SMBus) in master mode; you can't
-use these APIs to make a Linux system behave as a slave/device, either to
-speak a custom protocol or to emulate some other device.
index bfcb1a62a7b48466f3cbe5a08d3e1a632eadc3d2..32755634975708bf9dc511f36c6d3ec452ac3ef4 100644 (file)
@@ -1036,7 +1036,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Format: {"off" | "on" | "skip[mbr]"}
 
        efi=            [EFI]
-                       Format: { "old_map", "nochunk", "noruntime" }
+                       Format: { "old_map", "nochunk", "noruntime", "debug" }
                        old_map [X86-64]: switch to the old ioremap-based EFI
                        runtime services mapping. 32-bit still uses this one by
                        default.
@@ -1044,6 +1044,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        boot stub, as chunking can cause problems with some
                        firmware implementations.
                        noruntime : disable EFI runtime services support
+                       debug: enable misc debug output
 
        efi_no_storage_paranoia [EFI; X86]
                        Using this parameter you can use more than 50% of
@@ -1988,7 +1989,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        seconds.  Use this parameter to check at some
                        other rate.  0 disables periodic checking.
 
-       memtest=        [KNL,X86] Enable memtest
+       memtest=        [KNL,X86,ARM] Enable memtest
                        Format: <integer>
                        default : 0 <disable>
                        Specifies the number of memtest passes to be
@@ -2235,8 +2236,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        nmi_watchdog=   [KNL,BUGS=X86] Debugging features for SMP kernels
                        Format: [panic,][nopanic,][num]
-                       Valid num: 0
+                       Valid num: 0 or 1
                        0 - turn nmi_watchdog off
+                       1 - turn nmi_watchdog on
                        When panic is specified, panic when an NMI watchdog
                        timeout occurs (or 'nopanic' to override the opposite
                        default).
@@ -2321,6 +2323,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        register save and restore. The kernel will only save
                        legacy floating-point registers on task switch.
 
+       nohugeiomap     [KNL,x86] Disable kernel huge I/O mappings.
+
        noxsave         [BUGS=X86] Disables x86 extended register state save
                        and restore using xsave. The kernel will fallback to
                        enabling legacy floating-point and sse state.
@@ -2463,7 +2467,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        nousb           [USB] Disable the USB subsystem
 
-       nowatchdog      [KNL] Disable the lockup detector (NMI watchdog).
+       nowatchdog      [KNL] Disable both lockup detectors, i.e.
+                        soft-lockup and NMI watchdog (hard-lockup).
 
        nowb            [ARM]
 
@@ -2968,6 +2973,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Set maximum number of finished RCU callbacks to
                        process in one batch.
 
+       rcutree.gp_init_delay=  [KNL]
+                       Set the number of jiffies to delay each step of
+                       RCU grace-period initialization.  This only has
+                       effect when CONFIG_RCU_TORTURE_TEST_SLOW_INIT is
+                       set.
+
        rcutree.rcu_fanout_leaf= [KNL]
                        Increase the number of CPUs assigned to each
                        leaf rcu_node structure.  Useful for very large
@@ -2991,11 +3002,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        value is one, and maximum value is HZ.
 
        rcutree.kthread_prio=    [KNL,BOOT]
-                       Set the SCHED_FIFO priority of the RCU
-                       per-CPU kthreads (rcuc/N). This value is also
-                       used for the priority of the RCU boost threads
-                       (rcub/N). Valid values are 1-99 and the default
-                       is 1 (the least-favored priority).
+                       Set the SCHED_FIFO priority of the RCU per-CPU
+                       kthreads (rcuc/N). This value is also used for
+                       the priority of the RCU boost threads (rcub/N)
+                       and for the RCU grace-period kthreads (rcu_bh,
+                       rcu_preempt, and rcu_sched). If RCU_BOOST is
+                       set, valid values are 1-99 and the default is 1
+                       (the least-favored priority).  Otherwise, when
+                       RCU_BOOST is not set, valid values are 0-99 and
+                       the default is zero (non-realtime operation).
 
        rcutree.rcu_nocb_leader_stride= [KNL]
                        Set the number of NOCB kthread groups, which
index f3cd299fcc41203f9fe73ad16cd70aa77a421ef3..f4cbfe0ba1085b4df3067dcc457219699c5c6150 100644 (file)
@@ -190,20 +190,24 @@ To reduce its OS jitter, do any of the following:
                on each CPU, including cs_dbs_timer() and od_dbs_timer().
                WARNING:  Please check your CPU specifications to
                make sure that this is safe on your particular system.
-       d.      It is not possible to entirely get rid of OS jitter
-               from vmstat_update() on CONFIG_SMP=y systems, but you
-               can decrease its frequency by writing a large value
-               to /proc/sys/vm/stat_interval.  The default value is
-               HZ, for an interval of one second.  Of course, larger
-               values will make your virtual-memory statistics update
-               more slowly.  Of course, you can also run your workload
-               at a real-time priority, thus preempting vmstat_update(),
+       d.      As of v3.18, Christoph Lameter's on-demand vmstat workers
+               commit prevents OS jitter due to vmstat_update() on
+               CONFIG_SMP=y systems.  Before v3.18, is not possible
+               to entirely get rid of the OS jitter, but you can
+               decrease its frequency by writing a large value to
+               /proc/sys/vm/stat_interval.  The default value is HZ,
+               for an interval of one second.  Of course, larger values
+               will make your virtual-memory statistics update more
+               slowly.  Of course, you can also run your workload at
+               a real-time priority, thus preempting vmstat_update(),
                but if your workload is CPU-bound, this is a bad idea.
                However, there is an RFC patch from Christoph Lameter
                (based on an earlier one from Gilad Ben-Yossef) that
                reduces or even eliminates vmstat overhead for some
                workloads at https://lkml.org/lkml/2013/9/4/379.
-       e.      If running on high-end powerpc servers, build with
+       e.      Boot with "elevator=noop" to avoid workqueue use by
+               the block layer.
+       f.      If running on high-end powerpc servers, build with
                CONFIG_PPC_RTAS_DAEMON=n.  This prevents the RTAS
                daemon from running on each CPU every second or so.
                (This will require editing Kconfig files and will defeat
@@ -211,12 +215,12 @@ To reduce its OS jitter, do any of the following:
                due to the rtas_event_scan() function.
                WARNING:  Please check your CPU specifications to
                make sure that this is safe on your particular system.
-       f.      If running on Cell Processor, build your kernel with
+       g.      If running on Cell Processor, build your kernel with
                CBE_CPUFREQ_SPU_GOVERNOR=n to avoid OS jitter from
                spu_gov_work().
                WARNING:  Please check your CPU specifications to
                make sure that this is safe on your particular system.
-       g.      If running on PowerMAC, build your kernel with
+       h.      If running on PowerMAC, build your kernel with
                CONFIG_PMAC_RACKMETER=n to disable the CPU-meter,
                avoiding OS jitter from rackmeter_do_timer().
 
@@ -258,8 +262,12 @@ Purpose: Detect software lockups on each CPU.
 To reduce its OS jitter, do at least one of the following:
 1.     Build with CONFIG_LOCKUP_DETECTOR=n, which will prevent these
        kthreads from being created in the first place.
-2.     Echo a zero to /proc/sys/kernel/watchdog to disable the
+2.     Boot with "nosoftlockup=0", which will also prevent these kthreads
+       from being created.  Other related watchdog and softlockup boot
+       parameters may be found in Documentation/kernel-parameters.txt
+       and Documentation/watchdog/watchdog-parameters.txt.
+3.     Echo a zero to /proc/sys/kernel/watchdog to disable the
        watchdog timer.
-3.     Echo a large number of /proc/sys/kernel/watchdog_thresh in
+4.     Echo a large number of /proc/sys/kernel/watchdog_thresh in
        order to reduce the frequency of OS jitter due to the watchdog
        timer down to a level that is acceptable for your workload.
index ca2387ef27ab0c38cdb4b5e74ffbcde9509d61d8..6974f1c2b4e1edea11b0d31185153d12ef25957c 100644 (file)
@@ -592,9 +592,9 @@ See also the subsection on "Cache Coherency" for a more thorough example.
 CONTROL DEPENDENCIES
 --------------------
 
-A control dependency requires a full read memory barrier, not simply a data
-dependency barrier to make it work correctly.  Consider the following bit of
-code:
+A load-load control dependency requires a full read memory barrier, not
+simply a data dependency barrier to make it work correctly.  Consider the
+following bit of code:
 
        q = ACCESS_ONCE(a);
        if (q) {
@@ -615,14 +615,15 @@ case what's actually required is:
        }
 
 However, stores are not speculated.  This means that ordering -is- provided
-in the following example:
+for load-store control dependencies, as in the following example:
 
        q = ACCESS_ONCE(a);
        if (q) {
                ACCESS_ONCE(b) = p;
        }
 
-Please note that ACCESS_ONCE() is not optional!  Without the
+Control dependencies pair normally with other types of barriers.
+That said, please note that ACCESS_ONCE() is not optional!  Without the
 ACCESS_ONCE(), might combine the load from 'a' with other loads from
 'a', and the store to 'b' with other stores to 'b', with possible highly
 counterintuitive effects on ordering.
@@ -813,6 +814,8 @@ In summary:
       barrier() can help to preserve your control dependency.  Please
       see the Compiler Barrier section for more information.
 
+  (*) Control dependencies pair normally with other types of barriers.
+
   (*) Control dependencies do -not- provide transitivity.  If you
       need transitivity, use smp_mb().
 
@@ -823,14 +826,14 @@ SMP BARRIER PAIRING
 When dealing with CPU-CPU interactions, certain types of memory barrier should
 always be paired.  A lack of appropriate pairing is almost certainly an error.
 
-General barriers pair with each other, though they also pair with
-most other types of barriers, albeit without transitivity.  An acquire
-barrier pairs with a release barrier, but both may also pair with other
-barriers, including of course general barriers.  A write barrier pairs
-with a data dependency barrier, an acquire barrier, a release barrier,
-a read barrier, or a general barrier.  Similarly a read barrier or a
-data dependency barrier pairs with a write barrier, an acquire barrier,
-a release barrier, or a general barrier:
+General barriers pair with each other, though they also pair with most
+other types of barriers, albeit without transitivity.  An acquire barrier
+pairs with a release barrier, but both may also pair with other barriers,
+including of course general barriers.  A write barrier pairs with a data
+dependency barrier, a control dependency, an acquire barrier, a release
+barrier, a read barrier, or a general barrier.  Similarly a read barrier,
+control dependency, or a data dependency barrier pairs with a write
+barrier, an acquire barrier, a release barrier, or a general barrier:
 
        CPU 1                 CPU 2
        ===============       ===============
@@ -850,6 +853,19 @@ Or:
                              <data dependency barrier>
                              y = *x;
 
+Or even:
+
+       CPU 1                 CPU 2
+       ===============       ===============================
+       r1 = ACCESS_ONCE(y);
+       <general barrier>
+       ACCESS_ONCE(y) = 1;   if (r2 = ACCESS_ONCE(x)) {
+                                <implicit control dependency>
+                                ACCESS_ONCE(y) = 1;
+                             }
+
+       assert(r1 == 0 || r2 == 0);
+
 Basically, the read barrier always has to be there, even though it can be of
 the "weaker" type.
 
index b8f2147b96dd90afd16cd742a40be40f64a09c89..a9b47163bb5d6903f4c8f6fa436fca5977e4556d 100644 (file)
@@ -72,7 +72,6 @@ static struct pinctrl_desc foo_desc = {
        .name = "foo",
        .pins = foo_pins,
        .npins = ARRAY_SIZE(foo_pins),
-       .maxpin = 63,
        .owner = THIS_MODULE,
 };
 
@@ -164,8 +163,8 @@ static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
 }
 
 static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
-                              unsigned ** const pins,
-                              unsigned * const num_pins)
+                              const unsigned **pins,
+                              unsigned *num_pins)
 {
        *pins = (unsigned *) foo_groups[selector].pins;
        *num_pins = foo_groups[selector].num_pins;
@@ -570,9 +569,8 @@ is possible to perform the requested mux setting, poke the hardware so that
 this happens.
 
 Pinmux drivers are required to supply a few callback functions, some are
-optional. Usually the enable() and disable() functions are implemented,
-writing values into some certain registers to activate a certain mux setting
-for a certain pin.
+optional. Usually the set_mux() function is implemented, writing values into
+some certain registers to activate a certain mux setting for a certain pin.
 
 A simple driver for the above example will work by setting bits 0, 1, 2, 3 or 4
 into some register named MUX to select a certain function with a certain
@@ -683,12 +681,12 @@ static const struct foo_pmx_func foo_functions[] = {
        },
 };
 
-int foo_get_functions_count(struct pinctrl_dev *pctldev)
+static int foo_get_functions_count(struct pinctrl_dev *pctldev)
 {
        return ARRAY_SIZE(foo_functions);
 }
 
-const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector)
+static const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector)
 {
        return foo_functions[selector].name;
 }
@@ -702,7 +700,7 @@ static int foo_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
        return 0;
 }
 
-int foo_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
+static int foo_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
                unsigned group)
 {
        u8 regbit = (1 << selector + group);
@@ -711,7 +709,7 @@ int foo_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
        return 0;
 }
 
-struct pinmux_ops foo_pmxops = {
+static struct pinmux_ops foo_pmxops = {
        .get_functions_count = foo_get_functions_count,
        .get_function_name = foo_get_fname,
        .get_function_groups = foo_get_groups,
@@ -1266,7 +1264,7 @@ The semantics of the pinctrl APIs are:
 
 Usually the pin control core handled the get/put pair and call out to the
 device drivers bookkeeping operations, like checking available functions and
-the associated pins, whereas the enable/disable pass on to the pin controller
+the associated pins, whereas select_state pass on to the pin controller
 driver which takes care of activating and/or deactivating the mux setting by
 quickly poking some registers.
 
@@ -1363,8 +1361,9 @@ function, but with different named in the mapping as described under
 "Advanced mapping" above. So that for an SPI device, we have two states named
 "pos-A" and "pos-B".
 
-This snippet first muxes the function in the pins defined by group A, enables
-it, disables and releases it, and muxes it in on the pins defined by group B:
+This snippet first initializes a state object for both groups (in foo_probe()),
+then muxes the function in the pins defined by group A, and finally muxes it in
+on the pins defined by group B:
 
 #include <linux/pinctrl/consumer.h>
 
index 8afb236ca7653ed694af2b35e49eadbabd496152..e51564c1a140915c0646c81f8aae562f8d4baf68 100644 (file)
@@ -137,7 +137,7 @@ Indirect operating mode control.
 Consumer drivers can request a change in their supply regulator operating mode
 by calling :-
 
-int regulator_set_optimum_mode(struct regulator *regulator, int load_uA);
+int regulator_set_load(struct regulator *regulator, int load_uA);
 
 This will cause the core to recalculate the total load on the regulator (based
 on all its consumers) and change operating mode (if necessary and permitted)
index 596b60c08b7451a9739d22aa2a29cb3c5c2559c9..8446f1ea1410b87b071047dc310a787a92606c31 100644 (file)
@@ -204,266 +204,4 @@ Some common examples:
 
     *  RTC_PIE_ON, RTC_PIE_OFF: These are also emulated by the generic code.
 
-If all else fails, check out the rtc-test.c driver!
-
-
--------------------- 8< ---------------- 8< -----------------------------
-
-/*
- *      Real Time Clock Driver Test/Example Program
- *
- *      Compile with:
- *                  gcc -s -Wall -Wstrict-prototypes rtctest.c -o rtctest
- *
- *      Copyright (C) 1996, Paul Gortmaker.
- *
- *      Released under the GNU General Public License, version 2,
- *      included herein by reference.
- *
- */
-
-#include <stdio.h>
-#include <linux/rtc.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-
-
-/*
- * This expects the new RTC class driver framework, working with
- * clocks that will often not be clones of what the PC-AT had.
- * Use the command line to specify another RTC if you need one.
- */
-static const char default_rtc[] = "/dev/rtc0";
-
-
-int main(int argc, char **argv)
-{
-       int i, fd, retval, irqcount = 0;
-       unsigned long tmp, data;
-       struct rtc_time rtc_tm;
-       const char *rtc = default_rtc;
-
-       switch (argc) {
-       case 2:
-               rtc = argv[1];
-               /* FALLTHROUGH */
-       case 1:
-               break;
-       default:
-               fprintf(stderr, "usage:  rtctest [rtcdev]\n");
-               return 1;
-       }
-
-       fd = open(rtc, O_RDONLY);
-
-       if (fd ==  -1) {
-               perror(rtc);
-               exit(errno);
-       }
-
-       fprintf(stderr, "\n\t\t\tRTC Driver Test Example.\n\n");
-
-       /* Turn on update interrupts (one per second) */
-       retval = ioctl(fd, RTC_UIE_ON, 0);
-       if (retval == -1) {
-               if (errno == ENOTTY) {
-                       fprintf(stderr,
-                               "\n...Update IRQs not supported.\n");
-                       goto test_READ;
-               }
-               perror("RTC_UIE_ON ioctl");
-               exit(errno);
-       }
-
-       fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading %s:",
-                       rtc);
-       fflush(stderr);
-       for (i=1; i<6; i++) {
-               /* This read will block */
-               retval = read(fd, &data, sizeof(unsigned long));
-               if (retval == -1) {
-                       perror("read");
-                       exit(errno);
-               }
-               fprintf(stderr, " %d",i);
-               fflush(stderr);
-               irqcount++;
-       }
-
-       fprintf(stderr, "\nAgain, from using select(2) on /dev/rtc:");
-       fflush(stderr);
-       for (i=1; i<6; i++) {
-               struct timeval tv = {5, 0};     /* 5 second timeout on select */
-               fd_set readfds;
-
-               FD_ZERO(&readfds);
-               FD_SET(fd, &readfds);
-               /* The select will wait until an RTC interrupt happens. */
-               retval = select(fd+1, &readfds, NULL, NULL, &tv);
-               if (retval == -1) {
-                       perror("select");
-                       exit(errno);
-               }
-               /* This read won't block unlike the select-less case above. */
-               retval = read(fd, &data, sizeof(unsigned long));
-               if (retval == -1) {
-                       perror("read");
-                       exit(errno);
-               }
-               fprintf(stderr, " %d",i);
-               fflush(stderr);
-               irqcount++;
-       }
-
-       /* Turn off update interrupts */
-       retval = ioctl(fd, RTC_UIE_OFF, 0);
-       if (retval == -1) {
-               perror("RTC_UIE_OFF ioctl");
-               exit(errno);
-       }
-
-test_READ:
-       /* Read the RTC time/date */
-       retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
-       if (retval == -1) {
-               perror("RTC_RD_TIME ioctl");
-               exit(errno);
-       }
-
-       fprintf(stderr, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
-               rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
-               rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
-
-       /* Set the alarm to 5 sec in the future, and check for rollover */
-       rtc_tm.tm_sec += 5;
-       if (rtc_tm.tm_sec >= 60) {
-               rtc_tm.tm_sec %= 60;
-               rtc_tm.tm_min++;
-       }
-       if (rtc_tm.tm_min == 60) {
-               rtc_tm.tm_min = 0;
-               rtc_tm.tm_hour++;
-       }
-       if (rtc_tm.tm_hour == 24)
-               rtc_tm.tm_hour = 0;
-
-       retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
-       if (retval == -1) {
-               if (errno == ENOTTY) {
-                       fprintf(stderr,
-                               "\n...Alarm IRQs not supported.\n");
-                       goto test_PIE;
-               }
-               perror("RTC_ALM_SET ioctl");
-               exit(errno);
-       }
-
-       /* Read the current alarm settings */
-       retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
-       if (retval == -1) {
-               perror("RTC_ALM_READ ioctl");
-               exit(errno);
-       }
-
-       fprintf(stderr, "Alarm time now set to %02d:%02d:%02d.\n",
-               rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
-
-       /* Enable alarm interrupts */
-       retval = ioctl(fd, RTC_AIE_ON, 0);
-       if (retval == -1) {
-               perror("RTC_AIE_ON ioctl");
-               exit(errno);
-       }
-
-       fprintf(stderr, "Waiting 5 seconds for alarm...");
-       fflush(stderr);
-       /* This blocks until the alarm ring causes an interrupt */
-       retval = read(fd, &data, sizeof(unsigned long));
-       if (retval == -1) {
-               perror("read");
-               exit(errno);
-       }
-       irqcount++;
-       fprintf(stderr, " okay. Alarm rang.\n");
-
-       /* Disable alarm interrupts */
-       retval = ioctl(fd, RTC_AIE_OFF, 0);
-       if (retval == -1) {
-               perror("RTC_AIE_OFF ioctl");
-               exit(errno);
-       }
-
-test_PIE:
-       /* Read periodic IRQ rate */
-       retval = ioctl(fd, RTC_IRQP_READ, &tmp);
-       if (retval == -1) {
-               /* not all RTCs support periodic IRQs */
-               if (errno == ENOTTY) {
-                       fprintf(stderr, "\nNo periodic IRQ support\n");
-                       goto done;
-               }
-               perror("RTC_IRQP_READ ioctl");
-               exit(errno);
-       }
-       fprintf(stderr, "\nPeriodic IRQ rate is %ldHz.\n", tmp);
-
-       fprintf(stderr, "Counting 20 interrupts at:");
-       fflush(stderr);
-
-       /* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */
-       for (tmp=2; tmp<=64; tmp*=2) {
-
-               retval = ioctl(fd, RTC_IRQP_SET, tmp);
-               if (retval == -1) {
-                       /* not all RTCs can change their periodic IRQ rate */
-                       if (errno == ENOTTY) {
-                               fprintf(stderr,
-                                       "\n...Periodic IRQ rate is fixed\n");
-                               goto done;
-                       }
-                       perror("RTC_IRQP_SET ioctl");
-                       exit(errno);
-               }
-
-               fprintf(stderr, "\n%ldHz:\t", tmp);
-               fflush(stderr);
-
-               /* Enable periodic interrupts */
-               retval = ioctl(fd, RTC_PIE_ON, 0);
-               if (retval == -1) {
-                       perror("RTC_PIE_ON ioctl");
-                       exit(errno);
-               }
-
-               for (i=1; i<21; i++) {
-                       /* This blocks */
-                       retval = read(fd, &data, sizeof(unsigned long));
-                       if (retval == -1) {
-                               perror("read");
-                               exit(errno);
-                       }
-                       fprintf(stderr, " %d",i);
-                       fflush(stderr);
-                       irqcount++;
-               }
-
-               /* Disable periodic interrupts */
-               retval = ioctl(fd, RTC_PIE_OFF, 0);
-               if (retval == -1) {
-                       perror("RTC_PIE_OFF ioctl");
-                       exit(errno);
-               }
-       }
-
-done:
-       fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n");
-
-       close(fd);
-
-       return 0;
-}
+If all else fails, check out the tools/testing/selftests/timers/rtctest.c test!
index 1d508dcbf85942bd5bbfd982c14bf0de1a24321c..8586efff1e995b1947fd902e34576cbb1d8f2701 100644 (file)
@@ -786,7 +786,6 @@ port address 0x1400.
         irqm:1     same as initial settings (assumed BIOS settings)
         irqm:2     always totem pole
         irqm:0x10  driver will not use IRQF_SHARED flag when requesting irq
-        irqm:0x20  driver will not use IRQF_DISABLED flag when requesting irq
 
     (Bits 0x10 and 0x20 can be combined with hardware irq mode option)
 
@@ -1231,30 +1230,6 @@ they only refer to system buffers that are well aligned. So, a work around
 may only be needed under Linux when a scatter/gather list is not used and 
 when the SCSI DATA IN phase is reentered after a phase mismatch.
 
-14.5 IRQ sharing problems
-
-When an IRQ is shared by devices that are handled by different drivers, it 
-may happen that one driver complains about the request of the IRQ having 
-failed. Inder Linux-2.0, this may be due to one driver having requested the 
-IRQ using the IRQF_DISABLED flag but some other having requested the same IRQ
-without this flag. Under both Linux-2.0 and linux-2.2, this may be caused by 
-one driver not having requested the IRQ with the IRQF_SHARED flag.
-
-By default, the ncr53c8xx and sym53c8xx drivers request IRQs with both the 
-IRQF_DISABLED and the IRQF_SHARED flag under Linux-2.0 and with only the IRQF_SHARED
-flag under Linux-2.2.
-
-Under Linux-2.0, you can disable use of IRQF_DISABLED flag from the boot
-command line by using the following option:
-
-     ncr53c8xx=irqm:0x20   (for the generic ncr53c8xx driver)
-     sym53c8xx=irqm:0x20   (for the sym53c8xx driver)
-
-If this does not fix the problem, then you may want to check how all other 
-drivers are requesting the IRQ and report the problem. Note that if at least 
-a single driver does not request the IRQ with the IRQF_SHARED flag (share IRQ),
-then the request of the IRQ obviously will not succeed for all the drivers.
-
 15. SCSI problem troubleshooting
 
 15.1 Problem tracking
index 0810132772a87de851d36ab56a08a459c4ba5c5a..0e0322bf0020d125d4695f47ec47c19bc12dcf17 100644 (file)
@@ -107,10 +107,6 @@ produced errors and started to corrupt my disks. So don't do that! A 37.50
 MHz PCI bus works for me, though, but I don't recommend using higher clocks
 than the 33.33 MHz being in the PCI spec.
 
-If you want to share the IRQ with another device and the driver refuses to
-do so, you might succeed with changing the DC390_IRQ type in tmscsim.c to 
-IRQF_SHARED | IRQF_DISABLED.
-
 
 3.Features
 ----------
index d29734bff28c5beb38bf304b5b5d02903044d691..d1824b399b2d1d79059231a52e2552949d9ba24f 100644 (file)
@@ -342,12 +342,11 @@ SPI protocol drivers somewhat resemble platform device drivers:
                .driver = {
                        .name           = "CHIP",
                        .owner          = THIS_MODULE,
+                       .pm             = &CHIP_pm_ops,
                },
 
                .probe          = CHIP_probe,
                .remove         = CHIP_remove,
-               .suspend        = CHIP_suspend,
-               .resume         = CHIP_resume,
        };
 
 The driver core will automatically attempt to bind this driver to any SPI
index 3a2f9d59edabf9d7858a1fff178fc722971dafd3..94f574b0fdb25890c3e3f64a23622ee0e8fb3bea 100644 (file)
@@ -15,6 +15,7 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <getopt.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
@@ -34,24 +35,79 @@ static uint32_t mode;
 static uint8_t bits = 8;
 static uint32_t speed = 500000;
 static uint16_t delay;
+static int verbose;
 
-static void transfer(int fd)
+uint8_t default_tx[] = {
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xF0, 0x0D,
+};
+
+uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, };
+char *input_tx;
+
+static void hex_dump(const void *src, size_t length, size_t line_size, char *prefix)
+{
+       int i = 0;
+       const unsigned char *address = src;
+       const unsigned char *line = address;
+       unsigned char c;
+
+       printf("%s | ", prefix);
+       while (length-- > 0) {
+               printf("%02X ", *address++);
+               if (!(++i % line_size) || (length == 0 && i % line_size)) {
+                       if (length == 0) {
+                               while (i++ % line_size)
+                                       printf("__ ");
+                       }
+                       printf(" | ");  /* right close */
+                       while (line < address) {
+                               c = *line++;
+                               printf("%c", (c < 33 || c == 255) ? 0x2E : c);
+                       }
+                       printf("\n");
+                       if (length > 0)
+                               printf("%s | ", prefix);
+               }
+       }
+}
+
+/*
+ *  Unescape - process hexadecimal escape character
+ *      converts shell input "\x23" -> 0x23
+ */
+int unespcape(char *_dst, char *_src, size_t len)
+{
+       int ret = 0;
+       char *src = _src;
+       char *dst = _dst;
+       unsigned int ch;
+
+       while (*src) {
+               if (*src == '\\' && *(src+1) == 'x') {
+                       sscanf(src + 2, "%2x", &ch);
+                       src += 4;
+                       *dst++ = (unsigned char)ch;
+               } else {
+                       *dst++ = *src++;
+               }
+               ret++;
+       }
+       return ret;
+}
+
+static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
 {
        int ret;
-       uint8_t tx[] = {
-               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-               0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
-               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-               0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD,
-               0xF0, 0x0D,
-       };
-       uint8_t rx[ARRAY_SIZE(tx)] = {0, };
+
        struct spi_ioc_transfer tr = {
                .tx_buf = (unsigned long)tx,
                .rx_buf = (unsigned long)rx,
-               .len = ARRAY_SIZE(tx),
+               .len = len,
                .delay_usecs = delay,
                .speed_hz = speed,
                .bits_per_word = bits,
@@ -76,12 +132,9 @@ static void transfer(int fd)
        if (ret < 1)
                pabort("can't send spi message");
 
-       for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
-               if (!(ret % 6))
-                       puts("");
-               printf("%.2X ", rx[ret]);
-       }
-       puts("");
+       if (verbose)
+               hex_dump(tx, len, 32, "TX");
+       hex_dump(rx, len, 32, "RX");
 }
 
 static void print_usage(const char *prog)
@@ -97,6 +150,8 @@ static void print_usage(const char *prog)
             "  -L --lsb      least significant bit first\n"
             "  -C --cs-high  chip select active high\n"
             "  -3 --3wire    SI/SO signals shared\n"
+            "  -v --verbose  Verbose (show tx buffer)\n"
+            "  -p            Send data (e.g. \"1234\\xde\\xad\")\n"
             "  -N --no-cs    no chip select\n"
             "  -R --ready    slave pulls low to pause\n"
             "  -2 --dual     dual transfer\n"
@@ -121,12 +176,13 @@ static void parse_opts(int argc, char *argv[])
                        { "no-cs",   0, 0, 'N' },
                        { "ready",   0, 0, 'R' },
                        { "dual",    0, 0, '2' },
+                       { "verbose", 0, 0, 'v' },
                        { "quad",    0, 0, '4' },
                        { NULL, 0, 0, 0 },
                };
                int c;
 
-               c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24", lopts, NULL);
+               c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24p:v", lopts, NULL);
 
                if (c == -1)
                        break;
@@ -165,9 +221,15 @@ static void parse_opts(int argc, char *argv[])
                case 'N':
                        mode |= SPI_NO_CS;
                        break;
+               case 'v':
+                       verbose = 1;
+                       break;
                case 'R':
                        mode |= SPI_READY;
                        break;
+               case 'p':
+                       input_tx = optarg;
+                       break;
                case '2':
                        mode |= SPI_TX_DUAL;
                        break;
@@ -191,6 +253,9 @@ int main(int argc, char *argv[])
 {
        int ret = 0;
        int fd;
+       uint8_t *tx;
+       uint8_t *rx;
+       int size;
 
        parse_opts(argc, argv);
 
@@ -235,7 +300,17 @@ int main(int argc, char *argv[])
        printf("bits per word: %d\n", bits);
        printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
 
-       transfer(fd);
+       if (input_tx) {
+               size = strlen(input_tx+1);
+               tx = malloc(size);
+               rx = malloc(size);
+               size = unespcape((char *)tx, input_tx, size);
+               transfer(fd, tx, rx, size);
+               free(rx);
+               free(tx);
+       } else {
+               transfer(fd, default_tx, default_rx, sizeof(default_tx));
+       }
 
        close(fd);
 
index 02f8331edb8bfd54bf39b2ae150609ae158f2686..58d0ac4df94684d540f5afea73d4039726e6a4be 100644 (file)
@@ -81,6 +81,16 @@ format in the sign-off area:
      git cherry-pick fd21073
      git cherry-pick <this commit>
 
+Also, some patches may have kernel version prerequisites.  This can be
+specified in the following format in the sign-off area:
+
+     Cc:  <stable@vger.kernel.org> # 3.3.x-
+
+   The tag has the meaning of:
+     git cherry-pick <this commit>
+
+   For each "-stable" tree starting with the specified version.
+
 Following the submission:
 
  - The sender will receive an ACK when the patch has been accepted into the
index 83ab25660fc961de2d498b3a56724ecc09f950b2..99d7eb3a14164f68ea20c8790db4c138dcb55be9 100644 (file)
@@ -77,12 +77,14 @@ show up in /proc/sys/kernel:
 - shmmax                      [ sysv ipc ]
 - shmmni
 - softlockup_all_cpu_backtrace
+- soft_watchdog
 - stop-a                      [ SPARC only ]
 - sysrq                       ==> Documentation/sysrq.txt
 - sysctl_writes_strict
 - tainted
 - threads-max
 - unknown_nmi_panic
+- watchdog
 - watchdog_thresh
 - version
 
@@ -417,16 +419,23 @@ successful IPC object allocation.
 
 nmi_watchdog:
 
-Enables/Disables the NMI watchdog on x86 systems. When the value is
-non-zero the NMI watchdog is enabled and will continuously test all
-online cpus to determine whether or not they are still functioning
-properly. Currently, passing "nmi_watchdog=" parameter at boot time is
-required for this function to work.
+This parameter can be used to control the NMI watchdog
+(i.e. the hard lockup detector) on x86 systems.
 
-If LAPIC NMI watchdog method is in use (nmi_watchdog=2 kernel
-parameter), the NMI watchdog shares registers with oprofile. By
-disabling the NMI watchdog, oprofile may have more registers to
-utilize.
+   0 - disable the hard lockup detector
+   1 - enable the hard lockup detector
+
+The hard lockup detector monitors each CPU for its ability to respond to
+timer interrupts. The mechanism utilizes CPU performance counter registers
+that are programmed to generate Non-Maskable Interrupts (NMIs) periodically
+while a CPU is busy. Hence, the alternative name 'NMI watchdog'.
+
+The NMI watchdog is disabled by default if the kernel is running as a guest
+in a KVM virtual machine. This default can be overridden by adding
+
+   nmi_watchdog=1
+
+to the guest kernel command line (see Documentation/kernel-parameters.txt).
 
 ==============================================================
 
@@ -816,6 +825,22 @@ NMI.
 
 ==============================================================
 
+soft_watchdog
+
+This parameter can be used to control the soft lockup detector.
+
+   0 - disable the soft lockup detector
+   1 - enable the soft lockup detector
+
+The soft lockup detector monitors CPUs for threads that are hogging the CPUs
+without rescheduling voluntarily, and thus prevent the 'watchdog/N' threads
+from running. The mechanism depends on the CPUs ability to respond to timer
+interrupts which are needed for the 'watchdog/N' threads to be woken up by
+the watchdog timer function, otherwise the NMI watchdog - if enabled - can
+detect a hard lockup condition.
+
+==============================================================
+
 tainted:
 
 Non-zero if the kernel has been tainted.  Numeric values, which
@@ -858,6 +883,25 @@ example.  If a system hangs up, try pressing the NMI switch.
 
 ==============================================================
 
+watchdog:
+
+This parameter can be used to disable or enable the soft lockup detector
+_and_ the NMI watchdog (i.e. the hard lockup detector) at the same time.
+
+   0 - disable both lockup detectors
+   1 - enable both lockup detectors
+
+The soft lockup detector and the NMI watchdog can also be disabled or
+enabled individually, using the soft_watchdog and nmi_watchdog parameters.
+If the watchdog parameter is read, for example by executing
+
+   cat /proc/sys/kernel/watchdog
+
+the output of this command (0 or 1) shows the logical OR of soft_watchdog
+and nmi_watchdog.
+
+==============================================================
+
 watchdog_thresh:
 
 This value can be used to control the frequency of hrtimer and NMI
index cca122f25120b310fc1816b342d61adb29f832c6..6eaf576294f3bbd0d4d7d992fc17522edc723d48 100644 (file)
@@ -158,13 +158,9 @@ not come for free:
        to the need to inform kernel subsystems (such as RCU) about
        the change in mode.
 
-3.     POSIX CPU timers on adaptive-tick CPUs may miss their deadlines
-       (perhaps indefinitely) because they currently rely on
-       scheduling-tick interrupts.  This will likely be fixed in
-       one of two ways: (1) Prevent CPUs with POSIX CPU timers from
-       entering adaptive-tick mode, or (2) Use hrtimers or other
-       adaptive-ticks-immune mechanism to cause the POSIX CPU timer to
-       fire properly.
+3.     POSIX CPU timers prevent CPUs from entering adaptive-tick mode.
+       Real-time applications needing to take actions based on CPU time
+       consumption need to use other means of doing so.
 
 4.     If there are more perf events pending than the hardware can
        accommodate, they are normally round-robined so as to collect
index 995c8bca40e2e30eca0fe4f45139b8130c879658..3f848c1f2940d279b111945e0256140c8f71329e 100644 (file)
@@ -69,3 +69,24 @@ cat /sys/kernel/debug/ci_hdrc.0/registers
 ----------------------
 "On-The-Go and Embedded Host Supplement to the USB Revision 2.0 Specification
 July 27, 2012 Revision 2.0 version 1.1a"
+
+2. How to enable USB as system wakeup source
+-----------------------------------
+Below is the example for how to enable USB as system wakeup source
+at imx6 platform.
+
+2.1 Enable core's wakeup
+echo enabled > /sys/bus/platform/devices/ci_hdrc.0/power/wakeup
+2.2 Enable glue layer's wakeup
+echo enabled > /sys/bus/platform/devices/2184000.usb/power/wakeup
+2.3 Enable PHY's wakeup (optional)
+echo enabled > /sys/bus/platform/devices/20c9000.usbphy/power/wakeup
+2.4 Enable roothub's wakeup
+echo enabled > /sys/bus/usb/devices/usb1/power/wakeup
+2.5 Enable related device's wakeup
+echo enabled > /sys/bus/usb/devices/1-1/power/wakeup
+
+If the system has only one usb port, and you want usb wakeup at this port, you
+can use below script to enable usb wakeup.
+for i in $(find /sys -name wakeup | grep usb);do echo enabled > $i;done;
+
index 076ac7ba7f935e03d6b37bd214ad53fa36ff472b..f45b2bf4b41dead903254b2c1ecc4d382505f1a3 100644 (file)
@@ -19,6 +19,7 @@ provided by gadgets.
 16. UAC1 function
 17. UAC2 function
 18. UVC function
+19. PRINTER function
 
 
 1. ACM function
@@ -726,3 +727,49 @@ with these patches:
 http://www.spinics.net/lists/linux-usb/msg99220.html
 
 host: luvcview -f yuv
+
+19. PRINTER function
+====================
+
+The function is provided by usb_f_printer.ko module.
+
+Function-specific configfs interface
+------------------------------------
+
+The function name to use when creating the function directory is "printer".
+The printer function provides these attributes in its function directory:
+
+       pnp_string      - Data to be passed to the host in pnp string
+       q_len           - Number of requests per endpoint
+
+Testing the PRINTER function
+----------------------------
+
+The most basic testing:
+
+device: run the gadget
+# ls -l /devices/virtual/usb_printer_gadget/
+
+should show g_printer<number>.
+
+If udev is active, then /dev/g_printer<number> should appear automatically.
+
+host:
+
+If udev is active, then e.g. /dev/usb/lp0 should appear.
+
+host->device transmission:
+
+device:
+# cat /dev/g_printer<number>
+host:
+# cat > /dev/usb/lp0
+
+device->host transmission:
+
+# cat > /dev/g_printer<number>
+host:
+# cat /dev/usb/lp0
+
+More advanced testing can be done with the prn_example
+described in Documentation/usb/gadget-printer.txt.
index b112efc816f155093ef80815db788a2cdddf0ecc..bc9f6fe44e27614c2f26f155385fe0d5d13d2e3b 100644 (file)
@@ -997,7 +997,7 @@ for vm-wide capabilities.
 4.38 KVM_GET_MP_STATE
 
 Capability: KVM_CAP_MP_STATE
-Architectures: x86, s390
+Architectures: x86, s390, arm, arm64
 Type: vcpu ioctl
 Parameters: struct kvm_mp_state (out)
 Returns: 0 on success; -1 on error
@@ -1011,7 +1011,7 @@ uniprocessor guests).
 
 Possible values are:
 
- - KVM_MP_STATE_RUNNABLE:        the vcpu is currently running [x86]
+ - KVM_MP_STATE_RUNNABLE:        the vcpu is currently running [x86,arm/arm64]
  - KVM_MP_STATE_UNINITIALIZED:   the vcpu is an application processor (AP)
                                  which has not yet received an INIT signal [x86]
  - KVM_MP_STATE_INIT_RECEIVED:   the vcpu has received an INIT signal, and is
@@ -1020,7 +1020,7 @@ Possible values are:
                                  is waiting for an interrupt [x86]
  - KVM_MP_STATE_SIPI_RECEIVED:   the vcpu has just received a SIPI (vector
                                  accessible via KVM_GET_VCPU_EVENTS) [x86]
- - KVM_MP_STATE_STOPPED:         the vcpu is stopped [s390]
+ - KVM_MP_STATE_STOPPED:         the vcpu is stopped [s390,arm/arm64]
  - KVM_MP_STATE_CHECK_STOP:      the vcpu is in a special error state [s390]
  - KVM_MP_STATE_OPERATING:       the vcpu is operating (running or halted)
                                  [s390]
@@ -1031,11 +1031,15 @@ On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
 in-kernel irqchip, the multiprocessing state must be maintained by userspace on
 these architectures.
 
+For arm/arm64:
+
+The only states that are valid are KVM_MP_STATE_STOPPED and
+KVM_MP_STATE_RUNNABLE which reflect if the vcpu is paused or not.
 
 4.39 KVM_SET_MP_STATE
 
 Capability: KVM_CAP_MP_STATE
-Architectures: x86, s390
+Architectures: x86, s390, arm, arm64
 Type: vcpu ioctl
 Parameters: struct kvm_mp_state (in)
 Returns: 0 on success; -1 on error
@@ -1047,6 +1051,10 @@ On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
 in-kernel irqchip, the multiprocessing state must be maintained by userspace on
 these architectures.
 
+For arm/arm64:
+
+The only states that are valid are KVM_MP_STATE_STOPPED and
+KVM_MP_STATE_RUNNABLE which reflect if the vcpu should be paused or not.
 
 4.40 KVM_SET_IDENTITY_MAP_ADDR
 
@@ -1967,15 +1975,25 @@ registers, find a list below:
   MIPS  | KVM_REG_MIPS_CP0_STATUS       | 32
   MIPS  | KVM_REG_MIPS_CP0_CAUSE        | 32
   MIPS  | KVM_REG_MIPS_CP0_EPC          | 64
+  MIPS  | KVM_REG_MIPS_CP0_PRID         | 32
   MIPS  | KVM_REG_MIPS_CP0_CONFIG       | 32
   MIPS  | KVM_REG_MIPS_CP0_CONFIG1      | 32
   MIPS  | KVM_REG_MIPS_CP0_CONFIG2      | 32
   MIPS  | KVM_REG_MIPS_CP0_CONFIG3      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG4      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG5      | 32
   MIPS  | KVM_REG_MIPS_CP0_CONFIG7      | 32
   MIPS  | KVM_REG_MIPS_CP0_ERROREPC     | 64
   MIPS  | KVM_REG_MIPS_COUNT_CTL        | 64
   MIPS  | KVM_REG_MIPS_COUNT_RESUME     | 64
   MIPS  | KVM_REG_MIPS_COUNT_HZ         | 64
+  MIPS  | KVM_REG_MIPS_FPR_32(0..31)    | 32
+  MIPS  | KVM_REG_MIPS_FPR_64(0..31)    | 64
+  MIPS  | KVM_REG_MIPS_VEC_128(0..31)   | 128
+  MIPS  | KVM_REG_MIPS_FCR_IR           | 32
+  MIPS  | KVM_REG_MIPS_FCR_CSR          | 32
+  MIPS  | KVM_REG_MIPS_MSA_IR           | 32
+  MIPS  | KVM_REG_MIPS_MSA_CSR          | 32
 
 ARM registers are mapped using the lower 32 bits.  The upper 16 of that
 is the register group type, or coprocessor number:
@@ -2029,6 +2047,25 @@ patterns depending on whether they're 32-bit or 64-bit registers:
 MIPS KVM control registers (see above) have the following id bit patterns:
   0x7030 0000 0002 <reg:16>
 
+MIPS FPU registers (see KVM_REG_MIPS_FPR_{32,64}() above) have the following
+id bit patterns depending on the size of the register being accessed. They are
+always accessed according to the current guest FPU mode (Status.FR and
+Config5.FRE), i.e. as the guest would see them, and they become unpredictable
+if the guest FPU mode is changed. MIPS SIMD Architecture (MSA) vector
+registers (see KVM_REG_MIPS_VEC_128() above) have similar patterns as they
+overlap the FPU registers:
+  0x7020 0000 0003 00 <0:3> <reg:5> (32-bit FPU registers)
+  0x7030 0000 0003 00 <0:3> <reg:5> (64-bit FPU registers)
+  0x7040 0000 0003 00 <0:3> <reg:5> (128-bit MSA vector registers)
+
+MIPS FPU control registers (see KVM_REG_MIPS_FCR_{IR,CSR} above) have the
+following id bit patterns:
+  0x7020 0000 0003 01 <0:3> <reg:5>
+
+MIPS MSA control registers (see KVM_REG_MIPS_MSA_{IR,CSR} above) have the
+following id bit patterns:
+  0x7020 0000 0003 02 <0:3> <reg:5>
+
 
 4.69 KVM_GET_ONE_REG
 
@@ -2234,7 +2271,7 @@ into the hash PTE second double word).
 4.75 KVM_IRQFD
 
 Capability: KVM_CAP_IRQFD
-Architectures: x86 s390
+Architectures: x86 s390 arm arm64
 Type: vm ioctl
 Parameters: struct kvm_irqfd (in)
 Returns: 0 on success, -1 on error
@@ -2260,6 +2297,10 @@ Note that closing the resamplefd is not sufficient to disable the
 irqfd.  The KVM_IRQFD_FLAG_RESAMPLE is only necessary on assignment
 and need not be specified with KVM_IRQFD_FLAG_DEASSIGN.
 
+On ARM/ARM64, the gsi field in the kvm_irqfd struct specifies the Shared
+Peripheral Interrupt (SPI) index, such that the GIC interrupt ID is
+given by gsi + 32.
+
 4.76 KVM_PPC_ALLOCATE_HTAB
 
 Capability: KVM_CAP_PPC_ALLOC_HTAB
@@ -2716,6 +2757,227 @@ The fields in each entry are defined as follows:
    eax, ebx, ecx, edx: the values returned by the cpuid instruction for
          this function/index combination
 
+4.89 KVM_S390_MEM_OP
+
+Capability: KVM_CAP_S390_MEM_OP
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_mem_op (in)
+Returns: = 0 on success,
+         < 0 on generic error (e.g. -EFAULT or -ENOMEM),
+         > 0 if an exception occurred while walking the page tables
+
+Read or write data from/to the logical (virtual) memory of a VPCU.
+
+Parameters are specified via the following structure:
+
+struct kvm_s390_mem_op {
+       __u64 gaddr;            /* the guest address */
+       __u64 flags;            /* flags */
+       __u32 size;             /* amount of bytes */
+       __u32 op;               /* type of operation */
+       __u64 buf;              /* buffer in userspace */
+       __u8 ar;                /* the access register number */
+       __u8 reserved[31];      /* should be set to 0 */
+};
+
+The type of operation is specified in the "op" field. It is either
+KVM_S390_MEMOP_LOGICAL_READ for reading from logical memory space or
+KVM_S390_MEMOP_LOGICAL_WRITE for writing to logical memory space. The
+KVM_S390_MEMOP_F_CHECK_ONLY flag can be set in the "flags" field to check
+whether the corresponding memory access would create an access exception
+(without touching the data in the memory at the destination). In case an
+access exception occurred while walking the MMU tables of the guest, the
+ioctl returns a positive error number to indicate the type of exception.
+This exception is also raised directly at the corresponding VCPU if the
+flag KVM_S390_MEMOP_F_INJECT_EXCEPTION is set in the "flags" field.
+
+The start address of the memory region has to be specified in the "gaddr"
+field, and the length of the region in the "size" field. "buf" is the buffer
+supplied by the userspace application where the read data should be written
+to for KVM_S390_MEMOP_LOGICAL_READ, or where the data that should be written
+is stored for a KVM_S390_MEMOP_LOGICAL_WRITE. "buf" is unused and can be NULL
+when KVM_S390_MEMOP_F_CHECK_ONLY is specified. "ar" designates the access
+register number to be used.
+
+The "reserved" field is meant for future extensions. It is not used by
+KVM with the currently defined set of flags.
+
+4.90 KVM_S390_GET_SKEYS
+
+Capability: KVM_CAP_S390_SKEYS
+Architectures: s390
+Type: vm ioctl
+Parameters: struct kvm_s390_skeys
+Returns: 0 on success, KVM_S390_GET_KEYS_NONE if guest is not using storage
+         keys, negative value on error
+
+This ioctl is used to get guest storage key values on the s390
+architecture. The ioctl takes parameters via the kvm_s390_skeys struct.
+
+struct kvm_s390_skeys {
+       __u64 start_gfn;
+       __u64 count;
+       __u64 skeydata_addr;
+       __u32 flags;
+       __u32 reserved[9];
+};
+
+The start_gfn field is the number of the first guest frame whose storage keys
+you want to get.
+
+The count field is the number of consecutive frames (starting from start_gfn)
+whose storage keys to get. The count field must be at least 1 and the maximum
+allowed value is defined as KVM_S390_SKEYS_ALLOC_MAX. Values outside this range
+will cause the ioctl to return -EINVAL.
+
+The skeydata_addr field is the address to a buffer large enough to hold count
+bytes. This buffer will be filled with storage key data by the ioctl.
+
+4.91 KVM_S390_SET_SKEYS
+
+Capability: KVM_CAP_S390_SKEYS
+Architectures: s390
+Type: vm ioctl
+Parameters: struct kvm_s390_skeys
+Returns: 0 on success, negative value on error
+
+This ioctl is used to set guest storage key values on the s390
+architecture. The ioctl takes parameters via the kvm_s390_skeys struct.
+See section on KVM_S390_GET_SKEYS for struct definition.
+
+The start_gfn field is the number of the first guest frame whose storage keys
+you want to set.
+
+The count field is the number of consecutive frames (starting from start_gfn)
+whose storage keys to get. The count field must be at least 1 and the maximum
+allowed value is defined as KVM_S390_SKEYS_ALLOC_MAX. Values outside this range
+will cause the ioctl to return -EINVAL.
+
+The skeydata_addr field is the address to a buffer containing count bytes of
+storage keys. Each byte in the buffer will be set as the storage key for a
+single frame starting at start_gfn for count frames.
+
+Note: If any architecturally invalid key value is found in the given data then
+the ioctl will return -EINVAL.
+
+4.92 KVM_S390_IRQ
+
+Capability: KVM_CAP_S390_INJECT_IRQ
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_irq (in)
+Returns: 0 on success, -1 on error
+Errors:
+  EINVAL: interrupt type is invalid
+          type is KVM_S390_SIGP_STOP and flag parameter is invalid value
+          type is KVM_S390_INT_EXTERNAL_CALL and code is bigger
+            than the maximum of VCPUs
+  EBUSY:  type is KVM_S390_SIGP_SET_PREFIX and vcpu is not stopped
+          type is KVM_S390_SIGP_STOP and a stop irq is already pending
+          type is KVM_S390_INT_EXTERNAL_CALL and an external call interrupt
+            is already pending
+
+Allows to inject an interrupt to the guest.
+
+Using struct kvm_s390_irq as a parameter allows
+to inject additional payload which is not
+possible via KVM_S390_INTERRUPT.
+
+Interrupt parameters are passed via kvm_s390_irq:
+
+struct kvm_s390_irq {
+       __u64 type;
+       union {
+               struct kvm_s390_io_info io;
+               struct kvm_s390_ext_info ext;
+               struct kvm_s390_pgm_info pgm;
+               struct kvm_s390_emerg_info emerg;
+               struct kvm_s390_extcall_info extcall;
+               struct kvm_s390_prefix_info prefix;
+               struct kvm_s390_stop_info stop;
+               struct kvm_s390_mchk_info mchk;
+               char reserved[64];
+       } u;
+};
+
+type can be one of the following:
+
+KVM_S390_SIGP_STOP - sigp stop; parameter in .stop
+KVM_S390_PROGRAM_INT - program check; parameters in .pgm
+KVM_S390_SIGP_SET_PREFIX - sigp set prefix; parameters in .prefix
+KVM_S390_RESTART - restart; no parameters
+KVM_S390_INT_CLOCK_COMP - clock comparator interrupt; no parameters
+KVM_S390_INT_CPU_TIMER - CPU timer interrupt; no parameters
+KVM_S390_INT_EMERGENCY - sigp emergency; parameters in .emerg
+KVM_S390_INT_EXTERNAL_CALL - sigp external call; parameters in .extcall
+KVM_S390_MCHK - machine check interrupt; parameters in .mchk
+
+
+Note that the vcpu ioctl is asynchronous to vcpu execution.
+
+4.94 KVM_S390_GET_IRQ_STATE
+
+Capability: KVM_CAP_S390_IRQ_STATE
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_irq_state (out)
+Returns: >= number of bytes copied into buffer,
+         -EINVAL if buffer size is 0,
+         -ENOBUFS if buffer size is too small to fit all pending interrupts,
+         -EFAULT if the buffer address was invalid
+
+This ioctl allows userspace to retrieve the complete state of all currently
+pending interrupts in a single buffer. Use cases include migration
+and introspection. The parameter structure contains the address of a
+userspace buffer and its length:
+
+struct kvm_s390_irq_state {
+       __u64 buf;
+       __u32 flags;
+       __u32 len;
+       __u32 reserved[4];
+};
+
+Userspace passes in the above struct and for each pending interrupt a
+struct kvm_s390_irq is copied to the provided buffer.
+
+If -ENOBUFS is returned the buffer provided was too small and userspace
+may retry with a bigger buffer.
+
+4.95 KVM_S390_SET_IRQ_STATE
+
+Capability: KVM_CAP_S390_IRQ_STATE
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_irq_state (in)
+Returns: 0 on success,
+         -EFAULT if the buffer address was invalid,
+         -EINVAL for an invalid buffer length (see below),
+         -EBUSY if there were already interrupts pending,
+         errors occurring when actually injecting the
+          interrupt. See KVM_S390_IRQ.
+
+This ioctl allows userspace to set the complete state of all cpu-local
+interrupts currently pending for the vcpu. It is intended for restoring
+interrupt state after a migration. The input parameter is a userspace buffer
+containing a struct kvm_s390_irq_state:
+
+struct kvm_s390_irq_state {
+       __u64 buf;
+       __u32 len;
+       __u32 pad;
+};
+
+The userspace memory referenced by buf contains a struct kvm_s390_irq
+for each interrupt to be injected into the guest.
+If one of the interrupts could not be injected for some reason the
+ioctl aborts.
+
+len must be a multiple of sizeof(struct kvm_s390_irq). It must be > 0
+and it must not exceed (max_vcpus + 32) * sizeof(struct kvm_s390_irq),
+which is the maximum number of possibly pending cpu-local interrupts.
+
 5. The kvm_run structure
 ------------------------
 
@@ -3189,6 +3451,31 @@ Parameters: none
 This capability enables the in-kernel irqchip for s390. Please refer to
 "4.24 KVM_CREATE_IRQCHIP" for details.
 
+6.9 KVM_CAP_MIPS_FPU
+
+Architectures: mips
+Target: vcpu
+Parameters: args[0] is reserved for future use (should be 0).
+
+This capability allows the use of the host Floating Point Unit by the guest. It
+allows the Config1.FP bit to be set to enable the FPU in the guest. Once this is
+done the KVM_REG_MIPS_FPR_* and KVM_REG_MIPS_FCR_* registers can be accessed
+(depending on the current guest FPU register mode), and the Status.FR,
+Config5.FRE bits are accessible via the KVM API and also from the guest,
+depending on them being supported by the FPU.
+
+6.10 KVM_CAP_MIPS_MSA
+
+Architectures: mips
+Target: vcpu
+Parameters: args[0] is reserved for future use (should be 0).
+
+This capability allows the use of the MIPS SIMD Architecture (MSA) by the guest.
+It allows the Config3.MSAP bit to be set to enable the use of MSA by the guest.
+Once this is done the KVM_REG_MIPS_VEC_* and KVM_REG_MIPS_MSA_* registers can be
+accessed, and the Config5.MSAEn bit is accessible via the KVM API and also from
+the guest.
+
 7. Capabilities that can be enabled on VMs
 ------------------------------------------
 
@@ -3248,3 +3535,41 @@ All other orders will be handled completely in user space.
 Only privileged operation exceptions will be checked for in the kernel (or even
 in the hardware prior to interception). If this capability is not enabled, the
 old way of handling SIGP orders is used (partially in kernel and user space).
+
+7.3 KVM_CAP_S390_VECTOR_REGISTERS
+
+Architectures: s390
+Parameters: none
+Returns: 0 on success, negative value on error
+
+Allows use of the vector registers introduced with z13 processor, and
+provides for the synchronization between host and user space.  Will
+return -EINVAL if the machine does not support vectors.
+
+7.4 KVM_CAP_S390_USER_STSI
+
+Architectures: s390
+Parameters: none
+
+This capability allows post-handlers for the STSI instruction. After
+initial handling in the kernel, KVM exits to user space with
+KVM_EXIT_S390_STSI to allow user space to insert further data.
+
+Before exiting to userspace, kvm handlers should fill in s390_stsi field of
+vcpu->run:
+struct {
+       __u64 addr;
+       __u8 ar;
+       __u8 reserved;
+       __u8 fc;
+       __u8 sel1;
+       __u16 sel2;
+} s390_stsi;
+
+@addr - guest address of STSI SYSIB
+@fc   - function code
+@sel1 - selector 1
+@sel2 - selector 2
+@ar   - access register number
+
+KVM handlers should exit to userspace with rc = -EREMOTE.
index 4ceef53164b0289237238c3cf29d83e38e5d34de..d1ad9d5cae467ceb2c1169ce8b53d70078aedf27 100644 (file)
@@ -27,6 +27,9 @@ Groups:
     Copies all floating interrupts into a buffer provided by userspace.
     When the buffer is too small it returns -ENOMEM, which is the indication
     for userspace to try again with a bigger buffer.
+    -ENOBUFS is returned when the allocation of a kernelspace buffer has
+    failed.
+    -EFAULT is returned when copying data to userspace failed.
     All interrupts remain pending, i.e. are not deleted from the list of
     currently pending interrupts.
     attr->addr contains the userspace address of the buffer into which all
index 01d76282444ee46a9658c119f6a33d99864f0c15..e4b49df7a04844b75979421e445374aa8ca03e59 100644 (file)
@@ -28,9 +28,7 @@ IMPLEMENTATION OVERVIEW
 A cleancache "backend" that provides transcendent memory registers itself
 to the kernel's cleancache "frontend" by calling cleancache_register_ops,
 passing a pointer to a cleancache_ops structure with funcs set appropriately.
-Note that cleancache_register_ops returns the previous settings so that
-chaining can be performed if desired. The functions provided must conform to
-certain semantics as follows:
+The functions provided must conform to certain semantics as follows:
 
 Most important, cleancache is "ephemeral".  Pages which are copied into
 cleancache have an indefinite lifetime which is completely unknowable
index 744f82f86c5818f6837e1a3c072fd2bffd09ab54..86cb4624fc5ac8bf253b692360ca0192d02f80f9 100644 (file)
@@ -317,7 +317,7 @@ If the VMA passes some filtering as described in "Filtering Special Vmas"
 below, mlock_fixup() will attempt to merge the VMA with its neighbors or split
 off a subset of the VMA if the range does not cover the entire VMA.  Once the
 VMA has been merged or split or neither, mlock_fixup() will call
-__mlock_vma_pages_range() to fault in the pages via get_user_pages() and to
+populate_vma_page_range() to fault in the pages via get_user_pages() and to
 mark the pages as mlocked via mlock_vma_page().
 
 Note that the VMA being mlocked might be mapped with PROT_NONE.  In this case,
@@ -327,7 +327,7 @@ fault path or in vmscan.
 
 Also note that a page returned by get_user_pages() could be truncated or
 migrated out from under us, while we're trying to mlock it.  To detect this,
-__mlock_vma_pages_range() checks page_mapping() after acquiring the page lock.
+populate_vma_page_range() checks page_mapping() after acquiring the page lock.
 If the page is still associated with its mapping, we'll go ahead and call
 mlock_vma_page().  If the mapping is gone, we just unlock the page and move on.
 In the worst case, this will result in a page mapped in a VM_LOCKED VMA
@@ -392,7 +392,7 @@ ignored for munlock.
 
 If the VMA is VM_LOCKED, mlock_fixup() again attempts to merge or split off the
 specified range.  The range is then munlocked via the function
-__mlock_vma_pages_range() - the same function used to mlock a VMA range -
+populate_vma_page_range() - the same function used to mlock a VMA range -
 passing a flag to indicate that munlock() is being performed.
 
 Because the VMA access protections could have been changed to PROT_NONE after
@@ -402,7 +402,7 @@ get_user_pages() was enhanced to accept a flag to ignore the permissions when
 fetching the pages - all of which should be resident as a result of previous
 mlocking.
 
-For munlock(), __mlock_vma_pages_range() unlocks individual pages by calling
+For munlock(), populate_vma_page_range() unlocks individual pages by calling
 munlock_vma_page().  munlock_vma_page() unconditionally clears the PG_mlocked
 flag using TestClearPageMlocked().  As with mlock_vma_page(),
 munlock_vma_page() use the Test*PageMlocked() function to handle the case where
@@ -463,21 +463,11 @@ populate the page table.
 
 To mlock a range of memory under the unevictable/mlock infrastructure, the
 mmap() handler and task address space expansion functions call
-mlock_vma_pages_range() specifying the vma and the address range to mlock.
-mlock_vma_pages_range() filters VMAs like mlock_fixup(), as described above in
-"Filtering Special VMAs".  It will clear the VM_LOCKED flag, which will have
-already been set by the caller, in filtered VMAs.  Thus these VMA's need not be
-visited for munlock when the region is unmapped.
-
-For "normal" VMAs, mlock_vma_pages_range() calls __mlock_vma_pages_range() to
-fault/allocate the pages and mlock them.  Again, like mlock_fixup(),
-mlock_vma_pages_range() downgrades the mmap semaphore to read mode before
-attempting to fault/allocate and mlock the pages and "upgrades" the semaphore
-back to write mode before returning.
-
-The callers of mlock_vma_pages_range() will have already added the memory range
+populate_vma_page_range() specifying the vma and the address range to mlock.
+
+The callers of populate_vma_page_range() will have already added the memory range
 to be mlocked to the task's "locked_vm".  To account for filtered VMAs,
-mlock_vma_pages_range() returns the number of pages NOT mlocked.  All of the
+populate_vma_page_range() returns the number of pages NOT mlocked.  All of the
 callers then subtract a non-negative return value from the task's locked_vm.  A
 negative return value represent an error - for example, from get_user_pages()
 attempting to fault in a VMA with PROT_NONE access.  In this case, we leave the
index a75e3adaa39da277fb89150fb1d31daf8d1296ef..88b85899d30953a6be096a9e045fcf54be3676b4 100644 (file)
@@ -406,6 +406,12 @@ Protocol:  2.00+
        - If 0, the protected-mode code is loaded at 0x10000.
        - If 1, the protected-mode code is loaded at 0x100000.
 
+  Bit 1 (kernel internal): ALSR_FLAG
+       - Used internally by the compressed kernel to communicate
+         KASLR status to kernel proper.
+         If 1, KASLR enabled.
+         If 0, KASLR disabled.
+
   Bit 5 (write): QUIET_FLAG
        - If 0, print early messages.
        - If 1, suppress early messages.
index c98757d0626f371b9c96d7f7e2d62469c4b48576..283d1145e6d8474a27f439dba841446822970810 100644 (file)
@@ -724,7 +724,7 @@ F:  staging/iio/trigger/iio-trig-bfin-timer.c
 
 ANDROID DRIVERS
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-M:     Arve HjønnevÃ¥g <arve@android.com>
+M:     Arve HjønnevÃ¥g <arve@android.com>
 M:     Riley Andrews <riandrews@android.com>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/gregkh/staging.git
 L:     devel@driverdev.osuosl.org
@@ -1468,6 +1468,8 @@ F:        drivers/clocksource/arm_global_timer.c
 F:     drivers/i2c/busses/i2c-st.c
 F:     drivers/media/rc/st_rc.c
 F:     drivers/mmc/host/sdhci-st.c
+F:     drivers/phy/phy-miphy28lp.c
+F:     drivers/phy/phy-miphy365x.c
 F:     drivers/phy/phy-stih407-usb.c
 F:     drivers/phy/phy-stih41x-usb.c
 F:     drivers/pinctrl/pinctrl-st.c
@@ -2518,7 +2520,7 @@ F:        Documentation/zh_CN/
 
 CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
 M:     Peter Chen <Peter.Chen@freescale.com>
-T:     git git://github.com/hzpeterchen/linux-usb.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/chipidea/
@@ -3144,12 +3146,15 @@ S:      Supported
 F:     Documentation/hwmon/da90??
 F:     drivers/gpio/gpio-da90??.c
 F:     drivers/hwmon/da90??-hwmon.c
+F:     drivers/iio/adc/da91??-*.c
 F:     drivers/input/misc/da90??_onkey.c
 F:     drivers/input/touchscreen/da9052_tsi.c
 F:     drivers/leds/leds-da90??.c
 F:     drivers/mfd/da903x.c
 F:     drivers/mfd/da90??-*.c
+F:     drivers/mfd/da91??-*.c
 F:     drivers/power/da9052-battery.c
+F:     drivers/power/da91??-*.c
 F:     drivers/regulator/da903x.c
 F:     drivers/regulator/da9???-regulator.[ch]
 F:     drivers/rtc/rtc-da90??.c
@@ -3159,6 +3164,7 @@ F:        include/linux/mfd/da903x.h
 F:     include/linux/mfd/da9052/
 F:     include/linux/mfd/da9055/
 F:     include/linux/mfd/da9063/
+F:     include/linux/mfd/da9150/
 F:     include/sound/da[79]*.h
 F:     sound/soc/codecs/da[79]*.[ch]
 
@@ -4170,6 +4176,12 @@ F:       sound/soc/fsl/fsl*
 F:     sound/soc/fsl/imx*
 F:     sound/soc/fsl/mpc8610_hpcd.c
 
+FREESCALE QORIQ MANAGEMENT COMPLEX DRIVER
+M:     J. German Rivera <German.Rivera@freescale.com>
+L:     linux-kernel@vger.kernel.org
+S:     Maintained
+F:     drivers/staging/fsl-mc/
+
 FREEVXFS FILESYSTEM
 M:     Christoph Hellwig <hch@infradead.org>
 W:     ftp://ftp.openlinux.org/pub/people/hch/vxfs
@@ -4332,10 +4344,10 @@ F:      scripts/get_maintainer.pl
 
 GFS2 FILE SYSTEM
 M:     Steven Whitehouse <swhiteho@redhat.com>
+M:     Bob Peterson <rpeterso@redhat.com>
 L:     cluster-devel@redhat.com
 W:     http://sources.redhat.com/cluster/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git
 S:     Supported
 F:     Documentation/filesystems/gfs2*.txt
 F:     fs/gfs2/
@@ -4955,6 +4967,7 @@ S:        Maintained
 F:     drivers/iio/
 F:     drivers/staging/iio/
 F:     include/linux/iio/
+F:     tools/iio/
 
 IKANOS/ADI EAGLE ADSL USB DRIVER
 M:     Matthieu Castet <castet.matthieu@free.fr>
@@ -5598,6 +5611,8 @@ S:        Supported
 F:     Documentation/*/kvm*.txt
 F:     Documentation/virtual/kvm/
 F:     arch/*/kvm/
+F:     arch/x86/kernel/kvm.c
+F:     arch/x86/kernel/kvmclock.c
 F:     arch/*/include/asm/kvm*
 F:     include/linux/kvm*
 F:     include/uapi/linux/kvm*
@@ -6571,10 +6586,8 @@ F:       drivers/mfd/
 F:     include/linux/mfd/
 
 MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
-M:     Chris Ball <chris@printf.net>
 M:     Ulf Hansson <ulf.hansson@linaro.org>
 L:     linux-mmc@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
 T:     git git://git.linaro.org/people/ulf.hansson/mmc.git
 S:     Maintained
 F:     drivers/mmc/
@@ -8566,6 +8579,7 @@ F:        include/uapi/linux/timex.h
 F:     kernel/time/clocksource.c
 F:     kernel/time/time*.c
 F:     kernel/time/ntp.c
+F:     tools/testing/selftests/timers/
 
 SC1200 WDT DRIVER
 M:     Zwane Mwaikambo <zwanem@gmail.com>
@@ -8674,10 +8688,8 @@ S:       Maintained
 F:     drivers/mmc/host/sdricoh_cs.c
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
-M:     Chris Ball <chris@printf.net>
 L:     linux-mmc@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
-S:     Maintained
+S:     Orphan
 F:     drivers/mmc/host/sdhci.*
 F:     drivers/mmc/host/sdhci-pltfm.[ch]
 
@@ -8693,18 +8705,12 @@ F:      include/linux/seccomp.h
 K:     \bsecure_computing
 K:     \bTIF_SECCOMP\b
 
-SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
-M:     Anton Vorontsov <anton@enomsg.org>
-L:     linuxppc-dev@lists.ozlabs.org
-L:     linux-mmc@vger.kernel.org
-S:     Maintained
-F:     drivers/mmc/host/sdhci-pltfm.[ch]
-
 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER
 M:     Ben Dooks <ben-linux@fluff.org>
+M:     Jaehoon Chung <jh80.chung@samsung.com>
 L:     linux-mmc@vger.kernel.org
 S:     Maintained
-F:     drivers/mmc/host/sdhci-s3c.c
+F:     drivers/mmc/host/sdhci-s3c*
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) ST SPEAR DRIVER
 M:     Viresh Kumar <viresh.linux@gmail.com>
@@ -9371,6 +9377,14 @@ 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>
+M:     Sudip Mukherjee <sudip@vectorindia.org>
+L:     linux-fbdev@vger.kernel.org
+S:     Maintained
+F:     drivers/staging/sm750fb/
+
 STAGING - SLICOSS
 M:     Lior Dotan <liodot@gmail.com>
 M:     Christopher Harrer <charrer@alacritech.com>
@@ -10142,6 +10156,12 @@ S:     Maintained
 F:     drivers/net/usb/cdc_*.c
 F:     include/uapi/linux/usb/cdc.h
 
+USB CHAOSKEY DRIVER
+M:     Keith Packard <keithp@keithp.com>
+L:     linux-usb@vger.kernel.org
+S:     Maintained
+F:     drivers/usb/misc/chaoskey.c
+
 USB CYPRESS C67X00 DRIVER
 M:     Peter Korsgaard <jacmet@sunsite.dk>
 L:     linux-usb@vger.kernel.org
@@ -10222,7 +10242,7 @@ F:      drivers/usb/host/ohci*
 
 USB OTG FSM (Finite State Machine)
 M:     Peter Chen <Peter.Chen@freescale.com>
-T:     git git://github.com/hzpeterchen/linux-usb.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/common/usb-otg-fsm.c
index 54430f933b628ca99bdbc1e2bf5dd2570ca0354c..9b76ce1e08bbb80d15e3f2ee4859157323a23ee0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 0
 SUBLEVEL = 0
-EXTRAVERSION = -rc7
+EXTRAVERSION =
 NAME = Hurr durr I'ma sheep
 
 # *DOCUMENTATION*
@@ -779,6 +779,7 @@ KBUILD_ARFLAGS := $(call ar-option,D)
 # check for 'asm goto'
 ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
        KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
+       KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO
 endif
 
 include $(srctree)/scripts/Makefile.kasan
index 05d7a8a458d5850c181e527c2039904c66239de5..e1068987bad1c6fef286d084ca245cafbe0a8934 100644 (file)
@@ -446,6 +446,9 @@ config HAVE_IRQ_TIME_ACCOUNTING
 config HAVE_ARCH_TRANSPARENT_HUGEPAGE
        bool
 
+config HAVE_ARCH_HUGE_VMAP
+       bool
+
 config HAVE_ARCH_SOFT_DIRTY
        bool
 
@@ -484,6 +487,18 @@ config HAVE_IRQ_EXIT_ON_IRQ_STACK
          This spares a stack switch and improves cache usage on softirq
          processing.
 
+config PGTABLE_LEVELS
+       int
+       default 2
+
+config ARCH_HAS_ELF_RANDOMIZE
+       bool
+       help
+         An architecture supports choosing randomized locations for
+         stack, mmap, brk, and ET_DYN. Defined functions:
+         - arch_mmap_rnd()
+         - arch_randomize_brk()
+
 #
 # ABI hall of shame
 #
index b7ff9a318c31c3f849c5a2223582132ebde83f72..bf9e9d3b379218b74aa2bf6506d62f7978f71abd 100644 (file)
@@ -76,6 +76,10 @@ config GENERIC_ISA_DMA
        bool
        default y
 
+config PGTABLE_LEVELS
+       int
+       default 3
+
 source "init/Kconfig"
 source "kernel/Kconfig.freezer"
 
index 98a1525fa164df0178fd4cb5fc0267129b2844e3..82f738e5d54cb85f5b77c21304fd590d1e5bbbc5 100644 (file)
@@ -338,6 +338,8 @@ common_init_pci(void)
 
                bus = pci_scan_root_bus(NULL, next_busno, alpha_mv.pci_ops,
                                        hose, &resources);
+               if (!bus)
+                       continue;
                hose->bus = bus;
                hose->need_domain_info = need_domain_info;
                next_busno = bus->busn_res.end + 1;
@@ -353,6 +355,11 @@ common_init_pci(void)
 
        pci_assign_unassigned_resources();
        pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+       for (hose = hose_head; hose; hose = hose->next) {
+               bus = hose->bus;
+               if (bus)
+                       pci_bus_add_devices(bus);
+       }
 }
 
 
index c8d284d8521fc715a01122787294dd4fa2dbcbf5..f535a3fd0f60cc9651e89b83cb821b510374d087 100644 (file)
@@ -116,7 +116,7 @@ alpha_rtc_set_time(struct device *dev, struct rtc_time *tm)
 }
 
 static int
-alpha_rtc_set_mmss(struct device *dev, unsigned long nowtime)
+alpha_rtc_set_mmss(struct device *dev, time64_t nowtime)
 {
        int retval = 0;
        int real_seconds, real_minutes, cmos_minutes;
@@ -211,7 +211,7 @@ alpha_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 static const struct rtc_class_ops alpha_rtc_ops = {
        .read_time = alpha_rtc_read_time,
        .set_time = alpha_rtc_set_time,
-       .set_mmss = alpha_rtc_set_mmss,
+       .set_mmss64 = alpha_rtc_set_mmss,
        .ioctl = alpha_rtc_ioctl,
 };
 
@@ -276,7 +276,7 @@ do_remote_mmss(void *data)
 }
 
 static int
-remote_set_mmss(struct device *dev, unsigned long now)
+remote_set_mmss(struct device *dev, time64_t now)
 {
        union remote_data x;
        if (smp_processor_id() != boot_cpuid) {
@@ -290,7 +290,7 @@ remote_set_mmss(struct device *dev, unsigned long now)
 static const struct rtc_class_ops remote_rtc_ops = {
        .read_time = remote_read_time,
        .set_time = remote_set_time,
-       .set_mmss = remote_set_mmss,
+       .set_mmss64 = remote_set_mmss,
        .ioctl = alpha_rtc_ioctl,
 };
 #endif
index 837c0fa58317a2ff308c494aa69b7ad477b62e5e..700686d0486979c94ade2caec2c6938addbb63a2 100644 (file)
@@ -207,6 +207,9 @@ nautilus_init_pci(void)
 
        /* Scan our single hose.  */
        bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
+       if (!bus)
+               return;
+
        hose->bus = bus;
        pcibios_claim_one_bus(bus);
 
@@ -253,6 +256,7 @@ nautilus_init_pci(void)
           for the root bus, so just clear it. */
        bus->self = NULL;
        pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+       pci_bus_add_devices(bus);
 }
 
 /*
index 98c00a2d4dd9a57f1c503ac2ebb6d63a3f1a76b4..f46efd14059d302712df70442604c19f1a8f2fe6 100644 (file)
@@ -155,8 +155,6 @@ int copy_thread(unsigned long clone_flags,
  */
 void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long usp)
 {
-       set_fs(USER_DS); /* user space */
-
        regs->sp = usp;
        regs->ret = pc;
 
index e550b117ec4ffe4ccf3f79e4763fc511e5c9d7e9..93c6ea52b6719e4e238d6076fda6c3b981ac48fe 100644 (file)
@@ -841,7 +841,7 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
                                break;
                        case DW_CFA_GNU_window_save:
                        default:
-                               unw_debug("UNKNOW OPCODE 0x%x\n", opcode);
+                               unw_debug("UNKNOWN OPCODE 0x%x\n", opcode);
                                result = 0;
                                break;
                        }
index cf4c0c99aa253f3f69ecc08a07f0c5a695e63640..4b62f4caf0ce901fa08c863e2a3b71eaf517bd78 100644 (file)
@@ -1,8 +1,8 @@
 config ARM
        bool
        default y
-       select ARCH_BINFMT_ELF_RANDOMIZE_PIE
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+       select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_HAVE_CUSTOM_GPIO_H
        select ARCH_HAS_GCOV_PROFILE_ALL
@@ -286,6 +286,11 @@ config GENERIC_BUG
        def_bool y
        depends on BUG
 
+config PGTABLE_LEVELS
+       int
+       default 3 if ARM_LPAE
+       default 2
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
index 1943fc333e7c34c8ce13648000e94d233e7a733f..8a099bc10c1e4579e765819d2f87bd92bec8e4a5 100644 (file)
@@ -15,7 +15,7 @@
 
 / {
        compatible = "ti,am4372", "ti,am43";
-       interrupt-parent = <&gic>;
+       interrupt-parent = <&wakeupgen>;
 
 
        aliases {
                #interrupt-cells = <3>;
                reg = <0x48241000 0x1000>,
                      <0x48240100 0x0100>;
+               interrupt-parent = <&gic>;
+       };
+
+       wakeupgen: interrupt-controller@48281000 {
+               compatible = "ti,omap4-wugen-mpu";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x48281000 0x1000>;
+               interrupt-parent = <&gic>;
        };
 
        l2-cache-controller@48242000 {
index f84d9715a4a9fc286dbfca7af4e9d5963cda6549..26956cb50835d660d4a853e52e913eca9190e4e5 100644 (file)
                reg = <0x24>;
                compatible = "ti,tps65218";
                interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
-               interrupt-parent = <&gic>;
                interrupt-controller;
                #interrupt-cells = <2>;
 
index 832d24318f62b538da305b4939f71b31e7ca1d86..8ae29c955c11d7f83f4423184a8ed61412b515dd 100644 (file)
        tps@24 {
                compatible = "ti,tps65218";
                reg = <0x24>;
-               interrupt-parent = <&gic>;
                interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
                interrupt-controller;
                #interrupt-cells = <2>;
index 257c099c347e422b9dcde514355172958f14fb3f..1d7109196872299464ccfb5f3a1938b76e4f68ef 100644 (file)
                reg = <0x24>;
                compatible = "ti,tps65218";
                interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
-               interrupt-parent = <&gic>;
                interrupt-controller;
                #interrupt-cells = <2>;
 
index 6463f9ef2b548208bda288a78a07ab3353aa2220..bd48dba1674865878049e7786e28c7b720feb0cf 100644 (file)
        mcp_rtc: rtc@6f {
                compatible = "microchip,mcp7941x";
                reg = <0x6f>;
-               interrupt-parent = <&gic>;
                interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_LOW>;  /* IRQ_SYS_1N */
 
                pinctrl-names = "default";
 
 &uart3 {
        status = "okay";
-       interrupts-extended = <&gic GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+       interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
                              <&dra7_pmx_core 0x248>;
 
        pinctrl-names = "default";
index 7563d7ce01bbc74ed71fab8cd07a578060325500..b1bd06c6c2a801ee9c647cb63483430b8be60c44 100644 (file)
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <&uart1_pins>;
-       interrupts-extended = <&gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+       interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
                              <&dra7_pmx_core 0x3e0>;
 };
 
index c4659a979c41387558f8ea660d119568645acbcb..a0afce7ad482cab69ce4c3935ef59536dd41c9d2 100644 (file)
 #include "skeleton.dtsi"
 
 #define MAX_SOURCES 400
-#define DIRECT_IRQ(irq) (MAX_SOURCES + irq)
 
 / {
        #address-cells = <1>;
        #size-cells = <1>;
 
        compatible = "ti,dra7xx";
-       interrupt-parent = <&gic>;
+       interrupt-parent = <&crossbar_mpu>;
 
        aliases {
                i2c0 = &i2c1;
                             <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
                             <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
                             <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+               interrupt-parent = <&gic>;
        };
 
        gic: interrupt-controller@48211000 {
                compatible = "arm,cortex-a15-gic";
                interrupt-controller;
                #interrupt-cells = <3>;
-               arm,routable-irqs = <192>;
                reg = <0x48211000 0x1000>,
                      <0x48212000 0x1000>,
                      <0x48214000 0x2000>,
                      <0x48216000 0x2000>;
                interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+               interrupt-parent = <&gic>;
+       };
+
+       wakeupgen: interrupt-controller@48281000 {
+               compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x48281000 0x1000>;
+               interrupt-parent = <&gic>;
        };
 
        /*
@@ -91,8 +99,8 @@
                ti,hwmods = "l3_main_1", "l3_main_2";
                reg = <0x44000000 0x1000000>,
                      <0x45000000 0x1000>;
-               interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
-                            <GIC_SPI DIRECT_IRQ(10) IRQ_TYPE_LEVEL_HIGH>;
+               interrupts-extended = <&crossbar_mpu GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+                                     <&wakeupgen GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
                prm: prm@4ae06000 {
                        compatible = "ti,dra7-prm";
                uart1: serial@4806a000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4806a000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart1";
                        clock-frequency = <48000000>;
                        status = "disabled";
                uart2: serial@4806c000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4806c000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart2";
                        clock-frequency = <48000000>;
                        status = "disabled";
                uart3: serial@48020000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48020000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart3";
                        clock-frequency = <48000000>;
                        status = "disabled";
                uart4: serial@4806e000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4806e000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart4";
                        clock-frequency = <48000000>;
                         status = "disabled";
                uart5: serial@48066000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48066000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart5";
                        clock-frequency = <48000000>;
                        status = "disabled";
                uart6: serial@48068000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48068000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart6";
                        clock-frequency = <48000000>;
                        status = "disabled";
                uart7: serial@48420000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48420000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart7";
                        clock-frequency = <48000000>;
                        status = "disabled";
                uart8: serial@48422000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48422000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart8";
                        clock-frequency = <48000000>;
                        status = "disabled";
                uart9: serial@48424000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48424000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart9";
                        clock-frequency = <48000000>;
                        status = "disabled";
                uart10: serial@4ae2b000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4ae2b000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart10";
                        clock-frequency = <48000000>;
                        status = "disabled";
                        status = "disabled";
                };
 
-               crossbar_mpu: crossbar@4a020000 {
+               crossbar_mpu: crossbar@4a002a48 {
                        compatible = "ti,irq-crossbar";
                        reg = <0x4a002a48 0x130>;
+                       interrupt-controller;
+                       interrupt-parent = <&wakeupgen>;
+                       #interrupt-cells = <3>;
                        ti,max-irqs = <160>;
                        ti,max-crossbar-sources = <MAX_SOURCES>;
                        ti,reg-size = <2>;
index 40ed539ce4743a0f3eccc319e4a4c6be09472363..daf28110d4872224be02ef57de5c61de06a7f55a 100644 (file)
                pinctrl-0 = <&tps65917_pins_default>;
 
                interrupts = <GIC_SPI 2 IRQ_TYPE_NONE>;  /* IRQ_SYS_1N */
-               interrupt-parent = <&gic>;
                interrupt-controller;
                #interrupt-cells = <2>;
 
index e5a3d23a3df122895fc0672667e3cc41ac2b25e6..f7fb0d0ef25a5400b5738ba8b8afad955cded5f5 100644 (file)
@@ -25,6 +25,7 @@
 
        pmu {
                compatible = "arm,cortex-a15-pmu";
-               interrupts = <GIC_SPI DIRECT_IRQ(131) IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-parent = <&wakeupgen>;
+               interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
        };
 };
index 10173fab1a15b72983d43fddf453ed5d4105f73a..00eeed789b4b74a306137f82d6fb70ebea831fe7 100644 (file)
@@ -41,8 +41,9 @@
 
        pmu {
                compatible = "arm,cortex-a15-pmu";
-               interrupts = <GIC_SPI DIRECT_IRQ(131) IRQ_TYPE_LEVEL_HIGH>,
-                            <GIC_SPI DIRECT_IRQ(132) IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-parent = <&wakeupgen>;
+               interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        ocp {
index ac6b0ae42caff5f9ad7d14307f2421ddbf35c689..14ab515aa83cd1a1f02918563b769657fe8c472c 100644 (file)
                pmu_system_controller: system-controller@10020000 {
                        compatible = "samsung,exynos3250-pmu", "syscon";
                        reg = <0x10020000 0x4000>;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       interrupt-parent = <&gic>;
                };
 
                mipi_phy: video-phy@10020710 {
                        compatible = "samsung,exynos3250-rtc";
                        reg = <0x10070000 0x100>;
                        interrupts = <0 73 0>, <0 74 0>;
+                       interrupt-parent = <&pmu_system_controller>;
                        status = "disabled";
                };
 
index 77ea547768f4fa24965ce945b6a7ea2adc12ba60..e20cdc24c3bbd5f71d5f21db7187d0a101324609 100644 (file)
        pmu_system_controller: system-controller@10020000 {
                compatible = "samsung,exynos4210-pmu", "syscon";
                reg = <0x10020000 0x4000>;
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               interrupt-parent = <&gic>;
        };
 
        dsi_0: dsi@11C80000 {
        rtc@10070000 {
                compatible = "samsung,s3c6410-rtc";
                reg = <0x10070000 0x100>;
+               interrupt-parent = <&pmu_system_controller>;
                interrupts = <0 44 0>, <0 45 0>;
                clocks = <&clock CLK_RTC>;
                clock-names = "rtc";
index adbde1adad95ddf0bde124e25b2b16ac41dba83b..77f656eb8e6b87fe19182b72e66c2ae9160f4e59 100644 (file)
                clock-names = "clkout16";
                clocks = <&clock CLK_FIN_PLL>;
                #clock-cells = <1>;
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               interrupt-parent = <&gic>;
        };
 
        sysreg_system_controller: syscon@10050000 {
        rtc: rtc@101E0000 {
                clocks = <&clock CLK_RTC>;
                clock-names = "rtc";
+               interrupt-parent = <&pmu_system_controller>;
                status = "disabled";
        };
 
index c0e98cf3514fa1fec0031984f735b02ca054af3c..b3d2d53820e3d57005b6fb89d0f9e7dae72c3fa4 100644 (file)
        rtc: rtc@101E0000 {
                clocks = <&clock CLK_RTC>;
                clock-names = "rtc";
+               interrupt-parent = <&pmu_system_controller>;
                status = "disabled";
        };
 
                clock-names = "clkout16";
                clocks = <&clock CLK_FIN_PLL>;
                #clock-cells = <1>;
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               interrupt-parent = <&gic>;
        };
 
        sysreg_system_controller: syscon@10050000 {
index e860ccd9d09c073aa57a9f599b54e038ee70f0c7..f2a94fa625527661e19b4983f27372be0119f7e0 100644 (file)
        twl: twl@48 {
                reg = <0x48>;
                interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;           /* IRQ_SYS_1N cascaded to gic */
-               interrupt-parent = <&gic>;
        };
 
        twl6040: twl@4b {
                compatible = "ti,twl6040";
                reg = <0x4b>;
                interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;         /* IRQ_SYS_2N cascaded to gic */
-               interrupt-parent = <&gic>;
                ti,audpwron-gpio = <&gpio6 0 GPIO_ACTIVE_HIGH>;         /* gpio_160 */
 
                vio-supply = <&v1v8>;
index 150513506c19f9764f63cd5828b79d4b7b1417f5..7c15fb2e2fe4098a7393bb7fa1239e37a4ebab3d 100644 (file)
                reg = <0x48>;
                /* IRQ# = 7 */
                interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */
-               interrupt-parent = <&gic>;
        };
 
        twl6040: twl@4b {
 
                /* IRQ# = 119 */
                interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */
-               interrupt-parent = <&gic>;
                ti,audpwron-gpio = <&gpio4 31 GPIO_ACTIVE_HIGH>;  /* gpio line 127 */
 
                vio-supply = <&v1v8>;
 };
 
 &uart2 {
-       interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
+       interrupts-extended = <&wakeupgen GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
                               &omap4_pmx_core OMAP4_UART2_RX>;
 };
 
 &uart3 {
-       interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
+       interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
                               &omap4_pmx_core OMAP4_UART3_RX>;
 };
 
 &uart4 {
-       interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
+       interrupts-extended = <&wakeupgen GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
                               &omap4_pmx_core OMAP4_UART4_RX>;
 };
 
index 3e1da43068f68e67f7578d5eda64c12ea33501ca..8aca8dae968ad276f193a3b3c969082a23dcc7e7 100644 (file)
                reg = <0x48>;
                /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */
                interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */
-               interrupt-parent = <&gic>;
        };
 
        twl6040: twl@4b {
 
                /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */
                interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */
-               interrupt-parent = <&gic>;
                ti,audpwron-gpio = <&gpio4 31 0>;  /* gpio line 127 */
 
                vio-supply = <&v1v8>;
 };
 
 &uart2 {
-       interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
+       interrupts-extended = <&wakeupgen GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
                               &omap4_pmx_core OMAP4_UART2_RX>;
        pinctrl-names = "default";
        pinctrl-0 = <&uart2_pins>;
 };
 
 &uart3 {
-       interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
+       interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
                               &omap4_pmx_core OMAP4_UART3_RX>;
        pinctrl-names = "default";
        pinctrl-0 = <&uart3_pins>;
 };
 
 &uart4 {
-       interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
+       interrupts-extended = <&wakeupgen GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
                               &omap4_pmx_core OMAP4_UART4_RX>;
        pinctrl-names = "default";
        pinctrl-0 = <&uart4_pins>;
index 062701e1a8981cc800ebbcc8b2edcfc0f80e3e30..a4f1ba2e1903baead6b8be5f59ae8a87a157a109 100644 (file)
                reg = <0x48>;
                /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */
                interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */
-               interrupt-parent = <&gic>;
        };
 
        twl6040: twl@4b {
 
                /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */
                interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */
-               interrupt-parent = <&gic>;
                ti,audpwron-gpio = <&gpio6 22 0>; /* gpio 182 */
 
                vio-supply = <&v1v8>;
index 87401d9f4d8b02314323e5a46ee38e5b0c6e4523..f2091d1c9c36c2995e08a4d63929df6c2679d243 100644 (file)
@@ -14,7 +14,7 @@
 
 / {
        compatible = "ti,omap4430", "ti,omap4";
-       interrupt-parent = <&gic>;
+       interrupt-parent = <&wakeupgen>;
 
        aliases {
                i2c0 = &i2c1;
@@ -56,6 +56,7 @@
                #interrupt-cells = <3>;
                reg = <0x48241000 0x1000>,
                      <0x48240100 0x0100>;
+               interrupt-parent = <&gic>;
        };
 
        L2: l2-cache-controller@48242000 {
                clocks = <&mpu_periphclk>;
                reg = <0x48240600 0x20>;
                interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_HIGH)>;
+               interrupt-parent = <&gic>;
+       };
+
+       wakeupgen: interrupt-controller@48281000 {
+               compatible = "ti,omap4-wugen-mpu";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x48281000 0x1000>;
+               interrupt-parent = <&gic>;
        };
 
        /*
                uart2: serial@4806c000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4806c000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart2";
                        clock-frequency = <48000000>;
                };
                uart3: serial@48020000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48020000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart3";
                        clock-frequency = <48000000>;
                };
                uart4: serial@4806e000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4806e000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart4";
                        clock-frequency = <48000000>;
                };
index b54b271e153b65ccc709af6a2e298ef907fb63c3..61ad2ea347204bc9154b120ec861a7658f67f61b 100644 (file)
        palmas: palmas@48 {
                compatible = "ti,palmas";
                interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
-               interrupt-parent = <&gic>;
                reg = <0x48>;
                interrupt-controller;
                #interrupt-cells = <2>;
index 159720d6c9569aa6b13c65ee3674ca64d335a21e..74777a6e200a68bb7cda9257d70aee78549bc8bd 100644 (file)
        palmas: palmas@48 {
                compatible = "ti,palmas";
                interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
-               interrupt-parent = <&gic>;
                reg = <0x48>;
                interrupt-controller;
                #interrupt-cells = <2>;
                pinctrl-0 = <&twl6040_pins>;
 
                interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
-               interrupt-parent = <&gic>;
                ti,audpwron-gpio = <&gpio5 13 0>;  /* gpio line 141 */
 
                vio-supply = <&smps7_reg>;
index 4a485b63a1413bf8cfda0f027ed5e7a903c68066..77b5f70d0ebcc8279b1e8e3e45afbc92be2abc6a 100644 (file)
@@ -18,7 +18,7 @@
        #size-cells = <1>;
 
        compatible = "ti,omap5";
-       interrupt-parent = <&gic>;
+       interrupt-parent = <&wakeupgen>;
 
        aliases {
                i2c0 = &i2c1;
@@ -79,6 +79,7 @@
                             <GIC_PPI 14 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>,
                             <GIC_PPI 11 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>,
                             <GIC_PPI 10 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>;
+               interrupt-parent = <&gic>;
        };
 
        pmu {
                      <0x48212000 0x1000>,
                      <0x48214000 0x2000>,
                      <0x48216000 0x2000>;
+               interrupt-parent = <&gic>;
+       };
+
+       wakeupgen: interrupt-controller@48281000 {
+               compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x48281000 0x1000>;
+               interrupt-parent = <&gic>;
        };
 
        /*
                uart1: serial@4806a000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4806a000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart1";
                        clock-frequency = <48000000>;
                };
                uart2: serial@4806c000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4806c000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart2";
                        clock-frequency = <48000000>;
                };
                uart3: serial@48020000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48020000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart3";
                        clock-frequency = <48000000>;
                };
                uart4: serial@4806e000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4806e000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart4";
                        clock-frequency = <48000000>;
                };
                uart5: serial@48066000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48066000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart5";
                        clock-frequency = <48000000>;
                };
                uart6: serial@48068000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48068000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart6";
                        clock-frequency = <48000000>;
                };
                        usbhsohci: ohci@4a064800 {
                                compatible = "ti,ohci-omap3";
                                reg = <0x4a064800 0x400>;
-                               interrupt-parent = <&gic>;
                                interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        usbhsehci: ehci@4a064c00 {
                                compatible = "ti,ehci-omap";
                                reg = <0x4a064c00 0x400>;
-                               interrupt-parent = <&gic>;
                                interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
                        };
                };
index ea28ebadab1a18ed933288a6fb340de2afe63293..eeb7afecbbe6fa9b6dc3bf0b005156547628291c 100644 (file)
@@ -10,7 +10,7 @@
 #include "stih416-clock.dtsi"
 #include "stih416-pinctrl.dtsi"
 
-#include <dt-bindings/phy/phy-miphy365x.h>
+#include <dt-bindings/phy/phy.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/reset-controller/stih416-resets.h>
 / {
                        reg             = <0xfe380000 0x1000>;
                        interrupts      = <GIC_SPI 157 IRQ_TYPE_NONE>;
                        interrupt-names = "hostc";
-                       phys            = <&phy_port0 MIPHY_TYPE_SATA>;
+                       phys            = <&phy_port0 PHY_TYPE_SATA>;
                        phy-names       = "sata-phy";
                        resets          = <&powerdown STIH416_SATA0_POWERDOWN>,
                                          <&softreset STIH416_SATA0_SOFTRESET>;
index 4296b5398bf53ed7580208bc4165c569945c65f2..f58a3d9d5f1394760c4f931b27c5f31d2018f991 100644 (file)
@@ -8,7 +8,7 @@
 
 / {
        compatible = "nvidia,tegra114";
-       interrupt-parent = <&gic>;
+       interrupt-parent = <&lic>;
 
        host1x@50000000 {
                compatible = "nvidia,tegra114-host1x", "simple-bus";
                      <0x50046000 0x2000>;
                interrupts = <GIC_PPI 9
                        (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+               interrupt-parent = <&gic>;
+       };
+
+       lic: interrupt-controller@60004000 {
+               compatible = "nvidia,tegra114-ictlr", "nvidia,tegra30-ictlr";
+               reg = <0x60004000 0x100>,
+                     <0x60004100 0x50>,
+                     <0x60004200 0x50>,
+                     <0x60004300 0x50>,
+                     <0x60004400 0x50>;
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               interrupt-parent = <&gic>;
        };
 
        timer@60005000 {
                                (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
                        <GIC_PPI 10
                                (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+               interrupt-parent = <&gic>;
        };
 };
index 4be06c6ea0c8581dd71dad22af2ef45a8dc0984b..db85695aa7aa715713e0fa387e92de887565e233 100644 (file)
@@ -10,7 +10,7 @@
 
 / {
        compatible = "nvidia,tegra124";
-       interrupt-parent = <&gic>;
+       interrupt-parent = <&lic>;
        #address-cells = <2>;
        #size-cells = <2>;
 
                      <0x0 0x50046000 0x0 0x2000>;
                interrupts = <GIC_PPI 9
                        (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+               interrupt-parent = <&gic>;
        };
 
        gpu@0,57000000 {
                status = "disabled";
        };
 
+       lic: interrupt-controller@60004000 {
+               compatible = "nvidia,tegra124-ictlr", "nvidia,tegra30-ictlr";
+               reg = <0x0 0x60004000 0x0 0x100>,
+                     <0x0 0x60004100 0x0 0x100>,
+                     <0x0 0x60004200 0x0 0x100>,
+                     <0x0 0x60004300 0x0 0x100>,
+                     <0x0 0x60004400 0x0 0x100>;
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               interrupt-parent = <&gic>;
+       };
+
        timer@0,60005000 {
                compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer";
                reg = <0x0 0x60005000 0x0 0x400>;
                                (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
                             <GIC_PPI 10
                                (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+               interrupt-parent = <&gic>;
        };
 };
index e5527f74269666cd96f38b4ec6c335639e7b9314..adf6b048d0bb52b5355f26eb06f79212a2e34cde 100644 (file)
@@ -7,7 +7,7 @@
 
 / {
        compatible = "nvidia,tegra20";
-       interrupt-parent = <&intc>;
+       interrupt-parent = <&lic>;
 
        host1x@50000000 {
                compatible = "nvidia,tegra20-host1x", "simple-bus";
 
        timer@50040600 {
                compatible = "arm,cortex-a9-twd-timer";
+               interrupt-parent = <&intc>;
                reg = <0x50040600 0x20>;
                interrupts = <GIC_PPI 13
                        (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
                       0x50040100 0x0100>;
                interrupt-controller;
                #interrupt-cells = <3>;
+               interrupt-parent = <&intc>;
        };
 
        cache-controller@50043000 {
                cache-level = <2>;
        };
 
+       lic: interrupt-controller@60004000 {
+               compatible = "nvidia,tegra20-ictlr";
+               reg = <0x60004000 0x100>,
+                     <0x60004100 0x50>,
+                     <0x60004200 0x50>,
+                     <0x60004300 0x50>;
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               interrupt-parent = <&intc>;
+       };
+
        timer@60005000 {
                compatible = "nvidia,tegra20-timer";
                reg = <0x60005000 0x60>;
index db4810df142c39b62655d674229325c7a577b194..60e205a0f63d99640798938fcf06c55bf86980b1 100644 (file)
@@ -8,7 +8,7 @@
 
 / {
        compatible = "nvidia,tegra30";
-       interrupt-parent = <&intc>;
+       interrupt-parent = <&lic>;
 
        pcie-controller@00003000 {
                compatible = "nvidia,tegra30-pcie";
        timer@50040600 {
                compatible = "arm,cortex-a9-twd-timer";
                reg = <0x50040600 0x20>;
+               interrupt-parent = <&intc>;
                interrupts = <GIC_PPI 13
                        (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
                clocks = <&tegra_car TEGRA30_CLK_TWD>;
                       0x50040100 0x0100>;
                interrupt-controller;
                #interrupt-cells = <3>;
+               interrupt-parent = <&intc>;
        };
 
        cache-controller@50043000 {
                cache-level = <2>;
        };
 
+       lic: interrupt-controller@60004000 {
+               compatible = "nvidia,tegra30-ictlr";
+               reg = <0x60004000 0x100>,
+                     <0x60004100 0x50>,
+                     <0x60004200 0x50>,
+                     <0x60004300 0x50>,
+                     <0x60004400 0x50>;
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               interrupt-parent = <&intc>;
+       };
+
        timer@60005000 {
                compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
                reg = <0x60005000 0x400>;
index 6eaddc47c43dfbd60f52b6d49c425acbd55cab62..37dc0fe1093fb24bb26b1c852c568bd8fcd3f6d2 100644 (file)
@@ -151,8 +151,6 @@ static int bL_switch_to(unsigned int new_cluster_id)
        unsigned int mpidr, this_cpu, that_cpu;
        unsigned int ob_mpidr, ob_cpu, ob_cluster, ib_mpidr, ib_cpu, ib_cluster;
        struct completion inbound_alive;
-       struct tick_device *tdev;
-       enum clock_event_mode tdev_mode;
        long volatile *handshake_ptr;
        int ipi_nr, ret;
 
@@ -219,13 +217,7 @@ static int bL_switch_to(unsigned int new_cluster_id)
        /* redirect GIC's SGIs to our counterpart */
        gic_migrate_target(bL_gic_id[ib_cpu][ib_cluster]);
 
-       tdev = tick_get_device(this_cpu);
-       if (tdev && !cpumask_equal(tdev->evtdev->cpumask, cpumask_of(this_cpu)))
-               tdev = NULL;
-       if (tdev) {
-               tdev_mode = tdev->evtdev->mode;
-               clockevents_set_mode(tdev->evtdev, CLOCK_EVT_MODE_SHUTDOWN);
-       }
+       tick_suspend_local();
 
        ret = cpu_pm_enter();
 
@@ -251,11 +243,7 @@ static int bL_switch_to(unsigned int new_cluster_id)
 
        ret = cpu_pm_exit();
 
-       if (tdev) {
-               clockevents_set_mode(tdev->evtdev, tdev_mode);
-               clockevents_program_event(tdev->evtdev,
-                                         tdev->evtdev->next_event, 1);
-       }
+       tick_resume_local();
 
        trace_cpu_migrate_finish(ktime_get_real_ns(), ib_mpidr);
        local_fiq_enable();
index afb9cafd378618fef0d39a7bcae64e9950afdb1c..c1ff8ab12914ce6f934b3a65149e594d50fe76a6 100644 (file)
@@ -125,10 +125,6 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
 extern void elf_set_personality(const struct elf32_hdr *);
 #define SET_PERSONALITY(ex)    elf_set_personality(&(ex))
 
-struct mm_struct;
-extern unsigned long arch_randomize_brk(struct mm_struct *mm);
-#define arch_randomize_brk arch_randomize_brk
-
 #ifdef CONFIG_MMU
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
 struct linux_binprm;
index 70f9b9bfb1f9646a1bdfe3ab597c5b9c26e80b7e..5f337dc5c1087f49ebf8eae9fde6051d7c9d45be 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _ASM_ARM_JUMP_LABEL_H
 #define _ASM_ARM_JUMP_LABEL_H
 
-#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
 
 #include <linux/types.h>
 
@@ -27,8 +27,6 @@ l_yes:
        return true;
 }
 
-#endif /* __KERNEL__ */
-
 typedef u32 jump_label_t;
 
 struct jump_entry {
@@ -37,4 +35,5 @@ struct jump_entry {
        jump_label_t key;
 };
 
+#endif  /* __ASSEMBLY__ */
 #endif
index 816db0bf2dd8addbd9844488b5a72d4495be72c7..d995821f1698c67bc3e57e2073af9cdc3353fab4 100644 (file)
 #define HSR_COND       (0xfU << HSR_COND_SHIFT)
 
 #define FSC_FAULT      (0x04)
+#define FSC_ACCESS     (0x08)
 #define FSC_PERM       (0x0c)
 
 /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
index 41008cd7c53f6b39d1476d5a46dc610c578e8d5c..d71607c16601b6b1e1a595e32562195ccd63f5b1 100644 (file)
@@ -27,6 +27,8 @@
 #include <asm/fpstate.h>
 #include <kvm/arm_arch_timer.h>
 
+#define __KVM_HAVE_ARCH_INTC_INITIALIZED
+
 #if defined(CONFIG_KVM_ARM_MAX_VCPUS)
 #define KVM_MAX_VCPUS CONFIG_KVM_ARM_MAX_VCPUS
 #else
@@ -165,19 +167,10 @@ void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
 
 unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
 int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
+int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
 
 /* We do not have shadow page tables, hence the empty hooks */
-static inline int kvm_age_hva(struct kvm *kvm, unsigned long start,
-                             unsigned long end)
-{
-       return 0;
-}
-
-static inline int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
-{
-       return 0;
-}
-
 static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
                                                         unsigned long address)
 {
index 3f83db2f6cf053cb083c15b5fa910b5d7ae7ee61..d8e90c8cb5fa0ab4c0486cb6d9fd53d576456291 100644 (file)
@@ -28,28 +28,6 @@ struct kvm_decode {
        bool sign_extend;
 };
 
-/*
- * The in-kernel MMIO emulation code wants to use a copy of run->mmio,
- * which is an anonymous type. Use our own type instead.
- */
-struct kvm_exit_mmio {
-       phys_addr_t     phys_addr;
-       u8              data[8];
-       u32             len;
-       bool            is_write;
-       void            *private;
-};
-
-static inline void kvm_prepare_mmio(struct kvm_run *run,
-                                   struct kvm_exit_mmio *mmio)
-{
-       run->mmio.phys_addr     = mmio->phys_addr;
-       run->mmio.len           = mmio->len;
-       run->mmio.is_write      = mmio->is_write;
-       memcpy(run->mmio.data, mmio->data, mmio->len);
-       run->exit_reason        = KVM_EXIT_MMIO;
-}
-
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
                 phys_addr_t fault_ipa);
index 90c12e1e695c97682c229174a975bb6fdb97403e..0f79e4dec7f98ccddb8429a1e6b262ca146c0d38 100644 (file)
@@ -12,8 +12,7 @@
 
 extern void timer_tick(void);
 
-struct timespec;
-typedef void (*clock_access_fn)(struct timespec *);
+typedef void (*clock_access_fn)(struct timespec64 *);
 extern int register_persistent_clock(clock_access_fn read_boot,
                                     clock_access_fn read_persistent);
 
index 0db25bc328643de55ded82f3b9583a748038d97d..2499867dd0d86d79477e85ac0933228b9bbcf6a2 100644 (file)
@@ -198,6 +198,9 @@ struct kvm_arch_memory_slot {
 /* Highest supported SPI, from VGIC_NR_IRQS */
 #define KVM_ARM_IRQ_GIC_MAX            127
 
+/* One single KVM irqchip, ie. the VGIC */
+#define KVM_NR_IRQCHIPS          1
+
 /* PSCI interface */
 #define KVM_PSCI_FN_BASE               0x95c1ba5e
 #define KVM_PSCI_FN(n)                 (KVM_PSCI_FN_BASE + (n))
index 2d2d6087b9b105d5dadcd66f9821deefe50d1e66..488eaac56028f59ed08fc4030de25dd7d6a59ccb 100644 (file)
@@ -190,7 +190,6 @@ int main(void)
   DEFINE(VCPU_HxFAR,           offsetof(struct kvm_vcpu, arch.fault.hxfar));
   DEFINE(VCPU_HPFAR,           offsetof(struct kvm_vcpu, arch.fault.hpfar));
   DEFINE(VCPU_HYP_PC,          offsetof(struct kvm_vcpu, arch.fault.hyp_pc));
-#ifdef CONFIG_KVM_ARM_VGIC
   DEFINE(VCPU_VGIC_CPU,                offsetof(struct kvm_vcpu, arch.vgic_cpu));
   DEFINE(VGIC_V2_CPU_HCR,      offsetof(struct vgic_cpu, vgic_v2.vgic_hcr));
   DEFINE(VGIC_V2_CPU_VMCR,     offsetof(struct vgic_cpu, vgic_v2.vgic_vmcr));
@@ -200,14 +199,11 @@ int main(void)
   DEFINE(VGIC_V2_CPU_APR,      offsetof(struct vgic_cpu, vgic_v2.vgic_apr));
   DEFINE(VGIC_V2_CPU_LR,       offsetof(struct vgic_cpu, vgic_v2.vgic_lr));
   DEFINE(VGIC_CPU_NR_LR,       offsetof(struct vgic_cpu, nr_lr));
-#ifdef CONFIG_KVM_ARM_TIMER
   DEFINE(VCPU_TIMER_CNTV_CTL,  offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_ctl));
   DEFINE(VCPU_TIMER_CNTV_CVAL, offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_cval));
   DEFINE(KVM_TIMER_CNTVOFF,    offsetof(struct kvm, arch.timer.cntvoff));
   DEFINE(KVM_TIMER_ENABLED,    offsetof(struct kvm, arch.timer.enabled));
-#endif
   DEFINE(KVM_VGIC_VCTRL,       offsetof(struct kvm, arch.vgic.vctrl_base));
-#endif
   DEFINE(KVM_VTTBR,            offsetof(struct kvm, arch.vttbr));
 #endif
   return 0; 
index 7fc70ae21185b7295a6d0390831c0a83e8a45def..dc7d0a95bd3651c2949454027a3b6c47dd77863c 100644 (file)
@@ -648,7 +648,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
                 * Per-cpu breakpoints are not supported by our stepping
                 * mechanism.
                 */
-               if (!bp->hw.bp_target)
+               if (!bp->hw.target)
                        return -EINVAL;
 
                /*
index 0cc7e58c47cc79fd53ab4feac1b9440300e7a562..a66e37e211a9a8cbfabf85d9213f6b73db417085 100644 (file)
@@ -76,7 +76,7 @@ void timer_tick(void)
 }
 #endif
 
-static void dummy_clock_access(struct timespec *ts)
+static void dummy_clock_access(struct timespec64 *ts)
 {
        ts->tv_sec = 0;
        ts->tv_nsec = 0;
@@ -85,12 +85,12 @@ static void dummy_clock_access(struct timespec *ts)
 static clock_access_fn __read_persistent_clock = dummy_clock_access;
 static clock_access_fn __read_boot_clock = dummy_clock_access;;
 
-void read_persistent_clock(struct timespec *ts)
+void read_persistent_clock64(struct timespec64 *ts)
 {
        __read_persistent_clock(ts);
 }
 
-void read_boot_clock(struct timespec *ts)
+void read_boot_clock64(struct timespec64 *ts)
 {
        __read_boot_clock(ts);
 }
index 338ace78ed18611bcb4aea64baeb490fcf2bca05..f1f79d1043096093a780e46e4a68cf3796a153ac 100644 (file)
@@ -18,6 +18,7 @@ if VIRTUALIZATION
 
 config KVM
        bool "Kernel-based Virtual Machine (KVM) support"
+       depends on MMU && OF
        select PREEMPT_NOTIFIERS
        select ANON_INODES
        select HAVE_KVM_CPU_RELAX_INTERCEPT
@@ -26,10 +27,12 @@ config KVM
        select KVM_ARM_HOST
        select KVM_GENERIC_DIRTYLOG_READ_PROTECT
        select SRCU
-       depends on ARM_VIRT_EXT && ARM_LPAE
+       select MMU_NOTIFIER
+       select HAVE_KVM_EVENTFD
+       select HAVE_KVM_IRQFD
+       depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER
        ---help---
-         Support hosting virtualized guest machines. You will also
-         need to select one or more of the processor modules below.
+         Support hosting virtualized guest machines.
 
          This module provides access to the hardware capabilities through
          a character device node named /dev/kvm.
@@ -37,10 +40,7 @@ config KVM
          If unsure, say N.
 
 config KVM_ARM_HOST
-       bool "KVM host support for ARM cpus."
-       depends on KVM
-       depends on MMU
-       select  MMU_NOTIFIER
+       bool
        ---help---
          Provides host support for ARM processors.
 
@@ -55,20 +55,4 @@ config KVM_ARM_MAX_VCPUS
          large, so only choose a reasonable number that you expect to
          actually use.
 
-config KVM_ARM_VGIC
-       bool "KVM support for Virtual GIC"
-       depends on KVM_ARM_HOST && OF
-       select HAVE_KVM_IRQCHIP
-       default y
-       ---help---
-         Adds support for a hardware assisted, in-kernel GIC emulation.
-
-config KVM_ARM_TIMER
-       bool "KVM support for Architected Timers"
-       depends on KVM_ARM_VGIC && ARM_ARCH_TIMER
-       select HAVE_KVM_IRQCHIP
-       default y
-       ---help---
-         Adds support for the Architected Timers in virtual machines
-
 endif # VIRTUALIZATION
index 443b8bea43e93e862653f5f153d3ce7759da5528..139e46c08b6ec5daff4a3692a569027cf23c0347 100644 (file)
@@ -7,7 +7,7 @@ ifeq ($(plus_virt),+virt)
        plus_virt_def := -DREQUIRES_VIRT=1
 endif
 
-ccflags-y += -Ivirt/kvm -Iarch/arm/kvm
+ccflags-y += -Iarch/arm/kvm
 CFLAGS_arm.o := -I. $(plus_virt_def)
 CFLAGS_mmu.o := -I.
 
@@ -15,12 +15,12 @@ AFLAGS_init.o := -Wa,-march=armv7-a$(plus_virt)
 AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt)
 
 KVM := ../../../virt/kvm
-kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o
+kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o
 
 obj-y += kvm-arm.o init.o interrupts.o
 obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
 obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
-obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
-obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
-obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2-emul.o
-obj-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
+obj-y += $(KVM)/arm/vgic.o
+obj-y += $(KVM)/arm/vgic-v2.o
+obj-y += $(KVM)/arm/vgic-v2-emul.o
+obj-y += $(KVM)/arm/arch_timer.o
index 5560f74f9eeef1e3e4d2c9c39fc672e539eee93f..6f536451ab784e99966a308c0892e8614214591f 100644 (file)
@@ -61,8 +61,6 @@ static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
 static u8 kvm_next_vmid;
 static DEFINE_SPINLOCK(kvm_vmid_lock);
 
-static bool vgic_present;
-
 static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu)
 {
        BUG_ON(preemptible());
@@ -173,8 +171,8 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        int r;
        switch (ext) {
        case KVM_CAP_IRQCHIP:
-               r = vgic_present;
-               break;
+       case KVM_CAP_IRQFD:
+       case KVM_CAP_IOEVENTFD:
        case KVM_CAP_DEVICE_CTRL:
        case KVM_CAP_USER_MEMORY:
        case KVM_CAP_SYNC_MMU:
@@ -183,6 +181,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_ARM_PSCI:
        case KVM_CAP_ARM_PSCI_0_2:
        case KVM_CAP_READONLY_MEM:
+       case KVM_CAP_MP_STATE:
                r = 1;
                break;
        case KVM_CAP_COALESCED_MMIO:
@@ -268,7 +267,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 
 int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 {
-       return 0;
+       return kvm_timer_should_fire(vcpu);
 }
 
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
@@ -313,13 +312,29 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
 int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
                                    struct kvm_mp_state *mp_state)
 {
-       return -EINVAL;
+       if (vcpu->arch.pause)
+               mp_state->mp_state = KVM_MP_STATE_STOPPED;
+       else
+               mp_state->mp_state = KVM_MP_STATE_RUNNABLE;
+
+       return 0;
 }
 
 int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
                                    struct kvm_mp_state *mp_state)
 {
-       return -EINVAL;
+       switch (mp_state->mp_state) {
+       case KVM_MP_STATE_RUNNABLE:
+               vcpu->arch.pause = false;
+               break;
+       case KVM_MP_STATE_STOPPED:
+               vcpu->arch.pause = true;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
 }
 
 /**
@@ -452,6 +467,11 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
        return 0;
 }
 
+bool kvm_arch_intc_initialized(struct kvm *kvm)
+{
+       return vgic_initialized(kvm);
+}
+
 static void vcpu_pause(struct kvm_vcpu *vcpu)
 {
        wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu);
@@ -831,8 +851,6 @@ static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
 
        switch (dev_id) {
        case KVM_ARM_DEVICE_VGIC_V2:
-               if (!vgic_present)
-                       return -ENXIO;
                return kvm_vgic_addr(kvm, type, &dev_addr->addr, true);
        default:
                return -ENODEV;
@@ -847,10 +865,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
 
        switch (ioctl) {
        case KVM_CREATE_IRQCHIP: {
-               if (vgic_present)
-                       return kvm_vgic_create(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
-               else
-                       return -ENXIO;
+               return kvm_vgic_create(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
        }
        case KVM_ARM_SET_DEVICE_ADDR: {
                struct kvm_arm_device_addr dev_addr;
@@ -1035,10 +1050,6 @@ static int init_hyp_mode(void)
        if (err)
                goto out_free_context;
 
-#ifdef CONFIG_KVM_ARM_VGIC
-               vgic_present = true;
-#endif
-
        /*
         * Init HYP architected timer support
         */
index 384bab67c4629a9bece251d5577c9bf908f8348f..d503fbb787d362752b9b6b688b2829e19b675095 100644 (file)
@@ -109,22 +109,6 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
        return -EINVAL;
 }
 
-#ifndef CONFIG_KVM_ARM_TIMER
-
-#define NUM_TIMER_REGS 0
-
-static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
-{
-       return 0;
-}
-
-static bool is_timer_reg(u64 index)
-{
-       return false;
-}
-
-#else
-
 #define NUM_TIMER_REGS 3
 
 static bool is_timer_reg(u64 index)
@@ -152,8 +136,6 @@ static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
        return 0;
 }
 
-#endif
-
 static int set_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 {
        void __user *uaddr = (void __user *)(long)reg->addr;
index 14d488388480ea50a80d24b18bbed9636c8d1c25..35e4a3a0c476cd9730afa52192bea5b3ff6f20fd 100644 (file)
@@ -402,7 +402,6 @@ vcpu        .req    r0              @ vcpu pointer always in r0
  * Assumes vcpu pointer in vcpu reg
  */
 .macro save_vgic_state
-#ifdef CONFIG_KVM_ARM_VGIC
        /* Get VGIC VCTRL base into r2 */
        ldr     r2, [vcpu, #VCPU_KVM]
        ldr     r2, [r2, #KVM_VGIC_VCTRL]
@@ -460,7 +459,6 @@ ARM_BE8(rev r6, r6  )
        subs    r4, r4, #1
        bne     1b
 2:
-#endif
 .endm
 
 /*
@@ -469,7 +467,6 @@ ARM_BE8(rev r6, r6  )
  * Assumes vcpu pointer in vcpu reg
  */
 .macro restore_vgic_state
-#ifdef CONFIG_KVM_ARM_VGIC
        /* Get VGIC VCTRL base into r2 */
        ldr     r2, [vcpu, #VCPU_KVM]
        ldr     r2, [r2, #KVM_VGIC_VCTRL]
@@ -501,7 +498,6 @@ ARM_BE8(rev r6, r6  )
        subs    r4, r4, #1
        bne     1b
 2:
-#endif
 .endm
 
 #define CNTHCTL_PL1PCTEN       (1 << 0)
@@ -515,7 +511,6 @@ ARM_BE8(rev r6, r6  )
  * Clobbers r2-r5
  */
 .macro save_timer_state
-#ifdef CONFIG_KVM_ARM_TIMER
        ldr     r4, [vcpu, #VCPU_KVM]
        ldr     r2, [r4, #KVM_TIMER_ENABLED]
        cmp     r2, #0
@@ -537,7 +532,6 @@ ARM_BE8(rev r6, r6  )
        mcrr    p15, 4, r2, r2, c14     @ CNTVOFF
 
 1:
-#endif
        @ Allow physical timer/counter access for the host
        mrc     p15, 4, r2, c14, c1, 0  @ CNTHCTL
        orr     r2, r2, #(CNTHCTL_PL1PCEN | CNTHCTL_PL1PCTEN)
@@ -559,7 +553,6 @@ ARM_BE8(rev r6, r6  )
        bic     r2, r2, #CNTHCTL_PL1PCEN
        mcr     p15, 4, r2, c14, c1, 0  @ CNTHCTL
 
-#ifdef CONFIG_KVM_ARM_TIMER
        ldr     r4, [vcpu, #VCPU_KVM]
        ldr     r2, [r4, #KVM_TIMER_ENABLED]
        cmp     r2, #0
@@ -579,7 +572,6 @@ ARM_BE8(rev r6, r6  )
        and     r2, r2, #3
        mcr     p15, 0, r2, c14, c3, 1  @ CNTV_CTL
 1:
-#endif
 .endm
 
 .equ vmentry,  0
index 5d3bfc0eb3f000cb41cb217eb7fdc2611da85fc9..974b1c606d044c239bfa14ffbdf66f0fc982c4fb 100644 (file)
@@ -121,12 +121,11 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
        return 0;
 }
 
-static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
-                     struct kvm_exit_mmio *mmio)
+static int decode_hsr(struct kvm_vcpu *vcpu, bool *is_write, int *len)
 {
        unsigned long rt;
-       int len;
-       bool is_write, sign_extend;
+       int access_size;
+       bool sign_extend;
 
        if (kvm_vcpu_dabt_isextabt(vcpu)) {
                /* cache operation on I/O addr, tell guest unsupported */
@@ -140,17 +139,15 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                return 1;
        }
 
-       len = kvm_vcpu_dabt_get_as(vcpu);
-       if (unlikely(len < 0))
-               return len;
+       access_size = kvm_vcpu_dabt_get_as(vcpu);
+       if (unlikely(access_size < 0))
+               return access_size;
 
-       is_write = kvm_vcpu_dabt_iswrite(vcpu);
+       *is_write = kvm_vcpu_dabt_iswrite(vcpu);
        sign_extend = kvm_vcpu_dabt_issext(vcpu);
        rt = kvm_vcpu_dabt_get_rd(vcpu);
 
-       mmio->is_write = is_write;
-       mmio->phys_addr = fault_ipa;
-       mmio->len = len;
+       *len = access_size;
        vcpu->arch.mmio_decode.sign_extend = sign_extend;
        vcpu->arch.mmio_decode.rt = rt;
 
@@ -165,20 +162,20 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
                 phys_addr_t fault_ipa)
 {
-       struct kvm_exit_mmio mmio;
        unsigned long data;
        unsigned long rt;
        int ret;
+       bool is_write;
+       int len;
+       u8 data_buf[8];
 
        /*
-        * Prepare MMIO operation. First stash it in a private
-        * structure that we can use for in-kernel emulation. If the
-        * kernel can't handle it, copy it into run->mmio and let user
-        * space do its magic.
+        * Prepare MMIO operation. First decode the syndrome data we get
+        * from the CPU. Then try if some in-kernel emulation feels
+        * responsible, otherwise let user space do its magic.
         */
-
        if (kvm_vcpu_dabt_isvalid(vcpu)) {
-               ret = decode_hsr(vcpu, fault_ipa, &mmio);
+               ret = decode_hsr(vcpu, &is_write, &len);
                if (ret)
                        return ret;
        } else {
@@ -188,21 +185,34 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 
        rt = vcpu->arch.mmio_decode.rt;
 
-       if (mmio.is_write) {
-               data = vcpu_data_guest_to_host(vcpu, *vcpu_reg(vcpu, rt),
-                                              mmio.len);
+       if (is_write) {
+               data = vcpu_data_guest_to_host(vcpu, *vcpu_reg(vcpu, rt), len);
+
+               trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data);
+               mmio_write_buf(data_buf, len, data);
 
-               trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, mmio.len,
-                              fault_ipa, data);
-               mmio_write_buf(mmio.data, mmio.len, data);
+               ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len,
+                                      data_buf);
        } else {
-               trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, mmio.len,
+               trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, len,
                               fault_ipa, 0);
+
+               ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, fault_ipa, len,
+                                     data_buf);
        }
 
-       if (vgic_handle_mmio(vcpu, run, &mmio))
+       /* Now prepare kvm_run for the potential return to userland. */
+       run->mmio.is_write      = is_write;
+       run->mmio.phys_addr     = fault_ipa;
+       run->mmio.len           = len;
+       memcpy(run->mmio.data, data_buf, len);
+
+       if (!ret) {
+               /* We handled the access successfully in the kernel. */
+               kvm_handle_mmio_return(vcpu, run);
                return 1;
+       }
 
-       kvm_prepare_mmio(run, &mmio);
+       run->exit_reason        = KVM_EXIT_MMIO;
        return 0;
 }
index 5656d79c5a44f4d2ca816e15b647abf29a114e0b..15b050d46fc968afdc53029ada4b7d945ee23515 100644 (file)
@@ -1330,10 +1330,51 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 
 out_unlock:
        spin_unlock(&kvm->mmu_lock);
+       kvm_set_pfn_accessed(pfn);
        kvm_release_pfn_clean(pfn);
        return ret;
 }
 
+/*
+ * Resolve the access fault by making the page young again.
+ * Note that because the faulting entry is guaranteed not to be
+ * cached in the TLB, we don't need to invalidate anything.
+ */
+static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
+{
+       pmd_t *pmd;
+       pte_t *pte;
+       pfn_t pfn;
+       bool pfn_valid = false;
+
+       trace_kvm_access_fault(fault_ipa);
+
+       spin_lock(&vcpu->kvm->mmu_lock);
+
+       pmd = stage2_get_pmd(vcpu->kvm, NULL, fault_ipa);
+       if (!pmd || pmd_none(*pmd))     /* Nothing there */
+               goto out;
+
+       if (kvm_pmd_huge(*pmd)) {       /* THP, HugeTLB */
+               *pmd = pmd_mkyoung(*pmd);
+               pfn = pmd_pfn(*pmd);
+               pfn_valid = true;
+               goto out;
+       }
+
+       pte = pte_offset_kernel(pmd, fault_ipa);
+       if (pte_none(*pte))             /* Nothing there either */
+               goto out;
+
+       *pte = pte_mkyoung(*pte);       /* Just a page... */
+       pfn = pte_pfn(*pte);
+       pfn_valid = true;
+out:
+       spin_unlock(&vcpu->kvm->mmu_lock);
+       if (pfn_valid)
+               kvm_set_pfn_accessed(pfn);
+}
+
 /**
  * kvm_handle_guest_abort - handles all 2nd stage aborts
  * @vcpu:      the VCPU pointer
@@ -1364,7 +1405,8 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
        /* Check the stage-2 fault is trans. fault or write fault */
        fault_status = kvm_vcpu_trap_get_fault_type(vcpu);
-       if (fault_status != FSC_FAULT && fault_status != FSC_PERM) {
+       if (fault_status != FSC_FAULT && fault_status != FSC_PERM &&
+           fault_status != FSC_ACCESS) {
                kvm_err("Unsupported FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n",
                        kvm_vcpu_trap_get_class(vcpu),
                        (unsigned long)kvm_vcpu_trap_get_fault(vcpu),
@@ -1400,6 +1442,12 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
        /* Userspace should not be able to register out-of-bounds IPAs */
        VM_BUG_ON(fault_ipa >= KVM_PHYS_SIZE);
 
+       if (fault_status == FSC_ACCESS) {
+               handle_access_fault(vcpu, fault_ipa);
+               ret = 1;
+               goto out_unlock;
+       }
+
        ret = user_mem_abort(vcpu, fault_ipa, memslot, hva, fault_status);
        if (ret == 0)
                ret = 1;
@@ -1408,15 +1456,16 @@ out_unlock:
        return ret;
 }
 
-static void handle_hva_to_gpa(struct kvm *kvm,
-                             unsigned long start,
-                             unsigned long end,
-                             void (*handler)(struct kvm *kvm,
-                                             gpa_t gpa, void *data),
-                             void *data)
+static int handle_hva_to_gpa(struct kvm *kvm,
+                            unsigned long start,
+                            unsigned long end,
+                            int (*handler)(struct kvm *kvm,
+                                           gpa_t gpa, void *data),
+                            void *data)
 {
        struct kvm_memslots *slots;
        struct kvm_memory_slot *memslot;
+       int ret = 0;
 
        slots = kvm_memslots(kvm);
 
@@ -1440,14 +1489,17 @@ static void handle_hva_to_gpa(struct kvm *kvm,
 
                for (; gfn < gfn_end; ++gfn) {
                        gpa_t gpa = gfn << PAGE_SHIFT;
-                       handler(kvm, gpa, data);
+                       ret |= handler(kvm, gpa, data);
                }
        }
+
+       return ret;
 }
 
-static void kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
+static int kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
 {
        unmap_stage2_range(kvm, gpa, PAGE_SIZE);
+       return 0;
 }
 
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
@@ -1473,7 +1525,7 @@ int kvm_unmap_hva_range(struct kvm *kvm,
        return 0;
 }
 
-static void kvm_set_spte_handler(struct kvm *kvm, gpa_t gpa, void *data)
+static int kvm_set_spte_handler(struct kvm *kvm, gpa_t gpa, void *data)
 {
        pte_t *pte = (pte_t *)data;
 
@@ -1485,6 +1537,7 @@ static void kvm_set_spte_handler(struct kvm *kvm, gpa_t gpa, void *data)
         * through this calling path.
         */
        stage2_set_pte(kvm, NULL, gpa, pte, 0);
+       return 0;
 }
 
 
@@ -1501,6 +1554,67 @@ void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
        handle_hva_to_gpa(kvm, hva, end, &kvm_set_spte_handler, &stage2_pte);
 }
 
+static int kvm_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
+{
+       pmd_t *pmd;
+       pte_t *pte;
+
+       pmd = stage2_get_pmd(kvm, NULL, gpa);
+       if (!pmd || pmd_none(*pmd))     /* Nothing there */
+               return 0;
+
+       if (kvm_pmd_huge(*pmd)) {       /* THP, HugeTLB */
+               if (pmd_young(*pmd)) {
+                       *pmd = pmd_mkold(*pmd);
+                       return 1;
+               }
+
+               return 0;
+       }
+
+       pte = pte_offset_kernel(pmd, gpa);
+       if (pte_none(*pte))
+               return 0;
+
+       if (pte_young(*pte)) {
+               *pte = pte_mkold(*pte); /* Just a page... */
+               return 1;
+       }
+
+       return 0;
+}
+
+static int kvm_test_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
+{
+       pmd_t *pmd;
+       pte_t *pte;
+
+       pmd = stage2_get_pmd(kvm, NULL, gpa);
+       if (!pmd || pmd_none(*pmd))     /* Nothing there */
+               return 0;
+
+       if (kvm_pmd_huge(*pmd))         /* THP, HugeTLB */
+               return pmd_young(*pmd);
+
+       pte = pte_offset_kernel(pmd, gpa);
+       if (!pte_none(*pte))            /* Just a page... */
+               return pte_young(*pte);
+
+       return 0;
+}
+
+int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end)
+{
+       trace_kvm_age_hva(start, end);
+       return handle_hva_to_gpa(kvm, start, end, kvm_age_hva_handler, NULL);
+}
+
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       trace_kvm_test_age_hva(hva);
+       return handle_hva_to_gpa(kvm, hva, hva, kvm_test_age_hva_handler, NULL);
+}
+
 void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu)
 {
        mmu_free_memory_cache(&vcpu->arch.mmu_page_cache);
index 6817664b46b80419047066686a47a8bc7953ebeb..0ec35392d2083ac4d8df391de0670d6ea6be6378 100644 (file)
@@ -68,6 +68,21 @@ TRACE_EVENT(kvm_guest_fault,
                  __entry->hxfar, __entry->vcpu_pc)
 );
 
+TRACE_EVENT(kvm_access_fault,
+       TP_PROTO(unsigned long ipa),
+       TP_ARGS(ipa),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  ipa             )
+       ),
+
+       TP_fast_assign(
+               __entry->ipa            = ipa;
+       ),
+
+       TP_printk("IPA: %lx", __entry->ipa)
+);
+
 TRACE_EVENT(kvm_irq_line,
        TP_PROTO(unsigned int type, int vcpu_idx, int irq_num, int level),
        TP_ARGS(type, vcpu_idx, irq_num, level),
@@ -210,6 +225,39 @@ TRACE_EVENT(kvm_set_spte_hva,
        TP_printk("mmu notifier set pte hva: %#08lx", __entry->hva)
 );
 
+TRACE_EVENT(kvm_age_hva,
+       TP_PROTO(unsigned long start, unsigned long end),
+       TP_ARGS(start, end),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  start           )
+               __field(        unsigned long,  end             )
+       ),
+
+       TP_fast_assign(
+               __entry->start          = start;
+               __entry->end            = end;
+       ),
+
+       TP_printk("mmu notifier age hva: %#08lx -- %#08lx",
+                 __entry->start, __entry->end)
+);
+
+TRACE_EVENT(kvm_test_age_hva,
+       TP_PROTO(unsigned long hva),
+       TP_ARGS(hva),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  hva             )
+       ),
+
+       TP_fast_assign(
+               __entry->hva            = hva;
+       ),
+
+       TP_printk("mmu notifier test age hva: %#08lx", __entry->hva)
+);
+
 TRACE_EVENT(kvm_hvc,
        TP_PROTO(unsigned long vcpu_pc, unsigned long r0, unsigned long imm),
        TP_ARGS(vcpu_pc, r0, imm),
index 8a275f2975220f94063442c569510dbe5ea72dc9..91fe9714457004008d4701218deeb1c4cae1bbdf 100644 (file)
@@ -155,17 +155,13 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
 static struct pci_bus __init *
 dove_pcie_scan_bus(int nr, struct pci_sys_data *sys)
 {
-       struct pci_bus *bus;
-
-       if (nr < num_pcie_ports) {
-               bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
-                                       &sys->resources);
-       } else {
-               bus = NULL;
+       if (nr >= num_pcie_ports) {
                BUG();
+               return NULL;
        }
 
-       return bus;
+       return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
+                                &sys->resources);
 }
 
 static int __init dove_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
index 9e9dfdfad9d77fd670fd186d61907f503815cde3..f44c2e05c82e36ae3598ebf7ffe60e54a14235cc 100644 (file)
@@ -166,16 +166,14 @@ static void __init exynos_init_io(void)
        exynos_map_io();
 }
 
+/*
+ * Apparently, these SoCs are not able to wake-up from suspend using
+ * the PMU. Too bad. Should they suddenly become capable of such a
+ * feat, the matches below should be moved to suspend.c.
+ */
 static const struct of_device_id exynos_dt_pmu_match[] = {
-       { .compatible = "samsung,exynos3250-pmu" },
-       { .compatible = "samsung,exynos4210-pmu" },
-       { .compatible = "samsung,exynos4212-pmu" },
-       { .compatible = "samsung,exynos4412-pmu" },
-       { .compatible = "samsung,exynos4415-pmu" },
-       { .compatible = "samsung,exynos5250-pmu" },
        { .compatible = "samsung,exynos5260-pmu" },
        { .compatible = "samsung,exynos5410-pmu" },
-       { .compatible = "samsung,exynos5420-pmu" },
        { /*sentinel*/ },
 };
 
@@ -186,9 +184,6 @@ static void exynos_map_pmu(void)
        np = of_find_matching_node(NULL, exynos_dt_pmu_match);
        if (np)
                pmu_base_addr = of_iomap(np, 0);
-
-       if (!pmu_base_addr)
-               panic("failed to find exynos pmu register\n");
 }
 
 static void __init exynos_init_irq(void)
index 318d127df147c2515f5ecb6674bec31423d790b1..2146d918aedd265623cd3a7cb1393e4437095f3b 100644 (file)
@@ -18,7 +18,9 @@
 #include <linux/syscore_ops.h>
 #include <linux/cpu_pm.h>
 #include <linux/io.h>
-#include <linux/irqchip/arm-gic.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
 #include <linux/err.h>
 #include <linux/regulator/machine.h>
 
@@ -43,8 +45,8 @@
 #define EXYNOS5420_CPU_STATE   0x28
 
 /**
- * struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
- * @hwirq: Hardware IRQ signal of the GIC
+ * struct exynos_wkup_irq - PMU IRQ to mask mapping
+ * @hwirq: Hardware IRQ signal of the PMU
  * @mask: Mask in PMU wake-up mask register
  */
 struct exynos_wkup_irq {
@@ -93,14 +95,14 @@ static const struct exynos_wkup_irq exynos3250_wkup_irq[] = {
 };
 
 static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
-       { 76, BIT(1) }, /* RTC alarm */
-       { 77, BIT(2) }, /* RTC tick */
+       { 44, BIT(1) }, /* RTC alarm */
+       { 45, BIT(2) }, /* RTC tick */
        { /* sentinel */ },
 };
 
 static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
-       { 75, BIT(1) }, /* RTC alarm */
-       { 76, BIT(2) }, /* RTC tick */
+       { 43, BIT(1) }, /* RTC alarm */
+       { 44, BIT(2) }, /* RTC tick */
        { /* sentinel */ },
 };
 
@@ -167,6 +169,113 @@ static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
        return -ENOENT;
 }
 
+static struct irq_chip exynos_pmu_chip = {
+       .name                   = "PMU",
+       .irq_eoi                = irq_chip_eoi_parent,
+       .irq_mask               = irq_chip_mask_parent,
+       .irq_unmask             = irq_chip_unmask_parent,
+       .irq_retrigger          = irq_chip_retrigger_hierarchy,
+       .irq_set_wake           = exynos_irq_set_wake,
+#ifdef CONFIG_SMP
+       .irq_set_affinity       = irq_chip_set_affinity_parent,
+#endif
+};
+
+static int exynos_pmu_domain_xlate(struct irq_domain *domain,
+                                  struct device_node *controller,
+                                  const u32 *intspec,
+                                  unsigned int intsize,
+                                  unsigned long *out_hwirq,
+                                  unsigned int *out_type)
+{
+       if (domain->of_node != controller)
+               return -EINVAL; /* Shouldn't happen, really... */
+       if (intsize != 3)
+               return -EINVAL; /* Not GIC compliant */
+       if (intspec[0] != 0)
+               return -EINVAL; /* No PPI should point to this domain */
+
+       *out_hwirq = intspec[1];
+       *out_type = intspec[2];
+       return 0;
+}
+
+static int exynos_pmu_domain_alloc(struct irq_domain *domain,
+                                  unsigned int virq,
+                                  unsigned int nr_irqs, void *data)
+{
+       struct of_phandle_args *args = data;
+       struct of_phandle_args parent_args;
+       irq_hw_number_t hwirq;
+       int i;
+
+       if (args->args_count != 3)
+               return -EINVAL; /* Not GIC compliant */
+       if (args->args[0] != 0)
+               return -EINVAL; /* No PPI should point to this domain */
+
+       hwirq = args->args[1];
+
+       for (i = 0; i < nr_irqs; i++)
+               irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+                                             &exynos_pmu_chip, NULL);
+
+       parent_args = *args;
+       parent_args.np = domain->parent->of_node;
+       return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+}
+
+static struct irq_domain_ops exynos_pmu_domain_ops = {
+       .xlate  = exynos_pmu_domain_xlate,
+       .alloc  = exynos_pmu_domain_alloc,
+       .free   = irq_domain_free_irqs_common,
+};
+
+static int __init exynos_pmu_irq_init(struct device_node *node,
+                                     struct device_node *parent)
+{
+       struct irq_domain *parent_domain, *domain;
+
+       if (!parent) {
+               pr_err("%s: no parent, giving up\n", node->full_name);
+               return -ENODEV;
+       }
+
+       parent_domain = irq_find_host(parent);
+       if (!parent_domain) {
+               pr_err("%s: unable to obtain parent domain\n", node->full_name);
+               return -ENXIO;
+       }
+
+       pmu_base_addr = of_iomap(node, 0);
+
+       if (!pmu_base_addr) {
+               pr_err("%s: failed to find exynos pmu register\n",
+                      node->full_name);
+               return -ENOMEM;
+       }
+
+       domain = irq_domain_add_hierarchy(parent_domain, 0, 0,
+                                         node, &exynos_pmu_domain_ops,
+                                         NULL);
+       if (!domain) {
+               iounmap(pmu_base_addr);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+#define EXYNOS_PMU_IRQ(symbol, name)   OF_DECLARE_2(irqchip, symbol, name, exynos_pmu_irq_init)
+
+EXYNOS_PMU_IRQ(exynos3250_pmu_irq, "samsung,exynos3250-pmu");
+EXYNOS_PMU_IRQ(exynos4210_pmu_irq, "samsung,exynos4210-pmu");
+EXYNOS_PMU_IRQ(exynos4212_pmu_irq, "samsung,exynos4212-pmu");
+EXYNOS_PMU_IRQ(exynos4412_pmu_irq, "samsung,exynos4412-pmu");
+EXYNOS_PMU_IRQ(exynos4415_pmu_irq, "samsung,exynos4415-pmu");
+EXYNOS_PMU_IRQ(exynos5250_pmu_irq, "samsung,exynos5250-pmu");
+EXYNOS_PMU_IRQ(exynos5420_pmu_irq, "samsung,exynos5420-pmu");
+
 static int exynos_cpu_do_idle(void)
 {
        /* issue the standby signal into the pm unit. */
@@ -615,17 +724,19 @@ static struct syscore_ops exynos_pm_syscore_ops;
 void __init exynos_pm_init(void)
 {
        const struct of_device_id *match;
+       struct device_node *np;
        u32 tmp;
 
-       of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match);
-       if (!match) {
+       np = of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match);
+       if (!np) {
                pr_err("Failed to find PMU node\n");
                return;
        }
-       pm_data = (struct exynos_pm_data *) match->data;
 
-       /* Platform-specific GIC callback */
-       gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
+       if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL)))
+               pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
+
+       pm_data = (struct exynos_pm_data *) match->data;
 
        /* All wakeup disable */
        tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
index e8627e04e1e669e6485d8eb71e142c2acda25fea..c8dffcee97363eec0cb898f73973088496a3b0c6 100644 (file)
@@ -631,6 +631,7 @@ config SOC_IMX6SX
 
 config SOC_VF610
        bool "Vybrid Family VF610 support"
+       select IRQ_DOMAIN_HIERARCHY
        select ARM_GIC
        select PINCTRL_VF610
        select PL310_ERRATA_769419 if CACHE_L2X0
index 445e553f4a28e886469e4cd112ededdde1057ccb..097ea4cb1136f53bc9cf4f7b8857fa816bf3e6be 100644 (file)
@@ -197,17 +197,13 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
 static struct pci_bus __init *
 mv78xx0_pcie_scan_bus(int nr, struct pci_sys_data *sys)
 {
-       struct pci_bus *bus;
-
-       if (nr < num_pcie_ports) {
-               bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
-                                       &sys->resources);
-       } else {
-               bus = NULL;
+       if (nr >= num_pcie_ports) {
                BUG();
+               return NULL;
        }
 
-       return bus;
+       return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
+                                &sys->resources);
 }
 
 static int __init mv78xx0_pcie_map_irq(const struct pci_dev *dev, u8 slot,
index 01e398a868bcbf9d0e33456e8fc70c0a2996848d..57d429830e09b4ceffa71efc3b3b88f6a88c68cd 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/export.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 
 #include <asm/cpuidle.h>
 #include <asm/proc-fns.h>
@@ -84,7 +84,6 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
 {
        struct idle_statedata *cx = state_ptr + index;
        u32 mpuss_can_lose_context = 0;
-       int cpu_id = smp_processor_id();
 
        /*
         * CPU0 has to wait and stay ON until CPU1 is OFF state.
@@ -112,7 +111,7 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
        mpuss_can_lose_context = (cx->mpu_state == PWRDM_POWER_RET) &&
                                 (cx->mpu_logic_state == PWRDM_POWER_OFF);
 
-       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id);
+       tick_broadcast_enter();
 
        /*
         * Call idle CPU PM enter notifier chain so that
@@ -169,7 +168,7 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
        if (dev->cpu == 0 && mpuss_can_lose_context)
                cpu_cluster_pm_exit();
 
-       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id);
+       tick_broadcast_exit();
 
 fail:
        cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
@@ -184,8 +183,7 @@ fail:
  */
 static void omap_setup_broadcast_timer(void *arg)
 {
-       int cpu = smp_processor_id();
-       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
+       tick_broadcast_enable();
 }
 
 static struct cpuidle_driver omap4_idle_driver = {
index dc6e79c4484abbfb097abb322298c37a8b9dd5ca..9a8611ab5dfa60d3bf5e23d6118779db3495ee80 100644 (file)
@@ -150,9 +150,13 @@ static int nop_mmc_set_power(struct device *dev, int power_on, int vdd)
 static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data
                                  *mmc_controller, int controller_nr)
 {
-       if (gpio_is_valid(mmc_controller->switch_pin) &&
-           (mmc_controller->switch_pin < OMAP_MAX_GPIO_LINES))
-               omap_mux_init_gpio(mmc_controller->switch_pin,
+       if (gpio_is_valid(mmc_controller->gpio_cd) &&
+           (mmc_controller->gpio_cd < OMAP_MAX_GPIO_LINES))
+               omap_mux_init_gpio(mmc_controller->gpio_cd,
+                                  OMAP_PIN_INPUT_PULLUP);
+       if (gpio_is_valid(mmc_controller->gpio_cod) &&
+           (mmc_controller->gpio_cod < OMAP_MAX_GPIO_LINES))
+               omap_mux_init_gpio(mmc_controller->gpio_cod,
                                   OMAP_PIN_INPUT_PULLUP);
        if (gpio_is_valid(mmc_controller->gpio_wp) &&
            (mmc_controller->gpio_wp < OMAP_MAX_GPIO_LINES))
@@ -250,15 +254,20 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
        mmc->internal_clock = !c->ext_clock;
        mmc->reg_offset = 0;
 
-       mmc->switch_pin = c->gpio_cd;
+       if (c->cover_only) {
+               /* detect if mobile phone cover removed */
+               mmc->gpio_cd = -EINVAL;
+               mmc->gpio_cod = c->gpio_cd;
+       } else {
+               /* card detect pin on the mmc socket itself */
+               mmc->gpio_cd = c->gpio_cd;
+               mmc->gpio_cod = -EINVAL;
+       }
        mmc->gpio_wp = c->gpio_wp;
 
        mmc->remux = c->remux;
        mmc->init_card = c->init_card;
 
-       if (c->cover_only)
-               mmc->cover = 1;
-
        if (c->nonremovable)
                mmc->nonremovable = 1;
 
@@ -358,7 +367,15 @@ void omap_hsmmc_late_init(struct omap2_hsmmc_info *c)
                if (!mmc_pdata)
                        continue;
 
-               mmc_pdata->switch_pin = c->gpio_cd;
+               if (c->cover_only) {
+                       /* detect if mobile phone cover removed */
+                       mmc_pdata->gpio_cd = -EINVAL;
+                       mmc_pdata->gpio_cod = c->gpio_cd;
+               } else {
+                       /* card detect pin on the mmc socket itself */
+                       mmc_pdata->gpio_cd = c->gpio_cd;
+                       mmc_pdata->gpio_cod = -EINVAL;
+               }
                mmc_pdata->gpio_wp = c->gpio_wp;
 
                res = omap_device_register(pdev);
index f961c46453b97c3ba7aa636af837e4cc66801260..3b56722dfd8a975c77da8e1599207c8b447e290c 100644 (file)
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/cpu_pm.h>
-#include <linux/irqchip/arm-gic.h>
 
 #include "omap-wakeupgen.h"
 #include "omap-secure.h"
@@ -78,29 +79,12 @@ static inline void sar_writel(u32 val, u32 offset, u8 idx)
 
 static inline int _wakeupgen_get_irq_info(u32 irq, u32 *bit_posn, u8 *reg_index)
 {
-       unsigned int spi_irq;
-
-       /*
-        * PPIs and SGIs are not supported.
-        */
-       if (irq < OMAP44XX_IRQ_GIC_START)
-               return -EINVAL;
-
-       /*
-        * Subtract the GIC offset.
-        */
-       spi_irq = irq - OMAP44XX_IRQ_GIC_START;
-       if (spi_irq > MAX_IRQS) {
-               pr_err("omap wakeupGen: Invalid IRQ%d\n", irq);
-               return -EINVAL;
-       }
-
        /*
         * Each WakeupGen register controls 32 interrupt.
         * i.e. 1 bit per SPI IRQ
         */
-       *reg_index = spi_irq >> 5;
-       *bit_posn = spi_irq %= 32;
+       *reg_index = irq >> 5;
+       *bit_posn = irq %= 32;
 
        return 0;
 }
@@ -141,6 +125,7 @@ static void wakeupgen_mask(struct irq_data *d)
        raw_spin_lock_irqsave(&wakeupgen_lock, flags);
        _wakeupgen_clear(d->hwirq, irq_target_cpu[d->hwirq]);
        raw_spin_unlock_irqrestore(&wakeupgen_lock, flags);
+       irq_chip_mask_parent(d);
 }
 
 /*
@@ -153,6 +138,7 @@ static void wakeupgen_unmask(struct irq_data *d)
        raw_spin_lock_irqsave(&wakeupgen_lock, flags);
        _wakeupgen_set(d->hwirq, irq_target_cpu[d->hwirq]);
        raw_spin_unlock_irqrestore(&wakeupgen_lock, flags);
+       irq_chip_unmask_parent(d);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -400,15 +386,91 @@ int omap_secure_apis_support(void)
        return omap_secure_apis;
 }
 
+static struct irq_chip wakeupgen_chip = {
+       .name                   = "WUGEN",
+       .irq_eoi                = irq_chip_eoi_parent,
+       .irq_mask               = wakeupgen_mask,
+       .irq_unmask             = wakeupgen_unmask,
+       .irq_retrigger          = irq_chip_retrigger_hierarchy,
+       .flags                  = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
+#ifdef CONFIG_SMP
+       .irq_set_affinity       = irq_chip_set_affinity_parent,
+#endif
+};
+
+static int wakeupgen_domain_xlate(struct irq_domain *domain,
+                                 struct device_node *controller,
+                                 const u32 *intspec,
+                                 unsigned int intsize,
+                                 unsigned long *out_hwirq,
+                                 unsigned int *out_type)
+{
+       if (domain->of_node != controller)
+               return -EINVAL; /* Shouldn't happen, really... */
+       if (intsize != 3)
+               return -EINVAL; /* Not GIC compliant */
+       if (intspec[0] != 0)
+               return -EINVAL; /* No PPI should point to this domain */
+
+       *out_hwirq = intspec[1];
+       *out_type = intspec[2];
+       return 0;
+}
+
+static int wakeupgen_domain_alloc(struct irq_domain *domain,
+                                 unsigned int virq,
+                                 unsigned int nr_irqs, void *data)
+{
+       struct of_phandle_args *args = data;
+       struct of_phandle_args parent_args;
+       irq_hw_number_t hwirq;
+       int i;
+
+       if (args->args_count != 3)
+               return -EINVAL; /* Not GIC compliant */
+       if (args->args[0] != 0)
+               return -EINVAL; /* No PPI should point to this domain */
+
+       hwirq = args->args[1];
+       if (hwirq >= MAX_IRQS)
+               return -EINVAL; /* Can't deal with this */
+
+       for (i = 0; i < nr_irqs; i++)
+               irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+                                             &wakeupgen_chip, NULL);
+
+       parent_args = *args;
+       parent_args.np = domain->parent->of_node;
+       return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+}
+
+static struct irq_domain_ops wakeupgen_domain_ops = {
+       .xlate  = wakeupgen_domain_xlate,
+       .alloc  = wakeupgen_domain_alloc,
+       .free   = irq_domain_free_irqs_common,
+};
+
 /*
  * Initialise the wakeupgen module.
  */
-int __init omap_wakeupgen_init(void)
+static int __init wakeupgen_init(struct device_node *node,
+                                struct device_node *parent)
 {
+       struct irq_domain *parent_domain, *domain;
        int i;
        unsigned int boot_cpu = smp_processor_id();
        u32 val;
 
+       if (!parent) {
+               pr_err("%s: no parent, giving up\n", node->full_name);
+               return -ENODEV;
+       }
+
+       parent_domain = irq_find_host(parent);
+       if (!parent_domain) {
+               pr_err("%s: unable to obtain parent domain\n", node->full_name);
+               return -ENXIO;
+       }
        /* Not supported on OMAP4 ES1.0 silicon */
        if (omap_rev() == OMAP4430_REV_ES1_0) {
                WARN(1, "WakeupGen: Not supported on OMAP4430 ES1.0\n");
@@ -416,7 +478,7 @@ int __init omap_wakeupgen_init(void)
        }
 
        /* Static mapping, never released */
-       wakeupgen_base = ioremap(OMAP_WKUPGEN_BASE, SZ_4K);
+       wakeupgen_base = of_iomap(node, 0);
        if (WARN_ON(!wakeupgen_base))
                return -ENOMEM;
 
@@ -429,6 +491,14 @@ int __init omap_wakeupgen_init(void)
                max_irqs = AM43XX_IRQS;
        }
 
+       domain = irq_domain_add_hierarchy(parent_domain, 0, max_irqs,
+                                         node, &wakeupgen_domain_ops,
+                                         NULL);
+       if (!domain) {
+               iounmap(wakeupgen_base);
+               return -ENOMEM;
+       }
+
        /* Clear all IRQ bitmasks at wakeupGen level */
        for (i = 0; i < irq_banks; i++) {
                wakeupgen_writel(0, i, CPU0_ID);
@@ -436,14 +506,6 @@ int __init omap_wakeupgen_init(void)
                        wakeupgen_writel(0, i, CPU1_ID);
        }
 
-       /*
-        * Override GIC architecture specific functions to add
-        * OMAP WakeupGen interrupt controller along with GIC
-        */
-       gic_arch_extn.irq_mask = wakeupgen_mask;
-       gic_arch_extn.irq_unmask = wakeupgen_unmask;
-       gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE;
-
        /*
         * FIXME: Add support to set_smp_affinity() once the core
         * GIC code has necessary hooks in place.
@@ -474,3 +536,9 @@ int __init omap_wakeupgen_init(void)
 
        return 0;
 }
+
+/*
+ * We cannot use the IRQCHIP_DECLARE macro that lives in
+ * drivers/irqchip, so we're forced to roll our own. Not very nice.
+ */
+OF_DECLARE_2(irqchip, ti_wakeupgen, "ti,omap4-wugen-mpu", wakeupgen_init);
index b3c8eccfae790de050f853d7528662a3a5c33aa2..a3491ad12368f9fd8e7f03dd12799634d76f3a7e 100644 (file)
@@ -33,7 +33,6 @@
 #define OMAP_TIMESTAMPCYCLELO                  0xc08
 #define OMAP_TIMESTAMPCYCLEHI                  0xc0c
 
-extern int __init omap_wakeupgen_init(void);
 extern void __iomem *omap_get_wakeupgen_base(void);
 extern int omap_secure_apis_support(void);
 #endif
index cee0fe1ee6ffb0d3e5026a7328458feb34dc2732..7bb116a6f86f5b88c35830c2e2b78fd291b43499 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/of_platform.h>
 #include <linux/export.h>
 #include <linux/irqchip/arm-gic.h>
-#include <linux/irqchip/irq-crossbar.h>
 #include <linux/of_address.h>
 #include <linux/reboot.h>
 #include <linux/genalloc.h>
@@ -242,26 +241,26 @@ static int __init omap4_sar_ram_init(void)
 }
 omap_early_initcall(omap4_sar_ram_init);
 
-static const struct of_device_id gic_match[] = {
-       { .compatible = "arm,cortex-a9-gic", },
-       { .compatible = "arm,cortex-a15-gic", },
+static const struct of_device_id intc_match[] = {
+       { .compatible = "ti,omap4-wugen-mpu", },
+       { .compatible = "ti,omap5-wugen-mpu", },
        { },
 };
 
-static struct device_node *gic_node;
+static struct device_node *intc_node;
 
 unsigned int omap4_xlate_irq(unsigned int hwirq)
 {
        struct of_phandle_args irq_data;
        unsigned int irq;
 
-       if (!gic_node)
-               gic_node = of_find_matching_node(NULL, gic_match);
+       if (!intc_node)
+               intc_node = of_find_matching_node(NULL, intc_match);
 
-       if (WARN_ON(!gic_node))
+       if (WARN_ON(!intc_node))
                return hwirq;
 
-       irq_data.np = gic_node;
+       irq_data.np = intc_node;
        irq_data.args_count = 3;
        irq_data.args[0] = 0;
        irq_data.args[1] = hwirq - OMAP44XX_IRQ_GIC_START;
@@ -278,6 +277,12 @@ void __init omap_gic_of_init(void)
 {
        struct device_node *np;
 
+       intc_node = of_find_matching_node(NULL, intc_match);
+       if (WARN_ON(!intc_node)) {
+               pr_err("No WUGEN found in DT, system will misbehave.\n");
+               pr_err("UPDATE YOUR DEVICE TREE!\n");
+       }
+
        /* Extract GIC distributor and TWD bases for OMAP4460 ROM Errata WA */
        if (!cpu_is_omap446x())
                goto skip_errata_init;
@@ -291,9 +296,5 @@ void __init omap_gic_of_init(void)
        WARN_ON(!twd_base);
 
 skip_errata_init:
-       omap_wakeupgen_init();
-#ifdef CONFIG_IRQ_CROSSBAR
-       irqcrossbar_init();
-#endif
        irqchip_init();
 }
index 87a12d6930ffc4525a1a1335789162711968e4fe..b02f3947be516192adb7240ce83fc4eb89318fc2 100644 (file)
@@ -540,37 +540,33 @@ void __init orion5x_pci_set_cardbus_mode(void)
 
 int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys)
 {
-       int ret = 0;
-
        vga_base = ORION5X_PCIE_MEM_PHYS_BASE;
 
        if (nr == 0) {
                orion_pcie_set_local_bus_nr(PCIE_BASE, sys->busnr);
-               ret = pcie_setup(sys);
-       } else if (nr == 1 && !orion5x_pci_disabled) {
+               return pcie_setup(sys);
+       }
+
+       if (nr == 1 && !orion5x_pci_disabled) {
                orion5x_pci_set_bus_nr(sys->busnr);
-               ret = pci_setup(sys);
+               return pci_setup(sys);
        }
 
-       return ret;
+       return 0;
 }
 
 struct pci_bus __init *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys)
 {
-       struct pci_bus *bus;
+       if (nr == 0)
+               return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
+                                        &sys->resources);
 
-       if (nr == 0) {
-               bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
-                                       &sys->resources);
-       } else if (nr == 1 && !orion5x_pci_disabled) {
-               bus = pci_scan_root_bus(NULL, sys->busnr, &pci_ops, sys,
-                                       &sys->resources);
-       } else {
-               bus = NULL;
-               BUG();
-       }
+       if (nr == 1 && !orion5x_pci_disabled)
+               return pci_scan_root_bus(NULL, sys->busnr, &pci_ops, sys,
+                                        &sys->resources);
 
-       return bus;
+       BUG();
+       return NULL;
 }
 
 int __init orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
index a762b23ac830e5a8e90e5e98c2ea66b77c03ac1b..6dc4f025e6743342524cd49f2bef74e9955899e4 100644 (file)
@@ -758,8 +758,10 @@ static void raumfeld_power_signal_charged(void)
        struct power_supply *psy =
                power_supply_get_by_name(raumfeld_power_supplicants[0]);
 
-       if (psy)
+       if (psy) {
                power_supply_set_battery_charged(psy);
+               power_supply_put(psy);
+       }
 }
 
 static int raumfeld_power_resume(void)
index 9e3618028accea72442a4ca8fc1a09b36f267dd2..fd63ae6532fc9ab26149497f68870e81705ed7b7 100644 (file)
@@ -252,11 +252,6 @@ static irqreturn_t sh73a0_intcs_demux(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int sh73a0_set_wake(struct irq_data *data, unsigned int on)
-{
-       return 0; /* always allow wakeup */
-}
-
 #define PINTER0_PHYS 0xe69000a0
 #define PINTER1_PHYS 0xe69000a4
 #define PINTER0_VIRT IOMEM(0xe69000a0)
@@ -318,8 +313,8 @@ void __init sh73a0_init_irq(void)
        void __iomem *gic_cpu_base = IOMEM(0xf0000100);
        void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
 
+       gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE);
        gic_init(0, 29, gic_dist_base, gic_cpu_base);
-       gic_arch_extn.irq_set_wake = sh73a0_set_wake;
 
        register_intc_controller(&intcs_desc);
        register_intc_controller(&intc_pint0_desc);
index 27dceaf9e688c174910004fc80598f4beb130075..c03e562be12b17600e3492dc755a86449a222615 100644 (file)
@@ -713,18 +713,13 @@ void __init r8a7779_init_late(void)
 }
 
 #ifdef CONFIG_USE_OF
-static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
-{
-       return 0; /* always allow wakeup */
-}
-
 void __init r8a7779_init_irq_dt(void)
 {
 #ifdef CONFIG_ARCH_SHMOBILE_LEGACY
        void __iomem *gic_dist_base = ioremap_nocache(0xf0001000, 0x1000);
        void __iomem *gic_cpu_base = ioremap_nocache(0xf0000100, 0x1000);
 #endif
-       gic_arch_extn.irq_set_wake = r8a7779_set_wake;
+       gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE);
 
 #ifdef CONFIG_ARCH_SHMOBILE_LEGACY
        gic_init(0, 29, gic_dist_base, gic_cpu_base);
index f2b586d7b15dfe7cade115ecca4f785324eb15e0..155807fa6fdd0f5a3078064391ac5bb310ba3f53 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 #include <asm/firmware.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/kernel.h>
@@ -44,7 +44,7 @@ static int tegra114_idle_power_down(struct cpuidle_device *dev,
        tegra_set_cpu_in_lp2();
        cpu_pm_enter();
 
-       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+       tick_broadcast_enter();
 
        call_firmware_op(prepare_idle);
 
@@ -52,7 +52,7 @@ static int tegra114_idle_power_down(struct cpuidle_device *dev,
        if (call_firmware_op(do_idle, 0) == -ENOSYS)
                cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
 
-       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+       tick_broadcast_exit();
 
        cpu_pm_exit();
        tegra_clear_cpu_in_lp2();
index 4f25a7c7ca0fed7b74c8aab8b0f4281021f9e175..48844ae6c3a119b8493aaffef1c805cf929c7111 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 #include <linux/clk/tegra.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/kernel.h>
@@ -136,11 +136,11 @@ static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
        if (tegra20_reset_cpu_1() || !tegra_cpu_rail_off_ready())
                return false;
 
-       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+       tick_broadcast_enter();
 
        tegra_idle_lp2_last();
 
-       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+       tick_broadcast_exit();
 
        if (cpu_online(1))
                tegra20_wake_cpu1_from_reset();
@@ -153,13 +153,13 @@ static bool tegra20_idle_enter_lp2_cpu_1(struct cpuidle_device *dev,
                                         struct cpuidle_driver *drv,
                                         int index)
 {
-       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+       tick_broadcast_enter();
 
        cpu_suspend(0, tegra20_sleep_cpu_secondary_finish);
 
        tegra20_cpu_clear_resettable();
 
-       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+       tick_broadcast_exit();
 
        return true;
 }
index f8815ed65d9d5227b3f21ddea6c316bb9e24723a..84d809a3cba3b2f720d261ece0dc07df14ec72cf 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 #include <linux/clk/tegra.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/kernel.h>
@@ -76,11 +76,11 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
                return false;
        }
 
-       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+       tick_broadcast_enter();
 
        tegra_idle_lp2_last();
 
-       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+       tick_broadcast_exit();
 
        return true;
 }
@@ -90,13 +90,13 @@ static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
                                        struct cpuidle_driver *drv,
                                        int index)
 {
-       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+       tick_broadcast_enter();
 
        smp_wmb();
 
        cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
 
-       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+       tick_broadcast_exit();
 
        return true;
 }
index ee79808e93a3f2edf91e43f2f6c069917cf1f4dd..81dc950b4881c072409341a49279b0ade87f3fa7 100644 (file)
 #define TEGRA_ARM_INT_DIST_BASE                0x50041000
 #define TEGRA_ARM_INT_DIST_SIZE                SZ_4K
 
-#define TEGRA_PRIMARY_ICTLR_BASE       0x60004000
-#define TEGRA_PRIMARY_ICTLR_SIZE       SZ_64
-
-#define TEGRA_SECONDARY_ICTLR_BASE     0x60004100
-#define TEGRA_SECONDARY_ICTLR_SIZE     SZ_64
-
-#define TEGRA_TERTIARY_ICTLR_BASE      0x60004200
-#define TEGRA_TERTIARY_ICTLR_SIZE      SZ_64
-
-#define TEGRA_QUATERNARY_ICTLR_BASE    0x60004300
-#define TEGRA_QUATERNARY_ICTLR_SIZE    SZ_64
-
-#define TEGRA_QUINARY_ICTLR_BASE       0x60004400
-#define TEGRA_QUINARY_ICTLR_SIZE       SZ_64
-
 #define TEGRA_TMR1_BASE                        0x60005000
 #define TEGRA_TMR1_SIZE                        SZ_8
 
index ab95f5391a2b631e5cace17bbb176766e7d410bf..3b9098d27ea57146771ba55e8d5a8d823b7f5227 100644 (file)
 #include "board.h"
 #include "iomap.h"
 
-#define ICTLR_CPU_IEP_VFIQ     0x08
-#define ICTLR_CPU_IEP_FIR      0x14
-#define ICTLR_CPU_IEP_FIR_SET  0x18
-#define ICTLR_CPU_IEP_FIR_CLR  0x1c
-
-#define ICTLR_CPU_IER          0x20
-#define ICTLR_CPU_IER_SET      0x24
-#define ICTLR_CPU_IER_CLR      0x28
-#define ICTLR_CPU_IEP_CLASS    0x2C
-
-#define ICTLR_COP_IER          0x30
-#define ICTLR_COP_IER_SET      0x34
-#define ICTLR_COP_IER_CLR      0x38
-#define ICTLR_COP_IEP_CLASS    0x3c
-
-#define FIRST_LEGACY_IRQ 32
-#define TEGRA_MAX_NUM_ICTLRS   5
-
 #define SGI_MASK 0xFFFF
 
-static int num_ictlrs;
-
-static void __iomem *ictlr_reg_base[] = {
-       IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE),
-       IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE),
-       IO_ADDRESS(TEGRA_TERTIARY_ICTLR_BASE),
-       IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE),
-       IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE),
-};
-
 #ifdef CONFIG_PM_SLEEP
-static u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
-static u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
-static u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
-static u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
-
-static u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
 static void __iomem *tegra_gic_cpu_base;
 #endif
 
@@ -83,140 +49,7 @@ bool tegra_pending_sgi(void)
        return false;
 }
 
-static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg)
-{
-       void __iomem *base;
-       u32 mask;
-
-       BUG_ON(irq < FIRST_LEGACY_IRQ ||
-               irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32);
-
-       base = ictlr_reg_base[(irq - FIRST_LEGACY_IRQ) / 32];
-       mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
-
-       __raw_writel(mask, base + reg);
-}
-
-static void tegra_mask(struct irq_data *d)
-{
-       if (d->hwirq < FIRST_LEGACY_IRQ)
-               return;
-
-       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_CLR);
-}
-
-static void tegra_unmask(struct irq_data *d)
-{
-       if (d->hwirq < FIRST_LEGACY_IRQ)
-               return;
-
-       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_SET);
-}
-
-static void tegra_ack(struct irq_data *d)
-{
-       if (d->hwirq < FIRST_LEGACY_IRQ)
-               return;
-
-       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
-}
-
-static void tegra_eoi(struct irq_data *d)
-{
-       if (d->hwirq < FIRST_LEGACY_IRQ)
-               return;
-
-       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
-}
-
-static int tegra_retrigger(struct irq_data *d)
-{
-       if (d->hwirq < FIRST_LEGACY_IRQ)
-               return 0;
-
-       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_SET);
-
-       return 1;
-}
-
 #ifdef CONFIG_PM_SLEEP
-static int tegra_set_wake(struct irq_data *d, unsigned int enable)
-{
-       u32 irq = d->hwirq;
-       u32 index, mask;
-
-       if (irq < FIRST_LEGACY_IRQ ||
-               irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32)
-               return -EINVAL;
-
-       index = ((irq - FIRST_LEGACY_IRQ) / 32);
-       mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
-       if (enable)
-               ictlr_wake_mask[index] |= mask;
-       else
-               ictlr_wake_mask[index] &= ~mask;
-
-       return 0;
-}
-
-static int tegra_legacy_irq_suspend(void)
-{
-       unsigned long flags;
-       int i;
-
-       local_irq_save(flags);
-       for (i = 0; i < num_ictlrs; i++) {
-               void __iomem *ictlr = ictlr_reg_base[i];
-               /* Save interrupt state */
-               cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
-               cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
-               cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
-               cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
-
-               /* Disable COP interrupts */
-               writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
-
-               /* Disable CPU interrupts */
-               writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
-
-               /* Enable the wakeup sources of ictlr */
-               writel_relaxed(ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
-       }
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-static void tegra_legacy_irq_resume(void)
-{
-       unsigned long flags;
-       int i;
-
-       local_irq_save(flags);
-       for (i = 0; i < num_ictlrs; i++) {
-               void __iomem *ictlr = ictlr_reg_base[i];
-               writel_relaxed(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
-               writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
-               writel_relaxed(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
-               writel_relaxed(cop_iep[i], ictlr + ICTLR_COP_IEP_CLASS);
-               writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
-               writel_relaxed(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
-       }
-       local_irq_restore(flags);
-}
-
-static struct syscore_ops tegra_legacy_irq_syscore_ops = {
-       .suspend = tegra_legacy_irq_suspend,
-       .resume = tegra_legacy_irq_resume,
-};
-
-int tegra_legacy_irq_syscore_init(void)
-{
-       register_syscore_ops(&tegra_legacy_irq_syscore_ops);
-
-       return 0;
-}
-
 static int tegra_gic_notifier(struct notifier_block *self,
                              unsigned long cmd, void *v)
 {
@@ -251,45 +84,19 @@ static void tegra114_gic_cpu_pm_registration(void)
        cpu_pm_register_notifier(&tegra_gic_notifier_block);
 }
 #else
-#define tegra_set_wake NULL
 static void tegra114_gic_cpu_pm_registration(void) { }
 #endif
 
+static const struct of_device_id tegra_ictlr_match[] __initconst = {
+       { .compatible = "nvidia,tegra20-ictlr" },
+       { .compatible = "nvidia,tegra30-ictlr" },
+       { }
+};
+
 void __init tegra_init_irq(void)
 {
-       int i;
-       void __iomem *distbase;
-
-       distbase = IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE);
-       num_ictlrs = readl_relaxed(distbase + GIC_DIST_CTR) & 0x1f;
-
-       if (num_ictlrs > ARRAY_SIZE(ictlr_reg_base)) {
-               WARN(1, "Too many (%d) interrupt controllers found. Maximum is %d.",
-                       num_ictlrs, ARRAY_SIZE(ictlr_reg_base));
-               num_ictlrs = ARRAY_SIZE(ictlr_reg_base);
-       }
-
-       for (i = 0; i < num_ictlrs; i++) {
-               void __iomem *ictlr = ictlr_reg_base[i];
-               writel(~0, ictlr + ICTLR_CPU_IER_CLR);
-               writel(0, ictlr + ICTLR_CPU_IEP_CLASS);
-       }
-
-       gic_arch_extn.irq_ack = tegra_ack;
-       gic_arch_extn.irq_eoi = tegra_eoi;
-       gic_arch_extn.irq_mask = tegra_mask;
-       gic_arch_extn.irq_unmask = tegra_unmask;
-       gic_arch_extn.irq_retrigger = tegra_retrigger;
-       gic_arch_extn.irq_set_wake = tegra_set_wake;
-       gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
-
-       /*
-        * Check if there is a devicetree present, since the GIC will be
-        * initialized elsewhere under DT.
-        */
-       if (!of_have_populated_dt())
-               gic_init(0, 29, distbase,
-                       IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
+       if (WARN_ON(!of_find_matching_node(NULL, tegra_ictlr_match)))
+               pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
 
        tegra114_gic_cpu_pm_registration();
 }
index bc05ce5613fbf79195159f8eef03324992a5c73d..5142649bba05513b46ead7a336b3082141ac41da 100644 (file)
 
 bool tegra_pending_sgi(void);
 
-#ifdef CONFIG_PM_SLEEP
-int tegra_legacy_irq_syscore_init(void);
-#else
-static inline int tegra_legacy_irq_syscore_init(void) { return 0; }
-#endif
-
 #endif
index 914341bcef25faf08631113ce98b90228d728d9a..861d88486dbec233d4ab52a42af4f666ab48ba7c 100644 (file)
@@ -82,7 +82,6 @@ static void __init tegra_dt_init_irq(void)
 {
        tegra_init_irq();
        irqchip_init();
-       tegra_legacy_irq_syscore_init();
 }
 
 static void __init tegra_dt_init(void)
index dbb2970ee7da31e256b5394a79eacd2f53bf991b..6ced0f6802629f8e94ff67ccdd9fe185e4418bc6 100644 (file)
@@ -52,7 +52,7 @@ void ux500_restart(enum reboot_mode mode, const char *cmd)
 */
 void __init ux500_init_irq(void)
 {
-       gic_arch_extn.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
+       gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND);
        irqchip_init();
 
        /*
index c887196cfdbefac29d2b9e6c8da0a6769da26e0d..58ef2a700414fcca15d58091223778746c1d1c8d 100644 (file)
@@ -186,7 +186,7 @@ static void __init zynq_map_io(void)
 
 static void __init zynq_irq_init(void)
 {
-       gic_arch_extn.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
+       gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND);
        irqchip_init();
 }
 
index c27447653903f1134594fe309dc885285ea43bb3..e315dfe3af1b46e4a441085a89cdff2116d5a5c8 100644 (file)
@@ -2027,6 +2027,13 @@ static bool arm_setup_iommu_dma_ops(struct device *dev, u64 dma_base, u64 size,
        if (!iommu)
                return false;
 
+       /*
+        * currently arm_iommu_create_mapping() takes a max of size_t
+        * for size param. So check this limit for now.
+        */
+       if (size > SIZE_MAX)
+               return false;
+
        mapping = arm_iommu_create_mapping(dev->bus, dma_base, size);
        if (IS_ERR(mapping)) {
                pr_warn("Failed to create %llu-byte IOMMU mapping for device %s\n",
index 1609b022a72fa20254bf367dbb5e41d8e9e84f67..3d0e9aed4b40990111213feeb5ff96fd8ab9e09b 100644 (file)
@@ -335,6 +335,9 @@ void __init bootmem_init(void)
 
        find_limits(&min, &max_low, &max_high);
 
+       early_memtest((phys_addr_t)min << PAGE_SHIFT,
+                     (phys_addr_t)max_low << PAGE_SHIFT);
+
        /*
         * Sparsemem tries to allocate bootmem in memory_present(),
         * so must be done after the fixed reservations
index 5e85ed371364c17657be7d7155139a5e3f536437..407dc786583aec0e6077f50a8374f99002ca8233 100644 (file)
@@ -169,14 +169,22 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        return addr;
 }
 
+unsigned long arch_mmap_rnd(void)
+{
+       unsigned long rnd;
+
+       /* 8 bits of randomness in 20 address space bits */
+       rnd = (unsigned long)get_random_int() % (1 << 8);
+
+       return rnd << PAGE_SHIFT;
+}
+
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
        unsigned long random_factor = 0UL;
 
-       /* 8 bits of randomness in 20 address space bits */
-       if ((current->flags & PF_RANDOMIZE) &&
-           !(current->personality & ADDR_NO_RANDOMIZE))
-               random_factor = (get_random_int() % (1 << 8)) << PAGE_SHIFT;
+       if (current->flags & PF_RANDOMIZE)
+               random_factor = arch_mmap_rnd();
 
        if (mmap_is_legacy()) {
                mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
index 61b4d705c26720eb88f2dbcf7eab72361d31d14d..2438b96004c1c36013cb8e55fe2fb4b2eb180663 100644 (file)
@@ -44,24 +44,20 @@ static u64 notrace omap_32k_read_sched_clock(void)
 }
 
 /**
- * omap_read_persistent_clock -  Return time from a persistent clock.
+ * omap_read_persistent_clock64 -  Return time from a persistent clock.
  *
  * Reads the time from a source which isn't disabled during PM, the
  * 32k sync timer.  Convert the cycles elapsed since last read into
- * nsecs and adds to a monotonically increasing timespec.
+ * nsecs and adds to a monotonically increasing timespec64.
  */
-static struct timespec persistent_ts;
+static struct timespec64 persistent_ts;
 static cycles_t cycles;
 static unsigned int persistent_mult, persistent_shift;
-static DEFINE_SPINLOCK(read_persistent_clock_lock);
 
-static void omap_read_persistent_clock(struct timespec *ts)
+static void omap_read_persistent_clock64(struct timespec64 *ts)
 {
        unsigned long long nsecs;
        cycles_t last_cycles;
-       unsigned long flags;
-
-       spin_lock_irqsave(&read_persistent_clock_lock, flags);
 
        last_cycles = cycles;
        cycles = sync32k_cnt_reg ? readl_relaxed(sync32k_cnt_reg) : 0;
@@ -69,11 +65,9 @@ static void omap_read_persistent_clock(struct timespec *ts)
        nsecs = clocksource_cyc2ns(cycles - last_cycles,
                                        persistent_mult, persistent_shift);
 
-       timespec_add_ns(&persistent_ts, nsecs);
+       timespec64_add_ns(&persistent_ts, nsecs);
 
        *ts = persistent_ts;
-
-       spin_unlock_irqrestore(&read_persistent_clock_lock, flags);
 }
 
 /**
@@ -103,7 +97,7 @@ int __init omap_init_clocksource_32k(void __iomem *vbase)
 
        /*
         * 120000 rough estimate from the calculations in
-        * __clocksource_updatefreq_scale.
+        * __clocksource_update_freq_scale.
         */
        clocks_calc_mult_shift(&persistent_mult, &persistent_shift,
                        32768, NSEC_PER_SEC, 120000);
@@ -116,7 +110,7 @@ int __init omap_init_clocksource_32k(void __iomem *vbase)
        }
 
        sched_clock_register(omap_32k_read_sched_clock, 32, 32768);
-       register_persistent_clock(NULL, omap_read_persistent_clock);
+       register_persistent_clock(NULL, omap_read_persistent_clock64);
        pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n");
 
        return 0;
index 1b8e97331ffbdba1e8a6c6307ab76d3bc2f73028..34f487d5d84e4dbdc5253b2fd7b9f1a248d31646 100644 (file)
@@ -1,7 +1,7 @@
 config ARM64
        def_bool y
-       select ARCH_BINFMT_ELF_RANDOMIZE_PIE
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+       select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_GCOV_PROFILE_ALL
        select ARCH_HAS_SG_CHAIN
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
@@ -143,6 +143,13 @@ config KERNEL_MODE_NEON
 config FIX_EARLYCON_MEM
        def_bool y
 
+config PGTABLE_LEVELS
+       int
+       default 2 if ARM64_64K_PAGES && ARM64_VA_BITS_42
+       default 3 if ARM64_64K_PAGES && ARM64_VA_BITS_48
+       default 3 if ARM64_4K_PAGES && ARM64_VA_BITS_39
+       default 4 if ARM64_4K_PAGES && ARM64_VA_BITS_48
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
@@ -413,13 +420,6 @@ config ARM64_VA_BITS
        default 42 if ARM64_VA_BITS_42
        default 48 if ARM64_VA_BITS_48
 
-config ARM64_PGTABLE_LEVELS
-       int
-       default 2 if ARM64_64K_PAGES && ARM64_VA_BITS_42
-       default 3 if ARM64_64K_PAGES && ARM64_VA_BITS_48
-       default 3 if ARM64_4K_PAGES && ARM64_VA_BITS_39
-       default 4 if ARM64_4K_PAGES && ARM64_VA_BITS_48
-
 config CPU_BIG_ENDIAN
        bool "Build big-endian kernel"
        help
index 1f65be3931392c24352763bb9365430d48670b41..faad6df49e5b00a49f2b82f06dc48b735662e55c 100644 (file)
@@ -125,7 +125,6 @@ typedef struct user_fpsimd_state elf_fpregset_t;
  * the loader.  We need to make sure that it is out of the way of the program
  * that it will "exec", and that there is sufficient room for the brk.
  */
-extern unsigned long randomize_et_dyn(unsigned long base);
 #define ELF_ET_DYN_BASE        (2 * TASK_SIZE_64 / 3)
 
 /*
@@ -157,10 +156,6 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 #define STACK_RND_MASK                 (0x3ffff >> (PAGE_SHIFT - 12))
 #endif
 
-struct mm_struct;
-extern unsigned long arch_randomize_brk(struct mm_struct *mm);
-#define arch_randomize_brk arch_randomize_brk
-
 #ifdef CONFIG_COMPAT
 
 #ifdef __AARCH64EB__
index 92bbae38159821cb6ce45ab3dab456c7eedced15..70522450ca2342a66b3ec27167bb94e08590f6d1 100644 (file)
@@ -90,6 +90,7 @@
 #define ESR_ELx_FSC            (0x3F)
 #define ESR_ELx_FSC_TYPE       (0x3C)
 #define ESR_ELx_FSC_EXTABT     (0x10)
+#define ESR_ELx_FSC_ACCESS     (0x08)
 #define ESR_ELx_FSC_FAULT      (0x04)
 #define ESR_ELx_FSC_PERM       (0x0C)
 #define ESR_ELx_CV             (UL(1) << 24)
index 076a1c714049ffede6cf8fb3d46c6efcf3ac7f1f..c0e5165c2f76d3c1b979bbaac11121f6e27885da 100644 (file)
  */
 #ifndef __ASM_JUMP_LABEL_H
 #define __ASM_JUMP_LABEL_H
+
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <asm/insn.h>
 
-#ifdef __KERNEL__
-
 #define JUMP_LABEL_NOP_SIZE            AARCH64_INSN_SIZE
 
 static __always_inline bool arch_static_branch(struct static_key *key)
@@ -39,8 +40,6 @@ l_yes:
        return true;
 }
 
-#endif /* __KERNEL__ */
-
 typedef u64 jump_label_t;
 
 struct jump_entry {
@@ -49,4 +48,5 @@ struct jump_entry {
        jump_label_t key;
 };
 
+#endif  /* __ASSEMBLY__ */
 #endif /* __ASM_JUMP_LABEL_H */
index 54bb4ba974417e269656d50adb524654851fbbd2..ac6fafb95fe71e48048fe3831f226853f2f4914d 100644 (file)
 
 /* For compatibility with fault code shared with 32-bit */
 #define FSC_FAULT      ESR_ELx_FSC_FAULT
+#define FSC_ACCESS     ESR_ELx_FSC_ACCESS
 #define FSC_PERM       ESR_ELx_FSC_PERM
 
 /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
index 8ac3c70fe3c6ae7f234c5505a4a3c0e5bbd6c4ff..f0f58c9beec0e87c8c7eefa7a8ba52ba518e07c3 100644 (file)
@@ -28,6 +28,8 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmio.h>
 
+#define __KVM_HAVE_ARCH_INTC_INITIALIZED
+
 #if defined(CONFIG_KVM_ARM_MAX_VCPUS)
 #define KVM_MAX_VCPUS CONFIG_KVM_ARM_MAX_VCPUS
 #else
@@ -177,19 +179,10 @@ int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
 int kvm_unmap_hva_range(struct kvm *kvm,
                        unsigned long start, unsigned long end);
 void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
+int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
 
 /* We do not have shadow page tables, hence the empty hooks */
-static inline int kvm_age_hva(struct kvm *kvm, unsigned long start,
-                             unsigned long end)
-{
-       return 0;
-}
-
-static inline int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
-{
-       return 0;
-}
-
 static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
                                                         unsigned long address)
 {
index 9f52beb7cb1355e1ebf129b899830b7b463d67b2..889c908ee631b526594b5dfc32ef5dfde15480df 100644 (file)
@@ -31,28 +31,6 @@ struct kvm_decode {
        bool sign_extend;
 };
 
-/*
- * The in-kernel MMIO emulation code wants to use a copy of run->mmio,
- * which is an anonymous type. Use our own type instead.
- */
-struct kvm_exit_mmio {
-       phys_addr_t     phys_addr;
-       u8              data[8];
-       u32             len;
-       bool            is_write;
-       void            *private;
-};
-
-static inline void kvm_prepare_mmio(struct kvm_run *run,
-                                   struct kvm_exit_mmio *mmio)
-{
-       run->mmio.phys_addr     = mmio->phys_addr;
-       run->mmio.len           = mmio->len;
-       run->mmio.is_write      = mmio->is_write;
-       memcpy(run->mmio.data, mmio->data, mmio->len);
-       run->exit_reason        = KVM_EXIT_MMIO;
-}
-
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
                 phys_addr_t fault_ipa);
index bbfb600fa82295a8a81c85603254946422b70992..36250705dc4c0fe242057e8a4c793c56dc1db951 100644 (file)
@@ -163,12 +163,12 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd)
 /*
  * If we are concatenating first level stage-2 page tables, we would have less
  * than or equal to 16 pointers in the fake PGD, because that's what the
- * architecture allows.  In this case, (4 - CONFIG_ARM64_PGTABLE_LEVELS)
+ * architecture allows.  In this case, (4 - CONFIG_PGTABLE_LEVELS)
  * represents the first level for the host, and we add 1 to go to the next
  * level (which uses contatenation) for the stage-2 tables.
  */
 #if PTRS_PER_S2_PGD <= 16
-#define KVM_PREALLOC_LEVEL     (4 - CONFIG_ARM64_PGTABLE_LEVELS + 1)
+#define KVM_PREALLOC_LEVEL     (4 - CONFIG_PGTABLE_LEVELS + 1)
 #else
 #define KVM_PREALLOC_LEVEL     (0)
 #endif
index 22b16232bd609b7a916c4214df0e53819abe82fb..8fc8fa280e92a4ed468807211f05b5662c7ce292 100644 (file)
@@ -36,9 +36,9 @@
  * for more information).
  */
 #ifdef CONFIG_ARM64_64K_PAGES
-#define SWAPPER_PGTABLE_LEVELS (CONFIG_ARM64_PGTABLE_LEVELS)
+#define SWAPPER_PGTABLE_LEVELS (CONFIG_PGTABLE_LEVELS)
 #else
-#define SWAPPER_PGTABLE_LEVELS (CONFIG_ARM64_PGTABLE_LEVELS - 1)
+#define SWAPPER_PGTABLE_LEVELS (CONFIG_PGTABLE_LEVELS - 1)
 #endif
 
 #define SWAPPER_DIR_SIZE       (SWAPPER_PGTABLE_LEVELS * PAGE_SIZE)
index e20df38a8ff3885409291b8c2f7b7edfeb4b6cb7..76420568d66a463d7ba74fdf8a74ba916dd1dbd8 100644 (file)
@@ -28,7 +28,7 @@
 
 #define PGALLOC_GFP    (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
 
-#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+#if CONFIG_PGTABLE_LEVELS > 2
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
@@ -46,9 +46,9 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
        set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE));
 }
 
-#endif /* CONFIG_ARM64_PGTABLE_LEVELS > 2 */
+#endif /* CONFIG_PGTABLE_LEVELS > 2 */
 
-#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+#if CONFIG_PGTABLE_LEVELS > 3
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
@@ -66,7 +66,7 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
        set_pgd(pgd, __pgd(__pa(pud) | PUD_TYPE_TABLE));
 }
 
-#endif /* CONFIG_ARM64_PGTABLE_LEVELS > 3 */
+#endif /* CONFIG_PGTABLE_LEVELS > 3 */
 
 extern pgd_t *pgd_alloc(struct mm_struct *mm);
 extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
index 5f930cc9ea83956c496df721fc0e384dc8b862d9..80f3d241cff806b124b4c7e5650604d206139244 100644 (file)
@@ -21,7 +21,7 @@
 /*
  * PMD_SHIFT determines the size a level 2 page table entry can map.
  */
-#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+#if CONFIG_PGTABLE_LEVELS > 2
 #define PMD_SHIFT              ((PAGE_SHIFT - 3) * 2 + 3)
 #define PMD_SIZE               (_AC(1, UL) << PMD_SHIFT)
 #define PMD_MASK               (~(PMD_SIZE-1))
@@ -31,7 +31,7 @@
 /*
  * PUD_SHIFT determines the size a level 1 page table entry can map.
  */
-#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+#if CONFIG_PGTABLE_LEVELS > 3
 #define PUD_SHIFT              ((PAGE_SHIFT - 3) * 3 + 3)
 #define PUD_SIZE               (_AC(1, UL) << PUD_SHIFT)
 #define PUD_MASK               (~(PUD_SIZE-1))
@@ -42,7 +42,7 @@
  * PGDIR_SHIFT determines the size a top-level page table entry can map
  * (depending on the configuration, this level can be 0, 1 or 2).
  */
-#define PGDIR_SHIFT            ((PAGE_SHIFT - 3) * CONFIG_ARM64_PGTABLE_LEVELS + 3)
+#define PGDIR_SHIFT            ((PAGE_SHIFT - 3) * CONFIG_PGTABLE_LEVELS + 3)
 #define PGDIR_SIZE             (_AC(1, UL) << PGDIR_SHIFT)
 #define PGDIR_MASK             (~(PGDIR_SIZE-1))
 #define PTRS_PER_PGD           (1 << (VA_BITS - PGDIR_SHIFT))
index ca9df80af896fd1da1a9e272bb831d7c562fad60..2b1bd7e52c3b25e2d6ad93998e293df4054f49e1 100644 (file)
@@ -38,13 +38,13 @@ typedef struct { pteval_t pte; } pte_t;
 #define pte_val(x)     ((x).pte)
 #define __pte(x)       ((pte_t) { (x) } )
 
-#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+#if CONFIG_PGTABLE_LEVELS > 2
 typedef struct { pmdval_t pmd; } pmd_t;
 #define pmd_val(x)     ((x).pmd)
 #define __pmd(x)       ((pmd_t) { (x) } )
 #endif
 
-#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+#if CONFIG_PGTABLE_LEVELS > 3
 typedef struct { pudval_t pud; } pud_t;
 #define pud_val(x)     ((x).pud)
 #define __pud(x)       ((pud_t) { (x) } )
@@ -64,13 +64,13 @@ typedef pteval_t pte_t;
 #define pte_val(x)     (x)
 #define __pte(x)       (x)
 
-#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+#if CONFIG_PGTABLE_LEVELS > 2
 typedef pmdval_t pmd_t;
 #define pmd_val(x)     (x)
 #define __pmd(x)       (x)
 #endif
 
-#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+#if CONFIG_PGTABLE_LEVELS > 3
 typedef pudval_t pud_t;
 #define pud_val(x)     (x)
 #define __pud(x)       (x)
@@ -86,9 +86,9 @@ typedef pteval_t pgprot_t;
 
 #endif /* STRICT_MM_TYPECHECKS */
 
-#if CONFIG_ARM64_PGTABLE_LEVELS == 2
+#if CONFIG_PGTABLE_LEVELS == 2
 #include <asm-generic/pgtable-nopmd.h>
-#elif CONFIG_ARM64_PGTABLE_LEVELS == 3
+#elif CONFIG_PGTABLE_LEVELS == 3
 #include <asm-generic/pgtable-nopud.h>
 #endif
 
index 800ec0e87ed955bbd38e93e448b19b6b4401625b..56283f8a675c5f82ac5071fa7863e3d1fce68ed9 100644 (file)
@@ -374,7 +374,7 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
  */
 #define mk_pte(page,prot)      pfn_pte(page_to_pfn(page),prot)
 
-#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+#if CONFIG_PGTABLE_LEVELS > 2
 
 #define pmd_ERROR(pmd)         __pmd_error(__FILE__, __LINE__, pmd_val(pmd))
 
@@ -409,9 +409,9 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
 
 #define pud_page(pud)          pfn_to_page(__phys_to_pfn(pud_val(pud) & PHYS_MASK))
 
-#endif /* CONFIG_ARM64_PGTABLE_LEVELS > 2 */
+#endif /* CONFIG_PGTABLE_LEVELS > 2 */
 
-#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+#if CONFIG_PGTABLE_LEVELS > 3
 
 #define pud_ERROR(pud)         __pud_error(__FILE__, __LINE__, pud_val(pud))
 
@@ -445,7 +445,7 @@ static inline pud_t *pud_offset(pgd_t *pgd, unsigned long addr)
 
 #define pgd_page(pgd)          pfn_to_page(__phys_to_pfn(pgd_val(pgd) & PHYS_MASK))
 
-#endif  /* CONFIG_ARM64_PGTABLE_LEVELS > 3 */
+#endif  /* CONFIG_PGTABLE_LEVELS > 3 */
 
 #define pgd_ERROR(pgd)         __pgd_error(__FILE__, __LINE__, pgd_val(pgd))
 
index 53d9c354219f9737c4d6e47ee3d1123c8e9588ce..3a0242c7eb8daba49fbfa72c16b872060f1de3d5 100644 (file)
@@ -53,7 +53,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
        tlb_remove_entry(tlb, pte);
 }
 
-#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+#if CONFIG_PGTABLE_LEVELS > 2
 static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
                                  unsigned long addr)
 {
@@ -62,7 +62,7 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
 }
 #endif
 
-#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+#if CONFIG_PGTABLE_LEVELS > 3
 static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pudp,
                                  unsigned long addr)
 {
index 3ef77a4660187ace735216639ffc1e8f8d11a38b..c154c0b7eb604ae09214beed276063f222af69ae 100644 (file)
@@ -191,6 +191,9 @@ struct kvm_arch_memory_slot {
 /* Highest supported SPI, from VGIC_NR_IRQS */
 #define KVM_ARM_IRQ_GIC_MAX            127
 
+/* One single KVM irqchip, ie. the VGIC */
+#define KVM_NR_IRQCHIPS          1
+
 /* PSCI interface */
 #define KVM_PSCI_FN_BASE               0x95c1ba5e
 #define KVM_PSCI_FN(n)                 (KVM_PSCI_FN_BASE + (n))
index 98bbe06e469c91faf72218b95a52d3d429b0502a..e7d934d3afe02817fc53bf437d19c36195025b79 100644 (file)
@@ -527,7 +527,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
         * Disallow per-task kernel breakpoints since these would
         * complicate the stepping code.
         */
-       if (info->ctrl.privilege == AARCH64_BREAKPOINT_EL1 && bp->hw.bp_target)
+       if (info->ctrl.privilege == AARCH64_BREAKPOINT_EL1 && bp->hw.target)
                return -EINVAL;
 
        return 0;
index 32aeea083d93b2391122ad9d1c49c3925121e38b..ec37ab3f524f303419d2cc3a82b79c119e61de1d 100644 (file)
@@ -200,7 +200,7 @@ up_fail:
 void update_vsyscall(struct timekeeper *tk)
 {
        struct timespec xtime_coarse;
-       u32 use_syscall = strcmp(tk->tkr.clock->name, "arch_sys_counter");
+       u32 use_syscall = strcmp(tk->tkr_mono.clock->name, "arch_sys_counter");
 
        ++vdso_data->tb_seq_count;
        smp_wmb();
@@ -213,11 +213,11 @@ void update_vsyscall(struct timekeeper *tk)
        vdso_data->wtm_clock_nsec               = tk->wall_to_monotonic.tv_nsec;
 
        if (!use_syscall) {
-               vdso_data->cs_cycle_last        = tk->tkr.cycle_last;
+               vdso_data->cs_cycle_last        = tk->tkr_mono.cycle_last;
                vdso_data->xtime_clock_sec      = tk->xtime_sec;
-               vdso_data->xtime_clock_nsec     = tk->tkr.xtime_nsec;
-               vdso_data->cs_mult              = tk->tkr.mult;
-               vdso_data->cs_shift             = tk->tkr.shift;
+               vdso_data->xtime_clock_nsec     = tk->tkr_mono.xtime_nsec;
+               vdso_data->cs_mult              = tk->tkr_mono.mult;
+               vdso_data->cs_shift             = tk->tkr_mono.shift;
        }
 
        smp_wmb();
index f5590c81d95f9e494bd82b5dda127762d5ea01f7..5105e297ed5fef43509f264a001138d299fb5cba 100644 (file)
@@ -18,6 +18,7 @@ if VIRTUALIZATION
 
 config KVM
        bool "Kernel-based Virtual Machine (KVM) support"
+       depends on OF
        select MMU_NOTIFIER
        select PREEMPT_NOTIFIERS
        select ANON_INODES
@@ -25,10 +26,10 @@ config KVM
        select HAVE_KVM_ARCH_TLB_FLUSH_ALL
        select KVM_MMIO
        select KVM_ARM_HOST
-       select KVM_ARM_VGIC
-       select KVM_ARM_TIMER
        select KVM_GENERIC_DIRTYLOG_READ_PROTECT
        select SRCU
+       select HAVE_KVM_EVENTFD
+       select HAVE_KVM_IRQFD
        ---help---
          Support hosting virtualized guest machines.
 
@@ -50,17 +51,4 @@ config KVM_ARM_MAX_VCPUS
          large, so only choose a reasonable number that you expect to
          actually use.
 
-config KVM_ARM_VGIC
-       bool
-       depends on KVM_ARM_HOST && OF
-       select HAVE_KVM_IRQCHIP
-       ---help---
-         Adds support for a hardware assisted, in-kernel GIC emulation.
-
-config KVM_ARM_TIMER
-       bool
-       depends on KVM_ARM_VGIC
-       ---help---
-         Adds support for the Architected Timers in virtual machines.
-
 endif # VIRTUALIZATION
index 4e6e09ee4033503088d686af976a6f7b0f3ee46a..d5904f876cdb535a373c6299beeec09bb5538331 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for Kernel-based Virtual Machine module
 #
 
-ccflags-y += -Ivirt/kvm -Iarch/arm64/kvm
+ccflags-y += -Iarch/arm64/kvm
 CFLAGS_arm.o := -I.
 CFLAGS_mmu.o := -I.
 
@@ -11,7 +11,7 @@ ARM=../../../arch/arm/kvm
 
 obj-$(CONFIG_KVM_ARM_HOST) += kvm.o
 
-kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(ARM)/arm.o $(ARM)/mmu.o $(ARM)/mmio.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(ARM)/psci.o $(ARM)/perf.o
 
@@ -19,11 +19,11 @@ kvm-$(CONFIG_KVM_ARM_HOST) += emulate.o inject_fault.o regmap.o
 kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
 kvm-$(CONFIG_KVM_ARM_HOST) += guest.o reset.o sys_regs.o sys_regs_generic_v8.o
 
-kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
-kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
-kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2-emul.o
-kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v2-switch.o
-kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v3.o
-kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v3-emul.o
-kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v3-switch.o
-kvm-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2-emul.o
+kvm-$(CONFIG_KVM_ARM_HOST) += vgic-v2-switch.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3-emul.o
+kvm-$(CONFIG_KVM_ARM_HOST) += vgic-v3-switch.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
index ae85da6307bb921e286bb7a99a218cab5dbe137e..597831bdddf3db2c7d8f44e4d33fbc13bcb286cb 100644 (file)
@@ -190,6 +190,8 @@ void __init bootmem_init(void)
        min = PFN_UP(memblock_start_of_DRAM());
        max = PFN_DOWN(memblock_end_of_DRAM());
 
+       early_memtest(min << PAGE_SHIFT, max << PAGE_SHIFT);
+
        /*
         * Sparsemem tries to allocate bootmem in memory_present(), so must be
         * done after the fixed reservations.
index 54922d1275b8d1db8dbc05a1dfa482146366862b..ed177475dd8ce6abbee845f40e1cdbe3ebe72adb 100644 (file)
@@ -47,17 +47,16 @@ static int mmap_is_legacy(void)
        return sysctl_legacy_va_layout;
 }
 
-static unsigned long mmap_rnd(void)
+unsigned long arch_mmap_rnd(void)
 {
-       unsigned long rnd = 0;
+       unsigned long rnd;
 
-       if (current->flags & PF_RANDOMIZE)
-               rnd = (long)get_random_int() & STACK_RND_MASK;
+       rnd = (unsigned long)get_random_int() & STACK_RND_MASK;
 
        return rnd << PAGE_SHIFT;
 }
 
-static unsigned long mmap_base(void)
+static unsigned long mmap_base(unsigned long rnd)
 {
        unsigned long gap = rlimit(RLIMIT_STACK);
 
@@ -66,7 +65,7 @@ static unsigned long mmap_base(void)
        else if (gap > MAX_GAP)
                gap = MAX_GAP;
 
-       return PAGE_ALIGN(STACK_TOP - gap - mmap_rnd());
+       return PAGE_ALIGN(STACK_TOP - gap - rnd);
 }
 
 /*
@@ -75,15 +74,20 @@ static unsigned long mmap_base(void)
  */
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
+       unsigned long random_factor = 0UL;
+
+       if (current->flags & PF_RANDOMIZE)
+               random_factor = arch_mmap_rnd();
+
        /*
         * Fall back to the standard layout if the personality bit is set, or
         * if the expected stack growth is unlimited:
         */
        if (mmap_is_legacy()) {
-               mm->mmap_base = TASK_UNMAPPED_BASE;
+               mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
                mm->get_unmapped_area = arch_get_unmapped_area;
        } else {
-               mm->mmap_base = mmap_base();
+               mm->mmap_base = mmap_base(random_factor);
                mm->get_unmapped_area = arch_get_unmapped_area_topdown;
        }
 }
index c6daaf6c6f9790ab7f94dfb12b832c6ecca8c2b0..79e01163a981424db584789f3936a37592e2d765 100644 (file)
@@ -550,10 +550,10 @@ void vmemmap_free(unsigned long start, unsigned long end)
 #endif /* CONFIG_SPARSEMEM_VMEMMAP */
 
 static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
-#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+#if CONFIG_PGTABLE_LEVELS > 2
 static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
 #endif
-#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+#if CONFIG_PGTABLE_LEVELS > 3
 static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss;
 #endif
 
index d232888b99d5b1e210a70627413244d1e78b8ac7..0388ece75b02870d18d8711c14e782aa7a25136a 100644 (file)
@@ -84,7 +84,7 @@ typedef struct user_fpu_struct elf_fpregset_t;
    the loader.  We need to make sure that it is out of the way of the program
    that it will "exec", and that there is sufficient room for the brk.  */
 
-#define ELF_ET_DYN_BASE         (2 * TASK_SIZE / 3)
+#define ELF_ET_DYN_BASE         (TASK_SIZE / 3 * 2)
 
 
 /* This yields a mask that user programs can use to figure out what
index 8ad3e90cc8fc4c7780173003bc531c59624adaa4..1c7259597395e587e3660b10ad4e5f1e6f8d0ba3 100644 (file)
@@ -413,16 +413,14 @@ int __cpu_disable(void)
        return 0;
 }
 
-static DECLARE_COMPLETION(cpu_killed);
-
 int __cpu_die(unsigned int cpu)
 {
-       return wait_for_completion_timeout(&cpu_killed, 5000);
+       return cpu_wait_death(cpu, 5);
 }
 
 void cpu_die(void)
 {
-       complete(&cpu_killed);
+       (void)cpu_report_death();
 
        atomic_dec(&init_mm.mm_users);
        atomic_dec(&init_mm.mm_count);
index 57d2ea8d19773828d620c98b8593f069ff32cd23..3ae9f5a166a0584034dea8fb41ea645ccf88aeea 100644 (file)
@@ -101,7 +101,6 @@ void start_thread(struct pt_regs *regs, unsigned int pc, unsigned long usp)
         */
        usp -= 8;
 
-       set_fs(USER_DS);
        regs->pc  = pc;
        regs->sp  = usp;
        regs->tsr |= 0x40; /* set user mode */
index 336713ab47454fa2afd8e603d53255f5d91acaa0..85ca6727ca075c8ce47ca73f801ed612cdeeb86d 100644 (file)
@@ -176,8 +176,6 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set)
        struct sigframe __user *frame;
        int rsig, sig = ksig->sig;
 
-       set_fs(USER_DS);
-
        frame = get_sigframe(ksig, sizeof(*frame));
 
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
@@ -257,8 +255,6 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set)
        struct rt_sigframe __user *frame;
        int rsig, sig = ksig->sig;
 
-       set_fs(USER_DS);
-
        frame = get_sigframe(ksig, sizeof(*frame));
 
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
index b073f4d771a53c843709395e69228cca30edac01..f211839e2cae18f4d71999ec41ad8ed2a8ff1bca 100644 (file)
@@ -316,6 +316,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)
 
 int __init pcibios_init(void)
 {
+       struct pci_bus *bus;
        struct pci_ops *dir = NULL;
        LIST_HEAD(resources);
 
@@ -383,12 +384,15 @@ int __init pcibios_init(void)
        printk("PCI: Probing PCI hardware\n");
        pci_add_resource(&resources, &pci_ioport_resource);
        pci_add_resource(&resources, &pci_iomem_resource);
-       pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources);
+       bus = pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources);
 
        pcibios_irq_init();
        pcibios_fixup_irqs();
        pcibios_resource_survey();
+       if (!bus)
+               return 0;
 
+       pci_bus_add_devices(bus);
        return 0;
 }
 
index 0a0dd5c05b46af8fda112b2ab9cc606a08d6d5a5..a9ebd471823a6644a6773ed99d780c5c620f3e56 100644 (file)
@@ -37,8 +37,6 @@
  */
 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
 {
-       /* Set to run with user-mode data segmentation */
-       set_fs(USER_DS);
        /* We want to zero all data-containing registers. Is this overkill? */
        memset(regs, 0, sizeof(*regs));
        /* We might want to also zero all Processor registers here */
index 074e52bf815c36fdb813816d6ff3feaa0b3b332e..4f9a6661491b4d203f568470f4a7d1c18a3efeba 100644 (file)
@@ -1,3 +1,8 @@
+config PGTABLE_LEVELS
+       int "Page Table Levels" if !IA64_PAGE_SIZE_64KB
+       range 3 4 if !IA64_PAGE_SIZE_64KB
+       default 3
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
@@ -286,19 +291,6 @@ config IA64_PAGE_SIZE_64KB
 
 endchoice
 
-choice
-       prompt "Page Table Levels"
-       default PGTABLE_3
-
-config PGTABLE_3
-       bool "3 Levels"
-
-config PGTABLE_4
-       depends on !IA64_PAGE_SIZE_64KB
-       bool "4 Levels"
-
-endchoice
-
 if IA64_HP_SIM
 config HZ
        default 32
index 1f1bf144fe62b165cd7854c19c30717a9026d97d..ec48bb9f95e18da086dcf5db6a3e80f63430fff4 100644 (file)
@@ -173,7 +173,7 @@ get_order (unsigned long size)
    */
   typedef struct { unsigned long pte; } pte_t;
   typedef struct { unsigned long pmd; } pmd_t;
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
   typedef struct { unsigned long pud; } pud_t;
 #endif
   typedef struct { unsigned long pgd; } pgd_t;
@@ -182,7 +182,7 @@ get_order (unsigned long size)
 
 # define pte_val(x)    ((x).pte)
 # define pmd_val(x)    ((x).pmd)
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
 # define pud_val(x)    ((x).pud)
 #endif
 # define pgd_val(x)    ((x).pgd)
index 5767cdfc08db8b671e2536bb093fbe4a921e47c7..f5e70e9619486d6347dd61687e463b80db25885a 100644 (file)
@@ -32,7 +32,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
        quicklist_free(0, NULL, pgd);
 }
 
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
 static inline void
 pgd_populate(struct mm_struct *mm, pgd_t * pgd_entry, pud_t * pud)
 {
@@ -49,7 +49,7 @@ static inline void pud_free(struct mm_struct *mm, pud_t *pud)
        quicklist_free(0, NULL, pud);
 }
 #define __pud_free_tlb(tlb, pud, address)      pud_free((tlb)->mm, pud)
-#endif /* CONFIG_PGTABLE_4 */
+#endif /* CONFIG_PGTABLE_LEVELS == 4 */
 
 static inline void
 pud_populate(struct mm_struct *mm, pud_t * pud_entry, pmd_t * pmd)
index 7b6f8801df5765e9d825727a83172cc7793a969b..9f3ed9ee8f13e0e8feed6483e56b45a541ee7832 100644 (file)
@@ -99,7 +99,7 @@
 #define PMD_MASK       (~(PMD_SIZE-1))
 #define PTRS_PER_PMD   (1UL << (PTRS_PER_PTD_SHIFT))
 
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
 /*
  * Definitions for second level:
  *
  *
  * PGDIR_SHIFT determines what a first-level page table entry can map.
  */
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
 #define PGDIR_SHIFT            (PUD_SHIFT + (PTRS_PER_PTD_SHIFT))
 #else
 #define PGDIR_SHIFT            (PMD_SHIFT + (PTRS_PER_PTD_SHIFT))
 #define __S111 __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RWX)
 
 #define pgd_ERROR(e)   printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e))
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
 #define pud_ERROR(e)   printk("%s:%d: bad pud %016lx.\n", __FILE__, __LINE__, pud_val(e))
 #endif
 #define pmd_ERROR(e)   printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e))
@@ -281,7 +281,7 @@ extern unsigned long VMALLOC_END;
 #define pud_page_vaddr(pud)            ((unsigned long) __va(pud_val(pud) & _PFN_MASK))
 #define pud_page(pud)                  virt_to_page((pud_val(pud) + PAGE_OFFSET))
 
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
 #define pgd_none(pgd)                  (!pgd_val(pgd))
 #define pgd_bad(pgd)                   (!ia64_phys_addr_valid(pgd_val(pgd)))
 #define pgd_present(pgd)               (pgd_val(pgd) != 0UL)
@@ -384,7 +384,7 @@ pgd_offset (const struct mm_struct *mm, unsigned long address)
    here.  */
 #define pgd_offset_gate(mm, addr)      pgd_offset_k(addr)
 
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
 /* Find an entry in the second-level page table.. */
 #define pud_offset(dir,addr) \
        ((pud_t *) pgd_page_vaddr(*(dir)) + (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)))
@@ -586,7 +586,7 @@ extern struct page *zero_page_memmap_ptr;
 #define __HAVE_ARCH_PGD_OFFSET_GATE
 
 
-#ifndef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 3
 #include <asm-generic/pgtable-nopud.h>
 #endif
 #include <asm-generic/pgtable.h>
index 18e794a572489d7b308f7a779991d9c05351c463..e42bf7a913f3ed6f74c28332de4496ff2e5579fc 100644 (file)
@@ -146,7 +146,7 @@ ENTRY(vhpt_miss)
 (p6)   dep r17=r18,r19,3,(PAGE_SHIFT-3)        // r17=pgd_offset for region 5
 (p7)   dep r17=r18,r17,3,(PAGE_SHIFT-6)        // r17=pgd_offset for region[0-4]
        cmp.eq p7,p6=0,r21                      // unused address bits all zeroes?
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
        shr.u r28=r22,PUD_SHIFT                 // shift pud index into position
 #else
        shr.u r18=r22,PMD_SHIFT                 // shift pmd index into position
@@ -155,7 +155,7 @@ ENTRY(vhpt_miss)
        ld8 r17=[r17]                           // get *pgd (may be 0)
        ;;
 (p7)   cmp.eq p6,p7=r17,r0                     // was pgd_present(*pgd) == NULL?
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
        dep r28=r28,r17,3,(PAGE_SHIFT-3)        // r28=pud_offset(pgd,addr)
        ;;
        shr.u r18=r22,PMD_SHIFT                 // shift pmd index into position
@@ -222,13 +222,13 @@ ENTRY(vhpt_miss)
         */
        ld8 r25=[r21]                           // read *pte again
        ld8 r26=[r17]                           // read *pmd again
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
        ld8 r19=[r28]                           // read *pud again
 #endif
        cmp.ne p6,p7=r0,r0
        ;;
        cmp.ne.or.andcm p6,p7=r26,r20           // did *pmd change
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
        cmp.ne.or.andcm p6,p7=r19,r29           // did *pud change
 #endif
        mov r27=PAGE_SHIFT<<2
@@ -476,7 +476,7 @@ ENTRY(nested_dtlb_miss)
 (p6)   dep r17=r18,r19,3,(PAGE_SHIFT-3)        // r17=pgd_offset for region 5
 (p7)   dep r17=r18,r17,3,(PAGE_SHIFT-6)        // r17=pgd_offset for region[0-4]
        cmp.eq p7,p6=0,r21                      // unused address bits all zeroes?
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
        shr.u r18=r22,PUD_SHIFT                 // shift pud index into position
 #else
        shr.u r18=r22,PMD_SHIFT                 // shift pmd index into position
@@ -487,7 +487,7 @@ ENTRY(nested_dtlb_miss)
 (p7)   cmp.eq p6,p7=r17,r0                     // was pgd_present(*pgd) == NULL?
        dep r17=r18,r17,3,(PAGE_SHIFT-3)        // r17=p[u|m]d_offset(pgd,addr)
        ;;
-#ifdef CONFIG_PGTABLE_4
+#if CONFIG_PGTABLE_LEVELS == 4
 (p7)   ld8 r17=[r17]                           // get *pud (may be 0)
        shr.u r18=r22,PMD_SHIFT                 // shift pmd index into position
        ;;
index 5151a649c96ba0405bb21be344d79d600ff0b085..b72cd7a07222696978c64b33f3e86bf38b70fd19 100644 (file)
@@ -156,9 +156,9 @@ void arch_crash_save_vmcoreinfo(void)
        VMCOREINFO_OFFSET(node_memblk_s, start_paddr);
        VMCOREINFO_OFFSET(node_memblk_s, size);
 #endif
-#ifdef CONFIG_PGTABLE_3
+#if CONFIG_PGTABLE_LEVELS == 3
        VMCOREINFO_CONFIG(PGTABLE_3);
-#elif defined(CONFIG_PGTABLE_4)
+#elif CONFIG_PGTABLE_LEVELS == 4
        VMCOREINFO_CONFIG(PGTABLE_4);
 #endif
 }
index 0b5ce82d203dd5a908d01609b6f7377d2053161d..1be65eb074ece698501600ee62fa8887b4f5c9a3 100644 (file)
@@ -271,7 +271,9 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
        if (bus == NULL) {
                kfree(res);
                kfree(controller);
+               return;
        }
+       pci_bus_add_devices(bus);
 }
 
 /*
index 7736c6660a1580562bbbed37ece6aae5a61ac99a..8c25e0c8f6a5c752ba9c201de8292e4dd0c5120b 100644 (file)
@@ -214,8 +214,6 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
        regs->r2 = (unsigned long)&frame->uc;
        regs->bpc = (unsigned long)ksig->ka.sa.sa_handler;
 
-       set_fs(USER_DS);
-
 #if DEBUG_SIG
        printk("SIG deliver (%s:%d): sp=%p pc=%p\n",
                current->comm, current->pid, frame, regs->pc);
index 87b7c7581b1dd5777642a3b87dd9002b7e68dc50..2dd8f63bfbbb7850e7e797eb108f708eb1fc6d54 100644 (file)
@@ -67,6 +67,10 @@ config HZ
        default 1000 if CLEOPATRA
        default 100
 
+config PGTABLE_LEVELS
+       default 2 if SUN3 || COLDFIRE
+       default 3
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
index df9679238b6d20f480487040abe882cc41ae4cba..821de928dc3f9d14adbb16c1ad70accc9e57f477 100644 (file)
@@ -313,12 +313,16 @@ static int __init mcf_pci_init(void)
        schedule_timeout(msecs_to_jiffies(200));
 
        rootbus = pci_scan_bus(0, &mcf_pci_ops, NULL);
+       if (!rootbus)
+               return -ENODEV;
+
        rootbus->resource[0] = &mcf_pci_io;
        rootbus->resource[1] = &mcf_pci_mem;
 
        pci_fixup_irqs(pci_common_swizzle, mcf_pci_map_irq);
        pci_bus_size_bridges(rootbus);
        pci_bus_assign_resources(rootbus);
+       pci_bus_add_devices(rootbus);
        return 0;
 }
 
index 1a10a08ebec7474f35977d35e6a3b3513a74e86c..ed1643b4c67893b627be4c23a3c9bc0c25b718f0 100644 (file)
@@ -521,8 +521,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_HEXDUMP=m
 CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
+CONFIG_TEST_RHASHTABLE=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
@@ -573,5 +575,6 @@ 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_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 7859a738c81ead67ec513fbb4cbbd56545d3b825..d38822b1847ee272325793172d32804f3f8f8c00 100644 (file)
@@ -479,8 +479,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_HEXDUMP=m
 CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
+CONFIG_TEST_RHASHTABLE=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
@@ -531,5 +533,6 @@ 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_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 372593a3b398f3a693a4bd9d3a8b298da23d2344..c429199cf4a9332a9e43432c6bcfed6032863ba0 100644 (file)
@@ -501,8 +501,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_HEXDUMP=m
 CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
+CONFIG_TEST_RHASHTABLE=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
@@ -553,5 +555,6 @@ 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_HW is not set
 CONFIG_XZ_DEC_TEST=m
index f3bd35e76ea4823d156fc1d184602da8d35511f3..9b880371d6421ec9be77870c3fd352589eb571ee 100644 (file)
@@ -472,8 +472,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_HEXDUMP=m
 CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
+CONFIG_TEST_RHASHTABLE=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
@@ -524,5 +526,6 @@ 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_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 9f9793fb2b73dac7460ac6145b6aa141232b6b52..49ae3376e993a50f462a61dcd790ca4383b8ff40 100644 (file)
@@ -481,8 +481,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_HEXDUMP=m
 CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
+CONFIG_TEST_RHASHTABLE=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
@@ -533,5 +535,6 @@ 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_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 89f225c01a0b6745dcbf7032f9d1040742203924..ee143a57058cb93ed3fd116154ef19a9932e2532 100644 (file)
@@ -503,8 +503,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_HEXDUMP=m
 CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
+CONFIG_TEST_RHASHTABLE=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
@@ -555,5 +557,6 @@ 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_HW is not set
 CONFIG_XZ_DEC_TEST=m
index d3cdb5447a2ca7e539c443101a132663c8c0f72f..c777aa05048f0bad1a2b33d46e7d5617e3752c42 100644 (file)
@@ -583,8 +583,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_HEXDUMP=m
 CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
+CONFIG_TEST_RHASHTABLE=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
@@ -635,5 +637,6 @@ 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_HW is not set
 CONFIG_XZ_DEC_TEST=m
index b4c76640973eca3fb94b6e6b3c15c34583bc9a5a..a7628a85e260ddabb6e99f6ff5c71ee4fd565b8f 100644 (file)
@@ -472,8 +472,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_HEXDUMP=m
 CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
+CONFIG_TEST_RHASHTABLE=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
@@ -524,5 +526,6 @@ 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_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 0d4a26f9b58c5596ed306612a8b5788e205731c8..ebaa68268a4a5f3513b03f8e7fa842cf78427f60 100644 (file)
@@ -472,8 +472,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_HEXDUMP=m
 CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
+CONFIG_TEST_RHASHTABLE=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
@@ -524,5 +526,6 @@ 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_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 5d581c503fa375d516b3811482ed795f23aa2544..2c16853aedd350b8270623bf10e4e1e6cff9619b 100644 (file)
@@ -340,7 +340,7 @@ CONFIG_VETH=m
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
-CONFIG_NE2000=m
+CONFIG_NE2000=y
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
@@ -494,8 +494,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_HEXDUMP=m
 CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
+CONFIG_TEST_RHASHTABLE=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
@@ -546,5 +548,6 @@ 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_HW is not set
 CONFIG_XZ_DEC_TEST=m
index c6b49a4a887cab5edbd11ec4357124ad66c45610..e3056bf0f65bdea73d9b3eeefba282be8fc371a0 100644 (file)
@@ -473,8 +473,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_HEXDUMP=m
 CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
+CONFIG_TEST_RHASHTABLE=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
@@ -524,5 +526,6 @@ 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_HW is not set
 CONFIG_XZ_DEC_TEST=m
index b65785eaff8dc52f3482247444574dc1489e59ae..73c36b7a000978cf3d8f9a6f39271435cf0d2e21 100644 (file)
@@ -473,8 +473,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_HEXDUMP=m
 CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
+CONFIG_TEST_RHASHTABLE=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
@@ -525,5 +527,6 @@ 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_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 7b51416ccae221d103e489446461a7d16ffe4e1c..256da0e4aeb41b8a7381a7351f14942313c1cc71 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
 */
 
 #ifndef mcfqspi_h
index 931a31ff59ddb32de3300d494b00a8efdcba2afc..8520250a1d9369c58c706674b4f2b6d0cbfc7275 100644 (file)
@@ -62,7 +62,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 
                r = dev->resource + idx;
                if (!r->start && r->end) {
-                       pr_err(KERN_ERR "PCI: Device %s not available because of resource collisions\n",
+                       pr_err("PCI: Device %s not available because of resource collisions\n",
                                pci_name(dev));
                        return -EINVAL;
                }
index 7729f33878d1c43b17efeb81a7b229e049896c03..37234c2df47f6e8ed6edd4eb5d60fc29178f8ef7 100644 (file)
@@ -11,12 +11,7 @@ any later version.
 GNU CC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+GNU General Public License for more details. */
 
 #define BITS_PER_UNIT 8
 
index 18ea5f7ed921f50e63fe03117a78cce6cf8a392e..1d59345f36c631550767bc8f8c77c9e6a69afbc0 100644 (file)
@@ -11,12 +11,7 @@ any later version.
 GNU CC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+GNU General Public License for more details. */
 
 #define BITS_PER_UNIT 8
 
index ec307b61991e417d6cd93f38b96be14d7bff12e6..2c0ec85ac661547382c2206b613e86ba9d3a63be 100644 (file)
@@ -19,12 +19,7 @@ distribution when not linked into another program.)
 This file is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+General Public License for more details. */
 
 /* As a special exception, if you link this library with files
    compiled with GCC to produce an executable, this does not cause
index d06442d3a3288abf0b2b292872f918377e9ba45d..49e1ec8f2cc27a9f9880bfe78cef279afcdf3ab1 100644 (file)
@@ -11,12 +11,7 @@ any later version.
 GNU CC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+GNU General Public License for more details. */
 
 #define BITS_PER_UNIT 8
 
index ef3849435768587832ad39ea21e19954a6426cfd..1d9e0efdf31d201f67ae56496a6fae6496ef8868 100644 (file)
@@ -19,12 +19,7 @@ distribution when not linked into another program.)
 This file is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+General Public License for more details. */
 
 /* As a special exception, if you link this library with files
    compiled with GCC to produce an executable, this does not cause
index ee5f0b1b5c5dd9b86c78552f42e4e7e9210a74cb..9006d15b87218d95d77effd305bb49b4968e4914 100644 (file)
@@ -12,12 +12,7 @@ any later version.
 GNU CC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+GNU General Public License for more details. */
 
 #ifdef CONFIG_CPU_HAS_NO_MULDIV64
 
index ce29ea37b45ffdfc5962d826512739cc466a68ac..c39ad4e738e9a6522fcef640020502f727d46a52 100644 (file)
@@ -19,12 +19,7 @@ distribution when not linked into another program.)
 This file is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+General Public License for more details. */
 
 /* As a special exception, if you link this library with files
    compiled with GCC to produce an executable, this does not cause
index c424c4a1f0a3276a8ca186f169b3e0eed361bd79..35a5446572a5ee3bae78e725ae8c39619332b7a0 100644 (file)
@@ -19,12 +19,7 @@ distribution when not linked into another program.)
 This file is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+General Public License for more details. */
 
 /* As a special exception, if you link this library with files
    compiled with GCC to produce an executable, this does not cause
index 5def5f626478c38cbb2c12bf8f84cff2434e732f..099da514a8fd80daa85d3ba2644e3f2792175b5b 100644 (file)
@@ -19,12 +19,7 @@ distribution when not linked into another program.)
 This file is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+General Public License for more details. */
 
 /* As a special exception, if you link this library with files
    compiled with GCC to produce an executable, this does not cause
index 54037125ebf8c0e05c82cb937cb2560a7575244d..bb11dceed7ed2e947ea31f9393539c8b2e6f5c41 100644 (file)
@@ -47,9 +47,8 @@ void __init oss_init(void)
        /* Disable all interrupts. Unlike a VIA it looks like we    */
        /* do this by setting the source's interrupt level to zero. */
 
-       for (i = 0; i <= OSS_NUM_SOURCES; i++) {
+       for (i = 0; i < OSS_NUM_SOURCES; i++)
                oss->irq_level[i] = 0;
-       }
 }
 
 /*
index 13272fd5a5baec8e3b1a4de778a6982abf0adae7..0838ca69976466bbfc3c3854fecf91566afd6a9b 100644 (file)
@@ -111,7 +111,6 @@ struct thread_struct {
  */
 #define start_thread(regs, pc, usp) do {                                  \
        unsigned int *argc = (unsigned int *) bprm->exec;                  \
-       set_fs(USER_DS);                                                   \
        current->thread.int_depth = 1;                                     \
        /* Force this process down to user land */                         \
        regs->ctx.SaveMask = TBICTX_PRIV_BIT;                              \
index f006d2276f40abb67d6aeb2356a2f00aebcdb9fb..ac3a199e33e714d772f688b7f9620cb964d29a0f 100644 (file)
@@ -261,7 +261,6 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static DECLARE_COMPLETION(cpu_killed);
 
 /*
  * __cpu_disable runs on the processor to be shutdown.
@@ -299,7 +298,7 @@ int __cpu_disable(void)
  */
 void __cpu_die(unsigned int cpu)
 {
-       if (!wait_for_completion_timeout(&cpu_killed, msecs_to_jiffies(1)))
+       if (!cpu_wait_death(cpu, 1))
                pr_err("CPU%u: unable to kill\n", cpu);
 }
 
@@ -314,7 +313,7 @@ void cpu_die(void)
        local_irq_disable();
        idle_task_exit();
 
-       complete(&cpu_killed);
+       (void)cpu_report_death();
 
        asm ("XOR       TXENABLE, D0Re0,D0Re0\n");
 }
index a1cbaf90e2ea47215e8bfce77d7d8d113f9fd110..20ccd4e2baa54c88f4fbcdd13c1a407ee66ffc82 100644 (file)
@@ -236,8 +236,6 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
        /* Offset to handle microblaze rtid r14, 0 */
        regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
 
-       set_fs(USER_DS);
-
 #ifdef DEBUG_SIG
        pr_info("SIG deliver (%s:%d): sp=%p pc=%08lx\n",
                current->comm, current->pid, frame, regs->pc);
index 48528fb81effa07ef5c992c08efba2cad6a75ff0..ae838ed5fcf2535ca5c047a2837adadc434735cd 100644 (file)
@@ -1382,6 +1382,10 @@ static int __init pcibios_init(void)
 
        /* Call common code to handle resource allocation */
        pcibios_resource_survey();
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+               if (hose->bus)
+                       pci_bus_add_devices(hose->bus);
+       }
 
        return 0;
 }
index c7a16904cd03c705333f645419ec07888fc6fd87..a326c4cb8cf0e65f8e75eb4fb2c9e0b124f1d52e 100644 (file)
@@ -23,7 +23,7 @@ config MIPS
        select HAVE_KRETPROBES
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_SYSCALL_TRACEPOINTS
-       select ARCH_BINFMT_ELF_RANDOMIZE_PIE
+       select ARCH_HAS_ELF_RANDOMIZE
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT
        select RTC_LIB if !MACH_LOONGSON
        select GENERIC_ATOMIC64 if !64BIT
@@ -2600,6 +2600,11 @@ config STACKTRACE_SUPPORT
        bool
        default y
 
+config PGTABLE_LEVELS
+       int
+       default 3 if 64BIT && !PAGE_SIZE_64KB
+       default 2
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
index cdac7b3eeaf7fa6524b8f6ffb92edc7209eef4c5..80386470d3a4414da1a6ff17d14b624ddd417ad7 100644 (file)
        .set push
        SET_HARDFLOAT
        cfc1    \tmp,  fcr31
-       swc1    $f0,  THREAD_FPR0_LS64(\thread)
-       swc1    $f1,  THREAD_FPR1_LS64(\thread)
-       swc1    $f2,  THREAD_FPR2_LS64(\thread)
-       swc1    $f3,  THREAD_FPR3_LS64(\thread)
-       swc1    $f4,  THREAD_FPR4_LS64(\thread)
-       swc1    $f5,  THREAD_FPR5_LS64(\thread)
-       swc1    $f6,  THREAD_FPR6_LS64(\thread)
-       swc1    $f7,  THREAD_FPR7_LS64(\thread)
-       swc1    $f8,  THREAD_FPR8_LS64(\thread)
-       swc1    $f9,  THREAD_FPR9_LS64(\thread)
-       swc1    $f10, THREAD_FPR10_LS64(\thread)
-       swc1    $f11, THREAD_FPR11_LS64(\thread)
-       swc1    $f12, THREAD_FPR12_LS64(\thread)
-       swc1    $f13, THREAD_FPR13_LS64(\thread)
-       swc1    $f14, THREAD_FPR14_LS64(\thread)
-       swc1    $f15, THREAD_FPR15_LS64(\thread)
-       swc1    $f16, THREAD_FPR16_LS64(\thread)
-       swc1    $f17, THREAD_FPR17_LS64(\thread)
-       swc1    $f18, THREAD_FPR18_LS64(\thread)
-       swc1    $f19, THREAD_FPR19_LS64(\thread)
-       swc1    $f20, THREAD_FPR20_LS64(\thread)
-       swc1    $f21, THREAD_FPR21_LS64(\thread)
-       swc1    $f22, THREAD_FPR22_LS64(\thread)
-       swc1    $f23, THREAD_FPR23_LS64(\thread)
-       swc1    $f24, THREAD_FPR24_LS64(\thread)
-       swc1    $f25, THREAD_FPR25_LS64(\thread)
-       swc1    $f26, THREAD_FPR26_LS64(\thread)
-       swc1    $f27, THREAD_FPR27_LS64(\thread)
-       swc1    $f28, THREAD_FPR28_LS64(\thread)
-       swc1    $f29, THREAD_FPR29_LS64(\thread)
-       swc1    $f30, THREAD_FPR30_LS64(\thread)
-       swc1    $f31, THREAD_FPR31_LS64(\thread)
+       swc1    $f0,  THREAD_FPR0(\thread)
+       swc1    $f1,  THREAD_FPR1(\thread)
+       swc1    $f2,  THREAD_FPR2(\thread)
+       swc1    $f3,  THREAD_FPR3(\thread)
+       swc1    $f4,  THREAD_FPR4(\thread)
+       swc1    $f5,  THREAD_FPR5(\thread)
+       swc1    $f6,  THREAD_FPR6(\thread)
+       swc1    $f7,  THREAD_FPR7(\thread)
+       swc1    $f8,  THREAD_FPR8(\thread)
+       swc1    $f9,  THREAD_FPR9(\thread)
+       swc1    $f10, THREAD_FPR10(\thread)
+       swc1    $f11, THREAD_FPR11(\thread)
+       swc1    $f12, THREAD_FPR12(\thread)
+       swc1    $f13, THREAD_FPR13(\thread)
+       swc1    $f14, THREAD_FPR14(\thread)
+       swc1    $f15, THREAD_FPR15(\thread)
+       swc1    $f16, THREAD_FPR16(\thread)
+       swc1    $f17, THREAD_FPR17(\thread)
+       swc1    $f18, THREAD_FPR18(\thread)
+       swc1    $f19, THREAD_FPR19(\thread)
+       swc1    $f20, THREAD_FPR20(\thread)
+       swc1    $f21, THREAD_FPR21(\thread)
+       swc1    $f22, THREAD_FPR22(\thread)
+       swc1    $f23, THREAD_FPR23(\thread)
+       swc1    $f24, THREAD_FPR24(\thread)
+       swc1    $f25, THREAD_FPR25(\thread)
+       swc1    $f26, THREAD_FPR26(\thread)
+       swc1    $f27, THREAD_FPR27(\thread)
+       swc1    $f28, THREAD_FPR28(\thread)
+       swc1    $f29, THREAD_FPR29(\thread)
+       swc1    $f30, THREAD_FPR30(\thread)
+       swc1    $f31, THREAD_FPR31(\thread)
        sw      \tmp, THREAD_FCR31(\thread)
        .set pop
        .endm
        .set push
        SET_HARDFLOAT
        lw      \tmp, THREAD_FCR31(\thread)
-       lwc1    $f0,  THREAD_FPR0_LS64(\thread)
-       lwc1    $f1,  THREAD_FPR1_LS64(\thread)
-       lwc1    $f2,  THREAD_FPR2_LS64(\thread)
-       lwc1    $f3,  THREAD_FPR3_LS64(\thread)
-       lwc1    $f4,  THREAD_FPR4_LS64(\thread)
-       lwc1    $f5,  THREAD_FPR5_LS64(\thread)
-       lwc1    $f6,  THREAD_FPR6_LS64(\thread)
-       lwc1    $f7,  THREAD_FPR7_LS64(\thread)
-       lwc1    $f8,  THREAD_FPR8_LS64(\thread)
-       lwc1    $f9,  THREAD_FPR9_LS64(\thread)
-       lwc1    $f10, THREAD_FPR10_LS64(\thread)
-       lwc1    $f11, THREAD_FPR11_LS64(\thread)
-       lwc1    $f12, THREAD_FPR12_LS64(\thread)
-       lwc1    $f13, THREAD_FPR13_LS64(\thread)
-       lwc1    $f14, THREAD_FPR14_LS64(\thread)
-       lwc1    $f15, THREAD_FPR15_LS64(\thread)
-       lwc1    $f16, THREAD_FPR16_LS64(\thread)
-       lwc1    $f17, THREAD_FPR17_LS64(\thread)
-       lwc1    $f18, THREAD_FPR18_LS64(\thread)
-       lwc1    $f19, THREAD_FPR19_LS64(\thread)
-       lwc1    $f20, THREAD_FPR20_LS64(\thread)
-       lwc1    $f21, THREAD_FPR21_LS64(\thread)
-       lwc1    $f22, THREAD_FPR22_LS64(\thread)
-       lwc1    $f23, THREAD_FPR23_LS64(\thread)
-       lwc1    $f24, THREAD_FPR24_LS64(\thread)
-       lwc1    $f25, THREAD_FPR25_LS64(\thread)
-       lwc1    $f26, THREAD_FPR26_LS64(\thread)
-       lwc1    $f27, THREAD_FPR27_LS64(\thread)
-       lwc1    $f28, THREAD_FPR28_LS64(\thread)
-       lwc1    $f29, THREAD_FPR29_LS64(\thread)
-       lwc1    $f30, THREAD_FPR30_LS64(\thread)
-       lwc1    $f31, THREAD_FPR31_LS64(\thread)
+       lwc1    $f0,  THREAD_FPR0(\thread)
+       lwc1    $f1,  THREAD_FPR1(\thread)
+       lwc1    $f2,  THREAD_FPR2(\thread)
+       lwc1    $f3,  THREAD_FPR3(\thread)
+       lwc1    $f4,  THREAD_FPR4(\thread)
+       lwc1    $f5,  THREAD_FPR5(\thread)
+       lwc1    $f6,  THREAD_FPR6(\thread)
+       lwc1    $f7,  THREAD_FPR7(\thread)
+       lwc1    $f8,  THREAD_FPR8(\thread)
+       lwc1    $f9,  THREAD_FPR9(\thread)
+       lwc1    $f10, THREAD_FPR10(\thread)
+       lwc1    $f11, THREAD_FPR11(\thread)
+       lwc1    $f12, THREAD_FPR12(\thread)
+       lwc1    $f13, THREAD_FPR13(\thread)
+       lwc1    $f14, THREAD_FPR14(\thread)
+       lwc1    $f15, THREAD_FPR15(\thread)
+       lwc1    $f16, THREAD_FPR16(\thread)
+       lwc1    $f17, THREAD_FPR17(\thread)
+       lwc1    $f18, THREAD_FPR18(\thread)
+       lwc1    $f19, THREAD_FPR19(\thread)
+       lwc1    $f20, THREAD_FPR20(\thread)
+       lwc1    $f21, THREAD_FPR21(\thread)
+       lwc1    $f22, THREAD_FPR22(\thread)
+       lwc1    $f23, THREAD_FPR23(\thread)
+       lwc1    $f24, THREAD_FPR24(\thread)
+       lwc1    $f25, THREAD_FPR25(\thread)
+       lwc1    $f26, THREAD_FPR26(\thread)
+       lwc1    $f27, THREAD_FPR27(\thread)
+       lwc1    $f28, THREAD_FPR28(\thread)
+       lwc1    $f29, THREAD_FPR29(\thread)
+       lwc1    $f30, THREAD_FPR30(\thread)
+       lwc1    $f31, THREAD_FPR31(\thread)
        ctc1    \tmp, fcr31
        .set pop
        .endm
index 0cae4595e985bbc3d8043b3bb85aef66c582615b..6156ac8c4cfb9a854bf3ed3a5546606216161118 100644 (file)
        .set    push
        SET_HARDFLOAT
        cfc1    \tmp, fcr31
-       sdc1    $f0,  THREAD_FPR0_LS64(\thread)
-       sdc1    $f2,  THREAD_FPR2_LS64(\thread)
-       sdc1    $f4,  THREAD_FPR4_LS64(\thread)
-       sdc1    $f6,  THREAD_FPR6_LS64(\thread)
-       sdc1    $f8,  THREAD_FPR8_LS64(\thread)
-       sdc1    $f10, THREAD_FPR10_LS64(\thread)
-       sdc1    $f12, THREAD_FPR12_LS64(\thread)
-       sdc1    $f14, THREAD_FPR14_LS64(\thread)
-       sdc1    $f16, THREAD_FPR16_LS64(\thread)
-       sdc1    $f18, THREAD_FPR18_LS64(\thread)
-       sdc1    $f20, THREAD_FPR20_LS64(\thread)
-       sdc1    $f22, THREAD_FPR22_LS64(\thread)
-       sdc1    $f24, THREAD_FPR24_LS64(\thread)
-       sdc1    $f26, THREAD_FPR26_LS64(\thread)
-       sdc1    $f28, THREAD_FPR28_LS64(\thread)
-       sdc1    $f30, THREAD_FPR30_LS64(\thread)
+       sdc1    $f0,  THREAD_FPR0(\thread)
+       sdc1    $f2,  THREAD_FPR2(\thread)
+       sdc1    $f4,  THREAD_FPR4(\thread)
+       sdc1    $f6,  THREAD_FPR6(\thread)
+       sdc1    $f8,  THREAD_FPR8(\thread)
+       sdc1    $f10, THREAD_FPR10(\thread)
+       sdc1    $f12, THREAD_FPR12(\thread)
+       sdc1    $f14, THREAD_FPR14(\thread)
+       sdc1    $f16, THREAD_FPR16(\thread)
+       sdc1    $f18, THREAD_FPR18(\thread)
+       sdc1    $f20, THREAD_FPR20(\thread)
+       sdc1    $f22, THREAD_FPR22(\thread)
+       sdc1    $f24, THREAD_FPR24(\thread)
+       sdc1    $f26, THREAD_FPR26(\thread)
+       sdc1    $f28, THREAD_FPR28(\thread)
+       sdc1    $f30, THREAD_FPR30(\thread)
        sw      \tmp, THREAD_FCR31(\thread)
        .set    pop
        .endm
        .set    push
        .set    mips64r2
        SET_HARDFLOAT
-       sdc1    $f1,  THREAD_FPR1_LS64(\thread)
-       sdc1    $f3,  THREAD_FPR3_LS64(\thread)
-       sdc1    $f5,  THREAD_FPR5_LS64(\thread)
-       sdc1    $f7,  THREAD_FPR7_LS64(\thread)
-       sdc1    $f9,  THREAD_FPR9_LS64(\thread)
-       sdc1    $f11, THREAD_FPR11_LS64(\thread)
-       sdc1    $f13, THREAD_FPR13_LS64(\thread)
-       sdc1    $f15, THREAD_FPR15_LS64(\thread)
-       sdc1    $f17, THREAD_FPR17_LS64(\thread)
-       sdc1    $f19, THREAD_FPR19_LS64(\thread)
-       sdc1    $f21, THREAD_FPR21_LS64(\thread)
-       sdc1    $f23, THREAD_FPR23_LS64(\thread)
-       sdc1    $f25, THREAD_FPR25_LS64(\thread)
-       sdc1    $f27, THREAD_FPR27_LS64(\thread)
-       sdc1    $f29, THREAD_FPR29_LS64(\thread)
-       sdc1    $f31, THREAD_FPR31_LS64(\thread)
+       sdc1    $f1,  THREAD_FPR1(\thread)
+       sdc1    $f3,  THREAD_FPR3(\thread)
+       sdc1    $f5,  THREAD_FPR5(\thread)
+       sdc1    $f7,  THREAD_FPR7(\thread)
+       sdc1    $f9,  THREAD_FPR9(\thread)
+       sdc1    $f11, THREAD_FPR11(\thread)
+       sdc1    $f13, THREAD_FPR13(\thread)
+       sdc1    $f15, THREAD_FPR15(\thread)
+       sdc1    $f17, THREAD_FPR17(\thread)
+       sdc1    $f19, THREAD_FPR19(\thread)
+       sdc1    $f21, THREAD_FPR21(\thread)
+       sdc1    $f23, THREAD_FPR23(\thread)
+       sdc1    $f25, THREAD_FPR25(\thread)
+       sdc1    $f27, THREAD_FPR27(\thread)
+       sdc1    $f29, THREAD_FPR29(\thread)
+       sdc1    $f31, THREAD_FPR31(\thread)
        .set    pop
        .endm
 
        .set    push
        SET_HARDFLOAT
        lw      \tmp, THREAD_FCR31(\thread)
-       ldc1    $f0,  THREAD_FPR0_LS64(\thread)
-       ldc1    $f2,  THREAD_FPR2_LS64(\thread)
-       ldc1    $f4,  THREAD_FPR4_LS64(\thread)
-       ldc1    $f6,  THREAD_FPR6_LS64(\thread)
-       ldc1    $f8,  THREAD_FPR8_LS64(\thread)
-       ldc1    $f10, THREAD_FPR10_LS64(\thread)
-       ldc1    $f12, THREAD_FPR12_LS64(\thread)
-       ldc1    $f14, THREAD_FPR14_LS64(\thread)
-       ldc1    $f16, THREAD_FPR16_LS64(\thread)
-       ldc1    $f18, THREAD_FPR18_LS64(\thread)
-       ldc1    $f20, THREAD_FPR20_LS64(\thread)
-       ldc1    $f22, THREAD_FPR22_LS64(\thread)
-       ldc1    $f24, THREAD_FPR24_LS64(\thread)
-       ldc1    $f26, THREAD_FPR26_LS64(\thread)
-       ldc1    $f28, THREAD_FPR28_LS64(\thread)
-       ldc1    $f30, THREAD_FPR30_LS64(\thread)
+       ldc1    $f0,  THREAD_FPR0(\thread)
+       ldc1    $f2,  THREAD_FPR2(\thread)
+       ldc1    $f4,  THREAD_FPR4(\thread)
+       ldc1    $f6,  THREAD_FPR6(\thread)
+       ldc1    $f8,  THREAD_FPR8(\thread)
+       ldc1    $f10, THREAD_FPR10(\thread)
+       ldc1    $f12, THREAD_FPR12(\thread)
+       ldc1    $f14, THREAD_FPR14(\thread)
+       ldc1    $f16, THREAD_FPR16(\thread)
+       ldc1    $f18, THREAD_FPR18(\thread)
+       ldc1    $f20, THREAD_FPR20(\thread)
+       ldc1    $f22, THREAD_FPR22(\thread)
+       ldc1    $f24, THREAD_FPR24(\thread)
+       ldc1    $f26, THREAD_FPR26(\thread)
+       ldc1    $f28, THREAD_FPR28(\thread)
+       ldc1    $f30, THREAD_FPR30(\thread)
        ctc1    \tmp, fcr31
        .endm
 
        .set    push
        .set    mips64r2
        SET_HARDFLOAT
-       ldc1    $f1,  THREAD_FPR1_LS64(\thread)
-       ldc1    $f3,  THREAD_FPR3_LS64(\thread)
-       ldc1    $f5,  THREAD_FPR5_LS64(\thread)
-       ldc1    $f7,  THREAD_FPR7_LS64(\thread)
-       ldc1    $f9,  THREAD_FPR9_LS64(\thread)
-       ldc1    $f11, THREAD_FPR11_LS64(\thread)
-       ldc1    $f13, THREAD_FPR13_LS64(\thread)
-       ldc1    $f15, THREAD_FPR15_LS64(\thread)
-       ldc1    $f17, THREAD_FPR17_LS64(\thread)
-       ldc1    $f19, THREAD_FPR19_LS64(\thread)
-       ldc1    $f21, THREAD_FPR21_LS64(\thread)
-       ldc1    $f23, THREAD_FPR23_LS64(\thread)
-       ldc1    $f25, THREAD_FPR25_LS64(\thread)
-       ldc1    $f27, THREAD_FPR27_LS64(\thread)
-       ldc1    $f29, THREAD_FPR29_LS64(\thread)
-       ldc1    $f31, THREAD_FPR31_LS64(\thread)
+       ldc1    $f1,  THREAD_FPR1(\thread)
+       ldc1    $f3,  THREAD_FPR3(\thread)
+       ldc1    $f5,  THREAD_FPR5(\thread)
+       ldc1    $f7,  THREAD_FPR7(\thread)
+       ldc1    $f9,  THREAD_FPR9(\thread)
+       ldc1    $f11, THREAD_FPR11(\thread)
+       ldc1    $f13, THREAD_FPR13(\thread)
+       ldc1    $f15, THREAD_FPR15(\thread)
+       ldc1    $f17, THREAD_FPR17(\thread)
+       ldc1    $f19, THREAD_FPR19(\thread)
+       ldc1    $f21, THREAD_FPR21(\thread)
+       ldc1    $f23, THREAD_FPR23(\thread)
+       ldc1    $f25, THREAD_FPR25(\thread)
+       ldc1    $f27, THREAD_FPR27(\thread)
+       ldc1    $f29, THREAD_FPR29(\thread)
+       ldc1    $f31, THREAD_FPR31(\thread)
        .set    pop
        .endm
 
        .endm
 
 #ifdef TOOLCHAIN_SUPPORTS_MSA
+       .macro  _cfcmsa rd, cs
+       .set    push
+       .set    mips32r2
+       .set    msa
+       cfcmsa  \rd, $\cs
+       .set    pop
+       .endm
+
+       .macro  _ctcmsa cd, rs
+       .set    push
+       .set    mips32r2
+       .set    msa
+       ctcmsa  $\cd, \rs
+       .set    pop
+       .endm
+
        .macro  ld_d    wd, off, base
        .set    push
        .set    mips32r2
        .set    pop
        .endm
 
-       .macro  copy_u_w        rd, ws, n
+       .macro  copy_u_w        ws, n
        .set    push
        .set    mips32r2
        .set    msa
-       copy_u.w \rd, $w\ws[\n]
+       copy_u.w $1, $w\ws[\n]
        .set    pop
        .endm
 
-       .macro  copy_u_d        rd, ws, n
+       .macro  copy_u_d        ws, n
        .set    push
        .set    mips64r2
        .set    msa
-       copy_u.d \rd, $w\ws[\n]
+       copy_u.d $1, $w\ws[\n]
        .set    pop
        .endm
 
-       .macro  insert_w        wd, n, rs
+       .macro  insert_w        wd, n
        .set    push
        .set    mips32r2
        .set    msa
-       insert.w $w\wd[\n], \rs
+       insert.w $w\wd[\n], $1
        .set    pop
        .endm
 
-       .macro  insert_d        wd, n, rs
+       .macro  insert_d        wd, n
        .set    push
        .set    mips64r2
        .set    msa
-       insert.d $w\wd[\n], \rs
+       insert.d $w\wd[\n], $1
        .set    pop
        .endm
 #else
        /*
         * Temporary until all toolchains in use include MSA support.
         */
-       .macro  cfcmsa  rd, cs
+       .macro  _cfcmsa rd, cs
        .set    push
        .set    noat
        SET_HARDFLOAT
        .set    pop
        .endm
 
-       .macro  ctcmsa  cd, rs
+       .macro  _ctcmsa cd, rs
        .set    push
        .set    noat
        SET_HARDFLOAT
        .set    pop
        .endm
 
-       .macro  copy_u_w        rd, ws, n
+       .macro  copy_u_w        ws, n
        .set    push
        .set    noat
        SET_HARDFLOAT
        .insn
        .word   COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11)
-       /* move triggers an assembler bug... */
-       or      \rd, $1, zero
        .set    pop
        .endm
 
-       .macro  copy_u_d        rd, ws, n
+       .macro  copy_u_d        ws, n
        .set    push
        .set    noat
        SET_HARDFLOAT
        .insn
        .word   COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11)
-       /* move triggers an assembler bug... */
-       or      \rd, $1, zero
        .set    pop
        .endm
 
-       .macro  insert_w        wd, n, rs
+       .macro  insert_w        wd, n
        .set    push
        .set    noat
        SET_HARDFLOAT
-       /* move triggers an assembler bug... */
-       or      $1, \rs, zero
        .word   INSERT_W_MSA_INSN | (\n << 16) | (\wd << 6)
        .set    pop
        .endm
 
-       .macro  insert_d        wd, n, rs
+       .macro  insert_d        wd, n
        .set    push
        .set    noat
        SET_HARDFLOAT
-       /* move triggers an assembler bug... */
-       or      $1, \rs, zero
        .word   INSERT_D_MSA_INSN | (\n << 16) | (\wd << 6)
        .set    pop
        .endm
        .set    push
        .set    noat
        SET_HARDFLOAT
-       cfcmsa  $1, MSA_CSR
+       _cfcmsa $1, MSA_CSR
        sw      $1, THREAD_MSA_CSR(\thread)
        .set    pop
        .endm
        .set    noat
        SET_HARDFLOAT
        lw      $1, THREAD_MSA_CSR(\thread)
-       ctcmsa  MSA_CSR, $1
+       _ctcmsa MSA_CSR, $1
        .set    pop
        ld_d    0, THREAD_FPR0, \thread
        ld_d    1, THREAD_FPR1, \thread
        insert_w \wd, 2
        insert_w \wd, 3
 #endif
-       .if     31-\wd
-       msa_init_upper  (\wd+1)
-       .endif
        .endm
 
        .macro  msa_init_all_upper
        SET_HARDFLOAT
        not     $1, zero
        msa_init_upper  0
+       msa_init_upper  1
+       msa_init_upper  2
+       msa_init_upper  3
+       msa_init_upper  4
+       msa_init_upper  5
+       msa_init_upper  6
+       msa_init_upper  7
+       msa_init_upper  8
+       msa_init_upper  9
+       msa_init_upper  10
+       msa_init_upper  11
+       msa_init_upper  12
+       msa_init_upper  13
+       msa_init_upper  14
+       msa_init_upper  15
+       msa_init_upper  16
+       msa_init_upper  17
+       msa_init_upper  18
+       msa_init_upper  19
+       msa_init_upper  20
+       msa_init_upper  21
+       msa_init_upper  22
+       msa_init_upper  23
+       msa_init_upper  24
+       msa_init_upper  25
+       msa_init_upper  26
+       msa_init_upper  27
+       msa_init_upper  28
+       msa_init_upper  29
+       msa_init_upper  30
+       msa_init_upper  31
        .set    pop
        .endm
 
index 535f196ffe02da7ad769ab0b7053b4dd5253dd82..31d747d46a23c1ba76b97755f44d1f20203028f6 100644 (file)
@@ -410,10 +410,6 @@ struct linux_binprm;
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
                                       int uses_interp);
 
-struct mm_struct;
-extern unsigned long arch_randomize_brk(struct mm_struct *mm);
-#define arch_randomize_brk arch_randomize_brk
-
 struct arch_elf_state {
        int fp_abi;
        int interp_fp_abi;
index dd083e999b08a14ffdbef46d5f5f4a0731e9f18e..b104ad9d655f2da157544fcf783a225377cb996d 100644 (file)
@@ -48,6 +48,12 @@ enum fpu_mode {
 #define FPU_FR_MASK            0x1
 };
 
+#define __disable_fpu()                                                        \
+do {                                                                   \
+       clear_c0_status(ST0_CU1);                                       \
+       disable_fpu_hazard();                                           \
+} while (0)
+
 static inline int __enable_fpu(enum fpu_mode mode)
 {
        int fr;
@@ -86,7 +92,12 @@ fr_common:
                enable_fpu_hazard();
 
                /* check FR has the desired value */
-               return (!!(read_c0_status() & ST0_FR) == !!fr) ? 0 : SIGFPE;
+               if (!!(read_c0_status() & ST0_FR) == !!fr)
+                       return 0;
+
+               /* unsupported FR value */
+               __disable_fpu();
+               return SIGFPE;
 
        default:
                BUG();
@@ -95,12 +106,6 @@ fr_common:
        return SIGFPE;
 }
 
-#define __disable_fpu()                                                        \
-do {                                                                   \
-       clear_c0_status(ST0_CU1);                                       \
-       disable_fpu_hazard();                                           \
-} while (0)
-
 #define clear_fpu_owner()      clear_thread_flag(TIF_USEDFPU)
 
 static inline int __is_fpu_owner(void)
@@ -170,6 +175,7 @@ static inline void lose_fpu(int save)
                }
                disable_msa();
                clear_thread_flag(TIF_USEDMSA);
+               __disable_fpu();
        } else if (is_fpu_owner()) {
                if (save)
                        _save_fp(current);
index fdbff44e5482cd20acc5efc798091894a3292c4f..608aa57799c8194a88d39d2e9b6d9968e072ac8c 100644 (file)
@@ -8,9 +8,9 @@
 #ifndef _ASM_MIPS_JUMP_LABEL_H
 #define _ASM_MIPS_JUMP_LABEL_H
 
-#include <linux/types.h>
+#ifndef __ASSEMBLY__
 
-#ifdef __KERNEL__
+#include <linux/types.h>
 
 #define JUMP_LABEL_NOP_SIZE 4
 
@@ -39,8 +39,6 @@ l_yes:
        return true;
 }
 
-#endif /* __KERNEL__ */
-
 #ifdef CONFIG_64BIT
 typedef u64 jump_label_t;
 #else
@@ -53,4 +51,5 @@ struct jump_entry {
        jump_label_t key;
 };
 
+#endif  /* __ASSEMBLY__ */
 #endif /* _ASM_MIPS_JUMP_LABEL_H */
index 6a9af5fcb5d72ef7878dc9581f366b07568a1c0f..cba22ab7ad4d5fd9087aeb8181c6c45ba3398a8c 100644 (file)
@@ -10,7 +10,8 @@ enum die_val {
        DIE_RI,
        DIE_PAGE_FAULT,
        DIE_BREAK,
-       DIE_SSTEPBP
+       DIE_SSTEPBP,
+       DIE_MSAFP
 };
 
 #endif /* _ASM_MIPS_KDEBUG_H */
index ac4fc716062b791003c76f5572d56863bcdcb2cd..4c25823563fe16dfe8f4008351c111eb0dd5c4ad 100644 (file)
 
 /* MIPS KVM register ids */
 #define MIPS_CP0_32(_R, _S)                                    \
-       (KVM_REG_MIPS | KVM_REG_SIZE_U32 | 0x10000 | (8 * (_R) + (_S)))
+       (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U32 | (8 * (_R) + (_S)))
 
 #define MIPS_CP0_64(_R, _S)                                    \
-       (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0x10000 | (8 * (_R) + (_S)))
+       (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S)))
 
 #define KVM_REG_MIPS_CP0_INDEX         MIPS_CP0_32(0, 0)
 #define KVM_REG_MIPS_CP0_ENTRYLO0      MIPS_CP0_64(2, 0)
 #define KVM_REG_MIPS_CP0_STATUS                MIPS_CP0_32(12, 0)
 #define KVM_REG_MIPS_CP0_CAUSE         MIPS_CP0_32(13, 0)
 #define KVM_REG_MIPS_CP0_EPC           MIPS_CP0_64(14, 0)
+#define KVM_REG_MIPS_CP0_PRID          MIPS_CP0_32(15, 0)
 #define KVM_REG_MIPS_CP0_EBASE         MIPS_CP0_64(15, 1)
 #define KVM_REG_MIPS_CP0_CONFIG                MIPS_CP0_32(16, 0)
 #define KVM_REG_MIPS_CP0_CONFIG1       MIPS_CP0_32(16, 1)
 #define KVM_REG_MIPS_CP0_CONFIG2       MIPS_CP0_32(16, 2)
 #define KVM_REG_MIPS_CP0_CONFIG3       MIPS_CP0_32(16, 3)
+#define KVM_REG_MIPS_CP0_CONFIG4       MIPS_CP0_32(16, 4)
+#define KVM_REG_MIPS_CP0_CONFIG5       MIPS_CP0_32(16, 5)
 #define KVM_REG_MIPS_CP0_CONFIG7       MIPS_CP0_32(16, 7)
 #define KVM_REG_MIPS_CP0_XCONTEXT      MIPS_CP0_64(20, 0)
 #define KVM_REG_MIPS_CP0_ERROREPC      MIPS_CP0_64(30, 0)
@@ -119,6 +122,10 @@ struct kvm_vcpu_stat {
        u32 syscall_exits;
        u32 resvd_inst_exits;
        u32 break_inst_exits;
+       u32 trap_inst_exits;
+       u32 msa_fpe_exits;
+       u32 fpe_exits;
+       u32 msa_disabled_exits;
        u32 flush_dcache_exits;
        u32 halt_successful_poll;
        u32 halt_wakeup;
@@ -138,6 +145,10 @@ enum kvm_mips_exit_types {
        SYSCALL_EXITS,
        RESVD_INST_EXITS,
        BREAK_INST_EXITS,
+       TRAP_INST_EXITS,
+       MSA_FPE_EXITS,
+       FPE_EXITS,
+       MSA_DISABLED_EXITS,
        FLUSH_DCACHE_EXITS,
        MAX_KVM_MIPS_EXIT_TYPES
 };
@@ -206,6 +217,8 @@ struct mips_coproc {
 #define MIPS_CP0_CONFIG1_SEL   1
 #define MIPS_CP0_CONFIG2_SEL   2
 #define MIPS_CP0_CONFIG3_SEL   3
+#define MIPS_CP0_CONFIG4_SEL   4
+#define MIPS_CP0_CONFIG5_SEL   5
 
 /* Config0 register bits */
 #define CP0C0_M                        31
@@ -262,31 +275,6 @@ struct mips_coproc {
 #define CP0C3_SM               1
 #define CP0C3_TL               0
 
-/* Have config1, Cacheable, noncoherent, write-back, write allocate*/
-#define MIPS_CONFIG0                                           \
-  ((1 << CP0C0_M) | (0x3 << CP0C0_K0))
-
-/* Have config2, no coprocessor2 attached, no MDMX support attached,
-   no performance counters, watch registers present,
-   no code compression, EJTAG present, no FPU, no watch registers */
-#define MIPS_CONFIG1                                           \
-((1 << CP0C1_M) |                                              \
- (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) |         \
- (0 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) |         \
- (0 << CP0C1_FP))
-
-/* Have config3, no tertiary/secondary caches implemented */
-#define MIPS_CONFIG2                                           \
-((1 << CP0C2_M))
-
-/* No config4, no DSP ASE, no large physaddr (PABITS),
-   no external interrupt controller, no vectored interrupts,
-   no 1kb pages, no SmartMIPS ASE, no trace logic */
-#define MIPS_CONFIG3                                           \
-((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) |       \
- (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) |     \
- (0 << CP0C3_SM) | (0 << CP0C3_TL))
-
 /* MMU types, the first four entries have the same layout as the
    CP0C0_MT field.  */
 enum mips_mmu_types {
@@ -321,7 +309,9 @@ enum mips_mmu_types {
  */
 #define T_TRAP                 13      /* Trap instruction */
 #define T_VCEI                 14      /* Virtual coherency exception */
+#define T_MSAFPE               14      /* MSA floating point exception */
 #define T_FPE                  15      /* Floating point exception */
+#define T_MSADIS               21      /* MSA disabled exception */
 #define T_WATCH                        23      /* Watch address reference */
 #define T_VCED                 31      /* Virtual coherency data */
 
@@ -374,6 +364,9 @@ struct kvm_mips_tlb {
        long tlb_lo1;
 };
 
+#define KVM_MIPS_FPU_FPU       0x1
+#define KVM_MIPS_FPU_MSA       0x2
+
 #define KVM_MIPS_GUEST_TLB_SIZE        64
 struct kvm_vcpu_arch {
        void *host_ebase, *guest_ebase;
@@ -395,6 +388,8 @@ struct kvm_vcpu_arch {
 
        /* FPU State */
        struct mips_fpu_struct fpu;
+       /* Which FPU state is loaded (KVM_MIPS_FPU_*) */
+       unsigned int fpu_inuse;
 
        /* COP0 State */
        struct mips_coproc *cop0;
@@ -441,6 +436,9 @@ struct kvm_vcpu_arch {
 
        /* WAIT executed */
        int wait;
+
+       u8 fpu_enabled;
+       u8 msa_enabled;
 };
 
 
@@ -482,11 +480,15 @@ struct kvm_vcpu_arch {
 #define kvm_read_c0_guest_config1(cop0)                (cop0->reg[MIPS_CP0_CONFIG][1])
 #define kvm_read_c0_guest_config2(cop0)                (cop0->reg[MIPS_CP0_CONFIG][2])
 #define kvm_read_c0_guest_config3(cop0)                (cop0->reg[MIPS_CP0_CONFIG][3])
+#define kvm_read_c0_guest_config4(cop0)                (cop0->reg[MIPS_CP0_CONFIG][4])
+#define kvm_read_c0_guest_config5(cop0)                (cop0->reg[MIPS_CP0_CONFIG][5])
 #define kvm_read_c0_guest_config7(cop0)                (cop0->reg[MIPS_CP0_CONFIG][7])
 #define kvm_write_c0_guest_config(cop0, val)   (cop0->reg[MIPS_CP0_CONFIG][0] = (val))
 #define kvm_write_c0_guest_config1(cop0, val)  (cop0->reg[MIPS_CP0_CONFIG][1] = (val))
 #define kvm_write_c0_guest_config2(cop0, val)  (cop0->reg[MIPS_CP0_CONFIG][2] = (val))
 #define kvm_write_c0_guest_config3(cop0, val)  (cop0->reg[MIPS_CP0_CONFIG][3] = (val))
+#define kvm_write_c0_guest_config4(cop0, val)  (cop0->reg[MIPS_CP0_CONFIG][4] = (val))
+#define kvm_write_c0_guest_config5(cop0, val)  (cop0->reg[MIPS_CP0_CONFIG][5] = (val))
 #define kvm_write_c0_guest_config7(cop0, val)  (cop0->reg[MIPS_CP0_CONFIG][7] = (val))
 #define kvm_read_c0_guest_errorepc(cop0)       (cop0->reg[MIPS_CP0_ERROR_PC][0])
 #define kvm_write_c0_guest_errorepc(cop0, val) (cop0->reg[MIPS_CP0_ERROR_PC][0] = (val))
@@ -567,6 +569,31 @@ static inline void _kvm_atomic_change_c0_guest_reg(unsigned long *reg,
        kvm_set_c0_guest_ebase(cop0, ((val) & (change)));               \
 }
 
+/* Helpers */
+
+static inline bool kvm_mips_guest_can_have_fpu(struct kvm_vcpu_arch *vcpu)
+{
+       return (!__builtin_constant_p(cpu_has_fpu) || cpu_has_fpu) &&
+               vcpu->fpu_enabled;
+}
+
+static inline bool kvm_mips_guest_has_fpu(struct kvm_vcpu_arch *vcpu)
+{
+       return kvm_mips_guest_can_have_fpu(vcpu) &&
+               kvm_read_c0_guest_config1(vcpu->cop0) & MIPS_CONF1_FP;
+}
+
+static inline bool kvm_mips_guest_can_have_msa(struct kvm_vcpu_arch *vcpu)
+{
+       return (!__builtin_constant_p(cpu_has_msa) || cpu_has_msa) &&
+               vcpu->msa_enabled;
+}
+
+static inline bool kvm_mips_guest_has_msa(struct kvm_vcpu_arch *vcpu)
+{
+       return kvm_mips_guest_can_have_msa(vcpu) &&
+               kvm_read_c0_guest_config3(vcpu->cop0) & MIPS_CONF3_MSA;
+}
 
 struct kvm_mips_callbacks {
        int (*handle_cop_unusable)(struct kvm_vcpu *vcpu);
@@ -578,6 +605,10 @@ struct kvm_mips_callbacks {
        int (*handle_syscall)(struct kvm_vcpu *vcpu);
        int (*handle_res_inst)(struct kvm_vcpu *vcpu);
        int (*handle_break)(struct kvm_vcpu *vcpu);
+       int (*handle_trap)(struct kvm_vcpu *vcpu);
+       int (*handle_msa_fpe)(struct kvm_vcpu *vcpu);
+       int (*handle_fpe)(struct kvm_vcpu *vcpu);
+       int (*handle_msa_disabled)(struct kvm_vcpu *vcpu);
        int (*vm_init)(struct kvm *kvm);
        int (*vcpu_init)(struct kvm_vcpu *vcpu);
        int (*vcpu_setup)(struct kvm_vcpu *vcpu);
@@ -596,6 +627,8 @@ struct kvm_mips_callbacks {
                           const struct kvm_one_reg *reg, s64 *v);
        int (*set_one_reg)(struct kvm_vcpu *vcpu,
                           const struct kvm_one_reg *reg, s64 v);
+       int (*vcpu_get_regs)(struct kvm_vcpu *vcpu);
+       int (*vcpu_set_regs)(struct kvm_vcpu *vcpu);
 };
 extern struct kvm_mips_callbacks *kvm_mips_callbacks;
 int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks);
@@ -606,6 +639,19 @@ int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu);
 /* Trampoline ASM routine to start running in "Guest" context */
 extern int __kvm_mips_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu);
 
+/* FPU/MSA context management */
+void __kvm_save_fpu(struct kvm_vcpu_arch *vcpu);
+void __kvm_restore_fpu(struct kvm_vcpu_arch *vcpu);
+void __kvm_restore_fcsr(struct kvm_vcpu_arch *vcpu);
+void __kvm_save_msa(struct kvm_vcpu_arch *vcpu);
+void __kvm_restore_msa(struct kvm_vcpu_arch *vcpu);
+void __kvm_restore_msa_upper(struct kvm_vcpu_arch *vcpu);
+void __kvm_restore_msacsr(struct kvm_vcpu_arch *vcpu);
+void kvm_own_fpu(struct kvm_vcpu *vcpu);
+void kvm_own_msa(struct kvm_vcpu *vcpu);
+void kvm_drop_fpu(struct kvm_vcpu *vcpu);
+void kvm_lose_fpu(struct kvm_vcpu *vcpu);
+
 /* TLB handling */
 uint32_t kvm_get_kernel_asid(struct kvm_vcpu *vcpu);
 
@@ -711,6 +757,26 @@ extern enum emulation_result kvm_mips_emulate_bp_exc(unsigned long cause,
                                                     struct kvm_run *run,
                                                     struct kvm_vcpu *vcpu);
 
+extern enum emulation_result kvm_mips_emulate_trap_exc(unsigned long cause,
+                                                      uint32_t *opc,
+                                                      struct kvm_run *run,
+                                                      struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_emulate_msafpe_exc(unsigned long cause,
+                                                        uint32_t *opc,
+                                                        struct kvm_run *run,
+                                                        struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_emulate_fpe_exc(unsigned long cause,
+                                                     uint32_t *opc,
+                                                     struct kvm_run *run,
+                                                     struct kvm_vcpu *vcpu);
+
+extern enum emulation_result kvm_mips_emulate_msadis_exc(unsigned long cause,
+                                                        uint32_t *opc,
+                                                        struct kvm_run *run,
+                                                        struct kvm_vcpu *vcpu);
+
 extern enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
                                                         struct kvm_run *run);
 
@@ -749,6 +815,11 @@ enum emulation_result kvm_mips_emulate_load(uint32_t inst,
                                            struct kvm_run *run,
                                            struct kvm_vcpu *vcpu);
 
+unsigned int kvm_mips_config1_wrmask(struct kvm_vcpu *vcpu);
+unsigned int kvm_mips_config3_wrmask(struct kvm_vcpu *vcpu);
+unsigned int kvm_mips_config4_wrmask(struct kvm_vcpu *vcpu);
+unsigned int kvm_mips_config5_wrmask(struct kvm_vcpu *vcpu);
+
 /* Dynamic binary translation */
 extern int kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc,
                                      struct kvm_vcpu *vcpu);
index b5dcbee01fd7a52641584cbbf8b80848f7c6f4b9..9b3b48e21c221ffdcfc04ec9cae6165576043225 100644 (file)
@@ -105,7 +105,7 @@ union fpureg {
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
 # define FPR_IDX(width, idx)   (idx)
 #else
-# define FPR_IDX(width, idx)   ((FPU_REG_WIDTH / (width)) - 1 - (idx))
+# define FPR_IDX(width, idx)   ((idx) ^ ((64 / (width)) - 1))
 #endif
 
 #define BUILD_FPR_ACCESS(width) \
index 2c04b6d9ff85380de722745e934944411a5e33d3..6985eb59b08534581f7b4316655367182cb6f64f 100644 (file)
@@ -36,77 +36,85 @@ struct kvm_regs {
 
 /*
  * for KVM_GET_FPU and KVM_SET_FPU
- *
- * If Status[FR] is zero (32-bit FPU), the upper 32-bits of the FPRs
- * are zero filled.
  */
 struct kvm_fpu {
-       __u64 fpr[32];
-       __u32 fir;
-       __u32 fccr;
-       __u32 fexr;
-       __u32 fenr;
-       __u32 fcsr;
-       __u32 pad;
 };
 
 
 /*
- * For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access CP0
+ * For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various
  * registers.  The id field is broken down as follows:
  *
- *  bits[2..0]   - Register 'sel' index.
- *  bits[7..3]   - Register 'rd'  index.
- *  bits[15..8]  - Must be zero.
- *  bits[31..16] - 1 -> CP0 registers.
- *  bits[51..32] - Must be zero.
  *  bits[63..52] - As per linux/kvm.h
+ *  bits[51..32] - Must be zero.
+ *  bits[31..16] - Register set.
+ *
+ * Register set = 0: GP registers from kvm_regs (see definitions below).
+ *
+ * Register set = 1: CP0 registers.
+ *  bits[15..8]  - Must be zero.
+ *  bits[7..3]   - Register 'rd'  index.
+ *  bits[2..0]   - Register 'sel' index.
+ *
+ * Register set = 2: KVM specific registers (see definitions below).
+ *
+ * Register set = 3: FPU / MSA registers (see definitions below).
  *
  * Other sets registers may be added in the future.  Each set would
  * have its own identifier in bits[31..16].
- *
- * The registers defined in struct kvm_regs are also accessible, the
- * id values for these are below.
  */
 
-#define KVM_REG_MIPS_R0 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0)
-#define KVM_REG_MIPS_R1 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 1)
-#define KVM_REG_MIPS_R2 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 2)
-#define KVM_REG_MIPS_R3 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 3)
-#define KVM_REG_MIPS_R4 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 4)
-#define KVM_REG_MIPS_R5 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 5)
-#define KVM_REG_MIPS_R6 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 6)
-#define KVM_REG_MIPS_R7 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 7)
-#define KVM_REG_MIPS_R8 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 8)
-#define KVM_REG_MIPS_R9 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 9)
-#define KVM_REG_MIPS_R10 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 10)
-#define KVM_REG_MIPS_R11 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 11)
-#define KVM_REG_MIPS_R12 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 12)
-#define KVM_REG_MIPS_R13 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 13)
-#define KVM_REG_MIPS_R14 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 14)
-#define KVM_REG_MIPS_R15 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 15)
-#define KVM_REG_MIPS_R16 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 16)
-#define KVM_REG_MIPS_R17 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 17)
-#define KVM_REG_MIPS_R18 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 18)
-#define KVM_REG_MIPS_R19 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 19)
-#define KVM_REG_MIPS_R20 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 20)
-#define KVM_REG_MIPS_R21 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 21)
-#define KVM_REG_MIPS_R22 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 22)
-#define KVM_REG_MIPS_R23 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 23)
-#define KVM_REG_MIPS_R24 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 24)
-#define KVM_REG_MIPS_R25 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 25)
-#define KVM_REG_MIPS_R26 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 26)
-#define KVM_REG_MIPS_R27 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 27)
-#define KVM_REG_MIPS_R28 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 28)
-#define KVM_REG_MIPS_R29 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 29)
-#define KVM_REG_MIPS_R30 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 30)
-#define KVM_REG_MIPS_R31 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 31)
-
-#define KVM_REG_MIPS_HI (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 32)
-#define KVM_REG_MIPS_LO (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 33)
-#define KVM_REG_MIPS_PC (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 34)
-
-/* KVM specific control registers */
+#define KVM_REG_MIPS_GP                (KVM_REG_MIPS | 0x0000000000000000ULL)
+#define KVM_REG_MIPS_CP0       (KVM_REG_MIPS | 0x0000000000010000ULL)
+#define KVM_REG_MIPS_KVM       (KVM_REG_MIPS | 0x0000000000020000ULL)
+#define KVM_REG_MIPS_FPU       (KVM_REG_MIPS | 0x0000000000030000ULL)
+
+
+/*
+ * KVM_REG_MIPS_GP - General purpose registers from kvm_regs.
+ */
+
+#define KVM_REG_MIPS_R0                (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 |  0)
+#define KVM_REG_MIPS_R1                (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 |  1)
+#define KVM_REG_MIPS_R2                (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 |  2)
+#define KVM_REG_MIPS_R3                (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 |  3)
+#define KVM_REG_MIPS_R4                (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 |  4)
+#define KVM_REG_MIPS_R5                (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 |  5)
+#define KVM_REG_MIPS_R6                (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 |  6)
+#define KVM_REG_MIPS_R7                (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 |  7)
+#define KVM_REG_MIPS_R8                (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 |  8)
+#define KVM_REG_MIPS_R9                (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 |  9)
+#define KVM_REG_MIPS_R10       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 10)
+#define KVM_REG_MIPS_R11       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 11)
+#define KVM_REG_MIPS_R12       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 12)
+#define KVM_REG_MIPS_R13       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 13)
+#define KVM_REG_MIPS_R14       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 14)
+#define KVM_REG_MIPS_R15       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 15)
+#define KVM_REG_MIPS_R16       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 16)
+#define KVM_REG_MIPS_R17       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 17)
+#define KVM_REG_MIPS_R18       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 18)
+#define KVM_REG_MIPS_R19       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 19)
+#define KVM_REG_MIPS_R20       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 20)
+#define KVM_REG_MIPS_R21       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 21)
+#define KVM_REG_MIPS_R22       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 22)
+#define KVM_REG_MIPS_R23       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 23)
+#define KVM_REG_MIPS_R24       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 24)
+#define KVM_REG_MIPS_R25       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 25)
+#define KVM_REG_MIPS_R26       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 26)
+#define KVM_REG_MIPS_R27       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 27)
+#define KVM_REG_MIPS_R28       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 28)
+#define KVM_REG_MIPS_R29       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 29)
+#define KVM_REG_MIPS_R30       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 30)
+#define KVM_REG_MIPS_R31       (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 31)
+
+#define KVM_REG_MIPS_HI                (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 32)
+#define KVM_REG_MIPS_LO                (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 33)
+#define KVM_REG_MIPS_PC                (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 34)
+
+
+/*
+ * KVM_REG_MIPS_KVM - KVM specific control registers.
+ */
 
 /*
  * CP0_Count control
@@ -118,8 +126,7 @@ struct kvm_fpu {
  *        safely without losing time or guest timer interrupts.
  * Other: Reserved, do not change.
  */
-#define KVM_REG_MIPS_COUNT_CTL         (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
-                                        0x20000 | 0)
+#define KVM_REG_MIPS_COUNT_CTL     (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 0)
 #define KVM_REG_MIPS_COUNT_CTL_DC      0x00000001
 
 /*
@@ -131,15 +138,46 @@ struct kvm_fpu {
  * emulated.
  * Modifications to times in the future are rejected.
  */
-#define KVM_REG_MIPS_COUNT_RESUME      (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
-                                        0x20000 | 1)
+#define KVM_REG_MIPS_COUNT_RESUME   (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 1)
 /*
  * CP0_Count rate in Hz
  * Specifies the rate of the CP0_Count timer in Hz. Modifications occur without
  * discontinuities in CP0_Count.
  */
-#define KVM_REG_MIPS_COUNT_HZ          (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
-                                        0x20000 | 2)
+#define KVM_REG_MIPS_COUNT_HZ      (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 2)
+
+
+/*
+ * KVM_REG_MIPS_FPU - Floating Point and MIPS SIMD Architecture (MSA) registers.
+ *
+ *  bits[15..8]  - Register subset (see definitions below).
+ *  bits[7..5]   - Must be zero.
+ *  bits[4..0]   - Register number within register subset.
+ */
+
+#define KVM_REG_MIPS_FPR       (KVM_REG_MIPS_FPU | 0x0000000000000000ULL)
+#define KVM_REG_MIPS_FCR       (KVM_REG_MIPS_FPU | 0x0000000000000100ULL)
+#define KVM_REG_MIPS_MSACR     (KVM_REG_MIPS_FPU | 0x0000000000000200ULL)
+
+/*
+ * KVM_REG_MIPS_FPR - Floating point / Vector registers.
+ */
+#define KVM_REG_MIPS_FPR_32(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U32  | (n))
+#define KVM_REG_MIPS_FPR_64(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U64  | (n))
+#define KVM_REG_MIPS_VEC_128(n)        (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U128 | (n))
+
+/*
+ * KVM_REG_MIPS_FCR - Floating point control registers.
+ */
+#define KVM_REG_MIPS_FCR_IR    (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 |  0)
+#define KVM_REG_MIPS_FCR_CSR   (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 31)
+
+/*
+ * KVM_REG_MIPS_MSACR - MIPS SIMD Architecture (MSA) control registers.
+ */
+#define KVM_REG_MIPS_MSA_IR     (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 |  0)
+#define KVM_REG_MIPS_MSA_CSR    (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 |  1)
+
 
 /*
  * KVM MIPS specific structures and definitions
index 750d67ac41e9b19affe066d5be8d1f56f7363041..e59fd7cfac9e35b2eeb90912c58504b9ed435606 100644 (file)
@@ -167,72 +167,6 @@ void output_thread_fpu_defines(void)
        OFFSET(THREAD_FPR30, task_struct, thread.fpu.fpr[30]);
        OFFSET(THREAD_FPR31, task_struct, thread.fpu.fpr[31]);
 
-       /* the least significant 64 bits of each FP register */
-       OFFSET(THREAD_FPR0_LS64, task_struct,
-              thread.fpu.fpr[0].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR1_LS64, task_struct,
-              thread.fpu.fpr[1].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR2_LS64, task_struct,
-              thread.fpu.fpr[2].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR3_LS64, task_struct,
-              thread.fpu.fpr[3].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR4_LS64, task_struct,
-              thread.fpu.fpr[4].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR5_LS64, task_struct,
-              thread.fpu.fpr[5].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR6_LS64, task_struct,
-              thread.fpu.fpr[6].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR7_LS64, task_struct,
-              thread.fpu.fpr[7].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR8_LS64, task_struct,
-              thread.fpu.fpr[8].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR9_LS64, task_struct,
-              thread.fpu.fpr[9].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR10_LS64, task_struct,
-              thread.fpu.fpr[10].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR11_LS64, task_struct,
-              thread.fpu.fpr[11].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR12_LS64, task_struct,
-              thread.fpu.fpr[12].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR13_LS64, task_struct,
-              thread.fpu.fpr[13].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR14_LS64, task_struct,
-              thread.fpu.fpr[14].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR15_LS64, task_struct,
-              thread.fpu.fpr[15].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR16_LS64, task_struct,
-              thread.fpu.fpr[16].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR17_LS64, task_struct,
-              thread.fpu.fpr[17].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR18_LS64, task_struct,
-              thread.fpu.fpr[18].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR19_LS64, task_struct,
-              thread.fpu.fpr[19].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR20_LS64, task_struct,
-              thread.fpu.fpr[20].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR21_LS64, task_struct,
-              thread.fpu.fpr[21].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR22_LS64, task_struct,
-              thread.fpu.fpr[22].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR23_LS64, task_struct,
-              thread.fpu.fpr[23].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR24_LS64, task_struct,
-              thread.fpu.fpr[24].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR25_LS64, task_struct,
-              thread.fpu.fpr[25].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR26_LS64, task_struct,
-              thread.fpu.fpr[26].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR27_LS64, task_struct,
-              thread.fpu.fpr[27].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR28_LS64, task_struct,
-              thread.fpu.fpr[28].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR29_LS64, task_struct,
-              thread.fpu.fpr[29].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR30_LS64, task_struct,
-              thread.fpu.fpr[30].val64[FPR_IDX(64, 0)]);
-       OFFSET(THREAD_FPR31_LS64, task_struct,
-              thread.fpu.fpr[31].val64[FPR_IDX(64, 0)]);
-
        OFFSET(THREAD_FCR31, task_struct, thread.fpu.fcr31);
        OFFSET(THREAD_MSA_CSR, task_struct, thread.fpu.msacsr);
        BLANK();
@@ -470,6 +404,45 @@ void output_kvm_defines(void)
        OFFSET(VCPU_LO, kvm_vcpu_arch, lo);
        OFFSET(VCPU_HI, kvm_vcpu_arch, hi);
        OFFSET(VCPU_PC, kvm_vcpu_arch, pc);
+       BLANK();
+
+       OFFSET(VCPU_FPR0, kvm_vcpu_arch, fpu.fpr[0]);
+       OFFSET(VCPU_FPR1, kvm_vcpu_arch, fpu.fpr[1]);
+       OFFSET(VCPU_FPR2, kvm_vcpu_arch, fpu.fpr[2]);
+       OFFSET(VCPU_FPR3, kvm_vcpu_arch, fpu.fpr[3]);
+       OFFSET(VCPU_FPR4, kvm_vcpu_arch, fpu.fpr[4]);
+       OFFSET(VCPU_FPR5, kvm_vcpu_arch, fpu.fpr[5]);
+       OFFSET(VCPU_FPR6, kvm_vcpu_arch, fpu.fpr[6]);
+       OFFSET(VCPU_FPR7, kvm_vcpu_arch, fpu.fpr[7]);
+       OFFSET(VCPU_FPR8, kvm_vcpu_arch, fpu.fpr[8]);
+       OFFSET(VCPU_FPR9, kvm_vcpu_arch, fpu.fpr[9]);
+       OFFSET(VCPU_FPR10, kvm_vcpu_arch, fpu.fpr[10]);
+       OFFSET(VCPU_FPR11, kvm_vcpu_arch, fpu.fpr[11]);
+       OFFSET(VCPU_FPR12, kvm_vcpu_arch, fpu.fpr[12]);
+       OFFSET(VCPU_FPR13, kvm_vcpu_arch, fpu.fpr[13]);
+       OFFSET(VCPU_FPR14, kvm_vcpu_arch, fpu.fpr[14]);
+       OFFSET(VCPU_FPR15, kvm_vcpu_arch, fpu.fpr[15]);
+       OFFSET(VCPU_FPR16, kvm_vcpu_arch, fpu.fpr[16]);
+       OFFSET(VCPU_FPR17, kvm_vcpu_arch, fpu.fpr[17]);
+       OFFSET(VCPU_FPR18, kvm_vcpu_arch, fpu.fpr[18]);
+       OFFSET(VCPU_FPR19, kvm_vcpu_arch, fpu.fpr[19]);
+       OFFSET(VCPU_FPR20, kvm_vcpu_arch, fpu.fpr[20]);
+       OFFSET(VCPU_FPR21, kvm_vcpu_arch, fpu.fpr[21]);
+       OFFSET(VCPU_FPR22, kvm_vcpu_arch, fpu.fpr[22]);
+       OFFSET(VCPU_FPR23, kvm_vcpu_arch, fpu.fpr[23]);
+       OFFSET(VCPU_FPR24, kvm_vcpu_arch, fpu.fpr[24]);
+       OFFSET(VCPU_FPR25, kvm_vcpu_arch, fpu.fpr[25]);
+       OFFSET(VCPU_FPR26, kvm_vcpu_arch, fpu.fpr[26]);
+       OFFSET(VCPU_FPR27, kvm_vcpu_arch, fpu.fpr[27]);
+       OFFSET(VCPU_FPR28, kvm_vcpu_arch, fpu.fpr[28]);
+       OFFSET(VCPU_FPR29, kvm_vcpu_arch, fpu.fpr[29]);
+       OFFSET(VCPU_FPR30, kvm_vcpu_arch, fpu.fpr[30]);
+       OFFSET(VCPU_FPR31, kvm_vcpu_arch, fpu.fpr[31]);
+
+       OFFSET(VCPU_FCR31, kvm_vcpu_arch, fpu.fcr31);
+       OFFSET(VCPU_MSA_CSR, kvm_vcpu_arch, fpu.msacsr);
+       BLANK();
+
        OFFSET(VCPU_COP0, kvm_vcpu_arch, cop0);
        OFFSET(VCPU_GUEST_KERNEL_ASID, kvm_vcpu_arch, guest_kernel_asid);
        OFFSET(VCPU_GUEST_USER_ASID, kvm_vcpu_arch, guest_user_asid);
index 2ebaabe3af1513269e100d8bcffa9e8e9cb1f2c8..af42e7003f12d025cd31e2a5d167f2f4b158d37a 100644 (file)
@@ -360,12 +360,15 @@ NESTED(nmi_handler, PT_SIZE, sp)
        .set    mips1
        SET_HARDFLOAT
        cfc1    a1, fcr31
-       li      a2, ~(0x3f << 12)
-       and     a2, a1
-       ctc1    a2, fcr31
        .set    pop
-       TRACE_IRQS_ON
-       STI
+       CLI
+       TRACE_IRQS_OFF
+       .endm
+
+       .macro  __build_clear_msa_fpe
+       _cfcmsa a1, MSA_CSR
+       CLI
+       TRACE_IRQS_OFF
        .endm
 
        .macro  __build_clear_ade
@@ -426,7 +429,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
        BUILD_HANDLER cpu cpu sti silent                /* #11 */
        BUILD_HANDLER ov ov sti silent                  /* #12 */
        BUILD_HANDLER tr tr sti silent                  /* #13 */
-       BUILD_HANDLER msa_fpe msa_fpe sti silent        /* #14 */
+       BUILD_HANDLER msa_fpe msa_fpe msa_fpe silent    /* #14 */
        BUILD_HANDLER fpe fpe fpe silent                /* #15 */
        BUILD_HANDLER ftlb ftlb none silent             /* #16 */
        BUILD_HANDLER msa msa sti silent                /* #21 */
index 51045281259403c55fcefac09d510f874a3047bb..7da6e324dd354a77991c4fe2dd998c07b998d956 100644 (file)
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
 
+static void init_fp_ctx(struct task_struct *target)
+{
+       /* If FP has been used then the target already has context */
+       if (tsk_used_math(target))
+               return;
+
+       /* Begin with data registers set to all 1s... */
+       memset(&target->thread.fpu.fpr, ~0, sizeof(target->thread.fpu.fpr));
+
+       /* ...and FCSR zeroed */
+       target->thread.fpu.fcr31 = 0;
+
+       /*
+        * Record that the target has "used" math, such that the context
+        * just initialised, and any modifications made by the caller,
+        * aren't discarded.
+        */
+       set_stopped_child_used_math(target);
+}
+
 /*
  * Called by kernel/ptrace.c when detaching..
  *
@@ -142,6 +162,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
        if (!access_ok(VERIFY_READ, data, 33 * 8))
                return -EIO;
 
+       init_fp_ctx(child);
        fregs = get_fpu_regs(child);
 
        for (i = 0; i < 32; i++) {
@@ -439,6 +460,8 @@ static int fpr_set(struct task_struct *target,
 
        /* XXX fcr31  */
 
+       init_fp_ctx(target);
+
        if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
                return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
                                          &target->thread.fpu,
@@ -660,12 +683,7 @@ long arch_ptrace(struct task_struct *child, long request,
                case FPR_BASE ... FPR_BASE + 31: {
                        union fpureg *fregs = get_fpu_regs(child);
 
-                       if (!tsk_used_math(child)) {
-                               /* FP not yet used  */
-                               memset(&child->thread.fpu, ~0,
-                                      sizeof(child->thread.fpu));
-                               child->thread.fpu.fcr31 = 0;
-                       }
+                       init_fp_ctx(child);
 #ifdef CONFIG_32BIT
                        if (test_thread_flag(TIF_32BIT_FPREGS)) {
                                /*
index 676c5030a953bf9cca5ad038a7526d3b94ce372d..1d88af26ba82a0c3ee58ff8ff3b2b1661dad9455 100644 (file)
@@ -34,7 +34,6 @@
        .endm
 
        .set    noreorder
-       .set    MIPS_ISA_ARCH_LEVEL_RAW
 
 LEAF(_save_fp_context)
        .set    push
@@ -103,6 +102,7 @@ LEAF(_save_fp_context)
        /* Save 32-bit process floating point context */
 LEAF(_save_fp_context32)
        .set push
+       .set MIPS_ISA_ARCH_LEVEL_RAW
        SET_HARDFLOAT
        cfc1    t1, fcr31
 
index 33984c04b60b710516f1b0bfb88aa52aaa04629f..5b4d711f878da251a101526671a80283503736a4 100644 (file)
@@ -701,6 +701,13 @@ asmlinkage void do_ov(struct pt_regs *regs)
 
 int process_fpemu_return(int sig, void __user *fault_addr)
 {
+       /*
+        * We can't allow the emulated instruction to leave any of the cause
+        * bits set in FCSR. If they were then the kernel would take an FP
+        * exception when restoring FP context.
+        */
+       current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
+
        if (sig == SIGSEGV || sig == SIGBUS) {
                struct siginfo si = {0};
                si.si_addr = fault_addr;
@@ -781,6 +788,11 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
        if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs),
                       SIGFPE) == NOTIFY_STOP)
                goto out;
+
+       /* Clear FCSR.Cause before enabling interrupts */
+       write_32bit_cp1_register(CP1_STATUS, fcr31 & ~FPU_CSR_ALL_X);
+       local_irq_enable();
+
        die_if_kernel("FP exception in kernel code", regs);
 
        if (fcr31 & FPU_CSR_UNI_X) {
@@ -804,18 +816,12 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
                                               &fault_addr);
 
-               /*
-                * We can't allow the emulated instruction to leave any of
-                * the cause bit set in $fcr31.
-                */
-               current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
+               /* If something went wrong, signal */
+               process_fpemu_return(sig, fault_addr);
 
                /* Restore the hardware register state */
                own_fpu(1);     /* Using the FPU again.  */
 
-               /* If something went wrong, signal */
-               process_fpemu_return(sig, fault_addr);
-
                goto out;
        } else if (fcr31 & FPU_CSR_INV_X)
                info.si_code = FPE_FLTINV;
@@ -1392,13 +1398,22 @@ out:
        exception_exit(prev_state);
 }
 
-asmlinkage void do_msa_fpe(struct pt_regs *regs)
+asmlinkage void do_msa_fpe(struct pt_regs *regs, unsigned int msacsr)
 {
        enum ctx_state prev_state;
 
        prev_state = exception_enter();
+       if (notify_die(DIE_MSAFP, "MSA FP exception", regs, 0,
+                      regs_to_trapnr(regs), SIGFPE) == NOTIFY_STOP)
+               goto out;
+
+       /* Clear MSACSR.Cause before enabling interrupts */
+       write_msa_csr(msacsr & ~MSA_CSR_CAUSEF);
+       local_irq_enable();
+
        die_if_kernel("do_msa_fpe invoked from kernel context!", regs);
        force_sig(SIGFPE, current);
+out:
        exception_exit(prev_state);
 }
 
index 401fe027c2612cf774fa53173420f93c072ea3c7..637ebbebd549701c1a0a67e7e3a8fbb9d2cb61f0 100644 (file)
@@ -1,13 +1,15 @@
 # Makefile for KVM support for MIPS
 #
 
-common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
+common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
 
 EXTRA_CFLAGS += -Ivirt/kvm -Iarch/mips/kvm
 
-kvm-objs := $(common-objs) mips.o emulate.o locore.o \
+common-objs-$(CONFIG_CPU_HAS_MSA) += msa.o
+
+kvm-objs := $(common-objs-y) mips.o emulate.o locore.o \
            interrupt.o stats.o commpage.o \
-           dyntrans.o trap_emul.o
+           dyntrans.o trap_emul.o fpu.o
 
 obj-$(CONFIG_KVM)      += kvm.o
 obj-y                  += callback.o tlb.o
index fb3e8dfd1ff647263c0ca93a1d2ba6c5fdbd906b..6230f376a44e7ab6f09041c4b805e54e59468489 100644 (file)
@@ -884,6 +884,84 @@ enum emulation_result kvm_mips_emul_tlbp(struct kvm_vcpu *vcpu)
        return EMULATE_DONE;
 }
 
+/**
+ * kvm_mips_config1_wrmask() - Find mask of writable bits in guest Config1
+ * @vcpu:      Virtual CPU.
+ *
+ * Finds the mask of bits which are writable in the guest's Config1 CP0
+ * register, by userland (currently read-only to the guest).
+ */
+unsigned int kvm_mips_config1_wrmask(struct kvm_vcpu *vcpu)
+{
+       unsigned int mask = 0;
+
+       /* Permit FPU to be present if FPU is supported */
+       if (kvm_mips_guest_can_have_fpu(&vcpu->arch))
+               mask |= MIPS_CONF1_FP;
+
+       return mask;
+}
+
+/**
+ * kvm_mips_config3_wrmask() - Find mask of writable bits in guest Config3
+ * @vcpu:      Virtual CPU.
+ *
+ * Finds the mask of bits which are writable in the guest's Config3 CP0
+ * register, by userland (currently read-only to the guest).
+ */
+unsigned int kvm_mips_config3_wrmask(struct kvm_vcpu *vcpu)
+{
+       /* Config4 is optional */
+       unsigned int mask = MIPS_CONF_M;
+
+       /* Permit MSA to be present if MSA is supported */
+       if (kvm_mips_guest_can_have_msa(&vcpu->arch))
+               mask |= MIPS_CONF3_MSA;
+
+       return mask;
+}
+
+/**
+ * kvm_mips_config4_wrmask() - Find mask of writable bits in guest Config4
+ * @vcpu:      Virtual CPU.
+ *
+ * Finds the mask of bits which are writable in the guest's Config4 CP0
+ * register, by userland (currently read-only to the guest).
+ */
+unsigned int kvm_mips_config4_wrmask(struct kvm_vcpu *vcpu)
+{
+       /* Config5 is optional */
+       return MIPS_CONF_M;
+}
+
+/**
+ * kvm_mips_config5_wrmask() - Find mask of writable bits in guest Config5
+ * @vcpu:      Virtual CPU.
+ *
+ * Finds the mask of bits which are writable in the guest's Config5 CP0
+ * register, by the guest itself.
+ */
+unsigned int kvm_mips_config5_wrmask(struct kvm_vcpu *vcpu)
+{
+       unsigned int mask = 0;
+
+       /* Permit MSAEn changes if MSA supported and enabled */
+       if (kvm_mips_guest_has_msa(&vcpu->arch))
+               mask |= MIPS_CONF5_MSAEN;
+
+       /*
+        * Permit guest FPU mode changes if FPU is enabled and the relevant
+        * feature exists according to FIR register.
+        */
+       if (kvm_mips_guest_has_fpu(&vcpu->arch)) {
+               if (cpu_has_fre)
+                       mask |= MIPS_CONF5_FRE;
+               /* We don't support UFR or UFE */
+       }
+
+       return mask;
+}
+
 enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc,
                                           uint32_t cause, struct kvm_run *run,
                                           struct kvm_vcpu *vcpu)
@@ -1021,18 +1099,114 @@ enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc,
                                kvm_mips_write_compare(vcpu,
                                                       vcpu->arch.gprs[rt]);
                        } else if ((rd == MIPS_CP0_STATUS) && (sel == 0)) {
-                               kvm_write_c0_guest_status(cop0,
-                                                         vcpu->arch.gprs[rt]);
+                               unsigned int old_val, val, change;
+
+                               old_val = kvm_read_c0_guest_status(cop0);
+                               val = vcpu->arch.gprs[rt];
+                               change = val ^ old_val;
+
+                               /* Make sure that the NMI bit is never set */
+                               val &= ~ST0_NMI;
+
+                               /*
+                                * Don't allow CU1 or FR to be set unless FPU
+                                * capability enabled and exists in guest
+                                * configuration.
+                                */
+                               if (!kvm_mips_guest_has_fpu(&vcpu->arch))
+                                       val &= ~(ST0_CU1 | ST0_FR);
+
+                               /*
+                                * Also don't allow FR to be set if host doesn't
+                                * support it.
+                                */
+                               if (!(current_cpu_data.fpu_id & MIPS_FPIR_F64))
+                                       val &= ~ST0_FR;
+
+
+                               /* Handle changes in FPU mode */
+                               preempt_disable();
+
+                               /*
+                                * FPU and Vector register state is made
+                                * UNPREDICTABLE by a change of FR, so don't
+                                * even bother saving it.
+                                */
+                               if (change & ST0_FR)
+                                       kvm_drop_fpu(vcpu);
+
+                               /*
+                                * If MSA state is already live, it is undefined
+                                * how it interacts with FR=0 FPU state, and we
+                                * don't want to hit reserved instruction
+                                * exceptions trying to save the MSA state later
+                                * when CU=1 && FR=1, so play it safe and save
+                                * it first.
+                                */
+                               if (change & ST0_CU1 && !(val & ST0_FR) &&
+                                   vcpu->arch.fpu_inuse & KVM_MIPS_FPU_MSA)
+                                       kvm_lose_fpu(vcpu);
+
                                /*
-                                * Make sure that CU1 and NMI bits are
-                                * never set
+                                * Propagate CU1 (FPU enable) changes
+                                * immediately if the FPU context is already
+                                * loaded. When disabling we leave the context
+                                * loaded so it can be quickly enabled again in
+                                * the near future.
                                 */
-                               kvm_clear_c0_guest_status(cop0,
-                                                         (ST0_CU1 | ST0_NMI));
+                               if (change & ST0_CU1 &&
+                                   vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU)
+                                       change_c0_status(ST0_CU1, val);
+
+                               preempt_enable();
+
+                               kvm_write_c0_guest_status(cop0, val);
 
 #ifdef CONFIG_KVM_MIPS_DYN_TRANS
-                               kvm_mips_trans_mtc0(inst, opc, vcpu);
+                               /*
+                                * If FPU present, we need CU1/FR bits to take
+                                * effect fairly soon.
+                                */
+                               if (!kvm_mips_guest_has_fpu(&vcpu->arch))
+                                       kvm_mips_trans_mtc0(inst, opc, vcpu);
 #endif
+                       } else if ((rd == MIPS_CP0_CONFIG) && (sel == 5)) {
+                               unsigned int old_val, val, change, wrmask;
+
+                               old_val = kvm_read_c0_guest_config5(cop0);
+                               val = vcpu->arch.gprs[rt];
+
+                               /* Only a few bits are writable in Config5 */
+                               wrmask = kvm_mips_config5_wrmask(vcpu);
+                               change = (val ^ old_val) & wrmask;
+                               val = old_val ^ change;
+
+
+                               /* Handle changes in FPU/MSA modes */
+                               preempt_disable();
+
+                               /*
+                                * Propagate FRE changes immediately if the FPU
+                                * context is already loaded.
+                                */
+                               if (change & MIPS_CONF5_FRE &&
+                                   vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU)
+                                       change_c0_config5(MIPS_CONF5_FRE, val);
+
+                               /*
+                                * Propagate MSAEn changes immediately if the
+                                * MSA context is already loaded. When disabling
+                                * we leave the context loaded so it can be
+                                * quickly enabled again in the near future.
+                                */
+                               if (change & MIPS_CONF5_MSAEN &&
+                                   vcpu->arch.fpu_inuse & KVM_MIPS_FPU_MSA)
+                                       change_c0_config5(MIPS_CONF5_MSAEN,
+                                                         val);
+
+                               preempt_enable();
+
+                               kvm_write_c0_guest_config5(cop0, val);
                        } else if ((rd == MIPS_CP0_CAUSE) && (sel == 0)) {
                                uint32_t old_cause, new_cause;
 
@@ -1970,6 +2144,146 @@ enum emulation_result kvm_mips_emulate_bp_exc(unsigned long cause,
        return er;
 }
 
+enum emulation_result kvm_mips_emulate_trap_exc(unsigned long cause,
+                                               uint32_t *opc,
+                                               struct kvm_run *run,
+                                               struct kvm_vcpu *vcpu)
+{
+       struct mips_coproc *cop0 = vcpu->arch.cop0;
+       struct kvm_vcpu_arch *arch = &vcpu->arch;
+       enum emulation_result er = EMULATE_DONE;
+
+       if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+               /* save old pc */
+               kvm_write_c0_guest_epc(cop0, arch->pc);
+               kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+               if (cause & CAUSEF_BD)
+                       kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+               else
+                       kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+               kvm_debug("Delivering TRAP @ pc %#lx\n", arch->pc);
+
+               kvm_change_c0_guest_cause(cop0, (0xff),
+                                         (T_TRAP << CAUSEB_EXCCODE));
+
+               /* Set PC to the exception entry point */
+               arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+       } else {
+               kvm_err("Trying to deliver TRAP when EXL is already set\n");
+               er = EMULATE_FAIL;
+       }
+
+       return er;
+}
+
+enum emulation_result kvm_mips_emulate_msafpe_exc(unsigned long cause,
+                                                 uint32_t *opc,
+                                                 struct kvm_run *run,
+                                                 struct kvm_vcpu *vcpu)
+{
+       struct mips_coproc *cop0 = vcpu->arch.cop0;
+       struct kvm_vcpu_arch *arch = &vcpu->arch;
+       enum emulation_result er = EMULATE_DONE;
+
+       if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+               /* save old pc */
+               kvm_write_c0_guest_epc(cop0, arch->pc);
+               kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+               if (cause & CAUSEF_BD)
+                       kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+               else
+                       kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+               kvm_debug("Delivering MSAFPE @ pc %#lx\n", arch->pc);
+
+               kvm_change_c0_guest_cause(cop0, (0xff),
+                                         (T_MSAFPE << CAUSEB_EXCCODE));
+
+               /* Set PC to the exception entry point */
+               arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+       } else {
+               kvm_err("Trying to deliver MSAFPE when EXL is already set\n");
+               er = EMULATE_FAIL;
+       }
+
+       return er;
+}
+
+enum emulation_result kvm_mips_emulate_fpe_exc(unsigned long cause,
+                                              uint32_t *opc,
+                                              struct kvm_run *run,
+                                              struct kvm_vcpu *vcpu)
+{
+       struct mips_coproc *cop0 = vcpu->arch.cop0;
+       struct kvm_vcpu_arch *arch = &vcpu->arch;
+       enum emulation_result er = EMULATE_DONE;
+
+       if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+               /* save old pc */
+               kvm_write_c0_guest_epc(cop0, arch->pc);
+               kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+               if (cause & CAUSEF_BD)
+                       kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+               else
+                       kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+               kvm_debug("Delivering FPE @ pc %#lx\n", arch->pc);
+
+               kvm_change_c0_guest_cause(cop0, (0xff),
+                                         (T_FPE << CAUSEB_EXCCODE));
+
+               /* Set PC to the exception entry point */
+               arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+       } else {
+               kvm_err("Trying to deliver FPE when EXL is already set\n");
+               er = EMULATE_FAIL;
+       }
+
+       return er;
+}
+
+enum emulation_result kvm_mips_emulate_msadis_exc(unsigned long cause,
+                                                 uint32_t *opc,
+                                                 struct kvm_run *run,
+                                                 struct kvm_vcpu *vcpu)
+{
+       struct mips_coproc *cop0 = vcpu->arch.cop0;
+       struct kvm_vcpu_arch *arch = &vcpu->arch;
+       enum emulation_result er = EMULATE_DONE;
+
+       if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
+               /* save old pc */
+               kvm_write_c0_guest_epc(cop0, arch->pc);
+               kvm_set_c0_guest_status(cop0, ST0_EXL);
+
+               if (cause & CAUSEF_BD)
+                       kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
+               else
+                       kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
+
+               kvm_debug("Delivering MSADIS @ pc %#lx\n", arch->pc);
+
+               kvm_change_c0_guest_cause(cop0, (0xff),
+                                         (T_MSADIS << CAUSEB_EXCCODE));
+
+               /* Set PC to the exception entry point */
+               arch->pc = KVM_GUEST_KSEG0 + 0x180;
+
+       } else {
+               kvm_err("Trying to deliver MSADIS when EXL is already set\n");
+               er = EMULATE_FAIL;
+       }
+
+       return er;
+}
+
 /* ll/sc, rdhwr, sync emulation */
 
 #define OPCODE 0xfc000000
@@ -2176,6 +2490,10 @@ enum emulation_result kvm_mips_check_privilege(unsigned long cause,
                case T_SYSCALL:
                case T_BREAK:
                case T_RES_INST:
+               case T_TRAP:
+               case T_MSAFPE:
+               case T_FPE:
+               case T_MSADIS:
                        break;
 
                case T_COP_UNUSABLE:
diff --git a/arch/mips/kvm/fpu.S b/arch/mips/kvm/fpu.S
new file mode 100644 (file)
index 0000000..531fbf5
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ *
+ * FPU context handling code for KVM.
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ */
+
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+
+       .set    noreorder
+       .set    noat
+
+LEAF(__kvm_save_fpu)
+       .set    push
+       .set    mips64r2
+       SET_HARDFLOAT
+       mfc0    t0, CP0_STATUS
+       sll     t0, t0, 5                       # is Status.FR set?
+       bgez    t0, 1f                          # no: skip odd doubles
+        nop
+       sdc1    $f1,  VCPU_FPR1(a0)
+       sdc1    $f3,  VCPU_FPR3(a0)
+       sdc1    $f5,  VCPU_FPR5(a0)
+       sdc1    $f7,  VCPU_FPR7(a0)
+       sdc1    $f9,  VCPU_FPR9(a0)
+       sdc1    $f11, VCPU_FPR11(a0)
+       sdc1    $f13, VCPU_FPR13(a0)
+       sdc1    $f15, VCPU_FPR15(a0)
+       sdc1    $f17, VCPU_FPR17(a0)
+       sdc1    $f19, VCPU_FPR19(a0)
+       sdc1    $f21, VCPU_FPR21(a0)
+       sdc1    $f23, VCPU_FPR23(a0)
+       sdc1    $f25, VCPU_FPR25(a0)
+       sdc1    $f27, VCPU_FPR27(a0)
+       sdc1    $f29, VCPU_FPR29(a0)
+       sdc1    $f31, VCPU_FPR31(a0)
+1:     sdc1    $f0,  VCPU_FPR0(a0)
+       sdc1    $f2,  VCPU_FPR2(a0)
+       sdc1    $f4,  VCPU_FPR4(a0)
+       sdc1    $f6,  VCPU_FPR6(a0)
+       sdc1    $f8,  VCPU_FPR8(a0)
+       sdc1    $f10, VCPU_FPR10(a0)
+       sdc1    $f12, VCPU_FPR12(a0)
+       sdc1    $f14, VCPU_FPR14(a0)
+       sdc1    $f16, VCPU_FPR16(a0)
+       sdc1    $f18, VCPU_FPR18(a0)
+       sdc1    $f20, VCPU_FPR20(a0)
+       sdc1    $f22, VCPU_FPR22(a0)
+       sdc1    $f24, VCPU_FPR24(a0)
+       sdc1    $f26, VCPU_FPR26(a0)
+       sdc1    $f28, VCPU_FPR28(a0)
+       jr      ra
+        sdc1   $f30, VCPU_FPR30(a0)
+       .set    pop
+       END(__kvm_save_fpu)
+
+LEAF(__kvm_restore_fpu)
+       .set    push
+       .set    mips64r2
+       SET_HARDFLOAT
+       mfc0    t0, CP0_STATUS
+       sll     t0, t0, 5                       # is Status.FR set?
+       bgez    t0, 1f                          # no: skip odd doubles
+        nop
+       ldc1    $f1,  VCPU_FPR1(a0)
+       ldc1    $f3,  VCPU_FPR3(a0)
+       ldc1    $f5,  VCPU_FPR5(a0)
+       ldc1    $f7,  VCPU_FPR7(a0)
+       ldc1    $f9,  VCPU_FPR9(a0)
+       ldc1    $f11, VCPU_FPR11(a0)
+       ldc1    $f13, VCPU_FPR13(a0)
+       ldc1    $f15, VCPU_FPR15(a0)
+       ldc1    $f17, VCPU_FPR17(a0)
+       ldc1    $f19, VCPU_FPR19(a0)
+       ldc1    $f21, VCPU_FPR21(a0)
+       ldc1    $f23, VCPU_FPR23(a0)
+       ldc1    $f25, VCPU_FPR25(a0)
+       ldc1    $f27, VCPU_FPR27(a0)
+       ldc1    $f29, VCPU_FPR29(a0)
+       ldc1    $f31, VCPU_FPR31(a0)
+1:     ldc1    $f0,  VCPU_FPR0(a0)
+       ldc1    $f2,  VCPU_FPR2(a0)
+       ldc1    $f4,  VCPU_FPR4(a0)
+       ldc1    $f6,  VCPU_FPR6(a0)
+       ldc1    $f8,  VCPU_FPR8(a0)
+       ldc1    $f10, VCPU_FPR10(a0)
+       ldc1    $f12, VCPU_FPR12(a0)
+       ldc1    $f14, VCPU_FPR14(a0)
+       ldc1    $f16, VCPU_FPR16(a0)
+       ldc1    $f18, VCPU_FPR18(a0)
+       ldc1    $f20, VCPU_FPR20(a0)
+       ldc1    $f22, VCPU_FPR22(a0)
+       ldc1    $f24, VCPU_FPR24(a0)
+       ldc1    $f26, VCPU_FPR26(a0)
+       ldc1    $f28, VCPU_FPR28(a0)
+       jr      ra
+        ldc1   $f30, VCPU_FPR30(a0)
+       .set    pop
+       END(__kvm_restore_fpu)
+
+LEAF(__kvm_restore_fcsr)
+       .set    push
+       SET_HARDFLOAT
+       lw      t0, VCPU_FCR31(a0)
+       /*
+        * The ctc1 must stay at this offset in __kvm_restore_fcsr.
+        * See kvm_mips_csr_die_notify() which handles t0 containing a value
+        * which triggers an FP Exception, which must be stepped over and
+        * ignored since the set cause bits must remain there for the guest.
+        */
+       ctc1    t0, fcr31
+       jr      ra
+        nop
+       .set    pop
+       END(__kvm_restore_fcsr)
index 4a68b176d6e4f8dff9680a2c22a41019be1d574f..c567240386a0f10818b0e06433f4b33b1bf5e6dc 100644 (file)
@@ -36,6 +36,8 @@
 #define PT_HOST_USERLOCAL   PT_EPC
 
 #define CP0_DDATA_LO        $28,3
+#define CP0_CONFIG3         $16,3
+#define CP0_CONFIG5         $16,5
 #define CP0_EBASE           $15,1
 
 #define CP0_INTCTL          $12,1
@@ -353,6 +355,42 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
        LONG_L  k0, VCPU_HOST_EBASE(k1)
        mtc0    k0,CP0_EBASE
 
+       /*
+        * If FPU is enabled, save FCR31 and clear it so that later ctc1's don't
+        * trigger FPE for pending exceptions.
+        */
+       .set    at
+       and     v1, v0, ST0_CU1
+       beqz    v1, 1f
+        nop
+       .set    push
+       SET_HARDFLOAT
+       cfc1    t0, fcr31
+       sw      t0, VCPU_FCR31(k1)
+       ctc1    zero,fcr31
+       .set    pop
+       .set    noat
+1:
+
+#ifdef CONFIG_CPU_HAS_MSA
+       /*
+        * If MSA is enabled, save MSACSR and clear it so that later
+        * instructions don't trigger MSAFPE for pending exceptions.
+        */
+       mfc0    t0, CP0_CONFIG3
+       ext     t0, t0, 28, 1 /* MIPS_CONF3_MSAP */
+       beqz    t0, 1f
+        nop
+       mfc0    t0, CP0_CONFIG5
+       ext     t0, t0, 27, 1 /* MIPS_CONF5_MSAEN */
+       beqz    t0, 1f
+        nop
+       _cfcmsa t0, MSA_CSR
+       sw      t0, VCPU_MSA_CSR(k1)
+       _ctcmsa MSA_CSR, zero
+1:
+#endif
+
        /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
        .set    at
        and     v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
index c9eccf5df912037e2b71bbb4a7dddd2a1d2d866e..bb68e8d520e83b5a30b74b22ae3292b1dd1469e1 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/kdebug.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
@@ -48,6 +49,10 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "syscall",      VCPU_STAT(syscall_exits),      KVM_STAT_VCPU },
        { "resvd_inst",   VCPU_STAT(resvd_inst_exits),   KVM_STAT_VCPU },
        { "break_inst",   VCPU_STAT(break_inst_exits),   KVM_STAT_VCPU },
+       { "trap_inst",    VCPU_STAT(trap_inst_exits),    KVM_STAT_VCPU },
+       { "msa_fpe",      VCPU_STAT(msa_fpe_exits),      KVM_STAT_VCPU },
+       { "fpe",          VCPU_STAT(fpe_exits),          KVM_STAT_VCPU },
+       { "msa_disabled", VCPU_STAT(msa_disabled_exits), KVM_STAT_VCPU },
        { "flush_dcache", VCPU_STAT(flush_dcache_exits), KVM_STAT_VCPU },
        { "halt_successful_poll", VCPU_STAT(halt_successful_poll), KVM_STAT_VCPU },
        { "halt_wakeup",  VCPU_STAT(halt_wakeup),        KVM_STAT_VCPU },
@@ -504,10 +509,13 @@ static u64 kvm_mips_get_one_regs[] = {
        KVM_REG_MIPS_CP0_STATUS,
        KVM_REG_MIPS_CP0_CAUSE,
        KVM_REG_MIPS_CP0_EPC,
+       KVM_REG_MIPS_CP0_PRID,
        KVM_REG_MIPS_CP0_CONFIG,
        KVM_REG_MIPS_CP0_CONFIG1,
        KVM_REG_MIPS_CP0_CONFIG2,
        KVM_REG_MIPS_CP0_CONFIG3,
+       KVM_REG_MIPS_CP0_CONFIG4,
+       KVM_REG_MIPS_CP0_CONFIG5,
        KVM_REG_MIPS_CP0_CONFIG7,
        KVM_REG_MIPS_CP0_ERROREPC,
 
@@ -520,10 +528,14 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
                            const struct kvm_one_reg *reg)
 {
        struct mips_coproc *cop0 = vcpu->arch.cop0;
+       struct mips_fpu_struct *fpu = &vcpu->arch.fpu;
        int ret;
        s64 v;
+       s64 vs[2];
+       unsigned int idx;
 
        switch (reg->id) {
+       /* General purpose registers */
        case KVM_REG_MIPS_R0 ... KVM_REG_MIPS_R31:
                v = (long)vcpu->arch.gprs[reg->id - KVM_REG_MIPS_R0];
                break;
@@ -537,6 +549,67 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
                v = (long)vcpu->arch.pc;
                break;
 
+       /* Floating point registers */
+       case KVM_REG_MIPS_FPR_32(0) ... KVM_REG_MIPS_FPR_32(31):
+               if (!kvm_mips_guest_has_fpu(&vcpu->arch))
+                       return -EINVAL;
+               idx = reg->id - KVM_REG_MIPS_FPR_32(0);
+               /* Odd singles in top of even double when FR=0 */
+               if (kvm_read_c0_guest_status(cop0) & ST0_FR)
+                       v = get_fpr32(&fpu->fpr[idx], 0);
+               else
+                       v = get_fpr32(&fpu->fpr[idx & ~1], idx & 1);
+               break;
+       case KVM_REG_MIPS_FPR_64(0) ... KVM_REG_MIPS_FPR_64(31):
+               if (!kvm_mips_guest_has_fpu(&vcpu->arch))
+                       return -EINVAL;
+               idx = reg->id - KVM_REG_MIPS_FPR_64(0);
+               /* Can't access odd doubles in FR=0 mode */
+               if (idx & 1 && !(kvm_read_c0_guest_status(cop0) & ST0_FR))
+                       return -EINVAL;
+               v = get_fpr64(&fpu->fpr[idx], 0);
+               break;
+       case KVM_REG_MIPS_FCR_IR:
+               if (!kvm_mips_guest_has_fpu(&vcpu->arch))
+                       return -EINVAL;
+               v = boot_cpu_data.fpu_id;
+               break;
+       case KVM_REG_MIPS_FCR_CSR:
+               if (!kvm_mips_guest_has_fpu(&vcpu->arch))
+                       return -EINVAL;
+               v = fpu->fcr31;
+               break;
+
+       /* MIPS SIMD Architecture (MSA) registers */
+       case KVM_REG_MIPS_VEC_128(0) ... KVM_REG_MIPS_VEC_128(31):
+               if (!kvm_mips_guest_has_msa(&vcpu->arch))
+                       return -EINVAL;
+               /* Can't access MSA registers in FR=0 mode */
+               if (!(kvm_read_c0_guest_status(cop0) & ST0_FR))
+                       return -EINVAL;
+               idx = reg->id - KVM_REG_MIPS_VEC_128(0);
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+               /* least significant byte first */
+               vs[0] = get_fpr64(&fpu->fpr[idx], 0);
+               vs[1] = get_fpr64(&fpu->fpr[idx], 1);
+#else
+               /* most significant byte first */
+               vs[0] = get_fpr64(&fpu->fpr[idx], 1);
+               vs[1] = get_fpr64(&fpu->fpr[idx], 0);
+#endif
+               break;
+       case KVM_REG_MIPS_MSA_IR:
+               if (!kvm_mips_guest_has_msa(&vcpu->arch))
+                       return -EINVAL;
+               v = boot_cpu_data.msa_id;
+               break;
+       case KVM_REG_MIPS_MSA_CSR:
+               if (!kvm_mips_guest_has_msa(&vcpu->arch))
+                       return -EINVAL;
+               v = fpu->msacsr;
+               break;
+
+       /* Co-processor 0 registers */
        case KVM_REG_MIPS_CP0_INDEX:
                v = (long)kvm_read_c0_guest_index(cop0);
                break;
@@ -573,8 +646,8 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
        case KVM_REG_MIPS_CP0_EPC:
                v = (long)kvm_read_c0_guest_epc(cop0);
                break;
-       case KVM_REG_MIPS_CP0_ERROREPC:
-               v = (long)kvm_read_c0_guest_errorepc(cop0);
+       case KVM_REG_MIPS_CP0_PRID:
+               v = (long)kvm_read_c0_guest_prid(cop0);
                break;
        case KVM_REG_MIPS_CP0_CONFIG:
                v = (long)kvm_read_c0_guest_config(cop0);
@@ -588,9 +661,18 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
        case KVM_REG_MIPS_CP0_CONFIG3:
                v = (long)kvm_read_c0_guest_config3(cop0);
                break;
+       case KVM_REG_MIPS_CP0_CONFIG4:
+               v = (long)kvm_read_c0_guest_config4(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_CONFIG5:
+               v = (long)kvm_read_c0_guest_config5(cop0);
+               break;
        case KVM_REG_MIPS_CP0_CONFIG7:
                v = (long)kvm_read_c0_guest_config7(cop0);
                break;
+       case KVM_REG_MIPS_CP0_ERROREPC:
+               v = (long)kvm_read_c0_guest_errorepc(cop0);
+               break;
        /* registers to be handled specially */
        case KVM_REG_MIPS_CP0_COUNT:
        case KVM_REG_MIPS_COUNT_CTL:
@@ -612,6 +694,10 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
                u32 v32 = (u32)v;
 
                return put_user(v32, uaddr32);
+       } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
+               void __user *uaddr = (void __user *)(long)reg->addr;
+
+               return copy_to_user(uaddr, vs, 16);
        } else {
                return -EINVAL;
        }
@@ -621,7 +707,10 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
                            const struct kvm_one_reg *reg)
 {
        struct mips_coproc *cop0 = vcpu->arch.cop0;
-       u64 v;
+       struct mips_fpu_struct *fpu = &vcpu->arch.fpu;
+       s64 v;
+       s64 vs[2];
+       unsigned int idx;
 
        if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) {
                u64 __user *uaddr64 = (u64 __user *)(long)reg->addr;
@@ -635,11 +724,16 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
                if (get_user(v32, uaddr32) != 0)
                        return -EFAULT;
                v = (s64)v32;
+       } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
+               void __user *uaddr = (void __user *)(long)reg->addr;
+
+               return copy_from_user(vs, uaddr, 16);
        } else {
                return -EINVAL;
        }
 
        switch (reg->id) {
+       /* General purpose registers */
        case KVM_REG_MIPS_R0:
                /* Silently ignore requests to set $0 */
                break;
@@ -656,6 +750,64 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
                vcpu->arch.pc = v;
                break;
 
+       /* Floating point registers */
+       case KVM_REG_MIPS_FPR_32(0) ... KVM_REG_MIPS_FPR_32(31):
+               if (!kvm_mips_guest_has_fpu(&vcpu->arch))
+                       return -EINVAL;
+               idx = reg->id - KVM_REG_MIPS_FPR_32(0);
+               /* Odd singles in top of even double when FR=0 */
+               if (kvm_read_c0_guest_status(cop0) & ST0_FR)
+                       set_fpr32(&fpu->fpr[idx], 0, v);
+               else
+                       set_fpr32(&fpu->fpr[idx & ~1], idx & 1, v);
+               break;
+       case KVM_REG_MIPS_FPR_64(0) ... KVM_REG_MIPS_FPR_64(31):
+               if (!kvm_mips_guest_has_fpu(&vcpu->arch))
+                       return -EINVAL;
+               idx = reg->id - KVM_REG_MIPS_FPR_64(0);
+               /* Can't access odd doubles in FR=0 mode */
+               if (idx & 1 && !(kvm_read_c0_guest_status(cop0) & ST0_FR))
+                       return -EINVAL;
+               set_fpr64(&fpu->fpr[idx], 0, v);
+               break;
+       case KVM_REG_MIPS_FCR_IR:
+               if (!kvm_mips_guest_has_fpu(&vcpu->arch))
+                       return -EINVAL;
+               /* Read-only */
+               break;
+       case KVM_REG_MIPS_FCR_CSR:
+               if (!kvm_mips_guest_has_fpu(&vcpu->arch))
+                       return -EINVAL;
+               fpu->fcr31 = v;
+               break;
+
+       /* MIPS SIMD Architecture (MSA) registers */
+       case KVM_REG_MIPS_VEC_128(0) ... KVM_REG_MIPS_VEC_128(31):
+               if (!kvm_mips_guest_has_msa(&vcpu->arch))
+                       return -EINVAL;
+               idx = reg->id - KVM_REG_MIPS_VEC_128(0);
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+               /* least significant byte first */
+               set_fpr64(&fpu->fpr[idx], 0, vs[0]);
+               set_fpr64(&fpu->fpr[idx], 1, vs[1]);
+#else
+               /* most significant byte first */
+               set_fpr64(&fpu->fpr[idx], 1, vs[0]);
+               set_fpr64(&fpu->fpr[idx], 0, vs[1]);
+#endif
+               break;
+       case KVM_REG_MIPS_MSA_IR:
+               if (!kvm_mips_guest_has_msa(&vcpu->arch))
+                       return -EINVAL;
+               /* Read-only */
+               break;
+       case KVM_REG_MIPS_MSA_CSR:
+               if (!kvm_mips_guest_has_msa(&vcpu->arch))
+                       return -EINVAL;
+               fpu->msacsr = v;
+               break;
+
+       /* Co-processor 0 registers */
        case KVM_REG_MIPS_CP0_INDEX:
                kvm_write_c0_guest_index(cop0, v);
                break;
@@ -686,6 +838,9 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
        case KVM_REG_MIPS_CP0_EPC:
                kvm_write_c0_guest_epc(cop0, v);
                break;
+       case KVM_REG_MIPS_CP0_PRID:
+               kvm_write_c0_guest_prid(cop0, v);
+               break;
        case KVM_REG_MIPS_CP0_ERROREPC:
                kvm_write_c0_guest_errorepc(cop0, v);
                break;
@@ -693,6 +848,12 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
        case KVM_REG_MIPS_CP0_COUNT:
        case KVM_REG_MIPS_CP0_COMPARE:
        case KVM_REG_MIPS_CP0_CAUSE:
+       case KVM_REG_MIPS_CP0_CONFIG:
+       case KVM_REG_MIPS_CP0_CONFIG1:
+       case KVM_REG_MIPS_CP0_CONFIG2:
+       case KVM_REG_MIPS_CP0_CONFIG3:
+       case KVM_REG_MIPS_CP0_CONFIG4:
+       case KVM_REG_MIPS_CP0_CONFIG5:
        case KVM_REG_MIPS_COUNT_CTL:
        case KVM_REG_MIPS_COUNT_RESUME:
        case KVM_REG_MIPS_COUNT_HZ:
@@ -703,6 +864,33 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
+                                    struct kvm_enable_cap *cap)
+{
+       int r = 0;
+
+       if (!kvm_vm_ioctl_check_extension(vcpu->kvm, cap->cap))
+               return -EINVAL;
+       if (cap->flags)
+               return -EINVAL;
+       if (cap->args[0])
+               return -EINVAL;
+
+       switch (cap->cap) {
+       case KVM_CAP_MIPS_FPU:
+               vcpu->arch.fpu_enabled = true;
+               break;
+       case KVM_CAP_MIPS_MSA:
+               vcpu->arch.msa_enabled = true;
+               break;
+       default:
+               r = -EINVAL;
+               break;
+       }
+
+       return r;
+}
+
 long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl,
                         unsigned long arg)
 {
@@ -760,6 +948,15 @@ long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl,
                        r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
                        break;
                }
+       case KVM_ENABLE_CAP: {
+               struct kvm_enable_cap cap;
+
+               r = -EFAULT;
+               if (copy_from_user(&cap, argp, sizeof(cap)))
+                       goto out;
+               r = kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
+               break;
+       }
        default:
                r = -ENOIOCTLCMD;
        }
@@ -868,11 +1065,30 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 
        switch (ext) {
        case KVM_CAP_ONE_REG:
+       case KVM_CAP_ENABLE_CAP:
                r = 1;
                break;
        case KVM_CAP_COALESCED_MMIO:
                r = KVM_COALESCED_MMIO_PAGE_OFFSET;
                break;
+       case KVM_CAP_MIPS_FPU:
+               r = !!cpu_has_fpu;
+               break;
+       case KVM_CAP_MIPS_MSA:
+               /*
+                * We don't support MSA vector partitioning yet:
+                * 1) It would require explicit support which can't be tested
+                *    yet due to lack of support in current hardware.
+                * 2) It extends the state that would need to be saved/restored
+                *    by e.g. QEMU for migration.
+                *
+                * When vector partitioning hardware becomes available, support
+                * could be added by requiring a flag when enabling
+                * KVM_CAP_MIPS_MSA capability to indicate that userland knows
+                * to save/restore the appropriate extra state.
+                */
+               r = cpu_has_msa && !(boot_cpu_data.msa_id & MSA_IR_WRPF);
+               break;
        default:
                r = 0;
                break;
@@ -1119,6 +1335,30 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
                ret = kvm_mips_callbacks->handle_break(vcpu);
                break;
 
+       case T_TRAP:
+               ++vcpu->stat.trap_inst_exits;
+               trace_kvm_exit(vcpu, TRAP_INST_EXITS);
+               ret = kvm_mips_callbacks->handle_trap(vcpu);
+               break;
+
+       case T_MSAFPE:
+               ++vcpu->stat.msa_fpe_exits;
+               trace_kvm_exit(vcpu, MSA_FPE_EXITS);
+               ret = kvm_mips_callbacks->handle_msa_fpe(vcpu);
+               break;
+
+       case T_FPE:
+               ++vcpu->stat.fpe_exits;
+               trace_kvm_exit(vcpu, FPE_EXITS);
+               ret = kvm_mips_callbacks->handle_fpe(vcpu);
+               break;
+
+       case T_MSADIS:
+               ++vcpu->stat.msa_disabled_exits;
+               trace_kvm_exit(vcpu, MSA_DISABLED_EXITS);
+               ret = kvm_mips_callbacks->handle_msa_disabled(vcpu);
+               break;
+
        default:
                kvm_err("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x  BadVaddr: %#lx Status: %#lx\n",
                        exccode, opc, kvm_get_inst(opc, vcpu), badvaddr,
@@ -1146,12 +1386,233 @@ skip_emul:
                }
        }
 
+       if (ret == RESUME_GUEST) {
+               /*
+                * If FPU / MSA are enabled (i.e. the guest's FPU / MSA context
+                * is live), restore FCR31 / MSACSR.
+                *
+                * This should be before returning to the guest exception
+                * vector, as it may well cause an [MSA] FP exception if there
+                * are pending exception bits unmasked. (see
+                * kvm_mips_csr_die_notifier() for how that is handled).
+                */
+               if (kvm_mips_guest_has_fpu(&vcpu->arch) &&
+                   read_c0_status() & ST0_CU1)
+                       __kvm_restore_fcsr(&vcpu->arch);
+
+               if (kvm_mips_guest_has_msa(&vcpu->arch) &&
+                   read_c0_config5() & MIPS_CONF5_MSAEN)
+                       __kvm_restore_msacsr(&vcpu->arch);
+       }
+
        /* Disable HTW before returning to guest or host */
        htw_stop();
 
        return ret;
 }
 
+/* Enable FPU for guest and restore context */
+void kvm_own_fpu(struct kvm_vcpu *vcpu)
+{
+       struct mips_coproc *cop0 = vcpu->arch.cop0;
+       unsigned int sr, cfg5;
+
+       preempt_disable();
+
+       sr = kvm_read_c0_guest_status(cop0);
+
+       /*
+        * If MSA state is already live, it is undefined how it interacts with
+        * FR=0 FPU state, and we don't want to hit reserved instruction
+        * exceptions trying to save the MSA state later when CU=1 && FR=1, so
+        * play it safe and save it first.
+        *
+        * In theory we shouldn't ever hit this case since kvm_lose_fpu() should
+        * get called when guest CU1 is set, however we can't trust the guest
+        * not to clobber the status register directly via the commpage.
+        */
+       if (cpu_has_msa && sr & ST0_CU1 && !(sr & ST0_FR) &&
+           vcpu->arch.fpu_inuse & KVM_MIPS_FPU_MSA)
+               kvm_lose_fpu(vcpu);
+
+       /*
+        * Enable FPU for guest
+        * We set FR and FRE according to guest context
+        */
+       change_c0_status(ST0_CU1 | ST0_FR, sr);
+       if (cpu_has_fre) {
+               cfg5 = kvm_read_c0_guest_config5(cop0);
+               change_c0_config5(MIPS_CONF5_FRE, cfg5);
+       }
+       enable_fpu_hazard();
+
+       /* If guest FPU state not active, restore it now */
+       if (!(vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU)) {
+               __kvm_restore_fpu(&vcpu->arch);
+               vcpu->arch.fpu_inuse |= KVM_MIPS_FPU_FPU;
+       }
+
+       preempt_enable();
+}
+
+#ifdef CONFIG_CPU_HAS_MSA
+/* Enable MSA for guest and restore context */
+void kvm_own_msa(struct kvm_vcpu *vcpu)
+{
+       struct mips_coproc *cop0 = vcpu->arch.cop0;
+       unsigned int sr, cfg5;
+
+       preempt_disable();
+
+       /*
+        * Enable FPU if enabled in guest, since we're restoring FPU context
+        * anyway. We set FR and FRE according to guest context.
+        */
+       if (kvm_mips_guest_has_fpu(&vcpu->arch)) {
+               sr = kvm_read_c0_guest_status(cop0);
+
+               /*
+                * If FR=0 FPU state is already live, it is undefined how it
+                * interacts with MSA state, so play it safe and save it first.
+                */
+               if (!(sr & ST0_FR) &&
+                   (vcpu->arch.fpu_inuse & (KVM_MIPS_FPU_FPU |
+                               KVM_MIPS_FPU_MSA)) == KVM_MIPS_FPU_FPU)
+                       kvm_lose_fpu(vcpu);
+
+               change_c0_status(ST0_CU1 | ST0_FR, sr);
+               if (sr & ST0_CU1 && cpu_has_fre) {
+                       cfg5 = kvm_read_c0_guest_config5(cop0);
+                       change_c0_config5(MIPS_CONF5_FRE, cfg5);
+               }
+       }
+
+       /* Enable MSA for guest */
+       set_c0_config5(MIPS_CONF5_MSAEN);
+       enable_fpu_hazard();
+
+       switch (vcpu->arch.fpu_inuse & (KVM_MIPS_FPU_FPU | KVM_MIPS_FPU_MSA)) {
+       case KVM_MIPS_FPU_FPU:
+               /*
+                * Guest FPU state already loaded, only restore upper MSA state
+                */
+               __kvm_restore_msa_upper(&vcpu->arch);
+               vcpu->arch.fpu_inuse |= KVM_MIPS_FPU_MSA;
+               break;
+       case 0:
+               /* Neither FPU or MSA already active, restore full MSA state */
+               __kvm_restore_msa(&vcpu->arch);
+               vcpu->arch.fpu_inuse |= KVM_MIPS_FPU_MSA;
+               if (kvm_mips_guest_has_fpu(&vcpu->arch))
+                       vcpu->arch.fpu_inuse |= KVM_MIPS_FPU_FPU;
+               break;
+       default:
+               break;
+       }
+
+       preempt_enable();
+}
+#endif
+
+/* Drop FPU & MSA without saving it */
+void kvm_drop_fpu(struct kvm_vcpu *vcpu)
+{
+       preempt_disable();
+       if (cpu_has_msa && vcpu->arch.fpu_inuse & KVM_MIPS_FPU_MSA) {
+               disable_msa();
+               vcpu->arch.fpu_inuse &= ~KVM_MIPS_FPU_MSA;
+       }
+       if (vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU) {
+               clear_c0_status(ST0_CU1 | ST0_FR);
+               vcpu->arch.fpu_inuse &= ~KVM_MIPS_FPU_FPU;
+       }
+       preempt_enable();
+}
+
+/* Save and disable FPU & MSA */
+void kvm_lose_fpu(struct kvm_vcpu *vcpu)
+{
+       /*
+        * FPU & MSA get disabled in root context (hardware) when it is disabled
+        * in guest context (software), but the register state in the hardware
+        * may still be in use. This is why we explicitly re-enable the hardware
+        * before saving.
+        */
+
+       preempt_disable();
+       if (cpu_has_msa && vcpu->arch.fpu_inuse & KVM_MIPS_FPU_MSA) {
+               set_c0_config5(MIPS_CONF5_MSAEN);
+               enable_fpu_hazard();
+
+               __kvm_save_msa(&vcpu->arch);
+
+               /* Disable MSA & FPU */
+               disable_msa();
+               if (vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU)
+                       clear_c0_status(ST0_CU1 | ST0_FR);
+               vcpu->arch.fpu_inuse &= ~(KVM_MIPS_FPU_FPU | KVM_MIPS_FPU_MSA);
+       } else if (vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU) {
+               set_c0_status(ST0_CU1);
+               enable_fpu_hazard();
+
+               __kvm_save_fpu(&vcpu->arch);
+               vcpu->arch.fpu_inuse &= ~KVM_MIPS_FPU_FPU;
+
+               /* Disable FPU */
+               clear_c0_status(ST0_CU1 | ST0_FR);
+       }
+       preempt_enable();
+}
+
+/*
+ * Step over a specific ctc1 to FCSR and a specific ctcmsa to MSACSR which are
+ * used to restore guest FCSR/MSACSR state and may trigger a "harmless" FP/MSAFP
+ * exception if cause bits are set in the value being written.
+ */
+static int kvm_mips_csr_die_notify(struct notifier_block *self,
+                                  unsigned long cmd, void *ptr)
+{
+       struct die_args *args = (struct die_args *)ptr;
+       struct pt_regs *regs = args->regs;
+       unsigned long pc;
+
+       /* Only interested in FPE and MSAFPE */
+       if (cmd != DIE_FP && cmd != DIE_MSAFP)
+               return NOTIFY_DONE;
+
+       /* Return immediately if guest context isn't active */
+       if (!(current->flags & PF_VCPU))
+               return NOTIFY_DONE;
+
+       /* Should never get here from user mode */
+       BUG_ON(user_mode(regs));
+
+       pc = instruction_pointer(regs);
+       switch (cmd) {
+       case DIE_FP:
+               /* match 2nd instruction in __kvm_restore_fcsr */
+               if (pc != (unsigned long)&__kvm_restore_fcsr + 4)
+                       return NOTIFY_DONE;
+               break;
+       case DIE_MSAFP:
+               /* match 2nd/3rd instruction in __kvm_restore_msacsr */
+               if (!cpu_has_msa ||
+                   pc < (unsigned long)&__kvm_restore_msacsr + 4 ||
+                   pc > (unsigned long)&__kvm_restore_msacsr + 8)
+                       return NOTIFY_DONE;
+               break;
+       }
+
+       /* Move PC forward a little and continue executing */
+       instruction_pointer(regs) += 4;
+
+       return NOTIFY_STOP;
+}
+
+static struct notifier_block kvm_mips_csr_die_notifier = {
+       .notifier_call = kvm_mips_csr_die_notify,
+};
+
 int __init kvm_mips_init(void)
 {
        int ret;
@@ -1161,6 +1622,8 @@ int __init kvm_mips_init(void)
        if (ret)
                return ret;
 
+       register_die_notifier(&kvm_mips_csr_die_notifier);
+
        /*
         * On MIPS, kernel modules are executed from "mapped space", which
         * requires TLBs. The TLB handling code is statically linked with
@@ -1173,7 +1636,6 @@ int __init kvm_mips_init(void)
        kvm_mips_release_pfn_clean = kvm_release_pfn_clean;
        kvm_mips_is_error_pfn = is_error_pfn;
 
-       pr_info("KVM/MIPS Initialized\n");
        return 0;
 }
 
@@ -1185,7 +1647,7 @@ void __exit kvm_mips_exit(void)
        kvm_mips_release_pfn_clean = NULL;
        kvm_mips_is_error_pfn = NULL;
 
-       pr_info("KVM/MIPS unloaded\n");
+       unregister_die_notifier(&kvm_mips_csr_die_notifier);
 }
 
 module_init(kvm_mips_init);
diff --git a/arch/mips/kvm/msa.S b/arch/mips/kvm/msa.S
new file mode 100644 (file)
index 0000000..d02f0c6
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ *
+ * MIPS SIMD Architecture (MSA) context handling code for KVM.
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ */
+
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/asmmacro.h>
+#include <asm/regdef.h>
+
+       .set    noreorder
+       .set    noat
+
+LEAF(__kvm_save_msa)
+       st_d    0,  VCPU_FPR0,  a0
+       st_d    1,  VCPU_FPR1,  a0
+       st_d    2,  VCPU_FPR2,  a0
+       st_d    3,  VCPU_FPR3,  a0
+       st_d    4,  VCPU_FPR4,  a0
+       st_d    5,  VCPU_FPR5,  a0
+       st_d    6,  VCPU_FPR6,  a0
+       st_d    7,  VCPU_FPR7,  a0
+       st_d    8,  VCPU_FPR8,  a0
+       st_d    9,  VCPU_FPR9,  a0
+       st_d    10, VCPU_FPR10, a0
+       st_d    11, VCPU_FPR11, a0
+       st_d    12, VCPU_FPR12, a0
+       st_d    13, VCPU_FPR13, a0
+       st_d    14, VCPU_FPR14, a0
+       st_d    15, VCPU_FPR15, a0
+       st_d    16, VCPU_FPR16, a0
+       st_d    17, VCPU_FPR17, a0
+       st_d    18, VCPU_FPR18, a0
+       st_d    19, VCPU_FPR19, a0
+       st_d    20, VCPU_FPR20, a0
+       st_d    21, VCPU_FPR21, a0
+       st_d    22, VCPU_FPR22, a0
+       st_d    23, VCPU_FPR23, a0
+       st_d    24, VCPU_FPR24, a0
+       st_d    25, VCPU_FPR25, a0
+       st_d    26, VCPU_FPR26, a0
+       st_d    27, VCPU_FPR27, a0
+       st_d    28, VCPU_FPR28, a0
+       st_d    29, VCPU_FPR29, a0
+       st_d    30, VCPU_FPR30, a0
+       st_d    31, VCPU_FPR31, a0
+       jr      ra
+        nop
+       END(__kvm_save_msa)
+
+LEAF(__kvm_restore_msa)
+       ld_d    0,  VCPU_FPR0,  a0
+       ld_d    1,  VCPU_FPR1,  a0
+       ld_d    2,  VCPU_FPR2,  a0
+       ld_d    3,  VCPU_FPR3,  a0
+       ld_d    4,  VCPU_FPR4,  a0
+       ld_d    5,  VCPU_FPR5,  a0
+       ld_d    6,  VCPU_FPR6,  a0
+       ld_d    7,  VCPU_FPR7,  a0
+       ld_d    8,  VCPU_FPR8,  a0
+       ld_d    9,  VCPU_FPR9,  a0
+       ld_d    10, VCPU_FPR10, a0
+       ld_d    11, VCPU_FPR11, a0
+       ld_d    12, VCPU_FPR12, a0
+       ld_d    13, VCPU_FPR13, a0
+       ld_d    14, VCPU_FPR14, a0
+       ld_d    15, VCPU_FPR15, a0
+       ld_d    16, VCPU_FPR16, a0
+       ld_d    17, VCPU_FPR17, a0
+       ld_d    18, VCPU_FPR18, a0
+       ld_d    19, VCPU_FPR19, a0
+       ld_d    20, VCPU_FPR20, a0
+       ld_d    21, VCPU_FPR21, a0
+       ld_d    22, VCPU_FPR22, a0
+       ld_d    23, VCPU_FPR23, a0
+       ld_d    24, VCPU_FPR24, a0
+       ld_d    25, VCPU_FPR25, a0
+       ld_d    26, VCPU_FPR26, a0
+       ld_d    27, VCPU_FPR27, a0
+       ld_d    28, VCPU_FPR28, a0
+       ld_d    29, VCPU_FPR29, a0
+       ld_d    30, VCPU_FPR30, a0
+       ld_d    31, VCPU_FPR31, a0
+       jr      ra
+        nop
+       END(__kvm_restore_msa)
+
+       .macro  kvm_restore_msa_upper   wr, off, base
+       .set    push
+       .set    noat
+#ifdef CONFIG_64BIT
+       ld      $1, \off(\base)
+       insert_d \wr, 1
+#elif defined(CONFIG_CPU_LITTLE_ENDIAN)
+       lw      $1, \off(\base)
+       insert_w \wr, 2
+       lw      $1, (\off+4)(\base)
+       insert_w \wr, 3
+#else /* CONFIG_CPU_BIG_ENDIAN */
+       lw      $1, (\off+4)(\base)
+       insert_w \wr, 2
+       lw      $1, \off(\base)
+       insert_w \wr, 3
+#endif
+       .set    pop
+       .endm
+
+LEAF(__kvm_restore_msa_upper)
+       kvm_restore_msa_upper   0,  VCPU_FPR0 +8, a0
+       kvm_restore_msa_upper   1,  VCPU_FPR1 +8, a0
+       kvm_restore_msa_upper   2,  VCPU_FPR2 +8, a0
+       kvm_restore_msa_upper   3,  VCPU_FPR3 +8, a0
+       kvm_restore_msa_upper   4,  VCPU_FPR4 +8, a0
+       kvm_restore_msa_upper   5,  VCPU_FPR5 +8, a0
+       kvm_restore_msa_upper   6,  VCPU_FPR6 +8, a0
+       kvm_restore_msa_upper   7,  VCPU_FPR7 +8, a0
+       kvm_restore_msa_upper   8,  VCPU_FPR8 +8, a0
+       kvm_restore_msa_upper   9,  VCPU_FPR9 +8, a0
+       kvm_restore_msa_upper   10, VCPU_FPR10+8, a0
+       kvm_restore_msa_upper   11, VCPU_FPR11+8, a0
+       kvm_restore_msa_upper   12, VCPU_FPR12+8, a0
+       kvm_restore_msa_upper   13, VCPU_FPR13+8, a0
+       kvm_restore_msa_upper   14, VCPU_FPR14+8, a0
+       kvm_restore_msa_upper   15, VCPU_FPR15+8, a0
+       kvm_restore_msa_upper   16, VCPU_FPR16+8, a0
+       kvm_restore_msa_upper   17, VCPU_FPR17+8, a0
+       kvm_restore_msa_upper   18, VCPU_FPR18+8, a0
+       kvm_restore_msa_upper   19, VCPU_FPR19+8, a0
+       kvm_restore_msa_upper   20, VCPU_FPR20+8, a0
+       kvm_restore_msa_upper   21, VCPU_FPR21+8, a0
+       kvm_restore_msa_upper   22, VCPU_FPR22+8, a0
+       kvm_restore_msa_upper   23, VCPU_FPR23+8, a0
+       kvm_restore_msa_upper   24, VCPU_FPR24+8, a0
+       kvm_restore_msa_upper   25, VCPU_FPR25+8, a0
+       kvm_restore_msa_upper   26, VCPU_FPR26+8, a0
+       kvm_restore_msa_upper   27, VCPU_FPR27+8, a0
+       kvm_restore_msa_upper   28, VCPU_FPR28+8, a0
+       kvm_restore_msa_upper   29, VCPU_FPR29+8, a0
+       kvm_restore_msa_upper   30, VCPU_FPR30+8, a0
+       kvm_restore_msa_upper   31, VCPU_FPR31+8, a0
+       jr      ra
+        nop
+       END(__kvm_restore_msa_upper)
+
+LEAF(__kvm_restore_msacsr)
+       lw      t0, VCPU_MSA_CSR(a0)
+       /*
+        * The ctcmsa must stay at this offset in __kvm_restore_msacsr.
+        * See kvm_mips_csr_die_notify() which handles t0 containing a value
+        * which triggers an MSA FP Exception, which must be stepped over and
+        * ignored since the set cause bits must remain there for the guest.
+        */
+       _ctcmsa MSA_CSR, t0
+       jr      ra
+        nop
+       END(__kvm_restore_msacsr)
index a74d6024c5ad5f5c7e0701a309e246bd42532992..888bb67070ac6d1139a7f06f5958e180680511ef 100644 (file)
@@ -25,6 +25,10 @@ char *kvm_mips_exit_types_str[MAX_KVM_MIPS_EXIT_TYPES] = {
        "System Call",
        "Reserved Inst",
        "Break Inst",
+       "Trap Inst",
+       "MSA FPE",
+       "FPE",
+       "MSA Disabled",
        "D-Cache Flushes",
 };
 
index b6beb0e07b1b3b535f7625d61100e6c0087de00d..aed0ac2a4972cd1daf0f2992db6c100e9912fb70 100644 (file)
@@ -733,6 +733,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
                }
        }
 
+       /* restore guest state to registers */
+       kvm_mips_callbacks->vcpu_set_regs(vcpu);
+
        local_irq_restore(flags);
 
 }
@@ -751,6 +754,9 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
        vcpu->arch.preempt_entryhi = read_c0_entryhi();
        vcpu->arch.last_sched_cpu = cpu;
 
+       /* save guest state in registers */
+       kvm_mips_callbacks->vcpu_get_regs(vcpu);
+
        if (((cpu_context(cpu, current->mm) ^ asid_cache(cpu)) &
             ASID_VERSION_MASK)) {
                kvm_debug("%s: Dropping MMU Context:  %#lx\n", __func__,
index fd7257b70e656fcb8c53d72b552f240f5b255ce6..d836ed5b0bc7ea38e36350304a6238a520e0d74d 100644 (file)
@@ -39,16 +39,30 @@ static gpa_t kvm_trap_emul_gva_to_gpa_cb(gva_t gva)
 
 static int kvm_trap_emul_handle_cop_unusable(struct kvm_vcpu *vcpu)
 {
+       struct mips_coproc *cop0 = vcpu->arch.cop0;
        struct kvm_run *run = vcpu->run;
        uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
        unsigned long cause = vcpu->arch.host_cp0_cause;
        enum emulation_result er = EMULATE_DONE;
        int ret = RESUME_GUEST;
 
-       if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 1)
-               er = kvm_mips_emulate_fpu_exc(cause, opc, run, vcpu);
-       else
+       if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 1) {
+               /* FPU Unusable */
+               if (!kvm_mips_guest_has_fpu(&vcpu->arch) ||
+                   (kvm_read_c0_guest_status(cop0) & ST0_CU1) == 0) {
+                       /*
+                        * Unusable/no FPU in guest:
+                        * deliver guest COP1 Unusable Exception
+                        */
+                       er = kvm_mips_emulate_fpu_exc(cause, opc, run, vcpu);
+               } else {
+                       /* Restore FPU state */
+                       kvm_own_fpu(vcpu);
+                       er = EMULATE_DONE;
+               }
+       } else {
                er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
+       }
 
        switch (er) {
        case EMULATE_DONE:
@@ -330,6 +344,107 @@ static int kvm_trap_emul_handle_break(struct kvm_vcpu *vcpu)
        return ret;
 }
 
+static int kvm_trap_emul_handle_trap(struct kvm_vcpu *vcpu)
+{
+       struct kvm_run *run = vcpu->run;
+       uint32_t __user *opc = (uint32_t __user *)vcpu->arch.pc;
+       unsigned long cause = vcpu->arch.host_cp0_cause;
+       enum emulation_result er = EMULATE_DONE;
+       int ret = RESUME_GUEST;
+
+       er = kvm_mips_emulate_trap_exc(cause, opc, run, vcpu);
+       if (er == EMULATE_DONE) {
+               ret = RESUME_GUEST;
+       } else {
+               run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+               ret = RESUME_HOST;
+       }
+       return ret;
+}
+
+static int kvm_trap_emul_handle_msa_fpe(struct kvm_vcpu *vcpu)
+{
+       struct kvm_run *run = vcpu->run;
+       uint32_t __user *opc = (uint32_t __user *)vcpu->arch.pc;
+       unsigned long cause = vcpu->arch.host_cp0_cause;
+       enum emulation_result er = EMULATE_DONE;
+       int ret = RESUME_GUEST;
+
+       er = kvm_mips_emulate_msafpe_exc(cause, opc, run, vcpu);
+       if (er == EMULATE_DONE) {
+               ret = RESUME_GUEST;
+       } else {
+               run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+               ret = RESUME_HOST;
+       }
+       return ret;
+}
+
+static int kvm_trap_emul_handle_fpe(struct kvm_vcpu *vcpu)
+{
+       struct kvm_run *run = vcpu->run;
+       uint32_t __user *opc = (uint32_t __user *)vcpu->arch.pc;
+       unsigned long cause = vcpu->arch.host_cp0_cause;
+       enum emulation_result er = EMULATE_DONE;
+       int ret = RESUME_GUEST;
+
+       er = kvm_mips_emulate_fpe_exc(cause, opc, run, vcpu);
+       if (er == EMULATE_DONE) {
+               ret = RESUME_GUEST;
+       } else {
+               run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+               ret = RESUME_HOST;
+       }
+       return ret;
+}
+
+/**
+ * kvm_trap_emul_handle_msa_disabled() - Guest used MSA while disabled in root.
+ * @vcpu:      Virtual CPU context.
+ *
+ * Handle when the guest attempts to use MSA when it is disabled.
+ */
+static int kvm_trap_emul_handle_msa_disabled(struct kvm_vcpu *vcpu)
+{
+       struct mips_coproc *cop0 = vcpu->arch.cop0;
+       struct kvm_run *run = vcpu->run;
+       uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
+       unsigned long cause = vcpu->arch.host_cp0_cause;
+       enum emulation_result er = EMULATE_DONE;
+       int ret = RESUME_GUEST;
+
+       if (!kvm_mips_guest_has_msa(&vcpu->arch) ||
+           (kvm_read_c0_guest_status(cop0) & (ST0_CU1 | ST0_FR)) == ST0_CU1) {
+               /*
+                * No MSA in guest, or FPU enabled and not in FR=1 mode,
+                * guest reserved instruction exception
+                */
+               er = kvm_mips_emulate_ri_exc(cause, opc, run, vcpu);
+       } else if (!(kvm_read_c0_guest_config5(cop0) & MIPS_CONF5_MSAEN)) {
+               /* MSA disabled by guest, guest MSA disabled exception */
+               er = kvm_mips_emulate_msadis_exc(cause, opc, run, vcpu);
+       } else {
+               /* Restore MSA/FPU state */
+               kvm_own_msa(vcpu);
+               er = EMULATE_DONE;
+       }
+
+       switch (er) {
+       case EMULATE_DONE:
+               ret = RESUME_GUEST;
+               break;
+
+       case EMULATE_FAIL:
+               run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+               ret = RESUME_HOST;
+               break;
+
+       default:
+               BUG();
+       }
+       return ret;
+}
+
 static int kvm_trap_emul_vm_init(struct kvm *kvm)
 {
        return 0;
@@ -351,8 +466,9 @@ static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu)
         * guest will come up as expected, for now we simulate a MIPS 24kc
         */
        kvm_write_c0_guest_prid(cop0, 0x00019300);
-       kvm_write_c0_guest_config(cop0,
-                                 MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
+       /* Have config1, Cacheable, noncoherent, write-back, write allocate */
+       kvm_write_c0_guest_config(cop0, MIPS_CONF_M | (0x3 << CP0C0_K0) |
+                                 (0x1 << CP0C0_AR) |
                                  (MMU_TYPE_R4000 << CP0C0_MT));
 
        /* Read the cache characteristics from the host Config1 Register */
@@ -368,10 +484,18 @@ static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu)
              (1 << CP0C1_WR) | (1 << CP0C1_CA));
        kvm_write_c0_guest_config1(cop0, config1);
 
-       kvm_write_c0_guest_config2(cop0, MIPS_CONFIG2);
-       /* MIPS_CONFIG2 | (read_c0_config2() & 0xfff) */
-       kvm_write_c0_guest_config3(cop0, MIPS_CONFIG3 | (0 << CP0C3_VInt) |
-                                        (1 << CP0C3_ULRI));
+       /* Have config3, no tertiary/secondary caches implemented */
+       kvm_write_c0_guest_config2(cop0, MIPS_CONF_M);
+       /* MIPS_CONF_M | (read_c0_config2() & 0xfff) */
+
+       /* Have config4, UserLocal */
+       kvm_write_c0_guest_config3(cop0, MIPS_CONF_M | MIPS_CONF3_ULRI);
+
+       /* Have config5 */
+       kvm_write_c0_guest_config4(cop0, MIPS_CONF_M);
+
+       /* No config6 */
+       kvm_write_c0_guest_config5(cop0, 0);
 
        /* Set Wait IE/IXMT Ignore in Config7, IAR, AR */
        kvm_write_c0_guest_config7(cop0, (MIPS_CONF7_WII) | (1 << 10));
@@ -416,6 +540,7 @@ static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu,
 {
        struct mips_coproc *cop0 = vcpu->arch.cop0;
        int ret = 0;
+       unsigned int cur, change;
 
        switch (reg->id) {
        case KVM_REG_MIPS_CP0_COUNT:
@@ -444,6 +569,44 @@ static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu,
                        kvm_write_c0_guest_cause(cop0, v);
                }
                break;
+       case KVM_REG_MIPS_CP0_CONFIG:
+               /* read-only for now */
+               break;
+       case KVM_REG_MIPS_CP0_CONFIG1:
+               cur = kvm_read_c0_guest_config1(cop0);
+               change = (cur ^ v) & kvm_mips_config1_wrmask(vcpu);
+               if (change) {
+                       v = cur ^ change;
+                       kvm_write_c0_guest_config1(cop0, v);
+               }
+               break;
+       case KVM_REG_MIPS_CP0_CONFIG2:
+               /* read-only for now */
+               break;
+       case KVM_REG_MIPS_CP0_CONFIG3:
+               cur = kvm_read_c0_guest_config3(cop0);
+               change = (cur ^ v) & kvm_mips_config3_wrmask(vcpu);
+               if (change) {
+                       v = cur ^ change;
+                       kvm_write_c0_guest_config3(cop0, v);
+               }
+               break;
+       case KVM_REG_MIPS_CP0_CONFIG4:
+               cur = kvm_read_c0_guest_config4(cop0);
+               change = (cur ^ v) & kvm_mips_config4_wrmask(vcpu);
+               if (change) {
+                       v = cur ^ change;
+                       kvm_write_c0_guest_config4(cop0, v);
+               }
+               break;
+       case KVM_REG_MIPS_CP0_CONFIG5:
+               cur = kvm_read_c0_guest_config5(cop0);
+               change = (cur ^ v) & kvm_mips_config5_wrmask(vcpu);
+               if (change) {
+                       v = cur ^ change;
+                       kvm_write_c0_guest_config5(cop0, v);
+               }
+               break;
        case KVM_REG_MIPS_COUNT_CTL:
                ret = kvm_mips_set_count_ctl(vcpu, v);
                break;
@@ -459,6 +622,18 @@ static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu,
        return ret;
 }
 
+static int kvm_trap_emul_vcpu_get_regs(struct kvm_vcpu *vcpu)
+{
+       kvm_lose_fpu(vcpu);
+
+       return 0;
+}
+
+static int kvm_trap_emul_vcpu_set_regs(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
 static struct kvm_mips_callbacks kvm_trap_emul_callbacks = {
        /* exit handlers */
        .handle_cop_unusable = kvm_trap_emul_handle_cop_unusable,
@@ -470,6 +645,10 @@ static struct kvm_mips_callbacks kvm_trap_emul_callbacks = {
        .handle_syscall = kvm_trap_emul_handle_syscall,
        .handle_res_inst = kvm_trap_emul_handle_res_inst,
        .handle_break = kvm_trap_emul_handle_break,
+       .handle_trap = kvm_trap_emul_handle_trap,
+       .handle_msa_fpe = kvm_trap_emul_handle_msa_fpe,
+       .handle_fpe = kvm_trap_emul_handle_fpe,
+       .handle_msa_disabled = kvm_trap_emul_handle_msa_disabled,
 
        .vm_init = kvm_trap_emul_vm_init,
        .vcpu_init = kvm_trap_emul_vcpu_init,
@@ -483,6 +662,8 @@ static struct kvm_mips_callbacks kvm_trap_emul_callbacks = {
        .irq_clear = kvm_mips_irq_clear_cb,
        .get_one_reg = kvm_trap_emul_get_one_reg,
        .set_one_reg = kvm_trap_emul_set_one_reg,
+       .vcpu_get_regs = kvm_trap_emul_vcpu_get_regs,
+       .vcpu_set_regs = kvm_trap_emul_vcpu_set_regs,
 };
 
 int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks)
index 3b7f65cc42187e95627bdd14b461be0e60e7342b..cf9b4633257eb86dd14cea3656b94104ce8d909a 100644 (file)
@@ -75,11 +75,11 @@ static int rtctmp;
 int proc_dolasatrtc(struct ctl_table *table, int write,
                       void *buffer, size_t *lenp, loff_t *ppos)
 {
-       struct timespec ts;
+       struct timespec64 ts;
        int r;
 
        if (!write) {
-               read_persistent_clock(&ts);
+               read_persistent_clock64(&ts);
                rtctmp = ts.tv_sec;
                /* check for time < 0 and set to 0 */
                if (rtctmp < 0)
index e898d68668a95de5bcc645c0ccb322ef1c59117d..5c21cd3bd339ab253c8b9a956de7bd20534e00f5 100644 (file)
@@ -162,7 +162,7 @@ static irqreturn_t hpet_irq_handler(int irq, void *data)
 
 static struct irqaction hpet_irq = {
        .handler = hpet_irq_handler,
-       .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER,
+       .flags = IRQF_NOBALANCING | IRQF_TIMER,
        .name = "hpet",
 };
 
index f1baadd56e82e2b0b4f2b79bd82686ea61a112d0..5c81fdd032c3b1269549f27e27348e9606eb5424 100644 (file)
@@ -142,18 +142,26 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
                        addr0, len, pgoff, flags, DOWN);
 }
 
+unsigned long arch_mmap_rnd(void)
+{
+       unsigned long rnd;
+
+       rnd = (unsigned long)get_random_int();
+       rnd <<= PAGE_SHIFT;
+       if (TASK_IS_32BIT_ADDR)
+               rnd &= 0xfffffful;
+       else
+               rnd &= 0xffffffful;
+
+       return rnd;
+}
+
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
        unsigned long random_factor = 0UL;
 
-       if (current->flags & PF_RANDOMIZE) {
-               random_factor = get_random_int();
-               random_factor = random_factor << PAGE_SHIFT;
-               if (TASK_IS_32BIT_ADDR)
-                       random_factor &= 0xfffffful;
-               else
-                       random_factor &= 0xffffffful;
-       }
+       if (current->flags & PF_RANDOMIZE)
+               random_factor = arch_mmap_rnd();
 
        if (mmap_is_legacy()) {
                mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
index 1bf60b12737746d19cfec9c8b0512e6c419a2a5c..8bb13a4af68a097057f55d9379961a6f0319a4e4 100644 (file)
@@ -94,27 +94,29 @@ static void pcibios_scanbus(struct pci_controller *hose)
        pci_add_resource_offset(&resources, hose->io_resource, hose->io_offset);
        bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose,
                                &resources);
-       if (!bus)
-               pci_free_resource_list(&resources);
-
        hose->bus = bus;
 
        need_domain_info = need_domain_info || hose->index;
        hose->need_domain_info = need_domain_info;
-       if (bus) {
-               next_busno = bus->busn_res.end + 1;
-               /* Don't allow 8-bit bus number overflow inside the hose -
-                  reserve some space for bridges. */
-               if (next_busno > 224) {
-                       next_busno = 0;
-                       need_domain_info = 1;
-               }
 
-               if (!pci_has_flag(PCI_PROBE_ONLY)) {
-                       pci_bus_size_bridges(bus);
-                       pci_bus_assign_resources(bus);
-               }
+       if (!bus) {
+               pci_free_resource_list(&resources);
+               return;
+       }
+
+       next_busno = bus->busn_res.end + 1;
+       /* Don't allow 8-bit bus number overflow inside the hose -
+          reserve some space for bridges. */
+       if (next_busno > 224) {
+               next_busno = 0;
+               need_domain_info = 1;
+       }
+
+       if (!pci_has_flag(PCI_PROBE_ONLY)) {
+               pci_bus_size_bridges(bus);
+               pci_bus_assign_resources(bus);
        }
+       pci_bus_add_devices(bus);
 }
 
 #ifdef CONFIG_OF
index 613ca1e55b4b7d972843484e8fd9b0fda469b487..3dfe2d31c67b20971701cac89565af0531dec878 100644 (file)
@@ -342,6 +342,7 @@ static int __init pcibios_init(void)
 {
        resource_size_t io_offset, mem_offset;
        LIST_HEAD(resources);
+       struct pci_bus *bus;
 
        ioport_resource.start   = 0xA0000000;
        ioport_resource.end     = 0xDFFFFFFF;
@@ -371,11 +372,14 @@ static int __init pcibios_init(void)
 
        pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset);
        pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset);
-       pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources);
+       bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources);
+       if (!bus)
+               return 0;
 
        pcibios_irq_init();
        pcibios_fixup_irqs();
        pcibios_resource_survey();
+       pci_bus_add_devices(bus);
        return 0;
 }
 
index 1f266575beb51c459432ac918e96e0b3b810ae85..a16e55cbd8ad99dce9f448d14c3a4ddeb20b8e42 100644 (file)
@@ -47,7 +47,6 @@ struct thread_info {
                                                  0-0x7FFFFFFF for user-thead
                                                  0-0xFFFFFFFF for kernel-thread
                                                */
-       struct restart_block    restart_block;
        struct pt_regs          *regs;
 };
 
@@ -64,9 +63,6 @@ struct thread_info {
        .cpu            = 0,                    \
        .preempt_count  = INIT_PREEMPT_COUNT,   \
        .addr_limit     = KERNEL_DS,            \
-       .restart_block  = {                     \
-               .fn = do_no_restart_syscall,    \
-       },                                      \
 }
 
 #define init_thread_info       (init_thread_union.thread_info)
index 71a330597adff689dcae092d63839aad1fb8b7d3..eff00e67c0a245f5208ece2f662f9055f328f3c6 100644 (file)
 #define PTR_IPENDING   37
 #define PTR_CPUID      38
 #define PTR_CTL6       39
-#define PTR_CTL7       40
+#define PTR_EXCEPTION  40
 #define PTR_PTEADDR    41
 #define PTR_TLBACC     42
 #define PTR_TLBMISC    43
+#define PTR_ECCINJ     44
+#define PTR_BADADDR    45
+#define PTR_CONFIG     46
+#define PTR_MPUBASE    47
+#define PTR_MPUACC     48
 
-#define NUM_PTRACE_REG (PTR_TLBMISC + 1)
+#define NUM_PTRACE_REG (PTR_MPUACC + 1)
 
 /* User structures for general purpose registers.  */
 struct user_pt_regs {
index 7729bd3f2e79d48937e7dbead303640610ca24ae..27b006c52e12e1193fd392033f5804c1c42c56da 100644 (file)
@@ -161,7 +161,7 @@ ENTRY(inthandler)
  ***********************************************************************
  */
 ENTRY(handle_trap)
-       ldw     r24, -4(ea)     /* instruction that caused the exception */
+       ldwio   r24, -4(ea)     /* instruction that caused the exception */
        srli    r24, r24, 4
        andi    r24, r24, 0x7c
        movia   r9,trap_table
index 0e075b5ad2a54298c99ea668848b523c12449b15..2f8c74f93e705a08e28f2c7a9e6ba9da754ff187 100644 (file)
@@ -94,7 +94,6 @@ void show_regs(struct pt_regs *regs)
 
 void flush_thread(void)
 {
-       set_fs(USER_DS);
 }
 
 int copy_thread(unsigned long clone_flags,
index dda41e4fe7070885ee7ab77e4c5e9e18e51dd0a3..20662b0f6c9e30cd52279ce3274bcbc463fa5236 100644 (file)
@@ -43,7 +43,7 @@ static inline int rt_restore_ucontext(struct pt_regs *regs,
        int err;
 
        /* Always make any pending restarted system calls return -EINTR */
-       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+       current->restart_block.fn = do_no_restart_syscall;
 
        err = __get_user(temp, &uc->uc_mcontext.version);
        if (temp != MCONTEXT_VERSION)
index 2ae482b4266931cbcdd28267630b4f7bd2f56074..796642932e2ef446a9e78b72e7fecccc4ed14647 100644 (file)
@@ -23,9 +23,6 @@ static void __flush_dcache(unsigned long start, unsigned long end)
        end += (cpuinfo.dcache_line_size - 1);
        end &= ~(cpuinfo.dcache_line_size - 1);
 
-       if (end > start + cpuinfo.dcache_size)
-               end = start + cpuinfo.dcache_size;
-
        for (addr = start; addr < end; addr += cpuinfo.dcache_line_size) {
                __asm__ __volatile__ ("   flushda 0(%0)\n"
                                        : /* Outputs */
index 386af258591dbe7084867f88b79c3eef980ce15b..7095dfe7666ba3dd55a0807ffd7d09b00af3ccc2 100644 (file)
@@ -197,7 +197,6 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
 {
        unsigned long sr = mfspr(SPR_SR) & ~SPR_SR_SM;
 
-       set_fs(USER_DS);
        memset(regs, 0, sizeof(struct pt_regs));
 
        regs->pc = pc;
index 8014727a27434724d8a9efed4b693c09a93791b3..c36546959e86ff96f4b0a656d1562ee85e729904 100644 (file)
@@ -103,6 +103,11 @@ config ARCH_MAY_HAVE_PC_FDC
        depends on BROKEN
        default y
 
+config PGTABLE_LEVELS
+       int
+       default 3 if 64BIT && PARISC_PAGE_SIZE_4KB
+       default 2
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
index d17437238a2cef75dd4d46593c760320933b6d38..1ba29369257c1234585a23b8a290e9f788ab52ec 100644 (file)
@@ -51,7 +51,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
        free_pages((unsigned long)pgd, PGD_ALLOC_ORDER);
 }
 
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
 
 /* Three Level Page Table Support for pmd's */
 
index 15207b9362bfd0947064f7572ad34fdfb6e4d30c..0a183756d6ec2badccc840b881214077edaf556b 100644 (file)
@@ -68,13 +68,11 @@ extern void purge_tlb_entries(struct mm_struct *, unsigned long);
 #define KERNEL_INITIAL_ORDER   24      /* 0 to 1<<24 = 16MB */
 #define KERNEL_INITIAL_SIZE    (1 << KERNEL_INITIAL_ORDER)
 
-#if defined(CONFIG_64BIT) && defined(CONFIG_PARISC_PAGE_SIZE_4KB)
-#define PT_NLEVELS     3
+#if CONFIG_PGTABLE_LEVELS == 3
 #define PGD_ORDER      1 /* Number of pages per pgd */
 #define PMD_ORDER      1 /* Number of pages per pmd */
 #define PGD_ALLOC_ORDER        2 /* first pgd contains pmd */
 #else
-#define PT_NLEVELS     2
 #define PGD_ORDER      1 /* Number of pages per pgd */
 #define PGD_ALLOC_ORDER        PGD_ORDER
 #endif
@@ -93,7 +91,7 @@ extern void purge_tlb_entries(struct mm_struct *, unsigned long);
 #define PMD_SHIFT       (PLD_SHIFT + BITS_PER_PTE)
 #define PMD_SIZE       (1UL << PMD_SHIFT)
 #define PMD_MASK       (~(PMD_SIZE-1))
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
 #define BITS_PER_PMD   (PAGE_SHIFT + PMD_ORDER - BITS_PER_PMD_ENTRY)
 #else
 #define __PAGETABLE_PMD_FOLDED
@@ -277,7 +275,7 @@ extern unsigned long *empty_zero_page;
 #define pgd_flag(x)    (pgd_val(x) & PxD_FLAG_MASK)
 #define pgd_address(x) ((unsigned long)(pgd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT)
 
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
 /* The first entry of the permanent pmd is not there if it contains
  * the gateway marker */
 #define pmd_none(x)    (!pmd_val(x) || pmd_flag(x) == PxD_FLAG_ATTACHED)
@@ -287,7 +285,7 @@ extern unsigned long *empty_zero_page;
 #define pmd_bad(x)     (!(pmd_flag(x) & PxD_FLAG_VALID))
 #define pmd_present(x) (pmd_flag(x) & PxD_FLAG_PRESENT)
 static inline void pmd_clear(pmd_t *pmd) {
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
        if (pmd_flag(*pmd) & PxD_FLAG_ATTACHED)
                /* This is the entry pointing to the permanent pmd
                 * attached to the pgd; cannot clear it */
@@ -299,7 +297,7 @@ static inline void pmd_clear(pmd_t *pmd) {
 
 
 
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
 #define pgd_page_vaddr(pgd) ((unsigned long) __va(pgd_address(pgd)))
 #define pgd_page(pgd)  virt_to_page((void *)pgd_page_vaddr(pgd))
 
@@ -309,7 +307,7 @@ static inline void pmd_clear(pmd_t *pmd) {
 #define pgd_bad(x)      (!(pgd_flag(x) & PxD_FLAG_VALID))
 #define pgd_present(x)  (pgd_flag(x) & PxD_FLAG_PRESENT)
 static inline void pgd_clear(pgd_t *pgd) {
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
        if(pgd_flag(*pgd) & PxD_FLAG_ATTACHED)
                /* This is the permanent pmd attached to the pgd; cannot
                 * free it */
@@ -393,7 +391,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 
 /* Find an entry in the second-level page table.. */
 
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
 #define pmd_offset(dir,address) \
 ((pmd_t *) pgd_page_vaddr(*(dir)) + (((address)>>PMD_SHIFT) & (PTRS_PER_PMD-1)))
 #else
index 2ab16bb160a87a17186c0111f1b67858d36fd4b1..75819617f93b9c8fe3e7cd1c655354c83e338360 100644 (file)
         * can address up to 1TB
         */
        .macro          L2_ptep pmd,pte,index,va,fault
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
        extru           \va,31-ASM_PMD_SHIFT,ASM_BITS_PER_PMD,\index
 #else
 # if defined(CONFIG_64BIT)
         * all ILP32 processes and all the kernel for machines with
         * under 4GB of memory) */
        .macro          L3_ptep pgd,pte,index,va,fault
-#if PT_NLEVELS == 3 /* we might have a 2-Level scheme, e.g. with 16kb page size */
+#if CONFIG_PGTABLE_LEVELS == 3 /* we might have a 2-Level scheme, e.g. with 16kb page size */
        extrd,u         \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
        copy            %r0,\pte
        extrd,u,*=      \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
index d4dc588c0dc1f6963f99e6545de14031192d4543..e7d64527aff94f69b019f7bde3aad63da47420ec 100644 (file)
@@ -74,7 +74,7 @@ $bss_loop:
        mtctl           %r4,%cr24       /* Initialize kernel root pointer */
        mtctl           %r4,%cr25       /* Initialize user root pointer */
 
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
        /* Set pmd in pgd */
        load32          PA(pmd0),%r5
        shrd            %r5,PxD_VALUE_SHIFT,%r3 
@@ -97,7 +97,7 @@ $bss_loop:
        stw             %r3,0(%r4)
        ldo             (PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
        addib,>         -1,%r1,1b
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
        ldo             ASM_PMD_ENTRY_SIZE(%r4),%r4
 #else
        ldo             ASM_PGD_ENTRY_SIZE(%r4),%r4
index 15dbe81cf5f301d12fdda0db4c060afc61e114e8..c229427fa54627ffdfae7eaebd1e2b19f45a98ed 100644 (file)
@@ -34,7 +34,7 @@
 extern int  data_start;
 extern void parisc_kernel_start(void); /* Kernel entry point in head.S */
 
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
 /* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
  * with the first pmd adjacent to the pgd and below it. gcc doesn't actually
  * guarantee that global objects will be laid out in memory in the same order
index 22b0940494bb5016be1fca2a98aa7b75c105487a..e99014adf0171b75220742b1a33ae813c297e364 100644 (file)
@@ -88,7 +88,7 @@ config PPC
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_MIGHT_HAVE_PC_SERIO
        select BINFMT_ELF
-       select ARCH_BINFMT_ELF_RANDOMIZE_PIE
+       select ARCH_HAS_ELF_RANDOMIZE
        select OF
        select OF_EARLY_FLATTREE
        select OF_RESERVED_MEM
@@ -297,6 +297,12 @@ config ZONE_DMA32
        bool
        default y if PPC64
 
+config PGTABLE_LEVELS
+       int
+       default 2 if !PPC64
+       default 3 if PPC_64K_PAGES
+       default 4
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
index 57d289acb80325a063539eb8aa2ab92a6edefab0..ee46ffef608ee1679033a77c8ff5353ba6bfb51c 100644 (file)
@@ -128,10 +128,6 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
        (0x7ff >> (PAGE_SHIFT - 12)) : \
        (0x3ffff >> (PAGE_SHIFT - 12)))
 
-extern unsigned long arch_randomize_brk(struct mm_struct *mm);
-#define arch_randomize_brk arch_randomize_brk
-
-
 #ifdef CONFIG_SPU_BASE
 /* Notes used in ET_CORE. Note name is "SPU/<fd>/<filename>". */
 #define NT_SPU         1
index 942c7b1678e3f7ed2af0f9723e38c424c9287728..993090422690c748eeb9f272918724d0bc164e9f 100644 (file)
@@ -106,10 +106,6 @@ struct kvmppc_vcpu_book3s {
        spinlock_t mmu_lock;
 };
 
-#define CONTEXT_HOST           0
-#define CONTEXT_GUEST          1
-#define CONTEXT_GUEST_END      2
-
 #define VSID_REAL      0x07ffffffffc00000ULL
 #define VSID_BAT       0x07ffffffffb00000ULL
 #define VSID_64K       0x0800000000000000ULL
index 6e909f3e6a466972285aa2797fd315b898313720..37d2da6feabf7208bc659512e88214cd943d4b32 100644 (file)
@@ -478,7 +478,7 @@ extern unsigned long smu_cmdbuf_abs;
 
 
 /*
- * Kenrel asynchronous i2c interface
+ * Kernel asynchronous i2c interface
  */
 
 #define SMU_I2C_READ_MAX       0x1d
index b8e15c678960f3aadc5094860b9c1742c942e3d3..308c5e15676b9160141ddcd86939c82f91029f3f 100644 (file)
@@ -721,7 +721,7 @@ void __init early_init_devtree(void *params)
         */
        of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
        if (boot_cpuid < 0) {
-               printk("Failed to indentify boot CPU !\n");
+               printk("Failed to identify boot CPU !\n");
                BUG();
        }
 
index 39b3a8f816f28d0ecd61ca8a110d22bb99fb4507..6249cdc834d14977ffe5344a4b15857de01abe79 100644 (file)
@@ -34,7 +34,7 @@
 #include <asm/kvm_para.h>
 #include <asm/kvm_host.h>
 #include <asm/kvm_ppc.h>
-#include "iodev.h"
+#include <kvm/iodev.h>
 
 #define MAX_CPU     32
 #define MAX_SRC     256
@@ -289,11 +289,6 @@ static inline void IRQ_resetbit(struct irq_queue *q, int n_IRQ)
        clear_bit(n_IRQ, q->queue);
 }
 
-static inline int IRQ_testbit(struct irq_queue *q, int n_IRQ)
-{
-       return test_bit(n_IRQ, q->queue);
-}
-
 static void IRQ_check(struct openpic *opp, struct irq_queue *q)
 {
        int irq = -1;
@@ -1374,8 +1369,9 @@ static int kvm_mpic_write_internal(struct openpic *opp, gpa_t addr, u32 val)
        return -ENXIO;
 }
 
-static int kvm_mpic_read(struct kvm_io_device *this, gpa_t addr,
-                        int len, void *ptr)
+static int kvm_mpic_read(struct kvm_vcpu *vcpu,
+                        struct kvm_io_device *this,
+                        gpa_t addr, int len, void *ptr)
 {
        struct openpic *opp = container_of(this, struct openpic, mmio);
        int ret;
@@ -1415,8 +1411,9 @@ static int kvm_mpic_read(struct kvm_io_device *this, gpa_t addr,
        return ret;
 }
 
-static int kvm_mpic_write(struct kvm_io_device *this, gpa_t addr,
-                         int len, const void *ptr)
+static int kvm_mpic_write(struct kvm_vcpu *vcpu,
+                         struct kvm_io_device *this,
+                         gpa_t addr, int len, const void *ptr)
 {
        struct openpic *opp = container_of(this, struct openpic, mmio);
        int ret;
index 27c0face86f45cdac10ac74ba309de04094a8367..24bfe401373e44aad58268c95caf7e2a5e09198e 100644 (file)
@@ -807,7 +807,7 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        idx = srcu_read_lock(&vcpu->kvm->srcu);
 
-       ret = kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
+       ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, run->mmio.phys_addr,
                              bytes, &run->mmio.data);
 
        srcu_read_unlock(&vcpu->kvm->srcu, idx);
@@ -880,7 +880,7 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        idx = srcu_read_lock(&vcpu->kvm->srcu);
 
-       ret = kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
+       ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, run->mmio.phys_addr,
                               bytes, &run->mmio.data);
 
        srcu_read_unlock(&vcpu->kvm->srcu, idx);
index cb8bdbe4972fa8bbe4c63039537ab9cbd4ccb233..0f0502e12f6c4c8accbe7fc28eb4db08158decfb 100644 (file)
@@ -53,21 +53,20 @@ static inline int mmap_is_legacy(void)
        return sysctl_legacy_va_layout;
 }
 
-static unsigned long mmap_rnd(void)
+unsigned long arch_mmap_rnd(void)
 {
-       unsigned long rnd = 0;
+       unsigned long rnd;
+
+       /* 8MB for 32bit, 1GB for 64bit */
+       if (is_32bit_task())
+               rnd = (unsigned long)get_random_int() % (1<<(23-PAGE_SHIFT));
+       else
+               rnd = (unsigned long)get_random_int() % (1<<(30-PAGE_SHIFT));
 
-       if (current->flags & PF_RANDOMIZE) {
-               /* 8MB for 32bit, 1GB for 64bit */
-               if (is_32bit_task())
-                       rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT)));
-               else
-                       rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT)));
-       }
        return rnd << PAGE_SHIFT;
 }
 
-static inline unsigned long mmap_base(void)
+static inline unsigned long mmap_base(unsigned long rnd)
 {
        unsigned long gap = rlimit(RLIMIT_STACK);
 
@@ -76,7 +75,7 @@ static inline unsigned long mmap_base(void)
        else if (gap > MAX_GAP)
                gap = MAX_GAP;
 
-       return PAGE_ALIGN(TASK_SIZE - gap - mmap_rnd());
+       return PAGE_ALIGN(TASK_SIZE - gap - rnd);
 }
 
 /*
@@ -85,6 +84,11 @@ static inline unsigned long mmap_base(void)
  */
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
+       unsigned long random_factor = 0UL;
+
+       if (current->flags & PF_RANDOMIZE)
+               random_factor = arch_mmap_rnd();
+
        /*
         * Fall back to the standard layout if the personality
         * bit is set, or if the expected stack growth is unlimited:
@@ -93,7 +97,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
                mm->mmap_base = TASK_UNMAPPED_BASE;
                mm->get_unmapped_area = arch_get_unmapped_area;
        } else {
-               mm->mmap_base = mmap_base();
+               mm->mmap_base = mmap_base(random_factor);
                mm->get_unmapped_area = arch_get_unmapped_area_topdown;
        }
 }
index 7c4f6690533a5efab955565506a702ca352a56b2..7fd60dcb2cb0ebd734a7f2659bd70ae25632d374 100644 (file)
@@ -124,7 +124,7 @@ static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw)
 
 static inline void power_pmu_bhrb_enable(struct perf_event *event) {}
 static inline void power_pmu_bhrb_disable(struct perf_event *event) {}
-static void power_pmu_flush_branch_stack(void) {}
+static void power_pmu_sched_task(struct perf_event_context *ctx, bool sched_in) {}
 static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {}
 static void pmao_restore_workaround(bool ebb) { }
 #endif /* CONFIG_PPC32 */
@@ -350,6 +350,7 @@ static void power_pmu_bhrb_enable(struct perf_event *event)
                cpuhw->bhrb_context = event->ctx;
        }
        cpuhw->bhrb_users++;
+       perf_sched_cb_inc(event->ctx->pmu);
 }
 
 static void power_pmu_bhrb_disable(struct perf_event *event)
@@ -361,6 +362,7 @@ static void power_pmu_bhrb_disable(struct perf_event *event)
 
        cpuhw->bhrb_users--;
        WARN_ON_ONCE(cpuhw->bhrb_users < 0);
+       perf_sched_cb_dec(event->ctx->pmu);
 
        if (!cpuhw->disabled && !cpuhw->bhrb_users) {
                /* BHRB cannot be turned off when other
@@ -375,9 +377,12 @@ static void power_pmu_bhrb_disable(struct perf_event *event)
 /* Called from ctxsw to prevent one process's branch entries to
  * mingle with the other process's entries during context switch.
  */
-static void power_pmu_flush_branch_stack(void)
+static void power_pmu_sched_task(struct perf_event_context *ctx, bool sched_in)
 {
-       if (ppmu->bhrb_nr)
+       if (!ppmu->bhrb_nr)
+               return;
+
+       if (sched_in)
                power_pmu_bhrb_reset();
 }
 /* Calculate the to address for a branch */
@@ -1901,7 +1906,7 @@ static struct pmu power_pmu = {
        .cancel_txn     = power_pmu_cancel_txn,
        .commit_txn     = power_pmu_commit_txn,
        .event_idx      = power_pmu_event_idx,
-       .flush_branch_stack = power_pmu_flush_branch_stack,
+       .sched_task     = power_pmu_sched_task,
 };
 
 /*
index 9445a824819ea7f919fdc4191b561e07c07bd49c..abeb9ec0d117890bc284d70ac6283513a15be648 100644 (file)
@@ -1126,7 +1126,7 @@ static int h_24x7_event_init(struct perf_event *event)
        /* Physical domains & other lpars require extra capabilities */
        if (!caps.collect_privileged && (is_physical_domain(domain) ||
                (event_get_lpar(event) != event_get_lpar_max()))) {
-               pr_devel("hv permisions disallow: is_physical_domain:%d, lpar=0x%llx\n",
+               pr_devel("hv permissions disallow: is_physical_domain:%d, lpar=0x%llx\n",
                                is_physical_domain(domain),
                                event_get_lpar(event));
                return -EACCES;
index 7a180f0308d55ad316a74c39083515fb92322326..680232d6ba481cf5fcfe445ac262a44387e3a4f6 100644 (file)
@@ -50,14 +50,14 @@ void p1022rdk_set_pixel_clock(unsigned int pixclock)
        /* Map the global utilities registers. */
        guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
        if (!guts_np) {
-               pr_err("p1022rdk: missing global utilties device node\n");
+               pr_err("p1022rdk: missing global utilities device node\n");
                return;
        }
 
        guts = of_iomap(guts_np, 0);
        of_node_put(guts_np);
        if (!guts) {
-               pr_err("p1022rdk: could not map global utilties device\n");
+               pr_err("p1022rdk: could not map global utilities device\n");
                return;
        }
 
index 0509bca5e830b656c8a553c047740b68b172f4b1..fcbe899fe299303d8e96d3faf0ba74eb5dc1ee53 100644 (file)
@@ -9,11 +9,11 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <linux/jump_label.h>
 #include <asm/ppc_asm.h>
 #include <asm/hvcall.h>
 #include <asm/asm-offsets.h>
 #include <asm/opal.h>
-#include <asm/jump_label.h>
 
        .section        ".text"
 
index ccd53f91e8aa8e4f3b30bc550f55a63f509818a8..74b5b8e239c8235ac61b529b8085cc3ceff096ed 100644 (file)
@@ -7,12 +7,12 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
+#include <linux/jump_label.h>
 #include <asm/hvcall.h>
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
 #include <asm/ptrace.h>
-#include <asm/jump_label.h>
 
        .section        ".text"
        
index b5682fd6c9846b2cdb259720e35a2326cf7c45a1..b7a67e3d2201e4d5988e9cb3df651651c12024c8 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/console.h>
 #include <linux/export.h>
-#include <linux/static_key.h>
+#include <linux/jump_label.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/page.h>
index 373cd5badf1cf8eea7ff7c65610b0a4ee2bfd5b1..6321fd8bf813b4cadde000dffa98d5269309a621 100644 (file)
@@ -65,6 +65,7 @@ config S390
        def_bool y
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
+       select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_GCOV_PROFILE_ALL
        select ARCH_HAS_SG_CHAIN
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
@@ -133,6 +134,7 @@ config S390
        select HAVE_KPROBES
        select HAVE_KRETPROBES
        select HAVE_KVM if 64BIT
+       select HAVE_LIVEPATCH
        select HAVE_MEMBLOCK
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_MEMBLOCK_PHYS_MAP
@@ -155,10 +157,17 @@ config S390
 config SCHED_OMIT_FRAME_POINTER
        def_bool y
 
+config PGTABLE_LEVELS
+       int
+       default 4 if 64BIT
+       default 2
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
 
+source "kernel/livepatch/Kconfig"
+
 menu "Processor type and features"
 
 config HAVE_MARCH_Z900_FEATURES
index 99824ff8dd354e74ff421a2c9bb59243e045d541..df7d8cbee377a229c5f609d92ea7b72045c9cc86 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/mount.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include <asm/ebcdic.h>
 #include "hypfs.h"
 
index c9c875d9ed318cc75f7123a8d999b464201a4fd5..a5c4978462c1e25c1d3505bb2c82d8c400d56a39 100644 (file)
@@ -161,10 +161,11 @@ extern unsigned int vdso_enabled;
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
    use of this is to invoke "./ld.so someprog" to test out a new version of
    the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk.  */
-
-extern unsigned long randomize_et_dyn(void);
-#define ELF_ET_DYN_BASE                randomize_et_dyn()
+   that it will "exec", and that there is sufficient room for the brk. 64-bit
+   tasks are aligned to 4GB. */
+#define ELF_ET_DYN_BASE (is_32bit_task() ? \
+                               (STACK_TOP / 3 * 2) : \
+                               (STACK_TOP / 3 * 2) & ~((1UL << 32) - 1))
 
 /* This yields a mask that user programs can use to figure out what
    instruction set this CPU supports. */
@@ -225,9 +226,6 @@ struct linux_binprm;
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
 int arch_setup_additional_pages(struct linux_binprm *, int);
 
-extern unsigned long arch_randomize_brk(struct mm_struct *mm);
-#define arch_randomize_brk arch_randomize_brk
-
 void *fill_cpu_elf_notes(void *ptr, struct save_area *sa, __vector128 *vxrs);
 
 #endif
index 58642fd29c878c8d1fb5d384ecf58427b553552e..2b77e235b5fbdf54707551e067da19bd9ffb3a11 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_S390_JUMP_LABEL_H
 #define _ASM_S390_JUMP_LABEL_H
 
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 
 #define JUMP_LABEL_NOP_SIZE 6
@@ -39,4 +41,5 @@ struct jump_entry {
        jump_label_t key;
 };
 
+#endif  /* __ASSEMBLY__ */
 #endif
index f407bbf5ee94ca5e2f6122951e52ce2d7db1a7ef..d01fc588b5c378fddc46eba49e28b4de4be1f1a9 100644 (file)
@@ -172,7 +172,9 @@ struct kvm_s390_sie_block {
        __u32   fac;                    /* 0x01a0 */
        __u8    reserved1a4[20];        /* 0x01a4 */
        __u64   cbrlo;                  /* 0x01b8 */
-       __u8    reserved1c0[30];        /* 0x01c0 */
+       __u8    reserved1c0[8];         /* 0x01c0 */
+       __u32   ecd;                    /* 0x01c8 */
+       __u8    reserved1cc[18];        /* 0x01cc */
        __u64   pp;                     /* 0x01de */
        __u8    reserved1e6[2];         /* 0x01e6 */
        __u64   itdba;                  /* 0x01e8 */
@@ -183,11 +185,17 @@ struct kvm_s390_itdb {
        __u8    data[256];
 } __packed;
 
+struct kvm_s390_vregs {
+       __vector128 vrs[32];
+       __u8    reserved200[512];       /* for future vector expansion */
+} __packed;
+
 struct sie_page {
        struct kvm_s390_sie_block sie_block;
        __u8 reserved200[1024];         /* 0x0200 */
        struct kvm_s390_itdb itdb;      /* 0x0600 */
-       __u8 reserved700[2304];         /* 0x0700 */
+       __u8 reserved700[1280];         /* 0x0700 */
+       struct kvm_s390_vregs vregs;    /* 0x0c00 */
 } __packed;
 
 struct kvm_vcpu_stat {
@@ -238,6 +246,7 @@ struct kvm_vcpu_stat {
        u32 instruction_sigp_stop;
        u32 instruction_sigp_stop_store_status;
        u32 instruction_sigp_store_status;
+       u32 instruction_sigp_store_adtl_status;
        u32 instruction_sigp_arch;
        u32 instruction_sigp_prefix;
        u32 instruction_sigp_restart;
@@ -270,6 +279,7 @@ struct kvm_vcpu_stat {
 #define PGM_SPECIAL_OPERATION          0x13
 #define PGM_OPERAND                    0x15
 #define PGM_TRACE_TABEL                        0x16
+#define PGM_VECTOR_PROCESSING          0x1b
 #define PGM_SPACE_SWITCH               0x1c
 #define PGM_HFP_SQUARE_ROOT            0x1d
 #define PGM_PC_TRANSLATION_SPEC                0x1f
@@ -334,6 +344,11 @@ enum irq_types {
        IRQ_PEND_COUNT
 };
 
+/* We have 2M for virtio device descriptor pages. Smallest amount of
+ * memory per page is 24 bytes (1 queue), so (2048*1024) / 24 = 87381
+ */
+#define KVM_S390_MAX_VIRTIO_IRQS 87381
+
 /*
  * Repressible (non-floating) machine check interrupts
  * subclass bits in MCIC
@@ -411,13 +426,32 @@ struct kvm_s390_local_interrupt {
        unsigned long pending_irqs;
 };
 
+#define FIRQ_LIST_IO_ISC_0 0
+#define FIRQ_LIST_IO_ISC_1 1
+#define FIRQ_LIST_IO_ISC_2 2
+#define FIRQ_LIST_IO_ISC_3 3
+#define FIRQ_LIST_IO_ISC_4 4
+#define FIRQ_LIST_IO_ISC_5 5
+#define FIRQ_LIST_IO_ISC_6 6
+#define FIRQ_LIST_IO_ISC_7 7
+#define FIRQ_LIST_PFAULT   8
+#define FIRQ_LIST_VIRTIO   9
+#define FIRQ_LIST_COUNT   10
+#define FIRQ_CNTR_IO       0
+#define FIRQ_CNTR_SERVICE  1
+#define FIRQ_CNTR_VIRTIO   2
+#define FIRQ_CNTR_PFAULT   3
+#define FIRQ_MAX_COUNT     4
+
 struct kvm_s390_float_interrupt {
+       unsigned long pending_irqs;
        spinlock_t lock;
-       struct list_head list;
-       atomic_t active;
+       struct list_head lists[FIRQ_LIST_COUNT];
+       int counters[FIRQ_MAX_COUNT];
+       struct kvm_s390_mchk_info mchk;
+       struct kvm_s390_ext_info srv_signal;
        int next_rr_cpu;
        unsigned long idle_mask[BITS_TO_LONGS(KVM_MAX_VCPUS)];
-       unsigned int irq_count;
 };
 
 struct kvm_hw_wp_info_arch {
@@ -465,6 +499,7 @@ struct kvm_vcpu_arch {
        s390_fp_regs      host_fpregs;
        unsigned int      host_acrs[NUM_ACRS];
        s390_fp_regs      guest_fpregs;
+       struct kvm_s390_vregs   *host_vregs;
        struct kvm_s390_local_interrupt local_int;
        struct hrtimer    ckc_timer;
        struct kvm_s390_pgm_info pgm;
@@ -553,6 +588,7 @@ struct kvm_arch{
        int use_cmma;
        int user_cpu_state_ctrl;
        int user_sigp;
+       int user_stsi;
        struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS];
        wait_queue_head_t ipte_wq;
        int ipte_lock_count;
diff --git a/arch/s390/include/asm/livepatch.h b/arch/s390/include/asm/livepatch.h
new file mode 100644 (file)
index 0000000..7aa7991
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * livepatch.h - s390-specific Kernel Live Patching Core
+ *
+ *  Copyright (c) 2013-2015 SUSE
+ *   Authors: Jiri Kosina
+ *           Vojtech Pavlik
+ *           Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#ifndef ASM_LIVEPATCH_H
+#define ASM_LIVEPATCH_H
+
+#include <linux/module.h>
+
+#ifdef CONFIG_LIVEPATCH
+static inline int klp_check_compiler_support(void)
+{
+       return 0;
+}
+
+static inline int klp_write_module_reloc(struct module *mod, unsigned long
+               type, unsigned long loc, unsigned long value)
+{
+       /* not supported yet */
+       return -ENOSYS;
+}
+
+static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
+{
+       regs->psw.addr = ip;
+}
+#else
+#error Live patching support is disabled; check CONFIG_LIVEPATCH
+#endif
+
+#endif
index 9c77e60b9a269a59bcde0d4fe0a5fb77348f1520..ef1a5fcc6c66bbf5705173b41371378c4b541483 100644 (file)
@@ -150,6 +150,7 @@ struct kvm_guest_debug_arch {
 #define KVM_SYNC_CRS    (1UL << 3)
 #define KVM_SYNC_ARCH0  (1UL << 4)
 #define KVM_SYNC_PFAULT (1UL << 5)
+#define KVM_SYNC_VRS    (1UL << 6)
 /* definition of registers in kvm_run */
 struct kvm_sync_regs {
        __u64 prefix;   /* prefix register */
@@ -164,6 +165,9 @@ struct kvm_sync_regs {
        __u64 pft;      /* pfault token [PFAULT] */
        __u64 pfs;      /* pfault select [PFAULT] */
        __u64 pfc;      /* pfault compare [PFAULT] */
+       __u64 vrs[32][2];       /* vector registers */
+       __u8  reserved[512];    /* for future vector expansion */
+       __u32 fpc;      /* only valid with vector registers */
 };
 
 #define KVM_REG_S390_TODPR     (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1)
index d4096fdfc6ab45b02eda2f0a7258da5b98f46930..ee69c0854c8891067b67a0d8920e7f3cf671f308 100644 (file)
  * and returns a key, which can be used to find a mnemonic name
  * of the instruction in the icpt_insn_codes table.
  */
-#define icpt_insn_decoder(insn)                        \
+#define icpt_insn_decoder(insn) (              \
        INSN_DECODE_IPA0(0x01, insn, 48, 0xff)  \
        INSN_DECODE_IPA0(0xaa, insn, 48, 0x0f)  \
        INSN_DECODE_IPA0(0xb2, insn, 48, 0xff)  \
        INSN_DECODE_IPA0(0xe5, insn, 48, 0xff)  \
        INSN_DECODE_IPA0(0xeb, insn, 16, 0xff)  \
        INSN_DECODE_IPA0(0xc8, insn, 48, 0x0f)  \
-       INSN_DECODE(insn)
+       INSN_DECODE(insn))
 
 #endif /* _UAPI_ASM_S390_SIE_H */
index e07e91605353003084ff19511c1c520e8bca1dd7..8dc4db10d1608e81eafad41e5f87d1c92af7bbf5 100644 (file)
@@ -171,6 +171,7 @@ int main(void)
 #else /* CONFIG_32BIT */
        DEFINE(__LC_DATA_EXC_CODE, offsetof(struct _lowcore, data_exc_code));
        DEFINE(__LC_MCCK_FAIL_STOR_ADDR, offsetof(struct _lowcore, failing_storage_address));
+       DEFINE(__LC_VX_SAVE_AREA_ADDR, offsetof(struct _lowcore, vector_save_area_addr));
        DEFINE(__LC_EXT_PARAMS2, offsetof(struct _lowcore, ext_params2));
        DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, floating_pt_save_area));
        DEFINE(__LC_PASTE, offsetof(struct _lowcore, paste));
index 20660dddb2d67f1e4ebdd16a2a89ff99602935f1..170ddd2018b31667df8619b471df42b7fb562705 100644 (file)
@@ -215,20 +215,20 @@ void update_vsyscall(struct timekeeper *tk)
 {
        u64 nsecps;
 
-       if (tk->tkr.clock != &clocksource_tod)
+       if (tk->tkr_mono.clock != &clocksource_tod)
                return;
 
        /* Make userspace gettimeofday spin until we're done. */
        ++vdso_data->tb_update_count;
        smp_wmb();
-       vdso_data->xtime_tod_stamp = tk->tkr.cycle_last;
+       vdso_data->xtime_tod_stamp = tk->tkr_mono.cycle_last;
        vdso_data->xtime_clock_sec = tk->xtime_sec;
-       vdso_data->xtime_clock_nsec = tk->tkr.xtime_nsec;
+       vdso_data->xtime_clock_nsec = tk->tkr_mono.xtime_nsec;
        vdso_data->wtom_clock_sec =
                tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
-       vdso_data->wtom_clock_nsec = tk->tkr.xtime_nsec +
-               + ((u64) tk->wall_to_monotonic.tv_nsec << tk->tkr.shift);
-       nsecps = (u64) NSEC_PER_SEC << tk->tkr.shift;
+       vdso_data->wtom_clock_nsec = tk->tkr_mono.xtime_nsec +
+               + ((u64) tk->wall_to_monotonic.tv_nsec << tk->tkr_mono.shift);
+       nsecps = (u64) NSEC_PER_SEC << tk->tkr_mono.shift;
        while (vdso_data->wtom_clock_nsec >= nsecps) {
                vdso_data->wtom_clock_nsec -= nsecps;
                vdso_data->wtom_clock_sec++;
@@ -236,7 +236,7 @@ void update_vsyscall(struct timekeeper *tk)
 
        vdso_data->xtime_coarse_sec = tk->xtime_sec;
        vdso_data->xtime_coarse_nsec =
-               (long)(tk->tkr.xtime_nsec >> tk->tkr.shift);
+               (long)(tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift);
        vdso_data->wtom_coarse_sec =
                vdso_data->xtime_coarse_sec + tk->wall_to_monotonic.tv_sec;
        vdso_data->wtom_coarse_nsec =
@@ -246,8 +246,8 @@ void update_vsyscall(struct timekeeper *tk)
                vdso_data->wtom_coarse_sec++;
        }
 
-       vdso_data->tk_mult = tk->tkr.mult;
-       vdso_data->tk_shift = tk->tkr.shift;
+       vdso_data->tk_mult = tk->tkr_mono.mult;
+       vdso_data->tk_shift = tk->tkr_mono.shift;
        smp_wmb();
        ++vdso_data->tb_update_count;
 }
@@ -283,7 +283,7 @@ void __init time_init(void)
        if (register_external_irq(EXT_IRQ_TIMING_ALERT, timing_alert_interrupt))
                panic("Couldn't request external interrupt 0x1406");
 
-       if (clocksource_register(&clocksource_tod) != 0)
+       if (__clocksource_register(&clocksource_tod) != 0)
                panic("Could not register TOD clock source");
 
        /* Enable TOD clock interrupts on the boot cpu. */
index 9254afff250c968682db79c453d0542868bfdd9c..fc7ec95848c39c527c2a24ee723c9f45624e31a0 100644 (file)
@@ -77,7 +77,7 @@ static int __diag_page_ref_service(struct kvm_vcpu *vcpu)
 
        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], &parm, sizeof(parm));
+       rc = read_guest(vcpu, vcpu->run->s.regs.gprs[rx], rx, &parm, sizeof(parm));
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
        if (parm.parm_version != 2 || parm.parm_len < 5 || parm.code != 0x258)
@@ -213,7 +213,7 @@ static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu)
         * - gpr 3 contains the virtqueue index (passed as datamatch)
         * - gpr 4 contains the index on the bus (optionally)
         */
-       ret = kvm_io_bus_write_cookie(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS,
+       ret = kvm_io_bus_write_cookie(vcpu, KVM_VIRTIO_CCW_NOTIFY_BUS,
                                      vcpu->run->s.regs.gprs[2] & 0xffffffff,
                                      8, &vcpu->run->s.regs.gprs[3],
                                      vcpu->run->s.regs.gprs[4]);
@@ -230,7 +230,7 @@ static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu)
 
 int kvm_s390_handle_diag(struct kvm_vcpu *vcpu)
 {
-       int code = kvm_s390_get_base_disp_rs(vcpu) & 0xffff;
+       int code = kvm_s390_get_base_disp_rs(vcpu, NULL) & 0xffff;
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
index 267523cac6de7860cda644017e2b52ccfc7ea8d4..a7559f7207df3a0ac62d0fc16b199f3b4c6b6dac 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/pgtable.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
+#include <asm/switch_to.h>
 
 union asce {
        unsigned long val;
@@ -207,6 +208,54 @@ union raddress {
        unsigned long pfra : 52; /* Page-Frame Real Address */
 };
 
+union alet {
+       u32 val;
+       struct {
+               u32 reserved : 7;
+               u32 p        : 1;
+               u32 alesn    : 8;
+               u32 alen     : 16;
+       };
+};
+
+union ald {
+       u32 val;
+       struct {
+               u32     : 1;
+               u32 alo : 24;
+               u32 all : 7;
+       };
+};
+
+struct ale {
+       unsigned long i      : 1; /* ALEN-Invalid Bit */
+       unsigned long        : 5;
+       unsigned long fo     : 1; /* Fetch-Only Bit */
+       unsigned long p      : 1; /* Private Bit */
+       unsigned long alesn  : 8; /* Access-List-Entry Sequence Number */
+       unsigned long aleax  : 16; /* Access-List-Entry Authorization Index */
+       unsigned long        : 32;
+       unsigned long        : 1;
+       unsigned long asteo  : 25; /* ASN-Second-Table-Entry Origin */
+       unsigned long        : 6;
+       unsigned long astesn : 32; /* ASTE Sequence Number */
+} __packed;
+
+struct aste {
+       unsigned long i      : 1; /* ASX-Invalid Bit */
+       unsigned long ato    : 29; /* Authority-Table Origin */
+       unsigned long        : 1;
+       unsigned long b      : 1; /* Base-Space Bit */
+       unsigned long ax     : 16; /* Authorization Index */
+       unsigned long atl    : 12; /* Authority-Table Length */
+       unsigned long        : 2;
+       unsigned long ca     : 1; /* Controlled-ASN Bit */
+       unsigned long ra     : 1; /* Reusable-ASN Bit */
+       unsigned long asce   : 64; /* Address-Space-Control Element */
+       unsigned long ald    : 32;
+       unsigned long astesn : 32;
+       /* .. more fields there */
+} __packed;
 
 int ipte_lock_held(struct kvm_vcpu *vcpu)
 {
@@ -307,15 +356,157 @@ void ipte_unlock(struct kvm_vcpu *vcpu)
                ipte_unlock_simple(vcpu);
 }
 
-static unsigned long get_vcpu_asce(struct kvm_vcpu *vcpu)
+static int ar_translation(struct kvm_vcpu *vcpu, union asce *asce, ar_t ar,
+                         int write)
+{
+       union alet alet;
+       struct ale ale;
+       struct aste aste;
+       unsigned long ald_addr, authority_table_addr;
+       union ald ald;
+       int eax, rc;
+       u8 authority_table;
+
+       if (ar >= NUM_ACRS)
+               return -EINVAL;
+
+       save_access_regs(vcpu->run->s.regs.acrs);
+       alet.val = vcpu->run->s.regs.acrs[ar];
+
+       if (ar == 0 || alet.val == 0) {
+               asce->val = vcpu->arch.sie_block->gcr[1];
+               return 0;
+       } else if (alet.val == 1) {
+               asce->val = vcpu->arch.sie_block->gcr[7];
+               return 0;
+       }
+
+       if (alet.reserved)
+               return PGM_ALET_SPECIFICATION;
+
+       if (alet.p)
+               ald_addr = vcpu->arch.sie_block->gcr[5];
+       else
+               ald_addr = vcpu->arch.sie_block->gcr[2];
+       ald_addr &= 0x7fffffc0;
+
+       rc = read_guest_real(vcpu, ald_addr + 16, &ald.val, sizeof(union ald));
+       if (rc)
+               return rc;
+
+       if (alet.alen / 8 > ald.all)
+               return PGM_ALEN_TRANSLATION;
+
+       if (0x7fffffff - ald.alo * 128 < alet.alen * 16)
+               return PGM_ADDRESSING;
+
+       rc = read_guest_real(vcpu, ald.alo * 128 + alet.alen * 16, &ale,
+                            sizeof(struct ale));
+       if (rc)
+               return rc;
+
+       if (ale.i == 1)
+               return PGM_ALEN_TRANSLATION;
+       if (ale.alesn != alet.alesn)
+               return PGM_ALE_SEQUENCE;
+
+       rc = read_guest_real(vcpu, ale.asteo * 64, &aste, sizeof(struct aste));
+       if (rc)
+               return rc;
+
+       if (aste.i)
+               return PGM_ASTE_VALIDITY;
+       if (aste.astesn != ale.astesn)
+               return PGM_ASTE_SEQUENCE;
+
+       if (ale.p == 1) {
+               eax = (vcpu->arch.sie_block->gcr[8] >> 16) & 0xffff;
+               if (ale.aleax != eax) {
+                       if (eax / 16 > aste.atl)
+                               return PGM_EXTENDED_AUTHORITY;
+
+                       authority_table_addr = aste.ato * 4 + eax / 4;
+
+                       rc = read_guest_real(vcpu, authority_table_addr,
+                                            &authority_table,
+                                            sizeof(u8));
+                       if (rc)
+                               return rc;
+
+                       if ((authority_table & (0x40 >> ((eax & 3) * 2))) == 0)
+                               return PGM_EXTENDED_AUTHORITY;
+               }
+       }
+
+       if (ale.fo == 1 && write)
+               return PGM_PROTECTION;
+
+       asce->val = aste.asce;
+       return 0;
+}
+
+struct trans_exc_code_bits {
+       unsigned long addr : 52; /* Translation-exception Address */
+       unsigned long fsi  : 2;  /* Access Exception Fetch/Store Indication */
+       unsigned long      : 6;
+       unsigned long b60  : 1;
+       unsigned long b61  : 1;
+       unsigned long as   : 2;  /* ASCE Identifier */
+};
+
+enum {
+       FSI_UNKNOWN = 0, /* Unknown wether fetch or store */
+       FSI_STORE   = 1, /* Exception was due to store operation */
+       FSI_FETCH   = 2  /* Exception was due to fetch operation */
+};
+
+static int get_vcpu_asce(struct kvm_vcpu *vcpu, union asce *asce,
+                        ar_t ar, int write)
 {
+       int rc;
+       psw_t *psw = &vcpu->arch.sie_block->gpsw;
+       struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm;
+       struct trans_exc_code_bits *tec_bits;
+
+       memset(pgm, 0, sizeof(*pgm));
+       tec_bits = (struct trans_exc_code_bits *)&pgm->trans_exc_code;
+       tec_bits->fsi = write ? FSI_STORE : FSI_FETCH;
+       tec_bits->as = psw_bits(*psw).as;
+
+       if (!psw_bits(*psw).t) {
+               asce->val = 0;
+               asce->r = 1;
+               return 0;
+       }
+
        switch (psw_bits(vcpu->arch.sie_block->gpsw).as) {
        case PSW_AS_PRIMARY:
-               return vcpu->arch.sie_block->gcr[1];
+               asce->val = vcpu->arch.sie_block->gcr[1];
+               return 0;
        case PSW_AS_SECONDARY:
-               return vcpu->arch.sie_block->gcr[7];
+               asce->val = vcpu->arch.sie_block->gcr[7];
+               return 0;
        case PSW_AS_HOME:
-               return vcpu->arch.sie_block->gcr[13];
+               asce->val = vcpu->arch.sie_block->gcr[13];
+               return 0;
+       case PSW_AS_ACCREG:
+               rc = ar_translation(vcpu, asce, ar, write);
+               switch (rc) {
+               case PGM_ALEN_TRANSLATION:
+               case PGM_ALE_SEQUENCE:
+               case PGM_ASTE_VALIDITY:
+               case PGM_ASTE_SEQUENCE:
+               case PGM_EXTENDED_AUTHORITY:
+                       vcpu->arch.pgm.exc_access_id = ar;
+                       break;
+               case PGM_PROTECTION:
+                       tec_bits->b60 = 1;
+                       tec_bits->b61 = 1;
+                       break;
+               }
+               if (rc > 0)
+                       pgm->code = rc;
+               return rc;
        }
        return 0;
 }
@@ -330,10 +521,11 @@ static int deref_table(struct kvm *kvm, unsigned long gpa, unsigned long *val)
  * @vcpu: virtual cpu
  * @gva: guest virtual address
  * @gpa: points to where guest physical (absolute) address should be stored
+ * @asce: effective asce
  * @write: indicates if access is a write access
  *
  * Translate a guest virtual address into a guest absolute address by means
- * of dynamic address translation as specified by the architecuture.
+ * of dynamic address translation as specified by the architecture.
  * If the resulting absolute address is not available in the configuration
  * an addressing exception is indicated and @gpa will not be changed.
  *
@@ -345,7 +537,8 @@ static int deref_table(struct kvm *kvm, unsigned long gpa, unsigned long *val)
  *           by the architecture
  */
 static unsigned long guest_translate(struct kvm_vcpu *vcpu, unsigned long gva,
-                                    unsigned long *gpa, int write)
+                                    unsigned long *gpa, const union asce asce,
+                                    int write)
 {
        union vaddress vaddr = {.addr = gva};
        union raddress raddr = {.addr = gva};
@@ -354,12 +547,10 @@ static unsigned long guest_translate(struct kvm_vcpu *vcpu, unsigned long gva,
        union ctlreg0 ctlreg0;
        unsigned long ptr;
        int edat1, edat2;
-       union asce asce;
 
        ctlreg0.val = vcpu->arch.sie_block->gcr[0];
        edat1 = ctlreg0.edat && test_kvm_facility(vcpu->kvm, 8);
        edat2 = edat1 && test_kvm_facility(vcpu->kvm, 78);
-       asce.val = get_vcpu_asce(vcpu);
        if (asce.r)
                goto real_address;
        ptr = asce.origin * 4096;
@@ -506,48 +697,30 @@ static inline int is_low_address(unsigned long ga)
        return (ga & ~0x11fful) == 0;
 }
 
-static int low_address_protection_enabled(struct kvm_vcpu *vcpu)
+static int low_address_protection_enabled(struct kvm_vcpu *vcpu,
+                                         const union asce asce)
 {
        union ctlreg0 ctlreg0 = {.val = vcpu->arch.sie_block->gcr[0]};
        psw_t *psw = &vcpu->arch.sie_block->gpsw;
-       union asce asce;
 
        if (!ctlreg0.lap)
                return 0;
-       asce.val = get_vcpu_asce(vcpu);
        if (psw_bits(*psw).t && asce.p)
                return 0;
        return 1;
 }
 
-struct trans_exc_code_bits {
-       unsigned long addr : 52; /* Translation-exception Address */
-       unsigned long fsi  : 2;  /* Access Exception Fetch/Store Indication */
-       unsigned long      : 7;
-       unsigned long b61  : 1;
-       unsigned long as   : 2;  /* ASCE Identifier */
-};
-
-enum {
-       FSI_UNKNOWN = 0, /* Unknown wether fetch or store */
-       FSI_STORE   = 1, /* Exception was due to store operation */
-       FSI_FETCH   = 2  /* Exception was due to fetch operation */
-};
-
 static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga,
                            unsigned long *pages, unsigned long nr_pages,
-                           int write)
+                           const union asce asce, int write)
 {
        struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm;
        psw_t *psw = &vcpu->arch.sie_block->gpsw;
        struct trans_exc_code_bits *tec_bits;
        int lap_enabled, rc;
 
-       memset(pgm, 0, sizeof(*pgm));
        tec_bits = (struct trans_exc_code_bits *)&pgm->trans_exc_code;
-       tec_bits->fsi = write ? FSI_STORE : FSI_FETCH;
-       tec_bits->as = psw_bits(*psw).as;
-       lap_enabled = low_address_protection_enabled(vcpu);
+       lap_enabled = low_address_protection_enabled(vcpu, asce);
        while (nr_pages) {
                ga = kvm_s390_logical_to_effective(vcpu, ga);
                tec_bits->addr = ga >> PAGE_SHIFT;
@@ -557,7 +730,7 @@ static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga,
                }
                ga &= PAGE_MASK;
                if (psw_bits(*psw).t) {
-                       rc = guest_translate(vcpu, ga, pages, write);
+                       rc = guest_translate(vcpu, ga, pages, asce, write);
                        if (rc < 0)
                                return rc;
                        if (rc == PGM_PROTECTION)
@@ -578,7 +751,7 @@ static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga,
        return 0;
 }
 
-int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, void *data,
+int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar, void *data,
                 unsigned long len, int write)
 {
        psw_t *psw = &vcpu->arch.sie_block->gpsw;
@@ -591,20 +764,19 @@ int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, void *data,
 
        if (!len)
                return 0;
-       /* Access register mode is not supported yet. */
-       if (psw_bits(*psw).t && psw_bits(*psw).as == PSW_AS_ACCREG)
-               return -EOPNOTSUPP;
+       rc = get_vcpu_asce(vcpu, &asce, ar, write);
+       if (rc)
+               return rc;
        nr_pages = (((ga & ~PAGE_MASK) + len - 1) >> PAGE_SHIFT) + 1;
        pages = pages_array;
        if (nr_pages > ARRAY_SIZE(pages_array))
                pages = vmalloc(nr_pages * sizeof(unsigned long));
        if (!pages)
                return -ENOMEM;
-       asce.val = get_vcpu_asce(vcpu);
        need_ipte_lock = psw_bits(*psw).t && !asce.r;
        if (need_ipte_lock)
                ipte_lock(vcpu);
-       rc = guest_page_range(vcpu, ga, pages, nr_pages, write);
+       rc = guest_page_range(vcpu, ga, pages, nr_pages, asce, write);
        for (idx = 0; idx < nr_pages && !rc; idx++) {
                gpa = *(pages + idx) + (ga & ~PAGE_MASK);
                _len = min(PAGE_SIZE - (gpa & ~PAGE_MASK), len);
@@ -652,7 +824,7 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
  * Note: The IPTE lock is not taken during this function, so the caller
  * has to take care of this.
  */
-int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva,
+int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, ar_t ar,
                            unsigned long *gpa, int write)
 {
        struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm;
@@ -661,26 +833,21 @@ int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva,
        union asce asce;
        int rc;
 
-       /* Access register mode is not supported yet. */
-       if (psw_bits(*psw).t && psw_bits(*psw).as == PSW_AS_ACCREG)
-               return -EOPNOTSUPP;
-
        gva = kvm_s390_logical_to_effective(vcpu, gva);
-       memset(pgm, 0, sizeof(*pgm));
        tec = (struct trans_exc_code_bits *)&pgm->trans_exc_code;
-       tec->as = psw_bits(*psw).as;
-       tec->fsi = write ? FSI_STORE : FSI_FETCH;
+       rc = get_vcpu_asce(vcpu, &asce, ar, write);
        tec->addr = gva >> PAGE_SHIFT;
-       if (is_low_address(gva) && low_address_protection_enabled(vcpu)) {
+       if (rc)
+               return rc;
+       if (is_low_address(gva) && low_address_protection_enabled(vcpu, asce)) {
                if (write) {
                        rc = pgm->code = PGM_PROTECTION;
                        return rc;
                }
        }
 
-       asce.val = get_vcpu_asce(vcpu);
        if (psw_bits(*psw).t && !asce.r) {      /* Use DAT? */
-               rc = guest_translate(vcpu, gva, gpa, write);
+               rc = guest_translate(vcpu, gva, gpa, asce, write);
                if (rc > 0) {
                        if (rc == PGM_PROTECTION)
                                tec->b61 = 1;
@@ -697,28 +864,51 @@ int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva,
 }
 
 /**
- * kvm_s390_check_low_addr_protection - check for low-address protection
- * @ga: Guest address
+ * check_gva_range - test a range of guest virtual addresses for accessibility
+ */
+int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, ar_t ar,
+                   unsigned long length, int is_write)
+{
+       unsigned long gpa;
+       unsigned long currlen;
+       int rc = 0;
+
+       ipte_lock(vcpu);
+       while (length > 0 && !rc) {
+               currlen = min(length, PAGE_SIZE - (gva % PAGE_SIZE));
+               rc = guest_translate_address(vcpu, gva, ar, &gpa, is_write);
+               gva += currlen;
+               length -= currlen;
+       }
+       ipte_unlock(vcpu);
+
+       return rc;
+}
+
+/**
+ * kvm_s390_check_low_addr_prot_real - check for low-address protection
+ * @gra: Guest real address
  *
  * Checks whether an address is subject to low-address protection and set
  * up vcpu->arch.pgm accordingly if necessary.
  *
  * Return: 0 if no protection exception, or PGM_PROTECTION if protected.
  */
-int kvm_s390_check_low_addr_protection(struct kvm_vcpu *vcpu, unsigned long ga)
+int kvm_s390_check_low_addr_prot_real(struct kvm_vcpu *vcpu, unsigned long gra)
 {
        struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm;
        psw_t *psw = &vcpu->arch.sie_block->gpsw;
        struct trans_exc_code_bits *tec_bits;
+       union ctlreg0 ctlreg0 = {.val = vcpu->arch.sie_block->gcr[0]};
 
-       if (!is_low_address(ga) || !low_address_protection_enabled(vcpu))
+       if (!ctlreg0.lap || !is_low_address(gra))
                return 0;
 
        memset(pgm, 0, sizeof(*pgm));
        tec_bits = (struct trans_exc_code_bits *)&pgm->trans_exc_code;
        tec_bits->fsi = FSI_STORE;
        tec_bits->as = psw_bits(*psw).as;
-       tec_bits->addr = ga >> PAGE_SHIFT;
+       tec_bits->addr = gra >> PAGE_SHIFT;
        pgm->code = PGM_PROTECTION;
 
        return pgm->code;
index 0149cf15058ab9e8d12918192353884ac4ce8f4f..ef03726cc6611acd1e52fb6970e2e802a1730cbd 100644 (file)
@@ -156,9 +156,11 @@ int read_guest_lc(struct kvm_vcpu *vcpu, unsigned long gra, void *data,
 }
 
 int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva,
-                           unsigned long *gpa, int write);
+                           ar_t ar, unsigned long *gpa, int write);
+int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, ar_t ar,
+                   unsigned long length, int is_write);
 
-int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, void *data,
+int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar, void *data,
                 unsigned long len, int write);
 
 int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
@@ -168,6 +170,7 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
  * write_guest - copy data from kernel space to guest space
  * @vcpu: virtual cpu
  * @ga: guest address
+ * @ar: access register
  * @data: source address in kernel space
  * @len: number of bytes to copy
  *
@@ -176,8 +179,7 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
  * If DAT is off data will be copied to guest real or absolute memory.
  * If DAT is on data will be copied to the address space as specified by
  * the address space bits of the PSW:
- * Primary, secondory or home space (access register mode is currently not
- * implemented).
+ * Primary, secondary, home space or access register mode.
  * The addressing mode of the PSW is also inspected, so that address wrap
  * around is taken into account for 24-, 31- and 64-bit addressing mode,
  * if the to be copied data crosses page boundaries in guest address space.
@@ -210,16 +212,17 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
  *      if data has been changed in guest space in case of an exception.
  */
 static inline __must_check
-int write_guest(struct kvm_vcpu *vcpu, unsigned long ga, void *data,
+int write_guest(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar, void *data,
                unsigned long len)
 {
-       return access_guest(vcpu, ga, data, len, 1);
+       return access_guest(vcpu, ga, ar, data, len, 1);
 }
 
 /**
  * read_guest - copy data from guest space to kernel space
  * @vcpu: virtual cpu
  * @ga: guest address
+ * @ar: access register
  * @data: destination address in kernel space
  * @len: number of bytes to copy
  *
@@ -229,10 +232,10 @@ int write_guest(struct kvm_vcpu *vcpu, unsigned long ga, void *data,
  * data will be copied from guest space to kernel space.
  */
 static inline __must_check
-int read_guest(struct kvm_vcpu *vcpu, unsigned long ga, void *data,
+int read_guest(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar, void *data,
               unsigned long len)
 {
-       return access_guest(vcpu, ga, data, len, 0);
+       return access_guest(vcpu, ga, ar, data, len, 0);
 }
 
 /**
@@ -330,6 +333,6 @@ int read_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, void *data,
 void ipte_lock(struct kvm_vcpu *vcpu);
 void ipte_unlock(struct kvm_vcpu *vcpu);
 int ipte_lock_held(struct kvm_vcpu *vcpu);
-int kvm_s390_check_low_addr_protection(struct kvm_vcpu *vcpu, unsigned long ga);
+int kvm_s390_check_low_addr_prot_real(struct kvm_vcpu *vcpu, unsigned long gra);
 
 #endif /* __KVM_S390_GACCESS_H */
index 3e8d4092ce30f10a6bd4b9e486e926889a937b2e..e97b3455d7e6bfbb7b12c606a5224c5efeba37d4 100644 (file)
@@ -191,8 +191,8 @@ static int __import_wp_info(struct kvm_vcpu *vcpu,
        if (!wp_info->old_data)
                return -ENOMEM;
        /* try to backup the original value */
-       ret = read_guest(vcpu, wp_info->phys_addr, wp_info->old_data,
-                        wp_info->len);
+       ret = read_guest_abs(vcpu, wp_info->phys_addr, wp_info->old_data,
+                            wp_info->len);
        if (ret) {
                kfree(wp_info->old_data);
                wp_info->old_data = NULL;
@@ -362,8 +362,8 @@ static struct kvm_hw_wp_info_arch *any_wp_changed(struct kvm_vcpu *vcpu)
                        continue;
 
                /* refetch the wp data and compare it to the old value */
-               if (!read_guest(vcpu, wp_info->phys_addr, temp,
-                               wp_info->len)) {
+               if (!read_guest_abs(vcpu, wp_info->phys_addr, temp,
+                                   wp_info->len)) {
                        if (memcmp(temp, wp_info->old_data, wp_info->len)) {
                                kfree(temp);
                                return wp_info;
index bebd2157edd019448ff772c9ac75a778e7e124f4..9e3779e3e496314a4e3f15823c152867c3a3cadd 100644 (file)
@@ -165,6 +165,7 @@ static void __extract_prog_irq(struct kvm_vcpu *vcpu,
                pgm_info->mon_class_nr = vcpu->arch.sie_block->mcn;
                pgm_info->mon_code = vcpu->arch.sie_block->tecmc;
                break;
+       case PGM_VECTOR_PROCESSING:
        case PGM_DATA:
                pgm_info->data_exc_code = vcpu->arch.sie_block->dxc;
                break;
@@ -319,7 +320,7 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu)
 
        /* Make sure that the source is paged-in */
        rc = guest_translate_address(vcpu, vcpu->run->s.regs.gprs[reg2],
-                                    &srcaddr, 0);
+                                    reg2, &srcaddr, 0);
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
        rc = kvm_arch_fault_in_page(vcpu, srcaddr, 0);
@@ -328,7 +329,7 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu)
 
        /* Make sure that the destination is paged-in */
        rc = guest_translate_address(vcpu, vcpu->run->s.regs.gprs[reg1],
-                                    &dstaddr, 1);
+                                    reg1, &dstaddr, 1);
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
        rc = kvm_arch_fault_in_page(vcpu, dstaddr, 1);
index 073b5f387d1dd3484186dd69dcfc5aae63d90b21..9de47265ef73da07ffd7ef37337bf2e44e59bd46 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * handling kvm guest interrupts
  *
- * Copyright IBM Corp. 2008,2014
+ * Copyright IBM Corp. 2008, 2015
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
 #include <linux/signal.h>
 #include <linux/slab.h>
 #include <linux/bitmap.h>
+#include <linux/vmalloc.h>
 #include <asm/asm-offsets.h>
+#include <asm/dis.h>
 #include <asm/uaccess.h>
 #include <asm/sclp.h>
+#include <asm/isc.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
 #include "trace-s390.h"
 #define PFAULT_DONE 0x0680
 #define VIRTIO_PARAM 0x0d00
 
-static int is_ioint(u64 type)
-{
-       return ((type & 0xfffe0000u) != 0xfffe0000u);
-}
-
 int psw_extint_disabled(struct kvm_vcpu *vcpu)
 {
        return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT);
@@ -72,70 +70,45 @@ static int ckc_interrupts_enabled(struct kvm_vcpu *vcpu)
        return 1;
 }
 
-static u64 int_word_to_isc_bits(u32 int_word)
+static int ckc_irq_pending(struct kvm_vcpu *vcpu)
+{
+       if (!(vcpu->arch.sie_block->ckc <
+             get_tod_clock_fast() + vcpu->arch.sie_block->epoch))
+               return 0;
+       return ckc_interrupts_enabled(vcpu);
+}
+
+static int cpu_timer_interrupts_enabled(struct kvm_vcpu *vcpu)
+{
+       return !psw_extint_disabled(vcpu) &&
+              (vcpu->arch.sie_block->gcr[0] & 0x400ul);
+}
+
+static int cpu_timer_irq_pending(struct kvm_vcpu *vcpu)
+{
+       return (vcpu->arch.sie_block->cputm >> 63) &&
+              cpu_timer_interrupts_enabled(vcpu);
+}
+
+static inline int is_ioirq(unsigned long irq_type)
 {
-       u8 isc = (int_word & 0x38000000) >> 27;
+       return ((irq_type >= IRQ_PEND_IO_ISC_0) &&
+               (irq_type <= IRQ_PEND_IO_ISC_7));
+}
 
+static uint64_t isc_to_isc_bits(int isc)
+{
        return (0x80 >> isc) << 24;
 }
 
-static int __must_check __interrupt_is_deliverable(struct kvm_vcpu *vcpu,
-                                     struct kvm_s390_interrupt_info *inti)
+static inline u8 int_word_to_isc(u32 int_word)
 {
-       switch (inti->type) {
-       case KVM_S390_INT_EXTERNAL_CALL:
-               if (psw_extint_disabled(vcpu))
-                       return 0;
-               if (vcpu->arch.sie_block->gcr[0] & 0x2000ul)
-                       return 1;
-               return 0;
-       case KVM_S390_INT_EMERGENCY:
-               if (psw_extint_disabled(vcpu))
-                       return 0;
-               if (vcpu->arch.sie_block->gcr[0] & 0x4000ul)
-                       return 1;
-               return 0;
-       case KVM_S390_INT_CLOCK_COMP:
-               return ckc_interrupts_enabled(vcpu);
-       case KVM_S390_INT_CPU_TIMER:
-               if (psw_extint_disabled(vcpu))
-                       return 0;
-               if (vcpu->arch.sie_block->gcr[0] & 0x400ul)
-                       return 1;
-               return 0;
-       case KVM_S390_INT_SERVICE:
-       case KVM_S390_INT_PFAULT_INIT:
-       case KVM_S390_INT_PFAULT_DONE:
-       case KVM_S390_INT_VIRTIO:
-               if (psw_extint_disabled(vcpu))
-                       return 0;
-               if (vcpu->arch.sie_block->gcr[0] & 0x200ul)
-                       return 1;
-               return 0;
-       case KVM_S390_PROGRAM_INT:
-       case KVM_S390_SIGP_STOP:
-       case KVM_S390_SIGP_SET_PREFIX:
-       case KVM_S390_RESTART:
-               return 1;
-       case KVM_S390_MCHK:
-               if (psw_mchk_disabled(vcpu))
-                       return 0;
-               if (vcpu->arch.sie_block->gcr[14] & inti->mchk.cr14)
-                       return 1;
-               return 0;
-       case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
-               if (psw_ioint_disabled(vcpu))
-                       return 0;
-               if (vcpu->arch.sie_block->gcr[6] &
-                   int_word_to_isc_bits(inti->io.io_int_word))
-                       return 1;
-               return 0;
-       default:
-               printk(KERN_WARNING "illegal interrupt type %llx\n",
-                      inti->type);
-               BUG();
-       }
-       return 0;
+       return (int_word & 0x38000000) >> 27;
+}
+
+static inline unsigned long pending_floating_irqs(struct kvm_vcpu *vcpu)
+{
+       return vcpu->kvm->arch.float_int.pending_irqs;
 }
 
 static inline unsigned long pending_local_irqs(struct kvm_vcpu *vcpu)
@@ -143,12 +116,31 @@ static inline unsigned long pending_local_irqs(struct kvm_vcpu *vcpu)
        return vcpu->arch.local_int.pending_irqs;
 }
 
-static unsigned long deliverable_local_irqs(struct kvm_vcpu *vcpu)
+static unsigned long disable_iscs(struct kvm_vcpu *vcpu,
+                                  unsigned long active_mask)
+{
+       int i;
+
+       for (i = 0; i <= MAX_ISC; i++)
+               if (!(vcpu->arch.sie_block->gcr[6] & isc_to_isc_bits(i)))
+                       active_mask &= ~(1UL << (IRQ_PEND_IO_ISC_0 + i));
+
+       return active_mask;
+}
+
+static unsigned long deliverable_irqs(struct kvm_vcpu *vcpu)
 {
-       unsigned long active_mask = pending_local_irqs(vcpu);
+       unsigned long active_mask;
+
+       active_mask = pending_local_irqs(vcpu);
+       active_mask |= pending_floating_irqs(vcpu);
 
        if (psw_extint_disabled(vcpu))
                active_mask &= ~IRQ_PEND_EXT_MASK;
+       if (psw_ioint_disabled(vcpu))
+               active_mask &= ~IRQ_PEND_IO_MASK;
+       else
+               active_mask = disable_iscs(vcpu, active_mask);
        if (!(vcpu->arch.sie_block->gcr[0] & 0x2000ul))
                __clear_bit(IRQ_PEND_EXT_EXTERNAL, &active_mask);
        if (!(vcpu->arch.sie_block->gcr[0] & 0x4000ul))
@@ -157,8 +149,13 @@ static unsigned long deliverable_local_irqs(struct kvm_vcpu *vcpu)
                __clear_bit(IRQ_PEND_EXT_CLOCK_COMP, &active_mask);
        if (!(vcpu->arch.sie_block->gcr[0] & 0x400ul))
                __clear_bit(IRQ_PEND_EXT_CPU_TIMER, &active_mask);
+       if (!(vcpu->arch.sie_block->gcr[0] & 0x200ul))
+               __clear_bit(IRQ_PEND_EXT_SERVICE, &active_mask);
        if (psw_mchk_disabled(vcpu))
                active_mask &= ~IRQ_PEND_MCHK_MASK;
+       if (!(vcpu->arch.sie_block->gcr[14] &
+             vcpu->kvm->arch.float_int.mchk.cr14))
+               __clear_bit(IRQ_PEND_MCHK_REP, &active_mask);
 
        /*
         * STOP irqs will never be actively delivered. They are triggered via
@@ -200,6 +197,16 @@ static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag)
        atomic_set_mask(flag, &vcpu->arch.sie_block->cpuflags);
 }
 
+static void set_intercept_indicators_io(struct kvm_vcpu *vcpu)
+{
+       if (!(pending_floating_irqs(vcpu) & IRQ_PEND_IO_MASK))
+               return;
+       else if (psw_ioint_disabled(vcpu))
+               __set_cpuflag(vcpu, CPUSTAT_IO_INT);
+       else
+               vcpu->arch.sie_block->lctl |= LCTL_CR6;
+}
+
 static void set_intercept_indicators_ext(struct kvm_vcpu *vcpu)
 {
        if (!(pending_local_irqs(vcpu) & IRQ_PEND_EXT_MASK))
@@ -226,47 +233,17 @@ static void set_intercept_indicators_stop(struct kvm_vcpu *vcpu)
                __set_cpuflag(vcpu, CPUSTAT_STOP_INT);
 }
 
-/* Set interception request for non-deliverable local interrupts */
-static void set_intercept_indicators_local(struct kvm_vcpu *vcpu)
+/* Set interception request for non-deliverable interrupts */
+static void set_intercept_indicators(struct kvm_vcpu *vcpu)
 {
+       set_intercept_indicators_io(vcpu);
        set_intercept_indicators_ext(vcpu);
        set_intercept_indicators_mchk(vcpu);
        set_intercept_indicators_stop(vcpu);
 }
 
-static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
-                                     struct kvm_s390_interrupt_info *inti)
-{
-       switch (inti->type) {
-       case KVM_S390_INT_SERVICE:
-       case KVM_S390_INT_PFAULT_DONE:
-       case KVM_S390_INT_VIRTIO:
-               if (psw_extint_disabled(vcpu))
-                       __set_cpuflag(vcpu, CPUSTAT_EXT_INT);
-               else
-                       vcpu->arch.sie_block->lctl |= LCTL_CR0;
-               break;
-       case KVM_S390_MCHK:
-               if (psw_mchk_disabled(vcpu))
-                       vcpu->arch.sie_block->ictl |= ICTL_LPSW;
-               else
-                       vcpu->arch.sie_block->lctl |= LCTL_CR14;
-               break;
-       case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
-               if (psw_ioint_disabled(vcpu))
-                       __set_cpuflag(vcpu, CPUSTAT_IO_INT);
-               else
-                       vcpu->arch.sie_block->lctl |= LCTL_CR6;
-               break;
-       default:
-               BUG();
-       }
-}
-
 static u16 get_ilc(struct kvm_vcpu *vcpu)
 {
-       const unsigned short table[] = { 2, 4, 4, 6 };
-
        switch (vcpu->arch.sie_block->icptcode) {
        case ICPT_INST:
        case ICPT_INSTPROGI:
@@ -274,7 +251,7 @@ static u16 get_ilc(struct kvm_vcpu *vcpu)
        case ICPT_PARTEXEC:
        case ICPT_IOINST:
                /* last instruction only stored for these icptcodes */
-               return table[vcpu->arch.sie_block->ipa >> 14];
+               return insn_length(vcpu->arch.sie_block->ipa >> 8);
        case ICPT_PROGI:
                return vcpu->arch.sie_block->pgmilc;
        default:
@@ -350,38 +327,72 @@ static int __must_check __deliver_pfault_init(struct kvm_vcpu *vcpu)
 
 static int __must_check __deliver_machine_check(struct kvm_vcpu *vcpu)
 {
+       struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
-       struct kvm_s390_mchk_info mchk;
-       int rc;
+       struct kvm_s390_mchk_info mchk = {};
+       unsigned long adtl_status_addr;
+       int deliver = 0;
+       int rc = 0;
 
+       spin_lock(&fi->lock);
        spin_lock(&li->lock);
-       mchk = li->irq.mchk;
+       if (test_bit(IRQ_PEND_MCHK_EX, &li->pending_irqs) ||
+           test_bit(IRQ_PEND_MCHK_REP, &li->pending_irqs)) {
+               /*
+                * If there was an exigent machine check pending, then any
+                * repressible machine checks that might have been pending
+                * are indicated along with it, so always clear bits for
+                * repressible and exigent interrupts
+                */
+               mchk = li->irq.mchk;
+               clear_bit(IRQ_PEND_MCHK_EX, &li->pending_irqs);
+               clear_bit(IRQ_PEND_MCHK_REP, &li->pending_irqs);
+               memset(&li->irq.mchk, 0, sizeof(mchk));
+               deliver = 1;
+       }
        /*
-        * If there was an exigent machine check pending, then any repressible
-        * machine checks that might have been pending are indicated along
-        * with it, so always clear both bits
+        * We indicate floating repressible conditions along with
+        * other pending conditions. Channel Report Pending and Channel
+        * Subsystem damage are the only two and and are indicated by
+        * bits in mcic and masked in cr14.
         */
-       clear_bit(IRQ_PEND_MCHK_EX, &li->pending_irqs);
-       clear_bit(IRQ_PEND_MCHK_REP, &li->pending_irqs);
-       memset(&li->irq.mchk, 0, sizeof(mchk));
+       if (test_and_clear_bit(IRQ_PEND_MCHK_REP, &fi->pending_irqs)) {
+               mchk.mcic |= fi->mchk.mcic;
+               mchk.cr14 |= fi->mchk.cr14;
+               memset(&fi->mchk, 0, sizeof(mchk));
+               deliver = 1;
+       }
        spin_unlock(&li->lock);
+       spin_unlock(&fi->lock);
 
-       VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx",
-                  mchk.mcic);
-       trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_MCHK,
-                                        mchk.cr14, mchk.mcic);
-
-       rc  = kvm_s390_vcpu_store_status(vcpu, KVM_S390_STORE_STATUS_PREFIXED);
-       rc |= put_guest_lc(vcpu, mchk.mcic,
-                          (u64 __user *) __LC_MCCK_CODE);
-       rc |= put_guest_lc(vcpu, mchk.failing_storage_address,
-                          (u64 __user *) __LC_MCCK_FAIL_STOR_ADDR);
-       rc |= write_guest_lc(vcpu, __LC_PSW_SAVE_AREA,
-                            &mchk.fixed_logout, sizeof(mchk.fixed_logout));
-       rc |= write_guest_lc(vcpu, __LC_MCK_OLD_PSW,
-                            &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-       rc |= read_guest_lc(vcpu, __LC_MCK_NEW_PSW,
-                           &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+       if (deliver) {
+               VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx",
+                          mchk.mcic);
+               trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
+                                                KVM_S390_MCHK,
+                                                mchk.cr14, mchk.mcic);
+
+               rc  = kvm_s390_vcpu_store_status(vcpu,
+                                                KVM_S390_STORE_STATUS_PREFIXED);
+               rc |= read_guest_lc(vcpu, __LC_VX_SAVE_AREA_ADDR,
+                                   &adtl_status_addr,
+                                   sizeof(unsigned long));
+               rc |= kvm_s390_vcpu_store_adtl_status(vcpu,
+                                                     adtl_status_addr);
+               rc |= put_guest_lc(vcpu, mchk.mcic,
+                                  (u64 __user *) __LC_MCCK_CODE);
+               rc |= put_guest_lc(vcpu, mchk.failing_storage_address,
+                                  (u64 __user *) __LC_MCCK_FAIL_STOR_ADDR);
+               rc |= write_guest_lc(vcpu, __LC_PSW_SAVE_AREA,
+                                    &mchk.fixed_logout,
+                                    sizeof(mchk.fixed_logout));
+               rc |= write_guest_lc(vcpu, __LC_MCK_OLD_PSW,
+                                    &vcpu->arch.sie_block->gpsw,
+                                    sizeof(psw_t));
+               rc |= read_guest_lc(vcpu, __LC_MCK_NEW_PSW,
+                                   &vcpu->arch.sie_block->gpsw,
+                                   sizeof(psw_t));
+       }
        return rc ? -EFAULT : 0;
 }
 
@@ -484,7 +495,7 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
 {
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
        struct kvm_s390_pgm_info pgm_info;
-       int rc = 0;
+       int rc = 0, nullifying = false;
        u16 ilc = get_ilc(vcpu);
 
        spin_lock(&li->lock);
@@ -509,6 +520,8 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
        case PGM_LX_TRANSLATION:
        case PGM_PRIMARY_AUTHORITY:
        case PGM_SECONDARY_AUTHORITY:
+               nullifying = true;
+               /* fall through */
        case PGM_SPACE_SWITCH:
                rc = put_guest_lc(vcpu, pgm_info.trans_exc_code,
                                  (u64 *)__LC_TRANS_EXC_CODE);
@@ -521,6 +534,7 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
        case PGM_EXTENDED_AUTHORITY:
                rc = put_guest_lc(vcpu, pgm_info.exc_access_id,
                                  (u8 *)__LC_EXC_ACCESS_ID);
+               nullifying = true;
                break;
        case PGM_ASCE_TYPE:
        case PGM_PAGE_TRANSLATION:
@@ -534,6 +548,7 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
                                   (u8 *)__LC_EXC_ACCESS_ID);
                rc |= put_guest_lc(vcpu, pgm_info.op_access_id,
                                   (u8 *)__LC_OP_ACCESS_ID);
+               nullifying = true;
                break;
        case PGM_MONITOR:
                rc = put_guest_lc(vcpu, pgm_info.mon_class_nr,
@@ -541,6 +556,7 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
                rc |= put_guest_lc(vcpu, pgm_info.mon_code,
                                   (u64 *)__LC_MON_CODE);
                break;
+       case PGM_VECTOR_PROCESSING:
        case PGM_DATA:
                rc = put_guest_lc(vcpu, pgm_info.data_exc_code,
                                  (u32 *)__LC_DATA_EXC_CODE);
@@ -551,6 +567,15 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
                rc |= put_guest_lc(vcpu, pgm_info.exc_access_id,
                                   (u8 *)__LC_EXC_ACCESS_ID);
                break;
+       case PGM_STACK_FULL:
+       case PGM_STACK_EMPTY:
+       case PGM_STACK_SPECIFICATION:
+       case PGM_STACK_TYPE:
+       case PGM_STACK_OPERATION:
+       case PGM_TRACE_TABEL:
+       case PGM_CRYPTO_OPERATION:
+               nullifying = true;
+               break;
        }
 
        if (pgm_info.code & PGM_PER) {
@@ -564,7 +589,12 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
                                   (u8 *) __LC_PER_ACCESS_ID);
        }
 
+       if (nullifying && vcpu->arch.sie_block->icptcode == ICPT_INST)
+               kvm_s390_rewind_psw(vcpu, ilc);
+
        rc |= put_guest_lc(vcpu, ilc, (u16 *) __LC_PGM_ILC);
+       rc |= put_guest_lc(vcpu, vcpu->arch.sie_block->gbea,
+                                (u64 *) __LC_LAST_BREAK);
        rc |= put_guest_lc(vcpu, pgm_info.code,
                           (u16 *)__LC_PGM_INT_CODE);
        rc |= write_guest_lc(vcpu, __LC_PGM_OLD_PSW,
@@ -574,16 +604,27 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
        return rc ? -EFAULT : 0;
 }
 
-static int __must_check __deliver_service(struct kvm_vcpu *vcpu,
-                                         struct kvm_s390_interrupt_info *inti)
+static int __must_check __deliver_service(struct kvm_vcpu *vcpu)
 {
-       int rc;
+       struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+       struct kvm_s390_ext_info ext;
+       int rc = 0;
+
+       spin_lock(&fi->lock);
+       if (!(test_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs))) {
+               spin_unlock(&fi->lock);
+               return 0;
+       }
+       ext = fi->srv_signal;
+       memset(&fi->srv_signal, 0, sizeof(ext));
+       clear_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs);
+       spin_unlock(&fi->lock);
 
        VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
-                  inti->ext.ext_params);
+                  ext.ext_params);
        vcpu->stat.deliver_service_signal++;
-       trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
-                                        inti->ext.ext_params, 0);
+       trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_SERVICE,
+                                        ext.ext_params, 0);
 
        rc  = put_guest_lc(vcpu, EXT_IRQ_SERVICE_SIG, (u16 *)__LC_EXT_INT_CODE);
        rc |= put_guest_lc(vcpu, 0, (u16 *)__LC_EXT_CPU_ADDR);
@@ -591,106 +632,146 @@ static int __must_check __deliver_service(struct kvm_vcpu *vcpu,
                             &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
        rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
                            &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-       rc |= put_guest_lc(vcpu, inti->ext.ext_params,
+       rc |= put_guest_lc(vcpu, ext.ext_params,
                           (u32 *)__LC_EXT_PARAMS);
+
        return rc ? -EFAULT : 0;
 }
 
-static int __must_check __deliver_pfault_done(struct kvm_vcpu *vcpu,
-                                          struct kvm_s390_interrupt_info *inti)
+static int __must_check __deliver_pfault_done(struct kvm_vcpu *vcpu)
 {
-       int rc;
+       struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+       struct kvm_s390_interrupt_info *inti;
+       int rc = 0;
 
-       trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
-                                        KVM_S390_INT_PFAULT_DONE, 0,
-                                        inti->ext.ext_params2);
+       spin_lock(&fi->lock);
+       inti = list_first_entry_or_null(&fi->lists[FIRQ_LIST_PFAULT],
+                                       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;
+       }
+       if (list_empty(&fi->lists[FIRQ_LIST_PFAULT]))
+               clear_bit(IRQ_PEND_PFAULT_DONE, &fi->pending_irqs);
+       spin_unlock(&fi->lock);
 
-       rc  = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, (u16 *)__LC_EXT_INT_CODE);
-       rc |= put_guest_lc(vcpu, PFAULT_DONE, (u16 *)__LC_EXT_CPU_ADDR);
-       rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
-                            &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-       rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
-                           &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-       rc |= put_guest_lc(vcpu, inti->ext.ext_params2,
-                          (u64 *)__LC_EXT_PARAMS2);
+       if (inti) {
+               rc  = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE,
+                               (u16 *)__LC_EXT_INT_CODE);
+               rc |= put_guest_lc(vcpu, PFAULT_DONE,
+                               (u16 *)__LC_EXT_CPU_ADDR);
+               rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
+                               &vcpu->arch.sie_block->gpsw,
+                               sizeof(psw_t));
+               rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
+                               &vcpu->arch.sie_block->gpsw,
+                               sizeof(psw_t));
+               rc |= put_guest_lc(vcpu, inti->ext.ext_params2,
+                               (u64 *)__LC_EXT_PARAMS2);
+               kfree(inti);
+       }
        return rc ? -EFAULT : 0;
 }
 
-static int __must_check __deliver_virtio(struct kvm_vcpu *vcpu,
-                                        struct kvm_s390_interrupt_info *inti)
+static int __must_check __deliver_virtio(struct kvm_vcpu *vcpu)
 {
-       int rc;
+       struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+       struct kvm_s390_interrupt_info *inti;
+       int rc = 0;
 
-       VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx",
-                  inti->ext.ext_params, inti->ext.ext_params2);
-       vcpu->stat.deliver_virtio_interrupt++;
-       trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
-                                        inti->ext.ext_params,
-                                        inti->ext.ext_params2);
+       spin_lock(&fi->lock);
+       inti = list_first_entry_or_null(&fi->lists[FIRQ_LIST_VIRTIO],
+                                       struct kvm_s390_interrupt_info,
+                                       list);
+       if (inti) {
+               VCPU_EVENT(vcpu, 4,
+                          "interrupt: virtio parm:%x,parm64:%llx",
+                          inti->ext.ext_params, inti->ext.ext_params2);
+               vcpu->stat.deliver_virtio_interrupt++;
+               trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
+                               inti->type,
+                               inti->ext.ext_params,
+                               inti->ext.ext_params2);
+               list_del(&inti->list);
+               fi->counters[FIRQ_CNTR_VIRTIO] -= 1;
+       }
+       if (list_empty(&fi->lists[FIRQ_LIST_VIRTIO]))
+               clear_bit(IRQ_PEND_VIRTIO, &fi->pending_irqs);
+       spin_unlock(&fi->lock);
 
-       rc  = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, (u16 *)__LC_EXT_INT_CODE);
-       rc |= put_guest_lc(vcpu, VIRTIO_PARAM, (u16 *)__LC_EXT_CPU_ADDR);
-       rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
-                            &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-       rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
-                           &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-       rc |= put_guest_lc(vcpu, inti->ext.ext_params,
-                          (u32 *)__LC_EXT_PARAMS);
-       rc |= put_guest_lc(vcpu, inti->ext.ext_params2,
-                          (u64 *)__LC_EXT_PARAMS2);
+       if (inti) {
+               rc  = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE,
+                               (u16 *)__LC_EXT_INT_CODE);
+               rc |= put_guest_lc(vcpu, VIRTIO_PARAM,
+                               (u16 *)__LC_EXT_CPU_ADDR);
+               rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
+                               &vcpu->arch.sie_block->gpsw,
+                               sizeof(psw_t));
+               rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
+                               &vcpu->arch.sie_block->gpsw,
+                               sizeof(psw_t));
+               rc |= put_guest_lc(vcpu, inti->ext.ext_params,
+                               (u32 *)__LC_EXT_PARAMS);
+               rc |= put_guest_lc(vcpu, inti->ext.ext_params2,
+                               (u64 *)__LC_EXT_PARAMS2);
+               kfree(inti);
+       }
        return rc ? -EFAULT : 0;
 }
 
 static int __must_check __deliver_io(struct kvm_vcpu *vcpu,
-                                    struct kvm_s390_interrupt_info *inti)
+                                    unsigned long irq_type)
 {
-       int rc;
+       struct list_head *isc_list;
+       struct kvm_s390_float_interrupt *fi;
+       struct kvm_s390_interrupt_info *inti = NULL;
+       int rc = 0;
 
-       VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type);
-       vcpu->stat.deliver_io_int++;
-       trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
-                                        ((__u32)inti->io.subchannel_id << 16) |
-                                               inti->io.subchannel_nr,
-                                        ((__u64)inti->io.io_int_parm << 32) |
-                                               inti->io.io_int_word);
-
-       rc  = put_guest_lc(vcpu, inti->io.subchannel_id,
-                          (u16 *)__LC_SUBCHANNEL_ID);
-       rc |= put_guest_lc(vcpu, inti->io.subchannel_nr,
-                          (u16 *)__LC_SUBCHANNEL_NR);
-       rc |= put_guest_lc(vcpu, inti->io.io_int_parm,
-                          (u32 *)__LC_IO_INT_PARM);
-       rc |= put_guest_lc(vcpu, inti->io.io_int_word,
-                          (u32 *)__LC_IO_INT_WORD);
-       rc |= write_guest_lc(vcpu, __LC_IO_OLD_PSW,
-                            &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-       rc |= read_guest_lc(vcpu, __LC_IO_NEW_PSW,
-                           &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-       return rc ? -EFAULT : 0;
-}
+       fi = &vcpu->kvm->arch.float_int;
 
-static int __must_check __deliver_mchk_floating(struct kvm_vcpu *vcpu,
-                                          struct kvm_s390_interrupt_info *inti)
-{
-       struct kvm_s390_mchk_info *mchk = &inti->mchk;
-       int rc;
+       spin_lock(&fi->lock);
+       isc_list = &fi->lists[irq_type - IRQ_PEND_IO_ISC_0];
+       inti = list_first_entry_or_null(isc_list,
+                                       struct kvm_s390_interrupt_info,
+                                       list);
+       if (inti) {
+               VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type);
+               vcpu->stat.deliver_io_int++;
+               trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
+                               inti->type,
+                               ((__u32)inti->io.subchannel_id << 16) |
+                               inti->io.subchannel_nr,
+                               ((__u64)inti->io.io_int_parm << 32) |
+                               inti->io.io_int_word);
+               list_del(&inti->list);
+               fi->counters[FIRQ_CNTR_IO] -= 1;
+       }
+       if (list_empty(isc_list))
+               clear_bit(irq_type, &fi->pending_irqs);
+       spin_unlock(&fi->lock);
+
+       if (inti) {
+               rc  = put_guest_lc(vcpu, inti->io.subchannel_id,
+                               (u16 *)__LC_SUBCHANNEL_ID);
+               rc |= put_guest_lc(vcpu, inti->io.subchannel_nr,
+                               (u16 *)__LC_SUBCHANNEL_NR);
+               rc |= put_guest_lc(vcpu, inti->io.io_int_parm,
+                               (u32 *)__LC_IO_INT_PARM);
+               rc |= put_guest_lc(vcpu, inti->io.io_int_word,
+                               (u32 *)__LC_IO_INT_WORD);
+               rc |= write_guest_lc(vcpu, __LC_IO_OLD_PSW,
+                               &vcpu->arch.sie_block->gpsw,
+                               sizeof(psw_t));
+               rc |= read_guest_lc(vcpu, __LC_IO_NEW_PSW,
+                               &vcpu->arch.sie_block->gpsw,
+                               sizeof(psw_t));
+               kfree(inti);
+       }
 
-       VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx",
-                  mchk->mcic);
-       trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_MCHK,
-                                        mchk->cr14, mchk->mcic);
-
-       rc  = kvm_s390_vcpu_store_status(vcpu, KVM_S390_STORE_STATUS_PREFIXED);
-       rc |= put_guest_lc(vcpu, mchk->mcic,
-                       (u64 __user *) __LC_MCCK_CODE);
-       rc |= put_guest_lc(vcpu, mchk->failing_storage_address,
-                       (u64 __user *) __LC_MCCK_FAIL_STOR_ADDR);
-       rc |= write_guest_lc(vcpu, __LC_PSW_SAVE_AREA,
-                            &mchk->fixed_logout, sizeof(mchk->fixed_logout));
-       rc |= write_guest_lc(vcpu, __LC_MCK_OLD_PSW,
-                            &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-       rc |= read_guest_lc(vcpu, __LC_MCK_NEW_PSW,
-                           &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
        return rc ? -EFAULT : 0;
 }
 
@@ -698,6 +779,7 @@ typedef int (*deliver_irq_t)(struct kvm_vcpu *vcpu);
 
 static const deliver_irq_t deliver_irq_funcs[] = {
        [IRQ_PEND_MCHK_EX]        = __deliver_machine_check,
+       [IRQ_PEND_MCHK_REP]       = __deliver_machine_check,
        [IRQ_PEND_PROG]           = __deliver_prog,
        [IRQ_PEND_EXT_EMERGENCY]  = __deliver_emergency_signal,
        [IRQ_PEND_EXT_EXTERNAL]   = __deliver_external_call,
@@ -706,36 +788,11 @@ static const deliver_irq_t deliver_irq_funcs[] = {
        [IRQ_PEND_RESTART]        = __deliver_restart,
        [IRQ_PEND_SET_PREFIX]     = __deliver_set_prefix,
        [IRQ_PEND_PFAULT_INIT]    = __deliver_pfault_init,
+       [IRQ_PEND_EXT_SERVICE]    = __deliver_service,
+       [IRQ_PEND_PFAULT_DONE]    = __deliver_pfault_done,
+       [IRQ_PEND_VIRTIO]         = __deliver_virtio,
 };
 
-static int __must_check __deliver_floating_interrupt(struct kvm_vcpu *vcpu,
-                                          struct kvm_s390_interrupt_info *inti)
-{
-       int rc;
-
-       switch (inti->type) {
-       case KVM_S390_INT_SERVICE:
-               rc = __deliver_service(vcpu, inti);
-               break;
-       case KVM_S390_INT_PFAULT_DONE:
-               rc = __deliver_pfault_done(vcpu, inti);
-               break;
-       case KVM_S390_INT_VIRTIO:
-               rc = __deliver_virtio(vcpu, inti);
-               break;
-       case KVM_S390_MCHK:
-               rc = __deliver_mchk_floating(vcpu, inti);
-               break;
-       case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
-               rc = __deliver_io(vcpu, inti);
-               break;
-       default:
-               BUG();
-       }
-
-       return rc;
-}
-
 /* Check whether an external call is pending (deliverable or not) */
 int kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu)
 {
@@ -751,21 +808,9 @@ int kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu)
 
 int kvm_s390_vcpu_has_irq(struct kvm_vcpu *vcpu, int exclude_stop)
 {
-       struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int;
-       struct kvm_s390_interrupt_info  *inti;
        int rc;
 
-       rc = !!deliverable_local_irqs(vcpu);
-
-       if ((!rc) && atomic_read(&fi->active)) {
-               spin_lock(&fi->lock);
-               list_for_each_entry(inti, &fi->list, list)
-                       if (__interrupt_is_deliverable(vcpu, inti)) {
-                               rc = 1;
-                               break;
-                       }
-               spin_unlock(&fi->lock);
-       }
+       rc = !!deliverable_irqs(vcpu);
 
        if (!rc && kvm_cpu_has_pending_timer(vcpu))
                rc = 1;
@@ -784,12 +829,7 @@ int kvm_s390_vcpu_has_irq(struct kvm_vcpu *vcpu, int exclude_stop)
 
 int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 {
-       if (!(vcpu->arch.sie_block->ckc <
-             get_tod_clock_fast() + vcpu->arch.sie_block->epoch))
-               return 0;
-       if (!ckc_interrupts_enabled(vcpu))
-               return 0;
-       return 1;
+       return ckc_irq_pending(vcpu) || cpu_timer_irq_pending(vcpu);
 }
 
 int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
@@ -884,60 +924,45 @@ void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu)
 int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
 {
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
-       struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int;
-       struct kvm_s390_interrupt_info  *n, *inti = NULL;
        deliver_irq_t func;
-       int deliver;
        int rc = 0;
        unsigned long irq_type;
-       unsigned long deliverable_irqs;
+       unsigned long irqs;
 
        __reset_intercept_indicators(vcpu);
 
        /* pending ckc conditions might have been invalidated */
        clear_bit(IRQ_PEND_EXT_CLOCK_COMP, &li->pending_irqs);
-       if (kvm_cpu_has_pending_timer(vcpu))
+       if (ckc_irq_pending(vcpu))
                set_bit(IRQ_PEND_EXT_CLOCK_COMP, &li->pending_irqs);
 
+       /* pending cpu timer conditions might have been invalidated */
+       clear_bit(IRQ_PEND_EXT_CPU_TIMER, &li->pending_irqs);
+       if (cpu_timer_irq_pending(vcpu))
+               set_bit(IRQ_PEND_EXT_CPU_TIMER, &li->pending_irqs);
+
        do {
-               deliverable_irqs = deliverable_local_irqs(vcpu);
+               irqs = deliverable_irqs(vcpu);
                /* bits are in the order of interrupt priority */
-               irq_type = find_first_bit(&deliverable_irqs, IRQ_PEND_COUNT);
+               irq_type = find_first_bit(&irqs, IRQ_PEND_COUNT);
                if (irq_type == IRQ_PEND_COUNT)
                        break;
-               func = deliver_irq_funcs[irq_type];
-               if (!func) {
-                       WARN_ON_ONCE(func == NULL);
-                       clear_bit(irq_type, &li->pending_irqs);
-                       continue;
+               if (is_ioirq(irq_type)) {
+                       rc = __deliver_io(vcpu, irq_type);
+               } else {
+                       func = deliver_irq_funcs[irq_type];
+                       if (!func) {
+                               WARN_ON_ONCE(func == NULL);
+                               clear_bit(irq_type, &li->pending_irqs);
+                               continue;
+                       }
+                       rc = func(vcpu);
                }
-               rc = func(vcpu);
-       } while (!rc && irq_type != IRQ_PEND_COUNT);
+               if (rc)
+                       break;
+       } while (!rc);
 
-       set_intercept_indicators_local(vcpu);
-
-       if (!rc && atomic_read(&fi->active)) {
-               do {
-                       deliver = 0;
-                       spin_lock(&fi->lock);
-                       list_for_each_entry_safe(inti, n, &fi->list, list) {
-                               if (__interrupt_is_deliverable(vcpu, inti)) {
-                                       list_del(&inti->list);
-                                       fi->irq_count--;
-                                       deliver = 1;
-                                       break;
-                               }
-                               __set_intercept_indicator(vcpu, inti);
-                       }
-                       if (list_empty(&fi->list))
-                               atomic_set(&fi->active, 0);
-                       spin_unlock(&fi->lock);
-                       if (deliver) {
-                               rc = __deliver_floating_interrupt(vcpu, inti);
-                               kfree(inti);
-                       }
-               } while (!rc && deliver);
-       }
+       set_intercept_indicators(vcpu);
 
        return rc;
 }
@@ -1172,80 +1197,182 @@ static int __inject_cpu_timer(struct kvm_vcpu *vcpu)
        return 0;
 }
 
+static struct kvm_s390_interrupt_info *get_io_int(struct kvm *kvm,
+                                                 int isc, u32 schid)
+{
+       struct kvm_s390_float_interrupt *fi = &kvm->arch.float_int;
+       struct list_head *isc_list = &fi->lists[FIRQ_LIST_IO_ISC_0 + isc];
+       struct kvm_s390_interrupt_info *iter;
+       u16 id = (schid & 0xffff0000U) >> 16;
+       u16 nr = schid & 0x0000ffffU;
 
+       spin_lock(&fi->lock);
+       list_for_each_entry(iter, isc_list, list) {
+               if (schid && (id != iter->io.subchannel_id ||
+                             nr != iter->io.subchannel_nr))
+                       continue;
+               /* found an appropriate entry */
+               list_del_init(&iter->list);
+               fi->counters[FIRQ_CNTR_IO] -= 1;
+               if (list_empty(isc_list))
+                       clear_bit(IRQ_PEND_IO_ISC_0 + isc, &fi->pending_irqs);
+               spin_unlock(&fi->lock);
+               return iter;
+       }
+       spin_unlock(&fi->lock);
+       return NULL;
+}
+
+/*
+ * Dequeue and return an I/O interrupt matching any of the interruption
+ * subclasses as designated by the isc mask in cr6 and the schid (if != 0).
+ */
 struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
-                                                   u64 cr6, u64 schid)
+                                                   u64 isc_mask, u32 schid)
+{
+       struct kvm_s390_interrupt_info *inti = NULL;
+       int isc;
+
+       for (isc = 0; isc <= MAX_ISC && !inti; isc++) {
+               if (isc_mask & isc_to_isc_bits(isc))
+                       inti = get_io_int(kvm, isc, schid);
+       }
+       return inti;
+}
+
+#define SCCB_MASK 0xFFFFFFF8
+#define SCCB_EVENT_PENDING 0x3
+
+static int __inject_service(struct kvm *kvm,
+                            struct kvm_s390_interrupt_info *inti)
+{
+       struct kvm_s390_float_interrupt *fi = &kvm->arch.float_int;
+
+       spin_lock(&fi->lock);
+       fi->srv_signal.ext_params |= inti->ext.ext_params & SCCB_EVENT_PENDING;
+       /*
+        * Early versions of the QEMU s390 bios will inject several
+        * service interrupts after another without handling a
+        * condition code indicating busy.
+        * We will silently ignore those superfluous sccb values.
+        * A future version of QEMU will take care of serialization
+        * of servc requests
+        */
+       if (fi->srv_signal.ext_params & SCCB_MASK)
+               goto out;
+       fi->srv_signal.ext_params |= inti->ext.ext_params & SCCB_MASK;
+       set_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs);
+out:
+       spin_unlock(&fi->lock);
+       kfree(inti);
+       return 0;
+}
+
+static int __inject_virtio(struct kvm *kvm,
+                           struct kvm_s390_interrupt_info *inti)
+{
+       struct kvm_s390_float_interrupt *fi = &kvm->arch.float_int;
+
+       spin_lock(&fi->lock);
+       if (fi->counters[FIRQ_CNTR_VIRTIO] >= KVM_S390_MAX_VIRTIO_IRQS) {
+               spin_unlock(&fi->lock);
+               return -EBUSY;
+       }
+       fi->counters[FIRQ_CNTR_VIRTIO] += 1;
+       list_add_tail(&inti->list, &fi->lists[FIRQ_LIST_VIRTIO]);
+       set_bit(IRQ_PEND_VIRTIO, &fi->pending_irqs);
+       spin_unlock(&fi->lock);
+       return 0;
+}
+
+static int __inject_pfault_done(struct kvm *kvm,
+                                struct kvm_s390_interrupt_info *inti)
+{
+       struct kvm_s390_float_interrupt *fi = &kvm->arch.float_int;
+
+       spin_lock(&fi->lock);
+       if (fi->counters[FIRQ_CNTR_PFAULT] >=
+               (ASYNC_PF_PER_VCPU * KVM_MAX_VCPUS)) {
+               spin_unlock(&fi->lock);
+               return -EBUSY;
+       }
+       fi->counters[FIRQ_CNTR_PFAULT] += 1;
+       list_add_tail(&inti->list, &fi->lists[FIRQ_LIST_PFAULT]);
+       set_bit(IRQ_PEND_PFAULT_DONE, &fi->pending_irqs);
+       spin_unlock(&fi->lock);
+       return 0;
+}
+
+#define CR_PENDING_SUBCLASS 28
+static int __inject_float_mchk(struct kvm *kvm,
+                               struct kvm_s390_interrupt_info *inti)
+{
+       struct kvm_s390_float_interrupt *fi = &kvm->arch.float_int;
+
+       spin_lock(&fi->lock);
+       fi->mchk.cr14 |= inti->mchk.cr14 & (1UL << CR_PENDING_SUBCLASS);
+       fi->mchk.mcic |= inti->mchk.mcic;
+       set_bit(IRQ_PEND_MCHK_REP, &fi->pending_irqs);
+       spin_unlock(&fi->lock);
+       kfree(inti);
+       return 0;
+}
+
+static int __inject_io(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
 {
        struct kvm_s390_float_interrupt *fi;
-       struct kvm_s390_interrupt_info *inti, *iter;
+       struct list_head *list;
+       int isc;
 
-       if ((!schid && !cr6) || (schid && cr6))
-               return NULL;
        fi = &kvm->arch.float_int;
        spin_lock(&fi->lock);
-       inti = NULL;
-       list_for_each_entry(iter, &fi->list, list) {
-               if (!is_ioint(iter->type))
-                       continue;
-               if (cr6 &&
-                   ((cr6 & int_word_to_isc_bits(iter->io.io_int_word)) == 0))
-                       continue;
-               if (schid) {
-                       if (((schid & 0x00000000ffff0000) >> 16) !=
-                           iter->io.subchannel_id)
-                               continue;
-                       if ((schid & 0x000000000000ffff) !=
-                           iter->io.subchannel_nr)
-                               continue;
-               }
-               inti = iter;
-               break;
-       }
-       if (inti) {
-               list_del_init(&inti->list);
-               fi->irq_count--;
+       if (fi->counters[FIRQ_CNTR_IO] >= KVM_S390_MAX_FLOAT_IRQS) {
+               spin_unlock(&fi->lock);
+               return -EBUSY;
        }
-       if (list_empty(&fi->list))
-               atomic_set(&fi->active, 0);
+       fi->counters[FIRQ_CNTR_IO] += 1;
+
+       isc = int_word_to_isc(inti->io.io_int_word);
+       list = &fi->lists[FIRQ_LIST_IO_ISC_0 + isc];
+       list_add_tail(&inti->list, list);
+       set_bit(IRQ_PEND_IO_ISC_0 + isc, &fi->pending_irqs);
        spin_unlock(&fi->lock);
-       return inti;
+       return 0;
 }
 
 static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
 {
        struct kvm_s390_local_interrupt *li;
        struct kvm_s390_float_interrupt *fi;
-       struct kvm_s390_interrupt_info *iter;
        struct kvm_vcpu *dst_vcpu = NULL;
        int sigcpu;
-       int rc = 0;
+       u64 type = READ_ONCE(inti->type);
+       int rc;
 
        fi = &kvm->arch.float_int;
-       spin_lock(&fi->lock);
-       if (fi->irq_count >= KVM_S390_MAX_FLOAT_IRQS) {
+
+       switch (type) {
+       case KVM_S390_MCHK:
+               rc = __inject_float_mchk(kvm, inti);
+               break;
+       case KVM_S390_INT_VIRTIO:
+               rc = __inject_virtio(kvm, inti);
+               break;
+       case KVM_S390_INT_SERVICE:
+               rc = __inject_service(kvm, inti);
+               break;
+       case KVM_S390_INT_PFAULT_DONE:
+               rc = __inject_pfault_done(kvm, inti);
+               break;
+       case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
+               rc = __inject_io(kvm, inti);
+               break;
+       default:
                rc = -EINVAL;
-               goto unlock_fi;
        }
-       fi->irq_count++;
-       if (!is_ioint(inti->type)) {
-               list_add_tail(&inti->list, &fi->list);
-       } else {
-               u64 isc_bits = int_word_to_isc_bits(inti->io.io_int_word);
+       if (rc)
+               return rc;
 
-               /* Keep I/O interrupts sorted in isc order. */
-               list_for_each_entry(iter, &fi->list, list) {
-                       if (!is_ioint(iter->type))
-                               continue;
-                       if (int_word_to_isc_bits(iter->io.io_int_word)
-                           <= isc_bits)
-                               continue;
-                       break;
-               }
-               list_add_tail(&inti->list, &iter->list);
-       }
-       atomic_set(&fi->active, 1);
-       if (atomic_read(&kvm->online_vcpus) == 0)
-               goto unlock_fi;
        sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS);
        if (sigcpu == KVM_MAX_VCPUS) {
                do {
@@ -1257,7 +1384,7 @@ static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
        dst_vcpu = kvm_get_vcpu(kvm, sigcpu);
        li = &dst_vcpu->arch.local_int;
        spin_lock(&li->lock);
-       switch (inti->type) {
+       switch (type) {
        case KVM_S390_MCHK:
                atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
                break;
@@ -1270,9 +1397,8 @@ static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
        }
        spin_unlock(&li->lock);
        kvm_s390_vcpu_wakeup(kvm_get_vcpu(kvm, sigcpu));
-unlock_fi:
-       spin_unlock(&fi->lock);
-       return rc;
+       return 0;
+
 }
 
 int kvm_s390_inject_vm(struct kvm *kvm,
@@ -1332,10 +1458,10 @@ int kvm_s390_inject_vm(struct kvm *kvm,
        return rc;
 }
 
-void kvm_s390_reinject_io_int(struct kvm *kvm,
+int kvm_s390_reinject_io_int(struct kvm *kvm,
                              struct kvm_s390_interrupt_info *inti)
 {
-       __inject_vm(kvm, inti);
+       return __inject_vm(kvm, inti);
 }
 
 int s390int_to_s390irq(struct kvm_s390_interrupt *s390int,
@@ -1388,12 +1514,10 @@ void kvm_s390_clear_stop_irq(struct kvm_vcpu *vcpu)
        spin_unlock(&li->lock);
 }
 
-int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
+static int do_inject_vcpu(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
 {
-       struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
        int rc;
 
-       spin_lock(&li->lock);
        switch (irq->type) {
        case KVM_S390_PROGRAM_INT:
                VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)",
@@ -1433,83 +1557,130 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
        default:
                rc = -EINVAL;
        }
+
+       return rc;
+}
+
+int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
+{
+       struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
+       int rc;
+
+       spin_lock(&li->lock);
+       rc = do_inject_vcpu(vcpu, irq);
        spin_unlock(&li->lock);
        if (!rc)
                kvm_s390_vcpu_wakeup(vcpu);
        return rc;
 }
 
-void kvm_s390_clear_float_irqs(struct kvm *kvm)
+static inline void clear_irq_list(struct list_head *_list)
 {
-       struct kvm_s390_float_interrupt *fi;
-       struct kvm_s390_interrupt_info  *n, *inti = NULL;
+       struct kvm_s390_interrupt_info *inti, *n;
 
-       fi = &kvm->arch.float_int;
-       spin_lock(&fi->lock);
-       list_for_each_entry_safe(inti, n, &fi->list, list) {
+       list_for_each_entry_safe(inti, n, _list, list) {
                list_del(&inti->list);
                kfree(inti);
        }
-       fi->irq_count = 0;
-       atomic_set(&fi->active, 0);
-       spin_unlock(&fi->lock);
 }
 
-static inline int copy_irq_to_user(struct kvm_s390_interrupt_info *inti,
-                                  u8 *addr)
+static void inti_to_irq(struct kvm_s390_interrupt_info *inti,
+                      struct kvm_s390_irq *irq)
 {
-       struct kvm_s390_irq __user *uptr = (struct kvm_s390_irq __user *) addr;
-       struct kvm_s390_irq irq = {0};
-
-       irq.type = inti->type;
+       irq->type = inti->type;
        switch (inti->type) {
        case KVM_S390_INT_PFAULT_INIT:
        case KVM_S390_INT_PFAULT_DONE:
        case KVM_S390_INT_VIRTIO:
-       case KVM_S390_INT_SERVICE:
-               irq.u.ext = inti->ext;
+               irq->u.ext = inti->ext;
                break;
        case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
-               irq.u.io = inti->io;
+               irq->u.io = inti->io;
                break;
-       case KVM_S390_MCHK:
-               irq.u.mchk = inti->mchk;
-               break;
-       default:
-               return -EINVAL;
        }
+}
 
-       if (copy_to_user(uptr, &irq, sizeof(irq)))
-               return -EFAULT;
+void kvm_s390_clear_float_irqs(struct kvm *kvm)
+{
+       struct kvm_s390_float_interrupt *fi = &kvm->arch.float_int;
+       int i;
 
-       return 0;
-}
+       spin_lock(&fi->lock);
+       for (i = 0; i < FIRQ_LIST_COUNT; i++)
+               clear_irq_list(&fi->lists[i]);
+       for (i = 0; i < FIRQ_MAX_COUNT; i++)
+               fi->counters[i] = 0;
+       spin_unlock(&fi->lock);
+};
 
-static int get_all_floating_irqs(struct kvm *kvm, __u8 *buf, __u64 len)
+static int get_all_floating_irqs(struct kvm *kvm, u8 __user *usrbuf, u64 len)
 {
        struct kvm_s390_interrupt_info *inti;
        struct kvm_s390_float_interrupt *fi;
+       struct kvm_s390_irq *buf;
+       struct kvm_s390_irq *irq;
+       int max_irqs;
        int ret = 0;
        int n = 0;
+       int i;
+
+       if (len > KVM_S390_FLIC_MAX_BUFFER || len == 0)
+               return -EINVAL;
+
+       /*
+        * We are already using -ENOMEM to signal
+        * userspace it may retry with a bigger buffer,
+        * so we need to use something else for this case
+        */
+       buf = vzalloc(len);
+       if (!buf)
+               return -ENOBUFS;
+
+       max_irqs = len / sizeof(struct kvm_s390_irq);
 
        fi = &kvm->arch.float_int;
        spin_lock(&fi->lock);
-
-       list_for_each_entry(inti, &fi->list, list) {
-               if (len < sizeof(struct kvm_s390_irq)) {
+       for (i = 0; i < FIRQ_LIST_COUNT; i++) {
+               list_for_each_entry(inti, &fi->lists[i], list) {
+                       if (n == max_irqs) {
+                               /* signal userspace to try again */
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+                       inti_to_irq(inti, &buf[n]);
+                       n++;
+               }
+       }
+       if (test_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs)) {
+               if (n == max_irqs) {
                        /* signal userspace to try again */
                        ret = -ENOMEM;
-                       break;
+                       goto out;
                }
-               ret = copy_irq_to_user(inti, buf);
-               if (ret)
-                       break;
-               buf += sizeof(struct kvm_s390_irq);
-               len -= sizeof(struct kvm_s390_irq);
+               irq = (struct kvm_s390_irq *) &buf[n];
+               irq->type = KVM_S390_INT_SERVICE;
+               irq->u.ext = fi->srv_signal;
                n++;
        }
+       if (test_bit(IRQ_PEND_MCHK_REP, &fi->pending_irqs)) {
+               if (n == max_irqs) {
+                               /* signal userspace to try again */
+                               ret = -ENOMEM;
+                               goto out;
+               }
+               irq = (struct kvm_s390_irq *) &buf[n];
+               irq->type = KVM_S390_MCHK;
+               irq->u.mchk = fi->mchk;
+               n++;
+}
 
+out:
        spin_unlock(&fi->lock);
+       if (!ret && n > 0) {
+               if (copy_to_user(usrbuf, buf, sizeof(struct kvm_s390_irq) * n))
+                       ret = -EFAULT;
+       }
+       vfree(buf);
 
        return ret < 0 ? ret : n;
 }
@@ -1520,7 +1691,7 @@ static int flic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
 
        switch (attr->group) {
        case KVM_DEV_FLIC_GET_ALL_IRQS:
-               r = get_all_floating_irqs(dev->kvm, (u8 *) attr->addr,
+               r = get_all_floating_irqs(dev->kvm, (u8 __user *) attr->addr,
                                          attr->attr);
                break;
        default:
@@ -1952,3 +2123,143 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
 {
        return -EINVAL;
 }
+
+int kvm_s390_set_irq_state(struct kvm_vcpu *vcpu, void __user *irqstate, int len)
+{
+       struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
+       struct kvm_s390_irq *buf;
+       int r = 0;
+       int n;
+
+       buf = vmalloc(len);
+       if (!buf)
+               return -ENOMEM;
+
+       if (copy_from_user((void *) buf, irqstate, len)) {
+               r = -EFAULT;
+               goto out_free;
+       }
+
+       /*
+        * Don't allow setting the interrupt state
+        * when there are already interrupts pending
+        */
+       spin_lock(&li->lock);
+       if (li->pending_irqs) {
+               r = -EBUSY;
+               goto out_unlock;
+       }
+
+       for (n = 0; n < len / sizeof(*buf); n++) {
+               r = do_inject_vcpu(vcpu, &buf[n]);
+               if (r)
+                       break;
+       }
+
+out_unlock:
+       spin_unlock(&li->lock);
+out_free:
+       vfree(buf);
+
+       return r;
+}
+
+static void store_local_irq(struct kvm_s390_local_interrupt *li,
+                           struct kvm_s390_irq *irq,
+                           unsigned long irq_type)
+{
+       switch (irq_type) {
+       case IRQ_PEND_MCHK_EX:
+       case IRQ_PEND_MCHK_REP:
+               irq->type = KVM_S390_MCHK;
+               irq->u.mchk = li->irq.mchk;
+               break;
+       case IRQ_PEND_PROG:
+               irq->type = KVM_S390_PROGRAM_INT;
+               irq->u.pgm = li->irq.pgm;
+               break;
+       case IRQ_PEND_PFAULT_INIT:
+               irq->type = KVM_S390_INT_PFAULT_INIT;
+               irq->u.ext = li->irq.ext;
+               break;
+       case IRQ_PEND_EXT_EXTERNAL:
+               irq->type = KVM_S390_INT_EXTERNAL_CALL;
+               irq->u.extcall = li->irq.extcall;
+               break;
+       case IRQ_PEND_EXT_CLOCK_COMP:
+               irq->type = KVM_S390_INT_CLOCK_COMP;
+               break;
+       case IRQ_PEND_EXT_CPU_TIMER:
+               irq->type = KVM_S390_INT_CPU_TIMER;
+               break;
+       case IRQ_PEND_SIGP_STOP:
+               irq->type = KVM_S390_SIGP_STOP;
+               irq->u.stop = li->irq.stop;
+               break;
+       case IRQ_PEND_RESTART:
+               irq->type = KVM_S390_RESTART;
+               break;
+       case IRQ_PEND_SET_PREFIX:
+               irq->type = KVM_S390_SIGP_SET_PREFIX;
+               irq->u.prefix = li->irq.prefix;
+               break;
+       }
+}
+
+int kvm_s390_get_irq_state(struct kvm_vcpu *vcpu, __u8 __user *buf, int len)
+{
+       uint8_t sigp_ctrl = vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sigp_ctrl;
+       unsigned long sigp_emerg_pending[BITS_TO_LONGS(KVM_MAX_VCPUS)];
+       struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
+       unsigned long pending_irqs;
+       struct kvm_s390_irq irq;
+       unsigned long irq_type;
+       int cpuaddr;
+       int n = 0;
+
+       spin_lock(&li->lock);
+       pending_irqs = li->pending_irqs;
+       memcpy(&sigp_emerg_pending, &li->sigp_emerg_pending,
+              sizeof(sigp_emerg_pending));
+       spin_unlock(&li->lock);
+
+       for_each_set_bit(irq_type, &pending_irqs, IRQ_PEND_COUNT) {
+               memset(&irq, 0, sizeof(irq));
+               if (irq_type == IRQ_PEND_EXT_EMERGENCY)
+                       continue;
+               if (n + sizeof(irq) > len)
+                       return -ENOBUFS;
+               store_local_irq(&vcpu->arch.local_int, &irq, irq_type);
+               if (copy_to_user(&buf[n], &irq, sizeof(irq)))
+                       return -EFAULT;
+               n += sizeof(irq);
+       }
+
+       if (test_bit(IRQ_PEND_EXT_EMERGENCY, &pending_irqs)) {
+               for_each_set_bit(cpuaddr, sigp_emerg_pending, KVM_MAX_VCPUS) {
+                       memset(&irq, 0, sizeof(irq));
+                       if (n + sizeof(irq) > len)
+                               return -ENOBUFS;
+                       irq.type = KVM_S390_INT_EMERGENCY;
+                       irq.u.emerg.code = cpuaddr;
+                       if (copy_to_user(&buf[n], &irq, sizeof(irq)))
+                               return -EFAULT;
+                       n += sizeof(irq);
+               }
+       }
+
+       if ((sigp_ctrl & SIGP_CTRL_C) &&
+           (atomic_read(&vcpu->arch.sie_block->cpuflags) &
+            CPUSTAT_ECALL_PEND)) {
+               if (n + sizeof(irq) > len)
+                       return -ENOBUFS;
+               memset(&irq, 0, sizeof(irq));
+               irq.type = KVM_S390_INT_EXTERNAL_CALL;
+               irq.u.extcall.code = sigp_ctrl & SIGP_CTRL_SCN_MASK;
+               if (copy_to_user(&buf[n], &irq, sizeof(irq)))
+                       return -EFAULT;
+               n += sizeof(irq);
+       }
+
+       return n;
+}
index 19e17bd7aec09b2662874a3925e3d55f4e4207f4..afa2bd750ffc814d36300bc491a0a6eff516bda4 100644 (file)
 #include <linux/random.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
+#include <linux/vmalloc.h>
 #include <asm/asm-offsets.h>
 #include <asm/lowcore.h>
 #include <asm/pgtable.h>
 #include <asm/nmi.h>
 #include <asm/switch_to.h>
+#include <asm/isc.h>
 #include <asm/sclp.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
 #include "trace.h"
 #include "trace-s390.h"
 
+#define MEM_OP_MAX_SIZE 65536  /* Maximum transfer size for KVM_S390_MEM_OP */
+#define LOCAL_IRQS 32
+#define VCPU_IRQS_MAX_BUF (sizeof(struct kvm_s390_irq) * \
+                          (KVM_MAX_VCPUS + LOCAL_IRQS))
+
 #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
 
 struct kvm_stats_debugfs_item debugfs_entries[] = {
@@ -87,6 +94,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
        { "instruction_sigp_stop_store_status", VCPU_STAT(instruction_sigp_stop_store_status) },
        { "instruction_sigp_store_status", VCPU_STAT(instruction_sigp_store_status) },
+       { "instruction_sigp_store_adtl_status", VCPU_STAT(instruction_sigp_store_adtl_status) },
        { "instruction_sigp_set_arch", VCPU_STAT(instruction_sigp_arch) },
        { "instruction_sigp_set_prefix", VCPU_STAT(instruction_sigp_prefix) },
        { "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) },
@@ -101,8 +109,8 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 
 /* upper facilities limit for kvm */
 unsigned long kvm_s390_fac_list_mask[] = {
-       0xff82fffbf4fc2000UL,
-       0x005c000000000000UL,
+       0xffe6fffbfcfdfc40UL,
+       0x205c800000000000UL,
 };
 
 unsigned long kvm_s390_fac_list_mask_size(void)
@@ -171,9 +179,16 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_S390_IRQCHIP:
        case KVM_CAP_VM_ATTRIBUTES:
        case KVM_CAP_MP_STATE:
+       case KVM_CAP_S390_INJECT_IRQ:
        case KVM_CAP_S390_USER_SIGP:
+       case KVM_CAP_S390_USER_STSI:
+       case KVM_CAP_S390_SKEYS:
+       case KVM_CAP_S390_IRQ_STATE:
                r = 1;
                break;
+       case KVM_CAP_S390_MEM_OP:
+               r = MEM_OP_MAX_SIZE;
+               break;
        case KVM_CAP_NR_VCPUS:
        case KVM_CAP_MAX_VCPUS:
                r = KVM_MAX_VCPUS;
@@ -184,6 +199,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_S390_COW:
                r = MACHINE_HAS_ESOP;
                break;
+       case KVM_CAP_S390_VECTOR_REGISTERS:
+               r = MACHINE_HAS_VX;
+               break;
        default:
                r = 0;
        }
@@ -264,6 +282,18 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
                kvm->arch.user_sigp = 1;
                r = 0;
                break;
+       case KVM_CAP_S390_VECTOR_REGISTERS:
+               if (MACHINE_HAS_VX) {
+                       set_kvm_facility(kvm->arch.model.fac->mask, 129);
+                       set_kvm_facility(kvm->arch.model.fac->list, 129);
+                       r = 0;
+               } else
+                       r = -EINVAL;
+               break;
+       case KVM_CAP_S390_USER_STSI:
+               kvm->arch.user_stsi = 1;
+               r = 0;
+               break;
        default:
                r = -EINVAL;
                break;
@@ -708,6 +738,108 @@ static int kvm_s390_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
        return ret;
 }
 
+static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
+{
+       uint8_t *keys;
+       uint64_t hva;
+       unsigned long curkey;
+       int i, r = 0;
+
+       if (args->flags != 0)
+               return -EINVAL;
+
+       /* Is this guest using storage keys? */
+       if (!mm_use_skey(current->mm))
+               return KVM_S390_GET_SKEYS_NONE;
+
+       /* Enforce sane limit on memory allocation */
+       if (args->count < 1 || args->count > KVM_S390_SKEYS_MAX)
+               return -EINVAL;
+
+       keys = kmalloc_array(args->count, sizeof(uint8_t),
+                            GFP_KERNEL | __GFP_NOWARN);
+       if (!keys)
+               keys = vmalloc(sizeof(uint8_t) * args->count);
+       if (!keys)
+               return -ENOMEM;
+
+       for (i = 0; i < args->count; i++) {
+               hva = gfn_to_hva(kvm, args->start_gfn + i);
+               if (kvm_is_error_hva(hva)) {
+                       r = -EFAULT;
+                       goto out;
+               }
+
+               curkey = get_guest_storage_key(current->mm, hva);
+               if (IS_ERR_VALUE(curkey)) {
+                       r = curkey;
+                       goto out;
+               }
+               keys[i] = curkey;
+       }
+
+       r = copy_to_user((uint8_t __user *)args->skeydata_addr, keys,
+                        sizeof(uint8_t) * args->count);
+       if (r)
+               r = -EFAULT;
+out:
+       kvfree(keys);
+       return r;
+}
+
+static long kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
+{
+       uint8_t *keys;
+       uint64_t hva;
+       int i, r = 0;
+
+       if (args->flags != 0)
+               return -EINVAL;
+
+       /* Enforce sane limit on memory allocation */
+       if (args->count < 1 || args->count > KVM_S390_SKEYS_MAX)
+               return -EINVAL;
+
+       keys = kmalloc_array(args->count, sizeof(uint8_t),
+                            GFP_KERNEL | __GFP_NOWARN);
+       if (!keys)
+               keys = vmalloc(sizeof(uint8_t) * args->count);
+       if (!keys)
+               return -ENOMEM;
+
+       r = copy_from_user(keys, (uint8_t __user *)args->skeydata_addr,
+                          sizeof(uint8_t) * args->count);
+       if (r) {
+               r = -EFAULT;
+               goto out;
+       }
+
+       /* Enable storage key handling for the guest */
+       s390_enable_skey();
+
+       for (i = 0; i < args->count; i++) {
+               hva = gfn_to_hva(kvm, args->start_gfn + i);
+               if (kvm_is_error_hva(hva)) {
+                       r = -EFAULT;
+                       goto out;
+               }
+
+               /* Lowest order bit is reserved */
+               if (keys[i] & 0x01) {
+                       r = -EINVAL;
+                       goto out;
+               }
+
+               r = set_guest_storage_key(current->mm, hva,
+                                         (unsigned long)keys[i], 0);
+               if (r)
+                       goto out;
+       }
+out:
+       kvfree(keys);
+       return r;
+}
+
 long kvm_arch_vm_ioctl(struct file *filp,
                       unsigned int ioctl, unsigned long arg)
 {
@@ -767,6 +899,26 @@ long kvm_arch_vm_ioctl(struct file *filp,
                r = kvm_s390_vm_has_attr(kvm, &attr);
                break;
        }
+       case KVM_S390_GET_SKEYS: {
+               struct kvm_s390_skeys args;
+
+               r = -EFAULT;
+               if (copy_from_user(&args, argp,
+                                  sizeof(struct kvm_s390_skeys)))
+                       break;
+               r = kvm_s390_get_skeys(kvm, &args);
+               break;
+       }
+       case KVM_S390_SET_SKEYS: {
+               struct kvm_s390_skeys args;
+
+               r = -EFAULT;
+               if (copy_from_user(&args, argp,
+                                  sizeof(struct kvm_s390_skeys)))
+                       break;
+               r = kvm_s390_set_skeys(kvm, &args);
+               break;
+       }
        default:
                r = -ENOTTY;
        }
@@ -887,7 +1039,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 
        kvm->arch.dbf = debug_register(debug_name, 8, 2, 8 * sizeof(long));
        if (!kvm->arch.dbf)
-               goto out_nodbf;
+               goto out_err;
 
        /*
         * The architectural maximum amount of facilities is 16 kbit. To store
@@ -899,7 +1051,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        kvm->arch.model.fac =
                (struct kvm_s390_fac *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
        if (!kvm->arch.model.fac)
-               goto out_nofac;
+               goto out_err;
 
        /* Populate the facility mask initially. */
        memcpy(kvm->arch.model.fac->mask, S390_lowcore.stfle_fac_list,
@@ -919,10 +1071,11 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        kvm->arch.model.ibc = sclp_get_ibc() & 0x0fff;
 
        if (kvm_s390_crypto_init(kvm) < 0)
-               goto out_crypto;
+               goto out_err;
 
        spin_lock_init(&kvm->arch.float_int.lock);
-       INIT_LIST_HEAD(&kvm->arch.float_int.list);
+       for (i = 0; i < FIRQ_LIST_COUNT; i++)
+               INIT_LIST_HEAD(&kvm->arch.float_int.lists[i]);
        init_waitqueue_head(&kvm->arch.ipte_wq);
        mutex_init(&kvm->arch.ipte_mutex);
 
@@ -934,7 +1087,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        } else {
                kvm->arch.gmap = gmap_alloc(current->mm, (1UL << 44) - 1);
                if (!kvm->arch.gmap)
-                       goto out_nogmap;
+                       goto out_err;
                kvm->arch.gmap->private = kvm;
                kvm->arch.gmap->pfault_enabled = 0;
        }
@@ -946,15 +1099,11 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        spin_lock_init(&kvm->arch.start_stop_lock);
 
        return 0;
-out_nogmap:
+out_err:
        kfree(kvm->arch.crypto.crycb);
-out_crypto:
        free_page((unsigned long)kvm->arch.model.fac);
-out_nofac:
        debug_unregister(kvm->arch.dbf);
-out_nodbf:
        free_page((unsigned long)(kvm->arch.sca));
-out_err:
        return rc;
 }
 
@@ -1034,6 +1183,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
                                    KVM_SYNC_CRS |
                                    KVM_SYNC_ARCH0 |
                                    KVM_SYNC_PFAULT;
+       if (test_kvm_facility(vcpu->kvm, 129))
+               vcpu->run->kvm_valid_regs |= KVM_SYNC_VRS;
 
        if (kvm_is_ucontrol(vcpu->kvm))
                return __kvm_ucontrol_vcpu_init(vcpu);
@@ -1044,10 +1195,18 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
        save_fp_ctl(&vcpu->arch.host_fpregs.fpc);
-       save_fp_regs(vcpu->arch.host_fpregs.fprs);
+       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);
-       restore_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
-       restore_fp_regs(vcpu->arch.guest_fpregs.fprs);
+       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);
+       }
        restore_access_regs(vcpu->run->s.regs.acrs);
        gmap_enable(vcpu->arch.gmap);
        atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
@@ -1057,11 +1216,19 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
        atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
        gmap_disable(vcpu->arch.gmap);
-       save_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
-       save_fp_regs(vcpu->arch.guest_fpregs.fprs);
+       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);
-       restore_fp_regs(vcpu->arch.host_fpregs.fprs);
+       if (test_kvm_facility(vcpu->kvm, 129))
+               restore_vx_regs((__vector128 *)&vcpu->arch.host_vregs->vrs);
+       else
+               restore_fp_regs(vcpu->arch.host_fpregs.fprs);
        restore_access_regs(vcpu->arch.host_acrs);
 }
 
@@ -1129,6 +1296,15 @@ int kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu)
        return 0;
 }
 
+static void kvm_s390_vcpu_setup_model(struct kvm_vcpu *vcpu)
+{
+       struct kvm_s390_cpu_model *model = &vcpu->kvm->arch.model;
+
+       vcpu->arch.cpu_id = model->cpu_id;
+       vcpu->arch.sie_block->ibc = model->ibc;
+       vcpu->arch.sie_block->fac = (int) (long) model->fac->list;
+}
+
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
        int rc = 0;
@@ -1137,6 +1313,8 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
                                                    CPUSTAT_SM |
                                                    CPUSTAT_STOPPED |
                                                    CPUSTAT_GED);
+       kvm_s390_vcpu_setup_model(vcpu);
+
        vcpu->arch.sie_block->ecb   = 6;
        if (test_kvm_facility(vcpu->kvm, 50) && test_kvm_facility(vcpu->kvm, 73))
                vcpu->arch.sie_block->ecb |= 0x10;
@@ -1147,8 +1325,11 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
                vcpu->arch.sie_block->eca |= 1;
        if (sclp_has_sigpif())
                vcpu->arch.sie_block->eca |= 0x10000000U;
-       vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE |
-                                     ICTL_TPROT;
+       if (test_kvm_facility(vcpu->kvm, 129)) {
+               vcpu->arch.sie_block->eca |= 0x00020000;
+               vcpu->arch.sie_block->ecd |= 0x20000000;
+       }
+       vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE;
 
        if (kvm_s390_cmma_enabled(vcpu->kvm)) {
                rc = kvm_s390_vcpu_setup_cmma(vcpu);
@@ -1158,11 +1339,6 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup;
 
-       mutex_lock(&vcpu->kvm->lock);
-       vcpu->arch.cpu_id = vcpu->kvm->arch.model.cpu_id;
-       vcpu->arch.sie_block->ibc = vcpu->kvm->arch.model.ibc;
-       mutex_unlock(&vcpu->kvm->lock);
-
        kvm_s390_vcpu_crypto_setup(vcpu);
 
        return rc;
@@ -1190,6 +1366,7 @@ 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)) {
@@ -1205,7 +1382,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
                vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
                set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn);
        }
-       vcpu->arch.sie_block->fac = (int) (long) kvm->arch.model.fac->list;
 
        spin_lock_init(&vcpu->arch.local_int.lock);
        vcpu->arch.local_int.float_int = &kvm->arch.float_int;
@@ -1725,6 +1901,31 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu)
        return 0;
 }
 
+static int vcpu_post_run_fault_in_sie(struct kvm_vcpu *vcpu)
+{
+       psw_t *psw = &vcpu->arch.sie_block->gpsw;
+       u8 opcode;
+       int rc;
+
+       VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
+       trace_kvm_s390_sie_fault(vcpu);
+
+       /*
+        * We want to inject an addressing exception, which is defined as a
+        * suppressing or terminating exception. However, since we came here
+        * by a DAT access exception, the PSW still points to the faulting
+        * instruction since DAT exceptions are nullifying. So we've got
+        * to look up the current opcode to get the length of the instruction
+        * to be able to forward the PSW.
+        */
+       rc = read_guest(vcpu, psw->addr, 0, &opcode, 1);
+       if (rc)
+               return kvm_s390_inject_prog_cond(vcpu, rc);
+       psw->addr = __rewind_psw(*psw, -insn_length(opcode));
+
+       return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+}
+
 static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
 {
        int rc = -1;
@@ -1756,11 +1957,8 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
                }
        }
 
-       if (rc == -1) {
-               VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
-               trace_kvm_s390_sie_fault(vcpu);
-               rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
-       }
+       if (rc == -1)
+               rc = vcpu_post_run_fault_in_sie(vcpu);
 
        memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16);
 
@@ -1976,6 +2174,35 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
        return kvm_s390_store_status_unloaded(vcpu, addr);
 }
 
+/*
+ * store additional status at address
+ */
+int kvm_s390_store_adtl_status_unloaded(struct kvm_vcpu *vcpu,
+                                       unsigned long gpa)
+{
+       /* Only bits 0-53 are used for address formation */
+       if (!(gpa & ~0x3ff))
+               return 0;
+
+       return write_guest_abs(vcpu, gpa & ~0x3ff,
+                              (void *)&vcpu->run->s.regs.vrs, 512);
+}
+
+int kvm_s390_vcpu_store_adtl_status(struct kvm_vcpu *vcpu, unsigned long addr)
+{
+       if (!test_kvm_facility(vcpu->kvm, 129))
+               return 0;
+
+       /*
+        * 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.
+        */
+       save_vx_regs((__vector128 *)&vcpu->run->s.regs.vrs);
+
+       return kvm_s390_store_adtl_status_unloaded(vcpu, addr);
+}
+
 static void __disable_ibs_on_vcpu(struct kvm_vcpu *vcpu)
 {
        kvm_check_request(KVM_REQ_ENABLE_IBS, vcpu);
@@ -2100,6 +2327,65 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
        return r;
 }
 
+static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
+                                 struct kvm_s390_mem_op *mop)
+{
+       void __user *uaddr = (void __user *)mop->buf;
+       void *tmpbuf = NULL;
+       int r, srcu_idx;
+       const u64 supported_flags = KVM_S390_MEMOP_F_INJECT_EXCEPTION
+                                   | KVM_S390_MEMOP_F_CHECK_ONLY;
+
+       if (mop->flags & ~supported_flags)
+               return -EINVAL;
+
+       if (mop->size > MEM_OP_MAX_SIZE)
+               return -E2BIG;
+
+       if (!(mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY)) {
+               tmpbuf = vmalloc(mop->size);
+               if (!tmpbuf)
+                       return -ENOMEM;
+       }
+
+       srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+       switch (mop->op) {
+       case KVM_S390_MEMOP_LOGICAL_READ:
+               if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
+                       r = check_gva_range(vcpu, mop->gaddr, mop->ar, mop->size, false);
+                       break;
+               }
+               r = read_guest(vcpu, mop->gaddr, mop->ar, tmpbuf, mop->size);
+               if (r == 0) {
+                       if (copy_to_user(uaddr, tmpbuf, mop->size))
+                               r = -EFAULT;
+               }
+               break;
+       case KVM_S390_MEMOP_LOGICAL_WRITE:
+               if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
+                       r = check_gva_range(vcpu, mop->gaddr, mop->ar, mop->size, true);
+                       break;
+               }
+               if (copy_from_user(tmpbuf, uaddr, mop->size)) {
+                       r = -EFAULT;
+                       break;
+               }
+               r = write_guest(vcpu, mop->gaddr, mop->ar, tmpbuf, mop->size);
+               break;
+       default:
+               r = -EINVAL;
+       }
+
+       srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
+
+       if (r > 0 && (mop->flags & KVM_S390_MEMOP_F_INJECT_EXCEPTION) != 0)
+               kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm);
+
+       vfree(tmpbuf);
+       return r;
+}
+
 long kvm_arch_vcpu_ioctl(struct file *filp,
                         unsigned int ioctl, unsigned long arg)
 {
@@ -2109,6 +2395,15 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
        long r;
 
        switch (ioctl) {
+       case KVM_S390_IRQ: {
+               struct kvm_s390_irq s390irq;
+
+               r = -EFAULT;
+               if (copy_from_user(&s390irq, argp, sizeof(s390irq)))
+                       break;
+               r = kvm_s390_inject_vcpu(vcpu, &s390irq);
+               break;
+       }
        case KVM_S390_INTERRUPT: {
                struct kvm_s390_interrupt s390int;
                struct kvm_s390_irq s390irq;
@@ -2199,6 +2494,47 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                r = kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
                break;
        }
+       case KVM_S390_MEM_OP: {
+               struct kvm_s390_mem_op mem_op;
+
+               if (copy_from_user(&mem_op, argp, sizeof(mem_op)) == 0)
+                       r = kvm_s390_guest_mem_op(vcpu, &mem_op);
+               else
+                       r = -EFAULT;
+               break;
+       }
+       case KVM_S390_SET_IRQ_STATE: {
+               struct kvm_s390_irq_state irq_state;
+
+               r = -EFAULT;
+               if (copy_from_user(&irq_state, argp, sizeof(irq_state)))
+                       break;
+               if (irq_state.len > VCPU_IRQS_MAX_BUF ||
+                   irq_state.len == 0 ||
+                   irq_state.len % sizeof(struct kvm_s390_irq) > 0) {
+                       r = -EINVAL;
+                       break;
+               }
+               r = kvm_s390_set_irq_state(vcpu,
+                                          (void __user *) irq_state.buf,
+                                          irq_state.len);
+               break;
+       }
+       case KVM_S390_GET_IRQ_STATE: {
+               struct kvm_s390_irq_state irq_state;
+
+               r = -EFAULT;
+               if (copy_from_user(&irq_state, argp, sizeof(irq_state)))
+                       break;
+               if (irq_state.len == 0) {
+                       r = -EINVAL;
+                       break;
+               }
+               r = kvm_s390_get_irq_state(vcpu,
+                                          (__u8 __user *)  irq_state.buf,
+                                          irq_state.len);
+               break;
+       }
        default:
                r = -ENOTTY;
        }
index c34109aa552d9b1a6e5ea66f172b5c3e30ad001b..ca108b90ae5613a15e0d82a68ef0288a93d62792 100644 (file)
@@ -70,16 +70,22 @@ static inline void kvm_s390_set_prefix(struct kvm_vcpu *vcpu, u32 prefix)
        kvm_make_request(KVM_REQ_MMU_RELOAD, vcpu);
 }
 
-static inline u64 kvm_s390_get_base_disp_s(struct kvm_vcpu *vcpu)
+typedef u8 __bitwise ar_t;
+
+static inline u64 kvm_s390_get_base_disp_s(struct kvm_vcpu *vcpu, ar_t *ar)
 {
        u32 base2 = vcpu->arch.sie_block->ipb >> 28;
        u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
 
+       if (ar)
+               *ar = base2;
+
        return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
 }
 
 static inline void kvm_s390_get_base_disp_sse(struct kvm_vcpu *vcpu,
-                                             u64 *address1, u64 *address2)
+                                             u64 *address1, u64 *address2,
+                                             ar_t *ar_b1, ar_t *ar_b2)
 {
        u32 base1 = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28;
        u32 disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16;
@@ -88,6 +94,11 @@ static inline void kvm_s390_get_base_disp_sse(struct kvm_vcpu *vcpu,
 
        *address1 = (base1 ? vcpu->run->s.regs.gprs[base1] : 0) + disp1;
        *address2 = (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
+
+       if (ar_b1)
+               *ar_b1 = base1;
+       if (ar_b2)
+               *ar_b2 = base2;
 }
 
 static inline void kvm_s390_get_regs_rre(struct kvm_vcpu *vcpu, int *r1, int *r2)
@@ -98,7 +109,7 @@ static inline void kvm_s390_get_regs_rre(struct kvm_vcpu *vcpu, int *r1, int *r2
                *r2 = (vcpu->arch.sie_block->ipb & 0x000f0000) >> 16;
 }
 
-static inline u64 kvm_s390_get_base_disp_rsy(struct kvm_vcpu *vcpu)
+static inline u64 kvm_s390_get_base_disp_rsy(struct kvm_vcpu *vcpu, ar_t *ar)
 {
        u32 base2 = vcpu->arch.sie_block->ipb >> 28;
        u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) +
@@ -107,14 +118,20 @@ static inline u64 kvm_s390_get_base_disp_rsy(struct kvm_vcpu *vcpu)
        if (disp2 & 0x80000)
                disp2+=0xfff00000;
 
+       if (ar)
+               *ar = base2;
+
        return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + (long)(int)disp2;
 }
 
-static inline u64 kvm_s390_get_base_disp_rs(struct kvm_vcpu *vcpu)
+static inline u64 kvm_s390_get_base_disp_rs(struct kvm_vcpu *vcpu, ar_t *ar)
 {
        u32 base2 = vcpu->arch.sie_block->ipb >> 28;
        u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
 
+       if (ar)
+               *ar = base2;
+
        return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
 }
 
@@ -125,13 +142,24 @@ static inline void kvm_s390_set_psw_cc(struct kvm_vcpu *vcpu, unsigned long cc)
        vcpu->arch.sie_block->gpsw.mask |= cc << 44;
 }
 
-/* test availability of facility in a kvm intance */
+/* test availability of facility in a kvm instance */
 static inline int test_kvm_facility(struct kvm *kvm, unsigned long nr)
 {
        return __test_facility(nr, kvm->arch.model.fac->mask) &&
                __test_facility(nr, kvm->arch.model.fac->list);
 }
 
+static inline int set_kvm_facility(u64 *fac_list, unsigned long nr)
+{
+       unsigned char *ptr;
+
+       if (nr >= MAX_FACILITY_BIT)
+               return -EINVAL;
+       ptr = (unsigned char *) fac_list + (nr >> 3);
+       *ptr |= (0x80UL >> (nr & 7));
+       return 0;
+}
+
 /* are cpu states controlled by user space */
 static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm)
 {
@@ -150,9 +178,9 @@ int __must_check kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
                                      struct kvm_s390_irq *irq);
 int __must_check kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code);
 struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
-                                                   u64 cr6, u64 schid);
-void kvm_s390_reinject_io_int(struct kvm *kvm,
-                             struct kvm_s390_interrupt_info *inti);
+                                                   u64 isc_mask, u32 schid);
+int kvm_s390_reinject_io_int(struct kvm *kvm,
+                            struct kvm_s390_interrupt_info *inti);
 int kvm_s390_mask_adapter(struct kvm *kvm, unsigned int id, bool masked);
 
 /* implemented in intercept.c */
@@ -177,7 +205,10 @@ int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu);
 /* implemented in kvm-s390.c */
 long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable);
 int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr);
+int kvm_s390_store_adtl_status_unloaded(struct kvm_vcpu *vcpu,
+                                       unsigned long addr);
 int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr);
+int kvm_s390_vcpu_store_adtl_status(struct kvm_vcpu *vcpu, unsigned long addr);
 void kvm_s390_vcpu_start(struct kvm_vcpu *vcpu);
 void kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu);
 void s390_vcpu_block(struct kvm_vcpu *vcpu);
@@ -241,6 +272,10 @@ int kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu);
 extern struct kvm_device_ops kvm_flic_ops;
 int kvm_s390_is_stop_irq_pending(struct kvm_vcpu *vcpu);
 void kvm_s390_clear_stop_irq(struct kvm_vcpu *vcpu);
+int kvm_s390_set_irq_state(struct kvm_vcpu *vcpu,
+                          void __user *buf, int len);
+int kvm_s390_get_irq_state(struct kvm_vcpu *vcpu,
+                          __u8 __user *buf, int len);
 
 /* implemented in guestdbg.c */
 void kvm_s390_backup_guest_per_regs(struct kvm_vcpu *vcpu);
index 351116939ea27f2fcf6eb4de60447d86335d0b6e..d22d8ee1ff9d9c6404d653f5c4f8a04b8ddc70da 100644 (file)
@@ -36,15 +36,16 @@ static int handle_set_clock(struct kvm_vcpu *vcpu)
        struct kvm_vcpu *cpup;
        s64 hostclk, val;
        int i, rc;
+       ar_t ar;
        u64 op2;
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       op2 = kvm_s390_get_base_disp_s(vcpu);
+       op2 = kvm_s390_get_base_disp_s(vcpu, &ar);
        if (op2 & 7)    /* Operand must be on a doubleword boundary */
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
-       rc = read_guest(vcpu, op2, &val, sizeof(val));
+       rc = read_guest(vcpu, op2, ar, &val, sizeof(val));
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
 
@@ -68,20 +69,21 @@ static int handle_set_prefix(struct kvm_vcpu *vcpu)
        u64 operand2;
        u32 address;
        int rc;
+       ar_t ar;
 
        vcpu->stat.instruction_spx++;
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       operand2 = kvm_s390_get_base_disp_s(vcpu);
+       operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
 
        /* must be word boundary */
        if (operand2 & 3)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
        /* get the value */
-       rc = read_guest(vcpu, operand2, &address, sizeof(address));
+       rc = read_guest(vcpu, operand2, ar, &address, sizeof(address));
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
 
@@ -107,13 +109,14 @@ static int handle_store_prefix(struct kvm_vcpu *vcpu)
        u64 operand2;
        u32 address;
        int rc;
+       ar_t ar;
 
        vcpu->stat.instruction_stpx++;
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       operand2 = kvm_s390_get_base_disp_s(vcpu);
+       operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
 
        /* must be word boundary */
        if (operand2 & 3)
@@ -122,7 +125,7 @@ static int handle_store_prefix(struct kvm_vcpu *vcpu)
        address = kvm_s390_get_prefix(vcpu);
 
        /* get the value */
-       rc = write_guest(vcpu, operand2, &address, sizeof(address));
+       rc = write_guest(vcpu, operand2, ar, &address, sizeof(address));
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
 
@@ -136,18 +139,19 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
        u16 vcpu_id = vcpu->vcpu_id;
        u64 ga;
        int rc;
+       ar_t ar;
 
        vcpu->stat.instruction_stap++;
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       ga = kvm_s390_get_base_disp_s(vcpu);
+       ga = kvm_s390_get_base_disp_s(vcpu, &ar);
 
        if (ga & 1)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
-       rc = write_guest(vcpu, ga, &vcpu_id, sizeof(vcpu_id));
+       rc = write_guest(vcpu, ga, ar, &vcpu_id, sizeof(vcpu_id));
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
 
@@ -207,7 +211,7 @@ static int handle_test_block(struct kvm_vcpu *vcpu)
        kvm_s390_get_regs_rre(vcpu, NULL, &reg2);
        addr = vcpu->run->s.regs.gprs[reg2] & PAGE_MASK;
        addr = kvm_s390_logical_to_effective(vcpu, addr);
-       if (kvm_s390_check_low_addr_protection(vcpu, addr))
+       if (kvm_s390_check_low_addr_prot_real(vcpu, addr))
                return kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm);
        addr = kvm_s390_real_to_abs(vcpu, addr);
 
@@ -229,18 +233,20 @@ static int handle_tpi(struct kvm_vcpu *vcpu)
        struct kvm_s390_interrupt_info *inti;
        unsigned long len;
        u32 tpi_data[3];
-       int cc, rc;
+       int rc;
        u64 addr;
+       ar_t ar;
 
-       rc = 0;
-       addr = kvm_s390_get_base_disp_s(vcpu);
+       addr = kvm_s390_get_base_disp_s(vcpu, &ar);
        if (addr & 3)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
-       cc = 0;
+
        inti = kvm_s390_get_io_int(vcpu->kvm, vcpu->arch.sie_block->gcr[6], 0);
-       if (!inti)
-               goto no_interrupt;
-       cc = 1;
+       if (!inti) {
+               kvm_s390_set_psw_cc(vcpu, 0);
+               return 0;
+       }
+
        tpi_data[0] = inti->io.subchannel_id << 16 | inti->io.subchannel_nr;
        tpi_data[1] = inti->io.io_int_parm;
        tpi_data[2] = inti->io.io_int_word;
@@ -250,40 +256,51 @@ static int handle_tpi(struct kvm_vcpu *vcpu)
                 * provided area.
                 */
                len = sizeof(tpi_data) - 4;
-               rc = write_guest(vcpu, addr, &tpi_data, len);
-               if (rc)
-                       return kvm_s390_inject_prog_cond(vcpu, rc);
+               rc = write_guest(vcpu, addr, ar, &tpi_data, len);
+               if (rc) {
+                       rc = kvm_s390_inject_prog_cond(vcpu, rc);
+                       goto reinject_interrupt;
+               }
        } else {
                /*
                 * Store the three-word I/O interruption code into
                 * the appropriate lowcore area.
                 */
                len = sizeof(tpi_data);
-               if (write_guest_lc(vcpu, __LC_SUBCHANNEL_ID, &tpi_data, len))
+               if (write_guest_lc(vcpu, __LC_SUBCHANNEL_ID, &tpi_data, len)) {
+                       /* failed writes to the low core are not recoverable */
                        rc = -EFAULT;
+                       goto reinject_interrupt;
+               }
        }
+
+       /* irq was successfully handed to the guest */
+       kfree(inti);
+       kvm_s390_set_psw_cc(vcpu, 1);
+       return 0;
+reinject_interrupt:
        /*
         * If we encounter a problem storing the interruption code, the
         * instruction is suppressed from the guest's view: reinject the
         * interrupt.
         */
-       if (!rc)
+       if (kvm_s390_reinject_io_int(vcpu->kvm, inti)) {
                kfree(inti);
-       else
-               kvm_s390_reinject_io_int(vcpu->kvm, inti);
-no_interrupt:
-       /* Set condition code and we're done. */
-       if (!rc)
-               kvm_s390_set_psw_cc(vcpu, cc);
+               rc = -EFAULT;
+       }
+       /* don't set the cc, a pgm irq was injected or we drop to user space */
        return rc ? -EFAULT : 0;
 }
 
 static int handle_tsch(struct kvm_vcpu *vcpu)
 {
-       struct kvm_s390_interrupt_info *inti;
+       struct kvm_s390_interrupt_info *inti = NULL;
+       const u64 isc_mask = 0xffUL << 24; /* all iscs set */
 
-       inti = kvm_s390_get_io_int(vcpu->kvm, 0,
-                                  vcpu->run->s.regs.gprs[1]);
+       /* a valid schid has at least one bit set */
+       if (vcpu->run->s.regs.gprs[1])
+               inti = kvm_s390_get_io_int(vcpu->kvm, isc_mask,
+                                          vcpu->run->s.regs.gprs[1]);
 
        /*
         * Prepare exit to userspace.
@@ -386,15 +403,16 @@ int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu)
        psw_compat_t new_psw;
        u64 addr;
        int rc;
+       ar_t ar;
 
        if (gpsw->mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       addr = kvm_s390_get_base_disp_s(vcpu);
+       addr = kvm_s390_get_base_disp_s(vcpu, &ar);
        if (addr & 7)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
-       rc = read_guest(vcpu, addr, &new_psw, sizeof(new_psw));
+       rc = read_guest(vcpu, addr, ar, &new_psw, sizeof(new_psw));
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
        if (!(new_psw.mask & PSW32_MASK_BASE))
@@ -412,14 +430,15 @@ static int handle_lpswe(struct kvm_vcpu *vcpu)
        psw_t new_psw;
        u64 addr;
        int rc;
+       ar_t ar;
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       addr = kvm_s390_get_base_disp_s(vcpu);
+       addr = kvm_s390_get_base_disp_s(vcpu, &ar);
        if (addr & 7)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
-       rc = read_guest(vcpu, addr, &new_psw, sizeof(new_psw));
+       rc = read_guest(vcpu, addr, ar, &new_psw, sizeof(new_psw));
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
        vcpu->arch.sie_block->gpsw = new_psw;
@@ -433,18 +452,19 @@ static int handle_stidp(struct kvm_vcpu *vcpu)
        u64 stidp_data = vcpu->arch.stidp_data;
        u64 operand2;
        int rc;
+       ar_t ar;
 
        vcpu->stat.instruction_stidp++;
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       operand2 = kvm_s390_get_base_disp_s(vcpu);
+       operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
 
        if (operand2 & 7)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
-       rc = write_guest(vcpu, operand2, &stidp_data, sizeof(stidp_data));
+       rc = write_guest(vcpu, operand2, ar, &stidp_data, sizeof(stidp_data));
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
 
@@ -467,6 +487,7 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
        for (n = mem->count - 1; n > 0 ; n--)
                memcpy(&mem->vm[n], &mem->vm[n - 1], sizeof(mem->vm[0]));
 
+       memset(&mem->vm[0], 0, sizeof(mem->vm[0]));
        mem->vm[0].cpus_total = cpus;
        mem->vm[0].cpus_configured = cpus;
        mem->vm[0].cpus_standby = 0;
@@ -478,6 +499,17 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
        ASCEBC(mem->vm[0].cpi, 16);
 }
 
+static void insert_stsi_usr_data(struct kvm_vcpu *vcpu, u64 addr, ar_t ar,
+                                u8 fc, u8 sel1, u16 sel2)
+{
+       vcpu->run->exit_reason = KVM_EXIT_S390_STSI;
+       vcpu->run->s390_stsi.addr = addr;
+       vcpu->run->s390_stsi.ar = ar;
+       vcpu->run->s390_stsi.fc = fc;
+       vcpu->run->s390_stsi.sel1 = sel1;
+       vcpu->run->s390_stsi.sel2 = sel2;
+}
+
 static int handle_stsi(struct kvm_vcpu *vcpu)
 {
        int fc = (vcpu->run->s.regs.gprs[0] & 0xf0000000) >> 28;
@@ -486,6 +518,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
        unsigned long mem = 0;
        u64 operand2;
        int rc = 0;
+       ar_t ar;
 
        vcpu->stat.instruction_stsi++;
        VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2);
@@ -508,7 +541,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
                return 0;
        }
 
-       operand2 = kvm_s390_get_base_disp_s(vcpu);
+       operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
 
        if (operand2 & 0xfff)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -532,16 +565,20 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
                break;
        }
 
-       rc = write_guest(vcpu, operand2, (void *)mem, PAGE_SIZE);
+       rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
        if (rc) {
                rc = kvm_s390_inject_prog_cond(vcpu, rc);
                goto out;
        }
+       if (vcpu->kvm->arch.user_stsi) {
+               insert_stsi_usr_data(vcpu, operand2, ar, fc, sel1, sel2);
+               rc = -EREMOTE;
+       }
        trace_kvm_s390_handle_stsi(vcpu, fc, sel1, sel2, operand2);
        free_page(mem);
        kvm_s390_set_psw_cc(vcpu, 0);
        vcpu->run->s.regs.gprs[0] = 0;
-       return 0;
+       return rc;
 out_no_data:
        kvm_s390_set_psw_cc(vcpu, 3);
 out:
@@ -670,7 +707,7 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
        }
 
        if (vcpu->run->s.regs.gprs[reg1] & PFMF_CF) {
-               if (kvm_s390_check_low_addr_protection(vcpu, start))
+               if (kvm_s390_check_low_addr_prot_real(vcpu, start))
                        return kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm);
        }
 
@@ -776,13 +813,14 @@ int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu)
        int reg, rc, nr_regs;
        u32 ctl_array[16];
        u64 ga;
+       ar_t ar;
 
        vcpu->stat.instruction_lctl++;
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       ga = kvm_s390_get_base_disp_rs(vcpu);
+       ga = kvm_s390_get_base_disp_rs(vcpu, &ar);
 
        if (ga & 3)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -791,7 +829,7 @@ int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu)
        trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, ga);
 
        nr_regs = ((reg3 - reg1) & 0xf) + 1;
-       rc = read_guest(vcpu, ga, ctl_array, nr_regs * sizeof(u32));
+       rc = read_guest(vcpu, ga, ar, ctl_array, nr_regs * sizeof(u32));
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
        reg = reg1;
@@ -814,13 +852,14 @@ int kvm_s390_handle_stctl(struct kvm_vcpu *vcpu)
        int reg, rc, nr_regs;
        u32 ctl_array[16];
        u64 ga;
+       ar_t ar;
 
        vcpu->stat.instruction_stctl++;
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       ga = kvm_s390_get_base_disp_rs(vcpu);
+       ga = kvm_s390_get_base_disp_rs(vcpu, &ar);
 
        if (ga & 3)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -836,7 +875,7 @@ int kvm_s390_handle_stctl(struct kvm_vcpu *vcpu)
                        break;
                reg = (reg + 1) % 16;
        } while (1);
-       rc = write_guest(vcpu, ga, ctl_array, nr_regs * sizeof(u32));
+       rc = write_guest(vcpu, ga, ar, ctl_array, nr_regs * sizeof(u32));
        return rc ? kvm_s390_inject_prog_cond(vcpu, rc) : 0;
 }
 
@@ -847,13 +886,14 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
        int reg, rc, nr_regs;
        u64 ctl_array[16];
        u64 ga;
+       ar_t ar;
 
        vcpu->stat.instruction_lctlg++;
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       ga = kvm_s390_get_base_disp_rsy(vcpu);
+       ga = kvm_s390_get_base_disp_rsy(vcpu, &ar);
 
        if (ga & 7)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -862,7 +902,7 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
        trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, ga);
 
        nr_regs = ((reg3 - reg1) & 0xf) + 1;
-       rc = read_guest(vcpu, ga, ctl_array, nr_regs * sizeof(u64));
+       rc = read_guest(vcpu, ga, ar, ctl_array, nr_regs * sizeof(u64));
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
        reg = reg1;
@@ -884,13 +924,14 @@ static int handle_stctg(struct kvm_vcpu *vcpu)
        int reg, rc, nr_regs;
        u64 ctl_array[16];
        u64 ga;
+       ar_t ar;
 
        vcpu->stat.instruction_stctg++;
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       ga = kvm_s390_get_base_disp_rsy(vcpu);
+       ga = kvm_s390_get_base_disp_rsy(vcpu, &ar);
 
        if (ga & 7)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -906,7 +947,7 @@ static int handle_stctg(struct kvm_vcpu *vcpu)
                        break;
                reg = (reg + 1) % 16;
        } while (1);
-       rc = write_guest(vcpu, ga, ctl_array, nr_regs * sizeof(u64));
+       rc = write_guest(vcpu, ga, ar, ctl_array, nr_regs * sizeof(u64));
        return rc ? kvm_s390_inject_prog_cond(vcpu, rc) : 0;
 }
 
@@ -931,13 +972,14 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
        unsigned long hva, gpa;
        int ret = 0, cc = 0;
        bool writable;
+       ar_t ar;
 
        vcpu->stat.instruction_tprot++;
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       kvm_s390_get_base_disp_sse(vcpu, &address1, &address2);
+       kvm_s390_get_base_disp_sse(vcpu, &address1, &address2, &ar, NULL);
 
        /* we only handle the Linux memory detection case:
         * access key == 0
@@ -946,11 +988,11 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
                return -EOPNOTSUPP;
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
                ipte_lock(vcpu);
-       ret = guest_translate_address(vcpu, address1, &gpa, 1);
+       ret = guest_translate_address(vcpu, address1, ar, &gpa, 1);
        if (ret == PGM_PROTECTION) {
                /* Write protected? Try again with read-only... */
                cc = 1;
-               ret = guest_translate_address(vcpu, address1, &gpa, 0);
+               ret = guest_translate_address(vcpu, address1, ar, &gpa, 0);
        }
        if (ret) {
                if (ret == PGM_ADDRESSING || ret == PGM_TRANSLATION_SPEC) {
index 23b1e86b212245dcf7a95fb4ab82ab99f8749735..72e58bd2bee78162e963dc2bd531e40e03e29d97 100644 (file)
@@ -393,6 +393,9 @@ static int handle_sigp_order_in_user_space(struct kvm_vcpu *vcpu, u8 order_code)
        case SIGP_STORE_STATUS_AT_ADDRESS:
                vcpu->stat.instruction_sigp_store_status++;
                break;
+       case SIGP_STORE_ADDITIONAL_STATUS:
+               vcpu->stat.instruction_sigp_store_adtl_status++;
+               break;
        case SIGP_SET_PREFIX:
                vcpu->stat.instruction_sigp_prefix++;
                break;
@@ -431,7 +434,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       order_code = kvm_s390_get_base_disp_rs(vcpu);
+       order_code = kvm_s390_get_base_disp_rs(vcpu, NULL);
        if (handle_sigp_order_in_user_space(vcpu, order_code))
                return -EOPNOTSUPP;
 
@@ -473,7 +476,7 @@ int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu)
        int r3 = vcpu->arch.sie_block->ipa & 0x000f;
        u16 cpu_addr = vcpu->run->s.regs.gprs[r3];
        struct kvm_vcpu *dest_vcpu;
-       u8 order_code = kvm_s390_get_base_disp_rs(vcpu);
+       u8 order_code = kvm_s390_get_base_disp_rs(vcpu, NULL);
 
        trace_kvm_s390_handle_sigp_pei(vcpu, order_code, cpu_addr);
 
index 653a7ec09ef53a5bd4775e33280f4930d87b1e20..3208d33a48cb62a7a0704ba9a6216193f192c645 100644 (file)
@@ -9,6 +9,13 @@
 #undef TRACE_INCLUDE_FILE
 #define TRACE_INCLUDE_FILE trace-s390
 
+/*
+ * The TRACE_SYSTEM_VAR defaults to TRACE_SYSTEM, but must be a
+ * legitimate C variable. It is not exported to user space.
+ */
+#undef TRACE_SYSTEM_VAR
+#define TRACE_SYSTEM_VAR kvm_s390
+
 /*
  * Trace point for the creation of the kvm instance.
  */
index 179a2c20b01f143a51a897d9b85e33198bf881a7..bb3367c5cb0b41472fb93fc9c8b1d06891feea40 100644 (file)
@@ -60,22 +60,20 @@ static inline int mmap_is_legacy(void)
        return sysctl_legacy_va_layout;
 }
 
-static unsigned long mmap_rnd(void)
+unsigned long arch_mmap_rnd(void)
 {
-       if (!(current->flags & PF_RANDOMIZE))
-               return 0;
        if (is_32bit_task())
                return (get_random_int() & 0x7ff) << PAGE_SHIFT;
        else
                return (get_random_int() & mmap_rnd_mask) << PAGE_SHIFT;
 }
 
-static unsigned long mmap_base_legacy(void)
+static unsigned long mmap_base_legacy(unsigned long rnd)
 {
-       return TASK_UNMAPPED_BASE + mmap_rnd();
+       return TASK_UNMAPPED_BASE + rnd;
 }
 
-static inline unsigned long mmap_base(void)
+static inline unsigned long mmap_base(unsigned long rnd)
 {
        unsigned long gap = rlimit(RLIMIT_STACK);
 
@@ -84,7 +82,7 @@ static inline unsigned long mmap_base(void)
        else if (gap > MAX_GAP)
                gap = MAX_GAP;
        gap &= PAGE_MASK;
-       return STACK_TOP - stack_maxrandom_size() - mmap_rnd() - gap;
+       return STACK_TOP - stack_maxrandom_size() - rnd - gap;
 }
 
 unsigned long
@@ -179,17 +177,6 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        return addr;
 }
 
-unsigned long randomize_et_dyn(void)
-{
-       unsigned long base;
-
-       base = STACK_TOP / 3 * 2;
-       if (!is_32bit_task())
-               /* Align to 4GB */
-               base &= ~((1UL << 32) - 1);
-       return base + mmap_rnd();
-}
-
 #ifndef CONFIG_64BIT
 
 /*
@@ -198,15 +185,20 @@ unsigned long randomize_et_dyn(void)
  */
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
+       unsigned long random_factor = 0UL;
+
+       if (current->flags & PF_RANDOMIZE)
+               random_factor = arch_mmap_rnd();
+
        /*
         * Fall back to the standard layout if the personality
         * bit is set, or if the expected stack growth is unlimited:
         */
        if (mmap_is_legacy()) {
-               mm->mmap_base = mmap_base_legacy();
+               mm->mmap_base = mmap_base_legacy(random_factor);
                mm->get_unmapped_area = arch_get_unmapped_area;
        } else {
-               mm->mmap_base = mmap_base();
+               mm->mmap_base = mmap_base(random_factor);
                mm->get_unmapped_area = arch_get_unmapped_area_topdown;
        }
 }
@@ -273,15 +265,20 @@ s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr,
  */
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
+       unsigned long random_factor = 0UL;
+
+       if (current->flags & PF_RANDOMIZE)
+               random_factor = arch_mmap_rnd();
+
        /*
         * Fall back to the standard layout if the personality
         * bit is set, or if the expected stack growth is unlimited:
         */
        if (mmap_is_legacy()) {
-               mm->mmap_base = mmap_base_legacy();
+               mm->mmap_base = mmap_base_legacy(random_factor);
                mm->get_unmapped_area = s390_get_unmapped_area;
        } else {
-               mm->mmap_base = mmap_base();
+               mm->mmap_base = mmap_base(random_factor);
                mm->get_unmapped_area = s390_get_unmapped_area_topdown;
        }
 }
index f0b85443e06093d2f5d3d4c5dbe85554e459c138..b2c76f64c530f257db9a0550f6f551cc6acd9997 100644 (file)
@@ -780,8 +780,8 @@ static int zpci_scan_bus(struct zpci_dev *zdev)
                zpci_cleanup_bus_resources(zdev);
                return -EIO;
        }
-
        zdev->bus->max_bus_speed = zdev->max_bus_speed;
+       pci_bus_add_devices(zdev->bus);
        return 0;
 }
 
index eb4ef274ae9bd7193ec748606816d9800b6545bf..50057fed819ddf3c07a8e16841c65d63cbaa5168 100644 (file)
@@ -162,6 +162,10 @@ config NEED_DMA_MAP_STATE
 config NEED_SG_DMA_LENGTH
        def_bool y
 
+config PGTABLE_LEVELS
+       default 3 if X2TLB
+       default 2
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
index 1bc09ee7948f00a678d9564331dcdd2ae9cb7c78..d5462b7bc5148893f4348aa5805fd74a3a861ed2 100644 (file)
@@ -58,20 +58,23 @@ static void pcibios_scanbus(struct pci_channel *hose)
 
        need_domain_info = need_domain_info || hose->index;
        hose->need_domain_info = need_domain_info;
-       if (bus) {
-               next_busno = bus->busn_res.end + 1;
-               /* Don't allow 8-bit bus number overflow inside the hose -
-                  reserve some space for bridges. */
-               if (next_busno > 224) {
-                       next_busno = 0;
-                       need_domain_info = 1;
-               }
 
-               pci_bus_size_bridges(bus);
-               pci_bus_assign_resources(bus);
-       } else {
+       if (!bus) {
                pci_free_resource_list(&resources);
+               return;
+       }
+
+       next_busno = bus->busn_res.end + 1;
+       /* Don't allow 8-bit bus number overflow inside the hose -
+          reserve some space for bridges. */
+       if (next_busno > 224) {
+               next_busno = 0;
+               need_domain_info = 1;
        }
+
+       pci_bus_size_bridges(bus);
+       pci_bus_assign_resources(bus);
+       pci_bus_add_devices(bus);
 }
 
 /*
index 67a049e75ec12f60cf7f1d1934d94122eb2f2617..9d209a07235eaeda7154b170b19b04c395d4b11b 100644 (file)
@@ -993,7 +993,7 @@ static struct unwinder dwarf_unwinder = {
        .rating = 150,
 };
 
-static void dwarf_unwinder_cleanup(void)
+static void __init dwarf_unwinder_cleanup(void)
 {
        struct dwarf_fde *fde, *next_fde;
        struct dwarf_cie *cie, *next_cie;
@@ -1009,6 +1009,10 @@ static void dwarf_unwinder_cleanup(void)
        rbtree_postorder_for_each_entry_safe(cie, next_cie, &cie_root, node)
                kfree(cie);
 
+       if (dwarf_reg_pool)
+               mempool_destroy(dwarf_reg_pool);
+       if (dwarf_frame_pool)
+               mempool_destroy(dwarf_frame_pool);
        kmem_cache_destroy(dwarf_reg_cachep);
        kmem_cache_destroy(dwarf_frame_cachep);
 }
@@ -1176,17 +1180,13 @@ static int __init dwarf_unwinder_init(void)
                        sizeof(struct dwarf_reg), 0,
                        SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL);
 
-       dwarf_frame_pool = mempool_create(DWARF_FRAME_MIN_REQ,
-                                         mempool_alloc_slab,
-                                         mempool_free_slab,
-                                         dwarf_frame_cachep);
+       dwarf_frame_pool = mempool_create_slab_pool(DWARF_FRAME_MIN_REQ,
+                                                   dwarf_frame_cachep);
        if (!dwarf_frame_pool)
                goto out;
 
-       dwarf_reg_pool = mempool_create(DWARF_REG_MIN_REQ,
-                                        mempool_alloc_slab,
-                                        mempool_free_slab,
-                                        dwarf_reg_cachep);
+       dwarf_reg_pool = mempool_create_slab_pool(DWARF_REG_MIN_REQ,
+                                                 dwarf_reg_cachep);
        if (!dwarf_reg_pool)
                goto out;
 
index 0b34f2a704fe1d2fdcf03b49fe37d73a7725ecf7..97292890b51bc4d36121cfa35fde08c79e3260f5 100644 (file)
@@ -329,8 +329,6 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
        if (err)
                return -EFAULT;
 
-       set_fs(USER_DS);
-
        pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
                 current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
 
@@ -408,8 +406,6 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
        if (err)
                return -EFAULT;
 
-       set_fs(USER_DS);
-
        pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
                 current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
 
index 71993c6a7d94b0f6da895f78d96176de5aa31e14..0462995d4d7f66ed9531948aaf0d3ef9bdd63b63 100644 (file)
@@ -457,8 +457,6 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs
 
        regs->pc = neff_sign_extend((unsigned long)ksig->ka.sa.sa_handler);
 
-       set_fs(USER_DS);
-
        /* Broken %016Lx */
        pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
                 signal, current->comm, current->pid, frame,
@@ -547,8 +545,6 @@ static int setup_rt_frame(struct ksignal *kig, sigset_t *set,
        regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
        regs->pc = neff_sign_extend((unsigned long)ksig->ka.sa.sa_handler);
 
-       set_fs(USER_DS);
-
        pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
                 signal, current->comm, current->pid, frame,
                 regs->pc >> 32, regs->pc & 0xffffffff,
index efb00ec758058afebb97f912e2bc6f142bbd43ff..e49502acbab401669f4197b005cffcebbf2e8060 100644 (file)
@@ -146,6 +146,10 @@ config GENERIC_ISA_DMA
 config ARCH_SUPPORTS_DEBUG_PAGEALLOC
        def_bool y if SPARC64
 
+config PGTABLE_LEVELS
+       default 4 if 64BIT
+       default 3
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
index ec2e2e2aba7d8f15419aa12bc6f790993f8c54d4..cc9b04a2b11b6394cfcad8b485df1fac6f598583 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _ASM_SPARC_JUMP_LABEL_H
 #define _ASM_SPARC_JUMP_LABEL_H
 
-#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
 
 #include <linux/types.h>
 
@@ -22,8 +22,6 @@ l_yes:
        return true;
 }
 
-#endif /* __KERNEL__ */
-
 typedef u32 jump_label_t;
 
 struct jump_entry {
@@ -32,4 +30,5 @@ struct jump_entry {
        jump_label_t key;
 };
 
+#endif  /* __ASSEMBLY__ */
 #endif
index 899b7203a4e4a27545b1dc6a41728015dab33e5a..4371f72ff02500d57c56343a254468375324490c 100644 (file)
@@ -34,15 +34,17 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
 
        root_bus = pci_scan_root_bus(&ofdev->dev, 0, info->ops, info,
                                     &resources);
-       if (root_bus) {
-               /* Setup IRQs of all devices using custom routines */
-               pci_fixup_irqs(pci_common_swizzle, info->map_irq);
-
-               /* Assign devices with resources */
-               pci_assign_unassigned_resources();
-       } else {
+       if (!root_bus) {
                pci_free_resource_list(&resources);
+               return;
        }
+
+       /* Setup IRQs of all devices using custom routines */
+       pci_fixup_irqs(pci_common_swizzle, info->map_irq);
+
+       /* Assign devices with resources */
+       pci_assign_unassigned_resources();
+       pci_bus_add_devices(root_bus);
 }
 
 void pcibios_fixup_bus(struct pci_bus *pbus)
index 99632a87e697bcc37fd4ba3fd9de8bb395cdb9e3..26c80e18d7b1b47bd74e9fce01bdb48eeb88fcbd 100644 (file)
@@ -130,26 +130,26 @@ static struct mdesc_mem_ops memblock_mdesc_ops = {
 static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
 {
        unsigned int handle_size;
+       struct mdesc_handle *hp;
+       unsigned long addr;
        void *base;
 
        handle_size = (sizeof(struct mdesc_handle) -
                       sizeof(struct mdesc_hdr) +
                       mdesc_size);
 
+       /*
+        * Allocation has to succeed because mdesc update would be missed
+        * and such events are not retransmitted.
+        */
        base = kmalloc(handle_size + 15, GFP_KERNEL | __GFP_NOFAIL);
-       if (base) {
-               struct mdesc_handle *hp;
-               unsigned long addr;
-
-               addr = (unsigned long)base;
-               addr = (addr + 15UL) & ~15UL;
-               hp = (struct mdesc_handle *) addr;
+       addr = (unsigned long)base;
+       addr = (addr + 15UL) & ~15UL;
+       hp = (struct mdesc_handle *) addr;
 
-               mdesc_handle_init(hp, handle_size, base);
-               return hp;
-       }
+       mdesc_handle_init(hp, handle_size, base);
 
-       return NULL;
+       return hp;
 }
 
 static void mdesc_kfree(struct mdesc_handle *hp)
index 9ce5afe167ff509288b21605a2f9a35f96ff36dc..6f7251fd2eabc6b5b5790c2aa4486c84c042f814 100644 (file)
@@ -639,10 +639,7 @@ static void pci_claim_bus_resources(struct pci_bus *bus)
                                       (unsigned long long)r->end,
                                       (unsigned int)r->flags);
 
-                       if (pci_claim_resource(dev, i) == 0)
-                               continue;
-
-                       pci_claim_bridge_resource(dev, i);
+                       pci_claim_resource(dev, i);
                }
        }
 
@@ -677,11 +674,10 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
        }
 
        pci_of_scan_bus(pbm, node, bus);
-       pci_bus_add_devices(bus);
        pci_bus_register_of_sysfs(bus);
 
        pci_claim_bus_resources(bus);
-
+       pci_bus_add_devices(bus);
        return bus;
 }
 
index 6cc78c213c0169b0c15bcc19c0d675328ac47bcc..24384e1dc33d30bd22a8bc819f7b87daf0d3612b 100644 (file)
@@ -391,12 +391,16 @@ static void __init pcic_pbm_scan_bus(struct linux_pcic *pcic)
        struct linux_pbm_info *pbm = &pcic->pbm;
 
        pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, &pcic_ops, pbm);
+       if (!pbm->pci_bus)
+               return;
+
 #if 0 /* deadwood transplanted from sparc64 */
        pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
        pci_record_assignments(pbm, pbm->pci_bus);
        pci_assign_unassigned(pbm, pbm->pci_bus);
        pci_fixup_irq(pbm, pbm->pci_bus);
 #endif
+       pci_bus_add_devices(pbm->pci_bus);
 }
 
 /*
index 2f80d23a0a44964ebff804a2ab4428b9f30cb162..18147a5523d947736a3e7c0815a7eeb3526ec271 100644 (file)
@@ -181,17 +181,13 @@ static struct clocksource timer_cs = {
        .rating = 100,
        .read   = timer_cs_read,
        .mask   = CLOCKSOURCE_MASK(64),
-       .shift  = 2,
        .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static __init int setup_timer_cs(void)
 {
        timer_cs_enabled = 1;
-       timer_cs.mult = clocksource_hz2mult(sparc_config.clock_rate,
-                                           timer_cs.shift);
-
-       return clocksource_register(&timer_cs);
+       return clocksource_register_hz(&timer_cs, sparc_config.clock_rate);
 }
 
 #ifdef CONFIG_SMP
index 7cca41842a9e5acc9382f73896278f3404772eb3..0142d578b5a84d5277e7bdf81510aba80dc9ff9a 100644 (file)
@@ -147,6 +147,11 @@ config ARCH_DEFCONFIG
        default "arch/tile/configs/tilepro_defconfig" if !TILEGX
        default "arch/tile/configs/tilegx_defconfig" if TILEGX
 
+config PGTABLE_LEVELS
+       int
+       default 3 if 64BIT
+       default 2
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
index 325df47f114db5c76333b01c2e5c9705662d4c19..9475a74cd53ac9ed1711dc92339fc47d2d06796b 100644 (file)
@@ -339,6 +339,8 @@ int __init pcibios_init(void)
                        struct pci_bus *next_bus;
                        struct pci_dev *dev;
 
+                       pci_bus_add_devices(root_bus);
+
                        list_for_each_entry(dev, &root_bus->devices, bus_list) {
                                /*
                                 * Find the PCI host controller, ie. the 1st
index 2c95f37ebbed5bf9188e2305a765ee3ed26037a0..b1df847d0686706e455580293fe692255745282b 100644 (file)
@@ -1030,6 +1030,8 @@ int __init pcibios_init(void)
 alloc_mem_map_failed:
                        break;
                }
+
+               pci_bus_add_devices(root_bus);
        }
 
        return 0;
index d412b0856c0a2622b13b9bc84dc39f65c1b5b08c..00178ecf9aeab4731ffd24d86ff7bc28252e23b6 100644 (file)
@@ -257,34 +257,34 @@ void update_vsyscall_tz(void)
 
 void update_vsyscall(struct timekeeper *tk)
 {
-       if (tk->tkr.clock != &cycle_counter_cs)
+       if (tk->tkr_mono.clock != &cycle_counter_cs)
                return;
 
        write_seqcount_begin(&vdso_data->tb_seq);
 
-       vdso_data->cycle_last           = tk->tkr.cycle_last;
-       vdso_data->mask                 = tk->tkr.mask;
-       vdso_data->mult                 = tk->tkr.mult;
-       vdso_data->shift                = tk->tkr.shift;
+       vdso_data->cycle_last           = tk->tkr_mono.cycle_last;
+       vdso_data->mask                 = tk->tkr_mono.mask;
+       vdso_data->mult                 = tk->tkr_mono.mult;
+       vdso_data->shift                = tk->tkr_mono.shift;
 
        vdso_data->wall_time_sec        = tk->xtime_sec;
-       vdso_data->wall_time_snsec      = tk->tkr.xtime_nsec;
+       vdso_data->wall_time_snsec      = tk->tkr_mono.xtime_nsec;
 
        vdso_data->monotonic_time_sec   = tk->xtime_sec
                                        + tk->wall_to_monotonic.tv_sec;
-       vdso_data->monotonic_time_snsec = tk->tkr.xtime_nsec
+       vdso_data->monotonic_time_snsec = tk->tkr_mono.xtime_nsec
                                        + ((u64)tk->wall_to_monotonic.tv_nsec
-                                               << tk->tkr.shift);
+                                               << tk->tkr_mono.shift);
        while (vdso_data->monotonic_time_snsec >=
-                                       (((u64)NSEC_PER_SEC) << tk->tkr.shift)) {
+                                       (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
                vdso_data->monotonic_time_snsec -=
-                                       ((u64)NSEC_PER_SEC) << tk->tkr.shift;
+                                       ((u64)NSEC_PER_SEC) << tk->tkr_mono.shift;
                vdso_data->monotonic_time_sec++;
        }
 
        vdso_data->wall_time_coarse_sec = tk->xtime_sec;
-       vdso_data->wall_time_coarse_nsec = (long)(tk->tkr.xtime_nsec >>
-                                                tk->tkr.shift);
+       vdso_data->wall_time_coarse_nsec = (long)(tk->tkr_mono.xtime_nsec >>
+                                                tk->tkr_mono.shift);
 
        vdso_data->monotonic_time_coarse_sec =
                vdso_data->wall_time_coarse_sec + tk->wall_to_monotonic.tv_sec;
index a7520c90f62df53981d57dea1d1a3b90f0958ff8..5dbfe3d9107c83356efa99733739630eb43d0eaa 100644 (file)
@@ -155,3 +155,8 @@ config MMAPPER
 
 config NO_DMA
        def_bool y
+
+config PGTABLE_LEVELS
+       int
+       default 3 if 3_LEVEL_PGTABLES
+       default 2
index 374a055a8e6bb5886ead0595dabaa5627cf5868a..d45fa5f3e9c41dae187ebebf59f18c8b595cef9c 100644 (file)
@@ -266,17 +266,10 @@ static int __init pci_common_init(void)
        pci_fixup_irqs(pci_common_swizzle, pci_puv3_map_irq);
 
        if (!pci_has_flag(PCI_PROBE_ONLY)) {
-               /*
-                * Size the bridge windows.
-                */
                pci_bus_size_bridges(puv3_bus);
-
-               /*
-                * Assign resources.
-                */
                pci_bus_assign_resources(puv3_bus);
        }
-
+       pci_bus_add_devices(puv3_bus);
        return 0;
 }
 subsys_initcall(pci_common_init);
index b7d31ca5518744983c77bc8339f30756621dfea0..d43e7e1c784b308ee168a988536aa00e514e949c 100644 (file)
@@ -87,7 +87,7 @@ config X86
        select HAVE_ARCH_KMEMCHECK
        select HAVE_ARCH_KASAN if X86_64 && SPARSEMEM_VMEMMAP
        select HAVE_USER_RETURN_NOTIFIER
-       select ARCH_BINFMT_ELF_RANDOMIZE_PIE
+       select ARCH_HAS_ELF_RANDOMIZE
        select HAVE_ARCH_JUMP_LABEL
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select SPARSE_IRQ
@@ -99,6 +99,7 @@ config X86
        select IRQ_FORCED_THREADING
        select HAVE_BPF_JIT if X86_64
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+       select HAVE_ARCH_HUGE_VMAP if X86_64 || (X86_32 && X86_PAE)
        select ARCH_HAS_SG_CHAIN
        select CLKEVT_I8253
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
@@ -235,12 +236,10 @@ config ARCH_WANT_GENERAL_HUGETLB
        def_bool y
 
 config ZONE_DMA32
-       bool
-       default X86_64
+       def_bool y if X86_64
 
 config AUDIT_ARCH
-       bool
-       default X86_64
+       def_bool y if X86_64
 
 config ARCH_SUPPORTS_OPTIMIZED_INLINING
        def_bool y
@@ -279,6 +278,12 @@ config ARCH_SUPPORTS_UPROBES
 config FIX_EARLYCON_MEM
        def_bool y
 
+config PGTABLE_LEVELS
+       int
+       default 4 if X86_64
+       default 3 if X86_PAE
+       default 2
+
 source "init/Kconfig"
 source "kernel/Kconfig.freezer"
 
@@ -716,17 +721,6 @@ endif #HYPERVISOR_GUEST
 config NO_BOOTMEM
        def_bool y
 
-config MEMTEST
-       bool "Memtest"
-       ---help---
-         This option adds a kernel parameter 'memtest', which allows memtest
-         to be set.
-               memtest=0, mean disabled; -- default
-               memtest=1, mean do 1 test pattern;
-               ...
-               memtest=4, mean do 4 test patterns.
-         If you are unsure how to answer this question, answer N.
-
 source "arch/x86/Kconfig.cpu"
 
 config HPET_TIMER
@@ -891,7 +885,8 @@ config UP_LATE_INIT
        depends on !SMP && X86_LOCAL_APIC
 
 config X86_UP_APIC
-       bool "Local APIC support on uniprocessors"
+       bool "Local APIC support on uniprocessors" if !PCI_MSI
+       default PCI_MSI
        depends on X86_32 && !SMP && !X86_32_NON_STANDARD
        ---help---
          A local APIC (Advanced Programmable Interrupt Controller) is an
@@ -903,10 +898,6 @@ config X86_UP_APIC
          performance counters), and the NMI watchdog which detects hard
          lockups.
 
-config X86_UP_APIC_MSI
-       def_bool y
-       select X86_UP_APIC if X86_32 && !SMP && !X86_32_NON_STANDARD && PCI_MSI
-
 config X86_UP_IOAPIC
        bool "IO-APIC support on uniprocessors"
        depends on X86_UP_APIC
@@ -925,8 +916,8 @@ config X86_LOCAL_APIC
        select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
 
 config X86_IO_APIC
-       def_bool X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC
-       depends on X86_LOCAL_APIC
+       def_bool y
+       depends on X86_LOCAL_APIC || X86_UP_IOAPIC
        select IRQ_DOMAIN
 
 config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
@@ -1145,10 +1136,10 @@ config MICROCODE_OLD_INTERFACE
        depends on MICROCODE
 
 config MICROCODE_INTEL_EARLY
-       def_bool n
+       bool
 
 config MICROCODE_AMD_EARLY
-       def_bool n
+       bool
 
 config MICROCODE_EARLY
        bool "Early load microcode"
@@ -1300,14 +1291,14 @@ config ARCH_DMA_ADDR_T_64BIT
        def_bool y
        depends on X86_64 || HIGHMEM64G
 
-config DIRECT_GBPAGES
-       bool "Enable 1GB pages for kernel pagetables" if EXPERT
-       default y
-       depends on X86_64
+config X86_DIRECT_GBPAGES
+       def_bool y
+       depends on X86_64 && !DEBUG_PAGEALLOC && !KMEMCHECK
        ---help---
-         Allow the kernel linear mapping to use 1GB pages on CPUs that
-         support it. This can improve the kernel's performance a tiny bit by
-         reducing TLB pressure. If in doubt, say "Y".
+         Certain kernel features effectively disable kernel
+         linear 1 GB mappings (even if the CPU otherwise
+         supports them), so don't confuse the user by printing
+         that we have them enabled.
 
 # Common NUMA Features
 config NUMA
@@ -1747,14 +1738,11 @@ config KEXEC_VERIFY_SIG
        depends on KEXEC_FILE
        ---help---
          This option makes kernel signature verification mandatory for
-         kexec_file_load() syscall. If kernel is signature can not be
-         verified, kexec_file_load() will fail.
-
-         This option enforces signature verification at generic level.
-         One needs to enable signature verification for type of kernel
-         image being loaded to make sure it works. For example, enable
-         bzImage signature verification option to be able to load and
-         verify signatures of bzImage. Otherwise kernel loading will fail.
+         the kexec_file_load() syscall.
+
+         In addition to that option, you need to enable signature
+         verification for the corresponding kernel image type being
+         loaded in order for this to work.
 
 config KEXEC_BZIMAGE_VERIFY_SIG
        bool "Enable bzImage signature verification support"
index bb1376381985edb9f96e49c0a1b0269e56bd0f9e..d7b1f655b3ef4c2e14a4976fa565fe67d0159607 100644 (file)
@@ -295,7 +295,8 @@ static unsigned long find_random_addr(unsigned long minimum,
        return slots_fetch_random();
 }
 
-unsigned char *choose_kernel_location(unsigned char *input,
+unsigned char *choose_kernel_location(struct boot_params *boot_params,
+                                     unsigned char *input,
                                      unsigned long input_size,
                                      unsigned char *output,
                                      unsigned long output_size)
@@ -315,6 +316,8 @@ unsigned char *choose_kernel_location(unsigned char *input,
        }
 #endif
 
+       boot_params->hdr.loadflags |= KASLR_FLAG;
+
        /* Record the various known unsafe memory ranges. */
        mem_avoid_init((unsigned long)input, input_size,
                       (unsigned long)output, output_size);
index 1d7fbbcc196d6f8b661545130972453f109e27d7..8ef964ddc18ec656b1e3b0f038adf134484dbdd2 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/page_types.h>
 #include <asm/boot.h>
 #include <asm/asm-offsets.h>
+#include <asm/bootparam.h>
 
        __HEAD
 ENTRY(startup_32)
@@ -102,7 +103,7 @@ preferred_addr:
         * Test KEEP_SEGMENTS flag to see if the bootloader is asking
         * us to not reload segments
         */
-       testb   $(1<<6), BP_loadflags(%esi)
+       testb   $KEEP_SEGMENTS, BP_loadflags(%esi)
        jnz     1f
 
        cli
index 6b1766c6c08205f3bda8a527dff88097b48e77e3..b0c0d16ef58d1099342c97aff83767dd35c73691 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/msr.h>
 #include <asm/processor-flags.h>
 #include <asm/asm-offsets.h>
+#include <asm/bootparam.h>
 
        __HEAD
        .code32
@@ -46,7 +47,7 @@ ENTRY(startup_32)
         * Test KEEP_SEGMENTS flag to see if the bootloader is asking
         * us to not reload segments
         */
-       testb $(1<<6), BP_loadflags(%esi)
+       testb $KEEP_SEGMENTS, BP_loadflags(%esi)
        jnz 1f
 
        cli
@@ -164,7 +165,7 @@ ENTRY(startup_32)
        /* After gdt is loaded */
        xorl    %eax, %eax
        lldt    %ax
-       movl    $0x20, %eax
+       movl    $__BOOT_TSS, %eax
        ltr     %ax
 
        /*
index a950864a64dab3d558197c77bef3c56a07961494..a107b935e22fbc9a749ddf975cf72ea187cb1fa2 100644 (file)
@@ -377,6 +377,9 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
 
        real_mode = rmode;
 
+       /* Clear it for solely in-kernel use */
+       real_mode->hdr.loadflags &= ~KASLR_FLAG;
+
        sanitize_boot_params(real_mode);
 
        if (real_mode->screen_info.orig_video_mode == 7) {
@@ -401,7 +404,7 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
         * the entire decompressed kernel plus relocation table, or the
         * entire decompressed kernel plus .bss and .brk sections.
         */
-       output = choose_kernel_location(input_data, input_len, output,
+       output = choose_kernel_location(real_mode, input_data, input_len, output,
                                        output_len > run_size ? output_len
                                                              : run_size);
 
index 04477d68403f1fe6197d82276033ce27338c1bac..89dd0d78013aaff6c889340e0e3caceb4c8f8c88 100644 (file)
@@ -57,7 +57,8 @@ int cmdline_find_option_bool(const char *option);
 
 #if CONFIG_RANDOMIZE_BASE
 /* aslr.c */
-unsigned char *choose_kernel_location(unsigned char *input,
+unsigned char *choose_kernel_location(struct boot_params *boot_params,
+                                     unsigned char *input,
                                      unsigned long input_size,
                                      unsigned char *output,
                                      unsigned long output_size);
@@ -65,7 +66,8 @@ unsigned char *choose_kernel_location(unsigned char *input,
 bool has_cpuflag(int flag);
 #else
 static inline
-unsigned char *choose_kernel_location(unsigned char *input,
+unsigned char *choose_kernel_location(struct boot_params *boot_params,
+                                     unsigned char *input,
                                      unsigned long input_size,
                                      unsigned char *output,
                                      unsigned long output_size)
index 493f3fd9f1391815c29e06c2163f3225b4e52063..318b8465d30204cad7006bf0889672e0da093aed 100644 (file)
@@ -30,7 +30,7 @@ int strcmp(const char *str1, const char *str2)
        int delta = 0;
 
        while (*s1 || *s2) {
-               delta = *s2 - *s1;
+               delta = *s1 - *s2;
                if (delta)
                        return delta;
                s1++;
index 748e8d06290a668ff5c417197cf5c2bc5c7a16e3..aa8a96b052e30263d60afc6b81a60e387fc55773 100644 (file)
 /*
  * Common variables
  */
-int adapter;                   /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
-u16 video_segment;
+int adapter;           /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
 int force_x, force_y;  /* Don't query the BIOS for cols/rows */
-
 int do_restore;                /* Screen contents changed during mode flip */
 int graphic_mode;      /* Graphic mode with linear frame buffer */
 
index 43eda284d27fe96c2a4d407273f4b8d61bae87e2..05111bb8d018e38c71ae278ee0a78ccff76e34e2 100644 (file)
@@ -17,6 +17,8 @@
 #include "video.h"
 #include "vesa.h"
 
+static u16 video_segment;
+
 static void store_cursor_position(void)
 {
        struct biosregs ireg, oreg;
index 0bb25491262d00f941001d3f7f7b2fc800212250..b54e0328c449e981013dc1edc46d331827e290c4 100644 (file)
@@ -91,7 +91,6 @@ int mode_defined(u16 mode);   /* video.c */
 #define ADAPTER_VGA    2
 
 extern int adapter;
-extern u16 video_segment;
 extern int force_x, force_y;   /* Don't query the BIOS for cols/rows */
 extern int do_restore;         /* Restore screen contents */
 extern int graphic_mode;       /* Graphics mode with linear frame buffer */
index 419819d6dab3b7573196dc685c9bc9ea236a147f..aaa1118bf01e864f50dad66a0e1099bb50de08d7 100644 (file)
@@ -248,7 +248,7 @@ CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_TT_NEWSCHED=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_UHCI_HCD=y
 CONFIG_USB_PRINTER=y
index 4c311ddd973bb60686079a5c4d2831cd0bf224c7..315b861065725a4cd154744ee45d5331de6fb828 100644 (file)
@@ -243,7 +243,7 @@ CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_TT_NEWSCHED=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_UHCI_HCD=y
 CONFIG_USB_PRINTER=y
index 26d49ebae0404ee74fea7a5e7f6bd7d22b9bad80..225be06edc80982f9509e25af09e1ac0a0232237 100644 (file)
@@ -178,7 +178,7 @@ continue_block:
        ## 2a) PROCESS FULL BLOCKS:
        ################################################################
 full_block:
-       movq    $128,%rax
+       movl    $128,%eax
        lea     128*8*2(block_0), block_1
        lea     128*8*3(block_0), block_2
        add     $128*8*1, block_0
index a039d21986a21c87e9bdf9a41117a726ea3bf77f..a350c990dc86c86bdf5ec4396a9db17dd8dc7bfa 100644 (file)
@@ -264,7 +264,7 @@ ENTRY(twofish_enc_blk)
        movq    R1,     8(%rsi)
 
        popq    R1
-       movq    $1,%rax
+       movl    $1,%eax
        ret
 ENDPROC(twofish_enc_blk)
 
@@ -316,6 +316,6 @@ ENTRY(twofish_dec_blk)
        movq    R1,     8(%rsi)
 
        popq    R1
-       movq    $1,%rax
+       movl    $1,%eax
        ret
 ENDPROC(twofish_dec_blk)
index e785b422b76686b3bf79d95be5aebd20b961cef8..bb635c6418692f4fea1d02fce3b1c170f1a38b0f 100644 (file)
@@ -3,7 +3,6 @@
 #
 
 obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o
-obj-$(CONFIG_IA32_EMULATION) += nosyscall.o syscall_ia32.o
 
 obj-$(CONFIG_IA32_AOUT) += ia32_aout.o
 
index d0165c9a293241559c48742d6c0fb8df3e4fcf82..c81d35e6c7f1d91c22734793c006c0f5f33c0c10 100644 (file)
@@ -161,8 +161,7 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 }
 
 static int ia32_restore_sigcontext(struct pt_regs *regs,
-                                  struct sigcontext_ia32 __user *sc,
-                                  unsigned int *pax)
+                                  struct sigcontext_ia32 __user *sc)
 {
        unsigned int tmpflags, err = 0;
        void __user *buf;
@@ -184,7 +183,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
                RELOAD_SEG(es);
 
                COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
-               COPY(dx); COPY(cx); COPY(ip);
+               COPY(dx); COPY(cx); COPY(ip); COPY(ax);
                /* Don't touch extended registers */
 
                COPY_SEG_CPL3(cs);
@@ -197,12 +196,12 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
 
                get_user_ex(tmp, &sc->fpstate);
                buf = compat_ptr(tmp);
-
-               get_user_ex(*pax, &sc->ax);
        } get_user_catch(err);
 
        err |= restore_xstate_sig(buf, 1);
 
+       force_iret();
+
        return err;
 }
 
@@ -211,7 +210,6 @@ asmlinkage long sys32_sigreturn(void)
        struct pt_regs *regs = current_pt_regs();
        struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8);
        sigset_t set;
-       unsigned int ax;
 
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
@@ -224,9 +222,9 @@ asmlinkage long sys32_sigreturn(void)
 
        set_current_blocked(&set);
 
-       if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
+       if (ia32_restore_sigcontext(regs, &frame->sc))
                goto badframe;
-       return ax;
+       return regs->ax;
 
 badframe:
        signal_fault(regs, frame, "32bit sigreturn");
@@ -238,7 +236,6 @@ asmlinkage long sys32_rt_sigreturn(void)
        struct pt_regs *regs = current_pt_regs();
        struct rt_sigframe_ia32 __user *frame;
        sigset_t set;
-       unsigned int ax;
 
        frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
 
@@ -249,13 +246,13 @@ asmlinkage long sys32_rt_sigreturn(void)
 
        set_current_blocked(&set);
 
-       if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
+       if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
        if (compat_restore_altstack(&frame->uc.uc_stack))
                goto badframe;
 
-       return ax;
+       return regs->ax;
 
 badframe:
        signal_fault(regs, frame, "32bit rt sigreturn");
index 156ebcab4ada6d54cf8992fcd95398af390f41cc..a821b1cd4fa7a2748cce60ba986ef63d27efb131 100644 (file)
 
        .section .entry.text, "ax"
 
-       .macro IA32_ARG_FIXUP noebp=0
-       movl    %edi,%r8d
-       .if \noebp
-       .else
-       movl    %ebp,%r9d
-       .endif
-       xchg    %ecx,%esi
-       movl    %ebx,%edi
-       movl    %edx,%edx       /* zero extension */
-       .endm 
-
-       /* clobbers %eax */     
-       .macro  CLEAR_RREGS offset=0, _r9=rax
+       /* clobbers %rax */
+       .macro  CLEAR_RREGS _r9=rax
        xorl    %eax,%eax
-       movq    %rax,\offset+R11(%rsp)
-       movq    %rax,\offset+R10(%rsp)
-       movq    %\_r9,\offset+R9(%rsp)
-       movq    %rax,\offset+R8(%rsp)
+       movq    %rax,R11(%rsp)
+       movq    %rax,R10(%rsp)
+       movq    %\_r9,R9(%rsp)
+       movq    %rax,R8(%rsp)
        .endm
 
        /*
         * If it's -1 to make us punt the syscall, then (u32)-1 is still
         * an appropriately invalid value.
         */
-       .macro LOAD_ARGS32 offset, _r9=0
+       .macro LOAD_ARGS32 _r9=0
        .if \_r9
-       movl \offset+16(%rsp),%r9d
+       movl R9(%rsp),%r9d
        .endif
-       movl \offset+40(%rsp),%ecx
-       movl \offset+48(%rsp),%edx
-       movl \offset+56(%rsp),%esi
-       movl \offset+64(%rsp),%edi
+       movl RCX(%rsp),%ecx
+       movl RDX(%rsp),%edx
+       movl RSI(%rsp),%esi
+       movl RDI(%rsp),%edi
        movl %eax,%eax                  /* zero extension */
        .endm
        
@@ -99,54 +88,69 @@ ENDPROC(native_irq_enable_sysexit)
 /*
  * 32bit SYSENTER instruction entry.
  *
+ * SYSENTER loads ss, rsp, cs, and rip from previously programmed MSRs.
+ * IF and VM in rflags are cleared (IOW: interrupts are off).
+ * SYSENTER does not save anything on the stack,
+ * and does not save old rip (!!!) and rflags.
+ *
  * Arguments:
- * %eax        System call number.
- * %ebx Arg1
- * %ecx Arg2
- * %edx Arg3
- * %esi Arg4
- * %edi Arg5
- * %ebp user stack
- * 0(%ebp) Arg6        
- *     
- * Interrupts off.
- *     
+ * eax  system call number
+ * ebx  arg1
+ * ecx  arg2
+ * edx  arg3
+ * esi  arg4
+ * edi  arg5
+ * ebp  user stack
+ * 0(%ebp) arg6
+ *
  * This is purely a fast path. For anything complicated we use the int 0x80
- * path below. Set up a complete hardware stack frame to share code
+ * path below. We set up a complete hardware stack frame to share code
  * with the int 0x80 path.
- */    
+ */
 ENTRY(ia32_sysenter_target)
        CFI_STARTPROC32 simple
        CFI_SIGNAL_FRAME
        CFI_DEF_CFA     rsp,0
        CFI_REGISTER    rsp,rbp
-       SWAPGS_UNSAFE_STACK
-       movq    PER_CPU_VAR(kernel_stack), %rsp
-       addq    $(KERNEL_STACK_OFFSET),%rsp
+
        /*
-        * No need to follow this irqs on/off section: the syscall
-        * disabled irqs, here we enable it straight after entry:
+        * Interrupts are off on entry.
+        * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,
+        * it is too small to ever cause noticeable irq latency.
         */
+       SWAPGS_UNSAFE_STACK
+       movq    PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
        ENABLE_INTERRUPTS(CLBR_NONE)
-       movl    %ebp,%ebp               /* zero extension */
-       pushq_cfi $__USER32_DS
-       /*CFI_REL_OFFSET ss,0*/
-       pushq_cfi %rbp
-       CFI_REL_OFFSET rsp,0
-       pushfq_cfi
-       /*CFI_REL_OFFSET rflags,0*/
-       movl    TI_sysenter_return+THREAD_INFO(%rsp,3*8-KERNEL_STACK_OFFSET),%r10d
-       CFI_REGISTER rip,r10
-       pushq_cfi $__USER32_CS
-       /*CFI_REL_OFFSET cs,0*/
+
+       /* Zero-extending 32-bit regs, do not remove */
+       movl    %ebp, %ebp
        movl    %eax, %eax
-       pushq_cfi %r10
-       CFI_REL_OFFSET rip,0
-       pushq_cfi %rax
+
+       movl    ASM_THREAD_INFO(TI_sysenter_return, %rsp, 0), %r10d
+       CFI_REGISTER rip,r10
+
+       /* Construct struct pt_regs on stack */
+       pushq_cfi       $__USER32_DS            /* pt_regs->ss */
+       pushq_cfi       %rbp                    /* pt_regs->sp */
+       CFI_REL_OFFSET  rsp,0
+       pushfq_cfi                              /* pt_regs->flags */
+       pushq_cfi       $__USER32_CS            /* pt_regs->cs */
+       pushq_cfi       %r10 /* pt_regs->ip = thread_info->sysenter_return */
+       CFI_REL_OFFSET  rip,0
+       pushq_cfi_reg   rax                     /* pt_regs->orig_ax */
+       pushq_cfi_reg   rdi                     /* pt_regs->di */
+       pushq_cfi_reg   rsi                     /* pt_regs->si */
+       pushq_cfi_reg   rdx                     /* pt_regs->dx */
+       pushq_cfi_reg   rcx                     /* pt_regs->cx */
+       pushq_cfi_reg   rax                     /* pt_regs->ax */
        cld
-       SAVE_ARGS 0,1,0
-       /* no need to do an access_ok check here because rbp has been
-          32bit zero extended */ 
+       sub     $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
+       CFI_ADJUST_CFA_OFFSET 10*8
+
+       /*
+        * no need to do an access_ok check here because rbp has been
+        * 32bit zero extended
+        */
        ASM_STAC
 1:     movl    (%rbp),%ebp
        _ASM_EXTABLE(1b,ia32_badarg)
@@ -157,42 +161,80 @@ ENTRY(ia32_sysenter_target)
         * ourselves.  To save a few cycles, we can check whether
         * NT was set instead of doing an unconditional popfq.
         */
-       testl $X86_EFLAGS_NT,EFLAGS-ARGOFFSET(%rsp)
+       testl $X86_EFLAGS_NT,EFLAGS(%rsp)
        jnz sysenter_fix_flags
 sysenter_flags_fixed:
 
-       orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
-       testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+       orl     $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
+       testl   $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        CFI_REMEMBER_STATE
        jnz  sysenter_tracesys
        cmpq    $(IA32_NR_syscalls-1),%rax
        ja      ia32_badsys
 sysenter_do_call:
-       IA32_ARG_FIXUP
+       /* 32bit syscall -> 64bit C ABI argument conversion */
+       movl    %edi,%r8d       /* arg5 */
+       movl    %ebp,%r9d       /* arg6 */
+       xchg    %ecx,%esi       /* rsi:arg2, rcx:arg4 */
+       movl    %ebx,%edi       /* arg1 */
+       movl    %edx,%edx       /* arg3 (zero extension) */
 sysenter_dispatch:
        call    *ia32_sys_call_table(,%rax,8)
-       movq    %rax,RAX-ARGOFFSET(%rsp)
+       movq    %rax,RAX(%rsp)
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
-       testl   $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+       testl   $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        jnz     sysexit_audit
 sysexit_from_sys_call:
-       andl    $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
-       /* clear IF, that popfq doesn't enable interrupts early */
-       andl    $~0x200,EFLAGS-ARGOFFSET(%rsp)
-       movl    RIP-ARGOFFSET(%rsp),%edx                /* User %eip */
-       CFI_REGISTER rip,rdx
-       RESTORE_ARGS 0,24,0,0,0,0
+       /*
+        * NB: SYSEXIT is not obviously safe for 64-bit kernels -- an
+        * NMI between STI and SYSEXIT has poorly specified behavior,
+        * and and NMI followed by an IRQ with usergs is fatal.  So
+        * we just pretend we're using SYSEXIT but we really use
+        * SYSRETL instead.
+        *
+        * This code path is still called 'sysexit' because it pairs
+        * with 'sysenter' and it uses the SYSENTER calling convention.
+        */
+       andl    $~TS_COMPAT,ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
+       movl    RIP(%rsp),%ecx          /* User %eip */
+       CFI_REGISTER rip,rcx
+       RESTORE_RSI_RDI
+       xorl    %edx,%edx               /* avoid info leaks */
        xorq    %r8,%r8
        xorq    %r9,%r9
        xorq    %r10,%r10
-       xorq    %r11,%r11
-       popfq_cfi
+       movl    EFLAGS(%rsp),%r11d      /* User eflags */
        /*CFI_RESTORE rflags*/
-       popq_cfi %rcx                           /* User %esp */
-       CFI_REGISTER rsp,rcx
        TRACE_IRQS_ON
-       ENABLE_INTERRUPTS_SYSEXIT32
+
+       /*
+        * SYSRETL works even on Intel CPUs.  Use it in preference to SYSEXIT,
+        * since it avoids a dicey window with interrupts enabled.
+        */
+       movl    RSP(%rsp),%esp
+
+       /*
+        * USERGS_SYSRET32 does:
+        *  gsbase = user's gs base
+        *  eip = ecx
+        *  rflags = r11
+        *  cs = __USER32_CS
+        *  ss = __USER_DS
+        *
+        * The prologue set RIP(%rsp) to VDSO32_SYSENTER_RETURN, which does:
+        *
+        *  pop %ebp
+        *  pop %edx
+        *  pop %ecx
+        *
+        * Therefore, we invoke SYSRETL with EDX and R8-R10 zeroed to
+        * avoid info leaks.  R11 ends up with VDSO32_SYSENTER_RETURN's
+        * address (already known to user code), and R12-R15 are
+        * callee-saved and therefore don't contain any interesting
+        * kernel data.
+        */
+       USERGS_SYSRET32
 
        CFI_RESTORE_STATE
 
@@ -205,18 +247,18 @@ sysexit_from_sys_call:
        movl %ebx,%esi                  /* 2nd arg: 1st syscall arg */
        movl %eax,%edi                  /* 1st arg: syscall number */
        call __audit_syscall_entry
-       movl RAX-ARGOFFSET(%rsp),%eax   /* reload syscall number */
+       movl RAX(%rsp),%eax     /* reload syscall number */
        cmpq $(IA32_NR_syscalls-1),%rax
        ja ia32_badsys
        movl %ebx,%edi                  /* reload 1st syscall arg */
-       movl RCX-ARGOFFSET(%rsp),%esi   /* reload 2nd syscall arg */
-       movl RDX-ARGOFFSET(%rsp),%edx   /* reload 3rd syscall arg */
-       movl RSI-ARGOFFSET(%rsp),%ecx   /* reload 4th syscall arg */
-       movl RDI-ARGOFFSET(%rsp),%r8d   /* reload 5th syscall arg */
+       movl RCX(%rsp),%esi     /* reload 2nd syscall arg */
+       movl RDX(%rsp),%edx     /* reload 3rd syscall arg */
+       movl RSI(%rsp),%ecx     /* reload 4th syscall arg */
+       movl RDI(%rsp),%r8d     /* reload 5th syscall arg */
        .endm
 
        .macro auditsys_exit exit
-       testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+       testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        jnz ia32_ret_from_sys_call
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_NONE)
@@ -227,13 +269,13 @@ 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-ARGOFFSET(%rsp),%rax   /* reload syscall return value */
+       movq RAX(%rsp),%rax     /* reload syscall return value */
        movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
-       testl %edi,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+       testl %edi, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        jz \exit
-       CLEAR_RREGS -ARGOFFSET
+       CLEAR_RREGS
        jmp int_with_check
        .endm
 
@@ -253,16 +295,16 @@ sysenter_fix_flags:
 
 sysenter_tracesys:
 #ifdef CONFIG_AUDITSYSCALL
-       testl   $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+       testl   $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT), ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        jz      sysenter_auditsys
 #endif
-       SAVE_REST
+       SAVE_EXTRA_REGS
        CLEAR_RREGS
        movq    $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
        movq    %rsp,%rdi        /* &pt_regs -> arg1 */
        call    syscall_trace_enter
-       LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
-       RESTORE_REST
+       LOAD_ARGS32  /* reload args from stack in case ptrace changed it */
+       RESTORE_EXTRA_REGS
        cmpq    $(IA32_NR_syscalls-1),%rax
        ja      int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
        jmp     sysenter_do_call
@@ -272,94 +314,128 @@ ENDPROC(ia32_sysenter_target)
 /*
  * 32bit SYSCALL instruction entry.
  *
+ * 32bit SYSCALL saves rip to rcx, clears rflags.RF, then saves rflags to r11,
+ * then loads new ss, cs, and rip from previously programmed MSRs.
+ * rflags gets masked by a value from another MSR (so CLD and CLAC
+ * are not needed). SYSCALL does not save anything on the stack
+ * and does not change rsp.
+ *
+ * Note: rflags saving+masking-with-MSR happens only in Long mode
+ * (in legacy 32bit mode, IF, RF and VM bits are cleared and that's it).
+ * Don't get confused: rflags saving+masking depends on Long Mode Active bit
+ * (EFER.LMA=1), NOT on bitness of userspace where SYSCALL executes
+ * or target CS descriptor's L bit (SYSCALL does not read segment descriptors).
+ *
  * Arguments:
- * %eax        System call number.
- * %ebx Arg1
- * %ecx return EIP 
- * %edx Arg3
- * %esi Arg4
- * %edi Arg5
- * %ebp Arg2    [note: not saved in the stack frame, should not be touched]
- * %esp user stack 
- * 0(%esp) Arg6
- *     
- * Interrupts off.
- *     
+ * eax  system call number
+ * ecx  return address
+ * ebx  arg1
+ * ebp  arg2   (note: not saved in the stack frame, should not be touched)
+ * edx  arg3
+ * esi  arg4
+ * edi  arg5
+ * esp  user stack
+ * 0(%esp) arg6
+ *
  * This is purely a fast path. For anything complicated we use the int 0x80
- * path below. Set up a complete hardware stack frame to share code
- * with the int 0x80 path.     
- */    
+ * path below. We set up a complete hardware stack frame to share code
+ * with the int 0x80 path.
+ */
 ENTRY(ia32_cstar_target)
        CFI_STARTPROC32 simple
        CFI_SIGNAL_FRAME
-       CFI_DEF_CFA     rsp,KERNEL_STACK_OFFSET
+       CFI_DEF_CFA     rsp,0
        CFI_REGISTER    rip,rcx
        /*CFI_REGISTER  rflags,r11*/
+
+       /*
+        * Interrupts are off on entry.
+        * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,
+        * it is too small to ever cause noticeable irq latency.
+        */
        SWAPGS_UNSAFE_STACK
        movl    %esp,%r8d
        CFI_REGISTER    rsp,r8
        movq    PER_CPU_VAR(kernel_stack),%rsp
-       /*
-        * No need to follow this irqs on/off section: the syscall
-        * disabled irqs and here we enable it straight after entry:
-        */
        ENABLE_INTERRUPTS(CLBR_NONE)
-       SAVE_ARGS 8,0,0
-       movl    %eax,%eax       /* zero extension */
-       movq    %rax,ORIG_RAX-ARGOFFSET(%rsp)
-       movq    %rcx,RIP-ARGOFFSET(%rsp)
-       CFI_REL_OFFSET rip,RIP-ARGOFFSET
-       movq    %rbp,RCX-ARGOFFSET(%rsp) /* this lies slightly to ptrace */
+
+       /* Zero-extending 32-bit regs, do not remove */
+       movl    %eax,%eax
+
+       /* Construct struct pt_regs on stack */
+       pushq_cfi       $__USER32_DS            /* pt_regs->ss */
+       pushq_cfi       %r8                     /* pt_regs->sp */
+       CFI_REL_OFFSET rsp,0
+       pushq_cfi       %r11                    /* pt_regs->flags */
+       pushq_cfi       $__USER32_CS            /* pt_regs->cs */
+       pushq_cfi       %rcx                    /* pt_regs->ip */
+       CFI_REL_OFFSET rip,0
+       pushq_cfi_reg   rax                     /* pt_regs->orig_ax */
+       pushq_cfi_reg   rdi                     /* pt_regs->di */
+       pushq_cfi_reg   rsi                     /* pt_regs->si */
+       pushq_cfi_reg   rdx                     /* pt_regs->dx */
+       pushq_cfi_reg   rbp                     /* pt_regs->cx */
        movl    %ebp,%ecx
-       movq    $__USER32_CS,CS-ARGOFFSET(%rsp)
-       movq    $__USER32_DS,SS-ARGOFFSET(%rsp)
-       movq    %r11,EFLAGS-ARGOFFSET(%rsp)
-       /*CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/
-       movq    %r8,RSP-ARGOFFSET(%rsp) 
-       CFI_REL_OFFSET rsp,RSP-ARGOFFSET
-       /* no need to do an access_ok check here because r8 has been
-          32bit zero extended */ 
-       /* hardware stack frame is complete now */      
+       pushq_cfi_reg   rax                     /* pt_regs->ax */
+       sub     $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
+       CFI_ADJUST_CFA_OFFSET 10*8
+
+       /*
+        * no need to do an access_ok check here because r8 has been
+        * 32bit zero extended
+        */
        ASM_STAC
 1:     movl    (%r8),%r9d
        _ASM_EXTABLE(1b,ia32_badarg)
        ASM_CLAC
-       orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
-       testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+       orl     $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
+       testl   $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        CFI_REMEMBER_STATE
        jnz   cstar_tracesys
        cmpq $IA32_NR_syscalls-1,%rax
        ja  ia32_badsys
 cstar_do_call:
-       IA32_ARG_FIXUP 1
+       /* 32bit syscall -> 64bit C ABI argument conversion */
+       movl    %edi,%r8d       /* arg5 */
+       /* r9 already loaded */ /* arg6 */
+       xchg    %ecx,%esi       /* rsi:arg2, rcx:arg4 */
+       movl    %ebx,%edi       /* arg1 */
+       movl    %edx,%edx       /* arg3 (zero extension) */
 cstar_dispatch:
        call *ia32_sys_call_table(,%rax,8)
-       movq %rax,RAX-ARGOFFSET(%rsp)
+       movq %rax,RAX(%rsp)
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
-       testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+       testl $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        jnz sysretl_audit
 sysretl_from_sys_call:
-       andl $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
-       RESTORE_ARGS 0,-ARG_SKIP,0,0,0
-       movl RIP-ARGOFFSET(%rsp),%ecx
+       andl $~TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
+       RESTORE_RSI_RDI_RDX
+       movl RIP(%rsp),%ecx
        CFI_REGISTER rip,rcx
-       movl EFLAGS-ARGOFFSET(%rsp),%r11d       
+       movl EFLAGS(%rsp),%r11d
        /*CFI_REGISTER rflags,r11*/
        xorq    %r10,%r10
        xorq    %r9,%r9
        xorq    %r8,%r8
        TRACE_IRQS_ON
-       movl RSP-ARGOFFSET(%rsp),%esp
+       movl RSP(%rsp),%esp
        CFI_RESTORE rsp
+       /*
+        * 64bit->32bit SYSRET restores eip from ecx,
+        * eflags from r11 (but RF and VM bits are forced to 0),
+        * cs and ss are loaded from MSRs.
+        * (Note: 32bit->32bit SYSRET is different: since r11
+        * does not exist, it merely sets eflags.IF=1).
+        */
        USERGS_SYSRET32
-       
+
 #ifdef CONFIG_AUDITSYSCALL
 cstar_auditsys:
        CFI_RESTORE_STATE
-       movl %r9d,R9-ARGOFFSET(%rsp)    /* register to be clobbered by call */
+       movl %r9d,R9(%rsp)      /* register to be clobbered by call */
        auditsys_entry_common
-       movl R9-ARGOFFSET(%rsp),%r9d    /* reload 6th syscall arg */
+       movl R9(%rsp),%r9d      /* reload 6th syscall arg */
        jmp cstar_dispatch
 
 sysretl_audit:
@@ -368,17 +444,17 @@ sysretl_audit:
 
 cstar_tracesys:
 #ifdef CONFIG_AUDITSYSCALL
-       testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+       testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT), ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        jz cstar_auditsys
 #endif
        xchgl %r9d,%ebp
-       SAVE_REST
-       CLEAR_RREGS 0, r9
+       SAVE_EXTRA_REGS
+       CLEAR_RREGS r9
        movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
        movq %rsp,%rdi        /* &pt_regs -> arg1 */
        call syscall_trace_enter
-       LOAD_ARGS32 ARGOFFSET, 1  /* reload args from stack in case ptrace changed it */
-       RESTORE_REST
+       LOAD_ARGS32   /* reload args from stack in case ptrace changed it */
+       RESTORE_EXTRA_REGS
        xchgl %ebp,%r9d
        cmpq $(IA32_NR_syscalls-1),%rax
        ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
@@ -391,78 +467,94 @@ ia32_badarg:
        jmp ia32_sysret
        CFI_ENDPROC
 
-/* 
- * Emulated IA32 system calls via int 0x80. 
+/*
+ * Emulated IA32 system calls via int 0x80.
  *
- * Arguments:   
- * %eax        System call number.
- * %ebx Arg1
- * %ecx Arg2
- * %edx Arg3
- * %esi Arg4
- * %edi Arg5
- * %ebp Arg6    [note: not saved in the stack frame, should not be touched]
+ * Arguments:
+ * eax  system call number
+ * ebx  arg1
+ * ecx  arg2
+ * edx  arg3
+ * esi  arg4
+ * edi  arg5
+ * ebp  arg6   (note: not saved in the stack frame, should not be touched)
  *
  * Notes:
- * Uses the same stack frame as the x86-64 version.    
- * All registers except %eax must be saved (but ptrace may violate that)
+ * Uses the same stack frame as the x86-64 version.
+ * All registers except eax must be saved (but ptrace may violate that).
  * Arguments are zero extended. For system calls that want sign extension and
  * take long arguments a wrapper is needed. Most calls can just be called
  * directly.
- * Assumes it is only called from user space and entered with interrupts off.  
- */                            
+ * Assumes it is only called from user space and entered with interrupts off.
+ */
 
 ENTRY(ia32_syscall)
        CFI_STARTPROC32 simple
        CFI_SIGNAL_FRAME
-       CFI_DEF_CFA     rsp,SS+8-RIP
-       /*CFI_REL_OFFSET        ss,SS-RIP*/
-       CFI_REL_OFFSET  rsp,RSP-RIP
-       /*CFI_REL_OFFSET        rflags,EFLAGS-RIP*/
-       /*CFI_REL_OFFSET        cs,CS-RIP*/
-       CFI_REL_OFFSET  rip,RIP-RIP
-       PARAVIRT_ADJUST_EXCEPTION_FRAME
-       SWAPGS
+       CFI_DEF_CFA     rsp,5*8
+       /*CFI_REL_OFFSET        ss,4*8 */
+       CFI_REL_OFFSET  rsp,3*8
+       /*CFI_REL_OFFSET        rflags,2*8 */
+       /*CFI_REL_OFFSET        cs,1*8 */
+       CFI_REL_OFFSET  rip,0*8
+
        /*
-        * No need to follow this irqs on/off section: the syscall
-        * disabled irqs and here we enable it straight after entry:
+        * Interrupts are off on entry.
+        * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,
+        * it is too small to ever cause noticeable irq latency.
         */
+       PARAVIRT_ADJUST_EXCEPTION_FRAME
+       SWAPGS
        ENABLE_INTERRUPTS(CLBR_NONE)
-       movl %eax,%eax
-       pushq_cfi %rax
+
+       /* Zero-extending 32-bit regs, do not remove */
+       movl    %eax,%eax
+
+       /* Construct struct pt_regs on stack (iret frame is already on stack) */
+       pushq_cfi_reg   rax                     /* pt_regs->orig_ax */
+       pushq_cfi_reg   rdi                     /* pt_regs->di */
+       pushq_cfi_reg   rsi                     /* pt_regs->si */
+       pushq_cfi_reg   rdx                     /* pt_regs->dx */
+       pushq_cfi_reg   rcx                     /* pt_regs->cx */
+       pushq_cfi_reg   rax                     /* pt_regs->ax */
        cld
-       /* note the registers are not zero extended to the sf.
-          this could be a problem. */
-       SAVE_ARGS 0,1,0
-       orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
-       testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+       sub     $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
+       CFI_ADJUST_CFA_OFFSET 10*8
+
+       orl $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
+       testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        jnz ia32_tracesys
        cmpq $(IA32_NR_syscalls-1),%rax
        ja ia32_badsys
 ia32_do_call:
-       IA32_ARG_FIXUP
+       /* 32bit syscall -> 64bit C ABI argument conversion */
+       movl %edi,%r8d  /* arg5 */
+       movl %ebp,%r9d  /* arg6 */
+       xchg %ecx,%esi  /* rsi:arg2, rcx:arg4 */
+       movl %ebx,%edi  /* arg1 */
+       movl %edx,%edx  /* arg3 (zero extension) */
        call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
 ia32_sysret:
-       movq %rax,RAX-ARGOFFSET(%rsp)
+       movq %rax,RAX(%rsp)
 ia32_ret_from_sys_call:
-       CLEAR_RREGS -ARGOFFSET
-       jmp int_ret_from_sys_call 
+       CLEAR_RREGS
+       jmp int_ret_from_sys_call
 
-ia32_tracesys:                  
-       SAVE_REST
+ia32_tracesys:
+       SAVE_EXTRA_REGS
        CLEAR_RREGS
        movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
        movq %rsp,%rdi        /* &pt_regs -> arg1 */
        call syscall_trace_enter
-       LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
-       RESTORE_REST
+       LOAD_ARGS32     /* reload args from stack in case ptrace changed it */
+       RESTORE_EXTRA_REGS
        cmpq $(IA32_NR_syscalls-1),%rax
        ja  int_ret_from_sys_call       /* ia32_tracesys has set RAX(%rsp) */
        jmp ia32_do_call
 END(ia32_syscall)
 
 ia32_badsys:
-       movq $0,ORIG_RAX-ARGOFFSET(%rsp)
+       movq $0,ORIG_RAX(%rsp)
        movq $-ENOSYS,%rax
        jmp ia32_sysret
 
@@ -479,8 +571,6 @@ GLOBAL(\label)
 
        PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn
        PTREGSCALL stub32_sigreturn, sys32_sigreturn
-       PTREGSCALL stub32_execve, compat_sys_execve
-       PTREGSCALL stub32_execveat, compat_sys_execveat
        PTREGSCALL stub32_fork, sys_fork
        PTREGSCALL stub32_vfork, sys_vfork
 
@@ -492,24 +582,23 @@ GLOBAL(stub32_clone)
 
        ALIGN
 ia32_ptregs_common:
-       popq %r11
        CFI_ENDPROC
        CFI_STARTPROC32 simple
        CFI_SIGNAL_FRAME
-       CFI_DEF_CFA     rsp,SS+8-ARGOFFSET
-       CFI_REL_OFFSET  rax,RAX-ARGOFFSET
-       CFI_REL_OFFSET  rcx,RCX-ARGOFFSET
-       CFI_REL_OFFSET  rdx,RDX-ARGOFFSET
-       CFI_REL_OFFSET  rsi,RSI-ARGOFFSET
-       CFI_REL_OFFSET  rdi,RDI-ARGOFFSET
-       CFI_REL_OFFSET  rip,RIP-ARGOFFSET
-/*     CFI_REL_OFFSET  cs,CS-ARGOFFSET*/
-/*     CFI_REL_OFFSET  rflags,EFLAGS-ARGOFFSET*/
-       CFI_REL_OFFSET  rsp,RSP-ARGOFFSET
-/*     CFI_REL_OFFSET  ss,SS-ARGOFFSET*/
-       SAVE_REST
+       CFI_DEF_CFA     rsp,SIZEOF_PTREGS
+       CFI_REL_OFFSET  rax,RAX
+       CFI_REL_OFFSET  rcx,RCX
+       CFI_REL_OFFSET  rdx,RDX
+       CFI_REL_OFFSET  rsi,RSI
+       CFI_REL_OFFSET  rdi,RDI
+       CFI_REL_OFFSET  rip,RIP
+/*     CFI_REL_OFFSET  cs,CS*/
+/*     CFI_REL_OFFSET  rflags,EFLAGS*/
+       CFI_REL_OFFSET  rsp,RSP
+/*     CFI_REL_OFFSET  ss,SS*/
+       SAVE_EXTRA_REGS 8
        call *%rax
-       RESTORE_REST
-       jmp  ia32_sysret        /* misbalances the return cache */
+       RESTORE_EXTRA_REGS 8
+       ret
        CFI_ENDPROC
 END(ia32_ptregs_common)
diff --git a/arch/x86/ia32/nosyscall.c b/arch/x86/ia32/nosyscall.c
deleted file mode 100644 (file)
index 51ecd5b..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/errno.h>
-
-long compat_ni_syscall(void)
-{
-       return -ENOSYS;
-}
index 8e0ceecdc95790d7a53eb3fe5bc1c3867bcb9e7f..719cd702b0a476e13abb42bfa28b0a7911204382 100644 (file)
@@ -201,20 +201,6 @@ long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high,
                                advice);
 }
 
-long sys32_vm86_warning(void)
-{
-       struct task_struct *me = current;
-       static char lastcomm[sizeof(me->comm)];
-
-       if (strncmp(lastcomm, me->comm, sizeof(lastcomm))) {
-               compat_printk(KERN_INFO
-                             "%s: vm86 mode not supported on 64 bit kernel\n",
-                             me->comm);
-               strncpy(lastcomm, me->comm, sizeof(lastcomm));
-       }
-       return -ENOSYS;
-}
-
 asmlinkage ssize_t sys32_readahead(int fd, unsigned off_lo, unsigned off_hi,
                                   size_t count)
 {
diff --git a/arch/x86/ia32/syscall_ia32.c b/arch/x86/ia32/syscall_ia32.c
deleted file mode 100644 (file)
index 4754ba0..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/* System call table for ia32 emulation. */
-
-#include <linux/linkage.h>
-#include <linux/sys.h>
-#include <linux/cache.h>
-#include <asm/asm-offsets.h>
-
-#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void compat(void) ;
-#include <asm/syscalls_32.h>
-#undef __SYSCALL_I386
-
-#define __SYSCALL_I386(nr, sym, compat) [nr] = compat,
-
-typedef void (*sys_call_ptr_t)(void);
-
-extern void compat_ni_syscall(void);
-
-const sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = {
-       /*
-        * Smells like a compiler bug -- it doesn't work
-        * when the & below is removed.
-        */
-       [0 ... __NR_ia32_syscall_max] = &compat_ni_syscall,
-#include <asm/syscalls_32.h>
-};
index 372231c22a47a46b1417e5c6739d88eb927f89fd..bdf02eeee76519582b0fe9c35b631852b1b417d9 100644 (file)
        .endm
 #endif
 
-.macro altinstruction_entry orig alt feature orig_len alt_len
+.macro altinstruction_entry orig alt feature orig_len alt_len pad_len
        .long \orig - .
        .long \alt - .
        .word \feature
        .byte \orig_len
        .byte \alt_len
+       .byte \pad_len
+.endm
+
+.macro ALTERNATIVE oldinstr, newinstr, feature
+140:
+       \oldinstr
+141:
+       .skip -(((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)),0x90
+142:
+
+       .pushsection .altinstructions,"a"
+       altinstruction_entry 140b,143f,\feature,142b-140b,144f-143f,142b-141b
+       .popsection
+
+       .pushsection .altinstr_replacement,"ax"
+143:
+       \newinstr
+144:
+       .popsection
+.endm
+
+#define old_len                        141b-140b
+#define new_len1               144f-143f
+#define new_len2               145f-144f
+
+/*
+ * max without conditionals. Idea adapted from:
+ * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
+ */
+#define alt_max_short(a, b)    ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
+
+.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
+140:
+       \oldinstr
+141:
+       .skip -((alt_max_short(new_len1, new_len2) - (old_len)) > 0) * \
+               (alt_max_short(new_len1, new_len2) - (old_len)),0x90
+142:
+
+       .pushsection .altinstructions,"a"
+       altinstruction_entry 140b,143f,\feature1,142b-140b,144f-143f,142b-141b
+       altinstruction_entry 140b,144f,\feature2,142b-140b,145f-144f,142b-141b
+       .popsection
+
+       .pushsection .altinstr_replacement,"ax"
+143:
+       \newinstr1
+144:
+       \newinstr2
+145:
+       .popsection
 .endm
 
 #endif  /*  __ASSEMBLY__  */
index 473bdbee378a10ac2030b586dc33d3be74de5a11..ba32af062f61d69164a792630e3257c8cdc6deb5 100644 (file)
@@ -48,8 +48,9 @@ struct alt_instr {
        s32 repl_offset;        /* offset to replacement instruction */
        u16 cpuid;              /* cpuid bit set for replacement */
        u8  instrlen;           /* length of original instruction */
-       u8  replacementlen;     /* length of new instruction, <= instrlen */
-};
+       u8  replacementlen;     /* length of new instruction */
+       u8  padlen;             /* length of build-time padding */
+} __packed;
 
 extern void alternative_instructions(void);
 extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
@@ -76,50 +77,69 @@ static inline int alternatives_text_reserved(void *start, void *end)
 }
 #endif /* CONFIG_SMP */
 
-#define OLDINSTR(oldinstr)     "661:\n\t" oldinstr "\n662:\n"
+#define b_replacement(num)     "664"#num
+#define e_replacement(num)     "665"#num
 
-#define b_replacement(number)  "663"#number
-#define e_replacement(number)  "664"#number
+#define alt_end_marker         "663"
+#define alt_slen               "662b-661b"
+#define alt_pad_len            alt_end_marker"b-662b"
+#define alt_total_slen         alt_end_marker"b-661b"
+#define alt_rlen(num)          e_replacement(num)"f-"b_replacement(num)"f"
 
-#define alt_slen "662b-661b"
-#define alt_rlen(number) e_replacement(number)"f-"b_replacement(number)"f"
+#define __OLDINSTR(oldinstr, num)                                      \
+       "661:\n\t" oldinstr "\n662:\n"                                  \
+       ".skip -(((" alt_rlen(num) ")-(" alt_slen ")) > 0) * "          \
+               "((" alt_rlen(num) ")-(" alt_slen ")),0x90\n"
 
-#define ALTINSTR_ENTRY(feature, number)                                              \
+#define OLDINSTR(oldinstr, num)                                                \
+       __OLDINSTR(oldinstr, num)                                       \
+       alt_end_marker ":\n"
+
+/*
+ * max without conditionals. Idea adapted from:
+ * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
+ *
+ * The additional "-" is needed because gas works with s32s.
+ */
+#define alt_max_short(a, b)    "((" a ") ^ (((" a ") ^ (" b ")) & -(-((" a ") - (" b ")))))"
+
+/*
+ * Pad the second replacement alternative with additional NOPs if it is
+ * additionally longer than the first replacement alternative.
+ */
+#define OLDINSTR_2(oldinstr, num1, num2) \
+       "661:\n\t" oldinstr "\n662:\n"                                                          \
+       ".skip -((" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")) > 0) * "  \
+               "(" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")), 0x90\n"  \
+       alt_end_marker ":\n"
+
+#define ALTINSTR_ENTRY(feature, num)                                         \
        " .long 661b - .\n"                             /* label           */ \
-       " .long " b_replacement(number)"f - .\n"        /* new instruction */ \
+       " .long " b_replacement(num)"f - .\n"           /* new instruction */ \
        " .word " __stringify(feature) "\n"             /* feature bit     */ \
-       " .byte " alt_slen "\n"                         /* source len      */ \
-       " .byte " alt_rlen(number) "\n"                 /* replacement len */
-
-#define DISCARD_ENTRY(number)                          /* rlen <= slen */    \
-       " .byte 0xff + (" alt_rlen(number) ") - (" alt_slen ")\n"
+       " .byte " alt_total_slen "\n"                   /* source len      */ \
+       " .byte " alt_rlen(num) "\n"                    /* replacement len */ \
+       " .byte " alt_pad_len "\n"                      /* pad len */
 
-#define ALTINSTR_REPLACEMENT(newinstr, feature, number)        /* replacement */     \
-       b_replacement(number)":\n\t" newinstr "\n" e_replacement(number) ":\n\t"
+#define ALTINSTR_REPLACEMENT(newinstr, feature, num)   /* replacement */     \
+       b_replacement(num)":\n\t" newinstr "\n" e_replacement(num) ":\n\t"
 
 /* alternative assembly primitive: */
 #define ALTERNATIVE(oldinstr, newinstr, feature)                       \
-       OLDINSTR(oldinstr)                                              \
+       OLDINSTR(oldinstr, 1)                                           \
        ".pushsection .altinstructions,\"a\"\n"                         \
        ALTINSTR_ENTRY(feature, 1)                                      \
        ".popsection\n"                                                 \
-       ".pushsection .discard,\"aw\",@progbits\n"                      \
-       DISCARD_ENTRY(1)                                                \
-       ".popsection\n"                                                 \
        ".pushsection .altinstr_replacement, \"ax\"\n"                  \
        ALTINSTR_REPLACEMENT(newinstr, feature, 1)                      \
        ".popsection"
 
 #define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2)\
-       OLDINSTR(oldinstr)                                              \
+       OLDINSTR_2(oldinstr, 1, 2)                                      \
        ".pushsection .altinstructions,\"a\"\n"                         \
        ALTINSTR_ENTRY(feature1, 1)                                     \
        ALTINSTR_ENTRY(feature2, 2)                                     \
        ".popsection\n"                                                 \
-       ".pushsection .discard,\"aw\",@progbits\n"                      \
-       DISCARD_ENTRY(1)                                                \
-       DISCARD_ENTRY(2)                                                \
-       ".popsection\n"                                                 \
        ".pushsection .altinstr_replacement, \"ax\"\n"                  \
        ALTINSTR_REPLACEMENT(newinstr1, feature1, 1)                    \
        ALTINSTR_REPLACEMENT(newinstr2, feature2, 2)                    \
@@ -146,6 +166,9 @@ static inline int alternatives_text_reserved(void *start, void *end)
 #define alternative(oldinstr, newinstr, feature)                       \
        asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory")
 
+#define alternative_2(oldinstr, newinstr1, feature1, newinstr2, feature2) \
+       asm volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory")
+
 /*
  * Alternative inline assembly with input.
  *
index efc3b22d896eb23b7e37cf9c720065c0b6b0c717..976b86a325e55cedfd28c029455ddecb2c06b6be 100644 (file)
@@ -91,7 +91,7 @@ static inline void native_apic_mem_write(u32 reg, u32 v)
 {
        volatile u32 *addr = (volatile u32 *)(APIC_BASE + reg);
 
-       alternative_io("movl %0, %1", "xchgl %0, %1", X86_BUG_11AP,
+       alternative_io("movl %0, %P1", "xchgl %0, %P1", X86_BUG_11AP,
                       ASM_OUTPUT2("=r" (v), "=m" (*addr)),
                       ASM_OUTPUT2("0" (v), "m" (*addr)));
 }
@@ -204,7 +204,6 @@ extern void clear_local_APIC(void);
 extern void disconnect_bsp_APIC(int virt_wire_setup);
 extern void disable_local_APIC(void);
 extern void lapic_shutdown(void);
-extern int verify_local_APIC(void);
 extern void sync_Arb_IDs(void);
 extern void init_bsp_APIC(void);
 extern void setup_local_APIC(void);
index 2ab1eb33106eec42eff90d27b98cb698b5c4c835..959e45b81fe29192b0f1c97a65e028e7314f603d 100644 (file)
@@ -95,13 +95,11 @@ do {                                                                        \
  * Stop RDTSC speculation. This is needed when you need to use RDTSC
  * (or get_cycles or vread that possibly accesses the TSC) in a defined
  * code region.
- *
- * (Could use an alternative three way for this if there was one.)
  */
 static __always_inline void rdtsc_barrier(void)
 {
-       alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
-       alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
+       alternative_2("", "mfence", X86_FEATURE_MFENCE_RDTSC,
+                         "lfence", X86_FEATURE_LFENCE_RDTSC);
 }
 
 #endif /* _ASM_X86_BARRIER_H */
index 1f1297b46f833ecd7843bf09a9592e0e5e61ec96..1c8b50edb2db3cac8f54c0c300d393b18bf24342 100644 (file)
@@ -55,143 +55,157 @@ For 32-bit we have the following conventions - kernel is built with
  * for assembly code:
  */
 
-#define R15              0
-#define R14              8
-#define R13             16
-#define R12             24
-#define RBP             32
-#define RBX             40
-
-/* arguments: interrupts/non tracing syscalls only save up to here: */
-#define R11             48
-#define R10             56
-#define R9              64
-#define R8              72
-#define RAX             80
-#define RCX             88
-#define RDX             96
-#define RSI            104
-#define RDI            112
-#define ORIG_RAX       120       /* + error_code */
-/* end of arguments */
-
-/* cpu exception frame or undefined in case of fast syscall: */
-#define RIP            128
-#define CS             136
-#define EFLAGS         144
-#define RSP            152
-#define SS             160
-
-#define ARGOFFSET      R11
-
-       .macro SAVE_ARGS addskip=0, save_rcx=1, save_r891011=1, rax_enosys=0
-       subq  $9*8+\addskip, %rsp
-       CFI_ADJUST_CFA_OFFSET   9*8+\addskip
-       movq_cfi rdi, 8*8
-       movq_cfi rsi, 7*8
-       movq_cfi rdx, 6*8
-
-       .if \save_rcx
-       movq_cfi rcx, 5*8
-       .endif
+/* The layout forms the "struct pt_regs" on the stack: */
+/*
+ * C ABI says these regs are callee-preserved. They aren't saved on kernel entry
+ * unless syscall needs a complete, fully filled "struct pt_regs".
+ */
+#define R15            0*8
+#define R14            1*8
+#define R13            2*8
+#define R12            3*8
+#define RBP            4*8
+#define RBX            5*8
+/* These regs are callee-clobbered. Always saved on kernel entry. */
+#define R11            6*8
+#define R10            7*8
+#define R9             8*8
+#define R8             9*8
+#define RAX            10*8
+#define RCX            11*8
+#define RDX            12*8
+#define RSI            13*8
+#define RDI            14*8
+/*
+ * On syscall entry, this is syscall#. On CPU exception, this is error code.
+ * On hw interrupt, it's IRQ number:
+ */
+#define ORIG_RAX       15*8
+/* Return frame for iretq */
+#define RIP            16*8
+#define CS             17*8
+#define EFLAGS         18*8
+#define RSP            19*8
+#define SS             20*8
+
+#define SIZEOF_PTREGS  21*8
+
+       .macro ALLOC_PT_GPREGS_ON_STACK addskip=0
+       subq    $15*8+\addskip, %rsp
+       CFI_ADJUST_CFA_OFFSET 15*8+\addskip
+       .endm
 
-       .if \rax_enosys
-       movq $-ENOSYS, 4*8(%rsp)
-       .else
-       movq_cfi rax, 4*8
+       .macro SAVE_C_REGS_HELPER offset=0 rax=1 rcx=1 r8910=1 r11=1
+       .if \r11
+       movq_cfi r11, 6*8+\offset
        .endif
-
-       .if \save_r891011
-       movq_cfi r8,  3*8
-       movq_cfi r9,  2*8
-       movq_cfi r10, 1*8
-       movq_cfi r11, 0*8
+       .if \r8910
+       movq_cfi r10, 7*8+\offset
+       movq_cfi r9,  8*8+\offset
+       movq_cfi r8,  9*8+\offset
+       .endif
+       .if \rax
+       movq_cfi rax, 10*8+\offset
+       .endif
+       .if \rcx
+       movq_cfi rcx, 11*8+\offset
        .endif
+       movq_cfi rdx, 12*8+\offset
+       movq_cfi rsi, 13*8+\offset
+       movq_cfi rdi, 14*8+\offset
+       .endm
+       .macro SAVE_C_REGS offset=0
+       SAVE_C_REGS_HELPER \offset, 1, 1, 1, 1
+       .endm
+       .macro SAVE_C_REGS_EXCEPT_RAX_RCX offset=0
+       SAVE_C_REGS_HELPER \offset, 0, 0, 1, 1
+       .endm
+       .macro SAVE_C_REGS_EXCEPT_R891011
+       SAVE_C_REGS_HELPER 0, 1, 1, 0, 0
+       .endm
+       .macro SAVE_C_REGS_EXCEPT_RCX_R891011
+       SAVE_C_REGS_HELPER 0, 1, 0, 0, 0
+       .endm
+       .macro SAVE_C_REGS_EXCEPT_RAX_RCX_R11
+       SAVE_C_REGS_HELPER 0, 0, 0, 1, 0
+       .endm
+
+       .macro SAVE_EXTRA_REGS offset=0
+       movq_cfi r15, 0*8+\offset
+       movq_cfi r14, 1*8+\offset
+       movq_cfi r13, 2*8+\offset
+       movq_cfi r12, 3*8+\offset
+       movq_cfi rbp, 4*8+\offset
+       movq_cfi rbx, 5*8+\offset
+       .endm
+       .macro SAVE_EXTRA_REGS_RBP offset=0
+       movq_cfi rbp, 4*8+\offset
+       .endm
 
+       .macro RESTORE_EXTRA_REGS offset=0
+       movq_cfi_restore 0*8+\offset, r15
+       movq_cfi_restore 1*8+\offset, r14
+       movq_cfi_restore 2*8+\offset, r13
+       movq_cfi_restore 3*8+\offset, r12
+       movq_cfi_restore 4*8+\offset, rbp
+       movq_cfi_restore 5*8+\offset, rbx
        .endm
 
-#define ARG_SKIP       (9*8)
+       .macro ZERO_EXTRA_REGS
+       xorl    %r15d, %r15d
+       xorl    %r14d, %r14d
+       xorl    %r13d, %r13d
+       xorl    %r12d, %r12d
+       xorl    %ebp, %ebp
+       xorl    %ebx, %ebx
+       .endm
 
-       .macro RESTORE_ARGS rstor_rax=1, addskip=0, rstor_rcx=1, rstor_r11=1, \
-                           rstor_r8910=1, rstor_rdx=1
+       .macro RESTORE_C_REGS_HELPER rstor_rax=1, rstor_rcx=1, rstor_r11=1, rstor_r8910=1, rstor_rdx=1
        .if \rstor_r11
-       movq_cfi_restore 0*8, r11
+       movq_cfi_restore 6*8, r11
        .endif
-
        .if \rstor_r8910
-       movq_cfi_restore 1*8, r10
-       movq_cfi_restore 2*8, r9
-       movq_cfi_restore 3*8, r8
+       movq_cfi_restore 7*8, r10
+       movq_cfi_restore 8*8, r9
+       movq_cfi_restore 9*8, r8
        .endif
-
        .if \rstor_rax
-       movq_cfi_restore 4*8, rax
+       movq_cfi_restore 10*8, rax
        .endif
-
        .if \rstor_rcx
-       movq_cfi_restore 5*8, rcx
+       movq_cfi_restore 11*8, rcx
        .endif
-
        .if \rstor_rdx
-       movq_cfi_restore 6*8, rdx
-       .endif
-
-       movq_cfi_restore 7*8, rsi
-       movq_cfi_restore 8*8, rdi
-
-       .if ARG_SKIP+\addskip > 0
-       addq $ARG_SKIP+\addskip, %rsp
-       CFI_ADJUST_CFA_OFFSET   -(ARG_SKIP+\addskip)
+       movq_cfi_restore 12*8, rdx
        .endif
+       movq_cfi_restore 13*8, rsi
+       movq_cfi_restore 14*8, rdi
        .endm
-
-       .macro LOAD_ARGS offset, skiprax=0
-       movq \offset(%rsp),    %r11
-       movq \offset+8(%rsp),  %r10
-       movq \offset+16(%rsp), %r9
-       movq \offset+24(%rsp), %r8
-       movq \offset+40(%rsp), %rcx
-       movq \offset+48(%rsp), %rdx
-       movq \offset+56(%rsp), %rsi
-       movq \offset+64(%rsp), %rdi
-       .if \skiprax
-       .else
-       movq \offset+72(%rsp), %rax
-       .endif
+       .macro RESTORE_C_REGS
+       RESTORE_C_REGS_HELPER 1,1,1,1,1
        .endm
-
-#define REST_SKIP      (6*8)
-
-       .macro SAVE_REST
-       subq $REST_SKIP, %rsp
-       CFI_ADJUST_CFA_OFFSET   REST_SKIP
-       movq_cfi rbx, 5*8
-       movq_cfi rbp, 4*8
-       movq_cfi r12, 3*8
-       movq_cfi r13, 2*8
-       movq_cfi r14, 1*8
-       movq_cfi r15, 0*8
+       .macro RESTORE_C_REGS_EXCEPT_RAX
+       RESTORE_C_REGS_HELPER 0,1,1,1,1
        .endm
-
-       .macro RESTORE_REST
-       movq_cfi_restore 0*8, r15
-       movq_cfi_restore 1*8, r14
-       movq_cfi_restore 2*8, r13
-       movq_cfi_restore 3*8, r12
-       movq_cfi_restore 4*8, rbp
-       movq_cfi_restore 5*8, rbx
-       addq $REST_SKIP, %rsp
-       CFI_ADJUST_CFA_OFFSET   -(REST_SKIP)
+       .macro RESTORE_C_REGS_EXCEPT_RCX
+       RESTORE_C_REGS_HELPER 1,0,1,1,1
        .endm
-
-       .macro SAVE_ALL
-       SAVE_ARGS
-       SAVE_REST
+       .macro RESTORE_C_REGS_EXCEPT_R11
+       RESTORE_C_REGS_HELPER 1,1,0,1,1
+       .endm
+       .macro RESTORE_C_REGS_EXCEPT_RCX_R11
+       RESTORE_C_REGS_HELPER 1,0,0,1,1
+       .endm
+       .macro RESTORE_RSI_RDI
+       RESTORE_C_REGS_HELPER 0,0,0,0,0
+       .endm
+       .macro RESTORE_RSI_RDI_RDX
+       RESTORE_C_REGS_HELPER 0,0,0,0,1
        .endm
 
-       .macro RESTORE_ALL addskip=0
-       RESTORE_REST
-       RESTORE_ARGS 1, \addskip
+       .macro REMOVE_PT_GPREGS_FROM_STACK addskip=0
+       addq $15*8+\addskip, %rsp
+       CFI_ADJUST_CFA_OFFSET -(15*8+\addskip)
        .endm
 
        .macro icebp
@@ -210,37 +224,23 @@ For 32-bit we have the following conventions - kernel is built with
  */
 
        .macro SAVE_ALL
-       pushl_cfi %eax
-       CFI_REL_OFFSET eax, 0
-       pushl_cfi %ebp
-       CFI_REL_OFFSET ebp, 0
-       pushl_cfi %edi
-       CFI_REL_OFFSET edi, 0
-       pushl_cfi %esi
-       CFI_REL_OFFSET esi, 0
-       pushl_cfi %edx
-       CFI_REL_OFFSET edx, 0
-       pushl_cfi %ecx
-       CFI_REL_OFFSET ecx, 0
-       pushl_cfi %ebx
-       CFI_REL_OFFSET ebx, 0
+       pushl_cfi_reg eax
+       pushl_cfi_reg ebp
+       pushl_cfi_reg edi
+       pushl_cfi_reg esi
+       pushl_cfi_reg edx
+       pushl_cfi_reg ecx
+       pushl_cfi_reg ebx
        .endm
 
        .macro RESTORE_ALL
-       popl_cfi %ebx
-       CFI_RESTORE ebx
-       popl_cfi %ecx
-       CFI_RESTORE ecx
-       popl_cfi %edx
-       CFI_RESTORE edx
-       popl_cfi %esi
-       CFI_RESTORE esi
-       popl_cfi %edi
-       CFI_RESTORE edi
-       popl_cfi %ebp
-       CFI_RESTORE ebp
-       popl_cfi %eax
-       CFI_RESTORE eax
+       popl_cfi_reg ebx
+       popl_cfi_reg ecx
+       popl_cfi_reg edx
+       popl_cfi_reg esi
+       popl_cfi_reg edi
+       popl_cfi_reg ebp
+       popl_cfi_reg eax
        .endm
 
 #endif /* CONFIG_X86_64 */
index 59c6c401f79f16d9b98533275d66d437cbaeff0c..acdee09228b30e020332f0beb7e55e58e65b718e 100644 (file)
@@ -301,7 +301,7 @@ static inline void __user *arch_compat_alloc_user_space(long len)
                sp = task_pt_regs(current)->sp;
        } else {
                /* -128 for the x32 ABI redzone */
-               sp = this_cpu_read(old_rsp) - 128;
+               sp = task_pt_regs(current)->sp - 128;
        }
 
        return (void __user *)round_down(sp - len, 16);
index d2b12988d2ed19b355b09347582c81db15c41a3d..bf2caa1dedc5a3e1f9a3854b689d95c68b62b40f 100644 (file)
@@ -34,8 +34,6 @@ extern int _debug_hotplug_cpu(int cpu, int action);
 #endif
 #endif
 
-DECLARE_PER_CPU(int, cpu_state);
-
 int mwait_usable(const struct cpuinfo_x86 *);
 
 #endif /* _ASM_X86_CPU_H */
index 90a54851aedc98b29c65856986ade222818381b8..7ee9b94d9921bf0a1ea7e010c76985cb6a8595ce 100644 (file)
@@ -12,7 +12,7 @@
 #include <asm/disabled-features.h>
 #endif
 
-#define NCAPINTS       11      /* N 32-bit words worth of info */
+#define NCAPINTS       13      /* N 32-bit words worth of info */
 #define NBUGINTS       1       /* N 32-bit bug flags */
 
 /*
 #define X86_FEATURE_HWP_ACT_WINDOW ( 7*32+ 12) /* Intel HWP_ACT_WINDOW */
 #define X86_FEATURE_HWP_EPP    ( 7*32+13) /* Intel HWP_EPP */
 #define X86_FEATURE_HWP_PKG_REQ ( 7*32+14) /* Intel HWP_PKG_REQ */
+#define X86_FEATURE_INTEL_PT   ( 7*32+15) /* Intel Processor Trace */
 
 /* Virtualization flags: Linux defined, word 8 */
 #define X86_FEATURE_TPR_SHADOW  ( 8*32+ 0) /* Intel TPR Shadow */
 #define X86_FEATURE_ERMS       ( 9*32+ 9) /* Enhanced REP MOVSB/STOSB */
 #define X86_FEATURE_INVPCID    ( 9*32+10) /* Invalidate Processor Context ID */
 #define X86_FEATURE_RTM                ( 9*32+11) /* Restricted Transactional Memory */
+#define X86_FEATURE_CQM                ( 9*32+12) /* Cache QoS Monitoring */
 #define X86_FEATURE_MPX                ( 9*32+14) /* Memory Protection Extension */
 #define X86_FEATURE_AVX512F    ( 9*32+16) /* AVX-512 Foundation */
 #define X86_FEATURE_RDSEED     ( 9*32+18) /* The RDSEED instruction */
 #define X86_FEATURE_ADX                ( 9*32+19) /* The ADCX and ADOX instructions */
 #define X86_FEATURE_SMAP       ( 9*32+20) /* Supervisor Mode Access Prevention */
+#define X86_FEATURE_PCOMMIT    ( 9*32+22) /* PCOMMIT instruction */
 #define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
+#define X86_FEATURE_CLWB       ( 9*32+24) /* CLWB instruction */
 #define X86_FEATURE_AVX512PF   ( 9*32+26) /* AVX-512 Prefetch */
 #define X86_FEATURE_AVX512ER   ( 9*32+27) /* AVX-512 Exponential and Reciprocal */
 #define X86_FEATURE_AVX512CD   ( 9*32+28) /* AVX-512 Conflict Detection */
 #define X86_FEATURE_XGETBV1    (10*32+ 2) /* XGETBV with ECX = 1 */
 #define X86_FEATURE_XSAVES     (10*32+ 3) /* XSAVES/XRSTORS */
 
+/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:0 (edx), word 11 */
+#define X86_FEATURE_CQM_LLC    (11*32+ 1) /* LLC QoS if 1 */
+
+/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:1 (edx), word 12 */
+#define X86_FEATURE_CQM_OCCUP_LLC (12*32+ 0) /* LLC occupancy monitoring if 1 */
+
 /*
  * BUG word(s)
  */
@@ -418,6 +428,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
                         " .word %P0\n"         /* 1: do replace */
                         " .byte 2b - 1b\n"     /* source len */
                         " .byte 0\n"           /* replacement len */
+                        " .byte 0\n"           /* pad len */
                         ".previous\n"
                         /* skipping size check since replacement size = 0 */
                         : : "i" (X86_FEATURE_ALWAYS) : : t_warn);
@@ -432,6 +443,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
                         " .word %P0\n"         /* feature bit */
                         " .byte 2b - 1b\n"     /* source len */
                         " .byte 0\n"           /* replacement len */
+                        " .byte 0\n"           /* pad len */
                         ".previous\n"
                         /* skipping size check since replacement size = 0 */
                         : : "i" (bit) : : t_no);
@@ -457,6 +469,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
                             " .word %P1\n"             /* feature bit */
                             " .byte 2b - 1b\n"         /* source len */
                             " .byte 4f - 3f\n"         /* replacement len */
+                            " .byte 0\n"               /* pad len */
                             ".previous\n"
                             ".section .discard,\"aw\",@progbits\n"
                             " .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */
@@ -483,31 +496,30 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
 static __always_inline __pure bool _static_cpu_has_safe(u16 bit)
 {
 #ifdef CC_HAVE_ASM_GOTO
-/*
- * We need to spell the jumps to the compiler because, depending on the offset,
- * the replacement jump can be bigger than the original jump, and this we cannot
- * have. Thus, we force the jump to the widest, 4-byte, signed relative
- * offset even though the last would often fit in less bytes.
- */
-               asm_volatile_goto("1: .byte 0xe9\n .long %l[t_dynamic] - 2f\n"
+               asm_volatile_goto("1: jmp %l[t_dynamic]\n"
                         "2:\n"
+                        ".skip -(((5f-4f) - (2b-1b)) > 0) * "
+                                "((5f-4f) - (2b-1b)),0x90\n"
+                        "3:\n"
                         ".section .altinstructions,\"a\"\n"
                         " .long 1b - .\n"              /* src offset */
-                        " .long 3f - .\n"              /* repl offset */
+                        " .long 4f - .\n"              /* repl offset */
                         " .word %P1\n"                 /* always replace */
-                        " .byte 2b - 1b\n"             /* src len */
-                        " .byte 4f - 3f\n"             /* repl len */
+                        " .byte 3b - 1b\n"             /* src len */
+                        " .byte 5f - 4f\n"             /* repl len */
+                        " .byte 3b - 2b\n"             /* pad len */
                         ".previous\n"
                         ".section .altinstr_replacement,\"ax\"\n"
-                        "3: .byte 0xe9\n .long %l[t_no] - 2b\n"
-                        "4:\n"
+                        "4: jmp %l[t_no]\n"
+                        "5:\n"
                         ".previous\n"
                         ".section .altinstructions,\"a\"\n"
                         " .long 1b - .\n"              /* src offset */
                         " .long 0\n"                   /* no replacement */
                         " .word %P0\n"                 /* feature bit */
-                        " .byte 2b - 1b\n"             /* src len */
+                        " .byte 3b - 1b\n"             /* src len */
                         " .byte 0\n"                   /* repl len */
+                        " .byte 0\n"                   /* pad len */
                         ".previous\n"
                         : : "i" (bit), "i" (X86_FEATURE_ALWAYS)
                         : : t_dynamic, t_no);
@@ -527,6 +539,7 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit)
                             " .word %P2\n"             /* always replace */
                             " .byte 2b - 1b\n"         /* source len */
                             " .byte 4f - 3f\n"         /* replacement len */
+                            " .byte 0\n"               /* pad len */
                             ".previous\n"
                             ".section .discard,\"aw\",@progbits\n"
                             " .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */
@@ -541,6 +554,7 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit)
                             " .word %P1\n"             /* feature bit */
                             " .byte 4b - 3b\n"         /* src len */
                             " .byte 6f - 5f\n"         /* repl len */
+                            " .byte 0\n"               /* pad len */
                             ".previous\n"
                             ".section .discard,\"aw\",@progbits\n"
                             " .byte 0xff + (6f-5f) - (4b-3b)\n" /* size check */
index a94b82e8f156f3888e0ab90ac879e39dd05ccec1..a0bf89fd26470102f6f38031808437f01afe8e1f 100644 (file)
@@ -376,11 +376,16 @@ static inline void _set_gate(int gate, unsigned type, void *addr,
  * Pentium F0 0F bugfix can have resulted in the mapped
  * IDT being write-protected.
  */
-#define set_intr_gate(n, addr)                                         \
+#define set_intr_gate_notrace(n, addr)                                 \
        do {                                                            \
                BUG_ON((unsigned)n > 0xFF);                             \
                _set_gate(n, GATE_INTERRUPT, (void *)addr, 0, 0,        \
                          __KERNEL_CS);                                 \
+       } while (0)
+
+#define set_intr_gate(n, addr)                                         \
+       do {                                                            \
+               set_intr_gate_notrace(n, addr);                         \
                _trace_set_gate(n, GATE_INTERRUPT, (void *)trace_##addr,\
                                0, 0, __KERNEL_CS);                     \
        } while (0)
index f6f15986df6ca0f097cf245f04da7a6c123ad3b7..de1cdaf4d74346040667da81e767a5a32697c7c6 100644 (file)
        CFI_ADJUST_CFA_OFFSET 8
        .endm
 
+       .macro pushq_cfi_reg reg
+       pushq %\reg
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET \reg, 0
+       .endm
+
        .macro popq_cfi reg
        popq \reg
        CFI_ADJUST_CFA_OFFSET -8
        .endm
 
+       .macro popq_cfi_reg reg
+       popq %\reg
+       CFI_ADJUST_CFA_OFFSET -8
+       CFI_RESTORE \reg
+       .endm
+
        .macro pushfq_cfi
        pushfq
        CFI_ADJUST_CFA_OFFSET 8
        CFI_ADJUST_CFA_OFFSET 4
        .endm
 
+       .macro pushl_cfi_reg reg
+       pushl %\reg
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET \reg, 0
+       .endm
+
        .macro popl_cfi reg
        popl \reg
        CFI_ADJUST_CFA_OFFSET -4
        .endm
 
+       .macro popl_cfi_reg reg
+       popl %\reg
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE \reg
+       .endm
+
        .macro pushfl_cfi
        pushfl
        CFI_ADJUST_CFA_OFFSET 4
index 779c2efe2e97cf3ceabe2d421f3f1772514a9120..3ab0537872fb790e6864674efcf3130324687723 100644 (file)
@@ -40,14 +40,6 @@ static inline void e820_mark_nosave_regions(unsigned long limit_pfn)
 }
 #endif
 
-#ifdef CONFIG_MEMTEST
-extern void early_memtest(unsigned long start, unsigned long end);
-#else
-static inline void early_memtest(unsigned long start, unsigned long end)
-{
-}
-#endif
-
 extern unsigned long e820_end_of_ram_pfn(void);
 extern unsigned long e820_end_of_low_ram_pfn(void);
 extern u64 early_reserve_e820(u64 sizet, u64 align);
index 25bce45c6fc42f848bf70b56cf5a37884dd18684..3738b138b843d46467c75a910d916cc79ebad25f 100644 (file)
@@ -2,6 +2,8 @@
 #define _ASM_X86_EFI_H
 
 #include <asm/i387.h>
+#include <asm/pgtable.h>
+
 /*
  * We map the EFI regions needed for runtime services non-contiguously,
  * with preserved alignment on virtual addresses starting from -4G down
@@ -89,8 +91,8 @@ extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size,
 extern struct efi_scratch efi_scratch;
 extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable);
 extern int __init efi_memblock_x86_reserve_range(void);
-extern void __init efi_call_phys_prolog(void);
-extern void __init efi_call_phys_epilog(void);
+extern pgd_t * __init efi_call_phys_prolog(void);
+extern void __init efi_call_phys_epilog(pgd_t *save_pgd);
 extern void __init efi_unmap_memmap(void);
 extern void __init efi_memory_uc(u64 addr, unsigned long size);
 extern void __init efi_map_region(efi_memory_desc_t *md);
index ca3347a9dab5211399e9e93a5e53d71ca1943095..f161c189c27b580ef02d1a1c7c8795806445c825 100644 (file)
@@ -171,10 +171,11 @@ do {                                              \
 static inline void elf_common_init(struct thread_struct *t,
                                   struct pt_regs *regs, const u16 ds)
 {
-       regs->ax = regs->bx = regs->cx = regs->dx = 0;
-       regs->si = regs->di = regs->bp = 0;
+       /* Commented-out registers are cleared in stub_execve */
+       /*regs->ax = regs->bx =*/ regs->cx = regs->dx = 0;
+       regs->si = regs->di /*= regs->bp*/ = 0;
        regs->r8 = regs->r9 = regs->r10 = regs->r11 = 0;
-       regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0;
+       /*regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0;*/
        t->fs = t->gs = 0;
        t->fsindex = t->gsindex = 0;
        t->ds = t->es = ds;
@@ -338,9 +339,6 @@ extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
                                              int uses_interp);
 #define compat_arch_setup_additional_pages compat_arch_setup_additional_pages
 
-extern unsigned long arch_randomize_brk(struct mm_struct *mm);
-#define arch_randomize_brk arch_randomize_brk
-
 /*
  * True on X86_32 or when emulating IA32 on X86_64
  */
@@ -365,6 +363,7 @@ enum align_flags {
 struct va_alignment {
        int flags;
        unsigned long mask;
+       unsigned long bits;
 } ____cacheline_aligned;
 
 extern struct va_alignment va_align;
index 72ba21a8b5fc2ff8b76c6c3e53b331ca6a558339..da5e96756570be6b1794e20d4161f4a540d1a781 100644 (file)
@@ -67,6 +67,34 @@ extern void finit_soft_fpu(struct i387_soft_struct *soft);
 static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
 #endif
 
+/*
+ * Must be run with preemption disabled: this clears the fpu_owner_task,
+ * on this CPU.
+ *
+ * This will disable any lazy FPU state restore of the current FPU state,
+ * but if the current thread owns the FPU, it will still be saved by.
+ */
+static inline void __cpu_disable_lazy_restore(unsigned int cpu)
+{
+       per_cpu(fpu_owner_task, cpu) = NULL;
+}
+
+/*
+ * Used to indicate that the FPU state in memory is newer than the FPU
+ * state in registers, and the FPU state should be reloaded next time the
+ * task is run. Only safe on the current task, or non-running tasks.
+ */
+static inline void task_disable_lazy_fpu_restore(struct task_struct *tsk)
+{
+       tsk->thread.fpu.last_cpu = ~0;
+}
+
+static inline int fpu_lazy_restore(struct task_struct *new, unsigned int cpu)
+{
+       return new == this_cpu_read_stable(fpu_owner_task) &&
+               cpu == new->thread.fpu.last_cpu;
+}
+
 static inline int is_ia32_compat_frame(void)
 {
        return config_enabled(CONFIG_IA32_EMULATION) &&
@@ -107,7 +135,6 @@ static __always_inline __pure bool use_fxsr(void)
 
 static inline void fx_finit(struct i387_fxsave_struct *fx)
 {
-       memset(fx, 0, xstate_size);
        fx->cwd = 0x37f;
        fx->mxcsr = MXCSR_DEFAULT;
 }
@@ -351,8 +378,14 @@ static inline void __thread_fpu_begin(struct task_struct *tsk)
        __thread_set_has_fpu(tsk);
 }
 
-static inline void __drop_fpu(struct task_struct *tsk)
+static inline void drop_fpu(struct task_struct *tsk)
 {
+       /*
+        * Forget coprocessor state..
+        */
+       preempt_disable();
+       tsk->thread.fpu_counter = 0;
+
        if (__thread_has_fpu(tsk)) {
                /* Ignore delayed exceptions from user space */
                asm volatile("1: fwait\n"
@@ -360,30 +393,29 @@ static inline void __drop_fpu(struct task_struct *tsk)
                             _ASM_EXTABLE(1b, 2b));
                __thread_fpu_end(tsk);
        }
-}
 
-static inline void drop_fpu(struct task_struct *tsk)
-{
-       /*
-        * Forget coprocessor state..
-        */
-       preempt_disable();
-       tsk->thread.fpu_counter = 0;
-       __drop_fpu(tsk);
        clear_stopped_child_used_math(tsk);
        preempt_enable();
 }
 
-static inline void drop_init_fpu(struct task_struct *tsk)
+static inline void restore_init_xstate(void)
+{
+       if (use_xsave())
+               xrstor_state(init_xstate_buf, -1);
+       else
+               fxrstor_checking(&init_xstate_buf->i387);
+}
+
+/*
+ * Reset the FPU state in the eager case and drop it in the lazy case (later use
+ * will reinit it).
+ */
+static inline void fpu_reset_state(struct task_struct *tsk)
 {
        if (!use_eager_fpu())
                drop_fpu(tsk);
-       else {
-               if (use_xsave())
-                       xrstor_state(init_xstate_buf, -1);
-               else
-                       fxrstor_checking(&init_xstate_buf->i387);
-       }
+       else
+               restore_init_xstate();
 }
 
 /*
@@ -400,24 +432,6 @@ static inline void drop_init_fpu(struct task_struct *tsk)
  */
 typedef struct { int preload; } fpu_switch_t;
 
-/*
- * Must be run with preemption disabled: this clears the fpu_owner_task,
- * on this CPU.
- *
- * This will disable any lazy FPU state restore of the current FPU state,
- * but if the current thread owns the FPU, it will still be saved by.
- */
-static inline void __cpu_disable_lazy_restore(unsigned int cpu)
-{
-       per_cpu(fpu_owner_task, cpu) = NULL;
-}
-
-static inline int fpu_lazy_restore(struct task_struct *new, unsigned int cpu)
-{
-       return new == this_cpu_read_stable(fpu_owner_task) &&
-               cpu == new->thread.fpu.last_cpu;
-}
-
 static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct task_struct *new, int cpu)
 {
        fpu_switch_t fpu;
@@ -426,13 +440,17 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta
         * If the task has used the math, pre-load the FPU on xsave processors
         * or if the past 5 consecutive context-switches used math.
         */
-       fpu.preload = tsk_used_math(new) && (use_eager_fpu() ||
-                                            new->thread.fpu_counter > 5);
+       fpu.preload = tsk_used_math(new) &&
+                     (use_eager_fpu() || new->thread.fpu_counter > 5);
+
        if (__thread_has_fpu(old)) {
                if (!__save_init_fpu(old))
-                       cpu = ~0;
-               old->thread.fpu.last_cpu = cpu;
-               old->thread.fpu.has_fpu = 0;    /* But leave fpu_owner_task! */
+                       task_disable_lazy_fpu_restore(old);
+               else
+                       old->thread.fpu.last_cpu = cpu;
+
+               /* But leave fpu_owner_task! */
+               old->thread.fpu.has_fpu = 0;
 
                /* Don't change CR0.TS if we just switch! */
                if (fpu.preload) {
@@ -443,10 +461,10 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta
                        stts();
        } else {
                old->thread.fpu_counter = 0;
-               old->thread.fpu.last_cpu = ~0;
+               task_disable_lazy_fpu_restore(old);
                if (fpu.preload) {
                        new->thread.fpu_counter++;
-                       if (!use_eager_fpu() && fpu_lazy_restore(new, cpu))
+                       if (fpu_lazy_restore(new, cpu))
                                fpu.preload = 0;
                        else
                                prefetch(new->thread.fpu.state);
@@ -466,7 +484,7 @@ static inline void switch_fpu_finish(struct task_struct *new, fpu_switch_t fpu)
 {
        if (fpu.preload) {
                if (unlikely(restore_fpu_checking(new)))
-                       drop_init_fpu(new);
+                       fpu_reset_state(new);
        }
 }
 
@@ -495,10 +513,12 @@ static inline int restore_xstate_sig(void __user *buf, int ia32_frame)
 }
 
 /*
- * Need to be preemption-safe.
+ * Needs to be preemption-safe.
  *
  * NOTE! user_fpu_begin() must be used only immediately before restoring
- * it. This function does not do any save/restore on their own.
+ * the save state. It does not do any saving/restoring on its own. In
+ * lazy FPU mode, it is just an optimization to avoid a #NM exception,
+ * the task can lose the FPU right after preempt_enable().
  */
 static inline void user_fpu_begin(void)
 {
@@ -519,24 +539,6 @@ static inline void __save_fpu(struct task_struct *tsk)
                fpu_fxsave(&tsk->thread.fpu);
 }
 
-/*
- * These disable preemption on their own and are safe
- */
-static inline void save_init_fpu(struct task_struct *tsk)
-{
-       WARN_ON_ONCE(!__thread_has_fpu(tsk));
-
-       if (use_eager_fpu()) {
-               __save_fpu(tsk);
-               return;
-       }
-
-       preempt_disable();
-       __save_init_fpu(tsk);
-       __thread_fpu_end(tsk);
-       preempt_enable();
-}
-
 /*
  * i387 state interaction
  */
index 9662290e0b2075ab42608af776abbe4a4219b6fd..e9571ddabc4feb821ae04d47c9d6c3b509178344 100644 (file)
@@ -181,10 +181,9 @@ extern __visible void smp_call_function_single_interrupt(struct pt_regs *);
 extern __visible void smp_invalidate_interrupt(struct pt_regs *);
 #endif
 
-extern void (*__initconst interrupt[FIRST_SYSTEM_VECTOR
-                                   - FIRST_EXTERNAL_VECTOR])(void);
+extern char irq_entries_start[];
 #ifdef CONFIG_TRACING
-#define trace_interrupt interrupt
+#define trace_irq_entries_start irq_entries_start
 #endif
 
 #define VECTOR_UNDEFINED       (-1)
index 47f29b1d18464aa6870ce6add18d5f37af2c28fb..e7814b74caf8235c985d5f49492aa0656cfac053 100644 (file)
@@ -69,7 +69,7 @@ struct insn {
        const insn_byte_t *next_byte;
 };
 
-#define MAX_INSN_SIZE  16
+#define MAX_INSN_SIZE  15
 
 #define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6)
 #define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3)
index f42a04735a0a66c7f15cdc8640308861902c753d..e37d6b3ad9831bb05412114bac11f1cd0bf0bac3 100644 (file)
@@ -79,11 +79,12 @@ struct iommu_table_entry {
  *  d). Similar to the 'init', except that this gets called from pci_iommu_init
  *      where we do have a memory allocator.
  *
- * The standard vs the _FINISH differs in that the _FINISH variant will
- * continue detecting other IOMMUs in the call list after the
- * the detection routine returns a positive number. The _FINISH will
- * stop the execution chain. Both will still call the 'init' and
- * 'late_init' functions if they are set.
+ * The standard IOMMU_INIT differs from the IOMMU_INIT_FINISH variant
+ * in that the former will continue detecting other IOMMUs in the call
+ * list after the detection routine returns a positive number, while the
+ * latter will stop the execution chain upon first successful detection.
+ * Both variants will still call the 'init' and 'late_init' functions if
+ * they are set.
  */
 #define IOMMU_INIT_FINISH(_detect, _depend, _init, _late_init)         \
        __IOMMU_INIT(_detect, _depend, _init, _late_init, 1)
index 0a8b519226b8feb37368ffbc4ca81011bc031fde..b77f5edb03b0c02dc2047d52d07c9da447dba209 100644 (file)
@@ -136,10 +136,6 @@ static inline notrace unsigned long arch_local_irq_save(void)
 #define USERGS_SYSRET32                                \
        swapgs;                                 \
        sysretl
-#define ENABLE_INTERRUPTS_SYSEXIT32            \
-       swapgs;                                 \
-       sti;                                    \
-       sysexit
 
 #else
 #define INTERRUPT_RETURN               iret
@@ -163,22 +159,27 @@ static inline int arch_irqs_disabled(void)
 
        return arch_irqs_disabled_flags(flags);
 }
+#endif /* !__ASSEMBLY__ */
 
+#ifdef __ASSEMBLY__
+#ifdef CONFIG_TRACE_IRQFLAGS
+#  define TRACE_IRQS_ON                call trace_hardirqs_on_thunk;
+#  define TRACE_IRQS_OFF       call trace_hardirqs_off_thunk;
 #else
-
-#ifdef CONFIG_X86_64
-#define ARCH_LOCKDEP_SYS_EXIT          call lockdep_sys_exit_thunk
-#define ARCH_LOCKDEP_SYS_EXIT_IRQ      \
+#  define TRACE_IRQS_ON
+#  define TRACE_IRQS_OFF
+#endif
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#  ifdef CONFIG_X86_64
+#    define LOCKDEP_SYS_EXIT           call lockdep_sys_exit_thunk
+#    define LOCKDEP_SYS_EXIT_IRQ \
        TRACE_IRQS_ON; \
        sti; \
-       SAVE_REST; \
-       LOCKDEP_SYS_EXIT; \
-       RESTORE_REST; \
+       call lockdep_sys_exit_thunk; \
        cli; \
        TRACE_IRQS_OFF;
-
-#else
-#define ARCH_LOCKDEP_SYS_EXIT                  \
+#  else
+#    define LOCKDEP_SYS_EXIT \
        pushl %eax;                             \
        pushl %ecx;                             \
        pushl %edx;                             \
@@ -186,24 +187,12 @@ static inline int arch_irqs_disabled(void)
        popl %edx;                              \
        popl %ecx;                              \
        popl %eax;
-
-#define ARCH_LOCKDEP_SYS_EXIT_IRQ
-#endif
-
-#ifdef CONFIG_TRACE_IRQFLAGS
-#  define TRACE_IRQS_ON                call trace_hardirqs_on_thunk;
-#  define TRACE_IRQS_OFF       call trace_hardirqs_off_thunk;
+#    define LOCKDEP_SYS_EXIT_IRQ
+#  endif
 #else
-#  define TRACE_IRQS_ON
-#  define TRACE_IRQS_OFF
-#endif
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-#  define LOCKDEP_SYS_EXIT     ARCH_LOCKDEP_SYS_EXIT
-#  define LOCKDEP_SYS_EXIT_IRQ ARCH_LOCKDEP_SYS_EXIT_IRQ
-# else
 #  define LOCKDEP_SYS_EXIT
 #  define LOCKDEP_SYS_EXIT_IRQ
-# endif
-
+#endif
 #endif /* __ASSEMBLY__ */
+
 #endif
index 6a2cefb4395a4228cce550ef8b231f3e7158d9d1..a4c1cf7e93f812e85fb56d3f858547192c028c58 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
-#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
 
 #include <linux/stringify.h>
 #include <linux/types.h>
@@ -30,8 +30,6 @@ l_yes:
        return true;
 }
 
-#endif /* __KERNEL__ */
-
 #ifdef CONFIG_X86_64
 typedef u64 jump_label_t;
 #else
@@ -44,4 +42,5 @@ struct jump_entry {
        jump_label_t key;
 };
 
+#endif  /* __ASSEMBLY__ */
 #endif
index a236e39cc385a4a468e745ce0d9fdb1e2d08341b..dea2e7e962e3e0648c9ecaaaffc5cb723b32f299 100644 (file)
@@ -81,11 +81,6 @@ static inline gfn_t gfn_to_index(gfn_t gfn, gfn_t base_gfn, int level)
                (base_gfn >> KVM_HPAGE_GFN_SHIFT(level));
 }
 
-#define SELECTOR_TI_MASK (1 << 2)
-#define SELECTOR_RPL_MASK 0x03
-
-#define IOPL_SHIFT 12
-
 #define KVM_PERMILLE_MMU_PAGES 20
 #define KVM_MIN_ALLOC_MMU_PAGES 64
 #define KVM_MMU_HASH_SHIFT 10
@@ -345,6 +340,7 @@ struct kvm_pmu {
 enum {
        KVM_DEBUGREG_BP_ENABLED = 1,
        KVM_DEBUGREG_WONT_EXIT = 2,
+       KVM_DEBUGREG_RELOAD = 4,
 };
 
 struct kvm_vcpu_arch {
@@ -431,6 +427,9 @@ struct kvm_vcpu_arch {
 
        int cpuid_nent;
        struct kvm_cpuid_entry2 cpuid_entries[KVM_MAX_CPUID_ENTRIES];
+
+       int maxphyaddr;
+
        /* emulate context */
 
        struct x86_emulate_ctxt emulate_ctxt;
@@ -550,11 +549,20 @@ struct kvm_arch_memory_slot {
        struct kvm_lpage_info *lpage_info[KVM_NR_PAGE_SIZES - 1];
 };
 
+/*
+ * We use as the mode the number of bits allocated in the LDR for the
+ * logical processor ID.  It happens that these are all powers of two.
+ * This makes it is very easy to detect cases where the APICs are
+ * configured for multiple modes; in that case, we cannot use the map and
+ * hence cannot use kvm_irq_delivery_to_apic_fast either.
+ */
+#define KVM_APIC_MODE_XAPIC_CLUSTER          4
+#define KVM_APIC_MODE_XAPIC_FLAT             8
+#define KVM_APIC_MODE_X2APIC                16
+
 struct kvm_apic_map {
        struct rcu_head rcu;
-       u8 ldr_bits;
-       /* fields bellow are used to decode ldr values in different modes */
-       u32 cid_shift, cid_mask, lid_mask, broadcast;
+       u8 mode;
        struct kvm_lapic *phys_map[256];
        /* first index is cluster id second is cpu id in a cluster */
        struct kvm_lapic *logical_map[16][16];
@@ -859,6 +867,8 @@ void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
 void kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
 void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
                                      struct kvm_memory_slot *memslot);
+void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
+                                       struct kvm_memory_slot *memslot);
 void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
                                   struct kvm_memory_slot *memslot);
 void kvm_mmu_slot_largepage_remove_write_access(struct kvm *kvm,
@@ -933,6 +943,7 @@ struct x86_emulate_ctxt;
 int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, unsigned short port);
 void kvm_emulate_cpuid(struct kvm_vcpu *vcpu);
 int kvm_emulate_halt(struct kvm_vcpu *vcpu);
+int kvm_vcpu_halt(struct kvm_vcpu *vcpu);
 int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu);
 
 void kvm_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
@@ -1128,7 +1139,6 @@ int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
 int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
 int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
 void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
-int cpuid_maxphyaddr(struct kvm_vcpu *vcpu);
 int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v);
 int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu);
 int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu);
index e62cf897f7819bc9795ab096a15689b3543e07b2..c1adf33fdd0d6f70f055b9a056bc7787bda7635e 100644 (file)
@@ -115,7 +115,7 @@ static inline void kvm_spinlock_init(void)
 
 static inline bool kvm_para_available(void)
 {
-       return 0;
+       return false;
 }
 
 static inline unsigned int kvm_arch_para_features(void)
index a455a53d789a12c908097ee6b266086c56479e47..2d29197bd2fbfb7da88b1b3f9c9c932a78e177a5 100644 (file)
@@ -32,8 +32,8 @@ static inline int klp_check_compiler_support(void)
 #endif
        return 0;
 }
-extern int klp_write_module_reloc(struct module *mod, unsigned long type,
-                                 unsigned long loc, unsigned long value);
+int klp_write_module_reloc(struct module *mod, unsigned long type,
+                          unsigned long loc, unsigned long value);
 
 static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 {
index 9b3de99dc0044a8b6ccdba0e7523f5b1e8425c03..1f5a86d518db379ea65c100158df0c60988bb810 100644 (file)
@@ -116,6 +116,12 @@ struct mca_config {
        u32 rip_msr;
 };
 
+struct mce_vendor_flags {
+       __u64           overflow_recov  : 1, /* cpuid_ebx(80000007) */
+                       __reserved_0    : 63;
+};
+extern struct mce_vendor_flags mce_flags;
+
 extern struct mca_config mca_cfg;
 extern void mce_register_decode_chain(struct notifier_block *nb);
 extern void mce_unregister_decode_chain(struct notifier_block *nb);
@@ -128,9 +134,11 @@ extern int mce_p5_enabled;
 #ifdef CONFIG_X86_MCE
 int mcheck_init(void);
 void mcheck_cpu_init(struct cpuinfo_x86 *c);
+void mcheck_vendor_init_severity(void);
 #else
 static inline int mcheck_init(void) { return 0; }
 static inline void mcheck_cpu_init(struct cpuinfo_x86 *c) {}
+static inline void mcheck_vendor_init_severity(void) {}
 #endif
 
 #ifdef CONFIG_X86_ANCIENT_MCE
@@ -183,11 +191,11 @@ typedef DECLARE_BITMAP(mce_banks_t, MAX_NR_BANKS);
 DECLARE_PER_CPU(mce_banks_t, mce_poll_banks);
 
 enum mcp_flags {
-       MCP_TIMESTAMP = (1 << 0),       /* log time stamp */
-       MCP_UC = (1 << 1),              /* log uncorrected errors */
-       MCP_DONTLOG = (1 << 2),         /* only clear, don't log */
+       MCP_TIMESTAMP   = BIT(0),       /* log time stamp */
+       MCP_UC          = BIT(1),       /* log uncorrected errors */
+       MCP_DONTLOG     = BIT(2),       /* only clear, don't log */
 };
-void machine_check_poll(enum mcp_flags flags, mce_banks_t *b);
+bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b);
 
 int mce_notify_irq(void);
 
index 201b520521ed74b6e35b63cda531ae58f75ec674..2fb20d6f7e23b0ccace549901dacf89b51e9c381 100644 (file)
@@ -75,6 +75,79 @@ static inline void __exit exit_amd_microcode(void) {}
 
 #ifdef CONFIG_MICROCODE_EARLY
 #define MAX_UCODE_COUNT 128
+
+#define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
+#define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u')
+#define CPUID_INTEL2 QCHAR('i', 'n', 'e', 'I')
+#define CPUID_INTEL3 QCHAR('n', 't', 'e', 'l')
+#define CPUID_AMD1 QCHAR('A', 'u', 't', 'h')
+#define CPUID_AMD2 QCHAR('e', 'n', 't', 'i')
+#define CPUID_AMD3 QCHAR('c', 'A', 'M', 'D')
+
+#define CPUID_IS(a, b, c, ebx, ecx, edx)       \
+               (!((ebx ^ (a))|(edx ^ (b))|(ecx ^ (c))))
+
+/*
+ * In early loading microcode phase on BSP, boot_cpu_data is not set up yet.
+ * x86_vendor() gets vendor id for BSP.
+ *
+ * In 32 bit AP case, accessing boot_cpu_data needs linear address. To simplify
+ * coding, we still use x86_vendor() to get vendor id for AP.
+ *
+ * x86_vendor() gets vendor information directly from CPUID.
+ */
+static inline int x86_vendor(void)
+{
+       u32 eax = 0x00000000;
+       u32 ebx, ecx = 0, edx;
+
+       native_cpuid(&eax, &ebx, &ecx, &edx);
+
+       if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx))
+               return X86_VENDOR_INTEL;
+
+       if (CPUID_IS(CPUID_AMD1, CPUID_AMD2, CPUID_AMD3, ebx, ecx, edx))
+               return X86_VENDOR_AMD;
+
+       return X86_VENDOR_UNKNOWN;
+}
+
+static inline unsigned int __x86_family(unsigned int sig)
+{
+       unsigned int x86;
+
+       x86 = (sig >> 8) & 0xf;
+
+       if (x86 == 0xf)
+               x86 += (sig >> 20) & 0xff;
+
+       return x86;
+}
+
+static inline unsigned int x86_family(void)
+{
+       u32 eax = 0x00000001;
+       u32 ebx, ecx = 0, edx;
+
+       native_cpuid(&eax, &ebx, &ecx, &edx);
+
+       return __x86_family(eax);
+}
+
+static inline unsigned int x86_model(unsigned int sig)
+{
+       unsigned int x86, model;
+
+       x86 = __x86_family(sig);
+
+       model = (sig >> 4) & 0xf;
+
+       if (x86 == 0x6 || x86 == 0xf)
+               model += ((sig >> 16) & 0xf) << 4;
+
+       return model;
+}
+
 extern void __init load_ucode_bsp(void);
 extern void load_ucode_ap(void);
 extern int __init save_microcode_in_initrd(void);
index dd4c20043ce75be7545e963dd98ba38ce662396e..2b9209c46ca939991abed04a1c5d4ef786b0c698 100644 (file)
@@ -56,12 +56,15 @@ struct extended_sigtable {
 
 #define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
 
-extern int
-get_matching_microcode(unsigned int csig, int cpf, void *mc, int rev);
+extern int get_matching_microcode(unsigned int csig, int cpf, int rev, void *mc);
 extern int microcode_sanity_check(void *mc, int print_err);
-extern int get_matching_sig(unsigned int csig, int cpf, void *mc, int rev);
-extern int
-update_match_revision(struct microcode_header_intel *mc_header, int rev);
+extern int get_matching_sig(unsigned int csig, int cpf, int rev, void *mc);
+
+static inline int
+revision_is_newer(struct microcode_header_intel *mc_header, int rev)
+{
+       return (mc_header->rev <= rev) ? 0 : 1;
+}
 
 #ifdef CONFIG_MICROCODE_INTEL_EARLY
 extern void __init load_ucode_intel_bsp(void);
index a1410db38a1a682f758d44f384e2947b39203175..653dfa7662e17aa297b1277a81999854ecbea6e2 100644 (file)
@@ -30,6 +30,14 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
                     :: "a" (eax), "c" (ecx));
 }
 
+static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
+{
+       trace_hardirqs_on();
+       /* "mwait %eax, %ecx;" */
+       asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
+                    :: "a" (eax), "c" (ecx));
+}
+
 /*
  * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
  * which can obviate IPI to trigger checking of need_resched.
index f97fbe3abb67f5059d4e6f0a37261d6113df19de..c7c712f2648b001b84f06d7ef683239fd09dd2cc 100644 (file)
 
 #ifdef CONFIG_X86_64
 #include <asm/page_64_types.h>
+#define IOREMAP_MAX_ORDER       (PUD_SHIFT)
 #else
 #include <asm/page_32_types.h>
+#define IOREMAP_MAX_ORDER       (PMD_SHIFT)
 #endif /* CONFIG_X86_64 */
 
 #ifndef __ASSEMBLY__
index 965c47d254aa0f68ea83e4dc35cd983cc9ff789b..8957810ad7d1e348dd6315242c3411a863745be6 100644 (file)
@@ -545,7 +545,7 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
                PVOP_VCALL2(pv_mmu_ops.set_pmd, pmdp, val);
 }
 
-#if PAGETABLE_LEVELS >= 3
+#if CONFIG_PGTABLE_LEVELS >= 3
 static inline pmd_t __pmd(pmdval_t val)
 {
        pmdval_t ret;
@@ -585,7 +585,7 @@ static inline void set_pud(pud_t *pudp, pud_t pud)
                PVOP_VCALL2(pv_mmu_ops.set_pud, pudp,
                            val);
 }
-#if PAGETABLE_LEVELS == 4
+#if CONFIG_PGTABLE_LEVELS == 4
 static inline pud_t __pud(pudval_t val)
 {
        pudval_t ret;
@@ -636,9 +636,9 @@ static inline void pud_clear(pud_t *pudp)
        set_pud(pudp, __pud(0));
 }
 
-#endif /* PAGETABLE_LEVELS == 4 */
+#endif /* CONFIG_PGTABLE_LEVELS == 4 */
 
-#endif /* PAGETABLE_LEVELS >= 3 */
+#endif /* CONFIG_PGTABLE_LEVELS >= 3 */
 
 #ifdef CONFIG_X86_PAE
 /* Special-case pte-setting operations for PAE, which can't update a
@@ -976,11 +976,6 @@ extern void default_banner(void);
        PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret64),       \
                  CLBR_NONE,                                            \
                  jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret64))
-
-#define ENABLE_INTERRUPTS_SYSEXIT32                                    \
-       PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit),    \
-                 CLBR_NONE,                                            \
-                 jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit))
 #endif /* CONFIG_X86_32 */
 
 #endif /* __ASSEMBLY__ */
index 7549b8b369e47cf540d5dbb747b870ab42eb5b6a..f7b0b5c112f28cc89c524231e9022b4560158b48 100644 (file)
@@ -294,7 +294,7 @@ struct pv_mmu_ops {
        struct paravirt_callee_save pgd_val;
        struct paravirt_callee_save make_pgd;
 
-#if PAGETABLE_LEVELS >= 3
+#if CONFIG_PGTABLE_LEVELS >= 3
 #ifdef CONFIG_X86_PAE
        void (*set_pte_atomic)(pte_t *ptep, pte_t pteval);
        void (*pte_clear)(struct mm_struct *mm, unsigned long addr,
@@ -308,13 +308,13 @@ struct pv_mmu_ops {
        struct paravirt_callee_save pmd_val;
        struct paravirt_callee_save make_pmd;
 
-#if PAGETABLE_LEVELS == 4
+#if CONFIG_PGTABLE_LEVELS == 4
        struct paravirt_callee_save pud_val;
        struct paravirt_callee_save make_pud;
 
        void (*set_pgd)(pgd_t *pudp, pgd_t pgdval);
-#endif /* PAGETABLE_LEVELS == 4 */
-#endif /* PAGETABLE_LEVELS >= 3 */
+#endif /* CONFIG_PGTABLE_LEVELS == 4 */
+#endif /* CONFIG_PGTABLE_LEVELS >= 3 */
 
        struct pv_lazy_ops lazy_mode;
 
index c4412e972bbd4a876d969ff7b3991bd54d1e942c..bf7f8b55b0f9d8940d839b695466d32999078c10 100644 (file)
@@ -77,7 +77,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
 
 #define pmd_pgtable(pmd) pmd_page(pmd)
 
-#if PAGETABLE_LEVELS > 2
+#if CONFIG_PGTABLE_LEVELS > 2
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
        struct page *page;
@@ -116,7 +116,7 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
 }
 #endif /* CONFIG_X86_PAE */
 
-#if PAGETABLE_LEVELS > 3
+#if CONFIG_PGTABLE_LEVELS > 3
 static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
 {
        paravirt_alloc_pud(mm, __pa(pud) >> PAGE_SHIFT);
@@ -142,7 +142,7 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
        ___pud_free_tlb(tlb, pud);
 }
 
-#endif /* PAGETABLE_LEVELS > 3 */
-#endif /* PAGETABLE_LEVELS > 2 */
+#endif /* CONFIG_PGTABLE_LEVELS > 3 */
+#endif /* CONFIG_PGTABLE_LEVELS > 2 */
 
 #endif /* _ASM_X86_PGALLOC_H */
index daacc23e3fb95170173c5afd6f49ebbce5b2d5c3..392576433e7785769493032934bb44900304dd2e 100644 (file)
@@ -17,7 +17,6 @@ typedef union {
 #endif /* !__ASSEMBLY__ */
 
 #define SHARED_KERNEL_PMD      0
-#define PAGETABLE_LEVELS       2
 
 /*
  * traditional i386 two-level paging structure:
index 1bd5876c864949f4fd1ac3a9cd100ac64893f3ba..bcc89625ebe530964c5b23a13b212711651d2296 100644 (file)
@@ -24,8 +24,6 @@ typedef union {
 #define SHARED_KERNEL_PMD      1
 #endif
 
-#define PAGETABLE_LEVELS       3
-
 /*
  * PGDIR_SHIFT determines what a top-level page table entry can map
  */
index a0c35bf6cb92cf95abe8fc9ffe9f75c4f34b1fca..fe57e7a98839801ce76a6a33c0f3a7552e5d292a 100644 (file)
@@ -551,7 +551,7 @@ static inline unsigned long pages_to_mb(unsigned long npg)
        return npg >> (20 - PAGE_SHIFT);
 }
 
-#if PAGETABLE_LEVELS > 2
+#if CONFIG_PGTABLE_LEVELS > 2
 static inline int pud_none(pud_t pud)
 {
        return native_pud_val(pud) == 0;
@@ -594,9 +594,9 @@ static inline int pud_large(pud_t pud)
 {
        return 0;
 }
-#endif /* PAGETABLE_LEVELS > 2 */
+#endif /* CONFIG_PGTABLE_LEVELS > 2 */
 
-#if PAGETABLE_LEVELS > 3
+#if CONFIG_PGTABLE_LEVELS > 3
 static inline int pgd_present(pgd_t pgd)
 {
        return pgd_flags(pgd) & _PAGE_PRESENT;
@@ -633,7 +633,7 @@ static inline int pgd_none(pgd_t pgd)
 {
        return !native_pgd_val(pgd);
 }
-#endif /* PAGETABLE_LEVELS > 3 */
+#endif /* CONFIG_PGTABLE_LEVELS > 3 */
 
 #endif /* __ASSEMBLY__ */
 
index 602b6028c5b6e30c96d57031b85ec2f04793abd0..e6844dfb4471d643a88fa2ba7bb88f28a27bb5a2 100644 (file)
@@ -20,7 +20,6 @@ typedef struct { pteval_t pte; } pte_t;
 #endif /* !__ASSEMBLY__ */
 
 #define SHARED_KERNEL_PMD      0
-#define PAGETABLE_LEVELS       4
 
 /*
  * PGDIR_SHIFT determines what a top-level page table entry can map
index 8c7c10802e9c68706c9b91f2c5223c968920486b..78f0c8cbe316f9114746877420cfc400604bd486 100644 (file)
@@ -234,7 +234,7 @@ static inline pgdval_t pgd_flags(pgd_t pgd)
        return native_pgd_val(pgd) & PTE_FLAGS_MASK;
 }
 
-#if PAGETABLE_LEVELS > 3
+#if CONFIG_PGTABLE_LEVELS > 3
 typedef struct { pudval_t pud; } pud_t;
 
 static inline pud_t native_make_pud(pmdval_t val)
@@ -255,7 +255,7 @@ static inline pudval_t native_pud_val(pud_t pud)
 }
 #endif
 
-#if PAGETABLE_LEVELS > 2
+#if CONFIG_PGTABLE_LEVELS > 2
 typedef struct { pmdval_t pmd; } pmd_t;
 
 static inline pmd_t native_make_pmd(pmdval_t val)
index ec1c93588cefd0c4e3a4705c6d966e2555ba95aa..23ba6765b718c790dbf698edbb2758a2ca6f9102 100644 (file)
@@ -109,6 +109,9 @@ struct cpuinfo_x86 {
        /* in KB - valid for CPUS which support this call: */
        int                     x86_cache_size;
        int                     x86_cache_alignment;    /* In bytes */
+       /* Cache QoS architectural values: */
+       int                     x86_cache_max_rmid;     /* max index */
+       int                     x86_cache_occ_scale;    /* scale to bytes */
        int                     x86_power;
        unsigned long           loops_per_jiffy;
        /* cpuid returned max cores value: */
@@ -210,8 +213,23 @@ struct x86_hw_tss {
        unsigned long           sp0;
        unsigned short          ss0, __ss0h;
        unsigned long           sp1;
-       /* ss1 caches MSR_IA32_SYSENTER_CS: */
-       unsigned short          ss1, __ss1h;
+
+       /*
+        * We don't use ring 1, so ss1 is a convenient scratch space in
+        * the same cacheline as sp0.  We use ss1 to cache the value in
+        * MSR_IA32_SYSENTER_CS.  When we context switch
+        * MSR_IA32_SYSENTER_CS, we first check if the new value being
+        * written matches ss1, and, if it's not, then we wrmsr the new
+        * value and update ss1.
+        *
+        * The only reason we context switch MSR_IA32_SYSENTER_CS is
+        * that we set it to zero in vm86 tasks to avoid corrupting the
+        * stack if we were to go through the sysenter path from vm86
+        * mode.
+        */
+       unsigned short          ss1;    /* MSR_IA32_SYSENTER_CS */
+
+       unsigned short          __ss1h;
        unsigned long           sp2;
        unsigned short          ss2, __ss2h;
        unsigned long           __cr3;
@@ -276,13 +294,17 @@ struct tss_struct {
        unsigned long           io_bitmap[IO_BITMAP_LONGS + 1];
 
        /*
-        * .. and then another 0x100 bytes for the emergency kernel stack:
+        * Space for the temporary SYSENTER stack:
         */
-       unsigned long           stack[64];
+       unsigned long           SYSENTER_stack[64];
 
 } ____cacheline_aligned;
 
-DECLARE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss);
+DECLARE_PER_CPU_SHARED_ALIGNED(struct tss_struct, cpu_tss);
+
+#ifdef CONFIG_X86_32
+DECLARE_PER_CPU(unsigned long, cpu_current_top_of_stack);
+#endif
 
 /*
  * Save the original ist values for checking stack pointers during debugging
@@ -474,7 +496,6 @@ struct thread_struct {
 #ifdef CONFIG_X86_32
        unsigned long           sysenter_cs;
 #else
-       unsigned long           usersp; /* Copy from PDA */
        unsigned short          es;
        unsigned short          ds;
        unsigned short          fsindex;
@@ -564,6 +585,16 @@ static inline void native_swapgs(void)
 #endif
 }
 
+static inline unsigned long current_top_of_stack(void)
+{
+#ifdef CONFIG_X86_64
+       return this_cpu_read_stable(cpu_tss.x86_tss.sp0);
+#else
+       /* sp0 on x86_32 is special in and around vm86 mode. */
+       return this_cpu_read_stable(cpu_current_top_of_stack);
+#endif
+}
+
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #else
@@ -761,10 +792,10 @@ extern char                       ignore_fpu_irq;
 #define ARCH_HAS_SPINLOCK_PREFETCH
 
 #ifdef CONFIG_X86_32
-# define BASE_PREFETCH         ASM_NOP4
+# define BASE_PREFETCH         ""
 # define ARCH_HAS_PREFETCH
 #else
-# define BASE_PREFETCH         "prefetcht0 (%1)"
+# define BASE_PREFETCH         "prefetcht0 %P1"
 #endif
 
 /*
@@ -775,10 +806,9 @@ extern char                        ignore_fpu_irq;
  */
 static inline void prefetch(const void *x)
 {
-       alternative_input(BASE_PREFETCH,
-                         "prefetchnta (%1)",
+       alternative_input(BASE_PREFETCH, "prefetchnta %P1",
                          X86_FEATURE_XMM,
-                         "r" (x));
+                         "m" (*(const char *)x));
 }
 
 /*
@@ -788,10 +818,9 @@ static inline void prefetch(const void *x)
  */
 static inline void prefetchw(const void *x)
 {
-       alternative_input(BASE_PREFETCH,
-                         "prefetchw (%1)",
-                         X86_FEATURE_3DNOW,
-                         "r" (x));
+       alternative_input(BASE_PREFETCH, "prefetchw %P1",
+                         X86_FEATURE_3DNOWPREFETCH,
+                         "m" (*(const char *)x));
 }
 
 static inline void spin_lock_prefetch(const void *x)
@@ -799,6 +828,9 @@ static inline void spin_lock_prefetch(const void *x)
        prefetchw(x);
 }
 
+#define TOP_OF_INIT_STACK ((unsigned long)&init_stack + sizeof(init_stack) - \
+                          TOP_OF_KERNEL_STACK_PADDING)
+
 #ifdef CONFIG_X86_32
 /*
  * User space process size: 3GB (default).
@@ -809,39 +841,16 @@ static inline void spin_lock_prefetch(const void *x)
 #define STACK_TOP_MAX          STACK_TOP
 
 #define INIT_THREAD  {                                                   \
-       .sp0                    = sizeof(init_stack) + (long)&init_stack, \
+       .sp0                    = TOP_OF_INIT_STACK,                      \
        .vm86_info              = NULL,                                   \
        .sysenter_cs            = __KERNEL_CS,                            \
        .io_bitmap_ptr          = NULL,                                   \
 }
 
-/*
- * Note that the .io_bitmap member must be extra-big. This is because
- * the CPU will access an additional byte beyond the end of the IO
- * permission bitmap. The extra byte must be all 1 bits, and must
- * be within the limit.
- */
-#define INIT_TSS  {                                                      \
-       .x86_tss = {                                                      \
-               .sp0            = sizeof(init_stack) + (long)&init_stack, \
-               .ss0            = __KERNEL_DS,                            \
-               .ss1            = __KERNEL_CS,                            \
-               .io_bitmap_base = INVALID_IO_BITMAP_OFFSET,               \
-        },                                                               \
-       .io_bitmap              = { [0 ... IO_BITMAP_LONGS] = ~0 },       \
-}
-
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
 
-#define THREAD_SIZE_LONGS      (THREAD_SIZE/sizeof(unsigned long))
-#define KSTK_TOP(info)                                                 \
-({                                                                     \
-       unsigned long *__ptr = (unsigned long *)(info);                 \
-       (unsigned long)(&__ptr[THREAD_SIZE_LONGS]);                     \
-})
-
 /*
- * The below -8 is to reserve 8 bytes on top of the ring0 stack.
+ * TOP_OF_KERNEL_STACK_PADDING reserves 8 bytes on top of the ring0 stack.
  * This is necessary to guarantee that the entire "struct pt_regs"
  * is accessible even if the CPU haven't stored the SS/ESP registers
  * on the stack (interrupt gate does not save these registers
@@ -850,11 +859,11 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
  * "struct pt_regs" is possible, but they may contain the
  * completely wrong values.
  */
-#define task_pt_regs(task)                                             \
-({                                                                     \
-       struct pt_regs *__regs__;                                       \
-       __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
-       __regs__ - 1;                                                   \
+#define task_pt_regs(task) \
+({                                                                     \
+       unsigned long __ptr = (unsigned long)task_stack_page(task);     \
+       __ptr += THREAD_SIZE - TOP_OF_KERNEL_STACK_PADDING;             \
+       ((struct pt_regs *)__ptr) - 1;                                  \
 })
 
 #define KSTK_ESP(task)         (task_pt_regs(task)->sp)
@@ -886,11 +895,7 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
 #define STACK_TOP_MAX          TASK_SIZE_MAX
 
 #define INIT_THREAD  { \
-       .sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
-}
-
-#define INIT_TSS  { \
-       .x86_tss.sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+       .sp0 = TOP_OF_INIT_STACK \
 }
 
 /*
@@ -902,11 +907,6 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
 #define task_pt_regs(tsk)      ((struct pt_regs *)(tsk)->thread.sp0 - 1)
 extern unsigned long KSTK_ESP(struct task_struct *task);
 
-/*
- * User space RSP while inside the SYSCALL fast path
- */
-DECLARE_PER_CPU(unsigned long, old_rsp);
-
 #endif /* CONFIG_X86_64 */
 
 extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
index 86fc2bb82287a687bd8ca0e976e8d32761678480..19507ffa5d28e9ce3ddece3856dd9cde4446f7f8 100644 (file)
@@ -31,13 +31,17 @@ struct pt_regs {
 #else /* __i386__ */
 
 struct pt_regs {
+/*
+ * C ABI says these regs are callee-preserved. They aren't saved on kernel entry
+ * unless syscall needs a complete, fully filled "struct pt_regs".
+ */
        unsigned long r15;
        unsigned long r14;
        unsigned long r13;
        unsigned long r12;
        unsigned long bp;
        unsigned long bx;
-/* arguments: non interrupts/non tracing syscalls only save up to here*/
+/* These regs are callee-clobbered. Always saved on kernel entry. */
        unsigned long r11;
        unsigned long r10;
        unsigned long r9;
@@ -47,9 +51,12 @@ struct pt_regs {
        unsigned long dx;
        unsigned long si;
        unsigned long di;
+/*
+ * On syscall entry, this is syscall#. On CPU exception, this is error code.
+ * On hw interrupt, it's IRQ number:
+ */
        unsigned long orig_ax;
-/* end of arguments */
-/* cpu exception frame or undefined */
+/* Return frame for iretq */
        unsigned long ip;
        unsigned long cs;
        unsigned long flags;
@@ -89,11 +96,13 @@ static inline unsigned long regs_return_value(struct pt_regs *regs)
 }
 
 /*
- * user_mode_vm(regs) determines whether a register set came from user mode.
- * This is true if V8086 mode was enabled OR if the register set was from
- * protected mode with RPL-3 CS value.  This tricky test checks that with
- * one comparison.  Many places in the kernel can bypass this full check
- * if they have already ruled out V8086 mode, so user_mode(regs) can be used.
+ * user_mode(regs) determines whether a register set came from user
+ * mode.  On x86_32, this is true if V8086 mode was enabled OR if the
+ * register set was from protected mode with RPL-3 CS value.  This
+ * tricky test checks that with one comparison.
+ *
+ * On x86_64, vm86 mode is mercifully nonexistent, and we don't need
+ * the extra check.
  */
 static inline int user_mode(struct pt_regs *regs)
 {
@@ -104,16 +113,6 @@ static inline int user_mode(struct pt_regs *regs)
 #endif
 }
 
-static inline int user_mode_vm(struct pt_regs *regs)
-{
-#ifdef CONFIG_X86_32
-       return ((regs->cs & SEGMENT_RPL_MASK) | (regs->flags & X86_VM_MASK)) >=
-               USER_RPL;
-#else
-       return user_mode(regs);
-#endif
-}
-
 static inline int v8086_mode(struct pt_regs *regs)
 {
 #ifdef CONFIG_X86_32
@@ -138,12 +137,8 @@ static inline bool user_64bit_mode(struct pt_regs *regs)
 #endif
 }
 
-#define current_user_stack_pointer()   this_cpu_read(old_rsp)
-/* ia32 vs. x32 difference */
-#define compat_user_stack_pointer()    \
-       (test_thread_flag(TIF_IA32)     \
-        ? current_pt_regs()->sp        \
-        : this_cpu_read(old_rsp))
+#define current_user_stack_pointer()   current_pt_regs()->sp
+#define compat_user_stack_pointer()    current_pt_regs()->sp
 #endif
 
 #ifdef CONFIG_X86_32
@@ -248,7 +243,7 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
  */
 #define arch_ptrace_stop_needed(code, info)                            \
 ({                                                                     \
-       set_thread_flag(TIF_NOTIFY_RESUME);                             \
+       force_iret();                                                   \
        false;                                                          \
 })
 
index d6b078e9fa28a3f4588237cb9a122f5b5ce53162..25b1cc07d49668c8a40306bf2ec81e4e2a11988e 100644 (file)
@@ -95,6 +95,7 @@ unsigned __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src,
 
 struct pvclock_vsyscall_time_info {
        struct pvclock_vcpu_time_info pvti;
+       u32 migrate_count;
 } __attribute__((__aligned__(SMP_CACHE_BYTES)));
 
 #define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info)
index db257a58571f0b47429e2dcc70cf628f1a968fe4..5a9856eb12bad7edb0f9a333870e331f5677d588 100644 (file)
@@ -3,8 +3,10 @@
 
 #include <linux/const.h>
 
-/* Constructor for a conventional segment GDT (or LDT) entry */
-/* This is a macro so it can be used in initializers */
+/*
+ * Constructor for a conventional segment GDT (or LDT) entry.
+ * This is a macro so it can be used in initializers.
+ */
 #define GDT_ENTRY(flags, base, limit)                  \
        ((((base)  & _AC(0xff000000,ULL)) << (56-24)) | \
         (((flags) & _AC(0x0000f0ff,ULL)) << 40) |      \
         (((base)  & _AC(0x00ffffff,ULL)) << 16) |      \
         (((limit) & _AC(0x0000ffff,ULL))))
 
-/* Simple and small GDT entries for booting only */
+/* Simple and small GDT entries for booting only: */
 
 #define GDT_ENTRY_BOOT_CS      2
-#define __BOOT_CS              (GDT_ENTRY_BOOT_CS * 8)
+#define GDT_ENTRY_BOOT_DS      3
+#define GDT_ENTRY_BOOT_TSS     4
+#define __BOOT_CS              (GDT_ENTRY_BOOT_CS*8)
+#define __BOOT_DS              (GDT_ENTRY_BOOT_DS*8)
+#define __BOOT_TSS             (GDT_ENTRY_BOOT_TSS*8)
+
+/*
+ * Bottom two bits of selector give the ring
+ * privilege level
+ */
+#define SEGMENT_RPL_MASK       0x3
 
-#define GDT_ENTRY_BOOT_DS      (GDT_ENTRY_BOOT_CS + 1)
-#define __BOOT_DS              (GDT_ENTRY_BOOT_DS * 8)
+/* User mode is privilege level 3: */
+#define USER_RPL               0x3
 
-#define GDT_ENTRY_BOOT_TSS     (GDT_ENTRY_BOOT_CS + 2)
-#define __BOOT_TSS             (GDT_ENTRY_BOOT_TSS * 8)
+/* Bit 2 is Table Indicator (TI): selects between LDT or GDT */
+#define SEGMENT_TI_MASK                0x4
+/* LDT segment has TI set ... */
+#define SEGMENT_LDT            0x4
+/* ... GDT has it cleared */
+#define SEGMENT_GDT            0x0
 
-#define SEGMENT_RPL_MASK       0x3 /*
-                                    * Bottom two bits of selector give the ring
-                                    * privilege level
-                                    */
-#define SEGMENT_TI_MASK                0x4 /* Bit 2 is table indicator (LDT/GDT) */
-#define USER_RPL               0x3 /* User mode is privilege level 3 */
-#define SEGMENT_LDT            0x4 /* LDT segment has TI set... */
-#define SEGMENT_GDT            0x0 /* ... GDT has it cleared */
+#define GDT_ENTRY_INVALID_SEG  0
 
 #ifdef CONFIG_X86_32
 /*
  * The layout of the per-CPU GDT under Linux:
  *
- *   0 - null
+ *   0 - null                                                          <=== cacheline #1
  *   1 - reserved
  *   2 - reserved
  *   3 - reserved
  *
- *   4 - unused                        <==== new cacheline
+ *   4 - unused                                                                <=== cacheline #2
  *   5 - unused
  *
  *  ------- start of TLS (Thread-Local Storage) segments:
  *
  *   6 - TLS segment #1                        [ glibc's TLS segment ]
  *   7 - TLS segment #2                        [ Wine's %fs Win32 segment ]
- *   8 - TLS segment #3
+ *   8 - TLS segment #3                                                        <=== cacheline #3
  *   9 - reserved
  *  10 - reserved
  *  11 - reserved
  *
  *  ------- start of kernel segments:
  *
- *  12 - kernel code segment           <==== new cacheline
+ *  12 - kernel code segment                                           <=== cacheline #4
  *  13 - kernel data segment
  *  14 - default user CS
  *  15 - default user DS
- *  16 - TSS
+ *  16 - TSS                                                           <=== cacheline #5
  *  17 - LDT
  *  18 - PNPBIOS support (16->32 gate)
  *  19 - PNPBIOS support
- *  20 - PNPBIOS support
+ *  20 - PNPBIOS support                                               <=== cacheline #6
  *  21 - PNPBIOS support
  *  22 - PNPBIOS support
  *  23 - APM BIOS support
- *  24 - APM BIOS support
+ *  24 - APM BIOS support                                              <=== cacheline #7
  *  25 - APM BIOS support
  *
  *  26 - ESPFIX small SS
  *  27 - per-cpu                       [ offset to per-cpu data area ]
- *  28 - stack_canary-20               [ for stack protector ]
+ *  28 - stack_canary-20               [ for stack protector ]         <=== cacheline #8
  *  29 - unused
  *  30 - unused
  *  31 - TSS for double fault handler
  */
-#define GDT_ENTRY_TLS_MIN      6
-#define GDT_ENTRY_TLS_MAX      (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
+#define GDT_ENTRY_TLS_MIN              6
+#define GDT_ENTRY_TLS_MAX              (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
 
+#define GDT_ENTRY_KERNEL_CS            12
+#define GDT_ENTRY_KERNEL_DS            13
 #define GDT_ENTRY_DEFAULT_USER_CS      14
-
 #define GDT_ENTRY_DEFAULT_USER_DS      15
+#define GDT_ENTRY_TSS                  16
+#define GDT_ENTRY_LDT                  17
+#define GDT_ENTRY_PNPBIOS_CS32         18
+#define GDT_ENTRY_PNPBIOS_CS16         19
+#define GDT_ENTRY_PNPBIOS_DS           20
+#define GDT_ENTRY_PNPBIOS_TS1          21
+#define GDT_ENTRY_PNPBIOS_TS2          22
+#define GDT_ENTRY_APMBIOS_BASE         23
+
+#define GDT_ENTRY_ESPFIX_SS            26
+#define GDT_ENTRY_PERCPU               27
+#define GDT_ENTRY_STACK_CANARY         28
+
+#define GDT_ENTRY_DOUBLEFAULT_TSS      31
 
-#define GDT_ENTRY_KERNEL_BASE          (12)
+/*
+ * Number of entries in the GDT table:
+ */
+#define GDT_ENTRIES                    32
 
-#define GDT_ENTRY_KERNEL_CS            (GDT_ENTRY_KERNEL_BASE+0)
+/*
+ * Segment selector values corresponding to the above entries:
+ */
 
-#define GDT_ENTRY_KERNEL_DS            (GDT_ENTRY_KERNEL_BASE+1)
+#define __KERNEL_CS                    (GDT_ENTRY_KERNEL_CS*8)
+#define __KERNEL_DS                    (GDT_ENTRY_KERNEL_DS*8)
+#define __USER_DS                      (GDT_ENTRY_DEFAULT_USER_DS*8 + 3)
+#define __USER_CS                      (GDT_ENTRY_DEFAULT_USER_CS*8 + 3)
+#define __ESPFIX_SS                    (GDT_ENTRY_ESPFIX_SS*8)
 
-#define GDT_ENTRY_TSS                  (GDT_ENTRY_KERNEL_BASE+4)
-#define GDT_ENTRY_LDT                  (GDT_ENTRY_KERNEL_BASE+5)
+/* segment for calling fn: */
+#define PNP_CS32                       (GDT_ENTRY_PNPBIOS_CS32*8)
+/* code segment for BIOS: */
+#define PNP_CS16                       (GDT_ENTRY_PNPBIOS_CS16*8)
 
-#define GDT_ENTRY_PNPBIOS_BASE         (GDT_ENTRY_KERNEL_BASE+6)
-#define GDT_ENTRY_APMBIOS_BASE         (GDT_ENTRY_KERNEL_BASE+11)
+/* "Is this PNP code selector (PNP_CS32 or PNP_CS16)?" */
+#define SEGMENT_IS_PNP_CODE(x)         (((x) & 0xf4) == PNP_CS32)
 
-#define GDT_ENTRY_ESPFIX_SS            (GDT_ENTRY_KERNEL_BASE+14)
-#define __ESPFIX_SS                    (GDT_ENTRY_ESPFIX_SS*8)
+/* data segment for BIOS: */
+#define PNP_DS                         (GDT_ENTRY_PNPBIOS_DS*8)
+/* transfer data segment: */
+#define PNP_TS1                                (GDT_ENTRY_PNPBIOS_TS1*8)
+/* another data segment: */
+#define PNP_TS2                                (GDT_ENTRY_PNPBIOS_TS2*8)
 
-#define GDT_ENTRY_PERCPU               (GDT_ENTRY_KERNEL_BASE+15)
 #ifdef CONFIG_SMP
-#define __KERNEL_PERCPU (GDT_ENTRY_PERCPU * 8)
+# define __KERNEL_PERCPU               (GDT_ENTRY_PERCPU*8)
 #else
-#define __KERNEL_PERCPU 0
+# define __KERNEL_PERCPU               0
 #endif
 
-#define GDT_ENTRY_STACK_CANARY         (GDT_ENTRY_KERNEL_BASE+16)
 #ifdef CONFIG_CC_STACKPROTECTOR
-#define __KERNEL_STACK_CANARY          (GDT_ENTRY_STACK_CANARY*8)
+# define __KERNEL_STACK_CANARY         (GDT_ENTRY_STACK_CANARY*8)
 #else
-#define __KERNEL_STACK_CANARY          0
+# define __KERNEL_STACK_CANARY         0
 #endif
 
-#define GDT_ENTRY_DOUBLEFAULT_TSS      31
-
-/*
- * The GDT has 32 entries
- */
-#define GDT_ENTRIES 32
+#else /* 64-bit: */
 
-/* The PnP BIOS entries in the GDT */
-#define GDT_ENTRY_PNPBIOS_CS32         (GDT_ENTRY_PNPBIOS_BASE + 0)
-#define GDT_ENTRY_PNPBIOS_CS16         (GDT_ENTRY_PNPBIOS_BASE + 1)
-#define GDT_ENTRY_PNPBIOS_DS           (GDT_ENTRY_PNPBIOS_BASE + 2)
-#define GDT_ENTRY_PNPBIOS_TS1          (GDT_ENTRY_PNPBIOS_BASE + 3)
-#define GDT_ENTRY_PNPBIOS_TS2          (GDT_ENTRY_PNPBIOS_BASE + 4)
-
-/* The PnP BIOS selectors */
-#define PNP_CS32   (GDT_ENTRY_PNPBIOS_CS32 * 8)        /* segment for calling fn */
-#define PNP_CS16   (GDT_ENTRY_PNPBIOS_CS16 * 8)        /* code segment for BIOS */
-#define PNP_DS     (GDT_ENTRY_PNPBIOS_DS * 8)  /* data segment for BIOS */
-#define PNP_TS1    (GDT_ENTRY_PNPBIOS_TS1 * 8) /* transfer data segment */
-#define PNP_TS2    (GDT_ENTRY_PNPBIOS_TS2 * 8) /* another data segment */
+#include <asm/cache.h>
 
+#define GDT_ENTRY_KERNEL32_CS          1
+#define GDT_ENTRY_KERNEL_CS            2
+#define GDT_ENTRY_KERNEL_DS            3
 
 /*
- * Matching rules for certain types of segments.
+ * We cannot use the same code segment descriptor for user and kernel mode,
+ * not even in long flat mode, because of different DPL.
+ *
+ * GDT layout to get 64-bit SYSCALL/SYSRET support right. SYSRET hardcodes
+ * selectors:
+ *
+ *   if returning to 32-bit userspace: cs = STAR.SYSRET_CS,
+ *   if returning to 64-bit userspace: cs = STAR.SYSRET_CS+16,
+ *
+ * ss = STAR.SYSRET_CS+8 (in either case)
+ *
+ * thus USER_DS should be between 32-bit and 64-bit code selectors:
  */
+#define GDT_ENTRY_DEFAULT_USER32_CS    4
+#define GDT_ENTRY_DEFAULT_USER_DS      5
+#define GDT_ENTRY_DEFAULT_USER_CS      6
 
-/* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */
-#define SEGMENT_IS_PNP_CODE(x)   (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8)
-
+/* Needs two entries */
+#define GDT_ENTRY_TSS                  8
+/* Needs two entries */
+#define GDT_ENTRY_LDT                  10
 
-#else
-#include <asm/cache.h>
-
-#define GDT_ENTRY_KERNEL32_CS 1
-#define GDT_ENTRY_KERNEL_CS 2
-#define GDT_ENTRY_KERNEL_DS 3
+#define GDT_ENTRY_TLS_MIN              12
+#define GDT_ENTRY_TLS_MAX              14
 
-#define __KERNEL32_CS   (GDT_ENTRY_KERNEL32_CS * 8)
+/* Abused to load per CPU data from limit */
+#define GDT_ENTRY_PER_CPU              15
 
 /*
- * we cannot use the same code segment descriptor for user and kernel
- * -- not even in the long flat mode, because of different DPL /kkeil
- * The segment offset needs to contain a RPL. Grr. -AK
- * GDT layout to get 64bit syscall right (sysret hardcodes gdt offsets)
+ * Number of entries in the GDT table:
  */
-#define GDT_ENTRY_DEFAULT_USER32_CS 4
-#define GDT_ENTRY_DEFAULT_USER_DS 5
-#define GDT_ENTRY_DEFAULT_USER_CS 6
-#define __USER32_CS   (GDT_ENTRY_DEFAULT_USER32_CS*8+3)
-#define __USER32_DS    __USER_DS
-
-#define GDT_ENTRY_TSS 8        /* needs two entries */
-#define GDT_ENTRY_LDT 10 /* needs two entries */
-#define GDT_ENTRY_TLS_MIN 12
-#define GDT_ENTRY_TLS_MAX 14
-
-#define GDT_ENTRY_PER_CPU 15   /* Abused to load per CPU data from limit */
-#define __PER_CPU_SEG  (GDT_ENTRY_PER_CPU * 8 + 3)
+#define GDT_ENTRIES                    16
 
-/* TLS indexes for 64bit - hardcoded in arch_prctl */
-#define FS_TLS 0
-#define GS_TLS 1
-
-#define GS_TLS_SEL ((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3)
-#define FS_TLS_SEL ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3)
-
-#define GDT_ENTRIES 16
+/*
+ * Segment selector values corresponding to the above entries:
+ *
+ * Note, selectors also need to have a correct RPL,
+ * expressed with the +3 value for user-space selectors:
+ */
+#define __KERNEL32_CS                  (GDT_ENTRY_KERNEL32_CS*8)
+#define __KERNEL_CS                    (GDT_ENTRY_KERNEL_CS*8)
+#define __KERNEL_DS                    (GDT_ENTRY_KERNEL_DS*8)
+#define __USER32_CS                    (GDT_ENTRY_DEFAULT_USER32_CS*8 + 3)
+#define __USER_DS                      (GDT_ENTRY_DEFAULT_USER_DS*8 + 3)
+#define __USER32_DS                    __USER_DS
+#define __USER_CS                      (GDT_ENTRY_DEFAULT_USER_CS*8 + 3)
+#define __PER_CPU_SEG                  (GDT_ENTRY_PER_CPU*8 + 3)
+
+/* TLS indexes for 64-bit - hardcoded in arch_prctl(): */
+#define FS_TLS                         0
+#define GS_TLS                         1
+
+#define GS_TLS_SEL                     ((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3)
+#define FS_TLS_SEL                     ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3)
 
 #endif
 
-#define __KERNEL_CS    (GDT_ENTRY_KERNEL_CS*8)
-#define __KERNEL_DS    (GDT_ENTRY_KERNEL_DS*8)
-#define __USER_DS      (GDT_ENTRY_DEFAULT_USER_DS*8+3)
-#define __USER_CS      (GDT_ENTRY_DEFAULT_USER_CS*8+3)
 #ifndef CONFIG_PARAVIRT
-#define get_kernel_rpl()  0
+# define get_kernel_rpl()              0
 #endif
 
-#define IDT_ENTRIES 256
-#define NUM_EXCEPTION_VECTORS 32
-/* Bitmask of exception vectors which push an error code on the stack */
-#define EXCEPTION_ERRCODE_MASK  0x00027d00
-#define GDT_SIZE (GDT_ENTRIES * 8)
-#define GDT_ENTRY_TLS_ENTRIES 3
-#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
+#define IDT_ENTRIES                    256
+#define NUM_EXCEPTION_VECTORS          32
+
+/* Bitmask of exception vectors which push an error code on the stack: */
+#define EXCEPTION_ERRCODE_MASK         0x00027d00
+
+#define GDT_SIZE                       (GDT_ENTRIES*8)
+#define GDT_ENTRY_TLS_ENTRIES          3
+#define TLS_SIZE                       (GDT_ENTRY_TLS_ENTRIES* 8)
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
+
 extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5];
 #ifdef CONFIG_TRACING
-#define trace_early_idt_handlers early_idt_handlers
+# define trace_early_idt_handlers early_idt_handlers
 #endif
 
 /*
@@ -228,37 +260,30 @@ do {                                                                      \
 } while (0)
 
 /*
- * Save a segment register away
+ * Save a segment register away:
  */
 #define savesegment(seg, value)                                \
        asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
 
 /*
- * x86_32 user gs accessors.
+ * x86-32 user GS accessors:
  */
 #ifdef CONFIG_X86_32
-#ifdef CONFIG_X86_32_LAZY_GS
-#define get_user_gs(regs)      (u16)({unsigned long v; savesegment(gs, v); v;})
-#define set_user_gs(regs, v)   loadsegment(gs, (unsigned long)(v))
-#define task_user_gs(tsk)      ((tsk)->thread.gs)
-#define lazy_save_gs(v)                savesegment(gs, (v))
-#define lazy_load_gs(v)                loadsegment(gs, (v))
-#else  /* X86_32_LAZY_GS */
-#define get_user_gs(regs)      (u16)((regs)->gs)
-#define set_user_gs(regs, v)   do { (regs)->gs = (v); } while (0)
-#define task_user_gs(tsk)      (task_pt_regs(tsk)->gs)
-#define lazy_save_gs(v)                do { } while (0)
-#define lazy_load_gs(v)                do { } while (0)
-#endif /* X86_32_LAZY_GS */
+# ifdef CONFIG_X86_32_LAZY_GS
+#  define get_user_gs(regs)            (u16)({ unsigned long v; savesegment(gs, v); v; })
+#  define set_user_gs(regs, v)         loadsegment(gs, (unsigned long)(v))
+#  define task_user_gs(tsk)            ((tsk)->thread.gs)
+#  define lazy_save_gs(v)              savesegment(gs, (v))
+#  define lazy_load_gs(v)              loadsegment(gs, (v))
+# else /* X86_32_LAZY_GS */
+#  define get_user_gs(regs)            (u16)((regs)->gs)
+#  define set_user_gs(regs, v)         do { (regs)->gs = (v); } while (0)
+#  define task_user_gs(tsk)            (task_pt_regs(tsk)->gs)
+#  define lazy_save_gs(v)              do { } while (0)
+#  define lazy_load_gs(v)              do { } while (0)
+# endif        /* X86_32_LAZY_GS */
 #endif /* X86_32 */
 
-static inline unsigned long get_limit(unsigned long segment)
-{
-       unsigned long __limit;
-       asm("lsll %1,%0" : "=r" (__limit) : "r" (segment));
-       return __limit + 1;
-}
-
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 
index ff4e7b236e21d5393bd55c5f53493d44861c70c1..f69e06b283fb9ee03e8704847558aa577aecf221 100644 (file)
@@ -66,6 +66,11 @@ static inline void x86_ce4100_early_setup(void) { }
  */
 extern struct boot_params boot_params;
 
+static inline bool kaslr_enabled(void)
+{
+       return !!(boot_params.hdr.loadflags & KASLR_FLAG);
+}
+
 /*
  * Do NOT EVER look at the BIOS memory size location.
  * It does not work on many machines.
index 9dfce4e0417d92adc623d32ff93f67109316b451..6fe6b182c9981dd891a9a5bc9a55b3e6591a6f9f 100644 (file)
@@ -57,9 +57,9 @@ struct sigcontext {
        unsigned long ip;
        unsigned long flags;
        unsigned short cs;
-       unsigned short gs;
-       unsigned short fs;
-       unsigned short __pad0;
+       unsigned short __pad2;  /* Was called gs, but was always zero. */
+       unsigned short __pad1;  /* Was called fs, but was always zero. */
+       unsigned short ss;
        unsigned long err;
        unsigned long trapno;
        unsigned long oldmask;
index 7a958164088c10a61aeed98f6353152ebad83ff5..89db46752a8f0e1c78c9403ef4b40a805b488999 100644 (file)
@@ -13,9 +13,7 @@
                         X86_EFLAGS_CF | X86_EFLAGS_RF)
 
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
-
-int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
-                      unsigned long *pax);
+int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc);
 int setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
                     struct pt_regs *regs, unsigned long mask);
 
index 8d3120f4e27053b3fae6d6334fe7a3a6dee33e82..ba665ebd17bb8f22a39712dbf2a8c398b9e9207f 100644 (file)
 
 #ifdef CONFIG_X86_SMAP
 
-#define ASM_CLAC                                                       \
-       661: ASM_NOP3 ;                                                 \
-       .pushsection .altinstr_replacement, "ax" ;                      \
-       662: __ASM_CLAC ;                                               \
-       .popsection ;                                                   \
-       .pushsection .altinstructions, "a" ;                            \
-       altinstruction_entry 661b, 662b, X86_FEATURE_SMAP, 3, 3 ;       \
-       .popsection
-
-#define ASM_STAC                                                       \
-       661: ASM_NOP3 ;                                                 \
-       .pushsection .altinstr_replacement, "ax" ;                      \
-       662: __ASM_STAC ;                                               \
-       .popsection ;                                                   \
-       .pushsection .altinstructions, "a" ;                            \
-       altinstruction_entry 661b, 662b, X86_FEATURE_SMAP, 3, 3 ;       \
-       .popsection
+#define ASM_CLAC \
+       ALTERNATIVE "", __stringify(__ASM_CLAC), X86_FEATURE_SMAP
+
+#define ASM_STAC \
+       ALTERNATIVE "", __stringify(__ASM_STAC), X86_FEATURE_SMAP
 
 #else /* CONFIG_X86_SMAP */
 
 static __always_inline void clac(void)
 {
        /* Note: a barrier is implicit in alternative() */
-       alternative(ASM_NOP3, __stringify(__ASM_CLAC), X86_FEATURE_SMAP);
+       alternative("", __stringify(__ASM_CLAC), X86_FEATURE_SMAP);
 }
 
 static __always_inline void stac(void)
 {
        /* Note: a barrier is implicit in alternative() */
-       alternative(ASM_NOP3, __stringify(__ASM_STAC), X86_FEATURE_SMAP);
+       alternative("", __stringify(__ASM_STAC), X86_FEATURE_SMAP);
 }
 
 /* These macros can be used in asm() statements */
 #define ASM_CLAC \
-       ALTERNATIVE(ASM_NOP3, __stringify(__ASM_CLAC), X86_FEATURE_SMAP)
+       ALTERNATIVE("", __stringify(__ASM_CLAC), X86_FEATURE_SMAP)
 #define ASM_STAC \
-       ALTERNATIVE(ASM_NOP3, __stringify(__ASM_STAC), X86_FEATURE_SMAP)
+       ALTERNATIVE("", __stringify(__ASM_STAC), X86_FEATURE_SMAP)
 
 #else /* CONFIG_X86_SMAP */
 
index 8cd1cc3bc8356ffef29e349f08b3de43aeb79506..17a8dced12daef5c9fcc5351c165994225295372 100644 (file)
@@ -150,12 +150,13 @@ static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 }
 
 void cpu_disable_common(void);
-void cpu_die_common(unsigned int cpu);
 void native_smp_prepare_boot_cpu(void);
 void native_smp_prepare_cpus(unsigned int max_cpus);
 void native_smp_cpus_done(unsigned int max_cpus);
+void common_cpu_up(unsigned int cpunum, struct task_struct *tidle);
 int native_cpu_up(unsigned int cpunum, struct task_struct *tidle);
 int native_cpu_disable(void);
+int common_cpu_die(unsigned int cpu);
 void native_cpu_die(unsigned int cpu);
 void native_play_dead(void);
 void play_dead_common(void);
index 6a4b00fafb003cbcf4e2bdc62a244ee71dc75a45..aeb4666e0c0a770a7fbb8432b7d133b2dd9e764d 100644 (file)
@@ -4,6 +4,8 @@
 
 #ifdef __KERNEL__
 
+#include <asm/nops.h>
+
 static inline void native_clts(void)
 {
        asm volatile("clts");
@@ -199,6 +201,28 @@ static inline void clflushopt(volatile void *__p)
                       "+m" (*(volatile char __force *)__p));
 }
 
+static inline void clwb(volatile void *__p)
+{
+       volatile struct { char x[64]; } *p = __p;
+
+       asm volatile(ALTERNATIVE_2(
+               ".byte " __stringify(NOP_DS_PREFIX) "; clflush (%[pax])",
+               ".byte 0x66; clflush (%[pax])", /* clflushopt (%%rax) */
+               X86_FEATURE_CLFLUSHOPT,
+               ".byte 0x66, 0x0f, 0xae, 0x30",  /* clwb (%%rax) */
+               X86_FEATURE_CLWB)
+               : [p] "+m" (*p)
+               : [pax] "a" (p));
+}
+
+static inline void pcommit_sfence(void)
+{
+       alternative(ASM_NOP7,
+                   ".byte 0x66, 0x0f, 0xae, 0xf8\n\t" /* pcommit */
+                   "sfence",
+                   X86_FEATURE_PCOMMIT);
+}
+
 #define nop() asm volatile ("nop")
 
 
index 1d4e4f279a3281e094684ad29bd4b544d37af6ab..ea2dbe82cba3a74e06e269655cdfca8a67253e52 100644 (file)
 #include <asm/percpu.h>
 #include <asm/types.h>
 
+/*
+ * TOP_OF_KERNEL_STACK_PADDING is a number of unused bytes that we
+ * reserve at the top of the kernel stack.  We do it because of a nasty
+ * 32-bit corner case.  On x86_32, the hardware stack frame is
+ * variable-length.  Except for vm86 mode, struct pt_regs assumes a
+ * maximum-length frame.  If we enter from CPL 0, the top 8 bytes of
+ * pt_regs don't actually exist.  Ordinarily this doesn't matter, but it
+ * does in at least one case:
+ *
+ * If we take an NMI early enough in SYSENTER, then we can end up with
+ * pt_regs that extends above sp0.  On the way out, in the espfix code,
+ * we can read the saved SS value, but that value will be above sp0.
+ * Without this offset, that can result in a page fault.  (We are
+ * careful that, in this case, the value we read doesn't matter.)
+ *
+ * In vm86 mode, the hardware frame is much longer still, but we neither
+ * access the extra members from NMI context, nor do we write such a
+ * frame at sp0 at all.
+ *
+ * x86_64 has a fixed-length stack frame.
+ */
+#ifdef CONFIG_X86_32
+# define TOP_OF_KERNEL_STACK_PADDING 8
+#else
+# define TOP_OF_KERNEL_STACK_PADDING 0
+#endif
+
 /*
  * low level task data that entry.S needs immediate access to
  * - this struct should fit entirely inside of one cache line
@@ -145,7 +172,6 @@ struct thread_info {
 #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)
 
 #define STACK_WARN             (THREAD_SIZE/8)
-#define KERNEL_STACK_OFFSET    (5*(BITS_PER_LONG/8))
 
 /*
  * macros/functions for gaining access to the thread information structure
@@ -158,10 +184,7 @@ DECLARE_PER_CPU(unsigned long, kernel_stack);
 
 static inline struct thread_info *current_thread_info(void)
 {
-       struct thread_info *ti;
-       ti = (void *)(this_cpu_read_stable(kernel_stack) +
-                     KERNEL_STACK_OFFSET - THREAD_SIZE);
-       return ti;
+       return (struct thread_info *)(current_top_of_stack() - THREAD_SIZE);
 }
 
 static inline unsigned long current_stack_pointer(void)
@@ -177,16 +200,37 @@ static inline unsigned long current_stack_pointer(void)
 
 #else /* !__ASSEMBLY__ */
 
-/* how to get the thread information struct from ASM */
+/* Load thread_info address into "reg" */
 #define GET_THREAD_INFO(reg) \
        _ASM_MOV PER_CPU_VAR(kernel_stack),reg ; \
-       _ASM_SUB $(THREAD_SIZE-KERNEL_STACK_OFFSET),reg ;
+       _ASM_SUB $(THREAD_SIZE),reg ;
 
 /*
- * Same if PER_CPU_VAR(kernel_stack) is, perhaps with some offset, already in
- * a certain register (to be used in assembler memory operands).
+ * ASM operand which evaluates to a 'thread_info' address of
+ * the current task, if it is known that "reg" is exactly "off"
+ * bytes below the top of the stack currently.
+ *
+ * ( The kernel stack's size is known at build time, it is usually
+ *   2 or 4 pages, and the bottom  of the kernel stack contains
+ *   the thread_info structure. So to access the thread_info very
+ *   quickly from assembly code we can calculate down from the
+ *   top of the kernel stack to the bottom, using constant,
+ *   build-time calculations only. )
+ *
+ * For example, to fetch the current thread_info->flags value into %eax
+ * on x86-64 defconfig kernels, in syscall entry code where RSP is
+ * currently at exactly SIZEOF_PTREGS bytes away from the top of the
+ * stack:
+ *
+ *      mov ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS), %eax
+ *
+ * will translate to:
+ *
+ *      8b 84 24 b8 c0 ff ff      mov    -0x3f48(%rsp), %eax
+ *
+ * which is below the current RSP by almost 16K.
  */
-#define THREAD_INFO(reg, off) KERNEL_STACK_OFFSET+(off)-THREAD_SIZE(reg)
+#define ASM_THREAD_INFO(field, reg, off) ((field)+(off)-THREAD_SIZE)(reg)
 
 #endif
 
@@ -236,6 +280,16 @@ static inline bool is_ia32_task(void)
 #endif
        return false;
 }
+
+/*
+ * Force syscall return via IRET by making it look as if there was
+ * some work pending. IRET is our most capable (but slowest) syscall
+ * return path, which is able to restore modified SS, CS and certain
+ * EFLAGS values that other (fast) syscall return instructions
+ * are not able to restore properly.
+ */
+#define force_iret() set_thread_flag(TIF_NOTIFY_RESUME)
+
 #endif /* !__ASSEMBLY__ */
 
 #ifndef __ASSEMBLY__
index 12a26b979bf163008ebd1dc5b7cdff3ca5876f0b..f2f9b39b274ab0c2f81ab6b388f78ba5c881ec5e 100644 (file)
@@ -231,6 +231,6 @@ __copy_from_user_inatomic_nocache(void *dst, const void __user *src,
 }
 
 unsigned long
-copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest);
+copy_user_handle_tail(char *to, char *from, unsigned len);
 
 #endif /* _ASM_X86_UACCESS_64_H */
index 225b0988043a0a78ac9092a9af7a265122c685cd..ab456dc233b51482c53c0232a97ed71cbc50a990 100644 (file)
@@ -15,6 +15,7 @@
 
 /* loadflags */
 #define LOADED_HIGH    (1<<0)
+#define KASLR_FLAG     (1<<1)
 #define QUIET_FLAG     (1<<5)
 #define KEEP_SEGMENTS  (1<<6)
 #define CAN_USE_HEAP   (1<<7)
index 3ce079136c11ff8fd4a05c911c9ce68d10ac163f..1a4eae695ca8ace1c93b317e0f1d054875b0b03d 100644 (file)
 #define MSR_IA32_PERF_CAPABILITIES     0x00000345
 #define MSR_PEBS_LD_LAT_THRESHOLD      0x000003f6
 
+#define MSR_IA32_RTIT_CTL              0x00000570
+#define RTIT_CTL_TRACEEN               BIT(0)
+#define RTIT_CTL_OS                    BIT(2)
+#define RTIT_CTL_USR                   BIT(3)
+#define RTIT_CTL_CR3EN                 BIT(7)
+#define RTIT_CTL_TOPA                  BIT(8)
+#define RTIT_CTL_TSC_EN                        BIT(10)
+#define RTIT_CTL_DISRETC               BIT(11)
+#define RTIT_CTL_BRANCH_EN             BIT(13)
+#define MSR_IA32_RTIT_STATUS           0x00000571
+#define RTIT_STATUS_CONTEXTEN          BIT(1)
+#define RTIT_STATUS_TRIGGEREN          BIT(2)
+#define RTIT_STATUS_ERROR              BIT(4)
+#define RTIT_STATUS_STOPPED            BIT(5)
+#define MSR_IA32_RTIT_CR3_MATCH                0x00000572
+#define MSR_IA32_RTIT_OUTPUT_BASE      0x00000560
+#define MSR_IA32_RTIT_OUTPUT_MASK      0x00000561
+
 #define MSR_MTRRfix64K_00000           0x00000250
 #define MSR_MTRRfix16K_80000           0x00000258
 #define MSR_MTRRfix16K_A0000           0x00000259
index 7b0a55a8885115386f40a4207838e60ad66abc21..580aee3072e0684082b0f74e1358925efaf4f540 100644 (file)
 #else /* __i386__ */
 
 #if defined(__ASSEMBLY__) || defined(__FRAME_OFFSETS)
+/*
+ * C ABI says these regs are callee-preserved. They aren't saved on kernel entry
+ * unless syscall needs a complete, fully filled "struct pt_regs".
+ */
 #define R15 0
 #define R14 8
 #define R13 16
 #define R12 24
 #define RBP 32
 #define RBX 40
-/* arguments: interrupts/non tracing syscalls only save up to here*/
+/* These regs are callee-clobbered. Always saved on kernel entry. */
 #define R11 48
 #define R10 56
 #define R9 64
 #define RDX 96
 #define RSI 104
 #define RDI 112
-#define ORIG_RAX 120       /* = ERROR */
-/* end of arguments */
-/* cpu exception frame or undefined in case of fast syscall. */
+/*
+ * On syscall entry, this is syscall#. On CPU exception, this is error code.
+ * On hw interrupt, it's IRQ number:
+ */
+#define ORIG_RAX 120
+/* Return frame for iretq */
 #define RIP 128
 #define CS 136
 #define EFLAGS 144
 #define RSP 152
 #define SS 160
-#define ARGOFFSET R11
 #endif /* __ASSEMBLY__ */
 
 /* top of stack page */
index ac4b9aa4d9996b413eaf71ada8bb6b458e7a83a0..bc16115af39b9e66c048b5e0237180f505535b77 100644 (file)
@@ -41,13 +41,17 @@ struct pt_regs {
 #ifndef __KERNEL__
 
 struct pt_regs {
+/*
+ * C ABI says these regs are callee-preserved. They aren't saved on kernel entry
+ * unless syscall needs a complete, fully filled "struct pt_regs".
+ */
        unsigned long r15;
        unsigned long r14;
        unsigned long r13;
        unsigned long r12;
        unsigned long rbp;
        unsigned long rbx;
-/* arguments: non interrupts/non tracing syscalls only save up to here*/
+/* These regs are callee-clobbered. Always saved on kernel entry. */
        unsigned long r11;
        unsigned long r10;
        unsigned long r9;
@@ -57,9 +61,12 @@ struct pt_regs {
        unsigned long rdx;
        unsigned long rsi;
        unsigned long rdi;
+/*
+ * On syscall entry, this is syscall#. On CPU exception, this is error code.
+ * On hw interrupt, it's IRQ number:
+ */
        unsigned long orig_rax;
-/* end of arguments */
-/* cpu exception frame or undefined */
+/* Return frame for iretq */
        unsigned long rip;
        unsigned long cs;
        unsigned long eflags;
index d8b9f9081e86fb486c88c34b8359bdfec28dd5fe..16dc4e8a2cd34845042445915f9e9d74d90546c6 100644 (file)
@@ -177,9 +177,24 @@ struct sigcontext {
        __u64 rip;
        __u64 eflags;           /* RFLAGS */
        __u16 cs;
-       __u16 gs;
-       __u16 fs;
-       __u16 __pad0;
+
+       /*
+        * 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;
        __u64 err;
        __u64 trapno;
        __u64 oldmask;
index c5f1a1deb91a904e21d88c2762836dd98500e600..1fe92181ee9ef8b3cb061a6091a732b2b9fa7bf0 100644 (file)
@@ -67,6 +67,7 @@
 #define EXIT_REASON_EPT_VIOLATION       48
 #define EXIT_REASON_EPT_MISCONFIG       49
 #define EXIT_REASON_INVEPT              50
+#define EXIT_REASON_RDTSCP              51
 #define EXIT_REASON_PREEMPTION_TIMER    52
 #define EXIT_REASON_INVVPID             53
 #define EXIT_REASON_WBINVD              54
index cdb1b70ddad0f026cbe42800571d0869211bf6f5..c887cd944f0c18e849fda278ec50dbee6b731919 100644 (file)
@@ -32,6 +32,7 @@ obj-$(CONFIG_X86_32)  += i386_ksyms_32.o
 obj-$(CONFIG_X86_64)   += sys_x86_64.o x8664_ksyms_64.o
 obj-$(CONFIG_X86_64)   += mcount_64.o
 obj-y                  += syscall_$(BITS).o vsyscall_gtod.o
+obj-$(CONFIG_IA32_EMULATION)   += syscall_32.o
 obj-$(CONFIG_X86_VSYSCALL_EMULATION)   += vsyscall_64.o vsyscall_emu_64.o
 obj-$(CONFIG_X86_ESPFIX64)     += espfix_64.o
 obj-$(CONFIG_SYSFS)    += ksysfs.o
index 703130f469ecf71978b9d67bf0fb50da9b31cbc9..aef65319316065eab845f35141682c3550f18a22 100644 (file)
@@ -52,10 +52,25 @@ static int __init setup_noreplace_paravirt(char *str)
 __setup("noreplace-paravirt", setup_noreplace_paravirt);
 #endif
 
-#define DPRINTK(fmt, ...)                              \
-do {                                                   \
-       if (debug_alternative)                          \
-               printk(KERN_DEBUG fmt, ##__VA_ARGS__);  \
+#define DPRINTK(fmt, args...)                                          \
+do {                                                                   \
+       if (debug_alternative)                                          \
+               printk(KERN_DEBUG "%s: " fmt "\n", __func__, ##args);   \
+} while (0)
+
+#define DUMP_BYTES(buf, len, fmt, args...)                             \
+do {                                                                   \
+       if (unlikely(debug_alternative)) {                              \
+               int j;                                                  \
+                                                                       \
+               if (!(len))                                             \
+                       break;                                          \
+                                                                       \
+               printk(KERN_DEBUG fmt, ##args);                         \
+               for (j = 0; j < (len) - 1; j++)                         \
+                       printk(KERN_CONT "%02hhx ", buf[j]);            \
+               printk(KERN_CONT "%02hhx\n", buf[j]);                   \
+       }                                                               \
 } while (0)
 
 /*
@@ -243,12 +258,89 @@ extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
 extern s32 __smp_locks[], __smp_locks_end[];
 void *text_poke_early(void *addr, const void *opcode, size_t len);
 
-/* Replace instructions with better alternatives for this CPU type.
-   This runs before SMP is initialized to avoid SMP problems with
-   self modifying code. This implies that asymmetric systems where
-   APs have less capabilities than the boot processor are not handled.
-   Tough. Make sure you disable such features by hand. */
+/*
+ * Are we looking at a near JMP with a 1 or 4-byte displacement.
+ */
+static inline bool is_jmp(const u8 opcode)
+{
+       return opcode == 0xeb || opcode == 0xe9;
+}
+
+static void __init_or_module
+recompute_jump(struct alt_instr *a, u8 *orig_insn, u8 *repl_insn, u8 *insnbuf)
+{
+       u8 *next_rip, *tgt_rip;
+       s32 n_dspl, o_dspl;
+       int repl_len;
+
+       if (a->replacementlen != 5)
+               return;
+
+       o_dspl = *(s32 *)(insnbuf + 1);
+
+       /* next_rip of the replacement JMP */
+       next_rip = repl_insn + a->replacementlen;
+       /* target rip of the replacement JMP */
+       tgt_rip  = next_rip + o_dspl;
+       n_dspl = tgt_rip - orig_insn;
+
+       DPRINTK("target RIP: %p, new_displ: 0x%x", tgt_rip, n_dspl);
+
+       if (tgt_rip - orig_insn >= 0) {
+               if (n_dspl - 2 <= 127)
+                       goto two_byte_jmp;
+               else
+                       goto five_byte_jmp;
+       /* negative offset */
+       } else {
+               if (((n_dspl - 2) & 0xff) == (n_dspl - 2))
+                       goto two_byte_jmp;
+               else
+                       goto five_byte_jmp;
+       }
+
+two_byte_jmp:
+       n_dspl -= 2;
+
+       insnbuf[0] = 0xeb;
+       insnbuf[1] = (s8)n_dspl;
+       add_nops(insnbuf + 2, 3);
+
+       repl_len = 2;
+       goto done;
+
+five_byte_jmp:
+       n_dspl -= 5;
+
+       insnbuf[0] = 0xe9;
+       *(s32 *)&insnbuf[1] = n_dspl;
 
+       repl_len = 5;
+
+done:
+
+       DPRINTK("final displ: 0x%08x, JMP 0x%lx",
+               n_dspl, (unsigned long)orig_insn + n_dspl + repl_len);
+}
+
+static void __init_or_module optimize_nops(struct alt_instr *a, u8 *instr)
+{
+       if (instr[0] != 0x90)
+               return;
+
+       add_nops(instr + (a->instrlen - a->padlen), a->padlen);
+
+       DUMP_BYTES(instr, a->instrlen, "%p: [%d:%d) optimized NOPs: ",
+                  instr, a->instrlen - a->padlen, a->padlen);
+}
+
+/*
+ * Replace instructions with better alternatives for this CPU type. This runs
+ * before SMP is initialized to avoid SMP problems with self modifying code.
+ * This implies that asymmetric systems where APs have less capabilities than
+ * the boot processor are not handled. Tough. Make sure you disable such
+ * features by hand.
+ */
 void __init_or_module apply_alternatives(struct alt_instr *start,
                                         struct alt_instr *end)
 {
@@ -256,10 +348,10 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
        u8 *instr, *replacement;
        u8 insnbuf[MAX_PATCH_LEN];
 
-       DPRINTK("%s: alt table %p -> %p\n", __func__, start, end);
+       DPRINTK("alt table %p -> %p", start, end);
        /*
         * The scan order should be from start to end. A later scanned
-        * alternative code can overwrite a previous scanned alternative code.
+        * alternative code can overwrite previously scanned alternative code.
         * Some kernel functions (e.g. memcpy, memset, etc) use this order to
         * patch code.
         *
@@ -267,29 +359,54 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
         * order.
         */
        for (a = start; a < end; a++) {
+               int insnbuf_sz = 0;
+
                instr = (u8 *)&a->instr_offset + a->instr_offset;
                replacement = (u8 *)&a->repl_offset + a->repl_offset;
-               BUG_ON(a->replacementlen > a->instrlen);
                BUG_ON(a->instrlen > sizeof(insnbuf));
                BUG_ON(a->cpuid >= (NCAPINTS + NBUGINTS) * 32);
-               if (!boot_cpu_has(a->cpuid))
+               if (!boot_cpu_has(a->cpuid)) {
+                       if (a->padlen > 1)
+                               optimize_nops(a, instr);
+
                        continue;
+               }
+
+               DPRINTK("feat: %d*32+%d, old: (%p, len: %d), repl: (%p, len: %d), pad: %d",
+                       a->cpuid >> 5,
+                       a->cpuid & 0x1f,
+                       instr, a->instrlen,
+                       replacement, a->replacementlen, a->padlen);
+
+               DUMP_BYTES(instr, a->instrlen, "%p: old_insn: ", instr);
+               DUMP_BYTES(replacement, a->replacementlen, "%p: rpl_insn: ", replacement);
 
                memcpy(insnbuf, replacement, a->replacementlen);
+               insnbuf_sz = a->replacementlen;
 
                /* 0xe8 is a relative jump; fix the offset. */
-               if (*insnbuf == 0xe8 && a->replacementlen == 5)
-                   *(s32 *)(insnbuf + 1) += replacement - instr;
+               if (*insnbuf == 0xe8 && a->replacementlen == 5) {
+                       *(s32 *)(insnbuf + 1) += replacement - instr;
+                       DPRINTK("Fix CALL offset: 0x%x, CALL 0x%lx",
+                               *(s32 *)(insnbuf + 1),
+                               (unsigned long)instr + *(s32 *)(insnbuf + 1) + 5);
+               }
+
+               if (a->replacementlen && is_jmp(replacement[0]))
+                       recompute_jump(a, instr, replacement, insnbuf);
 
-               add_nops(insnbuf + a->replacementlen,
-                        a->instrlen - a->replacementlen);
+               if (a->instrlen > a->replacementlen) {
+                       add_nops(insnbuf + a->replacementlen,
+                                a->instrlen - a->replacementlen);
+                       insnbuf_sz += a->instrlen - a->replacementlen;
+               }
+               DUMP_BYTES(insnbuf, insnbuf_sz, "%p: final_insn: ", instr);
 
-               text_poke_early(instr, insnbuf, a->instrlen);
+               text_poke_early(instr, insnbuf, insnbuf_sz);
        }
 }
 
 #ifdef CONFIG_SMP
-
 static void alternatives_smp_lock(const s32 *start, const s32 *end,
                                  u8 *text, u8 *text_end)
 {
@@ -371,8 +488,8 @@ void __init_or_module alternatives_smp_module_add(struct module *mod,
        smp->locks_end  = locks_end;
        smp->text       = text;
        smp->text_end   = text_end;
-       DPRINTK("%s: locks %p -> %p, text %p -> %p, name %s\n",
-               __func__, smp->locks, smp->locks_end,
+       DPRINTK("locks %p -> %p, text %p -> %p, name %s\n",
+               smp->locks, smp->locks_end,
                smp->text, smp->text_end, smp->name);
 
        list_add_tail(&smp->next, &smp_alt_modules);
@@ -440,7 +557,7 @@ int alternatives_text_reserved(void *start, void *end)
 
        return 0;
 }
-#endif
+#endif /* CONFIG_SMP */
 
 #ifdef CONFIG_PARAVIRT
 void __init_or_module apply_paravirt(struct paravirt_patch_site *start,
@@ -601,7 +718,7 @@ int poke_int3_handler(struct pt_regs *regs)
        if (likely(!bp_patching_in_progress))
                return 0;
 
-       if (user_mode_vm(regs) || regs->ip != (unsigned long)bp_int3_addr)
+       if (user_mode(regs) || regs->ip != (unsigned long)bp_int3_addr)
                return 0;
 
        /* set up the specified breakpoint handler */
index ad3639ae1b9b50a71ff224faaf96e05302eccd9f..dcb52850a28fcbe00a4a25ddf47d6f4ccedf3c9c 100644 (file)
@@ -1084,67 +1084,6 @@ void lapic_shutdown(void)
        local_irq_restore(flags);
 }
 
-/*
- * This is to verify that we're looking at a real local APIC.
- * Check these against your board if the CPUs aren't getting
- * started for no apparent reason.
- */
-int __init verify_local_APIC(void)
-{
-       unsigned int reg0, reg1;
-
-       /*
-        * The version register is read-only in a real APIC.
-        */
-       reg0 = apic_read(APIC_LVR);
-       apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0);
-       apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK);
-       reg1 = apic_read(APIC_LVR);
-       apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1);
-
-       /*
-        * The two version reads above should print the same
-        * numbers.  If the second one is different, then we
-        * poke at a non-APIC.
-        */
-       if (reg1 != reg0)
-               return 0;
-
-       /*
-        * Check if the version looks reasonably.
-        */
-       reg1 = GET_APIC_VERSION(reg0);
-       if (reg1 == 0x00 || reg1 == 0xff)
-               return 0;
-       reg1 = lapic_get_maxlvt();
-       if (reg1 < 0x02 || reg1 == 0xff)
-               return 0;
-
-       /*
-        * The ID register is read/write in a real APIC.
-        */
-       reg0 = apic_read(APIC_ID);
-       apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
-       apic_write(APIC_ID, reg0 ^ apic->apic_id_mask);
-       reg1 = apic_read(APIC_ID);
-       apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1);
-       apic_write(APIC_ID, reg0);
-       if (reg1 != (reg0 ^ apic->apic_id_mask))
-               return 0;
-
-       /*
-        * The next two are just to see if we have sane values.
-        * They're only really relevant if we're in Virtual Wire
-        * compatibility mode, but most boxes are anymore.
-        */
-       reg0 = apic_read(APIC_LVT0);
-       apic_printk(APIC_DEBUG, "Getting LVT0: %x\n", reg0);
-       reg1 = apic_read(APIC_LVT1);
-       apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1);
-
-       return 1;
-}
-
 /**
  * sync_Arb_IDs - synchronize APIC bus arbitration IDs
  */
@@ -2283,7 +2222,6 @@ int __init APIC_init_uniprocessor(void)
                disable_ioapic_support();
 
        default_setup_apic_routing();
-       verify_local_APIC();
        apic_bsp_setup(true);
        return 0;
 }
index e658f21681c82e1ad8fa28bde084c7933939548b..d9d0bd2faaf42cf4b1e894628edb4139ee615780 100644 (file)
@@ -135,12 +135,12 @@ static void init_x2apic_ldr(void)
 
        per_cpu(x86_cpu_to_logical_apicid, this_cpu) = apic_read(APIC_LDR);
 
-       __cpu_set(this_cpu, per_cpu(cpus_in_cluster, this_cpu));
+       cpumask_set_cpu(this_cpu, per_cpu(cpus_in_cluster, this_cpu));
        for_each_online_cpu(cpu) {
                if (x2apic_cluster(this_cpu) != x2apic_cluster(cpu))
                        continue;
-               __cpu_set(this_cpu, per_cpu(cpus_in_cluster, cpu));
-               __cpu_set(cpu, per_cpu(cpus_in_cluster, this_cpu));
+               cpumask_set_cpu(this_cpu, per_cpu(cpus_in_cluster, cpu));
+               cpumask_set_cpu(cpu, per_cpu(cpus_in_cluster, this_cpu));
        }
 }
 
@@ -195,7 +195,7 @@ static int x2apic_init_cpu_notifier(void)
 
        BUG_ON(!per_cpu(cpus_in_cluster, cpu) || !per_cpu(ipi_mask, cpu));
 
-       __cpu_set(cpu, per_cpu(cpus_in_cluster, cpu));
+       cpumask_set_cpu(cpu, per_cpu(cpus_in_cluster, cpu));
        register_hotcpu_notifier(&x2apic_cpu_notifier);
        return 1;
 }
index 8e9dcfd630e4b539e7936050b7bb1673660ae752..c8d92950bc041bcebcb6a2361ebeac0ce3065279 100644 (file)
@@ -144,33 +144,60 @@ static void __init uv_set_apicid_hibit(void)
 
 static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
-       int pnodeid, is_uv1, is_uv2, is_uv3;
-
-       is_uv1 = !strcmp(oem_id, "SGI");
-       is_uv2 = !strcmp(oem_id, "SGI2");
-       is_uv3 = !strncmp(oem_id, "SGI3", 4);   /* there are varieties of UV3 */
-       if (is_uv1 || is_uv2 || is_uv3) {
-               uv_hub_info->hub_revision =
-                       (is_uv1 ? UV1_HUB_REVISION_BASE :
-                       (is_uv2 ? UV2_HUB_REVISION_BASE :
-                                 UV3_HUB_REVISION_BASE));
-               pnodeid = early_get_pnodeid();
-               early_get_apic_pnode_shift();
-               x86_platform.is_untracked_pat_range =  uv_is_untracked_pat_range;
-               x86_platform.nmi_init = uv_nmi_init;
-               if (!strcmp(oem_table_id, "UVL"))
-                       uv_system_type = UV_LEGACY_APIC;
-               else if (!strcmp(oem_table_id, "UVX"))
-                       uv_system_type = UV_X2APIC;
-               else if (!strcmp(oem_table_id, "UVH")) {
-                       __this_cpu_write(x2apic_extra_bits,
-                               pnodeid << uvh_apicid.s.pnode_shift);
-                       uv_system_type = UV_NON_UNIQUE_APIC;
-                       uv_set_apicid_hibit();
-                       return 1;
-               }
+       int pnodeid;
+       int uv_apic;
+
+       if (strncmp(oem_id, "SGI", 3) != 0)
+               return 0;
+
+       /*
+        * Determine UV arch type.
+        *   SGI: UV100/1000
+        *   SGI2: UV2000/3000
+        *   SGI3: UV300 (truncated to 4 chars because of different varieties)
+        */
+       uv_hub_info->hub_revision =
+               !strncmp(oem_id, "SGI3", 4) ? UV3_HUB_REVISION_BASE :
+               !strcmp(oem_id, "SGI2") ? UV2_HUB_REVISION_BASE :
+               !strcmp(oem_id, "SGI") ? UV1_HUB_REVISION_BASE : 0;
+
+       if (uv_hub_info->hub_revision == 0)
+               goto badbios;
+
+       pnodeid = early_get_pnodeid();
+       early_get_apic_pnode_shift();
+       x86_platform.is_untracked_pat_range =  uv_is_untracked_pat_range;
+       x86_platform.nmi_init = uv_nmi_init;
+
+       if (!strcmp(oem_table_id, "UVX")) {             /* most common */
+               uv_system_type = UV_X2APIC;
+               uv_apic = 0;
+
+       } else if (!strcmp(oem_table_id, "UVH")) {      /* only UV1 systems */
+               uv_system_type = UV_NON_UNIQUE_APIC;
+               __this_cpu_write(x2apic_extra_bits,
+                       pnodeid << uvh_apicid.s.pnode_shift);
+               uv_set_apicid_hibit();
+               uv_apic = 1;
+
+       } else  if (!strcmp(oem_table_id, "UVL")) {     /* only used for */
+               uv_system_type = UV_LEGACY_APIC;        /* very small systems */
+               uv_apic = 0;
+
+       } else {
+               goto badbios;
        }
-       return 0;
+
+       pr_info("UV: OEM IDs %s/%s, System/HUB Types %d/%d, uv_apic %d\n",
+               oem_id, oem_table_id, uv_system_type,
+               uv_min_hub_revision_id, uv_apic);
+
+       return uv_apic;
+
+badbios:
+       pr_err("UV: OEM_ID:%s OEM_TABLE_ID:%s\n", oem_id, oem_table_id);
+       pr_err("Current BIOS not supported, update kernel and/or BIOS\n");
+       BUG();
 }
 
 enum uv_system_type get_uv_system_type(void)
@@ -854,10 +881,14 @@ void __init uv_system_init(void)
        unsigned long mmr_base, present, paddr;
        unsigned short pnode_mask;
        unsigned char n_lshift;
-       char *hub = (is_uv1_hub() ? "UV1" :
-                   (is_uv2_hub() ? "UV2" :
-                                   "UV3"));
+       char *hub = (is_uv1_hub() ? "UV100/1000" :
+                   (is_uv2_hub() ? "UV2000/3000" :
+                   (is_uv3_hub() ? "UV300" : NULL)));
 
+       if (!hub) {
+               pr_err("UV: Unknown/unsupported UV hub\n");
+               return;
+       }
        pr_info("UV: Found %s hub\n", hub);
        map_low_mmrs();
 
index 3b3b9d33ac1d2f0809db3b16230c840e98774b70..47703aed74cfb7d013b2d577488d68c7280bf8c6 100644 (file)
@@ -68,7 +68,7 @@ void foo(void)
 
        /* Offset from the sysenter stack to tss.sp0 */
        DEFINE(TSS_sysenter_sp0, offsetof(struct tss_struct, x86_tss.sp0) -
-                sizeof(struct tss_struct));
+              offsetofend(struct tss_struct, SYSENTER_stack));
 
 #if defined(CONFIG_LGUEST) || defined(CONFIG_LGUEST_GUEST) || defined(CONFIG_LGUEST_MODULE)
        BLANK();
index fdcbb4d27c9f80f35a587f4284fa2b958c44e774..5ce6f2da87639c7d373879e43120c9035ba590b9 100644 (file)
@@ -81,6 +81,7 @@ int main(void)
 #undef ENTRY
 
        OFFSET(TSS_ist, tss_struct, x86_tss.ist);
+       OFFSET(TSS_sp0, tss_struct, x86_tss.sp0);
        BLANK();
 
        DEFINE(__NR_syscall_max, sizeof(syscalls_64) - 1);
index 80091ae54c2b0995ea56629a3f7e6969a484fb9b..9bff68798836232d51544e21ee3e15409171db11 100644 (file)
@@ -39,7 +39,8 @@ obj-$(CONFIG_CPU_SUP_AMD)             += perf_event_amd_iommu.o
 endif
 obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_p6.o perf_event_knc.o perf_event_p4.o
 obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_rapl.o
+obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_rapl.o perf_event_intel_cqm.o
+obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_pt.o perf_event_intel_bts.o
 
 obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += perf_event_intel_uncore.o \
                                           perf_event_intel_uncore_snb.o \
index a220239cea65ca99b3c52ebbfaed6ce973f0dec1..fd470ebf924e574e827f1942b973075d3168a9b6 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/io.h>
 #include <linux/sched.h>
+#include <linux/random.h>
 #include <asm/processor.h>
 #include <asm/apic.h>
 #include <asm/cpu.h>
@@ -488,6 +489,9 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
 
                va_align.mask     = (upperbit - 1) & PAGE_MASK;
                va_align.flags    = ALIGN_VA_32 | ALIGN_VA_64;
+
+               /* A random value per boot for bit slice [12:upper_bit) */
+               va_align.bits = get_random_int() & va_align.mask;
        }
 }
 
@@ -711,6 +715,11 @@ static void init_amd(struct cpuinfo_x86 *c)
                set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
 
        rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
+
+       /* 3DNow or LM implies PREFETCHW */
+       if (!cpu_has(c, X86_FEATURE_3DNOWPREFETCH))
+               if (cpu_has(c, X86_FEATURE_3DNOW) || cpu_has(c, X86_FEATURE_LM))
+                       set_cpu_cap(c, X86_FEATURE_3DNOWPREFETCH);
 }
 
 #ifdef CONFIG_X86_32
index 2346c95c6ab1945077fdde28c129342ffe09749d..a62cf04dac8ae99d1310b02b827bca528311d490 100644 (file)
@@ -646,6 +646,30 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
                c->x86_capability[10] = eax;
        }
 
+       /* Additional Intel-defined flags: level 0x0000000F */
+       if (c->cpuid_level >= 0x0000000F) {
+               u32 eax, ebx, ecx, edx;
+
+               /* QoS sub-leaf, EAX=0Fh, ECX=0 */
+               cpuid_count(0x0000000F, 0, &eax, &ebx, &ecx, &edx);
+               c->x86_capability[11] = edx;
+               if (cpu_has(c, X86_FEATURE_CQM_LLC)) {
+                       /* will be overridden if occupancy monitoring exists */
+                       c->x86_cache_max_rmid = ebx;
+
+                       /* QoS sub-leaf, EAX=0Fh, ECX=1 */
+                       cpuid_count(0x0000000F, 1, &eax, &ebx, &ecx, &edx);
+                       c->x86_capability[12] = edx;
+                       if (cpu_has(c, X86_FEATURE_CQM_OCCUP_LLC)) {
+                               c->x86_cache_max_rmid = ecx;
+                               c->x86_cache_occ_scale = ebx;
+                       }
+               } else {
+                       c->x86_cache_max_rmid = -1;
+                       c->x86_cache_occ_scale = -1;
+               }
+       }
+
        /* AMD-defined flags: level 0x80000001 */
        xlvl = cpuid_eax(0x80000000);
        c->extended_cpuid_level = xlvl;
@@ -834,6 +858,20 @@ static void generic_identify(struct cpuinfo_x86 *c)
        detect_nopl(c);
 }
 
+static void x86_init_cache_qos(struct cpuinfo_x86 *c)
+{
+       /*
+        * The heavy lifting of max_rmid and cache_occ_scale are handled
+        * in get_cpu_cap().  Here we just set the max_rmid for the boot_cpu
+        * in case CQM bits really aren't there in this CPU.
+        */
+       if (c != &boot_cpu_data) {
+               boot_cpu_data.x86_cache_max_rmid =
+                       min(boot_cpu_data.x86_cache_max_rmid,
+                           c->x86_cache_max_rmid);
+       }
+}
+
 /*
  * This does the hard work of actually picking apart the CPU stuff...
  */
@@ -923,6 +961,7 @@ static void identify_cpu(struct cpuinfo_x86 *c)
 
        init_hypervisor(c);
        x86_init_rdrand(c);
+       x86_init_cache_qos(c);
 
        /*
         * Clear/Set all flags overriden by options, need do it
@@ -959,38 +998,37 @@ static void identify_cpu(struct cpuinfo_x86 *c)
 #endif
 }
 
-#ifdef CONFIG_X86_64
-#ifdef CONFIG_IA32_EMULATION
-/* May not be __init: called during resume */
-static void syscall32_cpu_init(void)
-{
-       /* Load these always in case some future AMD CPU supports
-          SYSENTER from compat mode too. */
-       wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
-       wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
-       wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)ia32_sysenter_target);
-
-       wrmsrl(MSR_CSTAR, ia32_cstar_target);
-}
-#endif         /* CONFIG_IA32_EMULATION */
-#endif         /* CONFIG_X86_64 */
-
+/*
+ * Set up the CPU state needed to execute SYSENTER/SYSEXIT instructions
+ * on 32-bit kernels:
+ */
 #ifdef CONFIG_X86_32
 void enable_sep_cpu(void)
 {
-       int cpu = get_cpu();
-       struct tss_struct *tss = &per_cpu(init_tss, cpu);
+       struct tss_struct *tss;
+       int cpu;
 
-       if (!boot_cpu_has(X86_FEATURE_SEP)) {
-               put_cpu();
-               return;
-       }
+       cpu = get_cpu();
+       tss = &per_cpu(cpu_tss, cpu);
+
+       if (!boot_cpu_has(X86_FEATURE_SEP))
+               goto out;
+
+       /*
+        * We cache MSR_IA32_SYSENTER_CS's value in the TSS's ss1 field --
+        * see the big comment in struct x86_hw_tss's definition.
+        */
 
        tss->x86_tss.ss1 = __KERNEL_CS;
-       tss->x86_tss.sp1 = sizeof(struct tss_struct) + (unsigned long) tss;
-       wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
-       wrmsr(MSR_IA32_SYSENTER_ESP, tss->x86_tss.sp1, 0);
-       wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) ia32_sysenter_target, 0);
+       wrmsr(MSR_IA32_SYSENTER_CS, tss->x86_tss.ss1, 0);
+
+       wrmsr(MSR_IA32_SYSENTER_ESP,
+             (unsigned long)tss + offsetofend(struct tss_struct, SYSENTER_stack),
+             0);
+
+       wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long)ia32_sysenter_target, 0);
+
+out:
        put_cpu();
 }
 #endif
@@ -1118,7 +1156,7 @@ static __init int setup_disablecpuid(char *arg)
 __setup("clearcpuid=", setup_disablecpuid);
 
 DEFINE_PER_CPU(unsigned long, kernel_stack) =
-       (unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE;
+       (unsigned long)&init_thread_union + THREAD_SIZE;
 EXPORT_PER_CPU_SYMBOL(kernel_stack);
 
 #ifdef CONFIG_X86_64
@@ -1130,8 +1168,8 @@ DEFINE_PER_CPU_FIRST(union irq_stack_union,
                     irq_stack_union) __aligned(PAGE_SIZE) __visible;
 
 /*
- * The following four percpu variables are hot.  Align current_task to
- * cacheline size such that all four fall in the same cacheline.
+ * The following percpu variables are hot.  Align current_task to
+ * cacheline size such that they fall in the same cacheline.
  */
 DEFINE_PER_CPU(struct task_struct *, current_task) ____cacheline_aligned =
        &init_task;
@@ -1171,10 +1209,23 @@ void syscall_init(void)
         */
        wrmsrl(MSR_STAR,  ((u64)__USER32_CS)<<48  | ((u64)__KERNEL_CS)<<32);
        wrmsrl(MSR_LSTAR, system_call);
-       wrmsrl(MSR_CSTAR, ignore_sysret);
 
 #ifdef CONFIG_IA32_EMULATION
-       syscall32_cpu_init();
+       wrmsrl(MSR_CSTAR, ia32_cstar_target);
+       /*
+        * This only works on Intel CPUs.
+        * On AMD CPUs these MSRs are 32-bit, CPU truncates MSR_IA32_SYSENTER_EIP.
+        * This does not cause SYSENTER to jump to the wrong location, because
+        * AMD doesn't allow SYSENTER in long mode (either 32- or 64-bit).
+        */
+       wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
+       wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
+       wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)ia32_sysenter_target);
+#else
+       wrmsrl(MSR_CSTAR, ignore_sysret);
+       wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG);
+       wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
+       wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
 #endif
 
        /* Flags to clear on syscall */
@@ -1226,6 +1277,15 @@ DEFINE_PER_CPU(int, __preempt_count) = INIT_PREEMPT_COUNT;
 EXPORT_PER_CPU_SYMBOL(__preempt_count);
 DEFINE_PER_CPU(struct task_struct *, fpu_owner_task);
 
+/*
+ * On x86_32, vm86 modifies tss.sp0, so sp0 isn't a reliable way to find
+ * the top of the kernel stack.  Use an extra percpu variable to track the
+ * top of the kernel stack directly.
+ */
+DEFINE_PER_CPU(unsigned long, cpu_current_top_of_stack) =
+       (unsigned long)&init_thread_union + THREAD_SIZE;
+EXPORT_PER_CPU_SYMBOL(cpu_current_top_of_stack);
+
 #ifdef CONFIG_CC_STACKPROTECTOR
 DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);
 #endif
@@ -1307,7 +1367,7 @@ void cpu_init(void)
         */
        load_ucode_ap();
 
-       t = &per_cpu(init_tss, cpu);
+       t = &per_cpu(cpu_tss, cpu);
        oist = &per_cpu(orig_ist, cpu);
 
 #ifdef CONFIG_NUMA
@@ -1391,7 +1451,7 @@ void cpu_init(void)
 {
        int cpu = smp_processor_id();
        struct task_struct *curr = current;
-       struct tss_struct *t = &per_cpu(init_tss, cpu);
+       struct tss_struct *t = &per_cpu(cpu_tss, cpu);
        struct thread_struct *thread = &curr->thread;
 
        wait_for_master_cpu(cpu);
index 659643376dbf7d9d04b377e85ef04bf1e6bf1ada..edcb0e28c336d085d0ee1011793c98ba6f5a13ae 100644 (file)
@@ -7,16 +7,14 @@
  *     Andi Kleen / Andreas Herrmann   : CPUID4 emulation on AMD.
  */
 
-#include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/compiler.h>
+#include <linux/cacheinfo.h>
 #include <linux/cpu.h>
 #include <linux/sched.h>
+#include <linux/sysfs.h>
 #include <linux/pci.h>
 
 #include <asm/processor.h>
-#include <linux/smp.h>
 #include <asm/amd_nb.h>
 #include <asm/smp.h>
 
@@ -116,10 +114,10 @@ static const struct _cache_table cache_table[] =
 
 
 enum _cache_type {
-       CACHE_TYPE_NULL = 0,
-       CACHE_TYPE_DATA = 1,
-       CACHE_TYPE_INST = 2,
-       CACHE_TYPE_UNIFIED = 3
+       CTYPE_NULL = 0,
+       CTYPE_DATA = 1,
+       CTYPE_INST = 2,
+       CTYPE_UNIFIED = 3
 };
 
 union _cpuid4_leaf_eax {
@@ -159,11 +157,6 @@ struct _cpuid4_info_regs {
        struct amd_northbridge *nb;
 };
 
-struct _cpuid4_info {
-       struct _cpuid4_info_regs base;
-       DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
-};
-
 unsigned short                 num_cache_leaves;
 
 /* AMD doesn't have CPUID4. Emulate it here to report the same
@@ -220,6 +213,13 @@ static const unsigned short assocs[] = {
 static const unsigned char levels[] = { 1, 1, 2, 3 };
 static const unsigned char types[] = { 1, 2, 3, 3 };
 
+static const enum cache_type cache_type_map[] = {
+       [CTYPE_NULL] = CACHE_TYPE_NOCACHE,
+       [CTYPE_DATA] = CACHE_TYPE_DATA,
+       [CTYPE_INST] = CACHE_TYPE_INST,
+       [CTYPE_UNIFIED] = CACHE_TYPE_UNIFIED,
+};
+
 static void
 amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
                     union _cpuid4_leaf_ebx *ebx,
@@ -291,14 +291,8 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
                (ebx->split.ways_of_associativity + 1) - 1;
 }
 
-struct _cache_attr {
-       struct attribute attr;
-       ssize_t (*show)(struct _cpuid4_info *, char *, unsigned int);
-       ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count,
-                        unsigned int);
-};
-
 #if defined(CONFIG_AMD_NB) && defined(CONFIG_SYSFS)
+
 /*
  * L3 cache descriptors
  */
@@ -325,20 +319,6 @@ static void amd_calc_l3_indices(struct amd_northbridge *nb)
        l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1;
 }
 
-static void amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, int index)
-{
-       int node;
-
-       /* only for L3, and not in virtualized environments */
-       if (index < 3)
-               return;
-
-       node = amd_get_nb_id(smp_processor_id());
-       this_leaf->nb = node_to_amd_nb(node);
-       if (this_leaf->nb && !this_leaf->nb->l3_cache.indices)
-               amd_calc_l3_indices(this_leaf->nb);
-}
-
 /*
  * check whether a slot used for disabling an L3 index is occupied.
  * @l3: L3 cache descriptor
@@ -359,15 +339,13 @@ int amd_get_l3_disable_slot(struct amd_northbridge *nb, unsigned slot)
        return -1;
 }
 
-static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
+static ssize_t show_cache_disable(struct cacheinfo *this_leaf, char *buf,
                                  unsigned int slot)
 {
        int index;
+       struct amd_northbridge *nb = this_leaf->priv;
 
-       if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
-               return -EINVAL;
-
-       index = amd_get_l3_disable_slot(this_leaf->base.nb, slot);
+       index = amd_get_l3_disable_slot(nb, slot);
        if (index >= 0)
                return sprintf(buf, "%d\n", index);
 
@@ -376,9 +354,10 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
 
 #define SHOW_CACHE_DISABLE(slot)                                       \
 static ssize_t                                                         \
-show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf,   \
-                         unsigned int cpu)                             \
+cache_disable_##slot##_show(struct device *dev,                                \
+                           struct device_attribute *attr, char *buf)   \
 {                                                                      \
+       struct cacheinfo *this_leaf = dev_get_drvdata(dev);             \
        return show_cache_disable(this_leaf, buf, slot);                \
 }
 SHOW_CACHE_DISABLE(0)
@@ -446,25 +425,23 @@ int amd_set_l3_disable_slot(struct amd_northbridge *nb, int cpu, unsigned slot,
        return 0;
 }
 
-static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
-                                 const char *buf, size_t count,
-                                 unsigned int slot)
+static ssize_t store_cache_disable(struct cacheinfo *this_leaf,
+                                  const char *buf, size_t count,
+                                  unsigned int slot)
 {
        unsigned long val = 0;
        int cpu, err = 0;
+       struct amd_northbridge *nb = this_leaf->priv;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
-               return -EINVAL;
-
-       cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
+       cpu = cpumask_first(&this_leaf->shared_cpu_map);
 
        if (kstrtoul(buf, 10, &val) < 0)
                return -EINVAL;
 
-       err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val);
+       err = amd_set_l3_disable_slot(nb, cpu, slot, val);
        if (err) {
                if (err == -EEXIST)
                        pr_warning("L3 slot %d in use/index already disabled!\n",
@@ -476,41 +453,36 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
 
 #define STORE_CACHE_DISABLE(slot)                                      \
 static ssize_t                                                         \
-store_cache_disable_##slot(struct _cpuid4_info *this_leaf,             \
-                          const char *buf, size_t count,               \
-                          unsigned int cpu)                            \
+cache_disable_##slot##_store(struct device *dev,                       \
+                            struct device_attribute *attr,             \
+                            const char *buf, size_t count)             \
 {                                                                      \
+       struct cacheinfo *this_leaf = dev_get_drvdata(dev);             \
        return store_cache_disable(this_leaf, buf, count, slot);        \
 }
 STORE_CACHE_DISABLE(0)
 STORE_CACHE_DISABLE(1)
 
-static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644,
-               show_cache_disable_0, store_cache_disable_0);
-static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
-               show_cache_disable_1, store_cache_disable_1);
-
-static ssize_t
-show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu)
+static ssize_t subcaches_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
 {
-       if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
-               return -EINVAL;
+       struct cacheinfo *this_leaf = dev_get_drvdata(dev);
+       int cpu = cpumask_first(&this_leaf->shared_cpu_map);
 
        return sprintf(buf, "%x\n", amd_get_subcaches(cpu));
 }
 
-static ssize_t
-store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count,
-               unsigned int cpu)
+static ssize_t subcaches_store(struct device *dev,
+                              struct device_attribute *attr,
+                              const char *buf, size_t count)
 {
+       struct cacheinfo *this_leaf = dev_get_drvdata(dev);
+       int cpu = cpumask_first(&this_leaf->shared_cpu_map);
        unsigned long val;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
-               return -EINVAL;
-
        if (kstrtoul(buf, 16, &val) < 0)
                return -EINVAL;
 
@@ -520,9 +492,92 @@ store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count,
        return count;
 }
 
-static struct _cache_attr subcaches =
-       __ATTR(subcaches, 0644, show_subcaches, store_subcaches);
+static DEVICE_ATTR_RW(cache_disable_0);
+static DEVICE_ATTR_RW(cache_disable_1);
+static DEVICE_ATTR_RW(subcaches);
+
+static umode_t
+cache_private_attrs_is_visible(struct kobject *kobj,
+                              struct attribute *attr, int unused)
+{
+       struct device *dev = kobj_to_dev(kobj);
+       struct cacheinfo *this_leaf = dev_get_drvdata(dev);
+       umode_t mode = attr->mode;
+
+       if (!this_leaf->priv)
+               return 0;
+
+       if ((attr == &dev_attr_subcaches.attr) &&
+           amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+               return mode;
+
+       if ((attr == &dev_attr_cache_disable_0.attr ||
+            attr == &dev_attr_cache_disable_1.attr) &&
+           amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
+               return mode;
+
+       return 0;
+}
+
+static struct attribute_group cache_private_group = {
+       .is_visible = cache_private_attrs_is_visible,
+};
+
+static void init_amd_l3_attrs(void)
+{
+       int n = 1;
+       static struct attribute **amd_l3_attrs;
+
+       if (amd_l3_attrs) /* already initialized */
+               return;
+
+       if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
+               n += 2;
+       if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+               n += 1;
+
+       amd_l3_attrs = kcalloc(n, sizeof(*amd_l3_attrs), GFP_KERNEL);
+       if (!amd_l3_attrs)
+               return;
+
+       n = 0;
+       if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) {
+               amd_l3_attrs[n++] = &dev_attr_cache_disable_0.attr;
+               amd_l3_attrs[n++] = &dev_attr_cache_disable_1.attr;
+       }
+       if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+               amd_l3_attrs[n++] = &dev_attr_subcaches.attr;
 
+       cache_private_group.attrs = amd_l3_attrs;
+}
+
+const struct attribute_group *
+cache_get_priv_group(struct cacheinfo *this_leaf)
+{
+       struct amd_northbridge *nb = this_leaf->priv;
+
+       if (this_leaf->level < 3 || !nb)
+               return NULL;
+
+       if (nb && nb->l3_cache.indices)
+               init_amd_l3_attrs();
+
+       return &cache_private_group;
+}
+
+static void amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, int index)
+{
+       int node;
+
+       /* only for L3, and not in virtualized environments */
+       if (index < 3)
+               return;
+
+       node = amd_get_nb_id(smp_processor_id());
+       this_leaf->nb = node_to_amd_nb(node);
+       if (this_leaf->nb && !this_leaf->nb->l3_cache.indices)
+               amd_calc_l3_indices(this_leaf->nb);
+}
 #else
 #define amd_init_l3_cache(x, y)
 #endif  /* CONFIG_AMD_NB && CONFIG_SYSFS */
@@ -546,7 +601,7 @@ cpuid4_cache_lookup_regs(int index, struct _cpuid4_info_regs *this_leaf)
                cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
        }
 
-       if (eax.split.type == CACHE_TYPE_NULL)
+       if (eax.split.type == CTYPE_NULL)
                return -EIO; /* better error ? */
 
        this_leaf->eax = eax;
@@ -575,7 +630,7 @@ static int find_num_cache_leaves(struct cpuinfo_x86 *c)
                /* Do cpuid(op) loop to find out num_cache_leaves */
                cpuid_count(op, i, &eax, &ebx, &ecx, &edx);
                cache_eax.full = eax;
-       } while (cache_eax.split.type != CACHE_TYPE_NULL);
+       } while (cache_eax.split.type != CTYPE_NULL);
        return i;
 }
 
@@ -626,9 +681,9 @@ unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c)
 
                        switch (this_leaf.eax.split.level) {
                        case 1:
-                               if (this_leaf.eax.split.type == CACHE_TYPE_DATA)
+                               if (this_leaf.eax.split.type == CTYPE_DATA)
                                        new_l1d = this_leaf.size/1024;
-                               else if (this_leaf.eax.split.type == CACHE_TYPE_INST)
+                               else if (this_leaf.eax.split.type == CTYPE_INST)
                                        new_l1i = this_leaf.size/1024;
                                break;
                        case 2:
@@ -747,55 +802,52 @@ unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c)
        return l2;
 }
 
-#ifdef CONFIG_SYSFS
-
-/* pointer to _cpuid4_info array (for each cache leaf) */
-static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info);
-#define CPUID4_INFO_IDX(x, y)  (&((per_cpu(ici_cpuid4_info, x))[y]))
-
-#ifdef CONFIG_SMP
-
-static int cache_shared_amd_cpu_map_setup(unsigned int cpu, int index)
+static int __cache_amd_cpumap_setup(unsigned int cpu, int index,
+                                   struct _cpuid4_info_regs *base)
 {
-       struct _cpuid4_info *this_leaf;
+       struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
+       struct cacheinfo *this_leaf;
        int i, sibling;
 
        if (cpu_has_topoext) {
                unsigned int apicid, nshared, first, last;
 
-               if (!per_cpu(ici_cpuid4_info, cpu))
-                       return 0;
-
-               this_leaf = CPUID4_INFO_IDX(cpu, index);
-               nshared = this_leaf->base.eax.split.num_threads_sharing + 1;
+               this_leaf = this_cpu_ci->info_list + index;
+               nshared = base->eax.split.num_threads_sharing + 1;
                apicid = cpu_data(cpu).apicid;
                first = apicid - (apicid % nshared);
                last = first + nshared - 1;
 
                for_each_online_cpu(i) {
+                       this_cpu_ci = get_cpu_cacheinfo(i);
+                       if (!this_cpu_ci->info_list)
+                               continue;
+
                        apicid = cpu_data(i).apicid;
                        if ((apicid < first) || (apicid > last))
                                continue;
-                       if (!per_cpu(ici_cpuid4_info, i))
-                               continue;
-                       this_leaf = CPUID4_INFO_IDX(i, index);
+
+                       this_leaf = this_cpu_ci->info_list + index;
 
                        for_each_online_cpu(sibling) {
                                apicid = cpu_data(sibling).apicid;
                                if ((apicid < first) || (apicid > last))
                                        continue;
-                               set_bit(sibling, this_leaf->shared_cpu_map);
+                               cpumask_set_cpu(sibling,
+                                               &this_leaf->shared_cpu_map);
                        }
                }
        } else if (index == 3) {
                for_each_cpu(i, cpu_llc_shared_mask(cpu)) {
-                       if (!per_cpu(ici_cpuid4_info, i))
+                       this_cpu_ci = get_cpu_cacheinfo(i);
+                       if (!this_cpu_ci->info_list)
                                continue;
-                       this_leaf = CPUID4_INFO_IDX(i, index);
+                       this_leaf = this_cpu_ci->info_list + index;
                        for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) {
                                if (!cpu_online(sibling))
                                        continue;
-                               set_bit(sibling, this_leaf->shared_cpu_map);
+                               cpumask_set_cpu(sibling,
+                                               &this_leaf->shared_cpu_map);
                        }
                }
        } else
@@ -804,457 +856,86 @@ static int cache_shared_amd_cpu_map_setup(unsigned int cpu, int index)
        return 1;
 }
 
-static void cache_shared_cpu_map_setup(unsigned int cpu, int index)
+static void __cache_cpumap_setup(unsigned int cpu, int index,
+                                struct _cpuid4_info_regs *base)
 {
-       struct _cpuid4_info *this_leaf, *sibling_leaf;
+       struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
+       struct cacheinfo *this_leaf, *sibling_leaf;
        unsigned long num_threads_sharing;
        int index_msb, i;
        struct cpuinfo_x86 *c = &cpu_data(cpu);
 
        if (c->x86_vendor == X86_VENDOR_AMD) {
-               if (cache_shared_amd_cpu_map_setup(cpu, index))
+               if (__cache_amd_cpumap_setup(cpu, index, base))
                        return;
        }
 
-       this_leaf = CPUID4_INFO_IDX(cpu, index);
-       num_threads_sharing = 1 + this_leaf->base.eax.split.num_threads_sharing;
+       this_leaf = this_cpu_ci->info_list + index;
+       num_threads_sharing = 1 + base->eax.split.num_threads_sharing;
 
+       cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map);
        if (num_threads_sharing == 1)
-               cpumask_set_cpu(cpu, to_cpumask(this_leaf->shared_cpu_map));
-       else {
-               index_msb = get_count_order(num_threads_sharing);
-
-               for_each_online_cpu(i) {
-                       if (cpu_data(i).apicid >> index_msb ==
-                           c->apicid >> index_msb) {
-                               cpumask_set_cpu(i,
-                                       to_cpumask(this_leaf->shared_cpu_map));
-                               if (i != cpu && per_cpu(ici_cpuid4_info, i))  {
-                                       sibling_leaf =
-                                               CPUID4_INFO_IDX(i, index);
-                                       cpumask_set_cpu(cpu, to_cpumask(
-                                               sibling_leaf->shared_cpu_map));
-                               }
-                       }
-               }
-       }
-}
-static void cache_remove_shared_cpu_map(unsigned int cpu, int index)
-{
-       struct _cpuid4_info     *this_leaf, *sibling_leaf;
-       int sibling;
-
-       this_leaf = CPUID4_INFO_IDX(cpu, index);
-       for_each_cpu(sibling, to_cpumask(this_leaf->shared_cpu_map)) {
-               sibling_leaf = CPUID4_INFO_IDX(sibling, index);
-               cpumask_clear_cpu(cpu,
-                                 to_cpumask(sibling_leaf->shared_cpu_map));
-       }
-}
-#else
-static void cache_shared_cpu_map_setup(unsigned int cpu, int index)
-{
-}
-
-static void cache_remove_shared_cpu_map(unsigned int cpu, int index)
-{
-}
-#endif
-
-static void free_cache_attributes(unsigned int cpu)
-{
-       int i;
-
-       for (i = 0; i < num_cache_leaves; i++)
-               cache_remove_shared_cpu_map(cpu, i);
-
-       kfree(per_cpu(ici_cpuid4_info, cpu));
-       per_cpu(ici_cpuid4_info, cpu) = NULL;
-}
-
-static void get_cpu_leaves(void *_retval)
-{
-       int j, *retval = _retval, cpu = smp_processor_id();
+               return;
 
-       /* Do cpuid and store the results */
-       for (j = 0; j < num_cache_leaves; j++) {
-               struct _cpuid4_info *this_leaf = CPUID4_INFO_IDX(cpu, j);
+       index_msb = get_count_order(num_threads_sharing);
 
-               *retval = cpuid4_cache_lookup_regs(j, &this_leaf->base);
-               if (unlikely(*retval < 0)) {
-                       int i;
+       for_each_online_cpu(i)
+               if (cpu_data(i).apicid >> index_msb == c->apicid >> index_msb) {
+                       struct cpu_cacheinfo *sib_cpu_ci = get_cpu_cacheinfo(i);
 
-                       for (i = 0; i < j; i++)
-                               cache_remove_shared_cpu_map(cpu, i);
-                       break;
+                       if (i == cpu || !sib_cpu_ci->info_list)
+                               continue;/* skip if itself or no cacheinfo */
+                       sibling_leaf = sib_cpu_ci->info_list + index;
+                       cpumask_set_cpu(i, &this_leaf->shared_cpu_map);
+                       cpumask_set_cpu(cpu, &sibling_leaf->shared_cpu_map);
                }
-               cache_shared_cpu_map_setup(cpu, j);
-       }
 }
 
-static int detect_cache_attributes(unsigned int cpu)
+static void ci_leaf_init(struct cacheinfo *this_leaf,
+                        struct _cpuid4_info_regs *base)
 {
-       int                     retval;
-
-       if (num_cache_leaves == 0)
-               return -ENOENT;
-
-       per_cpu(ici_cpuid4_info, cpu) = kzalloc(
-           sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
-       if (per_cpu(ici_cpuid4_info, cpu) == NULL)
-               return -ENOMEM;
-
-       smp_call_function_single(cpu, get_cpu_leaves, &retval, true);
-       if (retval) {
-               kfree(per_cpu(ici_cpuid4_info, cpu));
-               per_cpu(ici_cpuid4_info, cpu) = NULL;
-       }
-
-       return retval;
+       this_leaf->level = base->eax.split.level;
+       this_leaf->type = cache_type_map[base->eax.split.type];
+       this_leaf->coherency_line_size =
+                               base->ebx.split.coherency_line_size + 1;
+       this_leaf->ways_of_associativity =
+                               base->ebx.split.ways_of_associativity + 1;
+       this_leaf->size = base->size;
+       this_leaf->number_of_sets = base->ecx.split.number_of_sets + 1;
+       this_leaf->physical_line_partition =
+                               base->ebx.split.physical_line_partition + 1;
+       this_leaf->priv = base->nb;
 }
 
-#include <linux/kobject.h>
-#include <linux/sysfs.h>
-#include <linux/cpu.h>
-
-/* pointer to kobject for cpuX/cache */
-static DEFINE_PER_CPU(struct kobject *, ici_cache_kobject);
-
-struct _index_kobject {
-       struct kobject kobj;
-       unsigned int cpu;
-       unsigned short index;
-};
-
-/* pointer to array of kobjects for cpuX/cache/indexY */
-static DEFINE_PER_CPU(struct _index_kobject *, ici_index_kobject);
-#define INDEX_KOBJECT_PTR(x, y)                (&((per_cpu(ici_index_kobject, x))[y]))
-
-#define show_one_plus(file_name, object, val)                          \
-static ssize_t show_##file_name(struct _cpuid4_info *this_leaf, char *buf, \
-                               unsigned int cpu)                       \
-{                                                                      \
-       return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \
-}
-
-show_one_plus(level, base.eax.split.level, 0);
-show_one_plus(coherency_line_size, base.ebx.split.coherency_line_size, 1);
-show_one_plus(physical_line_partition, base.ebx.split.physical_line_partition, 1);
-show_one_plus(ways_of_associativity, base.ebx.split.ways_of_associativity, 1);
-show_one_plus(number_of_sets, base.ecx.split.number_of_sets, 1);
-
-static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf,
-                        unsigned int cpu)
-{
-       return sprintf(buf, "%luK\n", this_leaf->base.size / 1024);
-}
-
-static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf,
-                                       int type, char *buf)
-{
-       const struct cpumask *mask = to_cpumask(this_leaf->shared_cpu_map);
-       int ret;
-
-       if (type)
-               ret = scnprintf(buf, PAGE_SIZE - 1, "%*pbl",
-                               cpumask_pr_args(mask));
-       else
-               ret = scnprintf(buf, PAGE_SIZE - 1, "%*pb",
-                               cpumask_pr_args(mask));
-       buf[ret++] = '\n';
-       buf[ret] = '\0';
-       return ret;
-}
-
-static inline ssize_t show_shared_cpu_map(struct _cpuid4_info *leaf, char *buf,
-                                         unsigned int cpu)
+static int __init_cache_level(unsigned int cpu)
 {
-       return show_shared_cpu_map_func(leaf, 0, buf);
-}
-
-static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf,
-                                          unsigned int cpu)
-{
-       return show_shared_cpu_map_func(leaf, 1, buf);
-}
+       struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
 
-static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf,
-                        unsigned int cpu)
-{
-       switch (this_leaf->base.eax.split.type) {
-       case CACHE_TYPE_DATA:
-               return sprintf(buf, "Data\n");
-       case CACHE_TYPE_INST:
-               return sprintf(buf, "Instruction\n");
-       case CACHE_TYPE_UNIFIED:
-               return sprintf(buf, "Unified\n");
-       default:
-               return sprintf(buf, "Unknown\n");
-       }
-}
-
-#define to_object(k)   container_of(k, struct _index_kobject, kobj)
-#define to_attr(a)     container_of(a, struct _cache_attr, attr)
-
-#define define_one_ro(_name) \
-static struct _cache_attr _name = \
-       __ATTR(_name, 0444, show_##_name, NULL)
-
-define_one_ro(level);
-define_one_ro(type);
-define_one_ro(coherency_line_size);
-define_one_ro(physical_line_partition);
-define_one_ro(ways_of_associativity);
-define_one_ro(number_of_sets);
-define_one_ro(size);
-define_one_ro(shared_cpu_map);
-define_one_ro(shared_cpu_list);
-
-static struct attribute *default_attrs[] = {
-       &type.attr,
-       &level.attr,
-       &coherency_line_size.attr,
-       &physical_line_partition.attr,
-       &ways_of_associativity.attr,
-       &number_of_sets.attr,
-       &size.attr,
-       &shared_cpu_map.attr,
-       &shared_cpu_list.attr,
-       NULL
-};
-
-#ifdef CONFIG_AMD_NB
-static struct attribute **amd_l3_attrs(void)
-{
-       static struct attribute **attrs;
-       int n;
-
-       if (attrs)
-               return attrs;
-
-       n = ARRAY_SIZE(default_attrs);
-
-       if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
-               n += 2;
-
-       if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
-               n += 1;
-
-       attrs = kzalloc(n * sizeof (struct attribute *), GFP_KERNEL);
-       if (attrs == NULL)
-               return attrs = default_attrs;
-
-       for (n = 0; default_attrs[n]; n++)
-               attrs[n] = default_attrs[n];
-
-       if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) {
-               attrs[n++] = &cache_disable_0.attr;
-               attrs[n++] = &cache_disable_1.attr;
-       }
-
-       if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
-               attrs[n++] = &subcaches.attr;
-
-       return attrs;
-}
-#endif
-
-static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
-{
-       struct _cache_attr *fattr = to_attr(attr);
-       struct _index_kobject *this_leaf = to_object(kobj);
-       ssize_t ret;
-
-       ret = fattr->show ?
-               fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
-                       buf, this_leaf->cpu) :
-               0;
-       return ret;
-}
-
-static ssize_t store(struct kobject *kobj, struct attribute *attr,
-                    const char *buf, size_t count)
-{
-       struct _cache_attr *fattr = to_attr(attr);
-       struct _index_kobject *this_leaf = to_object(kobj);
-       ssize_t ret;
-
-       ret = fattr->store ?
-               fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
-                       buf, count, this_leaf->cpu) :
-               0;
-       return ret;
-}
-
-static const struct sysfs_ops sysfs_ops = {
-       .show   = show,
-       .store  = store,
-};
-
-static struct kobj_type ktype_cache = {
-       .sysfs_ops      = &sysfs_ops,
-       .default_attrs  = default_attrs,
-};
-
-static struct kobj_type ktype_percpu_entry = {
-       .sysfs_ops      = &sysfs_ops,
-};
-
-static void cpuid4_cache_sysfs_exit(unsigned int cpu)
-{
-       kfree(per_cpu(ici_cache_kobject, cpu));
-       kfree(per_cpu(ici_index_kobject, cpu));
-       per_cpu(ici_cache_kobject, cpu) = NULL;
-       per_cpu(ici_index_kobject, cpu) = NULL;
-       free_cache_attributes(cpu);
-}
-
-static int cpuid4_cache_sysfs_init(unsigned int cpu)
-{
-       int err;
-
-       if (num_cache_leaves == 0)
+       if (!num_cache_leaves)
                return -ENOENT;
-
-       err = detect_cache_attributes(cpu);
-       if (err)
-               return err;
-
-       /* Allocate all required memory */
-       per_cpu(ici_cache_kobject, cpu) =
-               kzalloc(sizeof(struct kobject), GFP_KERNEL);
-       if (unlikely(per_cpu(ici_cache_kobject, cpu) == NULL))
-               goto err_out;
-
-       per_cpu(ici_index_kobject, cpu) = kzalloc(
-           sizeof(struct _index_kobject) * num_cache_leaves, GFP_KERNEL);
-       if (unlikely(per_cpu(ici_index_kobject, cpu) == NULL))
-               goto err_out;
-
+       if (!this_cpu_ci)
+               return -EINVAL;
+       this_cpu_ci->num_levels = 3;
+       this_cpu_ci->num_leaves = num_cache_leaves;
        return 0;
-
-err_out:
-       cpuid4_cache_sysfs_exit(cpu);
-       return -ENOMEM;
 }
 
-static DECLARE_BITMAP(cache_dev_map, NR_CPUS);
-
-/* Add/Remove cache interface for CPU device */
-static int cache_add_dev(struct device *dev)
+static int __populate_cache_leaves(unsigned int cpu)
 {
-       unsigned int cpu = dev->id;
-       unsigned long i, j;
-       struct _index_kobject *this_object;
-       struct _cpuid4_info   *this_leaf;
-       int retval;
-
-       retval = cpuid4_cache_sysfs_init(cpu);
-       if (unlikely(retval < 0))
-               return retval;
-
-       retval = kobject_init_and_add(per_cpu(ici_cache_kobject, cpu),
-                                     &ktype_percpu_entry,
-                                     &dev->kobj, "%s", "cache");
-       if (retval < 0) {
-               cpuid4_cache_sysfs_exit(cpu);
-               return retval;
-       }
+       unsigned int idx, ret;
+       struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
+       struct cacheinfo *this_leaf = this_cpu_ci->info_list;
+       struct _cpuid4_info_regs id4_regs = {};
 
-       for (i = 0; i < num_cache_leaves; i++) {
-               this_object = INDEX_KOBJECT_PTR(cpu, i);
-               this_object->cpu = cpu;
-               this_object->index = i;
-
-               this_leaf = CPUID4_INFO_IDX(cpu, i);
-
-               ktype_cache.default_attrs = default_attrs;
-#ifdef CONFIG_AMD_NB
-               if (this_leaf->base.nb)
-                       ktype_cache.default_attrs = amd_l3_attrs();
-#endif
-               retval = kobject_init_and_add(&(this_object->kobj),
-                                             &ktype_cache,
-                                             per_cpu(ici_cache_kobject, cpu),
-                                             "index%1lu", i);
-               if (unlikely(retval)) {
-                       for (j = 0; j < i; j++)
-                               kobject_put(&(INDEX_KOBJECT_PTR(cpu, j)->kobj));
-                       kobject_put(per_cpu(ici_cache_kobject, cpu));
-                       cpuid4_cache_sysfs_exit(cpu);
-                       return retval;
-               }
-               kobject_uevent(&(this_object->kobj), KOBJ_ADD);
+       for (idx = 0; idx < this_cpu_ci->num_leaves; idx++) {
+               ret = cpuid4_cache_lookup_regs(idx, &id4_regs);
+               if (ret)
+                       return ret;
+               ci_leaf_init(this_leaf++, &id4_regs);
+               __cache_cpumap_setup(cpu, idx, &id4_regs);
        }
-       cpumask_set_cpu(cpu, to_cpumask(cache_dev_map));
-
-       kobject_uevent(per_cpu(ici_cache_kobject, cpu), KOBJ_ADD);
        return 0;
 }
 
-static void cache_remove_dev(struct device *dev)
-{
-       unsigned int cpu = dev->id;
-       unsigned long i;
-
-       if (per_cpu(ici_cpuid4_info, cpu) == NULL)
-               return;
-       if (!cpumask_test_cpu(cpu, to_cpumask(cache_dev_map)))
-               return;
-       cpumask_clear_cpu(cpu, to_cpumask(cache_dev_map));
-
-       for (i = 0; i < num_cache_leaves; i++)
-               kobject_put(&(INDEX_KOBJECT_PTR(cpu, i)->kobj));
-       kobject_put(per_cpu(ici_cache_kobject, cpu));
-       cpuid4_cache_sysfs_exit(cpu);
-}
-
-static int cacheinfo_cpu_callback(struct notifier_block *nfb,
-                                 unsigned long action, void *hcpu)
-{
-       unsigned int cpu = (unsigned long)hcpu;
-       struct device *dev;
-
-       dev = get_cpu_device(cpu);
-       switch (action) {
-       case CPU_ONLINE:
-       case CPU_ONLINE_FROZEN:
-               cache_add_dev(dev);
-               break;
-       case CPU_DEAD:
-       case CPU_DEAD_FROZEN:
-               cache_remove_dev(dev);
-               break;
-       }
-       return NOTIFY_OK;
-}
-
-static struct notifier_block cacheinfo_cpu_notifier = {
-       .notifier_call = cacheinfo_cpu_callback,
-};
-
-static int __init cache_sysfs_init(void)
-{
-       int i, err = 0;
-
-       if (num_cache_leaves == 0)
-               return 0;
-
-       cpu_notifier_register_begin();
-       for_each_online_cpu(i) {
-               struct device *dev = get_cpu_device(i);
-
-               err = cache_add_dev(dev);
-               if (err)
-                       goto out;
-       }
-       __register_hotcpu_notifier(&cacheinfo_cpu_notifier);
-
-out:
-       cpu_notifier_register_done();
-       return err;
-}
-
-device_initcall(cache_sysfs_init);
-
-#endif
+DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
+DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)
diff --git a/arch/x86/kernel/cpu/intel_pt.h b/arch/x86/kernel/cpu/intel_pt.h
new file mode 100644 (file)
index 0000000..1c338b0
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Intel(R) Processor Trace PMU driver for perf
+ * Copyright (c) 2013-2014, 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.
+ *
+ * Intel PT is specified in the Intel Architecture Instruction Set Extensions
+ * Programming Reference:
+ * http://software.intel.com/en-us/intel-isa-extensions
+ */
+
+#ifndef __INTEL_PT_H__
+#define __INTEL_PT_H__
+
+/*
+ * Single-entry ToPA: when this close to region boundary, switch
+ * buffers to avoid losing data.
+ */
+#define TOPA_PMI_MARGIN 512
+
+/*
+ * Table of Physical Addresses bits
+ */
+enum topa_sz {
+       TOPA_4K = 0,
+       TOPA_8K,
+       TOPA_16K,
+       TOPA_32K,
+       TOPA_64K,
+       TOPA_128K,
+       TOPA_256K,
+       TOPA_512K,
+       TOPA_1MB,
+       TOPA_2MB,
+       TOPA_4MB,
+       TOPA_8MB,
+       TOPA_16MB,
+       TOPA_32MB,
+       TOPA_64MB,
+       TOPA_128MB,
+       TOPA_SZ_END,
+};
+
+static inline unsigned int sizes(enum topa_sz tsz)
+{
+       return 1 << (tsz + 12);
+};
+
+struct topa_entry {
+       u64     end     : 1;
+       u64     rsvd0   : 1;
+       u64     intr    : 1;
+       u64     rsvd1   : 1;
+       u64     stop    : 1;
+       u64     rsvd2   : 1;
+       u64     size    : 4;
+       u64     rsvd3   : 2;
+       u64     base    : 36;
+       u64     rsvd4   : 16;
+};
+
+#define TOPA_SHIFT 12
+#define PT_CPUID_LEAVES 2
+
+enum pt_capabilities {
+       PT_CAP_max_subleaf = 0,
+       PT_CAP_cr3_filtering,
+       PT_CAP_topa_output,
+       PT_CAP_topa_multiple_entries,
+       PT_CAP_payloads_lip,
+};
+
+struct pt_pmu {
+       struct pmu              pmu;
+       u32                     caps[4 * PT_CPUID_LEAVES];
+};
+
+/**
+ * struct pt_buffer - buffer configuration; one buffer per task_struct or
+ *             cpu, depending on perf event configuration
+ * @cpu:       cpu for per-cpu allocation
+ * @tables:    list of ToPA tables in this buffer
+ * @first:     shorthand for first topa table
+ * @last:      shorthand for last topa table
+ * @cur:       current topa table
+ * @nr_pages:  buffer size in pages
+ * @cur_idx:   current output region's index within @cur table
+ * @output_off:        offset within the current output region
+ * @data_size: running total of the amount of data in this buffer
+ * @lost:      if data was lost/truncated
+ * @head:      logical write offset inside the buffer
+ * @snapshot:  if this is for a snapshot/overwrite counter
+ * @stop_pos:  STOP topa entry in the buffer
+ * @intr_pos:  INT topa entry in the buffer
+ * @data_pages:        array of pages from perf
+ * @topa_index:        table of topa entries indexed by page offset
+ */
+struct pt_buffer {
+       int                     cpu;
+       struct list_head        tables;
+       struct topa             *first, *last, *cur;
+       unsigned int            cur_idx;
+       size_t                  output_off;
+       unsigned long           nr_pages;
+       local_t                 data_size;
+       local_t                 lost;
+       local64_t               head;
+       bool                    snapshot;
+       unsigned long           stop_pos, intr_pos;
+       void                    **data_pages;
+       struct topa_entry       *topa_index[0];
+};
+
+/**
+ * struct pt - per-cpu pt context
+ * @handle:    perf output handle
+ * @handle_nmi:        do handle PT PMI on this cpu, there's an active event
+ */
+struct pt {
+       struct perf_output_handle handle;
+       int                     handle_nmi;
+};
+
+#endif /* __INTEL_PT_H__ */
index 10b46906767fd4857389570322757fa89bbc8e6c..fe32074b865b1686ba9e0e2cdc3ccb5ebe99ddfe 100644 (file)
@@ -14,6 +14,7 @@ enum severity_level {
 };
 
 #define ATTR_LEN               16
+#define INITIAL_CHECK_INTERVAL 5 * 60 /* 5 minutes */
 
 /* One object for each MCE bank, shared by all CPUs */
 struct mce_bank {
@@ -23,20 +24,20 @@ struct mce_bank {
        char                    attrname[ATTR_LEN];     /* attribute name */
 };
 
-int mce_severity(struct mce *a, int tolerant, char **msg, bool is_excp);
+extern int (*mce_severity)(struct mce *a, int tolerant, char **msg, bool is_excp);
 struct dentry *mce_get_debugfs_dir(void);
 
 extern struct mce_bank *mce_banks;
 extern mce_banks_t mce_banks_ce_disabled;
 
 #ifdef CONFIG_X86_MCE_INTEL
-unsigned long mce_intel_adjust_timer(unsigned long interval);
-void mce_intel_cmci_poll(void);
+unsigned long cmci_intel_adjust_timer(unsigned long interval);
+bool mce_intel_cmci_poll(void);
 void mce_intel_hcpu_update(unsigned long cpu);
 void cmci_disable_bank(int bank);
 #else
-# define mce_intel_adjust_timer mce_adjust_timer_default
-static inline void mce_intel_cmci_poll(void) { }
+# define cmci_intel_adjust_timer mce_adjust_timer_default
+static inline bool mce_intel_cmci_poll(void) { return false; }
 static inline void mce_intel_hcpu_update(unsigned long cpu) { }
 static inline void cmci_disable_bank(int bank) { }
 #endif
index 8bb433043a7f6877beaa8b38ccb8ec9684069212..9c682c222071db1960ba848c24c76567306d0542 100644 (file)
@@ -186,7 +186,61 @@ static int error_context(struct mce *m)
        return ((m->cs & 3) == 3) ? IN_USER : IN_KERNEL;
 }
 
-int mce_severity(struct mce *m, int tolerant, char **msg, bool is_excp)
+/*
+ * See AMD Error Scope Hierarchy table in a newer BKDG. For example
+ * 49125_15h_Models_30h-3Fh_BKDG.pdf, section "RAS Features"
+ */
+static int mce_severity_amd(struct mce *m, int tolerant, char **msg, bool is_excp)
+{
+       enum context ctx = error_context(m);
+
+       /* Processor Context Corrupt, no need to fumble too much, die! */
+       if (m->status & MCI_STATUS_PCC)
+               return MCE_PANIC_SEVERITY;
+
+       if (m->status & MCI_STATUS_UC) {
+
+               /*
+                * On older systems where overflow_recov flag is not present, we
+                * should simply panic if an error overflow occurs. If
+                * overflow_recov flag is present and set, then software can try
+                * to at least kill process to prolong system operation.
+                */
+               if (mce_flags.overflow_recov) {
+                       /* software can try to contain */
+                       if (!(m->mcgstatus & MCG_STATUS_RIPV) && (ctx == IN_KERNEL))
+                               return MCE_PANIC_SEVERITY;
+
+                       /* kill current process */
+                       return MCE_AR_SEVERITY;
+               } else {
+                       /* at least one error was not logged */
+                       if (m->status & MCI_STATUS_OVER)
+                               return MCE_PANIC_SEVERITY;
+               }
+
+               /*
+                * For any other case, return MCE_UC_SEVERITY so that we log the
+                * error and exit #MC handler.
+                */
+               return MCE_UC_SEVERITY;
+       }
+
+       /*
+        * deferred error: poll handler catches these and adds to mce_ring so
+        * memory-failure can take recovery actions.
+        */
+       if (m->status & MCI_STATUS_DEFERRED)
+               return MCE_DEFERRED_SEVERITY;
+
+       /*
+        * corrected error: poll handler catches these and passes responsibility
+        * of decoding the error to EDAC
+        */
+       return MCE_KEEP_SEVERITY;
+}
+
+static int mce_severity_intel(struct mce *m, int tolerant, char **msg, bool is_excp)
 {
        enum exception excp = (is_excp ? EXCP_CONTEXT : NO_EXCP);
        enum context ctx = error_context(m);
@@ -216,6 +270,16 @@ int mce_severity(struct mce *m, int tolerant, char **msg, bool is_excp)
        }
 }
 
+/* Default to mce_severity_intel */
+int (*mce_severity)(struct mce *m, int tolerant, char **msg, bool is_excp) =
+                   mce_severity_intel;
+
+void __init mcheck_vendor_init_severity(void)
+{
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+               mce_severity = mce_severity_amd;
+}
+
 #ifdef CONFIG_DEBUG_FS
 static void *s_start(struct seq_file *f, loff_t *pos)
 {
index 3c036cb4a370cad399cac636f97840b40c62bd4d..e535533d5ab89313ba51937ad8dd5740413f119e 100644 (file)
@@ -60,11 +60,12 @@ static DEFINE_MUTEX(mce_chrdev_read_mutex);
 #define CREATE_TRACE_POINTS
 #include <trace/events/mce.h>
 
-#define SPINUNIT 100   /* 100ns */
+#define SPINUNIT               100     /* 100ns */
 
 DEFINE_PER_CPU(unsigned, mce_exception_count);
 
 struct mce_bank *mce_banks __read_mostly;
+struct mce_vendor_flags mce_flags __read_mostly;
 
 struct mca_config mca_cfg __read_mostly = {
        .bootlog  = -1,
@@ -89,9 +90,6 @@ static DECLARE_WAIT_QUEUE_HEAD(mce_chrdev_wait);
 static DEFINE_PER_CPU(struct mce, mces_seen);
 static int                     cpu_missing;
 
-/* CMCI storm detection filter */
-static DEFINE_PER_CPU(unsigned long, mce_polled_error);
-
 /*
  * MCA banks polled by the period polling timer for corrected events.
  * With Intel CMCI, this only has MCA banks which do not support CMCI (if any).
@@ -622,8 +620,9 @@ DEFINE_PER_CPU(unsigned, mce_poll_count);
  * is already totally * confused. In this case it's likely it will
  * not fully execute the machine check handler either.
  */
-void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
+bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
 {
+       bool error_logged = false;
        struct mce m;
        int severity;
        int i;
@@ -646,7 +645,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
                if (!(m.status & MCI_STATUS_VAL))
                        continue;
 
-               this_cpu_write(mce_polled_error, 1);
+
                /*
                 * Uncorrected or signalled events are handled by the exception
                 * handler when it is enabled, so don't process those here.
@@ -679,8 +678,10 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
                 * Don't get the IP here because it's unlikely to
                 * have anything to do with the actual error location.
                 */
-               if (!(flags & MCP_DONTLOG) && !mca_cfg.dont_log_ce)
+               if (!(flags & MCP_DONTLOG) && !mca_cfg.dont_log_ce) {
+                       error_logged = true;
                        mce_log(&m);
+               }
 
                /*
                 * Clear state for this bank.
@@ -694,6 +695,8 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
         */
 
        sync_core();
+
+       return error_logged;
 }
 EXPORT_SYMBOL_GPL(machine_check_poll);
 
@@ -813,7 +816,7 @@ static void mce_reign(void)
         * other CPUs.
         */
        if (m && global_worst >= MCE_PANIC_SEVERITY && mca_cfg.tolerant < 3)
-               mce_panic("Fatal Machine check", m, msg);
+               mce_panic("Fatal machine check", m, msg);
 
        /*
         * For UC somewhere we let the CPU who detects it handle it.
@@ -826,7 +829,7 @@ static void mce_reign(void)
         * source or one CPU is hung. Panic.
         */
        if (global_worst <= MCE_KEEP_SEVERITY && mca_cfg.tolerant < 3)
-               mce_panic("Machine check from unknown source", NULL, NULL);
+               mce_panic("Fatal machine check from unknown source", NULL, NULL);
 
        /*
         * Now clear all the mces_seen so that they don't reappear on
@@ -1258,7 +1261,7 @@ void mce_log_therm_throt_event(__u64 status)
  * poller finds an MCE, poll 2x faster.  When the poller finds no more
  * errors, poll 2x slower (up to check_interval seconds).
  */
-static unsigned long check_interval = 5 * 60; /* 5 minutes */
+static unsigned long check_interval = INITIAL_CHECK_INTERVAL;
 
 static DEFINE_PER_CPU(unsigned long, mce_next_interval); /* in jiffies */
 static DEFINE_PER_CPU(struct timer_list, mce_timer);
@@ -1268,49 +1271,57 @@ static unsigned long mce_adjust_timer_default(unsigned long interval)
        return interval;
 }
 
-static unsigned long (*mce_adjust_timer)(unsigned long interval) =
-       mce_adjust_timer_default;
+static unsigned long (*mce_adjust_timer)(unsigned long interval) = mce_adjust_timer_default;
 
-static int cmc_error_seen(void)
+static void __restart_timer(struct timer_list *t, unsigned long interval)
 {
-       unsigned long *v = this_cpu_ptr(&mce_polled_error);
+       unsigned long when = jiffies + interval;
+       unsigned long flags;
+
+       local_irq_save(flags);
 
-       return test_and_clear_bit(0, v);
+       if (timer_pending(t)) {
+               if (time_before(when, t->expires))
+                       mod_timer_pinned(t, when);
+       } else {
+               t->expires = round_jiffies(when);
+               add_timer_on(t, smp_processor_id());
+       }
+
+       local_irq_restore(flags);
 }
 
 static void mce_timer_fn(unsigned long data)
 {
        struct timer_list *t = this_cpu_ptr(&mce_timer);
+       int cpu = smp_processor_id();
        unsigned long iv;
-       int notify;
 
-       WARN_ON(smp_processor_id() != data);
+       WARN_ON(cpu != data);
+
+       iv = __this_cpu_read(mce_next_interval);
 
        if (mce_available(this_cpu_ptr(&cpu_info))) {
-               machine_check_poll(MCP_TIMESTAMP,
-                               this_cpu_ptr(&mce_poll_banks));
-               mce_intel_cmci_poll();
+               machine_check_poll(MCP_TIMESTAMP, this_cpu_ptr(&mce_poll_banks));
+
+               if (mce_intel_cmci_poll()) {
+                       iv = mce_adjust_timer(iv);
+                       goto done;
+               }
        }
 
        /*
-        * Alert userspace if needed.  If we logged an MCE, reduce the
-        * polling interval, otherwise increase the polling interval.
+        * Alert userspace if needed. If we logged an MCE, reduce the polling
+        * interval, otherwise increase the polling interval.
         */
-       iv = __this_cpu_read(mce_next_interval);
-       notify = mce_notify_irq();
-       notify |= cmc_error_seen();
-       if (notify) {
+       if (mce_notify_irq())
                iv = max(iv / 2, (unsigned long) HZ/100);
-       } else {
+       else
                iv = min(iv * 2, round_jiffies_relative(check_interval * HZ));
-               iv = mce_adjust_timer(iv);
-       }
+
+done:
        __this_cpu_write(mce_next_interval, iv);
-       /* Might have become 0 after CMCI storm subsided */
-       if (iv) {
-               t->expires = jiffies + iv;
-               add_timer_on(t, smp_processor_id());
-       }
+       __restart_timer(t, iv);
 }
 
 /*
@@ -1319,16 +1330,10 @@ static void mce_timer_fn(unsigned long data)
 void mce_timer_kick(unsigned long interval)
 {
        struct timer_list *t = this_cpu_ptr(&mce_timer);
-       unsigned long when = jiffies + interval;
        unsigned long iv = __this_cpu_read(mce_next_interval);
 
-       if (timer_pending(t)) {
-               if (time_before(when, t->expires))
-                       mod_timer_pinned(t, when);
-       } else {
-               t->expires = round_jiffies(when);
-               add_timer_on(t, smp_processor_id());
-       }
+       __restart_timer(t, interval);
+
        if (interval < iv)
                __this_cpu_write(mce_next_interval, interval);
 }
@@ -1525,45 +1530,46 @@ static int __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
                 * Various K7s with broken bank 0 around. Always disable
                 * by default.
                 */
-                if (c->x86 == 6 && cfg->banks > 0)
+               if (c->x86 == 6 && cfg->banks > 0)
                        mce_banks[0].ctl = 0;
 
-                /*
-                 * Turn off MC4_MISC thresholding banks on those models since
-                 * they're not supported there.
-                 */
-                if (c->x86 == 0x15 &&
-                    (c->x86_model >= 0x10 && c->x86_model <= 0x1f)) {
-                        int i;
-                        u64 val, hwcr;
-                        bool need_toggle;
-                        u32 msrs[] = {
+               /*
+                * overflow_recov is supported for F15h Models 00h-0fh
+                * even though we don't have a CPUID bit for it.
+                */
+               if (c->x86 == 0x15 && c->x86_model <= 0xf)
+                       mce_flags.overflow_recov = 1;
+
+               /*
+                * Turn off MC4_MISC thresholding banks on those models since
+                * they're not supported there.
+                */
+               if (c->x86 == 0x15 &&
+                   (c->x86_model >= 0x10 && c->x86_model <= 0x1f)) {
+                       int i;
+                       u64 hwcr;
+                       bool need_toggle;
+                       u32 msrs[] = {
                                0x00000413, /* MC4_MISC0 */
                                0xc0000408, /* MC4_MISC1 */
-                        };
+                       };
 
-                        rdmsrl(MSR_K7_HWCR, hwcr);
+                       rdmsrl(MSR_K7_HWCR, hwcr);
 
-                        /* McStatusWrEn has to be set */
-                        need_toggle = !(hwcr & BIT(18));
+                       /* McStatusWrEn has to be set */
+                       need_toggle = !(hwcr & BIT(18));
 
-                        if (need_toggle)
-                                wrmsrl(MSR_K7_HWCR, hwcr | BIT(18));
+                       if (need_toggle)
+                               wrmsrl(MSR_K7_HWCR, hwcr | BIT(18));
 
-                        for (i = 0; i < ARRAY_SIZE(msrs); i++) {
-                                rdmsrl(msrs[i], val);
+                       /* Clear CntP bit safely */
+                       for (i = 0; i < ARRAY_SIZE(msrs); i++)
+                               msr_clear_bit(msrs[i], 62);
 
-                                /* CntP bit set? */
-                                if (val & BIT_64(62)) {
-                                       val &= ~BIT_64(62);
-                                       wrmsrl(msrs[i], val);
-                                }
-                        }
-
-                        /* restore old settings */
-                        if (need_toggle)
-                                wrmsrl(MSR_K7_HWCR, hwcr);
-                }
+                       /* restore old settings */
+                       if (need_toggle)
+                               wrmsrl(MSR_K7_HWCR, hwcr);
+               }
        }
 
        if (c->x86_vendor == X86_VENDOR_INTEL) {
@@ -1629,10 +1635,11 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
        switch (c->x86_vendor) {
        case X86_VENDOR_INTEL:
                mce_intel_feature_init(c);
-               mce_adjust_timer = mce_intel_adjust_timer;
+               mce_adjust_timer = cmci_intel_adjust_timer;
                break;
        case X86_VENDOR_AMD:
                mce_amd_feature_init(c);
+               mce_flags.overflow_recov = cpuid_ebx(0x80000007) & 0x1;
                break;
        default:
                break;
@@ -2017,6 +2024,7 @@ __setup("mce", mcheck_enable);
 int __init mcheck_init(void)
 {
        mcheck_intel_therm_init();
+       mcheck_vendor_init_severity();
 
        return 0;
 }
index f1c3769bbd6433344968bf5f78ad223170ef6878..55ad9b37cae853ce0d50f193dc7eb82a49207fee 100644 (file)
@@ -79,7 +79,7 @@ static inline bool is_shared_bank(int bank)
        return (bank == 4);
 }
 
-static const char * const bank4_names(struct threshold_block *b)
+static const char *bank4_names(const struct threshold_block *b)
 {
        switch (b->address) {
        /* MSR4_MISC0 */
@@ -250,6 +250,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
                        if (!b.interrupt_capable)
                                goto init;
 
+                       b.interrupt_enable = 1;
                        new     = (high & MASK_LVTOFF_HI) >> 20;
                        offset  = setup_APIC_mce(offset, new);
 
@@ -322,6 +323,8 @@ static void amd_threshold_interrupt(void)
 log:
        mce_setup(&m);
        rdmsrl(MSR_IA32_MCx_STATUS(bank), m.status);
+       if (!(m.status & MCI_STATUS_VAL))
+               return;
        m.misc = ((u64)high << 32) | low;
        m.bank = bank;
        mce_log(&m);
@@ -497,10 +500,12 @@ static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
        b->interrupt_capable    = lvt_interrupt_supported(bank, high);
        b->threshold_limit      = THRESHOLD_MAX;
 
-       if (b->interrupt_capable)
+       if (b->interrupt_capable) {
                threshold_ktype.default_attrs[2] = &interrupt_enable.attr;
-       else
+               b->interrupt_enable = 1;
+       } else {
                threshold_ktype.default_attrs[2] = NULL;
+       }
 
        INIT_LIST_HEAD(&b->miscj);
 
index b3c97bafc1238fedd30f1ec0a3bab2ba7ee05cb8..b4a41cf030edab7dbfae7dc67560ba63eabc2309 100644 (file)
  */
 static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned);
 
+/*
+ * CMCI storm detection backoff counter
+ *
+ * During storm, we reset this counter to INITIAL_CHECK_INTERVAL in case we've
+ * encountered an error. If not, we decrement it by one. We signal the end of
+ * the CMCI storm when it reaches 0.
+ */
+static DEFINE_PER_CPU(int, cmci_backoff_cnt);
+
 /*
  * cmci_discover_lock protects against parallel discovery attempts
  * which could race against each other.
@@ -46,7 +55,7 @@ static DEFINE_RAW_SPINLOCK(cmci_discover_lock);
 
 #define CMCI_THRESHOLD         1
 #define CMCI_POLL_INTERVAL     (30 * HZ)
-#define CMCI_STORM_INTERVAL    (1 * HZ)
+#define CMCI_STORM_INTERVAL    (HZ)
 #define CMCI_STORM_THRESHOLD   15
 
 static DEFINE_PER_CPU(unsigned long, cmci_time_stamp);
@@ -82,11 +91,21 @@ static int cmci_supported(int *banks)
        return !!(cap & MCG_CMCI_P);
 }
 
-void mce_intel_cmci_poll(void)
+bool mce_intel_cmci_poll(void)
 {
        if (__this_cpu_read(cmci_storm_state) == CMCI_STORM_NONE)
-               return;
-       machine_check_poll(MCP_TIMESTAMP, this_cpu_ptr(&mce_banks_owned));
+               return false;
+
+       /*
+        * Reset the counter if we've logged an error in the last poll
+        * during the storm.
+        */
+       if (machine_check_poll(MCP_TIMESTAMP, this_cpu_ptr(&mce_banks_owned)))
+               this_cpu_write(cmci_backoff_cnt, INITIAL_CHECK_INTERVAL);
+       else
+               this_cpu_dec(cmci_backoff_cnt);
+
+       return true;
 }
 
 void mce_intel_hcpu_update(unsigned long cpu)
@@ -97,31 +116,32 @@ void mce_intel_hcpu_update(unsigned long cpu)
        per_cpu(cmci_storm_state, cpu) = CMCI_STORM_NONE;
 }
 
-unsigned long mce_intel_adjust_timer(unsigned long interval)
+unsigned long cmci_intel_adjust_timer(unsigned long interval)
 {
-       int r;
-
-       if (interval < CMCI_POLL_INTERVAL)
-               return interval;
+       if ((this_cpu_read(cmci_backoff_cnt) > 0) &&
+           (__this_cpu_read(cmci_storm_state) == CMCI_STORM_ACTIVE)) {
+               mce_notify_irq();
+               return CMCI_STORM_INTERVAL;
+       }
 
        switch (__this_cpu_read(cmci_storm_state)) {
        case CMCI_STORM_ACTIVE:
+
                /*
                 * We switch back to interrupt mode once the poll timer has
-                * silenced itself. That means no events recorded and the
-                * timer interval is back to our poll interval.
+                * silenced itself. That means no events recorded and the timer
+                * interval is back to our poll interval.
                 */
                __this_cpu_write(cmci_storm_state, CMCI_STORM_SUBSIDED);
-               r = atomic_sub_return(1, &cmci_storm_on_cpus);
-               if (r == 0)
+               if (!atomic_sub_return(1, &cmci_storm_on_cpus))
                        pr_notice("CMCI storm subsided: switching to interrupt mode\n");
+
                /* FALLTHROUGH */
 
        case CMCI_STORM_SUBSIDED:
                /*
-                * We wait for all cpus to go back to SUBSIDED
-                * state. When that happens we switch back to
-                * interrupt mode.
+                * We wait for all CPUs to go back to SUBSIDED state. When that
+                * happens we switch back to interrupt mode.
                 */
                if (!atomic_read(&cmci_storm_on_cpus)) {
                        __this_cpu_write(cmci_storm_state, CMCI_STORM_NONE);
@@ -130,10 +150,8 @@ unsigned long mce_intel_adjust_timer(unsigned long interval)
                }
                return CMCI_POLL_INTERVAL;
        default:
-               /*
-                * We have shiny weather. Let the poll do whatever it
-                * thinks.
-                */
+
+               /* We have shiny weather. Let the poll do whatever it thinks. */
                return interval;
        }
 }
@@ -178,7 +196,8 @@ static bool cmci_storm_detect(void)
        cmci_storm_disable_banks();
        __this_cpu_write(cmci_storm_state, CMCI_STORM_ACTIVE);
        r = atomic_add_return(1, &cmci_storm_on_cpus);
-       mce_timer_kick(CMCI_POLL_INTERVAL);
+       mce_timer_kick(CMCI_STORM_INTERVAL);
+       this_cpu_write(cmci_backoff_cnt, INITIAL_CHECK_INTERVAL);
 
        if (r == 1)
                pr_notice("CMCI storm detected: switching to poll mode\n");
@@ -195,6 +214,7 @@ static void intel_threshold_interrupt(void)
 {
        if (cmci_storm_detect())
                return;
+
        machine_check_poll(MCP_TIMESTAMP, this_cpu_ptr(&mce_banks_owned));
        mce_notify_irq();
 }
@@ -286,6 +306,7 @@ void cmci_recheck(void)
 
        if (!mce_available(raw_cpu_ptr(&cpu_info)) || !cmci_supported(&banks))
                return;
+
        local_irq_save(flags);
        machine_check_poll(MCP_TIMESTAMP, this_cpu_ptr(&mce_banks_owned));
        local_irq_restore(flags);
index bfbbe6195e2da7e798323d014cfc5ae2d406d0f3..12829c3ced3c549c982a3072f825c2ed1b1c7758 100644 (file)
@@ -21,7 +21,6 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/firmware.h>
-#include <linux/pci_ids.h>
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
 #include <linux/kernel.h>
index d45df4bd16abec23e9725132ab2f9e649237f564..a413a69cbd744f2e2873434ee20b66e86fb466dd 100644 (file)
 #include <asm/processor.h>
 #include <asm/cmdline.h>
 
-#define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
-#define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u')
-#define CPUID_INTEL2 QCHAR('i', 'n', 'e', 'I')
-#define CPUID_INTEL3 QCHAR('n', 't', 'e', 'l')
-#define CPUID_AMD1 QCHAR('A', 'u', 't', 'h')
-#define CPUID_AMD2 QCHAR('e', 'n', 't', 'i')
-#define CPUID_AMD3 QCHAR('c', 'A', 'M', 'D')
-
-#define CPUID_IS(a, b, c, ebx, ecx, edx)       \
-               (!((ebx ^ (a))|(edx ^ (b))|(ecx ^ (c))))
-
-/*
- * In early loading microcode phase on BSP, boot_cpu_data is not set up yet.
- * x86_vendor() gets vendor id for BSP.
- *
- * In 32 bit AP case, accessing boot_cpu_data needs linear address. To simplify
- * coding, we still use x86_vendor() to get vendor id for AP.
- *
- * x86_vendor() gets vendor information directly through cpuid.
- */
-static int x86_vendor(void)
-{
-       u32 eax = 0x00000000;
-       u32 ebx, ecx = 0, edx;
-
-       native_cpuid(&eax, &ebx, &ecx, &edx);
-
-       if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx))
-               return X86_VENDOR_INTEL;
-
-       if (CPUID_IS(CPUID_AMD1, CPUID_AMD2, CPUID_AMD3, ebx, ecx, edx))
-               return X86_VENDOR_AMD;
-
-       return X86_VENDOR_UNKNOWN;
-}
-
-static int x86_family(void)
-{
-       u32 eax = 0x00000001;
-       u32 ebx, ecx = 0, edx;
-       int x86;
-
-       native_cpuid(&eax, &ebx, &ecx, &edx);
-
-       x86 = (eax >> 8) & 0xf;
-       if (x86 == 15)
-               x86 += (eax >> 20) & 0xff;
-
-       return x86;
-}
-
 static bool __init check_loader_disabled_bsp(void)
 {
 #ifdef CONFIG_X86_32
@@ -96,7 +45,7 @@ static bool __init check_loader_disabled_bsp(void)
 
 void __init load_ucode_bsp(void)
 {
-       int vendor, x86;
+       int vendor, family;
 
        if (check_loader_disabled_bsp())
                return;
@@ -105,15 +54,15 @@ void __init load_ucode_bsp(void)
                return;
 
        vendor = x86_vendor();
-       x86 = x86_family();
+       family = x86_family();
 
        switch (vendor) {
        case X86_VENDOR_INTEL:
-               if (x86 >= 6)
+               if (family >= 6)
                        load_ucode_intel_bsp();
                break;
        case X86_VENDOR_AMD:
-               if (x86 >= 0x10)
+               if (family >= 0x10)
                        load_ucode_amd_bsp();
                break;
        default:
@@ -132,7 +81,7 @@ static bool check_loader_disabled_ap(void)
 
 void load_ucode_ap(void)
 {
-       int vendor, x86;
+       int vendor, family;
 
        if (check_loader_disabled_ap())
                return;
@@ -141,15 +90,15 @@ void load_ucode_ap(void)
                return;
 
        vendor = x86_vendor();
-       x86 = x86_family();
+       family = x86_family();
 
        switch (vendor) {
        case X86_VENDOR_INTEL:
-               if (x86 >= 6)
+               if (family >= 6)
                        load_ucode_intel_ap();
                break;
        case X86_VENDOR_AMD:
-               if (x86 >= 0x10)
+               if (family >= 0x10)
                        load_ucode_amd_ap();
                break;
        default:
@@ -179,18 +128,18 @@ int __init save_microcode_in_initrd(void)
 
 void reload_early_microcode(void)
 {
-       int vendor, x86;
+       int vendor, family;
 
        vendor = x86_vendor();
-       x86 = x86_family();
+       family = x86_family();
 
        switch (vendor) {
        case X86_VENDOR_INTEL:
-               if (x86 >= 6)
+               if (family >= 6)
                        reload_ucode_intel();
                break;
        case X86_VENDOR_AMD:
-               if (x86 >= 0x10)
+               if (family >= 0x10)
                        reload_ucode_amd();
                break;
        default:
index 746e7fd08aad7082747ee1d9dca80570f1a00e3b..a41beadb3db9a396e5b74795e62a49648b367870 100644 (file)
@@ -124,7 +124,7 @@ static int get_matching_mc(struct microcode_intel *mc_intel, int cpu)
        cpf = cpu_sig.pf;
        crev = cpu_sig.rev;
 
-       return get_matching_microcode(csig, cpf, mc_intel, crev);
+       return get_matching_microcode(csig, cpf, crev, mc_intel);
 }
 
 static int apply_microcode_intel(int cpu)
@@ -226,7 +226,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
 
                csig = uci->cpu_sig.sig;
                cpf = uci->cpu_sig.pf;
-               if (get_matching_microcode(csig, cpf, mc, new_rev)) {
+               if (get_matching_microcode(csig, cpf, new_rev, mc)) {
                        vfree(new_mc);
                        new_rev = mc_header.rev;
                        new_mc  = mc;
index 420eb933189ca487110607475ddbf33be8e8267b..2f49ab4ac0ae137d7ab0b851cf4b9e751d58922c 100644 (file)
  *     as published by the Free Software Foundation; either version
  *     2 of the License, or (at your option) any later version.
  */
+
+/*
+ * This needs to be before all headers so that pr_debug in printk.h doesn't turn
+ * printk calls into no_printk().
+ *
+ *#define DEBUG
+ */
+
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
@@ -28,6 +36,9 @@
 #include <asm/tlbflush.h>
 #include <asm/setup.h>
 
+#undef pr_fmt
+#define pr_fmt(fmt)    "microcode: " fmt
+
 static unsigned long mc_saved_in_initrd[MAX_UCODE_COUNT];
 static struct mc_saved_data {
        unsigned int mc_saved_count;
@@ -35,50 +46,45 @@ static struct mc_saved_data {
 } mc_saved_data;
 
 static enum ucode_state
-generic_load_microcode_early(struct microcode_intel **mc_saved_p,
-                            unsigned int mc_saved_count,
-                            struct ucode_cpu_info *uci)
+load_microcode_early(struct microcode_intel **saved,
+                    unsigned int num_saved, struct ucode_cpu_info *uci)
 {
        struct microcode_intel *ucode_ptr, *new_mc = NULL;
-       int new_rev = uci->cpu_sig.rev;
-       enum ucode_state state = UCODE_OK;
-       unsigned int mc_size;
-       struct microcode_header_intel *mc_header;
-       unsigned int csig = uci->cpu_sig.sig;
-       unsigned int cpf = uci->cpu_sig.pf;
-       int i;
+       struct microcode_header_intel *mc_hdr;
+       int new_rev, ret, i;
 
-       for (i = 0; i < mc_saved_count; i++) {
-               ucode_ptr = mc_saved_p[i];
+       new_rev = uci->cpu_sig.rev;
 
-               mc_header = (struct microcode_header_intel *)ucode_ptr;
-               mc_size = get_totalsize(mc_header);
-               if (get_matching_microcode(csig, cpf, ucode_ptr, new_rev)) {
-                       new_rev = mc_header->rev;
-                       new_mc  = ucode_ptr;
-               }
-       }
+       for (i = 0; i < num_saved; i++) {
+               ucode_ptr = saved[i];
+               mc_hdr    = (struct microcode_header_intel *)ucode_ptr;
 
-       if (!new_mc) {
-               state = UCODE_NFOUND;
-               goto out;
+               ret = get_matching_microcode(uci->cpu_sig.sig,
+                                            uci->cpu_sig.pf,
+                                            new_rev,
+                                            ucode_ptr);
+               if (!ret)
+                       continue;
+
+               new_rev = mc_hdr->rev;
+               new_mc  = ucode_ptr;
        }
 
+       if (!new_mc)
+               return UCODE_NFOUND;
+
        uci->mc = (struct microcode_intel *)new_mc;
-out:
-       return state;
+       return UCODE_OK;
 }
 
-static void
-microcode_pointer(struct microcode_intel **mc_saved,
-                 unsigned long *mc_saved_in_initrd,
-                 unsigned long initrd_start, int mc_saved_count)
+static inline void
+copy_initrd_ptrs(struct microcode_intel **mc_saved, unsigned long *initrd,
+                 unsigned long off, int num_saved)
 {
        int i;
 
-       for (i = 0; i < mc_saved_count; i++)
-               mc_saved[i] = (struct microcode_intel *)
-                             (mc_saved_in_initrd[i] + initrd_start);
+       for (i = 0; i < num_saved; i++)
+               mc_saved[i] = (struct microcode_intel *)(initrd[i] + off);
 }
 
 #ifdef CONFIG_X86_32
@@ -102,55 +108,27 @@ microcode_phys(struct microcode_intel **mc_saved_tmp,
 #endif
 
 static enum ucode_state
-load_microcode(struct mc_saved_data *mc_saved_data,
-              unsigned long *mc_saved_in_initrd,
-              unsigned long initrd_start,
-              struct ucode_cpu_info *uci)
+load_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
+              unsigned long initrd_start, struct ucode_cpu_info *uci)
 {
        struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
        unsigned int count = mc_saved_data->mc_saved_count;
 
        if (!mc_saved_data->mc_saved) {
-               microcode_pointer(mc_saved_tmp, mc_saved_in_initrd,
-                                 initrd_start, count);
+               copy_initrd_ptrs(mc_saved_tmp, initrd, initrd_start, count);
 
-               return generic_load_microcode_early(mc_saved_tmp, count, uci);
+               return load_microcode_early(mc_saved_tmp, count, uci);
        } else {
 #ifdef CONFIG_X86_32
                microcode_phys(mc_saved_tmp, mc_saved_data);
-               return generic_load_microcode_early(mc_saved_tmp, count, uci);
+               return load_microcode_early(mc_saved_tmp, count, uci);
 #else
-               return generic_load_microcode_early(mc_saved_data->mc_saved,
+               return load_microcode_early(mc_saved_data->mc_saved,
                                                    count, uci);
 #endif
        }
 }
 
-static u8 get_x86_family(unsigned long sig)
-{
-       u8 x86;
-
-       x86 = (sig >> 8) & 0xf;
-
-       if (x86 == 0xf)
-               x86 += (sig >> 20) & 0xff;
-
-       return x86;
-}
-
-static u8 get_x86_model(unsigned long sig)
-{
-       u8 x86, x86_model;
-
-       x86 = get_x86_family(sig);
-       x86_model = (sig >> 4) & 0xf;
-
-       if (x86 == 0x6 || x86 == 0xf)
-               x86_model += ((sig >> 16) & 0xf) << 4;
-
-       return x86_model;
-}
-
 /*
  * Given CPU signature and a microcode patch, this function finds if the
  * microcode patch has matching family and model with the CPU.
@@ -159,42 +137,40 @@ static enum ucode_state
 matching_model_microcode(struct microcode_header_intel *mc_header,
                        unsigned long sig)
 {
-       u8 x86, x86_model;
-       u8 x86_ucode, x86_model_ucode;
+       unsigned int fam, model;
+       unsigned int fam_ucode, model_ucode;
        struct extended_sigtable *ext_header;
        unsigned long total_size = get_totalsize(mc_header);
        unsigned long data_size = get_datasize(mc_header);
        int ext_sigcount, i;
        struct extended_signature *ext_sig;
 
-       x86 = get_x86_family(sig);
-       x86_model = get_x86_model(sig);
+       fam   = __x86_family(sig);
+       model = x86_model(sig);
 
-       x86_ucode = get_x86_family(mc_header->sig);
-       x86_model_ucode = get_x86_model(mc_header->sig);
+       fam_ucode   = __x86_family(mc_header->sig);
+       model_ucode = x86_model(mc_header->sig);
 
-       if (x86 == x86_ucode && x86_model == x86_model_ucode)
+       if (fam == fam_ucode && model == model_ucode)
                return UCODE_OK;
 
        /* Look for ext. headers: */
        if (total_size <= data_size + MC_HEADER_SIZE)
                return UCODE_NFOUND;
 
-       ext_header = (struct extended_sigtable *)
-                    mc_header + data_size + MC_HEADER_SIZE;
+       ext_header   = (void *) mc_header + data_size + MC_HEADER_SIZE;
+       ext_sig      = (void *)ext_header + EXT_HEADER_SIZE;
        ext_sigcount = ext_header->count;
-       ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
 
        for (i = 0; i < ext_sigcount; i++) {
-               x86_ucode = get_x86_family(ext_sig->sig);
-               x86_model_ucode = get_x86_model(ext_sig->sig);
+               fam_ucode   = __x86_family(ext_sig->sig);
+               model_ucode = x86_model(ext_sig->sig);
 
-               if (x86 == x86_ucode && x86_model == x86_model_ucode)
+               if (fam == fam_ucode && model == model_ucode)
                        return UCODE_OK;
 
                ext_sig++;
        }
-
        return UCODE_NFOUND;
 }
 
@@ -204,7 +180,7 @@ save_microcode(struct mc_saved_data *mc_saved_data,
               unsigned int mc_saved_count)
 {
        int i, j;
-       struct microcode_intel **mc_saved_p;
+       struct microcode_intel **saved_ptr;
        int ret;
 
        if (!mc_saved_count)
@@ -213,39 +189,45 @@ save_microcode(struct mc_saved_data *mc_saved_data,
        /*
         * Copy new microcode data.
         */
-       mc_saved_p = kmalloc(mc_saved_count*sizeof(struct microcode_intel *),
-                            GFP_KERNEL);
-       if (!mc_saved_p)
+       saved_ptr = kcalloc(mc_saved_count, sizeof(struct microcode_intel *), GFP_KERNEL);
+       if (!saved_ptr)
                return -ENOMEM;
 
        for (i = 0; i < mc_saved_count; i++) {
-               struct microcode_intel *mc = mc_saved_src[i];
-               struct microcode_header_intel *mc_header = &mc->hdr;
-               unsigned long mc_size = get_totalsize(mc_header);
-               mc_saved_p[i] = kmalloc(mc_size, GFP_KERNEL);
-               if (!mc_saved_p[i]) {
-                       ret = -ENOMEM;
-                       goto err;
-               }
+               struct microcode_header_intel *mc_hdr;
+               struct microcode_intel *mc;
+               unsigned long size;
+
                if (!mc_saved_src[i]) {
                        ret = -EINVAL;
                        goto err;
                }
-               memcpy(mc_saved_p[i], mc, mc_size);
+
+               mc     = mc_saved_src[i];
+               mc_hdr = &mc->hdr;
+               size   = get_totalsize(mc_hdr);
+
+               saved_ptr[i] = kmalloc(size, GFP_KERNEL);
+               if (!saved_ptr[i]) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               memcpy(saved_ptr[i], mc, size);
        }
 
        /*
         * Point to newly saved microcode.
         */
-       mc_saved_data->mc_saved = mc_saved_p;
+       mc_saved_data->mc_saved = saved_ptr;
        mc_saved_data->mc_saved_count = mc_saved_count;
 
        return 0;
 
 err:
        for (j = 0; j <= i; j++)
-               kfree(mc_saved_p[j]);
-       kfree(mc_saved_p);
+               kfree(saved_ptr[j]);
+       kfree(saved_ptr);
 
        return ret;
 }
@@ -257,48 +239,45 @@ err:
  * - or if it is a newly discovered microcode patch.
  *
  * The microcode patch should have matching model with CPU.
+ *
+ * Returns: The updated number @num_saved of saved microcode patches.
  */
-static void _save_mc(struct microcode_intel **mc_saved, u8 *ucode_ptr,
-                    unsigned int *mc_saved_count_p)
+static unsigned int _save_mc(struct microcode_intel **mc_saved,
+                            u8 *ucode_ptr, unsigned int num_saved)
 {
-       int i;
-       int found = 0;
-       unsigned int mc_saved_count = *mc_saved_count_p;
-       struct microcode_header_intel *mc_header;
+       struct microcode_header_intel *mc_hdr, *mc_saved_hdr;
+       unsigned int sig, pf, new_rev;
+       int found = 0, i;
+
+       mc_hdr = (struct microcode_header_intel *)ucode_ptr;
+
+       for (i = 0; i < num_saved; i++) {
+               mc_saved_hdr = (struct microcode_header_intel *)mc_saved[i];
+               sig          = mc_saved_hdr->sig;
+               pf           = mc_saved_hdr->pf;
+               new_rev      = mc_hdr->rev;
+
+               if (!get_matching_sig(sig, pf, new_rev, ucode_ptr))
+                       continue;
+
+               found = 1;
+
+               if (!revision_is_newer(mc_hdr, new_rev))
+                       continue;
 
-       mc_header = (struct microcode_header_intel *)ucode_ptr;
-       for (i = 0; i < mc_saved_count; i++) {
-               unsigned int sig, pf;
-               unsigned int new_rev;
-               struct microcode_header_intel *mc_saved_header =
-                            (struct microcode_header_intel *)mc_saved[i];
-               sig = mc_saved_header->sig;
-               pf = mc_saved_header->pf;
-               new_rev = mc_header->rev;
-
-               if (get_matching_sig(sig, pf, ucode_ptr, new_rev)) {
-                       found = 1;
-                       if (update_match_revision(mc_header, new_rev)) {
-                               /*
-                                * Found an older ucode saved before.
-                                * Replace the older one with this newer
-                                * one.
-                                */
-                               mc_saved[i] =
-                                       (struct microcode_intel *)ucode_ptr;
-                               break;
-                       }
-               }
-       }
-       if (i >= mc_saved_count && !found)
                /*
-                * This ucode is first time discovered in ucode file.
-                * Save it to memory.
+                * Found an older ucode saved earlier. Replace it with
+                * this newer one.
                 */
-               mc_saved[mc_saved_count++] =
-                                (struct microcode_intel *)ucode_ptr;
+               mc_saved[i] = (struct microcode_intel *)ucode_ptr;
+               break;
+       }
+
+       /* Newly detected microcode, save it to memory. */
+       if (i >= num_saved && !found)
+               mc_saved[num_saved++] = (struct microcode_intel *)ucode_ptr;
 
-       *mc_saved_count_p = mc_saved_count;
+       return num_saved;
 }
 
 /*
@@ -346,7 +325,7 @@ get_matching_model_microcode(int cpu, unsigned long start,
                        continue;
                }
 
-               _save_mc(mc_saved_tmp, ucode_ptr, &mc_saved_count);
+               mc_saved_count = _save_mc(mc_saved_tmp, ucode_ptr, mc_saved_count);
 
                ucode_ptr += mc_size;
        }
@@ -372,7 +351,7 @@ out:
 static int collect_cpu_info_early(struct ucode_cpu_info *uci)
 {
        unsigned int val[2];
-       u8 x86, x86_model;
+       unsigned int family, model;
        struct cpu_signature csig;
        unsigned int eax, ebx, ecx, edx;
 
@@ -387,10 +366,10 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci)
        native_cpuid(&eax, &ebx, &ecx, &edx);
        csig.sig = eax;
 
-       x86 = get_x86_family(csig.sig);
-       x86_model = get_x86_model(csig.sig);
+       family = __x86_family(csig.sig);
+       model  = x86_model(csig.sig);
 
-       if ((x86_model >= 5) || (x86 > 6)) {
+       if ((model >= 5) || (family > 6)) {
                /* get processor flags from MSR 0x17 */
                native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
                csig.pf = 1 << ((val[1] >> 18) & 7);
@@ -429,8 +408,7 @@ static void __ref show_saved_mc(void)
        sig = uci.cpu_sig.sig;
        pf = uci.cpu_sig.pf;
        rev = uci.cpu_sig.rev;
-       pr_debug("CPU%d: sig=0x%x, pf=0x%x, rev=0x%x\n",
-                smp_processor_id(), sig, pf, rev);
+       pr_debug("CPU: sig=0x%x, pf=0x%x, rev=0x%x\n", sig, pf, rev);
 
        for (i = 0; i < mc_saved_data.mc_saved_count; i++) {
                struct microcode_header_intel *mc_saved_header;
@@ -457,8 +435,7 @@ static void __ref show_saved_mc(void)
                if (total_size <= data_size + MC_HEADER_SIZE)
                        continue;
 
-               ext_header = (struct extended_sigtable *)
-                            mc_saved_header + data_size + MC_HEADER_SIZE;
+               ext_header = (void *) mc_saved_header + data_size + MC_HEADER_SIZE;
                ext_sigcount = ext_header->count;
                ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
 
@@ -515,8 +492,7 @@ int save_mc_for_early(u8 *mc)
         * Save the microcode patch mc in mc_save_tmp structure if it's a newer
         * version.
         */
-
-       _save_mc(mc_saved_tmp, mc, &mc_saved_count);
+       mc_saved_count = _save_mc(mc_saved_tmp, mc, mc_saved_count);
 
        /*
         * Save the mc_save_tmp in global mc_saved_data.
@@ -548,12 +524,10 @@ EXPORT_SYMBOL_GPL(save_mc_for_early);
 
 static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin";
 static __init enum ucode_state
-scan_microcode(unsigned long start, unsigned long end,
-               struct mc_saved_data *mc_saved_data,
-               unsigned long *mc_saved_in_initrd,
-               struct ucode_cpu_info *uci)
+scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
+              unsigned long start, unsigned long size,
+              struct ucode_cpu_info *uci)
 {
-       unsigned int size = end - start + 1;
        struct cpio_data cd;
        long offset = 0;
 #ifdef CONFIG_X86_32
@@ -569,10 +543,8 @@ scan_microcode(unsigned long start, unsigned long end,
        if (!cd.data)
                return UCODE_ERROR;
 
-
        return get_matching_model_microcode(0, start, cd.data, cd.size,
-                                           mc_saved_data, mc_saved_in_initrd,
-                                           uci);
+                                           mc_saved_data, initrd, uci);
 }
 
 /*
@@ -704,7 +676,7 @@ int __init save_microcode_in_initrd_intel(void)
        if (count == 0)
                return ret;
 
-       microcode_pointer(mc_saved, mc_saved_in_initrd, initrd_start, count);
+       copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, initrd_start, count);
        ret = save_microcode(&mc_saved_data, mc_saved, count);
        if (ret)
                pr_err("Cannot save microcode patches from initrd.\n");
@@ -716,52 +688,44 @@ int __init save_microcode_in_initrd_intel(void)
 
 static void __init
 _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data,
-                     unsigned long *mc_saved_in_initrd,
-                     unsigned long initrd_start_early,
-                     unsigned long initrd_end_early,
-                     struct ucode_cpu_info *uci)
+                     unsigned long *initrd,
+                     unsigned long start, unsigned long size)
 {
+       struct ucode_cpu_info uci;
        enum ucode_state ret;
 
-       collect_cpu_info_early(uci);
-       scan_microcode(initrd_start_early, initrd_end_early, mc_saved_data,
-                      mc_saved_in_initrd, uci);
+       collect_cpu_info_early(&uci);
 
-       ret = load_microcode(mc_saved_data, mc_saved_in_initrd,
-                            initrd_start_early, uci);
+       ret = scan_microcode(mc_saved_data, initrd, start, size, &uci);
+       if (ret != UCODE_OK)
+               return;
 
-       if (ret == UCODE_OK)
-               apply_microcode_early(uci, true);
+       ret = load_microcode(mc_saved_data, initrd, start, &uci);
+       if (ret != UCODE_OK)
+               return;
+
+       apply_microcode_early(&uci, true);
 }
 
-void __init
-load_ucode_intel_bsp(void)
+void __init load_ucode_intel_bsp(void)
 {
-       u64 ramdisk_image, ramdisk_size;
-       unsigned long initrd_start_early, initrd_end_early;
-       struct ucode_cpu_info uci;
+       u64 start, size;
 #ifdef CONFIG_X86_32
-       struct boot_params *boot_params_p;
+       struct boot_params *p;
 
-       boot_params_p = (struct boot_params *)__pa_nodebug(&boot_params);
-       ramdisk_image = boot_params_p->hdr.ramdisk_image;
-       ramdisk_size  = boot_params_p->hdr.ramdisk_size;
-       initrd_start_early = ramdisk_image;
-       initrd_end_early = initrd_start_early + ramdisk_size;
+       p       = (struct boot_params *)__pa_nodebug(&boot_params);
+       start   = p->hdr.ramdisk_image;
+       size    = p->hdr.ramdisk_size;
 
        _load_ucode_intel_bsp(
-               (struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
-               (unsigned long *)__pa_nodebug(&mc_saved_in_initrd),
-               initrd_start_early, initrd_end_early, &uci);
+                       (struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
+                       (unsigned long *)__pa_nodebug(&mc_saved_in_initrd),
+                       start, size);
 #else
-       ramdisk_image = boot_params.hdr.ramdisk_image;
-       ramdisk_size  = boot_params.hdr.ramdisk_size;
-       initrd_start_early = ramdisk_image + PAGE_OFFSET;
-       initrd_end_early = initrd_start_early + ramdisk_size;
-
-       _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd,
-                             initrd_start_early, initrd_end_early,
-                             &uci);
+       start   = boot_params.hdr.ramdisk_image + PAGE_OFFSET;
+       size    = boot_params.hdr.ramdisk_size;
+
+       _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, start, size);
 #endif
 }
 
@@ -771,6 +735,7 @@ void load_ucode_intel_ap(void)
        struct ucode_cpu_info uci;
        unsigned long *mc_saved_in_initrd_p;
        unsigned long initrd_start_addr;
+       enum ucode_state ret;
 #ifdef CONFIG_X86_32
        unsigned long *initrd_start_p;
 
@@ -793,8 +758,12 @@ void load_ucode_intel_ap(void)
                return;
 
        collect_cpu_info_early(&uci);
-       load_microcode(mc_saved_data_p, mc_saved_in_initrd_p,
-                      initrd_start_addr, &uci);
+       ret = load_microcode(mc_saved_data_p, mc_saved_in_initrd_p,
+                            initrd_start_addr, &uci);
+
+       if (ret != UCODE_OK)
+               return;
+
        apply_microcode_early(&uci, true);
 }
 
@@ -808,8 +777,8 @@ void reload_ucode_intel(void)
 
        collect_cpu_info_early(&uci);
 
-       ret = generic_load_microcode_early(mc_saved_data.mc_saved,
-                                          mc_saved_data.mc_saved_count, &uci);
+       ret = load_microcode_early(mc_saved_data.mc_saved,
+                                  mc_saved_data.mc_saved_count, &uci);
        if (ret != UCODE_OK)
                return;
 
index ce69320d017907aa2d8e25c4fe7ecef47c725005..cd47a510a3f174233300d8763705b6f200faf9f4 100644 (file)
@@ -38,12 +38,6 @@ update_match_cpu(unsigned int csig, unsigned int cpf,
        return (!sigmatch(sig, csig, pf, cpf)) ? 0 : 1;
 }
 
-int
-update_match_revision(struct microcode_header_intel *mc_header, int rev)
-{
-       return (mc_header->rev <= rev) ? 0 : 1;
-}
-
 int microcode_sanity_check(void *mc, int print_err)
 {
        unsigned long total_size, data_size, ext_table_size;
@@ -128,10 +122,9 @@ int microcode_sanity_check(void *mc, int print_err)
 EXPORT_SYMBOL_GPL(microcode_sanity_check);
 
 /*
- * return 0 - no update found
- * return 1 - found update
+ * Returns 1 if update has been found, 0 otherwise.
  */
-int get_matching_sig(unsigned int csig, int cpf, void *mc, int rev)
+int get_matching_sig(unsigned int csig, int cpf, int rev, void *mc)
 {
        struct microcode_header_intel *mc_header = mc;
        struct extended_sigtable *ext_header;
@@ -159,16 +152,15 @@ int get_matching_sig(unsigned int csig, int cpf, void *mc, int rev)
 }
 
 /*
- * return 0 - no update found
- * return 1 - found update
+ * Returns 1 if update has been found, 0 otherwise.
  */
-int get_matching_microcode(unsigned int csig, int cpf, void *mc, int rev)
+int get_matching_microcode(unsigned int csig, int cpf, int rev, void *mc)
 {
-       struct microcode_header_intel *mc_header = mc;
+       struct microcode_header_intel *mc_hdr = mc;
 
-       if (!update_match_revision(mc_header, rev))
+       if (!revision_is_newer(mc_hdr, rev))
                return 0;
 
-       return get_matching_sig(csig, cpf, mc, rev);
+       return get_matching_sig(csig, cpf, rev, mc);
 }
 EXPORT_SYMBOL_GPL(get_matching_microcode);
index 36d99a337b49f56398ca29d900638ddcedee277b..3f20710a5b23b7f7456e99bb7f654ce703bb6abf 100644 (file)
@@ -6,7 +6,7 @@
 IN=$1
 OUT=$2
 
-function dump_array()
+dump_array()
 {
        ARRAY=$1
        SIZE=$2
index b71a7f86d68aca8ba6dd864e9c8cf15e2b3d28ba..87848ebe2bb79a56625908c5a6af1b78055d70c9 100644 (file)
@@ -263,6 +263,14 @@ static void hw_perf_event_destroy(struct perf_event *event)
        }
 }
 
+void hw_perf_lbr_event_destroy(struct perf_event *event)
+{
+       hw_perf_event_destroy(event);
+
+       /* undo the lbr/bts event accounting */
+       x86_del_exclusive(x86_lbr_exclusive_lbr);
+}
+
 static inline int x86_pmu_initialized(void)
 {
        return x86_pmu.handle_irq != NULL;
@@ -302,6 +310,35 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event *event)
        return x86_pmu_extra_regs(val, event);
 }
 
+/*
+ * Check if we can create event of a certain type (that no conflicting events
+ * are present).
+ */
+int x86_add_exclusive(unsigned int what)
+{
+       int ret = -EBUSY, i;
+
+       if (atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what]))
+               return 0;
+
+       mutex_lock(&pmc_reserve_mutex);
+       for (i = 0; i < ARRAY_SIZE(x86_pmu.lbr_exclusive); i++)
+               if (i != what && atomic_read(&x86_pmu.lbr_exclusive[i]))
+                       goto out;
+
+       atomic_inc(&x86_pmu.lbr_exclusive[what]);
+       ret = 0;
+
+out:
+       mutex_unlock(&pmc_reserve_mutex);
+       return ret;
+}
+
+void x86_del_exclusive(unsigned int what)
+{
+       atomic_dec(&x86_pmu.lbr_exclusive[what]);
+}
+
 int x86_setup_perfctr(struct perf_event *event)
 {
        struct perf_event_attr *attr = &event->attr;
@@ -346,6 +383,12 @@ int x86_setup_perfctr(struct perf_event *event)
                /* BTS is currently only allowed for user-mode. */
                if (!attr->exclude_kernel)
                        return -EOPNOTSUPP;
+
+               /* disallow bts if conflicting events are present */
+               if (x86_add_exclusive(x86_lbr_exclusive_lbr))
+                       return -EBUSY;
+
+               event->destroy = hw_perf_lbr_event_destroy;
        }
 
        hwc->config |= config;
@@ -399,39 +442,41 @@ int x86_pmu_hw_config(struct perf_event *event)
 
                if (event->attr.precise_ip > precise)
                        return -EOPNOTSUPP;
-               /*
-                * check that PEBS LBR correction does not conflict with
-                * whatever the user is asking with attr->branch_sample_type
-                */
-               if (event->attr.precise_ip > 1 &&
-                   x86_pmu.intel_cap.pebs_format < 2) {
-                       u64 *br_type = &event->attr.branch_sample_type;
-
-                       if (has_branch_stack(event)) {
-                               if (!precise_br_compat(event))
-                                       return -EOPNOTSUPP;
-
-                               /* branch_sample_type is compatible */
-
-                       } else {
-                               /*
-                                * user did not specify  branch_sample_type
-                                *
-                                * For PEBS fixups, we capture all
-                                * the branches at the priv level of the
-                                * event.
-                                */
-                               *br_type = PERF_SAMPLE_BRANCH_ANY;
-
-                               if (!event->attr.exclude_user)
-                                       *br_type |= PERF_SAMPLE_BRANCH_USER;
-
-                               if (!event->attr.exclude_kernel)
-                                       *br_type |= PERF_SAMPLE_BRANCH_KERNEL;
-                       }
+       }
+       /*
+        * check that PEBS LBR correction does not conflict with
+        * whatever the user is asking with attr->branch_sample_type
+        */
+       if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format < 2) {
+               u64 *br_type = &event->attr.branch_sample_type;
+
+               if (has_branch_stack(event)) {
+                       if (!precise_br_compat(event))
+                               return -EOPNOTSUPP;
+
+                       /* branch_sample_type is compatible */
+
+               } else {
+                       /*
+                        * user did not specify  branch_sample_type
+                        *
+                        * For PEBS fixups, we capture all
+                        * the branches at the priv level of the
+                        * event.
+                        */
+                       *br_type = PERF_SAMPLE_BRANCH_ANY;
+
+                       if (!event->attr.exclude_user)
+                               *br_type |= PERF_SAMPLE_BRANCH_USER;
+
+                       if (!event->attr.exclude_kernel)
+                               *br_type |= PERF_SAMPLE_BRANCH_KERNEL;
                }
        }
 
+       if (event->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK)
+               event->attach_state |= PERF_ATTACH_TASK_DATA;
+
        /*
         * Generate PMC IRQs:
         * (keep 'enabled' bit clear for now)
@@ -449,6 +494,12 @@ int x86_pmu_hw_config(struct perf_event *event)
        if (event->attr.type == PERF_TYPE_RAW)
                event->hw.config |= event->attr.config & X86_RAW_EVENT_MASK;
 
+       if (event->attr.sample_period && x86_pmu.limit_period) {
+               if (x86_pmu.limit_period(event, event->attr.sample_period) >
+                               event->attr.sample_period)
+                       return -EINVAL;
+       }
+
        return x86_setup_perfctr(event);
 }
 
@@ -728,14 +779,17 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
        struct event_constraint *c;
        unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
        struct perf_event *e;
-       int i, wmin, wmax, num = 0;
+       int i, wmin, wmax, unsched = 0;
        struct hw_perf_event *hwc;
 
        bitmap_zero(used_mask, X86_PMC_IDX_MAX);
 
+       if (x86_pmu.start_scheduling)
+               x86_pmu.start_scheduling(cpuc);
+
        for (i = 0, wmin = X86_PMC_IDX_MAX, wmax = 0; i < n; i++) {
                hwc = &cpuc->event_list[i]->hw;
-               c = x86_pmu.get_event_constraints(cpuc, cpuc->event_list[i]);
+               c = x86_pmu.get_event_constraints(cpuc, i, cpuc->event_list[i]);
                hwc->constraint = c;
 
                wmin = min(wmin, c->weight);
@@ -768,24 +822,30 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
 
        /* slow path */
        if (i != n)
-               num = perf_assign_events(cpuc->event_list, n, wmin,
-                                        wmax, assign);
+               unsched = perf_assign_events(cpuc->event_list, n, wmin,
+                                            wmax, assign);
 
        /*
-        * Mark the event as committed, so we do not put_constraint()
-        * in case new events are added and fail scheduling.
+        * In case of success (unsched = 0), mark events as committed,
+        * so we do not put_constraint() in case new events are added
+        * and fail to be scheduled
+        *
+        * We invoke the lower level commit callback to lock the resource
+        *
+        * We do not need to do all of this in case we are called to
+        * validate an event group (assign == NULL)
         */
-       if (!num && assign) {
+       if (!unsched && assign) {
                for (i = 0; i < n; i++) {
                        e = cpuc->event_list[i];
                        e->hw.flags |= PERF_X86_EVENT_COMMITTED;
+                       if (x86_pmu.commit_scheduling)
+                               x86_pmu.commit_scheduling(cpuc, e, assign[i]);
                }
        }
-       /*
-        * scheduling failed or is just a simulation,
-        * free resources if necessary
-        */
-       if (!assign || num) {
+
+       if (!assign || unsched) {
+
                for (i = 0; i < n; i++) {
                        e = cpuc->event_list[i];
                        /*
@@ -795,11 +855,18 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
                        if ((e->hw.flags & PERF_X86_EVENT_COMMITTED))
                                continue;
 
+                       /*
+                        * release events that failed scheduling
+                        */
                        if (x86_pmu.put_event_constraints)
                                x86_pmu.put_event_constraints(cpuc, e);
                }
        }
-       return num ? -EINVAL : 0;
+
+       if (x86_pmu.stop_scheduling)
+               x86_pmu.stop_scheduling(cpuc);
+
+       return unsched ? -EINVAL : 0;
 }
 
 /*
@@ -986,6 +1053,9 @@ int x86_perf_event_set_period(struct perf_event *event)
        if (left > x86_pmu.max_period)
                left = x86_pmu.max_period;
 
+       if (x86_pmu.limit_period)
+               left = x86_pmu.limit_period(event, left);
+
        per_cpu(pmc_prev_left[idx], smp_processor_id()) = left;
 
        /*
@@ -1033,7 +1103,6 @@ static int x86_pmu_add(struct perf_event *event, int flags)
 
        hwc = &event->hw;
 
-       perf_pmu_disable(event->pmu);
        n0 = cpuc->n_events;
        ret = n = collect_events(cpuc, event, false);
        if (ret < 0)
@@ -1071,7 +1140,6 @@ done_collect:
 
        ret = 0;
 out:
-       perf_pmu_enable(event->pmu);
        return ret;
 }
 
@@ -1103,7 +1171,7 @@ static void x86_pmu_start(struct perf_event *event, int flags)
 void perf_event_print_debug(void)
 {
        u64 ctrl, status, overflow, pmc_ctrl, pmc_count, prev_left, fixed;
-       u64 pebs;
+       u64 pebs, debugctl;
        struct cpu_hw_events *cpuc;
        unsigned long flags;
        int cpu, idx;
@@ -1121,14 +1189,20 @@ void perf_event_print_debug(void)
                rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
                rdmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);
                rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
-               rdmsrl(MSR_IA32_PEBS_ENABLE, pebs);
 
                pr_info("\n");
                pr_info("CPU#%d: ctrl:       %016llx\n", cpu, ctrl);
                pr_info("CPU#%d: status:     %016llx\n", cpu, status);
                pr_info("CPU#%d: overflow:   %016llx\n", cpu, overflow);
                pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
-               pr_info("CPU#%d: pebs:       %016llx\n", cpu, pebs);
+               if (x86_pmu.pebs_constraints) {
+                       rdmsrl(MSR_IA32_PEBS_ENABLE, pebs);
+                       pr_info("CPU#%d: pebs:       %016llx\n", cpu, pebs);
+               }
+               if (x86_pmu.lbr_nr) {
+                       rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
+                       pr_info("CPU#%d: debugctl:   %016llx\n", cpu, debugctl);
+               }
        }
        pr_info("CPU#%d: active:     %016llx\n", cpu, *(u64 *)cpuc->active_mask);
 
@@ -1321,11 +1395,12 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
 {
        unsigned int cpu = (long)hcpu;
        struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
-       int ret = NOTIFY_OK;
+       int i, ret = NOTIFY_OK;
 
        switch (action & ~CPU_TASKS_FROZEN) {
        case CPU_UP_PREPARE:
-               cpuc->kfree_on_online = NULL;
+               for (i = 0 ; i < X86_PERF_KFREE_MAX; i++)
+                       cpuc->kfree_on_online[i] = NULL;
                if (x86_pmu.cpu_prepare)
                        ret = x86_pmu.cpu_prepare(cpu);
                break;
@@ -1336,7 +1411,10 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
                break;
 
        case CPU_ONLINE:
-               kfree(cpuc->kfree_on_online);
+               for (i = 0 ; i < X86_PERF_KFREE_MAX; i++) {
+                       kfree(cpuc->kfree_on_online[i]);
+                       cpuc->kfree_on_online[i] = NULL;
+               }
                break;
 
        case CPU_DYING:
@@ -1712,7 +1790,7 @@ static int validate_event(struct perf_event *event)
        if (IS_ERR(fake_cpuc))
                return PTR_ERR(fake_cpuc);
 
-       c = x86_pmu.get_event_constraints(fake_cpuc, event);
+       c = x86_pmu.get_event_constraints(fake_cpuc, -1, event);
 
        if (!c || !c->weight)
                ret = -EINVAL;
@@ -1914,10 +1992,10 @@ static const struct attribute_group *x86_pmu_attr_groups[] = {
        NULL,
 };
 
-static void x86_pmu_flush_branch_stack(void)
+static void x86_pmu_sched_task(struct perf_event_context *ctx, bool sched_in)
 {
-       if (x86_pmu.flush_branch_stack)
-               x86_pmu.flush_branch_stack();
+       if (x86_pmu.sched_task)
+               x86_pmu.sched_task(ctx, sched_in);
 }
 
 void perf_check_microcode(void)
@@ -1949,7 +2027,8 @@ static struct pmu pmu = {
        .commit_txn             = x86_pmu_commit_txn,
 
        .event_idx              = x86_pmu_event_idx,
-       .flush_branch_stack     = x86_pmu_flush_branch_stack,
+       .sched_task             = x86_pmu_sched_task,
+       .task_ctx_size          = sizeof(struct x86_perf_task_context),
 };
 
 void arch_perf_update_userpage(struct perf_event *event,
@@ -1968,13 +2047,23 @@ void arch_perf_update_userpage(struct perf_event *event,
 
        data = cyc2ns_read_begin();
 
+       /*
+        * Internal timekeeping for enabled/running/stopped times
+        * is always in the local_clock domain.
+        */
        userpg->cap_user_time = 1;
        userpg->time_mult = data->cyc2ns_mul;
        userpg->time_shift = data->cyc2ns_shift;
        userpg->time_offset = data->cyc2ns_offset - now;
 
-       userpg->cap_user_time_zero = 1;
-       userpg->time_zero = data->cyc2ns_offset;
+       /*
+        * cap_user_time_zero doesn't make sense when we're using a different
+        * time base for the records.
+        */
+       if (event->clock == &local_clock) {
+               userpg->cap_user_time_zero = 1;
+               userpg->time_zero = data->cyc2ns_offset;
+       }
 
        cyc2ns_read_end(data);
 }
@@ -2146,6 +2235,12 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
  */
 static unsigned long code_segment_base(struct pt_regs *regs)
 {
+       /*
+        * For IA32 we look at the GDT/LDT segment base to convert the
+        * effective IP to a linear address.
+        */
+
+#ifdef CONFIG_X86_32
        /*
         * If we are in VM86 mode, add the segment offset to convert to a
         * linear address.
@@ -2153,18 +2248,12 @@ static unsigned long code_segment_base(struct pt_regs *regs)
        if (regs->flags & X86_VM_MASK)
                return 0x10 * regs->cs;
 
-       /*
-        * For IA32 we look at the GDT/LDT segment base to convert the
-        * effective IP to a linear address.
-        */
-#ifdef CONFIG_X86_32
        if (user_mode(regs) && regs->cs != __USER_CS)
                return get_segment_base(regs->cs);
 #else
-       if (test_thread_flag(TIF_IA32)) {
-               if (user_mode(regs) && regs->cs != __USER32_CS)
-                       return get_segment_base(regs->cs);
-       }
+       if (user_mode(regs) && !user_64bit_mode(regs) &&
+           regs->cs != __USER32_CS)
+               return get_segment_base(regs->cs);
 #endif
        return 0;
 }
index df525d2be1e814766ac96a82ee3caf33cc4316e4..329f0356ad4a0a8b969ae4d61d9b29a10d3b9522 100644 (file)
@@ -71,6 +71,8 @@ struct event_constraint {
 #define PERF_X86_EVENT_COMMITTED       0x8 /* event passed commit_txn */
 #define PERF_X86_EVENT_PEBS_LD_HSW     0x10 /* haswell style datala, load */
 #define PERF_X86_EVENT_PEBS_NA_HSW     0x20 /* haswell style datala, unknown */
+#define PERF_X86_EVENT_EXCL            0x40 /* HT exclusivity on counter */
+#define PERF_X86_EVENT_DYNAMIC         0x80 /* dynamic alloc'd constraint */
 #define PERF_X86_EVENT_RDPMC_ALLOWED   0x40 /* grant rdpmc permission */
 
 
@@ -123,8 +125,37 @@ struct intel_shared_regs {
        unsigned                core_id;        /* per-core: core id */
 };
 
+enum intel_excl_state_type {
+       INTEL_EXCL_UNUSED    = 0, /* counter is unused */
+       INTEL_EXCL_SHARED    = 1, /* counter can be used by both threads */
+       INTEL_EXCL_EXCLUSIVE = 2, /* counter can be used by one thread only */
+};
+
+struct intel_excl_states {
+       enum intel_excl_state_type init_state[X86_PMC_IDX_MAX];
+       enum intel_excl_state_type state[X86_PMC_IDX_MAX];
+       int  num_alloc_cntrs;/* #counters allocated */
+       int  max_alloc_cntrs;/* max #counters allowed */
+       bool sched_started; /* true if scheduling has started */
+};
+
+struct intel_excl_cntrs {
+       raw_spinlock_t  lock;
+
+       struct intel_excl_states states[2];
+
+       int             refcnt;         /* per-core: #HT threads */
+       unsigned        core_id;        /* per-core: core id */
+};
+
 #define MAX_LBR_ENTRIES                16
 
+enum {
+       X86_PERF_KFREE_SHARED = 0,
+       X86_PERF_KFREE_EXCL   = 1,
+       X86_PERF_KFREE_MAX
+};
+
 struct cpu_hw_events {
        /*
         * Generic x86 PMC bits
@@ -179,6 +210,12 @@ struct cpu_hw_events {
         * used on Intel NHM/WSM/SNB
         */
        struct intel_shared_regs        *shared_regs;
+       /*
+        * manage exclusive counter access between hyperthread
+        */
+       struct event_constraint *constraint_list; /* in enable order */
+       struct intel_excl_cntrs         *excl_cntrs;
+       int excl_thread_id; /* 0 or 1 */
 
        /*
         * AMD specific bits
@@ -187,7 +224,7 @@ struct cpu_hw_events {
        /* Inverted mask of bits to clear in the perf_ctr ctrl registers */
        u64                             perf_ctr_virt_mask;
 
-       void                            *kfree_on_online;
+       void                            *kfree_on_online[X86_PERF_KFREE_MAX];
 };
 
 #define __EVENT_CONSTRAINT(c, n, m, w, o, f) {\
@@ -202,6 +239,10 @@ struct cpu_hw_events {
 #define EVENT_CONSTRAINT(c, n, m)      \
        __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n), 0, 0)
 
+#define INTEL_EXCLEVT_CONSTRAINT(c, n) \
+       __EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT, HWEIGHT(n),\
+                          0, PERF_X86_EVENT_EXCL)
+
 /*
  * The overlap flag marks event constraints with overlapping counter
  * masks. This is the case if the counter mask of such an event is not
@@ -259,6 +300,10 @@ struct cpu_hw_events {
 #define INTEL_FLAGS_UEVENT_CONSTRAINT(c, n)    \
        EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS)
 
+#define INTEL_EXCLUEVT_CONSTRAINT(c, n)        \
+       __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK, \
+                          HWEIGHT(n), 0, PERF_X86_EVENT_EXCL)
+
 #define INTEL_PLD_CONSTRAINT(c, n)     \
        __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
                           HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LDLAT)
@@ -283,22 +328,40 @@ struct cpu_hw_events {
 
 /* Check flags and event code, and set the HSW load flag */
 #define INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(code, n) \
-       __EVENT_CONSTRAINT(code, n,                     \
+       __EVENT_CONSTRAINT(code, n,                     \
                          ARCH_PERFMON_EVENTSEL_EVENT|X86_ALL_EVENT_FLAGS, \
                          HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LD_HSW)
 
+#define INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(code, n) \
+       __EVENT_CONSTRAINT(code, n,                     \
+                         ARCH_PERFMON_EVENTSEL_EVENT|X86_ALL_EVENT_FLAGS, \
+                         HWEIGHT(n), 0, \
+                         PERF_X86_EVENT_PEBS_LD_HSW|PERF_X86_EVENT_EXCL)
+
 /* Check flags and event code/umask, and set the HSW store flag */
 #define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(code, n) \
        __EVENT_CONSTRAINT(code, n,                     \
                          INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
                          HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST_HSW)
 
+#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(code, n) \
+       __EVENT_CONSTRAINT(code, n,                     \
+                         INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
+                         HWEIGHT(n), 0, \
+                         PERF_X86_EVENT_PEBS_ST_HSW|PERF_X86_EVENT_EXCL)
+
 /* Check flags and event code/umask, and set the HSW load flag */
 #define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(code, n) \
        __EVENT_CONSTRAINT(code, n,                     \
                          INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
                          HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LD_HSW)
 
+#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(code, n) \
+       __EVENT_CONSTRAINT(code, n,                     \
+                         INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
+                         HWEIGHT(n), 0, \
+                         PERF_X86_EVENT_PEBS_LD_HSW|PERF_X86_EVENT_EXCL)
+
 /* Check flags and event code/umask, and set the HSW N/A flag */
 #define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(code, n) \
        __EVENT_CONSTRAINT(code, n,                     \
@@ -408,6 +471,13 @@ union x86_pmu_config {
 
 #define X86_CONFIG(args...) ((union x86_pmu_config){.bits = {args}}).value
 
+enum {
+       x86_lbr_exclusive_lbr,
+       x86_lbr_exclusive_bts,
+       x86_lbr_exclusive_pt,
+       x86_lbr_exclusive_max,
+};
+
 /*
  * struct x86_pmu - generic x86 pmu
  */
@@ -443,14 +513,25 @@ struct x86_pmu {
        u64             max_period;
        struct event_constraint *
                        (*get_event_constraints)(struct cpu_hw_events *cpuc,
+                                                int idx,
                                                 struct perf_event *event);
 
        void            (*put_event_constraints)(struct cpu_hw_events *cpuc,
                                                 struct perf_event *event);
+
+       void            (*commit_scheduling)(struct cpu_hw_events *cpuc,
+                                            struct perf_event *event,
+                                            int cntr);
+
+       void            (*start_scheduling)(struct cpu_hw_events *cpuc);
+
+       void            (*stop_scheduling)(struct cpu_hw_events *cpuc);
+
        struct event_constraint *event_constraints;
        struct x86_pmu_quirk *quirks;
        int             perfctr_second_write;
        bool            late_ack;
+       unsigned        (*limit_period)(struct perf_event *event, unsigned l);
 
        /*
         * sysfs attrs
@@ -472,7 +553,8 @@ struct x86_pmu {
        void            (*cpu_dead)(int cpu);
 
        void            (*check_microcode)(void);
-       void            (*flush_branch_stack)(void);
+       void            (*sched_task)(struct perf_event_context *ctx,
+                                     bool sched_in);
 
        /*
         * Intel Arch Perfmon v2+
@@ -503,11 +585,16 @@ struct x86_pmu {
        const int       *lbr_sel_map;              /* lbr_select mappings */
        bool            lbr_double_abort;          /* duplicated lbr aborts */
 
+       /*
+        * Intel PT/LBR/BTS are exclusive
+        */
+       atomic_t        lbr_exclusive[x86_lbr_exclusive_max];
+
        /*
         * Extra registers for events
         */
        struct extra_reg *extra_regs;
-       unsigned int er_flags;
+       unsigned int flags;
 
        /*
         * Intel host/guest support (KVM)
@@ -515,6 +602,13 @@ struct x86_pmu {
        struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr);
 };
 
+struct x86_perf_task_context {
+       u64 lbr_from[MAX_LBR_ENTRIES];
+       u64 lbr_to[MAX_LBR_ENTRIES];
+       int lbr_callstack_users;
+       int lbr_stack_state;
+};
+
 #define x86_add_quirk(func_)                                           \
 do {                                                                   \
        static struct x86_pmu_quirk __quirk __initdata = {              \
@@ -524,8 +618,13 @@ do {                                                                       \
        x86_pmu.quirks = &__quirk;                                      \
 } while (0)
 
-#define ERF_NO_HT_SHARING      1
-#define ERF_HAS_RSP_1          2
+/*
+ * x86_pmu flags
+ */
+#define PMU_FL_NO_HT_SHARING   0x1 /* no hyper-threading resource sharing */
+#define PMU_FL_HAS_RSP_1       0x2 /* has 2 equivalent offcore_rsp regs   */
+#define PMU_FL_EXCL_CNTRS      0x4 /* has exclusive counter requirements  */
+#define PMU_FL_EXCL_ENABLED    0x8 /* exclusive counter active */
 
 #define EVENT_VAR(_id)  event_attr_##_id
 #define EVENT_PTR(_id) &event_attr_##_id.attr.attr
@@ -546,6 +645,12 @@ static struct perf_pmu_events_attr event_attr_##v = {                      \
 
 extern struct x86_pmu x86_pmu __read_mostly;
 
+static inline bool x86_pmu_has_lbr_callstack(void)
+{
+       return  x86_pmu.lbr_sel_map &&
+               x86_pmu.lbr_sel_map[PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT] > 0;
+}
+
 DECLARE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
 
 int x86_perf_event_set_period(struct perf_event *event);
@@ -588,6 +693,12 @@ static inline int x86_pmu_rdpmc_index(int index)
        return x86_pmu.rdpmc_index ? x86_pmu.rdpmc_index(index) : index;
 }
 
+int x86_add_exclusive(unsigned int what);
+
+void x86_del_exclusive(unsigned int what);
+
+void hw_perf_lbr_event_destroy(struct perf_event *event);
+
 int x86_setup_perfctr(struct perf_event *event);
 
 int x86_pmu_hw_config(struct perf_event *event);
@@ -674,10 +785,34 @@ static inline int amd_pmu_init(void)
 
 #ifdef CONFIG_CPU_SUP_INTEL
 
+static inline bool intel_pmu_needs_lbr_smpl(struct perf_event *event)
+{
+       /* user explicitly requested branch sampling */
+       if (has_branch_stack(event))
+               return true;
+
+       /* implicit branch sampling to correct PEBS skid */
+       if (x86_pmu.intel_cap.pebs_trap && event->attr.precise_ip > 1 &&
+           x86_pmu.intel_cap.pebs_format < 2)
+               return true;
+
+       return false;
+}
+
+static inline bool intel_pmu_has_bts(struct perf_event *event)
+{
+       if (event->attr.config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
+           !event->attr.freq && event->hw.sample_period == 1)
+               return true;
+
+       return false;
+}
+
 int intel_pmu_save_and_restart(struct perf_event *event);
 
 struct event_constraint *
-x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event);
+x86_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+                         struct perf_event *event);
 
 struct intel_shared_regs *allocate_shared_regs(int cpu);
 
@@ -727,13 +862,15 @@ void intel_pmu_pebs_disable_all(void);
 
 void intel_ds_init(void);
 
+void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in);
+
 void intel_pmu_lbr_reset(void);
 
 void intel_pmu_lbr_enable(struct perf_event *event);
 
 void intel_pmu_lbr_disable(struct perf_event *event);
 
-void intel_pmu_lbr_enable_all(void);
+void intel_pmu_lbr_enable_all(bool pmi);
 
 void intel_pmu_lbr_disable_all(void);
 
@@ -747,8 +884,18 @@ void intel_pmu_lbr_init_atom(void);
 
 void intel_pmu_lbr_init_snb(void);
 
+void intel_pmu_lbr_init_hsw(void);
+
 int intel_pmu_setup_lbr_filter(struct perf_event *event);
 
+void intel_pt_interrupt(void);
+
+int intel_bts_interrupt(void);
+
+void intel_bts_enable_local(void);
+
+void intel_bts_disable_local(void);
+
 int p4_pmu_init(void);
 
 int p6_pmu_init(void);
@@ -758,6 +905,10 @@ int knc_pmu_init(void);
 ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
                          char *page);
 
+static inline int is_ht_workaround_enabled(void)
+{
+       return !!(x86_pmu.flags & PMU_FL_EXCL_ENABLED);
+}
 #else /* CONFIG_CPU_SUP_INTEL */
 
 static inline void reserve_ds_buffers(void)
index 28926311aac1833b72a932e7108916e25bf4804d..1cee5d2d7eceafde5d5545dac8227c55f8097386 100644 (file)
@@ -382,6 +382,7 @@ static int amd_pmu_cpu_prepare(int cpu)
 static void amd_pmu_cpu_starting(int cpu)
 {
        struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+       void **onln = &cpuc->kfree_on_online[X86_PERF_KFREE_SHARED];
        struct amd_nb *nb;
        int i, nb_id;
 
@@ -399,7 +400,7 @@ static void amd_pmu_cpu_starting(int cpu)
                        continue;
 
                if (nb->nb_id == nb_id) {
-                       cpuc->kfree_on_online = cpuc->amd_nb;
+                       *onln = cpuc->amd_nb;
                        cpuc->amd_nb = nb;
                        break;
                }
@@ -429,7 +430,8 @@ static void amd_pmu_cpu_dead(int cpu)
 }
 
 static struct event_constraint *
-amd_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
+amd_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+                         struct perf_event *event)
 {
        /*
         * if not NB event or no NB, then no constraints
@@ -537,7 +539,8 @@ static struct event_constraint amd_f15_PMC50 = EVENT_CONSTRAINT(0, 0x3F, 0);
 static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0);
 
 static struct event_constraint *
-amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *event)
+amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, int idx,
+                              struct perf_event *event)
 {
        struct hw_perf_event *hwc = &event->hw;
        unsigned int event_code = amd_get_event_code(hwc);
index a61f5c6911daac339588b9099e5b897a3ef9d774..989d3c215d2bcea3b1a55bc2e8a42d9e20b31a98 100644 (file)
@@ -796,7 +796,7 @@ static int setup_ibs_ctl(int ibs_eilvt_off)
  * the IBS interrupt vector is handled by perf_ibs_cpu_notifier that
  * is using the new offset.
  */
-static int force_ibs_eilvt_setup(void)
+static void force_ibs_eilvt_setup(void)
 {
        int offset;
        int ret;
@@ -811,26 +811,24 @@ static int force_ibs_eilvt_setup(void)
 
        if (offset == APIC_EILVT_NR_MAX) {
                printk(KERN_DEBUG "No EILVT entry available\n");
-               return -EBUSY;
+               return;
        }
 
        ret = setup_ibs_ctl(offset);
        if (ret)
                goto out;
 
-       if (!ibs_eilvt_valid()) {
-               ret = -EFAULT;
+       if (!ibs_eilvt_valid())
                goto out;
-       }
 
        pr_info("IBS: LVT offset %d assigned\n", offset);
 
-       return 0;
+       return;
 out:
        preempt_disable();
        put_eilvt(offset);
        preempt_enable();
-       return ret;
+       return;
 }
 
 static void ibs_eilvt_setup(void)
index 258990688a5e999557de7f3b5398d7eccdc45ebb..9da2400c2ec37b7ea164e7a17f3bea68b172cbe6 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/watchdog.h>
 
 #include <asm/cpufeature.h>
 #include <asm/hardirq.h>
@@ -113,6 +114,12 @@ static struct event_constraint intel_snb_event_constraints[] __read_mostly =
        INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
        INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_NO_DISPATCH */
        INTEL_UEVENT_CONSTRAINT(0x02a3, 0x4), /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
+
+       INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
+
        EVENT_CONSTRAINT_END
 };
 
@@ -131,15 +138,12 @@ static struct event_constraint intel_ivb_event_constraints[] __read_mostly =
        INTEL_UEVENT_CONSTRAINT(0x08a3, 0x4), /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
        INTEL_UEVENT_CONSTRAINT(0x0ca3, 0x4), /* CYCLE_ACTIVITY.STALLS_L1D_PENDING */
        INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
-       /*
-        * Errata BV98 -- MEM_*_RETIRED events can leak between counters of SMT
-        * siblings; disable these events because they can corrupt unrelated
-        * counters.
-        */
-       INTEL_EVENT_CONSTRAINT(0xd0, 0x0), /* MEM_UOPS_RETIRED.* */
-       INTEL_EVENT_CONSTRAINT(0xd1, 0x0), /* MEM_LOAD_UOPS_RETIRED.* */
-       INTEL_EVENT_CONSTRAINT(0xd2, 0x0), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
-       INTEL_EVENT_CONSTRAINT(0xd3, 0x0), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
+
+       INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
+
        EVENT_CONSTRAINT_END
 };
 
@@ -217,6 +221,21 @@ static struct event_constraint intel_hsw_event_constraints[] = {
        INTEL_UEVENT_CONSTRAINT(0x0ca3, 0x4),
        /* CYCLE_ACTIVITY.CYCLES_NO_EXECUTE */
        INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf),
+
+       INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
+
+       EVENT_CONSTRAINT_END
+};
+
+struct event_constraint intel_bdw_event_constraints[] = {
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0),      /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1),      /* CPU_CLK_UNHALTED.CORE */
+       FIXED_EVENT_CONSTRAINT(0x0300, 2),      /* CPU_CLK_UNHALTED.REF */
+       INTEL_UEVENT_CONSTRAINT(0x148, 0x4),    /* L1D_PEND_MISS.PENDING */
+       INTEL_EVENT_CONSTRAINT(0xa3, 0x4),      /* CYCLE_ACTIVITY.* */
        EVENT_CONSTRAINT_END
 };
 
@@ -415,6 +434,202 @@ static __initconst const u64 snb_hw_cache_event_ids
 
 };
 
+/*
+ * Notes on the events:
+ * - data reads do not include code reads (comparable to earlier tables)
+ * - data counts include speculative execution (except L1 write, dtlb, bpu)
+ * - remote node access includes remote memory, remote cache, remote mmio.
+ * - prefetches are not included in the counts because they are not
+ *   reliably counted.
+ */
+
+#define HSW_DEMAND_DATA_RD             BIT_ULL(0)
+#define HSW_DEMAND_RFO                 BIT_ULL(1)
+#define HSW_ANY_RESPONSE               BIT_ULL(16)
+#define HSW_SUPPLIER_NONE              BIT_ULL(17)
+#define HSW_L3_MISS_LOCAL_DRAM         BIT_ULL(22)
+#define HSW_L3_MISS_REMOTE_HOP0                BIT_ULL(27)
+#define HSW_L3_MISS_REMOTE_HOP1                BIT_ULL(28)
+#define HSW_L3_MISS_REMOTE_HOP2P       BIT_ULL(29)
+#define HSW_L3_MISS                    (HSW_L3_MISS_LOCAL_DRAM| \
+                                        HSW_L3_MISS_REMOTE_HOP0|HSW_L3_MISS_REMOTE_HOP1| \
+                                        HSW_L3_MISS_REMOTE_HOP2P)
+#define HSW_SNOOP_NONE                 BIT_ULL(31)
+#define HSW_SNOOP_NOT_NEEDED           BIT_ULL(32)
+#define HSW_SNOOP_MISS                 BIT_ULL(33)
+#define HSW_SNOOP_HIT_NO_FWD           BIT_ULL(34)
+#define HSW_SNOOP_HIT_WITH_FWD         BIT_ULL(35)
+#define HSW_SNOOP_HITM                 BIT_ULL(36)
+#define HSW_SNOOP_NON_DRAM             BIT_ULL(37)
+#define HSW_ANY_SNOOP                  (HSW_SNOOP_NONE| \
+                                        HSW_SNOOP_NOT_NEEDED|HSW_SNOOP_MISS| \
+                                        HSW_SNOOP_HIT_NO_FWD|HSW_SNOOP_HIT_WITH_FWD| \
+                                        HSW_SNOOP_HITM|HSW_SNOOP_NON_DRAM)
+#define HSW_SNOOP_DRAM                 (HSW_ANY_SNOOP & ~HSW_SNOOP_NON_DRAM)
+#define HSW_DEMAND_READ                        HSW_DEMAND_DATA_RD
+#define HSW_DEMAND_WRITE               HSW_DEMAND_RFO
+#define HSW_L3_MISS_REMOTE             (HSW_L3_MISS_REMOTE_HOP0|\
+                                        HSW_L3_MISS_REMOTE_HOP1|HSW_L3_MISS_REMOTE_HOP2P)
+#define HSW_LLC_ACCESS                 HSW_ANY_RESPONSE
+
+#define BDW_L3_MISS_LOCAL              BIT(26)
+#define BDW_L3_MISS                    (BDW_L3_MISS_LOCAL| \
+                                        HSW_L3_MISS_REMOTE_HOP0|HSW_L3_MISS_REMOTE_HOP1| \
+                                        HSW_L3_MISS_REMOTE_HOP2P)
+
+
+static __initconst const u64 hsw_hw_cache_event_ids
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x81d0,  /* MEM_UOPS_RETIRED.ALL_LOADS */
+               [ C(RESULT_MISS)   ] = 0x151,   /* L1D.REPLACEMENT */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x82d0,  /* MEM_UOPS_RETIRED.ALL_STORES */
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x280,   /* ICACHE.MISSES */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
+               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
+               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x81d0,  /* MEM_UOPS_RETIRED.ALL_LOADS */
+               [ C(RESULT_MISS)   ] = 0x108,   /* DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x82d0,  /* MEM_UOPS_RETIRED.ALL_STORES */
+               [ C(RESULT_MISS)   ] = 0x149,   /* DTLB_STORE_MISSES.MISS_CAUSES_A_WALK */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x6085,  /* ITLB_MISSES.STLB_HIT */
+               [ C(RESULT_MISS)   ] = 0x185,   /* ITLB_MISSES.MISS_CAUSES_A_WALK */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0xc4,    /* BR_INST_RETIRED.ALL_BRANCHES */
+               [ C(RESULT_MISS)   ] = 0xc5,    /* BR_MISP_RETIRED.ALL_BRANCHES */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(NODE) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
+               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
+               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+};
+
+static __initconst const u64 hsw_hw_cache_extra_regs
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = HSW_DEMAND_READ|
+                                      HSW_LLC_ACCESS,
+               [ C(RESULT_MISS)   ] = HSW_DEMAND_READ|
+                                      HSW_L3_MISS|HSW_ANY_SNOOP,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = HSW_DEMAND_WRITE|
+                                      HSW_LLC_ACCESS,
+               [ C(RESULT_MISS)   ] = HSW_DEMAND_WRITE|
+                                      HSW_L3_MISS|HSW_ANY_SNOOP,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(NODE) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = HSW_DEMAND_READ|
+                                      HSW_L3_MISS_LOCAL_DRAM|
+                                      HSW_SNOOP_DRAM,
+               [ C(RESULT_MISS)   ] = HSW_DEMAND_READ|
+                                      HSW_L3_MISS_REMOTE|
+                                      HSW_SNOOP_DRAM,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = HSW_DEMAND_WRITE|
+                                      HSW_L3_MISS_LOCAL_DRAM|
+                                      HSW_SNOOP_DRAM,
+               [ C(RESULT_MISS)   ] = HSW_DEMAND_WRITE|
+                                      HSW_L3_MISS_REMOTE|
+                                      HSW_SNOOP_DRAM,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+};
+
 static __initconst const u64 westmere_hw_cache_event_ids
                                [PERF_COUNT_HW_CACHE_MAX]
                                [PERF_COUNT_HW_CACHE_OP_MAX]
@@ -1029,21 +1244,10 @@ static __initconst const u64 slm_hw_cache_event_ids
  },
 };
 
-static inline bool intel_pmu_needs_lbr_smpl(struct perf_event *event)
-{
-       /* user explicitly requested branch sampling */
-       if (has_branch_stack(event))
-               return true;
-
-       /* implicit branch sampling to correct PEBS skid */
-       if (x86_pmu.intel_cap.pebs_trap && event->attr.precise_ip > 1 &&
-           x86_pmu.intel_cap.pebs_format < 2)
-               return true;
-
-       return false;
-}
-
-static void intel_pmu_disable_all(void)
+/*
+ * Use from PMIs where the LBRs are already disabled.
+ */
+static void __intel_pmu_disable_all(void)
 {
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
 
@@ -1051,17 +1255,24 @@ static void intel_pmu_disable_all(void)
 
        if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask))
                intel_pmu_disable_bts();
+       else
+               intel_bts_disable_local();
 
        intel_pmu_pebs_disable_all();
+}
+
+static void intel_pmu_disable_all(void)
+{
+       __intel_pmu_disable_all();
        intel_pmu_lbr_disable_all();
 }
 
-static void intel_pmu_enable_all(int added)
+static void __intel_pmu_enable_all(int added, bool pmi)
 {
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
 
        intel_pmu_pebs_enable_all();
-       intel_pmu_lbr_enable_all();
+       intel_pmu_lbr_enable_all(pmi);
        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL,
                        x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask);
 
@@ -1073,7 +1284,13 @@ static void intel_pmu_enable_all(int added)
                        return;
 
                intel_pmu_enable_bts(event->hw.config);
-       }
+       } else
+               intel_bts_enable_local();
+}
+
+static void intel_pmu_enable_all(int added)
+{
+       __intel_pmu_enable_all(added, false);
 }
 
 /*
@@ -1207,7 +1424,7 @@ static void intel_pmu_disable_event(struct perf_event *event)
         * must disable before any actual event
         * because any event may be combined with LBR
         */
-       if (intel_pmu_needs_lbr_smpl(event))
+       if (needs_branch_stack(event))
                intel_pmu_lbr_disable(event);
 
        if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
@@ -1268,7 +1485,7 @@ static void intel_pmu_enable_event(struct perf_event *event)
         * must enabled before any actual event
         * because any event may be combined with LBR
         */
-       if (intel_pmu_needs_lbr_smpl(event))
+       if (needs_branch_stack(event))
                intel_pmu_lbr_enable(event);
 
        if (event->attr.exclude_host)
@@ -1334,6 +1551,18 @@ static void intel_pmu_reset(void)
        if (ds)
                ds->bts_index = ds->bts_buffer_base;
 
+       /* Ack all overflows and disable fixed counters */
+       if (x86_pmu.version >= 2) {
+               intel_pmu_ack_status(intel_pmu_get_status());
+               wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
+       }
+
+       /* Reset LBRs and LBR freezing */
+       if (x86_pmu.lbr_nr) {
+               update_debugctlmsr(get_debugctlmsr() &
+                       ~(DEBUGCTLMSR_FREEZE_LBRS_ON_PMI|DEBUGCTLMSR_LBR));
+       }
+
        local_irq_restore(flags);
 }
 
@@ -1357,8 +1586,9 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
         */
        if (!x86_pmu.late_ack)
                apic_write(APIC_LVTPC, APIC_DM_NMI);
-       intel_pmu_disable_all();
+       __intel_pmu_disable_all();
        handled = intel_pmu_drain_bts_buffer();
+       handled += intel_bts_interrupt();
        status = intel_pmu_get_status();
        if (!status)
                goto done;
@@ -1398,6 +1628,14 @@ again:
                x86_pmu.drain_pebs(regs);
        }
 
+       /*
+        * Intel PT
+        */
+       if (__test_and_clear_bit(55, (unsigned long *)&status)) {
+               handled++;
+               intel_pt_interrupt();
+       }
+
        /*
         * Checkpointed counters can lead to 'spurious' PMIs because the
         * rollback caused by the PMI will have cleared the overflow status
@@ -1433,7 +1671,7 @@ again:
                goto again;
 
 done:
-       intel_pmu_enable_all(0);
+       __intel_pmu_enable_all(0, true);
        /*
         * Only unmask the NMI after the overflow counters
         * have been reset. This avoids spurious NMIs on
@@ -1464,7 +1702,7 @@ intel_bts_constraints(struct perf_event *event)
 
 static int intel_alt_er(int idx)
 {
-       if (!(x86_pmu.er_flags & ERF_HAS_RSP_1))
+       if (!(x86_pmu.flags & PMU_FL_HAS_RSP_1))
                return idx;
 
        if (idx == EXTRA_REG_RSP_0)
@@ -1624,7 +1862,8 @@ intel_shared_regs_constraints(struct cpu_hw_events *cpuc,
 }
 
 struct event_constraint *
-x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
+x86_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+                         struct perf_event *event)
 {
        struct event_constraint *c;
 
@@ -1641,7 +1880,8 @@ x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
 }
 
 static struct event_constraint *
-intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
+__intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+                           struct perf_event *event)
 {
        struct event_constraint *c;
 
@@ -1657,7 +1897,278 @@ intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event
        if (c)
                return c;
 
-       return x86_get_event_constraints(cpuc, event);
+       return x86_get_event_constraints(cpuc, idx, event);
+}
+
+static void
+intel_start_scheduling(struct cpu_hw_events *cpuc)
+{
+       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
+       struct intel_excl_states *xl, *xlo;
+       int tid = cpuc->excl_thread_id;
+       int o_tid = 1 - tid; /* sibling thread */
+
+       /*
+        * nothing needed if in group validation mode
+        */
+       if (cpuc->is_fake || !is_ht_workaround_enabled())
+               return;
+
+       /*
+        * no exclusion needed
+        */
+       if (!excl_cntrs)
+               return;
+
+       xlo = &excl_cntrs->states[o_tid];
+       xl = &excl_cntrs->states[tid];
+
+       xl->sched_started = true;
+       xl->num_alloc_cntrs = 0;
+       /*
+        * lock shared state until we are done scheduling
+        * in stop_event_scheduling()
+        * makes scheduling appear as a transaction
+        */
+       WARN_ON_ONCE(!irqs_disabled());
+       raw_spin_lock(&excl_cntrs->lock);
+
+       /*
+        * save initial state of sibling thread
+        */
+       memcpy(xlo->init_state, xlo->state, sizeof(xlo->init_state));
+}
+
+static void
+intel_stop_scheduling(struct cpu_hw_events *cpuc)
+{
+       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
+       struct intel_excl_states *xl, *xlo;
+       int tid = cpuc->excl_thread_id;
+       int o_tid = 1 - tid; /* sibling thread */
+
+       /*
+        * nothing needed if in group validation mode
+        */
+       if (cpuc->is_fake || !is_ht_workaround_enabled())
+               return;
+       /*
+        * no exclusion needed
+        */
+       if (!excl_cntrs)
+               return;
+
+       xlo = &excl_cntrs->states[o_tid];
+       xl = &excl_cntrs->states[tid];
+
+       /*
+        * make new sibling thread state visible
+        */
+       memcpy(xlo->state, xlo->init_state, sizeof(xlo->state));
+
+       xl->sched_started = false;
+       /*
+        * release shared state lock (acquired in intel_start_scheduling())
+        */
+       raw_spin_unlock(&excl_cntrs->lock);
+}
+
+static struct event_constraint *
+intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
+                          int idx, struct event_constraint *c)
+{
+       struct event_constraint *cx;
+       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
+       struct intel_excl_states *xl, *xlo;
+       int is_excl, i;
+       int tid = cpuc->excl_thread_id;
+       int o_tid = 1 - tid; /* alternate */
+
+       /*
+        * validating a group does not require
+        * enforcing cross-thread  exclusion
+        */
+       if (cpuc->is_fake || !is_ht_workaround_enabled())
+               return c;
+
+       /*
+        * no exclusion needed
+        */
+       if (!excl_cntrs)
+               return c;
+       /*
+        * event requires exclusive counter access
+        * across HT threads
+        */
+       is_excl = c->flags & PERF_X86_EVENT_EXCL;
+
+       /*
+        * xl = state of current HT
+        * xlo = state of sibling HT
+        */
+       xl = &excl_cntrs->states[tid];
+       xlo = &excl_cntrs->states[o_tid];
+
+       /*
+        * do not allow scheduling of more than max_alloc_cntrs
+        * which is set to half the available generic counters.
+        * this helps avoid counter starvation of sibling thread
+        * by ensuring at most half the counters cannot be in
+        * exclusive mode. There is not designated counters for the
+        * limits. Any N/2 counters can be used. This helps with
+        * events with specifix counter constraints
+        */
+       if (xl->num_alloc_cntrs++ == xl->max_alloc_cntrs)
+               return &emptyconstraint;
+
+       cx = c;
+
+       /*
+        * because we modify the constraint, we need
+        * to make a copy. Static constraints come
+        * from static const tables.
+        *
+        * only needed when constraint has not yet
+        * been cloned (marked dynamic)
+        */
+       if (!(c->flags & PERF_X86_EVENT_DYNAMIC)) {
+
+               /* sanity check */
+               if (idx < 0)
+                       return &emptyconstraint;
+
+               /*
+                * grab pre-allocated constraint entry
+                */
+               cx = &cpuc->constraint_list[idx];
+
+               /*
+                * initialize dynamic constraint
+                * with static constraint
+                */
+               memcpy(cx, c, sizeof(*cx));
+
+               /*
+                * mark constraint as dynamic, so we
+                * can free it later on
+                */
+               cx->flags |= PERF_X86_EVENT_DYNAMIC;
+       }
+
+       /*
+        * From here on, the constraint is dynamic.
+        * Either it was just allocated above, or it
+        * was allocated during a earlier invocation
+        * of this function
+        */
+
+       /*
+        * Modify static constraint with current dynamic
+        * state of thread
+        *
+        * EXCLUSIVE: sibling counter measuring exclusive event
+        * SHARED   : sibling counter measuring non-exclusive event
+        * UNUSED   : sibling counter unused
+        */
+       for_each_set_bit(i, cx->idxmsk, X86_PMC_IDX_MAX) {
+               /*
+                * exclusive event in sibling counter
+                * our corresponding counter cannot be used
+                * regardless of our event
+                */
+               if (xl->state[i] == INTEL_EXCL_EXCLUSIVE)
+                       __clear_bit(i, cx->idxmsk);
+               /*
+                * if measuring an exclusive event, sibling
+                * measuring non-exclusive, then counter cannot
+                * be used
+                */
+               if (is_excl && xl->state[i] == INTEL_EXCL_SHARED)
+                       __clear_bit(i, cx->idxmsk);
+       }
+
+       /*
+        * recompute actual bit weight for scheduling algorithm
+        */
+       cx->weight = hweight64(cx->idxmsk64);
+
+       /*
+        * if we return an empty mask, then switch
+        * back to static empty constraint to avoid
+        * the cost of freeing later on
+        */
+       if (cx->weight == 0)
+               cx = &emptyconstraint;
+
+       return cx;
+}
+
+static struct event_constraint *
+intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+                           struct perf_event *event)
+{
+       struct event_constraint *c1 = event->hw.constraint;
+       struct event_constraint *c2;
+
+       /*
+        * first time only
+        * - static constraint: no change across incremental scheduling calls
+        * - dynamic constraint: handled by intel_get_excl_constraints()
+        */
+       c2 = __intel_get_event_constraints(cpuc, idx, event);
+       if (c1 && (c1->flags & PERF_X86_EVENT_DYNAMIC)) {
+               bitmap_copy(c1->idxmsk, c2->idxmsk, X86_PMC_IDX_MAX);
+               c1->weight = c2->weight;
+               c2 = c1;
+       }
+
+       if (cpuc->excl_cntrs)
+               return intel_get_excl_constraints(cpuc, event, idx, c2);
+
+       return c2;
+}
+
+static void intel_put_excl_constraints(struct cpu_hw_events *cpuc,
+               struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
+       struct intel_excl_states *xlo, *xl;
+       unsigned long flags = 0; /* keep compiler happy */
+       int tid = cpuc->excl_thread_id;
+       int o_tid = 1 - tid;
+
+       /*
+        * nothing needed if in group validation mode
+        */
+       if (cpuc->is_fake)
+               return;
+
+       WARN_ON_ONCE(!excl_cntrs);
+
+       if (!excl_cntrs)
+               return;
+
+       xl = &excl_cntrs->states[tid];
+       xlo = &excl_cntrs->states[o_tid];
+
+       /*
+        * put_constraint may be called from x86_schedule_events()
+        * which already has the lock held so here make locking
+        * conditional
+        */
+       if (!xl->sched_started)
+               raw_spin_lock_irqsave(&excl_cntrs->lock, flags);
+
+       /*
+        * if event was actually assigned, then mark the
+        * counter state as unused now
+        */
+       if (hwc->idx >= 0)
+               xlo->state[hwc->idx] = INTEL_EXCL_UNUSED;
+
+       if (!xl->sched_started)
+               raw_spin_unlock_irqrestore(&excl_cntrs->lock, flags);
 }
 
 static void
@@ -1678,7 +2189,57 @@ intel_put_shared_regs_event_constraints(struct cpu_hw_events *cpuc,
 static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
                                        struct perf_event *event)
 {
+       struct event_constraint *c = event->hw.constraint;
+
        intel_put_shared_regs_event_constraints(cpuc, event);
+
+       /*
+        * is PMU has exclusive counter restrictions, then
+        * all events are subject to and must call the
+        * put_excl_constraints() routine
+        */
+       if (c && cpuc->excl_cntrs)
+               intel_put_excl_constraints(cpuc, event);
+
+       /* cleanup dynamic constraint */
+       if (c && (c->flags & PERF_X86_EVENT_DYNAMIC))
+               event->hw.constraint = NULL;
+}
+
+static void intel_commit_scheduling(struct cpu_hw_events *cpuc,
+                                   struct perf_event *event, int cntr)
+{
+       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
+       struct event_constraint *c = event->hw.constraint;
+       struct intel_excl_states *xlo, *xl;
+       int tid = cpuc->excl_thread_id;
+       int o_tid = 1 - tid;
+       int is_excl;
+
+       if (cpuc->is_fake || !c)
+               return;
+
+       is_excl = c->flags & PERF_X86_EVENT_EXCL;
+
+       if (!(c->flags & PERF_X86_EVENT_DYNAMIC))
+               return;
+
+       WARN_ON_ONCE(!excl_cntrs);
+
+       if (!excl_cntrs)
+               return;
+
+       xl = &excl_cntrs->states[tid];
+       xlo = &excl_cntrs->states[o_tid];
+
+       WARN_ON_ONCE(!raw_spin_is_locked(&excl_cntrs->lock));
+
+       if (cntr >= 0) {
+               if (is_excl)
+                       xlo->init_state[cntr] = INTEL_EXCL_EXCLUSIVE;
+               else
+                       xlo->init_state[cntr] = INTEL_EXCL_SHARED;
+       }
 }
 
 static void intel_pebs_aliases_core2(struct perf_event *event)
@@ -1747,10 +2308,21 @@ static int intel_pmu_hw_config(struct perf_event *event)
        if (event->attr.precise_ip && x86_pmu.pebs_aliases)
                x86_pmu.pebs_aliases(event);
 
-       if (intel_pmu_needs_lbr_smpl(event)) {
+       if (needs_branch_stack(event)) {
                ret = intel_pmu_setup_lbr_filter(event);
                if (ret)
                        return ret;
+
+               /*
+                * BTS is set up earlier in this path, so don't account twice
+                */
+               if (!intel_pmu_has_bts(event)) {
+                       /* disallow lbr if conflicting events are present */
+                       if (x86_add_exclusive(x86_lbr_exclusive_lbr))
+                               return -EBUSY;
+
+                       event->destroy = hw_perf_lbr_event_destroy;
+               }
        }
 
        if (event->attr.type != PERF_TYPE_RAW)
@@ -1891,9 +2463,12 @@ static struct event_constraint counter2_constraint =
                        EVENT_CONSTRAINT(0, 0x4, 0);
 
 static struct event_constraint *
-hsw_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
+hsw_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+                         struct perf_event *event)
 {
-       struct event_constraint *c = intel_get_event_constraints(cpuc, event);
+       struct event_constraint *c;
+
+       c = intel_get_event_constraints(cpuc, idx, event);
 
        /* Handle special quirk on in_tx_checkpointed only in counter 2 */
        if (event->hw.config & HSW_IN_TX_CHECKPOINTED) {
@@ -1905,6 +2480,32 @@ hsw_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
        return c;
 }
 
+/*
+ * Broadwell:
+ *
+ * The INST_RETIRED.ALL period always needs to have lowest 6 bits cleared
+ * (BDM55) and it must not use a period smaller than 100 (BDM11). We combine
+ * the two to enforce a minimum period of 128 (the smallest value that has bits
+ * 0-5 cleared and >= 100).
+ *
+ * Because of how the code in x86_perf_event_set_period() works, the truncation
+ * of the lower 6 bits is 'harmless' as we'll occasionally add a longer period
+ * to make up for the 'lost' events due to carrying the 'error' in period_left.
+ *
+ * Therefore the effective (average) period matches the requested period,
+ * despite coarser hardware granularity.
+ */
+static unsigned bdw_limit_period(struct perf_event *event, unsigned left)
+{
+       if ((event->hw.config & INTEL_ARCH_EVENT_MASK) ==
+                       X86_CONFIG(.event=0xc0, .umask=0x01)) {
+               if (left < 128)
+                       left = 128;
+               left &= ~0x3fu;
+       }
+       return left;
+}
+
 PMU_FORMAT_ATTR(event, "config:0-7"    );
 PMU_FORMAT_ATTR(umask, "config:8-15"   );
 PMU_FORMAT_ATTR(edge,  "config:18"     );
@@ -1979,16 +2580,52 @@ struct intel_shared_regs *allocate_shared_regs(int cpu)
        return regs;
 }
 
+static struct intel_excl_cntrs *allocate_excl_cntrs(int cpu)
+{
+       struct intel_excl_cntrs *c;
+       int i;
+
+       c = kzalloc_node(sizeof(struct intel_excl_cntrs),
+                        GFP_KERNEL, cpu_to_node(cpu));
+       if (c) {
+               raw_spin_lock_init(&c->lock);
+               for (i = 0; i < X86_PMC_IDX_MAX; i++) {
+                       c->states[0].state[i] = INTEL_EXCL_UNUSED;
+                       c->states[0].init_state[i] = INTEL_EXCL_UNUSED;
+
+                       c->states[1].state[i] = INTEL_EXCL_UNUSED;
+                       c->states[1].init_state[i] = INTEL_EXCL_UNUSED;
+               }
+               c->core_id = -1;
+       }
+       return c;
+}
+
 static int intel_pmu_cpu_prepare(int cpu)
 {
        struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
 
-       if (!(x86_pmu.extra_regs || x86_pmu.lbr_sel_map))
-               return NOTIFY_OK;
+       if (x86_pmu.extra_regs || x86_pmu.lbr_sel_map) {
+               cpuc->shared_regs = allocate_shared_regs(cpu);
+               if (!cpuc->shared_regs)
+                       return NOTIFY_BAD;
+       }
 
-       cpuc->shared_regs = allocate_shared_regs(cpu);
-       if (!cpuc->shared_regs)
-               return NOTIFY_BAD;
+       if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
+               size_t sz = X86_PMC_IDX_MAX * sizeof(struct event_constraint);
+
+               cpuc->constraint_list = kzalloc(sz, GFP_KERNEL);
+               if (!cpuc->constraint_list)
+                       return NOTIFY_BAD;
+
+               cpuc->excl_cntrs = allocate_excl_cntrs(cpu);
+               if (!cpuc->excl_cntrs) {
+                       kfree(cpuc->constraint_list);
+                       kfree(cpuc->shared_regs);
+                       return NOTIFY_BAD;
+               }
+               cpuc->excl_thread_id = 0;
+       }
 
        return NOTIFY_OK;
 }
@@ -2010,13 +2647,15 @@ static void intel_pmu_cpu_starting(int cpu)
        if (!cpuc->shared_regs)
                return;
 
-       if (!(x86_pmu.er_flags & ERF_NO_HT_SHARING)) {
+       if (!(x86_pmu.flags & PMU_FL_NO_HT_SHARING)) {
+               void **onln = &cpuc->kfree_on_online[X86_PERF_KFREE_SHARED];
+
                for_each_cpu(i, topology_thread_cpumask(cpu)) {
                        struct intel_shared_regs *pc;
 
                        pc = per_cpu(cpu_hw_events, i).shared_regs;
                        if (pc && pc->core_id == core_id) {
-                               cpuc->kfree_on_online = cpuc->shared_regs;
+                               *onln = cpuc->shared_regs;
                                cpuc->shared_regs = pc;
                                break;
                        }
@@ -2027,6 +2666,44 @@ static void intel_pmu_cpu_starting(int cpu)
 
        if (x86_pmu.lbr_sel_map)
                cpuc->lbr_sel = &cpuc->shared_regs->regs[EXTRA_REG_LBR];
+
+       if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
+               int h = x86_pmu.num_counters >> 1;
+
+               for_each_cpu(i, topology_thread_cpumask(cpu)) {
+                       struct intel_excl_cntrs *c;
+
+                       c = per_cpu(cpu_hw_events, i).excl_cntrs;
+                       if (c && c->core_id == core_id) {
+                               cpuc->kfree_on_online[1] = cpuc->excl_cntrs;
+                               cpuc->excl_cntrs = c;
+                               cpuc->excl_thread_id = 1;
+                               break;
+                       }
+               }
+               cpuc->excl_cntrs->core_id = core_id;
+               cpuc->excl_cntrs->refcnt++;
+               /*
+                * set hard limit to half the number of generic counters
+                */
+               cpuc->excl_cntrs->states[0].max_alloc_cntrs = h;
+               cpuc->excl_cntrs->states[1].max_alloc_cntrs = h;
+       }
+}
+
+static void free_excl_cntrs(int cpu)
+{
+       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+       struct intel_excl_cntrs *c;
+
+       c = cpuc->excl_cntrs;
+       if (c) {
+               if (c->core_id == -1 || --c->refcnt == 0)
+                       kfree(c);
+               cpuc->excl_cntrs = NULL;
+               kfree(cpuc->constraint_list);
+               cpuc->constraint_list = NULL;
+       }
 }
 
 static void intel_pmu_cpu_dying(int cpu)
@@ -2041,19 +2718,9 @@ static void intel_pmu_cpu_dying(int cpu)
                cpuc->shared_regs = NULL;
        }
 
-       fini_debug_store_on_cpu(cpu);
-}
+       free_excl_cntrs(cpu);
 
-static void intel_pmu_flush_branch_stack(void)
-{
-       /*
-        * Intel LBR does not tag entries with the
-        * PID of the current task, then we need to
-        * flush it on ctxsw
-        * For now, we simply reset it
-        */
-       if (x86_pmu.lbr_nr)
-               intel_pmu_lbr_reset();
+       fini_debug_store_on_cpu(cpu);
 }
 
 PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
@@ -2107,7 +2774,7 @@ static __initconst const struct x86_pmu intel_pmu = {
        .cpu_starting           = intel_pmu_cpu_starting,
        .cpu_dying              = intel_pmu_cpu_dying,
        .guest_get_msrs         = intel_guest_get_msrs,
-       .flush_branch_stack     = intel_pmu_flush_branch_stack,
+       .sched_task             = intel_pmu_lbr_sched_task,
 };
 
 static __init void intel_clovertown_quirk(void)
@@ -2264,6 +2931,27 @@ static __init void intel_nehalem_quirk(void)
        }
 }
 
+/*
+ * enable software workaround for errata:
+ * SNB: BJ122
+ * IVB: BV98
+ * HSW: HSD29
+ *
+ * Only needed when HT is enabled. However detecting
+ * if HT is enabled is difficult (model specific). So instead,
+ * we enable the workaround in the early boot, and verify if
+ * it is needed in a later initcall phase once we have valid
+ * topology information to check if HT is actually enabled
+ */
+static __init void intel_ht_bug(void)
+{
+       x86_pmu.flags |= PMU_FL_EXCL_CNTRS | PMU_FL_EXCL_ENABLED;
+
+       x86_pmu.commit_scheduling = intel_commit_scheduling;
+       x86_pmu.start_scheduling = intel_start_scheduling;
+       x86_pmu.stop_scheduling = intel_stop_scheduling;
+}
+
 EVENT_ATTR_STR(mem-loads,      mem_ld_hsw,     "event=0xcd,umask=0x1,ldlat=3");
 EVENT_ATTR_STR(mem-stores,     mem_st_hsw,     "event=0xd0,umask=0x82")
 
@@ -2443,7 +3131,7 @@ __init int intel_pmu_init(void)
                x86_pmu.event_constraints = intel_slm_event_constraints;
                x86_pmu.pebs_constraints = intel_slm_pebs_event_constraints;
                x86_pmu.extra_regs = intel_slm_extra_regs;
-               x86_pmu.er_flags |= ERF_HAS_RSP_1;
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
                pr_cont("Silvermont events, ");
                break;
 
@@ -2461,7 +3149,7 @@ __init int intel_pmu_init(void)
                x86_pmu.enable_all = intel_pmu_nhm_enable_all;
                x86_pmu.pebs_constraints = intel_westmere_pebs_event_constraints;
                x86_pmu.extra_regs = intel_westmere_extra_regs;
-               x86_pmu.er_flags |= ERF_HAS_RSP_1;
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
 
                x86_pmu.cpu_events = nhm_events_attrs;
 
@@ -2478,6 +3166,7 @@ __init int intel_pmu_init(void)
        case 42: /* 32nm SandyBridge         */
        case 45: /* 32nm SandyBridge-E/EN/EP */
                x86_add_quirk(intel_sandybridge_quirk);
+               x86_add_quirk(intel_ht_bug);
                memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
@@ -2492,9 +3181,11 @@ __init int intel_pmu_init(void)
                        x86_pmu.extra_regs = intel_snbep_extra_regs;
                else
                        x86_pmu.extra_regs = intel_snb_extra_regs;
+
+
                /* all extra regs are per-cpu when HT is on */
-               x86_pmu.er_flags |= ERF_HAS_RSP_1;
-               x86_pmu.er_flags |= ERF_NO_HT_SHARING;
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
 
                x86_pmu.cpu_events = snb_events_attrs;
 
@@ -2510,6 +3201,7 @@ __init int intel_pmu_init(void)
 
        case 58: /* 22nm IvyBridge       */
        case 62: /* 22nm IvyBridge-EP/EX */
+               x86_add_quirk(intel_ht_bug);
                memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
                /* dTLB-load-misses on IVB is different than SNB */
@@ -2528,8 +3220,8 @@ __init int intel_pmu_init(void)
                else
                        x86_pmu.extra_regs = intel_snb_extra_regs;
                /* all extra regs are per-cpu when HT is on */
-               x86_pmu.er_flags |= ERF_HAS_RSP_1;
-               x86_pmu.er_flags |= ERF_NO_HT_SHARING;
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
 
                x86_pmu.cpu_events = snb_events_attrs;
 
@@ -2545,19 +3237,20 @@ __init int intel_pmu_init(void)
        case 63: /* 22nm Haswell Server */
        case 69: /* 22nm Haswell ULT */
        case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
+               x86_add_quirk(intel_ht_bug);
                x86_pmu.late_ack = true;
-               memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, sizeof(hw_cache_event_ids));
-               memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
+               memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
+               memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
 
-               intel_pmu_lbr_init_snb();
+               intel_pmu_lbr_init_hsw();
 
                x86_pmu.event_constraints = intel_hsw_event_constraints;
                x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints;
                x86_pmu.extra_regs = intel_snbep_extra_regs;
                x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
                /* all extra regs are per-cpu when HT is on */
-               x86_pmu.er_flags |= ERF_HAS_RSP_1;
-               x86_pmu.er_flags |= ERF_NO_HT_SHARING;
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
 
                x86_pmu.hw_config = hsw_hw_config;
                x86_pmu.get_event_constraints = hsw_get_event_constraints;
@@ -2566,6 +3259,39 @@ __init int intel_pmu_init(void)
                pr_cont("Haswell events, ");
                break;
 
+       case 61: /* 14nm Broadwell Core-M */
+       case 86: /* 14nm Broadwell Xeon D */
+               x86_pmu.late_ack = true;
+               memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
+               memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
+
+               /* L3_MISS_LOCAL_DRAM is BIT(26) in Broadwell */
+               hw_cache_extra_regs[C(LL)][C(OP_READ)][C(RESULT_MISS)] = HSW_DEMAND_READ |
+                                                                        BDW_L3_MISS|HSW_SNOOP_DRAM;
+               hw_cache_extra_regs[C(LL)][C(OP_WRITE)][C(RESULT_MISS)] = HSW_DEMAND_WRITE|BDW_L3_MISS|
+                                                                         HSW_SNOOP_DRAM;
+               hw_cache_extra_regs[C(NODE)][C(OP_READ)][C(RESULT_ACCESS)] = HSW_DEMAND_READ|
+                                                                            BDW_L3_MISS_LOCAL|HSW_SNOOP_DRAM;
+               hw_cache_extra_regs[C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = HSW_DEMAND_WRITE|
+                                                                             BDW_L3_MISS_LOCAL|HSW_SNOOP_DRAM;
+
+               intel_pmu_lbr_init_snb();
+
+               x86_pmu.event_constraints = intel_bdw_event_constraints;
+               x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints;
+               x86_pmu.extra_regs = intel_snbep_extra_regs;
+               x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
+               /* all extra regs are per-cpu when HT is on */
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
+
+               x86_pmu.hw_config = hsw_hw_config;
+               x86_pmu.get_event_constraints = hsw_get_event_constraints;
+               x86_pmu.cpu_events = hsw_events_attrs;
+               x86_pmu.limit_period = bdw_limit_period;
+               pr_cont("Broadwell events, ");
+               break;
+
        default:
                switch (x86_pmu.version) {
                case 1:
@@ -2651,3 +3377,47 @@ __init int intel_pmu_init(void)
 
        return 0;
 }
+
+/*
+ * HT bug: phase 2 init
+ * Called once we have valid topology information to check
+ * whether or not HT is enabled
+ * If HT is off, then we disable the workaround
+ */
+static __init int fixup_ht_bug(void)
+{
+       int cpu = smp_processor_id();
+       int w, c;
+       /*
+        * problem not present on this CPU model, nothing to do
+        */
+       if (!(x86_pmu.flags & PMU_FL_EXCL_ENABLED))
+               return 0;
+
+       w = cpumask_weight(topology_thread_cpumask(cpu));
+       if (w > 1) {
+               pr_info("PMU erratum BJ122, BV98, HSD29 worked around, HT is on\n");
+               return 0;
+       }
+
+       watchdog_nmi_disable_all();
+
+       x86_pmu.flags &= ~(PMU_FL_EXCL_CNTRS | PMU_FL_EXCL_ENABLED);
+
+       x86_pmu.commit_scheduling = NULL;
+       x86_pmu.start_scheduling = NULL;
+       x86_pmu.stop_scheduling = NULL;
+
+       watchdog_nmi_enable_all();
+
+       get_online_cpus();
+
+       for_each_online_cpu(c) {
+               free_excl_cntrs(c);
+       }
+
+       put_online_cpus();
+       pr_info("PMU erratum BJ122, BV98, HSD29 workaround disabled, HT off\n");
+       return 0;
+}
+subsys_initcall(fixup_ht_bug)
diff --git a/arch/x86/kernel/cpu/perf_event_intel_bts.c b/arch/x86/kernel/cpu/perf_event_intel_bts.c
new file mode 100644 (file)
index 0000000..ac1f0c5
--- /dev/null
@@ -0,0 +1,525 @@
+/*
+ * BTS PMU driver for perf
+ * Copyright (c) 2013-2014, 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.
+ */
+
+#undef DEBUG
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/coredump.h>
+
+#include <asm-generic/sizes.h>
+#include <asm/perf_event.h>
+
+#include "perf_event.h"
+
+struct bts_ctx {
+       struct perf_output_handle       handle;
+       struct debug_store              ds_back;
+       int                             started;
+};
+
+static DEFINE_PER_CPU(struct bts_ctx, bts_ctx);
+
+#define BTS_RECORD_SIZE                24
+#define BTS_SAFETY_MARGIN      4080
+
+struct bts_phys {
+       struct page     *page;
+       unsigned long   size;
+       unsigned long   offset;
+       unsigned long   displacement;
+};
+
+struct bts_buffer {
+       size_t          real_size;      /* multiple of BTS_RECORD_SIZE */
+       unsigned int    nr_pages;
+       unsigned int    nr_bufs;
+       unsigned int    cur_buf;
+       bool            snapshot;
+       local_t         data_size;
+       local_t         lost;
+       local_t         head;
+       unsigned long   end;
+       void            **data_pages;
+       struct bts_phys buf[0];
+};
+
+struct pmu bts_pmu;
+
+void intel_pmu_enable_bts(u64 config);
+void intel_pmu_disable_bts(void);
+
+static size_t buf_size(struct page *page)
+{
+       return 1 << (PAGE_SHIFT + page_private(page));
+}
+
+static void *
+bts_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool overwrite)
+{
+       struct bts_buffer *buf;
+       struct page *page;
+       int node = (cpu == -1) ? cpu : cpu_to_node(cpu);
+       unsigned long offset;
+       size_t size = nr_pages << PAGE_SHIFT;
+       int pg, nbuf, pad;
+
+       /* count all the high order buffers */
+       for (pg = 0, nbuf = 0; pg < nr_pages;) {
+               page = virt_to_page(pages[pg]);
+               if (WARN_ON_ONCE(!PagePrivate(page) && nr_pages > 1))
+                       return NULL;
+               pg += 1 << page_private(page);
+               nbuf++;
+       }
+
+       /*
+        * to avoid interrupts in overwrite mode, only allow one physical
+        */
+       if (overwrite && nbuf > 1)
+               return NULL;
+
+       buf = kzalloc_node(offsetof(struct bts_buffer, buf[nbuf]), GFP_KERNEL, node);
+       if (!buf)
+               return NULL;
+
+       buf->nr_pages = nr_pages;
+       buf->nr_bufs = nbuf;
+       buf->snapshot = overwrite;
+       buf->data_pages = pages;
+       buf->real_size = size - size % BTS_RECORD_SIZE;
+
+       for (pg = 0, nbuf = 0, offset = 0, pad = 0; nbuf < buf->nr_bufs; nbuf++) {
+               unsigned int __nr_pages;
+
+               page = virt_to_page(pages[pg]);
+               __nr_pages = PagePrivate(page) ? 1 << page_private(page) : 1;
+               buf->buf[nbuf].page = page;
+               buf->buf[nbuf].offset = offset;
+               buf->buf[nbuf].displacement = (pad ? BTS_RECORD_SIZE - pad : 0);
+               buf->buf[nbuf].size = buf_size(page) - buf->buf[nbuf].displacement;
+               pad = buf->buf[nbuf].size % BTS_RECORD_SIZE;
+               buf->buf[nbuf].size -= pad;
+
+               pg += __nr_pages;
+               offset += __nr_pages << PAGE_SHIFT;
+       }
+
+       return buf;
+}
+
+static void bts_buffer_free_aux(void *data)
+{
+       kfree(data);
+}
+
+static unsigned long bts_buffer_offset(struct bts_buffer *buf, unsigned int idx)
+{
+       return buf->buf[idx].offset + buf->buf[idx].displacement;
+}
+
+static void
+bts_config_buffer(struct bts_buffer *buf)
+{
+       int cpu = raw_smp_processor_id();
+       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
+       struct bts_phys *phys = &buf->buf[buf->cur_buf];
+       unsigned long index, thresh = 0, end = phys->size;
+       struct page *page = phys->page;
+
+       index = local_read(&buf->head);
+
+       if (!buf->snapshot) {
+               if (buf->end < phys->offset + buf_size(page))
+                       end = buf->end - phys->offset - phys->displacement;
+
+               index -= phys->offset + phys->displacement;
+
+               if (end - index > BTS_SAFETY_MARGIN)
+                       thresh = end - BTS_SAFETY_MARGIN;
+               else if (end - index > BTS_RECORD_SIZE)
+                       thresh = end - BTS_RECORD_SIZE;
+               else
+                       thresh = end;
+       }
+
+       ds->bts_buffer_base = (u64)(long)page_address(page) + phys->displacement;
+       ds->bts_index = ds->bts_buffer_base + index;
+       ds->bts_absolute_maximum = ds->bts_buffer_base + end;
+       ds->bts_interrupt_threshold = !buf->snapshot
+               ? ds->bts_buffer_base + thresh
+               : ds->bts_absolute_maximum + BTS_RECORD_SIZE;
+}
+
+static void bts_buffer_pad_out(struct bts_phys *phys, unsigned long head)
+{
+       unsigned long index = head - phys->offset;
+
+       memset(page_address(phys->page) + index, 0, phys->size - index);
+}
+
+static bool bts_buffer_is_full(struct bts_buffer *buf, struct bts_ctx *bts)
+{
+       if (buf->snapshot)
+               return false;
+
+       if (local_read(&buf->data_size) >= bts->handle.size ||
+           bts->handle.size - local_read(&buf->data_size) < BTS_RECORD_SIZE)
+               return true;
+
+       return false;
+}
+
+static void bts_update(struct bts_ctx *bts)
+{
+       int cpu = raw_smp_processor_id();
+       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
+       struct bts_buffer *buf = perf_get_aux(&bts->handle);
+       unsigned long index = ds->bts_index - ds->bts_buffer_base, old, head;
+
+       if (!buf)
+               return;
+
+       head = index + bts_buffer_offset(buf, buf->cur_buf);
+       old = local_xchg(&buf->head, head);
+
+       if (!buf->snapshot) {
+               if (old == head)
+                       return;
+
+               if (ds->bts_index >= ds->bts_absolute_maximum)
+                       local_inc(&buf->lost);
+
+               /*
+                * old and head are always in the same physical buffer, so we
+                * can subtract them to get the data size.
+                */
+               local_add(head - old, &buf->data_size);
+       } else {
+               local_set(&buf->data_size, head);
+       }
+}
+
+static void __bts_event_start(struct perf_event *event)
+{
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+       struct bts_buffer *buf = perf_get_aux(&bts->handle);
+       u64 config = 0;
+
+       if (!buf || bts_buffer_is_full(buf, bts))
+               return;
+
+       event->hw.state = 0;
+
+       if (!buf->snapshot)
+               config |= ARCH_PERFMON_EVENTSEL_INT;
+       if (!event->attr.exclude_kernel)
+               config |= ARCH_PERFMON_EVENTSEL_OS;
+       if (!event->attr.exclude_user)
+               config |= ARCH_PERFMON_EVENTSEL_USR;
+
+       bts_config_buffer(buf);
+
+       /*
+        * local barrier to make sure that ds configuration made it
+        * before we enable BTS
+        */
+       wmb();
+
+       intel_pmu_enable_bts(config);
+}
+
+static void bts_event_start(struct perf_event *event, int flags)
+{
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+
+       __bts_event_start(event);
+
+       /* PMI handler: this counter is running and likely generating PMIs */
+       ACCESS_ONCE(bts->started) = 1;
+}
+
+static void __bts_event_stop(struct perf_event *event)
+{
+       /*
+        * No extra synchronization is mandated by the documentation to have
+        * BTS data stores globally visible.
+        */
+       intel_pmu_disable_bts();
+
+       if (event->hw.state & PERF_HES_STOPPED)
+               return;
+
+       ACCESS_ONCE(event->hw.state) |= PERF_HES_STOPPED;
+}
+
+static void bts_event_stop(struct perf_event *event, int flags)
+{
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+
+       /* PMI handler: don't restart this counter */
+       ACCESS_ONCE(bts->started) = 0;
+
+       __bts_event_stop(event);
+
+       if (flags & PERF_EF_UPDATE)
+               bts_update(bts);
+}
+
+void intel_bts_enable_local(void)
+{
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+
+       if (bts->handle.event && bts->started)
+               __bts_event_start(bts->handle.event);
+}
+
+void intel_bts_disable_local(void)
+{
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+
+       if (bts->handle.event)
+               __bts_event_stop(bts->handle.event);
+}
+
+static int
+bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle)
+{
+       unsigned long head, space, next_space, pad, gap, skip, wakeup;
+       unsigned int next_buf;
+       struct bts_phys *phys, *next_phys;
+       int ret;
+
+       if (buf->snapshot)
+               return 0;
+
+       head = handle->head & ((buf->nr_pages << PAGE_SHIFT) - 1);
+       if (WARN_ON_ONCE(head != local_read(&buf->head)))
+               return -EINVAL;
+
+       phys = &buf->buf[buf->cur_buf];
+       space = phys->offset + phys->displacement + phys->size - head;
+       pad = space;
+       if (space > handle->size) {
+               space = handle->size;
+               space -= space % BTS_RECORD_SIZE;
+       }
+       if (space <= BTS_SAFETY_MARGIN) {
+               /* See if next phys buffer has more space */
+               next_buf = buf->cur_buf + 1;
+               if (next_buf >= buf->nr_bufs)
+                       next_buf = 0;
+               next_phys = &buf->buf[next_buf];
+               gap = buf_size(phys->page) - phys->displacement - phys->size +
+                     next_phys->displacement;
+               skip = pad + gap;
+               if (handle->size >= skip) {
+                       next_space = next_phys->size;
+                       if (next_space + skip > handle->size) {
+                               next_space = handle->size - skip;
+                               next_space -= next_space % BTS_RECORD_SIZE;
+                       }
+                       if (next_space > space || !space) {
+                               if (pad)
+                                       bts_buffer_pad_out(phys, head);
+                               ret = perf_aux_output_skip(handle, skip);
+                               if (ret)
+                                       return ret;
+                               /* Advance to next phys buffer */
+                               phys = next_phys;
+                               space = next_space;
+                               head = phys->offset + phys->displacement;
+                               /*
+                                * After this, cur_buf and head won't match ds
+                                * anymore, so we must not be racing with
+                                * bts_update().
+                                */
+                               buf->cur_buf = next_buf;
+                               local_set(&buf->head, head);
+                       }
+               }
+       }
+
+       /* Don't go far beyond wakeup watermark */
+       wakeup = BTS_SAFETY_MARGIN + BTS_RECORD_SIZE + handle->wakeup -
+                handle->head;
+       if (space > wakeup) {
+               space = wakeup;
+               space -= space % BTS_RECORD_SIZE;
+       }
+
+       buf->end = head + space;
+
+       /*
+        * If we have no space, the lost notification would have been sent when
+        * we hit absolute_maximum - see bts_update()
+        */
+       if (!space)
+               return -ENOSPC;
+
+       return 0;
+}
+
+int intel_bts_interrupt(void)
+{
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+       struct perf_event *event = bts->handle.event;
+       struct bts_buffer *buf;
+       s64 old_head;
+       int err;
+
+       if (!event || !bts->started)
+               return 0;
+
+       buf = perf_get_aux(&bts->handle);
+       /*
+        * Skip snapshot counters: they don't use the interrupt, but
+        * there's no other way of telling, because the pointer will
+        * keep moving
+        */
+       if (!buf || buf->snapshot)
+               return 0;
+
+       old_head = local_read(&buf->head);
+       bts_update(bts);
+
+       /* no new data */
+       if (old_head == local_read(&buf->head))
+               return 0;
+
+       perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
+                           !!local_xchg(&buf->lost, 0));
+
+       buf = perf_aux_output_begin(&bts->handle, event);
+       if (!buf)
+               return 1;
+
+       err = bts_buffer_reset(buf, &bts->handle);
+       if (err)
+               perf_aux_output_end(&bts->handle, 0, false);
+
+       return 1;
+}
+
+static void bts_event_del(struct perf_event *event, int mode)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+       struct bts_buffer *buf = perf_get_aux(&bts->handle);
+
+       bts_event_stop(event, PERF_EF_UPDATE);
+
+       if (buf) {
+               if (buf->snapshot)
+                       bts->handle.head =
+                               local_xchg(&buf->data_size,
+                                          buf->nr_pages << PAGE_SHIFT);
+               perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
+                                   !!local_xchg(&buf->lost, 0));
+       }
+
+       cpuc->ds->bts_index = bts->ds_back.bts_buffer_base;
+       cpuc->ds->bts_buffer_base = bts->ds_back.bts_buffer_base;
+       cpuc->ds->bts_absolute_maximum = bts->ds_back.bts_absolute_maximum;
+       cpuc->ds->bts_interrupt_threshold = bts->ds_back.bts_interrupt_threshold;
+}
+
+static int bts_event_add(struct perf_event *event, int mode)
+{
+       struct bts_buffer *buf;
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct hw_perf_event *hwc = &event->hw;
+       int ret = -EBUSY;
+
+       event->hw.state = PERF_HES_STOPPED;
+
+       if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask))
+               return -EBUSY;
+
+       if (bts->handle.event)
+               return -EBUSY;
+
+       buf = perf_aux_output_begin(&bts->handle, event);
+       if (!buf)
+               return -EINVAL;
+
+       ret = bts_buffer_reset(buf, &bts->handle);
+       if (ret) {
+               perf_aux_output_end(&bts->handle, 0, false);
+               return ret;
+       }
+
+       bts->ds_back.bts_buffer_base = cpuc->ds->bts_buffer_base;
+       bts->ds_back.bts_absolute_maximum = cpuc->ds->bts_absolute_maximum;
+       bts->ds_back.bts_interrupt_threshold = cpuc->ds->bts_interrupt_threshold;
+
+       if (mode & PERF_EF_START) {
+               bts_event_start(event, 0);
+               if (hwc->state & PERF_HES_STOPPED) {
+                       bts_event_del(event, 0);
+                       return -EBUSY;
+               }
+       }
+
+       return 0;
+}
+
+static void bts_event_destroy(struct perf_event *event)
+{
+       x86_del_exclusive(x86_lbr_exclusive_bts);
+}
+
+static int bts_event_init(struct perf_event *event)
+{
+       if (event->attr.type != bts_pmu.type)
+               return -ENOENT;
+
+       if (x86_add_exclusive(x86_lbr_exclusive_bts))
+               return -EBUSY;
+
+       event->destroy = bts_event_destroy;
+
+       return 0;
+}
+
+static void bts_event_read(struct perf_event *event)
+{
+}
+
+static __init int bts_init(void)
+{
+       if (!boot_cpu_has(X86_FEATURE_DTES64) || !x86_pmu.bts)
+               return -ENODEV;
+
+       bts_pmu.capabilities    = PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_ITRACE;
+       bts_pmu.task_ctx_nr     = perf_sw_context;
+       bts_pmu.event_init      = bts_event_init;
+       bts_pmu.add             = bts_event_add;
+       bts_pmu.del             = bts_event_del;
+       bts_pmu.start           = bts_event_start;
+       bts_pmu.stop            = bts_event_stop;
+       bts_pmu.read            = bts_event_read;
+       bts_pmu.setup_aux       = bts_buffer_setup_aux;
+       bts_pmu.free_aux        = bts_buffer_free_aux;
+
+       return perf_pmu_register(&bts_pmu, "intel_bts", -1);
+}
+
+module_init(bts_init);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_cqm.c b/arch/x86/kernel/cpu/perf_event_intel_cqm.c
new file mode 100644 (file)
index 0000000..e4d1b8b
--- /dev/null
@@ -0,0 +1,1379 @@
+/*
+ * Intel Cache Quality-of-Service Monitoring (CQM) support.
+ *
+ * Based very, very heavily on work by Peter Zijlstra.
+ */
+
+#include <linux/perf_event.h>
+#include <linux/slab.h>
+#include <asm/cpu_device_id.h>
+#include "perf_event.h"
+
+#define MSR_IA32_PQR_ASSOC     0x0c8f
+#define MSR_IA32_QM_CTR                0x0c8e
+#define MSR_IA32_QM_EVTSEL     0x0c8d
+
+static unsigned int cqm_max_rmid = -1;
+static unsigned int cqm_l3_scale; /* supposedly cacheline size */
+
+struct intel_cqm_state {
+       raw_spinlock_t          lock;
+       int                     rmid;
+       int                     cnt;
+};
+
+static DEFINE_PER_CPU(struct intel_cqm_state, cqm_state);
+
+/*
+ * Protects cache_cgroups and cqm_rmid_free_lru and cqm_rmid_limbo_lru.
+ * Also protects event->hw.cqm_rmid
+ *
+ * Hold either for stability, both for modification of ->hw.cqm_rmid.
+ */
+static DEFINE_MUTEX(cache_mutex);
+static DEFINE_RAW_SPINLOCK(cache_lock);
+
+/*
+ * Groups of events that have the same target(s), one RMID per group.
+ */
+static LIST_HEAD(cache_groups);
+
+/*
+ * Mask of CPUs for reading CQM values. We only need one per-socket.
+ */
+static cpumask_t cqm_cpumask;
+
+#define RMID_VAL_ERROR         (1ULL << 63)
+#define RMID_VAL_UNAVAIL       (1ULL << 62)
+
+#define QOS_L3_OCCUP_EVENT_ID  (1 << 0)
+
+#define QOS_EVENT_MASK QOS_L3_OCCUP_EVENT_ID
+
+/*
+ * This is central to the rotation algorithm in __intel_cqm_rmid_rotate().
+ *
+ * This rmid is always free and is guaranteed to have an associated
+ * near-zero occupancy value, i.e. no cachelines are tagged with this
+ * RMID, once __intel_cqm_rmid_rotate() returns.
+ */
+static unsigned int intel_cqm_rotation_rmid;
+
+#define INVALID_RMID           (-1)
+
+/*
+ * Is @rmid valid for programming the hardware?
+ *
+ * rmid 0 is reserved by the hardware for all non-monitored tasks, which
+ * means that we should never come across an rmid with that value.
+ * Likewise, an rmid value of -1 is used to indicate "no rmid currently
+ * assigned" and is used as part of the rotation code.
+ */
+static inline bool __rmid_valid(unsigned int rmid)
+{
+       if (!rmid || rmid == INVALID_RMID)
+               return false;
+
+       return true;
+}
+
+static u64 __rmid_read(unsigned int rmid)
+{
+       u64 val;
+
+       /*
+        * Ignore the SDM, this thing is _NOTHING_ like a regular perfcnt,
+        * it just says that to increase confusion.
+        */
+       wrmsr(MSR_IA32_QM_EVTSEL, QOS_L3_OCCUP_EVENT_ID, rmid);
+       rdmsrl(MSR_IA32_QM_CTR, val);
+
+       /*
+        * Aside from the ERROR and UNAVAIL bits, assume this thing returns
+        * the number of cachelines tagged with @rmid.
+        */
+       return val;
+}
+
+enum rmid_recycle_state {
+       RMID_YOUNG = 0,
+       RMID_AVAILABLE,
+       RMID_DIRTY,
+};
+
+struct cqm_rmid_entry {
+       unsigned int rmid;
+       enum rmid_recycle_state state;
+       struct list_head list;
+       unsigned long queue_time;
+};
+
+/*
+ * cqm_rmid_free_lru - A least recently used list of RMIDs.
+ *
+ * Oldest entry at the head, newest (most recently used) entry at the
+ * tail. This list is never traversed, it's only used to keep track of
+ * the lru order. That is, we only pick entries of the head or insert
+ * them on the tail.
+ *
+ * All entries on the list are 'free', and their RMIDs are not currently
+ * in use. To mark an RMID as in use, remove its entry from the lru
+ * list.
+ *
+ *
+ * cqm_rmid_limbo_lru - list of currently unused but (potentially) dirty RMIDs.
+ *
+ * This list is contains RMIDs that no one is currently using but that
+ * may have a non-zero occupancy value associated with them. The
+ * rotation worker moves RMIDs from the limbo list to the free list once
+ * the occupancy value drops below __intel_cqm_threshold.
+ *
+ * Both lists are protected by cache_mutex.
+ */
+static LIST_HEAD(cqm_rmid_free_lru);
+static LIST_HEAD(cqm_rmid_limbo_lru);
+
+/*
+ * We use a simple array of pointers so that we can lookup a struct
+ * cqm_rmid_entry in O(1). This alleviates the callers of __get_rmid()
+ * and __put_rmid() from having to worry about dealing with struct
+ * cqm_rmid_entry - they just deal with rmids, i.e. integers.
+ *
+ * Once this array is initialized it is read-only. No locks are required
+ * to access it.
+ *
+ * All entries for all RMIDs can be looked up in the this array at all
+ * times.
+ */
+static struct cqm_rmid_entry **cqm_rmid_ptrs;
+
+static inline struct cqm_rmid_entry *__rmid_entry(int rmid)
+{
+       struct cqm_rmid_entry *entry;
+
+       entry = cqm_rmid_ptrs[rmid];
+       WARN_ON(entry->rmid != rmid);
+
+       return entry;
+}
+
+/*
+ * Returns < 0 on fail.
+ *
+ * We expect to be called with cache_mutex held.
+ */
+static int __get_rmid(void)
+{
+       struct cqm_rmid_entry *entry;
+
+       lockdep_assert_held(&cache_mutex);
+
+       if (list_empty(&cqm_rmid_free_lru))
+               return INVALID_RMID;
+
+       entry = list_first_entry(&cqm_rmid_free_lru, struct cqm_rmid_entry, list);
+       list_del(&entry->list);
+
+       return entry->rmid;
+}
+
+static void __put_rmid(unsigned int rmid)
+{
+       struct cqm_rmid_entry *entry;
+
+       lockdep_assert_held(&cache_mutex);
+
+       WARN_ON(!__rmid_valid(rmid));
+       entry = __rmid_entry(rmid);
+
+       entry->queue_time = jiffies;
+       entry->state = RMID_YOUNG;
+
+       list_add_tail(&entry->list, &cqm_rmid_limbo_lru);
+}
+
+static int intel_cqm_setup_rmid_cache(void)
+{
+       struct cqm_rmid_entry *entry;
+       unsigned int nr_rmids;
+       int r = 0;
+
+       nr_rmids = cqm_max_rmid + 1;
+       cqm_rmid_ptrs = kmalloc(sizeof(struct cqm_rmid_entry *) *
+                               nr_rmids, GFP_KERNEL);
+       if (!cqm_rmid_ptrs)
+               return -ENOMEM;
+
+       for (; r <= cqm_max_rmid; r++) {
+               struct cqm_rmid_entry *entry;
+
+               entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+               if (!entry)
+                       goto fail;
+
+               INIT_LIST_HEAD(&entry->list);
+               entry->rmid = r;
+               cqm_rmid_ptrs[r] = entry;
+
+               list_add_tail(&entry->list, &cqm_rmid_free_lru);
+       }
+
+       /*
+        * RMID 0 is special and is always allocated. It's used for all
+        * tasks that are not monitored.
+        */
+       entry = __rmid_entry(0);
+       list_del(&entry->list);
+
+       mutex_lock(&cache_mutex);
+       intel_cqm_rotation_rmid = __get_rmid();
+       mutex_unlock(&cache_mutex);
+
+       return 0;
+fail:
+       while (r--)
+               kfree(cqm_rmid_ptrs[r]);
+
+       kfree(cqm_rmid_ptrs);
+       return -ENOMEM;
+}
+
+/*
+ * Determine if @a and @b measure the same set of tasks.
+ *
+ * If @a and @b measure the same set of tasks then we want to share a
+ * single RMID.
+ */
+static bool __match_event(struct perf_event *a, struct perf_event *b)
+{
+       /* Per-cpu and task events don't mix */
+       if ((a->attach_state & PERF_ATTACH_TASK) !=
+           (b->attach_state & PERF_ATTACH_TASK))
+               return false;
+
+#ifdef CONFIG_CGROUP_PERF
+       if (a->cgrp != b->cgrp)
+               return false;
+#endif
+
+       /* If not task event, we're machine wide */
+       if (!(b->attach_state & PERF_ATTACH_TASK))
+               return true;
+
+       /*
+        * Events that target same task are placed into the same cache group.
+        */
+       if (a->hw.target == b->hw.target)
+               return true;
+
+       /*
+        * Are we an inherited event?
+        */
+       if (b->parent == a)
+               return true;
+
+       return false;
+}
+
+#ifdef CONFIG_CGROUP_PERF
+static inline struct perf_cgroup *event_to_cgroup(struct perf_event *event)
+{
+       if (event->attach_state & PERF_ATTACH_TASK)
+               return perf_cgroup_from_task(event->hw.target);
+
+       return event->cgrp;
+}
+#endif
+
+/*
+ * Determine if @a's tasks intersect with @b's tasks
+ *
+ * There are combinations of events that we explicitly prohibit,
+ *
+ *                PROHIBITS
+ *     system-wide    ->       cgroup and task
+ *     cgroup        ->        system-wide
+ *                           ->        task in cgroup
+ *     task          ->        system-wide
+ *                           ->        task in cgroup
+ *
+ * Call this function before allocating an RMID.
+ */
+static bool __conflict_event(struct perf_event *a, struct perf_event *b)
+{
+#ifdef CONFIG_CGROUP_PERF
+       /*
+        * We can have any number of cgroups but only one system-wide
+        * event at a time.
+        */
+       if (a->cgrp && b->cgrp) {
+               struct perf_cgroup *ac = a->cgrp;
+               struct perf_cgroup *bc = b->cgrp;
+
+               /*
+                * This condition should have been caught in
+                * __match_event() and we should be sharing an RMID.
+                */
+               WARN_ON_ONCE(ac == bc);
+
+               if (cgroup_is_descendant(ac->css.cgroup, bc->css.cgroup) ||
+                   cgroup_is_descendant(bc->css.cgroup, ac->css.cgroup))
+                       return true;
+
+               return false;
+       }
+
+       if (a->cgrp || b->cgrp) {
+               struct perf_cgroup *ac, *bc;
+
+               /*
+                * cgroup and system-wide events are mutually exclusive
+                */
+               if ((a->cgrp && !(b->attach_state & PERF_ATTACH_TASK)) ||
+                   (b->cgrp && !(a->attach_state & PERF_ATTACH_TASK)))
+                       return true;
+
+               /*
+                * Ensure neither event is part of the other's cgroup
+                */
+               ac = event_to_cgroup(a);
+               bc = event_to_cgroup(b);
+               if (ac == bc)
+                       return true;
+
+               /*
+                * Must have cgroup and non-intersecting task events.
+                */
+               if (!ac || !bc)
+                       return false;
+
+               /*
+                * We have cgroup and task events, and the task belongs
+                * to a cgroup. Check for for overlap.
+                */
+               if (cgroup_is_descendant(ac->css.cgroup, bc->css.cgroup) ||
+                   cgroup_is_descendant(bc->css.cgroup, ac->css.cgroup))
+                       return true;
+
+               return false;
+       }
+#endif
+       /*
+        * If one of them is not a task, same story as above with cgroups.
+        */
+       if (!(a->attach_state & PERF_ATTACH_TASK) ||
+           !(b->attach_state & PERF_ATTACH_TASK))
+               return true;
+
+       /*
+        * Must be non-overlapping.
+        */
+       return false;
+}
+
+struct rmid_read {
+       unsigned int rmid;
+       atomic64_t value;
+};
+
+static void __intel_cqm_event_count(void *info);
+
+/*
+ * Exchange the RMID of a group of events.
+ */
+static unsigned int
+intel_cqm_xchg_rmid(struct perf_event *group, unsigned int rmid)
+{
+       struct perf_event *event;
+       unsigned int old_rmid = group->hw.cqm_rmid;
+       struct list_head *head = &group->hw.cqm_group_entry;
+
+       lockdep_assert_held(&cache_mutex);
+
+       /*
+        * If our RMID is being deallocated, perform a read now.
+        */
+       if (__rmid_valid(old_rmid) && !__rmid_valid(rmid)) {
+               struct rmid_read rr = {
+                       .value = ATOMIC64_INIT(0),
+                       .rmid = old_rmid,
+               };
+
+               on_each_cpu_mask(&cqm_cpumask, __intel_cqm_event_count,
+                                &rr, 1);
+               local64_set(&group->count, atomic64_read(&rr.value));
+       }
+
+       raw_spin_lock_irq(&cache_lock);
+
+       group->hw.cqm_rmid = rmid;
+       list_for_each_entry(event, head, hw.cqm_group_entry)
+               event->hw.cqm_rmid = rmid;
+
+       raw_spin_unlock_irq(&cache_lock);
+
+       return old_rmid;
+}
+
+/*
+ * If we fail to assign a new RMID for intel_cqm_rotation_rmid because
+ * cachelines are still tagged with RMIDs in limbo, we progressively
+ * increment the threshold until we find an RMID in limbo with <=
+ * __intel_cqm_threshold lines tagged. This is designed to mitigate the
+ * problem where cachelines tagged with an RMID are not steadily being
+ * evicted.
+ *
+ * On successful rotations we decrease the threshold back towards zero.
+ *
+ * __intel_cqm_max_threshold provides an upper bound on the threshold,
+ * and is measured in bytes because it's exposed to userland.
+ */
+static unsigned int __intel_cqm_threshold;
+static unsigned int __intel_cqm_max_threshold;
+
+/*
+ * Test whether an RMID has a zero occupancy value on this cpu.
+ */
+static void intel_cqm_stable(void *arg)
+{
+       struct cqm_rmid_entry *entry;
+
+       list_for_each_entry(entry, &cqm_rmid_limbo_lru, list) {
+               if (entry->state != RMID_AVAILABLE)
+                       break;
+
+               if (__rmid_read(entry->rmid) > __intel_cqm_threshold)
+                       entry->state = RMID_DIRTY;
+       }
+}
+
+/*
+ * If we have group events waiting for an RMID that don't conflict with
+ * events already running, assign @rmid.
+ */
+static bool intel_cqm_sched_in_event(unsigned int rmid)
+{
+       struct perf_event *leader, *event;
+
+       lockdep_assert_held(&cache_mutex);
+
+       leader = list_first_entry(&cache_groups, struct perf_event,
+                                 hw.cqm_groups_entry);
+       event = leader;
+
+       list_for_each_entry_continue(event, &cache_groups,
+                                    hw.cqm_groups_entry) {
+               if (__rmid_valid(event->hw.cqm_rmid))
+                       continue;
+
+               if (__conflict_event(event, leader))
+                       continue;
+
+               intel_cqm_xchg_rmid(event, rmid);
+               return true;
+       }
+
+       return false;
+}
+
+/*
+ * Initially use this constant for both the limbo queue time and the
+ * rotation timer interval, pmu::hrtimer_interval_ms.
+ *
+ * They don't need to be the same, but the two are related since if you
+ * rotate faster than you recycle RMIDs, you may run out of available
+ * RMIDs.
+ */
+#define RMID_DEFAULT_QUEUE_TIME 250    /* ms */
+
+static unsigned int __rmid_queue_time_ms = RMID_DEFAULT_QUEUE_TIME;
+
+/*
+ * intel_cqm_rmid_stabilize - move RMIDs from limbo to free list
+ * @nr_available: number of freeable RMIDs on the limbo list
+ *
+ * Quiescent state; wait for all 'freed' RMIDs to become unused, i.e. no
+ * cachelines are tagged with those RMIDs. After this we can reuse them
+ * and know that the current set of active RMIDs is stable.
+ *
+ * Return %true or %false depending on whether stabilization needs to be
+ * reattempted.
+ *
+ * If we return %true then @nr_available is updated to indicate the
+ * number of RMIDs on the limbo list that have been queued for the
+ * minimum queue time (RMID_AVAILABLE), but whose data occupancy values
+ * are above __intel_cqm_threshold.
+ */
+static bool intel_cqm_rmid_stabilize(unsigned int *available)
+{
+       struct cqm_rmid_entry *entry, *tmp;
+
+       lockdep_assert_held(&cache_mutex);
+
+       *available = 0;
+       list_for_each_entry(entry, &cqm_rmid_limbo_lru, list) {
+               unsigned long min_queue_time;
+               unsigned long now = jiffies;
+
+               /*
+                * We hold RMIDs placed into limbo for a minimum queue
+                * time. Before the minimum queue time has elapsed we do
+                * not recycle RMIDs.
+                *
+                * The reasoning is that until a sufficient time has
+                * passed since we stopped using an RMID, any RMID
+                * placed onto the limbo list will likely still have
+                * data tagged in the cache, which means we'll probably
+                * fail to recycle it anyway.
+                *
+                * We can save ourselves an expensive IPI by skipping
+                * any RMIDs that have not been queued for the minimum
+                * time.
+                */
+               min_queue_time = entry->queue_time +
+                       msecs_to_jiffies(__rmid_queue_time_ms);
+
+               if (time_after(min_queue_time, now))
+                       break;
+
+               entry->state = RMID_AVAILABLE;
+               (*available)++;
+       }
+
+       /*
+        * Fast return if none of the RMIDs on the limbo list have been
+        * sitting on the queue for the minimum queue time.
+        */
+       if (!*available)
+               return false;
+
+       /*
+        * Test whether an RMID is free for each package.
+        */
+       on_each_cpu_mask(&cqm_cpumask, intel_cqm_stable, NULL, true);
+
+       list_for_each_entry_safe(entry, tmp, &cqm_rmid_limbo_lru, list) {
+               /*
+                * Exhausted all RMIDs that have waited min queue time.
+                */
+               if (entry->state == RMID_YOUNG)
+                       break;
+
+               if (entry->state == RMID_DIRTY)
+                       continue;
+
+               list_del(&entry->list); /* remove from limbo */
+
+               /*
+                * The rotation RMID gets priority if it's
+                * currently invalid. In which case, skip adding
+                * the RMID to the the free lru.
+                */
+               if (!__rmid_valid(intel_cqm_rotation_rmid)) {
+                       intel_cqm_rotation_rmid = entry->rmid;
+                       continue;
+               }
+
+               /*
+                * If we have groups waiting for RMIDs, hand
+                * them one now provided they don't conflict.
+                */
+               if (intel_cqm_sched_in_event(entry->rmid))
+                       continue;
+
+               /*
+                * Otherwise place it onto the free list.
+                */
+               list_add_tail(&entry->list, &cqm_rmid_free_lru);
+       }
+
+
+       return __rmid_valid(intel_cqm_rotation_rmid);
+}
+
+/*
+ * Pick a victim group and move it to the tail of the group list.
+ * @next: The first group without an RMID
+ */
+static void __intel_cqm_pick_and_rotate(struct perf_event *next)
+{
+       struct perf_event *rotor;
+       unsigned int rmid;
+
+       lockdep_assert_held(&cache_mutex);
+
+       rotor = list_first_entry(&cache_groups, struct perf_event,
+                                hw.cqm_groups_entry);
+
+       /*
+        * The group at the front of the list should always have a valid
+        * RMID. If it doesn't then no groups have RMIDs assigned and we
+        * don't need to rotate the list.
+        */
+       if (next == rotor)
+               return;
+
+       rmid = intel_cqm_xchg_rmid(rotor, INVALID_RMID);
+       __put_rmid(rmid);
+
+       list_rotate_left(&cache_groups);
+}
+
+/*
+ * Deallocate the RMIDs from any events that conflict with @event, and
+ * place them on the back of the group list.
+ */
+static void intel_cqm_sched_out_conflicting_events(struct perf_event *event)
+{
+       struct perf_event *group, *g;
+       unsigned int rmid;
+
+       lockdep_assert_held(&cache_mutex);
+
+       list_for_each_entry_safe(group, g, &cache_groups, hw.cqm_groups_entry) {
+               if (group == event)
+                       continue;
+
+               rmid = group->hw.cqm_rmid;
+
+               /*
+                * Skip events that don't have a valid RMID.
+                */
+               if (!__rmid_valid(rmid))
+                       continue;
+
+               /*
+                * No conflict? No problem! Leave the event alone.
+                */
+               if (!__conflict_event(group, event))
+                       continue;
+
+               intel_cqm_xchg_rmid(group, INVALID_RMID);
+               __put_rmid(rmid);
+       }
+}
+
+/*
+ * Attempt to rotate the groups and assign new RMIDs.
+ *
+ * We rotate for two reasons,
+ *   1. To handle the scheduling of conflicting events
+ *   2. To recycle RMIDs
+ *
+ * Rotating RMIDs is complicated because the hardware doesn't give us
+ * any clues.
+ *
+ * There's problems with the hardware interface; when you change the
+ * task:RMID map cachelines retain their 'old' tags, giving a skewed
+ * picture. In order to work around this, we must always keep one free
+ * RMID - intel_cqm_rotation_rmid.
+ *
+ * Rotation works by taking away an RMID from a group (the old RMID),
+ * and assigning the free RMID to another group (the new RMID). We must
+ * then wait for the old RMID to not be used (no cachelines tagged).
+ * This ensure that all cachelines are tagged with 'active' RMIDs. At
+ * this point we can start reading values for the new RMID and treat the
+ * old RMID as the free RMID for the next rotation.
+ *
+ * Return %true or %false depending on whether we did any rotating.
+ */
+static bool __intel_cqm_rmid_rotate(void)
+{
+       struct perf_event *group, *start = NULL;
+       unsigned int threshold_limit;
+       unsigned int nr_needed = 0;
+       unsigned int nr_available;
+       bool rotated = false;
+
+       mutex_lock(&cache_mutex);
+
+again:
+       /*
+        * Fast path through this function if there are no groups and no
+        * RMIDs that need cleaning.
+        */
+       if (list_empty(&cache_groups) && list_empty(&cqm_rmid_limbo_lru))
+               goto out;
+
+       list_for_each_entry(group, &cache_groups, hw.cqm_groups_entry) {
+               if (!__rmid_valid(group->hw.cqm_rmid)) {
+                       if (!start)
+                               start = group;
+                       nr_needed++;
+               }
+       }
+
+       /*
+        * We have some event groups, but they all have RMIDs assigned
+        * and no RMIDs need cleaning.
+        */
+       if (!nr_needed && list_empty(&cqm_rmid_limbo_lru))
+               goto out;
+
+       if (!nr_needed)
+               goto stabilize;
+
+       /*
+        * We have more event groups without RMIDs than available RMIDs,
+        * or we have event groups that conflict with the ones currently
+        * scheduled.
+        *
+        * We force deallocate the rmid of the group at the head of
+        * cache_groups. The first event group without an RMID then gets
+        * assigned intel_cqm_rotation_rmid. This ensures we always make
+        * forward progress.
+        *
+        * Rotate the cache_groups list so the previous head is now the
+        * tail.
+        */
+       __intel_cqm_pick_and_rotate(start);
+
+       /*
+        * If the rotation is going to succeed, reduce the threshold so
+        * that we don't needlessly reuse dirty RMIDs.
+        */
+       if (__rmid_valid(intel_cqm_rotation_rmid)) {
+               intel_cqm_xchg_rmid(start, intel_cqm_rotation_rmid);
+               intel_cqm_rotation_rmid = __get_rmid();
+
+               intel_cqm_sched_out_conflicting_events(start);
+
+               if (__intel_cqm_threshold)
+                       __intel_cqm_threshold--;
+       }
+
+       rotated = true;
+
+stabilize:
+       /*
+        * We now need to stablize the RMID we freed above (if any) to
+        * ensure that the next time we rotate we have an RMID with zero
+        * occupancy value.
+        *
+        * Alternatively, if we didn't need to perform any rotation,
+        * we'll have a bunch of RMIDs in limbo that need stabilizing.
+        */
+       threshold_limit = __intel_cqm_max_threshold / cqm_l3_scale;
+
+       while (intel_cqm_rmid_stabilize(&nr_available) &&
+              __intel_cqm_threshold < threshold_limit) {
+               unsigned int steal_limit;
+
+               /*
+                * Don't spin if nobody is actively waiting for an RMID,
+                * the rotation worker will be kicked as soon as an
+                * event needs an RMID anyway.
+                */
+               if (!nr_needed)
+                       break;
+
+               /* Allow max 25% of RMIDs to be in limbo. */
+               steal_limit = (cqm_max_rmid + 1) / 4;
+
+               /*
+                * We failed to stabilize any RMIDs so our rotation
+                * logic is now stuck. In order to make forward progress
+                * we have a few options:
+                *
+                *   1. rotate ("steal") another RMID
+                *   2. increase the threshold
+                *   3. do nothing
+                *
+                * We do both of 1. and 2. until we hit the steal limit.
+                *
+                * The steal limit prevents all RMIDs ending up on the
+                * limbo list. This can happen if every RMID has a
+                * non-zero occupancy above threshold_limit, and the
+                * occupancy values aren't dropping fast enough.
+                *
+                * Note that there is prioritisation at work here - we'd
+                * rather increase the number of RMIDs on the limbo list
+                * than increase the threshold, because increasing the
+                * threshold skews the event data (because we reuse
+                * dirty RMIDs) - threshold bumps are a last resort.
+                */
+               if (nr_available < steal_limit)
+                       goto again;
+
+               __intel_cqm_threshold++;
+       }
+
+out:
+       mutex_unlock(&cache_mutex);
+       return rotated;
+}
+
+static void intel_cqm_rmid_rotate(struct work_struct *work);
+
+static DECLARE_DELAYED_WORK(intel_cqm_rmid_work, intel_cqm_rmid_rotate);
+
+static struct pmu intel_cqm_pmu;
+
+static void intel_cqm_rmid_rotate(struct work_struct *work)
+{
+       unsigned long delay;
+
+       __intel_cqm_rmid_rotate();
+
+       delay = msecs_to_jiffies(intel_cqm_pmu.hrtimer_interval_ms);
+       schedule_delayed_work(&intel_cqm_rmid_work, delay);
+}
+
+/*
+ * Find a group and setup RMID.
+ *
+ * If we're part of a group, we use the group's RMID.
+ */
+static void intel_cqm_setup_event(struct perf_event *event,
+                                 struct perf_event **group)
+{
+       struct perf_event *iter;
+       unsigned int rmid;
+       bool conflict = false;
+
+       list_for_each_entry(iter, &cache_groups, hw.cqm_groups_entry) {
+               rmid = iter->hw.cqm_rmid;
+
+               if (__match_event(iter, event)) {
+                       /* All tasks in a group share an RMID */
+                       event->hw.cqm_rmid = rmid;
+                       *group = iter;
+                       return;
+               }
+
+               /*
+                * We only care about conflicts for events that are
+                * actually scheduled in (and hence have a valid RMID).
+                */
+               if (__conflict_event(iter, event) && __rmid_valid(rmid))
+                       conflict = true;
+       }
+
+       if (conflict)
+               rmid = INVALID_RMID;
+       else
+               rmid = __get_rmid();
+
+       event->hw.cqm_rmid = rmid;
+}
+
+static void intel_cqm_event_read(struct perf_event *event)
+{
+       unsigned long flags;
+       unsigned int rmid;
+       u64 val;
+
+       /*
+        * Task events are handled by intel_cqm_event_count().
+        */
+       if (event->cpu == -1)
+               return;
+
+       raw_spin_lock_irqsave(&cache_lock, flags);
+       rmid = event->hw.cqm_rmid;
+
+       if (!__rmid_valid(rmid))
+               goto out;
+
+       val = __rmid_read(rmid);
+
+       /*
+        * Ignore this reading on error states and do not update the value.
+        */
+       if (val & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL))
+               goto out;
+
+       local64_set(&event->count, val);
+out:
+       raw_spin_unlock_irqrestore(&cache_lock, flags);
+}
+
+static void __intel_cqm_event_count(void *info)
+{
+       struct rmid_read *rr = info;
+       u64 val;
+
+       val = __rmid_read(rr->rmid);
+
+       if (val & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL))
+               return;
+
+       atomic64_add(val, &rr->value);
+}
+
+static inline bool cqm_group_leader(struct perf_event *event)
+{
+       return !list_empty(&event->hw.cqm_groups_entry);
+}
+
+static u64 intel_cqm_event_count(struct perf_event *event)
+{
+       unsigned long flags;
+       struct rmid_read rr = {
+               .value = ATOMIC64_INIT(0),
+       };
+
+       /*
+        * We only need to worry about task events. System-wide events
+        * are handled like usual, i.e. entirely with
+        * intel_cqm_event_read().
+        */
+       if (event->cpu != -1)
+               return __perf_event_count(event);
+
+       /*
+        * Only the group leader gets to report values. This stops us
+        * reporting duplicate values to userspace, and gives us a clear
+        * rule for which task gets to report the values.
+        *
+        * Note that it is impossible to attribute these values to
+        * specific packages - we forfeit that ability when we create
+        * task events.
+        */
+       if (!cqm_group_leader(event))
+               return 0;
+
+       /*
+        * Notice that we don't perform the reading of an RMID
+        * atomically, because we can't hold a spin lock across the
+        * IPIs.
+        *
+        * Speculatively perform the read, since @event might be
+        * assigned a different (possibly invalid) RMID while we're
+        * busying performing the IPI calls. It's therefore necessary to
+        * check @event's RMID afterwards, and if it has changed,
+        * discard the result of the read.
+        */
+       rr.rmid = ACCESS_ONCE(event->hw.cqm_rmid);
+
+       if (!__rmid_valid(rr.rmid))
+               goto out;
+
+       on_each_cpu_mask(&cqm_cpumask, __intel_cqm_event_count, &rr, 1);
+
+       raw_spin_lock_irqsave(&cache_lock, flags);
+       if (event->hw.cqm_rmid == rr.rmid)
+               local64_set(&event->count, atomic64_read(&rr.value));
+       raw_spin_unlock_irqrestore(&cache_lock, flags);
+out:
+       return __perf_event_count(event);
+}
+
+static void intel_cqm_event_start(struct perf_event *event, int mode)
+{
+       struct intel_cqm_state *state = this_cpu_ptr(&cqm_state);
+       unsigned int rmid = event->hw.cqm_rmid;
+       unsigned long flags;
+
+       if (!(event->hw.cqm_state & PERF_HES_STOPPED))
+               return;
+
+       event->hw.cqm_state &= ~PERF_HES_STOPPED;
+
+       raw_spin_lock_irqsave(&state->lock, flags);
+
+       if (state->cnt++)
+               WARN_ON_ONCE(state->rmid != rmid);
+       else
+               WARN_ON_ONCE(state->rmid);
+
+       state->rmid = rmid;
+       wrmsrl(MSR_IA32_PQR_ASSOC, state->rmid);
+
+       raw_spin_unlock_irqrestore(&state->lock, flags);
+}
+
+static void intel_cqm_event_stop(struct perf_event *event, int mode)
+{
+       struct intel_cqm_state *state = this_cpu_ptr(&cqm_state);
+       unsigned long flags;
+
+       if (event->hw.cqm_state & PERF_HES_STOPPED)
+               return;
+
+       event->hw.cqm_state |= PERF_HES_STOPPED;
+
+       raw_spin_lock_irqsave(&state->lock, flags);
+       intel_cqm_event_read(event);
+
+       if (!--state->cnt) {
+               state->rmid = 0;
+               wrmsrl(MSR_IA32_PQR_ASSOC, 0);
+       } else {
+               WARN_ON_ONCE(!state->rmid);
+       }
+
+       raw_spin_unlock_irqrestore(&state->lock, flags);
+}
+
+static int intel_cqm_event_add(struct perf_event *event, int mode)
+{
+       unsigned long flags;
+       unsigned int rmid;
+
+       raw_spin_lock_irqsave(&cache_lock, flags);
+
+       event->hw.cqm_state = PERF_HES_STOPPED;
+       rmid = event->hw.cqm_rmid;
+
+       if (__rmid_valid(rmid) && (mode & PERF_EF_START))
+               intel_cqm_event_start(event, mode);
+
+       raw_spin_unlock_irqrestore(&cache_lock, flags);
+
+       return 0;
+}
+
+static void intel_cqm_event_del(struct perf_event *event, int mode)
+{
+       intel_cqm_event_stop(event, mode);
+}
+
+static void intel_cqm_event_destroy(struct perf_event *event)
+{
+       struct perf_event *group_other = NULL;
+
+       mutex_lock(&cache_mutex);
+
+       /*
+        * If there's another event in this group...
+        */
+       if (!list_empty(&event->hw.cqm_group_entry)) {
+               group_other = list_first_entry(&event->hw.cqm_group_entry,
+                                              struct perf_event,
+                                              hw.cqm_group_entry);
+               list_del(&event->hw.cqm_group_entry);
+       }
+
+       /*
+        * And we're the group leader..
+        */
+       if (cqm_group_leader(event)) {
+               /*
+                * If there was a group_other, make that leader, otherwise
+                * destroy the group and return the RMID.
+                */
+               if (group_other) {
+                       list_replace(&event->hw.cqm_groups_entry,
+                                    &group_other->hw.cqm_groups_entry);
+               } else {
+                       unsigned int rmid = event->hw.cqm_rmid;
+
+                       if (__rmid_valid(rmid))
+                               __put_rmid(rmid);
+                       list_del(&event->hw.cqm_groups_entry);
+               }
+       }
+
+       mutex_unlock(&cache_mutex);
+}
+
+static int intel_cqm_event_init(struct perf_event *event)
+{
+       struct perf_event *group = NULL;
+       bool rotate = false;
+
+       if (event->attr.type != intel_cqm_pmu.type)
+               return -ENOENT;
+
+       if (event->attr.config & ~QOS_EVENT_MASK)
+               return -EINVAL;
+
+       /* unsupported modes and filters */
+       if (event->attr.exclude_user   ||
+           event->attr.exclude_kernel ||
+           event->attr.exclude_hv     ||
+           event->attr.exclude_idle   ||
+           event->attr.exclude_host   ||
+           event->attr.exclude_guest  ||
+           event->attr.sample_period) /* no sampling */
+               return -EINVAL;
+
+       INIT_LIST_HEAD(&event->hw.cqm_group_entry);
+       INIT_LIST_HEAD(&event->hw.cqm_groups_entry);
+
+       event->destroy = intel_cqm_event_destroy;
+
+       mutex_lock(&cache_mutex);
+
+       /* Will also set rmid */
+       intel_cqm_setup_event(event, &group);
+
+       if (group) {
+               list_add_tail(&event->hw.cqm_group_entry,
+                             &group->hw.cqm_group_entry);
+       } else {
+               list_add_tail(&event->hw.cqm_groups_entry,
+                             &cache_groups);
+
+               /*
+                * All RMIDs are either in use or have recently been
+                * used. Kick the rotation worker to clean/free some.
+                *
+                * We only do this for the group leader, rather than for
+                * every event in a group to save on needless work.
+                */
+               if (!__rmid_valid(event->hw.cqm_rmid))
+                       rotate = true;
+       }
+
+       mutex_unlock(&cache_mutex);
+
+       if (rotate)
+               schedule_delayed_work(&intel_cqm_rmid_work, 0);
+
+       return 0;
+}
+
+EVENT_ATTR_STR(llc_occupancy, intel_cqm_llc, "event=0x01");
+EVENT_ATTR_STR(llc_occupancy.per-pkg, intel_cqm_llc_pkg, "1");
+EVENT_ATTR_STR(llc_occupancy.unit, intel_cqm_llc_unit, "Bytes");
+EVENT_ATTR_STR(llc_occupancy.scale, intel_cqm_llc_scale, NULL);
+EVENT_ATTR_STR(llc_occupancy.snapshot, intel_cqm_llc_snapshot, "1");
+
+static struct attribute *intel_cqm_events_attr[] = {
+       EVENT_PTR(intel_cqm_llc),
+       EVENT_PTR(intel_cqm_llc_pkg),
+       EVENT_PTR(intel_cqm_llc_unit),
+       EVENT_PTR(intel_cqm_llc_scale),
+       EVENT_PTR(intel_cqm_llc_snapshot),
+       NULL,
+};
+
+static struct attribute_group intel_cqm_events_group = {
+       .name = "events",
+       .attrs = intel_cqm_events_attr,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-7");
+static struct attribute *intel_cqm_formats_attr[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+
+static struct attribute_group intel_cqm_format_group = {
+       .name = "format",
+       .attrs = intel_cqm_formats_attr,
+};
+
+static ssize_t
+max_recycle_threshold_show(struct device *dev, struct device_attribute *attr,
+                          char *page)
+{
+       ssize_t rv;
+
+       mutex_lock(&cache_mutex);
+       rv = snprintf(page, PAGE_SIZE-1, "%u\n", __intel_cqm_max_threshold);
+       mutex_unlock(&cache_mutex);
+
+       return rv;
+}
+
+static ssize_t
+max_recycle_threshold_store(struct device *dev,
+                           struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       unsigned int bytes, cachelines;
+       int ret;
+
+       ret = kstrtouint(buf, 0, &bytes);
+       if (ret)
+               return ret;
+
+       mutex_lock(&cache_mutex);
+
+       __intel_cqm_max_threshold = bytes;
+       cachelines = bytes / cqm_l3_scale;
+
+       /*
+        * The new maximum takes effect immediately.
+        */
+       if (__intel_cqm_threshold > cachelines)
+               __intel_cqm_threshold = cachelines;
+
+       mutex_unlock(&cache_mutex);
+
+       return count;
+}
+
+static DEVICE_ATTR_RW(max_recycle_threshold);
+
+static struct attribute *intel_cqm_attrs[] = {
+       &dev_attr_max_recycle_threshold.attr,
+       NULL,
+};
+
+static const struct attribute_group intel_cqm_group = {
+       .attrs = intel_cqm_attrs,
+};
+
+static const struct attribute_group *intel_cqm_attr_groups[] = {
+       &intel_cqm_events_group,
+       &intel_cqm_format_group,
+       &intel_cqm_group,
+       NULL,
+};
+
+static struct pmu intel_cqm_pmu = {
+       .hrtimer_interval_ms = RMID_DEFAULT_QUEUE_TIME,
+       .attr_groups         = intel_cqm_attr_groups,
+       .task_ctx_nr         = perf_sw_context,
+       .event_init          = intel_cqm_event_init,
+       .add                 = intel_cqm_event_add,
+       .del                 = intel_cqm_event_del,
+       .start               = intel_cqm_event_start,
+       .stop                = intel_cqm_event_stop,
+       .read                = intel_cqm_event_read,
+       .count               = intel_cqm_event_count,
+};
+
+static inline void cqm_pick_event_reader(int cpu)
+{
+       int phys_id = topology_physical_package_id(cpu);
+       int i;
+
+       for_each_cpu(i, &cqm_cpumask) {
+               if (phys_id == topology_physical_package_id(i))
+                       return; /* already got reader for this socket */
+       }
+
+       cpumask_set_cpu(cpu, &cqm_cpumask);
+}
+
+static void intel_cqm_cpu_prepare(unsigned int cpu)
+{
+       struct intel_cqm_state *state = &per_cpu(cqm_state, cpu);
+       struct cpuinfo_x86 *c = &cpu_data(cpu);
+
+       raw_spin_lock_init(&state->lock);
+       state->rmid = 0;
+       state->cnt  = 0;
+
+       WARN_ON(c->x86_cache_max_rmid != cqm_max_rmid);
+       WARN_ON(c->x86_cache_occ_scale != cqm_l3_scale);
+}
+
+static void intel_cqm_cpu_exit(unsigned int cpu)
+{
+       int phys_id = topology_physical_package_id(cpu);
+       int i;
+
+       /*
+        * Is @cpu a designated cqm reader?
+        */
+       if (!cpumask_test_and_clear_cpu(cpu, &cqm_cpumask))
+               return;
+
+       for_each_online_cpu(i) {
+               if (i == cpu)
+                       continue;
+
+               if (phys_id == topology_physical_package_id(i)) {
+                       cpumask_set_cpu(i, &cqm_cpumask);
+                       break;
+               }
+       }
+}
+
+static int intel_cqm_cpu_notifier(struct notifier_block *nb,
+                                 unsigned long action, void *hcpu)
+{
+       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:
+               cqm_pick_event_reader(cpu);
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static const struct x86_cpu_id intel_cqm_match[] = {
+       { .vendor = X86_VENDOR_INTEL, .feature = X86_FEATURE_CQM_OCCUP_LLC },
+       {}
+};
+
+static int __init intel_cqm_init(void)
+{
+       char *str, scale[20];
+       int i, cpu, ret;
+
+       if (!x86_match_cpu(intel_cqm_match))
+               return -ENODEV;
+
+       cqm_l3_scale = boot_cpu_data.x86_cache_occ_scale;
+
+       /*
+        * It's possible that not all resources support the same number
+        * of RMIDs. Instead of making scheduling much more complicated
+        * (where we have to match a task's RMID to a cpu that supports
+        * that many RMIDs) just find the minimum RMIDs supported across
+        * all cpus.
+        *
+        * Also, check that the scales match on all cpus.
+        */
+       cpu_notifier_register_begin();
+
+       for_each_online_cpu(cpu) {
+               struct cpuinfo_x86 *c = &cpu_data(cpu);
+
+               if (c->x86_cache_max_rmid < cqm_max_rmid)
+                       cqm_max_rmid = c->x86_cache_max_rmid;
+
+               if (c->x86_cache_occ_scale != cqm_l3_scale) {
+                       pr_err("Multiple LLC scale values, disabling\n");
+                       ret = -EINVAL;
+                       goto out;
+               }
+       }
+
+       /*
+        * A reasonable upper limit on the max threshold is the number
+        * of lines tagged per RMID if all RMIDs have the same number of
+        * lines tagged in the LLC.
+        *
+        * For a 35MB LLC and 56 RMIDs, this is ~1.8% of the LLC.
+        */
+       __intel_cqm_max_threshold =
+               boot_cpu_data.x86_cache_size * 1024 / (cqm_max_rmid + 1);
+
+       snprintf(scale, sizeof(scale), "%u", cqm_l3_scale);
+       str = kstrdup(scale, GFP_KERNEL);
+       if (!str) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       event_attr_intel_cqm_llc_scale.event_str = str;
+
+       ret = intel_cqm_setup_rmid_cache();
+       if (ret)
+               goto out;
+
+       for_each_online_cpu(i) {
+               intel_cqm_cpu_prepare(i);
+               cqm_pick_event_reader(i);
+       }
+
+       __perf_cpu_notifier(intel_cqm_cpu_notifier);
+
+       ret = perf_pmu_register(&intel_cqm_pmu, "intel_cqm", -1);
+       if (ret)
+               pr_err("Intel CQM perf registration failed: %d\n", ret);
+       else
+               pr_info("Intel CQM monitoring enabled\n");
+
+out:
+       cpu_notifier_register_done();
+
+       return ret;
+}
+device_initcall(intel_cqm_init);
index 07398339836426eae32b55fb08fa108593cd7389..ca69ea56c712b590876ff9c5289a839dc91158b7 100644 (file)
@@ -461,7 +461,8 @@ void intel_pmu_enable_bts(u64 config)
 
        debugctlmsr |= DEBUGCTLMSR_TR;
        debugctlmsr |= DEBUGCTLMSR_BTS;
-       debugctlmsr |= DEBUGCTLMSR_BTINT;
+       if (config & ARCH_PERFMON_EVENTSEL_INT)
+               debugctlmsr |= DEBUGCTLMSR_BTINT;
 
        if (!(config & ARCH_PERFMON_EVENTSEL_OS))
                debugctlmsr |= DEBUGCTLMSR_BTS_OFF_OS;
@@ -611,6 +612,10 @@ struct event_constraint intel_snb_pebs_event_constraints[] = {
        INTEL_PST_CONSTRAINT(0x02cd, 0x8),    /* MEM_TRANS_RETIRED.PRECISE_STORES */
        /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
        INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
+        INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf),    /* MEM_UOP_RETIRED.* */
+        INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
+        INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf),    /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+        INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf),    /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
        /* Allow all events as PEBS with no flags */
        INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
        EVENT_CONSTRAINT_END
@@ -622,6 +627,10 @@ struct event_constraint intel_ivb_pebs_event_constraints[] = {
        INTEL_PST_CONSTRAINT(0x02cd, 0x8),    /* MEM_TRANS_RETIRED.PRECISE_STORES */
        /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
        INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
+       INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf),    /* MEM_UOP_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf),    /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf),    /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
        /* Allow all events as PEBS with no flags */
        INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
         EVENT_CONSTRAINT_END
@@ -633,16 +642,16 @@ struct event_constraint intel_hsw_pebs_event_constraints[] = {
        /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
        INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
        INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x41d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_LOADS */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x81d0, 0xf), /* MEM_UOPS_RETIRED.ALL_LOADS */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_STORES */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x42d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_STORES */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x82d0, 0xf), /* MEM_UOPS_RETIRED.ALL_STORES */
-       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd2, 0xf),    /* MEM_LOAD_UOPS_L3_HIT_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd3, 0xf),    /* MEM_LOAD_UOPS_L3_MISS_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x11d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x41d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x81d0, 0xf), /* MEM_UOPS_RETIRED.ALL_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(0x12d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_STORES */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(0x42d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_STORES */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(0x82d0, 0xf), /* MEM_UOPS_RETIRED.ALL_STORES */
+       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(0xd2, 0xf),    /* MEM_LOAD_UOPS_L3_HIT_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(0xd3, 0xf),    /* MEM_LOAD_UOPS_L3_MISS_RETIRED.* */
        /* Allow all events as PEBS with no flags */
        INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
        EVENT_CONSTRAINT_END
index 58f1a94beaf09f6fdab1dd1b12727ad045a58913..94e5b506caa6d13206956095e646bfacbf558fb1 100644 (file)
@@ -39,6 +39,7 @@ static enum {
 #define LBR_IND_JMP_BIT                6 /* do not capture indirect jumps */
 #define LBR_REL_JMP_BIT                7 /* do not capture relative jumps */
 #define LBR_FAR_BIT            8 /* do not capture far branches */
+#define LBR_CALL_STACK_BIT     9 /* enable call stack */
 
 #define LBR_KERNEL     (1 << LBR_KERNEL_BIT)
 #define LBR_USER       (1 << LBR_USER_BIT)
@@ -49,6 +50,7 @@ static enum {
 #define LBR_REL_JMP    (1 << LBR_REL_JMP_BIT)
 #define LBR_IND_JMP    (1 << LBR_IND_JMP_BIT)
 #define LBR_FAR                (1 << LBR_FAR_BIT)
+#define LBR_CALL_STACK (1 << LBR_CALL_STACK_BIT)
 
 #define LBR_PLM (LBR_KERNEL | LBR_USER)
 
@@ -69,33 +71,31 @@ static enum {
 #define LBR_FROM_FLAG_IN_TX    (1ULL << 62)
 #define LBR_FROM_FLAG_ABORT    (1ULL << 61)
 
-#define for_each_branch_sample_type(x) \
-       for ((x) = PERF_SAMPLE_BRANCH_USER; \
-            (x) < PERF_SAMPLE_BRANCH_MAX; (x) <<= 1)
-
 /*
  * x86control flow change classification
  * x86control flow changes include branches, interrupts, traps, faults
  */
 enum {
-       X86_BR_NONE     = 0,      /* unknown */
-
-       X86_BR_USER     = 1 << 0, /* branch target is user */
-       X86_BR_KERNEL   = 1 << 1, /* branch target is kernel */
-
-       X86_BR_CALL     = 1 << 2, /* call */
-       X86_BR_RET      = 1 << 3, /* return */
-       X86_BR_SYSCALL  = 1 << 4, /* syscall */
-       X86_BR_SYSRET   = 1 << 5, /* syscall return */
-       X86_BR_INT      = 1 << 6, /* sw interrupt */
-       X86_BR_IRET     = 1 << 7, /* return from interrupt */
-       X86_BR_JCC      = 1 << 8, /* conditional */
-       X86_BR_JMP      = 1 << 9, /* jump */
-       X86_BR_IRQ      = 1 << 10,/* hw interrupt or trap or fault */
-       X86_BR_IND_CALL = 1 << 11,/* indirect calls */
-       X86_BR_ABORT    = 1 << 12,/* transaction abort */
-       X86_BR_IN_TX    = 1 << 13,/* in transaction */
-       X86_BR_NO_TX    = 1 << 14,/* not in transaction */
+       X86_BR_NONE             = 0,      /* unknown */
+
+       X86_BR_USER             = 1 << 0, /* branch target is user */
+       X86_BR_KERNEL           = 1 << 1, /* branch target is kernel */
+
+       X86_BR_CALL             = 1 << 2, /* call */
+       X86_BR_RET              = 1 << 3, /* return */
+       X86_BR_SYSCALL          = 1 << 4, /* syscall */
+       X86_BR_SYSRET           = 1 << 5, /* syscall return */
+       X86_BR_INT              = 1 << 6, /* sw interrupt */
+       X86_BR_IRET             = 1 << 7, /* return from interrupt */
+       X86_BR_JCC              = 1 << 8, /* conditional */
+       X86_BR_JMP              = 1 << 9, /* jump */
+       X86_BR_IRQ              = 1 << 10,/* hw interrupt or trap or fault */
+       X86_BR_IND_CALL         = 1 << 11,/* indirect calls */
+       X86_BR_ABORT            = 1 << 12,/* transaction abort */
+       X86_BR_IN_TX            = 1 << 13,/* in transaction */
+       X86_BR_NO_TX            = 1 << 14,/* not in transaction */
+       X86_BR_ZERO_CALL        = 1 << 15,/* zero length call */
+       X86_BR_CALL_STACK       = 1 << 16,/* call stack */
 };
 
 #define X86_BR_PLM (X86_BR_USER | X86_BR_KERNEL)
@@ -112,13 +112,15 @@ enum {
         X86_BR_JMP      |\
         X86_BR_IRQ      |\
         X86_BR_ABORT    |\
-        X86_BR_IND_CALL)
+        X86_BR_IND_CALL |\
+        X86_BR_ZERO_CALL)
 
 #define X86_BR_ALL (X86_BR_PLM | X86_BR_ANY)
 
 #define X86_BR_ANY_CALL                 \
        (X86_BR_CALL            |\
         X86_BR_IND_CALL        |\
+        X86_BR_ZERO_CALL       |\
         X86_BR_SYSCALL         |\
         X86_BR_IRQ             |\
         X86_BR_INT)
@@ -130,17 +132,32 @@ static void intel_pmu_lbr_filter(struct cpu_hw_events *cpuc);
  * otherwise it becomes near impossible to get a reliable stack.
  */
 
-static void __intel_pmu_lbr_enable(void)
+static void __intel_pmu_lbr_enable(bool pmi)
 {
-       u64 debugctl;
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       u64 debugctl, lbr_select = 0, orig_debugctl;
 
-       if (cpuc->lbr_sel)
-               wrmsrl(MSR_LBR_SELECT, cpuc->lbr_sel->config);
+       /*
+        * No need to reprogram LBR_SELECT in a PMI, as it
+        * did not change.
+        */
+       if (cpuc->lbr_sel && !pmi) {
+               lbr_select = cpuc->lbr_sel->config;
+               wrmsrl(MSR_LBR_SELECT, lbr_select);
+       }
 
        rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
-       debugctl |= (DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI);
-       wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
+       orig_debugctl = debugctl;
+       debugctl |= DEBUGCTLMSR_LBR;
+       /*
+        * LBR callstack does not work well with FREEZE_LBRS_ON_PMI.
+        * If FREEZE_LBRS_ON_PMI is set, PMI near call/return instructions
+        * may cause superfluous increase/decrease of LBR_TOS.
+        */
+       if (!(lbr_select & LBR_CALL_STACK))
+               debugctl |= DEBUGCTLMSR_FREEZE_LBRS_ON_PMI;
+       if (orig_debugctl != debugctl)
+               wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
 }
 
 static void __intel_pmu_lbr_disable(void)
@@ -181,9 +198,116 @@ void intel_pmu_lbr_reset(void)
                intel_pmu_lbr_reset_64();
 }
 
+/*
+ * TOS = most recently recorded branch
+ */
+static inline u64 intel_pmu_lbr_tos(void)
+{
+       u64 tos;
+
+       rdmsrl(x86_pmu.lbr_tos, tos);
+       return tos;
+}
+
+enum {
+       LBR_NONE,
+       LBR_VALID,
+};
+
+static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx)
+{
+       int i;
+       unsigned lbr_idx, mask;
+       u64 tos;
+
+       if (task_ctx->lbr_callstack_users == 0 ||
+           task_ctx->lbr_stack_state == LBR_NONE) {
+               intel_pmu_lbr_reset();
+               return;
+       }
+
+       mask = x86_pmu.lbr_nr - 1;
+       tos = intel_pmu_lbr_tos();
+       for (i = 0; i < x86_pmu.lbr_nr; i++) {
+               lbr_idx = (tos - i) & mask;
+               wrmsrl(x86_pmu.lbr_from + lbr_idx, task_ctx->lbr_from[i]);
+               wrmsrl(x86_pmu.lbr_to + lbr_idx, task_ctx->lbr_to[i]);
+       }
+       task_ctx->lbr_stack_state = LBR_NONE;
+}
+
+static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx)
+{
+       int i;
+       unsigned lbr_idx, mask;
+       u64 tos;
+
+       if (task_ctx->lbr_callstack_users == 0) {
+               task_ctx->lbr_stack_state = LBR_NONE;
+               return;
+       }
+
+       mask = x86_pmu.lbr_nr - 1;
+       tos = intel_pmu_lbr_tos();
+       for (i = 0; i < x86_pmu.lbr_nr; i++) {
+               lbr_idx = (tos - i) & mask;
+               rdmsrl(x86_pmu.lbr_from + lbr_idx, task_ctx->lbr_from[i]);
+               rdmsrl(x86_pmu.lbr_to + lbr_idx, task_ctx->lbr_to[i]);
+       }
+       task_ctx->lbr_stack_state = LBR_VALID;
+}
+
+void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct x86_perf_task_context *task_ctx;
+
+       if (!x86_pmu.lbr_nr)
+               return;
+
+       /*
+        * If LBR callstack feature is enabled and the stack was saved when
+        * the task was scheduled out, restore the stack. Otherwise flush
+        * the LBR stack.
+        */
+       task_ctx = ctx ? ctx->task_ctx_data : NULL;
+       if (task_ctx) {
+               if (sched_in) {
+                       __intel_pmu_lbr_restore(task_ctx);
+                       cpuc->lbr_context = ctx;
+               } else {
+                       __intel_pmu_lbr_save(task_ctx);
+               }
+               return;
+       }
+
+       /*
+        * When sampling the branck stack in system-wide, it may be
+        * necessary to flush the stack on context switch. This happens
+        * when the branch stack does not tag its entries with the pid
+        * of the current task. Otherwise it becomes impossible to
+        * associate a branch entry with a task. This ambiguity is more
+        * likely to appear when the branch stack supports priv level
+        * filtering and the user sets it to monitor only at the user
+        * level (which could be a useful measurement in system-wide
+        * mode). In that case, the risk is high of having a branch
+        * stack with branch from multiple tasks.
+        */
+       if (sched_in) {
+               intel_pmu_lbr_reset();
+               cpuc->lbr_context = ctx;
+       }
+}
+
+static inline bool branch_user_callstack(unsigned br_sel)
+{
+       return (br_sel & X86_BR_USER) && (br_sel & X86_BR_CALL_STACK);
+}
+
 void intel_pmu_lbr_enable(struct perf_event *event)
 {
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct x86_perf_task_context *task_ctx;
 
        if (!x86_pmu.lbr_nr)
                return;
@@ -198,18 +322,33 @@ void intel_pmu_lbr_enable(struct perf_event *event)
        }
        cpuc->br_sel = event->hw.branch_reg.reg;
 
+       if (branch_user_callstack(cpuc->br_sel) && event->ctx &&
+                                       event->ctx->task_ctx_data) {
+               task_ctx = event->ctx->task_ctx_data;
+               task_ctx->lbr_callstack_users++;
+       }
+
        cpuc->lbr_users++;
+       perf_sched_cb_inc(event->ctx->pmu);
 }
 
 void intel_pmu_lbr_disable(struct perf_event *event)
 {
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct x86_perf_task_context *task_ctx;
 
        if (!x86_pmu.lbr_nr)
                return;
 
+       if (branch_user_callstack(cpuc->br_sel) && event->ctx &&
+                                       event->ctx->task_ctx_data) {
+               task_ctx = event->ctx->task_ctx_data;
+               task_ctx->lbr_callstack_users--;
+       }
+
        cpuc->lbr_users--;
        WARN_ON_ONCE(cpuc->lbr_users < 0);
+       perf_sched_cb_dec(event->ctx->pmu);
 
        if (cpuc->enabled && !cpuc->lbr_users) {
                __intel_pmu_lbr_disable();
@@ -218,12 +357,12 @@ void intel_pmu_lbr_disable(struct perf_event *event)
        }
 }
 
-void intel_pmu_lbr_enable_all(void)
+void intel_pmu_lbr_enable_all(bool pmi)
 {
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
 
        if (cpuc->lbr_users)
-               __intel_pmu_lbr_enable();
+               __intel_pmu_lbr_enable(pmi);
 }
 
 void intel_pmu_lbr_disable_all(void)
@@ -234,18 +373,6 @@ void intel_pmu_lbr_disable_all(void)
                __intel_pmu_lbr_disable();
 }
 
-/*
- * TOS = most recently recorded branch
- */
-static inline u64 intel_pmu_lbr_tos(void)
-{
-       u64 tos;
-
-       rdmsrl(x86_pmu.lbr_tos, tos);
-
-       return tos;
-}
-
 static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc)
 {
        unsigned long mask = x86_pmu.lbr_nr - 1;
@@ -350,7 +477,7 @@ void intel_pmu_lbr_read(void)
  * - in case there is no HW filter
  * - in case the HW filter has errata or limitations
  */
-static void intel_pmu_setup_sw_lbr_filter(struct perf_event *event)
+static int intel_pmu_setup_sw_lbr_filter(struct perf_event *event)
 {
        u64 br_type = event->attr.branch_sample_type;
        int mask = 0;
@@ -387,11 +514,21 @@ static void intel_pmu_setup_sw_lbr_filter(struct perf_event *event)
        if (br_type & PERF_SAMPLE_BRANCH_COND)
                mask |= X86_BR_JCC;
 
+       if (br_type & PERF_SAMPLE_BRANCH_CALL_STACK) {
+               if (!x86_pmu_has_lbr_callstack())
+                       return -EOPNOTSUPP;
+               if (mask & ~(X86_BR_USER | X86_BR_KERNEL))
+                       return -EINVAL;
+               mask |= X86_BR_CALL | X86_BR_IND_CALL | X86_BR_RET |
+                       X86_BR_CALL_STACK;
+       }
+
        /*
         * stash actual user request into reg, it may
         * be used by fixup code for some CPU
         */
        event->hw.branch_reg.reg = mask;
+       return 0;
 }
 
 /*
@@ -403,14 +540,14 @@ static int intel_pmu_setup_hw_lbr_filter(struct perf_event *event)
 {
        struct hw_perf_event_extra *reg;
        u64 br_type = event->attr.branch_sample_type;
-       u64 mask = 0, m;
-       u64 v;
+       u64 mask = 0, v;
+       int i;
 
-       for_each_branch_sample_type(m) {
-               if (!(br_type & m))
+       for (i = 0; i < PERF_SAMPLE_BRANCH_MAX_SHIFT; i++) {
+               if (!(br_type & (1ULL << i)))
                        continue;
 
-               v = x86_pmu.lbr_sel_map[m];
+               v = x86_pmu.lbr_sel_map[i];
                if (v == LBR_NOT_SUPP)
                        return -EOPNOTSUPP;
 
@@ -420,8 +557,12 @@ static int intel_pmu_setup_hw_lbr_filter(struct perf_event *event)
        reg = &event->hw.branch_reg;
        reg->idx = EXTRA_REG_LBR;
 
-       /* LBR_SELECT operates in suppress mode so invert mask */
-       reg->config = ~mask & x86_pmu.lbr_sel_mask;
+       /*
+        * The first 9 bits (LBR_SEL_MASK) in LBR_SELECT operate
+        * in suppress mode. So LBR_SELECT should be set to
+        * (~mask & LBR_SEL_MASK) | (mask & ~LBR_SEL_MASK)
+        */
+       reg->config = mask ^ x86_pmu.lbr_sel_mask;
 
        return 0;
 }
@@ -439,7 +580,9 @@ int intel_pmu_setup_lbr_filter(struct perf_event *event)
        /*
         * setup SW LBR filter
         */
-       intel_pmu_setup_sw_lbr_filter(event);
+       ret = intel_pmu_setup_sw_lbr_filter(event);
+       if (ret)
+               return ret;
 
        /*
         * setup HW LBR filter, if any
@@ -568,6 +711,12 @@ static int branch_type(unsigned long from, unsigned long to, int abort)
                ret = X86_BR_INT;
                break;
        case 0xe8: /* call near rel */
+               insn_get_immediate(&insn);
+               if (insn.immediate1.value == 0) {
+                       /* zero length call */
+                       ret = X86_BR_ZERO_CALL;
+                       break;
+               }
        case 0x9a: /* call far absolute */
                ret = X86_BR_CALL;
                break;
@@ -678,35 +827,49 @@ intel_pmu_lbr_filter(struct cpu_hw_events *cpuc)
 /*
  * Map interface branch filters onto LBR filters
  */
-static const int nhm_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX] = {
-       [PERF_SAMPLE_BRANCH_ANY]        = LBR_ANY,
-       [PERF_SAMPLE_BRANCH_USER]       = LBR_USER,
-       [PERF_SAMPLE_BRANCH_KERNEL]     = LBR_KERNEL,
-       [PERF_SAMPLE_BRANCH_HV]         = LBR_IGN,
-       [PERF_SAMPLE_BRANCH_ANY_RETURN] = LBR_RETURN | LBR_REL_JMP
-                                       | LBR_IND_JMP | LBR_FAR,
+static const int nhm_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
+       [PERF_SAMPLE_BRANCH_ANY_SHIFT]          = LBR_ANY,
+       [PERF_SAMPLE_BRANCH_USER_SHIFT]         = LBR_USER,
+       [PERF_SAMPLE_BRANCH_KERNEL_SHIFT]       = LBR_KERNEL,
+       [PERF_SAMPLE_BRANCH_HV_SHIFT]           = LBR_IGN,
+       [PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]   = LBR_RETURN | LBR_REL_JMP
+                                               | LBR_IND_JMP | LBR_FAR,
        /*
         * NHM/WSM erratum: must include REL_JMP+IND_JMP to get CALL branches
         */
-       [PERF_SAMPLE_BRANCH_ANY_CALL] =
+       [PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT] =
         LBR_REL_CALL | LBR_IND_CALL | LBR_REL_JMP | LBR_IND_JMP | LBR_FAR,
        /*
         * NHM/WSM erratum: must include IND_JMP to capture IND_CALL
         */
-       [PERF_SAMPLE_BRANCH_IND_CALL] = LBR_IND_CALL | LBR_IND_JMP,
-       [PERF_SAMPLE_BRANCH_COND]     = LBR_JCC,
+       [PERF_SAMPLE_BRANCH_IND_CALL_SHIFT] = LBR_IND_CALL | LBR_IND_JMP,
+       [PERF_SAMPLE_BRANCH_COND_SHIFT]     = LBR_JCC,
 };
 
-static const int snb_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX] = {
-       [PERF_SAMPLE_BRANCH_ANY]        = LBR_ANY,
-       [PERF_SAMPLE_BRANCH_USER]       = LBR_USER,
-       [PERF_SAMPLE_BRANCH_KERNEL]     = LBR_KERNEL,
-       [PERF_SAMPLE_BRANCH_HV]         = LBR_IGN,
-       [PERF_SAMPLE_BRANCH_ANY_RETURN] = LBR_RETURN | LBR_FAR,
-       [PERF_SAMPLE_BRANCH_ANY_CALL]   = LBR_REL_CALL | LBR_IND_CALL
-                                       | LBR_FAR,
-       [PERF_SAMPLE_BRANCH_IND_CALL]   = LBR_IND_CALL,
-       [PERF_SAMPLE_BRANCH_COND]       = LBR_JCC,
+static const int snb_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
+       [PERF_SAMPLE_BRANCH_ANY_SHIFT]          = LBR_ANY,
+       [PERF_SAMPLE_BRANCH_USER_SHIFT]         = LBR_USER,
+       [PERF_SAMPLE_BRANCH_KERNEL_SHIFT]       = LBR_KERNEL,
+       [PERF_SAMPLE_BRANCH_HV_SHIFT]           = LBR_IGN,
+       [PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]   = LBR_RETURN | LBR_FAR,
+       [PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT]     = LBR_REL_CALL | LBR_IND_CALL
+                                               | LBR_FAR,
+       [PERF_SAMPLE_BRANCH_IND_CALL_SHIFT]     = LBR_IND_CALL,
+       [PERF_SAMPLE_BRANCH_COND_SHIFT]         = LBR_JCC,
+};
+
+static const int hsw_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
+       [PERF_SAMPLE_BRANCH_ANY_SHIFT]          = LBR_ANY,
+       [PERF_SAMPLE_BRANCH_USER_SHIFT]         = LBR_USER,
+       [PERF_SAMPLE_BRANCH_KERNEL_SHIFT]       = LBR_KERNEL,
+       [PERF_SAMPLE_BRANCH_HV_SHIFT]           = LBR_IGN,
+       [PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]   = LBR_RETURN | LBR_FAR,
+       [PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT]     = LBR_REL_CALL | LBR_IND_CALL
+                                               | LBR_FAR,
+       [PERF_SAMPLE_BRANCH_IND_CALL_SHIFT]     = LBR_IND_CALL,
+       [PERF_SAMPLE_BRANCH_COND_SHIFT]         = LBR_JCC,
+       [PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT]   = LBR_REL_CALL | LBR_IND_CALL
+                                               | LBR_RETURN | LBR_CALL_STACK,
 };
 
 /* core */
@@ -765,6 +928,20 @@ void __init intel_pmu_lbr_init_snb(void)
        pr_cont("16-deep LBR, ");
 }
 
+/* haswell */
+void intel_pmu_lbr_init_hsw(void)
+{
+       x86_pmu.lbr_nr   = 16;
+       x86_pmu.lbr_tos  = MSR_LBR_TOS;
+       x86_pmu.lbr_from = MSR_LBR_NHM_FROM;
+       x86_pmu.lbr_to   = MSR_LBR_NHM_TO;
+
+       x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
+       x86_pmu.lbr_sel_map  = hsw_lbr_sel_map;
+
+       pr_cont("16-deep LBR, ");
+}
+
 /* atom */
 void __init intel_pmu_lbr_init_atom(void)
 {
diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c b/arch/x86/kernel/cpu/perf_event_intel_pt.c
new file mode 100644 (file)
index 0000000..f277064
--- /dev/null
@@ -0,0 +1,1103 @@
+/*
+ * Intel(R) Processor Trace PMU driver for perf
+ * Copyright (c) 2013-2014, 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.
+ *
+ * Intel PT is specified in the Intel Architecture Instruction Set Extensions
+ * Programming Reference:
+ * http://software.intel.com/en-us/intel-isa-extensions
+ */
+
+#undef DEBUG
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+
+#include <asm/perf_event.h>
+#include <asm/insn.h>
+#include <asm/io.h>
+
+#include "perf_event.h"
+#include "intel_pt.h"
+
+static DEFINE_PER_CPU(struct pt, pt_ctx);
+
+static struct pt_pmu pt_pmu;
+
+enum cpuid_regs {
+       CR_EAX = 0,
+       CR_ECX,
+       CR_EDX,
+       CR_EBX
+};
+
+/*
+ * Capabilities of Intel PT hardware, such as number of address bits or
+ * supported output schemes, are cached and exported to userspace as "caps"
+ * attribute group of pt pmu device
+ * (/sys/bus/event_source/devices/intel_pt/caps/) so that userspace can store
+ * relevant bits together with intel_pt traces.
+ *
+ * These are necessary for both trace decoding (payloads_lip, contains address
+ * width encoded in IP-related packets), and event configuration (bitmasks with
+ * permitted values for certain bit fields).
+ */
+#define PT_CAP(_n, _l, _r, _m)                                         \
+       [PT_CAP_ ## _n] = { .name = __stringify(_n), .leaf = _l,        \
+                           .reg = _r, .mask = _m }
+
+static struct pt_cap_desc {
+       const char      *name;
+       u32             leaf;
+       u8              reg;
+       u32             mask;
+} pt_caps[] = {
+       PT_CAP(max_subleaf,             0, CR_EAX, 0xffffffff),
+       PT_CAP(cr3_filtering,           0, CR_EBX, BIT(0)),
+       PT_CAP(topa_output,             0, CR_ECX, BIT(0)),
+       PT_CAP(topa_multiple_entries,   0, CR_ECX, BIT(1)),
+       PT_CAP(payloads_lip,            0, CR_ECX, BIT(31)),
+};
+
+static u32 pt_cap_get(enum pt_capabilities cap)
+{
+       struct pt_cap_desc *cd = &pt_caps[cap];
+       u32 c = pt_pmu.caps[cd->leaf * 4 + cd->reg];
+       unsigned int shift = __ffs(cd->mask);
+
+       return (c & cd->mask) >> shift;
+}
+
+static ssize_t pt_cap_show(struct device *cdev,
+                          struct device_attribute *attr,
+                          char *buf)
+{
+       struct dev_ext_attribute *ea =
+               container_of(attr, struct dev_ext_attribute, attr);
+       enum pt_capabilities cap = (long)ea->var;
+
+       return snprintf(buf, PAGE_SIZE, "%x\n", pt_cap_get(cap));
+}
+
+static struct attribute_group pt_cap_group = {
+       .name   = "caps",
+};
+
+PMU_FORMAT_ATTR(tsc,           "config:10"     );
+PMU_FORMAT_ATTR(noretcomp,     "config:11"     );
+
+static struct attribute *pt_formats_attr[] = {
+       &format_attr_tsc.attr,
+       &format_attr_noretcomp.attr,
+       NULL,
+};
+
+static struct attribute_group pt_format_group = {
+       .name   = "format",
+       .attrs  = pt_formats_attr,
+};
+
+static const struct attribute_group *pt_attr_groups[] = {
+       &pt_cap_group,
+       &pt_format_group,
+       NULL,
+};
+
+static int __init pt_pmu_hw_init(void)
+{
+       struct dev_ext_attribute *de_attrs;
+       struct attribute **attrs;
+       size_t size;
+       int ret;
+       long i;
+
+       attrs = NULL;
+       ret = -ENODEV;
+       if (!test_cpu_cap(&boot_cpu_data, X86_FEATURE_INTEL_PT))
+               goto fail;
+
+       for (i = 0; i < PT_CPUID_LEAVES; i++) {
+               cpuid_count(20, i,
+                           &pt_pmu.caps[CR_EAX + i*4],
+                           &pt_pmu.caps[CR_EBX + i*4],
+                           &pt_pmu.caps[CR_ECX + i*4],
+                           &pt_pmu.caps[CR_EDX + i*4]);
+       }
+
+       ret = -ENOMEM;
+       size = sizeof(struct attribute *) * (ARRAY_SIZE(pt_caps)+1);
+       attrs = kzalloc(size, GFP_KERNEL);
+       if (!attrs)
+               goto fail;
+
+       size = sizeof(struct dev_ext_attribute) * (ARRAY_SIZE(pt_caps)+1);
+       de_attrs = kzalloc(size, GFP_KERNEL);
+       if (!de_attrs)
+               goto fail;
+
+       for (i = 0; i < ARRAY_SIZE(pt_caps); i++) {
+               struct dev_ext_attribute *de_attr = de_attrs + i;
+
+               de_attr->attr.attr.name = pt_caps[i].name;
+
+               sysfs_attr_init(&de_attrs->attr.attr);
+
+               de_attr->attr.attr.mode         = S_IRUGO;
+               de_attr->attr.show              = pt_cap_show;
+               de_attr->var                    = (void *)i;
+
+               attrs[i] = &de_attr->attr.attr;
+       }
+
+       pt_cap_group.attrs = attrs;
+
+       return 0;
+
+fail:
+       kfree(attrs);
+
+       return ret;
+}
+
+#define PT_CONFIG_MASK (RTIT_CTL_TSC_EN | RTIT_CTL_DISRETC)
+
+static bool pt_event_valid(struct perf_event *event)
+{
+       u64 config = event->attr.config;
+
+       if ((config & PT_CONFIG_MASK) != config)
+               return false;
+
+       return true;
+}
+
+/*
+ * PT configuration helpers
+ * These all are cpu affine and operate on a local PT
+ */
+
+static bool pt_is_running(void)
+{
+       u64 ctl;
+
+       rdmsrl(MSR_IA32_RTIT_CTL, ctl);
+
+       return !!(ctl & RTIT_CTL_TRACEEN);
+}
+
+static void pt_config(struct perf_event *event)
+{
+       u64 reg;
+
+       reg = RTIT_CTL_TOPA | RTIT_CTL_BRANCH_EN | RTIT_CTL_TRACEEN;
+
+       if (!event->attr.exclude_kernel)
+               reg |= RTIT_CTL_OS;
+       if (!event->attr.exclude_user)
+               reg |= RTIT_CTL_USR;
+
+       reg |= (event->attr.config & PT_CONFIG_MASK);
+
+       wrmsrl(MSR_IA32_RTIT_CTL, reg);
+}
+
+static void pt_config_start(bool start)
+{
+       u64 ctl;
+
+       rdmsrl(MSR_IA32_RTIT_CTL, ctl);
+       if (start)
+               ctl |= RTIT_CTL_TRACEEN;
+       else
+               ctl &= ~RTIT_CTL_TRACEEN;
+       wrmsrl(MSR_IA32_RTIT_CTL, ctl);
+
+       /*
+        * A wrmsr that disables trace generation serializes other PT
+        * registers and causes all data packets to be written to memory,
+        * but a fence is required for the data to become globally visible.
+        *
+        * The below WMB, separating data store and aux_head store matches
+        * the consumer's RMB that separates aux_head load and data load.
+        */
+       if (!start)
+               wmb();
+}
+
+static void pt_config_buffer(void *buf, unsigned int topa_idx,
+                            unsigned int output_off)
+{
+       u64 reg;
+
+       wrmsrl(MSR_IA32_RTIT_OUTPUT_BASE, virt_to_phys(buf));
+
+       reg = 0x7f | ((u64)topa_idx << 7) | ((u64)output_off << 32);
+
+       wrmsrl(MSR_IA32_RTIT_OUTPUT_MASK, reg);
+}
+
+/*
+ * Keep ToPA table-related metadata on the same page as the actual table,
+ * taking up a few words from the top
+ */
+
+#define TENTS_PER_PAGE (((PAGE_SIZE - 40) / sizeof(struct topa_entry)) - 1)
+
+/**
+ * struct topa - page-sized ToPA table with metadata at the top
+ * @table:     actual ToPA table entries, as understood by PT hardware
+ * @list:      linkage to struct pt_buffer's list of tables
+ * @phys:      physical address of this page
+ * @offset:    offset of the first entry in this table in the buffer
+ * @size:      total size of all entries in this table
+ * @last:      index of the last initialized entry in this table
+ */
+struct topa {
+       struct topa_entry       table[TENTS_PER_PAGE];
+       struct list_head        list;
+       u64                     phys;
+       u64                     offset;
+       size_t                  size;
+       int                     last;
+};
+
+/* make -1 stand for the last table entry */
+#define TOPA_ENTRY(t, i) ((i) == -1 ? &(t)->table[(t)->last] : &(t)->table[(i)])
+
+/**
+ * topa_alloc() - allocate page-sized ToPA table
+ * @cpu:       CPU on which to allocate.
+ * @gfp:       Allocation flags.
+ *
+ * Return:     On success, return the pointer to ToPA table page.
+ */
+static struct topa *topa_alloc(int cpu, gfp_t gfp)
+{
+       int node = cpu_to_node(cpu);
+       struct topa *topa;
+       struct page *p;
+
+       p = alloc_pages_node(node, gfp | __GFP_ZERO, 0);
+       if (!p)
+               return NULL;
+
+       topa = page_address(p);
+       topa->last = 0;
+       topa->phys = page_to_phys(p);
+
+       /*
+        * In case of singe-entry ToPA, always put the self-referencing END
+        * link as the 2nd entry in the table
+        */
+       if (!pt_cap_get(PT_CAP_topa_multiple_entries)) {
+               TOPA_ENTRY(topa, 1)->base = topa->phys >> TOPA_SHIFT;
+               TOPA_ENTRY(topa, 1)->end = 1;
+       }
+
+       return topa;
+}
+
+/**
+ * topa_free() - free a page-sized ToPA table
+ * @topa:      Table to deallocate.
+ */
+static void topa_free(struct topa *topa)
+{
+       free_page((unsigned long)topa);
+}
+
+/**
+ * topa_insert_table() - insert a ToPA table into a buffer
+ * @buf:        PT buffer that's being extended.
+ * @topa:       New topa table to be inserted.
+ *
+ * If it's the first table in this buffer, set up buffer's pointers
+ * accordingly; otherwise, add a END=1 link entry to @topa to the current
+ * "last" table and adjust the last table pointer to @topa.
+ */
+static void topa_insert_table(struct pt_buffer *buf, struct topa *topa)
+{
+       struct topa *last = buf->last;
+
+       list_add_tail(&topa->list, &buf->tables);
+
+       if (!buf->first) {
+               buf->first = buf->last = buf->cur = topa;
+               return;
+       }
+
+       topa->offset = last->offset + last->size;
+       buf->last = topa;
+
+       if (!pt_cap_get(PT_CAP_topa_multiple_entries))
+               return;
+
+       BUG_ON(last->last != TENTS_PER_PAGE - 1);
+
+       TOPA_ENTRY(last, -1)->base = topa->phys >> TOPA_SHIFT;
+       TOPA_ENTRY(last, -1)->end = 1;
+}
+
+/**
+ * topa_table_full() - check if a ToPA table is filled up
+ * @topa:      ToPA table.
+ */
+static bool topa_table_full(struct topa *topa)
+{
+       /* single-entry ToPA is a special case */
+       if (!pt_cap_get(PT_CAP_topa_multiple_entries))
+               return !!topa->last;
+
+       return topa->last == TENTS_PER_PAGE - 1;
+}
+
+/**
+ * topa_insert_pages() - create a list of ToPA tables
+ * @buf:       PT buffer being initialized.
+ * @gfp:       Allocation flags.
+ *
+ * This initializes a list of ToPA tables with entries from
+ * the data_pages provided by rb_alloc_aux().
+ *
+ * Return:     0 on success or error code.
+ */
+static int topa_insert_pages(struct pt_buffer *buf, gfp_t gfp)
+{
+       struct topa *topa = buf->last;
+       int order = 0;
+       struct page *p;
+
+       p = virt_to_page(buf->data_pages[buf->nr_pages]);
+       if (PagePrivate(p))
+               order = page_private(p);
+
+       if (topa_table_full(topa)) {
+               topa = topa_alloc(buf->cpu, gfp);
+               if (!topa)
+                       return -ENOMEM;
+
+               topa_insert_table(buf, topa);
+       }
+
+       TOPA_ENTRY(topa, -1)->base = page_to_phys(p) >> TOPA_SHIFT;
+       TOPA_ENTRY(topa, -1)->size = order;
+       if (!buf->snapshot && !pt_cap_get(PT_CAP_topa_multiple_entries)) {
+               TOPA_ENTRY(topa, -1)->intr = 1;
+               TOPA_ENTRY(topa, -1)->stop = 1;
+       }
+
+       topa->last++;
+       topa->size += sizes(order);
+
+       buf->nr_pages += 1ul << order;
+
+       return 0;
+}
+
+/**
+ * pt_topa_dump() - print ToPA tables and their entries
+ * @buf:       PT buffer.
+ */
+static void pt_topa_dump(struct pt_buffer *buf)
+{
+       struct topa *topa;
+
+       list_for_each_entry(topa, &buf->tables, list) {
+               int i;
+
+               pr_debug("# table @%p (%016Lx), off %llx size %zx\n", topa->table,
+                        topa->phys, topa->offset, topa->size);
+               for (i = 0; i < TENTS_PER_PAGE; i++) {
+                       pr_debug("# entry @%p (%lx sz %u %c%c%c) raw=%16llx\n",
+                                &topa->table[i],
+                                (unsigned long)topa->table[i].base << TOPA_SHIFT,
+                                sizes(topa->table[i].size),
+                                topa->table[i].end ?  'E' : ' ',
+                                topa->table[i].intr ? 'I' : ' ',
+                                topa->table[i].stop ? 'S' : ' ',
+                                *(u64 *)&topa->table[i]);
+                       if ((pt_cap_get(PT_CAP_topa_multiple_entries) &&
+                            topa->table[i].stop) ||
+                           topa->table[i].end)
+                               break;
+               }
+       }
+}
+
+/**
+ * pt_buffer_advance() - advance to the next output region
+ * @buf:       PT buffer.
+ *
+ * Advance the current pointers in the buffer to the next ToPA entry.
+ */
+static void pt_buffer_advance(struct pt_buffer *buf)
+{
+       buf->output_off = 0;
+       buf->cur_idx++;
+
+       if (buf->cur_idx == buf->cur->last) {
+               if (buf->cur == buf->last)
+                       buf->cur = buf->first;
+               else
+                       buf->cur = list_entry(buf->cur->list.next, struct topa,
+                                             list);
+               buf->cur_idx = 0;
+       }
+}
+
+/**
+ * pt_update_head() - calculate current offsets and sizes
+ * @pt:                Per-cpu pt context.
+ *
+ * Update buffer's current write pointer position and data size.
+ */
+static void pt_update_head(struct pt *pt)
+{
+       struct pt_buffer *buf = perf_get_aux(&pt->handle);
+       u64 topa_idx, base, old;
+
+       /* offset of the first region in this table from the beginning of buf */
+       base = buf->cur->offset + buf->output_off;
+
+       /* offset of the current output region within this table */
+       for (topa_idx = 0; topa_idx < buf->cur_idx; topa_idx++)
+               base += sizes(buf->cur->table[topa_idx].size);
+
+       if (buf->snapshot) {
+               local_set(&buf->data_size, base);
+       } else {
+               old = (local64_xchg(&buf->head, base) &
+                      ((buf->nr_pages << PAGE_SHIFT) - 1));
+               if (base < old)
+                       base += buf->nr_pages << PAGE_SHIFT;
+
+               local_add(base - old, &buf->data_size);
+       }
+}
+
+/**
+ * pt_buffer_region() - obtain current output region's address
+ * @buf:       PT buffer.
+ */
+static void *pt_buffer_region(struct pt_buffer *buf)
+{
+       return phys_to_virt(buf->cur->table[buf->cur_idx].base << TOPA_SHIFT);
+}
+
+/**
+ * pt_buffer_region_size() - obtain current output region's size
+ * @buf:       PT buffer.
+ */
+static size_t pt_buffer_region_size(struct pt_buffer *buf)
+{
+       return sizes(buf->cur->table[buf->cur_idx].size);
+}
+
+/**
+ * pt_handle_status() - take care of possible status conditions
+ * @pt:                Per-cpu pt context.
+ */
+static void pt_handle_status(struct pt *pt)
+{
+       struct pt_buffer *buf = perf_get_aux(&pt->handle);
+       int advance = 0;
+       u64 status;
+
+       rdmsrl(MSR_IA32_RTIT_STATUS, status);
+
+       if (status & RTIT_STATUS_ERROR) {
+               pr_err_ratelimited("ToPA ERROR encountered, trying to recover\n");
+               pt_topa_dump(buf);
+               status &= ~RTIT_STATUS_ERROR;
+       }
+
+       if (status & RTIT_STATUS_STOPPED) {
+               status &= ~RTIT_STATUS_STOPPED;
+
+               /*
+                * On systems that only do single-entry ToPA, hitting STOP
+                * means we are already losing data; need to let the decoder
+                * know.
+                */
+               if (!pt_cap_get(PT_CAP_topa_multiple_entries) ||
+                   buf->output_off == sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) {
+                       local_inc(&buf->lost);
+                       advance++;
+               }
+       }
+
+       /*
+        * Also on single-entry ToPA implementations, interrupt will come
+        * before the output reaches its output region's boundary.
+        */
+       if (!pt_cap_get(PT_CAP_topa_multiple_entries) && !buf->snapshot &&
+           pt_buffer_region_size(buf) - buf->output_off <= TOPA_PMI_MARGIN) {
+               void *head = pt_buffer_region(buf);
+
+               /* everything within this margin needs to be zeroed out */
+               memset(head + buf->output_off, 0,
+                      pt_buffer_region_size(buf) -
+                      buf->output_off);
+               advance++;
+       }
+
+       if (advance)
+               pt_buffer_advance(buf);
+
+       wrmsrl(MSR_IA32_RTIT_STATUS, status);
+}
+
+/**
+ * pt_read_offset() - translate registers into buffer pointers
+ * @buf:       PT buffer.
+ *
+ * Set buffer's output pointers from MSR values.
+ */
+static void pt_read_offset(struct pt_buffer *buf)
+{
+       u64 offset, base_topa;
+
+       rdmsrl(MSR_IA32_RTIT_OUTPUT_BASE, base_topa);
+       buf->cur = phys_to_virt(base_topa);
+
+       rdmsrl(MSR_IA32_RTIT_OUTPUT_MASK, offset);
+       /* offset within current output region */
+       buf->output_off = offset >> 32;
+       /* index of current output region within this table */
+       buf->cur_idx = (offset & 0xffffff80) >> 7;
+}
+
+/**
+ * pt_topa_next_entry() - obtain index of the first page in the next ToPA entry
+ * @buf:       PT buffer.
+ * @pg:                Page offset in the buffer.
+ *
+ * When advancing to the next output region (ToPA entry), given a page offset
+ * into the buffer, we need to find the offset of the first page in the next
+ * region.
+ */
+static unsigned int pt_topa_next_entry(struct pt_buffer *buf, unsigned int pg)
+{
+       struct topa_entry *te = buf->topa_index[pg];
+
+       /* one region */
+       if (buf->first == buf->last && buf->first->last == 1)
+               return pg;
+
+       do {
+               pg++;
+               pg &= buf->nr_pages - 1;
+       } while (buf->topa_index[pg] == te);
+
+       return pg;
+}
+
+/**
+ * pt_buffer_reset_markers() - place interrupt and stop bits in the buffer
+ * @buf:       PT buffer.
+ * @handle:    Current output handle.
+ *
+ * Place INT and STOP marks to prevent overwriting old data that the consumer
+ * hasn't yet collected.
+ */
+static int pt_buffer_reset_markers(struct pt_buffer *buf,
+                                  struct perf_output_handle *handle)
+
+{
+       unsigned long idx, npages, end;
+
+       if (buf->snapshot)
+               return 0;
+
+       /* can't stop in the middle of an output region */
+       if (buf->output_off + handle->size + 1 <
+           sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size))
+               return -EINVAL;
+
+
+       /* single entry ToPA is handled by marking all regions STOP=1 INT=1 */
+       if (!pt_cap_get(PT_CAP_topa_multiple_entries))
+               return 0;
+
+       /* clear STOP and INT from current entry */
+       buf->topa_index[buf->stop_pos]->stop = 0;
+       buf->topa_index[buf->intr_pos]->intr = 0;
+
+       if (pt_cap_get(PT_CAP_topa_multiple_entries)) {
+               npages = (handle->size + 1) >> PAGE_SHIFT;
+               end = (local64_read(&buf->head) >> PAGE_SHIFT) + npages;
+               /*if (end > handle->wakeup >> PAGE_SHIFT)
+                 end = handle->wakeup >> PAGE_SHIFT;*/
+               idx = end & (buf->nr_pages - 1);
+               buf->stop_pos = idx;
+               idx = (local64_read(&buf->head) >> PAGE_SHIFT) + npages - 1;
+               idx &= buf->nr_pages - 1;
+               buf->intr_pos = idx;
+       }
+
+       buf->topa_index[buf->stop_pos]->stop = 1;
+       buf->topa_index[buf->intr_pos]->intr = 1;
+
+       return 0;
+}
+
+/**
+ * pt_buffer_setup_topa_index() - build topa_index[] table of regions
+ * @buf:       PT buffer.
+ *
+ * topa_index[] references output regions indexed by offset into the
+ * buffer for purposes of quick reverse lookup.
+ */
+static void pt_buffer_setup_topa_index(struct pt_buffer *buf)
+{
+       struct topa *cur = buf->first, *prev = buf->last;
+       struct topa_entry *te_cur = TOPA_ENTRY(cur, 0),
+               *te_prev = TOPA_ENTRY(prev, prev->last - 1);
+       int pg = 0, idx = 0, ntopa = 0;
+
+       while (pg < buf->nr_pages) {
+               int tidx;
+
+               /* pages within one topa entry */
+               for (tidx = 0; tidx < 1 << te_cur->size; tidx++, pg++)
+                       buf->topa_index[pg] = te_prev;
+
+               te_prev = te_cur;
+
+               if (idx == cur->last - 1) {
+                       /* advance to next topa table */
+                       idx = 0;
+                       cur = list_entry(cur->list.next, struct topa, list);
+                       ntopa++;
+               } else
+                       idx++;
+               te_cur = TOPA_ENTRY(cur, idx);
+       }
+
+}
+
+/**
+ * pt_buffer_reset_offsets() - adjust buffer's write pointers from aux_head
+ * @buf:       PT buffer.
+ * @head:      Write pointer (aux_head) from AUX buffer.
+ *
+ * Find the ToPA table and entry corresponding to given @head and set buffer's
+ * "current" pointers accordingly.
+ */
+static void pt_buffer_reset_offsets(struct pt_buffer *buf, unsigned long head)
+{
+       int pg;
+
+       if (buf->snapshot)
+               head &= (buf->nr_pages << PAGE_SHIFT) - 1;
+
+       pg = (head >> PAGE_SHIFT) & (buf->nr_pages - 1);
+       pg = pt_topa_next_entry(buf, pg);
+
+       buf->cur = (struct topa *)((unsigned long)buf->topa_index[pg] & PAGE_MASK);
+       buf->cur_idx = ((unsigned long)buf->topa_index[pg] -
+                       (unsigned long)buf->cur) / sizeof(struct topa_entry);
+       buf->output_off = head & (sizes(buf->cur->table[buf->cur_idx].size) - 1);
+
+       local64_set(&buf->head, head);
+       local_set(&buf->data_size, 0);
+}
+
+/**
+ * pt_buffer_fini_topa() - deallocate ToPA structure of a buffer
+ * @buf:       PT buffer.
+ */
+static void pt_buffer_fini_topa(struct pt_buffer *buf)
+{
+       struct topa *topa, *iter;
+
+       list_for_each_entry_safe(topa, iter, &buf->tables, list) {
+               /*
+                * right now, this is in free_aux() path only, so
+                * no need to unlink this table from the list
+                */
+               topa_free(topa);
+       }
+}
+
+/**
+ * pt_buffer_init_topa() - initialize ToPA table for pt buffer
+ * @buf:       PT buffer.
+ * @size:      Total size of all regions within this ToPA.
+ * @gfp:       Allocation flags.
+ */
+static int pt_buffer_init_topa(struct pt_buffer *buf, unsigned long nr_pages,
+                              gfp_t gfp)
+{
+       struct topa *topa;
+       int err;
+
+       topa = topa_alloc(buf->cpu, gfp);
+       if (!topa)
+               return -ENOMEM;
+
+       topa_insert_table(buf, topa);
+
+       while (buf->nr_pages < nr_pages) {
+               err = topa_insert_pages(buf, gfp);
+               if (err) {
+                       pt_buffer_fini_topa(buf);
+                       return -ENOMEM;
+               }
+       }
+
+       pt_buffer_setup_topa_index(buf);
+
+       /* link last table to the first one, unless we're double buffering */
+       if (pt_cap_get(PT_CAP_topa_multiple_entries)) {
+               TOPA_ENTRY(buf->last, -1)->base = buf->first->phys >> TOPA_SHIFT;
+               TOPA_ENTRY(buf->last, -1)->end = 1;
+       }
+
+       pt_topa_dump(buf);
+       return 0;
+}
+
+/**
+ * pt_buffer_setup_aux() - set up topa tables for a PT buffer
+ * @cpu:       Cpu on which to allocate, -1 means current.
+ * @pages:     Array of pointers to buffer pages passed from perf core.
+ * @nr_pages:  Number of pages in the buffer.
+ * @snapshot:  If this is a snapshot/overwrite counter.
+ *
+ * This is a pmu::setup_aux callback that sets up ToPA tables and all the
+ * bookkeeping for an AUX buffer.
+ *
+ * Return:     Our private PT buffer structure.
+ */
+static void *
+pt_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool snapshot)
+{
+       struct pt_buffer *buf;
+       int node, ret;
+
+       if (!nr_pages)
+               return NULL;
+
+       if (cpu == -1)
+               cpu = raw_smp_processor_id();
+       node = cpu_to_node(cpu);
+
+       buf = kzalloc_node(offsetof(struct pt_buffer, topa_index[nr_pages]),
+                          GFP_KERNEL, node);
+       if (!buf)
+               return NULL;
+
+       buf->cpu = cpu;
+       buf->snapshot = snapshot;
+       buf->data_pages = pages;
+
+       INIT_LIST_HEAD(&buf->tables);
+
+       ret = pt_buffer_init_topa(buf, nr_pages, GFP_KERNEL);
+       if (ret) {
+               kfree(buf);
+               return NULL;
+       }
+
+       return buf;
+}
+
+/**
+ * pt_buffer_free_aux() - perf AUX deallocation path callback
+ * @data:      PT buffer.
+ */
+static void pt_buffer_free_aux(void *data)
+{
+       struct pt_buffer *buf = data;
+
+       pt_buffer_fini_topa(buf);
+       kfree(buf);
+}
+
+/**
+ * pt_buffer_is_full() - check if the buffer is full
+ * @buf:       PT buffer.
+ * @pt:                Per-cpu pt handle.
+ *
+ * If the user hasn't read data from the output region that aux_head
+ * points to, the buffer is considered full: the user needs to read at
+ * least this region and update aux_tail to point past it.
+ */
+static bool pt_buffer_is_full(struct pt_buffer *buf, struct pt *pt)
+{
+       if (buf->snapshot)
+               return false;
+
+       if (local_read(&buf->data_size) >= pt->handle.size)
+               return true;
+
+       return false;
+}
+
+/**
+ * intel_pt_interrupt() - PT PMI handler
+ */
+void intel_pt_interrupt(void)
+{
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
+       struct pt_buffer *buf;
+       struct perf_event *event = pt->handle.event;
+
+       /*
+        * There may be a dangling PT bit in the interrupt status register
+        * after PT has been disabled by pt_event_stop(). Make sure we don't
+        * do anything (particularly, re-enable) for this event here.
+        */
+       if (!ACCESS_ONCE(pt->handle_nmi))
+               return;
+
+       pt_config_start(false);
+
+       if (!event)
+               return;
+
+       buf = perf_get_aux(&pt->handle);
+       if (!buf)
+               return;
+
+       pt_read_offset(buf);
+
+       pt_handle_status(pt);
+
+       pt_update_head(pt);
+
+       perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0),
+                           local_xchg(&buf->lost, 0));
+
+       if (!event->hw.state) {
+               int ret;
+
+               buf = perf_aux_output_begin(&pt->handle, event);
+               if (!buf) {
+                       event->hw.state = PERF_HES_STOPPED;
+                       return;
+               }
+
+               pt_buffer_reset_offsets(buf, pt->handle.head);
+               ret = pt_buffer_reset_markers(buf, &pt->handle);
+               if (ret) {
+                       perf_aux_output_end(&pt->handle, 0, true);
+                       return;
+               }
+
+               pt_config_buffer(buf->cur->table, buf->cur_idx,
+                                buf->output_off);
+               wrmsrl(MSR_IA32_RTIT_STATUS, 0);
+               pt_config(event);
+       }
+}
+
+/*
+ * PMU callbacks
+ */
+
+static void pt_event_start(struct perf_event *event, int mode)
+{
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
+       struct pt_buffer *buf = perf_get_aux(&pt->handle);
+
+       if (pt_is_running() || !buf || pt_buffer_is_full(buf, pt)) {
+               event->hw.state = PERF_HES_STOPPED;
+               return;
+       }
+
+       ACCESS_ONCE(pt->handle_nmi) = 1;
+       event->hw.state = 0;
+
+       pt_config_buffer(buf->cur->table, buf->cur_idx,
+                        buf->output_off);
+       wrmsrl(MSR_IA32_RTIT_STATUS, 0);
+       pt_config(event);
+}
+
+static void pt_event_stop(struct perf_event *event, int mode)
+{
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
+
+       /*
+        * Protect against the PMI racing with disabling wrmsr,
+        * see comment in intel_pt_interrupt().
+        */
+       ACCESS_ONCE(pt->handle_nmi) = 0;
+       pt_config_start(false);
+
+       if (event->hw.state == PERF_HES_STOPPED)
+               return;
+
+       event->hw.state = PERF_HES_STOPPED;
+
+       if (mode & PERF_EF_UPDATE) {
+               struct pt *pt = this_cpu_ptr(&pt_ctx);
+               struct pt_buffer *buf = perf_get_aux(&pt->handle);
+
+               if (!buf)
+                       return;
+
+               if (WARN_ON_ONCE(pt->handle.event != event))
+                       return;
+
+               pt_read_offset(buf);
+
+               pt_handle_status(pt);
+
+               pt_update_head(pt);
+       }
+}
+
+static void pt_event_del(struct perf_event *event, int mode)
+{
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
+       struct pt_buffer *buf;
+
+       pt_event_stop(event, PERF_EF_UPDATE);
+
+       buf = perf_get_aux(&pt->handle);
+
+       if (buf) {
+               if (buf->snapshot)
+                       pt->handle.head =
+                               local_xchg(&buf->data_size,
+                                          buf->nr_pages << PAGE_SHIFT);
+               perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0),
+                                   local_xchg(&buf->lost, 0));
+       }
+}
+
+static int pt_event_add(struct perf_event *event, int mode)
+{
+       struct pt_buffer *buf;
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
+       struct hw_perf_event *hwc = &event->hw;
+       int ret = -EBUSY;
+
+       if (pt->handle.event)
+               goto out;
+
+       buf = perf_aux_output_begin(&pt->handle, event);
+       if (!buf) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       pt_buffer_reset_offsets(buf, pt->handle.head);
+       if (!buf->snapshot) {
+               ret = pt_buffer_reset_markers(buf, &pt->handle);
+               if (ret) {
+                       perf_aux_output_end(&pt->handle, 0, true);
+                       goto out;
+               }
+       }
+
+       if (mode & PERF_EF_START) {
+               pt_event_start(event, 0);
+               if (hwc->state == PERF_HES_STOPPED) {
+                       pt_event_del(event, 0);
+                       ret = -EBUSY;
+               }
+       } else {
+               hwc->state = PERF_HES_STOPPED;
+       }
+
+       ret = 0;
+out:
+
+       if (ret)
+               hwc->state = PERF_HES_STOPPED;
+
+       return ret;
+}
+
+static void pt_event_read(struct perf_event *event)
+{
+}
+
+static void pt_event_destroy(struct perf_event *event)
+{
+       x86_del_exclusive(x86_lbr_exclusive_pt);
+}
+
+static int pt_event_init(struct perf_event *event)
+{
+       if (event->attr.type != pt_pmu.pmu.type)
+               return -ENOENT;
+
+       if (!pt_event_valid(event))
+               return -EINVAL;
+
+       if (x86_add_exclusive(x86_lbr_exclusive_pt))
+               return -EBUSY;
+
+       event->destroy = pt_event_destroy;
+
+       return 0;
+}
+
+static __init int pt_init(void)
+{
+       int ret, cpu, prior_warn = 0;
+
+       BUILD_BUG_ON(sizeof(struct topa) > PAGE_SIZE);
+       get_online_cpus();
+       for_each_online_cpu(cpu) {
+               u64 ctl;
+
+               ret = rdmsrl_safe_on_cpu(cpu, MSR_IA32_RTIT_CTL, &ctl);
+               if (!ret && (ctl & RTIT_CTL_TRACEEN))
+                       prior_warn++;
+       }
+       put_online_cpus();
+
+       if (prior_warn) {
+               x86_add_exclusive(x86_lbr_exclusive_pt);
+               pr_warn("PT is enabled at boot time, doing nothing\n");
+
+               return -EBUSY;
+       }
+
+       ret = pt_pmu_hw_init();
+       if (ret)
+               return ret;
+
+       if (!pt_cap_get(PT_CAP_topa_output)) {
+               pr_warn("ToPA output is not supported on this CPU\n");
+               return -ENODEV;
+       }
+
+       if (!pt_cap_get(PT_CAP_topa_multiple_entries))
+               pt_pmu.pmu.capabilities =
+                       PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_AUX_SW_DOUBLEBUF;
+
+       pt_pmu.pmu.capabilities |= PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_ITRACE;
+       pt_pmu.pmu.attr_groups  = pt_attr_groups;
+       pt_pmu.pmu.task_ctx_nr  = perf_sw_context;
+       pt_pmu.pmu.event_init   = pt_event_init;
+       pt_pmu.pmu.add          = pt_event_add;
+       pt_pmu.pmu.del          = pt_event_del;
+       pt_pmu.pmu.start        = pt_event_start;
+       pt_pmu.pmu.stop         = pt_event_stop;
+       pt_pmu.pmu.read         = pt_event_read;
+       pt_pmu.pmu.setup_aux    = pt_buffer_setup_aux;
+       pt_pmu.pmu.free_aux     = pt_buffer_free_aux;
+       ret = perf_pmu_register(&pt_pmu.pmu, "intel_pt", -1);
+
+       return ret;
+}
+
+module_init(pt_init);
index 21af6149edf2e79dd462a7e8f4994c8fd201fa0f..12d9548457e7195a8a36b458e374cab9cabe5e07 100644 (file)
@@ -1132,8 +1132,7 @@ static int snbep_pci2phy_map_init(int devid)
                }
        }
 
-       if (ubox_dev)
-               pci_dev_put(ubox_dev);
+       pci_dev_put(ubox_dev);
 
        return err ? pcibios_err_to_errno(err) : 0;
 }
index 60639093d536a98806d21f9f675ffba6526c1322..3d423a101fae05ccd722a4e564b83ba5e0112b6e 100644 (file)
@@ -41,6 +41,7 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
                { X86_FEATURE_HWP_ACT_WINDOW,   CR_EAX, 9, 0x00000006, 0 },
                { X86_FEATURE_HWP_EPP,          CR_EAX,10, 0x00000006, 0 },
                { X86_FEATURE_HWP_PKG_REQ,      CR_EAX,11, 0x00000006, 0 },
+               { X86_FEATURE_INTEL_PT,         CR_EBX,25, 0x00000007, 0 },
                { X86_FEATURE_APERFMPERF,       CR_ECX, 0, 0x00000006, 0 },
                { X86_FEATURE_EPB,              CR_ECX, 3, 0x00000006, 0 },
                { X86_FEATURE_HW_PSTATE,        CR_EDX, 7, 0x80000007, 0 },
index aceb2f90c7166afcfa844cd7da58bfe6358efaa6..c76d3e37c6e1dc99a7083f05a2f79b7cd82968e1 100644 (file)
@@ -105,7 +105,7 @@ static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
 #ifdef CONFIG_X86_32
        struct pt_regs fixed_regs;
 
-       if (!user_mode_vm(regs)) {
+       if (!user_mode(regs)) {
                crash_fixup_ss_esp(&fixed_regs, regs);
                regs = &fixed_regs;
        }
index 3d3503351242b7c6d8dcc0d32350e36e63da1939..6367a780cc8ca891b9513d2e4688717c8d5d3207 100644 (file)
@@ -286,13 +286,13 @@ static void __init x86_flattree_get_config(void)
        initial_boot_params = dt = early_memremap(initial_dtb, map_len);
        size = of_get_flat_dt_size();
        if (map_len < size) {
-               early_iounmap(dt, map_len);
+               early_memunmap(dt, map_len);
                initial_boot_params = dt = early_memremap(initial_dtb, size);
                map_len = size;
        }
 
        unflatten_and_copy_device_tree();
-       early_iounmap(dt, map_len);
+       early_memunmap(dt, map_len);
 }
 #else
 static inline void x86_flattree_get_config(void) { }
index cf3df1d8d039e5d1689417e04c56bcb7057ae754..9c30acfadae24757cca11f00513d089e488da78d 100644 (file)
@@ -25,10 +25,12 @@ unsigned int code_bytes = 64;
 int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE;
 static int die_counter;
 
-static void printk_stack_address(unsigned long address, int reliable)
+static void printk_stack_address(unsigned long address, int reliable,
+               void *data)
 {
-       pr_cont(" [<%p>] %s%pB\n",
-               (void *)address, reliable ? "" : "? ", (void *)address);
+       printk("%s [<%p>] %s%pB\n",
+               (char *)data, (void *)address, reliable ? "" : "? ",
+               (void *)address);
 }
 
 void printk_address(unsigned long address)
@@ -155,8 +157,7 @@ static int print_trace_stack(void *data, char *name)
 static void print_trace_address(void *data, unsigned long addr, int reliable)
 {
        touch_nmi_watchdog();
-       printk(data);
-       printk_stack_address(addr, reliable);
+       printk_stack_address(addr, reliable, data);
 }
 
 static const struct stacktrace_ops print_trace_ops = {
@@ -278,7 +279,7 @@ int __die(const char *str, struct pt_regs *regs, long err)
        print_modules();
        show_regs(regs);
 #ifdef CONFIG_X86_32
-       if (user_mode_vm(regs)) {
+       if (user_mode(regs)) {
                sp = regs->sp;
                ss = regs->ss & 0xffff;
        } else {
@@ -307,7 +308,7 @@ void die(const char *str, struct pt_regs *regs, long err)
        unsigned long flags = oops_begin();
        int sig = SIGSEGV;
 
-       if (!user_mode_vm(regs))
+       if (!user_mode(regs))
                report_bug(regs->ip, regs);
 
        if (__die(str, regs, err))
index 5abd4cd4230c69f3ff4730e97a1297be40013c44..464ffd69b92e9ef376b9c534aec3c12973d6ad7a 100644 (file)
@@ -108,9 +108,12 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
        for (i = 0; i < kstack_depth_to_print; i++) {
                if (kstack_end(stack))
                        break;
-               if (i && ((i % STACKSLOTS_PER_LINE) == 0))
-                       pr_cont("\n");
-               pr_cont(" %08lx", *stack++);
+               if ((i % STACKSLOTS_PER_LINE) == 0) {
+                       if (i != 0)
+                               pr_cont("\n");
+                       printk("%s %08lx", log_lvl, *stack++);
+               } else
+                       pr_cont(" %08lx", *stack++);
                touch_nmi_watchdog();
        }
        pr_cont("\n");
@@ -123,13 +126,13 @@ void show_regs(struct pt_regs *regs)
        int i;
 
        show_regs_print_info(KERN_EMERG);
-       __show_regs(regs, !user_mode_vm(regs));
+       __show_regs(regs, !user_mode(regs));
 
        /*
         * When in-kernel, we also print out the stack and code at the
         * time of the fault..
         */
-       if (!user_mode_vm(regs)) {
+       if (!user_mode(regs)) {
                unsigned int code_prologue = code_bytes * 43 / 64;
                unsigned int code_len = code_bytes;
                unsigned char c;
index ff86f19b575849fca7e20a4086e09f798ae8291d..5f1c6266eb3028579f5036161dc240387dcb124f 100644 (file)
@@ -280,12 +280,15 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
                                pr_cont(" <EOI> ");
                        }
                } else {
-               if (((long) stack & (THREAD_SIZE-1)) == 0)
+               if (kstack_end(stack))
                        break;
                }
-               if (i && ((i % STACKSLOTS_PER_LINE) == 0))
-                       pr_cont("\n");
-               pr_cont(" %016lx", *stack++);
+               if ((i % STACKSLOTS_PER_LINE) == 0) {
+                       if (i != 0)
+                               pr_cont("\n");
+                       printk("%s %016lx", log_lvl, *stack++);
+               } else
+                       pr_cont(" %016lx", *stack++);
                touch_nmi_watchdog();
        }
        preempt_enable();
index 46201deee923fffd686244546dc7039dbaab8b2b..7d46bb2603346b41dfb924eee28975cd76e704f3 100644 (file)
@@ -661,7 +661,7 @@ void __init parse_e820_ext(u64 phys_addr, u32 data_len)
        extmap = (struct e820entry *)(sdata->data);
        __append_e820_map(extmap, entries);
        sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
-       early_iounmap(sdata, data_len);
+       early_memunmap(sdata, data_len);
        printk(KERN_INFO "e820: extended physical RAM map:\n");
        e820_print_map("extended");
 }
index a62536a1be889019081696b2e7df908b0a4ef9fb..49ff55ef9b26cba11af5d9b36c694926ea3e7f6b 100644 (file)
@@ -95,20 +95,6 @@ static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
 #define DLL             0       /*  Divisor Latch Low         */
 #define DLH             1       /*  Divisor latch High        */
 
-static void mem32_serial_out(unsigned long addr, int offset, int value)
-{
-       uint32_t *vaddr = (uint32_t *)addr;
-       /* shift implied by pointer type */
-       writel(value, vaddr + offset);
-}
-
-static unsigned int mem32_serial_in(unsigned long addr, int offset)
-{
-       uint32_t *vaddr = (uint32_t *)addr;
-       /* shift implied by pointer type */
-       return readl(vaddr + offset);
-}
-
 static unsigned int io_serial_in(unsigned long addr, int offset)
 {
        return inb(addr + offset);
@@ -205,6 +191,20 @@ static __init void early_serial_init(char *s)
 }
 
 #ifdef CONFIG_PCI
+static void mem32_serial_out(unsigned long addr, int offset, int value)
+{
+       u32 *vaddr = (u32 *)addr;
+       /* shift implied by pointer type */
+       writel(value, vaddr + offset);
+}
+
+static unsigned int mem32_serial_in(unsigned long addr, int offset)
+{
+       u32 *vaddr = (u32 *)addr;
+       /* shift implied by pointer type */
+       return readl(vaddr + offset);
+}
+
 /*
  * early_pci_serial_init()
  *
@@ -217,8 +217,8 @@ static __init void early_pci_serial_init(char *s)
        unsigned divisor;
        unsigned long baud = DEFAULT_BAUD;
        u8 bus, slot, func;
-       uint32_t classcode, bar0;
-       uint16_t cmdreg;
+       u32 classcode, bar0;
+       u16 cmdreg;
        char *e;
 
 
index 31e2d5bf3e38887ca06402bff6c647b9aa9a3c5c..1c309763e32197d255b72e3f976aa948ab67f431 100644 (file)
@@ -395,10 +395,13 @@ sysenter_past_esp:
        /*CFI_REL_OFFSET cs, 0*/
        /*
         * Push current_thread_info()->sysenter_return to the stack.
-        * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
-        * pushed above; +8 corresponds to copy_thread's esp0 setting.
+        * A tiny bit of offset fixup is necessary: TI_sysenter_return
+        * is relative to thread_info, which is at the bottom of the
+        * kernel stack page.  4*4 means the 4 words pushed above;
+        * TOP_OF_KERNEL_STACK_PADDING takes us to the top of the stack;
+        * and THREAD_SIZE takes us to the bottom.
         */
-       pushl_cfi ((TI_sysenter_return)-THREAD_SIZE+8+4*4)(%esp)
+       pushl_cfi ((TI_sysenter_return) - THREAD_SIZE + TOP_OF_KERNEL_STACK_PADDING + 4*4)(%esp)
        CFI_REL_OFFSET eip, 0
 
        pushl_cfi %eax
@@ -432,7 +435,7 @@ sysenter_after_call:
        TRACE_IRQS_OFF
        movl TI_flags(%ebp), %ecx
        testl $_TIF_ALLWORK_MASK, %ecx
-       jne sysexit_audit
+       jnz sysexit_audit
 sysenter_exit:
 /* if something modifies registers it must also disable sysexit */
        movl PT_EIP(%esp), %edx
@@ -460,7 +463,7 @@ sysenter_audit:
 
 sysexit_audit:
        testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %ecx
-       jne syscall_exit_work
+       jnz syscall_exit_work
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_ANY)
        movl %eax,%edx          /* second arg, syscall return value */
@@ -472,7 +475,7 @@ sysexit_audit:
        TRACE_IRQS_OFF
        movl TI_flags(%ebp), %ecx
        testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %ecx
-       jne syscall_exit_work
+       jnz syscall_exit_work
        movl PT_EAX(%esp),%eax  /* reload syscall return value */
        jmp sysenter_exit
 #endif
@@ -510,7 +513,7 @@ syscall_exit:
        TRACE_IRQS_OFF
        movl TI_flags(%ebp), %ecx
        testl $_TIF_ALLWORK_MASK, %ecx  # current->work
-       jne syscall_exit_work
+       jnz syscall_exit_work
 
 restore_all:
        TRACE_IRQS_IRET
@@ -612,7 +615,7 @@ work_notifysig:                             # deal with pending signals and
 #ifdef CONFIG_VM86
        testl $X86_EFLAGS_VM, PT_EFLAGS(%esp)
        movl %esp, %eax
-       jne work_notifysig_v86          # returning to kernel-space or
+       jnz work_notifysig_v86          # returning to kernel-space or
                                        # vm86-space
 1:
 #else
@@ -720,43 +723,22 @@ END(sysenter_badsys)
 .endm
 
 /*
- * Build the entry stubs and pointer table with some assembler magic.
- * We pack 7 stubs into a single 32-byte chunk, which will fit in a
- * single cache line on all modern x86 implementations.
+ * Build the entry stubs with some assembler magic.
+ * We pack 1 stub into every 8-byte block.
  */
-.section .init.rodata,"a"
-ENTRY(interrupt)
-.section .entry.text, "ax"
-       .p2align 5
-       .p2align CONFIG_X86_L1_CACHE_SHIFT
+       .align 8
 ENTRY(irq_entries_start)
        RING0_INT_FRAME
-vector=FIRST_EXTERNAL_VECTOR
-.rept (FIRST_SYSTEM_VECTOR-FIRST_EXTERNAL_VECTOR+6)/7
-       .balign 32
-  .rept        7
-    .if vector < FIRST_SYSTEM_VECTOR
-      .if vector <> FIRST_EXTERNAL_VECTOR
+    vector=FIRST_EXTERNAL_VECTOR
+    .rept (FIRST_SYSTEM_VECTOR - FIRST_EXTERNAL_VECTOR)
+       pushl_cfi $(~vector+0x80)       /* Note: always in signed byte range */
+    vector=vector+1
+       jmp     common_interrupt
        CFI_ADJUST_CFA_OFFSET -4
-      .endif
-1:     pushl_cfi $(~vector+0x80)       /* Note: always in signed byte range */
-      .if ((vector-FIRST_EXTERNAL_VECTOR)%7) <> 6
-       jmp 2f
-      .endif
-      .previous
-       .long 1b
-      .section .entry.text, "ax"
-vector=vector+1
-    .endif
-  .endr
-2:     jmp common_interrupt
-.endr
+       .align  8
+    .endr
 END(irq_entries_start)
 
-.previous
-END(interrupt)
-.previous
-
 /*
  * the CPU automatically disables interrupts when executing an IRQ vector,
  * so IRQ-flags tracing has to follow that:
@@ -816,15 +798,9 @@ ENTRY(simd_coprocessor_error)
        pushl_cfi $0
 #ifdef CONFIG_X86_INVD_BUG
        /* AMD 486 bug: invd from userspace calls exception 19 instead of #GP */
-661:   pushl_cfi $do_general_protection
-662:
-.section .altinstructions,"a"
-       altinstruction_entry 661b, 663f, X86_FEATURE_XMM, 662b-661b, 664f-663f
-.previous
-.section .altinstr_replacement,"ax"
-663:   pushl $do_simd_coprocessor_error
-664:
-.previous
+       ALTERNATIVE "pushl_cfi $do_general_protection", \
+                   "pushl $do_simd_coprocessor_error", \
+                   X86_FEATURE_XMM
 #else
        pushl_cfi $do_simd_coprocessor_error
 #endif
@@ -1240,20 +1216,13 @@ error_code:
        /*CFI_REL_OFFSET es, 0*/
        pushl_cfi %ds
        /*CFI_REL_OFFSET ds, 0*/
-       pushl_cfi %eax
-       CFI_REL_OFFSET eax, 0
-       pushl_cfi %ebp
-       CFI_REL_OFFSET ebp, 0
-       pushl_cfi %edi
-       CFI_REL_OFFSET edi, 0
-       pushl_cfi %esi
-       CFI_REL_OFFSET esi, 0
-       pushl_cfi %edx
-       CFI_REL_OFFSET edx, 0
-       pushl_cfi %ecx
-       CFI_REL_OFFSET ecx, 0
-       pushl_cfi %ebx
-       CFI_REL_OFFSET ebx, 0
+       pushl_cfi_reg eax
+       pushl_cfi_reg ebp
+       pushl_cfi_reg edi
+       pushl_cfi_reg esi
+       pushl_cfi_reg edx
+       pushl_cfi_reg ecx
+       pushl_cfi_reg ebx
        cld
        movl $(__KERNEL_PERCPU), %ecx
        movl %ecx, %fs
index f0095a76c18211813d711bfa52b82c916190f42d..c7b238494b31f267b9c4fc3f4a74d519fb7b3aa5 100644 (file)
  * NOTE: This code handles signal-recognition, which happens every time
  * after an interrupt and after each system call.
  *
- * Normal syscalls and interrupts don't save a full stack frame, this is
- * only done for syscall tracing, signals or fork/exec et.al.
- *
  * A note on terminology:
- * - top of stack: Architecture defined interrupt frame from SS to RIP
+ * - iret frame: Architecture defined interrupt frame from SS to RIP
  * at the top of the kernel process stack.
- * - partial stack frame: partially saved registers up to R11.
- * - full stack frame: Like partial stack frame, but all register saved.
  *
  * Some macro usage:
  * - CFI macros are used to generate dwarf2 unwind information for better
  * backtraces. They don't change any code.
- * - SAVE_ALL/RESTORE_ALL - Save/restore all registers
- * - SAVE_ARGS/RESTORE_ARGS - Save/restore registers that C functions modify.
- * There are unfortunately lots of special cases where some registers
- * not touched. The macro is a big mess that should be cleaned up.
- * - SAVE_REST/RESTORE_REST - Handle the registers not saved by SAVE_ARGS.
- * Gives a full stack frame.
  * - ENTRY/END Define functions in the symbol table.
- * - FIXUP_TOP_OF_STACK/RESTORE_TOP_OF_STACK - Fix up the hardware stack
- * frame that is otherwise undefined after a SYSCALL
  * - TRACE_IRQ_* - Trace hard interrupt state for lock debugging.
  * - idtentry - Define exception entry points.
  */
        .section .entry.text, "ax"
 
 
-#ifndef CONFIG_PREEMPT
-#define retint_kernel retint_restore_args
-#endif
-
 #ifdef CONFIG_PARAVIRT
 ENTRY(native_usergs_sysret64)
        swapgs
@@ -82,9 +65,9 @@ ENDPROC(native_usergs_sysret64)
 #endif /* CONFIG_PARAVIRT */
 
 
-.macro TRACE_IRQS_IRETQ offset=ARGOFFSET
+.macro TRACE_IRQS_IRETQ
 #ifdef CONFIG_TRACE_IRQFLAGS
-       bt   $9,EFLAGS-\offset(%rsp)    /* interrupts off? */
+       bt   $9,EFLAGS(%rsp)    /* interrupts off? */
        jnc  1f
        TRACE_IRQS_ON
 1:
@@ -116,8 +99,8 @@ ENDPROC(native_usergs_sysret64)
        call debug_stack_reset
 .endm
 
-.macro TRACE_IRQS_IRETQ_DEBUG offset=ARGOFFSET
-       bt   $9,EFLAGS-\offset(%rsp)    /* interrupts off? */
+.macro TRACE_IRQS_IRETQ_DEBUG
+       bt   $9,EFLAGS(%rsp)    /* interrupts off? */
        jnc  1f
        TRACE_IRQS_ON_DEBUG
 1:
@@ -130,34 +113,7 @@ ENDPROC(native_usergs_sysret64)
 #endif
 
 /*
- * C code is not supposed to know about undefined top of stack. Every time
- * a C function with an pt_regs argument is called from the SYSCALL based
- * fast path FIXUP_TOP_OF_STACK is needed.
- * RESTORE_TOP_OF_STACK syncs the syscall state after any possible ptregs
- * manipulation.
- */
-
-       /* %rsp:at FRAMEEND */
-       .macro FIXUP_TOP_OF_STACK tmp offset=0
-       movq PER_CPU_VAR(old_rsp),\tmp
-       movq \tmp,RSP+\offset(%rsp)
-       movq $__USER_DS,SS+\offset(%rsp)
-       movq $__USER_CS,CS+\offset(%rsp)
-       movq RIP+\offset(%rsp),\tmp  /* get rip */
-       movq \tmp,RCX+\offset(%rsp)  /* copy it to rcx as sysret would do */
-       movq R11+\offset(%rsp),\tmp  /* get eflags */
-       movq \tmp,EFLAGS+\offset(%rsp)
-       .endm
-
-       .macro RESTORE_TOP_OF_STACK tmp offset=0
-       movq RSP+\offset(%rsp),\tmp
-       movq \tmp,PER_CPU_VAR(old_rsp)
-       movq EFLAGS+\offset(%rsp),\tmp
-       movq \tmp,R11+\offset(%rsp)
-       .endm
-
-/*
- * initial frame state for interrupts (and exceptions without error code)
+ * empty frame
  */
        .macro EMPTY_FRAME start=1 offset=0
        .if \start
@@ -173,12 +129,12 @@ ENDPROC(native_usergs_sysret64)
  * initial frame state for interrupts (and exceptions without error code)
  */
        .macro INTR_FRAME start=1 offset=0
-       EMPTY_FRAME \start, SS+8+\offset-RIP
-       /*CFI_REL_OFFSET ss, SS+\offset-RIP*/
-       CFI_REL_OFFSET rsp, RSP+\offset-RIP
-       /*CFI_REL_OFFSET rflags, EFLAGS+\offset-RIP*/
-       /*CFI_REL_OFFSET cs, CS+\offset-RIP*/
-       CFI_REL_OFFSET rip, RIP+\offset-RIP
+       EMPTY_FRAME \start, 5*8+\offset
+       /*CFI_REL_OFFSET ss, 4*8+\offset*/
+       CFI_REL_OFFSET rsp, 3*8+\offset
+       /*CFI_REL_OFFSET rflags, 2*8+\offset*/
+       /*CFI_REL_OFFSET cs, 1*8+\offset*/
+       CFI_REL_OFFSET rip, 0*8+\offset
        .endm
 
 /*
@@ -186,30 +142,23 @@ ENDPROC(native_usergs_sysret64)
  * with vector already pushed)
  */
        .macro XCPT_FRAME start=1 offset=0
-       INTR_FRAME \start, RIP+\offset-ORIG_RAX
-       .endm
-
-/*
- * frame that enables calling into C.
- */
-       .macro PARTIAL_FRAME start=1 offset=0
-       XCPT_FRAME \start, ORIG_RAX+\offset-ARGOFFSET
-       CFI_REL_OFFSET rdi, RDI+\offset-ARGOFFSET
-       CFI_REL_OFFSET rsi, RSI+\offset-ARGOFFSET
-       CFI_REL_OFFSET rdx, RDX+\offset-ARGOFFSET
-       CFI_REL_OFFSET rcx, RCX+\offset-ARGOFFSET
-       CFI_REL_OFFSET rax, RAX+\offset-ARGOFFSET
-       CFI_REL_OFFSET r8, R8+\offset-ARGOFFSET
-       CFI_REL_OFFSET r9, R9+\offset-ARGOFFSET
-       CFI_REL_OFFSET r10, R10+\offset-ARGOFFSET
-       CFI_REL_OFFSET r11, R11+\offset-ARGOFFSET
+       INTR_FRAME \start, 1*8+\offset
        .endm
 
 /*
  * frame that enables passing a complete pt_regs to a C function.
  */
        .macro DEFAULT_FRAME start=1 offset=0
-       PARTIAL_FRAME \start, R11+\offset-R15
+       XCPT_FRAME \start, ORIG_RAX+\offset
+       CFI_REL_OFFSET rdi, RDI+\offset
+       CFI_REL_OFFSET rsi, RSI+\offset
+       CFI_REL_OFFSET rdx, RDX+\offset
+       CFI_REL_OFFSET rcx, RCX+\offset
+       CFI_REL_OFFSET rax, RAX+\offset
+       CFI_REL_OFFSET r8, R8+\offset
+       CFI_REL_OFFSET r9, R9+\offset
+       CFI_REL_OFFSET r10, R10+\offset
+       CFI_REL_OFFSET r11, R11+\offset
        CFI_REL_OFFSET rbx, RBX+\offset
        CFI_REL_OFFSET rbp, RBP+\offset
        CFI_REL_OFFSET r12, R12+\offset
@@ -218,105 +167,30 @@ ENDPROC(native_usergs_sysret64)
        CFI_REL_OFFSET r15, R15+\offset
        .endm
 
-ENTRY(save_paranoid)
-       XCPT_FRAME 1 RDI+8
-       cld
-       movq %rdi, RDI+8(%rsp)
-       movq %rsi, RSI+8(%rsp)
-       movq_cfi rdx, RDX+8
-       movq_cfi rcx, RCX+8
-       movq_cfi rax, RAX+8
-       movq %r8, R8+8(%rsp)
-       movq %r9, R9+8(%rsp)
-       movq %r10, R10+8(%rsp)
-       movq %r11, R11+8(%rsp)
-       movq_cfi rbx, RBX+8
-       movq %rbp, RBP+8(%rsp)
-       movq %r12, R12+8(%rsp)
-       movq %r13, R13+8(%rsp)
-       movq %r14, R14+8(%rsp)
-       movq %r15, R15+8(%rsp)
-       movl $1,%ebx
-       movl $MSR_GS_BASE,%ecx
-       rdmsr
-       testl %edx,%edx
-       js 1f   /* negative -> in kernel */
-       SWAPGS
-       xorl %ebx,%ebx
-1:     ret
-       CFI_ENDPROC
-END(save_paranoid)
-
 /*
- * A newly forked process directly context switches into this address.
+ * 64bit SYSCALL instruction entry. Up to 6 arguments in registers.
  *
- * rdi: prev task we switched from
- */
-ENTRY(ret_from_fork)
-       DEFAULT_FRAME
-
-       LOCK ; btr $TIF_FORK,TI_flags(%r8)
-
-       pushq_cfi $0x0002
-       popfq_cfi                               # reset kernel eflags
-
-       call schedule_tail                      # rdi: 'prev' task parameter
-
-       GET_THREAD_INFO(%rcx)
-
-       RESTORE_REST
-
-       testl $3, CS-ARGOFFSET(%rsp)            # from kernel_thread?
-       jz   1f
-
-       /*
-        * By the time we get here, we have no idea whether our pt_regs,
-        * ti flags, and ti status came from the 64-bit SYSCALL fast path,
-        * the slow path, or one of the ia32entry paths.
-        * Use int_ret_from_sys_call to return, since it can safely handle
-        * all of the above.
-        */
-       jmp  int_ret_from_sys_call
-
-1:
-       subq $REST_SKIP, %rsp   # leave space for volatiles
-       CFI_ADJUST_CFA_OFFSET   REST_SKIP
-       movq %rbp, %rdi
-       call *%rbx
-       movl $0, RAX(%rsp)
-       RESTORE_REST
-       jmp int_ret_from_sys_call
-       CFI_ENDPROC
-END(ret_from_fork)
-
-/*
- * System call entry. Up to 6 arguments in registers are supported.
+ * 64bit SYSCALL saves rip to rcx, clears rflags.RF, then saves rflags to r11,
+ * then loads new ss, cs, and rip from previously programmed MSRs.
+ * rflags gets masked by a value from another MSR (so CLD and CLAC
+ * are not needed). SYSCALL does not save anything on the stack
+ * and does not change rsp.
  *
- * SYSCALL does not save anything on the stack and does not change the
- * stack pointer.  However, it does mask the flags register for us, so
- * CLD and CLAC are not needed.
- */
-
-/*
- * Register setup:
+ * Registers on entry:
  * rax  system call number
+ * rcx  return address
+ * r11  saved rflags (note: r11 is callee-clobbered register in C ABI)
  * rdi  arg0
- * rcx  return address for syscall/sysret, C arg3
  * rsi  arg1
  * rdx  arg2
- * r10  arg3   (--> moved to rcx for C)
+ * r10  arg3 (needs to be moved to rcx to conform to C ABI)
  * r8   arg4
  * r9   arg5
- * r11  eflags for syscall/sysret, temporary for C
- * r12-r15,rbp,rbx saved by C code, not touched.
+ * (note: r12-r15,rbp,rbx are callee-preserved in C ABI)
  *
- * Interrupts are off on entry.
  * Only called from user space.
  *
- * XXX if we had a free scratch register we could save the RSP into the stack frame
- *      and report it properly in ps. Unfortunately we haven't.
- *
- * When user can change the frames always force IRET. That is because
+ * When user can change pt_regs->foo always force IRET. That is because
  * it deals with uncanonical addresses better. SYSRET has trouble
  * with them due to bugs in both AMD and Intel CPUs.
  */
@@ -324,9 +198,15 @@ END(ret_from_fork)
 ENTRY(system_call)
        CFI_STARTPROC   simple
        CFI_SIGNAL_FRAME
-       CFI_DEF_CFA     rsp,KERNEL_STACK_OFFSET
+       CFI_DEF_CFA     rsp,0
        CFI_REGISTER    rip,rcx
        /*CFI_REGISTER  rflags,r11*/
+
+       /*
+        * Interrupts are off on entry.
+        * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,
+        * it is too small to ever cause noticeable irq latency.
+        */
        SWAPGS_UNSAFE_STACK
        /*
         * A hypervisor implementation might want to use a label
@@ -335,18 +215,38 @@ ENTRY(system_call)
         */
 GLOBAL(system_call_after_swapgs)
 
-       movq    %rsp,PER_CPU_VAR(old_rsp)
+       movq    %rsp,PER_CPU_VAR(rsp_scratch)
        movq    PER_CPU_VAR(kernel_stack),%rsp
+
+       /* Construct struct pt_regs on stack */
+       pushq_cfi $__USER_DS                    /* pt_regs->ss */
+       pushq_cfi PER_CPU_VAR(rsp_scratch)      /* pt_regs->sp */
        /*
-        * No need to follow this irqs off/on section - it's straight
-        * and short:
+        * Re-enable interrupts.
+        * We use 'rsp_scratch' as a scratch space, hence irq-off block above
+        * must execute atomically in the face of possible interrupt-driven
+        * task preemption. We must enable interrupts only after we're done
+        * with using rsp_scratch:
         */
        ENABLE_INTERRUPTS(CLBR_NONE)
-       SAVE_ARGS 8, 0, rax_enosys=1
-       movq_cfi rax,(ORIG_RAX-ARGOFFSET)
-       movq  %rcx,RIP-ARGOFFSET(%rsp)
-       CFI_REL_OFFSET rip,RIP-ARGOFFSET
-       testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+       pushq_cfi       %r11                    /* pt_regs->flags */
+       pushq_cfi       $__USER_CS              /* pt_regs->cs */
+       pushq_cfi       %rcx                    /* pt_regs->ip */
+       CFI_REL_OFFSET rip,0
+       pushq_cfi_reg   rax                     /* pt_regs->orig_ax */
+       pushq_cfi_reg   rdi                     /* pt_regs->di */
+       pushq_cfi_reg   rsi                     /* pt_regs->si */
+       pushq_cfi_reg   rdx                     /* pt_regs->dx */
+       pushq_cfi_reg   rcx                     /* pt_regs->cx */
+       pushq_cfi       $-ENOSYS                /* pt_regs->ax */
+       pushq_cfi_reg   r8                      /* pt_regs->r8 */
+       pushq_cfi_reg   r9                      /* pt_regs->r9 */
+       pushq_cfi_reg   r10                     /* pt_regs->r10 */
+       pushq_cfi_reg   r11                     /* pt_regs->r11 */
+       sub     $(6*8),%rsp /* pt_regs->bp,bx,r12-15 not saved */
+       CFI_ADJUST_CFA_OFFSET 6*8
+
+       testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        jnz tracesys
 system_call_fastpath:
 #if __SYSCALL_MASK == ~0
@@ -355,18 +255,21 @@ system_call_fastpath:
        andl $__SYSCALL_MASK,%eax
        cmpl $__NR_syscall_max,%eax
 #endif
-       ja ret_from_sys_call  /* and return regs->ax */
+       ja      1f      /* return -ENOSYS (already in pt_regs->ax) */
        movq %r10,%rcx
-       call *sys_call_table(,%rax,8)  # XXX:    rip relative
-       movq %rax,RAX-ARGOFFSET(%rsp)
+       call *sys_call_table(,%rax,8)
+       movq %rax,RAX(%rsp)
+1:
 /*
- * Syscall return path ending with SYSRET (fast path)
- * Has incomplete stack frame and undefined top of stack.
+ * Syscall return path ending with SYSRET (fast path).
+ * Has incompletely filled pt_regs.
  */
-ret_from_sys_call:
        LOCKDEP_SYS_EXIT
+       /*
+        * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,
+        * it is too small to ever cause noticeable irq latency.
+        */
        DISABLE_INTERRUPTS(CLBR_NONE)
-       TRACE_IRQS_OFF
 
        /*
         * We must check ti flags with interrupts (or at least preemption)
@@ -376,72 +279,73 @@ ret_from_sys_call:
         * flags (TIF_NOTIFY_RESUME, TIF_USER_RETURN_NOTIFY, etc) set is
         * very bad.
         */
-       testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
-       jnz int_ret_from_sys_call_fixup /* Go the the slow path */
+       testl $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
+       jnz int_ret_from_sys_call_irqs_off      /* Go to the slow path */
 
        CFI_REMEMBER_STATE
-       /*
-        * sysretq will re-enable interrupts:
-        */
-       TRACE_IRQS_ON
-       movq RIP-ARGOFFSET(%rsp),%rcx
+
+       RESTORE_C_REGS_EXCEPT_RCX_R11
+       movq    RIP(%rsp),%rcx
        CFI_REGISTER    rip,rcx
-       RESTORE_ARGS 1,-ARG_SKIP,0
+       movq    EFLAGS(%rsp),%r11
        /*CFI_REGISTER  rflags,r11*/
-       movq    PER_CPU_VAR(old_rsp), %rsp
+       movq    RSP(%rsp),%rsp
+       /*
+        * 64bit SYSRET restores rip from rcx,
+        * rflags from r11 (but RF and VM bits are forced to 0),
+        * cs and ss are loaded from MSRs.
+        * Restoration of rflags re-enables interrupts.
+        */
        USERGS_SYSRET64
 
        CFI_RESTORE_STATE
 
-int_ret_from_sys_call_fixup:
-       FIXUP_TOP_OF_STACK %r11, -ARGOFFSET
-       jmp int_ret_from_sys_call_irqs_off
-
-       /* Do syscall tracing */
+       /* Do syscall entry tracing */
 tracesys:
-       leaq -REST_SKIP(%rsp), %rdi
-       movq $AUDIT_ARCH_X86_64, %rsi
+       movq %rsp, %rdi
+       movl $AUDIT_ARCH_X86_64, %esi
        call syscall_trace_enter_phase1
        test %rax, %rax
        jnz tracesys_phase2             /* if needed, run the slow path */
-       LOAD_ARGS 0                     /* else restore clobbered regs */
+       RESTORE_C_REGS_EXCEPT_RAX       /* else restore clobbered regs */
+       movq ORIG_RAX(%rsp), %rax
        jmp system_call_fastpath        /*      and return to the fast path */
 
 tracesys_phase2:
-       SAVE_REST
-       FIXUP_TOP_OF_STACK %rdi
+       SAVE_EXTRA_REGS
        movq %rsp, %rdi
-       movq $AUDIT_ARCH_X86_64, %rsi
+       movl $AUDIT_ARCH_X86_64, %esi
        movq %rax,%rdx
        call syscall_trace_enter_phase2
 
        /*
-        * Reload arg registers from stack in case ptrace changed them.
+        * Reload registers from stack in case ptrace changed them.
         * We don't reload %rax because syscall_trace_entry_phase2() returned
         * the value it wants us to use in the table lookup.
         */
-       LOAD_ARGS ARGOFFSET, 1
-       RESTORE_REST
+       RESTORE_C_REGS_EXCEPT_RAX
+       RESTORE_EXTRA_REGS
 #if __SYSCALL_MASK == ~0
        cmpq $__NR_syscall_max,%rax
 #else
        andl $__SYSCALL_MASK,%eax
        cmpl $__NR_syscall_max,%eax
 #endif
-       ja   int_ret_from_sys_call      /* RAX(%rsp) is already set */
+       ja      1f      /* return -ENOSYS (already in pt_regs->ax) */
        movq %r10,%rcx  /* fixup for C */
        call *sys_call_table(,%rax,8)
-       movq %rax,RAX-ARGOFFSET(%rsp)
-       /* Use IRET because user could have changed frame */
+       movq %rax,RAX(%rsp)
+1:
+       /* Use IRET because user could have changed pt_regs->foo */
 
 /*
  * Syscall return path ending with IRET.
- * Has correct top of stack, but partial stack frame.
+ * Has correct iret frame.
  */
 GLOBAL(int_ret_from_sys_call)
        DISABLE_INTERRUPTS(CLBR_NONE)
+int_ret_from_sys_call_irqs_off: /* jumps come here from the irqs-off SYSRET path */
        TRACE_IRQS_OFF
-int_ret_from_sys_call_irqs_off:
        movl $_TIF_ALLWORK_MASK,%edi
        /* edi: mask to check */
 GLOBAL(int_with_check)
@@ -450,8 +354,8 @@ GLOBAL(int_with_check)
        movl TI_flags(%rcx),%edx
        andl %edi,%edx
        jnz   int_careful
-       andl    $~TS_COMPAT,TI_status(%rcx)
-       jmp   retint_swapgs
+       andl    $~TS_COMPAT,TI_status(%rcx)
+       jmp     syscall_return
 
        /* Either reschedule or signal or syscall exit tracking needed. */
        /* First do a reschedule test. */
@@ -468,12 +372,11 @@ int_careful:
        TRACE_IRQS_OFF
        jmp int_with_check
 
-       /* handle signals and tracing -- both require a full stack frame */
+       /* handle signals and tracing -- both require a full pt_regs */
 int_very_careful:
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_NONE)
-int_check_syscall_exit_work:
-       SAVE_REST
+       SAVE_EXTRA_REGS
        /* Check for syscall exit trace */
        testl $_TIF_WORK_SYSCALL_EXIT,%edx
        jz int_signal
@@ -492,86 +395,192 @@ int_signal:
        call do_notify_resume
 1:     movl $_TIF_WORK_MASK,%edi
 int_restore_rest:
-       RESTORE_REST
+       RESTORE_EXTRA_REGS
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
        jmp int_with_check
+
+syscall_return:
+       /* The IRETQ could re-enable interrupts: */
+       DISABLE_INTERRUPTS(CLBR_ANY)
+       TRACE_IRQS_IRETQ
+
+       /*
+        * Try to use SYSRET instead of IRET if we're returning to
+        * a completely clean 64-bit userspace context.
+        */
+       movq RCX(%rsp),%rcx
+       cmpq %rcx,RIP(%rsp)             /* RCX == RIP */
+       jne opportunistic_sysret_failed
+
+       /*
+        * On Intel CPUs, SYSRET with non-canonical RCX/RIP will #GP
+        * in kernel space.  This essentially lets the user take over
+        * the kernel, since userspace controls RSP.  It's not worth
+        * testing for canonicalness exactly -- this check detects any
+        * of the 17 high bits set, which is true for non-canonical
+        * or kernel addresses.  (This will pessimize vsyscall=native.
+        * Big deal.)
+        *
+        * If virtual addresses ever become wider, this will need
+        * to be updated to remain correct on both old and new CPUs.
+        */
+       .ifne __VIRTUAL_MASK_SHIFT - 47
+       .error "virtual address width changed -- SYSRET checks need update"
+       .endif
+       shr $__VIRTUAL_MASK_SHIFT, %rcx
+       jnz opportunistic_sysret_failed
+
+       cmpq $__USER_CS,CS(%rsp)        /* CS must match SYSRET */
+       jne opportunistic_sysret_failed
+
+       movq R11(%rsp),%r11
+       cmpq %r11,EFLAGS(%rsp)          /* R11 == RFLAGS */
+       jne opportunistic_sysret_failed
+
+       /*
+        * SYSRET can't restore RF.  SYSRET can restore TF, but unlike IRET,
+        * restoring TF results in a trap from userspace immediately after
+        * SYSRET.  This would cause an infinite loop whenever #DB happens
+        * with register state that satisfies the opportunistic SYSRET
+        * conditions.  For example, single-stepping this user code:
+        *
+        *           movq $stuck_here,%rcx
+        *           pushfq
+        *           popq %r11
+        *   stuck_here:
+        *
+        * would never get past 'stuck_here'.
+        */
+       testq $(X86_EFLAGS_RF|X86_EFLAGS_TF), %r11
+       jnz opportunistic_sysret_failed
+
+       /* nothing to check for RSP */
+
+       cmpq $__USER_DS,SS(%rsp)        /* SS must match SYSRET */
+       jne opportunistic_sysret_failed
+
+       /*
+        * We win!  This label is here just for ease of understanding
+        * perf profiles.  Nothing jumps here.
+        */
+syscall_return_via_sysret:
+       CFI_REMEMBER_STATE
+       /* r11 is already restored (see code above) */
+       RESTORE_C_REGS_EXCEPT_R11
+       movq RSP(%rsp),%rsp
+       USERGS_SYSRET64
+       CFI_RESTORE_STATE
+
+opportunistic_sysret_failed:
+       SWAPGS
+       jmp     restore_c_regs_and_iret
        CFI_ENDPROC
 END(system_call)
 
+
        .macro FORK_LIKE func
 ENTRY(stub_\func)
        CFI_STARTPROC
-       popq    %r11                    /* save return address */
-       PARTIAL_FRAME 0
-       SAVE_REST
-       pushq   %r11                    /* put it back on stack */
-       FIXUP_TOP_OF_STACK %r11, 8
-       DEFAULT_FRAME 0 8               /* offset 8: return address */
-       call sys_\func
-       RESTORE_TOP_OF_STACK %r11, 8
-       ret $REST_SKIP          /* pop extended registers */
+       DEFAULT_FRAME 0, 8              /* offset 8: return address */
+       SAVE_EXTRA_REGS 8
+       jmp sys_\func
        CFI_ENDPROC
 END(stub_\func)
        .endm
 
-       .macro FIXED_FRAME label,func
-ENTRY(\label)
-       CFI_STARTPROC
-       PARTIAL_FRAME 0 8               /* offset 8: return address */
-       FIXUP_TOP_OF_STACK %r11, 8-ARGOFFSET
-       call \func
-       RESTORE_TOP_OF_STACK %r11, 8-ARGOFFSET
-       ret
-       CFI_ENDPROC
-END(\label)
-       .endm
-
        FORK_LIKE  clone
        FORK_LIKE  fork
        FORK_LIKE  vfork
-       FIXED_FRAME stub_iopl, sys_iopl
 
 ENTRY(stub_execve)
        CFI_STARTPROC
-       addq $8, %rsp
-       PARTIAL_FRAME 0
-       SAVE_REST
-       FIXUP_TOP_OF_STACK %r11
-       call sys_execve
-       movq %rax,RAX(%rsp)
-       RESTORE_REST
-       jmp int_ret_from_sys_call
+       DEFAULT_FRAME 0, 8
+       call    sys_execve
+return_from_execve:
+       testl   %eax, %eax
+       jz      1f
+       /* exec failed, can use fast SYSRET code path in this case */
+       ret
+1:
+       /* must use IRET code path (pt_regs->cs may have changed) */
+       addq    $8, %rsp
+       CFI_ADJUST_CFA_OFFSET -8
+       ZERO_EXTRA_REGS
+       movq    %rax,RAX(%rsp)
+       jmp     int_ret_from_sys_call
        CFI_ENDPROC
 END(stub_execve)
-
-ENTRY(stub_execveat)
+/*
+ * Remaining execve stubs are only 7 bytes long.
+ * ENTRY() often aligns to 16 bytes, which in this case has no benefits.
+ */
+       .align  8
+GLOBAL(stub_execveat)
        CFI_STARTPROC
-       addq $8, %rsp
-       PARTIAL_FRAME 0
-       SAVE_REST
-       FIXUP_TOP_OF_STACK %r11
-       call sys_execveat
-       RESTORE_TOP_OF_STACK %r11
-       movq %rax,RAX(%rsp)
-       RESTORE_REST
-       jmp int_ret_from_sys_call
+       DEFAULT_FRAME 0, 8
+       call    sys_execveat
+       jmp     return_from_execve
        CFI_ENDPROC
 END(stub_execveat)
 
+#ifdef CONFIG_X86_X32_ABI
+       .align  8
+GLOBAL(stub_x32_execve)
+       CFI_STARTPROC
+       DEFAULT_FRAME 0, 8
+       call    compat_sys_execve
+       jmp     return_from_execve
+       CFI_ENDPROC
+END(stub_x32_execve)
+       .align  8
+GLOBAL(stub_x32_execveat)
+       CFI_STARTPROC
+       DEFAULT_FRAME 0, 8
+       call    compat_sys_execveat
+       jmp     return_from_execve
+       CFI_ENDPROC
+END(stub_x32_execveat)
+#endif
+
+#ifdef CONFIG_IA32_EMULATION
+       .align  8
+GLOBAL(stub32_execve)
+       CFI_STARTPROC
+       call    compat_sys_execve
+       jmp     return_from_execve
+       CFI_ENDPROC
+END(stub32_execve)
+       .align  8
+GLOBAL(stub32_execveat)
+       CFI_STARTPROC
+       call    compat_sys_execveat
+       jmp     return_from_execve
+       CFI_ENDPROC
+END(stub32_execveat)
+#endif
+
 /*
  * sigreturn is special because it needs to restore all registers on return.
  * This cannot be done with SYSRET, so use the IRET return path instead.
  */
 ENTRY(stub_rt_sigreturn)
        CFI_STARTPROC
-       addq $8, %rsp
-       PARTIAL_FRAME 0
-       SAVE_REST
-       FIXUP_TOP_OF_STACK %r11
+       DEFAULT_FRAME 0, 8
+       /*
+        * SAVE_EXTRA_REGS result is not normally needed:
+        * sigreturn overwrites all pt_regs->GPREGS.
+        * But sigreturn can fail (!), and there is no easy way to detect that.
+        * To make sure RESTORE_EXTRA_REGS doesn't restore garbage on error,
+        * we SAVE_EXTRA_REGS here.
+        */
+       SAVE_EXTRA_REGS 8
        call sys_rt_sigreturn
-       movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
-       RESTORE_REST
+return_from_stub:
+       addq    $8, %rsp
+       CFI_ADJUST_CFA_OFFSET -8
+       RESTORE_EXTRA_REGS
+       movq %rax,RAX(%rsp)
        jmp int_ret_from_sys_call
        CFI_ENDPROC
 END(stub_rt_sigreturn)
@@ -579,86 +588,70 @@ END(stub_rt_sigreturn)
 #ifdef CONFIG_X86_X32_ABI
 ENTRY(stub_x32_rt_sigreturn)
        CFI_STARTPROC
-       addq $8, %rsp
-       PARTIAL_FRAME 0
-       SAVE_REST
-       FIXUP_TOP_OF_STACK %r11
+       DEFAULT_FRAME 0, 8
+       SAVE_EXTRA_REGS 8
        call sys32_x32_rt_sigreturn
-       movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
-       RESTORE_REST
-       jmp int_ret_from_sys_call
+       jmp  return_from_stub
        CFI_ENDPROC
 END(stub_x32_rt_sigreturn)
+#endif
 
-ENTRY(stub_x32_execve)
-       CFI_STARTPROC
-       addq $8, %rsp
-       PARTIAL_FRAME 0
-       SAVE_REST
-       FIXUP_TOP_OF_STACK %r11
-       call compat_sys_execve
-       RESTORE_TOP_OF_STACK %r11
-       movq %rax,RAX(%rsp)
-       RESTORE_REST
-       jmp int_ret_from_sys_call
-       CFI_ENDPROC
-END(stub_x32_execve)
+/*
+ * A newly forked process directly context switches into this address.
+ *
+ * rdi: prev task we switched from
+ */
+ENTRY(ret_from_fork)
+       DEFAULT_FRAME
 
-ENTRY(stub_x32_execveat)
-       CFI_STARTPROC
-       addq $8, %rsp
-       PARTIAL_FRAME 0
-       SAVE_REST
-       FIXUP_TOP_OF_STACK %r11
-       call compat_sys_execveat
-       RESTORE_TOP_OF_STACK %r11
-       movq %rax,RAX(%rsp)
-       RESTORE_REST
+       LOCK ; btr $TIF_FORK,TI_flags(%r8)
+
+       pushq_cfi $0x0002
+       popfq_cfi                               # reset kernel eflags
+
+       call schedule_tail                      # rdi: 'prev' task parameter
+
+       RESTORE_EXTRA_REGS
+
+       testl $3,CS(%rsp)                       # from kernel_thread?
+
+       /*
+        * By the time we get here, we have no idea whether our pt_regs,
+        * ti flags, and ti status came from the 64-bit SYSCALL fast path,
+        * the slow path, or one of the ia32entry paths.
+        * Use IRET code path to return, since it can safely handle
+        * all of the above.
+        */
+       jnz     int_ret_from_sys_call
+
+       /* We came from kernel_thread */
+       /* nb: we depend on RESTORE_EXTRA_REGS above */
+       movq %rbp, %rdi
+       call *%rbx
+       movl $0, RAX(%rsp)
+       RESTORE_EXTRA_REGS
        jmp int_ret_from_sys_call
        CFI_ENDPROC
-END(stub_x32_execveat)
-
-#endif
+END(ret_from_fork)
 
 /*
- * Build the entry stubs and pointer table with some assembler magic.
- * We pack 7 stubs into a single 32-byte chunk, which will fit in a
- * single cache line on all modern x86 implementations.
+ * Build the entry stubs with some assembler magic.
+ * We pack 1 stub into every 8-byte block.
  */
-       .section .init.rodata,"a"
-ENTRY(interrupt)
-       .section .entry.text
-       .p2align 5
-       .p2align CONFIG_X86_L1_CACHE_SHIFT
+       .align 8
 ENTRY(irq_entries_start)
        INTR_FRAME
-vector=FIRST_EXTERNAL_VECTOR
-.rept (FIRST_SYSTEM_VECTOR-FIRST_EXTERNAL_VECTOR+6)/7
-       .balign 32
-  .rept        7
-    .if vector < FIRST_SYSTEM_VECTOR
-      .if vector <> FIRST_EXTERNAL_VECTOR
+    vector=FIRST_EXTERNAL_VECTOR
+    .rept (FIRST_SYSTEM_VECTOR - FIRST_EXTERNAL_VECTOR)
+       pushq_cfi $(~vector+0x80)       /* Note: always in signed byte range */
+    vector=vector+1
+       jmp     common_interrupt
        CFI_ADJUST_CFA_OFFSET -8
-      .endif
-1:     pushq_cfi $(~vector+0x80)       /* Note: always in signed byte range */
-      .if ((vector-FIRST_EXTERNAL_VECTOR)%7) <> 6
-       jmp 2f
-      .endif
-      .previous
-       .quad 1b
-      .section .entry.text
-vector=vector+1
-    .endif
-  .endr
-2:     jmp common_interrupt
-.endr
+       .align  8
+    .endr
        CFI_ENDPROC
 END(irq_entries_start)
 
-.previous
-END(interrupt)
-.previous
-
 /*
  * Interrupt entry/exit.
  *
@@ -669,47 +662,45 @@ END(interrupt)
 
 /* 0(%rsp): ~(interrupt number) */
        .macro interrupt func
-       /* reserve pt_regs for scratch regs and rbp */
-       subq $ORIG_RAX-RBP, %rsp
-       CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP
        cld
-       /* start from rbp in pt_regs and jump over */
-       movq_cfi rdi, (RDI-RBP)
-       movq_cfi rsi, (RSI-RBP)
-       movq_cfi rdx, (RDX-RBP)
-       movq_cfi rcx, (RCX-RBP)
-       movq_cfi rax, (RAX-RBP)
-       movq_cfi  r8,  (R8-RBP)
-       movq_cfi  r9,  (R9-RBP)
-       movq_cfi r10, (R10-RBP)
-       movq_cfi r11, (R11-RBP)
-
-       /* Save rbp so that we can unwind from get_irq_regs() */
-       movq_cfi rbp, 0
-
-       /* Save previous stack value */
-       movq %rsp, %rsi
+       /*
+        * Since nothing in interrupt handling code touches r12...r15 members
+        * of "struct pt_regs", and since interrupts can nest, we can save
+        * four stack slots and simultaneously provide
+        * an unwind-friendly stack layout by saving "truncated" pt_regs
+        * exactly up to rbp slot, without these members.
+        */
+       ALLOC_PT_GPREGS_ON_STACK -RBP
+       SAVE_C_REGS -RBP
+       /* this goes to 0(%rsp) for unwinder, not for saving the value: */
+       SAVE_EXTRA_REGS_RBP -RBP
 
-       leaq -RBP(%rsp),%rdi    /* arg1 for handler */
-       testl $3, CS-RBP(%rsi)
+       leaq -RBP(%rsp),%rdi    /* arg1 for \func (pointer to pt_regs) */
+
+       testl $3, CS-RBP(%rsp)
        je 1f
        SWAPGS
+1:
        /*
+        * Save previous stack pointer, optionally switch to interrupt stack.
         * irq_count is used to check if a CPU is already on an interrupt stack
         * or not. While this is essentially redundant with preempt_count it is
         * a little cheaper to use a separate counter in the PDA (short of
         * moving irq_enter into assembly, which would be too much work)
         */
-1:     incl PER_CPU_VAR(irq_count)
+       movq %rsp, %rsi
+       incl PER_CPU_VAR(irq_count)
        cmovzq PER_CPU_VAR(irq_stack_ptr),%rsp
        CFI_DEF_CFA_REGISTER    rsi
-
-       /* Store previous stack value */
        pushq %rsi
+       /*
+        * For debugger:
+        * "CFA (Current Frame Address) is the value on stack + offset"
+        */
        CFI_ESCAPE      0x0f /* DW_CFA_def_cfa_expression */, 6, \
-                       0x77 /* DW_OP_breg7 */, 0, \
+                       0x77 /* DW_OP_breg7 (rsp) */, 0, \
                        0x06 /* DW_OP_deref */, \
-                       0x08 /* DW_OP_const1u */, SS+8-RBP, \
+                       0x08 /* DW_OP_const1u */, SIZEOF_PTREGS-RBP, \
                        0x22 /* DW_OP_plus */
        /* We entered an interrupt context - irqs are off: */
        TRACE_IRQS_OFF
@@ -727,7 +718,7 @@ common_interrupt:
        ASM_CLAC
        addq $-0x80,(%rsp)              /* Adjust vector to [-256,-1] range */
        interrupt do_IRQ
-       /* 0(%rsp): old_rsp-ARGOFFSET */
+       /* 0(%rsp): old RSP */
 ret_from_intr:
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
@@ -735,19 +726,18 @@ ret_from_intr:
 
        /* Restore saved previous stack */
        popq %rsi
-       CFI_DEF_CFA rsi,SS+8-RBP        /* reg/off reset after def_cfa_expr */
-       leaq ARGOFFSET-RBP(%rsi), %rsp
+       CFI_DEF_CFA rsi,SIZEOF_PTREGS-RBP /* reg/off reset after def_cfa_expr */
+       /* return code expects complete pt_regs - adjust rsp accordingly: */
+       leaq -RBP(%rsi),%rsp
        CFI_DEF_CFA_REGISTER    rsp
-       CFI_ADJUST_CFA_OFFSET   RBP-ARGOFFSET
+       CFI_ADJUST_CFA_OFFSET   RBP
 
-exit_intr:
-       GET_THREAD_INFO(%rcx)
-       testl $3,CS-ARGOFFSET(%rsp)
+       testl $3,CS(%rsp)
        je retint_kernel
-
        /* Interrupt came from user space */
+
+       GET_THREAD_INFO(%rcx)
        /*
-        * Has a correct top of stack, but a partial stack frame
         * %rcx: thread info. Interrupts off.
         */
 retint_with_reschedule:
@@ -766,84 +756,34 @@ retint_swapgs:            /* return to user-space */
        DISABLE_INTERRUPTS(CLBR_ANY)
        TRACE_IRQS_IRETQ
 
-       /*
-        * Try to use SYSRET instead of IRET if we're returning to
-        * a completely clean 64-bit userspace context.
-        */
-       movq (RCX-R11)(%rsp), %rcx
-       cmpq %rcx,(RIP-R11)(%rsp)               /* RCX == RIP */
-       jne opportunistic_sysret_failed
-
-       /*
-        * On Intel CPUs, sysret with non-canonical RCX/RIP will #GP
-        * in kernel space.  This essentially lets the user take over
-        * the kernel, since userspace controls RSP.  It's not worth
-        * testing for canonicalness exactly -- this check detects any
-        * of the 17 high bits set, which is true for non-canonical
-        * or kernel addresses.  (This will pessimize vsyscall=native.
-        * Big deal.)
-        *
-        * If virtual addresses ever become wider, this will need
-        * to be updated to remain correct on both old and new CPUs.
-        */
-       .ifne __VIRTUAL_MASK_SHIFT - 47
-       .error "virtual address width changed -- sysret checks need update"
-       .endif
-       shr $__VIRTUAL_MASK_SHIFT, %rcx
-       jnz opportunistic_sysret_failed
-
-       cmpq $__USER_CS,(CS-R11)(%rsp)          /* CS must match SYSRET */
-       jne opportunistic_sysret_failed
-
-       movq (R11-ARGOFFSET)(%rsp), %r11
-       cmpq %r11,(EFLAGS-ARGOFFSET)(%rsp)      /* R11 == RFLAGS */
-       jne opportunistic_sysret_failed
-
-       /*
-        * SYSRET can't restore RF.  SYSRET can restore TF, but unlike IRET,
-        * restoring TF results in a trap from userspace immediately after
-        * SYSRET.  This would cause an infinite loop whenever #DB happens
-        * with register state that satisfies the opportunistic SYSRET
-        * conditions.  For example, single-stepping this user code:
-        *
-        *           movq $stuck_here,%rcx
-        *           pushfq
-        *           popq %r11
-        *   stuck_here:
-        *
-        * would never get past 'stuck_here'.
-        */
-       testq $(X86_EFLAGS_RF|X86_EFLAGS_TF), %r11
-       jnz opportunistic_sysret_failed
-
-       /* nothing to check for RSP */
-
-       cmpq $__USER_DS,(SS-ARGOFFSET)(%rsp)    /* SS must match SYSRET */
-       jne opportunistic_sysret_failed
-
-       /*
-        * We win!  This label is here just for ease of understanding
-        * perf profiles.  Nothing jumps here.
-        */
-irq_return_via_sysret:
-       CFI_REMEMBER_STATE
-       RESTORE_ARGS 1,8,1
-       movq (RSP-RIP)(%rsp),%rsp
-       USERGS_SYSRET64
-       CFI_RESTORE_STATE
-
-opportunistic_sysret_failed:
        SWAPGS
-       jmp restore_args
+       jmp     restore_c_regs_and_iret
 
-retint_restore_args:   /* return to kernel space */
-       DISABLE_INTERRUPTS(CLBR_ANY)
+/* Returning to kernel space */
+retint_kernel:
+#ifdef CONFIG_PREEMPT
+       /* Interrupts are off */
+       /* Check if we need preemption */
+       bt      $9,EFLAGS(%rsp) /* interrupts were off? */
+       jnc     1f
+0:     cmpl    $0,PER_CPU_VAR(__preempt_count)
+       jnz     1f
+       call    preempt_schedule_irq
+       jmp     0b
+1:
+#endif
        /*
         * The iretq could re-enable interrupts:
         */
        TRACE_IRQS_IRETQ
-restore_args:
-       RESTORE_ARGS 1,8,1
+
+/*
+ * At this label, code paths which return to kernel and to user,
+ * which come from interrupts/exception and from syscalls, merge.
+ */
+restore_c_regs_and_iret:
+       RESTORE_C_REGS
+       REMOVE_PT_GPREGS_FROM_STACK 8
 
 irq_return:
        INTERRUPT_RETURN
@@ -914,28 +854,17 @@ retint_signal:
        jz    retint_swapgs
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_NONE)
-       SAVE_REST
+       SAVE_EXTRA_REGS
        movq $-1,ORIG_RAX(%rsp)
        xorl %esi,%esi          # oldset
        movq %rsp,%rdi          # &pt_regs
        call do_notify_resume
-       RESTORE_REST
+       RESTORE_EXTRA_REGS
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
        GET_THREAD_INFO(%rcx)
        jmp retint_with_reschedule
 
-#ifdef CONFIG_PREEMPT
-       /* Returning to kernel space. Check if we need preemption */
-       /* rcx:  threadinfo. interrupts off. */
-ENTRY(retint_kernel)
-       cmpl $0,PER_CPU_VAR(__preempt_count)
-       jnz  retint_restore_args
-       bt   $9,EFLAGS-ARGOFFSET(%rsp)  /* interrupts off? */
-       jnc  retint_restore_args
-       call preempt_schedule_irq
-       jmp exit_intr
-#endif
        CFI_ENDPROC
 END(common_interrupt)
 
@@ -1024,7 +953,7 @@ apicinterrupt IRQ_WORK_VECTOR \
 /*
  * Exception entry points.
  */
-#define INIT_TSS_IST(x) PER_CPU_VAR(init_tss) + (TSS_ist + ((x) - 1) * 8)
+#define CPU_TSS_IST(x) PER_CPU_VAR(cpu_tss) + (TSS_ist + ((x) - 1) * 8)
 
 .macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1
 ENTRY(\sym)
@@ -1046,8 +975,7 @@ ENTRY(\sym)
        pushq_cfi $-1                   /* ORIG_RAX: no syscall to restart */
        .endif
 
-       subq $ORIG_RAX-R15, %rsp
-       CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
+       ALLOC_PT_GPREGS_ON_STACK
 
        .if \paranoid
        .if \paranoid == 1
@@ -1055,10 +983,11 @@ ENTRY(\sym)
        testl $3, CS(%rsp)              /* If coming from userspace, switch */
        jnz 1f                          /* stacks. */
        .endif
-       call save_paranoid
+       call paranoid_entry
        .else
        call error_entry
        .endif
+       /* returned flag: ebx=0: need swapgs on exit, ebx=1: don't need it */
 
        DEFAULT_FRAME 0
 
@@ -1080,19 +1009,20 @@ ENTRY(\sym)
        .endif
 
        .if \shift_ist != -1
-       subq $EXCEPTION_STKSZ, INIT_TSS_IST(\shift_ist)
+       subq $EXCEPTION_STKSZ, CPU_TSS_IST(\shift_ist)
        .endif
 
        call \do_sym
 
        .if \shift_ist != -1
-       addq $EXCEPTION_STKSZ, INIT_TSS_IST(\shift_ist)
+       addq $EXCEPTION_STKSZ, CPU_TSS_IST(\shift_ist)
        .endif
 
+       /* these procedures expect "no swapgs" flag in ebx */
        .if \paranoid
-       jmp paranoid_exit               /* %ebx: no swapgs flag */
+       jmp paranoid_exit
        .else
-       jmp error_exit                  /* %ebx: no swapgs flag */
+       jmp error_exit
        .endif
 
        .if \paranoid == 1
@@ -1296,7 +1226,9 @@ ENTRY(xen_failsafe_callback)
        addq $0x30,%rsp
        CFI_ADJUST_CFA_OFFSET -0x30
        pushq_cfi $-1 /* orig_ax = -1 => not a system call */
-       SAVE_ALL
+       ALLOC_PT_GPREGS_ON_STACK
+       SAVE_C_REGS
+       SAVE_EXTRA_REGS
        jmp error_exit
        CFI_ENDPROC
 END(xen_failsafe_callback)
@@ -1328,59 +1260,66 @@ idtentry async_page_fault do_async_page_fault has_error_code=1
 idtentry machine_check has_error_code=0 paranoid=1 do_sym=*machine_check_vector(%rip)
 #endif
 
-       /*
-        * "Paranoid" exit path from exception stack.  This is invoked
-        * only on return from non-NMI IST interrupts that came
-        * from kernel space.
-        *
-        * We may be returning to very strange contexts (e.g. very early
-        * in syscall entry), so checking for preemption here would
-        * be complicated.  Fortunately, we there's no good reason
-        * to try to handle preemption here.
-        */
+/*
+ * Save all registers in pt_regs, and switch gs if needed.
+ * Use slow, but surefire "are we in kernel?" check.
+ * Return: ebx=0: need swapgs on exit, ebx=1: otherwise
+ */
+ENTRY(paranoid_entry)
+       XCPT_FRAME 1 15*8
+       cld
+       SAVE_C_REGS 8
+       SAVE_EXTRA_REGS 8
+       movl $1,%ebx
+       movl $MSR_GS_BASE,%ecx
+       rdmsr
+       testl %edx,%edx
+       js 1f   /* negative -> in kernel */
+       SWAPGS
+       xorl %ebx,%ebx
+1:     ret
+       CFI_ENDPROC
+END(paranoid_entry)
 
-       /* ebx: no swapgs flag */
+/*
+ * "Paranoid" exit path from exception stack.  This is invoked
+ * only on return from non-NMI IST interrupts that came
+ * from kernel space.
+ *
+ * We may be returning to very strange contexts (e.g. very early
+ * in syscall entry), so checking for preemption here would
+ * be complicated.  Fortunately, we there's no good reason
+ * to try to handle preemption here.
+ */
+/* On entry, ebx is "no swapgs" flag (1: don't need swapgs, 0: need it) */
 ENTRY(paranoid_exit)
        DEFAULT_FRAME
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF_DEBUG
        testl %ebx,%ebx                         /* swapgs needed? */
-       jnz paranoid_restore
-       TRACE_IRQS_IRETQ 0
+       jnz paranoid_exit_no_swapgs
+       TRACE_IRQS_IRETQ
        SWAPGS_UNSAFE_STACK
-       RESTORE_ALL 8
-       INTERRUPT_RETURN
-paranoid_restore:
-       TRACE_IRQS_IRETQ_DEBUG 0
-       RESTORE_ALL 8
+       jmp paranoid_exit_restore
+paranoid_exit_no_swapgs:
+       TRACE_IRQS_IRETQ_DEBUG
+paranoid_exit_restore:
+       RESTORE_EXTRA_REGS
+       RESTORE_C_REGS
+       REMOVE_PT_GPREGS_FROM_STACK 8
        INTERRUPT_RETURN
        CFI_ENDPROC
 END(paranoid_exit)
 
 /*
- * Exception entry point. This expects an error code/orig_rax on the stack.
- * returns in "no swapgs flag" in %ebx.
+ * Save all registers in pt_regs, and switch gs if needed.
+ * Return: ebx=0: need swapgs on exit, ebx=1: otherwise
  */
 ENTRY(error_entry)
-       XCPT_FRAME
-       CFI_ADJUST_CFA_OFFSET 15*8
-       /* oldrax contains error code */
+       XCPT_FRAME 1 15*8
        cld
-       movq %rdi, RDI+8(%rsp)
-       movq %rsi, RSI+8(%rsp)
-       movq %rdx, RDX+8(%rsp)
-       movq %rcx, RCX+8(%rsp)
-       movq %rax, RAX+8(%rsp)
-       movq  %r8,  R8+8(%rsp)
-       movq  %r9,  R9+8(%rsp)
-       movq %r10, R10+8(%rsp)
-       movq %r11, R11+8(%rsp)
-       movq_cfi rbx, RBX+8
-       movq %rbp, RBP+8(%rsp)
-       movq %r12, R12+8(%rsp)
-       movq %r13, R13+8(%rsp)
-       movq %r14, R14+8(%rsp)
-       movq %r15, R15+8(%rsp)
+       SAVE_C_REGS 8
+       SAVE_EXTRA_REGS 8
        xorl %ebx,%ebx
        testl $3,CS+8(%rsp)
        je error_kernelspace
@@ -1390,12 +1329,12 @@ error_sti:
        TRACE_IRQS_OFF
        ret
 
-/*
- * There are two places in the kernel that can potentially fault with
- * usergs. Handle them here.  B stepping K8s sometimes report a
- * truncated RIP for IRET exceptions returning to compat mode. Check
- * for these here too.
- */
+       /*
       * There are two places in the kernel that can potentially fault with
       * usergs. Handle them here.  B stepping K8s sometimes report a
       * truncated RIP for IRET exceptions returning to compat mode. Check
       * for these here too.
       */
 error_kernelspace:
        CFI_REL_OFFSET rcx, RCX+8
        incl %ebx
@@ -1425,11 +1364,11 @@ error_bad_iret:
 END(error_entry)
 
 
-/* ebx:        no swapgs flag (1: don't need swapgs, 0: need it) */
+/* On entry, ebx is "no swapgs" flag (1: don't need swapgs, 0: need it) */
 ENTRY(error_exit)
        DEFAULT_FRAME
        movl %ebx,%eax
-       RESTORE_REST
+       RESTORE_EXTRA_REGS
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
        GET_THREAD_INFO(%rcx)
@@ -1444,19 +1383,7 @@ ENTRY(error_exit)
        CFI_ENDPROC
 END(error_exit)
 
-/*
- * Test if a given stack is an NMI stack or not.
- */
-       .macro test_in_nmi reg stack nmi_ret normal_ret
-       cmpq %\reg, \stack
-       ja \normal_ret
-       subq $EXCEPTION_STKSZ, %\reg
-       cmpq %\reg, \stack
-       jb \normal_ret
-       jmp \nmi_ret
-       .endm
-
-       /* runs on exception stack */
+/* Runs on exception stack */
 ENTRY(nmi)
        INTR_FRAME
        PARAVIRT_ADJUST_EXCEPTION_FRAME
@@ -1492,7 +1419,7 @@ ENTRY(nmi)
         * NMI.
         */
 
-       /* Use %rdx as out temp variable throughout */
+       /* Use %rdx as our temp variable throughout */
        pushq_cfi %rdx
        CFI_REL_OFFSET rdx, 0
 
@@ -1517,8 +1444,17 @@ ENTRY(nmi)
         * We check the variable because the first NMI could be in a
         * breakpoint routine using a breakpoint stack.
         */
-       lea 6*8(%rsp), %rdx
-       test_in_nmi rdx, 4*8(%rsp), nested_nmi, first_nmi
+       lea     6*8(%rsp), %rdx
+       /* Compare the NMI stack (rdx) with the stack we came from (4*8(%rsp)) */
+       cmpq    %rdx, 4*8(%rsp)
+       /* If the stack pointer is above the NMI stack, this is a normal NMI */
+       ja      first_nmi
+       subq    $EXCEPTION_STKSZ, %rdx
+       cmpq    %rdx, 4*8(%rsp)
+       /* If it is below the NMI stack, it is a normal NMI */
+       jb      first_nmi
+       /* Ah, it is within the NMI stack, treat it as nested */
+
        CFI_REMEMBER_STATE
 
 nested_nmi:
@@ -1611,7 +1547,7 @@ first_nmi:
        .rept 5
        pushq_cfi 11*8(%rsp)
        .endr
-       CFI_DEF_CFA_OFFSET SS+8-RIP
+       CFI_DEF_CFA_OFFSET 5*8
 
        /* Everything up to here is safe from nested NMIs */
 
@@ -1639,7 +1575,7 @@ repeat_nmi:
        pushq_cfi -6*8(%rsp)
        .endr
        subq $(5*8), %rsp
-       CFI_DEF_CFA_OFFSET SS+8-RIP
+       CFI_DEF_CFA_OFFSET 5*8
 end_repeat_nmi:
 
        /*
@@ -1648,16 +1584,16 @@ end_repeat_nmi:
         * so that we repeat another NMI.
         */
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
-       subq $ORIG_RAX-R15, %rsp
-       CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
+       ALLOC_PT_GPREGS_ON_STACK
+
        /*
-        * Use save_paranoid to handle SWAPGS, but no need to use paranoid_exit
+        * Use paranoid_entry to handle SWAPGS, but no need to use paranoid_exit
         * as we should not be calling schedule in NMI context.
         * Even with normal interrupts enabled. An NMI should not be
         * setting NEED_RESCHED or anything that normal interrupts and
         * exceptions might do.
         */
-       call save_paranoid
+       call paranoid_entry
        DEFAULT_FRAME 0
 
        /*
@@ -1688,8 +1624,10 @@ end_repeat_nmi:
 nmi_swapgs:
        SWAPGS_UNSAFE_STACK
 nmi_restore:
+       RESTORE_EXTRA_REGS
+       RESTORE_C_REGS
        /* Pop the extra iret frame at once */
-       RESTORE_ALL 6*8
+       REMOVE_PT_GPREGS_FROM_STACK 6*8
 
        /* Clear the NMI executing stack variable */
        movq $0, 5*8(%rsp)
index c4f8d4659070db99ce190543186bc4a4ac5d2ac9..2b55ee6db053c79fbe91a6119e613075be54111b 100644 (file)
@@ -177,9 +177,6 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
         */
        load_ucode_bsp();
 
-       if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
-               early_printk("Kernel alive\n");
-
        clear_page(init_level4_pgt);
        /* set init_level4_pgt kernel high mapping*/
        init_level4_pgt[511] = early_level4_pgt[511];
index f36bd42d6f0c8b5fc5cd75dcf133b35a1f6bfe3b..d031bad9e07eadf3a80bc69a449cd13a44ed8080 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/cpufeature.h>
 #include <asm/percpu.h>
 #include <asm/nops.h>
+#include <asm/bootparam.h>
 
 /* Physical address */
 #define pa(X) ((X) - __PAGE_OFFSET)
@@ -90,7 +91,7 @@ ENTRY(startup_32)
        
        /* test KEEP_SEGMENTS flag to see if the bootloader is asking
                us to not reload segments */
-       testb $(1<<6), BP_loadflags(%esi)
+       testb $KEEP_SEGMENTS, BP_loadflags(%esi)
        jnz 2f
 
 /*
index 6fd514d9f69a267a7813ca2b04657991429932d5..ae6588b301c248b3c281a1e072802e6764e9ac44 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/x86_64/kernel/head.S -- start in 32bit and switch to 64bit
+ *  linux/arch/x86/kernel/head_64.S -- start in 32bit and switch to 64bit
  *
  *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
  *  Copyright (C) 2000 Pavel Machek <pavel@suse.cz>
@@ -56,7 +56,7 @@ startup_64:
         * %rsi holds a physical pointer to real_mode_data.
         *
         * We come here either directly from a 64bit bootloader, or from
-        * arch/x86_64/boot/compressed/head.S.
+        * arch/x86/boot/compressed/head_64.S.
         *
         * We only come here initially at boot nothing else comes here.
         *
@@ -146,7 +146,7 @@ startup_64:
        leaq    level2_kernel_pgt(%rip), %rdi
        leaq    4096(%rdi), %r8
        /* See if it is a valid page table entry */
-1:     testq   $1, 0(%rdi)
+1:     testb   $1, 0(%rdi)
        jz      2f
        addq    %rbp, 0(%rdi)
        /* Go to the next page */
index d5651fce0b71af6c15226483b6a06398ccbeb8a0..367f39d35e9cb98300fa368d3689d2ce143e71a6 100644 (file)
@@ -42,8 +42,8 @@ void kernel_fpu_enable(void)
  * be set (so that the clts/stts pair does nothing that is
  * visible in the interrupted kernel thread).
  *
- * Except for the eagerfpu case when we return 1 unless we've already
- * been eager and saved the state in kernel_fpu_begin().
+ * Except for the eagerfpu case when we return true; in the likely case
+ * the thread has FPU but we are not going to set/clear TS.
  */
 static inline bool interrupted_kernel_fpu_idle(void)
 {
@@ -51,7 +51,7 @@ static inline bool interrupted_kernel_fpu_idle(void)
                return false;
 
        if (use_eager_fpu())
-               return __thread_has_fpu(current);
+               return true;
 
        return !__thread_has_fpu(current) &&
                (read_cr0() & X86_CR0_TS);
@@ -68,7 +68,7 @@ static inline bool interrupted_kernel_fpu_idle(void)
 static inline bool interrupted_user_mode(void)
 {
        struct pt_regs *regs = get_irq_regs();
-       return regs && user_mode_vm(regs);
+       return regs && user_mode(regs);
 }
 
 /*
@@ -94,9 +94,10 @@ void __kernel_fpu_begin(void)
 
        if (__thread_has_fpu(me)) {
                __save_init_fpu(me);
-       } else if (!use_eager_fpu()) {
+       } else {
                this_cpu_write(fpu_owner_task, NULL);
-               clts();
+               if (!use_eager_fpu())
+                       clts();
        }
 }
 EXPORT_SYMBOL(__kernel_fpu_begin);
@@ -107,7 +108,7 @@ void __kernel_fpu_end(void)
 
        if (__thread_has_fpu(me)) {
                if (WARN_ON(restore_fpu_checking(me)))
-                       drop_init_fpu(me);
+                       fpu_reset_state(me);
        } else if (!use_eager_fpu()) {
                stts();
        }
@@ -120,10 +121,13 @@ void unlazy_fpu(struct task_struct *tsk)
 {
        preempt_disable();
        if (__thread_has_fpu(tsk)) {
-               __save_init_fpu(tsk);
-               __thread_fpu_end(tsk);
-       } else
-               tsk->thread.fpu_counter = 0;
+               if (use_eager_fpu()) {
+                       __save_fpu(tsk);
+               } else {
+                       __save_init_fpu(tsk);
+                       __thread_fpu_end(tsk);
+               }
+       }
        preempt_enable();
 }
 EXPORT_SYMBOL(unlazy_fpu);
@@ -221,11 +225,12 @@ void fpu_finit(struct fpu *fpu)
                return;
        }
 
+       memset(fpu->state, 0, xstate_size);
+
        if (cpu_has_fxsr) {
                fx_finit(&fpu->state->fxsave);
        } else {
                struct i387_fsave_struct *fp = &fpu->state->fsave;
-               memset(fp, 0, xstate_size);
                fp->cwd = 0xffff037fu;
                fp->swd = 0xffff0000u;
                fp->twd = 0xffffffffu;
@@ -247,7 +252,7 @@ int init_fpu(struct task_struct *tsk)
        if (tsk_used_math(tsk)) {
                if (cpu_has_fpu && tsk == current)
                        unlazy_fpu(tsk);
-               tsk->thread.fpu.last_cpu = ~0;
+               task_disable_lazy_fpu_restore(tsk);
                return 0;
        }
 
@@ -336,6 +341,7 @@ int xstateregs_get(struct task_struct *target, const struct user_regset *regset,
                unsigned int pos, unsigned int count,
                void *kbuf, void __user *ubuf)
 {
+       struct xsave_struct *xsave = &target->thread.fpu.state->xsave;
        int ret;
 
        if (!cpu_has_xsave)
@@ -350,14 +356,12 @@ int xstateregs_get(struct task_struct *target, const struct user_regset *regset,
         * memory layout in the thread struct, so that we can copy the entire
         * xstateregs to the user using one user_regset_copyout().
         */
-       memcpy(&target->thread.fpu.state->fxsave.sw_reserved,
-              xstate_fx_sw_bytes, sizeof(xstate_fx_sw_bytes));
-
+       memcpy(&xsave->i387.sw_reserved,
+               xstate_fx_sw_bytes, sizeof(xstate_fx_sw_bytes));
        /*
         * Copy the xstate memory layout.
         */
-       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-                                 &target->thread.fpu.state->xsave, 0, -1);
+       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, xsave, 0, -1);
        return ret;
 }
 
@@ -365,8 +369,8 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
                  unsigned int pos, unsigned int count,
                  const void *kbuf, const void __user *ubuf)
 {
+       struct xsave_struct *xsave = &target->thread.fpu.state->xsave;
        int ret;
-       struct xsave_hdr_struct *xsave_hdr;
 
        if (!cpu_has_xsave)
                return -ENODEV;
@@ -375,22 +379,16 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
        if (ret)
                return ret;
 
-       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-                                &target->thread.fpu.state->xsave, 0, -1);
-
+       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, xsave, 0, -1);
        /*
         * mxcsr reserved bits must be masked to zero for security reasons.
         */
-       target->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask;
-
-       xsave_hdr = &target->thread.fpu.state->xsave.xsave_hdr;
-
-       xsave_hdr->xstate_bv &= pcntxt_mask;
+       xsave->i387.mxcsr &= mxcsr_feature_mask;
+       xsave->xsave_hdr.xstate_bv &= pcntxt_mask;
        /*
         * These bits must be zero.
         */
-       memset(xsave_hdr->reserved, 0, 48);
-
+       memset(&xsave->xsave_hdr.reserved, 0, 48);
        return ret;
 }
 
index 4ddaf66ea35f696eac6afce6bb43f01d2d84f1aa..37dae792dbbed00b480aa67a33cb0b2ae1699428 100644 (file)
@@ -54,7 +54,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
         * because the ->io_bitmap_max value must match the bitmap
         * contents:
         */
-       tss = &per_cpu(init_tss, get_cpu());
+       tss = &per_cpu(cpu_tss, get_cpu());
 
        if (turn_on)
                bitmap_clear(t->io_bitmap_ptr, from, num);
index 67b1cbe0093adba1141f8d9ebda29ad34dc9d23e..e5952c22553241e2ceea5d5fd6f1f7b758cc960e 100644 (file)
@@ -295,7 +295,7 @@ int check_irq_vectors_for_cpu_disable(void)
 
        this_cpu = smp_processor_id();
        cpumask_copy(&online_new, cpu_online_mask);
-       cpu_clear(this_cpu, online_new);
+       cpumask_clear_cpu(this_cpu, &online_new);
 
        this_count = 0;
        for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
@@ -307,7 +307,7 @@ int check_irq_vectors_for_cpu_disable(void)
 
                        data = irq_desc_get_irq_data(desc);
                        cpumask_copy(&affinity_new, data->affinity);
-                       cpu_clear(this_cpu, affinity_new);
+                       cpumask_clear_cpu(this_cpu, &affinity_new);
 
                        /* Do not count inactive or per-cpu irqs. */
                        if (!irq_has_action(irq) || irqd_is_per_cpu(data))
index 28d28f5eb8f49c2a9b8f84997e1dd0dc8841ece0..f9fd86a7fcc7d1bc8c2cc920fc5b5037f5859336 100644 (file)
@@ -165,7 +165,7 @@ bool handle_irq(unsigned irq, struct pt_regs *regs)
        if (unlikely(!desc))
                return false;
 
-       if (user_mode_vm(regs) || !execute_on_irq_stack(overflow, desc, irq)) {
+       if (user_mode(regs) || !execute_on_irq_stack(overflow, desc, irq)) {
                if (unlikely(overflow))
                        print_stack_overflow();
                desc->handle_irq(irq, desc);
index e4b503d5558c5d435eddc3c3c5be8c55f1de558d..394e643d7830fc01d4da516bd79cab1dc0aa6962 100644 (file)
@@ -44,7 +44,7 @@ static inline void stack_overflow_check(struct pt_regs *regs)
        u64 estack_top, estack_bottom;
        u64 curbase = (u64)task_stack_page(current);
 
-       if (user_mode_vm(regs))
+       if (user_mode(regs))
                return;
 
        if (regs->sp >= curbase + sizeof(struct thread_info) +
index 70e181ea1eac1f2da444482e6714e61b52d5a19e..cd10a64372647c3579ba6717db49c6cd63c6353a 100644 (file)
@@ -178,7 +178,8 @@ void __init native_init_IRQ(void)
 #endif
        for_each_clear_bit_from(i, used_vectors, first_system_vector) {
                /* IA32_SYSCALL_VECTOR could be used in trap_init already. */
-               set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]);
+               set_intr_gate(i, irq_entries_start +
+                               8 * (i - FIRST_EXTERNAL_VECTOR));
        }
 #ifdef CONFIG_X86_LOCAL_APIC
        for_each_clear_bit_from(i, used_vectors, NR_VECTORS)
index 25ecd56cefa8f22496153cf29b763c266bd8d91e..d6178d9791db7966e8bc188e3df16c03233c3da3 100644 (file)
@@ -126,11 +126,11 @@ char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
 #ifdef CONFIG_X86_32
        switch (regno) {
        case GDB_SS:
-               if (!user_mode_vm(regs))
+               if (!user_mode(regs))
                        *(unsigned long *)mem = __KERNEL_DS;
                break;
        case GDB_SP:
-               if (!user_mode_vm(regs))
+               if (!user_mode(regs))
                        *(unsigned long *)mem = kernel_stack_pointer(regs);
                break;
        case GDB_GS:
index 4e3d5a9621fe0052fac43d5ad6c109b9d3f54447..1deffe6cc87367631fe23b4c5d4b6be697ff4b0e 100644 (file)
@@ -354,6 +354,7 @@ int __copy_instruction(u8 *dest, u8 *src)
 {
        struct insn insn;
        kprobe_opcode_t buf[MAX_INSN_SIZE];
+       int length;
        unsigned long recovered_insn =
                recover_probed_instruction(buf, (unsigned long)src);
 
@@ -361,16 +362,18 @@ int __copy_instruction(u8 *dest, u8 *src)
                return 0;
        kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE);
        insn_get_length(&insn);
+       length = insn.length;
+
        /* Another subsystem puts a breakpoint, failed to recover */
        if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
                return 0;
-       memcpy(dest, insn.kaddr, insn.length);
+       memcpy(dest, insn.kaddr, length);
 
 #ifdef CONFIG_X86_64
        if (insn_rip_relative(&insn)) {
                s64 newdisp;
                u8 *disp;
-               kernel_insn_init(&insn, dest, insn.length);
+               kernel_insn_init(&insn, dest, length);
                insn_get_displacement(&insn);
                /*
                 * The copied instruction uses the %rip-relative addressing
@@ -394,7 +397,7 @@ int __copy_instruction(u8 *dest, u8 *src)
                *(s32 *) disp = (s32) newdisp;
        }
 #endif
-       return insn.length;
+       return length;
 }
 
 static int arch_copy_kprobe(struct kprobe *p)
@@ -602,7 +605,7 @@ int kprobe_int3_handler(struct pt_regs *regs)
        struct kprobe *p;
        struct kprobe_ctlblk *kcb;
 
-       if (user_mode_vm(regs))
+       if (user_mode(regs))
                return 0;
 
        addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t));
@@ -1007,7 +1010,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
        struct die_args *args = data;
        int ret = NOTIFY_DONE;
 
-       if (args->regs && user_mode_vm(args->regs))
+       if (args->regs && user_mode(args->regs))
                return ret;
 
        if (val == DIE_GPF) {
index e354cc6446aba4286645dc799e48d8539c7005d6..9435620062df30e549d1510baaf9c4c72ab90290 100644 (file)
@@ -513,7 +513,7 @@ void __init kvm_guest_init(void)
         * can get false positives too easily, for example if the host is
         * overcommitted.
         */
-       watchdog_enable_hardlockup_detector(false);
+       hardlockup_detector_disable();
 }
 
 static noinline uint32_t __kvm_cpuid_base(void)
index d1ac80b72c72184a0b999c2b299b5e265d26de7a..005c03e93fc54c7907e8e9e2bc1d771902b1c3ca 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/setup.h>
 
 #if 0
 #define DEBUGP(fmt, ...)                               \
@@ -47,21 +48,13 @@ do {                                                        \
 
 #ifdef CONFIG_RANDOMIZE_BASE
 static unsigned long module_load_offset;
-static int randomize_modules = 1;
 
 /* Mutex protects the module_load_offset. */
 static DEFINE_MUTEX(module_kaslr_mutex);
 
-static int __init parse_nokaslr(char *p)
-{
-       randomize_modules = 0;
-       return 0;
-}
-early_param("nokaslr", parse_nokaslr);
-
 static unsigned long int get_module_load_offset(void)
 {
-       if (randomize_modules) {
+       if (kaslr_enabled()) {
                mutex_lock(&module_kaslr_mutex);
                /*
                 * Calculate the module_load_offset the first time this
index 548d25f00c90ad010379b0b36884cabee82b6e02..c614dd492f5f720058346a33883f5a67d4689b94 100644 (file)
@@ -443,7 +443,7 @@ struct pv_mmu_ops pv_mmu_ops = {
        .ptep_modify_prot_start = __ptep_modify_prot_start,
        .ptep_modify_prot_commit = __ptep_modify_prot_commit,
 
-#if PAGETABLE_LEVELS >= 3
+#if CONFIG_PGTABLE_LEVELS >= 3
 #ifdef CONFIG_X86_PAE
        .set_pte_atomic = native_set_pte_atomic,
        .pte_clear = native_pte_clear,
@@ -454,13 +454,13 @@ struct pv_mmu_ops pv_mmu_ops = {
        .pmd_val = PTE_IDENT,
        .make_pmd = PTE_IDENT,
 
-#if PAGETABLE_LEVELS == 4
+#if CONFIG_PGTABLE_LEVELS == 4
        .pud_val = PTE_IDENT,
        .make_pud = PTE_IDENT,
 
        .set_pgd = native_set_pgd,
 #endif
-#endif /* PAGETABLE_LEVELS >= 3 */
+#endif /* CONFIG_PGTABLE_LEVELS >= 3 */
 
        .pte_val = PTE_IDENT,
        .pgd_val = PTE_IDENT,
index 781861cc5ee8d7b9bbd27e9b13c380da59bb06c0..da8cb987b97312f6b37b5a967ce70fc5e75e0205 100644 (file)
@@ -131,10 +131,11 @@ void perf_get_regs_user(struct perf_regs *regs_user,
        }
 
        /*
-        * RIP, flags, and the argument registers are usually saved.
-        * orig_ax is probably okay, too.
+        * These registers are always saved on 64-bit syscall entry.
+        * On 32-bit entry points, they are saved too except r8..r11.
         */
        regs_user_copy->ip = user_regs->ip;
+       regs_user_copy->ax = user_regs->ax;
        regs_user_copy->cx = user_regs->cx;
        regs_user_copy->dx = user_regs->dx;
        regs_user_copy->si = user_regs->si;
@@ -145,9 +146,12 @@ void perf_get_regs_user(struct perf_regs *regs_user,
        regs_user_copy->r11 = user_regs->r11;
        regs_user_copy->orig_ax = user_regs->orig_ax;
        regs_user_copy->flags = user_regs->flags;
+       regs_user_copy->sp = user_regs->sp;
+       regs_user_copy->cs = user_regs->cs;
+       regs_user_copy->ss = user_regs->ss;
 
        /*
-        * Don't even try to report the "rest" regs.
+        * Most system calls don't save these registers, don't report them.
         */
        regs_user_copy->bx = -1;
        regs_user_copy->bp = -1;
@@ -158,37 +162,13 @@ void perf_get_regs_user(struct perf_regs *regs_user,
 
        /*
         * For this to be at all useful, we need a reasonable guess for
-        * sp and the ABI.  Be careful: we're in NMI context, and we're
+        * the ABI.  Be careful: we're in NMI context, and we're
         * considering current to be the current task, so we should
         * be careful not to look at any other percpu variables that might
         * change during context switches.
         */
-       if (IS_ENABLED(CONFIG_IA32_EMULATION) &&
-           task_thread_info(current)->status & TS_COMPAT) {
-               /* Easy case: we're in a compat syscall. */
-               regs_user->abi = PERF_SAMPLE_REGS_ABI_32;
-               regs_user_copy->sp = user_regs->sp;
-               regs_user_copy->cs = user_regs->cs;
-               regs_user_copy->ss = user_regs->ss;
-       } else if (user_regs->orig_ax != -1) {
-               /*
-                * We're probably in a 64-bit syscall.
-                * Warning: this code is severely racy.  At least it's better
-                * than just blindly copying user_regs.
-                */
-               regs_user->abi = PERF_SAMPLE_REGS_ABI_64;
-               regs_user_copy->sp = this_cpu_read(old_rsp);
-               regs_user_copy->cs = __USER_CS;
-               regs_user_copy->ss = __USER_DS;
-               regs_user_copy->cx = -1;  /* usually contains garbage */
-       } else {
-               /* We're probably in an interrupt or exception. */
-               regs_user->abi = user_64bit_mode(user_regs) ?
-                       PERF_SAMPLE_REGS_ABI_64 : PERF_SAMPLE_REGS_ABI_32;
-               regs_user_copy->sp = user_regs->sp;
-               regs_user_copy->cs = user_regs->cs;
-               regs_user_copy->ss = user_regs->ss;
-       }
+       regs_user->abi = user_64bit_mode(user_regs) ?
+               PERF_SAMPLE_REGS_ABI_64 : PERF_SAMPLE_REGS_ABI_32;
 
        regs_user->regs = regs_user_copy;
 }
index 046e2d620bbe7be507808e0f7188c45249f2d69c..8213da62b1b79c1c37798b598494add6802881d7 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/pm.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/random.h>
 #include <linux/user-return-notifier.h>
 #include <linux/dmi.h>
@@ -24,6 +24,7 @@
 #include <asm/syscalls.h>
 #include <asm/idle.h>
 #include <asm/uaccess.h>
+#include <asm/mwait.h>
 #include <asm/i387.h>
 #include <asm/fpu-internal.h>
 #include <asm/debugreg.h>
  * section. Since TSS's are completely CPU-local, we want them
  * on exact cacheline boundaries, to eliminate cacheline ping-pong.
  */
-__visible DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS;
+__visible DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, cpu_tss) = {
+       .x86_tss = {
+               .sp0 = TOP_OF_INIT_STACK,
+#ifdef CONFIG_X86_32
+               .ss0 = __KERNEL_DS,
+               .ss1 = __KERNEL_CS,
+               .io_bitmap_base = INVALID_IO_BITMAP_OFFSET,
+#endif
+        },
+#ifdef CONFIG_X86_32
+        /*
+         * Note that the .io_bitmap member must be extra-big. This is because
+         * the CPU will access an additional byte beyond the end of the IO
+         * permission bitmap. The extra byte must be all 1 bits, and must
+         * be within the limit.
+         */
+       .io_bitmap              = { [0 ... IO_BITMAP_LONGS] = ~0 },
+#endif
+};
+EXPORT_PER_CPU_SYMBOL_GPL(cpu_tss);
 
 #ifdef CONFIG_X86_64
 static DEFINE_PER_CPU(unsigned char, is_idle);
@@ -69,8 +89,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 
        dst->thread.fpu_counter = 0;
        dst->thread.fpu.has_fpu = 0;
-       dst->thread.fpu.last_cpu = ~0;
        dst->thread.fpu.state = NULL;
+       task_disable_lazy_fpu_restore(dst);
        if (tsk_used_math(src)) {
                int err = fpu_alloc(&dst->thread.fpu);
                if (err)
@@ -109,7 +129,7 @@ void exit_thread(void)
        unsigned long *bp = t->io_bitmap_ptr;
 
        if (bp) {
-               struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
+               struct tss_struct *tss = &per_cpu(cpu_tss, get_cpu());
 
                t->io_bitmap_ptr = NULL;
                clear_thread_flag(TIF_IO_BITMAP);
@@ -131,13 +151,18 @@ void flush_thread(void)
 
        flush_ptrace_hw_breakpoint(tsk);
        memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
-       drop_init_fpu(tsk);
-       /*
-        * Free the FPU state for non xsave platforms. They get reallocated
-        * lazily at the first use.
-        */
-       if (!use_eager_fpu())
+
+       if (!use_eager_fpu()) {
+               /* FPU state will be reallocated lazily at the first use. */
+               drop_fpu(tsk);
                free_thread_xstate(tsk);
+       } else if (!used_math()) {
+               /* kthread execs. TODO: cleanup this horror. */
+               if (WARN_ON(init_fpu(tsk)))
+                       force_sig(SIGKILL, tsk);
+               user_fpu_begin();
+               restore_init_xstate();
+       }
 }
 
 static void hard_disable_TSC(void)
@@ -377,14 +402,11 @@ static void amd_e400_idle(void)
 
                if (!cpumask_test_cpu(cpu, amd_e400_c1e_mask)) {
                        cpumask_set_cpu(cpu, amd_e400_c1e_mask);
-                       /*
-                        * Force broadcast so ACPI can not interfere.
-                        */
-                       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
-                                          &cpu);
+                       /* Force broadcast so ACPI can not interfere. */
+                       tick_broadcast_force();
                        pr_info("Switch to broadcast mode on CPU%d\n", cpu);
                }
-               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+               tick_broadcast_enter();
 
                default_idle();
 
@@ -393,12 +415,59 @@ static void amd_e400_idle(void)
                 * called with interrupts disabled.
                 */
                local_irq_disable();
-               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+               tick_broadcast_exit();
                local_irq_enable();
        } else
                default_idle();
 }
 
+/*
+ * Intel Core2 and older machines prefer MWAIT over HALT for C1.
+ * We can't rely on cpuidle installing MWAIT, because it will not load
+ * on systems that support only C1 -- so the boot default must be MWAIT.
+ *
+ * Some AMD machines are the opposite, they depend on using HALT.
+ *
+ * So for default C1, which is used during boot until cpuidle loads,
+ * use MWAIT-C1 on Intel HW that has it, else use HALT.
+ */
+static int prefer_mwait_c1_over_halt(const struct cpuinfo_x86 *c)
+{
+       if (c->x86_vendor != X86_VENDOR_INTEL)
+               return 0;
+
+       if (!cpu_has(c, X86_FEATURE_MWAIT))
+               return 0;
+
+       return 1;
+}
+
+/*
+ * MONITOR/MWAIT with no hints, used for default default C1 state.
+ * This invokes MWAIT with interrutps enabled and no flags,
+ * which is backwards compatible with the original MWAIT implementation.
+ */
+
+static void mwait_idle(void)
+{
+       if (!current_set_polling_and_test()) {
+               if (this_cpu_has(X86_BUG_CLFLUSH_MONITOR)) {
+                       smp_mb(); /* quirk */
+                       clflush((void *)&current_thread_info()->flags);
+                       smp_mb(); /* quirk */
+               }
+
+               __monitor((void *)&current_thread_info()->flags, 0, 0);
+               if (!need_resched())
+                       __sti_mwait(0, 0);
+               else
+                       local_irq_enable();
+       } else {
+               local_irq_enable();
+       }
+       __current_clr_polling();
+}
+
 void select_idle_routine(const struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
@@ -412,6 +481,9 @@ void select_idle_routine(const struct cpuinfo_x86 *c)
                /* E400: APIC timer interrupt does not wake up CPU from C1e */
                pr_info("using AMD E400 aware idle routine\n");
                x86_idle = amd_e400_idle;
+       } else if (prefer_mwait_c1_over_halt(c)) {
+               pr_info("using mwait in idle threads\n");
+               x86_idle = mwait_idle;
        } else
                x86_idle = default_idle;
 }
index 603c4f99cb5a17f83e65c3066a5642a4bb9d0f42..8ed2106b06da63e0a8e0dcf561aad7a1fc112e40 100644 (file)
@@ -73,7 +73,7 @@ void __show_regs(struct pt_regs *regs, int all)
        unsigned long sp;
        unsigned short ss, gs;
 
-       if (user_mode_vm(regs)) {
+       if (user_mode(regs)) {
                sp = regs->sp;
                ss = regs->ss & 0xffff;
                gs = get_user_gs(regs);
@@ -206,11 +206,7 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
        regs->ip                = new_ip;
        regs->sp                = new_sp;
        regs->flags             = X86_EFLAGS_IF;
-       /*
-        * force it to the iret return path by making it look as if there was
-        * some work pending.
-        */
-       set_thread_flag(TIF_NOTIFY_RESUME);
+       force_iret();
 }
 EXPORT_SYMBOL_GPL(start_thread);
 
@@ -248,18 +244,13 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        struct thread_struct *prev = &prev_p->thread,
                                 *next = &next_p->thread;
        int cpu = smp_processor_id();
-       struct tss_struct *tss = &per_cpu(init_tss, cpu);
+       struct tss_struct *tss = &per_cpu(cpu_tss, cpu);
        fpu_switch_t fpu;
 
        /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
 
        fpu = switch_fpu_prepare(prev_p, next_p, cpu);
 
-       /*
-        * Reload esp0.
-        */
-       load_sp0(tss, next);
-
        /*
         * Save away %gs. No need to save %fs, as it was saved on the
         * stack on entry.  No need to save %es and %ds, as those are
@@ -310,9 +301,17 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
         */
        arch_end_context_switch(next_p);
 
+       /*
+        * Reload esp0, kernel_stack, and current_top_of_stack.  This changes
+        * current_thread_info().
+        */
+       load_sp0(tss, next);
        this_cpu_write(kernel_stack,
-                 (unsigned long)task_stack_page(next_p) +
-                 THREAD_SIZE - KERNEL_STACK_OFFSET);
+                      (unsigned long)task_stack_page(next_p) +
+                      THREAD_SIZE);
+       this_cpu_write(cpu_current_top_of_stack,
+                      (unsigned long)task_stack_page(next_p) +
+                      THREAD_SIZE);
 
        /*
         * Restore %gs if needed (which is common)
index 67fcc43577d279faa02941dd56dbf36f270a9832..4baaa972f52aaed15b3dddd94b4df4f653126d81 100644 (file)
@@ -52,7 +52,7 @@
 
 asmlinkage extern void ret_from_fork(void);
 
-__visible DEFINE_PER_CPU(unsigned long, old_rsp);
+__visible DEFINE_PER_CPU(unsigned long, rsp_scratch);
 
 /* Prints also some state that isn't saved in the pt_regs */
 void __show_regs(struct pt_regs *regs, int all)
@@ -161,7 +161,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
        p->thread.sp0 = (unsigned long)task_stack_page(p) + THREAD_SIZE;
        childregs = task_pt_regs(p);
        p->thread.sp = (unsigned long) childregs;
-       p->thread.usersp = me->thread.usersp;
        set_tsk_thread_flag(p, TIF_FORK);
        p->thread.io_bitmap_ptr = NULL;
 
@@ -207,7 +206,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
         */
        if (clone_flags & CLONE_SETTLS) {
 #ifdef CONFIG_IA32_EMULATION
-               if (test_thread_flag(TIF_IA32))
+               if (is_ia32_task())
                        err = do_set_thread_area(p, -1,
                                (struct user_desc __user *)childregs->si, 0);
                else
@@ -235,13 +234,12 @@ start_thread_common(struct pt_regs *regs, unsigned long new_ip,
        loadsegment(es, _ds);
        loadsegment(ds, _ds);
        load_gs_index(0);
-       current->thread.usersp  = new_sp;
        regs->ip                = new_ip;
        regs->sp                = new_sp;
-       this_cpu_write(old_rsp, new_sp);
        regs->cs                = _cs;
        regs->ss                = _ss;
        regs->flags             = X86_EFLAGS_IF;
+       force_iret();
 }
 
 void
@@ -277,15 +275,12 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        struct thread_struct *prev = &prev_p->thread;
        struct thread_struct *next = &next_p->thread;
        int cpu = smp_processor_id();
-       struct tss_struct *tss = &per_cpu(init_tss, cpu);
+       struct tss_struct *tss = &per_cpu(cpu_tss, cpu);
        unsigned fsindex, gsindex;
        fpu_switch_t fpu;
 
        fpu = switch_fpu_prepare(prev_p, next_p, cpu);
 
-       /* Reload esp0 and ss1. */
-       load_sp0(tss, next);
-
        /* We must save %fs and %gs before load_TLS() because
         * %fs and %gs may be cleared by load_TLS().
         *
@@ -401,8 +396,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        /*
         * Switch the PDA and FPU contexts.
         */
-       prev->usersp = this_cpu_read(old_rsp);
-       this_cpu_write(old_rsp, next->usersp);
        this_cpu_write(current_task, next_p);
 
        /*
@@ -413,9 +406,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        task_thread_info(prev_p)->saved_preempt_count = this_cpu_read(__preempt_count);
        this_cpu_write(__preempt_count, task_thread_info(next_p)->saved_preempt_count);
 
+       /* Reload esp0 and ss1.  This changes current_thread_info(). */
+       load_sp0(tss, next);
+
        this_cpu_write(kernel_stack,
-                 (unsigned long)task_stack_page(next_p) +
-                 THREAD_SIZE - KERNEL_STACK_OFFSET);
+               (unsigned long)task_stack_page(next_p) + THREAD_SIZE);
 
        /*
         * Now maybe reload the debug registers and handle I/O bitmaps
@@ -602,6 +597,5 @@ long sys_arch_prctl(int code, unsigned long addr)
 
 unsigned long KSTK_ESP(struct task_struct *task)
 {
-       return (test_tsk_thread_flag(task, TIF_IA32)) ?
-                       (task_pt_regs(task)->sp) : ((task)->thread.usersp);
+       return task_pt_regs(task)->sp;
 }
index e510618b2e91a7969bb8cf6c74a35f59e4bf1bea..a7bc794807195af79b6c15054b1941867d373198 100644 (file)
@@ -364,18 +364,12 @@ static int set_segment_reg(struct task_struct *task,
        case offsetof(struct user_regs_struct,cs):
                if (unlikely(value == 0))
                        return -EIO;
-#ifdef CONFIG_IA32_EMULATION
-               if (test_tsk_thread_flag(task, TIF_IA32))
-                       task_pt_regs(task)->cs = value;
-#endif
+               task_pt_regs(task)->cs = value;
                break;
        case offsetof(struct user_regs_struct,ss):
                if (unlikely(value == 0))
                        return -EIO;
-#ifdef CONFIG_IA32_EMULATION
-               if (test_tsk_thread_flag(task, TIF_IA32))
-                       task_pt_regs(task)->ss = value;
-#endif
+               task_pt_regs(task)->ss = value;
                break;
        }
 
@@ -1421,7 +1415,7 @@ static void fill_sigtrap_info(struct task_struct *tsk,
        memset(info, 0, sizeof(*info));
        info->si_signo = SIGTRAP;
        info->si_code = si_code;
-       info->si_addr = user_mode_vm(regs) ? (void __user *)regs->ip : NULL;
+       info->si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL;
 }
 
 void user_single_step_siginfo(struct task_struct *tsk,
index 2f355d229a587771680b28080d92fd06f345d7e7..e5ecd20e72dd56d82447c94c17e6e85ae29eba90 100644 (file)
@@ -141,7 +141,46 @@ void pvclock_read_wallclock(struct pvclock_wall_clock *wall_clock,
        set_normalized_timespec(ts, now.tv_sec, now.tv_nsec);
 }
 
+static struct pvclock_vsyscall_time_info *pvclock_vdso_info;
+
+static struct pvclock_vsyscall_time_info *
+pvclock_get_vsyscall_user_time_info(int cpu)
+{
+       if (!pvclock_vdso_info) {
+               BUG();
+               return NULL;
+       }
+
+       return &pvclock_vdso_info[cpu];
+}
+
+struct pvclock_vcpu_time_info *pvclock_get_vsyscall_time_info(int cpu)
+{
+       return &pvclock_get_vsyscall_user_time_info(cpu)->pvti;
+}
+
 #ifdef CONFIG_X86_64
+static int pvclock_task_migrate(struct notifier_block *nb, unsigned long l,
+                               void *v)
+{
+       struct task_migration_notifier *mn = v;
+       struct pvclock_vsyscall_time_info *pvti;
+
+       pvti = pvclock_get_vsyscall_user_time_info(mn->from_cpu);
+
+       /* this is NULL when pvclock vsyscall is not initialized */
+       if (unlikely(pvti == NULL))
+               return NOTIFY_DONE;
+
+       pvti->migrate_count++;
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block pvclock_migrate = {
+       .notifier_call = pvclock_task_migrate,
+};
+
 /*
  * Initialize the generic pvclock vsyscall state.  This will allocate
  * a/some page(s) for the per-vcpu pvclock information, set up a
@@ -155,12 +194,17 @@ int __init pvclock_init_vsyscall(struct pvclock_vsyscall_time_info *i,
 
        WARN_ON (size != PVCLOCK_VSYSCALL_NR_PAGES*PAGE_SIZE);
 
+       pvclock_vdso_info = i;
+
        for (idx = 0; idx <= (PVCLOCK_FIXMAP_END-PVCLOCK_FIXMAP_BEGIN); idx++) {
                __set_fixmap(PVCLOCK_FIXMAP_BEGIN + idx,
                             __pa(i) + (idx*PAGE_SIZE),
                             PAGE_KERNEL_VVAR);
        }
 
+
+       register_task_migration_notifier(&pvclock_migrate);
+
        return 0;
 }
 #endif
index e13f8e7c22a68c3d9590b8deb69e116d2f625f68..77630d57e7bf30ac7f281e15c440cd7b7bae37a9 100644 (file)
@@ -226,23 +226,23 @@ swap_pages:
        movl    (%ebx), %ecx
        addl    $4, %ebx
 1:
-       testl   $0x1,   %ecx  /* is it a destination page */
+       testb   $0x1, %cl     /* is it a destination page */
        jz      2f
        movl    %ecx,   %edi
        andl    $0xfffff000, %edi
        jmp     0b
 2:
-       testl   $0x2,   %ecx  /* is it an indirection page */
+       testb   $0x2, %cl    /* is it an indirection page */
        jz      2f
        movl    %ecx,   %ebx
        andl    $0xfffff000, %ebx
        jmp     0b
 2:
-       testl   $0x4,   %ecx /* is it the done indicator */
+       testb   $0x4, %cl    /* is it the done indicator */
        jz      2f
        jmp     3f
 2:
-       testl   $0x8,   %ecx /* is it the source indicator */
+       testb   $0x8, %cl    /* is it the source indicator */
        jz      0b           /* Ignore it otherwise */
        movl    %ecx,   %esi /* For every source page do a copy */
        andl    $0xfffff000, %esi
index 3fd2c693e4752d01e071de68ef57e2db8b47b605..98111b38ebfd6eb9949242c5aae7b18bbbdb4489 100644 (file)
@@ -123,7 +123,7 @@ identity_mapped:
         * Set cr4 to a known state:
         *  - physical address extension enabled
         */
-       movq    $X86_CR4_PAE, %rax
+       movl    $X86_CR4_PAE, %eax
        movq    %rax, %cr4
 
        jmp 1f
@@ -221,23 +221,23 @@ swap_pages:
        movq    (%rbx), %rcx
        addq    $8,     %rbx
 1:
-       testq   $0x1,   %rcx  /* is it a destination page? */
+       testb   $0x1,   %cl   /* is it a destination page? */
        jz      2f
        movq    %rcx,   %rdi
        andq    $0xfffffffffffff000, %rdi
        jmp     0b
 2:
-       testq   $0x2,   %rcx  /* is it an indirection page? */
+       testb   $0x2,   %cl   /* is it an indirection page? */
        jz      2f
        movq    %rcx,   %rbx
        andq    $0xfffffffffffff000, %rbx
        jmp     0b
 2:
-       testq   $0x4,   %rcx  /* is it the done indicator? */
+       testb   $0x4,   %cl   /* is it the done indicator? */
        jz      2f
        jmp     3f
 2:
-       testq   $0x8,   %rcx  /* is it the source indicator? */
+       testb   $0x8,   %cl   /* is it the source indicator? */
        jz      0b            /* Ignore it otherwise */
        movq    %rcx,   %rsi  /* For ever source page do a copy */
        andq    $0xfffffffffffff000, %rsi
@@ -246,17 +246,17 @@ swap_pages:
        movq    %rsi, %rax
 
        movq    %r10, %rdi
-       movq    $512,   %rcx
+       movl    $512, %ecx
        rep ; movsq
 
        movq    %rax, %rdi
        movq    %rdx, %rsi
-       movq    $512,   %rcx
+       movl    $512, %ecx
        rep ; movsq
 
        movq    %rdx, %rdi
        movq    %r10, %rsi
-       movq    $512,   %rcx
+       movl    $512, %ecx
        rep ; movsq
 
        lea     PAGE_SIZE(%rax), %rsi
index 0a2421cca01fad095bbb7caa8e7c779d910d751b..d74ac33290ae3eeef46b923c4556d644b72f0d5a 100644 (file)
@@ -354,7 +354,7 @@ static void __init relocate_initrd(void)
                mapaddr = ramdisk_image & PAGE_MASK;
                p = early_memremap(mapaddr, clen+slop);
                memcpy(q, p+slop, clen);
-               early_iounmap(p, clen+slop);
+               early_memunmap(p, clen+slop);
                q += clen;
                ramdisk_image += clen;
                ramdisk_size  -= clen;
@@ -438,7 +438,7 @@ static void __init parse_setup_data(void)
                data_len = data->len + sizeof(struct setup_data);
                data_type = data->type;
                pa_next = data->next;
-               early_iounmap(data, sizeof(*data));
+               early_memunmap(data, sizeof(*data));
 
                switch (data_type) {
                case SETUP_E820_EXT:
@@ -470,7 +470,7 @@ static void __init e820_reserve_setup_data(void)
                         E820_RAM, E820_RESERVED_KERN);
                found = 1;
                pa_data = data->next;
-               early_iounmap(data, sizeof(*data));
+               early_memunmap(data, sizeof(*data));
        }
        if (!found)
                return;
@@ -491,7 +491,7 @@ static void __init memblock_x86_reserve_range_setup_data(void)
                data = early_memremap(pa_data, sizeof(*data));
                memblock_reserve(pa_data, sizeof(*data) + data->len);
                pa_data = data->next;
-               early_iounmap(data, sizeof(*data));
+               early_memunmap(data, sizeof(*data));
        }
 }
 
@@ -832,10 +832,15 @@ static void __init trim_low_memory_range(void)
 static int
 dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
 {
-       pr_emerg("Kernel Offset: 0x%lx from 0x%lx "
-                "(relocation range: 0x%lx-0x%lx)\n",
-                (unsigned long)&_text - __START_KERNEL, __START_KERNEL,
-                __START_KERNEL_map, MODULES_VADDR-1);
+       if (kaslr_enabled()) {
+               pr_emerg("Kernel Offset: 0x%lx from 0x%lx (relocation range: 0x%lx-0x%lx)\n",
+                        (unsigned long)&_text - __START_KERNEL,
+                        __START_KERNEL,
+                        __START_KERNEL_map,
+                        MODULES_VADDR-1);
+       } else {
+               pr_emerg("Kernel Offset: disabled\n");
+       }
 
        return 0;
 }
index e5042463c1bca59107e107117984c37753d732c3..3e581865c8e2a048bbc307a9d3fc4e04ad14b4d7 100644 (file)
@@ -61,8 +61,7 @@
        regs->seg = GET_SEG(seg) | 3;                   \
 } while (0)
 
-int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
-                      unsigned long *pax)
+int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
 {
        void __user *buf;
        unsigned int tmpflags;
@@ -81,7 +80,7 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
 #endif /* CONFIG_X86_32 */
 
                COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
-               COPY(dx); COPY(cx); COPY(ip);
+               COPY(dx); COPY(cx); COPY(ip); COPY(ax);
 
 #ifdef CONFIG_X86_64
                COPY(r8);
@@ -94,27 +93,20 @@ 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);
                regs->orig_ax = -1;             /* disable syscall checks */
 
                get_user_ex(buf, &sc->fpstate);
-
-               get_user_ex(*pax, &sc->ax);
        } get_user_catch(err);
 
        err |= restore_xstate_sig(buf, config_enabled(CONFIG_X86_32));
 
+       force_iret();
+
        return err;
 }
 
@@ -162,8 +154,9 @@ 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->gs);
-               put_user_ex(0, &sc->fs);
+               put_user_ex(0, &sc->__pad2);
+               put_user_ex(0, &sc->__pad1);
+               put_user_ex(regs->ss, &sc->ss);
 #endif /* CONFIG_X86_32 */
 
                put_user_ex(fpstate, &sc->fpstate);
@@ -457,9 +450,19 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
 
        regs->sp = (unsigned long)frame;
 
-       /* Set up the CS register to run signal handlers in 64-bit mode,
-          even if the handler happens to be interrupting 32-bit code. */
+       /*
+        * 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.
+        */
        regs->cs = __USER_CS;
+       regs->ss = __USER_DS;
 
        return 0;
 }
@@ -539,7 +542,6 @@ asmlinkage unsigned long sys_sigreturn(void)
 {
        struct pt_regs *regs = current_pt_regs();
        struct sigframe __user *frame;
-       unsigned long ax;
        sigset_t set;
 
        frame = (struct sigframe __user *)(regs->sp - 8);
@@ -553,9 +555,9 @@ asmlinkage unsigned long sys_sigreturn(void)
 
        set_current_blocked(&set);
 
-       if (restore_sigcontext(regs, &frame->sc, &ax))
+       if (restore_sigcontext(regs, &frame->sc))
                goto badframe;
-       return ax;
+       return regs->ax;
 
 badframe:
        signal_fault(regs, frame, "sigreturn");
@@ -568,7 +570,6 @@ asmlinkage long sys_rt_sigreturn(void)
 {
        struct pt_regs *regs = current_pt_regs();
        struct rt_sigframe __user *frame;
-       unsigned long ax;
        sigset_t set;
 
        frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
@@ -579,13 +580,13 @@ asmlinkage long sys_rt_sigreturn(void)
 
        set_current_blocked(&set);
 
-       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
        if (restore_altstack(&frame->uc.uc_stack))
                goto badframe;
 
-       return ax;
+       return regs->ax;
 
 badframe:
        signal_fault(regs, frame, "rt_sigreturn");
@@ -679,7 +680,7 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)
                 * Ensure the signal handler starts with the new fpu state.
                 */
                if (used_math())
-                       drop_init_fpu(current);
+                       fpu_reset_state(current);
        }
        signal_setup_done(failed, ksig, test_thread_flag(TIF_SINGLESTEP));
 }
@@ -780,7 +781,6 @@ asmlinkage long sys32_x32_rt_sigreturn(void)
        struct pt_regs *regs = current_pt_regs();
        struct rt_sigframe_x32 __user *frame;
        sigset_t set;
-       unsigned long ax;
 
        frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8);
 
@@ -791,13 +791,13 @@ asmlinkage long sys32_x32_rt_sigreturn(void)
 
        set_current_blocked(&set);
 
-       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
        if (compat_restore_altstack(&frame->uc.uc_stack))
                goto badframe;
 
-       return ax;
+       return regs->ax;
 
 badframe:
        signal_fault(regs, frame, "x32 rt_sigreturn");
index febc6aabc72e049443f68c167622d50cd8344f16..50e547eac8cd4b64e9e6892410366ec3a64a7a13 100644 (file)
@@ -77,9 +77,6 @@
 #include <asm/realmode.h>
 #include <asm/misc.h>
 
-/* State of each CPU */
-DEFINE_PER_CPU(int, cpu_state) = { 0 };
-
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
 EXPORT_SYMBOL(smp_num_siblings);
@@ -257,7 +254,7 @@ static void notrace start_secondary(void *unused)
        lock_vector_lock();
        set_cpu_online(smp_processor_id(), true);
        unlock_vector_lock();
-       per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+       cpu_set_state_online(smp_processor_id());
        x86_platform.nmi_init();
 
        /* enable local interrupts */
@@ -779,6 +776,26 @@ out:
        return boot_error;
 }
 
+void common_cpu_up(unsigned int cpu, struct task_struct *idle)
+{
+       /* Just in case we booted with a single CPU. */
+       alternatives_enable_smp();
+
+       per_cpu(current_task, cpu) = idle;
+
+#ifdef CONFIG_X86_32
+       /* Stack for startup_32 can be just as for start_secondary onwards */
+       irq_ctx_init(cpu);
+       per_cpu(cpu_current_top_of_stack, cpu) =
+               (unsigned long)task_stack_page(idle) + THREAD_SIZE;
+#else
+       clear_tsk_thread_flag(idle, TIF_FORK);
+       initial_gs = per_cpu_offset(cpu);
+#endif
+       per_cpu(kernel_stack, cpu) =
+               (unsigned long)task_stack_page(idle) + THREAD_SIZE;
+}
+
 /*
  * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
  * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
@@ -796,23 +813,9 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
        int cpu0_nmi_registered = 0;
        unsigned long timeout;
 
-       /* Just in case we booted with a single CPU. */
-       alternatives_enable_smp();
-
        idle->thread.sp = (unsigned long) (((struct pt_regs *)
                          (THREAD_SIZE +  task_stack_page(idle))) - 1);
-       per_cpu(current_task, cpu) = idle;
 
-#ifdef CONFIG_X86_32
-       /* Stack for startup_32 can be just as for start_secondary onwards */
-       irq_ctx_init(cpu);
-#else
-       clear_tsk_thread_flag(idle, TIF_FORK);
-       initial_gs = per_cpu_offset(cpu);
-#endif
-       per_cpu(kernel_stack, cpu) =
-               (unsigned long)task_stack_page(idle) -
-               KERNEL_STACK_OFFSET + THREAD_SIZE;
        early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
        initial_code = (unsigned long)start_secondary;
        stack_start  = idle->thread.sp;
@@ -948,11 +951,16 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle)
         */
        mtrr_save_state();
 
-       per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+       /* x86 CPUs take themselves offline, so delayed offline is OK. */
+       err = cpu_check_up_prepare(cpu);
+       if (err && err != -EBUSY)
+               return err;
 
        /* the FPU context is blank, nobody can own it */
        __cpu_disable_lazy_restore(cpu);
 
+       common_cpu_up(cpu, tidle);
+
        err = do_boot_cpu(apicid, cpu, tidle);
        if (err) {
                pr_err("do_boot_cpu failed(%d) to wakeup CPU#%u\n", err, cpu);
@@ -1086,8 +1094,6 @@ static int __init smp_sanity_check(unsigned max_cpus)
                return SMP_NO_APIC;
        }
 
-       verify_local_APIC();
-
        /*
         * If SMP should be disabled, then really disable it!
         */
@@ -1191,7 +1197,7 @@ void __init native_smp_prepare_boot_cpu(void)
        switch_to_new_gdt(me);
        /* already set me in cpu_online_mask in boot_cpu_init() */
        cpumask_set_cpu(me, cpu_callout_mask);
-       per_cpu(cpu_state, me) = CPU_ONLINE;
+       cpu_set_state_online(me);
 }
 
 void __init native_smp_cpus_done(unsigned int max_cpus)
@@ -1318,14 +1324,10 @@ static void __ref remove_cpu_from_maps(int cpu)
        numa_remove_cpu(cpu);
 }
 
-static DEFINE_PER_CPU(struct completion, die_complete);
-
 void cpu_disable_common(void)
 {
        int cpu = smp_processor_id();
 
-       init_completion(&per_cpu(die_complete, smp_processor_id()));
-
        remove_siblinginfo(cpu);
 
        /* It's now safe to remove this processor from the online map */
@@ -1349,24 +1351,27 @@ int native_cpu_disable(void)
        return 0;
 }
 
-void cpu_die_common(unsigned int cpu)
+int common_cpu_die(unsigned int cpu)
 {
-       wait_for_completion_timeout(&per_cpu(die_complete, cpu), HZ);
-}
+       int ret = 0;
 
-void native_cpu_die(unsigned int cpu)
-{
        /* We don't do anything here: idle task is faking death itself. */
 
-       cpu_die_common(cpu);
-
        /* They ack this in play_dead() by setting CPU_DEAD */
-       if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
+       if (cpu_wait_death(cpu, 5)) {
                if (system_state == SYSTEM_RUNNING)
                        pr_info("CPU %u is now offline\n", cpu);
        } else {
                pr_err("CPU %u didn't die...\n", cpu);
+               ret = -1;
        }
+
+       return ret;
+}
+
+void native_cpu_die(unsigned int cpu)
+{
+       common_cpu_die(cpu);
 }
 
 void play_dead_common(void)
@@ -1375,10 +1380,8 @@ void play_dead_common(void)
        reset_lazy_tlbstate();
        amd_e400_remove_cpu(raw_smp_processor_id());
 
-       mb();
        /* Ack it */
-       __this_cpu_write(cpu_state, CPU_DEAD);
-       complete(&per_cpu(die_complete, smp_processor_id()));
+       (void)cpu_report_death();
 
        /*
         * With physical CPU hotplug, we should halt the cpu
index 30277e27431acde9a9320e0b1be4470bddb40e3a..10e0272d789a189b7215100a1d66a676d9b4bbfa 100644 (file)
@@ -34,10 +34,26 @@ static unsigned long get_align_mask(void)
        return va_align.mask;
 }
 
+/*
+ * To avoid aliasing in the I$ on AMD F15h, the bits defined by the
+ * va_align.bits, [12:upper_bit), are set to a random value instead of
+ * zeroing them. This random value is computed once per boot. This form
+ * of ASLR is known as "per-boot ASLR".
+ *
+ * To achieve this, the random value is added to the info.align_offset
+ * value before calling vm_unmapped_area() or ORed directly to the
+ * address.
+ */
+static unsigned long get_align_bits(void)
+{
+       return va_align.bits & get_align_mask();
+}
+
 unsigned long align_vdso_addr(unsigned long addr)
 {
        unsigned long align_mask = get_align_mask();
-       return (addr + align_mask) & ~align_mask;
+       addr = (addr + align_mask) & ~align_mask;
+       return addr | get_align_bits();
 }
 
 static int __init control_va_addr_alignment(char *str)
@@ -135,8 +151,12 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
        info.length = len;
        info.low_limit = begin;
        info.high_limit = end;
-       info.align_mask = filp ? get_align_mask() : 0;
+       info.align_mask = 0;
        info.align_offset = pgoff << PAGE_SHIFT;
+       if (filp) {
+               info.align_mask = get_align_mask();
+               info.align_offset += get_align_bits();
+       }
        return vm_unmapped_area(&info);
 }
 
@@ -174,8 +194,12 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        info.length = len;
        info.low_limit = PAGE_SIZE;
        info.high_limit = mm->mmap_base;
-       info.align_mask = filp ? get_align_mask() : 0;
+       info.align_mask = 0;
        info.align_offset = pgoff << PAGE_SHIFT;
+       if (filp) {
+               info.align_mask = get_align_mask();
+               info.align_offset += get_align_bits();
+       }
        addr = vm_unmapped_area(&info);
        if (!(addr & ~PAGE_MASK))
                return addr;
index e9bcd57d8a9eb862212351527de3597040e611ba..3777189c4a19f04d1b7118ce2fae228e86356592 100644 (file)
@@ -5,21 +5,29 @@
 #include <linux/cache.h>
 #include <asm/asm-offsets.h>
 
-#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ;
+#ifdef CONFIG_IA32_EMULATION
+#define SYM(sym, compat) compat
+#else
+#define SYM(sym, compat) sym
+#define ia32_sys_call_table sys_call_table
+#define __NR_ia32_syscall_max __NR_syscall_max
+#endif
+
+#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void SYM(sym, compat)(void) ;
 #include <asm/syscalls_32.h>
 #undef __SYSCALL_I386
 
-#define __SYSCALL_I386(nr, sym, compat) [nr] = sym,
+#define __SYSCALL_I386(nr, sym, compat) [nr] = SYM(sym, compat),
 
 typedef asmlinkage void (*sys_call_ptr_t)(void);
 
 extern asmlinkage void sys_ni_syscall(void);
 
-__visible const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
+__visible const sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = {
        /*
         * Smells like a compiler bug -- it doesn't work
         * when the & below is removed.
         */
-       [0 ... __NR_syscall_max] = &sys_ni_syscall,
+       [0 ... __NR_ia32_syscall_max] = &sys_ni_syscall,
 #include <asm/syscalls_32.h>
 };
index b79133abda48d9c025eb1dad8ddf5a0b20ac1090..5ecbfe5099dad68e140b85ffdaefc75818afc6d9 100644 (file)
@@ -57,7 +57,7 @@ int rodata_test(void)
        /* test 3: check the value hasn't changed */
        /* If this test fails, we managed to overwrite the data */
        if (!rodata_test_data) {
-               printk(KERN_ERR "rodata_test: Test 3 failes (end data)\n");
+               printk(KERN_ERR "rodata_test: Test 3 fails (end data)\n");
                return -ENODEV;
        }
        /* test 4: check if the rodata section is 4Kb aligned */
index 25adc0e16eaa6349e78bd909860f6710705acb8e..d39c09119db6d2bf9e7ed6f1921f26f45dee3019 100644 (file)
@@ -30,7 +30,7 @@ unsigned long profile_pc(struct pt_regs *regs)
 {
        unsigned long pc = instruction_pointer(regs);
 
-       if (!user_mode_vm(regs) && in_lock_functions(pc)) {
+       if (!user_mode(regs) && in_lock_functions(pc)) {
 #ifdef CONFIG_FRAME_POINTER
                return *(unsigned long *)(regs->bp + sizeof(long));
 #else
index 4ff5d162ff9fd55381259ff8dd96f84064ecea72..324ab524768756b1987efbee11f06ce3ba24562b 100644 (file)
@@ -112,7 +112,7 @@ enum ctx_state ist_enter(struct pt_regs *regs)
 {
        enum ctx_state prev_state;
 
-       if (user_mode_vm(regs)) {
+       if (user_mode(regs)) {
                /* Other than that, we're just an exception. */
                prev_state = exception_enter();
        } else {
@@ -123,7 +123,7 @@ enum ctx_state ist_enter(struct pt_regs *regs)
                 * but we need to notify RCU.
                 */
                rcu_nmi_enter();
-               prev_state = IN_KERNEL;  /* the value is irrelevant. */
+               prev_state = CONTEXT_KERNEL;  /* the value is irrelevant. */
        }
 
        /*
@@ -146,7 +146,7 @@ void ist_exit(struct pt_regs *regs, enum ctx_state prev_state)
        /* Must be before exception_exit. */
        preempt_count_sub(HARDIRQ_OFFSET);
 
-       if (user_mode_vm(regs))
+       if (user_mode(regs))
                return exception_exit(prev_state);
        else
                rcu_nmi_exit();
@@ -158,7 +158,7 @@ void ist_exit(struct pt_regs *regs, enum ctx_state prev_state)
  *
  * IST exception handlers normally cannot schedule.  As a special
  * exception, if the exception interrupted userspace code (i.e.
- * user_mode_vm(regs) would return true) and the exception was not
+ * user_mode(regs) would return true) and the exception was not
  * a double fault, it can be safe to schedule.  ist_begin_non_atomic()
  * begins a non-atomic section within an ist_enter()/ist_exit() region.
  * Callers are responsible for enabling interrupts themselves inside
@@ -167,15 +167,15 @@ void ist_exit(struct pt_regs *regs, enum ctx_state prev_state)
  */
 void ist_begin_non_atomic(struct pt_regs *regs)
 {
-       BUG_ON(!user_mode_vm(regs));
+       BUG_ON(!user_mode(regs));
 
        /*
         * Sanity check: we need to be on the normal thread stack.  This
         * will catch asm bugs and any attempt to use ist_preempt_enable
         * from double_fault.
         */
-       BUG_ON(((current_stack_pointer() ^ this_cpu_read_stable(kernel_stack))
-               & ~(THREAD_SIZE - 1)) != 0);
+       BUG_ON((unsigned long)(current_top_of_stack() -
+                              current_stack_pointer()) >= THREAD_SIZE);
 
        preempt_count_sub(HARDIRQ_OFFSET);
 }
@@ -194,8 +194,7 @@ static nokprobe_inline int
 do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str,
                  struct pt_regs *regs, long error_code)
 {
-#ifdef CONFIG_X86_32
-       if (regs->flags & X86_VM_MASK) {
+       if (v8086_mode(regs)) {
                /*
                 * Traps 0, 1, 3, 4, and 5 should be forwarded to vm86.
                 * On nmi (interrupt 2), do_trap should not be called.
@@ -207,7 +206,7 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str,
                }
                return -1;
        }
-#endif
+
        if (!user_mode(regs)) {
                if (!fixup_exception(regs)) {
                        tsk->thread.error_code = error_code;
@@ -384,7 +383,7 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code)
                goto exit;
        conditional_sti(regs);
 
-       if (!user_mode_vm(regs))
+       if (!user_mode(regs))
                die("bounds", regs, error_code);
 
        if (!cpu_feature_enabled(X86_FEATURE_MPX)) {
@@ -462,13 +461,11 @@ do_general_protection(struct pt_regs *regs, long error_code)
        prev_state = exception_enter();
        conditional_sti(regs);
 
-#ifdef CONFIG_X86_32
-       if (regs->flags & X86_VM_MASK) {
+       if (v8086_mode(regs)) {
                local_irq_enable();
                handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
                goto exit;
        }
-#endif
 
        tsk = current;
        if (!user_mode(regs)) {
@@ -587,7 +584,7 @@ struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s)
        /* Copy the remainder of the stack from the current stack. */
        memmove(new_stack, s, offsetof(struct bad_iret_stack, regs.ip));
 
-       BUG_ON(!user_mode_vm(&new_stack->regs));
+       BUG_ON(!user_mode(&new_stack->regs));
        return new_stack;
 }
 NOKPROBE_SYMBOL(fixup_bad_iret);
@@ -637,7 +634,7 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code)
         * then it's very likely the result of an icebp/int01 trap.
         * User wants a sigtrap for that.
         */
-       if (!dr6 && user_mode_vm(regs))
+       if (!dr6 && user_mode(regs))
                user_icebp = 1;
 
        /* Catch kmemcheck conditions first of all! */
@@ -673,7 +670,7 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code)
        /* It's safe to allow irq's after DR6 has been saved */
        preempt_conditional_sti(regs);
 
-       if (regs->flags & X86_VM_MASK) {
+       if (v8086_mode(regs)) {
                handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code,
                                        X86_TRAP_DB);
                preempt_conditional_cli(regs);
@@ -721,7 +718,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr)
                return;
        conditional_sti(regs);
 
-       if (!user_mode_vm(regs))
+       if (!user_mode(regs))
        {
                if (!fixup_exception(regs)) {
                        task->thread.error_code = error_code;
@@ -734,7 +731,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr)
        /*
         * Save the info for the exception handler and clear the error.
         */
-       save_init_fpu(task);
+       unlazy_fpu(task);
        task->thread.trap_nr = trapnr;
        task->thread.error_code = error_code;
        info.si_signo = SIGFPE;
@@ -863,7 +860,7 @@ void math_state_restore(void)
        kernel_fpu_disable();
        __thread_fpu_begin(tsk);
        if (unlikely(restore_fpu_checking(tsk))) {
-               drop_init_fpu(tsk);
+               fpu_reset_state(tsk);
                force_sig_info(SIGSEGV, SEND_SIG_PRIV, tsk);
        } else {
                tsk->thread.fpu_counter++;
@@ -925,9 +922,21 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
 /* Set of traps needed for early debugging. */
 void __init early_trap_init(void)
 {
-       set_intr_gate_ist(X86_TRAP_DB, &debug, DEBUG_STACK);
+       /*
+        * Don't use IST to set DEBUG_STACK as it doesn't work until TSS
+        * is ready in cpu_init() <-- trap_init(). Before trap_init(),
+        * CPU runs at ring 0 so it is impossible to hit an invalid
+        * stack.  Using the original stack works well enough at this
+        * early stage. DEBUG_STACK will be equipped after cpu_init() in
+        * trap_init().
+        *
+        * We don't need to set trace_idt_table like set_intr_gate(),
+        * since we don't have trace_debug and it will be reset to
+        * 'debug' in trap_init() by set_intr_gate_ist().
+        */
+       set_intr_gate_notrace(X86_TRAP_DB, debug);
        /* int3 can be called from all */
-       set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK);
+       set_system_intr_gate(X86_TRAP_BP, &int3);
 #ifdef CONFIG_X86_32
        set_intr_gate(X86_TRAP_PF, page_fault);
 #endif
@@ -1005,6 +1014,15 @@ void __init trap_init(void)
         */
        cpu_init();
 
+       /*
+        * X86_TRAP_DB and X86_TRAP_BP have been set
+        * in early_trap_init(). However, ITS works only after
+        * cpu_init() loads TSS. See comments in early_trap_init().
+        */
+       set_intr_gate_ist(X86_TRAP_DB, &debug, DEBUG_STACK);
+       /* int3 can be called from all */
+       set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK);
+
        x86_init.irqs.trap_init();
 
 #ifdef CONFIG_X86_64
index 81f8adb0679e548d31af5982297c85141e3693f9..0b81ad67da07fa36e57577de5f7165ab320a55a1 100644 (file)
@@ -912,7 +912,7 @@ int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val,
        int ret = NOTIFY_DONE;
 
        /* We are only interested in userspace traps */
-       if (regs && !user_mode_vm(regs))
+       if (regs && !user_mode(regs))
                return NOTIFY_DONE;
 
        switch (val) {
index e8edcf52e06911fe5446e543f40368ea69114225..fc9db6ef2a95937b1abd4f37f3a466043ba818d4 100644 (file)
@@ -150,7 +150,7 @@ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs)
                do_exit(SIGSEGV);
        }
 
-       tss = &per_cpu(init_tss, get_cpu());
+       tss = &per_cpu(cpu_tss, get_cpu());
        current->thread.sp0 = current->thread.saved_sp0;
        current->thread.sysenter_cs = __KERNEL_CS;
        load_sp0(tss, &current->thread);
@@ -318,7 +318,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
        tsk->thread.saved_fs = info->regs32->fs;
        tsk->thread.saved_gs = get_user_gs(info->regs32);
 
-       tss = &per_cpu(init_tss, get_cpu());
+       tss = &per_cpu(cpu_tss, get_cpu());
        tsk->thread.sp0 = (unsigned long) &info->VM86_TSS_ESP0;
        if (cpu_has_sep)
                tsk->thread.sysenter_cs = 0;
index c7d791f32b98e4f8598684306f086c6193ff6e93..51e3304169951619362ea4a1494716e4f20696bf 100644 (file)
@@ -31,30 +31,30 @@ void update_vsyscall(struct timekeeper *tk)
        gtod_write_begin(vdata);
 
        /* copy vsyscall data */
-       vdata->vclock_mode      = tk->tkr.clock->archdata.vclock_mode;
-       vdata->cycle_last       = tk->tkr.cycle_last;
-       vdata->mask             = tk->tkr.mask;
-       vdata->mult             = tk->tkr.mult;
-       vdata->shift            = tk->tkr.shift;
+       vdata->vclock_mode      = tk->tkr_mono.clock->archdata.vclock_mode;
+       vdata->cycle_last       = tk->tkr_mono.cycle_last;
+       vdata->mask             = tk->tkr_mono.mask;
+       vdata->mult             = tk->tkr_mono.mult;
+       vdata->shift            = tk->tkr_mono.shift;
 
        vdata->wall_time_sec            = tk->xtime_sec;
-       vdata->wall_time_snsec          = tk->tkr.xtime_nsec;
+       vdata->wall_time_snsec          = tk->tkr_mono.xtime_nsec;
 
        vdata->monotonic_time_sec       = tk->xtime_sec
                                        + tk->wall_to_monotonic.tv_sec;
-       vdata->monotonic_time_snsec     = tk->tkr.xtime_nsec
+       vdata->monotonic_time_snsec     = tk->tkr_mono.xtime_nsec
                                        + ((u64)tk->wall_to_monotonic.tv_nsec
-                                               << tk->tkr.shift);
+                                               << tk->tkr_mono.shift);
        while (vdata->monotonic_time_snsec >=
-                                       (((u64)NSEC_PER_SEC) << tk->tkr.shift)) {
+                                       (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
                vdata->monotonic_time_snsec -=
-                                       ((u64)NSEC_PER_SEC) << tk->tkr.shift;
+                                       ((u64)NSEC_PER_SEC) << tk->tkr_mono.shift;
                vdata->monotonic_time_sec++;
        }
 
        vdata->wall_time_coarse_sec     = tk->xtime_sec;
-       vdata->wall_time_coarse_nsec    = (long)(tk->tkr.xtime_nsec >>
-                                                tk->tkr.shift);
+       vdata->wall_time_coarse_nsec    = (long)(tk->tkr_mono.xtime_nsec >>
+                                                tk->tkr_mono.shift);
 
        vdata->monotonic_time_coarse_sec =
                vdata->wall_time_coarse_sec + tk->wall_to_monotonic.tv_sec;
index cdc6cf90307800abb83f1b4b516ba389212c3dd0..87a815b85f3e5c1b9ee6db83224ad954eef1df75 100644 (file)
@@ -342,7 +342,7 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
                         config_enabled(CONFIG_IA32_EMULATION));
 
        if (!buf) {
-               drop_init_fpu(tsk);
+               fpu_reset_state(tsk);
                return 0;
        }
 
@@ -416,7 +416,7 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
                 */
                user_fpu_begin();
                if (restore_user_xstate(buf_fx, xstate_bv, fx_only)) {
-                       drop_init_fpu(tsk);
+                       fpu_reset_state(tsk);
                        return -1;
                }
        }
@@ -678,19 +678,13 @@ void xsave_init(void)
        this_func();
 }
 
-static inline void __init eager_fpu_init_bp(void)
-{
-       current->thread.fpu.state =
-           alloc_bootmem_align(xstate_size, __alignof__(struct xsave_struct));
-       if (!init_xstate_buf)
-               setup_init_fpu_buf();
-}
-
-void eager_fpu_init(void)
+/*
+ * setup_init_fpu_buf() is __init and it is OK to call it here because
+ * init_xstate_buf will be unset only once during boot.
+ */
+void __init_refok eager_fpu_init(void)
 {
-       static __refdata void (*boot_func)(void) = eager_fpu_init_bp;
-
-       clear_used_math();
+       WARN_ON(used_math());
        current_thread_info()->status = 0;
 
        if (eagerfpu == ENABLE)
@@ -701,21 +695,8 @@ void eager_fpu_init(void)
                return;
        }
 
-       if (boot_func) {
-               boot_func();
-               boot_func = NULL;
-       }
-
-       /*
-        * This is same as math_state_restore(). But use_xsave() is
-        * not yet patched to use math_state_restore().
-        */
-       init_fpu(current);
-       __thread_fpu_begin(current);
-       if (cpu_has_xsave)
-               xrstor_state(init_xstate_buf, -1);
-       else
-               fxrstor_checking(&init_xstate_buf->i387);
+       if (!init_xstate_buf)
+               setup_init_fpu_buf();
 }
 
 /*
index 08f790dfadc9fb90dc3591687aaa93cc73fe1f88..16e8f962eaadf9d8f0d1cb4942288ebcd3f12a94 100644 (file)
@@ -1,5 +1,5 @@
 
-ccflags-y += -Ivirt/kvm -Iarch/x86/kvm
+ccflags-y += -Iarch/x86/kvm
 
 CFLAGS_x86.o := -I.
 CFLAGS_svm.o := -I.
index 8a80737ee6e6ec14bc7d9a6ffe08d9f580d3c890..59b69f6a2844cdce101a69c3bb34eb7ccd30556f 100644 (file)
@@ -104,6 +104,9 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu)
                ((best->eax & 0xff00) >> 8) != 0)
                return -EINVAL;
 
+       /* Update physical-address width */
+       vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
+
        kvm_pmu_cpuid_update(vcpu);
        return 0;
 }
@@ -135,6 +138,21 @@ static void cpuid_fix_nx_cap(struct kvm_vcpu *vcpu)
        }
 }
 
+int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu)
+{
+       struct kvm_cpuid_entry2 *best;
+
+       best = kvm_find_cpuid_entry(vcpu, 0x80000000, 0);
+       if (!best || best->eax < 0x80000008)
+               goto not_found;
+       best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
+       if (best)
+               return best->eax & 0xff;
+not_found:
+       return 36;
+}
+EXPORT_SYMBOL_GPL(cpuid_query_maxphyaddr);
+
 /* when an old userspace process fills a new kernel module */
 int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
                             struct kvm_cpuid *cpuid,
@@ -757,21 +775,6 @@ struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
 }
 EXPORT_SYMBOL_GPL(kvm_find_cpuid_entry);
 
-int cpuid_maxphyaddr(struct kvm_vcpu *vcpu)
-{
-       struct kvm_cpuid_entry2 *best;
-
-       best = kvm_find_cpuid_entry(vcpu, 0x80000000, 0);
-       if (!best || best->eax < 0x80000008)
-               goto not_found;
-       best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
-       if (best)
-               return best->eax & 0xff;
-not_found:
-       return 36;
-}
-EXPORT_SYMBOL_GPL(cpuid_maxphyaddr);
-
 /*
  * If no match is found, check whether we exceed the vCPU's limit
  * and return the content of the highest valid _standard_ leaf instead.
index 4452eedfaedd0a4849b54d4137edd5e85b24ae46..c3b1ad9fca818befb9e5920f7eb7c0d2b703d245 100644 (file)
@@ -20,13 +20,19 @@ int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
                              struct kvm_cpuid_entry2 __user *entries);
 void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
 
+int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu);
+
+static inline int cpuid_maxphyaddr(struct kvm_vcpu *vcpu)
+{
+       return vcpu->arch.maxphyaddr;
+}
 
 static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
 
        if (!static_cpu_has(X86_FEATURE_XSAVE))
-               return 0;
+               return false;
 
        best = kvm_find_cpuid_entry(vcpu, 1, 0);
        return best && (best->ecx & bit(X86_FEATURE_XSAVE));
index 106c01557f2b63706eca28e462a3b072b590f0c5..630bcb0d7a045b4930213eac1c1bbee3ef7d0ebe 100644 (file)
@@ -248,27 +248,7 @@ struct mode_dual {
        struct opcode mode64;
 };
 
-/* EFLAGS bit definitions. */
-#define EFLG_ID (1<<21)
-#define EFLG_VIP (1<<20)
-#define EFLG_VIF (1<<19)
-#define EFLG_AC (1<<18)
-#define EFLG_VM (1<<17)
-#define EFLG_RF (1<<16)
-#define EFLG_IOPL (3<<12)
-#define EFLG_NT (1<<14)
-#define EFLG_OF (1<<11)
-#define EFLG_DF (1<<10)
-#define EFLG_IF (1<<9)
-#define EFLG_TF (1<<8)
-#define EFLG_SF (1<<7)
-#define EFLG_ZF (1<<6)
-#define EFLG_AF (1<<4)
-#define EFLG_PF (1<<2)
-#define EFLG_CF (1<<0)
-
 #define EFLG_RESERVED_ZEROS_MASK 0xffc0802a
-#define EFLG_RESERVED_ONE_MASK 2
 
 enum x86_transfer_type {
        X86_TRANSFER_NONE,
@@ -317,7 +297,8 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)
  * These EFLAGS bits are restored from saved value during emulation, and
  * any changes are written back to the saved value after emulation.
  */
-#define EFLAGS_MASK (EFLG_OF|EFLG_SF|EFLG_ZF|EFLG_AF|EFLG_PF|EFLG_CF)
+#define EFLAGS_MASK (X86_EFLAGS_OF|X86_EFLAGS_SF|X86_EFLAGS_ZF|X86_EFLAGS_AF|\
+                    X86_EFLAGS_PF|X86_EFLAGS_CF)
 
 #ifdef CONFIG_X86_64
 #define ON64(x) x
@@ -478,6 +459,25 @@ static void assign_masked(ulong *dest, ulong src, ulong mask)
        *dest = (*dest & ~mask) | (src & mask);
 }
 
+static void assign_register(unsigned long *reg, u64 val, int bytes)
+{
+       /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
+       switch (bytes) {
+       case 1:
+               *(u8 *)reg = (u8)val;
+               break;
+       case 2:
+               *(u16 *)reg = (u16)val;
+               break;
+       case 4:
+               *reg = (u32)val;
+               break;  /* 64b: zero-extend */
+       case 8:
+               *reg = val;
+               break;
+       }
+}
+
 static inline unsigned long ad_mask(struct x86_emulate_ctxt *ctxt)
 {
        return (1UL << (ctxt->ad_bytes << 3)) - 1;
@@ -943,6 +943,22 @@ FASTOP2(xadd);
 
 FASTOP2R(cmp, cmp_r);
 
+static int em_bsf_c(struct x86_emulate_ctxt *ctxt)
+{
+       /* If src is zero, do not writeback, but update flags */
+       if (ctxt->src.val == 0)
+               ctxt->dst.type = OP_NONE;
+       return fastop(ctxt, em_bsf);
+}
+
+static int em_bsr_c(struct x86_emulate_ctxt *ctxt)
+{
+       /* If src is zero, do not writeback, but update flags */
+       if (ctxt->src.val == 0)
+               ctxt->dst.type = OP_NONE;
+       return fastop(ctxt, em_bsr);
+}
+
 static u8 test_cc(unsigned int condition, unsigned long flags)
 {
        u8 rc;
@@ -1399,7 +1415,7 @@ static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
                unsigned int in_page, n;
                unsigned int count = ctxt->rep_prefix ?
                        address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) : 1;
-               in_page = (ctxt->eflags & EFLG_DF) ?
+               in_page = (ctxt->eflags & X86_EFLAGS_DF) ?
                        offset_in_page(reg_read(ctxt, VCPU_REGS_RDI)) :
                        PAGE_SIZE - offset_in_page(reg_read(ctxt, VCPU_REGS_RDI));
                n = min3(in_page, (unsigned int)sizeof(rc->data) / size, count);
@@ -1412,7 +1428,7 @@ static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
        }
 
        if (ctxt->rep_prefix && (ctxt->d & String) &&
-           !(ctxt->eflags & EFLG_DF)) {
+           !(ctxt->eflags & X86_EFLAGS_DF)) {
                ctxt->dst.data = rc->data + rc->pos;
                ctxt->dst.type = OP_MEM_STR;
                ctxt->dst.count = (rc->end - rc->pos) / size;
@@ -1691,21 +1707,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 
 static void write_register_operand(struct operand *op)
 {
-       /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
-       switch (op->bytes) {
-       case 1:
-               *(u8 *)op->addr.reg = (u8)op->val;
-               break;
-       case 2:
-               *(u16 *)op->addr.reg = (u16)op->val;
-               break;
-       case 4:
-               *op->addr.reg = (u32)op->val;
-               break;  /* 64b: zero-extend */
-       case 8:
-               *op->addr.reg = op->val;
-               break;
-       }
+       return assign_register(op->addr.reg, op->val, op->bytes);
 }
 
 static int writeback(struct x86_emulate_ctxt *ctxt, struct operand *op)
@@ -1792,32 +1794,34 @@ static int emulate_popf(struct x86_emulate_ctxt *ctxt,
 {
        int rc;
        unsigned long val, change_mask;
-       int iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
+       int iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> X86_EFLAGS_IOPL_BIT;
        int cpl = ctxt->ops->cpl(ctxt);
 
        rc = emulate_pop(ctxt, &val, len);
        if (rc != X86EMUL_CONTINUE)
                return rc;
 
-       change_mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_OF
-               | EFLG_TF | EFLG_DF | EFLG_NT | EFLG_AC | EFLG_ID;
+       change_mask = X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
+                     X86_EFLAGS_ZF | X86_EFLAGS_SF | X86_EFLAGS_OF |
+                     X86_EFLAGS_TF | X86_EFLAGS_DF | X86_EFLAGS_NT |
+                     X86_EFLAGS_AC | X86_EFLAGS_ID;
 
        switch(ctxt->mode) {
        case X86EMUL_MODE_PROT64:
        case X86EMUL_MODE_PROT32:
        case X86EMUL_MODE_PROT16:
                if (cpl == 0)
-                       change_mask |= EFLG_IOPL;
+                       change_mask |= X86_EFLAGS_IOPL;
                if (cpl <= iopl)
-                       change_mask |= EFLG_IF;
+                       change_mask |= X86_EFLAGS_IF;
                break;
        case X86EMUL_MODE_VM86:
                if (iopl < 3)
                        return emulate_gp(ctxt, 0);
-               change_mask |= EFLG_IF;
+               change_mask |= X86_EFLAGS_IF;
                break;
        default: /* real mode */
-               change_mask |= (EFLG_IOPL | EFLG_IF);
+               change_mask |= (X86_EFLAGS_IOPL | X86_EFLAGS_IF);
                break;
        }
 
@@ -1918,7 +1922,7 @@ static int em_pusha(struct x86_emulate_ctxt *ctxt)
 
 static int em_pushf(struct x86_emulate_ctxt *ctxt)
 {
-       ctxt->src.val = (unsigned long)ctxt->eflags & ~EFLG_VM;
+       ctxt->src.val = (unsigned long)ctxt->eflags & ~X86_EFLAGS_VM;
        return em_push(ctxt);
 }
 
@@ -1926,6 +1930,7 @@ static int em_popa(struct x86_emulate_ctxt *ctxt)
 {
        int rc = X86EMUL_CONTINUE;
        int reg = VCPU_REGS_RDI;
+       u32 val;
 
        while (reg >= VCPU_REGS_RAX) {
                if (reg == VCPU_REGS_RSP) {
@@ -1933,9 +1938,10 @@ static int em_popa(struct x86_emulate_ctxt *ctxt)
                        --reg;
                }
 
-               rc = emulate_pop(ctxt, reg_rmw(ctxt, reg), ctxt->op_bytes);
+               rc = emulate_pop(ctxt, &val, ctxt->op_bytes);
                if (rc != X86EMUL_CONTINUE)
                        break;
+               assign_register(reg_rmw(ctxt, reg), val, ctxt->op_bytes);
                --reg;
        }
        return rc;
@@ -1956,7 +1962,7 @@ static int __emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq)
        if (rc != X86EMUL_CONTINUE)
                return rc;
 
-       ctxt->eflags &= ~(EFLG_IF | EFLG_TF | EFLG_AC);
+       ctxt->eflags &= ~(X86_EFLAGS_IF | X86_EFLAGS_TF | X86_EFLAGS_AC);
 
        ctxt->src.val = get_segment_selector(ctxt, VCPU_SREG_CS);
        rc = em_push(ctxt);
@@ -2022,10 +2028,14 @@ static int emulate_iret_real(struct x86_emulate_ctxt *ctxt)
        unsigned long temp_eip = 0;
        unsigned long temp_eflags = 0;
        unsigned long cs = 0;
-       unsigned long mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_TF |
-                            EFLG_IF | EFLG_DF | EFLG_OF | EFLG_IOPL | EFLG_NT | EFLG_RF |
-                            EFLG_AC | EFLG_ID | (1 << 1); /* Last one is the reserved bit */
-       unsigned long vm86_mask = EFLG_VM | EFLG_VIF | EFLG_VIP;
+       unsigned long mask = X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
+                            X86_EFLAGS_ZF | X86_EFLAGS_SF | X86_EFLAGS_TF |
+                            X86_EFLAGS_IF | X86_EFLAGS_DF | X86_EFLAGS_OF |
+                            X86_EFLAGS_IOPL | X86_EFLAGS_NT | X86_EFLAGS_RF |
+                            X86_EFLAGS_AC | X86_EFLAGS_ID |
+                            X86_EFLAGS_FIXED;
+       unsigned long vm86_mask = X86_EFLAGS_VM | X86_EFLAGS_VIF |
+                                 X86_EFLAGS_VIP;
 
        /* TODO: Add stack limit check */
 
@@ -2054,7 +2064,6 @@ static int emulate_iret_real(struct x86_emulate_ctxt *ctxt)
 
        ctxt->_eip = temp_eip;
 
-
        if (ctxt->op_bytes == 4)
                ctxt->eflags = ((temp_eflags & mask) | (ctxt->eflags & vm86_mask));
        else if (ctxt->op_bytes == 2) {
@@ -2063,7 +2072,7 @@ static int emulate_iret_real(struct x86_emulate_ctxt *ctxt)
        }
 
        ctxt->eflags &= ~EFLG_RESERVED_ZEROS_MASK; /* Clear reserved zeros */
-       ctxt->eflags |= EFLG_RESERVED_ONE_MASK;
+       ctxt->eflags |= X86_EFLAGS_FIXED;
        ctxt->ops->set_nmi_mask(ctxt, false);
 
        return rc;
@@ -2145,12 +2154,12 @@ static int em_cmpxchg8b(struct x86_emulate_ctxt *ctxt)
            ((u32) (old >> 32) != (u32) reg_read(ctxt, VCPU_REGS_RDX))) {
                *reg_write(ctxt, VCPU_REGS_RAX) = (u32) (old >> 0);
                *reg_write(ctxt, VCPU_REGS_RDX) = (u32) (old >> 32);
-               ctxt->eflags &= ~EFLG_ZF;
+               ctxt->eflags &= ~X86_EFLAGS_ZF;
        } else {
                ctxt->dst.val64 = ((u64)reg_read(ctxt, VCPU_REGS_RCX) << 32) |
                        (u32) reg_read(ctxt, VCPU_REGS_RBX);
 
-               ctxt->eflags |= EFLG_ZF;
+               ctxt->eflags |= X86_EFLAGS_ZF;
        }
        return X86EMUL_CONTINUE;
 }
@@ -2222,7 +2231,7 @@ static int em_cmpxchg(struct x86_emulate_ctxt *ctxt)
        ctxt->src.val = ctxt->dst.orig_val;
        fastop(ctxt, em_cmp);
 
-       if (ctxt->eflags & EFLG_ZF) {
+       if (ctxt->eflags & X86_EFLAGS_ZF) {
                /* Success: write back to memory; no update of EAX */
                ctxt->src.type = OP_NONE;
                ctxt->dst.val = ctxt->src.orig_val;
@@ -2381,14 +2390,14 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt)
 
                ops->get_msr(ctxt, MSR_SYSCALL_MASK, &msr_data);
                ctxt->eflags &= ~msr_data;
-               ctxt->eflags |= EFLG_RESERVED_ONE_MASK;
+               ctxt->eflags |= X86_EFLAGS_FIXED;
 #endif
        } else {
                /* legacy mode */
                ops->get_msr(ctxt, MSR_STAR, &msr_data);
                ctxt->_eip = (u32)msr_data;
 
-               ctxt->eflags &= ~(EFLG_VM | EFLG_IF);
+               ctxt->eflags &= ~(X86_EFLAGS_VM | X86_EFLAGS_IF);
        }
 
        return X86EMUL_CONTINUE;
@@ -2425,8 +2434,8 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
        if ((msr_data & 0xfffc) == 0x0)
                return emulate_gp(ctxt, 0);
 
-       ctxt->eflags &= ~(EFLG_VM | EFLG_IF);
-       cs_sel = (u16)msr_data & ~SELECTOR_RPL_MASK;
+       ctxt->eflags &= ~(X86_EFLAGS_VM | X86_EFLAGS_IF);
+       cs_sel = (u16)msr_data & ~SEGMENT_RPL_MASK;
        ss_sel = cs_sel + 8;
        if (efer & EFER_LMA) {
                cs.d = 0;
@@ -2493,8 +2502,8 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
                        return emulate_gp(ctxt, 0);
                break;
        }
-       cs_sel |= SELECTOR_RPL_MASK;
-       ss_sel |= SELECTOR_RPL_MASK;
+       cs_sel |= SEGMENT_RPL_MASK;
+       ss_sel |= SEGMENT_RPL_MASK;
 
        ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS);
        ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
@@ -2512,7 +2521,7 @@ static bool emulator_bad_iopl(struct x86_emulate_ctxt *ctxt)
                return false;
        if (ctxt->mode == X86EMUL_MODE_VM86)
                return true;
-       iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
+       iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> X86_EFLAGS_IOPL_BIT;
        return ctxt->ops->cpl(ctxt) > iopl;
 }
 
@@ -2782,10 +2791,8 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
                return ret;
        ret = __load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS, cpl,
                                        X86_TRANSFER_TASK_SWITCH, NULL);
-       if (ret != X86EMUL_CONTINUE)
-               return ret;
 
-       return X86EMUL_CONTINUE;
+       return ret;
 }
 
 static int task_switch_32(struct x86_emulate_ctxt *ctxt,
@@ -2954,7 +2961,7 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
 static void string_addr_inc(struct x86_emulate_ctxt *ctxt, int reg,
                struct operand *op)
 {
-       int df = (ctxt->eflags & EFLG_DF) ? -op->count : op->count;
+       int df = (ctxt->eflags & X86_EFLAGS_DF) ? -op->count : op->count;
 
        register_address_increment(ctxt, reg, df * op->bytes);
        op->addr.mem.ea = register_address(ctxt, reg);
@@ -3323,7 +3330,7 @@ static int em_clts(struct x86_emulate_ctxt *ctxt)
        return X86EMUL_CONTINUE;
 }
 
-static int em_vmcall(struct x86_emulate_ctxt *ctxt)
+static int em_hypercall(struct x86_emulate_ctxt *ctxt)
 {
        int rc = ctxt->ops->fix_hypercall(ctxt);
 
@@ -3395,17 +3402,6 @@ static int em_lgdt(struct x86_emulate_ctxt *ctxt)
        return em_lgdt_lidt(ctxt, true);
 }
 
-static int em_vmmcall(struct x86_emulate_ctxt *ctxt)
-{
-       int rc;
-
-       rc = ctxt->ops->fix_hypercall(ctxt);
-
-       /* Disable writeback. */
-       ctxt->dst.type = OP_NONE;
-       return rc;
-}
-
 static int em_lidt(struct x86_emulate_ctxt *ctxt)
 {
        return em_lgdt_lidt(ctxt, false);
@@ -3504,7 +3500,8 @@ static int em_sahf(struct x86_emulate_ctxt *ctxt)
 {
        u32 flags;
 
-       flags = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF;
+       flags = X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF | X86_EFLAGS_ZF |
+               X86_EFLAGS_SF;
        flags &= *reg_rmw(ctxt, VCPU_REGS_RAX) >> 8;
 
        ctxt->eflags &= ~0xffUL;
@@ -3769,7 +3766,7 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
 
 static const struct opcode group7_rm0[] = {
        N,
-       I(SrcNone | Priv | EmulateOnUD, em_vmcall),
+       I(SrcNone | Priv | EmulateOnUD, em_hypercall),
        N, N, N, N, N, N,
 };
 
@@ -3781,7 +3778,7 @@ static const struct opcode group7_rm1[] = {
 
 static const struct opcode group7_rm3[] = {
        DIP(SrcNone | Prot | Priv,              vmrun,          check_svme_pa),
-       II(SrcNone  | Prot | EmulateOnUD,       em_vmmcall,     vmmcall),
+       II(SrcNone  | Prot | EmulateOnUD,       em_hypercall,   vmmcall),
        DIP(SrcNone | Prot | Priv,              vmload,         check_svme_pa),
        DIP(SrcNone | Prot | Priv,              vmsave,         check_svme_pa),
        DIP(SrcNone | Prot | Priv,              stgi,           check_svme),
@@ -4192,7 +4189,8 @@ static const struct opcode twobyte_table[256] = {
        N, N,
        G(BitOp, group8),
        F(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_btc),
-       F(DstReg | SrcMem | ModRM, em_bsf), F(DstReg | SrcMem | ModRM, em_bsr),
+       I(DstReg | SrcMem | ModRM, em_bsf_c),
+       I(DstReg | SrcMem | ModRM, em_bsr_c),
        D(DstReg | SrcMem8 | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
        /* 0xC0 - 0xC7 */
        F2bv(DstMem | SrcReg | ModRM | SrcWrite | Lock, em_xadd),
@@ -4759,9 +4757,9 @@ static bool string_insn_completed(struct x86_emulate_ctxt *ctxt)
        if (((ctxt->b == 0xa6) || (ctxt->b == 0xa7) ||
             (ctxt->b == 0xae) || (ctxt->b == 0xaf))
            && (((ctxt->rep_prefix == REPE_PREFIX) &&
-                ((ctxt->eflags & EFLG_ZF) == 0))
+                ((ctxt->eflags & X86_EFLAGS_ZF) == 0))
                || ((ctxt->rep_prefix == REPNE_PREFIX) &&
-                   ((ctxt->eflags & EFLG_ZF) == EFLG_ZF))))
+                   ((ctxt->eflags & X86_EFLAGS_ZF) == X86_EFLAGS_ZF))))
                return true;
 
        return false;
@@ -4913,7 +4911,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
                        /* All REP prefixes have the same first termination condition */
                        if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0) {
                                ctxt->eip = ctxt->_eip;
-                               ctxt->eflags &= ~EFLG_RF;
+                               ctxt->eflags &= ~X86_EFLAGS_RF;
                                goto done;
                        }
                }
@@ -4963,9 +4961,9 @@ special_insn:
        }
 
        if (ctxt->rep_prefix && (ctxt->d & String))
-               ctxt->eflags |= EFLG_RF;
+               ctxt->eflags |= X86_EFLAGS_RF;
        else
-               ctxt->eflags &= ~EFLG_RF;
+               ctxt->eflags &= ~X86_EFLAGS_RF;
 
        if (ctxt->execute) {
                if (ctxt->d & Fastop) {
@@ -5014,7 +5012,7 @@ special_insn:
                rc = emulate_int(ctxt, ctxt->src.val);
                break;
        case 0xce:              /* into */
-               if (ctxt->eflags & EFLG_OF)
+               if (ctxt->eflags & X86_EFLAGS_OF)
                        rc = emulate_int(ctxt, 4);
                break;
        case 0xe9: /* jmp rel */
@@ -5027,19 +5025,19 @@ special_insn:
                break;
        case 0xf5:      /* cmc */
                /* complement carry flag from eflags reg */
-               ctxt->eflags ^= EFLG_CF;
+               ctxt->eflags ^= X86_EFLAGS_CF;
                break;
        case 0xf8: /* clc */
-               ctxt->eflags &= ~EFLG_CF;
+               ctxt->eflags &= ~X86_EFLAGS_CF;
                break;
        case 0xf9: /* stc */
-               ctxt->eflags |= EFLG_CF;
+               ctxt->eflags |= X86_EFLAGS_CF;
                break;
        case 0xfc: /* cld */
-               ctxt->eflags &= ~EFLG_DF;
+               ctxt->eflags &= ~X86_EFLAGS_DF;
                break;
        case 0xfd: /* std */
-               ctxt->eflags |= EFLG_DF;
+               ctxt->eflags |= X86_EFLAGS_DF;
                break;
        default:
                goto cannot_emulate;
@@ -5100,7 +5098,7 @@ writeback:
                        }
                        goto done; /* skip rip writeback */
                }
-               ctxt->eflags &= ~EFLG_RF;
+               ctxt->eflags &= ~X86_EFLAGS_RF;
        }
 
        ctxt->eip = ctxt->_eip;
@@ -5137,8 +5135,7 @@ twobyte_insn:
        case 0x40 ... 0x4f:     /* cmov */
                if (test_cc(ctxt->b, ctxt->eflags))
                        ctxt->dst.val = ctxt->src.val;
-               else if (ctxt->mode != X86EMUL_MODE_PROT64 ||
-                        ctxt->op_bytes != 4)
+               else if (ctxt->op_bytes != 4)
                        ctxt->dst.type = OP_NONE; /* no writeback */
                break;
        case 0x80 ... 0x8f: /* jnz rel, etc*/
index 298781d4cfb44b7c6d6536d6d2779ada2eeb150a..4dce6f8b6129ebea2432840154cc97efd513947b 100644 (file)
@@ -443,7 +443,8 @@ static inline int pit_in_range(gpa_t addr)
                (addr < KVM_PIT_BASE_ADDRESS + KVM_PIT_MEM_LENGTH));
 }
 
-static int pit_ioport_write(struct kvm_io_device *this,
+static int pit_ioport_write(struct kvm_vcpu *vcpu,
+                               struct kvm_io_device *this,
                            gpa_t addr, int len, const void *data)
 {
        struct kvm_pit *pit = dev_to_pit(this);
@@ -519,7 +520,8 @@ static int pit_ioport_write(struct kvm_io_device *this,
        return 0;
 }
 
-static int pit_ioport_read(struct kvm_io_device *this,
+static int pit_ioport_read(struct kvm_vcpu *vcpu,
+                          struct kvm_io_device *this,
                           gpa_t addr, int len, void *data)
 {
        struct kvm_pit *pit = dev_to_pit(this);
@@ -589,7 +591,8 @@ static int pit_ioport_read(struct kvm_io_device *this,
        return 0;
 }
 
-static int speaker_ioport_write(struct kvm_io_device *this,
+static int speaker_ioport_write(struct kvm_vcpu *vcpu,
+                               struct kvm_io_device *this,
                                gpa_t addr, int len, const void *data)
 {
        struct kvm_pit *pit = speaker_to_pit(this);
@@ -606,8 +609,9 @@ static int speaker_ioport_write(struct kvm_io_device *this,
        return 0;
 }
 
-static int speaker_ioport_read(struct kvm_io_device *this,
-                              gpa_t addr, int len, void *data)
+static int speaker_ioport_read(struct kvm_vcpu *vcpu,
+                                  struct kvm_io_device *this,
+                                  gpa_t addr, int len, void *data)
 {
        struct kvm_pit *pit = speaker_to_pit(this);
        struct kvm_kpit_state *pit_state = &pit->pit_state;
index dd1b16b611b0ae6c9d2386a7e690e56a774f0b74..c84990b42b5b189550eecc904f781c0e3ecadf3d 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/kthread.h>
 
-#include "iodev.h"
+#include <kvm/iodev.h>
 
 struct kvm_kpit_channel_state {
        u32 count; /* can be 65536 */
index 9541ba34126b90123ddfe383453145ddfcf789c4..fef922ff263589de97348e76ee4faeaeb5aaeef2 100644 (file)
@@ -529,42 +529,42 @@ static int picdev_read(struct kvm_pic *s,
        return 0;
 }
 
-static int picdev_master_write(struct kvm_io_device *dev,
+static int picdev_master_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
                               gpa_t addr, int len, const void *val)
 {
        return picdev_write(container_of(dev, struct kvm_pic, dev_master),
                            addr, len, val);
 }
 
-static int picdev_master_read(struct kvm_io_device *dev,
+static int picdev_master_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
                              gpa_t addr, int len, void *val)
 {
        return picdev_read(container_of(dev, struct kvm_pic, dev_master),
                            addr, len, val);
 }
 
-static int picdev_slave_write(struct kvm_io_device *dev,
+static int picdev_slave_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
                              gpa_t addr, int len, const void *val)
 {
        return picdev_write(container_of(dev, struct kvm_pic, dev_slave),
                            addr, len, val);
 }
 
-static int picdev_slave_read(struct kvm_io_device *dev,
+static int picdev_slave_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
                             gpa_t addr, int len, void *val)
 {
        return picdev_read(container_of(dev, struct kvm_pic, dev_slave),
                            addr, len, val);
 }
 
-static int picdev_eclr_write(struct kvm_io_device *dev,
+static int picdev_eclr_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
                             gpa_t addr, int len, const void *val)
 {
        return picdev_write(container_of(dev, struct kvm_pic, dev_eclr),
                            addr, len, val);
 }
 
-static int picdev_eclr_read(struct kvm_io_device *dev,
+static int picdev_eclr_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
                            gpa_t addr, int len, void *val)
 {
        return picdev_read(container_of(dev, struct kvm_pic, dev_eclr),
index 46d4449772bc714daa658ea6424fb45659095c70..28146f03c51421ce12f728d69613ded0a65699fd 100644 (file)
@@ -206,6 +206,8 @@ static int ioapic_set_irq(struct kvm_ioapic *ioapic, unsigned int irq,
 
        old_irr = ioapic->irr;
        ioapic->irr |= mask;
+       if (edge)
+               ioapic->irr_delivered &= ~mask;
        if ((edge && old_irr == ioapic->irr) ||
            (!edge && entry.fields.remote_irr)) {
                ret = 0;
@@ -349,7 +351,7 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status)
        irqe.shorthand = 0;
 
        if (irqe.trig_mode == IOAPIC_EDGE_TRIG)
-               ioapic->irr &= ~(1 << irq);
+               ioapic->irr_delivered |= 1 << irq;
 
        if (irq == RTC_GSI && line_status) {
                /*
@@ -473,13 +475,6 @@ static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu,
        }
 }
 
-bool kvm_ioapic_handles_vector(struct kvm *kvm, int vector)
-{
-       struct kvm_ioapic *ioapic = kvm->arch.vioapic;
-       smp_rmb();
-       return test_bit(vector, ioapic->handled_vectors);
-}
-
 void kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu, int vector, int trigger_mode)
 {
        struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic;
@@ -500,8 +495,8 @@ static inline int ioapic_in_range(struct kvm_ioapic *ioapic, gpa_t addr)
                 (addr < ioapic->base_address + IOAPIC_MEM_LENGTH)));
 }
 
-static int ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len,
-                           void *val)
+static int ioapic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
+                               gpa_t addr, int len, void *val)
 {
        struct kvm_ioapic *ioapic = to_ioapic(this);
        u32 result;
@@ -543,8 +538,8 @@ static int ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len,
        return 0;
 }
 
-static int ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len,
-                            const void *val)
+static int ioapic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
+                                gpa_t addr, int len, const void *val)
 {
        struct kvm_ioapic *ioapic = to_ioapic(this);
        u32 data;
@@ -599,6 +594,7 @@ static void kvm_ioapic_reset(struct kvm_ioapic *ioapic)
        ioapic->base_address = IOAPIC_DEFAULT_BASE_ADDRESS;
        ioapic->ioregsel = 0;
        ioapic->irr = 0;
+       ioapic->irr_delivered = 0;
        ioapic->id = 0;
        memset(ioapic->irq_eoi, 0x00, IOAPIC_NUM_PINS);
        rtc_irq_eoi_tracking_reset(ioapic);
@@ -656,6 +652,7 @@ int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)
 
        spin_lock(&ioapic->lock);
        memcpy(state, ioapic, sizeof(struct kvm_ioapic_state));
+       state->irr &= ~ioapic->irr_delivered;
        spin_unlock(&ioapic->lock);
        return 0;
 }
@@ -669,6 +666,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)
        spin_lock(&ioapic->lock);
        memcpy(ioapic, state, sizeof(struct kvm_ioapic_state));
        ioapic->irr = 0;
+       ioapic->irr_delivered = 0;
        update_handled_vectors(ioapic);
        kvm_vcpu_request_scan_ioapic(kvm);
        kvm_ioapic_inject_all(ioapic, state->irr);
index c2e36d934af4d96ffceb2f1edb78601a2a848f67..ca0b0b4e625603687bbbe0343ddc0feb11dadbd7 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/kvm_host.h>
 
-#include "iodev.h"
+#include <kvm/iodev.h>
 
 struct kvm;
 struct kvm_vcpu;
@@ -77,6 +77,7 @@ struct kvm_ioapic {
        struct rtc_status rtc_status;
        struct delayed_work eoi_inject;
        u32 irq_eoi[IOAPIC_NUM_PINS];
+       u32 irr_delivered;
 };
 
 #ifdef DEBUG
@@ -97,13 +98,19 @@ static inline struct kvm_ioapic *ioapic_irqchip(struct kvm *kvm)
        return kvm->arch.vioapic;
 }
 
+static inline bool kvm_ioapic_handles_vector(struct kvm *kvm, int vector)
+{
+       struct kvm_ioapic *ioapic = kvm->arch.vioapic;
+       smp_rmb();
+       return test_bit(vector, ioapic->handled_vectors);
+}
+
 void kvm_rtc_eoi_tracking_restore_one(struct kvm_vcpu *vcpu);
 bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
                int short_hand, unsigned int dest, int dest_mode);
 int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2);
 void kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu, int vector,
                        int trigger_mode);
-bool kvm_ioapic_handles_vector(struct kvm *kvm, int vector);
 int kvm_ioapic_init(struct kvm *kvm);
 void kvm_ioapic_destroy(struct kvm *kvm);
 int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int irq_source_id,
index 2d03568e9498356716b7504c195c71a912819f4d..ad68c73008c57f0c1926f0cec9e83f79fe070252 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/kvm_host.h>
 #include <linux/spinlock.h>
 
-#include "iodev.h"
+#include <kvm/iodev.h>
 #include "ioapic.h"
 #include "lapic.h"
 
index 4ee827d7bf36f730c25d358f709aa99cda93260a..d67206a7b99a689a4d7361de8bd8fc1b9ab02c1a 100644 (file)
@@ -133,6 +133,28 @@ static inline int kvm_apic_id(struct kvm_lapic *apic)
        return (kvm_apic_get_reg(apic, APIC_ID) >> 24) & 0xff;
 }
 
+/* The logical map is definitely wrong if we have multiple
+ * modes at the same time.  (Physical map is always right.)
+ */
+static inline bool kvm_apic_logical_map_valid(struct kvm_apic_map *map)
+{
+       return !(map->mode & (map->mode - 1));
+}
+
+static inline void
+apic_logical_id(struct kvm_apic_map *map, u32 dest_id, u16 *cid, u16 *lid)
+{
+       unsigned lid_bits;
+
+       BUILD_BUG_ON(KVM_APIC_MODE_XAPIC_CLUSTER !=  4);
+       BUILD_BUG_ON(KVM_APIC_MODE_XAPIC_FLAT    !=  8);
+       BUILD_BUG_ON(KVM_APIC_MODE_X2APIC        != 16);
+       lid_bits = map->mode;
+
+       *cid = dest_id >> lid_bits;
+       *lid = dest_id & ((1 << lid_bits) - 1);
+}
+
 static void recalculate_apic_map(struct kvm *kvm)
 {
        struct kvm_apic_map *new, *old = NULL;
@@ -146,48 +168,6 @@ static void recalculate_apic_map(struct kvm *kvm)
        if (!new)
                goto out;
 
-       new->ldr_bits = 8;
-       /* flat mode is default */
-       new->cid_shift = 8;
-       new->cid_mask = 0;
-       new->lid_mask = 0xff;
-       new->broadcast = APIC_BROADCAST;
-
-       kvm_for_each_vcpu(i, vcpu, kvm) {
-               struct kvm_lapic *apic = vcpu->arch.apic;
-
-               if (!kvm_apic_present(vcpu))
-                       continue;
-
-               if (apic_x2apic_mode(apic)) {
-                       new->ldr_bits = 32;
-                       new->cid_shift = 16;
-                       new->cid_mask = new->lid_mask = 0xffff;
-                       new->broadcast = X2APIC_BROADCAST;
-               } else if (kvm_apic_get_reg(apic, APIC_LDR)) {
-                       if (kvm_apic_get_reg(apic, APIC_DFR) ==
-                                                       APIC_DFR_CLUSTER) {
-                               new->cid_shift = 4;
-                               new->cid_mask = 0xf;
-                               new->lid_mask = 0xf;
-                       } else {
-                               new->cid_shift = 8;
-                               new->cid_mask = 0;
-                               new->lid_mask = 0xff;
-                       }
-               }
-
-               /*
-                * All APICs have to be configured in the same mode by an OS.
-                * We take advatage of this while building logical id loockup
-                * table. After reset APICs are in software disabled mode, so if
-                * we find apic with different setting we assume this is the mode
-                * OS wants all apics to be in; build lookup table accordingly.
-                */
-               if (kvm_apic_sw_enabled(apic))
-                       break;
-       }
-
        kvm_for_each_vcpu(i, vcpu, kvm) {
                struct kvm_lapic *apic = vcpu->arch.apic;
                u16 cid, lid;
@@ -198,11 +178,25 @@ static void recalculate_apic_map(struct kvm *kvm)
 
                aid = kvm_apic_id(apic);
                ldr = kvm_apic_get_reg(apic, APIC_LDR);
-               cid = apic_cluster_id(new, ldr);
-               lid = apic_logical_id(new, ldr);
 
                if (aid < ARRAY_SIZE(new->phys_map))
                        new->phys_map[aid] = apic;
+
+               if (apic_x2apic_mode(apic)) {
+                       new->mode |= KVM_APIC_MODE_X2APIC;
+               } else if (ldr) {
+                       ldr = GET_APIC_LOGICAL_ID(ldr);
+                       if (kvm_apic_get_reg(apic, APIC_DFR) == APIC_DFR_FLAT)
+                               new->mode |= KVM_APIC_MODE_XAPIC_FLAT;
+                       else
+                               new->mode |= KVM_APIC_MODE_XAPIC_CLUSTER;
+               }
+
+               if (!kvm_apic_logical_map_valid(new))
+                       continue;
+
+               apic_logical_id(new, ldr, &cid, &lid);
+
                if (lid && cid < ARRAY_SIZE(new->logical_map))
                        new->logical_map[cid][ffs(lid) - 1] = apic;
        }
@@ -588,15 +582,23 @@ static void apic_set_tpr(struct kvm_lapic *apic, u32 tpr)
        apic_update_ppr(apic);
 }
 
-static bool kvm_apic_broadcast(struct kvm_lapic *apic, u32 dest)
+static bool kvm_apic_broadcast(struct kvm_lapic *apic, u32 mda)
 {
-       return dest == (apic_x2apic_mode(apic) ?
-                       X2APIC_BROADCAST : APIC_BROADCAST);
+       if (apic_x2apic_mode(apic))
+               return mda == X2APIC_BROADCAST;
+
+       return GET_APIC_DEST_FIELD(mda) == APIC_BROADCAST;
 }
 
-static bool kvm_apic_match_physical_addr(struct kvm_lapic *apic, u32 dest)
+static bool kvm_apic_match_physical_addr(struct kvm_lapic *apic, u32 mda)
 {
-       return kvm_apic_id(apic) == dest || kvm_apic_broadcast(apic, dest);
+       if (kvm_apic_broadcast(apic, mda))
+               return true;
+
+       if (apic_x2apic_mode(apic))
+               return mda == kvm_apic_id(apic);
+
+       return mda == SET_APIC_DEST_FIELD(kvm_apic_id(apic));
 }
 
 static bool kvm_apic_match_logical_addr(struct kvm_lapic *apic, u32 mda)
@@ -613,6 +615,7 @@ static bool kvm_apic_match_logical_addr(struct kvm_lapic *apic, u32 mda)
                       && (logical_id & mda & 0xffff) != 0;
 
        logical_id = GET_APIC_LOGICAL_ID(logical_id);
+       mda = GET_APIC_DEST_FIELD(mda);
 
        switch (kvm_apic_get_reg(apic, APIC_DFR)) {
        case APIC_DFR_FLAT:
@@ -627,10 +630,27 @@ static bool kvm_apic_match_logical_addr(struct kvm_lapic *apic, u32 mda)
        }
 }
 
+/* KVM APIC implementation has two quirks
+ *  - dest always begins at 0 while xAPIC MDA has offset 24,
+ *  - IOxAPIC messages have to be delivered (directly) to x2APIC.
+ */
+static u32 kvm_apic_mda(unsigned int dest_id, struct kvm_lapic *source,
+                                              struct kvm_lapic *target)
+{
+       bool ipi = source != NULL;
+       bool x2apic_mda = apic_x2apic_mode(ipi ? source : target);
+
+       if (!ipi && dest_id == APIC_BROADCAST && x2apic_mda)
+               return X2APIC_BROADCAST;
+
+       return x2apic_mda ? dest_id : SET_APIC_DEST_FIELD(dest_id);
+}
+
 bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
                           int short_hand, unsigned int dest, int dest_mode)
 {
        struct kvm_lapic *target = vcpu->arch.apic;
+       u32 mda = kvm_apic_mda(dest, source, target);
 
        apic_debug("target %p, source %p, dest 0x%x, "
                   "dest_mode 0x%x, short_hand 0x%x\n",
@@ -640,9 +660,9 @@ bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
        switch (short_hand) {
        case APIC_DEST_NOSHORT:
                if (dest_mode == APIC_DEST_PHYSICAL)
-                       return kvm_apic_match_physical_addr(target, dest);
+                       return kvm_apic_match_physical_addr(target, mda);
                else
-                       return kvm_apic_match_logical_addr(target, dest);
+                       return kvm_apic_match_logical_addr(target, mda);
        case APIC_DEST_SELF:
                return target == source;
        case APIC_DEST_ALLINC:
@@ -664,6 +684,7 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
        struct kvm_lapic **dst;
        int i;
        bool ret = false;
+       bool x2apic_ipi = src && apic_x2apic_mode(src);
 
        *r = -1;
 
@@ -675,15 +696,15 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
        if (irq->shorthand)
                return false;
 
+       if (irq->dest_id == (x2apic_ipi ? X2APIC_BROADCAST : APIC_BROADCAST))
+               return false;
+
        rcu_read_lock();
        map = rcu_dereference(kvm->arch.apic_map);
 
        if (!map)
                goto out;
 
-       if (irq->dest_id == map->broadcast)
-               goto out;
-
        ret = true;
 
        if (irq->dest_mode == APIC_DEST_PHYSICAL) {
@@ -692,16 +713,20 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
 
                dst = &map->phys_map[irq->dest_id];
        } else {
-               u32 mda = irq->dest_id << (32 - map->ldr_bits);
-               u16 cid = apic_cluster_id(map, mda);
+               u16 cid;
+
+               if (!kvm_apic_logical_map_valid(map)) {
+                       ret = false;
+                       goto out;
+               }
+
+               apic_logical_id(map, irq->dest_id, &cid, (u16 *)&bitmap);
 
                if (cid >= ARRAY_SIZE(map->logical_map))
                        goto out;
 
                dst = map->logical_map[cid];
 
-               bitmap = apic_logical_id(map, mda);
-
                if (irq->delivery_mode == APIC_DM_LOWEST) {
                        int l = -1;
                        for_each_set_bit(i, &bitmap, 16) {
@@ -1037,7 +1062,7 @@ static int apic_mmio_in_range(struct kvm_lapic *apic, gpa_t addr)
            addr < apic->base_address + LAPIC_MMIO_LENGTH;
 }
 
-static int apic_mmio_read(struct kvm_io_device *this,
+static int apic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
                           gpa_t address, int len, void *data)
 {
        struct kvm_lapic *apic = to_lapic(this);
@@ -1357,7 +1382,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
        return ret;
 }
 
-static int apic_mmio_write(struct kvm_io_device *this,
+static int apic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
                            gpa_t address, int len, const void *data)
 {
        struct kvm_lapic *apic = to_lapic(this);
@@ -1497,8 +1522,6 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
                return;
        }
 
-       if (!kvm_vcpu_is_bsp(apic->vcpu))
-               value &= ~MSR_IA32_APICBASE_BSP;
        vcpu->arch.apic_base = value;
 
        /* update jump label if enable bit changes */
index 0bc6c656625b8377df4ed6ed18da0ece953cfc38..9d28383fc1e70cc3437ae2eb062ff9433c659f96 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __KVM_X86_LAPIC_H
 #define __KVM_X86_LAPIC_H
 
-#include "iodev.h"
+#include <kvm/iodev.h>
 
 #include <linux/kvm_host.h>
 
@@ -148,21 +148,6 @@ static inline bool kvm_apic_vid_enabled(struct kvm *kvm)
        return kvm_x86_ops->vm_has_apicv(kvm);
 }
 
-static inline u16 apic_cluster_id(struct kvm_apic_map *map, u32 ldr)
-{
-       u16 cid;
-       ldr >>= 32 - map->ldr_bits;
-       cid = (ldr >> map->cid_shift) & map->cid_mask;
-
-       return cid;
-}
-
-static inline u16 apic_logical_id(struct kvm_apic_map *map, u32 ldr)
-{
-       ldr >>= (32 - map->ldr_bits);
-       return ldr & map->lid_mask;
-}
-
 static inline bool kvm_apic_has_events(struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.apic->pending_events;
index cee759299a356dd720a22095ea4cb684c89fcdd3..146f295ee32214a6f4ad40a58e53b61a3d1fa06d 100644 (file)
@@ -4465,6 +4465,79 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
                kvm_flush_remote_tlbs(kvm);
 }
 
+static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
+               unsigned long *rmapp)
+{
+       u64 *sptep;
+       struct rmap_iterator iter;
+       int need_tlb_flush = 0;
+       pfn_t pfn;
+       struct kvm_mmu_page *sp;
+
+       for (sptep = rmap_get_first(*rmapp, &iter); sptep;) {
+               BUG_ON(!(*sptep & PT_PRESENT_MASK));
+
+               sp = page_header(__pa(sptep));
+               pfn = spte_to_pfn(*sptep);
+
+               /*
+                * Only EPT supported for now; otherwise, one would need to
+                * find out efficiently whether the guest page tables are
+                * also using huge pages.
+                */
+               if (sp->role.direct &&
+                       !kvm_is_reserved_pfn(pfn) &&
+                       PageTransCompound(pfn_to_page(pfn))) {
+                       drop_spte(kvm, sptep);
+                       sptep = rmap_get_first(*rmapp, &iter);
+                       need_tlb_flush = 1;
+               } else
+                       sptep = rmap_get_next(&iter);
+       }
+
+       return need_tlb_flush;
+}
+
+void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
+                       struct kvm_memory_slot *memslot)
+{
+       bool flush = false;
+       unsigned long *rmapp;
+       unsigned long last_index, index;
+       gfn_t gfn_start, gfn_end;
+
+       spin_lock(&kvm->mmu_lock);
+
+       gfn_start = memslot->base_gfn;
+       gfn_end = memslot->base_gfn + memslot->npages - 1;
+
+       if (gfn_start >= gfn_end)
+               goto out;
+
+       rmapp = memslot->arch.rmap[0];
+       last_index = gfn_to_index(gfn_end, memslot->base_gfn,
+                                       PT_PAGE_TABLE_LEVEL);
+
+       for (index = 0; index <= last_index; ++index, ++rmapp) {
+               if (*rmapp)
+                       flush |= kvm_mmu_zap_collapsible_spte(kvm, rmapp);
+
+               if (need_resched() || spin_needbreak(&kvm->mmu_lock)) {
+                       if (flush) {
+                               kvm_flush_remote_tlbs(kvm);
+                               flush = false;
+                       }
+                       cond_resched_lock(&kvm->mmu_lock);
+               }
+       }
+
+       if (flush)
+               kvm_flush_remote_tlbs(kvm);
+
+out:
+       spin_unlock(&kvm->mmu_lock);
+}
+
 void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
                                   struct kvm_memory_slot *memslot)
 {
index 8e6b7d869d2f7f34432a1f1685606eab7945561a..29fbf9dfdc549f47f1e189f58c5d5adfeb7a5fd1 100644 (file)
@@ -38,7 +38,7 @@ static struct kvm_arch_event_perf_mapping {
 };
 
 /* mapping between fixed pmc index and arch_events array */
-int fixed_pmc_events[] = {1, 0, 7};
+static int fixed_pmc_events[] = {1, 0, 7};
 
 static bool pmc_is_gp(struct kvm_pmc *pmc)
 {
index cc618c882f900ad21cb4de57d94daa91a5f4ec4c..ce741b8650f6ece694fb47e1750d153291a1803f 100644 (file)
@@ -1261,7 +1261,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
 
        svm->vcpu.arch.apic_base = APIC_DEFAULT_PHYS_BASE |
                                   MSR_IA32_APICBASE_ENABLE;
-       if (kvm_vcpu_is_bsp(&svm->vcpu))
+       if (kvm_vcpu_is_reset_bsp(&svm->vcpu))
                svm->vcpu.arch.apic_base |= MSR_IA32_APICBASE_BSP;
 
        svm_init_osvw(&svm->vcpu);
@@ -1929,14 +1929,12 @@ static int nop_on_interception(struct vcpu_svm *svm)
 static int halt_interception(struct vcpu_svm *svm)
 {
        svm->next_rip = kvm_rip_read(&svm->vcpu) + 1;
-       skip_emulated_instruction(&svm->vcpu);
        return kvm_emulate_halt(&svm->vcpu);
 }
 
 static int vmmcall_interception(struct vcpu_svm *svm)
 {
        svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
-       skip_emulated_instruction(&svm->vcpu);
        kvm_emulate_hypercall(&svm->vcpu);
        return 1;
 }
@@ -2757,11 +2755,11 @@ static int invlpga_interception(struct vcpu_svm *svm)
 {
        struct kvm_vcpu *vcpu = &svm->vcpu;
 
-       trace_kvm_invlpga(svm->vmcb->save.rip, vcpu->arch.regs[VCPU_REGS_RCX],
-                         vcpu->arch.regs[VCPU_REGS_RAX]);
+       trace_kvm_invlpga(svm->vmcb->save.rip, kvm_register_read(&svm->vcpu, VCPU_REGS_RCX),
+                         kvm_register_read(&svm->vcpu, VCPU_REGS_RAX));
 
        /* Let's treat INVLPGA the same as INVLPG (can be optimized!) */
-       kvm_mmu_invlpg(vcpu, vcpu->arch.regs[VCPU_REGS_RAX]);
+       kvm_mmu_invlpg(vcpu, kvm_register_read(&svm->vcpu, VCPU_REGS_RAX));
 
        svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
        skip_emulated_instruction(&svm->vcpu);
@@ -2770,12 +2768,18 @@ static int invlpga_interception(struct vcpu_svm *svm)
 
 static int skinit_interception(struct vcpu_svm *svm)
 {
-       trace_kvm_skinit(svm->vmcb->save.rip, svm->vcpu.arch.regs[VCPU_REGS_RAX]);
+       trace_kvm_skinit(svm->vmcb->save.rip, kvm_register_read(&svm->vcpu, VCPU_REGS_RAX));
 
        kvm_queue_exception(&svm->vcpu, UD_VECTOR);
        return 1;
 }
 
+static int wbinvd_interception(struct vcpu_svm *svm)
+{
+       kvm_emulate_wbinvd(&svm->vcpu);
+       return 1;
+}
+
 static int xsetbv_interception(struct vcpu_svm *svm)
 {
        u64 new_bv = kvm_read_edx_eax(&svm->vcpu);
@@ -2902,7 +2906,8 @@ static int rdpmc_interception(struct vcpu_svm *svm)
        return 1;
 }
 
-bool check_selective_cr0_intercepted(struct vcpu_svm *svm, unsigned long val)
+static bool check_selective_cr0_intercepted(struct vcpu_svm *svm,
+                                           unsigned long val)
 {
        unsigned long cr0 = svm->vcpu.arch.cr0;
        bool ret = false;
@@ -2940,7 +2945,10 @@ static int cr_interception(struct vcpu_svm *svm)
                return emulate_on_interception(svm);
 
        reg = svm->vmcb->control.exit_info_1 & SVM_EXITINFO_REG_MASK;
-       cr = svm->vmcb->control.exit_code - SVM_EXIT_READ_CR0;
+       if (svm->vmcb->control.exit_code == SVM_EXIT_CR0_SEL_WRITE)
+               cr = SVM_EXIT_WRITE_CR0 - SVM_EXIT_READ_CR0;
+       else
+               cr = svm->vmcb->control.exit_code - SVM_EXIT_READ_CR0;
 
        err = 0;
        if (cr >= 16) { /* mov to cr */
@@ -3133,7 +3141,7 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)
 
 static int rdmsr_interception(struct vcpu_svm *svm)
 {
-       u32 ecx = svm->vcpu.arch.regs[VCPU_REGS_RCX];
+       u32 ecx = kvm_register_read(&svm->vcpu, VCPU_REGS_RCX);
        u64 data;
 
        if (svm_get_msr(&svm->vcpu, ecx, &data)) {
@@ -3142,8 +3150,8 @@ static int rdmsr_interception(struct vcpu_svm *svm)
        } else {
                trace_kvm_msr_read(ecx, data);
 
-               svm->vcpu.arch.regs[VCPU_REGS_RAX] = data & 0xffffffff;
-               svm->vcpu.arch.regs[VCPU_REGS_RDX] = data >> 32;
+               kvm_register_write(&svm->vcpu, VCPU_REGS_RAX, data & 0xffffffff);
+               kvm_register_write(&svm->vcpu, VCPU_REGS_RDX, data >> 32);
                svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
                skip_emulated_instruction(&svm->vcpu);
        }
@@ -3246,9 +3254,8 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
 static int wrmsr_interception(struct vcpu_svm *svm)
 {
        struct msr_data msr;
-       u32 ecx = svm->vcpu.arch.regs[VCPU_REGS_RCX];
-       u64 data = (svm->vcpu.arch.regs[VCPU_REGS_RAX] & -1u)
-               | ((u64)(svm->vcpu.arch.regs[VCPU_REGS_RDX] & -1u) << 32);
+       u32 ecx = kvm_register_read(&svm->vcpu, VCPU_REGS_RCX);
+       u64 data = kvm_read_edx_eax(&svm->vcpu);
 
        msr.data = data;
        msr.index = ecx;
@@ -3325,7 +3332,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
        [SVM_EXIT_READ_CR3]                     = cr_interception,
        [SVM_EXIT_READ_CR4]                     = cr_interception,
        [SVM_EXIT_READ_CR8]                     = cr_interception,
-       [SVM_EXIT_CR0_SEL_WRITE]                = emulate_on_interception,
+       [SVM_EXIT_CR0_SEL_WRITE]                = cr_interception,
        [SVM_EXIT_WRITE_CR0]                    = cr_interception,
        [SVM_EXIT_WRITE_CR3]                    = cr_interception,
        [SVM_EXIT_WRITE_CR4]                    = cr_interception,
@@ -3376,7 +3383,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
        [SVM_EXIT_STGI]                         = stgi_interception,
        [SVM_EXIT_CLGI]                         = clgi_interception,
        [SVM_EXIT_SKINIT]                       = skinit_interception,
-       [SVM_EXIT_WBINVD]                       = emulate_on_interception,
+       [SVM_EXIT_WBINVD]                       = wbinvd_interception,
        [SVM_EXIT_MONITOR]                      = monitor_interception,
        [SVM_EXIT_MWAIT]                        = mwait_interception,
        [SVM_EXIT_XSETBV]                       = xsetbv_interception,
@@ -3555,7 +3562,7 @@ static int handle_exit(struct kvm_vcpu *vcpu)
 
        if (exit_code >= ARRAY_SIZE(svm_exit_handlers)
            || !svm_exit_handlers[exit_code]) {
-               WARN_ONCE(1, "vmx: unexpected exit reason 0x%x\n", exit_code);
+               WARN_ONCE(1, "svm: unexpected exit reason 0x%x\n", exit_code);
                kvm_queue_exception(vcpu, UD_VECTOR);
                return 1;
        }
index ae4f6d35d19c268315745741150dd6d1a7df5222..f5e8dce8046c56b5273e9aa043754f98a7dee7d7 100644 (file)
@@ -2470,6 +2470,7 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
        vmx->nested.nested_vmx_secondary_ctls_low = 0;
        vmx->nested.nested_vmx_secondary_ctls_high &=
                SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
+               SECONDARY_EXEC_RDTSCP |
                SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
                SECONDARY_EXEC_APIC_REGISTER_VIRT |
                SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
@@ -3268,8 +3269,8 @@ static void fix_pmode_seg(struct kvm_vcpu *vcpu, int seg,
                 * default value.
                 */
                if (seg == VCPU_SREG_CS || seg == VCPU_SREG_SS)
-                       save->selector &= ~SELECTOR_RPL_MASK;
-               save->dpl = save->selector & SELECTOR_RPL_MASK;
+                       save->selector &= ~SEGMENT_RPL_MASK;
+               save->dpl = save->selector & SEGMENT_RPL_MASK;
                save->s = 1;
        }
        vmx_set_segment(vcpu, save, seg);
@@ -3842,7 +3843,7 @@ static bool code_segment_valid(struct kvm_vcpu *vcpu)
        unsigned int cs_rpl;
 
        vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
-       cs_rpl = cs.selector & SELECTOR_RPL_MASK;
+       cs_rpl = cs.selector & SEGMENT_RPL_MASK;
 
        if (cs.unusable)
                return false;
@@ -3870,7 +3871,7 @@ static bool stack_segment_valid(struct kvm_vcpu *vcpu)
        unsigned int ss_rpl;
 
        vmx_get_segment(vcpu, &ss, VCPU_SREG_SS);
-       ss_rpl = ss.selector & SELECTOR_RPL_MASK;
+       ss_rpl = ss.selector & SEGMENT_RPL_MASK;
 
        if (ss.unusable)
                return true;
@@ -3892,7 +3893,7 @@ static bool data_segment_valid(struct kvm_vcpu *vcpu, int seg)
        unsigned int rpl;
 
        vmx_get_segment(vcpu, &var, seg);
-       rpl = var.selector & SELECTOR_RPL_MASK;
+       rpl = var.selector & SEGMENT_RPL_MASK;
 
        if (var.unusable)
                return true;
@@ -3919,7 +3920,7 @@ static bool tr_valid(struct kvm_vcpu *vcpu)
 
        if (tr.unusable)
                return false;
-       if (tr.selector & SELECTOR_TI_MASK)     /* TI = 1 */
+       if (tr.selector & SEGMENT_TI_MASK)      /* TI = 1 */
                return false;
        if (tr.type != 3 && tr.type != 11) /* TODO: Check if guest is in IA32e mode */
                return false;
@@ -3937,7 +3938,7 @@ static bool ldtr_valid(struct kvm_vcpu *vcpu)
 
        if (ldtr.unusable)
                return true;
-       if (ldtr.selector & SELECTOR_TI_MASK)   /* TI = 1 */
+       if (ldtr.selector & SEGMENT_TI_MASK)    /* TI = 1 */
                return false;
        if (ldtr.type != 2)
                return false;
@@ -3954,8 +3955,8 @@ static bool cs_ss_rpl_check(struct kvm_vcpu *vcpu)
        vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
        vmx_get_segment(vcpu, &ss, VCPU_SREG_SS);
 
-       return ((cs.selector & SELECTOR_RPL_MASK) ==
-                (ss.selector & SELECTOR_RPL_MASK));
+       return ((cs.selector & SEGMENT_RPL_MASK) ==
+                (ss.selector & SEGMENT_RPL_MASK));
 }
 
 /*
@@ -4711,7 +4712,7 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu)
        vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
        kvm_set_cr8(&vmx->vcpu, 0);
        apic_base_msr.data = APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE;
-       if (kvm_vcpu_is_bsp(&vmx->vcpu))
+       if (kvm_vcpu_is_reset_bsp(&vmx->vcpu))
                apic_base_msr.data |= MSR_IA32_APICBASE_BSP;
        apic_base_msr.host_initiated = true;
        kvm_set_apic_base(&vmx->vcpu, &apic_base_msr);
@@ -5006,7 +5007,7 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
                if (emulate_instruction(vcpu, 0) == EMULATE_DONE) {
                        if (vcpu->arch.halt_request) {
                                vcpu->arch.halt_request = 0;
-                               return kvm_emulate_halt(vcpu);
+                               return kvm_vcpu_halt(vcpu);
                        }
                        return 1;
                }
@@ -5071,6 +5072,10 @@ static int handle_exception(struct kvm_vcpu *vcpu)
        }
 
        if (is_invalid_opcode(intr_info)) {
+               if (is_guest_mode(vcpu)) {
+                       kvm_queue_exception(vcpu, UD_VECTOR);
+                       return 1;
+               }
                er = emulate_instruction(vcpu, EMULTYPE_TRAP_UD);
                if (er != EMULATE_DONE)
                        kvm_queue_exception(vcpu, UD_VECTOR);
@@ -5090,9 +5095,10 @@ static int handle_exception(struct kvm_vcpu *vcpu)
            !(is_page_fault(intr_info) && !(error_code & PFERR_RSVD_MASK))) {
                vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
                vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_SIMUL_EX;
-               vcpu->run->internal.ndata = 2;
+               vcpu->run->internal.ndata = 3;
                vcpu->run->internal.data[0] = vect_info;
                vcpu->run->internal.data[1] = intr_info;
+               vcpu->run->internal.data[2] = error_code;
                return 0;
        }
 
@@ -5533,13 +5539,11 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu)
 
 static int handle_halt(struct kvm_vcpu *vcpu)
 {
-       skip_emulated_instruction(vcpu);
        return kvm_emulate_halt(vcpu);
 }
 
 static int handle_vmcall(struct kvm_vcpu *vcpu)
 {
-       skip_emulated_instruction(vcpu);
        kvm_emulate_hypercall(vcpu);
        return 1;
 }
@@ -5570,7 +5574,6 @@ static int handle_rdpmc(struct kvm_vcpu *vcpu)
 
 static int handle_wbinvd(struct kvm_vcpu *vcpu)
 {
-       skip_emulated_instruction(vcpu);
        kvm_emulate_wbinvd(vcpu);
        return 1;
 }
@@ -5828,7 +5831,7 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
        gpa_t gpa;
 
        gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
-       if (!kvm_io_bus_write(vcpu->kvm, KVM_FAST_MMIO_BUS, gpa, 0, NULL)) {
+       if (!kvm_io_bus_write(vcpu, KVM_FAST_MMIO_BUS, gpa, 0, NULL)) {
                skip_emulated_instruction(vcpu);
                return 1;
        }
@@ -5909,7 +5912,7 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
 
                if (vcpu->arch.halt_request) {
                        vcpu->arch.halt_request = 0;
-                       ret = kvm_emulate_halt(vcpu);
+                       ret = kvm_vcpu_halt(vcpu);
                        goto out;
                }
 
@@ -7318,21 +7321,21 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
                else if (port < 0x10000)
                        bitmap = vmcs12->io_bitmap_b;
                else
-                       return 1;
+                       return true;
                bitmap += (port & 0x7fff) / 8;
 
                if (last_bitmap != bitmap)
                        if (kvm_read_guest(vcpu->kvm, bitmap, &b, 1))
-                               return 1;
+                               return true;
                if (b & (1 << (port & 7)))
-                       return 1;
+                       return true;
 
                port++;
                size--;
                last_bitmap = bitmap;
        }
 
-       return 0;
+       return false;
 }
 
 /*
@@ -7348,7 +7351,7 @@ static bool nested_vmx_exit_handled_msr(struct kvm_vcpu *vcpu,
        gpa_t bitmap;
 
        if (!nested_cpu_has(vmcs12, CPU_BASED_USE_MSR_BITMAPS))
-               return 1;
+               return true;
 
        /*
         * The MSR_BITMAP page is divided into four 1024-byte bitmaps,
@@ -7367,10 +7370,10 @@ static bool nested_vmx_exit_handled_msr(struct kvm_vcpu *vcpu,
        if (msr_index < 1024*8) {
                unsigned char b;
                if (kvm_read_guest(vcpu->kvm, bitmap + msr_index/8, &b, 1))
-                       return 1;
+                       return true;
                return 1 & (b >> (msr_index & 7));
        } else
-               return 1; /* let L1 handle the wrong parameter */
+               return true; /* let L1 handle the wrong parameter */
 }
 
 /*
@@ -7392,7 +7395,7 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
                case 0:
                        if (vmcs12->cr0_guest_host_mask &
                            (val ^ vmcs12->cr0_read_shadow))
-                               return 1;
+                               return true;
                        break;
                case 3:
                        if ((vmcs12->cr3_target_count >= 1 &&
@@ -7403,37 +7406,37 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
                                        vmcs12->cr3_target_value2 == val) ||
                                (vmcs12->cr3_target_count >= 4 &&
                                        vmcs12->cr3_target_value3 == val))
-                               return 0;
+                               return false;
                        if (nested_cpu_has(vmcs12, CPU_BASED_CR3_LOAD_EXITING))
-                               return 1;
+                               return true;
                        break;
                case 4:
                        if (vmcs12->cr4_guest_host_mask &
                            (vmcs12->cr4_read_shadow ^ val))
-                               return 1;
+                               return true;
                        break;
                case 8:
                        if (nested_cpu_has(vmcs12, CPU_BASED_CR8_LOAD_EXITING))
-                               return 1;
+                               return true;
                        break;
                }
                break;
        case 2: /* clts */
                if ((vmcs12->cr0_guest_host_mask & X86_CR0_TS) &&
                    (vmcs12->cr0_read_shadow & X86_CR0_TS))
-                       return 1;
+                       return true;
                break;
        case 1: /* mov from cr */
                switch (cr) {
                case 3:
                        if (vmcs12->cpu_based_vm_exec_control &
                            CPU_BASED_CR3_STORE_EXITING)
-                               return 1;
+                               return true;
                        break;
                case 8:
                        if (vmcs12->cpu_based_vm_exec_control &
                            CPU_BASED_CR8_STORE_EXITING)
-                               return 1;
+                               return true;
                        break;
                }
                break;
@@ -7444,14 +7447,14 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
                 */
                if (vmcs12->cr0_guest_host_mask & 0xe &
                    (val ^ vmcs12->cr0_read_shadow))
-                       return 1;
+                       return true;
                if ((vmcs12->cr0_guest_host_mask & 0x1) &&
                    !(vmcs12->cr0_read_shadow & 0x1) &&
                    (val & 0x1))
-                       return 1;
+                       return true;
                break;
        }
-       return 0;
+       return false;
 }
 
 /*
@@ -7474,48 +7477,48 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
                                KVM_ISA_VMX);
 
        if (vmx->nested.nested_run_pending)
-               return 0;
+               return false;
 
        if (unlikely(vmx->fail)) {
                pr_info_ratelimited("%s failed vm entry %x\n", __func__,
                                    vmcs_read32(VM_INSTRUCTION_ERROR));
-               return 1;
+               return true;
        }
 
        switch (exit_reason) {
        case EXIT_REASON_EXCEPTION_NMI:
                if (!is_exception(intr_info))
-                       return 0;
+                       return false;
                else if (is_page_fault(intr_info))
                        return enable_ept;
                else if (is_no_device(intr_info) &&
                         !(vmcs12->guest_cr0 & X86_CR0_TS))
-                       return 0;
+                       return false;
                return vmcs12->exception_bitmap &
                                (1u << (intr_info & INTR_INFO_VECTOR_MASK));
        case EXIT_REASON_EXTERNAL_INTERRUPT:
-               return 0;
+               return false;
        case EXIT_REASON_TRIPLE_FAULT:
-               return 1;
+               return true;
        case EXIT_REASON_PENDING_INTERRUPT:
                return nested_cpu_has(vmcs12, CPU_BASED_VIRTUAL_INTR_PENDING);
        case EXIT_REASON_NMI_WINDOW:
                return nested_cpu_has(vmcs12, CPU_BASED_VIRTUAL_NMI_PENDING);
        case EXIT_REASON_TASK_SWITCH:
-               return 1;
+               return true;
        case EXIT_REASON_CPUID:
                if (kvm_register_read(vcpu, VCPU_REGS_RAX) == 0xa)
-                       return 0;
-               return 1;
+                       return false;
+               return true;
        case EXIT_REASON_HLT:
                return nested_cpu_has(vmcs12, CPU_BASED_HLT_EXITING);
        case EXIT_REASON_INVD:
-               return 1;
+               return true;
        case EXIT_REASON_INVLPG:
                return nested_cpu_has(vmcs12, CPU_BASED_INVLPG_EXITING);
        case EXIT_REASON_RDPMC:
                return nested_cpu_has(vmcs12, CPU_BASED_RDPMC_EXITING);
-       case EXIT_REASON_RDTSC:
+       case EXIT_REASON_RDTSC: case EXIT_REASON_RDTSCP:
                return nested_cpu_has(vmcs12, CPU_BASED_RDTSC_EXITING);
        case EXIT_REASON_VMCALL: case EXIT_REASON_VMCLEAR:
        case EXIT_REASON_VMLAUNCH: case EXIT_REASON_VMPTRLD:
@@ -7527,7 +7530,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
                 * VMX instructions trap unconditionally. This allows L1 to
                 * emulate them for its L2 guest, i.e., allows 3-level nesting!
                 */
-               return 1;
+               return true;
        case EXIT_REASON_CR_ACCESS:
                return nested_vmx_exit_handled_cr(vcpu, vmcs12);
        case EXIT_REASON_DR_ACCESS:
@@ -7538,7 +7541,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
        case EXIT_REASON_MSR_WRITE:
                return nested_vmx_exit_handled_msr(vcpu, vmcs12, exit_reason);
        case EXIT_REASON_INVALID_STATE:
-               return 1;
+               return true;
        case EXIT_REASON_MWAIT_INSTRUCTION:
                return nested_cpu_has(vmcs12, CPU_BASED_MWAIT_EXITING);
        case EXIT_REASON_MONITOR_INSTRUCTION:
@@ -7548,7 +7551,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
                        nested_cpu_has2(vmcs12,
                                SECONDARY_EXEC_PAUSE_LOOP_EXITING);
        case EXIT_REASON_MCE_DURING_VMENTRY:
-               return 0;
+               return false;
        case EXIT_REASON_TPR_BELOW_THRESHOLD:
                return nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW);
        case EXIT_REASON_APIC_ACCESS:
@@ -7557,7 +7560,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
        case EXIT_REASON_APIC_WRITE:
        case EXIT_REASON_EOI_INDUCED:
                /* apic_write and eoi_induced should exit unconditionally. */
-               return 1;
+               return true;
        case EXIT_REASON_EPT_VIOLATION:
                /*
                 * L0 always deals with the EPT violation. If nested EPT is
@@ -7565,7 +7568,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
                 * missing in the guest EPT table (EPT12), the EPT violation
                 * will be injected with nested_ept_inject_page_fault()
                 */
-               return 0;
+               return false;
        case EXIT_REASON_EPT_MISCONFIG:
                /*
                 * L2 never uses directly L1's EPT, but rather L0's own EPT
@@ -7573,11 +7576,11 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
                 * (EPT on EPT). So any problems with the structure of the
                 * table is L0's fault.
                 */
-               return 0;
+               return false;
        case EXIT_REASON_WBINVD:
                return nested_cpu_has2(vmcs12, SECONDARY_EXEC_WBINVD_EXITING);
        case EXIT_REASON_XSETBV:
-               return 1;
+               return true;
        case EXIT_REASON_XSAVES: case EXIT_REASON_XRSTORS:
                /*
                 * This should never happen, since it is not possible to
@@ -7587,7 +7590,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
                 */
                return nested_cpu_has2(vmcs12, SECONDARY_EXEC_XSAVES);
        default:
-               return 1;
+               return true;
        }
 }
 
@@ -8522,6 +8525,9 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
                                                exec_control);
                        }
                }
+               if (nested && !vmx->rdtscp_enabled)
+                       vmx->nested.nested_vmx_secondary_ctls_high &=
+                               ~SECONDARY_EXEC_RDTSCP;
        }
 
        /* Exposing INVPCID only when PCID is exposed */
@@ -8622,10 +8628,11 @@ static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu,
                                        struct vmcs12 *vmcs12)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
+       int maxphyaddr = cpuid_maxphyaddr(vcpu);
 
        if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
-               /* TODO: Also verify bits beyond physical address width are 0 */
-               if (!PAGE_ALIGNED(vmcs12->apic_access_addr))
+               if (!PAGE_ALIGNED(vmcs12->apic_access_addr) ||
+                   vmcs12->apic_access_addr >> maxphyaddr)
                        return false;
 
                /*
@@ -8641,8 +8648,8 @@ static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu,
        }
 
        if (nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW)) {
-               /* TODO: Also verify bits beyond physical address width are 0 */
-               if (!PAGE_ALIGNED(vmcs12->virtual_apic_page_addr))
+               if (!PAGE_ALIGNED(vmcs12->virtual_apic_page_addr) ||
+                   vmcs12->virtual_apic_page_addr >> maxphyaddr)
                        return false;
 
                if (vmx->nested.virtual_apic_page) /* shouldn't happen */
@@ -8665,7 +8672,8 @@ static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu,
        }
 
        if (nested_cpu_has_posted_intr(vmcs12)) {
-               if (!IS_ALIGNED(vmcs12->posted_intr_desc_addr, 64))
+               if (!IS_ALIGNED(vmcs12->posted_intr_desc_addr, 64) ||
+                   vmcs12->posted_intr_desc_addr >> maxphyaddr)
                        return false;
 
                if (vmx->nested.pi_desc_page) { /* shouldn't happen */
@@ -8864,9 +8872,9 @@ static int nested_vmx_check_apicv_controls(struct kvm_vcpu *vcpu,
 
 static int nested_vmx_check_msr_switch(struct kvm_vcpu *vcpu,
                                       unsigned long count_field,
-                                      unsigned long addr_field,
-                                      int maxphyaddr)
+                                      unsigned long addr_field)
 {
+       int maxphyaddr;
        u64 count, addr;
 
        if (vmcs12_read_any(vcpu, count_field, &count) ||
@@ -8876,6 +8884,7 @@ static int nested_vmx_check_msr_switch(struct kvm_vcpu *vcpu,
        }
        if (count == 0)
                return 0;
+       maxphyaddr = cpuid_maxphyaddr(vcpu);
        if (!IS_ALIGNED(addr, 16) || addr >> maxphyaddr ||
            (addr + count * sizeof(struct vmx_msr_entry) - 1) >> maxphyaddr) {
                pr_warn_ratelimited(
@@ -8889,19 +8898,16 @@ static int nested_vmx_check_msr_switch(struct kvm_vcpu *vcpu,
 static int nested_vmx_check_msr_switch_controls(struct kvm_vcpu *vcpu,
                                                struct vmcs12 *vmcs12)
 {
-       int maxphyaddr;
-
        if (vmcs12->vm_exit_msr_load_count == 0 &&
            vmcs12->vm_exit_msr_store_count == 0 &&
            vmcs12->vm_entry_msr_load_count == 0)
                return 0; /* Fast path */
-       maxphyaddr = cpuid_maxphyaddr(vcpu);
        if (nested_vmx_check_msr_switch(vcpu, VM_EXIT_MSR_LOAD_COUNT,
-                                       VM_EXIT_MSR_LOAD_ADDR, maxphyaddr) ||
+                                       VM_EXIT_MSR_LOAD_ADDR) ||
            nested_vmx_check_msr_switch(vcpu, VM_EXIT_MSR_STORE_COUNT,
-                                       VM_EXIT_MSR_STORE_ADDR, maxphyaddr) ||
+                                       VM_EXIT_MSR_STORE_ADDR) ||
            nested_vmx_check_msr_switch(vcpu, VM_ENTRY_MSR_LOAD_COUNT,
-                                       VM_ENTRY_MSR_LOAD_ADDR, maxphyaddr))
+                                       VM_ENTRY_MSR_LOAD_ADDR))
                return -EINVAL;
        return 0;
 }
@@ -9151,8 +9157,9 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
                        exec_control &= ~SECONDARY_EXEC_RDTSCP;
                /* Take the following fields only from vmcs12 */
                exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
+                                 SECONDARY_EXEC_RDTSCP |
                                  SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
-                                  SECONDARY_EXEC_APIC_REGISTER_VIRT);
+                                 SECONDARY_EXEC_APIC_REGISTER_VIRT);
                if (nested_cpu_has(vmcs12,
                                CPU_BASED_ACTIVATE_SECONDARY_CONTROLS))
                        exec_control |= vmcs12->secondary_vm_exec_control;
@@ -9385,7 +9392,6 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
        }
 
        if (!nested_get_vmcs12_pages(vcpu, vmcs12)) {
-               /*TODO: Also verify bits beyond physical address width are 0*/
                nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
                return 1;
        }
@@ -9524,7 +9530,7 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
        vmcs12->launch_state = 1;
 
        if (vmcs12->guest_activity_state == GUEST_ACTIVITY_HLT)
-               return kvm_emulate_halt(vcpu);
+               return kvm_vcpu_halt(vcpu);
 
        vmx->nested.nested_run_pending = 1;
 
index 32bf19ef3115f65c9dffc23a655be2763babcaff..e1a81267f3f632e971d1fc63cfe687be2e7c60f3 100644 (file)
@@ -801,6 +801,17 @@ unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_GPL(kvm_get_cr8);
 
+static void kvm_update_dr0123(struct kvm_vcpu *vcpu)
+{
+       int i;
+
+       if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) {
+               for (i = 0; i < KVM_NR_DB_REGS; i++)
+                       vcpu->arch.eff_db[i] = vcpu->arch.db[i];
+               vcpu->arch.switch_db_regs |= KVM_DEBUGREG_RELOAD;
+       }
+}
+
 static void kvm_update_dr6(struct kvm_vcpu *vcpu)
 {
        if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP))
@@ -1070,19 +1081,19 @@ static void update_pvclock_gtod(struct timekeeper *tk)
        struct pvclock_gtod_data *vdata = &pvclock_gtod_data;
        u64 boot_ns;
 
-       boot_ns = ktime_to_ns(ktime_add(tk->tkr.base_mono, tk->offs_boot));
+       boot_ns = ktime_to_ns(ktime_add(tk->tkr_mono.base, tk->offs_boot));
 
        write_seqcount_begin(&vdata->seq);
 
        /* copy pvclock gtod data */
-       vdata->clock.vclock_mode        = tk->tkr.clock->archdata.vclock_mode;
-       vdata->clock.cycle_last         = tk->tkr.cycle_last;
-       vdata->clock.mask               = tk->tkr.mask;
-       vdata->clock.mult               = tk->tkr.mult;
-       vdata->clock.shift              = tk->tkr.shift;
+       vdata->clock.vclock_mode        = tk->tkr_mono.clock->archdata.vclock_mode;
+       vdata->clock.cycle_last         = tk->tkr_mono.cycle_last;
+       vdata->clock.mask               = tk->tkr_mono.mask;
+       vdata->clock.mult               = tk->tkr_mono.mult;
+       vdata->clock.shift              = tk->tkr_mono.shift;
 
        vdata->boot_ns                  = boot_ns;
-       vdata->nsec_base                = tk->tkr.xtime_nsec;
+       vdata->nsec_base                = tk->tkr_mono.xtime_nsec;
 
        write_seqcount_end(&vdata->seq);
 }
@@ -3149,6 +3160,7 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
                return -EINVAL;
 
        memcpy(vcpu->arch.db, dbgregs->db, sizeof(vcpu->arch.db));
+       kvm_update_dr0123(vcpu);
        vcpu->arch.dr6 = dbgregs->dr6;
        kvm_update_dr6(vcpu);
        vcpu->arch.dr7 = dbgregs->dr7;
@@ -4114,8 +4126,8 @@ static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
        do {
                n = min(len, 8);
                if (!(vcpu->arch.apic &&
-                     !kvm_iodevice_write(&vcpu->arch.apic->dev, addr, n, v))
-                   && kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
+                     !kvm_iodevice_write(vcpu, &vcpu->arch.apic->dev, addr, n, v))
+                   && kvm_io_bus_write(vcpu, KVM_MMIO_BUS, addr, n, v))
                        break;
                handled += n;
                addr += n;
@@ -4134,8 +4146,9 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
        do {
                n = min(len, 8);
                if (!(vcpu->arch.apic &&
-                     !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, n, v))
-                   && kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
+                     !kvm_iodevice_read(vcpu, &vcpu->arch.apic->dev,
+                                        addr, n, v))
+                   && kvm_io_bus_read(vcpu, KVM_MMIO_BUS, addr, n, v))
                        break;
                trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v);
                handled += n;
@@ -4475,7 +4488,8 @@ mmio:
        return X86EMUL_CONTINUE;
 }
 
-int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,
+static int emulator_read_write(struct x86_emulate_ctxt *ctxt,
+                       unsigned long addr,
                        void *val, unsigned int bytes,
                        struct x86_exception *exception,
                        const struct read_write_emulator_ops *ops)
@@ -4538,7 +4552,7 @@ static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
                                   exception, &read_emultor);
 }
 
-int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
+static int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
                            unsigned long addr,
                            const void *val,
                            unsigned int bytes,
@@ -4629,10 +4643,10 @@ static int kernel_pio(struct kvm_vcpu *vcpu, void *pd)
        int r;
 
        if (vcpu->arch.pio.in)
-               r = kvm_io_bus_read(vcpu->kvm, KVM_PIO_BUS, vcpu->arch.pio.port,
+               r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port,
                                    vcpu->arch.pio.size, pd);
        else
-               r = kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS,
+               r = kvm_io_bus_write(vcpu, KVM_PIO_BUS,
                                     vcpu->arch.pio.port, vcpu->arch.pio.size,
                                     pd);
        return r;
@@ -4705,7 +4719,7 @@ static void emulator_invlpg(struct x86_emulate_ctxt *ctxt, ulong address)
        kvm_mmu_invlpg(emul_to_vcpu(ctxt), address);
 }
 
-int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu)
+int kvm_emulate_wbinvd_noskip(struct kvm_vcpu *vcpu)
 {
        if (!need_emulate_wbinvd(vcpu))
                return X86EMUL_CONTINUE;
@@ -4722,19 +4736,29 @@ int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu)
                wbinvd();
        return X86EMUL_CONTINUE;
 }
+
+int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu)
+{
+       kvm_x86_ops->skip_emulated_instruction(vcpu);
+       return kvm_emulate_wbinvd_noskip(vcpu);
+}
 EXPORT_SYMBOL_GPL(kvm_emulate_wbinvd);
 
+
+
 static void emulator_wbinvd(struct x86_emulate_ctxt *ctxt)
 {
-       kvm_emulate_wbinvd(emul_to_vcpu(ctxt));
+       kvm_emulate_wbinvd_noskip(emul_to_vcpu(ctxt));
 }
 
-int emulator_get_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long *dest)
+static int emulator_get_dr(struct x86_emulate_ctxt *ctxt, int dr,
+                          unsigned long *dest)
 {
        return kvm_get_dr(emul_to_vcpu(ctxt), dr, dest);
 }
 
-int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long value)
+static int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr,
+                          unsigned long value)
 {
 
        return __kvm_set_dr(emul_to_vcpu(ctxt), dr, value);
@@ -5816,7 +5840,7 @@ void kvm_arch_exit(void)
        free_percpu(shared_msrs);
 }
 
-int kvm_emulate_halt(struct kvm_vcpu *vcpu)
+int kvm_vcpu_halt(struct kvm_vcpu *vcpu)
 {
        ++vcpu->stat.halt_exits;
        if (irqchip_in_kernel(vcpu->kvm)) {
@@ -5827,6 +5851,13 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
                return 0;
        }
 }
+EXPORT_SYMBOL_GPL(kvm_vcpu_halt);
+
+int kvm_emulate_halt(struct kvm_vcpu *vcpu)
+{
+       kvm_x86_ops->skip_emulated_instruction(vcpu);
+       return kvm_vcpu_halt(vcpu);
+}
 EXPORT_SYMBOL_GPL(kvm_emulate_halt);
 
 int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
@@ -5903,7 +5934,7 @@ static void kvm_pv_kick_cpu_op(struct kvm *kvm, unsigned long flags, int apicid)
        lapic_irq.dest_id = apicid;
 
        lapic_irq.delivery_mode = APIC_DM_REMRD;
-       kvm_irq_delivery_to_apic(kvm, 0, &lapic_irq, NULL);
+       kvm_irq_delivery_to_apic(kvm, NULL, &lapic_irq, NULL);
 }
 
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
@@ -5911,6 +5942,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
        unsigned long nr, a0, a1, a2, a3, ret;
        int op_64_bit, r = 1;
 
+       kvm_x86_ops->skip_emulated_instruction(vcpu);
+
        if (kvm_hv_hypercall_enabled(vcpu->kvm))
                return kvm_hv_hypercall(vcpu);
 
@@ -6164,7 +6197,7 @@ void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
 }
 
 /*
- * Returns 1 to let __vcpu_run() continue the guest execution loop without
+ * Returns 1 to let vcpu_run() continue the guest execution loop without
  * exiting to the userspace.  Otherwise, the value will be returned to the
  * userspace.
  */
@@ -6301,6 +6334,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
                set_debugreg(vcpu->arch.eff_db[2], 2);
                set_debugreg(vcpu->arch.eff_db[3], 3);
                set_debugreg(vcpu->arch.dr6, 6);
+               vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD;
        }
 
        trace_kvm_entry(vcpu->vcpu_id);
@@ -6382,42 +6416,47 @@ out:
        return r;
 }
 
+static inline int vcpu_block(struct kvm *kvm, struct kvm_vcpu *vcpu)
+{
+       if (!kvm_arch_vcpu_runnable(vcpu)) {
+               srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
+               kvm_vcpu_block(vcpu);
+               vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
+               if (!kvm_check_request(KVM_REQ_UNHALT, vcpu))
+                       return 1;
+       }
+
+       kvm_apic_accept_events(vcpu);
+       switch(vcpu->arch.mp_state) {
+       case KVM_MP_STATE_HALTED:
+               vcpu->arch.pv.pv_unhalted = false;
+               vcpu->arch.mp_state =
+                       KVM_MP_STATE_RUNNABLE;
+       case KVM_MP_STATE_RUNNABLE:
+               vcpu->arch.apf.halted = false;
+               break;
+       case KVM_MP_STATE_INIT_RECEIVED:
+               break;
+       default:
+               return -EINTR;
+               break;
+       }
+       return 1;
+}
 
-static int __vcpu_run(struct kvm_vcpu *vcpu)
+static int vcpu_run(struct kvm_vcpu *vcpu)
 {
        int r;
        struct kvm *kvm = vcpu->kvm;
 
        vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
 
-       r = 1;
-       while (r > 0) {
+       for (;;) {
                if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
                    !vcpu->arch.apf.halted)
                        r = vcpu_enter_guest(vcpu);
-               else {
-                       srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
-                       kvm_vcpu_block(vcpu);
-                       vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
-                       if (kvm_check_request(KVM_REQ_UNHALT, vcpu)) {
-                               kvm_apic_accept_events(vcpu);
-                               switch(vcpu->arch.mp_state) {
-                               case KVM_MP_STATE_HALTED:
-                                       vcpu->arch.pv.pv_unhalted = false;
-                                       vcpu->arch.mp_state =
-                                               KVM_MP_STATE_RUNNABLE;
-                               case KVM_MP_STATE_RUNNABLE:
-                                       vcpu->arch.apf.halted = false;
-                                       break;
-                               case KVM_MP_STATE_INIT_RECEIVED:
-                                       break;
-                               default:
-                                       r = -EINTR;
-                                       break;
-                               }
-                       }
-               }
-
+               else
+                       r = vcpu_block(kvm, vcpu);
                if (r <= 0)
                        break;
 
@@ -6429,6 +6468,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
                        r = -EINTR;
                        vcpu->run->exit_reason = KVM_EXIT_INTR;
                        ++vcpu->stat.request_irq_exits;
+                       break;
                }
 
                kvm_check_async_pf_completion(vcpu);
@@ -6437,6 +6477,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
                        r = -EINTR;
                        vcpu->run->exit_reason = KVM_EXIT_INTR;
                        ++vcpu->stat.signal_exits;
+                       break;
                }
                if (need_resched()) {
                        srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
@@ -6568,7 +6609,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        } else
                WARN_ON(vcpu->arch.pio.count || vcpu->mmio_needed);
 
-       r = __vcpu_run(vcpu);
+       r = vcpu_run(vcpu);
 
 out:
        post_kvm_run_save(vcpu);
@@ -7075,11 +7116,14 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu)
        kvm_clear_exception_queue(vcpu);
 
        memset(vcpu->arch.db, 0, sizeof(vcpu->arch.db));
+       kvm_update_dr0123(vcpu);
        vcpu->arch.dr6 = DR6_INIT;
        kvm_update_dr6(vcpu);
        vcpu->arch.dr7 = DR7_FIXED_1;
        kvm_update_dr7(vcpu);
 
+       vcpu->arch.cr2 = 0;
+
        kvm_make_request(KVM_REQ_EVENT, vcpu);
        vcpu->arch.apf.msr_val = 0;
        vcpu->arch.st.msr_val = 0;
@@ -7240,7 +7284,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 
        vcpu->arch.pv.pv_unhalted = false;
        vcpu->arch.emulate_ctxt.ops = &emulate_ops;
-       if (!irqchip_in_kernel(kvm) || kvm_vcpu_is_bsp(vcpu))
+       if (!irqchip_in_kernel(kvm) || kvm_vcpu_is_reset_bsp(vcpu))
                vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
        else
                vcpu->arch.mp_state = KVM_MP_STATE_UNINITIALIZED;
@@ -7288,6 +7332,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
        vcpu->arch.guest_supported_xcr0 = 0;
        vcpu->arch.guest_xstate_size = XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET;
 
+       vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
+
        kvm_async_pf_hash_reset(vcpu);
        kvm_pmu_init(vcpu);
 
@@ -7428,7 +7474,7 @@ void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
 
        for (i = 0; i < KVM_NR_PAGE_SIZES; ++i) {
                if (!dont || free->arch.rmap[i] != dont->arch.rmap[i]) {
-                       kvm_kvfree(free->arch.rmap[i]);
+                       kvfree(free->arch.rmap[i]);
                        free->arch.rmap[i] = NULL;
                }
                if (i == 0)
@@ -7436,7 +7482,7 @@ void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
 
                if (!dont || free->arch.lpage_info[i - 1] !=
                             dont->arch.lpage_info[i - 1]) {
-                       kvm_kvfree(free->arch.lpage_info[i - 1]);
+                       kvfree(free->arch.lpage_info[i - 1]);
                        free->arch.lpage_info[i - 1] = NULL;
                }
        }
@@ -7490,12 +7536,12 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
 
 out_free:
        for (i = 0; i < KVM_NR_PAGE_SIZES; ++i) {
-               kvm_kvfree(slot->arch.rmap[i]);
+               kvfree(slot->arch.rmap[i]);
                slot->arch.rmap[i] = NULL;
                if (i == 0)
                        continue;
 
-               kvm_kvfree(slot->arch.lpage_info[i - 1]);
+               kvfree(slot->arch.lpage_info[i - 1]);
                slot->arch.lpage_info[i - 1] = NULL;
        }
        return -ENOMEM;
@@ -7617,6 +7663,23 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
        /* It's OK to get 'new' slot here as it has already been installed */
        new = id_to_memslot(kvm->memslots, mem->slot);
 
+       /*
+        * Dirty logging tracks sptes in 4k granularity, meaning that large
+        * sptes have to be split.  If live migration is successful, the guest
+        * in the source machine will be destroyed and large sptes will be
+        * created in the destination. However, if the guest continues to run
+        * in the source machine (for example if live migration fails), small
+        * sptes will remain around and cause bad performance.
+        *
+        * Scan sptes if dirty logging has been stopped, dropping those
+        * which can be collapsed into a single large-page spte.  Later
+        * page faults will create the large-page sptes.
+        */
+       if ((change != KVM_MR_DELETE) &&
+               (old->flags & KVM_MEM_LOG_DIRTY_PAGES) &&
+               !(new->flags & KVM_MEM_LOG_DIRTY_PAGES))
+               kvm_mmu_zap_collapsible_sptes(kvm, new);
+
        /*
         * Set up write protection and/or dirty logging for the new slot.
         *
index ac4453d8520efd5e2080ef6f29cfd7da7b154d61..717908b16037d45957a0ec69b94c8c7d396bfaa6 100644 (file)
@@ -868,7 +868,8 @@ static void __init lguest_init_IRQ(void)
                /* Some systems map "vectors" to interrupts weirdly.  Not us! */
                __this_cpu_write(vector_irq[i], i - FIRST_EXTERNAL_VECTOR);
                if (i != SYSCALL_VECTOR)
-                       set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]);
+                       set_intr_gate(i, irq_entries_start +
+                                       8 * (i - FIRST_EXTERNAL_VECTOR));
        }
 
        /*
@@ -1076,6 +1077,7 @@ static void lguest_load_sp0(struct tss_struct *tss,
 {
        lazy_hcall3(LHCALL_SET_STACK, __KERNEL_DS | 0x1, thread->sp0,
                   THREAD_SIZE / PAGE_SIZE);
+       tss->x86_tss.sp0 = thread->sp0;
 }
 
 /* Let's just say, I wouldn't do debugging under a Guest. */
index f5cc9eb1d51bc02ef817bd664c7810f4f5b928b1..082a85167a5b68feff28d749b0e04425a0f4adf2 100644 (file)
 #include <asm/alternative-asm.h>
 #include <asm/dwarf2.h>
 
-.macro SAVE reg
-       pushl_cfi %\reg
-       CFI_REL_OFFSET \reg, 0
-.endm
-
-.macro RESTORE reg
-       popl_cfi %\reg
-       CFI_RESTORE \reg
-.endm
-
 .macro read64 reg
        movl %ebx, %eax
        movl %ecx, %edx
@@ -67,10 +57,10 @@ ENDPROC(atomic64_xchg_cx8)
 .macro addsub_return func ins insc
 ENTRY(atomic64_\func\()_return_cx8)
        CFI_STARTPROC
-       SAVE ebp
-       SAVE ebx
-       SAVE esi
-       SAVE edi
+       pushl_cfi_reg ebp
+       pushl_cfi_reg ebx
+       pushl_cfi_reg esi
+       pushl_cfi_reg edi
 
        movl %eax, %esi
        movl %edx, %edi
@@ -89,10 +79,10 @@ ENTRY(atomic64_\func\()_return_cx8)
 10:
        movl %ebx, %eax
        movl %ecx, %edx
-       RESTORE edi
-       RESTORE esi
-       RESTORE ebx
-       RESTORE ebp
+       popl_cfi_reg edi
+       popl_cfi_reg esi
+       popl_cfi_reg ebx
+       popl_cfi_reg ebp
        ret
        CFI_ENDPROC
 ENDPROC(atomic64_\func\()_return_cx8)
@@ -104,7 +94,7 @@ addsub_return sub sub sbb
 .macro incdec_return func ins insc
 ENTRY(atomic64_\func\()_return_cx8)
        CFI_STARTPROC
-       SAVE ebx
+       pushl_cfi_reg ebx
 
        read64 %esi
 1:
@@ -119,7 +109,7 @@ ENTRY(atomic64_\func\()_return_cx8)
 10:
        movl %ebx, %eax
        movl %ecx, %edx
-       RESTORE ebx
+       popl_cfi_reg ebx
        ret
        CFI_ENDPROC
 ENDPROC(atomic64_\func\()_return_cx8)
@@ -130,7 +120,7 @@ incdec_return dec sub sbb
 
 ENTRY(atomic64_dec_if_positive_cx8)
        CFI_STARTPROC
-       SAVE ebx
+       pushl_cfi_reg ebx
 
        read64 %esi
 1:
@@ -146,18 +136,18 @@ ENTRY(atomic64_dec_if_positive_cx8)
 2:
        movl %ebx, %eax
        movl %ecx, %edx
-       RESTORE ebx
+       popl_cfi_reg ebx
        ret
        CFI_ENDPROC
 ENDPROC(atomic64_dec_if_positive_cx8)
 
 ENTRY(atomic64_add_unless_cx8)
        CFI_STARTPROC
-       SAVE ebp
-       SAVE ebx
+       pushl_cfi_reg ebp
+       pushl_cfi_reg ebx
 /* these just push these two parameters on the stack */
-       SAVE edi
-       SAVE ecx
+       pushl_cfi_reg edi
+       pushl_cfi_reg ecx
 
        movl %eax, %ebp
        movl %edx, %edi
@@ -179,8 +169,8 @@ ENTRY(atomic64_add_unless_cx8)
 3:
        addl $8, %esp
        CFI_ADJUST_CFA_OFFSET -8
-       RESTORE ebx
-       RESTORE ebp
+       popl_cfi_reg ebx
+       popl_cfi_reg ebp
        ret
 4:
        cmpl %edx, 4(%esp)
@@ -192,7 +182,7 @@ ENDPROC(atomic64_add_unless_cx8)
 
 ENTRY(atomic64_inc_not_zero_cx8)
        CFI_STARTPROC
-       SAVE ebx
+       pushl_cfi_reg ebx
 
        read64 %esi
 1:
@@ -209,7 +199,7 @@ ENTRY(atomic64_inc_not_zero_cx8)
 
        movl $1, %eax
 3:
-       RESTORE ebx
+       popl_cfi_reg ebx
        ret
        CFI_ENDPROC
 ENDPROC(atomic64_inc_not_zero_cx8)
index e78b8eee66155df85844e8cf6dae4507fa313bc6..9bc944a9127481ead40689a73054d80e50f0bc10 100644 (file)
@@ -51,10 +51,8 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
           */           
 ENTRY(csum_partial)
        CFI_STARTPROC
-       pushl_cfi %esi
-       CFI_REL_OFFSET esi, 0
-       pushl_cfi %ebx
-       CFI_REL_OFFSET ebx, 0
+       pushl_cfi_reg esi
+       pushl_cfi_reg ebx
        movl 20(%esp),%eax      # Function arg: unsigned int sum
        movl 16(%esp),%ecx      # Function arg: int len
        movl 12(%esp),%esi      # Function arg: unsigned char *buff
@@ -127,14 +125,12 @@ ENTRY(csum_partial)
 6:     addl %ecx,%eax
        adcl $0, %eax 
 7:     
-       testl $1, 12(%esp)
+       testb $1, 12(%esp)
        jz 8f
        roll $8, %eax
 8:
-       popl_cfi %ebx
-       CFI_RESTORE ebx
-       popl_cfi %esi
-       CFI_RESTORE esi
+       popl_cfi_reg ebx
+       popl_cfi_reg esi
        ret
        CFI_ENDPROC
 ENDPROC(csum_partial)
@@ -145,10 +141,8 @@ ENDPROC(csum_partial)
 
 ENTRY(csum_partial)
        CFI_STARTPROC
-       pushl_cfi %esi
-       CFI_REL_OFFSET esi, 0
-       pushl_cfi %ebx
-       CFI_REL_OFFSET ebx, 0
+       pushl_cfi_reg esi
+       pushl_cfi_reg ebx
        movl 20(%esp),%eax      # Function arg: unsigned int sum
        movl 16(%esp),%ecx      # Function arg: int len
        movl 12(%esp),%esi      # Function arg: const unsigned char *buf
@@ -251,14 +245,12 @@ ENTRY(csum_partial)
        addl %ebx,%eax
        adcl $0,%eax
 80: 
-       testl $1, 12(%esp)
+       testb $1, 12(%esp)
        jz 90f
        roll $8, %eax
 90: 
-       popl_cfi %ebx
-       CFI_RESTORE ebx
-       popl_cfi %esi
-       CFI_RESTORE esi
+       popl_cfi_reg ebx
+       popl_cfi_reg esi
        ret
        CFI_ENDPROC
 ENDPROC(csum_partial)
@@ -298,12 +290,9 @@ ENTRY(csum_partial_copy_generic)
        CFI_STARTPROC
        subl  $4,%esp   
        CFI_ADJUST_CFA_OFFSET 4
-       pushl_cfi %edi
-       CFI_REL_OFFSET edi, 0
-       pushl_cfi %esi
-       CFI_REL_OFFSET esi, 0
-       pushl_cfi %ebx
-       CFI_REL_OFFSET ebx, 0
+       pushl_cfi_reg edi
+       pushl_cfi_reg esi
+       pushl_cfi_reg ebx
        movl ARGBASE+16(%esp),%eax      # sum
        movl ARGBASE+12(%esp),%ecx      # len
        movl ARGBASE+4(%esp),%esi       # src
@@ -412,12 +401,9 @@ DST(       movb %cl, (%edi)        )
 
 .previous
 
-       popl_cfi %ebx
-       CFI_RESTORE ebx
-       popl_cfi %esi
-       CFI_RESTORE esi
-       popl_cfi %edi
-       CFI_RESTORE edi
+       popl_cfi_reg ebx
+       popl_cfi_reg esi
+       popl_cfi_reg edi
        popl_cfi %ecx                   # equivalent to addl $4,%esp
        ret     
        CFI_ENDPROC
@@ -441,12 +427,9 @@ ENDPROC(csum_partial_copy_generic)
                
 ENTRY(csum_partial_copy_generic)
        CFI_STARTPROC
-       pushl_cfi %ebx
-       CFI_REL_OFFSET ebx, 0
-       pushl_cfi %edi
-       CFI_REL_OFFSET edi, 0
-       pushl_cfi %esi
-       CFI_REL_OFFSET esi, 0
+       pushl_cfi_reg ebx
+       pushl_cfi_reg edi
+       pushl_cfi_reg esi
        movl ARGBASE+4(%esp),%esi       #src
        movl ARGBASE+8(%esp),%edi       #dst    
        movl ARGBASE+12(%esp),%ecx      #len
@@ -506,12 +489,9 @@ DST(       movb %dl, (%edi)         )
        jmp  7b                 
 .previous                              
 
-       popl_cfi %esi
-       CFI_RESTORE esi
-       popl_cfi %edi
-       CFI_RESTORE edi
-       popl_cfi %ebx
-       CFI_RESTORE ebx
+       popl_cfi_reg esi
+       popl_cfi_reg edi
+       popl_cfi_reg ebx
        ret
        CFI_ENDPROC
 ENDPROC(csum_partial_copy_generic)
index f2145cfa12a66830e834718340c4cc88e64a731a..e67e579c93bdf7f3d0737565ea106edeeefb3b6d 100644 (file)
@@ -1,31 +1,35 @@
 #include <linux/linkage.h>
 #include <asm/dwarf2.h>
+#include <asm/cpufeature.h>
 #include <asm/alternative-asm.h>
 
 /*
- * Zero a page.        
- * rdi page
- */                    
-ENTRY(clear_page_c)
+ * Most CPUs support enhanced REP MOVSB/STOSB instructions. It is
+ * recommended to use this when possible and we do use them by default.
+ * If enhanced REP MOVSB/STOSB is not available, try to use fast string.
+ * Otherwise, use original.
+ */
+
+/*
+ * Zero a page.
+ * %rdi        - page
+ */
+ENTRY(clear_page)
        CFI_STARTPROC
+
+       ALTERNATIVE_2 "jmp clear_page_orig", "", X86_FEATURE_REP_GOOD, \
+                     "jmp clear_page_c_e", X86_FEATURE_ERMS
+
        movl $4096/8,%ecx
        xorl %eax,%eax
        rep stosq
        ret
        CFI_ENDPROC
-ENDPROC(clear_page_c)
+ENDPROC(clear_page)
 
-ENTRY(clear_page_c_e)
+ENTRY(clear_page_orig)
        CFI_STARTPROC
-       movl $4096,%ecx
-       xorl %eax,%eax
-       rep stosb
-       ret
-       CFI_ENDPROC
-ENDPROC(clear_page_c_e)
 
-ENTRY(clear_page)
-       CFI_STARTPROC
        xorl   %eax,%eax
        movl   $4096/64,%ecx
        .p2align 4
@@ -45,29 +49,13 @@ ENTRY(clear_page)
        nop
        ret
        CFI_ENDPROC
-.Lclear_page_end:
-ENDPROC(clear_page)
-
-       /*
-        * Some CPUs support enhanced REP MOVSB/STOSB instructions.
-        * It is recommended to use this when possible.
-        * If enhanced REP MOVSB/STOSB is not available, try to use fast string.
-        * Otherwise, use original function.
-        *
-        */
+ENDPROC(clear_page_orig)
 
-#include <asm/cpufeature.h>
-
-       .section .altinstr_replacement,"ax"
-1:     .byte 0xeb                                      /* jmp <disp8> */
-       .byte (clear_page_c - clear_page) - (2f - 1b)   /* offset */
-2:     .byte 0xeb                                      /* jmp <disp8> */
-       .byte (clear_page_c_e - clear_page) - (3f - 2b) /* offset */
-3:
-       .previous
-       .section .altinstructions,"a"
-       altinstruction_entry clear_page,1b,X86_FEATURE_REP_GOOD,\
-                            .Lclear_page_end-clear_page, 2b-1b
-       altinstruction_entry clear_page,2b,X86_FEATURE_ERMS,   \
-                            .Lclear_page_end-clear_page,3b-2b
-       .previous
+ENTRY(clear_page_c_e)
+       CFI_STARTPROC
+       movl $4096,%ecx
+       xorl %eax,%eax
+       rep stosb
+       ret
+       CFI_ENDPROC
+ENDPROC(clear_page_c_e)
index 176cca67212b7072687f42450ef56018c03ebaaa..8239dbcbf98455a99a125953392114f07a09aa74 100644 (file)
@@ -2,23 +2,26 @@
 
 #include <linux/linkage.h>
 #include <asm/dwarf2.h>
+#include <asm/cpufeature.h>
 #include <asm/alternative-asm.h>
 
+/*
+ * Some CPUs run faster using the string copy instructions (sane microcode).
+ * It is also a lot simpler. Use this when possible. But, don't use streaming
+ * copy unless the CPU indicates X86_FEATURE_REP_GOOD. Could vary the
+ * prefetch distance based on SMP/UP.
+ */
        ALIGN
-copy_page_rep:
+ENTRY(copy_page)
        CFI_STARTPROC
+       ALTERNATIVE "jmp copy_page_regs", "", X86_FEATURE_REP_GOOD
        movl    $4096/8, %ecx
        rep     movsq
        ret
        CFI_ENDPROC
-ENDPROC(copy_page_rep)
-
-/*
- *  Don't use streaming copy unless the CPU indicates X86_FEATURE_REP_GOOD.
- *  Could vary the prefetch distance based on SMP/UP.
-*/
+ENDPROC(copy_page)
 
-ENTRY(copy_page)
+ENTRY(copy_page_regs)
        CFI_STARTPROC
        subq    $2*8,   %rsp
        CFI_ADJUST_CFA_OFFSET 2*8
@@ -90,21 +93,5 @@ ENTRY(copy_page)
        addq    $2*8, %rsp
        CFI_ADJUST_CFA_OFFSET -2*8
        ret
-.Lcopy_page_end:
        CFI_ENDPROC
-ENDPROC(copy_page)
-
-       /* Some CPUs run faster using the string copy instructions.
-          It is also a lot simpler. Use this when possible */
-
-#include <asm/cpufeature.h>
-
-       .section .altinstr_replacement,"ax"
-1:     .byte 0xeb                                      /* jmp <disp8> */
-       .byte (copy_page_rep - copy_page) - (2f - 1b)   /* offset */
-2:
-       .previous
-       .section .altinstructions,"a"
-       altinstruction_entry copy_page, 1b, X86_FEATURE_REP_GOOD,       \
-               .Lcopy_page_end-copy_page, 2b-1b
-       .previous
+ENDPROC(copy_page_regs)
index dee945d555941a078f40049b24b8b4731aba6f2c..fa997dfaef242fa9abdb28c20658a939caf72697 100644 (file)
@@ -8,9 +8,6 @@
 
 #include <linux/linkage.h>
 #include <asm/dwarf2.h>
-
-#define FIX_ALIGNMENT 1
-
 #include <asm/current.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/asm.h>
 #include <asm/smap.h>
 
-/*
- * By placing feature2 after feature1 in altinstructions section, we logically
- * implement:
- * If CPU has feature2, jmp to alt2 is used
- * else if CPU has feature1, jmp to alt1 is used
- * else jmp to orig is used.
- */
-       .macro ALTERNATIVE_JUMP feature1,feature2,orig,alt1,alt2
-0:
-       .byte 0xe9      /* 32bit jump */
-       .long \orig-1f  /* by default jump to orig */
-1:
-       .section .altinstr_replacement,"ax"
-2:     .byte 0xe9                      /* near jump with 32bit immediate */
-       .long \alt1-1b /* offset */   /* or alternatively to alt1 */
-3:     .byte 0xe9                      /* near jump with 32bit immediate */
-       .long \alt2-1b /* offset */   /* or alternatively to alt2 */
-       .previous
-
-       .section .altinstructions,"a"
-       altinstruction_entry 0b,2b,\feature1,5,5
-       altinstruction_entry 0b,3b,\feature2,5,5
-       .previous
-       .endm
-
        .macro ALIGN_DESTINATION
-#ifdef FIX_ALIGNMENT
        /* check for bad alignment of destination */
        movl %edi,%ecx
        andl $7,%ecx
@@ -67,7 +38,6 @@
 
        _ASM_EXTABLE(100b,103b)
        _ASM_EXTABLE(101b,103b)
-#endif
        .endm
 
 /* Standard copy_to_user with segment limit checking */
@@ -79,9 +49,11 @@ ENTRY(_copy_to_user)
        jc bad_to_user
        cmpq TI_addr_limit(%rax),%rcx
        ja bad_to_user
-       ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,X86_FEATURE_ERMS, \
-               copy_user_generic_unrolled,copy_user_generic_string,    \
-               copy_user_enhanced_fast_string
+       ALTERNATIVE_2 "jmp copy_user_generic_unrolled",         \
+                     "jmp copy_user_generic_string",           \
+                     X86_FEATURE_REP_GOOD,                     \
+                     "jmp copy_user_enhanced_fast_string",     \
+                     X86_FEATURE_ERMS
        CFI_ENDPROC
 ENDPROC(_copy_to_user)
 
@@ -94,9 +66,11 @@ ENTRY(_copy_from_user)
        jc bad_from_user
        cmpq TI_addr_limit(%rax),%rcx
        ja bad_from_user
-       ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,X86_FEATURE_ERMS, \
-               copy_user_generic_unrolled,copy_user_generic_string,    \
-               copy_user_enhanced_fast_string
+       ALTERNATIVE_2 "jmp copy_user_generic_unrolled",         \
+                     "jmp copy_user_generic_string",           \
+                     X86_FEATURE_REP_GOOD,                     \
+                     "jmp copy_user_enhanced_fast_string",     \
+                     X86_FEATURE_ERMS
        CFI_ENDPROC
 ENDPROC(_copy_from_user)
 
index 2419d5fefae30ac2453fabf71c633ede013d2e4a..9734182966f3be925a38c0762aa71e3148156148 100644 (file)
@@ -196,7 +196,7 @@ ENTRY(csum_partial_copy_generic)
 
        /* handle last odd byte */
 .Lhandle_1:
-       testl $1, %r10d
+       testb $1, %r10b
        jz    .Lende
        xorl  %ebx, %ebx
        source
index 1313ae6b478b6c439741ee032a8c33b86868ee2c..8f72b334aea03387ab7084d9998f497cf7287da2 100644 (file)
  */
 void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64)
 {
+       /*
+        * Instructions longer than MAX_INSN_SIZE (15 bytes) are invalid
+        * even if the input buffer is long enough to hold them.
+        */
+       if (buf_len > MAX_INSN_SIZE)
+               buf_len = MAX_INSN_SIZE;
+
        memset(insn, 0, sizeof(*insn));
        insn->kaddr = kaddr;
        insn->end_kaddr = kaddr + buf_len;
@@ -164,6 +171,12 @@ found:
                                /* VEX.W overrides opnd_size */
                                insn->opnd_bytes = 8;
                } else {
+                       /*
+                        * For VEX2, fake VEX3-like byte#2.
+                        * Makes it easier to decode vex.W, vex.vvvv,
+                        * vex.L and vex.pp. Masking with 0x7f sets vex.W == 0.
+                        */
+                       insn->vex_prefix.bytes[2] = b2 & 0x7f;
                        insn->vex_prefix.nbytes = 2;
                        insn->next_byte += 2;
                }
index 89b53c9968e7d50c1dd129dd92272f1a47edefe5..b046664f5a1ccf37f3c94b2ed7d8d5b3298e89bf 100644 (file)
@@ -1,11 +1,19 @@
 /* Copyright 2002 Andi Kleen */
 
 #include <linux/linkage.h>
-
 #include <asm/cpufeature.h>
 #include <asm/dwarf2.h>
 #include <asm/alternative-asm.h>
 
+/*
+ * We build a jump to memcpy_orig by default which gets NOPped out on
+ * the majority of x86 CPUs which set REP_GOOD. In addition, CPUs which
+ * have the enhanced REP MOVSB/STOSB feature (ERMS), change those NOPs
+ * to a jmp to memcpy_erms which does the REP; MOVSB mem copy.
+ */
+
+.weak memcpy
+
 /*
  * memcpy - Copy a memory block.
  *
  * Output:
  * rax original destination
  */
+ENTRY(__memcpy)
+ENTRY(memcpy)
+       ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
+                     "jmp memcpy_erms", X86_FEATURE_ERMS
 
-/*
- * memcpy_c() - fast string ops (REP MOVSQ) based variant.
- *
- * This gets patched over the unrolled variant (below) via the
- * alternative instructions framework:
- */
-       .section .altinstr_replacement, "ax", @progbits
-.Lmemcpy_c:
        movq %rdi, %rax
        movq %rdx, %rcx
        shrq $3, %rcx
        movl %edx, %ecx
        rep movsb
        ret
-.Lmemcpy_e:
-       .previous
+ENDPROC(memcpy)
+ENDPROC(__memcpy)
 
 /*
- * memcpy_c_e() - enhanced fast string memcpy. This is faster and simpler than
- * memcpy_c. Use memcpy_c_e when possible.
- *
- * This gets patched over the unrolled variant (below) via the
- * alternative instructions framework:
+ * memcpy_erms() - enhanced fast string memcpy. This is faster and
+ * simpler than memcpy. Use memcpy_erms when possible.
  */
-       .section .altinstr_replacement, "ax", @progbits
-.Lmemcpy_c_e:
+ENTRY(memcpy_erms)
        movq %rdi, %rax
        movq %rdx, %rcx
        rep movsb
        ret
-.Lmemcpy_e_e:
-       .previous
-
-.weak memcpy
+ENDPROC(memcpy_erms)
 
-ENTRY(__memcpy)
-ENTRY(memcpy)
+ENTRY(memcpy_orig)
        CFI_STARTPROC
        movq %rdi, %rax
 
@@ -183,26 +179,4 @@ ENTRY(memcpy)
 .Lend:
        retq
        CFI_ENDPROC
-ENDPROC(memcpy)
-ENDPROC(__memcpy)
-
-       /*
-        * Some CPUs are adding enhanced REP MOVSB/STOSB feature
-        * If the feature is supported, memcpy_c_e() is the first choice.
-        * If enhanced rep movsb copy is not available, use fast string copy
-        * memcpy_c() when possible. This is faster and code is simpler than
-        * original memcpy().
-        * Otherwise, original memcpy() is used.
-        * In .altinstructions section, ERMS feature is placed after REG_GOOD
-         * feature to implement the right patch order.
-        *
-        * Replace only beginning, memcpy is used to apply alternatives,
-        * so it is silly to overwrite itself with nops - reboot is the
-        * only outcome...
-        */
-       .section .altinstructions, "a"
-       altinstruction_entry __memcpy,.Lmemcpy_c,X86_FEATURE_REP_GOOD,\
-                            .Lmemcpy_e-.Lmemcpy_c,.Lmemcpy_e-.Lmemcpy_c
-       altinstruction_entry __memcpy,.Lmemcpy_c_e,X86_FEATURE_ERMS, \
-                            .Lmemcpy_e_e-.Lmemcpy_c_e,.Lmemcpy_e_e-.Lmemcpy_c_e
-       .previous
+ENDPROC(memcpy_orig)
index 9c4b530575da6e9b70cb8505f1e4b391b6fdff02..0f8a0d0331b91715238f01e8f54ce74525fb0cc4 100644 (file)
@@ -5,7 +5,6 @@
  * This assembly file is re-written from memmove_64.c file.
  *     - Copyright 2011 Fenghua Yu <fenghua.yu@intel.com>
  */
-#define _STRING_C
 #include <linux/linkage.h>
 #include <asm/dwarf2.h>
 #include <asm/cpufeature.h>
@@ -44,6 +43,8 @@ ENTRY(__memmove)
        jg 2f
 
 .Lmemmove_begin_forward:
+       ALTERNATIVE "", "movq %rdx, %rcx; rep movsb; retq", X86_FEATURE_ERMS
+
        /*
         * movsq instruction have many startup latency
         * so we handle small size by general register.
@@ -207,21 +208,5 @@ ENTRY(__memmove)
 13:
        retq
        CFI_ENDPROC
-
-       .section .altinstr_replacement,"ax"
-.Lmemmove_begin_forward_efs:
-       /* Forward moving data. */
-       movq %rdx, %rcx
-       rep movsb
-       retq
-.Lmemmove_end_forward_efs:
-       .previous
-
-       .section .altinstructions,"a"
-       altinstruction_entry .Lmemmove_begin_forward,           \
-               .Lmemmove_begin_forward_efs,X86_FEATURE_ERMS,   \
-               .Lmemmove_end_forward-.Lmemmove_begin_forward,  \
-               .Lmemmove_end_forward_efs-.Lmemmove_begin_forward_efs
-       .previous
 ENDPROC(__memmove)
 ENDPROC(memmove)
index 6f44935c6a606a1607022e889cc60ea151e54b65..93118fb239762ba78efd754d20a756aed0221411 100644 (file)
@@ -5,19 +5,30 @@
 #include <asm/cpufeature.h>
 #include <asm/alternative-asm.h>
 
+.weak memset
+
 /*
  * ISO C memset - set a memory block to a byte value. This function uses fast
  * string to get better performance than the original function. The code is
  * simpler and shorter than the orignal function as well.
- *     
+ *
  * rdi   destination
- * rsi   value (char) 
- * rdx   count (bytes) 
- * 
+ * rsi   value (char)
+ * rdx   count (bytes)
+ *
  * rax   original destination
- */    
-       .section .altinstr_replacement, "ax", @progbits
-.Lmemset_c:
+ */
+ENTRY(memset)
+ENTRY(__memset)
+       /*
+        * Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended
+        * to use it when possible. If not available, use fast string instructions.
+        *
+        * Otherwise, use original memset function.
+        */
+       ALTERNATIVE_2 "jmp memset_orig", "", X86_FEATURE_REP_GOOD, \
+                     "jmp memset_erms", X86_FEATURE_ERMS
+
        movq %rdi,%r9
        movq %rdx,%rcx
        andl $7,%edx
@@ -31,8 +42,8 @@
        rep stosb
        movq %r9,%rax
        ret
-.Lmemset_e:
-       .previous
+ENDPROC(memset)
+ENDPROC(__memset)
 
 /*
  * ISO C memset - set a memory block to a byte value. This function uses
  *
  * rax   original destination
  */
-       .section .altinstr_replacement, "ax", @progbits
-.Lmemset_c_e:
+ENTRY(memset_erms)
        movq %rdi,%r9
        movb %sil,%al
        movq %rdx,%rcx
        rep stosb
        movq %r9,%rax
        ret
-.Lmemset_e_e:
-       .previous
-
-.weak memset
+ENDPROC(memset_erms)
 
-ENTRY(memset)
-ENTRY(__memset)
+ENTRY(memset_orig)
        CFI_STARTPROC
        movq %rdi,%r10
 
@@ -134,23 +140,4 @@ ENTRY(__memset)
        jmp .Lafter_bad_alignment
 .Lfinal:
        CFI_ENDPROC
-ENDPROC(memset)
-ENDPROC(__memset)
-
-       /* Some CPUs support enhanced REP MOVSB/STOSB feature.
-        * It is recommended to use this when possible.
-        *
-        * If enhanced REP MOVSB/STOSB feature is not available, use fast string
-        * instructions.
-        *
-        * Otherwise, use original memset function.
-        *
-        * In .altinstructions section, ERMS feature is placed after REG_GOOD
-         * feature to implement the right patch order.
-        */
-       .section .altinstructions,"a"
-       altinstruction_entry __memset,.Lmemset_c,X86_FEATURE_REP_GOOD,\
-                            .Lfinal-__memset,.Lmemset_e-.Lmemset_c
-       altinstruction_entry __memset,.Lmemset_c_e,X86_FEATURE_ERMS, \
-                            .Lfinal-__memset,.Lmemset_e_e-.Lmemset_c_e
-       .previous
+ENDPROC(memset_orig)
index f6d13eefad1063d5e525dbc0cfff1ccc12b34bc9..3ca5218fbece0c568ed6079ee2370ff1cedf71f8 100644 (file)
@@ -14,8 +14,8 @@
 .macro op_safe_regs op
 ENTRY(\op\()_safe_regs)
        CFI_STARTPROC
-       pushq_cfi %rbx
-       pushq_cfi %rbp
+       pushq_cfi_reg rbx
+       pushq_cfi_reg rbp
        movq    %rdi, %r10      /* Save pointer */
        xorl    %r11d, %r11d    /* Return value */
        movl    (%rdi), %eax
@@ -35,8 +35,8 @@ ENTRY(\op\()_safe_regs)
        movl    %ebp, 20(%r10)
        movl    %esi, 24(%r10)
        movl    %edi, 28(%r10)
-       popq_cfi %rbp
-       popq_cfi %rbx
+       popq_cfi_reg rbp
+       popq_cfi_reg rbx
        ret
 3:
        CFI_RESTORE_STATE
@@ -53,10 +53,10 @@ ENDPROC(\op\()_safe_regs)
 .macro op_safe_regs op
 ENTRY(\op\()_safe_regs)
        CFI_STARTPROC
-       pushl_cfi %ebx
-       pushl_cfi %ebp
-       pushl_cfi %esi
-       pushl_cfi %edi
+       pushl_cfi_reg ebx
+       pushl_cfi_reg ebp
+       pushl_cfi_reg esi
+       pushl_cfi_reg edi
        pushl_cfi $0              /* Return value */
        pushl_cfi %eax
        movl    4(%eax), %ecx
@@ -80,10 +80,10 @@ ENTRY(\op\()_safe_regs)
        movl    %esi, 24(%eax)
        movl    %edi, 28(%eax)
        popl_cfi %eax
-       popl_cfi %edi
-       popl_cfi %esi
-       popl_cfi %ebp
-       popl_cfi %ebx
+       popl_cfi_reg edi
+       popl_cfi_reg esi
+       popl_cfi_reg ebp
+       popl_cfi_reg ebx
        ret
 3:
        CFI_RESTORE_STATE
index 5dff5f042468acfedf6e4058643855d59c75315d..2322abe4da3b014aef389c03e177c37eec31b802 100644 (file)
  */
 
 #define save_common_regs \
-       pushl_cfi %ecx; CFI_REL_OFFSET ecx, 0
+       pushl_cfi_reg ecx
 
 #define restore_common_regs \
-       popl_cfi %ecx; CFI_RESTORE ecx
+       popl_cfi_reg ecx
 
        /* Avoid uglifying the argument copying x86-64 needs to do. */
        .macro movq src, dst
  */
 
 #define save_common_regs \
-       pushq_cfi %rdi; CFI_REL_OFFSET rdi, 0; \
-       pushq_cfi %rsi; CFI_REL_OFFSET rsi, 0; \
-       pushq_cfi %rcx; CFI_REL_OFFSET rcx, 0; \
-       pushq_cfi %r8;  CFI_REL_OFFSET r8,  0; \
-       pushq_cfi %r9;  CFI_REL_OFFSET r9,  0; \
-       pushq_cfi %r10; CFI_REL_OFFSET r10, 0; \
-       pushq_cfi %r11; CFI_REL_OFFSET r11, 0
+       pushq_cfi_reg rdi; \
+       pushq_cfi_reg rsi; \
+       pushq_cfi_reg rcx; \
+       pushq_cfi_reg r8;  \
+       pushq_cfi_reg r9;  \
+       pushq_cfi_reg r10; \
+       pushq_cfi_reg r11
 
 #define restore_common_regs \
-       popq_cfi %r11; CFI_RESTORE r11; \
-       popq_cfi %r10; CFI_RESTORE r10; \
-       popq_cfi %r9;  CFI_RESTORE r9; \
-       popq_cfi %r8;  CFI_RESTORE r8; \
-       popq_cfi %rcx; CFI_RESTORE rcx; \
-       popq_cfi %rsi; CFI_RESTORE rsi; \
-       popq_cfi %rdi; CFI_RESTORE rdi
+       popq_cfi_reg r11; \
+       popq_cfi_reg r10; \
+       popq_cfi_reg r9; \
+       popq_cfi_reg r8; \
+       popq_cfi_reg rcx; \
+       popq_cfi_reg rsi; \
+       popq_cfi_reg rdi
 
 #endif
 
 ENTRY(call_rwsem_down_read_failed)
        CFI_STARTPROC
        save_common_regs
-       __ASM_SIZE(push,_cfi) %__ASM_REG(dx)
-       CFI_REL_OFFSET __ASM_REG(dx), 0
+       __ASM_SIZE(push,_cfi_reg) __ASM_REG(dx)
        movq %rax,%rdi
        call rwsem_down_read_failed
-       __ASM_SIZE(pop,_cfi) %__ASM_REG(dx)
-       CFI_RESTORE __ASM_REG(dx)
+       __ASM_SIZE(pop,_cfi_reg) __ASM_REG(dx)
        restore_common_regs
        ret
        CFI_ENDPROC
@@ -124,12 +122,10 @@ ENDPROC(call_rwsem_wake)
 ENTRY(call_rwsem_downgrade_wake)
        CFI_STARTPROC
        save_common_regs
-       __ASM_SIZE(push,_cfi) %__ASM_REG(dx)
-       CFI_REL_OFFSET __ASM_REG(dx), 0
+       __ASM_SIZE(push,_cfi_reg) __ASM_REG(dx)
        movq %rax,%rdi
        call rwsem_downgrade_wake
-       __ASM_SIZE(pop,_cfi) %__ASM_REG(dx)
-       CFI_RESTORE __ASM_REG(dx)
+       __ASM_SIZE(pop,_cfi_reg) __ASM_REG(dx)
        restore_common_regs
        ret
        CFI_ENDPROC
index e28cdaf5ac2c629cd8bca126a55a45745e403534..5eb715087b804e7d9cad520b46488c0270740d7c 100644 (file)
        .globl \name
 \name:
        CFI_STARTPROC
-       pushl_cfi %eax
-       CFI_REL_OFFSET eax, 0
-       pushl_cfi %ecx
-       CFI_REL_OFFSET ecx, 0
-       pushl_cfi %edx
-       CFI_REL_OFFSET edx, 0
+       pushl_cfi_reg eax
+       pushl_cfi_reg ecx
+       pushl_cfi_reg edx
 
        .if \put_ret_addr_in_eax
        /* Place EIP in the arg1 */
        .endif
 
        call \func
-       popl_cfi %edx
-       CFI_RESTORE edx
-       popl_cfi %ecx
-       CFI_RESTORE ecx
-       popl_cfi %eax
-       CFI_RESTORE eax
+       popl_cfi_reg edx
+       popl_cfi_reg ecx
+       popl_cfi_reg eax
        ret
        CFI_ENDPROC
        _ASM_NOKPROBE(\name)
index b30b5ebd614ada18d25b3fb7403f7a32e32a96d9..f89ba4e93025dec7c45480600a0ef567d4696e0a 100644 (file)
        CFI_STARTPROC
 
        /* this one pushes 9 elems, the next one would be %rIP */
-       SAVE_ARGS
+       pushq_cfi_reg rdi
+       pushq_cfi_reg rsi
+       pushq_cfi_reg rdx
+       pushq_cfi_reg rcx
+       pushq_cfi_reg rax
+       pushq_cfi_reg r8
+       pushq_cfi_reg r9
+       pushq_cfi_reg r10
+       pushq_cfi_reg r11
 
        .if \put_ret_addr_in_rdi
+       /* 9*8(%rsp) is return addr on stack */
        movq_cfi_restore 9*8, rdi
        .endif
 
 #endif
 #endif
 
-       /* SAVE_ARGS below is used only for the .cfi directives it contains. */
+#if defined(CONFIG_TRACE_IRQFLAGS) \
+ || defined(CONFIG_DEBUG_LOCK_ALLOC) \
+ || defined(CONFIG_PREEMPT)
        CFI_STARTPROC
-       SAVE_ARGS
+       CFI_ADJUST_CFA_OFFSET 9*8
 restore:
-       RESTORE_ARGS
+       popq_cfi_reg r11
+       popq_cfi_reg r10
+       popq_cfi_reg r9
+       popq_cfi_reg r8
+       popq_cfi_reg rax
+       popq_cfi_reg rcx
+       popq_cfi_reg rdx
+       popq_cfi_reg rsi
+       popq_cfi_reg rdi
        ret
        CFI_ENDPROC
        _ASM_NOKPROBE(restore)
+#endif
index c905e89e19feb5ff79778a11a162dfbaa88852a9..1f33b3d1fd68239c9bb07840d287bcee5d2d26b8 100644 (file)
@@ -69,21 +69,20 @@ EXPORT_SYMBOL(copy_in_user);
  * it is not necessary to optimize tail handling.
  */
 __visible unsigned long
-copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest)
+copy_user_handle_tail(char *to, char *from, unsigned len)
 {
-       char c;
-       unsigned zero_len;
-
        for (; len; --len, to++) {
+               char c;
+
                if (__get_user_nocheck(c, from++, sizeof(char)))
                        break;
                if (__put_user_nocheck(c, to, sizeof(char)))
                        break;
        }
-
-       for (c = 0, zero_len = len; zerorest && zero_len; --zero_len)
-               if (__put_user_nocheck(c, to++, sizeof(char)))
-                       break;
        clac();
+
+       /* If the destination is a kernel buffer, we always clear the end */
+       if ((unsigned long)to >= TASK_SIZE_MAX)
+               memset(to, 0, len);
        return len;
 }
index 1a2be7c6895d811be12083b5dab49f92cfb8791f..816488c0b97e3540a59af5c5f4c001fed1f5ba41 100644 (file)
@@ -273,6 +273,9 @@ dd: ESC
 de: ESC
 df: ESC
 # 0xe0 - 0xef
+# Note: "forced64" is Intel CPU behavior: they ignore 0x66 prefix
+# in 64-bit mode. AMD CPUs accept 0x66 prefix, it causes RIP truncation
+# to 16 bits. In 32-bit mode, 0x66 is accepted by both Intel and AMD.
 e0: LOOPNE/LOOPNZ Jb (f64)
 e1: LOOPE/LOOPZ Jb (f64)
 e2: LOOP Jb (f64)
@@ -281,6 +284,10 @@ e4: IN AL,Ib
 e5: IN eAX,Ib
 e6: OUT Ib,AL
 e7: OUT Ib,eAX
+# With 0x66 prefix in 64-bit mode, for AMD CPUs immediate offset
+# in "near" jumps and calls is 16-bit. For CALL,
+# push of return address is 16-bit wide, RSP is decremented by 2
+# but is not truncated to 16 bits, unlike RIP.
 e8: CALL Jz (f64)
 e9: JMP-near Jz (f64)
 ea: JMP-far Ap (i64)
@@ -456,6 +463,7 @@ AVXcode: 1
 7e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1)
 7f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqu Wx,Vx (F3)
 # 0x0f 0x80-0x8f
+# Note: "forced64" is Intel CPU behavior (see comment about CALL insn).
 80: JO Jz (f64)
 81: JNO Jz (f64)
 82: JB/JC/JNAE Jz (f64)
@@ -842,6 +850,7 @@ EndTable
 GrpTable: Grp5
 0: INC Ev
 1: DEC Ev
+# Note: "forced64" is Intel CPU behavior (see comment about CALL insn).
 2: CALLN Ev (f64)
 3: CALLF Ep
 4: JMPN Ev (f64)
index c4cc74006c61965b95e8d6035891eb5ef3a7cdff..a482d105172b68766b8cdfc89717a1623bc24a23 100644 (file)
@@ -32,6 +32,4 @@ obj-$(CONFIG_AMD_NUMA)                += amdtopology.o
 obj-$(CONFIG_ACPI_NUMA)                += srat.o
 obj-$(CONFIG_NUMA_EMU)         += numa_emulation.o
 
-obj-$(CONFIG_MEMTEST)          += memtest.o
-
 obj-$(CONFIG_X86_INTEL_MPX)    += mpx.o
index ede025fb46f137ed7576cd5a06547264356c25b0..181c53bac3a7ee8881b8844bae66b951d9beecde 100644 (file)
@@ -59,7 +59,7 @@ static nokprobe_inline int kprobes_fault(struct pt_regs *regs)
        int ret = 0;
 
        /* kprobe_running() needs smp_processor_id() */
-       if (kprobes_built_in() && !user_mode_vm(regs)) {
+       if (kprobes_built_in() && !user_mode(regs)) {
                preempt_disable();
                if (kprobe_running() && kprobe_fault_handler(regs, 14))
                        ret = 1;
@@ -148,7 +148,7 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
        instr = (void *)convert_ip_to_linear(current, regs);
        max_instr = instr + 15;
 
-       if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE)
+       if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE_MAX)
                return 0;
 
        while (instr < max_instr) {
@@ -1035,7 +1035,7 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs)
        if (error_code & PF_USER)
                return false;
 
-       if (!user_mode_vm(regs) && (regs->flags & X86_EFLAGS_AC))
+       if (!user_mode(regs) && (regs->flags & X86_EFLAGS_AC))
                return false;
 
        return true;
@@ -1140,7 +1140,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code,
         * User-mode registers count as a user access even for any
         * potential system fault or CPU buglet:
         */
-       if (user_mode_vm(regs)) {
+       if (user_mode(regs)) {
                local_irq_enable();
                error_code |= PF_USER;
                flags |= FAULT_FLAG_USER;
index a110efca6d068f7d881f8c1d955d8a6906457f64..1d553186c4345c02be5c0152764d988cfe365ae1 100644 (file)
 
 /*
  * Tables translating between page_cache_type_t and pte encoding.
- * Minimal supported modes are defined statically, modified if more supported
- * cache modes are available.
- * Index into __cachemode2pte_tbl is the cachemode.
- * Index into __pte2cachemode_tbl are the caching attribute bits of the pte
- * (_PAGE_PWT, _PAGE_PCD, _PAGE_PAT) at index bit positions 0, 1, 2.
+ *
+ * Minimal supported modes are defined statically, they are modified
+ * during bootup if more supported cache modes are available.
+ *
+ *   Index into __cachemode2pte_tbl[] is the cachemode.
+ *
+ *   Index into __pte2cachemode_tbl[] are the caching attribute bits of the pte
+ *   (_PAGE_PWT, _PAGE_PCD, _PAGE_PAT) at index bit positions 0, 1, 2.
  */
 uint16_t __cachemode2pte_tbl[_PAGE_CACHE_MODE_NUM] = {
-       [_PAGE_CACHE_MODE_WB]           = 0,
-       [_PAGE_CACHE_MODE_WC]           = _PAGE_PWT,
-       [_PAGE_CACHE_MODE_UC_MINUS]     = _PAGE_PCD,
-       [_PAGE_CACHE_MODE_UC]           = _PAGE_PCD | _PAGE_PWT,
-       [_PAGE_CACHE_MODE_WT]           = _PAGE_PCD,
-       [_PAGE_CACHE_MODE_WP]           = _PAGE_PCD,
+       [_PAGE_CACHE_MODE_WB      ]     = 0         | 0        ,
+       [_PAGE_CACHE_MODE_WC      ]     = _PAGE_PWT | 0        ,
+       [_PAGE_CACHE_MODE_UC_MINUS]     = 0         | _PAGE_PCD,
+       [_PAGE_CACHE_MODE_UC      ]     = _PAGE_PWT | _PAGE_PCD,
+       [_PAGE_CACHE_MODE_WT      ]     = 0         | _PAGE_PCD,
+       [_PAGE_CACHE_MODE_WP      ]     = 0         | _PAGE_PCD,
 };
 EXPORT_SYMBOL(__cachemode2pte_tbl);
+
 uint8_t __pte2cachemode_tbl[8] = {
-       [__pte2cm_idx(0)] = _PAGE_CACHE_MODE_WB,
-       [__pte2cm_idx(_PAGE_PWT)] = _PAGE_CACHE_MODE_WC,
-       [__pte2cm_idx(_PAGE_PCD)] = _PAGE_CACHE_MODE_UC_MINUS,
-       [__pte2cm_idx(_PAGE_PWT | _PAGE_PCD)] = _PAGE_CACHE_MODE_UC,
-       [__pte2cm_idx(_PAGE_PAT)] = _PAGE_CACHE_MODE_WB,
-       [__pte2cm_idx(_PAGE_PWT | _PAGE_PAT)] = _PAGE_CACHE_MODE_WC,
-       [__pte2cm_idx(_PAGE_PCD | _PAGE_PAT)] = _PAGE_CACHE_MODE_UC_MINUS,
+       [__pte2cm_idx( 0        | 0         | 0        )] = _PAGE_CACHE_MODE_WB,
+       [__pte2cm_idx(_PAGE_PWT | 0         | 0        )] = _PAGE_CACHE_MODE_WC,
+       [__pte2cm_idx( 0        | _PAGE_PCD | 0        )] = _PAGE_CACHE_MODE_UC_MINUS,
+       [__pte2cm_idx(_PAGE_PWT | _PAGE_PCD | 0        )] = _PAGE_CACHE_MODE_UC,
+       [__pte2cm_idx( 0        | 0         | _PAGE_PAT)] = _PAGE_CACHE_MODE_WB,
+       [__pte2cm_idx(_PAGE_PWT | 0         | _PAGE_PAT)] = _PAGE_CACHE_MODE_WC,
+       [__pte2cm_idx(0         | _PAGE_PCD | _PAGE_PAT)] = _PAGE_CACHE_MODE_UC_MINUS,
        [__pte2cm_idx(_PAGE_PWT | _PAGE_PCD | _PAGE_PAT)] = _PAGE_CACHE_MODE_UC,
 };
 EXPORT_SYMBOL(__pte2cachemode_tbl);
@@ -131,21 +135,7 @@ void  __init early_alloc_pgt_buf(void)
 
 int after_bootmem;
 
-int direct_gbpages
-#ifdef CONFIG_DIRECT_GBPAGES
-                               = 1
-#endif
-;
-
-static void __init init_gbpages(void)
-{
-#ifdef CONFIG_X86_64
-       if (direct_gbpages && cpu_has_gbpages)
-               printk(KERN_INFO "Using GB pages for direct mapping\n");
-       else
-               direct_gbpages = 0;
-#endif
-}
+early_param_on_off("gbpages", "nogbpages", direct_gbpages, CONFIG_X86_DIRECT_GBPAGES);
 
 struct map_range {
        unsigned long start;
@@ -157,16 +147,12 @@ static int page_size_mask;
 
 static void __init probe_page_size_mask(void)
 {
-       init_gbpages();
-
 #if !defined(CONFIG_DEBUG_PAGEALLOC) && !defined(CONFIG_KMEMCHECK)
        /*
         * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
         * This will simplify cpa(), which otherwise needs to support splitting
         * large pages into small in interrupt context, etc.
         */
-       if (direct_gbpages)
-               page_size_mask |= 1 << PG_LEVEL_1G;
        if (cpu_has_pse)
                page_size_mask |= 1 << PG_LEVEL_2M;
 #endif
@@ -179,6 +165,15 @@ static void __init probe_page_size_mask(void)
        if (cpu_has_pge) {
                cr4_set_bits_and_update_boot(X86_CR4_PGE);
                __supported_pte_mask |= _PAGE_GLOBAL;
+       } else
+               __supported_pte_mask &= ~_PAGE_GLOBAL;
+
+       /* Enable 1 GB linear kernel mappings if available: */
+       if (direct_gbpages && cpu_has_gbpages) {
+               printk(KERN_INFO "Using GB pages for direct mapping\n");
+               page_size_mask |= 1 << PG_LEVEL_1G;
+       } else {
+               direct_gbpages = 0;
        }
 }
 
index 30eb05ae7061624f7faee0077ce41bddb4991ef7..3fba623e3ba558553d9740d3a994343a2960428f 100644 (file)
@@ -130,20 +130,6 @@ int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
        return 0;
 }
 
-static int __init parse_direct_gbpages_off(char *arg)
-{
-       direct_gbpages = 0;
-       return 0;
-}
-early_param("nogbpages", parse_direct_gbpages_off);
-
-static int __init parse_direct_gbpages_on(char *arg)
-{
-       direct_gbpages = 1;
-       return 0;
-}
-early_param("gbpages", parse_direct_gbpages_on);
-
 /*
  * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
  * physical space so we can cache the place of the first one and move
index fdf617c00e2fecad500e4a58c5fc71fc801a105d..5ead4d6cf3a7ae4173265924246415b8fa12d520 100644 (file)
@@ -67,8 +67,13 @@ static int __ioremap_check_ram(unsigned long start_pfn, unsigned long nr_pages,
 
 /*
  * Remap an arbitrary physical address space into the kernel virtual
- * address space. Needed when the kernel wants to access high addresses
- * directly.
+ * address space. It transparently creates kernel huge I/O mapping when
+ * the physical address is aligned by a huge page size (1GB or 2MB) and
+ * the requested size is at least the huge page size.
+ *
+ * NOTE: MTRRs can override PAT memory types with a 4KB granularity.
+ * Therefore, the mapping code falls back to use a smaller page toward 4KB
+ * when a mapping range is covered by non-WB type of MTRRs.
  *
  * NOTE! We need to allow non-page-aligned mappings too: we will obviously
  * have to convert them into an offset in a page-aligned mapping, but the
@@ -326,6 +331,20 @@ void iounmap(volatile void __iomem *addr)
 }
 EXPORT_SYMBOL(iounmap);
 
+int arch_ioremap_pud_supported(void)
+{
+#ifdef CONFIG_X86_64
+       return cpu_has_gbpages;
+#else
+       return 0;
+#endif
+}
+
+int arch_ioremap_pmd_supported(void)
+{
+       return cpu_has_pse;
+}
+
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
  * access
diff --git a/arch/x86/mm/memtest.c b/arch/x86/mm/memtest.c
deleted file mode 100644 (file)
index 1e9da79..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/pfn.h>
-#include <linux/memblock.h>
-
-static u64 patterns[] __initdata = {
-       /* The first entry has to be 0 to leave memtest with zeroed memory */
-       0,
-       0xffffffffffffffffULL,
-       0x5555555555555555ULL,
-       0xaaaaaaaaaaaaaaaaULL,
-       0x1111111111111111ULL,
-       0x2222222222222222ULL,
-       0x4444444444444444ULL,
-       0x8888888888888888ULL,
-       0x3333333333333333ULL,
-       0x6666666666666666ULL,
-       0x9999999999999999ULL,
-       0xccccccccccccccccULL,
-       0x7777777777777777ULL,
-       0xbbbbbbbbbbbbbbbbULL,
-       0xddddddddddddddddULL,
-       0xeeeeeeeeeeeeeeeeULL,
-       0x7a6c7258554e494cULL, /* yeah ;-) */
-};
-
-static void __init reserve_bad_mem(u64 pattern, u64 start_bad, u64 end_bad)
-{
-       printk(KERN_INFO "  %016llx bad mem addr %010llx - %010llx reserved\n",
-              (unsigned long long) pattern,
-              (unsigned long long) start_bad,
-              (unsigned long long) end_bad);
-       memblock_reserve(start_bad, end_bad - start_bad);
-}
-
-static void __init memtest(u64 pattern, u64 start_phys, u64 size)
-{
-       u64 *p, *start, *end;
-       u64 start_bad, last_bad;
-       u64 start_phys_aligned;
-       const size_t incr = sizeof(pattern);
-
-       start_phys_aligned = ALIGN(start_phys, incr);
-       start = __va(start_phys_aligned);
-       end = start + (size - (start_phys_aligned - start_phys)) / incr;
-       start_bad = 0;
-       last_bad = 0;
-
-       for (p = start; p < end; p++)
-               *p = pattern;
-
-       for (p = start; p < end; p++, start_phys_aligned += incr) {
-               if (*p == pattern)
-                       continue;
-               if (start_phys_aligned == last_bad + incr) {
-                       last_bad += incr;
-                       continue;
-               }
-               if (start_bad)
-                       reserve_bad_mem(pattern, start_bad, last_bad + incr);
-               start_bad = last_bad = start_phys_aligned;
-       }
-       if (start_bad)
-               reserve_bad_mem(pattern, start_bad, last_bad + incr);
-}
-
-static void __init do_one_pass(u64 pattern, u64 start, u64 end)
-{
-       u64 i;
-       phys_addr_t this_start, this_end;
-
-       for_each_free_mem_range(i, NUMA_NO_NODE, &this_start, &this_end, NULL) {
-               this_start = clamp_t(phys_addr_t, this_start, start, end);
-               this_end = clamp_t(phys_addr_t, this_end, start, end);
-               if (this_start < this_end) {
-                       printk(KERN_INFO "  %010llx - %010llx pattern %016llx\n",
-                              (unsigned long long)this_start,
-                              (unsigned long long)this_end,
-                              (unsigned long long)cpu_to_be64(pattern));
-                       memtest(pattern, this_start, this_end - this_start);
-               }
-       }
-}
-
-/* default is disabled */
-static int memtest_pattern __initdata;
-
-static int __init parse_memtest(char *arg)
-{
-       if (arg)
-               memtest_pattern = simple_strtoul(arg, NULL, 0);
-       else
-               memtest_pattern = ARRAY_SIZE(patterns);
-
-       return 0;
-}
-
-early_param("memtest", parse_memtest);
-
-void __init early_memtest(unsigned long start, unsigned long end)
-{
-       unsigned int i;
-       unsigned int idx = 0;
-
-       if (!memtest_pattern)
-               return;
-
-       printk(KERN_INFO "early_memtest: # of tests: %d\n", memtest_pattern);
-       for (i = memtest_pattern-1; i < UINT_MAX; --i) {
-               idx = i % ARRAY_SIZE(patterns);
-               do_one_pass(patterns[idx], start, end);
-       }
-}
index df4552bd239e03b4a02e6505454e41420d530461..9d518d693b4b7adf07463c695f3cd14412a19192 100644 (file)
@@ -65,24 +65,23 @@ static int mmap_is_legacy(void)
        return sysctl_legacy_va_layout;
 }
 
-static unsigned long mmap_rnd(void)
+unsigned long arch_mmap_rnd(void)
 {
-       unsigned long rnd = 0;
+       unsigned long rnd;
 
        /*
-       *  8 bits of randomness in 32bit mmaps, 20 address space bits
-       * 28 bits of randomness in 64bit mmaps, 40 address space bits
-       */
-       if (current->flags & PF_RANDOMIZE) {
-               if (mmap_is_ia32())
-                       rnd = get_random_int() % (1<<8);
-               else
-                       rnd = get_random_int() % (1<<28);
-       }
+        *  8 bits of randomness in 32bit mmaps, 20 address space bits
+        * 28 bits of randomness in 64bit mmaps, 40 address space bits
+        */
+       if (mmap_is_ia32())
+               rnd = (unsigned long)get_random_int() % (1<<8);
+       else
+               rnd = (unsigned long)get_random_int() % (1<<28);
+
        return rnd << PAGE_SHIFT;
 }
 
-static unsigned long mmap_base(void)
+static unsigned long mmap_base(unsigned long rnd)
 {
        unsigned long gap = rlimit(RLIMIT_STACK);
 
@@ -91,19 +90,19 @@ static unsigned long mmap_base(void)
        else if (gap > MAX_GAP)
                gap = MAX_GAP;
 
-       return PAGE_ALIGN(TASK_SIZE - gap - mmap_rnd());
+       return PAGE_ALIGN(TASK_SIZE - gap - rnd);
 }
 
 /*
  * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64
  * does, but not when emulating X86_32
  */
-static unsigned long mmap_legacy_base(void)
+static unsigned long mmap_legacy_base(unsigned long rnd)
 {
        if (mmap_is_ia32())
                return TASK_UNMAPPED_BASE;
        else
-               return TASK_UNMAPPED_BASE + mmap_rnd();
+               return TASK_UNMAPPED_BASE + rnd;
 }
 
 /*
@@ -112,13 +111,18 @@ static unsigned long mmap_legacy_base(void)
  */
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
-       mm->mmap_legacy_base = mmap_legacy_base();
-       mm->mmap_base = mmap_base();
+       unsigned long random_factor = 0UL;
+
+       if (current->flags & PF_RANDOMIZE)
+               random_factor = arch_mmap_rnd();
+
+       mm->mmap_legacy_base = mmap_legacy_base(random_factor);
 
        if (mmap_is_legacy()) {
                mm->mmap_base = mm->mmap_legacy_base;
                mm->get_unmapped_area = arch_get_unmapped_area;
        } else {
+               mm->mmap_base = mmap_base(random_factor);
                mm->get_unmapped_area = arch_get_unmapped_area_topdown;
        }
 }
index cd4785bbacb9a86366ccd74121e5161b078e9596..4053bb58bf92e6c328936aed1c8439b528468e1d 100644 (file)
@@ -482,9 +482,16 @@ static void __init numa_clear_kernel_node_hotplug(void)
                                  &memblock.reserved, mb->nid);
        }
 
-       /* Mark all kernel nodes. */
+       /*
+        * Mark all kernel nodes.
+        *
+        * When booting with mem=nn[kMG] or in a kdump kernel, numa_meminfo
+        * may not include all the memblock.reserved memory ranges because
+        * trim_snb_memory() reserves specific pages for Sandy Bridge graphics.
+        */
        for_each_memblock(reserved, r)
-               node_set(r->nid, numa_kernel_nodes);
+               if (r->nid != MAX_NUMNODES)
+                       node_set(r->nid, numa_kernel_nodes);
 
        /* Clear MEMBLOCK_HOTPLUG flag for memory in kernel nodes. */
        for (i = 0; i < numa_meminfo.nr_blks; i++) {
index 536ea2fb6e335677df559390520c3312976dcb81..89af288ec6740cfd793a4c4804e939bb023e9453 100644 (file)
@@ -81,11 +81,9 @@ void arch_report_meminfo(struct seq_file *m)
        seq_printf(m, "DirectMap4M:    %8lu kB\n",
                        direct_pages_count[PG_LEVEL_2M] << 12);
 #endif
-#ifdef CONFIG_X86_64
        if (direct_gbpages)
                seq_printf(m, "DirectMap1G:    %8lu kB\n",
                        direct_pages_count[PG_LEVEL_1G] << 20);
-#endif
 }
 #else
 static inline void split_page_count(int level) { }
@@ -1654,13 +1652,11 @@ int set_memory_ro(unsigned long addr, int numpages)
 {
        return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_RW), 0);
 }
-EXPORT_SYMBOL_GPL(set_memory_ro);
 
 int set_memory_rw(unsigned long addr, int numpages)
 {
        return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_RW), 0);
 }
-EXPORT_SYMBOL_GPL(set_memory_rw);
 
 int set_memory_np(unsigned long addr, int numpages)
 {
index 7ac68698406c3b35e5ce0b0e98c73c5441e869a3..35af6771a95ad6c126cca1f352b896998116876e 100644 (file)
@@ -610,7 +610,7 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 }
 
 #ifdef CONFIG_STRICT_DEVMEM
-/* This check is done in drivers/char/mem.c in case of STRICT_DEVMEM*/
+/* This check is done in drivers/char/mem.c in case of STRICT_DEVMEM */
 static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 {
        return 1;
@@ -628,8 +628,8 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 
        while (cursor < to) {
                if (!devmem_is_allowed(pfn)) {
-                       printk(KERN_INFO "Program %s tried to access /dev/mem between [mem %#010Lx-%#010Lx]\n",
-                               current->comm, from, to - 1);
+                       printk(KERN_INFO "Program %s tried to access /dev/mem between [mem %#010Lx-%#010Lx], PAT prevents it\n",
+                              current->comm, from, to - 1);
                        return 0;
                }
                cursor += PAGE_SIZE;
index 7b22adaad4f1379a1195aec23b38a28a8db83f5c..0b97d2c75df3d5fc05b1caafdadce2972660543d 100644 (file)
@@ -4,6 +4,7 @@
 #include <asm/pgtable.h>
 #include <asm/tlb.h>
 #include <asm/fixmap.h>
+#include <asm/mtrr.h>
 
 #define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO
 
@@ -58,7 +59,7 @@ void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
        tlb_remove_page(tlb, pte);
 }
 
-#if PAGETABLE_LEVELS > 2
+#if CONFIG_PGTABLE_LEVELS > 2
 void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
 {
        struct page *page = virt_to_page(pmd);
@@ -74,14 +75,14 @@ void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
        tlb_remove_page(tlb, page);
 }
 
-#if PAGETABLE_LEVELS > 3
+#if CONFIG_PGTABLE_LEVELS > 3
 void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
 {
        paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
        tlb_remove_page(tlb, virt_to_page(pud));
 }
-#endif /* PAGETABLE_LEVELS > 3 */
-#endif /* PAGETABLE_LEVELS > 2 */
+#endif /* CONFIG_PGTABLE_LEVELS > 3 */
+#endif /* CONFIG_PGTABLE_LEVELS > 2 */
 
 static inline void pgd_list_add(pgd_t *pgd)
 {
@@ -117,9 +118,9 @@ static void pgd_ctor(struct mm_struct *mm, pgd_t *pgd)
        /* If the pgd points to a shared pagetable level (either the
           ptes in non-PAE, or shared PMD in PAE), then just copy the
           references from swapper_pg_dir. */
-       if (PAGETABLE_LEVELS == 2 ||
-           (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD) ||
-           PAGETABLE_LEVELS == 4) {
+       if (CONFIG_PGTABLE_LEVELS == 2 ||
+           (CONFIG_PGTABLE_LEVELS == 3 && SHARED_KERNEL_PMD) ||
+           CONFIG_PGTABLE_LEVELS == 4) {
                clone_pgd_range(pgd + KERNEL_PGD_BOUNDARY,
                                swapper_pg_dir + KERNEL_PGD_BOUNDARY,
                                KERNEL_PGD_PTRS);
@@ -275,12 +276,87 @@ static void pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmds[])
        }
 }
 
+/*
+ * Xen paravirt assumes pgd table should be in one page. 64 bit kernel also
+ * assumes that pgd should be in one page.
+ *
+ * But kernel with PAE paging that is not running as a Xen domain
+ * only needs to allocate 32 bytes for pgd instead of one page.
+ */
+#ifdef CONFIG_X86_PAE
+
+#include <linux/slab.h>
+
+#define PGD_SIZE       (PTRS_PER_PGD * sizeof(pgd_t))
+#define PGD_ALIGN      32
+
+static struct kmem_cache *pgd_cache;
+
+static int __init pgd_cache_init(void)
+{
+       /*
+        * When PAE kernel is running as a Xen domain, it does not use
+        * shared kernel pmd. And this requires a whole page for pgd.
+        */
+       if (!SHARED_KERNEL_PMD)
+               return 0;
+
+       /*
+        * when PAE kernel is not running as a Xen domain, it uses
+        * shared kernel pmd. Shared kernel pmd does not require a whole
+        * page for pgd. We are able to just allocate a 32-byte for pgd.
+        * During boot time, we create a 32-byte slab for pgd table allocation.
+        */
+       pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_ALIGN,
+                                     SLAB_PANIC, NULL);
+       if (!pgd_cache)
+               return -ENOMEM;
+
+       return 0;
+}
+core_initcall(pgd_cache_init);
+
+static inline pgd_t *_pgd_alloc(void)
+{
+       /*
+        * If no SHARED_KERNEL_PMD, PAE kernel is running as a Xen domain.
+        * We allocate one page for pgd.
+        */
+       if (!SHARED_KERNEL_PMD)
+               return (pgd_t *)__get_free_page(PGALLOC_GFP);
+
+       /*
+        * Now PAE kernel is not running as a Xen domain. We can allocate
+        * a 32-byte slab for pgd to save memory space.
+        */
+       return kmem_cache_alloc(pgd_cache, PGALLOC_GFP);
+}
+
+static inline void _pgd_free(pgd_t *pgd)
+{
+       if (!SHARED_KERNEL_PMD)
+               free_page((unsigned long)pgd);
+       else
+               kmem_cache_free(pgd_cache, pgd);
+}
+#else
+static inline pgd_t *_pgd_alloc(void)
+{
+       return (pgd_t *)__get_free_page(PGALLOC_GFP);
+}
+
+static inline void _pgd_free(pgd_t *pgd)
+{
+       free_page((unsigned long)pgd);
+}
+#endif /* CONFIG_X86_PAE */
+
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
        pgd_t *pgd;
        pmd_t *pmds[PREALLOCATED_PMDS];
 
-       pgd = (pgd_t *)__get_free_page(PGALLOC_GFP);
+       pgd = _pgd_alloc();
 
        if (pgd == NULL)
                goto out;
@@ -310,7 +386,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 out_free_pmds:
        free_pmds(mm, pmds);
 out_free_pgd:
-       free_page((unsigned long)pgd);
+       _pgd_free(pgd);
 out:
        return NULL;
 }
@@ -320,7 +396,7 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
        pgd_mop_up_pmds(mm, pgd);
        pgd_dtor(pgd);
        paravirt_pgd_free(mm, pgd);
-       free_page((unsigned long)pgd);
+       _pgd_free(pgd);
 }
 
 /*
@@ -485,3 +561,67 @@ void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys,
 {
        __native_set_fixmap(idx, pfn_pte(phys >> PAGE_SHIFT, flags));
 }
+
+#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
+int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
+{
+       u8 mtrr;
+
+       /*
+        * Do not use a huge page when the range is covered by non-WB type
+        * of MTRRs.
+        */
+       mtrr = mtrr_type_lookup(addr, addr + PUD_SIZE);
+       if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != 0xFF))
+               return 0;
+
+       prot = pgprot_4k_2_large(prot);
+
+       set_pte((pte_t *)pud, pfn_pte(
+               (u64)addr >> PAGE_SHIFT,
+               __pgprot(pgprot_val(prot) | _PAGE_PSE)));
+
+       return 1;
+}
+
+int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot)
+{
+       u8 mtrr;
+
+       /*
+        * Do not use a huge page when the range is covered by non-WB type
+        * of MTRRs.
+        */
+       mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE);
+       if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != 0xFF))
+               return 0;
+
+       prot = pgprot_4k_2_large(prot);
+
+       set_pte((pte_t *)pmd, pfn_pte(
+               (u64)addr >> PAGE_SHIFT,
+               __pgprot(pgprot_val(prot) | _PAGE_PSE)));
+
+       return 1;
+}
+
+int pud_clear_huge(pud_t *pud)
+{
+       if (pud_large(*pud)) {
+               pud_clear(pud);
+               return 1;
+       }
+
+       return 0;
+}
+
+int pmd_clear_huge(pmd_t *pmd)
+{
+       if (pmd_large(*pmd)) {
+               pmd_clear(pmd);
+               return 1;
+       }
+
+       return 0;
+}
+#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
index 5d04be5efb6401b1b7512f4ca519a24a016b20d2..4e664bdb535ad89d09633fd73ea6eca5a46d4097 100644 (file)
@@ -111,7 +111,7 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth)
 {
        struct stack_frame *head = (struct stack_frame *)frame_pointer(regs);
 
-       if (!user_mode_vm(regs)) {
+       if (!user_mode(regs)) {
                unsigned long stack = kernel_stack_pointer(regs);
                if (depth)
                        dump_trace(NULL, regs, (unsigned long *)stack, 0,
index 2fb384724ebb52d1cf0ba6131b418e81609ca55c..8fd6f44aee8370958076fb4a8af3e13a2781fe33 100644 (file)
@@ -490,7 +490,9 @@ void pcibios_scan_root(int busnum)
        if (!bus) {
                pci_free_resource_list(&resources);
                kfree(sd);
+               return;
        }
+       pci_bus_add_devices(bus);
 }
 
 void __init pcibios_set_cache_line_size(void)
index d143d216d52bec69b912128d88c3283cd0122c6c..d7f997f7c26d2502a1a188583d6817c3672417d1 100644 (file)
@@ -67,7 +67,7 @@ void __init efi_bgrt_init(void)
 
        image = efi_lookup_mapped_addr(bgrt_tab->image_address);
        if (!image) {
-               image = early_memremap(bgrt_tab->image_address,
+               image = early_ioremap(bgrt_tab->image_address,
                                       sizeof(bmp_header));
                ioremapped = true;
                if (!image) {
@@ -89,7 +89,7 @@ void __init efi_bgrt_init(void)
        }
 
        if (ioremapped) {
-               image = early_memremap(bgrt_tab->image_address,
+               image = early_ioremap(bgrt_tab->image_address,
                                       bmp_header.size);
                if (!image) {
                        pr_err("Ignoring BGRT: failed to map image memory\n");
index dbc8627a5cdf6d569a5f69cbea05ebac924d2279..02744df576d52588a35308998ecc1a138435012e 100644 (file)
@@ -85,12 +85,20 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
        efi_memory_desc_t *virtual_map)
 {
        efi_status_t status;
+       unsigned long flags;
+       pgd_t *save_pgd;
 
-       efi_call_phys_prolog();
+       save_pgd = efi_call_phys_prolog();
+
+       /* Disable interrupts around EFI calls: */
+       local_irq_save(flags);
        status = efi_call_phys(efi_phys.set_virtual_address_map,
                               memory_map_size, descriptor_size,
                               descriptor_version, virtual_map);
-       efi_call_phys_epilog();
+       local_irq_restore(flags);
+
+       efi_call_phys_epilog(save_pgd);
+
        return status;
 }
 
@@ -491,7 +499,8 @@ void __init efi_init(void)
        if (efi_memmap_init())
                return;
 
-       print_efi_memmap();
+       if (efi_enabled(EFI_DBG))
+               print_efi_memmap();
 }
 
 void __init efi_late_init(void)
@@ -939,6 +948,8 @@ static int __init arch_parse_efi_cmdline(char *str)
 {
        if (parse_option_str(str, "old_map"))
                set_bit(EFI_OLD_MEMMAP, &efi.flags);
+       if (parse_option_str(str, "debug"))
+               set_bit(EFI_DBG, &efi.flags);
 
        return 0;
 }
index 40e7cda529365133b50bab8745d9995c47557d53..ed5b67338294f1325fffe5f7d9fce637731d5917 100644 (file)
 
 /*
  * To make EFI call EFI runtime service in physical addressing mode we need
- * prolog/epilog before/after the invocation to disable interrupt, to
- * claim EFI runtime service handler exclusively and to duplicate a memory in
- * low memory space say 0 - 3G.
+ * prolog/epilog before/after the invocation to claim the EFI runtime service
+ * handler exclusively and to duplicate a memory mapping in low memory space,
+ * say 0 - 3G.
  */
-static unsigned long efi_rt_eflags;
 
 void efi_sync_low_kernel_mappings(void) {}
 void __init efi_dump_pagetable(void) {}
@@ -57,21 +56,24 @@ void __init efi_map_region(efi_memory_desc_t *md)
 void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
 void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}
 
-void __init efi_call_phys_prolog(void)
+pgd_t * __init efi_call_phys_prolog(void)
 {
        struct desc_ptr gdt_descr;
+       pgd_t *save_pgd;
 
-       local_irq_save(efi_rt_eflags);
-
+       /* Current pgd is swapper_pg_dir, we'll restore it later: */
+       save_pgd = swapper_pg_dir;
        load_cr3(initial_page_table);
        __flush_tlb_all();
 
        gdt_descr.address = __pa(get_cpu_gdt_table(0));
        gdt_descr.size = GDT_SIZE - 1;
        load_gdt(&gdt_descr);
+
+       return save_pgd;
 }
 
-void __init efi_call_phys_epilog(void)
+void __init efi_call_phys_epilog(pgd_t *save_pgd)
 {
        struct desc_ptr gdt_descr;
 
@@ -79,10 +81,8 @@ void __init efi_call_phys_epilog(void)
        gdt_descr.size = GDT_SIZE - 1;
        load_gdt(&gdt_descr);
 
-       load_cr3(swapper_pg_dir);
+       load_cr3(save_pgd);
        __flush_tlb_all();
-
-       local_irq_restore(efi_rt_eflags);
 }
 
 void __init efi_runtime_mkexec(void)
index 17e80d829df0391536ea49379108d1383a39c46f..a0ac0f9c307f661c8b3ed08c4ca6d23507772e36 100644 (file)
@@ -41,9 +41,6 @@
 #include <asm/realmode.h>
 #include <asm/time.h>
 
-static pgd_t *save_pgd __initdata;
-static unsigned long efi_flags __initdata;
-
 /*
  * We allocate runtime services regions bottom-up, starting from -4G, i.e.
  * 0xffff_ffff_0000_0000 and limit EFI VA mapping space to 64G.
@@ -78,17 +75,18 @@ static void __init early_code_mapping_set_exec(int executable)
        }
 }
 
-void __init efi_call_phys_prolog(void)
+pgd_t * __init efi_call_phys_prolog(void)
 {
        unsigned long vaddress;
+       pgd_t *save_pgd;
+
        int pgd;
        int n_pgds;
 
        if (!efi_enabled(EFI_OLD_MEMMAP))
-               return;
+               return NULL;
 
        early_code_mapping_set_exec(1);
-       local_irq_save(efi_flags);
 
        n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE);
        save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL);
@@ -99,24 +97,29 @@ void __init efi_call_phys_prolog(void)
                set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress));
        }
        __flush_tlb_all();
+
+       return save_pgd;
 }
 
-void __init efi_call_phys_epilog(void)
+void __init efi_call_phys_epilog(pgd_t *save_pgd)
 {
        /*
         * After the lock is released, the original page table is restored.
         */
-       int pgd;
-       int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE);
+       int pgd_idx;
+       int nr_pgds;
 
-       if (!efi_enabled(EFI_OLD_MEMMAP))
+       if (!save_pgd)
                return;
 
-       for (pgd = 0; pgd < n_pgds; pgd++)
-               set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]);
+       nr_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE);
+
+       for (pgd_idx = 0; pgd_idx < nr_pgds; pgd_idx++)
+               set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), save_pgd[pgd_idx]);
+
        kfree(save_pgd);
+
        __flush_tlb_all();
-       local_irq_restore(efi_flags);
        early_code_mapping_set_exec(0);
 }
 
index c9a0838890e241692f6a03f4984485b6746c2f72..278e4da4222f79cf82aa2f8dcbe0e371243fb836 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <asm-generic/sections.h>
+#include <asm/cpu_device_id.h>
 #include <asm/imr.h>
 #include <linux/init.h>
 #include <linux/mm.h>
@@ -101,6 +102,12 @@ static void __init imr_self_test(void)
        }
 }
 
+static const struct x86_cpu_id imr_ids[] __initconst = {
+       { X86_VENDOR_INTEL, 5, 9 },     /* Intel Quark SoC X1000. */
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, imr_ids);
+
 /**
  * imr_self_test_init - entry point for IMR driver.
  *
@@ -108,7 +115,8 @@ static void __init imr_self_test(void)
  */
 static int __init imr_self_test_init(void)
 {
-       imr_self_test();
+       if (x86_match_cpu(imr_ids))
+               imr_self_test();
        return 0;
 }
 
index 9a2e590dd202b57c90d83b657eecc218a3fd4825..7fa8b3b53bc0a563737f1d32de8e467b79d85ce0 100644 (file)
@@ -61,7 +61,7 @@ static void battery_status_changed(void)
 
        if (psy) {
                power_supply_changed(psy);
-               put_device(psy->dev);
+               power_supply_put(psy);
        }
 }
 
@@ -71,7 +71,7 @@ static void ac_status_changed(void)
 
        if (psy) {
                power_supply_changed(psy);
-               put_device(psy->dev);
+               power_supply_put(psy);
        }
 }
 
index 08e350e757dcd189c29e06d4d0b199a2cd920b9f..55130846ac87afe11d50e7bdbcf77b77827838b0 100644 (file)
@@ -83,7 +83,7 @@ static void battery_status_changed(void)
 
        if (psy) {
                power_supply_changed(psy);
-               put_device(psy->dev);
+               power_supply_put(psy);
        }
 }
 
@@ -93,7 +93,7 @@ static void ac_status_changed(void)
 
        if (psy) {
                power_supply_changed(psy);
-               put_device(psy->dev);
+               power_supply_put(psy);
        }
 }
 
index 994798548b1ad57288e4b51c01422d3dad70ff7f..3b6ec42718e460717182c2762ffd7e6a005fff6f 100644 (file)
@@ -415,7 +415,7 @@ static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp)
        struct reset_args reset_args;
 
        reset_args.sender = sender;
-       cpus_clear(*mask);
+       cpumask_clear(mask);
        /* find a single cpu for each uvhub in this distribution mask */
        maskbits = sizeof(struct pnmask) * BITSPERBYTE;
        /* each bit is a pnode relative to the partition base pnode */
@@ -425,7 +425,7 @@ static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp)
                        continue;
                apnode = pnode + bcp->partition_base_pnode;
                cpu = pnode_to_first_cpu(apnode, smaster);
-               cpu_set(cpu, *mask);
+               cpumask_set_cpu(cpu, mask);
        }
 
        /* IPI all cpus; preemption is already disabled */
@@ -1126,7 +1126,7 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
        /* don't actually do a shootdown of the local cpu */
        cpumask_andnot(flush_mask, cpumask, cpumask_of(cpu));
 
-       if (cpu_isset(cpu, *cpumask))
+       if (cpumask_test_cpu(cpu, cpumask))
                stat->s_ntargself++;
 
        bau_desc = bcp->descriptor_base;
index 3e32ed5648a03894604976c4a9b2ae5c155c1750..757678fb26e1a06277687c1c90f86e75377de03a 100644 (file)
@@ -134,7 +134,7 @@ static void do_fpu_end(void)
 static void fix_processor_context(void)
 {
        int cpu = smp_processor_id();
-       struct tss_struct *t = &per_cpu(init_tss, cpu);
+       struct tss_struct *t = &per_cpu(cpu_tss, cpu);
 #ifdef CONFIG_X86_64
        struct desc_struct *desc = get_cpu_gdt_table(cpu);
        tss_desc tss;
index b3560ece1c9fbae0ff05c14824b76a07efdb0776..ef8187f9d28d96651d3d52e39d4441c60a408332 100644 (file)
 110    i386    iopl                    sys_iopl
 111    i386    vhangup                 sys_vhangup
 112    i386    idle
-113    i386    vm86old                 sys_vm86old                     sys32_vm86_warning
+113    i386    vm86old                 sys_vm86old                     sys_ni_syscall
 114    i386    wait4                   sys_wait4                       compat_sys_wait4
 115    i386    swapoff                 sys_swapoff
 116    i386    sysinfo                 sys_sysinfo                     compat_sys_sysinfo
 163    i386    mremap                  sys_mremap
 164    i386    setresuid               sys_setresuid16
 165    i386    getresuid               sys_getresuid16
-166    i386    vm86                    sys_vm86                        sys32_vm86_warning
+166    i386    vm86                    sys_vm86                        sys_ni_syscall
 167    i386    query_module
 168    i386    poll                    sys_poll
 169    i386    nfsservctl
index 8d656fbb57aab2606132858d48b2db7e99e8bf7c..9ef32d5f1b19e67ed10b69c67be5f53806c19ffa 100644 (file)
 169    common  reboot                  sys_reboot
 170    common  sethostname             sys_sethostname
 171    common  setdomainname           sys_setdomainname
-172    common  iopl                    stub_iopl
+172    common  iopl                    sys_iopl
 173    common  ioperm                  sys_ioperm
 174    64      create_module
 175    common  init_module             sys_init_module
index 2d7d9a1f5b531ee399b7a0e6a1f9eb4a190fd820..8ffd2146fa6a0367be6710913b5c4161f1a8859b 100644 (file)
@@ -64,8 +64,8 @@
  */
 static inline void rdtsc_barrier(void)
 {
-       alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
-       alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
+       alternative_2("", "mfence", X86_FEATURE_MFENCE_RDTSC,
+                         "lfence", X86_FEATURE_LFENCE_RDTSC);
 }
 
 #endif
index 5cdfa9db22175ed8dc327465b4cf033a7a65d3bc..a75d8700472a4f52db0211217cf7bbcd4f2dc1f5 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 /* Not going to be implemented by UML, since we have no hardware. */
-#define stub_iopl sys_ni_syscall
+#define sys_iopl sys_ni_syscall
 #define sys_ioperm sys_ni_syscall
 
 /*
index 7b9be9822724ebd96347bdb41c96fdcdb7a5504e..275a3a8b78afa3221b78296d2a7e3c2945de512b 100644 (file)
@@ -51,7 +51,7 @@ VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
 $(obj)/vdso64.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
        $(call if_changed,vdso)
 
-HOST_EXTRACFLAGS += -I$(srctree)/tools/include
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi
 hostprogs-y                    += vdso2c
 
 quiet_cmd_vdso2c = VDSO2C  $@
@@ -206,4 +206,4 @@ $(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso FORCE
 PHONY += vdso_install $(vdso_img_insttargets)
 vdso_install: $(vdso_img_insttargets) FORCE
 
-clean-files := vdso32-syscall* vdso32-sysenter* vdso32-int80* vdso64*
+clean-files := vdso32-syscall* vdso32-sysenter* vdso32-int80* vdso64* vdso-image-*.c vdsox32.so*
index 9793322751e02f63ddba0d1b8fef5f21b0a4d502..40d2473836c923acc5705018bf3aebf50cfb12b8 100644 (file)
@@ -82,18 +82,15 @@ static notrace cycle_t vread_pvclock(int *mode)
        cycle_t ret;
        u64 last;
        u32 version;
+       u32 migrate_count;
        u8 flags;
        unsigned cpu, cpu1;
 
 
        /*
-        * Note: hypervisor must guarantee that:
-        * 1. cpu ID number maps 1:1 to per-CPU pvclock time info.
-        * 2. that per-CPU pvclock time info is updated if the
-        *    underlying CPU changes.
-        * 3. that version is increased whenever underlying CPU
-        *    changes.
-        *
+        * When looping to get a consistent (time-info, tsc) pair, we
+        * also need to deal with the possibility we can switch vcpus,
+        * so make sure we always re-fetch time-info for the current vcpu.
         */
        do {
                cpu = __getcpu() & VGETCPU_CPU_MASK;
@@ -102,20 +99,27 @@ static notrace cycle_t vread_pvclock(int *mode)
                 * __getcpu() calls (Gleb).
                 */
 
-               pvti = get_pvti(cpu);
+               /* Make sure migrate_count will change if we leave the VCPU. */
+               do {
+                       pvti = get_pvti(cpu);
+                       migrate_count = pvti->migrate_count;
+
+                       cpu1 = cpu;
+                       cpu = __getcpu() & VGETCPU_CPU_MASK;
+               } while (unlikely(cpu != cpu1));
 
                version = __pvclock_read_cycles(&pvti->pvti, &ret, &flags);
 
                /*
                 * Test we're still on the cpu as well as the version.
-                * We could have been migrated just after the first
-                * vgetcpu but before fetching the version, so we
-                * wouldn't notice a version change.
+                * - We must read TSC of pvti's VCPU.
+                * - KVM doesn't follow the versioning protocol, so data could
+                *   change before version if we left the VCPU.
                 */
-               cpu1 = __getcpu() & VGETCPU_CPU_MASK;
-       } while (unlikely(cpu != cpu1 ||
-                         (pvti->pvti.version & 1) ||
-                         pvti->pvti.version != version));
+               smp_rmb();
+       } while (unlikely((pvti->pvti.version & 1) ||
+                         pvti->pvti.version != version ||
+                         pvti->migrate_count != migrate_count));
 
        if (unlikely(!(flags & PVCLOCK_TSC_STABLE_BIT)))
                *mode = VCLOCK_NONE;
index 5415b5613d5545b68dc88ee08de03f1061c48f8c..6b286bb5251ce1d15cc00299ae096e7518f03986 100644 (file)
@@ -19,8 +19,6 @@ __kernel_vsyscall:
 .Lpush_ebp:
        movl    %ecx, %ebp
        syscall
-       movl    $__USER32_DS, %ecx
-       movl    %ecx, %ss
        movl    %ebp, %ecx
        popl    %ebp
 .Lpop_ebp:
index 5240f563076de2e0e27c92af2d04ad03d213ee8f..81665c9f21327f3e7db5088a94cbcef127bb3d93 100644 (file)
@@ -912,6 +912,7 @@ static void xen_load_sp0(struct tss_struct *tss,
        mcs = xen_mc_entry(0);
        MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0);
        xen_mc_issue(PARAVIRT_LAZY_CPU);
+       tss->x86_tss.sp0 = thread->sp0;
 }
 
 static void xen_set_iopl_mask(unsigned mask)
index adca9e2b65536f2fa3d7be6f707207e9e1ae1708..65083ad63b6f7bcfbdf49a83d46669b745831791 100644 (file)
@@ -502,7 +502,7 @@ __visible pmd_t xen_make_pmd(pmdval_t pmd)
 }
 PV_CALLEE_SAVE_REGS_THUNK(xen_make_pmd);
 
-#if PAGETABLE_LEVELS == 4
+#if CONFIG_PGTABLE_LEVELS == 4
 __visible pudval_t xen_pud_val(pud_t pud)
 {
        return pte_mfn_to_pfn(pud.pud);
@@ -589,7 +589,7 @@ static void xen_set_pgd(pgd_t *ptr, pgd_t val)
 
        xen_mc_issue(PARAVIRT_LAZY_MMU);
 }
-#endif /* PAGETABLE_LEVELS == 4 */
+#endif /* CONFIG_PGTABLE_LEVELS == 4 */
 
 /*
  * (Yet another) pagetable walker.  This one is intended for pinning a
@@ -1628,7 +1628,7 @@ static void xen_release_pmd(unsigned long pfn)
        xen_release_ptpage(pfn, PT_PMD);
 }
 
-#if PAGETABLE_LEVELS == 4
+#if CONFIG_PGTABLE_LEVELS == 4
 static void xen_alloc_pud(struct mm_struct *mm, unsigned long pfn)
 {
        xen_alloc_ptpage(mm, pfn, PT_PUD);
@@ -2046,7 +2046,7 @@ static void __init xen_post_allocator_init(void)
        pv_mmu_ops.set_pte = xen_set_pte;
        pv_mmu_ops.set_pmd = xen_set_pmd;
        pv_mmu_ops.set_pud = xen_set_pud;
-#if PAGETABLE_LEVELS == 4
+#if CONFIG_PGTABLE_LEVELS == 4
        pv_mmu_ops.set_pgd = xen_set_pgd;
 #endif
 
@@ -2056,7 +2056,7 @@ static void __init xen_post_allocator_init(void)
        pv_mmu_ops.alloc_pmd = xen_alloc_pmd;
        pv_mmu_ops.release_pte = xen_release_pte;
        pv_mmu_ops.release_pmd = xen_release_pmd;
-#if PAGETABLE_LEVELS == 4
+#if CONFIG_PGTABLE_LEVELS == 4
        pv_mmu_ops.alloc_pud = xen_alloc_pud;
        pv_mmu_ops.release_pud = xen_release_pud;
 #endif
@@ -2122,14 +2122,14 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = {
        .make_pmd = PV_CALLEE_SAVE(xen_make_pmd),
        .pmd_val = PV_CALLEE_SAVE(xen_pmd_val),
 
-#if PAGETABLE_LEVELS == 4
+#if CONFIG_PGTABLE_LEVELS == 4
        .pud_val = PV_CALLEE_SAVE(xen_pud_val),
        .make_pud = PV_CALLEE_SAVE(xen_make_pud),
        .set_pgd = xen_set_pgd_hyper,
 
        .alloc_pud = xen_alloc_pmd_init,
        .release_pud = xen_release_pmd_init,
-#endif /* PAGETABLE_LEVELS == 4 */
+#endif /* CONFIG_PGTABLE_LEVELS == 4 */
 
        .activate_mm = xen_activate_mm,
        .dup_mmap = xen_dup_mmap,
index 08e8489c47f1ba058ca57dd6353d6bf9c1776ba7..86484384492e97d8d41d030bdb78fd0119a8b2cf 100644 (file)
@@ -90,14 +90,10 @@ static void cpu_bringup(void)
 
        set_cpu_online(cpu, true);
 
-       this_cpu_write(cpu_state, CPU_ONLINE);
-
-       wmb();
+       cpu_set_state_online(cpu);  /* Implies full memory barrier. */
 
        /* We can take interrupts now: we're officially "up". */
        local_irq_enable();
-
-       wmb();                  /* make sure everything is out */
 }
 
 /*
@@ -445,21 +441,19 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
 {
        int rc;
 
-       per_cpu(current_task, cpu) = idle;
-#ifdef CONFIG_X86_32
-       irq_ctx_init(cpu);
-#else
-       clear_tsk_thread_flag(idle, TIF_FORK);
-#endif
-       per_cpu(kernel_stack, cpu) =
-               (unsigned long)task_stack_page(idle) -
-               KERNEL_STACK_OFFSET + THREAD_SIZE;
+       common_cpu_up(cpu, idle);
 
        xen_setup_runstate_info(cpu);
        xen_setup_timer(cpu);
        xen_init_lock_cpu(cpu);
 
-       per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+       /*
+        * PV VCPUs are always successfully taken down (see 'while' loop
+        * in xen_cpu_die()), so -EBUSY is an error.
+        */
+       rc = cpu_check_up_prepare(cpu);
+       if (rc)
+               return rc;
 
        /* make sure interrupts start blocked */
        per_cpu(xen_vcpu, cpu)->evtchn_upcall_mask = 1;
@@ -468,10 +462,6 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
        if (rc)
                return rc;
 
-       if (num_online_cpus() == 1)
-               /* Just in case we booted with a single CPU. */
-               alternatives_enable_smp();
-
        rc = xen_smp_intr_init(cpu);
        if (rc)
                return rc;
@@ -479,10 +469,8 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
        rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
        BUG_ON(rc);
 
-       while(per_cpu(cpu_state, cpu) != CPU_ONLINE) {
+       while (cpu_report_state(cpu) != CPU_ONLINE)
                HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
-               barrier();
-       }
 
        return 0;
 }
@@ -511,11 +499,11 @@ static void xen_cpu_die(unsigned int cpu)
                schedule_timeout(HZ/10);
        }
 
-       cpu_die_common(cpu);
-
-       xen_smp_intr_free(cpu);
-       xen_uninit_lock_cpu(cpu);
-       xen_teardown_timer(cpu);
+       if (common_cpu_die(cpu) == 0) {
+               xen_smp_intr_free(cpu);
+               xen_uninit_lock_cpu(cpu);
+               xen_teardown_timer(cpu);
+       }
 }
 
 static void xen_play_dead(void) /* used only with HOTPLUG_CPU */
@@ -747,6 +735,16 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
 static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
        int rc;
+
+       /*
+        * This can happen if CPU was offlined earlier and
+        * offlining timed out in common_cpu_die().
+        */
+       if (cpu_report_state(cpu) == CPU_DEAD_FROZEN) {
+               xen_smp_intr_free(cpu);
+               xen_uninit_lock_cpu(cpu);
+       }
+
        /*
         * xen_smp_intr_init() needs to run before native_cpu_up()
         * so that IPI vectors are set up on the booting CPU before
@@ -768,12 +766,6 @@ static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
        return rc;
 }
 
-static void xen_hvm_cpu_die(unsigned int cpu)
-{
-       xen_cpu_die(cpu);
-       native_cpu_die(cpu);
-}
-
 void __init xen_hvm_smp_init(void)
 {
        if (!xen_have_vector_callback)
@@ -781,7 +773,7 @@ void __init xen_hvm_smp_init(void)
        smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
        smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
        smp_ops.cpu_up = xen_hvm_cpu_up;
-       smp_ops.cpu_die = xen_hvm_cpu_die;
+       smp_ops.cpu_die = xen_cpu_die;
        smp_ops.send_call_func_ipi = xen_smp_send_call_function_ipi;
        smp_ops.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi;
        smp_ops.smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu;
index c4df9dbd63b7c81f70c624c417d8362b85d3d34e..d9497698645a53b10ab4b62ddc98d12f4412a616 100644 (file)
@@ -1,5 +1,5 @@
 #include <linux/types.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 
 #include <xen/interface/xen.h>
 #include <xen/grant_table.h>
@@ -81,17 +81,14 @@ void xen_arch_post_suspend(int cancelled)
 
 static void xen_vcpu_notify_restore(void *data)
 {
-       unsigned long reason = (unsigned long)data;
-
        /* Boot processor notified via generic timekeeping_resume() */
-       if ( smp_processor_id() == 0)
+       if (smp_processor_id() == 0)
                return;
 
-       clockevents_notify(reason, NULL);
+       tick_resume_local();
 }
 
 void xen_arch_resume(void)
 {
-       on_each_cpu(xen_vcpu_notify_restore,
-                   (void *)CLOCK_EVT_NOTIFY_RESUME, 1);
+       on_each_cpu(xen_vcpu_notify_restore, NULL, 1);
 }
index 53adefda4275330a810b6d883b6ad8b58a72730c..985fc3ee0973c85f916c67cd9a40fc9c2c73d340 100644 (file)
@@ -68,11 +68,11 @@ ENTRY(xen_sysret64)
         * We're already on the usermode stack at this point, but
         * still with the kernel gs, so we can easily switch back
         */
-       movq %rsp, PER_CPU_VAR(old_rsp)
+       movq %rsp, PER_CPU_VAR(rsp_scratch)
        movq PER_CPU_VAR(kernel_stack), %rsp
 
        pushq $__USER_DS
-       pushq PER_CPU_VAR(old_rsp)
+       pushq PER_CPU_VAR(rsp_scratch)
        pushq %r11
        pushq $__USER_CS
        pushq %rcx
@@ -87,11 +87,11 @@ ENTRY(xen_sysret32)
         * We're already on the usermode stack at this point, but
         * still with the kernel gs, so we can easily switch back
         */
-       movq %rsp, PER_CPU_VAR(old_rsp)
+       movq %rsp, PER_CPU_VAR(rsp_scratch)
        movq PER_CPU_VAR(kernel_stack), %rsp
 
        pushq $__USER32_DS
-       pushq PER_CPU_VAR(old_rsp)
+       pushq PER_CPU_VAR(rsp_scratch)
        pushq %r11
        pushq $__USER32_CS
        pushq %rcx
index 5b3403388d7f0b0465d3f1d00bdd2abb36c9410d..b848cc3dc913d8de7dc5181fc140a9f83215e6cf 100644 (file)
@@ -174,7 +174,7 @@ static int __init pcibios_init(void)
        struct pci_controller *pci_ctrl;
        struct list_head resources;
        struct pci_bus *bus;
-       int next_busno = 0;
+       int next_busno = 0, ret;
 
        printk("PCI: Probing PCI hardware\n");
 
@@ -185,14 +185,25 @@ static int __init pcibios_init(void)
                pci_controller_apertures(pci_ctrl, &resources);
                bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno,
                                        pci_ctrl->ops, pci_ctrl, &resources);
+               if (!bus)
+                       continue;
+
                pci_ctrl->bus = bus;
                pci_ctrl->last_busno = bus->busn_res.end;
                if (next_busno <= pci_ctrl->last_busno)
                        next_busno = pci_ctrl->last_busno+1;
        }
        pci_bus_count = next_busno;
+       ret = platform_pcibios_fixup();
+       if (ret)
+               return ret;
 
-       return platform_pcibios_fixup();
+       for (pci_ctrl = pci_ctrl_head; pci_ctrl; pci_ctrl = pci_ctrl->next) {
+               if (pci_ctrl->bus)
+                       pci_bus_add_devices(pci_ctrl->bus);
+       }
+
+       return 0;
 }
 
 subsys_initcall(pcibios_init);
index 3d733ba16f28a2db8f6f4c91c61170a44ca7fd83..6b3790445cbed4c5d2ab7fb31cdc6bb6d3db25f8 100644 (file)
@@ -405,11 +405,6 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
        regs->areg[8] = (unsigned long) &frame->uc;
        regs->threadptr = tp;
 
-       /* Set access mode to USER_DS.  Nomenclature is outdated, but
-        * functionality is used in uaccess.h
-        */
-       set_fs(USER_DS);
-
 #if DEBUG_SIG
        printk("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08x\n",
                current->comm, current->pid, signal, frame, regs->pc);
index b8d2725324a6b88391db4c8a5daf7a9c1309dd86..da310a1054299720d1b809d4ac3fd27af02b1e19 100644 (file)
@@ -124,10 +124,10 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq,
 {
        struct iovec iov;
        struct iov_iter i;
+       int ret = import_single_range(rq_data_dir(rq), ubuf, len, &iov, &i);
 
-       iov.iov_base = ubuf;
-       iov.iov_len = len;
-       iov_iter_init(&i, rq_data_dir(rq), &iov, 1, len);
+       if (unlikely(ret < 0))
+               return ret;
 
        return blk_rq_map_user_iov(q, rq, map_data, &i, gfp_mask);
 }
index b7b8933ec24188b2807229af1aa844503b46dc89..33c428530193548e38e0ec4ce3608e08be8b1d8d 100644 (file)
@@ -1457,7 +1457,7 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
 
                do {
                        page = alloc_pages_node(set->numa_node,
-                               GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY,
+                               GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO,
                                this_order);
                        if (page)
                                break;
@@ -1479,8 +1479,6 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
                left -= to_do * rq_size;
                for (j = 0; j < to_do; j++) {
                        tags->rqs[i] = p;
-                       tags->rqs[i]->atomic_flags = 0;
-                       tags->rqs[i]->cmd_flags = 0;
                        if (set->ops->init_request) {
                                if (set->ops->init_request(set->driver_data,
                                                tags->rqs[i], hctx_idx, i,
index e1f71c3961934b9ed9adbf01247d196b05801750..55b6f15dac900af77a5ad7038cd98f3133d816a8 100644 (file)
@@ -335,16 +335,14 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
                struct iov_iter i;
                struct iovec *iov = NULL;
 
-               ret = rw_copy_check_uvector(-1, hdr->dxferp, hdr->iovec_count,
-                                           0, NULL, &iov);
-               if (ret < 0) {
-                       kfree(iov);
+               ret = import_iovec(rq_data_dir(rq),
+                                  hdr->dxferp, hdr->iovec_count,
+                                  0, &iov, &i);
+               if (ret < 0)
                        goto out_free_cdb;
-               }
 
                /* SG_IO howto says that the shorter of the two wins */
-               iov_iter_init(&i, rq_data_dir(rq), iov, hdr->iovec_count,
-                             min_t(unsigned, ret, hdr->dxfer_len));
+               iov_iter_truncate(&i, hdr->dxfer_len);
 
                ret = blk_rq_map_user_iov(q, rq, NULL, &i, GFP_KERNEL);
                kfree(iov);
index 36b0e61f9c0949d479ae4be7fc3454933956b28c..bbcc2b5a70d4aa53a9b014c871241e93aaab66e3 100644 (file)
@@ -95,13 +95,14 @@ static struct acpi_driver acpi_ac_driver = {
 };
 
 struct acpi_ac {
-       struct power_supply charger;
+       struct power_supply *charger;
+       struct power_supply_desc charger_desc;
        struct acpi_device * device;
        unsigned long long state;
        struct notifier_block battery_nb;
 };
 
-#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger)
+#define to_acpi_ac(x) power_supply_get_drvdata(x)
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
 static const struct file_operations acpi_ac_fops = {
@@ -275,7 +276,7 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event)
                                                  dev_name(&device->dev), event,
                                                  (u32) ac->state);
                acpi_notifier_call_chain(device, event, (u32) ac->state);
-               kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
+               kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE);
        }
 
        return;
@@ -321,6 +322,7 @@ static struct dmi_system_id ac_dmi_table[] = {
 
 static int acpi_ac_add(struct acpi_device *device)
 {
+       struct power_supply_config psy_cfg = {};
        int result = 0;
        struct acpi_ac *ac = NULL;
 
@@ -341,19 +343,24 @@ static int acpi_ac_add(struct acpi_device *device)
        if (result)
                goto end;
 
-       ac->charger.name = acpi_device_bid(device);
+       psy_cfg.drv_data = ac;
+
+       ac->charger_desc.name = acpi_device_bid(device);
 #ifdef CONFIG_ACPI_PROCFS_POWER
        result = acpi_ac_add_fs(ac);
        if (result)
                goto end;
 #endif
-       ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
-       ac->charger.properties = ac_props;
-       ac->charger.num_properties = ARRAY_SIZE(ac_props);
-       ac->charger.get_property = get_ac_property;
-       result = power_supply_register(&ac->device->dev, &ac->charger);
-       if (result)
+       ac->charger_desc.type = POWER_SUPPLY_TYPE_MAINS;
+       ac->charger_desc.properties = ac_props;
+       ac->charger_desc.num_properties = ARRAY_SIZE(ac_props);
+       ac->charger_desc.get_property = get_ac_property;
+       ac->charger = power_supply_register(&ac->device->dev,
+                                           &ac->charger_desc, &psy_cfg);
+       if (IS_ERR(ac->charger)) {
+               result = PTR_ERR(ac->charger);
                goto end;
+       }
 
        printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
               acpi_device_name(device), acpi_device_bid(device),
@@ -390,7 +397,7 @@ static int acpi_ac_resume(struct device *dev)
        if (acpi_ac_get_state(ac))
                return 0;
        if (old_state != ac->state)
-               kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
+               kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE);
        return 0;
 }
 #else
@@ -407,8 +414,7 @@ static int acpi_ac_remove(struct acpi_device *device)
 
        ac = acpi_driver_data(device);
 
-       if (ac->charger.dev)
-               power_supply_unregister(&ac->charger);
+       power_supply_unregister(ac->charger);
        unregister_acpi_notifier(&ac->battery_nb);
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
index c7b105c0e1d377991f1e324fae161535e01efe27..6bc9cbc01ad6a3f20c27740ebbf1a919e7c74d0d 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 #include <linux/cpu.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <asm/mwait.h>
@@ -41,8 +41,6 @@ static unsigned long power_saving_mwait_eax;
 
 static unsigned char tsc_detected_unstable;
 static unsigned char tsc_marked_unstable;
-static unsigned char lapic_detected_unstable;
-static unsigned char lapic_marked_unstable;
 
 static void power_saving_mwait_init(void)
 {
@@ -82,13 +80,10 @@ static void power_saving_mwait_init(void)
                 */
                if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
                        tsc_detected_unstable = 1;
-               if (!boot_cpu_has(X86_FEATURE_ARAT))
-                       lapic_detected_unstable = 1;
                break;
        default:
-               /* TSC & LAPIC could halt in idle */
+               /* TSC could halt in idle */
                tsc_detected_unstable = 1;
-               lapic_detected_unstable = 1;
        }
 #endif
 }
@@ -155,7 +150,6 @@ static int power_saving_thread(void *data)
        sched_setscheduler(current, SCHED_RR, &param);
 
        while (!kthread_should_stop()) {
-               int cpu;
                unsigned long expire_time;
 
                try_to_freeze();
@@ -177,28 +171,15 @@ static int power_saving_thread(void *data)
                                mark_tsc_unstable("TSC halts in idle");
                                tsc_marked_unstable = 1;
                        }
-                       if (lapic_detected_unstable && !lapic_marked_unstable) {
-                               int i;
-                               /* LAPIC could halt in idle, so notify users */
-                               for_each_online_cpu(i)
-                                       clockevents_notify(
-                                               CLOCK_EVT_NOTIFY_BROADCAST_ON,
-                                               &i);
-                               lapic_marked_unstable = 1;
-                       }
                        local_irq_disable();
-                       cpu = smp_processor_id();
-                       if (lapic_marked_unstable)
-                               clockevents_notify(
-                                       CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+                       tick_broadcast_enable();
+                       tick_broadcast_enter();
                        stop_critical_timings();
 
                        mwait_idle_with_hints(power_saving_mwait_eax, 1);
 
                        start_critical_timings();
-                       if (lapic_marked_unstable)
-                               clockevents_notify(
-                                       CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+                       tick_broadcast_exit();
                        local_irq_enable();
 
                        if (time_before(expire_time, jiffies)) {
index d98ba43558190b9f6957212f93a33a9ad29476da..672263a3832c819165f460a5570751fe2602bf30 100644 (file)
@@ -117,7 +117,8 @@ enum {
 struct acpi_battery {
        struct mutex lock;
        struct mutex sysfs_lock;
-       struct power_supply bat;
+       struct power_supply *bat;
+       struct power_supply_desc bat_desc;
        struct acpi_device *device;
        struct notifier_block pm_nb;
        unsigned long update_time;
@@ -149,7 +150,7 @@ struct acpi_battery {
        unsigned long flags;
 };
 
-#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
+#define to_acpi_battery(x) power_supply_get_drvdata(x)
 
 static inline int acpi_battery_present(struct acpi_battery *battery)
 {
@@ -608,40 +609,45 @@ static struct device_attribute alarm_attr = {
 
 static int sysfs_add_battery(struct acpi_battery *battery)
 {
-       int result;
+       struct power_supply_config psy_cfg = { .drv_data = battery, };
 
        if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
-               battery->bat.properties = charge_battery_props;
-               battery->bat.num_properties =
+               battery->bat_desc.properties = charge_battery_props;
+               battery->bat_desc.num_properties =
                        ARRAY_SIZE(charge_battery_props);
        } else {
-               battery->bat.properties = energy_battery_props;
-               battery->bat.num_properties =
+               battery->bat_desc.properties = energy_battery_props;
+               battery->bat_desc.num_properties =
                        ARRAY_SIZE(energy_battery_props);
        }
 
-       battery->bat.name = acpi_device_bid(battery->device);
-       battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
-       battery->bat.get_property = acpi_battery_get_property;
+       battery->bat_desc.name = acpi_device_bid(battery->device);
+       battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+       battery->bat_desc.get_property = acpi_battery_get_property;
 
-       result = power_supply_register_no_ws(&battery->device->dev, &battery->bat);
+       battery->bat = power_supply_register_no_ws(&battery->device->dev,
+                               &battery->bat_desc, &psy_cfg);
 
-       if (result)
+       if (IS_ERR(battery->bat)) {
+               int result = PTR_ERR(battery->bat);
+
+               battery->bat = NULL;
                return result;
-       return device_create_file(battery->bat.dev, &alarm_attr);
+       }
+       return device_create_file(&battery->bat->dev, &alarm_attr);
 }
 
 static void sysfs_remove_battery(struct acpi_battery *battery)
 {
        mutex_lock(&battery->sysfs_lock);
-       if (!battery->bat.dev) {
+       if (!battery->bat) {
                mutex_unlock(&battery->sysfs_lock);
                return;
        }
 
-       device_remove_file(battery->bat.dev, &alarm_attr);
-       power_supply_unregister(&battery->bat);
-       battery->bat.dev = NULL;
+       device_remove_file(&battery->bat->dev, &alarm_attr);
+       power_supply_unregister(battery->bat);
+       battery->bat = NULL;
        mutex_unlock(&battery->sysfs_lock);
 }
 
@@ -738,7 +744,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
                        return result;
                acpi_battery_init_alarm(battery);
        }
-       if (!battery->bat.dev) {
+       if (!battery->bat) {
                result = sysfs_add_battery(battery);
                if (result)
                        return result;
@@ -764,7 +770,7 @@ static void acpi_battery_refresh(struct acpi_battery *battery)
 {
        int power_unit;
 
-       if (!battery->bat.dev)
+       if (!battery->bat)
                return;
 
        power_unit = battery->power_unit;
@@ -1062,11 +1068,11 @@ static void acpi_battery_remove_fs(struct acpi_device *device)
 static void acpi_battery_notify(struct acpi_device *device, u32 event)
 {
        struct acpi_battery *battery = acpi_driver_data(device);
-       struct device *old;
+       struct power_supply *old;
 
        if (!battery)
                return;
-       old = battery->bat.dev;
+       old = battery->bat;
        /*
        * On Acer Aspire V5-573G notifications are sometimes triggered too
        * early. For example, when AC is unplugged and notification is
@@ -1083,8 +1089,8 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event)
                                        acpi_battery_present(battery));
        acpi_notifier_call_chain(device, event, acpi_battery_present(battery));
        /* acpi_battery_update could remove power_supply object */
-       if (old && battery->bat.dev)
-               power_supply_changed(&battery->bat);
+       if (old && battery->bat)
+               power_supply_changed(battery->bat);
 }
 
 static int battery_notify(struct notifier_block *nb,
@@ -1100,7 +1106,7 @@ static int battery_notify(struct notifier_block *nb,
                if (!acpi_battery_present(battery))
                        return 0;
 
-               if (!battery->bat.dev) {
+               if (!battery->bat) {
                        result = acpi_battery_get_info(battery);
                        if (result)
                                return result;
index 68a5f712cd198e5cd61b866d2068b9d52a1274f4..1b5569c092c6e205a784257f88d6f1ad06c5c3be 100644 (file)
@@ -423,8 +423,7 @@ out:
 }
 EXPORT_SYMBOL(acpi_pci_osc_control_set);
 
-static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm,
-                                int *clear_aspm)
+static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm)
 {
        u32 support, control, requested;
        acpi_status status;
@@ -495,10 +494,12 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm,
                decode_osc_control(root, "OS now controls", control);
                if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
                        /*
-                        * We have ASPM control, but the FADT indicates
-                        * that it's unsupported. Clear it.
+                        * We have ASPM control, but the FADT indicates that
+                        * it's unsupported. Leave existing configuration
+                        * intact and prevent the OS from touching it.
                         */
-                       *clear_aspm = 1;
+                       dev_info(&device->dev, "FADT indicates ASPM is unsupported, using BIOS configuration\n");
+                       *no_aspm = 1;
                }
        } else {
                decode_osc_control(root, "OS requested", requested);
@@ -525,7 +526,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
        int result;
        struct acpi_pci_root *root;
        acpi_handle handle = device->handle;
-       int no_aspm = 0, clear_aspm = 0;
+       int no_aspm = 0;
        bool hotadd = system_state != SYSTEM_BOOTING;
 
        root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
@@ -584,7 +585,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
 
        root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle);
 
-       negotiate_os_control(root, &no_aspm, &clear_aspm);
+       negotiate_os_control(root, &no_aspm);
 
        /*
         * TBD: Need PCI interface for enumeration/configuration of roots.
@@ -607,10 +608,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
                goto remove_dmar;
        }
 
-       if (clear_aspm) {
-               dev_info(&device->dev, "Disabling ASPM (FADT indicates it is unsupported)\n");
-               pcie_clear_aspm(root->bus);
-       }
        if (no_aspm)
                pcie_no_aspm();
 
index c6bb9f1257c92844fa076c0585cf73125d278dec..39e0c8e36244f75aac3de4f09a0a89817e035b91 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/acpi.h>
 #include <linux/dmi.h>
 #include <linux/sched.h>       /* need_resched() */
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <linux/cpuidle.h>
 #include <linux/syscore_ops.h>
 #include <acpi/processor.h>
@@ -157,12 +157,11 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr,
 static void __lapic_timer_propagate_broadcast(void *arg)
 {
        struct acpi_processor *pr = (struct acpi_processor *) arg;
-       unsigned long reason;
 
-       reason = pr->power.timer_broadcast_on_state < INT_MAX ?
-               CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF;
-
-       clockevents_notify(reason, &pr->id);
+       if (pr->power.timer_broadcast_on_state < INT_MAX)
+               tick_broadcast_enable();
+       else
+               tick_broadcast_disable();
 }
 
 static void lapic_timer_propagate_broadcast(struct acpi_processor *pr)
@@ -179,11 +178,10 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
        int state = cx - pr->power.states;
 
        if (state >= pr->power.timer_broadcast_on_state) {
-               unsigned long reason;
-
-               reason = broadcast ?  CLOCK_EVT_NOTIFY_BROADCAST_ENTER :
-                       CLOCK_EVT_NOTIFY_BROADCAST_EXIT;
-               clockevents_notify(reason, &pr->id);
+               if (broadcast)
+                       tick_broadcast_enter();
+               else
+                       tick_broadcast_exit();
        }
 }
 
@@ -922,7 +920,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
                return -EINVAL;
 
        drv->safe_state_index = -1;
-       for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
+       for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) {
                drv->states[i].name[0] = '\0';
                drv->states[i].desc[0] = '\0';
        }
index a7a3edd28beb8d5f881ef891075e0f650e0482de..cd827625cf079207f36a2e2f2b86e00ae649faa4 100644 (file)
@@ -74,7 +74,8 @@ static const struct acpi_device_id sbs_device_ids[] = {
 MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
 
 struct acpi_battery {
-       struct power_supply bat;
+       struct power_supply *bat;
+       struct power_supply_desc bat_desc;
        struct acpi_sbs *sbs;
        unsigned long update_time;
        char name[8];
@@ -101,10 +102,10 @@ struct acpi_battery {
        u8 have_sysfs_alarm:1;
 };
 
-#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
+#define to_acpi_battery(x) power_supply_get_drvdata(x)
 
 struct acpi_sbs {
-       struct power_supply charger;
+       struct power_supply *charger;
        struct acpi_device *device;
        struct acpi_smb_hc *hc;
        struct mutex lock;
@@ -115,7 +116,7 @@ struct acpi_sbs {
        u8 charger_exists:1;
 };
 
-#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
+#define to_acpi_sbs(x) power_supply_get_drvdata(x)
 
 static int acpi_sbs_remove(struct acpi_device *device);
 static int acpi_battery_get_state(struct acpi_battery *battery);
@@ -303,6 +304,13 @@ static enum power_supply_property sbs_energy_battery_props[] = {
        POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
+static const struct power_supply_desc acpi_sbs_charger_desc = {
+       .name           = "sbs-charger",
+       .type           = POWER_SUPPLY_TYPE_MAINS,
+       .properties     = sbs_ac_props,
+       .num_properties = ARRAY_SIZE(sbs_ac_props),
+       .get_property   = sbs_get_ac_property,
+};
 
 /* --------------------------------------------------------------------------
                             Smart Battery System Management
@@ -519,6 +527,7 @@ static int acpi_battery_read(struct acpi_battery *battery)
 static int acpi_battery_add(struct acpi_sbs *sbs, int id)
 {
        struct acpi_battery *battery = &sbs->battery[id];
+       struct power_supply_config psy_cfg = { .drv_data = battery, };
        int result;
 
        battery->id = id;
@@ -528,23 +537,27 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
                return result;
 
        sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
-       battery->bat.name = battery->name;
-       battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
+       battery->bat_desc.name = battery->name;
+       battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
        if (!acpi_battery_mode(battery)) {
-               battery->bat.properties = sbs_charge_battery_props;
-               battery->bat.num_properties =
+               battery->bat_desc.properties = sbs_charge_battery_props;
+               battery->bat_desc.num_properties =
                    ARRAY_SIZE(sbs_charge_battery_props);
        } else {
-               battery->bat.properties = sbs_energy_battery_props;
-               battery->bat.num_properties =
+               battery->bat_desc.properties = sbs_energy_battery_props;
+               battery->bat_desc.num_properties =
                    ARRAY_SIZE(sbs_energy_battery_props);
        }
-       battery->bat.get_property = acpi_sbs_battery_get_property;
-       result = power_supply_register(&sbs->device->dev, &battery->bat);
-       if (result)
+       battery->bat_desc.get_property = acpi_sbs_battery_get_property;
+       battery->bat = power_supply_register(&sbs->device->dev,
+                                       &battery->bat_desc, &psy_cfg);
+       if (IS_ERR(battery->bat)) {
+               result = PTR_ERR(battery->bat);
+               battery->bat = NULL;
                goto end;
+       }
 
-       result = device_create_file(battery->bat.dev, &alarm_attr);
+       result = device_create_file(&battery->bat->dev, &alarm_attr);
        if (result)
                goto end;
        battery->have_sysfs_alarm = 1;
@@ -559,28 +572,29 @@ static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
 {
        struct acpi_battery *battery = &sbs->battery[id];
 
-       if (battery->bat.dev) {
+       if (battery->bat) {
                if (battery->have_sysfs_alarm)
-                       device_remove_file(battery->bat.dev, &alarm_attr);
-               power_supply_unregister(&battery->bat);
+                       device_remove_file(&battery->bat->dev, &alarm_attr);
+               power_supply_unregister(battery->bat);
        }
 }
 
 static int acpi_charger_add(struct acpi_sbs *sbs)
 {
        int result;
+       struct power_supply_config psy_cfg = { .drv_data = sbs, };
 
        result = acpi_ac_get_present(sbs);
        if (result)
                goto end;
 
        sbs->charger_exists = 1;
-       sbs->charger.name = "sbs-charger";
-       sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
-       sbs->charger.properties = sbs_ac_props;
-       sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props);
-       sbs->charger.get_property = sbs_get_ac_property;
-       power_supply_register(&sbs->device->dev, &sbs->charger);
+       sbs->charger = power_supply_register(&sbs->device->dev,
+                                       &acpi_sbs_charger_desc, &psy_cfg);
+       if (IS_ERR(sbs->charger)) {
+               result = PTR_ERR(sbs->charger);
+               sbs->charger = NULL;
+       }
        printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
               ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
               ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
@@ -590,8 +604,8 @@ static int acpi_charger_add(struct acpi_sbs *sbs)
 
 static void acpi_charger_remove(struct acpi_sbs *sbs)
 {
-       if (sbs->charger.dev)
-               power_supply_unregister(&sbs->charger);
+       if (sbs->charger)
+               power_supply_unregister(sbs->charger);
 }
 
 static void acpi_sbs_callback(void *context)
@@ -605,7 +619,7 @@ static void acpi_sbs_callback(void *context)
        if (sbs->charger_exists) {
                acpi_ac_get_present(sbs);
                if (sbs->charger_present != saved_charger_state)
-                       kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
+                       kobject_uevent(&sbs->charger->dev.kobj, KOBJ_CHANGE);
        }
 
        if (sbs->manager_present) {
@@ -617,7 +631,7 @@ static void acpi_sbs_callback(void *context)
                        acpi_battery_read(bat);
                        if (saved_battery_state == bat->present)
                                continue;
-                       kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE);
+                       kobject_uevent(&bat->bat->dev.kobj, KOBJ_CHANGE);
                }
        }
 }
index ae41107afc1f70423012623321c79aa276edd96c..b67e995179a947bcdda7e5bf6f5d95275841ad49 100644 (file)
@@ -111,7 +111,8 @@ obj-$(CONFIG_ATA_GENERIC)   += ata_generic.o
 # Should be last libata driver
 obj-$(CONFIG_PATA_LEGACY)      += pata_legacy.o
 
-libata-y       := libata-core.o libata-scsi.o libata-eh.o libata-transport.o
+libata-y       := libata-core.o libata-scsi.o libata-eh.o \
+       libata-transport.o libata-trace.o
 libata-$(CONFIG_ATA_SFF)       += libata-sff.o
 libata-$(CONFIG_SATA_PMP)      += libata-pmp.o
 libata-$(CONFIG_ATA_ACPI)      += libata-acpi.o
index c962886d7e7149fdde2c7ecda9ecf68ab04379ce..12489ce863c4bf06c06a38aa182124785346e365 100644 (file)
@@ -181,10 +181,10 @@ static int acard_ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
        int rc;
 
        if (using_dac &&
-           !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-               rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+           !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
+               rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
                if (rc) {
-                       rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+                       rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
                        if (rc) {
                                dev_err(&pdev->dev,
                                           "64-bit DMA enable failed\n");
@@ -192,12 +192,12 @@ static int acard_ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
                        }
                }
        } else {
-               rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+               rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
                if (rc) {
                        dev_err(&pdev->dev, "32-bit DMA enable failed\n");
                        return rc;
                }
-               rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+               rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
                if (rc) {
                        dev_err(&pdev->dev,
                                "32-bit consistent DMA enable failed\n");
index 33bb06e006c9d6cbd9689b92a08df1481b12c568..c7a92a743ed035e9af81ac779180fc65456a8390 100644 (file)
@@ -738,10 +738,10 @@ static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
                return 0;
 
        if (using_dac &&
-           !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-               rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+           !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
+               rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
                if (rc) {
-                       rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+                       rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
                        if (rc) {
                                dev_err(&pdev->dev,
                                        "64-bit DMA enable failed\n");
@@ -749,12 +749,12 @@ static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
                        }
                }
        } else {
-               rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+               rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
                if (rc) {
                        dev_err(&pdev->dev, "32-bit DMA enable failed\n");
                        return rc;
                }
-               rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+               rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
                if (rc) {
                        dev_err(&pdev->dev,
                                "32-bit consistent DMA enable failed\n");
index bc971af262e75f89cb64af2b408fb6a7ab0fdb03..ea0ff005b86ce702e4ccd0224c5b8f14c0fcfc89 100644 (file)
@@ -68,8 +68,6 @@ static int st_ahci_deassert_resets(struct device *dev)
                }
        }
 
-       st_ahci_configure_oob(drv_data->hpriv->mmio);
-
        if (drv_data->sw_rst) {
                err = reset_control_deassert(drv_data->sw_rst);
                if (err) {
@@ -172,6 +170,8 @@ static int st_ahci_probe(struct platform_device *pdev)
        if (err)
                return err;
 
+       st_ahci_configure_oob(drv_data->hpriv->mmio);
+
        err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info,
                                      &ahci_platform_sht);
        if (err) {
@@ -222,6 +222,8 @@ static int st_ahci_resume(struct device *dev)
                return err;
        }
 
+       st_ahci_configure_oob(drv_data->hpriv->mmio);
+
        return ahci_platform_resume_host(dev);
 }
 #endif
index 2e8bb603e44750b749c933a4dd71db1648e5f732..2b78510d94dd7732f7231d0348d7a1f0818a427a 100644 (file)
@@ -22,6 +22,7 @@
  * NOTE: PM support is not currently available.
  *
  */
+#include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/ahci_platform.h>
@@ -718,6 +719,14 @@ disable_resources:
        return rc;
 }
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id xgene_ahci_acpi_match[] = {
+       { "APMC0D0D", },
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, xgene_ahci_acpi_match);
+#endif
+
 static const struct of_device_id xgene_ahci_of_match[] = {
        {.compatible = "apm,xgene-ahci"},
        {},
@@ -730,6 +739,7 @@ static struct platform_driver xgene_ahci_driver = {
        .driver = {
                .name = DRV_NAME,
                .of_match_table = xgene_ahci_of_match,
+               .acpi_match_table = ACPI_PTR(xgene_ahci_acpi_match),
        },
 };
 
index 23dac3babfe3afc710db73a2ad4f8fe05174b7d7..f6cb1f1b30b7466278d47dae09bc959db24dfef1 100644 (file)
@@ -70,6 +70,9 @@
 #include <linux/pm_runtime.h>
 #include <linux/platform_device.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/libata.h>
+
 #include "libata.h"
 #include "libata-transport.h"
 
@@ -691,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(struct ata_taskfile *tf, struct ata_device *dev)
+u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev)
 {
        u64 block = 0;
 
-       if (tf->flags & ATA_TFLAG_LBA) {
+       if (!dev || tf->flags & ATA_TFLAG_LBA) {
                if (tf->flags & ATA_TFLAG_LBA48) {
                        block |= (u64)tf->hob_lbah << 40;
                        block |= (u64)tf->hob_lbam << 32;
@@ -2144,6 +2147,24 @@ 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
@@ -2366,7 +2387,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;
        }
 
@@ -4897,6 +4918,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
                 */
                if (unlikely(ata_tag_internal(qc->tag))) {
                        fill_result_tf(qc);
+                       trace_ata_qc_complete_internal(qc);
                        __ata_qc_complete(qc);
                        return;
                }
@@ -4907,6 +4929,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
                 */
                if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
                        fill_result_tf(qc);
+                       trace_ata_qc_complete_failed(qc);
                        ata_qc_schedule_eh(qc);
                        return;
                }
@@ -4917,6 +4940,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
                if (qc->flags & ATA_QCFLAG_RESULT_TF)
                        fill_result_tf(qc);
 
+               trace_ata_qc_complete_done(qc);
                /* Some commands need post-processing after successful
                 * completion.
                 */
@@ -5064,7 +5088,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
        }
 
        ap->ops->qc_prep(qc);
-
+       trace_ata_qc_issue(qc);
        qc->err_mask |= ap->ops->qc_issue(qc);
        if (unlikely(qc->err_mask))
                goto err;
index d2029a462e2c31b8510c1b088098ca9bd8536d10..07f41be38fbe556ffff9bd5efcacf8ed4538034e 100644 (file)
@@ -46,6 +46,7 @@
 
 #include <linux/libata.h>
 
+#include <trace/events/libata.h>
 #include "libata.h"
 
 enum {
@@ -1510,13 +1511,18 @@ unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
        DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page);
 
        ata_tf_init(dev, &tf);
-       tf.command = ATA_CMD_READ_LOG_EXT;
+       if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id)) {
+               tf.command = ATA_CMD_READ_LOG_DMA_EXT;
+               tf.protocol = ATA_PROT_DMA;
+       } else {
+               tf.command = ATA_CMD_READ_LOG_EXT;
+               tf.protocol = ATA_PROT_PIO;
+       }
        tf.lbal = log;
        tf.lbam = page;
        tf.nsect = sectors;
        tf.hob_nsect = sectors >> 8;
        tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
-       tf.protocol = ATA_PROT_PIO;
 
        err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
                                     buf, sectors * ATA_SECT_SIZE, 0);
@@ -1575,6 +1581,8 @@ 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;
 }
@@ -1610,6 +1618,70 @@ 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
@@ -1772,6 +1844,19 @@ 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;
 }
 
@@ -1801,6 +1886,27 @@ 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
@@ -2186,6 +2292,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
                all_err_mask |= qc->err_mask;
                if (qc->flags & ATA_QCFLAG_IO)
                        eflags |= ATA_EFLAG_IS_IO;
+               trace_ata_eh_link_autopsy_qc(qc);
        }
 
        /* enforce default EH actions */
@@ -2220,7 +2327,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
                        eflags |= ATA_EFLAG_DUBIOUS_XFER;
                ehc->i.action |= ata_eh_speed_down(dev, eflags, all_err_mask);
        }
-
+       trace_ata_eh_link_autopsy(dev, ehc->i.action, all_err_mask);
        DPRINTK("EXIT\n");
 }
 
@@ -2289,27 +2396,27 @@ const char *ata_get_cmd_descript(u8 command)
                const char *text;
        } cmd_descr[] = {
                { ATA_CMD_DEV_RESET,            "DEVICE RESET" },
-               { ATA_CMD_CHK_POWER,            "CHECK POWER MODE" },
-               { ATA_CMD_STANDBY,              "STANDBY" },
-               { ATA_CMD_IDLE,                 "IDLE" },
-               { ATA_CMD_EDD,                  "EXECUTE DEVICE DIAGNOSTIC" },
-               { ATA_CMD_DOWNLOAD_MICRO,       "DOWNLOAD MICROCODE" },
+               { ATA_CMD_CHK_POWER,            "CHECK POWER MODE" },
+               { ATA_CMD_STANDBY,              "STANDBY" },
+               { ATA_CMD_IDLE,                 "IDLE" },
+               { ATA_CMD_EDD,                  "EXECUTE DEVICE DIAGNOSTIC" },
+               { ATA_CMD_DOWNLOAD_MICRO,       "DOWNLOAD MICROCODE" },
                { ATA_CMD_DOWNLOAD_MICRO_DMA,   "DOWNLOAD MICROCODE DMA" },
                { ATA_CMD_NOP,                  "NOP" },
-               { ATA_CMD_FLUSH,                "FLUSH CACHE" },
-               { ATA_CMD_FLUSH_EXT,            "FLUSH CACHE EXT" },
-               { ATA_CMD_ID_ATA,               "IDENTIFY DEVICE" },
-               { ATA_CMD_ID_ATAPI,             "IDENTIFY PACKET DEVICE" },
-               { ATA_CMD_SERVICE,              "SERVICE" },
-               { ATA_CMD_READ,                 "READ DMA" },
-               { ATA_CMD_READ_EXT,             "READ DMA EXT" },
-               { ATA_CMD_READ_QUEUED,          "READ DMA QUEUED" },
-               { ATA_CMD_READ_STREAM_EXT,      "READ STREAM EXT" },
+               { ATA_CMD_FLUSH,                "FLUSH CACHE" },
+               { ATA_CMD_FLUSH_EXT,            "FLUSH CACHE EXT" },
+               { ATA_CMD_ID_ATA,               "IDENTIFY DEVICE" },
+               { ATA_CMD_ID_ATAPI,             "IDENTIFY PACKET DEVICE" },
+               { ATA_CMD_SERVICE,              "SERVICE" },
+               { ATA_CMD_READ,                 "READ DMA" },
+               { ATA_CMD_READ_EXT,             "READ DMA EXT" },
+               { ATA_CMD_READ_QUEUED,          "READ DMA QUEUED" },
+               { ATA_CMD_READ_STREAM_EXT,      "READ STREAM EXT" },
                { ATA_CMD_READ_STREAM_DMA_EXT,  "READ STREAM DMA EXT" },
-               { ATA_CMD_WRITE,                "WRITE DMA" },
-               { ATA_CMD_WRITE_EXT,            "WRITE DMA EXT" },
-               { ATA_CMD_WRITE_QUEUED,         "WRITE DMA QUEUED EXT" },
-               { ATA_CMD_WRITE_STREAM_EXT,     "WRITE STREAM EXT" },
+               { ATA_CMD_WRITE,                "WRITE DMA" },
+               { ATA_CMD_WRITE_EXT,            "WRITE DMA EXT" },
+               { ATA_CMD_WRITE_QUEUED,         "WRITE DMA QUEUED EXT" },
+               { ATA_CMD_WRITE_STREAM_EXT,     "WRITE STREAM EXT" },
                { ATA_CMD_WRITE_STREAM_DMA_EXT, "WRITE STREAM DMA EXT" },
                { ATA_CMD_WRITE_FUA_EXT,        "WRITE DMA FUA EXT" },
                { ATA_CMD_WRITE_QUEUED_FUA_EXT, "WRITE DMA QUEUED FUA EXT" },
@@ -2325,7 +2432,7 @@ const char *ata_get_cmd_descript(u8 command)
                { ATA_CMD_READ_MULTI_EXT,       "READ MULTIPLE EXT" },
                { ATA_CMD_WRITE_MULTI,          "WRITE MULTIPLE" },
                { ATA_CMD_WRITE_MULTI_EXT,      "WRITE MULTIPLE EXT" },
-               { ATA_CMD_WRITE_MULTI_FUA_EXT,  "WRITE MULTIPLE FUA EXT" },
+               { ATA_CMD_WRITE_MULTI_FUA_EXT,  "WRITE MULTIPLE FUA EXT" },
                { ATA_CMD_SET_FEATURES,         "SET FEATURES" },
                { ATA_CMD_SET_MULTI,            "SET MULTIPLE MODE" },
                { ATA_CMD_VERIFY,               "READ VERIFY SECTOR(S)" },
@@ -2342,12 +2449,12 @@ const char *ata_get_cmd_descript(u8 command)
                { ATA_CMD_READ_LOG_EXT,         "READ LOG EXT" },
                { ATA_CMD_WRITE_LOG_EXT,        "WRITE LOG EXT" },
                { ATA_CMD_READ_LOG_DMA_EXT,     "READ LOG DMA EXT" },
-               { ATA_CMD_WRITE_LOG_DMA_EXT,    "WRITE LOG DMA EXT" },
+               { ATA_CMD_WRITE_LOG_DMA_EXT,    "WRITE LOG DMA EXT" },
                { ATA_CMD_TRUSTED_NONDATA,      "TRUSTED NON-DATA" },
                { ATA_CMD_TRUSTED_RCV,          "TRUSTED RECEIVE" },
-               { ATA_CMD_TRUSTED_RCV_DMA,      "TRUSTED RECEIVE DMA" },
+               { ATA_CMD_TRUSTED_RCV_DMA,      "TRUSTED RECEIVE DMA" },
                { ATA_CMD_TRUSTED_SND,          "TRUSTED SEND" },
-               { ATA_CMD_TRUSTED_SND_DMA,      "TRUSTED SEND DMA" },
+               { ATA_CMD_TRUSTED_SND_DMA,      "TRUSTED SEND DMA" },
                { ATA_CMD_PMP_READ,             "READ BUFFER" },
                { ATA_CMD_PMP_READ_DMA,         "READ BUFFER DMA" },
                { ATA_CMD_PMP_WRITE,            "WRITE BUFFER" },
@@ -2364,12 +2471,12 @@ const char *ata_get_cmd_descript(u8 command)
                { ATA_CMD_MEDIA_LOCK,           "DOOR LOCK" },
                { ATA_CMD_MEDIA_UNLOCK,         "DOOR UNLOCK" },
                { ATA_CMD_DSM,                  "DATA SET MANAGEMENT" },
-               { ATA_CMD_CHK_MED_CRD_TYP,      "CHECK MEDIA CARD TYPE" },
-               { ATA_CMD_CFA_REQ_EXT_ERR,      "CFA REQUEST EXTENDED ERROR" },
+               { ATA_CMD_CHK_MED_CRD_TYP,      "CHECK MEDIA CARD TYPE" },
+               { ATA_CMD_CFA_REQ_EXT_ERR,      "CFA REQUEST EXTENDED ERROR" },
                { ATA_CMD_CFA_WRITE_NE,         "CFA WRITE SECTORS WITHOUT ERASE" },
                { ATA_CMD_CFA_TRANS_SECT,       "CFA TRANSLATE SECTOR" },
                { ATA_CMD_CFA_ERASE,            "CFA ERASE SECTORS" },
-               { ATA_CMD_CFA_WRITE_MULT_NE,    "CFA WRITE MULTIPLE WITHOUT ERASE" },
+               { ATA_CMD_CFA_WRITE_MULT_NE,    "CFA WRITE MULTIPLE WITHOUT ERASE" },
                { ATA_CMD_REQ_SENSE_DATA,       "REQUEST SENSE DATA EXT" },
                { ATA_CMD_SANITIZE_DEVICE,      "SANITIZE DEVICE" },
                { ATA_CMD_READ_LONG,            "READ LONG (with retries)" },
@@ -2543,14 +2650,15 @@ 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_ERR)) {
+                                   ATA_SENSE | 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}\n",
+                               ata_dev_err(qc->dev, "status: { %s%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 b061ba2c31d8f51408a15f2e019a3c328e882815..3131adcc1f87e001f7f8bfe317e92527665e4dd4 100644 (file)
@@ -270,13 +270,28 @@ DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR,
            ata_scsi_park_show, ata_scsi_park_store);
 EXPORT_SYMBOL_GPL(dev_attr_unload_heads);
 
-static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+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)
@@ -799,26 +814,27 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf)
        if (stat & ATA_BUSY) {
                printk("Busy }\n");     /* Data is not valid in this case */
        } else {
-               if (stat & 0x40)        printk("DriveReady ");
-               if (stat & 0x20)        printk("DeviceFault ");
-               if (stat & 0x10)        printk("SeekComplete ");
-               if (stat & 0x08)        printk("DataRequest ");
-               if (stat & 0x04)        printk("CorrectedError ");
-               if (stat & 0x02)        printk("Index ");
-               if (stat & 0x01)        printk("Error ");
+               if (stat & ATA_DRDY)    printk("DriveReady ");
+               if (stat & ATA_DF)      printk("DeviceFault ");
+               if (stat & ATA_DSC)     printk("SeekComplete ");
+               if (stat & ATA_DRQ)     printk("DataRequest ");
+               if (stat & ATA_CORR)    printk("CorrectedError ");
+               if (stat & ATA_SENSE)   printk("Sense ");
+               if (stat & ATA_ERR)     printk("Error ");
                printk("}\n");
 
                if (err) {
                        printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err);
-                       if (err & 0x04)         printk("DriveStatusError ");
-                       if (err & 0x80) {
-                               if (err & 0x04) printk("BadCRC ");
+                       if (err & ATA_ABORTED)  printk("DriveStatusError ");
+                       if (err & ATA_ICRC) {
+                               if (err & ATA_ABORTED)
+                                               printk("BadCRC ");
                                else            printk("Sector ");
                        }
-                       if (err & 0x40)         printk("UncorrectableError ");
-                       if (err & 0x10)         printk("SectorIdNotFound ");
-                       if (err & 0x02)         printk("TrackZeroNotFound ");
-                       if (err & 0x01)         printk("AddrMarkNotFound ");
+                       if (err & ATA_UNC)      printk("UncorrectableError ");
+                       if (err & ATA_IDNF)     printk("SectorIdNotFound ");
+                       if (err & ATA_TRK0NF)   printk("TrackZeroNotFound ");
+                       if (err & ATA_AMNF)     printk("AddrMarkNotFound ");
                        printk("}\n");
                }
        }
@@ -849,40 +865,59 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
        /* Based on the 3ware driver translation table */
        static const unsigned char sense_table[][4] = {
                /* BBD|ECC|ID|MAR */
-               {0xd1,          ABORTED_COMMAND, 0x00, 0x00},   // Device busy                  Aborted command
+               {0xd1,          ABORTED_COMMAND, 0x00, 0x00},
+                       // Device busy                  Aborted command
                /* BBD|ECC|ID */
-               {0xd0,          ABORTED_COMMAND, 0x00, 0x00},   // Device busy                  Aborted command
+               {0xd0,          ABORTED_COMMAND, 0x00, 0x00},
+                       // Device busy                  Aborted command
                /* ECC|MC|MARK */
-               {0x61,          HARDWARE_ERROR, 0x00, 0x00},    // Device fault                 Hardware error
+               {0x61,          HARDWARE_ERROR, 0x00, 0x00},
+                       // Device fault                 Hardware error
                /* ICRC|ABRT */         /* NB: ICRC & !ABRT is BBD */
-               {0x84,          ABORTED_COMMAND, 0x47, 0x00},   // Data CRC error               SCSI parity error
+               {0x84,          ABORTED_COMMAND, 0x47, 0x00},
+                       // Data CRC error               SCSI parity error
                /* MC|ID|ABRT|TRK0|MARK */
-               {0x37,          NOT_READY, 0x04, 0x00},         // Unit offline                 Not ready
+               {0x37,          NOT_READY, 0x04, 0x00},
+                       // Unit offline                 Not ready
                /* MCR|MARK */
-               {0x09,          NOT_READY, 0x04, 0x00},         // Unrecovered disk error       Not ready
+               {0x09,          NOT_READY, 0x04, 0x00},
+                       // Unrecovered disk error       Not ready
                /*  Bad address mark */
-               {0x01,          MEDIUM_ERROR, 0x13, 0x00},      // Address mark not found       Address mark not found for data field
-               /* TRK0 */
-               {0x02,          HARDWARE_ERROR, 0x00, 0x00},    // Track 0 not found            Hardware error
+               {0x01,          MEDIUM_ERROR, 0x13, 0x00},
+                       // Address mark not found for data field
+               /* TRK0 - Track 0 not found */
+               {0x02,          HARDWARE_ERROR, 0x00, 0x00},
+                       // Hardware error
                /* Abort: 0x04 is not translated here, see below */
                /* Media change request */
-               {0x08,          NOT_READY, 0x04, 0x00},         // Media change request   FIXME: faking offline
-               /* SRV/IDNF */
-               {0x10,          ILLEGAL_REQUEST, 0x21, 0x00},   // ID not found                 Logical address out of range
-               /* MC */
-               {0x20,          UNIT_ATTENTION, 0x28, 0x00},    // Media Changed                Not ready to ready change, medium may have changed
-               /* ECC */
-               {0x40,          MEDIUM_ERROR, 0x11, 0x04},      // Uncorrectable ECC error      Unrecovered read error
+               {0x08,          NOT_READY, 0x04, 0x00},
+                       // FIXME: faking offline
+               /* SRV/IDNF - ID not found */
+               {0x10,          ILLEGAL_REQUEST, 0x21, 0x00},
+                       // Logical address out of range
+               /* MC - Media Changed */
+               {0x20,          UNIT_ATTENTION, 0x28, 0x00},
+                       // Not ready to ready change, medium may have changed
+               /* ECC - Uncorrectable ECC error */
+               {0x40,          MEDIUM_ERROR, 0x11, 0x04},
+                       // Unrecovered read error
                /* BBD - block marked bad */
-               {0x80,          MEDIUM_ERROR, 0x11, 0x04},      // Block marked bad             Medium error, unrecovered read error
+               {0x80,          MEDIUM_ERROR, 0x11, 0x04},
+                       // Block marked bad     Medium error, unrecovered read error
                {0xFF, 0xFF, 0xFF, 0xFF}, // END mark
        };
        static const unsigned char stat_table[][4] = {
                /* Must be first because BUSY means no other bits valid */
-               {0x80,          ABORTED_COMMAND, 0x47, 0x00},   // Busy, fake parity for now
-               {0x20,          HARDWARE_ERROR,  0x44, 0x00},   // Device fault, internal target failure
-               {0x08,          ABORTED_COMMAND, 0x47, 0x00},   // Timed out in xfer, fake parity for now
-               {0x04,          RECOVERED_ERROR, 0x11, 0x00},   // Recovered ECC error    Medium error, recovered
+               {0x80,          ABORTED_COMMAND, 0x47, 0x00},
+               // Busy, fake parity for now
+               {0x40,          ILLEGAL_REQUEST, 0x21, 0x04},
+               // Device ready, unaligned write command
+               {0x20,          HARDWARE_ERROR,  0x44, 0x00},
+               // Device fault, internal target failure
+               {0x08,          ABORTED_COMMAND, 0x47, 0x00},
+               // Timed out in xfer, fake parity for now
+               {0x04,          RECOVERED_ERROR, 0x11, 0x00},
+               // Recovered ECC error    Medium error, recovered
                {0xFF, 0xFF, 0xFF, 0xFF}, // END mark
        };
 
@@ -1757,7 +1792,9 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
            ((cdb[2] & 0x20) || need_sense)) {
                ata_gen_passthru_sense(qc);
        } else {
-               if (!need_sense) {
+               if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+                       cmd->result = SAM_STAT_CHECK_CONDITION;
+               } else if (!need_sense) {
                        cmd->result = SAM_STAT_GOOD;
                } else {
                        /* TODO: decide which descriptor format to use
@@ -4240,10 +4277,7 @@ int ata_sas_allocate_tag(struct ata_port *ap)
        unsigned int i, tag;
 
        for (i = 0, tag = ap->sas_last_tag + 1; i < max_queue; i++, tag++) {
-               if (ap->flags & ATA_FLAG_LOWTAG)
-                       tag = 1;
-               else
-                       tag = tag < max_queue ? tag : 0;
+               tag = tag < max_queue ? tag : 0;
 
                /* the last tag is reserved for internal command. */
                if (tag == ATA_TAG_INTERNAL)
index 2e86e3b852666e3b57e55aafde26ba1c13f8c695..cdf6215a9a22beb93ede75a702797e12c5ad4870 100644 (file)
@@ -3220,11 +3220,11 @@ void ata_pci_bmdma_init(struct ata_host *host)
         * ->sff_irq_clear method.  Try to initialize bmdma_addr
         * regardless of dma masks.
         */
-       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                ata_bmdma_nodma(host, "failed to set dma mask");
        if (!rc) {
-               rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+               rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK);
                if (rc)
                        ata_bmdma_nodma(host,
                                        "failed to set consistent dma mask");
diff --git a/drivers/ata/libata-trace.c b/drivers/ata/libata-trace.c
new file mode 100644 (file)
index 0000000..fd30b8c
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * libata-trace.c - trace functions for libata
+ *
+ * Copyright 2015 Hannes Reinecke
+ * Copyright 2015 SUSE Linux GmbH
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/trace_seq.h>
+#include <trace/events/libata.h>
+
+const char *
+libata_trace_parse_status(struct trace_seq *p, unsigned char status)
+{
+       const char *ret = trace_seq_buffer_ptr(p);
+
+       trace_seq_printf(p, "{ ");
+       if (status & ATA_BUSY)
+               trace_seq_printf(p, "BUSY ");
+       if (status & ATA_DRDY)
+               trace_seq_printf(p, "DRDY ");
+       if (status & ATA_DF)
+               trace_seq_printf(p, "DF ");
+       if (status & ATA_DSC)
+               trace_seq_printf(p, "DSC ");
+       if (status & ATA_DRQ)
+               trace_seq_printf(p, "DRQ ");
+       if (status & ATA_CORR)
+               trace_seq_printf(p, "CORR ");
+       if (status & ATA_SENSE)
+               trace_seq_printf(p, "SENSE ");
+       if (status & ATA_ERR)
+               trace_seq_printf(p, "ERR ");
+       trace_seq_putc(p, '}');
+       trace_seq_putc(p, 0);
+
+       return ret;
+}
+
+const char *
+libata_trace_parse_eh_action(struct trace_seq *p, unsigned int eh_action)
+{
+       const char *ret = trace_seq_buffer_ptr(p);
+
+       trace_seq_printf(p, "%x", eh_action);
+       if (eh_action) {
+               trace_seq_printf(p, "{ ");
+               if (eh_action & ATA_EH_REVALIDATE)
+                       trace_seq_printf(p, "REVALIDATE ");
+               if (eh_action & (ATA_EH_SOFTRESET | ATA_EH_HARDRESET))
+                       trace_seq_printf(p, "RESET ");
+               else if (eh_action & ATA_EH_SOFTRESET)
+                       trace_seq_printf(p, "SOFTRESET ");
+               else if (eh_action & ATA_EH_HARDRESET)
+                       trace_seq_printf(p, "HARDRESET ");
+               if (eh_action & ATA_EH_ENABLE_LINK)
+                       trace_seq_printf(p, "ENABLE_LINK ");
+               if (eh_action & ATA_EH_PARK)
+                       trace_seq_printf(p, "PARK ");
+               trace_seq_putc(p, '}');
+       }
+       trace_seq_putc(p, 0);
+
+       return ret;
+}
+
+const char *
+libata_trace_parse_eh_err_mask(struct trace_seq *p, unsigned int eh_err_mask)
+{
+       const char *ret = trace_seq_buffer_ptr(p);
+
+       trace_seq_printf(p, "%x", eh_err_mask);
+       if (eh_err_mask) {
+               trace_seq_printf(p, "{ ");
+               if (eh_err_mask & AC_ERR_DEV)
+                       trace_seq_printf(p, "DEV ");
+               if (eh_err_mask & AC_ERR_HSM)
+                       trace_seq_printf(p, "HSM ");
+               if (eh_err_mask & AC_ERR_TIMEOUT)
+                       trace_seq_printf(p, "TIMEOUT ");
+               if (eh_err_mask & AC_ERR_MEDIA)
+                       trace_seq_printf(p, "MEDIA ");
+               if (eh_err_mask & AC_ERR_ATA_BUS)
+                       trace_seq_printf(p, "ATA_BUS ");
+               if (eh_err_mask & AC_ERR_HOST_BUS)
+                       trace_seq_printf(p, "HOST_BUS ");
+               if (eh_err_mask & AC_ERR_SYSTEM)
+                       trace_seq_printf(p, "SYSTEM ");
+               if (eh_err_mask & AC_ERR_INVALID)
+                       trace_seq_printf(p, "INVALID ");
+               if (eh_err_mask & AC_ERR_OTHER)
+                       trace_seq_printf(p, "OTHER ");
+               if (eh_err_mask & AC_ERR_NODEV_HINT)
+                       trace_seq_printf(p, "NODEV_HINT ");
+               if (eh_err_mask & AC_ERR_NCQ)
+                       trace_seq_printf(p, "NCQ ");
+               trace_seq_putc(p, '}');
+       }
+       trace_seq_putc(p, 0);
+
+       return ret;
+}
+
+const char *
+libata_trace_parse_qc_flags(struct trace_seq *p, unsigned int qc_flags)
+{
+       const char *ret = trace_seq_buffer_ptr(p);
+
+       trace_seq_printf(p, "%x", qc_flags);
+       if (qc_flags) {
+               trace_seq_printf(p, "{ ");
+               if (qc_flags & ATA_QCFLAG_ACTIVE)
+                       trace_seq_printf(p, "ACTIVE ");
+               if (qc_flags & ATA_QCFLAG_DMAMAP)
+                       trace_seq_printf(p, "DMAMAP ");
+               if (qc_flags & ATA_QCFLAG_IO)
+                       trace_seq_printf(p, "IO ");
+               if (qc_flags & ATA_QCFLAG_RESULT_TF)
+                       trace_seq_printf(p, "RESULT_TF ");
+               if (qc_flags & ATA_QCFLAG_CLEAR_EXCL)
+                       trace_seq_printf(p, "CLEAR_EXCL ");
+               if (qc_flags & ATA_QCFLAG_QUIET)
+                       trace_seq_printf(p, "QUIET ");
+               if (qc_flags & ATA_QCFLAG_RETRY)
+                       trace_seq_printf(p, "RETRY ");
+               if (qc_flags & ATA_QCFLAG_FAILED)
+                       trace_seq_printf(p, "FAILED ");
+               if (qc_flags & ATA_QCFLAG_SENSE_VALID)
+                       trace_seq_printf(p, "SENSE_VALID ");
+               if (qc_flags & ATA_QCFLAG_EH_SCHEDULED)
+                       trace_seq_printf(p, "EH_SCHEDULED ");
+               trace_seq_putc(p, '}');
+       }
+       trace_seq_putc(p, 0);
+
+       return ret;
+}
index f840ca18a7c014f5151d22e4bc55dff9fca459de..a998a175f9f144b50e4df782bbf7d1afd5f506cb 100644 (file)
@@ -67,7 +67,8 @@ 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(struct ata_taskfile *tf, struct ata_device *dev);
+extern u64 ata_tf_read_block(const 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,
@@ -137,6 +138,9 @@ 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 a705cfca90f7210806f7d61e4897aaec738a0f8f..3ea50dc5ea47480d0cf81b5f69825b8675737070 100644 (file)
@@ -475,11 +475,11 @@ static int atp867x_ata_pci_sff_init_host(struct ata_host *host)
 
        atp867x_fixup(host);
 
-       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
 
-       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK);
        return rc;
 }
 
index d65cb9d2fa8c1966dc8c33c1a535a580b7bea3d2..4cb24070cc2d23d6f51a40341db48ea236497b0c 100644 (file)
@@ -164,11 +164,11 @@ static int cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
                return -ENODEV;
        }
 
-       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+       if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
                printk(KERN_ERR DRV_NAME ": unable to configure DMA mask.\n");
                return -ENODEV;
        }
-       if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
+       if (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) {
                printk(KERN_ERR DRV_NAME ": unable to configure consistent DMA mask.\n");
                return -ENODEV;
        }
index d019cdd5bc9f3deb0e1f6a70000c0fb9b7c89090..b2fc023783b15c3338160d3a0370a4e494b5db6f 100644 (file)
@@ -221,10 +221,10 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        if (rc)
                return rc;
        host->iomap = pcim_iomap_table(pdev);
-       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
-       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
 
index efb272da8567e9c5c8b4605f5d38df6f25591a01..633aa2934a18f5c05f5e03cdaf5742a9b0735f99 100644 (file)
@@ -122,10 +122,10 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                return rc;
 
        host->iomap = pcim_iomap_table(dev);
-       rc = pci_set_dma_mask(dev, ATA_DMA_MASK);
+       rc = dma_set_mask(&dev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
-       rc = pci_set_consistent_dma_mask(dev, ATA_DMA_MASK);
+       rc = dma_set_coherent_mask(&dev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
        pci_set_master(dev);
index dca8251b1aeaed1fd38769f9a8e118d3b4357da5..d9ef9e276225456b5b2c5825ab6ca79c7f192582 100644 (file)
@@ -730,11 +730,11 @@ static int pdc2027x_init_one(struct pci_dev *pdev,
                return rc;
        host->iomap = pcim_iomap_table(pdev);
 
-       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
 
-       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
 
index 7f4cb76ed9fac1c6ff51a5f91ad4df0468ac5096..5cd60d6388ec88b683e88688f2df0d71cfbfa119 100644 (file)
@@ -1029,10 +1029,10 @@ static int scc_host_init(struct ata_host *host)
        if (rc)
                return rc;
 
-       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
-       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
 
index f597edccedecd1ab952d95fd0dd178e4c1be8c4c..c14071be4f55f2f5222f5599b7570bba6de4d430 100644 (file)
@@ -374,10 +374,10 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        host->iomap = pcim_iomap_table(pdev);
 
        /* Setup DMA masks */
-       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
-       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
        pci_set_master(pdev);
index f10631beffa87cd258950bb4c85778ce166205e0..64d682c6ee57e2afb7dc475cc3a15d70ff75d9d5 100644 (file)
@@ -593,12 +593,12 @@ static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
 {
        int rc;
 
-       rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+       rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
        if (rc) {
                dev_err(&pdev->dev, "32-bit DMA enable failed\n");
                return rc;
        }
-       rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+       rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
        if (rc) {
                dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n");
                return rc;
index fdb0f2879ea7c65a055eca20ccd8ba0642d0fc1e..902034991517347c6bbcb38f09fbdd99e63aaba3 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/libata.h>
 #include <linux/slab.h>
+
 #include "libata.h"
 
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 
+/* Supported DMA engine drivers */
+#include <linux/platform_data/dma-dw.h>
+#include <linux/dma/dw.h>
+
 /* These two are defined in "libata.h" */
 #undef DRV_NAME
 #undef DRV_VERSION
 #define NO_IRQ         0
 #endif
 
-/* SATA DMA driver Globals */
-#define DMA_NUM_CHANS          1
-#define DMA_NUM_CHAN_REGS      8
-
-/* SATA DMA Register definitions */
 #define AHB_DMA_BRST_DFLT      64      /* 16 data items burst length*/
 
-struct dmareg {
-       u32 low;                /* Low bits 0-31 */
-       u32 high;               /* High bits 32-63 */
-};
-
-/* DMA Per Channel registers */
-struct dma_chan_regs {
-       struct dmareg sar;      /* Source Address */
-       struct dmareg dar;      /* Destination address */
-       struct dmareg llp;      /* Linked List Pointer */
-       struct dmareg ctl;      /* Control */
-       struct dmareg sstat;    /* Source Status not implemented in core */
-       struct dmareg dstat;    /* Destination Status not implemented in core*/
-       struct dmareg sstatar;  /* Source Status Address not impl in core */
-       struct dmareg dstatar;  /* Destination Status Address not implemente */
-       struct dmareg cfg;      /* Config */
-       struct dmareg sgr;      /* Source Gather */
-       struct dmareg dsr;      /* Destination Scatter */
-};
-
-/* Generic Interrupt Registers */
-struct dma_interrupt_regs {
-       struct dmareg tfr;      /* Transfer Interrupt */
-       struct dmareg block;    /* Block Interrupt */
-       struct dmareg srctran;  /* Source Transfer Interrupt */
-       struct dmareg dsttran;  /* Dest Transfer Interrupt */
-       struct dmareg error;    /* Error */
-};
-
-struct ahb_dma_regs {
-       struct dma_chan_regs    chan_regs[DMA_NUM_CHAN_REGS];
-       struct dma_interrupt_regs interrupt_raw;        /* Raw Interrupt */
-       struct dma_interrupt_regs interrupt_status;     /* Interrupt Status */
-       struct dma_interrupt_regs interrupt_mask;       /* Interrupt Mask */
-       struct dma_interrupt_regs interrupt_clear;      /* Interrupt Clear */
-       struct dmareg           statusInt;      /* Interrupt combined*/
-       struct dmareg           rq_srcreg;      /* Src Trans Req */
-       struct dmareg           rq_dstreg;      /* Dst Trans Req */
-       struct dmareg           rq_sgl_srcreg;  /* Sngl Src Trans Req*/
-       struct dmareg           rq_sgl_dstreg;  /* Sngl Dst Trans Req*/
-       struct dmareg           rq_lst_srcreg;  /* Last Src Trans Req*/
-       struct dmareg           rq_lst_dstreg;  /* Last Dst Trans Req*/
-       struct dmareg           dma_cfg;                /* DMA Config */
-       struct dmareg           dma_chan_en;            /* DMA Channel Enable*/
-       struct dmareg           dma_id;                 /* DMA ID */
-       struct dmareg           dma_test;               /* DMA Test */
-       struct dmareg           res1;                   /* reserved */
-       struct dmareg           res2;                   /* reserved */
-       /*
-        * DMA Comp Params
-        * Param 6 = dma_param[0], Param 5 = dma_param[1],
-        * Param 4 = dma_param[2] ...
-        */
-       struct dmareg           dma_params[6];
-};
-
-/* Data structure for linked list item */
-struct lli {
-       u32             sar;            /* Source Address */
-       u32             dar;            /* Destination address */
-       u32             llp;            /* Linked List Pointer */
-       struct dmareg   ctl;            /* Control */
-       struct dmareg   dstat;          /* Destination Status */
-};
-
-enum {
-       SATA_DWC_DMAC_LLI_SZ =  (sizeof(struct lli)),
-       SATA_DWC_DMAC_LLI_NUM = 256,
-       SATA_DWC_DMAC_LLI_TBL_SZ = (SATA_DWC_DMAC_LLI_SZ * \
-                                       SATA_DWC_DMAC_LLI_NUM),
-       SATA_DWC_DMAC_TWIDTH_BYTES = 4,
-       SATA_DWC_DMAC_CTRL_TSIZE_MAX = (0x00000800 * \
-                                               SATA_DWC_DMAC_TWIDTH_BYTES),
-};
-
-/* DMA Register Operation Bits */
-enum {
-       DMA_EN  =               0x00000001, /* Enable AHB DMA */
-       DMA_CTL_LLP_SRCEN =     0x10000000, /* Blk chain enable Src */
-       DMA_CTL_LLP_DSTEN =     0x08000000, /* Blk chain enable Dst */
-};
-
-#define        DMA_CTL_BLK_TS(size)    ((size) & 0x000000FFF)  /* Blk Transfer size */
-#define DMA_CHANNEL(ch)                (0x00000001 << (ch))    /* Select channel */
-       /* Enable channel */
-#define        DMA_ENABLE_CHAN(ch)     ((0x00000001 << (ch)) |                 \
-                                ((0x000000001 << (ch)) << 8))
-       /* Disable channel */
-#define        DMA_DISABLE_CHAN(ch)    (0x00000000 | ((0x000000001 << (ch)) << 8))
-       /* Transfer Type & Flow Controller */
-#define        DMA_CTL_TTFC(type)      (((type) & 0x7) << 20)
-#define        DMA_CTL_SMS(num)        (((num) & 0x3) << 25) /* Src Master Select */
-#define        DMA_CTL_DMS(num)        (((num) & 0x3) << 23)/* Dst Master Select */
-       /* Src Burst Transaction Length */
-#define DMA_CTL_SRC_MSIZE(size) (((size) & 0x7) << 14)
-       /* Dst Burst Transaction Length */
-#define        DMA_CTL_DST_MSIZE(size) (((size) & 0x7) << 11)
-       /* Source Transfer Width */
-#define        DMA_CTL_SRC_TRWID(size) (((size) & 0x7) << 4)
-       /* Destination Transfer Width */
-#define        DMA_CTL_DST_TRWID(size) (((size) & 0x7) << 1)
-
-/* Assign HW handshaking interface (x) to destination / source peripheral */
-#define        DMA_CFG_HW_HS_DEST(int_num) (((int_num) & 0xF) << 11)
-#define        DMA_CFG_HW_HS_SRC(int_num) (((int_num) & 0xF) << 7)
-#define        DMA_CFG_HW_CH_PRIOR(int_num) (((int_num) & 0xF) << 5)
-#define        DMA_LLP_LMS(addr, master) (((addr) & 0xfffffffc) | (master))
-
-/*
- * This define is used to set block chaining disabled in the control low
- * register.  It is already in little endian format so it can be &'d dirctly.
- * It is essentially: cpu_to_le32(~(DMA_CTL_LLP_SRCEN | DMA_CTL_LLP_DSTEN))
- */
 enum {
-       DMA_CTL_LLP_DISABLE_LE32 = 0xffffffe7,
-       DMA_CTL_TTFC_P2M_DMAC = 0x00000002, /* Per to mem, DMAC cntr */
-       DMA_CTL_TTFC_M2P_PER =  0x00000003, /* Mem to per, peripheral cntr */
-       DMA_CTL_SINC_INC =      0x00000000, /* Source Address Increment */
-       DMA_CTL_SINC_DEC =      0x00000200,
-       DMA_CTL_SINC_NOCHANGE = 0x00000400,
-       DMA_CTL_DINC_INC =      0x00000000, /* Destination Address Increment */
-       DMA_CTL_DINC_DEC =      0x00000080,
-       DMA_CTL_DINC_NOCHANGE = 0x00000100,
-       DMA_CTL_INT_EN =        0x00000001, /* Interrupt Enable */
-
-/* Channel Configuration Register high bits */
-       DMA_CFG_FCMOD_REQ =     0x00000001, /* Flow Control - request based */
-       DMA_CFG_PROTCTL =       (0x00000003 << 2),/* Protection Control */
-
-/* Channel Configuration Register low bits */
-       DMA_CFG_RELD_DST =      0x80000000, /* Reload Dest / Src Addr */
-       DMA_CFG_RELD_SRC =      0x40000000,
-       DMA_CFG_HS_SELSRC =     0x00000800, /* Software handshake Src/ Dest */
-       DMA_CFG_HS_SELDST =     0x00000400,
-       DMA_CFG_FIFOEMPTY =     (0x00000001 << 9), /* FIFO Empty bit */
-
-/* Channel Linked List Pointer Register */
-       DMA_LLP_AHBMASTER1 =    0,      /* List Master Select */
-       DMA_LLP_AHBMASTER2 =    1,
-
        SATA_DWC_MAX_PORTS = 1,
 
        SATA_DWC_SCR_OFFSET = 0x24,
@@ -287,7 +148,7 @@ struct sata_dwc_device {
        struct ata_host         *host;
        u8 __iomem              *reg_base;
        struct sata_dwc_regs    *sata_dwc_regs; /* DW Synopsys SATA specific */
-       int                     irq_dma;
+       struct dw_dma_chip      *dma;
 };
 
 #define SATA_DWC_QCMD_MAX      32
@@ -295,10 +156,13 @@ struct sata_dwc_device {
 struct sata_dwc_device_port {
        struct sata_dwc_device  *hsdev;
        int                     cmd_issued[SATA_DWC_QCMD_MAX];
-       struct lli              *llit[SATA_DWC_QCMD_MAX];  /* DMA LLI table */
-       dma_addr_t              llit_dma[SATA_DWC_QCMD_MAX];
-       u32                     dma_chan[SATA_DWC_QCMD_MAX];
        int                     dma_pending[SATA_DWC_QCMD_MAX];
+
+       /* DMA info */
+       struct dw_dma_slave             *dws;
+       struct dma_chan                 *chan;
+       struct dma_async_tx_descriptor  *desc[SATA_DWC_QCMD_MAX];
+       u32                             dma_interrupt_count;
 };
 
 /*
@@ -330,14 +194,17 @@ struct sata_dwc_host_priv {
        void    __iomem  *scr_addr_sstatus;
        u32     sata_dwc_sactive_issued ;
        u32     sata_dwc_sactive_queued ;
-       u32     dma_interrupt_count;
-       struct  ahb_dma_regs    *sata_dma_regs;
-       struct  device  *dwc_dev;
-       int     dma_channel;
 };
 
 static struct sata_dwc_host_priv host_pvt;
 
+static struct dw_dma_slave sata_dwc_dma_dws = {
+       .src_id = 0,
+       .dst_id = 0,
+       .src_master = 0,
+       .dst_master = 1,
+};
+
 /*
  * Prototypes
  */
@@ -347,12 +214,6 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc,
 static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status);
 static void sata_dwc_port_stop(struct ata_port *ap);
 static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag);
-static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq);
-static void dma_dwc_exit(struct sata_dwc_device *hsdev);
-static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,
-                             struct lli *lli, dma_addr_t dma_lli,
-                             void __iomem *addr, int dir);
-static void dma_dwc_xfer_start(int dma_ch);
 
 static const char *get_prot_descript(u8 protocol)
 {
@@ -390,90 +251,23 @@ static const char *get_dma_dir_descript(int dma_dir)
        }
 }
 
-static void sata_dwc_tf_dump(struct ata_taskfile *tf)
+static void sata_dwc_tf_dump(struct ata_port *ap, struct ata_taskfile *tf)
 {
-       dev_vdbg(host_pvt.dwc_dev, "taskfile cmd: 0x%02x protocol: %s flags:"
-               "0x%lx device: %x\n", tf->command,
-               get_prot_descript(tf->protocol), tf->flags, tf->device);
-       dev_vdbg(host_pvt.dwc_dev, "feature: 0x%02x nsect: 0x%x lbal: 0x%x "
-               "lbam: 0x%x lbah: 0x%x\n", tf->feature, tf->nsect, tf->lbal,
-                tf->lbam, tf->lbah);
-       dev_vdbg(host_pvt.dwc_dev, "hob_feature: 0x%02x hob_nsect: 0x%x "
-               "hob_lbal: 0x%x hob_lbam: 0x%x hob_lbah: 0x%x\n",
+       dev_vdbg(ap->dev,
+               "taskfile cmd: 0x%02x protocol: %s flags: 0x%lx device: %x\n",
+               tf->command, get_prot_descript(tf->protocol), tf->flags,
+               tf->device);
+       dev_vdbg(ap->dev,
+               "feature: 0x%02x nsect: 0x%x lbal: 0x%x lbam: 0x%x lbah: 0x%x\n",
+               tf->feature, tf->nsect, tf->lbal, tf->lbam, tf->lbah);
+       dev_vdbg(ap->dev,
+               "hob_feature: 0x%02x hob_nsect: 0x%x hob_lbal: 0x%x hob_lbam: 0x%x hob_lbah: 0x%x\n",
                tf->hob_feature, tf->hob_nsect, tf->hob_lbal, tf->hob_lbam,
                tf->hob_lbah);
 }
 
-/*
- * Function: get_burst_length_encode
- * arguments: datalength: length in bytes of data
- * returns value to be programmed in register corresponding to data length
- * This value is effectively the log(base 2) of the length
- */
-static  int get_burst_length_encode(int datalength)
-{
-       int items = datalength >> 2;    /* div by 4 to get lword count */
-
-       if (items >= 64)
-               return 5;
-
-       if (items >= 32)
-               return 4;
-
-       if (items >= 16)
-               return 3;
-
-       if (items >= 8)
-               return 2;
-
-       if (items >= 4)
-               return 1;
-
-       return 0;
-}
-
-static  void clear_chan_interrupts(int c)
+static void dma_dwc_xfer_done(void *hsdev_instance)
 {
-       out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.tfr.low),
-                DMA_CHANNEL(c));
-       out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.block.low),
-                DMA_CHANNEL(c));
-       out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.srctran.low),
-                DMA_CHANNEL(c));
-       out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.dsttran.low),
-                DMA_CHANNEL(c));
-       out_le32(&(host_pvt.sata_dma_regs->interrupt_clear.error.low),
-                DMA_CHANNEL(c));
-}
-
-/*
- * Function: dma_request_channel
- * arguments: None
- * returns channel number if available else -1
- * This function assigns the next available DMA channel from the list to the
- * requester
- */
-static int dma_request_channel(void)
-{
-       /* Check if the channel is not currently in use */
-       if (!(in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low)) &
-               DMA_CHANNEL(host_pvt.dma_channel)))
-               return host_pvt.dma_channel;
-       dev_err(host_pvt.dwc_dev, "%s Channel %d is currently in use\n",
-               __func__, host_pvt.dma_channel);
-       return -1;
-}
-
-/*
- * Function: dma_dwc_interrupt
- * arguments: irq, dev_id, pt_regs
- * returns channel number if available else -1
- * Interrupt Handler for DW AHB SATA DMA
- */
-static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance)
-{
-       int chan;
-       u32 tfr_reg, err_reg;
        unsigned long flags;
        struct sata_dwc_device *hsdev = hsdev_instance;
        struct ata_host *host = (struct ata_host *)hsdev->host;
@@ -487,341 +281,65 @@ static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance)
        hsdevp = HSDEVP_FROM_AP(ap);
        tag = ap->link.active_tag;
 
-       tfr_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.tfr\
-                       .low));
-       err_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.error\
-                       .low));
-
-       dev_dbg(ap->dev, "eot=0x%08x err=0x%08x pending=%d active port=%d\n",
-               tfr_reg, err_reg, hsdevp->dma_pending[tag], port);
-
-       chan = host_pvt.dma_channel;
-       if (chan >= 0) {
-               /* Check for end-of-transfer interrupt. */
-               if (tfr_reg & DMA_CHANNEL(chan)) {
-                       /*
-                        * Each DMA command produces 2 interrupts.  Only
-                        * complete the command after both interrupts have been
-                        * seen. (See sata_dwc_isr())
-                        */
-                       host_pvt.dma_interrupt_count++;
-                       sata_dwc_clear_dmacr(hsdevp, tag);
-
-                       if (hsdevp->dma_pending[tag] ==
-                           SATA_DWC_DMA_PENDING_NONE) {
-                               dev_err(ap->dev, "DMA not pending eot=0x%08x "
-                                       "err=0x%08x tag=0x%02x pending=%d\n",
-                                       tfr_reg, err_reg, tag,
-                                       hsdevp->dma_pending[tag]);
-                       }
-
-                       if ((host_pvt.dma_interrupt_count % 2) == 0)
-                               sata_dwc_dma_xfer_complete(ap, 1);
-
-                       /* Clear the interrupt */
-                       out_le32(&(host_pvt.sata_dma_regs->interrupt_clear\
-                               .tfr.low),
-                                DMA_CHANNEL(chan));
-               }
-
-               /* Check for error interrupt. */
-               if (err_reg & DMA_CHANNEL(chan)) {
-                       /* TODO Need error handler ! */
-                       dev_err(ap->dev, "error interrupt err_reg=0x%08x\n",
-                               err_reg);
-
-                       /* Clear the interrupt. */
-                       out_le32(&(host_pvt.sata_dma_regs->interrupt_clear\
-                               .error.low),
-                                DMA_CHANNEL(chan));
-               }
-       }
-       spin_unlock_irqrestore(&host->lock, flags);
-       return IRQ_HANDLED;
-}
-
-/*
- * Function: dma_request_interrupts
- * arguments: hsdev
- * returns status
- * This function registers ISR for a particular DMA channel interrupt
- */
-static int dma_request_interrupts(struct sata_dwc_device *hsdev, int irq)
-{
-       int retval = 0;
-       int chan = host_pvt.dma_channel;
-
-       if (chan >= 0) {
-               /* Unmask error interrupt */
-               out_le32(&(host_pvt.sata_dma_regs)->interrupt_mask.error.low,
-                        DMA_ENABLE_CHAN(chan));
-
-               /* Unmask end-of-transfer interrupt */
-               out_le32(&(host_pvt.sata_dma_regs)->interrupt_mask.tfr.low,
-                        DMA_ENABLE_CHAN(chan));
-       }
-
-       retval = request_irq(irq, dma_dwc_interrupt, 0, "SATA DMA", hsdev);
-       if (retval) {
-               dev_err(host_pvt.dwc_dev, "%s: could not get IRQ %d\n",
-               __func__, irq);
-               return -ENODEV;
-       }
-
-       /* Mark this interrupt as requested */
-       hsdev->irq_dma = irq;
-       return 0;
-}
-
-/*
- * Function: map_sg_to_lli
- * The Synopsis driver has a comment proposing that better performance
- * is possible by only enabling interrupts on the last item in the linked list.
- * However, it seems that could be a problem if an error happened on one of the
- * first items.  The transfer would halt, but no error interrupt would occur.
- * Currently this function sets interrupts enabled for each linked list item:
- * DMA_CTL_INT_EN.
- */
-static int map_sg_to_lli(struct scatterlist *sg, int num_elems,
-                       struct lli *lli, dma_addr_t dma_lli,
-                       void __iomem *dmadr_addr, int dir)
-{
-       int i, idx = 0;
-       int fis_len = 0;
-       dma_addr_t next_llp;
-       int bl;
-       int sms_val, dms_val;
-
-       sms_val = 0;
-       dms_val = 1 + host_pvt.dma_channel;
-       dev_dbg(host_pvt.dwc_dev,
-               "%s: sg=%p nelem=%d lli=%p dma_lli=0x%pad dmadr=0x%p\n",
-               __func__, sg, num_elems, lli, &dma_lli, dmadr_addr);
-
-       bl = get_burst_length_encode(AHB_DMA_BRST_DFLT);
-
-       for (i = 0; i < num_elems; i++, sg++) {
-               u32 addr, offset;
-               u32 sg_len, len;
-
-               addr = (u32) sg_dma_address(sg);
-               sg_len = sg_dma_len(sg);
-
-               dev_dbg(host_pvt.dwc_dev, "%s: elem=%d sg_addr=0x%x sg_len"
-                       "=%d\n", __func__, i, addr, sg_len);
-
-               while (sg_len) {
-                       if (idx >= SATA_DWC_DMAC_LLI_NUM) {
-                               /* The LLI table is not large enough. */
-                               dev_err(host_pvt.dwc_dev, "LLI table overrun "
-                               "(idx=%d)\n", idx);
-                               break;
-                       }
-                       len = (sg_len > SATA_DWC_DMAC_CTRL_TSIZE_MAX) ?
-                               SATA_DWC_DMAC_CTRL_TSIZE_MAX : sg_len;
-
-                       offset = addr & 0xffff;
-                       if ((offset + sg_len) > 0x10000)
-                               len = 0x10000 - offset;
-
-                       /*
-                        * Make sure a LLI block is not created that will span
-                        * 8K max FIS boundary.  If the block spans such a FIS
-                        * boundary, there is a chance that a DMA burst will
-                        * cross that boundary -- this results in an error in
-                        * the host controller.
-                        */
-                       if (fis_len + len > 8192) {
-                               dev_dbg(host_pvt.dwc_dev, "SPLITTING: fis_len="
-                                       "%d(0x%x) len=%d(0x%x)\n", fis_len,
-                                        fis_len, len, len);
-                               len = 8192 - fis_len;
-                               fis_len = 0;
-                       } else {
-                               fis_len += len;
-                       }
-                       if (fis_len == 8192)
-                               fis_len = 0;
-
-                       /*
-                        * Set DMA addresses and lower half of control register
-                        * based on direction.
-                        */
-                       if (dir == DMA_FROM_DEVICE) {
-                               lli[idx].dar = cpu_to_le32(addr);
-                               lli[idx].sar = cpu_to_le32((u32)dmadr_addr);
-
-                               lli[idx].ctl.low = cpu_to_le32(
-                                       DMA_CTL_TTFC(DMA_CTL_TTFC_P2M_DMAC) |
-                                       DMA_CTL_SMS(sms_val) |
-                                       DMA_CTL_DMS(dms_val) |
-                                       DMA_CTL_SRC_MSIZE(bl) |
-                                       DMA_CTL_DST_MSIZE(bl) |
-                                       DMA_CTL_SINC_NOCHANGE |
-                                       DMA_CTL_SRC_TRWID(2) |
-                                       DMA_CTL_DST_TRWID(2) |
-                                       DMA_CTL_INT_EN |
-                                       DMA_CTL_LLP_SRCEN |
-                                       DMA_CTL_LLP_DSTEN);
-                       } else {        /* DMA_TO_DEVICE */
-                               lli[idx].sar = cpu_to_le32(addr);
-                               lli[idx].dar = cpu_to_le32((u32)dmadr_addr);
-
-                               lli[idx].ctl.low = cpu_to_le32(
-                                       DMA_CTL_TTFC(DMA_CTL_TTFC_M2P_PER) |
-                                       DMA_CTL_SMS(dms_val) |
-                                       DMA_CTL_DMS(sms_val) |
-                                       DMA_CTL_SRC_MSIZE(bl) |
-                                       DMA_CTL_DST_MSIZE(bl) |
-                                       DMA_CTL_DINC_NOCHANGE |
-                                       DMA_CTL_SRC_TRWID(2) |
-                                       DMA_CTL_DST_TRWID(2) |
-                                       DMA_CTL_INT_EN |
-                                       DMA_CTL_LLP_SRCEN |
-                                       DMA_CTL_LLP_DSTEN);
-                       }
-
-                       dev_dbg(host_pvt.dwc_dev, "%s setting ctl.high len: "
-                               "0x%08x val: 0x%08x\n", __func__,
-                               len, DMA_CTL_BLK_TS(len / 4));
-
-                       /* Program the LLI CTL high register */
-                       lli[idx].ctl.high = cpu_to_le32(DMA_CTL_BLK_TS\
-                                               (len / 4));
-
-                       /* Program the next pointer.  The next pointer must be
-                        * the physical address, not the virtual address.
-                        */
-                       next_llp = (dma_lli + ((idx + 1) * sizeof(struct \
-                                                       lli)));
-
-                       /* The last 2 bits encode the list master select. */
-                       next_llp = DMA_LLP_LMS(next_llp, DMA_LLP_AHBMASTER2);
-
-                       lli[idx].llp = cpu_to_le32(next_llp);
-                       idx++;
-                       sg_len -= len;
-                       addr += len;
-               }
-       }
-
        /*
-        * The last next ptr has to be zero and the last control low register
-        * has to have LLP_SRC_EN and LLP_DST_EN (linked list pointer source
-        * and destination enable) set back to 0 (disabled.) This is what tells
-        * the core that this is the last item in the linked list.
+        * Each DMA command produces 2 interrupts.  Only
+        * complete the command after both interrupts have been
+        * seen. (See sata_dwc_isr())
         */
-       if (idx) {
-               lli[idx-1].llp = 0x00000000;
-               lli[idx-1].ctl.low &= DMA_CTL_LLP_DISABLE_LE32;
+       hsdevp->dma_interrupt_count++;
+       sata_dwc_clear_dmacr(hsdevp, tag);
 
-               /* Flush cache to memory */
-               dma_cache_sync(NULL, lli, (sizeof(struct lli) * idx),
-                              DMA_BIDIRECTIONAL);
+       if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_NONE) {
+               dev_err(ap->dev, "DMA not pending tag=0x%02x pending=%d\n",
+                       tag, hsdevp->dma_pending[tag]);
        }
 
-       return idx;
-}
+       if ((hsdevp->dma_interrupt_count % 2) == 0)
+               sata_dwc_dma_xfer_complete(ap, 1);
 
-/*
- * Function: dma_dwc_xfer_start
- * arguments: Channel number
- * Return : None
- * Enables the DMA channel
- */
-static void dma_dwc_xfer_start(int dma_ch)
-{
-       /* Enable the DMA channel */
-       out_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low),
-                in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low)) |
-                DMA_ENABLE_CHAN(dma_ch));
+       spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,
-                             struct lli *lli, dma_addr_t dma_lli,
-                             void __iomem *addr, int dir)
+static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd *qc)
 {
-       int dma_ch;
-       int num_lli;
-       /* Acquire DMA channel */
-       dma_ch = dma_request_channel();
-       if (dma_ch == -1) {
-               dev_err(host_pvt.dwc_dev, "%s: dma channel unavailable\n",
-                        __func__);
-               return -EAGAIN;
+       struct ata_port *ap = qc->ap;
+       struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
+       struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
+       dma_addr_t addr = (dma_addr_t)&hsdev->sata_dwc_regs->dmadr;
+       struct dma_slave_config sconf;
+       struct dma_async_tx_descriptor *desc;
+
+       if (qc->dma_dir == DMA_DEV_TO_MEM) {
+               sconf.src_addr = addr;
+               sconf.device_fc = true;
+       } else {        /* DMA_MEM_TO_DEV */
+               sconf.dst_addr = addr;
+               sconf.device_fc = false;
        }
 
-       /* Convert SG list to linked list of items (LLIs) for AHB DMA */
-       num_lli = map_sg_to_lli(sg, num_elems, lli, dma_lli, addr, dir);
-
-       dev_dbg(host_pvt.dwc_dev, "%s sg: 0x%p, count: %d lli: %p dma_lli:"
-               " 0x%0xlx addr: %p lli count: %d\n", __func__, sg, num_elems,
-                lli, (u32)dma_lli, addr, num_lli);
-
-       clear_chan_interrupts(dma_ch);
+       sconf.direction = qc->dma_dir;
+       sconf.src_maxburst = AHB_DMA_BRST_DFLT;
+       sconf.dst_maxburst = AHB_DMA_BRST_DFLT;
+       sconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       sconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 
-       /* Program the CFG register. */
-       out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].cfg.high),
-                DMA_CFG_HW_HS_SRC(dma_ch) | DMA_CFG_HW_HS_DEST(dma_ch) |
-                DMA_CFG_PROTCTL | DMA_CFG_FCMOD_REQ);
-       out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].cfg.low),
-                DMA_CFG_HW_CH_PRIOR(dma_ch));
+       dmaengine_slave_config(hsdevp->chan, &sconf);
 
-       /* Program the address of the linked list */
-       out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].llp.low),
-                DMA_LLP_LMS(dma_lli, DMA_LLP_AHBMASTER2));
-
-       /* Program the CTL register with src enable / dst enable */
-       out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].ctl.low),
-                DMA_CTL_LLP_SRCEN | DMA_CTL_LLP_DSTEN);
-       return dma_ch;
-}
-
-/*
- * Function: dma_dwc_exit
- * arguments: None
- * returns status
- * This function exits the SATA DMA driver
- */
-static void dma_dwc_exit(struct sata_dwc_device *hsdev)
-{
-       dev_dbg(host_pvt.dwc_dev, "%s:\n", __func__);
-       if (host_pvt.sata_dma_regs) {
-               iounmap((void __iomem *)host_pvt.sata_dma_regs);
-               host_pvt.sata_dma_regs = NULL;
-       }
-
-       if (hsdev->irq_dma) {
-               free_irq(hsdev->irq_dma, hsdev);
-               hsdev->irq_dma = 0;
-       }
-}
-
-/*
- * Function: dma_dwc_init
- * arguments: hsdev
- * returns status
- * This function initializes the SATA DMA driver
- */
-static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq)
-{
-       int err;
+       /* Convert SG list to linked list of items (LLIs) for AHB DMA */
+       desc = dmaengine_prep_slave_sg(hsdevp->chan, qc->sg, qc->n_elem,
+                                      qc->dma_dir,
+                                      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 
-       err = dma_request_interrupts(hsdev, irq);
-       if (err) {
-               dev_err(host_pvt.dwc_dev, "%s: dma_request_interrupts returns"
-                       " %d\n", __func__, err);
-               return err;
-       }
+       if (!desc)
+               return NULL;
 
-       /* Enabe DMA */
-       out_le32(&(host_pvt.sata_dma_regs->dma_cfg.low), DMA_EN);
+       desc->callback = dma_dwc_xfer_done;
+       desc->callback_param = hsdev;
 
-       dev_notice(host_pvt.dwc_dev, "DMA initialized\n");
-       dev_dbg(host_pvt.dwc_dev, "SATA DMA registers=0x%p\n", host_pvt.\
-               sata_dma_regs);
+       dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pad\n",
+               __func__, qc->sg, qc->n_elem, &addr);
 
-       return 0;
+       return desc;
 }
 
 static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val)
@@ -891,21 +409,18 @@ static void sata_dwc_error_intr(struct ata_port *ap,
        struct ata_queued_cmd *qc;
        u32 serror;
        u8 status, tag;
-       u32 err_reg;
 
        ata_ehi_clear_desc(ehi);
 
        serror = core_scr_read(SCR_ERROR);
        status = ap->ops->sff_check_status(ap);
 
-       err_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.error.\
-                       low));
        tag = ap->link.active_tag;
 
-       dev_err(ap->dev, "%s SCR_ERROR=0x%08x intpr=0x%08x status=0x%08x "
-               "dma_intp=%d pending=%d issued=%d dma_err_status=0x%08x\n",
-               __func__, serror, intpr, status, host_pvt.dma_interrupt_count,
-               hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag], err_reg);
+       dev_err(ap->dev,
+               "%s SCR_ERROR=0x%08x intpr=0x%08x status=0x%08x dma_intp=%d pending=%d issued=%d",
+               __func__, serror, intpr, status, hsdevp->dma_interrupt_count,
+               hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag]);
 
        /* Clear error register and interrupt bit */
        clear_serror();
@@ -1003,8 +518,9 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
 
                /* DEV interrupt w/ no active qc? */
                if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
-                       dev_err(ap->dev, "%s interrupt with no active qc "
-                               "qc=%p\n", __func__, qc);
+                       dev_err(ap->dev,
+                               "%s interrupt with no active qc qc=%p\n",
+                               __func__, qc);
                        ap->ops->sff_check_status(ap);
                        handled = 1;
                        goto DONE;
@@ -1031,16 +547,16 @@ DRVSTILLBUSY:
                         * operation done interrupt. The command should be
                         * completed only after both interrupts are seen.
                         */
-                       host_pvt.dma_interrupt_count++;
+                       hsdevp->dma_interrupt_count++;
                        if (hsdevp->dma_pending[tag] == \
                                        SATA_DWC_DMA_PENDING_NONE) {
-                               dev_err(ap->dev, "%s: DMA not pending "
-                                       "intpr=0x%08x status=0x%08x pending"
-                                       "=%d\n", __func__, intpr, status,
+                               dev_err(ap->dev,
+                                       "%s: DMA not pending intpr=0x%08x status=0x%08x pending=%d\n",
+                                       __func__, intpr, status,
                                        hsdevp->dma_pending[tag]);
                        }
 
-                       if ((host_pvt.dma_interrupt_count % 2) == 0)
+                       if ((hsdevp->dma_interrupt_count % 2) == 0)
                                sata_dwc_dma_xfer_complete(ap, 1);
                } else if (ata_is_pio(qc->tf.protocol)) {
                        ata_sff_hsm_move(ap, qc, status, 0);
@@ -1068,17 +584,17 @@ DRVSTILLBUSY:
 
        if (sactive != 0 || (host_pvt.sata_dwc_sactive_issued) > 1 || \
                                                        tag_mask > 1) {
-               dev_dbg(ap->dev, "%s NCQ:sactive=0x%08x  sactive_issued=0x%08x"
-                       "tag_mask=0x%08x\n", __func__, sactive,
-                       host_pvt.sata_dwc_sactive_issued, tag_mask);
+               dev_dbg(ap->dev,
+                       "%s NCQ:sactive=0x%08x  sactive_issued=0x%08x tag_mask=0x%08x\n",
+                       __func__, sactive, host_pvt.sata_dwc_sactive_issued,
+                       tag_mask);
        }
 
        if ((tag_mask | (host_pvt.sata_dwc_sactive_issued)) != \
                                        (host_pvt.sata_dwc_sactive_issued)) {
-               dev_warn(ap->dev, "Bad tag mask?  sactive=0x%08x "
-                        "(host_pvt.sata_dwc_sactive_issued)=0x%08x  tag_mask"
-                        "=0x%08x\n", sactive, host_pvt.sata_dwc_sactive_issued,
-                         tag_mask);
+               dev_warn(ap->dev,
+                        "Bad tag mask?  sactive=0x%08x (host_pvt.sata_dwc_sactive_issued)=0x%08x  tag_mask=0x%08x\n",
+                        sactive, host_pvt.sata_dwc_sactive_issued, tag_mask);
        }
 
        /* read just to clear ... not bad if currently still busy */
@@ -1114,12 +630,12 @@ DRVSTILLBUSY:
                dev_dbg(ap->dev, "%s NCQ command, protocol: %s\n", __func__,
                        get_prot_descript(qc->tf.protocol));
                if (ata_is_dma(qc->tf.protocol)) {
-                       host_pvt.dma_interrupt_count++;
+                       hsdevp->dma_interrupt_count++;
                        if (hsdevp->dma_pending[tag] == \
                                        SATA_DWC_DMA_PENDING_NONE)
                                dev_warn(ap->dev, "%s: DMA not pending?\n",
                                        __func__);
-                       if ((host_pvt.dma_interrupt_count % 2) == 0)
+                       if ((hsdevp->dma_interrupt_count % 2) == 0)
                                sata_dwc_dma_xfer_complete(ap, 1);
                } else {
                        if (unlikely(sata_dwc_qc_complete(ap, qc, 1)))
@@ -1142,8 +658,9 @@ STILLBUSY:
         */
        sactive2 = core_scr_read(SCR_ACTIVE);
        if (sactive2 != sactive) {
-               dev_dbg(ap->dev, "More completed - sactive=0x%x sactive2"
-                       "=0x%x\n", sactive, sactive2);
+               dev_dbg(ap->dev,
+                       "More completed - sactive=0x%x sactive2=0x%x\n",
+                       sactive, sactive2);
        }
        handled = 1;
 
@@ -1169,11 +686,10 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag)
                 * This should not happen, it indicates the driver is out of
                 * sync.  If it does happen, clear dmacr anyway.
                 */
-               dev_err(host_pvt.dwc_dev, "%s DMA protocol RX and"
-                       "TX DMA not pending tag=0x%02x pending=%d"
-                       " dmacr: 0x%08x\n", __func__, tag,
-                       hsdevp->dma_pending[tag],
-                       in_le32(&(hsdev->sata_dwc_regs->dmacr)));
+               dev_err(hsdev->dev,
+                       "%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n",
+                       __func__, tag, hsdevp->dma_pending[tag],
+                       in_le32(&hsdev->sata_dwc_regs->dmacr));
                out_le32(&(hsdev->sata_dwc_regs->dmacr),
                        SATA_DWC_DMACR_TXRXCH_CLEAR);
        }
@@ -1195,8 +711,9 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status)
 
 #ifdef DEBUG_NCQ
        if (tag > 0) {
-               dev_info(ap->dev, "%s tag=%u cmd=0x%02x dma dir=%s proto=%s "
-                        "dmacr=0x%08x\n", __func__, qc->tag, qc->tf.command,
+               dev_info(ap->dev,
+                        "%s tag=%u cmd=0x%02x dma dir=%s proto=%s dmacr=0x%08x\n",
+                        __func__, qc->tag, qc->tf.command,
                         get_dma_dir_descript(qc->dma_dir),
                         get_prot_descript(qc->tf.protocol),
                         in_le32(&(hsdev->sata_dwc_regs->dmacr)));
@@ -1205,8 +722,9 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status)
 
        if (ata_is_dma(qc->tf.protocol)) {
                if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_NONE) {
-                       dev_err(ap->dev, "%s DMA protocol RX and TX DMA not "
-                               "pending dmacr: 0x%08x\n", __func__,
+                       dev_err(ap->dev,
+                               "%s DMA protocol RX and TX DMA not pending dmacr: 0x%08x\n",
+                               __func__,
                                in_le32(&(hsdev->sata_dwc_regs->dmacr)));
                }
 
@@ -1232,9 +750,9 @@ static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc,
                dev_err(ap->dev, "TX DMA PENDING\n");
        else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX)
                dev_err(ap->dev, "RX DMA PENDING\n");
-       dev_dbg(ap->dev, "QC complete cmd=0x%02x status=0x%02x ata%u:"
-               " protocol=%d\n", qc->tf.command, status, ap->print_id,
-                qc->tf.protocol);
+       dev_dbg(ap->dev,
+               "QC complete cmd=0x%02x status=0x%02x ata%u: protocol=%d\n",
+               qc->tf.command, status, ap->print_id, qc->tf.protocol);
 
        /* clear active bit */
        mask = (~(qcmd_tag_to_mask(tag)));
@@ -1260,11 +778,23 @@ static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev)
         */
        out_le32(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS);
 
-       dev_dbg(host_pvt.dwc_dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n",
+       dev_dbg(hsdev->dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n",
                 __func__, in_le32(&hsdev->sata_dwc_regs->intmr),
                in_le32(&hsdev->sata_dwc_regs->errmr));
 }
 
+static bool sata_dwc_dma_filter(struct dma_chan *chan, void *param)
+{
+       struct sata_dwc_device_port *hsdevp = param;
+       struct dw_dma_slave *dws = hsdevp->dws;
+
+       if (dws->dma_dev != chan->device->dev)
+               return false;
+
+       chan->private = dws;
+       return true;
+}
+
 static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base)
 {
        port->cmd_addr = (void __iomem *)base + 0x00;
@@ -1299,6 +829,7 @@ static int sata_dwc_port_start(struct ata_port *ap)
        struct sata_dwc_device *hsdev;
        struct sata_dwc_device_port *hsdevp = NULL;
        struct device *pdev;
+       dma_cap_mask_t mask;
        int i;
 
        hsdev = HSDEV_FROM_AP(ap);
@@ -1322,29 +853,27 @@ static int sata_dwc_port_start(struct ata_port *ap)
        }
        hsdevp->hsdev = hsdev;
 
+       hsdevp->dws = &sata_dwc_dma_dws;
+       hsdevp->dws->dma_dev = hsdev->dev;
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+
+       /* Acquire DMA channel */
+       hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp);
+       if (!hsdevp->chan) {
+               dev_err(hsdev->dev, "%s: dma channel unavailable\n",
+                        __func__);
+               err = -EAGAIN;
+               goto CLEANUP_ALLOC;
+       }
+
        for (i = 0; i < SATA_DWC_QCMD_MAX; i++)
                hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT;
 
        ap->bmdma_prd = NULL;   /* set these so libata doesn't use them */
        ap->bmdma_prd_dma = 0;
 
-       /*
-        * DMA - Assign scatter gather LLI table. We can't use the libata
-        * version since it's PRD is IDE PCI specific.
-        */
-       for (i = 0; i < SATA_DWC_QCMD_MAX; i++) {
-               hsdevp->llit[i] = dma_alloc_coherent(pdev,
-                                                    SATA_DWC_DMAC_LLI_TBL_SZ,
-                                                    &(hsdevp->llit_dma[i]),
-                                                    GFP_ATOMIC);
-               if (!hsdevp->llit[i]) {
-                       dev_err(ap->dev, "%s: dma_alloc_coherent failed\n",
-                                __func__);
-                       err = -ENOMEM;
-                       goto CLEANUP_ALLOC;
-               }
-       }
-
        if (ap->port_no == 0)  {
                dev_dbg(ap->dev, "%s: clearing TXCHEN, RXCHEN in DMAC\n",
                        __func__);
@@ -1373,22 +902,14 @@ CLEANUP:
 
 static void sata_dwc_port_stop(struct ata_port *ap)
 {
-       int i;
-       struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
        struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
 
        dev_dbg(ap->dev, "%s: ap->id = %d\n", __func__, ap->print_id);
 
-       if (hsdevp && hsdev) {
-               /* deallocate LLI table */
-               for (i = 0; i < SATA_DWC_QCMD_MAX; i++) {
-                       dma_free_coherent(ap->host->dev,
-                                         SATA_DWC_DMAC_LLI_TBL_SZ,
-                                        hsdevp->llit[i], hsdevp->llit_dma[i]);
-               }
+       dmaengine_terminate_all(hsdevp->chan);
+       dma_release_channel(hsdevp->chan);
 
-               kfree(hsdevp);
-       }
+       kfree(hsdevp);
        ap->private_data = NULL;
 }
 
@@ -1444,12 +965,12 @@ static void sata_dwc_bmdma_setup(struct ata_queued_cmd *qc)
 static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag)
 {
        int start_dma;
-       u32 reg, dma_chan;
+       u32 reg;
        struct sata_dwc_device *hsdev = HSDEV_FROM_QC(qc);
        struct ata_port *ap = qc->ap;
        struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
+       struct dma_async_tx_descriptor *desc = hsdevp->desc[tag];
        int dir = qc->dma_dir;
-       dma_chan = hsdevp->dma_chan[tag];
 
        if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_NOT) {
                start_dma = 1;
@@ -1458,16 +979,17 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag)
                else
                        hsdevp->dma_pending[tag] = SATA_DWC_DMA_PENDING_RX;
        } else {
-               dev_err(ap->dev, "%s: Command not pending cmd_issued=%d "
-                       "(tag=%d) DMA NOT started\n", __func__,
-                       hsdevp->cmd_issued[tag], tag);
+               dev_err(ap->dev,
+                       "%s: Command not pending cmd_issued=%d (tag=%d) DMA NOT started\n",
+                       __func__, hsdevp->cmd_issued[tag], tag);
                start_dma = 0;
        }
 
-       dev_dbg(ap->dev, "%s qc=%p tag: %x cmd: 0x%02x dma_dir: %s "
-               "start_dma? %x\n", __func__, qc, tag, qc->tf.command,
+       dev_dbg(ap->dev,
+               "%s qc=%p tag: %x cmd: 0x%02x dma_dir: %s start_dma? %x\n",
+               __func__, qc, tag, qc->tf.command,
                get_dma_dir_descript(qc->dma_dir), start_dma);
-       sata_dwc_tf_dump(&(qc->tf));
+       sata_dwc_tf_dump(ap, &qc->tf);
 
        if (start_dma) {
                reg = core_scr_read(SCR_ERROR);
@@ -1484,7 +1006,8 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag)
                                SATA_DWC_DMACR_RXCHEN);
 
                /* Enable AHB DMA transfer on the specified channel */
-               dma_dwc_xfer_start(dma_chan);
+               dmaengine_submit(desc);
+               dma_async_issue_pending(hsdevp->chan);
        }
 }
 
@@ -1510,26 +1033,21 @@ static void sata_dwc_bmdma_start(struct ata_queued_cmd *qc)
  */
 static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag)
 {
-       struct scatterlist *sg = qc->sg;
+       struct dma_async_tx_descriptor *desc;
        struct ata_port *ap = qc->ap;
-       int dma_chan;
-       struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
        struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
 
        dev_dbg(ap->dev, "%s: port=%d dma dir=%s n_elem=%d\n",
                __func__, ap->port_no, get_dma_dir_descript(qc->dma_dir),
                 qc->n_elem);
 
-       dma_chan = dma_dwc_xfer_setup(sg, qc->n_elem, hsdevp->llit[tag],
-                                     hsdevp->llit_dma[tag],
-                                     (void __iomem *)&hsdev->sata_dwc_regs->dmadr,
-                                     qc->dma_dir);
-       if (dma_chan < 0) {
-               dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns err %d\n",
-                       __func__, dma_chan);
+       desc = dma_dwc_xfer_setup(qc);
+       if (!desc) {
+               dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns NULL\n",
+                       __func__);
                return;
        }
-       hsdevp->dma_chan[tag] = dma_chan;
+       hsdevp->desc[tag] = desc;
 }
 
 static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
@@ -1540,8 +1058,8 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
 
 #ifdef DEBUG_NCQ
        if (qc->tag > 0 || ap->link.sactive > 1)
-               dev_info(ap->dev, "%s ap id=%d cmd(0x%02x)=%s qc tag=%d "
-                        "prot=%s ap active_tag=0x%08x ap sactive=0x%08x\n",
+               dev_info(ap->dev,
+                        "%s ap id=%d cmd(0x%02x)=%s qc tag=%d prot=%s ap active_tag=0x%08x ap sactive=0x%08x\n",
                         __func__, ap->print_id, qc->tf.command,
                         ata_get_cmd_descript(qc->tf.command),
                         qc->tag, get_prot_descript(qc->tf.protocol),
@@ -1557,9 +1075,9 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
                sactive |= (0x00000001 << tag);
                core_scr_write(SCR_ACTIVE, sactive);
 
-               dev_dbg(qc->ap->dev, "%s: tag=%d ap->link.sactive = 0x%08x "
-                       "sactive=0x%08x\n", __func__, tag, qc->ap->link.sactive,
-                       sactive);
+               dev_dbg(qc->ap->dev,
+                       "%s: tag=%d ap->link.sactive = 0x%08x sactive=0x%08x\n",
+                       __func__, tag, qc->ap->link.sactive, sactive);
 
                ap->ops->sff_tf_load(ap, &qc->tf);
                sata_dwc_exec_command_by_tag(ap, &qc->tf, qc->tag,
@@ -1673,7 +1191,6 @@ static int sata_dwc_probe(struct platform_device *ofdev)
        struct ata_port_info pi = sata_dwc_port_info[0];
        const struct ata_port_info *ppi[] = { &pi, NULL };
        struct device_node *np = ofdev->dev.of_node;
-       u32 dma_chan;
 
        /* Allocate DWC SATA device */
        host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_DWC_MAX_PORTS);
@@ -1683,18 +1200,11 @@ static int sata_dwc_probe(struct platform_device *ofdev)
 
        host->private_data = hsdev;
 
-       if (of_property_read_u32(np, "dma-channel", &dma_chan)) {
-               dev_warn(&ofdev->dev, "no dma-channel property set."
-                        " Use channel 0\n");
-               dma_chan = 0;
-       }
-       host_pvt.dma_channel = dma_chan;
-
        /* Ioremap SATA registers */
        base = of_iomap(np, 0);
        if (!base) {
-               dev_err(&ofdev->dev, "ioremap failed for SATA register"
-                       " address\n");
+               dev_err(&ofdev->dev,
+                       "ioremap failed for SATA register address\n");
                return -ENODEV;
        }
        hsdev->reg_base = base;
@@ -1716,27 +1226,29 @@ static int sata_dwc_probe(struct platform_device *ofdev)
                   idr, ver[0], ver[1], ver[2]);
 
        /* Get SATA DMA interrupt number */
-       irq = irq_of_parse_and_map(np, 1);
-       if (irq == NO_IRQ) {
+       hsdev->dma->irq = irq_of_parse_and_map(np, 1);
+       if (hsdev->dma->irq == NO_IRQ) {
                dev_err(&ofdev->dev, "no SATA DMA irq\n");
                err = -ENODEV;
                goto error_iomap;
        }
 
        /* Get physical SATA DMA register base address */
-       host_pvt.sata_dma_regs = (void *)of_iomap(np, 1);
-       if (!(host_pvt.sata_dma_regs)) {
-               dev_err(&ofdev->dev, "ioremap failed for AHBDMA register"
-                       " address\n");
+       hsdev->dma->regs = of_iomap(np, 1);
+       if (!hsdev->dma->regs) {
+               dev_err(&ofdev->dev,
+                       "ioremap failed for AHBDMA register address\n");
                err = -ENODEV;
                goto error_iomap;
        }
 
        /* Save dev for later use in dev_xxx() routines */
-       host_pvt.dwc_dev = &ofdev->dev;
+       hsdev->dev = &ofdev->dev;
+
+       hsdev->dma->dev = &ofdev->dev;
 
        /* Initialize AHB DMAC */
-       err = dma_dwc_init(hsdev, irq);
+       err = dw_dma_probe(hsdev->dma, NULL);
        if (err)
                goto error_dma_iomap;
 
@@ -1765,9 +1277,9 @@ static int sata_dwc_probe(struct platform_device *ofdev)
 
 error_out:
        /* Free SATA DMA resources */
-       dma_dwc_exit(hsdev);
+       dw_dma_remove(hsdev->dma);
 error_dma_iomap:
-       iounmap((void __iomem *)host_pvt.sata_dma_regs);
+       iounmap(hsdev->dma->regs);
 error_iomap:
        iounmap(base);
        return err;
@@ -1782,9 +1294,9 @@ static int sata_dwc_remove(struct platform_device *ofdev)
        ata_host_detach(host);
 
        /* Free SATA DMA resources */
-       dma_dwc_exit(hsdev);
+       dw_dma_remove(hsdev->dma);
 
-       iounmap((void __iomem *)host_pvt.sata_dma_regs);
+       iounmap(hsdev->dma->regs);
        iounmap(hsdev->reg_base);
        dev_dbg(&ofdev->dev, "done\n");
        return 0;
@@ -1809,5 +1321,5 @@ module_platform_driver(sata_dwc_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Mark Miesfeld <mmiesfeld@amcc.com>");
-MODULE_DESCRIPTION("DesignWare Cores SATA controller low lever driver");
+MODULE_DESCRIPTION("DesignWare Cores SATA controller low level driver");
 MODULE_VERSION(DRV_VERSION);
index 069827826b20ea9c0ec6a9d13e61dee850ccd524..e81a8217f1ff7be37ea2c3d61d6d1326f9f55a5e 100644 (file)
@@ -856,13 +856,13 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        /* Set dma_mask.  This devices doesn't support 64bit addressing. */
-       rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+       rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
        if (rc) {
                dev_err(&pdev->dev, "32-bit DMA enable failed\n");
                return rc;
        }
 
-       rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+       rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
        if (rc) {
                dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n");
                return rc;
index f8c33e3772b823e123f4b32c2c066608297e06c2..bd74ee555278513118d057e832b3ec599923bb69 100644 (file)
@@ -306,6 +306,11 @@ enum {
        MV5_PHY_CTL             = 0x0C,
        SATA_IFCFG              = 0x050,
        LP_PHY_CTL              = 0x058,
+       LP_PHY_CTL_PIN_PU_PLL   = (1 << 0),
+       LP_PHY_CTL_PIN_PU_RX    = (1 << 1),
+       LP_PHY_CTL_PIN_PU_TX    = (1 << 2),
+       LP_PHY_CTL_GEN_TX_3G    = (1 << 5),
+       LP_PHY_CTL_GEN_RX_3G    = (1 << 9),
 
        MV_M2_PREAMP_MASK       = 0x7e0,
 
@@ -1391,10 +1396,17 @@ static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val)
                                /*
                                 * Set PHY speed according to SControl speed.
                                 */
-                               if ((val & 0xf0) == 0x10)
-                                       writelfl(0x7, lp_phy_addr);
-                               else
-                                       writelfl(0x227, lp_phy_addr);
+                               u32 lp_phy_val =
+                                       LP_PHY_CTL_PIN_PU_PLL |
+                                       LP_PHY_CTL_PIN_PU_RX  |
+                                       LP_PHY_CTL_PIN_PU_TX;
+
+                               if ((val & 0xf0) != 0x10)
+                                       lp_phy_val |=
+                                               LP_PHY_CTL_GEN_TX_3G |
+                                               LP_PHY_CTL_GEN_RX_3G;
+
+                               writelfl(lp_phy_val, lp_phy_addr);
                        }
                }
                writelfl(val, addr);
@@ -4308,10 +4320,10 @@ static int pci_go_64(struct pci_dev *pdev)
 {
        int rc;
 
-       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-               rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+       if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
+               rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
                if (rc) {
-                       rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+                       rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
                        if (rc) {
                                dev_err(&pdev->dev,
                                        "64-bit DMA enable failed\n");
@@ -4319,12 +4331,12 @@ static int pci_go_64(struct pci_dev *pdev)
                        }
                }
        } else {
-               rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+               rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
                if (rc) {
                        dev_err(&pdev->dev, "32-bit DMA enable failed\n");
                        return rc;
                }
-               rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+               rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
                if (rc) {
                        dev_err(&pdev->dev,
                                "32-bit consistent DMA enable failed\n");
index 1db6f5ce5e8912b149f33b49f8876ebc608fc8e8..7ece85f43020967a9f9b3b5657bf7ce50ae22c9f 100644 (file)
@@ -756,10 +756,10 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
                        blk_queue_bounce_limit(sdev1->request_queue,
                                               ATA_DMA_MASK);
 
-               pci_set_dma_mask(pdev, ATA_DMA_MASK);
+               dma_set_mask(&pdev->dev, ATA_DMA_MASK);
        } else {
                /** This shouldn't fail as it was set to this value before */
-               pci_set_dma_mask(pdev, pp->adma_dma_mask);
+               dma_set_mask(&pdev->dev, pp->adma_dma_mask);
                if (sdev0)
                        blk_queue_bounce_limit(sdev0->request_queue,
                                               pp->adma_dma_mask);
@@ -1133,10 +1133,10 @@ static int nv_adma_port_start(struct ata_port *ap)
 
        /* Ensure DMA mask is set to 32-bit before allocating legacy PRD and
           pad buffers */
-       rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+       rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
        if (rc)
                return rc;
-       rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+       rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
        if (rc)
                return rc;
 
@@ -1161,8 +1161,8 @@ static int nv_adma_port_start(struct ata_port *ap)
           These are allowed to fail since we store the value that ends up
           being used to set as the bounce limit in slave_config later if
           needed. */
-       pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
-       pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+       dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
+       dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
        pp->adma_dma_mask = *dev->dma_mask;
 
        mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ,
index 3638887476f610a933d57b29cae7f84c4d6f229f..0fa211e2831cda6381320ae4f208273a1502c66b 100644 (file)
@@ -1246,10 +1246,10 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
        /* initialize adapter */
        pdc_host_init(host);
 
-       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
-       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
 
index 9a6bd4cd29a0661cefd71f686e7c4bbc778911ed..af987a4f33d1904b70f5dc226f0c8c154d6b83ff 100644 (file)
@@ -557,10 +557,10 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
        int rc, have_64bit_bus = (bus_info & QS_HPHY_64BIT);
 
        if (have_64bit_bus &&
-           !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-               rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+           !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
+               rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
                if (rc) {
-                       rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+                       rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
                        if (rc) {
                                dev_err(&pdev->dev,
                                        "64-bit DMA enable failed\n");
@@ -568,12 +568,12 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
                        }
                }
        } else {
-               rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+               rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
                if (rc) {
                        dev_err(&pdev->dev, "32-bit DMA enable failed\n");
                        return rc;
                }
-               rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+               rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
                if (rc) {
                        dev_err(&pdev->dev,
                                "32-bit consistent DMA enable failed\n");
index 40b76b2d18c6968af8e977e6c8f94b080a65649e..dea6edcbf145c3d1eaf45d8265ae7f971d6c808c 100644 (file)
@@ -770,10 +770,10 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                return rc;
        host->iomap = pcim_iomap_table(pdev);
 
-       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
-       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
 
index ba2667fa0528ff1f2138c438bfe72d10c6757c87..4b1995e2d044ba7e4da5f6e36ec0c2d2dedafd50 100644 (file)
@@ -246,7 +246,7 @@ enum {
        /* host flags */
        SIL24_COMMON_FLAGS      = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |
                                  ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA |
-                                 ATA_FLAG_AN | ATA_FLAG_PMP | ATA_FLAG_LOWTAG,
+                                 ATA_FLAG_AN | ATA_FLAG_PMP,
        SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
 
        IRQ_STAT_4PORTS         = 0xf,
@@ -1312,10 +1312,10 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        host->iomap = iomap;
 
        /* configure and activate the device */
-       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-               rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+       if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
+               rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
                if (rc) {
-                       rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+                       rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
                        if (rc) {
                                dev_err(&pdev->dev,
                                        "64-bit DMA enable failed\n");
@@ -1323,12 +1323,12 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                        }
                }
        } else {
-               rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+               rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
                if (rc) {
                        dev_err(&pdev->dev, "32-bit DMA enable failed\n");
                        return rc;
                }
-               rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+               rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
                if (rc) {
                        dev_err(&pdev->dev,
                                "32-bit consistent DMA enable failed\n");
index c630fa81262439939c3ad770f3538e48c0862522..ff8307b30ff0ebc12b681e8e72aef711d8aaea1f 100644 (file)
@@ -496,10 +496,10 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en
                ata_port_pbar_desc(ap, 5, offset, "port");
        }
 
-       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
-       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
 
index 39b5de60a1f96a93a80193b5a7ce8ec6e0ecea43..3a18a8a719b4ff1fa562a515b4701da241e4aeb7 100644 (file)
@@ -1476,10 +1476,10 @@ static int pdc_sata_init_one(struct pci_dev *pdev,
        }
 
        /* configure and activate */
-       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
-       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
 
index 47bf89464cef80d57e490187d37b23d4656ca299..17d31fc009abbcf14e0ea3f14ad9c06be8ac5b35 100644 (file)
@@ -502,10 +502,10 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
        for (i = 0; i < host->n_ports; i++)
                vt6421_init_addrs(host->ports[i]);
 
-       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
-       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK);
        if (rc)
                return rc;
 
index 29e847aac34be5ea88871ff03c99856b20c4492e..183eb52085df148a8795a8328452c5c5cd6a8532 100644 (file)
@@ -387,10 +387,10 @@ static int vsc_sata_init_one(struct pci_dev *pdev,
        /*
         * Use 32 bit DMA mask, because 64 bit address support is poor.
         */
-       rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+       rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
        if (rc)
                return rc;
-       rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+       rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
        if (rc)
                return rc;
 
index 3ead3af4be6197b8addaafd375d247e8f8c38f70..2ba4cac080c5e79cc8b5056f18aa45b75e816bf6 100644 (file)
@@ -94,6 +94,7 @@ int
 attribute_container_unregister(struct attribute_container *cont)
 {
        int retval = -EBUSY;
+
        mutex_lock(&attribute_container_mutex);
        spin_lock(&cont->containers.k_lock);
        if (!list_empty(&cont->containers.k_list))
@@ -349,6 +350,7 @@ int
 attribute_container_add_class_device(struct device *classdev)
 {
        int error = device_add(classdev);
+
        if (error)
                return error;
        return attribute_container_add_attrs(classdev);
index 876bae5ade3393464bd7b2250af8f1ed29bf5bc8..79bc203f51ef08511eff94661cc77fac163475d5 100644 (file)
@@ -515,11 +515,11 @@ int bus_add_device(struct device *dev)
                        goto out_put;
                error = device_add_groups(dev, bus->dev_groups);
                if (error)
-                       goto out_groups;
+                       goto out_id;
                error = sysfs_create_link(&bus->p->devices_kset->kobj,
                                                &dev->kobj, dev_name(dev));
                if (error)
-                       goto out_id;
+                       goto out_groups;
                error = sysfs_create_link(&dev->kobj,
                                &dev->bus->p->subsys.kobj, "subsystem");
                if (error)
index 6e64563361f071703394694cd11c1493343071c2..9c2ba1c97c4257016503a8ed4d2166ac19dea9c0 100644 (file)
@@ -62,15 +62,21 @@ static int cache_setup_of_node(unsigned int cpu)
                return -ENOENT;
        }
 
-       while (np && index < cache_leaves(cpu)) {
+       while (index < cache_leaves(cpu)) {
                this_leaf = this_cpu_ci->info_list + index;
                if (this_leaf->level != 1)
                        np = of_find_next_cache_node(np);
                else
                        np = of_node_get(np);/* cpu node itself */
+               if (!np)
+                       break;
                this_leaf->of_node = np;
                index++;
        }
+
+       if (index != cache_leaves(cpu)) /* not all OF nodes populated */
+               return -ENOENT;
+
        return 0;
 }
 
@@ -189,8 +195,11 @@ static int detect_cache_attributes(unsigned int cpu)
         * will be set up here only if they are not populated already
         */
        ret = cache_shared_cpu_map_setup(cpu);
-       if (ret)
+       if (ret) {
+               pr_warn("Unable to detect cache hierarcy from DT for CPU %d\n",
+                       cpu);
                goto free_ci;
+       }
        return 0;
 
 free_ci:
index f96f70419a785a722283336a4ca71a73015574b9..6e810881e48b09f0615250c8f2ca2dfdbb47c44e 100644 (file)
@@ -90,6 +90,7 @@ int class_create_file_ns(struct class *cls, const struct class_attribute *attr,
                         const void *ns)
 {
        int error;
+
        if (cls)
                error = sysfs_create_file_ns(&cls->p->subsys.kobj,
                                             &attr->attr, ns);
@@ -488,6 +489,7 @@ ssize_t show_class_attr_string(struct class *class,
                               struct class_attribute *attr, char *buf)
 {
        struct class_attribute_string *cs;
+
        cs = container_of(attr, struct class_attribute_string, attr);
        return snprintf(buf, PAGE_SIZE, "%s\n", cs->str);
 }
index 07304a3b9ee2872d85526cba24eabd422997aa7e..cadf165651d8c5a507a32492fb78b7cff3e0b993 100644 (file)
@@ -805,8 +805,16 @@ static void cleanup_device_parent(struct device *dev)
 
 static int device_add_class_symlinks(struct device *dev)
 {
+       struct device_node *of_node = dev_of_node(dev);
        int error;
 
+       if (of_node) {
+               error = sysfs_create_link(&dev->kobj, &of_node->kobj,"of_node");
+               if (error)
+                       dev_warn(dev, "Error %d creating of_node link\n",error);
+               /* An error here doesn't warrant bringing down the device */
+       }
+
        if (!dev->class)
                return 0;
 
@@ -814,7 +822,7 @@ static int device_add_class_symlinks(struct device *dev)
                                  &dev->class->p->subsys.kobj,
                                  "subsystem");
        if (error)
-               goto out;
+               goto out_devnode;
 
        if (dev->parent && device_is_not_partition(dev)) {
                error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
@@ -842,12 +850,16 @@ out_device:
 
 out_subsys:
        sysfs_remove_link(&dev->kobj, "subsystem");
-out:
+out_devnode:
+       sysfs_remove_link(&dev->kobj, "of_node");
        return error;
 }
 
 static void device_remove_class_symlinks(struct device *dev)
 {
+       if (dev_of_node(dev))
+               sysfs_remove_link(&dev->kobj, "of_node");
+
        if (!dev->class)
                return;
 
@@ -1095,8 +1107,7 @@ done:
        kobject_del(&dev->kobj);
  Error:
        cleanup_device_parent(dev);
-       if (parent)
-               put_device(parent);
+       put_device(parent);
 name_error:
        kfree(dev->p);
        dev->p = NULL;
index cdc779cf79a362c095d3183a0b1a51b187db1dc9..49a4a12fafef176506a46063b390a194b29e9db4 100644 (file)
@@ -320,21 +320,25 @@ probe_failed:
        dev->driver = NULL;
        dev_set_drvdata(dev, NULL);
 
-       if (ret == -EPROBE_DEFER) {
+       switch (ret) {
+       case -EPROBE_DEFER:
                /* Driver requested deferred probing */
-               dev_info(dev, "Driver %s requests probe deferral\n", drv->name);
+               dev_dbg(dev, "Driver %s requests probe deferral\n", drv->name);
                driver_deferred_probe_add(dev);
                /* Did a trigger occur while probing? Need to re-trigger if yes */
                if (local_trigger_count != atomic_read(&deferred_trigger_count))
                        driver_deferred_probe_trigger();
-       } else if (ret != -ENODEV && ret != -ENXIO) {
+               break;
+       case -ENODEV:
+       case -ENXIO:
+               pr_debug("%s: probe of %s rejects match %d\n",
+                        drv->name, dev_name(dev), ret);
+               break;
+       default:
                /* driver matched but the probe failed */
                printk(KERN_WARNING
                       "%s: probe of %s failed with error %d\n",
                       drv->name, dev_name(dev), ret);
-       } else {
-               pr_debug("%s: probe of %s rejects match %d\n",
-                      drv->name, dev_name(dev), ret);
        }
        /*
         * Ignore errors returned by ->probe so that the next driver can try
index 9e8bbdd470ca8e8842ba7ef56fdd120f7e31dc13..d95c5971c2256f20f473d5744b01fc54bbf9acf2 100644 (file)
@@ -62,7 +62,7 @@ static int dmam_match(struct device *dev, void *res, void *match_data)
  * RETURNS:
  * Pointer to allocated memory on success, NULL on failure.
  */
-void * dmam_alloc_coherent(struct device *dev, size_t size,
+void *dmam_alloc_coherent(struct device *dev, size_t size,
                           dma_addr_t *dma_handle, gfp_t gfp)
 {
        struct dma_devres *dr;
index 9e29943e56cae1d18d9dfcf3564baf4f839f087a..4eabfe28d2b39a89955ef820c3b069ba7d3b79e3 100644 (file)
@@ -103,6 +103,7 @@ int driver_create_file(struct device_driver *drv,
                       const struct driver_attribute *attr)
 {
        int error;
+
        if (drv)
                error = sysfs_create_file(&drv->p->kobj, &attr->attr);
        else
index 6c5c9edf5ff661cf2e7cd3f4c85665419403cd1a..171841ad10089feef1aea6e6035327a68e745604 100644 (file)
@@ -181,7 +181,7 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name,
 {
        struct firmware_buf *buf;
 
-       buf = kzalloc(sizeof(*buf) + strlen(fw_name) + 1 , GFP_ATOMIC);
+       buf = kzalloc(sizeof(*buf) + strlen(fw_name) + 1, GFP_ATOMIC);
 
        if (!buf)
                return buf;
@@ -835,6 +835,26 @@ static struct bin_attribute firmware_attr_data = {
        .write = firmware_data_write,
 };
 
+static struct attribute *fw_dev_attrs[] = {
+       &dev_attr_loading.attr,
+       NULL
+};
+
+static struct bin_attribute *fw_dev_bin_attrs[] = {
+       &firmware_attr_data,
+       NULL
+};
+
+static const struct attribute_group fw_dev_attr_group = {
+       .attrs = fw_dev_attrs,
+       .bin_attrs = fw_dev_bin_attrs,
+};
+
+static const struct attribute_group *fw_dev_attr_groups[] = {
+       &fw_dev_attr_group,
+       NULL
+};
+
 static struct firmware_priv *
 fw_create_instance(struct firmware *firmware, const char *fw_name,
                   struct device *device, unsigned int opt_flags)
@@ -856,6 +876,7 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
        dev_set_name(f_dev, "%s", fw_name);
        f_dev->parent = device;
        f_dev->class = &firmware_class;
+       f_dev->groups = fw_dev_attr_groups;
 exit:
        return fw_priv;
 }
@@ -879,25 +900,10 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
                goto err_put_dev;
        }
 
-       retval = device_create_bin_file(f_dev, &firmware_attr_data);
-       if (retval) {
-               dev_err(f_dev, "%s: sysfs_create_bin_file failed\n", __func__);
-               goto err_del_dev;
-       }
-
        mutex_lock(&fw_lock);
        list_add(&buf->pending_list, &pending_fw_head);
        mutex_unlock(&fw_lock);
 
-       retval = device_create_file(f_dev, &dev_attr_loading);
-       if (retval) {
-               mutex_lock(&fw_lock);
-               list_del_init(&buf->pending_list);
-               mutex_unlock(&fw_lock);
-               dev_err(f_dev, "%s: device_create_file failed\n", __func__);
-               goto err_del_bin_attr;
-       }
-
        if (opt_flags & FW_OPT_UEVENT) {
                buf->need_uevent = true;
                dev_set_uevent_suppress(f_dev, false);
@@ -913,6 +919,8 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
                mutex_lock(&fw_lock);
                fw_load_abort(fw_priv);
                mutex_unlock(&fw_lock);
+       } else if (retval > 0) {
+               retval = 0;
        }
 
        if (is_fw_load_aborted(buf))
@@ -920,10 +928,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
        else if (!buf->data)
                retval = -ENOMEM;
 
-       device_remove_file(f_dev, &dev_attr_loading);
-err_del_bin_attr:
-       device_remove_bin_file(f_dev, &firmware_attr_data);
-err_del_dev:
        device_del(f_dev);
 err_put_dev:
        put_device(f_dev);
@@ -1168,7 +1172,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
  **/
 int
 request_firmware(const struct firmware **firmware_p, const char *name,
-                 struct device *device)
+                struct device *device)
 {
        int ret;
 
@@ -1196,6 +1200,7 @@ int request_firmware_direct(const struct firmware **firmware_p,
                            const char *name, struct device *device)
 {
        int ret;
+
        __module_get(THIS_MODULE);
        ret = _request_firmware(firmware_p, name, device,
                                FW_OPT_UEVENT | FW_OPT_NO_WARN);
@@ -1276,7 +1281,7 @@ request_firmware_nowait(
 {
        struct firmware_work *fw_work;
 
-       fw_work = kzalloc(sizeof (struct firmware_work), gfp);
+       fw_work = kzalloc(sizeof(struct firmware_work), gfp);
        if (!fw_work)
                return -ENOMEM;
 
index e87017f3685356854629a439ae4ec5900a7129e2..c1d38234d725c858f2b986f4e4d5e37a75449e5c 100644 (file)
@@ -41,8 +41,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
        if (n > 255)
                n = 255;
 
-       p = kmalloc(sizeof(struct probe) * n, GFP_KERNEL);
-
+       p = kmalloc_array(n, sizeof(struct probe), GFP_KERNEL);
        if (p == NULL)
                return -ENOMEM;
 
index 85be040a21c80505c09183c1578eb9c15f524244..2804aed3f416aea878efde04937937e238ff4e5e 100644 (file)
@@ -52,13 +52,13 @@ static BLOCKING_NOTIFIER_HEAD(memory_chain);
 
 int register_memory_notifier(struct notifier_block *nb)
 {
-        return blocking_notifier_chain_register(&memory_chain, nb);
+       return blocking_notifier_chain_register(&memory_chain, nb);
 }
 EXPORT_SYMBOL(register_memory_notifier);
 
 void unregister_memory_notifier(struct notifier_block *nb)
 {
-        blocking_notifier_chain_unregister(&memory_chain, nb);
+       blocking_notifier_chain_unregister(&memory_chain, nb);
 }
 EXPORT_SYMBOL(unregister_memory_notifier);
 
@@ -152,20 +152,20 @@ static ssize_t show_mem_state(struct device *dev,
         * so that they're not open-coded
         */
        switch (mem->state) {
-               case MEM_ONLINE:
-                       len = sprintf(buf, "online\n");
-                       break;
-               case MEM_OFFLINE:
-                       len = sprintf(buf, "offline\n");
-                       break;
-               case MEM_GOING_OFFLINE:
-                       len = sprintf(buf, "going-offline\n");
-                       break;
-               default:
-                       len = sprintf(buf, "ERROR-UNKNOWN-%ld\n",
-                                       mem->state);
-                       WARN_ON(1);
-                       break;
+       case MEM_ONLINE:
+               len = sprintf(buf, "online\n");
+               break;
+       case MEM_OFFLINE:
+               len = sprintf(buf, "offline\n");
+               break;
+       case MEM_GOING_OFFLINE:
+               len = sprintf(buf, "going-offline\n");
+               break;
+       default:
+               len = sprintf(buf, "ERROR-UNKNOWN-%ld\n",
+                               mem->state);
+               WARN_ON(1);
+               break;
        }
 
        return len;
@@ -219,6 +219,7 @@ static bool pages_correctly_reserved(unsigned long start_pfn)
 /*
  * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is
  * OK to have direct references to sparsemem variables in here.
+ * Must already be protected by mem_hotplug_begin().
  */
 static int
 memory_block_action(unsigned long phys_index, unsigned long action, int online_type)
@@ -228,23 +229,23 @@ memory_block_action(unsigned long phys_index, unsigned long action, int online_t
        struct page *first_page;
        int ret;
 
-       start_pfn = phys_index << PFN_SECTION_SHIFT;
+       start_pfn = section_nr_to_pfn(phys_index);
        first_page = pfn_to_page(start_pfn);
 
        switch (action) {
-               case MEM_ONLINE:
-                       if (!pages_correctly_reserved(start_pfn))
-                               return -EBUSY;
-
-                       ret = online_pages(start_pfn, nr_pages, online_type);
-                       break;
-               case MEM_OFFLINE:
-                       ret = offline_pages(start_pfn, nr_pages);
-                       break;
-               default:
-                       WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
-                            "%ld\n", __func__, phys_index, action, action);
-                       ret = -EINVAL;
+       case MEM_ONLINE:
+               if (!pages_correctly_reserved(start_pfn))
+                       return -EBUSY;
+
+               ret = online_pages(start_pfn, nr_pages, online_type);
+               break;
+       case MEM_OFFLINE:
+               ret = offline_pages(start_pfn, nr_pages);
+               break;
+       default:
+               WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
+                    "%ld\n", __func__, phys_index, action, action);
+               ret = -EINVAL;
        }
 
        return ret;
@@ -286,6 +287,7 @@ static int memory_subsys_online(struct device *dev)
        if (mem->online_type < 0)
                mem->online_type = MMOP_ONLINE_KEEP;
 
+       /* Already under protection of mem_hotplug_begin() */
        ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
 
        /* clear online_type */
@@ -328,17 +330,19 @@ store_mem_state(struct device *dev,
                goto err;
        }
 
+       /*
+        * Memory hotplug needs to hold mem_hotplug_begin() for probe to find
+        * the correct memory block to online before doing device_online(dev),
+        * which will take dev->mutex.  Take the lock early to prevent an
+        * inversion, memory_subsys_online() callbacks will be implemented by
+        * assuming it's already protected.
+        */
+       mem_hotplug_begin();
+
        switch (online_type) {
        case MMOP_ONLINE_KERNEL:
        case MMOP_ONLINE_MOVABLE:
        case MMOP_ONLINE_KEEP:
-               /*
-                * mem->online_type is not protected so there can be a
-                * race here.  However, when racing online, the first
-                * will succeed and the second will just return as the
-                * block will already be online.  The online type
-                * could be either one, but that is expected.
-                */
                mem->online_type = online_type;
                ret = device_online(&mem->dev);
                break;
@@ -349,6 +353,7 @@ store_mem_state(struct device *dev,
                ret = -EINVAL; /* should never happen */
        }
 
+       mem_hotplug_done();
 err:
        unlock_device_hotplug();
 
index 36fabe43cd4497b83eba8afdef4358325045f88b..a2aa65b4215d390925c8470d6790b129c16ac88a 100644 (file)
@@ -180,7 +180,7 @@ static ssize_t node_read_vmstat(struct device *dev,
 static DEVICE_ATTR(vmstat, S_IRUGO, node_read_vmstat, NULL);
 
 static ssize_t node_read_distance(struct device *dev,
-                       struct device_attribute *attr, char * buf)
+                       struct device_attribute *attr, char *buf)
 {
        int nid = dev->id;
        int len = 0;
@@ -200,6 +200,17 @@ static ssize_t node_read_distance(struct device *dev,
 }
 static DEVICE_ATTR(distance, S_IRUGO, node_read_distance, NULL);
 
+static struct attribute *node_dev_attrs[] = {
+       &dev_attr_cpumap.attr,
+       &dev_attr_cpulist.attr,
+       &dev_attr_meminfo.attr,
+       &dev_attr_numastat.attr,
+       &dev_attr_distance.attr,
+       &dev_attr_vmstat.attr,
+       NULL
+};
+ATTRIBUTE_GROUPS(node_dev);
+
 #ifdef CONFIG_HUGETLBFS
 /*
  * hugetlbfs per node attributes registration interface:
@@ -273,16 +284,10 @@ static int register_node(struct node *node, int num, struct node *parent)
        node->dev.id = num;
        node->dev.bus = &node_subsys;
        node->dev.release = node_device_release;
+       node->dev.groups = node_dev_groups;
        error = device_register(&node->dev);
 
        if (!error){
-               device_create_file(&node->dev, &dev_attr_cpumap);
-               device_create_file(&node->dev, &dev_attr_cpulist);
-               device_create_file(&node->dev, &dev_attr_meminfo);
-               device_create_file(&node->dev, &dev_attr_numastat);
-               device_create_file(&node->dev, &dev_attr_distance);
-               device_create_file(&node->dev, &dev_attr_vmstat);
-
                hugetlb_register_node(node);
 
                compaction_register_node(node);
@@ -299,13 +304,6 @@ static int register_node(struct node *node, int num, struct node *parent)
  */
 void unregister_node(struct node *node)
 {
-       device_remove_file(&node->dev, &dev_attr_cpumap);
-       device_remove_file(&node->dev, &dev_attr_cpulist);
-       device_remove_file(&node->dev, &dev_attr_meminfo);
-       device_remove_file(&node->dev, &dev_attr_numastat);
-       device_remove_file(&node->dev, &dev_attr_distance);
-       device_remove_file(&node->dev, &dev_attr_vmstat);
-
        hugetlb_unregister_node(node);          /* no-op, if memoryless node */
 
        device_unregister(&node->dev);
index 9421fed40905354040c10757744fb9f868650a83..e68ab79df28bbc9e84c3e2f6f17f92369144c96d 100644 (file)
@@ -101,6 +101,15 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
        }
 
        r = platform_get_resource(dev, IORESOURCE_IRQ, num);
+       /*
+        * The resources may pass trigger flags to the irqs that need
+        * to be set up. It so happens that the trigger flags for
+        * IORESOURCE_BITS correspond 1-to-1 to the IRQF_TRIGGER*
+        * settings.
+        */
+       if (r && r->flags & IORESOURCE_BITS)
+               irqd_set_trigger_type(irq_get_irq_data(r->start),
+                                     r->flags & IORESOURCE_BITS);
 
        return r ? r->start : -ENXIO;
 #endif
index c45845874d4fe9258eccd74e603dc94e851f8175..423df593f262b1e0defaa087599781dad8ee4b8a 100644 (file)
@@ -365,7 +365,7 @@ int fwnode_property_read_string(struct fwnode_handle *fwnode,
                                const char *propname, const char **val)
 {
        if (is_of_node(fwnode))
-               return of_property_read_string(of_node(fwnode),propname, val);
+               return of_property_read_string(of_node(fwnode), propname, val);
        else if (is_acpi_node(fwnode))
                return acpi_dev_prop_read(acpi_node(fwnode), propname,
                                          DEV_PROP_STRING, val, 1);
index 0a533653ef3bec4ea52d4883792eb4f587c7a78c..609e4c84f485b89ab0d219a3cfd06a2faf5a68ba 100644 (file)
@@ -1,3 +1,6 @@
+# For include/trace/define_trace.h to include trace.h
+CFLAGS_regmap.o := -I$(src)
+
 obj-$(CONFIG_REGMAP) += regmap.o regcache.o
 obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o regcache-flat.o
 obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
index 87db9893b463ba505acc3c28e253b5a08cf20c90..7eb7b3b98794849c6718c068504c7ac1acf3a2c9 100644 (file)
@@ -15,8 +15,8 @@
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/sort.h>
-#include <trace/events/regmap.h>
 
+#include "trace.h"
 #include "internal.h"
 
 static const struct regcache_ops *cache_types[] = {
index dbfe6a69c3daa67969df7c670f9e5144a053afb6..6273ff072f3eaa4cbd777b1a4f41fb3cf533a42a 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/sched.h>
 
 #define CREATE_TRACE_POINTS
-#include <trace/events/regmap.h>
+#include "trace.h"
 
 #include "internal.h"
 
diff --git a/drivers/base/regmap/trace.h b/drivers/base/regmap/trace.h
new file mode 100644 (file)
index 0000000..64586a1
--- /dev/null
@@ -0,0 +1,257 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM regmap
+
+#if !defined(_TRACE_REGMAP_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_REGMAP_H
+
+#include <linux/ktime.h>
+#include <linux/tracepoint.h>
+
+#include "internal.h"
+
+/*
+ * Log register events
+ */
+DECLARE_EVENT_CLASS(regmap_reg,
+
+       TP_PROTO(struct regmap *map, unsigned int reg,
+                unsigned int val),
+
+       TP_ARGS(map, reg, val),
+
+       TP_STRUCT__entry(
+               __string(       name,           regmap_name(map)        )
+               __field(        unsigned int,   reg                     )
+               __field(        unsigned int,   val                     )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, regmap_name(map));
+               __entry->reg = reg;
+               __entry->val = val;
+       ),
+
+       TP_printk("%s reg=%x val=%x", __get_str(name),
+                 (unsigned int)__entry->reg,
+                 (unsigned int)__entry->val)
+);
+
+DEFINE_EVENT(regmap_reg, regmap_reg_write,
+
+       TP_PROTO(struct regmap *map, unsigned int reg,
+                unsigned int val),
+
+       TP_ARGS(map, reg, val)
+
+);
+
+DEFINE_EVENT(regmap_reg, regmap_reg_read,
+
+       TP_PROTO(struct regmap *map, unsigned int reg,
+                unsigned int val),
+
+       TP_ARGS(map, reg, val)
+
+);
+
+DEFINE_EVENT(regmap_reg, regmap_reg_read_cache,
+
+       TP_PROTO(struct regmap *map, unsigned int reg,
+                unsigned int val),
+
+       TP_ARGS(map, reg, val)
+
+);
+
+DECLARE_EVENT_CLASS(regmap_block,
+
+       TP_PROTO(struct regmap *map, unsigned int reg, int count),
+
+       TP_ARGS(map, reg, count),
+
+       TP_STRUCT__entry(
+               __string(       name,           regmap_name(map)        )
+               __field(        unsigned int,   reg                     )
+               __field(        int,            count                   )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, regmap_name(map));
+               __entry->reg = reg;
+               __entry->count = count;
+       ),
+
+       TP_printk("%s reg=%x count=%d", __get_str(name),
+                 (unsigned int)__entry->reg,
+                 (int)__entry->count)
+);
+
+DEFINE_EVENT(regmap_block, regmap_hw_read_start,
+
+       TP_PROTO(struct regmap *map, unsigned int reg, int count),
+
+       TP_ARGS(map, reg, count)
+);
+
+DEFINE_EVENT(regmap_block, regmap_hw_read_done,
+
+       TP_PROTO(struct regmap *map, unsigned int reg, int count),
+
+       TP_ARGS(map, reg, count)
+);
+
+DEFINE_EVENT(regmap_block, regmap_hw_write_start,
+
+       TP_PROTO(struct regmap *map, unsigned int reg, int count),
+
+       TP_ARGS(map, reg, count)
+);
+
+DEFINE_EVENT(regmap_block, regmap_hw_write_done,
+
+       TP_PROTO(struct regmap *map, unsigned int reg, int count),
+
+       TP_ARGS(map, reg, count)
+);
+
+TRACE_EVENT(regcache_sync,
+
+       TP_PROTO(struct regmap *map, const char *type,
+                const char *status),
+
+       TP_ARGS(map, type, status),
+
+       TP_STRUCT__entry(
+               __string(       name,           regmap_name(map)        )
+               __string(       status,         status                  )
+               __string(       type,           type                    )
+               __field(        int,            type                    )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, regmap_name(map));
+               __assign_str(status, status);
+               __assign_str(type, type);
+       ),
+
+       TP_printk("%s type=%s status=%s", __get_str(name),
+                 __get_str(type), __get_str(status))
+);
+
+DECLARE_EVENT_CLASS(regmap_bool,
+
+       TP_PROTO(struct regmap *map, bool flag),
+
+       TP_ARGS(map, flag),
+
+       TP_STRUCT__entry(
+               __string(       name,           regmap_name(map)        )
+               __field(        int,            flag                    )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, regmap_name(map));
+               __entry->flag = flag;
+       ),
+
+       TP_printk("%s flag=%d", __get_str(name),
+                 (int)__entry->flag)
+);
+
+DEFINE_EVENT(regmap_bool, regmap_cache_only,
+
+       TP_PROTO(struct regmap *map, bool flag),
+
+       TP_ARGS(map, flag)
+
+);
+
+DEFINE_EVENT(regmap_bool, regmap_cache_bypass,
+
+       TP_PROTO(struct regmap *map, bool flag),
+
+       TP_ARGS(map, flag)
+
+);
+
+DECLARE_EVENT_CLASS(regmap_async,
+
+       TP_PROTO(struct regmap *map),
+
+       TP_ARGS(map),
+
+       TP_STRUCT__entry(
+               __string(       name,           regmap_name(map)        )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, regmap_name(map));
+       ),
+
+       TP_printk("%s", __get_str(name))
+);
+
+DEFINE_EVENT(regmap_block, regmap_async_write_start,
+
+       TP_PROTO(struct regmap *map, unsigned int reg, int count),
+
+       TP_ARGS(map, reg, count)
+);
+
+DEFINE_EVENT(regmap_async, regmap_async_io_complete,
+
+       TP_PROTO(struct regmap *map),
+
+       TP_ARGS(map)
+
+);
+
+DEFINE_EVENT(regmap_async, regmap_async_complete_start,
+
+       TP_PROTO(struct regmap *map),
+
+       TP_ARGS(map)
+
+);
+
+DEFINE_EVENT(regmap_async, regmap_async_complete_done,
+
+       TP_PROTO(struct regmap *map),
+
+       TP_ARGS(map)
+
+);
+
+TRACE_EVENT(regcache_drop_region,
+
+       TP_PROTO(struct regmap *map, unsigned int from,
+                unsigned int to),
+
+       TP_ARGS(map, from, to),
+
+       TP_STRUCT__entry(
+               __string(       name,           regmap_name(map)        )
+               __field(        unsigned int,   from                    )
+               __field(        unsigned int,   to                      )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, regmap_name(map));
+               __entry->from = from;
+               __entry->to = to;
+       ),
+
+       TP_printk("%s %u-%u", __get_str(name), (unsigned int)__entry->from,
+                 (unsigned int)__entry->to)
+);
+
+#endif /* _TRACE_REGMAP_H */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index 72b5e7280d14792e6d83f3a59e4d4793d20fe28c..39fca01c8fa19a295e3988adbd8c1e351bf24d3a 100644 (file)
@@ -43,8 +43,8 @@ struct device *soc_device_to_device(struct soc_device *soc_dev)
 }
 
 static umode_t soc_attribute_mode(struct kobject *kobj,
-                                 struct attribute *attr,
-                                 int index)
+                               struct attribute *attr,
+                               int index)
 {
        struct device *dev = container_of(kobj, struct device, kobj);
        struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
@@ -60,7 +60,7 @@ static umode_t soc_attribute_mode(struct kobject *kobj,
                return attr->mode;
        if ((attr == &dev_attr_soc_id.attr)
            && (soc_dev->attr->soc_id != NULL))
-               return attr->mode;
+               return attr->mode;
 
        /* Unknown or unfilled attribute. */
        return 0;
@@ -117,7 +117,7 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
 
        soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL);
        if (!soc_dev) {
-               ret = -ENOMEM;
+               ret = -ENOMEM;
                goto out1;
        }
 
@@ -135,7 +135,7 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
        } while (ret == -EAGAIN);
 
        if (ret)
-                goto out2;
+               goto out2;
 
        soc_dev->attr = soc_dev_attr;
        soc_dev->dev.bus = &soc_bus_type;
index 2b944038453681ef15ba61f41e1cfa3a9e885fbe..f749df9e15cd427054d572c6f6e283630ca2bcc6 100644 (file)
@@ -405,8 +405,8 @@ static int cpqarray_register_ctlr(int i, struct pci_dev *pdev)
                goto Enomem4;
        }
        hba[i]->access.set_intr_mask(hba[i], 0);
-       if (request_irq(hba[i]->intr, do_ida_intr,
-               IRQF_DISABLED|IRQF_SHARED, hba[i]->devname, hba[i]))
+       if (request_irq(hba[i]->intr, do_ida_intr, IRQF_SHARED,
+                       hba[i]->devname, hba[i]))
        {
                printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n",
                                hba[i]->intr, hba[i]->devname);
index 029bc73de001cbb917f6e90a79ee48e117dd0dd5..11f7982cbdb321ba26020b8c8a1495973ebb62e1 100644 (file)
@@ -284,7 +284,7 @@ static int omap_l3_probe(struct platform_device *pdev)
         */
        l3->debug_irq = platform_get_irq(pdev, 0);
        ret = devm_request_irq(l3->dev, l3->debug_irq, l3_interrupt_handler,
-                              IRQF_DISABLED, "l3-dbg-irq", l3);
+                              0x0, "l3-dbg-irq", l3);
        if (ret) {
                dev_err(l3->dev, "request_irq failed for %d\n",
                        l3->debug_irq);
@@ -293,7 +293,7 @@ static int omap_l3_probe(struct platform_device *pdev)
 
        l3->app_irq = platform_get_irq(pdev, 1);
        ret = devm_request_irq(l3->dev, l3->app_irq, l3_interrupt_handler,
-                              IRQF_DISABLED, "l3-app-irq", l3);
+                              0x0, "l3-app-irq", l3);
        if (ret)
                dev_err(l3->dev, "request_irq failed for %d\n", l3->app_irq);
 
index 597fdaee731508c684fc5b83ac38a8963c34c2c6..360a5c0a4ee0f75333668a28973044a0e6b470e6 100644 (file)
@@ -251,18 +251,16 @@ static int omap3_l3_probe(struct platform_device *pdev)
        }
 
        l3->debug_irq = platform_get_irq(pdev, 0);
-       ret = request_irq(l3->debug_irq, omap3_l3_app_irq,
-               IRQF_DISABLED | IRQF_TRIGGER_RISING,
-               "l3-debug-irq", l3);
+       ret = request_irq(l3->debug_irq, omap3_l3_app_irq, IRQF_TRIGGER_RISING,
+                         "l3-debug-irq", l3);
        if (ret) {
                dev_err(&pdev->dev, "couldn't request debug irq\n");
                goto err1;
        }
 
        l3->app_irq = platform_get_irq(pdev, 1);
-       ret = request_irq(l3->app_irq, omap3_l3_app_irq,
-               IRQF_DISABLED | IRQF_TRIGGER_RISING,
-               "l3-app-irq", l3);
+       ret = request_irq(l3->app_irq, omap3_l3_app_irq, IRQF_TRIGGER_RISING,
+                         "l3-app-irq", l3);
        if (ret) {
                dev_err(&pdev->dev, "couldn't request app irq\n");
                goto err2;
index 79524ed2a3cb0d8bb24ebf94af80bd461591f96f..8753b0f6a317790562cc1126805a11eea3a25a5d 100644 (file)
@@ -125,6 +125,7 @@ static int ipmi_powernv_recv(struct ipmi_smi_powernv *smi)
        spin_lock_irqsave(&smi->msg_lock, flags);
 
        if (!smi->cur_msg) {
+               spin_unlock_irqrestore(&smi->msg_lock, flags);
                pr_warn("no current message?\n");
                return 0;
        }
index f6646ed3047e09a3656b089491f0afaa14982af1..518585c1ce94626b1142f83bd0697afef9c05438 100644 (file)
@@ -262,6 +262,11 @@ struct smi_info {
         */
        bool supports_event_msg_buff;
 
+       /*
+        * Can we clear the global enables receive irq bit?
+        */
+       bool cannot_clear_recv_irq_bit;
+
        /*
         * Did we get an attention that we did not handle?
         */
@@ -461,6 +466,9 @@ static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
  * allocate messages, we just leave them in the BMC and run the system
  * polled until we can allocate some memory.  Once we have some
  * memory, we will re-enable the interrupt.
+ *
+ * Note that we cannot just use disable_irq(), since the interrupt may
+ * be shared.
  */
 static inline bool disable_si_irq(struct smi_info *smi_info)
 {
@@ -549,20 +557,15 @@ static u8 current_global_enables(struct smi_info *smi_info, u8 base,
 
        if (smi_info->supports_event_msg_buff)
                enables |= IPMI_BMC_EVT_MSG_BUFF;
-       else
-               enables &= ~IPMI_BMC_EVT_MSG_BUFF;
 
-       if (smi_info->irq && !smi_info->interrupt_disabled)
+       if ((smi_info->irq && !smi_info->interrupt_disabled) ||
+           smi_info->cannot_clear_recv_irq_bit)
                enables |= IPMI_BMC_RCV_MSG_INTR;
-       else
-               enables &= ~IPMI_BMC_RCV_MSG_INTR;
 
        if (smi_info->supports_event_msg_buff &&
            smi_info->irq && !smi_info->interrupt_disabled)
 
                enables |= IPMI_BMC_EVT_MSG_INTR;
-       else
-               enables &= ~IPMI_BMC_EVT_MSG_INTR;
 
        *irq_on = enables & (IPMI_BMC_EVT_MSG_INTR | IPMI_BMC_RCV_MSG_INTR);
 
@@ -2900,6 +2903,96 @@ static int try_get_dev_id(struct smi_info *smi_info)
        return rv;
 }
 
+/*
+ * Some BMCs do not support clearing the receive irq bit in the global
+ * enables (even if they don't support interrupts on the BMC).  Check
+ * for this and handle it properly.
+ */
+static void check_clr_rcv_irq(struct smi_info *smi_info)
+{
+       unsigned char         msg[3];
+       unsigned char         *resp;
+       unsigned long         resp_len;
+       int                   rv;
+
+       resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
+       if (!resp) {
+               printk(KERN_WARNING PFX "Out of memory allocating response for"
+                      " global enables command, cannot check recv irq bit"
+                      " handling.\n");
+               return;
+       }
+
+       msg[0] = IPMI_NETFN_APP_REQUEST << 2;
+       msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
+       smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
+
+       rv = wait_for_msg_done(smi_info);
+       if (rv) {
+               printk(KERN_WARNING PFX "Error getting response from get"
+                      " global enables command, cannot check recv irq bit"
+                      " handling.\n");
+               goto out;
+       }
+
+       resp_len = smi_info->handlers->get_result(smi_info->si_sm,
+                                                 resp, IPMI_MAX_MSG_LENGTH);
+
+       if (resp_len < 4 ||
+                       resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
+                       resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD   ||
+                       resp[2] != 0) {
+               printk(KERN_WARNING PFX "Invalid return from get global"
+                      " enables command, cannot check recv irq bit"
+                      " handling.\n");
+               rv = -EINVAL;
+               goto out;
+       }
+
+       if ((resp[3] & IPMI_BMC_RCV_MSG_INTR) == 0)
+               /* Already clear, should work ok. */
+               goto out;
+
+       msg[0] = IPMI_NETFN_APP_REQUEST << 2;
+       msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
+       msg[2] = resp[3] & ~IPMI_BMC_RCV_MSG_INTR;
+       smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
+
+       rv = wait_for_msg_done(smi_info);
+       if (rv) {
+               printk(KERN_WARNING PFX "Error getting response from set"
+                      " global enables command, cannot check recv irq bit"
+                      " handling.\n");
+               goto out;
+       }
+
+       resp_len = smi_info->handlers->get_result(smi_info->si_sm,
+                                                 resp, IPMI_MAX_MSG_LENGTH);
+
+       if (resp_len < 3 ||
+                       resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
+                       resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) {
+               printk(KERN_WARNING PFX "Invalid return from get global"
+                      " enables command, cannot check recv irq bit"
+                      " handling.\n");
+               rv = -EINVAL;
+               goto out;
+       }
+
+       if (resp[2] != 0) {
+               /*
+                * An error when setting the event buffer bit means
+                * clearing the bit is not supported.
+                */
+               printk(KERN_WARNING PFX "The BMC does not support clearing"
+                      " the recv irq bit, compensating, but the BMC needs to"
+                      " be fixed.\n");
+               smi_info->cannot_clear_recv_irq_bit = true;
+       }
+ out:
+       kfree(resp);
+}
+
 static int try_enable_event_buffer(struct smi_info *smi_info)
 {
        unsigned char         msg[3];
@@ -3395,6 +3488,8 @@ static int try_smi_init(struct smi_info *new_smi)
                goto out_err;
        }
 
+       check_clr_rcv_irq(new_smi);
+
        setup_oem_data_handler(new_smi);
        setup_xaction_handlers(new_smi);
 
index f6e378dac5f5b1031530839d5967ab96607f1f7b..f40e3bd2c69c265400f1241900be8dddd26b51e8 100644 (file)
@@ -468,11 +468,13 @@ static int ipmi_ssif_thread(void *data)
                int result;
 
                /* Wait for something to do */
-               wait_for_completion(&ssif_info->wake_thread);
-               init_completion(&ssif_info->wake_thread);
-
+               result = wait_for_completion_interruptible(
+                                               &ssif_info->wake_thread);
                if (ssif_info->stopping)
                        break;
+               if (result == -ERESTARTSYS)
+                       continue;
+               init_completion(&ssif_info->wake_thread);
 
                if (ssif_info->i2c_read_write == I2C_SMBUS_WRITE) {
                        result = i2c_smbus_write_block_data(
index 297110c12635d3b8c36b53a7f089aa2666024eca..9c4fd7a8e2e5c466e6df5144082a22b868214d9f 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/pfn.h>
 #include <linux/export.h>
 #include <linux/io.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 #include <linux/uaccess.h>
 
index 02e76ac6d282d5a26a31598b05b4d89a6fefd671..69f6b4acc377143d87a54d5e46dd9710f4d53f73 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/types.h>       /* size_t */
 #include <linux/proc_fs.h>
 #include <linux/fcntl.h>       /* O_ACCMODE */
-#include <linux/aio.h>
 #include <linux/pagemap.h>
 #include <linux/hugetlb.h>
 #include <linux/uaccess.h>
index a3025e7ae35f1741883d610310b915040d633101..266469691e5820151ad3f70d1479863e5d820f9b 100644 (file)
@@ -661,17 +661,17 @@ static const struct of_device_id arch_timer_mem_of_match[] __initconst = {
 };
 
 static bool __init
-arch_timer_probed(int type, const struct of_device_id *matches)
+arch_timer_needs_probing(int type, const struct of_device_id *matches)
 {
        struct device_node *dn;
-       bool probed = true;
+       bool needs_probing = false;
 
        dn = of_find_matching_node(NULL, matches);
        if (dn && of_device_is_available(dn) && !(arch_timers_present & type))
-               probed = false;
+               needs_probing = true;
        of_node_put(dn);
 
-       return probed;
+       return needs_probing;
 }
 
 static void __init arch_timer_common_init(void)
@@ -680,9 +680,9 @@ static void __init arch_timer_common_init(void)
 
        /* Wait until both nodes are probed if we have two timers */
        if ((arch_timers_present & mask) != mask) {
-               if (!arch_timer_probed(ARCH_MEM_TIMER, arch_timer_mem_of_match))
+               if (arch_timer_needs_probing(ARCH_MEM_TIMER, arch_timer_mem_of_match))
                        return;
-               if (!arch_timer_probed(ARCH_CP15_TIMER, arch_timer_of_match))
+               if (arch_timer_needs_probing(ARCH_CP15_TIMER, arch_timer_of_match))
                        return;
        }
 
index d305fb089767c1b1c51d05f33c1e84e064f728a7..a19a3f619cc755d3a9a04dbdcde24b230cb30d6d 100644 (file)
@@ -108,7 +108,7 @@ static void __init add_clocksource(struct device_node *source_timer)
 
 static u64 notrace read_sched_clock(void)
 {
-       return ~__raw_readl(sched_io_base);
+       return ~readl_relaxed(sched_io_base);
 }
 
 static const struct of_device_id sptimer_ids[] __initconst = {
index d0a7bd66b8b91e0eb9aa4f7092ec42869a9067d8..dc3c6ee04aaa009e117fcb43fb065394ddfd6fae 100644 (file)
@@ -210,7 +210,7 @@ static int em_sti_clocksource_enable(struct clocksource *cs)
 
        ret = em_sti_start(p, USER_CLOCKSOURCE);
        if (!ret)
-               __clocksource_updatefreq_hz(cs, p->rate);
+               __clocksource_update_freq_hz(cs, p->rate);
        return ret;
 }
 
index 2bd13b53b727635500051746e27299c89d8d9b60..b8ff3c64cc452a16fc4108426fb6e5b1c54e91e8 100644 (file)
@@ -641,7 +641,7 @@ static int sh_cmt_clocksource_enable(struct clocksource *cs)
 
        ret = sh_cmt_start(ch, FLAG_CLOCKSOURCE);
        if (!ret) {
-               __clocksource_updatefreq_hz(cs, ch->rate);
+               __clocksource_update_freq_hz(cs, ch->rate);
                ch->cs_enabled = true;
        }
        return ret;
index f150ca82bfaf106a7ef2c5a40dd12a1e098e39f0..b6b8fa3cd211fc6b03460f678168d0f6568362f0 100644 (file)
@@ -272,7 +272,7 @@ static int sh_tmu_clocksource_enable(struct clocksource *cs)
 
        ret = sh_tmu_enable(ch);
        if (!ret) {
-               __clocksource_updatefreq_hz(cs, ch->rate);
+               __clocksource_update_freq_hz(cs, ch->rate);
                ch->cs_enabled = true;
        }
 
index f4a9c0058b4d677382863a12bf887b40202f63fe..1928a8912584b98e835251442e4313016e112aa2 100644 (file)
@@ -170,7 +170,15 @@ static void __init sun4i_timer_init(struct device_node *node)
               TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M),
               timer_base + TIMER_CTL_REG(1));
 
-       sched_clock_register(sun4i_timer_sched_read, 32, rate);
+       /*
+        * sched_clock_register does not have priorities, and on sun6i and
+        * later there is a better sched_clock registered by arm_arch_timer.c
+        */
+       if (of_machine_is_compatible("allwinner,sun4i-a10") ||
+           of_machine_is_compatible("allwinner,sun5i-a13") ||
+           of_machine_is_compatible("allwinner,sun5i-a10s"))
+               sched_clock_register(sun4i_timer_sched_read, 32, rate);
+
        clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name,
                              rate, 350, 32, clocksource_mmio_readl_down);
 
index d2616ef167701526a13efe7ef896f3cca2c8668a..5a112d72fc2d2ec43205f5cde5720431bdc89b54 100644 (file)
 static void __iomem *timer_reg_base;
 static void __iomem *rtc_base;
 
-static struct timespec persistent_ts;
+static struct timespec64 persistent_ts;
 static u64 persistent_ms, last_persistent_ms;
 
 static struct delay_timer tegra_delay_timer;
 
 #define timer_writel(value, reg) \
-       __raw_writel(value, timer_reg_base + (reg))
+       writel_relaxed(value, timer_reg_base + (reg))
 #define timer_readl(reg) \
-       __raw_readl(timer_reg_base + (reg))
+       readl_relaxed(timer_reg_base + (reg))
 
 static int tegra_timer_set_next_event(unsigned long cycles,
                                         struct clock_event_device *evt)
@@ -120,26 +120,25 @@ static u64 tegra_rtc_read_ms(void)
 }
 
 /*
- * tegra_read_persistent_clock -  Return time from a persistent clock.
+ * tegra_read_persistent_clock64 -  Return time from a persistent clock.
  *
  * Reads the time from a source which isn't disabled during PM, the
  * 32k sync timer.  Convert the cycles elapsed since last read into
- * nsecs and adds to a monotonically increasing timespec.
+ * nsecs and adds to a monotonically increasing timespec64.
  * Care must be taken that this funciton is not called while the
  * tegra_rtc driver could be executing to avoid race conditions
  * on the RTC shadow register
  */
-static void tegra_read_persistent_clock(struct timespec *ts)
+static void tegra_read_persistent_clock64(struct timespec64 *ts)
 {
        u64 delta;
-       struct timespec *tsp = &persistent_ts;
 
        last_persistent_ms = persistent_ms;
        persistent_ms = tegra_rtc_read_ms();
        delta = persistent_ms - last_persistent_ms;
 
-       timespec_add_ns(tsp, delta * NSEC_PER_MSEC);
-       *ts = *tsp;
+       timespec64_add_ns(&persistent_ts, delta * NSEC_PER_MSEC);
+       *ts = persistent_ts;
 }
 
 static unsigned long tegra_delay_timer_read_counter_long(void)
@@ -252,7 +251,7 @@ static void __init tegra20_init_rtc(struct device_node *np)
        else
                clk_prepare_enable(clk);
 
-       register_persistent_clock(NULL, tegra_read_persistent_clock);
+       register_persistent_clock(NULL, tegra_read_persistent_clock64);
 }
 CLOCKSOURCE_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc);
 
index ec57ba2bbd87ac9f2a251e350598fa52019d7815..5b6e3d5644c9519f12468369f6a25c9ab4946ff4 100644 (file)
@@ -111,7 +111,7 @@ static irqreturn_t efm32_clock_event_handler(int irq, void *dev_id)
 static struct efm32_clock_event_ddata clock_event_ddata = {
        .evtdev = {
                .name = "efm32 clockevent",
-               .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_MODE_PERIODIC,
+               .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
                .set_mode = efm32_clock_event_set_mode,
                .set_next_event = efm32_clock_event_set_next_event,
                .rating = 200,
index b5b4d4585c9aba41bc396e91cc107b710b154664..c0304ff608b064b3785af81532fc2b8c7f7f2b30 100644 (file)
@@ -61,12 +61,12 @@ static inline struct pit_data *clkevt_to_pit_data(struct clock_event_device *clk
 
 static inline unsigned int pit_read(void __iomem *base, unsigned int reg_offset)
 {
-       return __raw_readl(base + reg_offset);
+       return readl_relaxed(base + reg_offset);
 }
 
 static inline void pit_write(void __iomem *base, unsigned int reg_offset, unsigned long value)
 {
-       __raw_writel(value, base + reg_offset);
+       writel_relaxed(value, base + reg_offset);
 }
 
 /*
index 58597fbcc046f27f88238aa949730d6109a704b7..28aa4b7bb6020c416974ec52c8f80eb12366e705 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/irq.h>
 #include <linux/irqreturn.h>
 #include <linux/reset.h>
+#include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
 #define TIMER_SYNC_TICKS       3
 
-static void __iomem *timer_base;
-static u32 ticks_per_jiffy;
+struct sun5i_timer {
+       void __iomem            *base;
+       struct clk              *clk;
+       struct notifier_block   clk_rate_cb;
+       u32                     ticks_per_jiffy;
+};
+
+#define to_sun5i_timer(x) \
+       container_of(x, struct sun5i_timer, clk_rate_cb)
+
+struct sun5i_timer_clksrc {
+       struct sun5i_timer      timer;
+       struct clocksource      clksrc;
+};
+
+#define to_sun5i_timer_clksrc(x) \
+       container_of(x, struct sun5i_timer_clksrc, clksrc)
+
+struct sun5i_timer_clkevt {
+       struct sun5i_timer              timer;
+       struct clock_event_device       clkevt;
+};
+
+#define to_sun5i_timer_clkevt(x) \
+       container_of(x, struct sun5i_timer_clkevt, clkevt)
 
 /*
  * When we disable a timer, we need to wait at least for 2 cycles of
@@ -45,30 +69,30 @@ static u32 ticks_per_jiffy;
  * that is already setup and runs at the same frequency than the other
  * timers, and we never will be disabled.
  */
-static void sun5i_clkevt_sync(void)
+static void sun5i_clkevt_sync(struct sun5i_timer_clkevt *ce)
 {
-       u32 old = readl(timer_base + TIMER_CNTVAL_LO_REG(1));
+       u32 old = readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1));
 
-       while ((old - readl(timer_base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS)
+       while ((old - readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS)
                cpu_relax();
 }
 
-static void sun5i_clkevt_time_stop(u8 timer)
+static void sun5i_clkevt_time_stop(struct sun5i_timer_clkevt *ce, u8 timer)
 {
-       u32 val = readl(timer_base + TIMER_CTL_REG(timer));
-       writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer));
+       u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer));
+       writel(val & ~TIMER_CTL_ENABLE, ce->timer.base + TIMER_CTL_REG(timer));
 
-       sun5i_clkevt_sync();
+       sun5i_clkevt_sync(ce);
 }
 
-static void sun5i_clkevt_time_setup(u8 timer, u32 delay)
+static void sun5i_clkevt_time_setup(struct sun5i_timer_clkevt *ce, u8 timer, u32 delay)
 {
-       writel(delay, timer_base + TIMER_INTVAL_LO_REG(timer));
+       writel(delay, ce->timer.base + TIMER_INTVAL_LO_REG(timer));
 }
 
-static void sun5i_clkevt_time_start(u8 timer, bool periodic)
+static void sun5i_clkevt_time_start(struct sun5i_timer_clkevt *ce, u8 timer, bool periodic)
 {
-       u32 val = readl(timer_base + TIMER_CTL_REG(timer));
+       u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer));
 
        if (periodic)
                val &= ~TIMER_CTL_ONESHOT;
@@ -76,75 +100,230 @@ static void sun5i_clkevt_time_start(u8 timer, bool periodic)
                val |= TIMER_CTL_ONESHOT;
 
        writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
-              timer_base + TIMER_CTL_REG(timer));
+              ce->timer.base + TIMER_CTL_REG(timer));
 }
 
 static void sun5i_clkevt_mode(enum clock_event_mode mode,
-                             struct clock_event_device *clk)
+                             struct clock_event_device *clkevt)
 {
+       struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
+
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
-               sun5i_clkevt_time_stop(0);
-               sun5i_clkevt_time_setup(0, ticks_per_jiffy);
-               sun5i_clkevt_time_start(0, true);
+               sun5i_clkevt_time_stop(ce, 0);
+               sun5i_clkevt_time_setup(ce, 0, ce->timer.ticks_per_jiffy);
+               sun5i_clkevt_time_start(ce, 0, true);
                break;
        case CLOCK_EVT_MODE_ONESHOT:
-               sun5i_clkevt_time_stop(0);
-               sun5i_clkevt_time_start(0, false);
+               sun5i_clkevt_time_stop(ce, 0);
+               sun5i_clkevt_time_start(ce, 0, false);
                break;
        case CLOCK_EVT_MODE_UNUSED:
        case CLOCK_EVT_MODE_SHUTDOWN:
        default:
-               sun5i_clkevt_time_stop(0);
+               sun5i_clkevt_time_stop(ce, 0);
                break;
        }
 }
 
 static int sun5i_clkevt_next_event(unsigned long evt,
-                                  struct clock_event_device *unused)
+                                  struct clock_event_device *clkevt)
 {
-       sun5i_clkevt_time_stop(0);
-       sun5i_clkevt_time_setup(0, evt - TIMER_SYNC_TICKS);
-       sun5i_clkevt_time_start(0, false);
+       struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
+
+       sun5i_clkevt_time_stop(ce, 0);
+       sun5i_clkevt_time_setup(ce, 0, evt - TIMER_SYNC_TICKS);
+       sun5i_clkevt_time_start(ce, 0, false);
 
        return 0;
 }
 
-static struct clock_event_device sun5i_clockevent = {
-       .name = "sun5i_tick",
-       .rating = 340,
-       .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .set_mode = sun5i_clkevt_mode,
-       .set_next_event = sun5i_clkevt_next_event,
-};
-
-
 static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id)
 {
-       struct clock_event_device *evt = (struct clock_event_device *)dev_id;
+       struct sun5i_timer_clkevt *ce = (struct sun5i_timer_clkevt *)dev_id;
 
-       writel(0x1, timer_base + TIMER_IRQ_ST_REG);
-       evt->event_handler(evt);
+       writel(0x1, ce->timer.base + TIMER_IRQ_ST_REG);
+       ce->clkevt.event_handler(&ce->clkevt);
 
        return IRQ_HANDLED;
 }
 
-static struct irqaction sun5i_timer_irq = {
-       .name = "sun5i_timer0",
-       .flags = IRQF_TIMER | IRQF_IRQPOLL,
-       .handler = sun5i_timer_interrupt,
-       .dev_id = &sun5i_clockevent,
-};
+static cycle_t sun5i_clksrc_read(struct clocksource *clksrc)
+{
+       struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc);
+
+       return ~readl(cs->timer.base + TIMER_CNTVAL_LO_REG(1));
+}
+
+static int sun5i_rate_cb_clksrc(struct notifier_block *nb,
+                               unsigned long event, void *data)
+{
+       struct clk_notifier_data *ndata = data;
+       struct sun5i_timer *timer = to_sun5i_timer(nb);
+       struct sun5i_timer_clksrc *cs = container_of(timer, struct sun5i_timer_clksrc, timer);
+
+       switch (event) {
+       case PRE_RATE_CHANGE:
+               clocksource_unregister(&cs->clksrc);
+               break;
+
+       case POST_RATE_CHANGE:
+               clocksource_register_hz(&cs->clksrc, ndata->new_rate);
+               break;
+
+       default:
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static int __init sun5i_setup_clocksource(struct device_node *node,
+                                         void __iomem *base,
+                                         struct clk *clk, int irq)
+{
+       struct sun5i_timer_clksrc *cs;
+       unsigned long rate;
+       int ret;
+
+       cs = kzalloc(sizeof(*cs), GFP_KERNEL);
+       if (!cs)
+               return -ENOMEM;
+
+       ret = clk_prepare_enable(clk);
+       if (ret) {
+               pr_err("Couldn't enable parent clock\n");
+               goto err_free;
+       }
+
+       rate = clk_get_rate(clk);
+
+       cs->timer.base = base;
+       cs->timer.clk = clk;
+       cs->timer.clk_rate_cb.notifier_call = sun5i_rate_cb_clksrc;
+       cs->timer.clk_rate_cb.next = NULL;
+
+       ret = clk_notifier_register(clk, &cs->timer.clk_rate_cb);
+       if (ret) {
+               pr_err("Unable to register clock notifier.\n");
+               goto err_disable_clk;
+       }
+
+       writel(~0, base + TIMER_INTVAL_LO_REG(1));
+       writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
+              base + TIMER_CTL_REG(1));
+
+       cs->clksrc.name = node->name;
+       cs->clksrc.rating = 340;
+       cs->clksrc.read = sun5i_clksrc_read;
+       cs->clksrc.mask = CLOCKSOURCE_MASK(32);
+       cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+       ret = clocksource_register_hz(&cs->clksrc, rate);
+       if (ret) {
+               pr_err("Couldn't register clock source.\n");
+               goto err_remove_notifier;
+       }
+
+       return 0;
+
+err_remove_notifier:
+       clk_notifier_unregister(clk, &cs->timer.clk_rate_cb);
+err_disable_clk:
+       clk_disable_unprepare(clk);
+err_free:
+       kfree(cs);
+       return ret;
+}
+
+static int sun5i_rate_cb_clkevt(struct notifier_block *nb,
+                               unsigned long event, void *data)
+{
+       struct clk_notifier_data *ndata = data;
+       struct sun5i_timer *timer = to_sun5i_timer(nb);
+       struct sun5i_timer_clkevt *ce = container_of(timer, struct sun5i_timer_clkevt, timer);
+
+       if (event == POST_RATE_CHANGE) {
+               clockevents_update_freq(&ce->clkevt, ndata->new_rate);
+               ce->timer.ticks_per_jiffy = DIV_ROUND_UP(ndata->new_rate, HZ);
+       }
+
+       return NOTIFY_DONE;
+}
+
+static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem *base,
+                                        struct clk *clk, int irq)
+{
+       struct sun5i_timer_clkevt *ce;
+       unsigned long rate;
+       int ret;
+       u32 val;
+
+       ce = kzalloc(sizeof(*ce), GFP_KERNEL);
+       if (!ce)
+               return -ENOMEM;
+
+       ret = clk_prepare_enable(clk);
+       if (ret) {
+               pr_err("Couldn't enable parent clock\n");
+               goto err_free;
+       }
+
+       rate = clk_get_rate(clk);
+
+       ce->timer.base = base;
+       ce->timer.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
+       ce->timer.clk = clk;
+       ce->timer.clk_rate_cb.notifier_call = sun5i_rate_cb_clkevt;
+       ce->timer.clk_rate_cb.next = NULL;
+
+       ret = clk_notifier_register(clk, &ce->timer.clk_rate_cb);
+       if (ret) {
+               pr_err("Unable to register clock notifier.\n");
+               goto err_disable_clk;
+       }
+
+       ce->clkevt.name = node->name;
+       ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+       ce->clkevt.set_next_event = sun5i_clkevt_next_event;
+       ce->clkevt.set_mode = sun5i_clkevt_mode;
+       ce->clkevt.rating = 340;
+       ce->clkevt.irq = irq;
+       ce->clkevt.cpumask = cpu_possible_mask;
+
+       /* Enable timer0 interrupt */
+       val = readl(base + TIMER_IRQ_EN_REG);
+       writel(val | TIMER_IRQ_EN(0), base + TIMER_IRQ_EN_REG);
+
+       clockevents_config_and_register(&ce->clkevt, rate,
+                                       TIMER_SYNC_TICKS, 0xffffffff);
+
+       ret = request_irq(irq, sun5i_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
+                         "sun5i_timer0", ce);
+       if (ret) {
+               pr_err("Unable to register interrupt\n");
+               goto err_remove_notifier;
+       }
+
+       return 0;
+
+err_remove_notifier:
+       clk_notifier_unregister(clk, &ce->timer.clk_rate_cb);
+err_disable_clk:
+       clk_disable_unprepare(clk);
+err_free:
+       kfree(ce);
+       return ret;
+}
 
 static void __init sun5i_timer_init(struct device_node *node)
 {
        struct reset_control *rstc;
-       unsigned long rate;
+       void __iomem *timer_base;
        struct clk *clk;
-       int ret, irq;
-       u32 val;
+       int irq;
 
-       timer_base = of_iomap(node, 0);
+       timer_base = of_io_request_and_map(node, 0, of_node_full_name(node));
        if (!timer_base)
                panic("Can't map registers");
 
@@ -155,35 +334,13 @@ static void __init sun5i_timer_init(struct device_node *node)
        clk = of_clk_get(node, 0);
        if (IS_ERR(clk))
                panic("Can't get timer clock");
-       clk_prepare_enable(clk);
-       rate = clk_get_rate(clk);
 
        rstc = of_reset_control_get(node, NULL);
        if (!IS_ERR(rstc))
                reset_control_deassert(rstc);
 
-       writel(~0, timer_base + TIMER_INTVAL_LO_REG(1));
-       writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
-              timer_base + TIMER_CTL_REG(1));
-
-       clocksource_mmio_init(timer_base + TIMER_CNTVAL_LO_REG(1), node->name,
-                             rate, 340, 32, clocksource_mmio_readl_down);
-
-       ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
-
-       /* Enable timer0 interrupt */
-       val = readl(timer_base + TIMER_IRQ_EN_REG);
-       writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG);
-
-       sun5i_clockevent.cpumask = cpu_possible_mask;
-       sun5i_clockevent.irq = irq;
-
-       clockevents_config_and_register(&sun5i_clockevent, rate,
-                                       TIMER_SYNC_TICKS, 0xffffffff);
-
-       ret = setup_irq(irq, &sun5i_timer_irq);
-       if (ret)
-               pr_warn("failed to setup irq %d\n", irq);
+       sun5i_setup_clocksource(node, timer_base, clk, irq);
+       sun5i_setup_clockevent(node, timer_base, clk, irq);
 }
 CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
                       sun5i_timer_init);
index 28e59a48b35fdb993b28f621bdb0b065c0057e73..8ae655c364f48aeeeec7e4717aab6e6bfe2d9f95 100644 (file)
@@ -1698,15 +1698,18 @@ void cpufreq_resume(void)
                    || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))
                        pr_err("%s: Failed to start governor for policy: %p\n",
                                __func__, policy);
-
-               /*
-                * schedule call cpufreq_update_policy() for boot CPU, i.e. last
-                * policy in list. It will verify that the current freq is in
-                * sync with what we believe it to be.
-                */
-               if (list_is_last(&policy->policy_list, &cpufreq_policy_list))
-                       schedule_work(&policy->update);
        }
+
+       /*
+        * schedule call cpufreq_update_policy() for first-online CPU, as that
+        * wouldn't be hotplugged-out on suspend. It will verify that the
+        * current freq is in sync with what we believe it to be.
+        */
+       policy = cpufreq_cpu_get_raw(cpumask_first(cpu_online_mask));
+       if (WARN_ON(!policy))
+               return;
+
+       schedule_work(&policy->update);
 }
 
 /**
index 080bd2dbde4ba5408504a451e9454b51497202e3..7a73a279e179a52b9ea209e00b3f61f797c4d4cb 100644 (file)
@@ -330,9 +330,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
        if (!dev->registered)
                return -EINVAL;
 
-       if (!dev->state_count)
-               dev->state_count = drv->state_count;
-
        ret = cpuidle_add_device_sysfs(dev);
        if (ret)
                return ret;
index 2697e87d5b34ff9ae520f1130220afb4d0876dff..5db147859b9047db626d66e64bef2897a41822f2 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/sched.h>
 #include <linux/cpuidle.h>
 #include <linux/cpumask.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 
 #include "cpuidle.h"
 
@@ -130,21 +130,20 @@ static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv)
 #endif
 
 /**
- * cpuidle_setup_broadcast_timer - enable/disable the broadcast timer
+ * cpuidle_setup_broadcast_timer - enable/disable the broadcast timer on a cpu
  * @arg: a void pointer used to match the SMP cross call API
  *
- * @arg is used as a value of type 'long' with one of the two values:
- * - CLOCK_EVT_NOTIFY_BROADCAST_ON
- * - CLOCK_EVT_NOTIFY_BROADCAST_OFF
+ * If @arg is NULL broadcast is disabled otherwise enabled
  *
- * Set the broadcast timer notification for the current CPU.  This function
- * is executed per CPU by an SMP cross call.  It not supposed to be called
- * directly.
+ * This function is executed per CPU by an SMP cross call.  It's not
+ * supposed to be called directly.
  */
 static void cpuidle_setup_broadcast_timer(void *arg)
 {
-       int cpu = smp_processor_id();
-       clockevents_notify((long)(arg), &cpu);
+       if (arg)
+               tick_broadcast_enable();
+       else
+               tick_broadcast_disable();
 }
 
 /**
@@ -239,7 +238,7 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv)
 
        if (drv->bctimer)
                on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,
-                                (void *)CLOCK_EVT_NOTIFY_BROADCAST_ON, 1);
+                                (void *)1, 1);
 
        poll_idle_init(drv);
 
@@ -263,7 +262,7 @@ static void __cpuidle_unregister_driver(struct cpuidle_driver *drv)
        if (drv->bctimer) {
                drv->bctimer = 0;
                on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,
-                                (void *)CLOCK_EVT_NOTIFY_BROADCAST_OFF, 1);
+                                NULL, 1);
        }
 
        __cpuidle_unset_driver(drv);
index 97c5903b4606cf0fa02aecec826cbed605796234..832a2c3f01ffccf691842507955078299799eb86 100644 (file)
@@ -401,7 +401,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
        struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
 
        /* state statistics */
-       for (i = 0; i < device->state_count; i++) {
+       for (i = 0; i < drv->state_count; i++) {
                kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
                if (!kobj)
                        goto error_state;
@@ -433,9 +433,10 @@ error_state:
  */
 static void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
 {
+       struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
        int i;
 
-       for (i = 0; i < device->state_count; i++)
+       for (i = 0; i < drv->state_count; i++)
                cpuidle_free_state_kobj(device, i);
 }
 
index a874b6ec6650f33275c8a59ddb1d00a78c4271e9..942ca541dcbdc293e7a3dc11ef494584503f4a4e 100644 (file)
@@ -51,19 +51,6 @@ config INTEL_MIC_X100_DMA
          OS and tools for MIC to use with this driver are available from
          <http://software.intel.com/en-us/mic-developer>.
 
-config INTEL_MID_DMAC
-       tristate "Intel MID DMA support for Peripheral DMA controllers"
-       depends on PCI && X86
-       select DMA_ENGINE
-       default n
-       help
-         Enable support for the Intel(R) MID DMA engine present
-         in Intel MID chipsets.
-
-         Say Y here if you have such a chipset.
-
-         If unsure, say N.
-
 config ASYNC_TX_ENABLE_CHANNEL_SWITCH
        bool
 
index f915f61ec5747193757e6f2b6da61ebd0eea4d83..539d4825bd766ed956629e0b1d0aa4e9b91acf25 100644 (file)
@@ -6,7 +6,6 @@ obj-$(CONFIG_DMA_VIRTUAL_CHANNELS) += virt-dma.o
 obj-$(CONFIG_DMA_ACPI) += acpi-dma.o
 obj-$(CONFIG_DMA_OF) += of-dma.o
 
-obj-$(CONFIG_INTEL_MID_DMAC) += intel_mid_dma.o
 obj-$(CONFIG_DMATEST) += dmatest.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioat/
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
index 512cb8e2805e797ef12760d2e445652186410137..ceedafbd23e01fcda6968fb04707ae141cff3a88 100644 (file)
@@ -903,6 +903,11 @@ static const struct cppi_glue_infos *get_glue_info(struct device *dev)
        return of_id->data;
 }
 
+#define CPPI41_DMA_BUSWIDTHS   (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
+                               BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+                               BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
+                               BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
+
 static int cppi41_dma_probe(struct platform_device *pdev)
 {
        struct cppi41_dd *cdd;
@@ -926,6 +931,10 @@ static int cppi41_dma_probe(struct platform_device *pdev)
        cdd->ddev.device_issue_pending = cppi41_dma_issue_pending;
        cdd->ddev.device_prep_slave_sg = cppi41_dma_prep_slave_sg;
        cdd->ddev.device_terminate_all = cppi41_stop_chan;
+       cdd->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+       cdd->ddev.src_addr_widths = CPPI41_DMA_BUSWIDTHS;
+       cdd->ddev.dst_addr_widths = CPPI41_DMA_BUSWIDTHS;
+       cdd->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
        cdd->ddev.dev = dev;
        INIT_LIST_HEAD(&cdd->ddev.channels);
        cpp41_dma_info.dma_cap = cdd->ddev.cap_mask;
index f15712f2fec6c06949c23f845eeb8bbb776b8907..ac336a961dea97be01894027b9f4bd16d5566bad 100644 (file)
@@ -859,9 +859,6 @@ int dma_async_device_register(struct dma_device *device)
        BUG_ON(!device->device_issue_pending);
        BUG_ON(!device->dev);
 
-       WARN(dma_has_cap(DMA_SLAVE, device->cap_mask) && !device->directions,
-            "this driver doesn't support generic slave capabilities reporting\n");
-
        /* note: this only matters in the
         * CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=n case
         */
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
deleted file mode 100644 (file)
index 5aaead9..0000000
+++ /dev/null
@@ -1,1447 +0,0 @@
-/*
- *  intel_mid_dma.c - Intel Langwell DMA Drivers
- *
- *  Copyright (C) 2008-10 Intel Corp
- *  Author: Vinod Koul <vinod.koul@intel.com>
- *  The driver design is based on dw_dmac driver
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *
- */
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/pm_runtime.h>
-#include <linux/intel_mid_dma.h>
-#include <linux/module.h>
-
-#include "dmaengine.h"
-
-#define MAX_CHAN       4 /*max ch across controllers*/
-#include "intel_mid_dma_regs.h"
-
-#define INTEL_MID_DMAC1_ID             0x0814
-#define INTEL_MID_DMAC2_ID             0x0813
-#define INTEL_MID_GP_DMAC2_ID          0x0827
-#define INTEL_MFLD_DMAC1_ID            0x0830
-#define LNW_PERIPHRAL_MASK_BASE                0xFFAE8008
-#define LNW_PERIPHRAL_MASK_SIZE                0x10
-#define LNW_PERIPHRAL_STATUS           0x0
-#define LNW_PERIPHRAL_MASK             0x8
-
-struct intel_mid_dma_probe_info {
-       u8 max_chan;
-       u8 ch_base;
-       u16 block_size;
-       u32 pimr_mask;
-};
-
-#define INFO(_max_chan, _ch_base, _block_size, _pimr_mask) \
-       ((kernel_ulong_t)&(struct intel_mid_dma_probe_info) {   \
-               .max_chan = (_max_chan),                        \
-               .ch_base = (_ch_base),                          \
-               .block_size = (_block_size),                    \
-               .pimr_mask = (_pimr_mask),                      \
-       })
-
-/*****************************************************************************
-Utility Functions*/
-/**
- * get_ch_index        -       convert status to channel
- * @status: status mask
- * @base: dma ch base value
- *
- * Modify the status mask and return the channel index needing
- * attention (or -1 if neither)
- */
-static int get_ch_index(int *status, unsigned int base)
-{
-       int i;
-       for (i = 0; i < MAX_CHAN; i++) {
-               if (*status & (1 << (i + base))) {
-                       *status = *status & ~(1 << (i + base));
-                       pr_debug("MDMA: index %d New status %x\n", i, *status);
-                       return i;
-               }
-       }
-       return -1;
-}
-
-/**
- * get_block_ts        -       calculates dma transaction length
- * @len: dma transfer length
- * @tx_width: dma transfer src width
- * @block_size: dma controller max block size
- *
- * Based on src width calculate the DMA trsaction length in data items
- * return data items or FFFF if exceeds max length for block
- */
-static int get_block_ts(int len, int tx_width, int block_size)
-{
-       int byte_width = 0, block_ts = 0;
-
-       switch (tx_width) {
-       case DMA_SLAVE_BUSWIDTH_1_BYTE:
-               byte_width = 1;
-               break;
-       case DMA_SLAVE_BUSWIDTH_2_BYTES:
-               byte_width = 2;
-               break;
-       case DMA_SLAVE_BUSWIDTH_4_BYTES:
-       default:
-               byte_width = 4;
-               break;
-       }
-
-       block_ts = len/byte_width;
-       if (block_ts > block_size)
-               block_ts = 0xFFFF;
-       return block_ts;
-}
-
-/*****************************************************************************
-DMAC1 interrupt Functions*/
-
-/**
- * dmac1_mask_periphral_intr - mask the periphral interrupt
- * @mid: dma device for which masking is required
- *
- * Masks the DMA periphral interrupt
- * this is valid for DMAC1 family controllers only
- * This controller should have periphral mask registers already mapped
- */
-static void dmac1_mask_periphral_intr(struct middma_device *mid)
-{
-       u32 pimr;
-
-       if (mid->pimr_mask) {
-               pimr = readl(mid->mask_reg + LNW_PERIPHRAL_MASK);
-               pimr |= mid->pimr_mask;
-               writel(pimr, mid->mask_reg + LNW_PERIPHRAL_MASK);
-       }
-       return;
-}
-
-/**
- * dmac1_unmask_periphral_intr -       unmask the periphral interrupt
- * @midc: dma channel for which masking is required
- *
- * UnMasks the DMA periphral interrupt,
- * this is valid for DMAC1 family controllers only
- * This controller should have periphral mask registers already mapped
- */
-static void dmac1_unmask_periphral_intr(struct intel_mid_dma_chan *midc)
-{
-       u32 pimr;
-       struct middma_device *mid = to_middma_device(midc->chan.device);
-
-       if (mid->pimr_mask) {
-               pimr = readl(mid->mask_reg + LNW_PERIPHRAL_MASK);
-               pimr &= ~mid->pimr_mask;
-               writel(pimr, mid->mask_reg + LNW_PERIPHRAL_MASK);
-       }
-       return;
-}
-
-/**
- * enable_dma_interrupt -      enable the periphral interrupt
- * @midc: dma channel for which enable interrupt is required
- *
- * Enable the DMA periphral interrupt,
- * this is valid for DMAC1 family controllers only
- * This controller should have periphral mask registers already mapped
- */
-static void enable_dma_interrupt(struct intel_mid_dma_chan *midc)
-{
-       dmac1_unmask_periphral_intr(midc);
-
-       /*en ch interrupts*/
-       iowrite32(UNMASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_TFR);
-       iowrite32(UNMASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_ERR);
-       return;
-}
-
-/**
- * disable_dma_interrupt -     disable the periphral interrupt
- * @midc: dma channel for which disable interrupt is required
- *
- * Disable the DMA periphral interrupt,
- * this is valid for DMAC1 family controllers only
- * This controller should have periphral mask registers already mapped
- */
-static void disable_dma_interrupt(struct intel_mid_dma_chan *midc)
-{
-       /*Check LPE PISR, make sure fwd is disabled*/
-       iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_BLOCK);
-       iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_TFR);
-       iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_ERR);
-       return;
-}
-
-/*****************************************************************************
-DMA channel helper Functions*/
-/**
- * mid_desc_get                -       get a descriptor
- * @midc: dma channel for which descriptor is required
- *
- * Obtain a descriptor for the channel. Returns NULL if none are free.
- * Once the descriptor is returned it is private until put on another
- * list or freed
- */
-static struct intel_mid_dma_desc *midc_desc_get(struct intel_mid_dma_chan *midc)
-{
-       struct intel_mid_dma_desc *desc, *_desc;
-       struct intel_mid_dma_desc *ret = NULL;
-
-       spin_lock_bh(&midc->lock);
-       list_for_each_entry_safe(desc, _desc, &midc->free_list, desc_node) {
-               if (async_tx_test_ack(&desc->txd)) {
-                       list_del(&desc->desc_node);
-                       ret = desc;
-                       break;
-               }
-       }
-       spin_unlock_bh(&midc->lock);
-       return ret;
-}
-
-/**
- * mid_desc_put                -       put a descriptor
- * @midc: dma channel for which descriptor is required
- * @desc: descriptor to put
- *
- * Return a descriptor from lwn_desc_get back to the free pool
- */
-static void midc_desc_put(struct intel_mid_dma_chan *midc,
-                       struct intel_mid_dma_desc *desc)
-{
-       if (desc) {
-               spin_lock_bh(&midc->lock);
-               list_add_tail(&desc->desc_node, &midc->free_list);
-               spin_unlock_bh(&midc->lock);
-       }
-}
-/**
- * midc_dostart                -               begin a DMA transaction
- * @midc: channel for which txn is to be started
- * @first: first descriptor of series
- *
- * Load a transaction into the engine. This must be called with midc->lock
- * held and bh disabled.
- */
-static void midc_dostart(struct intel_mid_dma_chan *midc,
-                       struct intel_mid_dma_desc *first)
-{
-       struct middma_device *mid = to_middma_device(midc->chan.device);
-
-       /*  channel is idle */
-       if (midc->busy && test_ch_en(midc->dma_base, midc->ch_id)) {
-               /*error*/
-               pr_err("ERR_MDMA: channel is busy in start\n");
-               /* The tasklet will hopefully advance the queue... */
-               return;
-       }
-       midc->busy = true;
-       /*write registers and en*/
-       iowrite32(first->sar, midc->ch_regs + SAR);
-       iowrite32(first->dar, midc->ch_regs + DAR);
-       iowrite32(first->lli_phys, midc->ch_regs + LLP);
-       iowrite32(first->cfg_hi, midc->ch_regs + CFG_HIGH);
-       iowrite32(first->cfg_lo, midc->ch_regs + CFG_LOW);
-       iowrite32(first->ctl_lo, midc->ch_regs + CTL_LOW);
-       iowrite32(first->ctl_hi, midc->ch_regs + CTL_HIGH);
-       pr_debug("MDMA:TX SAR %x,DAR %x,CFGL %x,CFGH %x,CTLH %x, CTLL %x\n",
-               (int)first->sar, (int)first->dar, first->cfg_hi,
-               first->cfg_lo, first->ctl_hi, first->ctl_lo);
-       first->status = DMA_IN_PROGRESS;
-
-       iowrite32(ENABLE_CHANNEL(midc->ch_id), mid->dma_base + DMA_CHAN_EN);
-}
-
-/**
- * midc_descriptor_complete    -       process completed descriptor
- * @midc: channel owning the descriptor
- * @desc: the descriptor itself
- *
- * Process a completed descriptor and perform any callbacks upon
- * the completion. The completion handling drops the lock during the
- * callbacks but must be called with the lock held.
- */
-static void midc_descriptor_complete(struct intel_mid_dma_chan *midc,
-               struct intel_mid_dma_desc *desc)
-               __releases(&midc->lock) __acquires(&midc->lock)
-{
-       struct dma_async_tx_descriptor  *txd = &desc->txd;
-       dma_async_tx_callback callback_txd = NULL;
-       struct intel_mid_dma_lli        *llitem;
-       void *param_txd = NULL;
-
-       dma_cookie_complete(txd);
-       callback_txd = txd->callback;
-       param_txd = txd->callback_param;
-
-       if (desc->lli != NULL) {
-               /*clear the DONE bit of completed LLI in memory*/
-               llitem = desc->lli + desc->current_lli;
-               llitem->ctl_hi &= CLEAR_DONE;
-               if (desc->current_lli < desc->lli_length-1)
-                       (desc->current_lli)++;
-               else
-                       desc->current_lli = 0;
-       }
-       spin_unlock_bh(&midc->lock);
-       if (callback_txd) {
-               pr_debug("MDMA: TXD callback set ... calling\n");
-               callback_txd(param_txd);
-       }
-       if (midc->raw_tfr) {
-               desc->status = DMA_COMPLETE;
-               if (desc->lli != NULL) {
-                       pci_pool_free(desc->lli_pool, desc->lli,
-                                               desc->lli_phys);
-                       pci_pool_destroy(desc->lli_pool);
-                       desc->lli = NULL;
-               }
-               list_move(&desc->desc_node, &midc->free_list);
-               midc->busy = false;
-       }
-       spin_lock_bh(&midc->lock);
-
-}
-/**
- * midc_scan_descriptors -             check the descriptors in channel
- *                                     mark completed when tx is completete
- * @mid: device
- * @midc: channel to scan
- *
- * Walk the descriptor chain for the device and process any entries
- * that are complete.
- */
-static void midc_scan_descriptors(struct middma_device *mid,
-                               struct intel_mid_dma_chan *midc)
-{
-       struct intel_mid_dma_desc *desc = NULL, *_desc = NULL;
-
-       /*tx is complete*/
-       list_for_each_entry_safe(desc, _desc, &midc->active_list, desc_node) {
-               if (desc->status == DMA_IN_PROGRESS)
-                       midc_descriptor_complete(midc, desc);
-       }
-       return;
-       }
-/**
- * midc_lli_fill_sg -          Helper function to convert
- *                             SG list to Linked List Items.
- *@midc: Channel
- *@desc: DMA descriptor
- *@sglist: Pointer to SG list
- *@sglen: SG list length
- *@flags: DMA transaction flags
- *
- * Walk through the SG list and convert the SG list into Linked
- * List Items (LLI).
- */
-static int midc_lli_fill_sg(struct intel_mid_dma_chan *midc,
-                               struct intel_mid_dma_desc *desc,
-                               struct scatterlist *sglist,
-                               unsigned int sglen,
-                               unsigned int flags)
-{
-       struct intel_mid_dma_slave *mids;
-       struct scatterlist  *sg;
-       dma_addr_t lli_next, sg_phy_addr;
-       struct intel_mid_dma_lli *lli_bloc_desc;
-       union intel_mid_dma_ctl_lo ctl_lo;
-       union intel_mid_dma_ctl_hi ctl_hi;
-       int i;
-
-       pr_debug("MDMA: Entered midc_lli_fill_sg\n");
-       mids = midc->mid_slave;
-
-       lli_bloc_desc = desc->lli;
-       lli_next = desc->lli_phys;
-
-       ctl_lo.ctl_lo = desc->ctl_lo;
-       ctl_hi.ctl_hi = desc->ctl_hi;
-       for_each_sg(sglist, sg, sglen, i) {
-               /*Populate CTL_LOW and LLI values*/
-               if (i != sglen - 1) {
-                       lli_next = lli_next +
-                               sizeof(struct intel_mid_dma_lli);
-               } else {
-               /*Check for circular list, otherwise terminate LLI to ZERO*/
-                       if (flags & DMA_PREP_CIRCULAR_LIST) {
-                               pr_debug("MDMA: LLI is configured in circular mode\n");
-                               lli_next = desc->lli_phys;
-                       } else {
-                               lli_next = 0;
-                               ctl_lo.ctlx.llp_dst_en = 0;
-                               ctl_lo.ctlx.llp_src_en = 0;
-                       }
-               }
-               /*Populate CTL_HI values*/
-               ctl_hi.ctlx.block_ts = get_block_ts(sg_dma_len(sg),
-                                                       desc->width,
-                                                       midc->dma->block_size);
-               /*Populate SAR and DAR values*/
-               sg_phy_addr = sg_dma_address(sg);
-               if (desc->dirn ==  DMA_MEM_TO_DEV) {
-                       lli_bloc_desc->sar  = sg_phy_addr;
-                       lli_bloc_desc->dar  = mids->dma_slave.dst_addr;
-               } else if (desc->dirn ==  DMA_DEV_TO_MEM) {
-                       lli_bloc_desc->sar  = mids->dma_slave.src_addr;
-                       lli_bloc_desc->dar  = sg_phy_addr;
-               }
-               /*Copy values into block descriptor in system memroy*/
-               lli_bloc_desc->llp = lli_next;
-               lli_bloc_desc->ctl_lo = ctl_lo.ctl_lo;
-               lli_bloc_desc->ctl_hi = ctl_hi.ctl_hi;
-
-               lli_bloc_desc++;
-       }
-       /*Copy very first LLI values to descriptor*/
-       desc->ctl_lo = desc->lli->ctl_lo;
-       desc->ctl_hi = desc->lli->ctl_hi;
-       desc->sar = desc->lli->sar;
-       desc->dar = desc->lli->dar;
-
-       return 0;
-}
-/*****************************************************************************
-DMA engine callback Functions*/
-/**
- * intel_mid_dma_tx_submit -   callback to submit DMA transaction
- * @tx: dma engine descriptor
- *
- * Submit the DMA transaction for this descriptor, start if ch idle
- */
-static dma_cookie_t intel_mid_dma_tx_submit(struct dma_async_tx_descriptor *tx)
-{
-       struct intel_mid_dma_desc       *desc = to_intel_mid_dma_desc(tx);
-       struct intel_mid_dma_chan       *midc = to_intel_mid_dma_chan(tx->chan);
-       dma_cookie_t            cookie;
-
-       spin_lock_bh(&midc->lock);
-       cookie = dma_cookie_assign(tx);
-
-       if (list_empty(&midc->active_list))
-               list_add_tail(&desc->desc_node, &midc->active_list);
-       else
-               list_add_tail(&desc->desc_node, &midc->queue);
-
-       midc_dostart(midc, desc);
-       spin_unlock_bh(&midc->lock);
-
-       return cookie;
-}
-
-/**
- * intel_mid_dma_issue_pending -       callback to issue pending txn
- * @chan: chan where pending trascation needs to be checked and submitted
- *
- * Call for scan to issue pending descriptors
- */
-static void intel_mid_dma_issue_pending(struct dma_chan *chan)
-{
-       struct intel_mid_dma_chan       *midc = to_intel_mid_dma_chan(chan);
-
-       spin_lock_bh(&midc->lock);
-       if (!list_empty(&midc->queue))
-               midc_scan_descriptors(to_middma_device(chan->device), midc);
-       spin_unlock_bh(&midc->lock);
-}
-
-/**
- * intel_mid_dma_tx_status -   Return status of txn
- * @chan: chan for where status needs to be checked
- * @cookie: cookie for txn
- * @txstate: DMA txn state
- *
- * Return status of DMA txn
- */
-static enum dma_status intel_mid_dma_tx_status(struct dma_chan *chan,
-                                               dma_cookie_t cookie,
-                                               struct dma_tx_state *txstate)
-{
-       struct intel_mid_dma_chan *midc = to_intel_mid_dma_chan(chan);
-       enum dma_status ret;
-
-       ret = dma_cookie_status(chan, cookie, txstate);
-       if (ret != DMA_COMPLETE) {
-               spin_lock_bh(&midc->lock);
-               midc_scan_descriptors(to_middma_device(chan->device), midc);
-               spin_unlock_bh(&midc->lock);
-
-               ret = dma_cookie_status(chan, cookie, txstate);
-       }
-
-       return ret;
-}
-
-static int intel_mid_dma_config(struct dma_chan *chan,
-                               struct dma_slave_config *slave)
-{
-       struct intel_mid_dma_chan       *midc = to_intel_mid_dma_chan(chan);
-       struct intel_mid_dma_slave *mid_slave;
-
-       BUG_ON(!midc);
-       BUG_ON(!slave);
-       pr_debug("MDMA: slave control called\n");
-
-       mid_slave = to_intel_mid_dma_slave(slave);
-
-       BUG_ON(!mid_slave);
-
-       midc->mid_slave = mid_slave;
-       return 0;
-}
-
-static int intel_mid_dma_terminate_all(struct dma_chan *chan)
-{
-       struct intel_mid_dma_chan       *midc = to_intel_mid_dma_chan(chan);
-       struct middma_device    *mid = to_middma_device(chan->device);
-       struct intel_mid_dma_desc       *desc, *_desc;
-       union intel_mid_dma_cfg_lo cfg_lo;
-
-       spin_lock_bh(&midc->lock);
-       if (midc->busy == false) {
-               spin_unlock_bh(&midc->lock);
-               return 0;
-       }
-       /*Suspend and disable the channel*/
-       cfg_lo.cfg_lo = ioread32(midc->ch_regs + CFG_LOW);
-       cfg_lo.cfgx.ch_susp = 1;
-       iowrite32(cfg_lo.cfg_lo, midc->ch_regs + CFG_LOW);
-       iowrite32(DISABLE_CHANNEL(midc->ch_id), mid->dma_base + DMA_CHAN_EN);
-       midc->busy = false;
-       /* Disable interrupts */
-       disable_dma_interrupt(midc);
-       midc->descs_allocated = 0;
-
-       spin_unlock_bh(&midc->lock);
-       list_for_each_entry_safe(desc, _desc, &midc->active_list, desc_node) {
-               if (desc->lli != NULL) {
-                       pci_pool_free(desc->lli_pool, desc->lli,
-                                               desc->lli_phys);
-                       pci_pool_destroy(desc->lli_pool);
-                       desc->lli = NULL;
-               }
-               list_move(&desc->desc_node, &midc->free_list);
-       }
-       return 0;
-}
-
-
-/**
- * intel_mid_dma_prep_memcpy - Prep memcpy txn
- * @chan: chan for DMA transfer
- * @dest: destn address
- * @src: src address
- * @len: DMA transfer len
- * @flags: DMA flags
- *
- * Perform a DMA memcpy. Note we support slave periphral DMA transfers only
- * The periphral txn details should be filled in slave structure properly
- * Returns the descriptor for this txn
- */
-static struct dma_async_tx_descriptor *intel_mid_dma_prep_memcpy(
-                       struct dma_chan *chan, dma_addr_t dest,
-                       dma_addr_t src, size_t len, unsigned long flags)
-{
-       struct intel_mid_dma_chan *midc;
-       struct intel_mid_dma_desc *desc = NULL;
-       struct intel_mid_dma_slave *mids;
-       union intel_mid_dma_ctl_lo ctl_lo;
-       union intel_mid_dma_ctl_hi ctl_hi;
-       union intel_mid_dma_cfg_lo cfg_lo;
-       union intel_mid_dma_cfg_hi cfg_hi;
-       enum dma_slave_buswidth width;
-
-       pr_debug("MDMA: Prep for memcpy\n");
-       BUG_ON(!chan);
-       if (!len)
-               return NULL;
-
-       midc = to_intel_mid_dma_chan(chan);
-       BUG_ON(!midc);
-
-       mids = midc->mid_slave;
-       BUG_ON(!mids);
-
-       pr_debug("MDMA:called for DMA %x CH %d Length %zu\n",
-                               midc->dma->pci_id, midc->ch_id, len);
-       pr_debug("MDMA:Cfg passed Mode %x, Dirn %x, HS %x, Width %x\n",
-                       mids->cfg_mode, mids->dma_slave.direction,
-                       mids->hs_mode, mids->dma_slave.src_addr_width);
-
-       /*calculate CFG_LO*/
-       if (mids->hs_mode == LNW_DMA_SW_HS) {
-               cfg_lo.cfg_lo = 0;
-               cfg_lo.cfgx.hs_sel_dst = 1;
-               cfg_lo.cfgx.hs_sel_src = 1;
-       } else if (mids->hs_mode == LNW_DMA_HW_HS)
-               cfg_lo.cfg_lo = 0x00000;
-
-       /*calculate CFG_HI*/
-       if (mids->cfg_mode == LNW_DMA_MEM_TO_MEM) {
-               /*SW HS only*/
-               cfg_hi.cfg_hi = 0;
-       } else {
-               cfg_hi.cfg_hi = 0;
-               if (midc->dma->pimr_mask) {
-                       cfg_hi.cfgx.protctl = 0x0; /*default value*/
-                       cfg_hi.cfgx.fifo_mode = 1;
-                       if (mids->dma_slave.direction == DMA_MEM_TO_DEV) {
-                               cfg_hi.cfgx.src_per = 0;
-                               if (mids->device_instance == 0)
-                                       cfg_hi.cfgx.dst_per = 3;
-                               if (mids->device_instance == 1)
-                                       cfg_hi.cfgx.dst_per = 1;
-                       } else if (mids->dma_slave.direction == DMA_DEV_TO_MEM) {
-                               if (mids->device_instance == 0)
-                                       cfg_hi.cfgx.src_per = 2;
-                               if (mids->device_instance == 1)
-                                       cfg_hi.cfgx.src_per = 0;
-                               cfg_hi.cfgx.dst_per = 0;
-                       }
-               } else {
-                       cfg_hi.cfgx.protctl = 0x1; /*default value*/
-                       cfg_hi.cfgx.src_per = cfg_hi.cfgx.dst_per =
-                                       midc->ch_id - midc->dma->chan_base;
-               }
-       }
-
-       /*calculate CTL_HI*/
-       ctl_hi.ctlx.reser = 0;
-       ctl_hi.ctlx.done  = 0;
-       width = mids->dma_slave.src_addr_width;
-
-       ctl_hi.ctlx.block_ts = get_block_ts(len, width, midc->dma->block_size);
-       pr_debug("MDMA:calc len %d for block size %d\n",
-                               ctl_hi.ctlx.block_ts, midc->dma->block_size);
-       /*calculate CTL_LO*/
-       ctl_lo.ctl_lo = 0;
-       ctl_lo.ctlx.int_en = 1;
-       ctl_lo.ctlx.dst_msize = mids->dma_slave.src_maxburst;
-       ctl_lo.ctlx.src_msize = mids->dma_slave.dst_maxburst;
-
-       /*
-        * Here we need some translation from "enum dma_slave_buswidth"
-        * to the format for our dma controller
-        *              standard        intel_mid_dmac's format
-        *               1 Byte                 0b000
-        *               2 Bytes                0b001
-        *               4 Bytes                0b010
-        */
-       ctl_lo.ctlx.dst_tr_width = mids->dma_slave.dst_addr_width / 2;
-       ctl_lo.ctlx.src_tr_width = mids->dma_slave.src_addr_width / 2;
-
-       if (mids->cfg_mode == LNW_DMA_MEM_TO_MEM) {
-               ctl_lo.ctlx.tt_fc = 0;
-               ctl_lo.ctlx.sinc = 0;
-               ctl_lo.ctlx.dinc = 0;
-       } else {
-               if (mids->dma_slave.direction == DMA_MEM_TO_DEV) {
-                       ctl_lo.ctlx.sinc = 0;
-                       ctl_lo.ctlx.dinc = 2;
-                       ctl_lo.ctlx.tt_fc = 1;
-               } else if (mids->dma_slave.direction == DMA_DEV_TO_MEM) {
-                       ctl_lo.ctlx.sinc = 2;
-                       ctl_lo.ctlx.dinc = 0;
-                       ctl_lo.ctlx.tt_fc = 2;
-               }
-       }
-
-       pr_debug("MDMA:Calc CTL LO %x, CTL HI %x, CFG LO %x, CFG HI %x\n",
-               ctl_lo.ctl_lo, ctl_hi.ctl_hi, cfg_lo.cfg_lo, cfg_hi.cfg_hi);
-
-       enable_dma_interrupt(midc);
-
-       desc = midc_desc_get(midc);
-       if (desc == NULL)
-               goto err_desc_get;
-       desc->sar = src;
-       desc->dar = dest ;
-       desc->len = len;
-       desc->cfg_hi = cfg_hi.cfg_hi;
-       desc->cfg_lo = cfg_lo.cfg_lo;
-       desc->ctl_lo = ctl_lo.ctl_lo;
-       desc->ctl_hi = ctl_hi.ctl_hi;
-       desc->width = width;
-       desc->dirn = mids->dma_slave.direction;
-       desc->lli_phys = 0;
-       desc->lli = NULL;
-       desc->lli_pool = NULL;
-       return &desc->txd;
-
-err_desc_get:
-       pr_err("ERR_MDMA: Failed to get desc\n");
-       midc_desc_put(midc, desc);
-       return NULL;
-}
-/**
- * intel_mid_dma_prep_slave_sg -       Prep slave sg txn
- * @chan: chan for DMA transfer
- * @sgl: scatter gather list
- * @sg_len: length of sg txn
- * @direction: DMA transfer dirtn
- * @flags: DMA flags
- * @context: transfer context (ignored)
- *
- * Prepares LLI based periphral transfer
- */
-static struct dma_async_tx_descriptor *intel_mid_dma_prep_slave_sg(
-                       struct dma_chan *chan, struct scatterlist *sgl,
-                       unsigned int sg_len, enum dma_transfer_direction direction,
-                       unsigned long flags, void *context)
-{
-       struct intel_mid_dma_chan *midc = NULL;
-       struct intel_mid_dma_slave *mids = NULL;
-       struct intel_mid_dma_desc *desc = NULL;
-       struct dma_async_tx_descriptor *txd = NULL;
-       union intel_mid_dma_ctl_lo ctl_lo;
-
-       pr_debug("MDMA: Prep for slave SG\n");
-
-       if (!sg_len) {
-               pr_err("MDMA: Invalid SG length\n");
-               return NULL;
-       }
-       midc = to_intel_mid_dma_chan(chan);
-       BUG_ON(!midc);
-
-       mids = midc->mid_slave;
-       BUG_ON(!mids);
-
-       if (!midc->dma->pimr_mask) {
-               /* We can still handle sg list with only one item */
-               if (sg_len == 1) {
-                       txd = intel_mid_dma_prep_memcpy(chan,
-                                               mids->dma_slave.dst_addr,
-                                               mids->dma_slave.src_addr,
-                                               sg_dma_len(sgl),
-                                               flags);
-                       return txd;
-               } else {
-                       pr_warn("MDMA: SG list is not supported by this controller\n");
-                       return  NULL;
-               }
-       }
-
-       pr_debug("MDMA: SG Length = %d, direction = %d, Flags = %#lx\n",
-                       sg_len, direction, flags);
-
-       txd = intel_mid_dma_prep_memcpy(chan, 0, 0, sg_dma_len(sgl), flags);
-       if (NULL == txd) {
-               pr_err("MDMA: Prep memcpy failed\n");
-               return NULL;
-       }
-
-       desc = to_intel_mid_dma_desc(txd);
-       desc->dirn = direction;
-       ctl_lo.ctl_lo = desc->ctl_lo;
-       ctl_lo.ctlx.llp_dst_en = 1;
-       ctl_lo.ctlx.llp_src_en = 1;
-       desc->ctl_lo = ctl_lo.ctl_lo;
-       desc->lli_length = sg_len;
-       desc->current_lli = 0;
-       /* DMA coherent memory pool for LLI descriptors*/
-       desc->lli_pool = pci_pool_create("intel_mid_dma_lli_pool",
-                               midc->dma->pdev,
-                               (sizeof(struct intel_mid_dma_lli)*sg_len),
-                               32, 0);
-       if (NULL == desc->lli_pool) {
-               pr_err("MID_DMA:LLI pool create failed\n");
-               return NULL;
-       }
-
-       desc->lli = pci_pool_alloc(desc->lli_pool, GFP_KERNEL, &desc->lli_phys);
-       if (!desc->lli) {
-               pr_err("MID_DMA: LLI alloc failed\n");
-               pci_pool_destroy(desc->lli_pool);
-               return NULL;
-       }
-
-       midc_lli_fill_sg(midc, desc, sgl, sg_len, flags);
-       if (flags & DMA_PREP_INTERRUPT) {
-               iowrite32(UNMASK_INTR_REG(midc->ch_id),
-                               midc->dma_base + MASK_BLOCK);
-               pr_debug("MDMA:Enabled Block interrupt\n");
-       }
-       return &desc->txd;
-}
-
-/**
- * intel_mid_dma_free_chan_resources - Frees dma resources
- * @chan: chan requiring attention
- *
- * Frees the allocated resources on this DMA chan
- */
-static void intel_mid_dma_free_chan_resources(struct dma_chan *chan)
-{
-       struct intel_mid_dma_chan       *midc = to_intel_mid_dma_chan(chan);
-       struct middma_device    *mid = to_middma_device(chan->device);
-       struct intel_mid_dma_desc       *desc, *_desc;
-
-       if (true == midc->busy) {
-               /*trying to free ch in use!!!!!*/
-               pr_err("ERR_MDMA: trying to free ch in use\n");
-       }
-       spin_lock_bh(&midc->lock);
-       midc->descs_allocated = 0;
-       list_for_each_entry_safe(desc, _desc, &midc->active_list, desc_node) {
-               list_del(&desc->desc_node);
-               pci_pool_free(mid->dma_pool, desc, desc->txd.phys);
-       }
-       list_for_each_entry_safe(desc, _desc, &midc->free_list, desc_node) {
-               list_del(&desc->desc_node);
-               pci_pool_free(mid->dma_pool, desc, desc->txd.phys);
-       }
-       list_for_each_entry_safe(desc, _desc, &midc->queue, desc_node) {
-               list_del(&desc->desc_node);
-               pci_pool_free(mid->dma_pool, desc, desc->txd.phys);
-       }
-       spin_unlock_bh(&midc->lock);
-       midc->in_use = false;
-       midc->busy = false;
-       /* Disable CH interrupts */
-       iowrite32(MASK_INTR_REG(midc->ch_id), mid->dma_base + MASK_BLOCK);
-       iowrite32(MASK_INTR_REG(midc->ch_id), mid->dma_base + MASK_ERR);
-       pm_runtime_put(&mid->pdev->dev);
-}
-
-/**
- * intel_mid_dma_alloc_chan_resources -        Allocate dma resources
- * @chan: chan requiring attention
- *
- * Allocates DMA resources on this chan
- * Return the descriptors allocated
- */
-static int intel_mid_dma_alloc_chan_resources(struct dma_chan *chan)
-{
-       struct intel_mid_dma_chan       *midc = to_intel_mid_dma_chan(chan);
-       struct middma_device    *mid = to_middma_device(chan->device);
-       struct intel_mid_dma_desc       *desc;
-       dma_addr_t              phys;
-       int     i = 0;
-
-       pm_runtime_get_sync(&mid->pdev->dev);
-
-       if (mid->state == SUSPENDED) {
-               if (dma_resume(&mid->pdev->dev)) {
-                       pr_err("ERR_MDMA: resume failed");
-                       return -EFAULT;
-               }
-       }
-
-       /* ASSERT:  channel is idle */
-       if (test_ch_en(mid->dma_base, midc->ch_id)) {
-               /*ch is not idle*/
-               pr_err("ERR_MDMA: ch not idle\n");
-               pm_runtime_put(&mid->pdev->dev);
-               return -EIO;
-       }
-       dma_cookie_init(chan);
-
-       spin_lock_bh(&midc->lock);
-       while (midc->descs_allocated < DESCS_PER_CHANNEL) {
-               spin_unlock_bh(&midc->lock);
-               desc = pci_pool_alloc(mid->dma_pool, GFP_KERNEL, &phys);
-               if (!desc) {
-                       pr_err("ERR_MDMA: desc failed\n");
-                       pm_runtime_put(&mid->pdev->dev);
-                       return -ENOMEM;
-                       /*check*/
-               }
-               dma_async_tx_descriptor_init(&desc->txd, chan);
-               desc->txd.tx_submit = intel_mid_dma_tx_submit;
-               desc->txd.flags = DMA_CTRL_ACK;
-               desc->txd.phys = phys;
-               spin_lock_bh(&midc->lock);
-               i = ++midc->descs_allocated;
-               list_add_tail(&desc->desc_node, &midc->free_list);
-       }
-       spin_unlock_bh(&midc->lock);
-       midc->in_use = true;
-       midc->busy = false;
-       pr_debug("MID_DMA: Desc alloc done ret: %d desc\n", i);
-       return i;
-}
-
-/**
- * midc_handle_error - Handle DMA txn error
- * @mid: controller where error occurred
- * @midc: chan where error occurred
- *
- * Scan the descriptor for error
- */
-static void midc_handle_error(struct middma_device *mid,
-               struct intel_mid_dma_chan *midc)
-{
-       midc_scan_descriptors(mid, midc);
-}
-
-/**
- * dma_tasklet -       DMA interrupt tasklet
- * @data: tasklet arg (the controller structure)
- *
- * Scan the controller for interrupts for completion/error
- * Clear the interrupt and call for handling completion/error
- */
-static void dma_tasklet(unsigned long data)
-{
-       struct middma_device *mid = NULL;
-       struct intel_mid_dma_chan *midc = NULL;
-       u32 status, raw_tfr, raw_block;
-       int i;
-
-       mid = (struct middma_device *)data;
-       if (mid == NULL) {
-               pr_err("ERR_MDMA: tasklet Null param\n");
-               return;
-       }
-       pr_debug("MDMA: in tasklet for device %x\n", mid->pci_id);
-       raw_tfr = ioread32(mid->dma_base + RAW_TFR);
-       raw_block = ioread32(mid->dma_base + RAW_BLOCK);
-       status = raw_tfr | raw_block;
-       status &= mid->intr_mask;
-       while (status) {
-               /*txn interrupt*/
-               i = get_ch_index(&status, mid->chan_base);
-               if (i < 0) {
-                       pr_err("ERR_MDMA:Invalid ch index %x\n", i);
-                       return;
-               }
-               midc = &mid->ch[i];
-               if (midc == NULL) {
-                       pr_err("ERR_MDMA:Null param midc\n");
-                       return;
-               }
-               pr_debug("MDMA:Tx complete interrupt %x, Ch No %d Index %d\n",
-                               status, midc->ch_id, i);
-               midc->raw_tfr = raw_tfr;
-               midc->raw_block = raw_block;
-               spin_lock_bh(&midc->lock);
-               /*clearing this interrupts first*/
-               iowrite32((1 << midc->ch_id), mid->dma_base + CLEAR_TFR);
-               if (raw_block) {
-                       iowrite32((1 << midc->ch_id),
-                               mid->dma_base + CLEAR_BLOCK);
-               }
-               midc_scan_descriptors(mid, midc);
-               pr_debug("MDMA:Scan of desc... complete, unmasking\n");
-               iowrite32(UNMASK_INTR_REG(midc->ch_id),
-                               mid->dma_base + MASK_TFR);
-               if (raw_block) {
-                       iowrite32(UNMASK_INTR_REG(midc->ch_id),
-                               mid->dma_base + MASK_BLOCK);
-               }
-               spin_unlock_bh(&midc->lock);
-       }
-
-       status = ioread32(mid->dma_base + RAW_ERR);
-       status &= mid->intr_mask;
-       while (status) {
-               /*err interrupt*/
-               i = get_ch_index(&status, mid->chan_base);
-               if (i < 0) {
-                       pr_err("ERR_MDMA:Invalid ch index %x\n", i);
-                       return;
-               }
-               midc = &mid->ch[i];
-               if (midc == NULL) {
-                       pr_err("ERR_MDMA:Null param midc\n");
-                       return;
-               }
-               pr_debug("MDMA:Tx complete interrupt %x, Ch No %d Index %d\n",
-                               status, midc->ch_id, i);
-
-               iowrite32((1 << midc->ch_id), mid->dma_base + CLEAR_ERR);
-               spin_lock_bh(&midc->lock);
-               midc_handle_error(mid, midc);
-               iowrite32(UNMASK_INTR_REG(midc->ch_id),
-                               mid->dma_base + MASK_ERR);
-               spin_unlock_bh(&midc->lock);
-       }
-       pr_debug("MDMA:Exiting takslet...\n");
-       return;
-}
-
-static void dma_tasklet1(unsigned long data)
-{
-       pr_debug("MDMA:in takslet1...\n");
-       return dma_tasklet(data);
-}
-
-static void dma_tasklet2(unsigned long data)
-{
-       pr_debug("MDMA:in takslet2...\n");
-       return dma_tasklet(data);
-}
-
-/**
- * intel_mid_dma_interrupt -   DMA ISR
- * @irq: IRQ where interrupt occurred
- * @data: ISR cllback data (the controller structure)
- *
- * See if this is our interrupt if so then schedule the tasklet
- * otherwise ignore
- */
-static irqreturn_t intel_mid_dma_interrupt(int irq, void *data)
-{
-       struct middma_device *mid = data;
-       u32 tfr_status, err_status;
-       int call_tasklet = 0;
-
-       tfr_status = ioread32(mid->dma_base + RAW_TFR);
-       err_status = ioread32(mid->dma_base + RAW_ERR);
-       if (!tfr_status && !err_status)
-               return IRQ_NONE;
-
-       /*DMA Interrupt*/
-       pr_debug("MDMA:Got an interrupt on irq %d\n", irq);
-       pr_debug("MDMA: Status %x, Mask %x\n", tfr_status, mid->intr_mask);
-       tfr_status &= mid->intr_mask;
-       if (tfr_status) {
-               /*need to disable intr*/
-               iowrite32((tfr_status << INT_MASK_WE), mid->dma_base + MASK_TFR);
-               iowrite32((tfr_status << INT_MASK_WE), mid->dma_base + MASK_BLOCK);
-               pr_debug("MDMA: Calling tasklet %x\n", tfr_status);
-               call_tasklet = 1;
-       }
-       err_status &= mid->intr_mask;
-       if (err_status) {
-               iowrite32((err_status << INT_MASK_WE),
-                         mid->dma_base + MASK_ERR);
-               call_tasklet = 1;
-       }
-       if (call_tasklet)
-               tasklet_schedule(&mid->tasklet);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t intel_mid_dma_interrupt1(int irq, void *data)
-{
-       return intel_mid_dma_interrupt(irq, data);
-}
-
-static irqreturn_t intel_mid_dma_interrupt2(int irq, void *data)
-{
-       return intel_mid_dma_interrupt(irq, data);
-}
-
-/**
- * mid_setup_dma -     Setup the DMA controller
- * @pdev: Controller PCI device structure
- *
- * Initialize the DMA controller, channels, registers with DMA engine,
- * ISR. Initialize DMA controller channels.
- */
-static int mid_setup_dma(struct pci_dev *pdev)
-{
-       struct middma_device *dma = pci_get_drvdata(pdev);
-       int err, i;
-
-       /* DMA coherent memory pool for DMA descriptor allocations */
-       dma->dma_pool = pci_pool_create("intel_mid_dma_desc_pool", pdev,
-                                       sizeof(struct intel_mid_dma_desc),
-                                       32, 0);
-       if (NULL == dma->dma_pool) {
-               pr_err("ERR_MDMA:pci_pool_create failed\n");
-               err = -ENOMEM;
-               goto err_dma_pool;
-       }
-
-       INIT_LIST_HEAD(&dma->common.channels);
-       dma->pci_id = pdev->device;
-       if (dma->pimr_mask) {
-               dma->mask_reg = ioremap(LNW_PERIPHRAL_MASK_BASE,
-                                       LNW_PERIPHRAL_MASK_SIZE);
-               if (dma->mask_reg == NULL) {
-                       pr_err("ERR_MDMA:Can't map periphral intr space !!\n");
-                       err = -ENOMEM;
-                       goto err_ioremap;
-               }
-       } else
-               dma->mask_reg = NULL;
-
-       pr_debug("MDMA:Adding %d channel for this controller\n", dma->max_chan);
-       /*init CH structures*/
-       dma->intr_mask = 0;
-       dma->state = RUNNING;
-       for (i = 0; i < dma->max_chan; i++) {
-               struct intel_mid_dma_chan *midch = &dma->ch[i];
-
-               midch->chan.device = &dma->common;
-               dma_cookie_init(&midch->chan);
-               midch->ch_id = dma->chan_base + i;
-               pr_debug("MDMA:Init CH %d, ID %d\n", i, midch->ch_id);
-
-               midch->dma_base = dma->dma_base;
-               midch->ch_regs = dma->dma_base + DMA_CH_SIZE * midch->ch_id;
-               midch->dma = dma;
-               dma->intr_mask |= 1 << (dma->chan_base + i);
-               spin_lock_init(&midch->lock);
-
-               INIT_LIST_HEAD(&midch->active_list);
-               INIT_LIST_HEAD(&midch->queue);
-               INIT_LIST_HEAD(&midch->free_list);
-               /*mask interrupts*/
-               iowrite32(MASK_INTR_REG(midch->ch_id),
-                       dma->dma_base + MASK_BLOCK);
-               iowrite32(MASK_INTR_REG(midch->ch_id),
-                       dma->dma_base + MASK_SRC_TRAN);
-               iowrite32(MASK_INTR_REG(midch->ch_id),
-                       dma->dma_base + MASK_DST_TRAN);
-               iowrite32(MASK_INTR_REG(midch->ch_id),
-                       dma->dma_base + MASK_ERR);
-               iowrite32(MASK_INTR_REG(midch->ch_id),
-                       dma->dma_base + MASK_TFR);
-
-               disable_dma_interrupt(midch);
-               list_add_tail(&midch->chan.device_node, &dma->common.channels);
-       }
-       pr_debug("MDMA: Calc Mask as %x for this controller\n", dma->intr_mask);
-
-       /*init dma structure*/
-       dma_cap_zero(dma->common.cap_mask);
-       dma_cap_set(DMA_MEMCPY, dma->common.cap_mask);
-       dma_cap_set(DMA_SLAVE, dma->common.cap_mask);
-       dma_cap_set(DMA_PRIVATE, dma->common.cap_mask);
-       dma->common.dev = &pdev->dev;
-
-       dma->common.device_alloc_chan_resources =
-                                       intel_mid_dma_alloc_chan_resources;
-       dma->common.device_free_chan_resources =
-                                       intel_mid_dma_free_chan_resources;
-
-       dma->common.device_tx_status = intel_mid_dma_tx_status;
-       dma->common.device_prep_dma_memcpy = intel_mid_dma_prep_memcpy;
-       dma->common.device_issue_pending = intel_mid_dma_issue_pending;
-       dma->common.device_prep_slave_sg = intel_mid_dma_prep_slave_sg;
-       dma->common.device_config = intel_mid_dma_config;
-       dma->common.device_terminate_all = intel_mid_dma_terminate_all;
-
-       /*enable dma cntrl*/
-       iowrite32(REG_BIT0, dma->dma_base + DMA_CFG);
-
-       /*register irq */
-       if (dma->pimr_mask) {
-               pr_debug("MDMA:Requesting irq shared for DMAC1\n");
-               err = request_irq(pdev->irq, intel_mid_dma_interrupt1,
-                       IRQF_SHARED, "INTEL_MID_DMAC1", dma);
-               if (0 != err)
-                       goto err_irq;
-       } else {
-               dma->intr_mask = 0x03;
-               pr_debug("MDMA:Requesting irq for DMAC2\n");
-               err = request_irq(pdev->irq, intel_mid_dma_interrupt2,
-                       IRQF_SHARED, "INTEL_MID_DMAC2", dma);
-               if (0 != err)
-                       goto err_irq;
-       }
-       /*register device w/ engine*/
-       err = dma_async_device_register(&dma->common);
-       if (0 != err) {
-               pr_err("ERR_MDMA:device_register failed: %d\n", err);
-               goto err_engine;
-       }
-       if (dma->pimr_mask) {
-               pr_debug("setting up tasklet1 for DMAC1\n");
-               tasklet_init(&dma->tasklet, dma_tasklet1, (unsigned long)dma);
-       } else {
-               pr_debug("setting up tasklet2 for DMAC2\n");
-               tasklet_init(&dma->tasklet, dma_tasklet2, (unsigned long)dma);
-       }
-       return 0;
-
-err_engine:
-       free_irq(pdev->irq, dma);
-err_irq:
-       if (dma->mask_reg)
-               iounmap(dma->mask_reg);
-err_ioremap:
-       pci_pool_destroy(dma->dma_pool);
-err_dma_pool:
-       pr_err("ERR_MDMA:setup_dma failed: %d\n", err);
-       return err;
-
-}
-
-/**
- * middma_shutdown -   Shutdown the DMA controller
- * @pdev: Controller PCI device structure
- *
- * Called by remove
- * Unregister DMa controller, clear all structures and free interrupt
- */
-static void middma_shutdown(struct pci_dev *pdev)
-{
-       struct middma_device *device = pci_get_drvdata(pdev);
-
-       dma_async_device_unregister(&device->common);
-       pci_pool_destroy(device->dma_pool);
-       if (device->mask_reg)
-               iounmap(device->mask_reg);
-       if (device->dma_base)
-               iounmap(device->dma_base);
-       free_irq(pdev->irq, device);
-       return;
-}
-
-/**
- * intel_mid_dma_probe -       PCI Probe
- * @pdev: Controller PCI device structure
- * @id: pci device id structure
- *
- * Initialize the PCI device, map BARs, query driver data.
- * Call setup_dma to complete contoller and chan initilzation
- */
-static int intel_mid_dma_probe(struct pci_dev *pdev,
-                                       const struct pci_device_id *id)
-{
-       struct middma_device *device;
-       u32 base_addr, bar_size;
-       struct intel_mid_dma_probe_info *info;
-       int err;
-
-       pr_debug("MDMA: probe for %x\n", pdev->device);
-       info = (void *)id->driver_data;
-       pr_debug("MDMA: CH %d, base %d, block len %d, Periphral mask %x\n",
-                               info->max_chan, info->ch_base,
-                               info->block_size, info->pimr_mask);
-
-       err = pci_enable_device(pdev);
-       if (err)
-               goto err_enable_device;
-
-       err = pci_request_regions(pdev, "intel_mid_dmac");
-       if (err)
-               goto err_request_regions;
-
-       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-       if (err)
-               goto err_set_dma_mask;
-
-       err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-       if (err)
-               goto err_set_dma_mask;
-
-       device = kzalloc(sizeof(*device), GFP_KERNEL);
-       if (!device) {
-               pr_err("ERR_MDMA:kzalloc failed probe\n");
-               err = -ENOMEM;
-               goto err_kzalloc;
-       }
-       device->pdev = pci_dev_get(pdev);
-
-       base_addr = pci_resource_start(pdev, 0);
-       bar_size  = pci_resource_len(pdev, 0);
-       device->dma_base = ioremap_nocache(base_addr, DMA_REG_SIZE);
-       if (!device->dma_base) {
-               pr_err("ERR_MDMA:ioremap failed\n");
-               err = -ENOMEM;
-               goto err_ioremap;
-       }
-       pci_set_drvdata(pdev, device);
-       pci_set_master(pdev);
-       device->max_chan = info->max_chan;
-       device->chan_base = info->ch_base;
-       device->block_size = info->block_size;
-       device->pimr_mask = info->pimr_mask;
-
-       err = mid_setup_dma(pdev);
-       if (err)
-               goto err_dma;
-
-       pm_runtime_put_noidle(&pdev->dev);
-       pm_runtime_allow(&pdev->dev);
-       return 0;
-
-err_dma:
-       iounmap(device->dma_base);
-err_ioremap:
-       pci_dev_put(pdev);
-       kfree(device);
-err_kzalloc:
-err_set_dma_mask:
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-err_request_regions:
-err_enable_device:
-       pr_err("ERR_MDMA:Probe failed %d\n", err);
-       return err;
-}
-
-/**
- * intel_mid_dma_remove -      PCI remove
- * @pdev: Controller PCI device structure
- *
- * Free up all resources and data
- * Call shutdown_dma to complete contoller and chan cleanup
- */
-static void intel_mid_dma_remove(struct pci_dev *pdev)
-{
-       struct middma_device *device = pci_get_drvdata(pdev);
-
-       pm_runtime_get_noresume(&pdev->dev);
-       pm_runtime_forbid(&pdev->dev);
-       middma_shutdown(pdev);
-       pci_dev_put(pdev);
-       kfree(device);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-}
-
-/* Power Management */
-/*
-* dma_suspend - PCI suspend function
-*
-* @pci: PCI device structure
-* @state: PM message
-*
-* This function is called by OS when a power event occurs
-*/
-static int dma_suspend(struct device *dev)
-{
-       struct pci_dev *pci = to_pci_dev(dev);
-       int i;
-       struct middma_device *device = pci_get_drvdata(pci);
-       pr_debug("MDMA: dma_suspend called\n");
-
-       for (i = 0; i < device->max_chan; i++) {
-               if (device->ch[i].in_use)
-                       return -EAGAIN;
-       }
-       dmac1_mask_periphral_intr(device);
-       device->state = SUSPENDED;
-       pci_save_state(pci);
-       pci_disable_device(pci);
-       pci_set_power_state(pci, PCI_D3hot);
-       return 0;
-}
-
-/**
-* dma_resume - PCI resume function
-*
-* @pci:        PCI device structure
-*
-* This function is called by OS when a power event occurs
-*/
-int dma_resume(struct device *dev)
-{
-       struct pci_dev *pci = to_pci_dev(dev);
-       int ret;
-       struct middma_device *device = pci_get_drvdata(pci);
-
-       pr_debug("MDMA: dma_resume called\n");
-       pci_set_power_state(pci, PCI_D0);
-       pci_restore_state(pci);
-       ret = pci_enable_device(pci);
-       if (ret) {
-               pr_err("MDMA: device can't be enabled for %x\n", pci->device);
-               return ret;
-       }
-       device->state = RUNNING;
-       iowrite32(REG_BIT0, device->dma_base + DMA_CFG);
-       return 0;
-}
-
-static int dma_runtime_suspend(struct device *dev)
-{
-       struct pci_dev *pci_dev = to_pci_dev(dev);
-       struct middma_device *device = pci_get_drvdata(pci_dev);
-
-       device->state = SUSPENDED;
-       return 0;
-}
-
-static int dma_runtime_resume(struct device *dev)
-{
-       struct pci_dev *pci_dev = to_pci_dev(dev);
-       struct middma_device *device = pci_get_drvdata(pci_dev);
-
-       device->state = RUNNING;
-       iowrite32(REG_BIT0, device->dma_base + DMA_CFG);
-       return 0;
-}
-
-static int dma_runtime_idle(struct device *dev)
-{
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct middma_device *device = pci_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < device->max_chan; i++) {
-               if (device->ch[i].in_use)
-                       return -EAGAIN;
-       }
-
-       return 0;
-}
-
-/******************************************************************************
-* PCI stuff
-*/
-static struct pci_device_id intel_mid_dma_ids[] = {
-       { PCI_VDEVICE(INTEL, INTEL_MID_DMAC1_ID),       INFO(2, 6, 4095, 0x200020)},
-       { PCI_VDEVICE(INTEL, INTEL_MID_DMAC2_ID),       INFO(2, 0, 2047, 0)},
-       { PCI_VDEVICE(INTEL, INTEL_MID_GP_DMAC2_ID),    INFO(2, 0, 2047, 0)},
-       { PCI_VDEVICE(INTEL, INTEL_MFLD_DMAC1_ID),      INFO(4, 0, 4095, 0x400040)},
-       { 0, }
-};
-MODULE_DEVICE_TABLE(pci, intel_mid_dma_ids);
-
-static const struct dev_pm_ops intel_mid_dma_pm = {
-       .runtime_suspend = dma_runtime_suspend,
-       .runtime_resume = dma_runtime_resume,
-       .runtime_idle = dma_runtime_idle,
-       .suspend = dma_suspend,
-       .resume = dma_resume,
-};
-
-static struct pci_driver intel_mid_dma_pci_driver = {
-       .name           =       "Intel MID DMA",
-       .id_table       =       intel_mid_dma_ids,
-       .probe          =       intel_mid_dma_probe,
-       .remove         =       intel_mid_dma_remove,
-#ifdef CONFIG_PM
-       .driver = {
-               .pm = &intel_mid_dma_pm,
-       },
-#endif
-};
-
-static int __init intel_mid_dma_init(void)
-{
-       pr_debug("INFO_MDMA: LNW DMA Driver Version %s\n",
-                       INTEL_MID_DMA_DRIVER_VERSION);
-       return pci_register_driver(&intel_mid_dma_pci_driver);
-}
-fs_initcall(intel_mid_dma_init);
-
-static void __exit intel_mid_dma_exit(void)
-{
-       pci_unregister_driver(&intel_mid_dma_pci_driver);
-}
-module_exit(intel_mid_dma_exit);
-
-MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
-MODULE_DESCRIPTION("Intel (R) MID DMAC Driver");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION(INTEL_MID_DMA_DRIVER_VERSION);
diff --git a/drivers/dma/intel_mid_dma_regs.h b/drivers/dma/intel_mid_dma_regs.h
deleted file mode 100644 (file)
index 17b4219..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- *  intel_mid_dma_regs.h - Intel MID DMA Drivers
- *
- *  Copyright (C) 2008-10 Intel Corp
- *  Author: Vinod Koul <vinod.koul@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *
- */
-#ifndef __INTEL_MID_DMAC_REGS_H__
-#define __INTEL_MID_DMAC_REGS_H__
-
-#include <linux/dmaengine.h>
-#include <linux/dmapool.h>
-#include <linux/pci_ids.h>
-
-#define INTEL_MID_DMA_DRIVER_VERSION "1.1.0"
-
-#define        REG_BIT0                0x00000001
-#define        REG_BIT8                0x00000100
-#define INT_MASK_WE            0x8
-#define CLEAR_DONE             0xFFFFEFFF
-#define UNMASK_INTR_REG(chan_num) \
-       ((REG_BIT0 << chan_num) | (REG_BIT8 << chan_num))
-#define MASK_INTR_REG(chan_num) (REG_BIT8 << chan_num)
-
-#define ENABLE_CHANNEL(chan_num) \
-       ((REG_BIT0 << chan_num) | (REG_BIT8 << chan_num))
-
-#define DISABLE_CHANNEL(chan_num) \
-       (REG_BIT8 << chan_num)
-
-#define DESCS_PER_CHANNEL      16
-/*DMA Registers*/
-/*registers associated with channel programming*/
-#define DMA_REG_SIZE           0x400
-#define DMA_CH_SIZE            0x58
-
-/*CH X REG = (DMA_CH_SIZE)*CH_NO + REG*/
-#define SAR                    0x00 /* Source Address Register*/
-#define DAR                    0x08 /* Destination Address Register*/
-#define LLP                    0x10 /* Linked List Pointer Register*/
-#define CTL_LOW                        0x18 /* Control Register*/
-#define CTL_HIGH               0x1C /* Control Register*/
-#define CFG_LOW                        0x40 /* Configuration Register Low*/
-#define CFG_HIGH               0x44 /* Configuration Register high*/
-
-#define STATUS_TFR             0x2E8
-#define STATUS_BLOCK           0x2F0
-#define STATUS_ERR             0x308
-
-#define RAW_TFR                        0x2C0
-#define RAW_BLOCK              0x2C8
-#define RAW_ERR                        0x2E0
-
-#define MASK_TFR               0x310
-#define MASK_BLOCK             0x318
-#define MASK_SRC_TRAN          0x320
-#define MASK_DST_TRAN          0x328
-#define MASK_ERR               0x330
-
-#define CLEAR_TFR              0x338
-#define CLEAR_BLOCK            0x340
-#define CLEAR_SRC_TRAN         0x348
-#define CLEAR_DST_TRAN         0x350
-#define CLEAR_ERR              0x358
-
-#define INTR_STATUS            0x360
-#define DMA_CFG                        0x398
-#define DMA_CHAN_EN            0x3A0
-
-/*DMA channel control registers*/
-union intel_mid_dma_ctl_lo {
-       struct {
-               u32     int_en:1;       /*enable or disable interrupts*/
-                                       /*should be 0*/
-               u32     dst_tr_width:3; /*destination transfer width*/
-                                       /*usually 32 bits = 010*/
-               u32     src_tr_width:3; /*source transfer width*/
-                                       /*usually 32 bits = 010*/
-               u32     dinc:2;         /*destination address inc/dec*/
-                                       /*For mem:INC=00, Periphral NoINC=11*/
-               u32     sinc:2;         /*source address inc or dec, as above*/
-               u32     dst_msize:3;    /*destination burst transaction length*/
-                                       /*always = 16 ie 011*/
-               u32     src_msize:3;    /*source burst transaction length*/
-                                       /*always = 16 ie 011*/
-               u32     reser1:3;
-               u32     tt_fc:3;        /*transfer type and flow controller*/
-                                       /*M-M = 000
-                                         P-M = 010
-                                         M-P = 001*/
-               u32     dms:2;          /*destination master select = 0*/
-               u32     sms:2;          /*source master select = 0*/
-               u32     llp_dst_en:1;   /*enable/disable destination LLP = 0*/
-               u32     llp_src_en:1;   /*enable/disable source LLP = 0*/
-               u32     reser2:3;
-       } ctlx;
-       u32     ctl_lo;
-};
-
-union intel_mid_dma_ctl_hi {
-       struct {
-               u32     block_ts:12;    /*block transfer size*/
-               u32     done:1;         /*Done - updated by DMAC*/
-               u32     reser:19;       /*configured by DMAC*/
-       } ctlx;
-       u32     ctl_hi;
-
-};
-
-/*DMA channel configuration registers*/
-union intel_mid_dma_cfg_lo {
-       struct {
-               u32     reser1:5;
-               u32     ch_prior:3;     /*channel priority = 0*/
-               u32     ch_susp:1;      /*channel suspend = 0*/
-               u32     fifo_empty:1;   /*FIFO empty or not R bit = 0*/
-               u32     hs_sel_dst:1;   /*select HW/SW destn handshaking*/
-                                       /*HW = 0, SW = 1*/
-               u32     hs_sel_src:1;   /*select HW/SW src handshaking*/
-               u32     reser2:6;
-               u32     dst_hs_pol:1;   /*dest HS interface polarity*/
-               u32     src_hs_pol:1;   /*src HS interface polarity*/
-               u32     max_abrst:10;   /*max AMBA burst len = 0 (no sw limit*/
-               u32     reload_src:1;   /*auto reload src addr =1 if src is P*/
-               u32     reload_dst:1;   /*AR destn addr =1 if dstn is P*/
-       } cfgx;
-       u32     cfg_lo;
-};
-
-union intel_mid_dma_cfg_hi {
-       struct {
-               u32     fcmode:1;       /*flow control mode = 1*/
-               u32     fifo_mode:1;    /*FIFO mode select = 1*/
-               u32     protctl:3;      /*protection control = 0*/
-               u32     rsvd:2;
-               u32     src_per:4;      /*src hw HS interface*/
-               u32     dst_per:4;      /*dstn hw HS interface*/
-               u32     reser2:17;
-       } cfgx;
-       u32     cfg_hi;
-};
-
-
-/**
- * struct intel_mid_dma_chan - internal mid representation of a DMA channel
- * @chan: dma_chan strcture represetation for mid chan
- * @ch_regs: MMIO register space pointer to channel register
- * @dma_base: MMIO register space DMA engine base pointer
- * @ch_id: DMA channel id
- * @lock: channel spinlock
- * @active_list: current active descriptors
- * @queue: current queued up descriptors
- * @free_list: current free descriptors
- * @slave: dma slave structure
- * @descs_allocated: total number of descriptors allocated
- * @dma: dma device structure pointer
- * @busy: bool representing if ch is busy (active txn) or not
- * @in_use: bool representing if ch is in use or not
- * @raw_tfr: raw trf interrupt received
- * @raw_block: raw block interrupt received
- */
-struct intel_mid_dma_chan {
-       struct dma_chan         chan;
-       void __iomem            *ch_regs;
-       void __iomem            *dma_base;
-       int                     ch_id;
-       spinlock_t              lock;
-       struct list_head        active_list;
-       struct list_head        queue;
-       struct list_head        free_list;
-       unsigned int            descs_allocated;
-       struct middma_device    *dma;
-       bool                    busy;
-       bool                    in_use;
-       u32                     raw_tfr;
-       u32                     raw_block;
-       struct intel_mid_dma_slave *mid_slave;
-};
-
-static inline struct intel_mid_dma_chan *to_intel_mid_dma_chan(
-                                               struct dma_chan *chan)
-{
-       return container_of(chan, struct intel_mid_dma_chan, chan);
-}
-
-enum intel_mid_dma_state {
-       RUNNING = 0,
-       SUSPENDED,
-};
-/**
- * struct middma_device - internal representation of a DMA device
- * @pdev: PCI device
- * @dma_base: MMIO register space pointer of DMA
- * @dma_pool: for allocating DMA descriptors
- * @common: embedded struct dma_device
- * @tasklet: dma tasklet for processing interrupts
- * @ch: per channel data
- * @pci_id: DMA device PCI ID
- * @intr_mask: Interrupt mask to be used
- * @mask_reg: MMIO register for periphral mask
- * @chan_base: Base ch index (read from driver data)
- * @max_chan: max number of chs supported (from drv_data)
- * @block_size: Block size of DMA transfer supported (from drv_data)
- * @pimr_mask: MMIO register addr for periphral interrupt (from drv_data)
- * @state: dma PM device state
- */
-struct middma_device {
-       struct pci_dev          *pdev;
-       void __iomem            *dma_base;
-       struct pci_pool         *dma_pool;
-       struct dma_device       common;
-       struct tasklet_struct   tasklet;
-       struct intel_mid_dma_chan ch[MAX_CHAN];
-       unsigned int            pci_id;
-       unsigned int            intr_mask;
-       void __iomem            *mask_reg;
-       int                     chan_base;
-       int                     max_chan;
-       int                     block_size;
-       unsigned int            pimr_mask;
-       enum intel_mid_dma_state state;
-};
-
-static inline struct middma_device *to_middma_device(struct dma_device *common)
-{
-       return container_of(common, struct middma_device, common);
-}
-
-struct intel_mid_dma_desc {
-       void __iomem                    *block; /*ch ptr*/
-       struct list_head                desc_node;
-       struct dma_async_tx_descriptor  txd;
-       size_t                          len;
-       dma_addr_t                      sar;
-       dma_addr_t                      dar;
-       u32                             cfg_hi;
-       u32                             cfg_lo;
-       u32                             ctl_lo;
-       u32                             ctl_hi;
-       struct pci_pool                 *lli_pool;
-       struct intel_mid_dma_lli        *lli;
-       dma_addr_t                      lli_phys;
-       unsigned int                    lli_length;
-       unsigned int                    current_lli;
-       dma_addr_t                      next;
-       enum dma_transfer_direction             dirn;
-       enum dma_status                 status;
-       enum dma_slave_buswidth         width; /*width of DMA txn*/
-       enum intel_mid_dma_mode         cfg_mode; /*mode configuration*/
-
-};
-
-struct intel_mid_dma_lli {
-       dma_addr_t                      sar;
-       dma_addr_t                      dar;
-       dma_addr_t                      llp;
-       u32                             ctl_lo;
-       u32                             ctl_hi;
-} __attribute__ ((packed));
-
-static inline int test_ch_en(void __iomem *dma, u32 ch_no)
-{
-       u32 en_reg = ioread32(dma + DMA_CHAN_EN);
-       return (en_reg >> ch_no) & 0x1;
-}
-
-static inline struct intel_mid_dma_desc *to_intel_mid_dma_desc
-               (struct dma_async_tx_descriptor *txd)
-{
-       return container_of(txd, struct intel_mid_dma_desc, txd);
-}
-
-static inline struct intel_mid_dma_slave *to_intel_mid_dma_slave
-               (struct dma_slave_config *slave)
-{
-       return container_of(slave, struct intel_mid_dma_slave, dma_slave);
-}
-
-
-int dma_resume(struct device *dev);
-
-#endif /*__INTEL_MID_DMAC_REGS_H__*/
index 68aca3334a17e4fcc9fba62af4e89f082d5c681f..1332b1d4d541cb37c99f4a4ada988f3cbaee0f7f 100644 (file)
@@ -3548,7 +3548,7 @@ static int __init d40_probe(struct platform_device *pdev)
 
        if (!plat_data) {
                if (np) {
-                       if(d40_of_probe(pdev, np)) {
+                       if (d40_of_probe(pdev, np)) {
                                ret = -ENOMEM;
                                goto failure;
                        }
index 5907c1718f8c74fbe4a7d2c3bceb21759ed07422..92772fffc52ff292fc38e8acd09bf0002d332c8b 100644 (file)
@@ -20,8 +20,7 @@ static struct msr __percpu *msrs;
  */
 static atomic_t drv_instances = ATOMIC_INIT(0);
 
-/* Per-node driver instances */
-static struct mem_ctl_info **mcis;
+/* Per-node stuff */
 static struct ecc_settings **ecc_stngs;
 
 /*
@@ -903,9 +902,17 @@ static int k8_early_channel_count(struct amd64_pvt *pvt)
 /* On F10h and later ErrAddr is MC4_ADDR[47:1] */
 static u64 get_error_address(struct amd64_pvt *pvt, struct mce *m)
 {
-       u64 addr;
+       u16 mce_nid = amd_get_nb_id(m->extcpu);
+       struct mem_ctl_info *mci;
        u8 start_bit = 1;
        u8 end_bit   = 47;
+       u64 addr;
+
+       mci = edac_mc_find(mce_nid);
+       if (!mci)
+               return 0;
+
+       pvt = mci->pvt_info;
 
        if (pvt->fam == 0xf) {
                start_bit = 3;
@@ -918,17 +925,13 @@ static u64 get_error_address(struct amd64_pvt *pvt, struct mce *m)
         * Erratum 637 workaround
         */
        if (pvt->fam == 0x15) {
-               struct amd64_pvt *pvt;
                u64 cc6_base, tmp_addr;
                u32 tmp;
-               u16 mce_nid;
                u8 intlv_en;
 
                if ((addr & GENMASK_ULL(47, 24)) >> 24 != 0x00fdf7)
                        return addr;
 
-               mce_nid = amd_get_nb_id(m->extcpu);
-               pvt     = mcis[mce_nid]->pvt_info;
 
                amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_LIM, &tmp);
                intlv_en = tmp >> 21 & 0x7;
@@ -1511,7 +1514,7 @@ static int f1x_lookup_addr_in_dct(u64 in_addr, u8 nid, u8 dct)
        int cs_found = -EINVAL;
        int csrow;
 
-       mci = mcis[nid];
+       mci = edac_mc_find(nid);
        if (!mci)
                return cs_found;
 
@@ -2663,34 +2666,6 @@ static bool ecc_enabled(struct pci_dev *F3, u16 nid)
        return true;
 }
 
-static int set_mc_sysfs_attrs(struct mem_ctl_info *mci)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-       int rc;
-
-       rc = amd64_create_sysfs_dbg_files(mci);
-       if (rc < 0)
-               return rc;
-
-       if (pvt->fam >= 0x10) {
-               rc = amd64_create_sysfs_inject_files(mci);
-               if (rc < 0)
-                       return rc;
-       }
-
-       return 0;
-}
-
-static void del_mc_sysfs_attrs(struct mem_ctl_info *mci)
-{
-       struct amd64_pvt *pvt = mci->pvt_info;
-
-       amd64_remove_sysfs_dbg_files(mci);
-
-       if (pvt->fam >= 0x10)
-               amd64_remove_sysfs_inject_files(mci);
-}
-
 static void setup_mci_misc_attrs(struct mem_ctl_info *mci,
                                 struct amd64_family_type *fam)
 {
@@ -2778,6 +2753,16 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt)
        return fam_type;
 }
 
+static const struct attribute_group *amd64_edac_attr_groups[] = {
+#ifdef CONFIG_EDAC_DEBUG
+       &amd64_edac_dbg_group,
+#endif
+#ifdef CONFIG_EDAC_AMD64_ERROR_INJECTION
+       &amd64_edac_inj_group,
+#endif
+       NULL
+};
+
 static int init_one_instance(struct pci_dev *F2)
 {
        struct amd64_pvt *pvt = NULL;
@@ -2844,14 +2829,10 @@ static int init_one_instance(struct pci_dev *F2)
                mci->edac_cap = EDAC_FLAG_NONE;
 
        ret = -ENODEV;
-       if (edac_mc_add_mc(mci)) {
+       if (edac_mc_add_mc_with_groups(mci, amd64_edac_attr_groups)) {
                edac_dbg(1, "failed edac_mc_add_mc()\n");
                goto err_add_mc;
        }
-       if (set_mc_sysfs_attrs(mci)) {
-               edac_dbg(1, "failed edac_mc_add_mc()\n");
-               goto err_add_sysfs;
-       }
 
        /* register stuff with EDAC MCE */
        if (report_gart_errors)
@@ -2859,14 +2840,10 @@ static int init_one_instance(struct pci_dev *F2)
 
        amd_register_ecc_decoder(decode_bus_error);
 
-       mcis[nid] = mci;
-
        atomic_inc(&drv_instances);
 
        return 0;
 
-err_add_sysfs:
-       edac_mc_del_mc(mci->pdev);
 err_add_mc:
        edac_mc_free(mci);
 
@@ -2940,7 +2917,6 @@ static void remove_one_instance(struct pci_dev *pdev)
        mci = find_mci_by_dev(&pdev->dev);
        WARN_ON(!mci);
 
-       del_mc_sysfs_attrs(mci);
        /* Remove from EDAC CORE tracking list */
        mci = edac_mc_del_mc(&pdev->dev);
        if (!mci)
@@ -2961,7 +2937,6 @@ static void remove_one_instance(struct pci_dev *pdev)
 
        /* Free the EDAC CORE resources */
        mci->pvt_info = NULL;
-       mcis[nid] = NULL;
 
        kfree(pvt);
        edac_mc_free(mci);
@@ -2999,7 +2974,7 @@ static void setup_pci_device(void)
        if (pci_ctl)
                return;
 
-       mci = mcis[0];
+       mci = edac_mc_find(0);
        if (!mci)
                return;
 
@@ -3023,9 +2998,8 @@ static int __init amd64_edac_init(void)
                goto err_ret;
 
        err = -ENOMEM;
-       mcis      = kzalloc(amd_nb_num() * sizeof(mcis[0]), GFP_KERNEL);
        ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL);
-       if (!(mcis && ecc_stngs))
+       if (!ecc_stngs)
                goto err_free;
 
        msrs = msrs_alloc();
@@ -3056,9 +3030,6 @@ err_pci:
        msrs = NULL;
 
 err_free:
-       kfree(mcis);
-       mcis = NULL;
-
        kfree(ecc_stngs);
        ecc_stngs = NULL;
 
@@ -3076,9 +3047,6 @@ static void __exit amd64_edac_exit(void)
        kfree(ecc_stngs);
        ecc_stngs = NULL;
 
-       kfree(mcis);
-       mcis = NULL;
-
        msrs_free(msrs);
        msrs = NULL;
 }
index d8468c6679257b26b0157da63fd1d6bdd0633ba4..4bdec752d33096bfdfa9c5c201c81dba3c217af8 100644 (file)
@@ -453,31 +453,11 @@ struct ecc_settings {
 };
 
 #ifdef CONFIG_EDAC_DEBUG
-int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci);
-void amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci);
-
-#else
-static inline int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci)
-{
-       return 0;
-}
-static void inline amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci)
-{
-}
+extern const struct attribute_group amd64_edac_dbg_group;
 #endif
 
 #ifdef CONFIG_EDAC_AMD64_ERROR_INJECTION
-int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci);
-void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci);
-
-#else
-static inline int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci)
-{
-       return 0;
-}
-static inline void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci)
-{
-}
+extern const struct attribute_group amd64_edac_inj_group;
 #endif
 
 /*
index 2c1bbf7406058f4f80e1edb170db160c488cdcbc..4709c60798482e1e0b276ef35d810a30801111d4 100644 (file)
@@ -40,34 +40,15 @@ static DEVICE_ATTR(topmem, S_IRUGO, amd64_top_mem_show, NULL);
 static DEVICE_ATTR(topmem2, S_IRUGO, amd64_top_mem2_show, NULL);
 static DEVICE_ATTR(dram_hole, S_IRUGO, amd64_hole_show, NULL);
 
-int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci)
-{
-       int rc;
-
-       rc = device_create_file(&mci->dev, &dev_attr_dhar);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_dbam);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_topmem);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_topmem2);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_dram_hole);
-       if (rc < 0)
-               return rc;
-
-       return 0;
-}
-
-void amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci)
-{
-       device_remove_file(&mci->dev, &dev_attr_dhar);
-       device_remove_file(&mci->dev, &dev_attr_dbam);
-       device_remove_file(&mci->dev, &dev_attr_topmem);
-       device_remove_file(&mci->dev, &dev_attr_topmem2);
-       device_remove_file(&mci->dev, &dev_attr_dram_hole);
-}
+static struct attribute *amd64_edac_dbg_attrs[] = {
+       &dev_attr_dhar.attr,
+       &dev_attr_dbam.attr,
+       &dev_attr_topmem.attr,
+       &dev_attr_topmem2.attr,
+       &dev_attr_dram_hole.attr,
+       NULL
+};
+
+const struct attribute_group amd64_edac_dbg_group = {
+       .attrs = amd64_edac_dbg_attrs,
+};
index 0d66ae68d4681a9bb1ceedfca97fcafbde144d2c..e14977ff95dbb49dcd1038018091f37561cf86d4 100644 (file)
@@ -207,35 +207,28 @@ static DEVICE_ATTR(inject_write, S_IWUSR,
 static DEVICE_ATTR(inject_read,  S_IWUSR,
                   NULL, amd64_inject_read_store);
 
-
-int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci)
+static struct attribute *amd64_edac_inj_attrs[] = {
+       &dev_attr_inject_section.attr,
+       &dev_attr_inject_word.attr,
+       &dev_attr_inject_ecc_vector.attr,
+       &dev_attr_inject_write.attr,
+       &dev_attr_inject_read.attr,
+       NULL
+};
+
+static umode_t amd64_edac_inj_is_visible(struct kobject *kobj,
+                                        struct attribute *attr, int idx)
 {
-       int rc;
-
-       rc = device_create_file(&mci->dev, &dev_attr_inject_section);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_inject_word);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_inject_ecc_vector);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_inject_write);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_inject_read);
-       if (rc < 0)
-               return rc;
-
-       return 0;
-}
+       struct device *dev = kobj_to_dev(kobj);
+       struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev);
+       struct amd64_pvt *pvt = mci->pvt_info;
 
-void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci)
-{
-       device_remove_file(&mci->dev, &dev_attr_inject_section);
-       device_remove_file(&mci->dev, &dev_attr_inject_word);
-       device_remove_file(&mci->dev, &dev_attr_inject_ecc_vector);
-       device_remove_file(&mci->dev, &dev_attr_inject_write);
-       device_remove_file(&mci->dev, &dev_attr_inject_read);
+       if (pvt->fam < 0x10)
+               return 0;
+       return attr->mode;
 }
+
+const struct attribute_group amd64_edac_inj_group = {
+       .attrs = amd64_edac_inj_attrs,
+       .is_visible = amd64_edac_inj_is_visible,
+};
index 6c9f381e8fe6731d0c9c02bce1c793b0f0c302b7..ad42587c3f4d6e60d25ccb49fd9550b3341e6984 100644 (file)
@@ -446,7 +446,9 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
                                   unsigned n_layers,
                                   struct edac_mc_layer *layers,
                                   unsigned sz_pvt);
-extern int edac_mc_add_mc(struct mem_ctl_info *mci);
+extern int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
+                                     const struct attribute_group **groups);
+#define edac_mc_add_mc(mci)    edac_mc_add_mc_with_groups(mci, NULL)
 extern void edac_mc_free(struct mem_ctl_info *mci);
 extern struct mem_ctl_info *edac_mc_find(int idx);
 extern struct mem_ctl_info *find_mci_by_dev(struct device *dev);
index 1747906f10cedcd2f9b528065b4ae139fc34fdb4..af3be1914dbb8f85496473c4c3c5977edd0ed17a 100644 (file)
@@ -710,9 +710,10 @@ struct mem_ctl_info *edac_mc_find(int idx)
 EXPORT_SYMBOL(edac_mc_find);
 
 /**
- * edac_mc_add_mc: Insert the 'mci' structure into the mci global list and
- *                 create sysfs entries associated with mci structure
+ * edac_mc_add_mc_with_groups: Insert the 'mci' structure into the mci
+ *     global list and create sysfs entries associated with mci structure
  * @mci: pointer to the mci structure to be added to the list
+ * @groups: optional attribute groups for the driver-specific sysfs entries
  *
  * Return:
  *     0       Success
@@ -720,7 +721,8 @@ EXPORT_SYMBOL(edac_mc_find);
  */
 
 /* FIXME - should a warning be printed if no error detection? correction? */
-int edac_mc_add_mc(struct mem_ctl_info *mci)
+int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
+                              const struct attribute_group **groups)
 {
        int ret = -EINVAL;
        edac_dbg(0, "\n");
@@ -771,7 +773,7 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
 
        mci->bus = &mc_bus[mci->mc_idx];
 
-       if (edac_create_sysfs_mci_device(mci)) {
+       if (edac_create_sysfs_mci_device(mci, groups)) {
                edac_mc_printk(mci, KERN_WARNING,
                        "failed to create sysfs device\n");
                goto fail1;
@@ -805,7 +807,7 @@ fail0:
        mutex_unlock(&mem_ctls_mutex);
        return ret;
 }
-EXPORT_SYMBOL_GPL(edac_mc_add_mc);
+EXPORT_SYMBOL_GPL(edac_mc_add_mc_with_groups);
 
 /**
  * edac_mc_del_mc: Remove sysfs entries for specified mci structure and
index c84eecb191ef2a14364a57370bb1b6952bb9bcb6..112d63ad115470529c18e3c6d876cfdda000a9e5 100644 (file)
@@ -323,13 +323,14 @@ DEVICE_CHANNEL(ch5_dimm_label, S_IRUGO | S_IWUSR,
        channel_dimm_label_show, channel_dimm_label_store, 5);
 
 /* Total possible dynamic DIMM Label attribute file table */
-static struct device_attribute *dynamic_csrow_dimm_attr[] = {
-       &dev_attr_legacy_ch0_dimm_label.attr,
-       &dev_attr_legacy_ch1_dimm_label.attr,
-       &dev_attr_legacy_ch2_dimm_label.attr,
-       &dev_attr_legacy_ch3_dimm_label.attr,
-       &dev_attr_legacy_ch4_dimm_label.attr,
-       &dev_attr_legacy_ch5_dimm_label.attr
+static struct attribute *dynamic_csrow_dimm_attr[] = {
+       &dev_attr_legacy_ch0_dimm_label.attr.attr,
+       &dev_attr_legacy_ch1_dimm_label.attr.attr,
+       &dev_attr_legacy_ch2_dimm_label.attr.attr,
+       &dev_attr_legacy_ch3_dimm_label.attr.attr,
+       &dev_attr_legacy_ch4_dimm_label.attr.attr,
+       &dev_attr_legacy_ch5_dimm_label.attr.attr,
+       NULL
 };
 
 /* possible dynamic channel ce_count attribute files */
@@ -347,13 +348,45 @@ DEVICE_CHANNEL(ch5_ce_count, S_IRUGO,
                   channel_ce_count_show, NULL, 5);
 
 /* Total possible dynamic ce_count attribute file table */
-static struct device_attribute *dynamic_csrow_ce_count_attr[] = {
-       &dev_attr_legacy_ch0_ce_count.attr,
-       &dev_attr_legacy_ch1_ce_count.attr,
-       &dev_attr_legacy_ch2_ce_count.attr,
-       &dev_attr_legacy_ch3_ce_count.attr,
-       &dev_attr_legacy_ch4_ce_count.attr,
-       &dev_attr_legacy_ch5_ce_count.attr
+static struct attribute *dynamic_csrow_ce_count_attr[] = {
+       &dev_attr_legacy_ch0_ce_count.attr.attr,
+       &dev_attr_legacy_ch1_ce_count.attr.attr,
+       &dev_attr_legacy_ch2_ce_count.attr.attr,
+       &dev_attr_legacy_ch3_ce_count.attr.attr,
+       &dev_attr_legacy_ch4_ce_count.attr.attr,
+       &dev_attr_legacy_ch5_ce_count.attr.attr,
+       NULL
+};
+
+static umode_t csrow_dev_is_visible(struct kobject *kobj,
+                                   struct attribute *attr, int idx)
+{
+       struct device *dev = kobj_to_dev(kobj);
+       struct csrow_info *csrow = container_of(dev, struct csrow_info, dev);
+
+       if (idx >= csrow->nr_channels)
+               return 0;
+       /* Only expose populated DIMMs */
+       if (!csrow->channels[idx]->dimm->nr_pages)
+               return 0;
+       return attr->mode;
+}
+
+
+static const struct attribute_group csrow_dev_dimm_group = {
+       .attrs = dynamic_csrow_dimm_attr,
+       .is_visible = csrow_dev_is_visible,
+};
+
+static const struct attribute_group csrow_dev_ce_count_group = {
+       .attrs = dynamic_csrow_ce_count_attr,
+       .is_visible = csrow_dev_is_visible,
+};
+
+static const struct attribute_group *csrow_dev_groups[] = {
+       &csrow_dev_dimm_group,
+       &csrow_dev_ce_count_group,
+       NULL
 };
 
 static inline int nr_pages_per_csrow(struct csrow_info *csrow)
@@ -370,13 +403,12 @@ static inline int nr_pages_per_csrow(struct csrow_info *csrow)
 static int edac_create_csrow_object(struct mem_ctl_info *mci,
                                    struct csrow_info *csrow, int index)
 {
-       int err, chan;
-
        if (csrow->nr_channels > EDAC_NR_CHANNELS)
                return -ENODEV;
 
        csrow->dev.type = &csrow_attr_type;
        csrow->dev.bus = mci->bus;
+       csrow->dev.groups = csrow_dev_groups;
        device_initialize(&csrow->dev);
        csrow->dev.parent = &mci->dev;
        csrow->mci = mci;
@@ -386,45 +418,13 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
        edac_dbg(0, "creating (virtual) csrow node %s\n",
                 dev_name(&csrow->dev));
 
-       err = device_add(&csrow->dev);
-       if (err < 0)
-               return err;
-
-       for (chan = 0; chan < csrow->nr_channels; chan++) {
-               /* Only expose populated DIMMs */
-               if (!csrow->channels[chan]->dimm->nr_pages)
-                       continue;
-               err = device_create_file(&csrow->dev,
-                                        dynamic_csrow_dimm_attr[chan]);
-               if (err < 0)
-                       goto error;
-               err = device_create_file(&csrow->dev,
-                                        dynamic_csrow_ce_count_attr[chan]);
-               if (err < 0) {
-                       device_remove_file(&csrow->dev,
-                                          dynamic_csrow_dimm_attr[chan]);
-                       goto error;
-               }
-       }
-
-       return 0;
-
-error:
-       for (--chan; chan >= 0; chan--) {
-               device_remove_file(&csrow->dev,
-                                       dynamic_csrow_dimm_attr[chan]);
-               device_remove_file(&csrow->dev,
-                                          dynamic_csrow_ce_count_attr[chan]);
-       }
-       put_device(&csrow->dev);
-
-       return err;
+       return device_add(&csrow->dev);
 }
 
 /* Create a CSROW object under specifed edac_mc_device */
 static int edac_create_csrow_objects(struct mem_ctl_info *mci)
 {
-       int err, i, chan;
+       int err, i;
        struct csrow_info *csrow;
 
        for (i = 0; i < mci->nr_csrows; i++) {
@@ -446,14 +446,6 @@ error:
                csrow = mci->csrows[i];
                if (!nr_pages_per_csrow(csrow))
                        continue;
-               for (chan = csrow->nr_channels - 1; chan >= 0; chan--) {
-                       if (!csrow->channels[chan]->dimm->nr_pages)
-                               continue;
-                       device_remove_file(&csrow->dev,
-                                               dynamic_csrow_dimm_attr[chan]);
-                       device_remove_file(&csrow->dev,
-                                               dynamic_csrow_ce_count_attr[chan]);
-               }
                put_device(&mci->csrows[i]->dev);
        }
 
@@ -462,23 +454,13 @@ error:
 
 static void edac_delete_csrow_objects(struct mem_ctl_info *mci)
 {
-       int i, chan;
+       int i;
        struct csrow_info *csrow;
 
        for (i = mci->nr_csrows - 1; i >= 0; i--) {
                csrow = mci->csrows[i];
                if (!nr_pages_per_csrow(csrow))
                        continue;
-               for (chan = csrow->nr_channels - 1; chan >= 0; chan--) {
-                       if (!csrow->channels[chan]->dimm->nr_pages)
-                               continue;
-                       edac_dbg(1, "Removing csrow %d channel %d sysfs nodes\n",
-                                i, chan);
-                       device_remove_file(&csrow->dev,
-                                               dynamic_csrow_dimm_attr[chan]);
-                       device_remove_file(&csrow->dev,
-                                               dynamic_csrow_ce_count_attr[chan]);
-               }
                device_unregister(&mci->csrows[i]->dev);
        }
 }
@@ -863,7 +845,8 @@ static DEVICE_ATTR(ce_count, S_IRUGO, mci_ce_count_show, NULL);
 static DEVICE_ATTR(max_location, S_IRUGO, mci_max_location_show, NULL);
 
 /* memory scrubber attribute file */
-static DEVICE_ATTR(sdram_scrub_rate, 0, NULL, NULL);
+DEVICE_ATTR(sdram_scrub_rate, 0, mci_sdram_scrub_rate_show,
+           mci_sdram_scrub_rate_store); /* umode set later in is_visible */
 
 static struct attribute *mci_attrs[] = {
        &dev_attr_reset_counters.attr,
@@ -875,11 +858,29 @@ static struct attribute *mci_attrs[] = {
        &dev_attr_ue_count.attr,
        &dev_attr_ce_count.attr,
        &dev_attr_max_location.attr,
+       &dev_attr_sdram_scrub_rate.attr,
        NULL
 };
 
+static umode_t mci_attr_is_visible(struct kobject *kobj,
+                                  struct attribute *attr, int idx)
+{
+       struct device *dev = kobj_to_dev(kobj);
+       struct mem_ctl_info *mci = to_mci(dev);
+       umode_t mode = 0;
+
+       if (attr != &dev_attr_sdram_scrub_rate.attr)
+               return attr->mode;
+       if (mci->get_sdram_scrub_rate)
+               mode |= S_IRUGO;
+       if (mci->set_sdram_scrub_rate)
+               mode |= S_IWUSR;
+       return mode;
+}
+
 static struct attribute_group mci_attr_grp = {
        .attrs  = mci_attrs,
+       .is_visible = mci_attr_is_visible,
 };
 
 static const struct attribute_group *mci_attr_groups[] = {
@@ -913,7 +914,7 @@ int __init edac_debugfs_init(void)
        return 0;
 }
 
-void __exit edac_debugfs_exit(void)
+void edac_debugfs_exit(void)
 {
        debugfs_remove(edac_debugfs);
 }
@@ -973,7 +974,8 @@ nomem:
  *     0       Success
  *     !0      Failure
  */
-int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
+int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
+                                const struct attribute_group **groups)
 {
        int i, err;
 
@@ -997,6 +999,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
 
        mci->dev.parent = mci_pdev;
        mci->dev.bus = mci->bus;
+       mci->dev.groups = groups;
        dev_set_name(&mci->dev, "mc%d", mci->mc_idx);
        dev_set_drvdata(&mci->dev, mci);
        pm_runtime_forbid(&mci->dev);
@@ -1008,23 +1011,6 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
                goto fail_unregister_bus;
        }
 
-       if (mci->set_sdram_scrub_rate || mci->get_sdram_scrub_rate) {
-               if (mci->get_sdram_scrub_rate) {
-                       dev_attr_sdram_scrub_rate.attr.mode |= S_IRUGO;
-                       dev_attr_sdram_scrub_rate.show = &mci_sdram_scrub_rate_show;
-               }
-
-               if (mci->set_sdram_scrub_rate) {
-                       dev_attr_sdram_scrub_rate.attr.mode |= S_IWUSR;
-                       dev_attr_sdram_scrub_rate.store = &mci_sdram_scrub_rate_store;
-               }
-
-               err = device_create_file(&mci->dev, &dev_attr_sdram_scrub_rate);
-               if (err) {
-                       edac_dbg(1, "failure: create sdram_scrub_rate\n");
-                       goto fail_unregister_dev;
-               }
-       }
        /*
         * Create the dimm/rank devices
         */
@@ -1071,7 +1057,6 @@ fail_unregister_dimm:
 
                device_unregister(&dimm->dev);
        }
-fail_unregister_dev:
        device_unregister(&mci->dev);
 fail_unregister_bus:
        bus_unregister(mci->bus);
@@ -1170,7 +1155,7 @@ int __init edac_mc_sysfs_init(void)
        return err;
 }
 
-void __exit edac_mc_sysfs_exit(void)
+void edac_mc_sysfs_exit(void)
 {
        device_unregister(mci_pdev);
        edac_put_sysfs_subsys();
index e6d1691dfa45f310d7f7cbec0b8f391836daff22..9cb082a19d8a7ae2fbd7a2ae146bd3cd98a59618 100644 (file)
@@ -112,20 +112,23 @@ static int __init edac_init(void)
 
        err = edac_mc_sysfs_init();
        if (err)
-               goto error;
+               goto err_sysfs;
 
        edac_debugfs_init();
 
-       /* Setup/Initialize the workq for this core */
        err = edac_workqueue_setup();
        if (err) {
-               edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
-               goto error;
+               edac_printk(KERN_ERR, EDAC_MC, "Failure initializing workqueue\n");
+               goto err_wq;
        }
 
        return 0;
 
-error:
+err_wq:
+       edac_debugfs_exit();
+       edac_mc_sysfs_exit();
+
+err_sysfs:
        return err;
 }
 
index f2118bfcf8dfbd861d24754320ac0a0439cfb9ed..26ecc52e073d8b5dc246aa2897cd59fdf54700ad 100644 (file)
@@ -22,7 +22,8 @@
        /* on edac_mc_sysfs.c */
 int edac_mc_sysfs_init(void);
 void edac_mc_sysfs_exit(void);
-extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci);
+extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
+                                       const struct attribute_group **groups);
 extern void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci);
 void edac_unregister_sysfs(struct mem_ctl_info *mci);
 extern int edac_get_log_ue(void);
index f784de1dc7937f097265050b3336bcebf4534ef7..11260cc3360e44b8105f0351fd198026d205c685 100644 (file)
@@ -124,6 +124,13 @@ static ssize_t highbank_mc_inject_ctrl(struct device *dev,
 
 static DEVICE_ATTR(inject_ctrl, S_IWUSR, NULL, highbank_mc_inject_ctrl);
 
+static struct attribute *highbank_dev_attrs[] = {
+       &dev_attr_inject_ctrl.attr,
+       NULL
+};
+
+ATTRIBUTE_GROUPS(highbank_dev);
+
 struct hb_mc_settings {
        int     err_offset;
        int     int_offset;
@@ -139,7 +146,7 @@ static struct hb_mc_settings mw_settings = {
        .int_offset = MW_DDR_ECC_INT_BASE,
 };
 
-static struct of_device_id hb_ddr_ctrl_of_match[] = {
+static const struct of_device_id hb_ddr_ctrl_of_match[] = {
        { .compatible = "calxeda,hb-ddr-ctrl",          .data = &hb_settings },
        { .compatible = "calxeda,ecx-2000-ddr-ctrl",    .data = &mw_settings },
        {},
@@ -231,7 +238,7 @@ static int highbank_mc_probe(struct platform_device *pdev)
        dimm->mtype = MEM_DDR3;
        dimm->edac_mode = EDAC_SECDED;
 
-       res = edac_mc_add_mc(mci);
+       res = edac_mc_add_mc_with_groups(mci, highbank_dev_groups);
        if (res < 0)
                goto err;
 
@@ -243,8 +250,6 @@ static int highbank_mc_probe(struct platform_device *pdev)
                goto err2;
        }
 
-       device_create_file(&mci->dev, &dev_attr_inject_ctrl);
-
        devres_close_group(&pdev->dev, NULL);
        return 0;
 err2:
@@ -259,7 +264,6 @@ static int highbank_mc_remove(struct platform_device *pdev)
 {
        struct mem_ctl_info *mci = platform_get_drvdata(pdev);
 
-       device_remove_file(&mci->dev, &dev_attr_inject_ctrl);
        edac_mc_del_mc(&pdev->dev);
        edac_mc_free(mci);
        return 0;
index 9cd0b301f81ba5a5a3fb52dfcc87ef337d7bcb41..01087a38da226d08bd7e08da5a183885fbf420b1 100644 (file)
@@ -1157,27 +1157,24 @@ static DEVICE_ATTR(inject_eccmask, S_IRUGO | S_IWUSR,
 static DEVICE_ATTR(inject_enable, S_IRUGO | S_IWUSR,
                   i7core_inject_enable_show, i7core_inject_enable_store);
 
+static struct attribute *i7core_dev_attrs[] = {
+       &dev_attr_inject_section.attr,
+       &dev_attr_inject_type.attr,
+       &dev_attr_inject_eccmask.attr,
+       &dev_attr_inject_enable.attr,
+       NULL
+};
+
+ATTRIBUTE_GROUPS(i7core_dev);
+
 static int i7core_create_sysfs_devices(struct mem_ctl_info *mci)
 {
        struct i7core_pvt *pvt = mci->pvt_info;
        int rc;
 
-       rc = device_create_file(&mci->dev, &dev_attr_inject_section);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_inject_type);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_inject_eccmask);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_inject_enable);
-       if (rc < 0)
-               return rc;
-
        pvt->addrmatch_dev = kzalloc(sizeof(*pvt->addrmatch_dev), GFP_KERNEL);
        if (!pvt->addrmatch_dev)
-               return rc;
+               return -ENOMEM;
 
        pvt->addrmatch_dev->type = &addrmatch_type;
        pvt->addrmatch_dev->bus = mci->dev.bus;
@@ -1198,7 +1195,7 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci)
                if (!pvt->chancounts_dev) {
                        put_device(pvt->addrmatch_dev);
                        device_del(pvt->addrmatch_dev);
-                       return rc;
+                       return -ENOMEM;
                }
 
                pvt->chancounts_dev->type = &all_channel_counts_type;
@@ -1223,11 +1220,6 @@ static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci)
 
        edac_dbg(1, "\n");
 
-       device_remove_file(&mci->dev, &dev_attr_inject_section);
-       device_remove_file(&mci->dev, &dev_attr_inject_type);
-       device_remove_file(&mci->dev, &dev_attr_inject_eccmask);
-       device_remove_file(&mci->dev, &dev_attr_inject_enable);
-
        if (!pvt->is_registered) {
                put_device(pvt->chancounts_dev);
                device_del(pvt->chancounts_dev);
@@ -2259,7 +2251,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev)
                enable_sdram_scrub_setting(mci);
 
        /* add this new MC control structure to EDAC's list of MCs */
-       if (unlikely(edac_mc_add_mc(mci))) {
+       if (unlikely(edac_mc_add_mc_with_groups(mci, i7core_dev_groups))) {
                edac_dbg(0, "MC: failed edac_mc_add_mc()\n");
                /* FIXME: perhaps some code should go here that disables error
                 * reporting if we just enabled it
index b4705d9366bf33d3c6223aacf8f47b8461b25a59..4d4110364f021cc77dc699d2384a60ce88067b40 100644 (file)
@@ -350,8 +350,6 @@ fail:
        return -ENODEV;
 }
 
-EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_probe1);
-
 /* returns count (>= 0), or negative on error */
 static int i82443bxgx_edacmc_init_one(struct pci_dev *pdev,
                                      const struct pci_device_id *ent)
@@ -384,8 +382,6 @@ static void i82443bxgx_edacmc_remove_one(struct pci_dev *pdev)
        edac_mc_free(mci);
 }
 
-EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_remove_one);
-
 static const struct pci_device_id i82443bxgx_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2)},
@@ -445,9 +441,7 @@ fail1:
        pci_unregister_driver(&i82443bxgx_edacmc_driver);
 
 fail0:
-       if (mci_pdev != NULL)
-               pci_dev_put(mci_pdev);
-
+       pci_dev_put(mci_pdev);
        return pci_rc;
 }
 
index 4382343a7c60ed3cc4d5d1ea4f7661c62b1fe5bc..ee1078cd3b966a1b473ca76b164947177cd9fdbc 100644 (file)
@@ -343,20 +343,15 @@ fail1:
        pci_unregister_driver(&i82860_driver);
 
 fail0:
-       if (mci_pdev != NULL)
-               pci_dev_put(mci_pdev);
-
+       pci_dev_put(mci_pdev);
        return pci_rc;
 }
 
 static void __exit i82860_exit(void)
 {
        edac_dbg(3, "\n");
-
        pci_unregister_driver(&i82860_driver);
-
-       if (mci_pdev != NULL)
-               pci_dev_put(mci_pdev);
+       pci_dev_put(mci_pdev);
 }
 
 module_init(i82860_init);
index 64b68320249f0e5e05db5ef8a0eccc0a2925dade..c26a513f88697bf690f34e66ada74ec091ac764d 100644 (file)
@@ -576,9 +576,7 @@ fail1:
        pci_unregister_driver(&i82875p_driver);
 
 fail0:
-       if (mci_pdev != NULL)
-               pci_dev_put(mci_pdev);
-
+       pci_dev_put(mci_pdev);
        return pci_rc;
 }
 
index 10b10521f62e19a550479755ad41247683d336e6..35ab66c623a3061e4ab03de7221b4852fbd59f63 100644 (file)
@@ -685,9 +685,7 @@ fail1:
        pci_unregister_driver(&i82975x_driver);
 
 fail0:
-       if (mci_pdev != NULL)
-               pci_dev_put(mci_pdev);
-
+       pci_dev_put(mci_pdev);
        return pci_rc;
 }
 
index 1fa76a588af31ebec60889566a0a67eb4daa5a49..68bf234bdfe66c84d3d88d0fb339bb9fcbd451df 100644 (file)
@@ -134,29 +134,14 @@ DEVICE_ATTR(inject_data_lo, S_IRUGO | S_IWUSR,
 DEVICE_ATTR(inject_ctrl, S_IRUGO | S_IWUSR,
            mpc85xx_mc_inject_ctrl_show, mpc85xx_mc_inject_ctrl_store);
 
-static int mpc85xx_create_sysfs_attributes(struct mem_ctl_info *mci)
-{
-       int rc;
-
-       rc = device_create_file(&mci->dev, &dev_attr_inject_data_hi);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_inject_data_lo);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_inject_ctrl);
-       if (rc < 0)
-               return rc;
+static struct attribute *mpc85xx_dev_attrs[] = {
+       &dev_attr_inject_data_hi.attr,
+       &dev_attr_inject_data_lo.attr,
+       &dev_attr_inject_ctrl.attr,
+       NULL
+};
 
-       return 0;
-}
-
-static void mpc85xx_remove_sysfs_attributes(struct mem_ctl_info *mci)
-{
-       device_remove_file(&mci->dev, &dev_attr_inject_data_hi);
-       device_remove_file(&mci->dev, &dev_attr_inject_data_lo);
-       device_remove_file(&mci->dev, &dev_attr_inject_ctrl);
-}
+ATTRIBUTE_GROUPS(mpc85xx_dev);
 
 /**************************** PCI Err device ***************************/
 #ifdef CONFIG_PCI
@@ -685,7 +670,7 @@ static int mpc85xx_l2_err_remove(struct platform_device *op)
        return 0;
 }
 
-static struct of_device_id mpc85xx_l2_err_of_match[] = {
+static const struct of_device_id mpc85xx_l2_err_of_match[] = {
 /* deprecate the fsl,85.. forms in the future, 2.6.30? */
        { .compatible = "fsl,8540-l2-cache-controller", },
        { .compatible = "fsl,8541-l2-cache-controller", },
@@ -1106,13 +1091,7 @@ static int mpc85xx_mc_err_probe(struct platform_device *op)
        /* clear all error bits */
        out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, ~0);
 
-       if (edac_mc_add_mc(mci)) {
-               edac_dbg(3, "failed edac_mc_add_mc()\n");
-               goto err;
-       }
-
-       if (mpc85xx_create_sysfs_attributes(mci)) {
-               edac_mc_del_mc(mci->pdev);
+       if (edac_mc_add_mc_with_groups(mci, mpc85xx_dev_groups)) {
                edac_dbg(3, "failed edac_mc_add_mc()\n");
                goto err;
        }
@@ -1176,13 +1155,12 @@ static int mpc85xx_mc_err_remove(struct platform_device *op)
                 orig_ddr_err_disable);
        out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, orig_ddr_err_sbe);
 
-       mpc85xx_remove_sysfs_attributes(mci);
        edac_mc_del_mc(&op->dev);
        edac_mc_free(mci);
        return 0;
 }
 
-static struct of_device_id mpc85xx_mc_err_of_match[] = {
+static const struct of_device_id mpc85xx_mc_err_of_match[] = {
 /* deprecate the fsl,85.. forms in the future, 2.6.30? */
        { .compatible = "fsl,8540-memory-controller", },
        { .compatible = "fsl,8541-memory-controller", },
index 4bd10f94f0683a3c14e44f0fb8e5f41bb92ab83e..bb19e0732681ce6a4af6c2e980c0c4bb382889f9 100644 (file)
@@ -209,35 +209,18 @@ static DEVICE_ATTR(row, S_IRUGO | S_IWUSR,
 static DEVICE_ATTR(col, S_IRUGO | S_IWUSR,
                   octeon_mc_inject_col_show, octeon_mc_inject_col_store);
 
+static struct attribute *octeon_dev_attrs[] = {
+       &dev_attr_inject.attr,
+       &dev_attr_error_type.attr,
+       &dev_attr_dimm.attr,
+       &dev_attr_rank.attr,
+       &dev_attr_bank.attr,
+       &dev_attr_row.attr,
+       &dev_attr_col.attr,
+       NULL
+};
 
-static int octeon_set_mc_sysfs_attributes(struct mem_ctl_info *mci)
-{
-       int rc;
-
-       rc = device_create_file(&mci->dev, &dev_attr_inject);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_error_type);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_dimm);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_rank);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_bank);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_row);
-       if (rc < 0)
-               return rc;
-       rc = device_create_file(&mci->dev, &dev_attr_col);
-       if (rc < 0)
-               return rc;
-
-       return 0;
-}
+ATTRIBUTE_GROUPS(octeon_dev);
 
 static int octeon_lmc_edac_probe(struct platform_device *pdev)
 {
@@ -271,18 +254,12 @@ static int octeon_lmc_edac_probe(struct platform_device *pdev)
                mci->ctl_name = "octeon-lmc-err";
                mci->edac_check = octeon_lmc_edac_poll;
 
-               if (edac_mc_add_mc(mci)) {
+               if (edac_mc_add_mc_with_groups(mci, octeon_dev_groups)) {
                        dev_err(&pdev->dev, "edac_mc_add_mc() failed\n");
                        edac_mc_free(mci);
                        return -ENXIO;
                }
 
-               if (octeon_set_mc_sysfs_attributes(mci)) {
-                       dev_err(&pdev->dev, "octeon_set_mc_sysfs_attributes() failed\n");
-                       return -ENXIO;
-               }
-
-
                cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mc));
                cfg0.s.intr_ded_ena = 0;        /* We poll */
                cfg0.s.intr_sec_ena = 0;
@@ -309,18 +286,12 @@ static int octeon_lmc_edac_probe(struct platform_device *pdev)
                mci->ctl_name = "co_lmc_err";
                mci->edac_check = octeon_lmc_edac_poll_o2;
 
-               if (edac_mc_add_mc(mci)) {
+               if (edac_mc_add_mc_with_groups(mci, octeon_dev_groups)) {
                        dev_err(&pdev->dev, "edac_mc_add_mc() failed\n");
                        edac_mc_free(mci);
                        return -ENXIO;
                }
 
-               if (octeon_set_mc_sysfs_attributes(mci)) {
-                       dev_err(&pdev->dev, "octeon_set_mc_sysfs_attributes() failed\n");
-                       return -ENXIO;
-               }
-
-
                en.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mc));
                en.s.intr_ded_ena = 0;  /* We poll */
                en.s.intr_sec_ena = 0;
index 1b64fd06082171be84ab2ce41e6d3e293bd0984e..3515b381c1312612f56953bc267ee7d5d23b0f84 100644 (file)
@@ -193,7 +193,7 @@ static int ppc4xx_edac_remove(struct platform_device *device);
  * Device tree node type and compatible tuples this driver can match
  * on.
  */
-static struct of_device_id ppc4xx_edac_match[] = {
+static const struct of_device_id ppc4xx_edac_match[] = {
        {
                .compatible     = "ibm,sdram-4xx-ddr2"
        },
index 1c9691535e13ff7fd66a81662c5f363f71a406b2..fc153aea2f6cff1ce6b5043c11d4e16f24176ae0 100644 (file)
@@ -512,7 +512,7 @@ static int synps_edac_mc_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id synps_edac_match[] = {
+static const struct of_device_id synps_edac_match[] = {
        { .compatible = "xlnx,zynq-ddrc-a05", },
        { /* end of table */ }
 };
index 63f01c42aed486af8e3bd74b7f5c07dc0ee98ffd..6b5e795f3fe201cc0c29542a7ef61399fc4cb658 100644 (file)
@@ -1149,6 +1149,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
                }
                break;
        case WM5110:
+       case WM8280:
                switch (arizona->rev) {
                case 0 ... 2:
                        break;
index 2eebd28b4c40af2789c32e0008f2b60006fc03ac..6e45a43ffe8476686bcaee1157a7acc641fc3e6b 100644 (file)
@@ -17,7 +17,9 @@
  */
 static const char dmi_empty_string[] = "        ";
 
-static u16 __initdata dmi_ver;
+static u32 dmi_ver __initdata;
+static u32 dmi_len;
+static u16 dmi_num;
 /*
  * Catch too early calls to dmi_check_system():
  */
@@ -78,7 +80,7 @@ static const char * __init dmi_string(const struct dmi_header *dm, u8 s)
  *     We have to be cautious here. We have seen BIOSes with DMI pointers
  *     pointing to completely the wrong place for example
  */
-static void dmi_table(u8 *buf, u32 len, int num,
+static void dmi_table(u8 *buf,
                      void (*decode)(const struct dmi_header *, void *),
                      void *private_data)
 {
@@ -91,8 +93,8 @@ static void dmi_table(u8 *buf, u32 len, int num,
         * off the end of the table (should never happen but sometimes does
         * on bogus implementations.)
         */
-       while ((!num || i < num) &&
-              (data - buf + sizeof(struct dmi_header)) <= len) {
+       while ((!dmi_num || i < dmi_num) &&
+              (data - buf + sizeof(struct dmi_header)) <= dmi_len) {
                const struct dmi_header *dm = (const struct dmi_header *)data;
 
                /*
@@ -101,9 +103,9 @@ static void dmi_table(u8 *buf, u32 len, int num,
                 *  table in dmi_decode or dmi_string
                 */
                data += dm->length;
-               while ((data - buf < len - 1) && (data[0] || data[1]))
+               while ((data - buf < dmi_len - 1) && (data[0] || data[1]))
                        data++;
-               if (data - buf < len - 1)
+               if (data - buf < dmi_len - 1)
                        decode(dm, private_data);
 
                /*
@@ -118,8 +120,6 @@ static void dmi_table(u8 *buf, u32 len, int num,
 }
 
 static phys_addr_t dmi_base;
-static u32 dmi_len;
-static u16 dmi_num;
 
 static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
                void *))
@@ -130,7 +130,7 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
        if (buf == NULL)
                return -1;
 
-       dmi_table(buf, dmi_len, dmi_num, decode, NULL);
+       dmi_table(buf, decode, NULL);
 
        add_device_randomness(buf, dmi_len);
 
@@ -201,7 +201,7 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
         * the UUID are supposed to be little-endian encoded.  The specification
         * says that this is the defacto standard.
         */
-       if (dmi_ver >= 0x0206)
+       if (dmi_ver >= 0x020600)
                sprintf(s, "%pUL", d);
        else
                sprintf(s, "%pUB", d);
@@ -473,7 +473,7 @@ static void __init dmi_format_ids(char *buf, size_t len)
  */
 static int __init dmi_present(const u8 *buf)
 {
-       int smbios_ver;
+       u32 smbios_ver;
 
        if (memcmp(buf, "_SM_", 4) == 0 &&
            buf[5] < 32 && dmi_checksum(buf, buf[5])) {
@@ -506,14 +506,16 @@ static int __init dmi_present(const u8 *buf)
                if (dmi_walk_early(dmi_decode) == 0) {
                        if (smbios_ver) {
                                dmi_ver = smbios_ver;
-                               pr_info("SMBIOS %d.%d present.\n",
-                                      dmi_ver >> 8, dmi_ver & 0xFF);
+                               pr_info("SMBIOS %d.%d%s present.\n",
+                                       dmi_ver >> 8, dmi_ver & 0xFF,
+                                       (dmi_ver < 0x0300) ? "" : ".x");
                        } else {
                                dmi_ver = (buf[14] & 0xF0) << 4 |
                                           (buf[14] & 0x0F);
                                pr_info("Legacy DMI %d.%d present.\n",
                                       dmi_ver >> 8, dmi_ver & 0xFF);
                        }
+                       dmi_ver <<= 8;
                        dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
                        printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string);
                        return 0;
@@ -531,14 +533,16 @@ static int __init dmi_smbios3_present(const u8 *buf)
 {
        if (memcmp(buf, "_SM3_", 5) == 0 &&
            buf[6] < 32 && dmi_checksum(buf, buf[6])) {
-               dmi_ver = get_unaligned_be16(buf + 7);
+               dmi_ver = get_unaligned_be32(buf + 6);
+               dmi_ver &= 0xFFFFFF;
                dmi_num = 0;                    /* No longer specified */
                dmi_len = get_unaligned_le32(buf + 12);
                dmi_base = get_unaligned_le64(buf + 16);
 
                if (dmi_walk_early(dmi_decode) == 0) {
-                       pr_info("SMBIOS %d.%d present.\n",
-                               dmi_ver >> 8, dmi_ver & 0xFF);
+                       pr_info("SMBIOS %d.%d.%d present.\n",
+                               dmi_ver >> 16, (dmi_ver >> 8) & 0xFF,
+                               dmi_ver & 0xFF);
                        dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
                        pr_debug("DMI: %s\n", dmi_ids_string);
                        return 0;
@@ -893,7 +897,7 @@ int dmi_walk(void (*decode)(const struct dmi_header *, void *),
        if (buf == NULL)
                return -1;
 
-       dmi_table(buf, dmi_len, dmi_num, decode, private_data);
+       dmi_table(buf, decode, private_data);
 
        dmi_unmap(buf);
        return 0;
index dcae482a9a17c51a554e5928664e1b960b297588..e29560e6b40b0e5f28a141e7c88ceba1bdfa22ff 100644 (file)
@@ -175,7 +175,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
        unsigned long initrd_addr;
        u64 initrd_size = 0;
        unsigned long fdt_addr = 0;  /* Original DTB */
-       u64 fdt_size = 0;  /* We don't get size from configuration table */
+       unsigned long fdt_size = 0;
        char *cmdline_ptr = NULL;
        int cmdline_size = 0;
        unsigned long new_fdt_addr;
@@ -239,8 +239,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
        } else {
                status = handle_cmdline_files(sys_table, image, cmdline_ptr,
                                              "dtb=",
-                                             ~0UL, (unsigned long *)&fdt_addr,
-                                             (unsigned long *)&fdt_size);
+                                             ~0UL, &fdt_addr, &fdt_size);
 
                if (status != EFI_SUCCESS) {
                        pr_efi_err(sys_table, "Failed to load device tree!\n");
@@ -252,7 +251,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
                pr_efi(sys_table, "Using DTB from command line\n");
        } else {
                /* Look for a device tree configuration table entry. */
-               fdt_addr = (uintptr_t)get_fdt(sys_table);
+               fdt_addr = (uintptr_t)get_fdt(sys_table, &fdt_size);
                if (fdt_addr)
                        pr_efi(sys_table, "Using DTB from configuration table\n");
        }
index 47437b16b18697c2d624eadd8513d9bdfa8f5299..e334a01cf92f8243392ddd66616c8563306ccf5d 100644 (file)
@@ -41,7 +41,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
                                            unsigned long fdt_addr,
                                            unsigned long fdt_size);
 
-void *get_fdt(efi_system_table_t *sys_table);
+void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size);
 
 void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
                     unsigned long desc_size, efi_memory_desc_t *runtime_map,
index 91da56c4fd540cb5d381848e582f3f4453568af3..ef5d764e2a27ea506775e7c117dc291b9749ded1 100644 (file)
@@ -323,7 +323,7 @@ fail:
        return EFI_LOAD_ERROR;
 }
 
-void *get_fdt(efi_system_table_t *sys_table)
+void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size)
 {
        efi_guid_t fdt_guid = DEVICE_TREE_GUID;
        efi_config_table_t *tables;
@@ -336,6 +336,11 @@ void *get_fdt(efi_system_table_t *sys_table)
        for (i = 0; i < sys_table->nr_tables; i++)
                if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) {
                        fdt = (void *) tables[i].table;
+                       if (fdt_check_header(fdt) != 0) {
+                               pr_efi_err(sys_table, "Invalid header detected on UEFI supplied FDT, ignoring ...\n");
+                               return NULL;
+                       }
+                       *fdt_size = fdt_totalsize(fdt);
                        break;
         }
 
index fe369f5c7fa6d96c578ff202fcc6bab58bf0a5b2..9665d0aa4ebbf5352a3389fff9cb4bf75df49cce 100644 (file)
@@ -116,6 +116,7 @@ static int arizona_gpio_probe(struct platform_device *pdev)
        switch (arizona->type) {
        case WM5102:
        case WM5110:
+       case WM8280:
        case WM8997:
                arizona_gpio->gpio_chip.ngpio = 5;
                break;
index 679b10e34fb545f23c827f9699bfef1c9f4268bd..b6f076b213bcfde496a61824335b68d1760b5613 100644 (file)
@@ -2121,7 +2121,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
        connector = drm_connector_find(dev, out_resp->connector_id);
        if (!connector) {
                ret = -ENOENT;
-               goto out;
+               goto out_unlock;
        }
 
        for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
@@ -2201,6 +2201,8 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 
 out:
        drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+out_unlock:
        mutex_unlock(&dev->mode_config.mutex);
 
        return ret;
index 27cc95f363812516d4c2247b1253edbe19188938..ce3c42813fbbf4c917ba6e8f09de6e61fe83688a 100644 (file)
@@ -7,7 +7,6 @@
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM drm
-#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM)
 #define TRACE_INCLUDE_FILE drm_trace
 
 TRACE_EVENT(drm_vblank_event,
index cc6ea53d2b81951553d4b135a1760cb127e574c2..5c66b568bb8162345046fcce0118c5bf74eddc2f 100644 (file)
@@ -1095,6 +1095,7 @@ static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
        /* Gunit-Display CZ domain, 0x182028-0x1821CF */
        s->gu_ctl0              = I915_READ(VLV_GU_CTL0);
        s->gu_ctl1              = I915_READ(VLV_GU_CTL1);
+       s->pcbr                 = I915_READ(VLV_PCBR);
        s->clock_gate_dis2      = I915_READ(VLV_GUNIT_CLOCK_GATE2);
 
        /*
@@ -1189,6 +1190,7 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
        /* Gunit-Display CZ domain, 0x182028-0x1821CF */
        I915_WRITE(VLV_GU_CTL0,                 s->gu_ctl0);
        I915_WRITE(VLV_GU_CTL1,                 s->gu_ctl1);
+       I915_WRITE(VLV_PCBR,                    s->pcbr);
        I915_WRITE(VLV_GUNIT_CLOCK_GATE2,       s->clock_gate_dis2);
 }
 
@@ -1197,19 +1199,7 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
        u32 val;
        int err;
 
-       val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
-       WARN_ON(!!(val & VLV_GFX_CLK_FORCE_ON_BIT) == force_on);
-
 #define COND (I915_READ(VLV_GTLC_SURVIVABILITY_REG) & VLV_GFX_CLK_STATUS_BIT)
-       /* Wait for a previous force-off to settle */
-       if (force_on) {
-               err = wait_for(!COND, 20);
-               if (err) {
-                       DRM_ERROR("timeout waiting for GFX clock force-off (%08x)\n",
-                                 I915_READ(VLV_GTLC_SURVIVABILITY_REG));
-                       return err;
-               }
-       }
 
        val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
        val &= ~VLV_GFX_CLK_FORCE_ON_BIT;
index 8727086cf48ccce9e6548df8cf4e1d0df59012e7..b4faa2df9d3d8151c4e7aff8853be20937414096 100644 (file)
@@ -1094,6 +1094,7 @@ struct vlv_s0ix_state {
        /* Display 2 CZ domain */
        u32 gu_ctl0;
        u32 gu_ctl1;
+       u32 pcbr;
        u32 clock_gate_dis2;
 };
 
index 6058a01b444334472d7023661bb6a37b551dbf1c..d776621c8521aafbb566666ff09b2bc2e0d9389f 100644 (file)
@@ -12,7 +12,6 @@
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM i915
-#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM)
 #define TRACE_INCLUDE_FILE i915_trace
 
 /* pipe updates */
index 3e246210c46f543d23e3d8b6e04560a3fe4cac74..0ec5abdba5c421b4a7604c4fa1b70ff8e3c129f9 100644 (file)
@@ -332,7 +332,7 @@ static int edp_regulator_enable(struct edp_ctrl *ctrl)
                goto vdda_set_fail;
        }
 
-       ret = regulator_set_optimum_mode(ctrl->vdda_vreg, VDDA_UA_ON_LOAD);
+       ret = regulator_set_load(ctrl->vdda_vreg, VDDA_UA_ON_LOAD);
        if (ret < 0) {
                pr_err("%s: vdda_vreg set regulator mode failed.\n", __func__);
                goto vdda_set_fail;
@@ -356,7 +356,7 @@ static int edp_regulator_enable(struct edp_ctrl *ctrl)
 lvl_enable_fail:
        regulator_disable(ctrl->vdda_vreg);
 vdda_enable_fail:
-       regulator_set_optimum_mode(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD);
+       regulator_set_load(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD);
 vdda_set_fail:
        return ret;
 }
@@ -365,7 +365,7 @@ static void edp_regulator_disable(struct edp_ctrl *ctrl)
 {
        regulator_disable(ctrl->lvl_vreg);
        regulator_disable(ctrl->vdda_vreg);
-       regulator_set_optimum_mode(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD);
+       regulator_set_load(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD);
 }
 
 static int edp_gpio_config(struct edp_ctrl *ctrl)
index ce075cb08cb2b7b618a78c58d74915f06df3c8ff..fdce4062901fe91356ebf5646ab4e9d9e8e77eea 100644 (file)
@@ -9,7 +9,6 @@
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM radeon
-#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM)
 #define TRACE_INCLUDE_FILE radeon_trace
 
 TRACE_EVENT(radeon_bo_create,
index 152b006833cda2518614f80b4cac15b518b0ef0b..15338afdf7f9ab71c84a15dc3143c9dda11fa832 100644 (file)
@@ -92,7 +92,7 @@ menu "Special HID drivers"
        depends on HID
 
 config HID_A4TECH
-       tristate "A4 tech mice" if EXPERT
+       tristate "A4 tech mice"
        depends on HID
        default !EXPERT
        ---help---
@@ -113,7 +113,7 @@ config HID_ACRUX_FF
        game controllers.
 
 config HID_APPLE
-       tristate "Apple {i,Power,Mac}Books" if EXPERT
+       tristate "Apple {i,Power,Mac}Books"
        depends on HID
        default !EXPERT
        ---help---
@@ -141,7 +141,7 @@ config HID_AUREAL
        Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes.
 
 config HID_BELKIN
-       tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT
+       tristate "Belkin Flip KVM and Wireless keyboard"
        depends on HID
        default !EXPERT
        ---help---
@@ -158,14 +158,14 @@ config HID_BETOP_FF
         - BETOP 2185 PC & BFM MODE
 
 config HID_CHERRY
-       tristate "Cherry Cymotion keyboard" if EXPERT
+       tristate "Cherry Cymotion keyboard"
        depends on HID
        default !EXPERT
        ---help---
        Support for Cherry Cymotion keyboard.
 
 config HID_CHICONY
-       tristate "Chicony Tactical pad" if EXPERT
+       tristate "Chicony Tactical pad"
        depends on HID
        default !EXPERT
        ---help---
@@ -196,7 +196,7 @@ config HID_CP2112
        customizable USB descriptor fields are exposed as sysfs attributes.
 
 config HID_CYPRESS
-       tristate "Cypress mouse and barcode readers" if EXPERT
+       tristate "Cypress mouse and barcode readers"
        depends on HID
        default !EXPERT
        ---help---
@@ -245,7 +245,7 @@ config HID_ELO
        different devices than those handled by CONFIG_TOUCHSCREEN_USB_ELO.
 
 config HID_EZKEY
-       tristate "Ezkey BTC 8193 keyboard" if EXPERT
+       tristate "Ezkey BTC 8193 keyboard"
        depends on HID
        default !EXPERT
        ---help---
@@ -286,12 +286,6 @@ config HID_GT683R
        Currently the following devices are know to be supported:
          - MSI GT683R
 
-config HID_HUION
-       tristate "Huion tablets"
-       depends on USB_HID
-       ---help---
-       Support for Huion 580 tablet.
-
 config HID_KEYTOUCH
        tristate "Keytouch HID devices"
        depends on HID
@@ -312,9 +306,9 @@ config HID_KYE
 
 config HID_UCLOGIC
        tristate "UC-Logic"
-       depends on HID
+       depends on USB_HID
        ---help---
-       Support for UC-Logic tablets.
+       Support for UC-Logic and Huion tablets.
 
 config HID_WALTOP
        tristate "Waltop"
@@ -344,7 +338,7 @@ config HID_TWINHAN
        Support for Twinhan IR remote control.
 
 config HID_KENSINGTON
-       tristate "Kensington Slimblade Trackball" if EXPERT
+       tristate "Kensington Slimblade Trackball"
        depends on HID
        default !EXPERT
        ---help---
@@ -372,7 +366,7 @@ config HID_LENOVO
        - ThinkPad Compact USB Keyboard with TrackPoint (supports Fn keys)
 
 config HID_LOGITECH
-       tristate "Logitech devices" if EXPERT
+       tristate "Logitech devices"
        depends on HID
        default !EXPERT
        ---help---
@@ -461,14 +455,14 @@ config HID_MAGICMOUSE
        Apple Wireless "Magic" Mouse and the Apple Wireless "Magic" Trackpad.
 
 config HID_MICROSOFT
-       tristate "Microsoft non-fully HID-compliant devices" if EXPERT
+       tristate "Microsoft non-fully HID-compliant devices"
        depends on HID
        default !EXPERT
        ---help---
        Support for Microsoft devices that are not fully compliant with HID standard.
 
 config HID_MONTEREY
-       tristate "Monterey Genius KB29E keyboard" if EXPERT
+       tristate "Monterey Genius KB29E keyboard"
        depends on HID
        default !EXPERT
        ---help---
@@ -638,7 +632,6 @@ config HID_PICOLCD_CIR
 
 config HID_PLANTRONICS
        tristate "Plantronics USB HID Driver"
-       default !EXPERT
        depends on HID
        ---help---
        Provides HID support for Plantronics telephony devices.
@@ -885,6 +878,21 @@ config HID_SENSOR_HUB
          for events and handle data streams. Each sensor driver can format
          data and present to user mode using input or IIO interface.
 
+config HID_SENSOR_CUSTOM_SENSOR
+       tristate "HID Sensors hub custom sensor support"
+       depends on HID_SENSOR_HUB
+       default n
+       ---help---
+         HID Sensor hub specification allows definition of some custom and
+         generic sensors. Unlike other HID sensors, they can't be exported
+         via Linux IIO because of custom fields. This is up to the manufacturer
+         to decide how to interpret these special sensor ids and process in
+         the user space. Currently some manufacturers are using these ids for
+         sensor calibration and debugging other sensors. Manufacturers
+         should't use these special custom sensor ids to export any of the
+         standard sensors.
+         Select this config option for custom/generic sensor support.
+
 endmenu
 
 endif # HID
index 6f19958dfc3876f26bed994e508f1e8845b69b4f..e4a21dfd7ef3011506c9e4e50eb483480e05c5cd 100644 (file)
@@ -41,7 +41,6 @@ obj-$(CONFIG_HID_GYRATION)    += hid-gyration.o
 obj-$(CONFIG_HID_HOLTEK)       += hid-holtek-kbd.o
 obj-$(CONFIG_HID_HOLTEK)       += hid-holtek-mouse.o
 obj-$(CONFIG_HID_HOLTEK)       += hid-holtekff.o
-obj-$(CONFIG_HID_HUION)                += hid-huion.o
 obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
 obj-$(CONFIG_HID_ICADE)                += hid-icade.o
 obj-$(CONFIG_HID_KENSINGTON)   += hid-kensington.o
@@ -101,6 +100,7 @@ obj-$(CONFIG_HID_WACOM)             += wacom.o
 obj-$(CONFIG_HID_WALTOP)       += hid-waltop.o
 obj-$(CONFIG_HID_WIIMOTE)      += hid-wiimote.o
 obj-$(CONFIG_HID_SENSOR_HUB)   += hid-sensor-hub.o
+obj-$(CONFIG_HID_SENSOR_CUSTOM_SENSOR) += hid-sensor-custom.o
 
 obj-$(CONFIG_USB_HID)          += usbhid/
 obj-$(CONFIG_USB_MOUSE)                += usbhid/
index 56ce8c2b5530db20d851b585fa0c4f88ef81afa6..722a925795a2886557d9b86ed9befdc4c53b5514 100644 (file)
@@ -1562,12 +1562,26 @@ read_report_descriptor(struct file *filp, struct kobject *kobj,
        return count;
 }
 
+static ssize_t
+show_country(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+
+       return sprintf(buf, "%02x\n", hdev->country & 0xff);
+}
+
 static struct bin_attribute dev_bin_attr_report_desc = {
        .attr = { .name = "report_descriptor", .mode = 0444 },
        .read = read_report_descriptor,
        .size = HID_MAX_DESCRIPTOR_SIZE,
 };
 
+static struct device_attribute dev_attr_country = {
+       .attr = { .name = "country", .mode = 0444 },
+       .show = show_country,
+};
+
 int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
 {
        static const char *types[] = { "Device", "Pointer", "Mouse", "Device",
@@ -1646,6 +1660,11 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
                bus = "<UNKNOWN>";
        }
 
+       ret = device_create_file(&hdev->dev, &dev_attr_country);
+       if (ret)
+               hid_warn(hdev,
+                        "can't create sysfs country code attribute err: %d\n", ret);
+
        ret = device_create_bin_file(&hdev->dev, &dev_bin_attr_report_desc);
        if (ret)
                hid_warn(hdev,
@@ -1661,6 +1680,7 @@ EXPORT_SYMBOL_GPL(hid_connect);
 
 void hid_disconnect(struct hid_device *hdev)
 {
+       device_remove_file(&hdev->dev, &dev_attr_country);
        device_remove_bin_file(&hdev->dev, &dev_bin_attr_report_desc);
        if (hdev->claimed & HID_CLAIMED_INPUT)
                hidinput_disconnect(hdev);
@@ -1824,6 +1844,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
 #if IS_ENABLED(CONFIG_HID_LENOVO)
index 1086800693b211000a40812d3dc986eeff8d6da0..2886b645ced73808fe0f4d507823cf459ef70914 100644 (file)
@@ -165,6 +165,7 @@ static const struct hid_usage_entry hid_usage_table[] = {
     {0, 0x53, "DeviceIndex"},
     {0, 0x54, "ContactCount"},
     {0, 0x55, "ContactMaximumNumber"},
+    {0, 0x59, "ButtonType"},
     {0, 0x5A, "SecondaryBarrelSwitch"},
     {0, 0x5B, "TransducerSerialNumber"},
   { 15, 0, "PhysicalInterfaceDevice" },
@@ -1127,7 +1128,8 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
 
                                if (!list->hdev || !list->hdev->debug) {
                                        ret = -EIO;
-                                       break;
+                                       set_current_state(TASK_RUNNING);
+                                       goto out;
                                }
 
                                /* allow O_NONBLOCK from other threads */
diff --git a/drivers/hid/hid-huion.c b/drivers/hid/hid-huion.c
deleted file mode 100644 (file)
index 61b68ca..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- *  HID driver for Huion devices not fully compliant with HID standard
- *
- *  Copyright (c) 2013 Martin Rusko
- *  Copyright (c) 2014 Nikolai Kondrashov
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <asm/unaligned.h>
-#include "usbhid/usbhid.h"
-
-#include "hid-ids.h"
-
-/* Report descriptor template placeholder head */
-#define HUION_PH_HEAD  0xFE, 0xED, 0x1D
-
-/* Report descriptor template placeholder IDs */
-enum huion_ph_id {
-       HUION_PH_ID_X_LM,
-       HUION_PH_ID_X_PM,
-       HUION_PH_ID_Y_LM,
-       HUION_PH_ID_Y_PM,
-       HUION_PH_ID_PRESSURE_LM,
-       HUION_PH_ID_NUM
-};
-
-/* Report descriptor template placeholder */
-#define HUION_PH(_ID) HUION_PH_HEAD, HUION_PH_ID_##_ID
-
-/* Fixed report descriptor template */
-static const __u8 huion_tablet_rdesc_template[] = {
-       0x05, 0x0D,             /*  Usage Page (Digitizer),                 */
-       0x09, 0x02,             /*  Usage (Pen),                            */
-       0xA1, 0x01,             /*  Collection (Application),               */
-       0x85, 0x07,             /*      Report ID (7),                      */
-       0x09, 0x20,             /*      Usage (Stylus),                     */
-       0xA0,                   /*      Collection (Physical),              */
-       0x14,                   /*          Logical Minimum (0),            */
-       0x25, 0x01,             /*          Logical Maximum (1),            */
-       0x75, 0x01,             /*          Report Size (1),                */
-       0x09, 0x42,             /*          Usage (Tip Switch),             */
-       0x09, 0x44,             /*          Usage (Barrel Switch),          */
-       0x09, 0x46,             /*          Usage (Tablet Pick),            */
-       0x95, 0x03,             /*          Report Count (3),               */
-       0x81, 0x02,             /*          Input (Variable),               */
-       0x95, 0x03,             /*          Report Count (3),               */
-       0x81, 0x03,             /*          Input (Constant, Variable),     */
-       0x09, 0x32,             /*          Usage (In Range),               */
-       0x95, 0x01,             /*          Report Count (1),               */
-       0x81, 0x02,             /*          Input (Variable),               */
-       0x95, 0x01,             /*          Report Count (1),               */
-       0x81, 0x03,             /*          Input (Constant, Variable),     */
-       0x75, 0x10,             /*          Report Size (16),               */
-       0x95, 0x01,             /*          Report Count (1),               */
-       0xA4,                   /*          Push,                           */
-       0x05, 0x01,             /*          Usage Page (Desktop),           */
-       0x65, 0x13,             /*          Unit (Inch),                    */
-       0x55, 0xFD,             /*          Unit Exponent (-3),             */
-       0x34,                   /*          Physical Minimum (0),           */
-       0x09, 0x30,             /*          Usage (X),                      */
-       0x27, HUION_PH(X_LM),   /*          Logical Maximum (PLACEHOLDER),  */
-       0x47, HUION_PH(X_PM),   /*          Physical Maximum (PLACEHOLDER), */
-       0x81, 0x02,             /*          Input (Variable),               */
-       0x09, 0x31,             /*          Usage (Y),                      */
-       0x27, HUION_PH(Y_LM),   /*          Logical Maximum (PLACEHOLDER),  */
-       0x47, HUION_PH(Y_PM),   /*          Physical Maximum (PLACEHOLDER), */
-       0x81, 0x02,             /*          Input (Variable),               */
-       0xB4,                   /*          Pop,                            */
-       0x09, 0x30,             /*          Usage (Tip Pressure),           */
-       0x27,
-       HUION_PH(PRESSURE_LM),  /*          Logical Maximum (PLACEHOLDER),  */
-       0x81, 0x02,             /*          Input (Variable),               */
-       0xC0,                   /*      End Collection,                     */
-       0xC0                    /*  End Collection                          */
-};
-
-/* Parameter indices */
-enum huion_prm {
-       HUION_PRM_X_LM          = 1,
-       HUION_PRM_Y_LM          = 2,
-       HUION_PRM_PRESSURE_LM   = 4,
-       HUION_PRM_RESOLUTION    = 5,
-       HUION_PRM_NUM
-};
-
-/* Driver data */
-struct huion_drvdata {
-       __u8 *rdesc;
-       unsigned int rsize;
-};
-
-static __u8 *huion_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int *rsize)
-{
-       struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
-       switch (hdev->product) {
-       case USB_DEVICE_ID_HUION_TABLET:
-               if (drvdata->rdesc != NULL) {
-                       rdesc = drvdata->rdesc;
-                       *rsize = drvdata->rsize;
-               }
-               break;
-       }
-       return rdesc;
-}
-
-/**
- * Enable fully-functional tablet mode and determine device parameters.
- *
- * @hdev:      HID device
- */
-static int huion_tablet_enable(struct hid_device *hdev)
-{
-       int rc;
-       struct usb_device *usb_dev = hid_to_usb_dev(hdev);
-       struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
-       __le16 *buf = NULL;
-       size_t len;
-       s32 params[HUION_PH_ID_NUM];
-       s32 resolution;
-       __u8 *p;
-       s32 v;
-
-       /*
-        * Read string descriptor containing tablet parameters. The specific
-        * string descriptor and data were discovered by sniffing the Windows
-        * driver traffic.
-        * NOTE: This enables fully-functional tablet mode.
-        */
-       len = HUION_PRM_NUM * sizeof(*buf);
-       buf = kmalloc(len, GFP_KERNEL);
-       if (buf == NULL) {
-               hid_err(hdev, "failed to allocate parameter buffer\n");
-               rc = -ENOMEM;
-               goto cleanup;
-       }
-       rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-                               USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
-                               (USB_DT_STRING << 8) + 0x64,
-                               0x0409, buf, len,
-                               USB_CTRL_GET_TIMEOUT);
-       if (rc == -EPIPE) {
-               hid_err(hdev, "device parameters not found\n");
-               rc = -ENODEV;
-               goto cleanup;
-       } else if (rc < 0) {
-               hid_err(hdev, "failed to get device parameters: %d\n", rc);
-               rc = -ENODEV;
-               goto cleanup;
-       } else if (rc != len) {
-               hid_err(hdev, "invalid device parameters\n");
-               rc = -ENODEV;
-               goto cleanup;
-       }
-
-       /* Extract device parameters */
-       params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[HUION_PRM_X_LM]);
-       params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[HUION_PRM_Y_LM]);
-       params[HUION_PH_ID_PRESSURE_LM] =
-               le16_to_cpu(buf[HUION_PRM_PRESSURE_LM]);
-       resolution = le16_to_cpu(buf[HUION_PRM_RESOLUTION]);
-       if (resolution == 0) {
-               params[HUION_PH_ID_X_PM] = 0;
-               params[HUION_PH_ID_Y_PM] = 0;
-       } else {
-               params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] *
-                                               1000 / resolution;
-               params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] *
-                                               1000 / resolution;
-       }
-
-       /* Allocate fixed report descriptor */
-       drvdata->rdesc = devm_kmalloc(&hdev->dev,
-                               sizeof(huion_tablet_rdesc_template),
-                               GFP_KERNEL);
-       if (drvdata->rdesc == NULL) {
-               hid_err(hdev, "failed to allocate fixed rdesc\n");
-               rc = -ENOMEM;
-               goto cleanup;
-       }
-       drvdata->rsize = sizeof(huion_tablet_rdesc_template);
-
-       /* Format fixed report descriptor */
-       memcpy(drvdata->rdesc, huion_tablet_rdesc_template,
-               drvdata->rsize);
-       for (p = drvdata->rdesc;
-            p <= drvdata->rdesc + drvdata->rsize - 4;) {
-               if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
-                   p[3] < sizeof(params)) {
-                       v = params[p[3]];
-                       put_unaligned(cpu_to_le32(v), (s32 *)p);
-                       p += 4;
-               } else {
-                       p++;
-               }
-       }
-
-       rc = 0;
-
-cleanup:
-       kfree(buf);
-       return rc;
-}
-
-static int huion_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-       int rc;
-       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
-       struct huion_drvdata *drvdata;
-
-       /* Allocate and assign driver data */
-       drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
-       if (drvdata == NULL) {
-               hid_err(hdev, "failed to allocate driver data\n");
-               return -ENOMEM;
-       }
-       hid_set_drvdata(hdev, drvdata);
-
-       switch (id->product) {
-       case USB_DEVICE_ID_HUION_TABLET:
-               /* If this is the pen interface */
-               if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
-                       rc = huion_tablet_enable(hdev);
-                       if (rc) {
-                               hid_err(hdev, "tablet enabling failed\n");
-                               return rc;
-                       }
-               }
-               break;
-       }
-
-       rc = hid_parse(hdev);
-       if (rc) {
-               hid_err(hdev, "parse failed\n");
-               return rc;
-       }
-
-       rc = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-       if (rc) {
-               hid_err(hdev, "hw start failed\n");
-               return rc;
-       }
-
-       return 0;
-}
-
-static int huion_raw_event(struct hid_device *hdev, struct hid_report *report,
-                       u8 *data, int size)
-{
-       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
-
-       /* If this is a pen input report */
-       if (intf->cur_altsetting->desc.bInterfaceNumber == 0 &&
-           report->type == HID_INPUT_REPORT &&
-           report->id == 0x07 && size >= 2)
-               /* Invert the in-range bit */
-               data[1] ^= 0x40;
-
-       return 0;
-}
-
-static const struct hid_device_id huion_devices[] = {
-       { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) },
-       { }
-};
-MODULE_DEVICE_TABLE(hid, huion_devices);
-
-static struct hid_driver huion_driver = {
-       .name = "huion",
-       .id_table = huion_devices,
-       .probe = huion_probe,
-       .report_fixup = huion_report_fixup,
-       .raw_event = huion_raw_event,
-};
-module_hid_driver(huion_driver);
-
-MODULE_AUTHOR("Martin Rusko");
-MODULE_DESCRIPTION("Huion HID driver");
-MODULE_LICENSE("GPL");
index 9c4786759f16f4f397a839214600524b9826254c..41f167e4d75fdeec20d795b566fdeba1c642497f 100644 (file)
 #define USB_DEVICE_ID_UGCI_FLYING      0x0020
 #define USB_DEVICE_ID_UGCI_FIGHTING    0x0030
 
+#define USB_VENDOR_ID_HP               0x03f0
+#define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A  0x0a4a
+#define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A  0x0b4a
+#define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE         0x134a
+
 #define USB_VENDOR_ID_HUION            0x256c
 #define USB_DEVICE_ID_HUION_TABLET     0x006e
 
 #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X       0x5011
 #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2     0x501a
 #define USB_DEVICE_ID_KYE_EASYPEN_M610X        0x5013
+#define USB_DEVICE_ID_KYE_PENSKETCH_M912       0x5015
 
 #define USB_VENDOR_ID_LABTEC           0x1020
 #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006
 #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST  0xc110
 #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
 #define USB_DEVICE_ID_LOGITECH_HARMONY_PS3 0x0306
+#define USB_DEVICE_ID_LOGITECH_MOUSE_C01A      0xc01a
+#define USB_DEVICE_ID_LOGITECH_MOUSE_C05A      0xc05a
+#define USB_DEVICE_ID_LOGITECH_MOUSE_C06A      0xc06a
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD  0xc20a
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD       0xc211
 #define USB_DEVICE_ID_LOGITECH_EXTREME_3D      0xc215
 #define USB_DEVICE_ID_ZYTRONIC_ZXY100  0x0005
 
 #define USB_VENDOR_ID_PRIMAX   0x0461
+#define USB_DEVICE_ID_PRIMAX_MOUSE_4D22        0x4d22
 #define USB_DEVICE_ID_PRIMAX_KEYBOARD  0x4e05
 
 
index 052869d0ab787da2a3d685c5c6bf905d05e047b8..008e89bf6f3c3d112d92640bdf91f1e935e0641c 100644 (file)
@@ -339,7 +339,7 @@ static int hidinput_get_battery_property(struct power_supply *psy,
                                         enum power_supply_property prop,
                                         union power_supply_propval *val)
 {
-       struct hid_device *dev = container_of(psy, struct hid_device, battery);
+       struct hid_device *dev = power_supply_get_drvdata(psy);
        int ret = 0;
        __u8 *buf;
 
@@ -397,26 +397,32 @@ static int hidinput_get_battery_property(struct power_supply *psy,
 
 static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field)
 {
-       struct power_supply *battery = &dev->battery;
-       int ret;
+       struct power_supply_desc *psy_desc = NULL;
+       struct power_supply_config psy_cfg = { .drv_data = dev, };
        unsigned quirks;
        s32 min, max;
 
        if (field->usage->hid != HID_DC_BATTERYSTRENGTH)
                return false;   /* no match */
 
-       if (battery->name != NULL)
+       if (dev->battery != NULL)
                goto out;       /* already initialized? */
 
-       battery->name = kasprintf(GFP_KERNEL, "hid-%s-battery", dev->uniq);
-       if (battery->name == NULL)
+       psy_desc = kzalloc(sizeof(*psy_desc), GFP_KERNEL);
+       if (psy_desc == NULL)
                goto out;
 
-       battery->type = POWER_SUPPLY_TYPE_BATTERY;
-       battery->properties = hidinput_battery_props;
-       battery->num_properties = ARRAY_SIZE(hidinput_battery_props);
-       battery->use_for_apm = 0;
-       battery->get_property = hidinput_get_battery_property;
+       psy_desc->name = kasprintf(GFP_KERNEL, "hid-%s-battery", dev->uniq);
+       if (psy_desc->name == NULL) {
+               kfree(psy_desc);
+               goto out;
+       }
+
+       psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
+       psy_desc->properties = hidinput_battery_props;
+       psy_desc->num_properties = ARRAY_SIZE(hidinput_battery_props);
+       psy_desc->use_for_apm = 0;
+       psy_desc->get_property = hidinput_get_battery_property;
 
        quirks = find_battery_quirk(dev);
 
@@ -439,27 +445,30 @@ static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
        dev->battery_report_type = report_type;
        dev->battery_report_id = field->report->id;
 
-       ret = power_supply_register(&dev->dev, battery);
-       if (ret != 0) {
-               hid_warn(dev, "can't register power supply: %d\n", ret);
-               kfree(battery->name);
-               battery->name = NULL;
+       dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg);
+       if (IS_ERR(dev->battery)) {
+               hid_warn(dev, "can't register power supply: %ld\n",
+                               PTR_ERR(dev->battery));
+               kfree(psy_desc->name);
+               kfree(psy_desc);
+               dev->battery = NULL;
+       } else {
+               power_supply_powers(dev->battery, &dev->dev);
        }
 
-       power_supply_powers(battery, &dev->dev);
-
 out:
        return true;
 }
 
 static void hidinput_cleanup_battery(struct hid_device *dev)
 {
-       if (!dev->battery.name)
+       if (!dev->battery)
                return;
 
-       power_supply_unregister(&dev->battery);
-       kfree(dev->battery.name);
-       dev->battery.name = NULL;
+       power_supply_unregister(dev->battery);
+       kfree(dev->battery->desc->name);
+       kfree(dev->battery->desc);
+       dev->battery = NULL;
 }
 #else  /* !CONFIG_HID_BATTERY_STRENGTH */
 static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
@@ -711,6 +720,29 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                }
                break;
 
+       case HID_UP_TELEPHONY:
+               switch (usage->hid & HID_USAGE) {
+               case 0x2f: map_key_clear(KEY_MICMUTE);          break;
+               case 0xb0: map_key_clear(KEY_NUMERIC_0);        break;
+               case 0xb1: map_key_clear(KEY_NUMERIC_1);        break;
+               case 0xb2: map_key_clear(KEY_NUMERIC_2);        break;
+               case 0xb3: map_key_clear(KEY_NUMERIC_3);        break;
+               case 0xb4: map_key_clear(KEY_NUMERIC_4);        break;
+               case 0xb5: map_key_clear(KEY_NUMERIC_5);        break;
+               case 0xb6: map_key_clear(KEY_NUMERIC_6);        break;
+               case 0xb7: map_key_clear(KEY_NUMERIC_7);        break;
+               case 0xb8: map_key_clear(KEY_NUMERIC_8);        break;
+               case 0xb9: map_key_clear(KEY_NUMERIC_9);        break;
+               case 0xba: map_key_clear(KEY_NUMERIC_STAR);     break;
+               case 0xbb: map_key_clear(KEY_NUMERIC_POUND);    break;
+               case 0xbc: map_key_clear(KEY_NUMERIC_A);        break;
+               case 0xbd: map_key_clear(KEY_NUMERIC_B);        break;
+               case 0xbe: map_key_clear(KEY_NUMERIC_C);        break;
+               case 0xbf: map_key_clear(KEY_NUMERIC_D);        break;
+               default: goto ignore;
+               }
+               break;
+
        case HID_UP_CONSUMER:   /* USB HUT v1.12, pages 75-84 */
                switch (usage->hid & HID_USAGE) {
                case 0x000: goto ignore;
index 158fcf577fae570d331a37c46d650a151141c19c..32e6d8d9ded0ed4b2e4f1ab1d7c86d7f6413ec07 100644 (file)
@@ -268,6 +268,137 @@ static __u8 easypen_m610x_rdesc_fixed[] = {
        0xC0                          /*  End Collection                  */
 };
 
+
+/* Original PenSketch M912 report descriptor size */
+#define PENSKETCH_M912_RDESC_ORIG_SIZE 482
+
+/* Fixed PenSketch M912 report descriptor */
+static __u8 pensketch_m912_rdesc_fixed[] = {
+       0x05, 0x01,                   /*  Usage Page (Desktop),           */
+       0x08,                         /*  Usage (00h),                    */
+       0xA1, 0x01,                   /*  Collection (Application),       */
+       0x85, 0x05,                   /*    Report ID (5),                */
+       0x06, 0x00, 0xFF,             /*    Usage Page (FF00h),           */
+       0x09, 0x01,                   /*    Usage (01h),                  */
+       0x15, 0x81,                   /*    Logical Minimum (-127),       */
+       0x25, 0x7F,                   /*    Logical Maximum (127),        */
+       0x75, 0x08,                   /*    Report Size (8),              */
+       0x95, 0x07,                   /*    Report Count (7),             */
+       0xB1, 0x02,                   /*    Feature (Variable),           */
+       0xC0,                         /*  End Collection,                 */
+       0x05, 0x0D,                   /*  Usage Page (Digitizer),         */
+       0x09, 0x02,                   /*  Usage (Pen),                    */
+       0xA1, 0x01,                   /*  Collection (Application),       */
+       0x85, 0x10,                   /*    Report ID (16),               */
+       0x09, 0x20,                   /*    Usage (Stylus),               */
+       0xA0,                         /*    Collection (Physical),        */
+       0x09, 0x42,                   /*      Usage (Tip Switch),         */
+       0x09, 0x44,                   /*      Usage (Barrel Switch),      */
+       0x09, 0x46,                   /*      Usage (Tablet Pick),        */
+       0x14,                         /*      Logical Minimum (0),        */
+       0x25, 0x01,                   /*      Logical Maximum (1),        */
+       0x75, 0x01,                   /*      Report Size (1),            */
+       0x95, 0x03,                   /*      Report Count (3),           */
+       0x81, 0x02,                   /*      Input (Variable),           */
+       0x95, 0x04,                   /*      Report Count (4),           */
+       0x81, 0x03,                   /*      Input (Constant, Variable), */
+       0x09, 0x32,                   /*      Usage (In Range),           */
+       0x95, 0x01,                   /*      Report Count (1),           */
+       0x81, 0x02,                   /*      Input (Variable),           */
+       0x75, 0x10,                   /*      Report Size (16),           */
+       0x95, 0x01,                   /*      Report Count (1),           */
+       0xA4,                         /*      Push,                       */
+       0x05, 0x01,                   /*      Usage Page (Desktop),       */
+       0x55, 0xFD,                   /*      Unit Exponent (-3),         */
+       0x65, 0x13,                   /*      Unit (Inch),                */
+       0x14,                         /*      Logical Minimum (0),        */
+       0x34,                         /*      Physical Minimum (0),       */
+       0x09, 0x30,                   /*      Usage (X),                  */
+       0x27, 0x00, 0xF0, 0x00, 0x00, /*      Logical Maximum (61440),    */
+       0x46, 0xE0, 0x2E,             /*      Physical Maximum (12000),   */
+       0x81, 0x02,                   /*      Input (Variable),           */
+       0x09, 0x31,                   /*      Usage (Y),                  */
+       0x27, 0x00, 0xB4, 0x00, 0x00, /*      Logical Maximum (46080),    */
+       0x46, 0x28, 0x23,             /*      Physical Maximum (9000),    */
+       0x81, 0x02,                   /*      Input (Variable),           */
+       0xB4,                         /*      Pop,                        */
+       0x09, 0x30,                   /*      Usage (Tip Pressure),       */
+       0x14,                         /*      Logical Minimum (0),        */
+       0x26, 0xFF, 0x07,             /*      Logical Maximum (2047),     */
+       0x81, 0x02,                   /*      Input (Variable),           */
+       0xC0,                         /*    End Collection,               */
+       0xC0,                         /*  End Collection,                 */
+       0x05, 0x0D,                   /*  Usage Page (Digitizer),         */
+       0x09, 0x21,                   /*  Usage (Puck),                   */
+       0xA1, 0x01,                   /*  Collection (Application),       */
+       0x85, 0x11,                   /*    Report ID (17),               */
+       0x09, 0x21,                   /*    Usage (Puck),                 */
+       0xA0,                         /*    Collection (Physical),        */
+       0x05, 0x09,                   /*      Usage Page (Button),        */
+       0x75, 0x01,                   /*      Report Size (1),            */
+       0x19, 0x01,                   /*      Usage Minimum (01h),        */
+       0x29, 0x03,                   /*      Usage Maximum (03h),        */
+       0x14,                         /*      Logical Minimum (0),        */
+       0x25, 0x01,                   /*      Logical Maximum (1),        */
+       0x95, 0x03,                   /*      Report Count (3),           */
+       0x81, 0x02,                   /*      Input (Variable),           */
+       0x95, 0x04,                   /*      Report Count (4),           */
+       0x81, 0x01,                   /*      Input (Constant),           */
+       0x95, 0x01,                   /*      Report Count (1),           */
+       0x0B, 0x32, 0x00, 0x0D, 0x00, /*      Usage (Digitizer In Range), */
+       0x14,                         /*      Logical Minimum (0),        */
+       0x25, 0x01,                   /*      Logical Maximum (1),        */
+       0x81, 0x02,                   /*      Input (Variable),           */
+       0xA4,                         /*      Push,                       */
+       0x05, 0x01,                   /*      Usage Page (Desktop),       */
+       0x75, 0x10,                   /*      Report Size (16),           */
+       0x95, 0x01,                   /*      Report Count (1),           */
+       0x55, 0xFD,                   /*      Unit Exponent (-3),         */
+       0x65, 0x13,                   /*      Unit (Inch),                */
+       0x14,                         /*      Logical Minimum (0),        */
+       0x34,                         /*      Physical Minimum (0),       */
+       0x09, 0x30,                   /*      Usage (X),                  */
+       0x27, 0x00, 0xF0, 0x00, 0x00, /*      Logical Maximum (61440),    */
+       0x46, 0xE0, 0x2E,             /*      Physical Maximum (12000),   */
+       0x81, 0x02,                   /*      Input (Variable),           */
+       0x09, 0x31,                   /*      Usage (Y),                  */
+       0x27, 0x00, 0xB4, 0x00, 0x00, /*      Logical Maximum (46080),    */
+       0x46, 0x28, 0x23,             /*      Physical Maximum (9000),    */
+       0x81, 0x02,                   /*      Input (Variable),           */
+       0x09, 0x38,                   /*      Usage (Wheel),              */
+       0x75, 0x08,                   /*      Report Size (8),            */
+       0x95, 0x01,                   /*      Report Count (1),           */
+       0x15, 0xFF,                   /*      Logical Minimum (-1),       */
+       0x25, 0x01,                   /*      Logical Maximum (1),        */
+       0x34,                         /*      Physical Minimum (0),       */
+       0x44,                         /*      Physical Maximum (0),       */
+       0x81, 0x06,                   /*      Input (Variable, Relative), */
+       0xB4,                         /*      Pop,                        */
+       0xC0,                         /*    End Collection,               */
+       0xC0,                         /*  End Collection,                 */
+       0x05, 0x0C,                   /*  Usage Page (Consumer),          */
+       0x09, 0x01,                   /*  Usage (Consumer Control),       */
+       0xA1, 0x01,                   /*  Collection (Application),       */
+       0x85, 0x12,                   /*    Report ID (18),               */
+       0x14,                         /*    Logical Minimum (0),          */
+       0x25, 0x01,                   /*    Logical Maximum (1),          */
+       0x75, 0x01,                   /*    Report Size (1),              */
+       0x95, 0x08,                   /*    Report Count (8),             */
+       0x05, 0x0C,                   /*    Usage Page (Consumer),        */
+       0x0A, 0x6A, 0x02,             /*    Usage (AC Delete),            */
+       0x0A, 0x1A, 0x02,             /*    Usage (AC Undo),              */
+       0x0A, 0x01, 0x02,             /*    Usage (AC New),               */
+       0x0A, 0x2F, 0x02,             /*    Usage (AC Zoom),              */
+       0x0A, 0x25, 0x02,             /*    Usage (AC Forward),           */
+       0x0A, 0x24, 0x02,             /*    Usage (AC Back),              */
+       0x0A, 0x2D, 0x02,             /*    Usage (AC Zoom In),           */
+       0x0A, 0x2E, 0x02,             /*    Usage (AC Zoom Out),          */
+       0x81, 0x02,                   /*    Input (Variable),             */
+       0x95, 0x30,                   /*    Report Count (48),            */
+       0x81, 0x03,                   /*    Input (Constant, Variable),   */
+       0xC0                          /*  End Collection                  */
+};
+
 static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize, int offset, const char *device_name) {
        /*
@@ -335,6 +466,12 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                        *rsize = sizeof(easypen_m610x_rdesc_fixed);
                }
                break;
+       case USB_DEVICE_ID_KYE_PENSKETCH_M912:
+               if (*rsize == PENSKETCH_M912_RDESC_ORIG_SIZE) {
+                       rdesc = pensketch_m912_rdesc_fixed;
+                       *rsize = sizeof(pensketch_m912_rdesc_fixed);
+               }
+               break;
        case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE:
                rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
                                        "Genius Gila Gaming Mouse");
@@ -418,6 +555,7 @@ static int kye_probe(struct hid_device *hdev, const struct hid_device_id *id)
        case USB_DEVICE_ID_KYE_MOUSEPEN_I608X:
        case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2:
        case USB_DEVICE_ID_KYE_EASYPEN_M610X:
+       case USB_DEVICE_ID_KYE_PENSKETCH_M912:
                ret = kye_tablet_enable(hdev);
                if (ret) {
                        hid_err(hdev, "tablet enabling failed\n");
@@ -457,6 +595,8 @@ static const struct hid_device_id kye_devices[] = {
                                USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
                                USB_DEVICE_ID_GENIUS_MANTICORE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
+                               USB_DEVICE_ID_KYE_PENSKETCH_M912) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, kye_devices);
index f91ff145db9a0761ce487aa2b43aee1f2503af2f..b86c18e651ed361bedb2c1584f78c5b494df2ae7 100644 (file)
@@ -27,6 +27,7 @@
 #include "usbhid/usbhid.h"
 #include "hid-ids.h"
 #include "hid-lg.h"
+#include "hid-lg4ff.h"
 
 #define LG_RDESC               0x001
 #define LG_BAD_RELATIVE_KEYS   0x002
@@ -818,4 +819,10 @@ static struct hid_driver lg_driver = {
 };
 module_hid_driver(lg_driver);
 
+#ifdef CONFIG_LOGIWHEELS_FF
+int lg4ff_no_autoswitch = 0;
+module_param_named(lg4ff_no_autoswitch, lg4ff_no_autoswitch, int, S_IRUGO);
+MODULE_PARM_DESC(lg4ff_no_autoswitch, "Do not switch multimode wheels to their native mode automatically");
+#endif
+
 MODULE_LICENSE("GPL");
index 142ce3f5f055f0c3d7b00e34cc91e9411eb06817..10dd8f0241352544b24bc057c861cc04415292ec 100644 (file)
@@ -24,16 +24,4 @@ int lg3ff_init(struct hid_device *hdev);
 static inline int lg3ff_init(struct hid_device *hdev) { return -1; }
 #endif
 
-#ifdef CONFIG_LOGIWHEELS_FF
-int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
-                            struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data);
-int lg4ff_init(struct hid_device *hdev);
-int lg4ff_deinit(struct hid_device *hdev);
-#else
-static inline int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
-                                          struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data) { return 0; }
-static inline int lg4ff_init(struct hid_device *hdev) { return -1; }
-static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; }
-#endif
-
 #endif
index db0dd9b17e538d114c619a3b108e7a26ab1d56b1..1232210b1cc586f80703479eec634e595addbd9d 100644 (file)
 
 #include "usbhid/usbhid.h"
 #include "hid-lg.h"
+#include "hid-lg4ff.h"
 #include "hid-ids.h"
 
-#define DFGT_REV_MAJ 0x13
-#define DFGT_REV_MIN 0x22
-#define DFGT2_REV_MIN 0x26
-#define DFP_REV_MAJ 0x11
-#define DFP_REV_MIN 0x06
-#define FFEX_REV_MAJ 0x21
-#define FFEX_REV_MIN 0x00
-#define G25_REV_MAJ 0x12
-#define G25_REV_MIN 0x22
-#define G27_REV_MAJ 0x12
-#define G27_REV_MIN 0x38
-#define G27_2_REV_MIN 0x39
-
 #define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
 
+#define LG4FF_MMODE_IS_MULTIMODE 0
+#define LG4FF_MMODE_SWITCHED 1
+#define LG4FF_MMODE_NOT_MULTIMODE 2
+
+#define LG4FF_MODE_NATIVE_IDX 0
+#define LG4FF_MODE_DFEX_IDX 1
+#define LG4FF_MODE_DFP_IDX 2
+#define LG4FF_MODE_G25_IDX 3
+#define LG4FF_MODE_DFGT_IDX 4
+#define LG4FF_MODE_G27_IDX 5
+#define LG4FF_MODE_MAX_IDX 6
+
+#define LG4FF_MODE_NATIVE BIT(LG4FF_MODE_NATIVE_IDX)
+#define LG4FF_MODE_DFEX BIT(LG4FF_MODE_DFEX_IDX)
+#define LG4FF_MODE_DFP BIT(LG4FF_MODE_DFP_IDX)
+#define LG4FF_MODE_G25 BIT(LG4FF_MODE_G25_IDX)
+#define LG4FF_MODE_DFGT BIT(LG4FF_MODE_DFGT_IDX)
+#define LG4FF_MODE_G27 BIT(LG4FF_MODE_G27_IDX)
+
+#define LG4FF_DFEX_TAG "DF-EX"
+#define LG4FF_DFEX_NAME "Driving Force / Formula EX"
+#define LG4FF_DFP_TAG "DFP"
+#define LG4FF_DFP_NAME "Driving Force Pro"
+#define LG4FF_G25_TAG "G25"
+#define LG4FF_G25_NAME "G25 Racing Wheel"
+#define LG4FF_G27_TAG "G27"
+#define LG4FF_G27_NAME "G27 Racing Wheel"
+#define LG4FF_DFGT_TAG "DFGT"
+#define LG4FF_DFGT_NAME "Driving Force GT"
+
+#define LG4FF_FFEX_REV_MAJ 0x21
+#define LG4FF_FFEX_REV_MIN 0x00
+
 static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range);
 static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range);
 
@@ -59,6 +80,10 @@ struct lg4ff_device_entry {
        __u8  led_state;
        struct led_classdev *led[5];
 #endif
+       u32 alternate_modes;
+       const char *real_tag;
+       const char *real_name;
+       u16 real_product_id;
        struct list_head list;
        void (*set_range)(struct hid_device *hid, u16 range);
 };
@@ -77,6 +102,35 @@ struct lg4ff_wheel {
        void (*set_range)(struct hid_device *hid, u16 range);
 };
 
+struct lg4ff_compat_mode_switch {
+       const __u8 cmd_count;   /* Number of commands to send */
+       const __u8 cmd[];
+};
+
+struct lg4ff_wheel_ident_info {
+       const u16 mask;
+       const u16 result;
+       const u16 real_product_id;
+};
+
+struct lg4ff_wheel_ident_checklist {
+       const u32 count;
+       const struct lg4ff_wheel_ident_info *models[];
+};
+
+struct lg4ff_multimode_wheel {
+       const u16 product_id;
+       const u32 alternate_modes;
+       const char *real_tag;
+       const char *real_name;
+};
+
+struct lg4ff_alternate_mode {
+       const u16 product_id;
+       const char *tag;
+       const char *name;
+};
+
 static const struct lg4ff_wheel lg4ff_devices[] = {
        {USB_DEVICE_ID_LOGITECH_WHEEL,       lg4ff_wheel_effects, 40, 270, NULL},
        {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL,  lg4ff_wheel_effects, 40, 270, NULL},
@@ -88,46 +142,106 @@ static const struct lg4ff_wheel lg4ff_devices[] = {
        {USB_DEVICE_ID_LOGITECH_WII_WHEEL,   lg4ff_wheel_effects, 40, 270, NULL}
 };
 
-struct lg4ff_native_cmd {
-       const __u8 cmd_num;     /* Number of commands to send */
-       const __u8 cmd[];
+static const struct lg4ff_multimode_wheel lg4ff_multimode_wheels[] = {
+       {USB_DEVICE_ID_LOGITECH_DFP_WHEEL,
+        LG4FF_MODE_NATIVE | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
+        LG4FF_DFP_TAG, LG4FF_DFP_NAME},
+       {USB_DEVICE_ID_LOGITECH_G25_WHEEL,
+        LG4FF_MODE_NATIVE | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
+        LG4FF_G25_TAG, LG4FF_G25_NAME},
+       {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL,
+        LG4FF_MODE_NATIVE | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
+        LG4FF_DFGT_TAG, LG4FF_DFGT_NAME},
+       {USB_DEVICE_ID_LOGITECH_G27_WHEEL,
+        LG4FF_MODE_NATIVE | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
+        LG4FF_G27_TAG, LG4FF_G27_NAME},
 };
 
-struct lg4ff_usb_revision {
-       const __u16 rev_maj;
-       const __u16 rev_min;
-       const struct lg4ff_native_cmd *command;
+static const struct lg4ff_alternate_mode lg4ff_alternate_modes[] = {
+       [LG4FF_MODE_NATIVE_IDX] = {0, "native", ""},
+       [LG4FF_MODE_DFEX_IDX] = {USB_DEVICE_ID_LOGITECH_WHEEL, LG4FF_DFEX_TAG, LG4FF_DFEX_NAME},
+       [LG4FF_MODE_DFP_IDX] = {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, LG4FF_DFP_TAG, LG4FF_DFP_NAME},
+       [LG4FF_MODE_G25_IDX] = {USB_DEVICE_ID_LOGITECH_G25_WHEEL, LG4FF_G25_TAG, LG4FF_G25_NAME},
+       [LG4FF_MODE_DFGT_IDX] = {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, LG4FF_DFGT_TAG, LG4FF_DFGT_NAME},
+       [LG4FF_MODE_G27_IDX] = {USB_DEVICE_ID_LOGITECH_G27_WHEEL, LG4FF_G27_TAG, LG4FF_G27_NAME}
 };
 
-static const struct lg4ff_native_cmd native_dfp = {
-       1,
-       {0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}
+/* Multimode wheel identificators */
+static const struct lg4ff_wheel_ident_info lg4ff_dfp_ident_info = {
+       0xf000,
+       0x1000,
+       USB_DEVICE_ID_LOGITECH_DFP_WHEEL
+};
+
+static const struct lg4ff_wheel_ident_info lg4ff_g25_ident_info = {
+       0xff00,
+       0x1200,
+       USB_DEVICE_ID_LOGITECH_G25_WHEEL
+};
+
+static const struct lg4ff_wheel_ident_info lg4ff_g27_ident_info = {
+       0xfff0,
+       0x1230,
+       USB_DEVICE_ID_LOGITECH_G27_WHEEL
 };
 
-static const struct lg4ff_native_cmd native_dfgt = {
+static const struct lg4ff_wheel_ident_info lg4ff_dfgt_ident_info = {
+       0xff00,
+       0x1300,
+       USB_DEVICE_ID_LOGITECH_DFGT_WHEEL
+};
+
+/* Multimode wheel identification checklists */
+static const struct lg4ff_wheel_ident_checklist lg4ff_main_checklist = {
+       4,
+       {&lg4ff_dfgt_ident_info,
+        &lg4ff_g27_ident_info,
+        &lg4ff_g25_ident_info,
+        &lg4ff_dfp_ident_info}
+};
+
+/* Compatibility mode switching commands */
+/* EXT_CMD9 - Understood by G27 and DFGT */
+static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_dfex = {
        2,
-       {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,      /* 1st command */
-        0xf8, 0x09, 0x03, 0x01, 0x00, 0x00, 0x00}      /* 2nd command */
+       {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,      /* Revert mode upon USB reset */
+        0xf8, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00}      /* Switch mode to DF-EX with detach */
 };
 
-static const struct lg4ff_native_cmd native_g25 = {
-       1,
-       {0xf8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}
+static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_dfp = {
+       2,
+       {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,      /* Revert mode upon USB reset */
+        0xf8, 0x09, 0x01, 0x01, 0x00, 0x00, 0x00}      /* Switch mode to DFP with detach */
+};
+
+static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g25 = {
+       2,
+       {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,      /* Revert mode upon USB reset */
+        0xf8, 0x09, 0x02, 0x01, 0x00, 0x00, 0x00}      /* Switch mode to G25 with detach */
+};
+
+static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_dfgt = {
+       2,
+       {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,      /* Revert mode upon USB reset */
+        0xf8, 0x09, 0x03, 0x01, 0x00, 0x00, 0x00}      /* Switch mode to DFGT with detach */
 };
 
-static const struct lg4ff_native_cmd native_g27 = {
+static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g27 = {
        2,
-       {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,      /* 1st command */
-        0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00}      /* 2nd command */
+       {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,      /* Revert mode upon USB reset */
+        0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00}      /* Switch mode to G27 with detach */
 };
 
-static const struct lg4ff_usb_revision lg4ff_revs[] = {
-       {DFGT_REV_MAJ, DFGT_REV_MIN, &native_dfgt},     /* Driving Force GT */
-       {DFGT_REV_MAJ, DFGT2_REV_MIN, &native_dfgt},    /* Driving Force GT v2 */
-       {DFP_REV_MAJ,  DFP_REV_MIN,  &native_dfp},      /* Driving Force Pro */
-       {G25_REV_MAJ,  G25_REV_MIN,  &native_g25},      /* G25 */
-       {G27_REV_MAJ,  G27_REV_MIN,  &native_g27},      /* G27 */
-       {G27_REV_MAJ,  G27_2_REV_MIN,  &native_g27},    /* G27 v2 */
+/* EXT_CMD1 - Understood by DFP, G25, G27 and DFGT */
+static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext01_dfp = {
+       1,
+       {0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+/* EXT_CMD16 - Understood by G25 and G27 */
+static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext16_g25 = {
+       1,
+       {0xf8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}
 };
 
 /* Recalculates X axis value accordingly to currently selected range */
@@ -396,20 +510,216 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
        hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
-static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_native_cmd *cmd)
+static const struct lg4ff_compat_mode_switch *lg4ff_get_mode_switch_command(const u16 real_product_id, const u16 target_product_id)
+{
+       switch (real_product_id) {
+       case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+               switch (target_product_id) {
+               case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+                       return &lg4ff_mode_switch_ext01_dfp;
+               /* DFP can only be switched to its native mode */
+               default:
+                       return NULL;
+               }
+               break;
+       case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
+               switch (target_product_id) {
+               case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+                       return &lg4ff_mode_switch_ext01_dfp;
+               case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
+                       return &lg4ff_mode_switch_ext16_g25;
+               /* G25 can only be switched to DFP mode or its native mode */
+               default:
+                       return NULL;
+               }
+               break;
+       case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
+               switch (target_product_id) {
+               case USB_DEVICE_ID_LOGITECH_WHEEL:
+                       return &lg4ff_mode_switch_ext09_dfex;
+               case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+                       return &lg4ff_mode_switch_ext09_dfp;
+               case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
+                       return &lg4ff_mode_switch_ext09_g25;
+               case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
+                       return &lg4ff_mode_switch_ext09_g27;
+               /* G27 can only be switched to DF-EX, DFP, G25 or its native mode */
+               default:
+                       return NULL;
+               }
+               break;
+       case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
+               switch (target_product_id) {
+               case USB_DEVICE_ID_LOGITECH_WHEEL:
+                       return &lg4ff_mode_switch_ext09_dfex;
+               case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+                       return &lg4ff_mode_switch_ext09_dfp;
+               case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
+                       return &lg4ff_mode_switch_ext09_dfgt;
+               /* DFGT can only be switched to DF-EX, DFP or its native mode */
+               default:
+                       return NULL;
+               }
+               break;
+       /* No other wheels have multiple modes */
+       default:
+               return NULL;
+       }
+}
+
+static int lg4ff_switch_compatibility_mode(struct hid_device *hid, const struct lg4ff_compat_mode_switch *s)
 {
        struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
-       __u8 i, j;
+       __s32 *value = report->field[0]->value;
+       u8 i;
 
-       j = 0;
-       while (j < 7*cmd->cmd_num) {
-               for (i = 0; i < 7; i++)
-                       report->field[0]->value[i] = cmd->cmd[j++];
+       for (i = 0; i < s->cmd_count; i++) {
+               u8 j;
+
+               for (j = 0; j < 7; j++)
+                       value[j] = s->cmd[j + (7*i)];
 
                hid_hw_request(hid, report, HID_REQ_SET_REPORT);
        }
+       hid_hw_wait(hid);
+       return 0;
+}
+
+static ssize_t lg4ff_alternate_modes_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct hid_device *hid = to_hid_device(dev);
+       struct lg4ff_device_entry *entry;
+       struct lg_drv_data *drv_data;
+       ssize_t count = 0;
+       int i;
+
+       drv_data = hid_get_drvdata(hid);
+       if (!drv_data) {
+               hid_err(hid, "Private driver data not found!\n");
+               return 0;
+       }
+
+       entry = drv_data->device_props;
+       if (!entry) {
+               hid_err(hid, "Device properties not found!\n");
+               return 0;
+       }
+
+       if (!entry->real_name) {
+               hid_err(hid, "NULL pointer to string\n");
+               return 0;
+       }
+
+       for (i = 0; i < LG4FF_MODE_MAX_IDX; i++) {
+               if (entry->alternate_modes & BIT(i)) {
+                       /* Print tag and full name */
+                       count += scnprintf(buf + count, PAGE_SIZE - count, "%s: %s",
+                                          lg4ff_alternate_modes[i].tag,
+                                          !lg4ff_alternate_modes[i].product_id ? entry->real_name : lg4ff_alternate_modes[i].name);
+                       if (count >= PAGE_SIZE - 1)
+                               return count;
+
+                       /* Mark the currently active mode with an asterisk */
+                       if (lg4ff_alternate_modes[i].product_id == entry->product_id ||
+                           (lg4ff_alternate_modes[i].product_id == 0 && entry->product_id == entry->real_product_id))
+                               count += scnprintf(buf + count, PAGE_SIZE - count, " *\n");
+                       else
+                               count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
+
+                       if (count >= PAGE_SIZE - 1)
+                               return count;
+               }
+       }
+
+       return count;
+}
+
+static ssize_t lg4ff_alternate_modes_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct hid_device *hid = to_hid_device(dev);
+       struct lg4ff_device_entry *entry;
+       struct lg_drv_data *drv_data;
+       const struct lg4ff_compat_mode_switch *s;
+       u16 target_product_id = 0;
+       int i, ret;
+       char *lbuf;
+
+       drv_data = hid_get_drvdata(hid);
+       if (!drv_data) {
+               hid_err(hid, "Private driver data not found!\n");
+               return -EINVAL;
+       }
+
+       entry = drv_data->device_props;
+       if (!entry) {
+               hid_err(hid, "Device properties not found!\n");
+               return -EINVAL;
+       }
+
+       /* Allow \n at the end of the input parameter */
+       lbuf = kasprintf(GFP_KERNEL, "%s", buf);
+       if (!lbuf)
+               return -ENOMEM;
+
+       i = strlen(lbuf);
+       if (lbuf[i-1] == '\n') {
+               if (i == 1) {
+                       kfree(lbuf);
+                       return -EINVAL;
+               }
+               lbuf[i-1] = '\0';
+       }
+
+       for (i = 0; i < LG4FF_MODE_MAX_IDX; i++) {
+               const u16 mode_product_id = lg4ff_alternate_modes[i].product_id;
+               const char *tag = lg4ff_alternate_modes[i].tag;
+
+               if (entry->alternate_modes & BIT(i)) {
+                       if (!strcmp(tag, lbuf)) {
+                               if (!mode_product_id)
+                                       target_product_id = entry->real_product_id;
+                               else
+                                       target_product_id = mode_product_id;
+                               break;
+                       }
+               }
+       }
+
+       if (i == LG4FF_MODE_MAX_IDX) {
+               hid_info(hid, "Requested mode \"%s\" is not supported by the device\n", lbuf);
+               kfree(lbuf);
+               return -EINVAL;
+       }
+       kfree(lbuf); /* Not needed anymore */
+
+       if (target_product_id == entry->product_id) /* Nothing to do */
+               return count;
+
+       /* Automatic switching has to be disabled for the switch to DF-EX mode to work correctly */
+       if (target_product_id == USB_DEVICE_ID_LOGITECH_WHEEL && !lg4ff_no_autoswitch) {
+               hid_info(hid, "\"%s\" cannot be switched to \"DF-EX\" mode. Load the \"hid_logitech\" module with \"lg4ff_no_autoswitch=1\" parameter set and try again\n",
+                        entry->real_name);
+               return -EINVAL;
+       }
+
+       /* Take care of hardware limitations */
+       if ((entry->real_product_id == USB_DEVICE_ID_LOGITECH_DFP_WHEEL || entry->real_product_id == USB_DEVICE_ID_LOGITECH_G25_WHEEL) &&
+           entry->product_id > target_product_id) {
+               hid_info(hid, "\"%s\" cannot be switched back into \"%s\" mode\n", entry->real_name, lg4ff_alternate_modes[i].name);
+               return -EINVAL;
+       }
+
+       s = lg4ff_get_mode_switch_command(entry->real_product_id, target_product_id);
+       if (!s) {
+               hid_err(hid, "Invalid target product ID %X\n", target_product_id);
+               return -EINVAL;
+       }
+
+       ret = lg4ff_switch_compatibility_mode(hid, s);
+       return (ret == 0 ? count : ret);
 }
+static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store);
 
 /* Read current range and display it in terminal */
 static ssize_t range_show(struct device *dev, struct device_attribute *attr,
@@ -472,6 +782,41 @@ static ssize_t range_store(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RW(range);
 
+static ssize_t lg4ff_real_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct hid_device *hid = to_hid_device(dev);
+       struct lg4ff_device_entry *entry;
+       struct lg_drv_data *drv_data;
+       size_t count;
+
+       drv_data = hid_get_drvdata(hid);
+       if (!drv_data) {
+               hid_err(hid, "Private driver data not found!\n");
+               return 0;
+       }
+
+       entry = drv_data->device_props;
+       if (!entry) {
+               hid_err(hid, "Device properties not found!\n");
+               return 0;
+       }
+
+       if (!entry->real_tag || !entry->real_name) {
+               hid_err(hid, "NULL pointer to string\n");
+               return 0;
+       }
+
+       count = scnprintf(buf, PAGE_SIZE, "%s: %s\n", entry->real_tag, entry->real_name);
+       return count;
+}
+
+static ssize_t lg4ff_real_id_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       /* Real ID is a read-only value */
+       return -EPERM;
+}
+static DEVICE_ATTR(real_id, S_IRUGO, lg4ff_real_id_show, lg4ff_real_id_store);
+
 #ifdef CONFIG_LEDS_CLASS
 static void lg4ff_set_leds(struct hid_device *hid, __u8 leds)
 {
@@ -555,20 +900,119 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde
 }
 #endif
 
+static u16 lg4ff_identify_multimode_wheel(struct hid_device *hid, const u16 reported_product_id, const u16 bcdDevice)
+{
+       const struct lg4ff_wheel_ident_checklist *checklist;
+       int i, from_idx, to_idx;
+
+       switch (reported_product_id) {
+       case USB_DEVICE_ID_LOGITECH_WHEEL:
+       case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+               checklist = &lg4ff_main_checklist;
+               from_idx = 0;
+               to_idx = checklist->count - 1;
+               break;
+       case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
+               checklist = &lg4ff_main_checklist;
+               from_idx = 0;
+               to_idx = checklist->count - 2; /* End identity check at G25 */
+               break;
+       case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
+               checklist = &lg4ff_main_checklist;
+               from_idx = 1; /* Start identity check at G27 */
+               to_idx = checklist->count - 3; /* End identity check at G27 */
+               break;
+       case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
+               checklist = &lg4ff_main_checklist;
+               from_idx = 0;
+               to_idx = checklist->count - 4; /* End identity check at DFGT */
+               break;
+       default:
+               return 0;
+       }
+
+       for (i = from_idx; i <= to_idx; i++) {
+               const u16 mask = checklist->models[i]->mask;
+               const u16 result = checklist->models[i]->result;
+               const u16 real_product_id = checklist->models[i]->real_product_id;
+
+               if ((bcdDevice & mask) == result) {
+                       dbg_hid("Found wheel with real PID %X whose reported PID is %X\n", real_product_id, reported_product_id);
+                       return real_product_id;
+               }
+       }
+
+       /* No match found. This is either Driving Force or an unknown
+        * wheel model, do not touch it */
+       dbg_hid("Wheel with bcdDevice %X was not recognized as multimode wheel, leaving in its current mode\n", bcdDevice);
+       return 0;
+}
+
+static int lg4ff_handle_multimode_wheel(struct hid_device *hid, u16 *real_product_id, const u16 bcdDevice)
+{
+       const u16 reported_product_id = hid->product;
+       int ret;
+
+       *real_product_id = lg4ff_identify_multimode_wheel(hid, reported_product_id, bcdDevice);
+       /* Probed wheel is not a multimode wheel */
+       if (!*real_product_id) {
+               *real_product_id = reported_product_id;
+               dbg_hid("Wheel is not a multimode wheel\n");
+               return LG4FF_MMODE_NOT_MULTIMODE;
+       }
+
+       /* Switch from "Driving Force" mode to native mode automatically.
+        * Otherwise keep the wheel in its current mode */
+       if (reported_product_id == USB_DEVICE_ID_LOGITECH_WHEEL &&
+           reported_product_id != *real_product_id &&
+           !lg4ff_no_autoswitch) {
+               const struct lg4ff_compat_mode_switch *s = lg4ff_get_mode_switch_command(*real_product_id, *real_product_id);
+
+               if (!s) {
+                       hid_err(hid, "Invalid product id %X\n", *real_product_id);
+                       return LG4FF_MMODE_NOT_MULTIMODE;
+               }
+
+               ret = lg4ff_switch_compatibility_mode(hid, s);
+               if (ret) {
+                       /* Wheel could not have been switched to native mode,
+                        * leave it in "Driving Force" mode and continue */
+                       hid_err(hid, "Unable to switch wheel mode, errno %d\n", ret);
+                       return LG4FF_MMODE_IS_MULTIMODE;
+               }
+               return LG4FF_MMODE_SWITCHED;
+       }
+
+       return LG4FF_MMODE_IS_MULTIMODE;
+}
+
+
 int lg4ff_init(struct hid_device *hid)
 {
        struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
        struct input_dev *dev = hidinput->input;
+       const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor);
+       const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice);
        struct lg4ff_device_entry *entry;
        struct lg_drv_data *drv_data;
-       struct usb_device_descriptor *udesc;
        int error, i, j;
-       __u16 bcdDevice, rev_maj, rev_min;
+       int mmode_ret, mmode_idx = -1;
+       u16 real_product_id;
 
        /* Check that the report looks ok */
        if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
                return -1;
 
+       /* Check if a multimode wheel has been connected and
+        * handle it appropriately */
+       mmode_ret = lg4ff_handle_multimode_wheel(hid, &real_product_id, bcdDevice);
+
+       /* Wheel has been told to switch to native mode. There is no point in going on
+        * with the initialization as the wheel will do a USB reset when it switches mode
+        */
+       if (mmode_ret == LG4FF_MMODE_SWITCHED)
+               return 0;
+
        /* Check what wheel has been connected */
        for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) {
                if (hid->product == lg4ff_devices[i].product_id) {
@@ -583,25 +1027,15 @@ int lg4ff_init(struct hid_device *hid)
                return -1;
        }
 
-       /* Attempt to switch wheel to native mode when applicable */
-       udesc = &(hid_to_usb_dev(hid)->descriptor);
-       if (!udesc) {
-               hid_err(hid, "NULL USB device descriptor\n");
-               return -1;
-       }
-       bcdDevice = le16_to_cpu(udesc->bcdDevice);
-       rev_maj = bcdDevice >> 8;
-       rev_min = bcdDevice & 0xff;
-
-       if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_WHEEL) {
-               dbg_hid("Generic wheel detected, can it do native?\n");
-               dbg_hid("USB revision: %2x.%02x\n", rev_maj, rev_min);
+       if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) {
+               for (mmode_idx = 0; mmode_idx < ARRAY_SIZE(lg4ff_multimode_wheels); mmode_idx++) {
+                       if (real_product_id == lg4ff_multimode_wheels[mmode_idx].product_id)
+                               break;
+               }
 
-               for (j = 0; j < ARRAY_SIZE(lg4ff_revs); j++) {
-                       if (lg4ff_revs[j].rev_maj == rev_maj && lg4ff_revs[j].rev_min == rev_min) {
-                               hid_lg4ff_switch_native(hid, lg4ff_revs[j].command);
-                               hid_info(hid, "Switched to native mode\n");
-                       }
+               if (mmode_idx == ARRAY_SIZE(lg4ff_multimode_wheels)) {
+                       hid_err(hid, "Device product ID %X is not listed as a multimode wheel", real_product_id);
+                       return -1;
                }
        }
 
@@ -630,14 +1064,23 @@ int lg4ff_init(struct hid_device *hid)
        drv_data->device_props = entry;
 
        entry->product_id = lg4ff_devices[i].product_id;
+       entry->real_product_id = real_product_id;
        entry->min_range = lg4ff_devices[i].min_range;
        entry->max_range = lg4ff_devices[i].max_range;
        entry->set_range = lg4ff_devices[i].set_range;
+       if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) {
+               BUG_ON(mmode_idx == -1);
+               entry->alternate_modes = lg4ff_multimode_wheels[mmode_idx].alternate_modes;
+               entry->real_tag = lg4ff_multimode_wheels[mmode_idx].real_tag;
+               entry->real_name = lg4ff_multimode_wheels[mmode_idx].real_name;
+       }
 
        /* Check if autocentering is available and
         * set the centering force to zero by default */
        if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
-               if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */
+               /* Formula Force EX expects different autocentering command */
+               if ((bcdDevice >> 8) == LG4FF_FFEX_REV_MAJ &&
+                   (bcdDevice & 0xff) == LG4FF_FFEX_REV_MIN)
                        dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex;
                else
                        dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default;
@@ -649,6 +1092,14 @@ int lg4ff_init(struct hid_device *hid)
        error = device_create_file(&hid->dev, &dev_attr_range);
        if (error)
                return error;
+       if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) {
+               error = device_create_file(&hid->dev, &dev_attr_real_id);
+               if (error)
+                       return error;
+               error = device_create_file(&hid->dev, &dev_attr_alternate_modes);
+               if (error)
+                       return error;
+       }
        dbg_hid("sysfs interface created\n");
 
        /* Set the maximum range to start with */
@@ -711,24 +1162,26 @@ out:
        return 0;
 }
 
-
-
 int lg4ff_deinit(struct hid_device *hid)
 {
        struct lg4ff_device_entry *entry;
        struct lg_drv_data *drv_data;
 
-       device_remove_file(&hid->dev, &dev_attr_range);
-
        drv_data = hid_get_drvdata(hid);
        if (!drv_data) {
                hid_err(hid, "Error while deinitializing device, no private driver data.\n");
                return -1;
        }
        entry = drv_data->device_props;
-       if (!entry) {
-               hid_err(hid, "Error while deinitializing device, no device properties data.\n");
-               return -1;
+       if (!entry)
+               goto out; /* Nothing more to do */
+
+       device_remove_file(&hid->dev, &dev_attr_range);
+
+       /* Multimode devices will have at least the "MODE_NATIVE" bit set */
+       if (entry->alternate_modes) {
+               device_remove_file(&hid->dev, &dev_attr_real_id);
+               device_remove_file(&hid->dev, &dev_attr_alternate_modes);
        }
 
 #ifdef CONFIG_LEDS_CLASS
@@ -752,6 +1205,7 @@ int lg4ff_deinit(struct hid_device *hid)
        /* Deallocate memory */
        kfree(entry);
 
+out:
        dbg_hid("Device successfully unregistered\n");
        return 0;
 }
diff --git a/drivers/hid/hid-lg4ff.h b/drivers/hid/hid-lg4ff.h
new file mode 100644 (file)
index 0000000..5b6a508
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __HID_LG4FF_H
+#define __HID_LG4FF_H
+
+#ifdef CONFIG_LOGIWHEELS_FF
+extern int lg4ff_no_autoswitch; /* From hid-lg.c */
+
+int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
+                            struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data);
+int lg4ff_init(struct hid_device *hdev);
+int lg4ff_deinit(struct hid_device *hdev);
+#else
+static inline int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
+                                          struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data) { return 0; }
+static inline int lg4ff_init(struct hid_device *hdev) { return -1; }
+static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; }
+#endif
+
+#endif
index e77658cd037ca858270f8c238becbf93b7f22e8a..b3cf6fd4be96473ba62ebbbf92d1522c024a509e 100644 (file)
@@ -28,6 +28,11 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
 MODULE_AUTHOR("Nestor Lopez Casado <nlopezcasad@logitech.com>");
 
+static bool disable_raw_mode;
+module_param(disable_raw_mode, bool, 0644);
+MODULE_PARM_DESC(disable_raw_mode,
+       "Disable Raw mode reporting for touchpads and keep firmware gestures.");
+
 #define REPORT_ID_HIDPP_SHORT                  0x10
 #define REPORT_ID_HIDPP_LONG                   0x11
 
@@ -1188,6 +1193,11 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
        hidpp->quirks = id->driver_data;
 
+       if (disable_raw_mode) {
+               hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP;
+               hidpp->quirks &= ~HIDPP_QUIRK_DELAYED_INIT;
+       }
+
        if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) {
                ret = wtp_allocate(hdev, id);
                if (ret)
@@ -1210,6 +1220,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
        connected = hidpp_is_connected(hidpp);
        if (id->group != HID_GROUP_LOGITECH_DJ_DEVICE) {
                if (!connected) {
+                       ret = -ENODEV;
                        hid_err(hdev, "Device not connected");
                        hid_device_io_stop(hdev);
                        goto hid_parse_fail;
index f65e78b46999999bc8320240cf1adea51547a9b1..6a9b05b328a9d40e06b09ed8f8c6e6010669374b 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/hid.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/input/mt.h>
 #include <linux/string.h>
 
@@ -72,6 +71,8 @@ MODULE_LICENSE("GPL");
 #define MT_INPUTMODE_TOUCHSCREEN       0x02
 #define MT_INPUTMODE_TOUCHPAD          0x03
 
+#define MT_BUTTONTYPE_CLICKPAD         0
+
 struct mt_slot {
        __s32 x, y, cx, cy, p, w, h;
        __s32 contactid;        /* the device ContactID assigned to this slot */
@@ -116,6 +117,8 @@ struct mt_device {
        __u8 touches_by_report; /* how many touches are present in one report:
                                * 1 means we should use a serial protocol
                                * > 1 means hybrid (multitouch) protocol */
+       __u8 buttons_count;     /* number of physical buttons per touchpad */
+       bool is_buttonpad;      /* is this device a button pad? */
        bool serial_maybe;      /* need to check for serial protocol */
        bool curvalid;          /* is the current contact valid? */
        unsigned mt_flags;      /* flags to pass to input-mt */
@@ -333,6 +336,16 @@ static void mt_feature_mapping(struct hid_device *hdev,
                        /* check if the maxcontacts is given by the class */
                        td->maxcontacts = td->mtclass.maxcontacts;
 
+               break;
+       case HID_DG_BUTTONTYPE:
+               if (usage->usage_index >= field->report_count) {
+                       dev_err(&hdev->dev, "HID_DG_BUTTONTYPE out of range\n");
+                       break;
+               }
+
+               if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD)
+                       td->is_buttonpad = true;
+
                break;
        }
 }
@@ -379,6 +392,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
        }
 
+       /* count the buttons on touchpads */
+       if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
+               td->buttons_count++;
+
        if (usage->usage_index)
                prev_usage = &field->usage[usage->usage_index - 1];
 
@@ -728,6 +745,13 @@ static void mt_touch_input_configured(struct hid_device *hdev,
        if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
                td->mt_flags |= INPUT_MT_DROP_UNUSED;
 
+       /* check for clickpads */
+       if ((td->mt_flags & INPUT_MT_POINTER) && (td->buttons_count == 1))
+               td->is_buttonpad = true;
+
+       if (td->is_buttonpad)
+               __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+
        input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
 
        td->mt_flags = 0;
index 49d4fe4f5987e2e7074d6fa77cfd8974353c4a8a..368ffdf2c0a3af086d9242f00476f598a3fffdf9 100644 (file)
@@ -104,6 +104,7 @@ struct rmi_data {
 
        unsigned long flags;
 
+       struct rmi_function f01;
        struct rmi_function f11;
        struct rmi_function f30;
 
@@ -124,6 +125,7 @@ struct rmi_data {
        struct hid_device *hdev;
 
        unsigned long device_flags;
+       unsigned long firmware_id;
 };
 
 #define RMI_PAGE(addr) (((addr) >> 8) & 0xff)
@@ -272,6 +274,46 @@ static inline int rmi_read(struct hid_device *hdev, u16 addr, void *buf)
        return rmi_read_block(hdev, addr, buf, 1);
 }
 
+static int rmi_write_block(struct hid_device *hdev, u16 addr, void *buf,
+               const int len)
+{
+       struct rmi_data *data = hid_get_drvdata(hdev);
+       int ret;
+
+       mutex_lock(&data->page_mutex);
+
+       if (RMI_PAGE(addr) != data->page) {
+               ret = rmi_set_page(hdev, RMI_PAGE(addr));
+               if (ret < 0)
+                       goto exit;
+       }
+
+       data->writeReport[0] = RMI_WRITE_REPORT_ID;
+       data->writeReport[1] = len;
+       data->writeReport[2] = addr & 0xFF;
+       data->writeReport[3] = (addr >> 8) & 0xFF;
+       memcpy(&data->writeReport[4], buf, len);
+
+       ret = rmi_write_report(hdev, data->writeReport,
+                                       data->output_report_size);
+       if (ret < 0) {
+               dev_err(&hdev->dev,
+                       "failed to write request output report (%d)\n",
+                       ret);
+               goto exit;
+       }
+       ret = 0;
+
+exit:
+       mutex_unlock(&data->page_mutex);
+       return ret;
+}
+
+static inline int rmi_write(struct hid_device *hdev, u16 addr, void *buf)
+{
+       return rmi_write_block(hdev, addr, buf, 1);
+}
+
 static void rmi_f11_process_touch(struct rmi_data *hdata, int slot,
                u8 finger_state, u8 *touch_data)
 {
@@ -532,6 +574,9 @@ static void rmi_register_function(struct rmi_data *data,
        u16 page_base = page << 8;
 
        switch (pdt_entry->function_number) {
+       case 0x01:
+               f = &data->f01;
+               break;
        case 0x11:
                f = &data->f11;
                break;
@@ -604,6 +649,92 @@ error_exit:
        return retval;
 }
 
+#define RMI_DEVICE_F01_BASIC_QUERY_LEN 11
+
+static int rmi_populate_f01(struct hid_device *hdev)
+{
+       struct rmi_data *data = hid_get_drvdata(hdev);
+       u8 basic_queries[RMI_DEVICE_F01_BASIC_QUERY_LEN];
+       u8 info[3];
+       int ret;
+       bool has_query42;
+       bool has_lts;
+       bool has_sensor_id;
+       bool has_ds4_queries = false;
+       bool has_build_id_query = false;
+       bool has_package_id_query = false;
+       u16 query_offset = data->f01.query_base_addr;
+       u16 prod_info_addr;
+       u8 ds4_query_len;
+
+       ret = rmi_read_block(hdev, query_offset, basic_queries,
+                               RMI_DEVICE_F01_BASIC_QUERY_LEN);
+       if (ret) {
+               hid_err(hdev, "Can not read basic queries from Function 0x1.\n");
+               return ret;
+       }
+
+       has_lts = !!(basic_queries[0] & BIT(2));
+       has_sensor_id = !!(basic_queries[1] & BIT(3));
+       has_query42 = !!(basic_queries[1] & BIT(7));
+
+       query_offset += 11;
+       prod_info_addr = query_offset + 6;
+       query_offset += 10;
+
+       if (has_lts)
+               query_offset += 20;
+
+       if (has_sensor_id)
+               query_offset++;
+
+       if (has_query42) {
+               ret = rmi_read(hdev, query_offset, info);
+               if (ret) {
+                       hid_err(hdev, "Can not read query42.\n");
+                       return ret;
+               }
+               has_ds4_queries = !!(info[0] & BIT(0));
+               query_offset++;
+       }
+
+       if (has_ds4_queries) {
+               ret = rmi_read(hdev, query_offset, &ds4_query_len);
+               if (ret) {
+                       hid_err(hdev, "Can not read DS4 Query length.\n");
+                       return ret;
+               }
+               query_offset++;
+
+               if (ds4_query_len > 0) {
+                       ret = rmi_read(hdev, query_offset, info);
+                       if (ret) {
+                               hid_err(hdev, "Can not read DS4 query.\n");
+                               return ret;
+                       }
+
+                       has_package_id_query = !!(info[0] & BIT(0));
+                       has_build_id_query = !!(info[0] & BIT(1));
+               }
+       }
+
+       if (has_package_id_query)
+               prod_info_addr++;
+
+       if (has_build_id_query) {
+               ret = rmi_read_block(hdev, prod_info_addr, info, 3);
+               if (ret) {
+                       hid_err(hdev, "Can not read product info.\n");
+                       return ret;
+               }
+
+               data->firmware_id = info[1] << 8 | info[0];
+               data->firmware_id += info[2] * 65536;
+       }
+
+       return 0;
+}
+
 static int rmi_populate_f11(struct hid_device *hdev)
 {
        struct rmi_data *data = hid_get_drvdata(hdev);
@@ -620,6 +751,8 @@ static int rmi_populate_f11(struct hid_device *hdev)
        bool has_gestures;
        bool has_rel;
        bool has_data40 = false;
+       bool has_dribble = false;
+       bool has_palm_detect = false;
        unsigned x_size, y_size;
        u16 query_offset;
 
@@ -661,6 +794,14 @@ static int rmi_populate_f11(struct hid_device *hdev)
        has_rel = !!(buf[0] & BIT(3));
        has_gestures = !!(buf[0] & BIT(5));
 
+       ret = rmi_read(hdev, data->f11.query_base_addr + 5, buf);
+       if (ret) {
+               hid_err(hdev, "can not get absolute data sources: %d.\n", ret);
+               return ret;
+       }
+
+       has_dribble = !!(buf[0] & BIT(4));
+
        /*
         * At least 4 queries are guaranteed to be present in F11
         * +1 for query 5 which is present since absolute events are
@@ -680,6 +821,7 @@ static int rmi_populate_f11(struct hid_device *hdev)
                                ret);
                        return ret;
                }
+               has_palm_detect = !!(buf[0] & BIT(0));
                has_query10 = !!(buf[0] & BIT(2));
 
                query_offset += 2; /* query 7 and 8 are present */
@@ -766,17 +908,38 @@ static int rmi_populate_f11(struct hid_device *hdev)
         * retrieve the ctrl registers
         * the ctrl register has a size of 20 but a fw bug split it into 16 + 4,
         * and there is no way to know if the first 20 bytes are here or not.
-        * We use only the first 10 bytes, so get only them.
+        * We use only the first 12 bytes, so get only them.
         */
-       ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, 10);
+       ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, 12);
        if (ret) {
-               hid_err(hdev, "can not read ctrl block of size 10: %d.\n", ret);
+               hid_err(hdev, "can not read ctrl block of size 11: %d.\n", ret);
                return ret;
        }
 
        data->max_x = buf[6] | (buf[7] << 8);
        data->max_y = buf[8] | (buf[9] << 8);
 
+       if (has_dribble) {
+               buf[0] = buf[0] & ~BIT(6);
+               ret = rmi_write(hdev, data->f11.control_base_addr, buf);
+               if (ret) {
+                       hid_err(hdev, "can not write to control reg 0: %d.\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       if (has_palm_detect) {
+               buf[11] = buf[11] & ~BIT(0);
+               ret = rmi_write(hdev, data->f11.control_base_addr + 11,
+                               &buf[11]);
+               if (ret) {
+                       hid_err(hdev, "can not write to control reg 11: %d.\n",
+                               ret);
+                       return ret;
+               }
+       }
+
        return 0;
 }
 
@@ -858,6 +1021,12 @@ static int rmi_populate(struct hid_device *hdev)
                return ret;
        }
 
+       ret = rmi_populate_f01(hdev);
+       if (ret) {
+               hid_err(hdev, "Error while initializing F01 (%d).\n", ret);
+               return ret;
+       }
+
        ret = rmi_populate_f11(hdev);
        if (ret) {
                hid_err(hdev, "Error while initializing F11 (%d).\n", ret);
@@ -907,6 +1076,8 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
        if (ret)
                goto exit;
 
+       hid_info(hdev, "firmware id: %ld\n", data->firmware_id);
+
        __set_bit(EV_ABS, input->evbit);
        input_set_abs_params(input, ABS_MT_POSITION_X, 1, data->max_x, 0, 0);
        input_set_abs_params(input, ABS_MT_POSITION_Y, 1, data->max_y, 0, 0);
diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c
new file mode 100644 (file)
index 0000000..5614fee
--- /dev/null
@@ -0,0 +1,849 @@
+/*
+ * hid-sensor-custom.c
+ * Copyright (c) 2015, 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/module.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/kfifo.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/bsearch.h>
+#include <linux/platform_device.h>
+#include <linux/hid-sensor-hub.h>
+
+#define HID_CUSTOM_NAME_LENGTH         64
+#define HID_CUSTOM_MAX_CORE_ATTRS      10
+#define HID_CUSTOM_TOTAL_ATTRS         (HID_CUSTOM_MAX_CORE_ATTRS + 1)
+#define HID_CUSTOM_FIFO_SIZE           4096
+#define HID_CUSTOM_MAX_FEATURE_BYTES   64
+
+struct hid_sensor_custom_field {
+       int report_id;
+       char group_name[HID_CUSTOM_NAME_LENGTH];
+       struct hid_sensor_hub_attribute_info attribute;
+       struct device_attribute sd_attrs[HID_CUSTOM_MAX_CORE_ATTRS];
+       char attr_name[HID_CUSTOM_TOTAL_ATTRS][HID_CUSTOM_NAME_LENGTH];
+       struct attribute *attrs[HID_CUSTOM_TOTAL_ATTRS];
+       struct attribute_group hid_custom_attribute_group;
+};
+
+struct hid_sensor_custom {
+       struct mutex mutex;
+       struct platform_device *pdev;
+       struct hid_sensor_hub_device *hsdev;
+       struct hid_sensor_hub_callbacks callbacks;
+       int sensor_field_count;
+       struct hid_sensor_custom_field *fields;
+       int input_field_count;
+       int input_report_size;
+       int input_report_recd_size;
+       bool input_skip_sample;
+       bool enable;
+       struct hid_sensor_custom_field *power_state;
+       struct hid_sensor_custom_field *report_state;
+       struct miscdevice custom_dev;
+       struct kfifo data_fifo;
+       unsigned long misc_opened;
+       wait_queue_head_t wait;
+};
+
+/* Header for each sample to user space via dev interface */
+struct hid_sensor_sample {
+       u32 usage_id;
+       u64 timestamp;
+       u32 raw_len;
+} __packed;
+
+static struct attribute hid_custom_attrs[] = {
+       {.name = "name", .mode = S_IRUGO},
+       {.name = "units", .mode = S_IRUGO},
+       {.name = "unit-expo", .mode = S_IRUGO},
+       {.name = "minimum", .mode = S_IRUGO},
+       {.name = "maximum", .mode = S_IRUGO},
+       {.name = "size", .mode = S_IRUGO},
+       {.name = "value", .mode = S_IWUSR | S_IRUGO},
+       {.name = NULL}
+};
+
+static const struct hid_custom_usage_desc {
+       int usage_id;
+       char *desc;
+} hid_custom_usage_desc_table[] = {
+       {0x200201,      "event-sensor-state"},
+       {0x200202,      "event-sensor-event"},
+       {0x200301,      "property-friendly-name"},
+       {0x200302,      "property-persistent-unique-id"},
+       {0x200303,      "property-sensor-status"},
+       {0x200304,      "property-min-report-interval"},
+       {0x200305,      "property-sensor-manufacturer"},
+       {0x200306,      "property-sensor-model"},
+       {0x200307,      "property-sensor-serial-number"},
+       {0x200308,      "property-sensor-description"},
+       {0x200309,      "property-sensor-connection-type"},
+       {0x20030A,      "property-sensor-device-path"},
+       {0x20030B,      "property-hardware-revision"},
+       {0x20030C,      "property-firmware-version"},
+       {0x20030D,      "property-release-date"},
+       {0x20030E,      "property-report-interval"},
+       {0x20030F,      "property-change-sensitivity-absolute"},
+       {0x200310,      "property-change-sensitivity-percent-range"},
+       {0x200311,      "property-change-sensitivity-percent-relative"},
+       {0x200312,      "property-accuracy"},
+       {0x200313,      "property-resolution"},
+       {0x200314,      "property-maximum"},
+       {0x200315,      "property-minimum"},
+       {0x200316,      "property-reporting-state"},
+       {0x200317,      "property-sampling-rate"},
+       {0x200318,      "property-response-curve"},
+       {0x200319,      "property-power-state"},
+       {0x200540,      "data-field-custom"},
+       {0x200541,      "data-field-custom-usage"},
+       {0x200542,      "data-field-custom-boolean-array"},
+       {0x200543,      "data-field-custom-value"},
+       {0x200544,      "data-field-custom-value_1"},
+       {0x200545,      "data-field-custom-value_2"},
+       {0x200546,      "data-field-custom-value_3"},
+       {0x200547,      "data-field-custom-value_4"},
+       {0x200548,      "data-field-custom-value_5"},
+       {0x200549,      "data-field-custom-value_6"},
+       {0x20054A,      "data-field-custom-value_7"},
+       {0x20054B,      "data-field-custom-value_8"},
+       {0x20054C,      "data-field-custom-value_9"},
+       {0x20054D,      "data-field-custom-value_10"},
+       {0x20054E,      "data-field-custom-value_11"},
+       {0x20054F,      "data-field-custom-value_12"},
+       {0x200550,      "data-field-custom-value_13"},
+       {0x200551,      "data-field-custom-value_14"},
+       {0x200552,      "data-field-custom-value_15"},
+       {0x200553,      "data-field-custom-value_16"},
+       {0x200554,      "data-field-custom-value_17"},
+       {0x200555,      "data-field-custom-value_18"},
+       {0x200556,      "data-field-custom-value_19"},
+       {0x200557,      "data-field-custom-value_20"},
+       {0x200558,      "data-field-custom-value_21"},
+       {0x200559,      "data-field-custom-value_22"},
+       {0x20055A,      "data-field-custom-value_23"},
+       {0x20055B,      "data-field-custom-value_24"},
+       {0x20055C,      "data-field-custom-value_25"},
+       {0x20055D,      "data-field-custom-value_26"},
+       {0x20055E,      "data-field-custom-value_27"},
+       {0x20055F,      "data-field-custom-value_28"},
+};
+
+static int usage_id_cmp(const void *p1, const void *p2)
+{
+       if (*(int *)p1 < *(int *)p2)
+               return -1;
+
+       if (*(int *)p1 > *(int *)p2)
+               return 1;
+
+       return 0;
+}
+
+static ssize_t enable_sensor_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct hid_sensor_custom *sensor_inst = platform_get_drvdata(pdev);
+
+       return sprintf(buf, "%d\n", sensor_inst->enable);
+}
+
+static int set_power_report_state(struct hid_sensor_custom *sensor_inst,
+                                 bool state)
+{
+       int power_val = -1;
+       int report_val = -1;
+       u32 power_state_usage_id;
+       u32 report_state_usage_id;
+       int ret;
+
+       /*
+        * It is possible that the power/report state ids are not present.
+        * In this case this function will return success. But if the
+        * ids are present, then it will return error if set fails.
+        */
+       if (state) {
+               power_state_usage_id =
+                       HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
+               report_state_usage_id =
+                       HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
+       } else {
+               power_state_usage_id =
+                       HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM;
+               report_state_usage_id =
+                       HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM;
+       }
+
+       if (sensor_inst->power_state)
+               power_val = hid_sensor_get_usage_index(sensor_inst->hsdev,
+                               sensor_inst->power_state->attribute.report_id,
+                               sensor_inst->power_state->attribute.index,
+                               power_state_usage_id);
+       if (sensor_inst->report_state)
+               report_val = hid_sensor_get_usage_index(sensor_inst->hsdev,
+                               sensor_inst->report_state->attribute.report_id,
+                               sensor_inst->report_state->attribute.index,
+                               report_state_usage_id);
+
+       if (power_val >= 0) {
+               power_val +=
+                       sensor_inst->power_state->attribute.logical_minimum;
+               ret = sensor_hub_set_feature(sensor_inst->hsdev,
+                               sensor_inst->power_state->attribute.report_id,
+                               sensor_inst->power_state->attribute.index,
+                               sizeof(power_val),
+                               &power_val);
+               if (ret) {
+                       hid_err(sensor_inst->hsdev->hdev,
+                               "Set power state failed\n");
+                       return ret;
+               }
+       }
+
+       if (report_val >= 0) {
+               report_val +=
+                       sensor_inst->report_state->attribute.logical_minimum;
+               ret = sensor_hub_set_feature(sensor_inst->hsdev,
+                               sensor_inst->report_state->attribute.report_id,
+                               sensor_inst->report_state->attribute.index,
+                               sizeof(report_val),
+                               &report_val);
+               if (ret) {
+                       hid_err(sensor_inst->hsdev->hdev,
+                               "Set report state failed\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static ssize_t enable_sensor_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct hid_sensor_custom *sensor_inst = platform_get_drvdata(pdev);
+       int value;
+       int ret = -EINVAL;
+
+       if (kstrtoint(buf, 0, &value) != 0)
+               return -EINVAL;
+
+       mutex_lock(&sensor_inst->mutex);
+       if (value && !sensor_inst->enable) {
+               ret = sensor_hub_device_open(sensor_inst->hsdev);
+               if (ret)
+                       goto unlock_state;
+
+               ret = set_power_report_state(sensor_inst, true);
+               if (ret) {
+                       sensor_hub_device_close(sensor_inst->hsdev);
+                       goto unlock_state;
+               }
+               sensor_inst->enable = true;
+       } else if (!value && sensor_inst->enable) {
+               ret = set_power_report_state(sensor_inst, false);
+               sensor_hub_device_close(sensor_inst->hsdev);
+               sensor_inst->enable = false;
+       }
+unlock_state:
+       mutex_unlock(&sensor_inst->mutex);
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+static DEVICE_ATTR_RW(enable_sensor);
+
+static struct attribute *enable_sensor_attrs[] = {
+       &dev_attr_enable_sensor.attr,
+       NULL,
+};
+
+static struct attribute_group enable_sensor_attr_group = {
+       .attrs = enable_sensor_attrs,
+};
+
+static ssize_t show_value(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct hid_sensor_custom *sensor_inst = platform_get_drvdata(pdev);
+       struct hid_sensor_hub_attribute_info *attribute;
+       int index, usage, field_index;
+       char name[HID_CUSTOM_NAME_LENGTH];
+       bool feature = false;
+       bool input = false;
+       int value = 0;
+
+       if (sscanf(attr->attr.name, "feature-%d-%x-%s", &index, &usage,
+                  name) == 3) {
+               feature = true;
+               field_index = index + sensor_inst->input_field_count;
+       } else if (sscanf(attr->attr.name, "input-%d-%x-%s", &index, &usage,
+                  name) == 3) {
+               input = true;
+               field_index = index;
+       } else
+               return -EINVAL;
+
+       if (!strncmp(name, "value", strlen("value"))) {
+               u32 report_id;
+               int ret;
+
+               attribute = &sensor_inst->fields[field_index].attribute;
+               report_id = attribute->report_id;
+               if (feature) {
+                       u8 values[HID_CUSTOM_MAX_FEATURE_BYTES];
+                       int len = 0;
+                       u64 value = 0;
+                       int i = 0;
+
+                       ret = sensor_hub_get_feature(sensor_inst->hsdev,
+                                                    report_id,
+                                                    index,
+                                                    sizeof(values), values);
+                       if (ret < 0)
+                               return ret;
+
+                       while (i < ret) {
+                               if (i + attribute->size > ret) {
+                                       len += snprintf(&buf[len],
+                                                       PAGE_SIZE - len,
+                                                       "%d ", values[i]);
+                                       break;
+                               }
+                               switch (attribute->size) {
+                               case 2:
+                                       value = (u64) *(u16 *)&values[i];
+                                       i += attribute->size;
+                                       break;
+                               case 4:
+                                       value = (u64) *(u32 *)&values[i];
+                                       i += attribute->size;
+                                       break;
+                               case 8:
+                                       value = *(u64 *)&values[i];
+                                       i += attribute->size;
+                                       break;
+                               default:
+                                       value = (u64) values[i];
+                                       ++i;
+                                       break;
+                               }
+                               len += snprintf(&buf[len], PAGE_SIZE - len,
+                                               "%lld ", value);
+                       }
+                       len += snprintf(&buf[len], PAGE_SIZE - len, "\n");
+
+                       return len;
+               } else if (input)
+                       value = sensor_hub_input_attr_get_raw_value(
+                                               sensor_inst->hsdev,
+                                               sensor_inst->hsdev->usage,
+                                               usage, report_id,
+                                               SENSOR_HUB_SYNC);
+       } else if (!strncmp(name, "units", strlen("units")))
+               value = sensor_inst->fields[field_index].attribute.units;
+       else if (!strncmp(name, "unit-expo", strlen("unit-expo")))
+               value = sensor_inst->fields[field_index].attribute.unit_expo;
+       else if (!strncmp(name, "size", strlen("size")))
+               value = sensor_inst->fields[field_index].attribute.size;
+       else if (!strncmp(name, "minimum", strlen("minimum")))
+               value = sensor_inst->fields[field_index].attribute.
+                                                       logical_minimum;
+       else if (!strncmp(name, "maximum", strlen("maximum")))
+               value = sensor_inst->fields[field_index].attribute.
+                                                       logical_maximum;
+       else if (!strncmp(name, "name", strlen("name"))) {
+               struct hid_custom_usage_desc *usage_desc;
+
+               usage_desc = bsearch(&usage, hid_custom_usage_desc_table,
+                                    ARRAY_SIZE(hid_custom_usage_desc_table),
+                                    sizeof(struct hid_custom_usage_desc),
+                                    usage_id_cmp);
+               if (usage_desc)
+                       return snprintf(buf, PAGE_SIZE, "%s\n",
+                                       usage_desc->desc);
+               else
+                       return sprintf(buf, "not-specified\n");
+        } else
+               return -EINVAL;
+
+       return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t store_value(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct hid_sensor_custom *sensor_inst = platform_get_drvdata(pdev);
+       int index, field_index, usage;
+       char name[HID_CUSTOM_NAME_LENGTH];
+       int value;
+
+       if (sscanf(attr->attr.name, "feature-%d-%x-%s", &index, &usage,
+                  name) == 3) {
+               field_index = index + sensor_inst->input_field_count;
+       } else
+               return -EINVAL;
+
+       if (!strncmp(name, "value", strlen("value"))) {
+               u32 report_id;
+               int ret;
+
+               if (kstrtoint(buf, 0, &value) != 0)
+                       return -EINVAL;
+
+               report_id = sensor_inst->fields[field_index].attribute.
+                                                               report_id;
+               ret = sensor_hub_set_feature(sensor_inst->hsdev, report_id,
+                                            index, sizeof(value), &value);
+       } else
+               return -EINVAL;
+
+       return count;
+}
+
+static int hid_sensor_capture_sample(struct hid_sensor_hub_device *hsdev,
+                                 unsigned usage_id, size_t raw_len,
+                                 char *raw_data, void *priv)
+{
+       struct hid_sensor_custom *sensor_inst = platform_get_drvdata(priv);
+       struct hid_sensor_sample header;
+
+       /* If any error occurs in a sample, rest of the fields are ignored */
+       if (sensor_inst->input_skip_sample) {
+               hid_err(sensor_inst->hsdev->hdev, "Skipped remaining data\n");
+               return 0;
+       }
+
+       hid_dbg(sensor_inst->hsdev->hdev, "%s received %d of %d\n", __func__,
+               (int) (sensor_inst->input_report_recd_size + raw_len),
+               sensor_inst->input_report_size);
+
+       if (!test_bit(0, &sensor_inst->misc_opened))
+               return 0;
+
+       if (!sensor_inst->input_report_recd_size) {
+               int required_size = sizeof(struct hid_sensor_sample) +
+                                               sensor_inst->input_report_size;
+               header.usage_id = hsdev->usage;
+               header.raw_len = sensor_inst->input_report_size;
+               header.timestamp = ktime_get_real_ns();
+               if (kfifo_avail(&sensor_inst->data_fifo) >= required_size) {
+                       kfifo_in(&sensor_inst->data_fifo,
+                                (unsigned char *)&header,
+                                sizeof(header));
+               } else
+                       sensor_inst->input_skip_sample = true;
+       }
+       if (kfifo_avail(&sensor_inst->data_fifo) >= raw_len)
+               kfifo_in(&sensor_inst->data_fifo, (unsigned char *)raw_data,
+                        raw_len);
+
+       sensor_inst->input_report_recd_size += raw_len;
+
+       return 0;
+}
+
+static int hid_sensor_send_event(struct hid_sensor_hub_device *hsdev,
+                                unsigned usage_id, void *priv)
+{
+       struct hid_sensor_custom *sensor_inst = platform_get_drvdata(priv);
+
+       if (!test_bit(0, &sensor_inst->misc_opened))
+               return 0;
+
+       sensor_inst->input_report_recd_size = 0;
+       sensor_inst->input_skip_sample = false;
+
+       wake_up(&sensor_inst->wait);
+
+       return 0;
+}
+
+static int hid_sensor_custom_add_field(struct hid_sensor_custom *sensor_inst,
+                                      int index, int report_type,
+                                      struct hid_report *report,
+                                      struct hid_field *field)
+{
+       struct hid_sensor_custom_field *sensor_field;
+       void *fields;
+
+       fields = krealloc(sensor_inst->fields,
+                         (sensor_inst->sensor_field_count + 1) *
+                          sizeof(struct hid_sensor_custom_field), GFP_KERNEL);
+       if (!fields) {
+               kfree(sensor_inst->fields);
+               return -ENOMEM;
+       }
+       sensor_inst->fields = fields;
+       sensor_field = &sensor_inst->fields[sensor_inst->sensor_field_count];
+       sensor_field->attribute.usage_id = sensor_inst->hsdev->usage;
+       if (field->logical)
+               sensor_field->attribute.attrib_id = field->logical;
+       else
+               sensor_field->attribute.attrib_id = field->usage[0].hid;
+
+       sensor_field->attribute.index = index;
+       sensor_field->attribute.report_id = report->id;
+       sensor_field->attribute.units = field->unit;
+       sensor_field->attribute.unit_expo = field->unit_exponent;
+       sensor_field->attribute.size = (field->report_size / 8);
+       sensor_field->attribute.logical_minimum = field->logical_minimum;
+       sensor_field->attribute.logical_maximum = field->logical_maximum;
+
+       if (report_type == HID_FEATURE_REPORT)
+               snprintf(sensor_field->group_name,
+                        sizeof(sensor_field->group_name), "feature-%x-%x",
+                        sensor_field->attribute.index,
+                        sensor_field->attribute.attrib_id);
+       else if (report_type == HID_INPUT_REPORT) {
+               snprintf(sensor_field->group_name,
+                        sizeof(sensor_field->group_name),
+                        "input-%x-%x", sensor_field->attribute.index,
+                        sensor_field->attribute.attrib_id);
+               sensor_inst->input_field_count++;
+               sensor_inst->input_report_size += (field->report_size *
+                                                  field->report_count) / 8;
+       }
+
+       memset(&sensor_field->hid_custom_attribute_group, 0,
+              sizeof(struct attribute_group));
+       sensor_inst->sensor_field_count++;
+
+       return 0;
+}
+
+static int hid_sensor_custom_add_fields(struct hid_sensor_custom *sensor_inst,
+                                       struct hid_report_enum *report_enum,
+                                       int report_type)
+{
+       int i;
+       int ret;
+       struct hid_report *report;
+       struct hid_field *field;
+       struct hid_sensor_hub_device *hsdev = sensor_inst->hsdev;
+
+       list_for_each_entry(report, &report_enum->report_list, list) {
+               for (i = 0; i < report->maxfield; ++i) {
+                       field = report->field[i];
+                       if (field->maxusage &&
+                           ((field->usage[0].collection_index >=
+                             hsdev->start_collection_index) &&
+                             (field->usage[0].collection_index <
+                              hsdev->end_collection_index))) {
+
+                               ret = hid_sensor_custom_add_field(sensor_inst,
+                                                                 i,
+                                                                 report_type,
+                                                                 report,
+                                                                 field);
+                               if (ret)
+                                       return ret;
+
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int hid_sensor_custom_add_attributes(struct hid_sensor_custom
+                                                               *sensor_inst)
+{
+       struct hid_sensor_hub_device *hsdev = sensor_inst->hsdev;
+       struct hid_device *hdev = hsdev->hdev;
+       int ret = -1;
+       int i, j;
+
+       for (j = 0; j < HID_REPORT_TYPES; ++j) {
+               if (j == HID_OUTPUT_REPORT)
+                       continue;
+
+               ret = hid_sensor_custom_add_fields(sensor_inst,
+                                                  &hdev->report_enum[j], j);
+               if (ret)
+                       return ret;
+
+       }
+
+       /* Create sysfs attributes */
+       for (i = 0; i < sensor_inst->sensor_field_count; ++i) {
+               j = 0;
+               while (j < HID_CUSTOM_TOTAL_ATTRS &&
+                      hid_custom_attrs[j].name) {
+                       struct device_attribute *device_attr;
+
+                       device_attr = &sensor_inst->fields[i].sd_attrs[j];
+
+                       snprintf((char *)&sensor_inst->fields[i].attr_name[j],
+                                HID_CUSTOM_NAME_LENGTH, "%s-%s",
+                                sensor_inst->fields[i].group_name,
+                                hid_custom_attrs[j].name);
+                       sysfs_attr_init(&device_attr->attr);
+                       device_attr->attr.name =
+                               (char *)&sensor_inst->fields[i].attr_name[j];
+                       device_attr->attr.mode = hid_custom_attrs[j].mode;
+                       device_attr->show = show_value;
+                       if (hid_custom_attrs[j].mode & S_IWUSR)
+                               device_attr->store = store_value;
+                       sensor_inst->fields[i].attrs[j] = &device_attr->attr;
+                       ++j;
+               }
+               sensor_inst->fields[i].attrs[j] = NULL;
+               sensor_inst->fields[i].hid_custom_attribute_group.attrs =
+                                               sensor_inst->fields[i].attrs;
+               sensor_inst->fields[i].hid_custom_attribute_group.name =
+                                       sensor_inst->fields[i].group_name;
+               ret = sysfs_create_group(&sensor_inst->pdev->dev.kobj,
+                                        &sensor_inst->fields[i].
+                                        hid_custom_attribute_group);
+               if (ret)
+                       break;
+
+               /* For power or report field store indexes */
+               if (sensor_inst->fields[i].attribute.attrib_id ==
+                                       HID_USAGE_SENSOR_PROY_POWER_STATE)
+                       sensor_inst->power_state = &sensor_inst->fields[i];
+               else if (sensor_inst->fields[i].attribute.attrib_id ==
+                                       HID_USAGE_SENSOR_PROP_REPORT_STATE)
+                       sensor_inst->report_state = &sensor_inst->fields[i];
+       }
+
+       return ret;
+}
+
+static void hid_sensor_custom_remove_attributes(struct hid_sensor_custom *
+                                                               sensor_inst)
+{
+       int i;
+
+       for (i = 0; i < sensor_inst->sensor_field_count; ++i)
+               sysfs_remove_group(&sensor_inst->pdev->dev.kobj,
+                                  &sensor_inst->fields[i].
+                                  hid_custom_attribute_group);
+
+       kfree(sensor_inst->fields);
+}
+
+static ssize_t hid_sensor_custom_read(struct file *file, char __user *buf,
+                                     size_t count, loff_t *f_ps)
+{
+       struct hid_sensor_custom *sensor_inst;
+       unsigned int copied;
+       int ret;
+
+       sensor_inst = container_of(file->private_data,
+                                  struct hid_sensor_custom, custom_dev);
+
+       if (count < sizeof(struct hid_sensor_sample))
+               return -EINVAL;
+
+       do {
+               if (kfifo_is_empty(&sensor_inst->data_fifo)) {
+                       if (file->f_flags & O_NONBLOCK)
+                               return -EAGAIN;
+
+                       ret = wait_event_interruptible(sensor_inst->wait,
+                               !kfifo_is_empty(&sensor_inst->data_fifo));
+                       if (ret)
+                               return ret;
+               }
+               ret = kfifo_to_user(&sensor_inst->data_fifo, buf, count,
+                                   &copied);
+               if (ret)
+                       return ret;
+
+       } while (copied == 0);
+
+       return copied;
+}
+
+static int hid_sensor_custom_release(struct inode *inode, struct file *file)
+{
+       struct hid_sensor_custom *sensor_inst;
+
+       sensor_inst = container_of(file->private_data,
+                                  struct hid_sensor_custom, custom_dev);
+
+       clear_bit(0, &sensor_inst->misc_opened);
+
+       return 0;
+}
+
+static int hid_sensor_custom_open(struct inode *inode, struct file *file)
+{
+       struct hid_sensor_custom *sensor_inst;
+
+       sensor_inst = container_of(file->private_data,
+                                  struct hid_sensor_custom, custom_dev);
+       /* We essentially have single reader and writer */
+       if (test_and_set_bit(0, &sensor_inst->misc_opened))
+               return -EBUSY;
+
+       return nonseekable_open(inode, file);
+}
+
+static unsigned int hid_sensor_custom_poll(struct file *file,
+                                          struct poll_table_struct *wait)
+{
+       struct hid_sensor_custom *sensor_inst;
+       unsigned int mask = 0;
+
+       sensor_inst = container_of(file->private_data,
+                                  struct hid_sensor_custom, custom_dev);
+
+       poll_wait(file, &sensor_inst->wait, wait);
+
+       if (!kfifo_is_empty(&sensor_inst->data_fifo))
+               mask = POLLIN | POLLRDNORM;
+
+       return mask;
+}
+
+static const struct file_operations hid_sensor_custom_fops = {
+       .open =  hid_sensor_custom_open,
+       .read =  hid_sensor_custom_read,
+       .release = hid_sensor_custom_release,
+       .poll = hid_sensor_custom_poll,
+       .llseek = noop_llseek,
+};
+
+static int hid_sensor_custom_dev_if_add(struct hid_sensor_custom *sensor_inst)
+{
+       int ret;
+
+       ret = kfifo_alloc(&sensor_inst->data_fifo, HID_CUSTOM_FIFO_SIZE,
+                         GFP_KERNEL);
+       if (ret)
+               return ret;
+
+       init_waitqueue_head(&sensor_inst->wait);
+
+       sensor_inst->custom_dev.minor = MISC_DYNAMIC_MINOR;
+       sensor_inst->custom_dev.name = dev_name(&sensor_inst->pdev->dev);
+       sensor_inst->custom_dev.fops = &hid_sensor_custom_fops,
+       ret = misc_register(&sensor_inst->custom_dev);
+       if (ret) {
+               kfifo_free(&sensor_inst->data_fifo);
+               return ret;
+       }
+       return 0;
+}
+
+static void hid_sensor_custom_dev_if_remove(struct hid_sensor_custom
+                                                               *sensor_inst)
+{
+       wake_up(&sensor_inst->wait);
+       misc_deregister(&sensor_inst->custom_dev);
+       kfifo_free(&sensor_inst->data_fifo);
+
+}
+
+static int hid_sensor_custom_probe(struct platform_device *pdev)
+{
+       struct hid_sensor_custom *sensor_inst;
+       struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+       int ret;
+
+       sensor_inst = devm_kzalloc(&pdev->dev, sizeof(*sensor_inst),
+                                  GFP_KERNEL);
+       if (!sensor_inst)
+               return -ENOMEM;
+
+       sensor_inst->callbacks.capture_sample = hid_sensor_capture_sample;
+       sensor_inst->callbacks.send_event = hid_sensor_send_event;
+       sensor_inst->callbacks.pdev = pdev;
+       sensor_inst->hsdev = hsdev;
+       sensor_inst->pdev = pdev;
+       mutex_init(&sensor_inst->mutex);
+       platform_set_drvdata(pdev, sensor_inst);
+       ret = sensor_hub_register_callback(hsdev, hsdev->usage,
+                                          &sensor_inst->callbacks);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "callback reg failed\n");
+               return ret;
+       }
+
+       ret = sysfs_create_group(&sensor_inst->pdev->dev.kobj,
+                                &enable_sensor_attr_group);
+       if (ret)
+               goto err_remove_callback;
+
+       ret = hid_sensor_custom_add_attributes(sensor_inst);
+       if (ret)
+               goto err_remove_group;
+
+       ret = hid_sensor_custom_dev_if_add(sensor_inst);
+       if (ret)
+               goto err_remove_attributes;
+
+       return 0;
+
+err_remove_attributes:
+       hid_sensor_custom_remove_attributes(sensor_inst);
+err_remove_group:
+       sysfs_remove_group(&sensor_inst->pdev->dev.kobj,
+                          &enable_sensor_attr_group);
+err_remove_callback:
+       sensor_hub_remove_callback(hsdev, hsdev->usage);
+
+       return ret;
+}
+
+static int hid_sensor_custom_remove(struct platform_device *pdev)
+{
+       struct hid_sensor_custom *sensor_inst = platform_get_drvdata(pdev);
+       struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+
+       hid_sensor_custom_dev_if_remove(sensor_inst);
+       hid_sensor_custom_remove_attributes(sensor_inst);
+       sysfs_remove_group(&sensor_inst->pdev->dev.kobj,
+                          &enable_sensor_attr_group);
+       sensor_hub_remove_callback(hsdev, hsdev->usage);
+
+       return 0;
+}
+
+static struct platform_device_id hid_sensor_custom_ids[] = {
+       {
+               .name = "HID-SENSOR-2000e1",
+       },
+       {
+               .name = "HID-SENSOR-2000e2",
+       },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, hid_sensor_custom_ids);
+
+static struct platform_driver hid_sensor_custom_platform_driver = {
+       .id_table = hid_sensor_custom_ids,
+       .driver = {
+               .name   = KBUILD_MODNAME,
+       },
+       .probe          = hid_sensor_custom_probe,
+       .remove         = hid_sensor_custom_remove,
+};
+module_platform_driver(hid_sensor_custom_platform_driver);
+
+MODULE_DESCRIPTION("HID Sensor Custom and Generic sensor Driver");
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+MODULE_LICENSE("GPL");
index e54ce1097e2cc57f5049cf852016087a32534c47..c3f6f1e311ea0d98da6981669e292e085552a927 100644 (file)
 
 #define HID_SENSOR_HUB_ENUM_QUIRK      0x01
 
-/**
- * struct sensor_hub_pending - Synchronous read pending information
- * @status:            Pending status true/false.
- * @ready:             Completion synchronization data.
- * @usage_id:          Usage id for physical device, E.g. Gyro usage id.
- * @attr_usage_id:     Usage Id of a field, E.g. X-AXIS for a gyro.
- * @raw_size:          Response size for a read request.
- * @raw_data:          Place holder for received response.
- */
-struct sensor_hub_pending {
-       bool status;
-       struct completion ready;
-       u32 usage_id;
-       u32 attr_usage_id;
-       int raw_size;
-       u8  *raw_data;
-};
-
 /**
  * struct sensor_hub_data - Hold a instance data for a HID hub device
  * @hsdev:             Stored hid instance for current hub device.
  * @mutex:             Mutex to serialize synchronous request.
  * @lock:              Spin lock to protect pending request structure.
- * @pending:           Holds information of pending sync read request.
  * @dyn_callback_list: Holds callback function
  * @dyn_callback_lock: spin lock to protect callback list
  * @hid_sensor_hub_client_devs:        Stores all MFD cells for a hub instance.
@@ -61,7 +42,6 @@ struct sensor_hub_pending {
 struct sensor_hub_data {
        struct mutex mutex;
        spinlock_t lock;
-       struct sensor_hub_pending pending;
        struct list_head dyn_callback_list;
        spinlock_t dyn_callback_lock;
        struct mfd_cell *hid_sensor_hub_client_devs;
@@ -106,7 +86,8 @@ static int sensor_hub_get_physical_device_count(struct hid_device *hdev)
 
        for (i = 0; i < hdev->maxcollection; ++i) {
                struct hid_collection *collection = &hdev->collection[i];
-               if (collection->type == HID_COLLECTION_PHYSICAL)
+               if (collection->type == HID_COLLECTION_PHYSICAL ||
+                   collection->type == HID_COLLECTION_APPLICATION)
                        ++count;
        }
 
@@ -139,7 +120,8 @@ static struct hid_sensor_hub_callbacks *sensor_hub_get_callback(
 
        spin_lock_irqsave(&pdata->dyn_callback_lock, flags);
        list_for_each_entry(callback, &pdata->dyn_callback_list, list)
-               if (callback->usage_id == usage_id &&
+               if ((callback->usage_id == usage_id ||
+                    callback->usage_id == HID_USAGE_SENSOR_COLLECTION) &&
                        (collection_index >=
                                callback->hsdev->start_collection_index) &&
                        (collection_index <
@@ -179,7 +161,18 @@ int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
        callback->usage_callback = usage_callback;
        callback->usage_id = usage_id;
        callback->priv = NULL;
-       list_add_tail(&callback->list, &pdata->dyn_callback_list);
+       /*
+        * If there is a handler registered for the collection type, then
+        * it will handle all reports for sensors in this collection. If
+        * there is also an individual sensor handler registration, then
+        * we want to make sure that the reports are directed to collection
+        * handler, as this may be a fusion sensor. So add collection handlers
+        * to the beginning of the list, so that they are matched first.
+        */
+       if (usage_id == HID_USAGE_SENSOR_COLLECTION)
+               list_add(&callback->list, &pdata->dyn_callback_list);
+       else
+               list_add_tail(&callback->list, &pdata->dyn_callback_list);
        spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags);
 
        return 0;
@@ -208,10 +201,14 @@ int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev,
 EXPORT_SYMBOL_GPL(sensor_hub_remove_callback);
 
 int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
-                               u32 field_index, s32 value)
+                          u32 field_index, int buffer_size, void *buffer)
 {
        struct hid_report *report;
        struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
+       __s32 *buf32 = buffer;
+       int i = 0;
+       int remaining_bytes;
+       __s32 value;
        int ret = 0;
 
        mutex_lock(&data->mutex);
@@ -220,7 +217,21 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
                ret = -EINVAL;
                goto done_proc;
        }
-       hid_set_field(report->field[field_index], 0, value);
+
+       remaining_bytes = do_div(buffer_size, sizeof(__s32));
+       if (buffer_size) {
+               for (i = 0; i < buffer_size; ++i) {
+                       hid_set_field(report->field[field_index], i,
+                                     (__force __s32)cpu_to_le32(*buf32));
+                       ++buf32;
+               }
+       }
+       if (remaining_bytes) {
+               value = 0;
+               memcpy(&value, (u8 *)buf32, remaining_bytes);
+               hid_set_field(report->field[field_index], i,
+                             (__force __s32)cpu_to_le32(value));
+       }
        hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT);
        hid_hw_wait(hsdev->hdev);
 
@@ -232,10 +243,11 @@ done_proc:
 EXPORT_SYMBOL_GPL(sensor_hub_set_feature);
 
 int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
-                               u32 field_index, s32 *value)
+                          u32 field_index, int buffer_size, void *buffer)
 {
        struct hid_report *report;
        struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
+       int report_size;
        int ret = 0;
 
        mutex_lock(&data->mutex);
@@ -247,7 +259,17 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
        }
        hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
        hid_hw_wait(hsdev->hdev);
-       *value = report->field[field_index]->value[0];
+
+       /* calculate number of bytes required to read this field */
+       report_size = DIV_ROUND_UP(report->field[field_index]->report_size,
+                                  8) *
+                                  report->field[field_index]->report_count;
+       if (!report_size) {
+               ret = -EINVAL;
+               goto done_proc;
+       }
+       ret = min(report_size, buffer_size);
+       memcpy(buffer, report->field[field_index]->value, ret);
 
 done_proc:
        mutex_unlock(&data->mutex);
@@ -259,47 +281,54 @@ EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
 
 int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
                                        u32 usage_id,
-                                       u32 attr_usage_id, u32 report_id)
+                                       u32 attr_usage_id, u32 report_id,
+                                       enum sensor_hub_read_flags flag)
 {
        struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
        unsigned long flags;
        struct hid_report *report;
        int ret_val = 0;
 
-       mutex_lock(&data->mutex);
-       memset(&data->pending, 0, sizeof(data->pending));
-       init_completion(&data->pending.ready);
-       data->pending.usage_id = usage_id;
-       data->pending.attr_usage_id = attr_usage_id;
-       data->pending.raw_size = 0;
-
-       spin_lock_irqsave(&data->lock, flags);
-       data->pending.status = true;
-       spin_unlock_irqrestore(&data->lock, flags);
-       report = sensor_hub_report(report_id, hsdev->hdev, HID_INPUT_REPORT);
+       report = sensor_hub_report(report_id, hsdev->hdev,
+                                  HID_INPUT_REPORT);
        if (!report)
-               goto err_free;
-
-       hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
-       wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5);
-       switch (data->pending.raw_size) {
-       case 1:
-               ret_val = *(u8 *)data->pending.raw_data;
-               break;
-       case 2:
-               ret_val = *(u16 *)data->pending.raw_data;
-               break;
-       case 4:
-               ret_val = *(u32 *)data->pending.raw_data;
-               break;
-       default:
-               ret_val = 0;
+               return -EINVAL;
+
+       mutex_lock(&hsdev->mutex);
+       if (flag == SENSOR_HUB_SYNC) {
+               memset(&hsdev->pending, 0, sizeof(hsdev->pending));
+               init_completion(&hsdev->pending.ready);
+               hsdev->pending.usage_id = usage_id;
+               hsdev->pending.attr_usage_id = attr_usage_id;
+               hsdev->pending.raw_size = 0;
+
+               spin_lock_irqsave(&data->lock, flags);
+               hsdev->pending.status = true;
+               spin_unlock_irqrestore(&data->lock, flags);
        }
-       kfree(data->pending.raw_data);
-
-err_free:
-       data->pending.status = false;
+       mutex_lock(&data->mutex);
+       hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
        mutex_unlock(&data->mutex);
+       if (flag == SENSOR_HUB_SYNC) {
+               wait_for_completion_interruptible_timeout(
+                                               &hsdev->pending.ready, HZ*5);
+               switch (hsdev->pending.raw_size) {
+               case 1:
+                       ret_val = *(u8 *)hsdev->pending.raw_data;
+                       break;
+               case 2:
+                       ret_val = *(u16 *)hsdev->pending.raw_data;
+                       break;
+               case 4:
+                       ret_val = *(u32 *)hsdev->pending.raw_data;
+                       break;
+               default:
+                       ret_val = 0;
+               }
+               kfree(hsdev->pending.raw_data);
+               hsdev->pending.status = false;
+       }
+       mutex_unlock(&hsdev->mutex);
 
        return ret_val;
 }
@@ -455,16 +484,6 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
                                        report->field[i]->report_count)/8);
                sz = (report->field[i]->report_size *
                                        report->field[i]->report_count)/8;
-               if (pdata->pending.status && pdata->pending.attr_usage_id ==
-                               report->field[i]->usage->hid) {
-                       hid_dbg(hdev, "data was pending ...\n");
-                       pdata->pending.raw_data = kmemdup(ptr, sz, GFP_ATOMIC);
-                       if (pdata->pending.raw_data)
-                               pdata->pending.raw_size = sz;
-                       else
-                               pdata->pending.raw_size = 0;
-                       complete(&pdata->pending.ready);
-               }
                collection = &hdev->collection[
                                report->field[i]->usage->collection_index];
                hid_dbg(hdev, "collection->usage %x\n",
@@ -474,8 +493,23 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
                                report->field[i]->physical,
                                report->field[i]->usage[0].collection_index,
                                &hsdev, &priv);
-
-               if (callback && callback->capture_sample) {
+               if (!callback) {
+                       ptr += sz;
+                       continue;
+               }
+               if (hsdev->pending.status && (hsdev->pending.attr_usage_id ==
+                                             report->field[i]->usage->hid ||
+                                             hsdev->pending.attr_usage_id ==
+                                             report->field[i]->logical)) {
+                       hid_dbg(hdev, "data was pending ...\n");
+                       hsdev->pending.raw_data = kmemdup(ptr, sz, GFP_ATOMIC);
+                       if (hsdev->pending.raw_data)
+                               hsdev->pending.raw_size = sz;
+                       else
+                               hsdev->pending.raw_size = 0;
+                       complete(&hsdev->pending.ready);
+               }
+               if (callback->capture_sample) {
                        if (report->field[i]->logical)
                                callback->capture_sample(hsdev,
                                        report->field[i]->logical, sz, ptr,
@@ -572,6 +606,7 @@ static int sensor_hub_probe(struct hid_device *hdev,
        int dev_cnt;
        struct hid_sensor_hub_device *hsdev;
        struct hid_sensor_hub_device *last_hsdev = NULL;
+       struct hid_sensor_hub_device *collection_hsdev = NULL;
 
        sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL);
        if (!sd) {
@@ -618,7 +653,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
        for (i = 0; i < hdev->maxcollection; ++i) {
                struct hid_collection *collection = &hdev->collection[i];
 
-               if (collection->type == HID_COLLECTION_PHYSICAL) {
+               if (collection->type == HID_COLLECTION_PHYSICAL ||
+                   collection->type == HID_COLLECTION_APPLICATION) {
 
                        hsdev = devm_kzalloc(&hdev->dev, sizeof(*hsdev),
                                             GFP_KERNEL);
@@ -630,6 +666,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
                        hsdev->hdev = hdev;
                        hsdev->vendor_id = hdev->vendor;
                        hsdev->product_id = hdev->product;
+                       hsdev->usage = collection->usage;
+                       mutex_init(&hsdev->mutex);
                        hsdev->start_collection_index = i;
                        if (last_hsdev)
                                last_hsdev->end_collection_index = i;
@@ -653,10 +691,17 @@ static int sensor_hub_probe(struct hid_device *hdev,
                        hid_dbg(hdev, "Adding %s:%d\n", name,
                                        hsdev->start_collection_index);
                        sd->hid_sensor_client_cnt++;
+                       if (collection_hsdev)
+                               collection_hsdev->end_collection_index = i;
+                       if (collection->type == HID_COLLECTION_APPLICATION &&
+                           collection->usage == HID_USAGE_SENSOR_COLLECTION)
+                               collection_hsdev = hsdev;
                }
        }
        if (last_hsdev)
                last_hsdev->end_collection_index = i;
+       if (collection_hsdev)
+               collection_hsdev->end_collection_index = i;
 
        ret = mfd_add_hotplug_devices(&hdev->dev,
                        sd->hid_sensor_hub_client_devs,
@@ -676,13 +721,18 @@ static void sensor_hub_remove(struct hid_device *hdev)
 {
        struct sensor_hub_data *data = hid_get_drvdata(hdev);
        unsigned long flags;
+       int i;
 
        hid_dbg(hdev, " hardware removed\n");
        hid_hw_close(hdev);
        hid_hw_stop(hdev);
        spin_lock_irqsave(&data->lock, flags);
-       if (data->pending.status)
-               complete(&data->pending.ready);
+       for (i = 0; i < data->hid_sensor_client_cnt; ++i) {
+               struct hid_sensor_hub_device *hsdev =
+                       data->hid_sensor_hub_client_devs[i].platform_data;
+               if (hsdev->pending.status)
+                       complete(&hsdev->pending.ready);
+       }
        spin_unlock_irqrestore(&data->lock, flags);
        mfd_remove_devices(&hdev->dev);
        hid_set_drvdata(hdev, NULL);
index 1896c019e302934aa13c6f9ac434c51637f450ce..6ca96cebb44ce1e01290ae7d718ad97c44d9998b 100644 (file)
@@ -802,7 +802,8 @@ union sixaxis_output_report_01 {
 #define DS4_REPORT_0x05_SIZE 32
 #define DS4_REPORT_0x11_SIZE 78
 #define DS4_REPORT_0x81_SIZE 7
-#define SIXAXIS_REPORT_0xF2_SIZE 18
+#define SIXAXIS_REPORT_0xF2_SIZE 17
+#define SIXAXIS_REPORT_0xF5_SIZE 8
 
 static DEFINE_SPINLOCK(sony_dev_list_lock);
 static LIST_HEAD(sony_device_list);
@@ -815,7 +816,8 @@ struct sony_sc {
        struct led_classdev *leds[MAX_LEDS];
        unsigned long quirks;
        struct work_struct state_worker;
-       struct power_supply battery;
+       struct power_supply *battery;
+       struct power_supply_desc battery_desc;
        int device_id;
        __u8 *output_report_dmabuf;
 
@@ -1130,18 +1132,38 @@ static void sony_input_configured(struct hid_device *hdev,
  */
 static int sixaxis_set_operational_usb(struct hid_device *hdev)
 {
+       const int buf_size =
+               max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE);
+       __u8 *buf;
        int ret;
-       char *buf = kmalloc(18, GFP_KERNEL);
 
+       buf = kmalloc(buf_size, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
 
-       ret = hid_hw_raw_request(hdev, 0xf2, buf, 17, HID_FEATURE_REPORT,
-                                HID_REQ_GET_REPORT);
+       ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE,
+                                HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+       if (ret < 0) {
+               hid_err(hdev, "can't set operational mode: step 1\n");
+               goto out;
+       }
 
+       /*
+        * Some compatible controllers like the Speedlink Strike FX and
+        * Gasia need another query plus an USB interrupt to get operational.
+        */
+       ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE,
+                                HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+       if (ret < 0) {
+               hid_err(hdev, "can't set operational mode: step 2\n");
+               goto out;
+       }
+
+       ret = hid_hw_output_report(hdev, buf, 1);
        if (ret < 0)
-               hid_err(hdev, "can't set operational mode\n");
+               hid_err(hdev, "can't set operational mode: step 3\n");
 
+out:
        kfree(buf);
 
        return ret;
@@ -1660,7 +1682,7 @@ static int sony_battery_get_property(struct power_supply *psy,
                                     enum power_supply_property psp,
                                     union power_supply_propval *val)
 {
-       struct sony_sc *sc = container_of(psy, struct sony_sc, battery);
+       struct sony_sc *sc = power_supply_get_drvdata(psy);
        unsigned long flags;
        int ret = 0;
        u8 battery_charging, battery_capacity, cable_state;
@@ -1699,6 +1721,7 @@ static int sony_battery_get_property(struct power_supply *psy,
 
 static int sony_battery_probe(struct sony_sc *sc)
 {
+       struct power_supply_config psy_cfg = { .drv_data = sc, };
        struct hid_device *hdev = sc->hdev;
        int ret;
 
@@ -1708,39 +1731,42 @@ static int sony_battery_probe(struct sony_sc *sc)
         */
        sc->battery_capacity = 100;
 
-       sc->battery.properties = sony_battery_props;
-       sc->battery.num_properties = ARRAY_SIZE(sony_battery_props);
-       sc->battery.get_property = sony_battery_get_property;
-       sc->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-       sc->battery.use_for_apm = 0;
-       sc->battery.name = kasprintf(GFP_KERNEL, "sony_controller_battery_%pMR",
-                                    sc->mac_address);
-       if (!sc->battery.name)
+       sc->battery_desc.properties = sony_battery_props;
+       sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props);
+       sc->battery_desc.get_property = sony_battery_get_property;
+       sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+       sc->battery_desc.use_for_apm = 0;
+       sc->battery_desc.name = kasprintf(GFP_KERNEL,
+                                         "sony_controller_battery_%pMR",
+                                         sc->mac_address);
+       if (!sc->battery_desc.name)
                return -ENOMEM;
 
-       ret = power_supply_register(&hdev->dev, &sc->battery);
-       if (ret) {
+       sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc,
+                                           &psy_cfg);
+       if (IS_ERR(sc->battery)) {
+               ret = PTR_ERR(sc->battery);
                hid_err(hdev, "Unable to register battery device\n");
                goto err_free;
        }
 
-       power_supply_powers(&sc->battery, &hdev->dev);
+       power_supply_powers(sc->battery, &hdev->dev);
        return 0;
 
 err_free:
-       kfree(sc->battery.name);
-       sc->battery.name = NULL;
+       kfree(sc->battery_desc.name);
+       sc->battery_desc.name = NULL;
        return ret;
 }
 
 static void sony_battery_remove(struct sony_sc *sc)
 {
-       if (!sc->battery.name)
+       if (!sc->battery_desc.name)
                return;
 
-       power_supply_unregister(&sc->battery);
-       kfree(sc->battery.name);
-       sc->battery.name = NULL;
+       power_supply_unregister(sc->battery);
+       kfree(sc->battery_desc.name);
+       sc->battery_desc.name = NULL;
 }
 
 /*
index 29f328f411fb5454e03d46406c880fc9a5de0516..3edd4ac364942b1f181a5577a2d8db757efea540 100644 (file)
@@ -12,7 +12,6 @@
  */
 
 #include <linux/device.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 #include <linux/module.h>
 
index fb8b516ff0ed5f7693912ece34c4ff372d3918fa..94167310e15a4c95001d339d4da3b7319f9005eb 100644 (file)
@@ -1,7 +1,8 @@
 /*
  *  HID driver for UC-Logic devices not fully compliant with HID standard
  *
- *  Copyright (c) 2010 Nikolai Kondrashov
+ *  Copyright (c) 2010-2014 Nikolai Kondrashov
+ *  Copyright (c) 2013 Martin Rusko
  */
 
 /*
@@ -15,6 +16,8 @@
 #include <linux/hid.h>
 #include <linux/module.h>
 #include <linux/usb.h>
+#include <asm/unaligned.h>
+#include "usbhid/usbhid.h"
 
 #include "hid-ids.h"
 
@@ -546,11 +549,93 @@ static __u8 twha60_rdesc_fixed1[] = {
        0xC0        /*  End Collection              */
 };
 
+/* Report descriptor template placeholder head */
+#define UCLOGIC_PH_HEAD        0xFE, 0xED, 0x1D
+
+/* Report descriptor template placeholder IDs */
+enum uclogic_ph_id {
+       UCLOGIC_PH_ID_X_LM,
+       UCLOGIC_PH_ID_X_PM,
+       UCLOGIC_PH_ID_Y_LM,
+       UCLOGIC_PH_ID_Y_PM,
+       UCLOGIC_PH_ID_PRESSURE_LM,
+       UCLOGIC_PH_ID_NUM
+};
+
+/* Report descriptor template placeholder */
+#define UCLOGIC_PH(_ID) UCLOGIC_PH_HEAD, UCLOGIC_PH_ID_##_ID
+#define UCLOGIC_PEN_REPORT_ID  0x07
+
+/* Fixed report descriptor template */
+static const __u8 uclogic_tablet_rdesc_template[] = {
+       0x05, 0x0D,             /*  Usage Page (Digitizer),                 */
+       0x09, 0x02,             /*  Usage (Pen),                            */
+       0xA1, 0x01,             /*  Collection (Application),               */
+       0x85, 0x07,             /*      Report ID (7),                      */
+       0x09, 0x20,             /*      Usage (Stylus),                     */
+       0xA0,                   /*      Collection (Physical),              */
+       0x14,                   /*          Logical Minimum (0),            */
+       0x25, 0x01,             /*          Logical Maximum (1),            */
+       0x75, 0x01,             /*          Report Size (1),                */
+       0x09, 0x42,             /*          Usage (Tip Switch),             */
+       0x09, 0x44,             /*          Usage (Barrel Switch),          */
+       0x09, 0x46,             /*          Usage (Tablet Pick),            */
+       0x95, 0x03,             /*          Report Count (3),               */
+       0x81, 0x02,             /*          Input (Variable),               */
+       0x95, 0x03,             /*          Report Count (3),               */
+       0x81, 0x03,             /*          Input (Constant, Variable),     */
+       0x09, 0x32,             /*          Usage (In Range),               */
+       0x95, 0x01,             /*          Report Count (1),               */
+       0x81, 0x02,             /*          Input (Variable),               */
+       0x95, 0x01,             /*          Report Count (1),               */
+       0x81, 0x03,             /*          Input (Constant, Variable),     */
+       0x75, 0x10,             /*          Report Size (16),               */
+       0x95, 0x01,             /*          Report Count (1),               */
+       0xA4,                   /*          Push,                           */
+       0x05, 0x01,             /*          Usage Page (Desktop),           */
+       0x65, 0x13,             /*          Unit (Inch),                    */
+       0x55, 0xFD,             /*          Unit Exponent (-3),             */
+       0x34,                   /*          Physical Minimum (0),           */
+       0x09, 0x30,             /*          Usage (X),                      */
+       0x27, UCLOGIC_PH(X_LM), /*          Logical Maximum (PLACEHOLDER),  */
+       0x47, UCLOGIC_PH(X_PM), /*          Physical Maximum (PLACEHOLDER), */
+       0x81, 0x02,             /*          Input (Variable),               */
+       0x09, 0x31,             /*          Usage (Y),                      */
+       0x27, UCLOGIC_PH(Y_LM), /*          Logical Maximum (PLACEHOLDER),  */
+       0x47, UCLOGIC_PH(Y_PM), /*          Physical Maximum (PLACEHOLDER), */
+       0x81, 0x02,             /*          Input (Variable),               */
+       0xB4,                   /*          Pop,                            */
+       0x09, 0x30,             /*          Usage (Tip Pressure),           */
+       0x27,
+       UCLOGIC_PH(PRESSURE_LM),/*          Logical Maximum (PLACEHOLDER),  */
+       0x81, 0x02,             /*          Input (Variable),               */
+       0xC0,                   /*      End Collection,                     */
+       0xC0                    /*  End Collection                          */
+};
+
+/* Parameter indices */
+enum uclogic_prm {
+       UCLOGIC_PRM_X_LM        = 1,
+       UCLOGIC_PRM_Y_LM        = 2,
+       UCLOGIC_PRM_PRESSURE_LM = 4,
+       UCLOGIC_PRM_RESOLUTION  = 5,
+       UCLOGIC_PRM_NUM
+};
+
+/* Driver data */
+struct uclogic_drvdata {
+       __u8 *rdesc;
+       unsigned int rsize;
+       bool invert_pen_inrange;
+       bool ignore_pen_usage;
+};
+
 static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                                        unsigned int *rsize)
 {
        struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
        __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
+       struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
 
        switch (hdev->product) {
        case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209:
@@ -621,11 +706,241 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                        break;
                }
                break;
+       default:
+               if (drvdata->rdesc != NULL) {
+                       rdesc = drvdata->rdesc;
+                       *rsize = drvdata->rsize;
+               }
        }
 
        return rdesc;
 }
 
+static int uclogic_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
+
+       /* discard the unused pen interface */
+       if ((drvdata->ignore_pen_usage) &&
+           (field->application == HID_DG_PEN))
+               return -1;
+
+       /* let hid-core decide what to do */
+       return 0;
+}
+
+static void uclogic_input_configured(struct hid_device *hdev,
+               struct hid_input *hi)
+{
+       char *name;
+       const char *suffix = NULL;
+       struct hid_field *field;
+       size_t len;
+
+       /* no report associated (HID_QUIRK_MULTI_INPUT not set) */
+       if (!hi->report)
+               return;
+
+       field = hi->report->field[0];
+
+       switch (field->application) {
+       case HID_GD_KEYBOARD:
+               suffix = "Keyboard";
+               break;
+       case HID_GD_MOUSE:
+               suffix = "Mouse";
+               break;
+       case HID_GD_KEYPAD:
+               suffix = "Pad";
+               break;
+       case HID_DG_PEN:
+               suffix = "Pen";
+               break;
+       case HID_CP_CONSUMER_CONTROL:
+               suffix = "Consumer Control";
+               break;
+       case HID_GD_SYSTEM_CONTROL:
+               suffix = "System Control";
+               break;
+       }
+
+       if (suffix) {
+               len = strlen(hdev->name) + 2 + strlen(suffix);
+               name = devm_kzalloc(&hi->input->dev, len, GFP_KERNEL);
+               if (name) {
+                       snprintf(name, len, "%s %s", hdev->name, suffix);
+                       hi->input->name = name;
+               }
+       }
+}
+
+/**
+ * Enable fully-functional tablet mode and determine device parameters.
+ *
+ * @hdev:      HID device
+ */
+static int uclogic_tablet_enable(struct hid_device *hdev)
+{
+       int rc;
+       struct usb_device *usb_dev = hid_to_usb_dev(hdev);
+       struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
+       __le16 *buf = NULL;
+       size_t len;
+       s32 params[UCLOGIC_PH_ID_NUM];
+       s32 resolution;
+       __u8 *p;
+       s32 v;
+
+       /*
+        * Read string descriptor containing tablet parameters. The specific
+        * string descriptor and data were discovered by sniffing the Windows
+        * driver traffic.
+        * NOTE: This enables fully-functional tablet mode.
+        */
+       len = UCLOGIC_PRM_NUM * sizeof(*buf);
+       buf = kmalloc(len, GFP_KERNEL);
+       if (buf == NULL) {
+               hid_err(hdev, "failed to allocate parameter buffer\n");
+               rc = -ENOMEM;
+               goto cleanup;
+       }
+       rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+                               USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+                               (USB_DT_STRING << 8) + 0x64,
+                               0x0409, buf, len,
+                               USB_CTRL_GET_TIMEOUT);
+       if (rc == -EPIPE) {
+               hid_err(hdev, "device parameters not found\n");
+               rc = -ENODEV;
+               goto cleanup;
+       } else if (rc < 0) {
+               hid_err(hdev, "failed to get device parameters: %d\n", rc);
+               rc = -ENODEV;
+               goto cleanup;
+       } else if (rc != len) {
+               hid_err(hdev, "invalid device parameters\n");
+               rc = -ENODEV;
+               goto cleanup;
+       }
+
+       /* Extract device parameters */
+       params[UCLOGIC_PH_ID_X_LM] = le16_to_cpu(buf[UCLOGIC_PRM_X_LM]);
+       params[UCLOGIC_PH_ID_Y_LM] = le16_to_cpu(buf[UCLOGIC_PRM_Y_LM]);
+       params[UCLOGIC_PH_ID_PRESSURE_LM] =
+               le16_to_cpu(buf[UCLOGIC_PRM_PRESSURE_LM]);
+       resolution = le16_to_cpu(buf[UCLOGIC_PRM_RESOLUTION]);
+       if (resolution == 0) {
+               params[UCLOGIC_PH_ID_X_PM] = 0;
+               params[UCLOGIC_PH_ID_Y_PM] = 0;
+       } else {
+               params[UCLOGIC_PH_ID_X_PM] = params[UCLOGIC_PH_ID_X_LM] *
+                                               1000 / resolution;
+               params[UCLOGIC_PH_ID_Y_PM] = params[UCLOGIC_PH_ID_Y_LM] *
+                                               1000 / resolution;
+       }
+
+       /* Allocate fixed report descriptor */
+       drvdata->rdesc = devm_kzalloc(&hdev->dev,
+                               sizeof(uclogic_tablet_rdesc_template),
+                               GFP_KERNEL);
+       if (drvdata->rdesc == NULL) {
+               hid_err(hdev, "failed to allocate fixed rdesc\n");
+               rc = -ENOMEM;
+               goto cleanup;
+       }
+       drvdata->rsize = sizeof(uclogic_tablet_rdesc_template);
+
+       /* Format fixed report descriptor */
+       memcpy(drvdata->rdesc, uclogic_tablet_rdesc_template,
+               drvdata->rsize);
+       for (p = drvdata->rdesc;
+            p <= drvdata->rdesc + drvdata->rsize - 4;) {
+               if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
+                   p[3] < sizeof(params)) {
+                       v = params[p[3]];
+                       put_unaligned(cpu_to_le32(v), (s32 *)p);
+                       p += 4;
+               } else {
+                       p++;
+               }
+       }
+
+       rc = 0;
+
+cleanup:
+       kfree(buf);
+       return rc;
+}
+
+static int uclogic_probe(struct hid_device *hdev,
+               const struct hid_device_id *id)
+{
+       int rc;
+       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+       struct uclogic_drvdata *drvdata;
+
+       /*
+        * libinput requires the pad interface to be on a different node
+        * than the pen, so use QUIRK_MULTI_INPUT for all tablets.
+        */
+       hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+       hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
+
+       /* Allocate and assign driver data */
+       drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
+       if (drvdata == NULL)
+               return -ENOMEM;
+
+       hid_set_drvdata(hdev, drvdata);
+
+       switch (id->product) {
+       case USB_DEVICE_ID_HUION_TABLET:
+               /* If this is the pen interface */
+               if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
+                       rc = uclogic_tablet_enable(hdev);
+                       if (rc) {
+                               hid_err(hdev, "tablet enabling failed\n");
+                               return rc;
+                       }
+                       drvdata->invert_pen_inrange = true;
+               } else {
+                       drvdata->ignore_pen_usage = true;
+               }
+               break;
+       }
+
+       rc = hid_parse(hdev);
+       if (rc) {
+               hid_err(hdev, "parse failed\n");
+               return rc;
+       }
+
+       rc = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+       if (rc) {
+               hid_err(hdev, "hw start failed\n");
+               return rc;
+       }
+
+       return 0;
+}
+
+static int uclogic_raw_event(struct hid_device *hdev, struct hid_report *report,
+                       u8 *data, int size)
+{
+       struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
+
+       if ((drvdata->invert_pen_inrange) &&
+           (report->type == HID_INPUT_REPORT) &&
+           (report->id == UCLOGIC_PEN_REPORT_ID) &&
+           (size >= 2))
+               /* Invert the in-range bit */
+               data[1] ^= 0x40;
+
+       return 0;
+}
+
 static const struct hid_device_id uclogic_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
                                USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
@@ -641,6 +956,8 @@ static const struct hid_device_id uclogic_devices[] = {
                                USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
                                USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, uclogic_devices);
@@ -648,8 +965,14 @@ MODULE_DEVICE_TABLE(hid, uclogic_devices);
 static struct hid_driver uclogic_driver = {
        .name = "uclogic",
        .id_table = uclogic_devices,
+       .probe = uclogic_probe,
        .report_fixup = uclogic_report_fixup,
+       .raw_event = uclogic_raw_event,
+       .input_mapping = uclogic_input_mapping,
+       .input_configured = uclogic_input_configured,
 };
 module_hid_driver(uclogic_driver);
 
+MODULE_AUTHOR("Martin Rusko");
+MODULE_AUTHOR("Nikolai Kondrashov");
 MODULE_LICENSE("GPL");
index 6b61f01e01e7fad839f8dd960050596a26a9abfe..05e23c417d500567546b99af2c09d582f330d67e 100644 (file)
@@ -203,8 +203,7 @@ static int wiimod_battery_get_property(struct power_supply *psy,
                                       enum power_supply_property psp,
                                       union power_supply_propval *val)
 {
-       struct wiimote_data *wdata = container_of(psy, struct wiimote_data,
-                                                 battery);
+       struct wiimote_data *wdata = power_supply_get_drvdata(psy);
        int ret = 0, state;
        unsigned long flags;
 
@@ -238,42 +237,46 @@ static int wiimod_battery_get_property(struct power_supply *psy,
 static int wiimod_battery_probe(const struct wiimod_ops *ops,
                                struct wiimote_data *wdata)
 {
+       struct power_supply_config psy_cfg = { .drv_data = wdata, };
        int ret;
 
-       wdata->battery.properties = wiimod_battery_props;
-       wdata->battery.num_properties = ARRAY_SIZE(wiimod_battery_props);
-       wdata->battery.get_property = wiimod_battery_get_property;
-       wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-       wdata->battery.use_for_apm = 0;
-       wdata->battery.name = kasprintf(GFP_KERNEL, "wiimote_battery_%s",
-                                       wdata->hdev->uniq);
-       if (!wdata->battery.name)
+       wdata->battery_desc.properties = wiimod_battery_props;
+       wdata->battery_desc.num_properties = ARRAY_SIZE(wiimod_battery_props);
+       wdata->battery_desc.get_property = wiimod_battery_get_property;
+       wdata->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+       wdata->battery_desc.use_for_apm = 0;
+       wdata->battery_desc.name = kasprintf(GFP_KERNEL, "wiimote_battery_%s",
+                                            wdata->hdev->uniq);
+       if (!wdata->battery_desc.name)
                return -ENOMEM;
 
-       ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);
-       if (ret) {
+       wdata->battery = power_supply_register(&wdata->hdev->dev,
+                                              &wdata->battery_desc,
+                                              &psy_cfg);
+       if (IS_ERR(wdata->battery)) {
                hid_err(wdata->hdev, "cannot register battery device\n");
+               ret = PTR_ERR(wdata->battery);
                goto err_free;
        }
 
-       power_supply_powers(&wdata->battery, &wdata->hdev->dev);
+       power_supply_powers(wdata->battery, &wdata->hdev->dev);
        return 0;
 
 err_free:
-       kfree(wdata->battery.name);
-       wdata->battery.name = NULL;
+       kfree(wdata->battery_desc.name);
+       wdata->battery_desc.name = NULL;
        return ret;
 }
 
 static void wiimod_battery_remove(const struct wiimod_ops *ops,
                                  struct wiimote_data *wdata)
 {
-       if (!wdata->battery.name)
+       if (!wdata->battery_desc.name)
                return;
 
-       power_supply_unregister(&wdata->battery);
-       kfree(wdata->battery.name);
-       wdata->battery.name = NULL;
+       power_supply_unregister(wdata->battery);
+       kfree(wdata->battery_desc.name);
+       wdata->battery_desc.name = NULL;
 }
 
 static const struct wiimod_ops wiimod_battery = {
index 10934aa129fbb7743d90dadbd540e9b164b14c38..875694d43e4d9249ccc84e7e447d619fb0ba22d0 100644 (file)
@@ -147,7 +147,8 @@ struct wiimote_data {
        struct led_classdev *leds[4];
        struct input_dev *accel;
        struct input_dev *ir;
-       struct power_supply battery;
+       struct power_supply *battery;
+       struct power_supply_desc battery_desc;
        struct input_dev *mp;
        struct timer_list timer;
        struct wiimote_debug *debug;
index 36053f33d6d93e97009b0d6ba3f4aa5416be8fea..ab4dd952b6ba654d91d75523951f4f02cbfa1138 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/mutex.h>
 #include <linux/acpi.h>
 #include <linux/of.h>
+#include <linux/gpio/consumer.h>
 
 #include <linux/i2c/i2c-hid.h>
 
@@ -144,6 +145,8 @@ struct i2c_hid {
        unsigned long           flags;          /* device flags */
 
        wait_queue_head_t       wait;           /* For waiting the interrupt */
+       struct gpio_desc        *desc;
+       int                     irq;
 
        struct i2c_hid_platform_data pdata;
 };
@@ -785,16 +788,16 @@ static int i2c_hid_init_irq(struct i2c_client *client)
        struct i2c_hid *ihid = i2c_get_clientdata(client);
        int ret;
 
-       dev_dbg(&client->dev, "Requesting IRQ: %d\n", client->irq);
+       dev_dbg(&client->dev, "Requesting IRQ: %d\n", ihid->irq);
 
-       ret = request_threaded_irq(client->irq, NULL, i2c_hid_irq,
+       ret = request_threaded_irq(ihid->irq, NULL, i2c_hid_irq,
                        IRQF_TRIGGER_LOW | IRQF_ONESHOT,
                        client->name, ihid);
        if (ret < 0) {
                dev_warn(&client->dev,
                        "Could not register for %s interrupt, irq = %d,"
                        " ret = %d\n",
-                       client->name, client->irq, ret);
+                       client->name, ihid->irq, ret);
 
                return ret;
        }
@@ -841,6 +844,14 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
 }
 
 #ifdef CONFIG_ACPI
+
+/* Default GPIO mapping */
+static const struct acpi_gpio_params i2c_hid_irq_gpio = { 0, 0, true };
+static const struct acpi_gpio_mapping i2c_hid_acpi_gpios[] = {
+       { "gpios", &i2c_hid_irq_gpio, 1 },
+       { },
+};
+
 static int i2c_hid_acpi_pdata(struct i2c_client *client,
                struct i2c_hid_platform_data *pdata)
 {
@@ -866,7 +877,7 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
        pdata->hid_descriptor_address = obj->integer.value;
        ACPI_FREE(obj);
 
-       return 0;
+       return acpi_dev_add_driver_gpios(adev, i2c_hid_acpi_gpios);
 }
 
 static const struct acpi_device_id i2c_hid_acpi_match[] = {
@@ -930,12 +941,6 @@ static int i2c_hid_probe(struct i2c_client *client,
 
        dbg_hid("HID probe called for i2c 0x%02x\n", client->addr);
 
-       if (!client->irq) {
-               dev_err(&client->dev,
-                       "HID over i2c has not been provided an Int IRQ\n");
-               return -EINVAL;
-       }
-
        ihid = kzalloc(sizeof(struct i2c_hid), GFP_KERNEL);
        if (!ihid)
                return -ENOMEM;
@@ -955,6 +960,23 @@ static int i2c_hid_probe(struct i2c_client *client,
                ihid->pdata = *platform_data;
        }
 
+       if (client->irq > 0) {
+               ihid->irq = client->irq;
+       } else if (ACPI_COMPANION(&client->dev)) {
+               ihid->desc = gpiod_get(&client->dev, NULL, GPIOD_IN);
+               if (IS_ERR(ihid->desc)) {
+                       dev_err(&client->dev, "Failed to get GPIO interrupt\n");
+                       return PTR_ERR(ihid->desc);
+               }
+
+               ihid->irq = gpiod_to_irq(ihid->desc);
+               if (ihid->irq < 0) {
+                       gpiod_put(ihid->desc);
+                       dev_err(&client->dev, "Failed to convert GPIO to IRQ\n");
+                       return ihid->irq;
+               }
+       }
+
        i2c_set_clientdata(client, ihid);
 
        ihid->client = client;
@@ -1017,13 +1039,16 @@ err_mem_free:
        hid_destroy_device(hid);
 
 err_irq:
-       free_irq(client->irq, ihid);
+       free_irq(ihid->irq, ihid);
 
 err_pm:
        pm_runtime_put_noidle(&client->dev);
        pm_runtime_disable(&client->dev);
 
 err:
+       if (ihid->desc)
+               gpiod_put(ihid->desc);
+
        i2c_hid_free_buffers(ihid);
        kfree(ihid);
        return ret;
@@ -1042,13 +1067,18 @@ static int i2c_hid_remove(struct i2c_client *client)
        hid = ihid->hid;
        hid_destroy_device(hid);
 
-       free_irq(client->irq, ihid);
+       free_irq(ihid->irq, ihid);
 
        if (ihid->bufsize)
                i2c_hid_free_buffers(ihid);
 
+       if (ihid->desc)
+               gpiod_put(ihid->desc);
+
        kfree(ihid);
 
+       acpi_dev_remove_driver_gpios(ACPI_COMPANION(&client->dev));
+
        return 0;
 }
 
@@ -1060,9 +1090,9 @@ static int i2c_hid_suspend(struct device *dev)
        struct hid_device *hid = ihid->hid;
        int ret = 0;
 
-       disable_irq(client->irq);
+       disable_irq(ihid->irq);
        if (device_may_wakeup(&client->dev))
-               enable_irq_wake(client->irq);
+               enable_irq_wake(ihid->irq);
 
        if (hid->driver && hid->driver->suspend)
                ret = hid->driver->suspend(hid, PMSG_SUSPEND);
@@ -1080,13 +1110,13 @@ static int i2c_hid_resume(struct device *dev)
        struct i2c_hid *ihid = i2c_get_clientdata(client);
        struct hid_device *hid = ihid->hid;
 
-       enable_irq(client->irq);
+       enable_irq(ihid->irq);
        ret = i2c_hid_hwreset(client);
        if (ret)
                return ret;
 
        if (device_may_wakeup(&client->dev))
-               disable_irq_wake(client->irq);
+               disable_irq_wake(ihid->irq);
 
        if (hid->driver && hid->driver->reset_resume) {
                ret = hid->driver->reset_resume(hid);
@@ -1101,17 +1131,19 @@ static int i2c_hid_resume(struct device *dev)
 static int i2c_hid_runtime_suspend(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
 
        i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
-       disable_irq(client->irq);
+       disable_irq(ihid->irq);
        return 0;
 }
 
 static int i2c_hid_runtime_resume(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
+       struct i2c_hid *ihid = i2c_get_clientdata(client);
 
-       enable_irq(client->irq);
+       enable_irq(ihid->irq);
        i2c_hid_set_power(client, I2C_HID_PWR_ON);
        return 0;
 }
index 0b531c6a76a58871b9ea549367400c1a345cb6b8..08174d341f4a10cbb54b1a2cc2e894a3ee17c028 100644 (file)
@@ -568,6 +568,12 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
        int type_id;
        int error;
 
+       pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
+       if (old) {
+               pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] =
+                       pidff->pid_id[effect->id];
+       }
+
        switch (effect->type) {
        case FF_CONSTANT:
                if (!old) {
index a821277534611708973ccf080ad78f4136ef0df5..a775143e6265e337597e2dd15e6c9d682c04354f 100644 (file)
@@ -78,7 +78,13 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C01A, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP, HID_QUIRK_NO_INIT_REPORTS },
@@ -92,6 +98,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET },
@@ -107,12 +114,8 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
-       { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
-       { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60, HID_QUIRK_MULTI_INPUT },
-       { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT },
-       { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET, HID_QUIRK_MULTI_INPUT },
@@ -128,6 +131,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS },
index 7db432809e9ebd12c96a74c065b7a82f536c94fe..024f4d89d5792ae9a04739b5b895647177e6ecd4 100644 (file)
@@ -119,8 +119,10 @@ struct wacom {
                u8 img_lum;   /* OLED matrix display brightness */
        } led;
        bool led_initialized;
-       struct power_supply battery;
-       struct power_supply ac;
+       struct power_supply *battery;
+       struct power_supply *ac;
+       struct power_supply_desc battery_desc;
+       struct power_supply_desc ac_desc;
 };
 
 static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
@@ -129,13 +131,6 @@ static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
        schedule_work(&wacom->work);
 }
 
-static inline void wacom_notify_battery(struct wacom_wac *wacom_wac)
-{
-       struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
-
-       power_supply_changed(&wacom->battery);
-}
-
 extern const struct hid_device_id wacom_ids[];
 
 void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
@@ -149,4 +144,5 @@ void wacom_wac_usage_mapping(struct hid_device *hdev,
 int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
                struct hid_usage *usage, __s32 value);
 void wacom_wac_report(struct hid_device *hdev, struct hid_report *report);
+void wacom_battery_work(struct work_struct *work);
 #endif
index f0568a7e6de9b88d04e8ccad812c21f032ab1762..e8607d0961384684ad94d94f2f4777adfdfbf42f 100644 (file)
@@ -406,6 +406,9 @@ static int wacom_query_tablet_data(struct hid_device *hdev,
                else if (features->type == WACOM_27QHDT) {
                        return wacom_set_device_mode(hdev, 131, 3, 2);
                }
+               else if (features->type == BAMBOO_PAD) {
+                       return wacom_set_device_mode(hdev, 2, 2, 2);
+               }
        } else if (features->device_type == BTN_TOOL_PEN) {
                if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
                        return wacom_set_device_mode(hdev, 2, 2, 2);
@@ -524,6 +527,11 @@ static int wacom_add_shared_data(struct hid_device *hdev)
 
        wacom_wac->shared = &data->shared;
 
+       if (wacom_wac->features.device_type == BTN_TOOL_FINGER)
+               wacom_wac->shared->touch = hdev;
+       else if (wacom_wac->features.device_type == BTN_TOOL_PEN)
+               wacom_wac->shared->pen = hdev;
+
 out:
        mutex_unlock(&wacom_udev_list_lock);
        return retval;
@@ -541,14 +549,22 @@ static void wacom_release_shared_data(struct kref *kref)
        kfree(data);
 }
 
-static void wacom_remove_shared_data(struct wacom_wac *wacom)
+static void wacom_remove_shared_data(struct wacom *wacom)
 {
        struct wacom_hdev_data *data;
+       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+
+       if (wacom_wac->shared) {
+               data = container_of(wacom_wac->shared, struct wacom_hdev_data,
+                                   shared);
+
+               if (wacom_wac->shared->touch == wacom->hdev)
+                       wacom_wac->shared->touch = NULL;
+               else if (wacom_wac->shared->pen == wacom->hdev)
+                       wacom_wac->shared->pen = NULL;
 
-       if (wacom->shared) {
-               data = container_of(wacom->shared, struct wacom_hdev_data, shared);
                kref_put(&data->kref, wacom_release_shared_data);
-               wacom->shared = NULL;
+               wacom_wac->shared = NULL;
        }
 }
 
@@ -929,6 +945,7 @@ static void wacom_destroy_leds(struct wacom *wacom)
 }
 
 static enum power_supply_property wacom_battery_props[] = {
+       POWER_SUPPLY_PROP_PRESENT,
        POWER_SUPPLY_PROP_STATUS,
        POWER_SUPPLY_PROP_SCOPE,
        POWER_SUPPLY_PROP_CAPACITY
@@ -944,10 +961,13 @@ static int wacom_battery_get_property(struct power_supply *psy,
                                      enum power_supply_property psp,
                                      union power_supply_propval *val)
 {
-       struct wacom *wacom = container_of(psy, struct wacom, battery);
+       struct wacom *wacom = power_supply_get_drvdata(psy);
        int ret = 0;
 
        switch (psp) {
+               case POWER_SUPPLY_PROP_PRESENT:
+                       val->intval = wacom->wacom_wac.bat_connected;
+                       break;
                case POWER_SUPPLY_PROP_SCOPE:
                        val->intval = POWER_SUPPLY_SCOPE_DEVICE;
                        break;
@@ -961,6 +981,8 @@ static int wacom_battery_get_property(struct power_supply *psy,
                        else if (wacom->wacom_wac.battery_capacity == 100 &&
                                    wacom->wacom_wac.ps_connected)
                                val->intval = POWER_SUPPLY_STATUS_FULL;
+                       else if (wacom->wacom_wac.ps_connected)
+                               val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
                        else
                                val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
                        break;
@@ -976,7 +998,7 @@ static int wacom_ac_get_property(struct power_supply *psy,
                                enum power_supply_property psp,
                                union power_supply_propval *val)
 {
-       struct wacom *wacom = container_of(psy, struct wacom, ac);
+       struct wacom *wacom = power_supply_get_drvdata(psy);
        int ret = 0;
 
        switch (psp) {
@@ -998,42 +1020,46 @@ static int wacom_ac_get_property(struct power_supply *psy,
 static int wacom_initialize_battery(struct wacom *wacom)
 {
        static atomic_t battery_no = ATOMIC_INIT(0);
-       int error;
+       struct power_supply_config psy_cfg = { .drv_data = wacom, };
        unsigned long n;
 
        if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) {
+               struct power_supply_desc *bat_desc = &wacom->battery_desc;
+               struct power_supply_desc *ac_desc = &wacom->ac_desc;
                n = atomic_inc_return(&battery_no) - 1;
 
-               wacom->battery.properties = wacom_battery_props;
-               wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
-               wacom->battery.get_property = wacom_battery_get_property;
+               bat_desc->properties = wacom_battery_props;
+               bat_desc->num_properties = ARRAY_SIZE(wacom_battery_props);
+               bat_desc->get_property = wacom_battery_get_property;
                sprintf(wacom->wacom_wac.bat_name, "wacom_battery_%ld", n);
-               wacom->battery.name = wacom->wacom_wac.bat_name;
-               wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-               wacom->battery.use_for_apm = 0;
+               bat_desc->name = wacom->wacom_wac.bat_name;
+               bat_desc->type = POWER_SUPPLY_TYPE_BATTERY;
+               bat_desc->use_for_apm = 0;
 
-               wacom->ac.properties = wacom_ac_props;
-               wacom->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
-               wacom->ac.get_property = wacom_ac_get_property;
+               ac_desc->properties = wacom_ac_props;
+               ac_desc->num_properties = ARRAY_SIZE(wacom_ac_props);
+               ac_desc->get_property = wacom_ac_get_property;
                sprintf(wacom->wacom_wac.ac_name, "wacom_ac_%ld", n);
-               wacom->ac.name = wacom->wacom_wac.ac_name;
-               wacom->ac.type = POWER_SUPPLY_TYPE_MAINS;
-               wacom->ac.use_for_apm = 0;
-
-               error = power_supply_register(&wacom->hdev->dev,
-                                             &wacom->battery);
-               if (error)
-                       return error;
-
-               power_supply_powers(&wacom->battery, &wacom->hdev->dev);
-
-               error = power_supply_register(&wacom->hdev->dev, &wacom->ac);
-               if (error) {
-                       power_supply_unregister(&wacom->battery);
-                       return error;
+               ac_desc->name = wacom->wacom_wac.ac_name;
+               ac_desc->type = POWER_SUPPLY_TYPE_MAINS;
+               ac_desc->use_for_apm = 0;
+
+               wacom->battery = power_supply_register(&wacom->hdev->dev,
+                                             &wacom->battery_desc, &psy_cfg);
+               if (IS_ERR(wacom->battery))
+                       return PTR_ERR(wacom->battery);
+
+               power_supply_powers(wacom->battery, &wacom->hdev->dev);
+
+               wacom->ac = power_supply_register(&wacom->hdev->dev,
+                                                 &wacom->ac_desc,
+                                                 &psy_cfg);
+               if (IS_ERR(wacom->ac)) {
+                       power_supply_unregister(wacom->battery);
+                       return PTR_ERR(wacom->ac);
                }
 
-               power_supply_powers(&wacom->ac, &wacom->hdev->dev);
+               power_supply_powers(wacom->ac, &wacom->hdev->dev);
        }
 
        return 0;
@@ -1041,12 +1067,11 @@ static int wacom_initialize_battery(struct wacom *wacom)
 
 static void wacom_destroy_battery(struct wacom *wacom)
 {
-       if ((wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) &&
-            wacom->battery.dev) {
-               power_supply_unregister(&wacom->battery);
-               wacom->battery.dev = NULL;
-               power_supply_unregister(&wacom->ac);
-               wacom->ac.dev = NULL;
+       if (wacom->battery) {
+               power_supply_unregister(wacom->battery);
+               wacom->battery = NULL;
+               power_supply_unregister(wacom->ac);
+               wacom->ac = NULL;
        }
 }
 
@@ -1313,6 +1338,20 @@ fail:
        return;
 }
 
+void wacom_battery_work(struct work_struct *work)
+{
+       struct wacom *wacom = container_of(work, struct wacom, work);
+
+       if ((wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) &&
+            !wacom->battery) {
+               wacom_initialize_battery(wacom);
+       }
+       else if (!(wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) &&
+                wacom->battery) {
+               wacom_destroy_battery(wacom);
+       }
+}
+
 /*
  * Not all devices report physical dimensions from HID.
  * Compute the default from hardcoded logical dimension
@@ -1373,6 +1412,9 @@ static int wacom_probe(struct hid_device *hdev,
 
        hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
 
+       /* hid-core sets this quirk for the boot interface */
+       hdev->quirks &= ~HID_QUIRK_NOGET;
+
        wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
        if (!wacom)
                return -ENOMEM;
@@ -1412,6 +1454,21 @@ static int wacom_probe(struct hid_device *hdev,
                        goto fail_allocate_inputs;
        }
 
+       /*
+        * Bamboo Pad has a generic hid handling for the Pen, and we switch it
+        * into debug mode for the touch part.
+        * We ignore the other interfaces.
+        */
+       if (features->type == BAMBOO_PAD) {
+               if (features->pktlen == WACOM_PKGLEN_PENABLED) {
+                       features->type = HID_GENERIC;
+               } else if ((features->pktlen != WACOM_PKGLEN_BPAD_TOUCH) &&
+                          (features->pktlen != WACOM_PKGLEN_BPAD_TOUCH_USB)) {
+                       error = -ENODEV;
+                       goto fail_shared_data;
+               }
+       }
+
        /* set the default size in case we do not get them from hid */
        wacom_set_default_phy(features);
 
@@ -1446,6 +1503,12 @@ static int wacom_probe(struct hid_device *hdev,
                features->y_max = 4096;
        }
 
+       /*
+        * Same thing for Bamboo PAD
+        */
+       if (features->type == BAMBOO_PAD)
+               features->device_type = BTN_TOOL_FINGER;
+
        if (hdev->bus == BUS_BLUETOOTH)
                features->quirks |= WACOM_QUIRK_BATTERY;
 
@@ -1462,19 +1525,17 @@ static int wacom_probe(struct hid_device *hdev,
        snprintf(wacom_wac->pad_name, sizeof(wacom_wac->pad_name),
                "%s Pad", features->name);
 
-       if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
-               /* Append the device type to the name */
-               if (features->device_type != BTN_TOOL_FINGER)
-                       strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX);
-               else if (features->touch_max)
-                       strlcat(wacom_wac->name, " Finger", WACOM_NAME_MAX);
-               else
-                       strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX);
+       /* Append the device type to the name */
+       if (features->device_type != BTN_TOOL_FINGER)
+               strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX);
+       else if (features->touch_max)
+               strlcat(wacom_wac->name, " Finger", WACOM_NAME_MAX);
+       else
+               strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX);
 
-               error = wacom_add_shared_data(hdev);
-               if (error)
-                       goto fail_shared_data;
-       }
+       error = wacom_add_shared_data(hdev);
+       if (error)
+               goto fail_shared_data;
 
        if (!(features->quirks & WACOM_QUIRK_MONITOR) &&
             (features->quirks & WACOM_QUIRK_BATTERY)) {
@@ -1527,7 +1588,7 @@ fail_register_inputs:
        wacom_clean_inputs(wacom);
        wacom_destroy_battery(wacom);
 fail_battery:
-       wacom_remove_shared_data(wacom_wac);
+       wacom_remove_shared_data(wacom);
 fail_shared_data:
        wacom_clean_inputs(wacom);
 fail_allocate_inputs:
@@ -1550,7 +1611,7 @@ static void wacom_remove(struct hid_device *hdev)
        if (hdev->bus == BUS_BLUETOOTH)
                device_remove_file(&hdev->dev, &dev_attr_speed);
        wacom_destroy_battery(wacom);
-       wacom_remove_shared_data(&wacom->wacom_wac);
+       wacom_remove_shared_data(wacom);
 
        hid_set_drvdata(hdev, NULL);
        kfree(wacom);
index bbe32d66e5000157b4d3670c23350ff3fa1a0104..fa54d329065945bade5b9048df9cb5a98c0bf7f2 100644 (file)
@@ -45,6 +45,27 @@ static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 };
  */
 static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 };
 
+static void wacom_notify_battery(struct wacom_wac *wacom_wac,
+       int bat_capacity, bool bat_charging, bool bat_connected,
+       bool ps_connected)
+{
+       struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+       bool changed = wacom_wac->battery_capacity != bat_capacity  ||
+                      wacom_wac->bat_charging     != bat_charging  ||
+                      wacom_wac->bat_connected    != bat_connected ||
+                      wacom_wac->ps_connected     != ps_connected;
+
+       if (changed) {
+               wacom_wac->battery_capacity = bat_capacity;
+               wacom_wac->bat_charging = bat_charging;
+               wacom_wac->bat_connected = bat_connected;
+               wacom_wac->ps_connected = ps_connected;
+
+               if (wacom->battery)
+                       power_supply_changed(wacom->battery);
+       }
+}
+
 static int wacom_penpartner_irq(struct wacom_wac *wacom)
 {
        unsigned char *data = wacom->data;
@@ -419,17 +440,26 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
                rw = (data[7] >> 2 & 0x07);
                battery_capacity = batcap_gr[rw];
                ps_connected = rw == 7;
-               if ((wacom->battery_capacity != battery_capacity) ||
-                   (wacom->ps_connected != ps_connected)) {
-                       wacom->battery_capacity = battery_capacity;
-                       wacom->ps_connected = ps_connected;
-                       wacom_notify_battery(wacom);
-               }
+               wacom_notify_battery(wacom, battery_capacity, ps_connected,
+                                    1, ps_connected);
        }
 exit:
        return retval;
 }
 
+static void wacom_intuos_schedule_prox_event(struct wacom_wac *wacom_wac)
+{
+       struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+       struct hid_report *r;
+       struct hid_report_enum *re;
+
+       re = &(wacom->hdev->report_enum[HID_FEATURE_REPORT]);
+       r = re->report_id_hash[WACOM_REPORT_INTUOSREAD];
+       if (r) {
+               hid_hw_request(wacom->hdev, r, HID_REQ_GET_REPORT);
+       }
+}
+
 static int wacom_intuos_inout(struct wacom_wac *wacom)
 {
        struct wacom_features *features = &wacom->features;
@@ -551,12 +581,9 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
           (features->type == CINTIQ && !(data[1] & 0x40)))
                return 1;
 
-       if (wacom->shared) {
-               wacom->shared->stylus_in_proximity = true;
-
-               if (wacom->shared->touch_down)
-                       return 1;
-       }
+       wacom->shared->stylus_in_proximity = true;
+       if (wacom->shared->touch_down)
+               return 1;
 
        /* in Range while exiting */
        if (((data[1] & 0xfe) == 0x20) && wacom->reporting_data) {
@@ -568,8 +595,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
 
        /* Exit report */
        if ((data[1] & 0xfe) == 0x80) {
-               if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
-                       wacom->shared->stylus_in_proximity = false;
+               wacom->shared->stylus_in_proximity = false;
                wacom->reporting_data = false;
 
                /* don't report exit if we don't know the ID */
@@ -610,8 +636,11 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
        }
 
        /* don't report other events if we don't know the ID */
-       if (!wacom->id[idx])
+       if (!wacom->id[idx]) {
+               /* but reschedule a read of the current tool */
+               wacom_intuos_schedule_prox_event(wacom);
                return 1;
+       }
 
        return 0;
 }
@@ -1023,15 +1052,9 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
                bat_charging = (power_raw & 0x08) ? 1 : 0;
                ps_connected = (power_raw & 0x10) ? 1 : 0;
                battery_capacity = batcap_i4[power_raw & 0x07];
-               if ((wacom->battery_capacity != battery_capacity) ||
-                   (wacom->bat_charging != bat_charging) ||
-                   (wacom->ps_connected != ps_connected)) {
-                       wacom->battery_capacity = battery_capacity;
-                       wacom->bat_charging = bat_charging;
-                       wacom->ps_connected = ps_connected;
-                       wacom_notify_battery(wacom);
-               }
-
+               wacom_notify_battery(wacom, battery_capacity, bat_charging,
+                                    battery_capacity || bat_charging,
+                                    ps_connected);
                break;
        default:
                dev_dbg(wacom->input->dev.parent,
@@ -1042,6 +1065,28 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
        return 0;
 }
 
+static int wacom_wac_finger_count_touches(struct wacom_wac *wacom)
+{
+       struct input_dev *input = wacom->input;
+       unsigned touch_max = wacom->features.touch_max;
+       int count = 0;
+       int i;
+
+       /* non-HID_GENERIC single touch input doesn't call this routine */
+       if ((touch_max == 1) && (wacom->features.type == HID_GENERIC))
+               return wacom->hid_data.tipswitch &&
+                      !wacom->shared->stylus_in_proximity;
+
+       for (i = 0; i < input->mt->num_slots; i++) {
+               struct input_mt_slot *ps = &input->mt->slots[i];
+               int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
+               if (id >= 0)
+                       count++;
+       }
+
+       return count;
+}
+
 static int wacom_24hdt_irq(struct wacom_wac *wacom)
 {
        struct input_dev *input = wacom->input;
@@ -1052,7 +1097,6 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
        int num_contacts_left = 4; /* maximum contacts per packet */
        int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET;
        int y_offset = 2;
-       static int contact_with_no_pen_down_count = 0;
 
        if (wacom->features.type == WACOM_27QHDT) {
                current_num_contacts = data[63];
@@ -1065,10 +1109,8 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
         * First packet resets the counter since only the first
         * packet in series will have non-zero current_num_contacts.
         */
-       if (current_num_contacts) {
+       if (current_num_contacts)
                wacom->num_contacts_left = current_num_contacts;
-               contact_with_no_pen_down_count = 0;
-       }
 
        contacts_to_send = min(num_contacts_left, wacom->num_contacts_left);
 
@@ -1101,15 +1143,14 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
                                input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
                                input_report_abs(input, ABS_MT_ORIENTATION, w > h);
                        }
-                       contact_with_no_pen_down_count++;
                }
        }
-       input_mt_report_pointer_emulation(input, true);
+       input_mt_sync_frame(input);
 
        wacom->num_contacts_left -= contacts_to_send;
        if (wacom->num_contacts_left <= 0) {
                wacom->num_contacts_left = 0;
-               wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
+               wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom);
        }
        return 1;
 }
@@ -1122,7 +1163,6 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
        int current_num_contacts = data[2];
        int contacts_to_send = 0;
        int x_offset = 0;
-       static int contact_with_no_pen_down_count = 0;
 
        /* MTTPC does not support Height and Width */
        if (wacom->features.type == MTTPC || wacom->features.type == MTTPC_B)
@@ -1132,10 +1172,8 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
         * First packet resets the counter since only the first
         * packet in series will have non-zero current_num_contacts.
         */
-       if (current_num_contacts) {
+       if (current_num_contacts)
                wacom->num_contacts_left = current_num_contacts;
-               contact_with_no_pen_down_count = 0;
-       }
 
        /* There are at most 5 contacts per packet */
        contacts_to_send = min(5, wacom->num_contacts_left);
@@ -1156,15 +1194,14 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
                        int y = get_unaligned_le16(&data[offset + x_offset + 9]);
                        input_report_abs(input, ABS_MT_POSITION_X, x);
                        input_report_abs(input, ABS_MT_POSITION_Y, y);
-                       contact_with_no_pen_down_count++;
                }
        }
-       input_mt_report_pointer_emulation(input, true);
+       input_mt_sync_frame(input);
 
        wacom->num_contacts_left -= contacts_to_send;
        if (wacom->num_contacts_left <= 0) {
                wacom->num_contacts_left = 0;
-               wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
+               wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom);
        }
        return 1;
 }
@@ -1173,7 +1210,6 @@ static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
 {
        struct input_dev *input = wacom->input;
        unsigned char *data = wacom->data;
-       int contact_with_no_pen_down_count = 0;
        int i;
 
        for (i = 0; i < 2; i++) {
@@ -1188,13 +1224,12 @@ static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
 
                        input_report_abs(input, ABS_MT_POSITION_X, x);
                        input_report_abs(input, ABS_MT_POSITION_Y, y);
-                       contact_with_no_pen_down_count++;
                }
        }
-       input_mt_report_pointer_emulation(input, true);
+       input_mt_sync_frame(input);
 
        /* keep touch state for pen event */
-       wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
+       wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom);
 
        return 1;
 }
@@ -1522,29 +1557,6 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
        return 0;
 }
 
-static int wacom_wac_finger_count_touches(struct hid_device *hdev)
-{
-       struct wacom *wacom = hid_get_drvdata(hdev);
-       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
-       struct input_dev *input = wacom_wac->input;
-       unsigned touch_max = wacom_wac->features.touch_max;
-       int count = 0;
-       int i;
-
-       if (touch_max == 1)
-               return wacom_wac->hid_data.tipswitch &&
-                      !wacom_wac->shared->stylus_in_proximity;
-
-       for (i = 0; i < input->mt->num_slots; i++) {
-               struct input_mt_slot *ps = &input->mt->slots[i];
-               int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
-               if (id >= 0)
-                       count++;
-       }
-
-       return count;
-}
-
 static void wacom_wac_finger_report(struct hid_device *hdev,
                struct hid_report *report)
 {
@@ -1559,7 +1571,7 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
        input_sync(input);
 
        /* keep touch state for pen event */
-       wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(hdev);
+       wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac);
 }
 
 void wacom_wac_usage_mapping(struct hid_device *hdev,
@@ -1619,7 +1631,6 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
        struct input_dev *pad_input = wacom->pad_input;
        unsigned char *data = wacom->data;
        int i;
-       int contact_with_no_pen_down_count = 0;
 
        if (data[0] != 0x02)
            return 0;
@@ -1647,22 +1658,21 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
                        }
                        input_report_abs(input, ABS_MT_POSITION_X, x);
                        input_report_abs(input, ABS_MT_POSITION_Y, y);
-                       contact_with_no_pen_down_count++;
                }
        }
 
-       input_mt_report_pointer_emulation(input, true);
+       input_mt_sync_frame(input);
 
        input_report_key(pad_input, BTN_LEFT, (data[1] & 0x08) != 0);
        input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0);
        input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0);
        input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0);
-       wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
+       wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom);
 
        return 1;
 }
 
-static int wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data, int last_touch_count)
+static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
 {
        struct wacom_features *features = &wacom->features;
        struct input_dev *input = wacom->input;
@@ -1670,7 +1680,7 @@ static int wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data, in
        int slot = input_mt_get_slot_by_key(input, data[0]);
 
        if (slot < 0)
-               return 0;
+               return;
 
        touch = touch && !wacom->shared->stylus_in_proximity;
 
@@ -1702,9 +1712,7 @@ static int wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data, in
                input_report_abs(input, ABS_MT_POSITION_Y, y);
                input_report_abs(input, ABS_MT_TOUCH_MAJOR, width);
                input_report_abs(input, ABS_MT_TOUCH_MINOR, height);
-               last_touch_count++;
        }
-       return last_touch_count;
 }
 
 static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
@@ -1729,7 +1737,6 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
        unsigned char *data = wacom->data;
        int count = data[1] & 0x07;
        int i;
-       int contact_with_no_pen_down_count = 0;
 
        if (data[0] != 0x02)
            return 0;
@@ -1740,15 +1747,13 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
                int msg_id = data[offset];
 
                if (msg_id >= 2 && msg_id <= 17)
-                       contact_with_no_pen_down_count = 
-                           wacom_bpt3_touch_msg(wacom, data + offset,
-                                                contact_with_no_pen_down_count);
+                       wacom_bpt3_touch_msg(wacom, data + offset);
                else if (msg_id == 128)
                        wacom_bpt3_button_msg(wacom, data + offset);
 
        }
-       input_mt_report_pointer_emulation(input, true);
-       wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
+       input_mt_sync_frame(input);
+       wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom);
 
        return 1;
 }
@@ -1760,23 +1765,9 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
        unsigned char *data = wacom->data;
        int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
 
-       if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_USB)
+       if (data[0] != WACOM_REPORT_PENABLED)
            return 0;
 
-       if (data[0] == WACOM_REPORT_USB) {
-               if (features->type == INTUOSHT &&
-                   wacom->shared->touch_input &&
-                   features->touch_max) {
-                       input_report_switch(wacom->shared->touch_input,
-                                           SW_MUTE_DEVICE, data[8] & 0x40);
-                       input_sync(wacom->shared->touch_input);
-               }
-               return 0;
-       }
-
-       if (wacom->shared->touch_down)
-               return 0;
-
        prox = (data[1] & 0x20) == 0x20;
 
        /*
@@ -1789,17 +1780,21 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
         *
         * Hardware does report zero in most out-of-prox cases but not all.
         */
-       if (prox) {
-               if (!wacom->shared->stylus_in_proximity) {
-                       if (data[1] & 0x08) {
-                               wacom->tool[0] = BTN_TOOL_RUBBER;
-                               wacom->id[0] = ERASER_DEVICE_ID;
-                       } else {
-                               wacom->tool[0] = BTN_TOOL_PEN;
-                               wacom->id[0] = STYLUS_DEVICE_ID;
-                       }
-                       wacom->shared->stylus_in_proximity = true;
+       if (!wacom->shared->stylus_in_proximity) {
+               if (data[1] & 0x08) {
+                       wacom->tool[0] = BTN_TOOL_RUBBER;
+                       wacom->id[0] = ERASER_DEVICE_ID;
+               } else {
+                       wacom->tool[0] = BTN_TOOL_PEN;
+                       wacom->id[0] = STYLUS_DEVICE_ID;
                }
+       }
+
+       wacom->shared->stylus_in_proximity = prox;
+       if (wacom->shared->touch_down)
+               return 0;
+
+       if (prox) {
                x = le16_to_cpup((__le16 *)&data[2]);
                y = le16_to_cpup((__le16 *)&data[4]);
                p = le16_to_cpup((__le16 *)&data[6]);
@@ -1815,6 +1810,8 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
                pen = data[1] & 0x01;
                btn1 = data[1] & 0x02;
                btn2 = data[1] & 0x04;
+       } else {
+               wacom->id[0] = 0;
        }
 
        input_report_key(input, BTN_TOUCH, pen);
@@ -1826,11 +1823,6 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
        input_report_abs(input, ABS_PRESSURE, p);
        input_report_abs(input, ABS_DISTANCE, d);
 
-       if (!prox) {
-               wacom->id[0] = 0;
-               wacom->shared->stylus_in_proximity = false;
-       }
-
        input_report_key(input, wacom->tool[0], prox); /* PEN or RUBBER */
        input_report_abs(input, ABS_MISC, wacom->id[0]); /* TOOL ID */
 
@@ -1849,6 +1841,91 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
        return 0;
 }
 
+static void wacom_bamboo_pad_pen_event(struct wacom_wac *wacom,
+               unsigned char *data)
+{
+       unsigned char prefix;
+
+       /*
+        * We need to reroute the event from the debug interface to the
+        * pen interface.
+        * We need to add the report ID to the actual pen report, so we
+        * temporary overwrite the first byte to prevent having to kzalloc/kfree
+        * and memcpy the report.
+        */
+       prefix = data[0];
+       data[0] = WACOM_REPORT_BPAD_PEN;
+
+       /*
+        * actually reroute the event.
+        * No need to check if wacom->shared->pen is valid, hid_input_report()
+        * will check for us.
+        */
+       hid_input_report(wacom->shared->pen, HID_INPUT_REPORT, data,
+                        WACOM_PKGLEN_PENABLED, 1);
+
+       data[0] = prefix;
+}
+
+static int wacom_bamboo_pad_touch_event(struct wacom_wac *wacom,
+               unsigned char *data)
+{
+       struct input_dev *input = wacom->input;
+       unsigned char *finger_data, prefix;
+       unsigned id;
+       int x, y;
+       bool valid;
+
+       prefix = data[0];
+
+       for (id = 0; id < wacom->features.touch_max; id++) {
+               valid = !!(prefix & BIT(id)) &&
+                       !wacom->shared->stylus_in_proximity;
+
+               input_mt_slot(input, id);
+               input_mt_report_slot_state(input, MT_TOOL_FINGER, valid);
+
+               if (!valid)
+                       continue;
+
+               finger_data = data + 1 + id * 3;
+               x = finger_data[0] | ((finger_data[1] & 0x0f) << 8);
+               y = (finger_data[2] << 4) | (finger_data[1] >> 4);
+
+               input_report_abs(input, ABS_MT_POSITION_X, x);
+               input_report_abs(input, ABS_MT_POSITION_Y, y);
+       }
+
+       input_mt_sync_frame(input);
+
+       input_report_key(input, BTN_LEFT, prefix & 0x40);
+       input_report_key(input, BTN_RIGHT, prefix & 0x80);
+
+       /* keep touch state for pen event */
+       wacom->shared->touch_down = !!prefix &&
+                                   !wacom->shared->stylus_in_proximity;
+
+       return 1;
+}
+
+static int wacom_bamboo_pad_irq(struct wacom_wac *wacom, size_t len)
+{
+       unsigned char *data = wacom->data;
+
+       if (!((len == WACOM_PKGLEN_BPAD_TOUCH) ||
+             (len == WACOM_PKGLEN_BPAD_TOUCH_USB)) ||
+           (data[0] != WACOM_REPORT_BPAD_TOUCH))
+               return 0;
+
+       if (data[1] & 0x01)
+               wacom_bamboo_pad_pen_event(wacom, &data[1]);
+
+       if (data[1] & 0x02)
+               return wacom_bamboo_pad_touch_event(wacom, &data[9]);
+
+       return 0;
+}
+
 static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
 {
        unsigned char *data = wacom->data;
@@ -1859,7 +1936,7 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
 
        connected = data[1] & 0x01;
        if (connected) {
-               int pid, battery, ps_connected;
+               int pid, battery, charging;
 
                if ((wacom->shared->type == INTUOSHT) &&
                    wacom->shared->touch_input &&
@@ -1871,30 +1948,63 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
 
                pid = get_unaligned_be16(&data[6]);
                battery = (data[5] & 0x3f) * 100 / 31;
-               ps_connected = !!(data[5] & 0x80);
+               charging = !!(data[5] & 0x80);
                if (wacom->pid != pid) {
                        wacom->pid = pid;
                        wacom_schedule_work(wacom);
                }
 
-               if (wacom->shared->type &&
-                   (battery != wacom->battery_capacity ||
-                    ps_connected != wacom->ps_connected)) {
-                       wacom->battery_capacity = battery;
-                       wacom->ps_connected = ps_connected;
-                       wacom->bat_charging = ps_connected &&
-                                               wacom->battery_capacity < 100;
-                       wacom_notify_battery(wacom);
-               }
+               if (wacom->shared->type)
+                       wacom_notify_battery(wacom, battery, charging, 1, 0);
+
        } else if (wacom->pid != 0) {
                /* disconnected while previously connected */
                wacom->pid = 0;
                wacom_schedule_work(wacom);
-               wacom->battery_capacity = 0;
-               wacom->bat_charging = 0;
-               wacom->ps_connected = 0;
+               wacom_notify_battery(wacom, 0, 0, 0, 0);
+       }
+
+       return 0;
+}
+
+static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len)
+{
+       struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+       struct wacom_features *features = &wacom_wac->features;
+       unsigned char *data = wacom_wac->data;
+
+       if (data[0] != WACOM_REPORT_USB)
+               return 0;
+
+       if (features->type == INTUOSHT &&
+           wacom_wac->shared->touch_input &&
+           features->touch_max) {
+               input_report_switch(wacom_wac->shared->touch_input,
+                                   SW_MUTE_DEVICE, data[8] & 0x40);
+               input_sync(wacom_wac->shared->touch_input);
        }
 
+       if (data[9] & 0x02) { /* wireless module is attached */
+               int battery = (data[8] & 0x3f) * 100 / 31;
+               bool charging = !!(data[8] & 0x80);
+
+               wacom_notify_battery(wacom_wac, battery, charging,
+                                    battery || charging, 1);
+
+               if (!wacom->battery &&
+                   !(features->quirks & WACOM_QUIRK_BATTERY)) {
+                       features->quirks |= WACOM_QUIRK_BATTERY;
+                       INIT_WORK(&wacom->work, wacom_battery_work);
+                       wacom_schedule_work(wacom_wac);
+               }
+       }
+       else if ((features->quirks & WACOM_QUIRK_BATTERY) &&
+                wacom->battery) {
+               features->quirks &= ~WACOM_QUIRK_BATTERY;
+               INIT_WORK(&wacom->work, wacom_battery_work);
+               wacom_schedule_work(wacom_wac);
+               wacom_notify_battery(wacom_wac, 0, 0, 0, 0);
+       }
        return 0;
 }
 
@@ -1967,6 +2077,8 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
        case INTUOSPL:
                if (len == WACOM_PKGLEN_BBTOUCH3)
                        sync = wacom_bpt3_touch(wacom_wac);
+               else if (wacom_wac->data[0] == WACOM_REPORT_USB)
+                       sync = wacom_status_irq(wacom_wac, len);
                else
                        sync = wacom_intuos_irq(wacom_wac);
                break;
@@ -1982,7 +2094,14 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
 
        case BAMBOO_PT:
        case INTUOSHT:
-               sync = wacom_bpt_irq(wacom_wac, len);
+               if (wacom_wac->data[0] == WACOM_REPORT_USB)
+                       sync = wacom_status_irq(wacom_wac, len);
+               else
+                       sync = wacom_bpt_irq(wacom_wac, len);
+               break;
+
+       case BAMBOO_PAD:
+               sync = wacom_bamboo_pad_irq(wacom_wac, len);
                break;
 
        case WIRELESS:
@@ -2054,12 +2173,6 @@ void wacom_setup_device_quirks(struct wacom_features *features)
                features->y_max = 1023;
        }
 
-       /* these device have multiple inputs */
-       if (features->type >= WIRELESS ||
-           (features->type >= INTUOS5S && features->type <= INTUOSHT) ||
-           (features->oVid && features->oPid))
-               features->quirks |= WACOM_QUIRK_MULTI_INPUT;
-
        /* quirk for bamboo touch with 2 low res touches */
        if (features->type == BAMBOO_PT &&
            features->pktlen == WACOM_PKGLEN_BBTOUCH) {
@@ -2323,6 +2436,13 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev,
                                              0, 0);
                }
                break;
+       case BAMBOO_PAD:
+               __clear_bit(ABS_MISC, input_dev->absbit);
+               input_mt_init_slots(input_dev, features->touch_max,
+                                   INPUT_MT_POINTER);
+               __set_bit(BTN_LEFT, input_dev->keybit);
+               __set_bit(BTN_RIGHT, input_dev->keybit);
+               break;
        }
        return 0;
 }
@@ -2772,6 +2892,15 @@ static const struct wacom_features wacom_features_0x304 =
        { "Wacom Cintiq 13HD", 59152, 33448, 1023, 63,
          WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
          WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
+static const struct wacom_features wacom_features_0x333 =
+       { "Wacom Cintiq 13HD touch", 59152, 33448, 2047, 63,
+         WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+         WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x335 };
+static const struct wacom_features wacom_features_0x335 =
+       { "Wacom Cintiq 13HD touch", .type = WACOM_24HDT, /* Touch */
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x333, .touch_max = 10,
+         .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0xC7 =
        { "Wacom DTU1931", 37832, 30305, 511, 0,
          PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2976,6 +3105,12 @@ static const struct wacom_features wacom_features_0x30C =
        { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */
          .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30A, .touch_max = 10,
          .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x318 =
+       { "Wacom USB Bamboo PAD", 4095, 4095, /* Touch */
+         .type = BAMBOO_PAD, 35, 48, .touch_max = 4 };
+static const struct wacom_features wacom_features_0x319 =
+       { "Wacom Wireless Bamboo PAD", 4095, 4095, /* Touch */
+         .type = BAMBOO_PAD, 35, 48, .touch_max = 4 };
 static const struct wacom_features wacom_features_0x323 =
        { "Wacom Intuos P M", 21600, 13500, 1023, 31,
          INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
@@ -2992,6 +3127,10 @@ static const struct wacom_features wacom_features_HID_ANY_ID =
        HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
        .driver_data = (kernel_ulong_t)&wacom_features_##prod
 
+#define I2C_DEVICE_WACOM(prod)                                         \
+       HID_DEVICE(BUS_I2C, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
+       .driver_data = (kernel_ulong_t)&wacom_features_##prod
+
 #define USB_DEVICE_LENOVO(prod)                                        \
        HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod),                     \
        .driver_data = (kernel_ulong_t)&wacom_features_##prod
@@ -3124,11 +3263,15 @@ const struct hid_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x314) },
        { USB_DEVICE_WACOM(0x315) },
        { USB_DEVICE_WACOM(0x317) },
+       { USB_DEVICE_WACOM(0x318) },
+       { USB_DEVICE_WACOM(0x319) },
        { USB_DEVICE_WACOM(0x323) },
        { USB_DEVICE_WACOM(0x32A) },
        { USB_DEVICE_WACOM(0x32B) },
        { USB_DEVICE_WACOM(0x32C) },
        { USB_DEVICE_WACOM(0x32F) },
+       { USB_DEVICE_WACOM(0x333) },
+       { USB_DEVICE_WACOM(0x335) },
        { USB_DEVICE_WACOM(0x4001) },
        { USB_DEVICE_WACOM(0x4004) },
        { USB_DEVICE_WACOM(0x5000) },
@@ -3136,6 +3279,7 @@ const struct hid_device_id wacom_ids[] = {
        { USB_DEVICE_LENOVO(0x6004) },
 
        { USB_DEVICE_WACOM(HID_ANY_ID) },
+       { I2C_DEVICE_WACOM(HID_ANY_ID) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, wacom_ids);
index 021ee1c1980a832717f575d1fe50aa0df0071236..4700ac994a3b37c831b0903a34f62a5895f4b892 100644 (file)
@@ -33,6 +33,8 @@
 #define WACOM_PKGLEN_MTTPC     40
 #define WACOM_PKGLEN_DTUS      68
 #define WACOM_PKGLEN_PENABLED   8
+#define WACOM_PKGLEN_BPAD_TOUCH        32
+#define WACOM_PKGLEN_BPAD_TOUCH_USB    64
 
 /* wacom data size per MT contact */
 #define WACOM_BYTES_PER_MT_PACKET      11
 #define WACOM_REPORT_24HDT             1
 #define WACOM_REPORT_WL                        128
 #define WACOM_REPORT_USB               192
+#define WACOM_REPORT_BPAD_PEN          3
+#define WACOM_REPORT_BPAD_TOUCH                16
 
 /* device quirks */
-#define WACOM_QUIRK_MULTI_INPUT                0x0001
-#define WACOM_QUIRK_BBTOUCH_LOWRES     0x0002
-#define WACOM_QUIRK_NO_INPUT           0x0004
-#define WACOM_QUIRK_MONITOR            0x0008
-#define WACOM_QUIRK_BATTERY            0x0010
+#define WACOM_QUIRK_BBTOUCH_LOWRES     0x0001
+#define WACOM_QUIRK_NO_INPUT           0x0002
+#define WACOM_QUIRK_MONITOR            0x0004
+#define WACOM_QUIRK_BATTERY            0x0008
 
 #define WACOM_PEN_FIELD(f)     (((f)->logical == HID_DG_STYLUS) || \
                                 ((f)->physical == HID_DG_STYLUS) || \
@@ -122,6 +125,7 @@ enum {
        BAMBOO_PT,
        WACOM_24HDT,
        WACOM_27QHDT,
+       BAMBOO_PAD,
        TABLETPC,   /* add new TPC below */
        TABLETPCE,
        TABLETPC2FG,
@@ -169,6 +173,8 @@ struct wacom_shared {
        unsigned touch_max;
        int type;
        struct input_dev *touch_input;
+       struct hid_device *pen;
+       struct hid_device *touch;
 };
 
 struct hid_data {
@@ -205,6 +211,7 @@ struct wacom_wac {
        int battery_capacity;
        int num_contacts_left;
        int bat_charging;
+       int bat_connected;
        int ps_connected;
        u8 bt_features;
        u8 bt_high_speed;
index bc60dec3f586fec38c995af8300506a5f7caf5b5..d6126200361fcebf723808635d3798b8e932caf2 100644 (file)
@@ -6,13 +6,23 @@ comment "HSI clients"
 
 config NOKIA_MODEM
        tristate "Nokia Modem"
-       depends on HSI && SSI_PROTOCOL
+       depends on HSI && SSI_PROTOCOL && CMT_SPEECH
        help
        Say Y here if you want to add support for the modem on Nokia
        N900 (Nokia RX-51) hardware.
 
        If unsure, say N.
 
+config CMT_SPEECH
+       tristate "CMT speech"
+       depends on HSI && SSI_PROTOCOL
+       help
+       If you say Y here, you will enable the CMT speech protocol used
+       by Nokia modems. If you say M the protocol will be available as
+       module named cmt_speech.
+
+       If unsure, say N.
+
 config SSI_PROTOCOL
        tristate "SSI protocol"
        depends on HSI && PHONET && OMAP_SSI
index 4d5bc0e0b27b814b53dd076715d0cdfdb04f7d96..26072326640702152d6c383cc4aaf068cb6080f1 100644 (file)
@@ -4,4 +4,5 @@
 
 obj-$(CONFIG_NOKIA_MODEM)      += nokia-modem.o
 obj-$(CONFIG_SSI_PROTOCOL)     += ssi_protocol.o
+obj-$(CONFIG_CMT_SPEECH)       += cmt_speech.o
 obj-$(CONFIG_HSI_CHAR)         += hsi_char.o
diff --git a/drivers/hsi/clients/cmt_speech.c b/drivers/hsi/clients/cmt_speech.c
new file mode 100644 (file)
index 0000000..4983529
--- /dev/null
@@ -0,0 +1,1457 @@
+/*
+ * cmt_speech.c - HSI CMT speech driver
+ *
+ * Copyright (C) 2008,2009,2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Kai Vehmanen <kai.vehmanen@nokia.com>
+ * Original author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/ioctl.h>
+#include <linux/uaccess.h>
+#include <linux/pm_qos.h>
+#include <linux/hsi/hsi.h>
+#include <linux/hsi/ssi_protocol.h>
+#include <linux/hsi/cs-protocol.h>
+
+#define CS_MMAP_SIZE   PAGE_SIZE
+
+struct char_queue {
+       struct list_head        list;
+       u32                     msg;
+};
+
+struct cs_char {
+       unsigned int            opened;
+       struct hsi_client       *cl;
+       struct cs_hsi_iface     *hi;
+       struct list_head        chardev_queue;
+       struct list_head        dataind_queue;
+       int                     dataind_pending;
+       /* mmap things */
+       unsigned long           mmap_base;
+       unsigned long           mmap_size;
+       spinlock_t              lock;
+       struct fasync_struct    *async_queue;
+       wait_queue_head_t       wait;
+       /* hsi channel ids */
+       int                     channel_id_cmd;
+       int                     channel_id_data;
+};
+
+#define SSI_CHANNEL_STATE_READING      1
+#define SSI_CHANNEL_STATE_WRITING      (1 << 1)
+#define SSI_CHANNEL_STATE_POLL         (1 << 2)
+#define SSI_CHANNEL_STATE_ERROR                (1 << 3)
+
+#define TARGET_MASK                    0xf000000
+#define TARGET_REMOTE                  (1 << CS_DOMAIN_SHIFT)
+#define TARGET_LOCAL                   0
+
+/* Number of pre-allocated commands buffers */
+#define CS_MAX_CMDS                    4
+
+/*
+ * During data transfers, transactions must be handled
+ * within 20ms (fixed value in cmtspeech HSI protocol)
+ */
+#define CS_QOS_LATENCY_FOR_DATA_USEC   20000
+
+/* Timeout to wait for pending HSI transfers to complete */
+#define CS_HSI_TRANSFER_TIMEOUT_MS      500
+
+
+#define RX_PTR_BOUNDARY_SHIFT          8
+#define RX_PTR_MAX_SHIFT               (RX_PTR_BOUNDARY_SHIFT + \
+                                               CS_MAX_BUFFERS_SHIFT)
+struct cs_hsi_iface {
+       struct hsi_client               *cl;
+       struct hsi_client               *master;
+
+       unsigned int                    iface_state;
+       unsigned int                    wakeline_state;
+       unsigned int                    control_state;
+       unsigned int                    data_state;
+
+       /* state exposed to application */
+       struct cs_mmap_config_block     *mmap_cfg;
+
+       unsigned long                   mmap_base;
+       unsigned long                   mmap_size;
+
+       unsigned int                    rx_slot;
+       unsigned int                    tx_slot;
+
+       /* note: for security reasons, we do not trust the contents of
+        * mmap_cfg, but instead duplicate the variables here */
+       unsigned int                    buf_size;
+       unsigned int                    rx_bufs;
+       unsigned int                    tx_bufs;
+       unsigned int                    rx_ptr_boundary;
+       unsigned int                    rx_offsets[CS_MAX_BUFFERS];
+       unsigned int                    tx_offsets[CS_MAX_BUFFERS];
+
+       /* size of aligned memory blocks */
+       unsigned int                    slot_size;
+       unsigned int                    flags;
+
+       struct list_head                cmdqueue;
+
+       struct hsi_msg                  *data_rx_msg;
+       struct hsi_msg                  *data_tx_msg;
+       wait_queue_head_t               datawait;
+
+       struct pm_qos_request           pm_qos_req;
+
+       spinlock_t                      lock;
+};
+
+static struct cs_char cs_char_data;
+
+static void cs_hsi_read_on_control(struct cs_hsi_iface *hi);
+static void cs_hsi_read_on_data(struct cs_hsi_iface *hi);
+
+static inline void rx_ptr_shift_too_big(void)
+{
+       BUILD_BUG_ON((1LLU << RX_PTR_MAX_SHIFT) > UINT_MAX);
+}
+
+static void cs_notify(u32 message, struct list_head *head)
+{
+       struct char_queue *entry;
+
+       spin_lock(&cs_char_data.lock);
+
+       if (!cs_char_data.opened) {
+               spin_unlock(&cs_char_data.lock);
+               goto out;
+       }
+
+       entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+       if (!entry) {
+               dev_err(&cs_char_data.cl->device,
+                       "Can't allocate new entry for the queue.\n");
+               spin_unlock(&cs_char_data.lock);
+               goto out;
+       }
+
+       entry->msg = message;
+       list_add_tail(&entry->list, head);
+
+       spin_unlock(&cs_char_data.lock);
+
+       wake_up_interruptible(&cs_char_data.wait);
+       kill_fasync(&cs_char_data.async_queue, SIGIO, POLL_IN);
+
+out:
+       return;
+}
+
+static u32 cs_pop_entry(struct list_head *head)
+{
+       struct char_queue *entry;
+       u32 data;
+
+       entry = list_entry(head->next, struct char_queue, list);
+       data = entry->msg;
+       list_del(&entry->list);
+       kfree(entry);
+
+       return data;
+}
+
+static void cs_notify_control(u32 message)
+{
+       cs_notify(message, &cs_char_data.chardev_queue);
+}
+
+static void cs_notify_data(u32 message, int maxlength)
+{
+       cs_notify(message, &cs_char_data.dataind_queue);
+
+       spin_lock(&cs_char_data.lock);
+       cs_char_data.dataind_pending++;
+       while (cs_char_data.dataind_pending > maxlength &&
+                               !list_empty(&cs_char_data.dataind_queue)) {
+               dev_dbg(&cs_char_data.cl->device, "data notification "
+               "queue overrun (%u entries)\n", cs_char_data.dataind_pending);
+
+               cs_pop_entry(&cs_char_data.dataind_queue);
+               cs_char_data.dataind_pending--;
+       }
+       spin_unlock(&cs_char_data.lock);
+}
+
+static inline void cs_set_cmd(struct hsi_msg *msg, u32 cmd)
+{
+       u32 *data = sg_virt(msg->sgt.sgl);
+       *data = cmd;
+}
+
+static inline u32 cs_get_cmd(struct hsi_msg *msg)
+{
+       u32 *data = sg_virt(msg->sgt.sgl);
+       return *data;
+}
+
+static void cs_release_cmd(struct hsi_msg *msg)
+{
+       struct cs_hsi_iface *hi = msg->context;
+
+       list_add_tail(&msg->link, &hi->cmdqueue);
+}
+
+static void cs_cmd_destructor(struct hsi_msg *msg)
+{
+       struct cs_hsi_iface *hi = msg->context;
+
+       spin_lock(&hi->lock);
+
+       dev_dbg(&cs_char_data.cl->device, "control cmd destructor\n");
+
+       if (hi->iface_state != CS_STATE_CLOSED)
+               dev_err(&hi->cl->device, "Cmd flushed while driver active\n");
+
+       if (msg->ttype == HSI_MSG_READ)
+               hi->control_state &=
+                       ~(SSI_CHANNEL_STATE_POLL | SSI_CHANNEL_STATE_READING);
+       else if (msg->ttype == HSI_MSG_WRITE &&
+                       hi->control_state & SSI_CHANNEL_STATE_WRITING)
+               hi->control_state &= ~SSI_CHANNEL_STATE_WRITING;
+
+       cs_release_cmd(msg);
+
+       spin_unlock(&hi->lock);
+}
+
+static struct hsi_msg *cs_claim_cmd(struct cs_hsi_iface* ssi)
+{
+       struct hsi_msg *msg;
+
+       BUG_ON(list_empty(&ssi->cmdqueue));
+
+       msg = list_first_entry(&ssi->cmdqueue, struct hsi_msg, link);
+       list_del(&msg->link);
+       msg->destructor = cs_cmd_destructor;
+
+       return msg;
+}
+
+static void cs_free_cmds(struct cs_hsi_iface *ssi)
+{
+       struct hsi_msg *msg, *tmp;
+
+       list_for_each_entry_safe(msg, tmp, &ssi->cmdqueue, link) {
+               list_del(&msg->link);
+               msg->destructor = NULL;
+               kfree(sg_virt(msg->sgt.sgl));
+               hsi_free_msg(msg);
+       }
+}
+
+static int cs_alloc_cmds(struct cs_hsi_iface *hi)
+{
+       struct hsi_msg *msg;
+       u32 *buf;
+       unsigned int i;
+
+       INIT_LIST_HEAD(&hi->cmdqueue);
+
+       for (i = 0; i < CS_MAX_CMDS; i++) {
+               msg = hsi_alloc_msg(1, GFP_KERNEL);
+               if (!msg)
+                       goto out;
+               buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+               if (!buf) {
+                       hsi_free_msg(msg);
+                       goto out;
+               }
+               sg_init_one(msg->sgt.sgl, buf, sizeof(*buf));
+               msg->channel = cs_char_data.channel_id_cmd;
+               msg->context = hi;
+               list_add_tail(&msg->link, &hi->cmdqueue);
+       }
+
+       return 0;
+
+out:
+       cs_free_cmds(hi);
+       return -ENOMEM;
+}
+
+static void cs_hsi_data_destructor(struct hsi_msg *msg)
+{
+       struct cs_hsi_iface *hi = msg->context;
+       const char *dir = (msg->ttype == HSI_MSG_READ) ? "TX" : "RX";
+
+       dev_dbg(&cs_char_data.cl->device, "Freeing data %s message\n", dir);
+
+       spin_lock(&hi->lock);
+       if (hi->iface_state != CS_STATE_CLOSED)
+               dev_err(&cs_char_data.cl->device,
+                               "Data %s flush while device active\n", dir);
+       if (msg->ttype == HSI_MSG_READ)
+               hi->data_state &=
+                       ~(SSI_CHANNEL_STATE_POLL | SSI_CHANNEL_STATE_READING);
+       else
+               hi->data_state &= ~SSI_CHANNEL_STATE_WRITING;
+
+       msg->status = HSI_STATUS_COMPLETED;
+       if (unlikely(waitqueue_active(&hi->datawait)))
+               wake_up_interruptible(&hi->datawait);
+
+       spin_unlock(&hi->lock);
+}
+
+static int cs_hsi_alloc_data(struct cs_hsi_iface *hi)
+{
+       struct hsi_msg *txmsg, *rxmsg;
+       int res = 0;
+
+       rxmsg = hsi_alloc_msg(1, GFP_KERNEL);
+       if (!rxmsg) {
+               res = -ENOMEM;
+               goto out1;
+       }
+       rxmsg->channel = cs_char_data.channel_id_data;
+       rxmsg->destructor = cs_hsi_data_destructor;
+       rxmsg->context = hi;
+
+       txmsg = hsi_alloc_msg(1, GFP_KERNEL);
+       if (!txmsg) {
+               res = -ENOMEM;
+               goto out2;
+       }
+       txmsg->channel = cs_char_data.channel_id_data;
+       txmsg->destructor = cs_hsi_data_destructor;
+       txmsg->context = hi;
+
+       hi->data_rx_msg = rxmsg;
+       hi->data_tx_msg = txmsg;
+
+       return 0;
+
+out2:
+       hsi_free_msg(rxmsg);
+out1:
+       return res;
+}
+
+static void cs_hsi_free_data_msg(struct hsi_msg *msg)
+{
+       WARN_ON(msg->status != HSI_STATUS_COMPLETED &&
+                                       msg->status != HSI_STATUS_ERROR);
+       hsi_free_msg(msg);
+}
+
+static void cs_hsi_free_data(struct cs_hsi_iface *hi)
+{
+       cs_hsi_free_data_msg(hi->data_rx_msg);
+       cs_hsi_free_data_msg(hi->data_tx_msg);
+}
+
+static inline void __cs_hsi_error_pre(struct cs_hsi_iface *hi,
+                                       struct hsi_msg *msg, const char *info,
+                                       unsigned int *state)
+{
+       spin_lock(&hi->lock);
+       dev_err(&hi->cl->device, "HSI %s error, msg %d, state %u\n",
+               info, msg->status, *state);
+}
+
+static inline void __cs_hsi_error_post(struct cs_hsi_iface *hi)
+{
+       spin_unlock(&hi->lock);
+}
+
+static inline void __cs_hsi_error_read_bits(unsigned int *state)
+{
+       *state |= SSI_CHANNEL_STATE_ERROR;
+       *state &= ~(SSI_CHANNEL_STATE_READING | SSI_CHANNEL_STATE_POLL);
+}
+
+static inline void __cs_hsi_error_write_bits(unsigned int *state)
+{
+       *state |= SSI_CHANNEL_STATE_ERROR;
+       *state &= ~SSI_CHANNEL_STATE_WRITING;
+}
+
+static void cs_hsi_control_read_error(struct cs_hsi_iface *hi,
+                                                       struct hsi_msg *msg)
+{
+       __cs_hsi_error_pre(hi, msg, "control read", &hi->control_state);
+       cs_release_cmd(msg);
+       __cs_hsi_error_read_bits(&hi->control_state);
+       __cs_hsi_error_post(hi);
+}
+
+static void cs_hsi_control_write_error(struct cs_hsi_iface *hi,
+                                                       struct hsi_msg *msg)
+{
+       __cs_hsi_error_pre(hi, msg, "control write", &hi->control_state);
+       cs_release_cmd(msg);
+       __cs_hsi_error_write_bits(&hi->control_state);
+       __cs_hsi_error_post(hi);
+
+}
+
+static void cs_hsi_data_read_error(struct cs_hsi_iface *hi, struct hsi_msg *msg)
+{
+       __cs_hsi_error_pre(hi, msg, "data read", &hi->data_state);
+       __cs_hsi_error_read_bits(&hi->data_state);
+       __cs_hsi_error_post(hi);
+}
+
+static void cs_hsi_data_write_error(struct cs_hsi_iface *hi,
+                                                       struct hsi_msg *msg)
+{
+       __cs_hsi_error_pre(hi, msg, "data write", &hi->data_state);
+       __cs_hsi_error_write_bits(&hi->data_state);
+       __cs_hsi_error_post(hi);
+}
+
+static void cs_hsi_read_on_control_complete(struct hsi_msg *msg)
+{
+       u32 cmd = cs_get_cmd(msg);
+       struct cs_hsi_iface *hi = msg->context;
+
+       spin_lock(&hi->lock);
+       hi->control_state &= ~SSI_CHANNEL_STATE_READING;
+       if (msg->status == HSI_STATUS_ERROR) {
+               dev_err(&hi->cl->device, "Control RX error detected\n");
+               cs_hsi_control_read_error(hi, msg);
+               spin_unlock(&hi->lock);
+               goto out;
+       }
+       dev_dbg(&hi->cl->device, "Read on control: %08X\n", cmd);
+       cs_release_cmd(msg);
+       if (hi->flags & CS_FEAT_TSTAMP_RX_CTRL) {
+               struct timespec *tstamp =
+                       &hi->mmap_cfg->tstamp_rx_ctrl;
+               do_posix_clock_monotonic_gettime(tstamp);
+       }
+       spin_unlock(&hi->lock);
+
+       cs_notify_control(cmd);
+
+out:
+       cs_hsi_read_on_control(hi);
+}
+
+static void cs_hsi_peek_on_control_complete(struct hsi_msg *msg)
+{
+       struct cs_hsi_iface *hi = msg->context;
+       int ret;
+
+       if (msg->status == HSI_STATUS_ERROR) {
+               dev_err(&hi->cl->device, "Control peek RX error detected\n");
+               cs_hsi_control_read_error(hi, msg);
+               return;
+       }
+
+       WARN_ON(!(hi->control_state & SSI_CHANNEL_STATE_READING));
+
+       dev_dbg(&hi->cl->device, "Peek on control complete, reading\n");
+       msg->sgt.nents = 1;
+       msg->complete = cs_hsi_read_on_control_complete;
+       ret = hsi_async_read(hi->cl, msg);
+       if (ret)
+               cs_hsi_control_read_error(hi, msg);
+}
+
+static void cs_hsi_read_on_control(struct cs_hsi_iface *hi)
+{
+       struct hsi_msg *msg;
+       int ret;
+
+       spin_lock(&hi->lock);
+       if (hi->control_state & SSI_CHANNEL_STATE_READING) {
+               dev_err(&hi->cl->device, "Control read already pending (%d)\n",
+                       hi->control_state);
+               spin_unlock(&hi->lock);
+               return;
+       }
+       if (hi->control_state & SSI_CHANNEL_STATE_ERROR) {
+               dev_err(&hi->cl->device, "Control read error (%d)\n",
+                       hi->control_state);
+               spin_unlock(&hi->lock);
+               return;
+       }
+       hi->control_state |= SSI_CHANNEL_STATE_READING;
+       dev_dbg(&hi->cl->device, "Issuing RX on control\n");
+       msg = cs_claim_cmd(hi);
+       spin_unlock(&hi->lock);
+
+       msg->sgt.nents = 0;
+       msg->complete = cs_hsi_peek_on_control_complete;
+       ret = hsi_async_read(hi->cl, msg);
+       if (ret)
+               cs_hsi_control_read_error(hi, msg);
+}
+
+static void cs_hsi_write_on_control_complete(struct hsi_msg *msg)
+{
+       struct cs_hsi_iface *hi = msg->context;
+       if (msg->status == HSI_STATUS_COMPLETED) {
+               spin_lock(&hi->lock);
+               hi->control_state &= ~SSI_CHANNEL_STATE_WRITING;
+               cs_release_cmd(msg);
+               spin_unlock(&hi->lock);
+       } else if (msg->status == HSI_STATUS_ERROR) {
+               cs_hsi_control_write_error(hi, msg);
+       } else {
+               dev_err(&hi->cl->device,
+                       "unexpected status in control write callback %d\n",
+                       msg->status);
+       }
+}
+
+static int cs_hsi_write_on_control(struct cs_hsi_iface *hi, u32 message)
+{
+       struct hsi_msg *msg;
+       int ret;
+
+       spin_lock(&hi->lock);
+       if (hi->control_state & SSI_CHANNEL_STATE_ERROR) {
+               spin_unlock(&hi->lock);
+               return -EIO;
+       }
+       if (hi->control_state & SSI_CHANNEL_STATE_WRITING) {
+               dev_err(&hi->cl->device,
+                       "Write still pending on control channel.\n");
+               spin_unlock(&hi->lock);
+               return -EBUSY;
+       }
+       hi->control_state |= SSI_CHANNEL_STATE_WRITING;
+       msg = cs_claim_cmd(hi);
+       spin_unlock(&hi->lock);
+
+       cs_set_cmd(msg, message);
+       msg->sgt.nents = 1;
+       msg->complete = cs_hsi_write_on_control_complete;
+       dev_dbg(&hi->cl->device,
+               "Sending control message %08X\n", message);
+       ret = hsi_async_write(hi->cl, msg);
+       if (ret) {
+               dev_err(&hi->cl->device,
+                       "async_write failed with %d\n", ret);
+               cs_hsi_control_write_error(hi, msg);
+       }
+
+       /*
+        * Make sure control read is always pending when issuing
+        * new control writes. This is needed as the controller
+        * may flush our messages if e.g. the peer device reboots
+        * unexpectedly (and we cannot directly resubmit a new read from
+        * the message destructor; see cs_cmd_destructor()).
+        */
+       if (!(hi->control_state & SSI_CHANNEL_STATE_READING)) {
+               dev_err(&hi->cl->device, "Restarting control reads\n");
+               cs_hsi_read_on_control(hi);
+       }
+
+       return 0;
+}
+
+static void cs_hsi_read_on_data_complete(struct hsi_msg *msg)
+{
+       struct cs_hsi_iface *hi = msg->context;
+       u32 payload;
+
+       if (unlikely(msg->status == HSI_STATUS_ERROR)) {
+               cs_hsi_data_read_error(hi, msg);
+               return;
+       }
+
+       spin_lock(&hi->lock);
+       WARN_ON(!(hi->data_state & SSI_CHANNEL_STATE_READING));
+       hi->data_state &= ~SSI_CHANNEL_STATE_READING;
+       payload = CS_RX_DATA_RECEIVED;
+       payload |= hi->rx_slot;
+       hi->rx_slot++;
+       hi->rx_slot %= hi->rx_ptr_boundary;
+       /* expose current rx ptr in mmap area */
+       hi->mmap_cfg->rx_ptr = hi->rx_slot;
+       if (unlikely(waitqueue_active(&hi->datawait)))
+               wake_up_interruptible(&hi->datawait);
+       spin_unlock(&hi->lock);
+
+       cs_notify_data(payload, hi->rx_bufs);
+       cs_hsi_read_on_data(hi);
+}
+
+static void cs_hsi_peek_on_data_complete(struct hsi_msg *msg)
+{
+       struct cs_hsi_iface *hi = msg->context;
+       u32 *address;
+       int ret;
+
+       if (unlikely(msg->status == HSI_STATUS_ERROR)) {
+               cs_hsi_data_read_error(hi, msg);
+               return;
+       }
+       if (unlikely(hi->iface_state != CS_STATE_CONFIGURED)) {
+               dev_err(&hi->cl->device, "Data received in invalid state\n");
+               cs_hsi_data_read_error(hi, msg);
+               return;
+       }
+
+       spin_lock(&hi->lock);
+       WARN_ON(!(hi->data_state & SSI_CHANNEL_STATE_POLL));
+       hi->data_state &= ~SSI_CHANNEL_STATE_POLL;
+       hi->data_state |= SSI_CHANNEL_STATE_READING;
+       spin_unlock(&hi->lock);
+
+       address = (u32 *)(hi->mmap_base +
+                               hi->rx_offsets[hi->rx_slot % hi->rx_bufs]);
+       sg_init_one(msg->sgt.sgl, address, hi->buf_size);
+       msg->sgt.nents = 1;
+       msg->complete = cs_hsi_read_on_data_complete;
+       ret = hsi_async_read(hi->cl, msg);
+       if (ret)
+               cs_hsi_data_read_error(hi, msg);
+}
+
+/*
+ * Read/write transaction is ongoing. Returns false if in
+ * SSI_CHANNEL_STATE_POLL state.
+ */
+static inline int cs_state_xfer_active(unsigned int state)
+{
+       return (state & SSI_CHANNEL_STATE_WRITING) ||
+               (state & SSI_CHANNEL_STATE_READING);
+}
+
+/*
+ * No pending read/writes
+ */
+static inline int cs_state_idle(unsigned int state)
+{
+       return !(state & ~SSI_CHANNEL_STATE_ERROR);
+}
+
+static void cs_hsi_read_on_data(struct cs_hsi_iface *hi)
+{
+       struct hsi_msg *rxmsg;
+       int ret;
+
+       spin_lock(&hi->lock);
+       if (hi->data_state &
+               (SSI_CHANNEL_STATE_READING | SSI_CHANNEL_STATE_POLL)) {
+               dev_dbg(&hi->cl->device, "Data read already pending (%u)\n",
+                       hi->data_state);
+               spin_unlock(&hi->lock);
+               return;
+       }
+       hi->data_state |= SSI_CHANNEL_STATE_POLL;
+       spin_unlock(&hi->lock);
+
+       rxmsg = hi->data_rx_msg;
+       sg_init_one(rxmsg->sgt.sgl, (void *)hi->mmap_base, 0);
+       rxmsg->sgt.nents = 0;
+       rxmsg->complete = cs_hsi_peek_on_data_complete;
+
+       ret = hsi_async_read(hi->cl, rxmsg);
+       if (ret)
+               cs_hsi_data_read_error(hi, rxmsg);
+}
+
+static void cs_hsi_write_on_data_complete(struct hsi_msg *msg)
+{
+       struct cs_hsi_iface *hi = msg->context;
+
+       if (msg->status == HSI_STATUS_COMPLETED) {
+               spin_lock(&hi->lock);
+               hi->data_state &= ~SSI_CHANNEL_STATE_WRITING;
+               if (unlikely(waitqueue_active(&hi->datawait)))
+                       wake_up_interruptible(&hi->datawait);
+               spin_unlock(&hi->lock);
+       } else {
+               cs_hsi_data_write_error(hi, msg);
+       }
+}
+
+static int cs_hsi_write_on_data(struct cs_hsi_iface *hi, unsigned int slot)
+{
+       u32 *address;
+       struct hsi_msg *txmsg;
+       int ret;
+
+       spin_lock(&hi->lock);
+       if (hi->iface_state != CS_STATE_CONFIGURED) {
+               dev_err(&hi->cl->device, "Not configured, aborting\n");
+               ret = -EINVAL;
+               goto error;
+       }
+       if (hi->data_state & SSI_CHANNEL_STATE_ERROR) {
+               dev_err(&hi->cl->device, "HSI error, aborting\n");
+               ret = -EIO;
+               goto error;
+       }
+       if (hi->data_state & SSI_CHANNEL_STATE_WRITING) {
+               dev_err(&hi->cl->device, "Write pending on data channel.\n");
+               ret = -EBUSY;
+               goto error;
+       }
+       hi->data_state |= SSI_CHANNEL_STATE_WRITING;
+       spin_unlock(&hi->lock);
+
+       hi->tx_slot = slot;
+       address = (u32 *)(hi->mmap_base + hi->tx_offsets[hi->tx_slot]);
+       txmsg = hi->data_tx_msg;
+       sg_init_one(txmsg->sgt.sgl, address, hi->buf_size);
+       txmsg->complete = cs_hsi_write_on_data_complete;
+       ret = hsi_async_write(hi->cl, txmsg);
+       if (ret)
+               cs_hsi_data_write_error(hi, txmsg);
+
+       return ret;
+
+error:
+       spin_unlock(&hi->lock);
+       if (ret == -EIO)
+               cs_hsi_data_write_error(hi, hi->data_tx_msg);
+
+       return ret;
+}
+
+static unsigned int cs_hsi_get_state(struct cs_hsi_iface *hi)
+{
+       return hi->iface_state;
+}
+
+static int cs_hsi_command(struct cs_hsi_iface *hi, u32 cmd)
+{
+       int ret = 0;
+
+       local_bh_disable();
+       switch (cmd & TARGET_MASK) {
+       case TARGET_REMOTE:
+               ret = cs_hsi_write_on_control(hi, cmd);
+               break;
+       case TARGET_LOCAL:
+               if ((cmd & CS_CMD_MASK) == CS_TX_DATA_READY)
+                       ret = cs_hsi_write_on_data(hi, cmd & CS_PARAM_MASK);
+               else
+                       ret = -EINVAL;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       local_bh_enable();
+
+       return ret;
+}
+
+static void cs_hsi_set_wakeline(struct cs_hsi_iface *hi, bool new_state)
+{
+       int change = 0;
+
+       spin_lock_bh(&hi->lock);
+       if (hi->wakeline_state != new_state) {
+               hi->wakeline_state = new_state;
+               change = 1;
+               dev_dbg(&hi->cl->device, "setting wake line to %d (%p)\n",
+                       new_state, hi->cl);
+       }
+       spin_unlock_bh(&hi->lock);
+
+       if (change) {
+               if (new_state)
+                       ssip_slave_start_tx(hi->master);
+               else
+                       ssip_slave_stop_tx(hi->master);
+       }
+
+       dev_dbg(&hi->cl->device, "wake line set to %d (%p)\n",
+               new_state, hi->cl);
+}
+
+static void set_buffer_sizes(struct cs_hsi_iface *hi, int rx_bufs, int tx_bufs)
+{
+       hi->rx_bufs = rx_bufs;
+       hi->tx_bufs = tx_bufs;
+       hi->mmap_cfg->rx_bufs = rx_bufs;
+       hi->mmap_cfg->tx_bufs = tx_bufs;
+
+       if (hi->flags & CS_FEAT_ROLLING_RX_COUNTER) {
+               /*
+                * For more robust overrun detection, let the rx
+                * pointer run in range 0..'boundary-1'. Boundary
+                * is a multiple of rx_bufs, and limited in max size
+                * by RX_PTR_MAX_SHIFT to allow for fast ptr-diff
+                * calculation.
+                */
+               hi->rx_ptr_boundary = (rx_bufs << RX_PTR_BOUNDARY_SHIFT);
+               hi->mmap_cfg->rx_ptr_boundary = hi->rx_ptr_boundary;
+       } else {
+               hi->rx_ptr_boundary = hi->rx_bufs;
+       }
+}
+
+static int check_buf_params(struct cs_hsi_iface *hi,
+                                       const struct cs_buffer_config *buf_cfg)
+{
+       size_t buf_size_aligned = L1_CACHE_ALIGN(buf_cfg->buf_size) *
+                                       (buf_cfg->rx_bufs + buf_cfg->tx_bufs);
+       size_t ctrl_size_aligned = L1_CACHE_ALIGN(sizeof(*hi->mmap_cfg));
+       int r = 0;
+
+       if (buf_cfg->rx_bufs > CS_MAX_BUFFERS ||
+                                       buf_cfg->tx_bufs > CS_MAX_BUFFERS) {
+               r = -EINVAL;
+       } else if ((buf_size_aligned + ctrl_size_aligned) >= hi->mmap_size) {
+               dev_err(&hi->cl->device, "No space for the requested buffer "
+                       "configuration\n");
+               r = -ENOBUFS;
+       }
+
+       return r;
+}
+
+/**
+ * Block until pending data transfers have completed.
+ */
+static int cs_hsi_data_sync(struct cs_hsi_iface *hi)
+{
+       int r = 0;
+
+       spin_lock_bh(&hi->lock);
+
+       if (!cs_state_xfer_active(hi->data_state)) {
+               dev_dbg(&hi->cl->device, "hsi_data_sync break, idle\n");
+               goto out;
+       }
+
+       for (;;) {
+               int s;
+               DEFINE_WAIT(wait);
+               if (!cs_state_xfer_active(hi->data_state))
+                       goto out;
+               if (signal_pending(current)) {
+                       r = -ERESTARTSYS;
+                       goto out;
+               }
+               /**
+                * prepare_to_wait must be called with hi->lock held
+                * so that callbacks can check for waitqueue_active()
+                */
+               prepare_to_wait(&hi->datawait, &wait, TASK_INTERRUPTIBLE);
+               spin_unlock_bh(&hi->lock);
+               s = schedule_timeout(
+                       msecs_to_jiffies(CS_HSI_TRANSFER_TIMEOUT_MS));
+               spin_lock_bh(&hi->lock);
+               finish_wait(&hi->datawait, &wait);
+               if (!s) {
+                       dev_dbg(&hi->cl->device,
+                               "hsi_data_sync timeout after %d ms\n",
+                               CS_HSI_TRANSFER_TIMEOUT_MS);
+                       r = -EIO;
+                       goto out;
+               }
+       }
+
+out:
+       spin_unlock_bh(&hi->lock);
+       dev_dbg(&hi->cl->device, "hsi_data_sync done with res %d\n", r);
+
+       return r;
+}
+
+static void cs_hsi_data_enable(struct cs_hsi_iface *hi,
+                                       struct cs_buffer_config *buf_cfg)
+{
+       unsigned int data_start, i;
+
+       BUG_ON(hi->buf_size == 0);
+
+       set_buffer_sizes(hi, buf_cfg->rx_bufs, buf_cfg->tx_bufs);
+
+       hi->slot_size = L1_CACHE_ALIGN(hi->buf_size);
+       dev_dbg(&hi->cl->device,
+                       "setting slot size to %u, buf size %u, align %u\n",
+                       hi->slot_size, hi->buf_size, L1_CACHE_BYTES);
+
+       data_start = L1_CACHE_ALIGN(sizeof(*hi->mmap_cfg));
+       dev_dbg(&hi->cl->device,
+                       "setting data start at %u, cfg block %u, align %u\n",
+                       data_start, sizeof(*hi->mmap_cfg), L1_CACHE_BYTES);
+
+       for (i = 0; i < hi->mmap_cfg->rx_bufs; i++) {
+               hi->rx_offsets[i] = data_start + i * hi->slot_size;
+               hi->mmap_cfg->rx_offsets[i] = hi->rx_offsets[i];
+               dev_dbg(&hi->cl->device, "DL buf #%u at %u\n",
+                                       i, hi->rx_offsets[i]);
+       }
+       for (i = 0; i < hi->mmap_cfg->tx_bufs; i++) {
+               hi->tx_offsets[i] = data_start +
+                       (i + hi->mmap_cfg->rx_bufs) * hi->slot_size;
+               hi->mmap_cfg->tx_offsets[i] = hi->tx_offsets[i];
+               dev_dbg(&hi->cl->device, "UL buf #%u at %u\n",
+                                       i, hi->rx_offsets[i]);
+       }
+
+       hi->iface_state = CS_STATE_CONFIGURED;
+}
+
+static void cs_hsi_data_disable(struct cs_hsi_iface *hi, int old_state)
+{
+       if (old_state == CS_STATE_CONFIGURED) {
+               dev_dbg(&hi->cl->device,
+                       "closing data channel with slot size 0\n");
+               hi->iface_state = CS_STATE_OPENED;
+       }
+}
+
+static int cs_hsi_buf_config(struct cs_hsi_iface *hi,
+                                       struct cs_buffer_config *buf_cfg)
+{
+       int r = 0;
+       unsigned int old_state = hi->iface_state;
+
+       spin_lock_bh(&hi->lock);
+       /* Prevent new transactions during buffer reconfig */
+       if (old_state == CS_STATE_CONFIGURED)
+               hi->iface_state = CS_STATE_OPENED;
+       spin_unlock_bh(&hi->lock);
+
+       /*
+        * make sure that no non-zero data reads are ongoing before
+        * proceeding to change the buffer layout
+        */
+       r = cs_hsi_data_sync(hi);
+       if (r < 0)
+               return r;
+
+       WARN_ON(cs_state_xfer_active(hi->data_state));
+
+       spin_lock_bh(&hi->lock);
+       r = check_buf_params(hi, buf_cfg);
+       if (r < 0)
+               goto error;
+
+       hi->buf_size = buf_cfg->buf_size;
+       hi->mmap_cfg->buf_size = hi->buf_size;
+       hi->flags = buf_cfg->flags;
+
+       hi->rx_slot = 0;
+       hi->tx_slot = 0;
+       hi->slot_size = 0;
+
+       if (hi->buf_size)
+               cs_hsi_data_enable(hi, buf_cfg);
+       else
+               cs_hsi_data_disable(hi, old_state);
+
+       spin_unlock_bh(&hi->lock);
+
+       if (old_state != hi->iface_state) {
+               if (hi->iface_state == CS_STATE_CONFIGURED) {
+                       pm_qos_add_request(&hi->pm_qos_req,
+                               PM_QOS_CPU_DMA_LATENCY,
+                               CS_QOS_LATENCY_FOR_DATA_USEC);
+                       local_bh_disable();
+                       cs_hsi_read_on_data(hi);
+                       local_bh_enable();
+               } else if (old_state == CS_STATE_CONFIGURED) {
+                       pm_qos_remove_request(&hi->pm_qos_req);
+               }
+       }
+       return r;
+
+error:
+       spin_unlock_bh(&hi->lock);
+       return r;
+}
+
+static int cs_hsi_start(struct cs_hsi_iface **hi, struct hsi_client *cl,
+                       unsigned long mmap_base, unsigned long mmap_size)
+{
+       int err = 0;
+       struct cs_hsi_iface *hsi_if = kzalloc(sizeof(*hsi_if), GFP_KERNEL);
+
+       dev_dbg(&cl->device, "cs_hsi_start\n");
+
+       if (!hsi_if) {
+               err = -ENOMEM;
+               goto leave0;
+       }
+       spin_lock_init(&hsi_if->lock);
+       hsi_if->cl = cl;
+       hsi_if->iface_state = CS_STATE_CLOSED;
+       hsi_if->mmap_cfg = (struct cs_mmap_config_block *)mmap_base;
+       hsi_if->mmap_base = mmap_base;
+       hsi_if->mmap_size = mmap_size;
+       memset(hsi_if->mmap_cfg, 0, sizeof(*hsi_if->mmap_cfg));
+       init_waitqueue_head(&hsi_if->datawait);
+       err = cs_alloc_cmds(hsi_if);
+       if (err < 0) {
+               dev_err(&cl->device, "Unable to alloc HSI messages\n");
+               goto leave1;
+       }
+       err = cs_hsi_alloc_data(hsi_if);
+       if (err < 0) {
+               dev_err(&cl->device, "Unable to alloc HSI messages for data\n");
+               goto leave2;
+       }
+       err = hsi_claim_port(cl, 1);
+       if (err < 0) {
+               dev_err(&cl->device,
+                               "Could not open, HSI port already claimed\n");
+               goto leave3;
+       }
+       hsi_if->master = ssip_slave_get_master(cl);
+       if (IS_ERR(hsi_if->master)) {
+               err = PTR_ERR(hsi_if->master);
+               dev_err(&cl->device, "Could not get HSI master client\n");
+               goto leave4;
+       }
+       if (!ssip_slave_running(hsi_if->master)) {
+               err = -ENODEV;
+               dev_err(&cl->device,
+                               "HSI port not initialized\n");
+               goto leave4;
+       }
+
+       hsi_if->iface_state = CS_STATE_OPENED;
+       local_bh_disable();
+       cs_hsi_read_on_control(hsi_if);
+       local_bh_enable();
+
+       dev_dbg(&cl->device, "cs_hsi_start...done\n");
+
+       BUG_ON(!hi);
+       *hi = hsi_if;
+
+       return 0;
+
+leave4:
+       hsi_release_port(cl);
+leave3:
+       cs_hsi_free_data(hsi_if);
+leave2:
+       cs_free_cmds(hsi_if);
+leave1:
+       kfree(hsi_if);
+leave0:
+       dev_dbg(&cl->device, "cs_hsi_start...done/error\n\n");
+
+       return err;
+}
+
+static void cs_hsi_stop(struct cs_hsi_iface *hi)
+{
+       dev_dbg(&hi->cl->device, "cs_hsi_stop\n");
+       cs_hsi_set_wakeline(hi, 0);
+       ssip_slave_put_master(hi->master);
+
+       /* hsi_release_port() needs to be called with CS_STATE_CLOSED */
+       hi->iface_state = CS_STATE_CLOSED;
+       hsi_release_port(hi->cl);
+
+       /*
+        * hsi_release_port() should flush out all the pending
+        * messages, so cs_state_idle() should be true for both
+        * control and data channels.
+        */
+       WARN_ON(!cs_state_idle(hi->control_state));
+       WARN_ON(!cs_state_idle(hi->data_state));
+
+       if (pm_qos_request_active(&hi->pm_qos_req))
+               pm_qos_remove_request(&hi->pm_qos_req);
+
+       spin_lock_bh(&hi->lock);
+       cs_hsi_free_data(hi);
+       cs_free_cmds(hi);
+       spin_unlock_bh(&hi->lock);
+       kfree(hi);
+}
+
+static int cs_char_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       struct cs_char *csdata = vma->vm_private_data;
+       struct page *page;
+
+       page = virt_to_page(csdata->mmap_base);
+       get_page(page);
+       vmf->page = page;
+
+       return 0;
+}
+
+static struct vm_operations_struct cs_char_vm_ops = {
+       .fault  = cs_char_vma_fault,
+};
+
+static int cs_char_fasync(int fd, struct file *file, int on)
+{
+       struct cs_char *csdata = file->private_data;
+
+       if (fasync_helper(fd, file, on, &csdata->async_queue) < 0)
+               return -EIO;
+
+       return 0;
+}
+
+static unsigned int cs_char_poll(struct file *file, poll_table *wait)
+{
+       struct cs_char *csdata = file->private_data;
+       unsigned int ret = 0;
+
+       poll_wait(file, &cs_char_data.wait, wait);
+       spin_lock_bh(&csdata->lock);
+       if (!list_empty(&csdata->chardev_queue))
+               ret = POLLIN | POLLRDNORM;
+       else if (!list_empty(&csdata->dataind_queue))
+               ret = POLLIN | POLLRDNORM;
+       spin_unlock_bh(&csdata->lock);
+
+       return ret;
+}
+
+static ssize_t cs_char_read(struct file *file, char __user *buf, size_t count,
+                                                               loff_t *unused)
+{
+       struct cs_char *csdata = file->private_data;
+       u32 data;
+       ssize_t retval;
+
+       if (count < sizeof(data))
+               return -EINVAL;
+
+       for (;;) {
+               DEFINE_WAIT(wait);
+
+               spin_lock_bh(&csdata->lock);
+               if (!list_empty(&csdata->chardev_queue)) {
+                       data = cs_pop_entry(&csdata->chardev_queue);
+               } else if (!list_empty(&csdata->dataind_queue)) {
+                       data = cs_pop_entry(&csdata->dataind_queue);
+                       csdata->dataind_pending--;
+               } else {
+                       data = 0;
+               }
+               spin_unlock_bh(&csdata->lock);
+
+               if (data)
+                       break;
+               if (file->f_flags & O_NONBLOCK) {
+                       retval = -EAGAIN;
+                       goto out;
+               } else if (signal_pending(current)) {
+                       retval = -ERESTARTSYS;
+                       goto out;
+               }
+               prepare_to_wait_exclusive(&csdata->wait, &wait,
+                                               TASK_INTERRUPTIBLE);
+               schedule();
+               finish_wait(&csdata->wait, &wait);
+       }
+
+       retval = put_user(data, (u32 __user *)buf);
+       if (!retval)
+               retval = sizeof(data);
+
+out:
+       return retval;
+}
+
+static ssize_t cs_char_write(struct file *file, const char __user *buf,
+                                               size_t count, loff_t *unused)
+{
+       struct cs_char *csdata = file->private_data;
+       u32 data;
+       int err;
+       ssize_t retval;
+
+       if (count < sizeof(data))
+               return -EINVAL;
+
+       if (get_user(data, (u32 __user *)buf))
+               retval = -EFAULT;
+       else
+               retval = count;
+
+       err = cs_hsi_command(csdata->hi, data);
+       if (err < 0)
+               retval = err;
+
+       return retval;
+}
+
+static long cs_char_ioctl(struct file *file, unsigned int cmd,
+                               unsigned long arg)
+{
+       struct cs_char *csdata = file->private_data;
+       int r = 0;
+
+       switch (cmd) {
+       case CS_GET_STATE: {
+               unsigned int state;
+
+               state = cs_hsi_get_state(csdata->hi);
+               if (copy_to_user((void __user *)arg, &state, sizeof(state)))
+                       r = -EFAULT;
+
+               break;
+       }
+       case CS_SET_WAKELINE: {
+               unsigned int state;
+
+               if (copy_from_user(&state, (void __user *)arg, sizeof(state))) {
+                       r = -EFAULT;
+                       break;
+               }
+
+               if (state > 1) {
+                       r = -EINVAL;
+                       break;
+               }
+
+               cs_hsi_set_wakeline(csdata->hi, !!state);
+
+               break;
+       }
+       case CS_GET_IF_VERSION: {
+               unsigned int ifver = CS_IF_VERSION;
+
+               if (copy_to_user((void __user *)arg, &ifver, sizeof(ifver)))
+                       r = -EFAULT;
+
+               break;
+       }
+       case CS_CONFIG_BUFS: {
+               struct cs_buffer_config buf_cfg;
+
+               if (copy_from_user(&buf_cfg, (void __user *)arg,
+                                                       sizeof(buf_cfg)))
+                       r = -EFAULT;
+               else
+                       r = cs_hsi_buf_config(csdata->hi, &buf_cfg);
+
+               break;
+       }
+       default:
+               r = -ENOTTY;
+               break;
+       }
+
+       return r;
+}
+
+static int cs_char_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       if (vma->vm_end < vma->vm_start)
+               return -EINVAL;
+
+       if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) != 1)
+               return -EINVAL;
+
+       vma->vm_flags |= VM_IO | VM_DONTDUMP | VM_DONTEXPAND;
+       vma->vm_ops = &cs_char_vm_ops;
+       vma->vm_private_data = file->private_data;
+
+       return 0;
+}
+
+static int cs_char_open(struct inode *unused, struct file *file)
+{
+       int ret = 0;
+       unsigned long p;
+
+       spin_lock_bh(&cs_char_data.lock);
+       if (cs_char_data.opened) {
+               ret = -EBUSY;
+               spin_unlock_bh(&cs_char_data.lock);
+               goto out1;
+       }
+       cs_char_data.opened = 1;
+       cs_char_data.dataind_pending = 0;
+       spin_unlock_bh(&cs_char_data.lock);
+
+       p = get_zeroed_page(GFP_KERNEL);
+       if (!p) {
+               ret = -ENOMEM;
+               goto out2;
+       }
+
+       ret = cs_hsi_start(&cs_char_data.hi, cs_char_data.cl, p, CS_MMAP_SIZE);
+       if (ret) {
+               dev_err(&cs_char_data.cl->device, "Unable to initialize HSI\n");
+               goto out3;
+       }
+
+       /* these are only used in release so lock not needed */
+       cs_char_data.mmap_base = p;
+       cs_char_data.mmap_size = CS_MMAP_SIZE;
+
+       file->private_data = &cs_char_data;
+
+       return 0;
+
+out3:
+       free_page(p);
+out2:
+       spin_lock_bh(&cs_char_data.lock);
+       cs_char_data.opened = 0;
+       spin_unlock_bh(&cs_char_data.lock);
+out1:
+       return ret;
+}
+
+static void cs_free_char_queue(struct list_head *head)
+{
+       struct char_queue *entry;
+       struct list_head *cursor, *next;
+
+       if (!list_empty(head)) {
+               list_for_each_safe(cursor, next, head) {
+                       entry = list_entry(cursor, struct char_queue, list);
+                       list_del(&entry->list);
+                       kfree(entry);
+               }
+       }
+
+}
+
+static int cs_char_release(struct inode *unused, struct file *file)
+{
+       struct cs_char *csdata = file->private_data;
+
+       cs_hsi_stop(csdata->hi);
+       spin_lock_bh(&csdata->lock);
+       csdata->hi = NULL;
+       free_page(csdata->mmap_base);
+       cs_free_char_queue(&csdata->chardev_queue);
+       cs_free_char_queue(&csdata->dataind_queue);
+       csdata->opened = 0;
+       spin_unlock_bh(&csdata->lock);
+
+       return 0;
+}
+
+static const struct file_operations cs_char_fops = {
+       .owner          = THIS_MODULE,
+       .read           = cs_char_read,
+       .write          = cs_char_write,
+       .poll           = cs_char_poll,
+       .unlocked_ioctl = cs_char_ioctl,
+       .mmap           = cs_char_mmap,
+       .open           = cs_char_open,
+       .release        = cs_char_release,
+       .fasync         = cs_char_fasync,
+};
+
+static struct miscdevice cs_char_miscdev = {
+       .minor  = MISC_DYNAMIC_MINOR,
+       .name   = "cmt_speech",
+       .fops   = &cs_char_fops
+};
+
+static int cs_hsi_client_probe(struct device *dev)
+{
+       int err = 0;
+       struct hsi_client *cl = to_hsi_client(dev);
+
+       dev_dbg(dev, "hsi_client_probe\n");
+       init_waitqueue_head(&cs_char_data.wait);
+       spin_lock_init(&cs_char_data.lock);
+       cs_char_data.opened = 0;
+       cs_char_data.cl = cl;
+       cs_char_data.hi = NULL;
+       INIT_LIST_HEAD(&cs_char_data.chardev_queue);
+       INIT_LIST_HEAD(&cs_char_data.dataind_queue);
+
+       cs_char_data.channel_id_cmd = hsi_get_channel_id_by_name(cl,
+               "speech-control");
+       if (cs_char_data.channel_id_cmd < 0) {
+               err = cs_char_data.channel_id_cmd;
+               dev_err(dev, "Could not get cmd channel (%d)\n", err);
+               return err;
+       }
+
+       cs_char_data.channel_id_data = hsi_get_channel_id_by_name(cl,
+               "speech-data");
+       if (cs_char_data.channel_id_data < 0) {
+               err = cs_char_data.channel_id_data;
+               dev_err(dev, "Could not get data channel (%d)\n", err);
+               return err;
+       }
+
+       err = misc_register(&cs_char_miscdev);
+       if (err)
+               dev_err(dev, "Failed to register: %d\n", err);
+
+       return err;
+}
+
+static int cs_hsi_client_remove(struct device *dev)
+{
+       struct cs_hsi_iface *hi;
+
+       dev_dbg(dev, "hsi_client_remove\n");
+       misc_deregister(&cs_char_miscdev);
+       spin_lock_bh(&cs_char_data.lock);
+       hi = cs_char_data.hi;
+       cs_char_data.hi = NULL;
+       spin_unlock_bh(&cs_char_data.lock);
+       if (hi)
+               cs_hsi_stop(hi);
+
+       return 0;
+}
+
+static struct hsi_client_driver cs_hsi_driver = {
+       .driver = {
+               .name   = "cmt-speech",
+               .owner  = THIS_MODULE,
+               .probe  = cs_hsi_client_probe,
+               .remove = cs_hsi_client_remove,
+       },
+};
+
+static int __init cs_char_init(void)
+{
+       pr_info("CMT speech driver added\n");
+       return hsi_register_client_driver(&cs_hsi_driver);
+}
+module_init(cs_char_init);
+
+static void __exit cs_char_exit(void)
+{
+       hsi_unregister_client_driver(&cs_hsi_driver);
+       pr_info("CMT speech driver removed\n");
+}
+module_exit(cs_char_exit);
+
+MODULE_ALIAS("hsi:cmt-speech");
+MODULE_AUTHOR("Kai Vehmanen <kai.vehmanen@nokia.com>");
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@nokia.com>");
+MODULE_DESCRIPTION("CMT speech driver");
+MODULE_LICENSE("GPL v2");
index eb4dc63dbc9382ccf00889276532430f559e30f1..bbb19231fa82ed22267adf789f9f7fdb4de91d68 100644 (file)
@@ -46,6 +46,7 @@ struct nokia_modem_device {
        struct nokia_modem_gpio *gpios;
        int                     gpio_amount;
        struct hsi_client       *ssi_protocol;
+       struct hsi_client       *cmt_speech;
 };
 
 static void do_nokia_modem_rst_ind_tasklet(unsigned long data)
@@ -149,6 +150,7 @@ static int nokia_modem_probe(struct device *dev)
        struct hsi_port *port = hsi_get_port(cl);
        int irq, pflags, err;
        struct hsi_board_info ssip;
+       struct hsi_board_info cmtspeech;
 
        np = dev->of_node;
        if (!np) {
@@ -200,6 +202,7 @@ static int nokia_modem_probe(struct device *dev)
        modem->ssi_protocol = hsi_new_client(port, &ssip);
        if (!modem->ssi_protocol) {
                dev_err(dev, "Could not register ssi-protocol device\n");
+               err = -ENOMEM;
                goto error2;
        }
 
@@ -213,12 +216,35 @@ static int nokia_modem_probe(struct device *dev)
                goto error3;
        }
 
-       /* TODO: register cmt-speech hsi client */
+       cmtspeech.name = "cmt-speech";
+       cmtspeech.tx_cfg = cl->tx_cfg;
+       cmtspeech.rx_cfg = cl->rx_cfg;
+       cmtspeech.platform_data = NULL;
+       cmtspeech.archdata = NULL;
+
+       modem->cmt_speech = hsi_new_client(port, &cmtspeech);
+       if (!modem->cmt_speech) {
+               dev_err(dev, "Could not register cmt-speech device\n");
+               err = -ENOMEM;
+               goto error3;
+       }
+
+       err = device_attach(&modem->cmt_speech->device);
+       if (err == 0) {
+               dev_err(dev, "Missing cmt-speech driver\n");
+               err = -EPROBE_DEFER;
+               goto error4;
+       } else if (err < 0) {
+               dev_err(dev, "Could not load cmt-speech driver (%d)\n", err);
+               goto error4;
+       }
 
        dev_info(dev, "Registered Nokia HSI modem\n");
 
        return 0;
 
+error4:
+       hsi_remove_client(&modem->cmt_speech->device, NULL);
 error3:
        hsi_remove_client(&modem->ssi_protocol->device, NULL);
 error2:
@@ -237,6 +263,11 @@ static int nokia_modem_remove(struct device *dev)
        if (!modem)
                return 0;
 
+       if (modem->cmt_speech) {
+               hsi_remove_client(&modem->cmt_speech->device, NULL);
+               modem->cmt_speech = NULL;
+       }
+
        if (modem->ssi_protocol) {
                hsi_remove_client(&modem->ssi_protocol->device, NULL);
                modem->ssi_protocol = NULL;
index 110fade9cb74680f0f37115353fe166f7edeca3d..25d9e72627e9df97cb607de8038d2310d28c214b 100644 (file)
@@ -510,6 +510,7 @@ config SENSORS_G762
 config SENSORS_GPIO_FAN
        tristate "GPIO fan"
        depends on GPIOLIB
+       depends on THERMAL || THERMAL=n
        help
          If you say yes here you get support for fans connected to GPIO lines.
 
@@ -599,8 +600,8 @@ config SENSORS_IT87
        help
          If you say yes here you get support for ITE IT8705F, IT8712F,
          IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E,
-         IT8771E, IT8772E, IT8782F, IT8783E/F and IT8603E sensor chips,
-         and the SiS950 clone.
+         IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E,
+         IT8603E, IT8620E, and IT8623E sensor chips, and the SiS950 clone.
 
          This driver can also be built as a module.  If so, the module
          will be called it87.
@@ -624,7 +625,7 @@ config SENSORS_JC42
          mobile devices and servers.  Support will include, but not be limited
          to, ADT7408, AT30TS00, CAT34TS02, CAT6095, MAX6604, MCP9804, MCP9805,
          MCP98242, MCP98243, MCP98244, MCP9843, SE97, SE98, STTS424(E),
-         STTS2002, STTS3000, TSE2002B3, TSE2002GB2, TS3000B3, and TS3000GB2.
+         STTS2002, STTS3000, TSE2002, TSE2004, TS3000, and TS3001.
 
          This driver can also be built as a module.  If so, the module
          will be called jc42.
@@ -1145,6 +1146,16 @@ config SENSORS_NCT7802
          This driver can also be built as a module.  If so, the module
          will be called nct7802.
 
+config SENSORS_NCT7904
+       tristate "Nuvoton NCT7904"
+       depends on I2C
+       help
+         If you say yes here you get support for the Nuvoton NCT7904
+         hardware monitoring chip, including manual fan speed control.
+
+         This driver can also be built as a module.  If so, the module
+         will be called nct7904.
+
 config SENSORS_PCF8591
        tristate "Philips PCF8591 ADC/DAC"
        depends on I2C
@@ -1164,6 +1175,7 @@ source drivers/hwmon/pmbus/Kconfig
 config SENSORS_PWM_FAN
        tristate "PWM fan"
        depends on (PWM && OF) || COMPILE_TEST
+       depends on THERMAL || THERMAL=n
        help
          If you say yes here you get support for fans connected to PWM lines.
          The driver uses the generic PWM interface, thus it will work on a
index 6c941472e707a51b2dfb5f6889aea07bad4ff5b7..b4a40f17e2aa5211f767323f736cab872c16528d 100644 (file)
@@ -120,6 +120,7 @@ obj-$(CONFIG_SENSORS_MENF21BMC_HWMON) += menf21bmc_hwmon.o
 obj-$(CONFIG_SENSORS_NCT6683)  += nct6683.o
 obj-$(CONFIG_SENSORS_NCT6775)  += nct6775.o
 obj-$(CONFIG_SENSORS_NCT7802)  += nct7802.o
+obj-$(CONFIG_SENSORS_NCT7904)  += nct7904.o
 obj-$(CONFIG_SENSORS_NTC_THERMISTOR)   += ntc_thermistor.o
 obj-$(CONFIG_SENSORS_PC87360)  += pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)  += pc87427.o
index 5b7fec824f10a0eafc8109d7e9632789d6017e69..ed303ba3a59393533a1f0d06b95abc53a5febcdd 100644 (file)
@@ -397,14 +397,13 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
                        struct device_attribute *devattr, char *buf) = {
                        show_label, show_crit_alarm, show_temp, show_tjmax,
                        show_ttarget };
-       static const char *const names[TOTAL_ATTRS] = {
-                                       "temp%d_label", "temp%d_crit_alarm",
-                                       "temp%d_input", "temp%d_crit",
-                                       "temp%d_max" };
+       static const char *const suffixes[TOTAL_ATTRS] = {
+               "label", "crit_alarm", "input", "crit", "max"
+       };
 
        for (i = 0; i < tdata->attr_size; i++) {
-               snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i],
-                       attr_no);
+               snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH,
+                        "temp%d_%s", attr_no, suffixes[i]);
                sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr);
                tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i];
                tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO;
index 36abf814b8c77c57c0728beda6afac69b92cc802..a3dae6d0082a0d08e4183f63e27b79ae5510b863 100644 (file)
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
+#include <linux/thermal.h>
 
 struct gpio_fan_data {
        struct platform_device  *pdev;
        struct device           *hwmon_dev;
+       /* Cooling device if any */
+       struct thermal_cooling_device *cdev;
        struct mutex            lock; /* lock GPIOs operations. */
        int                     num_ctrl;
        unsigned                *ctrl;
@@ -387,6 +390,53 @@ static int fan_ctrl_init(struct gpio_fan_data *fan_data,
        return 0;
 }
 
+static int gpio_fan_get_max_state(struct thermal_cooling_device *cdev,
+                                 unsigned long *state)
+{
+       struct gpio_fan_data *fan_data = cdev->devdata;
+
+       if (!fan_data)
+               return -EINVAL;
+
+       *state = fan_data->num_speed - 1;
+       return 0;
+}
+
+static int gpio_fan_get_cur_state(struct thermal_cooling_device *cdev,
+                                 unsigned long *state)
+{
+       struct gpio_fan_data *fan_data = cdev->devdata;
+       int r;
+
+       if (!fan_data)
+               return -EINVAL;
+
+       r = get_fan_speed_index(fan_data);
+       if (r < 0)
+               return r;
+
+       *state = r;
+       return 0;
+}
+
+static int gpio_fan_set_cur_state(struct thermal_cooling_device *cdev,
+                                 unsigned long state)
+{
+       struct gpio_fan_data *fan_data = cdev->devdata;
+
+       if (!fan_data)
+               return -EINVAL;
+
+       set_fan_speed(fan_data, state);
+       return 0;
+}
+
+static const struct thermal_cooling_device_ops gpio_fan_cool_ops = {
+       .get_max_state = gpio_fan_get_max_state,
+       .get_cur_state = gpio_fan_get_cur_state,
+       .set_cur_state = gpio_fan_set_cur_state,
+};
+
 #ifdef CONFIG_OF_GPIO
 /*
  * Translate OpenFirmware node properties into platform_data
@@ -404,10 +454,32 @@ static int gpio_fan_get_of_pdata(struct device *dev,
 
        node = dev->of_node;
 
+       /* Alarm GPIO if one exists */
+       if (of_gpio_named_count(node, "alarm-gpios") > 0) {
+               struct gpio_fan_alarm *alarm;
+               int val;
+               enum of_gpio_flags flags;
+
+               alarm = devm_kzalloc(dev, sizeof(struct gpio_fan_alarm),
+                                       GFP_KERNEL);
+               if (!alarm)
+                       return -ENOMEM;
+
+               val = of_get_named_gpio_flags(node, "alarm-gpios", 0, &flags);
+               if (val < 0)
+                       return val;
+               alarm->gpio = val;
+               alarm->active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+               pdata->alarm = alarm;
+       }
+
        /* Fill GPIO pin array */
        pdata->num_ctrl = of_gpio_count(node);
        if (pdata->num_ctrl <= 0) {
-               dev_err(dev, "gpios DT property empty / missing");
+               if (pdata->alarm)
+                       return 0;
+               dev_err(dev, "DT properties empty / missing");
                return -ENODEV;
        }
        ctrl = devm_kzalloc(dev, pdata->num_ctrl * sizeof(unsigned),
@@ -460,26 +532,6 @@ static int gpio_fan_get_of_pdata(struct device *dev,
        }
        pdata->speed = speed;
 
-       /* Alarm GPIO if one exists */
-       if (of_gpio_named_count(node, "alarm-gpios") > 0) {
-               struct gpio_fan_alarm *alarm;
-               int val;
-               enum of_gpio_flags flags;
-
-               alarm = devm_kzalloc(dev, sizeof(struct gpio_fan_alarm),
-                                       GFP_KERNEL);
-               if (!alarm)
-                       return -ENOMEM;
-
-               val = of_get_named_gpio_flags(node, "alarm-gpios", 0, &flags);
-               if (val < 0)
-                       return val;
-               alarm->gpio = val;
-               alarm->active_low = flags & OF_GPIO_ACTIVE_LOW;
-
-               pdata->alarm = alarm;
-       }
-
        return 0;
 }
 
@@ -495,6 +547,11 @@ static int gpio_fan_probe(struct platform_device *pdev)
        struct gpio_fan_data *fan_data;
        struct gpio_fan_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
+       fan_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_fan_data),
+                               GFP_KERNEL);
+       if (!fan_data)
+               return -ENOMEM;
+
 #ifdef CONFIG_OF_GPIO
        if (!pdata) {
                pdata = devm_kzalloc(&pdev->dev,
@@ -512,11 +569,6 @@ static int gpio_fan_probe(struct platform_device *pdev)
                return -EINVAL;
 #endif /* CONFIG_OF_GPIO */
 
-       fan_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_fan_data),
-                               GFP_KERNEL);
-       if (!fan_data)
-               return -ENOMEM;
-
        fan_data->pdev = pdev;
        platform_set_drvdata(pdev, fan_data);
        mutex_init(&fan_data->lock);
@@ -544,18 +596,39 @@ static int gpio_fan_probe(struct platform_device *pdev)
                                                       gpio_fan_groups);
        if (IS_ERR(fan_data->hwmon_dev))
                return PTR_ERR(fan_data->hwmon_dev);
+#ifdef CONFIG_OF_GPIO
+       /* Optional cooling device register for Device tree platforms */
+       fan_data->cdev = thermal_of_cooling_device_register(pdev->dev.of_node,
+                                                           "gpio-fan",
+                                                           fan_data,
+                                                           &gpio_fan_cool_ops);
+#else /* CONFIG_OF_GPIO */
+       /* Optional cooling device register for non Device tree platforms */
+       fan_data->cdev = thermal_cooling_device_register("gpio-fan", fan_data,
+                                                        &gpio_fan_cool_ops);
+#endif /* CONFIG_OF_GPIO */
 
        dev_info(&pdev->dev, "GPIO fan initialized\n");
 
        return 0;
 }
 
-static void gpio_fan_shutdown(struct platform_device *pdev)
+static int gpio_fan_remove(struct platform_device *pdev)
 {
-       struct gpio_fan_data *fan_data = dev_get_drvdata(&pdev->dev);
+       struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
+
+       if (!IS_ERR(fan_data->cdev))
+               thermal_cooling_device_unregister(fan_data->cdev);
 
        if (fan_data->ctrl)
                set_fan_speed(fan_data, 0);
+
+       return 0;
+}
+
+static void gpio_fan_shutdown(struct platform_device *pdev)
+{
+       gpio_fan_remove(pdev);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -589,6 +662,7 @@ static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume);
 
 static struct platform_driver gpio_fan_driver = {
        .probe          = gpio_fan_probe,
+       .remove         = gpio_fan_remove,
        .shutdown       = gpio_fan_shutdown,
        .driver = {
                .name   = "gpio-fan",
index 030e7ff589be9558033ad8283537133c9c72dcf0..21b9c72f16bd7423dda3870b7e6eaf1ee047a6b5 100644 (file)
@@ -56,15 +56,10 @@ static u8 const temp_sensor_sig[]  = {0x74, 0x65, 0x6D};
 static u8 const watt_sensor_sig[]  = {0x41, 0x43};
 
 #define PEX_NUM_SENSOR_FUNCS   3
-static char const * const power_sensor_name_templates[] = {
-       "%s%d_average",
-       "%s%d_average_lowest",
-       "%s%d_average_highest"
-};
-static char const * const temp_sensor_name_templates[] = {
-       "%s%d_input",
-       "%s%d_input_lowest",
-       "%s%d_input_highest"
+static const char * const sensor_name_suffixes[] = {
+       "",
+       "_lowest",
+       "_highest"
 };
 
 static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
@@ -355,9 +350,11 @@ static int create_sensor(struct ibmpex_bmc_data *data, int type,
                return -ENOMEM;
 
        if (type == TEMP_SENSOR)
-               sprintf(n, temp_sensor_name_templates[func], "temp", counter);
+               sprintf(n, "temp%d_input%s",
+                       counter, sensor_name_suffixes[func]);
        else if (type == POWER_SENSOR)
-               sprintf(n, power_sensor_name_templates[func], "power", counter);
+               sprintf(n, "power%d_average%s",
+                       counter, sensor_name_suffixes[func]);
 
        sysfs_attr_init(&data->sensors[sensor].attr[func].dev_attr.attr);
        data->sensors[sensor].attr[func].dev_attr.attr.name = n;
index febe8175d36ced56b1894d663f3cf84f3b3f341b..4255514b2c72d917c2e2151f3d1fac405033e935 100644 (file)
 #include <linux/platform_device.h>
 #include <asm/opal.h>
 #include <linux/err.h>
+#include <asm/cputhreads.h>
+#include <asm/smp.h>
 
 #define MAX_ATTR_LEN   32
+#define MAX_LABEL_LEN  64
 
 /* Sensor suffix name from DT */
 #define DT_FAULT_ATTR_SUFFIX           "faulted"
  */
 enum sensors {
        FAN,
-       AMBIENT_TEMP,
+       TEMP,
        POWER_SUPPLY,
        POWER_INPUT,
        MAX_SENSOR_TYPE,
 };
 
+#define INVALID_INDEX (-1U)
+
 static struct sensor_group {
        const char *name;
        const char *compatible;
        struct attribute_group group;
        u32 attr_count;
+       u32 hwmon_index;
 } sensor_groups[] = {
        {"fan", "ibm,opal-sensor-cooling-fan"},
        {"temp", "ibm,opal-sensor-amb-temp"},
@@ -64,7 +70,10 @@ static struct sensor_group {
 
 struct sensor_data {
        u32 id; /* An opaque id of the firmware for each sensor */
+       u32 hwmon_index;
+       u32 opal_index;
        enum sensors type;
+       char label[MAX_LABEL_LEN];
        char name[MAX_ATTR_LEN];
        struct device_attribute dev_attr;
 };
@@ -87,7 +96,7 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr,
                return ret;
 
        /* Convert temperature to milli-degrees */
-       if (sdata->type == AMBIENT_TEMP)
+       if (sdata->type == TEMP)
                x *= 1000;
        /* Convert power to micro-watts */
        else if (sdata->type == POWER_INPUT)
@@ -96,8 +105,65 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr,
        return sprintf(buf, "%u\n", x);
 }
 
-static int get_sensor_index_attr(const char *name, u32 *index,
-                                       char *attr)
+static ssize_t show_label(struct device *dev, struct device_attribute *devattr,
+                         char *buf)
+{
+       struct sensor_data *sdata = container_of(devattr, struct sensor_data,
+                                                dev_attr);
+
+       return sprintf(buf, "%s\n", sdata->label);
+}
+
+static int __init get_logical_cpu(int hwcpu)
+{
+       int cpu;
+
+       for_each_possible_cpu(cpu)
+               if (get_hard_smp_processor_id(cpu) == hwcpu)
+                       return cpu;
+
+       return -ENOENT;
+}
+
+static void __init make_sensor_label(struct device_node *np,
+                                    struct sensor_data *sdata,
+                                    const char *label)
+{
+       u32 id;
+       size_t n;
+
+       n = snprintf(sdata->label, sizeof(sdata->label), "%s", label);
+
+       /*
+        * Core temp pretty print
+        */
+       if (!of_property_read_u32(np, "ibm,pir", &id)) {
+               int cpuid = get_logical_cpu(id);
+
+               if (cpuid >= 0)
+                       /*
+                        * The digital thermal sensors are associated
+                        * with a core. Let's print out the range of
+                        * cpu ids corresponding to the hardware
+                        * threads of the core.
+                        */
+                       n += snprintf(sdata->label + n,
+                                     sizeof(sdata->label) - n, " %d-%d",
+                                     cpuid, cpuid + threads_per_core - 1);
+               else
+                       n += snprintf(sdata->label + n,
+                                     sizeof(sdata->label) - n, " phy%d", id);
+       }
+
+       /*
+        * Membuffer pretty print
+        */
+       if (!of_property_read_u32(np, "ibm,chip-id", &id))
+               n += snprintf(sdata->label + n, sizeof(sdata->label) - n,
+                             " %d", id & 0xffff);
+}
+
+static int get_sensor_index_attr(const char *name, u32 *index, char *attr)
 {
        char *hash_pos = strchr(name, '#');
        char buf[8] = { 0 };
@@ -127,46 +193,90 @@ static int get_sensor_index_attr(const char *name, u32 *index,
        return 0;
 }
 
+static const char *convert_opal_attr_name(enum sensors type,
+                                         const char *opal_attr)
+{
+       const char *attr_name = NULL;
+
+       if (!strcmp(opal_attr, DT_FAULT_ATTR_SUFFIX)) {
+               attr_name = "fault";
+       } else if (!strcmp(opal_attr, DT_DATA_ATTR_SUFFIX)) {
+               attr_name = "input";
+       } else if (!strcmp(opal_attr, DT_THRESHOLD_ATTR_SUFFIX)) {
+               if (type == TEMP)
+                       attr_name = "max";
+               else if (type == FAN)
+                       attr_name = "min";
+       }
+
+       return attr_name;
+}
+
 /*
  * This function translates the DT node name into the 'hwmon' attribute name.
  * IBMPOWERNV device node appear like cooling-fan#2-data, amb-temp#1-thrs etc.
  * which need to be mapped as fan2_input, temp1_max respectively before
  * populating them inside hwmon device class.
  */
-static int create_hwmon_attr_name(struct device *dev, enum sensors type,
-                                        const char *node_name,
-                                        char *hwmon_attr_name)
+static const char *parse_opal_node_name(const char *node_name,
+                                       enum sensors type, u32 *index)
 {
        char attr_suffix[MAX_ATTR_LEN];
-       char *attr_name;
-       u32 index;
+       const char *attr_name;
        int err;
 
-       err = get_sensor_index_attr(node_name, &index, attr_suffix);
-       if (err) {
-               dev_err(dev, "Sensor device node name '%s' is invalid\n",
-                       node_name);
-               return err;
-       }
+       err = get_sensor_index_attr(node_name, index, attr_suffix);
+       if (err)
+               return ERR_PTR(err);
 
-       if (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX)) {
-               attr_name = "fault";
-       } else if (!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX)) {
-               attr_name = "input";
-       } else if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) {
-               if (type == AMBIENT_TEMP)
-                       attr_name = "max";
-               else if (type == FAN)
-                       attr_name = "min";
-               else
-                       return -ENOENT;
-       } else {
-               return -ENOENT;
+       attr_name = convert_opal_attr_name(type, attr_suffix);
+       if (!attr_name)
+               return ERR_PTR(-ENOENT);
+
+       return attr_name;
+}
+
+static int get_sensor_type(struct device_node *np)
+{
+       enum sensors type;
+       const char *str;
+
+       for (type = 0; type < MAX_SENSOR_TYPE; type++) {
+               if (of_device_is_compatible(np, sensor_groups[type].compatible))
+                       return type;
        }
 
-       snprintf(hwmon_attr_name, MAX_ATTR_LEN, "%s%d_%s",
-                sensor_groups[type].name, index, attr_name);
-       return 0;
+       /*
+        * Let's check if we have a newer device tree
+        */
+       if (!of_device_is_compatible(np, "ibm,opal-sensor"))
+               return MAX_SENSOR_TYPE;
+
+       if (of_property_read_string(np, "sensor-type", &str))
+               return MAX_SENSOR_TYPE;
+
+       for (type = 0; type < MAX_SENSOR_TYPE; type++)
+               if (!strcmp(str, sensor_groups[type].name))
+                       return type;
+
+       return MAX_SENSOR_TYPE;
+}
+
+static u32 get_sensor_hwmon_index(struct sensor_data *sdata,
+                                 struct sensor_data *sdata_table, int count)
+{
+       int i;
+
+       /*
+        * We don't use the OPAL index on newer device trees
+        */
+       if (sdata->opal_index != INVALID_INDEX) {
+               for (i = 0; i < count; i++)
+                       if (sdata_table[i].opal_index == sdata->opal_index &&
+                           sdata_table[i].type == sdata->type)
+                               return sdata_table[i].hwmon_index;
+       }
+       return ++sensor_groups[sdata->type].hwmon_index;
 }
 
 static int populate_attr_groups(struct platform_device *pdev)
@@ -178,15 +288,22 @@ static int populate_attr_groups(struct platform_device *pdev)
 
        opal = of_find_node_by_path("/ibm,opal/sensors");
        for_each_child_of_node(opal, np) {
+               const char *label;
+
                if (np->name == NULL)
                        continue;
 
-               for (type = 0; type < MAX_SENSOR_TYPE; type++)
-                       if (of_device_is_compatible(np,
-                                       sensor_groups[type].compatible)) {
-                               sensor_groups[type].attr_count++;
-                               break;
-                       }
+               type = get_sensor_type(np);
+               if (type == MAX_SENSOR_TYPE)
+                       continue;
+
+               sensor_groups[type].attr_count++;
+
+               /*
+                * add a new attribute for labels
+                */
+               if (!of_property_read_string(np, "label", &label))
+                       sensor_groups[type].attr_count++;
        }
 
        of_node_put(opal);
@@ -207,6 +324,21 @@ static int populate_attr_groups(struct platform_device *pdev)
        return 0;
 }
 
+static void create_hwmon_attr(struct sensor_data *sdata, const char *attr_name,
+                             ssize_t (*show)(struct device *dev,
+                                             struct device_attribute *attr,
+                                             char *buf))
+{
+       snprintf(sdata->name, MAX_ATTR_LEN, "%s%d_%s",
+                sensor_groups[sdata->type].name, sdata->hwmon_index,
+                attr_name);
+
+       sysfs_attr_init(&sdata->dev_attr.attr);
+       sdata->dev_attr.attr.name = sdata->name;
+       sdata->dev_attr.attr.mode = S_IRUGO;
+       sdata->dev_attr.show = show;
+}
+
 /*
  * Iterate through the device tree for each child of 'sensors' node, create
  * a sysfs attribute file, the file is named by translating the DT node name
@@ -233,18 +365,23 @@ static int create_device_attrs(struct platform_device *pdev)
        }
 
        for_each_child_of_node(opal, np) {
+               const char *attr_name;
+               u32 opal_index;
+               const char *label;
+
                if (np->name == NULL)
                        continue;
 
-               for (type = 0; type < MAX_SENSOR_TYPE; type++)
-                       if (of_device_is_compatible(np,
-                                       sensor_groups[type].compatible))
-                               break;
-
+               type = get_sensor_type(np);
                if (type == MAX_SENSOR_TYPE)
                        continue;
 
-               if (of_property_read_u32(np, "sensor-id", &sensor_id)) {
+               /*
+                * Newer device trees use a "sensor-data" property
+                * name for input.
+                */
+               if (of_property_read_u32(np, "sensor-id", &sensor_id) &&
+                   of_property_read_u32(np, "sensor-data", &sensor_id)) {
                        dev_info(&pdev->dev,
                                 "'sensor-id' missing in the node '%s'\n",
                                 np->name);
@@ -253,18 +390,46 @@ static int create_device_attrs(struct platform_device *pdev)
 
                sdata[count].id = sensor_id;
                sdata[count].type = type;
-               err = create_hwmon_attr_name(&pdev->dev, type, np->name,
-                                            sdata[count].name);
-               if (err)
-                       goto exit_put_node;
 
-               sysfs_attr_init(&sdata[count].dev_attr.attr);
-               sdata[count].dev_attr.attr.name = sdata[count].name;
-               sdata[count].dev_attr.attr.mode = S_IRUGO;
-               sdata[count].dev_attr.show = show_sensor;
+               /*
+                * If we can not parse the node name, it means we are
+                * running on a newer device tree. We can just forget
+                * about the OPAL index and use a defaut value for the
+                * hwmon attribute name
+                */
+               attr_name = parse_opal_node_name(np->name, type, &opal_index);
+               if (IS_ERR(attr_name)) {
+                       attr_name = "input";
+                       opal_index = INVALID_INDEX;
+               }
+
+               sdata[count].opal_index = opal_index;
+               sdata[count].hwmon_index =
+                       get_sensor_hwmon_index(&sdata[count], sdata, count);
+
+               create_hwmon_attr(&sdata[count], attr_name, show_sensor);
 
                pgroups[type]->attrs[sensor_groups[type].attr_count++] =
                                &sdata[count++].dev_attr.attr;
+
+               if (!of_property_read_string(np, "label", &label)) {
+                       /*
+                        * For the label attribute, we can reuse the
+                        * "properties" of the previous "input"
+                        * attribute. They are related to the same
+                        * sensor.
+                        */
+                       sdata[count].type = type;
+                       sdata[count].opal_index = sdata[count - 1].opal_index;
+                       sdata[count].hwmon_index = sdata[count - 1].hwmon_index;
+
+                       make_sensor_label(np, &sdata[count], label);
+
+                       create_hwmon_attr(&sdata[count], "label", show_label);
+
+                       pgroups[type]->attrs[sensor_groups[type].attr_count++] =
+                               &sdata[count++].dev_attr.attr;
+               }
        }
 
 exit_put_node:
index 409116c52cc57f650c8939fc6c7b7c50d3a1daea..d0ee556e8ce00447d9d16d8c3adb81de4160bfae 100644 (file)
@@ -11,6 +11,7 @@
  *  similar parts.  The other devices are supported by different drivers.
  *
  *  Supports: IT8603E  Super I/O chip w/LPC interface
+ *            IT8620E  Super I/O chip w/LPC interface
  *            IT8623E  Super I/O chip w/LPC interface
  *            IT8705F  Super I/O chip w/LPC interface
  *            IT8712F  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
+ *            IT8781F  Super I/O chip w/LPC interface
  *            IT8782F  Super I/O chip w/LPC interface
  *            IT8783E/F Super I/O chip w/LPC interface
+ *            IT8786E  Super I/O chip w/LPC interface
+ *            IT8790E  Super I/O chip w/LPC interface
  *            Sis950   A clone of the IT8705F
  *
  *  Copyright (C) 2001 Chris Gauthron
@@ -66,7 +70,7 @@
 #define DRVNAME "it87"
 
 enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8771,
-            it8772, it8782, it8783, it8603 };
+            it8772, it8781, it8782, it8783, it8786, it8790, it8603, it8620 };
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
@@ -146,15 +150,20 @@ static inline void superio_exit(void)
 #define IT8728F_DEVID 0x8728
 #define IT8771E_DEVID 0x8771
 #define IT8772E_DEVID 0x8772
+#define IT8781F_DEVID 0x8781
 #define IT8782F_DEVID 0x8782
 #define IT8783E_DEVID 0x8783
+#define IT8786E_DEVID 0x8786
+#define IT8790E_DEVID 0x8790
 #define IT8603E_DEVID 0x8603
+#define IT8620E_DEVID 0x8620
 #define IT8623E_DEVID 0x8623
 #define IT87_ACT_REG  0x30
 #define IT87_BASE_REG 0x60
 
 /* Logical device 7 registers (IT8712F and later) */
 #define IT87_SIO_GPIO1_REG     0x25
+#define IT87_SIO_GPIO2_REG     0x26
 #define IT87_SIO_GPIO3_REG     0x27
 #define IT87_SIO_GPIO5_REG     0x29
 #define IT87_SIO_PINX1_REG     0x2a    /* Pin selection */
@@ -207,11 +216,11 @@ static bool fix_pwm_polarity;
 
 /* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */
 
-static const u8 IT87_REG_FAN[]         = { 0x0d, 0x0e, 0x0f, 0x80, 0x82 };
-static const u8 IT87_REG_FAN_MIN[]     = { 0x10, 0x11, 0x12, 0x84, 0x86 };
-static const u8 IT87_REG_FANX[]                = { 0x18, 0x19, 0x1a, 0x81, 0x83 };
-static const u8 IT87_REG_FANX_MIN[]    = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
-static const u8 IT87_REG_TEMP_OFFSET[] = { 0x56, 0x57, 0x59 };
+static const u8 IT87_REG_FAN[]         = { 0x0d, 0x0e, 0x0f, 0x80, 0x82, 0x4c };
+static const u8 IT87_REG_FAN_MIN[]     = { 0x10, 0x11, 0x12, 0x84, 0x86, 0x4e };
+static const u8 IT87_REG_FANX[]        = { 0x18, 0x19, 0x1a, 0x81, 0x83, 0x4d };
+static const u8 IT87_REG_FANX_MIN[]    = { 0x1b, 0x1c, 0x1d, 0x85, 0x87, 0x4f };
+static const u8 IT87_REG_TEMP_OFFSET[] = { 0x56, 0x57, 0x59 };
 
 #define IT87_REG_FAN_MAIN_CTRL 0x13
 #define IT87_REG_FAN_CTL       0x14
@@ -238,6 +247,7 @@ static const u8 IT87_REG_TEMP_OFFSET[]      = { 0x56, 0x57, 0x59 };
 
 struct it87_devices {
        const char *name;
+       const char * const suffix;
        u16 features;
        u8 peci_mask;
        u8 old_peci_mask;
@@ -250,79 +260,131 @@ struct it87_devices {
 #define FEAT_TEMP_OFFSET       (1 << 4)
 #define FEAT_TEMP_PECI         (1 << 5)
 #define FEAT_TEMP_OLD_PECI     (1 << 6)
+#define FEAT_FAN16_CONFIG      (1 << 7)        /* Need to enable 16-bit fans */
+#define FEAT_FIVE_FANS         (1 << 8)        /* Supports five fans */
+#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 */
 
 static const struct it87_devices it87_devices[] = {
        [it87] = {
                .name = "it87",
+               .suffix = "F",
                .features = FEAT_OLD_AUTOPWM,   /* may need to overwrite */
        },
        [it8712] = {
                .name = "it8712",
-               .features = FEAT_OLD_AUTOPWM,   /* may need to overwrite */
+               .suffix = "F",
+               .features = FEAT_OLD_AUTOPWM | FEAT_VID,
+                                               /* may need to overwrite */
        },
        [it8716] = {
                .name = "it8716",
-               .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET,
+               .suffix = "F",
+               .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
+                 | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS,
        },
        [it8718] = {
                .name = "it8718",
-               .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
-                 | FEAT_TEMP_OLD_PECI,
+               .suffix = "F",
+               .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
+                 | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS,
                .old_peci_mask = 0x4,
        },
        [it8720] = {
                .name = "it8720",
-               .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
-                 | FEAT_TEMP_OLD_PECI,
+               .suffix = "F",
+               .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
+                 | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS,
                .old_peci_mask = 0x4,
        },
        [it8721] = {
                .name = "it8721",
+               .suffix = "F",
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
-                 | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI,
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
+                 | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_IN7_INTERNAL,
                .peci_mask = 0x05,
                .old_peci_mask = 0x02,  /* Actually reports PCH */
        },
        [it8728] = {
                .name = "it8728",
+               .suffix = "F",
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
-                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_FIVE_FANS
+                 | FEAT_IN7_INTERNAL,
                .peci_mask = 0x07,
        },
        [it8771] = {
                .name = "it8771",
+               .suffix = "E",
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
-                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
-                                       /* PECI: guesswork */
-                                       /* 12mV ADC (OHM) */
-                                       /* 16 bit fans (OHM) */
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL,
+                               /* PECI: guesswork */
+                               /* 12mV ADC (OHM) */
+                               /* 16 bit fans (OHM) */
+                               /* three fans, always 16 bit (guesswork) */
                .peci_mask = 0x07,
        },
        [it8772] = {
                .name = "it8772",
+               .suffix = "E",
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
-                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
-                                       /* PECI (coreboot) */
-                                       /* 12mV ADC (HWSensors4, OHM) */
-                                       /* 16 bit fans (HWSensors4, OHM) */
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL,
+                               /* PECI (coreboot) */
+                               /* 12mV ADC (HWSensors4, OHM) */
+                               /* 16 bit fans (HWSensors4, OHM) */
+                               /* three fans, always 16 bit (datasheet) */
                .peci_mask = 0x07,
        },
+       [it8781] = {
+               .name = "it8781",
+               .suffix = "F",
+               .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
+                 | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG,
+               .old_peci_mask = 0x4,
+       },
        [it8782] = {
                .name = "it8782",
+               .suffix = "F",
                .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
-                 | FEAT_TEMP_OLD_PECI,
+                 | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG,
                .old_peci_mask = 0x4,
        },
        [it8783] = {
                .name = "it8783",
+               .suffix = "E/F",
                .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
-                 | FEAT_TEMP_OLD_PECI,
+                 | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG,
                .old_peci_mask = 0x4,
        },
+       [it8786] = {
+               .name = "it8786",
+               .suffix = "E",
+               .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL,
+               .peci_mask = 0x07,
+       },
+       [it8790] = {
+               .name = "it8790",
+               .suffix = "E",
+               .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL,
+               .peci_mask = 0x07,
+       },
        [it8603] = {
                .name = "it8603",
+               .suffix = "E",
                .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
-                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL,
+               .peci_mask = 0x07,
+       },
+       [it8620] = {
+               .name = "it8620",
+               .suffix = "E",
+               .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS
+                 | FEAT_IN7_INTERNAL,
                .peci_mask = 0x07,
        },
 };
@@ -337,6 +399,12 @@ static const struct it87_devices it87_devices[] = {
 #define has_temp_old_peci(data, nr) \
                                (((data)->features & FEAT_TEMP_OLD_PECI) && \
                                 ((data)->old_peci_mask & (1 << nr)))
+#define has_fan16_config(data) ((data)->features & FEAT_FAN16_CONFIG)
+#define has_five_fans(data)    ((data)->features & (FEAT_FIVE_FANS | \
+                                                    FEAT_SIX_FANS))
+#define has_vid(data)          ((data)->features & FEAT_VID)
+#define has_in7_internal(data) ((data)->features & FEAT_IN7_INTERNAL)
+#define has_six_fans(data)     ((data)->features & FEAT_SIX_FANS)
 
 struct it87_sio_data {
        enum chips type;
@@ -373,7 +441,7 @@ struct it87_data {
        u16 in_scaled;          /* Internal voltage sensors are scaled */
        u8 in[10][3];           /* [nr][0]=in, [1]=min, [2]=max */
        u8 has_fan;             /* Bitfield, fans enabled */
-       u16 fan[5][2];          /* Register values, [nr][0]=fan, [1]=min */
+       u16 fan[6][2];          /* Register values, [nr][0]=fan, [1]=min */
        u8 has_temp;            /* Bitfield, temp sensors enabled */
        s8 temp[3][4];          /* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */
        u8 sensor;              /* Register value (IT87_REG_TEMP_ENABLE) */
@@ -475,15 +543,25 @@ static int DIV_TO_REG(int val)
 }
 #define DIV_FROM_REG(val) (1 << (val))
 
+/*
+ * PWM base frequencies. The frequency has to be divided by either 128 or 256,
+ * depending on the chip type, to calculate the actual PWM frequency.
+ *
+ * Some of the chip datasheets suggest a base frequency of 51 kHz instead
+ * of 750 kHz for the slowest base frequency, resulting in a PWM frequency
+ * of 200 Hz. Sometimes both PWM frequency select registers are affected,
+ * sometimes just one. It is unknown if this is a datasheet error or real,
+ * so this is ignored for now.
+ */
 static const unsigned int pwm_freq[8] = {
-       48000000 / 128,
-       24000000 / 128,
-       12000000 / 128,
-       8000000 / 128,
-       6000000 / 128,
-       3000000 / 128,
-       1500000 / 128,
-       750000 / 128,
+       48000000,
+       24000000,
+       12000000,
+       8000000,
+       6000000,
+       3000000,
+       1500000,
+       750000,
 };
 
 static int it87_probe(struct platform_device *pdev);
@@ -801,8 +879,11 @@ static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr,
 {
        struct it87_data *data = it87_update_device(dev);
        int index = (data->fan_ctl >> 4) & 0x07;
+       unsigned int freq;
 
-       return sprintf(buf, "%u\n", pwm_freq[index]);
+       freq = pwm_freq[index] / (has_newer_autopwm(data) ? 256 : 128);
+
+       return sprintf(buf, "%u\n", freq);
 }
 
 static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
@@ -1024,6 +1105,9 @@ static ssize_t set_pwm_freq(struct device *dev,
        if (kstrtoul(buf, 10, &val) < 0)
                return -EINVAL;
 
+       val = clamp_val(val, 0, 1000000);
+       val *= has_newer_autopwm(data) ? 256 : 128;
+
        /* Search for the nearest available frequency */
        for (i = 0; i < 7; i++) {
                if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2)
@@ -1196,6 +1280,10 @@ static SENSOR_DEVICE_ATTR_2(fan5_input, S_IRUGO, show_fan, NULL, 4, 0);
 static SENSOR_DEVICE_ATTR_2(fan5_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
                            4, 1);
 
+static SENSOR_DEVICE_ATTR_2(fan6_input, S_IRUGO, show_fan, NULL, 5, 0);
+static SENSOR_DEVICE_ATTR_2(fan6_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
+                           5, 1);
+
 static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
                          show_pwm_enable, set_pwm_enable, 0);
 static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
@@ -1326,6 +1414,7 @@ static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 1);
 static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 2);
 static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 3);
 static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 7);
 static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 16);
 static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17);
 static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18);
@@ -1376,6 +1465,7 @@ static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO, show_beep, set_beep, 0);
 static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO, show_beep, set_beep, 0);
 static SENSOR_DEVICE_ATTR(fan4_beep, S_IRUGO, show_beep, set_beep, 0);
 static SENSOR_DEVICE_ATTR(fan5_beep, S_IRUGO, show_beep, set_beep, 0);
+static SENSOR_DEVICE_ATTR(fan6_beep, S_IRUGO, show_beep, set_beep, 0);
 static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
                          show_beep, set_beep, 2);
 static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO, show_beep, NULL, 2);
@@ -1579,7 +1669,7 @@ static struct attribute *it87_attributes_temp_beep[] = {
        &sensor_dev_attr_temp3_beep.dev_attr.attr,
 };
 
-static struct attribute *it87_attributes_fan[5][3+1] = { {
+static struct attribute *it87_attributes_fan[6][3+1] = { {
        &sensor_dev_attr_fan1_input.dev_attr.attr,
        &sensor_dev_attr_fan1_min.dev_attr.attr,
        &sensor_dev_attr_fan1_alarm.dev_attr.attr,
@@ -1604,14 +1694,20 @@ static struct attribute *it87_attributes_fan[5][3+1] = { {
        &sensor_dev_attr_fan5_min.dev_attr.attr,
        &sensor_dev_attr_fan5_alarm.dev_attr.attr,
        NULL
+}, {
+       &sensor_dev_attr_fan6_input.dev_attr.attr,
+       &sensor_dev_attr_fan6_min.dev_attr.attr,
+       &sensor_dev_attr_fan6_alarm.dev_attr.attr,
+       NULL
 } };
 
-static const struct attribute_group it87_group_fan[5] = {
+static const struct attribute_group it87_group_fan[6] = {
        { .attrs = it87_attributes_fan[0] },
        { .attrs = it87_attributes_fan[1] },
        { .attrs = it87_attributes_fan[2] },
        { .attrs = it87_attributes_fan[3] },
        { .attrs = it87_attributes_fan[4] },
+       { .attrs = it87_attributes_fan[5] },
 };
 
 static const struct attribute *it87_attributes_fan_div[] = {
@@ -1693,6 +1789,7 @@ static struct attribute *it87_attributes_fan_beep[] = {
        &sensor_dev_attr_fan3_beep.dev_attr.attr,
        &sensor_dev_attr_fan4_beep.dev_attr.attr,
        &sensor_dev_attr_fan5_beep.dev_attr.attr,
+       &sensor_dev_attr_fan6_beep.dev_attr.attr,
 };
 
 static struct attribute *it87_attributes_vid[] = {
@@ -1724,6 +1821,7 @@ static int __init it87_find(unsigned short *address,
        int err;
        u16 chip_type;
        const char *board_vendor, *board_name;
+       const struct it87_devices *config;
 
        err = superio_enter();
        if (err)
@@ -1761,16 +1859,28 @@ static int __init it87_find(unsigned short *address,
        case IT8772E_DEVID:
                sio_data->type = it8772;
                break;
+       case IT8781F_DEVID:
+               sio_data->type = it8781;
+               break;
        case IT8782F_DEVID:
                sio_data->type = it8782;
                break;
        case IT8783E_DEVID:
                sio_data->type = it8783;
                break;
+       case IT8786E_DEVID:
+               sio_data->type = it8786;
+               break;
+       case IT8790E_DEVID:
+               sio_data->type = it8790;
+               break;
        case IT8603E_DEVID:
        case IT8623E_DEVID:
                sio_data->type = it8603;
                break;
+       case IT8620E_DEVID:
+               sio_data->type = it8620;
+               break;
        case 0xffff:    /* No device at all */
                goto exit;
        default:
@@ -1792,30 +1902,34 @@ static int __init it87_find(unsigned short *address,
 
        err = 0;
        sio_data->revision = superio_inb(DEVREV) & 0x0f;
-       pr_info("Found IT%04x%c chip at 0x%x, revision %d\n", chip_type,
-               chip_type == 0x8771 || chip_type == 0x8772 ||
-               chip_type == 0x8603 ? 'E' : 'F', *address,
-               sio_data->revision);
+       pr_info("Found IT%04x%s chip at 0x%x, revision %d\n", chip_type,
+               it87_devices[sio_data->type].suffix,
+               *address, sio_data->revision);
+
+       config = &it87_devices[sio_data->type];
+
+       /* in7 (VSB or VCCH5V) is always internal on some chips */
+       if (has_in7_internal(config))
+               sio_data->internal |= (1 << 1);
 
        /* in8 (Vbat) is always internal */
-       sio_data->internal = (1 << 2);
+       sio_data->internal |= (1 << 2);
+
        /* Only the IT8603E has in9 */
        if (sio_data->type != it8603)
                sio_data->skip_in |= (1 << 9);
 
-       /* Read GPIO config and VID value from LDN 7 (GPIO) */
-       if (sio_data->type == it87) {
-               /* The IT8705F doesn't have VID pins at all */
+       if (!has_vid(config))
                sio_data->skip_vid = 1;
 
+       /* Read GPIO config and VID value from LDN 7 (GPIO) */
+       if (sio_data->type == it87) {
                /* The IT8705F has a different LD number for GPIO */
                superio_select(5);
                sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
        } else if (sio_data->type == it8783) {
                int reg25, reg27, reg2a, reg2c, regef;
 
-               sio_data->skip_vid = 1; /* No VID */
-
                superio_select(GPIO);
 
                reg25 = superio_inb(IT87_SIO_GPIO1_REG);
@@ -1881,7 +1995,6 @@ static int __init it87_find(unsigned short *address,
        } else if (sio_data->type == it8603) {
                int reg27, reg29;
 
-               sio_data->skip_vid = 1; /* No VID */
                superio_select(GPIO);
 
                reg27 = superio_inb(IT87_SIO_GPIO3_REG);
@@ -1902,13 +2015,35 @@ static int __init it87_find(unsigned short *address,
                sio_data->skip_in |= (1 << 5); /* No VIN5 */
                sio_data->skip_in |= (1 << 6); /* No VIN6 */
 
-               /* no fan4 */
-               sio_data->skip_pwm |= (1 << 3);
-               sio_data->skip_fan |= (1 << 3);
-
-               sio_data->internal |= (1 << 1); /* in7 is VSB */
                sio_data->internal |= (1 << 3); /* in9 is AVCC */
 
+               sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
+       } else if (sio_data->type == it8620) {
+               int reg;
+
+               superio_select(GPIO);
+
+               /* Check for fan4, fan5 */
+               reg = superio_inb(IT87_SIO_GPIO2_REG);
+               if (!(reg & (1 << 5)))
+                       sio_data->skip_fan |= (1 << 3);
+               if (!(reg & (1 << 4)))
+                       sio_data->skip_fan |= (1 << 4);
+
+               /* Check for pwm3, fan3 */
+               reg = superio_inb(IT87_SIO_GPIO3_REG);
+               if (reg & (1 << 6))
+                       sio_data->skip_pwm |= (1 << 2);
+               if (reg & (1 << 7))
+                       sio_data->skip_fan |= (1 << 2);
+
+               /* Check for pwm2, fan2 */
+               reg = superio_inb(IT87_SIO_GPIO5_REG);
+               if (reg & (1 << 1))
+                       sio_data->skip_pwm |= (1 << 1);
+               if (reg & (1 << 2))
+                       sio_data->skip_fan |= (1 << 1);
+
                sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
        } else {
                int reg;
@@ -1917,15 +2052,7 @@ static int __init it87_find(unsigned short *address,
                superio_select(GPIO);
 
                reg = superio_inb(IT87_SIO_GPIO3_REG);
-               if (sio_data->type == it8721 || sio_data->type == it8728 ||
-                   sio_data->type == it8771 || sio_data->type == it8772 ||
-                   sio_data->type == it8782) {
-                       /*
-                        * IT8721F/IT8758E, and IT8782F don't have VID pins
-                        * at all, not sure about the IT8728F and compatibles.
-                        */
-                       sio_data->skip_vid = 1;
-               } else {
+               if (!sio_data->skip_vid) {
                        /* We need at least 4 VID pins */
                        if (reg & 0x0f) {
                                pr_info("VID is disabled (pins used for GPIO)\n");
@@ -1975,10 +2102,7 @@ static int __init it87_find(unsigned short *address,
                }
                if (reg & (1 << 0))
                        sio_data->internal |= (1 << 0);
-               if ((reg & (1 << 1)) || sio_data->type == it8721 ||
-                   sio_data->type == it8728 ||
-                   sio_data->type == it8771 ||
-                   sio_data->type == it8772)
+               if (reg & (1 << 1))
                        sio_data->internal |= (1 << 1);
 
                /*
@@ -2050,7 +2174,7 @@ static void it87_remove_files(struct device *dev)
                        sysfs_remove_file(&dev->kobj,
                                          it87_attributes_temp_beep[i]);
        }
-       for (i = 0; i < 5; i++) {
+       for (i = 0; i < 6; i++) {
                if (!(data->has_fan & (1 << i)))
                        continue;
                sysfs_remove_group(&dev->kobj, &it87_group_fan[i]);
@@ -2062,7 +2186,7 @@ static void it87_remove_files(struct device *dev)
                                          it87_attributes_fan_div[i]);
        }
        for (i = 0; i < 3; i++) {
-               if (sio_data->skip_pwm & (1 << 0))
+               if (sio_data->skip_pwm & (1 << i))
                        continue;
                sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]);
                if (has_old_autopwm(data))
@@ -2112,13 +2236,14 @@ static int it87_probe(struct platform_device *pdev)
        case it87:
                if (sio_data->revision >= 0x03) {
                        data->features &= ~FEAT_OLD_AUTOPWM;
-                       data->features |= FEAT_16BIT_FANS;
+                       data->features |= FEAT_FAN16_CONFIG | FEAT_16BIT_FANS;
                }
                break;
        case it8712:
                if (sio_data->revision >= 0x08) {
                        data->features &= ~FEAT_OLD_AUTOPWM;
-                       data->features |= FEAT_16BIT_FANS;
+                       data->features |= FEAT_FAN16_CONFIG | FEAT_16BIT_FANS |
+                                         FEAT_FIVE_FANS;
                }
                break;
        default:
@@ -2147,7 +2272,8 @@ static int it87_probe(struct platform_device *pdev)
                        data->in_scaled |= (1 << 8);    /* in8 is Vbat */
                if (sio_data->internal & (1 << 3))
                        data->in_scaled |= (1 << 9);    /* in9 is AVCC */
-       } else if (sio_data->type == it8782 || sio_data->type == it8783) {
+       } else if (sio_data->type == it8781 || sio_data->type == it8782 ||
+                  sio_data->type == it8783) {
                if (sio_data->internal & (1 << 0))
                        data->in_scaled |= (1 << 3);    /* in3 is VCC5V */
                if (sio_data->internal & (1 << 1))
@@ -2205,7 +2331,7 @@ static int it87_probe(struct platform_device *pdev)
 
        /* Do not create fan files for disabled fans */
        fan_beep_need_rw = 1;
-       for (i = 0; i < 5; i++) {
+       for (i = 0; i < 6; i++) {
                if (!(data->has_fan & (1 << i)))
                        continue;
                err = sysfs_create_group(&dev->kobj, &it87_group_fan[i]);
@@ -2450,24 +2576,26 @@ static void it87_init_device(struct platform_device *pdev)
        }
        data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
 
-       /* Set tachometers to 16-bit mode if needed, IT8603E (and IT8728F?)
-        * has it by default */
-       if (has_16bit_fans(data) && data->type != it8603) {
-               tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
+       tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
+
+       /* Set tachometers to 16-bit mode if needed */
+       if (has_fan16_config(data)) {
                if (~tmp & 0x07 & data->has_fan) {
                        dev_dbg(&pdev->dev,
                                "Setting fan1-3 to 16-bit mode\n");
                        it87_write_value(data, IT87_REG_FAN_16BIT,
                                         tmp | 0x07);
                }
-               /* IT8705F, IT8782F, and IT8783E/F only support three fans. */
-               if (data->type != it87 && data->type != it8782 &&
-                   data->type != it8783) {
-                       if (tmp & (1 << 4))
-                               data->has_fan |= (1 << 3); /* fan4 enabled */
-                       if (tmp & (1 << 5))
-                               data->has_fan |= (1 << 4); /* fan5 enabled */
-               }
+       }
+
+       /* Check for additional fans */
+       if (has_five_fans(data)) {
+               if (tmp & (1 << 4))
+                       data->has_fan |= (1 << 3); /* fan4 enabled */
+               if (tmp & (1 << 5))
+                       data->has_fan |= (1 << 4); /* fan5 enabled */
+               if (has_six_fans(data) && (tmp & (1 << 2)))
+                       data->has_fan |= (1 << 5); /* fan6 enabled */
        }
 
        /* Fan input pins may be used for alternative functions */
@@ -2535,7 +2663,7 @@ static struct it87_data *it87_update_device(struct device *dev)
                if (data->type == it8603)
                        data->in[9][0] = it87_read_value(data, 0x2f);
 
-               for (i = 0; i < 5; i++) {
+               for (i = 0; i < 6; i++) {
                        /* Skip disabled fans */
                        if (!(data->has_fan & (1 << i)))
                                continue;
index 996bdfd5cf25f93679857407951253d1f1e5b5ca..9887d3224a865e9aa0de33e8d38894600cc0be3b 100644 (file)
@@ -87,11 +87,14 @@ static const unsigned short normal_i2c[] = {
 #define AT30TSE004_DEVID_MASK  0xffff
 
 /* IDT */
-#define TS3000B3_DEVID         0x2903  /* Also matches TSE2002B3 */
-#define TS3000B3_DEVID_MASK    0xffff
+#define TSE2004_DEVID          0x2200
+#define TSE2004_DEVID_MASK     0xff00
 
-#define TS3000GB2_DEVID                0x2912  /* Also matches TSE2002GB2 */
-#define TS3000GB2_DEVID_MASK   0xffff
+#define TS3000_DEVID           0x2900  /* Also matches TSE2002 */
+#define TS3000_DEVID_MASK      0xff00
+
+#define TS3001_DEVID           0x3000
+#define TS3001_DEVID_MASK      0xff00
 
 /* Maxim */
 #define MAX6604_DEVID          0x3e00
@@ -152,8 +155,9 @@ static struct jc42_chips jc42_chips[] = {
        { ADT_MANID, ADT7408_DEVID, ADT7408_DEVID_MASK },
        { ATMEL_MANID, AT30TS00_DEVID, AT30TS00_DEVID_MASK },
        { ATMEL_MANID2, AT30TSE004_DEVID, AT30TSE004_DEVID_MASK },
-       { IDT_MANID, TS3000B3_DEVID, TS3000B3_DEVID_MASK },
-       { IDT_MANID, TS3000GB2_DEVID, TS3000GB2_DEVID_MASK },
+       { IDT_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },
+       { IDT_MANID, TS3000_DEVID, TS3000_DEVID_MASK },
+       { IDT_MANID, TS3001_DEVID, TS3001_DEVID_MASK },
        { MAX_MANID, MAX6604_DEVID, MAX6604_DEVID_MASK },
        { MCP_MANID, MCP9804_DEVID, MCP9804_DEVID_MASK },
        { MCP_MANID, MCP98242_DEVID, MCP98242_DEVID_MASK },
index 1be41177b620f5179f254f0e8936a74bfb79fe94..4fcb481032992f475e8d196dc3a9dbcfa2407b30 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 #include <linux/io.h>
 #include "lm75.h"
 
@@ -880,12 +881,12 @@ struct nct6775_data {
        u16 have_temp;
        u16 have_temp_fixed;
        u16 have_in;
-#ifdef CONFIG_PM
+
        /* Remember extra register values over suspend/resume */
        u8 vbat;
        u8 fandiv1;
        u8 fandiv2;
-#endif
+       u8 sio_reg_enable;
 };
 
 struct nct6775_sio_data {
@@ -3178,6 +3179,10 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
        int sioreg = data->sioreg;
        int regval;
 
+       /* Store SIO_REG_ENABLE for use during resume */
+       superio_select(sioreg, NCT6775_LD_HWM);
+       data->sio_reg_enable = superio_inb(sioreg, SIO_REG_ENABLE);
+
        /* fan4 and fan5 share some pins with the GPIO and serial flash */
        if (data->kind == nct6775) {
                regval = superio_inb(sioreg, 0x2c);
@@ -3195,21 +3200,38 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
                pwm6pin = false;
        } else if (data->kind == nct6776) {
                bool gpok = superio_inb(sioreg, 0x27) & 0x80;
+               const char *board_vendor, *board_name;
 
-               superio_select(sioreg, NCT6775_LD_HWM);
-               regval = superio_inb(sioreg, SIO_REG_ENABLE);
+               board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
+               board_name = dmi_get_system_info(DMI_BOARD_NAME);
+
+               if (board_name && board_vendor &&
+                   !strcmp(board_vendor, "ASRock")) {
+                       /*
+                        * Auxiliary fan monitoring is not enabled on ASRock
+                        * Z77 Pro4-M if booted in UEFI Ultra-FastBoot mode.
+                        * Observed with BIOS version 2.00.
+                        */
+                       if (!strcmp(board_name, "Z77 Pro4-M")) {
+                               if ((data->sio_reg_enable & 0xe0) != 0xe0) {
+                                       data->sio_reg_enable |= 0xe0;
+                                       superio_outb(sioreg, SIO_REG_ENABLE,
+                                                    data->sio_reg_enable);
+                               }
+                       }
+               }
 
-               if (regval & 0x80)
+               if (data->sio_reg_enable & 0x80)
                        fan3pin = gpok;
                else
                        fan3pin = !(superio_inb(sioreg, 0x24) & 0x40);
 
-               if (regval & 0x40)
+               if (data->sio_reg_enable & 0x40)
                        fan4pin = gpok;
                else
                        fan4pin = superio_inb(sioreg, 0x1C) & 0x01;
 
-               if (regval & 0x20)
+               if (data->sio_reg_enable & 0x20)
                        fan5pin = gpok;
                else
                        fan5pin = superio_inb(sioreg, 0x1C) & 0x02;
@@ -3989,8 +4011,7 @@ static void nct6791_enable_io_mapping(int sioaddr)
        }
 }
 
-#ifdef CONFIG_PM
-static int nct6775_suspend(struct device *dev)
+static int __maybe_unused nct6775_suspend(struct device *dev)
 {
        struct nct6775_data *data = nct6775_update_device(dev);
 
@@ -4005,22 +4026,29 @@ static int nct6775_suspend(struct device *dev)
        return 0;
 }
 
-static int nct6775_resume(struct device *dev)
+static int __maybe_unused nct6775_resume(struct device *dev)
 {
        struct nct6775_data *data = dev_get_drvdata(dev);
+       int sioreg = data->sioreg;
        int i, j, err = 0;
+       u8 reg;
 
        mutex_lock(&data->update_lock);
        data->bank = 0xff;              /* Force initial bank selection */
 
-       if (data->kind == nct6791 || data->kind == nct6792) {
-               err = superio_enter(data->sioreg);
-               if (err)
-                       goto abort;
+       err = superio_enter(sioreg);
+       if (err)
+               goto abort;
 
-               nct6791_enable_io_mapping(data->sioreg);
-               superio_exit(data->sioreg);
-       }
+       superio_select(sioreg, NCT6775_LD_HWM);
+       reg = superio_inb(sioreg, SIO_REG_ENABLE);
+       if (reg != data->sio_reg_enable)
+               superio_outb(sioreg, SIO_REG_ENABLE, data->sio_reg_enable);
+
+       if (data->kind == nct6791 || data->kind == nct6792)
+               nct6791_enable_io_mapping(sioreg);
+
+       superio_exit(sioreg);
 
        /* Restore limits */
        for (i = 0; i < data->in_num; i++) {
@@ -4066,22 +4094,12 @@ abort:
        return err;
 }
 
-static const struct dev_pm_ops nct6775_dev_pm_ops = {
-       .suspend = nct6775_suspend,
-       .resume = nct6775_resume,
-       .freeze = nct6775_suspend,
-       .restore = nct6775_resume,
-};
-
-#define NCT6775_DEV_PM_OPS     (&nct6775_dev_pm_ops)
-#else
-#define NCT6775_DEV_PM_OPS     NULL
-#endif /* CONFIG_PM */
+static SIMPLE_DEV_PM_OPS(nct6775_dev_pm_ops, nct6775_suspend, nct6775_resume);
 
 static struct platform_driver nct6775_driver = {
        .driver = {
                .name   = DRVNAME,
-               .pm     = NCT6775_DEV_PM_OPS,
+               .pm     = &nct6775_dev_pm_ops,
        },
        .probe          = nct6775_probe,
 };
diff --git a/drivers/hwmon/nct7904.c b/drivers/hwmon/nct7904.c
new file mode 100644 (file)
index 0000000..b77b82f
--- /dev/null
@@ -0,0 +1,593 @@
+/*
+ * nct7904.c - driver for Nuvoton NCT7904D.
+ *
+ * Copyright (c) 2015 Kontron
+ * Author: Vadim V. Vlasov <vvlasov@dev.rtsoft.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/device.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+#define VENDOR_ID_REG          0x7A    /* Any bank */
+#define NUVOTON_ID             0x50
+#define CHIP_ID_REG            0x7B    /* Any bank */
+#define NCT7904_ID             0xC5
+#define DEVICE_ID_REG          0x7C    /* Any bank */
+
+#define BANK_SEL_REG           0xFF
+#define BANK_0                 0x00
+#define BANK_1                 0x01
+#define BANK_2                 0x02
+#define BANK_3                 0x03
+#define BANK_4                 0x04
+#define BANK_MAX               0x04
+
+#define FANIN_MAX              12      /* Counted from 1 */
+#define VSEN_MAX               21      /* VSEN1..14, 3VDD, VBAT, V3VSB,
+                                          LTD (not a voltage), VSEN17..19 */
+#define FANCTL_MAX             4       /* Counted from 1 */
+#define TCPU_MAX               8       /* Counted from 1 */
+#define TEMP_MAX               4       /* Counted from 1 */
+
+#define VT_ADC_CTRL0_REG       0x20    /* Bank 0 */
+#define VT_ADC_CTRL1_REG       0x21    /* Bank 0 */
+#define VT_ADC_CTRL2_REG       0x22    /* Bank 0 */
+#define FANIN_CTRL0_REG                0x24
+#define FANIN_CTRL1_REG                0x25
+#define DTS_T_CTRL0_REG                0x26
+#define DTS_T_CTRL1_REG                0x27
+#define VT_ADC_MD_REG          0x2E
+
+#define VSEN1_HV_REG           0x40    /* Bank 0; 2 regs (HV/LV) per sensor */
+#define TEMP_CH1_HV_REG                0x42    /* Bank 0; same as VSEN2_HV */
+#define LTD_HV_REG             0x62    /* Bank 0; 2 regs in VSEN range */
+#define FANIN1_HV_REG          0x80    /* Bank 0; 2 regs (HV/LV) per sensor */
+#define T_CPU1_HV_REG          0xA0    /* Bank 0; 2 regs (HV/LV) per sensor */
+
+#define PRTS_REG               0x03    /* Bank 2 */
+#define FANCTL1_FMR_REG                0x00    /* Bank 3; 1 reg per channel */
+#define FANCTL1_OUT_REG                0x10    /* Bank 3; 1 reg per channel */
+
+static const unsigned short normal_i2c[] = {
+       0x2d, 0x2e, I2C_CLIENT_END
+};
+
+struct nct7904_data {
+       struct i2c_client *client;
+       struct mutex bank_lock;
+       int bank_sel;
+       u32 fanin_mask;
+       u32 vsen_mask;
+       u32 tcpu_mask;
+       u8 fan_mode[FANCTL_MAX];
+};
+
+/* Access functions */
+static int nct7904_bank_lock(struct nct7904_data *data, unsigned bank)
+{
+       int ret;
+
+       mutex_lock(&data->bank_lock);
+       if (data->bank_sel == bank)
+               return 0;
+       ret = i2c_smbus_write_byte_data(data->client, BANK_SEL_REG, bank);
+       if (ret == 0)
+               data->bank_sel = bank;
+       else
+               data->bank_sel = -1;
+       return ret;
+}
+
+static inline void nct7904_bank_release(struct nct7904_data *data)
+{
+       mutex_unlock(&data->bank_lock);
+}
+
+/* Read 1-byte register. Returns unsigned reg or -ERRNO on error. */
+static int nct7904_read_reg(struct nct7904_data *data,
+                           unsigned bank, unsigned reg)
+{
+       struct i2c_client *client = data->client;
+       int ret;
+
+       ret = nct7904_bank_lock(data, bank);
+       if (ret == 0)
+               ret = i2c_smbus_read_byte_data(client, reg);
+
+       nct7904_bank_release(data);
+       return ret;
+}
+
+/*
+ * Read 2-byte register. Returns register in big-endian format or
+ * -ERRNO on error.
+ */
+static int nct7904_read_reg16(struct nct7904_data *data,
+                             unsigned bank, unsigned reg)
+{
+       struct i2c_client *client = data->client;
+       int ret, hi;
+
+       ret = nct7904_bank_lock(data, bank);
+       if (ret == 0) {
+               ret = i2c_smbus_read_byte_data(client, reg);
+               if (ret >= 0) {
+                       hi = ret;
+                       ret = i2c_smbus_read_byte_data(client, reg + 1);
+                       if (ret >= 0)
+                               ret |= hi << 8;
+               }
+       }
+
+       nct7904_bank_release(data);
+       return ret;
+}
+
+/* Write 1-byte register. Returns 0 or -ERRNO on error. */
+static int nct7904_write_reg(struct nct7904_data *data,
+                            unsigned bank, unsigned reg, u8 val)
+{
+       struct i2c_client *client = data->client;
+       int ret;
+
+       ret = nct7904_bank_lock(data, bank);
+       if (ret == 0)
+               ret = i2c_smbus_write_byte_data(client, reg, val);
+
+       nct7904_bank_release(data);
+       return ret;
+}
+
+/* FANIN ATTR */
+static ssize_t show_fan(struct device *dev,
+                       struct device_attribute *devattr, char *buf)
+{
+       int index = to_sensor_dev_attr(devattr)->index;
+       struct nct7904_data *data = dev_get_drvdata(dev);
+       int ret;
+       unsigned cnt, rpm;
+
+       ret = nct7904_read_reg16(data, BANK_0, FANIN1_HV_REG + index * 2);
+       if (ret < 0)
+               return ret;
+       cnt = ((ret & 0xff00) >> 3) | (ret & 0x1f);
+       if (cnt == 0x1fff)
+               rpm = 0;
+       else
+               rpm = 1350000 / cnt;
+       return sprintf(buf, "%u\n", rpm);
+}
+
+static umode_t nct7904_fanin_is_visible(struct kobject *kobj,
+                                       struct attribute *a, int n)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct nct7904_data *data = dev_get_drvdata(dev);
+
+       if (data->fanin_mask & (1 << n))
+               return a->mode;
+       return 0;
+}
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7);
+static SENSOR_DEVICE_ATTR(fan9_input, S_IRUGO, show_fan, NULL, 8);
+static SENSOR_DEVICE_ATTR(fan10_input, S_IRUGO, show_fan, NULL, 9);
+static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, show_fan, NULL, 10);
+static SENSOR_DEVICE_ATTR(fan12_input, S_IRUGO, show_fan, NULL, 11);
+
+static struct attribute *nct7904_fanin_attrs[] = {
+       &sensor_dev_attr_fan1_input.dev_attr.attr,
+       &sensor_dev_attr_fan2_input.dev_attr.attr,
+       &sensor_dev_attr_fan3_input.dev_attr.attr,
+       &sensor_dev_attr_fan4_input.dev_attr.attr,
+       &sensor_dev_attr_fan5_input.dev_attr.attr,
+       &sensor_dev_attr_fan6_input.dev_attr.attr,
+       &sensor_dev_attr_fan7_input.dev_attr.attr,
+       &sensor_dev_attr_fan8_input.dev_attr.attr,
+       &sensor_dev_attr_fan9_input.dev_attr.attr,
+       &sensor_dev_attr_fan10_input.dev_attr.attr,
+       &sensor_dev_attr_fan11_input.dev_attr.attr,
+       &sensor_dev_attr_fan12_input.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group nct7904_fanin_group = {
+       .attrs = nct7904_fanin_attrs,
+       .is_visible = nct7904_fanin_is_visible,
+};
+
+/* VSEN ATTR */
+static ssize_t show_voltage(struct device *dev,
+                           struct device_attribute *devattr, char *buf)
+{
+       int index = to_sensor_dev_attr(devattr)->index;
+       struct nct7904_data *data = dev_get_drvdata(dev);
+       int ret;
+       int volt;
+
+       ret = nct7904_read_reg16(data, BANK_0, VSEN1_HV_REG + index * 2);
+       if (ret < 0)
+               return ret;
+       volt = ((ret & 0xff00) >> 5) | (ret & 0x7);
+       if (index < 14)
+               volt *= 2; /* 0.002V scale */
+       else
+               volt *= 6; /* 0.006V scale */
+
+       return sprintf(buf, "%d\n", volt);
+}
+
+static ssize_t show_ltemp(struct device *dev,
+                         struct device_attribute *devattr, char *buf)
+{
+       struct nct7904_data *data = dev_get_drvdata(dev);
+       int ret;
+       int temp;
+
+       ret = nct7904_read_reg16(data, BANK_0, LTD_HV_REG);
+       if (ret < 0)
+               return ret;
+       temp = ((ret & 0xff00) >> 5) | (ret & 0x7);
+       temp = sign_extend32(temp, 10) * 125;
+
+       return sprintf(buf, "%d\n", temp);
+}
+
+static umode_t nct7904_vsen_is_visible(struct kobject *kobj,
+                                      struct attribute *a, int n)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct nct7904_data *data = dev_get_drvdata(dev);
+
+       if (data->vsen_mask & (1 << n))
+               return a->mode;
+       return 0;
+}
+
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 0);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 1);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_voltage, NULL, 2);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_voltage, NULL, 3);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 4);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 5);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 6);
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_voltage, NULL, 7);
+static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_voltage, NULL, 8);
+static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_voltage, NULL, 9);
+static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_voltage, NULL, 10);
+static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_voltage, NULL, 11);
+static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_voltage, NULL, 12);
+static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, show_voltage, NULL, 13);
+/*
+ * Next 3 voltage sensors have specific names in the Nuvoton doc
+ * (3VDD, VBAT, 3VSB) but we use vacant numbers for them.
+ */
+static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, show_voltage, NULL, 14);
+static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_voltage, NULL, 15);
+static SENSOR_DEVICE_ATTR(in20_input, S_IRUGO, show_voltage, NULL, 16);
+/* This is not a voltage, but a local temperature sensor. */
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_ltemp, NULL, 0);
+static SENSOR_DEVICE_ATTR(in17_input, S_IRUGO, show_voltage, NULL, 18);
+static SENSOR_DEVICE_ATTR(in18_input, S_IRUGO, show_voltage, NULL, 19);
+static SENSOR_DEVICE_ATTR(in19_input, S_IRUGO, show_voltage, NULL, 20);
+
+static struct attribute *nct7904_vsen_attrs[] = {
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in3_input.dev_attr.attr,
+       &sensor_dev_attr_in4_input.dev_attr.attr,
+       &sensor_dev_attr_in5_input.dev_attr.attr,
+       &sensor_dev_attr_in6_input.dev_attr.attr,
+       &sensor_dev_attr_in7_input.dev_attr.attr,
+       &sensor_dev_attr_in8_input.dev_attr.attr,
+       &sensor_dev_attr_in9_input.dev_attr.attr,
+       &sensor_dev_attr_in10_input.dev_attr.attr,
+       &sensor_dev_attr_in11_input.dev_attr.attr,
+       &sensor_dev_attr_in12_input.dev_attr.attr,
+       &sensor_dev_attr_in13_input.dev_attr.attr,
+       &sensor_dev_attr_in14_input.dev_attr.attr,
+       &sensor_dev_attr_in15_input.dev_attr.attr,
+       &sensor_dev_attr_in16_input.dev_attr.attr,
+       &sensor_dev_attr_in20_input.dev_attr.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_in17_input.dev_attr.attr,
+       &sensor_dev_attr_in18_input.dev_attr.attr,
+       &sensor_dev_attr_in19_input.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group nct7904_vsen_group = {
+       .attrs = nct7904_vsen_attrs,
+       .is_visible = nct7904_vsen_is_visible,
+};
+
+/* CPU_TEMP ATTR */
+static ssize_t show_tcpu(struct device *dev,
+                        struct device_attribute *devattr, char *buf)
+{
+       int index = to_sensor_dev_attr(devattr)->index;
+       struct nct7904_data *data = dev_get_drvdata(dev);
+       int ret;
+       int temp;
+
+       ret = nct7904_read_reg16(data, BANK_0, T_CPU1_HV_REG + index * 2);
+       if (ret < 0)
+               return ret;
+
+       temp = ((ret & 0xff00) >> 5) | (ret & 0x7);
+       temp = sign_extend32(temp, 10) * 125;
+       return sprintf(buf, "%d\n", temp);
+}
+
+static umode_t nct7904_tcpu_is_visible(struct kobject *kobj,
+                                      struct attribute *a, int n)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct nct7904_data *data = dev_get_drvdata(dev);
+
+       if (data->tcpu_mask & (1 << n))
+               return a->mode;
+       return 0;
+}
+
+/* "temp1_input" reserved for local temp */
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_tcpu, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_tcpu, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_tcpu, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_tcpu, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_tcpu, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_tcpu, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_tcpu, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_tcpu, NULL, 7);
+
+static struct attribute *nct7904_tcpu_attrs[] = {
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp3_input.dev_attr.attr,
+       &sensor_dev_attr_temp4_input.dev_attr.attr,
+       &sensor_dev_attr_temp5_input.dev_attr.attr,
+       &sensor_dev_attr_temp6_input.dev_attr.attr,
+       &sensor_dev_attr_temp7_input.dev_attr.attr,
+       &sensor_dev_attr_temp8_input.dev_attr.attr,
+       &sensor_dev_attr_temp9_input.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group nct7904_tcpu_group = {
+       .attrs = nct7904_tcpu_attrs,
+       .is_visible = nct7904_tcpu_is_visible,
+};
+
+/* PWM ATTR */
+static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr,
+                        const char *buf, size_t count)
+{
+       int index = to_sensor_dev_attr(devattr)->index;
+       struct nct7904_data *data = dev_get_drvdata(dev);
+       unsigned long val;
+       int ret;
+
+       if (kstrtoul(buf, 10, &val) < 0)
+               return -EINVAL;
+       if (val > 255)
+               return -EINVAL;
+
+       ret = nct7904_write_reg(data, BANK_3, FANCTL1_OUT_REG + index, val);
+
+       return ret ? ret : count;
+}
+
+static ssize_t show_pwm(struct device *dev,
+                       struct device_attribute *devattr, char *buf)
+{
+       int index = to_sensor_dev_attr(devattr)->index;
+       struct nct7904_data *data = dev_get_drvdata(dev);
+       int val;
+
+       val = nct7904_read_reg(data, BANK_3, FANCTL1_OUT_REG + index);
+       if (val < 0)
+               return val;
+
+       return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t store_mode(struct device *dev, struct device_attribute *devattr,
+                         const char *buf, size_t count)
+{
+       int index = to_sensor_dev_attr(devattr)->index;
+       struct nct7904_data *data = dev_get_drvdata(dev);
+       unsigned long val;
+       int ret;
+
+       if (kstrtoul(buf, 10, &val) < 0)
+               return -EINVAL;
+       if (val > 1 || (val && !data->fan_mode[index]))
+               return -EINVAL;
+
+       ret = nct7904_write_reg(data, BANK_3, FANCTL1_FMR_REG + index,
+                               val ? data->fan_mode[index] : 0);
+
+       return ret ? ret : count;
+}
+
+/* Return 0 for manual mode or 1 for SmartFan mode */
+static ssize_t show_mode(struct device *dev,
+                        struct device_attribute *devattr, char *buf)
+{
+       int index = to_sensor_dev_attr(devattr)->index;
+       struct nct7904_data *data = dev_get_drvdata(dev);
+       int val;
+
+       val = nct7904_read_reg(data, BANK_3, FANCTL1_FMR_REG + index);
+       if (val < 0)
+               return val;
+
+       return sprintf(buf, "%d\n", val ? 1 : 0);
+}
+
+/* 2 attributes per channel: pwm and mode */
+static SENSOR_DEVICE_ATTR(fan1_pwm, S_IRUGO | S_IWUSR,
+                       show_pwm, store_pwm, 0);
+static SENSOR_DEVICE_ATTR(fan1_mode, S_IRUGO | S_IWUSR,
+                       show_mode, store_mode, 0);
+static SENSOR_DEVICE_ATTR(fan2_pwm, S_IRUGO | S_IWUSR,
+                       show_pwm, store_pwm, 1);
+static SENSOR_DEVICE_ATTR(fan2_mode, S_IRUGO | S_IWUSR,
+                       show_mode, store_mode, 1);
+static SENSOR_DEVICE_ATTR(fan3_pwm, S_IRUGO | S_IWUSR,
+                       show_pwm, store_pwm, 2);
+static SENSOR_DEVICE_ATTR(fan3_mode, S_IRUGO | S_IWUSR,
+                       show_mode, store_mode, 2);
+static SENSOR_DEVICE_ATTR(fan4_pwm, S_IRUGO | S_IWUSR,
+                       show_pwm, store_pwm, 3);
+static SENSOR_DEVICE_ATTR(fan4_mode, S_IRUGO | S_IWUSR,
+                       show_mode, store_mode, 3);
+
+static struct attribute *nct7904_fanctl_attrs[] = {
+       &sensor_dev_attr_fan1_pwm.dev_attr.attr,
+       &sensor_dev_attr_fan1_mode.dev_attr.attr,
+       &sensor_dev_attr_fan2_pwm.dev_attr.attr,
+       &sensor_dev_attr_fan2_mode.dev_attr.attr,
+       &sensor_dev_attr_fan3_pwm.dev_attr.attr,
+       &sensor_dev_attr_fan3_mode.dev_attr.attr,
+       &sensor_dev_attr_fan4_pwm.dev_attr.attr,
+       &sensor_dev_attr_fan4_mode.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group nct7904_fanctl_group = {
+       .attrs = nct7904_fanctl_attrs,
+};
+
+static const struct attribute_group *nct7904_groups[] = {
+       &nct7904_fanin_group,
+       &nct7904_vsen_group,
+       &nct7904_tcpu_group,
+       &nct7904_fanctl_group,
+       NULL
+};
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int nct7904_detect(struct i2c_client *client,
+                         struct i2c_board_info *info)
+{
+       struct i2c_adapter *adapter = client->adapter;
+
+       if (!i2c_check_functionality(adapter,
+                                    I2C_FUNC_SMBUS_READ_BYTE |
+                                    I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+               return -ENODEV;
+
+       /* Determine the chip type. */
+       if (i2c_smbus_read_byte_data(client, VENDOR_ID_REG) != NUVOTON_ID ||
+           i2c_smbus_read_byte_data(client, CHIP_ID_REG) != NCT7904_ID ||
+           (i2c_smbus_read_byte_data(client, DEVICE_ID_REG) & 0xf0) != 0x50 ||
+           (i2c_smbus_read_byte_data(client, BANK_SEL_REG) & 0xf8) != 0x00)
+               return -ENODEV;
+
+       strlcpy(info->type, "nct7904", I2C_NAME_SIZE);
+
+       return 0;
+}
+
+static int nct7904_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct nct7904_data *data;
+       struct device *hwmon_dev;
+       struct device *dev = &client->dev;
+       int ret, i;
+       u32 mask;
+
+       data = devm_kzalloc(dev, sizeof(struct nct7904_data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->client = client;
+       mutex_init(&data->bank_lock);
+       data->bank_sel = -1;
+
+       /* Setup sensor groups. */
+       /* FANIN attributes */
+       ret = nct7904_read_reg16(data, BANK_0, FANIN_CTRL0_REG);
+       if (ret < 0)
+               return ret;
+       data->fanin_mask = (ret >> 8) | ((ret & 0xff) << 8);
+
+       /*
+        * VSEN attributes
+        *
+        * Note: voltage sensors overlap with external temperature
+        * sensors. So, if we ever decide to support the latter
+        * we will have to adjust 'vsen_mask' accordingly.
+        */
+       mask = 0;
+       ret = nct7904_read_reg16(data, BANK_0, VT_ADC_CTRL0_REG);
+       if (ret >= 0)
+               mask = (ret >> 8) | ((ret & 0xff) << 8);
+       ret = nct7904_read_reg(data, BANK_0, VT_ADC_CTRL2_REG);
+       if (ret >= 0)
+               mask |= (ret << 16);
+       data->vsen_mask = mask;
+
+       /* CPU_TEMP attributes */
+       ret = nct7904_read_reg16(data, BANK_0, DTS_T_CTRL0_REG);
+       if (ret < 0)
+               return ret;
+       data->tcpu_mask = ((ret >> 8) & 0xf) | ((ret & 0xf) << 4);
+
+       for (i = 0; i < FANCTL_MAX; i++) {
+               ret = nct7904_read_reg(data, BANK_3, FANCTL1_FMR_REG + i);
+               if (ret < 0)
+                       return ret;
+               data->fan_mode[i] = ret;
+       }
+
+       hwmon_dev =
+               devm_hwmon_device_register_with_groups(dev, client->name, data,
+                                                      nct7904_groups);
+       return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct i2c_device_id nct7904_id[] = {
+       {"nct7904", 0},
+       {}
+};
+
+static struct i2c_driver nct7904_driver = {
+       .class = I2C_CLASS_HWMON,
+       .driver = {
+               .name = "nct7904",
+       },
+       .probe = nct7904_probe,
+       .id_table = nct7904_id,
+       .detect = nct7904_detect,
+       .address_list = normal_i2c,
+};
+
+module_i2c_driver(nct7904_driver);
+
+MODULE_AUTHOR("Vadim V. Vlasov <vvlasov@dev.rtsoft.ru>");
+MODULE_DESCRIPTION("Hwmon driver for NUVOTON NCT7904");
+MODULE_LICENSE("GPL");
index 1991d9032c3843de2ffcd20b82f5790d22ce2684..2d9a712699ff5d541e831629834b23882b4fa606 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/pwm.h>
 #include <linux/sysfs.h>
+#include <linux/thermal.h>
 
 #define MAX_PWM 255
 
 struct pwm_fan_ctx {
        struct mutex lock;
        struct pwm_device *pwm;
-       unsigned char pwm_value;
+       unsigned int pwm_value;
+       unsigned int pwm_fan_state;
+       unsigned int pwm_fan_max_state;
+       unsigned int *pwm_fan_cooling_levels;
+       struct thermal_cooling_device *cdev;
 };
 
-static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
-                      const char *buf, size_t count)
+static int  __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm)
 {
-       struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
-       unsigned long pwm, duty;
-       ssize_t ret;
-
-       if (kstrtoul(buf, 10, &pwm) || pwm > MAX_PWM)
-               return -EINVAL;
+       unsigned long duty;
+       int ret = 0;
 
        mutex_lock(&ctx->lock);
-
        if (ctx->pwm_value == pwm)
-               goto exit_set_pwm_no_change;
-
-       if (pwm == 0) {
-               pwm_disable(ctx->pwm);
-               goto exit_set_pwm;
-       }
+               goto exit_set_pwm_err;
 
        duty = DIV_ROUND_UP(pwm * (ctx->pwm->period - 1), MAX_PWM);
        ret = pwm_config(ctx->pwm, duty, ctx->pwm->period);
        if (ret)
                goto exit_set_pwm_err;
 
+       if (pwm == 0)
+               pwm_disable(ctx->pwm);
+
        if (ctx->pwm_value == 0) {
                ret = pwm_enable(ctx->pwm);
                if (ret)
                        goto exit_set_pwm_err;
        }
 
-exit_set_pwm:
        ctx->pwm_value = pwm;
-exit_set_pwm_no_change:
-       ret = count;
 exit_set_pwm_err:
        mutex_unlock(&ctx->lock);
        return ret;
 }
 
+static void pwm_fan_update_state(struct pwm_fan_ctx *ctx, unsigned long pwm)
+{
+       int i;
+
+       for (i = 0; i < ctx->pwm_fan_max_state; ++i)
+               if (pwm < ctx->pwm_fan_cooling_levels[i + 1])
+                       break;
+
+       ctx->pwm_fan_state = i;
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count)
+{
+       struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+       unsigned long pwm;
+       int ret;
+
+       if (kstrtoul(buf, 10, &pwm) || pwm > MAX_PWM)
+               return -EINVAL;
+
+       ret = __set_pwm(ctx, pwm);
+       if (ret)
+               return ret;
+
+       pwm_fan_update_state(ctx, pwm);
+       return count;
+}
+
 static ssize_t show_pwm(struct device *dev,
                        struct device_attribute *attr, char *buf)
 {
@@ -91,10 +114,108 @@ static struct attribute *pwm_fan_attrs[] = {
 
 ATTRIBUTE_GROUPS(pwm_fan);
 
+/* thermal cooling device callbacks */
+static int pwm_fan_get_max_state(struct thermal_cooling_device *cdev,
+                                unsigned long *state)
+{
+       struct pwm_fan_ctx *ctx = cdev->devdata;
+
+       if (!ctx)
+               return -EINVAL;
+
+       *state = ctx->pwm_fan_max_state;
+
+       return 0;
+}
+
+static int pwm_fan_get_cur_state(struct thermal_cooling_device *cdev,
+                                unsigned long *state)
+{
+       struct pwm_fan_ctx *ctx = cdev->devdata;
+
+       if (!ctx)
+               return -EINVAL;
+
+       *state = ctx->pwm_fan_state;
+
+       return 0;
+}
+
+static int
+pwm_fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
+{
+       struct pwm_fan_ctx *ctx = cdev->devdata;
+       int ret;
+
+       if (!ctx || (state > ctx->pwm_fan_max_state))
+               return -EINVAL;
+
+       if (state == ctx->pwm_fan_state)
+               return 0;
+
+       ret = __set_pwm(ctx, ctx->pwm_fan_cooling_levels[state]);
+       if (ret) {
+               dev_err(&cdev->device, "Cannot set pwm!\n");
+               return ret;
+       }
+
+       ctx->pwm_fan_state = state;
+
+       return ret;
+}
+
+static const struct thermal_cooling_device_ops pwm_fan_cooling_ops = {
+       .get_max_state = pwm_fan_get_max_state,
+       .get_cur_state = pwm_fan_get_cur_state,
+       .set_cur_state = pwm_fan_set_cur_state,
+};
+
+static int pwm_fan_of_get_cooling_data(struct device *dev,
+                                      struct pwm_fan_ctx *ctx)
+{
+       struct device_node *np = dev->of_node;
+       int num, i, ret;
+
+       if (!of_find_property(np, "cooling-levels", NULL))
+               return 0;
+
+       ret = of_property_count_u32_elems(np, "cooling-levels");
+       if (ret <= 0) {
+               dev_err(dev, "Wrong data!\n");
+               return ret ? : -EINVAL;
+       }
+
+       num = ret;
+       ctx->pwm_fan_cooling_levels = devm_kzalloc(dev, num * sizeof(u32),
+                                                  GFP_KERNEL);
+       if (!ctx->pwm_fan_cooling_levels)
+               return -ENOMEM;
+
+       ret = of_property_read_u32_array(np, "cooling-levels",
+                                        ctx->pwm_fan_cooling_levels, num);
+       if (ret) {
+               dev_err(dev, "Property 'cooling-levels' cannot be read!\n");
+               return ret;
+       }
+
+       for (i = 0; i < num; i++) {
+               if (ctx->pwm_fan_cooling_levels[i] > MAX_PWM) {
+                       dev_err(dev, "PWM fan state[%d]:%d > %d\n", i,
+                               ctx->pwm_fan_cooling_levels[i], MAX_PWM);
+                       return -EINVAL;
+               }
+       }
+
+       ctx->pwm_fan_max_state = num - 1;
+
+       return 0;
+}
+
 static int pwm_fan_probe(struct platform_device *pdev)
 {
-       struct device *hwmon;
+       struct thermal_cooling_device *cdev;
        struct pwm_fan_ctx *ctx;
+       struct device *hwmon;
        int duty_cycle;
        int ret;
 
@@ -136,6 +257,26 @@ static int pwm_fan_probe(struct platform_device *pdev)
                pwm_disable(ctx->pwm);
                return PTR_ERR(hwmon);
        }
+
+       ret = pwm_fan_of_get_cooling_data(&pdev->dev, ctx);
+       if (ret)
+               return ret;
+
+       ctx->pwm_fan_state = ctx->pwm_fan_max_state;
+       if (IS_ENABLED(CONFIG_THERMAL)) {
+               cdev = thermal_of_cooling_device_register(pdev->dev.of_node,
+                                                         "pwm-fan", ctx,
+                                                         &pwm_fan_cooling_ops);
+               if (IS_ERR(cdev)) {
+                       dev_err(&pdev->dev,
+                               "Failed to register pwm-fan as cooling device");
+                       pwm_disable(ctx->pwm);
+                       return PTR_ERR(cdev);
+               }
+               ctx->cdev = cdev;
+               thermal_cdev_update(cdev);
+       }
+
        return 0;
 }
 
@@ -143,6 +284,7 @@ static int pwm_fan_remove(struct platform_device *pdev)
 {
        struct pwm_fan_ctx *ctx = platform_get_drvdata(pdev);
 
+       thermal_cooling_device_unregister(ctx->cdev);
        if (ctx->pwm_value)
                pwm_disable(ctx->pwm);
        return 0;
@@ -177,7 +319,7 @@ static int pwm_fan_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(pwm_fan_pm, pwm_fan_suspend, pwm_fan_resume);
 
-static struct of_device_id of_pwm_fan_match[] = {
+static const struct of_device_id of_pwm_fan_match[] = {
        { .compatible = "pwm-fan", },
        {},
 };
index cf1848b8fb321a0e4f867352730956543088feb0..8ba419d343f86770b537e74fffb933b25a08b082 100644 (file)
@@ -193,7 +193,7 @@ static struct vexpress_hwmon_type vexpress_hwmon_energy = {
        },
 };
 
-static struct of_device_id vexpress_hwmon_of_match[] = {
+static const struct of_device_id vexpress_hwmon_of_match[] = {
 #if !defined(CONFIG_REGULATOR_VEXPRESS)
        {
                .compatible = "arm,vexpress-volt",
index 22da9c2ffa2250cad9a7172bdbc94890d659a744..2255af23b9c70e69ce3105fd2f3d3e5b80a757c9 100644 (file)
@@ -485,6 +485,15 @@ config I2C_DESIGNWARE_BAYTRAIL
          the platform firmware controlling it. You should say Y if running on
          a BayTrail system using the AXP288.
 
+config I2C_DIGICOLOR
+       tristate "Conexant Digicolor I2C driver"
+       depends on ARCH_DIGICOLOR
+       help
+         Support for Conexant Digicolor SoCs (CX92755) I2C controller driver.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-digicolor.
+
 config I2C_EFM32
        tristate "EFM32 I2C controller"
        depends on ARCH_EFM32 || COMPILE_TEST
@@ -574,6 +583,15 @@ config I2C_IOP3XX
          This driver can also be built as a module.  If so, the module
          will be called i2c-iop3xx.
 
+config I2C_JZ4780
+       tristate "JZ4780 I2C controller interface support"
+       depends on MACH_JZ4780 || COMPILE_TEST
+       help
+        If you say yes to this option, support will be included for the
+        Ingenic JZ4780 I2C controller.
+
+        If you don't know what to do here, say N.
+
 config I2C_KEMPLD
        tristate "Kontron COM I2C Controller"
        depends on MFD_KEMPLD
@@ -898,6 +916,16 @@ config I2C_XLR
          This driver can also be built as a module.  If so, the module
          will be called i2c-xlr.
 
+config I2C_XLP9XX
+       tristate "XLP9XX I2C support"
+       depends on CPU_XLP || COMPILE_TEST
+       help
+         This driver enables support for the on-chip I2C interface of
+         the Broadcom XLP9xx/XLP5xx MIPS processors.
+
+         This driver can also be built as a module.  If so, the module will
+         be called i2c-xlp9xx.
+
 config I2C_RCAR
        tristate "Renesas R-Car I2C Controller"
        depends on ARCH_SHMOBILE || COMPILE_TEST
index 3638feb6677e1d6d7991b6d0d831ebc1b99c2e11..cdf941da91c65ef829b7f658ed41c1f69d5ddf1d 100644 (file)
@@ -45,6 +45,7 @@ i2c-designware-platform-objs := i2c-designware-platdrv.o
 i2c-designware-platform-$(CONFIG_I2C_DESIGNWARE_BAYTRAIL) += i2c-designware-baytrail.o
 obj-$(CONFIG_I2C_DESIGNWARE_PCI)       += i2c-designware-pci.o
 i2c-designware-pci-objs := i2c-designware-pcidrv.o
+obj-$(CONFIG_I2C_DIGICOLOR)    += i2c-digicolor.o
 obj-$(CONFIG_I2C_EFM32)                += i2c-efm32.o
 obj-$(CONFIG_I2C_EG20T)                += i2c-eg20t.o
 obj-$(CONFIG_I2C_EXYNOS5)      += i2c-exynos5.o
@@ -55,6 +56,7 @@ obj-$(CONFIG_I2C_IBM_IIC)     += i2c-ibm_iic.o
 obj-$(CONFIG_I2C_IMG)          += i2c-img-scb.o
 obj-$(CONFIG_I2C_IMX)          += i2c-imx.o
 obj-$(CONFIG_I2C_IOP3XX)       += i2c-iop3xx.o
+obj-$(CONFIG_I2C_JZ4780)       += i2c-jz4780.o
 obj-$(CONFIG_I2C_KEMPLD)       += i2c-kempld.o
 obj-$(CONFIG_I2C_MESON)                += i2c-meson.o
 obj-$(CONFIG_I2C_MPC)          += i2c-mpc.o
@@ -87,6 +89,7 @@ obj-$(CONFIG_I2C_WMT)         += i2c-wmt.o
 obj-$(CONFIG_I2C_OCTEON)       += i2c-octeon.o
 obj-$(CONFIG_I2C_XILINX)       += i2c-xiic.o
 obj-$(CONFIG_I2C_XLR)          += i2c-xlr.o
+obj-$(CONFIG_I2C_XLP9XX)       += i2c-xlp9xx.o
 obj-$(CONFIG_I2C_RCAR)         += i2c-rcar.o
 
 # External I2C/SMBus adapter drivers
index 636fd2efad8850be3d028e940cae2667149ac4dc..ff23d1bdd23072c6c5cec5f690b048ae4dee0f8e 100644 (file)
@@ -381,6 +381,7 @@ static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
 static int at91_do_twi_transfer(struct at91_twi_dev *dev)
 {
        int ret;
+       unsigned long time_left;
        bool has_unre_flag = dev->pdata->has_unre_flag;
 
        dev_dbg(dev->dev, "transfer: %s %d bytes.\n",
@@ -436,9 +437,9 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
                }
        }
 
-       ret = wait_for_completion_timeout(&dev->cmd_complete,
-                                            dev->adapter.timeout);
-       if (ret == 0) {
+       time_left = wait_for_completion_timeout(&dev->cmd_complete,
+                                             dev->adapter.timeout);
+       if (time_left == 0) {
                dev_err(dev->dev, "controller timed out\n");
                at91_init_twi_bus(dev);
                ret = -ETIMEDOUT;
@@ -487,30 +488,10 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
        if (ret < 0)
                goto out;
 
-       /*
-        * The hardware can handle at most two messages concatenated by a
-        * repeated start via it's internal address feature.
-        */
-       if (num > 2) {
-               dev_err(dev->dev,
-                       "cannot handle more than two concatenated messages.\n");
-               ret = 0;
-               goto out;
-       } else if (num == 2) {
+       if (num == 2) {
                int internal_address = 0;
                int i;
 
-               if (msg->flags & I2C_M_RD) {
-                       dev_err(dev->dev, "first transfer must be write.\n");
-                       ret = -EINVAL;
-                       goto out;
-               }
-               if (msg->len > 3) {
-                       dev_err(dev->dev, "first message size must be <= 3.\n");
-                       ret = -EINVAL;
-                       goto out;
-               }
-
                /* 1st msg is put into the internal address, start with 2nd */
                m_start = &msg[1];
                for (i = 0; i < msg->len; ++i) {
@@ -540,6 +521,15 @@ out:
        return ret;
 }
 
+/*
+ * The hardware can handle at most two messages concatenated by a
+ * repeated start via it's internal address feature.
+ */
+static struct i2c_adapter_quirks at91_twi_quirks = {
+       .flags = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | I2C_AQ_COMB_SAME_ADDR,
+       .max_comb_1st_msg_len = 3,
+};
+
 static u32 at91_twi_func(struct i2c_adapter *adapter)
 {
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
@@ -777,6 +767,7 @@ static int at91_twi_probe(struct platform_device *pdev)
        dev->adapter.owner = THIS_MODULE;
        dev->adapter.class = I2C_CLASS_DEPRECATED;
        dev->adapter.algo = &at91_twi_algorithm;
+       dev->adapter.quirks = &at91_twi_quirks;
        dev->adapter.dev.parent = dev->dev;
        dev->adapter.nr = pdev->id;
        dev->adapter.timeout = AT91_I2C_TIMEOUT;
index 768a598d8d03add09e3a0e454e031d3f728f7a2b..32d88349086314fc739b3d5890285ac1ad28b714 100644 (file)
@@ -334,12 +334,7 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
        u32 int_mask = MST_STATUS_ERR | MST_STATUS_SNS;
        u32 rx_xfer, tx_xfer;
        u32 addr_1, addr_2;
-       int ret;
-
-       if (msg->len > 255) {
-               dev_warn(idev->dev, "unsupported length %u\n", msg->len);
-               return -EINVAL;
-       }
+       unsigned long time_left;
 
        idev->msg = msg;
        idev->msg_xfrd = 0;
@@ -388,15 +383,15 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
 
        i2c_int_enable(idev, int_mask);
 
-       ret = wait_for_completion_timeout(&idev->msg_complete,
-                                         I2C_XFER_TIMEOUT);
+       time_left = wait_for_completion_timeout(&idev->msg_complete,
+                                             I2C_XFER_TIMEOUT);
 
        i2c_int_disable(idev, int_mask);
 
        if (readl(idev->base + MST_COMMAND) & CMD_BUSY)
                dev_warn(idev->dev, "busy after xfer\n");
 
-       if (ret == 0)
+       if (time_left == 0)
                idev->msg_err = -ETIMEDOUT;
 
        if (unlikely(idev->msg_err) && idev->msg_err != -ENXIO)
@@ -408,17 +403,17 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
 static int axxia_i2c_stop(struct axxia_i2c_dev *idev)
 {
        u32 int_mask = MST_STATUS_ERR | MST_STATUS_SCC;
-       int ret;
+       unsigned long time_left;
 
        reinit_completion(&idev->msg_complete);
 
        /* Issue stop */
        writel(0xb, idev->base + MST_COMMAND);
        i2c_int_enable(idev, int_mask);
-       ret = wait_for_completion_timeout(&idev->msg_complete,
-                                         I2C_STOP_TIMEOUT);
+       time_left = wait_for_completion_timeout(&idev->msg_complete,
+                                             I2C_STOP_TIMEOUT);
        i2c_int_disable(idev, int_mask);
-       if (ret == 0)
+       if (time_left == 0)
                return -ETIMEDOUT;
 
        if (readl(idev->base + MST_COMMAND) & CMD_BUSY)
@@ -454,6 +449,11 @@ static const struct i2c_algorithm axxia_i2c_algo = {
        .functionality = axxia_i2c_func,
 };
 
+static struct i2c_adapter_quirks axxia_i2c_quirks = {
+       .max_read_len = 255,
+       .max_write_len = 255,
+};
+
 static int axxia_i2c_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -511,6 +511,7 @@ static int axxia_i2c_probe(struct platform_device *pdev)
        strlcpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name));
        idev->adapter.owner = THIS_MODULE;
        idev->adapter.algo = &axxia_i2c_algo;
+       idev->adapter.quirks = &axxia_i2c_quirks;
        idev->adapter.dev.parent = &pdev->dev;
        idev->adapter.dev.of_node = pdev->dev.of_node;
 
index d3c89157b337748e9868338612ee0c5dfe9c5968..f9f2c2082151e2203966235edd5b73db1ef899be 100644 (file)
@@ -160,14 +160,6 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c,
        u32 val;
        unsigned long time_left = msecs_to_jiffies(I2C_TIMEOUT_MESC);
 
-       /* need to reserve one byte in the FIFO for the slave address */
-       if (msg->len > M_TX_RX_FIFO_SIZE - 1) {
-               dev_err(iproc_i2c->device,
-                       "only support data length up to %u bytes\n",
-                       M_TX_RX_FIFO_SIZE - 1);
-               return -EOPNOTSUPP;
-       }
-
        /* check if bus is busy */
        if (!!(readl(iproc_i2c->base + M_CMD_OFFSET) &
               BIT(M_CMD_START_BUSY_SHIFT))) {
@@ -287,6 +279,12 @@ static const struct i2c_algorithm bcm_iproc_algo = {
        .functionality = bcm_iproc_i2c_functionality,
 };
 
+static struct i2c_adapter_quirks bcm_iproc_i2c_quirks = {
+       /* need to reserve one byte in the FIFO for the slave address */
+       .max_read_len = M_TX_RX_FIFO_SIZE - 1,
+       .max_write_len = M_TX_RX_FIFO_SIZE - 1,
+};
+
 static int bcm_iproc_i2c_cfg_speed(struct bcm_iproc_i2c_dev *iproc_i2c)
 {
        unsigned int bus_speed;
@@ -413,6 +411,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev)
        i2c_set_adapdata(adap, iproc_i2c);
        strlcpy(adap->name, "Broadcom iProc I2C adapter", sizeof(adap->name));
        adap->algo = &bcm_iproc_algo;
+       adap->quirks = &bcm_iproc_i2c_quirks;
        adap->dev.parent = &pdev->dev;
        adap->dev.of_node = pdev->dev.of_node;
 
index 5d6feb937b9dc4398c9a00dae2035c63a6813f0c..c9336a3202d5620681b38d6e8c2b47651a75af0e 100644 (file)
@@ -147,7 +147,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
                                struct i2c_msg *msg)
 {
        u32 c;
-       int time_left;
+       unsigned long time_left;
 
        i2c_dev->msg_buf = msg->buf;
        i2c_dev->msg_buf_remaining = msg->len;
index 7d7a14cdadfb187d5fd4f95918146c8c6555443a..2ee78e099d3047de1096ebbb469dc561e589cce3 100644 (file)
@@ -475,7 +475,7 @@ static void cdns_i2c_master_reset(struct i2c_adapter *adap)
 static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg,
                struct i2c_adapter *adap)
 {
-       int ret;
+       unsigned long time_left;
        u32 reg;
 
        id->p_msg = msg;
@@ -501,8 +501,8 @@ static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg,
                cdns_i2c_msend(id);
 
        /* Wait for the signal of completion */
-       ret = wait_for_completion_timeout(&id->xfer_done, adap->timeout);
-       if (!ret) {
+       time_left = wait_for_completion_timeout(&id->xfer_done, adap->timeout);
+       if (time_left == 0) {
                cdns_i2c_master_reset(adap);
                dev_err(id->adap.dev.parent,
                                "timeout waiting on completion\n");
index 2d466538b2e2c9eed0adfe00518dc13641a147eb..714bdc837769fdc74fdf9208c18d0568ecc653ae 100644 (file)
@@ -308,22 +308,12 @@ static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
        struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg;
        struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram;
        struct i2c_msg *pmsg;
-       int ret, i;
+       int ret;
        int tptr;
        int rptr;
        cbd_t __iomem *tbdf;
        cbd_t __iomem *rbdf;
 
-       if (num > CPM_MAXBD)
-               return -EINVAL;
-
-       /* Check if we have any oversized READ requests */
-       for (i = 0; i < num; i++) {
-               pmsg = &msgs[i];
-               if (pmsg->len >= CPM_MAX_READ)
-                       return -EINVAL;
-       }
-
        /* Reset to use first buffer */
        out_be16(&i2c_ram->rbptr, in_be16(&i2c_ram->rbase));
        out_be16(&i2c_ram->tbptr, in_be16(&i2c_ram->tbase));
@@ -424,10 +414,18 @@ static const struct i2c_algorithm cpm_i2c_algo = {
        .functionality = cpm_i2c_func,
 };
 
+/* CPM_MAX_READ is also limiting writes according to the code! */
+static struct i2c_adapter_quirks cpm_i2c_quirks = {
+       .max_num_msgs = CPM_MAXBD,
+       .max_read_len = CPM_MAX_READ,
+       .max_write_len = CPM_MAX_READ,
+};
+
 static const struct i2c_adapter cpm_ops = {
        .owner          = THIS_MODULE,
        .name           = "i2c-cpm",
        .algo           = &cpm_i2c_algo,
+       .quirks         = &cpm_i2c_quirks,
 };
 
 static int cpm_i2c_setup(struct cpm_i2c *cpm)
index 6dc7ff5d3d9a050aafd82d1143440f7654031033..4788a32afb8618da59c3f8c7579e4f4d23b4295c 100644 (file)
 #define DAVINCI_I2C_IVR_REG    0x28
 #define DAVINCI_I2C_EMDR_REG   0x2c
 #define DAVINCI_I2C_PSC_REG    0x30
+#define DAVINCI_I2C_FUNC_REG   0x48
+#define DAVINCI_I2C_DIR_REG    0x4c
+#define DAVINCI_I2C_DIN_REG    0x50
+#define DAVINCI_I2C_DOUT_REG   0x54
+#define DAVINCI_I2C_DSET_REG   0x58
+#define DAVINCI_I2C_DCLR_REG   0x5c
 
 #define DAVINCI_I2C_IVR_AAS    0x07
 #define DAVINCI_I2C_IVR_SCD    0x06
 #define DAVINCI_I2C_IMR_NACK   BIT(1)
 #define DAVINCI_I2C_IMR_AL     BIT(0)
 
+/* set SDA and SCL as GPIO */
+#define DAVINCI_I2C_FUNC_PFUNC0        BIT(0)
+
+/* set SCL as output when used as GPIO*/
+#define DAVINCI_I2C_DIR_PDIR0  BIT(0)
+/* set SDA as output when used as GPIO*/
+#define DAVINCI_I2C_DIR_PDIR1  BIT(1)
+
+/* read SCL GPIO level */
+#define DAVINCI_I2C_DIN_PDIN0 BIT(0)
+/* read SDA GPIO level */
+#define DAVINCI_I2C_DIN_PDIN1 BIT(1)
+
+/*set the SCL GPIO high */
+#define DAVINCI_I2C_DSET_PDSET0        BIT(0)
+/*set the SDA GPIO high */
+#define DAVINCI_I2C_DSET_PDSET1        BIT(1)
+
+/* set the SCL GPIO low */
+#define DAVINCI_I2C_DCLR_PDCLR0        BIT(0)
+/* set the SDA GPIO low */
+#define DAVINCI_I2C_DCLR_PDCLR1        BIT(1)
+
 struct davinci_i2c_dev {
        struct device           *dev;
        void __iomem            *base;
@@ -129,43 +158,6 @@ static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg)
        return readw_relaxed(i2c_dev->base + reg);
 }
 
-/* Generate a pulse on the i2c clock pin. */
-static void davinci_i2c_clock_pulse(unsigned int scl_pin)
-{
-       u16 i;
-
-       if (scl_pin) {
-               /* Send high and low on the SCL line */
-               for (i = 0; i < 9; i++) {
-                       gpio_set_value(scl_pin, 0);
-                       udelay(20);
-                       gpio_set_value(scl_pin, 1);
-                       udelay(20);
-               }
-       }
-}
-
-/* This routine does i2c bus recovery as specified in the
- * i2c protocol Rev. 03 section 3.16 titled "Bus clear"
- */
-static void davinci_i2c_recover_bus(struct davinci_i2c_dev *dev)
-{
-       u32 flag = 0;
-       struct davinci_i2c_platform_data *pdata = dev->pdata;
-
-       dev_err(dev->dev, "initiating i2c bus recovery\n");
-       /* Send NACK to the slave */
-       flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
-       flag |=  DAVINCI_I2C_MDR_NACK;
-       /* write the data into mode register */
-       davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
-       davinci_i2c_clock_pulse(pdata->scl_pin);
-       /* Send STOP */
-       flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
-       flag |= DAVINCI_I2C_MDR_STP;
-       davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
-}
-
 static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev,
                                                                int val)
 {
@@ -262,6 +254,99 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
        return 0;
 }
 
+/*
+ * This routine does i2c bus recovery by using i2c_generic_gpio_recovery
+ * which is provided by I2C Bus recovery infrastructure.
+ */
+static void davinci_i2c_prepare_recovery(struct i2c_adapter *adap)
+{
+       struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
+
+       /* Disable interrupts */
+       davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, 0);
+
+       /* put I2C into reset */
+       davinci_i2c_reset_ctrl(dev, 0);
+}
+
+static void davinci_i2c_unprepare_recovery(struct i2c_adapter *adap)
+{
+       struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
+
+       i2c_davinci_init(dev);
+}
+
+static struct i2c_bus_recovery_info davinci_i2c_gpio_recovery_info = {
+       .recover_bus = i2c_generic_gpio_recovery,
+       .prepare_recovery = davinci_i2c_prepare_recovery,
+       .unprepare_recovery = davinci_i2c_unprepare_recovery,
+};
+
+static void davinci_i2c_set_scl(struct i2c_adapter *adap, int val)
+{
+       struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
+
+       if (val)
+               davinci_i2c_write_reg(dev, DAVINCI_I2C_DSET_REG,
+                                     DAVINCI_I2C_DSET_PDSET0);
+       else
+               davinci_i2c_write_reg(dev, DAVINCI_I2C_DCLR_REG,
+                                     DAVINCI_I2C_DCLR_PDCLR0);
+}
+
+static int davinci_i2c_get_scl(struct i2c_adapter *adap)
+{
+       struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
+       int val;
+
+       /* read the state of SCL */
+       val = davinci_i2c_read_reg(dev, DAVINCI_I2C_DIN_REG);
+       return val & DAVINCI_I2C_DIN_PDIN0;
+}
+
+static int davinci_i2c_get_sda(struct i2c_adapter *adap)
+{
+       struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
+       int val;
+
+       /* read the state of SDA */
+       val = davinci_i2c_read_reg(dev, DAVINCI_I2C_DIN_REG);
+       return val & DAVINCI_I2C_DIN_PDIN1;
+}
+
+static void davinci_i2c_scl_prepare_recovery(struct i2c_adapter *adap)
+{
+       struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
+
+       davinci_i2c_prepare_recovery(adap);
+
+       /* SCL output, SDA input */
+       davinci_i2c_write_reg(dev, DAVINCI_I2C_DIR_REG, DAVINCI_I2C_DIR_PDIR0);
+
+       /* change to GPIO mode */
+       davinci_i2c_write_reg(dev, DAVINCI_I2C_FUNC_REG,
+                             DAVINCI_I2C_FUNC_PFUNC0);
+}
+
+static void davinci_i2c_scl_unprepare_recovery(struct i2c_adapter *adap)
+{
+       struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
+
+       /* change back to I2C mode */
+       davinci_i2c_write_reg(dev, DAVINCI_I2C_FUNC_REG, 0);
+
+       davinci_i2c_unprepare_recovery(adap);
+}
+
+static struct i2c_bus_recovery_info davinci_i2c_scl_recovery_info = {
+       .recover_bus = i2c_generic_scl_recovery,
+       .set_scl = davinci_i2c_set_scl,
+       .get_scl = davinci_i2c_get_scl,
+       .get_sda = davinci_i2c_get_sda,
+       .prepare_recovery = davinci_i2c_scl_prepare_recovery,
+       .unprepare_recovery = davinci_i2c_scl_unprepare_recovery,
+};
+
 /*
  * Waiting for bus not busy
  */
@@ -282,8 +367,7 @@ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev,
                                return -ETIMEDOUT;
                        } else {
                                to_cnt = 0;
-                               davinci_i2c_recover_bus(dev);
-                               i2c_davinci_init(dev);
+                               i2c_recover_bus(&dev->adapter);
                        }
                }
                if (allow_sleep)
@@ -304,7 +388,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
        struct davinci_i2c_platform_data *pdata = dev->pdata;
        u32 flag;
        u16 w;
-       int r;
+       unsigned long time_left;
 
        /* Introduce a delay, required for some boards (e.g Davinci EVM) */
        if (pdata->bus_delay)
@@ -368,11 +452,11 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
                flag |= DAVINCI_I2C_MDR_STP;
        davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
 
-       r = wait_for_completion_timeout(&dev->cmd_complete, dev->adapter.timeout);
-       if (r == 0) {
+       time_left = wait_for_completion_timeout(&dev->cmd_complete,
+                                               dev->adapter.timeout);
+       if (!time_left) {
                dev_err(dev->dev, "controller timed out\n");
-               davinci_i2c_recover_bus(dev);
-               i2c_davinci_init(dev);
+               i2c_recover_bus(adap);
                dev->buf_len = 0;
                return -ETIMEDOUT;
        }
@@ -380,17 +464,13 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
                /* This should be 0 if all bytes were transferred
                 * or dev->cmd_err denotes an error.
                 */
-               if (r >= 0) {
-                       dev_err(dev->dev, "abnormal termination buf_len=%i\n",
-                               dev->buf_len);
-                       r = -EREMOTEIO;
-               }
+               dev_err(dev->dev, "abnormal termination buf_len=%i\n",
+                       dev->buf_len);
                dev->terminate = 1;
                wmb();
                dev->buf_len = 0;
+               return -EREMOTEIO;
        }
-       if (r < 0)
-               return r;
 
        /* no error */
        if (likely(!dev->cmd_err))
@@ -674,6 +754,10 @@ static int davinci_i2c_probe(struct platform_device *pdev)
                if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency",
                        &prop))
                        dev->pdata->bus_freq = prop / 1000;
+
+               dev->pdata->has_pfunc =
+                       of_property_read_bool(pdev->dev.of_node,
+                                             "ti,has-pfunc");
        } else if (!dev->pdata) {
                dev->pdata = &davinci_i2c_platform_data_default;
        }
@@ -715,6 +799,14 @@ static int davinci_i2c_probe(struct platform_device *pdev)
        adap->timeout = DAVINCI_I2C_TIMEOUT;
        adap->dev.of_node = pdev->dev.of_node;
 
+       if (dev->pdata->has_pfunc)
+               adap->bus_recovery_info = &davinci_i2c_scl_recovery_info;
+       else if (dev->pdata->scl_pin) {
+               adap->bus_recovery_info = &davinci_i2c_gpio_recovery_info;
+               adap->bus_recovery_info->scl_gpio = dev->pdata->scl_pin;
+               adap->bus_recovery_info->sda_gpio = dev->pdata->sda_pin;
+       }
+
        adap->nr = pdev->id;
        r = i2c_add_numbered_adapter(adap);
        if (r) {
index 6e25c010e69037a544ad04f82df46e27e80ca9af..6f19a33773fe79dd4ef27643232b2df1e5bba66b 100644 (file)
@@ -656,8 +656,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        i2c_dw_xfer_init(dev);
 
        /* wait for tx to complete */
-       ret = wait_for_completion_timeout(&dev->cmd_complete, HZ);
-       if (ret == 0) {
+       if (!wait_for_completion_timeout(&dev->cmd_complete, HZ)) {
                dev_err(dev->dev, "controller timed out\n");
                /* i2c_dw_init implicitly disables the adapter */
                i2c_dw_init(dev);
index c270f5f9a8f9af3d3712bbd0f99874708875aa18..fa4e2b521f0d6f7b77951cf442aaa307a1b66109 100644 (file)
@@ -143,10 +143,8 @@ static int dw_i2c_probe(struct platform_device *pdev)
        u32 clk_freq, ht = 0;
 
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(&pdev->dev, "no irq resource?\n");
-               return irq; /* -ENXIO */
-       }
+       if (irq < 0)
+               return irq;
 
        dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL);
        if (!dev)
diff --git a/drivers/i2c/busses/i2c-digicolor.c b/drivers/i2c/busses/i2c-digicolor.c
new file mode 100644 (file)
index 0000000..03f1e55
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ * I2C bus driver for Conexant Digicolor SoCs
+ *
+ * Author: Baruch Siach <baruch@tkos.co.il>
+ *
+ * Copyright (C) 2015 Paradox Innovation Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define DEFAULT_FREQ           100000
+#define TIMEOUT_MS             100
+
+#define II_CONTROL             0x0
+#define II_CONTROL_LOCAL_RESET BIT(0)
+
+#define II_CLOCKTIME           0x1
+
+#define II_COMMAND             0x2
+#define II_CMD_START           1
+#define II_CMD_RESTART         2
+#define II_CMD_SEND_ACK                3
+#define II_CMD_GET_ACK         6
+#define II_CMD_GET_NOACK       7
+#define II_CMD_STOP            10
+#define II_COMMAND_GO          BIT(7)
+#define II_COMMAND_COMPLETION_STATUS(r)        (((r) >> 5) & 3)
+#define II_CMD_STATUS_NORMAL   0
+#define II_CMD_STATUS_ACK_GOOD 1
+#define II_CMD_STATUS_ACK_BAD  2
+#define II_CMD_STATUS_ABORT    3
+
+#define II_DATA                        0x3
+#define II_INTFLAG_CLEAR       0x8
+#define II_INTENABLE           0xa
+
+struct dc_i2c {
+       struct i2c_adapter      adap;
+       struct device           *dev;
+       void __iomem            *regs;
+       struct clk              *clk;
+       unsigned int            frequency;
+
+       struct i2c_msg          *msg;
+       unsigned int            msgbuf_ptr;
+       int                     last;
+       spinlock_t              lock;
+       struct completion       done;
+       int                     state;
+       int                     error;
+};
+
+enum {
+       STATE_IDLE,
+       STATE_START,
+       STATE_ADDR,
+       STATE_WRITE,
+       STATE_READ,
+       STATE_STOP,
+};
+
+static void dc_i2c_cmd(struct dc_i2c *i2c, u8 cmd)
+{
+       writeb_relaxed(cmd | II_COMMAND_GO, i2c->regs + II_COMMAND);
+}
+
+static u8 dc_i2c_addr_cmd(struct i2c_msg *msg)
+{
+       u8 addr = (msg->addr & 0x7f) << 1;
+
+       if (msg->flags & I2C_M_RD)
+               addr |= 1;
+
+       return addr;
+}
+
+static void dc_i2c_data(struct dc_i2c *i2c, u8 data)
+{
+       writeb_relaxed(data, i2c->regs + II_DATA);
+}
+
+static void dc_i2c_write_byte(struct dc_i2c *i2c, u8 byte)
+{
+       dc_i2c_data(i2c, byte);
+       dc_i2c_cmd(i2c, II_CMD_SEND_ACK);
+}
+
+static void dc_i2c_write_buf(struct dc_i2c *i2c)
+{
+       dc_i2c_write_byte(i2c, i2c->msg->buf[i2c->msgbuf_ptr++]);
+}
+
+static void dc_i2c_next_read(struct dc_i2c *i2c)
+{
+       bool last = (i2c->msgbuf_ptr + 1 == i2c->msg->len);
+
+       dc_i2c_cmd(i2c, last ? II_CMD_GET_NOACK : II_CMD_GET_ACK);
+}
+
+static void dc_i2c_stop(struct dc_i2c *i2c)
+{
+       i2c->state = STATE_STOP;
+       if (i2c->last)
+               dc_i2c_cmd(i2c, II_CMD_STOP);
+       else
+               complete(&i2c->done);
+}
+
+static u8 dc_i2c_read_byte(struct dc_i2c *i2c)
+{
+       return readb_relaxed(i2c->regs + II_DATA);
+}
+
+static void dc_i2c_read_buf(struct dc_i2c *i2c)
+{
+       i2c->msg->buf[i2c->msgbuf_ptr++] = dc_i2c_read_byte(i2c);
+       dc_i2c_next_read(i2c);
+}
+
+static void dc_i2c_set_irq(struct dc_i2c *i2c, int enable)
+{
+       if (enable)
+               writeb_relaxed(1, i2c->regs + II_INTFLAG_CLEAR);
+       writeb_relaxed(!!enable, i2c->regs + II_INTENABLE);
+}
+
+static int dc_i2c_cmd_status(struct dc_i2c *i2c)
+{
+       u8 cmd = readb_relaxed(i2c->regs + II_COMMAND);
+
+       return II_COMMAND_COMPLETION_STATUS(cmd);
+}
+
+static void dc_i2c_start_msg(struct dc_i2c *i2c, int first)
+{
+       struct i2c_msg *msg = i2c->msg;
+
+       if (!(msg->flags & I2C_M_NOSTART)) {
+               i2c->state = STATE_START;
+               dc_i2c_cmd(i2c, first ? II_CMD_START : II_CMD_RESTART);
+       } else if (msg->flags & I2C_M_RD) {
+               i2c->state = STATE_READ;
+               dc_i2c_next_read(i2c);
+       } else {
+               i2c->state = STATE_WRITE;
+               dc_i2c_write_buf(i2c);
+       }
+}
+
+static irqreturn_t dc_i2c_irq(int irq, void *dev_id)
+{
+       struct dc_i2c *i2c = dev_id;
+       int cmd_status = dc_i2c_cmd_status(i2c);
+       unsigned long flags;
+       u8 addr_cmd;
+
+       writeb_relaxed(1, i2c->regs + II_INTFLAG_CLEAR);
+
+       spin_lock_irqsave(&i2c->lock, flags);
+
+       if (cmd_status == II_CMD_STATUS_ACK_BAD
+           || cmd_status == II_CMD_STATUS_ABORT) {
+               i2c->error = -EIO;
+               complete(&i2c->done);
+               goto out;
+       }
+
+       switch (i2c->state) {
+       case STATE_START:
+               addr_cmd = dc_i2c_addr_cmd(i2c->msg);
+               dc_i2c_write_byte(i2c, addr_cmd);
+               i2c->state = STATE_ADDR;
+               break;
+       case STATE_ADDR:
+               if (i2c->msg->flags & I2C_M_RD) {
+                       dc_i2c_next_read(i2c);
+                       i2c->state = STATE_READ;
+                       break;
+               }
+               i2c->state = STATE_WRITE;
+               /* fall through */
+       case STATE_WRITE:
+               if (i2c->msgbuf_ptr < i2c->msg->len)
+                       dc_i2c_write_buf(i2c);
+               else
+                       dc_i2c_stop(i2c);
+               break;
+       case STATE_READ:
+               if (i2c->msgbuf_ptr < i2c->msg->len)
+                       dc_i2c_read_buf(i2c);
+               else
+                       dc_i2c_stop(i2c);
+               break;
+       case STATE_STOP:
+               i2c->state = STATE_IDLE;
+               complete(&i2c->done);
+               break;
+       }
+
+out:
+       spin_unlock_irqrestore(&i2c->lock, flags);
+       return IRQ_HANDLED;
+}
+
+static int dc_i2c_xfer_msg(struct dc_i2c *i2c, struct i2c_msg *msg, int first,
+                          int last)
+{
+       unsigned long timeout = msecs_to_jiffies(TIMEOUT_MS);
+       unsigned long flags;
+
+       spin_lock_irqsave(&i2c->lock, flags);
+       i2c->msg = msg;
+       i2c->msgbuf_ptr = 0;
+       i2c->last = last;
+       i2c->error = 0;
+
+       reinit_completion(&i2c->done);
+       dc_i2c_set_irq(i2c, 1);
+       dc_i2c_start_msg(i2c, first);
+       spin_unlock_irqrestore(&i2c->lock, flags);
+
+       timeout = wait_for_completion_timeout(&i2c->done, timeout);
+       dc_i2c_set_irq(i2c, 0);
+       if (timeout == 0) {
+               i2c->state = STATE_IDLE;
+               return -ETIMEDOUT;
+       }
+
+       if (i2c->error)
+               return i2c->error;
+
+       return 0;
+}
+
+static int dc_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+       struct dc_i2c *i2c = adap->algo_data;
+       int i, ret;
+
+       for (i = 0; i < num; i++) {
+               ret = dc_i2c_xfer_msg(i2c, &msgs[i], i == 0, i == num - 1);
+               if (ret)
+                       return ret;
+       }
+
+       return num;
+}
+
+static int dc_i2c_init_hw(struct dc_i2c *i2c)
+{
+       unsigned long clk_rate = clk_get_rate(i2c->clk);
+       unsigned int clocktime;
+
+       writeb_relaxed(II_CONTROL_LOCAL_RESET, i2c->regs + II_CONTROL);
+       udelay(100);
+       writeb_relaxed(0, i2c->regs + II_CONTROL);
+       udelay(100);
+
+       clocktime = DIV_ROUND_UP(clk_rate, 64 * i2c->frequency);
+       if (clocktime < 1 || clocktime > 0xff) {
+               dev_err(i2c->dev, "can't set bus speed of %u Hz\n",
+                       i2c->frequency);
+               return -EINVAL;
+       }
+       writeb_relaxed(clocktime - 1, i2c->regs + II_CLOCKTIME);
+
+       return 0;
+}
+
+static u32 dc_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART;
+}
+
+static const struct i2c_algorithm dc_i2c_algorithm = {
+       .master_xfer    = dc_i2c_xfer,
+       .functionality  = dc_i2c_func,
+};
+
+static int dc_i2c_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct dc_i2c *i2c;
+       struct resource *r;
+       int ret = 0, irq;
+
+       i2c = devm_kzalloc(&pdev->dev, sizeof(struct dc_i2c), GFP_KERNEL);
+       if (!i2c)
+               return -ENOMEM;
+
+       if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+                                &i2c->frequency))
+               i2c->frequency = DEFAULT_FREQ;
+
+       i2c->dev = &pdev->dev;
+       platform_set_drvdata(pdev, i2c);
+
+       spin_lock_init(&i2c->lock);
+       init_completion(&i2c->done);
+
+       i2c->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(i2c->clk))
+               return PTR_ERR(i2c->clk);
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       i2c->regs = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(i2c->regs))
+               return PTR_ERR(i2c->regs);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+
+       ret = devm_request_irq(&pdev->dev, irq, dc_i2c_irq, 0,
+                              dev_name(&pdev->dev), i2c);
+       if (ret < 0)
+               return ret;
+
+       strlcpy(i2c->adap.name, "Conexant Digicolor I2C adapter",
+               sizeof(i2c->adap.name));
+       i2c->adap.owner = THIS_MODULE;
+       i2c->adap.algo = &dc_i2c_algorithm;
+       i2c->adap.dev.parent = &pdev->dev;
+       i2c->adap.dev.of_node = np;
+       i2c->adap.algo_data = i2c;
+
+       ret = dc_i2c_init_hw(i2c);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(i2c->clk);
+       if (ret < 0)
+               return ret;
+
+       ret = i2c_add_adapter(&i2c->adap);
+       if (ret < 0) {
+               clk_unprepare(i2c->clk);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int dc_i2c_remove(struct platform_device *pdev)
+{
+       struct dc_i2c *i2c = platform_get_drvdata(pdev);
+
+       i2c_del_adapter(&i2c->adap);
+       clk_disable_unprepare(i2c->clk);
+
+       return 0;
+}
+
+static const struct of_device_id dc_i2c_match[] = {
+       { .compatible = "cnxt,cx92755-i2c" },
+       { },
+};
+
+static struct platform_driver dc_i2c_driver = {
+       .probe   = dc_i2c_probe,
+       .remove  = dc_i2c_remove,
+       .driver  = {
+               .name  = "digicolor-i2c",
+               .of_match_table = dc_i2c_match,
+       },
+};
+module_platform_driver(dc_i2c_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("Conexant Digicolor I2C master driver");
+MODULE_LICENSE("GPL v2");
index b3fb86af4cbb14d0cf75cfbc90e53b53382eab9b..1600edd57ce9d7d9a78adaf5daaaad46a4469b2b 100644 (file)
@@ -144,7 +144,6 @@ static int dln2_i2c_xfer(struct i2c_adapter *adapter,
 {
        struct dln2_i2c *dln2 = i2c_get_adapdata(adapter);
        struct i2c_msg *pmsg;
-       struct device *dev = &dln2->adapter.dev;
        int i;
 
        for (i = 0; i < num; i++) {
@@ -152,11 +151,6 @@ static int dln2_i2c_xfer(struct i2c_adapter *adapter,
 
                pmsg = &msgs[i];
 
-               if (pmsg->len > DLN2_I2C_MAX_XFER_SIZE) {
-                       dev_warn(dev, "maximum transfer size exceeded\n");
-                       return -EOPNOTSUPP;
-               }
-
                if (pmsg->flags & I2C_M_RD) {
                        ret = dln2_i2c_read(dln2, pmsg->addr, pmsg->buf,
                                            pmsg->len);
@@ -187,6 +181,11 @@ static const struct i2c_algorithm dln2_i2c_usb_algorithm = {
        .functionality = dln2_i2c_func,
 };
 
+static struct i2c_adapter_quirks dln2_i2c_quirks = {
+       .max_read_len = DLN2_I2C_MAX_XFER_SIZE,
+       .max_write_len = DLN2_I2C_MAX_XFER_SIZE,
+};
+
 static int dln2_i2c_probe(struct platform_device *pdev)
 {
        int ret;
@@ -209,7 +208,9 @@ static int dln2_i2c_probe(struct platform_device *pdev)
        dln2->adapter.owner = THIS_MODULE;
        dln2->adapter.class = I2C_CLASS_HWMON;
        dln2->adapter.algo = &dln2_i2c_usb_algorithm;
+       dln2->adapter.quirks = &dln2_i2c_quirks;
        dln2->adapter.dev.parent = dev;
+       dln2->adapter.dev.of_node = dev->of_node;
        i2c_set_adapdata(&dln2->adapter, dln2);
        snprintf(dln2->adapter.name, sizeof(dln2->adapter.name), "%s-%s-%d",
                 "dln2-i2c", dev_name(pdev->dev.parent), dln2->port);
index 8fafb254e42a5583b46906ff884369882b6cf83b..5ecbb3fdc27ee2c0c8c87e35cc4aa08d9621bb3f 100644 (file)
@@ -223,8 +223,6 @@ struct i801_priv {
 #endif
 };
 
-static struct pci_driver i801_driver;
-
 #define FEATURE_SMBUS_PEC      (1 << 0)
 #define FEATURE_BLOCK_BUFFER   (1 << 1)
 #define FEATURE_BLOCK_PROC     (1 << 2)
@@ -1140,7 +1138,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
        int err, i;
        struct i801_priv *priv;
 
-       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
@@ -1182,34 +1180,35 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
        }
        priv->features &= ~disable_features;
 
-       err = pci_enable_device(dev);
+       err = pcim_enable_device(dev);
        if (err) {
                dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
                        err);
-               goto exit;
+               return err;
        }
+       pcim_pin_device(dev);
 
        /* Determine the address of the SMBus area */
        priv->smba = pci_resource_start(dev, SMBBAR);
        if (!priv->smba) {
-               dev_err(&dev->dev, "SMBus base address uninitialized, "
-                       "upgrade BIOS\n");
-               err = -ENODEV;
-               goto exit;
+               dev_err(&dev->dev,
+                       "SMBus base address uninitialized, upgrade BIOS\n");
+               return -ENODEV;
        }
 
        err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
        if (err) {
-               err = -ENODEV;
-               goto exit;
+               return -ENODEV;
        }
 
-       err = pci_request_region(dev, SMBBAR, i801_driver.name);
+       err = pcim_iomap_regions(dev, 1 << SMBBAR,
+                                dev_driver_string(&dev->dev));
        if (err) {
-               dev_err(&dev->dev, "Failed to request SMBus region "
-                       "0x%lx-0x%Lx\n", priv->smba,
+               dev_err(&dev->dev,
+                       "Failed to request SMBus region 0x%lx-0x%Lx\n",
+                       priv->smba,
                        (unsigned long long)pci_resource_end(dev, SMBBAR));
-               goto exit;
+               return err;
        }
 
        pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &temp);
@@ -1254,8 +1253,9 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
        if (priv->features & FEATURE_IRQ) {
                init_waitqueue_head(&priv->waitq);
 
-               err = request_irq(dev->irq, i801_isr, IRQF_SHARED,
-                                 i801_driver.name, priv);
+               err = devm_request_irq(&dev->dev, dev->irq, i801_isr,
+                                      IRQF_SHARED,
+                                      dev_driver_string(&dev->dev), priv);
                if (err) {
                        dev_err(&dev->dev, "Failed to allocate irq %d: %d\n",
                                dev->irq, err);
@@ -1276,7 +1276,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
        err = i2c_add_adapter(&priv->adapter);
        if (err) {
                dev_err(&dev->dev, "Failed to add SMBus adapter\n");
-               goto exit_free_irq;
+               return err;
        }
 
        i801_probe_optional_slaves(priv);
@@ -1286,14 +1286,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
        pci_set_drvdata(dev, priv);
 
        return 0;
-
-exit_free_irq:
-       if (priv->features & FEATURE_IRQ)
-               free_irq(dev->irq, priv);
-       pci_release_region(dev, SMBBAR);
-exit:
-       kfree(priv);
-       return err;
 }
 
 static void i801_remove(struct pci_dev *dev)
@@ -1304,11 +1296,6 @@ static void i801_remove(struct pci_dev *dev)
        i2c_del_adapter(&priv->adapter);
        pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
 
-       if (priv->features & FEATURE_IRQ)
-               free_irq(dev->irq, priv);
-       pci_release_region(dev, SMBBAR);
-
-       kfree(priv);
        /*
         * do not call pci_disable_device(dev) since it can cause hard hangs on
         * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
@@ -1330,7 +1317,7 @@ static int i801_resume(struct pci_dev *dev)
 {
        pci_set_power_state(dev, PCI_D0);
        pci_restore_state(dev);
-       return pci_enable_device(dev);
+       return 0;
 }
 #else
 #define i801_suspend NULL
index 0fcc1694c6072a39bf8711999f65c5b1601daebd..00ffd661368069ab24e4d67ab2abcecd06333ab0 100644 (file)
@@ -988,15 +988,16 @@ out:
 static int img_i2c_reset_bus(struct img_i2c *i2c)
 {
        unsigned long flags;
-       int ret;
+       unsigned long time_left;
 
        spin_lock_irqsave(&i2c->lock, flags);
        reinit_completion(&i2c->msg_complete);
        img_i2c_reset_start(i2c);
        spin_unlock_irqrestore(&i2c->lock, flags);
 
-       ret = wait_for_completion_timeout(&i2c->msg_complete, IMG_I2C_TIMEOUT);
-       if (ret == 0)
+       time_left = wait_for_completion_timeout(&i2c->msg_complete,
+                                             IMG_I2C_TIMEOUT);
+       if (time_left == 0)
                return -ETIMEDOUT;
        return 0;
 }
@@ -1007,6 +1008,7 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
        struct img_i2c *i2c = i2c_get_adapdata(adap);
        bool atomic = false;
        int i, ret;
+       unsigned long time_left;
 
        if (i2c->mode == MODE_SUSPEND) {
                WARN(1, "refusing to service transaction in suspended state\n");
@@ -1068,11 +1070,11 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
                        img_i2c_write(i2c);
                spin_unlock_irqrestore(&i2c->lock, flags);
 
-               ret = wait_for_completion_timeout(&i2c->msg_complete,
-                                                 IMG_I2C_TIMEOUT);
+               time_left = wait_for_completion_timeout(&i2c->msg_complete,
+                                                     IMG_I2C_TIMEOUT);
                del_timer_sync(&i2c->check_timer);
 
-               if (ret == 0) {
+               if (time_left == 0) {
                        dev_err(adap->dev.parent, "i2c transfer timed out\n");
                        i2c->msg_status = -ETIMEDOUT;
                        break;
index d7b26fc6f432005bb02a2394fd4bfb6720271ab1..a53a7dd6694545c2fce0d522a1129f8993babad0 100644 (file)
@@ -601,6 +601,7 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
                                        struct i2c_msg *msgs)
 {
        int result;
+       unsigned long time_left;
        unsigned int temp = 0;
        unsigned long orig_jiffies = jiffies;
        struct imx_i2c_dma *dma = i2c_imx->dma;
@@ -624,10 +625,10 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
         */
        imx_i2c_write_reg(msgs->addr << 1, i2c_imx, IMX_I2C_I2DR);
        reinit_completion(&i2c_imx->dma->cmd_complete);
-       result = wait_for_completion_timeout(
+       time_left = wait_for_completion_timeout(
                                &i2c_imx->dma->cmd_complete,
                                msecs_to_jiffies(DMA_TIMEOUT));
-       if (result == 0) {
+       if (time_left == 0) {
                dmaengine_terminate_all(dma->chan_using);
                return -ETIMEDOUT;
        }
@@ -663,6 +664,7 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
                        struct i2c_msg *msgs, bool is_lastmsg)
 {
        int result;
+       unsigned long time_left;
        unsigned int temp;
        unsigned long orig_jiffies = jiffies;
        struct imx_i2c_dma *dma = i2c_imx->dma;
@@ -682,10 +684,10 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
                return result;
 
        reinit_completion(&i2c_imx->dma->cmd_complete);
-       result = wait_for_completion_timeout(
+       time_left = wait_for_completion_timeout(
                                &i2c_imx->dma->cmd_complete,
                                msecs_to_jiffies(DMA_TIMEOUT));
-       if (result == 0) {
+       if (time_left == 0) {
                dmaengine_terminate_all(dma->chan_using);
                return -ETIMEDOUT;
        }
index f2b0ff011631c9e920e042a1ec79b0b98126eb5b..f994712d0904733782e6804c20bd7ad47eaffb94 100644 (file)
@@ -380,6 +380,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
                       int size, union i2c_smbus_data *data)
 {
        int ret;
+       unsigned long time_left;
        dma_addr_t dma_addr = 0; /* address of the data buffer */
        u8 dma_size = 0;
        enum dma_data_direction dma_direction = 0;
@@ -578,13 +579,13 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
        ismt_submit_desc(priv);
 
        /* Now we wait for interrupt completion, 1s */
-       ret = wait_for_completion_timeout(&priv->cmp, HZ*1);
+       time_left = wait_for_completion_timeout(&priv->cmp, HZ*1);
 
        /* unmap the data buffer */
        if (dma_size != 0)
                dma_unmap_single(&adap->dev, dma_addr, dma_size, dma_direction);
 
-       if (unlikely(!ret)) {
+       if (unlikely(!time_left)) {
                dev_err(dev, "completion wait timed out\n");
                ret = -ETIMEDOUT;
                goto out;
diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c
new file mode 100644 (file)
index 0000000..ce1d693
--- /dev/null
@@ -0,0 +1,832 @@
+/*
+ * Ingenic JZ4780 I2C bus driver
+ *
+ * Copyright (C) 2006 - 2009 Ingenic Semiconductor Inc.
+ * Copyright (C) 2015 Imagination Technologies
+ *
+ * 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/bitops.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+
+#define JZ4780_I2C_CTRL                0x00
+#define JZ4780_I2C_TAR         0x04
+#define JZ4780_I2C_SAR         0x08
+#define JZ4780_I2C_DC          0x10
+#define JZ4780_I2C_SHCNT       0x14
+#define JZ4780_I2C_SLCNT       0x18
+#define JZ4780_I2C_FHCNT       0x1C
+#define JZ4780_I2C_FLCNT       0x20
+#define JZ4780_I2C_INTST       0x2C
+#define JZ4780_I2C_INTM                0x30
+#define JZ4780_I2C_RXTL                0x38
+#define JZ4780_I2C_TXTL                0x3C
+#define JZ4780_I2C_CINTR       0x40
+#define JZ4780_I2C_CRXUF       0x44
+#define JZ4780_I2C_CRXOF       0x48
+#define JZ4780_I2C_CTXOF       0x4C
+#define JZ4780_I2C_CRXREQ      0x50
+#define JZ4780_I2C_CTXABRT     0x54
+#define JZ4780_I2C_CRXDONE     0x58
+#define JZ4780_I2C_CACT                0x5C
+#define JZ4780_I2C_CSTP                0x60
+#define JZ4780_I2C_CSTT                0x64
+#define JZ4780_I2C_CGC         0x68
+#define JZ4780_I2C_ENB         0x6C
+#define JZ4780_I2C_STA         0x70
+#define JZ4780_I2C_TXABRT      0x80
+#define JZ4780_I2C_DMACR       0x88
+#define JZ4780_I2C_DMATDLR     0x8C
+#define JZ4780_I2C_DMARDLR     0x90
+#define JZ4780_I2C_SDASU       0x94
+#define JZ4780_I2C_ACKGC       0x98
+#define JZ4780_I2C_ENSTA       0x9C
+#define JZ4780_I2C_SDAHD       0xD0
+
+#define JZ4780_I2C_CTRL_STPHLD         BIT(7)
+#define JZ4780_I2C_CTRL_SLVDIS         BIT(6)
+#define JZ4780_I2C_CTRL_REST           BIT(5)
+#define JZ4780_I2C_CTRL_MATP           BIT(4)
+#define JZ4780_I2C_CTRL_SATP           BIT(3)
+#define JZ4780_I2C_CTRL_SPDF           BIT(2)
+#define JZ4780_I2C_CTRL_SPDS           BIT(1)
+#define JZ4780_I2C_CTRL_MD             BIT(0)
+
+#define JZ4780_I2C_STA_SLVACT          BIT(6)
+#define JZ4780_I2C_STA_MSTACT          BIT(5)
+#define JZ4780_I2C_STA_RFF             BIT(4)
+#define JZ4780_I2C_STA_RFNE            BIT(3)
+#define JZ4780_I2C_STA_TFE             BIT(2)
+#define JZ4780_I2C_STA_TFNF            BIT(1)
+#define JZ4780_I2C_STA_ACT             BIT(0)
+
+static const char * const jz4780_i2c_abrt_src[] = {
+       "ABRT_7B_ADDR_NOACK",
+       "ABRT_10ADDR1_NOACK",
+       "ABRT_10ADDR2_NOACK",
+       "ABRT_XDATA_NOACK",
+       "ABRT_GCALL_NOACK",
+       "ABRT_GCALL_READ",
+       "ABRT_HS_ACKD",
+       "SBYTE_ACKDET",
+       "ABRT_HS_NORSTRT",
+       "SBYTE_NORSTRT",
+       "ABRT_10B_RD_NORSTRT",
+       "ABRT_MASTER_DIS",
+       "ARB_LOST",
+       "SLVFLUSH_TXFIFO",
+       "SLV_ARBLOST",
+       "SLVRD_INTX",
+};
+
+#define JZ4780_I2C_INTST_IGC           BIT(11)
+#define JZ4780_I2C_INTST_ISTT          BIT(10)
+#define JZ4780_I2C_INTST_ISTP          BIT(9)
+#define JZ4780_I2C_INTST_IACT          BIT(8)
+#define JZ4780_I2C_INTST_RXDN          BIT(7)
+#define JZ4780_I2C_INTST_TXABT         BIT(6)
+#define JZ4780_I2C_INTST_RDREQ         BIT(5)
+#define JZ4780_I2C_INTST_TXEMP         BIT(4)
+#define JZ4780_I2C_INTST_TXOF          BIT(3)
+#define JZ4780_I2C_INTST_RXFL          BIT(2)
+#define JZ4780_I2C_INTST_RXOF          BIT(1)
+#define JZ4780_I2C_INTST_RXUF          BIT(0)
+
+#define JZ4780_I2C_INTM_MIGC           BIT(11)
+#define JZ4780_I2C_INTM_MISTT          BIT(10)
+#define JZ4780_I2C_INTM_MISTP          BIT(9)
+#define JZ4780_I2C_INTM_MIACT          BIT(8)
+#define JZ4780_I2C_INTM_MRXDN          BIT(7)
+#define JZ4780_I2C_INTM_MTXABT         BIT(6)
+#define JZ4780_I2C_INTM_MRDREQ         BIT(5)
+#define JZ4780_I2C_INTM_MTXEMP         BIT(4)
+#define JZ4780_I2C_INTM_MTXOF          BIT(3)
+#define JZ4780_I2C_INTM_MRXFL          BIT(2)
+#define JZ4780_I2C_INTM_MRXOF          BIT(1)
+#define JZ4780_I2C_INTM_MRXUF          BIT(0)
+
+#define JZ4780_I2C_DC_READ             BIT(8)
+
+#define JZ4780_I2C_SDAHD_HDENB         BIT(8)
+
+#define JZ4780_I2C_ENB_I2C             BIT(0)
+
+#define JZ4780_I2CSHCNT_ADJUST(n)      (((n) - 8) < 6 ? 6 : ((n) - 8))
+#define JZ4780_I2CSLCNT_ADJUST(n)      (((n) - 1) < 8 ? 8 : ((n) - 1))
+#define JZ4780_I2CFHCNT_ADJUST(n)      (((n) - 8) < 6 ? 6 : ((n) - 8))
+#define JZ4780_I2CFLCNT_ADJUST(n)      (((n) - 1) < 8 ? 8 : ((n) - 1))
+
+#define JZ4780_I2C_FIFO_LEN    16
+#define TX_LEVEL               3
+#define RX_LEVEL               (JZ4780_I2C_FIFO_LEN - TX_LEVEL - 1)
+
+#define JZ4780_I2C_TIMEOUT     300
+
+#define BUFSIZE 200
+
+struct jz4780_i2c {
+       void __iomem            *iomem;
+       int                      irq;
+       struct clk              *clk;
+       struct i2c_adapter       adap;
+
+       /* lock to protect rbuf and wbuf between xfer_rd/wr and irq handler */
+       spinlock_t              lock;
+
+       /* beginning of lock scope */
+       unsigned char           *rbuf;
+       int                     rd_total_len;
+       int                     rd_data_xfered;
+       int                     rd_cmd_xfered;
+
+       unsigned char           *wbuf;
+       int                     wt_len;
+
+       int                     is_write;
+       int                     stop_hold;
+       int                     speed;
+
+       int                     data_buf[BUFSIZE];
+       int                     cmd_buf[BUFSIZE];
+       int                     cmd;
+
+       /* end of lock scope */
+       struct completion       trans_waitq;
+};
+
+static inline unsigned short jz4780_i2c_readw(struct jz4780_i2c *i2c,
+                                             unsigned long offset)
+{
+       return readw(i2c->iomem + offset);
+}
+
+static inline void jz4780_i2c_writew(struct jz4780_i2c *i2c,
+                                    unsigned long offset, unsigned short val)
+{
+       writew(val, i2c->iomem + offset);
+}
+
+static int jz4780_i2c_disable(struct jz4780_i2c *i2c)
+{
+       unsigned short regval;
+       unsigned long loops = 5;
+
+       jz4780_i2c_writew(i2c, JZ4780_I2C_ENB, 0);
+
+       do {
+               regval = jz4780_i2c_readw(i2c, JZ4780_I2C_ENSTA);
+               if (!(regval & JZ4780_I2C_ENB_I2C))
+                       return 0;
+
+               usleep_range(5000, 15000);
+       } while (--loops);
+
+       dev_err(&i2c->adap.dev, "disable failed: ENSTA=0x%04x\n", regval);
+       return -ETIMEDOUT;
+}
+
+static int jz4780_i2c_enable(struct jz4780_i2c *i2c)
+{
+       unsigned short regval;
+       unsigned long loops = 5;
+
+       jz4780_i2c_writew(i2c, JZ4780_I2C_ENB, 1);
+
+       do {
+               regval = jz4780_i2c_readw(i2c, JZ4780_I2C_ENSTA);
+               if (regval & JZ4780_I2C_ENB_I2C)
+                       return 0;
+
+               usleep_range(5000, 15000);
+       } while (--loops);
+
+       dev_err(&i2c->adap.dev, "enable failed: ENSTA=0x%04x\n", regval);
+       return -ETIMEDOUT;
+}
+
+static int jz4780_i2c_set_target(struct jz4780_i2c *i2c, unsigned char address)
+{
+       unsigned short regval;
+       unsigned long loops = 5;
+
+       do {
+               regval = jz4780_i2c_readw(i2c, JZ4780_I2C_STA);
+               if ((regval & JZ4780_I2C_STA_TFE) &&
+                   !(regval & JZ4780_I2C_STA_MSTACT))
+                       break;
+
+               usleep_range(5000, 15000);
+       } while (--loops);
+
+       if (loops) {
+               jz4780_i2c_writew(i2c, JZ4780_I2C_TAR, address);
+               return 0;
+       }
+
+       dev_err(&i2c->adap.dev,
+               "set device to address 0x%02x failed, STA=0x%04x\n",
+               address, regval);
+
+       return -ENXIO;
+}
+
+static int jz4780_i2c_set_speed(struct jz4780_i2c *i2c)
+{
+       int dev_clk_khz = clk_get_rate(i2c->clk) / 1000;
+       int cnt_high = 0;       /* HIGH period count of the SCL clock */
+       int cnt_low = 0;        /* LOW period count of the SCL clock */
+       int cnt_period = 0;     /* period count of the SCL clock */
+       int setup_time = 0;
+       int hold_time = 0;
+       unsigned short tmp = 0;
+       int i2c_clk = i2c->speed;
+
+       if (jz4780_i2c_disable(i2c))
+               dev_dbg(&i2c->adap.dev, "i2c not disabled\n");
+
+       /*
+        * 1 JZ4780_I2C cycle equals to cnt_period PCLK(i2c_clk)
+        * standard mode, min LOW and HIGH period are 4700 ns and 4000 ns
+        * fast mode, min LOW and HIGH period are 1300 ns and 600 ns
+        */
+       cnt_period = dev_clk_khz / i2c_clk;
+
+       if (i2c_clk <= 100)
+               cnt_high = (cnt_period * 4000) / (4700 + 4000);
+       else
+               cnt_high = (cnt_period * 600) / (1300 + 600);
+
+       cnt_low = cnt_period - cnt_high;
+
+       /*
+        * NOTE: JZ4780_I2C_CTRL_REST can't set when i2c enabled, because
+        * normal read are 2 messages, we cannot disable i2c controller
+        * between these two messages, this means that we must always set
+        * JZ4780_I2C_CTRL_REST when init JZ4780_I2C_CTRL
+        *
+        */
+       if (i2c_clk <= 100) {
+               tmp = JZ4780_I2C_CTRL_SPDS | JZ4780_I2C_CTRL_REST
+                     | JZ4780_I2C_CTRL_SLVDIS | JZ4780_I2C_CTRL_MD;
+               jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
+
+               jz4780_i2c_writew(i2c, JZ4780_I2C_SHCNT,
+                                 JZ4780_I2CSHCNT_ADJUST(cnt_high));
+               jz4780_i2c_writew(i2c, JZ4780_I2C_SLCNT,
+                                 JZ4780_I2CSLCNT_ADJUST(cnt_low));
+       } else {
+               tmp = JZ4780_I2C_CTRL_SPDF | JZ4780_I2C_CTRL_REST
+                     | JZ4780_I2C_CTRL_SLVDIS | JZ4780_I2C_CTRL_MD;
+               jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
+
+               jz4780_i2c_writew(i2c, JZ4780_I2C_FHCNT,
+                                 JZ4780_I2CFHCNT_ADJUST(cnt_high));
+               jz4780_i2c_writew(i2c, JZ4780_I2C_FLCNT,
+                                 JZ4780_I2CFLCNT_ADJUST(cnt_low));
+       }
+
+       /*
+        * a i2c device must internally provide a hold time at least 300ns
+        * tHD:DAT
+        *      Standard Mode: min=300ns, max=3450ns
+        *      Fast Mode: min=0ns, max=900ns
+        * tSU:DAT
+        *      Standard Mode: min=250ns, max=infinite
+        *      Fast Mode: min=100(250ns is recommended), max=infinite
+        *
+        * 1i2c_clk = 10^6 / dev_clk_khz
+        * on FPGA, dev_clk_khz = 12000, so 1i2c_clk = 1000/12 = 83ns
+        * on Pisces(1008M), dev_clk_khz=126000, so 1i2c_clk = 1000 / 126 = 8ns
+        *
+        * The actual hold time is (SDAHD + 1) * (i2c_clk period).
+        *
+        * Length of setup time calculated using (SDASU - 1) * (ic_clk_period)
+        *
+        */
+       if (i2c_clk <= 100) { /* standard mode */
+               setup_time = 300;
+               hold_time = 400;
+       } else {
+               setup_time = 450;
+               hold_time = 450;
+       }
+
+       hold_time = ((hold_time * dev_clk_khz) / 1000000) - 1;
+       setup_time = ((setup_time * dev_clk_khz) / 1000000)  + 1;
+
+       if (setup_time > 255)
+               setup_time = 255;
+
+       if (setup_time <= 0)
+               setup_time = 1;
+
+       jz4780_i2c_writew(i2c, JZ4780_I2C_SDASU, setup_time);
+
+       if (hold_time > 255)
+               hold_time = 255;
+
+       if (hold_time >= 0) {
+               /*i2c hold time enable */
+               hold_time |= JZ4780_I2C_SDAHD_HDENB;
+               jz4780_i2c_writew(i2c, JZ4780_I2C_SDAHD, hold_time);
+       } else {
+               /* disable hold time */
+               jz4780_i2c_writew(i2c, JZ4780_I2C_SDAHD, 0);
+       }
+
+       return 0;
+}
+
+static int jz4780_i2c_cleanup(struct jz4780_i2c *i2c)
+{
+       int ret;
+       unsigned long flags;
+       unsigned short tmp;
+
+       spin_lock_irqsave(&i2c->lock, flags);
+
+       /* can send stop now if need */
+       tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
+       tmp &= ~JZ4780_I2C_CTRL_STPHLD;
+       jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
+
+       /* disable all interrupts first */
+       jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, 0);
+
+       /* then clear all interrupts */
+       jz4780_i2c_readw(i2c, JZ4780_I2C_CTXABRT);
+       jz4780_i2c_readw(i2c, JZ4780_I2C_CINTR);
+
+       /* then disable the controller */
+       tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
+       tmp &= ~JZ4780_I2C_ENB_I2C;
+       jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
+       udelay(10);
+       tmp |= JZ4780_I2C_ENB_I2C;
+       jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
+
+       spin_unlock_irqrestore(&i2c->lock, flags);
+
+       ret = jz4780_i2c_disable(i2c);
+       if (ret)
+               dev_err(&i2c->adap.dev,
+                       "unable to disable device during cleanup!\n");
+
+       if (unlikely(jz4780_i2c_readw(i2c, JZ4780_I2C_INTM)
+                    & jz4780_i2c_readw(i2c, JZ4780_I2C_INTST)))
+               dev_err(&i2c->adap.dev,
+                       "device has interrupts after a complete cleanup!\n");
+
+       return ret;
+}
+
+static int jz4780_i2c_prepare(struct jz4780_i2c *i2c)
+{
+       jz4780_i2c_set_speed(i2c);
+       return jz4780_i2c_enable(i2c);
+}
+
+static void jz4780_i2c_send_rcmd(struct jz4780_i2c *i2c, int cmd_count)
+{
+       int i;
+
+       for (i = 0; i < cmd_count; i++)
+               jz4780_i2c_writew(i2c, JZ4780_I2C_DC, JZ4780_I2C_DC_READ);
+}
+
+static void jz4780_i2c_trans_done(struct jz4780_i2c *i2c)
+{
+       jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, 0);
+       complete(&i2c->trans_waitq);
+}
+
+static irqreturn_t jz4780_i2c_irq(int irqno, void *dev_id)
+{
+       unsigned short tmp;
+       unsigned short intst;
+       unsigned short intmsk;
+       struct jz4780_i2c *i2c = dev_id;
+       unsigned long flags;
+
+       spin_lock_irqsave(&i2c->lock, flags);
+       intmsk = jz4780_i2c_readw(i2c, JZ4780_I2C_INTM);
+       intst = jz4780_i2c_readw(i2c, JZ4780_I2C_INTST);
+
+       intst &= intmsk;
+
+       if (intst & JZ4780_I2C_INTST_TXABT) {
+               jz4780_i2c_trans_done(i2c);
+               goto done;
+       }
+
+       if (intst & JZ4780_I2C_INTST_RXOF) {
+               dev_dbg(&i2c->adap.dev, "received fifo overflow!\n");
+               jz4780_i2c_trans_done(i2c);
+               goto done;
+       }
+
+       /*
+        * When reading, always drain RX FIFO before we send more Read
+        * Commands to avoid fifo overrun
+        */
+       if (i2c->is_write == 0) {
+               int rd_left;
+
+               while ((jz4780_i2c_readw(i2c, JZ4780_I2C_STA)
+                                 & JZ4780_I2C_STA_RFNE)) {
+                       *(i2c->rbuf++) = jz4780_i2c_readw(i2c, JZ4780_I2C_DC)
+                                        & 0xff;
+                       i2c->rd_data_xfered++;
+                       if (i2c->rd_data_xfered == i2c->rd_total_len) {
+                               jz4780_i2c_trans_done(i2c);
+                               goto done;
+                       }
+               }
+
+               rd_left = i2c->rd_total_len - i2c->rd_data_xfered;
+
+               if (rd_left <= JZ4780_I2C_FIFO_LEN)
+                       jz4780_i2c_writew(i2c, JZ4780_I2C_RXTL, rd_left - 1);
+       }
+
+       if (intst & JZ4780_I2C_INTST_TXEMP) {
+               if (i2c->is_write == 0) {
+                       int cmd_left = i2c->rd_total_len - i2c->rd_cmd_xfered;
+                       int max_send = (JZ4780_I2C_FIFO_LEN - 1)
+                                        - (i2c->rd_cmd_xfered
+                                        - i2c->rd_data_xfered);
+                       int cmd_to_send = min(cmd_left, max_send);
+
+                       if (i2c->rd_cmd_xfered != 0)
+                               cmd_to_send = min(cmd_to_send,
+                                                 JZ4780_I2C_FIFO_LEN
+                                                 - TX_LEVEL - 1);
+
+                       if (cmd_to_send) {
+                               jz4780_i2c_send_rcmd(i2c, cmd_to_send);
+                               i2c->rd_cmd_xfered += cmd_to_send;
+                       }
+
+                       cmd_left = i2c->rd_total_len - i2c->rd_cmd_xfered;
+                       if (cmd_left == 0) {
+                               intmsk = jz4780_i2c_readw(i2c, JZ4780_I2C_INTM);
+                               intmsk &= ~JZ4780_I2C_INTM_MTXEMP;
+                               jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, intmsk);
+
+                               tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
+                               tmp &= ~JZ4780_I2C_CTRL_STPHLD;
+                               jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
+                       }
+               } else {
+                       unsigned short data;
+                       unsigned short i2c_sta;
+
+                       i2c_sta = jz4780_i2c_readw(i2c, JZ4780_I2C_STA);
+
+                       while ((i2c_sta & JZ4780_I2C_STA_TFNF) &&
+                              (i2c->wt_len > 0)) {
+                               i2c_sta = jz4780_i2c_readw(i2c, JZ4780_I2C_STA);
+                               data = *i2c->wbuf;
+                               data &= ~JZ4780_I2C_DC_READ;
+                               jz4780_i2c_writew(i2c, JZ4780_I2C_DC,
+                                                 data);
+                               i2c->wbuf++;
+                               i2c->wt_len--;
+                       }
+
+                       if (i2c->wt_len == 0) {
+                               if (!i2c->stop_hold) {
+                                       tmp = jz4780_i2c_readw(i2c,
+                                                              JZ4780_I2C_CTRL);
+                                       tmp &= ~JZ4780_I2C_CTRL_STPHLD;
+                                       jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL,
+                                                         tmp);
+                               }
+
+                               jz4780_i2c_trans_done(i2c);
+                               goto done;
+                       }
+               }
+       }
+
+done:
+       spin_unlock_irqrestore(&i2c->lock, flags);
+       return IRQ_HANDLED;
+}
+
+static void jz4780_i2c_txabrt(struct jz4780_i2c *i2c, int src)
+{
+       int i;
+
+       dev_err(&i2c->adap.dev, "txabrt: 0x%08x\n", src);
+       dev_err(&i2c->adap.dev, "device addr=%x\n",
+               jz4780_i2c_readw(i2c, JZ4780_I2C_TAR));
+       dev_err(&i2c->adap.dev, "send cmd count:%d  %d\n",
+               i2c->cmd, i2c->cmd_buf[i2c->cmd]);
+       dev_err(&i2c->adap.dev, "receive data count:%d  %d\n",
+               i2c->cmd, i2c->data_buf[i2c->cmd]);
+
+       for (i = 0; i < 16; i++) {
+               if (src & BIT(i))
+                       dev_dbg(&i2c->adap.dev, "I2C TXABRT[%d]=%s\n",
+                               i, jz4780_i2c_abrt_src[i]);
+       }
+}
+
+static inline int jz4780_i2c_xfer_read(struct jz4780_i2c *i2c,
+                                      unsigned char *buf, int len, int cnt,
+                                      int idx)
+{
+       int ret = 0;
+       long timeout;
+       int wait_time = JZ4780_I2C_TIMEOUT * (len + 5);
+       unsigned short tmp;
+       unsigned long flags;
+
+       memset(buf, 0, len);
+
+       spin_lock_irqsave(&i2c->lock, flags);
+
+       i2c->stop_hold = 0;
+       i2c->is_write = 0;
+       i2c->rbuf = buf;
+       i2c->rd_total_len = len;
+       i2c->rd_data_xfered = 0;
+       i2c->rd_cmd_xfered = 0;
+
+       if (len <= JZ4780_I2C_FIFO_LEN)
+               jz4780_i2c_writew(i2c, JZ4780_I2C_RXTL, len - 1);
+       else
+               jz4780_i2c_writew(i2c, JZ4780_I2C_RXTL, RX_LEVEL);
+
+       jz4780_i2c_writew(i2c, JZ4780_I2C_TXTL, TX_LEVEL);
+
+       jz4780_i2c_writew(i2c, JZ4780_I2C_INTM,
+                         JZ4780_I2C_INTM_MRXFL | JZ4780_I2C_INTM_MTXEMP
+                         | JZ4780_I2C_INTM_MTXABT | JZ4780_I2C_INTM_MRXOF);
+
+       tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
+       tmp |= JZ4780_I2C_CTRL_STPHLD;
+       jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
+
+       spin_unlock_irqrestore(&i2c->lock, flags);
+
+       timeout = wait_for_completion_timeout(&i2c->trans_waitq,
+                                             msecs_to_jiffies(wait_time));
+
+       if (!timeout) {
+               dev_err(&i2c->adap.dev, "irq read timeout\n");
+               dev_dbg(&i2c->adap.dev, "send cmd count:%d  %d\n",
+                       i2c->cmd, i2c->cmd_buf[i2c->cmd]);
+               dev_dbg(&i2c->adap.dev, "receive data count:%d  %d\n",
+                       i2c->cmd, i2c->data_buf[i2c->cmd]);
+               ret = -EIO;
+       }
+
+       tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_TXABRT);
+       if (tmp) {
+               jz4780_i2c_txabrt(i2c, tmp);
+               ret = -EIO;
+       }
+
+       return ret;
+}
+
+static inline int jz4780_i2c_xfer_write(struct jz4780_i2c *i2c,
+                                       unsigned char *buf, int len,
+                                       int cnt, int idx)
+{
+       int ret = 0;
+       int wait_time = JZ4780_I2C_TIMEOUT * (len + 5);
+       long timeout;
+       unsigned short tmp;
+       unsigned long flags;
+
+       spin_lock_irqsave(&i2c->lock, flags);
+
+       if (idx < (cnt - 1))
+               i2c->stop_hold = 1;
+       else
+               i2c->stop_hold = 0;
+
+       i2c->is_write = 1;
+       i2c->wbuf = buf;
+       i2c->wt_len = len;
+
+       jz4780_i2c_writew(i2c, JZ4780_I2C_TXTL, TX_LEVEL);
+
+       jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, JZ4780_I2C_INTM_MTXEMP
+                                       | JZ4780_I2C_INTM_MTXABT);
+
+       tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
+       tmp |= JZ4780_I2C_CTRL_STPHLD;
+       jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
+
+       spin_unlock_irqrestore(&i2c->lock, flags);
+
+       timeout = wait_for_completion_timeout(&i2c->trans_waitq,
+                                             msecs_to_jiffies(wait_time));
+       if (timeout && !i2c->stop_hold) {
+               unsigned short i2c_sta;
+               int write_in_process;
+
+               timeout = JZ4780_I2C_TIMEOUT * 100;
+               for (; timeout > 0; timeout--) {
+                       i2c_sta = jz4780_i2c_readw(i2c, JZ4780_I2C_STA);
+
+                       write_in_process = (i2c_sta & JZ4780_I2C_STA_MSTACT) ||
+                               !(i2c_sta & JZ4780_I2C_STA_TFE);
+                       if (!write_in_process)
+                               break;
+                       udelay(10);
+               }
+       }
+
+       if (!timeout) {
+               dev_err(&i2c->adap.dev, "write wait timeout\n");
+               ret = -EIO;
+       }
+
+       tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_TXABRT);
+       if (tmp) {
+               jz4780_i2c_txabrt(i2c, tmp);
+               ret = -EIO;
+       }
+
+       return ret;
+}
+
+static int jz4780_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
+                          int count)
+{
+       int i = -EIO;
+       int ret = 0;
+       struct jz4780_i2c *i2c = adap->algo_data;
+
+       ret = jz4780_i2c_prepare(i2c);
+       if (ret) {
+               dev_err(&i2c->adap.dev, "I2C prepare failed\n");
+               goto out;
+       }
+
+       if (msg->addr != jz4780_i2c_readw(i2c, JZ4780_I2C_TAR)) {
+               ret = jz4780_i2c_set_target(i2c, msg->addr);
+               if (ret)
+                       goto out;
+       }
+       for (i = 0; i < count; i++, msg++) {
+               if (msg->flags & I2C_M_RD)
+                       ret = jz4780_i2c_xfer_read(i2c, msg->buf, msg->len,
+                                                  count, i);
+               else
+                       ret = jz4780_i2c_xfer_write(i2c, msg->buf, msg->len,
+                                                   count, i);
+
+               if (ret)
+                       goto out;
+       }
+
+       ret = i;
+
+out:
+       jz4780_i2c_cleanup(i2c);
+       return ret;
+}
+
+static u32 jz4780_i2c_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm jz4780_i2c_algorithm = {
+       .master_xfer    = jz4780_i2c_xfer,
+       .functionality  = jz4780_i2c_functionality,
+};
+
+static const struct of_device_id jz4780_i2c_of_matches[] = {
+       { .compatible = "ingenic,jz4780-i2c", },
+       { /* sentinel */ }
+};
+
+static int jz4780_i2c_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+       unsigned int clk_freq = 0;
+       unsigned short tmp;
+       struct resource *r;
+       struct jz4780_i2c *i2c;
+
+       i2c = devm_kzalloc(&pdev->dev, sizeof(struct jz4780_i2c), GFP_KERNEL);
+       if (!i2c)
+               return -ENOMEM;
+
+       i2c->adap.owner         = THIS_MODULE;
+       i2c->adap.algo          = &jz4780_i2c_algorithm;
+       i2c->adap.algo_data     = i2c;
+       i2c->adap.retries       = 5;
+       i2c->adap.dev.parent    = &pdev->dev;
+       i2c->adap.dev.of_node   = pdev->dev.of_node;
+       sprintf(i2c->adap.name, "%s", pdev->name);
+
+       init_completion(&i2c->trans_waitq);
+       spin_lock_init(&i2c->lock);
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       i2c->iomem = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(i2c->iomem))
+               return PTR_ERR(i2c->iomem);
+
+       platform_set_drvdata(pdev, i2c);
+
+       i2c->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(i2c->clk))
+               return PTR_ERR(i2c->clk);
+
+       clk_prepare_enable(i2c->clk);
+
+       if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+                                &clk_freq)) {
+               dev_err(&pdev->dev, "clock-frequency not specified in DT");
+               return clk_freq;
+       }
+
+       i2c->speed = clk_freq / 1000;
+       jz4780_i2c_set_speed(i2c);
+
+       dev_info(&pdev->dev, "Bus frequency is %d KHz\n", i2c->speed);
+
+       tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
+       tmp &= ~JZ4780_I2C_CTRL_STPHLD;
+       jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
+
+       jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, 0x0);
+
+       i2c->cmd = 0;
+       memset(i2c->cmd_buf, 0, BUFSIZE);
+       memset(i2c->data_buf, 0, BUFSIZE);
+
+       i2c->irq = platform_get_irq(pdev, 0);
+       ret = devm_request_irq(&pdev->dev, i2c->irq, jz4780_i2c_irq, 0,
+                              dev_name(&pdev->dev), i2c);
+       if (ret) {
+               ret = -ENODEV;
+               goto err;
+       }
+
+       ret = i2c_add_adapter(&i2c->adap);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to add bus\n");
+               goto err;
+       }
+
+       return 0;
+
+err:
+       clk_disable_unprepare(i2c->clk);
+       return ret;
+}
+
+static int jz4780_i2c_remove(struct platform_device *pdev)
+{
+       struct jz4780_i2c *i2c = platform_get_drvdata(pdev);
+
+       clk_disable_unprepare(i2c->clk);
+       i2c_del_adapter(&i2c->adap);
+       return 0;
+}
+
+static struct platform_driver jz4780_i2c_driver = {
+       .probe          = jz4780_i2c_probe,
+       .remove         = jz4780_i2c_remove,
+       .driver         = {
+               .name   = "jz4780-i2c",
+               .of_match_table = of_match_ptr(jz4780_i2c_of_matches),
+       },
+};
+
+module_platform_driver(jz4780_i2c_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("ztyan<ztyan@ingenic.cn>");
+MODULE_DESCRIPTION("i2c driver for JZ4780 SoCs");
index c74cc2be613b67f50c05217bc86fcbb0c2f4f919..48ecffecc0eda3fb42e63ff19a6e93d2f49ed918 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/delay.h>
 
 #include <asm/mpc52xx.h>
+#include <asm/mpc85xx.h>
 #include <sysdev/fsl_soc.h>
 
 #define DRV_NAME "mpc-i2c"
@@ -95,8 +96,9 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id)
                i2c->interrupt = readb(i2c->base + MPC_I2C_SR);
                writeb(0, i2c->base + MPC_I2C_SR);
                wake_up(&i2c->queue);
+               return IRQ_HANDLED;
        }
-       return IRQ_HANDLED;
+       return IRQ_NONE;
 }
 
 /* Sometimes 9th clock pulse isn't generated, and slave doesn't release
@@ -346,6 +348,33 @@ static u32 mpc_i2c_get_sec_cfg_8xxx(void)
        return val;
 }
 
+static u32 mpc_i2c_get_prescaler_8xxx(void)
+{
+       /* mpc83xx and mpc82xx all have prescaler 1 */
+       u32 prescaler = 1;
+
+       /* mpc85xx */
+       if (pvr_version_is(PVR_VER_E500V1) || pvr_version_is(PVR_VER_E500V2)
+               || pvr_version_is(PVR_VER_E500MC)
+               || pvr_version_is(PVR_VER_E5500)
+               || pvr_version_is(PVR_VER_E6500)) {
+               unsigned int svr = mfspr(SPRN_SVR);
+
+               if ((SVR_SOC_VER(svr) == SVR_8540)
+                       || (SVR_SOC_VER(svr) == SVR_8541)
+                       || (SVR_SOC_VER(svr) == SVR_8560)
+                       || (SVR_SOC_VER(svr) == SVR_8555)
+                       || (SVR_SOC_VER(svr) == SVR_8610))
+                       /* the above 85xx SoCs have prescaler 1 */
+                       prescaler = 1;
+               else
+                       /* all the other 85xx have prescaler 2 */
+                       prescaler = 2;
+       }
+
+       return prescaler;
+}
+
 static int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
                                          u32 prescaler, u32 *real_clk)
 {
@@ -363,7 +392,7 @@ static int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
        if (of_device_is_compatible(node, "fsl,mpc8544-i2c"))
                prescaler = mpc_i2c_get_sec_cfg_8xxx() ? 3 : 2;
        if (!prescaler)
-               prescaler = 1;
+               prescaler = mpc_i2c_get_prescaler_8xxx();
 
        divider = fsl_get_sys_freq() / clock / prescaler;
 
index ff8b12c8d25f50d88beda7e47a0d7d8dbc334e24..56fceff6ba1422eb5eb3b0d32f1835a489925c28 100644 (file)
@@ -568,6 +568,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
        int ret;
        int flags;
        int use_pio = 0;
+       unsigned long time_left;
 
        flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
 
@@ -599,9 +600,9 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
                if (ret)
                        return ret;
 
-               ret = wait_for_completion_timeout(&i2c->cmd_complete,
+               time_left = wait_for_completion_timeout(&i2c->cmd_complete,
                                                msecs_to_jiffies(1000));
-               if (ret == 0)
+               if (!time_left)
                        goto timeout;
 
                ret = i2c->cmd_err;
index 97998946c4f64b71d801539f2aa8b5583a9c7330..bcd17e8cbcb4b3cc8bb5b6aee7d4d6e2873df8b6 100644 (file)
@@ -446,9 +446,9 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev)
  */
 static int read_i2c(struct nmk_i2c_dev *dev, u16 flags)
 {
-       u32 status = 0;
+       int status = 0;
        u32 mcr, irq_mask;
-       int timeout;
+       unsigned long timeout;
 
        mcr = load_i2c_mcr_reg(dev, flags);
        writel(mcr, dev->virtbase + I2C_MCR);
@@ -517,7 +517,7 @@ static int write_i2c(struct nmk_i2c_dev *dev, u16 flags)
 {
        u32 status = 0;
        u32 mcr, irq_mask;
-       int timeout;
+       unsigned long timeout;
 
        mcr = load_i2c_mcr_reg(dev, flags);
 
index 16f90b1a750894851c544919aeef88fe9c23d598..75dd6d04124128957e95a2bf8a0d1b18eeda34dc 100644 (file)
@@ -104,18 +104,8 @@ static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
                req.buffer_ra = cpu_to_be64(__pa(msgs[0].buf));
                break;
        case 2:
-               /* For two messages, we basically support only simple
-                * smbus transactions of a write plus a read. We might
-                * want to allow also two writes but we'd have to bounce
-                * the data into a single buffer.
-                */
-               if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD))
-                       return -EOPNOTSUPP;
-               if (msgs[0].len > 4)
-                       return -EOPNOTSUPP;
-               if (msgs[0].addr != msgs[1].addr)
-                       return -EOPNOTSUPP;
-               req.type = OPAL_I2C_SM_READ;
+               req.type = (msgs[1].flags & I2C_M_RD) ?
+                       OPAL_I2C_SM_READ : OPAL_I2C_SM_WRITE;
                req.addr = cpu_to_be16(msgs[0].addr);
                req.subaddr_sz = msgs[0].len;
                for (i = 0; i < msgs[0].len; i++)
@@ -210,6 +200,15 @@ static const struct i2c_algorithm i2c_opal_algo = {
        .functionality  = i2c_opal_func,
 };
 
+/*
+ * For two messages, we basically support simple smbus transactions of a
+ * write-then-anything.
+ */
+static struct i2c_adapter_quirks i2c_opal_quirks = {
+       .flags = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | I2C_AQ_COMB_SAME_ADDR,
+       .max_comb_1st_msg_len = 4,
+};
+
 static int i2c_opal_probe(struct platform_device *pdev)
 {
        struct i2c_adapter      *adapter;
@@ -232,6 +231,7 @@ static int i2c_opal_probe(struct platform_device *pdev)
 
        adapter->algo = &i2c_opal_algo;
        adapter->algo_data = (void *)(unsigned long)opal_id;
+       adapter->quirks = &i2c_opal_quirks;
        adapter->dev.parent = &pdev->dev;
        adapter->dev.of_node = of_node_get(pdev->dev.of_node);
        pname = of_get_property(pdev->dev.of_node, "ibm,port-name", NULL);
index d37d9db6681e7b5745a45331ae60737a9b36f99a..2c40edbf6224eb69a0cf720616b3ca8aee321502 100644 (file)
@@ -456,14 +456,6 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
                return -EINVAL;
        }
 
-       if (cmd->read_len > MSP_MAX_BYTES_PER_RW ||
-           cmd->write_len > MSP_MAX_BYTES_PER_RW) {
-               dev_err(&pmcmsptwi_adapter.dev,
-                       "%s: Cannot transfer more than %d bytes\n",
-                       __func__, MSP_MAX_BYTES_PER_RW);
-               return -EINVAL;
-       }
-
        mutex_lock(&data->lock);
        dev_dbg(&pmcmsptwi_adapter.dev,
                "Setting address to 0x%04x\n", cmd->addr);
@@ -520,25 +512,14 @@ static int pmcmsptwi_master_xfer(struct i2c_adapter *adap,
        struct pmcmsptwi_cfg oldcfg, newcfg;
        int ret;
 
-       if (num > 2) {
-               dev_dbg(&adap->dev, "%d messages unsupported\n", num);
-               return -EINVAL;
-       } else if (num == 2) {
-               /* Check for a dual write-then-read command */
+       if (num == 2) {
                struct i2c_msg *nextmsg = msg + 1;
-               if (!(msg->flags & I2C_M_RD) &&
-                   (nextmsg->flags & I2C_M_RD) &&
-                   msg->addr == nextmsg->addr) {
-                       cmd.type = MSP_TWI_CMD_WRITE_READ;
-                       cmd.write_len = msg->len;
-                       cmd.write_data = msg->buf;
-                       cmd.read_len = nextmsg->len;
-                       cmd.read_data = nextmsg->buf;
-               } else {
-                       dev_dbg(&adap->dev,
-                               "Non write-read dual messages unsupported\n");
-                       return -EINVAL;
-               }
+
+               cmd.type = MSP_TWI_CMD_WRITE_READ;
+               cmd.write_len = msg->len;
+               cmd.write_data = msg->buf;
+               cmd.read_len = nextmsg->len;
+               cmd.read_data = nextmsg->buf;
        } else if (msg->flags & I2C_M_RD) {
                cmd.type = MSP_TWI_CMD_READ;
                cmd.read_len = msg->len;
@@ -598,6 +579,14 @@ static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter)
                I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL;
 }
 
+static struct i2c_adapter_quirks pmcmsptwi_i2c_quirks = {
+       .flags = I2C_AQ_COMB_WRITE_THEN_READ,
+       .max_write_len = MSP_MAX_BYTES_PER_RW,
+       .max_read_len = MSP_MAX_BYTES_PER_RW,
+       .max_comb_1st_msg_len = MSP_MAX_BYTES_PER_RW,
+       .max_comb_2nd_msg_len = MSP_MAX_BYTES_PER_RW,
+};
+
 /* -- Initialization -- */
 
 static struct i2c_algorithm pmcmsptwi_algo = {
@@ -609,6 +598,7 @@ static struct i2c_adapter pmcmsptwi_adapter = {
        .owner          = THIS_MODULE,
        .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &pmcmsptwi_algo,
+       .quirks         = &pmcmsptwi_i2c_quirks,
        .name           = DRV_NAME,
 };
 
index 60a53c169ed2b3c8d3803411a310b752d8e1631b..6abcf696e3594b50b6feb2608a3eaa7d0a0ee7aa 100644 (file)
@@ -153,12 +153,6 @@ static int i2c_powermac_master_xfer(       struct i2c_adapter *adap,
        int                     read;
        int                     addrdir;
 
-       if (num != 1) {
-               dev_err(&adap->dev,
-                       "Multi-message I2C transactions not supported\n");
-               return -EOPNOTSUPP;
-       }
-
        if (msgs->flags & I2C_M_TEN)
                return -EINVAL;
        read = (msgs->flags & I2C_M_RD) != 0;
@@ -205,6 +199,9 @@ static const struct i2c_algorithm i2c_powermac_algorithm = {
        .functionality  = i2c_powermac_func,
 };
 
+static struct i2c_adapter_quirks i2c_powermac_quirks = {
+       .max_num_msgs = 1,
+};
 
 static int i2c_powermac_remove(struct platform_device *dev)
 {
@@ -434,6 +431,7 @@ static int i2c_powermac_probe(struct platform_device *dev)
 
        platform_set_drvdata(dev, adapter);
        adapter->algo = &i2c_powermac_algorithm;
+       adapter->quirks = &i2c_powermac_quirks;
        i2c_set_adapdata(adapter, bus);
        adapter->dev.parent = &dev->dev;
 
index 4dad23bdffbe901e0180be86dadc6c3eea03ec82..fdcbdab808e9fcbea9eb301ab7a2fb261abb3226 100644 (file)
@@ -412,17 +412,6 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
        unsigned long left;
        int ret;
 
-       /*
-        * The QUP block will issue a NACK and STOP on the bus when reaching
-        * the end of the read, the length of the read is specified as one byte
-        * which limits the possible read to 256 (QUP_READ_LIMIT) bytes.
-        */
-       if (msg->len > QUP_READ_LIMIT) {
-               dev_err(qup->dev, "HW not capable of reads over %d bytes\n",
-                       QUP_READ_LIMIT);
-               return -EINVAL;
-       }
-
        qup->msg = msg;
        qup->pos  = 0;
 
@@ -534,6 +523,15 @@ static const struct i2c_algorithm qup_i2c_algo = {
        .functionality  = qup_i2c_func,
 };
 
+/*
+ * The QUP block will issue a NACK and STOP on the bus when reaching
+ * the end of the read, the length of the read is specified as one byte
+ * which limits the possible read to 256 (QUP_READ_LIMIT) bytes.
+ */
+static struct i2c_adapter_quirks qup_i2c_quirks = {
+       .max_read_len = QUP_READ_LIMIT,
+};
+
 static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup)
 {
        clk_prepare_enable(qup->clk);
@@ -670,6 +668,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
 
        i2c_set_adapdata(&qup->adap, qup);
        qup->adap.algo = &qup_i2c_algo;
+       qup->adap.quirks = &qup_i2c_quirks;
        qup->adap.dev.parent = qup->dev;
        qup->adap.dev.of_node = pdev->dev.of_node;
        strlcpy(qup->adap.name, "QUP I2C adapter", sizeof(qup->adap.name));
index 71a6e07eb7ab7c725655063515d801cec4617361..5a84bea5b84514389ae6c01c2b2b2a8eadc85346 100644 (file)
@@ -382,11 +382,11 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)
        if (ssr_filtered & SAR) {
                /* read or write request */
                if (ssr_raw & STM) {
-                       i2c_slave_event(priv->slave, I2C_SLAVE_REQ_READ_START, &value);
+                       i2c_slave_event(priv->slave, I2C_SLAVE_READ_REQUESTED, &value);
                        rcar_i2c_write(priv, ICRXTX, value);
                        rcar_i2c_write(priv, ICSIER, SDE | SSR | SAR);
                } else {
-                       i2c_slave_event(priv->slave, I2C_SLAVE_REQ_WRITE_START, &value);
+                       i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED, &value);
                        rcar_i2c_read(priv, ICRXTX);    /* dummy read */
                        rcar_i2c_write(priv, ICSIER, SDR | SSR | SAR);
                }
@@ -406,17 +406,15 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)
                int ret;
 
                value = rcar_i2c_read(priv, ICRXTX);
-               ret = i2c_slave_event(priv->slave, I2C_SLAVE_REQ_WRITE_END, &value);
+               ret = i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_RECEIVED, &value);
                /* Send NACK in case of error */
                rcar_i2c_write(priv, ICSCR, SIE | SDBS | (ret < 0 ? FNA : 0));
-               i2c_slave_event(priv->slave, I2C_SLAVE_REQ_WRITE_START, &value);
                rcar_i2c_write(priv, ICSSR, ~SDR & 0xff);
        }
 
        /* master wants to read from us */
        if (ssr_filtered & SDE) {
-               i2c_slave_event(priv->slave, I2C_SLAVE_REQ_READ_END, &value);
-               i2c_slave_event(priv->slave, I2C_SLAVE_REQ_READ_START, &value);
+               i2c_slave_event(priv->slave, I2C_SLAVE_READ_PROCESSED, &value);
                rcar_i2c_write(priv, ICRXTX, value);
                rcar_i2c_write(priv, ICSSR, ~SDE & 0xff);
        }
index 29f14331dd9d01fcb5d66f1e74602b61da9593cf..1bcd75ea0b4cfd25dfaf9052e8514b2ebdfd16eb 100644 (file)
@@ -532,7 +532,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 {
        u32 packet_header;
        u32 int_mask;
-       int ret;
+       unsigned long time_left;
 
        tegra_i2c_flush_fifos(i2c_dev);
 
@@ -585,18 +585,20 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
        dev_dbg(i2c_dev->dev, "unmasked irq: %02x\n",
                i2c_readl(i2c_dev, I2C_INT_MASK));
 
-       ret = wait_for_completion_timeout(&i2c_dev->msg_complete, TEGRA_I2C_TIMEOUT);
+       time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
+                                               TEGRA_I2C_TIMEOUT);
        tegra_i2c_mask_irq(i2c_dev, int_mask);
 
-       if (ret == 0) {
+       if (time_left == 0) {
                dev_err(i2c_dev->dev, "i2c transfer timed out\n");
 
                tegra_i2c_init(i2c_dev);
                return -ETIMEDOUT;
        }
 
-       dev_dbg(i2c_dev->dev, "transfer complete: %d %d %d\n",
-               ret, completion_done(&i2c_dev->msg_complete), i2c_dev->msg_err);
+       dev_dbg(i2c_dev->dev, "transfer complete: %lu %d %d\n",
+               time_left, completion_done(&i2c_dev->msg_complete),
+               i2c_dev->msg_err);
 
        if (likely(i2c_dev->msg_err == I2C_ERR_NONE))
                return 0;
index 7533fa34d73711191c55ddf091a3f79831bd919b..47e88adf2011e15509a070e663e80236a96f3c61 100644 (file)
@@ -288,10 +288,6 @@ static int vprbrd_i2c_xfer(struct i2c_adapter *i2c, struct i2c_msg *msgs,
                        i, pmsg->flags & I2C_M_RD ? "read" : "write",
                        pmsg->flags, pmsg->len, pmsg->addr);
 
-               /* msgs longer than 2048 bytes are not supported by adapter */
-               if (pmsg->len > 2048)
-                       return -EINVAL;
-
                mutex_lock(&vb->lock);
                /* directly send the message */
                if (pmsg->flags & I2C_M_RD) {
@@ -358,6 +354,11 @@ static const struct i2c_algorithm vprbrd_algorithm = {
        .functionality  = vprbrd_i2c_func,
 };
 
+static struct i2c_adapter_quirks vprbrd_quirks = {
+       .max_read_len = 2048,
+       .max_write_len = 2048,
+};
+
 static int vprbrd_i2c_probe(struct platform_device *pdev)
 {
        struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent);
@@ -373,6 +374,7 @@ static int vprbrd_i2c_probe(struct platform_device *pdev)
        vb_i2c->i2c.owner = THIS_MODULE;
        vb_i2c->i2c.class = I2C_CLASS_HWMON;
        vb_i2c->i2c.algo = &vprbrd_algorithm;
+       vb_i2c->i2c.quirks = &vprbrd_quirks;
        vb_i2c->i2c.algo_data = vb;
        /* save the param in usb capabable memory */
        vb_i2c->bus_freq_param = i2c_bus_param;
index 82ea349254899c2f3a274cc6df68c2ac9ef9a579..e1e3a85596c56285cd9ec89bf03e255ec69784d3 100644 (file)
@@ -128,7 +128,8 @@ static int wmt_i2c_write(struct i2c_adapter *adap, struct i2c_msg *pmsg,
 {
        struct wmt_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
        u16 val, tcr_val;
-       int ret, wait_result;
+       int ret;
+       unsigned long wait_result;
        int xfer_len = 0;
 
        if (!(pmsg->flags & I2C_M_NOSTART)) {
@@ -177,7 +178,7 @@ static int wmt_i2c_write(struct i2c_adapter *adap, struct i2c_msg *pmsg,
 
        while (xfer_len < pmsg->len) {
                wait_result = wait_for_completion_timeout(&i2c_dev->complete,
-                                                         500 * HZ / 1000);
+                                                       msecs_to_jiffies(500));
 
                if (wait_result == 0)
                        return -ETIMEDOUT;
@@ -218,7 +219,8 @@ static int wmt_i2c_read(struct i2c_adapter *adap, struct i2c_msg *pmsg,
 {
        struct wmt_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
        u16 val, tcr_val;
-       int ret, wait_result;
+       int ret;
+       unsigned long wait_result;
        u32 xfer_len = 0;
 
        if (!(pmsg->flags & I2C_M_NOSTART)) {
@@ -266,7 +268,7 @@ static int wmt_i2c_read(struct i2c_adapter *adap, struct i2c_msg *pmsg,
 
        while (xfer_len < pmsg->len) {
                wait_result = wait_for_completion_timeout(&i2c_dev->complete,
-                                                         500 * HZ / 1000);
+                                                       msecs_to_jiffies(500));
 
                if (!wait_result)
                        return -ETIMEDOUT;
diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c
new file mode 100644 (file)
index 0000000..c941418
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 2003-2015 Broadcom Corporation
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/completion.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define XLP9XX_I2C_DIV                 0x0
+#define XLP9XX_I2C_CTRL                        0x1
+#define XLP9XX_I2C_CMD                 0x2
+#define XLP9XX_I2C_STATUS              0x3
+#define XLP9XX_I2C_MTXFIFO             0x4
+#define XLP9XX_I2C_MRXFIFO             0x5
+#define XLP9XX_I2C_MFIFOCTRL           0x6
+#define XLP9XX_I2C_STXFIFO             0x7
+#define XLP9XX_I2C_SRXFIFO             0x8
+#define XLP9XX_I2C_SFIFOCTRL           0x9
+#define XLP9XX_I2C_SLAVEADDR           0xA
+#define XLP9XX_I2C_OWNADDR             0xB
+#define XLP9XX_I2C_FIFOWCNT            0xC
+#define XLP9XX_I2C_INTEN               0xD
+#define XLP9XX_I2C_INTST               0xE
+#define XLP9XX_I2C_WAITCNT             0xF
+#define XLP9XX_I2C_TIMEOUT             0X10
+#define XLP9XX_I2C_GENCALLADDR         0x11
+
+#define XLP9XX_I2C_CMD_START           BIT(7)
+#define XLP9XX_I2C_CMD_STOP            BIT(6)
+#define XLP9XX_I2C_CMD_READ            BIT(5)
+#define XLP9XX_I2C_CMD_WRITE           BIT(4)
+#define XLP9XX_I2C_CMD_ACK             BIT(3)
+
+#define XLP9XX_I2C_CTRL_MCTLEN_SHIFT   16
+#define XLP9XX_I2C_CTRL_MCTLEN_MASK    0xffff0000
+#define XLP9XX_I2C_CTRL_RST            BIT(8)
+#define XLP9XX_I2C_CTRL_EN             BIT(6)
+#define XLP9XX_I2C_CTRL_MASTER         BIT(4)
+#define XLP9XX_I2C_CTRL_FIFORD         BIT(1)
+#define XLP9XX_I2C_CTRL_ADDMODE                BIT(0)
+
+#define XLP9XX_I2C_INTEN_NACKADDR      BIT(25)
+#define XLP9XX_I2C_INTEN_SADDR         BIT(13)
+#define XLP9XX_I2C_INTEN_DATADONE      BIT(12)
+#define XLP9XX_I2C_INTEN_ARLOST                BIT(11)
+#define XLP9XX_I2C_INTEN_MFIFOFULL     BIT(4)
+#define XLP9XX_I2C_INTEN_MFIFOEMTY     BIT(3)
+#define XLP9XX_I2C_INTEN_MFIFOHI       BIT(2)
+#define XLP9XX_I2C_INTEN_BUSERR                BIT(0)
+
+#define XLP9XX_I2C_MFIFOCTRL_HITH_SHIFT                8
+#define XLP9XX_I2C_MFIFOCTRL_LOTH_SHIFT                0
+#define XLP9XX_I2C_MFIFOCTRL_RST               BIT(16)
+
+#define XLP9XX_I2C_SLAVEADDR_RW                        BIT(0)
+#define XLP9XX_I2C_SLAVEADDR_ADDR_SHIFT                1
+
+#define XLP9XX_I2C_IP_CLK_FREQ         133000000UL
+#define XLP9XX_I2C_DEFAULT_FREQ                100000
+#define XLP9XX_I2C_HIGH_FREQ           400000
+#define XLP9XX_I2C_FIFO_SIZE           0x80U
+#define XLP9XX_I2C_TIMEOUT_MS          1000
+
+#define XLP9XX_I2C_FIFO_WCNT_MASK      0xff
+#define XLP9XX_I2C_STATUS_ERRMASK      (XLP9XX_I2C_INTEN_ARLOST | \
+                       XLP9XX_I2C_INTEN_NACKADDR | XLP9XX_I2C_INTEN_BUSERR)
+
+struct xlp9xx_i2c_dev {
+       struct device *dev;
+       struct i2c_adapter adapter;
+       struct completion msg_complete;
+       int irq;
+       bool msg_read;
+       u32 __iomem *base;
+       u32 msg_buf_remaining;
+       u32 msg_len;
+       u32 clk_hz;
+       u32 msg_err;
+       u8 *msg_buf;
+};
+
+static inline void xlp9xx_write_i2c_reg(struct xlp9xx_i2c_dev *priv,
+                                       unsigned long reg, u32 val)
+{
+       writel(val, priv->base + reg);
+}
+
+static inline u32 xlp9xx_read_i2c_reg(struct xlp9xx_i2c_dev *priv,
+                                     unsigned long reg)
+{
+       return readl(priv->base + reg);
+}
+
+static void xlp9xx_i2c_mask_irq(struct xlp9xx_i2c_dev *priv, u32 mask)
+{
+       u32 inten;
+
+       inten = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_INTEN) & ~mask;
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_INTEN, inten);
+}
+
+static void xlp9xx_i2c_unmask_irq(struct xlp9xx_i2c_dev *priv, u32 mask)
+{
+       u32 inten;
+
+       inten = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_INTEN) | mask;
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_INTEN, inten);
+}
+
+static void xlp9xx_i2c_update_rx_fifo_thres(struct xlp9xx_i2c_dev *priv)
+{
+       u32 thres;
+
+       thres = min(priv->msg_buf_remaining, XLP9XX_I2C_FIFO_SIZE);
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_MFIFOCTRL,
+                            thres << XLP9XX_I2C_MFIFOCTRL_HITH_SHIFT);
+}
+
+static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv)
+{
+       u32 len, i;
+       u8 *buf = priv->msg_buf;
+
+       len = min(priv->msg_buf_remaining, XLP9XX_I2C_FIFO_SIZE);
+       for (i = 0; i < len; i++)
+               xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_MTXFIFO, buf[i]);
+       priv->msg_buf_remaining -= len;
+       priv->msg_buf += len;
+}
+
+static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
+{
+       u32 len, i;
+       u8 *buf = priv->msg_buf;
+
+       len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) &
+                                 XLP9XX_I2C_FIFO_WCNT_MASK;
+       len = min(priv->msg_buf_remaining, len);
+       for (i = 0; i < len; i++, buf++)
+               *buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
+
+       priv->msg_buf_remaining -= len;
+       priv->msg_buf = buf;
+
+       if (priv->msg_buf_remaining)
+               xlp9xx_i2c_update_rx_fifo_thres(priv);
+}
+
+static irqreturn_t xlp9xx_i2c_isr(int irq, void *dev_id)
+{
+       struct xlp9xx_i2c_dev *priv = dev_id;
+       u32 status;
+
+       status = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_INTST);
+       if (status == 0)
+               return IRQ_NONE;
+
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_INTST, status);
+       if (status & XLP9XX_I2C_STATUS_ERRMASK) {
+               priv->msg_err = status;
+               goto xfer_done;
+       }
+
+       /* SADDR ACK for SMBUS_QUICK */
+       if ((status & XLP9XX_I2C_INTEN_SADDR) && (priv->msg_len == 0))
+               goto xfer_done;
+
+       if (!priv->msg_read) {
+               if (status & XLP9XX_I2C_INTEN_MFIFOEMTY) {
+                       /* TX FIFO got empty, fill it up again */
+                       if (priv->msg_buf_remaining)
+                               xlp9xx_i2c_fill_tx_fifo(priv);
+                       else
+                               xlp9xx_i2c_mask_irq(priv,
+                                                   XLP9XX_I2C_INTEN_MFIFOEMTY);
+               }
+       } else {
+               if (status & (XLP9XX_I2C_INTEN_DATADONE |
+                             XLP9XX_I2C_INTEN_MFIFOHI)) {
+                       /* data is in FIFO, read it */
+                       if (priv->msg_buf_remaining)
+                               xlp9xx_i2c_drain_rx_fifo(priv);
+               }
+       }
+
+       /* Transfer complete */
+       if (status & XLP9XX_I2C_INTEN_DATADONE)
+               goto xfer_done;
+
+       return IRQ_HANDLED;
+
+xfer_done:
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_INTEN, 0);
+       complete(&priv->msg_complete);
+       return IRQ_HANDLED;
+}
+
+static int xlp9xx_i2c_init(struct xlp9xx_i2c_dev *priv)
+{
+       u32 prescale;
+
+       /*
+        * The controller uses 5 * SCL clock internally.
+        * So prescale value should be divided by 5.
+        */
+       prescale = DIV_ROUND_UP(XLP9XX_I2C_IP_CLK_FREQ, priv->clk_hz);
+       prescale = ((prescale - 8) / 5) - 1;
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, XLP9XX_I2C_CTRL_RST);
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, XLP9XX_I2C_CTRL_EN |
+                            XLP9XX_I2C_CTRL_MASTER);
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_DIV, prescale);
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_INTEN, 0);
+
+       return 0;
+}
+
+static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
+                              int last_msg)
+{
+       unsigned long timeleft;
+       u32 intr_mask, cmd, val;
+
+       priv->msg_buf = msg->buf;
+       priv->msg_buf_remaining = priv->msg_len = msg->len;
+       priv->msg_err = 0;
+       priv->msg_read = (msg->flags & I2C_M_RD);
+       reinit_completion(&priv->msg_complete);
+
+       /* Reset FIFO */
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_MFIFOCTRL,
+                            XLP9XX_I2C_MFIFOCTRL_RST);
+
+       /* set FIFO threshold if reading */
+       if (priv->msg_read)
+               xlp9xx_i2c_update_rx_fifo_thres(priv);
+
+       /* set slave addr */
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_SLAVEADDR,
+                            (msg->addr << XLP9XX_I2C_SLAVEADDR_ADDR_SHIFT) |
+                            (priv->msg_read ? XLP9XX_I2C_SLAVEADDR_RW : 0));
+
+       /* Build control word for transfer */
+       val = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_CTRL);
+       if (!priv->msg_read)
+               val &= ~XLP9XX_I2C_CTRL_FIFORD;
+       else
+               val |= XLP9XX_I2C_CTRL_FIFORD;  /* read */
+
+       if (msg->flags & I2C_M_TEN)
+               val |= XLP9XX_I2C_CTRL_ADDMODE; /* 10-bit address mode*/
+       else
+               val &= ~XLP9XX_I2C_CTRL_ADDMODE;
+
+       /* set data length to be transferred */
+       val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
+             (msg->len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val);
+
+       /* fill fifo during tx */
+       if (!priv->msg_read)
+               xlp9xx_i2c_fill_tx_fifo(priv);
+
+       /* set interrupt mask */
+       intr_mask = (XLP9XX_I2C_INTEN_ARLOST | XLP9XX_I2C_INTEN_BUSERR |
+                    XLP9XX_I2C_INTEN_NACKADDR | XLP9XX_I2C_INTEN_DATADONE);
+
+       if (priv->msg_read) {
+               intr_mask |= XLP9XX_I2C_INTEN_MFIFOHI;
+               if (msg->len == 0)
+                       intr_mask |= XLP9XX_I2C_INTEN_SADDR;
+       } else {
+               if (msg->len == 0)
+                       intr_mask |= XLP9XX_I2C_INTEN_SADDR;
+               else
+                       intr_mask |= XLP9XX_I2C_INTEN_MFIFOEMTY;
+       }
+       xlp9xx_i2c_unmask_irq(priv, intr_mask);
+
+       /* set cmd reg */
+       cmd = XLP9XX_I2C_CMD_START;
+       cmd |= (priv->msg_read ? XLP9XX_I2C_CMD_READ : XLP9XX_I2C_CMD_WRITE);
+       if (last_msg)
+               cmd |= XLP9XX_I2C_CMD_STOP;
+
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CMD, cmd);
+
+       timeleft = msecs_to_jiffies(XLP9XX_I2C_TIMEOUT_MS);
+       timeleft = wait_for_completion_timeout(&priv->msg_complete, timeleft);
+
+       if (priv->msg_err) {
+               dev_dbg(priv->dev, "transfer error %x!\n", priv->msg_err);
+               if (priv->msg_err & XLP9XX_I2C_INTEN_BUSERR)
+                       xlp9xx_i2c_init(priv);
+               return -EIO;
+       }
+
+       if (timeleft == 0) {
+               dev_dbg(priv->dev, "i2c transfer timed out!\n");
+               xlp9xx_i2c_init(priv);
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int xlp9xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+                          int num)
+{
+       int i, ret;
+       struct xlp9xx_i2c_dev *priv = i2c_get_adapdata(adap);
+
+       for (i = 0; i < num; i++) {
+               ret = xlp9xx_i2c_xfer_msg(priv, &msgs[i], i == num - 1);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return num;
+}
+
+static u32 xlp9xx_i2c_functionality(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C |
+               I2C_FUNC_10BIT_ADDR;
+}
+
+static struct i2c_algorithm xlp9xx_i2c_algo = {
+       .master_xfer = xlp9xx_i2c_xfer,
+       .functionality = xlp9xx_i2c_functionality,
+};
+
+static int xlp9xx_i2c_get_frequency(struct platform_device *pdev,
+                                   struct xlp9xx_i2c_dev *priv)
+{
+       struct device_node *np = pdev->dev.of_node;
+       u32 freq;
+       int err;
+
+       err = of_property_read_u32(np, "clock-frequency", &freq);
+       if (err) {
+               freq = XLP9XX_I2C_DEFAULT_FREQ;
+               dev_dbg(&pdev->dev, "using default frequency %u\n", freq);
+       } else if (freq == 0 || freq > XLP9XX_I2C_HIGH_FREQ) {
+               dev_warn(&pdev->dev, "invalid frequency %u, using default\n",
+                        freq);
+               freq = XLP9XX_I2C_DEFAULT_FREQ;
+       }
+       priv->clk_hz = freq;
+
+       return 0;
+}
+
+static int xlp9xx_i2c_probe(struct platform_device *pdev)
+{
+       struct xlp9xx_i2c_dev *priv;
+       struct resource *res;
+       int err = 0;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       priv->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(priv->base))
+               return PTR_ERR(priv->base);
+
+       priv->irq = platform_get_irq(pdev, 0);
+       if (priv->irq <= 0) {
+               dev_err(&pdev->dev, "invalid irq!\n");
+               return priv->irq;
+       }
+
+       xlp9xx_i2c_get_frequency(pdev, priv);
+       xlp9xx_i2c_init(priv);
+
+       err = devm_request_irq(&pdev->dev, priv->irq, xlp9xx_i2c_isr, 0,
+                              pdev->name, priv);
+       if (err) {
+               dev_err(&pdev->dev, "IRQ request failed!\n");
+               return err;
+       }
+
+       init_completion(&priv->msg_complete);
+       priv->adapter.dev.parent = &pdev->dev;
+       priv->adapter.algo = &xlp9xx_i2c_algo;
+       priv->adapter.dev.of_node = pdev->dev.of_node;
+       priv->dev = &pdev->dev;
+
+       snprintf(priv->adapter.name, sizeof(priv->adapter.name), "xlp9xx-i2c");
+       i2c_set_adapdata(&priv->adapter, priv);
+
+       err = i2c_add_adapter(&priv->adapter);
+       if (err) {
+               dev_err(&pdev->dev, "failed to add I2C adapter!\n");
+               return err;
+       }
+
+       platform_set_drvdata(pdev, priv);
+       dev_dbg(&pdev->dev, "I2C bus:%d added\n", priv->adapter.nr);
+
+       return 0;
+}
+
+static int xlp9xx_i2c_remove(struct platform_device *pdev)
+{
+       struct xlp9xx_i2c_dev *priv;
+
+       priv = platform_get_drvdata(pdev);
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_INTEN, 0);
+       synchronize_irq(priv->irq);
+       i2c_del_adapter(&priv->adapter);
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, 0);
+
+       return 0;
+}
+
+static const struct of_device_id xlp9xx_i2c_of_match[] = {
+       { .compatible = "netlogic,xlp980-i2c", },
+       { /* sentinel */ },
+};
+
+static struct platform_driver xlp9xx_i2c_driver = {
+       .probe = xlp9xx_i2c_probe,
+       .remove = xlp9xx_i2c_remove,
+       .driver = {
+               .name = "xlp9xx-i2c",
+               .of_match_table = xlp9xx_i2c_of_match,
+       },
+};
+
+module_platform_driver(xlp9xx_i2c_driver);
+
+MODULE_AUTHOR("Subhendu Sekhar Behera <sbehera@broadcom.com>");
+MODULE_DESCRIPTION("XLP9XX/5XX I2C Bus Controller Driver");
+MODULE_LICENSE("GPL v2");
index edf274cabe817208f0c4b3fceb98bca95f2671f4..68f687733379e5b06aeef3ac37fed7359d3fd397 100644 (file)
@@ -561,7 +561,7 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
        int i = 0, val = 1, ret = 0;
 
        if (bri->prepare_recovery)
-               bri->prepare_recovery(bri);
+               bri->prepare_recovery(adap);
 
        /*
         * By this time SCL is high, as we need to give 9 falling-rising edges
@@ -586,7 +586,7 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
        }
 
        if (bri->unprepare_recovery)
-               bri->unprepare_recovery(bri);
+               bri->unprepare_recovery(adap);
 
        return ret;
 }
@@ -1875,6 +1875,13 @@ static int __init i2c_init(void)
 {
        int retval;
 
+       retval = of_alias_get_highest_id("i2c");
+
+       down_write(&__i2c_board_lock);
+       if (retval >= __i2c_first_dynamic_bus_num)
+               __i2c_first_dynamic_bus_num = retval + 1;
+       up_write(&__i2c_board_lock);
+
        retval = bus_register(&i2c_bus_type);
        if (retval)
                return retval;
@@ -1926,6 +1933,65 @@ module_exit(i2c_exit);
  * ----------------------------------------------------
  */
 
+/* Check if val is exceeding the quirk IFF quirk is non 0 */
+#define i2c_quirk_exceeded(val, quirk) ((quirk) && ((val) > (quirk)))
+
+static int i2c_quirk_error(struct i2c_adapter *adap, struct i2c_msg *msg, char *err_msg)
+{
+       dev_err_ratelimited(&adap->dev, "adapter quirk: %s (addr 0x%04x, size %u, %s)\n",
+                           err_msg, msg->addr, msg->len,
+                           msg->flags & I2C_M_RD ? "read" : "write");
+       return -EOPNOTSUPP;
+}
+
+static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+       const struct i2c_adapter_quirks *q = adap->quirks;
+       int max_num = q->max_num_msgs, i;
+       bool do_len_check = true;
+
+       if (q->flags & I2C_AQ_COMB) {
+               max_num = 2;
+
+               /* special checks for combined messages */
+               if (num == 2) {
+                       if (q->flags & I2C_AQ_COMB_WRITE_FIRST && msgs[0].flags & I2C_M_RD)
+                               return i2c_quirk_error(adap, &msgs[0], "1st comb msg must be write");
+
+                       if (q->flags & I2C_AQ_COMB_READ_SECOND && !(msgs[1].flags & I2C_M_RD))
+                               return i2c_quirk_error(adap, &msgs[1], "2nd comb msg must be read");
+
+                       if (q->flags & I2C_AQ_COMB_SAME_ADDR && msgs[0].addr != msgs[1].addr)
+                               return i2c_quirk_error(adap, &msgs[0], "comb msg only to same addr");
+
+                       if (i2c_quirk_exceeded(msgs[0].len, q->max_comb_1st_msg_len))
+                               return i2c_quirk_error(adap, &msgs[0], "msg too long");
+
+                       if (i2c_quirk_exceeded(msgs[1].len, q->max_comb_2nd_msg_len))
+                               return i2c_quirk_error(adap, &msgs[1], "msg too long");
+
+                       do_len_check = false;
+               }
+       }
+
+       if (i2c_quirk_exceeded(num, max_num))
+               return i2c_quirk_error(adap, &msgs[0], "too many messages");
+
+       for (i = 0; i < num; i++) {
+               u16 len = msgs[i].len;
+
+               if (msgs[i].flags & I2C_M_RD) {
+                       if (do_len_check && i2c_quirk_exceeded(len, q->max_read_len))
+                               return i2c_quirk_error(adap, &msgs[i], "msg too long");
+               } else {
+                       if (do_len_check && i2c_quirk_exceeded(len, q->max_write_len))
+                               return i2c_quirk_error(adap, &msgs[i], "msg too long");
+               }
+       }
+
+       return 0;
+}
+
 /**
  * __i2c_transfer - unlocked flavor of i2c_transfer
  * @adap: Handle to I2C bus
@@ -1943,6 +2009,9 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
        unsigned long orig_jiffies;
        int ret, try;
 
+       if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))
+               return -EOPNOTSUPP;
+
        /* i2c_trace_msg gets enabled when tracepoint i2c_transfer gets
         * enabled.  This is an efficient way of keeping the for-loop from
         * being executed when not needed.
index cf9b09db092f4e9969666565ba1562220d6b2a46..8223746546093c7a08f4bdfc8425459d88fe1a52 100644 (file)
@@ -36,7 +36,7 @@ static int i2c_slave_eeprom_slave_cb(struct i2c_client *client,
        struct eeprom_data *eeprom = i2c_get_clientdata(client);
 
        switch (event) {
-       case I2C_SLAVE_REQ_WRITE_END:
+       case I2C_SLAVE_WRITE_RECEIVED:
                if (eeprom->first_write) {
                        eeprom->buffer_idx = *val;
                        eeprom->first_write = false;
@@ -47,17 +47,23 @@ static int i2c_slave_eeprom_slave_cb(struct i2c_client *client,
                }
                break;
 
-       case I2C_SLAVE_REQ_READ_START:
+       case I2C_SLAVE_READ_PROCESSED:
+               /* The previous byte made it to the bus, get next one */
+               eeprom->buffer_idx++;
+               /* fallthrough */
+       case I2C_SLAVE_READ_REQUESTED:
                spin_lock(&eeprom->buffer_lock);
                *val = eeprom->buffer[eeprom->buffer_idx];
                spin_unlock(&eeprom->buffer_lock);
-               break;
-
-       case I2C_SLAVE_REQ_READ_END:
-               eeprom->buffer_idx++;
+               /*
+                * Do not increment buffer_idx here, because we don't know if
+                * this byte will be actually used. Read Linux I2C slave docs
+                * for details.
+                */
                break;
 
        case I2C_SLAVE_STOP:
+       case I2C_SLAVE_WRITE_REQUESTED:
                eeprom->first_write = true;
                break;
 
index f5798eb4076b5cfd4eb8395ae7a7b460c7a25a1d..70db99264339ef5c7d6ffa0df9c5b1fdda9dfeaf 100644 (file)
@@ -76,10 +76,9 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
                return -ENODEV;
        }
        adapter = of_find_i2c_adapter_by_node(adapter_np);
-       if (!adapter) {
-               dev_err(&pdev->dev, "Cannot find parent bus\n");
+       if (!adapter)
                return -EPROBE_DEFER;
-       }
+
        mux->data.parent = i2c_adapter_id(adapter);
        put_device(&adapter->dev);
 
@@ -177,11 +176,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
        }
 
        parent = i2c_get_adapter(mux->data.parent);
-       if (!parent) {
-               dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
-                       mux->data.parent);
+       if (!parent)
                return -EPROBE_DEFER;
-       }
 
        mux->parent = parent;
        mux->gpio_base = gpio_base;
index 3d8f4fe2e47e52eefff7da7967fe41bf0fafe801..bea0d2de29938404cb96b69bb684c47d0a43bf7e 100644 (file)
@@ -204,9 +204,9 @@ static int pca954x_probe(struct i2c_client *client,
        i2c_set_clientdata(client, data);
 
        /* Get the mux out of reset if a reset GPIO is specified. */
-       gpio = devm_gpiod_get(&client->dev, "reset");
-       if (!IS_ERR(gpio))
-               gpiod_direction_output(gpio, 0);
+       gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW);
+       if (IS_ERR(gpio))
+               return PTR_ERR(gpio);
 
        /* Write the mux register at addr to verify
         * that the mux is in fact present. This also
index d9c9829c8b206118b665d282f847e7809887fb33..e1180fa461969d01bd7581b52e7ba0da84ab7dfe 100644 (file)
@@ -148,8 +148,8 @@ u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
                        printk(KERN_CONT "DataRequest ");
                if (stat & ATA_CORR)
                        printk(KERN_CONT "CorrectedError ");
-               if (stat & ATA_IDX)
-                       printk(KERN_CONT "Index ");
+               if (stat & ATA_SENSE)
+                       printk(KERN_CONT "Sense ");
                if (stat & ATA_ERR)
                        printk(KERN_CONT "Error ");
        }
index a3d3b1733c49c667f7f1495d9dfef23623e28fa0..0b63facd1d87d0def87864ee946ef92e179e3d1e 100644 (file)
@@ -273,7 +273,7 @@ int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id, int irq_ctx)
            (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) {
                a = tp_ops->read_altstatus(hwif);
                s = tp_ops->read_status(hwif);
-               if ((a ^ s) & ~ATA_IDX)
+               if ((a ^ s) & ~ATA_SENSE)
                        /* ancient Seagate drives, broken interfaces */
                        printk(KERN_INFO "%s: probing with STATUS(0x%02x) "
                                         "instead of ALTSTATUS(0x%02x)\n",
index b0e58522780d48c49b9a1ebff182d5fa7a43d93c..5c979d0667a2210d2d73873e8766d07ea0facb22 100644 (file)
@@ -55,7 +55,7 @@
 
 #include <linux/kernel.h>
 #include <linux/cpuidle.h>
-#include <linux/clockchips.h>
+#include <linux/tick.h>
 #include <trace/events/power.h>
 #include <linux/sched.h>
 #include <linux/notifier.h>
@@ -638,12 +638,12 @@ static int intel_idle(struct cpuidle_device *dev,
                leave_mm(cpu);
 
        if (!(lapic_timer_reliable_states & (1 << (cstate))))
-               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+               tick_broadcast_enter();
 
        mwait_idle_with_hints(eax, ecx);
 
        if (!(lapic_timer_reliable_states & (1 << (cstate))))
-               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+               tick_broadcast_exit();
 
        return index;
 }
@@ -665,13 +665,12 @@ static void intel_idle_freeze(struct cpuidle_device *dev,
 
 static void __setup_broadcast_timer(void *arg)
 {
-       unsigned long reason = (unsigned long)arg;
-       int cpu = smp_processor_id();
-
-       reason = reason ?
-               CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF;
+       unsigned long on = (unsigned long)arg;
 
-       clockevents_notify(reason, &cpu);
+       if (on)
+               tick_broadcast_enable();
+       else
+               tick_broadcast_disable();
 }
 
 static int cpu_hotplug_notify(struct notifier_block *n,
index 75567fd457dcc4b9bd7c147fdc4cb229cdbaf0c4..73e87739d2191831187ab30416b4111dcfda8ecc 100644 (file)
@@ -70,7 +70,9 @@
 #define BMC150_ACCEL_INT_MAP_0_BIT_SLOPE       BIT(2)
 
 #define BMC150_ACCEL_REG_INT_MAP_1             0x1A
-#define BMC150_ACCEL_INT_MAP_1_BIT_DATA        BIT(0)
+#define BMC150_ACCEL_INT_MAP_1_BIT_DATA                BIT(0)
+#define BMC150_ACCEL_INT_MAP_1_BIT_FWM         BIT(1)
+#define BMC150_ACCEL_INT_MAP_1_BIT_FFULL       BIT(2)
 
 #define BMC150_ACCEL_REG_INT_RST_LATCH         0x21
 #define BMC150_ACCEL_INT_MODE_LATCH_RESET      0x80
@@ -83,7 +85,9 @@
 #define BMC150_ACCEL_INT_EN_BIT_SLP_Z          BIT(2)
 
 #define BMC150_ACCEL_REG_INT_EN_1              0x17
-#define BMC150_ACCEL_INT_EN_BIT_DATA_EN        BIT(4)
+#define BMC150_ACCEL_INT_EN_BIT_DATA_EN                BIT(4)
+#define BMC150_ACCEL_INT_EN_BIT_FFULL_EN       BIT(5)
+#define BMC150_ACCEL_INT_EN_BIT_FWM_EN         BIT(6)
 
 #define BMC150_ACCEL_REG_INT_OUT_CTRL          0x20
 #define BMC150_ACCEL_INT_OUT_CTRL_INT1_LVL     BIT(0)
 #define BMC150_ACCEL_AXIS_TO_REG(axis) (BMC150_ACCEL_REG_XOUT_L + (axis * 2))
 #define BMC150_AUTO_SUSPEND_DELAY_MS           2000
 
+#define BMC150_ACCEL_REG_FIFO_STATUS           0x0E
+#define BMC150_ACCEL_REG_FIFO_CONFIG0          0x30
+#define BMC150_ACCEL_REG_FIFO_CONFIG1          0x3E
+#define BMC150_ACCEL_REG_FIFO_DATA             0x3F
+#define BMC150_ACCEL_FIFO_LENGTH               32
+
 enum bmc150_accel_axis {
        AXIS_X,
        AXIS_Y,
@@ -147,20 +157,46 @@ struct bmc150_accel_chip_info {
        const struct bmc150_scale_info scale_table[4];
 };
 
+struct bmc150_accel_interrupt {
+       const struct bmc150_accel_interrupt_info *info;
+       atomic_t users;
+};
+
+struct bmc150_accel_trigger {
+       struct bmc150_accel_data *data;
+       struct iio_trigger *indio_trig;
+       int (*setup)(struct bmc150_accel_trigger *t, bool state);
+       int intr;
+       bool enabled;
+};
+
+enum bmc150_accel_interrupt_id {
+       BMC150_ACCEL_INT_DATA_READY,
+       BMC150_ACCEL_INT_ANY_MOTION,
+       BMC150_ACCEL_INT_WATERMARK,
+       BMC150_ACCEL_INTERRUPTS,
+};
+
+enum bmc150_accel_trigger_id {
+       BMC150_ACCEL_TRIGGER_DATA_READY,
+       BMC150_ACCEL_TRIGGER_ANY_MOTION,
+       BMC150_ACCEL_TRIGGERS,
+};
+
 struct bmc150_accel_data {
        struct i2c_client *client;
-       struct iio_trigger *dready_trig;
-       struct iio_trigger *motion_trig;
+       struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS];
+       atomic_t active_intr;
+       struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS];
        struct mutex mutex;
+       u8 fifo_mode, watermark;
        s16 buffer[8];
        u8 bw_bits;
        u32 slope_dur;
        u32 slope_thres;
        u32 range;
        int ev_enable_state;
-       bool dready_trigger_on;
-       bool motion_trigger_on;
-       int64_t timestamp;
+       int64_t timestamp, old_timestamp;
        const struct bmc150_accel_chip_info *chip_info;
 };
 
@@ -269,6 +305,46 @@ static int bmc150_accel_set_bw(struct bmc150_accel_data *data, int val,
        return -EINVAL;
 }
 
+static int bmc150_accel_update_slope(struct bmc150_accel_data *data)
+{
+       int ret, val;
+
+       ret = i2c_smbus_write_byte_data(data->client, BMC150_ACCEL_REG_INT_6,
+                                       data->slope_thres);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error writing reg_int_6\n");
+               return ret;
+       }
+
+       ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_INT_5);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error reading reg_int_5\n");
+               return ret;
+       }
+
+       val = (ret & ~BMC150_ACCEL_SLOPE_DUR_MASK) | data->slope_dur;
+       ret = i2c_smbus_write_byte_data(data->client, BMC150_ACCEL_REG_INT_5,
+                                       val);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error write reg_int_5\n");
+               return ret;
+       }
+
+       dev_dbg(&data->client->dev, "%s: %x %x\n", __func__, data->slope_thres,
+               data->slope_dur);
+
+       return ret;
+}
+
+static int bmc150_accel_any_motion_setup(struct bmc150_accel_trigger *t,
+                                        bool state)
+{
+       if (state)
+               return bmc150_accel_update_slope(t->data);
+
+       return 0;
+}
+
 static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
 {
        int ret;
@@ -307,32 +383,12 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
 
        data->range = BMC150_ACCEL_DEF_RANGE_4G;
 
-       /* Set default slope duration */
-       ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_INT_5);
-       if (ret < 0) {
-               dev_err(&data->client->dev, "Error reading reg_int_5\n");
-               return ret;
-       }
-       data->slope_dur |= BMC150_ACCEL_DEF_SLOPE_DURATION;
-       ret = i2c_smbus_write_byte_data(data->client,
-                                       BMC150_ACCEL_REG_INT_5,
-                                       data->slope_dur);
-       if (ret < 0) {
-               dev_err(&data->client->dev, "Error writing reg_int_5\n");
-               return ret;
-       }
-       dev_dbg(&data->client->dev, "slope_dur %x\n", data->slope_dur);
-
-       /* Set default slope thresholds */
-       ret = i2c_smbus_write_byte_data(data->client,
-                                       BMC150_ACCEL_REG_INT_6,
-                                       BMC150_ACCEL_DEF_SLOPE_THRESHOLD);
-       if (ret < 0) {
-               dev_err(&data->client->dev, "Error writing reg_int_6\n");
-               return ret;
-       }
+       /* Set default slope duration and thresholds */
        data->slope_thres = BMC150_ACCEL_DEF_SLOPE_THRESHOLD;
-       dev_dbg(&data->client->dev, "slope_thres %x\n", data->slope_thres);
+       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,
@@ -348,155 +404,6 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
        return 0;
 }
 
-static int bmc150_accel_setup_any_motion_interrupt(
-                                       struct bmc150_accel_data *data,
-                                       bool status)
-{
-       int ret;
-
-       /* Enable/Disable INT1 mapping */
-       ret = i2c_smbus_read_byte_data(data->client,
-                                      BMC150_ACCEL_REG_INT_MAP_0);
-       if (ret < 0) {
-               dev_err(&data->client->dev, "Error reading reg_int_map_0\n");
-               return ret;
-       }
-       if (status)
-               ret |= BMC150_ACCEL_INT_MAP_0_BIT_SLOPE;
-       else
-               ret &= ~BMC150_ACCEL_INT_MAP_0_BIT_SLOPE;
-
-       ret = i2c_smbus_write_byte_data(data->client,
-                                       BMC150_ACCEL_REG_INT_MAP_0,
-                                       ret);
-       if (ret < 0) {
-               dev_err(&data->client->dev, "Error writing reg_int_map_0\n");
-               return ret;
-       }
-
-       if (status) {
-               /* Set slope duration (no of samples) */
-               ret = i2c_smbus_write_byte_data(data->client,
-                                               BMC150_ACCEL_REG_INT_5,
-                                               data->slope_dur);
-               if (ret < 0) {
-                       dev_err(&data->client->dev, "Error write reg_int_5\n");
-                       return ret;
-               }
-
-               /* Set slope thresholds */
-               ret = i2c_smbus_write_byte_data(data->client,
-                                               BMC150_ACCEL_REG_INT_6,
-                                               data->slope_thres);
-               if (ret < 0) {
-                       dev_err(&data->client->dev, "Error write reg_int_6\n");
-                       return ret;
-               }
-
-               /*
-                * New data interrupt is always non-latched,
-                * which will have higher priority, so no need
-                * to set latched mode, we will be flooded anyway with INTR
-                */
-               if (!data->dready_trigger_on) {
-                       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;
-                       }
-               }
-
-               ret = i2c_smbus_write_byte_data(data->client,
-                                               BMC150_ACCEL_REG_INT_EN_0,
-                                               BMC150_ACCEL_INT_EN_BIT_SLP_X |
-                                               BMC150_ACCEL_INT_EN_BIT_SLP_Y |
-                                               BMC150_ACCEL_INT_EN_BIT_SLP_Z);
-       } else
-               ret = i2c_smbus_write_byte_data(data->client,
-                                               BMC150_ACCEL_REG_INT_EN_0,
-                                               0);
-
-       if (ret < 0) {
-               dev_err(&data->client->dev, "Error writing reg_int_en_0\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-static int bmc150_accel_setup_new_data_interrupt(struct bmc150_accel_data *data,
-                                          bool status)
-{
-       int ret;
-
-       /* Enable/Disable INT1 mapping */
-       ret = i2c_smbus_read_byte_data(data->client,
-                                      BMC150_ACCEL_REG_INT_MAP_1);
-       if (ret < 0) {
-               dev_err(&data->client->dev, "Error reading reg_int_map_1\n");
-               return ret;
-       }
-       if (status)
-               ret |= BMC150_ACCEL_INT_MAP_1_BIT_DATA;
-       else
-               ret &= ~BMC150_ACCEL_INT_MAP_1_BIT_DATA;
-
-       ret = i2c_smbus_write_byte_data(data->client,
-                                       BMC150_ACCEL_REG_INT_MAP_1,
-                                       ret);
-       if (ret < 0) {
-               dev_err(&data->client->dev, "Error writing reg_int_map_1\n");
-               return ret;
-       }
-
-       if (status) {
-               /*
-                * Set non latched mode interrupt and clear any latched
-                * interrupt
-                */
-               ret = i2c_smbus_write_byte_data(data->client,
-                                       BMC150_ACCEL_REG_INT_RST_LATCH,
-                                       BMC150_ACCEL_INT_MODE_NON_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;
-               }
-
-               ret = i2c_smbus_write_byte_data(data->client,
-                                       BMC150_ACCEL_REG_INT_EN_1,
-                                       BMC150_ACCEL_INT_EN_BIT_DATA_EN);
-
-       } else {
-               /* Restore default interrupt mode */
-               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;
-               }
-
-               ret = i2c_smbus_write_byte_data(data->client,
-                                               BMC150_ACCEL_REG_INT_EN_1,
-                                               0);
-       }
-
-       if (ret < 0) {
-               dev_err(&data->client->dev, "Error writing reg_int_en_1\n");
-               return ret;
-       }
-
-       return 0;
-}
-
 static int bmc150_accel_get_bw(struct bmc150_accel_data *data, int *val,
                               int *val2)
 {
@@ -554,6 +461,120 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
 }
 #endif
 
+static const struct bmc150_accel_interrupt_info {
+       u8 map_reg;
+       u8 map_bitmask;
+       u8 en_reg;
+       u8 en_bitmask;
+} bmc150_accel_interrupts[BMC150_ACCEL_INTERRUPTS] = {
+       { /* data ready interrupt */
+               .map_reg = BMC150_ACCEL_REG_INT_MAP_1,
+               .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_DATA,
+               .en_reg = BMC150_ACCEL_REG_INT_EN_1,
+               .en_bitmask = BMC150_ACCEL_INT_EN_BIT_DATA_EN,
+       },
+       {  /* motion interrupt */
+               .map_reg = BMC150_ACCEL_REG_INT_MAP_0,
+               .map_bitmask = BMC150_ACCEL_INT_MAP_0_BIT_SLOPE,
+               .en_reg = BMC150_ACCEL_REG_INT_EN_0,
+               .en_bitmask =  BMC150_ACCEL_INT_EN_BIT_SLP_X |
+                       BMC150_ACCEL_INT_EN_BIT_SLP_Y |
+                       BMC150_ACCEL_INT_EN_BIT_SLP_Z
+       },
+       { /* fifo watermark interrupt */
+               .map_reg = BMC150_ACCEL_REG_INT_MAP_1,
+               .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_FWM,
+               .en_reg = BMC150_ACCEL_REG_INT_EN_1,
+               .en_bitmask = BMC150_ACCEL_INT_EN_BIT_FWM_EN,
+       },
+};
+
+static void bmc150_accel_interrupts_setup(struct iio_dev *indio_dev,
+                                         struct bmc150_accel_data *data)
+{
+       int i;
+
+       for (i = 0; i < BMC150_ACCEL_INTERRUPTS; i++)
+               data->interrupts[i].info = &bmc150_accel_interrupts[i];
+}
+
+static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
+                                     bool state)
+{
+       struct bmc150_accel_interrupt *intr = &data->interrupts[i];
+       const struct bmc150_accel_interrupt_info *info = intr->info;
+       int ret;
+
+       if (state) {
+               if (atomic_inc_return(&intr->users) > 1)
+                       return 0;
+       } else {
+               if (atomic_dec_return(&intr->users) > 0)
+                       return 0;
+       }
+
+       /*
+        * 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
+        */
+       ret = bmc150_accel_set_power_state(data, state);
+       if (ret < 0)
+               return ret;
+
+       /* map the interrupt to the appropriate pins */
+       ret = i2c_smbus_read_byte_data(data->client, info->map_reg);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error reading reg_int_map\n");
+               goto out_fix_power_state;
+       }
+       if (state)
+               ret |= info->map_bitmask;
+       else
+               ret &= ~info->map_bitmask;
+
+       ret = i2c_smbus_write_byte_data(data->client, info->map_reg,
+                                       ret);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error writing reg_int_map\n");
+               goto out_fix_power_state;
+       }
+
+       /* enable/disable the interrupt */
+       ret = i2c_smbus_read_byte_data(data->client, info->en_reg);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error reading reg_int_en\n");
+               goto out_fix_power_state;
+       }
+
+       if (state)
+               ret |= info->en_bitmask;
+       else
+               ret &= ~info->en_bitmask;
+
+       ret = i2c_smbus_write_byte_data(data->client, info->en_reg, ret);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error writing reg_int_en\n");
+               goto out_fix_power_state;
+       }
+
+       if (state)
+               atomic_inc(&data->active_intr);
+       else
+               atomic_dec(&data->active_intr);
+
+       return 0;
+
+out_fix_power_state:
+       bmc150_accel_set_power_state(data, false);
+       return ret;
+}
+
+
 static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
 {
        int ret, i;
@@ -732,7 +753,7 @@ static int bmc150_accel_read_event(struct iio_dev *indio_dev,
                *val = data->slope_thres;
                break;
        case IIO_EV_INFO_PERIOD:
-               *val = data->slope_dur & BMC150_ACCEL_SLOPE_DUR_MASK;
+               *val = data->slope_dur;
                break;
        default:
                return -EINVAL;
@@ -755,11 +776,10 @@ static int bmc150_accel_write_event(struct iio_dev *indio_dev,
 
        switch (info) {
        case IIO_EV_INFO_VALUE:
-               data->slope_thres = val;
+               data->slope_thres = val & 0xFF;
                break;
        case IIO_EV_INFO_PERIOD:
-               data->slope_dur &= ~BMC150_ACCEL_SLOPE_DUR_MASK;
-               data->slope_dur |= val & BMC150_ACCEL_SLOPE_DUR_MASK;
+               data->slope_dur = val & BMC150_ACCEL_SLOPE_DUR_MASK;
                break;
        default:
                return -EINVAL;
@@ -788,36 +808,14 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev,
        struct bmc150_accel_data *data = iio_priv(indio_dev);
        int ret;
 
-       if (state && data->ev_enable_state)
+       if (state == data->ev_enable_state)
                return 0;
 
        mutex_lock(&data->mutex);
 
-       if (!state && data->motion_trigger_on) {
-               data->ev_enable_state = 0;
-               mutex_unlock(&data->mutex);
-               return 0;
-       }
-
-       /*
-        * 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
-        */
-
-       ret = bmc150_accel_set_power_state(data, state);
-       if (ret < 0) {
-               mutex_unlock(&data->mutex);
-               return ret;
-       }
-
-       ret =  bmc150_accel_setup_any_motion_interrupt(data, state);
+       ret = bmc150_accel_set_interrupt(data, BMC150_ACCEL_INT_ANY_MOTION,
+                                        state);
        if (ret < 0) {
-               bmc150_accel_set_power_state(data, false);
                mutex_unlock(&data->mutex);
                return ret;
        }
@@ -832,13 +830,224 @@ static int bmc150_accel_validate_trigger(struct iio_dev *indio_dev,
                                   struct iio_trigger *trig)
 {
        struct bmc150_accel_data *data = iio_priv(indio_dev);
+       int i;
 
-       if (data->dready_trig != trig && data->motion_trig != trig)
-               return -EINVAL;
+       for (i = 0; i < BMC150_ACCEL_TRIGGERS; i++) {
+               if (data->triggers[i].indio_trig == trig)
+                       return 0;
+       }
+
+       return -EINVAL;
+}
+
+static ssize_t bmc150_accel_get_fifo_watermark(struct device *dev,
+                                              struct device_attribute *attr,
+                                              char *buf)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct bmc150_accel_data *data = iio_priv(indio_dev);
+       int wm;
+
+       mutex_lock(&data->mutex);
+       wm = data->watermark;
+       mutex_unlock(&data->mutex);
+
+       return sprintf(buf, "%d\n", wm);
+}
+
+static ssize_t bmc150_accel_get_fifo_state(struct device *dev,
+                                          struct device_attribute *attr,
+                                          char *buf)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct bmc150_accel_data *data = iio_priv(indio_dev);
+       bool state;
+
+       mutex_lock(&data->mutex);
+       state = data->fifo_mode;
+       mutex_unlock(&data->mutex);
+
+       return sprintf(buf, "%d\n", state);
+}
+
+static IIO_CONST_ATTR(hwfifo_watermark_min, "1");
+static IIO_CONST_ATTR(hwfifo_watermark_max,
+                     __stringify(BMC150_ACCEL_FIFO_LENGTH));
+static IIO_DEVICE_ATTR(hwfifo_enabled, S_IRUGO,
+                      bmc150_accel_get_fifo_state, NULL, 0);
+static IIO_DEVICE_ATTR(hwfifo_watermark, S_IRUGO,
+                      bmc150_accel_get_fifo_watermark, NULL, 0);
+
+static const struct attribute *bmc150_accel_fifo_attributes[] = {
+       &iio_const_attr_hwfifo_watermark_min.dev_attr.attr,
+       &iio_const_attr_hwfifo_watermark_max.dev_attr.attr,
+       &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
+       &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
+       NULL,
+};
+
+static int bmc150_accel_set_watermark(struct iio_dev *indio_dev, unsigned val)
+{
+       struct bmc150_accel_data *data = iio_priv(indio_dev);
+
+       if (val > BMC150_ACCEL_FIFO_LENGTH)
+               val = BMC150_ACCEL_FIFO_LENGTH;
+
+       mutex_lock(&data->mutex);
+       data->watermark = val;
+       mutex_unlock(&data->mutex);
 
        return 0;
 }
 
+/*
+ * We must read at least one full frame in one burst, otherwise the rest of the
+ * frame data is discarded.
+ */
+static int bmc150_accel_fifo_transfer(const struct i2c_client *client,
+                                     char *buffer, int samples)
+{
+       int sample_length = 3 * 2;
+       u8 reg_fifo_data = BMC150_ACCEL_REG_FIFO_DATA;
+       int ret = -EIO;
+
+       if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               struct i2c_msg msg[2] = {
+                       {
+                               .addr = client->addr,
+                               .flags = 0,
+                               .buf = &reg_fifo_data,
+                               .len = sizeof(reg_fifo_data),
+                       },
+                       {
+                               .addr = client->addr,
+                               .flags = I2C_M_RD,
+                               .buf = (u8 *)buffer,
+                               .len = samples * sample_length,
+                       }
+               };
+
+               ret = i2c_transfer(client->adapter, msg, 2);
+               if (ret != 2)
+                       ret = -EIO;
+               else
+                       ret = 0;
+       } else {
+               int i, step = I2C_SMBUS_BLOCK_MAX / sample_length;
+
+               for (i = 0; i < samples * sample_length; i += step) {
+                       ret = i2c_smbus_read_i2c_block_data(client,
+                                                           reg_fifo_data, step,
+                                                           &buffer[i]);
+                       if (ret != step) {
+                               ret = -EIO;
+                               break;
+                       }
+
+                       ret = 0;
+               }
+       }
+
+       if (ret)
+               dev_err(&client->dev, "Error transferring data from fifo\n");
+
+       return ret;
+}
+
+static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
+                                    unsigned samples, bool irq)
+{
+       struct bmc150_accel_data *data = iio_priv(indio_dev);
+       int ret, i;
+       u8 count;
+       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) {
+               dev_err(&data->client->dev, "Error reading reg_fifo_status\n");
+               return ret;
+       }
+
+       count = ret & 0x7F;
+
+       if (!count)
+               return 0;
+
+       /*
+        * If we getting called from IRQ handler we know the stored timestamp is
+        * fairly accurate for the last stored sample. Otherwise, if we are
+        * called as a result of a read operation from userspace and hence
+        * before the watermark interrupt was triggered, take a timestamp
+        * now. We can fall anywhere in between two samples so the error in this
+        * case is at most one sample period.
+        */
+       if (!irq) {
+               data->old_timestamp = data->timestamp;
+               data->timestamp = iio_get_time_ns();
+       }
+
+       /*
+        * Approximate timestamps for each of the sample based on the sampling
+        * frequency, timestamp for last sample and number of samples.
+        *
+        * Note that we can't use the current bandwidth settings to compute the
+        * sample period because the sample rate varies with the device
+        * (e.g. between 31.70ms to 32.20ms for a bandwidth of 15.63HZ). That
+        * small variation adds when we store a large number of samples and
+        * creates significant jitter between the last and first samples in
+        * different batches (e.g. 32ms vs 21ms).
+        *
+        * To avoid this issue we compute the actual sample period ourselves
+        * based on the timestamp delta between the last two flush operations.
+        */
+       sample_period = (data->timestamp - data->old_timestamp);
+       do_div(sample_period, count);
+       tstamp = data->timestamp - (count - 1) * sample_period;
+
+       if (samples && count > samples)
+               count = samples;
+
+       ret = bmc150_accel_fifo_transfer(data->client, (u8 *)buffer, count);
+       if (ret)
+               return ret;
+
+       /*
+        * Ideally we want the IIO core to handle the demux when running in fifo
+        * mode but not when running in triggered buffer mode. Unfortunately
+        * this does not seem to be possible, so stick with driver demux for
+        * now.
+        */
+       for (i = 0; i < count; i++) {
+               u16 sample[8];
+               int j, bit;
+
+               j = 0;
+               for_each_set_bit(bit, indio_dev->active_scan_mask,
+                                indio_dev->masklength)
+                       memcpy(&sample[j++], &buffer[i * 3 + bit], 2);
+
+               iio_push_to_buffers_with_timestamp(indio_dev, sample, tstamp);
+
+               tstamp += sample_period;
+       }
+
+       return count;
+}
+
+static int bmc150_accel_fifo_flush(struct iio_dev *indio_dev, unsigned samples)
+{
+       struct bmc150_accel_data *data = iio_priv(indio_dev);
+       int ret;
+
+       mutex_lock(&data->mutex);
+       ret = __bmc150_accel_fifo_flush(indio_dev, samples, false);
+       mutex_unlock(&data->mutex);
+
+       return ret;
+}
+
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
                "15.620000 31.260000 62.50000 125 250 500 1000 2000");
 
@@ -978,6 +1187,20 @@ static const struct iio_info bmc150_accel_info = {
        .driver_module          = THIS_MODULE,
 };
 
+static const struct iio_info bmc150_accel_info_fifo = {
+       .attrs                  = &bmc150_accel_attrs_group,
+       .read_raw               = bmc150_accel_read_raw,
+       .write_raw              = bmc150_accel_write_raw,
+       .read_event_value       = bmc150_accel_read_event,
+       .write_event_value      = bmc150_accel_write_event,
+       .write_event_config     = bmc150_accel_write_event_config,
+       .read_event_config      = bmc150_accel_read_event_config,
+       .validate_trigger       = bmc150_accel_validate_trigger,
+       .hwfifo_set_watermark   = bmc150_accel_set_watermark,
+       .hwfifo_flush_to_buffer = bmc150_accel_fifo_flush,
+       .driver_module          = THIS_MODULE,
+};
+
 static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p)
 {
        struct iio_poll_func *pf = p;
@@ -1008,12 +1231,12 @@ err_read:
 
 static int bmc150_accel_trig_try_reen(struct iio_trigger *trig)
 {
-       struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
-       struct bmc150_accel_data *data = iio_priv(indio_dev);
+       struct bmc150_accel_trigger *t = iio_trigger_get_drvdata(trig);
+       struct bmc150_accel_data *data = t->data;
        int ret;
 
        /* new data interrupts don't need ack */
-       if (data->dready_trigger_on)
+       if (t == &t->data->triggers[BMC150_ACCEL_TRIGGER_DATA_READY])
                return 0;
 
        mutex_lock(&data->mutex);
@@ -1032,43 +1255,35 @@ static int bmc150_accel_trig_try_reen(struct iio_trigger *trig)
        return 0;
 }
 
-static int bmc150_accel_data_rdy_trigger_set_state(struct iio_trigger *trig,
+static int bmc150_accel_trigger_set_state(struct iio_trigger *trig,
                                                   bool state)
 {
-       struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
-       struct bmc150_accel_data *data = iio_priv(indio_dev);
+       struct bmc150_accel_trigger *t = iio_trigger_get_drvdata(trig);
+       struct bmc150_accel_data *data = t->data;
        int ret;
 
        mutex_lock(&data->mutex);
 
-       if (!state && data->ev_enable_state && data->motion_trigger_on) {
-               data->motion_trigger_on = false;
+       if (t->enabled == state) {
                mutex_unlock(&data->mutex);
                return 0;
        }
 
-       /*
-        * Refer to comment in bmc150_accel_write_event_config for
-        * enable/disable operation order
-        */
-       ret = bmc150_accel_set_power_state(data, state);
-       if (ret < 0) {
-               mutex_unlock(&data->mutex);
-               return ret;
+       if (t->setup) {
+               ret = t->setup(t, state);
+               if (ret < 0) {
+                       mutex_unlock(&data->mutex);
+                       return ret;
+               }
        }
-       if (data->motion_trig == trig)
-               ret =  bmc150_accel_setup_any_motion_interrupt(data, state);
-       else
-               ret = bmc150_accel_setup_new_data_interrupt(data, state);
+
+       ret = bmc150_accel_set_interrupt(data, t->intr, state);
        if (ret < 0) {
-               bmc150_accel_set_power_state(data, false);
                mutex_unlock(&data->mutex);
                return ret;
        }
-       if (data->motion_trig == trig)
-               data->motion_trigger_on = state;
-       else
-               data->dready_trigger_on = state;
+
+       t->enabled = state;
 
        mutex_unlock(&data->mutex);
 
@@ -1076,23 +1291,22 @@ static int bmc150_accel_data_rdy_trigger_set_state(struct iio_trigger *trig,
 }
 
 static const struct iio_trigger_ops bmc150_accel_trigger_ops = {
-       .set_trigger_state = bmc150_accel_data_rdy_trigger_set_state,
+       .set_trigger_state = bmc150_accel_trigger_set_state,
        .try_reenable = bmc150_accel_trig_try_reen,
        .owner = THIS_MODULE,
 };
 
-static irqreturn_t bmc150_accel_event_handler(int irq, void *private)
+static int bmc150_accel_handle_roc_event(struct iio_dev *indio_dev)
 {
-       struct iio_dev *indio_dev = private;
        struct bmc150_accel_data *data = iio_priv(indio_dev);
-       int ret;
        int dir;
+       int ret;
 
        ret = i2c_smbus_read_byte_data(data->client,
                                       BMC150_ACCEL_REG_INT_STATUS_2);
        if (ret < 0) {
                dev_err(&data->client->dev, "Error reading reg_int_status_2\n");
-               goto ack_intr_status;
+               return ret;
        }
 
        if (ret & BMC150_ACCEL_ANY_MOTION_BIT_SIGN)
@@ -1121,32 +1335,73 @@ static irqreturn_t bmc150_accel_event_handler(int irq, void *private)
                                                        IIO_EV_TYPE_ROC,
                                                        dir),
                                                        data->timestamp);
-ack_intr_status:
-       if (!data->dready_trigger_on)
+       return ret;
+}
+
+static irqreturn_t bmc150_accel_irq_thread_handler(int irq, void *private)
+{
+       struct iio_dev *indio_dev = private;
+       struct bmc150_accel_data *data = iio_priv(indio_dev);
+       bool ack = false;
+       int ret;
+
+       mutex_lock(&data->mutex);
+
+       if (data->fifo_mode) {
+               ret = __bmc150_accel_fifo_flush(indio_dev,
+                                               BMC150_ACCEL_FIFO_LENGTH, true);
+               if (ret > 0)
+                       ack = true;
+       }
+
+       if (data->ev_enable_state) {
+               ret = bmc150_accel_handle_roc_event(indio_dev);
+               if (ret > 0)
+                       ack = true;
+       }
+
+       if (ack) {
                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)
+                       dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
+               ret = IRQ_HANDLED;
+       } else {
+               ret = IRQ_NONE;
+       }
 
-       return IRQ_HANDLED;
+       mutex_unlock(&data->mutex);
+
+       return ret;
 }
 
-static irqreturn_t bmc150_accel_data_rdy_trig_poll(int irq, void *private)
+static irqreturn_t bmc150_accel_irq_handler(int irq, void *private)
 {
        struct iio_dev *indio_dev = private;
        struct bmc150_accel_data *data = iio_priv(indio_dev);
+       bool ack = false;
+       int i;
 
+       data->old_timestamp = data->timestamp;
        data->timestamp = iio_get_time_ns();
 
-       if (data->dready_trigger_on)
-               iio_trigger_poll(data->dready_trig);
-       else if (data->motion_trigger_on)
-               iio_trigger_poll(data->motion_trig);
+       for (i = 0; i < BMC150_ACCEL_TRIGGERS; i++) {
+               if (data->triggers[i].enabled) {
+                       iio_trigger_poll(data->triggers[i].indio_trig);
+                       ack = true;
+                       break;
+               }
+       }
 
-       if (data->ev_enable_state)
+       if (data->ev_enable_state || data->fifo_mode)
                return IRQ_WAKE_THREAD;
-       else
+
+       if (ack)
                return IRQ_HANDLED;
+
+       return IRQ_NONE;
 }
 
 static const char *bmc150_accel_match_acpi_device(struct device *dev, int *data)
@@ -1176,23 +1431,171 @@ static int bmc150_accel_gpio_probe(struct i2c_client *client,
        dev = &client->dev;
 
        /* data ready gpio interrupt pin */
-       gpio = devm_gpiod_get_index(dev, BMC150_ACCEL_GPIO_NAME, 0);
+       gpio = devm_gpiod_get_index(dev, BMC150_ACCEL_GPIO_NAME, 0, GPIOD_IN);
        if (IS_ERR(gpio)) {
                dev_err(dev, "Failed: gpio get index\n");
                return PTR_ERR(gpio);
        }
 
-       ret = gpiod_direction_input(gpio);
+       ret = gpiod_to_irq(gpio);
+
+       dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
+
+       return ret;
+}
+
+static const struct {
+       int intr;
+       const char *name;
+       int (*setup)(struct bmc150_accel_trigger *t, bool state);
+} bmc150_accel_triggers[BMC150_ACCEL_TRIGGERS] = {
+       {
+               .intr = 0,
+               .name = "%s-dev%d",
+       },
+       {
+               .intr = 1,
+               .name = "%s-any-motion-dev%d",
+               .setup = bmc150_accel_any_motion_setup,
+       },
+};
+
+static void bmc150_accel_unregister_triggers(struct bmc150_accel_data *data,
+                                            int from)
+{
+       int i;
+
+       for (i = from; i >= 0; i++) {
+               if (data->triggers[i].indio_trig) {
+                       iio_trigger_unregister(data->triggers[i].indio_trig);
+                       data->triggers[i].indio_trig = NULL;
+               }
+       }
+}
+
+static int bmc150_accel_triggers_setup(struct iio_dev *indio_dev,
+                                      struct bmc150_accel_data *data)
+{
+       int i, ret;
+
+       for (i = 0; i < BMC150_ACCEL_TRIGGERS; i++) {
+               struct bmc150_accel_trigger *t = &data->triggers[i];
+
+               t->indio_trig = devm_iio_trigger_alloc(&data->client->dev,
+                                              bmc150_accel_triggers[i].name,
+                                                      indio_dev->name,
+                                                      indio_dev->id);
+               if (!t->indio_trig) {
+                       ret = -ENOMEM;
+                       break;
+               }
+
+               t->indio_trig->dev.parent = &data->client->dev;
+               t->indio_trig->ops = &bmc150_accel_trigger_ops;
+               t->intr = bmc150_accel_triggers[i].intr;
+               t->data = data;
+               t->setup = bmc150_accel_triggers[i].setup;
+               iio_trigger_set_drvdata(t->indio_trig, t);
+
+               ret = iio_trigger_register(t->indio_trig);
+               if (ret)
+                       break;
+       }
+
        if (ret)
+               bmc150_accel_unregister_triggers(data, i - 1);
+
+       return ret;
+}
+
+#define BMC150_ACCEL_FIFO_MODE_STREAM          0x80
+#define BMC150_ACCEL_FIFO_MODE_FIFO            0x40
+#define BMC150_ACCEL_FIFO_MODE_BYPASS          0x00
+
+static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
+{
+       u8 reg = BMC150_ACCEL_REG_FIFO_CONFIG1;
+       int ret;
+
+       ret = i2c_smbus_write_byte_data(data->client, reg, data->fifo_mode);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error writing reg_fifo_config1\n");
                return ret;
+       }
 
-       ret = gpiod_to_irq(gpio);
+       if (!data->fifo_mode)
+               return 0;
 
-       dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
+       ret = i2c_smbus_write_byte_data(data->client,
+                                       BMC150_ACCEL_REG_FIFO_CONFIG0,
+                                       data->watermark);
+       if (ret < 0)
+               dev_err(&data->client->dev, "Error writing reg_fifo_config0\n");
 
        return ret;
 }
 
+static int bmc150_accel_buffer_postenable(struct iio_dev *indio_dev)
+{
+       struct bmc150_accel_data *data = iio_priv(indio_dev);
+       int ret = 0;
+
+       if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED)
+               return iio_triggered_buffer_postenable(indio_dev);
+
+       mutex_lock(&data->mutex);
+
+       if (!data->watermark)
+               goto out;
+
+       ret = bmc150_accel_set_interrupt(data, BMC150_ACCEL_INT_WATERMARK,
+                                        true);
+       if (ret)
+               goto out;
+
+       data->fifo_mode = BMC150_ACCEL_FIFO_MODE_FIFO;
+
+       ret = bmc150_accel_fifo_set_mode(data);
+       if (ret) {
+               data->fifo_mode = 0;
+               bmc150_accel_set_interrupt(data, BMC150_ACCEL_INT_WATERMARK,
+                                          false);
+       }
+
+out:
+       mutex_unlock(&data->mutex);
+
+       return ret;
+}
+
+static int bmc150_accel_buffer_predisable(struct iio_dev *indio_dev)
+{
+       struct bmc150_accel_data *data = iio_priv(indio_dev);
+
+       if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED)
+               return iio_triggered_buffer_predisable(indio_dev);
+
+       mutex_lock(&data->mutex);
+
+       if (!data->fifo_mode)
+               goto out;
+
+       bmc150_accel_set_interrupt(data, BMC150_ACCEL_INT_WATERMARK, false);
+       __bmc150_accel_fifo_flush(indio_dev, BMC150_ACCEL_FIFO_LENGTH, false);
+       data->fifo_mode = 0;
+       bmc150_accel_fifo_set_mode(data);
+
+out:
+       mutex_unlock(&data->mutex);
+
+       return 0;
+}
+
+static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = {
+       .postenable = bmc150_accel_buffer_postenable,
+       .predisable = bmc150_accel_buffer_predisable,
+};
+
 static int bmc150_accel_probe(struct i2c_client *client,
                              const struct i2c_device_id *id)
 {
@@ -1239,53 +1642,51 @@ static int bmc150_accel_probe(struct i2c_client *client,
        if (client->irq >= 0) {
                ret = devm_request_threaded_irq(
                                                &client->dev, client->irq,
-                                               bmc150_accel_data_rdy_trig_poll,
-                                               bmc150_accel_event_handler,
+                                               bmc150_accel_irq_handler,
+                                               bmc150_accel_irq_thread_handler,
                                                IRQF_TRIGGER_RISING,
                                                BMC150_ACCEL_IRQ_NAME,
                                                indio_dev);
                if (ret)
                        return ret;
 
-               data->dready_trig = devm_iio_trigger_alloc(&client->dev,
-                                                          "%s-dev%d",
-                                                          indio_dev->name,
-                                                          indio_dev->id);
-               if (!data->dready_trig)
-                       return -ENOMEM;
-
-               data->motion_trig = devm_iio_trigger_alloc(&client->dev,
-                                                         "%s-any-motion-dev%d",
-                                                         indio_dev->name,
-                                                         indio_dev->id);
-               if (!data->motion_trig)
-                       return -ENOMEM;
-
-               data->dready_trig->dev.parent = &client->dev;
-               data->dready_trig->ops = &bmc150_accel_trigger_ops;
-               iio_trigger_set_drvdata(data->dready_trig, indio_dev);
-               ret = iio_trigger_register(data->dready_trig);
-               if (ret)
+               /*
+                * Set latched mode interrupt. While certain interrupts are
+                * non-latched regardless of this settings (e.g. new data) we
+                * want to use latch mode when we can to prevent interrupt
+                * flooding.
+                */
+               ret = i2c_smbus_write_byte_data(data->client,
+                                               BMC150_ACCEL_REG_INT_RST_LATCH,
+                                            BMC150_ACCEL_INT_MODE_LATCH_RESET);
+               if (ret < 0) {
+                       dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
                        return ret;
-
-               data->motion_trig->dev.parent = &client->dev;
-               data->motion_trig->ops = &bmc150_accel_trigger_ops;
-               iio_trigger_set_drvdata(data->motion_trig, indio_dev);
-               ret = iio_trigger_register(data->motion_trig);
-               if (ret) {
-                       data->motion_trig = NULL;
-                       goto err_trigger_unregister;
                }
 
+               bmc150_accel_interrupts_setup(indio_dev, data);
+
+               ret = bmc150_accel_triggers_setup(indio_dev, data);
+               if (ret)
+                       return ret;
+
                ret = iio_triggered_buffer_setup(indio_dev,
                                                 &iio_pollfunc_store_time,
                                                 bmc150_accel_trigger_handler,
-                                                NULL);
+                                                &bmc150_accel_buffer_ops);
                if (ret < 0) {
                        dev_err(&client->dev,
                                "Failed: iio triggered buffer setup\n");
                        goto err_trigger_unregister;
                }
+
+               if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ||
+                   i2c_check_functionality(client->adapter,
+                                           I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+                       indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
+                       indio_dev->info = &bmc150_accel_info_fifo;
+                       indio_dev->buffer->attrs = bmc150_accel_fifo_attributes;
+               }
        }
 
        ret = iio_device_register(indio_dev);
@@ -1308,13 +1709,10 @@ static int bmc150_accel_probe(struct i2c_client *client,
 err_iio_unregister:
        iio_device_unregister(indio_dev);
 err_buffer_cleanup:
-       if (data->dready_trig)
+       if (indio_dev->pollfunc)
                iio_triggered_buffer_cleanup(indio_dev);
 err_trigger_unregister:
-       if (data->dready_trig)
-               iio_trigger_unregister(data->dready_trig);
-       if (data->motion_trig)
-               iio_trigger_unregister(data->motion_trig);
+       bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1);
 
        return ret;
 }
@@ -1330,11 +1728,7 @@ static int bmc150_accel_remove(struct i2c_client *client)
 
        iio_device_unregister(indio_dev);
 
-       if (data->dready_trig) {
-               iio_triggered_buffer_cleanup(indio_dev);
-               iio_trigger_unregister(data->dready_trig);
-               iio_trigger_unregister(data->motion_trig);
-       }
+       bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1);
 
        mutex_lock(&data->mutex);
        bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_DEEP_SUSPEND, 0);
@@ -1362,9 +1756,9 @@ static int bmc150_accel_resume(struct device *dev)
        struct bmc150_accel_data *data = iio_priv(indio_dev);
 
        mutex_lock(&data->mutex);
-       if (data->dready_trigger_on || data->motion_trigger_on ||
-                                                       data->ev_enable_state)
+       if (atomic_read(&data->active_intr))
                bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
+       bmc150_accel_fifo_set_mode(data);
        mutex_unlock(&data->mutex);
 
        return 0;
@@ -1396,6 +1790,9 @@ static int bmc150_accel_runtime_resume(struct device *dev)
        dev_dbg(&data->client->dev,  __func__);
 
        ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
+       if (ret < 0)
+               return ret;
+       ret = bmc150_accel_fifo_set_mode(data);
        if (ret < 0)
                return ret;
 
index df6a593bd4bdbddd5fcd37e3dd3df231c0cfc1a2..2b4fad6998c150b583ed20831b5e3d4c497490fe 100644 (file)
@@ -123,7 +123,8 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
                        *val = sensor_hub_input_attr_get_raw_value(
                                        accel_state->common_attributes.hsdev,
                                        HID_USAGE_SENSOR_ACCEL_3D, address,
-                                       report_id);
+                                       report_id,
+                                       SENSOR_HUB_SYNC);
                else {
                        *val = 0;
                        hid_sensor_power_state(&accel_state->common_attributes,
index 1a6379525fa47e73497b17866be4276fc88c8065..51da3692d561377f7818584156d1d2700c7ef674 100644 (file)
@@ -1169,16 +1169,12 @@ static int kxcjk1013_gpio_probe(struct i2c_client *client,
        dev = &client->dev;
 
        /* data ready gpio interrupt pin */
-       gpio = devm_gpiod_get_index(dev, "kxcjk1013_int", 0);
+       gpio = devm_gpiod_get_index(dev, "kxcjk1013_int", 0, GPIOD_IN);
        if (IS_ERR(gpio)) {
                dev_err(dev, "acpi gpio get index failed\n");
                return PTR_ERR(gpio);
        }
 
-       ret = gpiod_direction_input(gpio);
-       if (ret)
-               return ret;
-
        ret = gpiod_to_irq(gpio);
 
        dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
index 46c38351c6a34644be08ae4ffb309a97259c05d8..7db7cc0bf362fceb3b97c770cc0ef0552dd4c4d3 100644 (file)
@@ -418,17 +418,18 @@ static int mma9551_gpio_probe(struct iio_dev *indio_dev)
        struct device *dev = &data->client->dev;
 
        for (i = 0; i < MMA9551_GPIO_COUNT; i++) {
-               gpio = devm_gpiod_get_index(dev, MMA9551_GPIO_NAME, i);
+               gpio = devm_gpiod_get_index(dev, MMA9551_GPIO_NAME, i,
+                                           GPIOD_IN);
                if (IS_ERR(gpio)) {
                        dev_err(dev, "acpi gpio get index failed\n");
                        return PTR_ERR(gpio);
                }
 
-               ret = gpiod_direction_input(gpio);
-               if (ret)
+               ret = gpiod_to_irq(gpio);
+               if (ret < 0)
                        return ret;
 
-               data->irqs[i] = gpiod_to_irq(gpio);
+               data->irqs[i] = ret;
                ret = devm_request_threaded_irq(dev, data->irqs[i],
                                NULL, mma9551_event_handler,
                                IRQF_TRIGGER_RISING | IRQF_ONESHOT,
index d23ebf192f632ec55f256e128cb1f3a990fc46ff..2df1af7d43fc6df34b87f80373e413152e33a739 100644 (file)
@@ -1109,16 +1109,12 @@ static int mma9553_gpio_probe(struct i2c_client *client)
        dev = &client->dev;
 
        /* data ready gpio interrupt pin */
-       gpio = devm_gpiod_get_index(dev, MMA9553_GPIO_NAME, 0);
+       gpio = devm_gpiod_get_index(dev, MMA9553_GPIO_NAME, 0, GPIOD_IN);
        if (IS_ERR(gpio)) {
                dev_err(dev, "acpi gpio get index failed\n");
                return PTR_ERR(gpio);
        }
 
-       ret = gpiod_direction_input(gpio);
-       if (ret)
-               return ret;
-
        ret = gpiod_to_irq(gpio);
 
        dev_dbg(dev, "gpio resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
index fa964603430501b4cb1a4b73003a043fd16a7b34..7ee9724b1428f67ca5273ebd5235db3765d896ee 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/iio/common/st_sensors.h>
 
+#define LIS3LV02DL_ACCEL_DEV_NAME      "lis3lv02dl_accel"
 #define LSM303DLHC_ACCEL_DEV_NAME      "lsm303dlhc_accel"
 #define LIS3DH_ACCEL_DEV_NAME          "lis3dh"
 #define LSM330D_ACCEL_DEV_NAME         "lsm330d_accel"
index 53f32629283a0d06d3e22d20a91c25b51bd877a2..58d1d13d552ae8cf336061f93603e4dd07b222ac 100644 (file)
 #define ST_ACCEL_3_IG1_EN_MASK                 0x08
 #define ST_ACCEL_3_MULTIREAD_BIT               false
 
+/* CUSTOM VALUES FOR SENSOR 4 */
+#define ST_ACCEL_4_WAI_EXP                     0x3a
+#define ST_ACCEL_4_ODR_ADDR                    0x20
+#define ST_ACCEL_4_ODR_MASK                    0x30 /* DF1 and DF0 */
+#define ST_ACCEL_4_ODR_AVL_40HZ_VAL            0x00
+#define ST_ACCEL_4_ODR_AVL_160HZ_VAL           0x01
+#define ST_ACCEL_4_ODR_AVL_640HZ_VAL           0x02
+#define ST_ACCEL_4_ODR_AVL_2560HZ_VAL          0x03
+#define ST_ACCEL_4_PW_ADDR                     0x20
+#define ST_ACCEL_4_PW_MASK                     0xc0
+#define ST_ACCEL_4_FS_ADDR                     0x21
+#define ST_ACCEL_4_FS_MASK                     0x80
+#define ST_ACCEL_4_FS_AVL_2_VAL                        0X00
+#define ST_ACCEL_4_FS_AVL_6_VAL                        0X01
+#define ST_ACCEL_4_FS_AVL_2_GAIN               IIO_G_TO_M_S_2(1024)
+#define ST_ACCEL_4_FS_AVL_6_GAIN               IIO_G_TO_M_S_2(340)
+#define ST_ACCEL_4_BDU_ADDR                    0x21
+#define ST_ACCEL_4_BDU_MASK                    0x40
+#define ST_ACCEL_4_DRDY_IRQ_ADDR               0x21
+#define ST_ACCEL_4_DRDY_IRQ_INT1_MASK          0x04
+#define ST_ACCEL_4_IG1_EN_ADDR                 0x21
+#define ST_ACCEL_4_IG1_EN_MASK                 0x08
+#define ST_ACCEL_4_MULTIREAD_BIT               true
+
 static const struct iio_chan_spec st_accel_12bit_channels[] = {
        ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
@@ -373,6 +397,63 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
                .multi_read_bit = ST_ACCEL_3_MULTIREAD_BIT,
                .bootime = 2,
        },
+       {
+               .wai = ST_ACCEL_4_WAI_EXP,
+               .sensors_supported = {
+                       [0] = LIS3LV02DL_ACCEL_DEV_NAME,
+               },
+               .ch = (struct iio_chan_spec *)st_accel_12bit_channels,
+               .odr = {
+                       .addr = ST_ACCEL_4_ODR_ADDR,
+                       .mask = ST_ACCEL_4_ODR_MASK,
+                       .odr_avl = {
+                               { 40, ST_ACCEL_4_ODR_AVL_40HZ_VAL },
+                               { 160, ST_ACCEL_4_ODR_AVL_160HZ_VAL, },
+                               { 640, ST_ACCEL_4_ODR_AVL_640HZ_VAL, },
+                               { 2560, ST_ACCEL_4_ODR_AVL_2560HZ_VAL, },
+                       },
+               },
+               .pw = {
+                       .addr = ST_ACCEL_4_PW_ADDR,
+                       .mask = ST_ACCEL_4_PW_MASK,
+                       .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
+                       .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+               },
+               .enable_axis = {
+                       .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
+                       .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
+               },
+               .fs = {
+                       .addr = ST_ACCEL_4_FS_ADDR,
+                       .mask = ST_ACCEL_4_FS_MASK,
+                       .fs_avl = {
+                               [0] = {
+                                       .num = ST_ACCEL_FS_AVL_2G,
+                                       .value = ST_ACCEL_4_FS_AVL_2_VAL,
+                                       .gain = ST_ACCEL_4_FS_AVL_2_GAIN,
+                               },
+                               [1] = {
+                                       .num = ST_ACCEL_FS_AVL_6G,
+                                       .value = ST_ACCEL_4_FS_AVL_6_VAL,
+                                       .gain = ST_ACCEL_4_FS_AVL_6_GAIN,
+                               },
+                       },
+               },
+               .bdu = {
+                       .addr = ST_ACCEL_4_BDU_ADDR,
+                       .mask = ST_ACCEL_4_BDU_MASK,
+               },
+               .drdy_irq = {
+                       .addr = ST_ACCEL_4_DRDY_IRQ_ADDR,
+                       .mask_int1 = ST_ACCEL_4_DRDY_IRQ_INT1_MASK,
+                       .ig1 = {
+                               .en_addr = ST_ACCEL_4_IG1_EN_ADDR,
+                               .en_mask = ST_ACCEL_4_IG1_EN_MASK,
+                       },
+               },
+               .multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT,
+               .bootime = 2, /* guess */
+       },
 };
 
 static int st_accel_read_raw(struct iio_dev *indio_dev,
index c7246bdd30b9532b2d4a8eea6910f532666731b5..6b720c190b2d802293e8836af490ff465dae031e 100644 (file)
 
 #ifdef CONFIG_OF
 static const struct of_device_id st_accel_of_match[] = {
+       {
+               .compatible = "st,lis3lv02dl-accel",
+               .data = LIS3LV02DL_ACCEL_DEV_NAME,
+       },
        {
                .compatible = "st,lsm303dlh-accel",
                .data = LSM303DLH_ACCEL_DEV_NAME,
index 46379b1fb25b59b10018a121b2cc8dc78082d4a6..e36a73e7c3a857775103bb1f9212d56ac2cba09c 100644 (file)
@@ -135,6 +135,15 @@ config AXP288_ADC
          device. Depending on platform configuration, this general purpose ADC can
          be used for sampling sensors such as thermal resistors.
 
+config DA9150_GPADC
+       tristate "Dialog DA9150 GPADC driver support"
+       depends on MFD_DA9150
+       help
+         Say yes here to build support for Dialog DA9150 GPADC.
+
+         This driver can also be built as a module. If chosen, the module name
+         will be da9150-gpadc.
+
 config CC10001_ADC
        tristate "Cosmic Circuits 10001 ADC driver"
        depends on HAVE_CLK || REGULATOR
@@ -187,10 +196,11 @@ config MAX1363
          data via the iio dev interface.
 
 config MCP320X
-       tristate "Microchip Technology MCP3204/08"
+       tristate "Microchip Technology MCP3x01/02/04/08"
        depends on SPI
        help
-         Say yes here to build support for Microchip Technology's MCP3204 or
+         Say yes here to build support for Microchip Technology's
+         MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204 or
          MCP3208 analog to digital converter.
 
          This driver can also be built as a module. If so, the module will be
index 0315af640866dfc85adc0a716bec9ad4bed6dd1c..3930e63e84bccb809b3b98ad9c9cbfae7d2889e3 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_AD7887) += ad7887.o
 obj-$(CONFIG_AD799X) += ad799x.o
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
 obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
+obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
 obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o
 obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
index 4dddeabdfbb02acdd847a79c6a567e8b0e5673b1..b84922a4b32e6bb508c8a5c812a281907102159f 100644 (file)
@@ -861,5 +861,5 @@ static struct spi_driver ad7793_driver = {
 module_spi_driver(ad7793_driver);
 
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("Analog Devices AD7793 and simialr ADCs");
+MODULE_DESCRIPTION("Analog Devices AD7793 and similar ADCs");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c
new file mode 100644 (file)
index 0000000..3445107
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ * DA9150 GPADC Driver
+ *
+ * Copyright (c) 2014 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+#include <linux/mfd/da9150/core.h>
+#include <linux/mfd/da9150/registers.h>
+
+/* Channels */
+enum da9150_gpadc_hw_channel {
+       DA9150_GPADC_HW_CHAN_GPIOA_2V = 0,
+       DA9150_GPADC_HW_CHAN_GPIOA_2V_,
+       DA9150_GPADC_HW_CHAN_GPIOB_2V,
+       DA9150_GPADC_HW_CHAN_GPIOB_2V_,
+       DA9150_GPADC_HW_CHAN_GPIOC_2V,
+       DA9150_GPADC_HW_CHAN_GPIOC_2V_,
+       DA9150_GPADC_HW_CHAN_GPIOD_2V,
+       DA9150_GPADC_HW_CHAN_GPIOD_2V_,
+       DA9150_GPADC_HW_CHAN_IBUS_SENSE,
+       DA9150_GPADC_HW_CHAN_IBUS_SENSE_,
+       DA9150_GPADC_HW_CHAN_VBUS_DIV,
+       DA9150_GPADC_HW_CHAN_VBUS_DIV_,
+       DA9150_GPADC_HW_CHAN_ID,
+       DA9150_GPADC_HW_CHAN_ID_,
+       DA9150_GPADC_HW_CHAN_VSYS,
+       DA9150_GPADC_HW_CHAN_VSYS_,
+       DA9150_GPADC_HW_CHAN_GPIOA_6V,
+       DA9150_GPADC_HW_CHAN_GPIOA_6V_,
+       DA9150_GPADC_HW_CHAN_GPIOB_6V,
+       DA9150_GPADC_HW_CHAN_GPIOB_6V_,
+       DA9150_GPADC_HW_CHAN_GPIOC_6V,
+       DA9150_GPADC_HW_CHAN_GPIOC_6V_,
+       DA9150_GPADC_HW_CHAN_GPIOD_6V,
+       DA9150_GPADC_HW_CHAN_GPIOD_6V_,
+       DA9150_GPADC_HW_CHAN_VBAT,
+       DA9150_GPADC_HW_CHAN_VBAT_,
+       DA9150_GPADC_HW_CHAN_TBAT,
+       DA9150_GPADC_HW_CHAN_TBAT_,
+       DA9150_GPADC_HW_CHAN_TJUNC_CORE,
+       DA9150_GPADC_HW_CHAN_TJUNC_CORE_,
+       DA9150_GPADC_HW_CHAN_TJUNC_OVP,
+       DA9150_GPADC_HW_CHAN_TJUNC_OVP_,
+};
+
+enum da9150_gpadc_channel {
+       DA9150_GPADC_CHAN_GPIOA = 0,
+       DA9150_GPADC_CHAN_GPIOB,
+       DA9150_GPADC_CHAN_GPIOC,
+       DA9150_GPADC_CHAN_GPIOD,
+       DA9150_GPADC_CHAN_IBUS,
+       DA9150_GPADC_CHAN_VBUS,
+       DA9150_GPADC_CHAN_VSYS,
+       DA9150_GPADC_CHAN_VBAT,
+       DA9150_GPADC_CHAN_TBAT,
+       DA9150_GPADC_CHAN_TJUNC_CORE,
+       DA9150_GPADC_CHAN_TJUNC_OVP,
+};
+
+/* Private data */
+struct da9150_gpadc {
+       struct da9150 *da9150;
+       struct device *dev;
+
+       struct mutex lock;
+       struct completion complete;
+};
+
+
+static irqreturn_t da9150_gpadc_irq(int irq, void *data)
+{
+
+       struct da9150_gpadc *gpadc = data;
+
+       complete(&gpadc->complete);
+
+       return IRQ_HANDLED;
+}
+
+static int da9150_gpadc_read_adc(struct da9150_gpadc *gpadc, int hw_chan)
+{
+       u8 result_regs[2];
+       int result;
+
+       mutex_lock(&gpadc->lock);
+
+       /* Set channel & enable measurement */
+       da9150_reg_write(gpadc->da9150, DA9150_GPADC_MAN,
+                        (DA9150_GPADC_EN_MASK |
+                         hw_chan << DA9150_GPADC_MUX_SHIFT));
+
+       /* Consume left-over completion from a previous timeout */
+       try_wait_for_completion(&gpadc->complete);
+
+       /* Check for actual completion */
+       wait_for_completion_timeout(&gpadc->complete, msecs_to_jiffies(5));
+
+       /* Read result and status from device */
+       da9150_bulk_read(gpadc->da9150, DA9150_GPADC_RES_A, 2, result_regs);
+
+       mutex_unlock(&gpadc->lock);
+
+       /* Check to make sure device really has completed reading */
+       if (result_regs[1] & DA9150_GPADC_RUN_MASK) {
+               dev_err(gpadc->dev, "Timeout on channel %d of GPADC\n",
+                       hw_chan);
+               return -ETIMEDOUT;
+       }
+
+       /* LSBs - 2 bits */
+       result = (result_regs[1] & DA9150_GPADC_RES_L_MASK) >>
+                DA9150_GPADC_RES_L_SHIFT;
+       /* MSBs - 8 bits */
+       result |= result_regs[0] << DA9150_GPADC_RES_L_BITS;
+
+       return result;
+}
+
+static inline int da9150_gpadc_gpio_6v_voltage_now(int raw_val)
+{
+       /* Convert to mV */
+       return (6 * ((raw_val * 1000) + 500)) / 1024;
+}
+
+static inline int da9150_gpadc_ibus_current_avg(int raw_val)
+{
+       /* Convert to mA */
+       return (4 * ((raw_val * 1000) + 500)) / 2048;
+}
+
+static inline int da9150_gpadc_vbus_21v_voltage_now(int raw_val)
+{
+       /* Convert to mV */
+       return (21 * ((raw_val * 1000) + 500)) / 1024;
+}
+
+static inline int da9150_gpadc_vsys_6v_voltage_now(int raw_val)
+{
+       /* Convert to mV */
+       return (3 * ((raw_val * 1000) + 500)) / 512;
+}
+
+static int da9150_gpadc_read_processed(struct da9150_gpadc *gpadc, int channel,
+                                      int hw_chan, int *val)
+{
+       int raw_val;
+
+       raw_val = da9150_gpadc_read_adc(gpadc, hw_chan);
+       if (raw_val < 0)
+               return raw_val;
+
+       switch (channel) {
+       case DA9150_GPADC_CHAN_GPIOA:
+       case DA9150_GPADC_CHAN_GPIOB:
+       case DA9150_GPADC_CHAN_GPIOC:
+       case DA9150_GPADC_CHAN_GPIOD:
+               *val = da9150_gpadc_gpio_6v_voltage_now(raw_val);
+               break;
+       case DA9150_GPADC_CHAN_IBUS:
+               *val = da9150_gpadc_ibus_current_avg(raw_val);
+               break;
+       case DA9150_GPADC_CHAN_VBUS:
+               *val = da9150_gpadc_vbus_21v_voltage_now(raw_val);
+               break;
+       case DA9150_GPADC_CHAN_VSYS:
+               *val = da9150_gpadc_vsys_6v_voltage_now(raw_val);
+               break;
+       default:
+               /* No processing for other channels so return raw value */
+               *val = raw_val;
+               break;
+       }
+
+       return IIO_VAL_INT;
+}
+
+static int da9150_gpadc_read_scale(int channel, int *val, int *val2)
+{
+       switch (channel) {
+       case DA9150_GPADC_CHAN_VBAT:
+               *val = 2932;
+               *val2 = 1000;
+               return IIO_VAL_FRACTIONAL;
+       case DA9150_GPADC_CHAN_TJUNC_CORE:
+       case DA9150_GPADC_CHAN_TJUNC_OVP:
+               *val = 1000000;
+               *val2 = 4420;
+               return IIO_VAL_FRACTIONAL;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int da9150_gpadc_read_offset(int channel, int *val)
+{
+       switch (channel) {
+       case DA9150_GPADC_CHAN_VBAT:
+               *val = 1500000 / 2932;
+               return IIO_VAL_INT;
+       case DA9150_GPADC_CHAN_TJUNC_CORE:
+       case DA9150_GPADC_CHAN_TJUNC_OVP:
+               *val = -144;
+               return IIO_VAL_INT;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int da9150_gpadc_read_raw(struct iio_dev *indio_dev,
+                                struct iio_chan_spec const *chan,
+                                int *val, int *val2, long mask)
+{
+       struct da9150_gpadc *gpadc = iio_priv(indio_dev);
+
+       if ((chan->channel < DA9150_GPADC_CHAN_GPIOA) ||
+           (chan->channel > DA9150_GPADC_CHAN_TJUNC_OVP))
+               return -EINVAL;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+       case IIO_CHAN_INFO_PROCESSED:
+               return da9150_gpadc_read_processed(gpadc, chan->channel,
+                                                  chan->address, val);
+       case IIO_CHAN_INFO_SCALE:
+               return da9150_gpadc_read_scale(chan->channel, val, val2);
+       case IIO_CHAN_INFO_OFFSET:
+               return da9150_gpadc_read_offset(chan->channel, val);
+       default:
+               return -EINVAL;
+       }
+}
+
+static const struct iio_info da9150_gpadc_info = {
+       .read_raw = &da9150_gpadc_read_raw,
+       .driver_module = THIS_MODULE,
+};
+
+#define DA9150_GPADC_CHANNEL(_id, _hw_id, _type, chan_info,    \
+                            _ext_name) {                       \
+       .type = _type,                                          \
+       .indexed = 1,                                           \
+       .channel = DA9150_GPADC_CHAN_##_id,                     \
+       .address = DA9150_GPADC_HW_CHAN_##_hw_id,               \
+       .info_mask_separate = chan_info,                        \
+       .extend_name = _ext_name,                               \
+       .datasheet_name = #_id,                                 \
+}
+
+#define DA9150_GPADC_CHANNEL_RAW(_id, _hw_id, _type, _ext_name)        \
+       DA9150_GPADC_CHANNEL(_id, _hw_id, _type,                \
+                            BIT(IIO_CHAN_INFO_RAW), _ext_name)
+
+#define DA9150_GPADC_CHANNEL_SCALED(_id, _hw_id, _type, _ext_name)     \
+       DA9150_GPADC_CHANNEL(_id, _hw_id, _type,                        \
+                            BIT(IIO_CHAN_INFO_RAW) |                   \
+                            BIT(IIO_CHAN_INFO_SCALE) |                 \
+                            BIT(IIO_CHAN_INFO_OFFSET),                 \
+                            _ext_name)
+
+#define DA9150_GPADC_CHANNEL_PROCESSED(_id, _hw_id, _type, _ext_name)  \
+       DA9150_GPADC_CHANNEL(_id, _hw_id, _type,                        \
+                            BIT(IIO_CHAN_INFO_PROCESSED), _ext_name)
+
+/* Supported channels */
+static const struct iio_chan_spec da9150_gpadc_channels[] = {
+       DA9150_GPADC_CHANNEL_PROCESSED(GPIOA, GPIOA_6V, IIO_VOLTAGE, NULL),
+       DA9150_GPADC_CHANNEL_PROCESSED(GPIOB, GPIOB_6V, IIO_VOLTAGE, NULL),
+       DA9150_GPADC_CHANNEL_PROCESSED(GPIOC, GPIOC_6V, IIO_VOLTAGE, NULL),
+       DA9150_GPADC_CHANNEL_PROCESSED(GPIOD, GPIOD_6V, IIO_VOLTAGE, NULL),
+       DA9150_GPADC_CHANNEL_PROCESSED(IBUS, IBUS_SENSE, IIO_CURRENT, "ibus"),
+       DA9150_GPADC_CHANNEL_PROCESSED(VBUS, VBUS_DIV_, IIO_VOLTAGE, "vbus"),
+       DA9150_GPADC_CHANNEL_PROCESSED(VSYS, VSYS, IIO_VOLTAGE, "vsys"),
+       DA9150_GPADC_CHANNEL_SCALED(VBAT, VBAT, IIO_VOLTAGE, "vbat"),
+       DA9150_GPADC_CHANNEL_RAW(TBAT, TBAT, IIO_VOLTAGE, "tbat"),
+       DA9150_GPADC_CHANNEL_SCALED(TJUNC_CORE, TJUNC_CORE, IIO_TEMP,
+                                   "tjunc_core"),
+       DA9150_GPADC_CHANNEL_SCALED(TJUNC_OVP, TJUNC_OVP, IIO_TEMP,
+                                   "tjunc_ovp"),
+};
+
+/* Default maps used by da9150-charger */
+static struct iio_map da9150_gpadc_default_maps[] = {
+       {
+               .consumer_dev_name = "da9150-charger",
+               .consumer_channel = "CHAN_IBUS",
+               .adc_channel_label = "IBUS",
+       },
+       {
+               .consumer_dev_name = "da9150-charger",
+               .consumer_channel = "CHAN_VBUS",
+               .adc_channel_label = "VBUS",
+       },
+       {
+               .consumer_dev_name = "da9150-charger",
+               .consumer_channel = "CHAN_TJUNC",
+               .adc_channel_label = "TJUNC_CORE",
+       },
+       {
+               .consumer_dev_name = "da9150-charger",
+               .consumer_channel = "CHAN_VBAT",
+               .adc_channel_label = "VBAT",
+       },
+       {},
+};
+
+static int da9150_gpadc_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct da9150 *da9150 = dev_get_drvdata(dev->parent);
+       struct da9150_gpadc *gpadc;
+       struct iio_dev *indio_dev;
+       int irq, ret;
+
+       indio_dev = devm_iio_device_alloc(dev, sizeof(*gpadc));
+       if (!indio_dev) {
+               dev_err(&pdev->dev, "Failed to allocate IIO device\n");
+               return -ENOMEM;
+       }
+       gpadc = iio_priv(indio_dev);
+
+       platform_set_drvdata(pdev, indio_dev);
+       gpadc->da9150 = da9150;
+       gpadc->dev = dev;
+       mutex_init(&gpadc->lock);
+       init_completion(&gpadc->complete);
+
+       irq = platform_get_irq_byname(pdev, "GPADC");
+       if (irq < 0) {
+               dev_err(dev, "Failed to get IRQ: %d\n", irq);
+               return irq;
+       }
+
+       ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq,
+                                       IRQF_ONESHOT, "GPADC", gpadc);
+       if (ret) {
+               dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
+               return ret;
+       }
+
+       ret = iio_map_array_register(indio_dev, da9150_gpadc_default_maps);
+       if (ret) {
+               dev_err(dev, "Failed to register IIO maps: %d\n", ret);
+               return ret;
+       }
+
+       indio_dev->name = dev_name(dev);
+       indio_dev->dev.parent = dev;
+       indio_dev->dev.of_node = pdev->dev.of_node;
+       indio_dev->info = &da9150_gpadc_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = da9150_gpadc_channels;
+       indio_dev->num_channels = ARRAY_SIZE(da9150_gpadc_channels);
+
+       ret = iio_device_register(indio_dev);
+       if (ret) {
+               dev_err(dev, "Failed to register IIO device: %d\n", ret);
+               goto iio_map_unreg;
+       }
+
+       return 0;
+
+iio_map_unreg:
+       iio_map_array_unregister(indio_dev);
+
+       return ret;
+}
+
+static int da9150_gpadc_remove(struct platform_device *pdev)
+{
+       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+       iio_device_unregister(indio_dev);
+       iio_map_array_unregister(indio_dev);
+
+       return 0;
+}
+
+static struct platform_driver da9150_gpadc_driver = {
+       .driver = {
+               .name = "da9150-gpadc",
+       },
+       .probe = da9150_gpadc_probe,
+       .remove = da9150_gpadc_remove,
+};
+
+module_platform_driver(da9150_gpadc_driver);
+
+MODULE_DESCRIPTION("GPADC Driver for DA9150");
+MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
+MODULE_LICENSE("GPL");
index 87ee1c7d0b54241e07d997cd21babf68c46b7b35..44bf815adb6c0d4edd9162fca82b4aaa1dd95d81 100644 (file)
@@ -436,7 +436,7 @@ static int max1027_probe(struct spi_device *spi)
                                  indio_dev->num_channels * 2,
                                  GFP_KERNEL);
        if (st->buffer == NULL) {
-               dev_err(&indio_dev->dev, "Can't allocate bufffer\n");
+               dev_err(&indio_dev->dev, "Can't allocate buffer\n");
                return -ENOMEM;
        }
 
index e63b8e76d4c3d54edc25d23561f28a11afeb05e7..56292ae4538db6fb506966b2905064ea14ea4fc2 100644 (file)
@@ -275,7 +275,6 @@ static void vf610_adc_cfg_post_set(struct vf610_adc *info)
 static void vf610_adc_calibration(struct vf610_adc *info)
 {
        int adc_gc, hc_cfg;
-       int timeout;
 
        if (!info->adc_feature.calibration)
                return;
@@ -287,9 +286,7 @@ static void vf610_adc_calibration(struct vf610_adc *info)
        adc_gc = readl(info->regs + VF610_REG_ADC_GC);
        writel(adc_gc | VF610_ADC_CAL, info->regs + VF610_REG_ADC_GC);
 
-       timeout = wait_for_completion_timeout
-                       (&info->completion, VF610_ADC_TIMEOUT);
-       if (timeout == 0)
+       if (!wait_for_completion_timeout(&info->completion, VF610_ADC_TIMEOUT))
                dev_err(info->dev, "Timeout for adc calibration\n");
 
        adc_gc = readl(info->regs + VF610_REG_ADC_GS);
index 25b01e156d8264ced9abf9b16f397129e76fc989..e81f434760f4c778c604c7d2e102bfa79adef9b2 100644 (file)
@@ -153,8 +153,8 @@ s32 hid_sensor_read_poll_value(struct hid_sensor_common *st)
        int ret;
 
        ret = sensor_hub_get_feature(st->hsdev,
-               st->poll.report_id,
-               st->poll.index, &value);
+                                    st->poll.report_id,
+                                    st->poll.index, sizeof(value), &value);
 
        if (ret < 0 || value < 0) {
                return -EINVAL;
@@ -174,8 +174,8 @@ int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st,
        int ret;
 
        ret = sensor_hub_get_feature(st->hsdev,
-               st->poll.report_id,
-               st->poll.index, &value);
+                                    st->poll.report_id,
+                                    st->poll.index, sizeof(value), &value);
        if (ret < 0 || value < 0) {
                *val1 = *val2 = 0;
                return -EINVAL;
@@ -212,9 +212,8 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st,
                else
                        value = 0;
        }
-       ret = sensor_hub_set_feature(st->hsdev,
-               st->poll.report_id,
-               st->poll.index, value);
+       ret = sensor_hub_set_feature(st->hsdev, st->poll.report_id,
+                                    st->poll.index, sizeof(value), &value);
        if (ret < 0 || value < 0)
                ret = -EINVAL;
 
@@ -229,8 +228,9 @@ int hid_sensor_read_raw_hyst_value(struct hid_sensor_common *st,
        int ret;
 
        ret = sensor_hub_get_feature(st->hsdev,
-               st->sensitivity.report_id,
-               st->sensitivity.index, &value);
+                                    st->sensitivity.report_id,
+                                    st->sensitivity.index, sizeof(value),
+                                    &value);
        if (ret < 0 || value < 0) {
                *val1 = *val2 = 0;
                return -EINVAL;
@@ -253,9 +253,9 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st,
        value = convert_to_vtf_format(st->sensitivity.size,
                                st->sensitivity.unit_expo,
                                val1, val2);
-       ret = sensor_hub_set_feature(st->hsdev,
-               st->sensitivity.report_id,
-               st->sensitivity.index, value);
+       ret = sensor_hub_set_feature(st->hsdev, st->sensitivity.report_id,
+                                    st->sensitivity.index, sizeof(value),
+                                    &value);
        if (ret < 0 || value < 0)
                ret = -EINVAL;
 
index 2f1d535b94c45d08a1824f17081466bace1ea14a..610fc98f88efa4f05fd996505f45411756a50fb1 100644 (file)
@@ -68,20 +68,21 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state)
        if (state_val >= 0) {
                state_val += st->power_state.logical_minimum;
                sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
-                                       st->power_state.index,
-                                       (s32)state_val);
+                                      st->power_state.index, sizeof(state_val),
+                                      &state_val);
        }
 
        if (report_val >= 0) {
                report_val += st->report_state.logical_minimum;
                sensor_hub_set_feature(st->hsdev, st->report_state.report_id,
-                                       st->report_state.index,
-                                       (s32)report_val);
+                                      st->report_state.index,
+                                      sizeof(report_val),
+                                      &report_val);
        }
 
        sensor_hub_get_feature(st->hsdev, st->power_state.report_id,
-                                       st->power_state.index,
-                                       &state_val);
+                              st->power_state.index,
+                              sizeof(state_val), &state_val);
        if (state && poll_value)
                msleep_interruptible(poll_value * 2);
 
index 55a90082a29bd4846aaea896f8c7f847d96fcb45..9a40097e7cf81439933c892d7bfc205cc43d69d7 100644 (file)
@@ -437,7 +437,7 @@ int ssp_queue_ssp_refresh_task(struct ssp_data *data, unsigned int delay)
 }
 
 #ifdef CONFIG_OF
-static struct of_device_id ssp_of_match[] = {
+static const struct of_device_id ssp_of_match[] = {
        {
                .compatible     = "samsung,sensorhub-rinato",
                .data           = &ssp_rinato_info,
index 2236ea22f98a50532b333c9b126373071da45ccb..13471a76e5bf0b7c99d09572900e7fbc6626baca 100644 (file)
@@ -143,11 +143,16 @@ config AD7303
          ad7303.
 
 config MAX517
-       tristate "Maxim MAX517/518/519 DAC driver"
+       tristate "Maxim MAX517/518/519/520/521 DAC driver"
        depends on I2C
        help
-         If you say yes here you get support for the Maxim chips MAX517,
-         MAX518 and MAX519 (I2C 8-Bit DACs with rail-to-rail outputs).
+         If you say yes here you get support for the following Maxim chips
+         (I2C 8-Bit DACs with rail-to-rail outputs):
+         MAX517 - Single channel, single reference
+         MAX518 - Dual channel, ref=Vdd
+         MAX519 - Dual channel, dual reference
+         MAX520 - Quad channel, quad reference
+         MAX521 - Octal channel, independent ref for ch0-3, shared ref for ch4-7
 
          This driver can also be built as a module.  If so, the module
          will be called max517.
index 9a82a7255ebb8d4420e22444f02a4e82a28bd0bb..5507b3970b4bc6afb7b2c45286cf92c6885fa124 100644 (file)
@@ -39,11 +39,13 @@ enum max517_device_ids {
        ID_MAX517,
        ID_MAX518,
        ID_MAX519,
+       ID_MAX520,
+       ID_MAX521,
 };
 
 struct max517_data {
        struct i2c_client       *client;
-       unsigned short          vref_mv[2];
+       unsigned short          vref_mv[8];
 };
 
 /*
@@ -149,7 +151,13 @@ static const struct iio_info max517_info = {
 
 static const struct iio_chan_spec max517_channels[] = {
        MAX517_CHANNEL(0),
-       MAX517_CHANNEL(1)
+       MAX517_CHANNEL(1),
+       MAX517_CHANNEL(2),
+       MAX517_CHANNEL(3),
+       MAX517_CHANNEL(4),
+       MAX517_CHANNEL(5),
+       MAX517_CHANNEL(6),
+       MAX517_CHANNEL(7),
 };
 
 static int max517_probe(struct i2c_client *client,
@@ -158,6 +166,7 @@ static int max517_probe(struct i2c_client *client,
        struct max517_data *data;
        struct iio_dev *indio_dev;
        struct max517_platform_data *platform_data = client->dev.platform_data;
+       int chan;
 
        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
        if (!indio_dev)
@@ -169,11 +178,21 @@ static int max517_probe(struct i2c_client *client,
        /* establish that the iio_dev is a child of the i2c device */
        indio_dev->dev.parent = &client->dev;
 
-       /* reduced channel set for MAX517 */
-       if (id->driver_data == ID_MAX517)
-               indio_dev->num_channels = 1;
-       else
+       switch (id->driver_data) {
+       case ID_MAX521:
+               indio_dev->num_channels = 8;
+               break;
+       case ID_MAX520:
+               indio_dev->num_channels = 4;
+               break;
+       case ID_MAX519:
+       case ID_MAX518:
                indio_dev->num_channels = 2;
+               break;
+       default:  /* single channel for MAX517 */
+               indio_dev->num_channels = 1;
+               break;
+       }
        indio_dev->channels = max517_channels;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &max517_info;
@@ -182,11 +201,11 @@ static int max517_probe(struct i2c_client *client,
         * Reference voltage on MAX518 and default is 5V, else take vref_mv
         * from platform_data
         */
-       if (id->driver_data == ID_MAX518 || !platform_data) {
-               data->vref_mv[0] = data->vref_mv[1] = 5000; /* mV */
-       } else {
-               data->vref_mv[0] = platform_data->vref_mv[0];
-               data->vref_mv[1] = platform_data->vref_mv[1];
+       for (chan = 0; chan < indio_dev->num_channels; chan++) {
+               if (id->driver_data == ID_MAX518 || !platform_data)
+                       data->vref_mv[chan] = 5000; /* mV */
+               else
+                       data->vref_mv[chan] = platform_data->vref_mv[chan];
        }
 
        return iio_device_register(indio_dev);
@@ -202,6 +221,8 @@ static const struct i2c_device_id max517_id[] = {
        { "max517", ID_MAX517 },
        { "max518", ID_MAX518 },
        { "max519", ID_MAX519 },
+       { "max520", ID_MAX520 },
+       { "max521", ID_MAX521 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, max517_id);
@@ -218,5 +239,5 @@ static struct i2c_driver max517_driver = {
 module_i2c_driver(max517_driver);
 
 MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
-MODULE_DESCRIPTION("MAX517/MAX518/MAX519 8-bit DAC");
+MODULE_DESCRIPTION("MAX517/518/519/520/521 8-bit DAC");
 MODULE_LICENSE("GPL");
index ccf3ea7e1afa8ca1848937b9a8b92e1f2cefc8be..4415f55d26b6b06944b222c4666c82b759ba3cd7 100644 (file)
@@ -1001,16 +1001,12 @@ static int bmg160_gpio_probe(struct i2c_client *client,
        dev = &client->dev;
 
        /* data ready gpio interrupt pin */
-       gpio = devm_gpiod_get_index(dev, BMG160_GPIO_NAME, 0);
+       gpio = devm_gpiod_get_index(dev, BMG160_GPIO_NAME, 0, GPIOD_IN);
        if (IS_ERR(gpio)) {
                dev_err(dev, "acpi gpio get index failed\n");
                return PTR_ERR(gpio);
        }
 
-       ret = gpiod_direction_input(gpio);
-       if (ret)
-               return ret;
-
        ret = gpiod_to_irq(gpio);
 
        dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
index a3c3e19de52758190889a559a77271c8d35410d5..b5883b6f4e5044f2e9f594bc29e526861a8a575e 100644 (file)
@@ -123,7 +123,8 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
                        *val = sensor_hub_input_attr_get_raw_value(
                                        gyro_state->common_attributes.hsdev,
                                        HID_USAGE_SENSOR_GYRO_3D, address,
-                                       report_id);
+                                       report_id,
+                                       SENSOR_HUB_SYNC);
                else {
                        *val = 0;
                        hid_sensor_power_state(&gyro_state->common_attributes,
index 6a8020d4814038b67cbad3b3c51d20d1987bbd77..f0fd94055d8858b722a5572b564edf0de125a90b 100644 (file)
@@ -223,6 +223,10 @@ static int itg3200_initial_setup(struct iio_dev *indio_dev)
        int ret;
        u8 val;
 
+       ret = itg3200_reset(indio_dev);
+       if (ret)
+               goto err_ret;
+
        ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_ADDRESS, &val);
        if (ret)
                goto err_ret;
@@ -233,10 +237,6 @@ static int itg3200_initial_setup(struct iio_dev *indio_dev)
                goto err_ret;
        }
 
-       ret = itg3200_reset(indio_dev);
-       if (ret)
-               goto err_ret;
-
        ret = itg3200_enable_full_scale(indio_dev);
 err_ret:
        return ret;
@@ -351,6 +351,26 @@ static int itg3200_remove(struct i2c_client *client)
        return 0;
 }
 
+static int __maybe_unused itg3200_suspend(struct device *dev)
+{
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct itg3200 *st = iio_priv(indio_dev);
+
+       dev_dbg(&st->i2c->dev, "suspend device");
+
+       return itg3200_write_reg_8(indio_dev, ITG3200_REG_POWER_MANAGEMENT,
+                                  ITG3200_SLEEP);
+}
+
+static int __maybe_unused itg3200_resume(struct device *dev)
+{
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+
+       return itg3200_initial_setup(indio_dev);
+}
+
+static SIMPLE_DEV_PM_OPS(itg3200_pm_ops, itg3200_suspend, itg3200_resume);
+
 static const struct i2c_device_id itg3200_id[] = {
        { "itg3200", 0 },
        { }
@@ -361,6 +381,7 @@ static struct i2c_driver itg3200_driver = {
        .driver = {
                .owner  = THIS_MODULE,
                .name   = "itg3200",
+               .pm     = &itg3200_pm_ops,
        },
        .id_table       = itg3200_id,
        .probe          = itg3200_probe,
index f07a2336f7dc705d4c328ac5d5caefe310516229..21395f26d2276548567dfd118f37c22087a0d1ce 100644 (file)
 #define ST_GYRO_2_DRDY_IRQ_INT2_MASK           0x08
 #define ST_GYRO_2_MULTIREAD_BIT                        true
 
+/* CUSTOM VALUES FOR SENSOR 3 */
+#define ST_GYRO_3_WAI_EXP                      0xd7
+#define ST_GYRO_3_ODR_ADDR                     0x20
+#define ST_GYRO_3_ODR_MASK                     0xc0
+#define ST_GYRO_3_ODR_AVL_95HZ_VAL             0x00
+#define ST_GYRO_3_ODR_AVL_190HZ_VAL            0x01
+#define ST_GYRO_3_ODR_AVL_380HZ_VAL            0x02
+#define ST_GYRO_3_ODR_AVL_760HZ_VAL            0x03
+#define ST_GYRO_3_PW_ADDR                      0x20
+#define ST_GYRO_3_PW_MASK                      0x08
+#define ST_GYRO_3_FS_ADDR                      0x23
+#define ST_GYRO_3_FS_MASK                      0x30
+#define ST_GYRO_3_FS_AVL_250_VAL               0x00
+#define ST_GYRO_3_FS_AVL_500_VAL               0x01
+#define ST_GYRO_3_FS_AVL_2000_VAL              0x02
+#define ST_GYRO_3_FS_AVL_250_GAIN              IIO_DEGREE_TO_RAD(8750)
+#define ST_GYRO_3_FS_AVL_500_GAIN              IIO_DEGREE_TO_RAD(17500)
+#define ST_GYRO_3_FS_AVL_2000_GAIN             IIO_DEGREE_TO_RAD(70000)
+#define ST_GYRO_3_BDU_ADDR                     0x23
+#define ST_GYRO_3_BDU_MASK                     0x80
+#define ST_GYRO_3_DRDY_IRQ_ADDR                        0x22
+#define ST_GYRO_3_DRDY_IRQ_INT2_MASK           0x08
+#define ST_GYRO_3_MULTIREAD_BIT                        true
+
+
 static const struct iio_chan_spec st_gyro_16bit_channels[] = {
        ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL,
                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
@@ -225,6 +250,64 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
                .multi_read_bit = ST_GYRO_2_MULTIREAD_BIT,
                .bootime = 2,
        },
+       {
+               .wai = ST_GYRO_3_WAI_EXP,
+               .sensors_supported = {
+                       [0] = L3GD20_GYRO_DEV_NAME,
+               },
+               .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
+               .odr = {
+                       .addr = ST_GYRO_3_ODR_ADDR,
+                       .mask = ST_GYRO_3_ODR_MASK,
+                       .odr_avl = {
+                               { 95, ST_GYRO_3_ODR_AVL_95HZ_VAL, },
+                               { 190, ST_GYRO_3_ODR_AVL_190HZ_VAL, },
+                               { 380, ST_GYRO_3_ODR_AVL_380HZ_VAL, },
+                               { 760, ST_GYRO_3_ODR_AVL_760HZ_VAL, },
+                       },
+               },
+               .pw = {
+                       .addr = ST_GYRO_3_PW_ADDR,
+                       .mask = ST_GYRO_3_PW_MASK,
+                       .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
+                       .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+               },
+               .enable_axis = {
+                       .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
+                       .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
+               },
+               .fs = {
+                       .addr = ST_GYRO_3_FS_ADDR,
+                       .mask = ST_GYRO_3_FS_MASK,
+                       .fs_avl = {
+                               [0] = {
+                                       .num = ST_GYRO_FS_AVL_250DPS,
+                                       .value = ST_GYRO_3_FS_AVL_250_VAL,
+                                       .gain = ST_GYRO_3_FS_AVL_250_GAIN,
+                               },
+                               [1] = {
+                                       .num = ST_GYRO_FS_AVL_500DPS,
+                                       .value = ST_GYRO_3_FS_AVL_500_VAL,
+                                       .gain = ST_GYRO_3_FS_AVL_500_GAIN,
+                               },
+                               [2] = {
+                                       .num = ST_GYRO_FS_AVL_2000DPS,
+                                       .value = ST_GYRO_3_FS_AVL_2000_VAL,
+                                       .gain = ST_GYRO_3_FS_AVL_2000_GAIN,
+                               },
+                       },
+               },
+               .bdu = {
+                       .addr = ST_GYRO_3_BDU_ADDR,
+                       .mask = ST_GYRO_3_BDU_MASK,
+               },
+               .drdy_irq = {
+                       .addr = ST_GYRO_3_DRDY_IRQ_ADDR,
+                       .mask_int2 = ST_GYRO_3_DRDY_IRQ_INT2_MASK,
+               },
+               .multi_read_bit = ST_GYRO_3_MULTIREAD_BIT,
+               .bootime = 2,
+       },
 };
 
 static int st_gyro_read_raw(struct iio_dev *indio_dev,
index 3a677c778afbaf11088a7cbafff7097b456e8a10..f566f6a7b3a9e91ef714e8db47e38366df9714bc 100644 (file)
@@ -3,4 +3,4 @@
 #
 
 obj-$(CONFIG_INV_MPU6050_IIO) += inv-mpu6050.o
-inv-mpu6050-objs := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o
+inv-mpu6050-objs := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o inv_mpu_acpi.o
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
new file mode 100644 (file)
index 0000000..1c982a5
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * inv_mpu_acpi: ACPI processing for creating client devices
+ * Copyright (c) 2015, 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.
+ */
+
+#ifdef CONFIG_ACPI
+
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/dmi.h>
+#include <linux/acpi.h>
+#include "inv_mpu_iio.h"
+
+enum inv_mpu_product_name {
+       INV_MPU_NOT_MATCHED,
+       INV_MPU_ASUS_T100TA,
+};
+
+static enum inv_mpu_product_name matched_product_name;
+
+static int __init asus_t100_matched(const struct dmi_system_id *d)
+{
+       matched_product_name = INV_MPU_ASUS_T100TA;
+
+       return 0;
+}
+
+static const struct dmi_system_id inv_mpu_dev_list[] = {
+       {
+       .callback = asus_t100_matched,
+       .ident = "Asus Transformer Book T100",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
+               },
+       },
+       /* Add more matching tables here..*/
+       {}
+};
+
+static int asus_acpi_get_sensor_info(struct acpi_device *adev,
+                                    struct i2c_client *client,
+                                    struct i2c_board_info *info)
+{
+       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+       int i;
+       acpi_status status;
+       union acpi_object *cpm;
+
+       status = acpi_evaluate_object(adev->handle, "CNF0", NULL, &buffer);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+
+       cpm = buffer.pointer;
+       for (i = 0; i < cpm->package.count; ++i) {
+               union acpi_object *elem;
+               int j;
+
+               elem = &(cpm->package.elements[i]);
+               for (j = 0; j < elem->package.count; ++j) {
+                       union acpi_object *sub_elem;
+
+                       sub_elem = &(elem->package.elements[j]);
+                       if (sub_elem->type == ACPI_TYPE_STRING)
+                               strlcpy(info->type, sub_elem->string.pointer,
+                                       sizeof(info->type));
+                       else if (sub_elem->type == ACPI_TYPE_INTEGER) {
+                               if (sub_elem->integer.value != client->addr) {
+                                       info->addr = sub_elem->integer.value;
+                                       break; /* Not a MPU6500 primary */
+                               }
+                       }
+               }
+       }
+
+       kfree(buffer.pointer);
+
+       return cpm->package.count;
+}
+
+static int acpi_i2c_check_resource(struct acpi_resource *ares, void *data)
+{
+       u32 *addr = data;
+
+       if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+               struct acpi_resource_i2c_serialbus *sb;
+
+               sb = &ares->data.i2c_serial_bus;
+               if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+                       if (*addr)
+                               *addr |= (sb->slave_address << 16);
+                       else
+                               *addr = sb->slave_address;
+               }
+       }
+
+       /* Tell the ACPI core that we already copied this address */
+       return 1;
+}
+
+static int inv_mpu_process_acpi_config(struct i2c_client *client,
+                                      unsigned short *primary_addr,
+                                      unsigned short *secondary_addr)
+{
+       const struct acpi_device_id *id;
+       struct acpi_device *adev;
+       u32 i2c_addr = 0;
+       LIST_HEAD(resources);
+       int ret;
+
+       id = acpi_match_device(client->dev.driver->acpi_match_table,
+                              &client->dev);
+       if (!id)
+               return -ENODEV;
+
+       adev = ACPI_COMPANION(&client->dev);
+       if (!adev)
+               return -ENODEV;
+
+       ret = acpi_dev_get_resources(adev, &resources,
+                                    acpi_i2c_check_resource, &i2c_addr);
+       if (ret < 0)
+               return ret;
+
+       acpi_dev_free_resource_list(&resources);
+       *primary_addr = i2c_addr & 0x0000ffff;
+       *secondary_addr = (i2c_addr & 0xffff0000) >> 16;
+
+       return 0;
+}
+
+int inv_mpu_acpi_create_mux_client(struct inv_mpu6050_state *st)
+{
+
+       st->mux_client = NULL;
+       if (ACPI_HANDLE(&st->client->dev)) {
+               struct i2c_board_info info;
+               struct acpi_device *adev;
+               int ret = -1;
+
+               adev = ACPI_COMPANION(&st->client->dev);
+               memset(&info, 0, sizeof(info));
+
+               dmi_check_system(inv_mpu_dev_list);
+               switch (matched_product_name) {
+               case INV_MPU_ASUS_T100TA:
+                       ret = asus_acpi_get_sensor_info(adev, st->client,
+                                                       &info);
+                       break;
+               /* Add more matched product processing here */
+               default:
+                       break;
+               }
+
+               if (ret < 0) {
+                       /* No matching DMI, so create device on INV6XX type */
+                       unsigned short primary, secondary;
+
+                       ret = inv_mpu_process_acpi_config(st->client, &primary,
+                                                         &secondary);
+                       if (!ret && secondary) {
+                               char *name;
+
+                               info.addr = secondary;
+                               strlcpy(info.type, dev_name(&adev->dev),
+                                       sizeof(info.type));
+                               name = strchr(info.type, ':');
+                               if (name)
+                                       *name = '\0';
+                               strlcat(info.type, "-client",
+                                       sizeof(info.type));
+                       } else
+                               return 0; /* no secondary addr, which is OK */
+               }
+               st->mux_client = i2c_new_device(st->mux_adapter, &info);
+               if (!st->mux_client)
+                       return -ENODEV;
+
+       }
+
+       return 0;
+}
+
+void inv_mpu_acpi_delete_mux_client(struct inv_mpu6050_state *st)
+{
+       if (st->mux_client)
+               i2c_unregister_device(st->mux_client);
+}
+#else
+
+#include "inv_mpu_iio.h"
+
+int inv_mpu_acpi_create_mux_client(struct inv_mpu6050_state *st)
+{
+       return 0;
+}
+
+void inv_mpu_acpi_delete_mux_client(struct inv_mpu6050_state *st)
+{
+}
+#endif
index ef76afe2643cb0bebe512124ca8c9326e09229c2..17d4bb15be4d2998681f203b5944c5c82ce606ea 100644 (file)
@@ -829,8 +829,14 @@ static int inv_mpu_probe(struct i2c_client *client,
                goto out_unreg_device;
        }
 
+       result = inv_mpu_acpi_create_mux_client(st);
+       if (result)
+               goto out_del_mux;
+
        return 0;
 
+out_del_mux:
+       i2c_del_mux_adapter(st->mux_adapter);
 out_unreg_device:
        iio_device_unregister(indio_dev);
 out_remove_trigger:
@@ -845,6 +851,7 @@ static int inv_mpu_remove(struct i2c_client *client)
        struct iio_dev *indio_dev = i2c_get_clientdata(client);
        struct inv_mpu6050_state *st = iio_priv(indio_dev);
 
+       inv_mpu_acpi_delete_mux_client(st);
        i2c_del_mux_adapter(st->mux_adapter);
        iio_device_unregister(indio_dev);
        inv_mpu6050_remove_trigger(st);
index aa837de57079ed1a5fa09f13b715995597fa53de..db0a4a2758ab1b5d4bf219aa86e8d4a934b0b0d2 100644 (file)
@@ -121,6 +121,7 @@ struct inv_mpu6050_state {
        spinlock_t time_stamp_lock;
        struct i2c_client *client;
        struct i2c_adapter *mux_adapter;
+       struct i2c_client *mux_client;
        unsigned int powerup_count;
        struct inv_mpu6050_platform_data plat_data;
        DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
@@ -251,3 +252,5 @@ int inv_reset_fifo(struct iio_dev *indio_dev);
 int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask);
 int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val);
 int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on);
+int inv_mpu_acpi_create_mux_client(struct inv_mpu6050_state *st);
+void inv_mpu_acpi_delete_mux_client(struct inv_mpu6050_state *st);
index b3a36376c719317006cf8b9d30e1369f8b6af8fb..462a010628cd52421458ab113f19b45ec58bf4d2 100644 (file)
@@ -169,19 +169,18 @@ static const u16 kmx61_uscale_table[] = {9582, 19163, 38326};
 static const struct {
        int val;
        int val2;
-       u8 odr_bits;
-} kmx61_samp_freq_table[] = { {12, 500000, 0x00},
-                       {25, 0, 0x01},
-                       {50, 0, 0x02},
-                       {100, 0, 0x03},
-                       {200, 0, 0x04},
-                       {400, 0, 0x05},
-                       {800, 0, 0x06},
-                       {1600, 0, 0x07},
-                       {0, 781000, 0x08},
-                       {1, 563000, 0x09},
-                       {3, 125000, 0x0A},
-                       {6, 250000, 0x0B} };
+} kmx61_samp_freq_table[] = { {12, 500000},
+                       {25, 0},
+                       {50, 0},
+                       {100, 0},
+                       {200, 0},
+                       {400, 0},
+                       {800, 0},
+                       {1600, 0},
+                       {0, 781000},
+                       {1, 563000},
+                       {3, 125000},
+                       {6, 250000} };
 
 static const struct {
        int val;
@@ -302,24 +301,10 @@ static int kmx61_convert_freq_to_bit(int val, int val2)
        for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++)
                if (val == kmx61_samp_freq_table[i].val &&
                    val2 == kmx61_samp_freq_table[i].val2)
-                       return kmx61_samp_freq_table[i].odr_bits;
+                       return i;
        return -EINVAL;
 }
 
-static int kmx61_convert_bit_to_freq(u8 odr_bits, int *val, int *val2)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++)
-               if (odr_bits == kmx61_samp_freq_table[i].odr_bits) {
-                       *val = kmx61_samp_freq_table[i].val;
-                       *val2 = kmx61_samp_freq_table[i].val2;
-                       return 0;
-               }
-       return -EINVAL;
-}
-
-
 static int kmx61_convert_wake_up_odr_to_bit(int val, int val2)
 {
        int i;
@@ -478,7 +463,7 @@ static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device)
 
 static int kmx61_get_odr(struct kmx61_data *data, int *val, int *val2,
                         u8 device)
-{      int i;
+{
        u8 lodr_bits;
 
        if (device & KMX61_ACC)
@@ -490,13 +475,13 @@ static int kmx61_get_odr(struct kmx61_data *data, int *val, int *val2,
        else
                return -EINVAL;
 
-       for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++)
-               if (lodr_bits == kmx61_samp_freq_table[i].odr_bits) {
-                       *val = kmx61_samp_freq_table[i].val;
-                       *val2 = kmx61_samp_freq_table[i].val2;
-                       return 0;
-               }
-       return -EINVAL;
+       if (lodr_bits >= ARRAY_SIZE(kmx61_samp_freq_table))
+               return -EINVAL;
+
+       *val = kmx61_samp_freq_table[lodr_bits].val;
+       *val2 = kmx61_samp_freq_table[lodr_bits].val2;
+
+       return 0;
 }
 
 static int kmx61_set_range(struct kmx61_data *data, u8 range)
@@ -580,8 +565,11 @@ static int kmx61_chip_init(struct kmx61_data *data)
        }
        data->odr_bits = ret;
 
-       /* set output data rate for wake up (motion detection) function */
-       ret = kmx61_convert_bit_to_freq(data->odr_bits, &val, &val2);
+       /*
+        * set output data rate for wake up (motion detection) function
+        * to match data rate for accelerometer sampling
+        */
+       ret = kmx61_get_odr(data, &val, &val2, KMX61_ACC);
        if (ret < 0)
                return ret;
 
@@ -1267,16 +1255,12 @@ static int kmx61_gpio_probe(struct i2c_client *client, struct kmx61_data *data)
        dev = &client->dev;
 
        /* data ready gpio interrupt pin */
-       gpio = devm_gpiod_get_index(dev, KMX61_GPIO_NAME, 0);
+       gpio = devm_gpiod_get_index(dev, KMX61_GPIO_NAME, 0, GPIOD_IN);
        if (IS_ERR(gpio)) {
                dev_err(dev, "acpi gpio get index failed\n");
                return PTR_ERR(gpio);
        }
 
-       ret = gpiod_direction_input(gpio);
-       if (ret)
-               return ret;
-
        ret = gpiod_to_irq(gpio);
 
        dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
index 71333140d42c4815a5b8e336fb54a107c55c92a9..df919f44d513f466a0caa4f870d956273007531f 100644 (file)
@@ -37,11 +37,57 @@ static bool iio_buffer_is_active(struct iio_buffer *buf)
        return !list_empty(&buf->buffer_list);
 }
 
-static bool iio_buffer_data_available(struct iio_buffer *buf)
+static size_t iio_buffer_data_available(struct iio_buffer *buf)
 {
        return buf->access->data_available(buf);
 }
 
+static int iio_buffer_flush_hwfifo(struct iio_dev *indio_dev,
+                                  struct iio_buffer *buf, size_t required)
+{
+       if (!indio_dev->info->hwfifo_flush_to_buffer)
+               return -ENODEV;
+
+       return indio_dev->info->hwfifo_flush_to_buffer(indio_dev, required);
+}
+
+static bool iio_buffer_ready(struct iio_dev *indio_dev, struct iio_buffer *buf,
+                            size_t to_wait, int to_flush)
+{
+       size_t avail;
+       int flushed = 0;
+
+       /* wakeup if the device was unregistered */
+       if (!indio_dev->info)
+               return true;
+
+       /* drain the buffer if it was disabled */
+       if (!iio_buffer_is_active(buf)) {
+               to_wait = min_t(size_t, to_wait, 1);
+               to_flush = 0;
+       }
+
+       avail = iio_buffer_data_available(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);
+               return true;
+       }
+
+       if (to_flush)
+               flushed = iio_buffer_flush_hwfifo(indio_dev, buf,
+                                                 to_wait - avail);
+       if (flushed <= 0)
+               return false;
+
+       if (avail + flushed >= to_wait)
+               return true;
+
+       return false;
+}
+
 /**
  * iio_buffer_read_first_n_outer() - chrdev read for buffer access
  *
@@ -53,6 +99,9 @@ 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;
        int ret;
 
        if (!indio_dev->info)
@@ -61,19 +110,28 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
        if (!rb || !rb->access->read_first_n)
                return -EINVAL;
 
+       datum_size = rb->bytes_per_datum;
+
+       /*
+        * If datum_size is 0 there will never be anything to read from the
+        * buffer, so signal end of file now.
+        */
+       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;
+
        do {
-               if (!iio_buffer_data_available(rb)) {
-                       if (filp->f_flags & O_NONBLOCK)
-                               return -EAGAIN;
+               ret = wait_event_interruptible(rb->pollq,
+                       iio_buffer_ready(indio_dev, rb, to_wait, to_read));
+               if (ret)
+                       return ret;
 
-                       ret = wait_event_interruptible(rb->pollq,
-                                       iio_buffer_data_available(rb) ||
-                                       indio_dev->info == NULL);
-                       if (ret)
-                               return ret;
-                       if (indio_dev->info == NULL)
-                               return -ENODEV;
-               }
+               if (!indio_dev->info)
+                       return -ENODEV;
 
                ret = rb->access->read_first_n(rb, n, buf);
                if (ret == 0 && (filp->f_flags & O_NONBLOCK))
@@ -96,9 +154,8 @@ unsigned int iio_buffer_poll(struct file *filp,
                return -ENODEV;
 
        poll_wait(filp, &rb->pollq, wait);
-       if (iio_buffer_data_available(rb))
+       if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
                return POLLIN | POLLRDNORM;
-       /* need a way of knowing if there may be enough data... */
        return 0;
 }
 
@@ -123,6 +180,7 @@ void iio_buffer_init(struct iio_buffer *buffer)
        INIT_LIST_HEAD(&buffer->buffer_list);
        init_waitqueue_head(&buffer->pollq);
        kref_init(&buffer->ref);
+       buffer->watermark = 1;
 }
 EXPORT_SYMBOL(iio_buffer_init);
 
@@ -416,6 +474,11 @@ static ssize_t iio_buffer_write_length(struct device *dev,
                buffer->access->set_length(buffer, val);
                ret = 0;
        }
+       if (ret)
+               goto out;
+       if (buffer->length && buffer->length < buffer->watermark)
+               buffer->watermark = buffer->length;
+out:
        mutex_unlock(&indio_dev->mlock);
 
        return ret ? ret : len;
@@ -472,6 +535,7 @@ static void iio_buffer_activate(struct iio_dev *indio_dev,
 static void iio_buffer_deactivate(struct iio_buffer *buffer)
 {
        list_del_init(&buffer->buffer_list);
+       wake_up_interruptible(&buffer->pollq);
        iio_buffer_put(buffer);
 }
 
@@ -629,19 +693,16 @@ static int __iio_update_buffers(struct iio_dev *indio_dev,
                }
        }
        /* Definitely possible for devices to support both of these. */
-       if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) {
-               if (!indio_dev->trig) {
-                       printk(KERN_INFO "Buffer not started: no trigger\n");
-                       ret = -EINVAL;
-                       /* Can only occur on first buffer */
-                       goto error_run_postdisable;
-               }
+       if ((indio_dev->modes & INDIO_BUFFER_TRIGGERED) && indio_dev->trig) {
                indio_dev->currentmode = INDIO_BUFFER_TRIGGERED;
        } else if (indio_dev->modes & INDIO_BUFFER_HARDWARE) {
                indio_dev->currentmode = INDIO_BUFFER_HARDWARE;
        } else if (indio_dev->modes & INDIO_BUFFER_SOFTWARE) {
                indio_dev->currentmode = INDIO_BUFFER_SOFTWARE;
        } else { /* Should never be reached */
+               /* Can only occur on first buffer */
+               if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
+                       pr_info("Buffer not started: no trigger\n");
                ret = -EINVAL;
                goto error_run_postdisable;
        }
@@ -754,12 +815,68 @@ done:
 
 static const char * const iio_scan_elements_group_name = "scan_elements";
 
+static ssize_t iio_buffer_show_watermark(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct iio_buffer *buffer = indio_dev->buffer;
+
+       return sprintf(buf, "%u\n", buffer->watermark);
+}
+
+static ssize_t iio_buffer_store_watermark(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf,
+                                         size_t len)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct iio_buffer *buffer = indio_dev->buffer;
+       unsigned int val;
+       int ret;
+
+       ret = kstrtouint(buf, 10, &val);
+       if (ret)
+               return ret;
+       if (!val)
+               return -EINVAL;
+
+       mutex_lock(&indio_dev->mlock);
+
+       if (val > buffer->length) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (iio_buffer_is_active(indio_dev->buffer)) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       buffer->watermark = val;
+
+       if (indio_dev->info->hwfifo_set_watermark)
+               indio_dev->info->hwfifo_set_watermark(indio_dev, val);
+out:
+       mutex_unlock(&indio_dev->mlock);
+
+       return ret ? ret : len;
+}
+
 static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length,
                   iio_buffer_write_length);
 static struct device_attribute dev_attr_length_ro = __ATTR(length,
        S_IRUGO, iio_buffer_read_length, NULL);
 static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR,
                   iio_buffer_show_enable, iio_buffer_store_enable);
+static DEVICE_ATTR(watermark, S_IRUGO | S_IWUSR,
+                  iio_buffer_show_watermark, iio_buffer_store_watermark);
+
+static struct attribute *iio_buffer_attrs[] = {
+       &dev_attr_length.attr,
+       &dev_attr_enable.attr,
+       &dev_attr_watermark.attr,
+};
 
 int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
 {
@@ -778,21 +895,23 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
                        attrcount++;
        }
 
-       buffer->buffer_group.name = "buffer";
-       buffer->buffer_group.attrs = kcalloc(attrcount + 3,
-                       sizeof(*buffer->buffer_group.attrs), GFP_KERNEL);
-       if (!buffer->buffer_group.attrs)
+       attr = kcalloc(attrcount + ARRAY_SIZE(iio_buffer_attrs) + 1,
+                      sizeof(struct attribute *), GFP_KERNEL);
+       if (!attr)
                return -ENOMEM;
 
-       if (buffer->access->set_length)
-               buffer->buffer_group.attrs[0] = &dev_attr_length.attr;
-       else
-               buffer->buffer_group.attrs[0] = &dev_attr_length_ro.attr;
-       buffer->buffer_group.attrs[1] = &dev_attr_enable.attr;
+       memcpy(attr, iio_buffer_attrs, sizeof(iio_buffer_attrs));
+       if (!buffer->access->set_length)
+               attr[0] = &dev_attr_length_ro.attr;
+
        if (buffer->attrs)
-               memcpy(&buffer->buffer_group.attrs[2], buffer->attrs,
-                       sizeof(*&buffer->buffer_group.attrs) * attrcount);
-       buffer->buffer_group.attrs[attrcount+2] = NULL;
+               memcpy(&attr[ARRAY_SIZE(iio_buffer_attrs)], buffer->attrs,
+                      sizeof(struct attribute *) * attrcount);
+
+       attr[attrcount + ARRAY_SIZE(iio_buffer_attrs)] = NULL;
+
+       buffer->buffer_group.name = "buffer";
+       buffer->buffer_group.attrs = attr;
 
        indio_dev->groups[indio_dev->groupcounter++] = &buffer->buffer_group;
 
@@ -937,8 +1056,18 @@ static const void *iio_demux(struct iio_buffer *buffer,
 static int iio_push_to_buffer(struct iio_buffer *buffer, const void *data)
 {
        const void *dataout = iio_demux(buffer, data);
+       int ret;
 
-       return buffer->access->store_to(buffer, dataout);
+       ret = buffer->access->store_to(buffer, dataout);
+       if (ret)
+               return ret;
+
+       /*
+        * We can't just test for watermark to decide if we wake the poll queue
+        * because read may request less samples than the watermark.
+        */
+       wake_up_interruptible_poll(&buffer->pollq, POLLIN | POLLRDNORM);
+       return 0;
 }
 
 static void iio_buffer_demux_free(struct iio_buffer *buffer)
index b2beea01c49b3c891683204b5f30d52c87012285..847ca561afe014e83707d04eaef02054f9b2bbfa 100644 (file)
@@ -83,9 +83,6 @@ static int iio_store_to_kfifo(struct iio_buffer *r,
        ret = kfifo_in(&kf->kf, data, 1);
        if (ret != 1)
                return -EBUSY;
-
-       wake_up_interruptible_poll(&r->pollq, POLLIN | POLLRDNORM);
-
        return 0;
 }
 
@@ -109,16 +106,16 @@ static int iio_read_first_n_kfifo(struct iio_buffer *r,
        return copied;
 }
 
-static bool iio_kfifo_buf_data_available(struct iio_buffer *r)
+static size_t iio_kfifo_buf_data_available(struct iio_buffer *r)
 {
        struct iio_kfifo *kf = iio_to_kfifo(r);
-       bool empty;
+       size_t samples;
 
        mutex_lock(&kf->user_lock);
-       empty = kfifo_is_empty(&kf->kf);
+       samples = kfifo_len(&kf->kf);
        mutex_unlock(&kf->user_lock);
 
-       return !empty;
+       return samples;
 }
 
 static void iio_kfifo_buffer_release(struct iio_buffer *buffer)
index a224afd6380c84eff7c76996c7c38eb621493140..01a1a16ab7be8fcc4ae7df6a2782caa377b271a7 100644 (file)
@@ -59,6 +59,16 @@ config CM3232
         To compile this driver as a module, choose M here:
         the module will be called cm3232.
 
+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
+        color sensor.
+
+        To compile this driver as a module, choose M here: the module will
+        be called cm3323.
+
 config CM36651
        depends on I2C
        tristate "CM36651 driver"
index b12a5160d9e05de741c6245dc989433217cad554..ad7c30fe443b26f6760bfe607a1a035b760752d3 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_AL3320A)           += al3320a.o
 obj-$(CONFIG_APDS9300)         += apds9300.o
 obj-$(CONFIG_CM32181)          += cm32181.o
 obj-$(CONFIG_CM3232)           += cm3232.o
+obj-$(CONFIG_CM3323)           += cm3323.o
 obj-$(CONFIG_CM36651)          += cm36651.o
 obj-$(CONFIG_GP2AP020A00F)     += gp2ap020a00f.o
 obj-$(CONFIG_HID_SENSOR_ALS)   += hid-sensor-als.o
index 90e3519a91de89310175b9073156f19acccd7907..39c8d99cc48ee988a59f17f605372d07258d0e05 100644 (file)
@@ -378,6 +378,39 @@ static const struct i2c_device_id cm3232_id[] = {
        {}
 };
 
+#ifdef CONFIG_PM_SLEEP
+static int cm3232_suspend(struct device *dev)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+       struct cm3232_chip *chip = iio_priv(indio_dev);
+       struct i2c_client *client = chip->client;
+       int ret;
+
+       chip->regs_cmd |= CM3232_CMD_ALS_DISABLE;
+       ret = i2c_smbus_write_byte_data(client, CM3232_REG_ADDR_CMD,
+                                       chip->regs_cmd);
+
+       return ret;
+}
+
+static int cm3232_resume(struct device *dev)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+       struct cm3232_chip *chip = iio_priv(indio_dev);
+       struct i2c_client *client = chip->client;
+       int ret;
+
+       chip->regs_cmd &= ~CM3232_CMD_ALS_DISABLE;
+       ret = i2c_smbus_write_byte_data(client, CM3232_REG_ADDR_CMD,
+                                       chip->regs_cmd | CM3232_CMD_ALS_RESET);
+
+       return ret;
+}
+
+static const struct dev_pm_ops cm3232_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(cm3232_suspend, cm3232_resume)};
+#endif
+
 MODULE_DEVICE_TABLE(i2c, cm3232_id);
 
 static const struct of_device_id cm3232_of_match[] = {
@@ -390,6 +423,9 @@ static struct i2c_driver cm3232_driver = {
                .name   = "cm3232",
                .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(cm3232_of_match),
+#ifdef CONFIG_PM_SLEEP
+               .pm     = &cm3232_pm_ops,
+#endif
        },
        .id_table       = cm3232_id,
        .probe          = cm3232_probe,
diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c
new file mode 100644 (file)
index 0000000..869033e
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * CM3323 - Capella Color Light 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 CM3323 (7-bit I2C slave address 0x10)
+ *
+ * TODO: calibscale to correct the lens factor
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define CM3323_DRV_NAME "cm3323"
+
+#define CM3323_CMD_CONF                0x00
+#define CM3323_CMD_RED_DATA    0x08
+#define CM3323_CMD_GREEN_DATA  0x09
+#define CM3323_CMD_BLUE_DATA   0x0A
+#define CM3323_CMD_CLEAR_DATA  0x0B
+
+#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_SHIFT   4
+
+#define CM3323_INT_TIME_AVAILABLE "0.04 0.08 0.16 0.32 0.64 1.28"
+
+static const struct {
+       int val;
+       int val2;
+} cm3323_int_time[] = {
+       {0, 40000},  /* 40 ms */
+       {0, 80000},  /* 80 ms */
+       {0, 160000}, /* 160 ms */
+       {0, 320000}, /* 320 ms */
+       {0, 640000}, /* 640 ms */
+       {1, 280000}, /* 1280 ms */
+};
+
+struct cm3323_data {
+       struct i2c_client *client;
+       u16 reg_conf;
+       struct mutex mutex;
+};
+
+#define CM3323_COLOR_CHANNEL(_color, _addr) { \
+       .type = IIO_INTENSITY, \
+       .modified = 1, \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+       .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), \
+       .channel2 = IIO_MOD_LIGHT_##_color, \
+       .address = _addr, \
+}
+
+static const struct iio_chan_spec cm3323_channels[] = {
+       CM3323_COLOR_CHANNEL(RED, CM3323_CMD_RED_DATA),
+       CM3323_COLOR_CHANNEL(GREEN, CM3323_CMD_GREEN_DATA),
+       CM3323_COLOR_CHANNEL(BLUE, CM3323_CMD_BLUE_DATA),
+       CM3323_COLOR_CHANNEL(CLEAR, CM3323_CMD_CLEAR_DATA),
+};
+
+static IIO_CONST_ATTR_INT_TIME_AVAIL(CM3323_INT_TIME_AVAILABLE);
+
+static struct attribute *cm3323_attributes[] = {
+       &iio_const_attr_integration_time_available.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group cm3323_attribute_group = {
+       .attrs = cm3323_attributes,
+};
+
+static int cm3323_init(struct iio_dev *indio_dev)
+{
+       int ret;
+       struct cm3323_data *data = iio_priv(indio_dev);
+
+       ret = i2c_smbus_read_word_data(data->client, CM3323_CMD_CONF);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error reading reg_conf\n");
+               return ret;
+       }
+
+       /* enable sensor and set auto force mode */
+       ret &= ~(CM3323_CONF_SD_BIT | CM3323_CONF_AF_BIT);
+
+       ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, ret);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error writing reg_conf\n");
+               return ret;
+       }
+
+       data->reg_conf = ret;
+
+       return 0;
+}
+
+static void cm3323_disable(struct iio_dev *indio_dev)
+{
+       int ret;
+       struct cm3323_data *data = iio_priv(indio_dev);
+
+       ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF,
+                                       CM3323_CONF_SD_BIT);
+       if (ret < 0)
+               dev_err(&data->client->dev, "Error writing reg_conf\n");
+}
+
+static int cm3323_set_it_bits(struct cm3323_data *data, int val, int val2)
+{
+       int i, ret;
+       u16 reg_conf;
+
+       for (i = 0; i < ARRAY_SIZE(cm3323_int_time); i++) {
+               if (val == cm3323_int_time[i].val &&
+                   val2 == cm3323_int_time[i].val2) {
+                       reg_conf = data->reg_conf;
+                       reg_conf |= i << CM3323_CONF_IT_SHIFT;
+
+                       ret = i2c_smbus_write_word_data(data->client,
+                                                       CM3323_CMD_CONF,
+                                                       reg_conf);
+                       if (ret < 0)
+                               return ret;
+
+                       data->reg_conf = reg_conf;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static int cm3323_get_it_bits(struct cm3323_data *data)
+{
+       int bits;
+
+       bits = (data->reg_conf & CM3323_CONF_IT_MASK) >>
+               CM3323_CONF_IT_SHIFT;
+
+       if (bits >= ARRAY_SIZE(cm3323_int_time))
+               return -EINVAL;
+       return bits;
+}
+
+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;
+       struct cm3323_data *data = iio_priv(indio_dev);
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               mutex_lock(&data->mutex);
+               ret = i2c_smbus_read_word_data(data->client, chan->address);
+               if (ret < 0) {
+                       mutex_unlock(&data->mutex);
+                       return ret;
+               }
+               *val = ret;
+               mutex_unlock(&data->mutex);
+
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_INT_TIME:
+               mutex_lock(&data->mutex);
+               i = cm3323_get_it_bits(data);
+               if (i < 0) {
+                       mutex_unlock(&data->mutex);
+                       return -EINVAL;
+               }
+
+               *val = cm3323_int_time[i].val;
+               *val2 = cm3323_int_time[i].val2;
+               mutex_unlock(&data->mutex);
+
+               return IIO_VAL_INT_PLUS_MICRO;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int cm3323_write_raw(struct iio_dev *indio_dev,
+                           struct iio_chan_spec const *chan, int val,
+                           int val2, long mask)
+{
+       struct cm3323_data *data = iio_priv(indio_dev);
+       int ret;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_INT_TIME:
+               mutex_lock(&data->mutex);
+               ret = cm3323_set_it_bits(data, val, val2);
+               mutex_unlock(&data->mutex);
+
+               return ret;
+       default:
+               return -EINVAL;
+       }
+}
+
+static const struct iio_info cm3323_info = {
+       .driver_module  = THIS_MODULE,
+       .read_raw       = cm3323_read_raw,
+       .write_raw      = cm3323_write_raw,
+       .attrs          = &cm3323_attribute_group,
+};
+
+static int cm3323_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       struct cm3323_data *data;
+       struct iio_dev *indio_dev;
+       int ret;
+
+       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       data = iio_priv(indio_dev);
+       i2c_set_clientdata(client, indio_dev);
+       data->client = client;
+
+       mutex_init(&data->mutex);
+
+       indio_dev->dev.parent = &client->dev;
+       indio_dev->info = &cm3323_info;
+       indio_dev->name = CM3323_DRV_NAME;
+       indio_dev->channels = cm3323_channels;
+       indio_dev->num_channels = ARRAY_SIZE(cm3323_channels);
+       indio_dev->modes = INDIO_DIRECT_MODE;
+
+       ret = cm3323_init(indio_dev);
+       if (ret < 0) {
+               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);
+       return ret;
+}
+
+static int cm3323_remove(struct i2c_client *client)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+       iio_device_unregister(indio_dev);
+       cm3323_disable(indio_dev);
+
+       return 0;
+}
+
+static const struct i2c_device_id cm3323_id[] = {
+       {"cm3323", 0},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, cm3323_id);
+
+static struct i2c_driver cm3323_driver = {
+       .driver = {
+               .name = CM3323_DRV_NAME,
+       },
+       .probe          = cm3323_probe,
+       .remove         = cm3323_remove,
+       .id_table       = cm3323_id,
+};
+
+module_i2c_driver(cm3323_driver);
+
+MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
+MODULE_DESCRIPTION("Capella CM3323 Color Light Sensor driver");
+MODULE_LICENSE("GPL v2");
index 221ed16de1f7babd220c81296c5eef7fdb959a0d..32b6449833faf5f6102e8b55edcb6810f2c25678 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <asm/unaligned.h>
 #include <linux/iio/buffer.h>
 #include <linux/iio/events.h>
 #include <linux/iio/iio.h>
@@ -966,7 +967,6 @@ static irqreturn_t gp2ap020a00f_trigger_handler(int irq, void *data)
        struct iio_dev *indio_dev = pf->indio_dev;
        struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
        size_t d_size = 0;
-       __le32 light_lux;
        int i, out_val, ret;
 
        for_each_set_bit(i, indio_dev->active_scan_mask,
@@ -981,8 +981,8 @@ static irqreturn_t gp2ap020a00f_trigger_handler(int irq, void *data)
                    i == GP2AP020A00F_SCAN_MODE_LIGHT_IR) {
                        out_val = le16_to_cpup((__le16 *)&priv->buffer[d_size]);
                        gp2ap020a00f_output_to_lux(priv, &out_val);
-                       light_lux = cpu_to_le32(out_val);
-                       memcpy(&priv->buffer[d_size], (u8 *)&light_lux, 4);
+
+                       put_unaligned_le32(out_val, &priv->buffer[d_size]);
                        d_size += 4;
                } else {
                        d_size += 2;
index 948acfc38b8cb3c0f142c8f7350254dc36cd377c..1609ecdd01b07a73b9ad697159f9eb58ac47c5de 100644 (file)
@@ -101,7 +101,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
                        *val = sensor_hub_input_attr_get_raw_value(
                                        als_state->common_attributes.hsdev,
                                        HID_USAGE_SENSOR_ALS, address,
-                                       report_id);
+                                       report_id,
+                                       SENSOR_HUB_SYNC);
                        hid_sensor_power_state(&als_state->common_attributes,
                                                false);
                } else {
index 3ecf79ed08ac89bf4f82eedbdb47813ed2997f53..91ecc46ffeaa0b9e5ecf25d3575d8ab364e4abe8 100644 (file)
@@ -96,7 +96,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
                        *val = sensor_hub_input_attr_get_raw_value(
                                prox_state->common_attributes.hsdev,
                                HID_USAGE_SENSOR_PROX, address,
-                               report_id);
+                               report_id,
+                               SENSOR_HUB_SYNC);
                        hid_sensor_power_state(&prox_state->common_attributes,
                                                false);
                } else {
index 29de7e7d9562421b983fe0f2b4042c684c878ed1..3a3af89beaf962671c9a5e65d0b3dd7fc25ce2c4 100644 (file)
@@ -308,7 +308,7 @@ static bool jsa1212_is_volatile_reg(struct device *dev, unsigned int reg)
        }
 }
 
-static struct regmap_config jsa1212_regmap_config = {
+static const struct regmap_config jsa1212_regmap_config = {
        .name =  JSA1212_REGMAP_NAME,
        .reg_bits = 8,
        .val_bits = 8,
index 62b7072af4de1425f0eb607b2d175a36b61bed09..78b87839c4b95864fffcc40c6aaceaf0b6093ccc 100644 (file)
@@ -333,6 +333,13 @@ static int ltr501_init(struct ltr501_data *data)
                data->ps_contr);
 }
 
+static int ltr501_powerdown(struct ltr501_data *data)
+{
+       return ltr501_write_contr(data->client,
+                                 data->als_contr & ~LTR501_CONTR_ACTIVE,
+                                 data->ps_contr & ~LTR501_CONTR_ACTIVE);
+}
+
 static int ltr501_probe(struct i2c_client *client,
                          const struct i2c_device_id *id)
 {
@@ -370,7 +377,7 @@ static int ltr501_probe(struct i2c_client *client,
        ret = iio_triggered_buffer_setup(indio_dev, NULL,
                ltr501_trigger_handler, NULL);
        if (ret)
-               return ret;
+               goto powerdown_on_error;
 
        ret = iio_device_register(indio_dev);
        if (ret)
@@ -380,16 +387,11 @@ static int ltr501_probe(struct i2c_client *client,
 
 error_unreg_buffer:
        iio_triggered_buffer_cleanup(indio_dev);
+powerdown_on_error:
+       ltr501_powerdown(data);
        return ret;
 }
 
-static int ltr501_powerdown(struct ltr501_data *data)
-{
-       return ltr501_write_contr(data->client,
-               data->als_contr & ~LTR501_CONTR_ACTIVE,
-               data->ps_contr & ~LTR501_CONTR_ACTIVE);
-}
-
 static int ltr501_remove(struct i2c_client *client)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(client);
index d22993b4066a0d1d50b8000c234bc2154f5477ef..4f9c0be244518d96ddeba9f1a5cb46329859129e 100644 (file)
@@ -170,7 +170,8 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,
                        *val = sensor_hub_input_attr_get_raw_value(
                                magn_state->common_attributes.hsdev,
                                HID_USAGE_SENSOR_COMPASS_3D, address,
-                               report_id);
+                               report_id,
+                               SENSOR_HUB_SYNC);
                else {
                        *val = 0;
                        hid_sensor_power_state(&magn_state->common_attributes,
index e3106b43ef488ff69b1108edc18781fcdbd29518..261d517428e475d49b89d9d8567666abe42750a0 100644 (file)
@@ -321,6 +321,12 @@ static const struct iio_info mag3110_info = {
 
 static const unsigned long mag3110_scan_masks[] = {0x7, 0xf, 0};
 
+static int mag3110_standby(struct mag3110_data *data)
+{
+       return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
+               data->ctrl_reg1 & ~MAG3110_CTRL_AC);
+}
+
 static int mag3110_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
@@ -360,12 +366,12 @@ static int mag3110_probe(struct i2c_client *client,
        ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG2,
                MAG3110_CTRL_AUTO_MRST_EN);
        if (ret < 0)
-               return ret;
+               goto standby_on_error;
 
        ret = iio_triggered_buffer_setup(indio_dev, NULL,
                mag3110_trigger_handler, NULL);
        if (ret < 0)
-               return ret;
+               goto standby_on_error;
 
        ret = iio_device_register(indio_dev);
        if (ret < 0)
@@ -374,15 +380,11 @@ static int mag3110_probe(struct i2c_client *client,
 
 buffer_cleanup:
        iio_triggered_buffer_cleanup(indio_dev);
+standby_on_error:
+       mag3110_standby(iio_priv(indio_dev));
        return ret;
 }
 
-static int mag3110_standby(struct mag3110_data *data)
-{
-       return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
-               data->ctrl_reg1 & ~MAG3110_CTRL_AC);
-}
-
 static int mag3110_remove(struct i2c_client *client)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(client);
index 73854460bb2cff5c18622ca39fc45f1b5e42625f..5930fa32a2ab19a4df3a42f6939b323d876d3c8e 100644 (file)
@@ -124,7 +124,8 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev,
                        *val = sensor_hub_input_attr_get_raw_value(
                                incl_state->common_attributes.hsdev,
                                HID_USAGE_SENSOR_INCLINOMETER_3D, address,
-                               report_id);
+                               report_id,
+                               SENSOR_HUB_SYNC);
                else {
                        hid_sensor_power_state(&incl_state->common_attributes,
                                                false);
index a3be53792072e454bcdcb38bee764c213d6d0ef6..fa62950419479233a3aecf0f1b3fe03c42e5fe6f 100644 (file)
@@ -52,6 +52,33 @@ config MPL3115
           To compile this driver as a module, choose M here: the module
           will be called mpl3115.
 
+config MS5611
+       tristate "Measurement Specialities MS5611 pressure sensor driver"
+       help
+         Say Y here to build support for the Measurement Specialities
+         MS5611 pressure and temperature sensor.
+
+         To compile this driver as a module, choose M here: the module will
+         be called ms5611_core.
+
+config MS5611_I2C
+       tristate "support I2C bus connection"
+       depends on I2C && MS5611
+       help
+         Say Y here to build I2C bus support for MS5611.
+
+         To compile this driver as a module, choose M here: the module will
+         be called ms5611_i2c.
+
+config MS5611_SPI
+       tristate "support SPI bus connection"
+       depends on SPI_MASTER && MS5611
+       help
+         Say Y here to build SPI bus support for MS5611.
+
+         To compile this driver as a module, choose M here: the module will
+         be called ms5611_spi.
+
 config IIO_ST_PRESS
        tristate "STMicroelectronics pressure sensor Driver"
        depends on (I2C || SPI_MASTER) && SYSFS
index 88011f2ae00e4ca0f0955e97ea7f927ccc8eb4b1..a4f98f8d90ed0c33d9023feb64d7fb8d5cddc389 100644 (file)
@@ -7,6 +7,9 @@ obj-$(CONFIG_BMP280) += bmp280.o
 obj-$(CONFIG_HID_SENSOR_PRESS)   += hid-sensor-press.o
 obj-$(CONFIG_MPL115) += mpl115.o
 obj-$(CONFIG_MPL3115) += mpl3115.o
+obj-$(CONFIG_MS5611) += ms5611_core.o
+obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o
+obj-$(CONFIG_MS5611_SPI) += ms5611_spi.o
 obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o
 st_pressure-y := st_pressure_core.o
 st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o
index 1af314926ebd1f94ae422394aa186af7a05557bd..7bb8d4c1f7df4922279dd328ddfc83fba1b113c4 100644 (file)
@@ -100,7 +100,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
                        *val = sensor_hub_input_attr_get_raw_value(
                                press_state->common_attributes.hsdev,
                                HID_USAGE_SENSOR_PRESSURE, address,
-                               report_id);
+                               report_id,
+                               SENSOR_HUB_SYNC);
                        hid_sensor_power_state(&press_state->common_attributes,
                                                false);
                } else {
diff --git a/drivers/iio/pressure/ms5611.h b/drivers/iio/pressure/ms5611.h
new file mode 100644 (file)
index 0000000..099c6cd
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * MS5611 pressure and temperature sensor driver
+ *
+ * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _MS5611_H
+#define _MS5611_H
+
+#include <linux/device.h>
+#include <linux/iio/iio.h>
+#include <linux/mutex.h>
+
+#define MS5611_RESET                   0x1e
+#define MS5611_READ_ADC                        0x00
+#define MS5611_READ_PROM_WORD          0xA0
+#define MS5611_START_TEMP_CONV         0x58
+#define MS5611_START_PRESSURE_CONV     0x48
+
+#define MS5611_CONV_TIME_MIN           9040
+#define MS5611_CONV_TIME_MAX           10000
+
+#define MS5611_PROM_WORDS_NB           8
+
+struct ms5611_state {
+       void *client;
+       struct mutex lock;
+
+       int (*reset)(struct device *dev);
+       int (*read_prom_word)(struct device *dev, int index, u16 *word);
+       int (*read_adc_temp_and_pressure)(struct device *dev,
+                                         s32 *temp, s32 *pressure);
+
+       u16 prom[MS5611_PROM_WORDS_NB];
+};
+
+int ms5611_probe(struct iio_dev *indio_dev, struct device *dev);
+
+#endif /* _MS5611_H */
diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c
new file mode 100644 (file)
index 0000000..e42c853
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * MS5611 pressure and temperature sensor driver
+ *
+ * Copyright (c) Tomasz Duszynski <tduszyns@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.
+ *
+ * Data sheet:
+ *  http://www.meas-spec.com/downloads/MS5611-01BA03.pdf
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/iio/iio.h>
+#include <linux/delay.h>
+
+#include "ms5611.h"
+
+static bool ms5611_prom_is_valid(u16 *prom, size_t len)
+{
+       int i, j;
+       uint16_t crc = 0, crc_orig = prom[7] & 0x000F;
+
+       prom[7] &= 0xFF00;
+
+       for (i = 0; i < len * 2; i++) {
+               if (i % 2 == 1)
+                       crc ^= prom[i >> 1] & 0x00FF;
+               else
+                       crc ^= prom[i >> 1] >> 8;
+
+               for (j = 0; j < 8; j++) {
+                       if (crc & 0x8000)
+                               crc = (crc << 1) ^ 0x3000;
+                       else
+                               crc <<= 1;
+               }
+       }
+
+       crc = (crc >> 12) & 0x000F;
+
+       return crc_orig != 0x0000 && crc == crc_orig;
+}
+
+static int ms5611_read_prom(struct iio_dev *indio_dev)
+{
+       int ret, i;
+       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]);
+               if (ret < 0) {
+                       dev_err(&indio_dev->dev,
+                               "failed to read prom at %d\n", i);
+                       return ret;
+               }
+       }
+
+       if (!ms5611_prom_is_valid(st->prom, MS5611_PROM_WORDS_NB)) {
+               dev_err(&indio_dev->dev, "PROM integrity check failed\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+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);
+       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);
+
+       t = 2000 + ((st->prom[6] * dt) >> 23);
+       if (t < 2000) {
+               s64 off2, sens2, t2;
+
+               t2 = (dt * dt) >> 31;
+               off2 = (5 * (t - 2000) * (t - 2000)) >> 1;
+               sens2 = off2 >> 1;
+
+               if (t < -1500) {
+                       s64 tmp = (t + 1500) * (t + 1500);
+
+                       off2 += 7 * tmp;
+                       sens2 += (11 * tmp) >> 1;
+               }
+
+               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;
+       struct ms5611_state *st = iio_priv(indio_dev);
+
+       ret = st->reset(&indio_dev->dev);
+       if (ret < 0) {
+               dev_err(&indio_dev->dev, "failed to reset device\n");
+               return ret;
+       }
+
+       usleep_range(3000, 4000);
+
+       return 0;
+}
+
+static int ms5611_read_raw(struct iio_dev *indio_dev,
+                          struct iio_chan_spec const *chan,
+                          int *val, int *val2, long mask)
+{
+       int ret;
+       s32 temp, pressure;
+       struct ms5611_state *st = iio_priv(indio_dev);
+
+       switch (mask) {
+       case IIO_CHAN_INFO_PROCESSED:
+               mutex_lock(&st->lock);
+               ret = ms5611_read_temp_and_pressure(indio_dev,
+                                                   &temp, &pressure);
+               mutex_unlock(&st->lock);
+               if (ret < 0)
+                       return ret;
+
+               switch (chan->type) {
+               case IIO_TEMP:
+                       *val = temp * 10;
+                       return IIO_VAL_INT;
+               case IIO_PRESSURE:
+                       *val = pressure / 1000;
+                       *val2 = (pressure % 1000) * 1000;
+                       return IIO_VAL_INT_PLUS_MICRO;
+               default:
+                       return -EINVAL;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static const struct iio_chan_spec ms5611_channels[] = {
+       {
+               .type = IIO_PRESSURE,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+                       BIT(IIO_CHAN_INFO_SCALE)
+       },
+       {
+               .type = IIO_TEMP,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+                       BIT(IIO_CHAN_INFO_SCALE)
+       }
+};
+
+static const struct iio_info ms5611_info = {
+       .read_raw = &ms5611_read_raw,
+       .driver_module = THIS_MODULE,
+};
+
+static int ms5611_init(struct iio_dev *indio_dev)
+{
+       int ret;
+
+       ret = ms5611_reset(indio_dev);
+       if (ret < 0)
+               return ret;
+
+       return ms5611_read_prom(indio_dev);
+}
+
+int ms5611_probe(struct iio_dev *indio_dev, struct device *dev)
+{
+       int ret;
+       struct ms5611_state *st = iio_priv(indio_dev);
+
+       mutex_init(&st->lock);
+       indio_dev->dev.parent = dev;
+       indio_dev->name = dev->driver->name;
+       indio_dev->info = &ms5611_info;
+       indio_dev->channels = ms5611_channels;
+       indio_dev->num_channels = ARRAY_SIZE(ms5611_channels);
+       indio_dev->modes = INDIO_DIRECT_MODE;
+
+       ret = ms5611_init(indio_dev);
+       if (ret < 0)
+               return ret;
+
+       return devm_iio_device_register(dev, indio_dev);
+}
+EXPORT_SYMBOL(ms5611_probe);
+
+MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
+MODULE_DESCRIPTION("MS5611 core driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/pressure/ms5611_i2c.c b/drivers/iio/pressure/ms5611_i2c.c
new file mode 100644 (file)
index 0000000..748fd9a
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * MS5611 pressure and temperature sensor driver (I2C bus)
+ *
+ * Copyright (c) Tomasz Duszynski <tduszyns@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.
+ *
+ * 7-bit I2C slave addresses:
+ *
+ * 0x77 (CSB pin low)
+ * 0x76 (CSB pin high)
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+
+#include "ms5611.h"
+
+static int ms5611_i2c_reset(struct device *dev)
+{
+       struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
+
+       return i2c_smbus_write_byte(st->client, MS5611_RESET);
+}
+
+static int ms5611_i2c_read_prom_word(struct device *dev, int index, u16 *word)
+{
+       int ret;
+       struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
+
+       ret = i2c_smbus_read_word_swapped(st->client,
+                       MS5611_READ_PROM_WORD + (index << 1));
+       if (ret < 0)
+               return ret;
+
+       *word = ret;
+
+       return 0;
+}
+
+static int ms5611_i2c_read_adc(struct ms5611_state *st, s32 *val)
+{
+       int ret;
+       u8 buf[3];
+
+       ret = i2c_smbus_read_i2c_block_data(st->client, MS5611_READ_ADC,
+                                           3, buf);
+       if (ret < 0)
+               return ret;
+
+       *val = (buf[0] << 16) | (buf[1] << 8) | buf[2];
+
+       return 0;
+}
+
+static int ms5611_i2c_read_adc_temp_and_pressure(struct device *dev,
+                                                s32 *temp, s32 *pressure)
+{
+       int ret;
+       struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
+
+       ret = i2c_smbus_write_byte(st->client, MS5611_START_TEMP_CONV);
+       if (ret < 0)
+               return ret;
+
+       usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
+
+       ret = ms5611_i2c_read_adc(st, temp);
+       if (ret < 0)
+               return ret;
+
+       ret = i2c_smbus_write_byte(st->client, MS5611_START_PRESSURE_CONV);
+       if (ret < 0)
+               return ret;
+
+       usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
+
+       return ms5611_i2c_read_adc(st, pressure);
+}
+
+static int ms5611_i2c_probe(struct i2c_client *client,
+                           const struct i2c_device_id *id)
+{
+       struct ms5611_state *st;
+       struct iio_dev *indio_dev;
+
+       if (!i2c_check_functionality(client->adapter,
+                                    I2C_FUNC_SMBUS_WRITE_BYTE |
+                                    I2C_FUNC_SMBUS_READ_WORD_DATA |
+                                    I2C_FUNC_SMBUS_READ_I2C_BLOCK))
+               return -ENODEV;
+
+       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       st = iio_priv(indio_dev);
+       st->reset = ms5611_i2c_reset;
+       st->read_prom_word = ms5611_i2c_read_prom_word;
+       st->read_adc_temp_and_pressure = ms5611_i2c_read_adc_temp_and_pressure;
+       st->client = client;
+
+       return ms5611_probe(indio_dev, &client->dev);
+}
+
+static const struct i2c_device_id ms5611_id[] = {
+       { "ms5611", 0 },
+       { }
+};
+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,
+};
+module_i2c_driver(ms5611_driver);
+
+MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
+MODULE_DESCRIPTION("MS5611 i2c driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c
new file mode 100644 (file)
index 0000000..976726f
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * MS5611 pressure and temperature sensor driver (SPI bus)
+ *
+ * Copyright (c) Tomasz Duszynski <tduszyns@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/delay.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#include "ms5611.h"
+
+static int ms5611_spi_reset(struct device *dev)
+{
+       u8 cmd = MS5611_RESET;
+       struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
+
+       return spi_write_then_read(st->client, &cmd, 1, NULL, 0);
+}
+
+static int ms5611_spi_read_prom_word(struct device *dev, int index, u16 *word)
+{
+       int ret;
+       struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
+
+       ret = spi_w8r16be(st->client, MS5611_READ_PROM_WORD + (index << 1));
+       if (ret < 0)
+               return ret;
+
+       *word = ret;
+
+       return 0;
+}
+
+static int ms5611_spi_read_adc(struct device *dev, s32 *val)
+{
+       int ret;
+       u8 buf[3] = { MS5611_READ_ADC };
+       struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
+
+       ret = spi_write_then_read(st->client, buf, 1, buf, 3);
+       if (ret < 0)
+               return ret;
+
+       *val = (buf[0] << 16) | (buf[1] << 8) | buf[2];
+
+       return 0;
+}
+
+static int ms5611_spi_read_adc_temp_and_pressure(struct device *dev,
+                                                s32 *temp, s32 *pressure)
+{
+       u8 cmd;
+       int ret;
+       struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
+
+       cmd = MS5611_START_TEMP_CONV;
+       ret = spi_write_then_read(st->client, &cmd, 1, NULL, 0);
+       if (ret < 0)
+               return ret;
+
+       usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
+
+       ret = ms5611_spi_read_adc(dev, temp);
+       if (ret < 0)
+               return ret;
+
+       cmd = MS5611_START_PRESSURE_CONV;
+       ret = spi_write_then_read(st->client, &cmd, 1, NULL, 0);
+       if (ret < 0)
+               return ret;
+
+       usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
+
+       return ms5611_spi_read_adc(dev, pressure);
+}
+
+static int ms5611_spi_probe(struct spi_device *spi)
+{
+       int ret;
+       struct ms5611_state *st;
+       struct iio_dev *indio_dev;
+
+       indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       spi->mode = SPI_MODE_0;
+       spi->max_speed_hz = 20000000;
+       spi->bits_per_word = 8;
+       ret = spi_setup(spi);
+       if (ret < 0)
+               return ret;
+
+       st = iio_priv(indio_dev);
+       st->reset = ms5611_spi_reset;
+       st->read_prom_word = ms5611_spi_read_prom_word;
+       st->read_adc_temp_and_pressure = ms5611_spi_read_adc_temp_and_pressure;
+       st->client = spi;
+
+       return ms5611_probe(indio_dev, &spi->dev);
+}
+
+static const struct spi_device_id ms5611_id[] = {
+       { "ms5611", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, ms5611_id);
+
+static struct spi_driver ms5611_driver = {
+       .driver = {
+               .name = "ms5611",
+               .owner = THIS_MODULE,
+       },
+       .id_table = ms5611_id,
+       .probe = ms5611_spi_probe,
+};
+module_spi_driver(ms5611_driver);
+
+MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
+MODULE_DESCRIPTION("MS5611 spi driver");
+MODULE_LICENSE("GPL v2");
index 89fca3a7075039b9b9a0de5514c1b96758d4593b..fa40f6d0ca394f0ae41f6509d6f6c3079062b77e 100644 (file)
@@ -618,16 +618,12 @@ static int sx9500_gpio_probe(struct i2c_client *client,
        dev = &client->dev;
 
        /* data ready gpio interrupt pin */
-       gpio = devm_gpiod_get_index(dev, SX9500_GPIO_NAME, 0);
+       gpio = devm_gpiod_get_index(dev, SX9500_GPIO_NAME, 0, GPIOD_IN);
        if (IS_ERR(gpio)) {
                dev_err(dev, "acpi gpio get index failed\n");
                return PTR_ERR(gpio);
        }
 
-       ret = gpiod_direction_input(gpio);
-       if (ret)
-               return ret;
-
        ret = gpiod_to_irq(gpio);
 
        dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
index c8b6ac8b2d69ad7cbfd834309d263a026b50b2e7..a112fc9abf4346ba0e53b03314fa3781aec9eeac 100644 (file)
@@ -2,6 +2,7 @@
  * mlx90614.c - Support for Melexis MLX90614 contactless IR temperature sensor
  *
  * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
+ * Copyright (c) 2015 Essensium NV
  *
  * 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
 
 #include <linux/iio/iio.h>
 
-#define MLX90614_OP_RAM 0x00
+#define MLX90614_OP_RAM                0x00
+#define MLX90614_OP_EEPROM     0x20
+#define MLX90614_OP_SLEEP      0xff
 
 /* RAM offsets with 16-bit data, MSB first */
-#define MLX90614_TA 0x06 /* ambient temperature */
-#define MLX90614_TOBJ1 0x07 /* object temperature */
+#define MLX90614_RAW1  (MLX90614_OP_RAM | 0x04) /* raw data IR channel 1 */
+#define MLX90614_RAW2  (MLX90614_OP_RAM | 0x05) /* raw data IR channel 2 */
+#define MLX90614_TA    (MLX90614_OP_RAM | 0x06) /* ambient temperature */
+#define MLX90614_TOBJ1 (MLX90614_OP_RAM | 0x07) /* object 1 temperature */
+#define MLX90614_TOBJ2 (MLX90614_OP_RAM | 0x08) /* object 2 temperature */
+
+/* EEPROM offsets with 16-bit data, MSB first */
+#define MLX90614_EMISSIVITY    (MLX90614_OP_EEPROM | 0x04) /* emissivity correction coefficient */
+#define MLX90614_CONFIG                (MLX90614_OP_EEPROM | 0x05) /* configuration register */
+
+/* Control bits in configuration register */
+#define MLX90614_CONFIG_IIR_SHIFT 0 /* IIR coefficient */
+#define MLX90614_CONFIG_IIR_MASK (0x7 << MLX90614_CONFIG_IIR_SHIFT)
+#define MLX90614_CONFIG_DUAL_SHIFT 6 /* single (0) or dual (1) IR sensor */
+#define MLX90614_CONFIG_DUAL_MASK (1 << MLX90614_CONFIG_DUAL_SHIFT)
+#define MLX90614_CONFIG_FIR_SHIFT 8 /* FIR coefficient */
+#define MLX90614_CONFIG_FIR_MASK (0x7 << MLX90614_CONFIG_FIR_SHIFT)
+#define MLX90614_CONFIG_GAIN_SHIFT 11 /* gain */
+#define MLX90614_CONFIG_GAIN_MASK (0x7 << MLX90614_CONFIG_GAIN_SHIFT)
+
+/* Timings (in ms) */
+#define MLX90614_TIMING_EEPROM 20 /* time for EEPROM write/erase to complete */
+#define MLX90614_TIMING_WAKEUP 34 /* time to hold SDA low for wake-up */
+#define MLX90614_TIMING_STARTUP 250 /* time before first data after wake-up */
 
 struct mlx90614_data {
        struct i2c_client *client;
@@ -35,26 +60,34 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev,
                            int *val2, long mask)
 {
        struct mlx90614_data *data = iio_priv(indio_dev);
+       u8 cmd;
        s32 ret;
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW: /* 0.02K / LSB */
                switch (channel->channel2) {
                case IIO_MOD_TEMP_AMBIENT:
-                       ret = i2c_smbus_read_word_data(data->client,
-                           MLX90614_OP_RAM | MLX90614_TA);
-                       if (ret < 0)
-                               return ret;
+                       cmd = MLX90614_TA;
                        break;
                case IIO_MOD_TEMP_OBJECT:
-                       ret = i2c_smbus_read_word_data(data->client,
-                           MLX90614_OP_RAM | MLX90614_TOBJ1);
-                       if (ret < 0)
-                               return ret;
+                       switch (channel->channel) {
+                       case 0:
+                               cmd = MLX90614_TOBJ1;
+                               break;
+                       case 1:
+                               cmd = MLX90614_TOBJ2;
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
                        break;
                default:
                        return -EINVAL;
                }
+
+               ret = i2c_smbus_read_word_data(data->client, cmd);
+               if (ret < 0)
+                       return ret;
                *val = ret;
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_OFFSET:
@@ -86,6 +119,16 @@ static const struct iio_chan_spec mlx90614_channels[] = {
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
                    BIT(IIO_CHAN_INFO_SCALE),
        },
+       {
+               .type = IIO_TEMP,
+               .indexed = 1,
+               .modified = 1,
+               .channel = 1,
+               .channel2 = IIO_MOD_TEMP_OBJECT,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+                   BIT(IIO_CHAN_INFO_SCALE),
+       },
 };
 
 static const struct iio_info mlx90614_info = {
@@ -93,11 +136,25 @@ static const struct iio_info mlx90614_info = {
        .driver_module = THIS_MODULE,
 };
 
+/* Return 0 for single sensor, 1 for dual sensor, <0 on error. */
+static int mlx90614_probe_num_ir_sensors(struct i2c_client *client)
+{
+       s32 ret;
+
+       ret = i2c_smbus_read_word_data(client, MLX90614_CONFIG);
+
+       if (ret < 0)
+               return ret;
+
+       return (ret & MLX90614_CONFIG_DUAL_MASK) ? 1 : 0;
+}
+
 static int mlx90614_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
        struct iio_dev *indio_dev;
        struct mlx90614_data *data;
+       int ret;
 
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
                return -ENODEV;
@@ -115,8 +172,21 @@ static int mlx90614_probe(struct i2c_client *client,
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &mlx90614_info;
 
-       indio_dev->channels = mlx90614_channels;
-       indio_dev->num_channels = ARRAY_SIZE(mlx90614_channels);
+       ret = mlx90614_probe_num_ir_sensors(client);
+       switch (ret) {
+       case 0:
+               dev_dbg(&client->dev, "Found single sensor");
+               indio_dev->channels = mlx90614_channels;
+               indio_dev->num_channels = 2;
+               break;
+       case 1:
+               dev_dbg(&client->dev, "Found dual sensor");
+               indio_dev->channels = mlx90614_channels;
+               indio_dev->num_channels = 3;
+               break;
+       default:
+               return ret;
+       }
 
        return iio_device_register(indio_dev);
 }
@@ -146,5 +216,6 @@ static struct i2c_driver mlx90614_driver = {
 module_i2c_driver(mlx90614_driver);
 
 MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_AUTHOR("Vianney le Clément de Saint-Marcq <vianney.leclement@essensium.com>");
 MODULE_DESCRIPTION("Melexis MLX90614 contactless IR temperature sensor driver");
 MODULE_LICENSE("GPL");
index 6d7f453b4d05ef7da7f74aeafe22608b85dc00fc..aed8afee56da16a6a3609a247c9bea2c54060c44 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/slab.h>
 #include <linux/highmem.h>
 #include <linux/io.h>
-#include <linux/aio.h>
 #include <linux/jiffies.h>
 #include <linux/cpu.h>
 #include <asm/pgtable.h>
index 41937c6f888af13deadb6c7b25678cfc34596cf8..14046f5a37fa332cf5e5b25ba1a86a5fe7918188 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
 #include <linux/io.h>
-#include <linux/aio.h>
 #include <linux/jiffies.h>
 #include <asm/pgtable.h>
 #include <linux/delay.h>
index b097af269e0097ae314c9c57c2aca05c4eb5f948..54fce56c80236808d5a6eb02fa6c8d17ebb76415 100644 (file)
@@ -88,10 +88,13 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
                        goto err_mem;
        }
 
-       /* Mark slots as 'unused' */
+       /* Mark slots as 'inactive' */
        for (i = 0; i < num_slots; i++)
                input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1);
 
+       /* Mark slots as 'unused' */
+       mt->frame = 1;
+
        dev->mt = mt;
        return 0;
 err_mem:
@@ -447,6 +450,8 @@ EXPORT_SYMBOL(input_mt_assign_slots);
  * set the key on the first unused slot and return.
  *
  * If no available slot can be found, -1 is returned.
+ * Note that for this function to work properly, input_mt_sync_frame() has
+ * to be called at each frame.
  */
 int input_mt_get_slot_by_key(struct input_dev *dev, int key)
 {
@@ -461,7 +466,7 @@ int input_mt_get_slot_by_key(struct input_dev *dev, int key)
                        return s - mt->slots;
 
        for (s = mt->slots; s != mt->slots + mt->num_slots; s++)
-               if (!input_mt_is_active(s)) {
+               if (!input_mt_is_active(s) && !input_mt_is_used(mt, s)) {
                        s->key = key;
                        return s - mt->slots;
                }
index af1dc6a1c0a1fba38df9d7a6f7b4556251182dea..43429ab62228a4d0674dadeab740be812af77ff8 100644 (file)
@@ -133,19 +133,25 @@ struct iommu_ops *of_iommu_get_ops(struct device_node *np)
        return ops;
 }
 
-struct iommu_ops *of_iommu_configure(struct device *dev)
+struct iommu_ops *of_iommu_configure(struct device *dev,
+                                    struct device_node *master_np)
 {
        struct of_phandle_args iommu_spec;
        struct device_node *np;
        struct iommu_ops *ops = NULL;
        int idx = 0;
 
+       if (dev_is_pci(dev)) {
+               dev_err(dev, "IOMMU is currently not supported for PCI\n");
+               return NULL;
+       }
+
        /*
         * We don't currently walk up the tree looking for a parent IOMMU.
         * See the `Notes:' section of
         * Documentation/devicetree/bindings/iommu/iommu.txt
         */
-       while (!of_parse_phandle_with_args(dev->of_node, "iommus",
+       while (!of_parse_phandle_with_args(master_np, "iommus",
                                           "#iommu-cells", idx,
                                           &iommu_spec)) {
                np = iommu_spec.np;
index cc79d2a5a8c212999ccc71da19f019ea5bf30210..c8d260e33a90d340cdb0a98d23eb1d289ba86160 100644 (file)
@@ -110,6 +110,13 @@ config RENESAS_IRQC
        bool
        select IRQ_DOMAIN
 
+config ST_IRQCHIP
+       bool
+       select REGMAP
+       select MFD_SYSCON
+       help
+         Enables SysCfg Controlled IRQs on STi based platforms.
+
 config TB10X_IRQC
        bool
        select IRQ_DOMAIN
index 42965d2476bbb03cb7d7caf66980b6caa360a16c..552a740276015179dd170e65d82f2f4983a72ddb 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_HIP04)                += irq-hip04.o
 obj-$(CONFIG_ARCH_MMP)                 += irq-mmp.o
 obj-$(CONFIG_ARCH_MVEBU)               += irq-armada-370-xp.o
 obj-$(CONFIG_ARCH_MXS)                 += irq-mxs.o
+obj-$(CONFIG_ARCH_TEGRA)               += irq-tegra.o
 obj-$(CONFIG_ARCH_S3C24XX)             += irq-s3c24xx.o
 obj-$(CONFIG_DW_APB_ICTL)              += irq-dw-apb-ictl.o
 obj-$(CONFIG_METAG)                    += irq-metag-ext.o
@@ -33,10 +34,12 @@ obj-$(CONFIG_RENESAS_IRQC)          += irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)       += irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_NSPIRE)              += irq-zevio.o
 obj-$(CONFIG_ARCH_VT8500)              += irq-vt8500.o
+obj-$(CONFIG_ST_IRQCHIP)               += irq-st.o
 obj-$(CONFIG_TB10X_IRQC)               += irq-tb10x.o
 obj-$(CONFIG_XTENSA)                   += irq-xtensa-pic.o
 obj-$(CONFIG_XTENSA_MX)                        += irq-xtensa-mx.o
 obj-$(CONFIG_IRQ_CROSSBAR)             += irq-crossbar.o
+obj-$(CONFIG_SOC_VF610)                        += irq-vf610-mscm-ir.o
 obj-$(CONFIG_BCM7120_L2_IRQ)           += irq-bcm7120-l2.o
 obj-$(CONFIG_BRCMSTB_L2_IRQ)           += irq-brcmstb-l2.o
 obj-$(CONFIG_KEYSTONE_IRQ)             += irq-keystone.o
index 4387dae14e453a949bb297ec1a74a59e400a3089..daccc8bdbb423fd5e6b700b4ffe6b57be0af30a1 100644 (file)
@@ -38,6 +38,8 @@
 /* Interrupt Controller Registers Map */
 #define ARMADA_370_XP_INT_SET_MASK_OFFS                (0x48)
 #define ARMADA_370_XP_INT_CLEAR_MASK_OFFS      (0x4C)
+#define ARMADA_370_XP_INT_FABRIC_MASK_OFFS     (0x54)
+#define ARMADA_370_XP_INT_CAUSE_PERF(cpu)      (1 << cpu)
 
 #define ARMADA_370_XP_INT_CONTROL              (0x00)
 #define ARMADA_370_XP_INT_SET_ENABLE_OFFS      (0x30)
@@ -56,6 +58,7 @@
 #define ARMADA_370_XP_MAX_PER_CPU_IRQS         (28)
 
 #define ARMADA_370_XP_TIMER0_PER_CPU_IRQ       (5)
+#define ARMADA_370_XP_FABRIC_IRQ               (3)
 
 #define IPI_DOORBELL_START                      (0)
 #define IPI_DOORBELL_END                        (8)
@@ -77,6 +80,17 @@ static DEFINE_MUTEX(msi_used_lock);
 static phys_addr_t msi_doorbell_addr;
 #endif
 
+static inline bool is_percpu_irq(irq_hw_number_t irq)
+{
+       switch (irq) {
+       case ARMADA_370_XP_TIMER0_PER_CPU_IRQ:
+       case ARMADA_370_XP_FABRIC_IRQ:
+               return true;
+       default:
+               return false;
+       }
+}
+
 /*
  * In SMP mode:
  * For shared global interrupts, mask/unmask global enable bit
@@ -86,7 +100,7 @@ static void armada_370_xp_irq_mask(struct irq_data *d)
 {
        irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
-       if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
+       if (!is_percpu_irq(hwirq))
                writel(hwirq, main_int_base +
                                ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS);
        else
@@ -98,7 +112,7 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
 {
        irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
-       if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
+       if (!is_percpu_irq(hwirq))
                writel(hwirq, main_int_base +
                                ARMADA_370_XP_INT_SET_ENABLE_OFFS);
        else
@@ -281,20 +295,21 @@ static struct irq_chip armada_370_xp_irq_chip = {
 #ifdef CONFIG_SMP
        .irq_set_affinity = armada_xp_set_affinity,
 #endif
+       .flags          = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
 };
 
 static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
                                      unsigned int virq, irq_hw_number_t hw)
 {
        armada_370_xp_irq_mask(irq_get_irq_data(virq));
-       if (hw != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
+       if (!is_percpu_irq(hw))
                writel(hw, per_cpu_int_base +
                        ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
        else
                writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS);
        irq_set_status_flags(virq, IRQ_LEVEL);
 
-       if (hw == ARMADA_370_XP_TIMER0_PER_CPU_IRQ) {
+       if (is_percpu_irq(hw)) {
                irq_set_percpu_devid(virq);
                irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
                                        handle_percpu_devid_irq);
@@ -308,28 +323,6 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
        return 0;
 }
 
-#ifdef CONFIG_SMP
-static void armada_mpic_send_doorbell(const struct cpumask *mask,
-                                     unsigned int irq)
-{
-       int cpu;
-       unsigned long map = 0;
-
-       /* Convert our logical CPU mask into a physical one. */
-       for_each_cpu(cpu, mask)
-               map |= 1 << cpu_logical_map(cpu);
-
-       /*
-        * Ensure that stores to Normal memory are visible to the
-        * other CPUs before issuing the IPI.
-        */
-       dsb();
-
-       /* submit softirq */
-       writel((map << 8) | irq, main_int_base +
-               ARMADA_370_XP_SW_TRIG_INT_OFFS);
-}
-
 static void armada_xp_mpic_smp_cpu_init(void)
 {
        u32 control;
@@ -352,11 +345,44 @@ static void armada_xp_mpic_smp_cpu_init(void)
        writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
 }
 
+static void armada_xp_mpic_perf_init(void)
+{
+       unsigned long cpuid = cpu_logical_map(smp_processor_id());
+
+       /* Enable Performance Counter Overflow interrupts */
+       writel(ARMADA_370_XP_INT_CAUSE_PERF(cpuid),
+              per_cpu_int_base + ARMADA_370_XP_INT_FABRIC_MASK_OFFS);
+}
+
+#ifdef CONFIG_SMP
+static void armada_mpic_send_doorbell(const struct cpumask *mask,
+                                     unsigned int irq)
+{
+       int cpu;
+       unsigned long map = 0;
+
+       /* Convert our logical CPU mask into a physical one. */
+       for_each_cpu(cpu, mask)
+               map |= 1 << cpu_logical_map(cpu);
+
+       /*
+        * Ensure that stores to Normal memory are visible to the
+        * other CPUs before issuing the IPI.
+        */
+       dsb();
+
+       /* submit softirq */
+       writel((map << 8) | irq, main_int_base +
+               ARMADA_370_XP_SW_TRIG_INT_OFFS);
+}
+
 static int armada_xp_mpic_secondary_init(struct notifier_block *nfb,
                                         unsigned long action, void *hcpu)
 {
-       if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
+       if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) {
+               armada_xp_mpic_perf_init();
                armada_xp_mpic_smp_cpu_init();
+       }
 
        return NOTIFY_OK;
 }
@@ -369,8 +395,10 @@ static struct notifier_block armada_370_xp_mpic_cpu_notifier = {
 static int mpic_cascaded_secondary_init(struct notifier_block *nfb,
                                        unsigned long action, void *hcpu)
 {
-       if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
+       if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) {
+               armada_xp_mpic_perf_init();
                enable_percpu_irq(parent_irq, IRQ_TYPE_NONE);
+       }
 
        return NOTIFY_OK;
 }
@@ -379,7 +407,6 @@ static struct notifier_block mpic_cascaded_cpu_notifier = {
        .notifier_call = mpic_cascaded_secondary_init,
        .priority = 100,
 };
-
 #endif /* CONFIG_SMP */
 
 static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
@@ -588,9 +615,9 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
 
        BUG_ON(!armada_370_xp_mpic_domain);
 
-#ifdef CONFIG_SMP
+       /* Setup for the boot CPU */
+       armada_xp_mpic_perf_init();
        armada_xp_mpic_smp_cpu_init();
-#endif
 
        armada_370_xp_msi_init(node, main_int_res.start);
 
index bbbaf5de65d2cda705949998e4e3a62ce813496e..692fe2bc81979b6b48f984ec6d88c117fbfdebdd 100644 (file)
  */
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
-#include <linux/irqchip/arm-gic.h>
-#include <linux/irqchip/irq-crossbar.h>
+
+#include "irqchip.h"
 
 #define IRQ_FREE       -1
 #define IRQ_RESERVED   -2
@@ -24,6 +25,7 @@
 
 /**
  * struct crossbar_device - crossbar device description
+ * @lock: spinlock serializing access to @irq_map
  * @int_max: maximum number of supported interrupts
  * @safe_map: safe default value to initialize the crossbar
  * @max_crossbar_sources: Maximum number of crossbar sources
@@ -33,6 +35,7 @@
  * @write: register write function pointer
  */
 struct crossbar_device {
+       raw_spinlock_t lock;
        uint int_max;
        uint safe_map;
        uint max_crossbar_sources;
@@ -44,72 +47,101 @@ struct crossbar_device {
 
 static struct crossbar_device *cb;
 
-static inline void crossbar_writel(int irq_no, int cb_no)
+static void crossbar_writel(int irq_no, int cb_no)
 {
        writel(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
 }
 
-static inline void crossbar_writew(int irq_no, int cb_no)
+static void crossbar_writew(int irq_no, int cb_no)
 {
        writew(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
 }
 
-static inline void crossbar_writeb(int irq_no, int cb_no)
+static void crossbar_writeb(int irq_no, int cb_no)
 {
        writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
 }
 
-static inline int get_prev_map_irq(int cb_no)
-{
-       int i;
-
-       for (i = cb->int_max - 1; i >= 0; i--)
-               if (cb->irq_map[i] == cb_no)
-                       return i;
-
-       return -ENODEV;
-}
+static struct irq_chip crossbar_chip = {
+       .name                   = "CBAR",
+       .irq_eoi                = irq_chip_eoi_parent,
+       .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,
+#ifdef CONFIG_SMP
+       .irq_set_affinity       = irq_chip_set_affinity_parent,
+#endif
+};
 
-static inline int allocate_free_irq(int cb_no)
+static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
+                           irq_hw_number_t hwirq)
 {
+       struct of_phandle_args args;
        int i;
+       int err;
 
+       raw_spin_lock(&cb->lock);
        for (i = cb->int_max - 1; i >= 0; i--) {
                if (cb->irq_map[i] == IRQ_FREE) {
-                       cb->irq_map[i] = cb_no;
-                       return i;
+                       cb->irq_map[i] = hwirq;
+                       break;
                }
        }
+       raw_spin_unlock(&cb->lock);
 
-       return -ENODEV;
-}
+       if (i < 0)
+               return -ENODEV;
 
-static inline bool needs_crossbar_write(irq_hw_number_t hw)
-{
-       int cb_no;
+       args.np = domain->parent->of_node;
+       args.args_count = 3;
+       args.args[0] = 0;       /* SPI */
+       args.args[1] = i;
+       args.args[2] = IRQ_TYPE_LEVEL_HIGH;
 
-       if (hw > GIC_IRQ_START) {
-               cb_no = cb->irq_map[hw - GIC_IRQ_START];
-               if (cb_no != IRQ_RESERVED && cb_no != IRQ_SKIP)
-                       return true;
-       }
+       err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+       if (err)
+               cb->irq_map[i] = IRQ_FREE;
+       else
+               cb->write(i, hwirq);
 
-       return false;
+       return err;
 }
 
-static int crossbar_domain_map(struct irq_domain *d, unsigned int irq,
-                              irq_hw_number_t hw)
+static int crossbar_domain_alloc(struct irq_domain *d, unsigned int virq,
+                                unsigned int nr_irqs, void *data)
 {
-       if (needs_crossbar_write(hw))
-               cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]);
+       struct of_phandle_args *args = data;
+       irq_hw_number_t hwirq;
+       int i;
+
+       if (args->args_count != 3)
+               return -EINVAL; /* Not GIC compliant */
+       if (args->args[0] != 0)
+               return -EINVAL; /* No PPI should point to this domain */
+
+       hwirq = args->args[1];
+       if ((hwirq + nr_irqs) > cb->max_crossbar_sources)
+               return -EINVAL; /* Can't deal with this */
+
+       for (i = 0; i < nr_irqs; i++) {
+               int err = allocate_gic_irq(d, virq + i, hwirq + i);
+
+               if (err)
+                       return err;
+
+               irq_domain_set_hwirq_and_chip(d, virq + i, hwirq + i,
+                                             &crossbar_chip, NULL);
+       }
 
        return 0;
 }
 
 /**
- * crossbar_domain_unmap - unmap a crossbar<->irq connection
- * @d: domain of irq to unmap
- * @irq: virq number
+ * crossbar_domain_free - unmap/free a crossbar<->irq connection
+ * @domain: domain of irq to unmap
+ * @virq: virq number
+ * @nr_irqs: number of irqs to free
  *
  * We do not maintain a use count of total number of map/unmap
  * calls for a particular irq to find out if a irq can be really
@@ -117,14 +149,20 @@ static int crossbar_domain_map(struct irq_domain *d, unsigned int irq,
  * after which irq is anyways unusable. So an explicit map has to be called
  * after that.
  */
-static void crossbar_domain_unmap(struct irq_domain *d, unsigned int irq)
+static void crossbar_domain_free(struct irq_domain *domain, unsigned int virq,
+                                unsigned int nr_irqs)
 {
-       irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq;
+       int i;
 
-       if (needs_crossbar_write(hw)) {
-               cb->irq_map[hw - GIC_IRQ_START] = IRQ_FREE;
-               cb->write(hw - GIC_IRQ_START, cb->safe_map);
+       raw_spin_lock(&cb->lock);
+       for (i = 0; i < nr_irqs; i++) {
+               struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
+
+               irq_domain_reset_irq_data(d);
+               cb->irq_map[d->hwirq] = IRQ_FREE;
+               cb->write(d->hwirq, cb->safe_map);
        }
+       raw_spin_unlock(&cb->lock);
 }
 
 static int crossbar_domain_xlate(struct irq_domain *d,
@@ -133,44 +171,22 @@ static int crossbar_domain_xlate(struct irq_domain *d,
                                 unsigned long *out_hwirq,
                                 unsigned int *out_type)
 {
-       int ret;
-       int req_num = intspec[1];
-       int direct_map_num;
-
-       if (req_num >= cb->max_crossbar_sources) {
-               direct_map_num = req_num - cb->max_crossbar_sources;
-               if (direct_map_num < cb->int_max) {
-                       ret = cb->irq_map[direct_map_num];
-                       if (ret == IRQ_RESERVED || ret == IRQ_SKIP) {
-                               /* We use the interrupt num as h/w irq num */
-                               ret = direct_map_num;
-                               goto found;
-                       }
-               }
-
-               pr_err("%s: requested crossbar number %d > max %d\n",
-                      __func__, req_num, cb->max_crossbar_sources);
-               return -EINVAL;
-       }
-
-       ret = get_prev_map_irq(req_num);
-       if (ret >= 0)
-               goto found;
-
-       ret = allocate_free_irq(req_num);
-
-       if (ret < 0)
-               return ret;
-
-found:
-       *out_hwirq = ret + GIC_IRQ_START;
+       if (d->of_node != controller)
+               return -EINVAL; /* Shouldn't happen, really... */
+       if (intsize != 3)
+               return -EINVAL; /* Not GIC compliant */
+       if (intspec[0] != 0)
+               return -EINVAL; /* No PPI should point to this domain */
+
+       *out_hwirq = intspec[1];
+       *out_type = intspec[2];
        return 0;
 }
 
-static const struct irq_domain_ops routable_irq_domain_ops = {
-       .map = crossbar_domain_map,
-       .unmap = crossbar_domain_unmap,
-       .xlate = crossbar_domain_xlate
+static const struct irq_domain_ops crossbar_domain_ops = {
+       .alloc  = crossbar_domain_alloc,
+       .free   = crossbar_domain_free,
+       .xlate  = crossbar_domain_xlate,
 };
 
 static int __init crossbar_of_init(struct device_node *node)
@@ -293,7 +309,8 @@ static int __init crossbar_of_init(struct device_node *node)
                cb->write(i, cb->safe_map);
        }
 
-       register_routable_domain_ops(&routable_irq_domain_ops);
+       raw_spin_lock_init(&cb->lock);
+
        return 0;
 
 err_reg_offset:
@@ -309,18 +326,37 @@ err_cb:
        return ret;
 }
 
-static const struct of_device_id crossbar_match[] __initconst = {
-       { .compatible = "ti,irq-crossbar" },
-       {}
-};
-
-int __init irqcrossbar_init(void)
+static int __init irqcrossbar_init(struct device_node *node,
+                                  struct device_node *parent)
 {
-       struct device_node *np;
-       np = of_find_matching_node(NULL, crossbar_match);
-       if (!np)
+       struct irq_domain *parent_domain, *domain;
+       int err;
+
+       if (!parent) {
+               pr_err("%s: no parent, giving up\n", node->full_name);
                return -ENODEV;
+       }
+
+       parent_domain = irq_find_host(parent);
+       if (!parent_domain) {
+               pr_err("%s: unable to obtain parent domain\n", node->full_name);
+               return -ENXIO;
+       }
+
+       err = crossbar_of_init(node);
+       if (err)
+               return err;
+
+       domain = irq_domain_add_hierarchy(parent_domain, 0,
+                                         cb->max_crossbar_sources,
+                                         node, &crossbar_domain_ops,
+                                         NULL);
+       if (!domain) {
+               pr_err("%s: failed to allocated domain\n", node->full_name);
+               return -ENOMEM;
+       }
 
-       crossbar_of_init(np);
        return 0;
 }
+
+IRQCHIP_DECLARE(ti_irqcrossbar, "ti,irq-crossbar", irqcrossbar_init);
index 930a2a2fac7ffd5182e36780fd3b1e929fd3651f..3cbc658afe27a4f7d28875373a1816afad86ac8b 100644 (file)
@@ -55,8 +55,8 @@ static void __exception_irq_entry digicolor_handle_irq(struct pt_regs *regs)
        } while (1);
 }
 
-static void digicolor_set_gc(void __iomem *reg_base, unsigned irq_base,
-                            unsigned en_reg, unsigned ack_reg)
+static void __init digicolor_set_gc(void __iomem *reg_base, unsigned irq_base,
+                                   unsigned en_reg, unsigned ack_reg)
 {
        struct irq_chip_generic *gc;
 
index fd8850def1b86a3310e376c821c3aaf33153f1cc..4f2fb62e6f373c5978bddaa17ac203abcc69703e 100644 (file)
@@ -195,6 +195,19 @@ static void gic_enable_redist(bool enable)
 /*
  * Routines to disable, enable, EOI and route interrupts
  */
+static int gic_peek_irq(struct irq_data *d, u32 offset)
+{
+       u32 mask = 1 << (gic_irq(d) % 32);
+       void __iomem *base;
+
+       if (gic_irq_in_rdist(d))
+               base = gic_data_rdist_sgi_base();
+       else
+               base = gic_data.dist_base;
+
+       return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask);
+}
+
 static void gic_poke_irq(struct irq_data *d, u32 offset)
 {
        u32 mask = 1 << (gic_irq(d) % 32);
@@ -223,6 +236,61 @@ static void gic_unmask_irq(struct irq_data *d)
        gic_poke_irq(d, GICD_ISENABLER);
 }
 
+static int gic_irq_set_irqchip_state(struct irq_data *d,
+                                    enum irqchip_irq_state which, bool val)
+{
+       u32 reg;
+
+       if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */
+               return -EINVAL;
+
+       switch (which) {
+       case IRQCHIP_STATE_PENDING:
+               reg = val ? GICD_ISPENDR : GICD_ICPENDR;
+               break;
+
+       case IRQCHIP_STATE_ACTIVE:
+               reg = val ? GICD_ISACTIVER : GICD_ICACTIVER;
+               break;
+
+       case IRQCHIP_STATE_MASKED:
+               reg = val ? GICD_ICENABLER : GICD_ISENABLER;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       gic_poke_irq(d, reg);
+       return 0;
+}
+
+static int gic_irq_get_irqchip_state(struct irq_data *d,
+                                    enum irqchip_irq_state which, bool *val)
+{
+       if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */
+               return -EINVAL;
+
+       switch (which) {
+       case IRQCHIP_STATE_PENDING:
+               *val = gic_peek_irq(d, GICD_ISPENDR);
+               break;
+
+       case IRQCHIP_STATE_ACTIVE:
+               *val = gic_peek_irq(d, GICD_ISACTIVER);
+               break;
+
+       case IRQCHIP_STATE_MASKED:
+               *val = !gic_peek_irq(d, GICD_ISENABLER);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static void gic_eoi_irq(struct irq_data *d)
 {
        gic_write_eoir(gic_irq(d));
@@ -418,19 +486,6 @@ static void gic_cpu_init(void)
 }
 
 #ifdef CONFIG_SMP
-static int gic_peek_irq(struct irq_data *d, u32 offset)
-{
-       u32 mask = 1 << (gic_irq(d) % 32);
-       void __iomem *base;
-
-       if (gic_irq_in_rdist(d))
-               base = gic_data_rdist_sgi_base();
-       else
-               base = gic_data.dist_base;
-
-       return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask);
-}
-
 static int gic_secondary_init(struct notifier_block *nfb,
                              unsigned long action, void *hcpu)
 {
@@ -601,6 +656,8 @@ static struct irq_chip gic_chip = {
        .irq_eoi                = gic_eoi_irq,
        .irq_set_type           = gic_set_type,
        .irq_set_affinity       = gic_set_affinity,
+       .irq_get_irqchip_state  = gic_irq_get_irqchip_state,
+       .irq_set_irqchip_state  = gic_irq_set_irqchip_state,
 };
 
 #define GIC_ID_NR              (1U << gic_data.rdists.id_bits)
index 471e1cdc193365dce99dcb53e3c8b21a388e0faa..a6ce3476834e4e218db5de2ec03d0a25df7e54da 100644 (file)
@@ -151,13 +151,24 @@ static inline unsigned int gic_irq(struct irq_data *d)
 /*
  * Routines to acknowledge, disable and enable interrupts
  */
-static void gic_mask_irq(struct irq_data *d)
+static void gic_poke_irq(struct irq_data *d, u32 offset)
 {
        u32 mask = 1 << (gic_irq(d) % 32);
+       writel_relaxed(mask, gic_dist_base(d) + offset + (gic_irq(d) / 32) * 4);
+}
+
+static int gic_peek_irq(struct irq_data *d, u32 offset)
+{
+       u32 mask = 1 << (gic_irq(d) % 32);
+       return !!(readl_relaxed(gic_dist_base(d) + offset + (gic_irq(d) / 32) * 4) & mask);
+}
+
+static void gic_mask_irq(struct irq_data *d)
+{
        unsigned long flags;
 
        raw_spin_lock_irqsave(&irq_controller_lock, flags);
-       writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
+       gic_poke_irq(d, GIC_DIST_ENABLE_CLEAR);
        if (gic_arch_extn.irq_mask)
                gic_arch_extn.irq_mask(d);
        raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
@@ -165,13 +176,12 @@ static void gic_mask_irq(struct irq_data *d)
 
 static void gic_unmask_irq(struct irq_data *d)
 {
-       u32 mask = 1 << (gic_irq(d) % 32);
        unsigned long flags;
 
        raw_spin_lock_irqsave(&irq_controller_lock, flags);
        if (gic_arch_extn.irq_unmask)
                gic_arch_extn.irq_unmask(d);
-       writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
+       gic_poke_irq(d, GIC_DIST_ENABLE_SET);
        raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
 }
 
@@ -186,6 +196,55 @@ static void gic_eoi_irq(struct irq_data *d)
        writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
 }
 
+static int gic_irq_set_irqchip_state(struct irq_data *d,
+                                    enum irqchip_irq_state which, bool val)
+{
+       u32 reg;
+
+       switch (which) {
+       case IRQCHIP_STATE_PENDING:
+               reg = val ? GIC_DIST_PENDING_SET : GIC_DIST_PENDING_CLEAR;
+               break;
+
+       case IRQCHIP_STATE_ACTIVE:
+               reg = val ? GIC_DIST_ACTIVE_SET : GIC_DIST_ACTIVE_CLEAR;
+               break;
+
+       case IRQCHIP_STATE_MASKED:
+               reg = val ? GIC_DIST_ENABLE_CLEAR : GIC_DIST_ENABLE_SET;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       gic_poke_irq(d, reg);
+       return 0;
+}
+
+static int gic_irq_get_irqchip_state(struct irq_data *d,
+                                     enum irqchip_irq_state which, bool *val)
+{
+       switch (which) {
+       case IRQCHIP_STATE_PENDING:
+               *val = gic_peek_irq(d, GIC_DIST_PENDING_SET);
+               break;
+
+       case IRQCHIP_STATE_ACTIVE:
+               *val = gic_peek_irq(d, GIC_DIST_ACTIVE_SET);
+               break;
+
+       case IRQCHIP_STATE_MASKED:
+               *val = !gic_peek_irq(d, GIC_DIST_ENABLE_SET);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int gic_set_type(struct irq_data *d, unsigned int type)
 {
        void __iomem *base = gic_dist_base(d);
@@ -329,6 +388,8 @@ static struct irq_chip gic_chip = {
        .irq_set_affinity       = gic_set_affinity,
 #endif
        .irq_set_wake           = gic_set_wake,
+       .irq_get_irqchip_state  = gic_irq_get_irqchip_state,
+       .irq_set_irqchip_state  = gic_irq_set_irqchip_state,
 };
 
 void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
@@ -353,7 +414,7 @@ static u8 gic_get_cpumask(struct gic_chip_data *gic)
                        break;
        }
 
-       if (!mask)
+       if (!mask && num_possible_cpus() > 1)
                pr_crit("GIC CPU mask not found - kernel will fail to boot.\n");
 
        return mask;
@@ -802,15 +863,12 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
                irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data,
                                    handle_fasteoi_irq, NULL, NULL);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-
-               gic_routable_irq_domain_ops->map(d, irq, hw);
        }
        return 0;
 }
 
 static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq)
 {
-       gic_routable_irq_domain_ops->unmap(d, irq);
 }
 
 static int gic_irq_domain_xlate(struct irq_domain *d,
@@ -829,16 +887,8 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
        *out_hwirq = intspec[1] + 16;
 
        /* For SPIs, we need to add 16 more to get the GIC irq ID number */
-       if (!intspec[0]) {
-               ret = gic_routable_irq_domain_ops->xlate(d, controller,
-                                                        intspec,
-                                                        intsize,
-                                                        out_hwirq,
-                                                        out_type);
-
-               if (IS_ERR_VALUE(ret))
-                       return ret;
-       }
+       if (!intspec[0])
+               *out_hwirq += 16;
 
        *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
 
@@ -895,37 +945,11 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
        .xlate = gic_irq_domain_xlate,
 };
 
-/* Default functions for routable irq domain */
-static int gic_routable_irq_domain_map(struct irq_domain *d, unsigned int irq,
-                             irq_hw_number_t hw)
+void gic_set_irqchip_flags(unsigned long flags)
 {
-       return 0;
+       gic_chip.flags |= flags;
 }
 
-static void gic_routable_irq_domain_unmap(struct irq_domain *d,
-                                         unsigned int irq)
-{
-}
-
-static int gic_routable_irq_domain_xlate(struct irq_domain *d,
-                               struct device_node *controller,
-                               const u32 *intspec, unsigned int intsize,
-                               unsigned long *out_hwirq,
-                               unsigned int *out_type)
-{
-       *out_hwirq += 16;
-       return 0;
-}
-
-static const struct irq_domain_ops gic_default_routable_irq_domain_ops = {
-       .map = gic_routable_irq_domain_map,
-       .unmap = gic_routable_irq_domain_unmap,
-       .xlate = gic_routable_irq_domain_xlate,
-};
-
-const struct irq_domain_ops *gic_routable_irq_domain_ops =
-                                       &gic_default_routable_irq_domain_ops;
-
 void __init gic_init_bases(unsigned int gic_nr, int irq_start,
                           void __iomem *dist_base, void __iomem *cpu_base,
                           u32 percpu_offset, struct device_node *node)
@@ -933,7 +957,6 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
        irq_hw_number_t hwirq_base;
        struct gic_chip_data *gic;
        int gic_irqs, irq_base, i;
-       int nr_routable_irqs;
 
        BUG_ON(gic_nr >= MAX_GIC_NR);
 
@@ -989,15 +1012,9 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
        gic->gic_irqs = gic_irqs;
 
        if (node) {             /* DT case */
-               const struct irq_domain_ops *ops = &gic_irq_domain_hierarchy_ops;
-
-               if (!of_property_read_u32(node, "arm,routable-irqs",
-                                         &nr_routable_irqs)) {
-                       ops = &gic_irq_domain_ops;
-                       gic_irqs = nr_routable_irqs;
-               }
-
-               gic->domain = irq_domain_add_linear(node, gic_irqs, ops, gic);
+               gic->domain = irq_domain_add_linear(node, gic_irqs,
+                                                   &gic_irq_domain_hierarchy_ops,
+                                                   gic);
        } else {                /* Non-DT case */
                /*
                 * For primary GICs, skip over SGIs.
index 9acdc080e7ecd21b2cd256c18e31c9c27337c7d1..f2d269bca78989850483666ba81ecbaa096f973a 100644 (file)
@@ -166,6 +166,27 @@ cycle_t gic_read_compare(void)
 
        return (((cycle_t) hi) << 32) + lo;
 }
+
+void gic_start_count(void)
+{
+       u32 gicconfig;
+
+       /* Start the counter */
+       gicconfig = gic_read(GIC_REG(SHARED, GIC_SH_CONFIG));
+       gicconfig &= ~(1 << GIC_SH_CONFIG_COUNTSTOP_SHF);
+       gic_write(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
+}
+
+void gic_stop_count(void)
+{
+       u32 gicconfig;
+
+       /* Stop the counter */
+       gicconfig = gic_read(GIC_REG(SHARED, GIC_SH_CONFIG));
+       gicconfig |= 1 << GIC_SH_CONFIG_COUNTSTOP_SHF;
+       gic_write(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
+}
+
 #endif
 
 static bool gic_local_irq_is_routable(int intr)
index 384e6ed61d7c5e94a3081380b0bde6edc2d08129..cdf80b7794cd738e38ec956f3246ae216f9ddde1 100644 (file)
@@ -17,6 +17,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <linux/clk.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/platform_data/irq-renesas-irqc.h>
+#include <linux/pm_runtime.h>
 
-#define IRQC_IRQ_MAX 32 /* maximum 32 interrupts per driver instance */
+#define IRQC_IRQ_MAX   32      /* maximum 32 interrupts per driver instance */
 
-#define IRQC_REQ_STS 0x00
-#define IRQC_EN_STS 0x04
-#define IRQC_EN_SET 0x08
+#define IRQC_REQ_STS   0x00    /* Interrupt Request Status Register */
+#define IRQC_EN_STS    0x04    /* Interrupt Enable Status Register */
+#define IRQC_EN_SET    0x08    /* Interrupt Enable Set Register */
 #define IRQC_INT_CPU_BASE(n) (0x000 + ((n) * 0x10))
-#define DETECT_STATUS 0x100
+                               /* SYS-CPU vs. RT-CPU */
+#define DETECT_STATUS  0x100   /* IRQn Detect Status Register */
+#define MONITOR                0x104   /* IRQn Signal Level Monitor Register */
+#define HLVL_STS       0x108   /* IRQn High Level Detect Status Register */
+#define LLVL_STS       0x10c   /* IRQn Low Level Detect Status Register */
+#define S_R_EDGE_STS   0x110   /* IRQn Sync Rising Edge Detect Status Reg. */
+#define S_F_EDGE_STS   0x114   /* IRQn Sync Falling Edge Detect Status Reg. */
+#define A_R_EDGE_STS   0x118   /* IRQn Async Rising Edge Detect Status Reg. */
+#define A_F_EDGE_STS   0x11c   /* IRQn Async Falling Edge Detect Status Reg. */
+#define CHTEN_STS      0x120   /* Chattering Reduction Status Register */
 #define IRQC_CONFIG(n) (0x180 + ((n) * 0x04))
+                               /* IRQn Configuration Register */
 
 struct irqc_irq {
        int hw_irq;
@@ -55,6 +67,7 @@ struct irqc_priv {
        struct platform_device *pdev;
        struct irq_chip irq_chip;
        struct irq_domain *irq_domain;
+       struct clk *clk;
 };
 
 static void irqc_dbg(struct irqc_irq *i, char *str)
@@ -94,7 +107,7 @@ static int irqc_irq_set_type(struct irq_data *d, unsigned int type)
        struct irqc_priv *p = irq_data_get_irq_chip_data(d);
        int hw_irq = irqd_to_hwirq(d);
        unsigned char value = irqc_sense[type & IRQ_TYPE_SENSE_MASK];
-       unsigned long tmp;
+       u32 tmp;
 
        irqc_dbg(&p->irq[hw_irq], "sense");
 
@@ -108,11 +121,26 @@ static int irqc_irq_set_type(struct irq_data *d, unsigned int type)
        return 0;
 }
 
+static int irqc_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+       struct irqc_priv *p = irq_data_get_irq_chip_data(d);
+
+       if (!p->clk)
+               return 0;
+
+       if (on)
+               clk_enable(p->clk);
+       else
+               clk_disable(p->clk);
+
+       return 0;
+}
+
 static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
 {
        struct irqc_irq *i = dev_id;
        struct irqc_priv *p = i->p;
-       unsigned long bit = BIT(i->hw_irq);
+       u32 bit = BIT(i->hw_irq);
 
        irqc_dbg(i, "demux1");
 
@@ -170,6 +198,15 @@ static int irqc_probe(struct platform_device *pdev)
        p->pdev = pdev;
        platform_set_drvdata(pdev, p);
 
+       p->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(p->clk)) {
+               dev_warn(&pdev->dev, "unable to get clock\n");
+               p->clk = NULL;
+       }
+
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
+
        /* get hold of manadatory IOMEM */
        io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!io) {
@@ -210,7 +247,8 @@ static int irqc_probe(struct platform_device *pdev)
        irq_chip->irq_mask = irqc_irq_disable;
        irq_chip->irq_unmask = irqc_irq_enable;
        irq_chip->irq_set_type = irqc_irq_set_type;
-       irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
+       irq_chip->irq_set_wake = irqc_irq_set_wake;
+       irq_chip->flags = IRQCHIP_MASK_ON_SUSPEND;
 
        p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
                                              p->number_of_irqs,
@@ -250,6 +288,8 @@ err3:
 err2:
        iounmap(p->iomem);
 err1:
+       pm_runtime_put(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
        kfree(p);
 err0:
        return ret;
@@ -265,6 +305,8 @@ static int irqc_remove(struct platform_device *pdev)
 
        irq_domain_remove(p->irq_domain);
        iounmap(p->iomem);
+       pm_runtime_put(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
        kfree(p);
        return 0;
 }
diff --git a/drivers/irqchip/irq-st.c b/drivers/irqchip/irq-st.c
new file mode 100644 (file)
index 0000000..9af48a8
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ *  Copyright (C) 2014 STMicroelectronics â€“ All Rights Reserved
+ *
+ *  Author: Lee Jones <lee.jones@linaro.org>
+ *
+ *  This is a re-write of Christophe Kerello's PMU driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/interrupt-controller/irq-st.h>
+#include <linux/err.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define STIH415_SYSCFG_642             0x0a8
+#define STIH416_SYSCFG_7543            0x87c
+#define STIH407_SYSCFG_5102            0x198
+#define STID127_SYSCFG_734             0x088
+
+#define ST_A9_IRQ_MASK                 0x001FFFFF
+#define ST_A9_IRQ_MAX_CHANS            2
+
+#define ST_A9_IRQ_EN_CTI_0             BIT(0)
+#define ST_A9_IRQ_EN_CTI_1             BIT(1)
+#define ST_A9_IRQ_EN_PMU_0             BIT(2)
+#define ST_A9_IRQ_EN_PMU_1             BIT(3)
+#define ST_A9_IRQ_EN_PL310_L2          BIT(4)
+#define ST_A9_IRQ_EN_EXT_0             BIT(5)
+#define ST_A9_IRQ_EN_EXT_1             BIT(6)
+#define ST_A9_IRQ_EN_EXT_2             BIT(7)
+
+#define ST_A9_FIQ_N_SEL(dev, chan)     (dev << (8  + (chan * 3)))
+#define ST_A9_IRQ_N_SEL(dev, chan)     (dev << (14 + (chan * 3)))
+#define ST_A9_EXTIRQ_INV_SEL(dev)      (dev << 20)
+
+struct st_irq_syscfg {
+       struct regmap *regmap;
+       unsigned int syscfg;
+       unsigned int config;
+       bool ext_inverted;
+};
+
+static const struct of_device_id st_irq_syscfg_match[] = {
+       {
+               .compatible = "st,stih415-irq-syscfg",
+               .data = (void *)STIH415_SYSCFG_642,
+       },
+       {
+               .compatible = "st,stih416-irq-syscfg",
+               .data = (void *)STIH416_SYSCFG_7543,
+       },
+       {
+               .compatible = "st,stih407-irq-syscfg",
+               .data = (void *)STIH407_SYSCFG_5102,
+       },
+       {
+               .compatible = "st,stid127-irq-syscfg",
+               .data = (void *)STID127_SYSCFG_734,
+       },
+       {}
+};
+
+static int st_irq_xlate(struct platform_device *pdev,
+                       int device, int channel, bool irq)
+{
+       struct st_irq_syscfg *ddata = dev_get_drvdata(&pdev->dev);
+
+       /* Set the device enable bit. */
+       switch (device) {
+       case ST_IRQ_SYSCFG_EXT_0:
+               ddata->config |= ST_A9_IRQ_EN_EXT_0;
+               break;
+       case ST_IRQ_SYSCFG_EXT_1:
+               ddata->config |= ST_A9_IRQ_EN_EXT_1;
+               break;
+       case ST_IRQ_SYSCFG_EXT_2:
+               ddata->config |= ST_A9_IRQ_EN_EXT_2;
+               break;
+       case ST_IRQ_SYSCFG_CTI_0:
+               ddata->config |= ST_A9_IRQ_EN_CTI_0;
+               break;
+       case ST_IRQ_SYSCFG_CTI_1:
+               ddata->config |= ST_A9_IRQ_EN_CTI_1;
+               break;
+       case ST_IRQ_SYSCFG_PMU_0:
+               ddata->config |= ST_A9_IRQ_EN_PMU_0;
+               break;
+       case ST_IRQ_SYSCFG_PMU_1:
+               ddata->config |= ST_A9_IRQ_EN_PMU_1;
+               break;
+       case ST_IRQ_SYSCFG_pl310_L2:
+               ddata->config |= ST_A9_IRQ_EN_PL310_L2;
+               break;
+       case ST_IRQ_SYSCFG_DISABLED:
+               return 0;
+       default:
+               dev_err(&pdev->dev, "Unrecognised device %d\n", device);
+               return -EINVAL;
+       }
+
+       /* Select IRQ/FIQ channel for device. */
+       ddata->config |= irq ?
+               ST_A9_IRQ_N_SEL(device, channel) :
+               ST_A9_FIQ_N_SEL(device, channel);
+
+       return 0;
+}
+
+static int st_irq_syscfg_enable(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct st_irq_syscfg *ddata = dev_get_drvdata(&pdev->dev);
+       int channels, ret, i;
+       u32 device, invert;
+
+       channels = of_property_count_u32_elems(np, "st,irq-device");
+       if (channels != ST_A9_IRQ_MAX_CHANS) {
+               dev_err(&pdev->dev, "st,enable-irq-device must have 2 elems\n");
+               return -EINVAL;
+       }
+
+       channels = of_property_count_u32_elems(np, "st,fiq-device");
+       if (channels != ST_A9_IRQ_MAX_CHANS) {
+               dev_err(&pdev->dev, "st,enable-fiq-device must have 2 elems\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < ST_A9_IRQ_MAX_CHANS; i++) {
+               of_property_read_u32_index(np, "st,irq-device", i, &device);
+
+               ret = st_irq_xlate(pdev, device, i, true);
+               if (ret)
+                       return ret;
+
+               of_property_read_u32_index(np, "st,fiq-device", i, &device);
+
+               ret = st_irq_xlate(pdev, device, i, false);
+               if (ret)
+                       return ret;
+       }
+
+       /* External IRQs may be inverted. */
+       of_property_read_u32(np, "st,invert-ext", &invert);
+       ddata->config |= ST_A9_EXTIRQ_INV_SEL(invert);
+
+       return regmap_update_bits(ddata->regmap, ddata->syscfg,
+                                 ST_A9_IRQ_MASK, ddata->config);
+}
+
+static int st_irq_syscfg_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       const struct of_device_id *match;
+       struct st_irq_syscfg *ddata;
+
+       ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+       if (!ddata)
+               return -ENOMEM;
+
+       match = of_match_device(st_irq_syscfg_match, &pdev->dev);
+       if (!match)
+               return -ENODEV;
+
+       ddata->syscfg = (unsigned int)match->data;
+
+       ddata->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+       if (IS_ERR(ddata->regmap)) {
+               dev_err(&pdev->dev, "syscfg phandle missing\n");
+               return PTR_ERR(ddata->regmap);
+       }
+
+       dev_set_drvdata(&pdev->dev, ddata);
+
+       return st_irq_syscfg_enable(pdev);
+}
+
+static int st_irq_syscfg_resume(struct device *dev)
+{
+       struct st_irq_syscfg *ddata = dev_get_drvdata(dev);
+
+       return regmap_update_bits(ddata->regmap, ddata->syscfg,
+                                 ST_A9_IRQ_MASK, ddata->config);
+}
+
+static SIMPLE_DEV_PM_OPS(st_irq_syscfg_pm_ops, NULL, st_irq_syscfg_resume);
+
+static struct platform_driver st_irq_syscfg_driver = {
+       .driver = {
+               .name = "st_irq_syscfg",
+               .pm = &st_irq_syscfg_pm_ops,
+               .of_match_table = st_irq_syscfg_match,
+       },
+       .probe = st_irq_syscfg_probe,
+};
+
+static int __init st_irq_syscfg_init(void)
+{
+       return platform_driver_register(&st_irq_syscfg_driver);
+}
+core_initcall(st_irq_syscfg_init);
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
new file mode 100644 (file)
index 0000000..51c485d
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * Driver code for Tegra's Legacy Interrupt Controller
+ *
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * Heavily based on the original arch/arm/mach-tegra/irq.c code:
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@android.com>
+ *
+ * Copyright (C) 2010,2013, NVIDIA Corporation
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/syscore_ops.h>
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "irqchip.h"
+
+#define ICTLR_CPU_IEP_VFIQ     0x08
+#define ICTLR_CPU_IEP_FIR      0x14
+#define ICTLR_CPU_IEP_FIR_SET  0x18
+#define ICTLR_CPU_IEP_FIR_CLR  0x1c
+
+#define ICTLR_CPU_IER          0x20
+#define ICTLR_CPU_IER_SET      0x24
+#define ICTLR_CPU_IER_CLR      0x28
+#define ICTLR_CPU_IEP_CLASS    0x2C
+
+#define ICTLR_COP_IER          0x30
+#define ICTLR_COP_IER_SET      0x34
+#define ICTLR_COP_IER_CLR      0x38
+#define ICTLR_COP_IEP_CLASS    0x3c
+
+#define TEGRA_MAX_NUM_ICTLRS   6
+
+static unsigned int num_ictlrs;
+
+struct tegra_ictlr_soc {
+       unsigned int num_ictlrs;
+};
+
+static const struct tegra_ictlr_soc tegra20_ictlr_soc = {
+       .num_ictlrs = 4,
+};
+
+static const struct tegra_ictlr_soc tegra30_ictlr_soc = {
+       .num_ictlrs = 5,
+};
+
+static const struct tegra_ictlr_soc tegra210_ictlr_soc = {
+       .num_ictlrs = 6,
+};
+
+static const struct of_device_id ictlr_matches[] = {
+       { .compatible = "nvidia,tegra210-ictlr", .data = &tegra210_ictlr_soc },
+       { .compatible = "nvidia,tegra30-ictlr", .data = &tegra30_ictlr_soc },
+       { .compatible = "nvidia,tegra20-ictlr", .data = &tegra20_ictlr_soc },
+       { }
+};
+
+struct tegra_ictlr_info {
+       void __iomem *base[TEGRA_MAX_NUM_ICTLRS];
+#ifdef CONFIG_PM_SLEEP
+       u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
+       u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
+       u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
+       u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
+
+       u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
+#endif
+};
+
+static struct tegra_ictlr_info *lic;
+
+static inline void tegra_ictlr_write_mask(struct irq_data *d, unsigned long reg)
+{
+       void __iomem *base = d->chip_data;
+       u32 mask;
+
+       mask = BIT(d->hwirq % 32);
+       writel_relaxed(mask, base + reg);
+}
+
+static void tegra_mask(struct irq_data *d)
+{
+       tegra_ictlr_write_mask(d, ICTLR_CPU_IER_CLR);
+       irq_chip_mask_parent(d);
+}
+
+static void tegra_unmask(struct irq_data *d)
+{
+       tegra_ictlr_write_mask(d, ICTLR_CPU_IER_SET);
+       irq_chip_unmask_parent(d);
+}
+
+static void tegra_eoi(struct irq_data *d)
+{
+       tegra_ictlr_write_mask(d, ICTLR_CPU_IEP_FIR_CLR);
+       irq_chip_eoi_parent(d);
+}
+
+static int tegra_retrigger(struct irq_data *d)
+{
+       tegra_ictlr_write_mask(d, ICTLR_CPU_IEP_FIR_SET);
+       return irq_chip_retrigger_hierarchy(d);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_set_wake(struct irq_data *d, unsigned int enable)
+{
+       u32 irq = d->hwirq;
+       u32 index, mask;
+
+       index = (irq / 32);
+       mask = BIT(irq % 32);
+       if (enable)
+               lic->ictlr_wake_mask[index] |= mask;
+       else
+               lic->ictlr_wake_mask[index] &= ~mask;
+
+       /*
+        * Do *not* call into the parent, as the GIC doesn't have any
+        * wake-up facility...
+        */
+       return 0;
+}
+
+static int tegra_ictlr_suspend(void)
+{
+       unsigned long flags;
+       unsigned int i;
+
+       local_irq_save(flags);
+       for (i = 0; i < num_ictlrs; i++) {
+               void __iomem *ictlr = lic->base[i];
+
+               /* Save interrupt state */
+               lic->cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
+               lic->cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
+               lic->cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
+               lic->cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
+
+               /* Disable COP interrupts */
+               writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+
+               /* Disable CPU interrupts */
+               writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+
+               /* Enable the wakeup sources of ictlr */
+               writel_relaxed(lic->ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
+       }
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+static void tegra_ictlr_resume(void)
+{
+       unsigned long flags;
+       unsigned int i;
+
+       local_irq_save(flags);
+       for (i = 0; i < num_ictlrs; i++) {
+               void __iomem *ictlr = lic->base[i];
+
+               writel_relaxed(lic->cpu_iep[i],
+                              ictlr + ICTLR_CPU_IEP_CLASS);
+               writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+               writel_relaxed(lic->cpu_ier[i],
+                              ictlr + ICTLR_CPU_IER_SET);
+               writel_relaxed(lic->cop_iep[i],
+                              ictlr + ICTLR_COP_IEP_CLASS);
+               writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+               writel_relaxed(lic->cop_ier[i],
+                              ictlr + ICTLR_COP_IER_SET);
+       }
+       local_irq_restore(flags);
+}
+
+static struct syscore_ops tegra_ictlr_syscore_ops = {
+       .suspend        = tegra_ictlr_suspend,
+       .resume         = tegra_ictlr_resume,
+};
+
+static void tegra_ictlr_syscore_init(void)
+{
+       register_syscore_ops(&tegra_ictlr_syscore_ops);
+}
+#else
+#define tegra_set_wake NULL
+static inline void tegra_ictlr_syscore_init(void) {}
+#endif
+
+static struct irq_chip tegra_ictlr_chip = {
+       .name                   = "LIC",
+       .irq_eoi                = tegra_eoi,
+       .irq_mask               = tegra_mask,
+       .irq_unmask             = tegra_unmask,
+       .irq_retrigger          = tegra_retrigger,
+       .irq_set_wake           = tegra_set_wake,
+       .flags                  = IRQCHIP_MASK_ON_SUSPEND,
+#ifdef CONFIG_SMP
+       .irq_set_affinity       = irq_chip_set_affinity_parent,
+#endif
+};
+
+static int tegra_ictlr_domain_xlate(struct irq_domain *domain,
+                                   struct device_node *controller,
+                                   const u32 *intspec,
+                                   unsigned int intsize,
+                                   unsigned long *out_hwirq,
+                                   unsigned int *out_type)
+{
+       if (domain->of_node != controller)
+               return -EINVAL; /* Shouldn't happen, really... */
+       if (intsize != 3)
+               return -EINVAL; /* Not GIC compliant */
+       if (intspec[0] != GIC_SPI)
+               return -EINVAL; /* No PPI should point to this domain */
+
+       *out_hwirq = intspec[1];
+       *out_type = intspec[2];
+       return 0;
+}
+
+static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
+                                   unsigned int virq,
+                                   unsigned int nr_irqs, void *data)
+{
+       struct of_phandle_args *args = data;
+       struct of_phandle_args parent_args;
+       struct tegra_ictlr_info *info = domain->host_data;
+       irq_hw_number_t hwirq;
+       unsigned int i;
+
+       if (args->args_count != 3)
+               return -EINVAL; /* Not GIC compliant */
+       if (args->args[0] != GIC_SPI)
+               return -EINVAL; /* No PPI should point to this domain */
+
+       hwirq = args->args[1];
+       if (hwirq >= (num_ictlrs * 32))
+               return -EINVAL;
+
+       for (i = 0; i < nr_irqs; i++) {
+               int ictlr = (hwirq + i) / 32;
+
+               irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+                                             &tegra_ictlr_chip,
+                                             &info->base[ictlr]);
+       }
+
+       parent_args = *args;
+       parent_args.np = domain->parent->of_node;
+       return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+}
+
+static void tegra_ictlr_domain_free(struct irq_domain *domain,
+                                   unsigned int virq,
+                                   unsigned int nr_irqs)
+{
+       unsigned int i;
+
+       for (i = 0; i < nr_irqs; i++) {
+               struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
+               irq_domain_reset_irq_data(d);
+       }
+}
+
+static const struct irq_domain_ops tegra_ictlr_domain_ops = {
+       .xlate  = tegra_ictlr_domain_xlate,
+       .alloc  = tegra_ictlr_domain_alloc,
+       .free   = tegra_ictlr_domain_free,
+};
+
+static int __init tegra_ictlr_init(struct device_node *node,
+                                  struct device_node *parent)
+{
+       struct irq_domain *parent_domain, *domain;
+       const struct of_device_id *match;
+       const struct tegra_ictlr_soc *soc;
+       unsigned int i;
+       int err;
+
+       if (!parent) {
+               pr_err("%s: no parent, giving up\n", node->full_name);
+               return -ENODEV;
+       }
+
+       parent_domain = irq_find_host(parent);
+       if (!parent_domain) {
+               pr_err("%s: unable to obtain parent domain\n", node->full_name);
+               return -ENXIO;
+       }
+
+       match = of_match_node(ictlr_matches, node);
+       if (!match)             /* Should never happen... */
+               return -ENODEV;
+
+       soc = match->data;
+
+       lic = kzalloc(sizeof(*lic), GFP_KERNEL);
+       if (!lic)
+               return -ENOMEM;
+
+       for (i = 0; i < TEGRA_MAX_NUM_ICTLRS; i++) {
+               void __iomem *base;
+
+               base = of_iomap(node, i);
+               if (!base)
+                       break;
+
+               lic->base[i] = base;
+
+               /* Disable all interrupts */
+               writel_relaxed(~0UL, base + ICTLR_CPU_IER_CLR);
+               /* All interrupts target IRQ */
+               writel_relaxed(0, base + ICTLR_CPU_IEP_CLASS);
+
+               num_ictlrs++;
+       }
+
+       if (!num_ictlrs) {
+               pr_err("%s: no valid regions, giving up\n", node->full_name);
+               err = -ENOMEM;
+               goto out_free;
+       }
+
+       WARN(num_ictlrs != soc->num_ictlrs,
+            "%s: Found %u interrupt controllers in DT; expected %u.\n",
+            node->full_name, num_ictlrs, soc->num_ictlrs);
+
+
+       domain = irq_domain_add_hierarchy(parent_domain, 0, num_ictlrs * 32,
+                                         node, &tegra_ictlr_domain_ops,
+                                         lic);
+       if (!domain) {
+               pr_err("%s: failed to allocated domain\n", node->full_name);
+               err = -ENOMEM;
+               goto out_unmap;
+       }
+
+       tegra_ictlr_syscore_init();
+
+       pr_info("%s: %d interrupts forwarded to %s\n",
+               node->full_name, num_ictlrs * 32, parent->full_name);
+
+       return 0;
+
+out_unmap:
+       for (i = 0; i < num_ictlrs; i++)
+               iounmap(lic->base[i]);
+out_free:
+       kfree(lic);
+       return err;
+}
+
+IRQCHIP_DECLARE(tegra20_ictlr, "nvidia,tegra20-ictlr", tegra_ictlr_init);
+IRQCHIP_DECLARE(tegra30_ictlr, "nvidia,tegra30-ictlr", tegra_ictlr_init);
+IRQCHIP_DECLARE(tegra210_ictlr, "nvidia,tegra210-ictlr", tegra_ictlr_init);
diff --git a/drivers/irqchip/irq-vf610-mscm-ir.c b/drivers/irqchip/irq-vf610-mscm-ir.c
new file mode 100644 (file)
index 0000000..9521057
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2014-2015 Toradex AG
+ * Author: Stefan Agner <stefan@agner.ch>
+ *
+ * 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.
+ *
+ *
+ * IRQ chip driver for MSCM interrupt router available on Vybrid SoC's.
+ * The interrupt router is between the CPU's interrupt controller and the
+ * peripheral. The router allows to route the peripheral interrupts to
+ * one of the two available CPU's on Vybrid VF6xx SoC's (Cortex-A5 or
+ * Cortex-M4). The router will be configured transparently on a IRQ
+ * request.
+ *
+ * o All peripheral interrupts of the Vybrid SoC can be routed to
+ *   CPU 0, CPU 1 or both. The routing is useful for dual-core
+ *   variants of Vybrid SoC such as VF6xx. This driver routes the
+ *   requested interrupt to the CPU currently running on.
+ *
+ * o It is required to setup the interrupt router even on single-core
+ *   variants of Vybrid.
+ */
+
+#include <linux/cpu_pm.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/mfd/syscon.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+
+#include "irqchip.h"
+
+#define MSCM_CPxNUM            0x4
+
+#define MSCM_IRSPRC(n)         (0x80 + 2 * (n))
+#define MSCM_IRSPRC_CPEN_MASK  0x3
+
+#define MSCM_IRSPRC_NUM                112
+
+struct vf610_mscm_ir_chip_data {
+       void __iomem *mscm_ir_base;
+       u16 cpu_mask;
+       u16 saved_irsprc[MSCM_IRSPRC_NUM];
+};
+
+static struct vf610_mscm_ir_chip_data *mscm_ir_data;
+
+static inline void vf610_mscm_ir_save(struct vf610_mscm_ir_chip_data *data)
+{
+       int i;
+
+       for (i = 0; i < MSCM_IRSPRC_NUM; i++)
+               data->saved_irsprc[i] = readw_relaxed(data->mscm_ir_base + MSCM_IRSPRC(i));
+}
+
+static inline void vf610_mscm_ir_restore(struct vf610_mscm_ir_chip_data *data)
+{
+       int i;
+
+       for (i = 0; i < MSCM_IRSPRC_NUM; i++)
+               writew_relaxed(data->saved_irsprc[i], data->mscm_ir_base + MSCM_IRSPRC(i));
+}
+
+static int vf610_mscm_ir_notifier(struct notifier_block *self,
+                                 unsigned long cmd, void *v)
+{
+       switch (cmd) {
+       case CPU_CLUSTER_PM_ENTER:
+               vf610_mscm_ir_save(mscm_ir_data);
+               break;
+       case CPU_CLUSTER_PM_ENTER_FAILED:
+       case CPU_CLUSTER_PM_EXIT:
+               vf610_mscm_ir_restore(mscm_ir_data);
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block mscm_ir_notifier_block = {
+       .notifier_call = vf610_mscm_ir_notifier,
+};
+
+static void vf610_mscm_ir_enable(struct irq_data *data)
+{
+       irq_hw_number_t hwirq = data->hwirq;
+       struct vf610_mscm_ir_chip_data *chip_data = data->chip_data;
+       u16 irsprc;
+
+       irsprc = readw_relaxed(chip_data->mscm_ir_base + MSCM_IRSPRC(hwirq));
+       irsprc &= MSCM_IRSPRC_CPEN_MASK;
+
+       WARN_ON(irsprc & ~chip_data->cpu_mask);
+
+       writew_relaxed(chip_data->cpu_mask,
+                      chip_data->mscm_ir_base + MSCM_IRSPRC(hwirq));
+
+       irq_chip_unmask_parent(data);
+}
+
+static void vf610_mscm_ir_disable(struct irq_data *data)
+{
+       irq_hw_number_t hwirq = data->hwirq;
+       struct vf610_mscm_ir_chip_data *chip_data = data->chip_data;
+
+       writew_relaxed(0x0, chip_data->mscm_ir_base + MSCM_IRSPRC(hwirq));
+
+       irq_chip_mask_parent(data);
+}
+
+static struct irq_chip vf610_mscm_ir_irq_chip = {
+       .name                   = "mscm-ir",
+       .irq_mask               = irq_chip_mask_parent,
+       .irq_unmask             = irq_chip_unmask_parent,
+       .irq_eoi                = irq_chip_eoi_parent,
+       .irq_enable             = vf610_mscm_ir_enable,
+       .irq_disable            = vf610_mscm_ir_disable,
+       .irq_retrigger          = irq_chip_retrigger_hierarchy,
+       .irq_set_affinity       = irq_chip_set_affinity_parent,
+};
+
+static int vf610_mscm_ir_domain_alloc(struct irq_domain *domain, unsigned int virq,
+                                     unsigned int nr_irqs, void *arg)
+{
+       int i;
+       irq_hw_number_t hwirq;
+       struct of_phandle_args *irq_data = arg;
+       struct of_phandle_args gic_data;
+
+       if (irq_data->args_count != 2)
+               return -EINVAL;
+
+       hwirq = irq_data->args[0];
+       for (i = 0; i < nr_irqs; i++)
+               irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+                                             &vf610_mscm_ir_irq_chip,
+                                             domain->host_data);
+
+       gic_data.np = domain->parent->of_node;
+       gic_data.args_count = 3;
+       gic_data.args[0] = GIC_SPI;
+       gic_data.args[1] = irq_data->args[0];
+       gic_data.args[2] = irq_data->args[1];
+       return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
+}
+
+static const struct irq_domain_ops mscm_irq_domain_ops = {
+       .xlate = irq_domain_xlate_twocell,
+       .alloc = vf610_mscm_ir_domain_alloc,
+       .free = irq_domain_free_irqs_common,
+};
+
+static int __init vf610_mscm_ir_of_init(struct device_node *node,
+                              struct device_node *parent)
+{
+       struct irq_domain *domain, *domain_parent;
+       struct regmap *mscm_cp_regmap;
+       int ret, cpuid;
+
+       domain_parent = irq_find_host(parent);
+       if (!domain_parent) {
+               pr_err("vf610_mscm_ir: interrupt-parent not found\n");
+               return -EINVAL;
+       }
+
+       mscm_ir_data = kzalloc(sizeof(*mscm_ir_data), GFP_KERNEL);
+       if (!mscm_ir_data)
+               return -ENOMEM;
+
+       mscm_ir_data->mscm_ir_base = of_io_request_and_map(node, 0, "mscm-ir");
+
+       if (!mscm_ir_data->mscm_ir_base) {
+               pr_err("vf610_mscm_ir: unable to map mscm register\n");
+               ret = -ENOMEM;
+               goto out_free;
+       }
+
+       mscm_cp_regmap = syscon_regmap_lookup_by_phandle(node, "fsl,cpucfg");
+       if (IS_ERR(mscm_cp_regmap)) {
+               ret = PTR_ERR(mscm_cp_regmap);
+               pr_err("vf610_mscm_ir: regmap lookup for cpucfg failed\n");
+               goto out_unmap;
+       }
+
+       regmap_read(mscm_cp_regmap, MSCM_CPxNUM, &cpuid);
+       mscm_ir_data->cpu_mask = 0x1 << cpuid;
+
+       domain = irq_domain_add_hierarchy(domain_parent, 0,
+                                         MSCM_IRSPRC_NUM, node,
+                                         &mscm_irq_domain_ops, mscm_ir_data);
+       if (!domain) {
+               ret = -ENOMEM;
+               goto out_unmap;
+       }
+
+       cpu_pm_register_notifier(&mscm_ir_notifier_block);
+
+       return 0;
+
+out_unmap:
+       iounmap(mscm_ir_data->mscm_ir_base);
+out_free:
+       kfree(mscm_ir_data);
+       return ret;
+}
+IRQCHIP_DECLARE(vf610_mscm_ir, "fsl,vf610-mscm-ir", vf610_mscm_ir_of_init);
index c1493f4162fbca4b6c6343e19035758f13ddbc68..d5bdbaf93a1afe2d905a21ecad5cca09d637a731 100644 (file)
@@ -1092,7 +1092,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
        card->ci = get_card_info(ent->driver_data);
        if (!card->ci) {
-               pr_info("mISDN: do not have informations about adapter at %s\n",
+               pr_info("mISDN: do not have information about adapter at %s\n",
                        pci_name(pdev));
                kfree(card);
                pci_disable_device(pdev);
index 87f7dff20ff66b269537b166642690722fd4accc..52c43821f746e0223c1ad6047b73fa9492e711ef 100644 (file)
@@ -295,7 +295,7 @@ dsp_cmx_del_conf_member(struct dsp *dsp)
                }
        }
        printk(KERN_WARNING
-              "%s: dsp is not present in its own conf_meber list.\n",
+              "%s: dsp is not present in its own conf_member list.\n",
               __func__);
 
        return -EINVAL;
index 77025f5cb57df7edbee7b8d342bd1c67645665d6..0222b1a35a2dd3c1ba0d4b2199016134066fa5ca 100644 (file)
@@ -460,7 +460,7 @@ dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb)
                }
                if (dsp_debug & DEBUG_DSP_CORE)
                        printk(KERN_DEBUG "%s: enable mixing of "
-                              "tx-data with conf mebers\n", __func__);
+                              "tx-data with conf members\n", __func__);
                dsp->tx_mix = 1;
                dsp_cmx_hardware(dsp->conf, dsp);
                dsp_rx_off(dsp);
@@ -474,7 +474,7 @@ dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb)
                }
                if (dsp_debug & DEBUG_DSP_CORE)
                        printk(KERN_DEBUG "%s: disable mixing of "
-                              "tx-data with conf mebers\n", __func__);
+                              "tx-data with conf members\n", __func__);
                dsp->tx_mix = 0;
                dsp_cmx_hardware(dsp->conf, dsp);
                dsp_rx_off(dsp);
index 717daad71fb101b2b97efd03b1bb41d8b35ecfe7..e6178787ce3dd4a9b0e33b80b72ac39f73e25e33 100644 (file)
@@ -249,6 +249,7 @@ static void md_make_request(struct request_queue *q, struct bio *bio)
        const int rw = bio_data_dir(bio);
        struct mddev *mddev = q->queuedata;
        unsigned int sectors;
+       int cpu;
 
        if (mddev == NULL || mddev->pers == NULL
            || !mddev->ready) {
@@ -284,7 +285,10 @@ static void md_make_request(struct request_queue *q, struct bio *bio)
        sectors = bio_sectors(bio);
        mddev->pers->make_request(mddev, bio);
 
-       generic_start_io_acct(rw, sectors, &mddev->gendisk->part0);
+       cpu = part_stat_lock();
+       part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
+       part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], sectors);
+       part_stat_unlock();
 
        if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)
                wake_up(&mddev->sb_wait);
index 3ed9f42ddca65e10351a1a453f16383e63c52634..3b5d7f704aa346ad27b4806c9e36ee9ba984edc7 100644 (file)
@@ -313,7 +313,7 @@ static struct strip_zone *find_zone(struct r0conf *conf,
 
 /*
  * remaps the bio to the target device. we separate two flows.
- * power 2 flow and a general flow for the sake of perfromance
+ * power 2 flow and a general flow for the sake of performance
 */
 static struct md_rdev *map_sector(struct mddev *mddev, struct strip_zone *zone,
                                sector_t sector, sector_t *sector_offset)
@@ -524,6 +524,7 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
                        split = bio;
                }
 
+               sector = bio->bi_iter.bi_sector;
                zone = find_zone(mddev->private, &sector);
                tmp_dev = map_sector(mddev, zone, sector, &sector);
                split->bi_bdev = tmp_dev->bdev;
index ba4ee0b488344079d8e690724778661f131bd2b6..d3d928e1c0cece10d413fc60503ae3b6ea5feced 100644 (file)
@@ -630,7 +630,7 @@ static int m88ds3103_init(struct dvb_frontend *fe)
        /* request the firmware, this will block and timeout */
        ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent);
        if (ret) {
-               dev_err(&priv->i2c->dev, "%s: firmare file '%s' not found\n",
+               dev_err(&priv->i2c->dev, "%s: firmware file '%s' not found\n",
                                KBUILD_MODNAME, fw_file);
                goto err;
        }
index 5d2d8f45b4b62a1005e261383b7c858d3c5e539e..67faa8d6950efb1e4f8b24c0aad0e99027473b43 100644 (file)
@@ -1240,7 +1240,7 @@ static int rtl2832_probe(struct i2c_client *client,
        dev->regmap_config.max_register = 5 * 0x100,
        dev->regmap_config.ranges = regmap_range_cfg,
        dev->regmap_config.num_ranges = ARRAY_SIZE(regmap_range_cfg),
-       dev->regmap_config.cache_type = REGCACHE_RBTREE,
+       dev->regmap_config.cache_type = REGCACHE_NONE,
        dev->regmap = regmap_init(&client->dev, &regmap_bus, client,
                                  &dev->regmap_config);
        if (IS_ERR(dev->regmap)) {
index aadd1367673fed96140a8abd9955bb4d6c6dad55..d7efce8043edb421f32d1b5e11f62f4fc5db44e6 100644 (file)
@@ -40,7 +40,7 @@ struct si2168_dev {
        bool ts_clock_inv;
 };
 
-/* firmare command struct */
+/* firmware command struct */
 #define SI2168_ARGLEN      30
 struct si2168_cmd {
        u8 args[SI2168_ARGLEN];
index 42048619273682089808eb1bffd1690704f7d13a..03f839c431e934c14a3d738f86f0f9a3352de009 100644 (file)
@@ -99,7 +99,7 @@ struct tda10071_reg_val_mask {
 #define CMD_BER_CONTROL         0x3e
 #define CMD_BER_UPDATE_COUNTERS 0x3f
 
-/* firmare command struct */
+/* firmware command struct */
 #define TDA10071_ARGLEN      30
 struct tda10071_cmd {
        u8 args[TDA10071_ARGLEN];
index e4901a503c7366dc10a8ded1c61e84683f62124e..63c0ee5d0bf5eca7511df486fe300b3a468301b5 100644 (file)
@@ -1339,14 +1339,13 @@ static int vidioc_querycap(struct file *file, void  *priv,
        strlcpy(cap->driver, dev->name, sizeof(cap->driver));
        strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
                sizeof(cap->card));
-       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-       cap->capabilities =
-               V4L2_CAP_VIDEO_CAPTURE |
-               V4L2_CAP_READWRITE     |
-               V4L2_CAP_STREAMING     |
-               0;
+       sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+                          V4L2_CAP_STREAMING;
        if (dev->tuner_type != TUNER_ABSENT)
-               cap->capabilities |= V4L2_CAP_TUNER;
+               cap->device_caps |= V4L2_CAP_TUNER;
+       cap->capabilities = cap->device_caps | V4L2_CAP_VBI_CAPTURE |
+               V4L2_CAP_AUDIO | V4L2_CAP_DEVICE_CAPS;
 
        return 0;
 }
index 12f7452edce3708a989eb0e7f71a94def8a31665..a92ff4249d100d33e84acaf50b372eb5e2a190b0 100644 (file)
@@ -1845,6 +1845,9 @@ static void exynos4_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
        struct s5p_jpeg_addr jpeg_addr;
        u32 pix_size, padding_bytes = 0;
 
+       jpeg_addr.cb = 0;
+       jpeg_addr.cr = 0;
+
        pix_size = ctx->cap_q.w * ctx->cap_q.h;
 
        if (ctx->mode == S5P_JPEG_ENCODE) {
index e8c2cad9396272ed9fa6f43c0fbab2699ba0073e..0974b9a7a584fb85f6aa268257264f995b5baef3 100644 (file)
@@ -20,7 +20,7 @@
 
 void exynos3250_jpeg_reset(void __iomem *regs)
 {
-       u32 reg = 0;
+       u32 reg = 1;
        int count = 1000;
 
        writel(1, regs + EXYNOS3250_SW_RESET);
index 8e44a59d8ec20f17bcfd601fd4a8c7abdaf8a530..98374e8bad3e99ffdf5a70d26b923e6e0c265bf3 100644 (file)
@@ -833,6 +833,7 @@ static int s5p_mfc_open(struct file *file)
        q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
        q->io_modes = VB2_MMAP;
        q->drv_priv = &ctx->fh;
+       q->lock = &dev->mfc_mutex;
        if (vdev == dev->vfd_dec) {
                q->io_modes = VB2_MMAP;
                q->ops = get_dec_queue_ops();
index 15f7663dd9f5c193ba28968b2da5326f2bf19ea4..24262bbb1a3568fe87875bedfcd4d52f42867e4e 100644 (file)
@@ -29,7 +29,7 @@
 
 /* Offset base used to differentiate between CAPTURE and OUTPUT
 *  while mmaping */
-#define DST_QUEUE_OFF_BASE      (TASK_SIZE / 2)
+#define DST_QUEUE_OFF_BASE     (1 << 30)
 
 #define MFC_BANK1_ALLOC_CTX    0
 #define MFC_BANK2_ALLOC_CTX    1
index de2b8c69daa535dd6ea906dcd476638e3185c72f..22dfb3effda8912ded31f8afabe089857b55ac78 100644 (file)
@@ -302,7 +302,7 @@ struct s5p_mfc_hw_ops {
        void (*write_info)(struct s5p_mfc_ctx *ctx, unsigned int data,
                        unsigned int ofs);
        unsigned int (*read_info)(struct s5p_mfc_ctx *ctx,
-                       unsigned int ofs);
+                       unsigned long ofs);
        int (*get_dspl_y_adr)(struct s5p_mfc_dev *dev);
        int (*get_dec_y_adr)(struct s5p_mfc_dev *dev);
        int (*get_dspl_status)(struct s5p_mfc_dev *dev);
index 0c4fcf2dfd09c68cd41e12481b44944a585a52fc..b09bcd14049133cb63c1d35150b5a465b75e694d 100644 (file)
@@ -263,15 +263,15 @@ static void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
 static void s5p_mfc_write_info_v5(struct s5p_mfc_ctx *ctx, unsigned int data,
                        unsigned int ofs)
 {
-       writel(data, (volatile void __iomem *)(ctx->shm.virt + ofs));
+       writel(data, (void *)(ctx->shm.virt + ofs));
        wmb();
 }
 
 static unsigned int s5p_mfc_read_info_v5(struct s5p_mfc_ctx *ctx,
-                               unsigned int ofs)
+                               unsigned long ofs)
 {
        rmb();
-       return readl((volatile void __iomem *)(ctx->shm.virt + ofs));
+       return readl((void *)(ctx->shm.virt + ofs));
 }
 
 static void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
index d826c58b5d538bfcc24fc3dc0f6539d3bbd5320e..cefad184fe969296db59858103f4c6e713c6acd3 100644 (file)
@@ -1852,17 +1852,17 @@ static void s5p_mfc_write_info_v6(struct s5p_mfc_ctx *ctx, unsigned int data,
                unsigned int ofs)
 {
        s5p_mfc_clock_on();
-       writel(data, (volatile void __iomem *)((unsigned long)ofs));
+       writel(data, (void *)((unsigned long)ofs));
        s5p_mfc_clock_off();
 }
 
 static unsigned int
-s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned int ofs)
+s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned long ofs)
 {
        int ret;
 
        s5p_mfc_clock_on();
-       ret = readl((volatile void __iomem *)((unsigned long)ofs));
+       ret = readl((void *)ofs);
        s5p_mfc_clock_off();
 
        return ret;
index 5a1835dd65e858e5622f5b01fbe5fe4f4b63e5bf..697aaed42486fb71fe3195be01e2c0b61ee2bb14 100644 (file)
@@ -20,6 +20,7 @@ if VIDEO_SAMSUNG_S5P_TV
 config VIDEO_SAMSUNG_S5P_HDMI
        tristate "Samsung HDMI Driver"
        depends on VIDEO_V4L2
+       depends on I2C
        depends on VIDEO_SAMSUNG_S5P_TV
        select VIDEO_SAMSUNG_S5P_HDMIPHY
        help
index a901b62485576489d4ed4867a131d7a6b7d69386..2554f3719b9e365584fb9b105c1ffd7d65bcd1b9 100644 (file)
@@ -1158,6 +1158,7 @@ static int sh_veu_probe(struct platform_device *pdev)
        }
 
        *vdev = sh_veu_videodev;
+       vdev->v4l2_dev = &veu->v4l2_dev;
        spin_lock_init(&veu->lock);
        mutex_init(&veu->fop_lock);
        vdev->lock = &veu->fop_lock;
index 8526bf5c8429aecbb5afa8030fca537b0720b2ab..c835beb2a1a8f30e14f48a34566b842dbdce96cf 100644 (file)
@@ -843,6 +843,8 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd)
        if (isi->pdata.full_mode)
                cfg1 |= ISI_CFG1_FULL_MODE;
 
+       cfg1 |= ISI_CFG1_THMASK_BEATS_16;
+
        isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
        isi_writel(isi, ISI_CFG1, cfg1);
 
index cee7b56f840499440142bc598fbd588bd8469f67..66634b469c9899f043f79a69c4c232599ec8ee0f 100644 (file)
@@ -1665,7 +1665,7 @@ eclkreg:
 eaddpdev:
        platform_device_put(sasc->pdev);
 eallocpdev:
-       devm_kfree(ici->v4l2_dev.dev, sasc);
+       devm_kfree(ici->v4l2_dev.dev, info);
        dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret);
 
        return ret;
index 26019e73199314b779e788bfd6a57905c9c68457..74cfc3c98edbd3806d798c412ba8ac5df62a67d0 100644 (file)
@@ -408,7 +408,7 @@ static int msi001_s_ctrl(struct v4l2_ctrl *ctrl)
                                s->mixer_gain->cur.val, s->if_gain->val);
                break;
        default:
-               dev_dbg(&s->spi->dev, "unkown control %d\n", ctrl->id);
+               dev_dbg(&s->spi->dev, "unknown control %d\n", ctrl->id);
                ret = -EINVAL;
        }
 
index 77dcfdf547ac8f62e4cc2ea5a8fa086478e545b5..87fc0fe29ebd30e91ee58488cf6398df111ece63 100644 (file)
@@ -780,8 +780,6 @@ static int rtl2832u_frontend_callback(void *adapter_priv, int component,
                case TUNER_RTL2832_TUA9001:
                        return rtl2832u_tua9001_tuner_callback(d, cmd, arg);
                }
-       default:
-               return -EINVAL;
        }
 
        return 0;
index 60af3b167f3b73e02071074a8e01ce39499c8d98..3fd94fe7e1eb1652b7dfc5df4d5983f3733eb65b 100644 (file)
@@ -1,6 +1,7 @@
 menuconfig USB_GSPCA
        tristate "GSPCA based webcams"
        depends on VIDEO_V4L2
+       depends on INPUT || INPUT=n
        default m
        ---help---
          Say Y here if you want to enable selecting webcams based
index bc08a829bc132068c0b51661f9459293ef30c142..cc16e76a24933c41a9cc81ddb5b2beb0193fcbe2 100644 (file)
@@ -3230,18 +3230,13 @@ int vb2_thread_stop(struct vb2_queue *q)
 
        if (threadio == NULL)
                return 0;
-       call_void_qop(q, wait_finish, q);
        threadio->stop = true;
-       vb2_internal_streamoff(q, q->type);
-       call_void_qop(q, wait_prepare, q);
+       /* Wake up all pending sleeps in the thread */
+       vb2_queue_error(q);
        err = kthread_stop(threadio->thread);
-       q->fileio = NULL;
-       fileio->req.count = 0;
-       vb2_reqbufs(q, &fileio->req);
-       kfree(fileio);
+       __vb2_cleanup_fileio(q);
        threadio->thread = NULL;
        kfree(threadio);
-       q->fileio = NULL;
        q->threadio = NULL;
        return err;
 }
index b481d20c83727aa46e30119380f02be200a41479..69e0483adfee02e569f89ece65a31f73c0a96f35 100644 (file)
@@ -632,8 +632,7 @@ static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
        }
 
        /* extract page list from userspace mapping */
-       ret = vb2_dc_get_user_pages(start, pages, n_pages, vma,
-                                   dma_dir == DMA_FROM_DEVICE);
+       ret = vb2_dc_get_user_pages(start, pages, n_pages, vma, dma_dir);
        if (ret) {
                unsigned long pfn;
                if (vb2_dc_get_user_pfn(start, n_pages, vma, &pfn) == 0) {
index 476e637457426883853416f49771b88d76046c50..d5ad04dad081df4e78418a6bb19c9ab6997d2e3f 100644 (file)
@@ -283,6 +283,18 @@ config HTC_I2CPLD
          This device provides input and output GPIOs through an I2C
          interface to one or more sub-chips.
 
+config MFD_INTEL_QUARK_I2C_GPIO
+       tristate "Intel Quark MFD I2C GPIO"
+       depends on PCI
+       depends on X86
+       depends on COMMON_CLK
+       select MFD_CORE
+       help
+         This MFD provides support for I2C and GPIO that exist only
+         in a single PCI device. It splits the 2 IO devices to
+         their respective IO driver.
+         The GPIO exports a total amount of 8 interrupt-capable GPIOs.
+
 config LPC_ICH
        tristate "Intel ICH LPC"
        depends on PCI
@@ -364,6 +376,7 @@ config MFD_KEMPLD
                * COMe-bIP#
                * COMe-bPC2 (ETXexpress-PC)
                * COMe-bSC# (ETXexpress-SC T#)
+               * COMe-cBL6
                * COMe-cBT6
                * COMe-cCT6
                * COMe-cDC2 (microETXexpress-DC)
@@ -455,6 +468,20 @@ config MFD_MAX77693
          additional drivers must be enabled in order to use the functionality
          of the device.
 
+config MFD_MAX77843
+       bool "Maxim Semiconductor MAX77843 PMIC Support"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       help
+         Say yes here to add support for Maxim Semiconductor MAX77843.
+         This is companion Power Management IC with LEDs, Haptic, Charger,
+         Fuel Gauge, MUIC(Micro USB Interface Controller) controls on chip.
+         This driver provides common support for accessing the device;
+         additional drivers must be enabled in order to use the functionality
+         of the device.
+
 config MFD_MAX8907
        tristate "Maxim Semiconductor MAX8907 PMIC Support"
        select MFD_CORE
@@ -502,6 +529,16 @@ config MFD_MAX8998
          additional drivers must be enabled in order to use the functionality
          of the device.
 
+config MFD_MT6397
+       tristate "MediaTek MT6397 PMIC Support"
+       select MFD_CORE
+       select IRQ_DOMAIN
+       help
+         Say yes here to add support for MediaTek MT6397 PMIC. This is
+         a Power Management IC. This driver provides common support for
+         accessing the device; additional drivers must be enabled in order
+         to use the functionality of the device.
+
 config MFD_MENF21BMC
        tristate "MEN 14F021P00 Board Management Controller Support"
        depends on I2C
@@ -655,6 +692,7 @@ config MFD_RT5033
        depends on I2C=y
        select MFD_CORE
        select REGMAP_I2C
+       select REGMAP_IRQ
        help
          This driver provides for the Richtek RT5033 Power Management IC,
          which includes the I2C driver and the Core APIs. This driver provides
@@ -753,6 +791,18 @@ config MFD_SM501_GPIO
         lines on the SM501. The platform data is used to supply the
         base number for the first GPIO line to register.
 
+config MFD_SKY81452
+       tristate "Skyworks Solutions SKY81452"
+       select MFD_CORE
+       select REGMAP_I2C
+       depends on I2C
+       help
+         This is the core driver for the Skyworks SKY81452 backlight and
+         voltage regulator device.
+
+         This driver can also be built as a module.  If so, the module
+         will be called sky81452.
+
 config MFD_SMSC
        bool "SMSC ECE1099 series chips"
        depends on I2C=y
@@ -1290,10 +1340,11 @@ config MFD_WM5102
          Support for Wolfson Microelectronics WM5102 low power audio SoC
 
 config MFD_WM5110
-       bool "Wolfson Microelectronics WM5110"
+       bool "Wolfson Microelectronics WM5110 and WM8280/WM8281"
        depends on MFD_ARIZONA
        help
-         Support for Wolfson Microelectronics WM5110 low power audio SoC
+         Support for Wolfson Microelectronics WM5110 and WM8280/WM8281
+         low power audio SoC
 
 config MFD_WM8997
        bool "Wolfson Microelectronics WM8997"
@@ -1363,7 +1414,7 @@ config MFD_WM8994
        depends on I2C
        help
          The WM8994 is a highly integrated hi-fi CODEC designed for
-         smartphone applicatiosn.  As well as audio functionality it
+         smartphone applications.  As well as audio functionality it
          has on board GPIO and regulator functionality which is
          supported via the relevant subsystems.  This driver provides
          core support for the WM8994, in order to use the actual
index 19f3d744e3bdad95f69337faf7c7c1ffc3058d67..0e5cfeba107ca4cc25d8169bd4afe76da4bc4162 100644 (file)
@@ -13,7 +13,7 @@ obj-$(CONFIG_MFD_CROS_EC)     += cros_ec.o
 obj-$(CONFIG_MFD_CROS_EC_I2C)  += cros_ec_i2c.o
 obj-$(CONFIG_MFD_CROS_EC_SPI)  += cros_ec_spi.o
 
-rtsx_pci-objs                  := rtsx_pcr.o rtsx_gops.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
+rtsx_pci-objs                  := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
 obj-$(CONFIG_MFD_RTSX_PCI)     += rtsx_pci.o
 obj-$(CONFIG_MFD_RTSX_USB)     += rtsx_usb.o
 
@@ -117,6 +117,7 @@ obj-$(CONFIG_MFD_DA9150)    += da9150-core.o
 obj-$(CONFIG_MFD_MAX14577)     += max14577.o
 obj-$(CONFIG_MFD_MAX77686)     += max77686.o
 obj-$(CONFIG_MFD_MAX77693)     += max77693.o
+obj-$(CONFIG_MFD_MAX77843)     += max77843.o
 obj-$(CONFIG_MFD_MAX8907)      += max8907.o
 max8925-objs                   := max8925-core.o max8925-i2c.o
 obj-$(CONFIG_MFD_MAX8925)      += max8925.o
@@ -138,6 +139,7 @@ obj-$(CONFIG_AB8500_CORE)   += ab8500-core.o ab8500-sysctrl.o
 obj-$(CONFIG_MFD_TIMBERDALE)    += timberdale.o
 obj-$(CONFIG_PMIC_ADP5520)     += adp5520.o
 obj-$(CONFIG_MFD_KEMPLD)       += kempld-core.o
+obj-$(CONFIG_MFD_INTEL_QUARK_I2C_GPIO) += intel_quark_i2c_gpio.o
 obj-$(CONFIG_LPC_SCH)          += lpc_sch.o
 obj-$(CONFIG_LPC_ICH)          += lpc_ich.o
 obj-$(CONFIG_MFD_RDC321X)      += rdc321x-southbridge.o
@@ -178,6 +180,8 @@ obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o
 obj-$(CONFIG_MFD_HI6421_PMIC)  += hi6421-pmic-core.o
 obj-$(CONFIG_MFD_DLN2)         += dln2.o
 obj-$(CONFIG_MFD_RT5033)       += rt5033.o
+obj-$(CONFIG_MFD_SKY81452)     += sky81452.o
 
 intel-soc-pmic-objs            := intel_soc_pmic_core.o intel_soc_pmic_crc.o
 obj-$(CONFIG_INTEL_SOC_PMIC)   += intel-soc-pmic.o
+obj-$(CONFIG_MFD_MT6397)       += mt6397-core.o
index 9a8e185f11dfaf5fe8ba87432a24e8f704484b40..cdd6f3d63314c90d8ccbf1467ff7e58eff024e1c 100644 (file)
@@ -1283,7 +1283,7 @@ static irqreturn_t ab8500_debug_handler(int irq, void *data)
 
 /* Prints to seq_file or log_buf */
 static int ab8500_registers_print(struct device *dev, u32 bank,
-                               struct seq_file *s)
+                                 struct seq_file *s)
 {
        unsigned int i;
 
@@ -1304,20 +1304,19 @@ static int ab8500_registers_print(struct device *dev, u32 bank,
                        }
 
                        if (s) {
-                               err = seq_printf(s,
-                                                "  [0x%02X/0x%02X]: 0x%02X\n",
-                                                bank, reg, value);
-                               if (err < 0) {
-                                       /* Error is not returned here since
-                                        * the output is wanted in any case */
+                               seq_printf(s, "  [0x%02X/0x%02X]: 0x%02X\n",
+                                          bank, reg, value);
+                               /* Error is not returned here since
+                                * the output is wanted in any case */
+                               if (seq_has_overflowed(s))
                                        return 0;
-                               }
                        } else {
                                dev_info(dev, " [0x%02X/0x%02X]: 0x%02X\n",
                                         bank, reg, value);
                        }
                }
        }
+
        return 0;
 }
 
@@ -1330,8 +1329,7 @@ static int ab8500_print_bank_registers(struct seq_file *s, void *p)
 
        seq_printf(s, " bank 0x%02X:\n", bank);
 
-       ab8500_registers_print(dev, bank, s);
-       return 0;
+       return ab8500_registers_print(dev, bank, s);
 }
 
 static int ab8500_registers_open(struct inode *inode, struct file *file)
@@ -1355,9 +1353,12 @@ static int ab8500_print_all_banks(struct seq_file *s, void *p)
        seq_puts(s, AB8500_NAME_STRING " register values:\n");
 
        for (i = 0; i < AB8500_NUM_BANKS; i++) {
-               seq_printf(s, " bank 0x%02X:\n", i);
+               int err;
 
-               ab8500_registers_print(dev, i, s);
+               seq_printf(s, " bank 0x%02X:\n", i);
+               err = ab8500_registers_print(dev, i, s);
+               if (err)
+                       return err;
        }
        return 0;
 }
@@ -1458,7 +1459,8 @@ static const struct file_operations ab8500_all_banks_fops = {
 
 static int ab8500_bank_print(struct seq_file *s, void *p)
 {
-       return seq_printf(s, "0x%02X\n", debug_bank);
+       seq_printf(s, "0x%02X\n", debug_bank);
+       return 0;
 }
 
 static int ab8500_bank_open(struct inode *inode, struct file *file)
@@ -1490,7 +1492,8 @@ static ssize_t ab8500_bank_write(struct file *file,
 
 static int ab8500_address_print(struct seq_file *s, void *p)
 {
-       return seq_printf(s, "0x%02X\n", debug_address);
+       seq_printf(s, "0x%02X\n", debug_address);
+       return 0;
 }
 
 static int ab8500_address_open(struct inode *inode, struct file *file)
@@ -1598,7 +1601,8 @@ static int ab8500_interrupts_print(struct seq_file *s, void *p)
        for (line = 0; line < num_interrupt_lines; line++) {
                struct irq_desc *desc = irq_to_desc(line + irq_first);
 
-               seq_printf(s, "%3i:  %6i %4i", line,
+               seq_printf(s, "%3i:  %6i %4i",
+                          line,
                           num_interrupts[line],
                           num_wake_interrupts[line]);
 
@@ -1705,8 +1709,7 @@ static int ab8500_print_modem_registers(struct seq_file *s, void *p)
                        dev_err(dev, "ab->read fail %d\n", err);
                        return err;
                }
-               err = seq_printf(s, "  [0x%02X/0x%02X]: 0x%02X\n",
-                       bank, reg, value);
+               seq_printf(s, "  [0x%02X/0x%02X]: 0x%02X\n", bank, reg, value);
        }
        err = abx500_set_register_interruptible(dev,
                AB8500_REGU_CTRL1, AB8500_SUPPLY_CONTROL_REG, orig_value);
@@ -1743,8 +1746,9 @@ static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p)
        bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc,
                BAT_CTRL, bat_ctrl_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-               bat_ctrl_convert, bat_ctrl_raw);
+       seq_printf(s, "%d,0x%X\n", bat_ctrl_convert, bat_ctrl_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file)
@@ -1773,8 +1777,9 @@ static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p)
        btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL,
                btemp_ball_raw);
 
-       return seq_printf(s,
-               "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw);
+       seq_printf(s, "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_btemp_ball_open(struct inode *inode,
@@ -1804,8 +1809,9 @@ static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p)
        main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
                MAIN_CHARGER_V, main_charger_v_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-                       main_charger_v_convert, main_charger_v_raw);
+       seq_printf(s, "%d,0x%X\n", main_charger_v_convert, main_charger_v_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_main_charger_v_open(struct inode *inode,
@@ -1835,8 +1841,9 @@ static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p)
        acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1,
                acc_detect1_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-               acc_detect1_convert, acc_detect1_raw);
+       seq_printf(s, "%d,0x%X\n", acc_detect1_convert, acc_detect1_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_acc_detect1_open(struct inode *inode,
@@ -1866,8 +1873,9 @@ static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p)
        acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc,
                ACC_DETECT2, acc_detect2_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-               acc_detect2_convert, acc_detect2_raw);
+       seq_printf(s, "%d,0x%X\n", acc_detect2_convert, acc_detect2_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_acc_detect2_open(struct inode *inode,
@@ -1897,8 +1905,9 @@ static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p)
        aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1,
                aux1_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-               aux1_convert, aux1_raw);
+       seq_printf(s, "%d,0x%X\n", aux1_convert, aux1_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_aux1_open(struct inode *inode, struct file *file)
@@ -1926,8 +1935,9 @@ static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p)
        aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2,
                aux2_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-                       aux2_convert, aux2_raw);
+       seq_printf(s, "%d,0x%X\n", aux2_convert, aux2_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_aux2_open(struct inode *inode, struct file *file)
@@ -1955,8 +1965,9 @@ static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p)
        main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V,
                main_bat_v_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-               main_bat_v_convert, main_bat_v_raw);
+       seq_printf(s, "%d,0x%X\n", main_bat_v_convert, main_bat_v_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_main_bat_v_open(struct inode *inode,
@@ -1986,8 +1997,9 @@ static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p)
        vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V,
                vbus_v_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-               vbus_v_convert, vbus_v_raw);
+       seq_printf(s, "%d,0x%X\n", vbus_v_convert, vbus_v_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_vbus_v_open(struct inode *inode, struct file *file)
@@ -2015,8 +2027,9 @@ static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p)
        main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
                MAIN_CHARGER_C, main_charger_c_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-               main_charger_c_convert, main_charger_c_raw);
+       seq_printf(s, "%d,0x%X\n", main_charger_c_convert, main_charger_c_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_main_charger_c_open(struct inode *inode,
@@ -2046,8 +2059,9 @@ static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p)
        usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
                USB_CHARGER_C, usb_charger_c_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-               usb_charger_c_convert, usb_charger_c_raw);
+       seq_printf(s, "%d,0x%X\n", usb_charger_c_convert, usb_charger_c_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_usb_charger_c_open(struct inode *inode,
@@ -2077,8 +2091,9 @@ static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p)
        bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
                BK_BAT_V, bk_bat_v_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-               bk_bat_v_convert, bk_bat_v_raw);
+       seq_printf(s, "%d,0x%X\n", bk_bat_v_convert, bk_bat_v_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file)
@@ -2107,8 +2122,9 @@ static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p)
        die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP,
                die_temp_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-               die_temp_convert, die_temp_raw);
+       seq_printf(s, "%d,0x%X\n", die_temp_convert, die_temp_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file)
@@ -2137,8 +2153,9 @@ static int ab8500_gpadc_usb_id_print(struct seq_file *s, void *p)
        usb_id_convert = ab8500_gpadc_ad_to_voltage(gpadc, USB_ID,
                usb_id_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-               usb_id_convert, usb_id_raw);
+       seq_printf(s, "%d,0x%X\n", usb_id_convert, usb_id_raw);
+
+       return 0;
 }
 
 static int ab8500_gpadc_usb_id_open(struct inode *inode, struct file *file)
@@ -2166,8 +2183,9 @@ static int ab8540_gpadc_xtal_temp_print(struct seq_file *s, void *p)
        xtal_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, XTAL_TEMP,
                xtal_temp_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-               xtal_temp_convert, xtal_temp_raw);
+       seq_printf(s, "%d,0x%X\n", xtal_temp_convert, xtal_temp_raw);
+
+       return 0;
 }
 
 static int ab8540_gpadc_xtal_temp_open(struct inode *inode, struct file *file)
@@ -2197,8 +2215,9 @@ static int ab8540_gpadc_vbat_true_meas_print(struct seq_file *s, void *p)
                ab8500_gpadc_ad_to_voltage(gpadc, VBAT_TRUE_MEAS,
                                           vbat_true_meas_raw);
 
-       return seq_printf(s, "%d,0x%X\n",
-               vbat_true_meas_convert, vbat_true_meas_raw);
+       seq_printf(s, "%d,0x%X\n", vbat_true_meas_convert, vbat_true_meas_raw);
+
+       return 0;
 }
 
 static int ab8540_gpadc_vbat_true_meas_open(struct inode *inode,
@@ -2233,9 +2252,13 @@ static int ab8540_gpadc_bat_ctrl_and_ibat_print(struct seq_file *s, void *p)
        ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
                ibat_raw);
 
-       return seq_printf(s, "%d,0x%X\n"  "%d,0x%X\n",
-               bat_ctrl_convert, bat_ctrl_raw,
-               ibat_convert, ibat_raw);
+       seq_printf(s,
+                  "%d,0x%X\n"
+                  "%d,0x%X\n",
+                  bat_ctrl_convert, bat_ctrl_raw,
+                  ibat_convert, ibat_raw);
+
+       return 0;
 }
 
 static int ab8540_gpadc_bat_ctrl_and_ibat_open(struct inode *inode,
@@ -2269,9 +2292,13 @@ static int ab8540_gpadc_vbat_meas_and_ibat_print(struct seq_file *s, void *p)
        ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
                ibat_raw);
 
-       return seq_printf(s, "%d,0x%X\n"  "%d,0x%X\n",
-               vbat_meas_convert, vbat_meas_raw,
-               ibat_convert, ibat_raw);
+       seq_printf(s,
+                  "%d,0x%X\n"
+                  "%d,0x%X\n",
+                  vbat_meas_convert, vbat_meas_raw,
+                  ibat_convert, ibat_raw);
+
+       return 0;
 }
 
 static int ab8540_gpadc_vbat_meas_and_ibat_open(struct inode *inode,
@@ -2307,9 +2334,13 @@ static int ab8540_gpadc_vbat_true_meas_and_ibat_print(struct seq_file *s,
        ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
                ibat_raw);
 
-       return seq_printf(s, "%d,0x%X\n"  "%d,0x%X\n",
-               vbat_true_meas_convert, vbat_true_meas_raw,
-               ibat_convert, ibat_raw);
+       seq_printf(s,
+                  "%d,0x%X\n"
+                  "%d,0x%X\n",
+                  vbat_true_meas_convert, vbat_true_meas_raw,
+                  ibat_convert, ibat_raw);
+
+       return 0;
 }
 
 static int ab8540_gpadc_vbat_true_meas_and_ibat_open(struct inode *inode,
@@ -2344,9 +2375,13 @@ static int ab8540_gpadc_bat_temp_and_ibat_print(struct seq_file *s, void *p)
        ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
                ibat_raw);
 
-       return seq_printf(s, "%d,0x%X\n"  "%d,0x%X\n",
-               bat_temp_convert, bat_temp_raw,
-               ibat_convert, ibat_raw);
+       seq_printf(s,
+                  "%d,0x%X\n"
+                  "%d,0x%X\n",
+                  bat_temp_convert, bat_temp_raw,
+                  ibat_convert, ibat_raw);
+
+       return 0;
 }
 
 static int ab8540_gpadc_bat_temp_and_ibat_open(struct inode *inode,
@@ -2373,16 +2408,19 @@ static int ab8540_gpadc_otp_cal_print(struct seq_file *s, void *p)
        gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
        ab8540_gpadc_get_otp(gpadc, &vmain_l, &vmain_h, &btemp_l, &btemp_h,
                        &vbat_l, &vbat_h, &ibat_l, &ibat_h);
-       return seq_printf(s, "VMAIN_L:0x%X\n"
-                         "VMAIN_H:0x%X\n"
-                         "BTEMP_L:0x%X\n"
-                         "BTEMP_H:0x%X\n"
-                         "VBAT_L:0x%X\n"
-                         "VBAT_H:0x%X\n"
-                         "IBAT_L:0x%X\n"
-                         "IBAT_H:0x%X\n",
-                         vmain_l, vmain_h, btemp_l, btemp_h,
-                         vbat_l, vbat_h, ibat_l, ibat_h);
+       seq_printf(s,
+                  "VMAIN_L:0x%X\n"
+                  "VMAIN_H:0x%X\n"
+                  "BTEMP_L:0x%X\n"
+                  "BTEMP_H:0x%X\n"
+                  "VBAT_L:0x%X\n"
+                  "VBAT_H:0x%X\n"
+                  "IBAT_L:0x%X\n"
+                  "IBAT_H:0x%X\n",
+                  vmain_l, vmain_h, btemp_l, btemp_h,
+                  vbat_l, vbat_h, ibat_l, ibat_h);
+
+       return 0;
 }
 
 static int ab8540_gpadc_otp_cal_open(struct inode *inode, struct file *file)
@@ -2400,7 +2438,9 @@ static const struct file_operations ab8540_gpadc_otp_calib_fops = {
 
 static int ab8500_gpadc_avg_sample_print(struct seq_file *s, void *p)
 {
-       return seq_printf(s, "%d\n", avg_sample);
+       seq_printf(s, "%d\n", avg_sample);
+
+       return 0;
 }
 
 static int ab8500_gpadc_avg_sample_open(struct inode *inode, struct file *file)
@@ -2445,7 +2485,9 @@ static const struct file_operations ab8500_gpadc_avg_sample_fops = {
 
 static int ab8500_gpadc_trig_edge_print(struct seq_file *s, void *p)
 {
-       return seq_printf(s, "%d\n", trig_edge);
+       seq_printf(s, "%d\n", trig_edge);
+
+       return 0;
 }
 
 static int ab8500_gpadc_trig_edge_open(struct inode *inode, struct file *file)
@@ -2490,7 +2532,9 @@ static const struct file_operations ab8500_gpadc_trig_edge_fops = {
 
 static int ab8500_gpadc_trig_timer_print(struct seq_file *s, void *p)
 {
-       return seq_printf(s, "%d\n", trig_timer);
+       seq_printf(s, "%d\n", trig_timer);
+
+       return 0;
 }
 
 static int ab8500_gpadc_trig_timer_open(struct inode *inode, struct file *file)
@@ -2533,7 +2577,9 @@ static const struct file_operations ab8500_gpadc_trig_timer_fops = {
 
 static int ab8500_gpadc_conv_type_print(struct seq_file *s, void *p)
 {
-       return seq_printf(s, "%d\n", conv_type);
+       seq_printf(s, "%d\n", conv_type);
+
+       return 0;
 }
 
 static int ab8500_gpadc_conv_type_open(struct inode *inode, struct file *file)
index cfff0b643f1b7352d439f5a1310d3829afd7341e..0d1825696153127862c7f369285bec72476702e6 100644 (file)
@@ -49,7 +49,9 @@ static void ab8500_power_off(void)
                if (!psy)
                        continue;
 
-               ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val);
+               ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE,
+                               &val);
+               power_supply_put(psy);
 
                if (!ret && val.intval) {
                        charger_present = true;
@@ -63,8 +65,8 @@ static void ab8500_power_off(void)
        /* Check if battery is known */
        psy = power_supply_get_by_name("ab8500_btemp");
        if (psy) {
-               ret = psy->get_property(psy, POWER_SUPPLY_PROP_TECHNOLOGY,
-                                       &val);
+               ret = power_supply_get_property(psy,
+                               POWER_SUPPLY_PROP_TECHNOLOGY, &val);
                if (!ret && val.intval != POWER_SUPPLY_TECHNOLOGY_UNKNOWN) {
                        printk(KERN_INFO
                               "Charger \"%s\" is connected with known battery."
@@ -72,6 +74,7 @@ static void ab8500_power_off(void)
                               pss[i]);
                        machine_restart("charging");
                }
+               power_supply_put(psy);
        }
 
 shutdown:
index 09ba8f186e6ad591dd748870153617fffa5a31f4..6ca6dfab50ebf3a975c51dc5234061ec09b1401a 100644 (file)
@@ -561,12 +561,23 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
                count++;
        }
 
+       count = 0;
+       of_property_for_each_u32(arizona->dev->of_node, "wlf,dmic-ref", prop,
+                                cur, val) {
+               if (count == ARRAY_SIZE(arizona->pdata.dmic_ref))
+                       break;
+
+               arizona->pdata.dmic_ref[count] = val;
+               count++;
+       }
+
        return 0;
 }
 
 const struct of_device_id arizona_of_match[] = {
        { .compatible = "wlf,wm5102", .data = (void *)WM5102 },
        { .compatible = "wlf,wm5110", .data = (void *)WM5110 },
+       { .compatible = "wlf,wm8280", .data = (void *)WM8280 },
        { .compatible = "wlf,wm8997", .data = (void *)WM8997 },
        {},
 };
@@ -671,6 +682,7 @@ int arizona_dev_init(struct arizona *arizona)
        switch (arizona->type) {
        case WM5102:
        case WM5110:
+       case WM8280:
        case WM8997:
                for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++)
                        arizona->core_supplies[i].supply
@@ -834,11 +846,19 @@ int arizona_dev_init(struct arizona *arizona)
 #endif
 #ifdef CONFIG_MFD_WM5110
        case 0x5110:
-               type_name = "WM5110";
-               if (arizona->type != WM5110) {
+               switch (arizona->type) {
+               case WM5110:
+                       type_name = "WM5110";
+                       break;
+               case WM8280:
+                       type_name = "WM8280";
+                       break;
+               default:
+                       type_name = "WM5110";
                        dev_err(arizona->dev, "WM5110 registered as %d\n",
                                arizona->type);
                        arizona->type = WM5110;
+                       break;
                }
                apply_patch = wm5110_patch;
                break;
@@ -1010,6 +1030,7 @@ int arizona_dev_init(struct arizona *arizona)
                                      ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
                break;
        case WM5110:
+       case WM8280:
                ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
                                      ARRAY_SIZE(wm5110_devs), NULL, 0, NULL);
                break;
index 9d4156fb082ae0b8d040e039ba17cd0aadf331d8..ff782a5de235f8fd62241b2e06d69c10527d9783 100644 (file)
@@ -44,6 +44,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
 #endif
 #ifdef CONFIG_MFD_WM5110
        case WM5110:
+       case WM8280:
                regmap_config = &wm5110_i2c_regmap;
                break;
 #endif
@@ -87,6 +88,7 @@ static int arizona_i2c_remove(struct i2c_client *i2c)
 static const struct i2c_device_id arizona_i2c_id[] = {
        { "wm5102", WM5102 },
        { "wm5110", WM5110 },
+       { "wm8280", WM8280 },
        { "wm8997", WM8997 },
        { }
 };
index 3a3fe7cc6d61e43b7dfeb2a528cd53da52542653..d063b94b94b5c97236cc04bb6311d486bd3adac2 100644 (file)
@@ -211,6 +211,7 @@ int arizona_irq_init(struct arizona *arizona)
 #endif
 #ifdef CONFIG_MFD_WM5110
        case WM5110:
+       case WM8280:
                aod = &wm5110_aod;
 
                switch (arizona->rev) {
index 8ef58bcff193e8c6c1f7e61872326cb545afdff2..1e845f6d407b82aa6e26ec5ef19b5545b911ddac 100644 (file)
@@ -44,6 +44,7 @@ static int arizona_spi_probe(struct spi_device *spi)
 #endif
 #ifdef CONFIG_MFD_WM5110
        case WM5110:
+       case WM8280:
                regmap_config = &wm5110_spi_regmap;
                break;
 #endif
@@ -84,6 +85,7 @@ static int arizona_spi_remove(struct spi_device *spi)
 static const struct spi_device_id arizona_spi_ids[] = {
        { "wm5102", WM5102 },
        { "wm5110", WM5110 },
+       { "wm8280", WM8280 },
        { },
 };
 MODULE_DEVICE_TABLE(spi, arizona_spi_ids);
index b1b580a88654f9fd1c70c1e89a85b3ba2d5b6786..d18029be6a78e3c0fecfbe2c64961eef25714eb6 100644 (file)
@@ -29,7 +29,7 @@
 
 #define AXP20X_OFF     0x80
 
-static const char const *axp20x_model_names[] = {
+static const char * const axp20x_model_names[] = {
        "AXP202",
        "AXP209",
        "AXP288",
@@ -87,7 +87,7 @@ static struct resource axp20x_pek_resources[] = {
        },
 };
 
-static struct resource axp288_battery_resources[] = {
+static struct resource axp288_fuel_gauge_resources[] = {
        {
                .start = AXP288_IRQ_QWBTU,
                .end   = AXP288_IRQ_QWBTU,
@@ -290,6 +290,29 @@ static struct resource axp288_adc_resources[] = {
        },
 };
 
+static struct resource axp288_extcon_resources[] = {
+       {
+               .start = AXP288_IRQ_VBUS_FALL,
+               .end   = AXP288_IRQ_VBUS_FALL,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_VBUS_RISE,
+               .end   = AXP288_IRQ_VBUS_RISE,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_MV_CHNG,
+               .end   = AXP288_IRQ_MV_CHNG,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_BC_USB_CHNG,
+               .end   = AXP288_IRQ_BC_USB_CHNG,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
 static struct resource axp288_charger_resources[] = {
        {
                .start = AXP288_IRQ_OV,
@@ -344,15 +367,20 @@ static struct mfd_cell axp288_cells[] = {
                .num_resources = ARRAY_SIZE(axp288_adc_resources),
                .resources = axp288_adc_resources,
        },
+       {
+               .name = "axp288_extcon",
+               .num_resources = ARRAY_SIZE(axp288_extcon_resources),
+               .resources = axp288_extcon_resources,
+       },
        {
                .name = "axp288_charger",
                .num_resources = ARRAY_SIZE(axp288_charger_resources),
                .resources = axp288_charger_resources,
        },
        {
-               .name = "axp288_battery",
-               .num_resources = ARRAY_SIZE(axp288_battery_resources),
-               .resources = axp288_battery_resources,
+               .name = "axp288_fuel_gauge",
+               .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources),
+               .resources = axp288_fuel_gauge_resources,
        },
        {
                .name = "axp288_pmic_acpi",
index 57ae7841f5362a11994fb9513606f062783065db..e65ca194fa98283a38539ab3b68393976a8c1604 100644 (file)
@@ -262,6 +262,8 @@ int da9052_irq_init(struct da9052 *da9052)
                goto regmap_err;
        }
 
+       enable_irq_wake(da9052->chip_irq);
+
        ret = da9052_request_irq(da9052, DA9052_IRQ_ADC_EOM, "adc-irq",
                            da9052_auxadc_irq, da9052);
 
index 45ae0b7d13ef19749311a3cdbc2f06dd456f8e4e..b5de8a6856c0de07f29c10dbeaa4de67c0ac4617 100644 (file)
@@ -32,7 +32,7 @@ static int da9052_spi_probe(struct spi_device *spi)
        if (!da9052)
                return -ENOMEM;
 
-       spi->mode = SPI_MODE_0 | SPI_CPOL;
+       spi->mode = SPI_MODE_0;
        spi->bits_per_word = 8;
        spi_setup(spi);
 
@@ -43,6 +43,10 @@ static int da9052_spi_probe(struct spi_device *spi)
 
        config = da9052_regmap_config;
        config.read_flag_mask = 1;
+       config.reg_bits = 7;
+       config.pad_bits = 1;
+       config.val_bits = 8;
+       config.use_single_rw = 1;
 
        da9052->regmap = devm_regmap_init_spi(spi, &config);
        if (IS_ERR(da9052->regmap)) {
index 4d757b97ef9a076fd4e433dff135c69b6adefe05..5549817df32e7954776a8e2334d44196bd785e6e 100644 (file)
@@ -95,7 +95,7 @@ static const struct regmap_range_cfg da9150_range_cfg[] = {
        },
 };
 
-static struct regmap_config da9150_regmap_config = {
+static const struct regmap_config da9150_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
        .ranges = da9150_range_cfg,
index 1be9bd1c046d1e5279c9968e6babc893ad350f64..704e189ca162ab6991d9b548c7aa88d67cc7a020 100644 (file)
@@ -435,7 +435,7 @@ static int _dln2_transfer(struct dln2_dev *dln2, u16 handle, u16 cmd,
        struct dln2_response *rsp;
        struct dln2_rx_context *rxc;
        struct device *dev = &dln2->interface->dev;
-       const unsigned long timeout = DLN2_USB_TIMEOUT * HZ / 1000;
+       const unsigned long timeout = msecs_to_jiffies(DLN2_USB_TIMEOUT);
        struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle];
        int size;
 
index 7210ae28bf816cbbb612a219b5f57fd4c94a149c..95b2ff8f223ab34bc06f45c585d1a5a55e02c810 100644 (file)
@@ -93,7 +93,7 @@ static int hi6421_pmic_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id of_hi6421_pmic_match_tbl[] = {
+static const struct of_device_id of_hi6421_pmic_match_tbl[] = {
        { .compatible = "hisilicon,hi6421-pmic", },
        { },
 };
diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c
new file mode 100644 (file)
index 0000000..1ce1603
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * Intel Quark MFD PCI driver for I2C & GPIO
+ *
+ * Copyright(c) 2014 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.
+ *
+ * Intel Quark PCI device for I2C and GPIO controller sharing the same
+ * PCI function. This PCI driver will split the 2 devices into their
+ * respective drivers.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/mfd/core.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/dmi.h>
+#include <linux/platform_data/gpio-dwapb.h>
+#include <linux/platform_data/i2c-designware.h>
+
+/* PCI BAR for register base address */
+#define MFD_I2C_BAR            0
+#define MFD_GPIO_BAR           1
+
+/* The base GPIO number under GPIOLIB framework */
+#define INTEL_QUARK_MFD_GPIO_BASE      8
+
+/* The default number of South-Cluster GPIO on Quark. */
+#define INTEL_QUARK_MFD_NGPIO          8
+
+/* The DesignWare GPIO ports on Quark. */
+#define INTEL_QUARK_GPIO_NPORTS        1
+
+#define INTEL_QUARK_IORES_MEM  0
+#define INTEL_QUARK_IORES_IRQ  1
+
+#define INTEL_QUARK_I2C_CONTROLLER_CLK "i2c_designware.0"
+
+/* The Quark I2C controller source clock */
+#define INTEL_QUARK_I2C_CLK_HZ 33000000
+
+#define INTEL_QUARK_I2C_NCLK   1
+
+struct intel_quark_mfd {
+       struct pci_dev          *pdev;
+       struct clk              *i2c_clk;
+       struct clk_lookup       *i2c_clk_lookup;
+};
+
+struct i2c_mode_info {
+       const char *name;
+       unsigned int i2c_scl_freq;
+};
+
+static const struct i2c_mode_info platform_i2c_mode_info[] = {
+       {
+               .name = "Galileo",
+               .i2c_scl_freq = 100000,
+       },
+       {
+               .name = "GalileoGen2",
+               .i2c_scl_freq = 400000,
+       },
+       {}
+};
+
+static struct resource intel_quark_i2c_res[] = {
+       [INTEL_QUARK_IORES_MEM] = {
+               .flags = IORESOURCE_MEM,
+       },
+       [INTEL_QUARK_IORES_IRQ] = {
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource intel_quark_gpio_res[] = {
+       [INTEL_QUARK_IORES_MEM] = {
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct mfd_cell intel_quark_mfd_cells[] = {
+       {
+               .id = MFD_I2C_BAR,
+               .name = "i2c_designware",
+               .num_resources = ARRAY_SIZE(intel_quark_i2c_res),
+               .resources = intel_quark_i2c_res,
+               .ignore_resource_conflicts = true,
+       },
+       {
+               .id = MFD_GPIO_BAR,
+               .name = "gpio-dwapb",
+               .num_resources = ARRAY_SIZE(intel_quark_gpio_res),
+               .resources = intel_quark_gpio_res,
+               .ignore_resource_conflicts = true,
+       },
+};
+
+static const struct pci_device_id intel_quark_mfd_ids[] = {
+       { PCI_VDEVICE(INTEL, 0x0934), },
+       {},
+};
+MODULE_DEVICE_TABLE(pci, intel_quark_mfd_ids);
+
+static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd)
+{
+       struct pci_dev *pdev = quark_mfd->pdev;
+       struct clk_lookup *i2c_clk_lookup;
+       struct clk *i2c_clk;
+       int ret;
+
+       i2c_clk_lookup = devm_kcalloc(&pdev->dev, INTEL_QUARK_I2C_NCLK,
+                                     sizeof(*i2c_clk_lookup), GFP_KERNEL);
+       if (!i2c_clk_lookup)
+               return -ENOMEM;
+
+       i2c_clk_lookup[0].dev_id = INTEL_QUARK_I2C_CONTROLLER_CLK;
+
+       i2c_clk = clk_register_fixed_rate(&pdev->dev,
+                                         INTEL_QUARK_I2C_CONTROLLER_CLK, NULL,
+                                         CLK_IS_ROOT, INTEL_QUARK_I2C_CLK_HZ);
+
+       quark_mfd->i2c_clk_lookup = i2c_clk_lookup;
+       quark_mfd->i2c_clk = i2c_clk;
+
+       ret = clk_register_clkdevs(i2c_clk, i2c_clk_lookup,
+                                  INTEL_QUARK_I2C_NCLK);
+       if (ret)
+               dev_err(&pdev->dev, "Fixed clk register failed: %d\n", ret);
+
+       return ret;
+}
+
+static void intel_quark_unregister_i2c_clk(struct pci_dev *pdev)
+{
+       struct intel_quark_mfd *quark_mfd = dev_get_drvdata(&pdev->dev);
+
+       if (!quark_mfd->i2c_clk || !quark_mfd->i2c_clk_lookup)
+               return;
+
+       clkdev_drop(quark_mfd->i2c_clk_lookup);
+       clk_unregister(quark_mfd->i2c_clk);
+}
+
+static int intel_quark_i2c_setup(struct pci_dev *pdev, struct mfd_cell *cell)
+{
+       const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
+       const struct i2c_mode_info *info;
+       struct dw_i2c_platform_data *pdata;
+       struct resource *res = (struct resource *)cell->resources;
+       struct device *dev = &pdev->dev;
+
+       res[INTEL_QUARK_IORES_MEM].start =
+               pci_resource_start(pdev, MFD_I2C_BAR);
+       res[INTEL_QUARK_IORES_MEM].end =
+               pci_resource_end(pdev, MFD_I2C_BAR);
+
+       res[INTEL_QUARK_IORES_IRQ].start = pdev->irq;
+       res[INTEL_QUARK_IORES_IRQ].end = pdev->irq;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+
+       /* Normal mode by default */
+       pdata->i2c_scl_freq = 100000;
+
+       if (board_name) {
+               for (info = platform_i2c_mode_info; info->name; info++) {
+                       if (!strcmp(board_name, info->name)) {
+                               pdata->i2c_scl_freq = info->i2c_scl_freq;
+                               break;
+                       }
+               }
+       }
+
+       cell->platform_data = pdata;
+       cell->pdata_size = sizeof(*pdata);
+
+       return 0;
+}
+
+static int intel_quark_gpio_setup(struct pci_dev *pdev, struct mfd_cell *cell)
+{
+       struct dwapb_platform_data *pdata;
+       struct resource *res = (struct resource *)cell->resources;
+       struct device *dev = &pdev->dev;
+
+       res[INTEL_QUARK_IORES_MEM].start =
+               pci_resource_start(pdev, MFD_GPIO_BAR);
+       res[INTEL_QUARK_IORES_MEM].end =
+               pci_resource_end(pdev, MFD_GPIO_BAR);
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+
+       /* For intel quark x1000, it has only one port: portA */
+       pdata->nports = INTEL_QUARK_GPIO_NPORTS;
+       pdata->properties = devm_kcalloc(dev, pdata->nports,
+                                        sizeof(*pdata->properties),
+                                        GFP_KERNEL);
+       if (!pdata->properties)
+               return -ENOMEM;
+
+       /* Set the properties for portA */
+       pdata->properties->node         = NULL;
+       pdata->properties->name         = "intel-quark-x1000-gpio-portA";
+       pdata->properties->idx          = 0;
+       pdata->properties->ngpio        = INTEL_QUARK_MFD_NGPIO;
+       pdata->properties->gpio_base    = INTEL_QUARK_MFD_GPIO_BASE;
+       pdata->properties->irq          = pdev->irq;
+       pdata->properties->irq_shared   = true;
+
+       cell->platform_data = pdata;
+       cell->pdata_size = sizeof(*pdata);
+
+       return 0;
+}
+
+static int intel_quark_mfd_probe(struct pci_dev *pdev,
+                                const struct pci_device_id *id)
+{
+       struct intel_quark_mfd *quark_mfd;
+       int ret;
+
+       ret = pcim_enable_device(pdev);
+       if (ret)
+               return ret;
+
+       quark_mfd = devm_kzalloc(&pdev->dev, sizeof(*quark_mfd), GFP_KERNEL);
+       if (!quark_mfd)
+               return -ENOMEM;
+       quark_mfd->pdev = pdev;
+
+       ret = intel_quark_register_i2c_clk(quark_mfd);
+       if (ret)
+               return ret;
+
+       dev_set_drvdata(&pdev->dev, quark_mfd);
+
+       ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[MFD_I2C_BAR]);
+       if (ret)
+               return ret;
+
+       ret = intel_quark_gpio_setup(pdev,
+                                    &intel_quark_mfd_cells[MFD_GPIO_BAR]);
+       if (ret)
+               return ret;
+
+       return mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells,
+                              ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0,
+                              NULL);
+}
+
+static void intel_quark_mfd_remove(struct pci_dev *pdev)
+{
+       intel_quark_unregister_i2c_clk(pdev);
+       mfd_remove_devices(&pdev->dev);
+}
+
+static struct pci_driver intel_quark_mfd_driver = {
+       .name           = "intel_quark_mfd_i2c_gpio",
+       .id_table       = intel_quark_mfd_ids,
+       .probe          = intel_quark_mfd_probe,
+       .remove         = intel_quark_mfd_remove,
+};
+
+module_pci_driver(intel_quark_mfd_driver);
+
+MODULE_AUTHOR("Raymond Tan <raymond.tan@intel.com>");
+MODULE_DESCRIPTION("Intel Quark MFD PCI driver for I2C & GPIO");
+MODULE_LICENSE("GPL v2");
index 80cef048b9040234593eded531c810f7152cd332..7b50b6b208a5b04bf578804590add7117d21deb0 100644 (file)
 #include <linux/mfd/intel_soc_pmic.h>
 #include "intel_soc_pmic_core.h"
 
-/*
- * On some boards the PMIC interrupt may come from a GPIO line.
- * Try to lookup the ACPI table and see if such connection exists. If not,
- * return -ENOENT and use the IRQ provided by I2C.
- */
 static int intel_soc_pmic_find_gpio_irq(struct device *dev)
 {
        struct gpio_desc *desc;
        int irq;
 
-       desc = devm_gpiod_get_index(dev, "intel_soc_pmic", 0);
+       desc = devm_gpiod_get_index(dev, "intel_soc_pmic", 0, GPIOD_IN);
        if (IS_ERR(desc))
-               return -ENOENT;
+               return PTR_ERR(desc);
 
        irq = gpiod_to_irq(desc);
        if (irq < 0)
@@ -71,6 +66,11 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
 
        pmic->regmap = devm_regmap_init_i2c(i2c, config->regmap_config);
 
+       /*
+        * On some boards the PMIC interrupt may come from a GPIO line. Try to
+        * lookup the ACPI table for a such connection and setup a GPIO
+        * interrupt if it exists. Otherwise use the IRQ provided by I2C
+        */
        irq = intel_soc_pmic_find_gpio_irq(dev);
        pmic->irq = (irq < 0) ? i2c->irq : irq;
 
index 5615522f8d628b0f9d4b43d240d18d7bad02c835..8057849d51ac5b1299015e4c54b2f96ffe64ce53 100644 (file)
@@ -508,8 +508,15 @@ static struct dmi_system_id kempld_dmi_table[] __initdata = {
                },
                .driver_data = (void *)&kempld_platform_data_generic,
                .callback = kempld_create_platform_device,
-       },
-       {
+       }, {
+               .ident = "CBL6",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
+                       DMI_MATCH(DMI_BOARD_NAME, "COMe-cBL6"),
+               },
+               .driver_data = (void *)&kempld_platform_data_generic,
+               .callback = kempld_create_platform_device,
+       }, {
                .ident = "CCR2",
                .matches = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
index f35d4280b2f743d85892fb3125f8931778be77c4..12d960a60ec459f1a2a063b228730070ddabc76e 100644 (file)
@@ -539,72 +539,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
  * functions that probably will be registered by other drivers.
  */
 static const struct pci_device_id lpc_ich_ids[] = {
-       { PCI_VDEVICE(INTEL, 0x2410), LPC_ICH},
-       { PCI_VDEVICE(INTEL, 0x2420), LPC_ICH0},
-       { PCI_VDEVICE(INTEL, 0x2440), LPC_ICH2},
-       { PCI_VDEVICE(INTEL, 0x244c), LPC_ICH2M},
-       { PCI_VDEVICE(INTEL, 0x2480), LPC_ICH3},
-       { PCI_VDEVICE(INTEL, 0x248c), LPC_ICH3M},
-       { PCI_VDEVICE(INTEL, 0x24c0), LPC_ICH4},
-       { PCI_VDEVICE(INTEL, 0x24cc), LPC_ICH4M},
-       { PCI_VDEVICE(INTEL, 0x2450), LPC_CICH},
-       { PCI_VDEVICE(INTEL, 0x24d0), LPC_ICH5},
-       { PCI_VDEVICE(INTEL, 0x25a1), LPC_6300ESB},
-       { PCI_VDEVICE(INTEL, 0x2640), LPC_ICH6},
-       { PCI_VDEVICE(INTEL, 0x2641), LPC_ICH6M},
-       { PCI_VDEVICE(INTEL, 0x2642), LPC_ICH6W},
-       { PCI_VDEVICE(INTEL, 0x2670), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x2671), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x2672), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x2673), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x2674), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x2675), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x2676), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x2677), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x2678), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x2679), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x267a), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x267b), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x267c), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x267d), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x267e), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x267f), LPC_631XESB},
-       { PCI_VDEVICE(INTEL, 0x27b8), LPC_ICH7},
-       { PCI_VDEVICE(INTEL, 0x27b0), LPC_ICH7DH},
-       { PCI_VDEVICE(INTEL, 0x27b9), LPC_ICH7M},
-       { PCI_VDEVICE(INTEL, 0x27bd), LPC_ICH7MDH},
-       { PCI_VDEVICE(INTEL, 0x27bc), LPC_NM10},
-       { PCI_VDEVICE(INTEL, 0x2810), LPC_ICH8},
-       { PCI_VDEVICE(INTEL, 0x2812), LPC_ICH8DH},
-       { PCI_VDEVICE(INTEL, 0x2814), LPC_ICH8DO},
-       { PCI_VDEVICE(INTEL, 0x2815), LPC_ICH8M},
-       { PCI_VDEVICE(INTEL, 0x2811), LPC_ICH8ME},
-       { PCI_VDEVICE(INTEL, 0x2918), LPC_ICH9},
-       { PCI_VDEVICE(INTEL, 0x2916), LPC_ICH9R},
-       { PCI_VDEVICE(INTEL, 0x2912), LPC_ICH9DH},
-       { PCI_VDEVICE(INTEL, 0x2914), LPC_ICH9DO},
-       { PCI_VDEVICE(INTEL, 0x2919), LPC_ICH9M},
-       { PCI_VDEVICE(INTEL, 0x2917), LPC_ICH9ME},
-       { PCI_VDEVICE(INTEL, 0x3a18), LPC_ICH10},
-       { PCI_VDEVICE(INTEL, 0x3a16), LPC_ICH10R},
-       { PCI_VDEVICE(INTEL, 0x3a1a), LPC_ICH10D},
-       { PCI_VDEVICE(INTEL, 0x3a14), LPC_ICH10DO},
-       { PCI_VDEVICE(INTEL, 0x3b00), LPC_PCH},
-       { PCI_VDEVICE(INTEL, 0x3b01), LPC_PCHM},
-       { PCI_VDEVICE(INTEL, 0x3b02), LPC_P55},
-       { PCI_VDEVICE(INTEL, 0x3b03), LPC_PM55},
-       { PCI_VDEVICE(INTEL, 0x3b06), LPC_H55},
-       { PCI_VDEVICE(INTEL, 0x3b07), LPC_QM57},
-       { PCI_VDEVICE(INTEL, 0x3b08), LPC_H57},
-       { PCI_VDEVICE(INTEL, 0x3b09), LPC_HM55},
-       { PCI_VDEVICE(INTEL, 0x3b0a), LPC_Q57},
-       { PCI_VDEVICE(INTEL, 0x3b0b), LPC_HM57},
-       { PCI_VDEVICE(INTEL, 0x3b0d), LPC_PCHMSFF},
-       { PCI_VDEVICE(INTEL, 0x3b0f), LPC_QS57},
-       { PCI_VDEVICE(INTEL, 0x3b12), LPC_3400},
-       { PCI_VDEVICE(INTEL, 0x3b14), LPC_3420},
-       { PCI_VDEVICE(INTEL, 0x3b16), LPC_3450},
-       { PCI_VDEVICE(INTEL, 0x5031), LPC_EP80579},
+       { PCI_VDEVICE(INTEL, 0x0f1c), LPC_BAYTRAIL},
        { PCI_VDEVICE(INTEL, 0x1c41), LPC_CPT},
        { PCI_VDEVICE(INTEL, 0x1c42), LPC_CPTD},
        { PCI_VDEVICE(INTEL, 0x1c43), LPC_CPTM},
@@ -638,7 +573,6 @@ static const struct pci_device_id lpc_ich_ids[] = {
        { PCI_VDEVICE(INTEL, 0x1c5f), LPC_CPT},
        { PCI_VDEVICE(INTEL, 0x1d40), LPC_PBG},
        { PCI_VDEVICE(INTEL, 0x1d41), LPC_PBG},
-       { PCI_VDEVICE(INTEL, 0x2310), LPC_DH89XXCC},
        { PCI_VDEVICE(INTEL, 0x1e40), LPC_PPT},
        { PCI_VDEVICE(INTEL, 0x1e41), LPC_PPT},
        { PCI_VDEVICE(INTEL, 0x1e42), LPC_PPT},
@@ -671,6 +605,79 @@ static const struct pci_device_id lpc_ich_ids[] = {
        { PCI_VDEVICE(INTEL, 0x1e5d), LPC_PPT},
        { PCI_VDEVICE(INTEL, 0x1e5e), LPC_PPT},
        { PCI_VDEVICE(INTEL, 0x1e5f), LPC_PPT},
+       { PCI_VDEVICE(INTEL, 0x1f38), LPC_AVN},
+       { PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN},
+       { PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN},
+       { PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN},
+       { PCI_VDEVICE(INTEL, 0x229c), LPC_BRASWELL},
+       { PCI_VDEVICE(INTEL, 0x2310), LPC_DH89XXCC},
+       { PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO},
+       { PCI_VDEVICE(INTEL, 0x2410), LPC_ICH},
+       { PCI_VDEVICE(INTEL, 0x2420), LPC_ICH0},
+       { PCI_VDEVICE(INTEL, 0x2440), LPC_ICH2},
+       { PCI_VDEVICE(INTEL, 0x244c), LPC_ICH2M},
+       { PCI_VDEVICE(INTEL, 0x2450), LPC_CICH},
+       { PCI_VDEVICE(INTEL, 0x2480), LPC_ICH3},
+       { PCI_VDEVICE(INTEL, 0x248c), LPC_ICH3M},
+       { PCI_VDEVICE(INTEL, 0x24c0), LPC_ICH4},
+       { PCI_VDEVICE(INTEL, 0x24cc), LPC_ICH4M},
+       { PCI_VDEVICE(INTEL, 0x24d0), LPC_ICH5},
+       { PCI_VDEVICE(INTEL, 0x25a1), LPC_6300ESB},
+       { PCI_VDEVICE(INTEL, 0x2640), LPC_ICH6},
+       { PCI_VDEVICE(INTEL, 0x2641), LPC_ICH6M},
+       { PCI_VDEVICE(INTEL, 0x2642), LPC_ICH6W},
+       { PCI_VDEVICE(INTEL, 0x2670), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2671), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2672), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2673), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2674), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2675), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2676), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2677), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2678), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x2679), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x267a), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x267b), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x267c), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x267d), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x267e), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x267f), LPC_631XESB},
+       { PCI_VDEVICE(INTEL, 0x27b0), LPC_ICH7DH},
+       { PCI_VDEVICE(INTEL, 0x27b8), LPC_ICH7},
+       { PCI_VDEVICE(INTEL, 0x27b9), LPC_ICH7M},
+       { PCI_VDEVICE(INTEL, 0x27bc), LPC_NM10},
+       { PCI_VDEVICE(INTEL, 0x27bd), LPC_ICH7MDH},
+       { PCI_VDEVICE(INTEL, 0x2810), LPC_ICH8},
+       { PCI_VDEVICE(INTEL, 0x2811), LPC_ICH8ME},
+       { PCI_VDEVICE(INTEL, 0x2812), LPC_ICH8DH},
+       { PCI_VDEVICE(INTEL, 0x2814), LPC_ICH8DO},
+       { PCI_VDEVICE(INTEL, 0x2815), LPC_ICH8M},
+       { PCI_VDEVICE(INTEL, 0x2912), LPC_ICH9DH},
+       { PCI_VDEVICE(INTEL, 0x2914), LPC_ICH9DO},
+       { PCI_VDEVICE(INTEL, 0x2916), LPC_ICH9R},
+       { PCI_VDEVICE(INTEL, 0x2917), LPC_ICH9ME},
+       { PCI_VDEVICE(INTEL, 0x2918), LPC_ICH9},
+       { PCI_VDEVICE(INTEL, 0x2919), LPC_ICH9M},
+       { PCI_VDEVICE(INTEL, 0x3a14), LPC_ICH10DO},
+       { PCI_VDEVICE(INTEL, 0x3a16), LPC_ICH10R},
+       { PCI_VDEVICE(INTEL, 0x3a18), LPC_ICH10},
+       { PCI_VDEVICE(INTEL, 0x3a1a), LPC_ICH10D},
+       { PCI_VDEVICE(INTEL, 0x3b00), LPC_PCH},
+       { PCI_VDEVICE(INTEL, 0x3b01), LPC_PCHM},
+       { PCI_VDEVICE(INTEL, 0x3b02), LPC_P55},
+       { PCI_VDEVICE(INTEL, 0x3b03), LPC_PM55},
+       { PCI_VDEVICE(INTEL, 0x3b06), LPC_H55},
+       { PCI_VDEVICE(INTEL, 0x3b07), LPC_QM57},
+       { PCI_VDEVICE(INTEL, 0x3b08), LPC_H57},
+       { PCI_VDEVICE(INTEL, 0x3b09), LPC_HM55},
+       { PCI_VDEVICE(INTEL, 0x3b0a), LPC_Q57},
+       { PCI_VDEVICE(INTEL, 0x3b0b), LPC_HM57},
+       { PCI_VDEVICE(INTEL, 0x3b0d), LPC_PCHMSFF},
+       { PCI_VDEVICE(INTEL, 0x3b0f), LPC_QS57},
+       { PCI_VDEVICE(INTEL, 0x3b12), LPC_3400},
+       { PCI_VDEVICE(INTEL, 0x3b14), LPC_3420},
+       { PCI_VDEVICE(INTEL, 0x3b16), LPC_3450},
+       { PCI_VDEVICE(INTEL, 0x5031), LPC_EP80579},
        { PCI_VDEVICE(INTEL, 0x8c40), LPC_LPT},
        { PCI_VDEVICE(INTEL, 0x8c41), LPC_LPT},
        { PCI_VDEVICE(INTEL, 0x8c42), LPC_LPT},
@@ -703,14 +710,11 @@ static const struct pci_device_id lpc_ich_ids[] = {
        { PCI_VDEVICE(INTEL, 0x8c5d), LPC_LPT},
        { PCI_VDEVICE(INTEL, 0x8c5e), LPC_LPT},
        { PCI_VDEVICE(INTEL, 0x8c5f), LPC_LPT},
-       { PCI_VDEVICE(INTEL, 0x9c40), LPC_LPT_LP},
-       { PCI_VDEVICE(INTEL, 0x9c41), LPC_LPT_LP},
-       { PCI_VDEVICE(INTEL, 0x9c42), LPC_LPT_LP},
-       { PCI_VDEVICE(INTEL, 0x9c43), LPC_LPT_LP},
-       { PCI_VDEVICE(INTEL, 0x9c44), LPC_LPT_LP},
-       { PCI_VDEVICE(INTEL, 0x9c45), LPC_LPT_LP},
-       { PCI_VDEVICE(INTEL, 0x9c46), LPC_LPT_LP},
-       { PCI_VDEVICE(INTEL, 0x9c47), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x8cc1), LPC_9S},
+       { PCI_VDEVICE(INTEL, 0x8cc2), LPC_9S},
+       { PCI_VDEVICE(INTEL, 0x8cc3), LPC_9S},
+       { PCI_VDEVICE(INTEL, 0x8cc4), LPC_9S},
+       { PCI_VDEVICE(INTEL, 0x8cc6), LPC_9S},
        { PCI_VDEVICE(INTEL, 0x8d40), LPC_WBG},
        { PCI_VDEVICE(INTEL, 0x8d41), LPC_WBG},
        { PCI_VDEVICE(INTEL, 0x8d42), LPC_WBG},
@@ -743,12 +747,14 @@ static const struct pci_device_id lpc_ich_ids[] = {
        { PCI_VDEVICE(INTEL, 0x8d5d), LPC_WBG},
        { PCI_VDEVICE(INTEL, 0x8d5e), LPC_WBG},
        { PCI_VDEVICE(INTEL, 0x8d5f), LPC_WBG},
-       { PCI_VDEVICE(INTEL, 0x1f38), LPC_AVN},
-       { PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN},
-       { PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN},
-       { PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN},
-       { PCI_VDEVICE(INTEL, 0x0f1c), LPC_BAYTRAIL},
-       { PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO},
+       { PCI_VDEVICE(INTEL, 0x9c40), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c41), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c42), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c43), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c44), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c45), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c46), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c47), LPC_LPT_LP},
        { PCI_VDEVICE(INTEL, 0x9cc1), LPC_WPT_LP},
        { PCI_VDEVICE(INTEL, 0x9cc2), LPC_WPT_LP},
        { PCI_VDEVICE(INTEL, 0x9cc3), LPC_WPT_LP},
@@ -756,12 +762,6 @@ static const struct pci_device_id lpc_ich_ids[] = {
        { PCI_VDEVICE(INTEL, 0x9cc6), LPC_WPT_LP},
        { PCI_VDEVICE(INTEL, 0x9cc7), LPC_WPT_LP},
        { PCI_VDEVICE(INTEL, 0x9cc9), LPC_WPT_LP},
-       { PCI_VDEVICE(INTEL, 0x229c), LPC_BRASWELL},
-       { PCI_VDEVICE(INTEL, 0x8cc1), LPC_9S},
-       { PCI_VDEVICE(INTEL, 0x8cc2), LPC_9S},
-       { PCI_VDEVICE(INTEL, 0x8cc3), LPC_9S},
-       { PCI_VDEVICE(INTEL, 0x8cc4), LPC_9S},
-       { PCI_VDEVICE(INTEL, 0x8cc6), LPC_9S},
        { 0, },                 /* End of list */
 };
 MODULE_DEVICE_TABLE(pci, lpc_ich_ids);
index a159593e27a0c42dd751ad24ae38026b6694c885..cb14afa97e6fbbf9403cd55687b39d43de5a7919 100644 (file)
@@ -53,8 +53,8 @@ static const struct mfd_cell max77693_devs[] = {
                .of_compatible = "maxim,max77693-haptic",
        },
        {
-               .name = "max77693-flash",
-               .of_compatible = "maxim,max77693-flash",
+               .name = "max77693-led",
+               .of_compatible = "maxim,max77693-led",
        },
 };
 
diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c
new file mode 100644 (file)
index 0000000..a354ac6
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * MFD core 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/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max77843-private.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+static const struct mfd_cell max77843_devs[] = {
+       {
+               .name = "max77843-muic",
+               .of_compatible = "maxim,max77843-muic",
+       }, {
+               .name = "max77843-regulator",
+               .of_compatible = "maxim,max77843-regulator",
+       }, {
+               .name = "max77843-charger",
+               .of_compatible = "maxim,max77843-charger"
+       }, {
+               .name = "max77843-fuelgauge",
+               .of_compatible = "maxim,max77843-fuelgauge",
+       }, {
+               .name = "max77843-haptic",
+               .of_compatible = "maxim,max77843-haptic",
+       },
+};
+
+static const struct regmap_config max77843_charger_regmap_config = {
+       .reg_bits       = 8,
+       .val_bits       = 8,
+       .max_register   = MAX77843_CHG_REG_END,
+};
+
+static const struct regmap_config max77843_regmap_config = {
+       .reg_bits       = 8,
+       .val_bits       = 8,
+       .max_register   = MAX77843_SYS_REG_END,
+};
+
+static const struct regmap_irq max77843_irqs[] = {
+       /* TOPSYS interrupts */
+       { .reg_offset = 0, .mask = MAX77843_SYS_IRQ_SYSUVLO_INT, },
+       { .reg_offset = 0, .mask = MAX77843_SYS_IRQ_SYSOVLO_INT, },
+       { .reg_offset = 0, .mask = MAX77843_SYS_IRQ_TSHDN_INT, },
+       { .reg_offset = 0, .mask = MAX77843_SYS_IRQ_TM_INT, },
+};
+
+static const struct regmap_irq_chip max77843_irq_chip = {
+       .name           = "max77843",
+       .status_base    = MAX77843_SYS_REG_SYSINTSRC,
+       .mask_base      = MAX77843_SYS_REG_SYSINTMASK,
+       .mask_invert    = false,
+       .num_regs       = 1,
+       .irqs           = max77843_irqs,
+       .num_irqs       = ARRAY_SIZE(max77843_irqs),
+};
+
+/* Charger and Charger regulator use same regmap. */
+static int max77843_chg_init(struct max77843 *max77843)
+{
+       int ret;
+
+       max77843->i2c_chg = i2c_new_dummy(max77843->i2c->adapter, I2C_ADDR_CHG);
+       if (!max77843->i2c_chg) {
+               dev_err(&max77843->i2c->dev,
+                               "Cannot allocate I2C device for Charger\n");
+               return PTR_ERR(max77843->i2c_chg);
+       }
+       i2c_set_clientdata(max77843->i2c_chg, max77843);
+
+       max77843->regmap_chg = devm_regmap_init_i2c(max77843->i2c_chg,
+                       &max77843_charger_regmap_config);
+       if (IS_ERR(max77843->regmap_chg)) {
+               ret = PTR_ERR(max77843->regmap_chg);
+               goto err_chg_i2c;
+       }
+
+       return 0;
+
+err_chg_i2c:
+       i2c_unregister_device(max77843->i2c_chg);
+
+       return ret;
+}
+
+static int max77843_probe(struct i2c_client *i2c,
+                         const struct i2c_device_id *id)
+{
+       struct max77843 *max77843;
+       unsigned int reg_data;
+       int ret;
+
+       max77843 = devm_kzalloc(&i2c->dev, sizeof(*max77843), GFP_KERNEL);
+       if (!max77843)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, max77843);
+       max77843->dev = &i2c->dev;
+       max77843->i2c = i2c;
+       max77843->irq = i2c->irq;
+
+       max77843->regmap = devm_regmap_init_i2c(i2c,
+                       &max77843_regmap_config);
+       if (IS_ERR(max77843->regmap)) {
+               dev_err(&i2c->dev, "Failed to allocate topsys register map\n");
+               return PTR_ERR(max77843->regmap);
+       }
+
+       ret = regmap_add_irq_chip(max77843->regmap, max77843->irq,
+                       IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
+                       0, &max77843_irq_chip, &max77843->irq_data);
+       if (ret) {
+               dev_err(&i2c->dev, "Failed to add TOPSYS IRQ chip\n");
+               return ret;
+       }
+
+       ret = regmap_read(max77843->regmap,
+                       MAX77843_SYS_REG_PMICID, &reg_data);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read PMIC ID\n");
+               goto err_pmic_id;
+       }
+       dev_info(&i2c->dev, "device ID: 0x%x\n", reg_data);
+
+       ret = max77843_chg_init(max77843);
+       if (ret) {
+               dev_err(&i2c->dev, "Failed to init Charger\n");
+               goto err_pmic_id;
+       }
+
+       ret = regmap_update_bits(max77843->regmap,
+                                MAX77843_SYS_REG_INTSRCMASK,
+                                MAX77843_INTSRC_MASK_MASK,
+                                (unsigned int)~MAX77843_INTSRC_MASK_MASK);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to unmask interrupt source\n");
+               goto err_pmic_id;
+       }
+
+       ret = mfd_add_devices(max77843->dev, -1, max77843_devs,
+                             ARRAY_SIZE(max77843_devs), NULL, 0, NULL);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to add mfd device\n");
+               goto err_pmic_id;
+       }
+
+       device_init_wakeup(max77843->dev, true);
+
+       return 0;
+
+err_pmic_id:
+       regmap_del_irq_chip(max77843->irq, max77843->irq_data);
+
+       return ret;
+}
+
+static int max77843_remove(struct i2c_client *i2c)
+{
+       struct max77843 *max77843 = i2c_get_clientdata(i2c);
+
+       mfd_remove_devices(max77843->dev);
+
+       regmap_del_irq_chip(max77843->irq, max77843->irq_data);
+
+       i2c_unregister_device(max77843->i2c_chg);
+
+       return 0;
+}
+
+static const struct of_device_id max77843_dt_match[] = {
+       { .compatible = "maxim,max77843", },
+       { },
+};
+
+static const struct i2c_device_id max77843_id[] = {
+       { "max77843", },
+       { },
+};
+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);
+
+       disable_irq(max77843->irq);
+       if (device_may_wakeup(dev))
+               enable_irq_wake(max77843->irq);
+
+       return 0;
+}
+
+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);
+
+       if (device_may_wakeup(dev))
+               disable_irq_wake(max77843->irq);
+       enable_irq(max77843->irq);
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(max77843_pm, max77843_suspend, max77843_resume);
+
+static struct i2c_driver max77843_i2c_driver = {
+       .driver = {
+               .name = "max77843",
+               .pm = &max77843_pm,
+               .of_match_table = max77843_dt_match,
+       },
+       .probe = max77843_probe,
+       .remove = max77843_remove,
+       .id_table = max77843_id,
+};
+
+static int __init max77843_i2c_init(void)
+{
+       return i2c_add_driver(&max77843_i2c_driver);
+}
+subsys_initcall(max77843_i2c_init);
+
+static void __exit max77843_i2c_exit(void)
+{
+       i2c_del_driver(&max77843_i2c_driver);
+}
+module_exit(max77843_i2c_exit);
index 64dde5d24b3206782d98a8d7066f3780779f9db5..25fd7116493a38efc7eddd141a8b469b603be072 100644 (file)
 void mc13xxx_lock(struct mc13xxx *mc13xxx)
 {
        if (!mutex_trylock(&mc13xxx->lock)) {
-               dev_dbg(mc13xxx->dev, "wait for %s from %pf\n",
+               dev_dbg(mc13xxx->dev, "wait for %s from %ps\n",
                                __func__, __builtin_return_address(0));
 
                mutex_lock(&mc13xxx->lock);
        }
-       dev_dbg(mc13xxx->dev, "%s from %pf\n",
+       dev_dbg(mc13xxx->dev, "%s from %ps\n",
                        __func__, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(mc13xxx_lock);
 
 void mc13xxx_unlock(struct mc13xxx *mc13xxx)
 {
-       dev_dbg(mc13xxx->dev, "%s from %pf\n",
+       dev_dbg(mc13xxx->dev, "%s from %ps\n",
                        __func__, __builtin_return_address(0));
        mutex_unlock(&mc13xxx->lock);
 }
index 9f01aef539ddd7a21a3958548b0c856b4138fff6..3ac36f5ccd3e13ddc81b3801ff196ee815742790 100644 (file)
@@ -532,29 +532,6 @@ static const struct menelaus_vtg_value vcore_values[] = {
        { 1450, 18 },
 };
 
-int menelaus_set_vcore_sw(unsigned int mV)
-{
-       int val, ret;
-       struct i2c_client *c = the_menelaus->client;
-
-       val = menelaus_get_vtg_value(mV, vcore_values,
-                                    ARRAY_SIZE(vcore_values));
-       if (val < 0)
-               return -EINVAL;
-
-       dev_dbg(&c->dev, "Setting VCORE to %d mV (val 0x%02x)\n", mV, val);
-
-       /* Set SW mode and the voltage in one go. */
-       mutex_lock(&the_menelaus->lock);
-       ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val);
-       if (ret == 0)
-               the_menelaus->vcore_hw_mode = 0;
-       mutex_unlock(&the_menelaus->lock);
-       msleep(1);
-
-       return ret;
-}
-
 int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV)
 {
        int fval, rval, val, ret;
@@ -1239,7 +1216,7 @@ static int menelaus_probe(struct i2c_client *client,
        err = menelaus_read_reg(MENELAUS_VCORE_CTRL1);
        if (err < 0)
                goto fail;
-       if (err & BIT(7))
+       if (err & VCORE_CTRL1_HW_NSW)
                menelaus->vcore_hw_mode = 1;
        else
                menelaus->vcore_hw_mode = 0;
@@ -1259,7 +1236,7 @@ fail:
        return err;
 }
 
-static int __exit menelaus_remove(struct i2c_client *client)
+static int menelaus_remove(struct i2c_client *client)
 {
        struct menelaus_chip    *menelaus = i2c_get_clientdata(client);
 
@@ -1280,7 +1257,7 @@ static struct i2c_driver menelaus_i2c_driver = {
                .name           = DRIVER_NAME,
        },
        .probe          = menelaus_probe,
-       .remove         = __exit_p(menelaus_remove),
+       .remove         = menelaus_remove,
        .id_table       = menelaus_id,
 };
 
index 2a87f69be53db0a4ca1951fd7cbc3d7733e44007..1aed3b7b8d9be1e965904a0cd4f7923a2310de2e 100644 (file)
@@ -128,7 +128,7 @@ static int mfd_add_device(struct device *parent, int id,
        int platform_id;
        int r;
 
-       if (id < 0)
+       if (id == PLATFORM_DEVID_AUTO)
                platform_id = id;
        else
                platform_id = id + cell->id;
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
new file mode 100644 (file)
index 0000000..09bc780
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/mt6397/core.h>
+#include <linux/mfd/mt6397/registers.h>
+
+static const struct mfd_cell mt6397_devs[] = {
+       {
+               .name = "mt6397-rtc",
+               .of_compatible = "mediatek,mt6397-rtc",
+       }, {
+               .name = "mt6397-regulator",
+               .of_compatible = "mediatek,mt6397-regulator",
+       }, {
+               .name = "mt6397-codec",
+               .of_compatible = "mediatek,mt6397-codec",
+       }, {
+               .name = "mt6397-clk",
+               .of_compatible = "mediatek,mt6397-clk",
+       },
+};
+
+static void mt6397_irq_lock(struct irq_data *data)
+{
+       struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
+
+       mutex_lock(&mt6397->irqlock);
+}
+
+static void mt6397_irq_sync_unlock(struct irq_data *data)
+{
+       struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
+
+       regmap_write(mt6397->regmap, MT6397_INT_CON0, mt6397->irq_masks_cur[0]);
+       regmap_write(mt6397->regmap, MT6397_INT_CON1, mt6397->irq_masks_cur[1]);
+
+       mutex_unlock(&mt6397->irqlock);
+}
+
+static void mt6397_irq_disable(struct irq_data *data)
+{
+       struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
+       int shift = data->hwirq & 0xf;
+       int reg = data->hwirq >> 4;
+
+       mt6397->irq_masks_cur[reg] &= ~BIT(shift);
+}
+
+static void mt6397_irq_enable(struct irq_data *data)
+{
+       struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
+       int shift = data->hwirq & 0xf;
+       int reg = data->hwirq >> 4;
+
+       mt6397->irq_masks_cur[reg] |= BIT(shift);
+}
+
+static struct irq_chip mt6397_irq_chip = {
+       .name = "mt6397-irq",
+       .irq_bus_lock = mt6397_irq_lock,
+       .irq_bus_sync_unlock = mt6397_irq_sync_unlock,
+       .irq_enable = mt6397_irq_enable,
+       .irq_disable = mt6397_irq_disable,
+};
+
+static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
+               int irqbase)
+{
+       unsigned int status;
+       int i, irq, ret;
+
+       ret = regmap_read(mt6397->regmap, reg, &status);
+       if (ret) {
+               dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
+               return;
+       }
+
+       for (i = 0; i < 16; i++) {
+               if (status & BIT(i)) {
+                       irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
+                       if (irq)
+                               handle_nested_irq(irq);
+               }
+       }
+
+       regmap_write(mt6397->regmap, reg, status);
+}
+
+static irqreturn_t mt6397_irq_thread(int irq, void *data)
+{
+       struct mt6397_chip *mt6397 = data;
+
+       mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS0, 0);
+       mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS1, 16);
+
+       return IRQ_HANDLED;
+}
+
+static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
+                                       irq_hw_number_t hw)
+{
+       struct mt6397_chip *mt6397 = d->host_data;
+
+       irq_set_chip_data(irq, mt6397);
+       irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
+       irq_set_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+       set_irq_flags(irq, IRQF_VALID);
+#else
+       irq_set_noprobe(irq);
+#endif
+
+       return 0;
+}
+
+static struct irq_domain_ops mt6397_irq_domain_ops = {
+       .map = mt6397_irq_domain_map,
+};
+
+static int mt6397_irq_init(struct mt6397_chip *mt6397)
+{
+       int ret;
+
+       mutex_init(&mt6397->irqlock);
+
+       /* Mask all interrupt sources */
+       regmap_write(mt6397->regmap, MT6397_INT_CON0, 0x0);
+       regmap_write(mt6397->regmap, MT6397_INT_CON1, 0x0);
+
+       mt6397->irq_domain = irq_domain_add_linear(mt6397->dev->of_node,
+               MT6397_IRQ_NR, &mt6397_irq_domain_ops, mt6397);
+       if (!mt6397->irq_domain) {
+               dev_err(mt6397->dev, "could not create irq domain\n");
+               return -ENOMEM;
+       }
+
+       ret = devm_request_threaded_irq(mt6397->dev, mt6397->irq, NULL,
+               mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", mt6397);
+       if (ret) {
+               dev_err(mt6397->dev, "failed to register irq=%d; err: %d\n",
+                       mt6397->irq, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int mt6397_probe(struct platform_device *pdev)
+{
+       int ret;
+       struct mt6397_chip *mt6397;
+
+       mt6397 = devm_kzalloc(&pdev->dev, sizeof(*mt6397), GFP_KERNEL);
+       if (!mt6397)
+               return -ENOMEM;
+
+       mt6397->dev = &pdev->dev;
+       /*
+        * mt6397 MFD is child device of soc pmic wrapper.
+        * Regmap is set from its parent.
+        */
+       mt6397->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+       if (!mt6397->regmap)
+               return -ENODEV;
+
+       platform_set_drvdata(pdev, mt6397);
+
+       mt6397->irq = platform_get_irq(pdev, 0);
+       if (mt6397->irq > 0) {
+               ret = mt6397_irq_init(mt6397);
+               if (ret)
+                       return ret;
+       }
+
+       ret = mfd_add_devices(&pdev->dev, -1, mt6397_devs,
+                       ARRAY_SIZE(mt6397_devs), NULL, 0, NULL);
+       if (ret)
+               dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
+
+       return ret;
+}
+
+static int mt6397_remove(struct platform_device *pdev)
+{
+       mfd_remove_devices(&pdev->dev);
+
+       return 0;
+}
+
+static const struct of_device_id mt6397_of_match[] = {
+       { .compatible = "mediatek,mt6397" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, mt6397_of_match);
+
+static struct platform_driver mt6397_driver = {
+       .probe = mt6397_probe,
+       .remove = mt6397_remove,
+       .driver = {
+               .name = "mt6397",
+               .of_match_table = of_match_ptr(mt6397_of_match),
+       },
+};
+
+module_platform_driver(mt6397_driver);
+
+MODULE_AUTHOR("Flora Fu, MediaTek");
+MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mt6397");
index 4b8beb2a1579c77e35943fc8859815c1c652f9c4..af6ac1c4b45c6817e88ddfa965cf68c114e6aeea 100644 (file)
 #include <linux/regmap.h>
 #include <linux/of_platform.h>
 
+#define PMIC_REV2              0x101
+#define PMIC_REV3              0x102
+#define PMIC_REV4              0x103
+#define PMIC_TYPE              0x104
+#define PMIC_SUBTYPE           0x105
+
+#define PMIC_TYPE_VALUE                0x51
+
+#define COMMON_SUBTYPE         0x00
+#define PM8941_SUBTYPE         0x01
+#define PM8841_SUBTYPE         0x02
+#define PM8019_SUBTYPE         0x03
+#define PM8226_SUBTYPE         0x04
+#define PM8110_SUBTYPE         0x05
+#define PMA8084_SUBTYPE                0x06
+#define PMI8962_SUBTYPE                0x07
+#define PMD9635_SUBTYPE                0x08
+#define PM8994_SUBTYPE         0x09
+#define PMI8994_SUBTYPE                0x0a
+#define PM8916_SUBTYPE         0x0b
+#define PM8004_SUBTYPE         0x0c
+#define PM8909_SUBTYPE         0x0d
+
+static const struct of_device_id pmic_spmi_id_table[] = {
+       { .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE },
+       { .compatible = "qcom,pm8941",    .data = (void *)PM8941_SUBTYPE },
+       { .compatible = "qcom,pm8841",    .data = (void *)PM8841_SUBTYPE },
+       { .compatible = "qcom,pm8019",    .data = (void *)PM8019_SUBTYPE },
+       { .compatible = "qcom,pm8226",    .data = (void *)PM8226_SUBTYPE },
+       { .compatible = "qcom,pm8110",    .data = (void *)PM8110_SUBTYPE },
+       { .compatible = "qcom,pma8084",   .data = (void *)PMA8084_SUBTYPE },
+       { .compatible = "qcom,pmi8962",   .data = (void *)PMI8962_SUBTYPE },
+       { .compatible = "qcom,pmd9635",   .data = (void *)PMD9635_SUBTYPE },
+       { .compatible = "qcom,pm8994",    .data = (void *)PM8994_SUBTYPE },
+       { .compatible = "qcom,pmi8994",   .data = (void *)PMI8994_SUBTYPE },
+       { .compatible = "qcom,pm8916",    .data = (void *)PM8916_SUBTYPE },
+       { .compatible = "qcom,pm8004",    .data = (void *)PM8004_SUBTYPE },
+       { .compatible = "qcom,pm8909",    .data = (void *)PM8909_SUBTYPE },
+       { }
+};
+
+static void pmic_spmi_show_revid(struct regmap *map, struct device *dev)
+{
+       unsigned int rev2, minor, major, type, subtype;
+       const char *name = "unknown";
+       int ret, i;
+
+       ret = regmap_read(map, PMIC_TYPE, &type);
+       if (ret < 0)
+               return;
+
+       if (type != PMIC_TYPE_VALUE)
+               return;
+
+       ret = regmap_read(map, PMIC_SUBTYPE, &subtype);
+       if (ret < 0)
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(pmic_spmi_id_table); i++) {
+               if (subtype == (unsigned long)pmic_spmi_id_table[i].data)
+                       break;
+       }
+
+       if (i != ARRAY_SIZE(pmic_spmi_id_table))
+               name = pmic_spmi_id_table[i].compatible;
+
+       ret = regmap_read(map, PMIC_REV2, &rev2);
+       if (ret < 0)
+               return;
+
+       ret = regmap_read(map, PMIC_REV3, &minor);
+       if (ret < 0)
+               return;
+
+       ret = regmap_read(map, PMIC_REV4, &major);
+       if (ret < 0)
+               return;
+
+       /*
+        * In early versions of PM8941 and PM8226, the major revision number
+        * started incrementing from 0 (eg 0 = v1.0, 1 = v2.0).
+        * Increment the major revision number here if the chip is an early
+        * version of PM8941 or PM8226.
+        */
+       if ((subtype == PM8941_SUBTYPE || subtype == PM8226_SUBTYPE) &&
+           major < 0x02)
+               major++;
+
+       if (subtype == PM8110_SUBTYPE)
+               minor = rev2;
+
+       dev_dbg(dev, "%x: %s v%d.%d\n", subtype, name, major, minor);
+}
+
 static const struct regmap_config spmi_regmap_config = {
        .reg_bits       = 16,
        .val_bits       = 8,
@@ -33,6 +127,8 @@ static int pmic_spmi_probe(struct spmi_device *sdev)
        if (IS_ERR(regmap))
                return PTR_ERR(regmap);
 
+       pmic_spmi_show_revid(regmap, &sdev->dev);
+
        return of_platform_populate(root, NULL, NULL, &sdev->dev);
 }
 
@@ -41,13 +137,6 @@ static void pmic_spmi_remove(struct spmi_device *sdev)
        of_platform_depopulate(&sdev->dev);
 }
 
-static const struct of_device_id pmic_spmi_id_table[] = {
-       { .compatible = "qcom,spmi-pmic" },
-       { .compatible = "qcom,pm8941" },
-       { .compatible = "qcom,pm8841" },
-       { .compatible = "qcom,pma8084" },
-       { }
-};
 MODULE_DEVICE_TABLE(of, pmic_spmi_id_table);
 
 static struct spmi_driver pmic_spmi_driver = {
index f696328c2933ff92a787853f3cf171494bcdec16..12e324319573eb260795c84c6c04b19200764a68 100644 (file)
@@ -323,10 +323,51 @@ static const struct qcom_rpm_data msm8960_template = {
        .n_resources = ARRAY_SIZE(msm8960_rpm_resource_table),
 };
 
+static const struct qcom_rpm_resource ipq806x_rpm_resource_table[] = {
+       [QCOM_RPM_CXO_CLK] =                    { 25, 9, 5, 1 },
+       [QCOM_RPM_PXO_CLK] =                    { 26, 10, 6, 1 },
+       [QCOM_RPM_APPS_FABRIC_CLK] =            { 27, 11, 8, 1 },
+       [QCOM_RPM_SYS_FABRIC_CLK] =             { 28, 12, 9, 1 },
+       [QCOM_RPM_NSS_FABRIC_0_CLK] =           { 29, 13, 10, 1 },
+       [QCOM_RPM_DAYTONA_FABRIC_CLK] =         { 30, 14, 11, 1 },
+       [QCOM_RPM_SFPB_CLK] =                   { 31, 15, 12, 1 },
+       [QCOM_RPM_CFPB_CLK] =                   { 32, 16, 13, 1 },
+       [QCOM_RPM_NSS_FABRIC_1_CLK] =           { 33, 17, 14, 1 },
+       [QCOM_RPM_EBI1_CLK] =                   { 34, 18, 16, 1 },
+       [QCOM_RPM_APPS_FABRIC_HALT] =           { 35, 19, 18, 2 },
+       [QCOM_RPM_APPS_FABRIC_MODE] =           { 37, 20, 19, 3 },
+       [QCOM_RPM_APPS_FABRIC_IOCTL] =          { 40, 21, 20, 1 },
+       [QCOM_RPM_APPS_FABRIC_ARB] =            { 41, 22, 21, 12 },
+       [QCOM_RPM_SYS_FABRIC_HALT] =            { 53, 23, 22, 2 },
+       [QCOM_RPM_SYS_FABRIC_MODE] =            { 55, 24, 23, 3 },
+       [QCOM_RPM_SYS_FABRIC_IOCTL] =           { 58, 25, 24, 1 },
+       [QCOM_RPM_SYS_FABRIC_ARB] =             { 59, 26, 25, 30 },
+       [QCOM_RPM_MM_FABRIC_HALT] =             { 89, 27, 26, 2 },
+       [QCOM_RPM_MM_FABRIC_MODE] =             { 91, 28, 27, 3 },
+       [QCOM_RPM_MM_FABRIC_IOCTL] =            { 94, 29, 28, 1 },
+       [QCOM_RPM_MM_FABRIC_ARB] =              { 95, 30, 29, 2 },
+       [QCOM_RPM_CXO_BUFFERS] =                { 209, 33, 31, 1 },
+       [QCOM_RPM_USB_OTG_SWITCH] =             { 210, 34, 32, 1 },
+       [QCOM_RPM_HDMI_SWITCH] =                { 211, 35, 33, 1 },
+       [QCOM_RPM_DDR_DMM] =                    { 212, 36, 34, 2 },
+       [QCOM_RPM_VDDMIN_GPIO] =                { 215, 40, 39, 1 },
+       [QCOM_RPM_SMB208_S1a] =                 { 216, 41, 90, 2 },
+       [QCOM_RPM_SMB208_S1b] =                 { 218, 43, 91, 2 },
+       [QCOM_RPM_SMB208_S2a] =                 { 220, 45, 92, 2 },
+       [QCOM_RPM_SMB208_S2b] =                 { 222, 47, 93, 2 },
+};
+
+static const struct qcom_rpm_data ipq806x_template = {
+       .version = 3,
+       .resource_table = ipq806x_rpm_resource_table,
+       .n_resources = ARRAY_SIZE(ipq806x_rpm_resource_table),
+};
+
 static const struct of_device_id qcom_rpm_of_match[] = {
        { .compatible = "qcom,rpm-apq8064", .data = &apq8064_template },
        { .compatible = "qcom,rpm-msm8660", .data = &msm8660_template },
        { .compatible = "qcom,rpm-msm8960", .data = &msm8960_template },
+       { .compatible = "qcom,rpm-ipq8064", .data = &ipq806x_template },
        { }
 };
 MODULE_DEVICE_TABLE(of, qcom_rpm_of_match);
index bd02150698759d0cebe9068ecd77fa1d0716c995..4b1e4399754bf2950c5662d763e3763653137b9d 100644 (file)
@@ -89,6 +89,7 @@ static const struct rk808_reg_data pre_init_reg[] = {
        { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
        { RK808_BUCK1_CONFIG_REG, BUCK1_RATE_MASK,  BUCK_ILMIN_200MA },
        { RK808_BUCK2_CONFIG_REG, BUCK2_RATE_MASK,  BUCK_ILMIN_200MA },
+       { RK808_DCDC_UV_ACT_REG,  BUCK_UV_ACT_MASK, BUCK_UV_ACT_DISABLE},
        { RK808_VB_MON_REG,       MASK_ALL,         VB_LO_ACT |
                                                    VB_LO_SEL_3500MV },
 };
@@ -245,7 +246,7 @@ static int rk808_remove(struct i2c_client *client)
        return 0;
 }
 
-static struct of_device_id rk808_of_match[] = {
+static const struct of_device_id rk808_of_match[] = {
        { .compatible = "rockchip,rk808" },
        { },
 };
index fdd34c883d868b96df11064b86933ab9c0172c35..b3ae6592014a0214b505df0b829f670877fe9c46 100644 (file)
@@ -53,7 +53,7 @@ static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
        u8 reg3 = 0;
 
        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg1);
-       dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1);
 
        if (!rtsx_vendor_setting_valid(reg1))
                return;
@@ -65,7 +65,7 @@ static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
        pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg1);
 
        rtsx_pci_read_config_byte(pcr, PCR_SETTING_REG3, &reg3);
-       dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG3, reg3);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG3, reg3);
        pcr->sd30_drive_sel_3v3 = rtl8411_reg_to_sd30_drive_sel_3v3(reg3);
 }
 
@@ -74,7 +74,7 @@ static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr)
        u32 reg = 0;
 
        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
-       dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
 
        if (!rtsx_vendor_setting_valid(reg))
                return;
@@ -260,9 +260,8 @@ static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
                rtsx_pci_write_register(pcr, CARD_PWR_CTL,
                                BPP_POWER_MASK, BPP_POWER_OFF);
 
-               dev_dbg(&(pcr->pci->dev),
-                               "After CD deglitch, card_exist = 0x%x\n",
-                               card_exist);
+               pcr_dbg(pcr, "After CD deglitch, card_exist = 0x%x\n",
+                       card_exist);
        }
 
        if (card_exist & MS_EXIST) {
index cb04174a8924b0279fccb697706f9227b6869e15..373e253c33df945544a9c6ce6caac564d1647bbc 100644 (file)
@@ -38,7 +38,7 @@ static void rts5209_fetch_vendor_settings(struct rtsx_pcr *pcr)
        u32 reg;
 
        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
-       dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
 
        if (rts5209_vendor_setting1_valid(reg)) {
                if (rts5209_reg_check_ms_pmos(reg))
@@ -47,7 +47,7 @@ static void rts5209_fetch_vendor_settings(struct rtsx_pcr *pcr)
        }
 
        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
-       dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
 
        if (rts5209_vendor_setting2_valid(reg)) {
                pcr->sd30_drive_sel_1v8 =
index 32407404d838f20c26977cee722c3876ccf9fd59..ce012d78ce2a0fe45ac78e52c6d17bb0a91f8632 100644 (file)
@@ -63,7 +63,7 @@ static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr)
        u32 reg;
 
        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
-       dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
 
        if (!rtsx_vendor_setting_valid(reg))
                return;
@@ -74,7 +74,7 @@ static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr)
        pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
 
        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
-       dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
        pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
        if (rtsx_reg_check_reverse_socket(reg))
                pcr->flags |= PCR_REVERSE_SOCKET;
@@ -118,11 +118,9 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
        rts5227_fill_driving(pcr, OUTPUT_3V3);
        /* Configure force_clock_req */
        if (pcr->flags & PCR_REVERSE_SOCKET)
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
-                               AUTOLOAD_CFG_BASE + 3, 0xB8, 0xB8);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0xB8);
        else
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
-                               AUTOLOAD_CFG_BASE + 3, 0xB8, 0x88);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0x88);
        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00);
 
        return rtsx_pci_send_cmd(pcr, 100);
@@ -132,7 +130,7 @@ static int rts5227_optimize_phy(struct rtsx_pcr *pcr)
 {
        int err;
 
-       err = rtsx_gops_pm_reset(pcr);
+       err = rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
        if (err < 0)
                return err;
 
index 6353f5df087aa41bb11653b69593ea3eb56abd8b..ace45384ec8bc2893f9c1ff2bb4ea6cb027e2a23 100644 (file)
@@ -38,7 +38,7 @@ static void rts5229_fetch_vendor_settings(struct rtsx_pcr *pcr)
        u32 reg;
 
        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
-       dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
 
        if (!rtsx_vendor_setting_valid(reg))
                return;
@@ -50,7 +50,7 @@ static void rts5229_fetch_vendor_settings(struct rtsx_pcr *pcr)
        pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
 
        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
-       dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
        pcr->sd30_drive_sel_3v3 =
                map_sd_drive(rtsx_reg_to_sd30_drive_sel_3v3(reg));
 }
index cf425cc959d5dfb64b1bf6179ceb64e03b051d28..eb2d5866f7195296999b5d9afb11ae2eb707d862 100644 (file)
@@ -36,16 +36,16 @@ static u8 rts5249_get_ic_version(struct rtsx_pcr *pcr)
 static void rts5249_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
 {
        u8 driving_3v3[4][3] = {
-               {0x11, 0x11, 0x11},
+               {0x11, 0x11, 0x18},
                {0x55, 0x55, 0x5C},
-               {0x99, 0x99, 0x92},
-               {0x99, 0x99, 0x92},
+               {0xFF, 0xFF, 0xFF},
+               {0x96, 0x96, 0x96},
        };
        u8 driving_1v8[4][3] = {
+               {0xC4, 0xC4, 0xC4},
                {0x3C, 0x3C, 0x3C},
-               {0xB3, 0xB3, 0xB3},
                {0xFE, 0xFE, 0xFE},
-               {0xC4, 0xC4, 0xC4},
+               {0xB3, 0xB3, 0xB3},
        };
        u8 (*driving)[3], drive_sel;
 
@@ -65,15 +65,17 @@ static void rts5249_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
                        0xFF, driving[drive_sel][2]);
 }
 
-static void rts5249_fetch_vendor_settings(struct rtsx_pcr *pcr)
+static void rtsx_base_fetch_vendor_settings(struct rtsx_pcr *pcr)
 {
        u32 reg;
 
        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
-       dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
 
-       if (!rtsx_vendor_setting_valid(reg))
+       if (!rtsx_vendor_setting_valid(reg)) {
+               pcr_dbg(pcr, "skip fetch vendor setting\n");
                return;
+       }
 
        pcr->aspm_en = rtsx_reg_to_aspm(reg);
        pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg);
@@ -81,13 +83,13 @@ static void rts5249_fetch_vendor_settings(struct rtsx_pcr *pcr)
        pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
 
        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
-       dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
        pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
        if (rtsx_reg_check_reverse_socket(reg))
                pcr->flags |= PCR_REVERSE_SOCKET;
 }
 
-static void rts5249_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
+static void rtsx_base_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
 {
        /* Set relink_time to 0 */
        rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0);
@@ -95,7 +97,8 @@ static void rts5249_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
        rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0);
 
        if (pm_state == HOST_ENTER_S3)
-               rtsx_pci_write_register(pcr, PM_CTRL3, 0x10, 0x10);
+               rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3,
+                       D3_DELINK_MODE_EN, D3_DELINK_MODE_EN);
 
        rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
 }
@@ -104,6 +107,8 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
 {
        rtsx_pci_init_cmd(pcr);
 
+       /* Rest L1SUB Config */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, L1SUB_CONFIG3, 0xFF, 0x00);
        /* Configure GPIO as output */
        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
        /* Reset ASPM state to default value */
@@ -116,12 +121,9 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
        /* Configure driving */
        rts5249_fill_driving(pcr, OUTPUT_3V3);
        if (pcr->flags & PCR_REVERSE_SOCKET)
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
-                               AUTOLOAD_CFG_BASE + 3, 0xB0, 0xB0);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0xB0);
        else
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
-                               AUTOLOAD_CFG_BASE + 3, 0xB0, 0x80);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0x80);
 
        return rtsx_pci_send_cmd(pcr, 100);
 }
@@ -130,15 +132,16 @@ static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
 {
        int err;
 
-       err = rtsx_gops_pm_reset(pcr);
+       err = rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
        if (err < 0)
                return err;
 
-       err = rtsx_pci_write_phy_register(pcr, PHY_REG_REV,
-                       PHY_REG_REV_RESV | PHY_REG_REV_RXIDLE_LATCHED |
-                       PHY_REG_REV_P1_EN | PHY_REG_REV_RXIDLE_EN |
-                       PHY_REG_REV_RX_PWST | PHY_REG_REV_CLKREQ_DLY_TIMER_1_0 |
-                       PHY_REG_REV_STOP_CLKRD | PHY_REG_REV_STOP_CLKWR);
+       err = rtsx_pci_write_phy_register(pcr, PHY_REV,
+                       PHY_REV_RESV | PHY_REV_RXIDLE_LATCHED |
+                       PHY_REV_P1_EN | PHY_REV_RXIDLE_EN |
+                       PHY_REV_CLKREQ_TX_EN | PHY_REV_RX_PWST |
+                       PHY_REV_CLKREQ_DT_1_0 | PHY_REV_STOP_CLKRD |
+                       PHY_REV_STOP_CLKWR);
        if (err < 0)
                return err;
 
@@ -149,19 +152,21 @@ static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
                        PHY_BPCR_IB_FILTER | PHY_BPCR_CMIRROR_EN);
        if (err < 0)
                return err;
+
        err = rtsx_pci_write_phy_register(pcr, PHY_PCR,
                        PHY_PCR_FORCE_CODE | PHY_PCR_OOBS_CALI_50 |
                        PHY_PCR_OOBS_VCM_08 | PHY_PCR_OOBS_SEN_90 |
-                       PHY_PCR_RSSI_EN);
+                       PHY_PCR_RSSI_EN | PHY_PCR_RX10K);
        if (err < 0)
                return err;
+
        err = rtsx_pci_write_phy_register(pcr, PHY_RCR2,
                        PHY_RCR2_EMPHASE_EN | PHY_RCR2_NADJR |
-                       PHY_RCR2_CDR_CP_10 | PHY_RCR2_CDR_SR_2 |
-                       PHY_RCR2_FREQSEL_12 | PHY_RCR2_CPADJEN |
-                       PHY_RCR2_CDR_SC_8 | PHY_RCR2_CALIB_LATE);
+                       PHY_RCR2_CDR_SR_2 | PHY_RCR2_FREQSEL_12 |
+                       PHY_RCR2_CDR_SC_12P | PHY_RCR2_CALIB_LATE);
        if (err < 0)
                return err;
+
        err = rtsx_pci_write_phy_register(pcr, PHY_FLD4,
                        PHY_FLD4_FLDEN_SEL | PHY_FLD4_REQ_REF |
                        PHY_FLD4_RXAMP_OFF | PHY_FLD4_REQ_ADDA |
@@ -169,11 +174,12 @@ static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
                        PHY_FLD4_BER_CHK_EN);
        if (err < 0)
                return err;
-       err = rtsx_pci_write_phy_register(pcr, PHY_RDR, PHY_RDR_RXDSEL_1_9);
+       err = rtsx_pci_write_phy_register(pcr, PHY_RDR,
+                       PHY_RDR_RXDSEL_1_9 | PHY_SSC_AUTO_PWD);
        if (err < 0)
                return err;
        err = rtsx_pci_write_phy_register(pcr, PHY_RCR1,
-                       PHY_RCR1_ADP_TIME | PHY_RCR1_VCO_COARSE);
+                       PHY_RCR1_ADP_TIME_4 | PHY_RCR1_VCO_COARSE);
        if (err < 0)
                return err;
        err = rtsx_pci_write_phy_register(pcr, PHY_FLD3,
@@ -181,33 +187,34 @@ static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
                        PHY_FLD3_RXDELINK);
        if (err < 0)
                return err;
+
        return rtsx_pci_write_phy_register(pcr, PHY_TUNE,
                        PHY_TUNE_TUNEREF_1_0 | PHY_TUNE_VBGSEL_1252 |
                        PHY_TUNE_SDBUS_33 | PHY_TUNE_TUNED18 |
-                       PHY_TUNE_TUNED12);
+                       PHY_TUNE_TUNED12 | PHY_TUNE_TUNEA12);
 }
 
-static int rts5249_turn_on_led(struct rtsx_pcr *pcr)
+static int rtsx_base_turn_on_led(struct rtsx_pcr *pcr)
 {
        return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
 }
 
-static int rts5249_turn_off_led(struct rtsx_pcr *pcr)
+static int rtsx_base_turn_off_led(struct rtsx_pcr *pcr)
 {
        return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
 }
 
-static int rts5249_enable_auto_blink(struct rtsx_pcr *pcr)
+static int rtsx_base_enable_auto_blink(struct rtsx_pcr *pcr)
 {
        return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
 }
 
-static int rts5249_disable_auto_blink(struct rtsx_pcr *pcr)
+static int rtsx_base_disable_auto_blink(struct rtsx_pcr *pcr)
 {
        return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
 }
 
-static int rts5249_card_power_on(struct rtsx_pcr *pcr, int card)
+static int rtsx_base_card_power_on(struct rtsx_pcr *pcr, int card)
 {
        int err;
 
@@ -234,7 +241,7 @@ static int rts5249_card_power_on(struct rtsx_pcr *pcr, int card)
        return 0;
 }
 
-static int rts5249_card_power_off(struct rtsx_pcr *pcr, int card)
+static int rtsx_base_card_power_off(struct rtsx_pcr *pcr, int card)
 {
        rtsx_pci_init_cmd(pcr);
        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
@@ -244,22 +251,35 @@ static int rts5249_card_power_off(struct rtsx_pcr *pcr, int card)
        return rtsx_pci_send_cmd(pcr, 100);
 }
 
-static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+static int rtsx_base_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
 {
        int err;
+       u16 append;
 
-       if (voltage == OUTPUT_3V3) {
-               err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4FC0 | 0x24);
+       switch (voltage) {
+       case OUTPUT_3V3:
+               err = rtsx_pci_update_phy(pcr, PHY_TUNE, PHY_TUNE_VOLTAGE_MASK,
+                       PHY_TUNE_VOLTAGE_3V3);
                if (err < 0)
                        return err;
-       } else if (voltage == OUTPUT_1V8) {
-               err = rtsx_pci_write_phy_register(pcr, PHY_BACR, 0x3C02);
+               break;
+       case OUTPUT_1V8:
+               append = PHY_TUNE_D18_1V8;
+               if (CHK_PCI_PID(pcr, 0x5249)) {
+                       err = rtsx_pci_update_phy(pcr, PHY_BACR,
+                               PHY_BACR_BASIC_MASK, 0);
+                       if (err < 0)
+                               return err;
+                       append = PHY_TUNE_D18_1V7;
+               }
+
+               err = rtsx_pci_update_phy(pcr, PHY_TUNE, PHY_TUNE_VOLTAGE_MASK,
+                       append);
                if (err < 0)
                        return err;
-               err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4C40 | 0x24);
-               if (err < 0)
-                       return err;
-       } else {
+               break;
+       default:
+               pcr_dbg(pcr, "unknown output voltage %d\n", voltage);
                return -EINVAL;
        }
 
@@ -270,17 +290,17 @@ static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
 }
 
 static const struct pcr_ops rts5249_pcr_ops = {
-       .fetch_vendor_settings = rts5249_fetch_vendor_settings,
+       .fetch_vendor_settings = rtsx_base_fetch_vendor_settings,
        .extra_init_hw = rts5249_extra_init_hw,
        .optimize_phy = rts5249_optimize_phy,
-       .turn_on_led = rts5249_turn_on_led,
-       .turn_off_led = rts5249_turn_off_led,
-       .enable_auto_blink = rts5249_enable_auto_blink,
-       .disable_auto_blink = rts5249_disable_auto_blink,
-       .card_power_on = rts5249_card_power_on,
-       .card_power_off = rts5249_card_power_off,
-       .switch_output_voltage = rts5249_switch_output_voltage,
-       .force_power_down = rts5249_force_power_down,
+       .turn_on_led = rtsx_base_turn_on_led,
+       .turn_off_led = rtsx_base_turn_off_led,
+       .enable_auto_blink = rtsx_base_enable_auto_blink,
+       .disable_auto_blink = rtsx_base_disable_auto_blink,
+       .card_power_on = rtsx_base_card_power_on,
+       .card_power_off = rtsx_base_card_power_off,
+       .switch_output_voltage = rtsx_base_switch_output_voltage,
+       .force_power_down = rtsx_base_force_power_down,
 };
 
 /* SD Pull Control Enable:
@@ -343,7 +363,7 @@ void rts5249_init_params(struct rtsx_pcr *pcr)
 
        pcr->flags = 0;
        pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
-       pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_C;
+       pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;
        pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
        pcr->aspm_en = ASPM_L1_EN;
        pcr->tx_initial_phase = SET_CLOCK_PHASE(1, 29, 16);
@@ -354,4 +374,219 @@ void rts5249_init_params(struct rtsx_pcr *pcr)
        pcr->sd_pull_ctl_disable_tbl = rts5249_sd_pull_ctl_disable_tbl;
        pcr->ms_pull_ctl_enable_tbl = rts5249_ms_pull_ctl_enable_tbl;
        pcr->ms_pull_ctl_disable_tbl = rts5249_ms_pull_ctl_disable_tbl;
+
+       pcr->reg_pm_ctrl3 = PM_CTRL3;
+}
+
+static int rts524a_write_phy(struct rtsx_pcr *pcr, u8 addr, u16 val)
+{
+       addr = addr & 0x80 ? (addr & 0x7F) | 0x40 : addr;
+
+       return __rtsx_pci_write_phy_register(pcr, addr, val);
+}
+
+static int rts524a_read_phy(struct rtsx_pcr *pcr, u8 addr, u16 *val)
+{
+       addr = addr & 0x80 ? (addr & 0x7F) | 0x40 : addr;
+
+       return __rtsx_pci_read_phy_register(pcr, addr, val);
 }
+
+static int rts524a_optimize_phy(struct rtsx_pcr *pcr)
+{
+       int err;
+
+       err = rtsx_pci_write_register(pcr, RTS524A_PM_CTRL3,
+               D3_DELINK_MODE_EN, 0x00);
+       if (err < 0)
+               return err;
+
+       rtsx_pci_write_phy_register(pcr, PHY_PCR,
+               PHY_PCR_FORCE_CODE | PHY_PCR_OOBS_CALI_50 |
+               PHY_PCR_OOBS_VCM_08 | PHY_PCR_OOBS_SEN_90 | PHY_PCR_RSSI_EN);
+       rtsx_pci_write_phy_register(pcr, PHY_SSCCR3,
+               PHY_SSCCR3_STEP_IN | PHY_SSCCR3_CHECK_DELAY);
+
+       if (is_version(pcr, 0x524A, IC_VER_A)) {
+               rtsx_pci_write_phy_register(pcr, PHY_SSCCR3,
+                       PHY_SSCCR3_STEP_IN | PHY_SSCCR3_CHECK_DELAY);
+               rtsx_pci_write_phy_register(pcr, PHY_SSCCR2,
+                       PHY_SSCCR2_PLL_NCODE | PHY_SSCCR2_TIME0 |
+                       PHY_SSCCR2_TIME2_WIDTH);
+               rtsx_pci_write_phy_register(pcr, PHY_ANA1A,
+                       PHY_ANA1A_TXR_LOOPBACK | PHY_ANA1A_RXT_BIST |
+                       PHY_ANA1A_TXR_BIST | PHY_ANA1A_REV);
+               rtsx_pci_write_phy_register(pcr, PHY_ANA1D,
+                       PHY_ANA1D_DEBUG_ADDR);
+               rtsx_pci_write_phy_register(pcr, PHY_DIG1E,
+                       PHY_DIG1E_REV | PHY_DIG1E_D0_X_D1 |
+                       PHY_DIG1E_RX_ON_HOST | PHY_DIG1E_RCLK_REF_HOST |
+                       PHY_DIG1E_RCLK_TX_EN_KEEP |
+                       PHY_DIG1E_RCLK_TX_TERM_KEEP |
+                       PHY_DIG1E_RCLK_RX_EIDLE_ON | PHY_DIG1E_TX_TERM_KEEP |
+                       PHY_DIG1E_RX_TERM_KEEP | PHY_DIG1E_TX_EN_KEEP |
+                       PHY_DIG1E_RX_EN_KEEP);
+       }
+
+       rtsx_pci_write_phy_register(pcr, PHY_ANA08,
+               PHY_ANA08_RX_EQ_DCGAIN | PHY_ANA08_SEL_RX_EN |
+               PHY_ANA08_RX_EQ_VAL | PHY_ANA08_SCP | PHY_ANA08_SEL_IPI);
+
+       return 0;
+}
+
+static int rts524a_extra_init_hw(struct rtsx_pcr *pcr)
+{
+       rts5249_extra_init_hw(pcr);
+
+       rtsx_pci_write_register(pcr, FUNC_FORCE_CTL,
+               FORCE_ASPM_L1_EN, FORCE_ASPM_L1_EN);
+       rtsx_pci_write_register(pcr, PM_EVENT_DEBUG, PME_DEBUG_0, PME_DEBUG_0);
+       rtsx_pci_write_register(pcr, LDO_VCC_CFG1, LDO_VCC_LMT_EN,
+               LDO_VCC_LMT_EN);
+       rtsx_pci_write_register(pcr, PCLK_CTL, PCLK_MODE_SEL, PCLK_MODE_SEL);
+       if (is_version(pcr, 0x524A, IC_VER_A)) {
+               rtsx_pci_write_register(pcr, LDO_DV18_CFG,
+                       LDO_DV18_SR_MASK, LDO_DV18_SR_DF);
+               rtsx_pci_write_register(pcr, LDO_VCC_CFG1,
+                       LDO_VCC_REF_TUNE_MASK, LDO_VCC_REF_1V2);
+               rtsx_pci_write_register(pcr, LDO_VIO_CFG,
+                       LDO_VIO_REF_TUNE_MASK, LDO_VIO_REF_1V2);
+               rtsx_pci_write_register(pcr, LDO_VIO_CFG,
+                       LDO_VIO_SR_MASK, LDO_VIO_SR_DF);
+               rtsx_pci_write_register(pcr, LDO_DV12S_CFG,
+                       LDO_REF12_TUNE_MASK, LDO_REF12_TUNE_DF);
+               rtsx_pci_write_register(pcr, SD40_LDO_CTL1,
+                       SD40_VIO_TUNE_MASK, SD40_VIO_TUNE_1V7);
+       }
+
+       return 0;
+}
+
+static const struct pcr_ops rts524a_pcr_ops = {
+       .write_phy = rts524a_write_phy,
+       .read_phy = rts524a_read_phy,
+       .fetch_vendor_settings = rtsx_base_fetch_vendor_settings,
+       .extra_init_hw = rts524a_extra_init_hw,
+       .optimize_phy = rts524a_optimize_phy,
+       .turn_on_led = rtsx_base_turn_on_led,
+       .turn_off_led = rtsx_base_turn_off_led,
+       .enable_auto_blink = rtsx_base_enable_auto_blink,
+       .disable_auto_blink = rtsx_base_disable_auto_blink,
+       .card_power_on = rtsx_base_card_power_on,
+       .card_power_off = rtsx_base_card_power_off,
+       .switch_output_voltage = rtsx_base_switch_output_voltage,
+       .force_power_down = rtsx_base_force_power_down,
+};
+
+void rts524a_init_params(struct rtsx_pcr *pcr)
+{
+       rts5249_init_params(pcr);
+
+       pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3;
+       pcr->ops = &rts524a_pcr_ops;
+}
+
+static int rts525a_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+       rtsx_pci_write_register(pcr, LDO_VCC_CFG1,
+               LDO_VCC_TUNE_MASK, LDO_VCC_3V3);
+       return rtsx_base_card_power_on(pcr, card);
+}
+
+static int rts525a_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+       switch (voltage) {
+       case OUTPUT_3V3:
+               rtsx_pci_write_register(pcr, LDO_CONFIG2,
+                       LDO_D3318_MASK, LDO_D3318_33V);
+               rtsx_pci_write_register(pcr, SD_PAD_CTL, SD_IO_USING_1V8, 0);
+               break;
+       case OUTPUT_1V8:
+               rtsx_pci_write_register(pcr, LDO_CONFIG2,
+                       LDO_D3318_MASK, LDO_D3318_18V);
+               rtsx_pci_write_register(pcr, SD_PAD_CTL, SD_IO_USING_1V8,
+                       SD_IO_USING_1V8);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       rtsx_pci_init_cmd(pcr);
+       rts5249_fill_driving(pcr, voltage);
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts525a_optimize_phy(struct rtsx_pcr *pcr)
+{
+       int err;
+
+       err = rtsx_pci_write_register(pcr, RTS524A_PM_CTRL3,
+               D3_DELINK_MODE_EN, 0x00);
+       if (err < 0)
+               return err;
+
+       rtsx_pci_write_phy_register(pcr, _PHY_FLD0,
+               _PHY_FLD0_CLK_REQ_20C | _PHY_FLD0_RX_IDLE_EN |
+               _PHY_FLD0_BIT_ERR_RSTN | _PHY_FLD0_BER_COUNT |
+               _PHY_FLD0_BER_TIMER | _PHY_FLD0_CHECK_EN);
+
+       rtsx_pci_write_phy_register(pcr, _PHY_ANA03,
+               _PHY_ANA03_TIMER_MAX | _PHY_ANA03_OOBS_DEB_EN |
+               _PHY_CMU_DEBUG_EN);
+
+       if (is_version(pcr, 0x525A, IC_VER_A))
+               rtsx_pci_write_phy_register(pcr, _PHY_REV0,
+                       _PHY_REV0_FILTER_OUT | _PHY_REV0_CDR_BYPASS_PFD |
+                       _PHY_REV0_CDR_RX_IDLE_BYPASS);
+
+       return 0;
+}
+
+static int rts525a_extra_init_hw(struct rtsx_pcr *pcr)
+{
+       rts5249_extra_init_hw(pcr);
+
+       rtsx_pci_write_register(pcr, PCLK_CTL, PCLK_MODE_SEL, PCLK_MODE_SEL);
+       if (is_version(pcr, 0x525A, IC_VER_A)) {
+               rtsx_pci_write_register(pcr, L1SUB_CONFIG2,
+                       L1SUB_AUTO_CFG, L1SUB_AUTO_CFG);
+               rtsx_pci_write_register(pcr, RREF_CFG,
+                       RREF_VBGSEL_MASK, RREF_VBGSEL_1V25);
+               rtsx_pci_write_register(pcr, LDO_VIO_CFG,
+                       LDO_VIO_TUNE_MASK, LDO_VIO_1V7);
+               rtsx_pci_write_register(pcr, LDO_DV12S_CFG,
+                       LDO_D12_TUNE_MASK, LDO_D12_TUNE_DF);
+               rtsx_pci_write_register(pcr, LDO_AV12S_CFG,
+                       LDO_AV12S_TUNE_MASK, LDO_AV12S_TUNE_DF);
+               rtsx_pci_write_register(pcr, LDO_VCC_CFG0,
+                       LDO_VCC_LMTVTH_MASK, LDO_VCC_LMTVTH_2A);
+               rtsx_pci_write_register(pcr, OOBS_CONFIG,
+                       OOBS_AUTOK_DIS | OOBS_VAL_MASK, 0x89);
+       }
+
+       return 0;
+}
+
+static const struct pcr_ops rts525a_pcr_ops = {
+       .fetch_vendor_settings = rtsx_base_fetch_vendor_settings,
+       .extra_init_hw = rts525a_extra_init_hw,
+       .optimize_phy = rts525a_optimize_phy,
+       .turn_on_led = rtsx_base_turn_on_led,
+       .turn_off_led = rtsx_base_turn_off_led,
+       .enable_auto_blink = rtsx_base_enable_auto_blink,
+       .disable_auto_blink = rtsx_base_disable_auto_blink,
+       .card_power_on = rts525a_card_power_on,
+       .card_power_off = rtsx_base_card_power_off,
+       .switch_output_voltage = rts525a_switch_output_voltage,
+       .force_power_down = rtsx_base_force_power_down,
+};
+
+void rts525a_init_params(struct rtsx_pcr *pcr)
+{
+       rts5249_init_params(pcr);
+
+       pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3;
+       pcr->ops = &rts525a_pcr_ops;
+}
+
diff --git a/drivers/mfd/rtsx_gops.c b/drivers/mfd/rtsx_gops.c
deleted file mode 100644 (file)
index b1a98c6..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. 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, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- *   Micky Ching <micky_ching@realsil.com.cn>
- */
-
-#include <linux/mfd/rtsx_pci.h>
-#include "rtsx_pcr.h"
-
-int rtsx_gops_pm_reset(struct rtsx_pcr *pcr)
-{
-       int err;
-
-       /* init aspm */
-       rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0xFF, 0x00);
-       err = rtsx_pci_update_cfg_byte(pcr, LCTLR, ~LCTLR_ASPM_CTL_MASK, 0x00);
-       if (err < 0)
-               return err;
-
-       /* reset PM_CTRL3 before send buffer cmd */
-       return rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
-}
index 30f7ca89a0e68619319f69dcebb12037f6e4af92..a66540a4907995bfd7b0dec0e0511c7c090ac1b6 100644 (file)
@@ -58,11 +58,25 @@ static const struct pci_device_id rtsx_pci_ids[] = {
        { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 },
        { PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 },
        { PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { PCI_DEVICE(0x10EC, 0x524A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { PCI_DEVICE(0x10EC, 0x525A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
        { 0, }
 };
 
 MODULE_DEVICE_TABLE(pci, rtsx_pci_ids);
 
+static inline void rtsx_pci_enable_aspm(struct rtsx_pcr *pcr)
+{
+       rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL,
+               0xFC, pcr->aspm_en);
+}
+
+static inline void rtsx_pci_disable_aspm(struct rtsx_pcr *pcr)
+{
+       rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL,
+               0xFC, 0);
+}
+
 void rtsx_pci_start_run(struct rtsx_pcr *pcr)
 {
        /* If pci device removed, don't queue idle work any more */
@@ -75,7 +89,7 @@ void rtsx_pci_start_run(struct rtsx_pcr *pcr)
                        pcr->ops->enable_auto_blink(pcr);
 
                if (pcr->aspm_en)
-                       rtsx_pci_write_config_byte(pcr, LCTLR, 0);
+                       rtsx_pci_disable_aspm(pcr);
        }
 
        mod_delayed_work(system_wq, &pcr->idle_work, msecs_to_jiffies(200));
@@ -130,7 +144,7 @@ int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data)
 }
 EXPORT_SYMBOL_GPL(rtsx_pci_read_register);
 
-int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
+int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
 {
        int err, i, finished = 0;
        u8 tmp;
@@ -162,9 +176,17 @@ int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
 
        return 0;
 }
+
+int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
+{
+       if (pcr->ops->write_phy)
+               return pcr->ops->write_phy(pcr, addr, val);
+
+       return __rtsx_pci_write_phy_register(pcr, addr, val);
+}
 EXPORT_SYMBOL_GPL(rtsx_pci_write_phy_register);
 
-int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
+int __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
 {
        int err, i, finished = 0;
        u16 data;
@@ -210,6 +232,14 @@ int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
 
        return 0;
 }
+
+int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
+{
+       if (pcr->ops->read_phy)
+               return pcr->ops->read_phy(pcr, addr, val);
+
+       return __rtsx_pci_read_phy_register(pcr, addr, val);
+}
 EXPORT_SYMBOL_GPL(rtsx_pci_read_phy_register);
 
 void rtsx_pci_stop_cmd(struct rtsx_pcr *pcr)
@@ -286,8 +316,7 @@ int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout)
        timeleft = wait_for_completion_interruptible_timeout(
                        &trans_done, msecs_to_jiffies(timeout));
        if (timeleft <= 0) {
-               dev_dbg(&(pcr->pci->dev), "Timeout (%s %d)\n",
-                               __func__, __LINE__);
+               pcr_dbg(pcr, "Timeout (%s %d)\n", __func__, __LINE__);
                err = -ETIMEDOUT;
                goto finish_send_cmd;
        }
@@ -323,8 +352,7 @@ static void rtsx_pci_add_sg_tbl(struct rtsx_pcr *pcr,
        u64 val;
        u8 option = SG_VALID | SG_TRANS_DATA;
 
-       dev_dbg(&(pcr->pci->dev), "DMA addr: 0x%x, Len: 0x%x\n",
-                       (unsigned int)addr, len);
+       pcr_dbg(pcr, "DMA addr: 0x%x, Len: 0x%x\n", (unsigned int)addr, len);
 
        if (end)
                option |= SG_END;
@@ -339,11 +367,11 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
 {
        int err = 0, count;
 
-       dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg);
+       pcr_dbg(pcr, "--> %s: num_sg = %d\n", __func__, num_sg);
        count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read);
        if (count < 1)
                return -EINVAL;
-       dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
+       pcr_dbg(pcr, "DMA mapping count: %d\n", count);
 
        err = rtsx_pci_dma_transfer(pcr, sglist, count, read, timeout);
 
@@ -417,8 +445,7 @@ int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
        timeleft = wait_for_completion_interruptible_timeout(
                        &trans_done, msecs_to_jiffies(timeout));
        if (timeleft <= 0) {
-               dev_dbg(&(pcr->pci->dev), "Timeout (%s %d)\n",
-                               __func__, __LINE__);
+               pcr_dbg(pcr, "Timeout (%s %d)\n", __func__, __LINE__);
                err = -ETIMEDOUT;
                goto out;
        }
@@ -592,7 +619,7 @@ static void rtsx_pci_enable_bus_int(struct rtsx_pcr *pcr)
        /* Enable Bus Interrupt */
        rtsx_pci_writel(pcr, RTSX_BIER, pcr->bier);
 
-       dev_dbg(&(pcr->pci->dev), "RTSX_BIER: 0x%08x\n", pcr->bier);
+       pcr_dbg(pcr, "RTSX_BIER: 0x%08x\n", pcr->bier);
 }
 
 static inline u8 double_ssc_depth(u8 depth)
@@ -638,14 +665,13 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
                return err;
 
        card_clock /= 1000000;
-       dev_dbg(&(pcr->pci->dev), "Switch card clock to %dMHz\n", card_clock);
+       pcr_dbg(pcr, "Switch card clock to %dMHz\n", card_clock);
 
        clk = card_clock;
        if (!initial_mode && double_clk)
                clk = card_clock * 2;
-       dev_dbg(&(pcr->pci->dev),
-                       "Internal SSC clock: %dMHz (cur_clock = %d)\n",
-                       clk, pcr->cur_clock);
+       pcr_dbg(pcr, "Internal SSC clock: %dMHz (cur_clock = %d)\n",
+               clk, pcr->cur_clock);
 
        if (clk == pcr->cur_clock)
                return 0;
@@ -674,14 +700,14 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
                }
                div++;
        }
-       dev_dbg(&(pcr->pci->dev), "n = %d, div = %d\n", n, div);
+       pcr_dbg(pcr, "n = %d, div = %d\n", n, div);
 
        ssc_depth = depth[ssc_depth];
        if (double_clk)
                ssc_depth = double_ssc_depth(ssc_depth);
 
        ssc_depth = revise_ssc_depth(ssc_depth, div);
-       dev_dbg(&(pcr->pci->dev), "ssc_depth = %d\n", ssc_depth);
+       pcr_dbg(pcr, "ssc_depth = %d\n", ssc_depth);
 
        rtsx_pci_init_cmd(pcr);
        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
@@ -803,13 +829,13 @@ static void rtsx_pci_card_detect(struct work_struct *work)
        dwork = to_delayed_work(work);
        pcr = container_of(dwork, struct rtsx_pcr, carddet_work);
 
-       dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__);
+       pcr_dbg(pcr, "--> %s\n", __func__);
 
        mutex_lock(&pcr->pcr_mutex);
        spin_lock_irqsave(&pcr->lock, flags);
 
        irq_status = rtsx_pci_readl(pcr, RTSX_BIPR);
-       dev_dbg(&(pcr->pci->dev), "irq_status: 0x%08x\n", irq_status);
+       pcr_dbg(pcr, "irq_status: 0x%08x\n", irq_status);
 
        irq_status &= CARD_EXIST;
        card_inserted = pcr->card_inserted & irq_status;
@@ -820,9 +846,8 @@ static void rtsx_pci_card_detect(struct work_struct *work)
        spin_unlock_irqrestore(&pcr->lock, flags);
 
        if (card_inserted || card_removed) {
-               dev_dbg(&(pcr->pci->dev),
-                               "card_inserted: 0x%x, card_removed: 0x%x\n",
-                               card_inserted, card_removed);
+               pcr_dbg(pcr, "card_inserted: 0x%x, card_removed: 0x%x\n",
+                       card_inserted, card_removed);
 
                if (pcr->ops->cd_deglitch)
                        card_inserted = pcr->ops->cd_deglitch(pcr);
@@ -930,7 +955,7 @@ static void rtsx_pci_idle_work(struct work_struct *work)
        struct delayed_work *dwork = to_delayed_work(work);
        struct rtsx_pcr *pcr = container_of(dwork, struct rtsx_pcr, idle_work);
 
-       dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__);
+       pcr_dbg(pcr, "--> %s\n", __func__);
 
        mutex_lock(&pcr->pcr_mutex);
 
@@ -942,7 +967,7 @@ static void rtsx_pci_idle_work(struct work_struct *work)
                pcr->ops->turn_off_led(pcr);
 
        if (pcr->aspm_en)
-               rtsx_pci_write_config_byte(pcr, LCTLR, pcr->aspm_en);
+               rtsx_pci_enable_aspm(pcr);
 
        mutex_unlock(&pcr->pcr_mutex);
 }
@@ -968,6 +993,7 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
 {
        int err;
 
+       pcr->pcie_cap = pci_find_capability(pcr->pci, PCI_CAP_ID_EXP);
        rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
 
        rtsx_pci_enable_bus_int(pcr);
@@ -980,6 +1006,7 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
        /* Wait SSC power stable */
        udelay(200);
 
+       rtsx_pci_disable_aspm(pcr);
        if (pcr->ops->optimize_phy) {
                err = pcr->ops->optimize_phy(pcr);
                if (err < 0)
@@ -1028,10 +1055,8 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
        if (err < 0)
                return err;
 
-       rtsx_pci_write_config_byte(pcr, LCTLR, 0);
-
        /* Enable clk_request_n to enable clock power management */
-       rtsx_pci_write_config_byte(pcr, 0x81, 1);
+       rtsx_pci_write_config_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL + 1, 1);
        /* Enter L1 when host tx idle */
        rtsx_pci_write_config_byte(pcr, 0x70F, 0x5B);
 
@@ -1081,6 +1106,14 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
                rts5249_init_params(pcr);
                break;
 
+       case 0x524A:
+               rts524a_init_params(pcr);
+               break;
+
+       case 0x525A:
+               rts525a_init_params(pcr);
+               break;
+
        case 0x5287:
                rtl8411b_init_params(pcr);
                break;
@@ -1090,7 +1123,7 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
                break;
        }
 
-       dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n",
+       pcr_dbg(pcr, "PID: 0x%04x, IC version: 0x%02x\n",
                        PCI_PID(pcr), pcr->ic_version);
 
        pcr->slots = kcalloc(pcr->num_slots, sizeof(struct rtsx_slot),
@@ -1101,14 +1134,14 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
        if (pcr->ops->fetch_vendor_settings)
                pcr->ops->fetch_vendor_settings(pcr);
 
-       dev_dbg(&(pcr->pci->dev), "pcr->aspm_en = 0x%x\n", pcr->aspm_en);
-       dev_dbg(&(pcr->pci->dev), "pcr->sd30_drive_sel_1v8 = 0x%x\n",
+       pcr_dbg(pcr, "pcr->aspm_en = 0x%x\n", pcr->aspm_en);
+       pcr_dbg(pcr, "pcr->sd30_drive_sel_1v8 = 0x%x\n",
                        pcr->sd30_drive_sel_1v8);
-       dev_dbg(&(pcr->pci->dev), "pcr->sd30_drive_sel_3v3 = 0x%x\n",
+       pcr_dbg(pcr, "pcr->sd30_drive_sel_3v3 = 0x%x\n",
                        pcr->sd30_drive_sel_3v3);
-       dev_dbg(&(pcr->pci->dev), "pcr->card_drive_sel = 0x%x\n",
+       pcr_dbg(pcr, "pcr->card_drive_sel = 0x%x\n",
                        pcr->card_drive_sel);
-       dev_dbg(&(pcr->pci->dev), "pcr->flags = 0x%x\n", pcr->flags);
+       pcr_dbg(pcr, "pcr->flags = 0x%x\n", pcr->flags);
 
        pcr->state = PDEV_STAT_IDLE;
        err = rtsx_pci_init_hw(pcr);
@@ -1126,7 +1159,7 @@ static int rtsx_pci_probe(struct pci_dev *pcidev,
        struct rtsx_pcr *pcr;
        struct pcr_handle *handle;
        u32 base, len;
-       int ret, i;
+       int ret, i, bar = 0;
 
        dev_dbg(&(pcidev->dev),
                ": Realtek PCI-E Card Reader found at %s [%04x:%04x] (rev %x)\n",
@@ -1171,8 +1204,10 @@ static int rtsx_pci_probe(struct pci_dev *pcidev,
        pcr->pci = pcidev;
        dev_set_drvdata(&pcidev->dev, handle);
 
-       len = pci_resource_len(pcidev, 0);
-       base = pci_resource_start(pcidev, 0);
+       if (CHK_PCI_PID(pcr, 0x525A))
+               bar = 1;
+       len = pci_resource_len(pcidev, bar);
+       base = pci_resource_start(pcidev, bar);
        pcr->remap_addr = ioremap_nocache(base, len);
        if (!pcr->remap_addr) {
                ret = -ENOMEM;
index fe2bbb67defcd24fddfa0842b7584b4daad0dcb4..ce48842570d7c93fb9aa51c0fa691e802324e5fd 100644 (file)
 #define MIN_DIV_N_PCR          80
 #define MAX_DIV_N_PCR          208
 
+#define RTS524A_PME_FORCE_CTL          0xFF78
+#define RTS524A_PM_CTRL3               0xFF7E
+
+int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val);
+int __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val);
+
 void rts5209_init_params(struct rtsx_pcr *pcr);
 void rts5229_init_params(struct rtsx_pcr *pcr);
 void rtl8411_init_params(struct rtsx_pcr *pcr);
 void rtl8402_init_params(struct rtsx_pcr *pcr);
 void rts5227_init_params(struct rtsx_pcr *pcr);
 void rts5249_init_params(struct rtsx_pcr *pcr);
+void rts524a_init_params(struct rtsx_pcr *pcr);
+void rts525a_init_params(struct rtsx_pcr *pcr);
 void rtl8411b_init_params(struct rtsx_pcr *pcr);
 
 static inline u8 map_sd_drive(int idx)
index 0a7bc43db4e47fe961ff6502c8972b280dbc1825..4a69afb425ad3e2a034849c30902ab8a09ca6a41 100644 (file)
@@ -68,6 +68,8 @@ static const struct mfd_cell s5m8767_devs[] = {
 static const struct mfd_cell s2mps11_devs[] = {
        {
                .name = "s2mps11-pmic",
+       }, {
+               .name = "s2mps14-rtc",
        }, {
                .name = "s2mps11-clk",
                .of_compatible = "samsung,s2mps11-clk",
@@ -267,10 +269,8 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
        struct sec_platform_data *pd;
 
        pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
-       if (!pd) {
-               dev_err(dev, "could not allocate memory for pdata\n");
+       if (!pd)
                return ERR_PTR(-ENOMEM);
-       }
 
        /*
         * ToDo: the 'wakeup' member in the platform data is more of a linux
@@ -333,7 +333,6 @@ static int sec_pmic_probe(struct i2c_client *i2c,
        }
        if (pdata) {
                sec_pmic->device_type = pdata->device_type;
-               sec_pmic->ono = pdata->ono;
                sec_pmic->irq_base = pdata->irq_base;
                sec_pmic->wakeup = pdata->wakeup;
                sec_pmic->pdata = pdata;
index ba86a918c2dace19be14235f484f380a970d667e..806fa8dbb22d81999df749d35ba90efe2d789e19 100644 (file)
@@ -61,14 +61,14 @@ static const struct regmap_irq s2mps11_irqs[] = {
                .reg_offset = 1,
                .mask = S2MPS11_IRQ_RTC60S_MASK,
        },
-       [S2MPS11_IRQ_RTCA0] = {
-               .reg_offset = 1,
-               .mask = S2MPS11_IRQ_RTCA0_MASK,
-       },
        [S2MPS11_IRQ_RTCA1] = {
                .reg_offset = 1,
                .mask = S2MPS11_IRQ_RTCA1_MASK,
        },
+       [S2MPS11_IRQ_RTCA0] = {
+               .reg_offset = 1,
+               .mask = S2MPS11_IRQ_RTCA0_MASK,
+       },
        [S2MPS11_IRQ_SMPL] = {
                .reg_offset = 1,
                .mask = S2MPS11_IRQ_SMPL_MASK,
@@ -484,6 +484,12 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
                return ret;
        }
 
+       /*
+        * The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11
+        * so the interrupt number must be consistent.
+        */
+       BUILD_BUG_ON(((enum s2mps14_irq)S2MPS11_IRQ_RTCA0) != S2MPS14_IRQ_RTCA0);
+
        return 0;
 }
 
index 0e4a76daf18789b37e84163f2a83bb45afb642ea..7f87c62d91b3b67f92a3904bc61f94b062c0c408 100644 (file)
@@ -766,7 +766,7 @@ static int si476x_core_probe(struct i2c_client *client,
                           sizeof(struct v4l2_rds_data),
                           GFP_KERNEL);
        if (rval) {
-               dev_err(&client->dev, "Could not alloate the FIFO\n");
+               dev_err(&client->dev, "Could not allocate the FIFO\n");
                goto free_gpio;
        }
        mutex_init(&core->rds_drainer_status_lock);
diff --git a/drivers/mfd/sky81452.c b/drivers/mfd/sky81452.c
new file mode 100644 (file)
index 0000000..b0c9b04
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * sky81452.c  SKY81452 MFD driver
+ *
+ * Copyright 2014 Skyworks Solutions Inc.
+ * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/sky81452.h>
+
+static const struct regmap_config sky81452_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+};
+
+static int sky81452_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
+{
+       struct device *dev = &client->dev;
+       const struct sky81452_platform_data *pdata = dev_get_platdata(dev);
+       struct mfd_cell cells[2];
+       struct regmap *regmap;
+       int ret;
+
+       if (!pdata) {
+               pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+               if (!pdata)
+                       return -ENOMEM;
+       }
+
+       regmap = devm_regmap_init_i2c(client, &sky81452_config);
+       if (IS_ERR(regmap)) {
+               dev_err(dev, "failed to initialize.err=%ld\n", PTR_ERR(regmap));
+               return PTR_ERR(regmap);
+       }
+
+       i2c_set_clientdata(client, regmap);
+
+       memset(cells, 0, sizeof(cells));
+       cells[0].name = "sky81452-backlight";
+       cells[0].of_compatible = "skyworks,sky81452-backlight";
+       cells[0].platform_data = pdata->bl_pdata;
+       cells[0].pdata_size = sizeof(*pdata->bl_pdata);
+       cells[1].name = "sky81452-regulator";
+       cells[1].platform_data = pdata->regulator_init_data;
+       cells[1].pdata_size = sizeof(*pdata->regulator_init_data);
+
+       ret = mfd_add_devices(dev, -1, cells, ARRAY_SIZE(cells), NULL, 0, NULL);
+       if (ret)
+               dev_err(dev, "failed to add child devices. err=%d\n", ret);
+
+       return ret;
+}
+
+static int sky81452_remove(struct i2c_client *client)
+{
+       mfd_remove_devices(&client->dev);
+       return 0;
+}
+
+static const struct i2c_device_id sky81452_ids[] = {
+       { "sky81452" },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, sky81452_ids);
+
+#ifdef CONFIG_OF
+static const struct of_device_id sky81452_of_match[] = {
+       { .compatible = "skyworks,sky81452", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, sky81452_of_match);
+#endif
+
+static struct i2c_driver sky81452_driver = {
+       .driver = {
+               .name = "sky81452",
+               .of_match_table = of_match_ptr(sky81452_of_match),
+       },
+       .probe = sky81452_probe,
+       .remove = sky81452_remove,
+       .id_table = sky81452_ids,
+};
+
+module_i2c_driver(sky81452_driver);
+
+MODULE_DESCRIPTION("Skyworks SKY81452 MFD driver");
+MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>");
+MODULE_LICENSE("GPL v2");
index 467c80e1c4aec117b3579f0d220b801a89f19708..e4e4b22eebc91cc33145ad233e46c3afdb4b3345 100644 (file)
@@ -68,12 +68,6 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
        DEFINE_WAIT(wait);
        u32 reg;
 
-       /*
-        * disable TSC steps so it does not run while the ADC is using it. If
-        * write 0 while it is running (it just started or was already running)
-        * then it completes all steps that were enabled and stops then.
-        */
-       tscadc_writel(tsadc, REG_SE, 0);
        reg = tscadc_readl(tsadc, REG_ADCFSM);
        if (reg & SEQ_STATUS) {
                tsadc->adc_waiting = true;
@@ -86,8 +80,12 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
                spin_lock_irq(&tsadc->reg_lock);
                finish_wait(&tsadc->reg_se_wait, &wait);
 
+               /*
+                * Sequencer should either be idle or
+                * busy applying the charge step.
+                */
                reg = tscadc_readl(tsadc, REG_ADCFSM);
-               WARN_ON(reg & SEQ_STATUS);
+               WARN_ON((reg & SEQ_STATUS) && !(reg & CHARGE_STEP));
                tsadc->adc_waiting = false;
        }
        tsadc->adc_in_use = true;
@@ -96,7 +94,6 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
 void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val)
 {
        spin_lock_irq(&tsadc->reg_lock);
-       tsadc->reg_se_cache |= val;
        am335x_tscadc_need_adc(tsadc);
 
        tscadc_writel(tsadc, REG_SE, val);
index 743fb524fc8ae96f58cfaa6ea635317b621878cb..448f0a182dc4562d19bb35f9952b96124dcd37d7 100644 (file)
@@ -515,7 +515,7 @@ static int tps65010_gpio_get(struct gpio_chip *chip, unsigned offset)
 
 static struct tps65010 *the_tps;
 
-static int __exit tps65010_remove(struct i2c_client *client)
+static int tps65010_remove(struct i2c_client *client)
 {
        struct tps65010         *tps = i2c_get_clientdata(client);
        struct tps65010_board   *board = dev_get_platdata(&client->dev);
@@ -684,7 +684,7 @@ static struct i2c_driver tps65010_driver = {
                .name   = "tps65010",
        },
        .probe  = tps65010_probe,
-       .remove = __exit_p(tps65010_remove),
+       .remove = tps65010_remove,
        .id_table = tps65010_id,
 };
 
index 3935092460374e3e93f1650c7e4e4b7b7aaa1a07..f440aed613056a2b1b506f7be43f598f19c26002 100644 (file)
@@ -829,7 +829,7 @@ static struct twl4030_power_data osc_off_idle = {
        .board_config           = osc_off_rconfig,
 };
 
-static struct of_device_id twl4030_power_of_match[] = {
+static const struct of_device_id twl4030_power_of_match[] = {
        {
                .compatible = "ti,twl4030-power",
        },
index f71ee3dbc2a24a8f416d2063cff1d04422a55000..c5265c1262c50c3496f9142c07704d78d799a1b0 100644 (file)
@@ -814,4 +814,3 @@ MODULE_DESCRIPTION("TWL6040 MFD");
 MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
 MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:twl6040");
index 8f43ab8fd2d6fec9a01ace9ed1bce4d1e64f2ed7..3e628df9280cb58a32d9e8ca4fc3a23161fc295e 100644 (file)
 #define SYS_HBI_MASK           0xfff
 #define SYS_PROCIDx_HBI_SHIFT  0
 
-#define SYS_MCI_CARDIN         (1 << 0)
-#define SYS_MCI_WPROT          (1 << 1)
-
 #define SYS_MISC_MASTERSITE    (1 << 14)
 
-
-static void __iomem *__vexpress_sysreg_base;
-
-static void __iomem *vexpress_sysreg_base(void)
+void vexpress_flags_set(u32 data)
 {
-       if (!__vexpress_sysreg_base) {
+       static void __iomem *base;
+
+       if (!base) {
                struct device_node *node = of_find_compatible_node(NULL, NULL,
                                "arm,vexpress-sysreg");
 
-               __vexpress_sysreg_base = of_iomap(node, 0);
+               base = of_iomap(node, 0);
        }
 
-       WARN_ON(!__vexpress_sysreg_base);
-
-       return __vexpress_sysreg_base;
-}
-
-
-static int vexpress_sysreg_get_master(void)
-{
-       if (readl(vexpress_sysreg_base() + SYS_MISC) & SYS_MISC_MASTERSITE)
-               return VEXPRESS_SITE_DB2;
-
-       return VEXPRESS_SITE_DB1;
-}
-
-void vexpress_flags_set(u32 data)
-{
-       writel(~0, vexpress_sysreg_base() + SYS_FLAGSCLR);
-       writel(data, vexpress_sysreg_base() + SYS_FLAGSSET);
-}
-
-unsigned int vexpress_get_mci_cardin(struct device *dev)
-{
-       return readl(vexpress_sysreg_base() + SYS_MCI) & SYS_MCI_CARDIN;
-}
-
-u32 vexpress_get_procid(int site)
-{
-       if (site == VEXPRESS_SITE_MASTER)
-               site = vexpress_sysreg_get_master();
+       if (WARN_ON(!base))
+               return;
 
-       return readl(vexpress_sysreg_base() + (site == VEXPRESS_SITE_DB1 ?
-                       SYS_PROCID0 : SYS_PROCID1));
+       writel(~0, base + SYS_FLAGSCLR);
+       writel(data, base + SYS_FLAGSSET);
 }
 
-void __iomem *vexpress_get_24mhz_clock_base(void)
-{
-       return vexpress_sysreg_base() + SYS_24MHZ;
-}
-
-
-void __init vexpress_sysreg_early_init(void __iomem *base)
-{
-       __vexpress_sysreg_base = base;
-
-       vexpress_config_set_master(vexpress_sysreg_get_master());
-}
-
-
 /* The sysreg block is just a random collection of various functions... */
 
 static struct syscon_platform_data vexpress_sysreg_sys_id_pdata = {
@@ -210,6 +165,7 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
        struct resource *mem;
        void __iomem *base;
        struct bgpio_chip *mmc_gpio_chip;
+       int master;
        u32 dt_hbi;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -220,11 +176,14 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
        if (!base)
                return -ENOMEM;
 
-       vexpress_config_set_master(vexpress_sysreg_get_master());
+       master = readl(base + SYS_MISC) & SYS_MISC_MASTERSITE ?
+                       VEXPRESS_SITE_DB2 : VEXPRESS_SITE_DB1;
+       vexpress_config_set_master(master);
 
        /* Confirm board type against DT property, if available */
        if (of_property_read_u32(of_root, "arm,hbi", &dt_hbi) == 0) {
-               u32 id = vexpress_get_procid(VEXPRESS_SITE_MASTER);
+               u32 id = readl(base + (master == VEXPRESS_SITE_DB1 ?
+                                SYS_PROCID0 : SYS_PROCID1));
                u32 hbi = (id >> SYS_PROCIDx_HBI_SHIFT) & SYS_HBI_MASK;
 
                if (WARN_ON(dt_hbi != hbi))
index b326a82017ee7f35dfeb0ab3355dda3854c0fc39..aeae6ec123b3ad76c8d7eec6f4ba326c1419907e 100644 (file)
@@ -1172,9 +1172,6 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_DAC_DIGITAL_VOLUME_3L:
        case ARIZONA_DAC_VOLUME_LIMIT_3L:
        case ARIZONA_NOISE_GATE_SELECT_3L:
-       case ARIZONA_OUTPUT_PATH_CONFIG_3R:
-       case ARIZONA_DAC_DIGITAL_VOLUME_3R:
-       case ARIZONA_DAC_VOLUME_LIMIT_3R:
        case ARIZONA_OUTPUT_PATH_CONFIG_4L:
        case ARIZONA_DAC_DIGITAL_VOLUME_4L:
        case ARIZONA_OUT_VOLUME_4L:
index 38552a31304aff8cf2747d0f6278897bd6b87d72..65fed7146e9bac2a407df1c05710d6a6eb75e6c4 100644 (file)
@@ -202,16 +202,17 @@ static void enclosure_remove_links(struct enclosure_component *cdev)
 {
        char name[ENCLOSURE_NAME_SIZE];
 
+       enclosure_link_name(cdev, name);
+
        /*
         * In odd circumstances, like multipath devices, something else may
         * already have removed the links, so check for this condition first.
         */
-       if (!cdev->dev->kobj.sd)
-               return;
+       if (cdev->dev->kobj.sd)
+               sysfs_remove_link(&cdev->dev->kobj, name);
 
-       enclosure_link_name(cdev, name);
-       sysfs_remove_link(&cdev->dev->kobj, name);
-       sysfs_remove_link(&cdev->cdev.kobj, "device");
+       if (cdev->cdev.kobj.sd)
+               sysfs_remove_link(&cdev->cdev.kobj, "device");
 }
 
 static int enclosure_add_links(struct enclosure_component *cdev)
index c4cb9a984a5fb3965bba581eab0dd5c9096ec851..40ea639fa413a92f0239e1835894e73d36ddc1c1 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
-#include <linux/aio.h>
 #include <linux/ioctl.h>
 #include <linux/cdev.h>
 #include <linux/list.h>
index 3c019c0e60eb859ede0621f26c4d71d72fca8abe..47680c84801c766f158bf65c2e2dd3893fdff300 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
-#include <linux/aio.h>
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/ioctl.h>
index bd3039ab8f98e67e86de56ef8429dfd164c89d86..af44ee26075d8b520401a2cc52150b74d45157f0 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
-#include <linux/aio.h>
 #include <linux/pci.h>
 #include <linux/poll.h>
 #include <linux/ioctl.h>
index 82dc5748f873b72ea355b517c606d59dc6235c31..7f327121e6d7c43416a3ca6820cd39111796d683 100644 (file)
@@ -1210,7 +1210,7 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args)
 
                if (((die_args->trapnr == X86_TRAP_MF) ||
                     (die_args->trapnr == X86_TRAP_XF)) &&
-                   !user_mode_vm(die_args->regs))
+                   !user_mode(die_args->regs))
                        xpc_die_deactivate();
 
                break;
index 23f10f72e5f391d1c32b63b8a2e33dd2a7eb777e..c296bc098fe23684f4be66195b2342d7cd0159ef 100644 (file)
@@ -897,6 +897,7 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
        DECLARE_WAITQUEUE(wait, current);
        unsigned long flags;
        int stop;
+       bool pm = false;
 
        might_sleep();
 
@@ -916,15 +917,18 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
                host->claimed = 1;
                host->claimer = current;
                host->claim_cnt += 1;
+               if (host->claim_cnt == 1)
+                       pm = true;
        } else
                wake_up(&host->wq);
        spin_unlock_irqrestore(&host->lock, flags);
        remove_wait_queue(&host->wq, &wait);
-       if (host->ops->enable && !stop && host->claim_cnt == 1)
-               host->ops->enable(host);
+
+       if (pm)
+               pm_runtime_get_sync(mmc_dev(host));
+
        return stop;
 }
-
 EXPORT_SYMBOL(__mmc_claim_host);
 
 /**
@@ -940,9 +944,6 @@ void mmc_release_host(struct mmc_host *host)
 
        WARN_ON(!host->claimed);
 
-       if (host->ops->disable && host->claim_cnt == 1)
-               host->ops->disable(host);
-
        spin_lock_irqsave(&host->lock, flags);
        if (--host->claim_cnt) {
                /* Release for nested claim */
@@ -952,6 +953,8 @@ void mmc_release_host(struct mmc_host *host)
                host->claimer = NULL;
                spin_unlock_irqrestore(&host->lock, flags);
                wake_up(&host->wq);
+               pm_runtime_mark_last_busy(mmc_dev(host));
+               pm_runtime_put_autosuspend(mmc_dev(host));
        }
 }
 EXPORT_SYMBOL(mmc_release_host);
index 1d41e8541f388d7a2f74f04e469b72841609f03b..f36c76f8b2321e11d7d142c90b9400cb8b950d79 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/err.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/pm_runtime.h>
@@ -336,6 +337,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
 {
        int err = 0, idx;
        unsigned int part_size;
+       struct device_node *np;
+       bool broken_hpi = false;
 
        /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */
        card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE];
@@ -349,6 +352,11 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
                }
        }
 
+       np = mmc_of_find_child_device(card->host, 0);
+       if (np && of_device_is_compatible(np, "mmc-card"))
+               broken_hpi = of_property_read_bool(np, "broken-hpi");
+       of_node_put(np);
+
        /*
         * The EXT_CSD format is meant to be forward compatible. As long
         * as CSD_STRUCTURE does not change, all values for EXT_CSD_REV
@@ -494,7 +502,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
                }
 
                /* check whether the eMMC card supports HPI */
-               if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) {
+               if (!broken_hpi && (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1)) {
                        card->ext_csd.hpi = 1;
                        if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2)
                                card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION;
@@ -1750,7 +1758,7 @@ static int mmc_runtime_suspend(struct mmc_host *host)
 
        err = _mmc_suspend(host, true);
        if (err)
-               pr_err("%s: error %d doing aggessive suspend\n",
+               pr_err("%s: error %d doing aggressive suspend\n",
                        mmc_hostname(host), err);
 
        return err;
@@ -1768,7 +1776,7 @@ static int mmc_runtime_resume(struct mmc_host *host)
 
        err = _mmc_resume(host);
        if (err)
-               pr_err("%s: error %d doing aggessive resume\n",
+               pr_err("%s: error %d doing aggressive resume\n",
                        mmc_hostname(host), err);
 
        return 0;
index 862356123d78c7def0c4f7530c86b223ff1adf32..ab21297811610089bc79f11c413be479a0114fe0 100644 (file)
@@ -19,7 +19,7 @@
 
 struct mmc_pwrseq_match {
        const char *compatible;
-       int (*alloc)(struct mmc_host *host, struct device *dev);
+       struct mmc_pwrseq *(*alloc)(struct mmc_host *host, struct device *dev);
 };
 
 static struct mmc_pwrseq_match pwrseq_match[] = {
@@ -52,6 +52,7 @@ int mmc_pwrseq_alloc(struct mmc_host *host)
        struct platform_device *pdev;
        struct device_node *np;
        struct mmc_pwrseq_match *match;
+       struct mmc_pwrseq *pwrseq;
        int ret = 0;
 
        np = of_parse_phandle(host->parent->of_node, "mmc-pwrseq", 0);
@@ -70,9 +71,14 @@ int mmc_pwrseq_alloc(struct mmc_host *host)
                goto err;
        }
 
-       ret = match->alloc(host, &pdev->dev);
-       if (!ret)
-               dev_info(host->parent, "allocated mmc-pwrseq\n");
+       pwrseq = match->alloc(host, &pdev->dev);
+       if (IS_ERR(pwrseq)) {
+               ret = PTR_ERR(host->pwrseq);
+               goto err;
+       }
+
+       host->pwrseq = pwrseq;
+       dev_info(host->parent, "allocated mmc-pwrseq\n");
 
 err:
        of_node_put(np);
@@ -109,4 +115,6 @@ void mmc_pwrseq_free(struct mmc_host *host)
 
        if (pwrseq && pwrseq->ops && pwrseq->ops->free)
                pwrseq->ops->free(host);
+
+       host->pwrseq = NULL;
 }
index aba3409e8d6e81debf567cffae1bb0ca0b65872c..096da48c6a7ecbb0ba294e6fd1bf9513b02bca36 100644 (file)
@@ -27,8 +27,10 @@ void mmc_pwrseq_post_power_on(struct mmc_host *host);
 void mmc_pwrseq_power_off(struct mmc_host *host);
 void mmc_pwrseq_free(struct mmc_host *host);
 
-int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev);
-int mmc_pwrseq_emmc_alloc(struct mmc_host *host, struct device *dev);
+struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host,
+                                          struct device *dev);
+struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host,
+                                        struct device *dev);
 
 #else
 
index a2d545904fbf6977a4f186a1a0c99503c945157b..9d6d2fb217967d069ff2f18db0b403dff05483e0 100644 (file)
@@ -49,7 +49,6 @@ static void mmc_pwrseq_emmc_free(struct mmc_host *host)
        unregister_restart_handler(&pwrseq->reset_nb);
        gpiod_put(pwrseq->reset_gpio);
        kfree(pwrseq);
-       host->pwrseq = NULL;
 }
 
 static struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = {
@@ -67,14 +66,15 @@ static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this,
        return NOTIFY_DONE;
 }
 
-int mmc_pwrseq_emmc_alloc(struct mmc_host *host, struct device *dev)
+struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host,
+                                        struct device *dev)
 {
        struct mmc_pwrseq_emmc *pwrseq;
        int ret = 0;
 
        pwrseq = kzalloc(sizeof(struct mmc_pwrseq_emmc), GFP_KERNEL);
        if (!pwrseq)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        pwrseq->reset_gpio = gpiod_get_index(dev, "reset", 0, GPIOD_OUT_LOW);
        if (IS_ERR(pwrseq->reset_gpio)) {
@@ -92,10 +92,9 @@ int mmc_pwrseq_emmc_alloc(struct mmc_host *host, struct device *dev)
        register_restart_handler(&pwrseq->reset_nb);
 
        pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops;
-       host->pwrseq = &pwrseq->pwrseq;
 
-       return 0;
+       return &pwrseq->pwrseq;
 free:
        kfree(pwrseq);
-       return ret;
+       return ERR_PTR(ret);
 }
index c53f14a7ce546533c300313a54078e1bad327bf9..0b14b83a53d6c9614a2ac897893f5cc1690a5b6e 100644 (file)
@@ -85,7 +85,6 @@ static void mmc_pwrseq_simple_free(struct mmc_host *host)
                clk_put(pwrseq->ext_clk);
 
        kfree(pwrseq);
-       host->pwrseq = NULL;
 }
 
 static struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = {
@@ -95,7 +94,8 @@ static struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = {
        .free = mmc_pwrseq_simple_free,
 };
 
-int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev)
+struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host,
+                                          struct device *dev)
 {
        struct mmc_pwrseq_simple *pwrseq;
        int i, nr_gpios, ret = 0;
@@ -107,7 +107,7 @@ int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev)
        pwrseq = kzalloc(sizeof(struct mmc_pwrseq_simple) + nr_gpios *
                         sizeof(struct gpio_desc *), GFP_KERNEL);
        if (!pwrseq)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        pwrseq->ext_clk = clk_get(dev, "ext_clock");
        if (IS_ERR(pwrseq->ext_clk) &&
@@ -133,13 +133,12 @@ int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev)
 
        pwrseq->nr_gpios = nr_gpios;
        pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops;
-       host->pwrseq = &pwrseq->pwrseq;
 
-       return 0;
+       return &pwrseq->pwrseq;
 clk_put:
        if (!IS_ERR(pwrseq->ext_clk))
                clk_put(pwrseq->ext_clk);
 free:
        kfree(pwrseq);
-       return ret;
+       return ERR_PTR(ret);
 }
index ad4d43eae99defd6b5a975cff9d074ff3929c245..31a9ef256d0652d5b2ce64623d3a161bbcfcd6b7 100644 (file)
@@ -1157,7 +1157,7 @@ static int mmc_sd_runtime_suspend(struct mmc_host *host)
 
        err = _mmc_sd_suspend(host);
        if (err)
-               pr_err("%s: error %d doing aggessive suspend\n",
+               pr_err("%s: error %d doing aggressive suspend\n",
                        mmc_hostname(host), err);
 
        return err;
@@ -1175,7 +1175,7 @@ static int mmc_sd_runtime_resume(struct mmc_host *host)
 
        err = _mmc_sd_resume(host);
        if (err)
-               pr_err("%s: error %d doing aggessive resume\n",
+               pr_err("%s: error %d doing aggressive resume\n",
                        mmc_hostname(host), err);
 
        return 0;
index ce6cc47206b0f3d6d91b4b69f35a66720cf14c47..5bc6c7dbbd6088153b6ee2bda65730caccea0a8a 100644 (file)
@@ -293,19 +293,22 @@ static int sdio_enable_4bit_bus(struct mmc_card *card)
        int err;
 
        if (card->type == MMC_TYPE_SDIO)
-               return sdio_enable_wide(card);
-
-       if ((card->host->caps & MMC_CAP_4_BIT_DATA) &&
-               (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+               err = sdio_enable_wide(card);
+       else if ((card->host->caps & MMC_CAP_4_BIT_DATA) &&
+                (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
                err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
                if (err)
                        return err;
+               err = sdio_enable_wide(card);
+               if (err <= 0)
+                       mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1);
        } else
                return 0;
 
-       err = sdio_enable_wide(card);
-       if (err <= 0)
-               mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1);
+       if (err > 0) {
+               mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
+               err = 0;
+       }
 
        return err;
 }
@@ -547,13 +550,8 @@ static int mmc_sdio_init_uhs_card(struct mmc_card *card)
        /*
         * Switch to wider bus (if supported).
         */
-       if (card->host->caps & MMC_CAP_4_BIT_DATA) {
+       if (card->host->caps & MMC_CAP_4_BIT_DATA)
                err = sdio_enable_4bit_bus(card);
-               if (err > 0) {
-                       mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
-                       err = 0;
-               }
-       }
 
        /* Set the driver strength for the card */
        sdio_select_driver_type(card);
@@ -803,9 +801,7 @@ try_again:
                 * Switch to wider bus (if supported).
                 */
                err = sdio_enable_4bit_bus(card);
-               if (err > 0)
-                       mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
-               else if (err)
+               if (err)
                        goto remove;
        }
 finish:
@@ -983,10 +979,6 @@ static int mmc_sdio_resume(struct mmc_host *host)
        } else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {
                /* We may have switched to 1-bit mode during suspend */
                err = sdio_enable_4bit_bus(host->card);
-               if (err > 0) {
-                       mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
-                       err = 0;
-               }
        }
 
        if (!err && host->sdio_irqs) {
index 61ac63a3776a789e2b98903118ab3198a00b9ffd..7f4db908f89b1a03e2f572b91e2331fa2fc44563 100644 (file)
@@ -132,7 +132,7 @@ config MMC_SDHCI_OF_ARASAN
 config MMC_SDHCI_OF_ESDHC
        tristate "SDHCI OF support for the Freescale eSDHC controller"
        depends on MMC_SDHCI_PLTFM
-       depends on PPC_OF
+       depends on PPC
        select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
        help
          This selects the Freescale eSDHC controller support.
@@ -144,7 +144,7 @@ config MMC_SDHCI_OF_ESDHC
 config MMC_SDHCI_OF_HLWD
        tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers"
        depends on MMC_SDHCI_PLTFM
-       depends on PPC_OF
+       depends on PPC
        select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
        help
          This selects the Secure Digital Host Controller Interface (SDHCI)
@@ -230,7 +230,7 @@ config MMC_SDHCI_PXAV3
        tristate "Marvell MMP2 SD Host Controller support (PXAV3)"
        depends on CLKDEV_LOOKUP
        depends on MMC_SDHCI_PLTFM
-       depends on ARCH_MMP || COMPILE_TEST
+       depends on ARCH_BERLIN || ARCH_MMP || ARCH_MVEBU || COMPILE_TEST
        default CPU_MMP2
        help
          This selects the Marvell(R) PXAV3 SD Host Controller.
@@ -255,6 +255,7 @@ config MMC_SDHCI_PXAV2
 config MMC_SDHCI_SPEAR
        tristate "SDHCI support on ST SPEAr platform"
        depends on MMC_SDHCI && PLAT_SPEAR
+       depends on OF
        help
          This selects the Secure Digital Host Controller Interface (SDHCI)
          often referrered to as the HSMMC block in some of the ST SPEAR range
@@ -307,6 +308,20 @@ config MMC_SDHCI_F_SDH30
 
          If unsure, say N.
 
+config MMC_SDHCI_IPROC
+       tristate "SDHCI platform support for the iProc SD/MMC Controller"
+       depends on ARCH_BCM_IPROC || COMPILE_TEST
+       depends on MMC_SDHCI_PLTFM
+       default ARCH_BCM_IPROC
+       select MMC_SDHCI_IO_ACCESSORS
+       help
+         This selects the iProc SD/MMC controller.
+
+         If you have an IPROC platform with SD or MMC devices,
+         say Y or M here.
+
+         If unsure, say N.
+
 config MMC_MOXART
        tristate "MOXART SD/MMC Host Controller support"
        depends on ARCH_MOXART && MMC
index 6a7cfe0de332689fdb8a8631e1327057b54b0e4f..711e913450f5be77d3aa0690931d827697f706c1 100644 (file)
@@ -71,6 +71,7 @@ obj-$(CONFIG_MMC_SDHCI_OF_ESDHC)      += sdhci-of-esdhc.o
 obj-$(CONFIG_MMC_SDHCI_OF_HLWD)                += sdhci-of-hlwd.o
 obj-$(CONFIG_MMC_SDHCI_BCM_KONA)       += sdhci-bcm-kona.o
 obj-$(CONFIG_MMC_SDHCI_BCM2835)                += sdhci-bcm2835.o
+obj-$(CONFIG_MMC_SDHCI_IPROC)          += sdhci-iproc.o
 obj-$(CONFIG_MMC_SDHCI_MSM)            += sdhci-msm.o
 obj-$(CONFIG_MMC_SDHCI_ST)             += sdhci-st.o
 
index c97001e15227aba5b337c5cb07da0a799969d6dd..0aa44e679df4965350abc9e7cce4f0d8e42da2ec 100644 (file)
 #define ATMCI_REGS_SIZE                0x100
 
 /* Register access macros */
-#define atmci_readl(port,reg)                          \
+#ifdef CONFIG_AVR32
+#define atmci_readl(port, reg)                 \
        __raw_readl((port)->regs + reg)
-#define atmci_writel(port,reg,value)                   \
+#define atmci_writel(port, reg, value)                 \
        __raw_writel((value), (port)->regs + reg)
+#else
+#define atmci_readl(port, reg)                 \
+       readl_relaxed((port)->regs + reg)
+#define atmci_writel(port, reg, value)                 \
+       writel_relaxed((value), (port)->regs + reg)
+#endif
 
 /* On AVR chips the Peripheral DMA Controller is not connected to MCI. */
 #ifdef CONFIG_AVR32
index fe32948c6114dbf9dd72820f958d3337872d4ec0..e761eb1b1441339e33a84822ff863b20165e97cf 100644 (file)
@@ -40,7 +40,12 @@ struct dw_mci_exynos_priv_data {
        u8                              ciu_div;
        u32                             sdr_timing;
        u32                             ddr_timing;
+       u32                             hs400_timing;
+       u32                             tuned_sample;
        u32                             cur_speed;
+       u32                             dqs_delay;
+       u32                             saved_dqs_en;
+       u32                             saved_strobe_ctrl;
 };
 
 static struct dw_mci_exynos_compatible {
@@ -71,6 +76,21 @@ static struct dw_mci_exynos_compatible {
        },
 };
 
+static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host)
+{
+       struct dw_mci_exynos_priv_data *priv = host->priv;
+
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
+               return EXYNOS4412_FIXED_CIU_CLK_DIV;
+       else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210)
+               return EXYNOS4210_FIXED_CIU_CLK_DIV;
+       else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+                       priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+               return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1;
+       else
+               return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL)) + 1;
+}
+
 static int dw_mci_exynos_priv_init(struct dw_mci *host)
 {
        struct dw_mci_exynos_priv_data *priv = host->priv;
@@ -85,6 +105,16 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
                           SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT);
        }
 
+       if (priv->ctrl_type >= DW_MCI_TYPE_EXYNOS5420) {
+               priv->saved_strobe_ctrl = mci_readl(host, HS400_DLINE_CTRL);
+               priv->saved_dqs_en = mci_readl(host, HS400_DQS_EN);
+               priv->saved_dqs_en |= AXI_NON_BLOCKING_WR;
+               mci_writel(host, HS400_DQS_EN, priv->saved_dqs_en);
+               if (!priv->dqs_delay)
+                       priv->dqs_delay =
+                               DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl);
+       }
+
        return 0;
 }
 
@@ -97,6 +127,26 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host)
        return 0;
 }
 
+static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
+{
+       struct dw_mci_exynos_priv_data *priv = host->priv;
+       u32 clksel;
+
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+               clksel = mci_readl(host, CLKSEL64);
+       else
+               clksel = mci_readl(host, CLKSEL);
+
+       clksel = (clksel & ~SDMMC_CLKSEL_TIMING_MASK) | timing;
+
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+               mci_writel(host, CLKSEL64, clksel);
+       else
+               mci_writel(host, CLKSEL, clksel);
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int dw_mci_exynos_suspend(struct device *dev)
 {
@@ -172,30 +222,38 @@ static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr)
        }
 }
 
-static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing)
 {
        struct dw_mci_exynos_priv_data *priv = host->priv;
-       unsigned int wanted = ios->clock;
-       unsigned long actual;
-       u8 div = priv->ciu_div + 1;
+       u32 dqs, strobe;
 
-       if (ios->timing == MMC_TIMING_MMC_DDR52) {
-               if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
-                       priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
-                       mci_writel(host, CLKSEL64, priv->ddr_timing);
-               else
-                       mci_writel(host, CLKSEL, priv->ddr_timing);
-               /* Should be double rate for DDR mode */
-               if (ios->bus_width == MMC_BUS_WIDTH_8)
-                       wanted <<= 1;
+       /*
+        * Not supported to configure register
+        * related to HS400
+        */
+       if (priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420)
+               return;
+
+       dqs = priv->saved_dqs_en;
+       strobe = priv->saved_strobe_ctrl;
+
+       if (timing == MMC_TIMING_MMC_HS400) {
+               dqs |= DATA_STROBE_EN;
+               strobe = DQS_CTRL_RD_DELAY(strobe, priv->dqs_delay);
        } else {
-               if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
-                       priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
-                       mci_writel(host, CLKSEL64, priv->sdr_timing);
-               else
-                       mci_writel(host, CLKSEL, priv->sdr_timing);
+               dqs &= ~DATA_STROBE_EN;
        }
 
+       mci_writel(host, HS400_DQS_EN, dqs);
+       mci_writel(host, HS400_DLINE_CTRL, strobe);
+}
+
+static void dw_mci_exynos_adjust_clock(struct dw_mci *host, unsigned int wanted)
+{
+       struct dw_mci_exynos_priv_data *priv = host->priv;
+       unsigned long actual;
+       u8 div;
+       int ret;
        /*
         * Don't care if wanted clock is zero or
         * ciu clock is unavailable
@@ -207,17 +265,52 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
        if (wanted < EXYNOS_CCLKIN_MIN)
                wanted = EXYNOS_CCLKIN_MIN;
 
-       if (wanted != priv->cur_speed) {
-               int ret = clk_set_rate(host->ciu_clk, wanted * div);
-               if (ret)
-                       dev_warn(host->dev,
-                               "failed to set clk-rate %u error: %d\n",
-                                wanted * div, ret);
-               actual = clk_get_rate(host->ciu_clk);
-               host->bus_hz = actual / div;
-               priv->cur_speed = wanted;
-               host->current_speed = 0;
+       if (wanted == priv->cur_speed)
+               return;
+
+       div = dw_mci_exynos_get_ciu_div(host);
+       ret = clk_set_rate(host->ciu_clk, wanted * div);
+       if (ret)
+               dev_warn(host->dev,
+                       "failed to set clk-rate %u error: %d\n",
+                       wanted * div, ret);
+       actual = clk_get_rate(host->ciu_clk);
+       host->bus_hz = actual / div;
+       priv->cur_speed = wanted;
+       host->current_speed = 0;
+}
+
+static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+       struct dw_mci_exynos_priv_data *priv = host->priv;
+       unsigned int wanted = ios->clock;
+       u32 timing = ios->timing, clksel;
+
+       switch (timing) {
+       case MMC_TIMING_MMC_HS400:
+               /* Update tuned sample timing */
+               clksel = SDMMC_CLKSEL_UP_SAMPLE(
+                               priv->hs400_timing, priv->tuned_sample);
+               wanted <<= 1;
+               break;
+       case MMC_TIMING_MMC_DDR52:
+               clksel = priv->ddr_timing;
+               /* Should be double rate for DDR mode */
+               if (ios->bus_width == MMC_BUS_WIDTH_8)
+                       wanted <<= 1;
+               break;
+       default:
+               clksel = priv->sdr_timing;
        }
+
+       /* Set clock timing for the requested speed mode*/
+       dw_mci_exynos_set_clksel_timing(host, clksel);
+
+       /* Configure setting for HS400 */
+       dw_mci_exynos_config_hs400(host, timing);
+
+       /* Configure clock rate */
+       dw_mci_exynos_adjust_clock(host, wanted);
 }
 
 static int dw_mci_exynos_parse_dt(struct dw_mci *host)
@@ -260,6 +353,16 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host)
                return ret;
 
        priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div);
+
+       ret = of_property_read_u32_array(np,
+                       "samsung,dw-mshc-hs400-timing", timing, 2);
+       if (!ret && of_property_read_u32(np,
+                               "samsung,read-strobe-delay", &priv->dqs_delay))
+               dev_dbg(host->dev,
+                       "read-strobe-delay is not found, assuming usage of default value\n");
+
+       priv->hs400_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1],
+                                               HS400_FIXED_CIU_CLK_DIV);
        host->priv = priv;
        return 0;
 }
@@ -285,7 +388,7 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
                clksel = mci_readl(host, CLKSEL64);
        else
                clksel = mci_readl(host, CLKSEL);
-       clksel = (clksel & ~0x7) | SDMMC_CLKSEL_CCLK_SAMPLE(sample);
+       clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
        if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
                priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
                mci_writel(host, CLKSEL64, clksel);
@@ -304,13 +407,16 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
                clksel = mci_readl(host, CLKSEL64);
        else
                clksel = mci_readl(host, CLKSEL);
+
        sample = (clksel + 1) & 0x7;
-       clksel = (clksel & ~0x7) | sample;
+       clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
+
        if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
                priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
                mci_writel(host, CLKSEL64, clksel);
        else
                mci_writel(host, CLKSEL, clksel);
+
        return sample;
 }
 
@@ -343,6 +449,7 @@ out:
 static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
 {
        struct dw_mci *host = slot->host;
+       struct dw_mci_exynos_priv_data *priv = host->priv;
        struct mmc_host *mmc = slot->mmc;
        u8 start_smpl, smpl, candiates = 0;
        s8 found = -1;
@@ -360,14 +467,27 @@ static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot)
        } while (start_smpl != smpl);
 
        found = dw_mci_exynos_get_best_clksmpl(candiates);
-       if (found >= 0)
+       if (found >= 0) {
                dw_mci_exynos_set_clksmpl(host, found);
-       else
+               priv->tuned_sample = found;
+       } else {
                ret = -EIO;
+       }
 
        return ret;
 }
 
+static int dw_mci_exynos_prepare_hs400_tuning(struct dw_mci *host,
+                                       struct mmc_ios *ios)
+{
+       struct dw_mci_exynos_priv_data *priv = host->priv;
+
+       dw_mci_exynos_set_clksel_timing(host, priv->hs400_timing);
+       dw_mci_exynos_adjust_clock(host, (ios->clock) << 1);
+
+       return 0;
+}
+
 /* Common capabilities of Exynos4/Exynos5 SoC */
 static unsigned long exynos_dwmmc_caps[4] = {
        MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23,
@@ -384,6 +504,7 @@ static const struct dw_mci_drv_data exynos_drv_data = {
        .set_ios                = dw_mci_exynos_set_ios,
        .parse_dt               = dw_mci_exynos_parse_dt,
        .execute_tuning         = dw_mci_exynos_execute_tuning,
+       .prepare_hs400_tuning   = dw_mci_exynos_prepare_hs400_tuning,
 };
 
 static const struct of_device_id dw_mci_exynos_match[] = {
index 7872ce586b558e07461c748f600f6ef6777bb12b..595c934e6166cf1b9aef2c18a8a28ec3c3062163 100644 (file)
 #ifndef _DW_MMC_EXYNOS_H_
 #define _DW_MMC_EXYNOS_H_
 
-/* Extended Register's Offset */
 #define SDMMC_CLKSEL                   0x09C
 #define SDMMC_CLKSEL64                 0x0A8
 
+/* Extended Register's Offset */
+#define SDMMC_HS400_DQS_EN             0x180
+#define SDMMC_HS400_ASYNC_FIFO_CTRL    0x184
+#define SDMMC_HS400_DLINE_CTRL         0x188
+
 /* CLKSEL register defines */
 #define SDMMC_CLKSEL_CCLK_SAMPLE(x)    (((x) & 7) << 0)
 #define SDMMC_CLKSEL_CCLK_DRIVE(x)     (((x) & 7) << 16)
 #define SDMMC_CLKSEL_CCLK_DIVIDER(x)   (((x) & 7) << 24)
 #define SDMMC_CLKSEL_GET_DRV_WD3(x)    (((x) >> 16) & 0x7)
+#define SDMMC_CLKSEL_GET_DIV(x)                (((x) >> 24) & 0x7)
+#define SDMMC_CLKSEL_UP_SAMPLE(x, y)   (((x) & ~SDMMC_CLKSEL_CCLK_SAMPLE(7)) |\
+                                        SDMMC_CLKSEL_CCLK_SAMPLE(y))
 #define SDMMC_CLKSEL_TIMING(x, y, z)   (SDMMC_CLKSEL_CCLK_SAMPLE(x) |  \
                                         SDMMC_CLKSEL_CCLK_DRIVE(y) |   \
                                         SDMMC_CLKSEL_CCLK_DIVIDER(z))
+#define SDMMC_CLKSEL_TIMING_MASK       SDMMC_CLKSEL_TIMING(0x7, 0x7, 0x7)
 #define SDMMC_CLKSEL_WAKEUP_INT                BIT(11)
 
+/* RCLK_EN register defines */
+#define DATA_STROBE_EN                 BIT(0)
+#define AXI_NON_BLOCKING_WR    BIT(7)
+
+/* DLINE_CTRL register defines */
+#define DQS_CTRL_RD_DELAY(x, y)                (((x) & ~0x3FF) | ((y) & 0x3FF))
+#define DQS_CTRL_GET_RD_DELAY(x)       ((x) & 0x3FF)
+
 /* Protector Register */
 #define SDMMC_EMMCP_BASE       0x1000
 #define SDMMC_MPSECURITY       (SDMMC_EMMCP_BASE + 0x0010)
@@ -49,6 +65,7 @@
 /* Fixed clock divider */
 #define EXYNOS4210_FIXED_CIU_CLK_DIV   2
 #define EXYNOS4412_FIXED_CIU_CLK_DIV   4
+#define HS400_FIXED_CIU_CLK_DIV                1
 
 /* Minimal required clock frequency for cclkin, unit: HZ */
 #define EXYNOS_CCLKIN_MIN      50000000
index e2a726a503ee147072bbd5afaf8692dab53ca87d..dbf166f94f1b6a1457238e29b435f83171509e26 100644 (file)
@@ -76,12 +76,20 @@ static int dw_mci_rockchip_init(struct dw_mci *host)
        return 0;
 }
 
+/* Common capabilities of RK3288 SoC */
+static unsigned long dw_mci_rk3288_dwmmc_caps[4] = {
+       MMC_CAP_RUNTIME_RESUME, /* emmc */
+       MMC_CAP_RUNTIME_RESUME, /* sdmmc */
+       MMC_CAP_RUNTIME_RESUME, /* sdio0 */
+       MMC_CAP_RUNTIME_RESUME, /* sdio1 */
+};
 static const struct dw_mci_drv_data rk2928_drv_data = {
        .prepare_command        = dw_mci_rockchip_prepare_command,
        .init                   = dw_mci_rockchip_init,
 };
 
 static const struct dw_mci_drv_data rk3288_drv_data = {
+       .caps                   = dw_mci_rk3288_dwmmc_caps,
        .prepare_command        = dw_mci_rockchip_prepare_command,
        .set_ios                = dw_mci_rk3288_set_ios,
        .setup_clock    = dw_mci_rk3288_setup_clock,
index 4d2e3c2e183057ddd13e29c1d1b8398a01dd7c5c..38b29265cc7c7625484db40b4d38f2148a2c1aa6 100644 (file)
@@ -69,7 +69,8 @@ struct idmac_desc_64addr {
 
        u32             des2;   /*Buffer sizes */
 #define IDMAC_64ADDR_SET_BUFFER1_SIZE(d, s) \
-       ((d)->des2 = ((d)->des2 & 0x03ffe000) | ((s) & 0x1fff))
+       ((d)->des2 = ((d)->des2 & cpu_to_le32(0x03ffe000)) | \
+        ((cpu_to_le32(s)) & cpu_to_le32(0x1fff)))
 
        u32             des3;   /* Reserved */
 
@@ -81,7 +82,7 @@ struct idmac_desc_64addr {
 };
 
 struct idmac_desc {
-       u32             des0;   /* Control Descriptor */
+       __le32          des0;   /* Control Descriptor */
 #define IDMAC_DES0_DIC BIT(1)
 #define IDMAC_DES0_LD  BIT(2)
 #define IDMAC_DES0_FD  BIT(3)
@@ -90,18 +91,19 @@ struct idmac_desc {
 #define IDMAC_DES0_CES BIT(30)
 #define IDMAC_DES0_OWN BIT(31)
 
-       u32             des1;   /* Buffer sizes */
+       __le32          des1;   /* Buffer sizes */
 #define IDMAC_SET_BUFFER1_SIZE(d, s) \
        ((d)->des1 = ((d)->des1 & 0x03ffe000) | ((s) & 0x1fff))
 
-       u32             des2;   /* buffer 1 physical address */
+       __le32          des2;   /* buffer 1 physical address */
 
-       u32             des3;   /* buffer 2 physical address */
+       __le32          des3;   /* buffer 2 physical address */
 };
 #endif /* CONFIG_MMC_DW_IDMAC */
 
 static bool dw_mci_reset(struct dw_mci *host);
 static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset);
+static int dw_mci_card_busy(struct mmc_host *mmc);
 
 #if defined(CONFIG_DEBUG_FS)
 static int dw_mci_req_show(struct seq_file *s, void *v)
@@ -335,6 +337,31 @@ static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd)
        return cmdr;
 }
 
+static void dw_mci_wait_while_busy(struct dw_mci *host, u32 cmd_flags)
+{
+       unsigned long timeout = jiffies + msecs_to_jiffies(500);
+
+       /*
+        * Databook says that before issuing a new data transfer command
+        * we need to check to see if the card is busy.  Data transfer commands
+        * all have SDMMC_CMD_PRV_DAT_WAIT set, so we'll key off that.
+        *
+        * ...also allow sending for SDMMC_CMD_VOLT_SWITCH where busy is
+        * expected.
+        */
+       if ((cmd_flags & SDMMC_CMD_PRV_DAT_WAIT) &&
+           !(cmd_flags & SDMMC_CMD_VOLT_SWITCH)) {
+               while (mci_readl(host, STATUS) & SDMMC_STATUS_BUSY) {
+                       if (time_after(jiffies, timeout)) {
+                               /* Command will fail; we'll pass error then */
+                               dev_err(host->dev, "Busy; trying anyway\n");
+                               break;
+                       }
+                       udelay(10);
+               }
+       }
+}
+
 static void dw_mci_start_command(struct dw_mci *host,
                                 struct mmc_command *cmd, u32 cmd_flags)
 {
@@ -345,6 +372,7 @@ static void dw_mci_start_command(struct dw_mci *host,
 
        mci_writel(host, CMDARG, cmd->arg);
        wmb();
+       dw_mci_wait_while_busy(host, cmd_flags);
 
        mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START);
 }
@@ -477,23 +505,23 @@ static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data,
                         * Set the OWN bit and disable interrupts for this
                         * descriptor
                         */
-                       desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
-                                               IDMAC_DES0_CH;
+                       desc->des0 = cpu_to_le32(IDMAC_DES0_OWN |
+                                       IDMAC_DES0_DIC | IDMAC_DES0_CH);
                        /* Buffer length */
                        IDMAC_SET_BUFFER1_SIZE(desc, length);
 
                        /* Physical address to DMA to/from */
-                       desc->des2 = mem_addr;
+                       desc->des2 = cpu_to_le32(mem_addr);
                }
 
                /* Set first descriptor */
                desc = host->sg_cpu;
-               desc->des0 |= IDMAC_DES0_FD;
+               desc->des0 |= cpu_to_le32(IDMAC_DES0_FD);
 
                /* Set last descriptor */
                desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc);
-               desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
-               desc->des0 |= IDMAC_DES0_LD;
+               desc->des0 &= cpu_to_le32(~(IDMAC_DES0_CH | IDMAC_DES0_DIC));
+               desc->des0 |= cpu_to_le32(IDMAC_DES0_LD);
        }
 
        wmb();
@@ -562,12 +590,12 @@ static int dw_mci_idmac_init(struct dw_mci *host)
 
                /* Forward link the descriptor list */
                for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
-                       p->des3 = host->sg_dma + (sizeof(struct idmac_desc) *
-                                                               (i + 1));
+                       p->des3 = cpu_to_le32(host->sg_dma +
+                                       (sizeof(struct idmac_desc) * (i + 1)));
 
                /* Set the last descriptor as the end-of-ring descriptor */
-               p->des3 = host->sg_dma;
-               p->des0 = IDMAC_DES0_ER;
+               p->des3 = cpu_to_le32(host->sg_dma);
+               p->des0 = cpu_to_le32(IDMAC_DES0_ER);
        }
 
        dw_mci_idmac_reset(host);
@@ -737,6 +765,7 @@ static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data)
                return;
 
        if (host->timing != MMC_TIMING_MMC_HS200 &&
+           host->timing != MMC_TIMING_MMC_HS400 &&
            host->timing != MMC_TIMING_UHS_SDR104)
                goto disable;
 
@@ -876,6 +905,7 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)
 
        mci_writel(host, CMDARG, arg);
        wmb();
+       dw_mci_wait_while_busy(host, cmd);
        mci_writel(host, CMD, SDMMC_CMD_START | cmd);
 
        while (time_before(jiffies, timeout)) {
@@ -992,6 +1022,26 @@ static void __dw_mci_start_request(struct dw_mci *host,
 
        dw_mci_start_command(host, cmd, cmdflags);
 
+       if (cmd->opcode == SD_SWITCH_VOLTAGE) {
+               unsigned long irqflags;
+
+               /*
+                * Databook says to fail after 2ms w/ no response, but evidence
+                * shows that sometimes the cmd11 interrupt takes over 130ms.
+                * We'll set to 500ms, plus an extra jiffy just in case jiffies
+                * is just about to roll over.
+                *
+                * We do this whole thing under spinlock and only if the
+                * command hasn't already completed (indicating the the irq
+                * already ran so we don't want the timeout).
+                */
+               spin_lock_irqsave(&host->irq_lock, irqflags);
+               if (!test_bit(EVENT_CMD_COMPLETE, &host->pending_events))
+                       mod_timer(&host->cmd11_timer,
+                               jiffies + msecs_to_jiffies(500) + 1);
+               spin_unlock_irqrestore(&host->irq_lock, irqflags);
+       }
+
        if (mrq->stop)
                host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop);
        else
@@ -1084,7 +1134,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        regs = mci_readl(slot->host, UHS_REG);
 
        /* DDR mode set */
-       if (ios->timing == MMC_TIMING_MMC_DDR52)
+       if (ios->timing == MMC_TIMING_MMC_DDR52 ||
+           ios->timing == MMC_TIMING_MMC_HS400)
                regs |= ((0x1 << slot->id) << 16);
        else
                regs &= ~((0x1 << slot->id) << 16);
@@ -1101,12 +1152,6 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        if (drv_data && drv_data->set_ios)
                drv_data->set_ios(slot->host, ios);
 
-       /* Slot specific timing and width adjustment */
-       dw_mci_setup_bus(slot, false);
-
-       if (slot->host->state == STATE_WAITING_CMD11_DONE && ios->clock != 0)
-               slot->host->state = STATE_IDLE;
-
        switch (ios->power_mode) {
        case MMC_POWER_UP:
                if (!IS_ERR(mmc->supply.vmmc)) {
@@ -1125,23 +1170,39 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                mci_writel(slot->host, PWREN, regs);
                break;
        case MMC_POWER_ON:
-               if (!IS_ERR(mmc->supply.vqmmc) && !slot->host->vqmmc_enabled) {
-                       ret = regulator_enable(mmc->supply.vqmmc);
-                       if (ret < 0)
-                               dev_err(slot->host->dev,
-                                       "failed to enable vqmmc regulator\n");
-                       else
+               if (!slot->host->vqmmc_enabled) {
+                       if (!IS_ERR(mmc->supply.vqmmc)) {
+                               ret = regulator_enable(mmc->supply.vqmmc);
+                               if (ret < 0)
+                                       dev_err(slot->host->dev,
+                                               "failed to enable vqmmc\n");
+                               else
+                                       slot->host->vqmmc_enabled = true;
+
+                       } else {
+                               /* Keep track so we don't reset again */
                                slot->host->vqmmc_enabled = true;
+                       }
+
+                       /* Reset our state machine after powering on */
+                       dw_mci_ctrl_reset(slot->host,
+                                         SDMMC_CTRL_ALL_RESET_FLAGS);
                }
+
+               /* Adjust clock / bus width after power is up */
+               dw_mci_setup_bus(slot, false);
+
                break;
        case MMC_POWER_OFF:
+               /* Turn clock off before power goes down */
+               dw_mci_setup_bus(slot, false);
+
                if (!IS_ERR(mmc->supply.vmmc))
                        mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
 
-               if (!IS_ERR(mmc->supply.vqmmc) && slot->host->vqmmc_enabled) {
+               if (!IS_ERR(mmc->supply.vqmmc) && slot->host->vqmmc_enabled)
                        regulator_disable(mmc->supply.vqmmc);
-                       slot->host->vqmmc_enabled = false;
-               }
+               slot->host->vqmmc_enabled = false;
 
                regs = mci_readl(slot->host, PWREN);
                regs &= ~(1 << slot->id);
@@ -1150,6 +1211,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        default:
                break;
        }
+
+       if (slot->host->state == STATE_WAITING_CMD11_DONE && ios->clock != 0)
+               slot->host->state = STATE_IDLE;
 }
 
 static int dw_mci_card_busy(struct mmc_host *mmc)
@@ -1323,6 +1387,18 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
        return err;
 }
 
+static int dw_mci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct dw_mci_slot *slot = mmc_priv(mmc);
+       struct dw_mci *host = slot->host;
+       const struct dw_mci_drv_data *drv_data = host->drv_data;
+
+       if (drv_data && drv_data->prepare_hs400_tuning)
+               return drv_data->prepare_hs400_tuning(host, ios);
+
+       return 0;
+}
+
 static const struct mmc_host_ops dw_mci_ops = {
        .request                = dw_mci_request,
        .pre_req                = dw_mci_pre_req,
@@ -1335,6 +1411,7 @@ static const struct mmc_host_ops dw_mci_ops = {
        .card_busy              = dw_mci_card_busy,
        .start_signal_voltage_switch = dw_mci_switch_voltage,
        .init_card              = dw_mci_init_card,
+       .prepare_hs400_tuning   = dw_mci_prepare_hs400_tuning,
 };
 
 static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
@@ -1520,7 +1597,10 @@ static void dw_mci_tasklet_func(unsigned long priv)
                        if (test_and_clear_bit(EVENT_DATA_ERROR,
                                               &host->pending_events)) {
                                dw_mci_stop_dma(host);
-                               send_stop_abort(host, data);
+                               if (data->stop ||
+                                   !(host->data_status & (SDMMC_INT_DRTO |
+                                                          SDMMC_INT_EBE)))
+                                       send_stop_abort(host, data);
                                state = STATE_DATA_ERROR;
                                break;
                        }
@@ -1547,7 +1627,10 @@ static void dw_mci_tasklet_func(unsigned long priv)
                        if (test_and_clear_bit(EVENT_DATA_ERROR,
                                               &host->pending_events)) {
                                dw_mci_stop_dma(host);
-                               send_stop_abort(host, data);
+                               if (data->stop ||
+                                   !(host->data_status & (SDMMC_INT_DRTO |
+                                                          SDMMC_INT_EBE)))
+                                       send_stop_abort(host, data);
                                state = STATE_DATA_ERROR;
                                break;
                        }
@@ -1685,8 +1768,7 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
                buf += len;
                cnt -= len;
                if (host->part_buf_count == 2) {
-                       mci_writew(host, DATA(host->data_offset),
-                                       host->part_buf16);
+                       mci_fifo_writew(host->fifo_reg, host->part_buf16);
                        host->part_buf_count = 0;
                }
        }
@@ -1703,15 +1785,14 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
                        cnt -= len;
                        /* push data from aligned buffer into fifo */
                        for (i = 0; i < items; ++i)
-                               mci_writew(host, DATA(host->data_offset),
-                                               aligned_buf[i]);
+                               mci_fifo_writew(host->fifo_reg, aligned_buf[i]);
                }
        } else
 #endif
        {
                u16 *pdata = buf;
                for (; cnt >= 2; cnt -= 2)
-                       mci_writew(host, DATA(host->data_offset), *pdata++);
+                       mci_fifo_writew(host->fifo_reg, *pdata++);
                buf = pdata;
        }
        /* put anything remaining in the part_buf */
@@ -1720,8 +1801,7 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
                 /* Push data if we have reached the expected data length */
                if ((data->bytes_xfered + init_cnt) ==
                    (data->blksz * data->blocks))
-                       mci_writew(host, DATA(host->data_offset),
-                                  host->part_buf16);
+                       mci_fifo_writew(host->fifo_reg, host->part_buf16);
        }
 }
 
@@ -1736,8 +1816,7 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
                        int items = len >> 1;
                        int i;
                        for (i = 0; i < items; ++i)
-                               aligned_buf[i] = mci_readw(host,
-                                               DATA(host->data_offset));
+                               aligned_buf[i] = mci_fifo_readw(host->fifo_reg);
                        /* memcpy from aligned buffer into output buffer */
                        memcpy(buf, aligned_buf, len);
                        buf += len;
@@ -1748,11 +1827,11 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
        {
                u16 *pdata = buf;
                for (; cnt >= 2; cnt -= 2)
-                       *pdata++ = mci_readw(host, DATA(host->data_offset));
+                       *pdata++ = mci_fifo_readw(host->fifo_reg);
                buf = pdata;
        }
        if (cnt) {
-               host->part_buf16 = mci_readw(host, DATA(host->data_offset));
+               host->part_buf16 = mci_fifo_readw(host->fifo_reg);
                dw_mci_pull_final_bytes(host, buf, cnt);
        }
 }
@@ -1768,8 +1847,7 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
                buf += len;
                cnt -= len;
                if (host->part_buf_count == 4) {
-                       mci_writel(host, DATA(host->data_offset),
-                                       host->part_buf32);
+                       mci_fifo_writel(host->fifo_reg, host->part_buf32);
                        host->part_buf_count = 0;
                }
        }
@@ -1786,15 +1864,14 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
                        cnt -= len;
                        /* push data from aligned buffer into fifo */
                        for (i = 0; i < items; ++i)
-                               mci_writel(host, DATA(host->data_offset),
-                                               aligned_buf[i]);
+                               mci_fifo_writel(host->fifo_reg, aligned_buf[i]);
                }
        } else
 #endif
        {
                u32 *pdata = buf;
                for (; cnt >= 4; cnt -= 4)
-                       mci_writel(host, DATA(host->data_offset), *pdata++);
+                       mci_fifo_writel(host->fifo_reg, *pdata++);
                buf = pdata;
        }
        /* put anything remaining in the part_buf */
@@ -1803,8 +1880,7 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
                 /* Push data if we have reached the expected data length */
                if ((data->bytes_xfered + init_cnt) ==
                    (data->blksz * data->blocks))
-                       mci_writel(host, DATA(host->data_offset),
-                                  host->part_buf32);
+                       mci_fifo_writel(host->fifo_reg, host->part_buf32);
        }
 }
 
@@ -1819,8 +1895,7 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)
                        int items = len >> 2;
                        int i;
                        for (i = 0; i < items; ++i)
-                               aligned_buf[i] = mci_readl(host,
-                                               DATA(host->data_offset));
+                               aligned_buf[i] = mci_fifo_readl(host->fifo_reg);
                        /* memcpy from aligned buffer into output buffer */
                        memcpy(buf, aligned_buf, len);
                        buf += len;
@@ -1831,11 +1906,11 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)
        {
                u32 *pdata = buf;
                for (; cnt >= 4; cnt -= 4)
-                       *pdata++ = mci_readl(host, DATA(host->data_offset));
+                       *pdata++ = mci_fifo_readl(host->fifo_reg);
                buf = pdata;
        }
        if (cnt) {
-               host->part_buf32 = mci_readl(host, DATA(host->data_offset));
+               host->part_buf32 = mci_fifo_readl(host->fifo_reg);
                dw_mci_pull_final_bytes(host, buf, cnt);
        }
 }
@@ -1852,8 +1927,7 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
                cnt -= len;
 
                if (host->part_buf_count == 8) {
-                       mci_writeq(host, DATA(host->data_offset),
-                                       host->part_buf);
+                       mci_fifo_writeq(host->fifo_reg, host->part_buf);
                        host->part_buf_count = 0;
                }
        }
@@ -1870,15 +1944,14 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
                        cnt -= len;
                        /* push data from aligned buffer into fifo */
                        for (i = 0; i < items; ++i)
-                               mci_writeq(host, DATA(host->data_offset),
-                                               aligned_buf[i]);
+                               mci_fifo_writeq(host->fifo_reg, aligned_buf[i]);
                }
        } else
 #endif
        {
                u64 *pdata = buf;
                for (; cnt >= 8; cnt -= 8)
-                       mci_writeq(host, DATA(host->data_offset), *pdata++);
+                       mci_fifo_writeq(host->fifo_reg, *pdata++);
                buf = pdata;
        }
        /* put anything remaining in the part_buf */
@@ -1887,8 +1960,7 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
                /* Push data if we have reached the expected data length */
                if ((data->bytes_xfered + init_cnt) ==
                    (data->blksz * data->blocks))
-                       mci_writeq(host, DATA(host->data_offset),
-                                  host->part_buf);
+                       mci_fifo_writeq(host->fifo_reg, host->part_buf);
        }
 }
 
@@ -1903,8 +1975,8 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)
                        int items = len >> 3;
                        int i;
                        for (i = 0; i < items; ++i)
-                               aligned_buf[i] = mci_readq(host,
-                                               DATA(host->data_offset));
+                               aligned_buf[i] = mci_fifo_readq(host->fifo_reg);
+
                        /* memcpy from aligned buffer into output buffer */
                        memcpy(buf, aligned_buf, len);
                        buf += len;
@@ -1915,11 +1987,11 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)
        {
                u64 *pdata = buf;
                for (; cnt >= 8; cnt -= 8)
-                       *pdata++ = mci_readq(host, DATA(host->data_offset));
+                       *pdata++ = mci_fifo_readq(host->fifo_reg);
                buf = pdata;
        }
        if (cnt) {
-               host->part_buf = mci_readq(host, DATA(host->data_offset));
+               host->part_buf = mci_fifo_readq(host->fifo_reg);
                dw_mci_pull_final_bytes(host, buf, cnt);
        }
 }
@@ -2097,9 +2169,20 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
                /* Check volt switch first, since it can look like an error */
                if ((host->state == STATE_SENDING_CMD11) &&
                    (pending & SDMMC_INT_VOLT_SWITCH)) {
+                       unsigned long irqflags;
+
                        mci_writel(host, RINTSTS, SDMMC_INT_VOLT_SWITCH);
                        pending &= ~SDMMC_INT_VOLT_SWITCH;
+
+                       /*
+                        * Hold the lock; we know cmd11_timer can't be kicked
+                        * off after the lock is released, so safe to delete.
+                        */
+                       spin_lock_irqsave(&host->irq_lock, irqflags);
                        dw_mci_cmd_interrupt(host, pending);
+                       spin_unlock_irqrestore(&host->irq_lock, irqflags);
+
+                       del_timer(&host->cmd11_timer);
                }
 
                if (pending & DW_MCI_CMD_ERROR_FLAGS) {
@@ -2156,6 +2239,10 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
                /* Handle SDIO Interrupts */
                for (i = 0; i < host->num_slots; i++) {
                        struct dw_mci_slot *slot = host->slot[i];
+
+                       if (!slot)
+                               continue;
+
                        if (pending & SDMMC_INT_SDIO(slot->sdio_id)) {
                                mci_writel(host, RINTSTS,
                                           SDMMC_INT_SDIO(slot->sdio_id));
@@ -2506,6 +2593,20 @@ ciu_out:
        return ret;
 }
 
+static void dw_mci_cmd11_timer(unsigned long arg)
+{
+       struct dw_mci *host = (struct dw_mci *)arg;
+
+       if (host->state != STATE_SENDING_CMD11) {
+               dev_warn(host->dev, "Unexpected CMD11 timeout\n");
+               return;
+       }
+
+       host->cmd_status = SDMMC_INT_RTO;
+       set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
+       tasklet_schedule(&host->tasklet);
+}
+
 #ifdef CONFIG_OF
 static struct dw_mci_of_quirks {
        char *quirk;
@@ -2574,6 +2675,34 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 }
 #endif /* CONFIG_OF */
 
+static void dw_mci_enable_cd(struct dw_mci *host)
+{
+       struct dw_mci_board *brd = host->pdata;
+       unsigned long irqflags;
+       u32 temp;
+       int i;
+
+       /* No need for CD if broken card detection */
+       if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
+               return;
+
+       /* No need for CD if all slots have a non-error GPIO */
+       for (i = 0; i < host->num_slots; i++) {
+               struct dw_mci_slot *slot = host->slot[i];
+
+               if (IS_ERR_VALUE(mmc_gpio_get_cd(slot->mmc)))
+                       break;
+       }
+       if (i == host->num_slots)
+               return;
+
+       spin_lock_irqsave(&host->irq_lock, irqflags);
+       temp = mci_readl(host, INTMASK);
+       temp  |= SDMMC_INT_CD;
+       mci_writel(host, INTMASK, temp);
+       spin_unlock_irqrestore(&host->irq_lock, irqflags);
+}
+
 int dw_mci_probe(struct dw_mci *host)
 {
        const struct dw_mci_drv_data *drv_data = host->drv_data;
@@ -2652,6 +2781,9 @@ int dw_mci_probe(struct dw_mci *host)
                }
        }
 
+       setup_timer(&host->cmd11_timer,
+                   dw_mci_cmd11_timer, (unsigned long)host);
+
        host->quirks = host->pdata->quirks;
 
        spin_lock_init(&host->lock);
@@ -2731,9 +2863,9 @@ int dw_mci_probe(struct dw_mci *host)
        dev_info(host->dev, "Version ID is %04x\n", host->verid);
 
        if (host->verid < DW_MMC_240A)
-               host->data_offset = DATA_OFFSET;
+               host->fifo_reg = host->regs + DATA_OFFSET;
        else
-               host->data_offset = DATA_240A_OFFSET;
+               host->fifo_reg = host->regs + DATA_240A_OFFSET;
 
        tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host);
        ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt,
@@ -2747,13 +2879,13 @@ int dw_mci_probe(struct dw_mci *host)
                host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1;
 
        /*
-        * Enable interrupts for command done, data over, data empty, card det,
+        * Enable interrupts for command done, data over, data empty,
         * receive ready and error such as transmit, receive timeout, crc error
         */
        mci_writel(host, RINTSTS, 0xFFFFFFFF);
        mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
                   SDMMC_INT_TXDR | SDMMC_INT_RXDR |
-                  DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
+                  DW_MCI_ERROR_FLAGS);
        mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
 
        dev_info(host->dev, "DW MMC controller at irq %d, "
@@ -2778,6 +2910,9 @@ int dw_mci_probe(struct dw_mci *host)
                goto err_dmaunmap;
        }
 
+       /* Now that slots are all setup, we can enable card detect */
+       dw_mci_enable_cd(host);
+
        if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
                dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
 
@@ -2864,7 +2999,7 @@ int dw_mci_resume(struct dw_mci *host)
        mci_writel(host, RINTSTS, 0xFFFFFFFF);
        mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
                   SDMMC_INT_TXDR | SDMMC_INT_RXDR |
-                  DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
+                  DW_MCI_ERROR_FLAGS);
        mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE);
 
        for (i = 0; i < host->num_slots; i++) {
@@ -2876,6 +3011,10 @@ int dw_mci_resume(struct dw_mci *host)
                        dw_mci_setup_bus(slot, true);
                }
        }
+
+       /* Now that slots are all setup, we can enable card detect */
+       dw_mci_enable_cd(host);
+
        return 0;
 }
 EXPORT_SYMBOL(dw_mci_resume);
index 18c4afe683b83c60d0941230b34735a64f58a6e4..f45ab91de33946ac86abc72ae8305eb1f18aa55e 100644 (file)
 #define SDMMC_CTRL_ALL_RESET_FLAGS \
        (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET)
 
+/* FIFO register access macros. These should not change the data endian-ness
+ * as they are written to memory to be dealt with by the upper layers */
+#define mci_fifo_readw(__reg)  __raw_readw(__reg)
+#define mci_fifo_readl(__reg)  __raw_readl(__reg)
+#define mci_fifo_readq(__reg)  __raw_readq(__reg)
+
+#define mci_fifo_writew(__value, __reg)        __raw_writew(__reg, __value)
+#define mci_fifo_writel(__value, __reg)        __raw_writel(__reg, __value)
+#define mci_fifo_writeq(__value, __reg)        __raw_writeq(__reg, __value)
+
 /* Register access macros */
 #define mci_readl(dev, reg)                    \
-       __raw_readl((dev)->regs + SDMMC_##reg)
+       readl_relaxed((dev)->regs + SDMMC_##reg)
 #define mci_writel(dev, reg, value)                    \
-       __raw_writel((value), (dev)->regs + SDMMC_##reg)
+       writel_relaxed((value), (dev)->regs + SDMMC_##reg)
 
 /* 16-bit FIFO access macros */
 #define mci_readw(dev, reg)                    \
-       __raw_readw((dev)->regs + SDMMC_##reg)
+       readw_relaxed((dev)->regs + SDMMC_##reg)
 #define mci_writew(dev, reg, value)                    \
-       __raw_writew((value), (dev)->regs + SDMMC_##reg)
+       writew_relaxed((value), (dev)->regs + SDMMC_##reg)
 
 /* 64-bit FIFO access macros */
 #ifdef readq
 #define mci_readq(dev, reg)                    \
-       __raw_readq((dev)->regs + SDMMC_##reg)
+       readq_relaxed((dev)->regs + SDMMC_##reg)
 #define mci_writeq(dev, reg, value)                    \
-       __raw_writeq((value), (dev)->regs + SDMMC_##reg)
+       writeq_relaxed((value), (dev)->regs + SDMMC_##reg)
 #else
 /*
  * Dummy readq implementation for architectures that don't define it.
        (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg))
 #define mci_writeq(dev, reg, value)                    \
        (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg) = (value))
+
+#define __raw_writeq(__value, __reg) \
+       (*(volatile u64 __force *)(__reg) = (__value))
+#define __raw_readq(__reg) (*(volatile u64 __force *)(__reg))
 #endif
 
 extern int dw_mci_probe(struct dw_mci *host);
@@ -271,5 +285,7 @@ struct dw_mci_drv_data {
        void            (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
        int             (*parse_dt)(struct dw_mci *host);
        int             (*execute_tuning)(struct dw_mci_slot *slot);
+       int             (*prepare_hs400_tuning)(struct dw_mci *host,
+                                               struct mmc_ios *ios);
 };
 #endif /* _DW_MMC_H_ */
index e4a07546f8b631d4c905dbe483449bf381960279..ae19d83bb9de0d966bb095f73c2f8b900578659a 100644 (file)
@@ -1507,7 +1507,7 @@ static int mmc_spi_remove(struct spi_device *spi)
        return 0;
 }
 
-static struct of_device_id mmc_spi_of_match_table[] = {
+static const struct of_device_id mmc_spi_of_match_table[] = {
        { .compatible = "mmc-spi-slot", },
        {},
 };
index 7fe16194ebc802c65c65a1741f746ff4af42fb2c..fb266745f8240d603956b8b791370ac4764f5a23 100644 (file)
@@ -1613,7 +1613,10 @@ static int mmci_probe(struct amba_device *dev,
        dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max);
 
        /* Get regulators and the supported OCR mask */
-       mmc_regulator_get_supply(mmc);
+       ret = mmc_regulator_get_supply(mmc);
+       if (ret == -EPROBE_DEFER)
+               goto clk_disable;
+
        if (!mmc->ocr_avail)
                mmc->ocr_avail = plat->ocr_mask;
        else if (plat->ocr_mask)
index f84cfb01716d777d159a9bbabf14b4176098b45b..9df2b6801f767c9c0da6904b689299c93d031417 100644 (file)
@@ -222,10 +222,6 @@ struct omap_hsmmc_host {
        struct omap_hsmmc_next  next_data;
        struct  omap_hsmmc_platform_data        *pdata;
 
-       /* To handle board related suspend/resume functionality for MMC */
-       int (*suspend)(struct device *dev);
-       int (*resume)(struct device *dev);
-
        /* return MMC cover switch state, can be NULL if not supported.
         *
         * possible return values:
@@ -234,12 +230,7 @@ struct omap_hsmmc_host {
         */
        int (*get_cover_state)(struct device *dev);
 
-       /* Card detection IRQs */
-       int card_detect_irq;
-
        int (*card_detect)(struct device *dev);
-       int (*get_ro)(struct device *dev);
-
 };
 
 struct omap_mmc_of_data {
@@ -256,13 +247,6 @@ static int omap_hsmmc_card_detect(struct device *dev)
        return mmc_gpio_get_cd(host->mmc);
 }
 
-static int omap_hsmmc_get_wp(struct device *dev)
-{
-       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
-
-       return mmc_gpio_get_ro(host->mmc);
-}
-
 static int omap_hsmmc_get_cover_state(struct device *dev)
 {
        struct omap_hsmmc_host *host = dev_get_drvdata(dev);
@@ -434,7 +418,7 @@ static inline int omap_hsmmc_have_reg(void)
 
 #endif
 
-static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id);
+static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id);
 
 static int omap_hsmmc_gpio_init(struct mmc_host *mmc,
                                struct omap_hsmmc_host *host,
@@ -442,29 +426,25 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc,
 {
        int ret;
 
-       if (gpio_is_valid(pdata->switch_pin)) {
-               if (pdata->cover)
-                       host->get_cover_state =
-                               omap_hsmmc_get_cover_state;
-               else
-                       host->card_detect = omap_hsmmc_card_detect;
-               host->card_detect_irq =
-                               gpio_to_irq(pdata->switch_pin);
-               mmc_gpio_set_cd_isr(mmc, omap_hsmmc_detect);
-               ret = mmc_gpio_request_cd(mmc, pdata->switch_pin, 0);
+       if (gpio_is_valid(pdata->gpio_cod)) {
+               ret = mmc_gpio_request_cd(mmc, pdata->gpio_cod, 0);
                if (ret)
                        return ret;
-       } else {
-               pdata->switch_pin = -EINVAL;
+
+               host->get_cover_state = omap_hsmmc_get_cover_state;
+               mmc_gpio_set_cd_isr(mmc, omap_hsmmc_cover_irq);
+       } else if (gpio_is_valid(pdata->gpio_cd)) {
+               ret = mmc_gpio_request_cd(mmc, pdata->gpio_cd, 0);
+               if (ret)
+                       return ret;
+
+               host->card_detect = omap_hsmmc_card_detect;
        }
 
        if (gpio_is_valid(pdata->gpio_wp)) {
-               host->get_ro = omap_hsmmc_get_wp;
                ret = mmc_gpio_request_ro(mmc, pdata->gpio_wp);
                if (ret)
                        return ret;
-       } else {
-               pdata->gpio_wp = -EINVAL;
        }
 
        return 0;
@@ -882,6 +862,8 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
                return;
        host->mrq = NULL;
        mmc_request_done(host->mmc, mrq);
+       pm_runtime_mark_last_busy(host->dev);
+       pm_runtime_put_autosuspend(host->dev);
 }
 
 /*
@@ -1252,26 +1234,16 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host)
 }
 
 /*
- * irq handler to notify the core about card insertion/removal
+ * irq handler when (cell-phone) cover is mounted/removed
  */
-static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id)
+static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id)
 {
        struct omap_hsmmc_host *host = dev_id;
-       int carddetect;
 
        sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
 
-       if (host->card_detect)
-               carddetect = host->card_detect(host->dev);
-       else {
-               omap_hsmmc_protect_card(host);
-               carddetect = -ENOSYS;
-       }
-
-       if (carddetect)
-               mmc_detect_change(host->mmc, (HZ * 200) / 1000);
-       else
-               mmc_detect_change(host->mmc, (HZ * 50) / 1000);
+       omap_hsmmc_protect_card(host);
+       mmc_detect_change(host->mmc, (HZ * 200) / 1000);
        return IRQ_HANDLED;
 }
 
@@ -1305,6 +1277,8 @@ static void omap_hsmmc_dma_callback(void *param)
 
                host->mrq = NULL;
                mmc_request_done(host->mmc, mrq);
+               pm_runtime_mark_last_busy(host->dev);
+               pm_runtime_put_autosuspend(host->dev);
        }
 }
 
@@ -1537,6 +1511,7 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
 
        BUG_ON(host->req_in_progress);
        BUG_ON(host->dma_ch != -1);
+       pm_runtime_get_sync(host->dev);
        if (host->protect_card) {
                if (host->reqs_blocked < 3) {
                        /*
@@ -1553,6 +1528,8 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
                        req->data->error = -EBADF;
                req->cmd->retries = 0;
                mmc_request_done(mmc, req);
+               pm_runtime_mark_last_busy(host->dev);
+               pm_runtime_put_autosuspend(host->dev);
                return;
        } else if (host->reqs_blocked)
                host->reqs_blocked = 0;
@@ -1566,6 +1543,8 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
                        req->data->error = err;
                host->mrq = NULL;
                mmc_request_done(mmc, req);
+               pm_runtime_mark_last_busy(host->dev);
+               pm_runtime_put_autosuspend(host->dev);
                return;
        }
        if (req->sbc && !(host->flags & AUTO_CMD23)) {
@@ -1641,15 +1620,6 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc)
        return host->card_detect(host->dev);
 }
 
-static int omap_hsmmc_get_ro(struct mmc_host *mmc)
-{
-       struct omap_hsmmc_host *host = mmc_priv(mmc);
-
-       if (!host->get_ro)
-               return -ENOSYS;
-       return host->get_ro(host->dev);
-}
-
 static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card)
 {
        struct omap_hsmmc_host *host = mmc_priv(mmc);
@@ -1778,25 +1748,6 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
        set_sd_bus_power(host);
 }
 
-static int omap_hsmmc_enable_fclk(struct mmc_host *mmc)
-{
-       struct omap_hsmmc_host *host = mmc_priv(mmc);
-
-       pm_runtime_get_sync(host->dev);
-
-       return 0;
-}
-
-static int omap_hsmmc_disable_fclk(struct mmc_host *mmc)
-{
-       struct omap_hsmmc_host *host = mmc_priv(mmc);
-
-       pm_runtime_mark_last_busy(host->dev);
-       pm_runtime_put_autosuspend(host->dev);
-
-       return 0;
-}
-
 static int omap_hsmmc_multi_io_quirk(struct mmc_card *card,
                                     unsigned int direction, int blk_size)
 {
@@ -1808,14 +1759,12 @@ static int omap_hsmmc_multi_io_quirk(struct mmc_card *card,
 }
 
 static struct mmc_host_ops omap_hsmmc_ops = {
-       .enable = omap_hsmmc_enable_fclk,
-       .disable = omap_hsmmc_disable_fclk,
        .post_req = omap_hsmmc_post_req,
        .pre_req = omap_hsmmc_pre_req,
        .request = omap_hsmmc_request,
        .set_ios = omap_hsmmc_set_ios,
        .get_cd = omap_hsmmc_get_cd,
-       .get_ro = omap_hsmmc_get_ro,
+       .get_ro = mmc_gpio_get_ro,
        .init_card = omap_hsmmc_init_card,
        .enable_sdio_irq = omap_hsmmc_enable_sdio_irq,
 };
@@ -1937,7 +1886,8 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
        if (of_find_property(np, "ti,dual-volt", NULL))
                pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT;
 
-       pdata->switch_pin = -EINVAL;
+       pdata->gpio_cd = -EINVAL;
+       pdata->gpio_cod = -EINVAL;
        pdata->gpio_wp = -EINVAL;
 
        if (of_find_property(np, "ti,non-removable", NULL)) {
@@ -2179,9 +2129,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
                if (ret < 0)
                        goto err_slot_name;
        }
-       if (host->card_detect_irq && host->get_cover_state) {
+       if (host->get_cover_state) {
                ret = device_create_file(&mmc->class_dev,
-                                       &dev_attr_cover_switch);
+                                        &dev_attr_cover_switch);
                if (ret < 0)
                        goto err_slot_name;
        }
@@ -2236,7 +2186,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int omap_hsmmc_suspend(struct device *dev)
 {
        struct omap_hsmmc_host *host = dev_get_drvdata(dev);
@@ -2292,10 +2242,6 @@ static int omap_hsmmc_resume(struct device *dev)
        pm_runtime_put_autosuspend(host->dev);
        return 0;
 }
-
-#else
-#define omap_hsmmc_suspend     NULL
-#define omap_hsmmc_resume      NULL
 #endif
 
 static int omap_hsmmc_runtime_suspend(struct device *dev)
@@ -2376,8 +2322,7 @@ static int omap_hsmmc_runtime_resume(struct device *dev)
 }
 
 static struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
-       .suspend        = omap_hsmmc_suspend,
-       .resume         = omap_hsmmc_resume,
+       SET_SYSTEM_SLEEP_PM_OPS(omap_hsmmc_suspend, omap_hsmmc_resume)
        .runtime_suspend = omap_hsmmc_runtime_suspend,
        .runtime_resume = omap_hsmmc_runtime_resume,
 };
index a45ed39d062c1d7a73d557cd3c62e326fbf61652..22d929fa3371adbf87c2efa744b0272701d72741 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/pm.h>
 #include <linux/mmc/slot-gpio.h>
-#include <linux/mmc/sdhci.h>
 
 #include "sdhci.h"
 
index 34bb8f92586e25980ea5467c366e1700884328a5..2bd90fb35c75e5b5c03f243aabd1edc99dce04d5 100644 (file)
@@ -54,7 +54,6 @@
 
 struct sdhci_bcm_kona_dev {
        struct mutex    write_lock; /* protect back to back writes */
-       struct clk      *external_clk;
 };
 
 
@@ -175,24 +174,6 @@ static void sdhci_bcm_kona_card_event(struct sdhci_host *host)
        }
 }
 
-/*
- * Get the base clock. Use central clock source for now. Not sure if different
- * clock speed to each dev is allowed
- */
-static unsigned int sdhci_bcm_kona_get_max_clk(struct sdhci_host *host)
-{
-       struct sdhci_bcm_kona_dev *kona_dev;
-       struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
-       kona_dev = sdhci_pltfm_priv(pltfm_priv);
-
-       return host->mmc->f_max;
-}
-
-static unsigned int sdhci_bcm_kona_get_timeout_clock(struct sdhci_host *host)
-{
-       return sdhci_bcm_kona_get_max_clk(host);
-}
-
 static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host,
                                u8 power_mode)
 {
@@ -207,8 +188,8 @@ static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host,
 
 static struct sdhci_ops sdhci_bcm_kona_ops = {
        .set_clock = sdhci_set_clock,
-       .get_max_clock = sdhci_bcm_kona_get_max_clk,
-       .get_timeout_clock = sdhci_bcm_kona_get_timeout_clock,
+       .get_max_clock = sdhci_pltfm_clk_get_max_clock,
+       .get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
        .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
        .set_bus_width = sdhci_set_bus_width,
        .reset = sdhci_reset,
@@ -264,21 +245,21 @@ static int sdhci_bcm_kona_probe(struct platform_device *pdev)
                goto err_pltfm_free;
        }
 
-       /* Get and enable the external clock */
-       kona_dev->external_clk = devm_clk_get(dev, NULL);
-       if (IS_ERR(kona_dev->external_clk)) {
-               dev_err(dev, "Failed to get external clock\n");
-               ret = PTR_ERR(kona_dev->external_clk);
+       /* Get and enable the core clock */
+       pltfm_priv->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(pltfm_priv->clk)) {
+               dev_err(dev, "Failed to get core clock\n");
+               ret = PTR_ERR(pltfm_priv->clk);
                goto err_pltfm_free;
        }
 
-       if (clk_set_rate(kona_dev->external_clk, host->mmc->f_max) != 0) {
-               dev_err(dev, "Failed to set rate external clock\n");
+       if (clk_set_rate(pltfm_priv->clk, host->mmc->f_max) != 0) {
+               dev_err(dev, "Failed to set rate core clock\n");
                goto err_pltfm_free;
        }
 
-       if (clk_prepare_enable(kona_dev->external_clk) != 0) {
-               dev_err(dev, "Failed to enable external clock\n");
+       if (clk_prepare_enable(pltfm_priv->clk) != 0) {
+               dev_err(dev, "Failed to enable core clock\n");
                goto err_pltfm_free;
        }
 
@@ -333,7 +314,7 @@ err_reset:
        sdhci_bcm_kona_sd_reset(host);
 
 err_clk_disable:
-       clk_disable_unprepare(kona_dev->external_clk);
+       clk_disable_unprepare(pltfm_priv->clk);
 
 err_pltfm_free:
        sdhci_pltfm_free(pdev);
@@ -342,22 +323,6 @@ err_pltfm_free:
        return ret;
 }
 
-static int sdhci_bcm_kona_remove(struct platform_device *pdev)
-{
-       struct sdhci_host *host = platform_get_drvdata(pdev);
-       struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
-       struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv);
-       int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
-
-       sdhci_remove_host(host, dead);
-
-       clk_disable_unprepare(kona_dev->external_clk);
-
-       sdhci_pltfm_free(pdev);
-
-       return 0;
-}
-
 static struct platform_driver sdhci_bcm_kona_driver = {
        .driver         = {
                .name   = "sdhci-kona",
@@ -365,7 +330,7 @@ static struct platform_driver sdhci_bcm_kona_driver = {
                .of_match_table = sdhci_bcm_kona_of_match,
        },
        .probe          = sdhci_bcm_kona_probe,
-       .remove         = sdhci_bcm_kona_remove,
+       .remove         = sdhci_pltfm_unregister,
 };
 module_platform_driver(sdhci_bcm_kona_driver);
 
index 439d259fdf1d571336fe86a3b3de483143430517..0ef0343c603ad492937ef338af8b058ecc9f51e9 100644 (file)
@@ -180,11 +180,6 @@ err:
        return ret;
 }
 
-static int bcm2835_sdhci_remove(struct platform_device *pdev)
-{
-       return sdhci_pltfm_unregister(pdev);
-}
-
 static const struct of_device_id bcm2835_sdhci_of_match[] = {
        { .compatible = "brcm,bcm2835-sdhci" },
        { }
@@ -198,7 +193,7 @@ static struct platform_driver bcm2835_sdhci_driver = {
                .pm = SDHCI_PLTFM_PMOPS,
        },
        .probe = bcm2835_sdhci_probe,
-       .remove = bcm2835_sdhci_remove,
+       .remove = sdhci_pltfm_unregister,
 };
 module_platform_driver(bcm2835_sdhci_driver);
 
index a7935a8d0922218f0874deea4e7f303a35dbb685..59f2923f80547d37f2dd5d8f43d3aeacb49854ce 100644 (file)
@@ -98,18 +98,13 @@ static int sdhci_cns3xxx_probe(struct platform_device *pdev)
        return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata, 0);
 }
 
-static int sdhci_cns3xxx_remove(struct platform_device *pdev)
-{
-       return sdhci_pltfm_unregister(pdev);
-}
-
 static struct platform_driver sdhci_cns3xxx_driver = {
        .driver         = {
                .name   = "sdhci-cns3xxx",
                .pm     = SDHCI_PLTFM_PMOPS,
        },
        .probe          = sdhci_cns3xxx_probe,
-       .remove         = sdhci_cns3xxx_remove,
+       .remove         = sdhci_pltfm_unregister,
 };
 
 module_platform_driver(sdhci_cns3xxx_driver);
index ca969d271a270bfb0bcb6e56fc3626f7398218a5..407c21f152b2dacad43706db77b8a2c5a97c08e8 100644 (file)
 
 #include "sdhci-pltfm.h"
 
-struct sdhci_dove_priv {
-       struct clk *clk;
-};
-
 static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
 {
        u16 ret;
@@ -84,27 +80,17 @@ static int sdhci_dove_probe(struct platform_device *pdev)
 {
        struct sdhci_host *host;
        struct sdhci_pltfm_host *pltfm_host;
-       struct sdhci_dove_priv *priv;
        int ret;
 
-       priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv),
-                           GFP_KERNEL);
-       if (!priv) {
-               dev_err(&pdev->dev, "unable to allocate private data");
-               return -ENOMEM;
-       }
-
-       priv->clk = devm_clk_get(&pdev->dev, NULL);
-
        host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata, 0);
        if (IS_ERR(host))
                return PTR_ERR(host);
 
        pltfm_host = sdhci_priv(host);
-       pltfm_host->priv = priv;
+       pltfm_host->clk = devm_clk_get(&pdev->dev, NULL);
 
-       if (!IS_ERR(priv->clk))
-               clk_prepare_enable(priv->clk);
+       if (!IS_ERR(pltfm_host->clk))
+               clk_prepare_enable(pltfm_host->clk);
 
        ret = mmc_of_parse(host->mmc);
        if (ret)
@@ -117,26 +103,11 @@ static int sdhci_dove_probe(struct platform_device *pdev)
        return 0;
 
 err_sdhci_add:
-       if (!IS_ERR(priv->clk))
-               clk_disable_unprepare(priv->clk);
+       clk_disable_unprepare(pltfm_host->clk);
        sdhci_pltfm_free(pdev);
        return ret;
 }
 
-static int sdhci_dove_remove(struct platform_device *pdev)
-{
-       struct sdhci_host *host = platform_get_drvdata(pdev);
-       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct sdhci_dove_priv *priv = pltfm_host->priv;
-
-       sdhci_pltfm_unregister(pdev);
-
-       if (!IS_ERR(priv->clk))
-               clk_disable_unprepare(priv->clk);
-
-       return 0;
-}
-
 static const struct of_device_id sdhci_dove_of_match_table[] = {
        { .compatible = "marvell,dove-sdhci", },
        {}
@@ -150,7 +121,7 @@ static struct platform_driver sdhci_dove_driver = {
                .of_match_table = sdhci_dove_of_match_table,
        },
        .probe          = sdhci_dove_probe,
-       .remove         = sdhci_dove_remove,
+       .remove         = sdhci_pltfm_unregister,
 };
 
 module_platform_driver(sdhci_dove_driver);
index 10ef8244a239632819fd2f399bf1ee48b2bb8496..82f512d87cb8916e76314f465339c820ef92b1f1 100644 (file)
@@ -416,7 +416,7 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
                        new_val |= ESDHC_VENDOR_SPEC_FRC_SDCLK_ON;
                else
                        new_val &= ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON;
-                       writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
+               writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
                return;
        case SDHCI_HOST_CONTROL2:
                new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
@@ -864,6 +864,7 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
 #ifdef CONFIG_OF
 static int
 sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
+                        struct sdhci_host *host,
                         struct esdhc_platform_data *boarddata)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -900,11 +901,14 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
        if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line))
                boarddata->delay_line = 0;
 
+       mmc_of_parse_voltage(np, &host->ocr_mask);
+
        return 0;
 }
 #else
 static inline int
 sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
+                        struct sdhci_host *host,
                         struct esdhc_platform_data *boarddata)
 {
        return -ENODEV;
@@ -999,7 +1003,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
                        host->ioaddr + ESDHC_TUNING_CTRL);
 
        boarddata = &imx_data->boarddata;
-       if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
+       if (sdhci_esdhc_imx_probe_dt(pdev, host, boarddata) < 0) {
                if (!host->mmc->parent->platform_data) {
                        dev_err(mmc_dev(host->mmc), "no board data!\n");
                        err = -EINVAL;
@@ -1009,40 +1013,9 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
                                        host->mmc->parent->platform_data);
        }
 
-       /* write_protect */
-       if (boarddata->wp_type == ESDHC_WP_GPIO) {
-               err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio);
-               if (err) {
-                       dev_err(mmc_dev(host->mmc),
-                               "failed to request write-protect gpio!\n");
-                       goto disable_clk;
-               }
-               host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
-       }
-
        /* card_detect */
-       switch (boarddata->cd_type) {
-       case ESDHC_CD_GPIO:
-               err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0);
-               if (err) {
-                       dev_err(mmc_dev(host->mmc),
-                               "failed to request card-detect gpio!\n");
-                       goto disable_clk;
-               }
-               /* fall through */
-
-       case ESDHC_CD_CONTROLLER:
-               /* we have a working card_detect back */
+       if (boarddata->cd_type == ESDHC_CD_CONTROLLER)
                host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
-               break;
-
-       case ESDHC_CD_PERMANENT:
-               host->mmc->caps |= MMC_CAP_NONREMOVABLE;
-               break;
-
-       case ESDHC_CD_NONE:
-               break;
-       }
 
        switch (boarddata->max_bus_width) {
        case 8:
@@ -1075,6 +1048,11 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
                host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
        }
 
+       /* call to generic mmc_of_parse to support additional capabilities */
+       err = mmc_of_parse(host->mmc);
+       if (err)
+               goto disable_clk;
+
        err = sdhci_add_host(host);
        if (err)
                goto disable_clk;
diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c
new file mode 100644 (file)
index 0000000..3b423b0
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2014 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * iProc SDHCI platform driver
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/mmc/host.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include "sdhci-pltfm.h"
+
+struct sdhci_iproc_data {
+       const struct sdhci_pltfm_data *pdata;
+       u32 caps;
+       u32 caps1;
+};
+
+struct sdhci_iproc_host {
+       const struct sdhci_iproc_data *data;
+       u32 shadow_cmd;
+       u32 shadow_blk;
+};
+
+#define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18)
+
+static inline u32 sdhci_iproc_readl(struct sdhci_host *host, int reg)
+{
+       u32 val = readl(host->ioaddr + reg);
+
+       pr_debug("%s: readl [0x%02x] 0x%08x\n",
+                mmc_hostname(host->mmc), reg, val);
+       return val;
+}
+
+static u16 sdhci_iproc_readw(struct sdhci_host *host, int reg)
+{
+       u32 val = sdhci_iproc_readl(host, (reg & ~3));
+       u16 word = val >> REG_OFFSET_IN_BITS(reg) & 0xffff;
+       return word;
+}
+
+static u8 sdhci_iproc_readb(struct sdhci_host *host, int reg)
+{
+       u32 val = sdhci_iproc_readl(host, (reg & ~3));
+       u8 byte = val >> REG_OFFSET_IN_BITS(reg) & 0xff;
+       return byte;
+}
+
+static inline void sdhci_iproc_writel(struct sdhci_host *host, u32 val, int reg)
+{
+       pr_debug("%s: writel [0x%02x] 0x%08x\n",
+                mmc_hostname(host->mmc), reg, val);
+
+       writel(val, host->ioaddr + reg);
+
+       if (host->clock <= 400000) {
+               /* Round up to micro-second four SD clock delay */
+               if (host->clock)
+                       udelay((4 * 1000000 + host->clock - 1) / host->clock);
+               else
+                       udelay(10);
+       }
+}
+
+/*
+ * The Arasan has a bugette whereby it may lose the content of successive
+ * writes to the same register that are within two SD-card clock cycles of
+ * each other (a clock domain crossing problem). The data
+ * register does not have this problem, which is just as well - otherwise we'd
+ * have to nobble the DMA engine too.
+ *
+ * This wouldn't be a problem with the code except that we can only write the
+ * controller with 32-bit writes.  So two different 16-bit registers are
+ * written back to back creates the problem.
+ *
+ * In reality, this only happens when SDHCI_BLOCK_SIZE and SDHCI_BLOCK_COUNT
+ * are written followed by SDHCI_TRANSFER_MODE and SDHCI_COMMAND.
+ * The BLOCK_SIZE and BLOCK_COUNT are meaningless until a command issued so
+ * the work around can be further optimized. We can keep shadow values of
+ * BLOCK_SIZE, BLOCK_COUNT, and TRANSFER_MODE until a COMMAND is issued.
+ * Then, write the BLOCK_SIZE+BLOCK_COUNT in a single 32-bit write followed
+ * by the TRANSFER+COMMAND in another 32-bit write.
+ */
+static void sdhci_iproc_writew(struct sdhci_host *host, u16 val, int reg)
+{
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_iproc_host *iproc_host = sdhci_pltfm_priv(pltfm_host);
+       u32 word_shift = REG_OFFSET_IN_BITS(reg);
+       u32 mask = 0xffff << word_shift;
+       u32 oldval, newval;
+
+       if (reg == SDHCI_COMMAND) {
+               /* Write the block now as we are issuing a command */
+               if (iproc_host->shadow_blk != 0) {
+                       sdhci_iproc_writel(host, iproc_host->shadow_blk,
+                               SDHCI_BLOCK_SIZE);
+                       iproc_host->shadow_blk = 0;
+               }
+               oldval = iproc_host->shadow_cmd;
+       } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) {
+               /* Block size and count are stored in shadow reg */
+               oldval = iproc_host->shadow_blk;
+       } else {
+               /* Read reg, all other registers are not shadowed */
+               oldval = sdhci_iproc_readl(host, (reg & ~3));
+       }
+       newval = (oldval & ~mask) | (val << word_shift);
+
+       if (reg == SDHCI_TRANSFER_MODE) {
+               /* Save the transfer mode until the command is issued */
+               iproc_host->shadow_cmd = newval;
+       } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) {
+               /* Save the block info until the command is issued */
+               iproc_host->shadow_blk = newval;
+       } else {
+               /* Command or other regular 32-bit write */
+               sdhci_iproc_writel(host, newval, reg & ~3);
+       }
+}
+
+static void sdhci_iproc_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+       u32 oldval = sdhci_iproc_readl(host, (reg & ~3));
+       u32 byte_shift = REG_OFFSET_IN_BITS(reg);
+       u32 mask = 0xff << byte_shift;
+       u32 newval = (oldval & ~mask) | (val << byte_shift);
+
+       sdhci_iproc_writel(host, newval, reg & ~3);
+}
+
+static const struct sdhci_ops sdhci_iproc_ops = {
+       .read_l = sdhci_iproc_readl,
+       .read_w = sdhci_iproc_readw,
+       .read_b = sdhci_iproc_readb,
+       .write_l = sdhci_iproc_writel,
+       .write_w = sdhci_iproc_writew,
+       .write_b = sdhci_iproc_writeb,
+       .set_clock = sdhci_set_clock,
+       .get_max_clock = sdhci_pltfm_clk_get_max_clock,
+       .set_bus_width = sdhci_set_bus_width,
+       .reset = sdhci_reset,
+       .set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
+static const struct sdhci_pltfm_data sdhci_iproc_pltfm_data = {
+       .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
+       .quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN,
+       .ops = &sdhci_iproc_ops,
+};
+
+static const struct sdhci_iproc_data iproc_data = {
+       .pdata = &sdhci_iproc_pltfm_data,
+       .caps = 0x05E90000,
+       .caps1 = 0x00000064,
+};
+
+static const struct of_device_id sdhci_iproc_of_match[] = {
+       { .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_data },
+       { }
+};
+MODULE_DEVICE_TABLE(of, sdhci_iproc_of_match);
+
+static int sdhci_iproc_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *match;
+       const struct sdhci_iproc_data *iproc_data;
+       struct sdhci_host *host;
+       struct sdhci_iproc_host *iproc_host;
+       struct sdhci_pltfm_host *pltfm_host;
+       int ret;
+
+       match = of_match_device(sdhci_iproc_of_match, &pdev->dev);
+       if (!match)
+               return -EINVAL;
+       iproc_data = match->data;
+
+       host = sdhci_pltfm_init(pdev, iproc_data->pdata, sizeof(*iproc_host));
+       if (IS_ERR(host))
+               return PTR_ERR(host);
+
+       pltfm_host = sdhci_priv(host);
+       iproc_host = sdhci_pltfm_priv(pltfm_host);
+
+       iproc_host->data = iproc_data;
+
+       mmc_of_parse(host->mmc);
+       sdhci_get_of_property(pdev);
+
+       /* Enable EMMC 1/8V DDR capable */
+       host->mmc->caps |= MMC_CAP_1_8V_DDR;
+
+       pltfm_host->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(pltfm_host->clk)) {
+               ret = PTR_ERR(pltfm_host->clk);
+               goto err;
+       }
+
+       if (iproc_host->data->pdata->quirks & SDHCI_QUIRK_MISSING_CAPS) {
+               host->caps = iproc_host->data->caps;
+               host->caps1 = iproc_host->data->caps1;
+       }
+
+       return sdhci_add_host(host);
+
+err:
+       sdhci_pltfm_free(pdev);
+       return ret;
+}
+
+static int sdhci_iproc_remove(struct platform_device *pdev)
+{
+       return sdhci_pltfm_unregister(pdev);
+}
+
+static struct platform_driver sdhci_iproc_driver = {
+       .driver = {
+               .name = "sdhci-iproc",
+               .of_match_table = sdhci_iproc_of_match,
+               .pm = SDHCI_PLTFM_PMOPS,
+       },
+       .probe = sdhci_iproc_probe,
+       .remove = sdhci_iproc_remove,
+};
+module_platform_driver(sdhci_iproc_driver);
+
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("IPROC SDHCI driver");
+MODULE_LICENSE("GPL v2");
index 3d32ce896b091f51cdfd74b383ade7ad6e8477a7..4a09f7608c66affcede7565ea7c75c41bb10f6ba 100644 (file)
 
 #include "sdhci-pltfm.h"
 
+#define CORE_MCI_VERSION               0x50
+#define CORE_VERSION_MAJOR_SHIFT       28
+#define CORE_VERSION_MAJOR_MASK                (0xf << CORE_VERSION_MAJOR_SHIFT)
+#define CORE_VERSION_MINOR_MASK                0xff
+
 #define CORE_HC_MODE           0x78
 #define HC_MODE_EN             0x1
 #define CORE_POWER             0x0
@@ -41,6 +46,8 @@
 #define CORE_VENDOR_SPEC       0x10c
 #define CORE_CLK_PWRSAVE       BIT(1)
 
+#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
+
 #define CDR_SELEXT_SHIFT       20
 #define CDR_SELEXT_MASK                (0xf << CDR_SELEXT_SHIFT)
 #define CMUX_SHIFT_PHASE_SHIFT 24
@@ -426,7 +433,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
        struct sdhci_msm_host *msm_host;
        struct resource *core_memres;
        int ret;
-       u16 host_version;
+       u16 host_version, core_minor;
+       u32 core_version, caps;
+       u8 core_major;
 
        msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL);
        if (!msm_host)
@@ -516,6 +525,24 @@ static int sdhci_msm_probe(struct platform_device *pdev)
                host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >>
                               SDHCI_VENDOR_VER_SHIFT));
 
+       core_version = readl_relaxed(msm_host->core_mem + CORE_MCI_VERSION);
+       core_major = (core_version & CORE_VERSION_MAJOR_MASK) >>
+                     CORE_VERSION_MAJOR_SHIFT;
+       core_minor = core_version & CORE_VERSION_MINOR_MASK;
+       dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n",
+               core_version, core_major, core_minor);
+
+       /*
+        * Support for some capabilities is not advertised by newer
+        * controller versions and must be explicitly enabled.
+        */
+       if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) {
+               caps = readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES);
+               caps |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT;
+               writel_relaxed(caps, host->ioaddr +
+                              CORE_VENDOR_SPEC_CAPABILITIES0);
+       }
+
        ret = sdhci_add_host(host);
        if (ret)
                goto clk_disable;
index bcb51e9dfdcd0789866ca7739a60444106f88770..6287d426c96bf933237aa948881b5bce53215fcb 100644 (file)
@@ -173,6 +173,12 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
        pltfm_host->priv = sdhci_arasan;
        pltfm_host->clk = clk_xin;
 
+       ret = mmc_of_parse(host->mmc);
+       if (ret) {
+               dev_err(&pdev->dev, "parsing dt failed (%u)\n", ret);
+               goto clk_disable_all;
+       }
+
        ret = sdhci_add_host(host);
        if (ret)
                goto err_pltfm_free;
@@ -195,7 +201,6 @@ static int sdhci_arasan_remove(struct platform_device *pdev)
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv;
 
-       clk_disable_unprepare(pltfm_host->clk);
        clk_disable_unprepare(sdhci_arasan->clk_ahb);
 
        return sdhci_pltfm_unregister(pdev);
index 17fe02ed667263a710f1aff755a8f94049c641a2..22e9111b11ffcbfcfcfeba35ba9ab260256a9de7 100644 (file)
@@ -386,11 +386,6 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int sdhci_esdhc_remove(struct platform_device *pdev)
-{
-       return sdhci_pltfm_unregister(pdev);
-}
-
 static const struct of_device_id sdhci_esdhc_of_match[] = {
        { .compatible = "fsl,mpc8379-esdhc" },
        { .compatible = "fsl,mpc8536-esdhc" },
@@ -406,7 +401,7 @@ static struct platform_driver sdhci_esdhc_driver = {
                .pm = ESDHC_PMOPS,
        },
        .probe = sdhci_esdhc_probe,
-       .remove = sdhci_esdhc_remove,
+       .remove = sdhci_pltfm_unregister,
 };
 
 module_platform_driver(sdhci_esdhc_driver);
index be479279a1d55479bad67654e855fa71781678ea..4079a96ad37e46e23522e11682f232191c50613d 100644 (file)
@@ -75,11 +75,6 @@ static int sdhci_hlwd_probe(struct platform_device *pdev)
        return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata, 0);
 }
 
-static int sdhci_hlwd_remove(struct platform_device *pdev)
-{
-       return sdhci_pltfm_unregister(pdev);
-}
-
 static const struct of_device_id sdhci_hlwd_of_match[] = {
        { .compatible = "nintendo,hollywood-sdhci" },
        { }
@@ -93,7 +88,7 @@ static struct platform_driver sdhci_hlwd_driver = {
                .pm = SDHCI_PLTFM_PMOPS,
        },
        .probe = sdhci_hlwd_probe,
-       .remove = sdhci_hlwd_remove,
+       .remove = sdhci_pltfm_unregister,
 };
 
 module_platform_driver(sdhci_hlwd_driver);
index 29eaff78238e9ee3dd50b9e4054522ffdf035a5f..7a3fc16d0a6c601fdb65cac29451232f5f6d30aa 100644 (file)
@@ -650,6 +650,7 @@ static int rtsx_probe_slot(struct sdhci_pci_slot *slot)
 
 static const struct sdhci_pci_fixes sdhci_rtsx = {
        .quirks2        = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
+                       SDHCI_QUIRK2_BROKEN_64_BIT_DMA |
                        SDHCI_QUIRK2_BROKEN_DDR50,
        .probe_slot     = rtsx_probe_slot,
 };
index c5b01d6bb85d41fdf236473b4f2b25cae9ee68f5..a207f5aaf62f53d7aa4db3699b4d695f9ce5d625 100644 (file)
@@ -75,43 +75,41 @@ void sdhci_get_of_property(struct platform_device *pdev)
        u32 bus_width;
        int size;
 
-       if (of_device_is_available(np)) {
-               if (of_get_property(np, "sdhci,auto-cmd12", NULL))
-                       host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+       if (of_get_property(np, "sdhci,auto-cmd12", NULL))
+               host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
 
-               if (of_get_property(np, "sdhci,1-bit-only", NULL) ||
-                   (of_property_read_u32(np, "bus-width", &bus_width) == 0 &&
-                   bus_width == 1))
-                       host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
+       if (of_get_property(np, "sdhci,1-bit-only", NULL) ||
+           (of_property_read_u32(np, "bus-width", &bus_width) == 0 &&
+           bus_width == 1))
+               host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
 
-               if (sdhci_of_wp_inverted(np))
-                       host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
+       if (sdhci_of_wp_inverted(np))
+               host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
 
-               if (of_get_property(np, "broken-cd", NULL))
-                       host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+       if (of_get_property(np, "broken-cd", NULL))
+               host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
 
-               if (of_get_property(np, "no-1-8-v", NULL))
-                       host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
+       if (of_get_property(np, "no-1-8-v", NULL))
+               host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
 
-               if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc"))
-                       host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
+       if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc"))
+               host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
 
-               if (of_device_is_compatible(np, "fsl,p2020-esdhc") ||
-                   of_device_is_compatible(np, "fsl,p1010-esdhc") ||
-                   of_device_is_compatible(np, "fsl,t4240-esdhc") ||
-                   of_device_is_compatible(np, "fsl,mpc8536-esdhc"))
-                       host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+       if (of_device_is_compatible(np, "fsl,p2020-esdhc") ||
+           of_device_is_compatible(np, "fsl,p1010-esdhc") ||
+           of_device_is_compatible(np, "fsl,t4240-esdhc") ||
+           of_device_is_compatible(np, "fsl,mpc8536-esdhc"))
+               host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
-               clk = of_get_property(np, "clock-frequency", &size);
-               if (clk && size == sizeof(*clk) && *clk)
-                       pltfm_host->clock = be32_to_cpup(clk);
+       clk = of_get_property(np, "clock-frequency", &size);
+       if (clk && size == sizeof(*clk) && *clk)
+               pltfm_host->clock = be32_to_cpup(clk);
 
-               if (of_find_property(np, "keep-power-in-suspend", NULL))
-                       host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
+       if (of_find_property(np, "keep-power-in-suspend", NULL))
+               host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
 
-               if (of_find_property(np, "enable-sdio-wakeup", NULL))
-                       host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
-       }
+       if (of_find_property(np, "enable-sdio-wakeup", NULL))
+               host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
 }
 #else
 void sdhci_get_of_property(struct platform_device *pdev) {}
@@ -225,9 +223,11 @@ EXPORT_SYMBOL_GPL(sdhci_pltfm_register);
 int sdhci_pltfm_unregister(struct platform_device *pdev)
 {
        struct sdhci_host *host = platform_get_drvdata(pdev);
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
 
        sdhci_remove_host(host, dead);
+       clk_disable_unprepare(pltfm_host->clk);
        sdhci_pltfm_free(pdev);
 
        return 0;
index f6f82ec3618d66bb6bf8a54fa7e118c71d7acb10..32848eb7ad807d70acee4a8125e21f509f24f65e 100644 (file)
 #define SIRF_TUNING_COUNT 128
 
 struct sdhci_sirf_priv {
-       struct clk *clk;
        int gpio_cd;
 };
 
-static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host)
-{
-       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host);
-       return clk_get_rate(priv->clk);
-}
-
 static void sdhci_sirf_set_bus_width(struct sdhci_host *host, int width)
 {
        u8 ctrl;
@@ -56,7 +48,7 @@ static int sdhci_sirf_execute_tuning(struct sdhci_host *host, u32 opcode)
        int tuning_seq_cnt = 3;
        u8 phase, tuned_phases[SIRF_TUNING_COUNT];
        u8 tuned_phase_cnt = 0;
-       int rc, longest_range = 0;
+       int rc = 0, longest_range = 0;
        int start = -1, end = 0, tuning_value = -1, range = 0;
        u16 clock_setting;
        struct mmc_host *mmc = host->mmc;
@@ -68,7 +60,7 @@ retry:
        phase = 0;
        do {
                sdhci_writel(host,
-                       clock_setting | phase | (phase << 7) | (phase << 16),
+                       clock_setting | phase,
                        SDHCI_CLK_DELAY_SETTING);
 
                if (!mmc_send_tuning(mmc)) {
@@ -102,7 +94,7 @@ retry:
                 */
                phase = tuning_value;
                sdhci_writel(host,
-                       clock_setting | phase | (phase << 7) | (phase << 16),
+                       clock_setting | phase,
                        SDHCI_CLK_DELAY_SETTING);
 
                dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n",
@@ -122,7 +114,7 @@ retry:
 static struct sdhci_ops sdhci_sirf_ops = {
        .platform_execute_tuning = sdhci_sirf_execute_tuning,
        .set_clock = sdhci_set_clock,
-       .get_max_clock  = sdhci_sirf_get_max_clk,
+       .get_max_clock  = sdhci_pltfm_clk_get_max_clock,
        .set_bus_width = sdhci_sirf_set_bus_width,
        .reset = sdhci_reset,
        .set_uhs_signaling = sdhci_set_uhs_signaling,
@@ -162,13 +154,13 @@ static int sdhci_sirf_probe(struct platform_device *pdev)
                return PTR_ERR(host);
 
        pltfm_host = sdhci_priv(host);
+       pltfm_host->clk = clk;
        priv = sdhci_pltfm_priv(pltfm_host);
-       priv->clk = clk;
        priv->gpio_cd = gpio_cd;
 
        sdhci_get_of_property(pdev);
 
-       ret = clk_prepare_enable(priv->clk);
+       ret = clk_prepare_enable(pltfm_host->clk);
        if (ret)
                goto err_clk_prepare;
 
@@ -195,37 +187,24 @@ static int sdhci_sirf_probe(struct platform_device *pdev)
 err_request_cd:
        sdhci_remove_host(host, 0);
 err_sdhci_add:
-       clk_disable_unprepare(priv->clk);
+       clk_disable_unprepare(pltfm_host->clk);
 err_clk_prepare:
        sdhci_pltfm_free(pdev);
        return ret;
 }
 
-static int sdhci_sirf_remove(struct platform_device *pdev)
-{
-       struct sdhci_host *host = platform_get_drvdata(pdev);
-       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host);
-
-       sdhci_pltfm_unregister(pdev);
-
-       clk_disable_unprepare(priv->clk);
-       return 0;
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int sdhci_sirf_suspend(struct device *dev)
 {
        struct sdhci_host *host = dev_get_drvdata(dev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host);
        int ret;
 
        ret = sdhci_suspend_host(host);
        if (ret)
                return ret;
 
-       clk_disable(priv->clk);
+       clk_disable(pltfm_host->clk);
 
        return 0;
 }
@@ -234,10 +213,9 @@ static int sdhci_sirf_resume(struct device *dev)
 {
        struct sdhci_host *host = dev_get_drvdata(dev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host);
        int ret;
 
-       ret = clk_enable(priv->clk);
+       ret = clk_enable(pltfm_host->clk);
        if (ret) {
                dev_dbg(dev, "Resume: Error enabling clock\n");
                return ret;
@@ -264,7 +242,7 @@ static struct platform_driver sdhci_sirf_driver = {
 #endif
        },
        .probe          = sdhci_sirf_probe,
-       .remove         = sdhci_sirf_remove,
+       .remove         = sdhci_pltfm_unregister,
 };
 
 module_platform_driver(sdhci_sirf_driver);
index 22e58268545f0b028ee3cd82d4fa7e50a49a4558..df088343d60f32413a3694813ad97f9abb57b7ae 100644 (file)
 #include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/sdhci-spear.h>
 #include <linux/mmc/slot-gpio.h>
 #include <linux/io.h>
 #include "sdhci.h"
 
 struct spear_sdhci {
        struct clk *clk;
-       struct sdhci_plat_data *data;
+       int card_int_gpio;
 };
 
 /* sdhci ops */
@@ -44,38 +43,20 @@ static const struct sdhci_ops sdhci_pltfm_ops = {
        .set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
-#ifdef CONFIG_OF
-static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev)
+static void sdhci_probe_config_dt(struct device_node *np,
+                               struct spear_sdhci *host)
 {
-       struct device_node *np = pdev->dev.of_node;
-       struct sdhci_plat_data *pdata = NULL;
        int cd_gpio;
 
        cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
        if (!gpio_is_valid(cd_gpio))
                cd_gpio = -1;
 
-       /* If pdata is required */
-       if (cd_gpio != -1) {
-               pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-               if (!pdata)
-                       dev_err(&pdev->dev, "DT: kzalloc failed\n");
-               else
-                       pdata->card_int_gpio = cd_gpio;
-       }
-
-       return pdata;
-}
-#else
-static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev)
-{
-       return ERR_PTR(-ENOSYS);
+       host->card_int_gpio = cd_gpio;
 }
-#endif
 
 static int sdhci_probe(struct platform_device *pdev)
 {
-       struct device_node *np = pdev->dev.of_node;
        struct sdhci_host *host;
        struct resource *iomem;
        struct spear_sdhci *sdhci;
@@ -124,28 +105,18 @@ static int sdhci_probe(struct platform_device *pdev)
                dev_dbg(&pdev->dev, "Error setting desired clk, clk=%lu\n",
                                clk_get_rate(sdhci->clk));
 
-       if (np) {
-               sdhci->data = sdhci_probe_config_dt(pdev);
-               if (IS_ERR(sdhci->data)) {
-                       dev_err(&pdev->dev, "DT: Failed to get pdata\n");
-                       goto disable_clk;
-               }
-       } else {
-               sdhci->data = dev_get_platdata(&pdev->dev);
-       }
-
+       sdhci_probe_config_dt(pdev->dev.of_node, sdhci);
        /*
         * It is optional to use GPIOs for sdhci card detection. If
-        * sdhci->data is NULL, then use original sdhci lines otherwise
+        * sdhci->card_int_gpio < 0, then use original sdhci lines otherwise
         * GPIO lines. We use the built-in GPIO support for this.
         */
-       if (sdhci->data && sdhci->data->card_int_gpio >= 0) {
-               ret = mmc_gpio_request_cd(host->mmc,
-                                         sdhci->data->card_int_gpio, 0);
+       if (sdhci->card_int_gpio >= 0) {
+               ret = mmc_gpio_request_cd(host->mmc, sdhci->card_int_gpio, 0);
                if (ret < 0) {
                        dev_dbg(&pdev->dev,
                                "failed to request card-detect gpio%d\n",
-                               sdhci->data->card_int_gpio);
+                               sdhci->card_int_gpio);
                        goto disable_clk;
                }
        }
index 882b07e9667e20d3675620152cf108fc55f2a3ae..682f2bb0f4bf3dc200ccb3bf0451a8759f1cd363 100644 (file)
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/mmc/host.h>
-
+#include <linux/reset.h>
 #include "sdhci-pltfm.h"
 
+struct st_mmc_platform_data {
+       struct  reset_control *rstc;
+       void __iomem *top_ioaddr;
+};
+
+/* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */
+
+#define ST_MMC_CCONFIG_REG_1           0x400
+#define ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT        BIT(24)
+#define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ        BIT(12)
+#define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT    BIT(8)
+#define ST_MMC_CCONFIG_ASYNC_WAKEUP    BIT(0)
+#define ST_MMC_CCONFIG_1_DEFAULT       \
+                               ((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \
+                                (ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \
+                                (ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT))
+
+#define ST_MMC_CCONFIG_REG_2           0x404
+#define ST_MMC_CCONFIG_HIGH_SPEED      BIT(28)
+#define ST_MMC_CCONFIG_ADMA2           BIT(24)
+#define ST_MMC_CCONFIG_8BIT            BIT(20)
+#define ST_MMC_CCONFIG_MAX_BLK_LEN     16
+#define  MAX_BLK_LEN_1024              1
+#define  MAX_BLK_LEN_2048              2
+#define BASE_CLK_FREQ_200              0xc8
+#define BASE_CLK_FREQ_100              0x64
+#define BASE_CLK_FREQ_50               0x32
+#define ST_MMC_CCONFIG_2_DEFAULT \
+       (ST_MMC_CCONFIG_HIGH_SPEED | ST_MMC_CCONFIG_ADMA2 | \
+        ST_MMC_CCONFIG_8BIT | \
+        (MAX_BLK_LEN_1024 << ST_MMC_CCONFIG_MAX_BLK_LEN))
+
+#define ST_MMC_CCONFIG_REG_3                   0x408
+#define ST_MMC_CCONFIG_EMMC_SLOT_TYPE          BIT(28)
+#define ST_MMC_CCONFIG_64BIT                   BIT(24)
+#define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT     BIT(20)
+#define ST_MMC_CCONFIG_1P8_VOLT                        BIT(16)
+#define ST_MMC_CCONFIG_3P0_VOLT                        BIT(12)
+#define ST_MMC_CCONFIG_3P3_VOLT                        BIT(8)
+#define ST_MMC_CCONFIG_SUSP_RES_SUPPORT                BIT(4)
+#define ST_MMC_CCONFIG_SDMA                    BIT(0)
+#define ST_MMC_CCONFIG_3_DEFAULT       \
+                        (ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT    | \
+                         ST_MMC_CCONFIG_3P3_VOLT               | \
+                         ST_MMC_CCONFIG_SUSP_RES_SUPPORT       | \
+                         ST_MMC_CCONFIG_SDMA)
+
+#define ST_MMC_CCONFIG_REG_4   0x40c
+#define ST_MMC_CCONFIG_D_DRIVER        BIT(20)
+#define ST_MMC_CCONFIG_C_DRIVER        BIT(16)
+#define ST_MMC_CCONFIG_A_DRIVER        BIT(12)
+#define ST_MMC_CCONFIG_DDR50   BIT(8)
+#define ST_MMC_CCONFIG_SDR104  BIT(4)
+#define ST_MMC_CCONFIG_SDR50   BIT(0)
+#define ST_MMC_CCONFIG_4_DEFAULT       0
+
+#define ST_MMC_CCONFIG_REG_5           0x410
+#define ST_MMC_CCONFIG_TUNING_FOR_SDR50        BIT(8)
+#define RETUNING_TIMER_CNT_MAX         0xf
+#define ST_MMC_CCONFIG_5_DEFAULT       0
+
+/* I/O configuration for Arasan IP */
+#define ST_MMC_GP_OUTPUT       0x450
+#define ST_MMC_GP_OUTPUT_CD    BIT(12)
+
+#define ST_MMC_STATUS_R                0x460
+
+#define ST_TOP_MMC_DLY_FIX_OFF(x)      (x - 0x8)
+
+/* TOP config registers to manage static and dynamic delay */
+#define ST_TOP_MMC_TX_CLK_DLY                  ST_TOP_MMC_DLY_FIX_OFF(0x8)
+#define ST_TOP_MMC_RX_CLK_DLY                  ST_TOP_MMC_DLY_FIX_OFF(0xc)
+/* MMC delay control register */
+#define ST_TOP_MMC_DLY_CTRL                    ST_TOP_MMC_DLY_FIX_OFF(0x18)
+#define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_CMD     BIT(0)
+#define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_PH_SEL  BIT(1)
+#define ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE      BIT(8)
+#define ST_TOP_MMC_DLY_CTRL_RX_DLL_ENABLE      BIT(9)
+#define ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY  BIT(10)
+#define ST_TOP_MMC_START_DLL_LOCK              BIT(11)
+
+/* register to provide the phase-shift value for DLL */
+#define ST_TOP_MMC_TX_DLL_STEP_DLY             ST_TOP_MMC_DLY_FIX_OFF(0x1c)
+#define ST_TOP_MMC_RX_DLL_STEP_DLY             ST_TOP_MMC_DLY_FIX_OFF(0x20)
+#define ST_TOP_MMC_RX_CMD_STEP_DLY             ST_TOP_MMC_DLY_FIX_OFF(0x24)
+
+/* phase shift delay on the tx clk 2.188ns */
+#define ST_TOP_MMC_TX_DLL_STEP_DLY_VALID       0x6
+
+#define ST_TOP_MMC_DLY_MAX                     0xf
+
+#define ST_TOP_MMC_DYN_DLY_CONF        \
+               (ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE | \
+                ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \
+                ST_TOP_MMC_START_DLL_LOCK)
+
+/*
+ * For clock speeds greater than 90MHz, we need to check that the
+ * DLL procedure has finished before switching to ultra-speed modes.
+ */
+#define        CLK_TO_CHECK_DLL_LOCK   90000000
+
+static inline void st_mmcss_set_static_delay(void __iomem *ioaddr)
+{
+       if (!ioaddr)
+               return;
+
+       writel_relaxed(0x0, ioaddr + ST_TOP_MMC_DLY_CTRL);
+       writel_relaxed(ST_TOP_MMC_DLY_MAX,
+                       ioaddr + ST_TOP_MMC_TX_CLK_DLY);
+}
+
+/**
+ * st_mmcss_cconfig: configure the Arasan HC inside the flashSS.
+ * @np: dt device node.
+ * @host: sdhci host
+ * Description: this function is to configure the Arasan host controller.
+ * On some ST SoCs, i.e. STiH407 family, the MMC devices inside a dedicated
+ * flashSS sub-system which needs to be configured to be compliant to eMMC 4.5
+ * or eMMC4.3.  This has to be done before registering the sdhci host.
+ */
+static void st_mmcss_cconfig(struct device_node *np, struct sdhci_host *host)
+{
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct mmc_host *mhost = host->mmc;
+       u32 cconf2, cconf3, cconf4, cconf5;
+
+       if (!of_device_is_compatible(np, "st,sdhci-stih407"))
+               return;
+
+       cconf2 = ST_MMC_CCONFIG_2_DEFAULT;
+       cconf3 = ST_MMC_CCONFIG_3_DEFAULT;
+       cconf4 = ST_MMC_CCONFIG_4_DEFAULT;
+       cconf5 = ST_MMC_CCONFIG_5_DEFAULT;
+
+       writel_relaxed(ST_MMC_CCONFIG_1_DEFAULT,
+                       host->ioaddr + ST_MMC_CCONFIG_REG_1);
+
+       /* Set clock frequency, default to 50MHz if max-frequency is not
+        * provided */
+
+       switch (mhost->f_max) {
+       case 200000000:
+               clk_set_rate(pltfm_host->clk, mhost->f_max);
+               cconf2 |= BASE_CLK_FREQ_200;
+               break;
+       case 100000000:
+               clk_set_rate(pltfm_host->clk, mhost->f_max);
+               cconf2 |= BASE_CLK_FREQ_100;
+               break;
+       default:
+               clk_set_rate(pltfm_host->clk, 50000000);
+               cconf2 |= BASE_CLK_FREQ_50;
+       }
+
+       writel_relaxed(cconf2, host->ioaddr + ST_MMC_CCONFIG_REG_2);
+
+       if (mhost->caps & MMC_CAP_NONREMOVABLE)
+               cconf3 |= ST_MMC_CCONFIG_EMMC_SLOT_TYPE;
+       else
+               /* CARD _D ET_CTRL */
+               writel_relaxed(ST_MMC_GP_OUTPUT_CD,
+                               host->ioaddr + ST_MMC_GP_OUTPUT);
+
+       if (mhost->caps & MMC_CAP_UHS_SDR50) {
+               /* use 1.8V */
+               cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;
+               cconf4 |= ST_MMC_CCONFIG_SDR50;
+               /* Use tuning */
+               cconf5 |= ST_MMC_CCONFIG_TUNING_FOR_SDR50;
+               /* Max timeout for retuning */
+               cconf5 |= RETUNING_TIMER_CNT_MAX;
+       }
+
+       if (mhost->caps & MMC_CAP_UHS_SDR104) {
+               /*
+                * SDR104 implies the HC can support HS200 mode, so
+                * it's mandatory to use 1.8V
+                */
+               cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;
+               cconf4 |= ST_MMC_CCONFIG_SDR104;
+               /* Max timeout for retuning */
+               cconf5 |= RETUNING_TIMER_CNT_MAX;
+       }
+
+       if (mhost->caps & MMC_CAP_UHS_DDR50)
+               cconf4 |= ST_MMC_CCONFIG_DDR50;
+
+       writel_relaxed(cconf3, host->ioaddr + ST_MMC_CCONFIG_REG_3);
+       writel_relaxed(cconf4, host->ioaddr + ST_MMC_CCONFIG_REG_4);
+       writel_relaxed(cconf5, host->ioaddr + ST_MMC_CCONFIG_REG_5);
+}
+
+static inline void st_mmcss_set_dll(void __iomem *ioaddr)
+{
+       if (!ioaddr)
+               return;
+
+       writel_relaxed(ST_TOP_MMC_DYN_DLY_CONF, ioaddr + ST_TOP_MMC_DLY_CTRL);
+       writel_relaxed(ST_TOP_MMC_TX_DLL_STEP_DLY_VALID,
+                       ioaddr + ST_TOP_MMC_TX_DLL_STEP_DLY);
+}
+
+static int st_mmcss_lock_dll(void __iomem *ioaddr)
+{
+       unsigned long curr, value;
+       unsigned long finish = jiffies + HZ;
+
+       /* Checks if the DLL procedure is finished */
+       do {
+               curr = jiffies;
+               value = readl(ioaddr + ST_MMC_STATUS_R);
+               if (value & 0x1)
+                       return 0;
+
+               cpu_relax();
+       } while (!time_after_eq(curr, finish));
+
+       return -EBUSY;
+}
+
+static int sdhci_st_set_dll_for_clock(struct sdhci_host *host)
+{
+       int ret = 0;
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct st_mmc_platform_data *pdata = pltfm_host->priv;
+
+       if (host->clock > CLK_TO_CHECK_DLL_LOCK) {
+               st_mmcss_set_dll(pdata->top_ioaddr);
+               ret = st_mmcss_lock_dll(host->ioaddr);
+       }
+
+       return ret;
+}
+
+static void sdhci_st_set_uhs_signaling(struct sdhci_host *host,
+                                       unsigned int uhs)
+{
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct st_mmc_platform_data *pdata = pltfm_host->priv;
+       u16 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+       int ret = 0;
+
+       /* Select Bus Speed Mode for host */
+       ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+       switch (uhs) {
+       /*
+        * Set V18_EN -- UHS modes do not work without this.
+        * does not change signaling voltage
+        */
+
+       case MMC_TIMING_UHS_SDR12:
+               st_mmcss_set_static_delay(pdata->top_ioaddr);
+               ctrl_2 |= SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180;
+               break;
+       case MMC_TIMING_UHS_SDR25:
+               st_mmcss_set_static_delay(pdata->top_ioaddr);
+               ctrl_2 |= SDHCI_CTRL_UHS_SDR25 | SDHCI_CTRL_VDD_180;
+               break;
+       case MMC_TIMING_UHS_SDR50:
+               st_mmcss_set_static_delay(pdata->top_ioaddr);
+               ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
+               ret = sdhci_st_set_dll_for_clock(host);
+               break;
+       case MMC_TIMING_UHS_SDR104:
+       case MMC_TIMING_MMC_HS200:
+               st_mmcss_set_static_delay(pdata->top_ioaddr);
+               ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
+               ret =  sdhci_st_set_dll_for_clock(host);
+               break;
+       case MMC_TIMING_UHS_DDR50:
+       case MMC_TIMING_MMC_DDR52:
+               st_mmcss_set_static_delay(pdata->top_ioaddr);
+               ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
+               break;
+       }
+
+       if (ret)
+               dev_warn(mmc_dev(host->mmc), "Error setting dll for clock "
+                                               "(uhs %d)\n", uhs);
+
+       dev_dbg(mmc_dev(host->mmc), "uhs %d, ctrl_2 %04X\n", uhs, ctrl_2);
+
+       sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+}
+
 static u32 sdhci_st_readl(struct sdhci_host *host, int reg)
 {
        u32 ret;
@@ -48,22 +334,33 @@ static const struct sdhci_ops sdhci_st_ops = {
        .set_bus_width = sdhci_set_bus_width,
        .read_l = sdhci_st_readl,
        .reset = sdhci_reset,
+       .set_uhs_signaling = sdhci_st_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data sdhci_st_pdata = {
        .ops = &sdhci_st_ops,
        .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
-           SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+               SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
+               SDHCI_QUIRK_NO_HISPD_BIT,
+       .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
+               SDHCI_QUIRK2_STOP_WITH_TC,
 };
 
 
 static int sdhci_st_probe(struct platform_device *pdev)
 {
+       struct device_node *np = pdev->dev.of_node;
        struct sdhci_host *host;
+       struct st_mmc_platform_data *pdata;
        struct sdhci_pltfm_host *pltfm_host;
        struct clk *clk;
        int ret = 0;
        u16 host_version;
+       struct resource *res;
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
 
        clk =  devm_clk_get(&pdev->dev, "mmc");
        if (IS_ERR(clk)) {
@@ -71,10 +368,17 @@ static int sdhci_st_probe(struct platform_device *pdev)
                return PTR_ERR(clk);
        }
 
+       pdata->rstc = devm_reset_control_get(&pdev->dev, NULL);
+       if (IS_ERR(pdata->rstc))
+               pdata->rstc = NULL;
+       else
+               reset_control_deassert(pdata->rstc);
+
        host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, 0);
        if (IS_ERR(host)) {
                dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n");
-               return PTR_ERR(host);
+               ret = PTR_ERR(host);
+               goto err_pltfm_init;
        }
 
        ret = mmc_of_parse(host->mmc);
@@ -85,9 +389,22 @@ static int sdhci_st_probe(struct platform_device *pdev)
 
        clk_prepare_enable(clk);
 
+       /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                          "top-mmc-delay");
+       pdata->top_ioaddr = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pdata->top_ioaddr)) {
+               dev_warn(&pdev->dev, "FlashSS Top Dly registers not available");
+               pdata->top_ioaddr = NULL;
+       }
+
        pltfm_host = sdhci_priv(host);
+       pltfm_host->priv = pdata;
        pltfm_host->clk = clk;
 
+       /* Configure the Arasan HC inside the flashSS */
+       st_mmcss_cconfig(np, host);
+
        ret = sdhci_add_host(host);
        if (ret) {
                dev_err(&pdev->dev, "Failed sdhci_add_host\n");
@@ -109,6 +426,9 @@ err_out:
        clk_disable_unprepare(clk);
 err_of:
        sdhci_pltfm_free(pdev);
+err_pltfm_init:
+       if (pdata->rstc)
+               reset_control_assert(pdata->rstc);
 
        return ret;
 }
@@ -117,10 +437,15 @@ static int sdhci_st_remove(struct platform_device *pdev)
 {
        struct sdhci_host *host = platform_get_drvdata(pdev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct st_mmc_platform_data *pdata = pltfm_host->priv;
+       int ret;
 
-       clk_disable_unprepare(pltfm_host->clk);
+       ret = sdhci_pltfm_unregister(pdev);
+
+       if (pdata->rstc)
+               reset_control_assert(pdata->rstc);
 
-       return sdhci_pltfm_unregister(pdev);
+       return ret;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -128,11 +453,15 @@ static int sdhci_st_suspend(struct device *dev)
 {
        struct sdhci_host *host = dev_get_drvdata(dev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct st_mmc_platform_data *pdata = pltfm_host->priv;
        int ret = sdhci_suspend_host(host);
 
        if (ret)
                goto out;
 
+       if (pdata->rstc)
+               reset_control_assert(pdata->rstc);
+
        clk_disable_unprepare(pltfm_host->clk);
 out:
        return ret;
@@ -142,9 +471,16 @@ static int sdhci_st_resume(struct device *dev)
 {
        struct sdhci_host *host = dev_get_drvdata(dev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct st_mmc_platform_data *pdata = pltfm_host->priv;
+       struct device_node *np = dev->of_node;
 
        clk_prepare_enable(pltfm_host->clk);
 
+       if (pdata->rstc)
+               reset_control_deassert(pdata->rstc);
+
+       st_mmcss_cconfig(np, host);
+
        return sdhci_resume_host(host);
 }
 #endif
index f3778d58d1cd42031663b92144deb3fd42723755..ad28b49f0203f5d734ef7325aba081c4c4b5ce4e 100644 (file)
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/gpio.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/slot-gpio.h>
+#include <linux/gpio/consumer.h>
 
 #include "sdhci-pltfm.h"
 
@@ -41,7 +40,6 @@
 #define NVQUIRK_DISABLE_SDR50          BIT(3)
 #define NVQUIRK_DISABLE_SDR104         BIT(4)
 #define NVQUIRK_DISABLE_DDR50          BIT(5)
-#define NVQUIRK_SHADOW_XFER_MODE_REG   BIT(6)
 
 struct sdhci_tegra_soc_data {
        const struct sdhci_pltfm_data *pdata;
@@ -50,7 +48,7 @@ struct sdhci_tegra_soc_data {
 
 struct sdhci_tegra {
        const struct sdhci_tegra_soc_data *soc_data;
-       int power_gpio;
+       struct gpio_desc *power_gpio;
 };
 
 static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
@@ -71,23 +69,19 @@ static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
 static void tegra_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct sdhci_tegra *tegra_host = pltfm_host->priv;
-       const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
 
-       if (soc_data->nvquirks & NVQUIRK_SHADOW_XFER_MODE_REG) {
-               switch (reg) {
-               case SDHCI_TRANSFER_MODE:
-                       /*
-                        * Postpone this write, we must do it together with a
-                        * command write that is down below.
-                        */
-                       pltfm_host->xfer_mode_shadow = val;
-                       return;
-               case SDHCI_COMMAND:
-                       writel((val << 16) | pltfm_host->xfer_mode_shadow,
-                               host->ioaddr + SDHCI_TRANSFER_MODE);
-                       return;
-               }
+       switch (reg) {
+       case SDHCI_TRANSFER_MODE:
+               /*
+                * Postpone this write, we must do it together with a
+                * command write that is down below.
+                */
+               pltfm_host->xfer_mode_shadow = val;
+               return;
+       case SDHCI_COMMAND:
+               writel((val << 16) | pltfm_host->xfer_mode_shadow,
+                       host->ioaddr + SDHCI_TRANSFER_MODE);
+               return;
        }
 
        writew(val, host->ioaddr + reg);
@@ -173,7 +167,6 @@ static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)
 static const struct sdhci_ops tegra_sdhci_ops = {
        .get_ro     = tegra_sdhci_get_ro,
        .read_w     = tegra_sdhci_readw,
-       .write_w    = tegra_sdhci_writew,
        .write_l    = tegra_sdhci_writel,
        .set_clock  = sdhci_set_clock,
        .set_bus_width = tegra_sdhci_set_bus_width,
@@ -214,6 +207,18 @@ static struct sdhci_tegra_soc_data soc_data_tegra30 = {
                    NVQUIRK_DISABLE_SDR104,
 };
 
+static const struct sdhci_ops tegra114_sdhci_ops = {
+       .get_ro     = tegra_sdhci_get_ro,
+       .read_w     = tegra_sdhci_readw,
+       .write_w    = tegra_sdhci_writew,
+       .write_l    = tegra_sdhci_writel,
+       .set_clock  = sdhci_set_clock,
+       .set_bus_width = tegra_sdhci_set_bus_width,
+       .reset      = tegra_sdhci_reset,
+       .set_uhs_signaling = sdhci_set_uhs_signaling,
+       .get_max_clock = sdhci_pltfm_clk_get_max_clock,
+};
+
 static const struct sdhci_pltfm_data sdhci_tegra114_pdata = {
        .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
                  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
@@ -221,15 +226,14 @@ static const struct sdhci_pltfm_data sdhci_tegra114_pdata = {
                  SDHCI_QUIRK_NO_HISPD_BIT |
                  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
                  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
-       .ops  = &tegra_sdhci_ops,
+       .ops  = &tegra114_sdhci_ops,
 };
 
 static struct sdhci_tegra_soc_data soc_data_tegra114 = {
        .pdata = &sdhci_tegra114_pdata,
        .nvquirks = NVQUIRK_DISABLE_SDR50 |
                    NVQUIRK_DISABLE_DDR50 |
-                   NVQUIRK_DISABLE_SDR104 |
-                   NVQUIRK_SHADOW_XFER_MODE_REG,
+                   NVQUIRK_DISABLE_SDR104,
 };
 
 static const struct of_device_id sdhci_tegra_dt_match[] = {
@@ -241,17 +245,6 @@ static const struct of_device_id sdhci_tegra_dt_match[] = {
 };
 MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match);
 
-static int sdhci_tegra_parse_dt(struct device *dev)
-{
-       struct device_node *np = dev->of_node;
-       struct sdhci_host *host = dev_get_drvdata(dev);
-       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct sdhci_tegra *tegra_host = pltfm_host->priv;
-
-       tegra_host->power_gpio = of_get_named_gpio(np, "power-gpios", 0);
-       return mmc_of_parse(host->mmc);
-}
-
 static int sdhci_tegra_probe(struct platform_device *pdev)
 {
        const struct of_device_id *match;
@@ -281,21 +274,18 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
        tegra_host->soc_data = soc_data;
        pltfm_host->priv = tegra_host;
 
-       rc = sdhci_tegra_parse_dt(&pdev->dev);
+       rc = mmc_of_parse(host->mmc);
        if (rc)
                goto err_parse_dt;
 
-       if (gpio_is_valid(tegra_host->power_gpio)) {
-               rc = gpio_request(tegra_host->power_gpio, "sdhci_power");
-               if (rc) {
-                       dev_err(mmc_dev(host->mmc),
-                               "failed to allocate power gpio\n");
-                       goto err_power_req;
-               }
-               gpio_direction_output(tegra_host->power_gpio, 1);
+       tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
+                                                        GPIOD_OUT_HIGH);
+       if (IS_ERR(tegra_host->power_gpio)) {
+               rc = PTR_ERR(tegra_host->power_gpio);
+               goto err_power_req;
        }
 
-       clk = clk_get(mmc_dev(host->mmc), NULL);
+       clk = devm_clk_get(mmc_dev(host->mmc), NULL);
        if (IS_ERR(clk)) {
                dev_err(mmc_dev(host->mmc), "clk err\n");
                rc = PTR_ERR(clk);
@@ -312,10 +302,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
 
 err_add_host:
        clk_disable_unprepare(pltfm_host->clk);
-       clk_put(pltfm_host->clk);
 err_clk_get:
-       if (gpio_is_valid(tegra_host->power_gpio))
-               gpio_free(tegra_host->power_gpio);
 err_power_req:
 err_parse_dt:
 err_alloc_tegra_host:
@@ -323,26 +310,6 @@ err_alloc_tegra_host:
        return rc;
 }
 
-static int sdhci_tegra_remove(struct platform_device *pdev)
-{
-       struct sdhci_host *host = platform_get_drvdata(pdev);
-       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct sdhci_tegra *tegra_host = pltfm_host->priv;
-       int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
-
-       sdhci_remove_host(host, dead);
-
-       if (gpio_is_valid(tegra_host->power_gpio))
-               gpio_free(tegra_host->power_gpio);
-
-       clk_disable_unprepare(pltfm_host->clk);
-       clk_put(pltfm_host->clk);
-
-       sdhci_pltfm_free(pdev);
-
-       return 0;
-}
-
 static struct platform_driver sdhci_tegra_driver = {
        .driver         = {
                .name   = "sdhci-tegra",
@@ -350,7 +317,7 @@ static struct platform_driver sdhci_tegra_driver = {
                .pm     = SDHCI_PLTFM_PMOPS,
        },
        .probe          = sdhci_tegra_probe,
-       .remove         = sdhci_tegra_remove,
+       .remove         = sdhci_pltfm_unregister,
 };
 
 module_platform_driver(sdhci_tegra_driver);
index 0ad412a4876fae403a1a2cdd1a75e7761c809fac..c80287a027356e079e366401c2d5f64d9967461b 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
+#include <linux/mmc/sdio.h>
 #include <linux/mmc/slot-gpio.h>
 
 #include "sdhci.h"
@@ -56,6 +57,7 @@ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
 static int sdhci_pre_dma_transfer(struct sdhci_host *host,
                                        struct mmc_data *data,
                                        struct sdhci_host_next *next);
+static int sdhci_do_get_cd(struct sdhci_host *host);
 
 #ifdef CONFIG_PM
 static int sdhci_runtime_pm_get(struct sdhci_host *host);
@@ -931,7 +933,8 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
                 * If we are sending CMD23, CMD12 never gets sent
                 * on successful completion (so no Auto-CMD12).
                 */
-               if (!host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD12))
+               if (!host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD12) &&
+                   (cmd->opcode != SD_IO_RW_EXTENDED))
                        mode |= SDHCI_TRNS_AUTO_CMD12;
                else if (host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) {
                        mode |= SDHCI_TRNS_AUTO_CMD23;
@@ -1356,7 +1359,8 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
        sdhci_runtime_pm_get(host);
 
-       present = mmc_gpio_get_cd(host->mmc);
+       /* Firstly check card presence */
+       present = sdhci_do_get_cd(host);
 
        spin_lock_irqsave(&host->lock, flags);
 
@@ -1379,22 +1383,6 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
        host->mrq = mrq;
 
-       /*
-        * Firstly check card presence from cd-gpio.  The return could
-        * be one of the following possibilities:
-        *     negative: cd-gpio is not available
-        *     zero: cd-gpio is used, and card is removed
-        *     one: cd-gpio is used, and card is present
-        */
-       if (present < 0) {
-               /* If polling, assume that the card is always present. */
-               if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
-                       present = 1;
-               else
-                       present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
-                                       SDHCI_CARD_PRESENT;
-       }
-
        if (!present || host->flags & SDHCI_DEVICE_DEAD) {
                host->mrq->cmd->error = -ENOMEDIUM;
                tasklet_schedule(&host->finish_tasklet);
@@ -3164,7 +3152,8 @@ int sdhci_add_host(struct sdhci_host *host)
        /* Auto-CMD23 stuff only works in ADMA or PIO. */
        if ((host->version >= SDHCI_SPEC_300) &&
            ((host->flags & SDHCI_USE_ADMA) ||
-            !(host->flags & SDHCI_USE_SDMA))) {
+            !(host->flags & SDHCI_USE_SDMA)) &&
+            !(host->quirks2 & SDHCI_QUIRK2_ACMD23_BROKEN)) {
                host->flags |= SDHCI_AUTO_CMD23;
                DBG("%s: Auto-CMD23 available\n", mmc_hostname(mmc));
        } else {
index 0315e1844330c4d0a70616c7525899eca57204a4..e639b7f435e564f6f8a56dc22a6747d23939c8f2 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/types.h>
 #include <linux/io.h>
 
-#include <linux/mmc/sdhci.h>
+#include <linux/mmc/host.h>
 
 /*
  * Controller registers
@@ -309,6 +309,207 @@ struct sdhci_adma2_64_desc {
  */
 #define SDHCI_MAX_SEGS         128
 
+struct sdhci_host_next {
+       unsigned int    sg_count;
+       s32             cookie;
+};
+
+struct sdhci_host {
+       /* Data set by hardware interface driver */
+       const char *hw_name;    /* Hardware bus name */
+
+       unsigned int quirks;    /* Deviations from spec. */
+
+/* Controller doesn't honor resets unless we touch the clock register */
+#define SDHCI_QUIRK_CLOCK_BEFORE_RESET                 (1<<0)
+/* Controller has bad caps bits, but really supports DMA */
+#define SDHCI_QUIRK_FORCE_DMA                          (1<<1)
+/* Controller doesn't like to be reset when there is no card inserted. */
+#define SDHCI_QUIRK_NO_CARD_NO_RESET                   (1<<2)
+/* Controller doesn't like clearing the power reg before a change */
+#define SDHCI_QUIRK_SINGLE_POWER_WRITE                 (1<<3)
+/* Controller has flaky internal state so reset it on each ios change */
+#define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS              (1<<4)
+/* Controller has an unusable DMA engine */
+#define SDHCI_QUIRK_BROKEN_DMA                         (1<<5)
+/* Controller has an unusable ADMA engine */
+#define SDHCI_QUIRK_BROKEN_ADMA                                (1<<6)
+/* Controller can only DMA from 32-bit aligned addresses */
+#define SDHCI_QUIRK_32BIT_DMA_ADDR                     (1<<7)
+/* Controller can only DMA chunk sizes that are a multiple of 32 bits */
+#define SDHCI_QUIRK_32BIT_DMA_SIZE                     (1<<8)
+/* Controller can only ADMA chunks that are a multiple of 32 bits */
+#define SDHCI_QUIRK_32BIT_ADMA_SIZE                    (1<<9)
+/* Controller needs to be reset after each request to stay stable */
+#define SDHCI_QUIRK_RESET_AFTER_REQUEST                        (1<<10)
+/* Controller needs voltage and power writes to happen separately */
+#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER            (1<<11)
+/* Controller provides an incorrect timeout value for transfers */
+#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL                 (1<<12)
+/* Controller has an issue with buffer bits for small transfers */
+#define SDHCI_QUIRK_BROKEN_SMALL_PIO                   (1<<13)
+/* Controller does not provide transfer-complete interrupt when not busy */
+#define SDHCI_QUIRK_NO_BUSY_IRQ                                (1<<14)
+/* Controller has unreliable card detection */
+#define SDHCI_QUIRK_BROKEN_CARD_DETECTION              (1<<15)
+/* Controller reports inverted write-protect state */
+#define SDHCI_QUIRK_INVERTED_WRITE_PROTECT             (1<<16)
+/* Controller does not like fast PIO transfers */
+#define SDHCI_QUIRK_PIO_NEEDS_DELAY                    (1<<18)
+/* Controller has to be forced to use block size of 2048 bytes */
+#define SDHCI_QUIRK_FORCE_BLK_SZ_2048                  (1<<20)
+/* Controller cannot do multi-block transfers */
+#define SDHCI_QUIRK_NO_MULTIBLOCK                      (1<<21)
+/* Controller can only handle 1-bit data transfers */
+#define SDHCI_QUIRK_FORCE_1_BIT_DATA                   (1<<22)
+/* Controller needs 10ms delay between applying power and clock */
+#define SDHCI_QUIRK_DELAY_AFTER_POWER                  (1<<23)
+/* Controller uses SDCLK instead of TMCLK for data timeouts */
+#define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK            (1<<24)
+/* Controller reports wrong base clock capability */
+#define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN              (1<<25)
+/* Controller cannot support End Attribute in NOP ADMA descriptor */
+#define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC              (1<<26)
+/* Controller is missing device caps. Use caps provided by host */
+#define SDHCI_QUIRK_MISSING_CAPS                       (1<<27)
+/* Controller uses Auto CMD12 command to stop the transfer */
+#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12             (1<<28)
+/* Controller doesn't have HISPD bit field in HI-SPEED SD card */
+#define SDHCI_QUIRK_NO_HISPD_BIT                       (1<<29)
+/* Controller treats ADMA descriptors with length 0000h incorrectly */
+#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC           (1<<30)
+/* The read-only detection via SDHCI_PRESENT_STATE register is unstable */
+#define SDHCI_QUIRK_UNSTABLE_RO_DETECT                 (1<<31)
+
+       unsigned int quirks2;   /* More deviations from spec. */
+
+#define SDHCI_QUIRK2_HOST_OFF_CARD_ON                  (1<<0)
+#define SDHCI_QUIRK2_HOST_NO_CMD23                     (1<<1)
+/* The system physically doesn't support 1.8v, even if the host does */
+#define SDHCI_QUIRK2_NO_1_8_V                          (1<<2)
+#define SDHCI_QUIRK2_PRESET_VALUE_BROKEN               (1<<3)
+#define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON              (1<<4)
+/* Controller has a non-standard host control register */
+#define SDHCI_QUIRK2_BROKEN_HOST_CONTROL               (1<<5)
+/* Controller does not support HS200 */
+#define SDHCI_QUIRK2_BROKEN_HS200                      (1<<6)
+/* Controller does not support DDR50 */
+#define SDHCI_QUIRK2_BROKEN_DDR50                      (1<<7)
+/* Stop command (CMD12) can set Transfer Complete when not using MMC_RSP_BUSY */
+#define SDHCI_QUIRK2_STOP_WITH_TC                      (1<<8)
+/* Controller does not support 64-bit DMA */
+#define SDHCI_QUIRK2_BROKEN_64_BIT_DMA                 (1<<9)
+/* need clear transfer mode register before send cmd */
+#define SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD (1<<10)
+/* Capability register bit-63 indicates HS400 support */
+#define SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400              (1<<11)
+/* forced tuned clock */
+#define SDHCI_QUIRK2_TUNING_WORK_AROUND                        (1<<12)
+/* disable the block count for single block transactions */
+#define SDHCI_QUIRK2_SUPPORT_SINGLE                    (1<<13)
+/* Controller broken with using ACMD23 */
+#define SDHCI_QUIRK2_ACMD23_BROKEN                     (1<<14)
+
+       int irq;                /* Device IRQ */
+       void __iomem *ioaddr;   /* Mapped address */
+
+       const struct sdhci_ops *ops;    /* Low level hw interface */
+
+       /* Internal data */
+       struct mmc_host *mmc;   /* MMC structure */
+       u64 dma_mask;           /* custom DMA mask */
+
+#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
+       struct led_classdev led;        /* LED control */
+       char led_name[32];
+#endif
+
+       spinlock_t lock;        /* Mutex */
+
+       int flags;              /* Host attributes */
+#define SDHCI_USE_SDMA         (1<<0)  /* Host is SDMA capable */
+#define SDHCI_USE_ADMA         (1<<1)  /* Host is ADMA capable */
+#define SDHCI_REQ_USE_DMA      (1<<2)  /* Use DMA for this req. */
+#define SDHCI_DEVICE_DEAD      (1<<3)  /* Device unresponsive */
+#define SDHCI_SDR50_NEEDS_TUNING (1<<4)        /* SDR50 needs tuning */
+#define SDHCI_NEEDS_RETUNING   (1<<5)  /* Host needs retuning */
+#define SDHCI_AUTO_CMD12       (1<<6)  /* Auto CMD12 support */
+#define SDHCI_AUTO_CMD23       (1<<7)  /* Auto CMD23 support */
+#define SDHCI_PV_ENABLED       (1<<8)  /* Preset value enabled */
+#define SDHCI_SDIO_IRQ_ENABLED (1<<9)  /* SDIO irq enabled */
+#define SDHCI_SDR104_NEEDS_TUNING (1<<10)      /* SDR104/HS200 needs tuning */
+#define SDHCI_USING_RETUNING_TIMER (1<<11)     /* Host is using a retuning timer for the card */
+#define SDHCI_USE_64_BIT_DMA   (1<<12) /* Use 64-bit DMA */
+#define SDHCI_HS400_TUNING     (1<<13) /* Tuning for HS400 */
+
+       unsigned int version;   /* SDHCI spec. version */
+
+       unsigned int max_clk;   /* Max possible freq (MHz) */
+       unsigned int timeout_clk;       /* Timeout freq (KHz) */
+       unsigned int clk_mul;   /* Clock Muliplier value */
+
+       unsigned int clock;     /* Current clock (MHz) */
+       u8 pwr;                 /* Current voltage */
+
+       bool runtime_suspended; /* Host is runtime suspended */
+       bool bus_on;            /* Bus power prevents runtime suspend */
+       bool preset_enabled;    /* Preset is enabled */
+
+       struct mmc_request *mrq;        /* Current request */
+       struct mmc_command *cmd;        /* Current command */
+       struct mmc_data *data;  /* Current data request */
+       unsigned int data_early:1;      /* Data finished before cmd */
+       unsigned int busy_handle:1;     /* Handling the order of Busy-end */
+
+       struct sg_mapping_iter sg_miter;        /* SG state for PIO */
+       unsigned int blocks;    /* remaining PIO blocks */
+
+       int sg_count;           /* Mapped sg entries */
+
+       void *adma_table;       /* ADMA descriptor table */
+       void *align_buffer;     /* Bounce buffer */
+
+       size_t adma_table_sz;   /* ADMA descriptor table size */
+       size_t align_buffer_sz; /* Bounce buffer size */
+
+       dma_addr_t adma_addr;   /* Mapped ADMA descr. table */
+       dma_addr_t align_addr;  /* Mapped bounce buffer */
+
+       unsigned int desc_sz;   /* ADMA descriptor size */
+       unsigned int align_sz;  /* ADMA alignment */
+       unsigned int align_mask;        /* ADMA alignment mask */
+
+       struct tasklet_struct finish_tasklet;   /* Tasklet structures */
+
+       struct timer_list timer;        /* Timer for timeouts */
+
+       u32 caps;               /* Alternative CAPABILITY_0 */
+       u32 caps1;              /* Alternative CAPABILITY_1 */
+
+       unsigned int            ocr_avail_sdio; /* OCR bit masks */
+       unsigned int            ocr_avail_sd;
+       unsigned int            ocr_avail_mmc;
+       u32 ocr_mask;           /* available voltages */
+
+       unsigned                timing;         /* Current timing */
+
+       u32                     thread_isr;
+
+       /* cached registers */
+       u32                     ier;
+
+       wait_queue_head_t       buf_ready_int;  /* Waitqueue for Buffer Read Ready interrupt */
+       unsigned int            tuning_done;    /* Condition flag set when CMD19 succeeds */
+
+       unsigned int            tuning_count;   /* Timer count for re-tuning */
+       unsigned int            tuning_mode;    /* Re-tuning mode supported by host */
+#define SDHCI_TUNING_MODE_1    0
+       struct timer_list       tuning_timer;   /* Timer for tuning */
+
+       struct sdhci_host_next  next_data;
+       unsigned long private[0] ____cacheline_aligned;
+};
+
 struct sdhci_ops {
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
        u32             (*read_l)(struct sdhci_host *host, int reg);
index 7d9d6a3215210f537b1b6e46070b610320f80ff5..072f67066df38e8d60d4eb0d1f5bc656947fa1fa 100644 (file)
@@ -875,6 +875,7 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
        struct mmc_command *cmd = mrq->cmd;
        u32 opc = cmd->opcode;
        u32 mask;
+       unsigned long flags;
 
        switch (opc) {
        /* response busy check */
@@ -909,10 +910,12 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
        /* set arg */
        sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg);
        /* set cmd */
+       spin_lock_irqsave(&host->lock, flags);
        sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc);
 
        host->wait_for = MMCIF_WAIT_FOR_CMD;
        schedule_delayed_work(&host->timeout_work, host->timeout);
+       spin_unlock_irqrestore(&host->lock, flags);
 }
 
 static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host,
@@ -1171,6 +1174,12 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
        struct sh_mmcif_host *host = dev_id;
        struct mmc_request *mrq;
        bool wait = false;
+       unsigned long flags;
+       int wait_work;
+
+       spin_lock_irqsave(&host->lock, flags);
+       wait_work = host->wait_for;
+       spin_unlock_irqrestore(&host->lock, flags);
 
        cancel_delayed_work_sync(&host->timeout_work);
 
@@ -1188,7 +1197,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
         * All handlers return true, if processing continues, and false, if the
         * request has to be completed - successfully or not
         */
-       switch (host->wait_for) {
+       switch (wait_work) {
        case MMCIF_WAIT_FOR_REQUEST:
                /* We're too late, the timeout has already kicked in */
                mutex_unlock(&host->thread_lock);
@@ -1312,15 +1321,15 @@ static void mmcif_timeout_work(struct work_struct *work)
                /* Don't run after mmc_remove_host() */
                return;
 
-       dev_err(&host->pd->dev, "Timeout waiting for %u on CMD%u\n",
-               host->wait_for, mrq->cmd->opcode);
-
        spin_lock_irqsave(&host->lock, flags);
        if (host->state == STATE_IDLE) {
                spin_unlock_irqrestore(&host->lock, flags);
                return;
        }
 
+       dev_err(&host->pd->dev, "Timeout waiting for %u on CMD%u\n",
+               host->wait_for, mrq->cmd->opcode);
+
        host->state = STATE_TIMEOUT;
        spin_unlock_irqrestore(&host->lock, flags);
 
index e8a4218b57267f508eb871f216de112e93707d31..4d3e1ffe5508273fc1f9f91b7b5c3218bed1ea07 100644 (file)
@@ -293,7 +293,7 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
                                    struct mmc_data *data)
 {
        struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu;
-       struct sunxi_idma_des *pdes_pa = (struct sunxi_idma_des *)host->sg_dma;
+       dma_addr_t next_desc = host->sg_dma;
        int i, max_len = (1 << host->idma_des_size_bits);
 
        for (i = 0; i < data->sg_len; i++) {
@@ -305,8 +305,9 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
                else
                        pdes[i].buf_size = data->sg[i].length;
 
+               next_desc += sizeof(struct sunxi_idma_des);
                pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]);
-               pdes[i].buf_addr_ptr2 = (u32)&pdes_pa[i + 1];
+               pdes[i].buf_addr_ptr2 = (u32)next_desc;
        }
 
        pdes[0].config |= SDXC_IDMAC_DES0_FD;
@@ -930,7 +931,9 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
                return PTR_ERR(host->clk_sample);
        }
 
-       host->reset = devm_reset_control_get(&pdev->dev, "ahb");
+       host->reset = devm_reset_control_get_optional(&pdev->dev, "ahb");
+       if (PTR_ERR(host->reset) == -EPROBE_DEFER)
+               return PTR_ERR(host->reset);
 
        ret = clk_prepare_enable(host->clk_ahb);
        if (ret) {
@@ -1028,7 +1031,7 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
        mmc->f_min              =   400000;
        mmc->f_max              = 50000000;
        mmc->caps              |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-                                 MMC_CAP_ERASE;
+                                 MMC_CAP_ERASE | MMC_CAP_SDIO_IRQ;
 
        ret = mmc_of_parse(mmc);
        if (ret)
index a31c3573d386f8c6f0a9f4e2143a623081d1d636..dba7e1c19dd758e784f31c89afe7dafc66334a06 100644 (file)
@@ -1073,8 +1073,6 @@ EXPORT_SYMBOL(tmio_mmc_host_alloc);
 void tmio_mmc_host_free(struct tmio_mmc_host *host)
 {
        mmc_free_host(host->mmc);
-
-       host->mmc = NULL;
 }
 EXPORT_SYMBOL(tmio_mmc_host_free);
 
index dd2e1aa95ba3fa4c999bfb25dc9fd3a7d3f08982..5af00559e9d6f7f933bccd41db4e3dc334a41673 100644 (file)
@@ -744,7 +744,7 @@ static struct wmt_mci_caps wm8505_caps = {
        .max_blk_size = 2048,
 };
 
-static struct of_device_id wmt_mci_dt_ids[] = {
+static const struct of_device_id wmt_mci_dt_ids[] = {
        { .compatible = "wm,wm8505-sdhc", .data = &wm8505_caps },
        { /* Sentinel */ },
 };
index 27f272ed502ac5b10e46f0fce4321b49d0cf95b0..43fa16b5f5107c8946ce6f1381e727bd0baa1c37 100644 (file)
@@ -1105,7 +1105,7 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
                mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip);
                reg = readl(r->gpmi_regs + HW_GPMI_STAT);
        } else
-               dev_err(this->dev, "unknow arch.\n");
+               dev_err(this->dev, "unknown arch.\n");
        return reg & mask;
 }
 
index 289ad3ac3e80d7fba32092856a717bea7d5c03c3..8dcc7b8fee40631680153d6fb7ca893546b1233f 100644 (file)
@@ -758,8 +758,7 @@ static int hisi_nfc_probe(struct platform_device *pdev)
 
        hisi_nfc_host_init(host);
 
-       ret = devm_request_irq(dev, irq, hinfc_irq_handle, IRQF_DISABLED,
-                               "nandc", host);
+       ret = devm_request_irq(dev, irq, hinfc_irq_handle, 0x0, "nandc", host);
        if (ret) {
                dev_err(dev, "failed to request IRQ\n");
                goto err_res;
index cfe3c7695455e16eab516e0f99db6ee6b7e58879..4c9678c8e13931408ad412111e27ab3e0fc204b8 100644 (file)
@@ -592,7 +592,7 @@ int bnx2x_vf_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf,
                mc = kzalloc(mc_num * sizeof(struct bnx2x_mcast_list_elem),
                             GFP_KERNEL);
                if (!mc) {
-                       BNX2X_ERR("Cannot Configure mulicasts due to lack of memory\n");
+                       BNX2X_ERR("Cannot Configure multicasts due to lack of memory\n");
                        return -ENOMEM;
                }
        }
index 3e0f705a43117d51926dde8d3b63ed3af3f3e6fd..75ee9e4ced51f50ba5017153cd072c2666ffa36f 100644 (file)
@@ -818,7 +818,7 @@ int qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter,
 
        if (rv)
                netdev_err(adapter->netdev,
-                          "Failed to set Rx coalescing parametrs\n");
+                          "Failed to set Rx coalescing parameters\n");
 
        return rv;
 }
index e22e602beef3426a600db641a66237f40c039732..4c2b5a80f17ce709346d9beae407835eee10f1bf 100644 (file)
@@ -614,7 +614,7 @@ static void recalibrate(struct dp83640_clock *clock)
        trigger = CAL_TRIGGER;
        cal_gpio = 1 + ptp_find_pin(clock->ptp_clock, PTP_PF_PHYSYNC, 0);
        if (cal_gpio < 1) {
-               pr_err("PHY calibration pin not avaible - PHY is not calibrated.");
+               pr_err("PHY calibration pin not available - PHY is not calibrated.");
                return;
        }
 
index e71a2ce7a4487a5386331e26023e5538512f14bd..b97367d507174778fe24bfc44397167295e73517 100644 (file)
@@ -3211,7 +3211,7 @@ static void airo_print_status(const char *devname, u16 status)
                        airo_print_dbg(devname, "link lost (TSF sync lost)");
                        break;
                default:
-                       airo_print_dbg(devname, "unknow status %x\n", status);
+                       airo_print_dbg(devname, "unknown status %x\n", status);
                        break;
                }
                break;
@@ -3233,7 +3233,7 @@ static void airo_print_status(const char *devname, u16 status)
        case STAT_REASSOC:
                break;
        default:
-               airo_print_dbg(devname, "unknow status %x\n", status);
+               airo_print_dbg(devname, "unknown status %x\n", status);
                break;
        }
 }
index d6d2f0f00caad18ec00ba69f5635c79f161b2ba7..4ce433f1c1fb5bd2b396871fd067179aba4eeb96 100644 (file)
@@ -4857,7 +4857,7 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
                        bw = WMI_PEER_CHWIDTH_80MHZ;
                        break;
                case IEEE80211_STA_RX_BW_160:
-                       ath10k_warn(ar, "Invalid bandwith %d in rc update for %pM\n",
+                       ath10k_warn(ar, "Invalid bandwidth %d in rc update for %pM\n",
                                    sta->bandwidth, sta->addr);
                        bw = WMI_PEER_CHWIDTH_20MHZ;
                        break;
index 69ed39731902c0c9262cda7153f5008467cd5f9e..dbd894428be60e104f6f1457e5aeff7f933e31bf 100644 (file)
@@ -1701,7 +1701,7 @@ int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
        } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) {
                /* TODO: it also support ARP response type */
        } else {
-               wcn36xx_warn("unknow keep alive packet type %d\n", packet_type);
+               wcn36xx_warn("unknown keep alive packet type %d\n", packet_type);
                ret = -EINVAL;
                goto out;
        }
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_brcmsmac.h b/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_brcmsmac.h
new file mode 100644 (file)
index 0000000..a0da324
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if !defined(__TRACE_BRCMSMAC_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __TRACE_BRCMSMAC_H
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac
+
+/*
+ * We define a tracepoint, its arguments, its printk format and its
+ * 'fast binary record' layout.
+ */
+TRACE_EVENT(brcms_timer,
+       /* TPPROTO is the prototype of the function called by this tracepoint */
+       TP_PROTO(struct brcms_timer *t),
+       /*
+        * TPARGS(firstarg, p) are the parameters names, same as found in the
+        * prototype.
+        */
+       TP_ARGS(t),
+       /*
+        * Fast binary tracing: define the trace record via TP_STRUCT__entry().
+        * You can think about it like a regular C structure local variable
+        * definition.
+        */
+       TP_STRUCT__entry(
+               __field(uint, ms)
+               __field(uint, set)
+               __field(uint, periodic)
+       ),
+       TP_fast_assign(
+               __entry->ms = t->ms;
+               __entry->set = t->set;
+               __entry->periodic = t->periodic;
+       ),
+       TP_printk(
+               "ms=%u set=%u periodic=%u",
+               __entry->ms, __entry->set, __entry->periodic
+       )
+);
+
+TRACE_EVENT(brcms_dpc,
+       TP_PROTO(unsigned long data),
+       TP_ARGS(data),
+       TP_STRUCT__entry(
+               __field(unsigned long, data)
+       ),
+       TP_fast_assign(
+               __entry->data = data;
+       ),
+       TP_printk(
+               "data=%p",
+               (void *)__entry->data
+       )
+);
+
+TRACE_EVENT(brcms_macintstatus,
+       TP_PROTO(const struct device *dev, int in_isr, u32 macintstatus,
+                u32 mask),
+       TP_ARGS(dev, in_isr, macintstatus, mask),
+       TP_STRUCT__entry(
+               __string(dev, dev_name(dev))
+               __field(int, in_isr)
+               __field(u32, macintstatus)
+               __field(u32, mask)
+       ),
+       TP_fast_assign(
+               __assign_str(dev, dev_name(dev));
+               __entry->in_isr = in_isr;
+               __entry->macintstatus = macintstatus;
+               __entry->mask = mask;
+       ),
+       TP_printk("[%s] in_isr=%d macintstatus=%#x mask=%#x", __get_str(dev),
+                 __entry->in_isr, __entry->macintstatus, __entry->mask)
+);
+#endif /* __TRACE_BRCMSMAC_H */
+
+#ifdef CONFIG_BRCM_TRACING
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE brcms_trace_brcmsmac
+#include <trace/define_trace.h>
+
+#endif /* CONFIG_BRCM_TRACING */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h b/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h
new file mode 100644 (file)
index 0000000..0e8a69a
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if !defined(__TRACE_BRCMSMAC_MSG_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __TRACE_BRCMSMAC_MSG_H
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac_msg
+
+#define MAX_MSG_LEN    100
+
+DECLARE_EVENT_CLASS(brcms_msg_event,
+       TP_PROTO(struct va_format *vaf),
+       TP_ARGS(vaf),
+       TP_STRUCT__entry(
+               __dynamic_array(char, msg, MAX_MSG_LEN)
+       ),
+       TP_fast_assign(
+               WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+                                      MAX_MSG_LEN, vaf->fmt,
+                                      *vaf->va) >= MAX_MSG_LEN);
+       ),
+       TP_printk("%s", __get_str(msg))
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_info,
+       TP_PROTO(struct va_format *vaf),
+       TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_warn,
+       TP_PROTO(struct va_format *vaf),
+       TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_err,
+       TP_PROTO(struct va_format *vaf),
+       TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_crit,
+       TP_PROTO(struct va_format *vaf),
+       TP_ARGS(vaf)
+);
+
+TRACE_EVENT(brcms_dbg,
+       TP_PROTO(u32 level, const char *func, struct va_format *vaf),
+       TP_ARGS(level, func, vaf),
+       TP_STRUCT__entry(
+               __field(u32, level)
+               __string(func, func)
+               __dynamic_array(char, msg, MAX_MSG_LEN)
+       ),
+       TP_fast_assign(
+               __entry->level = level;
+               __assign_str(func, func);
+               WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+                                      MAX_MSG_LEN, vaf->fmt,
+                                      *vaf->va) >= MAX_MSG_LEN);
+       ),
+       TP_printk("%s: %s", __get_str(func), __get_str(msg))
+);
+#endif /* __TRACE_BRCMSMAC_MSG_H */
+
+#ifdef CONFIG_BRCM_TRACING
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE brcms_trace_brcmsmac_msg
+#include <trace/define_trace.h>
+
+#endif /* CONFIG_BRCM_TRACING */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_brcmsmac_tx.h b/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_brcmsmac_tx.h
new file mode 100644 (file)
index 0000000..cf2cc07
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if !defined(__TRACE_BRCMSMAC_TX_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __TRACE_BRCMSMAC_TX_H
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac_tx
+
+TRACE_EVENT(brcms_txdesc,
+       TP_PROTO(const struct device *dev,
+                void *txh, size_t txh_len),
+       TP_ARGS(dev, txh, txh_len),
+       TP_STRUCT__entry(
+               __string(dev, dev_name(dev))
+               __dynamic_array(u8, txh, txh_len)
+       ),
+       TP_fast_assign(
+               __assign_str(dev, dev_name(dev));
+               memcpy(__get_dynamic_array(txh), txh, txh_len);
+       ),
+       TP_printk("[%s] txdesc", __get_str(dev))
+);
+
+TRACE_EVENT(brcms_txstatus,
+       TP_PROTO(const struct device *dev, u16 framelen, u16 frameid,
+                u16 status, u16 lasttxtime, u16 sequence, u16 phyerr,
+                u16 ackphyrxsh),
+       TP_ARGS(dev, framelen, frameid, status, lasttxtime, sequence, phyerr,
+               ackphyrxsh),
+       TP_STRUCT__entry(
+               __string(dev, dev_name(dev))
+               __field(u16, framelen)
+               __field(u16, frameid)
+               __field(u16, status)
+               __field(u16, lasttxtime)
+               __field(u16, sequence)
+               __field(u16, phyerr)
+               __field(u16, ackphyrxsh)
+       ),
+       TP_fast_assign(
+               __assign_str(dev, dev_name(dev));
+               __entry->framelen = framelen;
+               __entry->frameid = frameid;
+               __entry->status = status;
+               __entry->lasttxtime = lasttxtime;
+               __entry->sequence = sequence;
+               __entry->phyerr = phyerr;
+               __entry->ackphyrxsh = ackphyrxsh;
+       ),
+       TP_printk("[%s] FrameId %#04x TxStatus %#04x LastTxTime %#04x "
+                 "Seq %#04x PHYTxStatus %#04x RxAck %#04x",
+                 __get_str(dev), __entry->frameid, __entry->status,
+                 __entry->lasttxtime, __entry->sequence, __entry->phyerr,
+                 __entry->ackphyrxsh)
+);
+
+TRACE_EVENT(brcms_ampdu_session,
+       TP_PROTO(const struct device *dev, unsigned max_ampdu_len,
+                u16 max_ampdu_frames, u16 ampdu_len, u16 ampdu_frames,
+                u16 dma_len),
+       TP_ARGS(dev, max_ampdu_len, max_ampdu_frames, ampdu_len, ampdu_frames,
+               dma_len),
+       TP_STRUCT__entry(
+               __string(dev, dev_name(dev))
+               __field(unsigned, max_ampdu_len)
+               __field(u16, max_ampdu_frames)
+               __field(u16, ampdu_len)
+               __field(u16, ampdu_frames)
+               __field(u16, dma_len)
+       ),
+       TP_fast_assign(
+               __assign_str(dev, dev_name(dev));
+               __entry->max_ampdu_len = max_ampdu_len;
+               __entry->max_ampdu_frames = max_ampdu_frames;
+               __entry->ampdu_len = ampdu_len;
+               __entry->ampdu_frames = ampdu_frames;
+               __entry->dma_len = dma_len;
+       ),
+       TP_printk("[%s] ampdu session max_len=%u max_frames=%u len=%u frames=%u dma_len=%u",
+                 __get_str(dev), __entry->max_ampdu_len,
+                 __entry->max_ampdu_frames, __entry->ampdu_len,
+                 __entry->ampdu_frames, __entry->dma_len)
+);
+#endif /* __TRACE_BRCMSMAC_TX_H */
+
+#ifdef CONFIG_BRCM_TRACING
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE brcms_trace_brcmsmac_tx
+#include <trace/define_trace.h>
+
+#endif /* CONFIG_BRCM_TRACING */
index 871781e6a7138a0a9556c029dd8d265ecd53b733..cbf2f06436fcfe471bf417330f6de09f3d569abd 100644 (file)
@@ -14,9 +14,8 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#if !defined(__TRACE_BRCMSMAC_H) || defined(TRACE_HEADER_MULTI_READ)
-
-#define __TRACE_BRCMSMAC_H
+#ifndef __BRCMS_TRACE_EVENTS_H
+#define __BRCMS_TRACE_EVENTS_H
 
 #include <linux/types.h>
 #include <linux/device.h>
@@ -34,222 +33,8 @@ static inline void trace_ ## name(proto) {}
 static inline void trace_ ## name(proto) {}
 #endif
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM brcmsmac
-
-/*
- * We define a tracepoint, its arguments, its printk format and its
- * 'fast binary record' layout.
- */
-TRACE_EVENT(brcms_timer,
-       /* TPPROTO is the prototype of the function called by this tracepoint */
-       TP_PROTO(struct brcms_timer *t),
-       /*
-        * TPARGS(firstarg, p) are the parameters names, same as found in the
-        * prototype.
-        */
-       TP_ARGS(t),
-       /*
-        * Fast binary tracing: define the trace record via TP_STRUCT__entry().
-        * You can think about it like a regular C structure local variable
-        * definition.
-        */
-       TP_STRUCT__entry(
-               __field(uint, ms)
-               __field(uint, set)
-               __field(uint, periodic)
-       ),
-       TP_fast_assign(
-               __entry->ms = t->ms;
-               __entry->set = t->set;
-               __entry->periodic = t->periodic;
-       ),
-       TP_printk(
-               "ms=%u set=%u periodic=%u",
-               __entry->ms, __entry->set, __entry->periodic
-       )
-);
-
-TRACE_EVENT(brcms_dpc,
-       TP_PROTO(unsigned long data),
-       TP_ARGS(data),
-       TP_STRUCT__entry(
-               __field(unsigned long, data)
-       ),
-       TP_fast_assign(
-               __entry->data = data;
-       ),
-       TP_printk(
-               "data=%p",
-               (void *)__entry->data
-       )
-);
-
-TRACE_EVENT(brcms_macintstatus,
-       TP_PROTO(const struct device *dev, int in_isr, u32 macintstatus,
-                u32 mask),
-       TP_ARGS(dev, in_isr, macintstatus, mask),
-       TP_STRUCT__entry(
-               __string(dev, dev_name(dev))
-               __field(int, in_isr)
-               __field(u32, macintstatus)
-               __field(u32, mask)
-       ),
-       TP_fast_assign(
-               __assign_str(dev, dev_name(dev));
-               __entry->in_isr = in_isr;
-               __entry->macintstatus = macintstatus;
-               __entry->mask = mask;
-       ),
-       TP_printk("[%s] in_isr=%d macintstatus=%#x mask=%#x", __get_str(dev),
-                 __entry->in_isr, __entry->macintstatus, __entry->mask)
-);
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM brcmsmac_tx
-
-TRACE_EVENT(brcms_txdesc,
-       TP_PROTO(const struct device *dev,
-                void *txh, size_t txh_len),
-       TP_ARGS(dev, txh, txh_len),
-       TP_STRUCT__entry(
-               __string(dev, dev_name(dev))
-               __dynamic_array(u8, txh, txh_len)
-       ),
-       TP_fast_assign(
-               __assign_str(dev, dev_name(dev));
-               memcpy(__get_dynamic_array(txh), txh, txh_len);
-       ),
-       TP_printk("[%s] txdesc", __get_str(dev))
-);
-
-TRACE_EVENT(brcms_txstatus,
-       TP_PROTO(const struct device *dev, u16 framelen, u16 frameid,
-                u16 status, u16 lasttxtime, u16 sequence, u16 phyerr,
-                u16 ackphyrxsh),
-       TP_ARGS(dev, framelen, frameid, status, lasttxtime, sequence, phyerr,
-               ackphyrxsh),
-       TP_STRUCT__entry(
-               __string(dev, dev_name(dev))
-               __field(u16, framelen)
-               __field(u16, frameid)
-               __field(u16, status)
-               __field(u16, lasttxtime)
-               __field(u16, sequence)
-               __field(u16, phyerr)
-               __field(u16, ackphyrxsh)
-       ),
-       TP_fast_assign(
-               __assign_str(dev, dev_name(dev));
-               __entry->framelen = framelen;
-               __entry->frameid = frameid;
-               __entry->status = status;
-               __entry->lasttxtime = lasttxtime;
-               __entry->sequence = sequence;
-               __entry->phyerr = phyerr;
-               __entry->ackphyrxsh = ackphyrxsh;
-       ),
-       TP_printk("[%s] FrameId %#04x TxStatus %#04x LastTxTime %#04x "
-                 "Seq %#04x PHYTxStatus %#04x RxAck %#04x",
-                 __get_str(dev), __entry->frameid, __entry->status,
-                 __entry->lasttxtime, __entry->sequence, __entry->phyerr,
-                 __entry->ackphyrxsh)
-);
-
-TRACE_EVENT(brcms_ampdu_session,
-       TP_PROTO(const struct device *dev, unsigned max_ampdu_len,
-                u16 max_ampdu_frames, u16 ampdu_len, u16 ampdu_frames,
-                u16 dma_len),
-       TP_ARGS(dev, max_ampdu_len, max_ampdu_frames, ampdu_len, ampdu_frames,
-               dma_len),
-       TP_STRUCT__entry(
-               __string(dev, dev_name(dev))
-               __field(unsigned, max_ampdu_len)
-               __field(u16, max_ampdu_frames)
-               __field(u16, ampdu_len)
-               __field(u16, ampdu_frames)
-               __field(u16, dma_len)
-       ),
-       TP_fast_assign(
-               __assign_str(dev, dev_name(dev));
-               __entry->max_ampdu_len = max_ampdu_len;
-               __entry->max_ampdu_frames = max_ampdu_frames;
-               __entry->ampdu_len = ampdu_len;
-               __entry->ampdu_frames = ampdu_frames;
-               __entry->dma_len = dma_len;
-       ),
-       TP_printk("[%s] ampdu session max_len=%u max_frames=%u len=%u frames=%u dma_len=%u",
-                 __get_str(dev), __entry->max_ampdu_len,
-                 __entry->max_ampdu_frames, __entry->ampdu_len,
-                 __entry->ampdu_frames, __entry->dma_len)
-);
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM brcmsmac_msg
-
-#define MAX_MSG_LEN    100
-
-DECLARE_EVENT_CLASS(brcms_msg_event,
-       TP_PROTO(struct va_format *vaf),
-       TP_ARGS(vaf),
-       TP_STRUCT__entry(
-               __dynamic_array(char, msg, MAX_MSG_LEN)
-       ),
-       TP_fast_assign(
-               WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
-                                      MAX_MSG_LEN, vaf->fmt,
-                                      *vaf->va) >= MAX_MSG_LEN);
-       ),
-       TP_printk("%s", __get_str(msg))
-);
-
-DEFINE_EVENT(brcms_msg_event, brcms_info,
-       TP_PROTO(struct va_format *vaf),
-       TP_ARGS(vaf)
-);
-
-DEFINE_EVENT(brcms_msg_event, brcms_warn,
-       TP_PROTO(struct va_format *vaf),
-       TP_ARGS(vaf)
-);
-
-DEFINE_EVENT(brcms_msg_event, brcms_err,
-       TP_PROTO(struct va_format *vaf),
-       TP_ARGS(vaf)
-);
-
-DEFINE_EVENT(brcms_msg_event, brcms_crit,
-       TP_PROTO(struct va_format *vaf),
-       TP_ARGS(vaf)
-);
-
-TRACE_EVENT(brcms_dbg,
-       TP_PROTO(u32 level, const char *func, struct va_format *vaf),
-       TP_ARGS(level, func, vaf),
-       TP_STRUCT__entry(
-               __field(u32, level)
-               __string(func, func)
-               __dynamic_array(char, msg, MAX_MSG_LEN)
-       ),
-       TP_fast_assign(
-               __entry->level = level;
-               __assign_str(func, func);
-               WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
-                                      MAX_MSG_LEN, vaf->fmt,
-                                      *vaf->va) >= MAX_MSG_LEN);
-       ),
-       TP_printk("%s: %s", __get_str(func), __get_str(msg))
-);
+#include "brcms_trace_brcmsmac.h"
+#include "brcms_trace_brcmsmac_tx.h"
+#include "brcms_trace_brcmsmac_msg.h"
 
 #endif /* __TRACE_BRCMSMAC_H */
-
-#ifdef CONFIG_BRCM_TRACING
-
-#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
-#undef TRACE_INCLUDE_FILE
-#define TRACE_INCLUDE_FILE brcms_trace_events
-
-#include <trace/define_trace.h>
-
-#endif /* CONFIG_BRCM_TRACING */
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace-data.h b/drivers/net/wireless/iwlwifi/iwl-devtrace-data.h
new file mode 100644 (file)
index 0000000..04e6649
--- /dev/null
@@ -0,0 +1,79 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#if !defined(__IWLWIFI_DEVICE_TRACE_DATA) || defined(TRACE_HEADER_MULTI_READ)
+#define __IWLWIFI_DEVICE_TRACE_DATA
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi_data
+
+TRACE_EVENT(iwlwifi_dev_tx_data,
+       TP_PROTO(const struct device *dev,
+                struct sk_buff *skb,
+                void *data, size_t data_len),
+       TP_ARGS(dev, skb, data, data_len),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+
+               __dynamic_array(u8, data, iwl_trace_data(skb) ? data_len : 0)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               if (iwl_trace_data(skb))
+                       memcpy(__get_dynamic_array(data), data, data_len);
+       ),
+       TP_printk("[%s] TX frame data", __get_str(dev))
+);
+
+TRACE_EVENT(iwlwifi_dev_rx_data,
+       TP_PROTO(const struct device *dev,
+                const struct iwl_trans *trans,
+                void *rxbuf, size_t len),
+       TP_ARGS(dev, trans, rxbuf, len),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+
+               __dynamic_array(u8, data,
+                               len - iwl_rx_trace_len(trans, rxbuf, len))
+       ),
+       TP_fast_assign(
+               size_t offs = iwl_rx_trace_len(trans, rxbuf, len);
+               DEV_ASSIGN;
+               if (offs < len)
+                       memcpy(__get_dynamic_array(data),
+                              ((u8 *)rxbuf) + offs, len - offs);
+       ),
+       TP_printk("[%s] RX frame data", __get_str(dev))
+);
+#endif /* __IWLWIFI_DEVICE_TRACE_DATA */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE iwl-devtrace-data
+#include <trace/define_trace.h>
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace-io.h b/drivers/net/wireless/iwlwifi/iwl-devtrace-io.h
new file mode 100644 (file)
index 0000000..f62c544
--- /dev/null
@@ -0,0 +1,155 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#if !defined(__IWLWIFI_DEVICE_TRACE_IO) || defined(TRACE_HEADER_MULTI_READ)
+#define __IWLWIFI_DEVICE_TRACE_IO
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi_io
+
+TRACE_EVENT(iwlwifi_dev_ioread32,
+       TP_PROTO(const struct device *dev, u32 offs, u32 val),
+       TP_ARGS(dev, offs, val),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u32, offs)
+               __field(u32, val)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->offs = offs;
+               __entry->val = val;
+       ),
+       TP_printk("[%s] read io[%#x] = %#x",
+                 __get_str(dev), __entry->offs, __entry->val)
+);
+
+TRACE_EVENT(iwlwifi_dev_iowrite8,
+       TP_PROTO(const struct device *dev, u32 offs, u8 val),
+       TP_ARGS(dev, offs, val),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u32, offs)
+               __field(u8, val)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->offs = offs;
+               __entry->val = val;
+       ),
+       TP_printk("[%s] write io[%#x] = %#x)",
+                 __get_str(dev), __entry->offs, __entry->val)
+);
+
+TRACE_EVENT(iwlwifi_dev_iowrite32,
+       TP_PROTO(const struct device *dev, u32 offs, u32 val),
+       TP_ARGS(dev, offs, val),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u32, offs)
+               __field(u32, val)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->offs = offs;
+               __entry->val = val;
+       ),
+       TP_printk("[%s] write io[%#x] = %#x)",
+                 __get_str(dev), __entry->offs, __entry->val)
+);
+
+TRACE_EVENT(iwlwifi_dev_iowrite_prph32,
+       TP_PROTO(const struct device *dev, u32 offs, u32 val),
+       TP_ARGS(dev, offs, val),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u32, offs)
+               __field(u32, val)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->offs = offs;
+               __entry->val = val;
+       ),
+       TP_printk("[%s] write PRPH[%#x] = %#x)",
+                 __get_str(dev), __entry->offs, __entry->val)
+);
+
+TRACE_EVENT(iwlwifi_dev_ioread_prph32,
+       TP_PROTO(const struct device *dev, u32 offs, u32 val),
+       TP_ARGS(dev, offs, val),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u32, offs)
+               __field(u32, val)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->offs = offs;
+               __entry->val = val;
+       ),
+       TP_printk("[%s] read PRPH[%#x] = %#x",
+                 __get_str(dev), __entry->offs, __entry->val)
+);
+
+TRACE_EVENT(iwlwifi_dev_irq,
+       TP_PROTO(const struct device *dev),
+       TP_ARGS(dev),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+       ),
+       /* TP_printk("") doesn't compile */
+       TP_printk("%d", 0)
+);
+
+TRACE_EVENT(iwlwifi_dev_ict_read,
+       TP_PROTO(const struct device *dev, u32 index, u32 value),
+       TP_ARGS(dev, index, value),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u32, index)
+               __field(u32, value)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->index = index;
+               __entry->value = value;
+       ),
+       TP_printk("[%s] read ict[%d] = %#.8x",
+                 __get_str(dev), __entry->index, __entry->value)
+);
+#endif /* __IWLWIFI_DEVICE_TRACE_IO */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE iwl-devtrace-io
+#include <trace/define_trace.h>
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace-iwlwifi.h b/drivers/net/wireless/iwlwifi/iwl-devtrace-iwlwifi.h
new file mode 100644 (file)
index 0000000..6cb66a9
--- /dev/null
@@ -0,0 +1,200 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#if !defined(__IWLWIFI_DEVICE_TRACE_IWLWIFI) || defined(TRACE_HEADER_MULTI_READ)
+#define __IWLWIFI_DEVICE_TRACE_IWLWIFI
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi
+
+TRACE_EVENT(iwlwifi_dev_hcmd,
+       TP_PROTO(const struct device *dev,
+                struct iwl_host_cmd *cmd, u16 total_size,
+                struct iwl_cmd_header *hdr),
+       TP_ARGS(dev, cmd, total_size, hdr),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __dynamic_array(u8, hcmd, total_size)
+               __field(u32, flags)
+       ),
+       TP_fast_assign(
+               int i, offset = sizeof(*hdr);
+
+               DEV_ASSIGN;
+               __entry->flags = cmd->flags;
+               memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr));
+
+               for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
+                       if (!cmd->len[i])
+                               continue;
+                       memcpy((u8 *)__get_dynamic_array(hcmd) + offset,
+                              cmd->data[i], cmd->len[i]);
+                       offset += cmd->len[i];
+               }
+       ),
+       TP_printk("[%s] hcmd %#.2x (%ssync)",
+                 __get_str(dev), ((u8 *)__get_dynamic_array(hcmd))[0],
+                 __entry->flags & CMD_ASYNC ? "a" : "")
+);
+
+TRACE_EVENT(iwlwifi_dev_rx,
+       TP_PROTO(const struct device *dev, const struct iwl_trans *trans,
+                void *rxbuf, size_t len),
+       TP_ARGS(dev, trans, rxbuf, len),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, rxbuf, len))
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               memcpy(__get_dynamic_array(rxbuf), rxbuf,
+                      iwl_rx_trace_len(trans, rxbuf, len));
+       ),
+       TP_printk("[%s] RX cmd %#.2x",
+                 __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
+);
+
+TRACE_EVENT(iwlwifi_dev_tx,
+       TP_PROTO(const struct device *dev, struct sk_buff *skb,
+                void *tfd, size_t tfdlen,
+                void *buf0, size_t buf0_len,
+                void *buf1, size_t buf1_len),
+       TP_ARGS(dev, skb, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+
+               __field(size_t, framelen)
+               __dynamic_array(u8, tfd, tfdlen)
+
+               /*
+                * Do not insert between or below these items,
+                * we want to keep the frame together (except
+                * for the possible padding).
+                */
+               __dynamic_array(u8, buf0, buf0_len)
+               __dynamic_array(u8, buf1, iwl_trace_data(skb) ? 0 : buf1_len)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->framelen = buf0_len + buf1_len;
+               memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
+               memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
+               if (!iwl_trace_data(skb))
+                       memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
+       ),
+       TP_printk("[%s] TX %.2x (%zu bytes)",
+                 __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
+                 __entry->framelen)
+);
+
+TRACE_EVENT(iwlwifi_dev_ucode_error,
+       TP_PROTO(const struct device *dev, u32 desc, u32 tsf_low,
+                u32 data1, u32 data2, u32 line, u32 blink1,
+                u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time,
+                u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver,
+                u32 brd_ver),
+       TP_ARGS(dev, desc, tsf_low, data1, data2, line,
+               blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2,
+               gp3, ucode_ver, hw_ver, brd_ver),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+               __field(u32, desc)
+               __field(u32, tsf_low)
+               __field(u32, data1)
+               __field(u32, data2)
+               __field(u32, line)
+               __field(u32, blink1)
+               __field(u32, blink2)
+               __field(u32, ilink1)
+               __field(u32, ilink2)
+               __field(u32, bcon_time)
+               __field(u32, gp1)
+               __field(u32, gp2)
+               __field(u32, gp3)
+               __field(u32, ucode_ver)
+               __field(u32, hw_ver)
+               __field(u32, brd_ver)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->desc = desc;
+               __entry->tsf_low = tsf_low;
+               __entry->data1 = data1;
+               __entry->data2 = data2;
+               __entry->line = line;
+               __entry->blink1 = blink1;
+               __entry->blink2 = blink2;
+               __entry->ilink1 = ilink1;
+               __entry->ilink2 = ilink2;
+               __entry->bcon_time = bcon_time;
+               __entry->gp1 = gp1;
+               __entry->gp2 = gp2;
+               __entry->gp3 = gp3;
+               __entry->ucode_ver = ucode_ver;
+               __entry->hw_ver = hw_ver;
+               __entry->brd_ver = brd_ver;
+       ),
+       TP_printk("[%s] #%02d %010u data 0x%08X 0x%08X line %u, "
+                 "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X "
+                 "bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X "
+                 "hw 0x%08X brd 0x%08X",
+                 __get_str(dev), __entry->desc, __entry->tsf_low,
+                 __entry->data1,
+                 __entry->data2, __entry->line, __entry->blink1,
+                 __entry->blink2, __entry->ilink1, __entry->ilink2,
+                 __entry->bcon_time, __entry->gp1, __entry->gp2,
+                 __entry->gp3, __entry->ucode_ver, __entry->hw_ver,
+                 __entry->brd_ver)
+);
+
+TRACE_EVENT(iwlwifi_dev_ucode_event,
+       TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
+       TP_ARGS(dev, time, data, ev),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+
+               __field(u32, time)
+               __field(u32, data)
+               __field(u32, ev)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->time = time;
+               __entry->data = data;
+               __entry->ev = ev;
+       ),
+       TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
+                 __get_str(dev), __entry->time, __entry->data, __entry->ev)
+);
+#endif /* __IWLWIFI_DEVICE_TRACE_IWLWIFI */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE iwl-devtrace-iwlwifi
+#include <trace/define_trace.h>
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace-msg.h b/drivers/net/wireless/iwlwifi/iwl-devtrace-msg.h
new file mode 100644 (file)
index 0000000..a3b3c24
--- /dev/null
@@ -0,0 +1,97 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#if !defined(__IWLWIFI_DEVICE_TRACE_MSG) || defined(TRACE_HEADER_MULTI_READ)
+#define __IWLWIFI_DEVICE_TRACE_MSG
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi_msg
+
+#define MAX_MSG_LEN    110
+
+DECLARE_EVENT_CLASS(iwlwifi_msg_event,
+       TP_PROTO(struct va_format *vaf),
+       TP_ARGS(vaf),
+       TP_STRUCT__entry(
+               __dynamic_array(char, msg, MAX_MSG_LEN)
+       ),
+       TP_fast_assign(
+               WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+                                      MAX_MSG_LEN, vaf->fmt,
+                                      *vaf->va) >= MAX_MSG_LEN);
+       ),
+       TP_printk("%s", __get_str(msg))
+);
+
+DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_err,
+       TP_PROTO(struct va_format *vaf),
+       TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_warn,
+       TP_PROTO(struct va_format *vaf),
+       TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_info,
+       TP_PROTO(struct va_format *vaf),
+       TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_crit,
+       TP_PROTO(struct va_format *vaf),
+       TP_ARGS(vaf)
+);
+
+TRACE_EVENT(iwlwifi_dbg,
+       TP_PROTO(u32 level, bool in_interrupt, const char *function,
+                struct va_format *vaf),
+       TP_ARGS(level, in_interrupt, function, vaf),
+       TP_STRUCT__entry(
+               __field(u32, level)
+               __field(u8, in_interrupt)
+               __string(function, function)
+               __dynamic_array(char, msg, MAX_MSG_LEN)
+       ),
+       TP_fast_assign(
+               __entry->level = level;
+               __entry->in_interrupt = in_interrupt;
+               __assign_str(function, function);
+               WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+                                      MAX_MSG_LEN, vaf->fmt,
+                                      *vaf->va) >= MAX_MSG_LEN);
+       ),
+       TP_printk("%s", __get_str(msg))
+);
+#endif /* __IWLWIFI_DEVICE_TRACE_MSG */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE iwl-devtrace-msg
+#include <trace/define_trace.h>
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace-ucode.h b/drivers/net/wireless/iwlwifi/iwl-devtrace-ucode.h
new file mode 100644 (file)
index 0000000..10839fa
--- /dev/null
@@ -0,0 +1,81 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#if !defined(__IWLWIFI_DEVICE_TRACE_UCODE) || defined(TRACE_HEADER_MULTI_READ)
+#define __IWLWIFI_DEVICE_TRACE_UCODE
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi_ucode
+
+TRACE_EVENT(iwlwifi_dev_ucode_cont_event,
+       TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
+       TP_ARGS(dev, time, data, ev),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+
+               __field(u32, time)
+               __field(u32, data)
+               __field(u32, ev)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->time = time;
+               __entry->data = data;
+               __entry->ev = ev;
+       ),
+       TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
+                 __get_str(dev), __entry->time, __entry->data, __entry->ev)
+);
+
+TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
+       TP_PROTO(const struct device *dev, u32 wraps, u32 n_entry, u32 p_entry),
+       TP_ARGS(dev, wraps, n_entry, p_entry),
+       TP_STRUCT__entry(
+               DEV_ENTRY
+
+               __field(u32, wraps)
+               __field(u32, n_entry)
+               __field(u32, p_entry)
+       ),
+       TP_fast_assign(
+               DEV_ASSIGN;
+               __entry->wraps = wraps;
+               __entry->n_entry = n_entry;
+               __entry->p_entry = p_entry;
+       ),
+       TP_printk("[%s] wraps=#%02d n=0x%X p=0x%X",
+                 __get_str(dev), __entry->wraps, __entry->n_entry,
+                 __entry->p_entry)
+);
+#endif /* __IWLWIFI_DEVICE_TRACE_UCODE */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE iwl-devtrace-ucode
+#include <trace/define_trace.h>
index 78bd41bf34b0f04dac4d056d470ac30a80b212c8..b87acd6a229b8b3017b52178fdcbb29922660b59 100644 (file)
@@ -24,7 +24,7 @@
  *
  *****************************************************************************/
 
-#if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#ifndef __IWLWIFI_DEVICE_TRACE
 #include <linux/skbuff.h>
 #include <linux/ieee80211.h>
 #include <net/cfg80211.h>
@@ -80,436 +80,10 @@ static inline void trace_ ## name(proto) {}
 #define DEV_ENTRY      __string(dev, dev_name(dev))
 #define DEV_ASSIGN     __assign_str(dev, dev_name(dev))
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM iwlwifi_io
+#include "iwl-devtrace-io.h"
+#include "iwl-devtrace-ucode.h"
+#include "iwl-devtrace-msg.h"
+#include "iwl-devtrace-data.h"
+#include "iwl-devtrace-iwlwifi.h"
 
-TRACE_EVENT(iwlwifi_dev_ioread32,
-       TP_PROTO(const struct device *dev, u32 offs, u32 val),
-       TP_ARGS(dev, offs, val),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-               __field(u32, offs)
-               __field(u32, val)
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-               __entry->offs = offs;
-               __entry->val = val;
-       ),
-       TP_printk("[%s] read io[%#x] = %#x",
-                 __get_str(dev), __entry->offs, __entry->val)
-);
-
-TRACE_EVENT(iwlwifi_dev_iowrite8,
-       TP_PROTO(const struct device *dev, u32 offs, u8 val),
-       TP_ARGS(dev, offs, val),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-               __field(u32, offs)
-               __field(u8, val)
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-               __entry->offs = offs;
-               __entry->val = val;
-       ),
-       TP_printk("[%s] write io[%#x] = %#x)",
-                 __get_str(dev), __entry->offs, __entry->val)
-);
-
-TRACE_EVENT(iwlwifi_dev_iowrite32,
-       TP_PROTO(const struct device *dev, u32 offs, u32 val),
-       TP_ARGS(dev, offs, val),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-               __field(u32, offs)
-               __field(u32, val)
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-               __entry->offs = offs;
-               __entry->val = val;
-       ),
-       TP_printk("[%s] write io[%#x] = %#x)",
-                 __get_str(dev), __entry->offs, __entry->val)
-);
-
-TRACE_EVENT(iwlwifi_dev_iowrite_prph32,
-       TP_PROTO(const struct device *dev, u32 offs, u32 val),
-       TP_ARGS(dev, offs, val),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-               __field(u32, offs)
-               __field(u32, val)
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-               __entry->offs = offs;
-               __entry->val = val;
-       ),
-       TP_printk("[%s] write PRPH[%#x] = %#x)",
-                 __get_str(dev), __entry->offs, __entry->val)
-);
-
-TRACE_EVENT(iwlwifi_dev_ioread_prph32,
-       TP_PROTO(const struct device *dev, u32 offs, u32 val),
-       TP_ARGS(dev, offs, val),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-               __field(u32, offs)
-               __field(u32, val)
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-               __entry->offs = offs;
-               __entry->val = val;
-       ),
-       TP_printk("[%s] read PRPH[%#x] = %#x",
-                 __get_str(dev), __entry->offs, __entry->val)
-);
-
-TRACE_EVENT(iwlwifi_dev_irq,
-       TP_PROTO(const struct device *dev),
-       TP_ARGS(dev),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-       ),
-       /* TP_printk("") doesn't compile */
-       TP_printk("%d", 0)
-);
-
-TRACE_EVENT(iwlwifi_dev_ict_read,
-       TP_PROTO(const struct device *dev, u32 index, u32 value),
-       TP_ARGS(dev, index, value),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-               __field(u32, index)
-               __field(u32, value)
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-               __entry->index = index;
-               __entry->value = value;
-       ),
-       TP_printk("[%s] read ict[%d] = %#.8x",
-                 __get_str(dev), __entry->index, __entry->value)
-);
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM iwlwifi_ucode
-
-TRACE_EVENT(iwlwifi_dev_ucode_cont_event,
-       TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
-       TP_ARGS(dev, time, data, ev),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-
-               __field(u32, time)
-               __field(u32, data)
-               __field(u32, ev)
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-               __entry->time = time;
-               __entry->data = data;
-               __entry->ev = ev;
-       ),
-       TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
-                 __get_str(dev), __entry->time, __entry->data, __entry->ev)
-);
-
-TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
-       TP_PROTO(const struct device *dev, u32 wraps, u32 n_entry, u32 p_entry),
-       TP_ARGS(dev, wraps, n_entry, p_entry),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-
-               __field(u32, wraps)
-               __field(u32, n_entry)
-               __field(u32, p_entry)
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-               __entry->wraps = wraps;
-               __entry->n_entry = n_entry;
-               __entry->p_entry = p_entry;
-       ),
-       TP_printk("[%s] wraps=#%02d n=0x%X p=0x%X",
-                 __get_str(dev), __entry->wraps, __entry->n_entry,
-                 __entry->p_entry)
-);
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM iwlwifi_msg
-
-#define MAX_MSG_LEN    110
-
-DECLARE_EVENT_CLASS(iwlwifi_msg_event,
-       TP_PROTO(struct va_format *vaf),
-       TP_ARGS(vaf),
-       TP_STRUCT__entry(
-               __dynamic_array(char, msg, MAX_MSG_LEN)
-       ),
-       TP_fast_assign(
-               WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
-                                      MAX_MSG_LEN, vaf->fmt,
-                                      *vaf->va) >= MAX_MSG_LEN);
-       ),
-       TP_printk("%s", __get_str(msg))
-);
-
-DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_err,
-       TP_PROTO(struct va_format *vaf),
-       TP_ARGS(vaf)
-);
-
-DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_warn,
-       TP_PROTO(struct va_format *vaf),
-       TP_ARGS(vaf)
-);
-
-DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_info,
-       TP_PROTO(struct va_format *vaf),
-       TP_ARGS(vaf)
-);
-
-DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_crit,
-       TP_PROTO(struct va_format *vaf),
-       TP_ARGS(vaf)
-);
-
-TRACE_EVENT(iwlwifi_dbg,
-       TP_PROTO(u32 level, bool in_interrupt, const char *function,
-                struct va_format *vaf),
-       TP_ARGS(level, in_interrupt, function, vaf),
-       TP_STRUCT__entry(
-               __field(u32, level)
-               __field(u8, in_interrupt)
-               __string(function, function)
-               __dynamic_array(char, msg, MAX_MSG_LEN)
-       ),
-       TP_fast_assign(
-               __entry->level = level;
-               __entry->in_interrupt = in_interrupt;
-               __assign_str(function, function);
-               WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
-                                      MAX_MSG_LEN, vaf->fmt,
-                                      *vaf->va) >= MAX_MSG_LEN);
-       ),
-       TP_printk("%s", __get_str(msg))
-);
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM iwlwifi_data
-
-TRACE_EVENT(iwlwifi_dev_tx_data,
-       TP_PROTO(const struct device *dev,
-                struct sk_buff *skb,
-                void *data, size_t data_len),
-       TP_ARGS(dev, skb, data, data_len),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-
-               __dynamic_array(u8, data, iwl_trace_data(skb) ? data_len : 0)
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-               if (iwl_trace_data(skb))
-                       memcpy(__get_dynamic_array(data), data, data_len);
-       ),
-       TP_printk("[%s] TX frame data", __get_str(dev))
-);
-
-TRACE_EVENT(iwlwifi_dev_rx_data,
-       TP_PROTO(const struct device *dev,
-                const struct iwl_trans *trans,
-                void *rxbuf, size_t len),
-       TP_ARGS(dev, trans, rxbuf, len),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-
-               __dynamic_array(u8, data,
-                               len - iwl_rx_trace_len(trans, rxbuf, len))
-       ),
-       TP_fast_assign(
-               size_t offs = iwl_rx_trace_len(trans, rxbuf, len);
-               DEV_ASSIGN;
-               if (offs < len)
-                       memcpy(__get_dynamic_array(data),
-                              ((u8 *)rxbuf) + offs, len - offs);
-       ),
-       TP_printk("[%s] RX frame data", __get_str(dev))
-);
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM iwlwifi
-
-TRACE_EVENT(iwlwifi_dev_hcmd,
-       TP_PROTO(const struct device *dev,
-                struct iwl_host_cmd *cmd, u16 total_size,
-                struct iwl_cmd_header *hdr),
-       TP_ARGS(dev, cmd, total_size, hdr),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-               __dynamic_array(u8, hcmd, total_size)
-               __field(u32, flags)
-       ),
-       TP_fast_assign(
-               int i, offset = sizeof(*hdr);
-
-               DEV_ASSIGN;
-               __entry->flags = cmd->flags;
-               memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr));
-
-               for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
-                       if (!cmd->len[i])
-                               continue;
-                       memcpy((u8 *)__get_dynamic_array(hcmd) + offset,
-                              cmd->data[i], cmd->len[i]);
-                       offset += cmd->len[i];
-               }
-       ),
-       TP_printk("[%s] hcmd %#.2x (%ssync)",
-                 __get_str(dev), ((u8 *)__get_dynamic_array(hcmd))[0],
-                 __entry->flags & CMD_ASYNC ? "a" : "")
-);
-
-TRACE_EVENT(iwlwifi_dev_rx,
-       TP_PROTO(const struct device *dev, const struct iwl_trans *trans,
-                void *rxbuf, size_t len),
-       TP_ARGS(dev, trans, rxbuf, len),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-               __dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, rxbuf, len))
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-               memcpy(__get_dynamic_array(rxbuf), rxbuf,
-                      iwl_rx_trace_len(trans, rxbuf, len));
-       ),
-       TP_printk("[%s] RX cmd %#.2x",
-                 __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
-);
-
-TRACE_EVENT(iwlwifi_dev_tx,
-       TP_PROTO(const struct device *dev, struct sk_buff *skb,
-                void *tfd, size_t tfdlen,
-                void *buf0, size_t buf0_len,
-                void *buf1, size_t buf1_len),
-       TP_ARGS(dev, skb, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-
-               __field(size_t, framelen)
-               __dynamic_array(u8, tfd, tfdlen)
-
-               /*
-                * Do not insert between or below these items,
-                * we want to keep the frame together (except
-                * for the possible padding).
-                */
-               __dynamic_array(u8, buf0, buf0_len)
-               __dynamic_array(u8, buf1, iwl_trace_data(skb) ? 0 : buf1_len)
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-               __entry->framelen = buf0_len + buf1_len;
-               memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
-               memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
-               if (!iwl_trace_data(skb))
-                       memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
-       ),
-       TP_printk("[%s] TX %.2x (%zu bytes)",
-                 __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
-                 __entry->framelen)
-);
-
-TRACE_EVENT(iwlwifi_dev_ucode_error,
-       TP_PROTO(const struct device *dev, u32 desc, u32 tsf_low,
-                u32 data1, u32 data2, u32 line, u32 blink1,
-                u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time,
-                u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver,
-                u32 brd_ver),
-       TP_ARGS(dev, desc, tsf_low, data1, data2, line,
-               blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2,
-               gp3, ucode_ver, hw_ver, brd_ver),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-               __field(u32, desc)
-               __field(u32, tsf_low)
-               __field(u32, data1)
-               __field(u32, data2)
-               __field(u32, line)
-               __field(u32, blink1)
-               __field(u32, blink2)
-               __field(u32, ilink1)
-               __field(u32, ilink2)
-               __field(u32, bcon_time)
-               __field(u32, gp1)
-               __field(u32, gp2)
-               __field(u32, gp3)
-               __field(u32, ucode_ver)
-               __field(u32, hw_ver)
-               __field(u32, brd_ver)
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-               __entry->desc = desc;
-               __entry->tsf_low = tsf_low;
-               __entry->data1 = data1;
-               __entry->data2 = data2;
-               __entry->line = line;
-               __entry->blink1 = blink1;
-               __entry->blink2 = blink2;
-               __entry->ilink1 = ilink1;
-               __entry->ilink2 = ilink2;
-               __entry->bcon_time = bcon_time;
-               __entry->gp1 = gp1;
-               __entry->gp2 = gp2;
-               __entry->gp3 = gp3;
-               __entry->ucode_ver = ucode_ver;
-               __entry->hw_ver = hw_ver;
-               __entry->brd_ver = brd_ver;
-       ),
-       TP_printk("[%s] #%02d %010u data 0x%08X 0x%08X line %u, "
-                 "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X "
-                 "bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X "
-                 "hw 0x%08X brd 0x%08X",
-                 __get_str(dev), __entry->desc, __entry->tsf_low,
-                 __entry->data1,
-                 __entry->data2, __entry->line, __entry->blink1,
-                 __entry->blink2, __entry->ilink1, __entry->ilink2,
-                 __entry->bcon_time, __entry->gp1, __entry->gp2,
-                 __entry->gp3, __entry->ucode_ver, __entry->hw_ver,
-                 __entry->brd_ver)
-);
-
-TRACE_EVENT(iwlwifi_dev_ucode_event,
-       TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
-       TP_ARGS(dev, time, data, ev),
-       TP_STRUCT__entry(
-               DEV_ENTRY
-
-               __field(u32, time)
-               __field(u32, data)
-               __field(u32, ev)
-       ),
-       TP_fast_assign(
-               DEV_ASSIGN;
-               __entry->time = time;
-               __entry->data = data;
-               __entry->ev = ev;
-       ),
-       TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
-                 __get_str(dev), __entry->time, __entry->data, __entry->ev)
-);
 #endif /* __IWLWIFI_DEVICE_TRACE */
-
-#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
-#undef TRACE_INCLUDE_FILE
-#define TRACE_INCLUDE_FILE iwl-devtrace
-#include <trace/define_trace.h>
index 2367e8f47a5b57bd1c3ee9ce6080ecf4986cf168..e77c3a46c94a65ff0bad9578fdf22b725a50320f 100644 (file)
@@ -309,7 +309,7 @@ static void rtl8723be_dm_find_minimum_rssi(struct ieee80211_hw *hw)
                rtl_dm_dig->min_undec_pwdb_for_dm =
                                rtlpriv->dm.entry_min_undec_sm_pwdb;
                RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
-                        "AP Ext Port or disconnet PWDB = 0x%x\n",
+                        "AP Ext Port or disconnect PWDB = 0x%x\n",
                          rtl_dm_dig->min_undec_pwdb_for_dm);
        }
        RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n",
index 0b2082dc48f110aa00f09e4ec4893ea9d488ccdf..342678d2ed427d8549d446f5cb5ec0bbc5f3c41d 100644 (file)
@@ -873,7 +873,7 @@ static void rtl8821ae_dm_dig(struct ieee80211_hw *hw)
 
        if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
                RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
-                        "Abnornally false alarm case.\n");
+                        "Abnormally false alarm case.\n");
 
                if (dm_digtable->large_fa_hit != 3)
                        dm_digtable->large_fa_hit++;
index 8f165b112e03a285899655984491b000f0020e17..4cc06c702c41a46653c74d4ab863d708804e4e17 100644 (file)
@@ -1960,6 +1960,32 @@ int of_alias_get_id(struct device_node *np, const char *stem)
 }
 EXPORT_SYMBOL_GPL(of_alias_get_id);
 
+/**
+ * of_alias_get_highest_id - Get highest alias id for the given stem
+ * @stem:      Alias stem to be examined
+ *
+ * The function travels the lookup table to get the highest alias id for the
+ * given alias stem.  It returns the alias id if found.
+ */
+int of_alias_get_highest_id(const char *stem)
+{
+       struct alias_prop *app;
+       int id = -ENODEV;
+
+       mutex_lock(&of_mutex);
+       list_for_each_entry(app, &aliases_lookup, link) {
+               if (strcmp(app->stem, stem) != 0)
+                       continue;
+
+               if (app->id > id)
+                       id = app->id;
+       }
+       mutex_unlock(&of_mutex);
+
+       return id;
+}
+EXPORT_SYMBOL_GPL(of_alias_get_highest_id);
+
 const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
                               u32 *pu)
 {
index 46d6c75c14040903edf9b14f2ec2030c179b2c1e..20c1332a00182cb43bb707e2a7468dce73cdf991 100644 (file)
@@ -2,6 +2,9 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_iommu.h>
+#include <linux/dma-mapping.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mod_devicetable.h>
@@ -66,6 +69,87 @@ int of_device_add(struct platform_device *ofdev)
        return device_add(&ofdev->dev);
 }
 
+/**
+ * of_dma_configure - Setup DMA configuration
+ * @dev:       Device to apply DMA configuration
+ * @np:                Pointer to OF node having DMA configuration
+ *
+ * Try to get devices's DMA configuration from DT and update it
+ * accordingly.
+ *
+ * If platform code needs to use its own special DMA configuration, it
+ * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
+ * to fix up DMA configuration.
+ */
+void of_dma_configure(struct device *dev, struct device_node *np)
+{
+       u64 dma_addr, paddr, size;
+       int ret;
+       bool coherent;
+       unsigned long offset;
+       struct iommu_ops *iommu;
+
+       /*
+        * Set default coherent_dma_mask to 32 bit.  Drivers are expected to
+        * setup the correct supported mask.
+        */
+       if (!dev->coherent_dma_mask)
+               dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+       /*
+        * Set it to coherent_dma_mask by default if the architecture
+        * code has not set it.
+        */
+       if (!dev->dma_mask)
+               dev->dma_mask = &dev->coherent_dma_mask;
+
+       ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
+       if (ret < 0) {
+               dma_addr = offset = 0;
+               size = dev->coherent_dma_mask + 1;
+       } else {
+               offset = PFN_DOWN(paddr - dma_addr);
+
+               /*
+                * Add a work around to treat the size as mask + 1 in case
+                * it is defined in DT as a mask.
+                */
+               if (size & 1) {
+                       dev_warn(dev, "Invalid size 0x%llx for dma-range\n",
+                                size);
+                       size = size + 1;
+               }
+
+               if (!size) {
+                       dev_err(dev, "Adjusted size 0x%llx invalid\n", size);
+                       return;
+               }
+               dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
+       }
+
+       dev->dma_pfn_offset = offset;
+
+       /*
+        * Limit coherent and dma mask based on size and default mask
+        * set by the driver.
+        */
+       dev->coherent_dma_mask = min(dev->coherent_dma_mask,
+                                    DMA_BIT_MASK(ilog2(dma_addr + size)));
+       *dev->dma_mask = min((*dev->dma_mask),
+                            DMA_BIT_MASK(ilog2(dma_addr + size)));
+
+       coherent = of_dma_is_coherent(np);
+       dev_dbg(dev, "device is%sdma coherent\n",
+               coherent ? " " : " not ");
+
+       iommu = of_iommu_configure(dev, np);
+       dev_dbg(dev, "device is%sbehind an iommu\n",
+               iommu ? " " : " not ");
+
+       arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
+}
+EXPORT_SYMBOL_GPL(of_dma_configure);
+
 int of_device_register(struct platform_device *pdev)
 {
        device_initialize(&pdev->dev);
index 62426d81a4d656c7dfd57c32a6a5bfd15398c6ca..5751dc5b6494d41fd0ed9fd88cc877f3d10707a0 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/export.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/of_pci.h>
 #include <linux/slab.h>
 
@@ -116,6 +117,26 @@ int of_get_pci_domain_nr(struct device_node *node)
 }
 EXPORT_SYMBOL_GPL(of_get_pci_domain_nr);
 
+/**
+ * of_pci_dma_configure - Setup DMA configuration
+ * @dev: ptr to pci_dev struct of the PCI device
+ *
+ * Function to update PCI devices's DMA configuration using the same
+ * info from the OF node of host bridge's parent (if any).
+ */
+void of_pci_dma_configure(struct pci_dev *pci_dev)
+{
+       struct device *dev = &pci_dev->dev;
+       struct device *bridge = pci_get_host_bridge_device(pci_dev);
+
+       if (!bridge->parent)
+               return;
+
+       of_dma_configure(dev, bridge->parent->of_node);
+       pci_put_host_bridge_device(bridge);
+}
+EXPORT_SYMBOL_GPL(of_pci_dma_configure);
+
 #if defined(CONFIG_OF_ADDRESS)
 /**
  * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT
index b189733a1539a03c6b44cbb65d3ba165fef3fc0e..a01f57c9e34eab8a95306b0a2643d26d2d764a1c 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/slab.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
-#include <linux/of_iommu.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
@@ -150,59 +149,6 @@ struct platform_device *of_device_alloc(struct device_node *np,
 }
 EXPORT_SYMBOL(of_device_alloc);
 
-/**
- * of_dma_configure - Setup DMA configuration
- * @dev:       Device to apply DMA configuration
- *
- * Try to get devices's DMA configuration from DT and update it
- * accordingly.
- *
- * In case if platform code need to use own special DMA configuration,it
- * can use Platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE event
- * to fix up DMA configuration.
- */
-static void of_dma_configure(struct device *dev)
-{
-       u64 dma_addr, paddr, size;
-       int ret;
-       bool coherent;
-       unsigned long offset;
-       struct iommu_ops *iommu;
-
-       /*
-        * Set default dma-mask to 32 bit. Drivers are expected to setup
-        * the correct supported dma_mask.
-        */
-       dev->coherent_dma_mask = DMA_BIT_MASK(32);
-
-       /*
-        * Set it to coherent_dma_mask by default if the architecture
-        * code has not set it.
-        */
-       if (!dev->dma_mask)
-               dev->dma_mask = &dev->coherent_dma_mask;
-
-       ret = of_dma_get_range(dev->of_node, &dma_addr, &paddr, &size);
-       if (ret < 0) {
-               dma_addr = offset = 0;
-               size = dev->coherent_dma_mask;
-       } else {
-               offset = PFN_DOWN(paddr - dma_addr);
-               dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
-       }
-       dev->dma_pfn_offset = offset;
-
-       coherent = of_dma_is_coherent(dev->of_node);
-       dev_dbg(dev, "device is%sdma coherent\n",
-               coherent ? " " : " not ");
-
-       iommu = of_iommu_configure(dev);
-       dev_dbg(dev, "device is%sbehind an iommu\n",
-               iommu ? " " : " not ");
-
-       arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
-}
-
 static void of_dma_deconfigure(struct device *dev)
 {
        arch_teardown_dma_ops(dev);
@@ -236,7 +182,7 @@ static struct platform_device *of_platform_device_create_pdata(
 
        dev->dev.bus = &platform_bus_type;
        dev->dev.platform_data = platform_data;
-       of_dma_configure(&dev->dev);
+       of_dma_configure(&dev->dev, dev->dev.of_node);
 
        if (of_device_add(dev) != 0) {
                of_dma_deconfigure(&dev->dev);
@@ -299,7 +245,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
                dev_set_name(&dev->dev, "%s", bus_id);
        else
                of_device_make_bus_id(&dev->dev);
-       of_dma_configure(&dev->dev);
+       of_dma_configure(&dev->dev, dev->dev.of_node);
 
        /* Allow the HW Peripheral ID to be overridden */
        prop = of_get_property(node, "arm,primecell-periphid", NULL);
index caa1531337540dec37c71d6865da922702e9bf3d..a656d9e8334302c2ec4f013ad6c016034ace5f27 100644 (file)
@@ -357,7 +357,7 @@ static int parse_slot_config(int slot,
                }
                if (flags & HPEE_FUNCTION_INFO_CFG_FREE_FORM) {
                        /* I have no idea how to handle this */
-                       printk("function %d have free-form confgiuration, skipping ",
+                       printk("function %d have free-form configuration, skipping ",
                                num_func);
                        pos = p0 + function_len;
                        continue;
index 39b2dbe585aae651c930704eb4f1f53a68c66203..5f4a2e04c8d7cf237535d0cafb0274ba4df904e5 100644 (file)
@@ -16,13 +16,27 @@ static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)
        return bus;
 }
 
-static struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)
+struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus)
 {
        struct pci_bus *root_bus = find_pci_root_bus(bus);
 
        return to_pci_host_bridge(root_bus->bridge);
 }
 
+struct device *pci_get_host_bridge_device(struct pci_dev *dev)
+{
+       struct pci_bus *root_bus = find_pci_root_bus(dev->bus);
+       struct device *bridge = root_bus->bridge;
+
+       kobject_get(&bridge->kobj);
+       return bridge;
+}
+
+void  pci_put_host_bridge_device(struct device *dev)
+{
+       kobject_put(&dev->kobj);
+}
+
 void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
                                 void (*release_fn)(struct pci_host_bridge *),
                                 void *release_data)
@@ -34,7 +48,7 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
 void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
                             struct resource *res)
 {
-       struct pci_host_bridge *bridge = find_pci_host_bridge(bus);
+       struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
        struct resource_entry *window;
        resource_size_t offset = 0;
 
@@ -59,7 +73,7 @@ static bool region_contains(struct pci_bus_region *region1,
 void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
                             struct pci_bus_region *region)
 {
-       struct pci_host_bridge *bridge = find_pci_host_bridge(bus);
+       struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
        struct resource_entry *window;
        resource_size_t offset = 0;
 
index 7b892a9cc4fc6bcfb2e56c59476435f35f32ab95..1dfb567b3522fca7d34bd86e4ed859f4579f46b6 100644 (file)
@@ -106,4 +106,23 @@ config PCI_VERSATILE
        bool "ARM Versatile PB PCI controller"
        depends on ARCH_VERSATILE
 
+config PCIE_IPROC
+       tristate "Broadcom iProc PCIe controller"
+       depends on OF && ARM
+       default n
+       help
+         This enables the iProc PCIe core controller support for Broadcom's
+         iProc family of SoCs. An appropriate bus interface driver also needs
+         to be enabled
+
+config PCIE_IPROC_PLATFORM
+       tristate "Broadcom iProc PCIe platform bus driver"
+       depends on ARCH_BCM_IPROC || (ARM && COMPILE_TEST)
+       depends on OF
+       select PCIE_IPROC
+       default ARCH_BCM_IPROC
+       help
+         Say Y here if you want to use the Broadcom iProc PCIe controller
+         through the generic platform bus interface
+
 endmenu
index e61d91c92bf1f1c54eeeb3fd60b5a4c7e0d38a17..f733b4e27642ba34277ab92bca33201c38b88614 100644 (file)
@@ -13,3 +13,5 @@ obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
 obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
 obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
 obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
+obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o
+obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
index d202b37c369847afcf5bd49087bfbe20d13bba60..c139237e0e523cd9d9e36c9a9d7ce20b8a59f87f 100644 (file)
@@ -396,7 +396,7 @@ static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp)
 
        /* enable INTX interrupt */
        val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT |
-               IRQ_INTC_ASSERT | IRQ_INTD_ASSERT,
+               IRQ_INTC_ASSERT | IRQ_INTD_ASSERT;
        exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_PULSE);
 }
 
index 66d8ea41b972355ce377315bb7236e8b21872fac..f34892e0edb4f973e4dd3e9ab39b24cf0c2f0716 100644 (file)
@@ -496,11 +496,12 @@ int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
 
        /* Index 1 is the application reg. space address */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       ks_pcie->app = *res;
        ks_pcie->va_app_base = devm_ioremap_resource(pp->dev, res);
        if (IS_ERR(ks_pcie->va_app_base))
                return PTR_ERR(ks_pcie->va_app_base);
 
+       ks_pcie->app = *res;
+
        /* Create legacy IRQ domain */
        ks_pcie->legacy_irq_domain =
                        irq_domain_add_linear(ks_pcie->legacy_intc_np,
index 68c9e5e9b0a896edf0492e8588dddf873e22e38f..4a6e62f67579807476ae973006855d28cbfab0d6 100644 (file)
@@ -127,14 +127,11 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
        pcie->dev = &pdev->dev;
 
        dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
-       if (!dbi_base) {
-               dev_err(&pdev->dev, "missing *regs* space\n");
-               return -ENODEV;
-       }
-
        pcie->dbi = devm_ioremap_resource(&pdev->dev, dbi_base);
-       if (IS_ERR(pcie->dbi))
+       if (IS_ERR(pcie->dbi)) {
+               dev_err(&pdev->dev, "missing *regs* space\n");
                return PTR_ERR(pcie->dbi);
+       }
 
        pcie->scfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
                                                     "fsl,pcie-scfg");
index 1309cfbaa71960471acb7e63ba84ab0d40be3e08..1ab863551920214dd95ec45dc7f42db398195503 100644 (file)
@@ -129,6 +129,7 @@ struct mvebu_pcie_port {
        size_t memwin_size;
        phys_addr_t iowin_base;
        size_t iowin_size;
+       u32 saved_pcie_stat;
 };
 
 static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
@@ -899,6 +900,35 @@ static void mvebu_pcie_msi_enable(struct mvebu_pcie *pcie)
                pcie->msi->dev = &pcie->pdev->dev;
 }
 
+static int mvebu_pcie_suspend(struct device *dev)
+{
+       struct mvebu_pcie *pcie;
+       int i;
+
+       pcie = dev_get_drvdata(dev);
+       for (i = 0; i < pcie->nports; i++) {
+               struct mvebu_pcie_port *port = pcie->ports + i;
+               port->saved_pcie_stat = mvebu_readl(port, PCIE_STAT_OFF);
+       }
+
+       return 0;
+}
+
+static int mvebu_pcie_resume(struct device *dev)
+{
+       struct mvebu_pcie *pcie;
+       int i;
+
+       pcie = dev_get_drvdata(dev);
+       for (i = 0; i < pcie->nports; i++) {
+               struct mvebu_pcie_port *port = pcie->ports + i;
+               mvebu_writel(port, port->saved_pcie_stat, PCIE_STAT_OFF);
+               mvebu_pcie_setup_hw(port);
+       }
+
+       return 0;
+}
+
 static int mvebu_pcie_probe(struct platform_device *pdev)
 {
        struct mvebu_pcie *pcie;
@@ -1056,6 +1086,8 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
        mvebu_pcie_msi_enable(pcie);
        mvebu_pcie_enable(pcie);
 
+       platform_set_drvdata(pdev, pcie);
+
        return 0;
 }
 
@@ -1068,12 +1100,18 @@ static const struct of_device_id mvebu_pcie_of_match_table[] = {
 };
 MODULE_DEVICE_TABLE(of, mvebu_pcie_of_match_table);
 
+static struct dev_pm_ops mvebu_pcie_pm_ops = {
+       .suspend_noirq = mvebu_pcie_suspend,
+       .resume_noirq = mvebu_pcie_resume,
+};
+
 static struct platform_driver mvebu_pcie_driver = {
        .driver = {
                .name = "mvebu-pcie",
                .of_match_table = mvebu_pcie_of_match_table,
                /* driver unloading/unbinding currently not supported */
                .suppress_bind_attrs = true,
+               .pm = &mvebu_pcie_pm_ops,
        },
        .probe = mvebu_pcie_probe,
 };
index dd6b84e6206c4f40b213de597108af64abf9f3ea..367e28fa75643a1fe27218d640f090ac004877b9 100644 (file)
@@ -301,6 +301,9 @@ static int rcar_pci_probe(struct platform_device *pdev)
        if (!mem_res || !mem_res->start)
                return -ENODEV;
 
+       if (mem_res->start & 0xFFFF)
+               return -EINVAL;
+
        priv = devm_kzalloc(&pdev->dev,
                            sizeof(struct rcar_pci_priv), GFP_KERNEL);
        if (!priv)
index 464bf492ee2ae375e8fe92e0a5446dbdf0461f9d..0863d9cc25f8619e9abc42c4adccdc00cc14d03a 100644 (file)
@@ -138,19 +138,19 @@ static int versatile_pci_probe(struct platform_device *pdev)
        LIST_HEAD(pci_res);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENODEV;
        versatile_pci_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(versatile_pci_base))
+               return PTR_ERR(versatile_pci_base);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!res)
-               return -ENODEV;
        versatile_cfg_base[0] = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(versatile_cfg_base[0]))
+               return PTR_ERR(versatile_cfg_base[0]);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-       if (!res)
-               return -ENODEV;
        versatile_cfg_base[1] = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(versatile_cfg_base[1]))
+               return PTR_ERR(versatile_cfg_base[1]);
 
        ret = versatile_pci_parse_request_of_pci_ranges(&pdev->dev, &pci_res);
        if (ret)
@@ -214,6 +214,7 @@ static int versatile_pci_probe(struct platform_device *pdev)
 
        pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
        pci_assign_unassigned_bus_resources(bus);
+       pci_bus_add_devices(bus);
 
        return 0;
 }
index 1f4ea6f2d91094b1af4dee898d7fd0d63765f032..2e9f84fdd9ceb3d39611c617573f4895ab36423e 100644 (file)
@@ -342,7 +342,7 @@ static const struct irq_domain_ops msi_domain_ops = {
        .map = dw_pcie_msi_map,
 };
 
-int __init dw_pcie_host_init(struct pcie_port *pp)
+int dw_pcie_host_init(struct pcie_port *pp)
 {
        struct device_node *np = pp->dev->of_node;
        struct platform_device *pdev = to_platform_device(pp->dev);
diff --git a/drivers/pci/host/pcie-iproc-platform.c b/drivers/pci/host/pcie-iproc-platform.c
new file mode 100644 (file)
index 0000000..afad6c2
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+
+#include "pcie-iproc.h"
+
+static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
+{
+       struct iproc_pcie *pcie;
+       struct device_node *np = pdev->dev.of_node;
+       struct resource reg;
+       resource_size_t iobase = 0;
+       LIST_HEAD(res);
+       int ret;
+
+       pcie = devm_kzalloc(&pdev->dev, sizeof(struct iproc_pcie), GFP_KERNEL);
+       if (!pcie)
+               return -ENOMEM;
+
+       pcie->dev = &pdev->dev;
+       platform_set_drvdata(pdev, pcie);
+
+       ret = of_address_to_resource(np, 0, &reg);
+       if (ret < 0) {
+               dev_err(pcie->dev, "unable to obtain controller resources\n");
+               return ret;
+       }
+
+       pcie->base = devm_ioremap(pcie->dev, reg.start, resource_size(&reg));
+       if (!pcie->base) {
+               dev_err(pcie->dev, "unable to map controller registers\n");
+               return -ENOMEM;
+       }
+
+       /* PHY use is optional */
+       pcie->phy = devm_phy_get(&pdev->dev, "pcie-phy");
+       if (IS_ERR(pcie->phy)) {
+               if (PTR_ERR(pcie->phy) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+               pcie->phy = NULL;
+       }
+
+       ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &iobase);
+       if (ret) {
+               dev_err(pcie->dev,
+                       "unable to get PCI host bridge resources\n");
+               return ret;
+       }
+
+       pcie->resources = &res;
+
+       ret = iproc_pcie_setup(pcie);
+       if (ret) {
+               dev_err(pcie->dev, "PCIe controller setup failed\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int iproc_pcie_pltfm_remove(struct platform_device *pdev)
+{
+       struct iproc_pcie *pcie = platform_get_drvdata(pdev);
+
+       return iproc_pcie_remove(pcie);
+}
+
+static const struct of_device_id iproc_pcie_of_match_table[] = {
+       { .compatible = "brcm,iproc-pcie", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table);
+
+static struct platform_driver iproc_pcie_pltfm_driver = {
+       .driver = {
+               .name = "iproc-pcie",
+               .of_match_table = of_match_ptr(iproc_pcie_of_match_table),
+       },
+       .probe = iproc_pcie_pltfm_probe,
+       .remove = iproc_pcie_pltfm_remove,
+};
+module_platform_driver(iproc_pcie_pltfm_driver);
+
+MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom iPROC PCIe platform driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/host/pcie-iproc.c
new file mode 100644 (file)
index 0000000..329e1b5
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2014 Hauke Mehrtens <hauke@hauke-m.de>
+ * Copyright (C) 2015 Broadcom Corporatcommon ion
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/msi.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/mbus.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+
+#include "pcie-iproc.h"
+
+#define CLK_CONTROL_OFFSET           0x000
+#define EP_MODE_SURVIVE_PERST_SHIFT  1
+#define EP_MODE_SURVIVE_PERST        BIT(EP_MODE_SURVIVE_PERST_SHIFT)
+#define RC_PCIE_RST_OUTPUT_SHIFT     0
+#define RC_PCIE_RST_OUTPUT           BIT(RC_PCIE_RST_OUTPUT_SHIFT)
+
+#define CFG_IND_ADDR_OFFSET          0x120
+#define CFG_IND_ADDR_MASK            0x00001ffc
+
+#define CFG_IND_DATA_OFFSET          0x124
+
+#define CFG_ADDR_OFFSET              0x1f8
+#define CFG_ADDR_BUS_NUM_SHIFT       20
+#define CFG_ADDR_BUS_NUM_MASK        0x0ff00000
+#define CFG_ADDR_DEV_NUM_SHIFT       15
+#define CFG_ADDR_DEV_NUM_MASK        0x000f8000
+#define CFG_ADDR_FUNC_NUM_SHIFT      12
+#define CFG_ADDR_FUNC_NUM_MASK       0x00007000
+#define CFG_ADDR_REG_NUM_SHIFT       2
+#define CFG_ADDR_REG_NUM_MASK        0x00000ffc
+#define CFG_ADDR_CFG_TYPE_SHIFT      0
+#define CFG_ADDR_CFG_TYPE_MASK       0x00000003
+
+#define CFG_DATA_OFFSET              0x1fc
+
+#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)
+{
+       return sys->private_data;
+}
+
+/**
+ * Note access to the configuration registers are protected at the higher layer
+ * by 'pci_lock' in drivers/pci/access.c
+ */
+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);
+       unsigned slot = PCI_SLOT(devfn);
+       unsigned fn = PCI_FUNC(devfn);
+       unsigned busno = bus->number;
+       u32 val;
+
+       /* root complex access */
+       if (busno == 0) {
+               if (slot >= 1)
+                       return NULL;
+               writel(where & CFG_IND_ADDR_MASK,
+                      pcie->base + CFG_IND_ADDR_OFFSET);
+               return (pcie->base + CFG_IND_DATA_OFFSET);
+       }
+
+       if (fn > 1)
+               return NULL;
+
+       /* EP device access */
+       val = (busno << CFG_ADDR_BUS_NUM_SHIFT) |
+               (slot << CFG_ADDR_DEV_NUM_SHIFT) |
+               (fn << CFG_ADDR_FUNC_NUM_SHIFT) |
+               (where & CFG_ADDR_REG_NUM_MASK) |
+               (1 & CFG_ADDR_CFG_TYPE_MASK);
+       writel(val, pcie->base + CFG_ADDR_OFFSET);
+
+       return (pcie->base + CFG_DATA_OFFSET);
+}
+
+static struct pci_ops iproc_pcie_ops = {
+       .map_bus = iproc_pcie_map_cfg_bus,
+       .read = pci_generic_config_read32,
+       .write = pci_generic_config_write32,
+};
+
+static void iproc_pcie_reset(struct iproc_pcie *pcie)
+{
+       u32 val;
+
+       /*
+        * Configure the PCIe controller as root complex and send a downstream
+        * reset
+        */
+       val = EP_MODE_SURVIVE_PERST | RC_PCIE_RST_OUTPUT;
+       writel(val, pcie->base + CLK_CONTROL_OFFSET);
+       udelay(250);
+       val &= ~EP_MODE_SURVIVE_PERST;
+       writel(val, pcie->base + CLK_CONTROL_OFFSET);
+       msleep(250);
+}
+
+static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
+{
+       u8 hdr_type;
+       u32 link_ctrl;
+       u16 pos, link_status;
+       int link_is_active = 0;
+
+       /* make sure we are not in EP mode */
+       pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type);
+       if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) {
+               dev_err(pcie->dev, "in EP mode, hdr=%#02x\n", hdr_type);
+               return -EFAULT;
+       }
+
+       /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */
+       pci_bus_write_config_word(bus, 0, PCI_CLASS_DEVICE,
+                                 PCI_CLASS_BRIDGE_PCI);
+
+       /* check link status to see if link is active */
+       pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP);
+       pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status);
+       if (link_status & PCI_EXP_LNKSTA_NLW)
+               link_is_active = 1;
+
+       if (!link_is_active) {
+               /* try GEN 1 link speed */
+#define PCI_LINK_STATUS_CTRL_2_OFFSET 0x0dc
+#define PCI_TARGET_LINK_SPEED_MASK    0xf
+#define PCI_TARGET_LINK_SPEED_GEN2    0x2
+#define PCI_TARGET_LINK_SPEED_GEN1    0x1
+               pci_bus_read_config_dword(bus, 0,
+                                         PCI_LINK_STATUS_CTRL_2_OFFSET,
+                                         &link_ctrl);
+               if ((link_ctrl & PCI_TARGET_LINK_SPEED_MASK) ==
+                   PCI_TARGET_LINK_SPEED_GEN2) {
+                       link_ctrl &= ~PCI_TARGET_LINK_SPEED_MASK;
+                       link_ctrl |= PCI_TARGET_LINK_SPEED_GEN1;
+                       pci_bus_write_config_dword(bus, 0,
+                                          PCI_LINK_STATUS_CTRL_2_OFFSET,
+                                          link_ctrl);
+                       msleep(100);
+
+                       pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP);
+                       pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA,
+                                                &link_status);
+                       if (link_status & PCI_EXP_LNKSTA_NLW)
+                               link_is_active = 1;
+               }
+       }
+
+       dev_info(pcie->dev, "link: %s\n", link_is_active ? "UP" : "DOWN");
+
+       return link_is_active ? 0 : -ENODEV;
+}
+
+static void iproc_pcie_enable(struct iproc_pcie *pcie)
+{
+       writel(SYS_RC_INTX_MASK, pcie->base + SYS_RC_INTX_EN);
+}
+
+int iproc_pcie_setup(struct iproc_pcie *pcie)
+{
+       int ret;
+       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;
+               }
+
+       }
+
+       iproc_pcie_reset(pcie);
+
+       pcie->sysdata.private_data = pcie;
+
+       bus = pci_create_root_bus(pcie->dev, 0, &iproc_pcie_ops,
+                                 &pcie->sysdata, pcie->resources);
+       if (!bus) {
+               dev_err(pcie->dev, "unable to create PCI root bus\n");
+               ret = -ENOMEM;
+               goto err_power_off_phy;
+       }
+       pcie->root_bus = bus;
+
+       ret = iproc_pcie_check_link(pcie, bus);
+       if (ret) {
+               dev_err(pcie->dev, "no PCIe EP device detected\n");
+               goto err_rm_root_bus;
+       }
+
+       iproc_pcie_enable(pcie);
+
+       pci_scan_child_bus(bus);
+       pci_assign_unassigned_bus_resources(bus);
+       pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+       pci_bus_add_devices(bus);
+
+       return 0;
+
+err_rm_root_bus:
+       pci_stop_root_bus(bus);
+       pci_remove_root_bus(bus);
+
+err_power_off_phy:
+       if (pcie->phy)
+               phy_power_off(pcie->phy);
+err_exit_phy:
+       if (pcie->phy)
+               phy_exit(pcie->phy);
+
+       return ret;
+}
+EXPORT_SYMBOL(iproc_pcie_setup);
+
+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);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(iproc_pcie_remove);
+
+MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom iPROC PCIe common driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/host/pcie-iproc.h b/drivers/pci/host/pcie-iproc.h
new file mode 100644 (file)
index 0000000..e28075e
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014-2015 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _PCIE_IPROC_H
+#define _PCIE_IPROC_H
+
+#define IPROC_PCIE_MAX_NUM_IRQS 6
+
+/**
+ * iProc PCIe device
+ * @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
+ * @root_bus: pointer to root bus
+ * @phy: optional PHY device that controls the Serdes
+ * @irqs: interrupt IDs
+ */
+struct iproc_pcie {
+       struct device *dev;
+       void __iomem *base;
+       struct list_head *resources;
+       struct pci_sys_data sysdata;
+       struct pci_bus *root_bus;
+       struct phy *phy;
+       int irqs[IPROC_PCIE_MAX_NUM_IRQS];
+};
+
+int iproc_pcie_setup(struct iproc_pcie *pcie);
+int iproc_pcie_remove(struct iproc_pcie *pcie);
+
+#endif /* _PCIE_IPROC_H */
index c57bd0ac39a0099684552053259887e507ad451c..c086210f2ffd1d0962ff253e98d06946e4236e89 100644 (file)
@@ -64,8 +64,8 @@
 #define  LAR_ENABLE            (1 << 1)
 
 /* PCIe address reg & mask */
-#define PCIEPARL(x)            (0x03400 + ((x) * 0x20))
-#define PCIEPARH(x)            (0x03404 + ((x) * 0x20))
+#define PCIEPALR(x)            (0x03400 + ((x) * 0x20))
+#define PCIEPAUR(x)            (0x03404 + ((x) * 0x20))
 #define PCIEPAMR(x)            (0x03408 + ((x) * 0x20))
 #define PCIEPTCTLR(x)          (0x0340c + ((x) * 0x20))
 #define  PAR_ENABLE            (1 << 31)
@@ -341,8 +341,9 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
        else
                res_start = res->start;
 
-       rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPARH(win));
-       rcar_pci_write_reg(pcie, lower_32_bits(res_start), PCIEPARL(win));
+       rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPAUR(win));
+       rcar_pci_write_reg(pcie, lower_32_bits(res_start) & ~0x7F,
+                          PCIEPALR(win));
 
        /* First resource is for IO */
        mask = PAR_ENABLE;
@@ -501,7 +502,7 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
 
        /* Enable MSI */
        if (IS_ENABLED(CONFIG_PCI_MSI))
-               rcar_pci_write_reg(pcie, 0x101f0000, PCIEMSITXR);
+               rcar_pci_write_reg(pcie, 0x801f0000, PCIEMSITXR);
 
        /* Finish initialization - establish a PCI Express link */
        rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
index 866465fd3dbf7e617b3085e9a175bceea82d1ad1..020d788907191fd73ac1b7058b66b9a76f6b7351 100644 (file)
@@ -269,7 +269,7 @@ static struct pcie_host_ops spear13xx_pcie_host_ops = {
        .host_init = spear13xx_pcie_host_init,
 };
 
-static int __init spear13xx_add_pcie_port(struct pcie_port *pp,
+static int spear13xx_add_pcie_port(struct pcie_port *pp,
                                         struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -299,7 +299,7 @@ static int __init spear13xx_add_pcie_port(struct pcie_port *pp,
        return 0;
 }
 
-static int __init spear13xx_pcie_probe(struct platform_device *pdev)
+static int spear13xx_pcie_probe(struct platform_device *pdev)
 {
        struct spear13xx_pcie *spear13xx_pcie;
        struct pcie_port *pp;
@@ -370,7 +370,7 @@ static const struct of_device_id spear13xx_pcie_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, spear13xx_pcie_of_match);
 
-static struct platform_driver spear13xx_pcie_driver __initdata = {
+static struct platform_driver spear13xx_pcie_driver = {
        .probe          = spear13xx_pcie_probe,
        .driver = {
                .name   = "spear-pcie",
index 7d48ecae6695581e7ded9caa59adf782d5bf0d3f..788db48dbbad9ddf6ff697cd88c4fd832de29cde 100644 (file)
@@ -286,11 +286,12 @@ int cpci_configure_slot(struct slot *slot)
        }
        parent = slot->dev->bus;
 
-       list_for_each_entry(dev, &parent->devices, bus_list)
+       list_for_each_entry(dev, &parent->devices, bus_list) {
                if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
                        continue;
                if (pci_is_bridge(dev))
                        pci_hp_add_bridge(dev);
+       }
 
 
        pci_assign_unassigned_bridge_resources(parent->self);
index 96c5c729cdbcb9069ece7a12c03157902538caef..15302475f5b71dd1144e9fe598ead5555b4fe075 100644 (file)
@@ -738,7 +738,7 @@ static void ibm_unconfigure_device(struct pci_func *func)
  */
 static u8 bus_structure_fixup(u8 busno)
 {
-       struct pci_bus *bus;
+       struct pci_bus *bus, *b;
        struct pci_dev *dev;
        u16 l;
 
@@ -765,7 +765,11 @@ static u8 bus_structure_fixup(u8 busno)
                                        (l != 0x0000) && (l != 0xffff)) {
                        debug("%s - Inside bus_structure_fixup()\n",
                                                        __func__);
-                       pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL);
+                       b = pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL);
+                       if (!b)
+                               continue;
+
+                       pci_bus_add_devices(b);
                        break;
                }
        }
index 4890639873256812b721d83f304dff634ef58da1..6f6f175f51f78003524e96c046fb58b7298407ad 100644 (file)
 #include <linux/pm_qos.h>
 #include "pci.h"
 
+/*
+ * The UUID is defined in the PCI Firmware Specification available here:
+ * https://www.pcisig.com/members/downloads/pcifw_r3_1_13Dec10.pdf
+ */
+const u8 pci_acpi_dsm_uuid[] = {
+       0xd0, 0x37, 0xc9, 0xe5, 0x53, 0x35, 0x7a, 0x4d,
+       0x91, 0x17, 0xea, 0x4d, 0x19, 0xc3, 0x43, 0x4d
+};
+
 phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
 {
        acpi_status status = AE_NOT_EXIST;
@@ -248,6 +257,9 @@ int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp)
        acpi_handle handle, phandle;
        struct pci_bus *pbus;
 
+       if (acpi_pci_disabled)
+               return -ENODEV;
+
        handle = NULL;
        for (pbus = dev->bus; pbus; pbus = pbus->parent) {
                handle = acpi_pci_get_bridge_handle(pbus);
@@ -528,11 +540,32 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = {
 
 void acpi_pci_add_bus(struct pci_bus *bus)
 {
+       union acpi_object *obj;
+       struct pci_host_bridge *bridge;
+
        if (acpi_pci_disabled || !bus->bridge)
                return;
 
        acpi_pci_slot_enumerate(bus);
        acpiphp_enumerate_slots(bus);
+
+       /*
+        * For a host bridge, check its _DSM for function 8 and if
+        * that is available, mark it in pci_host_bridge.
+        */
+       if (!pci_is_root_bus(bus))
+               return;
+
+       obj = acpi_evaluate_dsm(ACPI_HANDLE(bus->bridge), pci_acpi_dsm_uuid, 3,
+                               RESET_DELAY_DSM, NULL);
+       if (!obj)
+               return;
+
+       if (obj->type == ACPI_TYPE_INTEGER && obj->integer.value == 1) {
+               bridge = pci_find_host_bridge(bus);
+               bridge->ignore_reset_delay = 1;
+       }
+       ACPI_FREE(obj);
 }
 
 void acpi_pci_remove_bus(struct pci_bus *bus)
@@ -558,6 +591,57 @@ static struct acpi_device *acpi_pci_find_companion(struct device *dev)
                                      check_children);
 }
 
+/**
+ * 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
+ *
+ * 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.
+ *
+ * Function 8, "Reset Delay," applies to the entire hierarchy below a PCI
+ * host bridge.  If it returns one, the OS may assume that all devices in
+ * the hierarchy have already completed power-on reset delays.
+ *
+ * Function 9, "Device Readiness Durations," applies only to the object
+ * where it is located.  It returns delay durations required after various
+ * events if the device requires less time than the spec requires.  Delays
+ * from this function take precedence over the Reset Delay function.
+ *
+ * These _DSM functions are defined by the draft ECN of January 28, 2014,
+ * titled "ACPI additions for FW latency optimizations."
+ */
+static void pci_acpi_optimize_delay(struct pci_dev *pdev,
+                                   acpi_handle handle)
+{
+       struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus);
+       int value;
+       union acpi_object *obj, *elements;
+
+       if (bridge->ignore_reset_delay)
+               pdev->d3cold_delay = 0;
+
+       obj = acpi_evaluate_dsm(handle, pci_acpi_dsm_uuid, 3,
+                               FUNCTION_DELAY_DSM, NULL);
+       if (!obj)
+               return;
+
+       if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 5) {
+               elements = obj->package.elements;
+               if (elements[0].type == ACPI_TYPE_INTEGER) {
+                       value = (int)elements[0].integer.value / 1000;
+                       if (value < PCI_PM_D3COLD_WAIT)
+                               pdev->d3cold_delay = value;
+               }
+               if (elements[3].type == ACPI_TYPE_INTEGER) {
+                       value = (int)elements[3].integer.value / 1000;
+                       if (value < PCI_PM_D3_WAIT)
+                               pdev->d3_delay = value;
+               }
+       }
+       ACPI_FREE(obj);
+}
+
 static void pci_acpi_setup(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
@@ -566,6 +650,8 @@ static void pci_acpi_setup(struct device *dev)
        if (!adev)
                return;
 
+       pci_acpi_optimize_delay(pci_dev, adev->handle);
+
        pci_acpi_add_pm_notifier(adev, pci_dev);
        if (!adev->wakeup.flags.valid)
                return;
index 2ab1b47c7651c2d86db3a56ea9bf842e44569f07..024b5c179348e26f062a2becab6896c260e26a06 100644 (file)
@@ -31,8 +31,6 @@
 #include <linux/pci-acpi.h>
 #include "pci.h"
 
-#define        DEVICE_LABEL_DSM        0x07
-
 #ifdef CONFIG_DMI
 enum smbios_attr_enum {
        SMBIOS_ATTR_NONE = 0,
@@ -148,11 +146,6 @@ static inline void pci_remove_smbiosname_file(struct pci_dev *pdev)
 #endif
 
 #ifdef CONFIG_ACPI
-static const char device_label_dsm_uuid[] = {
-       0xD0, 0x37, 0xC9, 0xE5, 0x53, 0x35, 0x7A, 0x4D,
-       0x91, 0x17, 0xEA, 0x4D, 0x19, 0xC3, 0x43, 0x4D
-};
-
 enum acpi_attr_enum {
        ACPI_ATTR_LABEL_SHOW,
        ACPI_ATTR_INDEX_SHOW,
@@ -179,7 +172,7 @@ static int dsm_get_label(struct device *dev, char *buf,
        if (!handle)
                return -1;
 
-       obj = acpi_evaluate_dsm(handle, device_label_dsm_uuid, 0x2,
+       obj = acpi_evaluate_dsm(handle, pci_acpi_dsm_uuid, 0x2,
                                DEVICE_LABEL_DSM, NULL);
        if (!obj)
                return -1;
@@ -219,7 +212,7 @@ static bool device_has_dsm(struct device *dev)
        if (!handle)
                return false;
 
-       return !!acpi_check_dsm(handle, device_label_dsm_uuid, 0x2,
+       return !!acpi_check_dsm(handle, pci_acpi_dsm_uuid, 0x2,
                                1 << DEVICE_LABEL_DSM);
 }
 
index 81f06e8dcc0449688e05b65504413320628b1579..acc4b6ef78c4380273b1af144838582dde57f80a 100644 (file)
@@ -126,15 +126,16 @@ EXPORT_SYMBOL_GPL(pci_bus_max_busnr);
 #ifdef CONFIG_HAS_IOMEM
 void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar)
 {
+       struct resource *res = &pdev->resource[bar];
+
        /*
         * Make sure the BAR is actually a memory resource, not an IO resource
         */
-       if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
-               WARN_ON(1);
+       if (res->flags & IORESOURCE_UNSET || !(res->flags & IORESOURCE_MEM)) {
+               dev_warn(&pdev->dev, "can't ioremap BAR %d: %pR\n", bar, res);
                return NULL;
        }
-       return ioremap_nocache(pci_resource_start(pdev, bar),
-                                    pci_resource_len(pdev, bar));
+       return ioremap_nocache(res->start, resource_size(res));
 }
 EXPORT_SYMBOL_GPL(pci_ioremap_bar);
 #endif
@@ -145,19 +146,22 @@ static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
                                   u8 pos, int cap, int *ttl)
 {
        u8 id;
+       u16 ent;
+
+       pci_bus_read_config_byte(bus, devfn, pos, &pos);
 
        while ((*ttl)--) {
-               pci_bus_read_config_byte(bus, devfn, pos, &pos);
                if (pos < 0x40)
                        break;
                pos &= ~3;
-               pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID,
-                                        &id);
+               pci_bus_read_config_word(bus, devfn, pos, &ent);
+
+               id = ent & 0xff;
                if (id == 0xff)
                        break;
                if (id == cap)
                        return pos;
-               pos += PCI_CAP_LIST_NEXT;
+               pos = (ent >> 8);
        }
        return 0;
 }
@@ -2492,6 +2496,7 @@ u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp)
        *pinp = pin;
        return PCI_SLOT(dev->devfn);
 }
+EXPORT_SYMBOL_GPL(pci_common_swizzle);
 
 /**
  *     pci_release_region - Release a PCI bar
index 4091f82239cdb86141bb3dfd34e583bff8b027db..d72f849174a4bd32740bcaeb7f2112186e501435 100644 (file)
@@ -321,4 +321,6 @@ static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)
 }
 #endif
 
+struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus);
+
 #endif /* DRIVERS_PCI_H */
index c6849d9e86ce6c33bc11ec8ea621e3e042878817..167fe411ce2e30460ba6d0c8a04383976532b4e9 100644 (file)
@@ -132,16 +132,8 @@ static const char *aer_agent_string[] = {
 static void __print_tlp_header(struct pci_dev *dev,
                               struct aer_header_log_regs *t)
 {
-       unsigned char *tlp = (unsigned char *)&t;
-
-       dev_err(&dev->dev, "  TLP Header:"
-               " %02x%02x%02x%02x %02x%02x%02x%02x"
-               " %02x%02x%02x%02x %02x%02x%02x%02x\n",
-               *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
-               *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
-               *(tlp + 11), *(tlp + 10), *(tlp + 9),
-               *(tlp + 8), *(tlp + 15), *(tlp + 14),
-               *(tlp + 13), *(tlp + 12));
+       dev_err(&dev->dev, "  TLP Header: %08x %08x %08x %08x\n",
+               t->dw0, t->dw1, t->dw2, t->dw3);
 }
 
 static void __aer_print_error(struct pci_dev *dev,
index 820740a22e94535a95bc4ed4e242435d6225709e..7d4fcdc512aa0ab5d4768b94272eb8359a2599cb 100644 (file)
@@ -782,24 +782,6 @@ void pci_disable_link_state(struct pci_dev *pdev, int state)
 }
 EXPORT_SYMBOL(pci_disable_link_state);
 
-void pcie_clear_aspm(struct pci_bus *bus)
-{
-       struct pci_dev *child;
-
-       if (aspm_force)
-               return;
-
-       /*
-        * Clear any ASPM setup that the firmware has carried out on this bus
-        */
-       list_for_each_entry(child, &bus->devices, bus_list) {
-               __pci_disable_link_state(child, PCIE_LINK_STATE_L0S |
-                                        PCIE_LINK_STATE_L1 |
-                                        PCIE_LINK_STATE_CLKPM,
-                                        false, true);
-       }
-}
-
 static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
 {
        int i;
index 8d2f400e96cb848260fb3882a385dae0259c7ee4..6675a7a1b9fc6a113379b9e5ac025b2a3df66ad3 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/of_pci.h>
 #include <linux/pci_hotplug.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -1520,6 +1521,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
        dev->dev.dma_mask = &dev->dma_mask;
        dev->dev.dma_parms = &dev->dma_parms;
        dev->dev.coherent_dma_mask = 0xffffffffull;
+       of_pci_dma_configure(dev);
 
        pci_set_dma_max_seg_size(dev, 65536);
        pci_set_dma_seg_boundary(dev, 0xffffffff);
@@ -1993,6 +1995,7 @@ err_out:
        kfree(b);
        return NULL;
 }
+EXPORT_SYMBOL_GPL(pci_create_root_bus);
 
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
 {
@@ -2087,7 +2090,6 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
        if (!found)
                pci_bus_update_busn_res_end(b, max);
 
-       pci_bus_add_devices(b);
        return b;
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
@@ -2123,7 +2125,6 @@ struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
        b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
        if (b) {
                pci_scan_child_bus(b);
-               pci_bus_add_devices(b);
        } else {
                pci_free_resource_list(&resources);
        }
index 85f247e28a806a512861864e05e5279688094003..c6dc1dfd25d55ea9ac536634143eafcf196ce2c2 100644 (file)
@@ -3182,7 +3182,7 @@ static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev)
                        || nhi->subsystem_vendor != 0x2222
                        || nhi->subsystem_device != 0x1111)
                goto out;
-       dev_info(&dev->dev, "quirk: wating for thunderbolt to reestablish pci tunnels...\n");
+       dev_info(&dev->dev, "quirk: waiting for thunderbolt to reestablish PCI tunnels...\n");
        device_pm_wait_for_dev(&dev->dev, &nhi->dev);
 out:
        pci_dev_put(nhi);
@@ -3822,6 +3822,38 @@ static const struct pci_dev_acs_enabled {
        { PCI_VENDOR_ID_INTEL, 0x154F, pci_quirk_mf_endpoint_acs },
        { PCI_VENDOR_ID_INTEL, 0x1551, pci_quirk_mf_endpoint_acs },
        { PCI_VENDOR_ID_INTEL, 0x1558, pci_quirk_mf_endpoint_acs },
+       /* 82580 */
+       { PCI_VENDOR_ID_INTEL, 0x1509, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x150E, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x150F, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x1510, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x1511, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x1516, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x1527, pci_quirk_mf_endpoint_acs },
+       /* 82576 */
+       { PCI_VENDOR_ID_INTEL, 0x10C9, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x10E6, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x10E7, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x10E8, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x150A, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x150D, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x1518, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x1526, pci_quirk_mf_endpoint_acs },
+       /* 82575 */
+       { PCI_VENDOR_ID_INTEL, 0x10A7, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x10A9, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x10D6, pci_quirk_mf_endpoint_acs },
+       /* I350 */
+       { PCI_VENDOR_ID_INTEL, 0x1521, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x1522, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x1523, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x1524, pci_quirk_mf_endpoint_acs },
+       /* 82571 (Quads omitted due to non-ACS switch) */
+       { PCI_VENDOR_ID_INTEL, 0x105E, pci_quirk_mf_endpoint_acs },
+       { 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 },
+       /* 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 */
        { 0x10df, 0x720, pci_quirk_mf_endpoint_acs }, /* Emulex Skyhawk-R */
index 8bd76c9ba21cf4e5c5a4b58cb40ccd990cfacc5e..8a280e9c2ad1e00b1cca15b4592d79c7460e1363 100644 (file)
@@ -139,6 +139,7 @@ void pci_stop_root_bus(struct pci_bus *bus)
        /* stop the host bridge */
        device_release_driver(&host_bridge->dev);
 }
+EXPORT_SYMBOL_GPL(pci_stop_root_bus);
 
 void pci_remove_root_bus(struct pci_bus *bus)
 {
@@ -158,3 +159,4 @@ void pci_remove_root_bus(struct pci_bus *bus)
        /* remove the host bridge */
        device_unregister(&host_bridge->dev);
 }
+EXPORT_SYMBOL_GPL(pci_remove_root_bus);
index e3e17f3c0f0f2929da94d7411c0740a391dc56c6..8169597e47cb3f0527f4a5adff9a54764bbbc929 100644 (file)
@@ -1750,3 +1750,4 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
        __pci_bus_assign_resources(bus, &add_list, NULL);
        BUG_ON(!list_empty(&add_list));
 }
+EXPORT_SYMBOL_GPL(pci_assign_unassigned_bus_resources);
index 4e2d595d50ca19c8a63ff537f5e89b0bab6c32d6..95c225be49d17c82483ce12aef9aca2cddcdb7d1 100644 (file)
@@ -65,3 +65,4 @@ void pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
        for_each_pci_dev(dev)
                pdev_fixup_irq(dev, swizzle, map_irq);
 }
+EXPORT_SYMBOL_GPL(pci_fixup_irqs);
index b7c3a5ea1fca0a266891d1954321716dc5073e8c..232f9254c11acf5b45d9b20f9fc4169dfad79084 100644 (file)
@@ -120,6 +120,7 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
        if (!root) {
                dev_info(&dev->dev, "can't claim BAR %d %pR: no compatible bridge window\n",
                         resource, res);
+               res->flags |= IORESOURCE_UNSET;
                return -EINVAL;
        }
 
@@ -127,6 +128,7 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
        if (conflict) {
                dev_info(&dev->dev, "can't claim BAR %d %pR: address conflict with %s %pR\n",
                         resource, res, conflict->name, conflict);
+               res->flags |= IORESOURCE_UNSET;
                return -EBUSY;
        }
 
index 2962de205ba7247bd06eeb5d89f752b30d39e9dc..a53bd5b52df97ff48fa921a5009f2fa6937aa377 100644 (file)
@@ -35,6 +35,13 @@ config ARMADA375_USBCLUSTER_PHY
        depends on OF
        select GENERIC_PHY
 
+config PHY_DM816X_USB
+       tristate "TI dm816x USB PHY driver"
+       depends on ARCH_OMAP2PLUS
+       select GENERIC_PHY
+       help
+         Enable this for dm816x USB to work.
+
 config PHY_EXYNOS_MIPI_VIDEO
        tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
        depends on HAS_IOMEM
@@ -174,6 +181,17 @@ config PHY_SUN4I_USB
          This driver controls the entire USB PHY block, both the USB OTG
          parts, as well as the 2 regular USB 2 host PHYs.
 
+config PHY_SUN9I_USB
+       tristate "Allwinner sun9i SoC USB PHY driver"
+       depends on ARCH_SUNXI && HAS_IOMEM && OF
+       depends on RESET_CONTROLLER
+       select GENERIC_PHY
+       help
+         Enable this to support the transceiver that is part of Allwinner
+         sun9i SoCs.
+
+         This driver controls each individual USB 2 host PHY.
+
 config PHY_SAMSUNG_USB2
        tristate "Samsung USB 2.0 PHY driver"
        depends on HAS_IOMEM
index f080e1bb2a74dc528757d01fbbaf917a8a962445..f1262517878008a587a2a8b2c52ef97b1c8103b7 100644 (file)
@@ -5,6 +5,7 @@
 obj-$(CONFIG_GENERIC_PHY)              += phy-core.o
 obj-$(CONFIG_PHY_BERLIN_USB)           += phy-berlin-usb.o
 obj-$(CONFIG_PHY_BERLIN_SATA)          += phy-berlin-sata.o
+obj-$(CONFIG_PHY_DM816X_USB)           += phy-dm816x-usb.o
 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
@@ -20,6 +21,7 @@ obj-$(CONFIG_TWL4030_USB)             += phy-twl4030-usb.o
 obj-$(CONFIG_PHY_EXYNOS5250_SATA)      += phy-exynos5250-sata.o
 obj-$(CONFIG_PHY_HIX5HD2_SATA)         += phy-hix5hd2-sata.o
 obj-$(CONFIG_PHY_SUN4I_USB)            += phy-sun4i-usb.o
+obj-$(CONFIG_PHY_SUN9I_USB)            += phy-sun9i-usb.o
 obj-$(CONFIG_PHY_SAMSUNG_USB2)         += phy-exynos-usb2.o
 phy-exynos-usb2-y                      += phy-samsung-usb2.o
 phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2)  += phy-exynos4210-usb2.o
index 099eee8851e55e3cc4991eca53cdbd541eafe954..6f3e06d687de99260b0300e10d0864387d740177 100644 (file)
@@ -218,7 +218,7 @@ static int phy_berlin_sata_probe(struct platform_device *pdev)
        if (priv->nphys == 0)
                return -ENODEV;
 
-       priv->phys = devm_kzalloc(dev, priv->nphys * sizeof(*priv->phys),
+       priv->phys = devm_kcalloc(dev, priv->nphys, sizeof(*priv->phys),
                                  GFP_KERNEL);
        if (!priv->phys)
                return -ENOMEM;
index c8a8d53a6eceb0b8ea0bfd2a8419b4c47e86d4e9..c6fc95b530835569b040f193f6cf051f7198f7b9 100644 (file)
 #define MODE_TEST_EN           BIT(11)
 #define ANA_TEST_DC_CTRL(x)    ((x) << 12)
 
-#define to_phy_berlin_usb_priv(p)      \
-       container_of((p), struct phy_berlin_usb_priv, phy)
-
 static const u32 phy_berlin_pll_dividers[] = {
        /* Berlin 2 */
        CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
@@ -115,14 +112,13 @@ static const u32 phy_berlin_pll_dividers[] = {
 
 struct phy_berlin_usb_priv {
        void __iomem            *base;
-       struct phy              *phy;
        struct reset_control    *rst_ctrl;
        u32                     pll_divider;
 };
 
 static int phy_berlin_usb_power_on(struct phy *phy)
 {
-       struct phy_berlin_usb_priv *priv = dev_get_drvdata(phy->dev.parent);
+       struct phy_berlin_usb_priv *priv = phy_get_drvdata(phy);
 
        reset_control_reset(priv->rst_ctrl);
 
@@ -175,6 +171,7 @@ static int phy_berlin_usb_probe(struct platform_device *pdev)
                of_match_device(phy_berlin_sata_of_match, &pdev->dev);
        struct phy_berlin_usb_priv *priv;
        struct resource *res;
+       struct phy *phy;
        struct phy_provider *phy_provider;
 
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -192,20 +189,18 @@ static int phy_berlin_usb_probe(struct platform_device *pdev)
 
        priv->pll_divider = *((u32 *)match->data);
 
-       priv->phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops);
-       if (IS_ERR(priv->phy)) {
+       phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops);
+       if (IS_ERR(phy)) {
                dev_err(&pdev->dev, "failed to create PHY\n");
-               return PTR_ERR(priv->phy);
+               return PTR_ERR(phy);
        }
 
        platform_set_drvdata(pdev, priv);
+       phy_set_drvdata(phy, priv);
 
        phy_provider =
                devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
-       return 0;
+       return PTR_ERR_OR_ZERO(phy_provider);
 }
 
 static struct platform_driver phy_berlin_usb_driver = {
diff --git a/drivers/phy/phy-dm816x-usb.c b/drivers/phy/phy-dm816x-usb.c
new file mode 100644 (file)
index 0000000..7b42555
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/usb/phy_companion.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/phy/phy.h>
+#include <linux/of_platform.h>
+
+#include <linux/mfd/syscon.h>
+
+/*
+ * TRM has two sets of USB_CTRL registers.. The correct register bits
+ * are in TRM section 24.9.8.2 USB_CTRL Register. The TRM documents the
+ * phy as being SR70LX Synopsys USB 2.0 OTG nanoPHY. It also seems at
+ * least dm816x rev c ignores writes to USB_CTRL register, but the TI
+ * kernel is writing to those so it's possible that later revisions
+ * have worknig USB_CTRL register.
+ *
+ * Also note that At least USB_CTRL register seems to be dm816x specific
+ * according to the TRM. It's possible that USBPHY_CTRL is more generic,
+ * but that would have to be checked against the SR70LX documentation
+ * which does not seem to be publicly available.
+ *
+ * Finally, the phy on dm814x and am335x is different from dm816x.
+ */
+#define DM816X_USB_CTRL_PHYCLKSRC      BIT(8)  /* 1 = PLL ref clock */
+#define DM816X_USB_CTRL_PHYSLEEP1      BIT(1)  /* Enable the first phy */
+#define DM816X_USB_CTRL_PHYSLEEP0      BIT(0)  /* Enable the second phy */
+
+#define DM816X_USBPHY_CTRL_TXRISETUNE  1
+#define DM816X_USBPHY_CTRL_TXVREFTUNE  0xc
+#define DM816X_USBPHY_CTRL_TXPREEMTUNE 0x2
+
+struct dm816x_usb_phy {
+       struct regmap *syscon;
+       struct device *dev;
+       unsigned int instance;
+       struct clk *refclk;
+       struct usb_phy phy;
+       unsigned int usb_ctrl;          /* Shared between phy0 and phy1 */
+       unsigned int usbphy_ctrl;
+};
+
+static int dm816x_usb_phy_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+       otg->host = host;
+       if (!host)
+               otg->state = OTG_STATE_UNDEFINED;
+
+       return 0;
+}
+
+static int dm816x_usb_phy_set_peripheral(struct usb_otg *otg,
+                                        struct usb_gadget *gadget)
+{
+       otg->gadget = gadget;
+       if (!gadget)
+               otg->state = OTG_STATE_UNDEFINED;
+
+       return 0;
+}
+
+static int dm816x_usb_phy_init(struct phy *x)
+{
+       struct dm816x_usb_phy *phy = phy_get_drvdata(x);
+       unsigned int val;
+       int error;
+
+       if (clk_get_rate(phy->refclk) != 24000000)
+               dev_warn(phy->dev, "nonstandard phy refclk\n");
+
+       /* Set PLL ref clock and put phys to sleep */
+       error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
+                                  DM816X_USB_CTRL_PHYCLKSRC |
+                                  DM816X_USB_CTRL_PHYSLEEP1 |
+                                  DM816X_USB_CTRL_PHYSLEEP0,
+                                  0);
+       regmap_read(phy->syscon, phy->usb_ctrl, &val);
+       if ((val & 3) != 0)
+               dev_info(phy->dev,
+                        "Working dm816x USB_CTRL! (0x%08x)\n",
+                        val);
+
+       /*
+        * TI kernel sets these values for "symmetrical eye diagram and
+        * better signal quality" so let's assume somebody checked the
+        * values with a scope and set them here too.
+        */
+       regmap_read(phy->syscon, phy->usbphy_ctrl, &val);
+       val |= DM816X_USBPHY_CTRL_TXRISETUNE |
+               DM816X_USBPHY_CTRL_TXVREFTUNE |
+               DM816X_USBPHY_CTRL_TXPREEMTUNE;
+       regmap_write(phy->syscon, phy->usbphy_ctrl, val);
+
+       return 0;
+}
+
+static struct phy_ops ops = {
+       .init           = dm816x_usb_phy_init,
+       .owner          = THIS_MODULE,
+};
+
+static int dm816x_usb_phy_runtime_suspend(struct device *dev)
+{
+       struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
+       unsigned int mask, val;
+       int error = 0;
+
+       mask = BIT(phy->instance);
+       val = ~BIT(phy->instance);
+       error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
+                                  mask, val);
+       if (error)
+               dev_err(phy->dev, "phy%i failed to power off\n",
+                       phy->instance);
+       clk_disable(phy->refclk);
+
+       return 0;
+}
+
+static int dm816x_usb_phy_runtime_resume(struct device *dev)
+{
+       struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
+       unsigned int mask, val;
+       int error;
+
+       error = clk_enable(phy->refclk);
+       if (error)
+               return error;
+
+       /*
+        * Note that at least dm816x rev c does not seem to do
+        * anything with the USB_CTRL register. But let's follow
+        * what the TI tree is doing in case later revisions use
+        * USB_CTRL.
+        */
+       mask = BIT(phy->instance);
+       val = BIT(phy->instance);
+       error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
+                                  mask, val);
+       if (error) {
+               dev_err(phy->dev, "phy%i failed to power on\n",
+                       phy->instance);
+               clk_disable(phy->refclk);
+               return error;
+       }
+
+       return 0;
+}
+
+static UNIVERSAL_DEV_PM_OPS(dm816x_usb_phy_pm_ops,
+                           dm816x_usb_phy_runtime_suspend,
+                           dm816x_usb_phy_runtime_resume,
+                           NULL);
+
+#ifdef CONFIG_OF
+static const struct of_device_id dm816x_usb_phy_id_table[] = {
+       {
+               .compatible = "ti,dm8168-usb-phy",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, dm816x_usb_phy_id_table);
+#endif
+
+static int dm816x_usb_phy_probe(struct platform_device *pdev)
+{
+       struct dm816x_usb_phy *phy;
+       struct resource *res;
+       struct phy *generic_phy;
+       struct phy_provider *phy_provider;
+       struct usb_otg *otg;
+       const struct of_device_id *of_id;
+       const struct usb_phy_data *phy_data;
+       int error;
+
+       of_id = of_match_device(of_match_ptr(dm816x_usb_phy_id_table),
+                               &pdev->dev);
+       if (!of_id)
+               return -EINVAL;
+
+       phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+       if (!phy)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENOENT;
+
+       phy->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+                                                     "syscon");
+       if (IS_ERR(phy->syscon))
+               return PTR_ERR(phy->syscon);
+
+       /*
+        * According to sprs614e.pdf, the first usb_ctrl is shared and
+        * the second instance for usb_ctrl is reserved.. Also the
+        * register bits are different from earlier TRMs.
+        */
+       phy->usb_ctrl = 0x20;
+       phy->usbphy_ctrl = (res->start & 0xff) + 4;
+       if (phy->usbphy_ctrl == 0x2c)
+               phy->instance = 1;
+
+       phy_data = of_id->data;
+
+       otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+       if (!otg)
+               return -ENOMEM;
+
+       phy->dev = &pdev->dev;
+       phy->phy.dev = phy->dev;
+       phy->phy.label = "dm8168_usb_phy";
+       phy->phy.otg = otg;
+       phy->phy.type = USB_PHY_TYPE_USB2;
+       otg->set_host = dm816x_usb_phy_set_host;
+       otg->set_peripheral = dm816x_usb_phy_set_peripheral;
+       otg->usb_phy = &phy->phy;
+
+       platform_set_drvdata(pdev, phy);
+
+       phy->refclk = devm_clk_get(phy->dev, "refclk");
+       if (IS_ERR(phy->refclk))
+               return PTR_ERR(phy->refclk);
+       error = clk_prepare(phy->refclk);
+       if (error)
+               return error;
+
+       pm_runtime_enable(phy->dev);
+       generic_phy = devm_phy_create(phy->dev, NULL, &ops);
+       if (IS_ERR(generic_phy))
+               return PTR_ERR(generic_phy);
+
+       phy_set_drvdata(generic_phy, phy);
+
+       phy_provider = devm_of_phy_provider_register(phy->dev,
+                                                    of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
+       usb_add_phy_dev(&phy->phy);
+
+       return 0;
+}
+
+static int dm816x_usb_phy_remove(struct platform_device *pdev)
+{
+       struct dm816x_usb_phy *phy = platform_get_drvdata(pdev);
+
+       usb_remove_phy(&phy->phy);
+       pm_runtime_disable(phy->dev);
+       clk_unprepare(phy->refclk);
+
+       return 0;
+}
+
+static struct platform_driver dm816x_usb_phy_driver = {
+       .probe          = dm816x_usb_phy_probe,
+       .remove         = dm816x_usb_phy_remove,
+       .driver         = {
+               .name   = "dm816x-usb-phy",
+               .pm     = &dm816x_usb_phy_pm_ops,
+               .of_match_table = of_match_ptr(dm816x_usb_phy_id_table),
+       },
+};
+
+module_platform_driver(dm816x_usb_phy_driver);
+
+MODULE_ALIAS("platform:dm816x_usb");
+MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
+MODULE_DESCRIPTION("dm816x usb phy driver");
+MODULE_LICENSE("GPL v2");
index e2a0be750ad962d82e2666e5005a8b8daf97f381..d72ef15b0d68d575917fc6293e8e9bf6fc0e5342 100644 (file)
@@ -624,6 +624,13 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
        .has_common_clk_gate    = true,
 };
 
+static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = {
+       .phy_cfg                = phy_cfg_exynos5,
+       .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
+       .pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL,
+       .has_common_clk_gate    = false,
+};
+
 static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
        .phy_cfg                = phy_cfg_exynos5,
        .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
@@ -637,6 +644,9 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
        }, {
                .compatible = "samsung,exynos5420-usbdrd-phy",
                .data = &exynos5420_usbdrd_phy
+       }, {
+               .compatible = "samsung,exynos5433-usbdrd-phy",
+               .data = &exynos5433_usbdrd_phy
        }, {
                .compatible = "samsung,exynos7-usbdrd-phy",
                .data = &exynos7_usbdrd_phy
index 933435214acce1db8895b95cc739138288b3de4b..c4cc11dcb2a237c16d801005fd0006a77140c139 100644 (file)
@@ -1259,10 +1259,7 @@ static int miphy28lp_probe(struct platform_device *pdev)
        }
 
        provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate);
-       if (IS_ERR(provider))
-               return PTR_ERR(provider);
-
-       return 0;
+       return PTR_ERR_OR_ZERO(provider);
 }
 
 static const struct of_device_id miphy28lp_of_match[] = {
index 51b459db9137417bb26fa971df92e6d8e86121ed..019c2d75344e4f79482b12d9108b2cdd93c2cf2e 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 
-#include <dt-bindings/phy/phy-miphy365x.h>
+#include <dt-bindings/phy/phy.h>
 
 #define HFC_TIMEOUT            100
 
@@ -177,7 +177,7 @@ static u8 rx_tx_spd[] = {
 static int miphy365x_set_path(struct miphy365x_phy *miphy_phy,
                              struct miphy365x_dev *miphy_dev)
 {
-       bool sata = (miphy_phy->type == MIPHY_TYPE_SATA);
+       bool sata = (miphy_phy->type == PHY_TYPE_SATA);
 
        return regmap_update_bits(miphy_dev->regmap,
                                  miphy_phy->ctrlreg,
@@ -431,7 +431,7 @@ static int miphy365x_init(struct phy *phy)
        }
 
        /* Initialise Miphy for PCIe or SATA */
-       if (miphy_phy->type == MIPHY_TYPE_PCIE)
+       if (miphy_phy->type == PHY_TYPE_PCIE)
                ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev);
        else
                ret = miphy365x_init_sata_port(miphy_phy, miphy_dev);
@@ -455,8 +455,8 @@ int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy,
                return ret;
        }
 
-       if (!((!strncmp(name, "sata", 4) && type == MIPHY_TYPE_SATA) ||
-             (!strncmp(name, "pcie", 4) && type == MIPHY_TYPE_PCIE)))
+       if (!((!strncmp(name, "sata", 4) && type == PHY_TYPE_SATA) ||
+             (!strncmp(name, "pcie", 4) && type == PHY_TYPE_PCIE)))
                return 0;
 
        miphy_phy->base = of_iomap(phynode, index);
@@ -499,8 +499,8 @@ static struct phy *miphy365x_xlate(struct device *dev,
 
        miphy_phy->type = args->args[0];
 
-       if (!(miphy_phy->type == MIPHY_TYPE_SATA ||
-             miphy_phy->type == MIPHY_TYPE_PCIE)) {
+       if (!(miphy_phy->type == PHY_TYPE_SATA ||
+             miphy_phy->type == PHY_TYPE_PCIE)) {
                dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type);
                return ERR_PTR(-EINVAL);
        }
index 93252e053a31ca752fe54bd0fc71760d318f2579..e9c41b3fa0ee8fa124eff48fe7e20159d6c3c41c 100644 (file)
@@ -216,7 +216,6 @@ void omap_control_usb_set_mode(struct device *dev,
                return;
 
        ctrl_phy = dev_get_drvdata(dev);
-
        if (!ctrl_phy) {
                dev_err(dev, "Invalid control phy device\n");
                return;
@@ -241,8 +240,6 @@ void omap_control_usb_set_mode(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
 
-#ifdef CONFIG_OF
-
 static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS;
 static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
 static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
@@ -278,8 +275,6 @@ static const struct of_device_id omap_control_phy_id_table[] = {
        {},
 };
 MODULE_DEVICE_TABLE(of, omap_control_phy_id_table);
-#endif
-
 
 static int omap_control_phy_probe(struct platform_device *pdev)
 {
@@ -287,8 +282,7 @@ static int omap_control_phy_probe(struct platform_device *pdev)
        const struct of_device_id *of_id;
        struct omap_control_phy *control_phy;
 
-       of_id = of_match_device(of_match_ptr(omap_control_phy_id_table),
-                               &pdev->dev);
+       of_id = of_match_device(omap_control_phy_id_table, &pdev->dev);
        if (!of_id)
                return -EINVAL;
 
@@ -344,7 +338,7 @@ static struct platform_driver omap_control_phy_driver = {
        .probe          = omap_control_phy_probe,
        .driver         = {
                .name   = "omap-control-phy",
-               .of_match_table = of_match_ptr(omap_control_phy_id_table),
+               .of_match_table = omap_control_phy_id_table,
        },
 };
 
index 4757e765696a232d1926ece274ef35111188cdc1..183ef43681016ba0f238edfa98bbbef3684ab543 100644 (file)
@@ -144,7 +144,6 @@ static struct phy_ops ops = {
        .owner          = THIS_MODULE,
 };
 
-#ifdef CONFIG_OF
 static const struct usb_phy_data omap_usb2_data = {
        .label = "omap_usb2",
        .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS,
@@ -185,7 +184,6 @@ static const struct of_device_id omap_usb2_id_table[] = {
        {},
 };
 MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
-#endif
 
 static int omap_usb2_probe(struct platform_device *pdev)
 {
@@ -200,7 +198,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
        const struct of_device_id *of_id;
        struct usb_phy_data *phy_data;
 
-       of_id = of_match_device(of_match_ptr(omap_usb2_id_table), &pdev->dev);
+       of_id = of_match_device(omap_usb2_id_table, &pdev->dev);
 
        if (!of_id)
                return -EINVAL;
@@ -378,7 +376,7 @@ static struct platform_driver omap_usb2_driver = {
        .driver         = {
                .name   = "omap-usb2",
                .pm     = DEV_PM_OPS,
-               .of_match_table = of_match_ptr(omap_usb2_id_table),
+               .of_match_table = omap_usb2_id_table,
        },
 };
 
index 44ee983d57fe5a2de86945606a4c63a64b88d11b..f9c618f0ab6e4fe120462616b2c84ba0d9fe30a6 100644 (file)
@@ -73,6 +73,7 @@ int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
 out:
        return ret;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate);
 
 struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
                                struct ufs_qcom_phy *common_cfg,
@@ -101,6 +102,7 @@ struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
        if (IS_ERR(generic_phy)) {
                err =  PTR_ERR(generic_phy);
                dev_err(dev, "%s: failed to create phy %d\n", __func__, err);
+               generic_phy = NULL;
                goto out;
        }
 
@@ -110,6 +112,7 @@ struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
 out:
        return generic_phy;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe);
 
 /*
  * This assumes the embedded phy structure inside generic_phy is of type
@@ -121,6 +124,7 @@ struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy)
 {
        return (struct ufs_qcom_phy *)phy_get_drvdata(generic_phy);
 }
+EXPORT_SYMBOL_GPL(get_ufs_qcom_phy);
 
 static
 int ufs_qcom_phy_base_init(struct platform_device *pdev,
@@ -131,40 +135,23 @@ int ufs_qcom_phy_base_init(struct platform_device *pdev,
        int err = 0;
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_mem");
-       if (!res) {
-               dev_err(dev, "%s: phy_mem resource not found\n", __func__);
-               err = -ENOMEM;
-               goto out;
-       }
-
        phy_common->mmio = devm_ioremap_resource(dev, res);
        if (IS_ERR((void const *)phy_common->mmio)) {
                err = PTR_ERR((void const *)phy_common->mmio);
                phy_common->mmio = NULL;
                dev_err(dev, "%s: ioremap for phy_mem resource failed %d\n",
                        __func__, err);
-               goto out;
+               return err;
        }
 
        /* "dev_ref_clk_ctrl_mem" is optional resource */
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
                                           "dev_ref_clk_ctrl_mem");
-       if (!res) {
-               dev_dbg(dev, "%s: dev_ref_clk_ctrl_mem resource not found\n",
-                       __func__);
-               goto out;
-       }
-
        phy_common->dev_ref_clk_ctrl_mmio = devm_ioremap_resource(dev, res);
-       if (IS_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio)) {
-               err = PTR_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio);
+       if (IS_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio))
                phy_common->dev_ref_clk_ctrl_mmio = NULL;
-               dev_err(dev, "%s: ioremap for dev_ref_clk_ctrl_mem resource failed %d\n",
-                       __func__, err);
-       }
 
-out:
-       return err;
+       return 0;
 }
 
 static int __ufs_qcom_phy_clk_get(struct phy *phy,
@@ -228,6 +215,7 @@ ufs_qcom_phy_init_clks(struct phy *generic_phy,
 out:
        return err;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_clks);
 
 int
 ufs_qcom_phy_init_vregulators(struct phy *generic_phy,
@@ -252,6 +240,7 @@ ufs_qcom_phy_init_vregulators(struct phy *generic_phy,
 out:
        return err;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_vregulators);
 
 static int __ufs_qcom_phy_init_vreg(struct phy *phy,
                struct ufs_qcom_phy_vreg *vreg, const char *name, bool optional)
@@ -346,10 +335,10 @@ int ufs_qcom_phy_cfg_vreg(struct phy *phy,
                        goto out;
                }
                uA_load = on ? vreg->max_uA : 0;
-               ret = regulator_set_optimum_mode(reg, uA_load);
+               ret = regulator_set_load(reg, uA_load);
                if (ret >= 0) {
                        /*
-                        * regulator_set_optimum_mode() returns new regulator
+                        * regulator_set_load() returns new regulator
                         * mode upon success.
                         */
                        ret = 0;
@@ -647,6 +636,7 @@ int ufs_qcom_phy_remove(struct phy *generic_phy,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_remove);
 
 int ufs_qcom_phy_exit(struct phy *generic_phy)
 {
@@ -657,6 +647,7 @@ int ufs_qcom_phy_exit(struct phy *generic_phy)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_exit);
 
 int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy)
 {
@@ -725,6 +716,7 @@ out_disable_phy:
 out:
        return err;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_on);
 
 int ufs_qcom_phy_power_off(struct phy *generic_phy)
 {
@@ -743,3 +735,4 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_off);
index 4a12f66b7fb5f7d23febedd7da57048513608f3f..55b6994932e37f0b3d5d14c72cb1ff7df4807f85 100644 (file)
@@ -37,10 +37,14 @@ static int samsung_usb2_phy_power_on(struct phy *phy)
                spin_lock(&drv->lock);
                ret = inst->cfg->power_on(inst);
                spin_unlock(&drv->lock);
+               if (ret)
+                       goto err_power_on;
        }
 
        return 0;
 
+err_power_on:
+       clk_disable_unprepare(drv->ref_clk);
 err_instance_clk:
        clk_disable_unprepare(drv->clk);
 err_main_clk:
@@ -51,7 +55,7 @@ static int samsung_usb2_phy_power_off(struct phy *phy)
 {
        struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
        struct samsung_usb2_phy_driver *drv = inst->drv;
-       int ret = 0;
+       int ret;
 
        dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n",
                inst->cfg->label);
@@ -59,10 +63,12 @@ static int samsung_usb2_phy_power_off(struct phy *phy)
                spin_lock(&drv->lock);
                ret = inst->cfg->power_off(inst);
                spin_unlock(&drv->lock);
+               if (ret)
+                       return ret;
        }
        clk_disable_unprepare(drv->ref_clk);
        clk_disable_unprepare(drv->clk);
-       return ret;
+       return 0;
 }
 
 static struct phy_ops samsung_usb2_phy_ops = {
index 9f47fae7eecb76d7e6b23c78050b1507ce97f107..65ae640cfbd1cf533b036597b045043483240429 100644 (file)
@@ -192,14 +192,14 @@ static struct phy *spear1310_miphy_xlate(struct device *dev,
 
        if (args->args_count < 1) {
                dev_err(dev, "DT did not pass correct no of args\n");
-               return NULL;
+               return ERR_PTR(-ENODEV);
        }
 
        priv->mode = args->args[0];
 
        if (priv->mode != SATA && priv->mode != PCIE) {
                dev_err(dev, "DT did not pass correct phy mode\n");
-               return NULL;
+               return ERR_PTR(-ENODEV);
        }
 
        return priv->phy;
index e42bc200275f1e228813a8a26c7d4407bc3c9354..1a00c2817f34f8a7c5837ef8f701b09192702116 100644 (file)
@@ -229,14 +229,14 @@ static struct phy *spear1340_miphy_xlate(struct device *dev,
 
        if (args->args_count < 1) {
                dev_err(dev, "DT did not pass correct no of args\n");
-               return NULL;
+               return ERR_PTR(-ENODEV);
        }
 
        priv->mode = args->args[0];
 
        if (priv->mode != SATA && priv->mode != PCIE) {
                dev_err(dev, "DT did not pass correct phy mode\n");
-               return NULL;
+               return ERR_PTR(-ENODEV);
        }
 
        return priv->phy;
index a603801293ffec6581d37d1f871247914745fe97..c093b472b57dadee94b832a989f5495a07dc98f2 100644 (file)
@@ -87,8 +87,12 @@ static int stih41x_usb_phy_power_on(struct phy *phy)
                return ret;
        }
 
-       return regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg,
-                       phy_dev->cfg->oscok, phy_dev->cfg->oscok);
+       ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg,
+                                phy_dev->cfg->oscok, phy_dev->cfg->oscok);
+       if (ret)
+               clk_disable_unprepare(phy_dev->clk);
+
+       return ret;
 }
 
 static int stih41x_usb_phy_power_off(struct phy *phy)
diff --git a/drivers/phy/phy-sun9i-usb.c b/drivers/phy/phy-sun9i-usb.c
new file mode 100644 (file)
index 0000000..0095914
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Allwinner sun9i USB phy driver
+ *
+ * Copyright (C) 2014-2015 Chen-Yu Tsai <wens@csie.org>
+ *
+ * Based on phy-sun4i-usb.c from
+ * Hans de Goede <hdegoede@redhat.com>
+ *
+ * and 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/io.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/usb/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#define SUNXI_AHB_INCR16_BURST_EN      BIT(11)
+#define SUNXI_AHB_INCR8_BURST_EN       BIT(10)
+#define SUNXI_AHB_INCR4_BURST_EN       BIT(9)
+#define SUNXI_AHB_INCRX_ALIGN_EN       BIT(8)
+#define SUNXI_ULPI_BYPASS_EN           BIT(0)
+
+/* usb1 HSIC specific bits */
+#define SUNXI_EHCI_HS_FORCE            BIT(20)
+#define SUNXI_HSIC_CONNECT_DET         BIT(17)
+#define SUNXI_HSIC_CONNECT_INT         BIT(16)
+#define SUNXI_HSIC                     BIT(1)
+
+struct sun9i_usb_phy {
+       struct phy *phy;
+       void __iomem *pmu;
+       struct reset_control *reset;
+       struct clk *clk;
+       struct clk *hsic_clk;
+       enum usb_phy_interface type;
+};
+
+static void sun9i_usb_phy_passby(struct sun9i_usb_phy *phy, int enable)
+{
+       u32 bits, reg_value;
+
+       bits = SUNXI_AHB_INCR16_BURST_EN | SUNXI_AHB_INCR8_BURST_EN |
+               SUNXI_AHB_INCR4_BURST_EN | SUNXI_AHB_INCRX_ALIGN_EN |
+               SUNXI_ULPI_BYPASS_EN;
+
+       if (phy->type == USBPHY_INTERFACE_MODE_HSIC)
+               bits |= SUNXI_HSIC | SUNXI_EHCI_HS_FORCE |
+                       SUNXI_HSIC_CONNECT_DET | SUNXI_HSIC_CONNECT_INT;
+
+       reg_value = readl(phy->pmu);
+
+       if (enable)
+               reg_value |= bits;
+       else
+               reg_value &= ~bits;
+
+       writel(reg_value, phy->pmu);
+}
+
+static int sun9i_usb_phy_init(struct phy *_phy)
+{
+       struct sun9i_usb_phy *phy = phy_get_drvdata(_phy);
+       int ret;
+
+       ret = clk_prepare_enable(phy->clk);
+       if (ret)
+               goto err_clk;
+
+       ret = clk_prepare_enable(phy->hsic_clk);
+       if (ret)
+               goto err_hsic_clk;
+
+       ret = reset_control_deassert(phy->reset);
+       if (ret)
+               goto err_reset;
+
+       sun9i_usb_phy_passby(phy, 1);
+       return 0;
+
+err_reset:
+       clk_disable_unprepare(phy->hsic_clk);
+
+err_hsic_clk:
+       clk_disable_unprepare(phy->clk);
+
+err_clk:
+       return ret;
+}
+
+static int sun9i_usb_phy_exit(struct phy *_phy)
+{
+       struct sun9i_usb_phy *phy = phy_get_drvdata(_phy);
+
+       sun9i_usb_phy_passby(phy, 0);
+       reset_control_assert(phy->reset);
+       clk_disable_unprepare(phy->hsic_clk);
+       clk_disable_unprepare(phy->clk);
+
+       return 0;
+}
+
+static struct phy_ops sun9i_usb_phy_ops = {
+       .init           = sun9i_usb_phy_init,
+       .exit           = sun9i_usb_phy_exit,
+       .owner          = THIS_MODULE,
+};
+
+static int sun9i_usb_phy_probe(struct platform_device *pdev)
+{
+       struct sun9i_usb_phy *phy;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct phy_provider *phy_provider;
+       struct resource *res;
+
+       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+       if (!phy)
+               return -ENOMEM;
+
+       phy->type = of_usb_get_phy_mode(np);
+       if (phy->type == USBPHY_INTERFACE_MODE_HSIC) {
+               phy->clk = devm_clk_get(dev, "hsic_480M");
+               if (IS_ERR(phy->clk)) {
+                       dev_err(dev, "failed to get hsic_480M clock\n");
+                       return PTR_ERR(phy->clk);
+               }
+
+               phy->hsic_clk = devm_clk_get(dev, "hsic_12M");
+               if (IS_ERR(phy->clk)) {
+                       dev_err(dev, "failed to get hsic_12M clock\n");
+                       return PTR_ERR(phy->clk);
+               }
+
+               phy->reset = devm_reset_control_get(dev, "hsic");
+               if (IS_ERR(phy->reset)) {
+                       dev_err(dev, "failed to get reset control\n");
+                       return PTR_ERR(phy->reset);
+               }
+       } else {
+               phy->clk = devm_clk_get(dev, "phy");
+               if (IS_ERR(phy->clk)) {
+                       dev_err(dev, "failed to get phy clock\n");
+                       return PTR_ERR(phy->clk);
+               }
+
+               phy->reset = devm_reset_control_get(dev, "phy");
+               if (IS_ERR(phy->reset)) {
+                       dev_err(dev, "failed to get reset control\n");
+                       return PTR_ERR(phy->reset);
+               }
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       phy->pmu = devm_ioremap_resource(dev, res);
+       if (IS_ERR(phy->pmu))
+               return PTR_ERR(phy->pmu);
+
+       phy->phy = devm_phy_create(dev, NULL, &sun9i_usb_phy_ops);
+       if (IS_ERR(phy->phy)) {
+               dev_err(dev, "failed to create PHY\n");
+               return PTR_ERR(phy->phy);
+       }
+
+       phy_set_drvdata(phy->phy, phy);
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id sun9i_usb_phy_of_match[] = {
+       { .compatible = "allwinner,sun9i-a80-usb-phy" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, sun9i_usb_phy_of_match);
+
+static struct platform_driver sun9i_usb_phy_driver = {
+       .probe  = sun9i_usb_phy_probe,
+       .driver = {
+               .of_match_table = sun9i_usb_phy_of_match,
+               .name  = "sun9i-usb-phy",
+       }
+};
+module_platform_driver(sun9i_usb_phy_driver);
+
+MODULE_DESCRIPTION("Allwinner sun9i USB phy driver");
+MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
+MODULE_LICENSE("GPL");
index 2ba610b72ca202842df7f6b43b18c7da17af1d1c..53f295c1bab1a72108d84b955714b8aef4d7e951 100644 (file)
@@ -287,9 +287,7 @@ static struct phy_ops ops = {
        .owner          = THIS_MODULE,
 };
 
-#ifdef CONFIG_OF
 static const struct of_device_id ti_pipe3_id_table[];
-#endif
 
 static int ti_pipe3_probe(struct platform_device *pdev)
 {
@@ -311,8 +309,7 @@ static int ti_pipe3_probe(struct platform_device *pdev)
        spin_lock_init(&phy->lock);
 
        if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
-               match = of_match_device(of_match_ptr(ti_pipe3_id_table),
-                                       &pdev->dev);
+               match = of_match_device(ti_pipe3_id_table, &pdev->dev);
                if (!match)
                        return -EINVAL;
 
@@ -570,7 +567,6 @@ static const struct dev_pm_ops ti_pipe3_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(ti_pipe3_suspend, ti_pipe3_resume)
 };
 
-#ifdef CONFIG_OF
 static const struct of_device_id ti_pipe3_id_table[] = {
        {
                .compatible = "ti,phy-usb3",
@@ -590,7 +586,6 @@ static const struct of_device_id ti_pipe3_id_table[] = {
        {}
 };
 MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
-#endif
 
 static struct platform_driver ti_pipe3_driver = {
        .probe          = ti_pipe3_probe,
@@ -598,7 +593,7 @@ static struct platform_driver ti_pipe3_driver = {
        .driver         = {
                .name   = "ti-pipe3",
                .pm     = &ti_pipe3_pm_ops,
-               .of_match_table = of_match_ptr(ti_pipe3_id_table),
+               .of_match_table = ti_pipe3_id_table,
        },
 };
 
index 2263cd01003211e6d81a39fcb7a48538ba08e2c1..385362e5b2f6fbee91a14ff9ba2afb9b14edcb7c 100644 (file)
@@ -1657,7 +1657,6 @@ static int xgene_phy_probe(struct platform_device *pdev)
        struct phy_provider *phy_provider;
        struct xgene_phy_ctx *ctx;
        struct resource *res;
-       int rc = 0;
        u32 default_spd[] = DEFAULT_SATA_SPD_SEL;
        u32 default_txboost_gain[] = DEFAULT_SATA_TXBOOST_GAIN;
        u32 default_txeye_direction[] = DEFAULT_SATA_TXEYEDIRECTION;
@@ -1676,10 +1675,8 @@ static int xgene_phy_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        ctx->sds_base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(ctx->sds_base)) {
-               rc = PTR_ERR(ctx->sds_base);
-               goto error;
-       }
+       if (IS_ERR(ctx->sds_base))
+               return PTR_ERR(ctx->sds_base);
 
        /* Retrieve optional clock */
        ctx->clk = clk_get(&pdev->dev, NULL);
@@ -1709,22 +1706,12 @@ static int xgene_phy_probe(struct platform_device *pdev)
        ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops);
        if (IS_ERR(ctx->phy)) {
                dev_dbg(&pdev->dev, "Failed to create PHY\n");
-               rc = PTR_ERR(ctx->phy);
-               goto error;
+               return PTR_ERR(ctx->phy);
        }
        phy_set_drvdata(ctx->phy, ctx);
 
-       phy_provider = devm_of_phy_provider_register(ctx->dev,
-                                                    xgene_phy_xlate);
-       if (IS_ERR(phy_provider)) {
-               rc = PTR_ERR(phy_provider);
-               goto error;
-       }
-
-       return 0;
-
-error:
-       return rc;
+       phy_provider = devm_of_phy_provider_register(ctx->dev, xgene_phy_xlate);
+       return PTR_ERR_OR_ZERO(phy_provider);
 }
 
 static const struct of_device_id xgene_phy_of_match[] = {
index ee9f44ad7f02f8aa5dea0a5c1c349128c20e4e32..c6f299ba25cb6c9d610507e138c7eb57dc535268 100644 (file)
@@ -67,23 +67,20 @@ config PINCTRL_AT91
        help
          Say Y here to enable the at91 pinctrl driver
 
-config PINCTRL_BCM2835
-       bool
-       select PINMUX
-       select PINCONF
-
-config PINCTRL_BCM281XX
-       bool "Broadcom BCM281xx pinctrl driver"
-       depends on OF && (ARCH_BCM_MOBILE || COMPILE_TEST)
-       select PINMUX
+config PINCTRL_AMD
+       bool "AMD GPIO pin control"
+       depends on GPIOLIB
+       select GPIOLIB_IRQCHIP
        select PINCONF
        select GENERIC_PINCONF
-       select REGMAP_MMIO
        help
-         Say Y here to support Broadcom BCM281xx pinctrl driver, which is used
-         for the BCM281xx SoC family, including BCM11130, BCM11140, BCM11351,
-         BCM28145, and BCM28155 SoCs.  This driver requires the pinctrl
-         framework.  GPIO is provided by a separate GPIO driver.
+         driver for memory mapped GPIO functionality on AMD platforms
+         (x86 or arm).Most pins are usually muxed to some other
+         functionality by firmware,so only a small amount is available
+         for gpio use.
+
+         Requires ACPI/FDT device enumeration code to set up a platform
+         device.
 
 config PINCTRL_LANTIQ
        bool
@@ -154,6 +151,10 @@ config PINCTRL_TEGRA124
        bool
        select PINCTRL_TEGRA
 
+config PINCTRL_TEGRA210
+       bool
+       select PINCTRL_TEGRA
+
 config PINCTRL_TEGRA_XUSB
        def_bool y if ARCH_TEGRA
        select GENERIC_PHY
@@ -207,6 +208,7 @@ config PINCTRL_ZYNQ
        help
          This selectes the pinctrl driver for Xilinx Zynq.
 
+source "drivers/pinctrl/bcm/Kconfig"
 source "drivers/pinctrl/berlin/Kconfig"
 source "drivers/pinctrl/freescale/Kconfig"
 source "drivers/pinctrl/intel/Kconfig"
@@ -218,6 +220,7 @@ source "drivers/pinctrl/sh-pfc/Kconfig"
 source "drivers/pinctrl/spear/Kconfig"
 source "drivers/pinctrl/sunxi/Kconfig"
 source "drivers/pinctrl/vt8500/Kconfig"
+source "drivers/pinctrl/mediatek/Kconfig"
 
 config PINCTRL_XWAY
        bool
index 0475206dd600098000797d63b11fbe13456042b7..6eadf04a33b3e56131a6fc0cb9d062b45a8240da 100644 (file)
@@ -14,8 +14,7 @@ obj-$(CONFIG_PINCTRL_AS3722)  += pinctrl-as3722.o
 obj-$(CONFIG_PINCTRL_BF54x)    += pinctrl-adi2-bf54x.o
 obj-$(CONFIG_PINCTRL_BF60x)    += pinctrl-adi2-bf60x.o
 obj-$(CONFIG_PINCTRL_AT91)     += pinctrl-at91.o
-obj-$(CONFIG_PINCTRL_BCM2835)  += pinctrl-bcm2835.o
-obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o
+obj-$(CONFIG_PINCTRL_AMD)      += pinctrl-amd.o
 obj-$(CONFIG_PINCTRL_FALCON)   += pinctrl-falcon.o
 obj-$(CONFIG_PINCTRL_MESON)    += meson/
 obj-$(CONFIG_PINCTRL_PALMAS)   += pinctrl-palmas.o
@@ -27,6 +26,7 @@ obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
 obj-$(CONFIG_PINCTRL_TEGRA30)  += pinctrl-tegra30.o
 obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o
 obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o
+obj-$(CONFIG_PINCTRL_TEGRA210) += pinctrl-tegra210.o
 obj-$(CONFIG_PINCTRL_TEGRA_XUSB)       += pinctrl-tegra-xusb.o
 obj-$(CONFIG_PINCTRL_TZ1090)   += pinctrl-tz1090.o
 obj-$(CONFIG_PINCTRL_TZ1090_PDC)       += pinctrl-tz1090-pdc.o
@@ -38,6 +38,7 @@ obj-$(CONFIG_PINCTRL_TB10X)   += pinctrl-tb10x.o
 obj-$(CONFIG_PINCTRL_ST)       += pinctrl-st.o
 obj-$(CONFIG_PINCTRL_ZYNQ)     += pinctrl-zynq.o
 
+obj-$(CONFIG_ARCH_BCM)         += bcm/
 obj-$(CONFIG_ARCH_BERLIN)      += berlin/
 obj-y                          += freescale/
 obj-$(CONFIG_X86)              += intel/
@@ -49,3 +50,4 @@ obj-$(CONFIG_PINCTRL_SH_PFC)  += sh-pfc/
 obj-$(CONFIG_PLAT_SPEAR)       += spear/
 obj-$(CONFIG_ARCH_SUNXI)       += sunxi/
 obj-$(CONFIG_ARCH_VT8500)      += vt8500/
+obj-$(CONFIG_ARCH_MEDIATEK)    += mediatek/
diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig
new file mode 100644 (file)
index 0000000..cd11d4d
--- /dev/null
@@ -0,0 +1,56 @@
+#
+# Broadcom pinctrl drivers
+#
+
+config PINCTRL_BCM281XX
+       bool "Broadcom BCM281xx pinctrl driver"
+       depends on OF && (ARCH_BCM_MOBILE || COMPILE_TEST)
+       select PINMUX
+       select PINCONF
+       select GENERIC_PINCONF
+       select REGMAP_MMIO
+       help
+         Say Y here to support Broadcom BCM281xx pinctrl driver, which is used
+         for the BCM281xx SoC family, including BCM11130, BCM11140, BCM11351,
+         BCM28145, and BCM28155 SoCs.  This driver requires the pinctrl
+         framework.  GPIO is provided by a separate GPIO driver.
+
+config PINCTRL_BCM2835
+       bool
+       select PINMUX
+       select PINCONF
+
+config PINCTRL_CYGNUS_GPIO
+       bool "Broadcom Cygnus GPIO (with PINCONF) driver"
+       depends on OF_GPIO && ARCH_BCM_CYGNUS
+       select GPIOLIB_IRQCHIP
+       select PINCONF
+       select GENERIC_PINCONF
+       default ARCH_BCM_CYGNUS
+       help
+         Say yes here to enable the Broadcom Cygnus GPIO driver.
+
+         The Broadcom Cygnus SoC has 3 GPIO controllers including the ASIU
+         GPIO controller (ASIU), the chipCommonG GPIO controller (CCM), and
+         the always-ON GPIO controller (CRMU/AON). All 3 GPIO controllers are
+         supported by this driver.
+
+         All 3 Cygnus GPIO controllers support basic PINCONF functions such
+         as bias pull up, pull down, and drive strength configurations, when
+         these pins are muxed to GPIO.
+
+         Pins from the ASIU GPIO can be individually muxed to GPIO function,
+         through interaction with the Cygnus IOMUX controller.
+
+config PINCTRL_CYGNUS_MUX
+       bool "Broadcom Cygnus IOMUX driver"
+       depends on (ARCH_BCM_CYGNUS || COMPILE_TEST)
+       select PINMUX
+       select GENERIC_PINCONF
+       default ARCH_BCM_CYGNUS
+       help
+         Say yes here to enable the Broadcom Cygnus IOMUX driver.
+
+         The Broadcom Cygnus IOMUX driver supports group based IOMUX
+         configuration, with the exception that certain individual pins
+         can be overrided to GPIO function
diff --git a/drivers/pinctrl/bcm/Makefile b/drivers/pinctrl/bcm/Makefile
new file mode 100644 (file)
index 0000000..2b2f70e
--- /dev/null
@@ -0,0 +1,6 @@
+# Broadcom pinctrl support
+
+obj-$(CONFIG_PINCTRL_BCM281XX)         += pinctrl-bcm281xx.o
+obj-$(CONFIG_PINCTRL_BCM2835)          += pinctrl-bcm2835.o
+obj-$(CONFIG_PINCTRL_CYGNUS_GPIO)      += pinctrl-cygnus-gpio.o
+obj-$(CONFIG_PINCTRL_CYGNUS_MUX)       += pinctrl-cygnus-mux.o
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
new file mode 100644 (file)
index 0000000..9641f1c
--- /dev/null
@@ -0,0 +1,1455 @@
+/*
+ * Copyright (C) 2013 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+/* BCM281XX Pin Control Registers Definitions */
+
+/* Function Select bits are the same for all pin control registers */
+#define BCM281XX_PIN_REG_F_SEL_MASK            0x0700
+#define BCM281XX_PIN_REG_F_SEL_SHIFT           8
+
+/* Standard pin register */
+#define BCM281XX_STD_PIN_REG_DRV_STR_MASK      0x0007
+#define BCM281XX_STD_PIN_REG_DRV_STR_SHIFT     0
+#define BCM281XX_STD_PIN_REG_INPUT_DIS_MASK    0x0008
+#define BCM281XX_STD_PIN_REG_INPUT_DIS_SHIFT   3
+#define BCM281XX_STD_PIN_REG_SLEW_MASK         0x0010
+#define BCM281XX_STD_PIN_REG_SLEW_SHIFT                4
+#define BCM281XX_STD_PIN_REG_PULL_UP_MASK      0x0020
+#define BCM281XX_STD_PIN_REG_PULL_UP_SHIFT     5
+#define BCM281XX_STD_PIN_REG_PULL_DN_MASK      0x0040
+#define BCM281XX_STD_PIN_REG_PULL_DN_SHIFT     6
+#define BCM281XX_STD_PIN_REG_HYST_MASK         0x0080
+#define BCM281XX_STD_PIN_REG_HYST_SHIFT                7
+
+/* I2C pin register */
+#define BCM281XX_I2C_PIN_REG_INPUT_DIS_MASK    0x0004
+#define BCM281XX_I2C_PIN_REG_INPUT_DIS_SHIFT   2
+#define BCM281XX_I2C_PIN_REG_SLEW_MASK         0x0008
+#define BCM281XX_I2C_PIN_REG_SLEW_SHIFT                3
+#define BCM281XX_I2C_PIN_REG_PULL_UP_STR_MASK  0x0070
+#define BCM281XX_I2C_PIN_REG_PULL_UP_STR_SHIFT 4
+
+/* HDMI pin register */
+#define BCM281XX_HDMI_PIN_REG_INPUT_DIS_MASK   0x0008
+#define BCM281XX_HDMI_PIN_REG_INPUT_DIS_SHIFT  3
+#define BCM281XX_HDMI_PIN_REG_MODE_MASK                0x0010
+#define BCM281XX_HDMI_PIN_REG_MODE_SHIFT       4
+
+/**
+ * bcm281xx_pin_type - types of pin register
+ */
+enum bcm281xx_pin_type {
+       BCM281XX_PIN_TYPE_UNKNOWN = 0,
+       BCM281XX_PIN_TYPE_STD,
+       BCM281XX_PIN_TYPE_I2C,
+       BCM281XX_PIN_TYPE_HDMI,
+};
+
+static enum bcm281xx_pin_type std_pin = BCM281XX_PIN_TYPE_STD;
+static enum bcm281xx_pin_type i2c_pin = BCM281XX_PIN_TYPE_I2C;
+static enum bcm281xx_pin_type hdmi_pin = BCM281XX_PIN_TYPE_HDMI;
+
+/**
+ * bcm281xx_pin_function- define pin function
+ */
+struct bcm281xx_pin_function {
+       const char *name;
+       const char * const *groups;
+       const unsigned ngroups;
+};
+
+/**
+ * bcm281xx_pinctrl_data - Broadcom-specific pinctrl data
+ * @reg_base - base of pinctrl registers
+ */
+struct bcm281xx_pinctrl_data {
+       void __iomem *reg_base;
+
+       /* List of all pins */
+       const struct pinctrl_pin_desc *pins;
+       const unsigned npins;
+
+       const struct bcm281xx_pin_function *functions;
+       const unsigned nfunctions;
+
+       struct regmap *regmap;
+};
+
+/*
+ * Pin number definition.  The order here must be the same as defined in the
+ * PADCTRLREG block in the RDB.
+ */
+#define BCM281XX_PIN_ADCSYNC           0
+#define BCM281XX_PIN_BAT_RM            1
+#define BCM281XX_PIN_BSC1_SCL          2
+#define BCM281XX_PIN_BSC1_SDA          3
+#define BCM281XX_PIN_BSC2_SCL          4
+#define BCM281XX_PIN_BSC2_SDA          5
+#define BCM281XX_PIN_CLASSGPWR         6
+#define BCM281XX_PIN_CLK_CX8           7
+#define BCM281XX_PIN_CLKOUT_0          8
+#define BCM281XX_PIN_CLKOUT_1          9
+#define BCM281XX_PIN_CLKOUT_2          10
+#define BCM281XX_PIN_CLKOUT_3          11
+#define BCM281XX_PIN_CLKREQ_IN_0       12
+#define BCM281XX_PIN_CLKREQ_IN_1       13
+#define BCM281XX_PIN_CWS_SYS_REQ1      14
+#define BCM281XX_PIN_CWS_SYS_REQ2      15
+#define BCM281XX_PIN_CWS_SYS_REQ3      16
+#define BCM281XX_PIN_DIGMIC1_CLK       17
+#define BCM281XX_PIN_DIGMIC1_DQ                18
+#define BCM281XX_PIN_DIGMIC2_CLK       19
+#define BCM281XX_PIN_DIGMIC2_DQ                20
+#define BCM281XX_PIN_GPEN13            21
+#define BCM281XX_PIN_GPEN14            22
+#define BCM281XX_PIN_GPEN15            23
+#define BCM281XX_PIN_GPIO00            24
+#define BCM281XX_PIN_GPIO01            25
+#define BCM281XX_PIN_GPIO02            26
+#define BCM281XX_PIN_GPIO03            27
+#define BCM281XX_PIN_GPIO04            28
+#define BCM281XX_PIN_GPIO05            29
+#define BCM281XX_PIN_GPIO06            30
+#define BCM281XX_PIN_GPIO07            31
+#define BCM281XX_PIN_GPIO08            32
+#define BCM281XX_PIN_GPIO09            33
+#define BCM281XX_PIN_GPIO10            34
+#define BCM281XX_PIN_GPIO11            35
+#define BCM281XX_PIN_GPIO12            36
+#define BCM281XX_PIN_GPIO13            37
+#define BCM281XX_PIN_GPIO14            38
+#define BCM281XX_PIN_GPS_PABLANK       39
+#define BCM281XX_PIN_GPS_TMARK         40
+#define BCM281XX_PIN_HDMI_SCL          41
+#define BCM281XX_PIN_HDMI_SDA          42
+#define BCM281XX_PIN_IC_DM             43
+#define BCM281XX_PIN_IC_DP             44
+#define BCM281XX_PIN_KP_COL_IP_0       45
+#define BCM281XX_PIN_KP_COL_IP_1       46
+#define BCM281XX_PIN_KP_COL_IP_2       47
+#define BCM281XX_PIN_KP_COL_IP_3       48
+#define BCM281XX_PIN_KP_ROW_OP_0       49
+#define BCM281XX_PIN_KP_ROW_OP_1       50
+#define BCM281XX_PIN_KP_ROW_OP_2       51
+#define BCM281XX_PIN_KP_ROW_OP_3       52
+#define BCM281XX_PIN_LCD_B_0           53
+#define BCM281XX_PIN_LCD_B_1           54
+#define BCM281XX_PIN_LCD_B_2           55
+#define BCM281XX_PIN_LCD_B_3           56
+#define BCM281XX_PIN_LCD_B_4           57
+#define BCM281XX_PIN_LCD_B_5           58
+#define BCM281XX_PIN_LCD_B_6           59
+#define BCM281XX_PIN_LCD_B_7           60
+#define BCM281XX_PIN_LCD_G_0           61
+#define BCM281XX_PIN_LCD_G_1           62
+#define BCM281XX_PIN_LCD_G_2           63
+#define BCM281XX_PIN_LCD_G_3           64
+#define BCM281XX_PIN_LCD_G_4           65
+#define BCM281XX_PIN_LCD_G_5           66
+#define BCM281XX_PIN_LCD_G_6           67
+#define BCM281XX_PIN_LCD_G_7           68
+#define BCM281XX_PIN_LCD_HSYNC         69
+#define BCM281XX_PIN_LCD_OE            70
+#define BCM281XX_PIN_LCD_PCLK          71
+#define BCM281XX_PIN_LCD_R_0           72
+#define BCM281XX_PIN_LCD_R_1           73
+#define BCM281XX_PIN_LCD_R_2           74
+#define BCM281XX_PIN_LCD_R_3           75
+#define BCM281XX_PIN_LCD_R_4           76
+#define BCM281XX_PIN_LCD_R_5           77
+#define BCM281XX_PIN_LCD_R_6           78
+#define BCM281XX_PIN_LCD_R_7           79
+#define BCM281XX_PIN_LCD_VSYNC         80
+#define BCM281XX_PIN_MDMGPIO0          81
+#define BCM281XX_PIN_MDMGPIO1          82
+#define BCM281XX_PIN_MDMGPIO2          83
+#define BCM281XX_PIN_MDMGPIO3          84
+#define BCM281XX_PIN_MDMGPIO4          85
+#define BCM281XX_PIN_MDMGPIO5          86
+#define BCM281XX_PIN_MDMGPIO6          87
+#define BCM281XX_PIN_MDMGPIO7          88
+#define BCM281XX_PIN_MDMGPIO8          89
+#define BCM281XX_PIN_MPHI_DATA_0       90
+#define BCM281XX_PIN_MPHI_DATA_1       91
+#define BCM281XX_PIN_MPHI_DATA_2       92
+#define BCM281XX_PIN_MPHI_DATA_3       93
+#define BCM281XX_PIN_MPHI_DATA_4       94
+#define BCM281XX_PIN_MPHI_DATA_5       95
+#define BCM281XX_PIN_MPHI_DATA_6       96
+#define BCM281XX_PIN_MPHI_DATA_7       97
+#define BCM281XX_PIN_MPHI_DATA_8       98
+#define BCM281XX_PIN_MPHI_DATA_9       99
+#define BCM281XX_PIN_MPHI_DATA_10      100
+#define BCM281XX_PIN_MPHI_DATA_11      101
+#define BCM281XX_PIN_MPHI_DATA_12      102
+#define BCM281XX_PIN_MPHI_DATA_13      103
+#define BCM281XX_PIN_MPHI_DATA_14      104
+#define BCM281XX_PIN_MPHI_DATA_15      105
+#define BCM281XX_PIN_MPHI_HA0          106
+#define BCM281XX_PIN_MPHI_HAT0         107
+#define BCM281XX_PIN_MPHI_HAT1         108
+#define BCM281XX_PIN_MPHI_HCE0_N       109
+#define BCM281XX_PIN_MPHI_HCE1_N       110
+#define BCM281XX_PIN_MPHI_HRD_N                111
+#define BCM281XX_PIN_MPHI_HWR_N                112
+#define BCM281XX_PIN_MPHI_RUN0         113
+#define BCM281XX_PIN_MPHI_RUN1         114
+#define BCM281XX_PIN_MTX_SCAN_CLK      115
+#define BCM281XX_PIN_MTX_SCAN_DATA     116
+#define BCM281XX_PIN_NAND_AD_0         117
+#define BCM281XX_PIN_NAND_AD_1         118
+#define BCM281XX_PIN_NAND_AD_2         119
+#define BCM281XX_PIN_NAND_AD_3         120
+#define BCM281XX_PIN_NAND_AD_4         121
+#define BCM281XX_PIN_NAND_AD_5         122
+#define BCM281XX_PIN_NAND_AD_6         123
+#define BCM281XX_PIN_NAND_AD_7         124
+#define BCM281XX_PIN_NAND_ALE          125
+#define BCM281XX_PIN_NAND_CEN_0                126
+#define BCM281XX_PIN_NAND_CEN_1                127
+#define BCM281XX_PIN_NAND_CLE          128
+#define BCM281XX_PIN_NAND_OEN          129
+#define BCM281XX_PIN_NAND_RDY_0                130
+#define BCM281XX_PIN_NAND_RDY_1                131
+#define BCM281XX_PIN_NAND_WEN          132
+#define BCM281XX_PIN_NAND_WP           133
+#define BCM281XX_PIN_PC1               134
+#define BCM281XX_PIN_PC2               135
+#define BCM281XX_PIN_PMU_INT           136
+#define BCM281XX_PIN_PMU_SCL           137
+#define BCM281XX_PIN_PMU_SDA           138
+#define BCM281XX_PIN_RFST2G_MTSLOTEN3G 139
+#define BCM281XX_PIN_RGMII_0_RX_CTL    140
+#define BCM281XX_PIN_RGMII_0_RXC       141
+#define BCM281XX_PIN_RGMII_0_RXD_0     142
+#define BCM281XX_PIN_RGMII_0_RXD_1     143
+#define BCM281XX_PIN_RGMII_0_RXD_2     144
+#define BCM281XX_PIN_RGMII_0_RXD_3     145
+#define BCM281XX_PIN_RGMII_0_TX_CTL    146
+#define BCM281XX_PIN_RGMII_0_TXC       147
+#define BCM281XX_PIN_RGMII_0_TXD_0     148
+#define BCM281XX_PIN_RGMII_0_TXD_1     149
+#define BCM281XX_PIN_RGMII_0_TXD_2     150
+#define BCM281XX_PIN_RGMII_0_TXD_3     151
+#define BCM281XX_PIN_RGMII_1_RX_CTL    152
+#define BCM281XX_PIN_RGMII_1_RXC       153
+#define BCM281XX_PIN_RGMII_1_RXD_0     154
+#define BCM281XX_PIN_RGMII_1_RXD_1     155
+#define BCM281XX_PIN_RGMII_1_RXD_2     156
+#define BCM281XX_PIN_RGMII_1_RXD_3     157
+#define BCM281XX_PIN_RGMII_1_TX_CTL    158
+#define BCM281XX_PIN_RGMII_1_TXC       159
+#define BCM281XX_PIN_RGMII_1_TXD_0     160
+#define BCM281XX_PIN_RGMII_1_TXD_1     161
+#define BCM281XX_PIN_RGMII_1_TXD_2     162
+#define BCM281XX_PIN_RGMII_1_TXD_3     163
+#define BCM281XX_PIN_RGMII_GPIO_0      164
+#define BCM281XX_PIN_RGMII_GPIO_1      165
+#define BCM281XX_PIN_RGMII_GPIO_2      166
+#define BCM281XX_PIN_RGMII_GPIO_3      167
+#define BCM281XX_PIN_RTXDATA2G_TXDATA3G1       168
+#define BCM281XX_PIN_RTXEN2G_TXDATA3G2 169
+#define BCM281XX_PIN_RXDATA3G0         170
+#define BCM281XX_PIN_RXDATA3G1         171
+#define BCM281XX_PIN_RXDATA3G2         172
+#define BCM281XX_PIN_SDIO1_CLK         173
+#define BCM281XX_PIN_SDIO1_CMD         174
+#define BCM281XX_PIN_SDIO1_DATA_0      175
+#define BCM281XX_PIN_SDIO1_DATA_1      176
+#define BCM281XX_PIN_SDIO1_DATA_2      177
+#define BCM281XX_PIN_SDIO1_DATA_3      178
+#define BCM281XX_PIN_SDIO4_CLK         179
+#define BCM281XX_PIN_SDIO4_CMD         180
+#define BCM281XX_PIN_SDIO4_DATA_0      181
+#define BCM281XX_PIN_SDIO4_DATA_1      182
+#define BCM281XX_PIN_SDIO4_DATA_2      183
+#define BCM281XX_PIN_SDIO4_DATA_3      184
+#define BCM281XX_PIN_SIM_CLK           185
+#define BCM281XX_PIN_SIM_DATA          186
+#define BCM281XX_PIN_SIM_DET           187
+#define BCM281XX_PIN_SIM_RESETN                188
+#define BCM281XX_PIN_SIM2_CLK          189
+#define BCM281XX_PIN_SIM2_DATA         190
+#define BCM281XX_PIN_SIM2_DET          191
+#define BCM281XX_PIN_SIM2_RESETN       192
+#define BCM281XX_PIN_SRI_C             193
+#define BCM281XX_PIN_SRI_D             194
+#define BCM281XX_PIN_SRI_E             195
+#define BCM281XX_PIN_SSP_EXTCLK                196
+#define BCM281XX_PIN_SSP0_CLK          197
+#define BCM281XX_PIN_SSP0_FS           198
+#define BCM281XX_PIN_SSP0_RXD          199
+#define BCM281XX_PIN_SSP0_TXD          200
+#define BCM281XX_PIN_SSP2_CLK          201
+#define BCM281XX_PIN_SSP2_FS_0         202
+#define BCM281XX_PIN_SSP2_FS_1         203
+#define BCM281XX_PIN_SSP2_FS_2         204
+#define BCM281XX_PIN_SSP2_FS_3         205
+#define BCM281XX_PIN_SSP2_RXD_0                206
+#define BCM281XX_PIN_SSP2_RXD_1                207
+#define BCM281XX_PIN_SSP2_TXD_0                208
+#define BCM281XX_PIN_SSP2_TXD_1                209
+#define BCM281XX_PIN_SSP3_CLK          210
+#define BCM281XX_PIN_SSP3_FS           211
+#define BCM281XX_PIN_SSP3_RXD          212
+#define BCM281XX_PIN_SSP3_TXD          213
+#define BCM281XX_PIN_SSP4_CLK          214
+#define BCM281XX_PIN_SSP4_FS           215
+#define BCM281XX_PIN_SSP4_RXD          216
+#define BCM281XX_PIN_SSP4_TXD          217
+#define BCM281XX_PIN_SSP5_CLK          218
+#define BCM281XX_PIN_SSP5_FS           219
+#define BCM281XX_PIN_SSP5_RXD          220
+#define BCM281XX_PIN_SSP5_TXD          221
+#define BCM281XX_PIN_SSP6_CLK          222
+#define BCM281XX_PIN_SSP6_FS           223
+#define BCM281XX_PIN_SSP6_RXD          224
+#define BCM281XX_PIN_SSP6_TXD          225
+#define BCM281XX_PIN_STAT_1            226
+#define BCM281XX_PIN_STAT_2            227
+#define BCM281XX_PIN_SYSCLKEN          228
+#define BCM281XX_PIN_TRACECLK          229
+#define BCM281XX_PIN_TRACEDT00         230
+#define BCM281XX_PIN_TRACEDT01         231
+#define BCM281XX_PIN_TRACEDT02         232
+#define BCM281XX_PIN_TRACEDT03         233
+#define BCM281XX_PIN_TRACEDT04         234
+#define BCM281XX_PIN_TRACEDT05         235
+#define BCM281XX_PIN_TRACEDT06         236
+#define BCM281XX_PIN_TRACEDT07         237
+#define BCM281XX_PIN_TRACEDT08         238
+#define BCM281XX_PIN_TRACEDT09         239
+#define BCM281XX_PIN_TRACEDT10         240
+#define BCM281XX_PIN_TRACEDT11         241
+#define BCM281XX_PIN_TRACEDT12         242
+#define BCM281XX_PIN_TRACEDT13         243
+#define BCM281XX_PIN_TRACEDT14         244
+#define BCM281XX_PIN_TRACEDT15         245
+#define BCM281XX_PIN_TXDATA3G0         246
+#define BCM281XX_PIN_TXPWRIND          247
+#define BCM281XX_PIN_UARTB1_UCTS       248
+#define BCM281XX_PIN_UARTB1_URTS       249
+#define BCM281XX_PIN_UARTB1_URXD       250
+#define BCM281XX_PIN_UARTB1_UTXD       251
+#define BCM281XX_PIN_UARTB2_URXD       252
+#define BCM281XX_PIN_UARTB2_UTXD       253
+#define BCM281XX_PIN_UARTB3_UCTS       254
+#define BCM281XX_PIN_UARTB3_URTS       255
+#define BCM281XX_PIN_UARTB3_URXD       256
+#define BCM281XX_PIN_UARTB3_UTXD       257
+#define BCM281XX_PIN_UARTB4_UCTS       258
+#define BCM281XX_PIN_UARTB4_URTS       259
+#define BCM281XX_PIN_UARTB4_URXD       260
+#define BCM281XX_PIN_UARTB4_UTXD       261
+#define BCM281XX_PIN_VC_CAM1_SCL       262
+#define BCM281XX_PIN_VC_CAM1_SDA       263
+#define BCM281XX_PIN_VC_CAM2_SCL       264
+#define BCM281XX_PIN_VC_CAM2_SDA       265
+#define BCM281XX_PIN_VC_CAM3_SCL       266
+#define BCM281XX_PIN_VC_CAM3_SDA       267
+
+#define BCM281XX_PIN_DESC(a, b, c) \
+       { .number = a, .name = b, .drv_data = &c##_pin }
+
+/*
+ * Pin description definition.  The order here must be the same as defined in
+ * the PADCTRLREG block in the RDB, since the pin number is used as an index
+ * into this array.
+ */
+static const struct pinctrl_pin_desc bcm281xx_pinctrl_pins[] = {
+       BCM281XX_PIN_DESC(BCM281XX_PIN_ADCSYNC, "adcsync", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_BAT_RM, "bat_rm", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_BSC1_SCL, "bsc1_scl", i2c),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_BSC1_SDA, "bsc1_sda", i2c),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_BSC2_SCL, "bsc2_scl", i2c),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_BSC2_SDA, "bsc2_sda", i2c),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_CLASSGPWR, "classgpwr", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_CLK_CX8, "clk_cx8", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_0, "clkout_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_1, "clkout_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_2, "clkout_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_3, "clkout_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_CLKREQ_IN_0, "clkreq_in_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_CLKREQ_IN_1, "clkreq_in_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_CWS_SYS_REQ1, "cws_sys_req1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_CWS_SYS_REQ2, "cws_sys_req2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_CWS_SYS_REQ3, "cws_sys_req3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC1_CLK, "digmic1_clk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC1_DQ, "digmic1_dq", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC2_CLK, "digmic2_clk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC2_DQ, "digmic2_dq", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPEN13, "gpen13", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPEN14, "gpen14", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPEN15, "gpen15", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO00, "gpio00", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO01, "gpio01", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO02, "gpio02", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO03, "gpio03", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO04, "gpio04", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO05, "gpio05", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO06, "gpio06", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO07, "gpio07", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO08, "gpio08", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO09, "gpio09", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO10, "gpio10", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO11, "gpio11", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO12, "gpio12", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO13, "gpio13", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO14, "gpio14", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPS_PABLANK, "gps_pablank", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_GPS_TMARK, "gps_tmark", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_HDMI_SCL, "hdmi_scl", hdmi),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_HDMI_SDA, "hdmi_sda", hdmi),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_IC_DM, "ic_dm", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_IC_DP, "ic_dp", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_0, "kp_col_ip_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_1, "kp_col_ip_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_2, "kp_col_ip_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_3, "kp_col_ip_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_0, "kp_row_op_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_1, "kp_row_op_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_2, "kp_row_op_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_3, "kp_row_op_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_0, "lcd_b_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_1, "lcd_b_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_2, "lcd_b_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_3, "lcd_b_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_4, "lcd_b_4", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_5, "lcd_b_5", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_6, "lcd_b_6", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_7, "lcd_b_7", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_0, "lcd_g_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_1, "lcd_g_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_2, "lcd_g_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_3, "lcd_g_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_4, "lcd_g_4", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_5, "lcd_g_5", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_6, "lcd_g_6", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_7, "lcd_g_7", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_HSYNC, "lcd_hsync", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_OE, "lcd_oe", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_PCLK, "lcd_pclk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_0, "lcd_r_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_1, "lcd_r_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_2, "lcd_r_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_3, "lcd_r_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_4, "lcd_r_4", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_5, "lcd_r_5", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_6, "lcd_r_6", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_7, "lcd_r_7", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_VSYNC, "lcd_vsync", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO0, "mdmgpio0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO1, "mdmgpio1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO2, "mdmgpio2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO3, "mdmgpio3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO4, "mdmgpio4", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO5, "mdmgpio5", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO6, "mdmgpio6", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO7, "mdmgpio7", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO8, "mdmgpio8", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_0, "mphi_data_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_1, "mphi_data_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_2, "mphi_data_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_3, "mphi_data_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_4, "mphi_data_4", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_5, "mphi_data_5", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_6, "mphi_data_6", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_7, "mphi_data_7", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_8, "mphi_data_8", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_9, "mphi_data_9", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_10, "mphi_data_10", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_11, "mphi_data_11", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_12, "mphi_data_12", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_13, "mphi_data_13", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_14, "mphi_data_14", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_15, "mphi_data_15", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HA0, "mphi_ha0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HAT0, "mphi_hat0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HAT1, "mphi_hat1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HCE0_N, "mphi_hce0_n", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HCE1_N, "mphi_hce1_n", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HRD_N, "mphi_hrd_n", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HWR_N, "mphi_hwr_n", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_RUN0, "mphi_run0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_RUN1, "mphi_run1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MTX_SCAN_CLK, "mtx_scan_clk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_MTX_SCAN_DATA, "mtx_scan_data", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_0, "nand_ad_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_1, "nand_ad_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_2, "nand_ad_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_3, "nand_ad_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_4, "nand_ad_4", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_5, "nand_ad_5", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_6, "nand_ad_6", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_7, "nand_ad_7", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_ALE, "nand_ale", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_CEN_0, "nand_cen_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_CEN_1, "nand_cen_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_CLE, "nand_cle", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_OEN, "nand_oen", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_RDY_0, "nand_rdy_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_RDY_1, "nand_rdy_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_WEN, "nand_wen", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_WP, "nand_wp", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_PC1, "pc1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_PC2, "pc2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_PMU_INT, "pmu_int", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_PMU_SCL, "pmu_scl", i2c),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_PMU_SDA, "pmu_sda", i2c),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RFST2G_MTSLOTEN3G, "rfst2g_mtsloten3g",
+               std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RX_CTL, "rgmii_0_rx_ctl", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXC, "rgmii_0_rxc", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_0, "rgmii_0_rxd_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_1, "rgmii_0_rxd_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_2, "rgmii_0_rxd_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_3, "rgmii_0_rxd_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TX_CTL, "rgmii_0_tx_ctl", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXC, "rgmii_0_txc", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_0, "rgmii_0_txd_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_1, "rgmii_0_txd_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_2, "rgmii_0_txd_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_3, "rgmii_0_txd_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RX_CTL, "rgmii_1_rx_ctl", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXC, "rgmii_1_rxc", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_0, "rgmii_1_rxd_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_1, "rgmii_1_rxd_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_2, "rgmii_1_rxd_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_3, "rgmii_1_rxd_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TX_CTL, "rgmii_1_tx_ctl", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXC, "rgmii_1_txc", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_0, "rgmii_1_txd_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_1, "rgmii_1_txd_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_2, "rgmii_1_txd_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_3, "rgmii_1_txd_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_0, "rgmii_gpio_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_1, "rgmii_gpio_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_2, "rgmii_gpio_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_3, "rgmii_gpio_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RTXDATA2G_TXDATA3G1,
+               "rtxdata2g_txdata3g1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RTXEN2G_TXDATA3G2, "rtxen2g_txdata3g2",
+               std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RXDATA3G0, "rxdata3g0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RXDATA3G1, "rxdata3g1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_RXDATA3G2, "rxdata3g2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_CLK, "sdio1_clk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_CMD, "sdio1_cmd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_0, "sdio1_data_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_1, "sdio1_data_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_2, "sdio1_data_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_3, "sdio1_data_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_CLK, "sdio4_clk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_CMD, "sdio4_cmd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_0, "sdio4_data_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_1, "sdio4_data_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_2, "sdio4_data_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_3, "sdio4_data_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_CLK, "sim_clk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_DATA, "sim_data", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_DET, "sim_det", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_RESETN, "sim_resetn", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_CLK, "sim2_clk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_DATA, "sim2_data", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_DET, "sim2_det", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_RESETN, "sim2_resetn", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SRI_C, "sri_c", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SRI_D, "sri_d", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SRI_E, "sri_e", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP_EXTCLK, "ssp_extclk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_CLK, "ssp0_clk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_FS, "ssp0_fs", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_RXD, "ssp0_rxd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_TXD, "ssp0_txd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_CLK, "ssp2_clk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_0, "ssp2_fs_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_1, "ssp2_fs_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_2, "ssp2_fs_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_3, "ssp2_fs_3", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_RXD_0, "ssp2_rxd_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_RXD_1, "ssp2_rxd_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_TXD_0, "ssp2_txd_0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_TXD_1, "ssp2_txd_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_CLK, "ssp3_clk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_FS, "ssp3_fs", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_RXD, "ssp3_rxd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_TXD, "ssp3_txd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_CLK, "ssp4_clk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_FS, "ssp4_fs", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_RXD, "ssp4_rxd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_TXD, "ssp4_txd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_CLK, "ssp5_clk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_FS, "ssp5_fs", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_RXD, "ssp5_rxd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_TXD, "ssp5_txd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_CLK, "ssp6_clk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_FS, "ssp6_fs", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_RXD, "ssp6_rxd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_TXD, "ssp6_txd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_STAT_1, "stat_1", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_STAT_2, "stat_2", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_SYSCLKEN, "sysclken", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACECLK, "traceclk", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT00, "tracedt00", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT01, "tracedt01", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT02, "tracedt02", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT03, "tracedt03", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT04, "tracedt04", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT05, "tracedt05", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT06, "tracedt06", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT07, "tracedt07", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT08, "tracedt08", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT09, "tracedt09", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT10, "tracedt10", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT11, "tracedt11", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT12, "tracedt12", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT13, "tracedt13", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT14, "tracedt14", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT15, "tracedt15", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TXDATA3G0, "txdata3g0", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_TXPWRIND, "txpwrind", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_UCTS, "uartb1_ucts", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_URTS, "uartb1_urts", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_URXD, "uartb1_urxd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_UTXD, "uartb1_utxd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB2_URXD, "uartb2_urxd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB2_UTXD, "uartb2_utxd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_UCTS, "uartb3_ucts", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_URTS, "uartb3_urts", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_URXD, "uartb3_urxd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_UTXD, "uartb3_utxd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_UCTS, "uartb4_ucts", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_URTS, "uartb4_urts", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_URXD, "uartb4_urxd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_UTXD, "uartb4_utxd", std),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM1_SCL, "vc_cam1_scl", i2c),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM1_SDA, "vc_cam1_sda", i2c),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM2_SCL, "vc_cam2_scl", i2c),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM2_SDA, "vc_cam2_sda", i2c),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM3_SCL, "vc_cam3_scl", i2c),
+       BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM3_SDA, "vc_cam3_sda", i2c),
+};
+
+static const char * const bcm281xx_alt_groups[] = {
+       "adcsync",
+       "bat_rm",
+       "bsc1_scl",
+       "bsc1_sda",
+       "bsc2_scl",
+       "bsc2_sda",
+       "classgpwr",
+       "clk_cx8",
+       "clkout_0",
+       "clkout_1",
+       "clkout_2",
+       "clkout_3",
+       "clkreq_in_0",
+       "clkreq_in_1",
+       "cws_sys_req1",
+       "cws_sys_req2",
+       "cws_sys_req3",
+       "digmic1_clk",
+       "digmic1_dq",
+       "digmic2_clk",
+       "digmic2_dq",
+       "gpen13",
+       "gpen14",
+       "gpen15",
+       "gpio00",
+       "gpio01",
+       "gpio02",
+       "gpio03",
+       "gpio04",
+       "gpio05",
+       "gpio06",
+       "gpio07",
+       "gpio08",
+       "gpio09",
+       "gpio10",
+       "gpio11",
+       "gpio12",
+       "gpio13",
+       "gpio14",
+       "gps_pablank",
+       "gps_tmark",
+       "hdmi_scl",
+       "hdmi_sda",
+       "ic_dm",
+       "ic_dp",
+       "kp_col_ip_0",
+       "kp_col_ip_1",
+       "kp_col_ip_2",
+       "kp_col_ip_3",
+       "kp_row_op_0",
+       "kp_row_op_1",
+       "kp_row_op_2",
+       "kp_row_op_3",
+       "lcd_b_0",
+       "lcd_b_1",
+       "lcd_b_2",
+       "lcd_b_3",
+       "lcd_b_4",
+       "lcd_b_5",
+       "lcd_b_6",
+       "lcd_b_7",
+       "lcd_g_0",
+       "lcd_g_1",
+       "lcd_g_2",
+       "lcd_g_3",
+       "lcd_g_4",
+       "lcd_g_5",
+       "lcd_g_6",
+       "lcd_g_7",
+       "lcd_hsync",
+       "lcd_oe",
+       "lcd_pclk",
+       "lcd_r_0",
+       "lcd_r_1",
+       "lcd_r_2",
+       "lcd_r_3",
+       "lcd_r_4",
+       "lcd_r_5",
+       "lcd_r_6",
+       "lcd_r_7",
+       "lcd_vsync",
+       "mdmgpio0",
+       "mdmgpio1",
+       "mdmgpio2",
+       "mdmgpio3",
+       "mdmgpio4",
+       "mdmgpio5",
+       "mdmgpio6",
+       "mdmgpio7",
+       "mdmgpio8",
+       "mphi_data_0",
+       "mphi_data_1",
+       "mphi_data_2",
+       "mphi_data_3",
+       "mphi_data_4",
+       "mphi_data_5",
+       "mphi_data_6",
+       "mphi_data_7",
+       "mphi_data_8",
+       "mphi_data_9",
+       "mphi_data_10",
+       "mphi_data_11",
+       "mphi_data_12",
+       "mphi_data_13",
+       "mphi_data_14",
+       "mphi_data_15",
+       "mphi_ha0",
+       "mphi_hat0",
+       "mphi_hat1",
+       "mphi_hce0_n",
+       "mphi_hce1_n",
+       "mphi_hrd_n",
+       "mphi_hwr_n",
+       "mphi_run0",
+       "mphi_run1",
+       "mtx_scan_clk",
+       "mtx_scan_data",
+       "nand_ad_0",
+       "nand_ad_1",
+       "nand_ad_2",
+       "nand_ad_3",
+       "nand_ad_4",
+       "nand_ad_5",
+       "nand_ad_6",
+       "nand_ad_7",
+       "nand_ale",
+       "nand_cen_0",
+       "nand_cen_1",
+       "nand_cle",
+       "nand_oen",
+       "nand_rdy_0",
+       "nand_rdy_1",
+       "nand_wen",
+       "nand_wp",
+       "pc1",
+       "pc2",
+       "pmu_int",
+       "pmu_scl",
+       "pmu_sda",
+       "rfst2g_mtsloten3g",
+       "rgmii_0_rx_ctl",
+       "rgmii_0_rxc",
+       "rgmii_0_rxd_0",
+       "rgmii_0_rxd_1",
+       "rgmii_0_rxd_2",
+       "rgmii_0_rxd_3",
+       "rgmii_0_tx_ctl",
+       "rgmii_0_txc",
+       "rgmii_0_txd_0",
+       "rgmii_0_txd_1",
+       "rgmii_0_txd_2",
+       "rgmii_0_txd_3",
+       "rgmii_1_rx_ctl",
+       "rgmii_1_rxc",
+       "rgmii_1_rxd_0",
+       "rgmii_1_rxd_1",
+       "rgmii_1_rxd_2",
+       "rgmii_1_rxd_3",
+       "rgmii_1_tx_ctl",
+       "rgmii_1_txc",
+       "rgmii_1_txd_0",
+       "rgmii_1_txd_1",
+       "rgmii_1_txd_2",
+       "rgmii_1_txd_3",
+       "rgmii_gpio_0",
+       "rgmii_gpio_1",
+       "rgmii_gpio_2",
+       "rgmii_gpio_3",
+       "rtxdata2g_txdata3g1",
+       "rtxen2g_txdata3g2",
+       "rxdata3g0",
+       "rxdata3g1",
+       "rxdata3g2",
+       "sdio1_clk",
+       "sdio1_cmd",
+       "sdio1_data_0",
+       "sdio1_data_1",
+       "sdio1_data_2",
+       "sdio1_data_3",
+       "sdio4_clk",
+       "sdio4_cmd",
+       "sdio4_data_0",
+       "sdio4_data_1",
+       "sdio4_data_2",
+       "sdio4_data_3",
+       "sim_clk",
+       "sim_data",
+       "sim_det",
+       "sim_resetn",
+       "sim2_clk",
+       "sim2_data",
+       "sim2_det",
+       "sim2_resetn",
+       "sri_c",
+       "sri_d",
+       "sri_e",
+       "ssp_extclk",
+       "ssp0_clk",
+       "ssp0_fs",
+       "ssp0_rxd",
+       "ssp0_txd",
+       "ssp2_clk",
+       "ssp2_fs_0",
+       "ssp2_fs_1",
+       "ssp2_fs_2",
+       "ssp2_fs_3",
+       "ssp2_rxd_0",
+       "ssp2_rxd_1",
+       "ssp2_txd_0",
+       "ssp2_txd_1",
+       "ssp3_clk",
+       "ssp3_fs",
+       "ssp3_rxd",
+       "ssp3_txd",
+       "ssp4_clk",
+       "ssp4_fs",
+       "ssp4_rxd",
+       "ssp4_txd",
+       "ssp5_clk",
+       "ssp5_fs",
+       "ssp5_rxd",
+       "ssp5_txd",
+       "ssp6_clk",
+       "ssp6_fs",
+       "ssp6_rxd",
+       "ssp6_txd",
+       "stat_1",
+       "stat_2",
+       "sysclken",
+       "traceclk",
+       "tracedt00",
+       "tracedt01",
+       "tracedt02",
+       "tracedt03",
+       "tracedt04",
+       "tracedt05",
+       "tracedt06",
+       "tracedt07",
+       "tracedt08",
+       "tracedt09",
+       "tracedt10",
+       "tracedt11",
+       "tracedt12",
+       "tracedt13",
+       "tracedt14",
+       "tracedt15",
+       "txdata3g0",
+       "txpwrind",
+       "uartb1_ucts",
+       "uartb1_urts",
+       "uartb1_urxd",
+       "uartb1_utxd",
+       "uartb2_urxd",
+       "uartb2_utxd",
+       "uartb3_ucts",
+       "uartb3_urts",
+       "uartb3_urxd",
+       "uartb3_utxd",
+       "uartb4_ucts",
+       "uartb4_urts",
+       "uartb4_urxd",
+       "uartb4_utxd",
+       "vc_cam1_scl",
+       "vc_cam1_sda",
+       "vc_cam2_scl",
+       "vc_cam2_sda",
+       "vc_cam3_scl",
+       "vc_cam3_sda",
+};
+
+/* Every pin can implement all ALT1-ALT4 functions */
+#define BCM281XX_PIN_FUNCTION(fcn_name)                        \
+{                                                      \
+       .name = #fcn_name,                              \
+       .groups = bcm281xx_alt_groups,                  \
+       .ngroups = ARRAY_SIZE(bcm281xx_alt_groups),     \
+}
+
+static const struct bcm281xx_pin_function bcm281xx_functions[] = {
+       BCM281XX_PIN_FUNCTION(alt1),
+       BCM281XX_PIN_FUNCTION(alt2),
+       BCM281XX_PIN_FUNCTION(alt3),
+       BCM281XX_PIN_FUNCTION(alt4),
+};
+
+static struct bcm281xx_pinctrl_data bcm281xx_pinctrl = {
+       .pins = bcm281xx_pinctrl_pins,
+       .npins = ARRAY_SIZE(bcm281xx_pinctrl_pins),
+       .functions = bcm281xx_functions,
+       .nfunctions = ARRAY_SIZE(bcm281xx_functions),
+};
+
+static inline enum bcm281xx_pin_type pin_type_get(struct pinctrl_dev *pctldev,
+                                                 unsigned pin)
+{
+       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+       if (pin >= pdata->npins)
+               return BCM281XX_PIN_TYPE_UNKNOWN;
+
+       return *(enum bcm281xx_pin_type *)(pdata->pins[pin].drv_data);
+}
+
+#define BCM281XX_PIN_SHIFT(type, param) \
+       (BCM281XX_ ## type ## _PIN_REG_ ## param ## _SHIFT)
+
+#define BCM281XX_PIN_MASK(type, param) \
+       (BCM281XX_ ## type ## _PIN_REG_ ## param ## _MASK)
+
+/*
+ * This helper function is used to build up the value and mask used to write to
+ * a pin register, but does not actually write to the register.
+ */
+static inline void bcm281xx_pin_update(u32 *reg_val, u32 *reg_mask,
+                                      u32 param_val, u32 param_shift,
+                                      u32 param_mask)
+{
+       *reg_val &= ~param_mask;
+       *reg_val |= (param_val << param_shift) & param_mask;
+       *reg_mask |= param_mask;
+}
+
+static const struct regmap_config bcm281xx_pinctrl_regmap_config = {
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .max_register = BCM281XX_PIN_VC_CAM3_SDA,
+};
+
+static int bcm281xx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+       return pdata->npins;
+}
+
+static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+                                                  unsigned group)
+{
+       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+       return pdata->pins[group].name;
+}
+
+static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+                                          unsigned group,
+                                          const unsigned **pins,
+                                          unsigned *num_pins)
+{
+       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+       *pins = &pdata->pins[group].number;
+       *num_pins = 1;
+
+       return 0;
+}
+
+static void bcm281xx_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
+                                         struct seq_file *s,
+                                         unsigned offset)
+{
+       seq_printf(s, " %s", dev_name(pctldev->dev));
+}
+
+static struct pinctrl_ops bcm281xx_pinctrl_ops = {
+       .get_groups_count = bcm281xx_pinctrl_get_groups_count,
+       .get_group_name = bcm281xx_pinctrl_get_group_name,
+       .get_group_pins = bcm281xx_pinctrl_get_group_pins,
+       .pin_dbg_show = bcm281xx_pinctrl_pin_dbg_show,
+       .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+       .dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int bcm281xx_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev)
+{
+       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+       return pdata->nfunctions;
+}
+
+static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
+                                                unsigned function)
+{
+       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+       return pdata->functions[function].name;
+}
+
+static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
+                                          unsigned function,
+                                          const char * const **groups,
+                                          unsigned * const num_groups)
+{
+       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+       *groups = pdata->functions[function].groups;
+       *num_groups = pdata->functions[function].ngroups;
+
+       return 0;
+}
+
+static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev,
+                              unsigned function,
+                              unsigned group)
+{
+       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+       const struct bcm281xx_pin_function *f = &pdata->functions[function];
+       u32 offset = 4 * pdata->pins[group].number;
+       int rc = 0;
+
+       dev_dbg(pctldev->dev,
+               "%s(): Enable function %s (%d) of pin %s (%d) @offset 0x%x.\n",
+               __func__, f->name, function, pdata->pins[group].name,
+               pdata->pins[group].number, offset);
+
+       rc = regmap_update_bits(pdata->regmap, offset,
+               BCM281XX_PIN_REG_F_SEL_MASK,
+               function << BCM281XX_PIN_REG_F_SEL_SHIFT);
+       if (rc)
+               dev_err(pctldev->dev,
+                       "Error updating register for pin %s (%d).\n",
+                       pdata->pins[group].name, pdata->pins[group].number);
+
+       return rc;
+}
+
+static struct pinmux_ops bcm281xx_pinctrl_pinmux_ops = {
+       .get_functions_count = bcm281xx_pinctrl_get_fcns_count,
+       .get_function_name = bcm281xx_pinctrl_get_fcn_name,
+       .get_function_groups = bcm281xx_pinctrl_get_fcn_groups,
+       .set_mux = bcm281xx_pinmux_set,
+};
+
+static int bcm281xx_pinctrl_pin_config_get(struct pinctrl_dev *pctldev,
+                                          unsigned pin,
+                                          unsigned long *config)
+{
+       return -ENOTSUPP;
+}
+
+
+/* Goes through the configs and update register val/mask */
+static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev,
+                                  unsigned pin,
+                                  unsigned long *configs,
+                                  unsigned num_configs,
+                                  u32 *val,
+                                  u32 *mask)
+{
+       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+       int i;
+       enum pin_config_param param;
+       u16 arg;
+
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
+               arg = pinconf_to_config_argument(configs[i]);
+
+               switch (param) {
+               case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+                       arg = (arg >= 1 ? 1 : 0);
+                       bcm281xx_pin_update(val, mask, arg,
+                               BCM281XX_PIN_SHIFT(STD, HYST),
+                               BCM281XX_PIN_MASK(STD, HYST));
+                       break;
+               /*
+                * The pin bias can only be one of pull-up, pull-down, or
+                * disable.  The user does not need to specify a value for the
+                * property, and the default value from pinconf-generic is
+                * ignored.
+                */
+               case PIN_CONFIG_BIAS_DISABLE:
+                       bcm281xx_pin_update(val, mask, 0,
+                               BCM281XX_PIN_SHIFT(STD, PULL_UP),
+                               BCM281XX_PIN_MASK(STD, PULL_UP));
+                       bcm281xx_pin_update(val, mask, 0,
+                               BCM281XX_PIN_SHIFT(STD, PULL_DN),
+                               BCM281XX_PIN_MASK(STD, PULL_DN));
+                       break;
+
+               case PIN_CONFIG_BIAS_PULL_UP:
+                       bcm281xx_pin_update(val, mask, 1,
+                               BCM281XX_PIN_SHIFT(STD, PULL_UP),
+                               BCM281XX_PIN_MASK(STD, PULL_UP));
+                       bcm281xx_pin_update(val, mask, 0,
+                               BCM281XX_PIN_SHIFT(STD, PULL_DN),
+                               BCM281XX_PIN_MASK(STD, PULL_DN));
+                       break;
+
+               case PIN_CONFIG_BIAS_PULL_DOWN:
+                       bcm281xx_pin_update(val, mask, 0,
+                               BCM281XX_PIN_SHIFT(STD, PULL_UP),
+                               BCM281XX_PIN_MASK(STD, PULL_UP));
+                       bcm281xx_pin_update(val, mask, 1,
+                               BCM281XX_PIN_SHIFT(STD, PULL_DN),
+                               BCM281XX_PIN_MASK(STD, PULL_DN));
+                       break;
+
+               case PIN_CONFIG_SLEW_RATE:
+                       arg = (arg >= 1 ? 1 : 0);
+                       bcm281xx_pin_update(val, mask, arg,
+                               BCM281XX_PIN_SHIFT(STD, SLEW),
+                               BCM281XX_PIN_MASK(STD, SLEW));
+                       break;
+
+               case PIN_CONFIG_INPUT_ENABLE:
+                       /* inversed since register is for input _disable_ */
+                       arg = (arg >= 1 ? 0 : 1);
+                       bcm281xx_pin_update(val, mask, arg,
+                               BCM281XX_PIN_SHIFT(STD, INPUT_DIS),
+                               BCM281XX_PIN_MASK(STD, INPUT_DIS));
+                       break;
+
+               case PIN_CONFIG_DRIVE_STRENGTH:
+                       /* Valid range is 2-16 mA, even numbers only */
+                       if ((arg < 2) || (arg > 16) || (arg % 2)) {
+                               dev_err(pctldev->dev,
+                                       "Invalid Drive Strength value (%d) for "
+                                       "pin %s (%d). Valid values are "
+                                       "(2..16) mA, even numbers only.\n",
+                                       arg, pdata->pins[pin].name, pin);
+                               return -EINVAL;
+                       }
+                       bcm281xx_pin_update(val, mask, (arg/2)-1,
+                               BCM281XX_PIN_SHIFT(STD, DRV_STR),
+                               BCM281XX_PIN_MASK(STD, DRV_STR));
+                       break;
+
+               default:
+                       dev_err(pctldev->dev,
+                               "Unrecognized pin config %d for pin %s (%d).\n",
+                               param, pdata->pins[pin].name, pin);
+                       return -EINVAL;
+
+               } /* switch config */
+       } /* for each config */
+
+       return 0;
+}
+
+/*
+ * The pull-up strength for an I2C pin is represented by bits 4-6 in the
+ * register with the following mapping:
+ *   0b000: No pull-up
+ *   0b001: 1200 Ohm
+ *   0b010: 1800 Ohm
+ *   0b011: 720 Ohm
+ *   0b100: 2700 Ohm
+ *   0b101: 831 Ohm
+ *   0b110: 1080 Ohm
+ *   0b111: 568 Ohm
+ * This array maps pull-up strength in Ohms to register values (1+index).
+ */
+static const u16 bcm281xx_pullup_map[] = {
+       1200, 1800, 720, 2700, 831, 1080, 568
+};
+
+/* Goes through the configs and update register val/mask */
+static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
+                                  unsigned pin,
+                                  unsigned long *configs,
+                                  unsigned num_configs,
+                                  u32 *val,
+                                  u32 *mask)
+{
+       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+       int i, j;
+       enum pin_config_param param;
+       u16 arg;
+
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
+               arg = pinconf_to_config_argument(configs[i]);
+
+               switch (param) {
+               case PIN_CONFIG_BIAS_PULL_UP:
+                       for (j = 0; j < ARRAY_SIZE(bcm281xx_pullup_map); j++)
+                               if (bcm281xx_pullup_map[j] == arg)
+                                       break;
+
+                       if (j == ARRAY_SIZE(bcm281xx_pullup_map)) {
+                               dev_err(pctldev->dev,
+                                       "Invalid pull-up value (%d) for pin %s "
+                                       "(%d). Valid values are 568, 720, 831, "
+                                       "1080, 1200, 1800, 2700 Ohms.\n",
+                                       arg, pdata->pins[pin].name, pin);
+                               return -EINVAL;
+                       }
+
+                       bcm281xx_pin_update(val, mask, j+1,
+                               BCM281XX_PIN_SHIFT(I2C, PULL_UP_STR),
+                               BCM281XX_PIN_MASK(I2C, PULL_UP_STR));
+                       break;
+
+               case PIN_CONFIG_BIAS_DISABLE:
+                       bcm281xx_pin_update(val, mask, 0,
+                               BCM281XX_PIN_SHIFT(I2C, PULL_UP_STR),
+                               BCM281XX_PIN_MASK(I2C, PULL_UP_STR));
+                       break;
+
+               case PIN_CONFIG_SLEW_RATE:
+                       arg = (arg >= 1 ? 1 : 0);
+                       bcm281xx_pin_update(val, mask, arg,
+                               BCM281XX_PIN_SHIFT(I2C, SLEW),
+                               BCM281XX_PIN_MASK(I2C, SLEW));
+                       break;
+
+               case PIN_CONFIG_INPUT_ENABLE:
+                       /* inversed since register is for input _disable_ */
+                       arg = (arg >= 1 ? 0 : 1);
+                       bcm281xx_pin_update(val, mask, arg,
+                               BCM281XX_PIN_SHIFT(I2C, INPUT_DIS),
+                               BCM281XX_PIN_MASK(I2C, INPUT_DIS));
+                       break;
+
+               default:
+                       dev_err(pctldev->dev,
+                               "Unrecognized pin config %d for pin %s (%d).\n",
+                               param, pdata->pins[pin].name, pin);
+                       return -EINVAL;
+
+               } /* switch config */
+       } /* for each config */
+
+       return 0;
+}
+
+/* Goes through the configs and update register val/mask */
+static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev,
+                                   unsigned pin,
+                                   unsigned long *configs,
+                                   unsigned num_configs,
+                                   u32 *val,
+                                   u32 *mask)
+{
+       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+       int i;
+       enum pin_config_param param;
+       u16 arg;
+
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
+               arg = pinconf_to_config_argument(configs[i]);
+
+               switch (param) {
+               case PIN_CONFIG_SLEW_RATE:
+                       arg = (arg >= 1 ? 1 : 0);
+                       bcm281xx_pin_update(val, mask, arg,
+                               BCM281XX_PIN_SHIFT(HDMI, MODE),
+                               BCM281XX_PIN_MASK(HDMI, MODE));
+                       break;
+
+               case PIN_CONFIG_INPUT_ENABLE:
+                       /* inversed since register is for input _disable_ */
+                       arg = (arg >= 1 ? 0 : 1);
+                       bcm281xx_pin_update(val, mask, arg,
+                               BCM281XX_PIN_SHIFT(HDMI, INPUT_DIS),
+                               BCM281XX_PIN_MASK(HDMI, INPUT_DIS));
+                       break;
+
+               default:
+                       dev_err(pctldev->dev,
+                               "Unrecognized pin config %d for pin %s (%d).\n",
+                               param, pdata->pins[pin].name, pin);
+                       return -EINVAL;
+
+               } /* switch config */
+       } /* for each config */
+
+       return 0;
+}
+
+static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
+                                          unsigned pin,
+                                          unsigned long *configs,
+                                          unsigned num_configs)
+{
+       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+       enum bcm281xx_pin_type pin_type;
+       u32 offset = 4 * pin;
+       u32 cfg_val, cfg_mask;
+       int rc;
+
+       cfg_val = 0;
+       cfg_mask = 0;
+       pin_type = pin_type_get(pctldev, pin);
+
+       /* Different pins have different configuration options */
+       switch (pin_type) {
+       case BCM281XX_PIN_TYPE_STD:
+               rc = bcm281xx_std_pin_update(pctldev, pin, configs,
+                       num_configs, &cfg_val, &cfg_mask);
+               break;
+
+       case BCM281XX_PIN_TYPE_I2C:
+               rc = bcm281xx_i2c_pin_update(pctldev, pin, configs,
+                       num_configs, &cfg_val, &cfg_mask);
+               break;
+
+       case BCM281XX_PIN_TYPE_HDMI:
+               rc = bcm281xx_hdmi_pin_update(pctldev, pin, configs,
+                       num_configs, &cfg_val, &cfg_mask);
+               break;
+
+       default:
+               dev_err(pctldev->dev, "Unknown pin type for pin %s (%d).\n",
+                       pdata->pins[pin].name, pin);
+               return -EINVAL;
+
+       } /* switch pin type */
+
+       if (rc)
+               return rc;
+
+       dev_dbg(pctldev->dev,
+               "%s(): Set pin %s (%d) with config 0x%x, mask 0x%x\n",
+               __func__, pdata->pins[pin].name, pin, cfg_val, cfg_mask);
+
+       rc = regmap_update_bits(pdata->regmap, offset, cfg_mask, cfg_val);
+       if (rc) {
+               dev_err(pctldev->dev,
+                       "Error updating register for pin %s (%d).\n",
+                       pdata->pins[pin].name, pin);
+               return rc;
+       }
+
+       return 0;
+}
+
+static struct pinconf_ops bcm281xx_pinctrl_pinconf_ops = {
+       .pin_config_get = bcm281xx_pinctrl_pin_config_get,
+       .pin_config_set = bcm281xx_pinctrl_pin_config_set,
+};
+
+static struct pinctrl_desc bcm281xx_pinctrl_desc = {
+       /* name, pins, npins members initialized in probe function */
+       .pctlops = &bcm281xx_pinctrl_ops,
+       .pmxops = &bcm281xx_pinctrl_pinmux_ops,
+       .confops = &bcm281xx_pinctrl_pinconf_ops,
+       .owner = THIS_MODULE,
+};
+
+static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
+{
+       struct bcm281xx_pinctrl_data *pdata = &bcm281xx_pinctrl;
+       struct resource *res;
+       struct pinctrl_dev *pctl;
+
+       /* So far We can assume there is only 1 bank of registers */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       pdata->reg_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pdata->reg_base)) {
+               dev_err(&pdev->dev, "Failed to ioremap MEM resource\n");
+               return -ENODEV;
+       }
+
+       /* Initialize the dynamic part of pinctrl_desc */
+       pdata->regmap = devm_regmap_init_mmio(&pdev->dev, pdata->reg_base,
+               &bcm281xx_pinctrl_regmap_config);
+       if (IS_ERR(pdata->regmap)) {
+               dev_err(&pdev->dev, "Regmap MMIO init failed.\n");
+               return -ENODEV;
+       }
+
+       bcm281xx_pinctrl_desc.name = dev_name(&pdev->dev);
+       bcm281xx_pinctrl_desc.pins = bcm281xx_pinctrl.pins;
+       bcm281xx_pinctrl_desc.npins = bcm281xx_pinctrl.npins;
+
+       pctl = pinctrl_register(&bcm281xx_pinctrl_desc,
+                               &pdev->dev,
+                               pdata);
+       if (!pctl) {
+               dev_err(&pdev->dev, "Failed to register pinctrl\n");
+               return -ENODEV;
+       }
+
+       platform_set_drvdata(pdev, pdata);
+
+       return 0;
+}
+
+static const struct of_device_id bcm281xx_pinctrl_of_match[] = {
+       { .compatible = "brcm,bcm11351-pinctrl", },
+       { },
+};
+
+static struct platform_driver bcm281xx_pinctrl_driver = {
+       .driver = {
+               .name = "bcm281xx-pinctrl",
+               .of_match_table = bcm281xx_pinctrl_of_match,
+       },
+};
+
+module_platform_driver_probe(bcm281xx_pinctrl_driver, bcm281xx_pinctrl_probe);
+
+MODULE_AUTHOR("Broadcom Corporation <bcm-kernel-feedback-list@broadcom.com>");
+MODULE_AUTHOR("Sherman Yin <syin@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom BCM281xx pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
new file mode 100644 (file)
index 0000000..8d908e3
--- /dev/null
@@ -0,0 +1,1080 @@
+/*
+ * Driver for Broadcom BCM2835 GPIO unit (pinctrl + GPIO)
+ *
+ * Copyright (C) 2012 Chris Boot, Simon Arlott, Stephen Warren
+ *
+ * This driver is inspired by:
+ * pinctrl-nomadik.c, please see original file for copyright information
+ * pinctrl-tegra.c, please see original file for copyright information
+ *
+ * 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/bitmap.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdesc.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#define MODULE_NAME "pinctrl-bcm2835"
+#define BCM2835_NUM_GPIOS 54
+#define BCM2835_NUM_BANKS 2
+
+#define BCM2835_PIN_BITMAP_SZ \
+       DIV_ROUND_UP(BCM2835_NUM_GPIOS, sizeof(unsigned long) * 8)
+
+/* GPIO register offsets */
+#define GPFSEL0                0x0     /* Function Select */
+#define GPSET0         0x1c    /* Pin Output Set */
+#define GPCLR0         0x28    /* Pin Output Clear */
+#define GPLEV0         0x34    /* Pin Level */
+#define GPEDS0         0x40    /* Pin Event Detect Status */
+#define GPREN0         0x4c    /* Pin Rising Edge Detect Enable */
+#define GPFEN0         0x58    /* Pin Falling Edge Detect Enable */
+#define GPHEN0         0x64    /* Pin High Detect Enable */
+#define GPLEN0         0x70    /* Pin Low Detect Enable */
+#define GPAREN0                0x7c    /* Pin Async Rising Edge Detect */
+#define GPAFEN0                0x88    /* Pin Async Falling Edge Detect */
+#define GPPUD          0x94    /* Pin Pull-up/down Enable */
+#define GPPUDCLK0      0x98    /* Pin Pull-up/down Enable Clock */
+
+#define FSEL_REG(p)            (GPFSEL0 + (((p) / 10) * 4))
+#define FSEL_SHIFT(p)          (((p) % 10) * 3)
+#define GPIO_REG_OFFSET(p)     ((p) / 32)
+#define GPIO_REG_SHIFT(p)      ((p) % 32)
+
+enum bcm2835_pinconf_param {
+       /* argument: bcm2835_pinconf_pull */
+       BCM2835_PINCONF_PARAM_PULL,
+};
+
+enum bcm2835_pinconf_pull {
+       BCM2835_PINCONFIG_PULL_NONE,
+       BCM2835_PINCONFIG_PULL_DOWN,
+       BCM2835_PINCONFIG_PULL_UP,
+};
+
+#define BCM2835_PINCONF_PACK(_param_, _arg_) ((_param_) << 16 | (_arg_))
+#define BCM2835_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16)
+#define BCM2835_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff)
+
+struct bcm2835_gpio_irqdata {
+       struct bcm2835_pinctrl *pc;
+       int bank;
+};
+
+struct bcm2835_pinctrl {
+       struct device *dev;
+       void __iomem *base;
+       int irq[BCM2835_NUM_BANKS];
+
+       /* note: locking assumes each bank will have its own unsigned long */
+       unsigned long enabled_irq_map[BCM2835_NUM_BANKS];
+       unsigned int irq_type[BCM2835_NUM_GPIOS];
+
+       struct pinctrl_dev *pctl_dev;
+       struct irq_domain *irq_domain;
+       struct gpio_chip gpio_chip;
+       struct pinctrl_gpio_range gpio_range;
+
+       struct bcm2835_gpio_irqdata irq_data[BCM2835_NUM_BANKS];
+       spinlock_t irq_lock[BCM2835_NUM_BANKS];
+};
+
+static struct lock_class_key gpio_lock_class;
+
+/* pins are just named GPIO0..GPIO53 */
+#define BCM2835_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
+static struct pinctrl_pin_desc bcm2835_gpio_pins[] = {
+       BCM2835_GPIO_PIN(0),
+       BCM2835_GPIO_PIN(1),
+       BCM2835_GPIO_PIN(2),
+       BCM2835_GPIO_PIN(3),
+       BCM2835_GPIO_PIN(4),
+       BCM2835_GPIO_PIN(5),
+       BCM2835_GPIO_PIN(6),
+       BCM2835_GPIO_PIN(7),
+       BCM2835_GPIO_PIN(8),
+       BCM2835_GPIO_PIN(9),
+       BCM2835_GPIO_PIN(10),
+       BCM2835_GPIO_PIN(11),
+       BCM2835_GPIO_PIN(12),
+       BCM2835_GPIO_PIN(13),
+       BCM2835_GPIO_PIN(14),
+       BCM2835_GPIO_PIN(15),
+       BCM2835_GPIO_PIN(16),
+       BCM2835_GPIO_PIN(17),
+       BCM2835_GPIO_PIN(18),
+       BCM2835_GPIO_PIN(19),
+       BCM2835_GPIO_PIN(20),
+       BCM2835_GPIO_PIN(21),
+       BCM2835_GPIO_PIN(22),
+       BCM2835_GPIO_PIN(23),
+       BCM2835_GPIO_PIN(24),
+       BCM2835_GPIO_PIN(25),
+       BCM2835_GPIO_PIN(26),
+       BCM2835_GPIO_PIN(27),
+       BCM2835_GPIO_PIN(28),
+       BCM2835_GPIO_PIN(29),
+       BCM2835_GPIO_PIN(30),
+       BCM2835_GPIO_PIN(31),
+       BCM2835_GPIO_PIN(32),
+       BCM2835_GPIO_PIN(33),
+       BCM2835_GPIO_PIN(34),
+       BCM2835_GPIO_PIN(35),
+       BCM2835_GPIO_PIN(36),
+       BCM2835_GPIO_PIN(37),
+       BCM2835_GPIO_PIN(38),
+       BCM2835_GPIO_PIN(39),
+       BCM2835_GPIO_PIN(40),
+       BCM2835_GPIO_PIN(41),
+       BCM2835_GPIO_PIN(42),
+       BCM2835_GPIO_PIN(43),
+       BCM2835_GPIO_PIN(44),
+       BCM2835_GPIO_PIN(45),
+       BCM2835_GPIO_PIN(46),
+       BCM2835_GPIO_PIN(47),
+       BCM2835_GPIO_PIN(48),
+       BCM2835_GPIO_PIN(49),
+       BCM2835_GPIO_PIN(50),
+       BCM2835_GPIO_PIN(51),
+       BCM2835_GPIO_PIN(52),
+       BCM2835_GPIO_PIN(53),
+};
+
+/* one pin per group */
+static const char * const bcm2835_gpio_groups[] = {
+       "gpio0",
+       "gpio1",
+       "gpio2",
+       "gpio3",
+       "gpio4",
+       "gpio5",
+       "gpio6",
+       "gpio7",
+       "gpio8",
+       "gpio9",
+       "gpio10",
+       "gpio11",
+       "gpio12",
+       "gpio13",
+       "gpio14",
+       "gpio15",
+       "gpio16",
+       "gpio17",
+       "gpio18",
+       "gpio19",
+       "gpio20",
+       "gpio21",
+       "gpio22",
+       "gpio23",
+       "gpio24",
+       "gpio25",
+       "gpio26",
+       "gpio27",
+       "gpio28",
+       "gpio29",
+       "gpio30",
+       "gpio31",
+       "gpio32",
+       "gpio33",
+       "gpio34",
+       "gpio35",
+       "gpio36",
+       "gpio37",
+       "gpio38",
+       "gpio39",
+       "gpio40",
+       "gpio41",
+       "gpio42",
+       "gpio43",
+       "gpio44",
+       "gpio45",
+       "gpio46",
+       "gpio47",
+       "gpio48",
+       "gpio49",
+       "gpio50",
+       "gpio51",
+       "gpio52",
+       "gpio53",
+};
+
+enum bcm2835_fsel {
+       BCM2835_FSEL_GPIO_IN = 0,
+       BCM2835_FSEL_GPIO_OUT = 1,
+       BCM2835_FSEL_ALT0 = 4,
+       BCM2835_FSEL_ALT1 = 5,
+       BCM2835_FSEL_ALT2 = 6,
+       BCM2835_FSEL_ALT3 = 7,
+       BCM2835_FSEL_ALT4 = 3,
+       BCM2835_FSEL_ALT5 = 2,
+       BCM2835_FSEL_COUNT = 8,
+       BCM2835_FSEL_MASK = 0x7,
+};
+
+static const char * const bcm2835_functions[BCM2835_FSEL_COUNT] = {
+       [BCM2835_FSEL_GPIO_IN] = "gpio_in",
+       [BCM2835_FSEL_GPIO_OUT] = "gpio_out",
+       [BCM2835_FSEL_ALT0] = "alt0",
+       [BCM2835_FSEL_ALT1] = "alt1",
+       [BCM2835_FSEL_ALT2] = "alt2",
+       [BCM2835_FSEL_ALT3] = "alt3",
+       [BCM2835_FSEL_ALT4] = "alt4",
+       [BCM2835_FSEL_ALT5] = "alt5",
+};
+
+static const char * const irq_type_names[] = {
+       [IRQ_TYPE_NONE] = "none",
+       [IRQ_TYPE_EDGE_RISING] = "edge-rising",
+       [IRQ_TYPE_EDGE_FALLING] = "edge-falling",
+       [IRQ_TYPE_EDGE_BOTH] = "edge-both",
+       [IRQ_TYPE_LEVEL_HIGH] = "level-high",
+       [IRQ_TYPE_LEVEL_LOW] = "level-low",
+};
+
+static inline u32 bcm2835_gpio_rd(struct bcm2835_pinctrl *pc, unsigned reg)
+{
+       return readl(pc->base + reg);
+}
+
+static inline void bcm2835_gpio_wr(struct bcm2835_pinctrl *pc, unsigned reg,
+               u32 val)
+{
+       writel(val, pc->base + reg);
+}
+
+static inline int bcm2835_gpio_get_bit(struct bcm2835_pinctrl *pc, unsigned reg,
+               unsigned bit)
+{
+       reg += GPIO_REG_OFFSET(bit) * 4;
+       return (bcm2835_gpio_rd(pc, reg) >> GPIO_REG_SHIFT(bit)) & 1;
+}
+
+/* note NOT a read/modify/write cycle */
+static inline void bcm2835_gpio_set_bit(struct bcm2835_pinctrl *pc,
+               unsigned reg, unsigned bit)
+{
+       reg += GPIO_REG_OFFSET(bit) * 4;
+       bcm2835_gpio_wr(pc, reg, BIT(GPIO_REG_SHIFT(bit)));
+}
+
+static inline enum bcm2835_fsel bcm2835_pinctrl_fsel_get(
+               struct bcm2835_pinctrl *pc, unsigned pin)
+{
+       u32 val = bcm2835_gpio_rd(pc, FSEL_REG(pin));
+       enum bcm2835_fsel status = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK;
+
+       dev_dbg(pc->dev, "get %08x (%u => %s)\n", val, pin,
+                       bcm2835_functions[status]);
+
+       return status;
+}
+
+static inline void bcm2835_pinctrl_fsel_set(
+               struct bcm2835_pinctrl *pc, unsigned pin,
+               enum bcm2835_fsel fsel)
+{
+       u32 val = bcm2835_gpio_rd(pc, FSEL_REG(pin));
+       enum bcm2835_fsel cur = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK;
+
+       dev_dbg(pc->dev, "read %08x (%u => %s)\n", val, pin,
+                       bcm2835_functions[cur]);
+
+       if (cur == fsel)
+               return;
+
+       if (cur != BCM2835_FSEL_GPIO_IN && fsel != BCM2835_FSEL_GPIO_IN) {
+               /* always transition through GPIO_IN */
+               val &= ~(BCM2835_FSEL_MASK << FSEL_SHIFT(pin));
+               val |= BCM2835_FSEL_GPIO_IN << FSEL_SHIFT(pin);
+
+               dev_dbg(pc->dev, "trans %08x (%u <= %s)\n", val, pin,
+                               bcm2835_functions[BCM2835_FSEL_GPIO_IN]);
+               bcm2835_gpio_wr(pc, FSEL_REG(pin), val);
+       }
+
+       val &= ~(BCM2835_FSEL_MASK << FSEL_SHIFT(pin));
+       val |= fsel << FSEL_SHIFT(pin);
+
+       dev_dbg(pc->dev, "write %08x (%u <= %s)\n", val, pin,
+                       bcm2835_functions[fsel]);
+       bcm2835_gpio_wr(pc, FSEL_REG(pin), val);
+}
+
+static int bcm2835_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void bcm2835_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       pinctrl_free_gpio(chip->base + offset);
+}
+
+static int bcm2835_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int bcm2835_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev);
+
+       return bcm2835_gpio_get_bit(pc, GPLEV0, offset);
+}
+
+static int bcm2835_gpio_direction_output(struct gpio_chip *chip,
+               unsigned offset, int value)
+{
+       return pinctrl_gpio_direction_output(chip->base + offset);
+}
+
+static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev);
+
+       bcm2835_gpio_set_bit(pc, value ? GPSET0 : GPCLR0, offset);
+}
+
+static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev);
+
+       return irq_linear_revmap(pc->irq_domain, offset);
+}
+
+static struct gpio_chip bcm2835_gpio_chip = {
+       .label = MODULE_NAME,
+       .owner = THIS_MODULE,
+       .request = bcm2835_gpio_request,
+       .free = bcm2835_gpio_free,
+       .direction_input = bcm2835_gpio_direction_input,
+       .direction_output = bcm2835_gpio_direction_output,
+       .get = bcm2835_gpio_get,
+       .set = bcm2835_gpio_set,
+       .to_irq = bcm2835_gpio_to_irq,
+       .base = -1,
+       .ngpio = BCM2835_NUM_GPIOS,
+       .can_sleep = false,
+};
+
+static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id)
+{
+       struct bcm2835_gpio_irqdata *irqdata = dev_id;
+       struct bcm2835_pinctrl *pc = irqdata->pc;
+       int bank = irqdata->bank;
+       unsigned long events;
+       unsigned offset;
+       unsigned gpio;
+       unsigned int type;
+
+       events = bcm2835_gpio_rd(pc, GPEDS0 + bank * 4);
+       events &= pc->enabled_irq_map[bank];
+       for_each_set_bit(offset, &events, 32) {
+               gpio = (32 * bank) + offset;
+               type = pc->irq_type[gpio];
+
+               generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio));
+       }
+       return events ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
+       unsigned reg, unsigned offset, bool enable)
+{
+       u32 value;
+       reg += GPIO_REG_OFFSET(offset) * 4;
+       value = bcm2835_gpio_rd(pc, reg);
+       if (enable)
+               value |= BIT(GPIO_REG_SHIFT(offset));
+       else
+               value &= ~(BIT(GPIO_REG_SHIFT(offset)));
+       bcm2835_gpio_wr(pc, reg, value);
+}
+
+/* fast path for IRQ handler */
+static void bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
+       unsigned offset, bool enable)
+{
+       switch (pc->irq_type[offset]) {
+       case IRQ_TYPE_EDGE_RISING:
+               __bcm2835_gpio_irq_config(pc, GPREN0, offset, enable);
+               break;
+
+       case IRQ_TYPE_EDGE_FALLING:
+               __bcm2835_gpio_irq_config(pc, GPFEN0, offset, enable);
+               break;
+
+       case IRQ_TYPE_EDGE_BOTH:
+               __bcm2835_gpio_irq_config(pc, GPREN0, offset, enable);
+               __bcm2835_gpio_irq_config(pc, GPFEN0, offset, enable);
+               break;
+
+       case IRQ_TYPE_LEVEL_HIGH:
+               __bcm2835_gpio_irq_config(pc, GPHEN0, offset, enable);
+               break;
+
+       case IRQ_TYPE_LEVEL_LOW:
+               __bcm2835_gpio_irq_config(pc, GPLEN0, offset, enable);
+               break;
+       }
+}
+
+static void bcm2835_gpio_irq_enable(struct irq_data *data)
+{
+       struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+       unsigned gpio = irqd_to_hwirq(data);
+       unsigned offset = GPIO_REG_SHIFT(gpio);
+       unsigned bank = GPIO_REG_OFFSET(gpio);
+       unsigned long flags;
+
+       spin_lock_irqsave(&pc->irq_lock[bank], flags);
+       set_bit(offset, &pc->enabled_irq_map[bank]);
+       bcm2835_gpio_irq_config(pc, gpio, true);
+       spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
+}
+
+static void bcm2835_gpio_irq_disable(struct irq_data *data)
+{
+       struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+       unsigned gpio = irqd_to_hwirq(data);
+       unsigned offset = GPIO_REG_SHIFT(gpio);
+       unsigned bank = GPIO_REG_OFFSET(gpio);
+       unsigned long flags;
+
+       spin_lock_irqsave(&pc->irq_lock[bank], flags);
+       bcm2835_gpio_irq_config(pc, gpio, false);
+       clear_bit(offset, &pc->enabled_irq_map[bank]);
+       spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
+}
+
+static int __bcm2835_gpio_irq_set_type_disabled(struct bcm2835_pinctrl *pc,
+       unsigned offset, unsigned int type)
+{
+       switch (type) {
+       case IRQ_TYPE_NONE:
+       case IRQ_TYPE_EDGE_RISING:
+       case IRQ_TYPE_EDGE_FALLING:
+       case IRQ_TYPE_EDGE_BOTH:
+       case IRQ_TYPE_LEVEL_HIGH:
+       case IRQ_TYPE_LEVEL_LOW:
+               pc->irq_type[offset] = type;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* slower path for reconfiguring IRQ type */
+static int __bcm2835_gpio_irq_set_type_enabled(struct bcm2835_pinctrl *pc,
+       unsigned offset, unsigned int type)
+{
+       switch (type) {
+       case IRQ_TYPE_NONE:
+               if (pc->irq_type[offset] != type) {
+                       bcm2835_gpio_irq_config(pc, offset, false);
+                       pc->irq_type[offset] = type;
+               }
+               break;
+
+       case IRQ_TYPE_EDGE_RISING:
+               if (pc->irq_type[offset] == IRQ_TYPE_EDGE_BOTH) {
+                       /* RISING already enabled, disable FALLING */
+                       pc->irq_type[offset] = IRQ_TYPE_EDGE_FALLING;
+                       bcm2835_gpio_irq_config(pc, offset, false);
+                       pc->irq_type[offset] = type;
+               } else if (pc->irq_type[offset] != type) {
+                       bcm2835_gpio_irq_config(pc, offset, false);
+                       pc->irq_type[offset] = type;
+                       bcm2835_gpio_irq_config(pc, offset, true);
+               }
+               break;
+
+       case IRQ_TYPE_EDGE_FALLING:
+               if (pc->irq_type[offset] == IRQ_TYPE_EDGE_BOTH) {
+                       /* FALLING already enabled, disable RISING */
+                       pc->irq_type[offset] = IRQ_TYPE_EDGE_RISING;
+                       bcm2835_gpio_irq_config(pc, offset, false);
+                       pc->irq_type[offset] = type;
+               } else if (pc->irq_type[offset] != type) {
+                       bcm2835_gpio_irq_config(pc, offset, false);
+                       pc->irq_type[offset] = type;
+                       bcm2835_gpio_irq_config(pc, offset, true);
+               }
+               break;
+
+       case IRQ_TYPE_EDGE_BOTH:
+               if (pc->irq_type[offset] == IRQ_TYPE_EDGE_RISING) {
+                       /* RISING already enabled, enable FALLING too */
+                       pc->irq_type[offset] = IRQ_TYPE_EDGE_FALLING;
+                       bcm2835_gpio_irq_config(pc, offset, true);
+                       pc->irq_type[offset] = type;
+               } else if (pc->irq_type[offset] == IRQ_TYPE_EDGE_FALLING) {
+                       /* FALLING already enabled, enable RISING too */
+                       pc->irq_type[offset] = IRQ_TYPE_EDGE_RISING;
+                       bcm2835_gpio_irq_config(pc, offset, true);
+                       pc->irq_type[offset] = type;
+               } else if (pc->irq_type[offset] != type) {
+                       bcm2835_gpio_irq_config(pc, offset, false);
+                       pc->irq_type[offset] = type;
+                       bcm2835_gpio_irq_config(pc, offset, true);
+               }
+               break;
+
+       case IRQ_TYPE_LEVEL_HIGH:
+       case IRQ_TYPE_LEVEL_LOW:
+               if (pc->irq_type[offset] != type) {
+                       bcm2835_gpio_irq_config(pc, offset, false);
+                       pc->irq_type[offset] = type;
+                       bcm2835_gpio_irq_config(pc, offset, true);
+               }
+               break;
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
+{
+       struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+       unsigned gpio = irqd_to_hwirq(data);
+       unsigned offset = GPIO_REG_SHIFT(gpio);
+       unsigned bank = GPIO_REG_OFFSET(gpio);
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&pc->irq_lock[bank], flags);
+
+       if (test_bit(offset, &pc->enabled_irq_map[bank]))
+               ret = __bcm2835_gpio_irq_set_type_enabled(pc, gpio, type);
+       else
+               ret = __bcm2835_gpio_irq_set_type_disabled(pc, gpio, type);
+
+       if (type & IRQ_TYPE_EDGE_BOTH)
+               __irq_set_handler_locked(data->irq, handle_edge_irq);
+       else
+               __irq_set_handler_locked(data->irq, handle_level_irq);
+
+       spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
+
+       return ret;
+}
+
+static void bcm2835_gpio_irq_ack(struct irq_data *data)
+{
+       struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+       unsigned gpio = irqd_to_hwirq(data);
+
+       bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
+}
+
+static struct irq_chip bcm2835_gpio_irq_chip = {
+       .name = MODULE_NAME,
+       .irq_enable = bcm2835_gpio_irq_enable,
+       .irq_disable = bcm2835_gpio_irq_disable,
+       .irq_set_type = bcm2835_gpio_irq_set_type,
+       .irq_ack = bcm2835_gpio_irq_ack,
+       .irq_mask = bcm2835_gpio_irq_disable,
+       .irq_unmask = bcm2835_gpio_irq_enable,
+};
+
+static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       return ARRAY_SIZE(bcm2835_gpio_groups);
+}
+
+static const char *bcm2835_pctl_get_group_name(struct pinctrl_dev *pctldev,
+               unsigned selector)
+{
+       return bcm2835_gpio_groups[selector];
+}
+
+static int bcm2835_pctl_get_group_pins(struct pinctrl_dev *pctldev,
+               unsigned selector,
+               const unsigned **pins,
+               unsigned *num_pins)
+{
+       *pins = &bcm2835_gpio_pins[selector].number;
+       *num_pins = 1;
+
+       return 0;
+}
+
+static void bcm2835_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
+               struct seq_file *s,
+               unsigned offset)
+{
+       struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+       enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset);
+       const char *fname = bcm2835_functions[fsel];
+       int value = bcm2835_gpio_get_bit(pc, GPLEV0, offset);
+       int irq = irq_find_mapping(pc->irq_domain, offset);
+
+       seq_printf(s, "function %s in %s; irq %d (%s)",
+               fname, value ? "hi" : "lo",
+               irq, irq_type_names[pc->irq_type[offset]]);
+}
+
+static void bcm2835_pctl_dt_free_map(struct pinctrl_dev *pctldev,
+               struct pinctrl_map *maps, unsigned num_maps)
+{
+       int i;
+
+       for (i = 0; i < num_maps; i++)
+               if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
+                       kfree(maps[i].data.configs.configs);
+
+       kfree(maps);
+}
+
+static int bcm2835_pctl_dt_node_to_map_func(struct bcm2835_pinctrl *pc,
+               struct device_node *np, u32 pin, u32 fnum,
+               struct pinctrl_map **maps)
+{
+       struct pinctrl_map *map = *maps;
+
+       if (fnum >= ARRAY_SIZE(bcm2835_functions)) {
+               dev_err(pc->dev, "%s: invalid brcm,function %d\n",
+                       of_node_full_name(np), fnum);
+               return -EINVAL;
+       }
+
+       map->type = PIN_MAP_TYPE_MUX_GROUP;
+       map->data.mux.group = bcm2835_gpio_groups[pin];
+       map->data.mux.function = bcm2835_functions[fnum];
+       (*maps)++;
+
+       return 0;
+}
+
+static int bcm2835_pctl_dt_node_to_map_pull(struct bcm2835_pinctrl *pc,
+               struct device_node *np, u32 pin, u32 pull,
+               struct pinctrl_map **maps)
+{
+       struct pinctrl_map *map = *maps;
+       unsigned long *configs;
+
+       if (pull > 2) {
+               dev_err(pc->dev, "%s: invalid brcm,pull %d\n",
+                       of_node_full_name(np), pull);
+               return -EINVAL;
+       }
+
+       configs = kzalloc(sizeof(*configs), GFP_KERNEL);
+       if (!configs)
+               return -ENOMEM;
+       configs[0] = BCM2835_PINCONF_PACK(BCM2835_PINCONF_PARAM_PULL, pull);
+
+       map->type = PIN_MAP_TYPE_CONFIGS_PIN;
+       map->data.configs.group_or_pin = bcm2835_gpio_pins[pin].name;
+       map->data.configs.configs = configs;
+       map->data.configs.num_configs = 1;
+       (*maps)++;
+
+       return 0;
+}
+
+static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
+               struct device_node *np,
+               struct pinctrl_map **map, unsigned *num_maps)
+{
+       struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+       struct property *pins, *funcs, *pulls;
+       int num_pins, num_funcs, num_pulls, maps_per_pin;
+       struct pinctrl_map *maps, *cur_map;
+       int i, err;
+       u32 pin, func, pull;
+
+       pins = of_find_property(np, "brcm,pins", NULL);
+       if (!pins) {
+               dev_err(pc->dev, "%s: missing brcm,pins property\n",
+                               of_node_full_name(np));
+               return -EINVAL;
+       }
+
+       funcs = of_find_property(np, "brcm,function", NULL);
+       pulls = of_find_property(np, "brcm,pull", NULL);
+
+       if (!funcs && !pulls) {
+               dev_err(pc->dev,
+                       "%s: neither brcm,function nor brcm,pull specified\n",
+                       of_node_full_name(np));
+               return -EINVAL;
+       }
+
+       num_pins = pins->length / 4;
+       num_funcs = funcs ? (funcs->length / 4) : 0;
+       num_pulls = pulls ? (pulls->length / 4) : 0;
+
+       if (num_funcs > 1 && num_funcs != num_pins) {
+               dev_err(pc->dev,
+                       "%s: brcm,function must have 1 or %d entries\n",
+                       of_node_full_name(np), num_pins);
+               return -EINVAL;
+       }
+
+       if (num_pulls > 1 && num_pulls != num_pins) {
+               dev_err(pc->dev,
+                       "%s: brcm,pull must have 1 or %d entries\n",
+                       of_node_full_name(np), num_pins);
+               return -EINVAL;
+       }
+
+       maps_per_pin = 0;
+       if (num_funcs)
+               maps_per_pin++;
+       if (num_pulls)
+               maps_per_pin++;
+       cur_map = maps = kzalloc(num_pins * maps_per_pin * sizeof(*maps),
+                               GFP_KERNEL);
+       if (!maps)
+               return -ENOMEM;
+
+       for (i = 0; i < num_pins; i++) {
+               err = of_property_read_u32_index(np, "brcm,pins", i, &pin);
+               if (err)
+                       goto out;
+               if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) {
+                       dev_err(pc->dev, "%s: invalid brcm,pins value %d\n",
+                               of_node_full_name(np), pin);
+                       err = -EINVAL;
+                       goto out;
+               }
+
+               if (num_funcs) {
+                       err = of_property_read_u32_index(np, "brcm,function",
+                                       (num_funcs > 1) ? i : 0, &func);
+                       if (err)
+                               goto out;
+                       err = bcm2835_pctl_dt_node_to_map_func(pc, np, pin,
+                                                       func, &cur_map);
+                       if (err)
+                               goto out;
+               }
+               if (num_pulls) {
+                       err = of_property_read_u32_index(np, "brcm,pull",
+                                       (num_funcs > 1) ? i : 0, &pull);
+                       if (err)
+                               goto out;
+                       err = bcm2835_pctl_dt_node_to_map_pull(pc, np, pin,
+                                                       pull, &cur_map);
+                       if (err)
+                               goto out;
+               }
+       }
+
+       *map = maps;
+       *num_maps = num_pins * maps_per_pin;
+
+       return 0;
+
+out:
+       kfree(maps);
+       return err;
+}
+
+static const struct pinctrl_ops bcm2835_pctl_ops = {
+       .get_groups_count = bcm2835_pctl_get_groups_count,
+       .get_group_name = bcm2835_pctl_get_group_name,
+       .get_group_pins = bcm2835_pctl_get_group_pins,
+       .pin_dbg_show = bcm2835_pctl_pin_dbg_show,
+       .dt_node_to_map = bcm2835_pctl_dt_node_to_map,
+       .dt_free_map = bcm2835_pctl_dt_free_map,
+};
+
+static int bcm2835_pmx_get_functions_count(struct pinctrl_dev *pctldev)
+{
+       return BCM2835_FSEL_COUNT;
+}
+
+static const char *bcm2835_pmx_get_function_name(struct pinctrl_dev *pctldev,
+               unsigned selector)
+{
+       return bcm2835_functions[selector];
+}
+
+static int bcm2835_pmx_get_function_groups(struct pinctrl_dev *pctldev,
+               unsigned selector,
+               const char * const **groups,
+               unsigned * const num_groups)
+{
+       /* every pin can do every function */
+       *groups = bcm2835_gpio_groups;
+       *num_groups = ARRAY_SIZE(bcm2835_gpio_groups);
+
+       return 0;
+}
+
+static int bcm2835_pmx_set(struct pinctrl_dev *pctldev,
+               unsigned func_selector,
+               unsigned group_selector)
+{
+       struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+
+       bcm2835_pinctrl_fsel_set(pc, group_selector, func_selector);
+
+       return 0;
+}
+
+static void bcm2835_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
+               struct pinctrl_gpio_range *range,
+               unsigned offset)
+{
+       struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+
+       /* disable by setting to GPIO_IN */
+       bcm2835_pinctrl_fsel_set(pc, offset, BCM2835_FSEL_GPIO_IN);
+}
+
+static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+               struct pinctrl_gpio_range *range,
+               unsigned offset,
+               bool input)
+{
+       struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+       enum bcm2835_fsel fsel = input ?
+               BCM2835_FSEL_GPIO_IN : BCM2835_FSEL_GPIO_OUT;
+
+       bcm2835_pinctrl_fsel_set(pc, offset, fsel);
+
+       return 0;
+}
+
+static const struct pinmux_ops bcm2835_pmx_ops = {
+       .get_functions_count = bcm2835_pmx_get_functions_count,
+       .get_function_name = bcm2835_pmx_get_function_name,
+       .get_function_groups = bcm2835_pmx_get_function_groups,
+       .set_mux = bcm2835_pmx_set,
+       .gpio_disable_free = bcm2835_pmx_gpio_disable_free,
+       .gpio_set_direction = bcm2835_pmx_gpio_set_direction,
+};
+
+static int bcm2835_pinconf_get(struct pinctrl_dev *pctldev,
+                       unsigned pin, unsigned long *config)
+{
+       /* No way to read back config in HW */
+       return -ENOTSUPP;
+}
+
+static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
+                       unsigned pin, unsigned long *configs,
+                       unsigned num_configs)
+{
+       struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+       enum bcm2835_pinconf_param param;
+       u16 arg;
+       u32 off, bit;
+       int i;
+
+       for (i = 0; i < num_configs; i++) {
+               param = BCM2835_PINCONF_UNPACK_PARAM(configs[i]);
+               arg = BCM2835_PINCONF_UNPACK_ARG(configs[i]);
+
+               if (param != BCM2835_PINCONF_PARAM_PULL)
+                       return -EINVAL;
+
+               off = GPIO_REG_OFFSET(pin);
+               bit = GPIO_REG_SHIFT(pin);
+
+               bcm2835_gpio_wr(pc, GPPUD, arg & 3);
+               /*
+                * Docs say to wait 150 cycles, but not of what. We assume a
+                * 1 MHz clock here, which is pretty slow...
+                */
+               udelay(150);
+               bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
+               udelay(150);
+               bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
+       } /* for each config */
+
+       return 0;
+}
+
+static const struct pinconf_ops bcm2835_pinconf_ops = {
+       .pin_config_get = bcm2835_pinconf_get,
+       .pin_config_set = bcm2835_pinconf_set,
+};
+
+static struct pinctrl_desc bcm2835_pinctrl_desc = {
+       .name = MODULE_NAME,
+       .pins = bcm2835_gpio_pins,
+       .npins = ARRAY_SIZE(bcm2835_gpio_pins),
+       .pctlops = &bcm2835_pctl_ops,
+       .pmxops = &bcm2835_pmx_ops,
+       .confops = &bcm2835_pinconf_ops,
+       .owner = THIS_MODULE,
+};
+
+static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = {
+       .name = MODULE_NAME,
+       .npins = BCM2835_NUM_GPIOS,
+};
+
+static int bcm2835_pinctrl_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct bcm2835_pinctrl *pc;
+       struct resource iomem;
+       int err, i;
+       BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2835_NUM_GPIOS);
+       BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2835_NUM_GPIOS);
+
+       pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
+       if (!pc)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, pc);
+       pc->dev = dev;
+
+       err = of_address_to_resource(np, 0, &iomem);
+       if (err) {
+               dev_err(dev, "could not get IO memory\n");
+               return err;
+       }
+
+       pc->base = devm_ioremap_resource(dev, &iomem);
+       if (IS_ERR(pc->base))
+               return PTR_ERR(pc->base);
+
+       pc->gpio_chip = bcm2835_gpio_chip;
+       pc->gpio_chip.dev = dev;
+       pc->gpio_chip.of_node = np;
+
+       pc->irq_domain = irq_domain_add_linear(np, BCM2835_NUM_GPIOS,
+                       &irq_domain_simple_ops, NULL);
+       if (!pc->irq_domain) {
+               dev_err(dev, "could not create IRQ domain\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < BCM2835_NUM_GPIOS; i++) {
+               int irq = irq_create_mapping(pc->irq_domain, i);
+               irq_set_lockdep_class(irq, &gpio_lock_class);
+               irq_set_chip_and_handler(irq, &bcm2835_gpio_irq_chip,
+                               handle_level_irq);
+               irq_set_chip_data(irq, pc);
+               set_irq_flags(irq, IRQF_VALID);
+       }
+
+       for (i = 0; i < BCM2835_NUM_BANKS; i++) {
+               unsigned long events;
+               unsigned offset;
+               int len;
+               char *name;
+
+               /* clear event detection flags */
+               bcm2835_gpio_wr(pc, GPREN0 + i * 4, 0);
+               bcm2835_gpio_wr(pc, GPFEN0 + i * 4, 0);
+               bcm2835_gpio_wr(pc, GPHEN0 + i * 4, 0);
+               bcm2835_gpio_wr(pc, GPLEN0 + i * 4, 0);
+               bcm2835_gpio_wr(pc, GPAREN0 + i * 4, 0);
+               bcm2835_gpio_wr(pc, GPAFEN0 + i * 4, 0);
+
+               /* clear all the events */
+               events = bcm2835_gpio_rd(pc, GPEDS0 + i * 4);
+               for_each_set_bit(offset, &events, 32)
+                       bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset));
+
+               pc->irq[i] = irq_of_parse_and_map(np, i);
+               pc->irq_data[i].pc = pc;
+               pc->irq_data[i].bank = i;
+               spin_lock_init(&pc->irq_lock[i]);
+
+               len = strlen(dev_name(pc->dev)) + 16;
+               name = devm_kzalloc(pc->dev, len, GFP_KERNEL);
+               if (!name)
+                       return -ENOMEM;
+               snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i);
+
+               err = devm_request_irq(dev, pc->irq[i],
+                       bcm2835_gpio_irq_handler, IRQF_SHARED,
+                       name, &pc->irq_data[i]);
+               if (err) {
+                       dev_err(dev, "unable to request IRQ %d\n", pc->irq[i]);
+                       return err;
+               }
+       }
+
+       err = gpiochip_add(&pc->gpio_chip);
+       if (err) {
+               dev_err(dev, "could not add GPIO chip\n");
+               return err;
+       }
+
+       pc->pctl_dev = pinctrl_register(&bcm2835_pinctrl_desc, dev, pc);
+       if (!pc->pctl_dev) {
+               gpiochip_remove(&pc->gpio_chip);
+               return -EINVAL;
+       }
+
+       pc->gpio_range = bcm2835_pinctrl_gpio_range;
+       pc->gpio_range.base = pc->gpio_chip.base;
+       pc->gpio_range.gc = &pc->gpio_chip;
+       pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
+
+       return 0;
+}
+
+static int bcm2835_pinctrl_remove(struct platform_device *pdev)
+{
+       struct bcm2835_pinctrl *pc = platform_get_drvdata(pdev);
+
+       pinctrl_unregister(pc->pctl_dev);
+       gpiochip_remove(&pc->gpio_chip);
+
+       return 0;
+}
+
+static const struct of_device_id bcm2835_pinctrl_match[] = {
+       { .compatible = "brcm,bcm2835-gpio" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, bcm2835_pinctrl_match);
+
+static struct platform_driver bcm2835_pinctrl_driver = {
+       .probe = bcm2835_pinctrl_probe,
+       .remove = bcm2835_pinctrl_remove,
+       .driver = {
+               .name = MODULE_NAME,
+               .of_match_table = bcm2835_pinctrl_match,
+       },
+};
+module_platform_driver(bcm2835_pinctrl_driver);
+
+MODULE_AUTHOR("Chris Boot, Simon Arlott, Stephen Warren");
+MODULE_DESCRIPTION("BCM2835 Pin control driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c b/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
new file mode 100644 (file)
index 0000000..4ad5c1a
--- /dev/null
@@ -0,0 +1,907 @@
+/*
+ * Copyright (C) 2014-2015 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This file contains the Broadcom Cygnus GPIO driver that supports 3
+ * GPIO controllers on Cygnus including the ASIU GPIO controller, the
+ * chipCommonG GPIO controller, and the always-on GPIO controller. Basic
+ * PINCONF such as bias pull up/down, and drive strength are also supported
+ * in this driver.
+ *
+ * Pins from the ASIU GPIO can be individually muxed to GPIO function,
+ * through the interaction with the Cygnus IOMUX controller
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/ioport.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+
+#include "../pinctrl-utils.h"
+
+#define CYGNUS_GPIO_DATA_IN_OFFSET   0x00
+#define CYGNUS_GPIO_DATA_OUT_OFFSET  0x04
+#define CYGNUS_GPIO_OUT_EN_OFFSET    0x08
+#define CYGNUS_GPIO_IN_TYPE_OFFSET   0x0c
+#define CYGNUS_GPIO_INT_DE_OFFSET    0x10
+#define CYGNUS_GPIO_INT_EDGE_OFFSET  0x14
+#define CYGNUS_GPIO_INT_MSK_OFFSET   0x18
+#define CYGNUS_GPIO_INT_STAT_OFFSET  0x1c
+#define CYGNUS_GPIO_INT_MSTAT_OFFSET 0x20
+#define CYGNUS_GPIO_INT_CLR_OFFSET   0x24
+#define CYGNUS_GPIO_PAD_RES_OFFSET   0x34
+#define CYGNUS_GPIO_RES_EN_OFFSET    0x38
+
+/* drive strength control for ASIU GPIO */
+#define CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET 0x58
+
+/* drive strength control for CCM/CRMU (AON) GPIO */
+#define CYGNUS_GPIO_DRV0_CTRL_OFFSET  0x00
+
+#define GPIO_BANK_SIZE 0x200
+#define NGPIOS_PER_BANK 32
+#define GPIO_BANK(pin) ((pin) / NGPIOS_PER_BANK)
+
+#define CYGNUS_GPIO_REG(pin, reg) (GPIO_BANK(pin) * GPIO_BANK_SIZE + (reg))
+#define CYGNUS_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK)
+
+#define GPIO_DRV_STRENGTH_BIT_SHIFT  20
+#define GPIO_DRV_STRENGTH_BITS       3
+#define GPIO_DRV_STRENGTH_BIT_MASK   ((1 << GPIO_DRV_STRENGTH_BITS) - 1)
+
+/*
+ * Cygnus GPIO core
+ *
+ * @dev: pointer to device
+ * @base: I/O register base for Cygnus GPIO controller
+ * @io_ctrl: I/O register base for certain type of Cygnus GPIO controller that
+ * has the PINCONF support implemented outside of the GPIO block
+ * @lock: lock to protect access to I/O registers
+ * @gc: GPIO chip
+ * @num_banks: number of GPIO banks, each bank supports up to 32 GPIOs
+ * @pinmux_is_supported: flag to indicate this GPIO controller contains pins
+ * that can be individually muxed to GPIO
+ * @pctl: pointer to pinctrl_dev
+ * @pctldesc: pinctrl descriptor
+ */
+struct cygnus_gpio {
+       struct device *dev;
+
+       void __iomem *base;
+       void __iomem *io_ctrl;
+
+       spinlock_t lock;
+
+       struct gpio_chip gc;
+       unsigned num_banks;
+
+       bool pinmux_is_supported;
+
+       struct pinctrl_dev *pctl;
+       struct pinctrl_desc pctldesc;
+};
+
+static inline struct cygnus_gpio *to_cygnus_gpio(struct gpio_chip *gc)
+{
+       return container_of(gc, struct cygnus_gpio, gc);
+}
+
+/*
+ * Mapping from PINCONF pins to GPIO pins is 1-to-1
+ */
+static inline unsigned cygnus_pin_to_gpio(unsigned pin)
+{
+       return pin;
+}
+
+/**
+ *  cygnus_set_bit - set or clear one bit (corresponding to the GPIO pin) in a
+ *  Cygnus GPIO register
+ *
+ *  @cygnus_gpio: Cygnus GPIO device
+ *  @reg: register offset
+ *  @gpio: GPIO pin
+ *  @set: set or clear
+ */
+static inline void cygnus_set_bit(struct cygnus_gpio *chip, unsigned int reg,
+                                 unsigned gpio, bool set)
+{
+       unsigned int offset = CYGNUS_GPIO_REG(gpio, reg);
+       unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
+       u32 val;
+
+       val = readl(chip->base + offset);
+       if (set)
+               val |= BIT(shift);
+       else
+               val &= ~BIT(shift);
+       writel(val, chip->base + offset);
+}
+
+static inline bool cygnus_get_bit(struct cygnus_gpio *chip, unsigned int reg,
+                                 unsigned gpio)
+{
+       unsigned int offset = CYGNUS_GPIO_REG(gpio, reg);
+       unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
+
+       return !!(readl(chip->base + offset) & BIT(shift));
+}
+
+static void cygnus_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+       struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+       struct irq_chip *irq_chip = irq_desc_get_chip(desc);
+       int i, bit;
+
+       chained_irq_enter(irq_chip, desc);
+
+       /* go through the entire GPIO banks and handle all interrupts */
+       for (i = 0; i < chip->num_banks; i++) {
+               unsigned long val = readl(chip->base + (i * GPIO_BANK_SIZE) +
+                                         CYGNUS_GPIO_INT_MSTAT_OFFSET);
+
+               for_each_set_bit(bit, &val, NGPIOS_PER_BANK) {
+                       unsigned pin = NGPIOS_PER_BANK * i + bit;
+                       int child_irq = irq_find_mapping(gc->irqdomain, pin);
+
+                       /*
+                        * Clear the interrupt before invoking the
+                        * handler, so we do not leave any window
+                        */
+                       writel(BIT(bit), chip->base + (i * GPIO_BANK_SIZE) +
+                              CYGNUS_GPIO_INT_CLR_OFFSET);
+
+                       generic_handle_irq(child_irq);
+               }
+       }
+
+       chained_irq_exit(irq_chip, desc);
+}
+
+
+static void cygnus_gpio_irq_ack(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+       unsigned gpio = d->hwirq;
+       unsigned int offset = CYGNUS_GPIO_REG(gpio,
+                       CYGNUS_GPIO_INT_CLR_OFFSET);
+       unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
+       u32 val = BIT(shift);
+
+       writel(val, chip->base + offset);
+}
+
+/**
+ *  cygnus_gpio_irq_set_mask - mask/unmask a GPIO interrupt
+ *
+ *  @d: IRQ chip data
+ *  @unmask: mask/unmask GPIO interrupt
+ */
+static void cygnus_gpio_irq_set_mask(struct irq_data *d, bool unmask)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+       unsigned gpio = d->hwirq;
+
+       cygnus_set_bit(chip, CYGNUS_GPIO_INT_MSK_OFFSET, gpio, unmask);
+}
+
+static void cygnus_gpio_irq_mask(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       cygnus_gpio_irq_set_mask(d, false);
+       spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+static void cygnus_gpio_irq_unmask(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       cygnus_gpio_irq_set_mask(d, true);
+       spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+static int cygnus_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+       unsigned gpio = d->hwirq;
+       bool level_triggered = false;
+       bool dual_edge = false;
+       bool rising_or_high = false;
+       unsigned long flags;
+
+       switch (type & IRQ_TYPE_SENSE_MASK) {
+       case IRQ_TYPE_EDGE_RISING:
+               rising_or_high = true;
+               break;
+
+       case IRQ_TYPE_EDGE_FALLING:
+               break;
+
+       case IRQ_TYPE_EDGE_BOTH:
+               dual_edge = true;
+               break;
+
+       case IRQ_TYPE_LEVEL_HIGH:
+               level_triggered = true;
+               rising_or_high = true;
+               break;
+
+       case IRQ_TYPE_LEVEL_LOW:
+               level_triggered = true;
+               break;
+
+       default:
+               dev_err(chip->dev, "invalid GPIO IRQ type 0x%x\n",
+                       type);
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&chip->lock, flags);
+       cygnus_set_bit(chip, CYGNUS_GPIO_IN_TYPE_OFFSET, gpio,
+                      level_triggered);
+       cygnus_set_bit(chip, CYGNUS_GPIO_INT_DE_OFFSET, gpio, dual_edge);
+       cygnus_set_bit(chip, CYGNUS_GPIO_INT_EDGE_OFFSET, gpio,
+                      rising_or_high);
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       dev_dbg(chip->dev,
+               "gpio:%u level_triggered:%d dual_edge:%d rising_or_high:%d\n",
+               gpio, level_triggered, dual_edge, rising_or_high);
+
+       return 0;
+}
+
+static struct irq_chip cygnus_gpio_irq_chip = {
+       .name = "bcm-cygnus-gpio",
+       .irq_ack = cygnus_gpio_irq_ack,
+       .irq_mask = cygnus_gpio_irq_mask,
+       .irq_unmask = cygnus_gpio_irq_unmask,
+       .irq_set_type = cygnus_gpio_irq_set_type,
+};
+
+/*
+ * Request the Cygnus IOMUX pinmux controller to mux individual pins to GPIO
+ */
+static int cygnus_gpio_request(struct gpio_chip *gc, unsigned offset)
+{
+       struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+       unsigned gpio = gc->base + offset;
+
+       /* not all Cygnus GPIO pins can be muxed individually */
+       if (!chip->pinmux_is_supported)
+               return 0;
+
+       return pinctrl_request_gpio(gpio);
+}
+
+static void cygnus_gpio_free(struct gpio_chip *gc, unsigned offset)
+{
+       struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+       unsigned gpio = gc->base + offset;
+
+       if (!chip->pinmux_is_supported)
+               return;
+
+       pinctrl_free_gpio(gpio);
+}
+
+static int cygnus_gpio_direction_input(struct gpio_chip *gc, unsigned gpio)
+{
+       struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, false);
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       dev_dbg(chip->dev, "gpio:%u set input\n", gpio);
+
+       return 0;
+}
+
+static int cygnus_gpio_direction_output(struct gpio_chip *gc, unsigned gpio,
+                                       int val)
+{
+       struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, true);
+       cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, !!(val));
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       dev_dbg(chip->dev, "gpio:%u set output, value:%d\n", gpio, val);
+
+       return 0;
+}
+
+static void cygnus_gpio_set(struct gpio_chip *gc, unsigned gpio, int val)
+{
+       struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, !!(val));
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       dev_dbg(chip->dev, "gpio:%u set, value:%d\n", gpio, val);
+}
+
+static int cygnus_gpio_get(struct gpio_chip *gc, unsigned gpio)
+{
+       struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+       unsigned int offset = CYGNUS_GPIO_REG(gpio,
+                                             CYGNUS_GPIO_DATA_IN_OFFSET);
+       unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
+
+       return !!(readl(chip->base + offset) & BIT(shift));
+}
+
+static int cygnus_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       return 1;
+}
+
+/*
+ * Only one group: "gpio_grp", since this local pinctrl device only performs
+ * GPIO specific PINCONF configurations
+ */
+static const char *cygnus_get_group_name(struct pinctrl_dev *pctldev,
+                                        unsigned selector)
+{
+       return "gpio_grp";
+}
+
+static const struct pinctrl_ops cygnus_pctrl_ops = {
+       .get_groups_count = cygnus_get_groups_count,
+       .get_group_name = cygnus_get_group_name,
+       .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+       .dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int cygnus_gpio_set_pull(struct cygnus_gpio *chip, unsigned gpio,
+                               bool disable, bool pull_up)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->lock, flags);
+
+       if (disable) {
+               cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, false);
+       } else {
+               cygnus_set_bit(chip, CYGNUS_GPIO_PAD_RES_OFFSET, gpio,
+                              pull_up);
+               cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, true);
+       }
+
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       dev_dbg(chip->dev, "gpio:%u set pullup:%d\n", gpio, pull_up);
+
+       return 0;
+}
+
+static void cygnus_gpio_get_pull(struct cygnus_gpio *chip, unsigned gpio,
+                                bool *disable, bool *pull_up)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       *disable = !cygnus_get_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio);
+       *pull_up = cygnus_get_bit(chip, CYGNUS_GPIO_PAD_RES_OFFSET, gpio);
+       spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+static int cygnus_gpio_set_strength(struct cygnus_gpio *chip, unsigned gpio,
+                                   unsigned strength)
+{
+       void __iomem *base;
+       unsigned int i, offset, shift;
+       u32 val;
+       unsigned long flags;
+
+       /* make sure drive strength is supported */
+       if (strength < 2 ||  strength > 16 || (strength % 2))
+               return -ENOTSUPP;
+
+       if (chip->io_ctrl) {
+               base = chip->io_ctrl;
+               offset = CYGNUS_GPIO_DRV0_CTRL_OFFSET;
+       } else {
+               base = chip->base;
+               offset = CYGNUS_GPIO_REG(gpio,
+                                        CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET);
+       }
+
+       shift = CYGNUS_GPIO_SHIFT(gpio);
+
+       dev_dbg(chip->dev, "gpio:%u set drive strength:%d mA\n", gpio,
+               strength);
+
+       spin_lock_irqsave(&chip->lock, flags);
+       strength = (strength / 2) - 1;
+       for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) {
+               val = readl(base + offset);
+               val &= ~BIT(shift);
+               val |= ((strength >> i) & 0x1) << shift;
+               writel(val, base + offset);
+               offset += 4;
+       }
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       return 0;
+}
+
+static int cygnus_gpio_get_strength(struct cygnus_gpio *chip, unsigned gpio,
+                                   u16 *strength)
+{
+       void __iomem *base;
+       unsigned int i, offset, shift;
+       u32 val;
+       unsigned long flags;
+
+       if (chip->io_ctrl) {
+               base = chip->io_ctrl;
+               offset = CYGNUS_GPIO_DRV0_CTRL_OFFSET;
+       } else {
+               base = chip->base;
+               offset = CYGNUS_GPIO_REG(gpio,
+                                        CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET);
+       }
+
+       shift = CYGNUS_GPIO_SHIFT(gpio);
+
+       spin_lock_irqsave(&chip->lock, flags);
+       *strength = 0;
+       for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) {
+               val = readl(base + offset) & BIT(shift);
+               val >>= shift;
+               *strength += (val << i);
+               offset += 4;
+       }
+
+       /* convert to mA */
+       *strength = (*strength + 1) * 2;
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       return 0;
+}
+
+static int cygnus_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
+                                unsigned long *config)
+{
+       struct cygnus_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
+       enum pin_config_param param = pinconf_to_config_param(*config);
+       unsigned gpio = cygnus_pin_to_gpio(pin);
+       u16 arg;
+       bool disable, pull_up;
+       int ret;
+
+       switch (param) {
+       case PIN_CONFIG_BIAS_DISABLE:
+               cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up);
+               if (disable)
+                       return 0;
+               else
+                       return -EINVAL;
+
+       case PIN_CONFIG_BIAS_PULL_UP:
+               cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up);
+               if (!disable && pull_up)
+                       return 0;
+               else
+                       return -EINVAL;
+
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up);
+               if (!disable && !pull_up)
+                       return 0;
+               else
+                       return -EINVAL;
+
+       case PIN_CONFIG_DRIVE_STRENGTH:
+               ret = cygnus_gpio_get_strength(chip, gpio, &arg);
+               if (ret)
+                       return ret;
+               else
+                       *config = pinconf_to_config_packed(param, arg);
+
+               return 0;
+
+       default:
+               return -ENOTSUPP;
+       }
+
+       return -ENOTSUPP;
+}
+
+static int cygnus_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
+                                unsigned long *configs, unsigned num_configs)
+{
+       struct cygnus_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
+       enum pin_config_param param;
+       u16 arg;
+       unsigned i, gpio = cygnus_pin_to_gpio(pin);
+       int ret = -ENOTSUPP;
+
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
+               arg = pinconf_to_config_argument(configs[i]);
+
+               switch (param) {
+               case PIN_CONFIG_BIAS_DISABLE:
+                       ret = cygnus_gpio_set_pull(chip, gpio, true, false);
+                       if (ret < 0)
+                               goto out;
+                       break;
+
+               case PIN_CONFIG_BIAS_PULL_UP:
+                       ret = cygnus_gpio_set_pull(chip, gpio, false, true);
+                       if (ret < 0)
+                               goto out;
+                       break;
+
+               case PIN_CONFIG_BIAS_PULL_DOWN:
+                       ret = cygnus_gpio_set_pull(chip, gpio, false, false);
+                       if (ret < 0)
+                               goto out;
+                       break;
+
+               case PIN_CONFIG_DRIVE_STRENGTH:
+                       ret = cygnus_gpio_set_strength(chip, gpio, arg);
+                       if (ret < 0)
+                               goto out;
+                       break;
+
+               default:
+                       dev_err(chip->dev, "invalid configuration\n");
+                       return -ENOTSUPP;
+               }
+       } /* for each config */
+
+out:
+       return ret;
+}
+
+static const struct pinconf_ops cygnus_pconf_ops = {
+       .is_generic = true,
+       .pin_config_get = cygnus_pin_config_get,
+       .pin_config_set = cygnus_pin_config_set,
+};
+
+/*
+ * Map a GPIO in the local gpio_chip pin space to a pin in the Cygnus IOMUX
+ * pinctrl pin space
+ */
+struct cygnus_gpio_pin_range {
+       unsigned offset;
+       unsigned pin_base;
+       unsigned num_pins;
+};
+
+#define CYGNUS_PINRANGE(o, p, n) { .offset = o, .pin_base = p, .num_pins = n }
+
+/*
+ * Pin mapping table for mapping local GPIO pins to Cygnus IOMUX pinctrl pins
+ */
+static const struct cygnus_gpio_pin_range cygnus_gpio_pintable[] = {
+       CYGNUS_PINRANGE(0, 42, 1),
+       CYGNUS_PINRANGE(1, 44, 3),
+       CYGNUS_PINRANGE(4, 48, 1),
+       CYGNUS_PINRANGE(5, 50, 3),
+       CYGNUS_PINRANGE(8, 126, 1),
+       CYGNUS_PINRANGE(9, 155, 1),
+       CYGNUS_PINRANGE(10, 152, 1),
+       CYGNUS_PINRANGE(11, 154, 1),
+       CYGNUS_PINRANGE(12, 153, 1),
+       CYGNUS_PINRANGE(13, 127, 3),
+       CYGNUS_PINRANGE(16, 140, 1),
+       CYGNUS_PINRANGE(17, 145, 7),
+       CYGNUS_PINRANGE(24, 130, 10),
+       CYGNUS_PINRANGE(34, 141, 4),
+       CYGNUS_PINRANGE(38, 54, 1),
+       CYGNUS_PINRANGE(39, 56, 3),
+       CYGNUS_PINRANGE(42, 60, 3),
+       CYGNUS_PINRANGE(45, 64, 3),
+       CYGNUS_PINRANGE(48, 68, 2),
+       CYGNUS_PINRANGE(50, 84, 6),
+       CYGNUS_PINRANGE(56, 94, 6),
+       CYGNUS_PINRANGE(62, 72, 1),
+       CYGNUS_PINRANGE(63, 70, 1),
+       CYGNUS_PINRANGE(64, 80, 1),
+       CYGNUS_PINRANGE(65, 74, 3),
+       CYGNUS_PINRANGE(68, 78, 1),
+       CYGNUS_PINRANGE(69, 82, 1),
+       CYGNUS_PINRANGE(70, 156, 17),
+       CYGNUS_PINRANGE(87, 104, 12),
+       CYGNUS_PINRANGE(99, 102, 2),
+       CYGNUS_PINRANGE(101, 90, 4),
+       CYGNUS_PINRANGE(105, 116, 10),
+       CYGNUS_PINRANGE(123, 11, 1),
+       CYGNUS_PINRANGE(124, 38, 4),
+       CYGNUS_PINRANGE(128, 43, 1),
+       CYGNUS_PINRANGE(129, 47, 1),
+       CYGNUS_PINRANGE(130, 49, 1),
+       CYGNUS_PINRANGE(131, 53, 1),
+       CYGNUS_PINRANGE(132, 55, 1),
+       CYGNUS_PINRANGE(133, 59, 1),
+       CYGNUS_PINRANGE(134, 63, 1),
+       CYGNUS_PINRANGE(135, 67, 1),
+       CYGNUS_PINRANGE(136, 71, 1),
+       CYGNUS_PINRANGE(137, 73, 1),
+       CYGNUS_PINRANGE(138, 77, 1),
+       CYGNUS_PINRANGE(139, 79, 1),
+       CYGNUS_PINRANGE(140, 81, 1),
+       CYGNUS_PINRANGE(141, 83, 1),
+       CYGNUS_PINRANGE(142, 10, 1)
+};
+
+/*
+ * The Cygnus IOMUX controller mainly supports group based mux configuration,
+ * but certain pins can be muxed to GPIO individually. Only the ASIU GPIO
+ * controller can support this, so it's an optional configuration
+ *
+ * Return -ENODEV means no support and that's fine
+ */
+static int cygnus_gpio_pinmux_add_range(struct cygnus_gpio *chip)
+{
+       struct device_node *node = chip->dev->of_node;
+       struct device_node *pinmux_node;
+       struct platform_device *pinmux_pdev;
+       struct gpio_chip *gc = &chip->gc;
+       int i, ret = 0;
+
+       /* parse DT to find the phandle to the pinmux controller */
+       pinmux_node = of_parse_phandle(node, "pinmux", 0);
+       if (!pinmux_node)
+               return -ENODEV;
+
+       pinmux_pdev = of_find_device_by_node(pinmux_node);
+       /* no longer need the pinmux node */
+       of_node_put(pinmux_node);
+       if (!pinmux_pdev) {
+               dev_err(chip->dev, "failed to get pinmux device\n");
+               return -EINVAL;
+       }
+
+       /* now need to create the mapping between local GPIO and PINMUX pins */
+       for (i = 0; i < ARRAY_SIZE(cygnus_gpio_pintable); i++) {
+               ret = gpiochip_add_pin_range(gc, dev_name(&pinmux_pdev->dev),
+                                            cygnus_gpio_pintable[i].offset,
+                                            cygnus_gpio_pintable[i].pin_base,
+                                            cygnus_gpio_pintable[i].num_pins);
+               if (ret) {
+                       dev_err(chip->dev, "unable to add GPIO pin range\n");
+                       goto err_put_device;
+               }
+       }
+
+       chip->pinmux_is_supported = true;
+
+       /* no need for pinmux_pdev device reference anymore */
+       put_device(&pinmux_pdev->dev);
+       return 0;
+
+err_put_device:
+       put_device(&pinmux_pdev->dev);
+       gpiochip_remove_pin_ranges(gc);
+       return ret;
+}
+
+/*
+ * Cygnus GPIO controller supports some PINCONF related configurations such as
+ * pull up, pull down, and drive strength, when the pin is configured to GPIO
+ *
+ * Here a local pinctrl device is created with simple 1-to-1 pin mapping to the
+ * local GPIO pins
+ */
+static int cygnus_gpio_register_pinconf(struct cygnus_gpio *chip)
+{
+       struct pinctrl_desc *pctldesc = &chip->pctldesc;
+       struct pinctrl_pin_desc *pins;
+       struct gpio_chip *gc = &chip->gc;
+       int i;
+
+       pins = devm_kcalloc(chip->dev, gc->ngpio, sizeof(*pins), GFP_KERNEL);
+       if (!pins)
+               return -ENOMEM;
+
+       for (i = 0; i < gc->ngpio; i++) {
+               pins[i].number = i;
+               pins[i].name = devm_kasprintf(chip->dev, GFP_KERNEL,
+                                             "gpio-%d", i);
+               if (!pins[i].name)
+                       return -ENOMEM;
+       }
+
+       pctldesc->name = dev_name(chip->dev);
+       pctldesc->pctlops = &cygnus_pctrl_ops;
+       pctldesc->pins = pins;
+       pctldesc->npins = gc->ngpio;
+       pctldesc->confops = &cygnus_pconf_ops;
+
+       chip->pctl = pinctrl_register(pctldesc, chip->dev, chip);
+       if (!chip->pctl) {
+               dev_err(chip->dev, "unable to register pinctrl device\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void cygnus_gpio_unregister_pinconf(struct cygnus_gpio *chip)
+{
+       if (chip->pctl)
+               pinctrl_unregister(chip->pctl);
+}
+
+struct cygnus_gpio_data {
+       unsigned num_gpios;
+};
+
+static const struct cygnus_gpio_data cygnus_cmm_gpio_data = {
+       .num_gpios = 24,
+};
+
+static const struct cygnus_gpio_data cygnus_asiu_gpio_data = {
+       .num_gpios = 146,
+};
+
+static const struct cygnus_gpio_data cygnus_crmu_gpio_data = {
+       .num_gpios = 6,
+};
+
+static const struct of_device_id cygnus_gpio_of_match[] = {
+       {
+               .compatible = "brcm,cygnus-ccm-gpio",
+               .data = &cygnus_cmm_gpio_data,
+       },
+       {
+               .compatible = "brcm,cygnus-asiu-gpio",
+               .data = &cygnus_asiu_gpio_data,
+       },
+       {
+               .compatible = "brcm,cygnus-crmu-gpio",
+               .data = &cygnus_crmu_gpio_data,
+       }
+};
+
+static int cygnus_gpio_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       struct cygnus_gpio *chip;
+       struct gpio_chip *gc;
+       u32 ngpios;
+       int irq, ret;
+       const struct of_device_id *match;
+       const struct cygnus_gpio_data *gpio_data;
+
+       match = of_match_device(cygnus_gpio_of_match, dev);
+       if (!match)
+               return -ENODEV;
+       gpio_data = match->data;
+       ngpios = gpio_data->num_gpios;
+
+       chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       chip->dev = dev;
+       platform_set_drvdata(pdev, chip);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       chip->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(chip->base)) {
+               dev_err(dev, "unable to map I/O memory\n");
+               return PTR_ERR(chip->base);
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (res) {
+               chip->io_ctrl = devm_ioremap_resource(dev, res);
+               if (IS_ERR(chip->io_ctrl)) {
+                       dev_err(dev, "unable to map I/O memory\n");
+                       return PTR_ERR(chip->io_ctrl);
+               }
+       }
+
+       spin_lock_init(&chip->lock);
+
+       gc = &chip->gc;
+       gc->base = -1;
+       gc->ngpio = ngpios;
+       chip->num_banks = (ngpios + NGPIOS_PER_BANK - 1) / NGPIOS_PER_BANK;
+       gc->label = dev_name(dev);
+       gc->dev = dev;
+       gc->of_node = dev->of_node;
+       gc->request = cygnus_gpio_request;
+       gc->free = cygnus_gpio_free;
+       gc->direction_input = cygnus_gpio_direction_input;
+       gc->direction_output = cygnus_gpio_direction_output;
+       gc->set = cygnus_gpio_set;
+       gc->get = cygnus_gpio_get;
+
+       ret = gpiochip_add(gc);
+       if (ret < 0) {
+               dev_err(dev, "unable to add GPIO chip\n");
+               return ret;
+       }
+
+       ret = cygnus_gpio_pinmux_add_range(chip);
+       if (ret && ret != -ENODEV) {
+               dev_err(dev, "unable to add GPIO pin range\n");
+               goto err_rm_gpiochip;
+       }
+
+       ret = cygnus_gpio_register_pinconf(chip);
+       if (ret) {
+               dev_err(dev, "unable to register pinconf\n");
+               goto err_rm_gpiochip;
+       }
+
+       /* optional GPIO interrupt support */
+       irq = platform_get_irq(pdev, 0);
+       if (irq) {
+               ret = gpiochip_irqchip_add(gc, &cygnus_gpio_irq_chip, 0,
+                                          handle_simple_irq, IRQ_TYPE_NONE);
+               if (ret) {
+                       dev_err(dev, "no GPIO irqchip\n");
+                       goto err_unregister_pinconf;
+               }
+
+               gpiochip_set_chained_irqchip(gc, &cygnus_gpio_irq_chip, irq,
+                                            cygnus_gpio_irq_handler);
+       }
+
+       return 0;
+
+err_unregister_pinconf:
+       cygnus_gpio_unregister_pinconf(chip);
+
+err_rm_gpiochip:
+       gpiochip_remove(gc);
+
+       return ret;
+}
+
+static struct platform_driver cygnus_gpio_driver = {
+       .driver = {
+               .name = "cygnus-gpio",
+               .of_match_table = cygnus_gpio_of_match,
+       },
+       .probe = cygnus_gpio_probe,
+};
+
+static int __init cygnus_gpio_init(void)
+{
+       return platform_driver_probe(&cygnus_gpio_driver, cygnus_gpio_probe);
+}
+arch_initcall_sync(cygnus_gpio_init);
diff --git a/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c b/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c
new file mode 100644 (file)
index 0000000..f9a9283
--- /dev/null
@@ -0,0 +1,1022 @@
+/* Copyright (C) 2014-2015 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This file contains the Cygnus IOMUX driver that supports group based PINMUX
+ * configuration. Although PINMUX configuration is mainly group based, the
+ * Cygnus IOMUX controller allows certain pins to be individually muxed to GPIO
+ * function, and therefore be controlled by the Cygnus ASIU GPIO controller
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#define CYGNUS_NUM_IOMUX_REGS     8
+#define CYGNUS_NUM_MUX_PER_REG    8
+#define CYGNUS_NUM_IOMUX          (CYGNUS_NUM_IOMUX_REGS * \
+                                  CYGNUS_NUM_MUX_PER_REG)
+
+/*
+ * Cygnus IOMUX register description
+ *
+ * @offset: register offset for mux configuration of a group
+ * @shift: bit shift for mux configuration of a group
+ * @alt: alternate function to set to
+ */
+struct cygnus_mux {
+       unsigned int offset;
+       unsigned int shift;
+       unsigned int alt;
+};
+
+/*
+ * Keep track of Cygnus IOMUX configuration and prevent double configuration
+ *
+ * @cygnus_mux: Cygnus IOMUX register description
+ * @is_configured: flag to indicate whether a mux setting has already been
+ * configured
+ */
+struct cygnus_mux_log {
+       struct cygnus_mux mux;
+       bool is_configured;
+};
+
+/*
+ * Group based IOMUX configuration
+ *
+ * @name: name of the group
+ * @pins: array of pins used by this group
+ * @num_pins: total number of pins used by this group
+ * @mux: Cygnus group based IOMUX configuration
+ */
+struct cygnus_pin_group {
+       const char *name;
+       const unsigned *pins;
+       unsigned num_pins;
+       struct cygnus_mux mux;
+};
+
+/*
+ * Cygnus mux function and supported pin groups
+ *
+ * @name: name of the function
+ * @groups: array of groups that can be supported by this function
+ * @num_groups: total number of groups that can be supported by this function
+ */
+struct cygnus_pin_function {
+       const char *name;
+       const char * const *groups;
+       unsigned num_groups;
+};
+
+/*
+ * Cygnus IOMUX pinctrl core
+ *
+ * @pctl: pointer to pinctrl_dev
+ * @dev: pointer to device
+ * @base0: first I/O register base of the Cygnus IOMUX controller
+ * @base1: second I/O register base
+ * @groups: pointer to array of groups
+ * @num_groups: total number of groups
+ * @functions: pointer to array of functions
+ * @num_functions: total number of functions
+ * @mux_log: pointer to the array of mux logs
+ * @lock: lock to protect register access
+ */
+struct cygnus_pinctrl {
+       struct pinctrl_dev *pctl;
+       struct device *dev;
+       void __iomem *base0;
+       void __iomem *base1;
+
+       const struct cygnus_pin_group *groups;
+       unsigned num_groups;
+
+       const struct cygnus_pin_function *functions;
+       unsigned num_functions;
+
+       struct cygnus_mux_log *mux_log;
+
+       spinlock_t lock;
+};
+
+/*
+ * Certain pins can be individually muxed to GPIO function
+ *
+ * @is_supported: flag to indicate GPIO mux is supported for this pin
+ * @offset: register offset for GPIO mux override of a pin
+ * @shift: bit shift for GPIO mux override of a pin
+ */
+struct cygnus_gpio_mux {
+       int is_supported;
+       unsigned int offset;
+       unsigned int shift;
+};
+
+/*
+ * Description of a pin in Cygnus
+ *
+ * @pin: pin number
+ * @name: pin name
+ * @gpio_mux: GPIO override related information
+ */
+struct cygnus_pin {
+       unsigned pin;
+       char *name;
+       struct cygnus_gpio_mux gpio_mux;
+};
+
+#define CYGNUS_PIN_DESC(p, n, i, o, s) \
+{                                      \
+       .pin = p,                       \
+       .name = n,                      \
+       .gpio_mux = {                   \
+               .is_supported = i,      \
+               .offset = o,            \
+               .shift = s,             \
+       },                              \
+}
+
+/*
+ * List of pins in Cygnus
+ */
+static struct cygnus_pin cygnus_pins[] = {
+       CYGNUS_PIN_DESC(0, "ext_device_reset_n", 0, 0, 0),
+       CYGNUS_PIN_DESC(1, "chip_mode0", 0, 0, 0),
+       CYGNUS_PIN_DESC(2, "chip_mode1", 0, 0, 0),
+       CYGNUS_PIN_DESC(3, "chip_mode2", 0, 0, 0),
+       CYGNUS_PIN_DESC(4, "chip_mode3", 0, 0, 0),
+       CYGNUS_PIN_DESC(5, "chip_mode4", 0, 0, 0),
+       CYGNUS_PIN_DESC(6, "bsc0_scl", 0, 0, 0),
+       CYGNUS_PIN_DESC(7, "bsc0_sda", 0, 0, 0),
+       CYGNUS_PIN_DESC(8, "bsc1_scl", 0, 0, 0),
+       CYGNUS_PIN_DESC(9, "bsc1_sda", 0, 0, 0),
+       CYGNUS_PIN_DESC(10, "d1w_dq", 1, 0x28, 0),
+       CYGNUS_PIN_DESC(11, "d1wowstz_l", 1, 0x4, 28),
+       CYGNUS_PIN_DESC(12, "gpio0", 0, 0, 0),
+       CYGNUS_PIN_DESC(13, "gpio1", 0, 0, 0),
+       CYGNUS_PIN_DESC(14, "gpio2", 0, 0, 0),
+       CYGNUS_PIN_DESC(15, "gpio3", 0, 0, 0),
+       CYGNUS_PIN_DESC(16, "gpio4", 0, 0, 0),
+       CYGNUS_PIN_DESC(17, "gpio5", 0, 0, 0),
+       CYGNUS_PIN_DESC(18, "gpio6", 0, 0, 0),
+       CYGNUS_PIN_DESC(19, "gpio7", 0, 0, 0),
+       CYGNUS_PIN_DESC(20, "gpio8", 0, 0, 0),
+       CYGNUS_PIN_DESC(21, "gpio9", 0, 0, 0),
+       CYGNUS_PIN_DESC(22, "gpio10", 0, 0, 0),
+       CYGNUS_PIN_DESC(23, "gpio11", 0, 0, 0),
+       CYGNUS_PIN_DESC(24, "gpio12", 0, 0, 0),
+       CYGNUS_PIN_DESC(25, "gpio13", 0, 0, 0),
+       CYGNUS_PIN_DESC(26, "gpio14", 0, 0, 0),
+       CYGNUS_PIN_DESC(27, "gpio15", 0, 0, 0),
+       CYGNUS_PIN_DESC(28, "gpio16", 0, 0, 0),
+       CYGNUS_PIN_DESC(29, "gpio17", 0, 0, 0),
+       CYGNUS_PIN_DESC(30, "gpio18", 0, 0, 0),
+       CYGNUS_PIN_DESC(31, "gpio19", 0, 0, 0),
+       CYGNUS_PIN_DESC(32, "gpio20", 0, 0, 0),
+       CYGNUS_PIN_DESC(33, "gpio21", 0, 0, 0),
+       CYGNUS_PIN_DESC(34, "gpio22", 0, 0, 0),
+       CYGNUS_PIN_DESC(35, "gpio23", 0, 0, 0),
+       CYGNUS_PIN_DESC(36, "mdc", 0, 0, 0),
+       CYGNUS_PIN_DESC(37, "mdio", 0, 0, 0),
+       CYGNUS_PIN_DESC(38, "pwm0", 1, 0x10, 30),
+       CYGNUS_PIN_DESC(39, "pwm1", 1, 0x10, 28),
+       CYGNUS_PIN_DESC(40, "pwm2", 1, 0x10, 26),
+       CYGNUS_PIN_DESC(41, "pwm3", 1, 0x10, 24),
+       CYGNUS_PIN_DESC(42, "sc0_clk", 1, 0x10, 22),
+       CYGNUS_PIN_DESC(43, "sc0_cmdvcc_l", 1, 0x10, 20),
+       CYGNUS_PIN_DESC(44, "sc0_detect", 1, 0x10, 18),
+       CYGNUS_PIN_DESC(45, "sc0_fcb", 1, 0x10, 16),
+       CYGNUS_PIN_DESC(46, "sc0_io", 1, 0x10, 14),
+       CYGNUS_PIN_DESC(47, "sc0_rst_l", 1, 0x10, 12),
+       CYGNUS_PIN_DESC(48, "sc1_clk", 1, 0x10, 10),
+       CYGNUS_PIN_DESC(49, "sc1_cmdvcc_l", 1, 0x10, 8),
+       CYGNUS_PIN_DESC(50, "sc1_detect", 1, 0x10, 6),
+       CYGNUS_PIN_DESC(51, "sc1_fcb", 1, 0x10, 4),
+       CYGNUS_PIN_DESC(52, "sc1_io", 1, 0x10, 2),
+       CYGNUS_PIN_DESC(53, "sc1_rst_l", 1, 0x10, 0),
+       CYGNUS_PIN_DESC(54, "spi0_clk", 1, 0x18, 10),
+       CYGNUS_PIN_DESC(55, "spi0_mosi", 1, 0x18, 6),
+       CYGNUS_PIN_DESC(56, "spi0_miso", 1, 0x18, 8),
+       CYGNUS_PIN_DESC(57, "spi0_ss", 1, 0x18, 4),
+       CYGNUS_PIN_DESC(58, "spi1_clk", 1, 0x18, 2),
+       CYGNUS_PIN_DESC(59, "spi1_mosi", 1, 0x1c, 30),
+       CYGNUS_PIN_DESC(60, "spi1_miso", 1, 0x18, 0),
+       CYGNUS_PIN_DESC(61, "spi1_ss", 1, 0x1c, 28),
+       CYGNUS_PIN_DESC(62, "spi2_clk", 1, 0x1c, 26),
+       CYGNUS_PIN_DESC(63, "spi2_mosi", 1, 0x1c, 22),
+       CYGNUS_PIN_DESC(64, "spi2_miso", 1, 0x1c, 24),
+       CYGNUS_PIN_DESC(65, "spi2_ss", 1, 0x1c, 20),
+       CYGNUS_PIN_DESC(66, "spi3_clk", 1, 0x1c, 18),
+       CYGNUS_PIN_DESC(67, "spi3_mosi", 1, 0x1c, 14),
+       CYGNUS_PIN_DESC(68, "spi3_miso", 1, 0x1c, 16),
+       CYGNUS_PIN_DESC(69, "spi3_ss", 1, 0x1c, 12),
+       CYGNUS_PIN_DESC(70, "uart0_cts", 1, 0x1c, 10),
+       CYGNUS_PIN_DESC(71, "uart0_rts", 1, 0x1c, 8),
+       CYGNUS_PIN_DESC(72, "uart0_rx", 1, 0x1c, 6),
+       CYGNUS_PIN_DESC(73, "uart0_tx", 1, 0x1c, 4),
+       CYGNUS_PIN_DESC(74, "uart1_cts", 1, 0x1c, 2),
+       CYGNUS_PIN_DESC(75, "uart1_dcd", 1, 0x1c, 0),
+       CYGNUS_PIN_DESC(76, "uart1_dsr", 1, 0x20, 14),
+       CYGNUS_PIN_DESC(77, "uart1_dtr", 1, 0x20, 12),
+       CYGNUS_PIN_DESC(78, "uart1_ri", 1, 0x20, 10),
+       CYGNUS_PIN_DESC(79, "uart1_rts", 1, 0x20, 8),
+       CYGNUS_PIN_DESC(80, "uart1_rx", 1, 0x20, 6),
+       CYGNUS_PIN_DESC(81, "uart1_tx", 1, 0x20, 4),
+       CYGNUS_PIN_DESC(82, "uart3_rx", 1, 0x20, 2),
+       CYGNUS_PIN_DESC(83, "uart3_tx", 1, 0x20, 0),
+       CYGNUS_PIN_DESC(84, "sdio1_clk_sdcard", 1, 0x14, 6),
+       CYGNUS_PIN_DESC(85, "sdio1_cmd", 1, 0x14, 4),
+       CYGNUS_PIN_DESC(86, "sdio1_data0", 1, 0x14, 2),
+       CYGNUS_PIN_DESC(87, "sdio1_data1", 1, 0x14, 0),
+       CYGNUS_PIN_DESC(88, "sdio1_data2", 1, 0x18, 30),
+       CYGNUS_PIN_DESC(89, "sdio1_data3", 1, 0x18, 28),
+       CYGNUS_PIN_DESC(90, "sdio1_wp_n", 1, 0x18, 24),
+       CYGNUS_PIN_DESC(91, "sdio1_card_rst", 1, 0x14, 10),
+       CYGNUS_PIN_DESC(92, "sdio1_led_on", 1, 0x18, 26),
+       CYGNUS_PIN_DESC(93, "sdio1_cd", 1, 0x14, 8),
+       CYGNUS_PIN_DESC(94, "sdio0_clk_sdcard", 1, 0x14, 26),
+       CYGNUS_PIN_DESC(95, "sdio0_cmd", 1, 0x14, 24),
+       CYGNUS_PIN_DESC(96, "sdio0_data0", 1, 0x14, 22),
+       CYGNUS_PIN_DESC(97, "sdio0_data1", 1, 0x14, 20),
+       CYGNUS_PIN_DESC(98, "sdio0_data2", 1, 0x14, 18),
+       CYGNUS_PIN_DESC(99, "sdio0_data3", 1, 0x14, 16),
+       CYGNUS_PIN_DESC(100, "sdio0_wp_n", 1, 0x14, 12),
+       CYGNUS_PIN_DESC(101, "sdio0_card_rst", 1, 0x14, 30),
+       CYGNUS_PIN_DESC(102, "sdio0_led_on", 1, 0x14, 14),
+       CYGNUS_PIN_DESC(103, "sdio0_cd", 1, 0x14, 28),
+       CYGNUS_PIN_DESC(104, "sflash_clk", 1, 0x18, 22),
+       CYGNUS_PIN_DESC(105, "sflash_cs_l", 1, 0x18, 20),
+       CYGNUS_PIN_DESC(106, "sflash_mosi", 1, 0x18, 14),
+       CYGNUS_PIN_DESC(107, "sflash_miso", 1, 0x18, 16),
+       CYGNUS_PIN_DESC(108, "sflash_wp_n", 1, 0x18, 12),
+       CYGNUS_PIN_DESC(109, "sflash_hold_n", 1, 0x18, 18),
+       CYGNUS_PIN_DESC(110, "nand_ale", 1, 0xc, 30),
+       CYGNUS_PIN_DESC(111, "nand_ce0_l", 1, 0xc, 28),
+       CYGNUS_PIN_DESC(112, "nand_ce1_l", 1, 0xc, 26),
+       CYGNUS_PIN_DESC(113, "nand_cle", 1, 0xc, 24),
+       CYGNUS_PIN_DESC(114, "nand_dq0", 1, 0xc, 22),
+       CYGNUS_PIN_DESC(115, "nand_dq1", 1, 0xc, 20),
+       CYGNUS_PIN_DESC(116, "nand_dq2", 1, 0xc, 18),
+       CYGNUS_PIN_DESC(117, "nand_dq3", 1, 0xc, 16),
+       CYGNUS_PIN_DESC(118, "nand_dq4", 1, 0xc, 14),
+       CYGNUS_PIN_DESC(119, "nand_dq5", 1, 0xc, 12),
+       CYGNUS_PIN_DESC(120, "nand_dq6", 1, 0xc, 10),
+       CYGNUS_PIN_DESC(121, "nand_dq7", 1, 0xc, 8),
+       CYGNUS_PIN_DESC(122, "nand_rb_l", 1, 0xc, 6),
+       CYGNUS_PIN_DESC(123, "nand_re_l", 1, 0xc, 4),
+       CYGNUS_PIN_DESC(124, "nand_we_l", 1, 0xc, 2),
+       CYGNUS_PIN_DESC(125, "nand_wp_l", 1, 0xc, 0),
+       CYGNUS_PIN_DESC(126, "lcd_clac", 1, 0x4, 26),
+       CYGNUS_PIN_DESC(127, "lcd_clcp", 1, 0x4, 24),
+       CYGNUS_PIN_DESC(128, "lcd_cld0", 1, 0x4, 22),
+       CYGNUS_PIN_DESC(129, "lcd_cld1", 1, 0x4, 0),
+       CYGNUS_PIN_DESC(130, "lcd_cld10", 1, 0x4, 20),
+       CYGNUS_PIN_DESC(131, "lcd_cld11", 1, 0x4, 18),
+       CYGNUS_PIN_DESC(132, "lcd_cld12", 1, 0x4, 16),
+       CYGNUS_PIN_DESC(133, "lcd_cld13", 1, 0x4, 14),
+       CYGNUS_PIN_DESC(134, "lcd_cld14", 1, 0x4, 12),
+       CYGNUS_PIN_DESC(135, "lcd_cld15", 1, 0x4, 10),
+       CYGNUS_PIN_DESC(136, "lcd_cld16", 1, 0x4, 8),
+       CYGNUS_PIN_DESC(137, "lcd_cld17", 1, 0x4, 6),
+       CYGNUS_PIN_DESC(138, "lcd_cld18", 1, 0x4, 4),
+       CYGNUS_PIN_DESC(139, "lcd_cld19", 1, 0x4, 2),
+       CYGNUS_PIN_DESC(140, "lcd_cld2", 1, 0x8, 22),
+       CYGNUS_PIN_DESC(141, "lcd_cld20", 1, 0x8, 30),
+       CYGNUS_PIN_DESC(142, "lcd_cld21", 1, 0x8, 28),
+       CYGNUS_PIN_DESC(143, "lcd_cld22", 1, 0x8, 26),
+       CYGNUS_PIN_DESC(144, "lcd_cld23", 1, 0x8, 24),
+       CYGNUS_PIN_DESC(145, "lcd_cld3", 1, 0x8, 20),
+       CYGNUS_PIN_DESC(146, "lcd_cld4", 1, 0x8, 18),
+       CYGNUS_PIN_DESC(147, "lcd_cld5", 1, 0x8, 16),
+       CYGNUS_PIN_DESC(148, "lcd_cld6", 1, 0x8, 14),
+       CYGNUS_PIN_DESC(149, "lcd_cld7", 1, 0x8, 12),
+       CYGNUS_PIN_DESC(150, "lcd_cld8", 1, 0x8, 10),
+       CYGNUS_PIN_DESC(151, "lcd_cld9", 1, 0x8, 8),
+       CYGNUS_PIN_DESC(152, "lcd_clfp", 1, 0x8, 6),
+       CYGNUS_PIN_DESC(153, "lcd_clle", 1, 0x8, 4),
+       CYGNUS_PIN_DESC(154, "lcd_cllp", 1, 0x8, 2),
+       CYGNUS_PIN_DESC(155, "lcd_clpower", 1, 0x8, 0),
+       CYGNUS_PIN_DESC(156, "camera_vsync", 1, 0x4, 30),
+       CYGNUS_PIN_DESC(157, "camera_trigger", 1, 0x0, 0),
+       CYGNUS_PIN_DESC(158, "camera_strobe", 1, 0x0, 2),
+       CYGNUS_PIN_DESC(159, "camera_standby", 1, 0x0, 4),
+       CYGNUS_PIN_DESC(160, "camera_reset_n", 1, 0x0, 6),
+       CYGNUS_PIN_DESC(161, "camera_pixdata9", 1, 0x0, 8),
+       CYGNUS_PIN_DESC(162, "camera_pixdata8", 1, 0x0, 10),
+       CYGNUS_PIN_DESC(163, "camera_pixdata7", 1, 0x0, 12),
+       CYGNUS_PIN_DESC(164, "camera_pixdata6", 1, 0x0, 14),
+       CYGNUS_PIN_DESC(165, "camera_pixdata5", 1, 0x0, 16),
+       CYGNUS_PIN_DESC(166, "camera_pixdata4", 1, 0x0, 18),
+       CYGNUS_PIN_DESC(167, "camera_pixdata3", 1, 0x0, 20),
+       CYGNUS_PIN_DESC(168, "camera_pixdata2", 1, 0x0, 22),
+       CYGNUS_PIN_DESC(169, "camera_pixdata1", 1, 0x0, 24),
+       CYGNUS_PIN_DESC(170, "camera_pixdata0", 1, 0x0, 26),
+       CYGNUS_PIN_DESC(171, "camera_pixclk", 1, 0x0, 28),
+       CYGNUS_PIN_DESC(172, "camera_hsync", 1, 0x0, 30),
+       CYGNUS_PIN_DESC(173, "camera_pll_ref_clk", 0, 0, 0),
+       CYGNUS_PIN_DESC(174, "usb_id_indication", 0, 0, 0),
+       CYGNUS_PIN_DESC(175, "usb_vbus_indication", 0, 0, 0),
+       CYGNUS_PIN_DESC(176, "gpio0_3p3", 0, 0, 0),
+       CYGNUS_PIN_DESC(177, "gpio1_3p3", 0, 0, 0),
+       CYGNUS_PIN_DESC(178, "gpio2_3p3", 0, 0, 0),
+       CYGNUS_PIN_DESC(179, "gpio3_3p3", 0, 0, 0),
+};
+
+/*
+ * List of groups of pins
+ */
+static const unsigned bsc1_pins[] = { 8, 9 };
+static const unsigned pcie_clkreq_pins[] = { 8, 9 };
+
+static const unsigned i2s2_0_pins[] = { 12 };
+static const unsigned i2s2_1_pins[] = { 13 };
+static const unsigned i2s2_2_pins[] = { 14 };
+static const unsigned i2s2_3_pins[] = { 15 };
+static const unsigned i2s2_4_pins[] = { 16 };
+
+static const unsigned pwm4_pins[] = { 17 };
+static const unsigned pwm5_pins[] = { 18 };
+
+static const unsigned key0_pins[] = { 20 };
+static const unsigned key1_pins[] = { 21 };
+static const unsigned key2_pins[] = { 22 };
+static const unsigned key3_pins[] = { 23 };
+static const unsigned key4_pins[] = { 24 };
+static const unsigned key5_pins[] = { 25 };
+
+static const unsigned key6_pins[] = { 26 };
+static const unsigned audio_dte0_pins[] = { 26 };
+
+static const unsigned key7_pins[] = { 27 };
+static const unsigned audio_dte1_pins[] = { 27 };
+
+static const unsigned key8_pins[] = { 28 };
+static const unsigned key9_pins[] = { 29 };
+static const unsigned key10_pins[] = { 30 };
+static const unsigned key11_pins[] = { 31 };
+static const unsigned key12_pins[] = { 32 };
+static const unsigned key13_pins[] = { 33 };
+
+static const unsigned key14_pins[] = { 34 };
+static const unsigned audio_dte2_pins[] = { 34 };
+
+static const unsigned key15_pins[] = { 35 };
+static const unsigned audio_dte3_pins[] = { 35 };
+
+static const unsigned pwm0_pins[] = { 38 };
+static const unsigned pwm1_pins[] = { 39 };
+static const unsigned pwm2_pins[] = { 40 };
+static const unsigned pwm3_pins[] = { 41 };
+
+static const unsigned sdio0_pins[] = { 94, 95, 96, 97, 98, 99 };
+
+static const unsigned smart_card0_pins[] = { 42, 43, 44, 46, 47 };
+static const unsigned i2s0_0_pins[] = { 42, 43, 44, 46 };
+static const unsigned spdif_pins[] = { 47 };
+
+static const unsigned smart_card1_pins[] = { 48, 49, 50, 52, 53 };
+static const unsigned i2s1_0_pins[] = { 48, 49, 50, 52 };
+
+static const unsigned spi0_pins[] = { 54, 55, 56, 57 };
+
+static const unsigned spi1_pins[] = { 58, 59, 60, 61 };
+
+static const unsigned spi2_pins[] = { 62, 63, 64, 65 };
+
+static const unsigned spi3_pins[] = { 66, 67, 68, 69 };
+static const unsigned sw_led0_0_pins[] = { 66, 67, 68, 69 };
+
+static const unsigned d1w_pins[] = { 10, 11 };
+static const unsigned uart4_pins[] = { 10, 11 };
+static const unsigned sw_led2_0_pins[] = { 10, 11 };
+
+static const unsigned lcd_pins[] = { 126, 127, 128, 129, 130, 131, 132, 133,
+       134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+       148, 149, 150, 151, 152, 153, 154, 155 };
+static const unsigned sram_0_pins[] = { 126, 127, 128, 129, 130, 131, 132, 133,
+       134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+       148, 149, 150, 151, 152, 153, 154, 155 };
+static const unsigned spi5_pins[] = { 141, 142, 143, 144 };
+
+static const unsigned uart0_pins[] = { 70, 71, 72, 73 };
+static const unsigned sw_led0_1_pins[] = { 70, 71, 72, 73 };
+
+static const unsigned uart1_dte_pins[] = { 75, 76, 77, 78 };
+static const unsigned uart2_pins[] = { 75, 76, 77, 78 };
+
+static const unsigned uart1_pins[] = { 74, 79, 80, 81 };
+
+static const unsigned uart3_pins[] = { 82, 83 };
+
+static const unsigned qspi_0_pins[] = { 104, 105, 106, 107 };
+
+static const unsigned nand_pins[] = { 110, 111, 112, 113, 114, 115, 116, 117,
+       118, 119, 120, 121, 122, 123, 124, 125 };
+
+static const unsigned sdio0_cd_pins[] = { 103 };
+
+static const unsigned sdio0_mmc_pins[] = { 100, 101, 102 };
+
+static const unsigned sdio1_data_0_pins[] = { 86, 87 };
+static const unsigned can0_pins[] = { 86, 87 };
+static const unsigned spi4_0_pins[] = { 86, 87 };
+
+static const unsigned sdio1_data_1_pins[] = { 88, 89 };
+static const unsigned can1_pins[] = { 88, 89 };
+static const unsigned spi4_1_pins[] = { 88, 89 };
+
+static const unsigned sdio1_cd_pins[] = { 93 };
+
+static const unsigned sdio1_led_pins[] = { 84, 85 };
+static const unsigned sw_led2_1_pins[] = { 84, 85 };
+
+static const unsigned sdio1_mmc_pins[] = { 90, 91, 92 };
+
+static const unsigned cam_led_pins[] = { 156, 157, 158, 159, 160 };
+static const unsigned sw_led1_pins[] = { 156, 157, 158, 159 };
+
+static const unsigned cam_0_pins[] = { 169, 170, 171, 169, 170 };
+
+static const unsigned cam_1_pins[] = { 161, 162, 163, 164, 165, 166, 167,
+       168 };
+static const unsigned sram_1_pins[] = { 161, 162, 163, 164, 165, 166, 167,
+       168 };
+
+static const unsigned qspi_1_pins[] = { 108, 109 };
+
+static const unsigned smart_card0_fcb_pins[] = { 45 };
+static const unsigned i2s0_1_pins[] = { 45 };
+
+static const unsigned smart_card1_fcb_pins[] = { 51 };
+static const unsigned i2s1_1_pins[] = { 51 };
+
+static const unsigned gpio0_3p3_pins[] = { 176 };
+static const unsigned usb0_oc_pins[] = { 176 };
+
+static const unsigned gpio1_3p3_pins[] = { 177 };
+static const unsigned usb1_oc_pins[] = { 177 };
+
+static const unsigned gpio2_3p3_pins[] = { 178 };
+static const unsigned usb2_oc_pins[] = { 178 };
+
+#define CYGNUS_PIN_GROUP(group_name, off, sh, al)      \
+{                                                      \
+       .name = __stringify(group_name) "_grp",         \
+       .pins = group_name ## _pins,                    \
+       .num_pins = ARRAY_SIZE(group_name ## _pins),    \
+       .mux = {                                        \
+               .offset = off,                          \
+               .shift = sh,                            \
+               .alt = al,                              \
+       }                                               \
+}
+
+/*
+ * List of Cygnus pin groups
+ */
+static const struct cygnus_pin_group cygnus_pin_groups[] = {
+       CYGNUS_PIN_GROUP(i2s2_0, 0x0, 0, 2),
+       CYGNUS_PIN_GROUP(i2s2_1, 0x0, 4, 2),
+       CYGNUS_PIN_GROUP(i2s2_2, 0x0, 8, 2),
+       CYGNUS_PIN_GROUP(i2s2_3, 0x0, 12, 2),
+       CYGNUS_PIN_GROUP(i2s2_4, 0x0, 16, 2),
+       CYGNUS_PIN_GROUP(pwm4, 0x0, 20, 0),
+       CYGNUS_PIN_GROUP(pwm5, 0x0, 24, 2),
+       CYGNUS_PIN_GROUP(key0, 0x4, 0, 1),
+       CYGNUS_PIN_GROUP(key1, 0x4, 4, 1),
+       CYGNUS_PIN_GROUP(key2, 0x4, 8, 1),
+       CYGNUS_PIN_GROUP(key3, 0x4, 12, 1),
+       CYGNUS_PIN_GROUP(key4, 0x4, 16, 1),
+       CYGNUS_PIN_GROUP(key5, 0x4, 20, 1),
+       CYGNUS_PIN_GROUP(key6, 0x4, 24, 1),
+       CYGNUS_PIN_GROUP(audio_dte0, 0x4, 24, 2),
+       CYGNUS_PIN_GROUP(key7, 0x4, 28, 1),
+       CYGNUS_PIN_GROUP(audio_dte1, 0x4, 28, 2),
+       CYGNUS_PIN_GROUP(key8, 0x8, 0, 1),
+       CYGNUS_PIN_GROUP(key9, 0x8, 4, 1),
+       CYGNUS_PIN_GROUP(key10, 0x8, 8, 1),
+       CYGNUS_PIN_GROUP(key11, 0x8, 12, 1),
+       CYGNUS_PIN_GROUP(key12, 0x8, 16, 1),
+       CYGNUS_PIN_GROUP(key13, 0x8, 20, 1),
+       CYGNUS_PIN_GROUP(key14, 0x8, 24, 1),
+       CYGNUS_PIN_GROUP(audio_dte2, 0x8, 24, 2),
+       CYGNUS_PIN_GROUP(key15, 0x8, 28, 1),
+       CYGNUS_PIN_GROUP(audio_dte3, 0x8, 28, 2),
+       CYGNUS_PIN_GROUP(pwm0, 0xc, 0, 0),
+       CYGNUS_PIN_GROUP(pwm1, 0xc, 4, 0),
+       CYGNUS_PIN_GROUP(pwm2, 0xc, 8, 0),
+       CYGNUS_PIN_GROUP(pwm3, 0xc, 12, 0),
+       CYGNUS_PIN_GROUP(sdio0, 0xc, 16, 0),
+       CYGNUS_PIN_GROUP(smart_card0, 0xc, 20, 0),
+       CYGNUS_PIN_GROUP(i2s0_0, 0xc, 20, 1),
+       CYGNUS_PIN_GROUP(spdif, 0xc, 20, 1),
+       CYGNUS_PIN_GROUP(smart_card1, 0xc, 24, 0),
+       CYGNUS_PIN_GROUP(i2s1_0, 0xc, 24, 1),
+       CYGNUS_PIN_GROUP(spi0, 0x10, 0, 0),
+       CYGNUS_PIN_GROUP(spi1, 0x10, 4, 0),
+       CYGNUS_PIN_GROUP(spi2, 0x10, 8, 0),
+       CYGNUS_PIN_GROUP(spi3, 0x10, 12, 0),
+       CYGNUS_PIN_GROUP(sw_led0_0, 0x10, 12, 2),
+       CYGNUS_PIN_GROUP(d1w, 0x10, 16, 0),
+       CYGNUS_PIN_GROUP(uart4, 0x10, 16, 1),
+       CYGNUS_PIN_GROUP(sw_led2_0, 0x10, 16, 2),
+       CYGNUS_PIN_GROUP(lcd, 0x10, 20, 0),
+       CYGNUS_PIN_GROUP(sram_0, 0x10, 20, 1),
+       CYGNUS_PIN_GROUP(spi5, 0x10, 20, 2),
+       CYGNUS_PIN_GROUP(uart0, 0x14, 0, 0),
+       CYGNUS_PIN_GROUP(sw_led0_1, 0x14, 0, 2),
+       CYGNUS_PIN_GROUP(uart1_dte, 0x14, 4, 0),
+       CYGNUS_PIN_GROUP(uart2, 0x14, 4, 1),
+       CYGNUS_PIN_GROUP(uart1, 0x14, 8, 0),
+       CYGNUS_PIN_GROUP(uart3, 0x14, 12, 0),
+       CYGNUS_PIN_GROUP(qspi_0, 0x14, 16, 0),
+       CYGNUS_PIN_GROUP(nand, 0x14, 20, 0),
+       CYGNUS_PIN_GROUP(sdio0_cd, 0x18, 0, 0),
+       CYGNUS_PIN_GROUP(sdio0_mmc, 0x18, 4, 0),
+       CYGNUS_PIN_GROUP(sdio1_data_0, 0x18, 8, 0),
+       CYGNUS_PIN_GROUP(can0, 0x18, 8, 1),
+       CYGNUS_PIN_GROUP(spi4_0, 0x18, 8, 2),
+       CYGNUS_PIN_GROUP(sdio1_data_1, 0x18, 12, 0),
+       CYGNUS_PIN_GROUP(can1, 0x18, 12, 1),
+       CYGNUS_PIN_GROUP(spi4_1, 0x18, 12, 2),
+       CYGNUS_PIN_GROUP(sdio1_cd, 0x18, 16, 0),
+       CYGNUS_PIN_GROUP(sdio1_led, 0x18, 20, 0),
+       CYGNUS_PIN_GROUP(sw_led2_1, 0x18, 20, 2),
+       CYGNUS_PIN_GROUP(sdio1_mmc, 0x18, 24, 0),
+       CYGNUS_PIN_GROUP(cam_led, 0x1c, 0, 0),
+       CYGNUS_PIN_GROUP(sw_led1, 0x1c, 0, 1),
+       CYGNUS_PIN_GROUP(cam_0, 0x1c, 4, 0),
+       CYGNUS_PIN_GROUP(cam_1, 0x1c, 8, 0),
+       CYGNUS_PIN_GROUP(sram_1, 0x1c, 8, 1),
+       CYGNUS_PIN_GROUP(qspi_1, 0x1c, 12, 0),
+       CYGNUS_PIN_GROUP(bsc1, 0x1c, 16, 0),
+       CYGNUS_PIN_GROUP(pcie_clkreq, 0x1c, 16, 1),
+       CYGNUS_PIN_GROUP(smart_card0_fcb, 0x20, 0, 0),
+       CYGNUS_PIN_GROUP(i2s0_1, 0x20, 0, 1),
+       CYGNUS_PIN_GROUP(smart_card1_fcb, 0x20, 4, 0),
+       CYGNUS_PIN_GROUP(i2s1_1, 0x20, 4, 1),
+       CYGNUS_PIN_GROUP(gpio0_3p3, 0x28, 0, 0),
+       CYGNUS_PIN_GROUP(usb0_oc, 0x28, 0, 1),
+       CYGNUS_PIN_GROUP(gpio1_3p3, 0x28, 4, 0),
+       CYGNUS_PIN_GROUP(usb1_oc, 0x28, 4, 1),
+       CYGNUS_PIN_GROUP(gpio2_3p3, 0x28, 8, 0),
+       CYGNUS_PIN_GROUP(usb2_oc, 0x28, 8, 1),
+};
+
+/*
+ * List of groups supported by functions
+ */
+static const char * const i2s0_grps[] = { "i2s0_0_grp", "i2s0_1_grp" };
+static const char * const i2s1_grps[] = { "i2s1_0_grp", "i2s1_1_grp" };
+static const char * const i2s2_grps[] = { "i2s2_0_grp", "i2s2_1_grp",
+       "i2s2_2_grp", "i2s2_3_grp", "i2s2_4_grp" };
+static const char * const spdif_grps[] = { "spdif_grp" };
+static const char * const pwm0_grps[] = { "pwm0_grp" };
+static const char * const pwm1_grps[] = { "pwm1_grp" };
+static const char * const pwm2_grps[] = { "pwm2_grp" };
+static const char * const pwm3_grps[] = { "pwm3_grp" };
+static const char * const pwm4_grps[] = { "pwm4_grp" };
+static const char * const pwm5_grps[] = { "pwm5_grp" };
+static const char * const key_grps[] = { "key0_grp", "key1_grp", "key2_grp",
+       "key3_grp", "key4_grp", "key5_grp", "key6_grp", "key7_grp", "key8_grp",
+       "key9_grp", "key10_grp", "key11_grp", "key12_grp", "key13_grp",
+       "key14_grp", "key15_grp" };
+static const char * const audio_dte_grps[] = { "audio_dte0_grp",
+       "audio_dte1_grp", "audio_dte2_grp", "audio_dte3_grp" };
+static const char * const smart_card0_grps[] = { "smart_card0_grp",
+       "smart_card0_fcb_grp" };
+static const char * const smart_card1_grps[] = { "smart_card1_grp",
+       "smart_card1_fcb_grp" };
+static const char * const spi0_grps[] = { "spi0_grp" };
+static const char * const spi1_grps[] = { "spi1_grp" };
+static const char * const spi2_grps[] = { "spi2_grp" };
+static const char * const spi3_grps[] = { "spi3_grp" };
+static const char * const spi4_grps[] = { "spi4_0_grp", "spi4_1_grp" };
+static const char * const spi5_grps[] = { "spi5_grp" };
+
+static const char * const sw_led0_grps[] = { "sw_led0_0_grp",
+       "sw_led0_1_grp" };
+static const char * const sw_led1_grps[] = { "sw_led1_grp" };
+static const char * const sw_led2_grps[] = { "sw_led2_0_grp",
+       "sw_led2_1_grp" };
+static const char * const d1w_grps[] = { "d1w_grp" };
+static const char * const lcd_grps[] = { "lcd_grp" };
+static const char * const sram_grps[] = { "sram_0_grp", "sram_1_grp" };
+
+static const char * const uart0_grps[] = { "uart0_grp" };
+static const char * const uart1_grps[] = { "uart1_grp", "uart1_dte_grp" };
+static const char * const uart2_grps[] = { "uart2_grp" };
+static const char * const uart3_grps[] = { "uart3_grp" };
+static const char * const uart4_grps[] = { "uart4_grp" };
+static const char * const qspi_grps[] = { "qspi_0_grp", "qspi_1_grp" };
+static const char * const nand_grps[] = { "nand_grp" };
+static const char * const sdio0_grps[] = { "sdio0_grp", "sdio0_cd_grp",
+       "sdio0_mmc_grp" };
+static const char * const sdio1_grps[] = { "sdio1_data_0_grp",
+       "sdio1_data_1_grp", "sdio1_cd_grp", "sdio1_led_grp", "sdio1_mmc_grp" };
+static const char * const can0_grps[] = { "can0_grp" };
+static const char * const can1_grps[] = { "can1_grp" };
+static const char * const cam_grps[] = { "cam_led_grp", "cam_0_grp",
+       "cam_1_grp" };
+static const char * const bsc1_grps[] = { "bsc1_grp" };
+static const char * const pcie_clkreq_grps[] = { "pcie_clkreq_grp" };
+static const char * const usb0_oc_grps[] = { "usb0_oc_grp" };
+static const char * const usb1_oc_grps[] = { "usb1_oc_grp" };
+static const char * const usb2_oc_grps[] = { "usb2_oc_grp" };
+
+#define CYGNUS_PIN_FUNCTION(func)                              \
+{                                                              \
+       .name = #func,                                          \
+       .groups = func ## _grps,                                \
+       .num_groups = ARRAY_SIZE(func ## _grps),                \
+}
+
+/*
+ * List of supported functions in Cygnus
+ */
+static const struct cygnus_pin_function cygnus_pin_functions[] = {
+       CYGNUS_PIN_FUNCTION(i2s0),
+       CYGNUS_PIN_FUNCTION(i2s1),
+       CYGNUS_PIN_FUNCTION(i2s2),
+       CYGNUS_PIN_FUNCTION(spdif),
+       CYGNUS_PIN_FUNCTION(pwm0),
+       CYGNUS_PIN_FUNCTION(pwm1),
+       CYGNUS_PIN_FUNCTION(pwm2),
+       CYGNUS_PIN_FUNCTION(pwm3),
+       CYGNUS_PIN_FUNCTION(pwm4),
+       CYGNUS_PIN_FUNCTION(pwm5),
+       CYGNUS_PIN_FUNCTION(key),
+       CYGNUS_PIN_FUNCTION(audio_dte),
+       CYGNUS_PIN_FUNCTION(smart_card0),
+       CYGNUS_PIN_FUNCTION(smart_card1),
+       CYGNUS_PIN_FUNCTION(spi0),
+       CYGNUS_PIN_FUNCTION(spi1),
+       CYGNUS_PIN_FUNCTION(spi2),
+       CYGNUS_PIN_FUNCTION(spi3),
+       CYGNUS_PIN_FUNCTION(spi4),
+       CYGNUS_PIN_FUNCTION(spi5),
+       CYGNUS_PIN_FUNCTION(sw_led0),
+       CYGNUS_PIN_FUNCTION(sw_led1),
+       CYGNUS_PIN_FUNCTION(sw_led2),
+       CYGNUS_PIN_FUNCTION(d1w),
+       CYGNUS_PIN_FUNCTION(lcd),
+       CYGNUS_PIN_FUNCTION(sram),
+       CYGNUS_PIN_FUNCTION(uart0),
+       CYGNUS_PIN_FUNCTION(uart1),
+       CYGNUS_PIN_FUNCTION(uart2),
+       CYGNUS_PIN_FUNCTION(uart3),
+       CYGNUS_PIN_FUNCTION(uart4),
+       CYGNUS_PIN_FUNCTION(qspi),
+       CYGNUS_PIN_FUNCTION(nand),
+       CYGNUS_PIN_FUNCTION(sdio0),
+       CYGNUS_PIN_FUNCTION(sdio1),
+       CYGNUS_PIN_FUNCTION(can0),
+       CYGNUS_PIN_FUNCTION(can1),
+       CYGNUS_PIN_FUNCTION(cam),
+       CYGNUS_PIN_FUNCTION(bsc1),
+       CYGNUS_PIN_FUNCTION(pcie_clkreq),
+       CYGNUS_PIN_FUNCTION(usb0_oc),
+       CYGNUS_PIN_FUNCTION(usb1_oc),
+       CYGNUS_PIN_FUNCTION(usb2_oc),
+};
+
+static int cygnus_get_groups_count(struct pinctrl_dev *pctrl_dev)
+{
+       struct cygnus_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+
+       return pinctrl->num_groups;
+}
+
+static const char *cygnus_get_group_name(struct pinctrl_dev *pctrl_dev,
+                                        unsigned selector)
+{
+       struct cygnus_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+
+       return pinctrl->groups[selector].name;
+}
+
+static int cygnus_get_group_pins(struct pinctrl_dev *pctrl_dev,
+                                unsigned selector, const unsigned **pins,
+                                unsigned *num_pins)
+{
+       struct cygnus_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+
+       *pins = pinctrl->groups[selector].pins;
+       *num_pins = pinctrl->groups[selector].num_pins;
+
+       return 0;
+}
+
+static void cygnus_pin_dbg_show(struct pinctrl_dev *pctrl_dev,
+                               struct seq_file *s, unsigned offset)
+{
+       seq_printf(s, " %s", dev_name(pctrl_dev->dev));
+}
+
+static const struct pinctrl_ops cygnus_pinctrl_ops = {
+       .get_groups_count = cygnus_get_groups_count,
+       .get_group_name = cygnus_get_group_name,
+       .get_group_pins = cygnus_get_group_pins,
+       .pin_dbg_show = cygnus_pin_dbg_show,
+       .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
+       .dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int cygnus_get_functions_count(struct pinctrl_dev *pctrl_dev)
+{
+       struct cygnus_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+
+       return pinctrl->num_functions;
+}
+
+static const char *cygnus_get_function_name(struct pinctrl_dev *pctrl_dev,
+                                           unsigned selector)
+{
+       struct cygnus_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+
+       return pinctrl->functions[selector].name;
+}
+
+static int cygnus_get_function_groups(struct pinctrl_dev *pctrl_dev,
+                                     unsigned selector,
+                                     const char * const **groups,
+                                     unsigned * const num_groups)
+{
+       struct cygnus_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+
+       *groups = pinctrl->functions[selector].groups;
+       *num_groups = pinctrl->functions[selector].num_groups;
+
+       return 0;
+}
+
+static int cygnus_pinmux_set(struct cygnus_pinctrl *pinctrl,
+                            const struct cygnus_pin_function *func,
+                            const struct cygnus_pin_group *grp,
+                            struct cygnus_mux_log *mux_log)
+{
+       const struct cygnus_mux *mux = &grp->mux;
+       int i;
+       u32 val, mask = 0x7;
+       unsigned long flags;
+
+       for (i = 0; i < CYGNUS_NUM_IOMUX; i++) {
+               if (mux->offset != mux_log[i].mux.offset ||
+                   mux->shift != mux_log[i].mux.shift)
+                       continue;
+
+               /* match found if we reach here */
+
+               /* if this is a new configuration, just do it! */
+               if (!mux_log[i].is_configured)
+                       break;
+
+               /*
+                * IOMUX has been configured previously and one is trying to
+                * configure it to a different function
+                */
+               if (mux_log[i].mux.alt != mux->alt) {
+                       dev_err(pinctrl->dev,
+                               "double configuration error detected!\n");
+                       dev_err(pinctrl->dev, "func:%s grp:%s\n",
+                               func->name, grp->name);
+                       return -EINVAL;
+               } else {
+                       /*
+                        * One tries to configure it to the same function.
+                        * Just quit and don't bother
+                        */
+                       return 0;
+               }
+       }
+
+       mux_log[i].mux.alt = mux->alt;
+       mux_log[i].is_configured = true;
+
+       spin_lock_irqsave(&pinctrl->lock, flags);
+
+       val = readl(pinctrl->base0 + grp->mux.offset);
+       val &= ~(mask << grp->mux.shift);
+       val |= grp->mux.alt << grp->mux.shift;
+       writel(val, pinctrl->base0 + grp->mux.offset);
+
+       spin_unlock_irqrestore(&pinctrl->lock, flags);
+
+       return 0;
+}
+
+static int cygnus_pinmux_set_mux(struct pinctrl_dev *pctrl_dev,
+                                unsigned func_select, unsigned grp_select)
+{
+       struct cygnus_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+       const struct cygnus_pin_function *func =
+               &pinctrl->functions[func_select];
+       const struct cygnus_pin_group *grp = &pinctrl->groups[grp_select];
+
+       dev_dbg(pctrl_dev->dev, "func:%u name:%s grp:%u name:%s\n",
+               func_select, func->name, grp_select, grp->name);
+
+       dev_dbg(pctrl_dev->dev, "offset:0x%08x shift:%u alt:%u\n",
+               grp->mux.offset, grp->mux.shift, grp->mux.alt);
+
+       return cygnus_pinmux_set(pinctrl, func, grp, pinctrl->mux_log);
+}
+
+static int cygnus_gpio_request_enable(struct pinctrl_dev *pctrl_dev,
+                                     struct pinctrl_gpio_range *range,
+                                     unsigned pin)
+{
+       struct cygnus_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+       const struct cygnus_gpio_mux *mux = pctrl_dev->desc->pins[pin].drv_data;
+       u32 val;
+       unsigned long flags;
+
+       /* not all pins support GPIO pinmux override */
+       if (!mux->is_supported)
+               return -ENOTSUPP;
+
+       spin_lock_irqsave(&pinctrl->lock, flags);
+
+       val = readl(pinctrl->base1 + mux->offset);
+       val |= 0x3 << mux->shift;
+       writel(val, pinctrl->base1 + mux->offset);
+
+       spin_unlock_irqrestore(&pinctrl->lock, flags);
+
+       dev_dbg(pctrl_dev->dev,
+               "gpio request enable pin=%u offset=0x%x shift=%u\n",
+               pin, mux->offset, mux->shift);
+
+       return 0;
+}
+
+static void cygnus_gpio_disable_free(struct pinctrl_dev *pctrl_dev,
+                                    struct pinctrl_gpio_range *range,
+                                    unsigned pin)
+{
+       struct cygnus_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+       struct cygnus_gpio_mux *mux = pctrl_dev->desc->pins[pin].drv_data;
+       u32 val;
+       unsigned long flags;
+
+       if (!mux->is_supported)
+               return;
+
+       spin_lock_irqsave(&pinctrl->lock, flags);
+
+       val = readl(pinctrl->base1 + mux->offset);
+       val &= ~(0x3 << mux->shift);
+       writel(val, pinctrl->base1 + mux->offset);
+
+       spin_unlock_irqrestore(&pinctrl->lock, flags);
+
+       dev_err(pctrl_dev->dev,
+               "gpio disable free pin=%u offset=0x%x shift=%u\n",
+               pin, mux->offset, mux->shift);
+}
+
+static const struct pinmux_ops cygnus_pinmux_ops = {
+       .get_functions_count = cygnus_get_functions_count,
+       .get_function_name = cygnus_get_function_name,
+       .get_function_groups = cygnus_get_function_groups,
+       .set_mux = cygnus_pinmux_set_mux,
+       .gpio_request_enable = cygnus_gpio_request_enable,
+       .gpio_disable_free = cygnus_gpio_disable_free,
+};
+
+static struct pinctrl_desc cygnus_pinctrl_desc = {
+       .name = "cygnus-pinmux",
+       .pctlops = &cygnus_pinctrl_ops,
+       .pmxops = &cygnus_pinmux_ops,
+};
+
+static int cygnus_mux_log_init(struct cygnus_pinctrl *pinctrl)
+{
+       struct cygnus_mux_log *log;
+       unsigned int i, j;
+
+       pinctrl->mux_log = devm_kcalloc(pinctrl->dev, CYGNUS_NUM_IOMUX,
+                                       sizeof(struct cygnus_mux_log),
+                                       GFP_KERNEL);
+       if (!pinctrl->mux_log)
+               return -ENOMEM;
+
+       log = pinctrl->mux_log;
+       for (i = 0; i < CYGNUS_NUM_IOMUX_REGS; i++) {
+               for (j = 0; j < CYGNUS_NUM_MUX_PER_REG; j++) {
+                       log = &pinctrl->mux_log[i * CYGNUS_NUM_MUX_PER_REG
+                               + j];
+                       log->mux.offset = i * 4;
+                       log->mux.shift = j * 4;
+                       log->mux.alt = 0;
+                       log->is_configured = false;
+               }
+       }
+
+       return 0;
+}
+
+static int cygnus_pinmux_probe(struct platform_device *pdev)
+{
+       struct cygnus_pinctrl *pinctrl;
+       struct resource *res;
+       int i, ret;
+       struct pinctrl_pin_desc *pins;
+       unsigned num_pins = ARRAY_SIZE(cygnus_pins);
+
+       pinctrl = devm_kzalloc(&pdev->dev, sizeof(*pinctrl), GFP_KERNEL);
+       if (!pinctrl)
+               return -ENOMEM;
+
+       pinctrl->dev = &pdev->dev;
+       platform_set_drvdata(pdev, pinctrl);
+       spin_lock_init(&pinctrl->lock);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       pinctrl->base0 = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pinctrl->base0)) {
+               dev_err(&pdev->dev, "unable to map I/O space\n");
+               return PTR_ERR(pinctrl->base0);
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       pinctrl->base1 = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pinctrl->base1)) {
+               dev_err(&pdev->dev, "unable to map I/O space\n");
+               return PTR_ERR(pinctrl->base1);
+       }
+
+       ret = cygnus_mux_log_init(pinctrl);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to initialize IOMUX log\n");
+               return ret;
+       }
+
+       pins = devm_kcalloc(&pdev->dev, num_pins, sizeof(*pins), GFP_KERNEL);
+       if (!pins)
+               return -ENOMEM;
+
+       for (i = 0; i < num_pins; i++) {
+               pins[i].number = cygnus_pins[i].pin;
+               pins[i].name = cygnus_pins[i].name;
+               pins[i].drv_data = &cygnus_pins[i].gpio_mux;
+       }
+
+       pinctrl->groups = cygnus_pin_groups;
+       pinctrl->num_groups = ARRAY_SIZE(cygnus_pin_groups);
+       pinctrl->functions = cygnus_pin_functions;
+       pinctrl->num_functions = ARRAY_SIZE(cygnus_pin_functions);
+       cygnus_pinctrl_desc.pins = pins;
+       cygnus_pinctrl_desc.npins = num_pins;
+
+       pinctrl->pctl = pinctrl_register(&cygnus_pinctrl_desc, &pdev->dev,
+                       pinctrl);
+       if (!pinctrl->pctl) {
+               dev_err(&pdev->dev, "unable to register Cygnus IOMUX pinctrl\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct of_device_id cygnus_pinmux_of_match[] = {
+       { .compatible = "brcm,cygnus-pinmux" },
+       { }
+};
+
+static struct platform_driver cygnus_pinmux_driver = {
+       .driver = {
+               .name = "cygnus-pinmux",
+               .of_match_table = cygnus_pinmux_of_match,
+               .suppress_bind_attrs = true,
+       },
+       .probe = cygnus_pinmux_probe,
+};
+
+static int __init cygnus_pinmux_init(void)
+{
+       return platform_driver_register(&cygnus_pinmux_driver);
+}
+arch_initcall(cygnus_pinmux_init);
+
+MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom Cygnus IOMUX driver");
+MODULE_LICENSE("GPL v2");
index 448f10986c28499449fcb970b9376c83431ec647..e261f1cf85c6c41feb14ce95c7661c0c30a96df4 100644 (file)
@@ -542,10 +542,13 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
                struct imx_pin_reg *pin_reg;
                struct imx_pin *pin = &grp->pins[i];
 
-               if (info->flags & SHARE_MUX_CONF_REG)
+               if (info->flags & SHARE_MUX_CONF_REG) {
                        conf_reg = mux_reg;
-               else
+               } else {
                        conf_reg = be32_to_cpu(*list++);
+                       if (!conf_reg)
+                               conf_reg = -1;
+               }
 
                pin_id = mux_reg ? mux_reg / 4 : conf_reg / 4;
                pin_reg = &info->pin_regs[pin_id];
@@ -645,7 +648,7 @@ int imx_pinctrl_probe(struct platform_device *pdev,
 {
        struct imx_pinctrl *ipctl;
        struct resource *res;
-       int ret;
+       int ret, i;
 
        if (!info || !info->pins || !info->npins) {
                dev_err(&pdev->dev, "wrong pinctrl info\n");
@@ -662,7 +665,11 @@ int imx_pinctrl_probe(struct platform_device *pdev,
                                      info->npins, GFP_KERNEL);
        if (!info->pin_regs)
                return -ENOMEM;
-       memset(info->pin_regs, 0xff, sizeof(*info->pin_regs) * info->npins);
+
+       for (i = 0; i < info->npins; i++) {
+               info->pin_regs[i].mux_reg = -1;
+               info->pin_regs[i].conf_reg = -1;
+       }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        ipctl->base = devm_ioremap_resource(&pdev->dev, res);
index fc86276892fd3f0fb7a152497ac0085f1e833816..37a037543d299115a09e6a4106f1592acc9566a9 100644 (file)
@@ -302,7 +302,7 @@ static struct imx_pinctrl_soc_info vf610_pinctrl_info = {
        .flags = SHARE_MUX_CONF_REG,
 };
 
-static struct of_device_id vf610_pinctrl_of_match[] = {
+static const struct of_device_id vf610_pinctrl_of_match[] = {
        { .compatible = "fsl,vf610-iomuxc", },
        { /* sentinel */ }
 };
index b801d869e91c805a3b76c76488cc4efb837ec26b..fe5e07db0a958258196da3d636c1121779e5245e 100644 (file)
@@ -25,3 +25,20 @@ config PINCTRL_CHERRYVIEW
        help
          Cherryview/Braswell pinctrl driver provides an interface that
          allows configuring of SoC pins and using them as GPIOs.
+
+config PINCTRL_INTEL
+       tristate
+       select PINMUX
+       select PINCONF
+       select GENERIC_PINCONF
+       select GPIOLIB
+       select GPIOLIB_IRQCHIP
+
+config PINCTRL_SUNRISEPOINT
+       tristate "Intel Sunrisepoint pinctrl and GPIO driver"
+       depends on ACPI
+       select PINCTRL_INTEL
+       help
+         Sunrisepoint is the PCH of Intel Skylake. This pinctrl driver
+         provides an interface that allows configuring of PCH pins and
+         using them as GPIOs.
index 4c210e4139e2162d9c6b1e57a8fcf11ddb6d537b..fee756e1255bb30aa64f2428d324501c82ddefdd 100644 (file)
@@ -2,3 +2,5 @@
 
 obj-$(CONFIG_PINCTRL_BAYTRAIL)         += pinctrl-baytrail.o
 obj-$(CONFIG_PINCTRL_CHERRYVIEW)       += pinctrl-cherryview.o
+obj-$(CONFIG_PINCTRL_INTEL)            += pinctrl-intel.o
+obj-$(CONFIG_PINCTRL_SUNRISEPOINT)     += pinctrl-sunrisepoint.o
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
new file mode 100644 (file)
index 0000000..00768e5
--- /dev/null
@@ -0,0 +1,1149 @@
+/*
+ * Intel pinctrl/GPIO core driver.
+ *
+ * Copyright (C) 2015, Intel Corporation
+ * Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
+ *          Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+
+#include "pinctrl-intel.h"
+
+/* Maximum number of pads in each group */
+#define NPADS_IN_GPP                   24
+
+/* Offset from regs */
+#define PADBAR                         0x00c
+#define GPI_IS                         0x100
+#define GPI_GPE_STS                    0x140
+#define GPI_GPE_EN                     0x160
+
+#define PADOWN_BITS                    4
+#define PADOWN_SHIFT(p)                        ((p) % 8 * PADOWN_BITS)
+#define PADOWN_MASK(p)                 (0xf << PADOWN_SHIFT(p))
+
+/* Offset from pad_regs */
+#define PADCFG0                                0x000
+#define PADCFG0_RXEVCFG_SHIFT          25
+#define PADCFG0_RXEVCFG_MASK           (3 << PADCFG0_RXEVCFG_SHIFT)
+#define PADCFG0_RXEVCFG_LEVEL          0
+#define PADCFG0_RXEVCFG_EDGE           1
+#define PADCFG0_RXEVCFG_DISABLED       2
+#define PADCFG0_RXEVCFG_EDGE_BOTH      3
+#define PADCFG0_RXINV                  BIT(23)
+#define PADCFG0_GPIROUTIOXAPIC         BIT(20)
+#define PADCFG0_GPIROUTSCI             BIT(19)
+#define PADCFG0_GPIROUTSMI             BIT(18)
+#define PADCFG0_GPIROUTNMI             BIT(17)
+#define PADCFG0_PMODE_SHIFT            10
+#define PADCFG0_PMODE_MASK             (0xf << PADCFG0_PMODE_SHIFT)
+#define PADCFG0_GPIORXDIS              BIT(9)
+#define PADCFG0_GPIOTXDIS              BIT(8)
+#define PADCFG0_GPIORXSTATE            BIT(1)
+#define PADCFG0_GPIOTXSTATE            BIT(0)
+
+#define PADCFG1                                0x004
+#define PADCFG1_TERM_UP                        BIT(13)
+#define PADCFG1_TERM_SHIFT             10
+#define PADCFG1_TERM_MASK              (7 << PADCFG1_TERM_SHIFT)
+#define PADCFG1_TERM_20K               4
+#define PADCFG1_TERM_2K                        3
+#define PADCFG1_TERM_5K                        2
+#define PADCFG1_TERM_1K                        1
+
+struct intel_pad_context {
+       u32 padcfg0;
+       u32 padcfg1;
+};
+
+struct intel_community_context {
+       u32 *intmask;
+};
+
+struct intel_pinctrl_context {
+       struct intel_pad_context *pads;
+       struct intel_community_context *communities;
+};
+
+/**
+ * struct intel_pinctrl - Intel pinctrl private structure
+ * @dev: Pointer to the device structure
+ * @lock: Lock to serialize register access
+ * @pctldesc: Pin controller description
+ * @pctldev: Pointer to the pin controller device
+ * @chip: GPIO chip in this pin controller
+ * @soc: SoC/PCH specific pin configuration data
+ * @communities: All communities in this pin controller
+ * @ncommunities: Number of communities in this pin controller
+ * @context: Configuration saved over system sleep
+ */
+struct intel_pinctrl {
+       struct device *dev;
+       spinlock_t lock;
+       struct pinctrl_desc pctldesc;
+       struct pinctrl_dev *pctldev;
+       struct gpio_chip chip;
+       const struct intel_pinctrl_soc_data *soc;
+       struct intel_community *communities;
+       size_t ncommunities;
+       struct intel_pinctrl_context context;
+};
+
+#define gpiochip_to_pinctrl(c) container_of(c, struct intel_pinctrl, chip)
+#define pin_to_padno(c, p)     ((p) - (c)->pin_base)
+
+static struct intel_community *intel_get_community(struct intel_pinctrl *pctrl,
+                                                  unsigned pin)
+{
+       struct intel_community *community;
+       int i;
+
+       for (i = 0; i < pctrl->ncommunities; i++) {
+               community = &pctrl->communities[i];
+               if (pin >= community->pin_base &&
+                   pin < community->pin_base + community->npins)
+                       return community;
+       }
+
+       dev_warn(pctrl->dev, "failed to find community for pin %u\n", pin);
+       return NULL;
+}
+
+static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl, unsigned pin,
+                                     unsigned reg)
+{
+       const struct intel_community *community;
+       unsigned padno;
+
+       community = intel_get_community(pctrl, pin);
+       if (!community)
+               return NULL;
+
+       padno = pin_to_padno(community, pin);
+       return community->pad_regs + reg + padno * 8;
+}
+
+static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
+{
+       const struct intel_community *community;
+       unsigned padno, gpp, gpp_offset, offset;
+       void __iomem *padown;
+
+       community = intel_get_community(pctrl, pin);
+       if (!community)
+               return false;
+       if (!community->padown_offset)
+               return true;
+
+       padno = pin_to_padno(community, pin);
+       gpp = padno / NPADS_IN_GPP;
+       gpp_offset = padno % NPADS_IN_GPP;
+       offset = community->padown_offset + gpp * 16 + (gpp_offset / 8) * 4;
+       padown = community->regs + offset;
+
+       return !(readl(padown) & PADOWN_MASK(padno));
+}
+
+static bool intel_pad_reserved_for_acpi(struct intel_pinctrl *pctrl,
+                                       unsigned pin)
+{
+       const struct intel_community *community;
+       unsigned padno, gpp, offset;
+       void __iomem *hostown;
+
+       community = intel_get_community(pctrl, pin);
+       if (!community)
+               return true;
+       if (!community->hostown_offset)
+               return false;
+
+       padno = pin_to_padno(community, pin);
+       gpp = padno / NPADS_IN_GPP;
+       offset = community->hostown_offset + gpp * 4;
+       hostown = community->regs + offset;
+
+       return !(readl(hostown) & BIT(padno % NPADS_IN_GPP));
+}
+
+static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned pin)
+{
+       struct intel_community *community;
+       unsigned padno, gpp, offset;
+       u32 value;
+
+       community = intel_get_community(pctrl, pin);
+       if (!community)
+               return true;
+       if (!community->padcfglock_offset)
+               return false;
+
+       padno = pin_to_padno(community, pin);
+       gpp = padno / NPADS_IN_GPP;
+
+       /*
+        * If PADCFGLOCK and PADCFGLOCKTX bits are both clear for this pad,
+        * the pad is considered unlocked. Any other case means that it is
+        * either fully or partially locked and we don't touch it.
+        */
+       offset = community->padcfglock_offset + gpp * 8;
+       value = readl(community->regs + offset);
+       if (value & BIT(pin % NPADS_IN_GPP))
+               return true;
+
+       offset = community->padcfglock_offset + 4 + gpp * 8;
+       value = readl(community->regs + offset);
+       if (value & BIT(pin % NPADS_IN_GPP))
+               return true;
+
+       return false;
+}
+
+static bool intel_pad_usable(struct intel_pinctrl *pctrl, unsigned pin)
+{
+       return intel_pad_owned_by_host(pctrl, pin) &&
+               !intel_pad_reserved_for_acpi(pctrl, pin) &&
+               !intel_pad_locked(pctrl, pin);
+}
+
+static int intel_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctrl->soc->ngroups;
+}
+
+static const char *intel_get_group_name(struct pinctrl_dev *pctldev,
+                                     unsigned group)
+{
+       struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctrl->soc->groups[group].name;
+}
+
+static int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
+                             const unsigned **pins, unsigned *npins)
+{
+       struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+       *pins = pctrl->soc->groups[group].pins;
+       *npins = pctrl->soc->groups[group].npins;
+       return 0;
+}
+
+static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+                              unsigned pin)
+{
+       struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+       u32 cfg0, cfg1, mode;
+       bool locked, acpi;
+
+       if (!intel_pad_owned_by_host(pctrl, pin)) {
+               seq_puts(s, "not available");
+               return;
+       }
+
+       cfg0 = readl(intel_get_padcfg(pctrl, pin, PADCFG0));
+       cfg1 = readl(intel_get_padcfg(pctrl, pin, PADCFG1));
+
+       mode = (cfg0 & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
+       if (!mode)
+               seq_puts(s, "GPIO ");
+       else
+               seq_printf(s, "mode %d ", mode);
+
+       seq_printf(s, "0x%08x 0x%08x", cfg0, cfg1);
+
+       locked = intel_pad_locked(pctrl, pin);
+       acpi = intel_pad_reserved_for_acpi(pctrl, pin);
+
+       if (locked || acpi) {
+               seq_puts(s, " [");
+               if (locked) {
+                       seq_puts(s, "LOCKED");
+                       if (acpi)
+                               seq_puts(s, ", ");
+               }
+               if (acpi)
+                       seq_puts(s, "ACPI");
+               seq_puts(s, "]");
+       }
+}
+
+static const struct pinctrl_ops intel_pinctrl_ops = {
+       .get_groups_count = intel_get_groups_count,
+       .get_group_name = intel_get_group_name,
+       .get_group_pins = intel_get_group_pins,
+       .pin_dbg_show = intel_pin_dbg_show,
+};
+
+static int intel_get_functions_count(struct pinctrl_dev *pctldev)
+{
+       struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctrl->soc->nfunctions;
+}
+
+static const char *intel_get_function_name(struct pinctrl_dev *pctldev,
+                                          unsigned function)
+{
+       struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctrl->soc->functions[function].name;
+}
+
+static int intel_get_function_groups(struct pinctrl_dev *pctldev,
+                                    unsigned function,
+                                    const char * const **groups,
+                                    unsigned * const ngroups)
+{
+       struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+       *groups = pctrl->soc->functions[function].groups;
+       *ngroups = pctrl->soc->functions[function].ngroups;
+       return 0;
+}
+
+static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned function,
+                               unsigned group)
+{
+       struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+       const struct intel_pingroup *grp = &pctrl->soc->groups[group];
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&pctrl->lock, flags);
+
+       /*
+        * All pins in the groups needs to be accessible and writable
+        * before we can enable the mux for this group.
+        */
+       for (i = 0; i < grp->npins; i++) {
+               if (!intel_pad_usable(pctrl, grp->pins[i])) {
+                       spin_unlock_irqrestore(&pctrl->lock, flags);
+                       return -EBUSY;
+               }
+       }
+
+       /* Now enable the mux setting for each pin in the group */
+       for (i = 0; i < grp->npins; i++) {
+               void __iomem *padcfg0;
+               u32 value;
+
+               padcfg0 = intel_get_padcfg(pctrl, grp->pins[i], PADCFG0);
+               value = readl(padcfg0);
+
+               value &= ~PADCFG0_PMODE_MASK;
+               value |= grp->mode << PADCFG0_PMODE_SHIFT;
+
+               writel(value, padcfg0);
+       }
+
+       spin_unlock_irqrestore(&pctrl->lock, flags);
+
+       return 0;
+}
+
+static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
+                                    struct pinctrl_gpio_range *range,
+                                    unsigned pin)
+{
+       struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+       void __iomem *padcfg0;
+       unsigned long flags;
+       u32 value;
+
+       spin_lock_irqsave(&pctrl->lock, flags);
+
+       if (!intel_pad_usable(pctrl, pin)) {
+               spin_unlock_irqrestore(&pctrl->lock, flags);
+               return -EBUSY;
+       }
+
+       padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
+       /* Put the pad into GPIO mode */
+       value = readl(padcfg0) & ~PADCFG0_PMODE_MASK;
+       /* Disable SCI/SMI/NMI generation */
+       value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
+       value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI);
+       /* Disable TX buffer and enable RX (this will be input) */
+       value &= ~PADCFG0_GPIORXDIS;
+       value |= PADCFG0_GPIOTXDIS;
+       writel(value, padcfg0);
+
+       spin_unlock_irqrestore(&pctrl->lock, flags);
+
+       return 0;
+}
+
+static int intel_gpio_set_direction(struct pinctrl_dev *pctldev,
+                                   struct pinctrl_gpio_range *range,
+                                   unsigned pin, bool input)
+{
+       struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+       void __iomem *padcfg0;
+       unsigned long flags;
+       u32 value;
+
+       spin_lock_irqsave(&pctrl->lock, flags);
+
+       padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
+
+       value = readl(padcfg0);
+       if (input)
+               value |= PADCFG0_GPIOTXDIS;
+       else
+               value &= ~PADCFG0_GPIOTXDIS;
+       writel(value, padcfg0);
+
+       spin_unlock_irqrestore(&pctrl->lock, flags);
+
+       return 0;
+}
+
+static const struct pinmux_ops intel_pinmux_ops = {
+       .get_functions_count = intel_get_functions_count,
+       .get_function_name = intel_get_function_name,
+       .get_function_groups = intel_get_function_groups,
+       .set_mux = intel_pinmux_set_mux,
+       .gpio_request_enable = intel_gpio_request_enable,
+       .gpio_set_direction = intel_gpio_set_direction,
+};
+
+static int intel_config_get(struct pinctrl_dev *pctldev, unsigned pin,
+                           unsigned long *config)
+{
+       struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+       enum pin_config_param param = pinconf_to_config_param(*config);
+       u32 value, term;
+       u16 arg = 0;
+
+       if (!intel_pad_owned_by_host(pctrl, pin))
+               return -ENOTSUPP;
+
+       value = readl(intel_get_padcfg(pctrl, pin, PADCFG1));
+       term = (value & PADCFG1_TERM_MASK) >> PADCFG1_TERM_SHIFT;
+
+       switch (param) {
+       case PIN_CONFIG_BIAS_DISABLE:
+               if (term)
+                       return -EINVAL;
+               break;
+
+       case PIN_CONFIG_BIAS_PULL_UP:
+               if (!term || !(value & PADCFG1_TERM_UP))
+                       return -EINVAL;
+
+               switch (term) {
+               case PADCFG1_TERM_1K:
+                       arg = 1000;
+                       break;
+               case PADCFG1_TERM_2K:
+                       arg = 2000;
+                       break;
+               case PADCFG1_TERM_5K:
+                       arg = 5000;
+                       break;
+               case PADCFG1_TERM_20K:
+                       arg = 20000;
+                       break;
+               }
+
+               break;
+
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               if (!term || value & PADCFG1_TERM_UP)
+                       return -EINVAL;
+
+               switch (term) {
+               case PADCFG1_TERM_5K:
+                       arg = 5000;
+                       break;
+               case PADCFG1_TERM_20K:
+                       arg = 20000;
+                       break;
+               }
+
+               break;
+
+       default:
+               return -ENOTSUPP;
+       }
+
+       *config = pinconf_to_config_packed(param, arg);
+       return 0;
+}
+
+static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin,
+                                unsigned long config)
+{
+       unsigned param = pinconf_to_config_param(config);
+       unsigned arg = pinconf_to_config_argument(config);
+       void __iomem *padcfg1;
+       unsigned long flags;
+       int ret = 0;
+       u32 value;
+
+       spin_lock_irqsave(&pctrl->lock, flags);
+
+       padcfg1 = intel_get_padcfg(pctrl, pin, PADCFG1);
+       value = readl(padcfg1);
+
+       switch (param) {
+       case PIN_CONFIG_BIAS_DISABLE:
+               value &= ~(PADCFG1_TERM_MASK | PADCFG1_TERM_UP);
+               break;
+
+       case PIN_CONFIG_BIAS_PULL_UP:
+               value &= ~PADCFG1_TERM_MASK;
+
+               value |= PADCFG1_TERM_UP;
+
+               switch (arg) {
+               case 20000:
+                       value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT;
+                       break;
+               case 5000:
+                       value |= PADCFG1_TERM_5K << PADCFG1_TERM_SHIFT;
+                       break;
+               case 2000:
+                       value |= PADCFG1_TERM_2K << PADCFG1_TERM_SHIFT;
+                       break;
+               case 1000:
+                       value |= PADCFG1_TERM_1K << PADCFG1_TERM_SHIFT;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+
+               break;
+
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               value &= ~(PADCFG1_TERM_UP | PADCFG1_TERM_MASK);
+
+               switch (arg) {
+               case 20000:
+                       value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT;
+                       break;
+               case 5000:
+                       value |= PADCFG1_TERM_5K << PADCFG1_TERM_SHIFT;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+
+               break;
+       }
+
+       if (!ret)
+               writel(value, padcfg1);
+
+       spin_unlock_irqrestore(&pctrl->lock, flags);
+
+       return ret;
+}
+
+static int intel_config_set(struct pinctrl_dev *pctldev, unsigned pin,
+                         unsigned long *configs, unsigned nconfigs)
+{
+       struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+       int i, ret;
+
+       if (!intel_pad_usable(pctrl, pin))
+               return -ENOTSUPP;
+
+       for (i = 0; i < nconfigs; i++) {
+               switch (pinconf_to_config_param(configs[i])) {
+               case PIN_CONFIG_BIAS_DISABLE:
+               case PIN_CONFIG_BIAS_PULL_UP:
+               case PIN_CONFIG_BIAS_PULL_DOWN:
+                       ret = intel_config_set_pull(pctrl, pin, configs[i]);
+                       if (ret)
+                               return ret;
+                       break;
+
+               default:
+                       return -ENOTSUPP;
+               }
+       }
+
+       return 0;
+}
+
+static const struct pinconf_ops intel_pinconf_ops = {
+       .is_generic = true,
+       .pin_config_get = intel_config_get,
+       .pin_config_set = intel_config_set,
+};
+
+static const struct pinctrl_desc intel_pinctrl_desc = {
+       .pctlops = &intel_pinctrl_ops,
+       .pmxops = &intel_pinmux_ops,
+       .confops = &intel_pinconf_ops,
+       .owner = THIS_MODULE,
+};
+
+static int intel_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void intel_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       pinctrl_free_gpio(chip->base + offset);
+}
+
+static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(chip);
+       void __iomem *reg;
+
+       reg = intel_get_padcfg(pctrl, offset, PADCFG0);
+       if (!reg)
+               return -EINVAL;
+
+       return !!(readl(reg) & PADCFG0_GPIORXSTATE);
+}
+
+static void intel_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(chip);
+       void __iomem *reg;
+
+       reg = intel_get_padcfg(pctrl, offset, PADCFG0);
+       if (reg) {
+               unsigned long flags;
+               u32 padcfg0;
+
+               spin_lock_irqsave(&pctrl->lock, flags);
+               padcfg0 = readl(reg);
+               if (value)
+                       padcfg0 |= PADCFG0_GPIOTXSTATE;
+               else
+                       padcfg0 &= ~PADCFG0_GPIOTXSTATE;
+               writel(padcfg0, reg);
+               spin_unlock_irqrestore(&pctrl->lock, flags);
+       }
+}
+
+static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int intel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                                      int value)
+{
+       intel_gpio_set(chip, offset, value);
+       return pinctrl_gpio_direction_output(chip->base + offset);
+}
+
+static const struct gpio_chip intel_gpio_chip = {
+       .owner = THIS_MODULE,
+       .request = intel_gpio_request,
+       .free = intel_gpio_free,
+       .direction_input = intel_gpio_direction_input,
+       .direction_output = intel_gpio_direction_output,
+       .get = intel_gpio_get,
+       .set = intel_gpio_set,
+};
+
+static void intel_gpio_irq_ack(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
+       const struct intel_community *community;
+       unsigned pin = irqd_to_hwirq(d);
+
+       spin_lock(&pctrl->lock);
+
+       community = intel_get_community(pctrl, pin);
+       if (community) {
+               unsigned padno = pin_to_padno(community, pin);
+               unsigned gpp_offset = padno % NPADS_IN_GPP;
+               unsigned gpp = padno / NPADS_IN_GPP;
+
+               writel(BIT(gpp_offset), community->regs + GPI_IS + gpp * 4);
+       }
+
+       spin_unlock(&pctrl->lock);
+}
+
+static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
+       const struct intel_community *community;
+       unsigned pin = irqd_to_hwirq(d);
+       unsigned long flags;
+
+       spin_lock_irqsave(&pctrl->lock, flags);
+
+       community = intel_get_community(pctrl, pin);
+       if (community) {
+               unsigned padno = pin_to_padno(community, pin);
+               unsigned gpp_offset = padno % NPADS_IN_GPP;
+               unsigned gpp = padno / NPADS_IN_GPP;
+               void __iomem *reg;
+               u32 value;
+
+               reg = community->regs + community->ie_offset + gpp * 4;
+               value = readl(reg);
+               if (mask)
+                       value &= ~BIT(gpp_offset);
+               else
+                       value |= BIT(gpp_offset);
+               writel(value, reg);
+       }
+
+       spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static void intel_gpio_irq_mask(struct irq_data *d)
+{
+       intel_gpio_irq_mask_unmask(d, true);
+}
+
+static void intel_gpio_irq_unmask(struct irq_data *d)
+{
+       intel_gpio_irq_mask_unmask(d, false);
+}
+
+static int intel_gpio_irq_type(struct irq_data *d, unsigned type)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
+       unsigned pin = irqd_to_hwirq(d);
+       unsigned long flags;
+       void __iomem *reg;
+       u32 value;
+
+       reg = intel_get_padcfg(pctrl, pin, PADCFG0);
+       if (!reg)
+               return -EINVAL;
+
+       spin_lock_irqsave(&pctrl->lock, flags);
+
+       value = readl(reg);
+
+       value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV);
+
+       if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+               value |= PADCFG0_RXEVCFG_EDGE_BOTH << PADCFG0_RXEVCFG_SHIFT;
+       } else if (type & IRQ_TYPE_EDGE_FALLING) {
+               value |= PADCFG0_RXEVCFG_EDGE << PADCFG0_RXEVCFG_SHIFT;
+               value |= PADCFG0_RXINV;
+       } else if (type & IRQ_TYPE_EDGE_RISING) {
+               value |= PADCFG0_RXEVCFG_EDGE << PADCFG0_RXEVCFG_SHIFT;
+       } else if (type & IRQ_TYPE_LEVEL_LOW) {
+               value |= PADCFG0_RXINV;
+       } else {
+               value |= PADCFG0_RXEVCFG_DISABLED << PADCFG0_RXEVCFG_SHIFT;
+       }
+
+       writel(value, reg);
+
+       if (type & IRQ_TYPE_EDGE_BOTH)
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
+       else if (type & IRQ_TYPE_LEVEL_MASK)
+               __irq_set_handler_locked(d->irq, handle_level_irq);
+
+       spin_unlock_irqrestore(&pctrl->lock, flags);
+
+       return 0;
+}
+
+static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
+       const struct intel_community *community;
+       unsigned pin = irqd_to_hwirq(d);
+       unsigned padno, gpp, gpp_offset;
+       u32 gpe_en;
+
+       community = intel_get_community(pctrl, pin);
+       if (!community)
+               return -EINVAL;
+
+       padno = pin_to_padno(community, pin);
+       gpp = padno / NPADS_IN_GPP;
+       gpp_offset = padno % NPADS_IN_GPP;
+
+       /* Clear the existing wake status */
+       writel(BIT(gpp_offset), community->regs + GPI_GPE_STS + gpp * 4);
+
+       /*
+        * The controller will generate wake when GPE of the corresponding
+        * pad is enabled and it is not routed to SCI (GPIROUTSCI is not
+        * set).
+        */
+       gpe_en = readl(community->regs + GPI_GPE_EN + gpp * 4);
+       if (on)
+               gpe_en |= BIT(gpp_offset);
+       else
+               gpe_en &= ~BIT(gpp_offset);
+       writel(gpe_en, community->regs + GPI_GPE_EN + gpp * 4);
+
+       dev_dbg(pctrl->dev, "%sable wake for pin %u\n", on ? "en" : "dis", pin);
+       return 0;
+}
+
+static void intel_gpio_community_irq_handler(struct gpio_chip *gc,
+       const struct intel_community *community)
+{
+       int gpp;
+
+       for (gpp = 0; gpp < community->ngpps; gpp++) {
+               unsigned long pending, enabled, gpp_offset;
+
+               pending = readl(community->regs + GPI_IS + gpp * 4);
+               enabled = readl(community->regs + community->ie_offset +
+                               gpp * 4);
+
+               /* Only interrupts that are enabled */
+               pending &= enabled;
+
+               for_each_set_bit(gpp_offset, &pending, NPADS_IN_GPP) {
+                       unsigned padno, irq;
+
+                       /*
+                        * The last group in community can have less pins
+                        * than NPADS_IN_GPP.
+                        */
+                       padno = gpp_offset + gpp * NPADS_IN_GPP;
+                       if (padno >= community->npins)
+                               break;
+
+                       irq = irq_find_mapping(gc->irqdomain,
+                                              community->pin_base + padno);
+                       generic_handle_irq(irq);
+               }
+       }
+}
+
+static void intel_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+       struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+       struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
+       struct irq_chip *chip = irq_get_chip(irq);
+       int i;
+
+       chained_irq_enter(chip, desc);
+
+       /* Need to check all communities for pending interrupts */
+       for (i = 0; i < pctrl->ncommunities; i++)
+               intel_gpio_community_irq_handler(gc, &pctrl->communities[i]);
+
+       chained_irq_exit(chip, desc);
+}
+
+static struct irq_chip intel_gpio_irqchip = {
+       .name = "intel-gpio",
+       .irq_ack = intel_gpio_irq_ack,
+       .irq_mask = intel_gpio_irq_mask,
+       .irq_unmask = intel_gpio_irq_unmask,
+       .irq_set_type = intel_gpio_irq_type,
+       .irq_set_wake = intel_gpio_irq_wake,
+};
+
+static void intel_gpio_irq_init(struct intel_pinctrl *pctrl)
+{
+       size_t i;
+
+       for (i = 0; i < pctrl->ncommunities; i++) {
+               const struct intel_community *community;
+               void __iomem *base;
+               unsigned gpp;
+
+               community = &pctrl->communities[i];
+               base = community->regs;
+
+               for (gpp = 0; gpp < community->ngpps; gpp++) {
+                       /* Mask and clear all interrupts */
+                       writel(0, base + community->ie_offset + gpp * 4);
+                       writel(0xffff, base + GPI_IS + gpp * 4);
+               }
+       }
+}
+
+static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
+{
+       int ret;
+
+       pctrl->chip = intel_gpio_chip;
+
+       pctrl->chip.ngpio = pctrl->soc->npins;
+       pctrl->chip.label = dev_name(pctrl->dev);
+       pctrl->chip.dev = pctrl->dev;
+       pctrl->chip.base = -1;
+
+       ret = gpiochip_add(&pctrl->chip);
+       if (ret) {
+               dev_err(pctrl->dev, "failed to register gpiochip\n");
+               return ret;
+       }
+
+       ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
+                                    0, 0, pctrl->soc->npins);
+       if (ret) {
+               dev_err(pctrl->dev, "failed to add GPIO pin range\n");
+               gpiochip_remove(&pctrl->chip);
+               return ret;
+       }
+
+       ret = gpiochip_irqchip_add(&pctrl->chip, &intel_gpio_irqchip, 0,
+                                  handle_simple_irq, IRQ_TYPE_NONE);
+       if (ret) {
+               dev_err(pctrl->dev, "failed to add irqchip\n");
+               gpiochip_remove(&pctrl->chip);
+               return ret;
+       }
+
+       gpiochip_set_chained_irqchip(&pctrl->chip, &intel_gpio_irqchip, irq,
+                                    intel_gpio_irq_handler);
+       return 0;
+}
+
+static int intel_pinctrl_pm_init(struct intel_pinctrl *pctrl)
+{
+#ifdef CONFIG_PM_SLEEP
+       const struct intel_pinctrl_soc_data *soc = pctrl->soc;
+       struct intel_community_context *communities;
+       struct intel_pad_context *pads;
+       int i;
+
+       pads = devm_kcalloc(pctrl->dev, soc->npins, sizeof(*pads), GFP_KERNEL);
+       if (!pads)
+               return -ENOMEM;
+
+       communities = devm_kcalloc(pctrl->dev, pctrl->ncommunities,
+                                  sizeof(*communities), GFP_KERNEL);
+       if (!communities)
+               return -ENOMEM;
+
+
+       for (i = 0; i < pctrl->ncommunities; i++) {
+               struct intel_community *community = &pctrl->communities[i];
+               u32 *intmask;
+
+               intmask = devm_kcalloc(pctrl->dev, community->ngpps,
+                                      sizeof(*intmask), GFP_KERNEL);
+               if (!intmask)
+                       return -ENOMEM;
+
+               communities[i].intmask = intmask;
+       }
+
+       pctrl->context.pads = pads;
+       pctrl->context.communities = communities;
+#endif
+
+       return 0;
+}
+
+int intel_pinctrl_probe(struct platform_device *pdev,
+                       const struct intel_pinctrl_soc_data *soc_data)
+{
+       struct intel_pinctrl *pctrl;
+       int i, ret, irq;
+
+       if (!soc_data)
+               return -EINVAL;
+
+       pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
+       if (!pctrl)
+               return -ENOMEM;
+
+       pctrl->dev = &pdev->dev;
+       pctrl->soc = soc_data;
+       spin_lock_init(&pctrl->lock);
+
+       /*
+        * Make a copy of the communities which we can use to hold pointers
+        * to the registers.
+        */
+       pctrl->ncommunities = pctrl->soc->ncommunities;
+       pctrl->communities = devm_kcalloc(&pdev->dev, pctrl->ncommunities,
+                                 sizeof(*pctrl->communities), GFP_KERNEL);
+       if (!pctrl->communities)
+               return -ENOMEM;
+
+       for (i = 0; i < pctrl->ncommunities; i++) {
+               struct intel_community *community = &pctrl->communities[i];
+               struct resource *res;
+               void __iomem *regs;
+               u32 padbar;
+
+               *community = pctrl->soc->communities[i];
+
+               res = platform_get_resource(pdev, IORESOURCE_MEM,
+                                           community->barno);
+               regs = devm_ioremap_resource(&pdev->dev, res);
+               if (IS_ERR(regs))
+                       return PTR_ERR(regs);
+
+               /* Read offset of the pad configuration registers */
+               padbar = readl(regs + PADBAR);
+
+               community->regs = regs;
+               community->pad_regs = regs + padbar;
+               community->ngpps = DIV_ROUND_UP(community->npins, NPADS_IN_GPP);
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "failed to get interrupt number\n");
+               return irq;
+       }
+
+       ret = intel_pinctrl_pm_init(pctrl);
+       if (ret)
+               return ret;
+
+       pctrl->pctldesc = intel_pinctrl_desc;
+       pctrl->pctldesc.name = dev_name(&pdev->dev);
+       pctrl->pctldesc.pins = pctrl->soc->pins;
+       pctrl->pctldesc.npins = pctrl->soc->npins;
+
+       pctrl->pctldev = pinctrl_register(&pctrl->pctldesc, &pdev->dev, pctrl);
+       if (!pctrl->pctldev) {
+               dev_err(&pdev->dev, "failed to register pinctrl driver\n");
+               return -ENODEV;
+       }
+
+       ret = intel_gpio_probe(pctrl, irq);
+       if (ret) {
+               pinctrl_unregister(pctrl->pctldev);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, pctrl);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(intel_pinctrl_probe);
+
+int intel_pinctrl_remove(struct platform_device *pdev)
+{
+       struct intel_pinctrl *pctrl = platform_get_drvdata(pdev);
+
+       gpiochip_remove(&pctrl->chip);
+       pinctrl_unregister(pctrl->pctldev);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(intel_pinctrl_remove);
+
+#ifdef CONFIG_PM_SLEEP
+int intel_pinctrl_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct intel_pinctrl *pctrl = platform_get_drvdata(pdev);
+       struct intel_community_context *communities;
+       struct intel_pad_context *pads;
+       int i;
+
+       pads = pctrl->context.pads;
+       for (i = 0; i < pctrl->soc->npins; i++) {
+               const struct pinctrl_pin_desc *desc = &pctrl->soc->pins[i];
+               u32 val;
+
+               if (!intel_pad_usable(pctrl, desc->number))
+                       continue;
+
+               val = readl(intel_get_padcfg(pctrl, desc->number, PADCFG0));
+               pads[i].padcfg0 = val & ~PADCFG0_GPIORXSTATE;
+               val = readl(intel_get_padcfg(pctrl, desc->number, PADCFG1));
+               pads[i].padcfg1 = val;
+       }
+
+       communities = pctrl->context.communities;
+       for (i = 0; i < pctrl->ncommunities; i++) {
+               struct intel_community *community = &pctrl->communities[i];
+               void __iomem *base;
+               unsigned gpp;
+
+               base = community->regs + community->ie_offset;
+               for (gpp = 0; gpp < community->ngpps; gpp++)
+                       communities[i].intmask[gpp] = readl(base + gpp * 4);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(intel_pinctrl_suspend);
+
+int intel_pinctrl_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct intel_pinctrl *pctrl = platform_get_drvdata(pdev);
+       const struct intel_community_context *communities;
+       const struct intel_pad_context *pads;
+       int i;
+
+       /* Mask all interrupts */
+       intel_gpio_irq_init(pctrl);
+
+       pads = pctrl->context.pads;
+       for (i = 0; i < pctrl->soc->npins; i++) {
+               const struct pinctrl_pin_desc *desc = &pctrl->soc->pins[i];
+               void __iomem *padcfg;
+               u32 val;
+
+               if (!intel_pad_usable(pctrl, desc->number))
+                       continue;
+
+               padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG0);
+               val = readl(padcfg) & ~PADCFG0_GPIORXSTATE;
+               if (val != pads[i].padcfg0) {
+                       writel(pads[i].padcfg0, padcfg);
+                       dev_dbg(dev, "restored pin %u padcfg0 %#08x\n",
+                               desc->number, readl(padcfg));
+               }
+
+               padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG1);
+               val = readl(padcfg);
+               if (val != pads[i].padcfg1) {
+                       writel(pads[i].padcfg1, padcfg);
+                       dev_dbg(dev, "restored pin %u padcfg1 %#08x\n",
+                               desc->number, readl(padcfg));
+               }
+       }
+
+       communities = pctrl->context.communities;
+       for (i = 0; i < pctrl->ncommunities; i++) {
+               struct intel_community *community = &pctrl->communities[i];
+               void __iomem *base;
+               unsigned gpp;
+
+               base = community->regs + community->ie_offset;
+               for (gpp = 0; gpp < community->ngpps; gpp++) {
+                       writel(communities[i].intmask[gpp], base + gpp * 4);
+                       dev_dbg(dev, "restored mask %d/%u %#08x\n", i, gpp,
+                               readl(base + gpp * 4));
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(intel_pinctrl_resume);
+#endif
+
+MODULE_AUTHOR("Mathias Nyman <mathias.nyman@linux.intel.com>");
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
+MODULE_DESCRIPTION("Intel pinctrl/GPIO core driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h
new file mode 100644 (file)
index 0000000..4ec8b57
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Core pinctrl/GPIO driver for Intel GPIO controllers
+ *
+ * Copyright (C) 2015, Intel Corporation
+ * Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
+ *          Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef PINCTRL_INTEL_H
+#define PINCTRL_INTEL_H
+
+struct pinctrl_pin_desc;
+struct platform_device;
+struct device;
+
+/**
+ * struct intel_pingroup - Description about group of pins
+ * @name: Name of the groups
+ * @pins: All pins in this group
+ * @npins: Number of pins in this groups
+ * @mode: Native mode in which the group is muxed out @pins
+ */
+struct intel_pingroup {
+       const char *name;
+       const unsigned *pins;
+       size_t npins;
+       unsigned short mode;
+};
+
+/**
+ * struct intel_function - Description about a function
+ * @name: Name of the function
+ * @groups: An array of groups for this function
+ * @ngroups: Number of groups in @groups
+ */
+struct intel_function {
+       const char *name;
+       const char * const *groups;
+       size_t ngroups;
+};
+
+/**
+ * struct intel_community - Intel pin community description
+ * @barno: MMIO BAR number where registers for this community reside
+ * @padown_offset: Register offset of PAD_OWN register from @regs. If %0
+ *                 then there is no support for owner.
+ * @padcfglock_offset: Register offset of PADCFGLOCK from @regs. If %0 then
+ *                     locking is not supported.
+ * @hostown_offset: Register offset of HOSTSW_OWN from @regs. If %0 then it
+ *                  is assumed that the host owns the pin (rather than
+ *                  ACPI).
+ * @ie_offset: Register offset of GPI_IE from @regs.
+ * @pin_base: Starting pin of pins in this community
+ * @npins: Number of pins in this community
+ * @regs: Community specific common registers (reserved for core driver)
+ * @pad_regs: Community specific pad registers (reserved for core driver)
+ * @ngpps: Number of groups (hw groups) in this community (reserved for
+ *         core driver)
+ */
+struct intel_community {
+       unsigned barno;
+       unsigned padown_offset;
+       unsigned padcfglock_offset;
+       unsigned hostown_offset;
+       unsigned ie_offset;
+       unsigned pin_base;
+       size_t npins;
+       void __iomem *regs;
+       void __iomem *pad_regs;
+       size_t ngpps;
+};
+
+#define PIN_GROUP(n, p, m)                     \
+       {                                       \
+               .name = (n),                    \
+               .pins = (p),                    \
+               .npins = ARRAY_SIZE((p)),       \
+               .mode = (m),                    \
+       }
+
+#define FUNCTION(n, g)                         \
+       {                                       \
+               .name = (n),                    \
+               .groups = (g),                  \
+               .ngroups = ARRAY_SIZE((g)),     \
+       }
+
+/**
+ * struct intel_pinctrl_soc_data - Intel pin controller per-SoC configuration
+ * @uid: ACPI _UID for the probe driver use if needed
+ * @pins: Array if pins this pinctrl controls
+ * @npins: Number of pins in the array
+ * @groups: Array of pin groups
+ * @ngroups: Number of groups in the array
+ * @functions: Array of functions
+ * @nfunctions: Number of functions in the array
+ * @communities: Array of communities this pinctrl handles
+ * @ncommunities: Number of communities in the array
+ *
+ * The @communities is used as a template by the core driver. It will make
+ * copy of all communities and fill in rest of the information.
+ */
+struct intel_pinctrl_soc_data {
+       const char *uid;
+       const struct pinctrl_pin_desc *pins;
+       size_t npins;
+       const struct intel_pingroup *groups;
+       size_t ngroups;
+       const struct intel_function *functions;
+       size_t nfunctions;
+       const struct intel_community *communities;
+       size_t ncommunities;
+};
+
+int intel_pinctrl_probe(struct platform_device *pdev,
+                       const struct intel_pinctrl_soc_data *soc_data);
+int intel_pinctrl_remove(struct platform_device *pdev);
+
+#ifdef CONFIG_PM_SLEEP
+int intel_pinctrl_suspend(struct device *dev);
+int intel_pinctrl_resume(struct device *dev);
+#endif
+
+#endif /* PINCTRL_INTEL_H */
diff --git a/drivers/pinctrl/intel/pinctrl-sunrisepoint.c b/drivers/pinctrl/intel/pinctrl-sunrisepoint.c
new file mode 100644 (file)
index 0000000..55d025d
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * Intel Sunrisepoint PCH pinctrl/GPIO driver
+ *
+ * Copyright (C) 2015, Intel Corporation
+ * Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
+ *          Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-intel.h"
+
+#define SPT_PAD_OWN    0x020
+#define SPT_PADCFGLOCK 0x0a0
+#define SPT_HOSTSW_OWN 0x0d0
+#define SPT_GPI_IE     0x120
+
+#define SPT_COMMUNITY(b, s, e)                         \
+       {                                               \
+               .barno = (b),                           \
+               .padown_offset = SPT_PAD_OWN,           \
+               .padcfglock_offset = SPT_PADCFGLOCK,    \
+               .hostown_offset = SPT_HOSTSW_OWN,       \
+               .ie_offset = SPT_GPI_IE,                \
+               .pin_base = (s),                        \
+               .npins = ((e) - (s) + 1),               \
+       }
+
+/* Sunrisepoint-LP */
+static const struct pinctrl_pin_desc sptlp_pins[] = {
+       /* GPP_A */
+       PINCTRL_PIN(0, "RCINB"),
+       PINCTRL_PIN(1, "LAD_0"),
+       PINCTRL_PIN(2, "LAD_1"),
+       PINCTRL_PIN(3, "LAD_2"),
+       PINCTRL_PIN(4, "LAD_3"),
+       PINCTRL_PIN(5, "LFRAMEB"),
+       PINCTRL_PIN(6, "SERIQ"),
+       PINCTRL_PIN(7, "PIRQAB"),
+       PINCTRL_PIN(8, "CLKRUNB"),
+       PINCTRL_PIN(9, "CLKOUT_LPC_0"),
+       PINCTRL_PIN(10, "CLKOUT_LPC_1"),
+       PINCTRL_PIN(11, "PMEB"),
+       PINCTRL_PIN(12, "BM_BUSYB"),
+       PINCTRL_PIN(13, "SUSWARNB_SUS_PWRDNACK"),
+       PINCTRL_PIN(14, "SUS_STATB"),
+       PINCTRL_PIN(15, "SUSACKB"),
+       PINCTRL_PIN(16, "SD_1P8_SEL"),
+       PINCTRL_PIN(17, "SD_PWR_EN_B"),
+       PINCTRL_PIN(18, "ISH_GP_0"),
+       PINCTRL_PIN(19, "ISH_GP_1"),
+       PINCTRL_PIN(20, "ISH_GP_2"),
+       PINCTRL_PIN(21, "ISH_GP_3"),
+       PINCTRL_PIN(22, "ISH_GP_4"),
+       PINCTRL_PIN(23, "ISH_GP_5"),
+       /* GPP_B */
+       PINCTRL_PIN(24, "CORE_VID_0"),
+       PINCTRL_PIN(25, "CORE_VID_1"),
+       PINCTRL_PIN(26, "VRALERTB"),
+       PINCTRL_PIN(27, "CPU_GP_2"),
+       PINCTRL_PIN(28, "CPU_GP_3"),
+       PINCTRL_PIN(29, "SRCCLKREQB_0"),
+       PINCTRL_PIN(30, "SRCCLKREQB_1"),
+       PINCTRL_PIN(31, "SRCCLKREQB_2"),
+       PINCTRL_PIN(32, "SRCCLKREQB_3"),
+       PINCTRL_PIN(33, "SRCCLKREQB_4"),
+       PINCTRL_PIN(34, "SRCCLKREQB_5"),
+       PINCTRL_PIN(35, "EXT_PWR_GATEB"),
+       PINCTRL_PIN(36, "SLP_S0B"),
+       PINCTRL_PIN(37, "PLTRSTB"),
+       PINCTRL_PIN(38, "SPKR"),
+       PINCTRL_PIN(39, "GSPI0_CSB"),
+       PINCTRL_PIN(40, "GSPI0_CLK"),
+       PINCTRL_PIN(41, "GSPI0_MISO"),
+       PINCTRL_PIN(42, "GSPI0_MOSI"),
+       PINCTRL_PIN(43, "GSPI1_CSB"),
+       PINCTRL_PIN(44, "GSPI1_CLK"),
+       PINCTRL_PIN(45, "GSPI1_MISO"),
+       PINCTRL_PIN(46, "GSPI1_MOSI"),
+       PINCTRL_PIN(47, "SML1ALERTB"),
+       /* GPP_C */
+       PINCTRL_PIN(48, "SMBCLK"),
+       PINCTRL_PIN(49, "SMBDATA"),
+       PINCTRL_PIN(50, "SMBALERTB"),
+       PINCTRL_PIN(51, "SML0CLK"),
+       PINCTRL_PIN(52, "SML0DATA"),
+       PINCTRL_PIN(53, "SML0ALERTB"),
+       PINCTRL_PIN(54, "SML1CLK"),
+       PINCTRL_PIN(55, "SML1DATA"),
+       PINCTRL_PIN(56, "UART0_RXD"),
+       PINCTRL_PIN(57, "UART0_TXD"),
+       PINCTRL_PIN(58, "UART0_RTSB"),
+       PINCTRL_PIN(59, "UART0_CTSB"),
+       PINCTRL_PIN(60, "UART1_RXD"),
+       PINCTRL_PIN(61, "UART1_TXD"),
+       PINCTRL_PIN(62, "UART1_RTSB"),
+       PINCTRL_PIN(63, "UART1_CTSB"),
+       PINCTRL_PIN(64, "I2C0_SDA"),
+       PINCTRL_PIN(65, "I2C0_SCL"),
+       PINCTRL_PIN(66, "I2C1_SDA"),
+       PINCTRL_PIN(67, "I2C1_SCL"),
+       PINCTRL_PIN(68, "UART2_RXD"),
+       PINCTRL_PIN(69, "UART2_TXD"),
+       PINCTRL_PIN(70, "UART2_RTSB"),
+       PINCTRL_PIN(71, "UART2_CTSB"),
+       /* GPP_D */
+       PINCTRL_PIN(72, "SPI1_CSB"),
+       PINCTRL_PIN(73, "SPI1_CLK"),
+       PINCTRL_PIN(74, "SPI1_MISO_IO_1"),
+       PINCTRL_PIN(75, "SPI1_MOSI_IO_0"),
+       PINCTRL_PIN(76, "FLASHTRIG"),
+       PINCTRL_PIN(77, "ISH_I2C0_SDA"),
+       PINCTRL_PIN(78, "ISH_I2C0_SCL"),
+       PINCTRL_PIN(79, "ISH_I2C1_SDA"),
+       PINCTRL_PIN(80, "ISH_I2C1_SCL"),
+       PINCTRL_PIN(81, "ISH_SPI_CSB"),
+       PINCTRL_PIN(82, "ISH_SPI_CLK"),
+       PINCTRL_PIN(83, "ISH_SPI_MISO"),
+       PINCTRL_PIN(84, "ISH_SPI_MOSI"),
+       PINCTRL_PIN(85, "ISH_UART0_RXD"),
+       PINCTRL_PIN(86, "ISH_UART0_TXD"),
+       PINCTRL_PIN(87, "ISH_UART0_RTSB"),
+       PINCTRL_PIN(88, "ISH_UART0_CTSB"),
+       PINCTRL_PIN(89, "DMIC_CLK_1"),
+       PINCTRL_PIN(90, "DMIC_DATA_1"),
+       PINCTRL_PIN(91, "DMIC_CLK_0"),
+       PINCTRL_PIN(92, "DMIC_DATA_0"),
+       PINCTRL_PIN(93, "SPI1_IO_2"),
+       PINCTRL_PIN(94, "SPI1_IO_3"),
+       PINCTRL_PIN(95, "SSP_MCLK"),
+       /* GPP_E */
+       PINCTRL_PIN(96, "SATAXPCIE_0"),
+       PINCTRL_PIN(97, "SATAXPCIE_1"),
+       PINCTRL_PIN(98, "SATAXPCIE_2"),
+       PINCTRL_PIN(99, "CPU_GP_0"),
+       PINCTRL_PIN(100, "SATA_DEVSLP_0"),
+       PINCTRL_PIN(101, "SATA_DEVSLP_1"),
+       PINCTRL_PIN(102, "SATA_DEVSLP_2"),
+       PINCTRL_PIN(103, "CPU_GP_1"),
+       PINCTRL_PIN(104, "SATA_LEDB"),
+       PINCTRL_PIN(105, "USB2_OCB_0"),
+       PINCTRL_PIN(106, "USB2_OCB_1"),
+       PINCTRL_PIN(107, "USB2_OCB_2"),
+       PINCTRL_PIN(108, "USB2_OCB_3"),
+       PINCTRL_PIN(109, "DDSP_HPD_0"),
+       PINCTRL_PIN(110, "DDSP_HPD_1"),
+       PINCTRL_PIN(111, "DDSP_HPD_2"),
+       PINCTRL_PIN(112, "DDSP_HPD_3"),
+       PINCTRL_PIN(113, "EDP_HPD"),
+       PINCTRL_PIN(114, "DDPB_CTRLCLK"),
+       PINCTRL_PIN(115, "DDPB_CTRLDATA"),
+       PINCTRL_PIN(116, "DDPC_CTRLCLK"),
+       PINCTRL_PIN(117, "DDPC_CTRLDATA"),
+       PINCTRL_PIN(118, "DDPD_CTRLCLK"),
+       PINCTRL_PIN(119, "DDPD_CTRLDATA"),
+       /* GPP_F */
+       PINCTRL_PIN(120, "SSP2_SCLK"),
+       PINCTRL_PIN(121, "SSP2_SFRM"),
+       PINCTRL_PIN(122, "SSP2_TXD"),
+       PINCTRL_PIN(123, "SSP2_RXD"),
+       PINCTRL_PIN(124, "I2C2_SDA"),
+       PINCTRL_PIN(125, "I2C2_SCL"),
+       PINCTRL_PIN(126, "I2C3_SDA"),
+       PINCTRL_PIN(127, "I2C3_SCL"),
+       PINCTRL_PIN(128, "I2C4_SDA"),
+       PINCTRL_PIN(129, "I2C4_SCL"),
+       PINCTRL_PIN(130, "I2C5_SDA"),
+       PINCTRL_PIN(131, "I2C5_SCL"),
+       PINCTRL_PIN(132, "EMMC_CMD"),
+       PINCTRL_PIN(133, "EMMC_DATA_0"),
+       PINCTRL_PIN(134, "EMMC_DATA_1"),
+       PINCTRL_PIN(135, "EMMC_DATA_2"),
+       PINCTRL_PIN(136, "EMMC_DATA_3"),
+       PINCTRL_PIN(137, "EMMC_DATA_4"),
+       PINCTRL_PIN(138, "EMMC_DATA_5"),
+       PINCTRL_PIN(139, "EMMC_DATA_6"),
+       PINCTRL_PIN(140, "EMMC_DATA_7"),
+       PINCTRL_PIN(141, "EMMC_RCLK"),
+       PINCTRL_PIN(142, "EMMC_CLK"),
+       PINCTRL_PIN(143, "GPP_F_23"),
+       /* GPP_G */
+       PINCTRL_PIN(144, "SD_CMD"),
+       PINCTRL_PIN(145, "SD_DATA_0"),
+       PINCTRL_PIN(146, "SD_DATA_1"),
+       PINCTRL_PIN(147, "SD_DATA_2"),
+       PINCTRL_PIN(148, "SD_DATA_3"),
+       PINCTRL_PIN(149, "SD_CDB"),
+       PINCTRL_PIN(150, "SD_CLK"),
+       PINCTRL_PIN(151, "SD_WP"),
+};
+
+static const unsigned sptlp_spi0_pins[] = { 39, 40, 41, 42 };
+static const unsigned sptlp_spi1_pins[] = { 43, 44, 45, 46 };
+static const unsigned sptlp_uart0_pins[] = { 56, 57, 58, 59 };
+static const unsigned sptlp_uart1_pins[] = { 60, 61, 62, 63 };
+static const unsigned sptlp_uart2_pins[] = { 68, 69, 71, 71 };
+static const unsigned sptlp_i2c0_pins[] = { 64, 65 };
+static const unsigned sptlp_i2c1_pins[] = { 66, 67 };
+static const unsigned sptlp_i2c2_pins[] = { 124, 125 };
+static const unsigned sptlp_i2c3_pins[] = { 126, 127 };
+static const unsigned sptlp_i2c4_pins[] = { 128, 129 };
+static const unsigned sptlp_i2c4b_pins[] = { 85, 86 };
+static const unsigned sptlp_i2c5_pins[] = { 130, 131 };
+static const unsigned sptlp_ssp2_pins[] = { 120, 121, 122, 123 };
+static const unsigned sptlp_emmc_pins[] = {
+       132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+};
+static const unsigned sptlp_sd_pins[] = {
+       144, 145, 146, 147, 148, 149, 150, 151,
+};
+
+static const struct intel_pingroup sptlp_groups[] = {
+       PIN_GROUP("spi0_grp", sptlp_spi0_pins, 1),
+       PIN_GROUP("spi1_grp", sptlp_spi1_pins, 1),
+       PIN_GROUP("uart0_grp", sptlp_uart0_pins, 1),
+       PIN_GROUP("uart1_grp", sptlp_uart1_pins, 1),
+       PIN_GROUP("uart2_grp", sptlp_uart2_pins, 1),
+       PIN_GROUP("i2c0_grp", sptlp_i2c0_pins, 1),
+       PIN_GROUP("i2c1_grp", sptlp_i2c1_pins, 1),
+       PIN_GROUP("i2c2_grp", sptlp_i2c2_pins, 1),
+       PIN_GROUP("i2c3_grp", sptlp_i2c3_pins, 1),
+       PIN_GROUP("i2c4_grp", sptlp_i2c4_pins, 1),
+       PIN_GROUP("i2c4b_grp", sptlp_i2c4b_pins, 3),
+       PIN_GROUP("i2c5_grp", sptlp_i2c5_pins, 1),
+       PIN_GROUP("ssp2_grp", sptlp_ssp2_pins, 1),
+       PIN_GROUP("emmc_grp", sptlp_emmc_pins, 1),
+       PIN_GROUP("sd_grp", sptlp_sd_pins, 1),
+};
+
+static const char * const sptlp_spi0_groups[] = { "spi0_grp" };
+static const char * const sptlp_spi1_groups[] = { "spi0_grp" };
+static const char * const sptlp_uart0_groups[] = { "uart0_grp" };
+static const char * const sptlp_uart1_groups[] = { "uart1_grp" };
+static const char * const sptlp_uart2_groups[] = { "uart2_grp" };
+static const char * const sptlp_i2c0_groups[] = { "i2c0_grp" };
+static const char * const sptlp_i2c1_groups[] = { "i2c1_grp" };
+static const char * const sptlp_i2c2_groups[] = { "i2c2_grp" };
+static const char * const sptlp_i2c3_groups[] = { "i2c3_grp" };
+static const char * const sptlp_i2c4_groups[] = { "i2c4_grp", "i2c4b_grp" };
+static const char * const sptlp_i2c5_groups[] = { "i2c5_grp" };
+static const char * const sptlp_ssp2_groups[] = { "ssp2_grp" };
+static const char * const sptlp_emmc_groups[] = { "emmc_grp" };
+static const char * const sptlp_sd_groups[] = { "sd_grp" };
+
+static const struct intel_function sptlp_functions[] = {
+       FUNCTION("spi0", sptlp_spi0_groups),
+       FUNCTION("spi1", sptlp_spi1_groups),
+       FUNCTION("uart0", sptlp_uart0_groups),
+       FUNCTION("uart1", sptlp_uart1_groups),
+       FUNCTION("uart2", sptlp_uart2_groups),
+       FUNCTION("i2c0", sptlp_i2c0_groups),
+       FUNCTION("i2c1", sptlp_i2c1_groups),
+       FUNCTION("i2c2", sptlp_i2c2_groups),
+       FUNCTION("i2c3", sptlp_i2c3_groups),
+       FUNCTION("i2c4", sptlp_i2c4_groups),
+       FUNCTION("i2c5", sptlp_i2c5_groups),
+       FUNCTION("ssp2", sptlp_ssp2_groups),
+       FUNCTION("emmc", sptlp_emmc_groups),
+       FUNCTION("sd", sptlp_sd_groups),
+};
+
+static const struct intel_community sptlp_communities[] = {
+       SPT_COMMUNITY(0, 0, 47),
+       SPT_COMMUNITY(1, 48, 119),
+       SPT_COMMUNITY(2, 120, 151),
+};
+
+static const struct intel_pinctrl_soc_data sptlp_soc_data = {
+       .pins = sptlp_pins,
+       .npins = ARRAY_SIZE(sptlp_pins),
+       .groups = sptlp_groups,
+       .ngroups = ARRAY_SIZE(sptlp_groups),
+       .functions = sptlp_functions,
+       .nfunctions = ARRAY_SIZE(sptlp_functions),
+       .communities = sptlp_communities,
+       .ncommunities = ARRAY_SIZE(sptlp_communities),
+};
+
+static const struct acpi_device_id spt_pinctrl_acpi_match[] = {
+       { "INT344B", (kernel_ulong_t)&sptlp_soc_data },
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, spt_pinctrl_acpi_match);
+
+static int spt_pinctrl_probe(struct platform_device *pdev)
+{
+       const struct intel_pinctrl_soc_data *soc_data;
+       const struct acpi_device_id *id;
+
+       id = acpi_match_device(spt_pinctrl_acpi_match, &pdev->dev);
+       if (!id || !id->driver_data)
+               return -ENODEV;
+
+       soc_data = (const struct intel_pinctrl_soc_data *)id->driver_data;
+       return intel_pinctrl_probe(pdev, soc_data);
+}
+
+static const struct dev_pm_ops spt_pinctrl_pm_ops = {
+       SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend,
+                                    intel_pinctrl_resume)
+};
+
+static struct platform_driver spt_pinctrl_driver = {
+       .probe = spt_pinctrl_probe,
+       .remove = intel_pinctrl_remove,
+       .driver = {
+               .name = "sunrisepoint-pinctrl",
+               .acpi_match_table = spt_pinctrl_acpi_match,
+               .pm = &spt_pinctrl_pm_ops,
+       },
+};
+
+static int __init spt_pinctrl_init(void)
+{
+       return platform_driver_register(&spt_pinctrl_driver);
+}
+subsys_initcall(spt_pinctrl_init);
+
+static void __exit spt_pinctrl_exit(void)
+{
+       platform_driver_unregister(&spt_pinctrl_driver);
+}
+module_exit(spt_pinctrl_exit);
+
+MODULE_AUTHOR("Mathias Nyman <mathias.nyman@linux.intel.com>");
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
+MODULE_DESCRIPTION("Intel Sunrisepoint PCH pinctrl/GPIO driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
new file mode 100644 (file)
index 0000000..5983cf5
--- /dev/null
@@ -0,0 +1,23 @@
+if ARCH_MEDIATEK || COMPILE_TEST
+
+config PINCTRL_MTK_COMMON
+       bool
+       select PINMUX
+       select GENERIC_PINCONF
+       select GPIOLIB
+       select OF_GPIO
+
+# For ARMv7 SoCs
+config PINCTRL_MT8135
+       bool "Mediatek MT8135 pin control" if COMPILE_TEST && !MACH_MT8135
+       default MACH_MT8135
+       select PINCTRL_MTK_COMMON
+
+# For ARMv8 SoCs
+config PINCTRL_MT8173
+       bool "Mediatek MT8173 pin control"
+       depends on ARM64 || COMPILE_TEST
+       default ARM64 && ARCH_MEDIATEK
+       select PINCTRL_MTK_COMMON
+
+endif
diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
new file mode 100644 (file)
index 0000000..d8606a2
--- /dev/null
@@ -0,0 +1,6 @@
+# Core
+obj-$(CONFIG_PINCTRL_MTK_COMMON)       += pinctrl-mtk-common.o
+
+# SoC Drivers
+obj-$(CONFIG_PINCTRL_MT8135)           += pinctrl-mt8135.o
+obj-$(CONFIG_PINCTRL_MT8173)           += pinctrl-mt8173.o
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8135.c b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
new file mode 100644 (file)
index 0000000..f1e1e18
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Hongzhou.Yang <hongzhou.yang@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/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/regmap.h>
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+#include "pinctrl-mtk-common.h"
+#include "pinctrl-mtk-mt8135.h"
+
+#define DRV_BASE1                              0x500
+#define DRV_BASE2                              0x510
+#define PUPD_BASE1                             0x400
+#define PUPD_BASE2                             0x450
+#define R0_BASE1                               0x4d0
+#define R1_BASE1                               0x200
+#define R1_BASE2                               0x250
+
+struct mtk_spec_pull_set {
+       unsigned int pin;
+       unsigned int pupd_offset;
+       unsigned char pupd_bit;
+       unsigned int r0_offset;
+       unsigned char r0_bit;
+       unsigned int r1_offset;
+       unsigned char r1_bit;
+};
+
+#define SPEC_PULL(_pin, _pupd_offset, _pupd_bit, _r0_offset, \
+       _r0_bit, _r1_offset, _r1_bit)   \
+       {       \
+               .pin = _pin,    \
+               .pupd_offset = _pupd_offset,    \
+               .pupd_bit = _pupd_bit,  \
+               .r0_offset = _r0_offset, \
+               .r0_bit = _r0_bit, \
+               .r1_offset = _r1_offset, \
+               .r1_bit = _r1_bit, \
+       }
+
+static const struct mtk_drv_group_desc mt8135_drv_grp[] =  {
+       /* E8E4E2 2/4/6/8/10/12/14/16 */
+       MTK_DRV_GRP(2, 16, 0, 2, 2),
+       /* E8E4  4/8/12/16 */
+       MTK_DRV_GRP(4, 16, 1, 2, 4),
+       /* E4E2  2/4/6/8 */
+       MTK_DRV_GRP(2, 8, 0, 1, 2),
+       /* E16E8E4 4/8/12/16/20/24/28/32 */
+       MTK_DRV_GRP(4, 32, 0, 2, 4)
+};
+
+static const struct mtk_pin_drv_grp mt8135_pin_drv[] = {
+       MTK_PIN_DRV_GRP(0, DRV_BASE1, 0, 0),
+       MTK_PIN_DRV_GRP(1, DRV_BASE1, 0, 0),
+       MTK_PIN_DRV_GRP(2, DRV_BASE1, 0, 0),
+       MTK_PIN_DRV_GRP(3, DRV_BASE1, 0, 0),
+       MTK_PIN_DRV_GRP(4, DRV_BASE1, 4, 0),
+       MTK_PIN_DRV_GRP(5, DRV_BASE1, 8, 0),
+       MTK_PIN_DRV_GRP(6, DRV_BASE1, 0, 0),
+       MTK_PIN_DRV_GRP(7, DRV_BASE1, 0, 0),
+       MTK_PIN_DRV_GRP(8, DRV_BASE1, 0, 0),
+       MTK_PIN_DRV_GRP(9, DRV_BASE1, 0, 0),
+
+       MTK_PIN_DRV_GRP(10, DRV_BASE1, 12, 1),
+       MTK_PIN_DRV_GRP(11, DRV_BASE1, 12, 1),
+       MTK_PIN_DRV_GRP(12, DRV_BASE1, 12, 1),
+       MTK_PIN_DRV_GRP(13, DRV_BASE1, 12, 1),
+       MTK_PIN_DRV_GRP(14, DRV_BASE1, 12, 1),
+       MTK_PIN_DRV_GRP(15, DRV_BASE1, 12, 1),
+       MTK_PIN_DRV_GRP(16, DRV_BASE1, 12, 1),
+       MTK_PIN_DRV_GRP(17, DRV_BASE1, 16, 1),
+       MTK_PIN_DRV_GRP(18, DRV_BASE1, 16, 1),
+       MTK_PIN_DRV_GRP(19, DRV_BASE1, 16, 1),
+       MTK_PIN_DRV_GRP(20, DRV_BASE1, 16, 1),
+       MTK_PIN_DRV_GRP(21, DRV_BASE1, 16, 1),
+       MTK_PIN_DRV_GRP(22, DRV_BASE1, 16, 1),
+       MTK_PIN_DRV_GRP(23, DRV_BASE1, 16, 1),
+       MTK_PIN_DRV_GRP(24, DRV_BASE1, 16, 1),
+       MTK_PIN_DRV_GRP(33, DRV_BASE1, 24, 1),
+       MTK_PIN_DRV_GRP(34, DRV_BASE2, 12, 2),
+       MTK_PIN_DRV_GRP(37, DRV_BASE2, 20, 1),
+       MTK_PIN_DRV_GRP(38, DRV_BASE2, 20, 1),
+       MTK_PIN_DRV_GRP(39, DRV_BASE2, 20, 1),
+       MTK_PIN_DRV_GRP(40, DRV_BASE2, 24, 1),
+       MTK_PIN_DRV_GRP(41, DRV_BASE2, 24, 1),
+       MTK_PIN_DRV_GRP(42, DRV_BASE2, 24, 1),
+       MTK_PIN_DRV_GRP(43, DRV_BASE2, 28, 1),
+       MTK_PIN_DRV_GRP(44, DRV_BASE2, 28, 1),
+       MTK_PIN_DRV_GRP(45, DRV_BASE2, 28, 1),
+       MTK_PIN_DRV_GRP(46, DRV_BASE2, 28, 1),
+       MTK_PIN_DRV_GRP(47, DRV_BASE2, 28, 1),
+
+       MTK_PIN_DRV_GRP(49, DRV_BASE2+0x10, 0, 1),
+       MTK_PIN_DRV_GRP(50, DRV_BASE2+0x10, 4, 1),
+       MTK_PIN_DRV_GRP(51, DRV_BASE2+0x10, 8, 1),
+       MTK_PIN_DRV_GRP(52, DRV_BASE2+0x10, 12, 2),
+       MTK_PIN_DRV_GRP(53, DRV_BASE2+0x10, 16, 1),
+       MTK_PIN_DRV_GRP(54, DRV_BASE2+0x10, 20, 1),
+       MTK_PIN_DRV_GRP(55, DRV_BASE2+0x10, 24, 1),
+       MTK_PIN_DRV_GRP(56, DRV_BASE2+0x10, 28, 1),
+
+       MTK_PIN_DRV_GRP(57, DRV_BASE2+0x20, 0, 1),
+       MTK_PIN_DRV_GRP(58, DRV_BASE2+0x20, 0, 1),
+       MTK_PIN_DRV_GRP(59, DRV_BASE2+0x20, 0, 1),
+       MTK_PIN_DRV_GRP(60, DRV_BASE2+0x20, 0, 1),
+       MTK_PIN_DRV_GRP(61, DRV_BASE2+0x20, 0, 1),
+       MTK_PIN_DRV_GRP(62, DRV_BASE2+0x20, 0, 1),
+       MTK_PIN_DRV_GRP(63, DRV_BASE2+0x20, 4, 1),
+       MTK_PIN_DRV_GRP(64, DRV_BASE2+0x20, 8, 1),
+       MTK_PIN_DRV_GRP(65, DRV_BASE2+0x20, 12, 1),
+       MTK_PIN_DRV_GRP(66, DRV_BASE2+0x20, 16, 1),
+       MTK_PIN_DRV_GRP(67, DRV_BASE2+0x20, 20, 1),
+       MTK_PIN_DRV_GRP(68, DRV_BASE2+0x20, 24, 1),
+       MTK_PIN_DRV_GRP(69, DRV_BASE2+0x20, 28, 1),
+
+       MTK_PIN_DRV_GRP(70, DRV_BASE2+0x30, 0, 1),
+       MTK_PIN_DRV_GRP(71, DRV_BASE2+0x30, 4, 1),
+       MTK_PIN_DRV_GRP(72, DRV_BASE2+0x30, 8, 1),
+       MTK_PIN_DRV_GRP(73, DRV_BASE2+0x30, 12, 1),
+       MTK_PIN_DRV_GRP(74, DRV_BASE2+0x30, 16, 1),
+       MTK_PIN_DRV_GRP(75, DRV_BASE2+0x30, 20, 1),
+       MTK_PIN_DRV_GRP(76, DRV_BASE2+0x30, 24, 1),
+       MTK_PIN_DRV_GRP(77, DRV_BASE2+0x30, 28, 3),
+       MTK_PIN_DRV_GRP(78, DRV_BASE2+0x30, 28, 3),
+
+       MTK_PIN_DRV_GRP(79, DRV_BASE2+0x40, 0, 3),
+       MTK_PIN_DRV_GRP(80, DRV_BASE2+0x40, 4, 3),
+
+       MTK_PIN_DRV_GRP(81, DRV_BASE2+0x30, 28, 3),
+       MTK_PIN_DRV_GRP(82, DRV_BASE2+0x30, 28, 3),
+
+       MTK_PIN_DRV_GRP(83, DRV_BASE2+0x40, 8, 3),
+       MTK_PIN_DRV_GRP(84, DRV_BASE2+0x40, 8, 3),
+       MTK_PIN_DRV_GRP(85, DRV_BASE2+0x40, 12, 3),
+       MTK_PIN_DRV_GRP(86, DRV_BASE2+0x40, 16, 3),
+       MTK_PIN_DRV_GRP(87, DRV_BASE2+0x40, 8, 3),
+       MTK_PIN_DRV_GRP(88, DRV_BASE2+0x40, 8, 3),
+
+       MTK_PIN_DRV_GRP(89, DRV_BASE2+0x50, 12, 0),
+       MTK_PIN_DRV_GRP(90, DRV_BASE2+0x50, 12, 0),
+       MTK_PIN_DRV_GRP(91, DRV_BASE2+0x50, 12, 0),
+       MTK_PIN_DRV_GRP(92, DRV_BASE2+0x50, 12, 0),
+       MTK_PIN_DRV_GRP(93, DRV_BASE2+0x50, 12, 0),
+       MTK_PIN_DRV_GRP(94, DRV_BASE2+0x50, 12, 0),
+       MTK_PIN_DRV_GRP(95, DRV_BASE2+0x50, 12, 0),
+
+       MTK_PIN_DRV_GRP(96, DRV_BASE1+0xb0, 28, 0),
+
+       MTK_PIN_DRV_GRP(97, DRV_BASE2+0x50, 12, 0),
+       MTK_PIN_DRV_GRP(98, DRV_BASE2+0x50, 16, 0),
+       MTK_PIN_DRV_GRP(99, DRV_BASE2+0x50, 20, 1),
+       MTK_PIN_DRV_GRP(102, DRV_BASE2+0x50, 24, 1),
+       MTK_PIN_DRV_GRP(103, DRV_BASE2+0x50, 28, 1),
+
+
+       MTK_PIN_DRV_GRP(104, DRV_BASE2+0x60, 0, 1),
+       MTK_PIN_DRV_GRP(105, DRV_BASE2+0x60, 4, 1),
+       MTK_PIN_DRV_GRP(106, DRV_BASE2+0x60, 4, 1),
+       MTK_PIN_DRV_GRP(107, DRV_BASE2+0x60, 4, 1),
+       MTK_PIN_DRV_GRP(108, DRV_BASE2+0x60, 4, 1),
+       MTK_PIN_DRV_GRP(109, DRV_BASE2+0x60, 8, 2),
+       MTK_PIN_DRV_GRP(110, DRV_BASE2+0x60, 12, 2),
+       MTK_PIN_DRV_GRP(111, DRV_BASE2+0x60, 16, 2),
+       MTK_PIN_DRV_GRP(112, DRV_BASE2+0x60, 20, 2),
+       MTK_PIN_DRV_GRP(113, DRV_BASE2+0x60, 24, 2),
+       MTK_PIN_DRV_GRP(114, DRV_BASE2+0x60, 28, 2),
+
+       MTK_PIN_DRV_GRP(115, DRV_BASE2+0x70, 0, 2),
+       MTK_PIN_DRV_GRP(116, DRV_BASE2+0x70, 4, 2),
+       MTK_PIN_DRV_GRP(117, DRV_BASE2+0x70, 8, 2),
+       MTK_PIN_DRV_GRP(118, DRV_BASE2+0x70, 12, 2),
+       MTK_PIN_DRV_GRP(119, DRV_BASE2+0x70, 16, 2),
+       MTK_PIN_DRV_GRP(120, DRV_BASE2+0x70, 20, 2),
+
+       MTK_PIN_DRV_GRP(181, DRV_BASE1+0xa0, 12, 1),
+       MTK_PIN_DRV_GRP(182, DRV_BASE1+0xa0, 16, 1),
+       MTK_PIN_DRV_GRP(183, DRV_BASE1+0xa0, 20, 1),
+       MTK_PIN_DRV_GRP(184, DRV_BASE1+0xa0, 24, 1),
+       MTK_PIN_DRV_GRP(185, DRV_BASE1+0xa0, 28, 1),
+
+       MTK_PIN_DRV_GRP(186, DRV_BASE1+0xb0, 0, 2),
+       MTK_PIN_DRV_GRP(187, DRV_BASE1+0xb0, 0, 2),
+       MTK_PIN_DRV_GRP(188, DRV_BASE1+0xb0, 0, 2),
+       MTK_PIN_DRV_GRP(189, DRV_BASE1+0xb0, 0, 2),
+       MTK_PIN_DRV_GRP(190, DRV_BASE1+0xb0, 4, 1),
+       MTK_PIN_DRV_GRP(191, DRV_BASE1+0xb0, 8, 1),
+       MTK_PIN_DRV_GRP(192, DRV_BASE1+0xb0, 12, 1),
+
+       MTK_PIN_DRV_GRP(197, DRV_BASE1+0xb0, 16, 0),
+       MTK_PIN_DRV_GRP(198, DRV_BASE1+0xb0, 16, 0),
+       MTK_PIN_DRV_GRP(199, DRV_BASE1+0xb0, 20, 0),
+       MTK_PIN_DRV_GRP(200, DRV_BASE1+0xb0, 24, 0),
+       MTK_PIN_DRV_GRP(201, DRV_BASE1+0xb0, 16, 0),
+       MTK_PIN_DRV_GRP(202, DRV_BASE1+0xb0, 16, 0)
+};
+
+static const struct mtk_spec_pull_set spec_pupd[] = {
+       SPEC_PULL(0, PUPD_BASE1, 0, R0_BASE1, 9, R1_BASE1, 0),
+       SPEC_PULL(1, PUPD_BASE1, 1, R0_BASE1, 8, R1_BASE1, 1),
+       SPEC_PULL(2, PUPD_BASE1, 2, R0_BASE1, 7, R1_BASE1, 2),
+       SPEC_PULL(3, PUPD_BASE1, 3, R0_BASE1, 6, R1_BASE1, 3),
+       SPEC_PULL(4, PUPD_BASE1, 4, R0_BASE1, 1, R1_BASE1, 4),
+       SPEC_PULL(5, PUPD_BASE1, 5, R0_BASE1, 0, R1_BASE1, 5),
+       SPEC_PULL(6, PUPD_BASE1, 6, R0_BASE1, 5, R1_BASE1, 6),
+       SPEC_PULL(7, PUPD_BASE1, 7, R0_BASE1, 4, R1_BASE1, 7),
+       SPEC_PULL(8, PUPD_BASE1, 8, R0_BASE1, 3, R1_BASE1, 8),
+       SPEC_PULL(9, PUPD_BASE1, 9, R0_BASE1, 2, R1_BASE1, 9),
+       SPEC_PULL(89, PUPD_BASE2, 9, R0_BASE1, 18, R1_BASE2, 9),
+       SPEC_PULL(90, PUPD_BASE2, 10, R0_BASE1, 19, R1_BASE2, 10),
+       SPEC_PULL(91, PUPD_BASE2, 11, R0_BASE1, 23, R1_BASE2, 11),
+       SPEC_PULL(92, PUPD_BASE2, 12, R0_BASE1, 24, R1_BASE2, 12),
+       SPEC_PULL(93, PUPD_BASE2, 13, R0_BASE1, 25, R1_BASE2, 13),
+       SPEC_PULL(94, PUPD_BASE2, 14, R0_BASE1, 22, R1_BASE2, 14),
+       SPEC_PULL(95, PUPD_BASE2, 15, R0_BASE1, 20, R1_BASE2, 15),
+       SPEC_PULL(96, PUPD_BASE2+0x10, 0, R0_BASE1, 16, R1_BASE2+0x10, 0),
+       SPEC_PULL(97, PUPD_BASE2+0x10, 1, R0_BASE1, 21, R1_BASE2+0x10, 1),
+       SPEC_PULL(98, PUPD_BASE2+0x10, 2, R0_BASE1, 17, R1_BASE2+0x10, 2),
+       SPEC_PULL(197, PUPD_BASE1+0xc0, 5, R0_BASE1, 13, R1_BASE2+0xc0, 5),
+       SPEC_PULL(198, PUPD_BASE2+0xc0, 6, R0_BASE1, 14, R1_BASE2+0xc0, 6),
+       SPEC_PULL(199, PUPD_BASE2+0xc0, 7, R0_BASE1, 11, R1_BASE2+0xc0, 7),
+       SPEC_PULL(200, PUPD_BASE2+0xc0, 8, R0_BASE1, 10, R1_BASE2+0xc0, 8),
+       SPEC_PULL(201, PUPD_BASE2+0xc0, 9, R0_BASE1, 13, R1_BASE2+0xc0, 9),
+       SPEC_PULL(202, PUPD_BASE2+0xc0, 10, R0_BASE1, 12, R1_BASE2+0xc0, 10)
+};
+
+static int spec_pull_set(struct regmap *regmap, unsigned int pin,
+               unsigned char align, bool isup, unsigned int r1r0)
+{
+       unsigned int i;
+       unsigned int reg_pupd, reg_set_r0, reg_set_r1;
+       unsigned int reg_rst_r0, reg_rst_r1;
+       bool find = false;
+
+       for (i = 0; i < ARRAY_SIZE(spec_pupd); i++) {
+               if (pin == spec_pupd[i].pin) {
+                       find = true;
+                       break;
+               }
+       }
+
+       if (!find)
+               return -EINVAL;
+
+       if (isup)
+               reg_pupd = spec_pupd[i].pupd_offset + align;
+       else
+               reg_pupd = spec_pupd[i].pupd_offset + (align << 1);
+
+       regmap_write(regmap, reg_pupd, spec_pupd[i].pupd_bit);
+
+       reg_set_r0 = spec_pupd[i].r0_offset + align;
+       reg_rst_r0 = spec_pupd[i].r0_offset + (align << 1);
+       reg_set_r1 = spec_pupd[i].r1_offset + align;
+       reg_rst_r1 = spec_pupd[i].r1_offset + (align << 1);
+
+       switch (r1r0) {
+       case MTK_PUPD_SET_R1R0_00:
+               regmap_write(regmap, reg_rst_r0, spec_pupd[i].r0_bit);
+               regmap_write(regmap, reg_rst_r1, spec_pupd[i].r1_bit);
+               break;
+       case MTK_PUPD_SET_R1R0_01:
+               regmap_write(regmap, reg_set_r0, spec_pupd[i].r0_bit);
+               regmap_write(regmap, reg_rst_r1, spec_pupd[i].r1_bit);
+               break;
+       case MTK_PUPD_SET_R1R0_10:
+               regmap_write(regmap, reg_rst_r0, spec_pupd[i].r0_bit);
+               regmap_write(regmap, reg_set_r1, spec_pupd[i].r1_bit);
+               break;
+       case MTK_PUPD_SET_R1R0_11:
+               regmap_write(regmap, reg_set_r0, spec_pupd[i].r0_bit);
+               regmap_write(regmap, reg_set_r1, spec_pupd[i].r1_bit);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct mtk_pinctrl_devdata mt8135_pinctrl_data = {
+       .pins = mtk_pins_mt8135,
+       .npins = ARRAY_SIZE(mtk_pins_mt8135),
+       .grp_desc = mt8135_drv_grp,
+       .n_grp_cls = ARRAY_SIZE(mt8135_drv_grp),
+       .pin_drv_grp = mt8135_pin_drv,
+       .n_pin_drv_grps = ARRAY_SIZE(mt8135_pin_drv),
+       .spec_pull_set = spec_pull_set,
+       .dir_offset = 0x0000,
+       .ies_offset = 0x0100,
+       .pullen_offset = 0x0200,
+       .smt_offset = 0x0300,
+       .pullsel_offset = 0x0400,
+       .invser_offset = 0x0600,
+       .dout_offset = 0x0800,
+       .din_offset = 0x0A00,
+       .pinmux_offset = 0x0C00,
+       .type1_start = 34,
+       .type1_end = 149,
+       .port_shf = 4,
+       .port_mask = 0xf,
+       .port_align = 4,
+       .chip_type = MTK_CHIP_TYPE_BASE,
+       .eint_offsets = {
+               .name = "mt8135_eint",
+               .stat      = 0x000,
+               .ack       = 0x040,
+               .mask      = 0x080,
+               .mask_set  = 0x0c0,
+               .mask_clr  = 0x100,
+               .sens      = 0x140,
+               .sens_set  = 0x180,
+               .sens_clr  = 0x1c0,
+               .soft      = 0x200,
+               .soft_set  = 0x240,
+               .soft_clr  = 0x280,
+               .pol       = 0x300,
+               .pol_set   = 0x340,
+               .pol_clr   = 0x380,
+               .dom_en    = 0x400,
+               .dbnc_ctrl = 0x500,
+               .dbnc_set  = 0x600,
+               .dbnc_clr  = 0x700,
+               .port_mask = 7,
+               .ports     = 6,
+       },
+       .ap_num = 192,
+       .db_cnt = 16,
+};
+
+static int mt8135_pinctrl_probe(struct platform_device *pdev)
+{
+       return mtk_pctrl_init(pdev, &mt8135_pinctrl_data);
+}
+
+static const struct of_device_id mt8135_pctrl_match[] = {
+       {
+               .compatible = "mediatek,mt8135-pinctrl",
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, mt8135_pctrl_match);
+
+static struct platform_driver mtk_pinctrl_driver = {
+       .probe = mt8135_pinctrl_probe,
+       .driver = {
+               .name = "mediatek-mt8135-pinctrl",
+               .owner = THIS_MODULE,
+               .of_match_table = mt8135_pctrl_match,
+       },
+};
+
+static int __init mtk_pinctrl_init(void)
+{
+       return platform_driver_register(&mtk_pinctrl_driver);
+}
+
+module_init(mtk_pinctrl_init);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MediaTek Pinctrl Driver");
+MODULE_AUTHOR("Hongzhou Yang <hongzhou.yang@mediatek.com>");
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
new file mode 100644 (file)
index 0000000..412ea84
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 2014-2015 MediaTek Inc.
+ * Author: Hongzhou.Yang <hongzhou.yang@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/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/regmap.h>
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+#include "pinctrl-mtk-common.h"
+#include "pinctrl-mtk-mt8173.h"
+
+#define DRV_BASE                               0xb00
+
+/**
+ * struct mtk_pin_ies_smt_set - For special pins' ies and smt setting.
+ * @start: The start pin number of those special pins.
+ * @end: The end pin number of those special pins.
+ * @offset: The offset of special setting register.
+ * @bit: The bit of special setting register.
+ */
+struct mtk_pin_ies_smt_set {
+       unsigned int start;
+       unsigned int end;
+       unsigned int offset;
+       unsigned char bit;
+};
+
+#define MTK_PIN_IES_SMT_SET(_start, _end, _offset, _bit)       \
+       {       \
+               .start = _start,        \
+               .end = _end,    \
+               .bit = _bit,    \
+               .offset = _offset,      \
+       }
+
+/**
+ * struct mtk_pin_spec_pupd_set - For special pins' pull up/down setting.
+ * @pin: The pin number.
+ * @offset: The offset of special pull up/down setting register.
+ * @pupd_bit: The pull up/down bit in this register.
+ * @r0_bit: The r0 bit of pull resistor.
+ * @r1_bit: The r1 bit of pull resistor.
+ */
+struct mtk_pin_spec_pupd_set {
+       unsigned int pin;
+       unsigned int offset;
+       unsigned char pupd_bit;
+       unsigned char r1_bit;
+       unsigned char r0_bit;
+};
+
+#define MTK_PIN_PUPD_SPEC(_pin, _offset, _pupd, _r1, _r0)      \
+       {       \
+               .pin = _pin,    \
+               .offset = _offset,      \
+               .pupd_bit = _pupd,      \
+               .r1_bit = _r1,          \
+               .r0_bit = _r0,          \
+       }
+
+static const struct mtk_pin_spec_pupd_set mt8173_spec_pupd[] = {
+       MTK_PIN_PUPD_SPEC(119, 0xe00, 2, 1, 0),  /* KROW0 */
+       MTK_PIN_PUPD_SPEC(120, 0xe00, 6, 5, 4),  /* KROW1 */
+       MTK_PIN_PUPD_SPEC(121, 0xe00, 10, 9, 8), /* KROW2 */
+       MTK_PIN_PUPD_SPEC(122, 0xe10, 2, 1, 0),  /* KCOL0 */
+       MTK_PIN_PUPD_SPEC(123, 0xe10, 6, 5, 4),  /* KCOL1 */
+       MTK_PIN_PUPD_SPEC(124, 0xe10, 10, 9, 8), /* KCOL2 */
+
+       MTK_PIN_PUPD_SPEC(67, 0xd10, 2, 1, 0),   /* ms0 DS */
+       MTK_PIN_PUPD_SPEC(68, 0xd00, 2, 1, 0),   /* ms0 RST */
+       MTK_PIN_PUPD_SPEC(66, 0xc10, 2, 1, 0),   /* ms0 cmd */
+       MTK_PIN_PUPD_SPEC(65, 0xc00, 2, 1, 0),   /* ms0 clk */
+       MTK_PIN_PUPD_SPEC(57, 0xc20, 2, 1, 0),   /* ms0 data0 */
+       MTK_PIN_PUPD_SPEC(58, 0xc20, 2, 1, 0),   /* ms0 data1 */
+       MTK_PIN_PUPD_SPEC(59, 0xc20, 2, 1, 0),   /* ms0 data2 */
+       MTK_PIN_PUPD_SPEC(60, 0xc20, 2, 1, 0),   /* ms0 data3 */
+       MTK_PIN_PUPD_SPEC(61, 0xc20, 2, 1, 0),   /* ms0 data4 */
+       MTK_PIN_PUPD_SPEC(62, 0xc20, 2, 1, 0),   /* ms0 data5 */
+       MTK_PIN_PUPD_SPEC(63, 0xc20, 2, 1, 0),   /* ms0 data6 */
+       MTK_PIN_PUPD_SPEC(64, 0xc20, 2, 1, 0),   /* ms0 data7 */
+
+       MTK_PIN_PUPD_SPEC(78, 0xc50, 2, 1, 0),    /* ms1 cmd */
+       MTK_PIN_PUPD_SPEC(73, 0xd20, 2, 1, 0),    /* ms1 dat0 */
+       MTK_PIN_PUPD_SPEC(74, 0xd20, 6, 5, 4),    /* ms1 dat1 */
+       MTK_PIN_PUPD_SPEC(75, 0xd20, 10, 9, 8),   /* ms1 dat2 */
+       MTK_PIN_PUPD_SPEC(76, 0xd20, 14, 13, 12), /* ms1 dat3 */
+       MTK_PIN_PUPD_SPEC(77, 0xc40, 2, 1, 0),    /* ms1 clk */
+
+       MTK_PIN_PUPD_SPEC(100, 0xd40, 2, 1, 0),    /* ms2 dat0 */
+       MTK_PIN_PUPD_SPEC(101, 0xd40, 6, 5, 4),    /* ms2 dat1 */
+       MTK_PIN_PUPD_SPEC(102, 0xd40, 10, 9, 8),   /* ms2 dat2 */
+       MTK_PIN_PUPD_SPEC(103, 0xd40, 14, 13, 12), /* ms2 dat3 */
+       MTK_PIN_PUPD_SPEC(104, 0xc80, 2, 1, 0),    /* ms2 clk */
+       MTK_PIN_PUPD_SPEC(105, 0xc90, 2, 1, 0),    /* ms2 cmd */
+
+       MTK_PIN_PUPD_SPEC(22, 0xd60, 2, 1, 0),    /* ms3 dat0 */
+       MTK_PIN_PUPD_SPEC(23, 0xd60, 6, 5, 4),    /* ms3 dat1 */
+       MTK_PIN_PUPD_SPEC(24, 0xd60, 10, 9, 8),   /* ms3 dat2 */
+       MTK_PIN_PUPD_SPEC(25, 0xd60, 14, 13, 12), /* ms3 dat3 */
+       MTK_PIN_PUPD_SPEC(26, 0xcc0, 2, 1, 0),    /* ms3 clk */
+       MTK_PIN_PUPD_SPEC(27, 0xcd0, 2, 1, 0)     /* ms3 cmd */
+};
+
+static int spec_pull_set(struct regmap *regmap, unsigned int pin,
+               unsigned char align, bool isup, unsigned int r1r0)
+{
+       unsigned int i;
+       unsigned int reg_pupd, reg_set, reg_rst;
+       unsigned int bit_pupd, bit_r0, bit_r1;
+       const struct mtk_pin_spec_pupd_set *spec_pupd_pin;
+       bool find = false;
+
+       for (i = 0; i < ARRAY_SIZE(mt8173_spec_pupd); i++) {
+               if (pin == mt8173_spec_pupd[i].pin) {
+                       find = true;
+                       break;
+               }
+       }
+
+       if (!find)
+               return -EINVAL;
+
+       spec_pupd_pin = mt8173_spec_pupd + i;
+       reg_set = spec_pupd_pin->offset + align;
+       reg_rst = spec_pupd_pin->offset + (align << 1);
+
+       if (isup)
+               reg_pupd = reg_rst;
+       else
+               reg_pupd = reg_set;
+
+       bit_pupd = BIT(spec_pupd_pin->pupd_bit);
+       regmap_write(regmap, reg_pupd, bit_pupd);
+
+       bit_r0 = BIT(spec_pupd_pin->r0_bit);
+       bit_r1 = BIT(spec_pupd_pin->r1_bit);
+
+       switch (r1r0) {
+       case MTK_PUPD_SET_R1R0_00:
+               regmap_write(regmap, reg_rst, bit_r0);
+               regmap_write(regmap, reg_rst, bit_r1);
+               break;
+       case MTK_PUPD_SET_R1R0_01:
+               regmap_write(regmap, reg_set, bit_r0);
+               regmap_write(regmap, reg_rst, bit_r1);
+               break;
+       case MTK_PUPD_SET_R1R0_10:
+               regmap_write(regmap, reg_rst, bit_r0);
+               regmap_write(regmap, reg_set, bit_r1);
+               break;
+       case MTK_PUPD_SET_R1R0_11:
+               regmap_write(regmap, reg_set, bit_r0);
+               regmap_write(regmap, reg_set, bit_r1);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct mtk_pin_ies_smt_set mt8173_ies_smt_set[] = {
+       MTK_PIN_IES_SMT_SET(0, 4, 0x930, 1),
+       MTK_PIN_IES_SMT_SET(5, 9, 0x930, 2),
+       MTK_PIN_IES_SMT_SET(10, 13, 0x930, 10),
+       MTK_PIN_IES_SMT_SET(14, 15, 0x940, 10),
+       MTK_PIN_IES_SMT_SET(16, 16, 0x930, 0),
+       MTK_PIN_IES_SMT_SET(17, 17, 0x950, 2),
+       MTK_PIN_IES_SMT_SET(18, 21, 0x940, 3),
+       MTK_PIN_IES_SMT_SET(29, 32, 0x930, 3),
+       MTK_PIN_IES_SMT_SET(33, 33, 0x930, 4),
+       MTK_PIN_IES_SMT_SET(34, 36, 0x930, 5),
+       MTK_PIN_IES_SMT_SET(37, 38, 0x930, 6),
+       MTK_PIN_IES_SMT_SET(39, 39, 0x930, 7),
+       MTK_PIN_IES_SMT_SET(40, 41, 0x930, 9),
+       MTK_PIN_IES_SMT_SET(42, 42, 0x940, 0),
+       MTK_PIN_IES_SMT_SET(43, 44, 0x930, 11),
+       MTK_PIN_IES_SMT_SET(45, 46, 0x930, 12),
+       MTK_PIN_IES_SMT_SET(57, 64, 0xc20, 13),
+       MTK_PIN_IES_SMT_SET(65, 65, 0xc10, 13),
+       MTK_PIN_IES_SMT_SET(66, 66, 0xc00, 13),
+       MTK_PIN_IES_SMT_SET(67, 67, 0xd10, 13),
+       MTK_PIN_IES_SMT_SET(68, 68, 0xd00, 13),
+       MTK_PIN_IES_SMT_SET(69, 72, 0x940, 14),
+       MTK_PIN_IES_SMT_SET(73, 76, 0xc60, 13),
+       MTK_PIN_IES_SMT_SET(77, 77, 0xc40, 13),
+       MTK_PIN_IES_SMT_SET(78, 78, 0xc50, 13),
+       MTK_PIN_IES_SMT_SET(79, 82, 0x940, 15),
+       MTK_PIN_IES_SMT_SET(83, 83, 0x950, 0),
+       MTK_PIN_IES_SMT_SET(84, 85, 0x950, 1),
+       MTK_PIN_IES_SMT_SET(86, 91, 0x950, 2),
+       MTK_PIN_IES_SMT_SET(92, 92, 0x930, 13),
+       MTK_PIN_IES_SMT_SET(93, 95, 0x930, 14),
+       MTK_PIN_IES_SMT_SET(96, 99, 0x930, 15),
+       MTK_PIN_IES_SMT_SET(100, 103, 0xca0, 13),
+       MTK_PIN_IES_SMT_SET(104, 104, 0xc80, 13),
+       MTK_PIN_IES_SMT_SET(105, 105, 0xc90, 13),
+       MTK_PIN_IES_SMT_SET(106, 107, 0x940, 4),
+       MTK_PIN_IES_SMT_SET(108, 112, 0x940, 1),
+       MTK_PIN_IES_SMT_SET(113, 116, 0x940, 2),
+       MTK_PIN_IES_SMT_SET(117, 118, 0x940, 5),
+       MTK_PIN_IES_SMT_SET(119, 124, 0x940, 6),
+       MTK_PIN_IES_SMT_SET(125, 126, 0x940, 7),
+       MTK_PIN_IES_SMT_SET(127, 127, 0x940, 0),
+       MTK_PIN_IES_SMT_SET(128, 128, 0x950, 8),
+       MTK_PIN_IES_SMT_SET(129, 130, 0x950, 9),
+       MTK_PIN_IES_SMT_SET(131, 132, 0x950, 8),
+       MTK_PIN_IES_SMT_SET(133, 134, 0x910, 8)
+};
+
+static int spec_ies_smt_set(struct regmap *regmap, unsigned int pin,
+               unsigned char align, int value)
+{
+       unsigned int i, reg_addr, bit;
+       bool find = false;
+
+       for (i = 0; i < ARRAY_SIZE(mt8173_ies_smt_set); i++) {
+               if (pin >= mt8173_ies_smt_set[i].start &&
+                               pin <= mt8173_ies_smt_set[i].end) {
+                       find = true;
+                       break;
+               }
+       }
+
+       if (!find)
+               return -EINVAL;
+
+       if (value)
+               reg_addr = mt8173_ies_smt_set[i].offset + align;
+       else
+               reg_addr = mt8173_ies_smt_set[i].offset + (align << 1);
+
+       bit = BIT(mt8173_ies_smt_set[i].bit);
+       regmap_write(regmap, reg_addr, bit);
+       return 0;
+}
+
+static const struct mtk_drv_group_desc mt8173_drv_grp[] =  {
+       /* 0E4E8SR 4/8/12/16 */
+       MTK_DRV_GRP(4, 16, 1, 2, 4),
+       /* 0E2E4SR  2/4/6/8 */
+       MTK_DRV_GRP(2, 8, 1, 2, 2),
+       /* E8E4E2  2/4/6/8/10/12/14/16 */
+       MTK_DRV_GRP(2, 16, 0, 2, 2)
+};
+
+static const struct mtk_pin_drv_grp mt8173_pin_drv[] = {
+       MTK_PIN_DRV_GRP(0, DRV_BASE+0x20, 12, 0),
+       MTK_PIN_DRV_GRP(1, DRV_BASE+0x20, 12, 0),
+       MTK_PIN_DRV_GRP(2, DRV_BASE+0x20, 12, 0),
+       MTK_PIN_DRV_GRP(3, DRV_BASE+0x20, 12, 0),
+       MTK_PIN_DRV_GRP(4, DRV_BASE+0x20, 12, 0),
+       MTK_PIN_DRV_GRP(5, DRV_BASE+0x30, 0, 0),
+       MTK_PIN_DRV_GRP(6, DRV_BASE+0x30, 0, 0),
+       MTK_PIN_DRV_GRP(7, DRV_BASE+0x30, 0, 0),
+       MTK_PIN_DRV_GRP(8, DRV_BASE+0x30, 0, 0),
+       MTK_PIN_DRV_GRP(9, DRV_BASE+0x30, 0, 0),
+       MTK_PIN_DRV_GRP(10, DRV_BASE+0x30, 4, 1),
+       MTK_PIN_DRV_GRP(11, DRV_BASE+0x30, 4, 1),
+       MTK_PIN_DRV_GRP(12, DRV_BASE+0x30, 4, 1),
+       MTK_PIN_DRV_GRP(13, DRV_BASE+0x30, 4, 1),
+       MTK_PIN_DRV_GRP(14, DRV_BASE+0x40, 8, 1),
+       MTK_PIN_DRV_GRP(15, DRV_BASE+0x40, 8, 1),
+       MTK_PIN_DRV_GRP(16, DRV_BASE, 8, 1),
+       MTK_PIN_DRV_GRP(17, 0xce0, 8, 2),
+       MTK_PIN_DRV_GRP(22, 0xce0, 8, 2),
+       MTK_PIN_DRV_GRP(23, 0xce0, 8, 2),
+       MTK_PIN_DRV_GRP(24, 0xce0, 8, 2),
+       MTK_PIN_DRV_GRP(25, 0xce0, 8, 2),
+       MTK_PIN_DRV_GRP(26, 0xcc0, 8, 2),
+       MTK_PIN_DRV_GRP(27, 0xcd0, 8, 2),
+       MTK_PIN_DRV_GRP(28, 0xd70, 8, 2),
+       MTK_PIN_DRV_GRP(29, DRV_BASE+0x80, 12, 1),
+       MTK_PIN_DRV_GRP(30, DRV_BASE+0x80, 12, 1),
+       MTK_PIN_DRV_GRP(31, DRV_BASE+0x80, 12, 1),
+       MTK_PIN_DRV_GRP(32, DRV_BASE+0x80, 12, 1),
+       MTK_PIN_DRV_GRP(33, DRV_BASE+0x10, 12, 1),
+       MTK_PIN_DRV_GRP(34, DRV_BASE+0x10, 8, 1),
+       MTK_PIN_DRV_GRP(35, DRV_BASE+0x10, 8, 1),
+       MTK_PIN_DRV_GRP(36, DRV_BASE+0x10, 8, 1),
+       MTK_PIN_DRV_GRP(37, DRV_BASE+0x10, 4, 1),
+       MTK_PIN_DRV_GRP(38, DRV_BASE+0x10, 4, 1),
+       MTK_PIN_DRV_GRP(39, DRV_BASE+0x20, 0, 0),
+       MTK_PIN_DRV_GRP(40, DRV_BASE+0x20, 8, 0),
+       MTK_PIN_DRV_GRP(41, DRV_BASE+0x20, 8, 0),
+       MTK_PIN_DRV_GRP(42, DRV_BASE+0x50, 8, 1),
+       MTK_PIN_DRV_GRP(57, 0xc20, 8, 2),
+       MTK_PIN_DRV_GRP(58, 0xc20, 8, 2),
+       MTK_PIN_DRV_GRP(59, 0xc20, 8, 2),
+       MTK_PIN_DRV_GRP(60, 0xc20, 8, 2),
+       MTK_PIN_DRV_GRP(61, 0xc20, 8, 2),
+       MTK_PIN_DRV_GRP(62, 0xc20, 8, 2),
+       MTK_PIN_DRV_GRP(63, 0xc20, 8, 2),
+       MTK_PIN_DRV_GRP(64, 0xc20, 8, 2),
+       MTK_PIN_DRV_GRP(65, 0xc00, 8, 2),
+       MTK_PIN_DRV_GRP(66, 0xc10, 8, 2),
+       MTK_PIN_DRV_GRP(67, 0xd10, 8, 2),
+       MTK_PIN_DRV_GRP(68, 0xd00, 8, 2),
+       MTK_PIN_DRV_GRP(69, DRV_BASE+0x80, 0, 1),
+       MTK_PIN_DRV_GRP(70, DRV_BASE+0x80, 0, 1),
+       MTK_PIN_DRV_GRP(71, DRV_BASE+0x80, 0, 1),
+       MTK_PIN_DRV_GRP(72, DRV_BASE+0x80, 0, 1),
+       MTK_PIN_DRV_GRP(73, 0xc60, 8, 2),
+       MTK_PIN_DRV_GRP(74, 0xc60, 8, 2),
+       MTK_PIN_DRV_GRP(75, 0xc60, 8, 2),
+       MTK_PIN_DRV_GRP(76, 0xc60, 8, 2),
+       MTK_PIN_DRV_GRP(77, 0xc40, 8, 2),
+       MTK_PIN_DRV_GRP(78, 0xc50, 8, 2),
+       MTK_PIN_DRV_GRP(79, DRV_BASE+0x70, 12, 1),
+       MTK_PIN_DRV_GRP(80, DRV_BASE+0x70, 12, 1),
+       MTK_PIN_DRV_GRP(81, DRV_BASE+0x70, 12, 1),
+       MTK_PIN_DRV_GRP(82, DRV_BASE+0x70, 12, 1),
+       MTK_PIN_DRV_GRP(83, DRV_BASE, 4, 1),
+       MTK_PIN_DRV_GRP(84, DRV_BASE, 0, 1),
+       MTK_PIN_DRV_GRP(85, DRV_BASE, 0, 1),
+       MTK_PIN_DRV_GRP(85, DRV_BASE+0x60, 8, 1),
+       MTK_PIN_DRV_GRP(86, DRV_BASE+0x60, 8, 1),
+       MTK_PIN_DRV_GRP(87, DRV_BASE+0x60, 8, 1),
+       MTK_PIN_DRV_GRP(88, DRV_BASE+0x60, 8, 1),
+       MTK_PIN_DRV_GRP(89, DRV_BASE+0x60, 8, 1),
+       MTK_PIN_DRV_GRP(90, DRV_BASE+0x60, 8, 1),
+       MTK_PIN_DRV_GRP(91, DRV_BASE+0x60, 8, 1),
+       MTK_PIN_DRV_GRP(92, DRV_BASE+0x60, 4, 0),
+       MTK_PIN_DRV_GRP(93, DRV_BASE+0x60, 0, 0),
+       MTK_PIN_DRV_GRP(94, DRV_BASE+0x60, 0, 0),
+       MTK_PIN_DRV_GRP(95, DRV_BASE+0x60, 0, 0),
+       MTK_PIN_DRV_GRP(96, DRV_BASE+0x80, 8, 1),
+       MTK_PIN_DRV_GRP(97, DRV_BASE+0x80, 8, 1),
+       MTK_PIN_DRV_GRP(98, DRV_BASE+0x80, 8, 1),
+       MTK_PIN_DRV_GRP(99, DRV_BASE+0x80, 8, 1),
+       MTK_PIN_DRV_GRP(100, 0xca0, 8, 2),
+       MTK_PIN_DRV_GRP(101, 0xca0, 8, 2),
+       MTK_PIN_DRV_GRP(102, 0xca0, 8, 2),
+       MTK_PIN_DRV_GRP(103, 0xca0, 8, 2),
+       MTK_PIN_DRV_GRP(104, 0xc80, 8, 2),
+       MTK_PIN_DRV_GRP(105, 0xc90, 8, 2),
+       MTK_PIN_DRV_GRP(108, DRV_BASE+0x50, 0, 1),
+       MTK_PIN_DRV_GRP(109, DRV_BASE+0x50, 0, 1),
+       MTK_PIN_DRV_GRP(110, DRV_BASE+0x50, 0, 1),
+       MTK_PIN_DRV_GRP(111, DRV_BASE+0x50, 0, 1),
+       MTK_PIN_DRV_GRP(112, DRV_BASE+0x50, 0, 1),
+       MTK_PIN_DRV_GRP(113, DRV_BASE+0x80, 4, 1),
+       MTK_PIN_DRV_GRP(114, DRV_BASE+0x80, 4, 1),
+       MTK_PIN_DRV_GRP(115, DRV_BASE+0x80, 4, 1),
+       MTK_PIN_DRV_GRP(116, DRV_BASE+0x80, 4, 1),
+       MTK_PIN_DRV_GRP(117, DRV_BASE+0x90, 0, 1),
+       MTK_PIN_DRV_GRP(118, DRV_BASE+0x90, 0, 1),
+       MTK_PIN_DRV_GRP(119, DRV_BASE+0x50, 4, 1),
+       MTK_PIN_DRV_GRP(120, DRV_BASE+0x50, 4, 1),
+       MTK_PIN_DRV_GRP(121, DRV_BASE+0x50, 4, 1),
+       MTK_PIN_DRV_GRP(122, DRV_BASE+0x50, 4, 1),
+       MTK_PIN_DRV_GRP(123, DRV_BASE+0x50, 4, 1),
+       MTK_PIN_DRV_GRP(124, DRV_BASE+0x50, 4, 1),
+       MTK_PIN_DRV_GRP(125, DRV_BASE+0x30, 12, 1),
+       MTK_PIN_DRV_GRP(126, DRV_BASE+0x30, 12, 1),
+       MTK_PIN_DRV_GRP(127, DRV_BASE+0x50, 8, 1),
+       MTK_PIN_DRV_GRP(128, DRV_BASE+0x40, 0, 1),
+       MTK_PIN_DRV_GRP(129, DRV_BASE+0x40, 0, 1),
+       MTK_PIN_DRV_GRP(130, DRV_BASE+0x40, 0, 1),
+       MTK_PIN_DRV_GRP(131, DRV_BASE+0x40, 0, 1),
+       MTK_PIN_DRV_GRP(132, DRV_BASE+0x40, 0, 1)
+};
+
+static const struct mtk_pinctrl_devdata mt8173_pinctrl_data = {
+       .pins = mtk_pins_mt8173,
+       .npins = ARRAY_SIZE(mtk_pins_mt8173),
+       .grp_desc = mt8173_drv_grp,
+       .n_grp_cls = ARRAY_SIZE(mt8173_drv_grp),
+       .pin_drv_grp = mt8173_pin_drv,
+       .n_pin_drv_grps = ARRAY_SIZE(mt8173_pin_drv),
+       .spec_pull_set = spec_pull_set,
+       .spec_ies_smt_set = spec_ies_smt_set,
+       .dir_offset = 0x0000,
+       .pullen_offset = 0x0100,
+       .pullsel_offset = 0x0200,
+       .dout_offset = 0x0400,
+       .din_offset = 0x0500,
+       .pinmux_offset = 0x0600,
+       .type1_start = 135,
+       .type1_end = 135,
+       .port_shf = 4,
+       .port_mask = 0xf,
+       .port_align = 4,
+       .eint_offsets = {
+               .name = "mt8173_eint",
+               .stat      = 0x000,
+               .ack       = 0x040,
+               .mask      = 0x080,
+               .mask_set  = 0x0c0,
+               .mask_clr  = 0x100,
+               .sens      = 0x140,
+               .sens_set  = 0x180,
+               .sens_clr  = 0x1c0,
+               .soft      = 0x200,
+               .soft_set  = 0x240,
+               .soft_clr  = 0x280,
+               .pol       = 0x300,
+               .pol_set   = 0x340,
+               .pol_clr   = 0x380,
+               .dom_en    = 0x400,
+               .dbnc_ctrl = 0x500,
+               .dbnc_set  = 0x600,
+               .dbnc_clr  = 0x700,
+               .port_mask = 7,
+               .ports     = 6,
+       },
+       .ap_num = 224,
+       .db_cnt = 16,
+};
+
+static int mt8173_pinctrl_probe(struct platform_device *pdev)
+{
+       return mtk_pctrl_init(pdev, &mt8173_pinctrl_data);
+}
+
+static const struct of_device_id mt8173_pctrl_match[] = {
+       {
+               .compatible = "mediatek,mt8173-pinctrl",
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, mt8173_pctrl_match);
+
+static struct platform_driver mtk_pinctrl_driver = {
+       .probe = mt8173_pinctrl_probe,
+       .driver = {
+               .name = "mediatek-mt8173-pinctrl",
+               .of_match_table = mt8173_pctrl_match,
+       },
+};
+
+static int __init mtk_pinctrl_init(void)
+{
+       return platform_driver_register(&mtk_pinctrl_driver);
+}
+
+module_init(mtk_pinctrl_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MediaTek Pinctrl Driver");
+MODULE_AUTHOR("Hongzhou Yang <hongzhou.yang@mediatek.com>");
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
new file mode 100644 (file)
index 0000000..493294c
--- /dev/null
@@ -0,0 +1,1257 @@
+/*
+ * mt65xx pinctrl driver based on Allwinner A1X pinctrl driver.
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Hongzhou.Yang <hongzhou.yang@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/io.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "../pinctrl-utils.h"
+#include "pinctrl-mtk-common.h"
+
+#define MAX_GPIO_MODE_PER_REG 5
+#define GPIO_MODE_BITS        3
+
+static const char * const mtk_gpio_functions[] = {
+       "func0", "func1", "func2", "func3",
+       "func4", "func5", "func6", "func7",
+};
+
+/*
+ * There are two base address for pull related configuration
+ * in mt8135, and different GPIO pins use different base address.
+ * When pin number greater than type1_start and less than type1_end,
+ * should use the second base address.
+ */
+static struct regmap *mtk_get_regmap(struct mtk_pinctrl *pctl,
+               unsigned long pin)
+{
+       if (pin >= pctl->devdata->type1_start && pin < pctl->devdata->type1_end)
+               return pctl->regmap2;
+       return pctl->regmap1;
+}
+
+static unsigned int mtk_get_port(struct mtk_pinctrl *pctl, unsigned long pin)
+{
+       /* Different SoC has different mask and port shift. */
+       return ((pin >> 4) & pctl->devdata->port_mask)
+                       << pctl->devdata->port_shf;
+}
+
+static int mtk_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+                       struct pinctrl_gpio_range *range, unsigned offset,
+                       bool input)
+{
+       unsigned int reg_addr;
+       unsigned int bit;
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       reg_addr = mtk_get_port(pctl, offset) + pctl->devdata->dir_offset;
+       bit = BIT(offset & 0xf);
+
+       if (input)
+               /* Different SoC has different alignment offset. */
+               reg_addr = CLR_ADDR(reg_addr, pctl);
+       else
+               reg_addr = SET_ADDR(reg_addr, pctl);
+
+       regmap_write(mtk_get_regmap(pctl, offset), reg_addr, bit);
+       return 0;
+}
+
+static void mtk_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       unsigned int reg_addr;
+       unsigned int bit;
+       struct mtk_pinctrl *pctl = dev_get_drvdata(chip->dev);
+
+       reg_addr = mtk_get_port(pctl, offset) + pctl->devdata->dout_offset;
+       bit = BIT(offset & 0xf);
+
+       if (value)
+               reg_addr = SET_ADDR(reg_addr, pctl);
+       else
+               reg_addr = CLR_ADDR(reg_addr, pctl);
+
+       regmap_write(mtk_get_regmap(pctl, offset), reg_addr, bit);
+}
+
+static void mtk_pconf_set_ies_smt(struct mtk_pinctrl *pctl, unsigned pin,
+               int value, enum pin_config_param param)
+{
+       unsigned int reg_addr, offset;
+       unsigned int bit;
+       int ret;
+
+       /*
+        * Due to some pins are irregular, their input enable and smt
+        * control register are discontinuous, but they are mapping together.
+        * So we need this special handle.
+        */
+       if (pctl->devdata->spec_ies_smt_set) {
+               ret = pctl->devdata->spec_ies_smt_set(mtk_get_regmap(pctl, pin),
+                       pin, pctl->devdata->port_align, value);
+               if (!ret)
+                       return;
+       }
+
+       bit = BIT(pin & 0xf);
+
+       if (param == PIN_CONFIG_INPUT_ENABLE)
+               offset = pctl->devdata->ies_offset;
+       else
+               offset = pctl->devdata->smt_offset;
+
+       if (value)
+               reg_addr = SET_ADDR(mtk_get_port(pctl, pin) + offset, pctl);
+       else
+               reg_addr = CLR_ADDR(mtk_get_port(pctl, pin) + offset, pctl);
+
+       regmap_write(mtk_get_regmap(pctl, pin), reg_addr, bit);
+}
+
+static const struct mtk_pin_drv_grp *mtk_find_pin_drv_grp_by_pin(
+               struct mtk_pinctrl *pctl,  unsigned long pin) {
+       int i;
+
+       for (i = 0; i < pctl->devdata->n_pin_drv_grps; i++) {
+               const struct mtk_pin_drv_grp *pin_drv =
+                               pctl->devdata->pin_drv_grp + i;
+               if (pin == pin_drv->pin)
+                       return pin_drv;
+       }
+
+       return NULL;
+}
+
+static int mtk_pconf_set_driving(struct mtk_pinctrl *pctl,
+               unsigned int pin, unsigned char driving)
+{
+       const struct mtk_pin_drv_grp *pin_drv;
+       unsigned int val;
+       unsigned int bits, mask, shift;
+       const struct mtk_drv_group_desc *drv_grp;
+
+       if (pin >= pctl->devdata->npins)
+               return -EINVAL;
+
+       pin_drv = mtk_find_pin_drv_grp_by_pin(pctl, pin);
+       if (!pin_drv || pin_drv->grp > pctl->devdata->n_grp_cls)
+               return -EINVAL;
+
+       drv_grp = pctl->devdata->grp_desc + pin_drv->grp;
+       if (driving >= drv_grp->min_drv && driving <= drv_grp->max_drv
+               && !(driving % drv_grp->step)) {
+               val = driving / drv_grp->step - 1;
+               bits = drv_grp->high_bit - drv_grp->low_bit + 1;
+               mask = BIT(bits) - 1;
+               shift = pin_drv->bit + drv_grp->low_bit;
+               mask <<= shift;
+               val <<= shift;
+               return regmap_update_bits(mtk_get_regmap(pctl, pin),
+                               pin_drv->offset, mask, val);
+       }
+
+       return -EINVAL;
+}
+
+static int mtk_pconf_set_pull_select(struct mtk_pinctrl *pctl,
+               unsigned int pin, bool enable, bool isup, unsigned int arg)
+{
+       unsigned int bit;
+       unsigned int reg_pullen, reg_pullsel;
+       int ret;
+
+       /* Some pins' pull setting are very different,
+        * they have separate pull up/down bit, R0 and R1
+        * resistor bit, so we need this special handle.
+        */
+       if (pctl->devdata->spec_pull_set) {
+               ret = pctl->devdata->spec_pull_set(mtk_get_regmap(pctl, pin),
+                       pin, pctl->devdata->port_align, isup, arg);
+               if (!ret)
+                       return 0;
+       }
+
+       /* For generic pull config, default arg value should be 0 or 1. */
+       if (arg != 0 && arg != 1) {
+               dev_err(pctl->dev, "invalid pull-up argument %d on pin %d .\n",
+                       arg, pin);
+               return -EINVAL;
+       }
+
+       bit = BIT(pin & 0xf);
+       if (enable)
+               reg_pullen = SET_ADDR(mtk_get_port(pctl, pin) +
+                       pctl->devdata->pullen_offset, pctl);
+       else
+               reg_pullen = CLR_ADDR(mtk_get_port(pctl, pin) +
+                       pctl->devdata->pullen_offset, pctl);
+
+       if (isup)
+               reg_pullsel = SET_ADDR(mtk_get_port(pctl, pin) +
+                       pctl->devdata->pullsel_offset, pctl);
+       else
+               reg_pullsel = CLR_ADDR(mtk_get_port(pctl, pin) +
+                       pctl->devdata->pullsel_offset, pctl);
+
+       regmap_write(mtk_get_regmap(pctl, pin), reg_pullen, bit);
+       regmap_write(mtk_get_regmap(pctl, pin), reg_pullsel, bit);
+       return 0;
+}
+
+static int mtk_pconf_parse_conf(struct pinctrl_dev *pctldev,
+               unsigned int pin, enum pin_config_param param,
+               enum pin_config_param arg)
+{
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       switch (param) {
+       case PIN_CONFIG_BIAS_DISABLE:
+               mtk_pconf_set_pull_select(pctl, pin, false, false, arg);
+               break;
+       case PIN_CONFIG_BIAS_PULL_UP:
+               mtk_pconf_set_pull_select(pctl, pin, true, true, arg);
+               break;
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               mtk_pconf_set_pull_select(pctl, pin, true, false, arg);
+               break;
+       case PIN_CONFIG_INPUT_ENABLE:
+               mtk_pconf_set_ies_smt(pctl, pin, arg, param);
+               break;
+       case PIN_CONFIG_OUTPUT:
+               mtk_gpio_set(pctl->chip, pin, arg);
+               mtk_pmx_gpio_set_direction(pctldev, NULL, pin, false);
+               break;
+       case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+               mtk_pconf_set_ies_smt(pctl, pin, arg, param);
+               break;
+       case PIN_CONFIG_DRIVE_STRENGTH:
+               mtk_pconf_set_driving(pctl, pin, arg);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int mtk_pconf_group_get(struct pinctrl_dev *pctldev,
+                                unsigned group,
+                                unsigned long *config)
+{
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       *config = pctl->groups[group].config;
+
+       return 0;
+}
+
+static int mtk_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
+                                unsigned long *configs, unsigned num_configs)
+{
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct mtk_pinctrl_group *g = &pctl->groups[group];
+       int i;
+
+       for (i = 0; i < num_configs; i++) {
+               mtk_pconf_parse_conf(pctldev, g->pin,
+                       pinconf_to_config_param(configs[i]),
+                       pinconf_to_config_argument(configs[i]));
+
+               g->config = configs[i];
+       }
+
+       return 0;
+}
+
+static const struct pinconf_ops mtk_pconf_ops = {
+       .pin_config_group_get   = mtk_pconf_group_get,
+       .pin_config_group_set   = mtk_pconf_group_set,
+};
+
+static struct mtk_pinctrl_group *
+mtk_pctrl_find_group_by_pin(struct mtk_pinctrl *pctl, u32 pin)
+{
+       int i;
+
+       for (i = 0; i < pctl->ngroups; i++) {
+               struct mtk_pinctrl_group *grp = pctl->groups + i;
+
+               if (grp->pin == pin)
+                       return grp;
+       }
+
+       return NULL;
+}
+
+static const struct mtk_desc_function *mtk_pctrl_find_function_by_pin(
+               struct mtk_pinctrl *pctl, u32 pin_num, u32 fnum)
+{
+       const struct mtk_desc_pin *pin = pctl->devdata->pins + pin_num;
+       const struct mtk_desc_function *func = pin->functions;
+
+       while (func && func->name) {
+               if (func->muxval == fnum)
+                       return func;
+               func++;
+       }
+
+       return NULL;
+}
+
+static bool mtk_pctrl_is_function_valid(struct mtk_pinctrl *pctl,
+               u32 pin_num, u32 fnum)
+{
+       int i;
+
+       for (i = 0; i < pctl->devdata->npins; i++) {
+               const struct mtk_desc_pin *pin = pctl->devdata->pins + i;
+
+               if (pin->pin.number == pin_num) {
+                       const struct mtk_desc_function *func =
+                                       pin->functions;
+
+                       while (func && func->name) {
+                               if (func->muxval == fnum)
+                                       return true;
+                               func++;
+                       }
+
+                       break;
+               }
+       }
+
+       return false;
+}
+
+static int mtk_pctrl_dt_node_to_map_func(struct mtk_pinctrl *pctl,
+               u32 pin, u32 fnum, struct mtk_pinctrl_group *grp,
+               struct pinctrl_map **map, unsigned *reserved_maps,
+               unsigned *num_maps)
+{
+       bool ret;
+
+       if (*num_maps == *reserved_maps)
+               return -ENOSPC;
+
+       (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
+       (*map)[*num_maps].data.mux.group = grp->name;
+
+       ret = mtk_pctrl_is_function_valid(pctl, pin, fnum);
+       if (!ret) {
+               dev_err(pctl->dev, "invalid function %d on pin %d .\n",
+                               fnum, pin);
+               return -EINVAL;
+       }
+
+       (*map)[*num_maps].data.mux.function = mtk_gpio_functions[fnum];
+       (*num_maps)++;
+
+       return 0;
+}
+
+static int mtk_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+                                     struct device_node *node,
+                                     struct pinctrl_map **map,
+                                     unsigned *reserved_maps,
+                                     unsigned *num_maps)
+{
+       struct property *pins;
+       u32 pinfunc, pin, func;
+       int num_pins, num_funcs, maps_per_pin;
+       unsigned long *configs;
+       unsigned int num_configs;
+       bool has_config = 0;
+       int i, err;
+       unsigned reserve = 0;
+       struct mtk_pinctrl_group *grp;
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       pins = of_find_property(node, "pinmux", NULL);
+       if (!pins) {
+               dev_err(pctl->dev, "missing pins property in node %s .\n",
+                               node->name);
+               return -EINVAL;
+       }
+
+       err = pinconf_generic_parse_dt_config(node, pctldev, &configs,
+               &num_configs);
+       if (num_configs)
+               has_config = 1;
+
+       num_pins = pins->length / sizeof(u32);
+       num_funcs = num_pins;
+       maps_per_pin = 0;
+       if (num_funcs)
+               maps_per_pin++;
+       if (has_config && num_pins >= 1)
+               maps_per_pin++;
+
+       if (!num_pins || !maps_per_pin)
+               return -EINVAL;
+
+       reserve = num_pins * maps_per_pin;
+
+       err = pinctrl_utils_reserve_map(pctldev, map,
+                       reserved_maps, num_maps, reserve);
+       if (err < 0)
+               goto fail;
+
+       for (i = 0; i < num_pins; i++) {
+               err = of_property_read_u32_index(node, "pinmux",
+                               i, &pinfunc);
+               if (err)
+                       goto fail;
+
+               pin = MTK_GET_PIN_NO(pinfunc);
+               func = MTK_GET_PIN_FUNC(pinfunc);
+
+               if (pin >= pctl->devdata->npins ||
+                               func >= ARRAY_SIZE(mtk_gpio_functions)) {
+                       dev_err(pctl->dev, "invalid pins value.\n");
+                       err = -EINVAL;
+                       goto fail;
+               }
+
+               grp = mtk_pctrl_find_group_by_pin(pctl, pin);
+               if (!grp) {
+                       dev_err(pctl->dev, "unable to match pin %d to group\n",
+                                       pin);
+                       return -EINVAL;
+               }
+
+               err = mtk_pctrl_dt_node_to_map_func(pctl, pin, func, grp, map,
+                               reserved_maps, num_maps);
+               if (err < 0)
+                       goto fail;
+
+               if (has_config) {
+                       err = pinctrl_utils_add_map_configs(pctldev, map,
+                                       reserved_maps, num_maps, grp->name,
+                                       configs, num_configs,
+                                       PIN_MAP_TYPE_CONFIGS_GROUP);
+                       if (err < 0)
+                               goto fail;
+               }
+       }
+
+       return 0;
+
+fail:
+       return err;
+}
+
+static int mtk_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+                                struct device_node *np_config,
+                                struct pinctrl_map **map, unsigned *num_maps)
+{
+       struct device_node *np;
+       unsigned reserved_maps;
+       int ret;
+
+       *map = NULL;
+       *num_maps = 0;
+       reserved_maps = 0;
+
+       for_each_child_of_node(np_config, np) {
+               ret = mtk_pctrl_dt_subnode_to_map(pctldev, np, map,
+                               &reserved_maps, num_maps);
+               if (ret < 0) {
+                       pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int mtk_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctl->ngroups;
+}
+
+static const char *mtk_pctrl_get_group_name(struct pinctrl_dev *pctldev,
+                                             unsigned group)
+{
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctl->groups[group].name;
+}
+
+static int mtk_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
+                                     unsigned group,
+                                     const unsigned **pins,
+                                     unsigned *num_pins)
+{
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       *pins = (unsigned *)&pctl->groups[group].pin;
+       *num_pins = 1;
+
+       return 0;
+}
+
+static const struct pinctrl_ops mtk_pctrl_ops = {
+       .dt_node_to_map         = mtk_pctrl_dt_node_to_map,
+       .dt_free_map            = pinctrl_utils_dt_free_map,
+       .get_groups_count       = mtk_pctrl_get_groups_count,
+       .get_group_name         = mtk_pctrl_get_group_name,
+       .get_group_pins         = mtk_pctrl_get_group_pins,
+};
+
+static int mtk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
+{
+       return ARRAY_SIZE(mtk_gpio_functions);
+}
+
+static const char *mtk_pmx_get_func_name(struct pinctrl_dev *pctldev,
+                                          unsigned selector)
+{
+       return mtk_gpio_functions[selector];
+}
+
+static int mtk_pmx_get_func_groups(struct pinctrl_dev *pctldev,
+                                    unsigned function,
+                                    const char * const **groups,
+                                    unsigned * const num_groups)
+{
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       *groups = pctl->grp_names;
+       *num_groups = pctl->ngroups;
+
+       return 0;
+}
+
+static int mtk_pmx_set_mode(struct pinctrl_dev *pctldev,
+               unsigned long pin, unsigned long mode)
+{
+       unsigned int reg_addr;
+       unsigned char bit;
+       unsigned int val;
+       unsigned int mask = (1L << GPIO_MODE_BITS) - 1;
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       reg_addr = ((pin / MAX_GPIO_MODE_PER_REG) << pctl->devdata->port_shf)
+                       + pctl->devdata->pinmux_offset;
+
+       bit = pin % MAX_GPIO_MODE_PER_REG;
+       mask <<= (GPIO_MODE_BITS * bit);
+       val = (mode << (GPIO_MODE_BITS * bit));
+       return regmap_update_bits(mtk_get_regmap(pctl, pin),
+                       reg_addr, mask, val);
+}
+
+static const struct mtk_desc_pin *
+mtk_find_pin_by_eint_num(struct mtk_pinctrl *pctl, unsigned int eint_num)
+{
+       int i;
+       const struct mtk_desc_pin *pin;
+
+       for (i = 0; i < pctl->devdata->npins; i++) {
+               pin = pctl->devdata->pins + i;
+               if (pin->eint.eintnum == eint_num)
+                       return pin;
+       }
+
+       return NULL;
+}
+
+static int mtk_pmx_set_mux(struct pinctrl_dev *pctldev,
+                           unsigned function,
+                           unsigned group)
+{
+       bool ret;
+       const struct mtk_desc_function *desc;
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct mtk_pinctrl_group *g = pctl->groups + group;
+
+       ret = mtk_pctrl_is_function_valid(pctl, g->pin, function);
+       if (!ret) {
+               dev_err(pctl->dev, "invaild function %d on group %d .\n",
+                               function, group);
+               return -EINVAL;
+       }
+
+       desc = mtk_pctrl_find_function_by_pin(pctl, g->pin, function);
+       if (!desc)
+               return -EINVAL;
+       mtk_pmx_set_mode(pctldev, g->pin, desc->muxval);
+       return 0;
+}
+
+static const struct pinmux_ops mtk_pmx_ops = {
+       .get_functions_count    = mtk_pmx_get_funcs_cnt,
+       .get_function_name      = mtk_pmx_get_func_name,
+       .get_function_groups    = mtk_pmx_get_func_groups,
+       .set_mux                = mtk_pmx_set_mux,
+       .gpio_set_direction     = mtk_pmx_gpio_set_direction,
+};
+
+static int mtk_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void mtk_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       pinctrl_free_gpio(chip->base + offset);
+}
+
+static int mtk_gpio_direction_input(struct gpio_chip *chip,
+                                       unsigned offset)
+{
+       return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int mtk_gpio_direction_output(struct gpio_chip *chip,
+                                       unsigned offset, int value)
+{
+       mtk_gpio_set(chip, offset, value);
+       return pinctrl_gpio_direction_output(chip->base + offset);
+}
+
+static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+       unsigned int reg_addr;
+       unsigned int bit;
+       unsigned int read_val = 0;
+
+       struct mtk_pinctrl *pctl = dev_get_drvdata(chip->dev);
+
+       reg_addr =  mtk_get_port(pctl, offset) + pctl->devdata->dir_offset;
+       bit = BIT(offset & 0xf);
+       regmap_read(pctl->regmap1, reg_addr, &read_val);
+       return !!(read_val & bit);
+}
+
+static int mtk_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       unsigned int reg_addr;
+       unsigned int bit;
+       unsigned int read_val = 0;
+       struct mtk_pinctrl *pctl = dev_get_drvdata(chip->dev);
+
+       if (mtk_gpio_get_direction(chip, offset))
+               reg_addr = mtk_get_port(pctl, offset) +
+                       pctl->devdata->dout_offset;
+       else
+               reg_addr = mtk_get_port(pctl, offset) +
+                       pctl->devdata->din_offset;
+
+       bit = BIT(offset & 0xf);
+       regmap_read(pctl->regmap1, reg_addr, &read_val);
+       return !!(read_val & bit);
+}
+
+static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       const struct mtk_desc_pin *pin;
+       struct mtk_pinctrl *pctl = dev_get_drvdata(chip->dev);
+       int irq;
+
+       pin = pctl->devdata->pins + offset;
+       if (pin->eint.eintnum == NO_EINT_SUPPORT)
+               return -EINVAL;
+
+       irq = irq_find_mapping(pctl->domain, pin->eint.eintnum);
+       if (!irq)
+               return -EINVAL;
+
+       return irq;
+}
+
+static int mtk_pinctrl_irq_request_resources(struct irq_data *d)
+{
+       struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
+       const struct mtk_desc_pin *pin;
+       int ret;
+
+       pin = mtk_find_pin_by_eint_num(pctl, d->hwirq);
+
+       if (!pin) {
+               dev_err(pctl->dev, "Can not find pin\n");
+               return -EINVAL;
+       }
+
+       ret = gpiochip_lock_as_irq(pctl->chip, pin->pin.number);
+       if (ret) {
+               dev_err(pctl->dev, "unable to lock HW IRQ %lu for IRQ\n",
+                       irqd_to_hwirq(d));
+               return ret;
+       }
+
+       /* set mux to INT mode */
+       mtk_pmx_set_mode(pctl->pctl_dev, pin->pin.number, pin->eint.eintmux);
+
+       return 0;
+}
+
+static void mtk_pinctrl_irq_release_resources(struct irq_data *d)
+{
+       struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
+       const struct mtk_desc_pin *pin;
+
+       pin = mtk_find_pin_by_eint_num(pctl, d->hwirq);
+
+       if (!pin) {
+               dev_err(pctl->dev, "Can not find pin\n");
+               return;
+       }
+
+       gpiochip_unlock_as_irq(pctl->chip, pin->pin.number);
+}
+
+static void __iomem *mtk_eint_get_offset(struct mtk_pinctrl *pctl,
+       unsigned int eint_num, unsigned int offset)
+{
+       unsigned int eint_base = 0;
+       void __iomem *reg;
+
+       if (eint_num >= pctl->devdata->ap_num)
+               eint_base = pctl->devdata->ap_num;
+
+       reg = pctl->eint_reg_base + offset + ((eint_num - eint_base) / 32) * 4;
+
+       return reg;
+}
+
+/*
+ * mtk_can_en_debounce: Check the EINT number is able to enable debounce or not
+ * @eint_num: the EINT number to setmtk_pinctrl
+ */
+static unsigned int mtk_eint_can_en_debounce(struct mtk_pinctrl *pctl,
+       unsigned int eint_num)
+{
+       unsigned int sens;
+       unsigned int bit = BIT(eint_num % 32);
+       const struct mtk_eint_offsets *eint_offsets =
+               &pctl->devdata->eint_offsets;
+
+       void __iomem *reg = mtk_eint_get_offset(pctl, eint_num,
+                       eint_offsets->sens);
+
+       if (readl(reg) & bit)
+               sens = MT_LEVEL_SENSITIVE;
+       else
+               sens = MT_EDGE_SENSITIVE;
+
+       if ((eint_num < pctl->devdata->db_cnt) && (sens != MT_EDGE_SENSITIVE))
+               return 1;
+       else
+               return 0;
+}
+
+/*
+ * mtk_eint_get_mask: To get the eint mask
+ * @eint_num: the EINT number to get
+ */
+static unsigned int mtk_eint_get_mask(struct mtk_pinctrl *pctl,
+       unsigned int eint_num)
+{
+       unsigned int bit = BIT(eint_num % 32);
+       const struct mtk_eint_offsets *eint_offsets =
+               &pctl->devdata->eint_offsets;
+
+       void __iomem *reg = mtk_eint_get_offset(pctl, eint_num,
+                       eint_offsets->mask);
+
+       return !!(readl(reg) & bit);
+}
+
+static int mtk_eint_flip_edge(struct mtk_pinctrl *pctl, int hwirq)
+{
+       int start_level, curr_level;
+       unsigned int reg_offset;
+       const struct mtk_eint_offsets *eint_offsets = &(pctl->devdata->eint_offsets);
+       u32 mask = 1 << (hwirq & 0x1f);
+       u32 port = (hwirq >> 5) & eint_offsets->port_mask;
+       void __iomem *reg = pctl->eint_reg_base + (port << 2);
+       const struct mtk_desc_pin *pin;
+
+       pin = mtk_find_pin_by_eint_num(pctl, hwirq);
+       curr_level = mtk_gpio_get(pctl->chip, pin->pin.number);
+       do {
+               start_level = curr_level;
+               if (start_level)
+                       reg_offset = eint_offsets->pol_clr;
+               else
+                       reg_offset = eint_offsets->pol_set;
+               writel(mask, reg + reg_offset);
+
+               curr_level = mtk_gpio_get(pctl->chip, pin->pin.number);
+       } while (start_level != curr_level);
+
+       return start_level;
+}
+
+static void mtk_eint_mask(struct irq_data *d)
+{
+       struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
+       const struct mtk_eint_offsets *eint_offsets =
+                       &pctl->devdata->eint_offsets;
+       u32 mask = BIT(d->hwirq & 0x1f);
+       void __iomem *reg = mtk_eint_get_offset(pctl, d->hwirq,
+                       eint_offsets->mask_set);
+
+       writel(mask, reg);
+}
+
+static void mtk_eint_unmask(struct irq_data *d)
+{
+       struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
+       const struct mtk_eint_offsets *eint_offsets =
+               &pctl->devdata->eint_offsets;
+       u32 mask = BIT(d->hwirq & 0x1f);
+       void __iomem *reg = mtk_eint_get_offset(pctl, d->hwirq,
+                       eint_offsets->mask_clr);
+
+       writel(mask, reg);
+
+       if (pctl->eint_dual_edges[d->hwirq])
+               mtk_eint_flip_edge(pctl, d->hwirq);
+}
+
+static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
+       unsigned debounce)
+{
+       struct mtk_pinctrl *pctl = dev_get_drvdata(chip->dev);
+       int eint_num, virq, eint_offset;
+       unsigned int set_offset, bit, clr_bit, clr_offset, rst, i, unmask, dbnc;
+       static const unsigned int dbnc_arr[] = {0 , 1, 16, 32, 64, 128, 256};
+       const struct mtk_desc_pin *pin;
+       struct irq_data *d;
+
+       pin = pctl->devdata->pins + offset;
+       if (pin->eint.eintnum == NO_EINT_SUPPORT)
+               return -EINVAL;
+
+       eint_num = pin->eint.eintnum;
+       virq = irq_find_mapping(pctl->domain, eint_num);
+       eint_offset = (eint_num % 4) * 8;
+       d = irq_get_irq_data(virq);
+
+       set_offset = (eint_num / 4) * 4 + pctl->devdata->eint_offsets.dbnc_set;
+       clr_offset = (eint_num / 4) * 4 + pctl->devdata->eint_offsets.dbnc_clr;
+       if (!mtk_eint_can_en_debounce(pctl, eint_num))
+               return -ENOSYS;
+
+       dbnc = ARRAY_SIZE(dbnc_arr);
+       for (i = 0; i < ARRAY_SIZE(dbnc_arr); i++) {
+               if (debounce <= dbnc_arr[i]) {
+                       dbnc = i;
+                       break;
+               }
+       }
+
+       if (!mtk_eint_get_mask(pctl, eint_num)) {
+               mtk_eint_mask(d);
+               unmask = 1;
+       }
+
+       clr_bit = 0xff << eint_offset;
+       writel(clr_bit, pctl->eint_reg_base + clr_offset);
+
+       bit = ((dbnc << EINT_DBNC_SET_DBNC_BITS) | EINT_DBNC_SET_EN) <<
+               eint_offset;
+       rst = EINT_DBNC_RST_BIT << eint_offset;
+       writel(rst | bit, pctl->eint_reg_base + set_offset);
+
+       /* Delay a while (more than 2T) to wait for hw debounce counter reset
+       work correctly */
+       udelay(1);
+       if (unmask == 1)
+               mtk_eint_unmask(d);
+
+       return 0;
+}
+
+static struct gpio_chip mtk_gpio_chip = {
+       .owner                  = THIS_MODULE,
+       .request                = mtk_gpio_request,
+       .free                   = mtk_gpio_free,
+       .direction_input        = mtk_gpio_direction_input,
+       .direction_output       = mtk_gpio_direction_output,
+       .get                    = mtk_gpio_get,
+       .set                    = mtk_gpio_set,
+       .to_irq                 = mtk_gpio_to_irq,
+       .set_debounce           = mtk_gpio_set_debounce,
+       .of_gpio_n_cells        = 2,
+};
+
+static int mtk_eint_set_type(struct irq_data *d,
+                                     unsigned int type)
+{
+       struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
+       const struct mtk_eint_offsets *eint_offsets =
+               &pctl->devdata->eint_offsets;
+       u32 mask = BIT(d->hwirq & 0x1f);
+       void __iomem *reg;
+
+       if (((type & IRQ_TYPE_EDGE_BOTH) && (type & IRQ_TYPE_LEVEL_MASK)) ||
+               ((type & IRQ_TYPE_LEVEL_MASK) == IRQ_TYPE_LEVEL_MASK)) {
+               dev_err(pctl->dev, "Can't configure IRQ%d (EINT%lu) for type 0x%X\n",
+                       d->irq, d->hwirq, type);
+               return -EINVAL;
+       }
+
+       if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+               pctl->eint_dual_edges[d->hwirq] = 1;
+       else
+               pctl->eint_dual_edges[d->hwirq] = 0;
+
+       if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) {
+               reg = mtk_eint_get_offset(pctl, d->hwirq,
+                       eint_offsets->pol_clr);
+               writel(mask, reg);
+       } else {
+               reg = mtk_eint_get_offset(pctl, d->hwirq,
+                       eint_offsets->pol_set);
+               writel(mask, reg);
+       }
+
+       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
+               reg = mtk_eint_get_offset(pctl, d->hwirq,
+                       eint_offsets->sens_clr);
+               writel(mask, reg);
+       } else {
+               reg = mtk_eint_get_offset(pctl, d->hwirq,
+                       eint_offsets->sens_set);
+               writel(mask, reg);
+       }
+
+       if (pctl->eint_dual_edges[d->hwirq])
+               mtk_eint_flip_edge(pctl, d->hwirq);
+
+       return 0;
+}
+
+static void mtk_eint_ack(struct irq_data *d)
+{
+       struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
+       const struct mtk_eint_offsets *eint_offsets =
+               &pctl->devdata->eint_offsets;
+       u32 mask = BIT(d->hwirq & 0x1f);
+       void __iomem *reg = mtk_eint_get_offset(pctl, d->hwirq,
+                       eint_offsets->ack);
+
+       writel(mask, reg);
+}
+
+static struct irq_chip mtk_pinctrl_irq_chip = {
+       .name = "mt-eint",
+       .irq_mask = mtk_eint_mask,
+       .irq_unmask = mtk_eint_unmask,
+       .irq_ack = mtk_eint_ack,
+       .irq_set_type = mtk_eint_set_type,
+       .irq_request_resources = mtk_pinctrl_irq_request_resources,
+       .irq_release_resources = mtk_pinctrl_irq_release_resources,
+};
+
+static unsigned int mtk_eint_init(struct mtk_pinctrl *pctl)
+{
+       const struct mtk_eint_offsets *eint_offsets =
+               &pctl->devdata->eint_offsets;
+       void __iomem *reg = pctl->eint_reg_base + eint_offsets->dom_en;
+       unsigned int i;
+
+       for (i = 0; i < pctl->devdata->ap_num; i += 32) {
+               writel(0xffffffff, reg);
+               reg += 4;
+       }
+       return 0;
+}
+
+static inline void
+mtk_eint_debounce_process(struct mtk_pinctrl *pctl, int index)
+{
+       unsigned int rst, ctrl_offset;
+       unsigned int bit, dbnc;
+       const struct mtk_eint_offsets *eint_offsets =
+               &pctl->devdata->eint_offsets;
+
+       ctrl_offset = (index / 4) * 4 + eint_offsets->dbnc_ctrl;
+       dbnc = readl(pctl->eint_reg_base + ctrl_offset);
+       bit = EINT_DBNC_SET_EN << ((index % 4) * 8);
+       if ((bit & dbnc) > 0) {
+               ctrl_offset = (index / 4) * 4 + eint_offsets->dbnc_set;
+               rst = EINT_DBNC_RST_BIT << ((index % 4) * 8);
+               writel(rst, pctl->eint_reg_base + ctrl_offset);
+       }
+}
+
+static void mtk_eint_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_get_chip(irq);
+       struct mtk_pinctrl *pctl = irq_get_handler_data(irq);
+       unsigned int status, eint_num;
+       int offset, index, virq;
+       const struct mtk_eint_offsets *eint_offsets =
+               &pctl->devdata->eint_offsets;
+       void __iomem *reg =  mtk_eint_get_offset(pctl, 0, eint_offsets->stat);
+       int dual_edges, start_level, curr_level;
+       const struct mtk_desc_pin *pin;
+
+       chained_irq_enter(chip, desc);
+       for (eint_num = 0; eint_num < pctl->devdata->ap_num; eint_num += 32) {
+               status = readl(reg);
+               reg += 4;
+               while (status) {
+                       offset = __ffs(status);
+                       index = eint_num + offset;
+                       virq = irq_find_mapping(pctl->domain, index);
+                       status &= ~BIT(offset);
+
+                       dual_edges = pctl->eint_dual_edges[index];
+                       if (dual_edges) {
+                               /* Clear soft-irq in case we raised it
+                                  last time */
+                               writel(BIT(offset), reg - eint_offsets->stat +
+                                       eint_offsets->soft_clr);
+
+                               pin = mtk_find_pin_by_eint_num(pctl, index);
+                               start_level = mtk_gpio_get(pctl->chip,
+                                                          pin->pin.number);
+                       }
+
+                       generic_handle_irq(virq);
+
+                       if (dual_edges) {
+                               curr_level = mtk_eint_flip_edge(pctl, index);
+
+                               /* If level changed, we might lost one edge
+                                  interrupt, raised it through soft-irq */
+                               if (start_level != curr_level)
+                                       writel(BIT(offset), reg -
+                                               eint_offsets->stat +
+                                               eint_offsets->soft_set);
+                       }
+
+                       if (index < pctl->devdata->db_cnt)
+                               mtk_eint_debounce_process(pctl , index);
+               }
+       }
+       chained_irq_exit(chip, desc);
+}
+
+static int mtk_pctrl_build_state(struct platform_device *pdev)
+{
+       struct mtk_pinctrl *pctl = platform_get_drvdata(pdev);
+       int i;
+
+       pctl->ngroups = pctl->devdata->npins;
+
+       /* Allocate groups */
+       pctl->groups = devm_kcalloc(&pdev->dev, pctl->ngroups,
+                                   sizeof(*pctl->groups), GFP_KERNEL);
+       if (!pctl->groups)
+               return -ENOMEM;
+
+       /* We assume that one pin is one group, use pin name as group name. */
+       pctl->grp_names = devm_kcalloc(&pdev->dev, pctl->ngroups,
+                                      sizeof(*pctl->grp_names), GFP_KERNEL);
+       if (!pctl->grp_names)
+               return -ENOMEM;
+
+       for (i = 0; i < pctl->devdata->npins; i++) {
+               const struct mtk_desc_pin *pin = pctl->devdata->pins + i;
+               struct mtk_pinctrl_group *group = pctl->groups + i;
+
+               group->name = pin->pin.name;
+               group->pin = pin->pin.number;
+
+               pctl->grp_names[i] = pin->pin.name;
+       }
+
+       return 0;
+}
+
+static struct pinctrl_desc mtk_pctrl_desc = {
+       .confops        = &mtk_pconf_ops,
+       .pctlops        = &mtk_pctrl_ops,
+       .pmxops         = &mtk_pmx_ops,
+};
+
+int mtk_pctrl_init(struct platform_device *pdev,
+               const struct mtk_pinctrl_devdata *data)
+{
+       struct pinctrl_pin_desc *pins;
+       struct mtk_pinctrl *pctl;
+       struct device_node *np = pdev->dev.of_node, *node;
+       struct property *prop;
+       struct resource *res;
+       int i, ret, irq;
+
+       pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+       if (!pctl)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, pctl);
+
+       prop = of_find_property(np, "pins-are-numbered", NULL);
+       if (!prop) {
+               dev_err(&pdev->dev, "only support pins-are-numbered format\n");
+               return -EINVAL;
+       }
+
+       node = of_parse_phandle(np, "mediatek,pctl-regmap", 0);
+       if (node) {
+               pctl->regmap1 = syscon_node_to_regmap(node);
+               if (IS_ERR(pctl->regmap1))
+                       return PTR_ERR(pctl->regmap1);
+       }
+
+       /* Only 8135 has two base addr, other SoCs have only one. */
+       node = of_parse_phandle(np, "mediatek,pctl-regmap", 1);
+       if (node) {
+               pctl->regmap2 = syscon_node_to_regmap(node);
+               if (IS_ERR(pctl->regmap2))
+                       return PTR_ERR(pctl->regmap2);
+       }
+
+       pctl->devdata = data;
+       ret = mtk_pctrl_build_state(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "build state failed: %d\n", ret);
+               return -EINVAL;
+       }
+
+       pins = devm_kcalloc(&pdev->dev, pctl->devdata->npins, sizeof(*pins),
+                           GFP_KERNEL);
+       if (!pins)
+               return -ENOMEM;
+
+       for (i = 0; i < pctl->devdata->npins; i++)
+               pins[i] = pctl->devdata->pins[i].pin;
+       mtk_pctrl_desc.name = dev_name(&pdev->dev);
+       mtk_pctrl_desc.owner = THIS_MODULE;
+       mtk_pctrl_desc.pins = pins;
+       mtk_pctrl_desc.npins = pctl->devdata->npins;
+       pctl->dev = &pdev->dev;
+       pctl->pctl_dev = pinctrl_register(&mtk_pctrl_desc, &pdev->dev, pctl);
+       if (!pctl->pctl_dev) {
+               dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
+               return -EINVAL;
+       }
+
+       pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL);
+       if (!pctl->chip) {
+               ret = -ENOMEM;
+               goto pctrl_error;
+       }
+
+       pctl->chip = &mtk_gpio_chip;
+       pctl->chip->ngpio = pctl->devdata->npins;
+       pctl->chip->label = dev_name(&pdev->dev);
+       pctl->chip->dev = &pdev->dev;
+       pctl->chip->base = 0;
+
+       ret = gpiochip_add(pctl->chip);
+       if (ret) {
+               ret = -EINVAL;
+               goto pctrl_error;
+       }
+
+       /* Register the GPIO to pin mappings. */
+       ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev),
+                       0, 0, pctl->devdata->npins);
+       if (ret) {
+               ret = -EINVAL;
+               goto chip_error;
+       }
+
+       /* Get EINT register base from dts. */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "Unable to get Pinctrl resource\n");
+               ret = -EINVAL;
+               goto chip_error;
+       }
+
+       pctl->eint_reg_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pctl->eint_reg_base)) {
+               ret = -EINVAL;
+               goto chip_error;
+       }
+
+       pctl->eint_dual_edges = devm_kcalloc(&pdev->dev, pctl->devdata->ap_num,
+                                            sizeof(int), GFP_KERNEL);
+       if (!pctl->eint_dual_edges) {
+               ret = -ENOMEM;
+               goto chip_error;
+       }
+
+       irq = irq_of_parse_and_map(np, 0);
+       if (!irq) {
+               dev_err(&pdev->dev, "couldn't parse and map irq\n");
+               ret = -EINVAL;
+               goto chip_error;
+       }
+
+       pctl->domain = irq_domain_add_linear(np,
+               pctl->devdata->ap_num, &irq_domain_simple_ops, NULL);
+       if (!pctl->domain) {
+               dev_err(&pdev->dev, "Couldn't register IRQ domain\n");
+               ret = -ENOMEM;
+               goto chip_error;
+       }
+
+       mtk_eint_init(pctl);
+       for (i = 0; i < pctl->devdata->ap_num; i++) {
+               int virq = irq_create_mapping(pctl->domain, i);
+
+               irq_set_chip_and_handler(virq, &mtk_pinctrl_irq_chip,
+                       handle_level_irq);
+               irq_set_chip_data(virq, pctl);
+               set_irq_flags(virq, IRQF_VALID);
+       };
+
+       irq_set_chained_handler(irq, mtk_eint_irq_handler);
+       irq_set_handler_data(irq, pctl);
+       set_irq_flags(irq, IRQF_VALID);
+       return 0;
+
+chip_error:
+       gpiochip_remove(pctl->chip);
+pctrl_error:
+       pinctrl_unregister(pctl->pctl_dev);
+       return ret;
+}
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MediaTek Pinctrl Driver");
+MODULE_AUTHOR("Hongzhou Yang <hongzhou.yang@mediatek.com>");
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
new file mode 100644 (file)
index 0000000..375771d
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Hongzhou.Yang <hongzhou.yang@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 __PINCTRL_MTK_COMMON_H
+#define __PINCTRL_MTK_COMMON_H
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/regmap.h>
+
+#define NO_EINT_SUPPORT    255
+#define MTK_CHIP_TYPE_BASE     0
+#define MTK_CHIP_TYPE_PMIC     1
+#define MT_EDGE_SENSITIVE           0
+#define MT_LEVEL_SENSITIVE          1
+#define EINT_DBNC_SET_DBNC_BITS     4
+#define EINT_DBNC_RST_BIT           (0x1 << 1)
+#define EINT_DBNC_SET_EN            (0x1 << 0)
+
+struct mtk_desc_function {
+       const char *name;
+       unsigned char muxval;
+};
+
+struct mtk_desc_eint {
+       unsigned char eintmux;
+       unsigned char eintnum;
+};
+
+struct mtk_desc_pin {
+       struct pinctrl_pin_desc pin;
+       const char *chip;
+       const struct mtk_desc_eint eint;
+       const struct mtk_desc_function  *functions;
+};
+
+#define MTK_PIN(_pin, _pad, _chip, _eint, ...)         \
+       {                                                       \
+               .pin = _pin,                                    \
+               .chip = _chip,                                  \
+               .eint = _eint,                                  \
+               .functions = (struct mtk_desc_function[]){      \
+                       __VA_ARGS__, { } },                     \
+       }
+
+#define MTK_EINT_FUNCTION(_eintmux, _eintnum)                          \
+       {                                                       \
+               .eintmux = _eintmux,                                    \
+               .eintnum = _eintnum,                                    \
+       }
+
+#define MTK_FUNCTION(_val, _name)                              \
+       {                                                       \
+               .muxval = _val,                                 \
+               .name = _name,                                  \
+       }
+
+#define SET_ADDR(x, y)  (x + (y->devdata->port_align))
+#define CLR_ADDR(x, y)  (x + (y->devdata->port_align << 1))
+
+struct mtk_pinctrl_group {
+       const char      *name;
+       unsigned long   config;
+       unsigned        pin;
+};
+
+/**
+ * struct mtk_drv_group_desc - Provide driving group data.
+ * @max_drv: The maximum current of this group.
+ * @min_drv: The minimum current of this group.
+ * @low_bit: The lowest bit of this group.
+ * @high_bit: The highest bit of this group.
+ * @step: The step current of this group.
+ */
+struct mtk_drv_group_desc {
+       unsigned char min_drv;
+       unsigned char max_drv;
+       unsigned char low_bit;
+       unsigned char high_bit;
+       unsigned char step;
+};
+
+#define MTK_DRV_GRP(_min, _max, _low, _high, _step)    \
+       {       \
+               .min_drv = _min,        \
+               .max_drv = _max,        \
+               .low_bit = _low,        \
+               .high_bit = _high,      \
+               .step = _step,          \
+       }
+
+/**
+ * struct mtk_pin_drv_grp - Provide each pin driving info.
+ * @pin: The pin number.
+ * @offset: The offset of driving register for this pin.
+ * @bit: The bit of driving register for this pin.
+ * @grp: The group for this pin belongs to.
+ */
+struct mtk_pin_drv_grp {
+       unsigned int pin;
+       unsigned int offset;
+       unsigned char bit;
+       unsigned char grp;
+};
+
+#define MTK_PIN_DRV_GRP(_pin, _offset, _bit, _grp)     \
+       {       \
+               .pin = _pin,    \
+               .offset = _offset,      \
+               .bit = _bit,    \
+               .grp = _grp,    \
+       }
+
+struct mtk_eint_offsets {
+       const char *name;
+       unsigned int  stat;
+       unsigned int  ack;
+       unsigned int  mask;
+       unsigned int  mask_set;
+       unsigned int  mask_clr;
+       unsigned int  sens;
+       unsigned int  sens_set;
+       unsigned int  sens_clr;
+       unsigned int  soft;
+       unsigned int  soft_set;
+       unsigned int  soft_clr;
+       unsigned int  pol;
+       unsigned int  pol_set;
+       unsigned int  pol_clr;
+       unsigned int  dom_en;
+       unsigned int  dbnc_ctrl;
+       unsigned int  dbnc_set;
+       unsigned int  dbnc_clr;
+       u8  port_mask;
+       u8  ports;
+};
+
+/**
+ * struct mtk_pinctrl_devdata - Provide HW GPIO related data.
+ * @pins: An array describing all pins the pin controller affects.
+ * @npins: The number of entries in @pins.
+ *
+ * @grp_desc: The driving group info.
+ * @pin_drv_grp: The driving group for all pins.
+ * @spec_pull_set: Each SoC may have special pins for pull up/down setting,
+ *  these pins' pull setting are very different, they have separate pull
+ *  up/down bit, R0 and R1 resistor bit, so they need special pull setting.
+ *  If special setting is success, this should return 0, otherwise it should
+ *  return non-zero value.
+ * @spec_ies_smt_set: Some pins are irregular, their input enable and smt
+ * control register are discontinuous, but they are mapping together. That
+ * means when user set smt, input enable is set at the same time. So they
+ * also need special control. If special control is success, this should
+ * return 0, otherwise return non-zero value.
+ *
+ * @dir_offset: The direction register offset.
+ * @pullen_offset: The pull-up/pull-down enable register offset.
+ * @pinmux_offset: The pinmux register offset.
+ *
+ * @type1_start: Some chips have two base addresses for pull select register,
+ *  that means some pins use the first address and others use the second. This
+ *  member record the start of pin number to use the second address.
+ * @type1_end: The end of pin number to use the second address.
+ *
+ * @port_shf: The shift between two registers.
+ * @port_mask: The mask of register.
+ * @port_align: Provide clear register and set register step.
+ */
+struct mtk_pinctrl_devdata {
+       const struct mtk_desc_pin       *pins;
+       unsigned int                            npins;
+       const struct mtk_drv_group_desc *grp_desc;
+       unsigned int    n_grp_cls;
+       const struct mtk_pin_drv_grp    *pin_drv_grp;
+       unsigned int    n_pin_drv_grps;
+       int (*spec_pull_set)(struct regmap *reg, unsigned int pin,
+                       unsigned char align, bool isup, unsigned int arg);
+       int (*spec_ies_smt_set)(struct regmap *reg, unsigned int pin,
+                       unsigned char align, int value);
+       unsigned int dir_offset;
+       unsigned int ies_offset;
+       unsigned int smt_offset;
+       unsigned int pullen_offset;
+       unsigned int pullsel_offset;
+       unsigned int drv_offset;
+       unsigned int invser_offset;
+       unsigned int dout_offset;
+       unsigned int din_offset;
+       unsigned int pinmux_offset;
+       unsigned short type1_start;
+       unsigned short type1_end;
+       unsigned char  port_shf;
+       unsigned char  port_mask;
+       unsigned char  port_align;
+       unsigned char   chip_type;
+       struct mtk_eint_offsets eint_offsets;
+       unsigned int    ap_num;
+       unsigned int    db_cnt;
+};
+
+struct mtk_pinctrl {
+       struct regmap   *regmap1;
+       struct regmap   *regmap2;
+       struct device           *dev;
+       struct gpio_chip        *chip;
+       struct mtk_pinctrl_group        *groups;
+       unsigned                        ngroups;
+       const char          **grp_names;
+       struct pinctrl_dev      *pctl_dev;
+       const struct mtk_pinctrl_devdata  *devdata;
+       void __iomem            *eint_reg_base;
+       struct irq_domain       *domain;
+       int                     *eint_dual_edges;
+};
+
+int mtk_pctrl_init(struct platform_device *pdev,
+               const struct mtk_pinctrl_devdata *data);
+
+#endif /* __PINCTRL_MTK_COMMON_H */
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt8135.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8135.h
new file mode 100644 (file)
index 0000000..e17aedb
--- /dev/null
@@ -0,0 +1,2114 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Hongzhou.Yang <hongzhou.yang@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 __PINCTRL_MTK_MT8135_H
+#define __PINCTRL_MTK_MT8135_H
+
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-mtk-common.h"
+
+static const struct mtk_desc_pin mtk_pins_mt8135[] = {
+       MTK_PIN(
+               PINCTRL_PIN(0, "MSDC0_DAT7"),
+               "D21", "mt8135",
+               MTK_EINT_FUNCTION(2, 49),
+               MTK_FUNCTION(0, "GPIO0"),
+               MTK_FUNCTION(1, "MSDC0_DAT7"),
+               MTK_FUNCTION(2, "EINT49"),
+               MTK_FUNCTION(3, "I2SOUT_DAT"),
+               MTK_FUNCTION(4, "DAC_DAT_OUT"),
+               MTK_FUNCTION(5, "PCM1_DO"),
+               MTK_FUNCTION(6, "SPI1_MO"),
+               MTK_FUNCTION(7, "NALE")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(1, "MSDC0_DAT6"),
+               "D22", "mt8135",
+               MTK_EINT_FUNCTION(2, 48),
+               MTK_FUNCTION(0, "GPIO1"),
+               MTK_FUNCTION(1, "MSDC0_DAT6"),
+               MTK_FUNCTION(2, "EINT48"),
+               MTK_FUNCTION(3, "I2SIN_WS"),
+               MTK_FUNCTION(4, "DAC_WS"),
+               MTK_FUNCTION(5, "PCM1_WS"),
+               MTK_FUNCTION(6, "SPI1_CSN"),
+               MTK_FUNCTION(7, "NCLE")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(2, "MSDC0_DAT5"),
+               "E22", "mt8135",
+               MTK_EINT_FUNCTION(2, 47),
+               MTK_FUNCTION(0, "GPIO2"),
+               MTK_FUNCTION(1, "MSDC0_DAT5"),
+               MTK_FUNCTION(2, "EINT47"),
+               MTK_FUNCTION(3, "I2SIN_CK"),
+               MTK_FUNCTION(4, "DAC_CK"),
+               MTK_FUNCTION(5, "PCM1_CK"),
+               MTK_FUNCTION(6, "SPI1_CLK"),
+               MTK_FUNCTION(7, "NLD4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(3, "MSDC0_DAT4"),
+               "F21", "mt8135",
+               MTK_EINT_FUNCTION(2, 46),
+               MTK_FUNCTION(0, "GPIO3"),
+               MTK_FUNCTION(1, "MSDC0_DAT4"),
+               MTK_FUNCTION(2, "EINT46"),
+               MTK_FUNCTION(3, "A_FUNC_CK"),
+               MTK_FUNCTION(6, "LSCE1B_2X"),
+               MTK_FUNCTION(7, "NLD5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(4, "MSDC0_CMD"),
+               "F20", "mt8135",
+               MTK_EINT_FUNCTION(2, 41),
+               MTK_FUNCTION(0, "GPIO4"),
+               MTK_FUNCTION(1, "MSDC0_CMD"),
+               MTK_FUNCTION(2, "EINT41"),
+               MTK_FUNCTION(3, "A_FUNC_DOUT[0]"),
+               MTK_FUNCTION(5, "USB_TEST_IO[0]"),
+               MTK_FUNCTION(6, "LRSTB_2X"),
+               MTK_FUNCTION(7, "NRNB")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(5, "MSDC0_CLK"),
+               "G18", "mt8135",
+               MTK_EINT_FUNCTION(2, 40),
+               MTK_FUNCTION(0, "GPIO5"),
+               MTK_FUNCTION(1, "MSDC0_CLK"),
+               MTK_FUNCTION(2, "EINT40"),
+               MTK_FUNCTION(3, "A_FUNC_DOUT[1]"),
+               MTK_FUNCTION(5, "USB_TEST_IO[1]"),
+               MTK_FUNCTION(6, "LPTE"),
+               MTK_FUNCTION(7, "NREB")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(6, "MSDC0_DAT3"),
+               "G21", "mt8135",
+               MTK_EINT_FUNCTION(2, 45),
+               MTK_FUNCTION(0, "GPIO6"),
+               MTK_FUNCTION(1, "MSDC0_DAT3"),
+               MTK_FUNCTION(2, "EINT45"),
+               MTK_FUNCTION(3, "A_FUNC_DOUT[2]"),
+               MTK_FUNCTION(5, "USB_TEST_IO[2]"),
+               MTK_FUNCTION(6, "LSCE0B_2X"),
+               MTK_FUNCTION(7, "NLD7")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(7, "MSDC0_DAT2"),
+               "E21", "mt8135",
+               MTK_EINT_FUNCTION(2, 44),
+               MTK_FUNCTION(0, "GPIO7"),
+               MTK_FUNCTION(1, "MSDC0_DAT2"),
+               MTK_FUNCTION(2, "EINT44"),
+               MTK_FUNCTION(3, "A_FUNC_DOUT[3]"),
+               MTK_FUNCTION(5, "USB_TEST_IO[3]"),
+               MTK_FUNCTION(6, "LSA0_2X"),
+               MTK_FUNCTION(7, "NLD14")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(8, "MSDC0_DAT1"),
+               "E23", "mt8135",
+               MTK_EINT_FUNCTION(2, 43),
+               MTK_FUNCTION(0, "GPIO8"),
+               MTK_FUNCTION(1, "MSDC0_DAT1"),
+               MTK_FUNCTION(2, "EINT43"),
+               MTK_FUNCTION(5, "USB_TEST_IO[4]"),
+               MTK_FUNCTION(6, "LSCK_2X"),
+               MTK_FUNCTION(7, "NLD11")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(9, "MSDC0_DAT0"),
+               "F22", "mt8135",
+               MTK_EINT_FUNCTION(2, 42),
+               MTK_FUNCTION(0, "GPIO9"),
+               MTK_FUNCTION(1, "MSDC0_DAT0"),
+               MTK_FUNCTION(2, "EINT42"),
+               MTK_FUNCTION(5, "USB_TEST_IO[5]"),
+               MTK_FUNCTION(6, "LSDA_2X")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(10, "NCEB0"),
+               "G20", "mt8135",
+               MTK_EINT_FUNCTION(2, 139),
+               MTK_FUNCTION(0, "GPIO10"),
+               MTK_FUNCTION(1, "NCEB0"),
+               MTK_FUNCTION(2, "EINT139"),
+               MTK_FUNCTION(7, "TESTA_OUT4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(11, "NCEB1"),
+               "L17", "mt8135",
+               MTK_EINT_FUNCTION(2, 140),
+               MTK_FUNCTION(0, "GPIO11"),
+               MTK_FUNCTION(1, "NCEB1"),
+               MTK_FUNCTION(2, "EINT140"),
+               MTK_FUNCTION(6, "USB_DRVVBUS"),
+               MTK_FUNCTION(7, "TESTA_OUT5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(12, "NRNB"),
+               "G19", "mt8135",
+               MTK_EINT_FUNCTION(2, 141),
+               MTK_FUNCTION(0, "GPIO12"),
+               MTK_FUNCTION(1, "NRNB"),
+               MTK_FUNCTION(2, "EINT141"),
+               MTK_FUNCTION(3, "A_FUNC_DOUT[4]"),
+               MTK_FUNCTION(7, "TESTA_OUT6")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(13, "NCLE"),
+               "J18", "mt8135",
+               MTK_EINT_FUNCTION(2, 142),
+               MTK_FUNCTION(0, "GPIO13"),
+               MTK_FUNCTION(1, "NCLE"),
+               MTK_FUNCTION(2, "EINT142"),
+               MTK_FUNCTION(3, "A_FUNC_DOUT[5]"),
+               MTK_FUNCTION(4, "CM2PDN_1X"),
+               MTK_FUNCTION(6, "NALE"),
+               MTK_FUNCTION(7, "TESTA_OUT7")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(14, "NALE"),
+               "J19", "mt8135",
+               MTK_EINT_FUNCTION(2, 143),
+               MTK_FUNCTION(0, "GPIO14"),
+               MTK_FUNCTION(1, "NALE"),
+               MTK_FUNCTION(2, "EINT143"),
+               MTK_FUNCTION(3, "A_FUNC_DOUT[6]"),
+               MTK_FUNCTION(4, "CM2MCLK_1X"),
+               MTK_FUNCTION(5, "IRDA_RXD"),
+               MTK_FUNCTION(6, "NCLE"),
+               MTK_FUNCTION(7, "TESTA_OUT8")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(15, "NREB"),
+               "L18", "mt8135",
+               MTK_EINT_FUNCTION(2, 144),
+               MTK_FUNCTION(0, "GPIO15"),
+               MTK_FUNCTION(1, "NREB"),
+               MTK_FUNCTION(2, "EINT144"),
+               MTK_FUNCTION(3, "A_FUNC_DOUT[7]"),
+               MTK_FUNCTION(4, "CM2RST_1X"),
+               MTK_FUNCTION(5, "IRDA_TXD"),
+               MTK_FUNCTION(7, "TESTA_OUT9")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(16, "NWEB"),
+               "J20", "mt8135",
+               MTK_EINT_FUNCTION(2, 145),
+               MTK_FUNCTION(0, "GPIO16"),
+               MTK_FUNCTION(1, "NWEB"),
+               MTK_FUNCTION(2, "EINT145"),
+               MTK_FUNCTION(3, "A_FUNC_DIN[0]"),
+               MTK_FUNCTION(4, "CM2PCLK_1X"),
+               MTK_FUNCTION(5, "IRDA_PDN"),
+               MTK_FUNCTION(7, "TESTA_OUT10")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(17, "NLD0"),
+               "K21", "mt8135",
+               MTK_EINT_FUNCTION(2, 146),
+               MTK_FUNCTION(0, "GPIO17"),
+               MTK_FUNCTION(1, "NLD0"),
+               MTK_FUNCTION(2, "EINT146"),
+               MTK_FUNCTION(3, "A_FUNC_DIN[1]"),
+               MTK_FUNCTION(4, "CM2DAT_1X[0]"),
+               MTK_FUNCTION(5, "I2SIN_CK"),
+               MTK_FUNCTION(6, "DAC_CK"),
+               MTK_FUNCTION(7, "TESTA_OUT11")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(18, "NLD1"),
+               "K22", "mt8135",
+               MTK_EINT_FUNCTION(2, 147),
+               MTK_FUNCTION(0, "GPIO18"),
+               MTK_FUNCTION(1, "NLD1"),
+               MTK_FUNCTION(2, "EINT147"),
+               MTK_FUNCTION(3, "A_FUNC_DIN[2]"),
+               MTK_FUNCTION(4, "CM2DAT_1X[1]"),
+               MTK_FUNCTION(5, "I2SIN_WS"),
+               MTK_FUNCTION(6, "DAC_WS"),
+               MTK_FUNCTION(7, "TESTA_OUT12")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(19, "NLD2"),
+               "J21", "mt8135",
+               MTK_EINT_FUNCTION(2, 148),
+               MTK_FUNCTION(0, "GPIO19"),
+               MTK_FUNCTION(1, "NLD2"),
+               MTK_FUNCTION(2, "EINT148"),
+               MTK_FUNCTION(3, "A_FUNC_DIN[3]"),
+               MTK_FUNCTION(4, "CM2DAT_1X[2]"),
+               MTK_FUNCTION(5, "I2SOUT_DAT"),
+               MTK_FUNCTION(6, "DAC_DAT_OUT"),
+               MTK_FUNCTION(7, "TESTA_OUT13")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(20, "NLD3"),
+               "J23", "mt8135",
+               MTK_EINT_FUNCTION(2, 149),
+               MTK_FUNCTION(0, "GPIO20"),
+               MTK_FUNCTION(1, "NLD3"),
+               MTK_FUNCTION(2, "EINT149"),
+               MTK_FUNCTION(3, "A_FUNC_DIN[4]"),
+               MTK_FUNCTION(4, "CM2DAT_1X[3]"),
+               MTK_FUNCTION(7, "TESTA_OUT14")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(21, "NLD4"),
+               "J22", "mt8135",
+               MTK_EINT_FUNCTION(2, 150),
+               MTK_FUNCTION(0, "GPIO21"),
+               MTK_FUNCTION(1, "NLD4"),
+               MTK_FUNCTION(2, "EINT150"),
+               MTK_FUNCTION(3, "A_FUNC_DIN[5]"),
+               MTK_FUNCTION(4, "CM2DAT_1X[4]"),
+               MTK_FUNCTION(7, "TESTA_OUT15")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(22, "NLD5"),
+               "H21", "mt8135",
+               MTK_EINT_FUNCTION(2, 151),
+               MTK_FUNCTION(0, "GPIO22"),
+               MTK_FUNCTION(1, "NLD5"),
+               MTK_FUNCTION(2, "EINT151"),
+               MTK_FUNCTION(3, "A_FUNC_DIN[6]"),
+               MTK_FUNCTION(4, "CM2DAT_1X[5]"),
+               MTK_FUNCTION(7, "TESTA_OUT16")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(23, "NLD6"),
+               "H22", "mt8135",
+               MTK_EINT_FUNCTION(2, 152),
+               MTK_FUNCTION(0, "GPIO23"),
+               MTK_FUNCTION(1, "NLD6"),
+               MTK_FUNCTION(2, "EINT152"),
+               MTK_FUNCTION(3, "A_FUNC_DIN[7]"),
+               MTK_FUNCTION(4, "CM2DAT_1X[6]"),
+               MTK_FUNCTION(7, "TESTA_OUT17")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(24, "NLD7"),
+               "H20", "mt8135",
+               MTK_EINT_FUNCTION(2, 153),
+               MTK_FUNCTION(0, "GPIO24"),
+               MTK_FUNCTION(1, "NLD7"),
+               MTK_FUNCTION(2, "EINT153"),
+               MTK_FUNCTION(3, "A_FUNC_DIN[8]"),
+               MTK_FUNCTION(4, "CM2DAT_1X[7]"),
+               MTK_FUNCTION(7, "TESTA_OUT18")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(25, "NLD8"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 154),
+               MTK_FUNCTION(0, "GPIO25"),
+               MTK_FUNCTION(1, "NLD8"),
+               MTK_FUNCTION(2, "EINT154"),
+               MTK_FUNCTION(4, "CM2DAT_1X[8]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(26, "NLD9"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 155),
+               MTK_FUNCTION(0, "GPIO26"),
+               MTK_FUNCTION(1, "NLD9"),
+               MTK_FUNCTION(2, "EINT155"),
+               MTK_FUNCTION(4, "CM2DAT_1X[9]"),
+               MTK_FUNCTION(5, "PWM1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(27, "NLD10"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 156),
+               MTK_FUNCTION(0, "GPIO27"),
+               MTK_FUNCTION(1, "NLD10"),
+               MTK_FUNCTION(2, "EINT156"),
+               MTK_FUNCTION(4, "CM2VSYNC_1X"),
+               MTK_FUNCTION(5, "PWM2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(28, "NLD11"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 157),
+               MTK_FUNCTION(0, "GPIO28"),
+               MTK_FUNCTION(1, "NLD11"),
+               MTK_FUNCTION(2, "EINT157"),
+               MTK_FUNCTION(4, "CM2HSYNC_1X"),
+               MTK_FUNCTION(5, "PWM3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(29, "NLD12"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 158),
+               MTK_FUNCTION(0, "GPIO29"),
+               MTK_FUNCTION(1, "NLD12"),
+               MTK_FUNCTION(2, "EINT158"),
+               MTK_FUNCTION(3, "I2SIN_CK"),
+               MTK_FUNCTION(4, "DAC_CK"),
+               MTK_FUNCTION(5, "PCM1_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(30, "NLD13"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 159),
+               MTK_FUNCTION(0, "GPIO30"),
+               MTK_FUNCTION(1, "NLD13"),
+               MTK_FUNCTION(2, "EINT159"),
+               MTK_FUNCTION(3, "I2SIN_WS"),
+               MTK_FUNCTION(4, "DAC_WS"),
+               MTK_FUNCTION(5, "PCM1_WS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(31, "NLD14"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 160),
+               MTK_FUNCTION(0, "GPIO31"),
+               MTK_FUNCTION(1, "NLD14"),
+               MTK_FUNCTION(2, "EINT160"),
+               MTK_FUNCTION(3, "I2SOUT_DAT"),
+               MTK_FUNCTION(4, "DAC_DAT_OUT"),
+               MTK_FUNCTION(5, "PCM1_DO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(32, "NLD15"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 161),
+               MTK_FUNCTION(0, "GPIO32"),
+               MTK_FUNCTION(1, "NLD15"),
+               MTK_FUNCTION(2, "EINT161"),
+               MTK_FUNCTION(3, "DISP_PWM"),
+               MTK_FUNCTION(4, "PWM4"),
+               MTK_FUNCTION(5, "PCM1_DI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(33, "MSDC0_RSTB"),
+               "G22", "mt8135",
+               MTK_EINT_FUNCTION(2, 50),
+               MTK_FUNCTION(0, "GPIO33"),
+               MTK_FUNCTION(1, "MSDC0_RSTB"),
+               MTK_FUNCTION(2, "EINT50"),
+               MTK_FUNCTION(3, "I2SIN_DAT"),
+               MTK_FUNCTION(5, "PCM1_DI"),
+               MTK_FUNCTION(6, "SPI1_MI"),
+               MTK_FUNCTION(7, "NLD10")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(34, "IDDIG"),
+               "N17", "mt8135",
+               MTK_EINT_FUNCTION(2, 34),
+               MTK_FUNCTION(0, "GPIO34"),
+               MTK_FUNCTION(1, "IDDIG"),
+               MTK_FUNCTION(2, "EINT34")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(35, "SCL3"),
+               "L19", "mt8135",
+               MTK_EINT_FUNCTION(2, 96),
+               MTK_FUNCTION(0, "GPIO35"),
+               MTK_FUNCTION(1, "SCL3"),
+               MTK_FUNCTION(2, "EINT96"),
+               MTK_FUNCTION(3, "CLKM6"),
+               MTK_FUNCTION(4, "PWM6")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(36, "SDA3"),
+               "L20", "mt8135",
+               MTK_EINT_FUNCTION(2, 97),
+               MTK_FUNCTION(0, "GPIO36"),
+               MTK_FUNCTION(1, "SDA3"),
+               MTK_FUNCTION(2, "EINT97")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(37, "AUD_CLK_MOSI"),
+               "L21", "mt8135",
+               MTK_EINT_FUNCTION(4, 19),
+               MTK_FUNCTION(0, "GPIO37"),
+               MTK_FUNCTION(1, "AUD_CLK"),
+               MTK_FUNCTION(2, "ADC_CK"),
+               MTK_FUNCTION(3, " HDMI_SDATA0"),
+               MTK_FUNCTION(4, "EINT19"),
+               MTK_FUNCTION(5, "USB_TEST_IO[6]"),
+               MTK_FUNCTION(7, "TESTA_OUT19")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(38, "AUD_DAT_MOSI"),
+               "L23", "mt8135",
+               MTK_EINT_FUNCTION(4, 21),
+               MTK_FUNCTION(0, "GPIO38"),
+               MTK_FUNCTION(1, "AUD_DAT_MOSI"),
+               MTK_FUNCTION(2, "ADC_WS"),
+               MTK_FUNCTION(3, "AUD_DAT_MISO"),
+               MTK_FUNCTION(4, "EINT21"),
+               MTK_FUNCTION(5, "USB_TEST_IO[7]"),
+               MTK_FUNCTION(7, "TESTA_OUT20")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(39, "AUD_DAT_MISO"),
+               "L22", "mt8135",
+               MTK_EINT_FUNCTION(4, 20),
+               MTK_FUNCTION(0, "GPIO39"),
+               MTK_FUNCTION(1, "AUD_DAT_MISO"),
+               MTK_FUNCTION(2, "ADC_DAT_IN"),
+               MTK_FUNCTION(3, "AUD_DAT_MOSI"),
+               MTK_FUNCTION(4, "EINT20"),
+               MTK_FUNCTION(5, "USB_TEST_IO[8]"),
+               MTK_FUNCTION(7, "TESTA_OUT21")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(40, "DAC_CLK"),
+               "P21", "mt8135",
+               MTK_EINT_FUNCTION(2, 22),
+               MTK_FUNCTION(0, "GPIO40"),
+               MTK_FUNCTION(1, "DAC_CK"),
+               MTK_FUNCTION(2, "EINT22"),
+               MTK_FUNCTION(3, " HDMI_SDATA1"),
+               MTK_FUNCTION(5, "USB_TEST_IO[9]"),
+               MTK_FUNCTION(7, "TESTA_OUT22")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(41, "DAC_WS"),
+               "N18", "mt8135",
+               MTK_EINT_FUNCTION(2, 24),
+               MTK_FUNCTION(0, "GPIO41"),
+               MTK_FUNCTION(1, "DAC_WS"),
+               MTK_FUNCTION(2, "EINT24"),
+               MTK_FUNCTION(3, " HDMI_SDATA2"),
+               MTK_FUNCTION(5, "USB_TEST_IO[10]"),
+               MTK_FUNCTION(7, "TESTA_OUT23")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(42, "DAC_DAT_OUT"),
+               "N22", "mt8135",
+               MTK_EINT_FUNCTION(2, 23),
+               MTK_FUNCTION(0, "GPIO42"),
+               MTK_FUNCTION(1, "DAC_DAT_OUT"),
+               MTK_FUNCTION(2, "EINT23"),
+               MTK_FUNCTION(3, " HDMI_SDATA3"),
+               MTK_FUNCTION(5, "USB_TEST_IO[11]"),
+               MTK_FUNCTION(7, "TESTA_OUT24")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(43, "PWRAP_SPI0_MO"),
+               "M22", "mt8135",
+               MTK_EINT_FUNCTION(2, 29),
+               MTK_FUNCTION(0, "GPIO43"),
+               MTK_FUNCTION(1, "PWRAP_SPIDI"),
+               MTK_FUNCTION(2, "EINT29")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(44, "PWRAP_SPI0_MI"),
+               "P23", "mt8135",
+               MTK_EINT_FUNCTION(2, 28),
+               MTK_FUNCTION(0, "GPIO44"),
+               MTK_FUNCTION(1, "PWRAP_SPIDO"),
+               MTK_FUNCTION(2, "EINT28")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(45, "PWRAP_SPI0_CSN"),
+               "M21", "mt8135",
+               MTK_EINT_FUNCTION(2, 27),
+               MTK_FUNCTION(0, "GPIO45"),
+               MTK_FUNCTION(1, "PWRAP_SPICS_B_I"),
+               MTK_FUNCTION(2, "EINT27")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(46, "PWRAP_SPI0_CLK"),
+               "P22", "mt8135",
+               MTK_EINT_FUNCTION(2, 26),
+               MTK_FUNCTION(0, "GPIO46"),
+               MTK_FUNCTION(1, "PWRAP_SPICK_I"),
+               MTK_FUNCTION(2, "EINT26")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(47, "PWRAP_EVENT"),
+               "M23", "mt8135",
+               MTK_EINT_FUNCTION(2, 25),
+               MTK_FUNCTION(0, "GPIO47"),
+               MTK_FUNCTION(1, "PWRAP_EVENT_IN"),
+               MTK_FUNCTION(2, "EINT25"),
+               MTK_FUNCTION(7, "TESTA_OUT2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(48, "RTC32K_CK"),
+               "N20", "mt8135",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO48"),
+               MTK_FUNCTION(1, "RTC32K_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(49, "WATCHDOG"),
+               "R22", "mt8135",
+               MTK_EINT_FUNCTION(2, 36),
+               MTK_FUNCTION(0, "GPIO49"),
+               MTK_FUNCTION(1, "WATCHDOG"),
+               MTK_FUNCTION(2, "EINT36")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(50, "SRCLKENA"),
+               "T22", "mt8135",
+               MTK_EINT_FUNCTION(2, 38),
+               MTK_FUNCTION(0, "GPIO50"),
+               MTK_FUNCTION(1, "SRCLKENA"),
+               MTK_FUNCTION(2, "EINT38")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(51, "SRCVOLTEN"),
+               "T23", "mt8135",
+               MTK_EINT_FUNCTION(2, 37),
+               MTK_FUNCTION(0, "GPIO51"),
+               MTK_FUNCTION(1, "SRCVOLTEN"),
+               MTK_FUNCTION(2, "EINT37")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(52, "EINT0"),
+               "T21", "mt8135",
+               MTK_EINT_FUNCTION(1, 0),
+               MTK_FUNCTION(0, "GPIO52"),
+               MTK_FUNCTION(1, "EINT0"),
+               MTK_FUNCTION(2, "PWM1"),
+               MTK_FUNCTION(3, "CLKM0"),
+               MTK_FUNCTION(4, " SPDIF_OUT"),
+               MTK_FUNCTION(5, "USB_TEST_IO[12]"),
+               MTK_FUNCTION(7, "USB_SCL")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(53, "URXD2"),
+               "R18", "mt8135",
+               MTK_EINT_FUNCTION(2, 83),
+               MTK_FUNCTION(0, "GPIO53"),
+               MTK_FUNCTION(1, "URXD2"),
+               MTK_FUNCTION(2, "EINT83"),
+               MTK_FUNCTION(4, " HDMI_LRCK"),
+               MTK_FUNCTION(5, "CLKM3"),
+               MTK_FUNCTION(7, "UTXD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(54, "UTXD2"),
+               "R17", "mt8135",
+               MTK_EINT_FUNCTION(2, 82),
+               MTK_FUNCTION(0, "GPIO54"),
+               MTK_FUNCTION(1, "UTXD2"),
+               MTK_FUNCTION(2, "EINT82"),
+               MTK_FUNCTION(4, " HDMI_BCK_OUT"),
+               MTK_FUNCTION(5, "CLKM2"),
+               MTK_FUNCTION(7, "URXD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(55, "UCTS2"),
+               "R20", "mt8135",
+               MTK_EINT_FUNCTION(2, 84),
+               MTK_FUNCTION(0, "GPIO55"),
+               MTK_FUNCTION(1, "UCTS2"),
+               MTK_FUNCTION(2, "EINT84"),
+               MTK_FUNCTION(5, "PWM1"),
+               MTK_FUNCTION(7, "URTS2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(56, "URTS2"),
+               "R19", "mt8135",
+               MTK_EINT_FUNCTION(2, 85),
+               MTK_FUNCTION(0, "GPIO56"),
+               MTK_FUNCTION(1, "URTS2"),
+               MTK_FUNCTION(2, "EINT85"),
+               MTK_FUNCTION(5, "PWM2"),
+               MTK_FUNCTION(7, "UCTS2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(57, "JTCK"),
+               "V17", "mt8135",
+               MTK_EINT_FUNCTION(2, 188),
+               MTK_FUNCTION(0, "GPIO57"),
+               MTK_FUNCTION(1, "JTCK"),
+               MTK_FUNCTION(2, "EINT188"),
+               MTK_FUNCTION(3, "DSP1_ICK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(58, "JTDO"),
+               "T16", "mt8135",
+               MTK_EINT_FUNCTION(2, 190),
+               MTK_FUNCTION(0, "GPIO58"),
+               MTK_FUNCTION(1, "JTDO"),
+               MTK_FUNCTION(2, "EINT190"),
+               MTK_FUNCTION(3, "DSP2_IMS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(59, "JTRST_B"),
+               "T19", "mt8135",
+               MTK_EINT_FUNCTION(2, 0),
+               MTK_FUNCTION(0, "GPIO59"),
+               MTK_FUNCTION(1, "JTRST_B"),
+               MTK_FUNCTION(2, "EINT0"),
+               MTK_FUNCTION(3, "DSP2_ICK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(60, "JTDI"),
+               "T18", "mt8135",
+               MTK_EINT_FUNCTION(2, 189),
+               MTK_FUNCTION(0, "GPIO60"),
+               MTK_FUNCTION(1, "JTDI"),
+               MTK_FUNCTION(2, "EINT189"),
+               MTK_FUNCTION(3, "DSP1_IMS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(61, "JRTCK"),
+               "T20", "mt8135",
+               MTK_EINT_FUNCTION(2, 187),
+               MTK_FUNCTION(0, "GPIO61"),
+               MTK_FUNCTION(1, "JRTCK"),
+               MTK_FUNCTION(2, "EINT187"),
+               MTK_FUNCTION(3, "DSP1_ID")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(62, "JTMS"),
+               "T17", "mt8135",
+               MTK_EINT_FUNCTION(2, 191),
+               MTK_FUNCTION(0, "GPIO62"),
+               MTK_FUNCTION(1, "JTMS"),
+               MTK_FUNCTION(2, "EINT191"),
+               MTK_FUNCTION(3, "DSP2_ID")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(63, "MSDC1_INSI"),
+               "V18", "mt8135",
+               MTK_EINT_FUNCTION(1, 15),
+               MTK_FUNCTION(0, "GPIO63"),
+               MTK_FUNCTION(1, "MSDC1_INSI"),
+               MTK_FUNCTION(3, "SCL5"),
+               MTK_FUNCTION(4, "PWM6"),
+               MTK_FUNCTION(5, "CLKM5"),
+               MTK_FUNCTION(7, "TESTB_OUT6")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(64, "MSDC1_SDWPI"),
+               "W18", "mt8135",
+               MTK_EINT_FUNCTION(2, 58),
+               MTK_FUNCTION(0, "GPIO64"),
+               MTK_FUNCTION(1, "MSDC1_SDWPI"),
+               MTK_FUNCTION(2, "EINT58"),
+               MTK_FUNCTION(3, "SDA5"),
+               MTK_FUNCTION(4, "PWM7"),
+               MTK_FUNCTION(5, "CLKM6"),
+               MTK_FUNCTION(7, "TESTB_OUT7")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(65, "MSDC2_INSI"),
+               "U22", "mt8135",
+               MTK_EINT_FUNCTION(1, 14),
+               MTK_FUNCTION(0, "GPIO65"),
+               MTK_FUNCTION(1, "MSDC2_INSI"),
+               MTK_FUNCTION(5, "USB_TEST_IO[27]"),
+               MTK_FUNCTION(7, "TESTA_OUT3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(66, "MSDC2_SDWPI"),
+               "U21", "mt8135",
+               MTK_EINT_FUNCTION(2, 66),
+               MTK_FUNCTION(0, "GPIO66"),
+               MTK_FUNCTION(1, "MSDC2_SDWPI"),
+               MTK_FUNCTION(2, "EINT66"),
+               MTK_FUNCTION(5, "USB_TEST_IO[28]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(67, "URXD4"),
+               "V23", "mt8135",
+               MTK_EINT_FUNCTION(2, 89),
+               MTK_FUNCTION(0, "GPIO67"),
+               MTK_FUNCTION(1, "URXD4"),
+               MTK_FUNCTION(2, "EINT89"),
+               MTK_FUNCTION(3, "URXD1"),
+               MTK_FUNCTION(6, "UTXD4"),
+               MTK_FUNCTION(7, "TESTB_OUT10")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(68, "UTXD4"),
+               "V22", "mt8135",
+               MTK_EINT_FUNCTION(2, 88),
+               MTK_FUNCTION(0, "GPIO68"),
+               MTK_FUNCTION(1, "UTXD4"),
+               MTK_FUNCTION(2, "EINT88"),
+               MTK_FUNCTION(3, "UTXD1"),
+               MTK_FUNCTION(6, "URXD4"),
+               MTK_FUNCTION(7, "TESTB_OUT11")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(69, "URXD1"),
+               "W22", "mt8135",
+               MTK_EINT_FUNCTION(2, 79),
+               MTK_FUNCTION(0, "GPIO69"),
+               MTK_FUNCTION(1, "URXD1"),
+               MTK_FUNCTION(2, "EINT79"),
+               MTK_FUNCTION(3, "URXD4"),
+               MTK_FUNCTION(6, "UTXD1"),
+               MTK_FUNCTION(7, "TESTB_OUT24")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(70, "UTXD1"),
+               "V21", "mt8135",
+               MTK_EINT_FUNCTION(2, 78),
+               MTK_FUNCTION(0, "GPIO70"),
+               MTK_FUNCTION(1, "UTXD1"),
+               MTK_FUNCTION(2, "EINT78"),
+               MTK_FUNCTION(3, "UTXD4"),
+               MTK_FUNCTION(6, "URXD1"),
+               MTK_FUNCTION(7, "TESTB_OUT25")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(71, "UCTS1"),
+               "V19", "mt8135",
+               MTK_EINT_FUNCTION(2, 80),
+               MTK_FUNCTION(0, "GPIO71"),
+               MTK_FUNCTION(1, "UCTS1"),
+               MTK_FUNCTION(2, "EINT80"),
+               MTK_FUNCTION(5, "CLKM0"),
+               MTK_FUNCTION(6, "URTS1"),
+               MTK_FUNCTION(7, "TESTB_OUT31")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(72, "URTS1"),
+               "V20", "mt8135",
+               MTK_EINT_FUNCTION(2, 81),
+               MTK_FUNCTION(0, "GPIO72"),
+               MTK_FUNCTION(1, "URTS1"),
+               MTK_FUNCTION(2, "EINT81"),
+               MTK_FUNCTION(5, "CLKM1"),
+               MTK_FUNCTION(6, "UCTS1"),
+               MTK_FUNCTION(7, "TESTB_OUT21")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(73, "PWM1"),
+               "W17", "mt8135",
+               MTK_EINT_FUNCTION(2, 73),
+               MTK_FUNCTION(0, "GPIO73"),
+               MTK_FUNCTION(1, "PWM1"),
+               MTK_FUNCTION(2, "EINT73"),
+               MTK_FUNCTION(5, "USB_DRVVBUS"),
+               MTK_FUNCTION(6, "DISP_PWM"),
+               MTK_FUNCTION(7, "TESTB_OUT8")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(74, "PWM2"),
+               "Y17", "mt8135",
+               MTK_EINT_FUNCTION(2, 74),
+               MTK_FUNCTION(0, "GPIO74"),
+               MTK_FUNCTION(1, "PWM2"),
+               MTK_FUNCTION(2, "EINT74"),
+               MTK_FUNCTION(3, "DPI33_CK"),
+               MTK_FUNCTION(4, "PWM5"),
+               MTK_FUNCTION(5, "URXD2"),
+               MTK_FUNCTION(6, "DISP_PWM"),
+               MTK_FUNCTION(7, "TESTB_OUT9")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(75, "PWM3"),
+               "Y19", "mt8135",
+               MTK_EINT_FUNCTION(2, 75),
+               MTK_FUNCTION(0, "GPIO75"),
+               MTK_FUNCTION(1, "PWM3"),
+               MTK_FUNCTION(2, "EINT75"),
+               MTK_FUNCTION(3, "DPI33_D0"),
+               MTK_FUNCTION(4, "PWM6"),
+               MTK_FUNCTION(5, "UTXD2"),
+               MTK_FUNCTION(6, "DISP_PWM"),
+               MTK_FUNCTION(7, "TESTB_OUT12")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(76, "PWM4"),
+               "W19", "mt8135",
+               MTK_EINT_FUNCTION(2, 76),
+               MTK_FUNCTION(0, "GPIO76"),
+               MTK_FUNCTION(1, "PWM4"),
+               MTK_FUNCTION(2, "EINT76"),
+               MTK_FUNCTION(3, "DPI33_D1"),
+               MTK_FUNCTION(4, "PWM7"),
+               MTK_FUNCTION(6, "DISP_PWM"),
+               MTK_FUNCTION(7, "TESTB_OUT13")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(77, "MSDC2_DAT2"),
+               "W21", "mt8135",
+               MTK_EINT_FUNCTION(2, 63),
+               MTK_FUNCTION(0, "GPIO77"),
+               MTK_FUNCTION(1, "MSDC2_DAT2"),
+               MTK_FUNCTION(2, "EINT63"),
+               MTK_FUNCTION(4, "DSP2_IMS"),
+               MTK_FUNCTION(6, "DPI33_D6"),
+               MTK_FUNCTION(7, "TESTA_OUT25")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(78, "MSDC2_DAT3"),
+               "AA23", "mt8135",
+               MTK_EINT_FUNCTION(2, 64),
+               MTK_FUNCTION(0, "GPIO78"),
+               MTK_FUNCTION(1, "MSDC2_DAT3"),
+               MTK_FUNCTION(2, "EINT64"),
+               MTK_FUNCTION(4, "DSP2_ID"),
+               MTK_FUNCTION(6, "DPI33_D7"),
+               MTK_FUNCTION(7, "TESTA_OUT26")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(79, "MSDC2_CMD"),
+               "Y22", "mt8135",
+               MTK_EINT_FUNCTION(2, 60),
+               MTK_FUNCTION(0, "GPIO79"),
+               MTK_FUNCTION(1, "MSDC2_CMD"),
+               MTK_FUNCTION(2, "EINT60"),
+               MTK_FUNCTION(4, "DSP1_IMS"),
+               MTK_FUNCTION(5, "PCM1_WS"),
+               MTK_FUNCTION(6, "DPI33_D3"),
+               MTK_FUNCTION(7, "TESTA_OUT0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(80, "MSDC2_CLK"),
+               "AA22", "mt8135",
+               MTK_EINT_FUNCTION(2, 59),
+               MTK_FUNCTION(0, "GPIO80"),
+               MTK_FUNCTION(1, "MSDC2_CLK"),
+               MTK_FUNCTION(2, "EINT59"),
+               MTK_FUNCTION(4, "DSP1_ICK"),
+               MTK_FUNCTION(5, "PCM1_CK"),
+               MTK_FUNCTION(6, "DPI33_D2"),
+               MTK_FUNCTION(7, "TESTA_OUT1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(81, "MSDC2_DAT1"),
+               "Y21", "mt8135",
+               MTK_EINT_FUNCTION(2, 62),
+               MTK_FUNCTION(0, "GPIO81"),
+               MTK_FUNCTION(1, "MSDC2_DAT1"),
+               MTK_FUNCTION(2, "EINT62"),
+               MTK_FUNCTION(4, "DSP2_ICK"),
+               MTK_FUNCTION(5, "PCM1_DO"),
+               MTK_FUNCTION(6, "DPI33_D5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(82, "MSDC2_DAT0"),
+               "AB22", "mt8135",
+               MTK_EINT_FUNCTION(2, 61),
+               MTK_FUNCTION(0, "GPIO82"),
+               MTK_FUNCTION(1, "MSDC2_DAT0"),
+               MTK_FUNCTION(2, "EINT61"),
+               MTK_FUNCTION(4, "DSP1_ID"),
+               MTK_FUNCTION(5, "PCM1_DI"),
+               MTK_FUNCTION(6, "DPI33_D4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(83, "MSDC1_DAT0"),
+               "AC19", "mt8135",
+               MTK_EINT_FUNCTION(2, 53),
+               MTK_FUNCTION(0, "GPIO83"),
+               MTK_FUNCTION(1, "MSDC1_DAT0"),
+               MTK_FUNCTION(2, "EINT53"),
+               MTK_FUNCTION(3, "SCL1"),
+               MTK_FUNCTION(4, "PWM2"),
+               MTK_FUNCTION(5, "CLKM1"),
+               MTK_FUNCTION(7, "TESTB_OUT2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(84, "MSDC1_DAT1"),
+               "AA19", "mt8135",
+               MTK_EINT_FUNCTION(2, 54),
+               MTK_FUNCTION(0, "GPIO84"),
+               MTK_FUNCTION(1, "MSDC1_DAT1"),
+               MTK_FUNCTION(2, "EINT54"),
+               MTK_FUNCTION(3, "SDA1"),
+               MTK_FUNCTION(4, "PWM3"),
+               MTK_FUNCTION(5, "CLKM2"),
+               MTK_FUNCTION(7, "TESTB_OUT3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(85, "MSDC1_CMD"),
+               "AA20", "mt8135",
+               MTK_EINT_FUNCTION(2, 52),
+               MTK_FUNCTION(0, "GPIO85"),
+               MTK_FUNCTION(1, "MSDC1_CMD"),
+               MTK_FUNCTION(2, "EINT52"),
+               MTK_FUNCTION(3, "SDA0"),
+               MTK_FUNCTION(4, "PWM1"),
+               MTK_FUNCTION(5, "CLKM0"),
+               MTK_FUNCTION(7, "TESTB_OUT1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(86, "MSDC1_CLK"),
+               "AB19", "mt8135",
+               MTK_EINT_FUNCTION(2, 51),
+               MTK_FUNCTION(0, "GPIO86"),
+               MTK_FUNCTION(1, "MSDC1_CLK"),
+               MTK_FUNCTION(2, "EINT51"),
+               MTK_FUNCTION(3, "SCL0"),
+               MTK_FUNCTION(4, "DISP_PWM"),
+               MTK_FUNCTION(7, "TESTB_OUT0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(87, "MSDC1_DAT2"),
+               "AA21", "mt8135",
+               MTK_EINT_FUNCTION(2, 55),
+               MTK_FUNCTION(0, "GPIO87"),
+               MTK_FUNCTION(1, "MSDC1_DAT2"),
+               MTK_FUNCTION(2, "EINT55"),
+               MTK_FUNCTION(3, "SCL4"),
+               MTK_FUNCTION(4, "PWM4"),
+               MTK_FUNCTION(5, "CLKM3"),
+               MTK_FUNCTION(7, "TESTB_OUT4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(88, "MSDC1_DAT3"),
+               "AB20", "mt8135",
+               MTK_EINT_FUNCTION(2, 56),
+               MTK_FUNCTION(0, "GPIO88"),
+               MTK_FUNCTION(1, "MSDC1_DAT3"),
+               MTK_FUNCTION(2, "EINT56"),
+               MTK_FUNCTION(3, "SDA4"),
+               MTK_FUNCTION(4, "PWM5"),
+               MTK_FUNCTION(5, "CLKM4"),
+               MTK_FUNCTION(7, "TESTB_OUT5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(89, "MSDC4_DAT0"),
+               "AB8", "mt8135",
+               MTK_EINT_FUNCTION(2, 133),
+               MTK_FUNCTION(0, "GPIO89"),
+               MTK_FUNCTION(1, "MSDC4_DAT0"),
+               MTK_FUNCTION(2, "EINT133"),
+               MTK_FUNCTION(4, "EXT_FRAME_SYNC"),
+               MTK_FUNCTION(5, "USB_DRVVBUS"),
+               MTK_FUNCTION(6, "A_FUNC_DIN[9]"),
+               MTK_FUNCTION(7, "LPTE")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(90, "MSDC4_DAT1"),
+               "AB7", "mt8135",
+               MTK_EINT_FUNCTION(2, 134),
+               MTK_FUNCTION(0, "GPIO90"),
+               MTK_FUNCTION(1, "MSDC4_DAT1"),
+               MTK_FUNCTION(2, "EINT134"),
+               MTK_FUNCTION(6, "A_FUNC_DIN[10]"),
+               MTK_FUNCTION(7, "LRSTB_1X")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(91, "MSDC4_DAT5"),
+               "AA8", "mt8135",
+               MTK_EINT_FUNCTION(2, 136),
+               MTK_FUNCTION(0, "GPIO91"),
+               MTK_FUNCTION(1, "MSDC4_DAT5"),
+               MTK_FUNCTION(2, "EINT136"),
+               MTK_FUNCTION(3, "I2SIN_WS"),
+               MTK_FUNCTION(4, "DAC_WS"),
+               MTK_FUNCTION(5, "PCM1_WS"),
+               MTK_FUNCTION(6, "A_FUNC_DIN[11]"),
+               MTK_FUNCTION(7, "SPI1_CSN")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(92, "MSDC4_DAT6"),
+               "AC4", "mt8135",
+               MTK_EINT_FUNCTION(2, 137),
+               MTK_FUNCTION(0, "GPIO92"),
+               MTK_FUNCTION(1, "MSDC4_DAT6"),
+               MTK_FUNCTION(2, "EINT137"),
+               MTK_FUNCTION(3, "I2SOUT_DAT"),
+               MTK_FUNCTION(4, "DAC_DAT_OUT"),
+               MTK_FUNCTION(5, "PCM1_DO"),
+               MTK_FUNCTION(6, "A_FUNC_DIN[12]"),
+               MTK_FUNCTION(7, "SPI1_MO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(93, "MSDC4_DAT7"),
+               "AC6", "mt8135",
+               MTK_EINT_FUNCTION(2, 138),
+               MTK_FUNCTION(0, "GPIO93"),
+               MTK_FUNCTION(1, "MSDC4_DAT7"),
+               MTK_FUNCTION(2, "EINT138"),
+               MTK_FUNCTION(3, "I2SIN_DAT"),
+               MTK_FUNCTION(5, "PCM1_DI"),
+               MTK_FUNCTION(6, "A_FUNC_DIN[13]"),
+               MTK_FUNCTION(7, "SPI1_MI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(94, "MSDC4_DAT4"),
+               "AA7", "mt8135",
+               MTK_EINT_FUNCTION(2, 135),
+               MTK_FUNCTION(0, "GPIO94"),
+               MTK_FUNCTION(1, "MSDC4_DAT4"),
+               MTK_FUNCTION(2, "EINT135"),
+               MTK_FUNCTION(3, "I2SIN_CK"),
+               MTK_FUNCTION(4, "DAC_CK"),
+               MTK_FUNCTION(5, "PCM1_CK"),
+               MTK_FUNCTION(6, "A_FUNC_DIN[14]"),
+               MTK_FUNCTION(7, "SPI1_CLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(95, "MSDC4_DAT2"),
+               "AB6", "mt8135",
+               MTK_EINT_FUNCTION(2, 131),
+               MTK_FUNCTION(0, "GPIO95"),
+               MTK_FUNCTION(1, "MSDC4_DAT2"),
+               MTK_FUNCTION(2, "EINT131"),
+               MTK_FUNCTION(3, "I2SIN_WS"),
+               MTK_FUNCTION(4, "CM2PDN_2X"),
+               MTK_FUNCTION(5, "DAC_WS"),
+               MTK_FUNCTION(6, "PCM1_WS"),
+               MTK_FUNCTION(7, "LSCE0B_1X")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(96, "MSDC4_CLK"),
+               "AB5", "mt8135",
+               MTK_EINT_FUNCTION(2, 129),
+               MTK_FUNCTION(0, "GPIO96"),
+               MTK_FUNCTION(1, "MSDC4_CLK"),
+               MTK_FUNCTION(2, "EINT129"),
+               MTK_FUNCTION(3, "DPI1_CK_2X"),
+               MTK_FUNCTION(4, "CM2PCLK_2X"),
+               MTK_FUNCTION(5, "PWM4"),
+               MTK_FUNCTION(6, "PCM1_DI"),
+               MTK_FUNCTION(7, "LSCK_1X")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(97, "MSDC4_DAT3"),
+               "Y8", "mt8135",
+               MTK_EINT_FUNCTION(2, 132),
+               MTK_FUNCTION(0, "GPIO97"),
+               MTK_FUNCTION(1, "MSDC4_DAT3"),
+               MTK_FUNCTION(2, "EINT132"),
+               MTK_FUNCTION(3, "I2SOUT_DAT"),
+               MTK_FUNCTION(4, "CM2RST_2X"),
+               MTK_FUNCTION(5, "DAC_DAT_OUT"),
+               MTK_FUNCTION(6, "PCM1_DO"),
+               MTK_FUNCTION(7, "LSCE1B_1X")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(98, "MSDC4_CMD"),
+               "AC3", "mt8135",
+               MTK_EINT_FUNCTION(2, 128),
+               MTK_FUNCTION(0, "GPIO98"),
+               MTK_FUNCTION(1, "MSDC4_CMD"),
+               MTK_FUNCTION(2, "EINT128"),
+               MTK_FUNCTION(3, "DPI1_DE_2X"),
+               MTK_FUNCTION(5, "PWM3"),
+               MTK_FUNCTION(7, "LSDA_1X")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(99, "MSDC4_RSTB"),
+               "AB4", "mt8135",
+               MTK_EINT_FUNCTION(2, 130),
+               MTK_FUNCTION(0, "GPIO99"),
+               MTK_FUNCTION(1, "MSDC4_RSTB"),
+               MTK_FUNCTION(2, "EINT130"),
+               MTK_FUNCTION(3, "I2SIN_CK"),
+               MTK_FUNCTION(4, "CM2MCLK_2X"),
+               MTK_FUNCTION(5, "DAC_CK"),
+               MTK_FUNCTION(6, "PCM1_CK"),
+               MTK_FUNCTION(7, "LSA0_1X")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(100, "SDA0"),
+               "W9", "mt8135",
+               MTK_EINT_FUNCTION(2, 91),
+               MTK_FUNCTION(0, "GPIO100"),
+               MTK_FUNCTION(1, "SDA0"),
+               MTK_FUNCTION(2, "EINT91"),
+               MTK_FUNCTION(3, "CLKM1"),
+               MTK_FUNCTION(4, "PWM1"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[15]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(101, "SCL0"),
+               "W11", "mt8135",
+               MTK_EINT_FUNCTION(2, 90),
+               MTK_FUNCTION(0, "GPIO101"),
+               MTK_FUNCTION(1, "SCL0"),
+               MTK_FUNCTION(2, "EINT90"),
+               MTK_FUNCTION(3, "CLKM0"),
+               MTK_FUNCTION(4, "DISP_PWM"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[16]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(102, "EINT10_AUXIN2"),
+               "AA3", "mt8135",
+               MTK_EINT_FUNCTION(1, 10),
+               MTK_FUNCTION(0, "GPIO102"),
+               MTK_FUNCTION(1, "EINT10"),
+               MTK_FUNCTION(5, "USB_TEST_IO[16]"),
+               MTK_FUNCTION(6, "TESTB_OUT16"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[17]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(103, "EINT11_AUXIN3"),
+               "AB2", "mt8135",
+               MTK_EINT_FUNCTION(1, 11),
+               MTK_FUNCTION(0, "GPIO103"),
+               MTK_FUNCTION(1, "EINT11"),
+               MTK_FUNCTION(5, "USB_TEST_IO[17]"),
+               MTK_FUNCTION(6, "TESTB_OUT17"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[18]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(104, "EINT16_AUXIN4"),
+               "AB3", "mt8135",
+               MTK_EINT_FUNCTION(1, 16),
+               MTK_FUNCTION(0, "GPIO104"),
+               MTK_FUNCTION(1, "EINT16"),
+               MTK_FUNCTION(5, "USB_TEST_IO[18]"),
+               MTK_FUNCTION(6, "TESTB_OUT18"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[19]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(105, "I2S_CLK"),
+               "W6", "mt8135",
+               MTK_EINT_FUNCTION(2, 10),
+               MTK_FUNCTION(0, "GPIO105"),
+               MTK_FUNCTION(1, "I2SIN_CK"),
+               MTK_FUNCTION(2, "EINT10"),
+               MTK_FUNCTION(3, "DAC_CK"),
+               MTK_FUNCTION(4, "PCM1_CK"),
+               MTK_FUNCTION(5, "USB_TEST_IO[19]"),
+               MTK_FUNCTION(6, "TESTB_OUT19"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[20]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(106, "I2S_WS"),
+               "AA6", "mt8135",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO106"),
+               MTK_FUNCTION(1, "I2SIN_WS"),
+               MTK_FUNCTION(3, "DAC_WS"),
+               MTK_FUNCTION(4, "PCM1_WS"),
+               MTK_FUNCTION(5, "USB_TEST_IO[20]"),
+               MTK_FUNCTION(6, "TESTB_OUT20"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[21]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(107, "I2S_DATA_IN"),
+               "AA5", "mt8135",
+               MTK_EINT_FUNCTION(2, 11),
+               MTK_FUNCTION(0, "GPIO107"),
+               MTK_FUNCTION(1, "I2SIN_DAT"),
+               MTK_FUNCTION(2, "EINT11"),
+               MTK_FUNCTION(4, "PCM1_DI"),
+               MTK_FUNCTION(5, "USB_TEST_IO[21]"),
+               MTK_FUNCTION(6, "TESTB_OUT22"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[22]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(108, "I2S_DATA_OUT"),
+               "AA4", "mt8135",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO108"),
+               MTK_FUNCTION(1, "I2SOUT_DAT"),
+               MTK_FUNCTION(3, "DAC_DAT_OUT"),
+               MTK_FUNCTION(4, "PCM1_DO"),
+               MTK_FUNCTION(5, "USB_TEST_IO[22]"),
+               MTK_FUNCTION(6, "TESTB_OUT23"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[23]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(109, "EINT5"),
+               "W5", "mt8135",
+               MTK_EINT_FUNCTION(1, 5),
+               MTK_FUNCTION(0, "GPIO109"),
+               MTK_FUNCTION(1, "EINT5"),
+               MTK_FUNCTION(2, "PWM5"),
+               MTK_FUNCTION(3, "CLKM3"),
+               MTK_FUNCTION(4, "GPU_JTRSTB"),
+               MTK_FUNCTION(5, "USB_TEST_IO[23]"),
+               MTK_FUNCTION(6, "TESTB_OUT26"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[24]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(110, "EINT6"),
+               "V5", "mt8135",
+               MTK_EINT_FUNCTION(1, 6),
+               MTK_FUNCTION(0, "GPIO110"),
+               MTK_FUNCTION(1, "EINT6"),
+               MTK_FUNCTION(2, "PWM6"),
+               MTK_FUNCTION(3, "CLKM4"),
+               MTK_FUNCTION(4, "GPU_JTMS"),
+               MTK_FUNCTION(5, "USB_TEST_IO[24]"),
+               MTK_FUNCTION(6, "TESTB_OUT27"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[25]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(111, "EINT7"),
+               "W3", "mt8135",
+               MTK_EINT_FUNCTION(1, 7),
+               MTK_FUNCTION(0, "GPIO111"),
+               MTK_FUNCTION(1, "EINT7"),
+               MTK_FUNCTION(2, "PWM7"),
+               MTK_FUNCTION(3, "CLKM5"),
+               MTK_FUNCTION(4, "GPU_JTDO"),
+               MTK_FUNCTION(5, "USB_TEST_IO[25]"),
+               MTK_FUNCTION(6, "TESTB_OUT28"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[26]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(112, "EINT8"),
+               "V6", "mt8135",
+               MTK_EINT_FUNCTION(1, 8),
+               MTK_FUNCTION(0, "GPIO112"),
+               MTK_FUNCTION(1, "EINT8"),
+               MTK_FUNCTION(2, "DISP_PWM"),
+               MTK_FUNCTION(3, "CLKM6"),
+               MTK_FUNCTION(4, "GPU_JTDI"),
+               MTK_FUNCTION(5, "USB_TEST_IO[26]"),
+               MTK_FUNCTION(6, "TESTB_OUT29"),
+               MTK_FUNCTION(7, "EXT_FRAME_SYNC")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(113, "EINT9"),
+               "W8", "mt8135",
+               MTK_EINT_FUNCTION(1, 9),
+               MTK_FUNCTION(0, "GPIO113"),
+               MTK_FUNCTION(1, "EINT9"),
+               MTK_FUNCTION(4, "GPU_JTCK"),
+               MTK_FUNCTION(5, "USB_DRVVBUS"),
+               MTK_FUNCTION(6, "TESTB_OUT30"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[27]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(114, "LPCE1B"),
+               "W4", "mt8135",
+               MTK_EINT_FUNCTION(2, 127),
+               MTK_FUNCTION(0, "GPIO114"),
+               MTK_FUNCTION(1, "LPCE1B"),
+               MTK_FUNCTION(2, "EINT127"),
+               MTK_FUNCTION(5, "PWM2"),
+               MTK_FUNCTION(6, "TESTB_OUT14"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[28]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(115, "LPCE0B"),
+               "T5", "mt8135",
+               MTK_EINT_FUNCTION(2, 126),
+               MTK_FUNCTION(0, "GPIO115"),
+               MTK_FUNCTION(1, "LPCE0B"),
+               MTK_FUNCTION(2, "EINT126"),
+               MTK_FUNCTION(5, "PWM1"),
+               MTK_FUNCTION(6, "TESTB_OUT15"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[29]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(116, "DISP_PWM"),
+               "V4", "mt8135",
+               MTK_EINT_FUNCTION(2, 77),
+               MTK_FUNCTION(0, "GPIO116"),
+               MTK_FUNCTION(1, "DISP_PWM"),
+               MTK_FUNCTION(2, "EINT77"),
+               MTK_FUNCTION(3, "LSDI"),
+               MTK_FUNCTION(4, "PWM1"),
+               MTK_FUNCTION(5, "PWM2"),
+               MTK_FUNCTION(7, "PWM3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(117, "EINT1"),
+               "T6", "mt8135",
+               MTK_EINT_FUNCTION(1, 1),
+               MTK_FUNCTION(0, "GPIO117"),
+               MTK_FUNCTION(1, "EINT1"),
+               MTK_FUNCTION(2, "PWM2"),
+               MTK_FUNCTION(3, "CLKM1"),
+               MTK_FUNCTION(5, "USB_TEST_IO[13]"),
+               MTK_FUNCTION(7, "USB_SDA")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(118, "EINT2"),
+               "T4", "mt8135",
+               MTK_EINT_FUNCTION(1, 2),
+               MTK_FUNCTION(0, "GPIO118"),
+               MTK_FUNCTION(1, "EINT2"),
+               MTK_FUNCTION(2, "PWM3"),
+               MTK_FUNCTION(3, "CLKM2"),
+               MTK_FUNCTION(5, "USB_TEST_IO[14]"),
+               MTK_FUNCTION(6, "SRCLKENAI2"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[30]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(119, "EINT3"),
+               "R4", "mt8135",
+               MTK_EINT_FUNCTION(1, 3),
+               MTK_FUNCTION(0, "GPIO119"),
+               MTK_FUNCTION(1, "EINT3"),
+               MTK_FUNCTION(5, "USB_TEST_IO[15]"),
+               MTK_FUNCTION(6, "SRCLKENAI1"),
+               MTK_FUNCTION(7, "EXT_26M_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(120, "EINT4"),
+               "R5", "mt8135",
+               MTK_EINT_FUNCTION(1, 4),
+               MTK_FUNCTION(0, "GPIO120"),
+               MTK_FUNCTION(1, "EINT4"),
+               MTK_FUNCTION(2, "PWM4"),
+               MTK_FUNCTION(5, "USB_DRVVBUS"),
+               MTK_FUNCTION(7, "A_FUNC_DIN[31]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(121, "DPIDE"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 100),
+               MTK_FUNCTION(0, "GPIO121"),
+               MTK_FUNCTION(1, "DPI0_DE"),
+               MTK_FUNCTION(2, "EINT100"),
+               MTK_FUNCTION(3, "I2SOUT_DAT"),
+               MTK_FUNCTION(4, "DAC_DAT_OUT"),
+               MTK_FUNCTION(5, "PCM1_DO"),
+               MTK_FUNCTION(6, "IRDA_TXD")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(122, "DPICK"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 101),
+               MTK_FUNCTION(0, "GPIO122"),
+               MTK_FUNCTION(1, "DPI0_CK"),
+               MTK_FUNCTION(2, "EINT101"),
+               MTK_FUNCTION(3, "I2SIN_DAT"),
+               MTK_FUNCTION(5, "PCM1_DI"),
+               MTK_FUNCTION(6, "IRDA_PDN")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(123, "DPIG4"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 114),
+               MTK_FUNCTION(0, "GPIO123"),
+               MTK_FUNCTION(1, "DPI0_G4"),
+               MTK_FUNCTION(2, "EINT114"),
+               MTK_FUNCTION(4, "CM2DAT_2X[0]"),
+               MTK_FUNCTION(5, "DSP2_ID")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(124, "DPIG5"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 115),
+               MTK_FUNCTION(0, "GPIO124"),
+               MTK_FUNCTION(1, "DPI0_G5"),
+               MTK_FUNCTION(2, "EINT115"),
+               MTK_FUNCTION(4, "CM2DAT_2X[1]"),
+               MTK_FUNCTION(5, "DSP2_ICK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(125, "DPIR3"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 121),
+               MTK_FUNCTION(0, "GPIO125"),
+               MTK_FUNCTION(1, "DPI0_R3"),
+               MTK_FUNCTION(2, "EINT121"),
+               MTK_FUNCTION(4, "CM2DAT_2X[7]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(126, "DPIG1"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 111),
+               MTK_FUNCTION(0, "GPIO126"),
+               MTK_FUNCTION(1, "DPI0_G1"),
+               MTK_FUNCTION(2, "EINT111"),
+               MTK_FUNCTION(5, "DSP1_ICK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(127, "DPIVSYNC"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 98),
+               MTK_FUNCTION(0, "GPIO127"),
+               MTK_FUNCTION(1, "DPI0_VSYNC"),
+               MTK_FUNCTION(2, "EINT98"),
+               MTK_FUNCTION(3, "I2SIN_CK"),
+               MTK_FUNCTION(4, "DAC_CK"),
+               MTK_FUNCTION(5, "PCM1_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(128, "DPIHSYNC"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 99),
+               MTK_FUNCTION(0, "GPIO128"),
+               MTK_FUNCTION(1, "DPI0_HSYNC"),
+               MTK_FUNCTION(2, "EINT99"),
+               MTK_FUNCTION(3, "I2SIN_WS"),
+               MTK_FUNCTION(4, "DAC_WS"),
+               MTK_FUNCTION(5, "PCM1_WS"),
+               MTK_FUNCTION(6, "IRDA_RXD")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(129, "DPIB0"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 102),
+               MTK_FUNCTION(0, "GPIO129"),
+               MTK_FUNCTION(1, "DPI0_B0"),
+               MTK_FUNCTION(2, "EINT102"),
+               MTK_FUNCTION(4, "SCL0"),
+               MTK_FUNCTION(5, "DISP_PWM")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(130, "DPIB1"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 103),
+               MTK_FUNCTION(0, "GPIO130"),
+               MTK_FUNCTION(1, "DPI0_B1"),
+               MTK_FUNCTION(2, "EINT103"),
+               MTK_FUNCTION(3, "CLKM0"),
+               MTK_FUNCTION(4, "SDA0"),
+               MTK_FUNCTION(5, "PWM1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(131, "DPIB2"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 104),
+               MTK_FUNCTION(0, "GPIO131"),
+               MTK_FUNCTION(1, "DPI0_B2"),
+               MTK_FUNCTION(2, "EINT104"),
+               MTK_FUNCTION(3, "CLKM1"),
+               MTK_FUNCTION(4, "SCL1"),
+               MTK_FUNCTION(5, "PWM2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(132, "DPIB3"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 105),
+               MTK_FUNCTION(0, "GPIO132"),
+               MTK_FUNCTION(1, "DPI0_B3"),
+               MTK_FUNCTION(2, "EINT105"),
+               MTK_FUNCTION(3, "CLKM2"),
+               MTK_FUNCTION(4, "SDA1"),
+               MTK_FUNCTION(5, "PWM3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(133, "DPIB4"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 106),
+               MTK_FUNCTION(0, "GPIO133"),
+               MTK_FUNCTION(1, "DPI0_B4"),
+               MTK_FUNCTION(2, "EINT106"),
+               MTK_FUNCTION(3, "CLKM3"),
+               MTK_FUNCTION(4, "SCL2"),
+               MTK_FUNCTION(5, "PWM4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(134, "DPIB5"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 107),
+               MTK_FUNCTION(0, "GPIO134"),
+               MTK_FUNCTION(1, "DPI0_B5"),
+               MTK_FUNCTION(2, "EINT107"),
+               MTK_FUNCTION(3, "CLKM4"),
+               MTK_FUNCTION(4, "SDA2"),
+               MTK_FUNCTION(5, "PWM5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(135, "DPIB6"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 108),
+               MTK_FUNCTION(0, "GPIO135"),
+               MTK_FUNCTION(1, "DPI0_B6"),
+               MTK_FUNCTION(2, "EINT108"),
+               MTK_FUNCTION(3, "CLKM5"),
+               MTK_FUNCTION(4, "SCL3"),
+               MTK_FUNCTION(5, "PWM6")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(136, "DPIB7"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 109),
+               MTK_FUNCTION(0, "GPIO136"),
+               MTK_FUNCTION(1, "DPI0_B7"),
+               MTK_FUNCTION(2, "EINT109"),
+               MTK_FUNCTION(3, "CLKM6"),
+               MTK_FUNCTION(4, "SDA3"),
+               MTK_FUNCTION(5, "PWM7")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(137, "DPIG0"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 110),
+               MTK_FUNCTION(0, "GPIO137"),
+               MTK_FUNCTION(1, "DPI0_G0"),
+               MTK_FUNCTION(2, "EINT110"),
+               MTK_FUNCTION(5, "DSP1_ID")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(138, "DPIG2"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 112),
+               MTK_FUNCTION(0, "GPIO138"),
+               MTK_FUNCTION(1, "DPI0_G2"),
+               MTK_FUNCTION(2, "EINT112"),
+               MTK_FUNCTION(5, "DSP1_IMS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(139, "DPIG3"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 113),
+               MTK_FUNCTION(0, "GPIO139"),
+               MTK_FUNCTION(1, "DPI0_G3"),
+               MTK_FUNCTION(2, "EINT113"),
+               MTK_FUNCTION(5, "DSP2_IMS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(140, "DPIG6"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 116),
+               MTK_FUNCTION(0, "GPIO140"),
+               MTK_FUNCTION(1, "DPI0_G6"),
+               MTK_FUNCTION(2, "EINT116"),
+               MTK_FUNCTION(4, "CM2DAT_2X[2]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(141, "DPIG7"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 117),
+               MTK_FUNCTION(0, "GPIO141"),
+               MTK_FUNCTION(1, "DPI0_G7"),
+               MTK_FUNCTION(2, "EINT117"),
+               MTK_FUNCTION(4, "CM2DAT_2X[3]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(142, "DPIR0"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 118),
+               MTK_FUNCTION(0, "GPIO142"),
+               MTK_FUNCTION(1, "DPI0_R0"),
+               MTK_FUNCTION(2, "EINT118"),
+               MTK_FUNCTION(4, "CM2DAT_2X[4]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(143, "DPIR1"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 119),
+               MTK_FUNCTION(0, "GPIO143"),
+               MTK_FUNCTION(1, "DPI0_R1"),
+               MTK_FUNCTION(2, "EINT119"),
+               MTK_FUNCTION(4, "CM2DAT_2X[5]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(144, "DPIR2"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 120),
+               MTK_FUNCTION(0, "GPIO144"),
+               MTK_FUNCTION(1, "DPI0_R2"),
+               MTK_FUNCTION(2, "EINT120"),
+               MTK_FUNCTION(4, "CM2DAT_2X[6]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(145, "DPIR4"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 122),
+               MTK_FUNCTION(0, "GPIO145"),
+               MTK_FUNCTION(1, "DPI0_R4"),
+               MTK_FUNCTION(2, "EINT122"),
+               MTK_FUNCTION(4, "CM2DAT_2X[8]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(146, "DPIR5"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 123),
+               MTK_FUNCTION(0, "GPIO146"),
+               MTK_FUNCTION(1, "DPI0_R5"),
+               MTK_FUNCTION(2, "EINT123"),
+               MTK_FUNCTION(4, "CM2DAT_2X[9]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(147, "DPIR6"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 124),
+               MTK_FUNCTION(0, "GPIO147"),
+               MTK_FUNCTION(1, "DPI0_R6"),
+               MTK_FUNCTION(2, "EINT124"),
+               MTK_FUNCTION(4, "CM2VSYNC_2X")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(148, "DPIR7"),
+               NULL, "mt8135",
+               MTK_EINT_FUNCTION(2, 125),
+               MTK_FUNCTION(0, "GPIO148"),
+               MTK_FUNCTION(1, "DPI0_R7"),
+               MTK_FUNCTION(2, "EINT125"),
+               MTK_FUNCTION(4, "CM2HSYNC_2X")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(149, "TDN3/LVDS(TDN3)"),
+               "AA2", "mt8135",
+               MTK_EINT_FUNCTION(2, 36),
+               MTK_FUNCTION(0, "GPIO149"),
+               MTK_FUNCTION(2, "EINT36")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(150, "TDP3/LVDS(TDP3)"),
+               "AA1", "mt8135",
+               MTK_EINT_FUNCTION(2, 35),
+               MTK_FUNCTION(0, "GPIO150"),
+               MTK_FUNCTION(2, "EINT35")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(151, "TDN2/LVDS(TCN)"),
+               "Y2", "mt8135",
+               MTK_EINT_FUNCTION(2, 169),
+               MTK_FUNCTION(0, "GPIO151"),
+               MTK_FUNCTION(2, "EINT169")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(152, "TDP2/LVDS(TCP)"),
+               "Y1", "mt8135",
+               MTK_EINT_FUNCTION(2, 168),
+               MTK_FUNCTION(0, "GPIO152"),
+               MTK_FUNCTION(2, "EINT168")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(153, "TCN/LVDS(TDN2)"),
+               "W2", "mt8135",
+               MTK_EINT_FUNCTION(2, 163),
+               MTK_FUNCTION(0, "GPIO153"),
+               MTK_FUNCTION(2, "EINT163")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(154, "TCP/LVDS(TDP2)"),
+               "W1", "mt8135",
+               MTK_EINT_FUNCTION(2, 162),
+               MTK_FUNCTION(0, "GPIO154"),
+               MTK_FUNCTION(2, "EINT162")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(155, "TDN1/LVDS(TDN1)"),
+               "V3", "mt8135",
+               MTK_EINT_FUNCTION(2, 167),
+               MTK_FUNCTION(0, "GPIO155"),
+               MTK_FUNCTION(2, "EINT167")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(156, "TDP1/LVDS(TDP1)"),
+               "V2", "mt8135",
+               MTK_EINT_FUNCTION(2, 166),
+               MTK_FUNCTION(0, "GPIO156"),
+               MTK_FUNCTION(2, "EINT166")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(157, "TDN0/LVDS(TDN0)"),
+               "U3", "mt8135",
+               MTK_EINT_FUNCTION(2, 165),
+               MTK_FUNCTION(0, "GPIO157"),
+               MTK_FUNCTION(2, "EINT165")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(158, "TDP0/LVDS(TDP0)"),
+               "U2", "mt8135",
+               MTK_EINT_FUNCTION(2, 164),
+               MTK_FUNCTION(0, "GPIO158"),
+               MTK_FUNCTION(2, "EINT164")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(159, "RDN3"),
+               "N5", "mt8135",
+               MTK_EINT_FUNCTION(2, 18),
+               MTK_FUNCTION(0, "GPIO159"),
+               MTK_FUNCTION(2, "EINT18")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(160, "RDP3"),
+               "N4", "mt8135",
+               MTK_EINT_FUNCTION(2, 30),
+               MTK_FUNCTION(0, "GPIO160"),
+               MTK_FUNCTION(2, "EINT30")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(161, "RDN2"),
+               "T2", "mt8135",
+               MTK_EINT_FUNCTION(2, 31),
+               MTK_FUNCTION(0, "GPIO161"),
+               MTK_FUNCTION(2, "EINT31")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(162, "RDP2"),
+               "T3", "mt8135",
+               MTK_EINT_FUNCTION(2, 32),
+               MTK_FUNCTION(0, "GPIO162"),
+               MTK_FUNCTION(2, "EINT32")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(163, "RCN"),
+               "P2", "mt8135",
+               MTK_EINT_FUNCTION(2, 33),
+               MTK_FUNCTION(0, "GPIO163"),
+               MTK_FUNCTION(2, "EINT33")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(164, "RCP"),
+               "P3", "mt8135",
+               MTK_EINT_FUNCTION(2, 39),
+               MTK_FUNCTION(0, "GPIO164"),
+               MTK_FUNCTION(2, "EINT39")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(165, "RDN1"),
+               "R3", "mt8135",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO165")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(166, "RDP1"),
+               "R2", "mt8135",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO166")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(167, "RDN0"),
+               "N3", "mt8135",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO167")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(168, "RDP0"),
+               "N2", "mt8135",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO168")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(169, "RDN1_A"),
+               "M4", "mt8135",
+               MTK_EINT_FUNCTION(2, 175),
+               MTK_FUNCTION(0, "GPIO169"),
+               MTK_FUNCTION(1, "CMDAT6"),
+               MTK_FUNCTION(2, "EINT175")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(170, "RDP1_A"),
+               "M3", "mt8135",
+               MTK_EINT_FUNCTION(2, 174),
+               MTK_FUNCTION(0, "GPIO170"),
+               MTK_FUNCTION(1, "CMDAT7"),
+               MTK_FUNCTION(2, "EINT174")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(171, "RCN_A"),
+               "L3", "mt8135",
+               MTK_EINT_FUNCTION(2, 171),
+               MTK_FUNCTION(0, "GPIO171"),
+               MTK_FUNCTION(1, "CMDAT8"),
+               MTK_FUNCTION(2, "EINT171")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(172, "RCP_A"),
+               "L2", "mt8135",
+               MTK_EINT_FUNCTION(2, 170),
+               MTK_FUNCTION(0, "GPIO172"),
+               MTK_FUNCTION(1, "CMDAT9"),
+               MTK_FUNCTION(2, "EINT170")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(173, "RDN0_A"),
+               "M2", "mt8135",
+               MTK_EINT_FUNCTION(2, 173),
+               MTK_FUNCTION(0, "GPIO173"),
+               MTK_FUNCTION(1, "CMHSYNC"),
+               MTK_FUNCTION(2, "EINT173")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(174, "RDP0_A"),
+               "M1", "mt8135",
+               MTK_EINT_FUNCTION(2, 172),
+               MTK_FUNCTION(0, "GPIO174"),
+               MTK_FUNCTION(1, "CMVSYNC"),
+               MTK_FUNCTION(2, "EINT172")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(175, "RDN1_B"),
+               "H2", "mt8135",
+               MTK_EINT_FUNCTION(2, 181),
+               MTK_FUNCTION(0, "GPIO175"),
+               MTK_FUNCTION(1, "CMDAT2"),
+               MTK_FUNCTION(2, "EINT181"),
+               MTK_FUNCTION(3, "CMCSD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(176, "RDP1_B"),
+               "H1", "mt8135",
+               MTK_EINT_FUNCTION(2, 180),
+               MTK_FUNCTION(0, "GPIO176"),
+               MTK_FUNCTION(1, "CMDAT3"),
+               MTK_FUNCTION(2, "EINT180"),
+               MTK_FUNCTION(3, "CMCSD3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(177, "RCN_B"),
+               "K3", "mt8135",
+               MTK_EINT_FUNCTION(2, 177),
+               MTK_FUNCTION(0, "GPIO177"),
+               MTK_FUNCTION(1, "CMDAT4"),
+               MTK_FUNCTION(2, "EINT177")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(178, "RCP_B"),
+               "K2", "mt8135",
+               MTK_EINT_FUNCTION(2, 176),
+               MTK_FUNCTION(0, "GPIO178"),
+               MTK_FUNCTION(1, "CMDAT5"),
+               MTK_FUNCTION(2, "EINT176")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(179, "RDN0_B"),
+               "J3", "mt8135",
+               MTK_EINT_FUNCTION(2, 179),
+               MTK_FUNCTION(0, "GPIO179"),
+               MTK_FUNCTION(1, "CMDAT0"),
+               MTK_FUNCTION(2, "EINT179"),
+               MTK_FUNCTION(3, "CMCSD0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(180, "RDP0_B"),
+               "J2", "mt8135",
+               MTK_EINT_FUNCTION(2, 178),
+               MTK_FUNCTION(0, "GPIO180"),
+               MTK_FUNCTION(1, "CMDAT1"),
+               MTK_FUNCTION(2, "EINT178"),
+               MTK_FUNCTION(3, "CMCSD1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(181, "CMPCLK"),
+               "K4", "mt8135",
+               MTK_EINT_FUNCTION(2, 182),
+               MTK_FUNCTION(0, "GPIO181"),
+               MTK_FUNCTION(1, "CMPCLK"),
+               MTK_FUNCTION(2, "EINT182"),
+               MTK_FUNCTION(3, "CMCSK"),
+               MTK_FUNCTION(4, "CM2MCLK_4X"),
+               MTK_FUNCTION(5, "TS_AUXADC_SEL[3]"),
+               MTK_FUNCTION(6, "VENC_TEST_CK"),
+               MTK_FUNCTION(7, "TESTA_OUT27")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(182, "CMMCLK"),
+               "J5", "mt8135",
+               MTK_EINT_FUNCTION(2, 183),
+               MTK_FUNCTION(0, "GPIO182"),
+               MTK_FUNCTION(1, "CMMCLK"),
+               MTK_FUNCTION(2, "EINT183"),
+               MTK_FUNCTION(5, "TS_AUXADC_SEL[2]"),
+               MTK_FUNCTION(7, "TESTA_OUT28")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(183, "CMRST"),
+               "J6", "mt8135",
+               MTK_EINT_FUNCTION(2, 185),
+               MTK_FUNCTION(0, "GPIO183"),
+               MTK_FUNCTION(1, "CMRST"),
+               MTK_FUNCTION(2, "EINT185"),
+               MTK_FUNCTION(5, "TS_AUXADC_SEL[1]"),
+               MTK_FUNCTION(7, "TESTA_OUT30")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(184, "CMPDN"),
+               "J4", "mt8135",
+               MTK_EINT_FUNCTION(2, 184),
+               MTK_FUNCTION(0, "GPIO184"),
+               MTK_FUNCTION(1, "CMPDN"),
+               MTK_FUNCTION(2, "EINT184"),
+               MTK_FUNCTION(5, "TS_AUXADC_SEL[0]"),
+               MTK_FUNCTION(7, "TESTA_OUT29")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(185, "CMFLASH"),
+               "G4", "mt8135",
+               MTK_EINT_FUNCTION(2, 186),
+               MTK_FUNCTION(0, "GPIO185"),
+               MTK_FUNCTION(1, "CMFLASH"),
+               MTK_FUNCTION(2, "EINT186"),
+               MTK_FUNCTION(3, "CM2MCLK_3X"),
+               MTK_FUNCTION(6, "MFG_TEST_CK_1"),
+               MTK_FUNCTION(7, "TESTA_OUT31")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(186, "MRG_I2S_PCM_CLK"),
+               "F5", "mt8135",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO186"),
+               MTK_FUNCTION(1, "MRG_I2S_PCM_CLK"),
+               MTK_FUNCTION(3, "I2SIN_CK"),
+               MTK_FUNCTION(4, "PCM0_CK"),
+               MTK_FUNCTION(5, "DSP2_ICK"),
+               MTK_FUNCTION(6, "IMG_TEST_CK"),
+               MTK_FUNCTION(7, "USB_SCL")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(187, "MRG_I2S_PCM_SYNC"),
+               "G6", "mt8135",
+               MTK_EINT_FUNCTION(2, 16),
+               MTK_FUNCTION(0, "GPIO187"),
+               MTK_FUNCTION(1, "MRG_I2S_PCM_SYNC"),
+               MTK_FUNCTION(2, "EINT16"),
+               MTK_FUNCTION(3, "I2SIN_WS"),
+               MTK_FUNCTION(4, "PCM0_WS"),
+               MTK_FUNCTION(6, "DISP_TEST_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(188, "MRG_I2S_PCM_RX"),
+               "G3", "mt8135",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO188"),
+               MTK_FUNCTION(1, "MRG_I2S_PCM_RX"),
+               MTK_FUNCTION(3, "I2SIN_DAT"),
+               MTK_FUNCTION(4, "PCM0_DI"),
+               MTK_FUNCTION(5, "DSP2_ID"),
+               MTK_FUNCTION(6, "MFG_TEST_CK"),
+               MTK_FUNCTION(7, "USB_SDA")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(189, "MRG_I2S_PCM_TX"),
+               "G5", "mt8135",
+               MTK_EINT_FUNCTION(2, 17),
+               MTK_FUNCTION(0, "GPIO189"),
+               MTK_FUNCTION(1, "MRG_I2S_PCM_TX"),
+               MTK_FUNCTION(2, "EINT17"),
+               MTK_FUNCTION(3, "I2SOUT_DAT"),
+               MTK_FUNCTION(4, "PCM0_DO"),
+               MTK_FUNCTION(6, "VDEC_TEST_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(190, "SRCLKENAI"),
+               "K5", "mt8135",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO190"),
+               MTK_FUNCTION(1, "SRCLKENAI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(191, "URXD3"),
+               "C3", "mt8135",
+               MTK_EINT_FUNCTION(2, 87),
+               MTK_FUNCTION(0, "GPIO191"),
+               MTK_FUNCTION(1, "URXD3"),
+               MTK_FUNCTION(2, "EINT87"),
+               MTK_FUNCTION(3, "UTXD3"),
+               MTK_FUNCTION(5, "TS_AUX_ST"),
+               MTK_FUNCTION(6, "PWM4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(192, "UTXD3"),
+               "B2", "mt8135",
+               MTK_EINT_FUNCTION(2, 86),
+               MTK_FUNCTION(0, "GPIO192"),
+               MTK_FUNCTION(1, "UTXD3"),
+               MTK_FUNCTION(2, "EINT86"),
+               MTK_FUNCTION(3, "URXD3"),
+               MTK_FUNCTION(5, "TS_AUX_CS_B"),
+               MTK_FUNCTION(6, "PWM3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(193, "SDA2"),
+               "G2", "mt8135",
+               MTK_EINT_FUNCTION(2, 95),
+               MTK_FUNCTION(0, "GPIO193"),
+               MTK_FUNCTION(1, "SDA2"),
+               MTK_FUNCTION(2, "EINT95"),
+               MTK_FUNCTION(3, "CLKM5"),
+               MTK_FUNCTION(4, "PWM5"),
+               MTK_FUNCTION(5, "TS_AUX_PWDB")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(194, "SCL2"),
+               "F4", "mt8135",
+               MTK_EINT_FUNCTION(2, 94),
+               MTK_FUNCTION(0, "GPIO194"),
+               MTK_FUNCTION(1, "SCL2"),
+               MTK_FUNCTION(2, "EINT94"),
+               MTK_FUNCTION(3, "CLKM4"),
+               MTK_FUNCTION(4, "PWM4"),
+               MTK_FUNCTION(5, "TS_AUXADC_TEST_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(195, "SDA1"),
+               "F2", "mt8135",
+               MTK_EINT_FUNCTION(2, 93),
+               MTK_FUNCTION(0, "GPIO195"),
+               MTK_FUNCTION(1, "SDA1"),
+               MTK_FUNCTION(2, "EINT93"),
+               MTK_FUNCTION(3, "CLKM3"),
+               MTK_FUNCTION(4, "PWM3"),
+               MTK_FUNCTION(5, "TS_AUX_SCLK_PWDB")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(196, "SCL1"),
+               "F3", "mt8135",
+               MTK_EINT_FUNCTION(2, 92),
+               MTK_FUNCTION(0, "GPIO196"),
+               MTK_FUNCTION(1, "SCL1"),
+               MTK_FUNCTION(2, "EINT92"),
+               MTK_FUNCTION(3, "CLKM2"),
+               MTK_FUNCTION(4, "PWM2"),
+               MTK_FUNCTION(5, "TS_AUX_DIN")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(197, "MSDC3_DAT2"),
+               "E1", "mt8135",
+               MTK_EINT_FUNCTION(2, 71),
+               MTK_FUNCTION(0, "GPIO197"),
+               MTK_FUNCTION(1, "MSDC3_DAT2"),
+               MTK_FUNCTION(2, "EINT71"),
+               MTK_FUNCTION(3, "SCL6"),
+               MTK_FUNCTION(4, "PWM5"),
+               MTK_FUNCTION(5, "CLKM4"),
+               MTK_FUNCTION(6, "MFG_TEST_CK_2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(198, "MSDC3_DAT3"),
+               "C2", "mt8135",
+               MTK_EINT_FUNCTION(2, 72),
+               MTK_FUNCTION(0, "GPIO198"),
+               MTK_FUNCTION(1, "MSDC3_DAT3"),
+               MTK_FUNCTION(2, "EINT72"),
+               MTK_FUNCTION(3, "SDA6"),
+               MTK_FUNCTION(4, "PWM6"),
+               MTK_FUNCTION(5, "CLKM5"),
+               MTK_FUNCTION(6, "MFG_TEST_CK_3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(199, "MSDC3_CMD"),
+               "D2", "mt8135",
+               MTK_EINT_FUNCTION(2, 68),
+               MTK_FUNCTION(0, "GPIO199"),
+               MTK_FUNCTION(1, "MSDC3_CMD"),
+               MTK_FUNCTION(2, "EINT68"),
+               MTK_FUNCTION(3, "SDA2"),
+               MTK_FUNCTION(4, "PWM2"),
+               MTK_FUNCTION(5, "CLKM1"),
+               MTK_FUNCTION(6, "MFG_TEST_CK_4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(200, "MSDC3_CLK"),
+               "E2", "mt8135",
+               MTK_EINT_FUNCTION(2, 67),
+               MTK_FUNCTION(0, "GPIO200"),
+               MTK_FUNCTION(1, "MSDC3_CLK"),
+               MTK_FUNCTION(2, "EINT67"),
+               MTK_FUNCTION(3, "SCL2"),
+               MTK_FUNCTION(4, "PWM1"),
+               MTK_FUNCTION(5, "CLKM0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(201, "MSDC3_DAT1"),
+               "D3", "mt8135",
+               MTK_EINT_FUNCTION(2, 70),
+               MTK_FUNCTION(0, "GPIO201"),
+               MTK_FUNCTION(1, "MSDC3_DAT1"),
+               MTK_FUNCTION(2, "EINT70"),
+               MTK_FUNCTION(3, "SDA3"),
+               MTK_FUNCTION(4, "PWM4"),
+               MTK_FUNCTION(5, "CLKM3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(202, "MSDC3_DAT0"),
+               "E3", "mt8135",
+               MTK_EINT_FUNCTION(2, 69),
+               MTK_FUNCTION(0, "GPIO202"),
+               MTK_FUNCTION(1, "MSDC3_DAT0"),
+               MTK_FUNCTION(2, "EINT69"),
+               MTK_FUNCTION(3, "SCL3"),
+               MTK_FUNCTION(4, "PWM3"),
+               MTK_FUNCTION(5, "CLKM2")
+       ),
+};
+
+#endif /* __PINCTRL_MTK_MT8135_H */
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h
new file mode 100644 (file)
index 0000000..13e5b68
--- /dev/null
@@ -0,0 +1,1226 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Hongzhou.Yang <hongzhou.yang@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 __PINCTRL_MTK_MT8173_H
+#define __PINCTRL_MTK_MT8173_H
+
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-mtk-common.h"
+
+static const struct mtk_desc_pin mtk_pins_mt8173[] = {
+       MTK_PIN(
+               PINCTRL_PIN(0, "EINT0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 0),
+               MTK_FUNCTION(0, "GPIO0"),
+               MTK_FUNCTION(1, "IRDA_PDN"),
+               MTK_FUNCTION(2, "I2S1_WS"),
+               MTK_FUNCTION(3, "AUD_SPDIF"),
+               MTK_FUNCTION(4, "UTXD0"),
+               MTK_FUNCTION(7, "DBG_MON_A_20_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(1, "EINT1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 1),
+               MTK_FUNCTION(0, "GPIO1"),
+               MTK_FUNCTION(1, "IRDA_RXD"),
+               MTK_FUNCTION(2, "I2S1_BCK"),
+               MTK_FUNCTION(3, "SDA5"),
+               MTK_FUNCTION(4, "URXD0"),
+               MTK_FUNCTION(7, "DBG_MON_A_21_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(2, "EINT2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 2),
+               MTK_FUNCTION(0, "GPIO2"),
+               MTK_FUNCTION(1, "IRDA_TXD"),
+               MTK_FUNCTION(2, "I2S1_MCK"),
+               MTK_FUNCTION(3, "SCL5"),
+               MTK_FUNCTION(4, "UTXD3"),
+               MTK_FUNCTION(7, "DBG_MON_A_22_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(3, "EINT3"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 3),
+               MTK_FUNCTION(0, "GPIO3"),
+               MTK_FUNCTION(1, "DSI1_TE"),
+               MTK_FUNCTION(2, "I2S1_DO_1"),
+               MTK_FUNCTION(3, "SDA3"),
+               MTK_FUNCTION(4, "URXD3"),
+               MTK_FUNCTION(7, "DBG_MON_A_23_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(4, "EINT4"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 4),
+               MTK_FUNCTION(0, "GPIO4"),
+               MTK_FUNCTION(1, "DISP_PWM1"),
+               MTK_FUNCTION(2, "I2S1_DO_2"),
+               MTK_FUNCTION(3, "SCL3"),
+               MTK_FUNCTION(4, "UCTS3"),
+               MTK_FUNCTION(6, "SFWP_B")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(5, "EINT5"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 5),
+               MTK_FUNCTION(0, "GPIO5"),
+               MTK_FUNCTION(1, "PCM1_CLK"),
+               MTK_FUNCTION(2, "I2S2_WS"),
+               MTK_FUNCTION(3, "SPI_CK_3_"),
+               MTK_FUNCTION(4, "URTS3"),
+               MTK_FUNCTION(5, "AP_MD32_JTAG_TMS"),
+               MTK_FUNCTION(6, "SFOUT")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(6, "EINT6"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 6),
+               MTK_FUNCTION(0, "GPIO6"),
+               MTK_FUNCTION(1, "PCM1_SYNC"),
+               MTK_FUNCTION(2, "I2S2_BCK"),
+               MTK_FUNCTION(3, "SPI_MI_3_"),
+               MTK_FUNCTION(5, "AP_MD32_JTAG_TCK"),
+               MTK_FUNCTION(6, "SFCS0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(7, "EINT7"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 7),
+               MTK_FUNCTION(0, "GPIO7"),
+               MTK_FUNCTION(1, "PCM1_DI"),
+               MTK_FUNCTION(2, "I2S2_DI_1"),
+               MTK_FUNCTION(3, "SPI_MO_3_"),
+               MTK_FUNCTION(5, "AP_MD32_JTAG_TDI"),
+               MTK_FUNCTION(6, "SFHOLD")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(8, "EINT8"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 8),
+               MTK_FUNCTION(0, "GPIO8"),
+               MTK_FUNCTION(1, "PCM1_DO"),
+               MTK_FUNCTION(2, "I2S2_DI_2"),
+               MTK_FUNCTION(3, "SPI_CS_3_"),
+               MTK_FUNCTION(4, "AUD_SPDIF"),
+               MTK_FUNCTION(5, "AP_MD32_JTAG_TDO"),
+               MTK_FUNCTION(6, "SFIN")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(9, "EINT9"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 9),
+               MTK_FUNCTION(0, "GPIO9"),
+               MTK_FUNCTION(1, "USB_DRVVBUS_P0"),
+               MTK_FUNCTION(2, "I2S2_MCK"),
+               MTK_FUNCTION(4, "USB_DRVVBUS_P1"),
+               MTK_FUNCTION(5, "AP_MD32_JTAG_TRST"),
+               MTK_FUNCTION(6, "SFCK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(10, "EINT10"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 10),
+               MTK_FUNCTION(0, "GPIO10"),
+               MTK_FUNCTION(1, "CLKM0"),
+               MTK_FUNCTION(2, "DSI1_TE"),
+               MTK_FUNCTION(3, "DISP_PWM1"),
+               MTK_FUNCTION(4, "PWM4"),
+               MTK_FUNCTION(5, "IRDA_RXD")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(11, "EINT11"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 11),
+               MTK_FUNCTION(0, "GPIO11"),
+               MTK_FUNCTION(1, "CLKM1"),
+               MTK_FUNCTION(2, "I2S3_WS"),
+               MTK_FUNCTION(3, "USB_DRVVBUS_P0"),
+               MTK_FUNCTION(4, "PWM5"),
+               MTK_FUNCTION(5, "IRDA_TXD"),
+               MTK_FUNCTION(6, "USB_DRVVBUS_P1"),
+               MTK_FUNCTION(7, "DBG_MON_B_30_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(12, "EINT12"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 12),
+               MTK_FUNCTION(0, "GPIO12"),
+               MTK_FUNCTION(1, "CLKM2"),
+               MTK_FUNCTION(2, "I2S3_BCK"),
+               MTK_FUNCTION(3, "SRCLKENA0"),
+               MTK_FUNCTION(5, "I2S2_WS"),
+               MTK_FUNCTION(7, "DBG_MON_B_32_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(13, "EINT13"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 13),
+               MTK_FUNCTION(0, "GPIO13"),
+               MTK_FUNCTION(1, "CLKM3"),
+               MTK_FUNCTION(2, "I2S3_MCK"),
+               MTK_FUNCTION(3, "SRCLKENA0"),
+               MTK_FUNCTION(5, "I2S2_BCK"),
+               MTK_FUNCTION(7, "DBG_MON_A_32_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(14, "EINT14"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 14),
+               MTK_FUNCTION(0, "GPIO14"),
+               MTK_FUNCTION(1, "CMDAT0"),
+               MTK_FUNCTION(2, "CMCSD0"),
+               MTK_FUNCTION(4, "CLKM2"),
+               MTK_FUNCTION(7, "DBG_MON_B_6_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(15, "EINT15"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 15),
+               MTK_FUNCTION(0, "GPIO15"),
+               MTK_FUNCTION(1, "CMDAT1"),
+               MTK_FUNCTION(2, "CMCSD1"),
+               MTK_FUNCTION(3, "CMFLASH"),
+               MTK_FUNCTION(4, "CLKM3"),
+               MTK_FUNCTION(7, "DBG_MON_B_29_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(16, "IDDIG"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 16),
+               MTK_FUNCTION(0, "GPIO16"),
+               MTK_FUNCTION(1, "IDDIG"),
+               MTK_FUNCTION(2, "CMFLASH"),
+               MTK_FUNCTION(4, "PWM5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(17, "WATCHDOG"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 17),
+               MTK_FUNCTION(0, "GPIO17"),
+               MTK_FUNCTION(1, "WATCHDOG_AO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(18, "CEC"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 18),
+               MTK_FUNCTION(0, "GPIO18"),
+               MTK_FUNCTION(1, "CEC")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(19, "HDMISCK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 19),
+               MTK_FUNCTION(0, "GPIO19"),
+               MTK_FUNCTION(1, "HDMISCK"),
+               MTK_FUNCTION(2, "HDCP_SCL")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(20, "HDMISD"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 20),
+               MTK_FUNCTION(0, "GPIO20"),
+               MTK_FUNCTION(1, "HDMISD"),
+               MTK_FUNCTION(2, "HDCP_SDA")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(21, "HTPLG"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 21),
+               MTK_FUNCTION(0, "GPIO21"),
+               MTK_FUNCTION(1, "HTPLG")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(22, "MSDC3_DAT0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 22),
+               MTK_FUNCTION(0, "GPIO22"),
+               MTK_FUNCTION(1, "MSDC3_DAT0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(23, "MSDC3_DAT1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 23),
+               MTK_FUNCTION(0, "GPIO23"),
+               MTK_FUNCTION(1, "MSDC3_DAT1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(24, "MSDC3_DAT2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 24),
+               MTK_FUNCTION(0, "GPIO24"),
+               MTK_FUNCTION(1, "MSDC3_DAT2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(25, "MSDC3_DAT3"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 25),
+               MTK_FUNCTION(0, "GPIO25"),
+               MTK_FUNCTION(1, "MSDC3_DAT3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(26, "MSDC3_CLK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 26),
+               MTK_FUNCTION(0, "GPIO26"),
+               MTK_FUNCTION(1, "MSDC3_CLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(27, "MSDC3_CMD"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 27),
+               MTK_FUNCTION(0, "GPIO27"),
+               MTK_FUNCTION(1, "MSDC3_CMD")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(28, "MSDC3_DSL"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 28),
+               MTK_FUNCTION(0, "GPIO28"),
+               MTK_FUNCTION(1, "MSDC3_DSL")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(29, "UCTS2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 29),
+               MTK_FUNCTION(0, "GPIO29"),
+               MTK_FUNCTION(1, "UCTS2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(30, "URTS2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 30),
+               MTK_FUNCTION(0, "GPIO30"),
+               MTK_FUNCTION(1, "URTS2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(31, "URXD2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 31),
+               MTK_FUNCTION(0, "GPIO31"),
+               MTK_FUNCTION(1, "URXD2"),
+               MTK_FUNCTION(2, "UTXD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(32, "UTXD2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 32),
+               MTK_FUNCTION(0, "GPIO32"),
+               MTK_FUNCTION(1, "UTXD2"),
+               MTK_FUNCTION(2, "URXD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(33, "DAICLK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 33),
+               MTK_FUNCTION(0, "GPIO33"),
+               MTK_FUNCTION(1, " MRG_CLK"),
+               MTK_FUNCTION(2, "PCM0_CLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(34, "DAIPCMIN"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 34),
+               MTK_FUNCTION(0, "GPIO34"),
+               MTK_FUNCTION(1, " MRG_DI"),
+               MTK_FUNCTION(2, "PCM0_DI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(35, "DAIPCMOUT"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 35),
+               MTK_FUNCTION(0, "GPIO35"),
+               MTK_FUNCTION(1, " MRG_DO"),
+               MTK_FUNCTION(2, "PCM0_DO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(36, "DAISYNC"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 36),
+               MTK_FUNCTION(0, "GPIO36"),
+               MTK_FUNCTION(1, " MRG_SYNC"),
+               MTK_FUNCTION(2, "PCM0_SYNC")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(37, "EINT16"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 37),
+               MTK_FUNCTION(0, "GPIO37"),
+               MTK_FUNCTION(1, "USB_DRVVBUS_P0"),
+               MTK_FUNCTION(2, "USB_DRVVBUS_P1"),
+               MTK_FUNCTION(3, "PWM0"),
+               MTK_FUNCTION(4, "PWM1"),
+               MTK_FUNCTION(5, "PWM2"),
+               MTK_FUNCTION(6, "CLKM0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(38, "CONN_RST"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 38),
+               MTK_FUNCTION(0, "GPIO38"),
+               MTK_FUNCTION(1, "USB_DRVVBUS_P0"),
+               MTK_FUNCTION(2, "USB_DRVVBUS_P1"),
+               MTK_FUNCTION(6, "CLKM1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(39, "CM2MCLK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 39),
+               MTK_FUNCTION(0, "GPIO39"),
+               MTK_FUNCTION(1, "CM2MCLK"),
+               MTK_FUNCTION(2, "CMCSD0"),
+               MTK_FUNCTION(7, "DBG_MON_A_17_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(40, "CMPCLK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 40),
+               MTK_FUNCTION(0, "GPIO40"),
+               MTK_FUNCTION(1, "CMPCLK"),
+               MTK_FUNCTION(2, "CMCSK"),
+               MTK_FUNCTION(3, "CMCSD2"),
+               MTK_FUNCTION(7, "DBG_MON_A_18_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(41, "CMMCLK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 41),
+               MTK_FUNCTION(0, "GPIO41"),
+               MTK_FUNCTION(1, "CMMCLK"),
+               MTK_FUNCTION(7, "DBG_MON_A_19_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(42, "DSI_TE"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 42),
+               MTK_FUNCTION(0, "GPIO42"),
+               MTK_FUNCTION(1, "DSI_TE")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(43, "SDA2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 43),
+               MTK_FUNCTION(0, "GPIO43"),
+               MTK_FUNCTION(1, "SDA2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(44, "SCL2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 44),
+               MTK_FUNCTION(0, "GPIO44"),
+               MTK_FUNCTION(1, "SCL2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(45, "SDA0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 45),
+               MTK_FUNCTION(0, "GPIO45"),
+               MTK_FUNCTION(1, "SDA0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(46, "SCL0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 46),
+               MTK_FUNCTION(0, "GPIO46"),
+               MTK_FUNCTION(1, "SCL0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(47, "RDN0_A"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 47),
+               MTK_FUNCTION(0, "GPIO47"),
+               MTK_FUNCTION(1, "CMDAT2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(48, "RDP0_A"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 48),
+               MTK_FUNCTION(0, "GPIO48"),
+               MTK_FUNCTION(1, "CMDAT3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(49, "RDN1_A"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 49),
+               MTK_FUNCTION(0, "GPIO49"),
+               MTK_FUNCTION(1, "CMDAT4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(50, "RDP1_A"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 50),
+               MTK_FUNCTION(0, "GPIO50"),
+               MTK_FUNCTION(1, "CMDAT5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(51, "RCN_A"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 51),
+               MTK_FUNCTION(0, "GPIO51"),
+               MTK_FUNCTION(1, "CMDAT6")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(52, "RCP_A"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 52),
+               MTK_FUNCTION(0, "GPIO52"),
+               MTK_FUNCTION(1, "CMDAT7")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(53, "RDN2_A"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 53),
+               MTK_FUNCTION(0, "GPIO53"),
+               MTK_FUNCTION(1, "CMDAT8"),
+               MTK_FUNCTION(2, "CMCSD3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(54, "RDP2_A"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 54),
+               MTK_FUNCTION(0, "GPIO54"),
+               MTK_FUNCTION(1, "CMDAT9"),
+               MTK_FUNCTION(2, "CMCSD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(55, "RDN3_A"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 55),
+               MTK_FUNCTION(0, "GPIO55"),
+               MTK_FUNCTION(1, "CMHSYNC"),
+               MTK_FUNCTION(2, "CMCSD1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(56, "RDP3_A"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 56),
+               MTK_FUNCTION(0, "GPIO56"),
+               MTK_FUNCTION(1, "CMVSYNC"),
+               MTK_FUNCTION(2, "CMCSD0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(57, "MSDC0_DAT0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 57),
+               MTK_FUNCTION(0, "GPIO57"),
+               MTK_FUNCTION(1, "MSDC0_DAT0"),
+               MTK_FUNCTION(2, "I2S1_WS"),
+               MTK_FUNCTION(7, "DBG_MON_B_7_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(58, "MSDC0_DAT1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 58),
+               MTK_FUNCTION(0, "GPIO58"),
+               MTK_FUNCTION(1, "MSDC0_DAT1"),
+               MTK_FUNCTION(2, "I2S1_BCK"),
+               MTK_FUNCTION(7, "DBG_MON_B_8_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(59, "MSDC0_DAT2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 59),
+               MTK_FUNCTION(0, "GPIO59"),
+               MTK_FUNCTION(1, "MSDC0_DAT2"),
+               MTK_FUNCTION(2, "I2S1_MCK"),
+               MTK_FUNCTION(7, "DBG_MON_B_9_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(60, "MSDC0_DAT3"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 60),
+               MTK_FUNCTION(0, "GPIO60"),
+               MTK_FUNCTION(1, "MSDC0_DAT3"),
+               MTK_FUNCTION(2, "I2S1_DO_1"),
+               MTK_FUNCTION(7, "DBG_MON_B_10_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(61, "MSDC0_DAT4"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 61),
+               MTK_FUNCTION(0, "GPIO61"),
+               MTK_FUNCTION(1, "MSDC0_DAT4"),
+               MTK_FUNCTION(2, "I2S1_DO_2"),
+               MTK_FUNCTION(7, "DBG_MON_B_11_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(62, "MSDC0_DAT5"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 62),
+               MTK_FUNCTION(0, "GPIO62"),
+               MTK_FUNCTION(1, "MSDC0_DAT5"),
+               MTK_FUNCTION(2, "I2S2_WS"),
+               MTK_FUNCTION(7, "DBG_MON_B_12_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(63, "MSDC0_DAT6"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 63),
+               MTK_FUNCTION(0, "GPIO63"),
+               MTK_FUNCTION(1, "MSDC0_DAT6"),
+               MTK_FUNCTION(2, "I2S2_BCK"),
+               MTK_FUNCTION(7, "DBG_MON_B_13_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(64, "MSDC0_DAT7"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 64),
+               MTK_FUNCTION(0, "GPIO64"),
+               MTK_FUNCTION(1, "MSDC0_DAT7"),
+               MTK_FUNCTION(2, "I2S2_DI_1"),
+               MTK_FUNCTION(7, "DBG_MON_B_14_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(65, "MSDC0_CLK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 65),
+               MTK_FUNCTION(0, "GPIO65"),
+               MTK_FUNCTION(1, "MSDC0_CLK"),
+               MTK_FUNCTION(7, "DBG_MON_B_16_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(66, "MSDC0_CMD"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 66),
+               MTK_FUNCTION(0, "GPIO66"),
+               MTK_FUNCTION(1, "MSDC0_CMD"),
+               MTK_FUNCTION(2, "I2S2_DI_2"),
+               MTK_FUNCTION(7, "DBG_MON_B_15_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(67, "MSDC0_DSL"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 67),
+               MTK_FUNCTION(0, "GPIO67"),
+               MTK_FUNCTION(1, "MSDC0_DSL"),
+               MTK_FUNCTION(7, "DBG_MON_B_17_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(68, "MSDC0_RST_"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 68),
+               MTK_FUNCTION(0, "GPIO68"),
+               MTK_FUNCTION(1, "MSDC0_RSTB"),
+               MTK_FUNCTION(2, "I2S2_MCK"),
+               MTK_FUNCTION(7, "DBG_MON_B_18_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(69, "SPI_CK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 69),
+               MTK_FUNCTION(0, "GPIO69"),
+               MTK_FUNCTION(1, "SPI_CK_0_"),
+               MTK_FUNCTION(2, "I2S3_DO_1"),
+               MTK_FUNCTION(3, "PWM0"),
+               MTK_FUNCTION(4, "PWM5"),
+               MTK_FUNCTION(5, "I2S2_MCK"),
+               MTK_FUNCTION(7, "DBG_MON_B_19_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(70, "SPI_MI"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 70),
+               MTK_FUNCTION(0, "GPIO70"),
+               MTK_FUNCTION(1, "SPI_MI_0_"),
+               MTK_FUNCTION(2, "I2S3_DO_2"),
+               MTK_FUNCTION(3, "PWM1"),
+               MTK_FUNCTION(4, "SPI_MO_0_"),
+               MTK_FUNCTION(5, "I2S2_DI_1"),
+               MTK_FUNCTION(6, "DSI1_TE"),
+               MTK_FUNCTION(7, "DBG_MON_B_20_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(71, "SPI_MO"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 71),
+               MTK_FUNCTION(0, "GPIO71"),
+               MTK_FUNCTION(1, "SPI_MO_0_"),
+               MTK_FUNCTION(2, "I2S3_DO_3"),
+               MTK_FUNCTION(3, "PWM2"),
+               MTK_FUNCTION(4, "SPI_MI_0_"),
+               MTK_FUNCTION(5, "I2S2_DI_2"),
+               MTK_FUNCTION(7, "DBG_MON_B_21_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(72, "SPI_CS"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 72),
+               MTK_FUNCTION(0, "GPIO72"),
+               MTK_FUNCTION(1, "SPI_CS_0_"),
+               MTK_FUNCTION(2, "I2S3_DO_4"),
+               MTK_FUNCTION(3, "PWM3"),
+               MTK_FUNCTION(4, "PWM6"),
+               MTK_FUNCTION(5, "DISP_PWM1"),
+               MTK_FUNCTION(7, "DBG_MON_B_22_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(73, "MSDC1_DAT0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 73),
+               MTK_FUNCTION(0, "GPIO73"),
+               MTK_FUNCTION(1, "MSDC1_DAT0"),
+               MTK_FUNCTION(7, "DBG_MON_B_24_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(74, "MSDC1_DAT1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 74),
+               MTK_FUNCTION(0, "GPIO74"),
+               MTK_FUNCTION(1, "MSDC1_DAT1"),
+               MTK_FUNCTION(7, "DBG_MON_B_25_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(75, "MSDC1_DAT2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 75),
+               MTK_FUNCTION(0, "GPIO75"),
+               MTK_FUNCTION(1, "MSDC1_DAT2"),
+               MTK_FUNCTION(7, "DBG_MON_B_26_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(76, "MSDC1_DAT3"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 76),
+               MTK_FUNCTION(0, "GPIO76"),
+               MTK_FUNCTION(1, "MSDC1_DAT3"),
+               MTK_FUNCTION(7, "DBG_MON_B_27_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(77, "MSDC1_CLK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 77),
+               MTK_FUNCTION(0, "GPIO77"),
+               MTK_FUNCTION(1, "MSDC1_CLK"),
+               MTK_FUNCTION(7, "DBG_MON_B_28_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(78, "MSDC1_CMD"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 78),
+               MTK_FUNCTION(0, "GPIO78"),
+               MTK_FUNCTION(1, "MSDC1_CMD"),
+               MTK_FUNCTION(7, "DBG_MON_B_23_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(79, "PWRAP_SPI0_MI"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 79),
+               MTK_FUNCTION(0, "GPIO79"),
+               MTK_FUNCTION(1, "PWRAP_SPIMI"),
+               MTK_FUNCTION(2, "PWRAP_SPIMO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(80, "PWRAP_SPI0_MO"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 80),
+               MTK_FUNCTION(0, "GPIO80"),
+               MTK_FUNCTION(1, "PWRAP_SPIMO"),
+               MTK_FUNCTION(2, "PWRAP_SPIMI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(81, "PWRAP_SPI0_CK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 81),
+               MTK_FUNCTION(0, "GPIO81"),
+               MTK_FUNCTION(1, "PWRAP_SPICK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(82, "PWRAP_SPI0_CSN"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 82),
+               MTK_FUNCTION(0, "GPIO82"),
+               MTK_FUNCTION(1, "PWRAP_SPICS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(83, "AUD_CLK_MOSI"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 83),
+               MTK_FUNCTION(0, "GPIO83"),
+               MTK_FUNCTION(1, "AUD_CLK_MOSI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(84, "AUD_DAT_MISO"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 84),
+               MTK_FUNCTION(0, "GPIO84"),
+               MTK_FUNCTION(1, "AUD_DAT_MISO"),
+               MTK_FUNCTION(2, "AUD_DAT_MOSI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(85, "AUD_DAT_MOSI"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 85),
+               MTK_FUNCTION(0, "GPIO85"),
+               MTK_FUNCTION(1, "AUD_DAT_MOSI"),
+               MTK_FUNCTION(2, "AUD_DAT_MISO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(86, "RTC32K_CK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 86),
+               MTK_FUNCTION(0, "GPIO86"),
+               MTK_FUNCTION(1, "RTC32K_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(87, "DISP_PWM0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 87),
+               MTK_FUNCTION(0, "GPIO87"),
+               MTK_FUNCTION(1, "DISP_PWM0"),
+               MTK_FUNCTION(2, "DISP_PWM1"),
+               MTK_FUNCTION(7, "DBG_MON_B_31_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(88, "SRCLKENAI"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 88),
+               MTK_FUNCTION(0, "GPIO88"),
+               MTK_FUNCTION(1, "SRCLKENAI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(89, "SRCLKENAI2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 89),
+               MTK_FUNCTION(0, "GPIO89"),
+               MTK_FUNCTION(1, "SRCLKENAI2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(90, "SRCLKENA0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 90),
+               MTK_FUNCTION(0, "GPIO90"),
+               MTK_FUNCTION(1, "SRCLKENA0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(91, "SRCLKENA1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 91),
+               MTK_FUNCTION(0, "GPIO91"),
+               MTK_FUNCTION(1, "SRCLKENA1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(92, "PCM_CLK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 92),
+               MTK_FUNCTION(0, "GPIO92"),
+               MTK_FUNCTION(1, "PCM1_CLK"),
+               MTK_FUNCTION(2, "I2S0_BCK"),
+               MTK_FUNCTION(7, "DBG_MON_A_24_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(93, "PCM_SYNC"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 93),
+               MTK_FUNCTION(0, "GPIO93"),
+               MTK_FUNCTION(1, "PCM1_SYNC"),
+               MTK_FUNCTION(2, "I2S0_WS"),
+               MTK_FUNCTION(7, "DBG_MON_A_25_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(94, "PCM_RX"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 94),
+               MTK_FUNCTION(0, "GPIO94"),
+               MTK_FUNCTION(1, "PCM1_DI"),
+               MTK_FUNCTION(2, "I2S0_DI"),
+               MTK_FUNCTION(7, "DBG_MON_A_26_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(95, "PCM_TX"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 95),
+               MTK_FUNCTION(0, "GPIO95"),
+               MTK_FUNCTION(1, "PCM1_DO"),
+               MTK_FUNCTION(2, "I2S0_DO"),
+               MTK_FUNCTION(7, "DBG_MON_A_27_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(96, "URXD1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 96),
+               MTK_FUNCTION(0, "GPIO96"),
+               MTK_FUNCTION(1, "URXD1"),
+               MTK_FUNCTION(2, "UTXD1"),
+               MTK_FUNCTION(7, "DBG_MON_A_28_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(97, "UTXD1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 97),
+               MTK_FUNCTION(0, "GPIO97"),
+               MTK_FUNCTION(1, "UTXD1"),
+               MTK_FUNCTION(2, "URXD1"),
+               MTK_FUNCTION(7, "DBG_MON_A_29_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(98, "URTS1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 98),
+               MTK_FUNCTION(0, "GPIO98"),
+               MTK_FUNCTION(1, "URTS1"),
+               MTK_FUNCTION(2, "UCTS1"),
+               MTK_FUNCTION(7, "DBG_MON_A_30_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(99, "UCTS1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 99),
+               MTK_FUNCTION(0, "GPIO99"),
+               MTK_FUNCTION(1, "UCTS1"),
+               MTK_FUNCTION(2, "URTS1"),
+               MTK_FUNCTION(7, "DBG_MON_A_31_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(100, "MSDC2_DAT0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 100),
+               MTK_FUNCTION(0, "GPIO100"),
+               MTK_FUNCTION(1, "MSDC2_DAT0"),
+               MTK_FUNCTION(3, "USB_DRVVBUS_P0"),
+               MTK_FUNCTION(4, "SDA5"),
+               MTK_FUNCTION(5, "USB_DRVVBUS_P1"),
+               MTK_FUNCTION(7, "DBG_MON_B_0_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(101, "MSDC2_DAT1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 101),
+               MTK_FUNCTION(0, "GPIO101"),
+               MTK_FUNCTION(1, "MSDC2_DAT1"),
+               MTK_FUNCTION(3, "AUD_SPDIF"),
+               MTK_FUNCTION(4, "SCL5"),
+               MTK_FUNCTION(7, "DBG_MON_B_1_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(102, "MSDC2_DAT2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 102),
+               MTK_FUNCTION(0, "GPIO102"),
+               MTK_FUNCTION(1, "MSDC2_DAT2"),
+               MTK_FUNCTION(3, "UTXD0"),
+               MTK_FUNCTION(5, "PWM0"),
+               MTK_FUNCTION(6, "SPI_CK_1_"),
+               MTK_FUNCTION(7, "DBG_MON_B_2_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(103, "MSDC2_DAT3"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 103),
+               MTK_FUNCTION(0, "GPIO103"),
+               MTK_FUNCTION(1, "MSDC2_DAT3"),
+               MTK_FUNCTION(3, "URXD0"),
+               MTK_FUNCTION(5, "PWM1"),
+               MTK_FUNCTION(6, "SPI_MI_1_"),
+               MTK_FUNCTION(7, "DBG_MON_B_3_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(104, "MSDC2_CLK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 104),
+               MTK_FUNCTION(0, "GPIO104"),
+               MTK_FUNCTION(1, "MSDC2_CLK"),
+               MTK_FUNCTION(3, "UTXD3"),
+               MTK_FUNCTION(4, "SDA3"),
+               MTK_FUNCTION(5, "PWM2"),
+               MTK_FUNCTION(6, "SPI_MO_1_"),
+               MTK_FUNCTION(7, "DBG_MON_B_4_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(105, "MSDC2_CMD"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 105),
+               MTK_FUNCTION(0, "GPIO105"),
+               MTK_FUNCTION(1, "MSDC2_CMD"),
+               MTK_FUNCTION(3, "URXD3"),
+               MTK_FUNCTION(4, "SCL3"),
+               MTK_FUNCTION(5, "PWM3"),
+               MTK_FUNCTION(6, "SPI_CS_1_"),
+               MTK_FUNCTION(7, "DBG_MON_B_5_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(106, "SDA3"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 106),
+               MTK_FUNCTION(0, "GPIO106"),
+               MTK_FUNCTION(1, "SDA3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(107, "SCL3"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 107),
+               MTK_FUNCTION(0, "GPIO107"),
+               MTK_FUNCTION(1, "SCL3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(108, "JTMS"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 108),
+               MTK_FUNCTION(0, "GPIO108"),
+               MTK_FUNCTION(1, "JTMS"),
+               MTK_FUNCTION(2, " MFG_JTAG_TMS"),
+               MTK_FUNCTION(5, "AP_MD32_JTAG_TMS"),
+               MTK_FUNCTION(6, "DFD_TMS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(109, "JTCK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 109),
+               MTK_FUNCTION(0, "GPIO109"),
+               MTK_FUNCTION(1, "JTCK"),
+               MTK_FUNCTION(2, " MFG_JTAG_TCK"),
+               MTK_FUNCTION(5, "AP_MD32_JTAG_TCK"),
+               MTK_FUNCTION(6, "DFD_TCK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(110, "JTDI"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 110),
+               MTK_FUNCTION(0, "GPIO110"),
+               MTK_FUNCTION(1, "JTDI"),
+               MTK_FUNCTION(2, " MFG_JTAG_TDI"),
+               MTK_FUNCTION(5, "AP_MD32_JTAG_TDI"),
+               MTK_FUNCTION(6, "DFD_TDI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(111, "JTDO"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 111),
+               MTK_FUNCTION(0, "GPIO111"),
+               MTK_FUNCTION(1, "JTDO"),
+               MTK_FUNCTION(2, "MFG_JTAG_TDO"),
+               MTK_FUNCTION(5, "AP_MD32_JTAG_TDO"),
+               MTK_FUNCTION(6, "DFD_TDO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(112, "JTRST_B"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 112),
+               MTK_FUNCTION(0, "GPIO112"),
+               MTK_FUNCTION(1, "JTRST_B"),
+               MTK_FUNCTION(2, " MFG_JTAG_TRSTN"),
+               MTK_FUNCTION(5, "AP_MD32_JTAG_TRST"),
+               MTK_FUNCTION(6, "DFD_NTRST")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(113, "URXD0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 113),
+               MTK_FUNCTION(0, "GPIO113"),
+               MTK_FUNCTION(1, "URXD0"),
+               MTK_FUNCTION(2, "UTXD0"),
+               MTK_FUNCTION(6, "I2S2_WS"),
+               MTK_FUNCTION(7, "DBG_MON_A_0_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(114, "UTXD0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 114),
+               MTK_FUNCTION(0, "GPIO114"),
+               MTK_FUNCTION(1, "UTXD0"),
+               MTK_FUNCTION(2, "URXD0"),
+               MTK_FUNCTION(6, "I2S2_BCK"),
+               MTK_FUNCTION(7, "DBG_MON_A_1_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(115, "URTS0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 115),
+               MTK_FUNCTION(0, "GPIO115"),
+               MTK_FUNCTION(1, "URTS0"),
+               MTK_FUNCTION(2, "UCTS0"),
+               MTK_FUNCTION(6, "I2S2_MCK"),
+               MTK_FUNCTION(7, "DBG_MON_A_2_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(116, "UCTS0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 116),
+               MTK_FUNCTION(0, "GPIO116"),
+               MTK_FUNCTION(1, "UCTS0"),
+               MTK_FUNCTION(2, "URTS0"),
+               MTK_FUNCTION(6, "I2S2_DI_1"),
+               MTK_FUNCTION(7, "DBG_MON_A_3_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(117, "URXD3"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 117),
+               MTK_FUNCTION(0, "GPIO117"),
+               MTK_FUNCTION(1, "URXD3"),
+               MTK_FUNCTION(2, "UTXD3"),
+               MTK_FUNCTION(7, "DBG_MON_A_9_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(118, "UTXD3"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 118),
+               MTK_FUNCTION(0, "GPIO118"),
+               MTK_FUNCTION(1, "UTXD3"),
+               MTK_FUNCTION(2, "URXD3"),
+               MTK_FUNCTION(7, "DBG_MON_A_10_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(119, "KPROW0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 119),
+               MTK_FUNCTION(0, "GPIO119"),
+               MTK_FUNCTION(1, "KROW0"),
+               MTK_FUNCTION(7, "DBG_MON_A_11_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(120, "KPROW1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 120),
+               MTK_FUNCTION(0, "GPIO120"),
+               MTK_FUNCTION(1, "KROW1"),
+               MTK_FUNCTION(3, "PWM6"),
+               MTK_FUNCTION(7, "DBG_MON_A_12_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(121, "KPROW2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 121),
+               MTK_FUNCTION(0, "GPIO121"),
+               MTK_FUNCTION(1, "KROW2"),
+               MTK_FUNCTION(2, "IRDA_PDN"),
+               MTK_FUNCTION(3, "USB_DRVVBUS_P0"),
+               MTK_FUNCTION(4, "PWM4"),
+               MTK_FUNCTION(5, "USB_DRVVBUS_P1"),
+               MTK_FUNCTION(7, "DBG_MON_A_13_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(122, "KPCOL0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 122),
+               MTK_FUNCTION(0, "GPIO122"),
+               MTK_FUNCTION(1, "KCOL0"),
+               MTK_FUNCTION(7, "DBG_MON_A_14_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(123, "KPCOL1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 123),
+               MTK_FUNCTION(0, "GPIO123"),
+               MTK_FUNCTION(1, "KCOL1"),
+               MTK_FUNCTION(2, "IRDA_RXD"),
+               MTK_FUNCTION(3, "PWM5"),
+               MTK_FUNCTION(7, "DBG_MON_A_15_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(124, "KPCOL2"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 124),
+               MTK_FUNCTION(0, "GPIO124"),
+               MTK_FUNCTION(1, "KCOL2"),
+               MTK_FUNCTION(2, "IRDA_TXD"),
+               MTK_FUNCTION(3, "USB_DRVVBUS_P0"),
+               MTK_FUNCTION(4, "PWM3"),
+               MTK_FUNCTION(5, "USB_DRVVBUS_P1"),
+               MTK_FUNCTION(7, "DBG_MON_A_16_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(125, "SDA1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 125),
+               MTK_FUNCTION(0, "GPIO125"),
+               MTK_FUNCTION(1, "SDA1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(126, "SCL1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 126),
+               MTK_FUNCTION(0, "GPIO126"),
+               MTK_FUNCTION(1, "SCL1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(127, "LCM_RST"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 127),
+               MTK_FUNCTION(0, "GPIO127"),
+               MTK_FUNCTION(1, "LCM_RST")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(128, "I2S0_LRCK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 128),
+               MTK_FUNCTION(0, "GPIO128"),
+               MTK_FUNCTION(1, "I2S0_WS"),
+               MTK_FUNCTION(2, "I2S1_WS"),
+               MTK_FUNCTION(3, "I2S2_WS"),
+               MTK_FUNCTION(5, "SPI_CK_2_"),
+               MTK_FUNCTION(7, "DBG_MON_A_4_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(129, "I2S0_BCK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 129),
+               MTK_FUNCTION(0, "GPIO129"),
+               MTK_FUNCTION(1, "I2S0_BCK"),
+               MTK_FUNCTION(2, "I2S1_BCK"),
+               MTK_FUNCTION(3, "I2S2_BCK"),
+               MTK_FUNCTION(5, "SPI_MI_2_"),
+               MTK_FUNCTION(7, "DBG_MON_A_5_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(130, "I2S0_MCK"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 130),
+               MTK_FUNCTION(0, "GPIO130"),
+               MTK_FUNCTION(1, "I2S0_MCK"),
+               MTK_FUNCTION(2, "I2S1_MCK"),
+               MTK_FUNCTION(3, "I2S2_MCK"),
+               MTK_FUNCTION(5, "SPI_MO_2_"),
+               MTK_FUNCTION(7, "DBG_MON_A_6_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(131, "I2S0_DATA0"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 131),
+               MTK_FUNCTION(0, "GPIO131"),
+               MTK_FUNCTION(1, "I2S0_DO"),
+               MTK_FUNCTION(2, "I2S1_DO_1"),
+               MTK_FUNCTION(3, "I2S2_DI_1"),
+               MTK_FUNCTION(5, "SPI_CS_2_"),
+               MTK_FUNCTION(7, "DBG_MON_A_7_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(132, "I2S0_DATA1"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 132),
+               MTK_FUNCTION(0, "GPIO132"),
+               MTK_FUNCTION(1, "I2S0_DI"),
+               MTK_FUNCTION(2, "I2S1_DO_2"),
+               MTK_FUNCTION(3, "I2S2_DI_2"),
+               MTK_FUNCTION(7, "DBG_MON_A_8_")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(133, "SDA4"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 133),
+               MTK_FUNCTION(0, "GPIO133"),
+               MTK_FUNCTION(1, "SDA4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(134, "SCL4"),
+               NULL, "mt8173",
+               MTK_EINT_FUNCTION(0, 134),
+               MTK_FUNCTION(0, "GPIO134"),
+               MTK_FUNCTION(1, "SCL4")
+       ),
+};
+
+#endif /* __PINCTRL_MTK_MT8173_H */
index eafc216067a4e8ac0ec42fa2a8a7e7a235e1453e..c751d22fdf29f6e53c8f97223b0a53232a6c7f50 100644 (file)
@@ -1,2 +1,2 @@
-obj-y  += pinctrl-meson8.o
+obj-y  += pinctrl-meson8.o pinctrl-meson8b.o
 obj-y  += pinctrl-meson.o
index a2bf49ce16e702870fe9b5eccf2146b86705c190..edcd140e089968e0f7b95fef4ffcd82f157f8294 100644 (file)
@@ -13,8 +13,9 @@
 
 /*
  * The available pins are organized in banks (A,B,C,D,E,X,Y,Z,AO,
- * BOOT,CARD for meson6 and X,Y,DV,H,Z,AO,BOOT,CARD for meson8) and
- * each bank has a variable number of pins.
+ * BOOT,CARD for meson6, X,Y,DV,H,Z,AO,BOOT,CARD for meson8 and
+ * X,Y,DV,H,AO,BOOT,CARD,DIF for meson8b) and each bank has a
+ * variable number of pins.
  *
  * The AO bank is special because it belongs to the Always-On power
  * domain which can't be powered off; the bank also uses a set of
@@ -544,6 +545,10 @@ static const struct of_device_id meson_pinctrl_dt_match[] = {
                .compatible = "amlogic,meson8-pinctrl",
                .data = &meson8_pinctrl_data,
        },
+       {
+               .compatible = "amlogic,meson8b-pinctrl",
+               .data = &meson8b_pinctrl_data,
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, meson_pinctrl_dt_match);
index bfea8adc79534bb14282a9aa1d2d2a4d5647ed71..0fe7d53849ce09834b72691f0f0bcf74ecc953b8 100644 (file)
@@ -155,6 +155,8 @@ struct meson_pinctrl {
        struct meson_domain *domains;
 };
 
+#define PIN(x, b)      (b + x)
+
 #define GROUP(grp, r, b)                                               \
        {                                                               \
                .name = #grp,                                           \
@@ -165,10 +167,10 @@ struct meson_pinctrl {
                .domain = 0,                                            \
         }
 
-#define GPIO_GROUP(gpio)                                               \
+#define GPIO_GROUP(gpio, b)                                            \
        {                                                               \
                .name = #gpio,                                          \
-               .pins = (const unsigned int[]){ PIN_ ## gpio},          \
+               .pins = (const unsigned int[]){ PIN(gpio, b) },         \
                .num_pins = 1,                                          \
                .is_gpio = true,                                        \
         }
@@ -204,6 +206,7 @@ struct meson_pinctrl {
                },                                                      \
         }
 
-#define MESON_PIN(x) PINCTRL_PIN(PIN_ ## x, #x)
+#define MESON_PIN(x, b) PINCTRL_PIN(PIN(x, b), #x)
 
 extern struct meson_pinctrl_data meson8_pinctrl_data;
+extern struct meson_pinctrl_data meson8b_pinctrl_data;
index f8aa3a28176730c0e2d73ed927b9fd604b77ac4b..7b1cc91733efaf6a5def1fc951660d7209eebf3a 100644 (file)
 #include <dt-bindings/gpio/meson8-gpio.h>
 #include "pinctrl-meson.h"
 
-#define AO_OFFSET      120
-
-#define PIN_GPIOX_0    GPIOX_0
-#define PIN_GPIOX_1    GPIOX_1
-#define PIN_GPIOX_2    GPIOX_2
-#define PIN_GPIOX_3    GPIOX_3
-#define PIN_GPIOX_4    GPIOX_4
-#define PIN_GPIOX_5    GPIOX_5
-#define PIN_GPIOX_6    GPIOX_6
-#define PIN_GPIOX_7    GPIOX_7
-#define PIN_GPIOX_8    GPIOX_8
-#define PIN_GPIOX_9    GPIOX_9
-#define PIN_GPIOX_10   GPIOX_10
-#define PIN_GPIOX_11   GPIOX_11
-#define PIN_GPIOX_12   GPIOX_12
-#define PIN_GPIOX_13   GPIOX_13
-#define PIN_GPIOX_14   GPIOX_14
-#define PIN_GPIOX_15   GPIOX_15
-#define PIN_GPIOX_16   GPIOX_16
-#define PIN_GPIOX_17   GPIOX_17
-#define PIN_GPIOX_18   GPIOX_18
-#define PIN_GPIOX_19   GPIOX_19
-#define PIN_GPIOX_20   GPIOX_20
-#define PIN_GPIOX_21   GPIOX_21
-#define PIN_GPIOY_0    GPIOY_0
-#define PIN_GPIOY_1    GPIOY_1
-#define PIN_GPIOY_2    GPIOY_2
-#define PIN_GPIOY_3    GPIOY_3
-#define PIN_GPIOY_4    GPIOY_4
-#define PIN_GPIOY_5    GPIOY_5
-#define PIN_GPIOY_6    GPIOY_6
-#define PIN_GPIOY_7    GPIOY_7
-#define PIN_GPIOY_8    GPIOY_8
-#define PIN_GPIOY_9    GPIOY_9
-#define PIN_GPIOY_10   GPIOY_10
-#define PIN_GPIOY_11   GPIOY_11
-#define PIN_GPIOY_12   GPIOY_12
-#define PIN_GPIOY_13   GPIOY_13
-#define PIN_GPIOY_14   GPIOY_14
-#define PIN_GPIOY_15   GPIOY_15
-#define PIN_GPIOY_16   GPIOY_16
-#define PIN_GPIODV_0   GPIODV_0
-#define PIN_GPIODV_1   GPIODV_1
-#define PIN_GPIODV_2   GPIODV_2
-#define PIN_GPIODV_3   GPIODV_3
-#define PIN_GPIODV_4   GPIODV_4
-#define PIN_GPIODV_5   GPIODV_5
-#define PIN_GPIODV_6   GPIODV_6
-#define PIN_GPIODV_7   GPIODV_7
-#define PIN_GPIODV_8   GPIODV_8
-#define PIN_GPIODV_9   GPIODV_9
-#define PIN_GPIODV_10  GPIODV_10
-#define PIN_GPIODV_11  GPIODV_11
-#define PIN_GPIODV_12  GPIODV_12
-#define PIN_GPIODV_13  GPIODV_13
-#define PIN_GPIODV_14  GPIODV_14
-#define PIN_GPIODV_15  GPIODV_15
-#define PIN_GPIODV_16  GPIODV_16
-#define PIN_GPIODV_17  GPIODV_17
-#define PIN_GPIODV_18  GPIODV_18
-#define PIN_GPIODV_19  GPIODV_19
-#define PIN_GPIODV_20  GPIODV_20
-#define PIN_GPIODV_21  GPIODV_21
-#define PIN_GPIODV_22  GPIODV_22
-#define PIN_GPIODV_23  GPIODV_23
-#define PIN_GPIODV_24  GPIODV_24
-#define PIN_GPIODV_25  GPIODV_25
-#define PIN_GPIODV_26  GPIODV_26
-#define PIN_GPIODV_27  GPIODV_27
-#define PIN_GPIODV_28  GPIODV_28
-#define PIN_GPIODV_29  GPIODV_29
-#define PIN_GPIOH_0    GPIOH_0
-#define PIN_GPIOH_1    GPIOH_1
-#define PIN_GPIOH_2    GPIOH_2
-#define PIN_GPIOH_3    GPIOH_3
-#define PIN_GPIOH_4    GPIOH_4
-#define PIN_GPIOH_5    GPIOH_5
-#define PIN_GPIOH_6    GPIOH_6
-#define PIN_GPIOH_7    GPIOH_7
-#define PIN_GPIOH_8    GPIOH_8
-#define PIN_GPIOH_9    GPIOH_9
-#define PIN_GPIOZ_0    GPIOZ_0
-#define PIN_GPIOZ_1    GPIOZ_1
-#define PIN_GPIOZ_2    GPIOZ_2
-#define PIN_GPIOZ_3    GPIOZ_3
-#define PIN_GPIOZ_4    GPIOZ_4
-#define PIN_GPIOZ_5    GPIOZ_5
-#define PIN_GPIOZ_6    GPIOZ_6
-#define PIN_GPIOZ_7    GPIOZ_7
-#define PIN_GPIOZ_8    GPIOZ_8
-#define PIN_GPIOZ_9    GPIOZ_9
-#define PIN_GPIOZ_10   GPIOZ_10
-#define PIN_GPIOZ_11   GPIOZ_11
-#define PIN_GPIOZ_12   GPIOZ_12
-#define PIN_GPIOZ_13   GPIOZ_13
-#define PIN_GPIOZ_14   GPIOZ_14
-#define PIN_CARD_0     CARD_0
-#define PIN_CARD_1     CARD_1
-#define PIN_CARD_2     CARD_2
-#define PIN_CARD_3     CARD_3
-#define PIN_CARD_4     CARD_4
-#define PIN_CARD_5     CARD_5
-#define PIN_CARD_6     CARD_6
-#define PIN_BOOT_0     BOOT_0
-#define PIN_BOOT_1     BOOT_1
-#define PIN_BOOT_2     BOOT_2
-#define PIN_BOOT_3     BOOT_3
-#define PIN_BOOT_4     BOOT_4
-#define PIN_BOOT_5     BOOT_5
-#define PIN_BOOT_6     BOOT_6
-#define PIN_BOOT_7     BOOT_7
-#define PIN_BOOT_8     BOOT_8
-#define PIN_BOOT_9     BOOT_9
-#define PIN_BOOT_10    BOOT_10
-#define PIN_BOOT_11    BOOT_11
-#define PIN_BOOT_12    BOOT_12
-#define PIN_BOOT_13    BOOT_13
-#define PIN_BOOT_14    BOOT_14
-#define PIN_BOOT_15    BOOT_15
-#define PIN_BOOT_16    BOOT_16
-#define PIN_BOOT_17    BOOT_17
-#define PIN_BOOT_18    BOOT_18
-
-#define PIN_GPIOAO_0   (AO_OFFSET + GPIOAO_0)
-#define PIN_GPIOAO_1   (AO_OFFSET + GPIOAO_1)
-#define PIN_GPIOAO_2   (AO_OFFSET + GPIOAO_2)
-#define PIN_GPIOAO_3   (AO_OFFSET + GPIOAO_3)
-#define PIN_GPIOAO_4   (AO_OFFSET + GPIOAO_4)
-#define PIN_GPIOAO_5   (AO_OFFSET + GPIOAO_5)
-#define PIN_GPIOAO_6   (AO_OFFSET + GPIOAO_6)
-#define PIN_GPIOAO_7   (AO_OFFSET + GPIOAO_7)
-#define PIN_GPIOAO_8   (AO_OFFSET + GPIOAO_8)
-#define PIN_GPIOAO_9   (AO_OFFSET + GPIOAO_9)
-#define PIN_GPIOAO_10  (AO_OFFSET + GPIOAO_10)
-#define PIN_GPIOAO_11  (AO_OFFSET + GPIOAO_11)
-#define PIN_GPIOAO_12  (AO_OFFSET + GPIOAO_12)
-#define PIN_GPIOAO_13  (AO_OFFSET + GPIOAO_13)
-#define PIN_GPIO_BSD_EN        (AO_OFFSET + GPIO_BSD_EN)
-#define PIN_GPIO_TEST_N        (AO_OFFSET + GPIO_TEST_N)
+#define AO_OFF 120
 
 static const struct pinctrl_pin_desc meson8_pins[] = {
-       MESON_PIN(GPIOX_0),
-       MESON_PIN(GPIOX_1),
-       MESON_PIN(GPIOX_2),
-       MESON_PIN(GPIOX_3),
-       MESON_PIN(GPIOX_4),
-       MESON_PIN(GPIOX_5),
-       MESON_PIN(GPIOX_6),
-       MESON_PIN(GPIOX_7),
-       MESON_PIN(GPIOX_8),
-       MESON_PIN(GPIOX_9),
-       MESON_PIN(GPIOX_10),
-       MESON_PIN(GPIOX_11),
-       MESON_PIN(GPIOX_12),
-       MESON_PIN(GPIOX_13),
-       MESON_PIN(GPIOX_14),
-       MESON_PIN(GPIOX_15),
-       MESON_PIN(GPIOX_16),
-       MESON_PIN(GPIOX_17),
-       MESON_PIN(GPIOX_18),
-       MESON_PIN(GPIOX_19),
-       MESON_PIN(GPIOX_20),
-       MESON_PIN(GPIOX_21),
-       MESON_PIN(GPIOY_0),
-       MESON_PIN(GPIOY_1),
-       MESON_PIN(GPIOY_2),
-       MESON_PIN(GPIOY_3),
-       MESON_PIN(GPIOY_4),
-       MESON_PIN(GPIOY_5),
-       MESON_PIN(GPIOY_6),
-       MESON_PIN(GPIOY_7),
-       MESON_PIN(GPIOY_8),
-       MESON_PIN(GPIOY_9),
-       MESON_PIN(GPIOY_10),
-       MESON_PIN(GPIOY_11),
-       MESON_PIN(GPIOY_12),
-       MESON_PIN(GPIOY_13),
-       MESON_PIN(GPIOY_14),
-       MESON_PIN(GPIOY_15),
-       MESON_PIN(GPIOY_16),
-       MESON_PIN(GPIODV_0),
-       MESON_PIN(GPIODV_1),
-       MESON_PIN(GPIODV_2),
-       MESON_PIN(GPIODV_3),
-       MESON_PIN(GPIODV_4),
-       MESON_PIN(GPIODV_5),
-       MESON_PIN(GPIODV_6),
-       MESON_PIN(GPIODV_7),
-       MESON_PIN(GPIODV_8),
-       MESON_PIN(GPIODV_9),
-       MESON_PIN(GPIODV_10),
-       MESON_PIN(GPIODV_11),
-       MESON_PIN(GPIODV_12),
-       MESON_PIN(GPIODV_13),
-       MESON_PIN(GPIODV_14),
-       MESON_PIN(GPIODV_15),
-       MESON_PIN(GPIODV_16),
-       MESON_PIN(GPIODV_17),
-       MESON_PIN(GPIODV_18),
-       MESON_PIN(GPIODV_19),
-       MESON_PIN(GPIODV_20),
-       MESON_PIN(GPIODV_21),
-       MESON_PIN(GPIODV_22),
-       MESON_PIN(GPIODV_23),
-       MESON_PIN(GPIODV_24),
-       MESON_PIN(GPIODV_25),
-       MESON_PIN(GPIODV_26),
-       MESON_PIN(GPIODV_27),
-       MESON_PIN(GPIODV_28),
-       MESON_PIN(GPIODV_29),
-       MESON_PIN(GPIOH_0),
-       MESON_PIN(GPIOH_1),
-       MESON_PIN(GPIOH_2),
-       MESON_PIN(GPIOH_3),
-       MESON_PIN(GPIOH_4),
-       MESON_PIN(GPIOH_5),
-       MESON_PIN(GPIOH_6),
-       MESON_PIN(GPIOH_7),
-       MESON_PIN(GPIOH_8),
-       MESON_PIN(GPIOH_9),
-       MESON_PIN(GPIOZ_0),
-       MESON_PIN(GPIOZ_1),
-       MESON_PIN(GPIOZ_2),
-       MESON_PIN(GPIOZ_3),
-       MESON_PIN(GPIOZ_4),
-       MESON_PIN(GPIOZ_5),
-       MESON_PIN(GPIOZ_6),
-       MESON_PIN(GPIOZ_7),
-       MESON_PIN(GPIOZ_8),
-       MESON_PIN(GPIOZ_9),
-       MESON_PIN(GPIOZ_10),
-       MESON_PIN(GPIOZ_11),
-       MESON_PIN(GPIOZ_12),
-       MESON_PIN(GPIOZ_13),
-       MESON_PIN(GPIOZ_14),
-       MESON_PIN(CARD_0),
-       MESON_PIN(CARD_1),
-       MESON_PIN(CARD_2),
-       MESON_PIN(CARD_3),
-       MESON_PIN(CARD_4),
-       MESON_PIN(CARD_5),
-       MESON_PIN(CARD_6),
-       MESON_PIN(BOOT_0),
-       MESON_PIN(BOOT_1),
-       MESON_PIN(BOOT_2),
-       MESON_PIN(BOOT_3),
-       MESON_PIN(BOOT_4),
-       MESON_PIN(BOOT_5),
-       MESON_PIN(BOOT_6),
-       MESON_PIN(BOOT_7),
-       MESON_PIN(BOOT_8),
-       MESON_PIN(BOOT_9),
-       MESON_PIN(BOOT_10),
-       MESON_PIN(BOOT_11),
-       MESON_PIN(BOOT_12),
-       MESON_PIN(BOOT_13),
-       MESON_PIN(BOOT_14),
-       MESON_PIN(BOOT_15),
-       MESON_PIN(BOOT_16),
-       MESON_PIN(BOOT_17),
-       MESON_PIN(BOOT_18),
-       MESON_PIN(GPIOAO_0),
-       MESON_PIN(GPIOAO_1),
-       MESON_PIN(GPIOAO_2),
-       MESON_PIN(GPIOAO_3),
-       MESON_PIN(GPIOAO_4),
-       MESON_PIN(GPIOAO_5),
-       MESON_PIN(GPIOAO_6),
-       MESON_PIN(GPIOAO_7),
-       MESON_PIN(GPIOAO_8),
-       MESON_PIN(GPIOAO_9),
-       MESON_PIN(GPIOAO_10),
-       MESON_PIN(GPIOAO_11),
-       MESON_PIN(GPIOAO_12),
-       MESON_PIN(GPIOAO_13),
-       MESON_PIN(GPIO_BSD_EN),
-       MESON_PIN(GPIO_TEST_N),
+       MESON_PIN(GPIOX_0, 0),
+       MESON_PIN(GPIOX_1, 0),
+       MESON_PIN(GPIOX_2, 0),
+       MESON_PIN(GPIOX_3, 0),
+       MESON_PIN(GPIOX_4, 0),
+       MESON_PIN(GPIOX_5, 0),
+       MESON_PIN(GPIOX_6, 0),
+       MESON_PIN(GPIOX_7, 0),
+       MESON_PIN(GPIOX_8, 0),
+       MESON_PIN(GPIOX_9, 0),
+       MESON_PIN(GPIOX_10, 0),
+       MESON_PIN(GPIOX_11, 0),
+       MESON_PIN(GPIOX_12, 0),
+       MESON_PIN(GPIOX_13, 0),
+       MESON_PIN(GPIOX_14, 0),
+       MESON_PIN(GPIOX_15, 0),
+       MESON_PIN(GPIOX_16, 0),
+       MESON_PIN(GPIOX_17, 0),
+       MESON_PIN(GPIOX_18, 0),
+       MESON_PIN(GPIOX_19, 0),
+       MESON_PIN(GPIOX_20, 0),
+       MESON_PIN(GPIOX_21, 0),
+       MESON_PIN(GPIOY_0, 0),
+       MESON_PIN(GPIOY_1, 0),
+       MESON_PIN(GPIOY_2, 0),
+       MESON_PIN(GPIOY_3, 0),
+       MESON_PIN(GPIOY_4, 0),
+       MESON_PIN(GPIOY_5, 0),
+       MESON_PIN(GPIOY_6, 0),
+       MESON_PIN(GPIOY_7, 0),
+       MESON_PIN(GPIOY_8, 0),
+       MESON_PIN(GPIOY_9, 0),
+       MESON_PIN(GPIOY_10, 0),
+       MESON_PIN(GPIOY_11, 0),
+       MESON_PIN(GPIOY_12, 0),
+       MESON_PIN(GPIOY_13, 0),
+       MESON_PIN(GPIOY_14, 0),
+       MESON_PIN(GPIOY_15, 0),
+       MESON_PIN(GPIOY_16, 0),
+       MESON_PIN(GPIODV_0, 0),
+       MESON_PIN(GPIODV_1, 0),
+       MESON_PIN(GPIODV_2, 0),
+       MESON_PIN(GPIODV_3, 0),
+       MESON_PIN(GPIODV_4, 0),
+       MESON_PIN(GPIODV_5, 0),
+       MESON_PIN(GPIODV_6, 0),
+       MESON_PIN(GPIODV_7, 0),
+       MESON_PIN(GPIODV_8, 0),
+       MESON_PIN(GPIODV_9, 0),
+       MESON_PIN(GPIODV_10, 0),
+       MESON_PIN(GPIODV_11, 0),
+       MESON_PIN(GPIODV_12, 0),
+       MESON_PIN(GPIODV_13, 0),
+       MESON_PIN(GPIODV_14, 0),
+       MESON_PIN(GPIODV_15, 0),
+       MESON_PIN(GPIODV_16, 0),
+       MESON_PIN(GPIODV_17, 0),
+       MESON_PIN(GPIODV_18, 0),
+       MESON_PIN(GPIODV_19, 0),
+       MESON_PIN(GPIODV_20, 0),
+       MESON_PIN(GPIODV_21, 0),
+       MESON_PIN(GPIODV_22, 0),
+       MESON_PIN(GPIODV_23, 0),
+       MESON_PIN(GPIODV_24, 0),
+       MESON_PIN(GPIODV_25, 0),
+       MESON_PIN(GPIODV_26, 0),
+       MESON_PIN(GPIODV_27, 0),
+       MESON_PIN(GPIODV_28, 0),
+       MESON_PIN(GPIODV_29, 0),
+       MESON_PIN(GPIOH_0, 0),
+       MESON_PIN(GPIOH_1, 0),
+       MESON_PIN(GPIOH_2, 0),
+       MESON_PIN(GPIOH_3, 0),
+       MESON_PIN(GPIOH_4, 0),
+       MESON_PIN(GPIOH_5, 0),
+       MESON_PIN(GPIOH_6, 0),
+       MESON_PIN(GPIOH_7, 0),
+       MESON_PIN(GPIOH_8, 0),
+       MESON_PIN(GPIOH_9, 0),
+       MESON_PIN(GPIOZ_0, 0),
+       MESON_PIN(GPIOZ_1, 0),
+       MESON_PIN(GPIOZ_2, 0),
+       MESON_PIN(GPIOZ_3, 0),
+       MESON_PIN(GPIOZ_4, 0),
+       MESON_PIN(GPIOZ_5, 0),
+       MESON_PIN(GPIOZ_6, 0),
+       MESON_PIN(GPIOZ_7, 0),
+       MESON_PIN(GPIOZ_8, 0),
+       MESON_PIN(GPIOZ_9, 0),
+       MESON_PIN(GPIOZ_10, 0),
+       MESON_PIN(GPIOZ_11, 0),
+       MESON_PIN(GPIOZ_12, 0),
+       MESON_PIN(GPIOZ_13, 0),
+       MESON_PIN(GPIOZ_14, 0),
+       MESON_PIN(CARD_0, 0),
+       MESON_PIN(CARD_1, 0),
+       MESON_PIN(CARD_2, 0),
+       MESON_PIN(CARD_3, 0),
+       MESON_PIN(CARD_4, 0),
+       MESON_PIN(CARD_5, 0),
+       MESON_PIN(CARD_6, 0),
+       MESON_PIN(BOOT_0, 0),
+       MESON_PIN(BOOT_1, 0),
+       MESON_PIN(BOOT_2, 0),
+       MESON_PIN(BOOT_3, 0),
+       MESON_PIN(BOOT_4, 0),
+       MESON_PIN(BOOT_5, 0),
+       MESON_PIN(BOOT_6, 0),
+       MESON_PIN(BOOT_7, 0),
+       MESON_PIN(BOOT_8, 0),
+       MESON_PIN(BOOT_9, 0),
+       MESON_PIN(BOOT_10, 0),
+       MESON_PIN(BOOT_11, 0),
+       MESON_PIN(BOOT_12, 0),
+       MESON_PIN(BOOT_13, 0),
+       MESON_PIN(BOOT_14, 0),
+       MESON_PIN(BOOT_15, 0),
+       MESON_PIN(BOOT_16, 0),
+       MESON_PIN(BOOT_17, 0),
+       MESON_PIN(BOOT_18, 0),
+       MESON_PIN(GPIOAO_0, AO_OFF),
+       MESON_PIN(GPIOAO_1, AO_OFF),
+       MESON_PIN(GPIOAO_2, AO_OFF),
+       MESON_PIN(GPIOAO_3, AO_OFF),
+       MESON_PIN(GPIOAO_4, AO_OFF),
+       MESON_PIN(GPIOAO_5, AO_OFF),
+       MESON_PIN(GPIOAO_6, AO_OFF),
+       MESON_PIN(GPIOAO_7, AO_OFF),
+       MESON_PIN(GPIOAO_8, AO_OFF),
+       MESON_PIN(GPIOAO_9, AO_OFF),
+       MESON_PIN(GPIOAO_10, AO_OFF),
+       MESON_PIN(GPIOAO_11, AO_OFF),
+       MESON_PIN(GPIOAO_12, AO_OFF),
+       MESON_PIN(GPIOAO_13, AO_OFF),
+       MESON_PIN(GPIO_BSD_EN, AO_OFF),
+       MESON_PIN(GPIO_TEST_N, AO_OFF),
 };
 
 /* bank X */
-static const unsigned int sd_d0_a_pins[] = { PIN_GPIOX_0 };
-static const unsigned int sd_d1_a_pins[] = { PIN_GPIOX_1 };
-static const unsigned int sd_d2_a_pins[] = { PIN_GPIOX_2 };
-static const unsigned int sd_d3_a_pins[] = { PIN_GPIOX_3 };
-static const unsigned int sd_clk_a_pins[] = { PIN_GPIOX_8 };
-static const unsigned int sd_cmd_a_pins[] = { PIN_GPIOX_9 };
-
-static const unsigned int sdxc_d0_a_pins[] = { PIN_GPIOX_0 };
-static const unsigned int sdxc_d13_a_pins[] = { PIN_GPIOX_1, PIN_GPIOX_2,
-                                               PIN_GPIOX_3 };
-static const unsigned int sdxc_d47_a_pins[] = { PIN_GPIOX_4, PIN_GPIOX_5,
-                                               PIN_GPIOX_6, PIN_GPIOX_7 };
-static const unsigned int sdxc_clk_a_pins[] = { PIN_GPIOX_8 };
-static const unsigned int sdxc_cmd_a_pins[] = { PIN_GPIOX_9 };
-
-static const unsigned int pcm_out_a_pins[] = { PIN_GPIOX_4 };
-static const unsigned int pcm_in_a_pins[] = { PIN_GPIOX_5 };
-static const unsigned int pcm_fs_a_pins[] = { PIN_GPIOX_6 };
-static const unsigned int pcm_clk_a_pins[] = { PIN_GPIOX_7 };
-
-static const unsigned int uart_tx_a0_pins[] = { PIN_GPIOX_4 };
-static const unsigned int uart_rx_a0_pins[] = { PIN_GPIOX_5 };
-static const unsigned int uart_cts_a0_pins[] = { PIN_GPIOX_6 };
-static const unsigned int uart_rts_a0_pins[] = { PIN_GPIOX_7 };
-
-static const unsigned int uart_tx_a1_pins[] = { PIN_GPIOX_12 };
-static const unsigned int uart_rx_a1_pins[] = { PIN_GPIOX_13 };
-static const unsigned int uart_cts_a1_pins[] = { PIN_GPIOX_14 };
-static const unsigned int uart_rts_a1_pins[] = { PIN_GPIOX_15 };
-
-static const unsigned int uart_tx_b0_pins[] = { PIN_GPIOX_16 };
-static const unsigned int uart_rx_b0_pins[] = { PIN_GPIOX_17 };
-static const unsigned int uart_cts_b0_pins[] = { PIN_GPIOX_18 };
-static const unsigned int uart_rts_b0_pins[] = { PIN_GPIOX_19 };
-
-static const unsigned int iso7816_det_pins[] = { PIN_GPIOX_16 };
-static const unsigned int iso7816_reset_pins[] = { PIN_GPIOX_17 };
-static const unsigned int iso7816_clk_pins[] = { PIN_GPIOX_18 };
-static const unsigned int iso7816_data_pins[] = { PIN_GPIOX_19 };
-
-static const unsigned int i2c_sda_d0_pins[] = { PIN_GPIOX_16 };
-static const unsigned int i2c_sck_d0_pins[] = { PIN_GPIOX_17 };
-
-static const unsigned int xtal_32k_out_pins[] = { PIN_GPIOX_10 };
-static const unsigned int xtal_24m_out_pins[] = { PIN_GPIOX_11 };
+static const unsigned int sd_d0_a_pins[] = { PIN(GPIOX_0, 0) };
+static const unsigned int sd_d1_a_pins[] = { PIN(GPIOX_1, 0) };
+static const unsigned int sd_d2_a_pins[] = { PIN(GPIOX_2, 0) };
+static const unsigned int sd_d3_a_pins[] = { PIN(GPIOX_3, 0) };
+static const unsigned int sd_clk_a_pins[] = { PIN(GPIOX_8, 0) };
+static const unsigned int sd_cmd_a_pins[] = { PIN(GPIOX_9, 0) };
+
+static const unsigned int sdxc_d0_a_pins[] = { PIN(GPIOX_0, 0) };
+static const unsigned int sdxc_d13_a_pins[] = { PIN(GPIOX_1, 0), PIN(GPIOX_2, 0),
+                                               PIN(GPIOX_3, 0) };
+static const unsigned int sdxc_d47_a_pins[] = { PIN(GPIOX_4, 0), PIN(GPIOX_5, 0),
+                                               PIN(GPIOX_6, 0), PIN(GPIOX_7, 0) };
+static const unsigned int sdxc_clk_a_pins[] = { PIN(GPIOX_8, 0) };
+static const unsigned int sdxc_cmd_a_pins[] = { PIN(GPIOX_9, 0) };
+
+static const unsigned int pcm_out_a_pins[] = { PIN(GPIOX_4, 0) };
+static const unsigned int pcm_in_a_pins[] = { PIN(GPIOX_5, 0) };
+static const unsigned int pcm_fs_a_pins[] = { PIN(GPIOX_6, 0) };
+static const unsigned int pcm_clk_a_pins[] = { PIN(GPIOX_7, 0) };
+
+static const unsigned int uart_tx_a0_pins[] = { PIN(GPIOX_4, 0) };
+static const unsigned int uart_rx_a0_pins[] = { PIN(GPIOX_5, 0) };
+static const unsigned int uart_cts_a0_pins[] = { PIN(GPIOX_6, 0) };
+static const unsigned int uart_rts_a0_pins[] = { PIN(GPIOX_7, 0) };
+
+static const unsigned int uart_tx_a1_pins[] = { PIN(GPIOX_12, 0) };
+static const unsigned int uart_rx_a1_pins[] = { PIN(GPIOX_13, 0) };
+static const unsigned int uart_cts_a1_pins[] = { PIN(GPIOX_14, 0) };
+static const unsigned int uart_rts_a1_pins[] = { PIN(GPIOX_15, 0) };
+
+static const unsigned int uart_tx_b0_pins[] = { PIN(GPIOX_16, 0) };
+static const unsigned int uart_rx_b0_pins[] = { PIN(GPIOX_17, 0) };
+static const unsigned int uart_cts_b0_pins[] = { PIN(GPIOX_18, 0) };
+static const unsigned int uart_rts_b0_pins[] = { PIN(GPIOX_19, 0) };
+
+static const unsigned int iso7816_det_pins[] = { PIN(GPIOX_16, 0) };
+static const unsigned int iso7816_reset_pins[] = { PIN(GPIOX_17, 0) };
+static const unsigned int iso7816_clk_pins[] = { PIN(GPIOX_18, 0) };
+static const unsigned int iso7816_data_pins[] = { PIN(GPIOX_19, 0) };
+
+static const unsigned int i2c_sda_d0_pins[] = { PIN(GPIOX_16, 0) };
+static const unsigned int i2c_sck_d0_pins[] = { PIN(GPIOX_17, 0) };
+
+static const unsigned int xtal_32k_out_pins[] = { PIN(GPIOX_10, 0) };
+static const unsigned int xtal_24m_out_pins[] = { PIN(GPIOX_11, 0) };
 
 /* bank Y */
-static const unsigned int uart_tx_c_pins[] = { PIN_GPIOY_0 };
-static const unsigned int uart_rx_c_pins[] = { PIN_GPIOY_1 };
-static const unsigned int uart_cts_c_pins[] = { PIN_GPIOY_2 };
-static const unsigned int uart_rts_c_pins[] = { PIN_GPIOY_3 };
+static const unsigned int uart_tx_c_pins[] = { PIN(GPIOY_0, 0) };
+static const unsigned int uart_rx_c_pins[] = { PIN(GPIOY_1, 0) };
+static const unsigned int uart_cts_c_pins[] = { PIN(GPIOY_2, 0) };
+static const unsigned int uart_rts_c_pins[] = { PIN(GPIOY_3, 0) };
 
-static const unsigned int pcm_out_b_pins[] = { PIN_GPIOY_4 };
-static const unsigned int pcm_in_b_pins[] = { PIN_GPIOY_5 };
-static const unsigned int pcm_fs_b_pins[] = { PIN_GPIOY_6 };
-static const unsigned int pcm_clk_b_pins[] = { PIN_GPIOY_7 };
+static const unsigned int pcm_out_b_pins[] = { PIN(GPIOY_4, 0) };
+static const unsigned int pcm_in_b_pins[] = { PIN(GPIOY_5, 0) };
+static const unsigned int pcm_fs_b_pins[] = { PIN(GPIOY_6, 0) };
+static const unsigned int pcm_clk_b_pins[] = { PIN(GPIOY_7, 0) };
 
-static const unsigned int i2c_sda_c0_pins[] = { PIN_GPIOY_0 };
-static const unsigned int i2c_sck_c0_pins[] = { PIN_GPIOY_1 };
+static const unsigned int i2c_sda_c0_pins[] = { PIN(GPIOY_0, 0) };
+static const unsigned int i2c_sck_c0_pins[] = { PIN(GPIOY_1, 0) };
 
 /* bank DV */
-static const unsigned int dvin_rgb_pins[] = { PIN_GPIODV_0, PIN_GPIODV_1,
-                                             PIN_GPIODV_2, PIN_GPIODV_3,
-                                             PIN_GPIODV_4, PIN_GPIODV_5,
-                                             PIN_GPIODV_6, PIN_GPIODV_7,
-                                             PIN_GPIODV_8, PIN_GPIODV_9,
-                                             PIN_GPIODV_10, PIN_GPIODV_11,
-                                             PIN_GPIODV_12, PIN_GPIODV_13,
-                                             PIN_GPIODV_14, PIN_GPIODV_15,
-                                             PIN_GPIODV_16, PIN_GPIODV_17,
-                                             PIN_GPIODV_18, PIN_GPIODV_19,
-                                             PIN_GPIODV_20, PIN_GPIODV_21,
-                                             PIN_GPIODV_22, PIN_GPIODV_23 };
-static const unsigned int dvin_vs_pins[] = { PIN_GPIODV_24 };
-static const unsigned int dvin_hs_pins[] = { PIN_GPIODV_25 };
-static const unsigned int dvin_clk_pins[] = { PIN_GPIODV_26 };
-static const unsigned int dvin_de_pins[] = { PIN_GPIODV_27 };
-
-static const unsigned int enc_0_pins[] = { PIN_GPIODV_0 };
-static const unsigned int enc_1_pins[] = { PIN_GPIODV_1 };
-static const unsigned int enc_2_pins[] = { PIN_GPIODV_2 };
-static const unsigned int enc_3_pins[] = { PIN_GPIODV_3 };
-static const unsigned int enc_4_pins[] = { PIN_GPIODV_4 };
-static const unsigned int enc_5_pins[] = { PIN_GPIODV_5 };
-static const unsigned int enc_6_pins[] = { PIN_GPIODV_6 };
-static const unsigned int enc_7_pins[] = { PIN_GPIODV_7 };
-static const unsigned int enc_8_pins[] = { PIN_GPIODV_8 };
-static const unsigned int enc_9_pins[] = { PIN_GPIODV_9 };
-static const unsigned int enc_10_pins[] = { PIN_GPIODV_10 };
-static const unsigned int enc_11_pins[] = { PIN_GPIODV_11 };
-static const unsigned int enc_12_pins[] = { PIN_GPIODV_12 };
-static const unsigned int enc_13_pins[] = { PIN_GPIODV_13 };
-static const unsigned int enc_14_pins[] = { PIN_GPIODV_14 };
-static const unsigned int enc_15_pins[] = { PIN_GPIODV_15 };
-static const unsigned int enc_16_pins[] = { PIN_GPIODV_16 };
-static const unsigned int enc_17_pins[] = { PIN_GPIODV_17 };
-
-static const unsigned int uart_tx_b1_pins[] = { PIN_GPIODV_24 };
-static const unsigned int uart_rx_b1_pins[] = { PIN_GPIODV_25 };
-static const unsigned int uart_cts_b1_pins[] = { PIN_GPIODV_26 };
-static const unsigned int uart_rts_b1_pins[] = { PIN_GPIODV_27 };
-
-static const unsigned int vga_vs_pins[] = { PIN_GPIODV_24 };
-static const unsigned int vga_hs_pins[] = { PIN_GPIODV_25 };
+static const unsigned int dvin_rgb_pins[] = { PIN(GPIODV_0, 0), PIN(GPIODV_1, 0),
+                                             PIN(GPIODV_2, 0), PIN(GPIODV_3, 0),
+                                             PIN(GPIODV_4, 0), PIN(GPIODV_5, 0),
+                                             PIN(GPIODV_6, 0), PIN(GPIODV_7, 0),
+                                             PIN(GPIODV_8, 0), PIN(GPIODV_9, 0),
+                                             PIN(GPIODV_10, 0), PIN(GPIODV_11, 0),
+                                             PIN(GPIODV_12, 0), PIN(GPIODV_13, 0),
+                                             PIN(GPIODV_14, 0), PIN(GPIODV_15, 0),
+                                             PIN(GPIODV_16, 0), PIN(GPIODV_17, 0),
+                                             PIN(GPIODV_18, 0), PIN(GPIODV_19, 0),
+                                             PIN(GPIODV_20, 0), PIN(GPIODV_21, 0),
+                                             PIN(GPIODV_22, 0), PIN(GPIODV_23, 0) };
+static const unsigned int dvin_vs_pins[] = { PIN(GPIODV_24, 0) };
+static const unsigned int dvin_hs_pins[] = { PIN(GPIODV_25, 0) };
+static const unsigned int dvin_clk_pins[] = { PIN(GPIODV_26, 0) };
+static const unsigned int dvin_de_pins[] = { PIN(GPIODV_27, 0) };
+
+static const unsigned int enc_0_pins[] = { PIN(GPIODV_0, 0) };
+static const unsigned int enc_1_pins[] = { PIN(GPIODV_1, 0) };
+static const unsigned int enc_2_pins[] = { PIN(GPIODV_2, 0) };
+static const unsigned int enc_3_pins[] = { PIN(GPIODV_3, 0) };
+static const unsigned int enc_4_pins[] = { PIN(GPIODV_4, 0) };
+static const unsigned int enc_5_pins[] = { PIN(GPIODV_5, 0) };
+static const unsigned int enc_6_pins[] = { PIN(GPIODV_6, 0) };
+static const unsigned int enc_7_pins[] = { PIN(GPIODV_7, 0) };
+static const unsigned int enc_8_pins[] = { PIN(GPIODV_8, 0) };
+static const unsigned int enc_9_pins[] = { PIN(GPIODV_9, 0) };
+static const unsigned int enc_10_pins[] = { PIN(GPIODV_10, 0) };
+static const unsigned int enc_11_pins[] = { PIN(GPIODV_11, 0) };
+static const unsigned int enc_12_pins[] = { PIN(GPIODV_12, 0) };
+static const unsigned int enc_13_pins[] = { PIN(GPIODV_13, 0) };
+static const unsigned int enc_14_pins[] = { PIN(GPIODV_14, 0) };
+static const unsigned int enc_15_pins[] = { PIN(GPIODV_15, 0) };
+static const unsigned int enc_16_pins[] = { PIN(GPIODV_16, 0) };
+static const unsigned int enc_17_pins[] = { PIN(GPIODV_17, 0) };
+
+static const unsigned int uart_tx_b1_pins[] = { PIN(GPIODV_24, 0) };
+static const unsigned int uart_rx_b1_pins[] = { PIN(GPIODV_25, 0) };
+static const unsigned int uart_cts_b1_pins[] = { PIN(GPIODV_26, 0) };
+static const unsigned int uart_rts_b1_pins[] = { PIN(GPIODV_27, 0) };
+
+static const unsigned int vga_vs_pins[] = { PIN(GPIODV_24, 0) };
+static const unsigned int vga_hs_pins[] = { PIN(GPIODV_25, 0) };
 
 /* bank H */
-static const unsigned int hdmi_hpd_pins[] = { PIN_GPIOH_0 };
-static const unsigned int hdmi_sda_pins[] = { PIN_GPIOH_1 };
-static const unsigned int hdmi_scl_pins[] = { PIN_GPIOH_2 };
-static const unsigned int hdmi_cec_pins[] = { PIN_GPIOH_3 };
+static const unsigned int hdmi_hpd_pins[] = { PIN(GPIOH_0, 0) };
+static const unsigned int hdmi_sda_pins[] = { PIN(GPIOH_1, 0) };
+static const unsigned int hdmi_scl_pins[] = { PIN(GPIOH_2, 0) };
+static const unsigned int hdmi_cec_pins[] = { PIN(GPIOH_3, 0) };
 
-static const unsigned int spi_ss0_0_pins[] = { PIN_GPIOH_3 };
-static const unsigned int spi_miso_0_pins[] = { PIN_GPIOH_4 };
-static const unsigned int spi_mosi_0_pins[] = { PIN_GPIOH_5 };
-static const unsigned int spi_sclk_0_pins[] = { PIN_GPIOH_6 };
+static const unsigned int spi_ss0_0_pins[] = { PIN(GPIOH_3, 0) };
+static const unsigned int spi_miso_0_pins[] = { PIN(GPIOH_4, 0) };
+static const unsigned int spi_mosi_0_pins[] = { PIN(GPIOH_5, 0) };
+static const unsigned int spi_sclk_0_pins[] = { PIN(GPIOH_6, 0) };
 
-static const unsigned int i2c_sda_d1_pins[] = { PIN_GPIOH_7 };
-static const unsigned int i2c_sck_d1_pins[] = { PIN_GPIOH_8 };
+static const unsigned int i2c_sda_d1_pins[] = { PIN(GPIOH_7, 0) };
+static const unsigned int i2c_sck_d1_pins[] = { PIN(GPIOH_8, 0) };
 
 /* bank Z */
-static const unsigned int spi_ss0_1_pins[] = { PIN_GPIOZ_9 };
-static const unsigned int spi_ss1_1_pins[] = { PIN_GPIOZ_10 };
-static const unsigned int spi_sclk_1_pins[] = { PIN_GPIOZ_11 };
-static const unsigned int spi_mosi_1_pins[] = { PIN_GPIOZ_12 };
-static const unsigned int spi_miso_1_pins[] = { PIN_GPIOZ_13 };
-static const unsigned int spi_ss2_1_pins[] = { PIN_GPIOZ_14 };
-
-static const unsigned int eth_tx_clk_50m_pins[] = { PIN_GPIOZ_4 };
-static const unsigned int eth_tx_en_pins[] = { PIN_GPIOZ_5 };
-static const unsigned int eth_txd1_pins[] = { PIN_GPIOZ_6 };
-static const unsigned int eth_txd0_pins[] = { PIN_GPIOZ_7 };
-static const unsigned int eth_rx_clk_in_pins[] = { PIN_GPIOZ_8 };
-static const unsigned int eth_rx_dv_pins[] = { PIN_GPIOZ_9 };
-static const unsigned int eth_rxd1_pins[] = { PIN_GPIOZ_10 };
-static const unsigned int eth_rxd0_pins[] = { PIN_GPIOZ_11 };
-static const unsigned int eth_mdio_pins[] = { PIN_GPIOZ_12 };
-static const unsigned int eth_mdc_pins[] = { PIN_GPIOZ_13 };
-
-static const unsigned int i2c_sda_a0_pins[] = { PIN_GPIOZ_0 };
-static const unsigned int i2c_sck_a0_pins[] = { PIN_GPIOZ_1 };
-
-static const unsigned int i2c_sda_b_pins[] = { PIN_GPIOZ_2 };
-static const unsigned int i2c_sck_b_pins[] = { PIN_GPIOZ_3 };
-
-static const unsigned int i2c_sda_c1_pins[] = { PIN_GPIOZ_4 };
-static const unsigned int i2c_sck_c1_pins[] = { PIN_GPIOZ_5 };
-
-static const unsigned int i2c_sda_a1_pins[] = { PIN_GPIOZ_0 };
-static const unsigned int i2c_sck_a1_pins[] = { PIN_GPIOZ_1 };
-
-static const unsigned int i2c_sda_a2_pins[] = { PIN_GPIOZ_0 };
-static const unsigned int i2c_sck_a2_pins[] = { PIN_GPIOZ_1 };
+static const unsigned int spi_ss0_1_pins[] = { PIN(GPIOZ_9, 0) };
+static const unsigned int spi_ss1_1_pins[] = { PIN(GPIOZ_10, 0) };
+static const unsigned int spi_sclk_1_pins[] = { PIN(GPIOZ_11, 0) };
+static const unsigned int spi_mosi_1_pins[] = { PIN(GPIOZ_12, 0) };
+static const unsigned int spi_miso_1_pins[] = { PIN(GPIOZ_13, 0) };
+static const unsigned int spi_ss2_1_pins[] = { PIN(GPIOZ_14, 0) };
+
+static const unsigned int eth_tx_clk_50m_pins[] = { PIN(GPIOZ_4, 0) };
+static const unsigned int eth_tx_en_pins[] = { PIN(GPIOZ_5, 0) };
+static const unsigned int eth_txd1_pins[] = { PIN(GPIOZ_6, 0) };
+static const unsigned int eth_txd0_pins[] = { PIN(GPIOZ_7, 0) };
+static const unsigned int eth_rx_clk_in_pins[] = { PIN(GPIOZ_8, 0) };
+static const unsigned int eth_rx_dv_pins[] = { PIN(GPIOZ_9, 0) };
+static const unsigned int eth_rxd1_pins[] = { PIN(GPIOZ_10, 0) };
+static const unsigned int eth_rxd0_pins[] = { PIN(GPIOZ_11, 0) };
+static const unsigned int eth_mdio_pins[] = { PIN(GPIOZ_12, 0) };
+static const unsigned int eth_mdc_pins[] = { PIN(GPIOZ_13, 0) };
+
+static const unsigned int i2c_sda_a0_pins[] = { PIN(GPIOZ_0, 0) };
+static const unsigned int i2c_sck_a0_pins[] = { PIN(GPIOZ_1, 0) };
+
+static const unsigned int i2c_sda_b_pins[] = { PIN(GPIOZ_2, 0) };
+static const unsigned int i2c_sck_b_pins[] = { PIN(GPIOZ_3, 0) };
+
+static const unsigned int i2c_sda_c1_pins[] = { PIN(GPIOZ_4, 0) };
+static const unsigned int i2c_sck_c1_pins[] = { PIN(GPIOZ_5, 0) };
+
+static const unsigned int i2c_sda_a1_pins[] = { PIN(GPIOZ_0, 0) };
+static const unsigned int i2c_sck_a1_pins[] = { PIN(GPIOZ_1, 0) };
+
+static const unsigned int i2c_sda_a2_pins[] = { PIN(GPIOZ_0, 0) };
+static const unsigned int i2c_sck_a2_pins[] = { PIN(GPIOZ_1, 0) };
 
 /* bank BOOT */
-static const unsigned int sd_d0_c_pins[] = { PIN_BOOT_0 };
-static const unsigned int sd_d1_c_pins[] = { PIN_BOOT_1 };
-static const unsigned int sd_d2_c_pins[] = { PIN_BOOT_2 };
-static const unsigned int sd_d3_c_pins[] = { PIN_BOOT_3 };
-static const unsigned int sd_cmd_c_pins[] = { PIN_BOOT_16 };
-static const unsigned int sd_clk_c_pins[] = { PIN_BOOT_17 };
-
-static const unsigned int sdxc_d0_c_pins[] = { PIN_BOOT_0};
-static const unsigned int sdxc_d13_c_pins[] = { PIN_BOOT_1, PIN_BOOT_2,
-                                               PIN_BOOT_3 };
-static const unsigned int sdxc_d47_c_pins[] = { PIN_BOOT_4, PIN_BOOT_5,
-                                               PIN_BOOT_6, PIN_BOOT_7 };
-static const unsigned int sdxc_cmd_c_pins[] = { PIN_BOOT_16 };
-static const unsigned int sdxc_clk_c_pins[] = { PIN_BOOT_17 };
-
-static const unsigned int nand_io_pins[] = { PIN_BOOT_0, PIN_BOOT_1,
-                                            PIN_BOOT_2, PIN_BOOT_3,
-                                            PIN_BOOT_4, PIN_BOOT_5,
-                                            PIN_BOOT_6, PIN_BOOT_7 };
-static const unsigned int nand_io_ce0_pins[] = { PIN_BOOT_8 };
-static const unsigned int nand_io_ce1_pins[] = { PIN_BOOT_9 };
-static const unsigned int nand_io_rb0_pins[] = { PIN_BOOT_10 };
-static const unsigned int nand_ale_pins[] = { PIN_BOOT_11 };
-static const unsigned int nand_cle_pins[] = { PIN_BOOT_12 };
-static const unsigned int nand_wen_clk_pins[] = { PIN_BOOT_13 };
-static const unsigned int nand_ren_clk_pins[] = { PIN_BOOT_14 };
-static const unsigned int nand_dqs_pins[] = { PIN_BOOT_15 };
-static const unsigned int nand_ce2_pins[] = { PIN_BOOT_16 };
-static const unsigned int nand_ce3_pins[] = { PIN_BOOT_17 };
-
-static const unsigned int nor_d_pins[] = { PIN_BOOT_11 };
-static const unsigned int nor_q_pins[] = { PIN_BOOT_12 };
-static const unsigned int nor_c_pins[] = { PIN_BOOT_13 };
-static const unsigned int nor_cs_pins[] = { PIN_BOOT_18 };
+static const unsigned int sd_d0_c_pins[] = { PIN(BOOT_0, 0) };
+static const unsigned int sd_d1_c_pins[] = { PIN(BOOT_1, 0) };
+static const unsigned int sd_d2_c_pins[] = { PIN(BOOT_2, 0) };
+static const unsigned int sd_d3_c_pins[] = { PIN(BOOT_3, 0) };
+static const unsigned int sd_cmd_c_pins[] = { PIN(BOOT_16, 0) };
+static const unsigned int sd_clk_c_pins[] = { PIN(BOOT_17, 0) };
+
+static const unsigned int sdxc_d0_c_pins[] = { PIN(BOOT_0, 0)};
+static const unsigned int sdxc_d13_c_pins[] = { PIN(BOOT_1, 0), PIN(BOOT_2, 0),
+                                               PIN(BOOT_3, 0) };
+static const unsigned int sdxc_d47_c_pins[] = { PIN(BOOT_4, 0), PIN(BOOT_5, 0),
+                                               PIN(BOOT_6, 0), PIN(BOOT_7, 0) };
+static const unsigned int sdxc_cmd_c_pins[] = { PIN(BOOT_16, 0) };
+static const unsigned int sdxc_clk_c_pins[] = { PIN(BOOT_17, 0) };
+
+static const unsigned int nand_io_pins[] = { PIN(BOOT_0, 0), PIN(BOOT_1, 0),
+                                            PIN(BOOT_2, 0), PIN(BOOT_3, 0),
+                                            PIN(BOOT_4, 0), PIN(BOOT_5, 0),
+                                            PIN(BOOT_6, 0), PIN(BOOT_7, 0) };
+static const unsigned int nand_io_ce0_pins[] = { PIN(BOOT_8, 0) };
+static const unsigned int nand_io_ce1_pins[] = { PIN(BOOT_9, 0) };
+static const unsigned int nand_io_rb0_pins[] = { PIN(BOOT_10, 0) };
+static const unsigned int nand_ale_pins[] = { PIN(BOOT_11, 0) };
+static const unsigned int nand_cle_pins[] = { PIN(BOOT_12, 0) };
+static const unsigned int nand_wen_clk_pins[] = { PIN(BOOT_13, 0) };
+static const unsigned int nand_ren_clk_pins[] = { PIN(BOOT_14, 0) };
+static const unsigned int nand_dqs_pins[] = { PIN(BOOT_15, 0) };
+static const unsigned int nand_ce2_pins[] = { PIN(BOOT_16, 0) };
+static const unsigned int nand_ce3_pins[] = { PIN(BOOT_17, 0) };
+
+static const unsigned int nor_d_pins[] = { PIN(BOOT_11, 0) };
+static const unsigned int nor_q_pins[] = { PIN(BOOT_12, 0) };
+static const unsigned int nor_c_pins[] = { PIN(BOOT_13, 0) };
+static const unsigned int nor_cs_pins[] = { PIN(BOOT_18, 0) };
 
 /* bank CARD */
-static const unsigned int sd_d1_b_pins[] = { PIN_CARD_0 };
-static const unsigned int sd_d0_b_pins[] = { PIN_CARD_1 };
-static const unsigned int sd_clk_b_pins[] = { PIN_CARD_2 };
-static const unsigned int sd_cmd_b_pins[] = { PIN_CARD_3 };
-static const unsigned int sd_d3_b_pins[] = { PIN_CARD_4 };
-static const unsigned int sd_d2_b_pins[] = { PIN_CARD_5 };
-
-static const unsigned int sdxc_d13_b_pins[] = { PIN_CARD_0, PIN_CARD_4,
-                                               PIN_CARD_5 };
-static const unsigned int sdxc_d0_b_pins[] = { PIN_CARD_1 };
-static const unsigned int sdxc_clk_b_pins[] = { PIN_CARD_2 };
-static const unsigned int sdxc_cmd_b_pins[] = { PIN_CARD_3 };
+static const unsigned int sd_d1_b_pins[] = { PIN(CARD_0, 0) };
+static const unsigned int sd_d0_b_pins[] = { PIN(CARD_1, 0) };
+static const unsigned int sd_clk_b_pins[] = { PIN(CARD_2, 0) };
+static const unsigned int sd_cmd_b_pins[] = { PIN(CARD_3, 0) };
+static const unsigned int sd_d3_b_pins[] = { PIN(CARD_4, 0) };
+static const unsigned int sd_d2_b_pins[] = { PIN(CARD_5, 0) };
+
+static const unsigned int sdxc_d13_b_pins[] = { PIN(CARD_0, 0), PIN(CARD_4, 0),
+                                               PIN(CARD_5, 0) };
+static const unsigned int sdxc_d0_b_pins[] = { PIN(CARD_1, 0) };
+static const unsigned int sdxc_clk_b_pins[] = { PIN(CARD_2, 0) };
+static const unsigned int sdxc_cmd_b_pins[] = { PIN(CARD_3, 0) };
 
 /* bank AO */
-static const unsigned int uart_tx_ao_a_pins[] = { PIN_GPIOAO_0 };
-static const unsigned int uart_rx_ao_a_pins[] = { PIN_GPIOAO_1 };
-static const unsigned int uart_cts_ao_a_pins[] = { PIN_GPIOAO_2 };
-static const unsigned int uart_rts_ao_a_pins[] = { PIN_GPIOAO_3 };
+static const unsigned int uart_tx_ao_a_pins[] = { PIN(GPIOAO_0, AO_OFF) };
+static const unsigned int uart_rx_ao_a_pins[] = { PIN(GPIOAO_1, AO_OFF) };
+static const unsigned int uart_cts_ao_a_pins[] = { PIN(GPIOAO_2, AO_OFF) };
+static const unsigned int uart_rts_ao_a_pins[] = { PIN(GPIOAO_3, AO_OFF) };
 
-static const unsigned int remote_input_pins[] = { PIN_GPIOAO_7 };
+static const unsigned int remote_input_pins[] = { PIN(GPIOAO_7, AO_OFF) };
 
-static const unsigned int i2c_slave_sck_ao_pins[] = { PIN_GPIOAO_4 };
-static const unsigned int i2c_slave_sda_ao_pins[] = { PIN_GPIOAO_5 };
+static const unsigned int i2c_slave_sck_ao_pins[] = { PIN(GPIOAO_4, AO_OFF) };
+static const unsigned int i2c_slave_sda_ao_pins[] = { PIN(GPIOAO_5, AO_OFF) };
 
-static const unsigned int uart_tx_ao_b0_pins[] = { PIN_GPIOAO_0 };
-static const unsigned int uart_rx_ao_b0_pins[] = { PIN_GPIOAO_1 };
+static const unsigned int uart_tx_ao_b0_pins[] = { PIN(GPIOAO_0, AO_OFF) };
+static const unsigned int uart_rx_ao_b0_pins[] = { PIN(GPIOAO_1, AO_OFF) };
 
-static const unsigned int uart_tx_ao_b1_pins[] = { PIN_GPIOAO_4 };
-static const unsigned int uart_rx_ao_b1_pins[] = { PIN_GPIOAO_5 };
+static const unsigned int uart_tx_ao_b1_pins[] = { PIN(GPIOAO_4, AO_OFF) };
+static const unsigned int uart_rx_ao_b1_pins[] = { PIN(GPIOAO_5, AO_OFF) };
 
-static const unsigned int i2c_mst_sck_ao_pins[] = { PIN_GPIOAO_4 };
-static const unsigned int i2c_mst_sda_ao_pins[] = { PIN_GPIOAO_5 };
+static const unsigned int i2c_mst_sck_ao_pins[] = { PIN(GPIOAO_4, AO_OFF) };
+static const unsigned int i2c_mst_sda_ao_pins[] = { PIN(GPIOAO_5, AO_OFF) };
 
 static struct meson_pmx_group meson8_groups[] = {
-       GPIO_GROUP(GPIOX_0),
-       GPIO_GROUP(GPIOX_1),
-       GPIO_GROUP(GPIOX_2),
-       GPIO_GROUP(GPIOX_3),
-       GPIO_GROUP(GPIOX_4),
-       GPIO_GROUP(GPIOX_5),
-       GPIO_GROUP(GPIOX_6),
-       GPIO_GROUP(GPIOX_7),
-       GPIO_GROUP(GPIOX_8),
-       GPIO_GROUP(GPIOX_9),
-       GPIO_GROUP(GPIOX_10),
-       GPIO_GROUP(GPIOX_11),
-       GPIO_GROUP(GPIOX_12),
-       GPIO_GROUP(GPIOX_13),
-       GPIO_GROUP(GPIOX_14),
-       GPIO_GROUP(GPIOX_15),
-       GPIO_GROUP(GPIOX_16),
-       GPIO_GROUP(GPIOX_17),
-       GPIO_GROUP(GPIOX_18),
-       GPIO_GROUP(GPIOX_19),
-       GPIO_GROUP(GPIOX_20),
-       GPIO_GROUP(GPIOX_21),
-       GPIO_GROUP(GPIOY_0),
-       GPIO_GROUP(GPIOY_1),
-       GPIO_GROUP(GPIOY_2),
-       GPIO_GROUP(GPIOY_3),
-       GPIO_GROUP(GPIOY_4),
-       GPIO_GROUP(GPIOY_5),
-       GPIO_GROUP(GPIOY_6),
-       GPIO_GROUP(GPIOY_7),
-       GPIO_GROUP(GPIOY_8),
-       GPIO_GROUP(GPIOY_9),
-       GPIO_GROUP(GPIOY_10),
-       GPIO_GROUP(GPIOY_11),
-       GPIO_GROUP(GPIOY_12),
-       GPIO_GROUP(GPIOY_13),
-       GPIO_GROUP(GPIOY_14),
-       GPIO_GROUP(GPIOY_15),
-       GPIO_GROUP(GPIOY_16),
-       GPIO_GROUP(GPIODV_0),
-       GPIO_GROUP(GPIODV_1),
-       GPIO_GROUP(GPIODV_2),
-       GPIO_GROUP(GPIODV_3),
-       GPIO_GROUP(GPIODV_4),
-       GPIO_GROUP(GPIODV_5),
-       GPIO_GROUP(GPIODV_6),
-       GPIO_GROUP(GPIODV_7),
-       GPIO_GROUP(GPIODV_8),
-       GPIO_GROUP(GPIODV_9),
-       GPIO_GROUP(GPIODV_10),
-       GPIO_GROUP(GPIODV_11),
-       GPIO_GROUP(GPIODV_12),
-       GPIO_GROUP(GPIODV_13),
-       GPIO_GROUP(GPIODV_14),
-       GPIO_GROUP(GPIODV_15),
-       GPIO_GROUP(GPIODV_16),
-       GPIO_GROUP(GPIODV_17),
-       GPIO_GROUP(GPIODV_18),
-       GPIO_GROUP(GPIODV_19),
-       GPIO_GROUP(GPIODV_20),
-       GPIO_GROUP(GPIODV_21),
-       GPIO_GROUP(GPIODV_22),
-       GPIO_GROUP(GPIODV_23),
-       GPIO_GROUP(GPIODV_24),
-       GPIO_GROUP(GPIODV_25),
-       GPIO_GROUP(GPIODV_26),
-       GPIO_GROUP(GPIODV_27),
-       GPIO_GROUP(GPIODV_28),
-       GPIO_GROUP(GPIODV_29),
-       GPIO_GROUP(GPIOH_0),
-       GPIO_GROUP(GPIOH_1),
-       GPIO_GROUP(GPIOH_2),
-       GPIO_GROUP(GPIOH_3),
-       GPIO_GROUP(GPIOH_4),
-       GPIO_GROUP(GPIOH_5),
-       GPIO_GROUP(GPIOH_6),
-       GPIO_GROUP(GPIOH_7),
-       GPIO_GROUP(GPIOH_8),
-       GPIO_GROUP(GPIOH_9),
-       GPIO_GROUP(GPIOZ_0),
-       GPIO_GROUP(GPIOZ_1),
-       GPIO_GROUP(GPIOZ_2),
-       GPIO_GROUP(GPIOZ_3),
-       GPIO_GROUP(GPIOZ_4),
-       GPIO_GROUP(GPIOZ_5),
-       GPIO_GROUP(GPIOZ_6),
-       GPIO_GROUP(GPIOZ_7),
-       GPIO_GROUP(GPIOZ_8),
-       GPIO_GROUP(GPIOZ_9),
-       GPIO_GROUP(GPIOZ_10),
-       GPIO_GROUP(GPIOZ_11),
-       GPIO_GROUP(GPIOZ_12),
-       GPIO_GROUP(GPIOZ_13),
-       GPIO_GROUP(GPIOZ_14),
-       GPIO_GROUP(GPIOAO_0),
-       GPIO_GROUP(GPIOAO_1),
-       GPIO_GROUP(GPIOAO_2),
-       GPIO_GROUP(GPIOAO_3),
-       GPIO_GROUP(GPIOAO_4),
-       GPIO_GROUP(GPIOAO_5),
-       GPIO_GROUP(GPIOAO_6),
-       GPIO_GROUP(GPIOAO_7),
-       GPIO_GROUP(GPIOAO_8),
-       GPIO_GROUP(GPIOAO_9),
-       GPIO_GROUP(GPIOAO_10),
-       GPIO_GROUP(GPIOAO_11),
-       GPIO_GROUP(GPIOAO_12),
-       GPIO_GROUP(GPIOAO_13),
-       GPIO_GROUP(GPIO_BSD_EN),
-       GPIO_GROUP(GPIO_TEST_N),
+       GPIO_GROUP(GPIOX_0, 0),
+       GPIO_GROUP(GPIOX_1, 0),
+       GPIO_GROUP(GPIOX_2, 0),
+       GPIO_GROUP(GPIOX_3, 0),
+       GPIO_GROUP(GPIOX_4, 0),
+       GPIO_GROUP(GPIOX_5, 0),
+       GPIO_GROUP(GPIOX_6, 0),
+       GPIO_GROUP(GPIOX_7, 0),
+       GPIO_GROUP(GPIOX_8, 0),
+       GPIO_GROUP(GPIOX_9, 0),
+       GPIO_GROUP(GPIOX_10, 0),
+       GPIO_GROUP(GPIOX_11, 0),
+       GPIO_GROUP(GPIOX_12, 0),
+       GPIO_GROUP(GPIOX_13, 0),
+       GPIO_GROUP(GPIOX_14, 0),
+       GPIO_GROUP(GPIOX_15, 0),
+       GPIO_GROUP(GPIOX_16, 0),
+       GPIO_GROUP(GPIOX_17, 0),
+       GPIO_GROUP(GPIOX_18, 0),
+       GPIO_GROUP(GPIOX_19, 0),
+       GPIO_GROUP(GPIOX_20, 0),
+       GPIO_GROUP(GPIOX_21, 0),
+       GPIO_GROUP(GPIOY_0, 0),
+       GPIO_GROUP(GPIOY_1, 0),
+       GPIO_GROUP(GPIOY_2, 0),
+       GPIO_GROUP(GPIOY_3, 0),
+       GPIO_GROUP(GPIOY_4, 0),
+       GPIO_GROUP(GPIOY_5, 0),
+       GPIO_GROUP(GPIOY_6, 0),
+       GPIO_GROUP(GPIOY_7, 0),
+       GPIO_GROUP(GPIOY_8, 0),
+       GPIO_GROUP(GPIOY_9, 0),
+       GPIO_GROUP(GPIOY_10, 0),
+       GPIO_GROUP(GPIOY_11, 0),
+       GPIO_GROUP(GPIOY_12, 0),
+       GPIO_GROUP(GPIOY_13, 0),
+       GPIO_GROUP(GPIOY_14, 0),
+       GPIO_GROUP(GPIOY_15, 0),
+       GPIO_GROUP(GPIOY_16, 0),
+       GPIO_GROUP(GPIODV_0, 0),
+       GPIO_GROUP(GPIODV_1, 0),
+       GPIO_GROUP(GPIODV_2, 0),
+       GPIO_GROUP(GPIODV_3, 0),
+       GPIO_GROUP(GPIODV_4, 0),
+       GPIO_GROUP(GPIODV_5, 0),
+       GPIO_GROUP(GPIODV_6, 0),
+       GPIO_GROUP(GPIODV_7, 0),
+       GPIO_GROUP(GPIODV_8, 0),
+       GPIO_GROUP(GPIODV_9, 0),
+       GPIO_GROUP(GPIODV_10, 0),
+       GPIO_GROUP(GPIODV_11, 0),
+       GPIO_GROUP(GPIODV_12, 0),
+       GPIO_GROUP(GPIODV_13, 0),
+       GPIO_GROUP(GPIODV_14, 0),
+       GPIO_GROUP(GPIODV_15, 0),
+       GPIO_GROUP(GPIODV_16, 0),
+       GPIO_GROUP(GPIODV_17, 0),
+       GPIO_GROUP(GPIODV_18, 0),
+       GPIO_GROUP(GPIODV_19, 0),
+       GPIO_GROUP(GPIODV_20, 0),
+       GPIO_GROUP(GPIODV_21, 0),
+       GPIO_GROUP(GPIODV_22, 0),
+       GPIO_GROUP(GPIODV_23, 0),
+       GPIO_GROUP(GPIODV_24, 0),
+       GPIO_GROUP(GPIODV_25, 0),
+       GPIO_GROUP(GPIODV_26, 0),
+       GPIO_GROUP(GPIODV_27, 0),
+       GPIO_GROUP(GPIODV_28, 0),
+       GPIO_GROUP(GPIODV_29, 0),
+       GPIO_GROUP(GPIOH_0, 0),
+       GPIO_GROUP(GPIOH_1, 0),
+       GPIO_GROUP(GPIOH_2, 0),
+       GPIO_GROUP(GPIOH_3, 0),
+       GPIO_GROUP(GPIOH_4, 0),
+       GPIO_GROUP(GPIOH_5, 0),
+       GPIO_GROUP(GPIOH_6, 0),
+       GPIO_GROUP(GPIOH_7, 0),
+       GPIO_GROUP(GPIOH_8, 0),
+       GPIO_GROUP(GPIOH_9, 0),
+       GPIO_GROUP(GPIOZ_0, 0),
+       GPIO_GROUP(GPIOZ_1, 0),
+       GPIO_GROUP(GPIOZ_2, 0),
+       GPIO_GROUP(GPIOZ_3, 0),
+       GPIO_GROUP(GPIOZ_4, 0),
+       GPIO_GROUP(GPIOZ_5, 0),
+       GPIO_GROUP(GPIOZ_6, 0),
+       GPIO_GROUP(GPIOZ_7, 0),
+       GPIO_GROUP(GPIOZ_8, 0),
+       GPIO_GROUP(GPIOZ_9, 0),
+       GPIO_GROUP(GPIOZ_10, 0),
+       GPIO_GROUP(GPIOZ_11, 0),
+       GPIO_GROUP(GPIOZ_12, 0),
+       GPIO_GROUP(GPIOZ_13, 0),
+       GPIO_GROUP(GPIOZ_14, 0),
+       GPIO_GROUP(GPIOAO_0, AO_OFF),
+       GPIO_GROUP(GPIOAO_1, AO_OFF),
+       GPIO_GROUP(GPIOAO_2, AO_OFF),
+       GPIO_GROUP(GPIOAO_3, AO_OFF),
+       GPIO_GROUP(GPIOAO_4, AO_OFF),
+       GPIO_GROUP(GPIOAO_5, AO_OFF),
+       GPIO_GROUP(GPIOAO_6, AO_OFF),
+       GPIO_GROUP(GPIOAO_7, AO_OFF),
+       GPIO_GROUP(GPIOAO_8, AO_OFF),
+       GPIO_GROUP(GPIOAO_9, AO_OFF),
+       GPIO_GROUP(GPIOAO_10, AO_OFF),
+       GPIO_GROUP(GPIOAO_11, AO_OFF),
+       GPIO_GROUP(GPIOAO_12, AO_OFF),
+       GPIO_GROUP(GPIOAO_13, AO_OFF),
+       GPIO_GROUP(GPIO_BSD_EN, AO_OFF),
+       GPIO_GROUP(GPIO_TEST_N, AO_OFF),
 
        /* bank X */
        GROUP(sd_d0_a,          8,      5),
@@ -1045,19 +907,19 @@ static struct meson_pmx_func meson8_functions[] = {
 };
 
 static struct meson_bank meson8_banks[] = {
-       /*   name    first         last             pullen  pull     dir     out     in  */
-       BANK("X",    PIN_GPIOX_0,  PIN_GPIOX_21,    4,  0,  4,  0,  0,  0,  1,  0,  2,  0),
-       BANK("Y",    PIN_GPIOY_0,  PIN_GPIOY_16,    3,  0,  3,  0,  3,  0,  4,  0,  5,  0),
-       BANK("DV",   PIN_GPIODV_0, PIN_GPIODV_29,   0,  0,  0,  0,  7,  0,  8,  0,  9,  0),
-       BANK("H",    PIN_GPIOH_0,  PIN_GPIOH_9,     1, 16,  1, 16,  9, 19, 10, 19, 11, 19),
-       BANK("Z",    PIN_GPIOZ_0,  PIN_GPIOZ_14,    1,  0,  1,  0,  3, 17,  4, 17,  5, 17),
-       BANK("CARD", PIN_CARD_0,   PIN_CARD_6,      2, 20,  2, 20,  0, 22,  1, 22,  2, 22),
-       BANK("BOOT", PIN_BOOT_0,   PIN_BOOT_18,     2,  0,  2,  0,  9,  0, 10,  0, 11,  0),
+       /*   name    first             last                 pullen  pull    dir     out     in  */
+       BANK("X",    PIN(GPIOX_0, 0),  PIN(GPIOX_21, 0),    4,  0,  4,  0,  0,  0,  1,  0,  2,  0),
+       BANK("Y",    PIN(GPIOY_0, 0),  PIN(GPIOY_16, 0),    3,  0,  3,  0,  3,  0,  4,  0,  5,  0),
+       BANK("DV",   PIN(GPIODV_0, 0), PIN(GPIODV_29, 0),   0,  0,  0,  0,  7,  0,  8,  0,  9,  0),
+       BANK("H",    PIN(GPIOH_0, 0),  PIN(GPIOH_9, 0),     1, 16,  1, 16,  9, 19, 10, 19, 11, 19),
+       BANK("Z",    PIN(GPIOZ_0, 0),  PIN(GPIOZ_14, 0),    1,  0,  1,  0,  3, 17,  4, 17,  5, 17),
+       BANK("CARD", PIN(CARD_0, 0),   PIN(CARD_6, 0),      2, 20,  2, 20,  0, 22,  1, 22,  2, 22),
+       BANK("BOOT", PIN(BOOT_0, 0),   PIN(BOOT_18, 0),     2,  0,  2,  0,  9,  0, 10,  0, 11,  0),
 };
 
 static struct meson_bank meson8_ao_banks[] = {
-       /*   name    first         last             pullen  pull     dir     out     in  */
-       BANK("AO",   PIN_GPIOAO_0, PIN_GPIO_TEST_N, 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
+       /*   name    first                  last                      pullen  pull    dir     out     in  */
+       BANK("AO",   PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
 };
 
 static struct meson_domain_data meson8_domain_data[] = {
diff --git a/drivers/pinctrl/meson/pinctrl-meson8b.c b/drivers/pinctrl/meson/pinctrl-meson8b.c
new file mode 100644 (file)
index 0000000..2f7ea62
--- /dev/null
@@ -0,0 +1,899 @@
+/*
+ * Pin controller and GPIO driver for Amlogic Meson8b.
+ *
+ * Copyright (C) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.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.
+ *
+ * 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 <dt-bindings/gpio/meson8b-gpio.h>
+#include "pinctrl-meson.h"
+
+#define AO_OFF 130
+
+static const struct pinctrl_pin_desc meson8b_pins[] = {
+       MESON_PIN(GPIOX_0, 0),
+       MESON_PIN(GPIOX_1, 0),
+       MESON_PIN(GPIOX_2, 0),
+       MESON_PIN(GPIOX_3, 0),
+       MESON_PIN(GPIOX_4, 0),
+       MESON_PIN(GPIOX_5, 0),
+       MESON_PIN(GPIOX_6, 0),
+       MESON_PIN(GPIOX_7, 0),
+       MESON_PIN(GPIOX_8, 0),
+       MESON_PIN(GPIOX_9, 0),
+       MESON_PIN(GPIOX_10, 0),
+       MESON_PIN(GPIOX_11, 0),
+       MESON_PIN(GPIOX_16, 0),
+       MESON_PIN(GPIOX_17, 0),
+       MESON_PIN(GPIOX_18, 0),
+       MESON_PIN(GPIOX_19, 0),
+       MESON_PIN(GPIOX_20, 0),
+       MESON_PIN(GPIOX_21, 0),
+
+       MESON_PIN(GPIOY_0, 0),
+       MESON_PIN(GPIOY_1, 0),
+       MESON_PIN(GPIOY_3, 0),
+       MESON_PIN(GPIOY_6, 0),
+       MESON_PIN(GPIOY_7, 0),
+       MESON_PIN(GPIOY_8, 0),
+       MESON_PIN(GPIOY_9, 0),
+       MESON_PIN(GPIOY_10, 0),
+       MESON_PIN(GPIOY_11, 0),
+       MESON_PIN(GPIOY_12, 0),
+       MESON_PIN(GPIOY_13, 0),
+       MESON_PIN(GPIOY_14, 0),
+
+       MESON_PIN(GPIODV_9, 0),
+       MESON_PIN(GPIODV_24, 0),
+       MESON_PIN(GPIODV_25, 0),
+       MESON_PIN(GPIODV_26, 0),
+       MESON_PIN(GPIODV_27, 0),
+       MESON_PIN(GPIODV_28, 0),
+       MESON_PIN(GPIODV_29, 0),
+
+       MESON_PIN(GPIOH_0, 0),
+       MESON_PIN(GPIOH_1, 0),
+       MESON_PIN(GPIOH_2, 0),
+       MESON_PIN(GPIOH_3, 0),
+       MESON_PIN(GPIOH_4, 0),
+       MESON_PIN(GPIOH_5, 0),
+       MESON_PIN(GPIOH_6, 0),
+       MESON_PIN(GPIOH_7, 0),
+       MESON_PIN(GPIOH_8, 0),
+       MESON_PIN(GPIOH_9, 0),
+
+       MESON_PIN(CARD_0, 0),
+       MESON_PIN(CARD_1, 0),
+       MESON_PIN(CARD_2, 0),
+       MESON_PIN(CARD_3, 0),
+       MESON_PIN(CARD_4, 0),
+       MESON_PIN(CARD_5, 0),
+       MESON_PIN(CARD_6, 0),
+
+       MESON_PIN(BOOT_0, 0),
+       MESON_PIN(BOOT_1, 0),
+       MESON_PIN(BOOT_2, 0),
+       MESON_PIN(BOOT_3, 0),
+       MESON_PIN(BOOT_4, 0),
+       MESON_PIN(BOOT_5, 0),
+       MESON_PIN(BOOT_6, 0),
+       MESON_PIN(BOOT_7, 0),
+       MESON_PIN(BOOT_8, 0),
+       MESON_PIN(BOOT_9, 0),
+       MESON_PIN(BOOT_10, 0),
+       MESON_PIN(BOOT_11, 0),
+       MESON_PIN(BOOT_12, 0),
+       MESON_PIN(BOOT_13, 0),
+       MESON_PIN(BOOT_14, 0),
+       MESON_PIN(BOOT_15, 0),
+       MESON_PIN(BOOT_16, 0),
+       MESON_PIN(BOOT_17, 0),
+       MESON_PIN(BOOT_18, 0),
+
+       MESON_PIN(DIF_0_P, 0),
+       MESON_PIN(DIF_0_N, 0),
+       MESON_PIN(DIF_1_P, 0),
+       MESON_PIN(DIF_1_N, 0),
+       MESON_PIN(DIF_2_P, 0),
+       MESON_PIN(DIF_2_N, 0),
+       MESON_PIN(DIF_3_P, 0),
+       MESON_PIN(DIF_3_N, 0),
+       MESON_PIN(DIF_4_P, 0),
+       MESON_PIN(DIF_4_N, 0),
+
+       MESON_PIN(GPIOAO_0, AO_OFF),
+       MESON_PIN(GPIOAO_1, AO_OFF),
+       MESON_PIN(GPIOAO_2, AO_OFF),
+       MESON_PIN(GPIOAO_3, AO_OFF),
+       MESON_PIN(GPIOAO_4, AO_OFF),
+       MESON_PIN(GPIOAO_5, AO_OFF),
+       MESON_PIN(GPIOAO_6, AO_OFF),
+       MESON_PIN(GPIOAO_7, AO_OFF),
+       MESON_PIN(GPIOAO_8, AO_OFF),
+       MESON_PIN(GPIOAO_9, AO_OFF),
+       MESON_PIN(GPIOAO_10, AO_OFF),
+       MESON_PIN(GPIOAO_11, AO_OFF),
+       MESON_PIN(GPIOAO_12, AO_OFF),
+       MESON_PIN(GPIOAO_13, AO_OFF),
+       MESON_PIN(GPIO_BSD_EN, AO_OFF),
+       MESON_PIN(GPIO_TEST_N, AO_OFF),
+};
+
+/* bank X */
+static const unsigned int sd_d0_a_pins[]       = { PIN(GPIOX_0, 0) };
+static const unsigned int sd_d1_a_pins[]       = { PIN(GPIOX_1, 0) };
+static const unsigned int sd_d2_a_pins[]       = { PIN(GPIOX_2, 0) };
+static const unsigned int sd_d3_a_pins[]       = { PIN(GPIOX_3, 0) };
+static const unsigned int sdxc_d0_0_a_pins[]   = { PIN(GPIOX_4, 0) };
+static const unsigned int sdxc_d47_a_pins[]    = { PIN(GPIOX_4, 0), PIN(GPIOX_5, 0),
+                                                   PIN(GPIOX_6, 0), PIN(GPIOX_7, 0) };
+static const unsigned int sdxc_d13_0_a_pins[]  = { PIN(GPIOX_5, 0), PIN(GPIOX_6, 0),
+                                                   PIN(GPIOX_7, 0) };
+static const unsigned int sd_clk_a_pins[]      = { PIN(GPIOX_8, 0) };
+static const unsigned int sd_cmd_a_pins[]      = { PIN(GPIOX_9, 0) };
+static const unsigned int xtal_32k_out_pins[]  = { PIN(GPIOX_10, 0) };
+static const unsigned int xtal_24m_out_pins[]  = { PIN(GPIOX_11, 0) };
+static const unsigned int uart_tx_b0_pins[]    = { PIN(GPIOX_16, 0) };
+static const unsigned int uart_rx_b0_pins[]    = { PIN(GPIOX_17, 0) };
+static const unsigned int uart_cts_b0_pins[]   = { PIN(GPIOX_18, 0) };
+static const unsigned int uart_rts_b0_pins[]   = { PIN(GPIOX_19, 0) };
+
+static const unsigned int sdxc_d0_1_a_pins[]   = { PIN(GPIOX_0, 0) };
+static const unsigned int sdxc_d13_1_a_pins[]  = { PIN(GPIOX_1, 0), PIN(GPIOX_2, 0),
+                                                   PIN(GPIOX_3, 0) };
+static const unsigned int pcm_out_a_pins[]     = { PIN(GPIOX_4, 0) };
+static const unsigned int pcm_in_a_pins[]      = { PIN(GPIOX_5, 0) };
+static const unsigned int pcm_fs_a_pins[]      = { PIN(GPIOX_6, 0) };
+static const unsigned int pcm_clk_a_pins[]     = { PIN(GPIOX_7, 0) };
+static const unsigned int sdxc_clk_a_pins[]    = { PIN(GPIOX_8, 0) };
+static const unsigned int sdxc_cmd_a_pins[]    = { PIN(GPIOX_9, 0) };
+static const unsigned int pwm_vs_0_pins[]      = { PIN(GPIOX_10, 0) };
+static const unsigned int pwm_e_pins[]         = { PIN(GPIOX_10, 0) };
+static const unsigned int pwm_vs_1_pins[]      = { PIN(GPIOX_11, 0) };
+
+static const unsigned int uart_tx_a_pins[]     = { PIN(GPIOX_4, 0) };
+static const unsigned int uart_rx_a_pins[]     = { PIN(GPIOX_5, 0) };
+static const unsigned int uart_cts_a_pins[]    = { PIN(GPIOX_6, 0) };
+static const unsigned int uart_rts_a_pins[]    = { PIN(GPIOX_7, 0) };
+static const unsigned int uart_tx_b1_pins[]    = { PIN(GPIOX_8, 0) };
+static const unsigned int uart_rx_b1_pins[]    = { PIN(GPIOX_9, 0) };
+static const unsigned int uart_cts_b1_pins[]   = { PIN(GPIOX_10, 0) };
+static const unsigned int uart_rts_b1_pins[]   = { PIN(GPIOX_20, 0) };
+
+static const unsigned int iso7816_0_clk_pins[] = { PIN(GPIOX_6, 0) };
+static const unsigned int iso7816_0_data_pins[]        = { PIN(GPIOX_7, 0) };
+static const unsigned int spi_sclk_0_pins[]    = { PIN(GPIOX_8, 0) };
+static const unsigned int spi_miso_0_pins[]    = { PIN(GPIOX_9, 0) };
+static const unsigned int spi_mosi_0_pins[]    = { PIN(GPIOX_10, 0) };
+static const unsigned int iso7816_det_pins[]   = { PIN(GPIOX_16, 0) };
+static const unsigned int iso7816_reset_pins[] = { PIN(GPIOX_17, 0) };
+static const unsigned int iso7816_1_clk_pins[] = { PIN(GPIOX_18, 0) };
+static const unsigned int iso7816_1_data_pins[]        = { PIN(GPIOX_19, 0) };
+static const unsigned int spi_ss0_0_pins[]     = { PIN(GPIOX_20, 0) };
+
+static const unsigned int tsin_clk_b_pins[]    = { PIN(GPIOX_8, 0) };
+static const unsigned int tsin_sop_b_pins[]    = { PIN(GPIOX_9, 0) };
+static const unsigned int tsin_d0_b_pins[]     = { PIN(GPIOX_10, 0) };
+static const unsigned int pwm_b_pins[]         = { PIN(GPIOX_11, 0) };
+static const unsigned int i2c_sda_d0_pins[]    = { PIN(GPIOX_16, 0) };
+static const unsigned int i2c_sck_d0_pins[]    = { PIN(GPIOX_17, 0) };
+static const unsigned int tsin_d_valid_b_pins[] = { PIN(GPIOX_20, 0) };
+
+/* bank Y */
+static const unsigned int tsin_d_valid_a_pins[] = { PIN(GPIOY_0, 0) };
+static const unsigned int tsin_sop_a_pins[]    = { PIN(GPIOY_1, 0) };
+static const unsigned int tsin_d17_a_pins[]    = { PIN(GPIOY_6, 0), PIN(GPIOY_7, 0),
+                                                   PIN(GPIOY_10, 0), PIN(GPIOY_11, 0),
+                                                   PIN(GPIOY_12, 0), PIN(GPIOY_13, 0),
+                                                   PIN(GPIOY_14, 0) };
+static const unsigned int tsin_clk_a_pins[]    = { PIN(GPIOY_8, 0) };
+static const unsigned int tsin_d0_a_pins[]     = { PIN(GPIOY_9, 0) };
+
+static const unsigned int spdif_out_0_pins[]   = { PIN(GPIOY_3, 0) };
+
+static const unsigned int xtal_24m_pins[]      = { PIN(GPIOY_3, 0) };
+static const unsigned int iso7816_2_clk_pins[] = { PIN(GPIOY_13, 0) };
+static const unsigned int iso7816_2_data_pins[] = { PIN(GPIOY_14, 0) };
+
+/* bank DV */
+static const unsigned int pwm_d_pins[]         = { PIN(GPIODV_28, 0) };
+static const unsigned int pwm_c0_pins[]                = { PIN(GPIODV_29, 0) };
+
+static const unsigned int pwm_vs_2_pins[]      = { PIN(GPIODV_9, 0) };
+static const unsigned int pwm_vs_3_pins[]      = { PIN(GPIODV_28, 0) };
+static const unsigned int pwm_vs_4_pins[]      = { PIN(GPIODV_29, 0) };
+
+static const unsigned int xtal24_out_pins[]    = { PIN(GPIODV_29, 0) };
+
+static const unsigned int uart_tx_c_pins[]     = { PIN(GPIODV_24, 0) };
+static const unsigned int uart_rx_c_pins[]     = { PIN(GPIODV_25, 0) };
+static const unsigned int uart_cts_c_pins[]    = { PIN(GPIODV_26, 0) };
+static const unsigned int uart_rts_c_pins[]    = { PIN(GPIODV_27, 0) };
+
+static const unsigned int pwm_c1_pins[]                = { PIN(GPIODV_9, 0) };
+
+static const unsigned int i2c_sda_a_pins[]     = { PIN(GPIODV_24, 0) };
+static const unsigned int i2c_sck_a_pins[]     = { PIN(GPIODV_25, 0) };
+static const unsigned int i2c_sda_b0_pins[]    = { PIN(GPIODV_26, 0) };
+static const unsigned int i2c_sck_b0_pins[]    = { PIN(GPIODV_27, 0) };
+static const unsigned int i2c_sda_c0_pins[]    = { PIN(GPIODV_28, 0) };
+static const unsigned int i2c_sck_c0_pins[]    = { PIN(GPIODV_29, 0) };
+
+/* bank H */
+static const unsigned int hdmi_hpd_pins[]      = { PIN(GPIOH_0, 0) };
+static const unsigned int hdmi_sda_pins[]      = { PIN(GPIOH_1, 0) };
+static const unsigned int hdmi_scl_pins[]      = { PIN(GPIOH_2, 0) };
+static const unsigned int hdmi_cec_0_pins[]    = { PIN(GPIOH_3, 0) };
+static const unsigned int eth_txd1_0_pins[]    = { PIN(GPIOH_5, 0) };
+static const unsigned int eth_txd0_0_pins[]    = { PIN(GPIOH_6, 0) };
+static const unsigned int clk_24m_out_pins[]   = { PIN(GPIOH_9, 0) };
+
+static const unsigned int spi_ss1_pins[]       = { PIN(GPIOH_0, 0) };
+static const unsigned int spi_ss2_pins[]       = { PIN(GPIOH_1, 0) };
+static const unsigned int spi_ss0_1_pins[]     = { PIN(GPIOH_3, 0) };
+static const unsigned int spi_miso_1_pins[]    = { PIN(GPIOH_4, 0) };
+static const unsigned int spi_mosi_1_pins[]    = { PIN(GPIOH_5, 0) };
+static const unsigned int spi_sclk_1_pins[]    = { PIN(GPIOH_6, 0) };
+
+static const unsigned int eth_txd3_pins[]      = { PIN(GPIOH_7, 0) };
+static const unsigned int eth_txd2_pins[]      = { PIN(GPIOH_8, 0) };
+static const unsigned int eth_tx_clk_pins[]    = { PIN(GPIOH_9, 0) };
+
+static const unsigned int i2c_sda_b1_pins[]    = { PIN(GPIOH_3, 0) };
+static const unsigned int i2c_sck_b1_pins[]    = { PIN(GPIOH_4, 0) };
+static const unsigned int i2c_sda_c1_pins[]    = { PIN(GPIOH_5, 0) };
+static const unsigned int i2c_sck_c1_pins[]    = { PIN(GPIOH_6, 0) };
+static const unsigned int i2c_sda_d1_pins[]    = { PIN(GPIOH_7, 0) };
+static const unsigned int i2c_sck_d1_pins[]    = { PIN(GPIOH_8, 0) };
+
+/* bank BOOT */
+static const unsigned int nand_io_pins[]       = { PIN(BOOT_0, 0), PIN(BOOT_1, 0),
+                                                   PIN(BOOT_2, 0), PIN(BOOT_3, 0),
+                                                   PIN(BOOT_4, 0), PIN(BOOT_5, 0),
+                                                   PIN(BOOT_6, 0), PIN(BOOT_7, 0) };
+static const unsigned int nand_io_ce0_pins[]   = { PIN(BOOT_8, 0) };
+static const unsigned int nand_io_ce1_pins[]   = { PIN(BOOT_9, 0) };
+static const unsigned int nand_io_rb0_pins[]   = { PIN(BOOT_10, 0) };
+static const unsigned int nand_ale_pins[]      = { PIN(BOOT_11, 0) };
+static const unsigned int nand_cle_pins[]      = { PIN(BOOT_12, 0) };
+static const unsigned int nand_wen_clk_pins[]  = { PIN(BOOT_13, 0) };
+static const unsigned int nand_ren_clk_pins[]  = { PIN(BOOT_14, 0) };
+static const unsigned int nand_dqs_0_pins[]    = { PIN(BOOT_15, 0) };
+static const unsigned int nand_dqs_1_pins[]    = { PIN(BOOT_18, 0) };
+
+static const unsigned int sdxc_d0_c_pins[]     = { PIN(BOOT_0, 0)};
+static const unsigned int sdxc_d13_c_pins[]    = { PIN(BOOT_1, 0), PIN(BOOT_2, 0),
+                                                   PIN(BOOT_3, 0) };
+static const unsigned int sdxc_d47_c_pins[]    = { PIN(BOOT_4, 0), PIN(BOOT_5, 0),
+                                                   PIN(BOOT_6, 0), PIN(BOOT_7, 0) };
+static const unsigned int sdxc_clk_c_pins[]    = { PIN(BOOT_8, 0) };
+static const unsigned int sdxc_cmd_c_pins[]    = { PIN(BOOT_10, 0) };
+static const unsigned int nor_d_pins[]         = { PIN(BOOT_11, 0) };
+static const unsigned int nor_q_pins[]         = { PIN(BOOT_12, 0) };
+static const unsigned int nor_c_pins[]         = { PIN(BOOT_13, 0) };
+static const unsigned int nor_cs_pins[]                = { PIN(BOOT_18, 0) };
+
+static const unsigned int sd_d0_c_pins[]       = { PIN(BOOT_0, 0) };
+static const unsigned int sd_d1_c_pins[]       = { PIN(BOOT_1, 0) };
+static const unsigned int sd_d2_c_pins[]       = { PIN(BOOT_2, 0) };
+static const unsigned int sd_d3_c_pins[]       = { PIN(BOOT_3, 0) };
+static const unsigned int sd_cmd_c_pins[]      = { PIN(BOOT_8, 0) };
+static const unsigned int sd_clk_c_pins[]      = { PIN(BOOT_10, 0) };
+
+/* bank CARD */
+static const unsigned int sd_d1_b_pins[]       = { PIN(CARD_0, 0) };
+static const unsigned int sd_d0_b_pins[]       = { PIN(CARD_1, 0) };
+static const unsigned int sd_clk_b_pins[]      = { PIN(CARD_2, 0) };
+static const unsigned int sd_cmd_b_pins[]      = { PIN(CARD_3, 0) };
+static const unsigned int sd_d3_b_pins[]       = { PIN(CARD_4, 0) };
+static const unsigned int sd_d2_b_pins[]       = { PIN(CARD_5, 0) };
+
+static const unsigned int sdxc_d13_b_pins[]    = { PIN(CARD_0, 0), PIN(CARD_4, 0),
+                                                   PIN(CARD_5, 0) };
+static const unsigned int sdxc_d0_b_pins[]     = { PIN(CARD_1, 0) };
+static const unsigned int sdxc_clk_b_pins[]    = { PIN(CARD_2, 0) };
+static const unsigned int sdxc_cmd_b_pins[]    = { PIN(CARD_3, 0) };
+
+/* bank AO */
+static const unsigned int uart_tx_ao_a_pins[]  = { PIN(GPIOAO_0, AO_OFF) };
+static const unsigned int uart_rx_ao_a_pins[]  = { PIN(GPIOAO_1, AO_OFF) };
+static const unsigned int uart_cts_ao_a_pins[] = { PIN(GPIOAO_2, AO_OFF) };
+static const unsigned int uart_rts_ao_a_pins[] = { PIN(GPIOAO_3, AO_OFF) };
+static const unsigned int i2c_mst_sck_ao_pins[] = { PIN(GPIOAO_4, AO_OFF) };
+static const unsigned int i2c_mst_sda_ao_pins[] = { PIN(GPIOAO_5, AO_OFF) };
+static const unsigned int clk_32k_in_out_pins[]        = { PIN(GPIOAO_6, AO_OFF) };
+static const unsigned int remote_input_pins[]  = { PIN(GPIOAO_7, AO_OFF) };
+static const unsigned int hdmi_cec_1_pins[]    = { PIN(GPIOAO_12, AO_OFF) };
+static const unsigned int ir_blaster_pins[]    = { PIN(GPIOAO_13, AO_OFF) };
+
+static const unsigned int pwm_c2_pins[]                = { PIN(GPIOAO_3, AO_OFF) };
+static const unsigned int i2c_sck_ao_pins[]    = { PIN(GPIOAO_4, AO_OFF) };
+static const unsigned int i2c_sda_ao_pins[]    = { PIN(GPIOAO_5, AO_OFF) };
+static const unsigned int ir_remote_out_pins[] = { PIN(GPIOAO_7, AO_OFF) };
+static const unsigned int i2s_am_clk_out_pins[]        = { PIN(GPIOAO_8, AO_OFF) };
+static const unsigned int i2s_ao_clk_out_pins[]        = { PIN(GPIOAO_9, AO_OFF) };
+static const unsigned int i2s_lr_clk_out_pins[]        = { PIN(GPIOAO_10, AO_OFF) };
+static const unsigned int i2s_out_01_pins[]    = { PIN(GPIOAO_11, AO_OFF) };
+
+static const unsigned int uart_tx_ao_b0_pins[] = { PIN(GPIOAO_0, AO_OFF) };
+static const unsigned int uart_rx_ao_b0_pins[] = { PIN(GPIOAO_1, AO_OFF) };
+static const unsigned int uart_cts_ao_b_pins[] = { PIN(GPIOAO_2, AO_OFF) };
+static const unsigned int uart_rts_ao_b_pins[] = { PIN(GPIOAO_3, AO_OFF) };
+static const unsigned int uart_tx_ao_b1_pins[] = { PIN(GPIOAO_4, AO_OFF) };
+static const unsigned int uart_rx_ao_b1_pins[] = { PIN(GPIOAO_5, AO_OFF) };
+static const unsigned int spdif_out_1_pins[]   = { PIN(GPIOAO_6, AO_OFF) };
+
+static const unsigned int i2s_in_ch01_pins[]   = { PIN(GPIOAO_6, AO_OFF) };
+static const unsigned int i2s_ao_clk_in_pins[] = { PIN(GPIOAO_9, AO_OFF) };
+static const unsigned int i2s_lr_clk_in_pins[] = { PIN(GPIOAO_10, AO_OFF) };
+
+/* bank DIF */
+static const unsigned int eth_rxd1_pins[]      = { PIN(DIF_0_P, 0) };
+static const unsigned int eth_rxd0_pins[]      = { PIN(DIF_0_N, 0) };
+static const unsigned int eth_rx_dv_pins[]     = { PIN(DIF_1_P, 0) };
+static const unsigned int eth_rx_clk_pins[]    = { PIN(DIF_1_N, 0) };
+static const unsigned int eth_txd0_1_pins[]    = { PIN(DIF_2_P, 0) };
+static const unsigned int eth_txd1_1_pins[]    = { PIN(DIF_2_N, 0) };
+static const unsigned int eth_tx_en_pins[]     = { PIN(DIF_3_P, 0) };
+static const unsigned int eth_ref_clk_pins[]   = { PIN(DIF_3_N, 0) };
+static const unsigned int eth_mdc_pins[]       = { PIN(DIF_4_P, 0) };
+static const unsigned int eth_mdio_en_pins[]   = { PIN(DIF_4_N, 0) };
+
+static struct meson_pmx_group meson8b_groups[] = {
+       GPIO_GROUP(GPIOX_0, 0),
+       GPIO_GROUP(GPIOX_1, 0),
+       GPIO_GROUP(GPIOX_2, 0),
+       GPIO_GROUP(GPIOX_3, 0),
+       GPIO_GROUP(GPIOX_4, 0),
+       GPIO_GROUP(GPIOX_5, 0),
+       GPIO_GROUP(GPIOX_6, 0),
+       GPIO_GROUP(GPIOX_7, 0),
+       GPIO_GROUP(GPIOX_8, 0),
+       GPIO_GROUP(GPIOX_9, 0),
+       GPIO_GROUP(GPIOX_10, 0),
+       GPIO_GROUP(GPIOX_11, 0),
+       GPIO_GROUP(GPIOX_16, 0),
+       GPIO_GROUP(GPIOX_17, 0),
+       GPIO_GROUP(GPIOX_18, 0),
+       GPIO_GROUP(GPIOX_19, 0),
+       GPIO_GROUP(GPIOX_20, 0),
+       GPIO_GROUP(GPIOX_21, 0),
+
+       GPIO_GROUP(GPIOY_0, 0),
+       GPIO_GROUP(GPIOY_1, 0),
+       GPIO_GROUP(GPIOY_3, 0),
+       GPIO_GROUP(GPIOY_6, 0),
+       GPIO_GROUP(GPIOY_7, 0),
+       GPIO_GROUP(GPIOY_8, 0),
+       GPIO_GROUP(GPIOY_9, 0),
+       GPIO_GROUP(GPIOY_10, 0),
+       GPIO_GROUP(GPIOY_11, 0),
+       GPIO_GROUP(GPIOY_12, 0),
+       GPIO_GROUP(GPIOY_13, 0),
+       GPIO_GROUP(GPIOY_14, 0),
+
+       GPIO_GROUP(GPIODV_9, 0),
+       GPIO_GROUP(GPIODV_24, 0),
+       GPIO_GROUP(GPIODV_25, 0),
+       GPIO_GROUP(GPIODV_26, 0),
+       GPIO_GROUP(GPIODV_27, 0),
+       GPIO_GROUP(GPIODV_28, 0),
+       GPIO_GROUP(GPIODV_29, 0),
+
+       GPIO_GROUP(GPIOH_0, 0),
+       GPIO_GROUP(GPIOH_1, 0),
+       GPIO_GROUP(GPIOH_2, 0),
+       GPIO_GROUP(GPIOH_3, 0),
+       GPIO_GROUP(GPIOH_4, 0),
+       GPIO_GROUP(GPIOH_5, 0),
+       GPIO_GROUP(GPIOH_6, 0),
+       GPIO_GROUP(GPIOH_7, 0),
+       GPIO_GROUP(GPIOH_8, 0),
+       GPIO_GROUP(GPIOH_9, 0),
+
+       GPIO_GROUP(DIF_0_P, 0),
+       GPIO_GROUP(DIF_0_N, 0),
+       GPIO_GROUP(DIF_1_P, 0),
+       GPIO_GROUP(DIF_1_N, 0),
+       GPIO_GROUP(DIF_2_P, 0),
+       GPIO_GROUP(DIF_2_N, 0),
+       GPIO_GROUP(DIF_3_P, 0),
+       GPIO_GROUP(DIF_3_N, 0),
+       GPIO_GROUP(DIF_4_P, 0),
+       GPIO_GROUP(DIF_4_N, 0),
+
+       GPIO_GROUP(GPIOAO_0, AO_OFF),
+       GPIO_GROUP(GPIOAO_1, AO_OFF),
+       GPIO_GROUP(GPIOAO_2, AO_OFF),
+       GPIO_GROUP(GPIOAO_3, AO_OFF),
+       GPIO_GROUP(GPIOAO_4, AO_OFF),
+       GPIO_GROUP(GPIOAO_5, AO_OFF),
+       GPIO_GROUP(GPIOAO_6, AO_OFF),
+       GPIO_GROUP(GPIOAO_7, AO_OFF),
+       GPIO_GROUP(GPIOAO_8, AO_OFF),
+       GPIO_GROUP(GPIOAO_9, AO_OFF),
+       GPIO_GROUP(GPIOAO_10, AO_OFF),
+       GPIO_GROUP(GPIOAO_11, AO_OFF),
+       GPIO_GROUP(GPIOAO_12, AO_OFF),
+       GPIO_GROUP(GPIOAO_13, AO_OFF),
+       GPIO_GROUP(GPIO_BSD_EN, AO_OFF),
+       GPIO_GROUP(GPIO_TEST_N, AO_OFF),
+
+       /* bank X */
+       GROUP(sd_d0_a,          8,      5),
+       GROUP(sd_d1_a,          8,      4),
+       GROUP(sd_d2_a,          8,      3),
+       GROUP(sd_d3_a,          8,      2),
+       GROUP(sdxc_d0_0_a,      5,      29),
+       GROUP(sdxc_d47_a,       5,      12),
+       GROUP(sdxc_d13_0_a,     5,      28),
+       GROUP(sd_clk_a,         8,      1),
+       GROUP(sd_cmd_a,         8,      0),
+       GROUP(xtal_32k_out,     3,      22),
+       GROUP(xtal_24m_out,     3,      20),
+       GROUP(uart_tx_b0,       4,      9),
+       GROUP(uart_rx_b0,       4,      8),
+       GROUP(uart_cts_b0,      4,      7),
+       GROUP(uart_rts_b0,      4,      6),
+       GROUP(sdxc_d0_1_a,      5,      14),
+       GROUP(sdxc_d13_1_a,     5,      13),
+       GROUP(pcm_out_a,        3,      30),
+       GROUP(pcm_in_a,         3,      29),
+       GROUP(pcm_fs_a,         3,      28),
+       GROUP(pcm_clk_a,        3,      27),
+       GROUP(sdxc_clk_a,       5,      11),
+       GROUP(sdxc_cmd_a,       5,      10),
+       GROUP(pwm_vs_0,         7,      31),
+       GROUP(pwm_e,            9,      19),
+       GROUP(pwm_vs_1,         7,      30),
+       GROUP(uart_tx_a,        4,      17),
+       GROUP(uart_rx_a,        4,      16),
+       GROUP(uart_cts_a,       4,      15),
+       GROUP(uart_rts_a,       4,      14),
+       GROUP(uart_tx_b1,       6,      19),
+       GROUP(uart_rx_b1,       6,      18),
+       GROUP(uart_cts_b1,      6,      17),
+       GROUP(uart_rts_b1,      6,      16),
+       GROUP(iso7816_0_clk,    5,      9),
+       GROUP(iso7816_0_data,   5,      8),
+       GROUP(spi_sclk_0,       4,      22),
+       GROUP(spi_miso_0,       4,      24),
+       GROUP(spi_mosi_0,       4,      23),
+       GROUP(iso7816_det,      4,      21),
+       GROUP(iso7816_reset,    4,      20),
+       GROUP(iso7816_1_clk,    4,      19),
+       GROUP(iso7816_1_data,   4,      18),
+       GROUP(spi_ss0_0,        4,      25),
+       GROUP(tsin_clk_b,       3,      6),
+       GROUP(tsin_sop_b,       3,      7),
+       GROUP(tsin_d0_b,        3,      8),
+       GROUP(pwm_b,            2,      3),
+       GROUP(i2c_sda_d0,       4,      5),
+       GROUP(i2c_sck_d0,       4,      4),
+       GROUP(tsin_d_valid_b,   3,      9),
+
+       /* bank Y */
+       GROUP(tsin_d_valid_a,   3,      2),
+       GROUP(tsin_sop_a,       3,      1),
+       GROUP(tsin_d17_a,       3,      5),
+       GROUP(tsin_clk_a,       3,      0),
+       GROUP(tsin_d0_a,        3,      4),
+       GROUP(spdif_out_0,      1,      7),
+       GROUP(xtal_24m,         3,      18),
+       GROUP(iso7816_2_clk,    5,      7),
+       GROUP(iso7816_2_data,   5,      6),
+
+       /* bank DV */
+       GROUP(pwm_d,            3,      26),
+       GROUP(pwm_c0,           3,      25),
+       GROUP(pwm_vs_2,         7,      28),
+       GROUP(pwm_vs_3,         7,      27),
+       GROUP(pwm_vs_4,         7,      26),
+       GROUP(xtal24_out,       7,      25),
+       GROUP(uart_tx_c,        6,      23),
+       GROUP(uart_rx_c,        6,      22),
+       GROUP(uart_cts_c,       6,      21),
+       GROUP(uart_rts_c,       6,      20),
+       GROUP(pwm_c1,           3,      24),
+       GROUP(i2c_sda_a,        9,      31),
+       GROUP(i2c_sck_a,        9,      30),
+       GROUP(i2c_sda_b0,       9,      29),
+       GROUP(i2c_sck_b0,       9,      28),
+       GROUP(i2c_sda_c0,       9,      27),
+       GROUP(i2c_sck_c0,       9,      26),
+
+       /* bank H */
+       GROUP(hdmi_hpd,         1,      26),
+       GROUP(hdmi_sda,         1,      25),
+       GROUP(hdmi_scl,         1,      24),
+       GROUP(hdmi_cec_0,       1,      23),
+       GROUP(eth_txd1_0,       7,      21),
+       GROUP(eth_txd0_0,       7,      20),
+       GROUP(clk_24m_out,      4,      1),
+       GROUP(spi_ss1,          8,      11),
+       GROUP(spi_ss2,          8,      12),
+       GROUP(spi_ss0_1,        9,      13),
+       GROUP(spi_miso_1,       9,      12),
+       GROUP(spi_mosi_1,       9,      11),
+       GROUP(spi_sclk_1,       9,      10),
+       GROUP(eth_txd3,         6,      13),
+       GROUP(eth_txd2,         6,      12),
+       GROUP(eth_tx_clk,       6,      11),
+       GROUP(i2c_sda_b1,       5,      27),
+       GROUP(i2c_sck_b1,       5,      26),
+       GROUP(i2c_sda_c1,       5,      25),
+       GROUP(i2c_sck_c1,       5,      24),
+       GROUP(i2c_sda_d1,       4,      3),
+       GROUP(i2c_sck_d1,       4,      2),
+
+       /* bank BOOT */
+       GROUP(nand_io,          2,      26),
+       GROUP(nand_io_ce0,      2,      25),
+       GROUP(nand_io_ce1,      2,      24),
+       GROUP(nand_io_rb0,      2,      17),
+       GROUP(nand_ale,         2,      21),
+       GROUP(nand_cle,         2,      20),
+       GROUP(nand_wen_clk,     2,      19),
+       GROUP(nand_ren_clk,     2,      18),
+       GROUP(nand_dqs_0,       2,      27),
+       GROUP(nand_dqs_1,       2,      28),
+       GROUP(sdxc_d0_c,        4,      30),
+       GROUP(sdxc_d13_c,       4,      29),
+       GROUP(sdxc_d47_c,       4,      28),
+       GROUP(sdxc_clk_c,       7,      19),
+       GROUP(sdxc_cmd_c,       7,      18),
+       GROUP(nor_d,            5,      1),
+       GROUP(nor_q,            5,      3),
+       GROUP(nor_c,            5,      2),
+       GROUP(nor_cs,           5,      0),
+       GROUP(sd_d0_c,          6,      29),
+       GROUP(sd_d1_c,          6,      28),
+       GROUP(sd_d2_c,          6,      27),
+       GROUP(sd_d3_c,          6,      26),
+       GROUP(sd_cmd_c,         6,      30),
+       GROUP(sd_clk_c,         6,      31),
+
+       /* bank CARD */
+       GROUP(sd_d1_b,          2,      14),
+       GROUP(sd_d0_b,          2,      15),
+       GROUP(sd_clk_b,         2,      11),
+       GROUP(sd_cmd_b,         2,      10),
+       GROUP(sd_d3_b,          2,      12),
+       GROUP(sd_d2_b,          2,      13),
+       GROUP(sdxc_d13_b,       2,      6),
+       GROUP(sdxc_d0_b,        2,      7),
+       GROUP(sdxc_clk_b,       2,      5),
+       GROUP(sdxc_cmd_b,       2,      4),
+
+       /* bank AO */
+       GROUP(uart_tx_ao_a,     0,      12),
+       GROUP(uart_rx_ao_a,     0,      11),
+       GROUP(uart_cts_ao_a,    0,      10),
+       GROUP(uart_rts_ao_a,    0,      9),
+       GROUP(i2c_mst_sck_ao,   0,      6),
+       GROUP(i2c_mst_sda_ao,   0,      5),
+       GROUP(clk_32k_in_out,   0,      18),
+       GROUP(remote_input,     0,      0),
+       GROUP(hdmi_cec_1,       0,      17),
+       GROUP(ir_blaster,       0,      31),
+       GROUP(pwm_c2,           0,      22),
+       GROUP(i2c_sck_ao,       0,      2),
+       GROUP(i2c_sda_ao,       0,      1),
+       GROUP(ir_remote_out,    0,      21),
+       GROUP(i2s_am_clk_out,   0,      30),
+       GROUP(i2s_ao_clk_out,   0,      29),
+       GROUP(i2s_lr_clk_out,   0,      28),
+       GROUP(i2s_out_01,       0,      27),
+       GROUP(uart_tx_ao_b0,    0,      26),
+       GROUP(uart_rx_ao_b0,    0,      25),
+       GROUP(uart_cts_ao_b,    0,      8),
+       GROUP(uart_rts_ao_b,    0,      7),
+       GROUP(uart_tx_ao_b1,    0,      24),
+       GROUP(uart_rx_ao_b1,    0,      23),
+       GROUP(spdif_out_1,      0,      16),
+       GROUP(i2s_in_ch01,      0,      13),
+       GROUP(i2s_ao_clk_in,    0,      15),
+       GROUP(i2s_lr_clk_in,    0,      14),
+
+       /* bank DIF */
+       GROUP(eth_rxd1,         6,      0),
+       GROUP(eth_rxd0,         6,      1),
+       GROUP(eth_rx_dv,        6,      2),
+       GROUP(eth_rx_clk,       6,      3),
+       GROUP(eth_txd0_1,       6,      4),
+       GROUP(eth_txd1_1,       6,      5),
+       GROUP(eth_tx_en,        6,      0),
+       GROUP(eth_ref_clk,      6,      8),
+       GROUP(eth_mdc,          6,      9),
+       GROUP(eth_mdio_en,      6,      10),
+};
+
+static const char * const gpio_groups[] = {
+       "GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4",
+       "GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9",
+       "GPIOX_10", "GPIOX_11", "GPIOX_16", "GPIOX_17", "GPIOX_18",
+       "GPIOX_19", "GPIOX_20", "GPIOX_21",
+
+       "GPIOY_0", "GPIOY_1", "GPIOY_3", "GPIOY_6", "GPIOY_7",
+       "GPIOY_8", "GPIOY_9", "GPIOY_10", "GPIOY_11", "GPIOY_12",
+       "GPIOY_13", "GPIOY_14",
+
+       "GPIODV_9", "GPIODV_24", "GPIODV_25", "GPIODV_26",
+       "GPIODV_27", "GPIODV_28", "GPIODV_29",
+
+       "GPIOH_0", "GPIOH_1", "GPIOH_2", "GPIOH_3", "GPIOH_4",
+       "GPIOH_5", "GPIOH_6", "GPIOH_7", "GPIOH_8", "GPIOH_9",
+
+       "CARD_0", "CARD_1", "CARD_2", "CARD_3", "CARD_4",
+       "CARD_5", "CARD_6",
+
+       "BOOT_0", "BOOT_1", "BOOT_2", "BOOT_3", "BOOT_4",
+       "BOOT_5", "BOOT_6", "BOOT_7", "BOOT_8", "BOOT_9",
+       "BOOT_10", "BOOT_11", "BOOT_12", "BOOT_13", "BOOT_14",
+       "BOOT_15", "BOOT_16", "BOOT_17", "BOOT_18",
+
+       "GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3",
+       "GPIOAO_4", "GPIOAO_5", "GPIOAO_6", "GPIOAO_7",
+       "GPIOAO_8", "GPIOAO_9", "GPIOAO_10", "GPIOAO_11",
+       "GPIOAO_12", "GPIOAO_13", "GPIO_BSD_EN", "GPIO_TEST_N",
+
+       "DIF_0_P", "DIF_0_N", "DIF_1_P", "DIF_1_N",
+       "DIF_2_P", "DIF_2_N", "DIF_3_P", "DIF_3_N",
+       "DIF_4_P", "DIF_4_N"
+};
+
+static const char * const sd_a_groups[] = {
+       "sd_d0_a", "sd_d1_a", "sd_d2_a", "sd_d3_a", "sd_clk_a",
+       "sd_cmd_a"
+};
+
+static const char * const sdxc_a_groups[] = {
+       "sdxc_d0_0_a", "sdxc_d13_0_a", "sdxc_d47_a", "sdxc_clk_a",
+       "sdxc_cmd_a", "sdxc_d0_1_a", "sdxc_d0_13_1_a"
+};
+
+static const char * const pcm_a_groups[] = {
+       "pcm_out_a", "pcm_in_a", "pcm_fs_a", "pcm_clk_a"
+};
+
+static const char * const uart_a_groups[] = {
+       "uart_tx_a", "uart_rx_a", "uart_cts_a", "uart_rts_a"
+};
+
+static const char * const uart_b_groups[] = {
+       "uart_tx_b0", "uart_rx_b0", "uart_cts_b0", "uart_rts_b0",
+       "uart_tx_b1", "uart_rx_b1", "uart_cts_b1", "uart_rts_b1"
+};
+
+static const char * const iso7816_groups[] = {
+       "iso7816_det", "iso7816_reset", "iso7816_0_clk", "iso7816_0_data",
+       "iso7816_1_clk", "iso7816_1_data", "iso7816_2_clk", "iso7816_2_data"
+};
+
+static const char * const i2c_d_groups[] = {
+       "i2c_sda_d0", "i2c_sck_d0", "i2c_sda_d1", "i2c_sck_d1"
+};
+
+static const char * const xtal_groups[] = {
+       "xtal_32k_out", "xtal_24m_out", "xtal_24m", "xtal24_out"
+};
+
+static const char * const uart_c_groups[] = {
+       "uart_tx_c", "uart_rx_c", "uart_cts_c", "uart_rts_c"
+};
+
+static const char * const i2c_c_groups[] = {
+       "i2c_sda_c0", "i2c_sck_c0", "i2c_sda_c1", "i2c_sck_c1"
+};
+
+static const char * const hdmi_groups[] = {
+       "hdmi_hpd", "hdmi_sda", "hdmi_scl", "hdmi_cec_0",
+       "hdmi_cec_1"
+};
+
+static const char * const spi_groups[] = {
+       "spi_ss0_0", "spi_miso_0", "spi_mosi_0", "spi_sclk_0",
+       "spi_ss0_1", "spi_ss1", "spi_sclk_1", "spi_mosi_1",
+       "spi_miso_1", "spi_ss2"
+};
+
+static const char * const ethernet_groups[] = {
+       "eth_tx_clk", "eth_tx_en", "eth_txd1_0", "eth_txd1_1",
+       "eth_txd0_0", "eth_txd0_1", "eth_rx_clk", "eth_rx_dv",
+       "eth_rxd1", "eth_rxd0", "eth_mdio_en", "eth_mdc", "eth_ref_clk",
+       "eth_txd2", "eth_txd3"
+};
+
+static const char * const i2c_a_groups[] = {
+       "i2c_sda_a", "i2c_sck_a",
+};
+
+static const char * const i2c_b_groups[] = {
+       "i2c_sda_b0", "i2c_sck_b0", "i2c_sda_b1", "i2c_sck_b1"
+};
+
+static const char * const sd_c_groups[] = {
+       "sd_d0_c", "sd_d1_c", "sd_d2_c", "sd_d3_c",
+       "sd_cmd_c", "sd_clk_c"
+};
+
+static const char * const sdxc_c_groups[] = {
+       "sdxc_d0_c", "sdxc_d13_c", "sdxc_d47_c", "sdxc_cmd_c",
+       "sdxc_clk_c"
+};
+
+static const char * const nand_groups[] = {
+       "nand_io", "nand_io_ce0", "nand_io_ce1",
+       "nand_io_rb0", "nand_ale", "nand_cle",
+       "nand_wen_clk", "nand_ren_clk", "nand_dqs0",
+       "nand_dqs1"
+};
+
+static const char * const nor_groups[] = {
+       "nor_d", "nor_q", "nor_c", "nor_cs"
+};
+
+static const char * const sd_b_groups[] = {
+       "sd_d1_b", "sd_d0_b", "sd_clk_b", "sd_cmd_b",
+       "sd_d3_b", "sd_d2_b"
+};
+
+static const char * const sdxc_b_groups[] = {
+       "sdxc_d13_b", "sdxc_d0_b", "sdxc_clk_b", "sdxc_cmd_b"
+};
+
+static const char * const uart_ao_groups[] = {
+       "uart_tx_ao_a", "uart_rx_ao_a", "uart_cts_ao_a", "uart_rts_ao_a"
+};
+
+static const char * const remote_groups[] = {
+       "remote_input", "ir_blaster", "ir_remote_out"
+};
+
+static const char * const i2c_slave_ao_groups[] = {
+       "i2c_sck_ao", "i2c_sda_ao"
+};
+
+static const char * const uart_ao_b_groups[] = {
+       "uart_tx_ao_b0", "uart_rx_ao_b0", "uart_tx_ao_b1", "uart_rx_ao_b1",
+       "uart_cts_ao_b", "uart_rts_ao_b"
+};
+
+static const char * const i2c_mst_ao_groups[] = {
+       "i2c_mst_sck_ao", "i2c_mst_sda_ao"
+};
+
+static const char * const clk_groups[] = {
+       "clk_24m_out", "clk_32k_in_out"
+};
+
+static const char * const spdif_groups[] = {
+       "spdif_out_1", "spdif_out_0"
+};
+
+static const char * const i2s_groups[] = {
+       "i2s_am_clk_out", "i2s_ao_clk_out", "i2s_lr_clk_out",
+       "i2s_out_01", "i2s_in_ch01", "i2s_ao_clk_in",
+       "i2s_lr_clk_in"
+};
+
+static const char * const pwm_b_groups[] = {
+       "pwm_b"
+};
+
+static const char * const pwm_c_groups[] = {
+       "pwm_c0", "pwm_c1", "pwm_c2"
+};
+
+static const char * const pwm_d_groups[] = {
+       "pwm_d"
+};
+
+static const char * const pwm_e_groups[] = {
+       "pwm_e"
+};
+
+static const char * const pwm_vs_groups[] = {
+       "pwm_vs_0", "pwm_vs_1", "pwm_vs_2",
+       "pwm_vs_3", "pwm_vs_4"
+};
+
+static const char * const tsin_a_groups[] = {
+       "tsin_d0_a", "tsin_d17_a", "tsin_clk_a", "tsin_sop_a",
+       "tsin_d_valid_a"
+};
+
+static const char * const tsin_b_groups[] = {
+       "tsin_d0_b", "tsin_clk_b", "tsin_sop_b", "tsin_d_valid_b"
+};
+
+static struct meson_pmx_func meson8b_functions[] = {
+       FUNCTION(gpio),
+       FUNCTION(sd_a),
+       FUNCTION(sdxc_a),
+       FUNCTION(pcm_a),
+       FUNCTION(uart_a),
+       FUNCTION(uart_b),
+       FUNCTION(iso7816),
+       FUNCTION(i2c_d),
+       FUNCTION(xtal),
+       FUNCTION(uart_c),
+       FUNCTION(i2c_c),
+       FUNCTION(hdmi),
+       FUNCTION(spi),
+       FUNCTION(ethernet),
+       FUNCTION(i2c_a),
+       FUNCTION(i2c_b),
+       FUNCTION(sd_c),
+       FUNCTION(sdxc_c),
+       FUNCTION(nand),
+       FUNCTION(nor),
+       FUNCTION(sd_b),
+       FUNCTION(sdxc_b),
+       FUNCTION(uart_ao),
+       FUNCTION(remote),
+       FUNCTION(i2c_slave_ao),
+       FUNCTION(uart_ao_b),
+       FUNCTION(i2c_mst_ao),
+       FUNCTION(clk),
+       FUNCTION(spdif),
+       FUNCTION(i2s),
+       FUNCTION(pwm_b),
+       FUNCTION(pwm_c),
+       FUNCTION(pwm_d),
+       FUNCTION(pwm_e),
+       FUNCTION(pwm_vs),
+       FUNCTION(tsin_a),
+       FUNCTION(tsin_b),
+};
+
+static struct meson_bank meson8b_banks[] = {
+       /*   name    first                      last                   pullen  pull    dir     out     in  */
+       BANK("X",    PIN(GPIOX_0, 0),           PIN(GPIOX_21, 0),      4,  0,  4,  0,  0,  0,  1,  0,  2,  0),
+       BANK("Y",    PIN(GPIOY_0, 0),           PIN(GPIOY_14, 0),      3,  0,  3,  0,  3,  0,  4,  0,  5,  0),
+       BANK("DV",   PIN(GPIODV_9, 0),          PIN(GPIODV_29, 0),     0,  0,  0,  0,  7,  0,  8,  0,  9,  0),
+       BANK("H",    PIN(GPIOH_0, 0),           PIN(GPIOH_9, 0),       1, 16,  1, 16,  9, 19, 10, 19, 11, 19),
+       BANK("CARD", PIN(CARD_0, 0),            PIN(CARD_6, 0),        2, 20,  2, 20,  0, 22,  1, 22,  2, 22),
+       BANK("BOOT", PIN(BOOT_0, 0),            PIN(BOOT_18, 0),       2,  0,  2,  0,  9,  0, 10,  0, 11,  0),
+       BANK("DIF",  PIN(DIF_0_P, 0),           PIN(DIF_4_N, 0),       5,  8,  5,  8, 12, 12, 13, 12, 14, 12),
+};
+
+static struct meson_bank meson8b_ao_banks[] = {
+       /*   name    first                  last                      pullen  pull    dir     out     in  */
+       BANK("AO",   PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
+};
+
+static struct meson_domain_data meson8b_domain_data[] = {
+       {
+               .name           = "banks",
+               .banks          = meson8b_banks,
+               .num_banks      = ARRAY_SIZE(meson8b_banks),
+               .pin_base       = 0,
+               .num_pins       = 83,
+       },
+       {
+               .name           = "ao-bank",
+               .banks          = meson8b_ao_banks,
+               .num_banks      = ARRAY_SIZE(meson8b_ao_banks),
+               .pin_base       = 83,
+               .num_pins       = 16,
+       },
+};
+
+struct meson_pinctrl_data meson8b_pinctrl_data = {
+       .pins           = meson8b_pins,
+       .groups         = meson8b_groups,
+       .funcs          = meson8b_functions,
+       .domain_data    = meson8b_domain_data,
+       .num_pins       = ARRAY_SIZE(meson8b_pins),
+       .num_groups     = ARRAY_SIZE(meson8b_groups),
+       .num_funcs      = ARRAY_SIZE(meson8b_functions),
+       .num_domains    = ARRAY_SIZE(meson8b_domain_data),
+};
index d6dd8358a6f60e519659aa51f01ae81fe630ca26..170602407c0d75c64d15531ac2e95ded9ceb3911 100644 (file)
@@ -26,6 +26,10 @@ config PINCTRL_ARMADA_38X
        bool
        select PINCTRL_MVEBU
 
+config PINCTRL_ARMADA_39X
+       bool
+       select PINCTRL_MVEBU
+
 config PINCTRL_ARMADA_XP
        bool
        select PINCTRL_MVEBU
index a0818e96374b7fa52a4f4b5d626a84ab1e963eff..554d8af14eebbb8d26e83ff64f7c1d01cebd0b91 100644 (file)
@@ -4,5 +4,6 @@ obj-$(CONFIG_PINCTRL_KIRKWOOD)  += pinctrl-kirkwood.o
 obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
 obj-$(CONFIG_PINCTRL_ARMADA_375) += pinctrl-armada-375.o
 obj-$(CONFIG_PINCTRL_ARMADA_38X) += pinctrl-armada-38x.o
+obj-$(CONFIG_PINCTRL_ARMADA_39X) += pinctrl-armada-39x.o
 obj-$(CONFIG_PINCTRL_ARMADA_XP)  += pinctrl-armada-xp.o
 obj-$(CONFIG_PINCTRL_ORION)  += pinctrl-orion.o
index c4f51d0cd2ccec322e0ede56e1b58f5386964c20..42f930f70de31e9086d4d7f7fec78a47d83cbfcc 100644 (file)
@@ -379,7 +379,7 @@ static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
 
 static struct mvebu_pinctrl_soc_info armada_370_pinctrl_info;
 
-static struct of_device_id armada_370_pinctrl_of_match[] = {
+static const struct of_device_id armada_370_pinctrl_of_match[] = {
        { .compatible = "marvell,mv88f6710-pinctrl" },
        { },
 };
index cd7c8f51f7d900c9a6e5f6c0c8b940c2cde3c2f4..ca1e7571fedb51475aba33c3004d9a781b8836b1 100644 (file)
@@ -399,7 +399,7 @@ static struct mvebu_mpp_mode mv88f6720_mpp_modes[] = {
 
 static struct mvebu_pinctrl_soc_info armada_375_pinctrl_info;
 
-static struct of_device_id armada_375_pinctrl_of_match[] = {
+static const struct of_device_id armada_375_pinctrl_of_match[] = {
        { .compatible = "marvell,mv88f6720-pinctrl" },
        { },
 };
index 7302f66f4f1990d4611a096a6beb62ee4193f2e5..83bbcc72be1f8ae582f056dfe02768516dc17ec1 100644 (file)
@@ -389,7 +389,7 @@ static struct mvebu_mpp_mode armada_38x_mpp_modes[] = {
 
 static struct mvebu_pinctrl_soc_info armada_38x_pinctrl_info;
 
-static struct of_device_id armada_38x_pinctrl_of_match[] = {
+static const struct of_device_id armada_38x_pinctrl_of_match[] = {
        {
                .compatible = "marvell,mv88f6810-pinctrl",
                .data       = (void *) V_88F6810,
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-39x.c b/drivers/pinctrl/mvebu/pinctrl-armada-39x.c
new file mode 100644 (file)
index 0000000..4249162
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * Marvell Armada 39x pinctrl driver based on mvebu pinctrl core
+ *
+ * Copyright (C) 2015 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@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.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+static void __iomem *mpp_base;
+
+static int armada_39x_mpp_ctrl_get(unsigned pid, unsigned long *config)
+{
+       return default_mpp_ctrl_get(mpp_base, pid, config);
+}
+
+static int armada_39x_mpp_ctrl_set(unsigned pid, unsigned long config)
+{
+       return default_mpp_ctrl_set(mpp_base, pid, config);
+}
+
+enum {
+       V_88F6920 = BIT(0),
+       V_88F6928 = BIT(1),
+       V_88F6920_PLUS = (V_88F6920 | V_88F6928),
+};
+
+static struct mvebu_mpp_mode armada_39x_mpp_modes[] = {
+       MPP_MODE(0,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "ua0",     "rxd",      V_88F6920_PLUS)),
+       MPP_MODE(1,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "ua0",     "txd",      V_88F6920_PLUS)),
+       MPP_MODE(2,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "i2c0",    "sck",      V_88F6920_PLUS)),
+       MPP_MODE(3,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "i2c0",    "sda",      V_88F6920_PLUS)),
+       MPP_MODE(4,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(2, "ua1",     "txd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "ua0",     "rts",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "smi",     "mdc",      V_88F6920_PLUS)),
+       MPP_MODE(5,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(2, "ua1",     "rxd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "ua0",     "cts",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "smi",     "mdio",     V_88F6920_PLUS)),
+       MPP_MODE(6,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "cs3",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "xsmi",    "mdio",     V_88F6920_PLUS)),
+       MPP_MODE(7,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad9",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "xsmi",    "mdc",      V_88F6920_PLUS)),
+       MPP_MODE(8,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad10",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "ptp",     "trig",     V_88F6920_PLUS)),
+       MPP_MODE(9,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad11",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "ptp",     "clk",      V_88F6920_PLUS)),
+       MPP_MODE(10,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad12",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "ptp",     "event",    V_88F6920_PLUS)),
+       MPP_MODE(11,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad13",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "led",     "clk",      V_88F6920_PLUS)),
+       MPP_MODE(12,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(2, "pcie0",   "rstout",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad14",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "led",     "stb",      V_88F6920_PLUS)),
+       MPP_MODE(13,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad15",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "led",     "data",     V_88F6920_PLUS)),
+       MPP_MODE(14,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "m",       "vtt",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "wen1",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "ua1",     "txd",      V_88F6920_PLUS)),
+       MPP_MODE(15,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "pcie0",   "rstout",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "spi0",    "mosi",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "i2c1",    "sck",      V_88F6920_PLUS)),
+       MPP_MODE(16,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "m",       "decc",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "spi0",    "miso",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "i2c1",    "sda",      V_88F6920_PLUS)),
+       MPP_MODE(17,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "ua1",     "rxd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "spi0",    "sck",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "smi",     "mdio",     V_88F6920_PLUS)),
+       MPP_MODE(18,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "ua1",     "txd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "spi0",    "cs0",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "i2c2",    "sck",      V_88F6920_PLUS)),
+       MPP_MODE(19,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "sata1",   "present",  V_88F6928),
+                MPP_VAR_FUNCTION(5, "ua0",     "cts",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(6, "ua1",     "rxd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "i2c2",    "sda",      V_88F6920_PLUS)),
+       MPP_MODE(20,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "sata0",   "present",  V_88F6928),
+                MPP_VAR_FUNCTION(5, "ua0",     "rts",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(6, "ua1",     "txd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "smi",     "mdc",      V_88F6920_PLUS)),
+       MPP_MODE(21,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "spi0",    "cs1",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "sata0",   "present",  V_88F6928),
+                MPP_VAR_FUNCTION(4, "sd",      "cmd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "bootcs",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(8, "ge",      "rxd0",     V_88F6920_PLUS)),
+       MPP_MODE(22,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "spi0",    "mosi",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad0",      V_88F6920_PLUS)),
+       MPP_MODE(23,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "spi0",    "sck",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad2",      V_88F6920_PLUS)),
+       MPP_MODE(24,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "spi0",    "miso",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(2, "ua0",     "cts",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "ua1",     "rxd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "sd",      "d4",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "readyn",   V_88F6920_PLUS)),
+       MPP_MODE(25,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "spi0",    "cs0",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(2, "ua0",     "rts",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "ua1",     "txd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "sd",      "d5",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "cs0",      V_88F6920_PLUS)),
+       MPP_MODE(26,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "spi0",    "cs2",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "i2c1",    "sck",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "sd",      "d6",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "cs1",      V_88F6920_PLUS)),
+       MPP_MODE(27,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "spi0",    "cs3",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "i2c1",    "sda",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "sd",      "d7",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "cs2",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(8, "ge",      "txclkout", V_88F6920_PLUS)),
+       MPP_MODE(28,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "sd",      "clk",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad5",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(8, "ge",      "txd0",     V_88F6920_PLUS)),
+       MPP_MODE(29,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ale0",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(8, "ge",      "txd1",     V_88F6920_PLUS)),
+       MPP_MODE(30,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "oen",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(8, "ge",      "txd2",     V_88F6920_PLUS)),
+       MPP_MODE(31,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ale1",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(8, "ge",      "txd3",     V_88F6920_PLUS)),
+       MPP_MODE(32,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "wen0",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(8, "ge",      "txctl",    V_88F6920_PLUS)),
+       MPP_MODE(33,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "m",       "decc",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad3",      V_88F6920_PLUS)),
+       MPP_MODE(34,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad1",      V_88F6920_PLUS)),
+       MPP_MODE(35,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "ref",     "clk",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "a1",       V_88F6920_PLUS)),
+       MPP_MODE(36,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "a0",       V_88F6920_PLUS)),
+       MPP_MODE(37,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "sd",      "d3",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad8",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(8, "ge",      "rxclk",    V_88F6920_PLUS)),
+       MPP_MODE(38,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "ref",     "clk",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "sd",      "d0",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad4",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(8, "ge",      "rxd1",     V_88F6920_PLUS)),
+       MPP_MODE(39,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "i2c1",    "sck",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "ua0",     "cts",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "sd",      "d1",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "a2",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(8, "ge",      "rxd2",     V_88F6920_PLUS)),
+       MPP_MODE(40,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "i2c1",    "sda",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "ua0",     "rts",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "sd",      "d2",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad6",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(8, "ge",      "rxd3",     V_88F6920_PLUS)),
+       MPP_MODE(41,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "ua1",     "rxd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "ua0",     "cts",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "spi1",    "cs3",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "burstn",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(6, "nd",      "rbn0",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(8, "ge",      "rxctl",    V_88F6920_PLUS)),
+       MPP_MODE(42,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "ua1",     "txd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "ua0",     "rts",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "ad7",      V_88F6920_PLUS)),
+       MPP_MODE(43,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "pcie0",   "clkreq",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(2, "m",       "vtt",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "m",       "decc",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "spi1",    "cs2",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "dev",     "clkout",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(6, "nd",      "rbn1",     V_88F6920_PLUS)),
+       MPP_MODE(44,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "sata0",   "present",  V_88F6928),
+                MPP_VAR_FUNCTION(2, "sata1",   "present",  V_88F6928),
+                MPP_VAR_FUNCTION(7, "led",     "clk",      V_88F6920_PLUS)),
+       MPP_MODE(45,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "ref",     "clk",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(2, "pcie0",   "rstout",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(6, "ua1",     "rxd",      V_88F6920_PLUS)),
+       MPP_MODE(46,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "ref",     "clk",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(2, "pcie0",   "rstout",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(6, "ua1",     "txd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "led",     "stb",      V_88F6920_PLUS)),
+       MPP_MODE(47,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "sata0",   "present",  V_88F6928),
+                MPP_VAR_FUNCTION(2, "sata1",   "present",  V_88F6928),
+                MPP_VAR_FUNCTION(7, "led",     "data",     V_88F6920_PLUS)),
+       MPP_MODE(48,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "sata0",   "present",  V_88F6928),
+                MPP_VAR_FUNCTION(2, "m",       "vtt",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "tdm",     "pclk",     V_88F6928),
+                MPP_VAR_FUNCTION(4, "audio",   "mclk",     V_88F6928),
+                MPP_VAR_FUNCTION(5, "sd",      "d4",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(6, "pcie0",   "clkreq",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "ua1",     "txd",      V_88F6920_PLUS)),
+       MPP_MODE(49,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "tdm",     "fsync",    V_88F6928),
+                MPP_VAR_FUNCTION(4, "audio",   "lrclk",    V_88F6928),
+                MPP_VAR_FUNCTION(5, "sd",      "d5",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "ua2",     "rxd",      V_88F6920_PLUS)),
+       MPP_MODE(50,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "pcie0",   "rstout",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "tdm",     "drx",      V_88F6928),
+                MPP_VAR_FUNCTION(4, "audio",   "extclk",   V_88F6928),
+                MPP_VAR_FUNCTION(5, "sd",      "cmd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "ua2",     "rxd",      V_88F6920_PLUS)),
+       MPP_MODE(51,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "tdm",     "dtx",      V_88F6928),
+                MPP_VAR_FUNCTION(4, "audio",   "sdo",      V_88F6928),
+                MPP_VAR_FUNCTION(5, "m",       "decc",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "ua2",     "txd",      V_88F6920_PLUS)),
+       MPP_MODE(52,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "pcie0",   "rstout",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "tdm",     "intn",     V_88F6928),
+                MPP_VAR_FUNCTION(4, "audio",   "sdi",      V_88F6928),
+                MPP_VAR_FUNCTION(5, "sd",      "d6",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "i2c3",    "sck",      V_88F6920_PLUS)),
+       MPP_MODE(53,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "sata1",   "present",  V_88F6928),
+                MPP_VAR_FUNCTION(2, "sata0",   "present",  V_88F6928),
+                MPP_VAR_FUNCTION(3, "tdm",     "rstn",     V_88F6928),
+                MPP_VAR_FUNCTION(4, "audio",   "bclk",     V_88F6928),
+                MPP_VAR_FUNCTION(5, "sd",      "d7",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "i2c3",    "sda",      V_88F6920_PLUS)),
+       MPP_MODE(54,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "sata0",   "present",  V_88F6928),
+                MPP_VAR_FUNCTION(2, "sata1",   "present",  V_88F6928),
+                MPP_VAR_FUNCTION(3, "pcie0",   "rstout",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "sd",      "d3",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "ua3",     "txd",      V_88F6920_PLUS)),
+       MPP_MODE(55,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "ua1",     "cts",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "spi1",    "cs1",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "sd",      "d0",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(6, "ua1",     "rxd",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(7, "ua3",     "rxd",      V_88F6920_PLUS)),
+       MPP_MODE(56,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "ua1",     "rts",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "m",       "decc",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "spi1",    "mosi",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(6, "ua1",     "txd",      V_88F6920_PLUS)),
+       MPP_MODE(57,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "spi1",    "sck",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "sd",      "clk",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(6, "ua1",     "txd",      V_88F6920_PLUS)),
+       MPP_MODE(58,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(2, "i2c1",    "sck",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(3, "pcie2",   "clkreq",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "spi1",    "miso",     V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "sd",      "d1",       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(6, "ua1",     "rxd",      V_88F6920_PLUS)),
+       MPP_MODE(59,
+                MPP_VAR_FUNCTION(0, "gpio",    NULL,       V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(1, "pcie0",   "rstout",   V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(2, "i2c1",    "sda",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(4, "spi1",    "cs0",      V_88F6920_PLUS),
+                MPP_VAR_FUNCTION(5, "sd",      "d2",       V_88F6920_PLUS)),
+};
+
+static struct mvebu_pinctrl_soc_info armada_39x_pinctrl_info;
+
+static const struct of_device_id armada_39x_pinctrl_of_match[] = {
+       {
+               .compatible = "marvell,mv88f6920-pinctrl",
+               .data       = (void *) V_88F6920,
+       },
+       {
+               .compatible = "marvell,mv88f6928-pinctrl",
+               .data       = (void *) V_88F6928,
+       },
+       { },
+};
+
+static struct mvebu_mpp_ctrl armada_39x_mpp_controls[] = {
+       MPP_FUNC_CTRL(0, 59, NULL, armada_39x_mpp_ctrl),
+};
+
+static struct pinctrl_gpio_range armada_39x_mpp_gpio_ranges[] = {
+       MPP_GPIO_RANGE(0,   0,  0, 32),
+       MPP_GPIO_RANGE(1,  32, 32, 27),
+};
+
+static int armada_39x_pinctrl_probe(struct platform_device *pdev)
+{
+       struct mvebu_pinctrl_soc_info *soc = &armada_39x_pinctrl_info;
+       const struct of_device_id *match =
+               of_match_device(armada_39x_pinctrl_of_match, &pdev->dev);
+       struct resource *res;
+
+       if (!match)
+               return -ENODEV;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       mpp_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(mpp_base))
+               return PTR_ERR(mpp_base);
+
+       soc->variant = (unsigned) match->data & 0xff;
+       soc->controls = armada_39x_mpp_controls;
+       soc->ncontrols = ARRAY_SIZE(armada_39x_mpp_controls);
+       soc->gpioranges = armada_39x_mpp_gpio_ranges;
+       soc->ngpioranges = ARRAY_SIZE(armada_39x_mpp_gpio_ranges);
+       soc->modes = armada_39x_mpp_modes;
+       soc->nmodes = armada_39x_mpp_controls[0].npins;
+
+       pdev->dev.platform_data = soc;
+
+       return mvebu_pinctrl_probe(pdev);
+}
+
+static int armada_39x_pinctrl_remove(struct platform_device *pdev)
+{
+       return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver armada_39x_pinctrl_driver = {
+       .driver = {
+               .name = "armada-39x-pinctrl",
+               .of_match_table = of_match_ptr(armada_39x_pinctrl_of_match),
+       },
+       .probe = armada_39x_pinctrl_probe,
+       .remove = armada_39x_pinctrl_remove,
+};
+
+module_platform_driver(armada_39x_pinctrl_driver);
+
+MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell Armada 39x pinctrl driver");
+MODULE_LICENSE("GPL v2");
index fc3376147c189962d30e4cd7aaf6a6246161f10e..578db9f033b23c001257d94fe90c39a9c20ca9f1 100644 (file)
@@ -34,6 +34,7 @@
 #include "pinctrl-mvebu.h"
 
 static void __iomem *mpp_base;
+static u32 *mpp_saved_regs;
 
 static int armada_xp_mpp_ctrl_get(unsigned pid, unsigned long *config)
 {
@@ -361,7 +362,7 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = {
 
 static struct mvebu_pinctrl_soc_info armada_xp_pinctrl_info;
 
-static struct of_device_id armada_xp_pinctrl_of_match[] = {
+static const struct of_device_id armada_xp_pinctrl_of_match[] = {
        {
                .compatible = "marvell,mv78230-pinctrl",
                .data       = (void *) V_MV78230,
@@ -406,12 +407,42 @@ static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = {
        MPP_GPIO_RANGE(2,  64, 64,  3),
 };
 
+static int armada_xp_pinctrl_suspend(struct platform_device *pdev,
+                                    pm_message_t state)
+{
+       struct mvebu_pinctrl_soc_info *soc =
+               platform_get_drvdata(pdev);
+       int i, nregs;
+
+       nregs = DIV_ROUND_UP(soc->nmodes, MVEBU_MPPS_PER_REG);
+
+       for (i = 0; i < nregs; i++)
+               mpp_saved_regs[i] = readl(mpp_base + i * 4);
+
+       return 0;
+}
+
+static int armada_xp_pinctrl_resume(struct platform_device *pdev)
+{
+       struct mvebu_pinctrl_soc_info *soc =
+               platform_get_drvdata(pdev);
+       int i, nregs;
+
+       nregs = DIV_ROUND_UP(soc->nmodes, MVEBU_MPPS_PER_REG);
+
+       for (i = 0; i < nregs; i++)
+               writel(mpp_saved_regs[i], mpp_base + i * 4);
+
+       return 0;
+}
+
 static int armada_xp_pinctrl_probe(struct platform_device *pdev)
 {
        struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info;
        const struct of_device_id *match =
                of_match_device(armada_xp_pinctrl_of_match, &pdev->dev);
        struct resource *res;
+       int nregs;
 
        if (!match)
                return -ENODEV;
@@ -459,6 +490,13 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev)
                break;
        }
 
+       nregs = DIV_ROUND_UP(soc->nmodes, MVEBU_MPPS_PER_REG);
+
+       mpp_saved_regs = devm_kmalloc(&pdev->dev, nregs * sizeof(u32),
+                                     GFP_KERNEL);
+       if (!mpp_saved_regs)
+               return -ENOMEM;
+
        pdev->dev.platform_data = soc;
 
        return mvebu_pinctrl_probe(pdev);
@@ -476,6 +514,8 @@ static struct platform_driver armada_xp_pinctrl_driver = {
        },
        .probe = armada_xp_pinctrl_probe,
        .remove = armada_xp_pinctrl_remove,
+       .suspend = armada_xp_pinctrl_suspend,
+       .resume = armada_xp_pinctrl_resume,
 };
 
 module_platform_driver(armada_xp_pinctrl_driver);
index dbc673cf713135196d7514804e2c99bc5b2b4f09..0f07dc554a1dd8e977f435d7fcc925267f2fabf4 100644 (file)
@@ -456,7 +456,7 @@ static struct mvebu_pinctrl_soc_info mv98dx4122_info = {
        .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
 };
 
-static struct of_device_id kirkwood_pinctrl_of_match[] = {
+static const struct of_device_id kirkwood_pinctrl_of_match[] = {
        { .compatible = "marvell,88f6180-pinctrl", .data = &mv88f6180_info },
        { .compatible = "marvell,88f6190-pinctrl", .data = &mv88f6190_info },
        { .compatible = "marvell,88f6192-pinctrl", .data = &mv88f6192_info },
index 3a632efb56bb7a559f97079a0878dbd652f593b7..3b7122d826e415bd6a1c5f7fbc0bbe451ab3114e 100644 (file)
@@ -211,7 +211,7 @@ static struct mvebu_pinctrl_soc_info mv88f5281_info = {
  * There are multiple variants of the Orion SoCs, but in terms of pin
  * muxing, they are identical.
  */
-static struct of_device_id orion_pinctrl_of_match[] = {
+static const struct of_device_id orion_pinctrl_of_match[] = {
        { .compatible = "marvell,88f5181l-pinctrl", .data = &mv88f5181l_info },
        { .compatible = "marvell,88f5182-pinctrl", .data = &mv88f5182_info },
        { .compatible = "marvell,88f5281-pinctrl", .data = &mv88f5281_info },
index 1806b24faa14e65322fa9a2efbaa0c54e679cf28..23db4c9ac76cc20de4b68c06d289250754c83d8a 100644 (file)
@@ -466,7 +466,7 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
                break;
 
        default:
-               dev_dbg(pct->dev, "unknow alt_setting %d\n", alt_setting);
+               dev_dbg(pct->dev, "unknown alt_setting %d\n", alt_setting);
 
                return -EINVAL;
        }
index 4db92f64b4de77ef1038ad8e39695cff22c696e8..e63ad9fbd388a79c1afe0f1b4a2ff99e19a11574 100644 (file)
@@ -283,23 +283,40 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
        struct device *dev = pctldev->dev;
        unsigned long *configs = NULL;
        unsigned num_configs = 0;
-       unsigned reserve;
+       unsigned reserve, strings_count;
        struct property *prop;
        const char *group;
        const char *subnode_target_type = "pins";
 
+       ret = of_property_count_strings(np, "pins");
+       if (ret < 0) {
+               ret = of_property_count_strings(np, "groups");
+               if (ret < 0)
+                       /* skip this node; may contain config child nodes */
+                       return 0;
+               if (type == PIN_MAP_TYPE_INVALID)
+                       type = PIN_MAP_TYPE_CONFIGS_GROUP;
+               subnode_target_type = "groups";
+       } else {
+               if (type == PIN_MAP_TYPE_INVALID)
+                       type = PIN_MAP_TYPE_CONFIGS_PIN;
+       }
+       strings_count = ret;
+
        ret = of_property_read_string(np, "function", &function);
        if (ret < 0) {
                /* EINVAL=missing, which is fine since it's optional */
                if (ret != -EINVAL)
-                       dev_err(dev, "could not parse property function\n");
+                       dev_err(dev, "%s: could not parse property function\n",
+                               of_node_full_name(np));
                function = NULL;
        }
 
        ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
                                              &num_configs);
        if (ret < 0) {
-               dev_err(dev, "could not parse node property\n");
+               dev_err(dev, "%s: could not parse node property\n",
+                       of_node_full_name(np));
                return ret;
        }
 
@@ -309,21 +326,7 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
        if (num_configs)
                reserve++;
 
-       ret = of_property_count_strings(np, "pins");
-       if (ret < 0) {
-               ret = of_property_count_strings(np, "groups");
-               if (ret < 0) {
-                       dev_err(dev, "could not parse property pins/groups\n");
-                       goto exit;
-               }
-               if (type == PIN_MAP_TYPE_INVALID)
-                       type = PIN_MAP_TYPE_CONFIGS_GROUP;
-               subnode_target_type = "groups";
-       } else {
-               if (type == PIN_MAP_TYPE_INVALID)
-                       type = PIN_MAP_TYPE_CONFIGS_PIN;
-       }
-       reserve *= ret;
+       reserve *= strings_count;
 
        ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps,
                        num_maps, reserve);
@@ -367,15 +370,22 @@ int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev,
        *map = NULL;
        *num_maps = 0;
 
+       ret = pinconf_generic_dt_subnode_to_map(pctldev, np_config, map,
+                                               &reserved_maps, num_maps, type);
+       if (ret < 0)
+               goto exit;
+
        for_each_child_of_node(np_config, np) {
                ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map,
                                        &reserved_maps, num_maps, type);
-               if (ret < 0) {
-                       pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
-                       return ret;
-               }
+               if (ret < 0)
+                       goto exit;
        }
        return 0;
+
+exit:
+       pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(pinconf_generic_dt_node_to_map);
 
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
new file mode 100644 (file)
index 0000000..7de3b64
--- /dev/null
@@ -0,0 +1,869 @@
+/*
+ * GPIO driver for AMD
+ *
+ * Copyright (c) 2014,2015 AMD Corporation.
+ * Authors: Ken Xue <Ken.Xue@amd.com>
+ *      Wu, Jeff <Jeff.Wu@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/log2.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/acpi.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/bitops.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+
+#include "pinctrl-utils.h"
+#include "pinctrl-amd.h"
+
+static inline struct amd_gpio *to_amd_gpio(struct gpio_chip *gc)
+{
+       return container_of(gc, struct amd_gpio, gc);
+}
+
+static int amd_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+       unsigned long flags;
+       u32 pin_reg;
+       struct amd_gpio *gpio_dev = to_amd_gpio(gc);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       pin_reg = readl(gpio_dev->base + offset * 4);
+       /*
+        * Suppose BIOS or Bootloader sets specific debounce for the
+        * GPIO. if not, set debounce to be  2.75ms and remove glitch.
+       */
+       if ((pin_reg & DB_TMR_OUT_MASK) == 0) {
+               pin_reg |= 0xf;
+               pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF);
+               pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF;
+               pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
+       }
+
+       pin_reg &= ~BIT(OUTPUT_ENABLE_OFF);
+       writel(pin_reg, gpio_dev->base + offset * 4);
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+
+       return 0;
+}
+
+static int amd_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
+               int value)
+{
+       u32 pin_reg;
+       unsigned long flags;
+       struct amd_gpio *gpio_dev = to_amd_gpio(gc);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       pin_reg = readl(gpio_dev->base + offset * 4);
+       pin_reg |= BIT(OUTPUT_ENABLE_OFF);
+       if (value)
+               pin_reg |= BIT(OUTPUT_VALUE_OFF);
+       else
+               pin_reg &= ~BIT(OUTPUT_VALUE_OFF);
+       writel(pin_reg, gpio_dev->base + offset * 4);
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+
+       return 0;
+}
+
+static int amd_gpio_get_value(struct gpio_chip *gc, unsigned offset)
+{
+       u32 pin_reg;
+       unsigned long flags;
+       struct amd_gpio *gpio_dev = to_amd_gpio(gc);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       pin_reg = readl(gpio_dev->base + offset * 4);
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+
+       return !!(pin_reg & BIT(PIN_STS_OFF));
+}
+
+static void amd_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value)
+{
+       u32 pin_reg;
+       unsigned long flags;
+       struct amd_gpio *gpio_dev = to_amd_gpio(gc);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       pin_reg = readl(gpio_dev->base + offset * 4);
+       if (value)
+               pin_reg |= BIT(OUTPUT_VALUE_OFF);
+       else
+               pin_reg &= ~BIT(OUTPUT_VALUE_OFF);
+       writel(pin_reg, gpio_dev->base + offset * 4);
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+}
+
+static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
+               unsigned debounce)
+{
+       u32 time;
+       u32 pin_reg;
+       int ret = 0;
+       unsigned long flags;
+       struct amd_gpio *gpio_dev = to_amd_gpio(gc);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       pin_reg = readl(gpio_dev->base + offset * 4);
+
+       if (debounce) {
+               pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF;
+               pin_reg &= ~DB_TMR_OUT_MASK;
+               /*
+               Debounce        Debounce        Timer   Max
+               TmrLarge        TmrOutUnit      Unit    Debounce
+                                                       Time
+               0       0       61 usec (2 RtcClk)      976 usec
+               0       1       244 usec (8 RtcClk)     3.9 msec
+               1       0       15.6 msec (512 RtcClk)  250 msec
+               1       1       62.5 msec (2048 RtcClk) 1 sec
+               */
+
+               if (debounce < 61) {
+                       pin_reg |= 1;
+                       pin_reg &= ~BIT(DB_TMR_OUT_UNIT_OFF);
+                       pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
+               } else if (debounce < 976) {
+                       time = debounce / 61;
+                       pin_reg |= time & DB_TMR_OUT_MASK;
+                       pin_reg &= ~BIT(DB_TMR_OUT_UNIT_OFF);
+                       pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
+               } else if (debounce < 3900) {
+                       time = debounce / 244;
+                       pin_reg |= time & DB_TMR_OUT_MASK;
+                       pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF);
+                       pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
+               } else if (debounce < 250000) {
+                       time = debounce / 15600;
+                       pin_reg |= time & DB_TMR_OUT_MASK;
+                       pin_reg &= ~BIT(DB_TMR_OUT_UNIT_OFF);
+                       pin_reg |= BIT(DB_TMR_LARGE_OFF);
+               } else if (debounce < 1000000) {
+                       time = debounce / 62500;
+                       pin_reg |= time & DB_TMR_OUT_MASK;
+                       pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF);
+                       pin_reg |= BIT(DB_TMR_LARGE_OFF);
+               } else {
+                       pin_reg &= ~DB_CNTRl_MASK;
+                       ret = -EINVAL;
+               }
+       } else {
+               pin_reg &= ~BIT(DB_TMR_OUT_UNIT_OFF);
+               pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
+               pin_reg &= ~DB_TMR_OUT_MASK;
+               pin_reg &= ~DB_CNTRl_MASK;
+       }
+       writel(pin_reg, gpio_dev->base + offset * 4);
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+
+       return ret;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
+{
+       u32 pin_reg;
+       unsigned long flags;
+       unsigned int bank, i, pin_num;
+       struct amd_gpio *gpio_dev = to_amd_gpio(gc);
+
+       char *level_trig;
+       char *active_level;
+       char *interrupt_enable;
+       char *interrupt_mask;
+       char *wake_cntrl0;
+       char *wake_cntrl1;
+       char *wake_cntrl2;
+       char *pin_sts;
+       char *pull_up_sel;
+       char *pull_up_enable;
+       char *pull_down_enable;
+       char *output_value;
+       char *output_enable;
+
+       for (bank = 0; bank < AMD_GPIO_TOTAL_BANKS; bank++) {
+               seq_printf(s, "GPIO bank%d\t", bank);
+
+               switch (bank) {
+               case 0:
+                       i = 0;
+                       pin_num = AMD_GPIO_PINS_BANK0;
+                       break;
+               case 1:
+                       i = 64;
+                       pin_num = AMD_GPIO_PINS_BANK1 + i;
+                       break;
+               case 2:
+                       i = 128;
+                       pin_num = AMD_GPIO_PINS_BANK2 + i;
+                       break;
+               }
+
+               for (; i < pin_num; i++) {
+                       seq_printf(s, "pin%d\t", i);
+                       spin_lock_irqsave(&gpio_dev->lock, flags);
+                       pin_reg = readl(gpio_dev->base + i * 4);
+                       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+
+                       if (pin_reg & BIT(INTERRUPT_ENABLE_OFF)) {
+                               interrupt_enable = "interrupt is enabled|";
+
+                               if (!(pin_reg & BIT(ACTIVE_LEVEL_OFF))
+                               && !(pin_reg & BIT(ACTIVE_LEVEL_OFF+1)))
+                                       active_level = "Active low|";
+                               else if (pin_reg & BIT(ACTIVE_LEVEL_OFF)
+                               && !(pin_reg & BIT(ACTIVE_LEVEL_OFF+1)))
+                                       active_level = "Active high|";
+                               else if (!(pin_reg & BIT(ACTIVE_LEVEL_OFF))
+                                       && pin_reg & BIT(ACTIVE_LEVEL_OFF+1))
+                                       active_level = "Active on both|";
+                               else
+                                       active_level = "Unknow Active level|";
+
+                               if (pin_reg & BIT(LEVEL_TRIG_OFF))
+                                       level_trig = "Level trigger|";
+                               else
+                                       level_trig = "Edge trigger|";
+
+                       } else {
+                               interrupt_enable =
+                                       "interrupt is disabled|";
+                               active_level = " ";
+                               level_trig = " ";
+                       }
+
+                       if (pin_reg & BIT(INTERRUPT_MASK_OFF))
+                               interrupt_mask =
+                                       "interrupt is unmasked|";
+                       else
+                               interrupt_mask =
+                                       "interrupt is masked|";
+
+                       if (pin_reg & BIT(WAKE_CNTRL_OFF))
+                               wake_cntrl0 = "enable wakeup in S0i3 state|";
+                       else
+                               wake_cntrl0 = "disable wakeup in S0i3 state|";
+
+                       if (pin_reg & BIT(WAKE_CNTRL_OFF))
+                               wake_cntrl1 = "enable wakeup in S3 state|";
+                       else
+                               wake_cntrl1 = "disable wakeup in S3 state|";
+
+                       if (pin_reg & BIT(WAKE_CNTRL_OFF))
+                               wake_cntrl2 = "enable wakeup in S4/S5 state|";
+                       else
+                               wake_cntrl2 = "disable wakeup in S4/S5 state|";
+
+                       if (pin_reg & BIT(PULL_UP_ENABLE_OFF)) {
+                               pull_up_enable = "pull-up is enabled|";
+                               if (pin_reg & BIT(PULL_UP_SEL_OFF))
+                                       pull_up_sel = "8k pull-up|";
+                               else
+                                       pull_up_sel = "4k pull-up|";
+                       } else {
+                               pull_up_enable = "pull-up is disabled|";
+                               pull_up_sel = " ";
+                       }
+
+                       if (pin_reg & BIT(PULL_DOWN_ENABLE_OFF))
+                               pull_down_enable = "pull-down is enabled|";
+                       else
+                               pull_down_enable = "Pull-down is disabled|";
+
+                       if (pin_reg & BIT(OUTPUT_ENABLE_OFF)) {
+                               pin_sts = " ";
+                               output_enable = "output is enabled|";
+                               if (pin_reg & BIT(OUTPUT_VALUE_OFF))
+                                       output_value = "output is high|";
+                               else
+                                       output_value = "output is low|";
+                       } else {
+                               output_enable = "output is disabled|";
+                               output_value = " ";
+
+                               if (pin_reg & BIT(PIN_STS_OFF))
+                                       pin_sts = "input is high|";
+                               else
+                                       pin_sts = "input is low|";
+                       }
+
+                       seq_printf(s, "%s %s %s %s %s %s\n"
+                               " %s %s %s %s %s %s %s 0x%x\n",
+                               level_trig, active_level, interrupt_enable,
+                               interrupt_mask, wake_cntrl0, wake_cntrl1,
+                               wake_cntrl2, pin_sts, pull_up_sel,
+                               pull_up_enable, pull_down_enable,
+                               output_value, output_enable, pin_reg);
+               }
+       }
+}
+#else
+#define amd_gpio_dbg_show NULL
+#endif
+
+static void amd_gpio_irq_enable(struct irq_data *d)
+{
+       u32 pin_reg;
+       unsigned long flags;
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct amd_gpio *gpio_dev = to_amd_gpio(gc);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
+       /*
+               Suppose BIOS or Bootloader sets specific debounce for the
+               GPIO. if not, set debounce to be  2.75ms.
+       */
+       if ((pin_reg & DB_TMR_OUT_MASK) == 0) {
+               pin_reg |= 0xf;
+               pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF);
+               pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
+       }
+       pin_reg |= BIT(INTERRUPT_ENABLE_OFF);
+       pin_reg |= BIT(INTERRUPT_MASK_OFF);
+       writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+}
+
+static void amd_gpio_irq_disable(struct irq_data *d)
+{
+       u32 pin_reg;
+       unsigned long flags;
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct amd_gpio *gpio_dev = to_amd_gpio(gc);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
+       pin_reg &= ~BIT(INTERRUPT_ENABLE_OFF);
+       pin_reg &= ~BIT(INTERRUPT_MASK_OFF);
+       writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+}
+
+static void amd_gpio_irq_mask(struct irq_data *d)
+{
+       u32 pin_reg;
+       unsigned long flags;
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct amd_gpio *gpio_dev = to_amd_gpio(gc);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
+       pin_reg &= ~BIT(INTERRUPT_MASK_OFF);
+       writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+}
+
+static void amd_gpio_irq_unmask(struct irq_data *d)
+{
+       u32 pin_reg;
+       unsigned long flags;
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct amd_gpio *gpio_dev = to_amd_gpio(gc);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
+       pin_reg |= BIT(INTERRUPT_MASK_OFF);
+       writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+}
+
+static void amd_gpio_irq_eoi(struct irq_data *d)
+{
+       u32 reg;
+       unsigned long flags;
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct amd_gpio *gpio_dev = to_amd_gpio(gc);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
+       reg |= EOI_MASK;
+       writel(reg, gpio_dev->base + WAKE_INT_MASTER_REG);
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+}
+
+static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       int ret = 0;
+       u32 pin_reg;
+       unsigned long flags;
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct amd_gpio *gpio_dev = to_amd_gpio(gc);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
+
+       switch (type & IRQ_TYPE_SENSE_MASK) {
+       case IRQ_TYPE_EDGE_RISING:
+               pin_reg &= ~BIT(LEVEL_TRIG_OFF);
+               pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
+               pin_reg |= ACTIVE_HIGH << ACTIVE_LEVEL_OFF;
+               pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF;
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               break;
+
+       case IRQ_TYPE_EDGE_FALLING:
+               pin_reg &= ~BIT(LEVEL_TRIG_OFF);
+               pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
+               pin_reg |= ACTIVE_LOW << ACTIVE_LEVEL_OFF;
+               pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF;
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               break;
+
+       case IRQ_TYPE_EDGE_BOTH:
+               pin_reg &= ~BIT(LEVEL_TRIG_OFF);
+               pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
+               pin_reg |= BOTH_EADGE << ACTIVE_LEVEL_OFF;
+               pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF;
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               break;
+
+       case IRQ_TYPE_LEVEL_HIGH:
+               pin_reg |= LEVEL_TRIGGER << LEVEL_TRIG_OFF;
+               pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
+               pin_reg |= ACTIVE_HIGH << ACTIVE_LEVEL_OFF;
+               pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF);
+               pin_reg |= DB_TYPE_PRESERVE_LOW_GLITCH << DB_CNTRL_OFF;
+               __irq_set_handler_locked(d->irq, handle_level_irq);
+               break;
+
+       case IRQ_TYPE_LEVEL_LOW:
+               pin_reg |= LEVEL_TRIGGER << LEVEL_TRIG_OFF;
+               pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
+               pin_reg |= ACTIVE_LOW << ACTIVE_LEVEL_OFF;
+               pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF);
+               pin_reg |= DB_TYPE_PRESERVE_HIGH_GLITCH << DB_CNTRL_OFF;
+               __irq_set_handler_locked(d->irq, handle_level_irq);
+               break;
+
+       case IRQ_TYPE_NONE:
+               break;
+
+       default:
+               dev_err(&gpio_dev->pdev->dev, "Invalid type value\n");
+               ret = -EINVAL;
+       }
+
+       pin_reg |= CLR_INTR_STAT << INTERRUPT_STS_OFF;
+       writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+
+       return ret;
+}
+
+static void amd_irq_ack(struct irq_data *d)
+{
+       /*
+        * based on HW design,there is no need to ack HW
+        * before handle current irq. But this routine is
+        * necessary for handle_edge_irq
+       */
+}
+
+static struct irq_chip amd_gpio_irqchip = {
+       .name         = "amd_gpio",
+       .irq_ack      = amd_irq_ack,
+       .irq_enable   = amd_gpio_irq_enable,
+       .irq_disable  = amd_gpio_irq_disable,
+       .irq_mask     = amd_gpio_irq_mask,
+       .irq_unmask   = amd_gpio_irq_unmask,
+       .irq_eoi      = amd_gpio_irq_eoi,
+       .irq_set_type = amd_gpio_irq_set_type,
+};
+
+static void amd_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       u32 i;
+       u32 off;
+       u32 reg;
+       u32 pin_reg;
+       u64 reg64;
+       int handled = 0;
+       unsigned long flags;
+       struct irq_chip *chip = irq_get_chip(irq);
+       struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+       struct amd_gpio *gpio_dev = to_amd_gpio(gc);
+
+       chained_irq_enter(chip, desc);
+       /*enable GPIO interrupt again*/
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       reg = readl(gpio_dev->base + WAKE_INT_STATUS_REG1);
+       reg64 = reg;
+       reg64 = reg64 << 32;
+
+       reg = readl(gpio_dev->base + WAKE_INT_STATUS_REG0);
+       reg64 |= reg;
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+
+       /*
+        * first 46 bits indicates interrupt status.
+        * one bit represents four interrupt sources.
+       */
+       for (off = 0; off < 46 ; off++) {
+               if (reg64 & BIT(off)) {
+                       for (i = 0; i < 4; i++) {
+                               pin_reg = readl(gpio_dev->base +
+                                               (off * 4 + i) * 4);
+                               if ((pin_reg & BIT(INTERRUPT_STS_OFF)) ||
+                                       (pin_reg & BIT(WAKE_STS_OFF))) {
+                                       irq = irq_find_mapping(gc->irqdomain,
+                                                               off * 4 + i);
+                                       generic_handle_irq(irq);
+                                       writel(pin_reg,
+                                               gpio_dev->base
+                                               + (off * 4 + i) * 4);
+                                       handled++;
+                               }
+                       }
+               }
+       }
+
+       if (handled == 0)
+               handle_bad_irq(irq, desc);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
+       reg |= EOI_MASK;
+       writel(reg, gpio_dev->base + WAKE_INT_MASTER_REG);
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+
+       chained_irq_exit(chip, desc);
+}
+
+static int amd_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctldev);
+
+       return gpio_dev->ngroups;
+}
+
+static const char *amd_get_group_name(struct pinctrl_dev *pctldev,
+                                     unsigned group)
+{
+       struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctldev);
+
+       return gpio_dev->groups[group].name;
+}
+
+static int amd_get_group_pins(struct pinctrl_dev *pctldev,
+                             unsigned group,
+                             const unsigned **pins,
+                             unsigned *num_pins)
+{
+       struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctldev);
+
+       *pins = gpio_dev->groups[group].pins;
+       *num_pins = gpio_dev->groups[group].npins;
+       return 0;
+}
+
+static const struct pinctrl_ops amd_pinctrl_ops = {
+       .get_groups_count       = amd_get_groups_count,
+       .get_group_name         = amd_get_group_name,
+       .get_group_pins         = amd_get_group_pins,
+#ifdef CONFIG_OF
+       .dt_node_to_map         = pinconf_generic_dt_node_to_map_group,
+       .dt_free_map            = pinctrl_utils_dt_free_map,
+#endif
+};
+
+static int amd_pinconf_get(struct pinctrl_dev *pctldev,
+                         unsigned int pin,
+                         unsigned long *config)
+{
+       u32 pin_reg;
+       unsigned arg;
+       unsigned long flags;
+       struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctldev);
+       enum pin_config_param param = pinconf_to_config_param(*config);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       pin_reg = readl(gpio_dev->base + pin*4);
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       switch (param) {
+       case PIN_CONFIG_INPUT_DEBOUNCE:
+               arg = pin_reg & DB_TMR_OUT_MASK;
+               break;
+
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               arg = (pin_reg >> PULL_DOWN_ENABLE_OFF) & BIT(0);
+               break;
+
+       case PIN_CONFIG_BIAS_PULL_UP:
+               arg = (pin_reg >> PULL_UP_SEL_OFF) & (BIT(0) | BIT(1));
+               break;
+
+       case PIN_CONFIG_DRIVE_STRENGTH:
+               arg = (pin_reg >> DRV_STRENGTH_SEL_OFF) & DRV_STRENGTH_SEL_MASK;
+               break;
+
+       default:
+               dev_err(&gpio_dev->pdev->dev, "Invalid config param %04x\n",
+                       param);
+               return -ENOTSUPP;
+       }
+
+       *config = pinconf_to_config_packed(param, arg);
+
+       return 0;
+}
+
+static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+                               unsigned long *configs, unsigned num_configs)
+{
+       int i;
+       u32 arg;
+       int ret = 0;
+       u32 pin_reg;
+       unsigned long flags;
+       enum pin_config_param param;
+       struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctldev);
+
+       spin_lock_irqsave(&gpio_dev->lock, flags);
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
+               arg = pinconf_to_config_argument(configs[i]);
+               pin_reg = readl(gpio_dev->base + pin*4);
+
+               switch (param) {
+               case PIN_CONFIG_INPUT_DEBOUNCE:
+                       pin_reg &= ~DB_TMR_OUT_MASK;
+                       pin_reg |= arg & DB_TMR_OUT_MASK;
+                       break;
+
+               case PIN_CONFIG_BIAS_PULL_DOWN:
+                       pin_reg &= ~BIT(PULL_DOWN_ENABLE_OFF);
+                       pin_reg |= (arg & BIT(0)) << PULL_DOWN_ENABLE_OFF;
+                       break;
+
+               case PIN_CONFIG_BIAS_PULL_UP:
+                       pin_reg &= ~BIT(PULL_UP_SEL_OFF);
+                       pin_reg |= (arg & BIT(0)) << PULL_UP_SEL_OFF;
+                       pin_reg &= ~BIT(PULL_UP_ENABLE_OFF);
+                       pin_reg |= ((arg>>1) & BIT(0)) << PULL_UP_ENABLE_OFF;
+                       break;
+
+               case PIN_CONFIG_DRIVE_STRENGTH:
+                       pin_reg &= ~(DRV_STRENGTH_SEL_MASK
+                                       << DRV_STRENGTH_SEL_OFF);
+                       pin_reg |= (arg & DRV_STRENGTH_SEL_MASK)
+                                       << DRV_STRENGTH_SEL_OFF;
+                       break;
+
+               default:
+                       dev_err(&gpio_dev->pdev->dev,
+                               "Invalid config param %04x\n", param);
+                       ret = -ENOTSUPP;
+               }
+
+               writel(pin_reg, gpio_dev->base + pin*4);
+       }
+       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+
+       return ret;
+}
+
+static int amd_pinconf_group_get(struct pinctrl_dev *pctldev,
+                               unsigned int group,
+                               unsigned long *config)
+{
+       const unsigned *pins;
+       unsigned npins;
+       int ret;
+
+       ret = amd_get_group_pins(pctldev, group, &pins, &npins);
+       if (ret)
+               return ret;
+
+       if (amd_pinconf_get(pctldev, pins[0], config))
+                       return -ENOTSUPP;
+
+       return 0;
+}
+
+static int amd_pinconf_group_set(struct pinctrl_dev *pctldev,
+                               unsigned group, unsigned long *configs,
+                               unsigned num_configs)
+{
+       const unsigned *pins;
+       unsigned npins;
+       int i, ret;
+
+       ret = amd_get_group_pins(pctldev, group, &pins, &npins);
+       if (ret)
+               return ret;
+       for (i = 0; i < npins; i++) {
+               if (amd_pinconf_set(pctldev, pins[i], configs, num_configs))
+                       return -ENOTSUPP;
+       }
+       return 0;
+}
+
+static const struct pinconf_ops amd_pinconf_ops = {
+       .pin_config_get         = amd_pinconf_get,
+       .pin_config_set         = amd_pinconf_set,
+       .pin_config_group_get = amd_pinconf_group_get,
+       .pin_config_group_set = amd_pinconf_group_set,
+};
+
+static struct pinctrl_desc amd_pinctrl_desc = {
+       .pins   = kerncz_pins,
+       .npins = ARRAY_SIZE(kerncz_pins),
+       .pctlops = &amd_pinctrl_ops,
+       .confops = &amd_pinconf_ops,
+       .owner = THIS_MODULE,
+};
+
+static int amd_gpio_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+       int irq_base;
+       struct resource *res;
+       struct amd_gpio *gpio_dev;
+
+       gpio_dev = devm_kzalloc(&pdev->dev,
+                               sizeof(struct amd_gpio), GFP_KERNEL);
+       if (!gpio_dev)
+               return -ENOMEM;
+
+       spin_lock_init(&gpio_dev->lock);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "Failed to get gpio io resource.\n");
+               return -EINVAL;
+       }
+
+       gpio_dev->base = devm_ioremap_nocache(&pdev->dev, res->start,
+                                               resource_size(res));
+       if (IS_ERR(gpio_dev->base))
+               return PTR_ERR(gpio_dev->base);
+
+       irq_base = platform_get_irq(pdev, 0);
+       if (irq_base < 0) {
+               dev_err(&pdev->dev, "Failed to get gpio IRQ.\n");
+               return -EINVAL;
+       }
+
+       gpio_dev->pdev = pdev;
+       gpio_dev->gc.direction_input    = amd_gpio_direction_input;
+       gpio_dev->gc.direction_output   = amd_gpio_direction_output;
+       gpio_dev->gc.get                        = amd_gpio_get_value;
+       gpio_dev->gc.set                        = amd_gpio_set_value;
+       gpio_dev->gc.set_debounce       = amd_gpio_set_debounce;
+       gpio_dev->gc.dbg_show           = amd_gpio_dbg_show;
+
+       gpio_dev->gc.base                       = 0;
+       gpio_dev->gc.label                      = pdev->name;
+       gpio_dev->gc.owner                      = THIS_MODULE;
+       gpio_dev->gc.dev                        = &pdev->dev;
+       gpio_dev->gc.ngpio                      = TOTAL_NUMBER_OF_PINS;
+#if defined(CONFIG_OF_GPIO)
+       gpio_dev->gc.of_node                    = pdev->dev.of_node;
+#endif
+
+       gpio_dev->groups = kerncz_groups;
+       gpio_dev->ngroups = ARRAY_SIZE(kerncz_groups);
+
+       amd_pinctrl_desc.name = dev_name(&pdev->dev);
+       gpio_dev->pctrl = pinctrl_register(&amd_pinctrl_desc,
+                                       &pdev->dev, gpio_dev);
+       if (!gpio_dev->pctrl) {
+               dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
+               return -ENODEV;
+       }
+
+       ret = gpiochip_add(&gpio_dev->gc);
+       if (ret)
+               goto out1;
+
+       ret = gpiochip_add_pin_range(&gpio_dev->gc, dev_name(&pdev->dev),
+                               0, 0, TOTAL_NUMBER_OF_PINS);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to add pin range\n");
+               goto out2;
+       }
+
+       ret = gpiochip_irqchip_add(&gpio_dev->gc,
+                               &amd_gpio_irqchip,
+                               0,
+                               handle_simple_irq,
+                               IRQ_TYPE_NONE);
+       if (ret) {
+               dev_err(&pdev->dev, "could not add irqchip\n");
+               ret = -ENODEV;
+               goto out2;
+       }
+
+       gpiochip_set_chained_irqchip(&gpio_dev->gc,
+                                &amd_gpio_irqchip,
+                                irq_base,
+                                amd_gpio_irq_handler);
+
+       platform_set_drvdata(pdev, gpio_dev);
+
+       dev_dbg(&pdev->dev, "amd gpio driver loaded\n");
+       return ret;
+
+out2:
+       gpiochip_remove(&gpio_dev->gc);
+
+out1:
+       pinctrl_unregister(gpio_dev->pctrl);
+       return ret;
+}
+
+static int amd_gpio_remove(struct platform_device *pdev)
+{
+       struct amd_gpio *gpio_dev;
+
+       gpio_dev = platform_get_drvdata(pdev);
+
+       gpiochip_remove(&gpio_dev->gc);
+       pinctrl_unregister(gpio_dev->pctrl);
+
+       return 0;
+}
+
+static const struct acpi_device_id amd_gpio_acpi_match[] = {
+       { "AMD0030", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, amd_gpio_acpi_match);
+
+static struct platform_driver amd_gpio_driver = {
+       .driver         = {
+               .name   = "amd_gpio",
+               .owner  = THIS_MODULE,
+               .acpi_match_table = ACPI_PTR(amd_gpio_acpi_match),
+       },
+       .probe          = amd_gpio_probe,
+       .remove         = amd_gpio_remove,
+};
+
+module_platform_driver(amd_gpio_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Ken Xue <Ken.Xue@amd.com>, Jeff Wu <Jeff.Wu@amd.com>");
+MODULE_DESCRIPTION("AMD GPIO pinctrl driver");
diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h
new file mode 100644 (file)
index 0000000..7bfea47
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * GPIO driver for AMD
+ *
+ * Copyright (c) 2014,2015 Ken Xue <Ken.Xue@amd.com>
+ *             Jeff Wu <Jeff.Wu@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _PINCTRL_AMD_H
+#define _PINCTRL_AMD_H
+
+#define TOTAL_NUMBER_OF_PINS   192
+#define AMD_GPIO_PINS_PER_BANK  64
+#define AMD_GPIO_TOTAL_BANKS    3
+
+#define AMD_GPIO_PINS_BANK0     63
+#define AMD_GPIO_PINS_BANK1     64
+#define AMD_GPIO_PINS_BANK2     56
+
+#define WAKE_INT_MASTER_REG 0xfc
+#define EOI_MASK (1 << 29)
+
+#define WAKE_INT_STATUS_REG0 0x2f8
+#define WAKE_INT_STATUS_REG1 0x2fc
+
+#define DB_TMR_OUT_OFF                 0
+#define DB_TMR_OUT_UNIT_OFF            4
+#define DB_CNTRL_OFF                   5
+#define DB_TMR_LARGE_OFF               7
+#define LEVEL_TRIG_OFF                 8
+#define ACTIVE_LEVEL_OFF               9
+#define INTERRUPT_ENABLE_OFF           11
+#define INTERRUPT_MASK_OFF             12
+#define WAKE_CNTRL_OFF                 13
+#define PIN_STS_OFF                    16
+#define DRV_STRENGTH_SEL_OFF           17
+#define PULL_UP_SEL_OFF                        19
+#define PULL_UP_ENABLE_OFF             20
+#define PULL_DOWN_ENABLE_OFF           21
+#define OUTPUT_VALUE_OFF               22
+#define OUTPUT_ENABLE_OFF              23
+#define SW_CNTRL_IN_OFF                        24
+#define SW_CNTRL_EN_OFF                        25
+#define INTERRUPT_STS_OFF              28
+#define WAKE_STS_OFF                   29
+
+#define DB_TMR_OUT_MASK        0xFUL
+#define DB_CNTRl_MASK  0x3UL
+#define ACTIVE_LEVEL_MASK      0x3UL
+#define DRV_STRENGTH_SEL_MASK  0x3UL
+
+#define DB_TYPE_NO_DEBOUNCE               0x0UL
+#define DB_TYPE_PRESERVE_LOW_GLITCH       0x1UL
+#define DB_TYPE_PRESERVE_HIGH_GLITCH      0x2UL
+#define DB_TYPE_REMOVE_GLITCH             0x3UL
+
+#define EDGE_TRAGGER   0x0UL
+#define LEVEL_TRIGGER  0x1UL
+
+#define ACTIVE_HIGH    0x0UL
+#define ACTIVE_LOW     0x1UL
+#define BOTH_EADGE     0x2UL
+
+#define ENABLE_INTERRUPT       0x1UL
+#define DISABLE_INTERRUPT      0x0UL
+
+#define ENABLE_INTERRUPT_MASK  0x0UL
+#define DISABLE_INTERRUPT_MASK 0x1UL
+
+#define CLR_INTR_STAT  0x1UL
+
+struct amd_pingroup {
+       const char *name;
+       const unsigned *pins;
+       unsigned npins;
+};
+
+struct amd_function {
+       const char *name;
+       const char * const *groups;
+       unsigned ngroups;
+};
+
+struct amd_gpio {
+       spinlock_t              lock;
+       void __iomem            *base;
+
+       const struct amd_pingroup *groups;
+       u32 ngroups;
+       struct pinctrl_dev *pctrl;
+       struct gpio_chip        gc;
+       struct resource         *res;
+       struct platform_device  *pdev;
+};
+
+/*  KERNCZ configuration*/
+static const struct pinctrl_pin_desc kerncz_pins[] = {
+       PINCTRL_PIN(0, "GPIO_0"),
+       PINCTRL_PIN(1, "GPIO_1"),
+       PINCTRL_PIN(2, "GPIO_2"),
+       PINCTRL_PIN(3, "GPIO_3"),
+       PINCTRL_PIN(4, "GPIO_4"),
+       PINCTRL_PIN(5, "GPIO_5"),
+       PINCTRL_PIN(6, "GPIO_6"),
+       PINCTRL_PIN(7, "GPIO_7"),
+       PINCTRL_PIN(8, "GPIO_8"),
+       PINCTRL_PIN(9, "GPIO_9"),
+       PINCTRL_PIN(10, "GPIO_10"),
+       PINCTRL_PIN(11, "GPIO_11"),
+       PINCTRL_PIN(12, "GPIO_12"),
+       PINCTRL_PIN(13, "GPIO_13"),
+       PINCTRL_PIN(14, "GPIO_14"),
+       PINCTRL_PIN(15, "GPIO_15"),
+       PINCTRL_PIN(16, "GPIO_16"),
+       PINCTRL_PIN(17, "GPIO_17"),
+       PINCTRL_PIN(18, "GPIO_18"),
+       PINCTRL_PIN(19, "GPIO_19"),
+       PINCTRL_PIN(20, "GPIO_20"),
+       PINCTRL_PIN(23, "GPIO_23"),
+       PINCTRL_PIN(24, "GPIO_24"),
+       PINCTRL_PIN(25, "GPIO_25"),
+       PINCTRL_PIN(26, "GPIO_26"),
+       PINCTRL_PIN(39, "GPIO_39"),
+       PINCTRL_PIN(40, "GPIO_40"),
+       PINCTRL_PIN(43, "GPIO_42"),
+       PINCTRL_PIN(46, "GPIO_46"),
+       PINCTRL_PIN(47, "GPIO_47"),
+       PINCTRL_PIN(48, "GPIO_48"),
+       PINCTRL_PIN(49, "GPIO_49"),
+       PINCTRL_PIN(50, "GPIO_50"),
+       PINCTRL_PIN(51, "GPIO_51"),
+       PINCTRL_PIN(52, "GPIO_52"),
+       PINCTRL_PIN(53, "GPIO_53"),
+       PINCTRL_PIN(54, "GPIO_54"),
+       PINCTRL_PIN(55, "GPIO_55"),
+       PINCTRL_PIN(56, "GPIO_56"),
+       PINCTRL_PIN(57, "GPIO_57"),
+       PINCTRL_PIN(58, "GPIO_58"),
+       PINCTRL_PIN(59, "GPIO_59"),
+       PINCTRL_PIN(60, "GPIO_60"),
+       PINCTRL_PIN(61, "GPIO_61"),
+       PINCTRL_PIN(62, "GPIO_62"),
+       PINCTRL_PIN(64, "GPIO_64"),
+       PINCTRL_PIN(65, "GPIO_65"),
+       PINCTRL_PIN(66, "GPIO_66"),
+       PINCTRL_PIN(68, "GPIO_68"),
+       PINCTRL_PIN(69, "GPIO_69"),
+       PINCTRL_PIN(70, "GPIO_70"),
+       PINCTRL_PIN(71, "GPIO_71"),
+       PINCTRL_PIN(72, "GPIO_72"),
+       PINCTRL_PIN(74, "GPIO_74"),
+       PINCTRL_PIN(75, "GPIO_75"),
+       PINCTRL_PIN(76, "GPIO_76"),
+       PINCTRL_PIN(84, "GPIO_84"),
+       PINCTRL_PIN(85, "GPIO_85"),
+       PINCTRL_PIN(86, "GPIO_86"),
+       PINCTRL_PIN(87, "GPIO_87"),
+       PINCTRL_PIN(88, "GPIO_88"),
+       PINCTRL_PIN(89, "GPIO_89"),
+       PINCTRL_PIN(90, "GPIO_90"),
+       PINCTRL_PIN(91, "GPIO_91"),
+       PINCTRL_PIN(92, "GPIO_92"),
+       PINCTRL_PIN(93, "GPIO_93"),
+       PINCTRL_PIN(95, "GPIO_95"),
+       PINCTRL_PIN(96, "GPIO_96"),
+       PINCTRL_PIN(97, "GPIO_97"),
+       PINCTRL_PIN(98, "GPIO_98"),
+       PINCTRL_PIN(99, "GPIO_99"),
+       PINCTRL_PIN(100, "GPIO_100"),
+       PINCTRL_PIN(101, "GPIO_101"),
+       PINCTRL_PIN(102, "GPIO_102"),
+       PINCTRL_PIN(113, "GPIO_113"),
+       PINCTRL_PIN(114, "GPIO_114"),
+       PINCTRL_PIN(115, "GPIO_115"),
+       PINCTRL_PIN(116, "GPIO_116"),
+       PINCTRL_PIN(117, "GPIO_117"),
+       PINCTRL_PIN(118, "GPIO_118"),
+       PINCTRL_PIN(119, "GPIO_119"),
+       PINCTRL_PIN(120, "GPIO_120"),
+       PINCTRL_PIN(121, "GPIO_121"),
+       PINCTRL_PIN(122, "GPIO_122"),
+       PINCTRL_PIN(126, "GPIO_126"),
+       PINCTRL_PIN(129, "GPIO_129"),
+       PINCTRL_PIN(130, "GPIO_130"),
+       PINCTRL_PIN(131, "GPIO_131"),
+       PINCTRL_PIN(132, "GPIO_132"),
+       PINCTRL_PIN(133, "GPIO_133"),
+       PINCTRL_PIN(135, "GPIO_135"),
+       PINCTRL_PIN(136, "GPIO_136"),
+       PINCTRL_PIN(137, "GPIO_137"),
+       PINCTRL_PIN(138, "GPIO_138"),
+       PINCTRL_PIN(139, "GPIO_139"),
+       PINCTRL_PIN(140, "GPIO_140"),
+       PINCTRL_PIN(141, "GPIO_141"),
+       PINCTRL_PIN(142, "GPIO_142"),
+       PINCTRL_PIN(143, "GPIO_143"),
+       PINCTRL_PIN(144, "GPIO_144"),
+       PINCTRL_PIN(145, "GPIO_145"),
+       PINCTRL_PIN(146, "GPIO_146"),
+       PINCTRL_PIN(147, "GPIO_147"),
+       PINCTRL_PIN(148, "GPIO_148"),
+       PINCTRL_PIN(166, "GPIO_166"),
+       PINCTRL_PIN(167, "GPIO_167"),
+       PINCTRL_PIN(168, "GPIO_168"),
+       PINCTRL_PIN(169, "GPIO_169"),
+       PINCTRL_PIN(170, "GPIO_170"),
+       PINCTRL_PIN(171, "GPIO_171"),
+       PINCTRL_PIN(172, "GPIO_172"),
+       PINCTRL_PIN(173, "GPIO_173"),
+       PINCTRL_PIN(174, "GPIO_174"),
+       PINCTRL_PIN(175, "GPIO_175"),
+       PINCTRL_PIN(176, "GPIO_176"),
+       PINCTRL_PIN(177, "GPIO_177"),
+};
+
+static const unsigned i2c0_pins[] = {145, 146};
+static const unsigned i2c1_pins[] = {147, 148};
+static const unsigned i2c2_pins[] = {113, 114};
+static const unsigned i2c3_pins[] = {19, 20};
+
+static const unsigned uart0_pins[] = {135, 136, 137, 138, 139};
+static const unsigned uart1_pins[] = {140, 141, 142, 143, 144};
+
+static const struct amd_pingroup kerncz_groups[] = {
+       {
+               .name = "i2c0",
+               .pins = i2c0_pins,
+               .npins = 2,
+       },
+       {
+               .name = "i2c1",
+               .pins = i2c1_pins,
+               .npins = 2,
+       },
+       {
+               .name = "i2c2",
+               .pins = i2c2_pins,
+               .npins = 2,
+       },
+       {
+               .name = "i2c3",
+               .pins = i2c3_pins,
+               .npins = 2,
+       },
+       {
+               .name = "uart0",
+               .pins = uart0_pins,
+               .npins = 9,
+       },
+       {
+               .name = "uart1",
+               .pins = uart1_pins,
+               .npins = 5,
+       },
+};
+
+#endif
index 169b1bfa00c81931169780b2245cabebf6d5a012..db0571ffbe99e2241687384fcf779f4d4e186a4a 100644 (file)
@@ -625,7 +625,7 @@ static int as3722_pinctrl_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id as3722_pinctrl_of_match[] = {
+static const struct of_device_id as3722_pinctrl_of_match[] = {
        { .compatible = "ams,as3722-pinctrl", },
        { },
 };
index a4814066ea0876d7f52063f5ba2cfb5ca5a6f6d3..2f797cb7e2050175e8b870d9caf342a623061dce 100644 (file)
@@ -451,18 +451,18 @@ static enum at91_mux at91_mux_get_periph(void __iomem *pio, unsigned mask)
 
 static bool at91_mux_get_deglitch(void __iomem *pio, unsigned pin)
 {
-       return (__raw_readl(pio + PIO_IFSR) >> pin) & 0x1;
+       return (readl_relaxed(pio + PIO_IFSR) >> pin) & 0x1;
 }
 
 static void at91_mux_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
 {
-       __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
+       writel_relaxed(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
 }
 
 static bool at91_mux_pio3_get_deglitch(void __iomem *pio, unsigned pin)
 {
-       if ((__raw_readl(pio + PIO_IFSR) >> pin) & 0x1)
-               return !((__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1);
+       if ((readl_relaxed(pio + PIO_IFSR) >> pin) & 0x1)
+               return !((readl_relaxed(pio + PIO_IFSCSR) >> pin) & 0x1);
 
        return false;
 }
@@ -470,55 +470,55 @@ static bool at91_mux_pio3_get_deglitch(void __iomem *pio, unsigned pin)
 static void at91_mux_pio3_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
 {
        if (is_on)
-               __raw_writel(mask, pio + PIO_IFSCDR);
+               writel_relaxed(mask, pio + PIO_IFSCDR);
        at91_mux_set_deglitch(pio, mask, is_on);
 }
 
 static bool at91_mux_pio3_get_debounce(void __iomem *pio, unsigned pin, u32 *div)
 {
-       *div = __raw_readl(pio + PIO_SCDR);
+       *div = readl_relaxed(pio + PIO_SCDR);
 
-       return ((__raw_readl(pio + PIO_IFSR) >> pin) & 0x1) &&
-              ((__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1);
+       return ((readl_relaxed(pio + PIO_IFSR) >> pin) & 0x1) &&
+              ((readl_relaxed(pio + PIO_IFSCSR) >> pin) & 0x1);
 }
 
 static void at91_mux_pio3_set_debounce(void __iomem *pio, unsigned mask,
                                bool is_on, u32 div)
 {
        if (is_on) {
-               __raw_writel(mask, pio + PIO_IFSCER);
-               __raw_writel(div & PIO_SCDR_DIV, pio + PIO_SCDR);
-               __raw_writel(mask, pio + PIO_IFER);
+               writel_relaxed(mask, pio + PIO_IFSCER);
+               writel_relaxed(div & PIO_SCDR_DIV, pio + PIO_SCDR);
+               writel_relaxed(mask, pio + PIO_IFER);
        } else
-               __raw_writel(mask, pio + PIO_IFSCDR);
+               writel_relaxed(mask, pio + PIO_IFSCDR);
 }
 
 static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin)
 {
-       return !((__raw_readl(pio + PIO_PPDSR) >> pin) & 0x1);
+       return !((readl_relaxed(pio + PIO_PPDSR) >> pin) & 0x1);
 }
 
 static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is_on)
 {
        if (is_on)
-               __raw_writel(mask, pio + PIO_PUDR);
+               writel_relaxed(mask, pio + PIO_PUDR);
 
-       __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
+       writel_relaxed(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
 }
 
 static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
 {
-       __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
+       writel_relaxed(readl_relaxed(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
 }
 
 static bool at91_mux_pio3_get_schmitt_trig(void __iomem *pio, unsigned pin)
 {
-       return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1;
+       return (readl_relaxed(pio + PIO_SCHMITT) >> pin) & 0x1;
 }
 
 static inline u32 read_drive_strength(void __iomem *reg, unsigned pin)
 {
-       unsigned tmp = __raw_readl(reg);
+       unsigned tmp = readl_relaxed(reg);
 
        tmp = tmp >> two_bit_pin_value_shift_amount(pin);
 
@@ -554,13 +554,13 @@ static unsigned at91_mux_sam9x5_get_drivestrength(void __iomem *pio,
 
 static void set_drive_strength(void __iomem *reg, unsigned pin, u32 strength)
 {
-       unsigned tmp = __raw_readl(reg);
+       unsigned tmp = readl_relaxed(reg);
        unsigned shift = two_bit_pin_value_shift_amount(pin);
 
        tmp &= ~(DRIVE_STRENGTH_MASK  <<  shift);
        tmp |= strength << shift;
 
-       __raw_writel(tmp, reg);
+       writel_relaxed(tmp, reg);
 }
 
 static void at91_mux_sama5d3_set_drivestrength(void __iomem *pio, unsigned pin,
@@ -1114,7 +1114,7 @@ static int at91_pinctrl_parse_functions(struct device_node *np,
        return 0;
 }
 
-static struct of_device_id at91_pinctrl_of_match[] = {
+static const struct of_device_id at91_pinctrl_of_match[] = {
        { .compatible = "atmel,sama5d3-pinctrl", .data = &sama5d3_ops },
        { .compatible = "atmel,at91sam9x5-pinctrl", .data = &at91sam9x5_ops },
        { .compatible = "atmel,at91rm9200-pinctrl", .data = &at91rm9200_ops },
@@ -1240,8 +1240,7 @@ static int at91_pinctrl_probe(struct platform_device *pdev)
 
        if (!info->pctl) {
                dev_err(&pdev->dev, "could not register AT91 pinctrl driver\n");
-               ret = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
 
        /* We will handle a range of GPIO pins */
@@ -1252,9 +1251,6 @@ static int at91_pinctrl_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "initialized AT91 pinctrl driver\n");
 
        return 0;
-
-err:
-       return ret;
 }
 
 static int at91_pinctrl_remove(struct platform_device *pdev)
@@ -1535,9 +1531,9 @@ void at91_pinctrl_gpio_suspend(void)
 
                pio = gpio_chips[i]->regbase;
 
-               backups[i] = __raw_readl(pio + PIO_IMR);
-               __raw_writel(backups[i], pio + PIO_IDR);
-               __raw_writel(wakeups[i], pio + PIO_IER);
+               backups[i] = readl_relaxed(pio + PIO_IMR);
+               writel_relaxed(backups[i], pio + PIO_IDR);
+               writel_relaxed(wakeups[i], pio + PIO_IER);
 
                if (!wakeups[i])
                        clk_disable_unprepare(gpio_chips[i]->clock);
@@ -1562,8 +1558,8 @@ void at91_pinctrl_gpio_resume(void)
                if (!wakeups[i])
                        clk_prepare_enable(gpio_chips[i]->clock);
 
-               __raw_writel(wakeups[i], pio + PIO_IDR);
-               __raw_writel(backups[i], pio + PIO_IER);
+               writel_relaxed(wakeups[i], pio + PIO_IDR);
+               writel_relaxed(backups[i], pio + PIO_IER);
        }
 }
 
@@ -1694,7 +1690,7 @@ static struct gpio_chip at91_gpio_template = {
        .ngpio                  = MAX_NB_GPIO_PER_BANK,
 };
 
-static struct of_device_id at91_gpio_of_match[] = {
+static const struct of_device_id at91_gpio_of_match[] = {
        { .compatible = "atmel,at91sam9x5-gpio", .data = &at91sam9x5_ops, },
        { .compatible = "atmel,at91rm9200-gpio", .data = &at91rm9200_ops },
        { /* sentinel */ }
diff --git a/drivers/pinctrl/pinctrl-bcm281xx.c b/drivers/pinctrl/pinctrl-bcm281xx.c
deleted file mode 100644 (file)
index b88cfe5..0000000
+++ /dev/null
@@ -1,1455 +0,0 @@
-/*
- * Copyright (C) 2013 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-#include <linux/pinctrl/pinconf-generic.h>
-#include <linux/regmap.h>
-#include <linux/slab.h>
-#include "core.h"
-#include "pinctrl-utils.h"
-
-/* BCM281XX Pin Control Registers Definitions */
-
-/* Function Select bits are the same for all pin control registers */
-#define BCM281XX_PIN_REG_F_SEL_MASK            0x0700
-#define BCM281XX_PIN_REG_F_SEL_SHIFT           8
-
-/* Standard pin register */
-#define BCM281XX_STD_PIN_REG_DRV_STR_MASK      0x0007
-#define BCM281XX_STD_PIN_REG_DRV_STR_SHIFT     0
-#define BCM281XX_STD_PIN_REG_INPUT_DIS_MASK    0x0008
-#define BCM281XX_STD_PIN_REG_INPUT_DIS_SHIFT   3
-#define BCM281XX_STD_PIN_REG_SLEW_MASK         0x0010
-#define BCM281XX_STD_PIN_REG_SLEW_SHIFT                4
-#define BCM281XX_STD_PIN_REG_PULL_UP_MASK      0x0020
-#define BCM281XX_STD_PIN_REG_PULL_UP_SHIFT     5
-#define BCM281XX_STD_PIN_REG_PULL_DN_MASK      0x0040
-#define BCM281XX_STD_PIN_REG_PULL_DN_SHIFT     6
-#define BCM281XX_STD_PIN_REG_HYST_MASK         0x0080
-#define BCM281XX_STD_PIN_REG_HYST_SHIFT                7
-
-/* I2C pin register */
-#define BCM281XX_I2C_PIN_REG_INPUT_DIS_MASK    0x0004
-#define BCM281XX_I2C_PIN_REG_INPUT_DIS_SHIFT   2
-#define BCM281XX_I2C_PIN_REG_SLEW_MASK         0x0008
-#define BCM281XX_I2C_PIN_REG_SLEW_SHIFT                3
-#define BCM281XX_I2C_PIN_REG_PULL_UP_STR_MASK  0x0070
-#define BCM281XX_I2C_PIN_REG_PULL_UP_STR_SHIFT 4
-
-/* HDMI pin register */
-#define BCM281XX_HDMI_PIN_REG_INPUT_DIS_MASK   0x0008
-#define BCM281XX_HDMI_PIN_REG_INPUT_DIS_SHIFT  3
-#define BCM281XX_HDMI_PIN_REG_MODE_MASK                0x0010
-#define BCM281XX_HDMI_PIN_REG_MODE_SHIFT       4
-
-/**
- * bcm281xx_pin_type - types of pin register
- */
-enum bcm281xx_pin_type {
-       BCM281XX_PIN_TYPE_UNKNOWN = 0,
-       BCM281XX_PIN_TYPE_STD,
-       BCM281XX_PIN_TYPE_I2C,
-       BCM281XX_PIN_TYPE_HDMI,
-};
-
-static enum bcm281xx_pin_type std_pin = BCM281XX_PIN_TYPE_STD;
-static enum bcm281xx_pin_type i2c_pin = BCM281XX_PIN_TYPE_I2C;
-static enum bcm281xx_pin_type hdmi_pin = BCM281XX_PIN_TYPE_HDMI;
-
-/**
- * bcm281xx_pin_function- define pin function
- */
-struct bcm281xx_pin_function {
-       const char *name;
-       const char * const *groups;
-       const unsigned ngroups;
-};
-
-/**
- * bcm281xx_pinctrl_data - Broadcom-specific pinctrl data
- * @reg_base - base of pinctrl registers
- */
-struct bcm281xx_pinctrl_data {
-       void __iomem *reg_base;
-
-       /* List of all pins */
-       const struct pinctrl_pin_desc *pins;
-       const unsigned npins;
-
-       const struct bcm281xx_pin_function *functions;
-       const unsigned nfunctions;
-
-       struct regmap *regmap;
-};
-
-/*
- * Pin number definition.  The order here must be the same as defined in the
- * PADCTRLREG block in the RDB.
- */
-#define BCM281XX_PIN_ADCSYNC           0
-#define BCM281XX_PIN_BAT_RM            1
-#define BCM281XX_PIN_BSC1_SCL          2
-#define BCM281XX_PIN_BSC1_SDA          3
-#define BCM281XX_PIN_BSC2_SCL          4
-#define BCM281XX_PIN_BSC2_SDA          5
-#define BCM281XX_PIN_CLASSGPWR         6
-#define BCM281XX_PIN_CLK_CX8           7
-#define BCM281XX_PIN_CLKOUT_0          8
-#define BCM281XX_PIN_CLKOUT_1          9
-#define BCM281XX_PIN_CLKOUT_2          10
-#define BCM281XX_PIN_CLKOUT_3          11
-#define BCM281XX_PIN_CLKREQ_IN_0       12
-#define BCM281XX_PIN_CLKREQ_IN_1       13
-#define BCM281XX_PIN_CWS_SYS_REQ1      14
-#define BCM281XX_PIN_CWS_SYS_REQ2      15
-#define BCM281XX_PIN_CWS_SYS_REQ3      16
-#define BCM281XX_PIN_DIGMIC1_CLK       17
-#define BCM281XX_PIN_DIGMIC1_DQ                18
-#define BCM281XX_PIN_DIGMIC2_CLK       19
-#define BCM281XX_PIN_DIGMIC2_DQ                20
-#define BCM281XX_PIN_GPEN13            21
-#define BCM281XX_PIN_GPEN14            22
-#define BCM281XX_PIN_GPEN15            23
-#define BCM281XX_PIN_GPIO00            24
-#define BCM281XX_PIN_GPIO01            25
-#define BCM281XX_PIN_GPIO02            26
-#define BCM281XX_PIN_GPIO03            27
-#define BCM281XX_PIN_GPIO04            28
-#define BCM281XX_PIN_GPIO05            29
-#define BCM281XX_PIN_GPIO06            30
-#define BCM281XX_PIN_GPIO07            31
-#define BCM281XX_PIN_GPIO08            32
-#define BCM281XX_PIN_GPIO09            33
-#define BCM281XX_PIN_GPIO10            34
-#define BCM281XX_PIN_GPIO11            35
-#define BCM281XX_PIN_GPIO12            36
-#define BCM281XX_PIN_GPIO13            37
-#define BCM281XX_PIN_GPIO14            38
-#define BCM281XX_PIN_GPS_PABLANK       39
-#define BCM281XX_PIN_GPS_TMARK         40
-#define BCM281XX_PIN_HDMI_SCL          41
-#define BCM281XX_PIN_HDMI_SDA          42
-#define BCM281XX_PIN_IC_DM             43
-#define BCM281XX_PIN_IC_DP             44
-#define BCM281XX_PIN_KP_COL_IP_0       45
-#define BCM281XX_PIN_KP_COL_IP_1       46
-#define BCM281XX_PIN_KP_COL_IP_2       47
-#define BCM281XX_PIN_KP_COL_IP_3       48
-#define BCM281XX_PIN_KP_ROW_OP_0       49
-#define BCM281XX_PIN_KP_ROW_OP_1       50
-#define BCM281XX_PIN_KP_ROW_OP_2       51
-#define BCM281XX_PIN_KP_ROW_OP_3       52
-#define BCM281XX_PIN_LCD_B_0           53
-#define BCM281XX_PIN_LCD_B_1           54
-#define BCM281XX_PIN_LCD_B_2           55
-#define BCM281XX_PIN_LCD_B_3           56
-#define BCM281XX_PIN_LCD_B_4           57
-#define BCM281XX_PIN_LCD_B_5           58
-#define BCM281XX_PIN_LCD_B_6           59
-#define BCM281XX_PIN_LCD_B_7           60
-#define BCM281XX_PIN_LCD_G_0           61
-#define BCM281XX_PIN_LCD_G_1           62
-#define BCM281XX_PIN_LCD_G_2           63
-#define BCM281XX_PIN_LCD_G_3           64
-#define BCM281XX_PIN_LCD_G_4           65
-#define BCM281XX_PIN_LCD_G_5           66
-#define BCM281XX_PIN_LCD_G_6           67
-#define BCM281XX_PIN_LCD_G_7           68
-#define BCM281XX_PIN_LCD_HSYNC         69
-#define BCM281XX_PIN_LCD_OE            70
-#define BCM281XX_PIN_LCD_PCLK          71
-#define BCM281XX_PIN_LCD_R_0           72
-#define BCM281XX_PIN_LCD_R_1           73
-#define BCM281XX_PIN_LCD_R_2           74
-#define BCM281XX_PIN_LCD_R_3           75
-#define BCM281XX_PIN_LCD_R_4           76
-#define BCM281XX_PIN_LCD_R_5           77
-#define BCM281XX_PIN_LCD_R_6           78
-#define BCM281XX_PIN_LCD_R_7           79
-#define BCM281XX_PIN_LCD_VSYNC         80
-#define BCM281XX_PIN_MDMGPIO0          81
-#define BCM281XX_PIN_MDMGPIO1          82
-#define BCM281XX_PIN_MDMGPIO2          83
-#define BCM281XX_PIN_MDMGPIO3          84
-#define BCM281XX_PIN_MDMGPIO4          85
-#define BCM281XX_PIN_MDMGPIO5          86
-#define BCM281XX_PIN_MDMGPIO6          87
-#define BCM281XX_PIN_MDMGPIO7          88
-#define BCM281XX_PIN_MDMGPIO8          89
-#define BCM281XX_PIN_MPHI_DATA_0       90
-#define BCM281XX_PIN_MPHI_DATA_1       91
-#define BCM281XX_PIN_MPHI_DATA_2       92
-#define BCM281XX_PIN_MPHI_DATA_3       93
-#define BCM281XX_PIN_MPHI_DATA_4       94
-#define BCM281XX_PIN_MPHI_DATA_5       95
-#define BCM281XX_PIN_MPHI_DATA_6       96
-#define BCM281XX_PIN_MPHI_DATA_7       97
-#define BCM281XX_PIN_MPHI_DATA_8       98
-#define BCM281XX_PIN_MPHI_DATA_9       99
-#define BCM281XX_PIN_MPHI_DATA_10      100
-#define BCM281XX_PIN_MPHI_DATA_11      101
-#define BCM281XX_PIN_MPHI_DATA_12      102
-#define BCM281XX_PIN_MPHI_DATA_13      103
-#define BCM281XX_PIN_MPHI_DATA_14      104
-#define BCM281XX_PIN_MPHI_DATA_15      105
-#define BCM281XX_PIN_MPHI_HA0          106
-#define BCM281XX_PIN_MPHI_HAT0         107
-#define BCM281XX_PIN_MPHI_HAT1         108
-#define BCM281XX_PIN_MPHI_HCE0_N       109
-#define BCM281XX_PIN_MPHI_HCE1_N       110
-#define BCM281XX_PIN_MPHI_HRD_N                111
-#define BCM281XX_PIN_MPHI_HWR_N                112
-#define BCM281XX_PIN_MPHI_RUN0         113
-#define BCM281XX_PIN_MPHI_RUN1         114
-#define BCM281XX_PIN_MTX_SCAN_CLK      115
-#define BCM281XX_PIN_MTX_SCAN_DATA     116
-#define BCM281XX_PIN_NAND_AD_0         117
-#define BCM281XX_PIN_NAND_AD_1         118
-#define BCM281XX_PIN_NAND_AD_2         119
-#define BCM281XX_PIN_NAND_AD_3         120
-#define BCM281XX_PIN_NAND_AD_4         121
-#define BCM281XX_PIN_NAND_AD_5         122
-#define BCM281XX_PIN_NAND_AD_6         123
-#define BCM281XX_PIN_NAND_AD_7         124
-#define BCM281XX_PIN_NAND_ALE          125
-#define BCM281XX_PIN_NAND_CEN_0                126
-#define BCM281XX_PIN_NAND_CEN_1                127
-#define BCM281XX_PIN_NAND_CLE          128
-#define BCM281XX_PIN_NAND_OEN          129
-#define BCM281XX_PIN_NAND_RDY_0                130
-#define BCM281XX_PIN_NAND_RDY_1                131
-#define BCM281XX_PIN_NAND_WEN          132
-#define BCM281XX_PIN_NAND_WP           133
-#define BCM281XX_PIN_PC1               134
-#define BCM281XX_PIN_PC2               135
-#define BCM281XX_PIN_PMU_INT           136
-#define BCM281XX_PIN_PMU_SCL           137
-#define BCM281XX_PIN_PMU_SDA           138
-#define BCM281XX_PIN_RFST2G_MTSLOTEN3G 139
-#define BCM281XX_PIN_RGMII_0_RX_CTL    140
-#define BCM281XX_PIN_RGMII_0_RXC       141
-#define BCM281XX_PIN_RGMII_0_RXD_0     142
-#define BCM281XX_PIN_RGMII_0_RXD_1     143
-#define BCM281XX_PIN_RGMII_0_RXD_2     144
-#define BCM281XX_PIN_RGMII_0_RXD_3     145
-#define BCM281XX_PIN_RGMII_0_TX_CTL    146
-#define BCM281XX_PIN_RGMII_0_TXC       147
-#define BCM281XX_PIN_RGMII_0_TXD_0     148
-#define BCM281XX_PIN_RGMII_0_TXD_1     149
-#define BCM281XX_PIN_RGMII_0_TXD_2     150
-#define BCM281XX_PIN_RGMII_0_TXD_3     151
-#define BCM281XX_PIN_RGMII_1_RX_CTL    152
-#define BCM281XX_PIN_RGMII_1_RXC       153
-#define BCM281XX_PIN_RGMII_1_RXD_0     154
-#define BCM281XX_PIN_RGMII_1_RXD_1     155
-#define BCM281XX_PIN_RGMII_1_RXD_2     156
-#define BCM281XX_PIN_RGMII_1_RXD_3     157
-#define BCM281XX_PIN_RGMII_1_TX_CTL    158
-#define BCM281XX_PIN_RGMII_1_TXC       159
-#define BCM281XX_PIN_RGMII_1_TXD_0     160
-#define BCM281XX_PIN_RGMII_1_TXD_1     161
-#define BCM281XX_PIN_RGMII_1_TXD_2     162
-#define BCM281XX_PIN_RGMII_1_TXD_3     163
-#define BCM281XX_PIN_RGMII_GPIO_0      164
-#define BCM281XX_PIN_RGMII_GPIO_1      165
-#define BCM281XX_PIN_RGMII_GPIO_2      166
-#define BCM281XX_PIN_RGMII_GPIO_3      167
-#define BCM281XX_PIN_RTXDATA2G_TXDATA3G1       168
-#define BCM281XX_PIN_RTXEN2G_TXDATA3G2 169
-#define BCM281XX_PIN_RXDATA3G0         170
-#define BCM281XX_PIN_RXDATA3G1         171
-#define BCM281XX_PIN_RXDATA3G2         172
-#define BCM281XX_PIN_SDIO1_CLK         173
-#define BCM281XX_PIN_SDIO1_CMD         174
-#define BCM281XX_PIN_SDIO1_DATA_0      175
-#define BCM281XX_PIN_SDIO1_DATA_1      176
-#define BCM281XX_PIN_SDIO1_DATA_2      177
-#define BCM281XX_PIN_SDIO1_DATA_3      178
-#define BCM281XX_PIN_SDIO4_CLK         179
-#define BCM281XX_PIN_SDIO4_CMD         180
-#define BCM281XX_PIN_SDIO4_DATA_0      181
-#define BCM281XX_PIN_SDIO4_DATA_1      182
-#define BCM281XX_PIN_SDIO4_DATA_2      183
-#define BCM281XX_PIN_SDIO4_DATA_3      184
-#define BCM281XX_PIN_SIM_CLK           185
-#define BCM281XX_PIN_SIM_DATA          186
-#define BCM281XX_PIN_SIM_DET           187
-#define BCM281XX_PIN_SIM_RESETN                188
-#define BCM281XX_PIN_SIM2_CLK          189
-#define BCM281XX_PIN_SIM2_DATA         190
-#define BCM281XX_PIN_SIM2_DET          191
-#define BCM281XX_PIN_SIM2_RESETN       192
-#define BCM281XX_PIN_SRI_C             193
-#define BCM281XX_PIN_SRI_D             194
-#define BCM281XX_PIN_SRI_E             195
-#define BCM281XX_PIN_SSP_EXTCLK                196
-#define BCM281XX_PIN_SSP0_CLK          197
-#define BCM281XX_PIN_SSP0_FS           198
-#define BCM281XX_PIN_SSP0_RXD          199
-#define BCM281XX_PIN_SSP0_TXD          200
-#define BCM281XX_PIN_SSP2_CLK          201
-#define BCM281XX_PIN_SSP2_FS_0         202
-#define BCM281XX_PIN_SSP2_FS_1         203
-#define BCM281XX_PIN_SSP2_FS_2         204
-#define BCM281XX_PIN_SSP2_FS_3         205
-#define BCM281XX_PIN_SSP2_RXD_0                206
-#define BCM281XX_PIN_SSP2_RXD_1                207
-#define BCM281XX_PIN_SSP2_TXD_0                208
-#define BCM281XX_PIN_SSP2_TXD_1                209
-#define BCM281XX_PIN_SSP3_CLK          210
-#define BCM281XX_PIN_SSP3_FS           211
-#define BCM281XX_PIN_SSP3_RXD          212
-#define BCM281XX_PIN_SSP3_TXD          213
-#define BCM281XX_PIN_SSP4_CLK          214
-#define BCM281XX_PIN_SSP4_FS           215
-#define BCM281XX_PIN_SSP4_RXD          216
-#define BCM281XX_PIN_SSP4_TXD          217
-#define BCM281XX_PIN_SSP5_CLK          218
-#define BCM281XX_PIN_SSP5_FS           219
-#define BCM281XX_PIN_SSP5_RXD          220
-#define BCM281XX_PIN_SSP5_TXD          221
-#define BCM281XX_PIN_SSP6_CLK          222
-#define BCM281XX_PIN_SSP6_FS           223
-#define BCM281XX_PIN_SSP6_RXD          224
-#define BCM281XX_PIN_SSP6_TXD          225
-#define BCM281XX_PIN_STAT_1            226
-#define BCM281XX_PIN_STAT_2            227
-#define BCM281XX_PIN_SYSCLKEN          228
-#define BCM281XX_PIN_TRACECLK          229
-#define BCM281XX_PIN_TRACEDT00         230
-#define BCM281XX_PIN_TRACEDT01         231
-#define BCM281XX_PIN_TRACEDT02         232
-#define BCM281XX_PIN_TRACEDT03         233
-#define BCM281XX_PIN_TRACEDT04         234
-#define BCM281XX_PIN_TRACEDT05         235
-#define BCM281XX_PIN_TRACEDT06         236
-#define BCM281XX_PIN_TRACEDT07         237
-#define BCM281XX_PIN_TRACEDT08         238
-#define BCM281XX_PIN_TRACEDT09         239
-#define BCM281XX_PIN_TRACEDT10         240
-#define BCM281XX_PIN_TRACEDT11         241
-#define BCM281XX_PIN_TRACEDT12         242
-#define BCM281XX_PIN_TRACEDT13         243
-#define BCM281XX_PIN_TRACEDT14         244
-#define BCM281XX_PIN_TRACEDT15         245
-#define BCM281XX_PIN_TXDATA3G0         246
-#define BCM281XX_PIN_TXPWRIND          247
-#define BCM281XX_PIN_UARTB1_UCTS       248
-#define BCM281XX_PIN_UARTB1_URTS       249
-#define BCM281XX_PIN_UARTB1_URXD       250
-#define BCM281XX_PIN_UARTB1_UTXD       251
-#define BCM281XX_PIN_UARTB2_URXD       252
-#define BCM281XX_PIN_UARTB2_UTXD       253
-#define BCM281XX_PIN_UARTB3_UCTS       254
-#define BCM281XX_PIN_UARTB3_URTS       255
-#define BCM281XX_PIN_UARTB3_URXD       256
-#define BCM281XX_PIN_UARTB3_UTXD       257
-#define BCM281XX_PIN_UARTB4_UCTS       258
-#define BCM281XX_PIN_UARTB4_URTS       259
-#define BCM281XX_PIN_UARTB4_URXD       260
-#define BCM281XX_PIN_UARTB4_UTXD       261
-#define BCM281XX_PIN_VC_CAM1_SCL       262
-#define BCM281XX_PIN_VC_CAM1_SDA       263
-#define BCM281XX_PIN_VC_CAM2_SCL       264
-#define BCM281XX_PIN_VC_CAM2_SDA       265
-#define BCM281XX_PIN_VC_CAM3_SCL       266
-#define BCM281XX_PIN_VC_CAM3_SDA       267
-
-#define BCM281XX_PIN_DESC(a, b, c) \
-       { .number = a, .name = b, .drv_data = &c##_pin }
-
-/*
- * Pin description definition.  The order here must be the same as defined in
- * the PADCTRLREG block in the RDB, since the pin number is used as an index
- * into this array.
- */
-static const struct pinctrl_pin_desc bcm281xx_pinctrl_pins[] = {
-       BCM281XX_PIN_DESC(BCM281XX_PIN_ADCSYNC, "adcsync", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_BAT_RM, "bat_rm", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_BSC1_SCL, "bsc1_scl", i2c),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_BSC1_SDA, "bsc1_sda", i2c),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_BSC2_SCL, "bsc2_scl", i2c),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_BSC2_SDA, "bsc2_sda", i2c),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_CLASSGPWR, "classgpwr", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_CLK_CX8, "clk_cx8", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_0, "clkout_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_1, "clkout_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_2, "clkout_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_3, "clkout_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_CLKREQ_IN_0, "clkreq_in_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_CLKREQ_IN_1, "clkreq_in_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_CWS_SYS_REQ1, "cws_sys_req1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_CWS_SYS_REQ2, "cws_sys_req2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_CWS_SYS_REQ3, "cws_sys_req3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC1_CLK, "digmic1_clk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC1_DQ, "digmic1_dq", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC2_CLK, "digmic2_clk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC2_DQ, "digmic2_dq", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPEN13, "gpen13", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPEN14, "gpen14", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPEN15, "gpen15", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO00, "gpio00", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO01, "gpio01", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO02, "gpio02", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO03, "gpio03", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO04, "gpio04", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO05, "gpio05", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO06, "gpio06", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO07, "gpio07", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO08, "gpio08", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO09, "gpio09", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO10, "gpio10", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO11, "gpio11", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO12, "gpio12", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO13, "gpio13", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO14, "gpio14", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPS_PABLANK, "gps_pablank", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_GPS_TMARK, "gps_tmark", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_HDMI_SCL, "hdmi_scl", hdmi),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_HDMI_SDA, "hdmi_sda", hdmi),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_IC_DM, "ic_dm", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_IC_DP, "ic_dp", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_0, "kp_col_ip_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_1, "kp_col_ip_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_2, "kp_col_ip_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_3, "kp_col_ip_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_0, "kp_row_op_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_1, "kp_row_op_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_2, "kp_row_op_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_3, "kp_row_op_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_0, "lcd_b_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_1, "lcd_b_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_2, "lcd_b_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_3, "lcd_b_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_4, "lcd_b_4", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_5, "lcd_b_5", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_6, "lcd_b_6", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_7, "lcd_b_7", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_0, "lcd_g_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_1, "lcd_g_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_2, "lcd_g_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_3, "lcd_g_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_4, "lcd_g_4", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_5, "lcd_g_5", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_6, "lcd_g_6", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_7, "lcd_g_7", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_HSYNC, "lcd_hsync", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_OE, "lcd_oe", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_PCLK, "lcd_pclk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_0, "lcd_r_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_1, "lcd_r_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_2, "lcd_r_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_3, "lcd_r_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_4, "lcd_r_4", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_5, "lcd_r_5", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_6, "lcd_r_6", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_7, "lcd_r_7", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_VSYNC, "lcd_vsync", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO0, "mdmgpio0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO1, "mdmgpio1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO2, "mdmgpio2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO3, "mdmgpio3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO4, "mdmgpio4", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO5, "mdmgpio5", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO6, "mdmgpio6", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO7, "mdmgpio7", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO8, "mdmgpio8", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_0, "mphi_data_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_1, "mphi_data_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_2, "mphi_data_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_3, "mphi_data_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_4, "mphi_data_4", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_5, "mphi_data_5", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_6, "mphi_data_6", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_7, "mphi_data_7", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_8, "mphi_data_8", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_9, "mphi_data_9", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_10, "mphi_data_10", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_11, "mphi_data_11", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_12, "mphi_data_12", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_13, "mphi_data_13", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_14, "mphi_data_14", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_15, "mphi_data_15", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HA0, "mphi_ha0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HAT0, "mphi_hat0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HAT1, "mphi_hat1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HCE0_N, "mphi_hce0_n", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HCE1_N, "mphi_hce1_n", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HRD_N, "mphi_hrd_n", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HWR_N, "mphi_hwr_n", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_RUN0, "mphi_run0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_RUN1, "mphi_run1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MTX_SCAN_CLK, "mtx_scan_clk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_MTX_SCAN_DATA, "mtx_scan_data", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_0, "nand_ad_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_1, "nand_ad_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_2, "nand_ad_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_3, "nand_ad_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_4, "nand_ad_4", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_5, "nand_ad_5", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_6, "nand_ad_6", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_7, "nand_ad_7", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_ALE, "nand_ale", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_CEN_0, "nand_cen_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_CEN_1, "nand_cen_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_CLE, "nand_cle", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_OEN, "nand_oen", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_RDY_0, "nand_rdy_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_RDY_1, "nand_rdy_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_WEN, "nand_wen", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_WP, "nand_wp", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_PC1, "pc1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_PC2, "pc2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_PMU_INT, "pmu_int", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_PMU_SCL, "pmu_scl", i2c),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_PMU_SDA, "pmu_sda", i2c),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RFST2G_MTSLOTEN3G, "rfst2g_mtsloten3g",
-               std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RX_CTL, "rgmii_0_rx_ctl", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXC, "rgmii_0_rxc", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_0, "rgmii_0_rxd_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_1, "rgmii_0_rxd_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_2, "rgmii_0_rxd_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_3, "rgmii_0_rxd_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TX_CTL, "rgmii_0_tx_ctl", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXC, "rgmii_0_txc", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_0, "rgmii_0_txd_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_1, "rgmii_0_txd_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_2, "rgmii_0_txd_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_3, "rgmii_0_txd_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RX_CTL, "rgmii_1_rx_ctl", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXC, "rgmii_1_rxc", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_0, "rgmii_1_rxd_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_1, "rgmii_1_rxd_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_2, "rgmii_1_rxd_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_3, "rgmii_1_rxd_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TX_CTL, "rgmii_1_tx_ctl", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXC, "rgmii_1_txc", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_0, "rgmii_1_txd_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_1, "rgmii_1_txd_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_2, "rgmii_1_txd_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_3, "rgmii_1_txd_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_0, "rgmii_gpio_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_1, "rgmii_gpio_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_2, "rgmii_gpio_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_3, "rgmii_gpio_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RTXDATA2G_TXDATA3G1,
-               "rtxdata2g_txdata3g1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RTXEN2G_TXDATA3G2, "rtxen2g_txdata3g2",
-               std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RXDATA3G0, "rxdata3g0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RXDATA3G1, "rxdata3g1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_RXDATA3G2, "rxdata3g2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_CLK, "sdio1_clk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_CMD, "sdio1_cmd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_0, "sdio1_data_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_1, "sdio1_data_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_2, "sdio1_data_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_3, "sdio1_data_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_CLK, "sdio4_clk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_CMD, "sdio4_cmd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_0, "sdio4_data_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_1, "sdio4_data_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_2, "sdio4_data_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_3, "sdio4_data_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_CLK, "sim_clk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_DATA, "sim_data", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_DET, "sim_det", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_RESETN, "sim_resetn", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_CLK, "sim2_clk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_DATA, "sim2_data", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_DET, "sim2_det", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_RESETN, "sim2_resetn", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SRI_C, "sri_c", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SRI_D, "sri_d", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SRI_E, "sri_e", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP_EXTCLK, "ssp_extclk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_CLK, "ssp0_clk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_FS, "ssp0_fs", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_RXD, "ssp0_rxd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_TXD, "ssp0_txd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_CLK, "ssp2_clk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_0, "ssp2_fs_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_1, "ssp2_fs_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_2, "ssp2_fs_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_3, "ssp2_fs_3", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_RXD_0, "ssp2_rxd_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_RXD_1, "ssp2_rxd_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_TXD_0, "ssp2_txd_0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_TXD_1, "ssp2_txd_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_CLK, "ssp3_clk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_FS, "ssp3_fs", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_RXD, "ssp3_rxd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_TXD, "ssp3_txd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_CLK, "ssp4_clk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_FS, "ssp4_fs", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_RXD, "ssp4_rxd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_TXD, "ssp4_txd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_CLK, "ssp5_clk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_FS, "ssp5_fs", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_RXD, "ssp5_rxd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_TXD, "ssp5_txd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_CLK, "ssp6_clk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_FS, "ssp6_fs", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_RXD, "ssp6_rxd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_TXD, "ssp6_txd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_STAT_1, "stat_1", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_STAT_2, "stat_2", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_SYSCLKEN, "sysclken", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACECLK, "traceclk", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT00, "tracedt00", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT01, "tracedt01", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT02, "tracedt02", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT03, "tracedt03", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT04, "tracedt04", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT05, "tracedt05", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT06, "tracedt06", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT07, "tracedt07", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT08, "tracedt08", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT09, "tracedt09", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT10, "tracedt10", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT11, "tracedt11", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT12, "tracedt12", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT13, "tracedt13", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT14, "tracedt14", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT15, "tracedt15", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TXDATA3G0, "txdata3g0", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_TXPWRIND, "txpwrind", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_UCTS, "uartb1_ucts", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_URTS, "uartb1_urts", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_URXD, "uartb1_urxd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_UTXD, "uartb1_utxd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB2_URXD, "uartb2_urxd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB2_UTXD, "uartb2_utxd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_UCTS, "uartb3_ucts", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_URTS, "uartb3_urts", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_URXD, "uartb3_urxd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_UTXD, "uartb3_utxd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_UCTS, "uartb4_ucts", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_URTS, "uartb4_urts", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_URXD, "uartb4_urxd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_UTXD, "uartb4_utxd", std),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM1_SCL, "vc_cam1_scl", i2c),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM1_SDA, "vc_cam1_sda", i2c),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM2_SCL, "vc_cam2_scl", i2c),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM2_SDA, "vc_cam2_sda", i2c),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM3_SCL, "vc_cam3_scl", i2c),
-       BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM3_SDA, "vc_cam3_sda", i2c),
-};
-
-static const char * const bcm281xx_alt_groups[] = {
-       "adcsync",
-       "bat_rm",
-       "bsc1_scl",
-       "bsc1_sda",
-       "bsc2_scl",
-       "bsc2_sda",
-       "classgpwr",
-       "clk_cx8",
-       "clkout_0",
-       "clkout_1",
-       "clkout_2",
-       "clkout_3",
-       "clkreq_in_0",
-       "clkreq_in_1",
-       "cws_sys_req1",
-       "cws_sys_req2",
-       "cws_sys_req3",
-       "digmic1_clk",
-       "digmic1_dq",
-       "digmic2_clk",
-       "digmic2_dq",
-       "gpen13",
-       "gpen14",
-       "gpen15",
-       "gpio00",
-       "gpio01",
-       "gpio02",
-       "gpio03",
-       "gpio04",
-       "gpio05",
-       "gpio06",
-       "gpio07",
-       "gpio08",
-       "gpio09",
-       "gpio10",
-       "gpio11",
-       "gpio12",
-       "gpio13",
-       "gpio14",
-       "gps_pablank",
-       "gps_tmark",
-       "hdmi_scl",
-       "hdmi_sda",
-       "ic_dm",
-       "ic_dp",
-       "kp_col_ip_0",
-       "kp_col_ip_1",
-       "kp_col_ip_2",
-       "kp_col_ip_3",
-       "kp_row_op_0",
-       "kp_row_op_1",
-       "kp_row_op_2",
-       "kp_row_op_3",
-       "lcd_b_0",
-       "lcd_b_1",
-       "lcd_b_2",
-       "lcd_b_3",
-       "lcd_b_4",
-       "lcd_b_5",
-       "lcd_b_6",
-       "lcd_b_7",
-       "lcd_g_0",
-       "lcd_g_1",
-       "lcd_g_2",
-       "lcd_g_3",
-       "lcd_g_4",
-       "lcd_g_5",
-       "lcd_g_6",
-       "lcd_g_7",
-       "lcd_hsync",
-       "lcd_oe",
-       "lcd_pclk",
-       "lcd_r_0",
-       "lcd_r_1",
-       "lcd_r_2",
-       "lcd_r_3",
-       "lcd_r_4",
-       "lcd_r_5",
-       "lcd_r_6",
-       "lcd_r_7",
-       "lcd_vsync",
-       "mdmgpio0",
-       "mdmgpio1",
-       "mdmgpio2",
-       "mdmgpio3",
-       "mdmgpio4",
-       "mdmgpio5",
-       "mdmgpio6",
-       "mdmgpio7",
-       "mdmgpio8",
-       "mphi_data_0",
-       "mphi_data_1",
-       "mphi_data_2",
-       "mphi_data_3",
-       "mphi_data_4",
-       "mphi_data_5",
-       "mphi_data_6",
-       "mphi_data_7",
-       "mphi_data_8",
-       "mphi_data_9",
-       "mphi_data_10",
-       "mphi_data_11",
-       "mphi_data_12",
-       "mphi_data_13",
-       "mphi_data_14",
-       "mphi_data_15",
-       "mphi_ha0",
-       "mphi_hat0",
-       "mphi_hat1",
-       "mphi_hce0_n",
-       "mphi_hce1_n",
-       "mphi_hrd_n",
-       "mphi_hwr_n",
-       "mphi_run0",
-       "mphi_run1",
-       "mtx_scan_clk",
-       "mtx_scan_data",
-       "nand_ad_0",
-       "nand_ad_1",
-       "nand_ad_2",
-       "nand_ad_3",
-       "nand_ad_4",
-       "nand_ad_5",
-       "nand_ad_6",
-       "nand_ad_7",
-       "nand_ale",
-       "nand_cen_0",
-       "nand_cen_1",
-       "nand_cle",
-       "nand_oen",
-       "nand_rdy_0",
-       "nand_rdy_1",
-       "nand_wen",
-       "nand_wp",
-       "pc1",
-       "pc2",
-       "pmu_int",
-       "pmu_scl",
-       "pmu_sda",
-       "rfst2g_mtsloten3g",
-       "rgmii_0_rx_ctl",
-       "rgmii_0_rxc",
-       "rgmii_0_rxd_0",
-       "rgmii_0_rxd_1",
-       "rgmii_0_rxd_2",
-       "rgmii_0_rxd_3",
-       "rgmii_0_tx_ctl",
-       "rgmii_0_txc",
-       "rgmii_0_txd_0",
-       "rgmii_0_txd_1",
-       "rgmii_0_txd_2",
-       "rgmii_0_txd_3",
-       "rgmii_1_rx_ctl",
-       "rgmii_1_rxc",
-       "rgmii_1_rxd_0",
-       "rgmii_1_rxd_1",
-       "rgmii_1_rxd_2",
-       "rgmii_1_rxd_3",
-       "rgmii_1_tx_ctl",
-       "rgmii_1_txc",
-       "rgmii_1_txd_0",
-       "rgmii_1_txd_1",
-       "rgmii_1_txd_2",
-       "rgmii_1_txd_3",
-       "rgmii_gpio_0",
-       "rgmii_gpio_1",
-       "rgmii_gpio_2",
-       "rgmii_gpio_3",
-       "rtxdata2g_txdata3g1",
-       "rtxen2g_txdata3g2",
-       "rxdata3g0",
-       "rxdata3g1",
-       "rxdata3g2",
-       "sdio1_clk",
-       "sdio1_cmd",
-       "sdio1_data_0",
-       "sdio1_data_1",
-       "sdio1_data_2",
-       "sdio1_data_3",
-       "sdio4_clk",
-       "sdio4_cmd",
-       "sdio4_data_0",
-       "sdio4_data_1",
-       "sdio4_data_2",
-       "sdio4_data_3",
-       "sim_clk",
-       "sim_data",
-       "sim_det",
-       "sim_resetn",
-       "sim2_clk",
-       "sim2_data",
-       "sim2_det",
-       "sim2_resetn",
-       "sri_c",
-       "sri_d",
-       "sri_e",
-       "ssp_extclk",
-       "ssp0_clk",
-       "ssp0_fs",
-       "ssp0_rxd",
-       "ssp0_txd",
-       "ssp2_clk",
-       "ssp2_fs_0",
-       "ssp2_fs_1",
-       "ssp2_fs_2",
-       "ssp2_fs_3",
-       "ssp2_rxd_0",
-       "ssp2_rxd_1",
-       "ssp2_txd_0",
-       "ssp2_txd_1",
-       "ssp3_clk",
-       "ssp3_fs",
-       "ssp3_rxd",
-       "ssp3_txd",
-       "ssp4_clk",
-       "ssp4_fs",
-       "ssp4_rxd",
-       "ssp4_txd",
-       "ssp5_clk",
-       "ssp5_fs",
-       "ssp5_rxd",
-       "ssp5_txd",
-       "ssp6_clk",
-       "ssp6_fs",
-       "ssp6_rxd",
-       "ssp6_txd",
-       "stat_1",
-       "stat_2",
-       "sysclken",
-       "traceclk",
-       "tracedt00",
-       "tracedt01",
-       "tracedt02",
-       "tracedt03",
-       "tracedt04",
-       "tracedt05",
-       "tracedt06",
-       "tracedt07",
-       "tracedt08",
-       "tracedt09",
-       "tracedt10",
-       "tracedt11",
-       "tracedt12",
-       "tracedt13",
-       "tracedt14",
-       "tracedt15",
-       "txdata3g0",
-       "txpwrind",
-       "uartb1_ucts",
-       "uartb1_urts",
-       "uartb1_urxd",
-       "uartb1_utxd",
-       "uartb2_urxd",
-       "uartb2_utxd",
-       "uartb3_ucts",
-       "uartb3_urts",
-       "uartb3_urxd",
-       "uartb3_utxd",
-       "uartb4_ucts",
-       "uartb4_urts",
-       "uartb4_urxd",
-       "uartb4_utxd",
-       "vc_cam1_scl",
-       "vc_cam1_sda",
-       "vc_cam2_scl",
-       "vc_cam2_sda",
-       "vc_cam3_scl",
-       "vc_cam3_sda",
-};
-
-/* Every pin can implement all ALT1-ALT4 functions */
-#define BCM281XX_PIN_FUNCTION(fcn_name)                        \
-{                                                      \
-       .name = #fcn_name,                              \
-       .groups = bcm281xx_alt_groups,                  \
-       .ngroups = ARRAY_SIZE(bcm281xx_alt_groups),     \
-}
-
-static const struct bcm281xx_pin_function bcm281xx_functions[] = {
-       BCM281XX_PIN_FUNCTION(alt1),
-       BCM281XX_PIN_FUNCTION(alt2),
-       BCM281XX_PIN_FUNCTION(alt3),
-       BCM281XX_PIN_FUNCTION(alt4),
-};
-
-static struct bcm281xx_pinctrl_data bcm281xx_pinctrl = {
-       .pins = bcm281xx_pinctrl_pins,
-       .npins = ARRAY_SIZE(bcm281xx_pinctrl_pins),
-       .functions = bcm281xx_functions,
-       .nfunctions = ARRAY_SIZE(bcm281xx_functions),
-};
-
-static inline enum bcm281xx_pin_type pin_type_get(struct pinctrl_dev *pctldev,
-                                                 unsigned pin)
-{
-       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-       if (pin >= pdata->npins)
-               return BCM281XX_PIN_TYPE_UNKNOWN;
-
-       return *(enum bcm281xx_pin_type *)(pdata->pins[pin].drv_data);
-}
-
-#define BCM281XX_PIN_SHIFT(type, param) \
-       (BCM281XX_ ## type ## _PIN_REG_ ## param ## _SHIFT)
-
-#define BCM281XX_PIN_MASK(type, param) \
-       (BCM281XX_ ## type ## _PIN_REG_ ## param ## _MASK)
-
-/*
- * This helper function is used to build up the value and mask used to write to
- * a pin register, but does not actually write to the register.
- */
-static inline void bcm281xx_pin_update(u32 *reg_val, u32 *reg_mask,
-                                      u32 param_val, u32 param_shift,
-                                      u32 param_mask)
-{
-       *reg_val &= ~param_mask;
-       *reg_val |= (param_val << param_shift) & param_mask;
-       *reg_mask |= param_mask;
-}
-
-static const struct regmap_config bcm281xx_pinctrl_regmap_config = {
-       .reg_bits = 32,
-       .reg_stride = 4,
-       .val_bits = 32,
-       .max_register = BCM281XX_PIN_VC_CAM3_SDA,
-};
-
-static int bcm281xx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
-{
-       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-       return pdata->npins;
-}
-
-static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
-                                                  unsigned group)
-{
-       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-       return pdata->pins[group].name;
-}
-
-static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
-                                          unsigned group,
-                                          const unsigned **pins,
-                                          unsigned *num_pins)
-{
-       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-       *pins = &pdata->pins[group].number;
-       *num_pins = 1;
-
-       return 0;
-}
-
-static void bcm281xx_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
-                                         struct seq_file *s,
-                                         unsigned offset)
-{
-       seq_printf(s, " %s", dev_name(pctldev->dev));
-}
-
-static struct pinctrl_ops bcm281xx_pinctrl_ops = {
-       .get_groups_count = bcm281xx_pinctrl_get_groups_count,
-       .get_group_name = bcm281xx_pinctrl_get_group_name,
-       .get_group_pins = bcm281xx_pinctrl_get_group_pins,
-       .pin_dbg_show = bcm281xx_pinctrl_pin_dbg_show,
-       .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
-       .dt_free_map = pinctrl_utils_dt_free_map,
-};
-
-static int bcm281xx_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev)
-{
-       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-       return pdata->nfunctions;
-}
-
-static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
-                                                unsigned function)
-{
-       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-       return pdata->functions[function].name;
-}
-
-static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
-                                          unsigned function,
-                                          const char * const **groups,
-                                          unsigned * const num_groups)
-{
-       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
-       *groups = pdata->functions[function].groups;
-       *num_groups = pdata->functions[function].ngroups;
-
-       return 0;
-}
-
-static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev,
-                              unsigned function,
-                              unsigned group)
-{
-       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-       const struct bcm281xx_pin_function *f = &pdata->functions[function];
-       u32 offset = 4 * pdata->pins[group].number;
-       int rc = 0;
-
-       dev_dbg(pctldev->dev,
-               "%s(): Enable function %s (%d) of pin %s (%d) @offset 0x%x.\n",
-               __func__, f->name, function, pdata->pins[group].name,
-               pdata->pins[group].number, offset);
-
-       rc = regmap_update_bits(pdata->regmap, offset,
-               BCM281XX_PIN_REG_F_SEL_MASK,
-               function << BCM281XX_PIN_REG_F_SEL_SHIFT);
-       if (rc)
-               dev_err(pctldev->dev,
-                       "Error updating register for pin %s (%d).\n",
-                       pdata->pins[group].name, pdata->pins[group].number);
-
-       return rc;
-}
-
-static struct pinmux_ops bcm281xx_pinctrl_pinmux_ops = {
-       .get_functions_count = bcm281xx_pinctrl_get_fcns_count,
-       .get_function_name = bcm281xx_pinctrl_get_fcn_name,
-       .get_function_groups = bcm281xx_pinctrl_get_fcn_groups,
-       .set_mux = bcm281xx_pinmux_set,
-};
-
-static int bcm281xx_pinctrl_pin_config_get(struct pinctrl_dev *pctldev,
-                                          unsigned pin,
-                                          unsigned long *config)
-{
-       return -ENOTSUPP;
-}
-
-
-/* Goes through the configs and update register val/mask */
-static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev,
-                                  unsigned pin,
-                                  unsigned long *configs,
-                                  unsigned num_configs,
-                                  u32 *val,
-                                  u32 *mask)
-{
-       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-       int i;
-       enum pin_config_param param;
-       u16 arg;
-
-       for (i = 0; i < num_configs; i++) {
-               param = pinconf_to_config_param(configs[i]);
-               arg = pinconf_to_config_argument(configs[i]);
-
-               switch (param) {
-               case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
-                       arg = (arg >= 1 ? 1 : 0);
-                       bcm281xx_pin_update(val, mask, arg,
-                               BCM281XX_PIN_SHIFT(STD, HYST),
-                               BCM281XX_PIN_MASK(STD, HYST));
-                       break;
-               /*
-                * The pin bias can only be one of pull-up, pull-down, or
-                * disable.  The user does not need to specify a value for the
-                * property, and the default value from pinconf-generic is
-                * ignored.
-                */
-               case PIN_CONFIG_BIAS_DISABLE:
-                       bcm281xx_pin_update(val, mask, 0,
-                               BCM281XX_PIN_SHIFT(STD, PULL_UP),
-                               BCM281XX_PIN_MASK(STD, PULL_UP));
-                       bcm281xx_pin_update(val, mask, 0,
-                               BCM281XX_PIN_SHIFT(STD, PULL_DN),
-                               BCM281XX_PIN_MASK(STD, PULL_DN));
-                       break;
-
-               case PIN_CONFIG_BIAS_PULL_UP:
-                       bcm281xx_pin_update(val, mask, 1,
-                               BCM281XX_PIN_SHIFT(STD, PULL_UP),
-                               BCM281XX_PIN_MASK(STD, PULL_UP));
-                       bcm281xx_pin_update(val, mask, 0,
-                               BCM281XX_PIN_SHIFT(STD, PULL_DN),
-                               BCM281XX_PIN_MASK(STD, PULL_DN));
-                       break;
-
-               case PIN_CONFIG_BIAS_PULL_DOWN:
-                       bcm281xx_pin_update(val, mask, 0,
-                               BCM281XX_PIN_SHIFT(STD, PULL_UP),
-                               BCM281XX_PIN_MASK(STD, PULL_UP));
-                       bcm281xx_pin_update(val, mask, 1,
-                               BCM281XX_PIN_SHIFT(STD, PULL_DN),
-                               BCM281XX_PIN_MASK(STD, PULL_DN));
-                       break;
-
-               case PIN_CONFIG_SLEW_RATE:
-                       arg = (arg >= 1 ? 1 : 0);
-                       bcm281xx_pin_update(val, mask, arg,
-                               BCM281XX_PIN_SHIFT(STD, SLEW),
-                               BCM281XX_PIN_MASK(STD, SLEW));
-                       break;
-
-               case PIN_CONFIG_INPUT_ENABLE:
-                       /* inversed since register is for input _disable_ */
-                       arg = (arg >= 1 ? 0 : 1);
-                       bcm281xx_pin_update(val, mask, arg,
-                               BCM281XX_PIN_SHIFT(STD, INPUT_DIS),
-                               BCM281XX_PIN_MASK(STD, INPUT_DIS));
-                       break;
-
-               case PIN_CONFIG_DRIVE_STRENGTH:
-                       /* Valid range is 2-16 mA, even numbers only */
-                       if ((arg < 2) || (arg > 16) || (arg % 2)) {
-                               dev_err(pctldev->dev,
-                                       "Invalid Drive Strength value (%d) for "
-                                       "pin %s (%d). Valid values are "
-                                       "(2..16) mA, even numbers only.\n",
-                                       arg, pdata->pins[pin].name, pin);
-                               return -EINVAL;
-                       }
-                       bcm281xx_pin_update(val, mask, (arg/2)-1,
-                               BCM281XX_PIN_SHIFT(STD, DRV_STR),
-                               BCM281XX_PIN_MASK(STD, DRV_STR));
-                       break;
-
-               default:
-                       dev_err(pctldev->dev,
-                               "Unrecognized pin config %d for pin %s (%d).\n",
-                               param, pdata->pins[pin].name, pin);
-                       return -EINVAL;
-
-               } /* switch config */
-       } /* for each config */
-
-       return 0;
-}
-
-/*
- * The pull-up strength for an I2C pin is represented by bits 4-6 in the
- * register with the following mapping:
- *   0b000: No pull-up
- *   0b001: 1200 Ohm
- *   0b010: 1800 Ohm
- *   0b011: 720 Ohm
- *   0b100: 2700 Ohm
- *   0b101: 831 Ohm
- *   0b110: 1080 Ohm
- *   0b111: 568 Ohm
- * This array maps pull-up strength in Ohms to register values (1+index).
- */
-static const u16 bcm281xx_pullup_map[] = {
-       1200, 1800, 720, 2700, 831, 1080, 568
-};
-
-/* Goes through the configs and update register val/mask */
-static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
-                                  unsigned pin,
-                                  unsigned long *configs,
-                                  unsigned num_configs,
-                                  u32 *val,
-                                  u32 *mask)
-{
-       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-       int i, j;
-       enum pin_config_param param;
-       u16 arg;
-
-       for (i = 0; i < num_configs; i++) {
-               param = pinconf_to_config_param(configs[i]);
-               arg = pinconf_to_config_argument(configs[i]);
-
-               switch (param) {
-               case PIN_CONFIG_BIAS_PULL_UP:
-                       for (j = 0; j < ARRAY_SIZE(bcm281xx_pullup_map); j++)
-                               if (bcm281xx_pullup_map[j] == arg)
-                                       break;
-
-                       if (j == ARRAY_SIZE(bcm281xx_pullup_map)) {
-                               dev_err(pctldev->dev,
-                                       "Invalid pull-up value (%d) for pin %s "
-                                       "(%d). Valid values are 568, 720, 831, "
-                                       "1080, 1200, 1800, 2700 Ohms.\n",
-                                       arg, pdata->pins[pin].name, pin);
-                               return -EINVAL;
-                       }
-
-                       bcm281xx_pin_update(val, mask, j+1,
-                               BCM281XX_PIN_SHIFT(I2C, PULL_UP_STR),
-                               BCM281XX_PIN_MASK(I2C, PULL_UP_STR));
-                       break;
-
-               case PIN_CONFIG_BIAS_DISABLE:
-                       bcm281xx_pin_update(val, mask, 0,
-                               BCM281XX_PIN_SHIFT(I2C, PULL_UP_STR),
-                               BCM281XX_PIN_MASK(I2C, PULL_UP_STR));
-                       break;
-
-               case PIN_CONFIG_SLEW_RATE:
-                       arg = (arg >= 1 ? 1 : 0);
-                       bcm281xx_pin_update(val, mask, arg,
-                               BCM281XX_PIN_SHIFT(I2C, SLEW),
-                               BCM281XX_PIN_MASK(I2C, SLEW));
-                       break;
-
-               case PIN_CONFIG_INPUT_ENABLE:
-                       /* inversed since register is for input _disable_ */
-                       arg = (arg >= 1 ? 0 : 1);
-                       bcm281xx_pin_update(val, mask, arg,
-                               BCM281XX_PIN_SHIFT(I2C, INPUT_DIS),
-                               BCM281XX_PIN_MASK(I2C, INPUT_DIS));
-                       break;
-
-               default:
-                       dev_err(pctldev->dev,
-                               "Unrecognized pin config %d for pin %s (%d).\n",
-                               param, pdata->pins[pin].name, pin);
-                       return -EINVAL;
-
-               } /* switch config */
-       } /* for each config */
-
-       return 0;
-}
-
-/* Goes through the configs and update register val/mask */
-static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev,
-                                   unsigned pin,
-                                   unsigned long *configs,
-                                   unsigned num_configs,
-                                   u32 *val,
-                                   u32 *mask)
-{
-       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-       int i;
-       enum pin_config_param param;
-       u16 arg;
-
-       for (i = 0; i < num_configs; i++) {
-               param = pinconf_to_config_param(configs[i]);
-               arg = pinconf_to_config_argument(configs[i]);
-
-               switch (param) {
-               case PIN_CONFIG_SLEW_RATE:
-                       arg = (arg >= 1 ? 1 : 0);
-                       bcm281xx_pin_update(val, mask, arg,
-                               BCM281XX_PIN_SHIFT(HDMI, MODE),
-                               BCM281XX_PIN_MASK(HDMI, MODE));
-                       break;
-
-               case PIN_CONFIG_INPUT_ENABLE:
-                       /* inversed since register is for input _disable_ */
-                       arg = (arg >= 1 ? 0 : 1);
-                       bcm281xx_pin_update(val, mask, arg,
-                               BCM281XX_PIN_SHIFT(HDMI, INPUT_DIS),
-                               BCM281XX_PIN_MASK(HDMI, INPUT_DIS));
-                       break;
-
-               default:
-                       dev_err(pctldev->dev,
-                               "Unrecognized pin config %d for pin %s (%d).\n",
-                               param, pdata->pins[pin].name, pin);
-                       return -EINVAL;
-
-               } /* switch config */
-       } /* for each config */
-
-       return 0;
-}
-
-static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
-                                          unsigned pin,
-                                          unsigned long *configs,
-                                          unsigned num_configs)
-{
-       struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-       enum bcm281xx_pin_type pin_type;
-       u32 offset = 4 * pin;
-       u32 cfg_val, cfg_mask;
-       int rc;
-
-       cfg_val = 0;
-       cfg_mask = 0;
-       pin_type = pin_type_get(pctldev, pin);
-
-       /* Different pins have different configuration options */
-       switch (pin_type) {
-       case BCM281XX_PIN_TYPE_STD:
-               rc = bcm281xx_std_pin_update(pctldev, pin, configs,
-                       num_configs, &cfg_val, &cfg_mask);
-               break;
-
-       case BCM281XX_PIN_TYPE_I2C:
-               rc = bcm281xx_i2c_pin_update(pctldev, pin, configs,
-                       num_configs, &cfg_val, &cfg_mask);
-               break;
-
-       case BCM281XX_PIN_TYPE_HDMI:
-               rc = bcm281xx_hdmi_pin_update(pctldev, pin, configs,
-                       num_configs, &cfg_val, &cfg_mask);
-               break;
-
-       default:
-               dev_err(pctldev->dev, "Unknown pin type for pin %s (%d).\n",
-                       pdata->pins[pin].name, pin);
-               return -EINVAL;
-
-       } /* switch pin type */
-
-       if (rc)
-               return rc;
-
-       dev_dbg(pctldev->dev,
-               "%s(): Set pin %s (%d) with config 0x%x, mask 0x%x\n",
-               __func__, pdata->pins[pin].name, pin, cfg_val, cfg_mask);
-
-       rc = regmap_update_bits(pdata->regmap, offset, cfg_mask, cfg_val);
-       if (rc) {
-               dev_err(pctldev->dev,
-                       "Error updating register for pin %s (%d).\n",
-                       pdata->pins[pin].name, pin);
-               return rc;
-       }
-
-       return 0;
-}
-
-static struct pinconf_ops bcm281xx_pinctrl_pinconf_ops = {
-       .pin_config_get = bcm281xx_pinctrl_pin_config_get,
-       .pin_config_set = bcm281xx_pinctrl_pin_config_set,
-};
-
-static struct pinctrl_desc bcm281xx_pinctrl_desc = {
-       /* name, pins, npins members initialized in probe function */
-       .pctlops = &bcm281xx_pinctrl_ops,
-       .pmxops = &bcm281xx_pinctrl_pinmux_ops,
-       .confops = &bcm281xx_pinctrl_pinconf_ops,
-       .owner = THIS_MODULE,
-};
-
-static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
-{
-       struct bcm281xx_pinctrl_data *pdata = &bcm281xx_pinctrl;
-       struct resource *res;
-       struct pinctrl_dev *pctl;
-
-       /* So far We can assume there is only 1 bank of registers */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       pdata->reg_base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(pdata->reg_base)) {
-               dev_err(&pdev->dev, "Failed to ioremap MEM resource\n");
-               return -ENODEV;
-       }
-
-       /* Initialize the dynamic part of pinctrl_desc */
-       pdata->regmap = devm_regmap_init_mmio(&pdev->dev, pdata->reg_base,
-               &bcm281xx_pinctrl_regmap_config);
-       if (IS_ERR(pdata->regmap)) {
-               dev_err(&pdev->dev, "Regmap MMIO init failed.\n");
-               return -ENODEV;
-       }
-
-       bcm281xx_pinctrl_desc.name = dev_name(&pdev->dev);
-       bcm281xx_pinctrl_desc.pins = bcm281xx_pinctrl.pins;
-       bcm281xx_pinctrl_desc.npins = bcm281xx_pinctrl.npins;
-
-       pctl = pinctrl_register(&bcm281xx_pinctrl_desc,
-                               &pdev->dev,
-                               pdata);
-       if (!pctl) {
-               dev_err(&pdev->dev, "Failed to register pinctrl\n");
-               return -ENODEV;
-       }
-
-       platform_set_drvdata(pdev, pdata);
-
-       return 0;
-}
-
-static const struct of_device_id bcm281xx_pinctrl_of_match[] = {
-       { .compatible = "brcm,bcm11351-pinctrl", },
-       { },
-};
-
-static struct platform_driver bcm281xx_pinctrl_driver = {
-       .driver = {
-               .name = "bcm281xx-pinctrl",
-               .of_match_table = bcm281xx_pinctrl_of_match,
-       },
-};
-
-module_platform_driver_probe(bcm281xx_pinctrl_driver, bcm281xx_pinctrl_probe);
-
-MODULE_AUTHOR("Broadcom Corporation <bcm-kernel-feedback-list@broadcom.com>");
-MODULE_AUTHOR("Sherman Yin <syin@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom BCM281xx pinctrl driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c
deleted file mode 100644 (file)
index 9aa8a3f..0000000
+++ /dev/null
@@ -1,1072 +0,0 @@
-/*
- * Driver for Broadcom BCM2835 GPIO unit (pinctrl + GPIO)
- *
- * Copyright (C) 2012 Chris Boot, Simon Arlott, Stephen Warren
- *
- * This driver is inspired by:
- * pinctrl-nomadik.c, please see original file for copyright information
- * pinctrl-tegra.c, please see original file for copyright information
- *
- * 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/bitmap.h>
-#include <linux/bug.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/irqdesc.h>
-#include <linux/irqdomain.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/pinctrl/pinconf.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/platform_device.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-#define MODULE_NAME "pinctrl-bcm2835"
-#define BCM2835_NUM_GPIOS 54
-#define BCM2835_NUM_BANKS 2
-
-#define BCM2835_PIN_BITMAP_SZ \
-       DIV_ROUND_UP(BCM2835_NUM_GPIOS, sizeof(unsigned long) * 8)
-
-/* GPIO register offsets */
-#define GPFSEL0                0x0     /* Function Select */
-#define GPSET0         0x1c    /* Pin Output Set */
-#define GPCLR0         0x28    /* Pin Output Clear */
-#define GPLEV0         0x34    /* Pin Level */
-#define GPEDS0         0x40    /* Pin Event Detect Status */
-#define GPREN0         0x4c    /* Pin Rising Edge Detect Enable */
-#define GPFEN0         0x58    /* Pin Falling Edge Detect Enable */
-#define GPHEN0         0x64    /* Pin High Detect Enable */
-#define GPLEN0         0x70    /* Pin Low Detect Enable */
-#define GPAREN0                0x7c    /* Pin Async Rising Edge Detect */
-#define GPAFEN0                0x88    /* Pin Async Falling Edge Detect */
-#define GPPUD          0x94    /* Pin Pull-up/down Enable */
-#define GPPUDCLK0      0x98    /* Pin Pull-up/down Enable Clock */
-
-#define FSEL_REG(p)            (GPFSEL0 + (((p) / 10) * 4))
-#define FSEL_SHIFT(p)          (((p) % 10) * 3)
-#define GPIO_REG_OFFSET(p)     ((p) / 32)
-#define GPIO_REG_SHIFT(p)      ((p) % 32)
-
-enum bcm2835_pinconf_param {
-       /* argument: bcm2835_pinconf_pull */
-       BCM2835_PINCONF_PARAM_PULL,
-};
-
-enum bcm2835_pinconf_pull {
-       BCM2835_PINCONFIG_PULL_NONE,
-       BCM2835_PINCONFIG_PULL_DOWN,
-       BCM2835_PINCONFIG_PULL_UP,
-};
-
-#define BCM2835_PINCONF_PACK(_param_, _arg_) ((_param_) << 16 | (_arg_))
-#define BCM2835_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16)
-#define BCM2835_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff)
-
-struct bcm2835_gpio_irqdata {
-       struct bcm2835_pinctrl *pc;
-       int bank;
-};
-
-struct bcm2835_pinctrl {
-       struct device *dev;
-       void __iomem *base;
-       int irq[BCM2835_NUM_BANKS];
-
-       /* note: locking assumes each bank will have its own unsigned long */
-       unsigned long enabled_irq_map[BCM2835_NUM_BANKS];
-       unsigned int irq_type[BCM2835_NUM_GPIOS];
-
-       struct pinctrl_dev *pctl_dev;
-       struct irq_domain *irq_domain;
-       struct gpio_chip gpio_chip;
-       struct pinctrl_gpio_range gpio_range;
-
-       struct bcm2835_gpio_irqdata irq_data[BCM2835_NUM_BANKS];
-       spinlock_t irq_lock[BCM2835_NUM_BANKS];
-};
-
-static struct lock_class_key gpio_lock_class;
-
-/* pins are just named GPIO0..GPIO53 */
-#define BCM2835_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
-static struct pinctrl_pin_desc bcm2835_gpio_pins[] = {
-       BCM2835_GPIO_PIN(0),
-       BCM2835_GPIO_PIN(1),
-       BCM2835_GPIO_PIN(2),
-       BCM2835_GPIO_PIN(3),
-       BCM2835_GPIO_PIN(4),
-       BCM2835_GPIO_PIN(5),
-       BCM2835_GPIO_PIN(6),
-       BCM2835_GPIO_PIN(7),
-       BCM2835_GPIO_PIN(8),
-       BCM2835_GPIO_PIN(9),
-       BCM2835_GPIO_PIN(10),
-       BCM2835_GPIO_PIN(11),
-       BCM2835_GPIO_PIN(12),
-       BCM2835_GPIO_PIN(13),
-       BCM2835_GPIO_PIN(14),
-       BCM2835_GPIO_PIN(15),
-       BCM2835_GPIO_PIN(16),
-       BCM2835_GPIO_PIN(17),
-       BCM2835_GPIO_PIN(18),
-       BCM2835_GPIO_PIN(19),
-       BCM2835_GPIO_PIN(20),
-       BCM2835_GPIO_PIN(21),
-       BCM2835_GPIO_PIN(22),
-       BCM2835_GPIO_PIN(23),
-       BCM2835_GPIO_PIN(24),
-       BCM2835_GPIO_PIN(25),
-       BCM2835_GPIO_PIN(26),
-       BCM2835_GPIO_PIN(27),
-       BCM2835_GPIO_PIN(28),
-       BCM2835_GPIO_PIN(29),
-       BCM2835_GPIO_PIN(30),
-       BCM2835_GPIO_PIN(31),
-       BCM2835_GPIO_PIN(32),
-       BCM2835_GPIO_PIN(33),
-       BCM2835_GPIO_PIN(34),
-       BCM2835_GPIO_PIN(35),
-       BCM2835_GPIO_PIN(36),
-       BCM2835_GPIO_PIN(37),
-       BCM2835_GPIO_PIN(38),
-       BCM2835_GPIO_PIN(39),
-       BCM2835_GPIO_PIN(40),
-       BCM2835_GPIO_PIN(41),
-       BCM2835_GPIO_PIN(42),
-       BCM2835_GPIO_PIN(43),
-       BCM2835_GPIO_PIN(44),
-       BCM2835_GPIO_PIN(45),
-       BCM2835_GPIO_PIN(46),
-       BCM2835_GPIO_PIN(47),
-       BCM2835_GPIO_PIN(48),
-       BCM2835_GPIO_PIN(49),
-       BCM2835_GPIO_PIN(50),
-       BCM2835_GPIO_PIN(51),
-       BCM2835_GPIO_PIN(52),
-       BCM2835_GPIO_PIN(53),
-};
-
-/* one pin per group */
-static const char * const bcm2835_gpio_groups[] = {
-       "gpio0",
-       "gpio1",
-       "gpio2",
-       "gpio3",
-       "gpio4",
-       "gpio5",
-       "gpio6",
-       "gpio7",
-       "gpio8",
-       "gpio9",
-       "gpio10",
-       "gpio11",
-       "gpio12",
-       "gpio13",
-       "gpio14",
-       "gpio15",
-       "gpio16",
-       "gpio17",
-       "gpio18",
-       "gpio19",
-       "gpio20",
-       "gpio21",
-       "gpio22",
-       "gpio23",
-       "gpio24",
-       "gpio25",
-       "gpio26",
-       "gpio27",
-       "gpio28",
-       "gpio29",
-       "gpio30",
-       "gpio31",
-       "gpio32",
-       "gpio33",
-       "gpio34",
-       "gpio35",
-       "gpio36",
-       "gpio37",
-       "gpio38",
-       "gpio39",
-       "gpio40",
-       "gpio41",
-       "gpio42",
-       "gpio43",
-       "gpio44",
-       "gpio45",
-       "gpio46",
-       "gpio47",
-       "gpio48",
-       "gpio49",
-       "gpio50",
-       "gpio51",
-       "gpio52",
-       "gpio53",
-};
-
-enum bcm2835_fsel {
-       BCM2835_FSEL_GPIO_IN = 0,
-       BCM2835_FSEL_GPIO_OUT = 1,
-       BCM2835_FSEL_ALT0 = 4,
-       BCM2835_FSEL_ALT1 = 5,
-       BCM2835_FSEL_ALT2 = 6,
-       BCM2835_FSEL_ALT3 = 7,
-       BCM2835_FSEL_ALT4 = 3,
-       BCM2835_FSEL_ALT5 = 2,
-       BCM2835_FSEL_COUNT = 8,
-       BCM2835_FSEL_MASK = 0x7,
-};
-
-static const char * const bcm2835_functions[BCM2835_FSEL_COUNT] = {
-       [BCM2835_FSEL_GPIO_IN] = "gpio_in",
-       [BCM2835_FSEL_GPIO_OUT] = "gpio_out",
-       [BCM2835_FSEL_ALT0] = "alt0",
-       [BCM2835_FSEL_ALT1] = "alt1",
-       [BCM2835_FSEL_ALT2] = "alt2",
-       [BCM2835_FSEL_ALT3] = "alt3",
-       [BCM2835_FSEL_ALT4] = "alt4",
-       [BCM2835_FSEL_ALT5] = "alt5",
-};
-
-static const char * const irq_type_names[] = {
-       [IRQ_TYPE_NONE] = "none",
-       [IRQ_TYPE_EDGE_RISING] = "edge-rising",
-       [IRQ_TYPE_EDGE_FALLING] = "edge-falling",
-       [IRQ_TYPE_EDGE_BOTH] = "edge-both",
-       [IRQ_TYPE_LEVEL_HIGH] = "level-high",
-       [IRQ_TYPE_LEVEL_LOW] = "level-low",
-};
-
-static inline u32 bcm2835_gpio_rd(struct bcm2835_pinctrl *pc, unsigned reg)
-{
-       return readl(pc->base + reg);
-}
-
-static inline void bcm2835_gpio_wr(struct bcm2835_pinctrl *pc, unsigned reg,
-               u32 val)
-{
-       writel(val, pc->base + reg);
-}
-
-static inline int bcm2835_gpio_get_bit(struct bcm2835_pinctrl *pc, unsigned reg,
-               unsigned bit)
-{
-       reg += GPIO_REG_OFFSET(bit) * 4;
-       return (bcm2835_gpio_rd(pc, reg) >> GPIO_REG_SHIFT(bit)) & 1;
-}
-
-/* note NOT a read/modify/write cycle */
-static inline void bcm2835_gpio_set_bit(struct bcm2835_pinctrl *pc,
-               unsigned reg, unsigned bit)
-{
-       reg += GPIO_REG_OFFSET(bit) * 4;
-       bcm2835_gpio_wr(pc, reg, BIT(GPIO_REG_SHIFT(bit)));
-}
-
-static inline enum bcm2835_fsel bcm2835_pinctrl_fsel_get(
-               struct bcm2835_pinctrl *pc, unsigned pin)
-{
-       u32 val = bcm2835_gpio_rd(pc, FSEL_REG(pin));
-       enum bcm2835_fsel status = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK;
-
-       dev_dbg(pc->dev, "get %08x (%u => %s)\n", val, pin,
-                       bcm2835_functions[status]);
-
-       return status;
-}
-
-static inline void bcm2835_pinctrl_fsel_set(
-               struct bcm2835_pinctrl *pc, unsigned pin,
-               enum bcm2835_fsel fsel)
-{
-       u32 val = bcm2835_gpio_rd(pc, FSEL_REG(pin));
-       enum bcm2835_fsel cur = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK;
-
-       dev_dbg(pc->dev, "read %08x (%u => %s)\n", val, pin,
-                       bcm2835_functions[cur]);
-
-       if (cur == fsel)
-               return;
-
-       if (cur != BCM2835_FSEL_GPIO_IN && fsel != BCM2835_FSEL_GPIO_IN) {
-               /* always transition through GPIO_IN */
-               val &= ~(BCM2835_FSEL_MASK << FSEL_SHIFT(pin));
-               val |= BCM2835_FSEL_GPIO_IN << FSEL_SHIFT(pin);
-
-               dev_dbg(pc->dev, "trans %08x (%u <= %s)\n", val, pin,
-                               bcm2835_functions[BCM2835_FSEL_GPIO_IN]);
-               bcm2835_gpio_wr(pc, FSEL_REG(pin), val);
-       }
-
-       val &= ~(BCM2835_FSEL_MASK << FSEL_SHIFT(pin));
-       val |= fsel << FSEL_SHIFT(pin);
-
-       dev_dbg(pc->dev, "write %08x (%u <= %s)\n", val, pin,
-                       bcm2835_functions[fsel]);
-       bcm2835_gpio_wr(pc, FSEL_REG(pin), val);
-}
-
-static int bcm2835_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-       return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void bcm2835_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-       pinctrl_free_gpio(chip->base + offset);
-}
-
-static int bcm2835_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       return pinctrl_gpio_direction_input(chip->base + offset);
-}
-
-static int bcm2835_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev);
-
-       return bcm2835_gpio_get_bit(pc, GPLEV0, offset);
-}
-
-static int bcm2835_gpio_direction_output(struct gpio_chip *chip,
-               unsigned offset, int value)
-{
-       return pinctrl_gpio_direction_output(chip->base + offset);
-}
-
-static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev);
-
-       bcm2835_gpio_set_bit(pc, value ? GPSET0 : GPCLR0, offset);
-}
-
-static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev);
-
-       return irq_linear_revmap(pc->irq_domain, offset);
-}
-
-static struct gpio_chip bcm2835_gpio_chip = {
-       .label = MODULE_NAME,
-       .owner = THIS_MODULE,
-       .request = bcm2835_gpio_request,
-       .free = bcm2835_gpio_free,
-       .direction_input = bcm2835_gpio_direction_input,
-       .direction_output = bcm2835_gpio_direction_output,
-       .get = bcm2835_gpio_get,
-       .set = bcm2835_gpio_set,
-       .to_irq = bcm2835_gpio_to_irq,
-       .base = -1,
-       .ngpio = BCM2835_NUM_GPIOS,
-       .can_sleep = false,
-};
-
-static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id)
-{
-       struct bcm2835_gpio_irqdata *irqdata = dev_id;
-       struct bcm2835_pinctrl *pc = irqdata->pc;
-       int bank = irqdata->bank;
-       unsigned long events;
-       unsigned offset;
-       unsigned gpio;
-       unsigned int type;
-
-       events = bcm2835_gpio_rd(pc, GPEDS0 + bank * 4);
-       events &= pc->enabled_irq_map[bank];
-       for_each_set_bit(offset, &events, 32) {
-               gpio = (32 * bank) + offset;
-               type = pc->irq_type[gpio];
-
-               /* ack edge triggered IRQs immediately */
-               if (!(type & IRQ_TYPE_LEVEL_MASK))
-                       bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
-
-               generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio));
-
-               /* ack level triggered IRQ after handling them */
-               if (type & IRQ_TYPE_LEVEL_MASK)
-                       bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
-       }
-       return events ? IRQ_HANDLED : IRQ_NONE;
-}
-
-static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
-       unsigned reg, unsigned offset, bool enable)
-{
-       u32 value;
-       reg += GPIO_REG_OFFSET(offset) * 4;
-       value = bcm2835_gpio_rd(pc, reg);
-       if (enable)
-               value |= BIT(GPIO_REG_SHIFT(offset));
-       else
-               value &= ~(BIT(GPIO_REG_SHIFT(offset)));
-       bcm2835_gpio_wr(pc, reg, value);
-}
-
-/* fast path for IRQ handler */
-static void bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
-       unsigned offset, bool enable)
-{
-       switch (pc->irq_type[offset]) {
-       case IRQ_TYPE_EDGE_RISING:
-               __bcm2835_gpio_irq_config(pc, GPREN0, offset, enable);
-               break;
-
-       case IRQ_TYPE_EDGE_FALLING:
-               __bcm2835_gpio_irq_config(pc, GPFEN0, offset, enable);
-               break;
-
-       case IRQ_TYPE_EDGE_BOTH:
-               __bcm2835_gpio_irq_config(pc, GPREN0, offset, enable);
-               __bcm2835_gpio_irq_config(pc, GPFEN0, offset, enable);
-               break;
-
-       case IRQ_TYPE_LEVEL_HIGH:
-               __bcm2835_gpio_irq_config(pc, GPHEN0, offset, enable);
-               break;
-
-       case IRQ_TYPE_LEVEL_LOW:
-               __bcm2835_gpio_irq_config(pc, GPLEN0, offset, enable);
-               break;
-       }
-}
-
-static void bcm2835_gpio_irq_enable(struct irq_data *data)
-{
-       struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
-       unsigned gpio = irqd_to_hwirq(data);
-       unsigned offset = GPIO_REG_SHIFT(gpio);
-       unsigned bank = GPIO_REG_OFFSET(gpio);
-       unsigned long flags;
-
-       spin_lock_irqsave(&pc->irq_lock[bank], flags);
-       set_bit(offset, &pc->enabled_irq_map[bank]);
-       bcm2835_gpio_irq_config(pc, gpio, true);
-       spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
-}
-
-static void bcm2835_gpio_irq_disable(struct irq_data *data)
-{
-       struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
-       unsigned gpio = irqd_to_hwirq(data);
-       unsigned offset = GPIO_REG_SHIFT(gpio);
-       unsigned bank = GPIO_REG_OFFSET(gpio);
-       unsigned long flags;
-
-       spin_lock_irqsave(&pc->irq_lock[bank], flags);
-       bcm2835_gpio_irq_config(pc, gpio, false);
-       clear_bit(offset, &pc->enabled_irq_map[bank]);
-       spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
-}
-
-static int __bcm2835_gpio_irq_set_type_disabled(struct bcm2835_pinctrl *pc,
-       unsigned offset, unsigned int type)
-{
-       switch (type) {
-       case IRQ_TYPE_NONE:
-       case IRQ_TYPE_EDGE_RISING:
-       case IRQ_TYPE_EDGE_FALLING:
-       case IRQ_TYPE_EDGE_BOTH:
-       case IRQ_TYPE_LEVEL_HIGH:
-       case IRQ_TYPE_LEVEL_LOW:
-               pc->irq_type[offset] = type;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-/* slower path for reconfiguring IRQ type */
-static int __bcm2835_gpio_irq_set_type_enabled(struct bcm2835_pinctrl *pc,
-       unsigned offset, unsigned int type)
-{
-       switch (type) {
-       case IRQ_TYPE_NONE:
-               if (pc->irq_type[offset] != type) {
-                       bcm2835_gpio_irq_config(pc, offset, false);
-                       pc->irq_type[offset] = type;
-               }
-               break;
-
-       case IRQ_TYPE_EDGE_RISING:
-               if (pc->irq_type[offset] == IRQ_TYPE_EDGE_BOTH) {
-                       /* RISING already enabled, disable FALLING */
-                       pc->irq_type[offset] = IRQ_TYPE_EDGE_FALLING;
-                       bcm2835_gpio_irq_config(pc, offset, false);
-                       pc->irq_type[offset] = type;
-               } else if (pc->irq_type[offset] != type) {
-                       bcm2835_gpio_irq_config(pc, offset, false);
-                       pc->irq_type[offset] = type;
-                       bcm2835_gpio_irq_config(pc, offset, true);
-               }
-               break;
-
-       case IRQ_TYPE_EDGE_FALLING:
-               if (pc->irq_type[offset] == IRQ_TYPE_EDGE_BOTH) {
-                       /* FALLING already enabled, disable RISING */
-                       pc->irq_type[offset] = IRQ_TYPE_EDGE_RISING;
-                       bcm2835_gpio_irq_config(pc, offset, false);
-                       pc->irq_type[offset] = type;
-               } else if (pc->irq_type[offset] != type) {
-                       bcm2835_gpio_irq_config(pc, offset, false);
-                       pc->irq_type[offset] = type;
-                       bcm2835_gpio_irq_config(pc, offset, true);
-               }
-               break;
-
-       case IRQ_TYPE_EDGE_BOTH:
-               if (pc->irq_type[offset] == IRQ_TYPE_EDGE_RISING) {
-                       /* RISING already enabled, enable FALLING too */
-                       pc->irq_type[offset] = IRQ_TYPE_EDGE_FALLING;
-                       bcm2835_gpio_irq_config(pc, offset, true);
-                       pc->irq_type[offset] = type;
-               } else if (pc->irq_type[offset] == IRQ_TYPE_EDGE_FALLING) {
-                       /* FALLING already enabled, enable RISING too */
-                       pc->irq_type[offset] = IRQ_TYPE_EDGE_RISING;
-                       bcm2835_gpio_irq_config(pc, offset, true);
-                       pc->irq_type[offset] = type;
-               } else if (pc->irq_type[offset] != type) {
-                       bcm2835_gpio_irq_config(pc, offset, false);
-                       pc->irq_type[offset] = type;
-                       bcm2835_gpio_irq_config(pc, offset, true);
-               }
-               break;
-
-       case IRQ_TYPE_LEVEL_HIGH:
-       case IRQ_TYPE_LEVEL_LOW:
-               if (pc->irq_type[offset] != type) {
-                       bcm2835_gpio_irq_config(pc, offset, false);
-                       pc->irq_type[offset] = type;
-                       bcm2835_gpio_irq_config(pc, offset, true);
-               }
-               break;
-
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
-{
-       struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
-       unsigned gpio = irqd_to_hwirq(data);
-       unsigned offset = GPIO_REG_SHIFT(gpio);
-       unsigned bank = GPIO_REG_OFFSET(gpio);
-       unsigned long flags;
-       int ret;
-
-       spin_lock_irqsave(&pc->irq_lock[bank], flags);
-
-       if (test_bit(offset, &pc->enabled_irq_map[bank]))
-               ret = __bcm2835_gpio_irq_set_type_enabled(pc, gpio, type);
-       else
-               ret = __bcm2835_gpio_irq_set_type_disabled(pc, gpio, type);
-
-       spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
-
-       return ret;
-}
-
-static struct irq_chip bcm2835_gpio_irq_chip = {
-       .name = MODULE_NAME,
-       .irq_enable = bcm2835_gpio_irq_enable,
-       .irq_disable = bcm2835_gpio_irq_disable,
-       .irq_set_type = bcm2835_gpio_irq_set_type,
-};
-
-static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev)
-{
-       return ARRAY_SIZE(bcm2835_gpio_groups);
-}
-
-static const char *bcm2835_pctl_get_group_name(struct pinctrl_dev *pctldev,
-               unsigned selector)
-{
-       return bcm2835_gpio_groups[selector];
-}
-
-static int bcm2835_pctl_get_group_pins(struct pinctrl_dev *pctldev,
-               unsigned selector,
-               const unsigned **pins,
-               unsigned *num_pins)
-{
-       *pins = &bcm2835_gpio_pins[selector].number;
-       *num_pins = 1;
-
-       return 0;
-}
-
-static void bcm2835_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
-               struct seq_file *s,
-               unsigned offset)
-{
-       struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
-       enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset);
-       const char *fname = bcm2835_functions[fsel];
-       int value = bcm2835_gpio_get_bit(pc, GPLEV0, offset);
-       int irq = irq_find_mapping(pc->irq_domain, offset);
-
-       seq_printf(s, "function %s in %s; irq %d (%s)",
-               fname, value ? "hi" : "lo",
-               irq, irq_type_names[pc->irq_type[offset]]);
-}
-
-static void bcm2835_pctl_dt_free_map(struct pinctrl_dev *pctldev,
-               struct pinctrl_map *maps, unsigned num_maps)
-{
-       int i;
-
-       for (i = 0; i < num_maps; i++)
-               if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
-                       kfree(maps[i].data.configs.configs);
-
-       kfree(maps);
-}
-
-static int bcm2835_pctl_dt_node_to_map_func(struct bcm2835_pinctrl *pc,
-               struct device_node *np, u32 pin, u32 fnum,
-               struct pinctrl_map **maps)
-{
-       struct pinctrl_map *map = *maps;
-
-       if (fnum >= ARRAY_SIZE(bcm2835_functions)) {
-               dev_err(pc->dev, "%s: invalid brcm,function %d\n",
-                       of_node_full_name(np), fnum);
-               return -EINVAL;
-       }
-
-       map->type = PIN_MAP_TYPE_MUX_GROUP;
-       map->data.mux.group = bcm2835_gpio_groups[pin];
-       map->data.mux.function = bcm2835_functions[fnum];
-       (*maps)++;
-
-       return 0;
-}
-
-static int bcm2835_pctl_dt_node_to_map_pull(struct bcm2835_pinctrl *pc,
-               struct device_node *np, u32 pin, u32 pull,
-               struct pinctrl_map **maps)
-{
-       struct pinctrl_map *map = *maps;
-       unsigned long *configs;
-
-       if (pull > 2) {
-               dev_err(pc->dev, "%s: invalid brcm,pull %d\n",
-                       of_node_full_name(np), pull);
-               return -EINVAL;
-       }
-
-       configs = kzalloc(sizeof(*configs), GFP_KERNEL);
-       if (!configs)
-               return -ENOMEM;
-       configs[0] = BCM2835_PINCONF_PACK(BCM2835_PINCONF_PARAM_PULL, pull);
-
-       map->type = PIN_MAP_TYPE_CONFIGS_PIN;
-       map->data.configs.group_or_pin = bcm2835_gpio_pins[pin].name;
-       map->data.configs.configs = configs;
-       map->data.configs.num_configs = 1;
-       (*maps)++;
-
-       return 0;
-}
-
-static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
-               struct device_node *np,
-               struct pinctrl_map **map, unsigned *num_maps)
-{
-       struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
-       struct property *pins, *funcs, *pulls;
-       int num_pins, num_funcs, num_pulls, maps_per_pin;
-       struct pinctrl_map *maps, *cur_map;
-       int i, err;
-       u32 pin, func, pull;
-
-       pins = of_find_property(np, "brcm,pins", NULL);
-       if (!pins) {
-               dev_err(pc->dev, "%s: missing brcm,pins property\n",
-                               of_node_full_name(np));
-               return -EINVAL;
-       }
-
-       funcs = of_find_property(np, "brcm,function", NULL);
-       pulls = of_find_property(np, "brcm,pull", NULL);
-
-       if (!funcs && !pulls) {
-               dev_err(pc->dev,
-                       "%s: neither brcm,function nor brcm,pull specified\n",
-                       of_node_full_name(np));
-               return -EINVAL;
-       }
-
-       num_pins = pins->length / 4;
-       num_funcs = funcs ? (funcs->length / 4) : 0;
-       num_pulls = pulls ? (pulls->length / 4) : 0;
-
-       if (num_funcs > 1 && num_funcs != num_pins) {
-               dev_err(pc->dev,
-                       "%s: brcm,function must have 1 or %d entries\n",
-                       of_node_full_name(np), num_pins);
-               return -EINVAL;
-       }
-
-       if (num_pulls > 1 && num_pulls != num_pins) {
-               dev_err(pc->dev,
-                       "%s: brcm,pull must have 1 or %d entries\n",
-                       of_node_full_name(np), num_pins);
-               return -EINVAL;
-       }
-
-       maps_per_pin = 0;
-       if (num_funcs)
-               maps_per_pin++;
-       if (num_pulls)
-               maps_per_pin++;
-       cur_map = maps = kzalloc(num_pins * maps_per_pin * sizeof(*maps),
-                               GFP_KERNEL);
-       if (!maps)
-               return -ENOMEM;
-
-       for (i = 0; i < num_pins; i++) {
-               err = of_property_read_u32_index(np, "brcm,pins", i, &pin);
-               if (err)
-                       goto out;
-               if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) {
-                       dev_err(pc->dev, "%s: invalid brcm,pins value %d\n",
-                               of_node_full_name(np), pin);
-                       err = -EINVAL;
-                       goto out;
-               }
-
-               if (num_funcs) {
-                       err = of_property_read_u32_index(np, "brcm,function",
-                                       (num_funcs > 1) ? i : 0, &func);
-                       if (err)
-                               goto out;
-                       err = bcm2835_pctl_dt_node_to_map_func(pc, np, pin,
-                                                       func, &cur_map);
-                       if (err)
-                               goto out;
-               }
-               if (num_pulls) {
-                       err = of_property_read_u32_index(np, "brcm,pull",
-                                       (num_funcs > 1) ? i : 0, &pull);
-                       if (err)
-                               goto out;
-                       err = bcm2835_pctl_dt_node_to_map_pull(pc, np, pin,
-                                                       pull, &cur_map);
-                       if (err)
-                               goto out;
-               }
-       }
-
-       *map = maps;
-       *num_maps = num_pins * maps_per_pin;
-
-       return 0;
-
-out:
-       kfree(maps);
-       return err;
-}
-
-static const struct pinctrl_ops bcm2835_pctl_ops = {
-       .get_groups_count = bcm2835_pctl_get_groups_count,
-       .get_group_name = bcm2835_pctl_get_group_name,
-       .get_group_pins = bcm2835_pctl_get_group_pins,
-       .pin_dbg_show = bcm2835_pctl_pin_dbg_show,
-       .dt_node_to_map = bcm2835_pctl_dt_node_to_map,
-       .dt_free_map = bcm2835_pctl_dt_free_map,
-};
-
-static int bcm2835_pmx_get_functions_count(struct pinctrl_dev *pctldev)
-{
-       return BCM2835_FSEL_COUNT;
-}
-
-static const char *bcm2835_pmx_get_function_name(struct pinctrl_dev *pctldev,
-               unsigned selector)
-{
-       return bcm2835_functions[selector];
-}
-
-static int bcm2835_pmx_get_function_groups(struct pinctrl_dev *pctldev,
-               unsigned selector,
-               const char * const **groups,
-               unsigned * const num_groups)
-{
-       /* every pin can do every function */
-       *groups = bcm2835_gpio_groups;
-       *num_groups = ARRAY_SIZE(bcm2835_gpio_groups);
-
-       return 0;
-}
-
-static int bcm2835_pmx_set(struct pinctrl_dev *pctldev,
-               unsigned func_selector,
-               unsigned group_selector)
-{
-       struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
-
-       bcm2835_pinctrl_fsel_set(pc, group_selector, func_selector);
-
-       return 0;
-}
-
-static void bcm2835_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
-               struct pinctrl_gpio_range *range,
-               unsigned offset)
-{
-       struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
-
-       /* disable by setting to GPIO_IN */
-       bcm2835_pinctrl_fsel_set(pc, offset, BCM2835_FSEL_GPIO_IN);
-}
-
-static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
-               struct pinctrl_gpio_range *range,
-               unsigned offset,
-               bool input)
-{
-       struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
-       enum bcm2835_fsel fsel = input ?
-               BCM2835_FSEL_GPIO_IN : BCM2835_FSEL_GPIO_OUT;
-
-       bcm2835_pinctrl_fsel_set(pc, offset, fsel);
-
-       return 0;
-}
-
-static const struct pinmux_ops bcm2835_pmx_ops = {
-       .get_functions_count = bcm2835_pmx_get_functions_count,
-       .get_function_name = bcm2835_pmx_get_function_name,
-       .get_function_groups = bcm2835_pmx_get_function_groups,
-       .set_mux = bcm2835_pmx_set,
-       .gpio_disable_free = bcm2835_pmx_gpio_disable_free,
-       .gpio_set_direction = bcm2835_pmx_gpio_set_direction,
-};
-
-static int bcm2835_pinconf_get(struct pinctrl_dev *pctldev,
-                       unsigned pin, unsigned long *config)
-{
-       /* No way to read back config in HW */
-       return -ENOTSUPP;
-}
-
-static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
-                       unsigned pin, unsigned long *configs,
-                       unsigned num_configs)
-{
-       struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
-       enum bcm2835_pinconf_param param;
-       u16 arg;
-       u32 off, bit;
-       int i;
-
-       for (i = 0; i < num_configs; i++) {
-               param = BCM2835_PINCONF_UNPACK_PARAM(configs[i]);
-               arg = BCM2835_PINCONF_UNPACK_ARG(configs[i]);
-
-               if (param != BCM2835_PINCONF_PARAM_PULL)
-                       return -EINVAL;
-
-               off = GPIO_REG_OFFSET(pin);
-               bit = GPIO_REG_SHIFT(pin);
-
-               bcm2835_gpio_wr(pc, GPPUD, arg & 3);
-               /*
-                * Docs say to wait 150 cycles, but not of what. We assume a
-                * 1 MHz clock here, which is pretty slow...
-                */
-               udelay(150);
-               bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
-               udelay(150);
-               bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
-       } /* for each config */
-
-       return 0;
-}
-
-static const struct pinconf_ops bcm2835_pinconf_ops = {
-       .pin_config_get = bcm2835_pinconf_get,
-       .pin_config_set = bcm2835_pinconf_set,
-};
-
-static struct pinctrl_desc bcm2835_pinctrl_desc = {
-       .name = MODULE_NAME,
-       .pins = bcm2835_gpio_pins,
-       .npins = ARRAY_SIZE(bcm2835_gpio_pins),
-       .pctlops = &bcm2835_pctl_ops,
-       .pmxops = &bcm2835_pmx_ops,
-       .confops = &bcm2835_pinconf_ops,
-       .owner = THIS_MODULE,
-};
-
-static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = {
-       .name = MODULE_NAME,
-       .npins = BCM2835_NUM_GPIOS,
-};
-
-static int bcm2835_pinctrl_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       struct bcm2835_pinctrl *pc;
-       struct resource iomem;
-       int err, i;
-       BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2835_NUM_GPIOS);
-       BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2835_NUM_GPIOS);
-
-       pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
-       if (!pc)
-               return -ENOMEM;
-
-       platform_set_drvdata(pdev, pc);
-       pc->dev = dev;
-
-       err = of_address_to_resource(np, 0, &iomem);
-       if (err) {
-               dev_err(dev, "could not get IO memory\n");
-               return err;
-       }
-
-       pc->base = devm_ioremap_resource(dev, &iomem);
-       if (IS_ERR(pc->base))
-               return PTR_ERR(pc->base);
-
-       pc->gpio_chip = bcm2835_gpio_chip;
-       pc->gpio_chip.dev = dev;
-       pc->gpio_chip.of_node = np;
-
-       pc->irq_domain = irq_domain_add_linear(np, BCM2835_NUM_GPIOS,
-                       &irq_domain_simple_ops, NULL);
-       if (!pc->irq_domain) {
-               dev_err(dev, "could not create IRQ domain\n");
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < BCM2835_NUM_GPIOS; i++) {
-               int irq = irq_create_mapping(pc->irq_domain, i);
-               irq_set_lockdep_class(irq, &gpio_lock_class);
-               irq_set_chip_and_handler(irq, &bcm2835_gpio_irq_chip,
-                               handle_simple_irq);
-               irq_set_chip_data(irq, pc);
-               set_irq_flags(irq, IRQF_VALID);
-       }
-
-       for (i = 0; i < BCM2835_NUM_BANKS; i++) {
-               unsigned long events;
-               unsigned offset;
-               int len;
-               char *name;
-
-               /* clear event detection flags */
-               bcm2835_gpio_wr(pc, GPREN0 + i * 4, 0);
-               bcm2835_gpio_wr(pc, GPFEN0 + i * 4, 0);
-               bcm2835_gpio_wr(pc, GPHEN0 + i * 4, 0);
-               bcm2835_gpio_wr(pc, GPLEN0 + i * 4, 0);
-               bcm2835_gpio_wr(pc, GPAREN0 + i * 4, 0);
-               bcm2835_gpio_wr(pc, GPAFEN0 + i * 4, 0);
-
-               /* clear all the events */
-               events = bcm2835_gpio_rd(pc, GPEDS0 + i * 4);
-               for_each_set_bit(offset, &events, 32)
-                       bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset));
-
-               pc->irq[i] = irq_of_parse_and_map(np, i);
-               pc->irq_data[i].pc = pc;
-               pc->irq_data[i].bank = i;
-               spin_lock_init(&pc->irq_lock[i]);
-
-               len = strlen(dev_name(pc->dev)) + 16;
-               name = devm_kzalloc(pc->dev, len, GFP_KERNEL);
-               if (!name)
-                       return -ENOMEM;
-               snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i);
-
-               err = devm_request_irq(dev, pc->irq[i],
-                       bcm2835_gpio_irq_handler, IRQF_SHARED,
-                       name, &pc->irq_data[i]);
-               if (err) {
-                       dev_err(dev, "unable to request IRQ %d\n", pc->irq[i]);
-                       return err;
-               }
-       }
-
-       err = gpiochip_add(&pc->gpio_chip);
-       if (err) {
-               dev_err(dev, "could not add GPIO chip\n");
-               return err;
-       }
-
-       pc->pctl_dev = pinctrl_register(&bcm2835_pinctrl_desc, dev, pc);
-       if (!pc->pctl_dev) {
-               gpiochip_remove(&pc->gpio_chip);
-               return -EINVAL;
-       }
-
-       pc->gpio_range = bcm2835_pinctrl_gpio_range;
-       pc->gpio_range.base = pc->gpio_chip.base;
-       pc->gpio_range.gc = &pc->gpio_chip;
-       pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
-
-       return 0;
-}
-
-static int bcm2835_pinctrl_remove(struct platform_device *pdev)
-{
-       struct bcm2835_pinctrl *pc = platform_get_drvdata(pdev);
-
-       pinctrl_unregister(pc->pctl_dev);
-       gpiochip_remove(&pc->gpio_chip);
-
-       return 0;
-}
-
-static struct of_device_id bcm2835_pinctrl_match[] = {
-       { .compatible = "brcm,bcm2835-gpio" },
-       {}
-};
-MODULE_DEVICE_TABLE(of, bcm2835_pinctrl_match);
-
-static struct platform_driver bcm2835_pinctrl_driver = {
-       .probe = bcm2835_pinctrl_probe,
-       .remove = bcm2835_pinctrl_remove,
-       .driver = {
-               .name = MODULE_NAME,
-               .of_match_table = bcm2835_pinctrl_match,
-       },
-};
-module_platform_driver(bcm2835_pinctrl_driver);
-
-MODULE_AUTHOR("Chris Boot, Simon Arlott, Stephen Warren");
-MODULE_DESCRIPTION("BCM2835 Pin control driver");
-MODULE_LICENSE("GPL");
index c7cfad5527d70ab04a5596bb841eab5f62321a48..eb89ba045228253d66e01b4a736c9e63a54bbf7c 100644 (file)
@@ -193,4 +193,4 @@ enum ltq_pin {
 extern int ltq_pinctrl_register(struct platform_device *pdev,
                                   struct ltq_pinmux_info *info);
 extern int ltq_pinctrl_unregister(struct platform_device *pdev);
-#endif /* __PINCTRL_PXA3XX_H */
+#endif /* __PINCTRL_LANTIQ_H */
index 26461e30f0aebf6bd3fff75f9c29dd61143985ef..2631df0504bd62a9edd519ad6824f8c4f7e6a879 100644 (file)
@@ -987,7 +987,7 @@ static struct palmas_pinctrl_data tps80036_pinctrl_data = {
        .num_pin_groups = ARRAY_SIZE(tps80036_pingroups),
 };
 
-static struct of_device_id palmas_pinctrl_of_match[] = {
+static const struct of_device_id palmas_pinctrl_of_match[] = {
        { .compatible = "ti,palmas-pinctrl", .data = &tps65913_pinctrl_data},
        { .compatible = "ti,tps65913-pinctrl", .data = &tps65913_pinctrl_data},
        { .compatible = "ti,tps80036-pinctrl", .data = &tps80036_pinctrl_data},
index 69e84427f9134ad3c0d5bdbe1299dd1379b44e7e..13b45f29772788514e62dca7b74cad5d0063e856 100644 (file)
@@ -1501,7 +1501,7 @@ static void pcs_free_resources(struct pcs_device *pcs)
                }                                                       \
        } while (0);
 
-static struct of_device_id pcs_of_match[];
+static const struct of_device_id pcs_of_match[];
 
 static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
 {
@@ -2000,7 +2000,7 @@ static const struct pcs_soc_data pinconf_single = {
        .flags = PCS_FEAT_PINCONF,
 };
 
-static struct of_device_id pcs_of_match[] = {
+static const struct of_device_id pcs_of_match[] = {
        { .compatible = "ti,omap3-padconf", .data = &pinctrl_single_omap_wkup },
        { .compatible = "ti,omap4-padconf", .data = &pinctrl_single_omap_wkup },
        { .compatible = "ti,omap5-padconf", .data = &pinctrl_single_omap_wkup },
index 9e5ec00084bb1dcc2aad395af7c37d2bf0e3044a..65bf73b70e3406c72db02f796840fa6296bbdcb9 100644 (file)
 #define gpio_chip_to_bank(chip) \
                container_of(chip, struct st_gpio_bank, gpio_chip)
 
+#define pc_to_bank(pc) \
+               container_of(pc, struct st_gpio_bank, pc)
 
 enum st_retime_style {
        st_retime_style_none,
@@ -398,6 +400,16 @@ static const struct st_pctl_data stih407_flashdata = {
        .rt = 100,
 };
 
+static struct st_pio_control *st_get_pio_control(
+                       struct pinctrl_dev *pctldev, int pin)
+{
+       struct pinctrl_gpio_range *range =
+                        pinctrl_find_gpio_range_from_pin(pctldev, pin);
+       struct st_gpio_bank *bank = gpio_range_to_bank(range);
+
+       return &bank->pc;
+}
+
 /* Low level functions.. */
 static inline int st_gpio_bank(int gpio)
 {
@@ -460,6 +472,20 @@ static void st_pctl_set_function(struct st_pio_control *pc,
        regmap_field_write(alt, val);
 }
 
+static unsigned int st_pctl_get_pin_function(struct st_pio_control *pc, int pin)
+{
+       struct regmap_field *alt = pc->alt;
+       unsigned int val;
+       int offset = pin * 4;
+
+       if (!alt)
+               return 0;
+
+       regmap_field_read(alt, &val);
+
+       return (val >> offset) & 0xf;
+}
+
 static unsigned long st_pinconf_delay_to_bit(unsigned int delay,
        const struct st_pctl_data *data, unsigned long config)
 {
@@ -757,6 +783,35 @@ static int st_gpio_direction_output(struct gpio_chip *chip,
        return 0;
 }
 
+static int st_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+       struct st_gpio_bank *bank = gpio_chip_to_bank(chip);
+       struct st_pio_control pc = bank->pc;
+       unsigned long config;
+       unsigned int direction = 0;
+       unsigned int function;
+       unsigned int value;
+       int i = 0;
+
+       /* Alternate function direction is handled by Pinctrl */
+       function = st_pctl_get_pin_function(&pc, offset);
+       if (function) {
+               st_pinconf_get_direction(&pc, offset, &config);
+               return !ST_PINCONF_UNPACK_OE(config);
+       }
+
+       /*
+        * GPIO direction is handled differently
+        * - See st_gpio_direction() above for an explanation
+        */
+       for (i = 0; i <= 2; i++) {
+               value = readl(bank->base + REG_PIO_PC(i));
+               direction |= ((value >> offset) & 0x1) << i;
+       }
+
+       return (direction == ST_GPIO_DIRECTION_IN);
+}
+
 static int st_gpio_xlate(struct gpio_chip *gc,
                        const struct of_phandle_args *gpiospec, u32 *flags)
 {
@@ -904,16 +959,6 @@ static int st_pmx_get_groups(struct pinctrl_dev *pctldev,
        return 0;
 }
 
-static struct st_pio_control *st_get_pio_control(
-                       struct pinctrl_dev *pctldev, int pin)
-{
-       struct pinctrl_gpio_range *range =
-                        pinctrl_find_gpio_range_from_pin(pctldev, pin);
-       struct st_gpio_bank *bank = gpio_range_to_bank(range);
-
-       return &bank->pc;
-}
-
 static int st_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
                        unsigned group)
 {
@@ -1011,17 +1056,30 @@ static int st_pinconf_get(struct pinctrl_dev *pctldev,
 static void st_pinconf_dbg_show(struct pinctrl_dev *pctldev,
                                   struct seq_file *s, unsigned pin_id)
 {
+       struct st_pio_control *pc;
        unsigned long config;
+       unsigned int function;
+       int offset = st_gpio_pin(pin_id);
+       char f[16];
 
        mutex_unlock(&pctldev->mutex);
+       pc = st_get_pio_control(pctldev, pin_id);
        st_pinconf_get(pctldev, pin_id, &config);
        mutex_lock(&pctldev->mutex);
-       seq_printf(s, "[OE:%ld,PU:%ld,OD:%ld]\n"
+
+       function = st_pctl_get_pin_function(pc, offset);
+       if (function)
+               snprintf(f, 10, "Alt Fn %d", function);
+       else
+               snprintf(f, 5, "GPIO");
+
+       seq_printf(s, "[OE:%d,PU:%ld,OD:%ld]\t%s\n"
                "\t\t[retime:%ld,invclk:%ld,clknotdat:%ld,"
                "de:%ld,rt-clk:%ld,rt-delay:%ld]",
-               ST_PINCONF_UNPACK_OE(config),
+               !st_gpio_get_direction(&pc_to_bank(pc)->gpio_chip, offset),
                ST_PINCONF_UNPACK_PU(config),
                ST_PINCONF_UNPACK_OD(config),
+               f,
                ST_PINCONF_UNPACK_RT(config),
                ST_PINCONF_UNPACK_RT_INVERTCLK(config),
                ST_PINCONF_UNPACK_RT_CLKNOTDATA(config),
@@ -1438,6 +1496,7 @@ static struct gpio_chip st_gpio_template = {
        .set                    = st_gpio_set,
        .direction_input        = st_gpio_direction_input,
        .direction_output       = st_gpio_direction_output,
+       .get_direction          = st_gpio_get_direction,
        .ngpio                  = ST_GPIO_PINS_PER_BANK,
        .of_gpio_n_cells        = 1,
        .of_xlate               = st_gpio_xlate,
@@ -1531,7 +1590,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
        return 0;
 }
 
-static struct of_device_id st_pctl_of_match[] = {
+static const struct of_device_id st_pctl_of_match[] = {
        { .compatible = "st,stih415-sbc-pinctrl", .data = &stih415_sbc_data },
        { .compatible = "st,stih415-rear-pinctrl", .data = &stih415_rear_data },
        { .compatible = "st,stih415-left-pinctrl", .data = &stih415_left_data },
index e5949d51bc52c827930e82ebf65b99375d04409b..4c95c2024a1c24496d731a8ffc0fc056857228a0 100644 (file)
@@ -103,6 +103,7 @@ static const struct cfg_param {
        {"nvidia,lock",                 TEGRA_PINCONF_PARAM_LOCK},
        {"nvidia,io-reset",             TEGRA_PINCONF_PARAM_IORESET},
        {"nvidia,rcv-sel",              TEGRA_PINCONF_PARAM_RCV_SEL},
+       {"nvidia,io-hv",                TEGRA_PINCONF_PARAM_RCV_SEL},
        {"nvidia,high-speed-mode",      TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE},
        {"nvidia,schmitt",              TEGRA_PINCONF_PARAM_SCHMITT},
        {"nvidia,low-power-mode",       TEGRA_PINCONF_PARAM_LOW_POWER_MODE},
@@ -348,14 +349,24 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
                *width = 1;
                break;
        case TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE:
-               *bank = g->drv_bank;
-               *reg = g->drv_reg;
+               if (pmx->soc->hsm_in_mux) {
+                       *bank = g->mux_bank;
+                       *reg = g->mux_reg;
+               } else {
+                       *bank = g->drv_bank;
+                       *reg = g->drv_reg;
+               }
                *bit = g->hsm_bit;
                *width = 1;
                break;
        case TEGRA_PINCONF_PARAM_SCHMITT:
-               *bank = g->drv_bank;
-               *reg = g->drv_reg;
+               if (pmx->soc->schmitt_in_mux) {
+                       *bank = g->mux_bank;
+                       *reg = g->mux_reg;
+               } else {
+                       *bank = g->drv_bank;
+                       *reg = g->drv_reg;
+               }
                *bit = g->schmitt_bit;
                *width = 1;
                break;
@@ -390,8 +401,13 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
                *width = g->slwr_width;
                break;
        case TEGRA_PINCONF_PARAM_DRIVE_TYPE:
-               *bank = g->drv_bank;
-               *reg = g->drv_reg;
+               if (pmx->soc->drvtype_in_mux) {
+                       *bank = g->mux_bank;
+                       *reg = g->mux_reg;
+               } else {
+                       *bank = g->drv_bank;
+                       *reg = g->drv_reg;
+               }
                *bit = g->drvtype_bit;
                *width = 2;
                break;
index 8d94d1332e7b48a5f5d534a29829f7d0ce868048..1615db7e3a4bd065dcedc059b8041e0a0c782cbf 100644 (file)
@@ -139,26 +139,26 @@ struct tegra_pingroup {
        u32 pupd_bank:2;
        u32 tri_bank:2;
        u32 drv_bank:2;
-       u32 mux_bit:6;
-       u32 pupd_bit:6;
-       u32 tri_bit:6;
-       u32 einput_bit:6;
-       u32 odrain_bit:6;
-       u32 lock_bit:6;
-       u32 ioreset_bit:6;
-       u32 rcv_sel_bit:6;
-       u32 hsm_bit:6;
-       u32 schmitt_bit:6;
-       u32 lpmd_bit:6;
-       u32 drvdn_bit:6;
-       u32 drvup_bit:6;
-       u32 slwr_bit:6;
-       u32 slwf_bit:6;
-       u32 drvtype_bit:6;
-       u32 drvdn_width:6;
-       u32 drvup_width:6;
-       u32 slwr_width:6;
-       u32 slwf_width:6;
+       s32 mux_bit:6;
+       s32 pupd_bit:6;
+       s32 tri_bit:6;
+       s32 einput_bit:6;
+       s32 odrain_bit:6;
+       s32 lock_bit:6;
+       s32 ioreset_bit:6;
+       s32 rcv_sel_bit:6;
+       s32 hsm_bit:6;
+       s32 schmitt_bit:6;
+       s32 lpmd_bit:6;
+       s32 drvdn_bit:6;
+       s32 drvup_bit:6;
+       s32 slwr_bit:6;
+       s32 slwf_bit:6;
+       s32 drvtype_bit:6;
+       s32 drvdn_width:6;
+       s32 drvup_width:6;
+       s32 slwr_width:6;
+       s32 slwf_width:6;
 };
 
 /**
@@ -182,6 +182,9 @@ struct tegra_pinctrl_soc_data {
        unsigned nfunctions;
        const struct tegra_pingroup *groups;
        unsigned ngroups;
+       bool hsm_in_mux;
+       bool schmitt_in_mux;
+       bool drvtype_in_mux;
 };
 
 int tegra_pinctrl_probe(struct platform_device *pdev,
index 52e4ec6386b4189c6dda71c2cb48a167338308c6..05e49d5137ab358e7f5175bc97b9c0316762c55f 100644 (file)
@@ -1547,6 +1547,7 @@ static struct tegra_function tegra114_functions[] = {
 #define DRV_PINGROUP_REG_A             0x868   /* bank 0 */
 #define PINGROUP_REG_A                 0x3000  /* bank 1 */
 
+#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
 #define PINGROUP_REG(r)                        ((r) - PINGROUP_REG_A)
 
 #define PINGROUP_BIT_Y(b)              (b)
@@ -1572,20 +1573,17 @@ static struct tegra_function tegra114_functions[] = {
                .tri_reg = PINGROUP_REG(r),                             \
                .tri_bank = 1,                                          \
                .tri_bit = 4,                                           \
-               .einput_bit = PINGROUP_BIT_Y(5),                        \
+               .einput_bit = 5,                                        \
                .odrain_bit = PINGROUP_BIT_##od(6),                     \
-               .lock_bit = PINGROUP_BIT_Y(7),                          \
+               .lock_bit = 7,                                          \
                .ioreset_bit = PINGROUP_BIT_##ior(8),                   \
                .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9),               \
                .drv_reg = -1,                                          \
        }
 
-#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
-
-#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b,             \
-                    drvdn_b, drvdn_w, drvup_b, drvup_w,                \
-                    slwr_b, slwr_w, slwf_b, slwf_w,                    \
-                    drvtype)                                           \
+#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b,    \
+                    drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w,         \
+                    slwf_b, slwf_w, drvtype)                           \
        {                                                               \
                .name = "drive_" #pg_name,                              \
                .pins = drive_##pg_name##_pins,                         \
@@ -1843,6 +1841,9 @@ static const struct tegra_pinctrl_soc_data tegra114_pinctrl = {
        .nfunctions = ARRAY_SIZE(tegra114_functions),
        .groups = tegra114_groups,
        .ngroups = ARRAY_SIZE(tegra114_groups),
+       .hsm_in_mux = false,
+       .schmitt_in_mux = false,
+       .drvtype_in_mux = false,
 };
 
 static int tegra114_pinctrl_probe(struct platform_device *pdev)
index 2b20906c53561a3ee907f07ba2f47018bf0a4b4c..7cd44c7c296daa75ef2400542b14a83480b98303 100644 (file)
@@ -1536,6 +1536,7 @@ enum tegra_mux {
        TEGRA_MUX_CLK,
        TEGRA_MUX_CLK12,
        TEGRA_MUX_CPU,
+       TEGRA_MUX_CSI,
        TEGRA_MUX_DAP,
        TEGRA_MUX_DAP1,
        TEGRA_MUX_DAP2,
@@ -1544,6 +1545,7 @@ enum tegra_mux {
        TEGRA_MUX_DISPLAYA_ALT,
        TEGRA_MUX_DISPLAYB,
        TEGRA_MUX_DP,
+       TEGRA_MUX_DSI_B,
        TEGRA_MUX_DTV,
        TEGRA_MUX_EXTPERIPH1,
        TEGRA_MUX_EXTPERIPH2,
@@ -1613,8 +1615,6 @@ enum tegra_mux {
        TEGRA_MUX_VI_ALT3,
        TEGRA_MUX_VIMCLK2,
        TEGRA_MUX_VIMCLK2_ALT,
-       TEGRA_MUX_CSI,
-       TEGRA_MUX_DSI_B,
 };
 
 #define FUNCTION(fname)                                        \
@@ -1630,6 +1630,7 @@ static struct tegra_function tegra124_functions[] = {
        FUNCTION(clk),
        FUNCTION(clk12),
        FUNCTION(cpu),
+       FUNCTION(csi),
        FUNCTION(dap),
        FUNCTION(dap1),
        FUNCTION(dap2),
@@ -1638,6 +1639,7 @@ static struct tegra_function tegra124_functions[] = {
        FUNCTION(displaya_alt),
        FUNCTION(displayb),
        FUNCTION(dp),
+       FUNCTION(dsi_b),
        FUNCTION(dtv),
        FUNCTION(extperiph1),
        FUNCTION(extperiph2),
@@ -1707,15 +1709,15 @@ static struct tegra_function tegra124_functions[] = {
        FUNCTION(vi_alt3),
        FUNCTION(vimclk2),
        FUNCTION(vimclk2_alt),
-       FUNCTION(csi),
-       FUNCTION(dsi_b),
 };
 
 #define DRV_PINGROUP_REG_A             0x868   /* bank 0 */
 #define PINGROUP_REG_A                 0x3000  /* bank 1 */
 #define MIPI_PAD_CTRL_PINGROUP_REG_A   0x820   /* bank 2 */
 
+#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
 #define PINGROUP_REG(r)                        ((r) - PINGROUP_REG_A)
+#define MIPI_PAD_CTRL_PINGROUP_REG_Y(r)        ((r) - MIPI_PAD_CTRL_PINGROUP_REG_A)
 
 #define PINGROUP_BIT_Y(b)              (b)
 #define PINGROUP_BIT_N(b)              (-1)
@@ -1740,20 +1742,17 @@ static struct tegra_function tegra124_functions[] = {
                .tri_reg = PINGROUP_REG(r),                             \
                .tri_bank = 1,                                          \
                .tri_bit = 4,                                           \
-               .einput_bit = PINGROUP_BIT_Y(5),                        \
+               .einput_bit = 5,                                        \
                .odrain_bit = PINGROUP_BIT_##od(6),                     \
-               .lock_bit = PINGROUP_BIT_Y(7),                          \
+               .lock_bit = 7,                                          \
                .ioreset_bit = PINGROUP_BIT_##ior(8),                   \
                .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9),               \
                .drv_reg = -1,                                          \
        }
 
-#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
-
-#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b,             \
-                    drvdn_b, drvdn_w, drvup_b, drvup_w,                \
-                    slwr_b, slwr_w, slwf_b, slwf_w,                    \
-                    drvtype)                                           \
+#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b,    \
+                    drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w,         \
+                    slwf_b, slwf_w, drvtype)                           \
        {                                                               \
                .name = "drive_" #pg_name,                              \
                .pins = drive_##pg_name##_pins,                         \
@@ -1782,8 +1781,6 @@ static struct tegra_function tegra124_functions[] = {
                .drvtype_bit = PINGROUP_BIT_##drvtype(6),               \
        }
 
-#define MIPI_PAD_CTRL_PINGROUP_REG_Y(r)        ((r) - MIPI_PAD_CTRL_PINGROUP_REG_A)
-
 #define MIPI_PAD_CTRL_PINGROUP(pg_name, r, b, f0, f1)                  \
        {                                                               \
                .name = "mipi_pad_ctrl_" #pg_name,                      \
@@ -2044,8 +2041,8 @@ static const struct tegra_pingroup tegra124_groups[] = {
        DRV_PINGROUP(sdio4,       0x9c4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
        DRV_PINGROUP(ao4,         0x9c8,  2,  3,  4,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
 
-       /*                     pg_name, r      b  f0,  f1 */
-       MIPI_PAD_CTRL_PINGROUP(dsi_b,   0x820, 1, CSI, DSI_B)
+       /*                     pg_name, r,     b, f0,  f1 */
+       MIPI_PAD_CTRL_PINGROUP(dsi_b,   0x820, 1, CSI, DSI_B),
 };
 
 static const struct tegra_pinctrl_soc_data tegra124_pinctrl = {
@@ -2056,6 +2053,9 @@ static const struct tegra_pinctrl_soc_data tegra124_pinctrl = {
        .nfunctions = ARRAY_SIZE(tegra124_functions),
        .groups = tegra124_groups,
        .ngroups = ARRAY_SIZE(tegra124_groups),
+       .hsm_in_mux = false,
+       .schmitt_in_mux = false,
+       .drvtype_in_mux = false,
 };
 
 static int tegra124_pinctrl_probe(struct platform_device *pdev)
index d3a5722e4acbde4318d3b8f9501214dfe8cbdbb1..4833db4433d948c757bc6f5336bfde89fdd1d6e1 100644 (file)
@@ -2221,6 +2221,9 @@ static const struct tegra_pinctrl_soc_data tegra20_pinctrl = {
        .nfunctions = ARRAY_SIZE(tegra20_functions),
        .groups = tegra20_groups,
        .ngroups = ARRAY_SIZE(tegra20_groups),
+       .hsm_in_mux = false,
+       .schmitt_in_mux = false,
+       .drvtype_in_mux = false,
 };
 
 static int tegra20_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/pinctrl-tegra210.c b/drivers/pinctrl/pinctrl-tegra210.c
new file mode 100644 (file)
index 0000000..252b464
--- /dev/null
@@ -0,0 +1,1588 @@
+/*
+ * Pinctrl data for the NVIDIA Tegra210 pinmux
+ *
+ * Copyright (c) 2015, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-tegra.h"
+
+/*
+ * Most pins affected by the pinmux can also be GPIOs. Define these first.
+ * These must match how the GPIO driver names/numbers its pins.
+ */
+#define _GPIO(offset)                          (offset)
+
+#define TEGRA_PIN_PEX_L0_RST_N_PA0             _GPIO(0)
+#define TEGRA_PIN_PEX_L0_CLKREQ_N_PA1          _GPIO(1)
+#define TEGRA_PIN_PEX_WAKE_N_PA2               _GPIO(2)
+#define TEGRA_PIN_PEX_L1_RST_N_PA3             _GPIO(3)
+#define TEGRA_PIN_PEX_L1_CLKREQ_N_PA4          _GPIO(4)
+#define TEGRA_PIN_SATA_LED_ACTIVE_PA5          _GPIO(5)
+#define TEGRA_PIN_PA6                          _GPIO(6)
+#define TEGRA_PIN_DAP1_FS_PB0                  _GPIO(8)
+#define TEGRA_PIN_DAP1_DIN_PB1                 _GPIO(9)
+#define TEGRA_PIN_DAP1_DOUT_PB2                        _GPIO(10)
+#define TEGRA_PIN_DAP1_SCLK_PB3                        _GPIO(11)
+#define TEGRA_PIN_SPI2_MOSI_PB4                        _GPIO(12)
+#define TEGRA_PIN_SPI2_MISO_PB5                        _GPIO(13)
+#define TEGRA_PIN_SPI2_SCK_PB6                 _GPIO(14)
+#define TEGRA_PIN_SPI2_CS0_PB7                 _GPIO(15)
+#define TEGRA_PIN_SPI1_MOSI_PC0                        _GPIO(16)
+#define TEGRA_PIN_SPI1_MISO_PC1                        _GPIO(17)
+#define TEGRA_PIN_SPI1_SCK_PC2                 _GPIO(18)
+#define TEGRA_PIN_SPI1_CS0_PC3                 _GPIO(19)
+#define TEGRA_PIN_SPI1_CS1_PC4                 _GPIO(20)
+#define TEGRA_PIN_SPI4_SCK_PC5                 _GPIO(21)
+#define TEGRA_PIN_SPI4_CS0_PC6                 _GPIO(22)
+#define TEGRA_PIN_SPI4_MOSI_PC7                        _GPIO(23)
+#define TEGRA_PIN_SPI4_MISO_PD0                        _GPIO(24)
+#define TEGRA_PIN_UART3_TX_PD1                 _GPIO(25)
+#define TEGRA_PIN_UART3_RX_PD2                 _GPIO(26)
+#define TEGRA_PIN_UART3_RTS_PD3                        _GPIO(27)
+#define TEGRA_PIN_UART3_CTS_PD4                        _GPIO(28)
+#define TEGRA_PIN_DMIC1_CLK_PE0                        _GPIO(32)
+#define TEGRA_PIN_DMIC1_DAT_PE1                        _GPIO(33)
+#define TEGRA_PIN_DMIC2_CLK_PE2                        _GPIO(34)
+#define TEGRA_PIN_DMIC2_DAT_PE3                        _GPIO(35)
+#define TEGRA_PIN_DMIC3_CLK_PE4                        _GPIO(36)
+#define TEGRA_PIN_DMIC3_DAT_PE5                        _GPIO(37)
+#define TEGRA_PIN_PE6                          _GPIO(38)
+#define TEGRA_PIN_PE7                          _GPIO(39)
+#define TEGRA_PIN_GEN3_I2C_SCL_PF0             _GPIO(40)
+#define TEGRA_PIN_GEN3_I2C_SDA_PF1             _GPIO(41)
+#define TEGRA_PIN_UART2_TX_PG0                 _GPIO(48)
+#define TEGRA_PIN_UART2_RX_PG1                 _GPIO(49)
+#define TEGRA_PIN_UART2_RTS_PG2                        _GPIO(50)
+#define TEGRA_PIN_UART2_CTS_PG3                        _GPIO(51)
+#define TEGRA_PIN_WIFI_EN_PH0                  _GPIO(56)
+#define TEGRA_PIN_WIFI_RST_PH1                 _GPIO(57)
+#define TEGRA_PIN_WIFI_WAKE_AP_PH2             _GPIO(58)
+#define TEGRA_PIN_AP_WAKE_BT_PH3               _GPIO(59)
+#define TEGRA_PIN_BT_RST_PH4                   _GPIO(60)
+#define TEGRA_PIN_BT_WAKE_AP_PH5               _GPIO(61)
+#define TEGRA_PIN_PH6                          _GPIO(62)
+#define TEGRA_PIN_AP_WAKE_NFC_PH7              _GPIO(63)
+#define TEGRA_PIN_NFC_EN_PI0                   _GPIO(64)
+#define TEGRA_PIN_NFC_INT_PI1                  _GPIO(65)
+#define TEGRA_PIN_GPS_EN_PI2                   _GPIO(66)
+#define TEGRA_PIN_GPS_RST_PI3                  _GPIO(67)
+#define TEGRA_PIN_UART4_TX_PI4                 _GPIO(68)
+#define TEGRA_PIN_UART4_RX_PI5                 _GPIO(69)
+#define TEGRA_PIN_UART4_RTS_PI6                        _GPIO(70)
+#define TEGRA_PIN_UART4_CTS_PI7                        _GPIO(71)
+#define TEGRA_PIN_GEN1_I2C_SDA_PJ0             _GPIO(72)
+#define TEGRA_PIN_GEN1_I2C_SCL_PJ1             _GPIO(73)
+#define TEGRA_PIN_GEN2_I2C_SCL_PJ2             _GPIO(74)
+#define TEGRA_PIN_GEN2_I2C_SDA_PJ3             _GPIO(75)
+#define TEGRA_PIN_DAP4_FS_PJ4                  _GPIO(76)
+#define TEGRA_PIN_DAP4_DIN_PJ5                 _GPIO(77)
+#define TEGRA_PIN_DAP4_DOUT_PJ6                        _GPIO(78)
+#define TEGRA_PIN_DAP4_SCLK_PJ7                        _GPIO(79)
+#define TEGRA_PIN_PK0                          _GPIO(80)
+#define TEGRA_PIN_PK1                          _GPIO(81)
+#define TEGRA_PIN_PK2                          _GPIO(82)
+#define TEGRA_PIN_PK3                          _GPIO(83)
+#define TEGRA_PIN_PK4                          _GPIO(84)
+#define TEGRA_PIN_PK5                          _GPIO(85)
+#define TEGRA_PIN_PK6                          _GPIO(86)
+#define TEGRA_PIN_PK7                          _GPIO(87)
+#define TEGRA_PIN_PL0                          _GPIO(88)
+#define TEGRA_PIN_PL1                          _GPIO(89)
+#define TEGRA_PIN_SDMMC1_CLK_PM0               _GPIO(96)
+#define TEGRA_PIN_SDMMC1_CMD_PM1               _GPIO(97)
+#define TEGRA_PIN_SDMMC1_DAT3_PM2              _GPIO(98)
+#define TEGRA_PIN_SDMMC1_DAT2_PM3              _GPIO(99)
+#define TEGRA_PIN_SDMMC1_DAT1_PM4              _GPIO(100)
+#define TEGRA_PIN_SDMMC1_DAT0_PM5              _GPIO(101)
+#define TEGRA_PIN_SDMMC3_CLK_PP0               _GPIO(120)
+#define TEGRA_PIN_SDMMC3_CMD_PP1               _GPIO(121)
+#define TEGRA_PIN_SDMMC3_DAT3_PP2              _GPIO(122)
+#define TEGRA_PIN_SDMMC3_DAT2_PP3              _GPIO(123)
+#define TEGRA_PIN_SDMMC3_DAT1_PP4              _GPIO(124)
+#define TEGRA_PIN_SDMMC3_DAT0_PP5              _GPIO(125)
+#define TEGRA_PIN_CAM1_MCLK_PS0                        _GPIO(144)
+#define TEGRA_PIN_CAM2_MCLK_PS1                        _GPIO(145)
+#define TEGRA_PIN_CAM_I2C_SCL_PS2              _GPIO(146)
+#define TEGRA_PIN_CAM_I2C_SDA_PS3              _GPIO(147)
+#define TEGRA_PIN_CAM_RST_PS4                  _GPIO(148)
+#define TEGRA_PIN_CAM_AF_EN_PS5                        _GPIO(149)
+#define TEGRA_PIN_CAM_FLASH_EN_PS6             _GPIO(150)
+#define TEGRA_PIN_CAM1_PWDN_PS7                        _GPIO(151)
+#define TEGRA_PIN_CAM2_PWDN_PT0                        _GPIO(152)
+#define TEGRA_PIN_CAM1_STROBE_PT1              _GPIO(153)
+#define TEGRA_PIN_UART1_TX_PU0                 _GPIO(160)
+#define TEGRA_PIN_UART1_RX_PU1                 _GPIO(161)
+#define TEGRA_PIN_UART1_RTS_PU2                        _GPIO(162)
+#define TEGRA_PIN_UART1_CTS_PU3                        _GPIO(163)
+#define TEGRA_PIN_LCD_BL_PWM_PV0               _GPIO(168)
+#define TEGRA_PIN_LCD_BL_EN_PV1                        _GPIO(169)
+#define TEGRA_PIN_LCD_RST_PV2                  _GPIO(170)
+#define TEGRA_PIN_LCD_GPIO1_PV3                        _GPIO(171)
+#define TEGRA_PIN_LCD_GPIO2_PV4                        _GPIO(172)
+#define TEGRA_PIN_AP_READY_PV5                 _GPIO(173)
+#define TEGRA_PIN_TOUCH_RST_PV6                        _GPIO(174)
+#define TEGRA_PIN_TOUCH_CLK_PV7                        _GPIO(175)
+#define TEGRA_PIN_MODEM_WAKE_AP_PX0            _GPIO(184)
+#define TEGRA_PIN_TOUCH_INT_PX1                        _GPIO(185)
+#define TEGRA_PIN_MOTION_INT_PX2               _GPIO(186)
+#define TEGRA_PIN_ALS_PROX_INT_PX3             _GPIO(187)
+#define TEGRA_PIN_TEMP_ALERT_PX4               _GPIO(188)
+#define TEGRA_PIN_BUTTON_POWER_ON_PX5          _GPIO(189)
+#define TEGRA_PIN_BUTTON_VOL_UP_PX6            _GPIO(190)
+#define TEGRA_PIN_BUTTON_VOL_DOWN_PX7          _GPIO(191)
+#define TEGRA_PIN_BUTTON_SLIDE_SW_PY0          _GPIO(192)
+#define TEGRA_PIN_BUTTON_HOME_PY1              _GPIO(193)
+#define TEGRA_PIN_LCD_TE_PY2                   _GPIO(194)
+#define TEGRA_PIN_PWR_I2C_SCL_PY3              _GPIO(195)
+#define TEGRA_PIN_PWR_I2C_SDA_PY4              _GPIO(196)
+#define TEGRA_PIN_CLK_32K_OUT_PY5              _GPIO(197)
+#define TEGRA_PIN_PZ0                          _GPIO(200)
+#define TEGRA_PIN_PZ1                          _GPIO(201)
+#define TEGRA_PIN_PZ2                          _GPIO(202)
+#define TEGRA_PIN_PZ3                          _GPIO(203)
+#define TEGRA_PIN_PZ4                          _GPIO(204)
+#define TEGRA_PIN_PZ5                          _GPIO(205)
+#define TEGRA_PIN_DAP2_FS_PAA0                 _GPIO(208)
+#define TEGRA_PIN_DAP2_SCLK_PAA1               _GPIO(209)
+#define TEGRA_PIN_DAP2_DIN_PAA2                        _GPIO(210)
+#define TEGRA_PIN_DAP2_DOUT_PAA3               _GPIO(211)
+#define TEGRA_PIN_AUD_MCLK_PBB0                        _GPIO(216)
+#define TEGRA_PIN_DVFS_PWM_PBB1                        _GPIO(217)
+#define TEGRA_PIN_DVFS_CLK_PBB2                        _GPIO(218)
+#define TEGRA_PIN_GPIO_X1_AUD_PBB3             _GPIO(219)
+#define TEGRA_PIN_GPIO_X3_AUD_PBB4             _GPIO(220)
+#define TEGRA_PIN_HDMI_CEC_PCC0                        _GPIO(224)
+#define TEGRA_PIN_HDMI_INT_DP_HPD_PCC1         _GPIO(225)
+#define TEGRA_PIN_SPDIF_OUT_PCC2               _GPIO(226)
+#define TEGRA_PIN_SPDIF_IN_PCC3                        _GPIO(227)
+#define TEGRA_PIN_USB_VBUS_EN0_PCC4            _GPIO(228)
+#define TEGRA_PIN_USB_VBUS_EN1_PCC5            _GPIO(229)
+#define TEGRA_PIN_DP_HPD0_PCC6                 _GPIO(230)
+#define TEGRA_PIN_PCC7                         _GPIO(231)
+#define TEGRA_PIN_SPI2_CS1_PDD0                        _GPIO(232)
+#define TEGRA_PIN_QSPI_SCK_PEE0                        _GPIO(240)
+#define TEGRA_PIN_QSPI_CS_N_PEE1               _GPIO(241)
+#define TEGRA_PIN_QSPI_IO0_PEE2                        _GPIO(242)
+#define TEGRA_PIN_QSPI_IO1_PEE3                        _GPIO(243)
+#define TEGRA_PIN_QSPI_IO2_PEE4                        _GPIO(244)
+#define TEGRA_PIN_QSPI_IO3_PEE5                        _GPIO(245)
+
+/* All non-GPIO pins follow */
+#define NUM_GPIOS                              (TEGRA_PIN_QSPI_IO3_PEE5 + 1)
+#define _PIN(offset)                           (NUM_GPIOS + (offset))
+
+/* Non-GPIO pins */
+#define TEGRA_PIN_CORE_PWR_REQ                 _PIN(0)
+#define TEGRA_PIN_CPU_PWR_REQ                  _PIN(1)
+#define TEGRA_PIN_PWR_INT_N                    _PIN(2)
+#define TEGRA_PIN_CLK_32K_IN                   _PIN(3)
+#define TEGRA_PIN_JTAG_RTCK                    _PIN(4)
+#define TEGRA_PIN_BATT_BCL                     _PIN(5)
+#define TEGRA_PIN_CLK_REQ                      _PIN(6)
+#define TEGRA_PIN_SHUTDOWN                     _PIN(7)
+
+static const struct pinctrl_pin_desc tegra210_pins[] = {
+       PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PA0, "PEX_L0_RST_N PA0"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PA1, "PEX_L0_CLKREQ_N PA1"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PA2, "PEX_WAKE_N PA2"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PA3, "PEX_L1_RST_N PA3"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PA4, "PEX_L1_CLKREQ_N PA4"),
+       PINCTRL_PIN(TEGRA_PIN_SATA_LED_ACTIVE_PA5, "SATA_LED_ACTIVE PA5"),
+       PINCTRL_PIN(TEGRA_PIN_PA6, "PA6"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PB0, "DAP1_FS PB0"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PB1, "DAP1_DIN PB1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PB2, "DAP1_DOUT PB2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PB3, "DAP1_SCLK PB3"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PB4, "SPI2_MOSI PB4"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PB5, "SPI2_MISO PB5"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PB6, "SPI2_SCK PB6"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_PB7, "SPI2_CS0 PB7"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PC0, "SPI1_MOSI PC0"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PC1, "SPI1_MISO PC1"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PC2, "SPI1_SCK PC2"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_PC3, "SPI1_CS0 PC3"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_CS1_PC4, "SPI1_CS1 PC4"),
+       PINCTRL_PIN(TEGRA_PIN_SPI4_SCK_PC5, "SPI4_SCK PC5"),
+       PINCTRL_PIN(TEGRA_PIN_SPI4_CS0_PC6, "SPI4_CS0 PC6"),
+       PINCTRL_PIN(TEGRA_PIN_SPI4_MOSI_PC7, "SPI4_MOSI PC7"),
+       PINCTRL_PIN(TEGRA_PIN_SPI4_MISO_PD0, "SPI4_MISO PD0"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_TX_PD1, "UART3_TX PD1"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_RX_PD2, "UART3_RX PD2"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_RTS_PD3, "UART3_RTS PD3"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_CTS_PD4, "UART3_CTS PD4"),
+       PINCTRL_PIN(TEGRA_PIN_DMIC1_CLK_PE0, "DMIC1_CLK PE0"),
+       PINCTRL_PIN(TEGRA_PIN_DMIC1_DAT_PE1, "DMIC1_DAT PE1"),
+       PINCTRL_PIN(TEGRA_PIN_DMIC2_CLK_PE2, "DMIC2_CLK PE2"),
+       PINCTRL_PIN(TEGRA_PIN_DMIC2_DAT_PE3, "DMIC2_DAT PE3"),
+       PINCTRL_PIN(TEGRA_PIN_DMIC3_CLK_PE4, "DMIC3_CLK PE4"),
+       PINCTRL_PIN(TEGRA_PIN_DMIC3_DAT_PE5, "DMIC3_DAT PE5"),
+       PINCTRL_PIN(TEGRA_PIN_PE6, "PE6"),
+       PINCTRL_PIN(TEGRA_PIN_PE7, "PE7"),
+       PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SCL_PF0, "GEN3_I2C_SCL PF0"),
+       PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SDA_PF1, "GEN3_I2C_SDA PF1"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_TX_PG0, "UART2_TX PG0"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_RX_PG1, "UART2_RX PG1"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_RTS_PG2, "UART2_RTS PG2"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_CTS_PG3, "UART2_CTS PG3"),
+       PINCTRL_PIN(TEGRA_PIN_WIFI_EN_PH0, "WIFI_EN PH0"),
+       PINCTRL_PIN(TEGRA_PIN_WIFI_RST_PH1, "WIFI_RST PH1"),
+       PINCTRL_PIN(TEGRA_PIN_WIFI_WAKE_AP_PH2, "WIFI_WAKE_AP PH2"),
+       PINCTRL_PIN(TEGRA_PIN_AP_WAKE_BT_PH3, "AP_WAKE_BT PH3"),
+       PINCTRL_PIN(TEGRA_PIN_BT_RST_PH4, "BT_RST PH4"),
+       PINCTRL_PIN(TEGRA_PIN_BT_WAKE_AP_PH5, "BT_WAKE_AP PH5"),
+       PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"),
+       PINCTRL_PIN(TEGRA_PIN_AP_WAKE_NFC_PH7, "AP_WAKE_NFC PH7"),
+       PINCTRL_PIN(TEGRA_PIN_NFC_EN_PI0, "NFC_EN PI0"),
+       PINCTRL_PIN(TEGRA_PIN_NFC_INT_PI1, "NFC_INT PI1"),
+       PINCTRL_PIN(TEGRA_PIN_GPS_EN_PI2, "GPS_EN PI2"),
+       PINCTRL_PIN(TEGRA_PIN_GPS_RST_PI3, "GPS_RST PI3"),
+       PINCTRL_PIN(TEGRA_PIN_UART4_TX_PI4, "UART4_TX PI4"),
+       PINCTRL_PIN(TEGRA_PIN_UART4_RX_PI5, "UART4_RX PI5"),
+       PINCTRL_PIN(TEGRA_PIN_UART4_RTS_PI6, "UART4_RTS PI6"),
+       PINCTRL_PIN(TEGRA_PIN_UART4_CTS_PI7, "UART4_CTS PI7"),
+       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PJ0, "GEN1_I2C_SDA PJ0"),
+       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PJ1, "GEN1_I2C_SCL PJ1"),
+       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PJ2, "GEN2_I2C_SCL PJ2"),
+       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PJ3, "GEN2_I2C_SDA PJ3"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PJ4, "DAP4_FS PJ4"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PJ5, "DAP4_DIN PJ5"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PJ6, "DAP4_DOUT PJ6"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PJ7, "DAP4_SCLK PJ7"),
+       PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"),
+       PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"),
+       PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"),
+       PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"),
+       PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"),
+       PINCTRL_PIN(TEGRA_PIN_PK5, "PK5"),
+       PINCTRL_PIN(TEGRA_PIN_PK6, "PK6"),
+       PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"),
+       PINCTRL_PIN(TEGRA_PIN_PL0, "PL0"),
+       PINCTRL_PIN(TEGRA_PIN_PL1, "PL1"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PM0, "SDMMC1_CLK PM0"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PM1, "SDMMC1_CMD PM1"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PM2, "SDMMC1_DAT3 PM2"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PM3, "SDMMC1_DAT2 PM3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PM4, "SDMMC1_DAT1 PM4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PM5, "SDMMC1_DAT0 PM5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PP0, "SDMMC3_CLK PP0"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PP1, "SDMMC3_CMD PP1"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PP2, "SDMMC3_DAT3 PP2"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PP3, "SDMMC3_DAT2 PP3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PP4, "SDMMC3_DAT1 PP4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PP5, "SDMMC3_DAT0 PP5"),
+       PINCTRL_PIN(TEGRA_PIN_CAM1_MCLK_PS0, "CAM1_MCLK PS0"),
+       PINCTRL_PIN(TEGRA_PIN_CAM2_MCLK_PS1, "CAM2_MCLK PS1"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PS2, "CAM_I2C_SCL PS2"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PS3, "CAM_I2C_SDA PS3"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_RST_PS4, "CAM_RST PS4"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_AF_EN_PS5, "CAM_AF_EN PS5"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_FLASH_EN_PS6, "CAM_FLASH_EN PS6"),
+       PINCTRL_PIN(TEGRA_PIN_CAM1_PWDN_PS7, "CAM1_PWDN PS7"),
+       PINCTRL_PIN(TEGRA_PIN_CAM2_PWDN_PT0, "CAM2_PWDN PT0"),
+       PINCTRL_PIN(TEGRA_PIN_CAM1_STROBE_PT1, "CAM1_STROBE PT1"),
+       PINCTRL_PIN(TEGRA_PIN_UART1_TX_PU0, "UART1_TX PU0"),
+       PINCTRL_PIN(TEGRA_PIN_UART1_RX_PU1, "UART1_RX PU1"),
+       PINCTRL_PIN(TEGRA_PIN_UART1_RTS_PU2, "UART1_RTS PU2"),
+       PINCTRL_PIN(TEGRA_PIN_UART1_CTS_PU3, "UART1_CTS PU3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_BL_PWM_PV0, "LCD_BL_PWM PV0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_BL_EN_PV1, "LCD_BL_EN PV1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_RST_PV2, "LCD_RST PV2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_GPIO1_PV3, "LCD_GPIO1 PV3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_GPIO2_PV4, "LCD_GPIO2 PV4"),
+       PINCTRL_PIN(TEGRA_PIN_AP_READY_PV5, "AP_READY PV5"),
+       PINCTRL_PIN(TEGRA_PIN_TOUCH_RST_PV6, "TOUCH_RST PV6"),
+       PINCTRL_PIN(TEGRA_PIN_TOUCH_CLK_PV7, "TOUCH_CLK PV7"),
+       PINCTRL_PIN(TEGRA_PIN_MODEM_WAKE_AP_PX0, "MODEM_WAKE_AP PX0"),
+       PINCTRL_PIN(TEGRA_PIN_TOUCH_INT_PX1, "TOUCH_INT PX1"),
+       PINCTRL_PIN(TEGRA_PIN_MOTION_INT_PX2, "MOTION_INT PX2"),
+       PINCTRL_PIN(TEGRA_PIN_ALS_PROX_INT_PX3, "ALS_PROX_INT PX3"),
+       PINCTRL_PIN(TEGRA_PIN_TEMP_ALERT_PX4, "TEMP_ALERT PX4"),
+       PINCTRL_PIN(TEGRA_PIN_BUTTON_POWER_ON_PX5, "BUTTON_POWER_ON PX5"),
+       PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_UP_PX6, "BUTTON_VOL_UP PX6"),
+       PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_DOWN_PX7, "BUTTON_VOL_DOWN PX7"),
+       PINCTRL_PIN(TEGRA_PIN_BUTTON_SLIDE_SW_PY0, "BUTTON_SLIDE_SW PY0"),
+       PINCTRL_PIN(TEGRA_PIN_BUTTON_HOME_PY1, "BUTTON_HOME PY1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_TE_PY2, "LCD_TE PY2"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PY3, "PWR_I2C_SCL PY3"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PY4, "PWR_I2C_SDA PY4"),
+       PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PY5, "CLK_32K_OUT PY5"),
+       PINCTRL_PIN(TEGRA_PIN_PZ0, "PZ0"),
+       PINCTRL_PIN(TEGRA_PIN_PZ1, "PZ1"),
+       PINCTRL_PIN(TEGRA_PIN_PZ2, "PZ2"),
+       PINCTRL_PIN(TEGRA_PIN_PZ3, "PZ3"),
+       PINCTRL_PIN(TEGRA_PIN_PZ4, "PZ4"),
+       PINCTRL_PIN(TEGRA_PIN_PZ5, "PZ5"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PAA0, "DAP2_FS PAA0"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PAA1, "DAP2_SCLK PAA1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PAA2, "DAP2_DIN PAA2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PAA3, "DAP2_DOUT PAA3"),
+       PINCTRL_PIN(TEGRA_PIN_AUD_MCLK_PBB0, "AUD_MCLK PBB0"),
+       PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PBB1, "DVFS_PWM PBB1"),
+       PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PBB2, "DVFS_CLK PBB2"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PBB3, "GPIO_X1_AUD PBB3"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PBB4, "GPIO_X3_AUD PBB4"),
+       PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PCC0, "HDMI_CEC PCC0"),
+       PINCTRL_PIN(TEGRA_PIN_HDMI_INT_DP_HPD_PCC1, "HDMI_INT_DP_HPD PCC1"),
+       PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PCC2, "SPDIF_OUT PCC2"),
+       PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PCC3, "SPDIF_IN PCC3"),
+       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PCC4, "USB_VBUS_EN0 PCC4"),
+       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PCC5, "USB_VBUS_EN1 PCC5"),
+       PINCTRL_PIN(TEGRA_PIN_DP_HPD0_PCC6, "DP_HPD0 PCC6"),
+       PINCTRL_PIN(TEGRA_PIN_PCC7, "PCC7"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_PDD0, "SPI2_CS1 PDD0"),
+       PINCTRL_PIN(TEGRA_PIN_QSPI_SCK_PEE0, "QSPI_SCK PEE0"),
+       PINCTRL_PIN(TEGRA_PIN_QSPI_CS_N_PEE1, "QSPI_CS_N PEE1"),
+       PINCTRL_PIN(TEGRA_PIN_QSPI_IO0_PEE2, "QSPI_IO0 PEE2"),
+       PINCTRL_PIN(TEGRA_PIN_QSPI_IO1_PEE3, "QSPI_IO1 PEE3"),
+       PINCTRL_PIN(TEGRA_PIN_QSPI_IO2_PEE4, "QSPI_IO2 PEE4"),
+       PINCTRL_PIN(TEGRA_PIN_QSPI_IO3_PEE5, "QSPI_IO3 PEE5"),
+       PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"),
+       PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"),
+       PINCTRL_PIN(TEGRA_PIN_BATT_BCL, "BATT_BCL"),
+       PINCTRL_PIN(TEGRA_PIN_CLK_REQ, "CLK_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_SHUTDOWN, "SHUTDOWN"),
+};
+
+static const unsigned pex_l0_rst_n_pa0_pins[] = {
+       TEGRA_PIN_PEX_L0_RST_N_PA0,
+};
+
+static const unsigned pex_l0_clkreq_n_pa1_pins[] = {
+       TEGRA_PIN_PEX_L0_CLKREQ_N_PA1,
+};
+
+static const unsigned pex_wake_n_pa2_pins[] = {
+       TEGRA_PIN_PEX_WAKE_N_PA2,
+};
+
+static const unsigned pex_l1_rst_n_pa3_pins[] = {
+       TEGRA_PIN_PEX_L1_RST_N_PA3,
+};
+
+static const unsigned pex_l1_clkreq_n_pa4_pins[] = {
+       TEGRA_PIN_PEX_L1_CLKREQ_N_PA4,
+};
+
+static const unsigned sata_led_active_pa5_pins[] = {
+       TEGRA_PIN_SATA_LED_ACTIVE_PA5,
+};
+
+static const unsigned pa6_pins[] = {
+       TEGRA_PIN_PA6,
+};
+
+static const unsigned dap1_fs_pb0_pins[] = {
+       TEGRA_PIN_DAP1_FS_PB0,
+};
+
+static const unsigned dap1_din_pb1_pins[] = {
+       TEGRA_PIN_DAP1_DIN_PB1,
+};
+
+static const unsigned dap1_dout_pb2_pins[] = {
+       TEGRA_PIN_DAP1_DOUT_PB2,
+};
+
+static const unsigned dap1_sclk_pb3_pins[] = {
+       TEGRA_PIN_DAP1_SCLK_PB3,
+};
+
+static const unsigned spi2_mosi_pb4_pins[] = {
+       TEGRA_PIN_SPI2_MOSI_PB4,
+};
+
+static const unsigned spi2_miso_pb5_pins[] = {
+       TEGRA_PIN_SPI2_MISO_PB5,
+};
+
+static const unsigned spi2_sck_pb6_pins[] = {
+       TEGRA_PIN_SPI2_SCK_PB6,
+};
+
+static const unsigned spi2_cs0_pb7_pins[] = {
+       TEGRA_PIN_SPI2_CS0_PB7,
+};
+
+static const unsigned spi1_mosi_pc0_pins[] = {
+       TEGRA_PIN_SPI1_MOSI_PC0,
+};
+
+static const unsigned spi1_miso_pc1_pins[] = {
+       TEGRA_PIN_SPI1_MISO_PC1,
+};
+
+static const unsigned spi1_sck_pc2_pins[] = {
+       TEGRA_PIN_SPI1_SCK_PC2,
+};
+
+static const unsigned spi1_cs0_pc3_pins[] = {
+       TEGRA_PIN_SPI1_CS0_PC3,
+};
+
+static const unsigned spi1_cs1_pc4_pins[] = {
+       TEGRA_PIN_SPI1_CS1_PC4,
+};
+
+static const unsigned spi4_sck_pc5_pins[] = {
+       TEGRA_PIN_SPI4_SCK_PC5,
+};
+
+static const unsigned spi4_cs0_pc6_pins[] = {
+       TEGRA_PIN_SPI4_CS0_PC6,
+};
+
+static const unsigned spi4_mosi_pc7_pins[] = {
+       TEGRA_PIN_SPI4_MOSI_PC7,
+};
+
+static const unsigned spi4_miso_pd0_pins[] = {
+       TEGRA_PIN_SPI4_MISO_PD0,
+};
+
+static const unsigned uart3_tx_pd1_pins[] = {
+       TEGRA_PIN_UART3_TX_PD1,
+};
+
+static const unsigned uart3_rx_pd2_pins[] = {
+       TEGRA_PIN_UART3_RX_PD2,
+};
+
+static const unsigned uart3_rts_pd3_pins[] = {
+       TEGRA_PIN_UART3_RTS_PD3,
+};
+
+static const unsigned uart3_cts_pd4_pins[] = {
+       TEGRA_PIN_UART3_CTS_PD4,
+};
+
+static const unsigned dmic1_clk_pe0_pins[] = {
+       TEGRA_PIN_DMIC1_CLK_PE0,
+};
+
+static const unsigned dmic1_dat_pe1_pins[] = {
+       TEGRA_PIN_DMIC1_DAT_PE1,
+};
+
+static const unsigned dmic2_clk_pe2_pins[] = {
+       TEGRA_PIN_DMIC2_CLK_PE2,
+};
+
+static const unsigned dmic2_dat_pe3_pins[] = {
+       TEGRA_PIN_DMIC2_DAT_PE3,
+};
+
+static const unsigned dmic3_clk_pe4_pins[] = {
+       TEGRA_PIN_DMIC3_CLK_PE4,
+};
+
+static const unsigned dmic3_dat_pe5_pins[] = {
+       TEGRA_PIN_DMIC3_DAT_PE5,
+};
+
+static const unsigned pe6_pins[] = {
+       TEGRA_PIN_PE6,
+};
+
+static const unsigned pe7_pins[] = {
+       TEGRA_PIN_PE7,
+};
+
+static const unsigned gen3_i2c_scl_pf0_pins[] = {
+       TEGRA_PIN_GEN3_I2C_SCL_PF0,
+};
+
+static const unsigned gen3_i2c_sda_pf1_pins[] = {
+       TEGRA_PIN_GEN3_I2C_SDA_PF1,
+};
+
+static const unsigned uart2_tx_pg0_pins[] = {
+       TEGRA_PIN_UART2_TX_PG0,
+};
+
+static const unsigned uart2_rx_pg1_pins[] = {
+       TEGRA_PIN_UART2_RX_PG1,
+};
+
+static const unsigned uart2_rts_pg2_pins[] = {
+       TEGRA_PIN_UART2_RTS_PG2,
+};
+
+static const unsigned uart2_cts_pg3_pins[] = {
+       TEGRA_PIN_UART2_CTS_PG3,
+};
+
+static const unsigned wifi_en_ph0_pins[] = {
+       TEGRA_PIN_WIFI_EN_PH0,
+};
+
+static const unsigned wifi_rst_ph1_pins[] = {
+       TEGRA_PIN_WIFI_RST_PH1,
+};
+
+static const unsigned wifi_wake_ap_ph2_pins[] = {
+       TEGRA_PIN_WIFI_WAKE_AP_PH2,
+};
+
+static const unsigned ap_wake_bt_ph3_pins[] = {
+       TEGRA_PIN_AP_WAKE_BT_PH3,
+};
+
+static const unsigned bt_rst_ph4_pins[] = {
+       TEGRA_PIN_BT_RST_PH4,
+};
+
+static const unsigned bt_wake_ap_ph5_pins[] = {
+       TEGRA_PIN_BT_WAKE_AP_PH5,
+};
+
+static const unsigned ph6_pins[] = {
+       TEGRA_PIN_PH6,
+};
+
+static const unsigned ap_wake_nfc_ph7_pins[] = {
+       TEGRA_PIN_AP_WAKE_NFC_PH7,
+};
+
+static const unsigned nfc_en_pi0_pins[] = {
+       TEGRA_PIN_NFC_EN_PI0,
+};
+
+static const unsigned nfc_int_pi1_pins[] = {
+       TEGRA_PIN_NFC_INT_PI1,
+};
+
+static const unsigned gps_en_pi2_pins[] = {
+       TEGRA_PIN_GPS_EN_PI2,
+};
+
+static const unsigned gps_rst_pi3_pins[] = {
+       TEGRA_PIN_GPS_RST_PI3,
+};
+
+static const unsigned uart4_tx_pi4_pins[] = {
+       TEGRA_PIN_UART4_TX_PI4,
+};
+
+static const unsigned uart4_rx_pi5_pins[] = {
+       TEGRA_PIN_UART4_RX_PI5,
+};
+
+static const unsigned uart4_rts_pi6_pins[] = {
+       TEGRA_PIN_UART4_RTS_PI6,
+};
+
+static const unsigned uart4_cts_pi7_pins[] = {
+       TEGRA_PIN_UART4_CTS_PI7,
+};
+
+static const unsigned gen1_i2c_sda_pj0_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SDA_PJ0,
+};
+
+static const unsigned gen1_i2c_scl_pj1_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SCL_PJ1,
+};
+
+static const unsigned gen2_i2c_scl_pj2_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SCL_PJ2,
+};
+
+static const unsigned gen2_i2c_sda_pj3_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SDA_PJ3,
+};
+
+static const unsigned dap4_fs_pj4_pins[] = {
+       TEGRA_PIN_DAP4_FS_PJ4,
+};
+
+static const unsigned dap4_din_pj5_pins[] = {
+       TEGRA_PIN_DAP4_DIN_PJ5,
+};
+
+static const unsigned dap4_dout_pj6_pins[] = {
+       TEGRA_PIN_DAP4_DOUT_PJ6,
+};
+
+static const unsigned dap4_sclk_pj7_pins[] = {
+       TEGRA_PIN_DAP4_SCLK_PJ7,
+};
+
+static const unsigned pk0_pins[] = {
+       TEGRA_PIN_PK0,
+};
+
+static const unsigned pk1_pins[] = {
+       TEGRA_PIN_PK1,
+};
+
+static const unsigned pk2_pins[] = {
+       TEGRA_PIN_PK2,
+};
+
+static const unsigned pk3_pins[] = {
+       TEGRA_PIN_PK3,
+};
+
+static const unsigned pk4_pins[] = {
+       TEGRA_PIN_PK4,
+};
+
+static const unsigned pk5_pins[] = {
+       TEGRA_PIN_PK5,
+};
+
+static const unsigned pk6_pins[] = {
+       TEGRA_PIN_PK6,
+};
+
+static const unsigned pk7_pins[] = {
+       TEGRA_PIN_PK7,
+};
+
+static const unsigned pl0_pins[] = {
+       TEGRA_PIN_PL0,
+};
+
+static const unsigned pl1_pins[] = {
+       TEGRA_PIN_PL1,
+};
+
+static const unsigned sdmmc1_clk_pm0_pins[] = {
+       TEGRA_PIN_SDMMC1_CLK_PM0,
+};
+
+static const unsigned sdmmc1_cmd_pm1_pins[] = {
+       TEGRA_PIN_SDMMC1_CMD_PM1,
+};
+
+static const unsigned sdmmc1_dat3_pm2_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT3_PM2,
+};
+
+static const unsigned sdmmc1_dat2_pm3_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT2_PM3,
+};
+
+static const unsigned sdmmc1_dat1_pm4_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT1_PM4,
+};
+
+static const unsigned sdmmc1_dat0_pm5_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT0_PM5,
+};
+
+static const unsigned sdmmc3_clk_pp0_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_PP0,
+};
+
+static const unsigned sdmmc3_cmd_pp1_pins[] = {
+       TEGRA_PIN_SDMMC3_CMD_PP1,
+};
+
+static const unsigned sdmmc3_dat3_pp2_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT3_PP2,
+};
+
+static const unsigned sdmmc3_dat2_pp3_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT2_PP3,
+};
+
+static const unsigned sdmmc3_dat1_pp4_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT1_PP4,
+};
+
+static const unsigned sdmmc3_dat0_pp5_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT0_PP5,
+};
+
+static const unsigned cam1_mclk_ps0_pins[] = {
+       TEGRA_PIN_CAM1_MCLK_PS0,
+};
+
+static const unsigned cam2_mclk_ps1_pins[] = {
+       TEGRA_PIN_CAM2_MCLK_PS1,
+};
+
+static const unsigned cam_i2c_scl_ps2_pins[] = {
+       TEGRA_PIN_CAM_I2C_SCL_PS2,
+};
+
+static const unsigned cam_i2c_sda_ps3_pins[] = {
+       TEGRA_PIN_CAM_I2C_SDA_PS3,
+};
+
+static const unsigned cam_rst_ps4_pins[] = {
+       TEGRA_PIN_CAM_RST_PS4,
+};
+
+static const unsigned cam_af_en_ps5_pins[] = {
+       TEGRA_PIN_CAM_AF_EN_PS5,
+};
+
+static const unsigned cam_flash_en_ps6_pins[] = {
+       TEGRA_PIN_CAM_FLASH_EN_PS6,
+};
+
+static const unsigned cam1_pwdn_ps7_pins[] = {
+       TEGRA_PIN_CAM1_PWDN_PS7,
+};
+
+static const unsigned cam2_pwdn_pt0_pins[] = {
+       TEGRA_PIN_CAM2_PWDN_PT0,
+};
+
+static const unsigned cam1_strobe_pt1_pins[] = {
+       TEGRA_PIN_CAM1_STROBE_PT1,
+};
+
+static const unsigned uart1_tx_pu0_pins[] = {
+       TEGRA_PIN_UART1_TX_PU0,
+};
+
+static const unsigned uart1_rx_pu1_pins[] = {
+       TEGRA_PIN_UART1_RX_PU1,
+};
+
+static const unsigned uart1_rts_pu2_pins[] = {
+       TEGRA_PIN_UART1_RTS_PU2,
+};
+
+static const unsigned uart1_cts_pu3_pins[] = {
+       TEGRA_PIN_UART1_CTS_PU3,
+};
+
+static const unsigned lcd_bl_pwm_pv0_pins[] = {
+       TEGRA_PIN_LCD_BL_PWM_PV0,
+};
+
+static const unsigned lcd_bl_en_pv1_pins[] = {
+       TEGRA_PIN_LCD_BL_EN_PV1,
+};
+
+static const unsigned lcd_rst_pv2_pins[] = {
+       TEGRA_PIN_LCD_RST_PV2,
+};
+
+static const unsigned lcd_gpio1_pv3_pins[] = {
+       TEGRA_PIN_LCD_GPIO1_PV3,
+};
+
+static const unsigned lcd_gpio2_pv4_pins[] = {
+       TEGRA_PIN_LCD_GPIO2_PV4,
+};
+
+static const unsigned ap_ready_pv5_pins[] = {
+       TEGRA_PIN_AP_READY_PV5,
+};
+
+static const unsigned touch_rst_pv6_pins[] = {
+       TEGRA_PIN_TOUCH_RST_PV6,
+};
+
+static const unsigned touch_clk_pv7_pins[] = {
+       TEGRA_PIN_TOUCH_CLK_PV7,
+};
+
+static const unsigned modem_wake_ap_px0_pins[] = {
+       TEGRA_PIN_MODEM_WAKE_AP_PX0,
+};
+
+static const unsigned touch_int_px1_pins[] = {
+       TEGRA_PIN_TOUCH_INT_PX1,
+};
+
+static const unsigned motion_int_px2_pins[] = {
+       TEGRA_PIN_MOTION_INT_PX2,
+};
+
+static const unsigned als_prox_int_px3_pins[] = {
+       TEGRA_PIN_ALS_PROX_INT_PX3,
+};
+
+static const unsigned temp_alert_px4_pins[] = {
+       TEGRA_PIN_TEMP_ALERT_PX4,
+};
+
+static const unsigned button_power_on_px5_pins[] = {
+       TEGRA_PIN_BUTTON_POWER_ON_PX5,
+};
+
+static const unsigned button_vol_up_px6_pins[] = {
+       TEGRA_PIN_BUTTON_VOL_UP_PX6,
+};
+
+static const unsigned button_vol_down_px7_pins[] = {
+       TEGRA_PIN_BUTTON_VOL_DOWN_PX7,
+};
+
+static const unsigned button_slide_sw_py0_pins[] = {
+       TEGRA_PIN_BUTTON_SLIDE_SW_PY0,
+};
+
+static const unsigned button_home_py1_pins[] = {
+       TEGRA_PIN_BUTTON_HOME_PY1,
+};
+
+static const unsigned lcd_te_py2_pins[] = {
+       TEGRA_PIN_LCD_TE_PY2,
+};
+
+static const unsigned pwr_i2c_scl_py3_pins[] = {
+       TEGRA_PIN_PWR_I2C_SCL_PY3,
+};
+
+static const unsigned pwr_i2c_sda_py4_pins[] = {
+       TEGRA_PIN_PWR_I2C_SDA_PY4,
+};
+
+static const unsigned clk_32k_out_py5_pins[] = {
+       TEGRA_PIN_CLK_32K_OUT_PY5,
+};
+
+static const unsigned pz0_pins[] = {
+       TEGRA_PIN_PZ0,
+};
+
+static const unsigned pz1_pins[] = {
+       TEGRA_PIN_PZ1,
+};
+
+static const unsigned pz2_pins[] = {
+       TEGRA_PIN_PZ2,
+};
+
+static const unsigned pz3_pins[] = {
+       TEGRA_PIN_PZ3,
+};
+
+static const unsigned pz4_pins[] = {
+       TEGRA_PIN_PZ4,
+};
+
+static const unsigned pz5_pins[] = {
+       TEGRA_PIN_PZ5,
+};
+
+static const unsigned dap2_fs_paa0_pins[] = {
+       TEGRA_PIN_DAP2_FS_PAA0,
+};
+
+static const unsigned dap2_sclk_paa1_pins[] = {
+       TEGRA_PIN_DAP2_SCLK_PAA1,
+};
+
+static const unsigned dap2_din_paa2_pins[] = {
+       TEGRA_PIN_DAP2_DIN_PAA2,
+};
+
+static const unsigned dap2_dout_paa3_pins[] = {
+       TEGRA_PIN_DAP2_DOUT_PAA3,
+};
+
+static const unsigned aud_mclk_pbb0_pins[] = {
+       TEGRA_PIN_AUD_MCLK_PBB0,
+};
+
+static const unsigned dvfs_pwm_pbb1_pins[] = {
+       TEGRA_PIN_DVFS_PWM_PBB1,
+};
+
+static const unsigned dvfs_clk_pbb2_pins[] = {
+       TEGRA_PIN_DVFS_CLK_PBB2,
+};
+
+static const unsigned gpio_x1_aud_pbb3_pins[] = {
+       TEGRA_PIN_GPIO_X1_AUD_PBB3,
+};
+
+static const unsigned gpio_x3_aud_pbb4_pins[] = {
+       TEGRA_PIN_GPIO_X3_AUD_PBB4,
+};
+
+static const unsigned hdmi_cec_pcc0_pins[] = {
+       TEGRA_PIN_HDMI_CEC_PCC0,
+};
+
+static const unsigned hdmi_int_dp_hpd_pcc1_pins[] = {
+       TEGRA_PIN_HDMI_INT_DP_HPD_PCC1,
+};
+
+static const unsigned spdif_out_pcc2_pins[] = {
+       TEGRA_PIN_SPDIF_OUT_PCC2,
+};
+
+static const unsigned spdif_in_pcc3_pins[] = {
+       TEGRA_PIN_SPDIF_IN_PCC3,
+};
+
+static const unsigned usb_vbus_en0_pcc4_pins[] = {
+       TEGRA_PIN_USB_VBUS_EN0_PCC4,
+};
+
+static const unsigned usb_vbus_en1_pcc5_pins[] = {
+       TEGRA_PIN_USB_VBUS_EN1_PCC5,
+};
+
+static const unsigned dp_hpd0_pcc6_pins[] = {
+       TEGRA_PIN_DP_HPD0_PCC6,
+};
+
+static const unsigned pcc7_pins[] = {
+       TEGRA_PIN_PCC7,
+};
+
+static const unsigned spi2_cs1_pdd0_pins[] = {
+       TEGRA_PIN_SPI2_CS1_PDD0,
+};
+
+static const unsigned qspi_sck_pee0_pins[] = {
+       TEGRA_PIN_QSPI_SCK_PEE0,
+};
+
+static const unsigned qspi_cs_n_pee1_pins[] = {
+       TEGRA_PIN_QSPI_CS_N_PEE1,
+};
+
+static const unsigned qspi_io0_pee2_pins[] = {
+       TEGRA_PIN_QSPI_IO0_PEE2,
+};
+
+static const unsigned qspi_io1_pee3_pins[] = {
+       TEGRA_PIN_QSPI_IO1_PEE3,
+};
+
+static const unsigned qspi_io2_pee4_pins[] = {
+       TEGRA_PIN_QSPI_IO2_PEE4,
+};
+
+static const unsigned qspi_io3_pee5_pins[] = {
+       TEGRA_PIN_QSPI_IO3_PEE5,
+};
+
+static const unsigned core_pwr_req_pins[] = {
+       TEGRA_PIN_CORE_PWR_REQ,
+};
+
+static const unsigned cpu_pwr_req_pins[] = {
+       TEGRA_PIN_CPU_PWR_REQ,
+};
+
+static const unsigned pwr_int_n_pins[] = {
+       TEGRA_PIN_PWR_INT_N,
+};
+
+static const unsigned clk_32k_in_pins[] = {
+       TEGRA_PIN_CLK_32K_IN,
+};
+
+static const unsigned jtag_rtck_pins[] = {
+       TEGRA_PIN_JTAG_RTCK,
+};
+
+static const unsigned batt_bcl_pins[] = {
+       TEGRA_PIN_BATT_BCL,
+};
+
+static const unsigned clk_req_pins[] = {
+       TEGRA_PIN_CLK_REQ,
+};
+
+static const unsigned shutdown_pins[] = {
+       TEGRA_PIN_SHUTDOWN,
+};
+
+static const unsigned drive_pa6_pins[] = {
+       TEGRA_PIN_PA6,
+};
+
+static const unsigned drive_pcc7_pins[] = {
+       TEGRA_PIN_PCC7,
+};
+
+static const unsigned drive_pe6_pins[] = {
+       TEGRA_PIN_PE6,
+};
+
+static const unsigned drive_pe7_pins[] = {
+       TEGRA_PIN_PE7,
+};
+
+static const unsigned drive_ph6_pins[] = {
+       TEGRA_PIN_PH6,
+};
+
+static const unsigned drive_pk0_pins[] = {
+       TEGRA_PIN_PK0,
+};
+
+static const unsigned drive_pk1_pins[] = {
+       TEGRA_PIN_PK1,
+};
+
+static const unsigned drive_pk2_pins[] = {
+       TEGRA_PIN_PK2,
+};
+
+static const unsigned drive_pk3_pins[] = {
+       TEGRA_PIN_PK3,
+};
+
+static const unsigned drive_pk4_pins[] = {
+       TEGRA_PIN_PK4,
+};
+
+static const unsigned drive_pk5_pins[] = {
+       TEGRA_PIN_PK5,
+};
+
+static const unsigned drive_pk6_pins[] = {
+       TEGRA_PIN_PK6,
+};
+
+static const unsigned drive_pk7_pins[] = {
+       TEGRA_PIN_PK7,
+};
+
+static const unsigned drive_pl0_pins[] = {
+       TEGRA_PIN_PL0,
+};
+
+static const unsigned drive_pl1_pins[] = {
+       TEGRA_PIN_PL1,
+};
+
+static const unsigned drive_pz0_pins[] = {
+       TEGRA_PIN_PZ0,
+};
+
+static const unsigned drive_pz1_pins[] = {
+       TEGRA_PIN_PZ1,
+};
+
+static const unsigned drive_pz2_pins[] = {
+       TEGRA_PIN_PZ2,
+};
+
+static const unsigned drive_pz3_pins[] = {
+       TEGRA_PIN_PZ3,
+};
+
+static const unsigned drive_pz4_pins[] = {
+       TEGRA_PIN_PZ4,
+};
+
+static const unsigned drive_pz5_pins[] = {
+       TEGRA_PIN_PZ5,
+};
+
+static const unsigned drive_sdmmc1_pins[] = {
+       TEGRA_PIN_SDMMC1_CLK_PM0,
+       TEGRA_PIN_SDMMC1_CMD_PM1,
+       TEGRA_PIN_SDMMC1_DAT3_PM2,
+       TEGRA_PIN_SDMMC1_DAT2_PM3,
+       TEGRA_PIN_SDMMC1_DAT1_PM4,
+       TEGRA_PIN_SDMMC1_DAT0_PM5,
+};
+
+static const unsigned drive_sdmmc2_pins[] = {
+};
+
+static const unsigned drive_sdmmc3_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_PP0,
+       TEGRA_PIN_SDMMC3_CMD_PP1,
+       TEGRA_PIN_SDMMC3_DAT3_PP2,
+       TEGRA_PIN_SDMMC3_DAT2_PP3,
+       TEGRA_PIN_SDMMC3_DAT1_PP4,
+       TEGRA_PIN_SDMMC3_DAT0_PP5,
+};
+
+static const unsigned drive_sdmmc4_pins[] = {
+};
+
+enum tegra_mux {
+       TEGRA_MUX_AUD,
+       TEGRA_MUX_BCL,
+       TEGRA_MUX_BLINK,
+       TEGRA_MUX_CCLA,
+       TEGRA_MUX_CEC,
+       TEGRA_MUX_CLDVFS,
+       TEGRA_MUX_CLK,
+       TEGRA_MUX_CORE,
+       TEGRA_MUX_CPU,
+       TEGRA_MUX_DISPLAYA,
+       TEGRA_MUX_DISPLAYB,
+       TEGRA_MUX_DMIC1,
+       TEGRA_MUX_DMIC2,
+       TEGRA_MUX_DMIC3,
+       TEGRA_MUX_DP,
+       TEGRA_MUX_DTV,
+       TEGRA_MUX_EXTPERIPH3,
+       TEGRA_MUX_I2C1,
+       TEGRA_MUX_I2C2,
+       TEGRA_MUX_I2C3,
+       TEGRA_MUX_I2CPMU,
+       TEGRA_MUX_I2CVI,
+       TEGRA_MUX_I2S1,
+       TEGRA_MUX_I2S2,
+       TEGRA_MUX_I2S3,
+       TEGRA_MUX_I2S4A,
+       TEGRA_MUX_I2S4B,
+       TEGRA_MUX_I2S5A,
+       TEGRA_MUX_I2S5B,
+       TEGRA_MUX_IQC0,
+       TEGRA_MUX_IQC1,
+       TEGRA_MUX_JTAG,
+       TEGRA_MUX_PE,
+       TEGRA_MUX_PE0,
+       TEGRA_MUX_PE1,
+       TEGRA_MUX_PMI,
+       TEGRA_MUX_PWM0,
+       TEGRA_MUX_PWM1,
+       TEGRA_MUX_PWM2,
+       TEGRA_MUX_PWM3,
+       TEGRA_MUX_QSPI,
+       TEGRA_MUX_RSVD0,
+       TEGRA_MUX_RSVD1,
+       TEGRA_MUX_RSVD2,
+       TEGRA_MUX_RSVD3,
+       TEGRA_MUX_SATA,
+       TEGRA_MUX_SDMMC1,
+       TEGRA_MUX_SDMMC3,
+       TEGRA_MUX_SHUTDOWN,
+       TEGRA_MUX_SOC,
+       TEGRA_MUX_SOR0,
+       TEGRA_MUX_SOR1,
+       TEGRA_MUX_SPDIF,
+       TEGRA_MUX_SPI1,
+       TEGRA_MUX_SPI2,
+       TEGRA_MUX_SPI3,
+       TEGRA_MUX_SPI4,
+       TEGRA_MUX_SYS,
+       TEGRA_MUX_TOUCH,
+       TEGRA_MUX_UART,
+       TEGRA_MUX_UARTA,
+       TEGRA_MUX_UARTB,
+       TEGRA_MUX_UARTC,
+       TEGRA_MUX_UARTD,
+       TEGRA_MUX_USB,
+       TEGRA_MUX_VGP1,
+       TEGRA_MUX_VGP2,
+       TEGRA_MUX_VGP3,
+       TEGRA_MUX_VGP4,
+       TEGRA_MUX_VGP5,
+       TEGRA_MUX_VGP6,
+       TEGRA_MUX_VIMCLK,
+       TEGRA_MUX_VIMCLK2,
+};
+
+#define FUNCTION(fname)                                        \
+       {                                               \
+               .name = #fname,                         \
+       }
+
+static struct tegra_function tegra210_functions[] = {
+       FUNCTION(aud),
+       FUNCTION(bcl),
+       FUNCTION(blink),
+       FUNCTION(ccla),
+       FUNCTION(cec),
+       FUNCTION(cldvfs),
+       FUNCTION(clk),
+       FUNCTION(core),
+       FUNCTION(cpu),
+       FUNCTION(displaya),
+       FUNCTION(displayb),
+       FUNCTION(dmic1),
+       FUNCTION(dmic2),
+       FUNCTION(dmic3),
+       FUNCTION(dp),
+       FUNCTION(dtv),
+       FUNCTION(extperiph3),
+       FUNCTION(i2c1),
+       FUNCTION(i2c2),
+       FUNCTION(i2c3),
+       FUNCTION(i2cpmu),
+       FUNCTION(i2cvi),
+       FUNCTION(i2s1),
+       FUNCTION(i2s2),
+       FUNCTION(i2s3),
+       FUNCTION(i2s4a),
+       FUNCTION(i2s4b),
+       FUNCTION(i2s5a),
+       FUNCTION(i2s5b),
+       FUNCTION(iqc0),
+       FUNCTION(iqc1),
+       FUNCTION(jtag),
+       FUNCTION(pe),
+       FUNCTION(pe0),
+       FUNCTION(pe1),
+       FUNCTION(pmi),
+       FUNCTION(pwm0),
+       FUNCTION(pwm1),
+       FUNCTION(pwm2),
+       FUNCTION(pwm3),
+       FUNCTION(qspi),
+       FUNCTION(rsvd0),
+       FUNCTION(rsvd1),
+       FUNCTION(rsvd2),
+       FUNCTION(rsvd3),
+       FUNCTION(sata),
+       FUNCTION(sdmmc1),
+       FUNCTION(sdmmc3),
+       FUNCTION(shutdown),
+       FUNCTION(soc),
+       FUNCTION(sor0),
+       FUNCTION(sor1),
+       FUNCTION(spdif),
+       FUNCTION(spi1),
+       FUNCTION(spi2),
+       FUNCTION(spi3),
+       FUNCTION(spi4),
+       FUNCTION(sys),
+       FUNCTION(touch),
+       FUNCTION(uart),
+       FUNCTION(uarta),
+       FUNCTION(uartb),
+       FUNCTION(uartc),
+       FUNCTION(uartd),
+       FUNCTION(usb),
+       FUNCTION(vgp1),
+       FUNCTION(vgp2),
+       FUNCTION(vgp3),
+       FUNCTION(vgp4),
+       FUNCTION(vgp5),
+       FUNCTION(vgp6),
+       FUNCTION(vimclk),
+       FUNCTION(vimclk2),
+};
+
+#define DRV_PINGROUP_REG_A             0x8d4   /* bank 0 */
+#define PINGROUP_REG_A                 0x3000  /* bank 1 */
+
+#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
+#define PINGROUP_REG(r)                        ((r) - PINGROUP_REG_A)
+
+#define PINGROUP_BIT_Y(b)              (b)
+#define PINGROUP_BIT_N(b)              (-1)
+
+#define PINGROUP(pg_name, f0, f1, f2, f3, r, hsm, drvtype, e_io_hv,    \
+                rdrv, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b,      \
+                slwr_w, slwf_b, slwf_w)                                \
+       {                                                               \
+               .name = #pg_name,                                       \
+               .pins = pg_name##_pins,                                 \
+               .npins = ARRAY_SIZE(pg_name##_pins),                    \
+               .funcs = {                                              \
+                       TEGRA_MUX_##f0,                                 \
+                       TEGRA_MUX_##f1,                                 \
+                       TEGRA_MUX_##f2,                                 \
+                       TEGRA_MUX_##f3,                                 \
+               },                                                      \
+               .mux_reg = PINGROUP_REG(r),                             \
+               .mux_bank = 1,                                          \
+               .mux_bit = 0,                                           \
+               .pupd_reg = PINGROUP_REG(r),                            \
+               .pupd_bank = 1,                                         \
+               .pupd_bit = 2,                                          \
+               .tri_reg = PINGROUP_REG(r),                             \
+               .tri_bank = 1,                                          \
+               .tri_bit = 4,                                           \
+               .einput_bit = 6,                                        \
+               .odrain_bit = 11,                                       \
+               .lock_bit = 7,                                          \
+               .ioreset_bit = -1,                                      \
+               .rcv_sel_bit = PINGROUP_BIT_##e_io_hv(10),              \
+               .hsm_bit = PINGROUP_BIT_##hsm(9),                       \
+               .schmitt_bit = 12,                                      \
+               .drvtype_bit = PINGROUP_BIT_##drvtype(13),              \
+               .drv_reg = DRV_PINGROUP_REG(rdrv),                      \
+               .drv_bank = 0,                                          \
+               .lpmd_bit = -1,                                         \
+               .drvdn_bit = drvdn_b,                                   \
+               .drvdn_width = drvdn_w,                                 \
+               .drvup_bit = drvup_b,                                   \
+               .drvup_width = drvup_w,                                 \
+               .slwr_bit = slwr_b,                                     \
+               .slwr_width = slwr_w,                                   \
+               .slwf_bit = slwf_b,                                     \
+               .slwf_width = slwf_w,                                   \
+       }
+
+#define DRV_PINGROUP(pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w,   \
+                    slwr_b, slwr_w, slwf_b, slwf_w)                    \
+       {                                                               \
+               .name = "drive_" #pg_name,                              \
+               .pins = drive_##pg_name##_pins,                         \
+               .npins = ARRAY_SIZE(drive_##pg_name##_pins),            \
+               .mux_reg = -1,                                          \
+               .pupd_reg = -1,                                         \
+               .tri_reg = -1,                                          \
+               .einput_bit = -1,                                       \
+               .odrain_bit = -1,                                       \
+               .lock_bit = -1,                                         \
+               .ioreset_bit = -1,                                      \
+               .rcv_sel_bit = -1,                                      \
+               .drv_reg = DRV_PINGROUP_REG(r),                         \
+               .drv_bank = 0,                                          \
+               .hsm_bit = -1,                                          \
+               .schmitt_bit = -1,                                      \
+               .lpmd_bit = -1,                                         \
+               .drvdn_bit = drvdn_b,                                   \
+               .drvdn_width = drvdn_w,                                 \
+               .drvup_bit = drvup_b,                                   \
+               .drvup_width = drvup_w,                                 \
+               .slwr_bit = slwr_b,                                     \
+               .slwr_width = slwr_w,                                   \
+               .slwf_bit = slwf_b,                                     \
+               .slwf_width = slwf_w,                                   \
+               .drvtype_bit = -1,                                      \
+       }
+
+static const struct tegra_pingroup tegra210_groups[] = {
+       /*       pg_name,              f0,         f1,     f2,    f3,    r,      hsm, drvtype, e_io_hv, rdrv,  drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */
+       PINGROUP(sdmmc1_clk_pm0,       SDMMC1,     RSVD1,  RSVD2, RSVD3, 0x3000, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc1_cmd_pm1,       SDMMC1,     SPI3,   RSVD2, RSVD3, 0x3004, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc1_dat3_pm2,      SDMMC1,     SPI3,   RSVD2, RSVD3, 0x3008, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc1_dat2_pm3,      SDMMC1,     SPI3,   RSVD2, RSVD3, 0x300c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc1_dat1_pm4,      SDMMC1,     SPI3,   RSVD2, RSVD3, 0x3010, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc1_dat0_pm5,      SDMMC1,     RSVD1,  RSVD2, RSVD3, 0x3014, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc3_clk_pp0,       SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x301c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc3_cmd_pp1,       SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3020, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc3_dat0_pp5,      SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3024, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc3_dat1_pp4,      SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3028, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc3_dat2_pp3,      SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x302c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc3_dat3_pp2,      SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3030, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pex_l0_rst_n_pa0,     PE0,        RSVD1,  RSVD2, RSVD3, 0x3038, N,   N,       Y,       0xa5c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pex_l0_clkreq_n_pa1,  PE0,        RSVD1,  RSVD2, RSVD3, 0x303c, N,   N,       Y,       0xa58, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pex_wake_n_pa2,       PE,         RSVD1,  RSVD2, RSVD3, 0x3040, N,   N,       Y,       0xa68, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pex_l1_rst_n_pa3,     PE1,        RSVD1,  RSVD2, RSVD3, 0x3044, N,   N,       Y,       0xa64, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pex_l1_clkreq_n_pa4,  PE1,        RSVD1,  RSVD2, RSVD3, 0x3048, N,   N,       Y,       0xa60, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(sata_led_active_pa5,  SATA,       RSVD1,  RSVD2, RSVD3, 0x304c, N,   N,       N,       0xa94, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(spi1_mosi_pc0,        SPI1,       RSVD1,  RSVD2, RSVD3, 0x3050, Y,   Y,       N,       0xae0, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi1_miso_pc1,        SPI1,       RSVD1,  RSVD2, RSVD3, 0x3054, Y,   Y,       N,       0xadc, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi1_sck_pc2,         SPI1,       RSVD1,  RSVD2, RSVD3, 0x3058, Y,   Y,       N,       0xae4, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi1_cs0_pc3,         SPI1,       RSVD1,  RSVD2, RSVD3, 0x305c, Y,   Y,       N,       0xad4, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi1_cs1_pc4,         SPI1,       RSVD1,  RSVD2, RSVD3, 0x3060, Y,   Y,       N,       0xad8, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi2_mosi_pb4,        SPI2,       DTV,    RSVD2, RSVD3, 0x3064, Y,   Y,       N,       0xaf4, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi2_miso_pb5,        SPI2,       DTV,    RSVD2, RSVD3, 0x3068, Y,   Y,       N,       0xaf0, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi2_sck_pb6,         SPI2,       DTV,    RSVD2, RSVD3, 0x306c, Y,   Y,       N,       0xaf8, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi2_cs0_pb7,         SPI2,       DTV,    RSVD2, RSVD3, 0x3070, Y,   Y,       N,       0xae8, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi2_cs1_pdd0,        SPI2,       RSVD1,  RSVD2, RSVD3, 0x3074, Y,   Y,       N,       0xaec, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi4_mosi_pc7,        SPI4,       RSVD1,  RSVD2, RSVD3, 0x3078, Y,   Y,       N,       0xb04, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi4_miso_pd0,        SPI4,       RSVD1,  RSVD2, RSVD3, 0x307c, Y,   Y,       N,       0xb00, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi4_sck_pc5,         SPI4,       RSVD1,  RSVD2, RSVD3, 0x3080, Y,   Y,       N,       0xb08, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi4_cs0_pc6,         SPI4,       RSVD1,  RSVD2, RSVD3, 0x3084, Y,   Y,       N,       0xafc, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(qspi_sck_pee0,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x3088, Y,   Y,       N,       0xa90, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(qspi_cs_n_pee1,       QSPI,       RSVD1,  RSVD2, RSVD3, 0x308c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(qspi_io0_pee2,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x3090, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(qspi_io1_pee3,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x3094, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(qspi_io2_pee4,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x3098, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(qspi_io3_pee5,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x309c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(dmic1_clk_pe0,        DMIC1,      I2S3,   RSVD2, RSVD3, 0x30a4, N,   N,       N,       0x984, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dmic1_dat_pe1,        DMIC1,      I2S3,   RSVD2, RSVD3, 0x30a8, N,   N,       N,       0x988, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dmic2_clk_pe2,        DMIC2,      I2S3,   RSVD2, RSVD3, 0x30ac, N,   N,       N,       0x98c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dmic2_dat_pe3,        DMIC2,      I2S3,   RSVD2, RSVD3, 0x30b0, N,   N,       N,       0x990, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dmic3_clk_pe4,        DMIC3,      I2S5A,  RSVD2, RSVD3, 0x30b4, N,   N,       N,       0x994, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dmic3_dat_pe5,        DMIC3,      I2S5A,  RSVD2, RSVD3, 0x30b8, N,   N,       N,       0x998, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gen1_i2c_scl_pj1,     I2C1,       RSVD1,  RSVD2, RSVD3, 0x30bc, N,   N,       Y,       0x9a8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gen1_i2c_sda_pj0,     I2C1,       RSVD1,  RSVD2, RSVD3, 0x30c0, N,   N,       Y,       0x9ac, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gen2_i2c_scl_pj2,     I2C2,       RSVD1,  RSVD2, RSVD3, 0x30c4, N,   N,       Y,       0x9b0, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gen2_i2c_sda_pj3,     I2C2,       RSVD1,  RSVD2, RSVD3, 0x30c8, N,   N,       Y,       0x9b4, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gen3_i2c_scl_pf0,     I2C3,       RSVD1,  RSVD2, RSVD3, 0x30cc, N,   N,       Y,       0x9b8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gen3_i2c_sda_pf1,     I2C3,       RSVD1,  RSVD2, RSVD3, 0x30d0, N,   N,       Y,       0x9bc, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam_i2c_scl_ps2,      I2C3,       I2CVI,  RSVD2, RSVD3, 0x30d4, N,   N,       Y,       0x934, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam_i2c_sda_ps3,      I2C3,       I2CVI,  RSVD2, RSVD3, 0x30d8, N,   N,       Y,       0x938, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pwr_i2c_scl_py3,      I2CPMU,     RSVD1,  RSVD2, RSVD3, 0x30dc, N,   N,       Y,       0xa6c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pwr_i2c_sda_py4,      I2CPMU,     RSVD1,  RSVD2, RSVD3, 0x30e0, N,   N,       Y,       0xa70, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart1_tx_pu0,         UARTA,      RSVD1,  RSVD2, RSVD3, 0x30e4, N,   N,       N,       0xb28, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart1_rx_pu1,         UARTA,      RSVD1,  RSVD2, RSVD3, 0x30e8, N,   N,       N,       0xb24, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart1_rts_pu2,        UARTA,      RSVD1,  RSVD2, RSVD3, 0x30ec, N,   N,       N,       0xb20, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart1_cts_pu3,        UARTA,      RSVD1,  RSVD2, RSVD3, 0x30f0, N,   N,       N,       0xb1c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart2_tx_pg0,         UARTB,      I2S4A,  SPDIF, UART,  0x30f4, N,   N,       N,       0xb38, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart2_rx_pg1,         UARTB,      I2S4A,  SPDIF, UART,  0x30f8, N,   N,       N,       0xb34, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart2_rts_pg2,        UARTB,      I2S4A,  RSVD2, UART,  0x30fc, N,   N,       N,       0xb30, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart2_cts_pg3,        UARTB,      I2S4A,  RSVD2, UART,  0x3100, N,   N,       N,       0xb2c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart3_tx_pd1,         UARTC,      SPI4,   RSVD2, RSVD3, 0x3104, N,   N,       N,       0xb48, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart3_rx_pd2,         UARTC,      SPI4,   RSVD2, RSVD3, 0x3108, N,   N,       N,       0xb44, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart3_rts_pd3,        UARTC,      SPI4,   RSVD2, RSVD3, 0x310c, N,   N,       N,       0xb40, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart3_cts_pd4,        UARTC,      SPI4,   RSVD2, RSVD3, 0x3110, N,   N,       N,       0xb3c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart4_tx_pi4,         UARTD,      UART,   RSVD2, RSVD3, 0x3114, N,   N,       N,       0xb58, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart4_rx_pi5,         UARTD,      UART,   RSVD2, RSVD3, 0x3118, N,   N,       N,       0xb54, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart4_rts_pi6,        UARTD,      UART,   RSVD2, RSVD3, 0x311c, N,   N,       N,       0xb50, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart4_cts_pi7,        UARTD,      UART,   RSVD2, RSVD3, 0x3120, N,   N,       N,       0xb4c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dap1_fs_pb0,          I2S1,       RSVD1,  RSVD2, RSVD3, 0x3124, Y,   Y,       N,       0x95c, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap1_din_pb1,         I2S1,       RSVD1,  RSVD2, RSVD3, 0x3128, Y,   Y,       N,       0x954, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap1_dout_pb2,        I2S1,       RSVD1,  RSVD2, RSVD3, 0x312c, Y,   Y,       N,       0x958, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap1_sclk_pb3,        I2S1,       RSVD1,  RSVD2, RSVD3, 0x3130, Y,   Y,       N,       0x960, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap2_fs_paa0,         I2S2,       RSVD1,  RSVD2, RSVD3, 0x3134, Y,   Y,       N,       0x96c, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap2_din_paa2,        I2S2,       RSVD1,  RSVD2, RSVD3, 0x3138, Y,   Y,       N,       0x964, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap2_dout_paa3,       I2S2,       RSVD1,  RSVD2, RSVD3, 0x313c, Y,   Y,       N,       0x968, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap2_sclk_paa1,       I2S2,       RSVD1,  RSVD2, RSVD3, 0x3140, Y,   Y,       N,       0x970, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap4_fs_pj4,          I2S4B,      RSVD1,  RSVD2, RSVD3, 0x3144, N,   N,       N,       0x97c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dap4_din_pj5,         I2S4B,      RSVD1,  RSVD2, RSVD3, 0x3148, N,   N,       N,       0x974, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dap4_dout_pj6,        I2S4B,      RSVD1,  RSVD2, RSVD3, 0x314c, N,   N,       N,       0x978, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dap4_sclk_pj7,        I2S4B,      RSVD1,  RSVD2, RSVD3, 0x3150, N,   N,       N,       0x980, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam1_mclk_ps0,        EXTPERIPH3, RSVD1,  RSVD2, RSVD3, 0x3154, N,   N,       N,       0x918, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam2_mclk_ps1,        EXTPERIPH3, RSVD1,  RSVD2, RSVD3, 0x3158, N,   N,       N,       0x924, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(jtag_rtck,            JTAG,       RSVD1,  RSVD2, RSVD3, 0x315c, N,   N,       N,       0xa2c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(clk_32k_in,           CLK,        RSVD1,  RSVD2, RSVD3, 0x3160, N,   N,       N,       0x940, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(clk_32k_out_py5,      SOC,        BLINK,  RSVD2, RSVD3, 0x3164, N,   N,       N,       0x944, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(batt_bcl,             BCL,        RSVD1,  RSVD2, RSVD3, 0x3168, N,   N,       Y,       0x8f8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(clk_req,              SYS,        RSVD1,  RSVD2, RSVD3, 0x316c, N,   N,       N,       0x948, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cpu_pwr_req,          CPU,        RSVD1,  RSVD2, RSVD3, 0x3170, N,   N,       N,       0x950, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pwr_int_n,            PMI,        RSVD1,  RSVD2, RSVD3, 0x3174, N,   N,       N,       0xa74, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(shutdown,             SHUTDOWN,   RSVD1,  RSVD2, RSVD3, 0x3178, N,   N,       N,       0xac8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(core_pwr_req,         CORE,       RSVD1,  RSVD2, RSVD3, 0x317c, N,   N,       N,       0x94c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(aud_mclk_pbb0,        AUD,        RSVD1,  RSVD2, RSVD3, 0x3180, N,   N,       N,       0x8f4, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dvfs_pwm_pbb1,        RSVD0,      CLDVFS, SPI3,  RSVD3, 0x3184, N,   N,       N,       0x9a4, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dvfs_clk_pbb2,        RSVD0,      CLDVFS, SPI3,  RSVD3, 0x3188, N,   N,       N,       0x9a0, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gpio_x1_aud_pbb3,     RSVD0,      RSVD1,  SPI3,  RSVD3, 0x318c, N,   N,       N,       0xa14, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gpio_x3_aud_pbb4,     RSVD0,      RSVD1,  SPI3,  RSVD3, 0x3190, N,   N,       N,       0xa18, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pcc7,                 RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3194, N,   N,       Y,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(hdmi_cec_pcc0,        CEC,        RSVD1,  RSVD2, RSVD3, 0x3198, N,   N,       Y,       0xa24, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(hdmi_int_dp_hpd_pcc1, DP,         RSVD1,  RSVD2, RSVD3, 0x319c, N,   N,       Y,       0xa28, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(spdif_out_pcc2,       SPDIF,      RSVD1,  RSVD2, RSVD3, 0x31a0, N,   N,       N,       0xad0, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(spdif_in_pcc3,        SPDIF,      RSVD1,  RSVD2, RSVD3, 0x31a4, N,   N,       N,       0xacc, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(usb_vbus_en0_pcc4,    USB,        RSVD1,  RSVD2, RSVD3, 0x31a8, N,   N,       Y,       0xb5c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(usb_vbus_en1_pcc5,    USB,        RSVD1,  RSVD2, RSVD3, 0x31ac, N,   N,       Y,       0xb60, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dp_hpd0_pcc6,         DP,         RSVD1,  RSVD2, RSVD3, 0x31b0, N,   N,       N,       0x99c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(wifi_en_ph0,          RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31b4, N,   N,       N,       0xb64, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(wifi_rst_ph1,         RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31b8, N,   N,       N,       0xb68, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(wifi_wake_ap_ph2,     RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31bc, N,   N,       N,       0xb6c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(ap_wake_bt_ph3,       RSVD0,      UARTB,  SPDIF, RSVD3, 0x31c0, N,   N,       N,       0x8ec, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(bt_rst_ph4,           RSVD0,      UARTB,  SPDIF, RSVD3, 0x31c4, N,   N,       N,       0x8fc, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(bt_wake_ap_ph5,       RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31c8, N,   N,       N,       0x900, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(ap_wake_nfc_ph7,      RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31cc, N,   N,       N,       0x8f0, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(nfc_en_pi0,           RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31d0, N,   N,       N,       0xa50, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(nfc_int_pi1,          RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31d4, N,   N,       N,       0xa54, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gps_en_pi2,           RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31d8, N,   N,       N,       0xa1c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gps_rst_pi3,          RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31dc, N,   N,       N,       0xa20, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam_rst_ps4,          VGP1,       RSVD1,  RSVD2, RSVD3, 0x31e0, N,   N,       N,       0x93c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam_af_en_ps5,        VIMCLK,     VGP2,   RSVD2, RSVD3, 0x31e4, N,   N,       N,       0x92c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam_flash_en_ps6,     VIMCLK,     VGP3,   RSVD2, RSVD3, 0x31e8, N,   N,       N,       0x930, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam1_pwdn_ps7,        VGP4,       RSVD1,  RSVD2, RSVD3, 0x31ec, N,   N,       N,       0x91c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam2_pwdn_pt0,        VGP5,       RSVD1,  RSVD2, RSVD3, 0x31f0, N,   N,       N,       0x928, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam1_strobe_pt1,      VGP6,       RSVD1,  RSVD2, RSVD3, 0x31f4, N,   N,       N,       0x920, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(lcd_te_py2,           DISPLAYA,   RSVD1,  RSVD2, RSVD3, 0x31f8, N,   N,       N,       0xa44, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(lcd_bl_pwm_pv0,       DISPLAYA,   PWM0,   SOR0,  RSVD3, 0x31fc, N,   N,       N,       0xa34, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(lcd_bl_en_pv1,        RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3200, N,   N,       N,       0xa30, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(lcd_rst_pv2,          RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3204, N,   N,       N,       0xa40, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(lcd_gpio1_pv3,        DISPLAYB,   RSVD1,  RSVD2, RSVD3, 0x3208, N,   N,       N,       0xa38, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(lcd_gpio2_pv4,        DISPLAYB,   PWM1,   RSVD2, SOR1,  0x320c, N,   N,       N,       0xa3c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(ap_ready_pv5,         RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3210, N,   N,       N,       0x8e8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(touch_rst_pv6,        RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3214, N,   N,       N,       0xb18, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(touch_clk_pv7,        TOUCH,      RSVD1,  RSVD2, RSVD3, 0x3218, N,   N,       N,       0xb10, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(modem_wake_ap_px0,    RSVD0,      RSVD1,  RSVD2, RSVD3, 0x321c, N,   N,       N,       0xa48, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(touch_int_px1,        RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3220, N,   N,       N,       0xb14, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(motion_int_px2,       RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3224, N,   N,       N,       0xa4c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(als_prox_int_px3,     RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3228, N,   N,       N,       0x8e4, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(temp_alert_px4,       RSVD0,      RSVD1,  RSVD2, RSVD3, 0x322c, N,   N,       N,       0xb0c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(button_power_on_px5,  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3230, N,   N,       N,       0x908, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(button_vol_up_px6,    RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3234, N,   N,       N,       0x914, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(button_vol_down_px7,  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3238, N,   N,       N,       0x910, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(button_slide_sw_py0,  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x323c, N,   N,       N,       0x90c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(button_home_py1,      RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3240, N,   N,       N,       0x904, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pa6,                  SATA,       RSVD1,  RSVD2, RSVD3, 0x3244, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pe6,                  RSVD0,      I2S5A,  PWM2,  RSVD3, 0x3248, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pe7,                  RSVD0,      I2S5A,  PWM3,  RSVD3, 0x324c, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(ph6,                  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3250, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk0,                  IQC0,       I2S5B,  RSVD2, RSVD3, 0x3254, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk1,                  IQC0,       I2S5B,  RSVD2, RSVD3, 0x3258, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk2,                  IQC0,       I2S5B,  RSVD2, RSVD3, 0x325c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk3,                  IQC0,       I2S5B,  RSVD2, RSVD3, 0x3260, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk4,                  IQC1,       RSVD1,  RSVD2, RSVD3, 0x3264, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk5,                  IQC1,       RSVD1,  RSVD2, RSVD3, 0x3268, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk6,                  IQC1,       RSVD1,  RSVD2, RSVD3, 0x326c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk7,                  IQC1,       RSVD1,  RSVD2, RSVD3, 0x3270, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pl0,                  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3274, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pl1,                  SOC,        RSVD1,  RSVD2, RSVD3, 0x3278, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pz0,                  VIMCLK2,    RSVD1,  RSVD2, RSVD3, 0x327c, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pz1,                  VIMCLK2,    SDMMC1, RSVD2, RSVD3, 0x3280, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pz2,                  SDMMC3,     CCLA,   RSVD2, RSVD3, 0x3284, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pz3,                  SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3288, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pz4,                  SDMMC1,     RSVD1,  RSVD2, RSVD3, 0x328c, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pz5,                  SOC,        RSVD1,  RSVD2, RSVD3, 0x3290, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+
+       /* pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */
+       DRV_PINGROUP(pa6,    0x9c0, 12, 5,  20, 5,  -1, -1, -1, -1),
+       DRV_PINGROUP(pcc7,   0x9c4, 12, 5,  20, 5,  -1, -1, -1, -1),
+       DRV_PINGROUP(pe6,    0x9c8, 12, 5,  20, 5,  -1, -1, -1, -1),
+       DRV_PINGROUP(pe7,    0x9cc, 12, 5,  20, 5,  -1, -1, -1, -1),
+       DRV_PINGROUP(ph6,    0x9d0, 12, 5,  20, 5,  -1, -1, -1, -1),
+       DRV_PINGROUP(pk0,    0x9d4, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk1,    0x9d8, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk2,    0x9dc, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk3,    0x9e0, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk4,    0x9e4, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk5,    0x9e8, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk6,    0x9ec, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk7,    0x9f0, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pl0,    0x9f4, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pl1,    0x9f8, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pz0,    0x9fc, 12, 7,  20, 7,  -1, -1, -1, -1),
+       DRV_PINGROUP(pz1,    0xa00, 12, 7,  20, 7,  -1, -1, -1, -1),
+       DRV_PINGROUP(pz2,    0xa04, 12, 7,  20, 7,  -1, -1, -1, -1),
+       DRV_PINGROUP(pz3,    0xa08, 12, 7,  20, 7,  -1, -1, -1, -1),
+       DRV_PINGROUP(pz4,    0xa0c, 12, 7,  20, 7,  -1, -1, -1, -1),
+       DRV_PINGROUP(pz5,    0xa10, 12, 7,  20, 7,  -1, -1, -1, -1),
+       DRV_PINGROUP(sdmmc1, 0xa98, 12, 7,  20, 7,  28, 2,  30, 2),
+       DRV_PINGROUP(sdmmc2, 0xa9c, 2,  6,  8,  6,  28, 2,  30, 2),
+       DRV_PINGROUP(sdmmc3, 0xab0, 12, 7,  20, 7,  28, 2,  30, 2),
+       DRV_PINGROUP(sdmmc4, 0xab4, 2,  6,  8,  6,  28, 2,  30, 2),
+};
+
+static const struct tegra_pinctrl_soc_data tegra210_pinctrl = {
+       .ngpios = NUM_GPIOS,
+       .pins = tegra210_pins,
+       .npins = ARRAY_SIZE(tegra210_pins),
+       .functions = tegra210_functions,
+       .nfunctions = ARRAY_SIZE(tegra210_functions),
+       .groups = tegra210_groups,
+       .ngroups = ARRAY_SIZE(tegra210_groups),
+       .hsm_in_mux = true,
+       .schmitt_in_mux = true,
+       .drvtype_in_mux = true,
+};
+
+static int tegra210_pinctrl_probe(struct platform_device *pdev)
+{
+       return tegra_pinctrl_probe(pdev, &tegra210_pinctrl);
+}
+
+static const struct of_device_id tegra210_pinctrl_of_match[] = {
+       { .compatible = "nvidia,tegra210-pinmux", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, tegra210_pinctrl_of_match);
+
+static struct platform_driver tegra210_pinctrl_driver = {
+       .driver = {
+               .name = "tegra210-pinctrl",
+               .of_match_table = tegra210_pinctrl_of_match,
+       },
+       .probe = tegra210_pinctrl_probe,
+       .remove = tegra_pinctrl_remove,
+};
+module_platform_driver(tegra210_pinctrl_driver);
+
+MODULE_AUTHOR("NVIDIA");
+MODULE_DESCRIPTION("NVIDIA Tegra210 pinctrl driver");
+MODULE_LICENSE("GPL v2");
index f6edc2ff5494d5ddeab85ad02e3af3e130f150c9..47b2fd8bb2e9daba9b0209869fc211add86997fc 100644 (file)
@@ -2108,70 +2108,69 @@ static struct tegra_function tegra30_functions[] = {
 #define DRV_PINGROUP_REG_A             0x868   /* bank 0 */
 #define PINGROUP_REG_A                 0x3000  /* bank 1 */
 
+#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
 #define PINGROUP_REG(r)                        ((r) - PINGROUP_REG_A)
 
 #define PINGROUP_BIT_Y(b)              (b)
 #define PINGROUP_BIT_N(b)              (-1)
 
-#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior)          \
-       {                                                       \
-               .name = #pg_name,                               \
-               .pins = pg_name##_pins,                         \
-               .npins = ARRAY_SIZE(pg_name##_pins),            \
-               .funcs = {                                      \
-                       TEGRA_MUX_##f0,                         \
-                       TEGRA_MUX_##f1,                         \
-                       TEGRA_MUX_##f2,                         \
-                       TEGRA_MUX_##f3,                         \
-               },                                              \
-               .mux_reg = PINGROUP_REG(r),                     \
-               .mux_bank = 1,                                  \
-               .mux_bit = 0,                                   \
-               .pupd_reg = PINGROUP_REG(r),                    \
-               .pupd_bank = 1,                                 \
-               .pupd_bit = 2,                                  \
-               .tri_reg = PINGROUP_REG(r),                     \
-               .tri_bank = 1,                                  \
-               .tri_bit = 4,                                   \
-               .einput_bit = PINGROUP_BIT_Y(5),                \
-               .odrain_bit = PINGROUP_BIT_##od(6),             \
-               .lock_bit = PINGROUP_BIT_Y(7),                  \
-               .ioreset_bit = PINGROUP_BIT_##ior(8),           \
-               .rcv_sel_bit = -1,                              \
-               .drv_reg = -1,                                  \
+#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior)                  \
+       {                                                               \
+               .name = #pg_name,                                       \
+               .pins = pg_name##_pins,                                 \
+               .npins = ARRAY_SIZE(pg_name##_pins),                    \
+               .funcs = {                                              \
+                       TEGRA_MUX_##f0,                                 \
+                       TEGRA_MUX_##f1,                                 \
+                       TEGRA_MUX_##f2,                                 \
+                       TEGRA_MUX_##f3,                                 \
+               },                                                      \
+               .mux_reg = PINGROUP_REG(r),                             \
+               .mux_bank = 1,                                          \
+               .mux_bit = 0,                                           \
+               .pupd_reg = PINGROUP_REG(r),                            \
+               .pupd_bank = 1,                                         \
+               .pupd_bit = 2,                                          \
+               .tri_reg = PINGROUP_REG(r),                             \
+               .tri_bank = 1,                                          \
+               .tri_bit = 4,                                           \
+               .einput_bit = 5,                                        \
+               .odrain_bit = PINGROUP_BIT_##od(6),                     \
+               .lock_bit = 7,                                          \
+               .ioreset_bit = PINGROUP_BIT_##ior(8),                   \
+               .rcv_sel_bit = -1,                                      \
+               .drv_reg = -1,                                          \
        }
 
-#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
-
-#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b,     \
-                    drvdn_b, drvdn_w, drvup_b, drvup_w,        \
-                    slwr_b, slwr_w, slwf_b, slwf_w)            \
-       {                                                       \
-               .name = "drive_" #pg_name,                      \
-               .pins = drive_##pg_name##_pins,                 \
-               .npins = ARRAY_SIZE(drive_##pg_name##_pins),    \
-               .mux_reg = -1,                                  \
-               .pupd_reg = -1,                                 \
-               .tri_reg = -1,                                  \
-               .einput_bit = -1,                               \
-               .odrain_bit = -1,                               \
-               .lock_bit = -1,                                 \
-               .ioreset_bit = -1,                              \
-               .rcv_sel_bit = -1,                              \
-               .drv_reg = DRV_PINGROUP_REG(r),                 \
-               .drv_bank = 0,                                  \
-               .hsm_bit = hsm_b,                               \
-               .schmitt_bit = schmitt_b,                       \
-               .lpmd_bit = lpmd_b,                             \
-               .drvdn_bit = drvdn_b,                           \
-               .drvdn_width = drvdn_w,                         \
-               .drvup_bit = drvup_b,                           \
-               .drvup_width = drvup_w,                         \
-               .slwr_bit = slwr_b,                             \
-               .slwr_width = slwr_w,                           \
-               .slwf_bit = slwf_b,                             \
-               .slwf_width = slwf_w,                           \
-               .drvtype_bit = -1,                              \
+#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b,    \
+                    drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w,         \
+                    slwf_b, slwf_w)                                    \
+       {                                                               \
+               .name = "drive_" #pg_name,                              \
+               .pins = drive_##pg_name##_pins,                         \
+               .npins = ARRAY_SIZE(drive_##pg_name##_pins),            \
+               .mux_reg = -1,                                          \
+               .pupd_reg = -1,                                         \
+               .tri_reg = -1,                                          \
+               .einput_bit = -1,                                       \
+               .odrain_bit = -1,                                       \
+               .lock_bit = -1,                                         \
+               .ioreset_bit = -1,                                      \
+               .rcv_sel_bit = -1,                                      \
+               .drv_reg = DRV_PINGROUP_REG(r),                         \
+               .drv_bank = 0,                                          \
+               .hsm_bit = hsm_b,                                       \
+               .schmitt_bit = schmitt_b,                               \
+               .lpmd_bit = lpmd_b,                                     \
+               .drvdn_bit = drvdn_b,                                   \
+               .drvdn_width = drvdn_w,                                 \
+               .drvup_bit = drvup_b,                                   \
+               .drvup_width = drvup_w,                                 \
+               .slwr_bit = slwr_b,                                     \
+               .slwr_width = slwr_w,                                   \
+               .slwf_bit = slwf_b,                                     \
+               .slwf_width = slwf_w,                                   \
+               .drvtype_bit = -1,                                      \
        }
 
 static const struct tegra_pingroup tegra30_groups[] = {
@@ -2477,6 +2476,9 @@ static const struct tegra_pinctrl_soc_data tegra30_pinctrl = {
        .nfunctions = ARRAY_SIZE(tegra30_functions),
        .groups = tegra30_groups,
        .ngroups = ARRAY_SIZE(tegra30_groups),
+       .hsm_in_mux = false,
+       .schmitt_in_mux = false,
+       .drvtype_in_mux = false,
 };
 
 static int tegra30_pinctrl_probe(struct platform_device *pdev)
index fab6aafa6a9f4466984ba83a3cf0719a1df7b2dc..8a8911bb883a2007d83f6fc53bacfc440ba5c103 100644 (file)
@@ -969,7 +969,7 @@ static int tz1090_pdc_pinctrl_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id tz1090_pdc_pinctrl_of_match[] = {
+static const struct of_device_id tz1090_pdc_pinctrl_of_match[] = {
        { .compatible = "img,tz1090-pdc-pinctrl", },
        { },
 };
index 8bd73075f9dd3e658c7e41210eb90efec676589e..fc5594a530c2f9770f0e8db92c7874b91a643c37 100644 (file)
@@ -1984,7 +1984,7 @@ static int tz1090_pinctrl_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id tz1090_pinctrl_of_match[] = {
+static const struct of_device_id tz1090_pinctrl_of_match[] = {
        { .compatible = "img,tz1090-pinctrl", },
        { },
 };
index a535f9c23678b1a73548a8fc5950078170704c4b..f3d800f796c2f48c4a7c6c5e6b71d23dbc8cbb31 100644 (file)
@@ -193,11 +193,11 @@ static int msm_config_reg(struct msm_pinctrl *pctrl,
                *mask = 7;
                break;
        case PIN_CONFIG_OUTPUT:
+       case PIN_CONFIG_INPUT_ENABLE:
                *bit = g->oe_bit;
                *mask = 1;
                break;
        default:
-               dev_err(pctrl->dev, "Invalid config param %04x\n", param);
                return -ENOTSUPP;
        }
 
@@ -261,10 +261,14 @@ static int msm_config_group_get(struct pinctrl_dev *pctldev,
                val = readl(pctrl->regs + g->io_reg);
                arg = !!(val & BIT(g->in_bit));
                break;
+       case PIN_CONFIG_INPUT_ENABLE:
+               /* Pin is output */
+               if (arg)
+                       return -EINVAL;
+               arg = 1;
+               break;
        default:
-               dev_err(pctrl->dev, "Unsupported config parameter: %x\n",
-                       param);
-               return -EINVAL;
+               return -ENOTSUPP;
        }
 
        *config = pinconf_to_config_packed(param, arg);
@@ -333,6 +337,10 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev,
                        /* enable output */
                        arg = 1;
                        break;
+               case PIN_CONFIG_INPUT_ENABLE:
+                       /* disable output */
+                       arg = 0;
+                       break;
                default:
                        dev_err(pctrl->dev, "Unsupported config parameter: %x\n",
                                param);
@@ -357,6 +365,7 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev,
 }
 
 static const struct pinconf_ops msm_pinconf_ops = {
+       .is_generic             = true,
        .pin_config_group_get   = msm_config_group_get,
        .pin_config_group_set   = msm_config_group_set,
 };
index 0f11a26d932b616611abfdd5aef92c0fb6c9c872..b2d22218a2582f94b2c5d0274843fa0c2d3d7162 100644 (file)
@@ -810,6 +810,7 @@ static int pmic_gpio_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id pmic_gpio_of_match[] = {
+       { .compatible = "qcom,pm8916-gpio" },   /* 4 GPIO's */
        { .compatible = "qcom,pm8941-gpio" },   /* 36 GPIO's */
        { .compatible = "qcom,pma8084-gpio" },  /* 22 GPIO's */
        { },
index a8924dba335e51861475dedb84566e2bfbc8976e..8f36c5f9194903fd8433736499a03a61afbfb2ac 100644 (file)
@@ -925,6 +925,7 @@ static int pmic_mpp_remove(struct platform_device *pdev)
 
 static const struct of_device_id pmic_mpp_of_match[] = {
        { .compatible = "qcom,pm8841-mpp" },    /* 4 MPP's */
+       { .compatible = "qcom,pm8916-mpp" },    /* 4 MPP's */
        { .compatible = "qcom,pm8941-mpp" },    /* 8 MPP's */
        { .compatible = "qcom,pma8084-mpp" },   /* 8 MPP's */
        { },
index c8f83f96546c0741f36ac96b9ff2522c7d2e8065..0b7afa50121a249d385fddd5d1ae9a906a0f322b 100644 (file)
@@ -1240,6 +1240,159 @@ const struct samsung_pin_ctrl exynos5420_pin_ctrl[] __initconst = {
        },
 };
 
+/* pin banks of exynos5433 pin-controller - ALIVE */
+static const struct samsung_pin_bank_data exynos5433_pin_banks0[] = {
+       EXYNOS_PIN_BANK_EINTW(8, 0x000, "gpa0", 0x00),
+       EXYNOS_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04),
+       EXYNOS_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08),
+       EXYNOS_PIN_BANK_EINTW(8, 0x060, "gpa3", 0x0c),
+};
+
+/* pin banks of exynos5433 pin-controller - AUD */
+static const struct samsung_pin_bank_data exynos5433_pin_banks1[] = {
+       EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00),
+       EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04),
+};
+
+/* pin banks of exynos5433 pin-controller - CPIF */
+static const struct samsung_pin_bank_data exynos5433_pin_banks2[] = {
+       EXYNOS_PIN_BANK_EINTG(2, 0x000, "gpv6", 0x00),
+};
+
+/* pin banks of exynos5433 pin-controller - eSE */
+static const struct samsung_pin_bank_data exynos5433_pin_banks3[] = {
+       EXYNOS_PIN_BANK_EINTG(3, 0x000, "gpj2", 0x00),
+};
+
+/* pin banks of exynos5433 pin-controller - FINGER */
+static const struct samsung_pin_bank_data exynos5433_pin_banks4[] = {
+       EXYNOS_PIN_BANK_EINTG(4, 0x000, "gpd5", 0x00),
+};
+
+/* pin banks of exynos5433 pin-controller - FSYS */
+static const struct samsung_pin_bank_data exynos5433_pin_banks5[] = {
+       EXYNOS_PIN_BANK_EINTG(6, 0x000, "gph1", 0x00),
+       EXYNOS_PIN_BANK_EINTG(7, 0x020, "gpr4", 0x04),
+       EXYNOS_PIN_BANK_EINTG(5, 0x040, "gpr0", 0x08),
+       EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpr1", 0x0c),
+       EXYNOS_PIN_BANK_EINTG(2, 0x080, "gpr2", 0x10),
+       EXYNOS_PIN_BANK_EINTG(8, 0x0a0, "gpr3", 0x14),
+};
+
+/* pin banks of exynos5433 pin-controller - IMEM */
+static const struct samsung_pin_bank_data exynos5433_pin_banks6[] = {
+       EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpf0", 0x00),
+};
+
+/* pin banks of exynos5433 pin-controller - NFC */
+static const struct samsung_pin_bank_data exynos5433_pin_banks7[] = {
+       EXYNOS_PIN_BANK_EINTG(3, 0x000, "gpj0", 0x00),
+};
+
+/* pin banks of exynos5433 pin-controller - PERIC */
+static const struct samsung_pin_bank_data exynos5433_pin_banks8[] = {
+       EXYNOS_PIN_BANK_EINTG(6, 0x000, "gpv7", 0x00),
+       EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpb0", 0x04),
+       EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpc0", 0x08),
+       EXYNOS_PIN_BANK_EINTG(2, 0x060, "gpc1", 0x0c),
+       EXYNOS_PIN_BANK_EINTG(6, 0x080, "gpc2", 0x10),
+       EXYNOS_PIN_BANK_EINTG(8, 0x0a0, "gpc3", 0x14),
+       EXYNOS_PIN_BANK_EINTG(2, 0x0c0, "gpg0", 0x18),
+       EXYNOS_PIN_BANK_EINTG(4, 0x0e0, "gpd0", 0x1c),
+       EXYNOS_PIN_BANK_EINTG(6, 0x100, "gpd1", 0x20),
+       EXYNOS_PIN_BANK_EINTG(8, 0x120, "gpd2", 0x24),
+       EXYNOS_PIN_BANK_EINTG(5, 0x140, "gpd4", 0x28),
+       EXYNOS_PIN_BANK_EINTG(2, 0x160, "gpd8", 0x2c),
+       EXYNOS_PIN_BANK_EINTG(7, 0x180, "gpd6", 0x30),
+       EXYNOS_PIN_BANK_EINTG(3, 0x1a0, "gpd7", 0x34),
+       EXYNOS_PIN_BANK_EINTG(5, 0x1c0, "gpg1", 0x38),
+       EXYNOS_PIN_BANK_EINTG(2, 0x1e0, "gpg2", 0x3c),
+       EXYNOS_PIN_BANK_EINTG(8, 0x200, "gpg3", 0x40),
+};
+
+/* pin banks of exynos5433 pin-controller - TOUCH */
+static const struct samsung_pin_bank_data exynos5433_pin_banks9[] = {
+       EXYNOS_PIN_BANK_EINTG(3, 0x000, "gpj1", 0x00),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos5433 SoC. Exynos5433 SoC includes
+ * ten gpio/pin-mux/pinconfig controllers.
+ */
+const struct samsung_pin_ctrl exynos5433_pin_ctrl[] = {
+       {
+               /* pin-controller instance 0 data */
+               .pin_banks      = exynos5433_pin_banks0,
+               .nr_banks       = ARRAY_SIZE(exynos5433_pin_banks0),
+               .eint_wkup_init = exynos_eint_wkup_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
+       }, {
+               /* pin-controller instance 1 data */
+               .pin_banks      = exynos5433_pin_banks1,
+               .nr_banks       = ARRAY_SIZE(exynos5433_pin_banks1),
+               .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
+       }, {
+               /* pin-controller instance 2 data */
+               .pin_banks      = exynos5433_pin_banks2,
+               .nr_banks       = ARRAY_SIZE(exynos5433_pin_banks2),
+               .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
+       }, {
+               /* pin-controller instance 3 data */
+               .pin_banks      = exynos5433_pin_banks3,
+               .nr_banks       = ARRAY_SIZE(exynos5433_pin_banks3),
+               .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
+       }, {
+               /* pin-controller instance 4 data */
+               .pin_banks      = exynos5433_pin_banks4,
+               .nr_banks       = ARRAY_SIZE(exynos5433_pin_banks4),
+               .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
+       }, {
+               /* pin-controller instance 5 data */
+               .pin_banks      = exynos5433_pin_banks5,
+               .nr_banks       = ARRAY_SIZE(exynos5433_pin_banks5),
+               .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
+       }, {
+               /* pin-controller instance 6 data */
+               .pin_banks      = exynos5433_pin_banks6,
+               .nr_banks       = ARRAY_SIZE(exynos5433_pin_banks6),
+               .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
+       }, {
+               /* pin-controller instance 7 data */
+               .pin_banks      = exynos5433_pin_banks7,
+               .nr_banks       = ARRAY_SIZE(exynos5433_pin_banks7),
+               .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
+       }, {
+               /* pin-controller instance 8 data */
+               .pin_banks      = exynos5433_pin_banks8,
+               .nr_banks       = ARRAY_SIZE(exynos5433_pin_banks8),
+               .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
+       }, {
+               /* pin-controller instance 9 data */
+               .pin_banks      = exynos5433_pin_banks9,
+               .nr_banks       = ARRAY_SIZE(exynos5433_pin_banks9),
+               .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
+       },
+};
+
 /* pin banks of exynos7 pin-controller - ALIVE */
 static const struct samsung_pin_bank_data exynos7_pin_banks0[] __initconst = {
        EXYNOS_PIN_BANK_EINTW(8, 0x000, "gpa0", 0x00),
@@ -1324,7 +1477,6 @@ const struct samsung_pin_ctrl exynos7_pin_ctrl[] __initconst = {
                /* pin-controller instance 0 Alive data */
                .pin_banks      = exynos7_pin_banks0,
                .nr_banks       = ARRAY_SIZE(exynos7_pin_banks0),
-               .eint_gpio_init = exynos_eint_gpio_init,
                .eint_wkup_init = exynos_eint_wkup_init,
        }, {
                /* pin-controller instance 1 BUS0 data */
index ec580af3585635056f5cb21937edfbed054bcf70..ed165ba2eb2f187c550fd95c8767e6d4263961d2 100644 (file)
@@ -1239,6 +1239,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
                .data = (void *)exynos5260_pin_ctrl },
        { .compatible = "samsung,exynos5420-pinctrl",
                .data = (void *)exynos5420_pin_ctrl },
+       { .compatible = "samsung,exynos5433-pinctrl",
+               .data = (void *)exynos5433_pin_ctrl },
        { .compatible = "samsung,s5pv210-pinctrl",
                .data = (void *)s5pv210_pin_ctrl },
        { .compatible = "samsung,exynos7-pinctrl",
index 1b8c0139d604b1b59dbc6d4fe7f80771515cc606..c1239ff6157d0d5bbfc3524e7664c617660eb94b 100644 (file)
@@ -271,6 +271,7 @@ extern const struct samsung_pin_ctrl exynos4415_pin_ctrl[];
 extern const struct samsung_pin_ctrl exynos5250_pin_ctrl[];
 extern const struct samsung_pin_ctrl exynos5260_pin_ctrl[];
 extern const struct samsung_pin_ctrl exynos5420_pin_ctrl[];
+extern const struct samsung_pin_ctrl exynos5433_pin_ctrl[];
 extern const struct samsung_pin_ctrl exynos7_pin_ctrl[];
 extern const struct samsung_pin_ctrl s3c64xx_pin_ctrl[];
 extern const struct samsung_pin_ctrl s3c2412_pin_ctrl[];
index a56280814a3f884b24a19b0fda2ae20ba3fe9ab0..7b2c9495c3832410fca31e1676feedf7ffbd9e01 100644 (file)
@@ -92,10 +92,10 @@ static int sh_pfc_map_resources(struct sh_pfc *pfc,
        return 0;
 }
 
-static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc,
-                                        unsigned long address)
+static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc, u32 reg)
 {
        struct sh_pfc_window *window;
+       phys_addr_t address = reg;
        unsigned int i;
 
        /* scan through physical windows and convert address */
@@ -144,8 +144,7 @@ static int sh_pfc_enum_in_range(u16 enum_id, const struct pinmux_range *r)
        return 1;
 }
 
-unsigned long sh_pfc_read_raw_reg(void __iomem *mapped_reg,
-                                 unsigned long reg_width)
+u32 sh_pfc_read_raw_reg(void __iomem *mapped_reg, unsigned int reg_width)
 {
        switch (reg_width) {
        case 8:
@@ -160,8 +159,8 @@ unsigned long sh_pfc_read_raw_reg(void __iomem *mapped_reg,
        return 0;
 }
 
-void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned long reg_width,
-                         unsigned long data)
+void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width,
+                         u32 data)
 {
        switch (reg_width) {
        case 8:
@@ -180,10 +179,9 @@ void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned long reg_width,
 
 static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
                                     const struct pinmux_cfg_reg *crp,
-                                    unsigned long in_pos,
-                                    void __iomem **mapped_regp,
-                                    unsigned long *maskp,
-                                    unsigned long *posp)
+                                    unsigned int in_pos,
+                                    void __iomem **mapped_regp, u32 *maskp,
+                                    unsigned int *posp)
 {
        unsigned int k;
 
@@ -202,15 +200,16 @@ static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
 
 static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
                                    const struct pinmux_cfg_reg *crp,
-                                   unsigned long field, unsigned long value)
+                                   unsigned int field, u32 value)
 {
        void __iomem *mapped_reg;
-       unsigned long mask, pos, data;
+       unsigned int pos;
+       u32 mask, data;
 
        sh_pfc_config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
 
-       dev_dbg(pfc->dev, "write_reg addr = %lx, value = %ld, field = %ld, "
-               "r_width = %ld, f_width = %ld\n",
+       dev_dbg(pfc->dev, "write_reg addr = %x, value = 0x%x, field = %u, "
+               "r_width = %u, f_width = %u\n",
                crp->reg, value, field, crp->reg_width, crp->field_width);
 
        mask = ~(mask << pos);
@@ -229,26 +228,28 @@ static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
 }
 
 static int sh_pfc_get_config_reg(struct sh_pfc *pfc, u16 enum_id,
-                                const struct pinmux_cfg_reg **crp, int *fieldp,
-                                int *valuep)
+                                const struct pinmux_cfg_reg **crp,
+                                unsigned int *fieldp, u32 *valuep)
 {
-       const struct pinmux_cfg_reg *config_reg;
-       unsigned long r_width, f_width, curr_width, ncomb;
-       unsigned int k, m, n, pos, bit_pos;
+       unsigned int k = 0;
 
-       k = 0;
        while (1) {
-               config_reg = pfc->info->cfg_regs + k;
-
-               r_width = config_reg->reg_width;
-               f_width = config_reg->field_width;
+               const struct pinmux_cfg_reg *config_reg =
+                       pfc->info->cfg_regs + k;
+               unsigned int r_width = config_reg->reg_width;
+               unsigned int f_width = config_reg->field_width;
+               unsigned int curr_width;
+               unsigned int bit_pos;
+               unsigned int pos = 0;
+               unsigned int m = 0;
 
                if (!r_width)
                        break;
 
-               pos = 0;
-               m = 0;
                for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
+                       u32 ncomb;
+                       u32 n;
+
                        if (f_width)
                                curr_width = f_width;
                        else
@@ -297,11 +298,8 @@ static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, u16 mark, int pos,
 
 int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
 {
-       const struct pinmux_cfg_reg *cr = NULL;
-       u16 enum_id;
        const struct pinmux_range *range;
-       int in_range, pos, field, value;
-       int ret;
+       int pos = 0;
 
        switch (pinmux_type) {
        case PINMUX_TYPE_GPIO:
@@ -321,13 +319,15 @@ int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
                return -EINVAL;
        }
 
-       pos = 0;
-       enum_id = 0;
-       field = 0;
-       value = 0;
-
        /* Iterate over all the configuration fields we need to update. */
        while (1) {
+               const struct pinmux_cfg_reg *cr;
+               unsigned int field;
+               u16 enum_id;
+               u32 value;
+               int in_range;
+               int ret;
+
                pos = sh_pfc_mark_to_enum(pfc, mark, pos, &enum_id);
                if (pos < 0)
                        return pos;
@@ -579,9 +579,6 @@ static int sh_pfc_remove(struct platform_device *pdev)
 }
 
 static const struct platform_device_id sh_pfc_id_table[] = {
-#ifdef CONFIG_PINCTRL_PFC_EMEV2
-       { "pfc-emev2", (kernel_ulong_t)&emev2_pinmux_info },
-#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A73A4
        { "pfc-r8a73a4", (kernel_ulong_t)&r8a73a4_pinmux_info },
 #endif
@@ -594,12 +591,6 @@ static const struct platform_device_id sh_pfc_id_table[] = {
 #ifdef CONFIG_PINCTRL_PFC_R8A7779
        { "pfc-r8a7779", (kernel_ulong_t)&r8a7779_pinmux_info },
 #endif
-#ifdef CONFIG_PINCTRL_PFC_R8A7790
-       { "pfc-r8a7790", (kernel_ulong_t)&r8a7790_pinmux_info },
-#endif
-#ifdef CONFIG_PINCTRL_PFC_R8A7791
-       { "pfc-r8a7791", (kernel_ulong_t)&r8a7791_pinmux_info },
-#endif
 #ifdef CONFIG_PINCTRL_PFC_SH7203
        { "pfc-sh7203", (kernel_ulong_t)&sh7203_pinmux_info },
 #endif
index 6b59d63b9c01e7a6973a0aef1f2c05c18fb7c4d1..6dc8a6fc27468b39a1cc9aca4a51f594bde95608 100644 (file)
@@ -57,10 +57,9 @@ int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc);
 int sh_pfc_register_pinctrl(struct sh_pfc *pfc);
 int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc);
 
-unsigned long sh_pfc_read_raw_reg(void __iomem *mapped_reg,
-                                 unsigned long reg_width);
-void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned long reg_width,
-                         unsigned long data);
+u32 sh_pfc_read_raw_reg(void __iomem *mapped_reg, unsigned int reg_width);
+void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width,
+                         u32 data);
 
 int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin);
 int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type);
index 80f641ee4dea31468d60de86127b979947078c22..ba353735ecf2be9a1ca39c29e516c850beaa1ce1 100644 (file)
@@ -21,7 +21,7 @@
 
 struct sh_pfc_gpio_data_reg {
        const struct pinmux_data_reg *info;
-       unsigned long shadow;
+       u32 shadow;
 };
 
 struct sh_pfc_gpio_pin {
@@ -59,19 +59,20 @@ static void gpio_get_data_reg(struct sh_pfc_chip *chip, unsigned int offset,
        *bit = gpio_pin->dbit;
 }
 
-static unsigned long gpio_read_data_reg(struct sh_pfc_chip *chip,
-                                       const struct pinmux_data_reg *dreg)
+static u32 gpio_read_data_reg(struct sh_pfc_chip *chip,
+                             const struct pinmux_data_reg *dreg)
 {
-       void __iomem *mem = dreg->reg - chip->mem->phys + chip->mem->virt;
+       phys_addr_t address = dreg->reg;
+       void __iomem *mem = address - chip->mem->phys + chip->mem->virt;
 
        return sh_pfc_read_raw_reg(mem, dreg->reg_width);
 }
 
 static void gpio_write_data_reg(struct sh_pfc_chip *chip,
-                               const struct pinmux_data_reg *dreg,
-                               unsigned long value)
+                               const struct pinmux_data_reg *dreg, u32 value)
 {
-       void __iomem *mem = dreg->reg - chip->mem->phys + chip->mem->virt;
+       phys_addr_t address = dreg->reg;
+       void __iomem *mem = address - chip->mem->phys + chip->mem->virt;
 
        sh_pfc_write_raw_reg(mem, dreg->reg_width, value);
 }
@@ -85,7 +86,7 @@ static void gpio_setup_data_reg(struct sh_pfc_chip *chip, unsigned idx)
        unsigned int bit;
        unsigned int i;
 
-       for (i = 0, dreg = pfc->info->data_regs; dreg->reg; ++i, ++dreg) {
+       for (i = 0, dreg = pfc->info->data_regs; dreg->reg_width; ++i, ++dreg) {
                for (bit = 0; bit < dreg->reg_width; bit++) {
                        if (dreg->enum_ids[bit] == pin->enum_id) {
                                gpio_pin->dreg = i;
@@ -154,17 +155,17 @@ static void gpio_pin_set_value(struct sh_pfc_chip *chip, unsigned offset,
                               int value)
 {
        struct sh_pfc_gpio_data_reg *reg;
-       unsigned long pos;
        unsigned int bit;
+       unsigned int pos;
 
        gpio_get_data_reg(chip, offset, &reg, &bit);
 
        pos = reg->info->reg_width - (bit + 1);
 
        if (value)
-               set_bit(pos, &reg->shadow);
+               reg->shadow |= BIT(pos);
        else
-               clear_bit(pos, &reg->shadow);
+               reg->shadow &= ~BIT(pos);
 
        gpio_write_data_reg(chip, reg->info, reg->shadow);
 }
@@ -186,8 +187,8 @@ static int gpio_pin_get(struct gpio_chip *gc, unsigned offset)
 {
        struct sh_pfc_chip *chip = gpio_to_pfc_chip(gc);
        struct sh_pfc_gpio_data_reg *reg;
-       unsigned long pos;
        unsigned int bit;
+       unsigned int pos;
 
        gpio_get_data_reg(chip, offset, &reg, &bit);
 
@@ -341,6 +342,7 @@ sh_pfc_add_gpiochip(struct sh_pfc *pfc, int(*setup)(struct sh_pfc_chip *),
 int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
 {
        struct sh_pfc_chip *chip;
+       phys_addr_t address;
        unsigned int i;
        int ret;
 
@@ -352,11 +354,12 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
         * that covers the data registers. In that case don't try to handle
         * GPIOs.
         */
+       address = pfc->info->data_regs[0].reg;
        for (i = 0; i < pfc->num_windows; ++i) {
                struct sh_pfc_window *window = &pfc->windows[i];
 
-               if (pfc->info->data_regs[0].reg >= window->phys &&
-                   pfc->info->data_regs[0].reg < window->phys + window->size)
+               if (address >= window->phys &&
+                   address < window->phys + window->size)
                        break;
        }
 
index 80c1843bb6ad6303f5ac79153802f3adbd2252c1..22a5470889f533edb6fdb03b7b87b28f17396983 100644 (file)
@@ -1799,6 +1799,81 @@ static const unsigned int audio_clkout_d_pins[] = {
 static const unsigned int audio_clkout_d_mux[] = {
        AUDIO_CLKOUT_D_MARK,
 };
+/* - AVB -------------------------------------------------------------------- */
+static const unsigned int avb_link_pins[] = {
+       RCAR_GP_PIN(3, 11),
+};
+static const unsigned int avb_link_mux[] = {
+       AVB_LINK_MARK,
+};
+static const unsigned int avb_magic_pins[] = {
+       RCAR_GP_PIN(2, 14),
+};
+static const unsigned int avb_magic_mux[] = {
+       AVB_MAGIC_MARK,
+};
+static const unsigned int avb_phy_int_pins[] = {
+       RCAR_GP_PIN(2, 15),
+};
+static const unsigned int avb_phy_int_mux[] = {
+       AVB_PHY_INT_MARK,
+};
+static const unsigned int avb_mdio_pins[] = {
+       RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 12),
+};
+static const unsigned int avb_mdio_mux[] = {
+       AVB_MDC_MARK, AVB_MDIO_MARK,
+};
+static const unsigned int avb_mii_pins[] = {
+       RCAR_GP_PIN(0, 8), RCAR_GP_PIN(0, 9), RCAR_GP_PIN(0, 10),
+       RCAR_GP_PIN(0, 11),
+
+       RCAR_GP_PIN(3, 13), RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1),
+       RCAR_GP_PIN(2, 2),
+
+       RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9),
+       RCAR_GP_PIN(2, 10), RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 10),
+       RCAR_GP_PIN(3, 12),
+};
+static const unsigned int avb_mii_mux[] = {
+       AVB_TXD0_MARK, AVB_TXD1_MARK, AVB_TXD2_MARK,
+       AVB_TXD3_MARK,
+
+       AVB_RXD0_MARK, AVB_RXD1_MARK, AVB_RXD2_MARK,
+       AVB_RXD3_MARK,
+
+       AVB_RX_ER_MARK, AVB_RX_CLK_MARK, AVB_RX_DV_MARK,
+       AVB_CRS_MARK, AVB_TX_EN_MARK, AVB_TX_CLK_MARK,
+       AVB_COL_MARK,
+};
+static const unsigned int avb_gmii_pins[] = {
+       RCAR_GP_PIN(0, 8), RCAR_GP_PIN(0, 9), RCAR_GP_PIN(0, 10),
+       RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 12), RCAR_GP_PIN(0, 13),
+       RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 15),
+
+       RCAR_GP_PIN(3, 13), RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1),
+       RCAR_GP_PIN(2, 2), RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 4),
+       RCAR_GP_PIN(2, 5), RCAR_GP_PIN(2, 6),
+
+       RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9),
+       RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 13), RCAR_GP_PIN(2, 16),
+       RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), RCAR_GP_PIN(3, 10),
+       RCAR_GP_PIN(3, 12),
+};
+static const unsigned int avb_gmii_mux[] = {
+       AVB_TXD0_MARK, AVB_TXD1_MARK, AVB_TXD2_MARK,
+       AVB_TXD3_MARK, AVB_TXD4_MARK, AVB_TXD5_MARK,
+       AVB_TXD6_MARK, AVB_TXD7_MARK,
+
+       AVB_RXD0_MARK, AVB_RXD1_MARK, AVB_RXD2_MARK,
+       AVB_RXD3_MARK, AVB_RXD4_MARK, AVB_RXD5_MARK,
+       AVB_RXD6_MARK, AVB_RXD7_MARK,
+
+       AVB_RX_ER_MARK, AVB_RX_CLK_MARK, AVB_RX_DV_MARK,
+       AVB_CRS_MARK, AVB_GTX_CLK_MARK, AVB_GTXREFCLK_MARK,
+       AVB_TX_EN_MARK, AVB_TX_ER_MARK, AVB_TX_CLK_MARK,
+       AVB_COL_MARK,
+};
 /* - DU RGB ----------------------------------------------------------------- */
 static const unsigned int du_rgb666_pins[] = {
        /* R[7:2], G[7:2], B[7:2] */
@@ -3823,6 +3898,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
        SH_PFC_PIN_GROUP(audio_clkout_b),
        SH_PFC_PIN_GROUP(audio_clkout_c),
        SH_PFC_PIN_GROUP(audio_clkout_d),
+       SH_PFC_PIN_GROUP(avb_link),
+       SH_PFC_PIN_GROUP(avb_magic),
+       SH_PFC_PIN_GROUP(avb_phy_int),
+       SH_PFC_PIN_GROUP(avb_mdio),
+       SH_PFC_PIN_GROUP(avb_mii),
+       SH_PFC_PIN_GROUP(avb_gmii),
        SH_PFC_PIN_GROUP(du_rgb666),
        SH_PFC_PIN_GROUP(du_rgb888),
        SH_PFC_PIN_GROUP(du_clk_out_0),
@@ -4101,6 +4182,15 @@ static const char * const audio_clk_groups[] = {
        "audio_clkout_d",
 };
 
+static const char * const avb_groups[] = {
+       "avb_link",
+       "avb_magic",
+       "avb_phy_int",
+       "avb_mdio",
+       "avb_mii",
+       "avb_gmii",
+};
+
 static const char * const du_groups[] = {
        "du_rgb666",
        "du_rgb888",
@@ -4507,6 +4597,7 @@ static const char * const vin3_groups[] = {
 
 static const struct sh_pfc_function pinmux_functions[] = {
        SH_PFC_FUNCTION(audio_clk),
+       SH_PFC_FUNCTION(avb),
        SH_PFC_FUNCTION(du),
        SH_PFC_FUNCTION(du0),
        SH_PFC_FUNCTION(du1),
index c83728626906c16c586954aa866aafa94ecf576b..c7508d5f688613b26e6eb226628f61ba9cd38f66 100644 (file)
@@ -69,9 +69,10 @@ struct pinmux_func {
 };
 
 struct pinmux_cfg_reg {
-       unsigned long reg, reg_width, field_width;
+       u32 reg;
+       u8 reg_width, field_width;
        const u16 *enum_ids;
-       const unsigned long *var_field_width;
+       const u8 *var_field_width;
 };
 
 #define PINMUX_CFG_REG(name, r, r_width, f_width) \
@@ -80,12 +81,13 @@ struct pinmux_cfg_reg {
 
 #define PINMUX_CFG_REG_VAR(name, r, r_width, var_fw0, var_fwn...) \
        .reg = r, .reg_width = r_width, \
-       .var_field_width = (const unsigned long [r_width]) \
+       .var_field_width = (const u8 [r_width]) \
                { var_fw0, var_fwn, 0 }, \
        .enum_ids = (const u16 [])
 
 struct pinmux_data_reg {
-       unsigned long reg, reg_width;
+       u32 reg;
+       u8 reg_width;
        const u16 *enum_ids;
 };
 
@@ -148,7 +150,7 @@ struct sh_pfc_soc_info {
        const struct pinmux_irq *gpio_irq;
        unsigned int gpio_irq_size;
 
-       unsigned long unlock_reg;
+       u32 unlock_reg;
 };
 
 /* -----------------------------------------------------------------------------
@@ -302,20 +304,21 @@ struct sh_pfc_soc_info {
 /*
  * PORTnCR macro
  */
-#define _PCRH(in, in_pd, in_pu, out)   \
-       0, (out), (in), 0,              \
-       0, 0, 0, 0,                     \
-       0, 0, (in_pd), 0,               \
-       0, 0, (in_pu), 0
-
 #define PORTCR(nr, reg)                                                        \
        {                                                               \
-               PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {             \
-                       _PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT),     \
-                               PORT##nr##_FN0, PORT##nr##_FN1,         \
-                               PORT##nr##_FN2, PORT##nr##_FN3,         \
-                               PORT##nr##_FN4, PORT##nr##_FN5,         \
-                               PORT##nr##_FN6, PORT##nr##_FN7 }        \
+               PINMUX_CFG_REG_VAR("PORT" nr "CR", reg, 8, 2, 2, 1, 3) {\
+                       /* PULMD[1:0], handled by .set_bias() */        \
+                       0, 0, 0, 0,                                     \
+                       /* IE and OE */                                 \
+                       0, PORT##nr##_OUT, PORT##nr##_IN, 0,            \
+                       /* SEC, not supported */                        \
+                       0, 0,                                           \
+                       /* PTMD[2:0] */                                 \
+                       PORT##nr##_FN0, PORT##nr##_FN1,                 \
+                       PORT##nr##_FN2, PORT##nr##_FN3,                 \
+                       PORT##nr##_FN4, PORT##nr##_FN5,                 \
+                       PORT##nr##_FN6, PORT##nr##_FN7                  \
+               }                                                       \
        }
 
 #endif /* __SH_PFC_H */
index 2a1f07249b2fd68c98a53f63847562cc65fc6f8f..e2efbbae4061301cf60f3a55a104ea553ad2e7ad 100644 (file)
@@ -39,10 +39,9 @@ struct sirfsoc_gpio_bank {
 struct sirfsoc_gpio_chip {
        struct of_mm_gpio_chip chip;
        struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
+       spinlock_t lock;
 };
 
-static DEFINE_SPINLOCK(sgpio_lock);
-
 static struct sirfsoc_pin_group *sirfsoc_pin_groups;
 static int sirfsoc_pingrp_cnt;
 
@@ -427,13 +426,13 @@ static void sirfsoc_gpio_irq_ack(struct irq_data *d)
 
        offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
 
-       spin_lock_irqsave(&sgpio_lock, flags);
+       spin_lock_irqsave(&sgpio->lock, flags);
 
        val = readl(sgpio->chip.regs + offset);
 
        writel(val, sgpio->chip.regs + offset);
 
-       spin_unlock_irqrestore(&sgpio_lock, flags);
+       spin_unlock_irqrestore(&sgpio->lock, flags);
 }
 
 static void __sirfsoc_gpio_irq_mask(struct sirfsoc_gpio_chip *sgpio,
@@ -445,14 +444,14 @@ static void __sirfsoc_gpio_irq_mask(struct sirfsoc_gpio_chip *sgpio,
 
        offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
 
-       spin_lock_irqsave(&sgpio_lock, flags);
+       spin_lock_irqsave(&sgpio->lock, flags);
 
        val = readl(sgpio->chip.regs + offset);
        val &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
        val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
        writel(val, sgpio->chip.regs + offset);
 
-       spin_unlock_irqrestore(&sgpio_lock, flags);
+       spin_unlock_irqrestore(&sgpio->lock, flags);
 }
 
 static void sirfsoc_gpio_irq_mask(struct irq_data *d)
@@ -475,14 +474,14 @@ static void sirfsoc_gpio_irq_unmask(struct irq_data *d)
 
        offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
 
-       spin_lock_irqsave(&sgpio_lock, flags);
+       spin_lock_irqsave(&sgpio->lock, flags);
 
        val = readl(sgpio->chip.regs + offset);
        val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
        val |= SIRFSOC_GPIO_CTL_INTR_EN_MASK;
        writel(val, sgpio->chip.regs + offset);
 
-       spin_unlock_irqrestore(&sgpio_lock, flags);
+       spin_unlock_irqrestore(&sgpio->lock, flags);
 }
 
 static int sirfsoc_gpio_irq_type(struct irq_data *d, unsigned type)
@@ -496,7 +495,7 @@ static int sirfsoc_gpio_irq_type(struct irq_data *d, unsigned type)
 
        offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
 
-       spin_lock_irqsave(&sgpio_lock, flags);
+       spin_lock_irqsave(&sgpio->lock, flags);
 
        val = readl(sgpio->chip.regs + offset);
        val &= ~(SIRFSOC_GPIO_CTL_INTR_STS_MASK | SIRFSOC_GPIO_CTL_OUT_EN_MASK);
@@ -533,7 +532,7 @@ static int sirfsoc_gpio_irq_type(struct irq_data *d, unsigned type)
 
        writel(val, sgpio->chip.regs + offset);
 
-       spin_unlock_irqrestore(&sgpio_lock, flags);
+       spin_unlock_irqrestore(&sgpio->lock, flags);
 
        return 0;
 }
@@ -568,7 +567,7 @@ static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc)
        status = readl(sgpio->chip.regs + SIRFSOC_GPIO_INT_STATUS(bank->id));
        if (!status) {
                printk(KERN_WARNING
-                       "%s: gpio id %d status %#x no interrupt is flaged\n",
+                       "%s: gpio id %d status %#x no interrupt is flagged\n",
                        __func__, bank->id, status);
                handle_bad_irq(irq, desc);
                return;
@@ -697,11 +696,11 @@ static int sirfsoc_gpio_direction_output(struct gpio_chip *chip,
 
        offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
 
-       spin_lock_irqsave(&sgpio_lock, flags);
+       spin_lock_irqsave(&sgpio->lock, flags);
 
        sirfsoc_gpio_set_output(sgpio, bank, offset, value);
 
-       spin_unlock_irqrestore(&sgpio_lock, flags);
+       spin_unlock_irqrestore(&sgpio->lock, flags);
 
        return 0;
 }
@@ -793,6 +792,7 @@ static int sirfsoc_gpio_probe(struct device_node *np)
        sgpio = devm_kzalloc(&pdev->dev, sizeof(*sgpio), GFP_KERNEL);
        if (!sgpio)
                return -ENOMEM;
+       spin_lock_init(&sgpio->lock);
 
        regs = of_iomap(np, 0);
        if (!regs)
index 3c68a8e5e0dd4d4bbb8d6fae4166a6bf92e521a2..7376a97b5e65c3f27471c6a2fc90848144d507ce 100644 (file)
@@ -1020,7 +1020,7 @@ static int sun4i_a10_pinctrl_probe(struct platform_device *pdev)
                                  &sun4i_a10_pinctrl_data);
 }
 
-static struct of_device_id sun4i_a10_pinctrl_match[] = {
+static const struct of_device_id sun4i_a10_pinctrl_match[] = {
        { .compatible = "allwinner,sun4i-a10-pinctrl", },
        {}
 };
index 45a351affa59d02f39acb14a7c21d0a828354026..63676617bc5997218729a56c15c8597f8c2499b9 100644 (file)
@@ -670,7 +670,7 @@ static int sun5i_a10s_pinctrl_probe(struct platform_device *pdev)
                                  &sun5i_a10s_pinctrl_data);
 }
 
-static struct of_device_id sun5i_a10s_pinctrl_match[] = {
+static const struct of_device_id sun5i_a10s_pinctrl_match[] = {
        { .compatible = "allwinner,sun5i-a10s-pinctrl", },
        {}
 };
index 4bd23471412ccaa54f707f072d5d354f4873e7a2..2bb07b38834f743b7705af3d816803567064311f 100644 (file)
@@ -388,7 +388,7 @@ static int sun5i_a13_pinctrl_probe(struct platform_device *pdev)
                                  &sun5i_a13_pinctrl_data);
 }
 
-static struct of_device_id sun5i_a13_pinctrl_match[] = {
+static const struct of_device_id sun5i_a13_pinctrl_match[] = {
        { .compatible = "allwinner,sun5i-a13-pinctrl", },
        {}
 };
index 02174fa57997e4c07b6fc7822e456db95b9fa772..9596b0a3df6be7f1b4cdfb238ae4d29f94538d0e 100644 (file)
@@ -120,7 +120,7 @@ static int sun6i_a31_r_pinctrl_probe(struct platform_device *pdev)
        return ret;
 }
 
-static struct of_device_id sun6i_a31_r_pinctrl_match[] = {
+static const struct of_device_id sun6i_a31_r_pinctrl_match[] = {
        { .compatible = "allwinner,sun6i-a31-r-pinctrl", },
        {}
 };
index 18038f0d6b5222cf77a1386cbe874d23cd0a94b3..022863ab0c5824f3fd832b0c82906d0178b8b9a7 100644 (file)
@@ -922,7 +922,7 @@ static int sun6i_a31_pinctrl_probe(struct platform_device *pdev)
                                  &sun6i_a31_pinctrl_data);
 }
 
-static struct of_device_id sun6i_a31_pinctrl_match[] = {
+static const struct of_device_id sun6i_a31_pinctrl_match[] = {
        { .compatible = "allwinner,sun6i-a31-pinctrl", },
        {}
 };
index 9b5a91f610c7e4d0c8e131b09bfb307e609626f4..d3725dcd6979b874431e7f7f9c3ab61eb484ec63 100644 (file)
@@ -794,7 +794,7 @@ static int sun6i_a31s_pinctrl_probe(struct platform_device *pdev)
                                  &sun6i_a31s_pinctrl_data);
 }
 
-static struct of_device_id sun6i_a31s_pinctrl_match[] = {
+static const struct of_device_id sun6i_a31s_pinctrl_match[] = {
        { .compatible = "allwinner,sun6i-a31s-pinctrl", },
        {}
 };
index 6af6cc8547b0f39a00f998d5529f834902f1f8d0..cf1ce0c02600e6e051f9726f693e3a848eaa379d 100644 (file)
@@ -1045,7 +1045,7 @@ static int sun7i_a20_pinctrl_probe(struct platform_device *pdev)
                                  &sun7i_a20_pinctrl_data);
 }
 
-static struct of_device_id sun7i_a20_pinctrl_match[] = {
+static const struct of_device_id sun7i_a20_pinctrl_match[] = {
        { .compatible = "allwinner,sun7i-a20-pinctrl", },
        {}
 };
index 327e03ff7c4dc3eb249918f3296b5880892f57c5..05628763587335b7e8c1a1689bd937fd723d8cbe 100644 (file)
@@ -119,7 +119,7 @@ static int sun8i_a23_r_pinctrl_probe(struct platform_device *pdev)
        return ret;
 }
 
-static struct of_device_id sun8i_a23_r_pinctrl_match[] = {
+static const struct of_device_id sun8i_a23_r_pinctrl_match[] = {
        { .compatible = "allwinner,sun8i-a23-r-pinctrl", },
        {}
 };
index 62695c9a92c21bd0696ef78e91887fbfef521ad7..55083d278bb1eb36e38772fc36206f41a1460138 100644 (file)
@@ -571,7 +571,7 @@ static int sun8i_a23_pinctrl_probe(struct platform_device *pdev)
                                  &sun8i_a23_pinctrl_data);
 }
 
-static struct of_device_id sun8i_a23_pinctrl_match[] = {
+static const struct of_device_id sun8i_a23_pinctrl_match[] = {
        { .compatible = "allwinner,sun8i-a23-pinctrl", },
        {}
 };
index adb29422efc97a409a9da5e58c843299d8bc8215..1b580ba764531a6d04d2293486f9e1b78a466f45 100644 (file)
@@ -729,7 +729,7 @@ static int sun9i_a80_pinctrl_probe(struct platform_device *pdev)
                                  &sun9i_a80_pinctrl_data);
 }
 
-static struct of_device_id sun9i_a80_pinctrl_match[] = {
+static const struct of_device_id sun9i_a80_pinctrl_match[] = {
        { .compatible = "allwinner,sun9i-a80-pinctrl", },
        {}
 };
index cf8bbc946ff70f7aa73b14eba19a05a29e67dba2..ca946b3dbdb4f717b2543ee9fade272c4c0926ea 100644 (file)
@@ -478,7 +478,7 @@ static int vt8500_pinctrl_remove(struct platform_device *pdev)
        return wmt_pinctrl_remove(pdev);
 }
 
-static struct of_device_id wmt_pinctrl_of_match[] = {
+static const struct of_device_id wmt_pinctrl_of_match[] = {
        { .compatible = "via,vt8500-pinctrl" },
        { /* sentinel */ },
 };
index 3f9c32dcb3d04cd24048e623ade3f3511108484a..626fc7ec017462948e784715851f84dd58281b35 100644 (file)
@@ -509,7 +509,7 @@ static int wm8505_pinctrl_remove(struct platform_device *pdev)
        return wmt_pinctrl_remove(pdev);
 }
 
-static struct of_device_id wmt_pinctrl_of_match[] = {
+static const struct of_device_id wmt_pinctrl_of_match[] = {
        { .compatible = "wm,wm8505-pinctrl" },
        { /* sentinel */ },
 };
index 4e80f98c2ba7c24656904b1364cb95b4b64775bc..8953aba8bfc2261e5c6cef9392d69cb4c5b1209f 100644 (file)
@@ -347,7 +347,7 @@ static int wm8650_pinctrl_remove(struct platform_device *pdev)
        return wmt_pinctrl_remove(pdev);
 }
 
-static struct of_device_id wmt_pinctrl_of_match[] = {
+static const struct of_device_id wmt_pinctrl_of_match[] = {
        { .compatible = "wm,wm8650-pinctrl" },
        { /* sentinel */ },
 };
index 47b52a7cacac049d5b576ecd98965e9c2cd5d8b9..c79053d430db5ad6894ebf60d10e30fdbfe05b06 100644 (file)
@@ -386,7 +386,7 @@ static int wm8750_pinctrl_remove(struct platform_device *pdev)
        return wmt_pinctrl_remove(pdev);
 }
 
-static struct of_device_id wmt_pinctrl_of_match[] = {
+static const struct of_device_id wmt_pinctrl_of_match[] = {
        { .compatible = "wm,wm8750-pinctrl" },
        { /* sentinel */ },
 };
index 8bbb38c931f659f24e3cbd024557c9b3d1f52592..f232b163c735cfb4e9a4c3fa11033c9d5142739f 100644 (file)
@@ -365,7 +365,7 @@ static int wm8850_pinctrl_remove(struct platform_device *pdev)
        return wmt_pinctrl_remove(pdev);
 }
 
-static struct of_device_id wmt_pinctrl_of_match[] = {
+static const struct of_device_id wmt_pinctrl_of_match[] = {
        { .compatible = "wm,wm8850-pinctrl" },
        { /* sentinel */ },
 };
index 15c0fab2bfa10496d466e70e0537cc0ad08768d4..b4e94471f3d57e049b99893cc156729e02bf255c 100644 (file)
@@ -177,7 +177,7 @@ struct compal_data{
        unsigned char curr_pwm;
 
        /* Power supply */
-       struct power_supply psy;
+       struct power_supply *psy;
        struct power_supply_info psy_info;
        char bat_model_name[BAT_MODEL_NAME_LEN + 1];
        char bat_manufacturer_name[BAT_MANUFACTURER_NAME_LEN + 1];
@@ -565,8 +565,7 @@ static int bat_get_property(struct power_supply *psy,
                                enum power_supply_property psp,
                                union power_supply_propval *val)
 {
-       struct compal_data *data;
-       data = container_of(psy, struct compal_data, psy);
+       struct compal_data *data = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
@@ -875,13 +874,16 @@ static struct dmi_system_id __initdata compal_dmi_table[] = {
 };
 MODULE_DEVICE_TABLE(dmi, compal_dmi_table);
 
+static const struct power_supply_desc psy_bat_desc = {
+       .name           = DRIVER_NAME,
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .properties     = compal_bat_properties,
+       .num_properties = ARRAY_SIZE(compal_bat_properties),
+       .get_property   = bat_get_property,
+};
+
 static void initialize_power_supply_data(struct compal_data *data)
 {
-       data->psy.name = DRIVER_NAME;
-       data->psy.type = POWER_SUPPLY_TYPE_BATTERY;
-       data->psy.properties = compal_bat_properties;
-       data->psy.num_properties = ARRAY_SIZE(compal_bat_properties);
-       data->psy.get_property = bat_get_property;
 
        ec_read_sequence(BAT_MANUFACTURER_NAME_ADDR,
                                        data->bat_manufacturer_name,
@@ -1011,6 +1013,7 @@ static int compal_probe(struct platform_device *pdev)
        int err;
        struct compal_data *data;
        struct device *hwmon_dev;
+       struct power_supply_config psy_cfg = {};
 
        if (!extra_features)
                return 0;
@@ -1026,9 +1029,9 @@ static int compal_probe(struct platform_device *pdev)
        if (err)
                return err;
 
-       hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
-                                                     "compal", data,
-                                                     compal_hwmon_groups);
+       hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev,
+                                                          "compal", data,
+                                                          compal_hwmon_groups);
        if (IS_ERR(hwmon_dev)) {
                err = PTR_ERR(hwmon_dev);
                goto remove;
@@ -1036,7 +1039,13 @@ static int compal_probe(struct platform_device *pdev)
 
        /* Power supply */
        initialize_power_supply_data(data);
-       power_supply_register(&compal_device->dev, &data->psy);
+       psy_cfg.drv_data = data;
+       data->psy = power_supply_register(&compal_device->dev, &psy_bat_desc,
+                                         &psy_cfg);
+       if (IS_ERR(data->psy)) {
+               err = PTR_ERR(data->psy);
+               goto remove;
+       }
 
        platform_set_drvdata(pdev, data);
 
@@ -1071,7 +1080,7 @@ static int compal_remove(struct platform_device *pdev)
        pwm_disable_control();
 
        data = platform_get_drvdata(pdev);
-       power_supply_unregister(&data->psy);
+       power_supply_unregister(data->psy);
 
        sysfs_remove_group(&pdev->dev.kobj, &compal_platform_attr_group);
 
index ebf0d6710b5a0d4150627313a3edca99e50a8745..943c1cb9566c803b168aac842aa00187a4627720 100644 (file)
@@ -246,13 +246,16 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
         */
        for_each_pci_dev(pdev) {
                for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-                       unsigned long type;
+                       unsigned long flags, type;
 
-                       type = pci_resource_flags(pdev, i) &
-                                       (IORESOURCE_IO | IORESOURCE_MEM);
+                       flags = pci_resource_flags(pdev, i);
+                       type = flags & (IORESOURCE_IO | IORESOURCE_MEM);
                        if (!type || pci_resource_len(pdev, i) == 0)
                                continue;
 
+                       if (flags & IORESOURCE_UNSET)
+                               continue;
+
                        pci_start = pci_resource_start(pdev, i);
                        pci_end = pci_resource_end(pdev, i);
                        for (j = 0;
index bd3c997f4feea094884c2273dc92a0e1bd9fc200..d49579b227ec13deb372226d45fee71eeee4ce18 100644 (file)
@@ -98,7 +98,7 @@ struct pm860x_battery_info {
        struct i2c_client *i2c;
        struct device *dev;
 
-       struct power_supply battery;
+       struct power_supply *battery;
        struct mutex lock;
        int status;
        int irq_cc;
@@ -798,9 +798,8 @@ out:
 
 static void pm860x_external_power_changed(struct power_supply *psy)
 {
-       struct pm860x_battery_info *info;
+       struct pm860x_battery_info *info = dev_get_drvdata(psy->dev.parent);
 
-       info = container_of(psy, struct pm860x_battery_info, battery);
        calc_resistor(info);
 }
 
@@ -808,7 +807,7 @@ static int pm860x_batt_get_prop(struct power_supply *psy,
                                enum power_supply_property psp,
                                union power_supply_propval *val)
 {
-       struct pm860x_battery_info *info = dev_get_drvdata(psy->dev->parent);
+       struct pm860x_battery_info *info = dev_get_drvdata(psy->dev.parent);
        int data;
        int ret;
 
@@ -874,7 +873,7 @@ static int pm860x_batt_set_prop(struct power_supply *psy,
                                       enum power_supply_property psp,
                                       const union power_supply_propval *val)
 {
-       struct pm860x_battery_info *info = dev_get_drvdata(psy->dev->parent);
+       struct pm860x_battery_info *info = dev_get_drvdata(psy->dev.parent);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_CHARGE_FULL:
@@ -901,6 +900,16 @@ static enum power_supply_property pm860x_batt_props[] = {
        POWER_SUPPLY_PROP_TEMP,
 };
 
+static const struct power_supply_desc pm860x_battery_desc = {
+       .name                   = "battery-monitor",
+       .type                   = POWER_SUPPLY_TYPE_BATTERY,
+       .properties             = pm860x_batt_props,
+       .num_properties         = ARRAY_SIZE(pm860x_batt_props),
+       .get_property           = pm860x_batt_get_prop,
+       .set_property           = pm860x_batt_set_prop,
+       .external_power_changed = pm860x_external_power_changed,
+};
+
 static int pm860x_battery_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
@@ -936,14 +945,6 @@ static int pm860x_battery_probe(struct platform_device *pdev)
 
        pm860x_init_battery(info);
 
-       info->battery.name = "battery-monitor";
-       info->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-       info->battery.properties = pm860x_batt_props;
-       info->battery.num_properties = ARRAY_SIZE(pm860x_batt_props);
-       info->battery.get_property = pm860x_batt_get_prop;
-       info->battery.set_property = pm860x_batt_set_prop;
-       info->battery.external_power_changed = pm860x_external_power_changed;
-
        if (pdata && pdata->max_capacity)
                info->max_capacity = pdata->max_capacity;
        else
@@ -953,10 +954,11 @@ static int pm860x_battery_probe(struct platform_device *pdev)
        else
                info->resistor = 300;   /* set default internal resistor */
 
-       ret = power_supply_register(&pdev->dev, &info->battery);
-       if (ret)
-               return ret;
-       info->battery.dev->parent = &pdev->dev;
+       info->battery = power_supply_register(&pdev->dev, &pm860x_battery_desc,
+                                             NULL);
+       if (IS_ERR(info->battery))
+               return PTR_ERR(info->battery);
+       info->battery->dev.parent = &pdev->dev;
 
        ret = request_threaded_irq(info->irq_cc, NULL,
                                pm860x_coulomb_handler, IRQF_ONESHOT,
@@ -981,7 +983,7 @@ static int pm860x_battery_probe(struct platform_device *pdev)
 out_coulomb:
        free_irq(info->irq_cc, info);
 out_reg:
-       power_supply_unregister(&info->battery);
+       power_supply_unregister(info->battery);
        return ret;
 }
 
@@ -991,7 +993,7 @@ static int pm860x_battery_remove(struct platform_device *pdev)
 
        free_irq(info->irq_batt, info);
        free_irq(info->irq_cc, info);
-       power_supply_unregister(&info->battery);
+       power_supply_unregister(info->battery);
        return 0;
 }
 
index 734ec4afa14d63ef88f3932ec2faae6774d1d5cc..0e448c68c02bb9e4e6cba0a428e59b29e5231e68 100644 (file)
@@ -102,7 +102,7 @@ struct pm860x_charger_info {
        struct i2c_client *i2c_8606;
        struct device *dev;
 
-       struct power_supply usb;
+       struct power_supply *usb;
        struct mutex lock;
        int irq_nums;
        int irq[7];
@@ -296,14 +296,20 @@ static int set_charging_fsm(struct pm860x_charger_info *info)
        psy = power_supply_get_by_name(pm860x_supplied_to[0]);
        if (!psy)
                return -EINVAL;
-       ret = psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &data);
-       if (ret)
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,
+                       &data);
+       if (ret) {
+               power_supply_put(psy);
                return ret;
+       }
        vbatt = data.intval / 1000;
 
-       ret = psy->get_property(psy, POWER_SUPPLY_PROP_PRESENT, &data);
-       if (ret)
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_PRESENT, &data);
+       if (ret) {
+               power_supply_put(psy);
                return ret;
+       }
+       power_supply_put(psy);
 
        mutex_lock(&info->lock);
        info->present = data.intval;
@@ -414,7 +420,7 @@ static irqreturn_t pm860x_charger_handler(int irq, void *data)
 
        set_charging_fsm(info);
 
-       power_supply_changed(&info->usb);
+       power_supply_changed(info->usb);
 out:
        return IRQ_HANDLED;
 }
@@ -430,7 +436,7 @@ static irqreturn_t pm860x_temp_handler(int irq, void *data)
        psy = power_supply_get_by_name(pm860x_supplied_to[0]);
        if (!psy)
                goto out;
-       ret = psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &temp);
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_TEMP, &temp);
        if (ret)
                goto out;
        value = temp.intval / 10;
@@ -446,6 +452,7 @@ static irqreturn_t pm860x_temp_handler(int irq, void *data)
 
        set_charging_fsm(info);
 out:
+       power_supply_put(psy);
        return IRQ_HANDLED;
 }
 
@@ -485,9 +492,10 @@ static irqreturn_t pm860x_done_handler(int irq, void *data)
        psy = power_supply_get_by_name(pm860x_supplied_to[0]);
        if (!psy)
                goto out;
-       ret = psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,
+                       &val);
        if (ret)
-               goto out;
+               goto out_psy_put;
        vbatt = val.intval / 1000;
        /*
         * CHG_DONE interrupt is faster than CHG_DET interrupt when
@@ -498,10 +506,13 @@ static irqreturn_t pm860x_done_handler(int irq, void *data)
         */
        ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2);
        if (ret < 0)
-               goto out;
+               goto out_psy_put;
        if (vbatt > CHARGE_THRESHOLD && ret & STATUS2_CHG)
-               psy->set_property(psy, POWER_SUPPLY_PROP_CHARGE_FULL, &val);
+               power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGE_FULL,
+                               &val);
 
+out_psy_put:
+       power_supply_put(psy);
 out:
        mutex_unlock(&info->lock);
        dev_dbg(info->dev, "%s, Allowed: %d\n", __func__, info->allowed);
@@ -584,8 +595,7 @@ static int pm860x_usb_get_prop(struct power_supply *psy,
                               enum power_supply_property psp,
                               union power_supply_propval *val)
 {
-       struct pm860x_charger_info *info =
-           dev_get_drvdata(psy->dev->parent);
+       struct pm860x_charger_info *info = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
@@ -645,9 +655,18 @@ static struct pm860x_irq_desc {
        { "vchg", pm860x_vchg_handler },
 };
 
+static const struct power_supply_desc pm860x_charger_desc = {
+       .name           = "usb",
+       .type           = POWER_SUPPLY_TYPE_USB,
+       .properties     = pm860x_usb_props,
+       .num_properties = ARRAY_SIZE(pm860x_usb_props),
+       .get_property   = pm860x_usb_get_prop,
+};
+
 static int pm860x_charger_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+       struct power_supply_config psy_cfg = {};
        struct pm860x_charger_info *info;
        int ret;
        int count;
@@ -685,16 +704,15 @@ static int pm860x_charger_probe(struct platform_device *pdev)
        mutex_init(&info->lock);
        platform_set_drvdata(pdev, info);
 
-       info->usb.name = "usb";
-       info->usb.type = POWER_SUPPLY_TYPE_USB;
-       info->usb.supplied_to = pm860x_supplied_to;
-       info->usb.num_supplicants = ARRAY_SIZE(pm860x_supplied_to);
-       info->usb.properties = pm860x_usb_props;
-       info->usb.num_properties = ARRAY_SIZE(pm860x_usb_props);
-       info->usb.get_property = pm860x_usb_get_prop;
-       ret = power_supply_register(&pdev->dev, &info->usb);
-       if (ret)
+       psy_cfg.drv_data = info;
+       psy_cfg.supplied_to = pm860x_supplied_to;
+       psy_cfg.num_supplicants = ARRAY_SIZE(pm860x_supplied_to);
+       info->usb = power_supply_register(&pdev->dev, &pm860x_charger_desc,
+                                         &psy_cfg);
+       if (IS_ERR(info->usb)) {
+               ret = PTR_ERR(info->usb);
                goto out;
+       }
 
        pm860x_init_charger(info);
 
@@ -711,7 +729,7 @@ static int pm860x_charger_probe(struct platform_device *pdev)
        return 0;
 
 out_irq:
-       power_supply_unregister(&info->usb);
+       power_supply_unregister(info->usb);
        while (--i >= 0)
                free_irq(info->irq[i], info);
 out:
@@ -723,7 +741,7 @@ static int pm860x_charger_remove(struct platform_device *pdev)
        struct pm860x_charger_info *info = platform_get_drvdata(pdev);
        int i;
 
-       power_supply_unregister(&info->usb);
+       power_supply_unregister(info->usb);
        free_irq(info->irq[0], info);
        for (i = 0; i < info->irq_nums; i++)
                free_irq(info->irq[i], info);
index 27b751b995fb245d5a6f7b34dd0a0e5eee4cc851..4091fb092d067aca615a376452db4814a75e0aa6 100644 (file)
@@ -192,6 +192,27 @@ config BATTERY_DA9052
          Say Y here to enable support for batteries charger integrated into
          DA9052 PMIC.
 
+config CHARGER_DA9150
+       tristate "Dialog Semiconductor DA9150 Charger support"
+       depends on MFD_DA9150
+       depends on DA9150_GPADC
+       depends on IIO
+       help
+         Say Y here to enable support for charger unit of the DA9150
+         Integrated Charger & Fuel-Gauge IC.
+
+         This driver can also be built as a module. If so, the module will be
+         called da9150-charger.
+
+config AXP288_FUEL_GAUGE
+       tristate "X-Powers AXP288 Fuel Gauge"
+       depends on MFD_AXP20X && IIO
+       help
+         Say yes here to have support for X-Power power management IC (PMIC)
+         Fuel Gauge. The device provides battery statistics and status
+         monitoring as well as alerts for battery over/under voltage and
+         over/under temperature.
+
 config BATTERY_MAX17040
        tristate "Maxim MAX17040 Fuel Gauge"
        depends on I2C
index 36f9e0d10111f3b6f86eb2c7393cce8db3b2fd06..b7b0181c95e583e453de6210fd0a87d0a9d5f6fc 100644 (file)
@@ -1,4 +1,4 @@
-ccflags-$(CONFIG_POWER_SUPPLY_DEBUG) := -DDEBUG
+subdir-ccflags-$(CONFIG_POWER_SUPPLY_DEBUG) := -DDEBUG
 
 power_supply-y                         := power_supply_core.o
 power_supply-$(CONFIG_SYSFS)           += power_supply_sysfs.o
@@ -32,6 +32,7 @@ obj-$(CONFIG_BATTERY_SBS)     += sbs-battery.o
 obj-$(CONFIG_BATTERY_BQ27x00)  += bq27x00_battery.o
 obj-$(CONFIG_BATTERY_DA9030)   += da9030_battery.o
 obj-$(CONFIG_BATTERY_DA9052)   += da9052-battery.o
+obj-$(CONFIG_CHARGER_DA9150)   += da9150-charger.o
 obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
 obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
 obj-$(CONFIG_BATTERY_Z2)       += z2_battery.o
@@ -62,3 +63,4 @@ obj-$(CONFIG_POWER_AVS)               += avs/
 obj-$(CONFIG_CHARGER_SMB347)   += smb347-charger.o
 obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
 obj-$(CONFIG_POWER_RESET)      += reset/
+obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
index 4ebf7b0819f76837fab13dfb05c448edd07e55c6..8f8044e1acf33910dc495d30abde319a82cd8418 100644 (file)
@@ -45,9 +45,6 @@
 #define BTEMP_BATCTRL_CURR_SRC_60UA    60
 #define BTEMP_BATCTRL_CURR_SRC_120UA   120
 
-#define to_ab8500_btemp_device_info(x) container_of((x), \
-       struct ab8500_btemp, btemp_psy);
-
 /**
  * struct ab8500_btemp_interrupts - ab8500 interrupts
  * @name:      name of the interrupt
@@ -102,7 +99,7 @@ struct ab8500_btemp {
        struct ab8500_gpadc *gpadc;
        struct ab8500_fg *fg;
        struct abx500_bm_data *bm;
-       struct power_supply btemp_psy;
+       struct power_supply *btemp_psy;
        struct ab8500_btemp_events events;
        struct ab8500_btemp_ranges btemp_ranges;
        struct workqueue_struct *btemp_wq;
@@ -654,14 +651,14 @@ static void ab8500_btemp_periodic_work(struct work_struct *work)
                if ((di->bat_temp != di->prev_bat_temp) || !di->initialized) {
                        di->initialized = true;
                        di->bat_temp = bat_temp;
-                       power_supply_changed(&di->btemp_psy);
+                       power_supply_changed(di->btemp_psy);
                }
        } else if (bat_temp < di->prev_bat_temp) {
                di->bat_temp--;
-               power_supply_changed(&di->btemp_psy);
+               power_supply_changed(di->btemp_psy);
        } else if (bat_temp > di->prev_bat_temp) {
                di->bat_temp++;
-               power_supply_changed(&di->btemp_psy);
+               power_supply_changed(di->btemp_psy);
        }
        di->prev_bat_temp = bat_temp;
 
@@ -689,7 +686,7 @@ static irqreturn_t ab8500_btemp_batctrlindb_handler(int irq, void *_di)
        dev_err(di->dev, "Battery removal detected!\n");
 
        di->events.batt_rem = true;
-       power_supply_changed(&di->btemp_psy);
+       power_supply_changed(di->btemp_psy);
 
        return IRQ_HANDLED;
 }
@@ -715,7 +712,7 @@ static irqreturn_t ab8500_btemp_templow_handler(int irq, void *_di)
                di->events.btemp_high = false;
                di->events.btemp_medhigh = false;
                di->events.btemp_lowmed = false;
-               power_supply_changed(&di->btemp_psy);
+               power_supply_changed(di->btemp_psy);
        }
 
        return IRQ_HANDLED;
@@ -738,7 +735,7 @@ static irqreturn_t ab8500_btemp_temphigh_handler(int irq, void *_di)
        di->events.btemp_medhigh = false;
        di->events.btemp_lowmed = false;
        di->events.btemp_low = false;
-       power_supply_changed(&di->btemp_psy);
+       power_supply_changed(di->btemp_psy);
 
        return IRQ_HANDLED;
 }
@@ -760,7 +757,7 @@ static irqreturn_t ab8500_btemp_lowmed_handler(int irq, void *_di)
        di->events.btemp_medhigh = false;
        di->events.btemp_high = false;
        di->events.btemp_low = false;
-       power_supply_changed(&di->btemp_psy);
+       power_supply_changed(di->btemp_psy);
 
        return IRQ_HANDLED;
 }
@@ -782,7 +779,7 @@ static irqreturn_t ab8500_btemp_medhigh_handler(int irq, void *_di)
        di->events.btemp_lowmed = false;
        di->events.btemp_high = false;
        di->events.btemp_low = false;
-       power_supply_changed(&di->btemp_psy);
+       power_supply_changed(di->btemp_psy);
 
        return IRQ_HANDLED;
 }
@@ -884,9 +881,7 @@ static int ab8500_btemp_get_property(struct power_supply *psy,
        enum power_supply_property psp,
        union power_supply_propval *val)
 {
-       struct ab8500_btemp *di;
-
-       di = to_ab8500_btemp_device_info(psy);
+       struct ab8500_btemp *di = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_PRESENT:
@@ -919,14 +914,14 @@ static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
 
        psy = (struct power_supply *)data;
        ext = dev_get_drvdata(dev);
-       di = to_ab8500_btemp_device_info(psy);
+       di = power_supply_get_drvdata(psy);
 
        /*
         * For all psy where the name of your driver
         * appears in any supplied_to
         */
        for (i = 0; i < ext->num_supplicants; i++) {
-               if (!strcmp(ext->supplied_to[i], psy->name))
+               if (!strcmp(ext->supplied_to[i], psy->desc->name))
                        psy_found = true;
        }
 
@@ -934,16 +929,16 @@ static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
                return 0;
 
        /* Go through all properties for the psy */
-       for (j = 0; j < ext->num_properties; j++) {
+       for (j = 0; j < ext->desc->num_properties; j++) {
                enum power_supply_property prop;
-               prop = ext->properties[j];
+               prop = ext->desc->properties[j];
 
-               if (ext->get_property(ext, prop, &ret))
+               if (power_supply_get_property(ext, prop, &ret))
                        continue;
 
                switch (prop) {
                case POWER_SUPPLY_PROP_PRESENT:
-                       switch (ext->type) {
+                       switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_MAINS:
                                /* AC disconnected */
                                if (!ret.intval && di->events.ac_conn) {
@@ -990,10 +985,10 @@ static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
  */
 static void ab8500_btemp_external_power_changed(struct power_supply *psy)
 {
-       struct ab8500_btemp *di = to_ab8500_btemp_device_info(psy);
+       struct ab8500_btemp *di = power_supply_get_drvdata(psy);
 
        class_for_each_device(power_supply_class, NULL,
-               &di->btemp_psy, ab8500_btemp_get_ext_psy_data);
+               di->btemp_psy, ab8500_btemp_get_ext_psy_data);
 }
 
 /* ab8500 btemp driver interrupts and their respective isr */
@@ -1044,7 +1039,7 @@ static int ab8500_btemp_remove(struct platform_device *pdev)
        destroy_workqueue(di->btemp_wq);
 
        flush_scheduled_work();
-       power_supply_unregister(&di->btemp_psy);
+       power_supply_unregister(di->btemp_psy);
 
        return 0;
 }
@@ -1054,10 +1049,20 @@ static char *supply_interface[] = {
        "ab8500_fg",
 };
 
+static const struct power_supply_desc ab8500_btemp_desc = {
+       .name                   = "ab8500_btemp",
+       .type                   = POWER_SUPPLY_TYPE_BATTERY,
+       .properties             = ab8500_btemp_props,
+       .num_properties         = ARRAY_SIZE(ab8500_btemp_props),
+       .get_property           = ab8500_btemp_get_property,
+       .external_power_changed = ab8500_btemp_external_power_changed,
+};
+
 static int ab8500_btemp_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct abx500_bm_data *plat = pdev->dev.platform_data;
+       struct power_supply_config psy_cfg = {};
        struct ab8500_btemp *di;
        int irq, i, ret = 0;
        u8 val;
@@ -1089,17 +1094,9 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
 
        di->initialized = false;
 
-       /* BTEMP supply */
-       di->btemp_psy.name = "ab8500_btemp";
-       di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
-       di->btemp_psy.properties = ab8500_btemp_props;
-       di->btemp_psy.num_properties = ARRAY_SIZE(ab8500_btemp_props);
-       di->btemp_psy.get_property = ab8500_btemp_get_property;
-       di->btemp_psy.supplied_to = supply_interface;
-       di->btemp_psy.num_supplicants = ARRAY_SIZE(supply_interface);
-       di->btemp_psy.external_power_changed =
-               ab8500_btemp_external_power_changed;
-
+       psy_cfg.supplied_to = supply_interface;
+       psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
+       psy_cfg.drv_data = di;
 
        /* Create a work queue for the btemp */
        di->btemp_wq =
@@ -1140,9 +1137,11 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
        }
 
        /* Register BTEMP power supply class */
-       ret = power_supply_register(di->dev, &di->btemp_psy);
-       if (ret) {
+       di->btemp_psy = power_supply_register(di->dev, &ab8500_btemp_desc,
+                                             &psy_cfg);
+       if (IS_ERR(di->btemp_psy)) {
                dev_err(di->dev, "failed to register BTEMP psy\n");
+               ret = PTR_ERR(di->btemp_psy);
                goto free_btemp_wq;
        }
 
@@ -1171,7 +1170,7 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
        return ret;
 
 free_irq:
-       power_supply_unregister(&di->btemp_psy);
+       power_supply_unregister(di->btemp_psy);
 
        /* We also have to free all successfully registered irqs */
        for (i = i - 1; i >= 0; i--) {
index 8c8d170ff0f86533c01d560791f84e7b6bdd2010..e388171f4e587e8931ec44ca32e03b08cd916a0b 100644 (file)
@@ -435,7 +435,7 @@ static void ab8500_charger_set_usb_connected(struct ab8500_charger *di,
                if (!connected)
                        di->flags.vbus_drop_end = false;
 
-               sysfs_notify(&di->usb_chg.psy.dev->kobj, NULL, "present");
+               sysfs_notify(&di->usb_chg.psy->dev.kobj, NULL, "present");
 
                if (connected) {
                        mutex_lock(&di->charger_attached_mutex);
@@ -1516,7 +1516,7 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger,
 
                dev_dbg(di->dev, "%s Disabled AC charging\n", __func__);
        }
-       ab8500_power_supply_changed(di, &di->ac_chg.psy);
+       ab8500_power_supply_changed(di, di->ac_chg.psy);
 
        return ret;
 }
@@ -1672,7 +1672,7 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger,
                cancel_delayed_work(&di->check_vbat_work);
 
        }
-       ab8500_power_supply_changed(di, &di->usb_chg.psy);
+       ab8500_power_supply_changed(di, di->usb_chg.psy);
 
        return ret;
 }
@@ -1811,9 +1811,9 @@ static int ab8500_charger_watchdog_kick(struct ux500_charger *charger)
        int ret;
        struct ab8500_charger *di;
 
-       if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS)
+       if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
                di = to_ab8500_charger_ac_device_info(charger);
-       else if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
+       else if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB)
                di = to_ab8500_charger_usb_device_info(charger);
        else
                return -ENXIO;
@@ -1839,9 +1839,9 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger,
        int ret;
        struct ab8500_charger *di;
 
-       if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS)
+       if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
                di = to_ab8500_charger_ac_device_info(charger);
-       else if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
+       else if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB)
                di = to_ab8500_charger_usb_device_info(charger);
        else
                return -ENXIO;
@@ -1879,7 +1879,7 @@ static int ab8540_charger_power_path_enable(struct ux500_charger *charger,
        int ret;
        struct ab8500_charger *di;
 
-       if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
+       if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB)
                di = to_ab8500_charger_usb_device_info(charger);
        else
                return -ENXIO;
@@ -1910,7 +1910,7 @@ static int ab8540_charger_usb_pre_chg_enable(struct ux500_charger *charger,
        int ret;
        struct ab8500_charger *di;
 
-       if (charger->psy.type == POWER_SUPPLY_TYPE_USB)
+       if (charger->psy->desc->type == POWER_SUPPLY_TYPE_USB)
                di = to_ab8500_charger_usb_device_info(charger);
        else
                return -ENXIO;
@@ -1937,7 +1937,7 @@ static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
        struct ux500_charger *usb_chg;
 
        usb_chg = (struct ux500_charger *)data;
-       psy = &usb_chg->psy;
+       psy = usb_chg->psy;
 
        di = to_ab8500_charger_usb_device_info(usb_chg);
 
@@ -1945,7 +1945,7 @@ static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
 
        /* For all psy where the driver name appears in any supplied_to */
        for (i = 0; i < ext->num_supplicants; i++) {
-               if (!strcmp(ext->supplied_to[i], psy->name))
+               if (!strcmp(ext->supplied_to[i], psy->desc->name))
                        psy_found = true;
        }
 
@@ -1953,16 +1953,16 @@ static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
                return 0;
 
        /* Go through all properties for the psy */
-       for (j = 0; j < ext->num_properties; j++) {
+       for (j = 0; j < ext->desc->num_properties; j++) {
                enum power_supply_property prop;
-               prop = ext->properties[j];
+               prop = ext->desc->properties[j];
 
-               if (ext->get_property(ext, prop, &ret))
+               if (power_supply_get_property(ext, prop, &ret))
                        continue;
 
                switch (prop) {
                case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-                       switch (ext->type) {
+                       switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_BATTERY:
                                di->vbat = ret.intval / 1000;
                                break;
@@ -1993,7 +1993,7 @@ static void ab8500_charger_check_vbat_work(struct work_struct *work)
                struct ab8500_charger, check_vbat_work.work);
 
        class_for_each_device(power_supply_class, NULL,
-               &di->usb_chg.psy, ab8500_charger_get_ext_psy_data);
+               di->usb_chg.psy, ab8500_charger_get_ext_psy_data);
 
        /* First run old_vbat is 0. */
        if (di->old_vbat == 0)
@@ -2009,7 +2009,7 @@ static void ab8500_charger_check_vbat_work(struct work_struct *work)
                        di->vbat, di->old_vbat);
                ab8500_charger_set_vbus_in_curr(di,
                                        di->max_usb_in_curr.usb_type_max);
-               power_supply_changed(&di->usb_chg.psy);
+               power_supply_changed(di->usb_chg.psy);
        }
 
        di->old_vbat = di->vbat;
@@ -2049,7 +2049,7 @@ static void ab8500_charger_check_hw_failure_work(struct work_struct *work)
                }
                if (!(reg_value & MAIN_CH_NOK)) {
                        di->flags.mainextchnotok = false;
-                       ab8500_power_supply_changed(di, &di->ac_chg.psy);
+                       ab8500_power_supply_changed(di, di->ac_chg.psy);
                }
        }
        if (di->flags.vbus_ovv) {
@@ -2062,7 +2062,7 @@ static void ab8500_charger_check_hw_failure_work(struct work_struct *work)
                }
                if (!(reg_value & VBUS_OVV_TH)) {
                        di->flags.vbus_ovv = false;
-                       ab8500_power_supply_changed(di, &di->usb_chg.psy);
+                       ab8500_power_supply_changed(di, di->usb_chg.psy);
                }
        }
        /* If we still have a failure, schedule a new check */
@@ -2132,8 +2132,8 @@ static void ab8500_charger_ac_work(struct work_struct *work)
                di->ac.charger_connected = 0;
        }
 
-       ab8500_power_supply_changed(di, &di->ac_chg.psy);
-       sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present");
+       ab8500_power_supply_changed(di, di->ac_chg.psy);
+       sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present");
 }
 
 static void ab8500_charger_usb_attached_work(struct work_struct *work)
@@ -2240,7 +2240,7 @@ static void ab8500_charger_detect_usb_type_work(struct work_struct *work)
                dev_dbg(di->dev, "%s di->vbus_detected = false\n", __func__);
                di->vbus_detected = false;
                ab8500_charger_set_usb_connected(di, false);
-               ab8500_power_supply_changed(di, &di->usb_chg.psy);
+               ab8500_power_supply_changed(di, di->usb_chg.psy);
        } else {
                dev_dbg(di->dev, "%s di->vbus_detected = true\n", __func__);
                di->vbus_detected = true;
@@ -2250,7 +2250,7 @@ static void ab8500_charger_detect_usb_type_work(struct work_struct *work)
                        if (!ret) {
                                ab8500_charger_set_usb_connected(di, true);
                                ab8500_power_supply_changed(di,
-                                                           &di->usb_chg.psy);
+                                                           di->usb_chg.psy);
                        }
                } else {
                        /*
@@ -2267,7 +2267,7 @@ static void ab8500_charger_detect_usb_type_work(struct work_struct *work)
                                        ab8500_charger_set_usb_connected(di,
                                                true);
                                        ab8500_power_supply_changed(di,
-                                               &di->usb_chg.psy);
+                                               di->usb_chg.psy);
                                }
                        }
                }
@@ -2295,7 +2295,7 @@ static void ab8500_charger_usb_link_attach_work(struct work_struct *work)
        }
 
        ab8500_charger_set_usb_connected(di, true);
-       ab8500_power_supply_changed(di, &di->usb_chg.psy);
+       ab8500_power_supply_changed(di, di->usb_chg.psy);
 }
 
 /**
@@ -2393,7 +2393,7 @@ static void ab8500_charger_usb_link_status_work(struct work_struct *work)
        if (!(detected_chargers & USB_PW_CONN)) {
                di->vbus_detected = false;
                ab8500_charger_set_usb_connected(di, false);
-               ab8500_power_supply_changed(di, &di->usb_chg.psy);
+               ab8500_power_supply_changed(di, di->usb_chg.psy);
                return;
        }
 
@@ -2404,7 +2404,7 @@ static void ab8500_charger_usb_link_status_work(struct work_struct *work)
                if (ret == -ENXIO) {
                        /* No valid charger type detected */
                        ab8500_charger_set_usb_connected(di, false);
-                       ab8500_power_supply_changed(di, &di->usb_chg.psy);
+                       ab8500_power_supply_changed(di, di->usb_chg.psy);
                }
                return;
        }
@@ -2463,7 +2463,7 @@ static void ab8500_charger_usb_state_changed_work(struct work_struct *work)
        case AB8500_BM_USB_STATE_SUSPEND:
        case AB8500_BM_USB_STATE_MAX:
                ab8500_charger_set_usb_connected(di, false);
-               ab8500_power_supply_changed(di, &di->usb_chg.psy);
+               ab8500_power_supply_changed(di, di->usb_chg.psy);
                break;
 
        case AB8500_BM_USB_STATE_RESUME:
@@ -2486,7 +2486,7 @@ static void ab8500_charger_usb_state_changed_work(struct work_struct *work)
                                return;
 
                        ab8500_charger_set_usb_connected(di, true);
-                       ab8500_power_supply_changed(di, &di->usb_chg.psy);
+                       ab8500_power_supply_changed(di, di->usb_chg.psy);
                }
                break;
 
@@ -2530,7 +2530,7 @@ static void ab8500_charger_check_usbchargernotok_work(struct work_struct *work)
        }
 
        if (prev_status != di->flags.usbchargernotok)
-               ab8500_power_supply_changed(di, &di->usb_chg.psy);
+               ab8500_power_supply_changed(di, di->usb_chg.psy);
 }
 
 /**
@@ -2560,7 +2560,7 @@ static void ab8500_charger_check_main_thermal_prot_work(
        else
                di->flags.main_thermal_prot = false;
 
-       ab8500_power_supply_changed(di, &di->ac_chg.psy);
+       ab8500_power_supply_changed(di, di->ac_chg.psy);
 }
 
 /**
@@ -2590,7 +2590,7 @@ static void ab8500_charger_check_usb_thermal_prot_work(
        else
                di->flags.usb_thermal_prot = false;
 
-       ab8500_power_supply_changed(di, &di->usb_chg.psy);
+       ab8500_power_supply_changed(di, di->usb_chg.psy);
 }
 
 /**
@@ -2651,7 +2651,7 @@ static irqreturn_t ab8500_charger_mainextchnotok_handler(int irq, void *_di)
 
        dev_dbg(di->dev, "Main charger not ok\n");
        di->flags.mainextchnotok = true;
-       ab8500_power_supply_changed(di, &di->ac_chg.psy);
+       ab8500_power_supply_changed(di, di->ac_chg.psy);
 
        /* Schedule a new HW failure check */
        queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0);
@@ -2880,11 +2880,11 @@ static irqreturn_t ab8500_charger_chwdexp_handler(int irq, void *_di)
         */
        if (di->ac.charger_online) {
                di->ac.wd_expired = true;
-               ab8500_power_supply_changed(di, &di->ac_chg.psy);
+               ab8500_power_supply_changed(di, di->ac_chg.psy);
        }
        if (di->usb.charger_online) {
                di->usb.wd_expired = true;
-               ab8500_power_supply_changed(di, &di->usb_chg.psy);
+               ab8500_power_supply_changed(di, di->usb_chg.psy);
        }
 
        return IRQ_HANDLED;
@@ -2927,7 +2927,7 @@ static irqreturn_t ab8500_charger_vbusovv_handler(int irq, void *_di)
 
        dev_dbg(di->dev, "VBUS overvoltage detected\n");
        di->flags.vbus_ovv = true;
-       ab8500_power_supply_changed(di, &di->usb_chg.psy);
+       ab8500_power_supply_changed(di, di->usb_chg.psy);
 
        /* Schedule a new HW failure check */
        queue_delayed_work(di->charger_wq, &di->check_hw_failure_work, 0);
@@ -3428,10 +3428,10 @@ static int ab8500_charger_remove(struct platform_device *pdev)
 
        flush_scheduled_work();
        if (di->usb_chg.enabled)
-               power_supply_unregister(&di->usb_chg.psy);
+               power_supply_unregister(di->usb_chg.psy);
 
        if (di->ac_chg.enabled && !di->ac_chg.external)
-               power_supply_unregister(&di->ac_chg.psy);
+               power_supply_unregister(di->ac_chg.psy);
 
        return 0;
 }
@@ -3442,10 +3442,27 @@ static char *supply_interface[] = {
        "ab8500_btemp",
 };
 
+static const struct power_supply_desc ab8500_ac_chg_desc = {
+       .name           = "ab8500_ac",
+       .type           = POWER_SUPPLY_TYPE_MAINS,
+       .properties     = ab8500_charger_ac_props,
+       .num_properties = ARRAY_SIZE(ab8500_charger_ac_props),
+       .get_property   = ab8500_charger_ac_get_property,
+};
+
+static const struct power_supply_desc ab8500_usb_chg_desc = {
+       .name           = "ab8500_usb",
+       .type           = POWER_SUPPLY_TYPE_USB,
+       .properties     = ab8500_charger_usb_props,
+       .num_properties = ARRAY_SIZE(ab8500_charger_usb_props),
+       .get_property   = ab8500_charger_usb_get_property,
+};
+
 static int ab8500_charger_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct abx500_bm_data *plat = pdev->dev.platform_data;
+       struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {};
        struct ab8500_charger *di;
        int irq, i, charger_status, ret = 0, ch_stat;
 
@@ -3483,15 +3500,15 @@ static int ab8500_charger_probe(struct platform_device *pdev)
        di->autopower = false;
        di->invalid_charger_detect_state = 0;
 
+       /* AC and USB supply config */
+       ac_psy_cfg.supplied_to = supply_interface;
+       ac_psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
+       ac_psy_cfg.drv_data = &di->ac_chg;
+       usb_psy_cfg.supplied_to = supply_interface;
+       usb_psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
+       usb_psy_cfg.drv_data = &di->usb_chg;
+
        /* AC supply */
-       /* power_supply base class */
-       di->ac_chg.psy.name = "ab8500_ac";
-       di->ac_chg.psy.type = POWER_SUPPLY_TYPE_MAINS;
-       di->ac_chg.psy.properties = ab8500_charger_ac_props;
-       di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props);
-       di->ac_chg.psy.get_property = ab8500_charger_ac_get_property;
-       di->ac_chg.psy.supplied_to = supply_interface;
-       di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
        /* ux500_charger sub-class */
        di->ac_chg.ops.enable = &ab8500_charger_ac_en;
        di->ac_chg.ops.check_enable = &ab8500_charger_ac_check_enable;
@@ -3511,14 +3528,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
                        &charger_notifier_list, &charger_nb);
 
        /* USB supply */
-       /* power_supply base class */
-       di->usb_chg.psy.name = "ab8500_usb";
-       di->usb_chg.psy.type = POWER_SUPPLY_TYPE_USB;
-       di->usb_chg.psy.properties = ab8500_charger_usb_props;
-       di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props);
-       di->usb_chg.psy.get_property = ab8500_charger_usb_get_property;
-       di->usb_chg.psy.supplied_to = supply_interface;
-       di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
        /* ux500_charger sub-class */
        di->usb_chg.ops.enable = &ab8500_charger_usb_en;
        di->usb_chg.ops.check_enable = &ab8500_charger_usb_check_enable;
@@ -3616,18 +3625,24 @@ static int ab8500_charger_probe(struct platform_device *pdev)
 
        /* Register AC charger class */
        if (di->ac_chg.enabled) {
-               ret = power_supply_register(di->dev, &di->ac_chg.psy);
-               if (ret) {
+               di->ac_chg.psy = power_supply_register(di->dev,
+                                                      &ab8500_ac_chg_desc,
+                                                      &ac_psy_cfg);
+               if (IS_ERR(di->ac_chg.psy)) {
                        dev_err(di->dev, "failed to register AC charger\n");
+                       ret = PTR_ERR(di->ac_chg.psy);
                        goto free_charger_wq;
                }
        }
 
        /* Register USB charger class */
        if (di->usb_chg.enabled) {
-               ret = power_supply_register(di->dev, &di->usb_chg.psy);
-               if (ret) {
+               di->usb_chg.psy = power_supply_register(di->dev,
+                                                       &ab8500_usb_chg_desc,
+                                                       &usb_psy_cfg);
+               if (IS_ERR(di->usb_chg.psy)) {
                        dev_err(di->dev, "failed to register USB charger\n");
+                       ret = PTR_ERR(di->usb_chg.psy);
                        goto free_ac;
                }
        }
@@ -3650,8 +3665,8 @@ static int ab8500_charger_probe(struct platform_device *pdev)
        if (charger_status & AC_PW_CONN) {
                di->ac.charger_connected = 1;
                di->ac_conn = true;
-               ab8500_power_supply_changed(di, &di->ac_chg.psy);
-               sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present");
+               ab8500_power_supply_changed(di, di->ac_chg.psy);
+               sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present");
        }
 
        if (charger_status & USB_PW_CONN) {
@@ -3712,10 +3727,10 @@ put_usb_phy:
        usb_put_phy(di->usb_phy);
 free_usb:
        if (di->usb_chg.enabled)
-               power_supply_unregister(&di->usb_chg.psy);
+               power_supply_unregister(di->usb_chg.psy);
 free_ac:
        if (di->ac_chg.enabled)
-               power_supply_unregister(&di->ac_chg.psy);
+               power_supply_unregister(di->ac_chg.psy);
 free_charger_wq:
        destroy_workqueue(di->charger_wq);
        return ret;
index c908658aa31aa7500ec51b373c2cfa7296dfbebf..3830dade5d69d145a2fe79d0630f891c4f0936d3 100644 (file)
@@ -57,9 +57,6 @@
 #define interpolate(x, x1, y1, x2, y2) \
        ((y1) + ((((y2) - (y1)) * ((x) - (x1))) / ((x2) - (x1))));
 
-#define to_ab8500_fg_device_info(x) container_of((x), \
-       struct ab8500_fg, fg_psy);
-
 /**
  * struct ab8500_fg_interrupts - ab8500 fg interupts
  * @name:      name of the interrupt
@@ -229,7 +226,7 @@ struct ab8500_fg {
        struct ab8500 *parent;
        struct ab8500_gpadc *gpadc;
        struct abx500_bm_data *bm;
-       struct power_supply fg_psy;
+       struct power_supply *fg_psy;
        struct workqueue_struct *fg_wq;
        struct delayed_work fg_periodic_work;
        struct delayed_work fg_low_bat_work;
@@ -622,14 +619,14 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res)
        u8 low, high;
        int val;
        int ret;
-       int timeout;
+       unsigned long timeout;
 
        if (!completion_done(&di->ab8500_fg_complete)) {
                timeout = wait_for_completion_timeout(
                        &di->ab8500_fg_complete,
                        INS_CURR_TIMEOUT);
                dev_dbg(di->dev, "Finalize time: %d ms\n",
-                       ((INS_CURR_TIMEOUT - timeout) * 1000) / HZ);
+                       jiffies_to_msecs(INS_CURR_TIMEOUT - timeout));
                if (!timeout) {
                        ret = -ETIME;
                        disable_irq(di->irq);
@@ -716,7 +713,7 @@ fail:
 int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di)
 {
        int ret;
-       int timeout;
+       unsigned long timeout;
        int res = 0;
 
        ret = ab8500_fg_inst_curr_start(di);
@@ -731,7 +728,7 @@ int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di)
                        &di->ab8500_fg_started,
                        INS_CURR_TIMEOUT);
                dev_dbg(di->dev, "Start time: %d ms\n",
-                       ((INS_CURR_TIMEOUT - timeout) * 1000) / HZ);
+                       jiffies_to_msecs(INS_CURR_TIMEOUT - timeout));
                if (!timeout) {
                        ret = -ETIME;
                        dev_err(di->dev, "completion timed out [%d]\n",
@@ -1391,7 +1388,7 @@ static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init)
                                di->bat_cap.prev_percent,
                                di->bat_cap.cap_scale.scaled_cap);
                }
-               power_supply_changed(&di->fg_psy);
+               power_supply_changed(di->fg_psy);
                if (di->flags.fully_charged && di->flags.force_full) {
                        dev_dbg(di->dev, "Battery full, notifying.\n");
                        di->flags.force_full = false;
@@ -1850,7 +1847,7 @@ static void ab8500_fg_check_hw_failure_work(struct work_struct *work)
                if (!di->flags.bat_ovv) {
                        dev_dbg(di->dev, "Battery OVV\n");
                        di->flags.bat_ovv = true;
-                       power_supply_changed(&di->fg_psy);
+                       power_supply_changed(di->fg_psy);
                }
                /* Not yet recovered from ovv, reschedule this test */
                queue_delayed_work(di->fg_wq, &di->fg_check_hw_failure_work,
@@ -1858,7 +1855,7 @@ static void ab8500_fg_check_hw_failure_work(struct work_struct *work)
                } else {
                        dev_dbg(di->dev, "Battery recovered from OVV\n");
                        di->flags.bat_ovv = false;
-                       power_supply_changed(&di->fg_psy);
+                       power_supply_changed(di->fg_psy);
        }
 }
 
@@ -2096,9 +2093,7 @@ static int ab8500_fg_get_property(struct power_supply *psy,
        enum power_supply_property psp,
        union power_supply_propval *val)
 {
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        /*
         * If battery is identified as unknown and charging of unknown
@@ -2181,14 +2176,14 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data)
 
        psy = (struct power_supply *)data;
        ext = dev_get_drvdata(dev);
-       di = to_ab8500_fg_device_info(psy);
+       di = power_supply_get_drvdata(psy);
 
        /*
         * For all psy where the name of your driver
         * appears in any supplied_to
         */
        for (i = 0; i < ext->num_supplicants; i++) {
-               if (!strcmp(ext->supplied_to[i], psy->name))
+               if (!strcmp(ext->supplied_to[i], psy->desc->name))
                        psy_found = true;
        }
 
@@ -2196,16 +2191,16 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data)
                return 0;
 
        /* Go through all properties for the psy */
-       for (j = 0; j < ext->num_properties; j++) {
+       for (j = 0; j < ext->desc->num_properties; j++) {
                enum power_supply_property prop;
-               prop = ext->properties[j];
+               prop = ext->desc->properties[j];
 
-               if (ext->get_property(ext, prop, &ret))
+               if (power_supply_get_property(ext, prop, &ret))
                        continue;
 
                switch (prop) {
                case POWER_SUPPLY_PROP_STATUS:
-                       switch (ext->type) {
+                       switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_BATTERY:
                                switch (ret.intval) {
                                case POWER_SUPPLY_STATUS_UNKNOWN:
@@ -2244,7 +2239,7 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data)
                        };
                        break;
                case POWER_SUPPLY_PROP_TECHNOLOGY:
-                       switch (ext->type) {
+                       switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_BATTERY:
                                if (!di->flags.batt_id_received &&
                                    di->bm->batt_id != BATTERY_UNKNOWN) {
@@ -2274,7 +2269,7 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data)
                        }
                        break;
                case POWER_SUPPLY_PROP_TEMP:
-                       switch (ext->type) {
+                       switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_BATTERY:
                                if (di->flags.batt_id_received)
                                        di->bat_temp = ret.intval;
@@ -2399,10 +2394,10 @@ out:
  */
 static void ab8500_fg_external_power_changed(struct power_supply *psy)
 {
-       struct ab8500_fg *di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        class_for_each_device(power_supply_class, NULL,
-               &di->fg_psy, ab8500_fg_get_ext_psy_data);
+               di->fg_psy, ab8500_fg_get_ext_psy_data);
 }
 
 /**
@@ -2580,9 +2575,7 @@ static ssize_t ab8505_powercut_flagtime_read(struct device *dev,
        int ret;
        u8 reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
                AB8505_RTC_PCUT_FLAG_TIME_REG, &reg_value);
@@ -2605,9 +2598,7 @@ static ssize_t ab8505_powercut_flagtime_write(struct device *dev,
        int ret;
        long unsigned reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        reg_value = simple_strtoul(buf, NULL, 10);
 
@@ -2633,9 +2624,7 @@ static ssize_t ab8505_powercut_maxtime_read(struct device *dev,
        int ret;
        u8 reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
                AB8505_RTC_PCUT_MAX_TIME_REG, &reg_value);
@@ -2659,9 +2648,7 @@ static ssize_t ab8505_powercut_maxtime_write(struct device *dev,
        int ret;
        int reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        reg_value = simple_strtoul(buf, NULL, 10);
        if (reg_value > 0x7F) {
@@ -2686,9 +2673,7 @@ static ssize_t ab8505_powercut_restart_read(struct device *dev,
        int ret;
        u8 reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
                AB8505_RTC_PCUT_RESTART_REG, &reg_value);
@@ -2711,9 +2696,7 @@ static ssize_t ab8505_powercut_restart_write(struct device *dev,
        int ret;
        int reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        reg_value = simple_strtoul(buf, NULL, 10);
        if (reg_value > 0xF) {
@@ -2739,9 +2722,7 @@ static ssize_t ab8505_powercut_timer_read(struct device *dev,
        int ret;
        u8 reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
                                                AB8505_RTC_PCUT_TIME_REG, &reg_value);
@@ -2764,9 +2745,7 @@ static ssize_t ab8505_powercut_restart_counter_read(struct device *dev,
        int ret;
        u8 reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
                                                AB8505_RTC_PCUT_RESTART_REG, &reg_value);
@@ -2789,9 +2768,7 @@ static ssize_t ab8505_powercut_read(struct device *dev,
        int ret;
        u8 reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
                                                AB8505_RTC_PCUT_CTL_STATUS_REG, &reg_value);
@@ -2812,9 +2789,7 @@ static ssize_t ab8505_powercut_write(struct device *dev,
        int ret;
        int reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        reg_value = simple_strtoul(buf, NULL, 10);
        if (reg_value > 0x1) {
@@ -2840,9 +2815,7 @@ static ssize_t ab8505_powercut_flag_read(struct device *dev,
        int ret;
        u8 reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
                                                AB8505_RTC_PCUT_CTL_STATUS_REG,  &reg_value);
@@ -2865,9 +2838,7 @@ static ssize_t ab8505_powercut_debounce_read(struct device *dev,
        int ret;
        u8 reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
                                                AB8505_RTC_PCUT_DEBOUNCE_REG,  &reg_value);
@@ -2890,9 +2861,7 @@ static ssize_t ab8505_powercut_debounce_write(struct device *dev,
        int ret;
        int reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        reg_value = simple_strtoul(buf, NULL, 10);
        if (reg_value > 0x7) {
@@ -2917,9 +2886,7 @@ static ssize_t ab8505_powercut_enable_status_read(struct device *dev,
        int ret;
        u8 reg_value;
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
+       struct ab8500_fg *di = power_supply_get_drvdata(psy);
 
        ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
                                                AB8505_RTC_PCUT_CTL_STATUS_REG, &reg_value);
@@ -2954,44 +2921,38 @@ static struct device_attribute ab8505_fg_sysfs_psy_attrs[] = {
                ab8505_powercut_enable_status_read, NULL),
 };
 
-static int ab8500_fg_sysfs_psy_create_attrs(struct device *dev)
+static int ab8500_fg_sysfs_psy_create_attrs(struct ab8500_fg *di)
 {
        unsigned int i;
-       struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
 
        if (((is_ab8505(di->parent) || is_ab9540(di->parent)) &&
-            abx500_get_chip_id(dev->parent) >= AB8500_CUT2P0)
+            abx500_get_chip_id(di->dev) >= AB8500_CUT2P0)
            || is_ab8540(di->parent)) {
                for (i = 0; i < ARRAY_SIZE(ab8505_fg_sysfs_psy_attrs); i++)
-                       if (device_create_file(dev,
+                       if (device_create_file(&di->fg_psy->dev,
                                               &ab8505_fg_sysfs_psy_attrs[i]))
                                goto sysfs_psy_create_attrs_failed_ab8505;
        }
        return 0;
 sysfs_psy_create_attrs_failed_ab8505:
-       dev_err(dev, "Failed creating sysfs psy attrs for ab8505.\n");
+       dev_err(&di->fg_psy->dev, "Failed creating sysfs psy attrs for ab8505.\n");
        while (i--)
-               device_remove_file(dev, &ab8505_fg_sysfs_psy_attrs[i]);
+               device_remove_file(&di->fg_psy->dev,
+                                  &ab8505_fg_sysfs_psy_attrs[i]);
 
        return -EIO;
 }
 
-static void ab8500_fg_sysfs_psy_remove_attrs(struct device *dev)
+static void ab8500_fg_sysfs_psy_remove_attrs(struct ab8500_fg *di)
 {
        unsigned int i;
-       struct power_supply *psy = dev_get_drvdata(dev);
-       struct ab8500_fg *di;
-
-       di = to_ab8500_fg_device_info(psy);
 
        if (((is_ab8505(di->parent) || is_ab9540(di->parent)) &&
-            abx500_get_chip_id(dev->parent) >= AB8500_CUT2P0)
+            abx500_get_chip_id(di->dev) >= AB8500_CUT2P0)
            || is_ab8540(di->parent)) {
                for (i = 0; i < ARRAY_SIZE(ab8505_fg_sysfs_psy_attrs); i++)
-                       (void)device_remove_file(dev, &ab8505_fg_sysfs_psy_attrs[i]);
+                       (void)device_remove_file(&di->fg_psy->dev,
+                                                &ab8505_fg_sysfs_psy_attrs[i]);
        }
 }
 
@@ -3056,17 +3017,20 @@ static int ab8500_fg_remove(struct platform_device *pdev)
        ab8500_fg_sysfs_exit(di);
 
        flush_scheduled_work();
-       ab8500_fg_sysfs_psy_remove_attrs(di->fg_psy.dev);
-       power_supply_unregister(&di->fg_psy);
+       ab8500_fg_sysfs_psy_remove_attrs(di);
+       power_supply_unregister(di->fg_psy);
        return ret;
 }
 
 /* ab8500 fg driver interrupts and their respective isr */
-static struct ab8500_fg_interrupts ab8500_fg_irq[] = {
+static struct ab8500_fg_interrupts ab8500_fg_irq_th[] = {
        {"NCONV_ACCU", ab8500_fg_cc_convend_handler},
        {"BATT_OVV", ab8500_fg_batt_ovv_handler},
        {"LOW_BAT_F", ab8500_fg_lowbatf_handler},
        {"CC_INT_CALIB", ab8500_fg_cc_int_calib_handler},
+};
+
+static struct ab8500_fg_interrupts ab8500_fg_irq_bh[] = {
        {"CCEOC", ab8500_fg_cc_data_end_handler},
 };
 
@@ -3075,10 +3039,20 @@ static char *supply_interface[] = {
        "ab8500_usb",
 };
 
+static const struct power_supply_desc ab8500_fg_desc = {
+       .name                   = "ab8500_fg",
+       .type                   = POWER_SUPPLY_TYPE_BATTERY,
+       .properties             = ab8500_fg_props,
+       .num_properties         = ARRAY_SIZE(ab8500_fg_props),
+       .get_property           = ab8500_fg_get_property,
+       .external_power_changed = ab8500_fg_external_power_changed,
+};
+
 static int ab8500_fg_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct abx500_bm_data *plat = pdev->dev.platform_data;
+       struct power_supply_config psy_cfg = {};
        struct ab8500_fg *di;
        int i, irq;
        int ret = 0;
@@ -3110,14 +3084,9 @@ static int ab8500_fg_probe(struct platform_device *pdev)
        di->parent = dev_get_drvdata(pdev->dev.parent);
        di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
 
-       di->fg_psy.name = "ab8500_fg";
-       di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY;
-       di->fg_psy.properties = ab8500_fg_props;
-       di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props);
-       di->fg_psy.get_property = ab8500_fg_get_property;
-       di->fg_psy.supplied_to = supply_interface;
-       di->fg_psy.num_supplicants = ARRAY_SIZE(supply_interface),
-       di->fg_psy.external_power_changed = ab8500_fg_external_power_changed;
+       psy_cfg.supplied_to = supply_interface;
+       psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
+       psy_cfg.drv_data = di;
 
        di->bat_cap.max_mah_design = MILLI_TO_MICRO *
                di->bm->bat_type[di->bm->batt_id].charge_full_design;
@@ -3178,9 +3147,10 @@ static int ab8500_fg_probe(struct platform_device *pdev)
        di->flags.batt_id_received = false;
 
        /* Register FG power supply class */
-       ret = power_supply_register(di->dev, &di->fg_psy);
-       if (ret) {
+       di->fg_psy = power_supply_register(di->dev, &ab8500_fg_desc, &psy_cfg);
+       if (IS_ERR(di->fg_psy)) {
                dev_err(di->dev, "failed to register FG psy\n");
+               ret = PTR_ERR(di->fg_psy);
                goto free_inst_curr_wq;
        }
 
@@ -3194,21 +3164,36 @@ static int ab8500_fg_probe(struct platform_device *pdev)
        init_completion(&di->ab8500_fg_started);
        init_completion(&di->ab8500_fg_complete);
 
-       /* Register interrupts */
-       for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq); i++) {
-               irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name);
-               ret = request_threaded_irq(irq, NULL, ab8500_fg_irq[i].isr,
-                       IRQF_SHARED | IRQF_NO_SUSPEND,
-                       ab8500_fg_irq[i].name, di);
+       /* Register primary interrupt handlers */
+       for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq_th); i++) {
+               irq = platform_get_irq_byname(pdev, ab8500_fg_irq_th[i].name);
+               ret = request_irq(irq, ab8500_fg_irq_th[i].isr,
+                                 IRQF_SHARED | IRQF_NO_SUSPEND,
+                                 ab8500_fg_irq_th[i].name, di);
 
                if (ret != 0) {
-                       dev_err(di->dev, "failed to request %s IRQ %d: %d\n"
-                               , ab8500_fg_irq[i].name, irq, ret);
+                       dev_err(di->dev, "failed to request %s IRQ %d: %d\n",
+                               ab8500_fg_irq_th[i].name, irq, ret);
                        goto free_irq;
                }
                dev_dbg(di->dev, "Requested %s IRQ %d: %d\n",
-                       ab8500_fg_irq[i].name, irq, ret);
+                       ab8500_fg_irq_th[i].name, irq, ret);
        }
+
+       /* Register threaded interrupt handler */
+       irq = platform_get_irq_byname(pdev, ab8500_fg_irq_bh[0].name);
+       ret = request_threaded_irq(irq, NULL, ab8500_fg_irq_bh[0].isr,
+                               IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT,
+                       ab8500_fg_irq_bh[0].name, di);
+
+       if (ret != 0) {
+               dev_err(di->dev, "failed to request %s IRQ %d: %d\n",
+                       ab8500_fg_irq_bh[0].name, irq, ret);
+               goto free_irq;
+       }
+       dev_dbg(di->dev, "Requested %s IRQ %d: %d\n",
+               ab8500_fg_irq_bh[0].name, irq, ret);
+
        di->irq = platform_get_irq_byname(pdev, "CCEOC");
        disable_irq(di->irq);
        di->nbr_cceoc_irq_cnt = 0;
@@ -3221,7 +3206,7 @@ static int ab8500_fg_probe(struct platform_device *pdev)
                goto free_irq;
        }
 
-       ret = ab8500_fg_sysfs_psy_create_attrs(di->fg_psy.dev);
+       ret = ab8500_fg_sysfs_psy_create_attrs(di);
        if (ret) {
                dev_err(di->dev, "failed to create FG psy\n");
                ab8500_fg_sysfs_exit(di);
@@ -3243,13 +3228,15 @@ static int ab8500_fg_probe(struct platform_device *pdev)
        return ret;
 
 free_irq:
-       power_supply_unregister(&di->fg_psy);
+       power_supply_unregister(di->fg_psy);
 
-       /* We also have to free all successfully registered irqs */
-       for (i = i - 1; i >= 0; i--) {
-               irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name);
+       /* We also have to free all registered irqs */
+       for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq_th); i++) {
+               irq = platform_get_irq_byname(pdev, ab8500_fg_irq_th[i].name);
                free_irq(irq, di);
        }
+       irq = platform_get_irq_byname(pdev, ab8500_fg_irq_bh[0].name);
+       free_irq(irq, di);
 free_inst_curr_wq:
        destroy_workqueue(di->fg_wq);
        return ret;
index ab54b8dea670eaa3759e3488f12d2768dcc886b8..541f702e0451c732b7d00efed27fd53f05b03b79 100644 (file)
@@ -50,9 +50,6 @@
 #define CHARGALG_CURR_STEP_LOW         0
 #define CHARGALG_CURR_STEP_HIGH        100
 
-#define to_abx500_chargalg_device_info(x) container_of((x), \
-       struct abx500_chargalg, chargalg_psy);
-
 enum abx500_chargers {
        NO_CHG,
        AC_CHG,
@@ -256,7 +253,7 @@ struct abx500_chargalg {
        struct ab8500 *parent;
        struct abx500_chargalg_current_step_status curr_status;
        struct abx500_bm_data *bm;
-       struct power_supply chargalg_psy;
+       struct power_supply *chargalg_psy;
        struct ux500_charger *ac_chg;
        struct ux500_charger *usb_chg;
        struct abx500_chargalg_events events;
@@ -695,7 +692,7 @@ static void abx500_chargalg_stop_charging(struct abx500_chargalg *di)
        di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
        di->maintenance_chg = false;
        cancel_delayed_work(&di->chargalg_wd_work);
-       power_supply_changed(&di->chargalg_psy);
+       power_supply_changed(di->chargalg_psy);
 }
 
 /**
@@ -715,7 +712,7 @@ static void abx500_chargalg_hold_charging(struct abx500_chargalg *di)
        di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
        di->maintenance_chg = false;
        cancel_delayed_work(&di->chargalg_wd_work);
-       power_supply_changed(&di->chargalg_psy);
+       power_supply_changed(di->chargalg_psy);
 }
 
 /**
@@ -842,7 +839,7 @@ static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di)
                        di->charge_status = POWER_SUPPLY_STATUS_FULL;
                        di->maintenance_chg = true;
                        dev_dbg(di->dev, "EOC reached!\n");
-                       power_supply_changed(&di->chargalg_psy);
+                       power_supply_changed(di->chargalg_psy);
                } else {
                        dev_dbg(di->dev,
                                " EOC limit reached for the %d"
@@ -987,10 +984,10 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
 
        psy = (struct power_supply *)data;
        ext = dev_get_drvdata(dev);
-       di = to_abx500_chargalg_device_info(psy);
+       di = power_supply_get_drvdata(psy);
        /* For all psy where the driver name appears in any supplied_to */
        for (i = 0; i < ext->num_supplicants; i++) {
-               if (!strcmp(ext->supplied_to[i], psy->name))
+               if (!strcmp(ext->supplied_to[i], psy->desc->name))
                        psy_found = true;
        }
        if (!psy_found)
@@ -1001,29 +998,31 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
         * property because of handling that sysfs entry on its own, this is
         * the place to get the battery capacity.
         */
-       if (!ext->get_property(ext, POWER_SUPPLY_PROP_CAPACITY, &ret)) {
+       if (!power_supply_get_property(ext, POWER_SUPPLY_PROP_CAPACITY, &ret)) {
                di->batt_data.percent = ret.intval;
                capacity_updated = true;
        }
 
        /* Go through all properties for the psy */
-       for (j = 0; j < ext->num_properties; j++) {
+       for (j = 0; j < ext->desc->num_properties; j++) {
                enum power_supply_property prop;
-               prop = ext->properties[j];
+               prop = ext->desc->properties[j];
 
-               /* Initialize chargers if not already done */
+               /*
+                * Initialize chargers if not already done.
+                * The ab8500_charger*/
                if (!di->ac_chg &&
-                       ext->type == POWER_SUPPLY_TYPE_MAINS)
+                       ext->desc->type == POWER_SUPPLY_TYPE_MAINS)
                        di->ac_chg = psy_to_ux500_charger(ext);
                else if (!di->usb_chg &&
-                       ext->type == POWER_SUPPLY_TYPE_USB)
+                       ext->desc->type == POWER_SUPPLY_TYPE_USB)
                        di->usb_chg = psy_to_ux500_charger(ext);
 
-               if (ext->get_property(ext, prop, &ret))
+               if (power_supply_get_property(ext, prop, &ret))
                        continue;
                switch (prop) {
                case POWER_SUPPLY_PROP_PRESENT:
-                       switch (ext->type) {
+                       switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_BATTERY:
                                /* Battery present */
                                if (ret.intval)
@@ -1070,7 +1069,7 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
                        break;
 
                case POWER_SUPPLY_PROP_ONLINE:
-                       switch (ext->type) {
+                       switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_BATTERY:
                                break;
                        case POWER_SUPPLY_TYPE_MAINS:
@@ -1115,7 +1114,7 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
                        break;
 
                case POWER_SUPPLY_PROP_HEALTH:
-                       switch (ext->type) {
+                       switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_BATTERY:
                                break;
                        case POWER_SUPPLY_TYPE_MAINS:
@@ -1198,7 +1197,7 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
                        break;
 
                case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-                       switch (ext->type) {
+                       switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_BATTERY:
                                di->batt_data.volt = ret.intval / 1000;
                                break;
@@ -1214,7 +1213,7 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
                        break;
 
                case POWER_SUPPLY_PROP_VOLTAGE_AVG:
-                       switch (ext->type) {
+                       switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_MAINS:
                                /* AVG is used to indicate when we are
                                 * in CV mode */
@@ -1239,7 +1238,7 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
                        break;
 
                case POWER_SUPPLY_PROP_TECHNOLOGY:
-                       switch (ext->type) {
+                       switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_BATTERY:
                                if (ret.intval)
                                        di->events.batt_unknown = false;
@@ -1257,7 +1256,7 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
                        break;
 
                case POWER_SUPPLY_PROP_CURRENT_NOW:
-                       switch (ext->type) {
+                       switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_MAINS:
                                        di->chg_info.ac_curr =
                                                ret.intval / 1000;
@@ -1275,7 +1274,7 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
                        break;
 
                case POWER_SUPPLY_PROP_CURRENT_AVG:
-                       switch (ext->type) {
+                       switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_BATTERY:
                                di->batt_data.avg_curr = ret.intval / 1000;
                                break;
@@ -1311,7 +1310,7 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
  */
 static void abx500_chargalg_external_power_changed(struct power_supply *psy)
 {
-       struct abx500_chargalg *di = to_abx500_chargalg_device_info(psy);
+       struct abx500_chargalg *di = power_supply_get_drvdata(psy);
 
        /*
         * Trigger execution of the algorithm instantly and read
@@ -1336,7 +1335,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
 
        /* Collect data from all power_supply class devices */
        class_for_each_device(power_supply_class, NULL,
-               &di->chargalg_psy, abx500_chargalg_get_ext_psy_data);
+               di->chargalg_psy, abx500_chargalg_get_ext_psy_data);
 
        abx500_chargalg_end_of_charge(di);
        abx500_chargalg_check_temp(di);
@@ -1478,7 +1477,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
                di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
                di->maintenance_chg = false;
                abx500_chargalg_state_to(di, STATE_SUSPENDED);
-               power_supply_changed(&di->chargalg_psy);
+               power_supply_changed(di->chargalg_psy);
                /* Intentional fallthrough */
 
        case STATE_SUSPENDED:
@@ -1576,7 +1575,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
                di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
                di->eoc_cnt = 0;
                di->maintenance_chg = false;
-               power_supply_changed(&di->chargalg_psy);
+               power_supply_changed(di->chargalg_psy);
 
                break;
 
@@ -1624,7 +1623,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
                        di->bm->bat_type[
                                di->bm->batt_id].maint_a_cur_lvl);
                abx500_chargalg_state_to(di, STATE_MAINTENANCE_A);
-               power_supply_changed(&di->chargalg_psy);
+               power_supply_changed(di->chargalg_psy);
                /* Intentional fallthrough*/
 
        case STATE_MAINTENANCE_A:
@@ -1644,7 +1643,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
                        di->bm->bat_type[
                                di->bm->batt_id].maint_b_cur_lvl);
                abx500_chargalg_state_to(di, STATE_MAINTENANCE_B);
-               power_supply_changed(&di->chargalg_psy);
+               power_supply_changed(di->chargalg_psy);
                /* Intentional fallthrough*/
 
        case STATE_MAINTENANCE_B:
@@ -1663,7 +1662,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
                abx500_chargalg_stop_maintenance_timer(di);
                di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
                abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH);
-               power_supply_changed(&di->chargalg_psy);
+               power_supply_changed(di->chargalg_psy);
                /* Intentional fallthrough */
 
        case STATE_TEMP_LOWHIGH:
@@ -1779,9 +1778,7 @@ static int abx500_chargalg_get_property(struct power_supply *psy,
        enum power_supply_property psp,
        union power_supply_propval *val)
 {
-       struct abx500_chargalg *di;
-
-       di = to_abx500_chargalg_device_info(psy);
+       struct abx500_chargalg *di = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
@@ -2034,7 +2031,7 @@ static int abx500_chargalg_remove(struct platform_device *pdev)
        /* Delete the work queue */
        destroy_workqueue(di->chargalg_wq);
 
-       power_supply_unregister(&di->chargalg_psy);
+       power_supply_unregister(di->chargalg_psy);
 
        return 0;
 }
@@ -2043,10 +2040,20 @@ static char *supply_interface[] = {
        "ab8500_fg",
 };
 
+static const struct power_supply_desc abx500_chargalg_desc = {
+       .name                   = "abx500_chargalg",
+       .type                   = POWER_SUPPLY_TYPE_BATTERY,
+       .properties             = abx500_chargalg_props,
+       .num_properties         = ARRAY_SIZE(abx500_chargalg_props),
+       .get_property           = abx500_chargalg_get_property,
+       .external_power_changed = abx500_chargalg_external_power_changed,
+};
+
 static int abx500_chargalg_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct abx500_bm_data *plat = pdev->dev.platform_data;
+       struct power_supply_config psy_cfg = {};
        struct abx500_chargalg *di;
        int ret = 0;
 
@@ -2074,16 +2081,9 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
        di->dev = &pdev->dev;
        di->parent = dev_get_drvdata(pdev->dev.parent);
 
-       /* chargalg supply */
-       di->chargalg_psy.name = "abx500_chargalg";
-       di->chargalg_psy.type = POWER_SUPPLY_TYPE_BATTERY;
-       di->chargalg_psy.properties = abx500_chargalg_props;
-       di->chargalg_psy.num_properties = ARRAY_SIZE(abx500_chargalg_props);
-       di->chargalg_psy.get_property = abx500_chargalg_get_property;
-       di->chargalg_psy.supplied_to = supply_interface;
-       di->chargalg_psy.num_supplicants = ARRAY_SIZE(supply_interface),
-       di->chargalg_psy.external_power_changed =
-               abx500_chargalg_external_power_changed;
+       psy_cfg.supplied_to = supply_interface;
+       psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
+       psy_cfg.drv_data = di;
 
        /* Initilialize safety timer */
        hrtimer_init(&di->safety_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
@@ -2115,9 +2115,11 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
        di->chg_info.prev_conn_chg = -1;
 
        /* Register chargalg power supply class */
-       ret = power_supply_register(di->dev, &di->chargalg_psy);
-       if (ret) {
+       di->chargalg_psy = power_supply_register(di->dev, &abx500_chargalg_desc,
+                                                &psy_cfg);
+       if (IS_ERR(di->chargalg_psy)) {
                dev_err(di->dev, "failed to register chargalg psy\n");
+               ret = PTR_ERR(di->chargalg_psy);
                goto free_chargalg_wq;
        }
 
@@ -2138,7 +2140,7 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
        return ret;
 
 free_psy:
-       power_supply_unregister(&di->chargalg_psy);
+       power_supply_unregister(di->chargalg_psy);
 free_chargalg_wq:
        destroy_workqueue(di->chargalg_wq);
        return ret;
index 39763015b3601cdd0333f585cc482beacbe7ae49..9d1a7fbcaed4226d1893ea610299dcff31687f07 100644 (file)
 #include <linux/apm-emulation.h>
 
 
-#define PSY_PROP(psy, prop, val) (psy->get_property(psy, \
+#define PSY_PROP(psy, prop, val) (power_supply_get_property(psy, \
                         POWER_SUPPLY_PROP_##prop, val))
 
-#define _MPSY_PROP(prop, val) (main_battery->get_property(main_battery, \
+#define _MPSY_PROP(prop, val) (power_supply_get_property(main_battery, \
                                                         prop, val))
 
 #define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val)
@@ -48,7 +48,7 @@ static int __find_main_battery(struct device *dev, void *data)
 
        bp->bat = dev_get_drvdata(dev);
 
-       if (bp->bat->use_for_apm) {
+       if (bp->bat->desc->use_for_apm) {
                /* nice, we explicitly asked to report this battery. */
                bp->main = bp->bat;
                return 1;
diff --git a/drivers/power/axp288_fuel_gauge.c b/drivers/power/axp288_fuel_gauge.c
new file mode 100644 (file)
index 0000000..ca1cc5a
--- /dev/null
@@ -0,0 +1,1154 @@
+/*
+ * axp288_fuel_gauge.c - Xpower AXP288 PMIC Fuel Gauge Driver
+ *
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/iio/consumer.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#define CHRG_STAT_BAT_SAFE_MODE                (1 << 3)
+#define CHRG_STAT_BAT_VALID                    (1 << 4)
+#define CHRG_STAT_BAT_PRESENT          (1 << 5)
+#define CHRG_STAT_CHARGING                     (1 << 6)
+#define CHRG_STAT_PMIC_OTP                     (1 << 7)
+
+#define CHRG_CCCV_CC_MASK                      0xf     /* 4 bits */
+#define CHRG_CCCV_CC_BIT_POS           0
+#define CHRG_CCCV_CC_OFFSET                    200     /* 200mA */
+#define CHRG_CCCV_CC_LSB_RES           200     /* 200mA */
+#define CHRG_CCCV_ITERM_20P                    (1 << 4)    /* 20% of CC */
+#define CHRG_CCCV_CV_MASK                      0x60        /* 2 bits */
+#define CHRG_CCCV_CV_BIT_POS           5
+#define CHRG_CCCV_CV_4100MV                    0x0     /* 4.10V */
+#define CHRG_CCCV_CV_4150MV                    0x1     /* 4.15V */
+#define CHRG_CCCV_CV_4200MV                    0x2     /* 4.20V */
+#define CHRG_CCCV_CV_4350MV                    0x3     /* 4.35V */
+#define CHRG_CCCV_CHG_EN                       (1 << 7)
+
+#define CV_4100                                                4100    /* 4100mV */
+#define CV_4150                                                4150    /* 4150mV */
+#define CV_4200                                                4200    /* 4200mV */
+#define CV_4350                                                4350    /* 4350mV */
+
+#define TEMP_IRQ_CFG_QWBTU                     (1 << 0)
+#define TEMP_IRQ_CFG_WBTU                      (1 << 1)
+#define TEMP_IRQ_CFG_QWBTO                     (1 << 2)
+#define TEMP_IRQ_CFG_WBTO                      (1 << 3)
+#define TEMP_IRQ_CFG_MASK                      0xf
+
+#define FG_IRQ_CFG_LOWBATT_WL2         (1 << 0)
+#define FG_IRQ_CFG_LOWBATT_WL1         (1 << 1)
+#define FG_IRQ_CFG_LOWBATT_MASK                0x3
+#define LOWBAT_IRQ_STAT_LOWBATT_WL2    (1 << 0)
+#define LOWBAT_IRQ_STAT_LOWBATT_WL1    (1 << 1)
+
+#define FG_CNTL_OCV_ADJ_STAT           (1 << 2)
+#define FG_CNTL_OCV_ADJ_EN                     (1 << 3)
+#define FG_CNTL_CAP_ADJ_STAT           (1 << 4)
+#define FG_CNTL_CAP_ADJ_EN                     (1 << 5)
+#define FG_CNTL_CC_EN                          (1 << 6)
+#define FG_CNTL_GAUGE_EN                       (1 << 7)
+
+#define FG_REP_CAP_VALID                       (1 << 7)
+#define FG_REP_CAP_VAL_MASK                    0x7F
+
+#define FG_DES_CAP1_VALID                      (1 << 7)
+#define FG_DES_CAP1_VAL_MASK           0x7F
+#define FG_DES_CAP0_VAL_MASK           0xFF
+#define FG_DES_CAP_RES_LSB                     1456    /* 1.456mAhr */
+
+#define FG_CC_MTR1_VALID                       (1 << 7)
+#define FG_CC_MTR1_VAL_MASK                    0x7F
+#define FG_CC_MTR0_VAL_MASK                    0xFF
+#define FG_DES_CC_RES_LSB                      1456    /* 1.456mAhr */
+
+#define FG_OCV_CAP_VALID                       (1 << 7)
+#define FG_OCV_CAP_VAL_MASK                    0x7F
+#define FG_CC_CAP_VALID                                (1 << 7)
+#define FG_CC_CAP_VAL_MASK                     0x7F
+
+#define FG_LOW_CAP_THR1_MASK           0xf0    /* 5% tp 20% */
+#define FG_LOW_CAP_THR1_VAL                    0xa0    /* 15 perc */
+#define FG_LOW_CAP_THR2_MASK           0x0f    /* 0% to 15% */
+#define FG_LOW_CAP_WARN_THR                    14  /* 14 perc */
+#define FG_LOW_CAP_CRIT_THR                    4   /* 4 perc */
+#define FG_LOW_CAP_SHDN_THR                    0   /* 0 perc */
+
+#define STATUS_MON_DELAY_JIFFIES    (HZ * 60)   /*60 sec */
+#define NR_RETRY_CNT    3
+#define DEV_NAME       "axp288_fuel_gauge"
+
+/* 1.1mV per LSB expressed in uV */
+#define VOLTAGE_FROM_ADC(a)                    ((a * 11) / 10)
+/* properties converted to tenths of degrees, uV, uA, uW */
+#define PROP_TEMP(a)           ((a) * 10)
+#define UNPROP_TEMP(a)         ((a) / 10)
+#define PROP_VOLT(a)           ((a) * 1000)
+#define PROP_CURR(a)           ((a) * 1000)
+
+#define AXP288_FG_INTR_NUM     6
+enum {
+       QWBTU_IRQ = 0,
+       WBTU_IRQ,
+       QWBTO_IRQ,
+       WBTO_IRQ,
+       WL2_IRQ,
+       WL1_IRQ,
+};
+
+struct axp288_fg_info {
+       struct platform_device *pdev;
+       struct axp20x_fg_pdata *pdata;
+       struct regmap *regmap;
+       struct regmap_irq_chip_data *regmap_irqc;
+       int irq[AXP288_FG_INTR_NUM];
+       struct power_supply *bat;
+       struct mutex lock;
+       int status;
+       struct delayed_work status_monitor;
+       struct dentry *debug_file;
+};
+
+static enum power_supply_property fuel_gauge_props[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+       POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_VOLTAGE_OCV,
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN,
+       POWER_SUPPLY_PROP_TEMP,
+       POWER_SUPPLY_PROP_TEMP_MAX,
+       POWER_SUPPLY_PROP_TEMP_MIN,
+       POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
+       POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
+       POWER_SUPPLY_PROP_TECHNOLOGY,
+       POWER_SUPPLY_PROP_CHARGE_FULL,
+       POWER_SUPPLY_PROP_CHARGE_NOW,
+       POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+       POWER_SUPPLY_PROP_MODEL_NAME,
+};
+
+static int fuel_gauge_reg_readb(struct axp288_fg_info *info, int reg)
+{
+       int ret, i;
+       unsigned int val;
+
+       for (i = 0; i < NR_RETRY_CNT; i++) {
+               ret = regmap_read(info->regmap, reg, &val);
+               if (ret == -EBUSY)
+                       continue;
+               else
+                       break;
+       }
+
+       if (ret < 0)
+               dev_err(&info->pdev->dev, "axp288 reg read err:%d\n", ret);
+
+       return val;
+}
+
+static int fuel_gauge_reg_writeb(struct axp288_fg_info *info, int reg, u8 val)
+{
+       int ret;
+
+       ret = regmap_write(info->regmap, reg, (unsigned int)val);
+
+       if (ret < 0)
+               dev_err(&info->pdev->dev, "axp288 reg write err:%d\n", ret);
+
+       return ret;
+}
+
+static int pmic_read_adc_val(const char *name, int *raw_val,
+               struct axp288_fg_info *info)
+{
+       int ret, val = 0;
+       struct iio_channel *indio_chan;
+
+       indio_chan = iio_channel_get(NULL, name);
+       if (IS_ERR_OR_NULL(indio_chan)) {
+               ret = PTR_ERR(indio_chan);
+               goto exit;
+       }
+       ret = iio_read_channel_raw(indio_chan, &val);
+       if (ret < 0) {
+               dev_err(&info->pdev->dev,
+                       "IIO channel read error: %x, %x\n", ret, val);
+               goto err_exit;
+       }
+
+       dev_dbg(&info->pdev->dev, "adc raw val=%x\n", val);
+       *raw_val = val;
+
+err_exit:
+       iio_channel_release(indio_chan);
+exit:
+       return ret;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int fuel_gauge_debug_show(struct seq_file *s, void *data)
+{
+       struct axp288_fg_info *info = s->private;
+       int raw_val, ret;
+
+       seq_printf(s, " PWR_STATUS[%02x] : %02x\n",
+               AXP20X_PWR_INPUT_STATUS,
+               fuel_gauge_reg_readb(info, AXP20X_PWR_INPUT_STATUS));
+       seq_printf(s, "PWR_OP_MODE[%02x] : %02x\n",
+               AXP20X_PWR_OP_MODE,
+               fuel_gauge_reg_readb(info, AXP20X_PWR_OP_MODE));
+       seq_printf(s, " CHRG_CTRL1[%02x] : %02x\n",
+               AXP20X_CHRG_CTRL1,
+               fuel_gauge_reg_readb(info, AXP20X_CHRG_CTRL1));
+       seq_printf(s, "       VLTF[%02x] : %02x\n",
+               AXP20X_V_LTF_DISCHRG,
+               fuel_gauge_reg_readb(info, AXP20X_V_LTF_DISCHRG));
+       seq_printf(s, "       VHTF[%02x] : %02x\n",
+               AXP20X_V_HTF_DISCHRG,
+               fuel_gauge_reg_readb(info, AXP20X_V_HTF_DISCHRG));
+       seq_printf(s, "    CC_CTRL[%02x] : %02x\n",
+               AXP20X_CC_CTRL,
+               fuel_gauge_reg_readb(info, AXP20X_CC_CTRL));
+       seq_printf(s, "BATTERY CAP[%02x] : %02x\n",
+               AXP20X_FG_RES,
+               fuel_gauge_reg_readb(info, AXP20X_FG_RES));
+       seq_printf(s, "    FG_RDC1[%02x] : %02x\n",
+               AXP288_FG_RDC1_REG,
+               fuel_gauge_reg_readb(info, AXP288_FG_RDC1_REG));
+       seq_printf(s, "    FG_RDC0[%02x] : %02x\n",
+               AXP288_FG_RDC0_REG,
+               fuel_gauge_reg_readb(info, AXP288_FG_RDC0_REG));
+       seq_printf(s, "    FG_OCVH[%02x] : %02x\n",
+               AXP288_FG_OCVH_REG,
+               fuel_gauge_reg_readb(info, AXP288_FG_OCVH_REG));
+       seq_printf(s, "    FG_OCVL[%02x] : %02x\n",
+               AXP288_FG_OCVL_REG,
+               fuel_gauge_reg_readb(info, AXP288_FG_OCVL_REG));
+       seq_printf(s, "FG_DES_CAP1[%02x] : %02x\n",
+               AXP288_FG_DES_CAP1_REG,
+               fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG));
+       seq_printf(s, "FG_DES_CAP0[%02x] : %02x\n",
+               AXP288_FG_DES_CAP0_REG,
+               fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP0_REG));
+       seq_printf(s, " FG_CC_MTR1[%02x] : %02x\n",
+               AXP288_FG_CC_MTR1_REG,
+               fuel_gauge_reg_readb(info, AXP288_FG_CC_MTR1_REG));
+       seq_printf(s, " FG_CC_MTR0[%02x] : %02x\n",
+               AXP288_FG_CC_MTR0_REG,
+               fuel_gauge_reg_readb(info, AXP288_FG_CC_MTR0_REG));
+       seq_printf(s, " FG_OCV_CAP[%02x] : %02x\n",
+               AXP288_FG_OCV_CAP_REG,
+               fuel_gauge_reg_readb(info, AXP288_FG_OCV_CAP_REG));
+       seq_printf(s, "  FG_CC_CAP[%02x] : %02x\n",
+               AXP288_FG_CC_CAP_REG,
+               fuel_gauge_reg_readb(info, AXP288_FG_CC_CAP_REG));
+       seq_printf(s, " FG_LOW_CAP[%02x] : %02x\n",
+               AXP288_FG_LOW_CAP_REG,
+               fuel_gauge_reg_readb(info, AXP288_FG_LOW_CAP_REG));
+       seq_printf(s, "TUNING_CTL0[%02x] : %02x\n",
+               AXP288_FG_TUNE0,
+               fuel_gauge_reg_readb(info, AXP288_FG_TUNE0));
+       seq_printf(s, "TUNING_CTL1[%02x] : %02x\n",
+               AXP288_FG_TUNE1,
+               fuel_gauge_reg_readb(info, AXP288_FG_TUNE1));
+       seq_printf(s, "TUNING_CTL2[%02x] : %02x\n",
+               AXP288_FG_TUNE2,
+               fuel_gauge_reg_readb(info, AXP288_FG_TUNE2));
+       seq_printf(s, "TUNING_CTL3[%02x] : %02x\n",
+               AXP288_FG_TUNE3,
+               fuel_gauge_reg_readb(info, AXP288_FG_TUNE3));
+       seq_printf(s, "TUNING_CTL4[%02x] : %02x\n",
+               AXP288_FG_TUNE4,
+               fuel_gauge_reg_readb(info, AXP288_FG_TUNE4));
+       seq_printf(s, "TUNING_CTL5[%02x] : %02x\n",
+               AXP288_FG_TUNE5,
+               fuel_gauge_reg_readb(info, AXP288_FG_TUNE5));
+
+       ret = pmic_read_adc_val("axp288-batt-temp", &raw_val, info);
+       if (ret >= 0)
+               seq_printf(s, "axp288-batttemp : %d\n", raw_val);
+       ret = pmic_read_adc_val("axp288-pmic-temp", &raw_val, info);
+       if (ret >= 0)
+               seq_printf(s, "axp288-pmictemp : %d\n", raw_val);
+       ret = pmic_read_adc_val("axp288-system-temp", &raw_val, info);
+       if (ret >= 0)
+               seq_printf(s, "axp288-systtemp : %d\n", raw_val);
+       ret = pmic_read_adc_val("axp288-chrg-curr", &raw_val, info);
+       if (ret >= 0)
+               seq_printf(s, "axp288-chrgcurr : %d\n", raw_val);
+       ret = pmic_read_adc_val("axp288-chrg-d-curr", &raw_val, info);
+       if (ret >= 0)
+               seq_printf(s, "axp288-dchrgcur : %d\n", raw_val);
+       ret = pmic_read_adc_val("axp288-batt-volt", &raw_val, info);
+       if (ret >= 0)
+               seq_printf(s, "axp288-battvolt : %d\n", raw_val);
+
+       return 0;
+}
+
+static int debug_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, fuel_gauge_debug_show, inode->i_private);
+}
+
+static const struct file_operations fg_debug_fops = {
+       .open       = debug_open,
+       .read       = seq_read,
+       .llseek     = seq_lseek,
+       .release    = single_release,
+};
+
+static void fuel_gauge_create_debugfs(struct axp288_fg_info *info)
+{
+       info->debug_file = debugfs_create_file("fuelgauge", 0666, NULL,
+               info, &fg_debug_fops);
+}
+
+static void fuel_gauge_remove_debugfs(struct axp288_fg_info *info)
+{
+       debugfs_remove(info->debug_file);
+}
+#else
+static inline void fuel_gauge_create_debugfs(struct axp288_fg_info *info)
+{
+}
+static inline void fuel_gauge_remove_debugfs(struct axp288_fg_info *info)
+{
+}
+#endif
+
+static void fuel_gauge_get_status(struct axp288_fg_info *info)
+{
+       int pwr_stat, ret;
+       int charge, discharge;
+
+       pwr_stat = fuel_gauge_reg_readb(info, AXP20X_PWR_INPUT_STATUS);
+       if (pwr_stat < 0) {
+               dev_err(&info->pdev->dev,
+                       "PWR STAT read failed:%d\n", pwr_stat);
+               return;
+       }
+       ret = pmic_read_adc_val("axp288-chrg-curr", &charge, info);
+       if (ret < 0) {
+               dev_err(&info->pdev->dev,
+                       "ADC charge current read failed:%d\n", ret);
+               return;
+       }
+       ret = pmic_read_adc_val("axp288-chrg-d-curr", &discharge, info);
+       if (ret < 0) {
+               dev_err(&info->pdev->dev,
+                       "ADC discharge current read failed:%d\n", ret);
+               return;
+       }
+
+       if (charge > 0)
+               info->status = POWER_SUPPLY_STATUS_CHARGING;
+       else if (discharge > 0)
+               info->status = POWER_SUPPLY_STATUS_DISCHARGING;
+       else {
+               if (pwr_stat & CHRG_STAT_BAT_PRESENT)
+                       info->status = POWER_SUPPLY_STATUS_FULL;
+               else
+                       info->status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+       }
+}
+
+static int fuel_gauge_get_vbatt(struct axp288_fg_info *info, int *vbatt)
+{
+       int ret = 0, raw_val;
+
+       ret = pmic_read_adc_val("axp288-batt-volt", &raw_val, info);
+       if (ret < 0)
+               goto vbatt_read_fail;
+
+       *vbatt = VOLTAGE_FROM_ADC(raw_val);
+vbatt_read_fail:
+       return ret;
+}
+
+static int fuel_gauge_get_current(struct axp288_fg_info *info, int *cur)
+{
+       int ret, value = 0;
+       int charge, discharge;
+
+       ret = pmic_read_adc_val("axp288-chrg-curr", &charge, info);
+       if (ret < 0)
+               goto current_read_fail;
+       ret = pmic_read_adc_val("axp288-chrg-d-curr", &discharge, info);
+       if (ret < 0)
+               goto current_read_fail;
+
+       if (charge > 0)
+               value = charge;
+       else if (discharge > 0)
+               value = -1 * discharge;
+
+       *cur = value;
+current_read_fail:
+       return ret;
+}
+
+static int temp_to_adc(struct axp288_fg_info *info, int tval)
+{
+       int rntc = 0, i, ret, adc_val;
+       int rmin, rmax, tmin, tmax;
+       int tcsz = info->pdata->tcsz;
+
+       /* get the Rntc resitance value for this temp */
+       if (tval > info->pdata->thermistor_curve[0][1]) {
+               rntc = info->pdata->thermistor_curve[0][0];
+       } else if (tval <= info->pdata->thermistor_curve[tcsz-1][1]) {
+               rntc = info->pdata->thermistor_curve[tcsz-1][0];
+       } else {
+               for (i = 1; i < tcsz; i++) {
+                       if (tval > info->pdata->thermistor_curve[i][1]) {
+                               rmin = info->pdata->thermistor_curve[i-1][0];
+                               rmax = info->pdata->thermistor_curve[i][0];
+                               tmin = info->pdata->thermistor_curve[i-1][1];
+                               tmax = info->pdata->thermistor_curve[i][1];
+                               rntc = rmin + ((rmax - rmin) *
+                                       (tval - tmin) / (tmax - tmin));
+                               break;
+                       }
+               }
+       }
+
+       /* we need the current to calculate the proper adc voltage */
+       ret = fuel_gauge_reg_readb(info, AXP20X_ADC_RATE);
+       if (ret < 0) {
+               dev_err(&info->pdev->dev, "%s:read err:%d\n", __func__, ret);
+               ret = 0x30;
+       }
+
+       /*
+        * temperature is proportional to NTS thermistor resistance
+        * ADC_RATE[5-4] determines current, 00=20uA,01=40uA,10=60uA,11=80uA
+        * [12-bit ADC VAL] = R_NTC(Ω) * current / 800
+        */
+       adc_val = rntc * (20 + (20 * ((ret >> 4) & 0x3))) / 800;
+
+       return adc_val;
+}
+
+static int adc_to_temp(struct axp288_fg_info *info, int adc_val)
+{
+       int ret, r, i, tval = 0;
+       int rmin, rmax, tmin, tmax;
+       int tcsz = info->pdata->tcsz;
+
+       ret = fuel_gauge_reg_readb(info, AXP20X_ADC_RATE);
+       if (ret < 0) {
+               dev_err(&info->pdev->dev, "%s:read err:%d\n", __func__, ret);
+               ret = 0x30;
+       }
+
+       /*
+        * temperature is proportional to NTS thermistor resistance
+        * ADC_RATE[5-4] determines current, 00=20uA,01=40uA,10=60uA,11=80uA
+        * R_NTC(Ω) = [12-bit ADC VAL] * 800 / current
+        */
+       r = adc_val * 800 / (20 + (20 * ((ret >> 4) & 0x3)));
+
+       if (r < info->pdata->thermistor_curve[0][0]) {
+               tval = info->pdata->thermistor_curve[0][1];
+       } else if (r >= info->pdata->thermistor_curve[tcsz-1][0]) {
+               tval = info->pdata->thermistor_curve[tcsz-1][1];
+       } else {
+               for (i = 1; i < tcsz; i++) {
+                       if (r < info->pdata->thermistor_curve[i][0]) {
+                               rmin = info->pdata->thermistor_curve[i-1][0];
+                               rmax = info->pdata->thermistor_curve[i][0];
+                               tmin = info->pdata->thermistor_curve[i-1][1];
+                               tmax = info->pdata->thermistor_curve[i][1];
+                               tval = tmin + ((tmax - tmin) *
+                                       (r - rmin) / (rmax - rmin));
+                               break;
+                       }
+               }
+       }
+
+       return tval;
+}
+
+static int fuel_gauge_get_btemp(struct axp288_fg_info *info, int *btemp)
+{
+       int ret, raw_val = 0;
+
+       ret = pmic_read_adc_val("axp288-batt-temp", &raw_val, info);
+       if (ret < 0)
+               goto temp_read_fail;
+
+       *btemp = adc_to_temp(info, raw_val);
+
+temp_read_fail:
+       return ret;
+}
+
+static int fuel_gauge_get_vocv(struct axp288_fg_info *info, int *vocv)
+{
+       int ret, value;
+
+       /* 12-bit data value, upper 8 in OCVH, lower 4 in OCVL */
+       ret = fuel_gauge_reg_readb(info, AXP288_FG_OCVH_REG);
+       if (ret < 0)
+               goto vocv_read_fail;
+       value = ret << 4;
+
+       ret = fuel_gauge_reg_readb(info, AXP288_FG_OCVL_REG);
+       if (ret < 0)
+               goto vocv_read_fail;
+       value |= (ret & 0xf);
+
+       *vocv = VOLTAGE_FROM_ADC(value);
+vocv_read_fail:
+       return ret;
+}
+
+static int fuel_gauge_battery_health(struct axp288_fg_info *info)
+{
+       int temp, vocv;
+       int ret, health = POWER_SUPPLY_HEALTH_UNKNOWN;
+
+       ret = fuel_gauge_get_btemp(info, &temp);
+       if (ret < 0)
+               goto health_read_fail;
+
+       ret = fuel_gauge_get_vocv(info, &vocv);
+       if (ret < 0)
+               goto health_read_fail;
+
+       if (vocv > info->pdata->max_volt)
+               health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+       else if (temp > info->pdata->max_temp)
+               health = POWER_SUPPLY_HEALTH_OVERHEAT;
+       else if (temp < info->pdata->min_temp)
+               health = POWER_SUPPLY_HEALTH_COLD;
+       else if (vocv < info->pdata->min_volt)
+               health = POWER_SUPPLY_HEALTH_DEAD;
+       else
+               health = POWER_SUPPLY_HEALTH_GOOD;
+
+health_read_fail:
+       return health;
+}
+
+static int fuel_gauge_set_high_btemp_alert(struct axp288_fg_info *info)
+{
+       int ret, adc_val;
+
+       /* program temperature threshold as 1/16 ADC value */
+       adc_val = temp_to_adc(info, info->pdata->max_temp);
+       ret = fuel_gauge_reg_writeb(info, AXP20X_V_HTF_DISCHRG, adc_val >> 4);
+
+       return ret;
+}
+
+static int fuel_gauge_set_low_btemp_alert(struct axp288_fg_info *info)
+{
+       int ret, adc_val;
+
+       /* program temperature threshold as 1/16 ADC value */
+       adc_val = temp_to_adc(info, info->pdata->min_temp);
+       ret = fuel_gauge_reg_writeb(info, AXP20X_V_LTF_DISCHRG, adc_val >> 4);
+
+       return ret;
+}
+
+static int fuel_gauge_get_property(struct power_supply *ps,
+               enum power_supply_property prop,
+               union power_supply_propval *val)
+{
+       struct axp288_fg_info *info = power_supply_get_drvdata(ps);
+       int ret = 0, value;
+
+       mutex_lock(&info->lock);
+       switch (prop) {
+       case POWER_SUPPLY_PROP_STATUS:
+               fuel_gauge_get_status(info);
+               val->intval = info->status;
+               break;
+       case POWER_SUPPLY_PROP_HEALTH:
+               val->intval = fuel_gauge_battery_health(info);
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               ret = fuel_gauge_get_vbatt(info, &value);
+               if (ret < 0)
+                       goto fuel_gauge_read_err;
+               val->intval = PROP_VOLT(value);
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_OCV:
+               ret = fuel_gauge_get_vocv(info, &value);
+               if (ret < 0)
+                       goto fuel_gauge_read_err;
+               val->intval = PROP_VOLT(value);
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               ret = fuel_gauge_get_current(info, &value);
+               if (ret < 0)
+                       goto fuel_gauge_read_err;
+               val->intval = PROP_CURR(value);
+               break;
+       case POWER_SUPPLY_PROP_PRESENT:
+               ret = fuel_gauge_reg_readb(info, AXP20X_PWR_OP_MODE);
+               if (ret < 0)
+                       goto fuel_gauge_read_err;
+
+               if (ret & CHRG_STAT_BAT_PRESENT)
+                       val->intval = 1;
+               else
+                       val->intval = 0;
+               break;
+       case POWER_SUPPLY_PROP_CAPACITY:
+               ret = fuel_gauge_reg_readb(info, AXP20X_FG_RES);
+               if (ret < 0)
+                       goto fuel_gauge_read_err;
+
+               if (!(ret & FG_REP_CAP_VALID))
+                       dev_err(&info->pdev->dev,
+                               "capacity measurement not valid\n");
+               val->intval = (ret & FG_REP_CAP_VAL_MASK);
+               break;
+       case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
+               ret = fuel_gauge_reg_readb(info, AXP288_FG_LOW_CAP_REG);
+               if (ret < 0)
+                       goto fuel_gauge_read_err;
+               val->intval = (ret & 0x0f);
+               break;
+       case POWER_SUPPLY_PROP_TEMP:
+               ret = fuel_gauge_get_btemp(info, &value);
+               if (ret < 0)
+                       goto fuel_gauge_read_err;
+               val->intval = PROP_TEMP(value);
+               break;
+       case POWER_SUPPLY_PROP_TEMP_MAX:
+       case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+               val->intval = PROP_TEMP(info->pdata->max_temp);
+               break;
+       case POWER_SUPPLY_PROP_TEMP_MIN:
+       case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+               val->intval = PROP_TEMP(info->pdata->min_temp);
+               break;
+       case POWER_SUPPLY_PROP_TECHNOLOGY:
+               val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_NOW:
+               ret = fuel_gauge_reg_readb(info, AXP288_FG_CC_MTR1_REG);
+               if (ret < 0)
+                       goto fuel_gauge_read_err;
+
+               value = (ret & FG_CC_MTR1_VAL_MASK) << 8;
+               ret = fuel_gauge_reg_readb(info, AXP288_FG_CC_MTR0_REG);
+               if (ret < 0)
+                       goto fuel_gauge_read_err;
+               value |= (ret & FG_CC_MTR0_VAL_MASK);
+               val->intval = value * FG_DES_CAP_RES_LSB;
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_FULL:
+               ret = fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG);
+               if (ret < 0)
+                       goto fuel_gauge_read_err;
+
+               value = (ret & FG_DES_CAP1_VAL_MASK) << 8;
+               ret = fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP0_REG);
+               if (ret < 0)
+                       goto fuel_gauge_read_err;
+               value |= (ret & FG_DES_CAP0_VAL_MASK);
+               val->intval = value * FG_DES_CAP_RES_LSB;
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+               val->intval = PROP_CURR(info->pdata->design_cap);
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+               val->intval = PROP_VOLT(info->pdata->max_volt);
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+               val->intval = PROP_VOLT(info->pdata->min_volt);
+               break;
+       case POWER_SUPPLY_PROP_MODEL_NAME:
+               val->strval = info->pdata->battid;
+               break;
+       default:
+               mutex_unlock(&info->lock);
+               return -EINVAL;
+       }
+
+       mutex_unlock(&info->lock);
+       return 0;
+
+fuel_gauge_read_err:
+       mutex_unlock(&info->lock);
+       return ret;
+}
+
+static int fuel_gauge_set_property(struct power_supply *ps,
+               enum power_supply_property prop,
+               const union power_supply_propval *val)
+{
+       struct axp288_fg_info *info = power_supply_get_drvdata(ps);
+       int ret = 0;
+
+       mutex_lock(&info->lock);
+       switch (prop) {
+       case POWER_SUPPLY_PROP_STATUS:
+               info->status = val->intval;
+               break;
+       case POWER_SUPPLY_PROP_TEMP_MIN:
+       case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+               if ((val->intval < PD_DEF_MIN_TEMP) ||
+                       (val->intval > PD_DEF_MAX_TEMP)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               info->pdata->min_temp = UNPROP_TEMP(val->intval);
+               ret = fuel_gauge_set_low_btemp_alert(info);
+               if (ret < 0)
+                       dev_err(&info->pdev->dev,
+                               "temp alert min set fail:%d\n", ret);
+               break;
+       case POWER_SUPPLY_PROP_TEMP_MAX:
+       case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+               if ((val->intval < PD_DEF_MIN_TEMP) ||
+                       (val->intval > PD_DEF_MAX_TEMP)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               info->pdata->max_temp = UNPROP_TEMP(val->intval);
+               ret = fuel_gauge_set_high_btemp_alert(info);
+               if (ret < 0)
+                       dev_err(&info->pdev->dev,
+                               "temp alert max set fail:%d\n", ret);
+               break;
+       case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
+               if ((val->intval < 0) || (val->intval > 15)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = fuel_gauge_reg_readb(info, AXP288_FG_LOW_CAP_REG);
+               if (ret < 0)
+                       break;
+               ret &= 0xf0;
+               ret |= (val->intval & 0xf);
+               ret = fuel_gauge_reg_writeb(info, AXP288_FG_LOW_CAP_REG, ret);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       mutex_unlock(&info->lock);
+       return ret;
+}
+
+static int fuel_gauge_property_is_writeable(struct power_supply *psy,
+       enum power_supply_property psp)
+{
+       int ret;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+       case POWER_SUPPLY_PROP_TEMP_MIN:
+       case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+       case POWER_SUPPLY_PROP_TEMP_MAX:
+       case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+       case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
+               ret = 1;
+               break;
+       default:
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static void fuel_gauge_status_monitor(struct work_struct *work)
+{
+       struct axp288_fg_info *info = container_of(work,
+               struct axp288_fg_info, status_monitor.work);
+
+       fuel_gauge_get_status(info);
+       power_supply_changed(info->bat);
+       schedule_delayed_work(&info->status_monitor, STATUS_MON_DELAY_JIFFIES);
+}
+
+static irqreturn_t fuel_gauge_thread_handler(int irq, void *dev)
+{
+       struct axp288_fg_info *info = dev;
+       int i;
+
+       for (i = 0; i < AXP288_FG_INTR_NUM; i++) {
+               if (info->irq[i] == irq)
+                       break;
+       }
+
+       if (i >= AXP288_FG_INTR_NUM) {
+               dev_warn(&info->pdev->dev, "spurious interrupt!!\n");
+               return IRQ_NONE;
+       }
+
+       switch (i) {
+       case QWBTU_IRQ:
+               dev_info(&info->pdev->dev,
+                       "Quit Battery under temperature in work mode IRQ (QWBTU)\n");
+               break;
+       case WBTU_IRQ:
+               dev_info(&info->pdev->dev,
+                       "Battery under temperature in work mode IRQ (WBTU)\n");
+               break;
+       case QWBTO_IRQ:
+               dev_info(&info->pdev->dev,
+                       "Quit Battery over temperature in work mode IRQ (QWBTO)\n");
+               break;
+       case WBTO_IRQ:
+               dev_info(&info->pdev->dev,
+                       "Battery over temperature in work mode IRQ (WBTO)\n");
+               break;
+       case WL2_IRQ:
+               dev_info(&info->pdev->dev, "Low Batt Warning(2) INTR\n");
+               break;
+       case WL1_IRQ:
+               dev_info(&info->pdev->dev, "Low Batt Warning(1) INTR\n");
+               break;
+       default:
+               dev_warn(&info->pdev->dev, "Spurious Interrupt!!!\n");
+       }
+
+       power_supply_changed(info->bat);
+       return IRQ_HANDLED;
+}
+
+static void fuel_gauge_external_power_changed(struct power_supply *psy)
+{
+       struct axp288_fg_info *info = power_supply_get_drvdata(psy);
+
+       power_supply_changed(info->bat);
+}
+
+static const struct power_supply_desc fuel_gauge_desc = {
+       .name                   = DEV_NAME,
+       .type                   = POWER_SUPPLY_TYPE_BATTERY,
+       .properties             = fuel_gauge_props,
+       .num_properties         = ARRAY_SIZE(fuel_gauge_props),
+       .get_property           = fuel_gauge_get_property,
+       .set_property           = fuel_gauge_set_property,
+       .property_is_writeable  = fuel_gauge_property_is_writeable,
+       .external_power_changed = fuel_gauge_external_power_changed,
+};
+
+static int fuel_gauge_set_lowbatt_thresholds(struct axp288_fg_info *info)
+{
+       int ret;
+       u8 reg_val;
+
+       ret = fuel_gauge_reg_readb(info, AXP20X_FG_RES);
+       if (ret < 0) {
+               dev_err(&info->pdev->dev, "%s:read err:%d\n", __func__, ret);
+               return ret;
+       }
+       ret = (ret & FG_REP_CAP_VAL_MASK);
+
+       if (ret > FG_LOW_CAP_WARN_THR)
+               reg_val = FG_LOW_CAP_WARN_THR;
+       else if (ret > FG_LOW_CAP_CRIT_THR)
+               reg_val = FG_LOW_CAP_CRIT_THR;
+       else
+               reg_val = FG_LOW_CAP_SHDN_THR;
+
+       reg_val |= FG_LOW_CAP_THR1_VAL;
+       ret = fuel_gauge_reg_writeb(info, AXP288_FG_LOW_CAP_REG, reg_val);
+       if (ret < 0)
+               dev_err(&info->pdev->dev, "%s:write err:%d\n", __func__, ret);
+
+       return ret;
+}
+
+static int fuel_gauge_program_vbatt_full(struct axp288_fg_info *info)
+{
+       int ret;
+       u8 val;
+
+       ret = fuel_gauge_reg_readb(info, AXP20X_CHRG_CTRL1);
+       if (ret < 0)
+               goto fg_prog_ocv_fail;
+       else
+               val = (ret & ~CHRG_CCCV_CV_MASK);
+
+       switch (info->pdata->max_volt) {
+       case CV_4100:
+               val |= (CHRG_CCCV_CV_4100MV << CHRG_CCCV_CV_BIT_POS);
+               break;
+       case CV_4150:
+               val |= (CHRG_CCCV_CV_4150MV << CHRG_CCCV_CV_BIT_POS);
+               break;
+       case CV_4200:
+               val |= (CHRG_CCCV_CV_4200MV << CHRG_CCCV_CV_BIT_POS);
+               break;
+       case CV_4350:
+               val |= (CHRG_CCCV_CV_4350MV << CHRG_CCCV_CV_BIT_POS);
+               break;
+       default:
+               val |= (CHRG_CCCV_CV_4200MV << CHRG_CCCV_CV_BIT_POS);
+               break;
+       }
+
+       ret = fuel_gauge_reg_writeb(info, AXP20X_CHRG_CTRL1, val);
+fg_prog_ocv_fail:
+       return ret;
+}
+
+static int fuel_gauge_program_design_cap(struct axp288_fg_info *info)
+{
+       int ret;
+
+       ret = fuel_gauge_reg_writeb(info,
+               AXP288_FG_DES_CAP1_REG, info->pdata->cap1);
+       if (ret < 0)
+               goto fg_prog_descap_fail;
+
+       ret = fuel_gauge_reg_writeb(info,
+               AXP288_FG_DES_CAP0_REG, info->pdata->cap0);
+
+fg_prog_descap_fail:
+       return ret;
+}
+
+static int fuel_gauge_program_ocv_curve(struct axp288_fg_info *info)
+{
+       int ret = 0, i;
+
+       for (i = 0; i < OCV_CURVE_SIZE; i++) {
+               ret = fuel_gauge_reg_writeb(info,
+                       AXP288_FG_OCV_CURVE_REG + i, info->pdata->ocv_curve[i]);
+               if (ret < 0)
+                       goto fg_prog_ocv_fail;
+       }
+
+fg_prog_ocv_fail:
+       return ret;
+}
+
+static int fuel_gauge_program_rdc_vals(struct axp288_fg_info *info)
+{
+       int ret;
+
+       ret = fuel_gauge_reg_writeb(info,
+               AXP288_FG_RDC1_REG, info->pdata->rdc1);
+       if (ret < 0)
+               goto fg_prog_ocv_fail;
+
+       ret = fuel_gauge_reg_writeb(info,
+               AXP288_FG_RDC0_REG, info->pdata->rdc0);
+
+fg_prog_ocv_fail:
+       return ret;
+}
+
+static void fuel_gauge_init_config_regs(struct axp288_fg_info *info)
+{
+       int ret;
+
+       /*
+        * check if the config data is already
+        * programmed and if so just return.
+        */
+
+       ret = fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG);
+       if (ret < 0) {
+               dev_warn(&info->pdev->dev, "CAP1 reg read err!!\n");
+       } else if (!(ret & FG_DES_CAP1_VALID)) {
+               dev_info(&info->pdev->dev, "FG data needs to be initialized\n");
+       } else {
+               dev_info(&info->pdev->dev, "FG data is already initialized\n");
+               return;
+       }
+
+       ret = fuel_gauge_program_vbatt_full(info);
+       if (ret < 0)
+               dev_err(&info->pdev->dev, "set vbatt full fail:%d\n", ret);
+
+       ret = fuel_gauge_program_design_cap(info);
+       if (ret < 0)
+               dev_err(&info->pdev->dev, "set design cap fail:%d\n", ret);
+
+       ret = fuel_gauge_program_rdc_vals(info);
+       if (ret < 0)
+               dev_err(&info->pdev->dev, "set rdc fail:%d\n", ret);
+
+       ret = fuel_gauge_program_ocv_curve(info);
+       if (ret < 0)
+               dev_err(&info->pdev->dev, "set ocv curve fail:%d\n", ret);
+
+       ret = fuel_gauge_set_lowbatt_thresholds(info);
+       if (ret < 0)
+               dev_err(&info->pdev->dev, "lowbatt thr set fail:%d\n", ret);
+
+       ret = fuel_gauge_reg_writeb(info, AXP20X_CC_CTRL, 0xef);
+       if (ret < 0)
+               dev_err(&info->pdev->dev, "gauge cntl set fail:%d\n", ret);
+}
+
+static void fuel_gauge_init_irq(struct axp288_fg_info *info)
+{
+       int ret, i, pirq;
+
+       for (i = 0; i < AXP288_FG_INTR_NUM; i++) {
+               pirq = platform_get_irq(info->pdev, i);
+               info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq);
+               if (info->irq[i] < 0) {
+                       dev_warn(&info->pdev->dev,
+                               "regmap_irq get virq failed for IRQ %d: %d\n",
+                               pirq, info->irq[i]);
+                       info->irq[i] = -1;
+                       goto intr_failed;
+               }
+               ret = request_threaded_irq(info->irq[i],
+                               NULL, fuel_gauge_thread_handler,
+                               IRQF_ONESHOT, DEV_NAME, info);
+               if (ret) {
+                       dev_warn(&info->pdev->dev,
+                               "request irq failed for IRQ %d: %d\n",
+                               pirq, info->irq[i]);
+                       info->irq[i] = -1;
+                       goto intr_failed;
+               } else {
+                       dev_info(&info->pdev->dev, "HW IRQ %d -> VIRQ %d\n",
+                               pirq, info->irq[i]);
+               }
+       }
+       return;
+
+intr_failed:
+       for (; i > 0; i--) {
+               free_irq(info->irq[i - 1], info);
+               info->irq[i - 1] = -1;
+       }
+}
+
+static void fuel_gauge_init_hw_regs(struct axp288_fg_info *info)
+{
+       int ret;
+       unsigned int val;
+
+       ret = fuel_gauge_set_high_btemp_alert(info);
+       if (ret < 0)
+               dev_err(&info->pdev->dev, "high batt temp set fail:%d\n", ret);
+
+       ret = fuel_gauge_set_low_btemp_alert(info);
+       if (ret < 0)
+               dev_err(&info->pdev->dev, "low batt temp set fail:%d\n", ret);
+
+       /* enable interrupts */
+       val = fuel_gauge_reg_readb(info, AXP20X_IRQ3_EN);
+       val |= TEMP_IRQ_CFG_MASK;
+       fuel_gauge_reg_writeb(info, AXP20X_IRQ3_EN, val);
+
+       val = fuel_gauge_reg_readb(info, AXP20X_IRQ4_EN);
+       val |= FG_IRQ_CFG_LOWBATT_MASK;
+       val = fuel_gauge_reg_writeb(info, AXP20X_IRQ4_EN, val);
+}
+
+static int axp288_fuel_gauge_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct axp288_fg_info *info;
+       struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
+       struct power_supply_config psy_cfg = {};
+
+       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       info->pdev = pdev;
+       info->regmap = axp20x->regmap;
+       info->regmap_irqc = axp20x->regmap_irqc;
+       info->status = POWER_SUPPLY_STATUS_UNKNOWN;
+       info->pdata = pdev->dev.platform_data;
+       if (!info->pdata)
+               return -ENODEV;
+
+       platform_set_drvdata(pdev, info);
+
+       mutex_init(&info->lock);
+       INIT_DELAYED_WORK(&info->status_monitor, fuel_gauge_status_monitor);
+
+       psy_cfg.drv_data = info;
+       info->bat = power_supply_register(&pdev->dev, &fuel_gauge_desc, &psy_cfg);
+       if (IS_ERR(info->bat)) {
+               ret = PTR_ERR(info->bat);
+               dev_err(&pdev->dev, "failed to register battery: %d\n", ret);
+               return ret;
+       }
+
+       fuel_gauge_create_debugfs(info);
+       fuel_gauge_init_config_regs(info);
+       fuel_gauge_init_irq(info);
+       fuel_gauge_init_hw_regs(info);
+       schedule_delayed_work(&info->status_monitor, STATUS_MON_DELAY_JIFFIES);
+
+       return ret;
+}
+
+static struct platform_device_id axp288_fg_id_table[] = {
+       { .name = DEV_NAME },
+       {},
+};
+
+static int axp288_fuel_gauge_remove(struct platform_device *pdev)
+{
+       struct axp288_fg_info *info = platform_get_drvdata(pdev);
+       int i;
+
+       cancel_delayed_work_sync(&info->status_monitor);
+       power_supply_unregister(info->bat);
+       fuel_gauge_remove_debugfs(info);
+
+       for (i = 0; i < AXP288_FG_INTR_NUM; i++)
+               if (info->irq[i] >= 0)
+                       free_irq(info->irq[i], info);
+
+       return 0;
+}
+
+static struct platform_driver axp288_fuel_gauge_driver = {
+       .probe = axp288_fuel_gauge_probe,
+       .remove = axp288_fuel_gauge_remove,
+       .id_table = axp288_fg_id_table,
+       .driver = {
+               .name = DEV_NAME,
+       },
+};
+
+module_platform_driver(axp288_fuel_gauge_driver);
+
+MODULE_AUTHOR("Todd Brandt <todd.e.brandt@linux.intel.com>");
+MODULE_DESCRIPTION("Xpower AXP288 Fuel Gauge Driver");
+MODULE_LICENSE("GPL");
index 1f49986fc6057c8c4db858735ec8d9fd38326f8a..6c534dcbc19cb3c8639da09bef6b48281ac3cd44 100644 (file)
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/*
  * Datasheets:
  * http://www.ti.com/product/bq24150
  * http://www.ti.com/product/bq24150a
@@ -26,6 +20,8 @@
  * http://www.ti.com/product/bq24153
  * http://www.ti.com/product/bq24153a
  * http://www.ti.com/product/bq24155
+ * http://www.ti.com/product/bq24157s
+ * http://www.ti.com/product/bq24158
  */
 
 #include <linux/kernel.h>
@@ -147,6 +143,7 @@ enum bq2415x_chip {
        BQ24155,
        BQ24156,
        BQ24156A,
+       BQ24157S,
        BQ24158,
 };
 
@@ -162,18 +159,20 @@ static char *bq2415x_chip_name[] = {
        "bq24155",
        "bq24156",
        "bq24156a",
+       "bq24157s",
        "bq24158",
 };
 
 struct bq2415x_device {
        struct device *dev;
        struct bq2415x_platform_data init_data;
-       struct power_supply charger;
+       struct power_supply *charger;
+       struct power_supply_desc charger_desc;
        struct delayed_work work;
        struct power_supply *notify_psy;
        struct notifier_block nb;
        enum bq2415x_mode reported_mode;/* mode reported by hook function */
-       enum bq2415x_mode mode;         /* current configured mode */
+       enum bq2415x_mode mode;         /* currently configured mode */
        enum bq2415x_chip chip;
        const char *timer_error;
        char *model;
@@ -352,8 +351,7 @@ static int bq2415x_exec_command(struct bq2415x_device *bq,
                        BQ2415X_BIT_CE);
                if (ret < 0)
                        return ret;
-               else
-                       return ret > 0 ? 0 : 1;
+               return ret > 0 ? 0 : 1;
        case BQ2415X_CHARGER_ENABLE:
                return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
                                0, BQ2415X_BIT_CE);
@@ -426,20 +424,17 @@ static enum bq2415x_chip bq2415x_detect_chip(struct bq2415x_device *bq)
                case 0:
                        if (bq->chip == BQ24151A)
                                return bq->chip;
-                       else
-                               return BQ24151;
+                       return BQ24151;
                case 1:
                        if (bq->chip == BQ24150A ||
                                bq->chip == BQ24152 ||
                                bq->chip == BQ24155)
                                return bq->chip;
-                       else
-                               return BQ24150;
+                       return BQ24150;
                case 2:
                        if (bq->chip == BQ24153A)
                                return bq->chip;
-                       else
-                               return BQ24153;
+                       return BQ24153;
                default:
                        return BQUNKNOWN;
                }
@@ -450,9 +445,10 @@ static enum bq2415x_chip bq2415x_detect_chip(struct bq2415x_device *bq)
                case 0:
                        if (bq->chip == BQ24156A)
                                return bq->chip;
-                       else
-                               return BQ24156;
+                       return BQ24156;
                case 2:
+                       if (bq->chip == BQ24157S)
+                               return bq->chip;
                        return BQ24158;
                default:
                        return BQUNKNOWN;
@@ -480,24 +476,22 @@ static int bq2415x_detect_revision(struct bq2415x_device *bq)
        case BQ24152:
                if (ret >= 0 && ret <= 3)
                        return ret;
-               else
-                       return -1;
+               return -1;
        case BQ24153:
        case BQ24153A:
        case BQ24156:
        case BQ24156A:
+       case BQ24157S:
        case BQ24158:
                if (ret == 3)
                        return 0;
                else if (ret == 1)
                        return 1;
-               else
-                       return -1;
+               return -1;
        case BQ24155:
                if (ret == 3)
                        return 3;
-               else
-                       return -1;
+               return -1;
        case BQUNKNOWN:
                return -1;
        }
@@ -791,7 +785,7 @@ static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode)
        bq2415x_set_default_value(bq, battery_regulation_voltage);
 
        bq->mode = mode;
-       sysfs_notify(&bq->charger.dev->kobj, NULL, "mode");
+       sysfs_notify(&bq->charger->dev.kobj, NULL, "mode");
 
        return 0;
 
@@ -816,7 +810,8 @@ static int bq2415x_notifier_call(struct notifier_block *nb,
 
        dev_dbg(bq->dev, "notifier call was called\n");
 
-       ret = psy->get_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX,
+                       &prop);
        if (ret != 0)
                return NOTIFY_OK;
 
@@ -874,7 +869,7 @@ static void bq2415x_set_autotimer(struct bq2415x_device *bq, int state)
 static void bq2415x_timer_error(struct bq2415x_device *bq, const char *msg)
 {
        bq->timer_error = msg;
-       sysfs_notify(&bq->charger.dev->kobj, NULL, "timer");
+       sysfs_notify(&bq->charger->dev.kobj, NULL, "timer");
        dev_err(bq->dev, "%s\n", msg);
        if (bq->automode > 0)
                bq->automode = 0;
@@ -892,7 +887,7 @@ static void bq2415x_timer_work(struct work_struct *work)
        int boost;
 
        if (bq->automode > 0 && (bq->reported_mode != bq->mode)) {
-               sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode");
+               sysfs_notify(&bq->charger->dev.kobj, NULL, "reported_mode");
                bq2415x_set_mode(bq, bq->reported_mode);
        }
 
@@ -998,8 +993,7 @@ static int bq2415x_power_supply_get_property(struct power_supply *psy,
                                             enum power_supply_property psp,
                                             union power_supply_propval *val)
 {
-       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
-                                                charger);
+       struct bq2415x_device *bq = power_supply_get_drvdata(psy);
        int ret;
 
        switch (psp) {
@@ -1030,12 +1024,14 @@ static int bq2415x_power_supply_init(struct bq2415x_device *bq)
        int ret;
        int chip;
        char revstr[8];
+       struct power_supply_config psy_cfg = { .drv_data = bq, };
 
-       bq->charger.name = bq->name;
-       bq->charger.type = POWER_SUPPLY_TYPE_USB;
-       bq->charger.properties = bq2415x_power_supply_props;
-       bq->charger.num_properties = ARRAY_SIZE(bq2415x_power_supply_props);
-       bq->charger.get_property = bq2415x_power_supply_get_property;
+       bq->charger_desc.name = bq->name;
+       bq->charger_desc.type = POWER_SUPPLY_TYPE_USB;
+       bq->charger_desc.properties = bq2415x_power_supply_props;
+       bq->charger_desc.num_properties =
+                       ARRAY_SIZE(bq2415x_power_supply_props);
+       bq->charger_desc.get_property = bq2415x_power_supply_get_property;
 
        ret = bq2415x_detect_chip(bq);
        if (ret < 0)
@@ -1058,10 +1054,11 @@ static int bq2415x_power_supply_init(struct bq2415x_device *bq)
                return -ENOMEM;
        }
 
-       ret = power_supply_register(bq->dev, &bq->charger);
-       if (ret) {
+       bq->charger = power_supply_register(bq->dev, &bq->charger_desc,
+                                           &psy_cfg);
+       if (IS_ERR(bq->charger)) {
                kfree(bq->model);
-               return ret;
+               return PTR_ERR(bq->charger);
        }
 
        return 0;
@@ -1073,7 +1070,7 @@ static void bq2415x_power_supply_exit(struct bq2415x_device *bq)
        if (bq->automode > 0)
                bq->automode = 0;
        cancel_delayed_work_sync(&bq->work);
-       power_supply_unregister(&bq->charger);
+       power_supply_unregister(bq->charger);
        kfree(bq->model);
 }
 
@@ -1085,8 +1082,7 @@ static ssize_t bq2415x_sysfs_show_status(struct device *dev,
                                         char *buf)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
-                                               charger);
+       struct bq2415x_device *bq = power_supply_get_drvdata(psy);
        enum bq2415x_command command;
        int ret;
 
@@ -1119,8 +1115,7 @@ static ssize_t bq2415x_sysfs_set_timer(struct device *dev,
                                       size_t count)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
-                                               charger);
+       struct bq2415x_device *bq = power_supply_get_drvdata(psy);
        int ret = 0;
 
        if (strncmp(buf, "auto", 4) == 0)
@@ -1141,8 +1136,7 @@ static ssize_t bq2415x_sysfs_show_timer(struct device *dev,
                                        char *buf)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
-                                                charger);
+       struct bq2415x_device *bq = power_supply_get_drvdata(psy);
 
        if (bq->timer_error)
                return sprintf(buf, "%s\n", bq->timer_error);
@@ -1166,8 +1160,7 @@ static ssize_t bq2415x_sysfs_set_mode(struct device *dev,
                                      size_t count)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
-                                                charger);
+       struct bq2415x_device *bq = power_supply_get_drvdata(psy);
        enum bq2415x_mode mode;
        int ret = 0;
 
@@ -1219,8 +1212,7 @@ static ssize_t bq2415x_sysfs_show_mode(struct device *dev,
                                       char *buf)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
-                                               charger);
+       struct bq2415x_device *bq = power_supply_get_drvdata(psy);
        ssize_t ret = 0;
 
        if (bq->automode > 0)
@@ -1257,8 +1249,7 @@ static ssize_t bq2415x_sysfs_show_reported_mode(struct device *dev,
                                                char *buf)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
-                                                charger);
+       struct bq2415x_device *bq = power_supply_get_drvdata(psy);
 
        if (bq->automode < 0)
                return -EINVAL;
@@ -1286,8 +1277,7 @@ static ssize_t bq2415x_sysfs_set_registers(struct device *dev,
                                           size_t count)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
-                                                charger);
+       struct bq2415x_device *bq = power_supply_get_drvdata(psy);
        ssize_t ret = 0;
        unsigned int reg;
        unsigned int val;
@@ -1322,8 +1312,7 @@ static ssize_t bq2415x_sysfs_show_registers(struct device *dev,
                                            char *buf)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
-                                                charger);
+       struct bq2415x_device *bq = power_supply_get_drvdata(psy);
        ssize_t ret = 0;
 
        ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_STATUS, buf+ret);
@@ -1341,8 +1330,7 @@ static ssize_t bq2415x_sysfs_set_limit(struct device *dev,
                                       size_t count)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
-                                                charger);
+       struct bq2415x_device *bq = power_supply_get_drvdata(psy);
        long val;
        int ret;
 
@@ -1373,8 +1361,7 @@ static ssize_t bq2415x_sysfs_show_limit(struct device *dev,
                                        char *buf)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
-                                                charger);
+       struct bq2415x_device *bq = power_supply_get_drvdata(psy);
        int ret;
 
        if (strcmp(attr->attr.name, "current_limit") == 0)
@@ -1402,8 +1389,7 @@ static ssize_t bq2415x_sysfs_set_enable(struct device *dev,
                                        size_t count)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
-                                                charger);
+       struct bq2415x_device *bq = power_supply_get_drvdata(psy);
        enum bq2415x_command command;
        long val;
        int ret;
@@ -1438,8 +1424,7 @@ static ssize_t bq2415x_sysfs_show_enable(struct device *dev,
                                         char *buf)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
-                                                charger);
+       struct bq2415x_device *bq = power_supply_get_drvdata(psy);
        enum bq2415x_command command;
        int ret;
 
@@ -1530,13 +1515,13 @@ static const struct attribute_group bq2415x_sysfs_attr_group = {
 
 static int bq2415x_sysfs_init(struct bq2415x_device *bq)
 {
-       return sysfs_create_group(&bq->charger.dev->kobj,
+       return sysfs_create_group(&bq->charger->dev.kobj,
                        &bq2415x_sysfs_attr_group);
 }
 
 static void bq2415x_sysfs_exit(struct bq2415x_device *bq)
 {
-       sysfs_remove_group(&bq->charger.dev->kobj, &bq2415x_sysfs_attr_group);
+       sysfs_remove_group(&bq->charger->dev.kobj, &bq2415x_sysfs_attr_group);
 }
 
 /* main bq2415x probe function */
@@ -1609,27 +1594,27 @@ static int bq2415x_probe(struct i2c_client *client,
                ret = of_property_read_u32(np, "ti,current-limit",
                                &bq->init_data.current_limit);
                if (ret)
-                       goto error_2;
+                       goto error_3;
                ret = of_property_read_u32(np, "ti,weak-battery-voltage",
                                &bq->init_data.weak_battery_voltage);
                if (ret)
-                       goto error_2;
+                       goto error_3;
                ret = of_property_read_u32(np, "ti,battery-regulation-voltage",
                                &bq->init_data.battery_regulation_voltage);
                if (ret)
-                       goto error_2;
+                       goto error_3;
                ret = of_property_read_u32(np, "ti,charge-current",
                                &bq->init_data.charge_current);
                if (ret)
-                       goto error_2;
+                       goto error_3;
                ret = of_property_read_u32(np, "ti,termination-current",
                                &bq->init_data.termination_current);
                if (ret)
-                       goto error_2;
+                       goto error_3;
                ret = of_property_read_u32(np, "ti,resistor-sense",
                                &bq->init_data.resistor_sense);
                if (ret)
-                       goto error_2;
+                       goto error_3;
        } else {
                memcpy(&bq->init_data, pdata, sizeof(bq->init_data));
        }
@@ -1639,19 +1624,19 @@ 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_2;
+               goto error_3;
        }
 
        ret = bq2415x_sysfs_init(bq);
        if (ret) {
                dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret);
-               goto error_3;
+               goto error_4;
        }
 
        ret = bq2415x_set_defaults(bq);
        if (ret) {
                dev_err(bq->dev, "failed to set default values: %d\n", ret);
-               goto error_4;
+               goto error_5;
        }
 
        if (bq->notify_psy) {
@@ -1659,7 +1644,7 @@ static int bq2415x_probe(struct i2c_client *client,
                ret = power_supply_reg_notifier(&bq->nb);
                if (ret) {
                        dev_err(bq->dev, "failed to reg notifier: %d\n", ret);
-                       goto error_5;
+                       goto error_6;
                }
 
                /* Query for initial reported_mode and set it */
@@ -1679,11 +1664,14 @@ static int bq2415x_probe(struct i2c_client *client,
        dev_info(bq->dev, "driver registered\n");
        return 0;
 
+error_6:
 error_5:
-error_4:
        bq2415x_sysfs_exit(bq);
-error_3:
+error_4:
        bq2415x_power_supply_exit(bq);
+error_3:
+       if (bq->notify_psy)
+               power_supply_put(bq->notify_psy);
 error_2:
        kfree(name);
 error_1:
@@ -1700,8 +1688,10 @@ static int bq2415x_remove(struct i2c_client *client)
 {
        struct bq2415x_device *bq = i2c_get_clientdata(client);
 
-       if (bq->notify_psy)
+       if (bq->notify_psy) {
                power_supply_unreg_notifier(&bq->nb);
+               power_supply_put(bq->notify_psy);
+       }
 
        bq2415x_sysfs_exit(bq);
        bq2415x_power_supply_exit(bq);
@@ -1731,6 +1721,7 @@ static const struct i2c_device_id bq2415x_i2c_id_table[] = {
        { "bq24155", BQ24155 },
        { "bq24156", BQ24156 },
        { "bq24156a", BQ24156A },
+       { "bq24157s", BQ24157S },
        { "bq24158", BQ24158 },
        {},
 };
index d0e8236a64042d8c614ba598d2634b8bd9b0ca7b..407c4af83891331611ba710c62a7b5a8d1633d7b 100644 (file)
 struct bq24190_dev_info {
        struct i2c_client               *client;
        struct device                   *dev;
-       struct power_supply             charger;
-       struct power_supply             battery;
+       struct power_supply             *charger;
+       struct power_supply             *battery;
        char                            model_name[I2C_NAME_SIZE];
        kernel_ulong_t                  model;
        unsigned int                    gpio_int;
@@ -423,8 +423,7 @@ static ssize_t bq24190_sysfs_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq24190_dev_info *bdi =
-                       container_of(psy, struct bq24190_dev_info, charger);
+       struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
        struct bq24190_sysfs_field_info *info;
        int ret;
        u8 v;
@@ -444,8 +443,7 @@ static ssize_t bq24190_sysfs_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
        struct power_supply *psy = dev_get_drvdata(dev);
-       struct bq24190_dev_info *bdi =
-                       container_of(psy, struct bq24190_dev_info, charger);
+       struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
        struct bq24190_sysfs_field_info *info;
        int ret;
        u8 v;
@@ -469,13 +467,13 @@ static int bq24190_sysfs_create_group(struct bq24190_dev_info *bdi)
 {
        bq24190_sysfs_init_attrs();
 
-       return sysfs_create_group(&bdi->charger.dev->kobj,
+       return sysfs_create_group(&bdi->charger->dev.kobj,
                        &bq24190_sysfs_attr_group);
 }
 
 static void bq24190_sysfs_remove_group(struct bq24190_dev_info *bdi)
 {
-       sysfs_remove_group(&bdi->charger.dev->kobj, &bq24190_sysfs_attr_group);
+       sysfs_remove_group(&bdi->charger->dev.kobj, &bq24190_sysfs_attr_group);
 }
 #else
 static int bq24190_sysfs_create_group(struct bq24190_dev_info *bdi)
@@ -807,8 +805,7 @@ static int bq24190_charger_set_voltage(struct bq24190_dev_info *bdi,
 static int bq24190_charger_get_property(struct power_supply *psy,
                enum power_supply_property psp, union power_supply_propval *val)
 {
-       struct bq24190_dev_info *bdi =
-                       container_of(psy, struct bq24190_dev_info, charger);
+       struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
        int ret;
 
        dev_dbg(bdi->dev, "prop: %d\n", psp);
@@ -861,8 +858,7 @@ static int bq24190_charger_set_property(struct power_supply *psy,
                enum power_supply_property psp,
                const union power_supply_propval *val)
 {
-       struct bq24190_dev_info *bdi =
-                       container_of(psy, struct bq24190_dev_info, charger);
+       struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
        int ret;
 
        dev_dbg(bdi->dev, "prop: %d\n", psp);
@@ -922,18 +918,15 @@ static char *bq24190_charger_supplied_to[] = {
        "main-battery",
 };
 
-static void bq24190_charger_init(struct power_supply *charger)
-{
-       charger->name = "bq24190-charger";
-       charger->type = POWER_SUPPLY_TYPE_USB;
-       charger->properties = bq24190_charger_properties;
-       charger->num_properties = ARRAY_SIZE(bq24190_charger_properties);
-       charger->supplied_to = bq24190_charger_supplied_to;
-       charger->num_supplicants = ARRAY_SIZE(bq24190_charger_supplied_to);
-       charger->get_property = bq24190_charger_get_property;
-       charger->set_property = bq24190_charger_set_property;
-       charger->property_is_writeable = bq24190_charger_property_is_writeable;
-}
+static const struct power_supply_desc bq24190_charger_desc = {
+       .name                   = "bq24190-charger",
+       .type                   = POWER_SUPPLY_TYPE_USB,
+       .properties             = bq24190_charger_properties,
+       .num_properties         = ARRAY_SIZE(bq24190_charger_properties),
+       .get_property           = bq24190_charger_get_property,
+       .set_property           = bq24190_charger_set_property,
+       .property_is_writeable  = bq24190_charger_property_is_writeable,
+};
 
 /* Battery power supply property routines */
 
@@ -1102,8 +1095,7 @@ static int bq24190_battery_set_temp_alert_max(struct bq24190_dev_info *bdi,
 static int bq24190_battery_get_property(struct power_supply *psy,
                enum power_supply_property psp, union power_supply_propval *val)
 {
-       struct bq24190_dev_info *bdi =
-                       container_of(psy, struct bq24190_dev_info, battery);
+       struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
        int ret;
 
        dev_dbg(bdi->dev, "prop: %d\n", psp);
@@ -1144,8 +1136,7 @@ static int bq24190_battery_set_property(struct power_supply *psy,
                enum power_supply_property psp,
                const union power_supply_propval *val)
 {
-       struct bq24190_dev_info *bdi =
-                       container_of(psy, struct bq24190_dev_info, battery);
+       struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
        int ret;
 
        dev_dbg(bdi->dev, "prop: %d\n", psp);
@@ -1193,16 +1184,15 @@ static enum power_supply_property bq24190_battery_properties[] = {
        POWER_SUPPLY_PROP_SCOPE,
 };
 
-static void bq24190_battery_init(struct power_supply *battery)
-{
-       battery->name = "bq24190-battery";
-       battery->type = POWER_SUPPLY_TYPE_BATTERY;
-       battery->properties = bq24190_battery_properties;
-       battery->num_properties = ARRAY_SIZE(bq24190_battery_properties);
-       battery->get_property = bq24190_battery_get_property;
-       battery->set_property = bq24190_battery_set_property;
-       battery->property_is_writeable = bq24190_battery_property_is_writeable;
-}
+static const struct power_supply_desc bq24190_battery_desc = {
+       .name                   = "bq24190-battery",
+       .type                   = POWER_SUPPLY_TYPE_BATTERY,
+       .properties             = bq24190_battery_properties,
+       .num_properties         = ARRAY_SIZE(bq24190_battery_properties),
+       .get_property           = bq24190_battery_get_property,
+       .set_property           = bq24190_battery_set_property,
+       .property_is_writeable  = bq24190_battery_property_is_writeable,
+};
 
 static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
 {
@@ -1269,8 +1259,8 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
         * interrupt received).
         */
        if (alert_userspace && !bdi->first_time) {
-               power_supply_changed(&bdi->charger);
-               power_supply_changed(&bdi->battery);
+               power_supply_changed(bdi->charger);
+               power_supply_changed(bdi->battery);
                bdi->first_time = false;
        }
 
@@ -1362,6 +1352,7 @@ static int bq24190_probe(struct i2c_client *client,
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
        struct device *dev = &client->dev;
        struct bq24190_platform_data *pdata = client->dev.platform_data;
+       struct power_supply_config charger_cfg = {}, battery_cfg = {};
        struct bq24190_dev_info *bdi;
        int ret;
 
@@ -1416,19 +1407,23 @@ static int bq24190_probe(struct i2c_client *client,
                goto out2;
        }
 
-       bq24190_charger_init(&bdi->charger);
-
-       ret = power_supply_register(dev, &bdi->charger);
-       if (ret) {
+       charger_cfg.drv_data = bdi;
+       charger_cfg.supplied_to = bq24190_charger_supplied_to;
+       charger_cfg.num_supplicants = ARRAY_SIZE(bq24190_charger_supplied_to),
+       bdi->charger = power_supply_register(dev, &bq24190_charger_desc,
+                                               &charger_cfg);
+       if (IS_ERR(bdi->charger)) {
                dev_err(dev, "Can't register charger\n");
+               ret = PTR_ERR(bdi->charger);
                goto out2;
        }
 
-       bq24190_battery_init(&bdi->battery);
-
-       ret = power_supply_register(dev, &bdi->battery);
-       if (ret) {
+       battery_cfg.drv_data = bdi;
+       bdi->battery = power_supply_register(dev, &bq24190_battery_desc,
+                                               &battery_cfg);
+       if (IS_ERR(bdi->battery)) {
                dev_err(dev, "Can't register battery\n");
+               ret = PTR_ERR(bdi->battery);
                goto out3;
        }
 
@@ -1441,9 +1436,9 @@ static int bq24190_probe(struct i2c_client *client,
        return 0;
 
 out4:
-       power_supply_unregister(&bdi->battery);
+       power_supply_unregister(bdi->battery);
 out3:
-       power_supply_unregister(&bdi->charger);
+       power_supply_unregister(bdi->charger);
 out2:
        pm_runtime_disable(dev);
 out1:
@@ -1462,8 +1457,8 @@ static int bq24190_remove(struct i2c_client *client)
        pm_runtime_put_sync(bdi->dev);
 
        bq24190_sysfs_remove_group(bdi);
-       power_supply_unregister(&bdi->battery);
-       power_supply_unregister(&bdi->charger);
+       power_supply_unregister(bdi->battery);
+       power_supply_unregister(bdi->charger);
        pm_runtime_disable(bdi->dev);
 
        if (bdi->gpio_int)
@@ -1499,8 +1494,8 @@ static int bq24190_pm_resume(struct device *dev)
        pm_runtime_put_sync(bdi->dev);
 
        /* Things may have changed while suspended so alert upper layer */
-       power_supply_changed(&bdi->charger);
-       power_supply_changed(&bdi->battery);
+       power_supply_changed(bdi->charger);
+       power_supply_changed(bdi->battery);
 
        return 0;
 }
index d022b823305b340183acfe1e55e89799ec9b41ac..961a189300275a3d65b5885ab5d647822059ba4c 100644 (file)
 #define BQ24735_DEVICE_ID              0xff
 
 struct bq24735 {
-       struct power_supply     charger;
-       struct i2c_client       *client;
-       struct bq24735_platform *pdata;
+       struct power_supply             *charger;
+       struct power_supply_desc        charger_desc;
+       struct i2c_client               *client;
+       struct bq24735_platform         *pdata;
 };
 
 static inline struct bq24735 *to_bq24735(struct power_supply *psy)
 {
-       return container_of(psy, struct bq24735, charger);
+       return power_supply_get_drvdata(psy);
 }
 
 static enum power_supply_property bq24735_charger_properties[] = {
@@ -192,9 +193,7 @@ static int bq24735_charger_get_property(struct power_supply *psy,
                                        enum power_supply_property psp,
                                        union power_supply_propval *val)
 {
-       struct bq24735 *charger;
-
-       charger = container_of(psy, struct bq24735, charger);
+       struct bq24735 *charger = to_bq24735(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_ONLINE:
@@ -248,7 +247,8 @@ static int bq24735_charger_probe(struct i2c_client *client,
 {
        int ret;
        struct bq24735 *charger;
-       struct power_supply *supply;
+       struct power_supply_desc *supply_desc;
+       struct power_supply_config psy_cfg = {};
        char *name;
 
        charger = devm_kzalloc(&client->dev, sizeof(*charger), GFP_KERNEL);
@@ -277,16 +277,18 @@ static int bq24735_charger_probe(struct i2c_client *client,
 
        charger->client = client;
 
-       supply = &charger->charger;
+       supply_desc = &charger->charger_desc;
 
-       supply->name = name;
-       supply->type = POWER_SUPPLY_TYPE_MAINS;
-       supply->properties = bq24735_charger_properties;
-       supply->num_properties = ARRAY_SIZE(bq24735_charger_properties);
-       supply->get_property = bq24735_charger_get_property;
-       supply->supplied_to = charger->pdata->supplied_to;
-       supply->num_supplicants = charger->pdata->num_supplicants;
-       supply->of_node = client->dev.of_node;
+       supply_desc->name = name;
+       supply_desc->type = POWER_SUPPLY_TYPE_MAINS;
+       supply_desc->properties = bq24735_charger_properties;
+       supply_desc->num_properties = ARRAY_SIZE(bq24735_charger_properties);
+       supply_desc->get_property = bq24735_charger_get_property;
+
+       psy_cfg.supplied_to = charger->pdata->supplied_to;
+       psy_cfg.num_supplicants = charger->pdata->num_supplicants;
+       psy_cfg.of_node = client->dev.of_node;
+       psy_cfg.drv_data = charger;
 
        i2c_set_clientdata(client, charger);
 
@@ -341,8 +343,10 @@ static int bq24735_charger_probe(struct i2c_client *client,
                }
        }
 
-       ret = power_supply_register(&client->dev, supply);
-       if (ret < 0) {
+       charger->charger = 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;
@@ -354,7 +358,8 @@ static int bq24735_charger_probe(struct i2c_client *client,
                                                IRQF_TRIGGER_RISING |
                                                IRQF_TRIGGER_FALLING |
                                                IRQF_ONESHOT,
-                                               supply->name, supply);
+                                               supply_desc->name,
+                                               charger->charger);
                if (ret) {
                        dev_err(&client->dev,
                                "Unable to register IRQ %d err %d\n",
@@ -365,7 +370,7 @@ static int bq24735_charger_probe(struct i2c_client *client,
 
        return 0;
 err_unregister_supply:
-       power_supply_unregister(supply);
+       power_supply_unregister(charger->charger);
 err_free_name:
        if (name != charger->pdata->name)
                kfree(name);
@@ -381,10 +386,10 @@ static int bq24735_charger_remove(struct i2c_client *client)
                devm_free_irq(&charger->client->dev, charger->client->irq,
                              &charger->charger);
 
-       power_supply_unregister(&charger->charger);
+       power_supply_unregister(charger->charger);
 
-       if (charger->charger.name != charger->pdata->name)
-               kfree(charger->charger.name);
+       if (charger->charger_desc.name != charger->pdata->name)
+               kfree(charger->charger_desc.name);
 
        return 0;
 }
index b72ba7c1bd69fd99365381414ca84305d5b20808..a57433de5c249fa33e6fb4f59e7c2dbf3190208b 100644 (file)
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- */
-
-/*
  * Datasheets:
  * http://focus.ti.com/docs/prod/folders/print/bq27000.html
  * http://focus.ti.com/docs/prod/folders/print/bq27500.html
  * http://www.ti.com/product/bq27425-g1
  * http://www.ti.com/product/BQ27742-G1
+ * http://www.ti.com/product/BQ27510-G3
  */
 
 #include <linux/device.h>
 
 #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_SOC                (0x1C + BQ27425_REG_OFFSET)
@@ -87,7 +89,7 @@ struct bq27x00_access_methods {
        int (*read)(struct bq27x00_device_info *di, u8 reg, bool single);
 };
 
-enum bq27x00_chip { BQ27000, BQ27500, BQ27425, BQ27742};
+enum bq27x00_chip { BQ27000, BQ27500, BQ27425, BQ27742, BQ27510};
 
 struct bq27x00_reg_cache {
        int temperature;
@@ -114,7 +116,7 @@ struct bq27x00_device_info {
        unsigned long last_update;
        struct delayed_work work;
 
-       struct power_supply     bat;
+       struct power_supply     *bat;
 
        struct bq27x00_access_methods bus;
 
@@ -174,6 +176,24 @@ static enum power_supply_property bq27742_battery_props[] = {
        POWER_SUPPLY_PROP_HEALTH,
 };
 
+static enum power_supply_property bq27510_battery_props[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+       POWER_SUPPLY_PROP_TEMP,
+       POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+       POWER_SUPPLY_PROP_TECHNOLOGY,
+       POWER_SUPPLY_PROP_CHARGE_FULL,
+       POWER_SUPPLY_PROP_CHARGE_NOW,
+       POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+       POWER_SUPPLY_PROP_CYCLE_COUNT,
+       POWER_SUPPLY_PROP_POWER_AVG,
+       POWER_SUPPLY_PROP_HEALTH,
+};
+
 static unsigned int poll_interval = 360;
 module_param(poll_interval, uint, 0644);
 MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \
@@ -198,7 +218,8 @@ static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg,
  */
 static bool bq27xxx_is_chip_version_higher(struct bq27x00_device_info *di)
 {
-       if (di->chip == BQ27425 || di->chip == BQ27500 || di->chip == BQ27742)
+       if (di->chip == BQ27425 || di->chip == BQ27500 || di->chip == BQ27742
+           || di->chip == BQ27510)
                return true;
        return false;
 }
@@ -213,6 +234,8 @@ static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
 
        if (di->chip == BQ27500 || di->chip == BQ27742)
                rsoc = bq27x00_read(di, BQ27500_REG_SOC, false);
+       else if (di->chip == BQ27510)
+               rsoc = bq27x00_read(di, BQ27510_REG_SOC, false);
        else if (di->chip == BQ27425)
                rsoc = bq27x00_read(di, BQ27425_REG_SOC, false);
        else
@@ -286,6 +309,8 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
        if (bq27xxx_is_chip_version_higher(di)) {
                if (di->chip == BQ27425)
                        ilmd = bq27x00_read(di, BQ27425_REG_DCAP, false);
+               else if (di->chip == BQ27510)
+                       ilmd = bq27x00_read(di, BQ27510_REG_DCAP, false);
                else
                        ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false);
        } else
@@ -354,7 +379,10 @@ static int bq27x00_battery_read_cyct(struct bq27x00_device_info *di)
 {
        int cyct;
 
-       cyct = bq27x00_read(di, BQ27x00_REG_CYCT, false);
+       if (di->chip == BQ27510)
+               cyct = bq27x00_read(di, BQ27510_REG_CYCT, false);
+       else
+               cyct = bq27x00_read(di, BQ27x00_REG_CYCT, false);
        if (cyct < 0)
                dev_err(di->dev, "error reading cycle count total\n");
 
@@ -425,6 +453,10 @@ static int bq27x00_battery_read_health(struct bq27x00_device_info *di)
                else
                        tval = POWER_SUPPLY_HEALTH_GOOD;
                return tval;
+       } else if (di->chip == BQ27510) {
+               if (tval & BQ27500_FLAG_OTC)
+                       return POWER_SUPPLY_HEALTH_OVERHEAT;
+               return POWER_SUPPLY_HEALTH_GOOD;
        } else {
                if (tval & BQ27000_FLAG_EDV1)
                        tval = POWER_SUPPLY_HEALTH_DEAD;
@@ -440,6 +472,7 @@ static void bq27x00_update(struct bq27x00_device_info *di)
 {
        struct bq27x00_reg_cache cache = {0, };
        bool is_bq27500 = di->chip == BQ27500;
+       bool is_bq27510 = di->chip == BQ27510;
        bool is_bq27425 = di->chip == BQ27425;
        bool is_bq27742 = di->chip == BQ27742;
        bool flags_1b = !(is_bq27500 || is_bq27742);
@@ -449,7 +482,7 @@ static void bq27x00_update(struct bq27x00_device_info *di)
                /* read error */
                cache.flags = -1;
        if (cache.flags >= 0) {
-               if (!is_bq27500 && !is_bq27425 && !is_bq27742
+               if (!is_bq27500 && !is_bq27425 && !is_bq27742 && !is_bq27510
                                && (cache.flags & BQ27000_FLAG_CI)) {
                        dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
                        cache.capacity = -ENODATA;
@@ -461,7 +494,7 @@ static void bq27x00_update(struct bq27x00_device_info *di)
                        cache.health = -ENODATA;
                } else {
                        cache.capacity = bq27x00_battery_read_rsoc(di);
-                       if (is_bq27742)
+                       if (is_bq27742 || is_bq27510)
                                cache.time_to_empty =
                                        bq27x00_battery_read_time(di,
                                                        BQ27x00_REG_TTE);
@@ -498,7 +531,7 @@ static void bq27x00_update(struct bq27x00_device_info *di)
        }
 
        if (di->cache.capacity != cache.capacity)
-               power_supply_changed(&di->bat);
+               power_supply_changed(di->bat);
 
        if (memcmp(&di->cache, &cache, sizeof(cache)) != 0)
                di->cache = cache;
@@ -570,7 +603,7 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,
                        status = POWER_SUPPLY_STATUS_FULL;
                else if (di->cache.flags & BQ27000_FLAG_CHGS)
                        status = POWER_SUPPLY_STATUS_CHARGING;
-               else if (power_supply_am_i_supplied(&di->bat))
+               else if (power_supply_am_i_supplied(di->bat))
                        status = POWER_SUPPLY_STATUS_NOT_CHARGING;
                else
                        status = POWER_SUPPLY_STATUS_DISCHARGING;
@@ -642,15 +675,12 @@ static int bq27x00_simple_value(int value,
        return 0;
 }
 
-#define to_bq27x00_device_info(x) container_of((x), \
-                               struct bq27x00_device_info, bat);
-
 static int bq27x00_battery_get_property(struct power_supply *psy,
                                        enum power_supply_property psp,
                                        union power_supply_propval *val)
 {
        int ret = 0;
-       struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
+       struct bq27x00_device_info *di = power_supply_get_drvdata(psy);
 
        mutex_lock(&di->lock);
        if (time_is_before_jiffies(di->last_update + 5 * HZ)) {
@@ -728,35 +758,47 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
 
 static void bq27x00_external_power_changed(struct power_supply *psy)
 {
-       struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
+       struct bq27x00_device_info *di = power_supply_get_drvdata(psy);
 
        cancel_delayed_work_sync(&di->work);
        schedule_delayed_work(&di->work, 0);
 }
 
-static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
+static int bq27x00_powersupply_init(struct bq27x00_device_info *di,
+                                   const char *name)
 {
        int ret;
+       struct power_supply_desc *psy_desc;
+       struct power_supply_config psy_cfg = { .drv_data = di, };
 
-       di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
+       psy_desc = devm_kzalloc(di->dev, sizeof(*psy_desc), GFP_KERNEL);
+       if (!psy_desc)
+               return -ENOMEM;
+
+       psy_desc->name = name;
+       psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
        if (di->chip == BQ27425) {
-               di->bat.properties = bq27425_battery_props;
-               di->bat.num_properties = ARRAY_SIZE(bq27425_battery_props);
+               psy_desc->properties = bq27425_battery_props;
+               psy_desc->num_properties = ARRAY_SIZE(bq27425_battery_props);
        } else if (di->chip == BQ27742) {
-               di->bat.properties = bq27742_battery_props;
-               di->bat.num_properties = ARRAY_SIZE(bq27742_battery_props);
+               psy_desc->properties = bq27742_battery_props;
+               psy_desc->num_properties = ARRAY_SIZE(bq27742_battery_props);
+       } else if (di->chip == BQ27510) {
+               psy_desc->properties = bq27510_battery_props;
+               psy_desc->num_properties = ARRAY_SIZE(bq27510_battery_props);
        } else {
-               di->bat.properties = bq27x00_battery_props;
-               di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props);
+               psy_desc->properties = bq27x00_battery_props;
+               psy_desc->num_properties = ARRAY_SIZE(bq27x00_battery_props);
        }
-       di->bat.get_property = bq27x00_battery_get_property;
-       di->bat.external_power_changed = bq27x00_external_power_changed;
+       psy_desc->get_property = bq27x00_battery_get_property;
+       psy_desc->external_power_changed = bq27x00_external_power_changed;
 
        INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll);
        mutex_init(&di->lock);
 
-       ret = power_supply_register(di->dev, &di->bat);
-       if (ret) {
+       di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
+       if (IS_ERR(di->bat)) {
+               ret = PTR_ERR(di->bat);
                dev_err(di->dev, "failed to register battery: %d\n", ret);
                return ret;
        }
@@ -780,7 +822,7 @@ static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
 
        cancel_delayed_work_sync(&di->work);
 
-       power_supply_unregister(&di->bat);
+       power_supply_unregister(di->bat);
 
        mutex_destroy(&di->lock);
 }
@@ -844,37 +886,34 @@ static int bq27x00_battery_probe(struct i2c_client *client,
        if (num < 0)
                return num;
 
-       name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num);
+       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_1;
+               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_2;
+               goto batt_failed;
        }
 
        di->id = num;
        di->dev = &client->dev;
        di->chip = id->driver_data;
-       di->bat.name = name;
        di->bus.read = &bq27x00_read_i2c;
 
-       retval = bq27x00_powersupply_init(di);
+       retval = bq27x00_powersupply_init(di, name);
        if (retval)
-               goto batt_failed_2;
+               goto batt_failed;
 
        i2c_set_clientdata(client, di);
 
        return 0;
 
-batt_failed_2:
-       kfree(name);
-batt_failed_1:
+batt_failed:
        mutex_lock(&battery_mutex);
        idr_remove(&battery_id, num);
        mutex_unlock(&battery_mutex);
@@ -888,8 +927,6 @@ static int bq27x00_battery_remove(struct i2c_client *client)
 
        bq27x00_powersupply_unregister(di);
 
-       kfree(di->bat.name);
-
        mutex_lock(&battery_mutex);
        idr_remove(&battery_id, di->id);
        mutex_unlock(&battery_mutex);
@@ -902,6 +939,7 @@ static const struct i2c_device_id bq27x00_id[] = {
        { "bq27500", BQ27500 },
        { "bq27425", BQ27425 },
        { "bq27742", BQ27742 },
+       { "bq27510", BQ27510 },
        {},
 };
 MODULE_DEVICE_TABLE(i2c, bq27x00_id);
@@ -977,6 +1015,7 @@ static int bq27000_battery_probe(struct platform_device *pdev)
 {
        struct bq27x00_device_info *di;
        struct bq27000_platform_data *pdata = pdev->dev.platform_data;
+       const char *name;
 
        if (!pdata) {
                dev_err(&pdev->dev, "no platform_data supplied\n");
@@ -999,10 +1038,10 @@ static int bq27000_battery_probe(struct platform_device *pdev)
        di->dev = &pdev->dev;
        di->chip = BQ27000;
 
-       di->bat.name = pdata->name ?: dev_name(&pdev->dev);
+       name = pdata->name ?: dev_name(&pdev->dev);
        di->bus.read = &bq27000_read_platform;
 
-       return bq27x00_powersupply_init(di);
+       return bq27x00_powersupply_init(di, name);
 }
 
 static int bq27000_battery_remove(struct platform_device *pdev)
index 14b0d85318eb59fac2fa9837f85750cfe31b5476..0aed13f908914a5dfdf0b9303ff95587e7552492 100644 (file)
@@ -103,10 +103,11 @@ static bool is_batt_present(struct charger_manager *cm)
                if (!psy)
                        break;
 
-               ret = psy->get_property(psy,
-                               POWER_SUPPLY_PROP_PRESENT, &val);
+               ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_PRESENT,
+                               &val);
                if (ret == 0 && val.intval)
                        present = true;
+               power_supply_put(psy);
                break;
        case CM_CHARGER_STAT:
                for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
@@ -118,8 +119,9 @@ static bool is_batt_present(struct charger_manager *cm)
                                continue;
                        }
 
-                       ret = psy->get_property(psy, POWER_SUPPLY_PROP_PRESENT,
-                                       &val);
+                       ret = power_supply_get_property(psy,
+                               POWER_SUPPLY_PROP_PRESENT, &val);
+                       power_supply_put(psy);
                        if (ret == 0 && val.intval) {
                                present = true;
                                break;
@@ -155,7 +157,9 @@ static bool is_ext_pwr_online(struct charger_manager *cm)
                        continue;
                }
 
-               ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val);
+               ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE,
+                               &val);
+               power_supply_put(psy);
                if (ret == 0 && val.intval) {
                        online = true;
                        break;
@@ -183,8 +187,9 @@ static int get_batt_uV(struct charger_manager *cm, int *uV)
        if (!fuel_gauge)
                return -ENODEV;
 
-       ret = fuel_gauge->get_property(fuel_gauge,
+       ret = power_supply_get_property(fuel_gauge,
                                POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
+       power_supply_put(fuel_gauge);
        if (ret)
                return ret;
 
@@ -223,20 +228,26 @@ static bool is_charging(struct charger_manager *cm)
                }
 
                /* 2. The charger should be online (ext-power) */
-               ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val);
+               ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE,
+                               &val);
                if (ret) {
                        dev_warn(cm->dev, "Cannot read ONLINE value from %s\n",
                                 cm->desc->psy_charger_stat[i]);
+                       power_supply_put(psy);
                        continue;
                }
-               if (val.intval == 0)
+               if (val.intval == 0) {
+                       power_supply_put(psy);
                        continue;
+               }
 
                /*
                 * 3. The charger should not be FULL, DISCHARGING,
                 * or NOT_CHARGING.
                 */
-               ret = psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &val);
+               ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS,
+                               &val);
+               power_supply_put(psy);
                if (ret) {
                        dev_warn(cm->dev, "Cannot read STATUS value from %s\n",
                                 cm->desc->psy_charger_stat[i]);
@@ -264,6 +275,7 @@ static bool is_full_charged(struct charger_manager *cm)
        struct charger_desc *desc = cm->desc;
        union power_supply_propval val;
        struct power_supply *fuel_gauge;
+       bool is_full = false;
        int ret = 0;
        int uV;
 
@@ -279,30 +291,38 @@ static bool is_full_charged(struct charger_manager *cm)
                val.intval = 0;
 
                /* Not full if capacity of fuel gauge isn't full */
-               ret = fuel_gauge->get_property(fuel_gauge,
+               ret = power_supply_get_property(fuel_gauge,
                                POWER_SUPPLY_PROP_CHARGE_FULL, &val);
-               if (!ret && val.intval > desc->fullbatt_full_capacity)
-                       return true;
+               if (!ret && val.intval > desc->fullbatt_full_capacity) {
+                       is_full = true;
+                       goto out;
+               }
        }
 
        /* Full, if it's over the fullbatt voltage */
        if (desc->fullbatt_uV > 0) {
                ret = get_batt_uV(cm, &uV);
-               if (!ret && uV >= desc->fullbatt_uV)
-                       return true;
+               if (!ret && uV >= desc->fullbatt_uV) {
+                       is_full = true;
+                       goto out;
+               }
        }
 
        /* Full, if the capacity is more than fullbatt_soc */
        if (desc->fullbatt_soc > 0) {
                val.intval = 0;
 
-               ret = fuel_gauge->get_property(fuel_gauge,
+               ret = power_supply_get_property(fuel_gauge,
                                POWER_SUPPLY_PROP_CAPACITY, &val);
-               if (!ret && val.intval >= desc->fullbatt_soc)
-                       return true;
+               if (!ret && val.intval >= desc->fullbatt_soc) {
+                       is_full = true;
+                       goto out;
+               }
        }
 
-       return false;
+out:
+       power_supply_put(fuel_gauge);
+       return is_full;
 }
 
 /**
@@ -575,14 +595,18 @@ static int cm_get_battery_temperature_by_psy(struct charger_manager *cm,
                                        int *temp)
 {
        struct power_supply *fuel_gauge;
+       int ret;
 
        fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
        if (!fuel_gauge)
                return -ENODEV;
 
-       return fuel_gauge->get_property(fuel_gauge,
+       ret = power_supply_get_property(fuel_gauge,
                                POWER_SUPPLY_PROP_TEMP,
                                (union power_supply_propval *)temp);
+       power_supply_put(fuel_gauge);
+
+       return ret;
 }
 
 static int cm_get_battery_temperature(struct charger_manager *cm,
@@ -861,10 +885,9 @@ static int charger_get_property(struct power_supply *psy,
                enum power_supply_property psp,
                union power_supply_propval *val)
 {
-       struct charger_manager *cm = container_of(psy,
-                       struct charger_manager, charger_psy);
+       struct charger_manager *cm = power_supply_get_drvdata(psy);
        struct charger_desc *desc = cm->desc;
-       struct power_supply *fuel_gauge;
+       struct power_supply *fuel_gauge = NULL;
        int ret = 0;
        int uV;
 
@@ -900,26 +923,26 @@ static int charger_get_property(struct power_supply *psy,
                        ret = -ENODEV;
                        break;
                }
-               ret = fuel_gauge->get_property(fuel_gauge,
+               ret = power_supply_get_property(fuel_gauge,
                                POWER_SUPPLY_PROP_CURRENT_NOW, val);
                break;
        case POWER_SUPPLY_PROP_TEMP:
        case POWER_SUPPLY_PROP_TEMP_AMBIENT:
                return cm_get_battery_temperature(cm, &val->intval);
        case POWER_SUPPLY_PROP_CAPACITY:
-               fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
-               if (!fuel_gauge) {
-                       ret = -ENODEV;
-                       break;
-               }
-
                if (!is_batt_present(cm)) {
                        /* There is no battery. Assume 100% */
                        val->intval = 100;
                        break;
                }
 
-               ret = fuel_gauge->get_property(fuel_gauge,
+               fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
+               if (!fuel_gauge) {
+                       ret = -ENODEV;
+                       break;
+               }
+
+               ret = power_supply_get_property(fuel_gauge,
                                        POWER_SUPPLY_PROP_CAPACITY, val);
                if (ret)
                        break;
@@ -975,7 +998,7 @@ static int charger_get_property(struct power_supply *psy,
                                break;
                        }
 
-                       ret = fuel_gauge->get_property(fuel_gauge,
+                       ret = power_supply_get_property(fuel_gauge,
                                                POWER_SUPPLY_PROP_CHARGE_NOW,
                                                val);
                        if (ret) {
@@ -993,6 +1016,8 @@ static int charger_get_property(struct power_supply *psy,
        default:
                return -EINVAL;
        }
+       if (fuel_gauge)
+               power_supply_put(fuel_gauge);
        return ret;
 }
 
@@ -1015,7 +1040,7 @@ static enum power_supply_property default_charger_props[] = {
         */
 };
 
-static struct power_supply psy_default = {
+static const struct power_supply_desc psy_default = {
        .name = "battery",
        .type = POWER_SUPPLY_TYPE_BATTERY,
        .properties = default_charger_props,
@@ -1396,7 +1421,7 @@ static int charger_manager_register_sysfs(struct charger_manager *cm)
                dev_info(cm->dev, "'%s' regulator's externally_control is %d\n",
                         charger->regulator_name, charger->externally_control);
 
-               ret = sysfs_create_group(&cm->charger_psy.dev->kobj,
+               ret = sysfs_create_group(&cm->charger_psy->dev.kobj,
                                        &charger->attr_g);
                if (ret < 0) {
                        dev_err(cm->dev, "Cannot create sysfs entry of %s regulator\n",
@@ -1424,13 +1449,13 @@ static int cm_init_thermal_data(struct charger_manager *cm,
        int ret;
 
        /* Verify whether fuel gauge provides battery temperature */
-       ret = fuel_gauge->get_property(fuel_gauge,
+       ret = power_supply_get_property(fuel_gauge,
                                        POWER_SUPPLY_PROP_TEMP, &val);
 
        if (!ret) {
-               cm->charger_psy.properties[cm->charger_psy.num_properties] =
+               cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] =
                                POWER_SUPPLY_PROP_TEMP;
-               cm->charger_psy.num_properties++;
+               cm->charger_psy_desc.num_properties++;
                cm->desc->measure_battery_temp = true;
        }
 #ifdef CONFIG_THERMAL
@@ -1441,9 +1466,9 @@ static int cm_init_thermal_data(struct charger_manager *cm,
                        return PTR_ERR(cm->tzd_batt);
 
                /* Use external thermometer */
-               cm->charger_psy.properties[cm->charger_psy.num_properties] =
+               cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] =
                                POWER_SUPPLY_PROP_TEMP_AMBIENT;
-               cm->charger_psy.num_properties++;
+               cm->charger_psy_desc.num_properties++;
                cm->desc->measure_battery_temp = true;
                ret = 0;
        }
@@ -1459,7 +1484,7 @@ static int cm_init_thermal_data(struct charger_manager *cm,
        return ret;
 }
 
-static struct of_device_id charger_manager_match[] = {
+static const struct of_device_id charger_manager_match[] = {
        {
                .compatible = "charger-manager",
        },
@@ -1603,6 +1628,7 @@ static int charger_manager_probe(struct platform_device *pdev)
        int j = 0;
        union power_supply_propval val;
        struct power_supply *fuel_gauge;
+       struct power_supply_config psy_cfg = {};
 
        if (IS_ERR(desc)) {
                dev_err(&pdev->dev, "No platform data (desc) found\n");
@@ -1617,6 +1643,7 @@ static int charger_manager_probe(struct platform_device *pdev)
        /* Basic Values. Unspecified are Null or 0 */
        cm->dev = &pdev->dev;
        cm->desc = desc;
+       psy_cfg.drv_data = cm;
 
        /* Initialize alarm timer */
        if (alarmtimer_get_rtcdev()) {
@@ -1672,13 +1699,7 @@ static int charger_manager_probe(struct platform_device *pdev)
                                desc->psy_charger_stat[i]);
                        return -ENODEV;
                }
-       }
-
-       fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge);
-       if (!fuel_gauge) {
-               dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n",
-                       desc->psy_fuel_gauge);
-               return -ENODEV;
+               power_supply_put(psy);
        }
 
        if (desc->polling_interval_ms == 0 ||
@@ -1696,40 +1717,46 @@ static int charger_manager_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, cm);
 
-       memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default));
+       memcpy(&cm->charger_psy_desc, &psy_default, sizeof(psy_default));
 
        if (!desc->psy_name)
                strncpy(cm->psy_name_buf, psy_default.name, PSY_NAME_MAX);
        else
                strncpy(cm->psy_name_buf, desc->psy_name, PSY_NAME_MAX);
-       cm->charger_psy.name = cm->psy_name_buf;
+       cm->charger_psy_desc.name = cm->psy_name_buf;
 
        /* Allocate for psy properties because they may vary */
-       cm->charger_psy.properties = devm_kzalloc(&pdev->dev,
+       cm->charger_psy_desc.properties = devm_kzalloc(&pdev->dev,
                                sizeof(enum power_supply_property)
                                * (ARRAY_SIZE(default_charger_props) +
                                NUM_CHARGER_PSY_OPTIONAL), GFP_KERNEL);
-       if (!cm->charger_psy.properties)
+       if (!cm->charger_psy_desc.properties)
                return -ENOMEM;
 
-       memcpy(cm->charger_psy.properties, default_charger_props,
+       memcpy(cm->charger_psy_desc.properties, default_charger_props,
                sizeof(enum power_supply_property) *
                ARRAY_SIZE(default_charger_props));
-       cm->charger_psy.num_properties = psy_default.num_properties;
+       cm->charger_psy_desc.num_properties = psy_default.num_properties;
 
        /* Find which optional psy-properties are available */
-       if (!fuel_gauge->get_property(fuel_gauge,
+       fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge);
+       if (!fuel_gauge) {
+               dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n",
+                       desc->psy_fuel_gauge);
+               return -ENODEV;
+       }
+       if (!power_supply_get_property(fuel_gauge,
                                          POWER_SUPPLY_PROP_CHARGE_NOW, &val)) {
-               cm->charger_psy.properties[cm->charger_psy.num_properties] =
+               cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] =
                                POWER_SUPPLY_PROP_CHARGE_NOW;
-               cm->charger_psy.num_properties++;
+               cm->charger_psy_desc.num_properties++;
        }
-       if (!fuel_gauge->get_property(fuel_gauge,
+       if (!power_supply_get_property(fuel_gauge,
                                          POWER_SUPPLY_PROP_CURRENT_NOW,
                                          &val)) {
-               cm->charger_psy.properties[cm->charger_psy.num_properties] =
+               cm->charger_psy_desc.properties[cm->charger_psy_desc.num_properties] =
                                POWER_SUPPLY_PROP_CURRENT_NOW;
-               cm->charger_psy.num_properties++;
+               cm->charger_psy_desc.num_properties++;
        }
 
        ret = cm_init_thermal_data(cm, fuel_gauge);
@@ -1737,14 +1764,16 @@ static int charger_manager_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "Failed to initialize thermal data\n");
                cm->desc->measure_battery_temp = false;
        }
+       power_supply_put(fuel_gauge);
 
        INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk);
 
-       ret = power_supply_register(NULL, &cm->charger_psy);
-       if (ret) {
+       cm->charger_psy = power_supply_register(NULL, &cm->charger_psy_desc,
+                                               &psy_cfg);
+       if (IS_ERR(cm->charger_psy)) {
                dev_err(&pdev->dev, "Cannot register charger-manager with name \"%s\"\n",
-                       cm->charger_psy.name);
-               return ret;
+                       cm->charger_psy_desc.name);
+               return PTR_ERR(cm->charger_psy);
        }
 
        /* Register extcon device for charger cable */
@@ -1790,7 +1819,7 @@ err_reg_sysfs:
                struct charger_regulator *charger;
 
                charger = &desc->charger_regulators[i];
-               sysfs_remove_group(&cm->charger_psy.dev->kobj,
+               sysfs_remove_group(&cm->charger_psy->dev.kobj,
                                &charger->attr_g);
        }
 err_reg_extcon:
@@ -1808,7 +1837,7 @@ err_reg_extcon:
                regulator_put(desc->charger_regulators[i].consumer);
        }
 
-       power_supply_unregister(&cm->charger_psy);
+       power_supply_unregister(cm->charger_psy);
 
        return ret;
 }
@@ -1840,7 +1869,7 @@ static int charger_manager_remove(struct platform_device *pdev)
        for (i = 0 ; i < desc->num_charger_regulators ; i++)
                regulator_put(desc->charger_regulators[i].consumer);
 
-       power_supply_unregister(&cm->charger_psy);
+       power_supply_unregister(cm->charger_psy);
 
        try_charger_enable(cm, false);
 
@@ -1999,7 +2028,7 @@ static bool find_power_supply(struct charger_manager *cm,
        bool found = false;
 
        for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
-               if (!strcmp(psy->name, cm->desc->psy_charger_stat[i])) {
+               if (!strcmp(psy->desc->name, cm->desc->psy_charger_stat[i])) {
                        found = true;
                        break;
                }
index 594e4dbc2d51030df093e021df20f9d3a3352aca..2da9ed8ccbb5391f50c7137866b3fad5669dd2d7 100644 (file)
@@ -30,7 +30,7 @@ static int wakeup_enabled;
 
 struct collie_bat {
        int status;
-       struct power_supply psy;
+       struct power_supply *psy;
        int full_chrg;
 
        struct mutex work_lock; /* protects data */
@@ -98,7 +98,7 @@ static int collie_bat_get_property(struct power_supply *psy,
                            union power_supply_propval *val)
 {
        int ret = 0;
-       struct collie_bat *bat = container_of(psy, struct collie_bat, psy);
+       struct collie_bat *bat = power_supply_get_drvdata(psy);
 
        if (bat->is_present && !bat->is_present(bat)
                        && psp != POWER_SUPPLY_PROP_PRESENT) {
@@ -155,14 +155,14 @@ static irqreturn_t collie_bat_gpio_isr(int irq, void *data)
 static void collie_bat_update(struct collie_bat *bat)
 {
        int old;
-       struct power_supply *psy = &bat->psy;
+       struct power_supply *psy = bat->psy;
 
        mutex_lock(&bat->work_lock);
 
        old = bat->status;
 
        if (bat->is_present && !bat->is_present(bat)) {
-               printk(KERN_NOTICE "%s not present\n", psy->name);
+               printk(KERN_NOTICE "%s not present\n", psy->desc->name);
                bat->status = POWER_SUPPLY_STATUS_UNKNOWN;
                bat->full_chrg = -1;
        } else if (power_supply_am_i_supplied(psy)) {
@@ -220,18 +220,20 @@ static enum power_supply_property collie_bat_bu_props[] = {
        POWER_SUPPLY_PROP_PRESENT,
 };
 
+static const struct power_supply_desc collie_bat_main_desc = {
+       .name           = "main-battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .properties     = collie_bat_main_props,
+       .num_properties = ARRAY_SIZE(collie_bat_main_props),
+       .get_property   = collie_bat_get_property,
+       .external_power_changed = collie_bat_external_power_changed,
+       .use_for_apm    = 1,
+};
+
 static struct collie_bat collie_bat_main = {
        .status = POWER_SUPPLY_STATUS_DISCHARGING,
        .full_chrg = -1,
-       .psy = {
-               .name           = "main-battery",
-               .type           = POWER_SUPPLY_TYPE_BATTERY,
-               .properties     = collie_bat_main_props,
-               .num_properties = ARRAY_SIZE(collie_bat_main_props),
-               .get_property   = collie_bat_get_property,
-               .external_power_changed = collie_bat_external_power_changed,
-               .use_for_apm    = 1,
-       },
+       .psy = NULL,
 
        .gpio_full = COLLIE_GPIO_CO,
        .gpio_charge_on = COLLIE_GPIO_CHARGE_ON,
@@ -249,18 +251,19 @@ static struct collie_bat collie_bat_main = {
        .adc_temp_divider = 10000,
 };
 
+static const struct power_supply_desc collie_bat_bu_desc = {
+       .name           = "backup-battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .properties     = collie_bat_bu_props,
+       .num_properties = ARRAY_SIZE(collie_bat_bu_props),
+       .get_property   = collie_bat_get_property,
+       .external_power_changed = collie_bat_external_power_changed,
+};
+
 static struct collie_bat collie_bat_bu = {
        .status = POWER_SUPPLY_STATUS_UNKNOWN,
        .full_chrg = -1,
-
-       .psy = {
-               .name           = "backup-battery",
-               .type           = POWER_SUPPLY_TYPE_BATTERY,
-               .properties     = collie_bat_bu_props,
-               .num_properties = ARRAY_SIZE(collie_bat_bu_props),
-               .get_property   = collie_bat_get_property,
-               .external_power_changed = collie_bat_external_power_changed,
-       },
+       .psy = NULL,
 
        .gpio_full = -1,
        .gpio_charge_on = -1,
@@ -319,6 +322,7 @@ static int collie_bat_resume(struct ucb1x00_dev *dev)
 static int collie_bat_probe(struct ucb1x00_dev *dev)
 {
        int ret;
+       struct power_supply_config psy_main_cfg = {}, psy_bu_cfg = {};
 
        if (!machine_is_collie())
                return -ENODEV;
@@ -334,12 +338,23 @@ static int collie_bat_probe(struct ucb1x00_dev *dev)
 
        INIT_WORK(&bat_work, collie_bat_work);
 
-       ret = power_supply_register(&dev->ucb->dev, &collie_bat_main.psy);
-       if (ret)
+       psy_main_cfg.drv_data = &collie_bat_main;
+       collie_bat_main.psy = power_supply_register(&dev->ucb->dev,
+                                                   &collie_bat_main_desc,
+                                                   &psy_main_cfg);
+       if (IS_ERR(collie_bat_main.psy)) {
+               ret = PTR_ERR(collie_bat_main.psy);
                goto err_psy_reg_main;
-       ret = power_supply_register(&dev->ucb->dev, &collie_bat_bu.psy);
-       if (ret)
+       }
+
+       psy_main_cfg.drv_data = &collie_bat_bu;
+       collie_bat_bu.psy = power_supply_register(&dev->ucb->dev,
+                                                 &collie_bat_bu_desc,
+                                                 &psy_bu_cfg);
+       if (IS_ERR(collie_bat_bu.psy)) {
+               ret = PTR_ERR(collie_bat_bu.psy);
                goto err_psy_reg_bu;
+       }
 
        ret = request_irq(gpio_to_irq(COLLIE_GPIO_CO),
                                collie_bat_gpio_isr,
@@ -354,9 +369,9 @@ static int collie_bat_probe(struct ucb1x00_dev *dev)
        return 0;
 
 err_irq:
-       power_supply_unregister(&collie_bat_bu.psy);
+       power_supply_unregister(collie_bat_bu.psy);
 err_psy_reg_bu:
-       power_supply_unregister(&collie_bat_main.psy);
+       power_supply_unregister(collie_bat_main.psy);
 err_psy_reg_main:
 
        /* see comment in collie_bat_remove */
@@ -369,8 +384,8 @@ static void collie_bat_remove(struct ucb1x00_dev *dev)
 {
        free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main);
 
-       power_supply_unregister(&collie_bat_bu.psy);
-       power_supply_unregister(&collie_bat_main.psy);
+       power_supply_unregister(collie_bat_bu.psy);
+       power_supply_unregister(collie_bat_main.psy);
 
        /*
         * Now cancel the bat_work.  We won't get any more schedules,
index 78cd5d66144b8861fde99aaf070d0b0e2c04794f..5ca0f4d90792d0c49be2f7225d6174744d867a82 100644 (file)
@@ -89,7 +89,8 @@ struct da9030_battery_thresholds {
 };
 
 struct da9030_charger {
-       struct power_supply psy;
+       struct power_supply *psy;
+       struct power_supply_desc psy_desc;
 
        struct device *master;
 
@@ -245,7 +246,7 @@ static void da9030_set_charge(struct da9030_charger *charger, int on)
 
        da903x_write(charger->master, DA9030_CHARGE_CONTROL, val);
 
-       power_supply_changed(&charger->psy);
+       power_supply_changed(charger->psy);
 }
 
 static void da9030_charger_check_state(struct da9030_charger *charger)
@@ -341,8 +342,7 @@ static int da9030_battery_get_property(struct power_supply *psy,
                                   enum power_supply_property psp,
                                   union power_supply_propval *val)
 {
-       struct da9030_charger *charger;
-       charger = container_of(psy, struct da9030_charger, psy);
+       struct da9030_charger *charger = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
@@ -447,16 +447,16 @@ static void da9030_battery_convert_thresholds(struct da9030_charger *charger,
 
 static void da9030_battery_setup_psy(struct da9030_charger *charger)
 {
-       struct power_supply *psy = &charger->psy;
+       struct power_supply_desc *psy_desc = &charger->psy_desc;
        struct power_supply_info *info = charger->battery_info;
 
-       psy->name = info->name;
-       psy->use_for_apm = info->use_for_apm;
-       psy->type = POWER_SUPPLY_TYPE_BATTERY;
-       psy->get_property = da9030_battery_get_property;
+       psy_desc->name = info->name;
+       psy_desc->use_for_apm = info->use_for_apm;
+       psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
+       psy_desc->get_property = da9030_battery_get_property;
 
-       psy->properties = da9030_battery_props;
-       psy->num_properties = ARRAY_SIZE(da9030_battery_props);
+       psy_desc->properties = da9030_battery_props;
+       psy_desc->num_properties = ARRAY_SIZE(da9030_battery_props);
 };
 
 static int da9030_battery_charger_init(struct da9030_charger *charger)
@@ -494,6 +494,7 @@ static int da9030_battery_charger_init(struct da9030_charger *charger)
 static int da9030_battery_probe(struct platform_device *pdev)
 {
        struct da9030_charger *charger;
+       struct power_supply_config psy_cfg = {};
        struct da9030_battery_info *pdata = pdev->dev.platform_data;
        int ret;
 
@@ -541,9 +542,13 @@ static int da9030_battery_probe(struct platform_device *pdev)
                goto err_notifier;
 
        da9030_battery_setup_psy(charger);
-       ret = power_supply_register(&pdev->dev, &charger->psy);
-       if (ret)
+       psy_cfg.drv_data = charger;
+       charger->psy = power_supply_register(&pdev->dev, &charger->psy_desc,
+                                            &psy_cfg);
+       if (IS_ERR(charger->psy)) {
+               ret = PTR_ERR(charger->psy);
                goto err_ps_register;
+       }
 
        charger->debug_file = da9030_bat_create_debugfs(charger);
        platform_set_drvdata(pdev, charger);
@@ -571,7 +576,7 @@ static int da9030_battery_remove(struct platform_device *dev)
                                   DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT);
        cancel_delayed_work_sync(&charger->work);
        da9030_set_charge(charger, 0);
-       power_supply_unregister(&charger->psy);
+       power_supply_unregister(charger->psy);
 
        return 0;
 }
index d17250f745c29abd1560686b74de688c049c9b9c..830ec46fe7d02380cd20e62c75c16653f79b3962 100644 (file)
@@ -169,7 +169,7 @@ static u32 const vc_tbl[3][68][2] = {
 
 struct da9052_battery {
        struct da9052 *da9052;
-       struct power_supply psy;
+       struct power_supply *psy;
        struct notifier_block nb;
        int charger_type;
        int status;
@@ -452,7 +452,7 @@ static irqreturn_t da9052_bat_irq(int irq, void *data)
 
        if (irq == DA9052_IRQ_CHGEND || irq == DA9052_IRQ_DCIN ||
            irq == DA9052_IRQ_VBUS || irq == DA9052_IRQ_TBAT) {
-               power_supply_changed(&bat->psy);
+               power_supply_changed(bat->psy);
        }
 
        return IRQ_HANDLED;
@@ -499,8 +499,7 @@ static int da9052_bat_get_property(struct power_supply *psy,
 {
        int ret;
        int illegal;
-       struct da9052_battery *bat = container_of(psy, struct da9052_battery,
-                                                 psy);
+       struct da9052_battery *bat = power_supply_get_drvdata(psy);
 
        ret = da9052_bat_check_presence(bat, &illegal);
        if (ret < 0)
@@ -561,7 +560,7 @@ static enum power_supply_property da9052_bat_props[] = {
        POWER_SUPPLY_PROP_TECHNOLOGY,
 };
 
-static struct power_supply template_battery = {
+static struct power_supply_desc psy_desc = {
        .name           = "da9052-bat",
        .type           = POWER_SUPPLY_TYPE_BATTERY,
        .properties     = da9052_bat_props,
@@ -591,6 +590,7 @@ static s32 da9052_bat_probe(struct platform_device *pdev)
 {
        struct da9052_pdata *pdata;
        struct da9052_battery *bat;
+       struct power_supply_config psy_cfg = {};
        int ret;
        int i;
 
@@ -599,8 +599,9 @@ static s32 da9052_bat_probe(struct platform_device *pdev)
        if (!bat)
                return -ENOMEM;
 
+       psy_cfg.drv_data = bat;
+
        bat->da9052 = dev_get_drvdata(pdev->dev.parent);
-       bat->psy = template_battery;
        bat->charger_type = DA9052_NOCHARGER;
        bat->status = POWER_SUPPLY_STATUS_UNKNOWN;
        bat->health = POWER_SUPPLY_HEALTH_UNKNOWN;
@@ -608,9 +609,9 @@ static s32 da9052_bat_probe(struct platform_device *pdev)
 
        pdata = bat->da9052->dev->platform_data;
        if (pdata != NULL && pdata->use_for_apm)
-               bat->psy.use_for_apm = pdata->use_for_apm;
+               psy_desc.use_for_apm = pdata->use_for_apm;
        else
-               bat->psy.use_for_apm = 1;
+               psy_desc.use_for_apm = 1;
 
        for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) {
                ret = da9052_request_irq(bat->da9052,
@@ -625,9 +626,11 @@ static s32 da9052_bat_probe(struct platform_device *pdev)
                }
        }
 
-       ret = power_supply_register(&pdev->dev, &bat->psy);
-        if (ret)
+       bat->psy = power_supply_register(&pdev->dev, &psy_desc, &psy_cfg);
+       if (IS_ERR(bat->psy)) {
+               ret = PTR_ERR(bat->psy);
                goto err;
+       }
 
        platform_set_drvdata(pdev, bat);
        return 0;
@@ -646,7 +649,7 @@ static int da9052_bat_remove(struct platform_device *pdev)
        for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++)
                da9052_free_irq(bat->da9052, da9052_bat_irq_bits[i], bat);
 
-       power_supply_unregister(&bat->psy);
+       power_supply_unregister(bat->psy);
 
        return 0;
 }
diff --git a/drivers/power/da9150-charger.c b/drivers/power/da9150-charger.c
new file mode 100644 (file)
index 0000000..6009981
--- /dev/null
@@ -0,0 +1,694 @@
+/*
+ * DA9150 Charger Driver
+ *
+ * Copyright (c) 2014 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/interrupt.h>
+#include <linux/power_supply.h>
+#include <linux/notifier.h>
+#include <linux/usb/phy.h>
+#include <linux/iio/consumer.h>
+#include <linux/mfd/da9150/core.h>
+#include <linux/mfd/da9150/registers.h>
+
+/* Private data */
+struct da9150_charger {
+       struct da9150 *da9150;
+       struct device *dev;
+
+       struct power_supply *usb;
+       struct power_supply *battery;
+       struct power_supply *supply_online;
+
+       struct usb_phy *usb_phy;
+       struct notifier_block otg_nb;
+       struct work_struct otg_work;
+       unsigned long usb_event;
+
+       struct iio_channel *ibus_chan;
+       struct iio_channel *vbus_chan;
+       struct iio_channel *tjunc_chan;
+       struct iio_channel *vbat_chan;
+};
+
+static inline int da9150_charger_supply_online(struct da9150_charger *charger,
+                                              struct power_supply *psy,
+                                              union power_supply_propval *val)
+{
+       val->intval = (psy == charger->supply_online) ? 1 : 0;
+
+       return 0;
+}
+
+/* Charger Properties */
+static int da9150_charger_vbus_voltage_now(struct da9150_charger *charger,
+                                          union power_supply_propval *val)
+{
+       int v_val, ret;
+
+       /* Read processed value - mV units */
+       ret = iio_read_channel_processed(charger->vbus_chan, &v_val);
+       if (ret < 0)
+               return ret;
+
+       /* Convert voltage to expected uV units */
+       val->intval = v_val * 1000;
+
+       return 0;
+}
+
+static int da9150_charger_ibus_current_avg(struct da9150_charger *charger,
+                                          union power_supply_propval *val)
+{
+       int i_val, ret;
+
+       /* Read processed value - mA units */
+       ret = iio_read_channel_processed(charger->ibus_chan, &i_val);
+       if (ret < 0)
+               return ret;
+
+       /* Convert current to expected uA units */
+       val->intval = i_val * 1000;
+
+       return 0;
+}
+
+static int da9150_charger_tjunc_temp(struct da9150_charger *charger,
+                                    union power_supply_propval *val)
+{
+       int t_val, ret;
+
+       /* Read processed value - 0.001 degrees C units */
+       ret = iio_read_channel_processed(charger->tjunc_chan, &t_val);
+       if (ret < 0)
+               return ret;
+
+       /* Convert temp to expect 0.1 degrees C units */
+       val->intval = t_val / 100;
+
+       return 0;
+}
+
+static enum power_supply_property da9150_charger_props[] = {
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_CURRENT_AVG,
+       POWER_SUPPLY_PROP_TEMP,
+};
+
+static int da9150_charger_get_prop(struct power_supply *psy,
+                                  enum power_supply_property psp,
+                                  union power_supply_propval *val)
+{
+       struct da9150_charger *charger = dev_get_drvdata(psy->dev.parent);
+       int ret;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               ret = da9150_charger_supply_online(charger, psy, val);
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               ret = da9150_charger_vbus_voltage_now(charger, val);
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_AVG:
+               ret = da9150_charger_ibus_current_avg(charger, val);
+               break;
+       case POWER_SUPPLY_PROP_TEMP:
+               ret = da9150_charger_tjunc_temp(charger, val);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+/* Battery Properties */
+static int da9150_charger_battery_status(struct da9150_charger *charger,
+                                        union power_supply_propval *val)
+{
+       u8 reg;
+
+       /* Check to see if battery is discharging */
+       reg = da9150_reg_read(charger->da9150, DA9150_STATUS_H);
+
+       if (((reg & DA9150_VBUS_STAT_MASK) == DA9150_VBUS_STAT_OFF) ||
+           ((reg & DA9150_VBUS_STAT_MASK) == DA9150_VBUS_STAT_WAIT)) {
+               val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+
+               return 0;
+       }
+
+       reg = da9150_reg_read(charger->da9150, DA9150_STATUS_J);
+
+       /* Now check for other states */
+       switch (reg & DA9150_CHG_STAT_MASK) {
+       case DA9150_CHG_STAT_ACT:
+       case DA9150_CHG_STAT_PRE:
+       case DA9150_CHG_STAT_CC:
+       case DA9150_CHG_STAT_CV:
+               val->intval = POWER_SUPPLY_STATUS_CHARGING;
+               break;
+       case DA9150_CHG_STAT_OFF:
+       case DA9150_CHG_STAT_SUSP:
+       case DA9150_CHG_STAT_TEMP:
+       case DA9150_CHG_STAT_TIME:
+       case DA9150_CHG_STAT_BAT:
+               val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               break;
+       case DA9150_CHG_STAT_FULL:
+               val->intval = POWER_SUPPLY_STATUS_FULL;
+               break;
+       default:
+               val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+               break;
+       }
+
+       return 0;
+}
+
+static int da9150_charger_battery_health(struct da9150_charger *charger,
+                                        union power_supply_propval *val)
+{
+       u8 reg;
+
+       reg = da9150_reg_read(charger->da9150, DA9150_STATUS_J);
+
+       /* Check if temperature limit reached */
+       switch (reg & DA9150_CHG_TEMP_MASK) {
+       case DA9150_CHG_TEMP_UNDER:
+               val->intval = POWER_SUPPLY_HEALTH_COLD;
+               return 0;
+       case DA9150_CHG_TEMP_OVER:
+               val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+               return 0;
+       default:
+               break;
+       }
+
+       /* Check for other health states */
+       switch (reg & DA9150_CHG_STAT_MASK) {
+       case DA9150_CHG_STAT_ACT:
+       case DA9150_CHG_STAT_PRE:
+               val->intval = POWER_SUPPLY_HEALTH_DEAD;
+               break;
+       case DA9150_CHG_STAT_TIME:
+               val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+               break;
+       default:
+               val->intval = POWER_SUPPLY_HEALTH_GOOD;
+               break;
+       }
+
+       return 0;
+}
+
+static int da9150_charger_battery_present(struct da9150_charger *charger,
+                                         union power_supply_propval *val)
+{
+       u8 reg;
+
+       /* Check if battery present or removed */
+       reg = da9150_reg_read(charger->da9150, DA9150_STATUS_J);
+       if ((reg & DA9150_CHG_STAT_MASK) == DA9150_CHG_STAT_BAT)
+               val->intval = 0;
+       else
+               val->intval = 1;
+
+       return 0;
+}
+
+static int da9150_charger_battery_charge_type(struct da9150_charger *charger,
+                                             union power_supply_propval *val)
+{
+       u8 reg;
+
+       reg = da9150_reg_read(charger->da9150, DA9150_STATUS_J);
+
+       switch (reg & DA9150_CHG_STAT_MASK) {
+       case DA9150_CHG_STAT_CC:
+               val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+               break;
+       case DA9150_CHG_STAT_ACT:
+       case DA9150_CHG_STAT_PRE:
+       case DA9150_CHG_STAT_CV:
+               val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+               break;
+       default:
+               val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+               break;
+       }
+
+       return 0;
+}
+
+static int da9150_charger_battery_voltage_min(struct da9150_charger *charger,
+                                             union power_supply_propval *val)
+{
+       u8 reg;
+
+       reg = da9150_reg_read(charger->da9150, DA9150_PPR_CHGCTRL_C);
+
+       /* Value starts at 2500 mV, 50 mV increments, presented in uV */
+       val->intval = ((reg & DA9150_CHG_VFAULT_MASK) * 50000) + 2500000;
+
+       return 0;
+}
+
+static int da9150_charger_battery_voltage_now(struct da9150_charger *charger,
+                                             union power_supply_propval *val)
+{
+       int v_val, ret;
+
+       /* Read processed value - mV units */
+       ret = iio_read_channel_processed(charger->vbat_chan, &v_val);
+       if (ret < 0)
+               return ret;
+
+       val->intval = v_val * 1000;
+
+       return 0;
+}
+
+static int da9150_charger_battery_current_max(struct da9150_charger *charger,
+                                             union power_supply_propval *val)
+{
+       int reg;
+
+       reg = da9150_reg_read(charger->da9150, DA9150_PPR_CHGCTRL_D);
+
+       /* 25mA increments */
+       val->intval = reg * 25000;
+
+       return 0;
+}
+
+static int da9150_charger_battery_voltage_max(struct da9150_charger *charger,
+                                             union power_supply_propval *val)
+{
+       u8 reg;
+
+       reg = da9150_reg_read(charger->da9150, DA9150_PPR_CHGCTRL_B);
+
+       /* Value starts at 3650 mV, 25 mV increments, presented in uV */
+       val->intval = ((reg & DA9150_CHG_VBAT_MASK) * 25000) + 3650000;
+       return 0;
+}
+
+static enum power_supply_property da9150_charger_bat_props[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_CHARGE_TYPE,
+       POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+       POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
+};
+
+static int da9150_charger_battery_get_prop(struct power_supply *psy,
+                                          enum power_supply_property psp,
+                                          union power_supply_propval *val)
+{
+       struct da9150_charger *charger = dev_get_drvdata(psy->dev.parent);
+       int ret;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               ret = da9150_charger_battery_status(charger, val);
+               break;
+       case POWER_SUPPLY_PROP_ONLINE:
+               ret = da9150_charger_supply_online(charger, psy, val);
+               break;
+       case POWER_SUPPLY_PROP_HEALTH:
+               ret = da9150_charger_battery_health(charger, val);
+               break;
+       case POWER_SUPPLY_PROP_PRESENT:
+               ret = da9150_charger_battery_present(charger, val);
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_TYPE:
+               ret = da9150_charger_battery_charge_type(charger, val);
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+               ret = da9150_charger_battery_voltage_min(charger, val);
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               ret = da9150_charger_battery_voltage_now(charger, val);
+               break;
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+               ret = da9150_charger_battery_current_max(charger, val);
+               break;
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
+               ret = da9150_charger_battery_voltage_max(charger, val);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static irqreturn_t da9150_charger_chg_irq(int irq, void *data)
+{
+       struct da9150_charger *charger = data;
+
+       power_supply_changed(charger->battery);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t da9150_charger_tjunc_irq(int irq, void *data)
+{
+       struct da9150_charger *charger = data;
+
+       /* Nothing we can really do except report this. */
+       dev_crit(charger->dev, "TJunc over temperature!!!\n");
+       power_supply_changed(charger->usb);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t da9150_charger_vfault_irq(int irq, void *data)
+{
+       struct da9150_charger *charger = data;
+
+       /* Nothing we can really do except report this. */
+       dev_crit(charger->dev, "VSYS under voltage!!!\n");
+       power_supply_changed(charger->usb);
+       power_supply_changed(charger->battery);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t da9150_charger_vbus_irq(int irq, void *data)
+{
+       struct da9150_charger *charger = data;
+       u8 reg;
+
+       reg = da9150_reg_read(charger->da9150, DA9150_STATUS_H);
+
+       /* Charger plugged in or battery only */
+       switch (reg & DA9150_VBUS_STAT_MASK) {
+       case DA9150_VBUS_STAT_OFF:
+       case DA9150_VBUS_STAT_WAIT:
+               charger->supply_online = charger->battery;
+               break;
+       case DA9150_VBUS_STAT_CHG:
+               charger->supply_online = charger->usb;
+               break;
+       default:
+               dev_warn(charger->dev, "Unknown VBUS state - reg = 0x%x\n",
+                        reg);
+               charger->supply_online = NULL;
+               break;
+       }
+
+       power_supply_changed(charger->usb);
+       power_supply_changed(charger->battery);
+
+       return IRQ_HANDLED;
+}
+
+static void da9150_charger_otg_work(struct work_struct *data)
+{
+       struct da9150_charger *charger =
+               container_of(data, struct da9150_charger, otg_work);
+
+       switch (charger->usb_event) {
+       case USB_EVENT_ID:
+               /* Enable OTG Boost */
+               da9150_set_bits(charger->da9150, DA9150_PPR_BKCTRL_A,
+                               DA9150_VBUS_MODE_MASK, DA9150_VBUS_MODE_OTG);
+               break;
+       case USB_EVENT_NONE:
+               /* Revert to charge mode */
+               power_supply_changed(charger->usb);
+               power_supply_changed(charger->battery);
+               da9150_set_bits(charger->da9150, DA9150_PPR_BKCTRL_A,
+                               DA9150_VBUS_MODE_MASK, DA9150_VBUS_MODE_CHG);
+               break;
+       }
+}
+
+static int da9150_charger_otg_ncb(struct notifier_block *nb, unsigned long val,
+                                 void *priv)
+{
+       struct da9150_charger *charger =
+               container_of(nb, struct da9150_charger, otg_nb);
+
+       dev_dbg(charger->dev, "DA9150 OTG notify %lu\n", val);
+
+       charger->usb_event = val;
+       schedule_work(&charger->otg_work);
+
+       return NOTIFY_OK;
+}
+
+static int da9150_charger_register_irq(struct platform_device *pdev,
+                                      irq_handler_t handler,
+                                      const char *irq_name)
+{
+       struct device *dev = &pdev->dev;
+       struct da9150_charger *charger = platform_get_drvdata(pdev);
+       int irq, ret;
+
+       irq = platform_get_irq_byname(pdev, irq_name);
+       if (irq < 0) {
+               dev_err(dev, "Failed to get IRQ CHG_STATUS: %d\n", irq);
+               return irq;
+       }
+
+       ret = request_threaded_irq(irq, NULL, handler, IRQF_ONESHOT, irq_name,
+                                  charger);
+       if (ret)
+               dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
+
+       return ret;
+}
+
+static void da9150_charger_unregister_irq(struct platform_device *pdev,
+                                         const char *irq_name)
+{
+       struct device *dev = &pdev->dev;
+       struct da9150_charger *charger = platform_get_drvdata(pdev);
+       int irq;
+
+       irq = platform_get_irq_byname(pdev, irq_name);
+       if (irq < 0) {
+               dev_err(dev, "Failed to get IRQ CHG_STATUS: %d\n", irq);
+               return;
+       }
+
+       free_irq(irq, charger);
+}
+
+static const struct power_supply_desc usb_desc = {
+       .name           = "da9150-usb",
+       .type           = POWER_SUPPLY_TYPE_USB,
+       .properties     = da9150_charger_props,
+       .num_properties = ARRAY_SIZE(da9150_charger_props),
+       .get_property   = da9150_charger_get_prop,
+};
+
+static const struct power_supply_desc battery_desc = {
+       .name           = "da9150-battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .properties     = da9150_charger_bat_props,
+       .num_properties = ARRAY_SIZE(da9150_charger_bat_props),
+       .get_property   = da9150_charger_battery_get_prop,
+};
+
+static int da9150_charger_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct da9150 *da9150 = dev_get_drvdata(dev->parent);
+       struct da9150_charger *charger;
+       u8 reg;
+       int ret;
+
+       charger = devm_kzalloc(dev, sizeof(struct da9150_charger), GFP_KERNEL);
+       if (!charger)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, charger);
+       charger->da9150 = da9150;
+       charger->dev = dev;
+
+       /* Acquire ADC channels */
+       charger->ibus_chan = iio_channel_get(dev, "CHAN_IBUS");
+       if (IS_ERR(charger->ibus_chan)) {
+               ret = PTR_ERR(charger->ibus_chan);
+               goto ibus_chan_fail;
+       }
+
+       charger->vbus_chan = iio_channel_get(dev, "CHAN_VBUS");
+       if (IS_ERR(charger->vbus_chan)) {
+               ret = PTR_ERR(charger->vbus_chan);
+               goto vbus_chan_fail;
+       }
+
+       charger->tjunc_chan = iio_channel_get(dev, "CHAN_TJUNC");
+       if (IS_ERR(charger->tjunc_chan)) {
+               ret = PTR_ERR(charger->tjunc_chan);
+               goto tjunc_chan_fail;
+       }
+
+       charger->vbat_chan = iio_channel_get(dev, "CHAN_VBAT");
+       if (IS_ERR(charger->vbat_chan)) {
+               ret = PTR_ERR(charger->vbat_chan);
+               goto vbat_chan_fail;
+       }
+
+       /* Register power supplies */
+       charger->usb = power_supply_register(dev, &usb_desc, NULL);
+       if (IS_ERR(charger->usb)) {
+               ret = PTR_ERR(charger->usb);
+               goto usb_fail;
+       }
+
+       charger->battery = power_supply_register(dev, &battery_desc, NULL);
+       if (IS_ERR(charger->battery)) {
+               ret = PTR_ERR(charger->battery);
+               goto battery_fail;
+       }
+
+       /* Get initial online supply */
+       reg = da9150_reg_read(da9150, DA9150_STATUS_H);
+
+       switch (reg & DA9150_VBUS_STAT_MASK) {
+       case DA9150_VBUS_STAT_OFF:
+       case DA9150_VBUS_STAT_WAIT:
+               charger->supply_online = charger->battery;
+               break;
+       case DA9150_VBUS_STAT_CHG:
+               charger->supply_online = charger->usb;
+               break;
+       default:
+               dev_warn(dev, "Unknown VBUS state - reg = 0x%x\n", reg);
+               charger->supply_online = NULL;
+               break;
+       }
+
+       /* Setup OTG reporting & configuration */
+       charger->usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+       if (!IS_ERR_OR_NULL(charger->usb_phy)) {
+               INIT_WORK(&charger->otg_work, da9150_charger_otg_work);
+               charger->otg_nb.notifier_call = da9150_charger_otg_ncb;
+               usb_register_notifier(charger->usb_phy, &charger->otg_nb);
+       }
+
+       /* Register IRQs */
+       ret = da9150_charger_register_irq(pdev, da9150_charger_chg_irq,
+                                         "CHG_STATUS");
+       if (ret < 0)
+               goto chg_irq_fail;
+
+       ret = da9150_charger_register_irq(pdev, da9150_charger_tjunc_irq,
+                                         "CHG_TJUNC");
+       if (ret < 0)
+               goto tjunc_irq_fail;
+
+       ret = da9150_charger_register_irq(pdev, da9150_charger_vfault_irq,
+                                         "CHG_VFAULT");
+       if (ret < 0)
+               goto vfault_irq_fail;
+
+       ret = da9150_charger_register_irq(pdev, da9150_charger_vbus_irq,
+                                         "CHG_VBUS");
+       if (ret < 0)
+               goto vbus_irq_fail;
+
+       return 0;
+
+
+vbus_irq_fail:
+       da9150_charger_unregister_irq(pdev, "CHG_VFAULT");
+vfault_irq_fail:
+       da9150_charger_unregister_irq(pdev, "CHG_TJUNC");
+tjunc_irq_fail:
+       da9150_charger_unregister_irq(pdev, "CHG_STATUS");
+chg_irq_fail:
+       if (!IS_ERR_OR_NULL(charger->usb_phy))
+               usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
+battery_fail:
+       power_supply_unregister(charger->usb);
+
+usb_fail:
+       iio_channel_release(charger->vbat_chan);
+
+vbat_chan_fail:
+       iio_channel_release(charger->tjunc_chan);
+
+tjunc_chan_fail:
+       iio_channel_release(charger->vbus_chan);
+
+vbus_chan_fail:
+       iio_channel_release(charger->ibus_chan);
+
+ibus_chan_fail:
+       return ret;
+}
+
+static int da9150_charger_remove(struct platform_device *pdev)
+{
+       struct da9150_charger *charger = platform_get_drvdata(pdev);
+       int irq;
+
+       /* Make sure IRQs are released before unregistering power supplies */
+       irq = platform_get_irq_byname(pdev, "CHG_VBUS");
+       free_irq(irq, charger);
+
+       irq = platform_get_irq_byname(pdev, "CHG_VFAULT");
+       free_irq(irq, charger);
+
+       irq = platform_get_irq_byname(pdev, "CHG_TJUNC");
+       free_irq(irq, charger);
+
+       irq = platform_get_irq_byname(pdev, "CHG_STATUS");
+       free_irq(irq, charger);
+
+       if (!IS_ERR_OR_NULL(charger->usb_phy))
+               usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
+
+       power_supply_unregister(charger->battery);
+       power_supply_unregister(charger->usb);
+
+       /* Release ADC channels */
+       iio_channel_release(charger->ibus_chan);
+       iio_channel_release(charger->vbus_chan);
+       iio_channel_release(charger->tjunc_chan);
+       iio_channel_release(charger->vbat_chan);
+
+       return 0;
+}
+
+static struct platform_driver da9150_charger_driver = {
+       .driver = {
+               .name = "da9150-charger",
+       },
+       .probe = da9150_charger_probe,
+       .remove = da9150_charger_remove,
+};
+
+module_platform_driver(da9150_charger_driver);
+
+MODULE_DESCRIPTION("Charger Driver for DA9150");
+MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
+MODULE_LICENSE("GPL");
index 85b4e6eca0b1984cc39ea0a3e0d6fbd5614ab543..80f73ccb77ab707b56614e44c66d84d60c143b0e 100644 (file)
@@ -53,7 +53,8 @@ struct ds2760_device_info {
        int charge_status;              /* POWER_SUPPLY_STATUS_* */
 
        int full_counter;
-       struct power_supply bat;
+       struct power_supply *bat;
+       struct power_supply_desc bat_desc;
        struct device *w1_dev;
        struct workqueue_struct *monitor_wqueue;
        struct delayed_work monitor_work;
@@ -254,7 +255,7 @@ static void ds2760_battery_update_status(struct ds2760_device_info *di)
        if (di->charge_status == POWER_SUPPLY_STATUS_UNKNOWN)
                di->full_counter = 0;
 
-       if (power_supply_am_i_supplied(&di->bat)) {
+       if (power_supply_am_i_supplied(di->bat)) {
                if (di->current_uA > 10000) {
                        di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
                        di->full_counter = 0;
@@ -287,7 +288,7 @@ static void ds2760_battery_update_status(struct ds2760_device_info *di)
        }
 
        if (di->charge_status != old_charge_status)
-               power_supply_changed(&di->bat);
+               power_supply_changed(di->bat);
 }
 
 static void ds2760_battery_write_status(struct ds2760_device_info *di,
@@ -346,12 +347,9 @@ static void ds2760_battery_work(struct work_struct *work)
        queue_delayed_work(di->monitor_wqueue, &di->monitor_work, interval);
 }
 
-#define to_ds2760_device_info(x) container_of((x), struct ds2760_device_info, \
-                                             bat);
-
 static void ds2760_battery_external_power_changed(struct power_supply *psy)
 {
-       struct ds2760_device_info *di = to_ds2760_device_info(psy);
+       struct ds2760_device_info *di = power_supply_get_drvdata(psy);
 
        dev_dbg(di->dev, "%s\n", __func__);
 
@@ -377,7 +375,7 @@ static void ds2760_battery_set_charged_work(struct work_struct *work)
         * that error.
         */
 
-       if (!power_supply_am_i_supplied(&di->bat))
+       if (!power_supply_am_i_supplied(di->bat))
                return;
 
        bias = (signed char) di->current_raw +
@@ -396,7 +394,7 @@ static void ds2760_battery_set_charged_work(struct work_struct *work)
 
 static void ds2760_battery_set_charged(struct power_supply *psy)
 {
-       struct ds2760_device_info *di = to_ds2760_device_info(psy);
+       struct ds2760_device_info *di = power_supply_get_drvdata(psy);
 
        /* postpone the actual work by 20 secs. This is for debouncing GPIO
         * signals and to let the current value settle. See AN4188. */
@@ -407,7 +405,7 @@ static int ds2760_battery_get_property(struct power_supply *psy,
                                       enum power_supply_property psp,
                                       union power_supply_propval *val)
 {
-       struct ds2760_device_info *di = to_ds2760_device_info(psy);
+       struct ds2760_device_info *di = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
@@ -458,7 +456,7 @@ static int ds2760_battery_set_property(struct power_supply *psy,
                                       enum power_supply_property psp,
                                       const union power_supply_propval *val)
 {
-       struct ds2760_device_info *di = to_ds2760_device_info(psy);
+       struct ds2760_device_info *di = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_CHARGE_FULL:
@@ -508,6 +506,7 @@ static enum power_supply_property ds2760_battery_props[] = {
 
 static int ds2760_battery_probe(struct platform_device *pdev)
 {
+       struct power_supply_config psy_cfg = {};
        char status;
        int retval = 0;
        struct ds2760_device_info *di;
@@ -520,20 +519,22 @@ static int ds2760_battery_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, di);
 
-       di->dev                 = &pdev->dev;
-       di->w1_dev              = pdev->dev.parent;
-       di->bat.name            = dev_name(&pdev->dev);
-       di->bat.type            = POWER_SUPPLY_TYPE_BATTERY;
-       di->bat.properties      = ds2760_battery_props;
-       di->bat.num_properties  = ARRAY_SIZE(ds2760_battery_props);
-       di->bat.get_property    = ds2760_battery_get_property;
-       di->bat.set_property    = ds2760_battery_set_property;
-       di->bat.property_is_writeable =
+       di->dev                         = &pdev->dev;
+       di->w1_dev                      = pdev->dev.parent;
+       di->bat_desc.name               = dev_name(&pdev->dev);
+       di->bat_desc.type               = POWER_SUPPLY_TYPE_BATTERY;
+       di->bat_desc.properties         = ds2760_battery_props;
+       di->bat_desc.num_properties     = ARRAY_SIZE(ds2760_battery_props);
+       di->bat_desc.get_property       = ds2760_battery_get_property;
+       di->bat_desc.set_property       = ds2760_battery_set_property;
+       di->bat_desc.property_is_writeable =
                                  ds2760_battery_property_is_writeable;
-       di->bat.set_charged     = ds2760_battery_set_charged;
-       di->bat.external_power_changed =
+       di->bat_desc.set_charged        = ds2760_battery_set_charged;
+       di->bat_desc.external_power_changed =
                                  ds2760_battery_external_power_changed;
 
+       psy_cfg.drv_data                = di;
+
        di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
 
        /* enable sleep mode feature */
@@ -555,9 +556,10 @@ static int ds2760_battery_probe(struct platform_device *pdev)
        if (current_accum)
                ds2760_battery_set_current_accum(di, current_accum);
 
-       retval = power_supply_register(&pdev->dev, &di->bat);
-       if (retval) {
+       di->bat = power_supply_register(&pdev->dev, &di->bat_desc, &psy_cfg);
+       if (IS_ERR(di->bat)) {
                dev_err(di->dev, "failed to register battery\n");
+               retval = PTR_ERR(di->bat);
                goto batt_failed;
        }
 
@@ -574,7 +576,7 @@ static int ds2760_battery_probe(struct platform_device *pdev)
        goto success;
 
 workqueue_failed:
-       power_supply_unregister(&di->bat);
+       power_supply_unregister(di->bat);
 batt_failed:
 di_alloc_failed:
 success:
@@ -588,7 +590,7 @@ static int ds2760_battery_remove(struct platform_device *pdev)
        cancel_delayed_work_sync(&di->monitor_work);
        cancel_delayed_work_sync(&di->set_charged_work);
        destroy_workqueue(di->monitor_wqueue);
-       power_supply_unregister(&di->bat);
+       power_supply_unregister(di->bat);
 
        return 0;
 }
@@ -610,7 +612,7 @@ static int ds2760_battery_resume(struct platform_device *pdev)
        struct ds2760_device_info *di = platform_get_drvdata(pdev);
 
        di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
-       power_supply_changed(&di->bat);
+       power_supply_changed(di->bat);
 
        mod_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ);
 
index 9f418fa879e5027141414444e619d64db0a73d64..a7a0427343f3ef563fd9d6264165e27edf1e0ef2 100644 (file)
@@ -37,7 +37,8 @@
 
 struct ds2780_device_info {
        struct device *dev;
-       struct power_supply bat;
+       struct power_supply *bat;
+       struct power_supply_desc bat_desc;
        struct device *w1_dev;
 };
 
@@ -52,7 +53,7 @@ static const char manufacturer[] = "Maxim/Dallas";
 static inline struct ds2780_device_info *
 to_ds2780_device_info(struct power_supply *psy)
 {
-       return container_of(psy, struct ds2780_device_info, bat);
+       return power_supply_get_drvdata(psy);
 }
 
 static inline struct power_supply *to_power_supply(struct device *dev)
@@ -757,6 +758,7 @@ static const struct attribute_group ds2780_attr_group = {
 
 static int ds2780_battery_probe(struct platform_device *pdev)
 {
+       struct power_supply_config psy_cfg = {};
        int ret = 0;
        struct ds2780_device_info *dev_info;
 
@@ -770,25 +772,29 @@ static int ds2780_battery_probe(struct platform_device *pdev)
 
        dev_info->dev                   = &pdev->dev;
        dev_info->w1_dev                = pdev->dev.parent;
-       dev_info->bat.name              = dev_name(&pdev->dev);
-       dev_info->bat.type              = POWER_SUPPLY_TYPE_BATTERY;
-       dev_info->bat.properties        = ds2780_battery_props;
-       dev_info->bat.num_properties    = ARRAY_SIZE(ds2780_battery_props);
-       dev_info->bat.get_property      = ds2780_battery_get_property;
+       dev_info->bat_desc.name         = dev_name(&pdev->dev);
+       dev_info->bat_desc.type         = POWER_SUPPLY_TYPE_BATTERY;
+       dev_info->bat_desc.properties   = ds2780_battery_props;
+       dev_info->bat_desc.num_properties = ARRAY_SIZE(ds2780_battery_props);
+       dev_info->bat_desc.get_property = ds2780_battery_get_property;
 
-       ret = power_supply_register(&pdev->dev, &dev_info->bat);
-       if (ret) {
+       psy_cfg.drv_data                = dev_info;
+
+       dev_info->bat = power_supply_register(&pdev->dev, &dev_info->bat_desc,
+                                             &psy_cfg);
+       if (IS_ERR(dev_info->bat)) {
                dev_err(dev_info->dev, "failed to register battery\n");
+               ret = PTR_ERR(dev_info->bat);
                goto fail;
        }
 
-       ret = sysfs_create_group(&dev_info->bat.dev->kobj, &ds2780_attr_group);
+       ret = sysfs_create_group(&dev_info->bat->dev.kobj, &ds2780_attr_group);
        if (ret) {
                dev_err(dev_info->dev, "failed to create sysfs group\n");
                goto fail_unregister;
        }
 
-       ret = sysfs_create_bin_file(&dev_info->bat.dev->kobj,
+       ret = sysfs_create_bin_file(&dev_info->bat->dev.kobj,
                                        &ds2780_param_eeprom_bin_attr);
        if (ret) {
                dev_err(dev_info->dev,
@@ -796,7 +802,7 @@ static int ds2780_battery_probe(struct platform_device *pdev)
                goto fail_remove_group;
        }
 
-       ret = sysfs_create_bin_file(&dev_info->bat.dev->kobj,
+       ret = sysfs_create_bin_file(&dev_info->bat->dev.kobj,
                                        &ds2780_user_eeprom_bin_attr);
        if (ret) {
                dev_err(dev_info->dev,
@@ -807,12 +813,12 @@ static int ds2780_battery_probe(struct platform_device *pdev)
        return 0;
 
 fail_remove_bin_file:
-       sysfs_remove_bin_file(&dev_info->bat.dev->kobj,
+       sysfs_remove_bin_file(&dev_info->bat->dev.kobj,
                                &ds2780_param_eeprom_bin_attr);
 fail_remove_group:
-       sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group);
+       sysfs_remove_group(&dev_info->bat->dev.kobj, &ds2780_attr_group);
 fail_unregister:
-       power_supply_unregister(&dev_info->bat);
+       power_supply_unregister(dev_info->bat);
 fail:
        return ret;
 }
@@ -821,10 +827,13 @@ static int ds2780_battery_remove(struct platform_device *pdev)
 {
        struct ds2780_device_info *dev_info = platform_get_drvdata(pdev);
 
-       /* remove attributes */
-       sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group);
+       /*
+        * Remove attributes before unregistering power supply
+        * because 'bat' will be freed on power_supply_unregister() call.
+        */
+       sysfs_remove_group(&dev_info->bat->dev.kobj, &ds2780_attr_group);
 
-       power_supply_unregister(&dev_info->bat);
+       power_supply_unregister(dev_info->bat);
 
        return 0;
 }
index 0a5acc6fc6f0c75aabc36c548bff7b6d640a4582..56d583dae9087c89742bf25e4d0a61364d4f5885 100644 (file)
@@ -35,7 +35,8 @@
 
 struct ds2781_device_info {
        struct device *dev;
-       struct power_supply bat;
+       struct power_supply *bat;
+       struct power_supply_desc bat_desc;
        struct device *w1_dev;
 };
 
@@ -50,7 +51,7 @@ static const char manufacturer[] = "Maxim/Dallas";
 static inline struct ds2781_device_info *
 to_ds2781_device_info(struct power_supply *psy)
 {
-       return container_of(psy, struct ds2781_device_info, bat);
+       return power_supply_get_drvdata(psy);
 }
 
 static inline struct power_supply *to_power_supply(struct device *dev)
@@ -328,7 +329,7 @@ static int ds2781_get_status(struct ds2781_device_info *dev_info, int *status)
        if (ret < 0)
                return ret;
 
-       if (power_supply_am_i_supplied(&dev_info->bat)) {
+       if (power_supply_am_i_supplied(dev_info->bat)) {
                if (capacity == 100)
                        *status = POWER_SUPPLY_STATUS_FULL;
                else if (current_uA > 50000)
@@ -752,6 +753,7 @@ static const struct attribute_group ds2781_attr_group = {
 
 static int ds2781_battery_probe(struct platform_device *pdev)
 {
+       struct power_supply_config psy_cfg = {};
        int ret = 0;
        struct ds2781_device_info *dev_info;
 
@@ -763,25 +765,29 @@ static int ds2781_battery_probe(struct platform_device *pdev)
 
        dev_info->dev                   = &pdev->dev;
        dev_info->w1_dev                = pdev->dev.parent;
-       dev_info->bat.name              = dev_name(&pdev->dev);
-       dev_info->bat.type              = POWER_SUPPLY_TYPE_BATTERY;
-       dev_info->bat.properties        = ds2781_battery_props;
-       dev_info->bat.num_properties    = ARRAY_SIZE(ds2781_battery_props);
-       dev_info->bat.get_property      = ds2781_battery_get_property;
+       dev_info->bat_desc.name         = dev_name(&pdev->dev);
+       dev_info->bat_desc.type         = POWER_SUPPLY_TYPE_BATTERY;
+       dev_info->bat_desc.properties   = ds2781_battery_props;
+       dev_info->bat_desc.num_properties = ARRAY_SIZE(ds2781_battery_props);
+       dev_info->bat_desc.get_property = ds2781_battery_get_property;
 
-       ret = power_supply_register(&pdev->dev, &dev_info->bat);
-       if (ret) {
+       psy_cfg.drv_data                = dev_info;
+
+       dev_info->bat = power_supply_register(&pdev->dev, &dev_info->bat_desc,
+                                               &psy_cfg);
+       if (IS_ERR(dev_info->bat)) {
                dev_err(dev_info->dev, "failed to register battery\n");
+               ret = PTR_ERR(dev_info->bat);
                goto fail;
        }
 
-       ret = sysfs_create_group(&dev_info->bat.dev->kobj, &ds2781_attr_group);
+       ret = sysfs_create_group(&dev_info->bat->dev.kobj, &ds2781_attr_group);
        if (ret) {
                dev_err(dev_info->dev, "failed to create sysfs group\n");
                goto fail_unregister;
        }
 
-       ret = sysfs_create_bin_file(&dev_info->bat.dev->kobj,
+       ret = sysfs_create_bin_file(&dev_info->bat->dev.kobj,
                                        &ds2781_param_eeprom_bin_attr);
        if (ret) {
                dev_err(dev_info->dev,
@@ -789,7 +795,7 @@ static int ds2781_battery_probe(struct platform_device *pdev)
                goto fail_remove_group;
        }
 
-       ret = sysfs_create_bin_file(&dev_info->bat.dev->kobj,
+       ret = sysfs_create_bin_file(&dev_info->bat->dev.kobj,
                                        &ds2781_user_eeprom_bin_attr);
        if (ret) {
                dev_err(dev_info->dev,
@@ -800,12 +806,12 @@ static int ds2781_battery_probe(struct platform_device *pdev)
        return 0;
 
 fail_remove_bin_file:
-       sysfs_remove_bin_file(&dev_info->bat.dev->kobj,
+       sysfs_remove_bin_file(&dev_info->bat->dev.kobj,
                                &ds2781_param_eeprom_bin_attr);
 fail_remove_group:
-       sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2781_attr_group);
+       sysfs_remove_group(&dev_info->bat->dev.kobj, &ds2781_attr_group);
 fail_unregister:
-       power_supply_unregister(&dev_info->bat);
+       power_supply_unregister(dev_info->bat);
 fail:
        return ret;
 }
@@ -814,10 +820,13 @@ static int ds2781_battery_remove(struct platform_device *pdev)
 {
        struct ds2781_device_info *dev_info = platform_get_drvdata(pdev);
 
-       /* remove attributes */
-       sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2781_attr_group);
+       /*
+        * Remove attributes before unregistering power supply
+        * because 'bat' will be freed on power_supply_unregister() call.
+        */
+       sysfs_remove_group(&dev_info->bat->dev.kobj, &ds2781_attr_group);
 
-       power_supply_unregister(&dev_info->bat);
+       power_supply_unregister(dev_info->bat);
 
        return 0;
 }
index 39694883d3bf6c7ea108018c409a232d7495acef..ed4d756d21e4bd7f660e7b5d007b68829c6e95bb 100644 (file)
@@ -53,11 +53,12 @@ struct ds278x_battery_ops {
        int (*get_battery_capacity)(struct ds278x_info *info, int *capacity);
 };
 
-#define to_ds278x_info(x) container_of(x, struct ds278x_info, battery)
+#define to_ds278x_info(x) power_supply_get_drvdata(x)
 
 struct ds278x_info {
        struct i2c_client       *client;
-       struct power_supply     battery;
+       struct power_supply     *battery;
+       struct power_supply_desc        battery_desc;
        struct ds278x_battery_ops  *ops;
        struct delayed_work     bat_work;
        int                     id;
@@ -285,7 +286,7 @@ static void ds278x_bat_update(struct ds278x_info *info)
        ds278x_get_status(info, &info->status);
 
        if ((old_status != info->status) || (old_capacity != info->capacity))
-               power_supply_changed(&info->battery);
+               power_supply_changed(info->battery);
 }
 
 static void ds278x_bat_work(struct work_struct *work)
@@ -306,7 +307,7 @@ static enum power_supply_property ds278x_battery_props[] = {
        POWER_SUPPLY_PROP_TEMP,
 };
 
-static void ds278x_power_supply_init(struct power_supply *battery)
+static void ds278x_power_supply_init(struct power_supply_desc *battery)
 {
        battery->type                   = POWER_SUPPLY_TYPE_BATTERY;
        battery->properties             = ds278x_battery_props;
@@ -319,8 +320,8 @@ static int ds278x_battery_remove(struct i2c_client *client)
 {
        struct ds278x_info *info = i2c_get_clientdata(client);
 
-       power_supply_unregister(&info->battery);
-       kfree(info->battery.name);
+       power_supply_unregister(info->battery);
+       kfree(info->battery_desc.name);
 
        mutex_lock(&battery_lock);
        idr_remove(&battery_id, info->id);
@@ -377,6 +378,7 @@ static int ds278x_battery_probe(struct i2c_client *client,
                                const struct i2c_device_id *id)
 {
        struct ds278x_platform_data *pdata = client->dev.platform_data;
+       struct power_supply_config psy_cfg = {};
        struct ds278x_info *info;
        int ret;
        int num;
@@ -404,8 +406,9 @@ static int ds278x_battery_probe(struct i2c_client *client,
                goto fail_info;
        }
 
-       info->battery.name = kasprintf(GFP_KERNEL, "%s-%d", client->name, num);
-       if (!info->battery.name) {
+       info->battery_desc.name = kasprintf(GFP_KERNEL, "%s-%d",
+                                           client->name, num);
+       if (!info->battery_desc.name) {
                ret = -ENOMEM;
                goto fail_name;
        }
@@ -417,16 +420,19 @@ static int ds278x_battery_probe(struct i2c_client *client,
        info->client = client;
        info->id = num;
        info->ops  = &ds278x_ops[id->driver_data];
-       ds278x_power_supply_init(&info->battery);
+       ds278x_power_supply_init(&info->battery_desc);
+       psy_cfg.drv_data = info;
 
        info->capacity = 100;
        info->status = POWER_SUPPLY_STATUS_FULL;
 
        INIT_DELAYED_WORK(&info->bat_work, ds278x_bat_work);
 
-       ret = power_supply_register(&client->dev, &info->battery);
-       if (ret) {
+       info->battery = power_supply_register(&client->dev,
+                                             &info->battery_desc, &psy_cfg);
+       if (IS_ERR(info->battery)) {
                dev_err(&client->dev, "failed to register battery\n");
+               ret = PTR_ERR(info->battery);
                goto fail_register;
        } else {
                schedule_delayed_work(&info->bat_work, DS278x_DELAY);
@@ -435,7 +441,7 @@ static int ds278x_battery_probe(struct i2c_client *client,
        return 0;
 
 fail_register:
-       kfree(info->battery.name);
+       kfree(info->battery_desc.name);
 fail_name:
        kfree(info);
 fail_info:
index d72733e4f93aa68a8fe12b24b2bc2d9e6bc9bd32..fedc5818fab7b74b96b5da2f81b77d4a992c6baf 100644 (file)
@@ -44,7 +44,8 @@ static const char *const gab_chan_name[] = {
 };
 
 struct gab {
-       struct power_supply     psy;
+       struct power_supply             *psy;
+       struct power_supply_desc        psy_desc;
        struct iio_channel      *channel[GAB_MAX_CHAN_TYPE];
        struct gab_platform_data        *pdata;
        struct delayed_work bat_work;
@@ -55,7 +56,7 @@ struct gab {
 
 static struct gab *to_generic_bat(struct power_supply *psy)
 {
-       return container_of(psy, struct gab, psy);
+       return power_supply_get_drvdata(psy);
 }
 
 static void gab_ext_power_changed(struct power_supply *psy)
@@ -151,7 +152,7 @@ static int gab_get_property(struct power_supply *psy,
 
        adc_bat = to_generic_bat(psy);
        if (!adc_bat) {
-               dev_err(psy->dev, "no battery infos ?!\n");
+               dev_err(&psy->dev, "no battery infos ?!\n");
                return -EINVAL;
        }
        pdata = adc_bat->pdata;
@@ -159,7 +160,7 @@ static int gab_get_property(struct power_supply *psy,
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
-               gab_get_status(adc_bat);
+               val->intval = gab_get_status(adc_bat);
                break;
        case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN:
                val->intval = 0;
@@ -210,7 +211,7 @@ static void gab_work(struct work_struct *work)
        pdata = adc_bat->pdata;
        status = adc_bat->status;
 
-       is_plugged = power_supply_am_i_supplied(&adc_bat->psy);
+       is_plugged = power_supply_am_i_supplied(adc_bat->psy);
        adc_bat->cable_plugged = is_plugged;
 
        if (!is_plugged)
@@ -221,7 +222,7 @@ static void gab_work(struct work_struct *work)
                adc_bat->status = POWER_SUPPLY_STATUS_CHARGING;
 
        if (status != adc_bat->status)
-               power_supply_changed(&adc_bat->psy);
+               power_supply_changed(adc_bat->psy);
 }
 
 static irqreturn_t gab_charged(int irq, void *dev_id)
@@ -239,7 +240,8 @@ static irqreturn_t gab_charged(int irq, void *dev_id)
 static int gab_probe(struct platform_device *pdev)
 {
        struct gab *adc_bat;
-       struct power_supply *psy;
+       struct power_supply_desc *psy_desc;
+       struct power_supply_config psy_cfg = {};
        struct gab_platform_data *pdata = pdev->dev.platform_data;
        enum power_supply_property *properties;
        int ret = 0;
@@ -252,32 +254,34 @@ static int gab_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       psy = &adc_bat->psy;
-       psy->name = pdata->battery_info.name;
+       psy_cfg.drv_data = adc_bat;
+       psy_desc = &adc_bat->psy_desc;
+       psy_desc->name = pdata->battery_info.name;
 
        /* bootup default values for the battery */
        adc_bat->cable_plugged = false;
        adc_bat->status = POWER_SUPPLY_STATUS_DISCHARGING;
-       psy->type = POWER_SUPPLY_TYPE_BATTERY;
-       psy->get_property = gab_get_property;
-       psy->external_power_changed = gab_ext_power_changed;
+       psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
+       psy_desc->get_property = gab_get_property;
+       psy_desc->external_power_changed = gab_ext_power_changed;
        adc_bat->pdata = pdata;
 
        /*
         * copying the static properties and allocating extra memory for holding
         * the extra configurable properties received from platform data.
         */
-       psy->properties = kcalloc(ARRAY_SIZE(gab_props) +
+       psy_desc->properties = kcalloc(ARRAY_SIZE(gab_props) +
                                        ARRAY_SIZE(gab_chan_name),
-                                       sizeof(*psy->properties), GFP_KERNEL);
-       if (!psy->properties) {
+                                       sizeof(*psy_desc->properties),
+                                       GFP_KERNEL);
+       if (!psy_desc->properties) {
                ret = -ENOMEM;
                goto first_mem_fail;
        }
 
-       memcpy(psy->properties, gab_props, sizeof(gab_props));
+       memcpy(psy_desc->properties, gab_props, sizeof(gab_props));
        properties = (enum power_supply_property *)
-                               ((char *)psy->properties + sizeof(gab_props));
+                       ((char *)psy_desc->properties + sizeof(gab_props));
 
        /*
         * getting channel from iio and copying the battery properties
@@ -291,7 +295,7 @@ static int gab_probe(struct platform_device *pdev)
                        adc_bat->channel[chan] = NULL;
                } else {
                        /* copying properties for supported channels only */
-                       memcpy(properties + sizeof(*(psy->properties)) * index,
+                       memcpy(properties + sizeof(*(psy_desc->properties)) * index,
                                        &gab_dyn_props[chan],
                                        sizeof(gab_dyn_props[chan]));
                        index++;
@@ -310,11 +314,13 @@ static int gab_probe(struct platform_device *pdev)
         * as come channels may be not be supported by the device.So
         * we need to take care of that.
         */
-       psy->num_properties = ARRAY_SIZE(gab_props) + index;
+       psy_desc->num_properties = ARRAY_SIZE(gab_props) + index;
 
-       ret = power_supply_register(&pdev->dev, psy);
-       if (ret)
+       adc_bat->psy = power_supply_register(&pdev->dev, psy_desc, &psy_cfg);
+       if (IS_ERR(adc_bat->psy)) {
+               ret = PTR_ERR(adc_bat->psy);
                goto err_reg_fail;
+       }
 
        INIT_DELAYED_WORK(&adc_bat->bat_work, gab_work);
 
@@ -342,14 +348,14 @@ static int gab_probe(struct platform_device *pdev)
 err_gpio:
        gpio_free(pdata->gpio_charge_finished);
 gpio_req_fail:
-       power_supply_unregister(psy);
+       power_supply_unregister(adc_bat->psy);
 err_reg_fail:
        for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) {
                if (adc_bat->channel[chan])
                        iio_channel_release(adc_bat->channel[chan]);
        }
 second_mem_fail:
-       kfree(psy->properties);
+       kfree(psy_desc->properties);
 first_mem_fail:
        return ret;
 }
@@ -360,7 +366,7 @@ static int gab_remove(struct platform_device *pdev)
        struct gab *adc_bat = platform_get_drvdata(pdev);
        struct gab_platform_data *pdata = adc_bat->pdata;
 
-       power_supply_unregister(&adc_bat->psy);
+       power_supply_unregister(adc_bat->psy);
 
        if (gpio_is_valid(pdata->gpio_charge_finished)) {
                free_irq(gpio_to_irq(pdata->gpio_charge_finished), adc_bat);
@@ -372,7 +378,7 @@ static int gab_remove(struct platform_device *pdev)
                        iio_channel_release(adc_bat->channel[chan]);
        }
 
-       kfree(adc_bat->psy.properties);
+       kfree(adc_bat->psy_desc.properties);
        cancel_delayed_work(&adc_bat->bat_work);
        return 0;
 }
index 29eba88a296367ffe10c1886462cb77822f05ac8..a50bb988c69a0bbd49cbf455ee3304c066599bbb 100644 (file)
@@ -30,8 +30,8 @@ struct goldfish_battery_data {
        int irq;
        spinlock_t lock;
 
-       struct power_supply battery;
-       struct power_supply ac;
+       struct power_supply *battery;
+       struct power_supply *ac;
 };
 
 #define GOLDFISH_BATTERY_READ(data, addr) \
@@ -67,8 +67,7 @@ static int goldfish_ac_get_property(struct power_supply *psy,
                        enum power_supply_property psp,
                        union power_supply_propval *val)
 {
-       struct goldfish_battery_data *data = container_of(psy,
-               struct goldfish_battery_data, ac);
+       struct goldfish_battery_data *data = power_supply_get_drvdata(psy);
        int ret = 0;
 
        switch (psp) {
@@ -86,8 +85,7 @@ static int goldfish_battery_get_property(struct power_supply *psy,
                                 enum power_supply_property psp,
                                 union power_supply_propval *val)
 {
-       struct goldfish_battery_data *data = container_of(psy,
-               struct goldfish_battery_data, battery);
+       struct goldfish_battery_data *data = power_supply_get_drvdata(psy);
        int ret = 0;
 
        switch (psp) {
@@ -139,20 +137,36 @@ static irqreturn_t goldfish_battery_interrupt(int irq, void *dev_id)
        status &= BATTERY_INT_MASK;
 
        if (status & BATTERY_STATUS_CHANGED)
-               power_supply_changed(&data->battery);
+               power_supply_changed(data->battery);
        if (status & AC_STATUS_CHANGED)
-               power_supply_changed(&data->ac);
+               power_supply_changed(data->ac);
 
        spin_unlock_irqrestore(&data->lock, irq_flags);
        return status ? IRQ_HANDLED : IRQ_NONE;
 }
 
+static const struct power_supply_desc battery_desc = {
+       .properties     = goldfish_battery_props,
+       .num_properties = ARRAY_SIZE(goldfish_battery_props),
+       .get_property   = goldfish_battery_get_property,
+       .name           = "battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+};
+
+static const struct power_supply_desc ac_desc = {
+       .properties     = goldfish_ac_props,
+       .num_properties = ARRAY_SIZE(goldfish_ac_props),
+       .get_property   = goldfish_ac_get_property,
+       .name           = "ac",
+       .type           = POWER_SUPPLY_TYPE_MAINS,
+};
 
 static int goldfish_battery_probe(struct platform_device *pdev)
 {
        int ret;
        struct resource *r;
        struct goldfish_battery_data *data;
+       struct power_supply_config psy_cfg = {};
 
        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
        if (data == NULL)
@@ -160,18 +174,6 @@ static int goldfish_battery_probe(struct platform_device *pdev)
 
        spin_lock_init(&data->lock);
 
-       data->battery.properties = goldfish_battery_props;
-       data->battery.num_properties = ARRAY_SIZE(goldfish_battery_props);
-       data->battery.get_property = goldfish_battery_get_property;
-       data->battery.name = "battery";
-       data->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-
-       data->ac.properties = goldfish_ac_props;
-       data->ac.num_properties = ARRAY_SIZE(goldfish_ac_props);
-       data->ac.get_property = goldfish_ac_get_property;
-       data->ac.name = "ac";
-       data->ac.type = POWER_SUPPLY_TYPE_MAINS;
-
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (r == NULL) {
                dev_err(&pdev->dev, "platform_get_resource failed\n");
@@ -195,14 +197,17 @@ static int goldfish_battery_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       ret = power_supply_register(&pdev->dev, &data->ac);
-       if (ret)
-               return ret;
+       psy_cfg.drv_data = data;
 
-       ret = power_supply_register(&pdev->dev, &data->battery);
-       if (ret) {
-               power_supply_unregister(&data->ac);
-               return ret;
+       data->ac = power_supply_register(&pdev->dev, &ac_desc, &psy_cfg);
+       if (IS_ERR(data->ac))
+               return PTR_ERR(data->ac);
+
+       data->battery = power_supply_register(&pdev->dev, &battery_desc,
+                                               &psy_cfg);
+       if (IS_ERR(data->battery)) {
+               power_supply_unregister(data->ac);
+               return PTR_ERR(data->battery);
        }
 
        platform_set_drvdata(pdev, data);
@@ -216,8 +221,8 @@ static int goldfish_battery_remove(struct platform_device *pdev)
 {
        struct goldfish_battery_data *data = platform_get_drvdata(pdev);
 
-       power_supply_unregister(&data->battery);
-       power_supply_unregister(&data->ac);
+       power_supply_unregister(data->battery);
+       power_supply_unregister(data->ac);
        battery_data = NULL;
        return 0;
 }
index b7424c8501f106d8c6e460c14ca5f946602ad088..c5869b1941acddbe75a1221527238d6641d6daf3 100644 (file)
@@ -32,7 +32,8 @@ struct gpio_charger {
        unsigned int irq;
        bool wakeup_enabled;
 
-       struct power_supply charger;
+       struct power_supply *charger;
+       struct power_supply_desc charger_desc;
 };
 
 static irqreturn_t gpio_charger_irq(int irq, void *devid)
@@ -46,7 +47,7 @@ static irqreturn_t gpio_charger_irq(int irq, void *devid)
 
 static inline struct gpio_charger *psy_to_gpio_charger(struct power_supply *psy)
 {
-       return container_of(psy, struct gpio_charger, charger);
+       return power_supply_get_drvdata(psy);
 }
 
 static int gpio_charger_get_property(struct power_supply *psy,
@@ -127,8 +128,9 @@ struct gpio_charger_platform_data *gpio_charger_parse_dt(struct device *dev)
 static int gpio_charger_probe(struct platform_device *pdev)
 {
        const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data;
+       struct power_supply_config psy_cfg = {};
        struct gpio_charger *gpio_charger;
-       struct power_supply *charger;
+       struct power_supply_desc *charger_desc;
        int ret;
        int irq;
 
@@ -154,16 +156,18 @@ static int gpio_charger_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       charger = &gpio_charger->charger;
+       charger_desc = &gpio_charger->charger_desc;
+
+       charger_desc->name = pdata->name ? pdata->name : "gpio-charger";
+       charger_desc->type = pdata->type;
+       charger_desc->properties = gpio_charger_properties;
+       charger_desc->num_properties = ARRAY_SIZE(gpio_charger_properties);
+       charger_desc->get_property = gpio_charger_get_property;
 
-       charger->name = pdata->name ? pdata->name : "gpio-charger";
-       charger->type = pdata->type;
-       charger->properties = gpio_charger_properties;
-       charger->num_properties = ARRAY_SIZE(gpio_charger_properties);
-       charger->get_property = gpio_charger_get_property;
-       charger->supplied_to = pdata->supplied_to;
-       charger->num_supplicants = pdata->num_supplicants;
-       charger->of_node = pdev->dev.of_node;
+       psy_cfg.supplied_to = pdata->supplied_to;
+       psy_cfg.num_supplicants = pdata->num_supplicants;
+       psy_cfg.of_node = pdev->dev.of_node;
+       psy_cfg.drv_data = gpio_charger;
 
        ret = gpio_request(pdata->gpio, dev_name(&pdev->dev));
        if (ret) {
@@ -178,8 +182,10 @@ static int gpio_charger_probe(struct platform_device *pdev)
 
        gpio_charger->pdata = pdata;
 
-       ret = power_supply_register(&pdev->dev, charger);
-       if (ret < 0) {
+       gpio_charger->charger = power_supply_register(&pdev->dev,
+                                                     charger_desc, &psy_cfg);
+       if (IS_ERR(gpio_charger->charger)) {
+               ret = PTR_ERR(gpio_charger->charger);
                dev_err(&pdev->dev, "Failed to register power supply: %d\n",
                        ret);
                goto err_gpio_free;
@@ -189,7 +195,7 @@ static int gpio_charger_probe(struct platform_device *pdev)
        if (irq > 0) {
                ret = request_any_context_irq(irq, gpio_charger_irq,
                                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                               dev_name(&pdev->dev), charger);
+                               dev_name(&pdev->dev), gpio_charger->charger);
                if (ret < 0)
                        dev_warn(&pdev->dev, "Failed to request irq: %d\n", ret);
                else
@@ -213,9 +219,9 @@ static int gpio_charger_remove(struct platform_device *pdev)
        struct gpio_charger *gpio_charger = platform_get_drvdata(pdev);
 
        if (gpio_charger->irq)
-               free_irq(gpio_charger->irq, &gpio_charger->charger);
+               free_irq(gpio_charger->irq, gpio_charger->charger);
 
-       power_supply_unregister(&gpio_charger->charger);
+       power_supply_unregister(gpio_charger->charger);
 
        gpio_free(gpio_charger->pdata->gpio);
 
@@ -241,7 +247,7 @@ static int gpio_charger_resume(struct device *dev)
 
        if (device_may_wakeup(dev) && gpio_charger->wakeup_enabled)
                disable_irq_wake(gpio_charger->irq);
-       power_supply_changed(&gpio_charger->charger);
+       power_supply_changed(gpio_charger->charger);
 
        return 0;
 }
index de3f39e6fa8e6a47f18174d2bcaface588c23f86..9fa4acc107caf1a7bc37d47f4630e44e2c98d839 100644 (file)
@@ -107,8 +107,8 @@ struct pmic_power_module_info {
        unsigned int batt_prev_charge_full;     /* in mAS */
        unsigned int batt_charge_rate;          /* in units per second */
 
-       struct power_supply usb;
-       struct power_supply batt;
+       struct power_supply *usb;
+       struct power_supply *batt;
        int irq;                                /* GPE_ID or IRQ# */
        struct workqueue_struct *monitor_wqueue;
        struct delayed_work monitor_battery;
@@ -404,8 +404,7 @@ static int pmic_usb_get_property(struct power_supply *psy,
                                enum power_supply_property psp,
                                union power_supply_propval *val)
 {
-       struct pmic_power_module_info *pbi = container_of(psy,
-                               struct pmic_power_module_info, usb);
+       struct pmic_power_module_info *pbi = power_supply_get_drvdata(psy);
 
        /* update pmic_power_module_info members */
        pmic_battery_read_status(pbi);
@@ -444,8 +443,7 @@ static int pmic_battery_get_property(struct power_supply *psy,
                                enum power_supply_property psp,
                                union power_supply_propval *val)
 {
-       struct pmic_power_module_info *pbi = container_of(psy,
-                               struct pmic_power_module_info, batt);
+       struct pmic_power_module_info *pbi = power_supply_get_drvdata(psy);
 
        /* update pmic_power_module_info members */
        pmic_battery_read_status(pbi);
@@ -640,6 +638,25 @@ static void pmic_battery_handle_intrpt(struct work_struct *work)
                        __func__);
 }
 
+/*
+ * Description of power supplies
+ */
+static const struct power_supply_desc pmic_usb_desc = {
+       .name           = "pmic-usb",
+       .type           = POWER_SUPPLY_TYPE_USB,
+       .properties     = pmic_usb_props,
+       .num_properties = ARRAY_SIZE(pmic_usb_props),
+       .get_property   = pmic_usb_get_property,
+};
+
+static const struct power_supply_desc pmic_batt_desc = {
+       .name           = "pmic-batt",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .properties     = pmic_battery_props,
+       .num_properties = ARRAY_SIZE(pmic_battery_props),
+       .get_property   = pmic_battery_get_property,
+};
+
 /**
  * pmic_battery_probe - pmic battery initialize
  * @irq: pmic battery device irq
@@ -653,6 +670,7 @@ static int probe(int irq, struct device *dev)
 {
        int retval = 0;
        struct pmic_power_module_info *pbi;
+       struct power_supply_config psy_cfg = {};
 
        dev_dbg(dev, "pmic-battery: found pmic battery device\n");
 
@@ -666,6 +684,7 @@ static int probe(int irq, struct device *dev)
        pbi->dev = dev;
        pbi->irq = irq;
        dev_set_drvdata(dev, pbi);
+       psy_cfg.drv_data = pbi;
 
        /* initialize all required framework before enabling interrupts */
        INIT_WORK(&pbi->handler, pmic_battery_handle_intrpt);
@@ -687,16 +706,12 @@ static int probe(int irq, struct device *dev)
        }
 
        /* register pmic-batt with power supply subsystem */
-       pbi->batt.name = "pmic-batt";
-       pbi->batt.type = POWER_SUPPLY_TYPE_BATTERY;
-       pbi->batt.properties = pmic_battery_props;
-       pbi->batt.num_properties = ARRAY_SIZE(pmic_battery_props);
-       pbi->batt.get_property = pmic_battery_get_property;
-       retval = power_supply_register(dev, &pbi->batt);
-       if (retval) {
+       pbi->batt = power_supply_register(dev, &pmic_usb_desc, &psy_cfg);
+       if (IS_ERR(pbi->batt)) {
                dev_err(dev,
                        "%s(): failed to register pmic battery device with power supply subsystem\n",
                                __func__);
+               retval = PTR_ERR(pbi->batt);
                goto power_reg_failed;
        }
 
@@ -707,16 +722,12 @@ static int probe(int irq, struct device *dev)
        queue_delayed_work(pbi->monitor_wqueue, &pbi->monitor_battery, HZ * 1);
 
        /* register pmic-usb with power supply subsystem */
-       pbi->usb.name = "pmic-usb";
-       pbi->usb.type = POWER_SUPPLY_TYPE_USB;
-       pbi->usb.properties = pmic_usb_props;
-       pbi->usb.num_properties = ARRAY_SIZE(pmic_usb_props);
-       pbi->usb.get_property = pmic_usb_get_property;
-       retval = power_supply_register(dev, &pbi->usb);
-       if (retval) {
+       pbi->usb = power_supply_register(dev, &pmic_batt_desc, &psy_cfg);
+       if (IS_ERR(pbi->usb)) {
                dev_err(dev,
                        "%s(): failed to register pmic usb device with power supply subsystem\n",
                                __func__);
+               retval = PTR_ERR(pbi->usb);
                goto power_reg_failed_1;
        }
 
@@ -728,7 +739,7 @@ static int probe(int irq, struct device *dev)
        return retval;
 
 power_reg_failed_1:
-       power_supply_unregister(&pbi->batt);
+       power_supply_unregister(pbi->batt);
 power_reg_failed:
        cancel_delayed_work_sync(&pbi->monitor_battery);
 requestirq_failed:
@@ -762,8 +773,8 @@ static int platform_pmic_battery_remove(struct platform_device *pdev)
        cancel_delayed_work_sync(&pbi->monitor_battery);
        destroy_workqueue(pbi->monitor_wqueue);
 
-       power_supply_unregister(&pbi->usb);
-       power_supply_unregister(&pbi->batt);
+       power_supply_unregister(pbi->usb);
+       power_supply_unregister(pbi->batt);
 
        cancel_work_sync(&pbi->handler);
        kfree(pbi);
index 9d694605cdb77f35456dad106425b760266f7927..f03014ea1dc4a4c229d57acacf040002c875ed8b 100644 (file)
@@ -93,7 +93,7 @@ static void micro_battery_work(struct work_struct *work)
 
 static int get_capacity(struct power_supply *b)
 {
-       struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
+       struct micro_battery *mb = dev_get_drvdata(b->dev.parent);
 
        switch (mb->flag & 0x07) {
        case MICRO_BATT_STATUS_HIGH:
@@ -113,7 +113,7 @@ static int get_capacity(struct power_supply *b)
 
 static int get_status(struct power_supply *b)
 {
-       struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
+       struct micro_battery *mb = dev_get_drvdata(b->dev.parent);
 
        if (mb->flag == MICRO_BATT_STATUS_UNKNOWN)
                return POWER_SUPPLY_STATUS_UNKNOWN;
@@ -132,7 +132,7 @@ static int micro_batt_get_property(struct power_supply *b,
                                        enum power_supply_property psp,
                                        union power_supply_propval *val)
 {
-       struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
+       struct micro_battery *mb = dev_get_drvdata(b->dev.parent);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_TECHNOLOGY:
@@ -180,7 +180,7 @@ static int micro_ac_get_property(struct power_supply *b,
                                 enum power_supply_property psp,
                                 union power_supply_propval *val)
 {
-       struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
+       struct micro_battery *mb = dev_get_drvdata(b->dev.parent);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_ONLINE:
@@ -202,7 +202,7 @@ static enum power_supply_property micro_batt_power_props[] = {
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
 };
 
-static struct power_supply micro_batt_power = {
+static const struct power_supply_desc micro_batt_power_desc = {
        .name                   = "main-battery",
        .type                   = POWER_SUPPLY_TYPE_BATTERY,
        .properties             = micro_batt_power_props,
@@ -215,7 +215,7 @@ static enum power_supply_property micro_ac_power_props[] = {
        POWER_SUPPLY_PROP_ONLINE,
 };
 
-static struct power_supply micro_ac_power = {
+static const struct power_supply_desc micro_ac_power_desc = {
        .name                   = "ac",
        .type                   = POWER_SUPPLY_TYPE_MAINS,
        .properties             = micro_ac_power_props,
@@ -223,9 +223,12 @@ static struct power_supply micro_ac_power = {
        .get_property           = micro_ac_get_property,
 };
 
+static struct power_supply *micro_batt_power, *micro_ac_power;
+
 static int micro_batt_probe(struct platform_device *pdev)
 {
        struct micro_battery *mb;
+       int ret;
 
        mb = devm_kzalloc(&pdev->dev, sizeof(*mb), GFP_KERNEL);
        if (!mb)
@@ -233,14 +236,36 @@ static int micro_batt_probe(struct platform_device *pdev)
 
        mb->micro = dev_get_drvdata(pdev->dev.parent);
        mb->wq = create_singlethread_workqueue("ipaq-battery-wq");
+       if (!mb->wq)
+               return -ENOMEM;
+
        INIT_DELAYED_WORK(&mb->update, micro_battery_work);
        platform_set_drvdata(pdev, mb);
        queue_delayed_work(mb->wq, &mb->update, 1);
-       power_supply_register(&pdev->dev, &micro_batt_power);
-       power_supply_register(&pdev->dev, &micro_ac_power);
+
+       micro_batt_power = power_supply_register(&pdev->dev,
+                                                &micro_batt_power_desc, NULL);
+       if (IS_ERR(micro_batt_power)) {
+               ret = PTR_ERR(micro_batt_power);
+               goto batt_err;
+       }
+
+       micro_ac_power = power_supply_register(&pdev->dev,
+                                              &micro_ac_power_desc, NULL);
+       if (IS_ERR(micro_ac_power)) {
+               ret = PTR_ERR(micro_ac_power);
+               goto ac_err;
+       }
 
        dev_info(&pdev->dev, "iPAQ micro battery driver\n");
        return 0;
+
+ac_err:
+       power_supply_unregister(micro_ac_power);
+batt_err:
+       cancel_delayed_work_sync(&mb->update);
+       destroy_workqueue(mb->wq);
+       return ret;
 }
 
 static int micro_batt_remove(struct platform_device *pdev)
@@ -248,9 +273,10 @@ static int micro_batt_remove(struct platform_device *pdev)
 {
        struct micro_battery *mb = platform_get_drvdata(pdev);
 
-       power_supply_unregister(&micro_ac_power);
-       power_supply_unregister(&micro_batt_power);
+       power_supply_unregister(micro_ac_power);
+       power_supply_unregister(micro_batt_power);
        cancel_delayed_work_sync(&mb->update);
+       destroy_workqueue(mb->wq);
 
        return 0;
 }
index 0b4cf9d63291d0e152197c0eeffb1eb128818dd3..f2a7d970388f179be4450fa90e6c567dc037d413 100644 (file)
@@ -57,11 +57,12 @@ static u16 isp170x_id[] = {
 };
 
 struct isp1704_charger {
-       struct device           *dev;
-       struct power_supply     psy;
-       struct usb_phy          *phy;
-       struct notifier_block   nb;
-       struct work_struct      work;
+       struct device                   *dev;
+       struct power_supply             *psy;
+       struct power_supply_desc        psy_desc;
+       struct usb_phy                  *phy;
+       struct notifier_block           nb;
+       struct work_struct              work;
 
        /* properties */
        char                    model[8];
@@ -259,10 +260,10 @@ static void isp1704_charger_work(struct work_struct *data)
 
                        /* detect wall charger */
                        if (isp1704_charger_detect_dcp(isp)) {
-                               isp->psy.type = POWER_SUPPLY_TYPE_USB_DCP;
+                               isp->psy_desc.type = POWER_SUPPLY_TYPE_USB_DCP;
                                isp->current_max = 1800;
                        } else {
-                               isp->psy.type = POWER_SUPPLY_TYPE_USB;
+                               isp->psy_desc.type = POWER_SUPPLY_TYPE_USB;
                                isp->current_max = 500;
                        }
 
@@ -271,7 +272,7 @@ static void isp1704_charger_work(struct work_struct *data)
                                usb_gadget_connect(isp->phy->otg->gadget);
                }
 
-               if (isp->psy.type != POWER_SUPPLY_TYPE_USB_DCP) {
+               if (isp->psy_desc.type != POWER_SUPPLY_TYPE_USB_DCP) {
                        /*
                         * Only 500mA here or high speed chirp
                         * handshaking may break
@@ -280,14 +281,14 @@ static void isp1704_charger_work(struct work_struct *data)
                                isp->current_max = 500;
 
                        if (isp->current_max > 100)
-                               isp->psy.type = POWER_SUPPLY_TYPE_USB_CDP;
+                               isp->psy_desc.type = POWER_SUPPLY_TYPE_USB_CDP;
                }
                break;
        case USB_EVENT_NONE:
                isp->online = false;
                isp->present = 0;
                isp->current_max = 0;
-               isp->psy.type = POWER_SUPPLY_TYPE_USB;
+               isp->psy_desc.type = POWER_SUPPLY_TYPE_USB;
 
                /*
                 * Disable data pullups. We need to prevent the controller from
@@ -306,7 +307,7 @@ static void isp1704_charger_work(struct work_struct *data)
                goto out;
        }
 
-       power_supply_changed(&isp->psy);
+       power_supply_changed(isp->psy);
 out:
        mutex_unlock(&lock);
 }
@@ -326,8 +327,7 @@ static int isp1704_charger_get_property(struct power_supply *psy,
                                enum power_supply_property psp,
                                union power_supply_propval *val)
 {
-       struct isp1704_charger *isp =
-               container_of(psy, struct isp1704_charger, psy);
+       struct isp1704_charger *isp = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_PRESENT:
@@ -403,6 +403,7 @@ static int isp1704_charger_probe(struct platform_device *pdev)
 {
        struct isp1704_charger  *isp;
        int                     ret = -ENODEV;
+       struct power_supply_config psy_cfg = {};
 
        struct isp1704_charger_data *pdata = dev_get_platdata(&pdev->dev);
        struct device_node *np = pdev->dev.of_node;
@@ -454,15 +455,19 @@ static int isp1704_charger_probe(struct platform_device *pdev)
        if (ret < 0)
                goto fail1;
 
-       isp->psy.name           = "isp1704";
-       isp->psy.type           = POWER_SUPPLY_TYPE_USB;
-       isp->psy.properties     = power_props;
-       isp->psy.num_properties = ARRAY_SIZE(power_props);
-       isp->psy.get_property   = isp1704_charger_get_property;
+       isp->psy_desc.name              = "isp1704";
+       isp->psy_desc.type              = POWER_SUPPLY_TYPE_USB;
+       isp->psy_desc.properties        = power_props;
+       isp->psy_desc.num_properties    = ARRAY_SIZE(power_props);
+       isp->psy_desc.get_property      = isp1704_charger_get_property;
 
-       ret = power_supply_register(isp->dev, &isp->psy);
-       if (ret)
+       psy_cfg.drv_data                = isp;
+
+       isp->psy = power_supply_register(isp->dev, &isp->psy_desc, &psy_cfg);
+       if (IS_ERR(isp->psy)) {
+               ret = PTR_ERR(isp->psy);
                goto fail1;
+       }
 
        /*
         * REVISIT: using work in order to allow the usb notifications to be
@@ -498,7 +503,7 @@ static int isp1704_charger_probe(struct platform_device *pdev)
 
        return 0;
 fail2:
-       power_supply_unregister(&isp->psy);
+       power_supply_unregister(isp->psy);
 fail1:
        isp1704_charger_set_power(isp, 0);
 fail0:
@@ -512,7 +517,7 @@ static int isp1704_charger_remove(struct platform_device *pdev)
        struct isp1704_charger *isp = platform_get_drvdata(pdev);
 
        usb_unregister_notifier(isp->phy, &isp->nb);
-       power_supply_unregister(&isp->psy);
+       power_supply_unregister(isp->psy);
        isp1704_charger_set_power(isp, 0);
 
        return 0;
index 9cd391d61819e9d336e1a854239cfbc24f599cd3..abdfc21ec13fc17bf99a2ca15e6ad2fc20ea6f0c 100644 (file)
@@ -46,7 +46,8 @@ struct jz_battery {
 
        struct completion read_completion;
 
-       struct power_supply battery;
+       struct power_supply *battery;
+       struct power_supply_desc battery_desc;
        struct delayed_work work;
 
        struct mutex lock;
@@ -54,7 +55,7 @@ struct jz_battery {
 
 static inline struct jz_battery *psy_to_jz_battery(struct power_supply *psy)
 {
-       return container_of(psy, struct jz_battery, battery);
+       return power_supply_get_drvdata(psy);
 }
 
 static irqreturn_t jz_battery_irq_handler(int irq, void *devid)
@@ -213,7 +214,7 @@ static void jz_battery_update(struct jz_battery *jz_battery)
        }
 
        if (has_changed)
-               power_supply_changed(&jz_battery->battery);
+               power_supply_changed(jz_battery->battery);
 }
 
 static enum power_supply_property jz_battery_properties[] = {
@@ -242,8 +243,9 @@ static int jz_battery_probe(struct platform_device *pdev)
 {
        int ret = 0;
        struct jz_battery_platform_data *pdata = pdev->dev.parent->platform_data;
+       struct power_supply_config psy_cfg = {};
        struct jz_battery *jz_battery;
-       struct power_supply *battery;
+       struct power_supply_desc *battery_desc;
        struct resource *mem;
 
        if (!pdata) {
@@ -271,14 +273,17 @@ static int jz_battery_probe(struct platform_device *pdev)
        if (IS_ERR(jz_battery->base))
                return PTR_ERR(jz_battery->base);
 
-       battery = &jz_battery->battery;
-       battery->name = pdata->info.name;
-       battery->type = POWER_SUPPLY_TYPE_BATTERY;
-       battery->properties     = jz_battery_properties;
-       battery->num_properties = ARRAY_SIZE(jz_battery_properties);
-       battery->get_property = jz_battery_get_property;
-       battery->external_power_changed = jz_battery_external_power_changed;
-       battery->use_for_apm = 1;
+       battery_desc = &jz_battery->battery_desc;
+       battery_desc->name = pdata->info.name;
+       battery_desc->type = POWER_SUPPLY_TYPE_BATTERY;
+       battery_desc->properties        = jz_battery_properties;
+       battery_desc->num_properties    = ARRAY_SIZE(jz_battery_properties);
+       battery_desc->get_property      = jz_battery_get_property;
+       battery_desc->external_power_changed =
+                                       jz_battery_external_power_changed;
+       battery_desc->use_for_apm       = 1;
+
+       psy_cfg.drv_data = jz_battery;
 
        jz_battery->pdata = pdata;
        jz_battery->pdev = pdev;
@@ -330,9 +335,11 @@ static int jz_battery_probe(struct platform_device *pdev)
        else
                jz4740_adc_set_config(pdev->dev.parent, JZ_ADC_CONFIG_BAT_MB, 0);
 
-       ret = power_supply_register(&pdev->dev, &jz_battery->battery);
-       if (ret) {
+       jz_battery->battery = power_supply_register(&pdev->dev, battery_desc,
+                                                       &psy_cfg);
+       if (IS_ERR(jz_battery->battery)) {
                dev_err(&pdev->dev, "power supply battery register failed.\n");
+               ret = PTR_ERR(jz_battery->battery);
                goto err_free_charge_irq;
        }
 
@@ -364,7 +371,7 @@ static int jz_battery_remove(struct platform_device *pdev)
                gpio_free(jz_battery->pdata->gpio_charge);
        }
 
-       power_supply_unregister(&jz_battery->battery);
+       power_supply_unregister(jz_battery->battery);
 
        free_irq(jz_battery->irq, jz_battery);
 
index 32de636dcd732d4f392cff5fd2c8e08bb1125f4a..7e741f1d3cd5e392d8a13445daefc2688d861e7d 100644 (file)
@@ -80,9 +80,9 @@ enum lp8727_die_temp {
 };
 
 struct lp8727_psy {
-       struct power_supply ac;
-       struct power_supply usb;
-       struct power_supply batt;
+       struct power_supply *ac;
+       struct power_supply *usb;
+       struct power_supply *batt;
 };
 
 struct lp8727_chg {
@@ -242,9 +242,9 @@ static void lp8727_delayed_func(struct work_struct *_work)
        lp8727_id_detection(pchg, idno, vbus);
        lp8727_enable_chgdet(pchg);
 
-       power_supply_changed(&pchg->psy->ac);
-       power_supply_changed(&pchg->psy->usb);
-       power_supply_changed(&pchg->psy->batt);
+       power_supply_changed(pchg->psy->ac);
+       power_supply_changed(pchg->psy->usb);
+       power_supply_changed(pchg->psy->batt);
 }
 
 static irqreturn_t lp8727_isr_func(int irq, void *ptr)
@@ -311,12 +311,12 @@ static int lp8727_charger_get_property(struct power_supply *psy,
                                       enum power_supply_property psp,
                                       union power_supply_propval *val)
 {
-       struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
+       struct lp8727_chg *pchg = dev_get_drvdata(psy->dev.parent);
 
        if (psp != POWER_SUPPLY_PROP_ONLINE)
                return -EINVAL;
 
-       val->intval = lp8727_is_charger_attached(psy->name, pchg->devid);
+       val->intval = lp8727_is_charger_attached(psy->desc->name, pchg->devid);
 
        return 0;
 }
@@ -337,14 +337,14 @@ static int lp8727_battery_get_property(struct power_supply *psy,
                                       enum power_supply_property psp,
                                       union power_supply_propval *val)
 {
-       struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
+       struct lp8727_chg *pchg = dev_get_drvdata(psy->dev.parent);
        struct lp8727_platform_data *pdata = pchg->pdata;
        enum lp8727_die_temp temp;
        u8 read;
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
-               if (!lp8727_is_charger_attached(psy->name, pchg->devid)) {
+               if (!lp8727_is_charger_attached(psy->desc->name, pchg->devid)) {
                        val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
                        return 0;
                }
@@ -400,13 +400,13 @@ static int lp8727_battery_get_property(struct power_supply *psy,
 
 static void lp8727_charger_changed(struct power_supply *psy)
 {
-       struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
+       struct lp8727_chg *pchg = dev_get_drvdata(psy->dev.parent);
        u8 eoc_level;
        u8 ichg;
        u8 val;
 
        /* skip if no charger exists */
-       if (!lp8727_is_charger_attached(psy->name, pchg->devid))
+       if (!lp8727_is_charger_attached(psy->desc->name, pchg->devid))
                return;
 
        /* update charging parameters */
@@ -418,8 +418,34 @@ static void lp8727_charger_changed(struct power_supply *psy)
        }
 }
 
+static const struct power_supply_desc lp8727_ac_desc = {
+       .name                   = "ac",
+       .type                   = POWER_SUPPLY_TYPE_MAINS,
+       .properties             = lp8727_charger_prop,
+       .num_properties         = ARRAY_SIZE(lp8727_charger_prop),
+       .get_property           = lp8727_charger_get_property,
+};
+
+static const struct power_supply_desc lp8727_usb_desc = {
+       .name                   = "usb",
+       .type                   = POWER_SUPPLY_TYPE_USB,
+       .properties             = lp8727_charger_prop,
+       .num_properties         = ARRAY_SIZE(lp8727_charger_prop),
+       .get_property           = lp8727_charger_get_property,
+};
+
+static const struct power_supply_desc lp8727_batt_desc = {
+       .name                   = "main_batt",
+       .type                   = POWER_SUPPLY_TYPE_BATTERY,
+       .properties             = lp8727_battery_prop,
+       .num_properties         = ARRAY_SIZE(lp8727_battery_prop),
+       .get_property           = lp8727_battery_get_property,
+       .external_power_changed = lp8727_charger_changed,
+};
+
 static int lp8727_register_psy(struct lp8727_chg *pchg)
 {
+       struct power_supply_config psy_cfg = {}; /* Only for ac and usb */
        struct lp8727_psy *psy;
 
        psy = devm_kzalloc(pchg->dev, sizeof(*psy), GFP_KERNEL);
@@ -428,44 +454,28 @@ static int lp8727_register_psy(struct lp8727_chg *pchg)
 
        pchg->psy = psy;
 
-       psy->ac.name = "ac";
-       psy->ac.type = POWER_SUPPLY_TYPE_MAINS;
-       psy->ac.properties = lp8727_charger_prop;
-       psy->ac.num_properties = ARRAY_SIZE(lp8727_charger_prop);
-       psy->ac.get_property = lp8727_charger_get_property;
-       psy->ac.supplied_to = battery_supplied_to;
-       psy->ac.num_supplicants = ARRAY_SIZE(battery_supplied_to);
+       psy_cfg.supplied_to = battery_supplied_to;
+       psy_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
 
-       if (power_supply_register(pchg->dev, &psy->ac))
+       psy->ac = power_supply_register(pchg->dev, &lp8727_ac_desc, &psy_cfg);
+       if (IS_ERR(psy->ac))
                goto err_psy_ac;
 
-       psy->usb.name = "usb";
-       psy->usb.type = POWER_SUPPLY_TYPE_USB;
-       psy->usb.properties = lp8727_charger_prop;
-       psy->usb.num_properties = ARRAY_SIZE(lp8727_charger_prop);
-       psy->usb.get_property = lp8727_charger_get_property;
-       psy->usb.supplied_to = battery_supplied_to;
-       psy->usb.num_supplicants = ARRAY_SIZE(battery_supplied_to);
-
-       if (power_supply_register(pchg->dev, &psy->usb))
+       psy->usb = power_supply_register(pchg->dev, &lp8727_usb_desc,
+                                        &psy_cfg);
+       if (IS_ERR(psy->usb))
                goto err_psy_usb;
 
-       psy->batt.name = "main_batt";
-       psy->batt.type = POWER_SUPPLY_TYPE_BATTERY;
-       psy->batt.properties = lp8727_battery_prop;
-       psy->batt.num_properties = ARRAY_SIZE(lp8727_battery_prop);
-       psy->batt.get_property = lp8727_battery_get_property;
-       psy->batt.external_power_changed = lp8727_charger_changed;
-
-       if (power_supply_register(pchg->dev, &psy->batt))
+       psy->batt = power_supply_register(pchg->dev, &lp8727_batt_desc, NULL);
+       if (IS_ERR(psy->batt))
                goto err_psy_batt;
 
        return 0;
 
 err_psy_batt:
-       power_supply_unregister(&psy->usb);
+       power_supply_unregister(psy->usb);
 err_psy_usb:
-       power_supply_unregister(&psy->ac);
+       power_supply_unregister(psy->ac);
 err_psy_ac:
        return -EPERM;
 }
@@ -477,9 +487,9 @@ static void lp8727_unregister_psy(struct lp8727_chg *pchg)
        if (!psy)
                return;
 
-       power_supply_unregister(&psy->ac);
-       power_supply_unregister(&psy->usb);
-       power_supply_unregister(&psy->batt);
+       power_supply_unregister(psy->ac);
+       power_supply_unregister(psy->usb);
+       power_supply_unregister(psy->batt);
 }
 
 #ifdef CONFIG_OF
index 21fc233c7d61363091ba63904e7eb010ba70a830..f5a48fd68b01249beb0854a8877ace9aa2011344 100644 (file)
@@ -105,8 +105,8 @@ struct lp8788_chg_irq {
  */
 struct lp8788_charger {
        struct lp8788 *lp;
-       struct power_supply charger;
-       struct power_supply battery;
+       struct power_supply *charger;
+       struct power_supply *battery;
        struct work_struct charger_work;
        struct iio_channel *chan[LP8788_NUM_CHG_ADC];
        struct lp8788_chg_irq irqs[LP8788_MAX_CHG_IRQS];
@@ -148,7 +148,7 @@ static int lp8788_charger_get_property(struct power_supply *psy,
                                        enum power_supply_property psp,
                                        union power_supply_propval *val)
 {
-       struct lp8788_charger *pchg = dev_get_drvdata(psy->dev->parent);
+       struct lp8788_charger *pchg = dev_get_drvdata(psy->dev.parent);
        u8 read;
 
        switch (psp) {
@@ -337,7 +337,7 @@ static int lp8788_battery_get_property(struct power_supply *psy,
                                        enum power_supply_property psp,
                                        union power_supply_propval *val)
 {
-       struct lp8788_charger *pchg = dev_get_drvdata(psy->dev->parent);
+       struct lp8788_charger *pchg = dev_get_drvdata(psy->dev.parent);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
@@ -397,36 +397,50 @@ static int lp8788_update_charger_params(struct platform_device *pdev,
        return 0;
 }
 
+static const struct power_supply_desc lp8788_psy_charger_desc = {
+       .name           = LP8788_CHARGER_NAME,
+       .type           = POWER_SUPPLY_TYPE_MAINS,
+       .properties     = lp8788_charger_prop,
+       .num_properties = ARRAY_SIZE(lp8788_charger_prop),
+       .get_property   = lp8788_charger_get_property,
+};
+
+static const struct power_supply_desc lp8788_psy_battery_desc = {
+       .name           = LP8788_BATTERY_NAME,
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .properties     = lp8788_battery_prop,
+       .num_properties = ARRAY_SIZE(lp8788_battery_prop),
+       .get_property   = lp8788_battery_get_property,
+};
+
 static int lp8788_psy_register(struct platform_device *pdev,
                                struct lp8788_charger *pchg)
 {
-       pchg->charger.name = LP8788_CHARGER_NAME;
-       pchg->charger.type = POWER_SUPPLY_TYPE_MAINS;
-       pchg->charger.properties = lp8788_charger_prop;
-       pchg->charger.num_properties = ARRAY_SIZE(lp8788_charger_prop);
-       pchg->charger.get_property = lp8788_charger_get_property;
-       pchg->charger.supplied_to = battery_supplied_to;
-       pchg->charger.num_supplicants = ARRAY_SIZE(battery_supplied_to);
-
-       if (power_supply_register(&pdev->dev, &pchg->charger))
-               return -EPERM;
+       struct power_supply_config charger_cfg = {};
+
+       charger_cfg.supplied_to = battery_supplied_to;
+       charger_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
 
-       pchg->battery.name = LP8788_BATTERY_NAME;
-       pchg->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-       pchg->battery.properties = lp8788_battery_prop;
-       pchg->battery.num_properties = ARRAY_SIZE(lp8788_battery_prop);
-       pchg->battery.get_property = lp8788_battery_get_property;
+       pchg->charger = power_supply_register(&pdev->dev,
+                                             &lp8788_psy_charger_desc,
+                                             &charger_cfg);
+       if (IS_ERR(pchg->charger))
+               return -EPERM;
 
-       if (power_supply_register(&pdev->dev, &pchg->battery))
+       pchg->battery = power_supply_register(&pdev->dev,
+                                             &lp8788_psy_battery_desc, NULL);
+       if (IS_ERR(pchg->battery)) {
+               power_supply_unregister(pchg->charger);
                return -EPERM;
+       }
 
        return 0;
 }
 
 static void lp8788_psy_unregister(struct lp8788_charger *pchg)
 {
-       power_supply_unregister(&pchg->battery);
-       power_supply_unregister(&pchg->charger);
+       power_supply_unregister(pchg->battery);
+       power_supply_unregister(pchg->charger);
 }
 
 static void lp8788_charger_event(struct work_struct *work)
@@ -470,8 +484,8 @@ static irqreturn_t lp8788_charger_irq_thread(int virq, void *ptr)
        case LP8788_INT_EOC:
        case LP8788_INT_BATT_LOW:
        case LP8788_INT_NO_BATT:
-               power_supply_changed(&pchg->charger);
-               power_supply_changed(&pchg->battery);
+               power_supply_changed(pchg->charger);
+               power_supply_changed(pchg->battery);
                break;
        default:
                break;
index e31c927a6d1611a514c245554a99ff6daa2ada9d..daeb0860736c1d5a954eda63f1a87d716c1b6832 100644 (file)
@@ -59,7 +59,8 @@ enum ltc294x_reg {
 
 struct ltc294x_info {
        struct i2c_client *client;      /* I2C Client pointer */
-       struct power_supply supply;     /* Supply pointer */
+       struct power_supply *supply;    /* Supply pointer */
+       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 */
@@ -294,8 +295,7 @@ static int ltc294x_get_property(struct power_supply *psy,
                                enum power_supply_property prop,
                                union power_supply_propval *val)
 {
-       struct ltc294x_info *info =
-               container_of(psy, struct ltc294x_info, supply);
+       struct ltc294x_info *info = power_supply_get_drvdata(psy);
 
        switch (prop) {
        case POWER_SUPPLY_PROP_CHARGE_NOW:
@@ -317,8 +317,7 @@ static int ltc294x_set_property(struct power_supply *psy,
        enum power_supply_property psp,
        const union power_supply_propval *val)
 {
-       struct ltc294x_info *info =
-               container_of(psy, struct ltc294x_info, supply);
+       struct ltc294x_info *info = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_CHARGE_NOW:
@@ -345,7 +344,7 @@ static void ltc294x_update(struct ltc294x_info *info)
 
        if (charge != info->charge) {
                info->charge = charge;
-               power_supply_changed(&info->supply);
+               power_supply_changed(info->supply);
        }
 }
 
@@ -371,8 +370,8 @@ static int ltc294x_i2c_remove(struct i2c_client *client)
        struct ltc294x_info *info = i2c_get_clientdata(client);
 
        cancel_delayed_work(&info->work);
-       power_supply_unregister(&info->supply);
-       kfree(info->supply.name);
+       power_supply_unregister(info->supply);
+       kfree(info->supply_desc.name);
        mutex_lock(&ltc294x_lock);
        idr_remove(&ltc294x_id, info->id);
        mutex_unlock(&ltc294x_lock);
@@ -382,6 +381,7 @@ static int ltc294x_i2c_remove(struct i2c_client *client)
 static int ltc294x_i2c_probe(struct i2c_client *client,
        const struct i2c_device_id *id)
 {
+       struct power_supply_config psy_cfg = {};
        struct ltc294x_info *info;
        int ret;
        int num;
@@ -406,8 +406,9 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
        i2c_set_clientdata(client, info);
 
        info->num_regs = id->driver_data;
-       info->supply.name = kasprintf(GFP_KERNEL, "%s-%d", client->name, num);
-       if (!info->supply.name) {
+       info->supply_desc.name = kasprintf(GFP_KERNEL, "%s-%d", client->name,
+                                          num);
+       if (!info->supply_desc.name) {
                ret = -ENOMEM;
                goto fail_name;
        }
@@ -440,30 +441,32 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
        } else {
                if (prescaler_exp > LTC2941_MAX_PRESCALER_EXP)
                        prescaler_exp = LTC2941_MAX_PRESCALER_EXP;
-               info->Qlsb = ((58 * 50000) / r_sense) /
+               info->Qlsb = ((85 * 50000) / r_sense) /
                                (128 / (1 << prescaler_exp));
        }
 
        info->client = client;
        info->id = num;
-       info->supply.type = POWER_SUPPLY_TYPE_BATTERY;
-       info->supply.properties = ltc294x_properties;
+       info->supply_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+       info->supply_desc.properties = ltc294x_properties;
        if (info->num_regs >= LTC294X_REG_TEMPERATURE_LSB)
-               info->supply.num_properties =
+               info->supply_desc.num_properties =
                        ARRAY_SIZE(ltc294x_properties);
        else if (info->num_regs >= LTC294X_REG_CURRENT_LSB)
-               info->supply.num_properties =
+               info->supply_desc.num_properties =
                        ARRAY_SIZE(ltc294x_properties) - 1;
        else if (info->num_regs >= LTC294X_REG_VOLTAGE_LSB)
-               info->supply.num_properties =
+               info->supply_desc.num_properties =
                        ARRAY_SIZE(ltc294x_properties) - 2;
        else
-               info->supply.num_properties =
+               info->supply_desc.num_properties =
                        ARRAY_SIZE(ltc294x_properties) - 3;
-       info->supply.get_property = ltc294x_get_property;
-       info->supply.set_property = ltc294x_set_property;
-       info->supply.property_is_writeable = ltc294x_property_is_writeable;
-       info->supply.external_power_changed     = NULL;
+       info->supply_desc.get_property = ltc294x_get_property;
+       info->supply_desc.set_property = ltc294x_set_property;
+       info->supply_desc.property_is_writeable = ltc294x_property_is_writeable;
+       info->supply_desc.external_power_changed        = NULL;
+
+       psy_cfg.drv_data = info;
 
        INIT_DELAYED_WORK(&info->work, ltc294x_work);
 
@@ -473,9 +476,11 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
                goto fail_comm;
        }
 
-       ret = power_supply_register(&client->dev, &info->supply);
-       if (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;
        } else {
                schedule_delayed_work(&info->work, LTC294X_WORK_DELAY * HZ);
@@ -484,7 +489,7 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
        return 0;
 
 fail_register:
-       kfree(info->supply.name);
+       kfree(info->supply_desc.name);
 fail_comm:
 fail_name:
 fail_info:
index ef4103ee6021419da909748ea4189546e3146290..a36bcaf62dd44fad1044f390db7e908b7f95acfd 100644 (file)
 #include <linux/mfd/max14577.h>
 
 struct max14577_charger {
-       struct device *dev;
-       struct max14577 *max14577;
-       struct power_supply     charger;
-
-       unsigned int            charging_state;
-       unsigned int            battery_state;
+       struct device           *dev;
+       struct max14577         *max14577;
+       struct power_supply     *charger;
 
        struct max14577_charger_platform_data   *pdata;
 };
@@ -57,10 +54,10 @@ static enum max14577_muic_charger_type maxim_get_charger_type(
        }
 }
 
-static int max14577_get_charger_state(struct max14577_charger *chg)
+static int max14577_get_charger_state(struct max14577_charger *chg, int *val)
 {
        struct regmap *rmap = chg->max14577->regmap;
-       int state = POWER_SUPPLY_STATUS_DISCHARGING;
+       int ret;
        u8 reg_data;
 
        /*
@@ -74,23 +71,32 @@ static int max14577_get_charger_state(struct max14577_charger *chg)
         *  - handle properly dead-battery charging (respect timer)
         *  - handle timers (fast-charge and prequal) /MBCCHGERR/
         */
-       max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL2, &reg_data);
-       if ((reg_data & CHGCTRL2_MBCHOSTEN_MASK) == 0)
-               goto state_set;
+       ret = max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL2, &reg_data);
+       if (ret < 0)
+               goto out;
+
+       if ((reg_data & CHGCTRL2_MBCHOSTEN_MASK) == 0) {
+               *val = POWER_SUPPLY_STATUS_DISCHARGING;
+               goto out;
+       }
+
+       ret = max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, &reg_data);
+       if (ret < 0)
+               goto out;
 
-       max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, &reg_data);
        if (reg_data & STATUS3_CGMBC_MASK) {
                /* Charger or USB-cable is connected */
                if (reg_data & STATUS3_EOC_MASK)
-                       state = POWER_SUPPLY_STATUS_FULL;
+                       *val = POWER_SUPPLY_STATUS_FULL;
                else
-                       state = POWER_SUPPLY_STATUS_CHARGING;
-               goto state_set;
+                       *val = POWER_SUPPLY_STATUS_CHARGING;
+               goto out;
        }
 
-state_set:
-       chg->charging_state = state;
-       return state;
+       *val = POWER_SUPPLY_STATUS_DISCHARGING;
+
+out:
+       return ret;
 }
 
 /*
@@ -98,8 +104,10 @@ state_set:
  *  - POWER_SUPPLY_CHARGE_TYPE_NONE
  *  - POWER_SUPPLY_CHARGE_TYPE_FAST
  */
-static int max14577_get_charge_type(struct max14577_charger *chg)
+static int max14577_get_charge_type(struct max14577_charger *chg, int *val)
 {
+       int ret, charging;
+
        /*
         * TODO: CHARGE_TYPE_TRICKLE (VCHGR_RC or EOC)?
         * As spec says:
@@ -108,18 +116,29 @@ static int max14577_get_charge_type(struct max14577_charger *chg)
         *  top-off timer starts. The device continues to trickle
         *  charge the battery until the top-off timer runs out."
         */
-       if (max14577_get_charger_state(chg) == POWER_SUPPLY_STATUS_CHARGING)
-               return POWER_SUPPLY_CHARGE_TYPE_FAST;
-       return POWER_SUPPLY_CHARGE_TYPE_NONE;
+       ret = max14577_get_charger_state(chg, &charging);
+       if (ret < 0)
+               return ret;
+
+       if (charging == POWER_SUPPLY_STATUS_CHARGING)
+               *val = POWER_SUPPLY_CHARGE_TYPE_FAST;
+       else
+               *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
+
+       return 0;
 }
 
-static int max14577_get_online(struct max14577_charger *chg)
+static int max14577_get_online(struct max14577_charger *chg, int *val)
 {
        struct regmap *rmap = chg->max14577->regmap;
        u8 reg_data;
+       int ret;
        enum max14577_muic_charger_type chg_type;
 
-       max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, &reg_data);
+       ret = max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, &reg_data);
+       if (ret < 0)
+               return ret;
+
        reg_data = ((reg_data & STATUS2_CHGTYP_MASK) >> STATUS2_CHGTYP_SHIFT);
        chg_type = maxim_get_charger_type(chg->max14577->dev_type, reg_data);
        switch (chg_type) {
@@ -129,14 +148,17 @@ static int max14577_get_online(struct max14577_charger *chg)
        case MAX14577_CHARGER_TYPE_SPECIAL_1A:
        case MAX14577_CHARGER_TYPE_DEAD_BATTERY:
        case MAX77836_CHARGER_TYPE_SPECIAL_BIAS:
-               return 1;
+               *val = 1;
+               break;
        case MAX14577_CHARGER_TYPE_NONE:
        case MAX14577_CHARGER_TYPE_DOWNSTREAM_PORT:
        case MAX14577_CHARGER_TYPE_RESERVED:
        case MAX77836_CHARGER_TYPE_RESERVED:
        default:
-               return 0;
+               *val = 0;
        }
+
+       return 0;
 }
 
 /*
@@ -145,30 +167,38 @@ static int max14577_get_online(struct max14577_charger *chg)
  *  - POWER_SUPPLY_HEALTH_OVERVOLTAGE
  *  - POWER_SUPPLY_HEALTH_GOOD
  */
-static int max14577_get_battery_health(struct max14577_charger *chg)
+static int max14577_get_battery_health(struct max14577_charger *chg, int *val)
 {
        struct regmap *rmap = chg->max14577->regmap;
-       int state = POWER_SUPPLY_HEALTH_GOOD;
+       int ret;
        u8 reg_data;
        enum max14577_muic_charger_type chg_type;
 
-       max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, &reg_data);
+       ret = max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, &reg_data);
+       if (ret < 0)
+               goto out;
+
        reg_data = ((reg_data & STATUS2_CHGTYP_MASK) >> STATUS2_CHGTYP_SHIFT);
        chg_type = maxim_get_charger_type(chg->max14577->dev_type, reg_data);
        if (chg_type == MAX14577_CHARGER_TYPE_DEAD_BATTERY) {
-               state = POWER_SUPPLY_HEALTH_DEAD;
-               goto state_set;
+               *val = POWER_SUPPLY_HEALTH_DEAD;
+               goto out;
        }
 
-       max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, &reg_data);
+       ret = max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, &reg_data);
+       if (ret < 0)
+               goto out;
+
        if (reg_data & STATUS3_OVP_MASK) {
-               state = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
-               goto state_set;
+               *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+               goto out;
        }
 
-state_set:
-       chg->battery_state = state;
-       return state;
+       /* Not dead, not overvoltage */
+       *val = POWER_SUPPLY_HEALTH_GOOD;
+
+out:
+       return ret;
 }
 
 /*
@@ -176,9 +206,11 @@ state_set:
  * The max14577 chip doesn't report any status of battery presence.
  * Lets assume that it will always be used with some battery.
  */
-static int max14577_get_present(struct max14577_charger *chg)
+static int max14577_get_present(struct max14577_charger *chg, int *val)
 {
-       return 1;
+       *val = 1;
+
+       return 0;
 }
 
 static int max14577_set_fast_charge_timer(struct max14577_charger *chg,
@@ -389,26 +421,24 @@ static int max14577_charger_get_property(struct power_supply *psy,
                            enum power_supply_property psp,
                            union power_supply_propval *val)
 {
-       struct max14577_charger *chg = container_of(psy,
-                                                 struct max14577_charger,
-                                                 charger);
+       struct max14577_charger *chg = power_supply_get_drvdata(psy);
        int ret = 0;
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
-               val->intval = max14577_get_charger_state(chg);
+               ret = max14577_get_charger_state(chg, &val->intval);
                break;
        case POWER_SUPPLY_PROP_CHARGE_TYPE:
-               val->intval = max14577_get_charge_type(chg);
+               ret = max14577_get_charge_type(chg, &val->intval);
                break;
        case POWER_SUPPLY_PROP_HEALTH:
-               val->intval = max14577_get_battery_health(chg);
+               ret = max14577_get_battery_health(chg, &val->intval);
                break;
        case POWER_SUPPLY_PROP_PRESENT:
-               val->intval = max14577_get_present(chg);
+               ret = max14577_get_present(chg, &val->intval);
                break;
        case POWER_SUPPLY_PROP_ONLINE:
-               val->intval = max14577_get_online(chg);
+               ret = max14577_get_online(chg, &val->intval);
                break;
        case POWER_SUPPLY_PROP_MODEL_NAME:
                BUILD_BUG_ON(ARRAY_SIZE(model_names) != MAXIM_DEVICE_TYPE_NUM);
@@ -424,6 +454,14 @@ static int max14577_charger_get_property(struct power_supply *psy,
        return ret;
 }
 
+static const struct power_supply_desc max14577_charger_desc = {
+       .name = "max14577-charger",
+       .type = POWER_SUPPLY_TYPE_BATTERY,
+       .properties = max14577_charger_props,
+       .num_properties = ARRAY_SIZE(max14577_charger_props),
+       .get_property = max14577_charger_get_property,
+};
+
 #ifdef CONFIG_OF
 static struct max14577_charger_platform_data *max14577_charger_dt_init(
                struct platform_device *pdev)
@@ -531,6 +569,7 @@ static DEVICE_ATTR(fast_charge_timer, S_IRUGO | S_IWUSR,
 static int max14577_charger_probe(struct platform_device *pdev)
 {
        struct max14577_charger *chg;
+       struct power_supply_config psy_cfg = {};
        struct max14577 *max14577 = dev_get_drvdata(pdev->dev.parent);
        int ret;
 
@@ -550,21 +589,18 @@ static int max14577_charger_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       chg->charger.name = "max14577-charger",
-       chg->charger.type = POWER_SUPPLY_TYPE_BATTERY,
-       chg->charger.properties = max14577_charger_props,
-       chg->charger.num_properties = ARRAY_SIZE(max14577_charger_props),
-       chg->charger.get_property = max14577_charger_get_property,
-
        ret = device_create_file(&pdev->dev, &dev_attr_fast_charge_timer);
        if (ret) {
                dev_err(&pdev->dev, "failed: create sysfs entry\n");
                return ret;
        }
 
-       ret = power_supply_register(&pdev->dev, &chg->charger);
-       if (ret) {
+       psy_cfg.drv_data = chg;
+       chg->charger = power_supply_register(&pdev->dev, &max14577_charger_desc,
+                                               &psy_cfg);
+       if (IS_ERR(chg->charger)) {
                dev_err(&pdev->dev, "failed: power supply register\n");
+               ret = PTR_ERR(chg->charger);
                goto err;
        }
 
@@ -585,7 +621,7 @@ static int max14577_charger_remove(struct platform_device *pdev)
        struct max14577_charger *chg = platform_get_drvdata(pdev);
 
        device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer);
-       power_supply_unregister(&chg->charger);
+       power_supply_unregister(chg->charger);
 
        return 0;
 }
index 14d44706327bca64fc487a4a057a4c2a0c130b1d..8689c80202b532047252840f3f12872aeebcf92b 100644 (file)
@@ -40,7 +40,7 @@
 struct max17040_chip {
        struct i2c_client               *client;
        struct delayed_work             work;
-       struct power_supply             battery;
+       struct power_supply             *battery;
        struct max17040_platform_data   *pdata;
 
        /* State Of Connect */
@@ -57,8 +57,7 @@ static int max17040_get_property(struct power_supply *psy,
                            enum power_supply_property psp,
                            union power_supply_propval *val)
 {
-       struct max17040_chip *chip = container_of(psy,
-                               struct max17040_chip, battery);
+       struct max17040_chip *chip = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
@@ -188,7 +187,8 @@ static void max17040_work(struct work_struct *work)
        max17040_get_online(chip->client);
        max17040_get_status(chip->client);
 
-       schedule_delayed_work(&chip->work, MAX17040_DELAY);
+       queue_delayed_work(system_power_efficient_wq, &chip->work,
+                          MAX17040_DELAY);
 }
 
 static enum power_supply_property max17040_battery_props[] = {
@@ -198,12 +198,20 @@ static enum power_supply_property max17040_battery_props[] = {
        POWER_SUPPLY_PROP_CAPACITY,
 };
 
+static const struct power_supply_desc max17040_battery_desc = {
+       .name           = "battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .get_property   = max17040_get_property,
+       .properties     = max17040_battery_props,
+       .num_properties = ARRAY_SIZE(max17040_battery_props),
+};
+
 static int max17040_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       struct power_supply_config psy_cfg = {};
        struct max17040_chip *chip;
-       int ret;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
                return -EIO;
@@ -216,24 +224,21 @@ static int max17040_probe(struct i2c_client *client,
        chip->pdata = client->dev.platform_data;
 
        i2c_set_clientdata(client, chip);
+       psy_cfg.drv_data = chip;
 
-       chip->battery.name              = "battery";
-       chip->battery.type              = POWER_SUPPLY_TYPE_BATTERY;
-       chip->battery.get_property      = max17040_get_property;
-       chip->battery.properties        = max17040_battery_props;
-       chip->battery.num_properties    = ARRAY_SIZE(max17040_battery_props);
-
-       ret = power_supply_register(&client->dev, &chip->battery);
-       if (ret) {
+       chip->battery = power_supply_register(&client->dev,
+                               &max17040_battery_desc, &psy_cfg);
+       if (IS_ERR(chip->battery)) {
                dev_err(&client->dev, "failed: power supply register\n");
-               return ret;
+               return PTR_ERR(chip->battery);
        }
 
        max17040_reset(client);
        max17040_get_version(client);
 
        INIT_DEFERRABLE_WORK(&chip->work, max17040_work);
-       schedule_delayed_work(&chip->work, MAX17040_DELAY);
+       queue_delayed_work(system_power_efficient_wq, &chip->work,
+                          MAX17040_DELAY);
 
        return 0;
 }
@@ -242,7 +247,7 @@ static int max17040_remove(struct i2c_client *client)
 {
        struct max17040_chip *chip = i2c_get_clientdata(client);
 
-       power_supply_unregister(&chip->battery);
+       power_supply_unregister(chip->battery);
        cancel_delayed_work(&chip->work);
        return 0;
 }
@@ -263,7 +268,8 @@ static int max17040_resume(struct device *dev)
        struct i2c_client *client = to_i2c_client(dev);
        struct max17040_chip *chip = i2c_get_clientdata(client);
 
-       schedule_delayed_work(&chip->work, MAX17040_DELAY);
+       queue_delayed_work(system_power_efficient_wq, &chip->work,
+                          MAX17040_DELAY);
        return 0;
 }
 
index 1da6c5fbdff5b5165866576e0bfcc5fd66a53867..6cc5e87ec031073ebda3dfea04e4899096622ba1 100644 (file)
 #define dP_ACC_100     0x1900
 #define dP_ACC_200     0x3200
 
-#define MAX17042_IC_VERSION    0x0092
-#define MAX17047_IC_VERSION    0x00AC  /* same for max17050 */
-
 struct max17042_chip {
        struct i2c_client *client;
        struct regmap *regmap;
-       struct power_supply battery;
+       struct power_supply *battery;
        enum max170xx_chip_type chip_type;
        struct max17042_platform_data *pdata;
        struct work_struct work;
@@ -96,8 +93,7 @@ static int max17042_get_property(struct power_supply *psy,
                            enum power_supply_property psp,
                            union power_supply_propval *val)
 {
-       struct max17042_chip *chip = container_of(psy,
-                               struct max17042_chip, battery);
+       struct max17042_chip *chip = power_supply_get_drvdata(psy);
        struct regmap *map = chip->regmap;
        int ret;
        u32 data;
@@ -132,7 +128,7 @@ static int max17042_get_property(struct power_supply *psy,
                val->intval *= 20000; /* Units of LSB = 20mV */
                break;
        case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
-               if (chip->chip_type == MAX17042)
+               if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042)
                        ret = regmap_read(map, MAX17042_V_empty, &data);
                else
                        ret = regmap_read(map, MAX17047_V_empty, &data);
@@ -272,6 +268,7 @@ static inline void max17042_override_por(struct regmap *map,
 static inline void max10742_unlock_model(struct max17042_chip *chip)
 {
        struct regmap *map = chip->regmap;
+
        regmap_write(map, MAX17042_MLOCKReg1, MODEL_UNLOCK1);
        regmap_write(map, MAX17042_MLOCKReg2, MODEL_UNLOCK2);
 }
@@ -289,6 +286,7 @@ static inline void max17042_write_model_data(struct max17042_chip *chip,
 {
        struct regmap *map = chip->regmap;
        int i;
+
        for (i = 0; i < size; i++)
                regmap_write(map, addr + i,
                        chip->pdata->config_data->cell_char_tbl[i]);
@@ -379,7 +377,8 @@ static void max17042_write_config_regs(struct max17042_chip *chip)
        regmap_write(map, MAX17042_FilterCFG,
                        config->filter_cfg);
        regmap_write(map, MAX17042_RelaxCFG, config->relax_cfg);
-       if (chip->chip_type == MAX17047)
+       if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047 ||
+                       chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050)
                regmap_write(map, MAX17047_FullSOCThr,
                                                config->full_soc_thresh);
 }
@@ -392,7 +391,7 @@ static void  max17042_write_custom_regs(struct max17042_chip *chip)
        max17042_write_verify_reg(map, MAX17042_RCOMP0, config->rcomp0);
        max17042_write_verify_reg(map, MAX17042_TempCo, config->tcompc0);
        max17042_write_verify_reg(map, MAX17042_ICHGTerm, config->ichgt_term);
-       if (chip->chip_type == MAX17042) {
+       if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) {
                regmap_write(map, MAX17042_EmptyTempCo, config->empty_tempco);
                max17042_write_verify_reg(map, MAX17042_K_empty0,
                                        config->kempty0);
@@ -501,14 +500,14 @@ static inline void max17042_override_por_values(struct max17042_chip *chip)
 
        max17042_override_por(map, MAX17042_FullCAP, config->fullcap);
        max17042_override_por(map, MAX17042_FullCAPNom, config->fullcapnom);
-       if (chip->chip_type == MAX17042)
+       if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042)
                max17042_override_por(map, MAX17042_SOC_empty,
                                                config->socempty);
        max17042_override_por(map, MAX17042_LAvg_empty, config->lavg_empty);
        max17042_override_por(map, MAX17042_dQacc, config->dqacc);
        max17042_override_por(map, MAX17042_dPacc, config->dpacc);
 
-       if (chip->chip_type == MAX17042)
+       if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042)
                max17042_override_por(map, MAX17042_V_empty, config->vempty);
        else
                max17042_override_por(map, MAX17047_V_empty, config->vempty);
@@ -529,7 +528,6 @@ static int max17042_init_chip(struct max17042_chip *chip)
 {
        struct regmap *map = chip->regmap;
        int ret;
-       int val;
 
        max17042_override_por_values(chip);
        /* After Power up, the MAX17042 requires 500mS in order
@@ -572,8 +570,7 @@ static int max17042_init_chip(struct max17042_chip *chip)
        max17042_load_new_capacity_params(chip);
 
        /* Init complete, Clear the POR bit */
-       regmap_read(map, MAX17042_STATUS, &val);
-       regmap_write(map, MAX17042_STATUS, val & (~STATUS_POR_BIT));
+       regmap_update_bits(map, MAX17042_STATUS, STATUS_POR_BIT, 0x0);
        return 0;
 }
 
@@ -604,7 +601,7 @@ static irqreturn_t max17042_thread_handler(int id, void *dev)
                max17042_set_soc_threshold(chip, 1);
        }
 
-       power_supply_changed(&chip->battery);
+       power_supply_changed(chip->battery);
        return IRQ_HANDLED;
 }
 
@@ -664,10 +661,28 @@ static const struct regmap_config max17042_regmap_config = {
        .val_format_endian = REGMAP_ENDIAN_NATIVE,
 };
 
+static const struct power_supply_desc max17042_psy_desc = {
+       .name           = "max170xx_battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .get_property   = max17042_get_property,
+       .properties     = max17042_battery_props,
+       .num_properties = ARRAY_SIZE(max17042_battery_props),
+};
+
+static const struct power_supply_desc max17042_no_current_sense_psy_desc = {
+       .name           = "max170xx_battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .get_property   = max17042_get_property,
+       .properties     = max17042_battery_props,
+       .num_properties = ARRAY_SIZE(max17042_battery_props) - 2,
+};
+
 static int max17042_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       const struct power_supply_desc *max17042_desc = &max17042_psy_desc;
+       struct power_supply_config psy_cfg = {};
        struct max17042_chip *chip;
        int ret;
        int i;
@@ -694,29 +709,13 @@ static int max17042_probe(struct i2c_client *client,
        }
 
        i2c_set_clientdata(client, chip);
-
-       regmap_read(chip->regmap, MAX17042_DevName, &val);
-       if (val == MAX17042_IC_VERSION) {
-               dev_dbg(&client->dev, "chip type max17042 detected\n");
-               chip->chip_type = MAX17042;
-       } else if (val == MAX17047_IC_VERSION) {
-               dev_dbg(&client->dev, "chip type max17047/50 detected\n");
-               chip->chip_type = MAX17047;
-       } else {
-               dev_err(&client->dev, "device version mismatch: %x\n", val);
-               return -EIO;
-       }
-
-       chip->battery.name              = "max170xx_battery";
-       chip->battery.type              = POWER_SUPPLY_TYPE_BATTERY;
-       chip->battery.get_property      = max17042_get_property;
-       chip->battery.properties        = max17042_battery_props;
-       chip->battery.num_properties    = ARRAY_SIZE(max17042_battery_props);
+       chip->chip_type = id->driver_data;
+       psy_cfg.drv_data = chip;
 
        /* When current is not measured,
         * CURRENT_NOW and CURRENT_AVG properties should be invisible. */
        if (!chip->pdata->enable_current_sense)
-               chip->battery.num_properties -= 2;
+               max17042_desc = &max17042_no_current_sense_psy_desc;
 
        if (chip->pdata->r_sns == 0)
                chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
@@ -733,21 +732,22 @@ static int max17042_probe(struct i2c_client *client,
                regmap_write(chip->regmap, MAX17042_LearnCFG, 0x0007);
        }
 
-       ret = power_supply_register(&client->dev, &chip->battery);
-       if (ret) {
+       chip->battery = power_supply_register(&client->dev, max17042_desc,
+                                               &psy_cfg);
+       if (IS_ERR(chip->battery)) {
                dev_err(&client->dev, "failed: power supply register\n");
-               return ret;
+               return PTR_ERR(chip->battery);
        }
 
        if (client->irq) {
                ret = request_threaded_irq(client->irq, NULL,
                                        max17042_thread_handler,
                                        IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                                       chip->battery.name, chip);
+                                       chip->battery->desc->name, chip);
                if (!ret) {
-                       regmap_read(chip->regmap, MAX17042_CONFIG, &val);
-                       val |= CONFIG_ALRT_BIT_ENBL;
-                       regmap_write(chip->regmap, MAX17042_CONFIG, val);
+                       regmap_update_bits(chip->regmap, MAX17042_CONFIG,
+                                       CONFIG_ALRT_BIT_ENBL,
+                                       CONFIG_ALRT_BIT_ENBL);
                        max17042_set_soc_threshold(chip, 1);
                } else {
                        client->irq = 0;
@@ -773,7 +773,7 @@ static int max17042_remove(struct i2c_client *client)
 
        if (client->irq)
                free_irq(client->irq, chip);
-       power_supply_unregister(&chip->battery);
+       power_supply_unregister(chip->battery);
        return 0;
 }
 
@@ -823,9 +823,9 @@ MODULE_DEVICE_TABLE(of, max17042_dt_match);
 #endif
 
 static const struct i2c_device_id max17042_id[] = {
-       { "max17042", 0 },
-       { "max17047", 1 },
-       { "max17050", 2 },
+       { "max17042", MAXIM_DEVICE_TYPE_MAX17042 },
+       { "max17047", MAXIM_DEVICE_TYPE_MAX17047 },
+       { "max17050", MAXIM_DEVICE_TYPE_MAX17050 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, max17042_id);
index b042970fdeafa787ab4b464cdcc2175aebd3423a..754879eb59f67b878fc70b6b19dc10935c15d257 100644 (file)
 #include <linux/mfd/max77693.h>
 #include <linux/mfd/max77693-private.h>
 
-static const char *max77693_charger_name               = "max77693-charger";
+#define MAX77693_CHARGER_NAME                          "max77693-charger"
 static const char *max77693_charger_model              = "MAX77693";
 static const char *max77693_charger_manufacturer       = "Maxim Integrated";
 
 struct max77693_charger {
        struct device           *dev;
        struct max77693_dev     *max77693;
-       struct power_supply     charger;
+       struct power_supply     *charger;
 
        u32 constant_volt;
        u32 min_system_volt;
@@ -38,13 +38,14 @@ struct max77693_charger {
        u32 charge_input_threshold_volt;
 };
 
-static int max77693_get_charger_state(struct regmap *regmap)
+static int max77693_get_charger_state(struct regmap *regmap, int *val)
 {
-       int state;
+       int ret;
        unsigned int data;
 
-       if (regmap_read(regmap, MAX77693_CHG_REG_CHG_DETAILS_01, &data) < 0)
-               return POWER_SUPPLY_STATUS_UNKNOWN;
+       ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_DETAILS_01, &data);
+       if (ret < 0)
+               return ret;
 
        data &= CHG_DETAILS_01_CHG_MASK;
        data >>= CHG_DETAILS_01_CHG_SHIFT;
@@ -56,35 +57,36 @@ static int max77693_get_charger_state(struct regmap *regmap)
        case MAX77693_CHARGING_TOP_OFF:
        /* In high temp the charging current is reduced, but still charging */
        case MAX77693_CHARGING_HIGH_TEMP:
-               state = POWER_SUPPLY_STATUS_CHARGING;
+               *val = POWER_SUPPLY_STATUS_CHARGING;
                break;
        case MAX77693_CHARGING_DONE:
-               state = POWER_SUPPLY_STATUS_FULL;
+               *val = POWER_SUPPLY_STATUS_FULL;
                break;
        case MAX77693_CHARGING_TIMER_EXPIRED:
        case MAX77693_CHARGING_THERMISTOR_SUSPEND:
-               state = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
                break;
        case MAX77693_CHARGING_OFF:
        case MAX77693_CHARGING_OVER_TEMP:
        case MAX77693_CHARGING_WATCHDOG_EXPIRED:
-               state = POWER_SUPPLY_STATUS_DISCHARGING;
+               *val = POWER_SUPPLY_STATUS_DISCHARGING;
                break;
        case MAX77693_CHARGING_RESERVED:
        default:
-               state = POWER_SUPPLY_STATUS_UNKNOWN;
+               *val = POWER_SUPPLY_STATUS_UNKNOWN;
        }
 
-       return state;
+       return 0;
 }
 
-static int max77693_get_charge_type(struct regmap *regmap)
+static int max77693_get_charge_type(struct regmap *regmap, int *val)
 {
-       int state;
+       int ret;
        unsigned int data;
 
-       if (regmap_read(regmap, MAX77693_CHG_REG_CHG_DETAILS_01, &data) < 0)
-               return POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+       ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_DETAILS_01, &data);
+       if (ret < 0)
+               return ret;
 
        data &= CHG_DETAILS_01_CHG_MASK;
        data >>= CHG_DETAILS_01_CHG_SHIFT;
@@ -96,13 +98,13 @@ static int max77693_get_charge_type(struct regmap *regmap)
         * 100 and 250 mA. It is higher than prequalification current.
         */
        case MAX77693_CHARGING_TOP_OFF:
-               state = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+               *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
                break;
        case MAX77693_CHARGING_FAST_CONST_CURRENT:
        case MAX77693_CHARGING_FAST_CONST_VOLTAGE:
        /* In high temp the charging current is reduced, but still charging */
        case MAX77693_CHARGING_HIGH_TEMP:
-               state = POWER_SUPPLY_CHARGE_TYPE_FAST;
+               *val = POWER_SUPPLY_CHARGE_TYPE_FAST;
                break;
        case MAX77693_CHARGING_DONE:
        case MAX77693_CHARGING_TIMER_EXPIRED:
@@ -110,14 +112,14 @@ static int max77693_get_charge_type(struct regmap *regmap)
        case MAX77693_CHARGING_OFF:
        case MAX77693_CHARGING_OVER_TEMP:
        case MAX77693_CHARGING_WATCHDOG_EXPIRED:
-               state = POWER_SUPPLY_CHARGE_TYPE_NONE;
+               *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
                break;
        case MAX77693_CHARGING_RESERVED:
        default:
-               state = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+               *val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
        }
 
-       return state;
+       return 0;
 }
 
 /*
@@ -129,69 +131,78 @@ static int max77693_get_charge_type(struct regmap *regmap)
  *  - POWER_SUPPLY_HEALTH_UNKNOWN
  *  - POWER_SUPPLY_HEALTH_UNSPEC_FAILURE
  */
-static int max77693_get_battery_health(struct regmap *regmap)
+static int max77693_get_battery_health(struct regmap *regmap, int *val)
 {
-       int state;
+       int ret;
        unsigned int data;
 
-       if (regmap_read(regmap, MAX77693_CHG_REG_CHG_DETAILS_01, &data) < 0)
-               return POWER_SUPPLY_HEALTH_UNKNOWN;
+       ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_DETAILS_01, &data);
+       if (ret < 0)
+               return ret;
 
        data &= CHG_DETAILS_01_BAT_MASK;
        data >>= CHG_DETAILS_01_BAT_SHIFT;
 
        switch (data) {
        case MAX77693_BATTERY_NOBAT:
-               state = POWER_SUPPLY_HEALTH_DEAD;
+               *val = POWER_SUPPLY_HEALTH_DEAD;
                break;
        case MAX77693_BATTERY_PREQUALIFICATION:
        case MAX77693_BATTERY_GOOD:
        case MAX77693_BATTERY_LOWVOLTAGE:
-               state = POWER_SUPPLY_HEALTH_GOOD;
+               *val = POWER_SUPPLY_HEALTH_GOOD;
                break;
        case MAX77693_BATTERY_TIMER_EXPIRED:
                /*
                 * Took longer to charge than expected, charging suspended.
                 * Damaged battery?
                 */
-               state = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
+               *val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
                break;
        case MAX77693_BATTERY_OVERVOLTAGE:
-               state = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+               *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
                break;
        case MAX77693_BATTERY_OVERCURRENT:
-               state = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+               *val = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
                break;
        case MAX77693_BATTERY_RESERVED:
        default:
-               state = POWER_SUPPLY_HEALTH_UNKNOWN;
+               *val = POWER_SUPPLY_HEALTH_UNKNOWN;
                break;
        }
 
-       return state;
+       return 0;
 }
 
-static int max77693_get_present(struct regmap *regmap)
+static int max77693_get_present(struct regmap *regmap, int *val)
 {
        unsigned int data;
+       int ret;
 
        /*
         * Read CHG_INT_OK register. High DETBAT bit here should be
         * equal to value 0x0 in CHG_DETAILS_01/BAT field.
         */
-       regmap_read(regmap, MAX77693_CHG_REG_CHG_INT_OK, &data);
-       if (data & CHG_INT_OK_DETBAT_MASK)
-               return 0;
-       return 1;
+       ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_INT_OK, &data);
+       if (ret < 0)
+               return ret;
+
+       *val = (data & CHG_INT_OK_DETBAT_MASK) ? 0 : 1;
+
+       return 0;
 }
 
-static int max77693_get_online(struct regmap *regmap)
+static int max77693_get_online(struct regmap *regmap, int *val)
 {
        unsigned int data;
+       int ret;
+
+       ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_INT_OK, &data);
+       if (ret < 0)
+               return ret;
+
+       *val = (data & CHG_INT_OK_CHGIN_MASK) ? 1 : 0;
 
-       regmap_read(regmap, MAX77693_CHG_REG_CHG_INT_OK, &data);
-       if (data & CHG_INT_OK_CHGIN_MASK)
-               return 1;
        return 0;
 }
 
@@ -209,27 +220,25 @@ static int max77693_charger_get_property(struct power_supply *psy,
                            enum power_supply_property psp,
                            union power_supply_propval *val)
 {
-       struct max77693_charger *chg = container_of(psy,
-                                                 struct max77693_charger,
-                                                 charger);
+       struct max77693_charger *chg = power_supply_get_drvdata(psy);
        struct regmap *regmap = chg->max77693->regmap;
        int ret = 0;
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
-               val->intval = max77693_get_charger_state(regmap);
+               ret = max77693_get_charger_state(regmap, &val->intval);
                break;
        case POWER_SUPPLY_PROP_CHARGE_TYPE:
-               val->intval = max77693_get_charge_type(regmap);
+               ret = max77693_get_charge_type(regmap, &val->intval);
                break;
        case POWER_SUPPLY_PROP_HEALTH:
-               val->intval = max77693_get_battery_health(regmap);
+               ret = max77693_get_battery_health(regmap, &val->intval);
                break;
        case POWER_SUPPLY_PROP_PRESENT:
-               val->intval = max77693_get_present(regmap);
+               ret = max77693_get_present(regmap, &val->intval);
                break;
        case POWER_SUPPLY_PROP_ONLINE:
-               val->intval = max77693_get_online(regmap);
+               ret = max77693_get_online(regmap, &val->intval);
                break;
        case POWER_SUPPLY_PROP_MODEL_NAME:
                val->strval = max77693_charger_model;
@@ -244,6 +253,14 @@ static int max77693_charger_get_property(struct power_supply *psy,
        return ret;
 }
 
+static const struct power_supply_desc max77693_charger_desc = {
+       .name           = MAX77693_CHARGER_NAME,
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .properties     = max77693_charger_props,
+       .num_properties = ARRAY_SIZE(max77693_charger_props),
+       .get_property   = max77693_charger_get_property,
+};
+
 static ssize_t device_attr_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count,
                int (*fn)(struct max77693_charger *, unsigned long))
@@ -659,6 +676,7 @@ static int max77693_dt_init(struct device *dev, struct max77693_charger *chg)
 static int max77693_charger_probe(struct platform_device *pdev)
 {
        struct max77693_charger *chg;
+       struct power_supply_config psy_cfg = {};
        struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
        int ret;
 
@@ -678,11 +696,7 @@ static int max77693_charger_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       chg->charger.name = max77693_charger_name;
-       chg->charger.type = POWER_SUPPLY_TYPE_BATTERY;
-       chg->charger.properties = max77693_charger_props;
-       chg->charger.num_properties = ARRAY_SIZE(max77693_charger_props);
-       chg->charger.get_property = max77693_charger_get_property;
+       psy_cfg.drv_data = chg;
 
        ret = device_create_file(&pdev->dev, &dev_attr_fast_charge_timer);
        if (ret) {
@@ -703,9 +717,12 @@ static int max77693_charger_probe(struct platform_device *pdev)
                goto err;
        }
 
-       ret = power_supply_register(&pdev->dev, &chg->charger);
-       if (ret) {
+       chg->charger = power_supply_register(&pdev->dev,
+                                               &max77693_charger_desc,
+                                               &psy_cfg);
+       if (IS_ERR(chg->charger)) {
                dev_err(&pdev->dev, "failed: power supply register\n");
+               ret = PTR_ERR(chg->charger);
                goto err;
        }
 
@@ -727,7 +744,7 @@ static int max77693_charger_remove(struct platform_device *pdev)
        device_remove_file(&pdev->dev, &dev_attr_top_off_threshold_current);
        device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer);
 
-       power_supply_unregister(&chg->charger);
+       power_supply_unregister(chg->charger);
 
        return 0;
 }
index 99e3cdcd3e11f06c7763865809f83c20f4eedae1..bf2b4b3a7caef2db27317dc6e919f87ae3fdd72d 100644 (file)
@@ -31,7 +31,8 @@
 struct max8903_data {
        struct max8903_pdata pdata;
        struct device *dev;
-       struct power_supply psy;
+       struct power_supply *psy;
+       struct power_supply_desc psy_desc;
        bool fault;
        bool usb_in;
        bool ta_in;
@@ -47,8 +48,7 @@ static int max8903_get_property(struct power_supply *psy,
                enum power_supply_property psp,
                union power_supply_propval *val)
 {
-       struct max8903_data *data = container_of(psy,
-                       struct max8903_data, psy);
+       struct max8903_data *data = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
@@ -104,17 +104,17 @@ static irqreturn_t max8903_dcin(int irq, void *_data)
        dev_dbg(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ?
                        "Connected" : "Disconnected");
 
-       old_type = data->psy.type;
+       old_type = data->psy_desc.type;
 
        if (data->ta_in)
-               data->psy.type = POWER_SUPPLY_TYPE_MAINS;
+               data->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
        else if (data->usb_in)
-               data->psy.type = POWER_SUPPLY_TYPE_USB;
+               data->psy_desc.type = POWER_SUPPLY_TYPE_USB;
        else
-               data->psy.type = POWER_SUPPLY_TYPE_BATTERY;
+               data->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
 
-       if (old_type != data->psy.type)
-               power_supply_changed(&data->psy);
+       if (old_type != data->psy_desc.type)
+               power_supply_changed(data->psy);
 
        return IRQ_HANDLED;
 }
@@ -143,17 +143,17 @@ static irqreturn_t max8903_usbin(int irq, void *_data)
        dev_dbg(data->dev, "USB Charger %s.\n", usb_in ?
                        "Connected" : "Disconnected");
 
-       old_type = data->psy.type;
+       old_type = data->psy_desc.type;
 
        if (data->ta_in)
-               data->psy.type = POWER_SUPPLY_TYPE_MAINS;
+               data->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
        else if (data->usb_in)
-               data->psy.type = POWER_SUPPLY_TYPE_USB;
+               data->psy_desc.type = POWER_SUPPLY_TYPE_USB;
        else
-               data->psy.type = POWER_SUPPLY_TYPE_BATTERY;
+               data->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
 
-       if (old_type != data->psy.type)
-               power_supply_changed(&data->psy);
+       if (old_type != data->psy_desc.type)
+               power_supply_changed(data->psy);
 
        return IRQ_HANDLED;
 }
@@ -184,6 +184,7 @@ static int max8903_probe(struct platform_device *pdev)
        struct max8903_data *data;
        struct device *dev = &pdev->dev;
        struct max8903_pdata *pdata = pdev->dev.platform_data;
+       struct power_supply_config psy_cfg = {};
        int ret = 0;
        int gpio;
        int ta_in = 0;
@@ -280,17 +281,20 @@ static int max8903_probe(struct platform_device *pdev)
        data->ta_in = ta_in;
        data->usb_in = usb_in;
 
-       data->psy.name = "max8903_charger";
-       data->psy.type = (ta_in) ? POWER_SUPPLY_TYPE_MAINS :
+       data->psy_desc.name = "max8903_charger";
+       data->psy_desc.type = (ta_in) ? POWER_SUPPLY_TYPE_MAINS :
                        ((usb_in) ? POWER_SUPPLY_TYPE_USB :
                         POWER_SUPPLY_TYPE_BATTERY);
-       data->psy.get_property = max8903_get_property;
-       data->psy.properties = max8903_charger_props;
-       data->psy.num_properties = ARRAY_SIZE(max8903_charger_props);
+       data->psy_desc.get_property = max8903_get_property;
+       data->psy_desc.properties = max8903_charger_props;
+       data->psy_desc.num_properties = ARRAY_SIZE(max8903_charger_props);
 
-       ret = power_supply_register(dev, &data->psy);
-       if (ret) {
+       psy_cfg.drv_data = data;
+
+       data->psy = power_supply_register(dev, &data->psy_desc, &psy_cfg);
+       if (IS_ERR(data->psy)) {
                dev_err(dev, "failed: power supply register.\n");
+               ret = PTR_ERR(data->psy);
                goto err;
        }
 
@@ -339,7 +343,7 @@ err_dc_irq:
        if (pdata->dc_valid)
                free_irq(gpio_to_irq(pdata->dok), data);
 err_psy:
-       power_supply_unregister(&data->psy);
+       power_supply_unregister(data->psy);
 err:
        return ret;
 }
@@ -357,7 +361,7 @@ static int max8903_remove(struct platform_device *pdev)
                        free_irq(gpio_to_irq(pdata->uok), data);
                if (pdata->dc_valid)
                        free_irq(gpio_to_irq(pdata->dok), data);
-               power_supply_unregister(&data->psy);
+               power_supply_unregister(data->psy);
        }
 
        return 0;
index a6d45eef64dda574a6ab1b6db41af43c9e748e4c..57eb5c2bfc212b5ff643f9cda13d95eb06ece526 100644 (file)
@@ -68,9 +68,9 @@ struct max8925_power_info {
        struct i2c_client       *gpm;
        struct i2c_client       *adc;
 
-       struct power_supply     ac;
-       struct power_supply     usb;
-       struct power_supply     battery;
+       struct power_supply     *ac;
+       struct power_supply     *usb;
+       struct power_supply     *battery;
        int                     irq_base;
        unsigned                ac_online:1;
        unsigned                usb_online:1;
@@ -196,7 +196,7 @@ static int max8925_ac_get_prop(struct power_supply *psy,
                               enum power_supply_property psp,
                               union power_supply_propval *val)
 {
-       struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
+       struct max8925_power_info *info = dev_get_drvdata(psy->dev.parent);
        int ret = 0;
 
        switch (psp) {
@@ -230,7 +230,7 @@ static int max8925_usb_get_prop(struct power_supply *psy,
                                enum power_supply_property psp,
                                union power_supply_propval *val)
 {
-       struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
+       struct max8925_power_info *info = dev_get_drvdata(psy->dev.parent);
        int ret = 0;
 
        switch (psp) {
@@ -264,7 +264,7 @@ static int max8925_bat_get_prop(struct power_supply *psy,
                                enum power_supply_property psp,
                                union power_supply_propval *val)
 {
-       struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
+       struct max8925_power_info *info = dev_get_drvdata(psy->dev.parent);
        int ret = 0;
 
        switch (psp) {
@@ -347,6 +347,30 @@ static enum power_supply_property max8925_battery_props[] = {
        POWER_SUPPLY_PROP_STATUS,
 };
 
+static const struct power_supply_desc ac_desc = {
+       .name           = "max8925-ac",
+       .type           = POWER_SUPPLY_TYPE_MAINS,
+       .properties     = max8925_ac_props,
+       .num_properties = ARRAY_SIZE(max8925_ac_props),
+       .get_property   = max8925_ac_get_prop,
+};
+
+static const struct power_supply_desc usb_desc = {
+       .name           = "max8925-usb",
+       .type           = POWER_SUPPLY_TYPE_USB,
+       .properties     = max8925_usb_props,
+       .num_properties = ARRAY_SIZE(max8925_usb_props),
+       .get_property   = max8925_usb_get_prop,
+};
+
+static const struct power_supply_desc battery_desc = {
+       .name           = "max8925-battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .properties     = max8925_battery_props,
+       .num_properties = ARRAY_SIZE(max8925_battery_props),
+       .get_property   = max8925_bat_get_prop,
+};
+
 #define REQUEST_IRQ(_irq, _name)                                       \
 do {                                                                   \
        ret = request_threaded_irq(chip->irq_base + _irq, NULL,         \
@@ -482,6 +506,7 @@ max8925_power_dt_init(struct platform_device *pdev)
 static int max8925_power_probe(struct platform_device *pdev)
 {
        struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+       struct power_supply_config psy_cfg = {}; /* Only for ac and usb */
        struct max8925_power_pdata *pdata = NULL;
        struct max8925_power_info *info;
        int ret;
@@ -502,40 +527,29 @@ static int max8925_power_probe(struct platform_device *pdev)
        info->adc = chip->adc;
        platform_set_drvdata(pdev, info);
 
-       info->ac.name = "max8925-ac";
-       info->ac.type = POWER_SUPPLY_TYPE_MAINS;
-       info->ac.properties = max8925_ac_props;
-       info->ac.num_properties = ARRAY_SIZE(max8925_ac_props);
-       info->ac.get_property = max8925_ac_get_prop;
-       info->ac.supplied_to = pdata->supplied_to;
-       info->ac.num_supplicants = pdata->num_supplicants;
-       ret = power_supply_register(&pdev->dev, &info->ac);
-       if (ret)
+       psy_cfg.supplied_to = pdata->supplied_to;
+       psy_cfg.num_supplicants = pdata->num_supplicants;
+
+       info->ac = power_supply_register(&pdev->dev, &ac_desc, &psy_cfg);
+       if (IS_ERR(info->ac)) {
+               ret = PTR_ERR(info->ac);
                goto out;
-       info->ac.dev->parent = &pdev->dev;
-
-       info->usb.name = "max8925-usb";
-       info->usb.type = POWER_SUPPLY_TYPE_USB;
-       info->usb.properties = max8925_usb_props;
-       info->usb.num_properties = ARRAY_SIZE(max8925_usb_props);
-       info->usb.get_property = max8925_usb_get_prop;
-       info->usb.supplied_to = pdata->supplied_to;
-       info->usb.num_supplicants = pdata->num_supplicants;
-
-       ret = power_supply_register(&pdev->dev, &info->usb);
-       if (ret)
+       }
+       info->ac->dev.parent = &pdev->dev;
+
+       info->usb = power_supply_register(&pdev->dev, &usb_desc, &psy_cfg);
+       if (IS_ERR(info->usb)) {
+               ret = PTR_ERR(info->usb);
                goto out_usb;
-       info->usb.dev->parent = &pdev->dev;
-
-       info->battery.name = "max8925-battery";
-       info->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-       info->battery.properties = max8925_battery_props;
-       info->battery.num_properties = ARRAY_SIZE(max8925_battery_props);
-       info->battery.get_property = max8925_bat_get_prop;
-       ret = power_supply_register(&pdev->dev, &info->battery);
-       if (ret)
+       }
+       info->usb->dev.parent = &pdev->dev;
+
+       info->battery = power_supply_register(&pdev->dev, &battery_desc, NULL);
+       if (IS_ERR(info->battery)) {
+               ret = PTR_ERR(info->battery);
                goto out_battery;
-       info->battery.dev->parent = &pdev->dev;
+       }
+       info->battery->dev.parent = &pdev->dev;
 
        info->batt_detect = pdata->batt_detect;
        info->topoff_threshold = pdata->topoff_threshold;
@@ -547,9 +561,9 @@ static int max8925_power_probe(struct platform_device *pdev)
        max8925_init_charger(chip, info);
        return 0;
 out_battery:
-       power_supply_unregister(&info->battery);
+       power_supply_unregister(info->battery);
 out_usb:
-       power_supply_unregister(&info->ac);
+       power_supply_unregister(info->ac);
 out:
        return ret;
 }
@@ -559,9 +573,9 @@ static int max8925_power_remove(struct platform_device *pdev)
        struct max8925_power_info *info = platform_get_drvdata(pdev);
 
        if (info) {
-               power_supply_unregister(&info->ac);
-               power_supply_unregister(&info->usb);
-               power_supply_unregister(&info->battery);
+               power_supply_unregister(info->ac);
+               power_supply_unregister(info->usb);
+               power_supply_unregister(info->battery);
                max8925_deinit_charger(info);
        }
        return 0;
index aefa0c9a3007dcd729859542900f902801719286..0b2eab571528eaed9cbe08fb47c90e313049f01c 100644 (file)
@@ -30,7 +30,7 @@
 struct charger_data {
        struct device *dev;
        struct max8997_dev *iodev;
-       struct power_supply battery;
+       struct power_supply *battery;
 };
 
 static enum power_supply_property max8997_battery_props[] = {
@@ -44,8 +44,7 @@ static int max8997_battery_get_property(struct power_supply *psy,
                enum power_supply_property psp,
                union power_supply_propval *val)
 {
-       struct charger_data *charger = container_of(psy,
-                       struct charger_data, battery);
+       struct charger_data *charger = power_supply_get_drvdata(psy);
        struct i2c_client *i2c = charger->iodev->i2c;
        int ret;
        u8 reg;
@@ -86,12 +85,21 @@ static int max8997_battery_get_property(struct power_supply *psy,
        return 0;
 }
 
+static const struct power_supply_desc max8997_battery_desc = {
+       .name           = "max8997_pmic",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .get_property   = max8997_battery_get_property,
+       .properties     = max8997_battery_props,
+       .num_properties = ARRAY_SIZE(max8997_battery_props),
+};
+
 static int max8997_battery_probe(struct platform_device *pdev)
 {
        int ret = 0;
        struct charger_data *charger;
        struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+       struct power_supply_config psy_cfg = {};
 
        if (!pdata)
                return -EINVAL;
@@ -147,19 +155,18 @@ static int max8997_battery_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, charger);
 
-       charger->battery.name = "max8997_pmic";
-       charger->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-       charger->battery.get_property = max8997_battery_get_property;
-       charger->battery.properties = max8997_battery_props;
-       charger->battery.num_properties = ARRAY_SIZE(max8997_battery_props);
 
        charger->dev = &pdev->dev;
        charger->iodev = iodev;
 
-       ret = power_supply_register(&pdev->dev, &charger->battery);
-       if (ret) {
+       psy_cfg.drv_data = charger;
+
+       charger->battery = power_supply_register(&pdev->dev,
+                                                &max8997_battery_desc,
+                                                &psy_cfg);
+       if (IS_ERR(charger->battery)) {
                dev_err(&pdev->dev, "failed: power supply register\n");
-               return ret;
+               return PTR_ERR(charger->battery);
        }
 
        return 0;
@@ -169,7 +176,7 @@ static int max8997_battery_remove(struct platform_device *pdev)
 {
        struct charger_data *charger = platform_get_drvdata(pdev);
 
-       power_supply_unregister(&charger->battery);
+       power_supply_unregister(charger->battery);
        return 0;
 }
 
index 08694c7a9f38c1823885206fac0b14528599bd01..47448d4bc6cd3a1fccba042ed1588564b2c1bcf1 100644 (file)
@@ -30,7 +30,7 @@
 struct max8998_battery_data {
        struct device *dev;
        struct max8998_dev *iodev;
-       struct power_supply battery;
+       struct power_supply *battery;
 };
 
 static enum power_supply_property max8998_battery_props[] = {
@@ -43,8 +43,7 @@ static int max8998_battery_get_property(struct power_supply *psy,
                enum power_supply_property psp,
                union power_supply_propval *val)
 {
-       struct max8998_battery_data *max8998 = container_of(psy,
-                       struct max8998_battery_data, battery);
+       struct max8998_battery_data *max8998 = power_supply_get_drvdata(psy);
        struct i2c_client *i2c = max8998->iodev->i2c;
        int ret;
        u8 reg;
@@ -75,10 +74,19 @@ static int max8998_battery_get_property(struct power_supply *psy,
        return 0;
 }
 
+static const struct power_supply_desc max8998_battery_desc = {
+       .name           = "max8998_pmic",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .get_property   = max8998_battery_get_property,
+       .properties     = max8998_battery_props,
+       .num_properties = ARRAY_SIZE(max8998_battery_props),
+};
+
 static int max8998_battery_probe(struct platform_device *pdev)
 {
        struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
+       struct power_supply_config psy_cfg = {};
        struct max8998_battery_data *max8998;
        struct i2c_client *i2c;
        int ret = 0;
@@ -161,15 +169,15 @@ static int max8998_battery_probe(struct platform_device *pdev)
                goto err;
        }
 
-       max8998->battery.name = "max8998_pmic";
-       max8998->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-       max8998->battery.get_property = max8998_battery_get_property;
-       max8998->battery.properties = max8998_battery_props;
-       max8998->battery.num_properties = ARRAY_SIZE(max8998_battery_props);
+       psy_cfg.drv_data = max8998;
 
-       ret = power_supply_register(max8998->dev, &max8998->battery);
-       if (ret) {
-               dev_err(max8998->dev, "failed: power supply register\n");
+       max8998->battery = power_supply_register(max8998->dev,
+                                                &max8998_battery_desc,
+                                                &psy_cfg);
+       if (IS_ERR(max8998->battery)) {
+               ret = PTR_ERR(max8998->battery);
+               dev_err(max8998->dev, "failed: power supply register: %d\n",
+                       ret);
                goto err;
        }
 
@@ -182,7 +190,7 @@ static int max8998_battery_remove(struct platform_device *pdev)
 {
        struct max8998_battery_data *max8998 = platform_get_drvdata(pdev);
 
-       power_supply_unregister(&max8998->battery);
+       power_supply_unregister(max8998->battery);
 
        return 0;
 }
index ad9cde705de1071ba748dfaec3b59ea1f70e3cb9..a944338a39de406d80d932c31babebbb50731318 100644 (file)
@@ -81,7 +81,7 @@ static enum power_supply_property olpc_ac_props[] = {
        POWER_SUPPLY_PROP_ONLINE,
 };
 
-static struct power_supply olpc_ac = {
+static const struct power_supply_desc olpc_ac_desc = {
        .name = "olpc-ac",
        .type = POWER_SUPPLY_TYPE_MAINS,
        .properties = olpc_ac_props,
@@ -89,6 +89,8 @@ static struct power_supply olpc_ac = {
        .get_property = olpc_ac_get_prop,
 };
 
+static struct power_supply *olpc_ac;
+
 static char bat_serial[17]; /* Ick */
 
 static int olpc_bat_get_status(union power_supply_propval *val, uint8_t ec_byte)
@@ -574,21 +576,23 @@ static struct device_attribute olpc_bat_error = {
  *             Initialisation
  *********************************************************************/
 
-static struct power_supply olpc_bat = {
+static struct power_supply_desc olpc_bat_desc = {
        .name = "olpc-battery",
        .get_property = olpc_bat_get_property,
        .use_for_apm = 1,
 };
 
+static struct power_supply *olpc_bat;
+
 static int olpc_battery_suspend(struct platform_device *pdev,
                                pm_message_t state)
 {
-       if (device_may_wakeup(olpc_ac.dev))
+       if (device_may_wakeup(&olpc_ac->dev))
                olpc_ec_wakeup_set(EC_SCI_SRC_ACPWR);
        else
                olpc_ec_wakeup_clear(EC_SCI_SRC_ACPWR);
 
-       if (device_may_wakeup(olpc_bat.dev))
+       if (device_may_wakeup(&olpc_bat->dev))
                olpc_ec_wakeup_set(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC
                                   | EC_SCI_SRC_BATERR);
        else
@@ -619,52 +623,54 @@ static int olpc_battery_probe(struct platform_device *pdev)
 
        /* Ignore the status. It doesn't actually matter */
 
-       ret = power_supply_register(&pdev->dev, &olpc_ac);
-       if (ret)
-               return ret;
+       olpc_ac = power_supply_register(&pdev->dev, &olpc_ac_desc, NULL);
+       if (IS_ERR(olpc_ac))
+               return PTR_ERR(olpc_ac);
 
        if (olpc_board_at_least(olpc_board_pre(0xd0))) { /* XO-1.5 */
-               olpc_bat.properties = olpc_xo15_bat_props;
-               olpc_bat.num_properties = ARRAY_SIZE(olpc_xo15_bat_props);
+               olpc_bat_desc.properties = olpc_xo15_bat_props;
+               olpc_bat_desc.num_properties = ARRAY_SIZE(olpc_xo15_bat_props);
        } else { /* XO-1 */
-               olpc_bat.properties = olpc_xo1_bat_props;
-               olpc_bat.num_properties = ARRAY_SIZE(olpc_xo1_bat_props);
+               olpc_bat_desc.properties = olpc_xo1_bat_props;
+               olpc_bat_desc.num_properties = ARRAY_SIZE(olpc_xo1_bat_props);
        }
 
-       ret = power_supply_register(&pdev->dev, &olpc_bat);
-       if (ret)
+       olpc_bat = power_supply_register(&pdev->dev, &olpc_bat_desc, NULL);
+       if (IS_ERR(olpc_bat)) {
+               ret = PTR_ERR(olpc_bat);
                goto battery_failed;
+       }
 
-       ret = device_create_bin_file(olpc_bat.dev, &olpc_bat_eeprom);
+       ret = device_create_bin_file(&olpc_bat->dev, &olpc_bat_eeprom);
        if (ret)
                goto eeprom_failed;
 
-       ret = device_create_file(olpc_bat.dev, &olpc_bat_error);
+       ret = device_create_file(&olpc_bat->dev, &olpc_bat_error);
        if (ret)
                goto error_failed;
 
        if (olpc_ec_wakeup_available()) {
-               device_set_wakeup_capable(olpc_ac.dev, true);
-               device_set_wakeup_capable(olpc_bat.dev, true);
+               device_set_wakeup_capable(&olpc_ac->dev, true);
+               device_set_wakeup_capable(&olpc_bat->dev, true);
        }
 
        return 0;
 
 error_failed:
-       device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom);
+       device_remove_bin_file(&olpc_bat->dev, &olpc_bat_eeprom);
 eeprom_failed:
-       power_supply_unregister(&olpc_bat);
+       power_supply_unregister(olpc_bat);
 battery_failed:
-       power_supply_unregister(&olpc_ac);
+       power_supply_unregister(olpc_ac);
        return ret;
 }
 
 static int olpc_battery_remove(struct platform_device *pdev)
 {
-       device_remove_file(olpc_bat.dev, &olpc_bat_error);
-       device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom);
-       power_supply_unregister(&olpc_bat);
-       power_supply_unregister(&olpc_ac);
+       device_remove_file(&olpc_bat->dev, &olpc_bat_error);
+       device_remove_bin_file(&olpc_bat->dev, &olpc_bat_eeprom);
+       power_supply_unregister(olpc_bat);
+       power_supply_unregister(olpc_ac);
        return 0;
 }
 
index 771c4f0fb8ac620a2f64654319a539990cfd1617..d05597b4e40f5a613271f8bf0021560508e15997 100644 (file)
@@ -33,9 +33,9 @@ struct pcf50633_mbc {
        int adapter_online;
        int usb_online;
 
-       struct power_supply usb;
-       struct power_supply adapter;
-       struct power_supply ac;
+       struct power_supply *usb;
+       struct power_supply *adapter;
+       struct power_supply *ac;
 };
 
 int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
@@ -104,7 +104,7 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
                                PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA);
        }
 
-       power_supply_changed(&mbc->usb);
+       power_supply_changed(mbc->usb);
 
        return ret;
 }
@@ -278,9 +278,9 @@ pcf50633_mbc_irq_handler(int irq, void *data)
        else if (irq == PCF50633_IRQ_ADPREM)
                mbc->adapter_online = 0;
 
-       power_supply_changed(&mbc->ac);
-       power_supply_changed(&mbc->usb);
-       power_supply_changed(&mbc->adapter);
+       power_supply_changed(mbc->ac);
+       power_supply_changed(mbc->usb);
+       power_supply_changed(mbc->adapter);
 
        if (mbc->pcf->pdata->mbc_event_callback)
                mbc->pcf->pdata->mbc_event_callback(mbc->pcf, irq);
@@ -290,8 +290,7 @@ static int adapter_get_property(struct power_supply *psy,
                        enum power_supply_property psp,
                        union power_supply_propval *val)
 {
-       struct pcf50633_mbc *mbc = container_of(psy,
-                               struct pcf50633_mbc, adapter);
+       struct pcf50633_mbc *mbc = power_supply_get_drvdata(psy);
        int ret = 0;
 
        switch (psp) {
@@ -309,7 +308,7 @@ static int usb_get_property(struct power_supply *psy,
                        enum power_supply_property psp,
                        union power_supply_propval *val)
 {
-       struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb);
+       struct pcf50633_mbc *mbc = power_supply_get_drvdata(psy);
        int ret = 0;
        u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) &
                                                PCF50633_MBCC7_USB_MASK;
@@ -330,7 +329,7 @@ static int ac_get_property(struct power_supply *psy,
                        enum power_supply_property psp,
                        union power_supply_propval *val)
 {
-       struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, ac);
+       struct pcf50633_mbc *mbc = power_supply_get_drvdata(psy);
        int ret = 0;
        u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) &
                                                PCF50633_MBCC7_USB_MASK;
@@ -366,8 +365,33 @@ static const u8 mbc_irq_handlers[] = {
        PCF50633_IRQ_LOWBAT,
 };
 
+static const struct power_supply_desc pcf50633_mbc_adapter_desc = {
+       .name           = "adapter",
+       .type           = POWER_SUPPLY_TYPE_MAINS,
+       .properties     = power_props,
+       .num_properties = ARRAY_SIZE(power_props),
+       .get_property   = &adapter_get_property,
+};
+
+static const struct power_supply_desc pcf50633_mbc_usb_desc = {
+       .name           = "usb",
+       .type           = POWER_SUPPLY_TYPE_USB,
+       .properties     = power_props,
+       .num_properties = ARRAY_SIZE(power_props),
+       .get_property   = usb_get_property,
+};
+
+static const struct power_supply_desc pcf50633_mbc_ac_desc = {
+       .name           = "ac",
+       .type           = POWER_SUPPLY_TYPE_MAINS,
+       .properties     = power_props,
+       .num_properties = ARRAY_SIZE(power_props),
+       .get_property   = ac_get_property,
+};
+
 static int pcf50633_mbc_probe(struct platform_device *pdev)
 {
+       struct power_supply_config psy_cfg = {};
        struct pcf50633_mbc *mbc;
        int ret;
        int i;
@@ -385,49 +409,36 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
                pcf50633_register_irq(mbc->pcf, mbc_irq_handlers[i],
                                        pcf50633_mbc_irq_handler, mbc);
 
+       psy_cfg.supplied_to             = mbc->pcf->pdata->batteries;
+       psy_cfg.num_supplicants         = mbc->pcf->pdata->num_batteries;
+       psy_cfg.drv_data                = mbc;
+
        /* Create power supplies */
-       mbc->adapter.name               = "adapter";
-       mbc->adapter.type               = POWER_SUPPLY_TYPE_MAINS;
-       mbc->adapter.properties         = power_props;
-       mbc->adapter.num_properties     = ARRAY_SIZE(power_props);
-       mbc->adapter.get_property       = &adapter_get_property;
-       mbc->adapter.supplied_to        = mbc->pcf->pdata->batteries;
-       mbc->adapter.num_supplicants    = mbc->pcf->pdata->num_batteries;
-
-       mbc->usb.name                   = "usb";
-       mbc->usb.type                   = POWER_SUPPLY_TYPE_USB;
-       mbc->usb.properties             = power_props;
-       mbc->usb.num_properties         = ARRAY_SIZE(power_props);
-       mbc->usb.get_property           = usb_get_property;
-       mbc->usb.supplied_to            = mbc->pcf->pdata->batteries;
-       mbc->usb.num_supplicants        = mbc->pcf->pdata->num_batteries;
-
-       mbc->ac.name                    = "ac";
-       mbc->ac.type                    = POWER_SUPPLY_TYPE_MAINS;
-       mbc->ac.properties              = power_props;
-       mbc->ac.num_properties          = ARRAY_SIZE(power_props);
-       mbc->ac.get_property            = ac_get_property;
-       mbc->ac.supplied_to             = mbc->pcf->pdata->batteries;
-       mbc->ac.num_supplicants         = mbc->pcf->pdata->num_batteries;
-
-       ret = power_supply_register(&pdev->dev, &mbc->adapter);
-       if (ret) {
+       mbc->adapter = power_supply_register(&pdev->dev,
+                                            &pcf50633_mbc_adapter_desc,
+                                            &psy_cfg);
+       if (IS_ERR(mbc->adapter)) {
                dev_err(mbc->pcf->dev, "failed to register adapter\n");
+               ret = PTR_ERR(mbc->adapter);
                return ret;
        }
 
-       ret = power_supply_register(&pdev->dev, &mbc->usb);
-       if (ret) {
+       mbc->usb = power_supply_register(&pdev->dev, &pcf50633_mbc_usb_desc,
+                                        &psy_cfg);
+       if (IS_ERR(mbc->usb)) {
                dev_err(mbc->pcf->dev, "failed to register usb\n");
-               power_supply_unregister(&mbc->adapter);
+               power_supply_unregister(mbc->adapter);
+               ret = PTR_ERR(mbc->usb);
                return ret;
        }
 
-       ret = power_supply_register(&pdev->dev, &mbc->ac);
-       if (ret) {
+       mbc->ac = power_supply_register(&pdev->dev, &pcf50633_mbc_ac_desc,
+                                       &psy_cfg);
+       if (IS_ERR(mbc->ac)) {
                dev_err(mbc->pcf->dev, "failed to register ac\n");
-               power_supply_unregister(&mbc->adapter);
-               power_supply_unregister(&mbc->usb);
+               power_supply_unregister(mbc->adapter);
+               power_supply_unregister(mbc->usb);
+               ret = PTR_ERR(mbc->ac);
                return ret;
        }
 
@@ -454,9 +465,9 @@ static int pcf50633_mbc_remove(struct platform_device *pdev)
                pcf50633_free_irq(mbc->pcf, mbc_irq_handlers[i]);
 
        sysfs_remove_group(&pdev->dev.kobj, &mbc_attr_group);
-       power_supply_unregister(&mbc->usb);
-       power_supply_unregister(&mbc->adapter);
-       power_supply_unregister(&mbc->ac);
+       power_supply_unregister(mbc->usb);
+       power_supply_unregister(mbc->adapter);
+       power_supply_unregister(mbc->ac);
 
        return 0;
 }
index 0c52e2a0d90cdba166a5cdfda72f70d86f5a2572..dfe1ee89f7c7ad06fc014b3986c240904329e6ba 100644 (file)
@@ -34,6 +34,7 @@ static struct timer_list charger_timer;
 static struct timer_list supply_timer;
 static struct timer_list polling_timer;
 static int polling;
+static struct power_supply *pda_psy_ac, *pda_psy_usb;
 
 #if IS_ENABLED(CONFIG_USB_PHY)
 static struct usb_phy *transceiver;
@@ -58,7 +59,7 @@ static int pda_power_get_property(struct power_supply *psy,
 {
        switch (psp) {
        case POWER_SUPPLY_PROP_ONLINE:
-               if (psy->type == POWER_SUPPLY_TYPE_MAINS)
+               if (psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
                        val->intval = pdata->is_ac_online ?
                                      pdata->is_ac_online() : 0;
                else
@@ -80,21 +81,17 @@ static char *pda_power_supplied_to[] = {
        "backup-battery",
 };
 
-static struct power_supply pda_psy_ac = {
+static const struct power_supply_desc pda_psy_ac_desc = {
        .name = "ac",
        .type = POWER_SUPPLY_TYPE_MAINS,
-       .supplied_to = pda_power_supplied_to,
-       .num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
        .properties = pda_power_props,
        .num_properties = ARRAY_SIZE(pda_power_props),
        .get_property = pda_power_get_property,
 };
 
-static struct power_supply pda_psy_usb = {
+static const struct power_supply_desc pda_psy_usb_desc = {
        .name = "usb",
        .type = POWER_SUPPLY_TYPE_USB,
-       .supplied_to = pda_power_supplied_to,
-       .num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
        .properties = pda_power_props,
        .num_properties = ARRAY_SIZE(pda_power_props),
        .get_property = pda_power_get_property,
@@ -147,12 +144,12 @@ static void supply_timer_func(unsigned long unused)
 {
        if (ac_status == PDA_PSY_TO_CHANGE) {
                ac_status = new_ac_status;
-               power_supply_changed(&pda_psy_ac);
+               power_supply_changed(pda_psy_ac);
        }
 
        if (usb_status == PDA_PSY_TO_CHANGE) {
                usb_status = new_usb_status;
-               power_supply_changed(&pda_psy_usb);
+               power_supply_changed(pda_psy_usb);
        }
 }
 
@@ -176,9 +173,9 @@ static void charger_timer_func(unsigned long unused)
 
 static irqreturn_t power_changed_isr(int irq, void *power_supply)
 {
-       if (power_supply == &pda_psy_ac)
+       if (power_supply == pda_psy_ac)
                ac_status = PDA_PSY_TO_CHANGE;
-       else if (power_supply == &pda_psy_usb)
+       else if (power_supply == pda_psy_usb)
                usb_status = PDA_PSY_TO_CHANGE;
        else
                return IRQ_NONE;
@@ -262,6 +259,7 @@ static int otg_handle_notification(struct notifier_block *nb,
 
 static int pda_power_probe(struct platform_device *pdev)
 {
+       struct power_supply_config psy_cfg = {};
        int ret = 0;
 
        dev = &pdev->dev;
@@ -309,10 +307,11 @@ static int pda_power_probe(struct platform_device *pdev)
        usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");
 
        if (pdata->supplied_to) {
-               pda_psy_ac.supplied_to = pdata->supplied_to;
-               pda_psy_ac.num_supplicants = pdata->num_supplicants;
-               pda_psy_usb.supplied_to = pdata->supplied_to;
-               pda_psy_usb.num_supplicants = pdata->num_supplicants;
+               psy_cfg.supplied_to = pdata->supplied_to;
+               psy_cfg.num_supplicants = pdata->num_supplicants;
+       } else {
+               psy_cfg.supplied_to = pda_power_supplied_to;
+               psy_cfg.num_supplicants = ARRAY_SIZE(pda_power_supplied_to);
        }
 
 #if IS_ENABLED(CONFIG_USB_PHY)
@@ -326,17 +325,19 @@ static int pda_power_probe(struct platform_device *pdev)
 #endif
 
        if (pdata->is_ac_online) {
-               ret = power_supply_register(&pdev->dev, &pda_psy_ac);
-               if (ret) {
+               pda_psy_ac = power_supply_register(&pdev->dev,
+                                                  &pda_psy_ac_desc, &psy_cfg);
+               if (IS_ERR(pda_psy_ac)) {
                        dev_err(dev, "failed to register %s power supply\n",
-                               pda_psy_ac.name);
+                               pda_psy_ac_desc.name);
+                       ret = PTR_ERR(pda_psy_ac);
                        goto ac_supply_failed;
                }
 
                if (ac_irq) {
                        ret = request_irq(ac_irq->start, power_changed_isr,
                                          get_irq_flags(ac_irq), ac_irq->name,
-                                         &pda_psy_ac);
+                                         pda_psy_ac);
                        if (ret) {
                                dev_err(dev, "request ac irq failed\n");
                                goto ac_irq_failed;
@@ -347,17 +348,20 @@ static int pda_power_probe(struct platform_device *pdev)
        }
 
        if (pdata->is_usb_online) {
-               ret = power_supply_register(&pdev->dev, &pda_psy_usb);
-               if (ret) {
+               pda_psy_usb = power_supply_register(&pdev->dev,
+                                                   &pda_psy_usb_desc,
+                                                   &psy_cfg);
+               if (IS_ERR(pda_psy_usb)) {
                        dev_err(dev, "failed to register %s power supply\n",
-                               pda_psy_usb.name);
+                               pda_psy_usb_desc.name);
+                       ret = PTR_ERR(pda_psy_usb);
                        goto usb_supply_failed;
                }
 
                if (usb_irq) {
                        ret = request_irq(usb_irq->start, power_changed_isr,
                                          get_irq_flags(usb_irq),
-                                         usb_irq->name, &pda_psy_usb);
+                                         usb_irq->name, pda_psy_usb);
                        if (ret) {
                                dev_err(dev, "request usb irq failed\n");
                                goto usb_irq_failed;
@@ -394,21 +398,21 @@ static int pda_power_probe(struct platform_device *pdev)
 #if IS_ENABLED(CONFIG_USB_PHY)
 otg_reg_notifier_failed:
        if (pdata->is_usb_online && usb_irq)
-               free_irq(usb_irq->start, &pda_psy_usb);
+               free_irq(usb_irq->start, pda_psy_usb);
 #endif
 usb_irq_failed:
        if (pdata->is_usb_online)
-               power_supply_unregister(&pda_psy_usb);
+               power_supply_unregister(pda_psy_usb);
 usb_supply_failed:
        if (pdata->is_ac_online && ac_irq)
-               free_irq(ac_irq->start, &pda_psy_ac);
+               free_irq(ac_irq->start, pda_psy_ac);
 #if IS_ENABLED(CONFIG_USB_PHY)
        if (!IS_ERR_OR_NULL(transceiver))
                usb_put_phy(transceiver);
 #endif
 ac_irq_failed:
        if (pdata->is_ac_online)
-               power_supply_unregister(&pda_psy_ac);
+               power_supply_unregister(pda_psy_ac);
 ac_supply_failed:
        if (ac_draw) {
                regulator_put(ac_draw);
@@ -424,9 +428,9 @@ wrongid:
 static int pda_power_remove(struct platform_device *pdev)
 {
        if (pdata->is_usb_online && usb_irq)
-               free_irq(usb_irq->start, &pda_psy_usb);
+               free_irq(usb_irq->start, pda_psy_usb);
        if (pdata->is_ac_online && ac_irq)
-               free_irq(ac_irq->start, &pda_psy_ac);
+               free_irq(ac_irq->start, pda_psy_ac);
 
        if (polling)
                del_timer_sync(&polling_timer);
@@ -434,9 +438,9 @@ static int pda_power_remove(struct platform_device *pdev)
        del_timer_sync(&supply_timer);
 
        if (pdata->is_usb_online)
-               power_supply_unregister(&pda_psy_usb);
+               power_supply_unregister(pda_psy_usb);
        if (pdata->is_ac_online)
-               power_supply_unregister(&pda_psy_ac);
+               power_supply_unregister(pda_psy_ac);
 #if IS_ENABLED(CONFIG_USB_PHY)
        if (!IS_ERR_OR_NULL(transceiver))
                usb_put_phy(transceiver);
index 777324992c59b225d8c6ac54eab47c97688b4bc0..cc0893ffbf7e66bc2d107b4ea708d04cf09a87b1 100644 (file)
@@ -216,7 +216,7 @@ static int pm2xxx_charger_ovv_mngt(struct pm2xxx_charger *pm2, int val)
 {
        dev_err(pm2->dev, "Overvoltage detected\n");
        pm2->flags.ovv = true;
-       power_supply_changed(&pm2->ac_chg.psy);
+       power_supply_changed(pm2->ac_chg.psy);
 
        /* Schedule a new HW failure check */
        queue_delayed_work(pm2->charger_wq, &pm2->check_hw_failure_work, 0);
@@ -229,7 +229,7 @@ static int pm2xxx_charger_wd_exp_mngt(struct pm2xxx_charger *pm2, int val)
        dev_dbg(pm2->dev , "20 minutes watchdog expired\n");
 
        pm2->ac.wd_expired = true;
-       power_supply_changed(&pm2->ac_chg.psy);
+       power_supply_changed(pm2->ac_chg.psy);
 
        return 0;
 }
@@ -573,7 +573,7 @@ static int pm2xxx_charger_update_charger_current(struct ux500_charger *charger,
        struct pm2xxx_charger *pm2;
        u8 val;
 
-       if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS)
+       if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
                pm2 = to_pm2xxx_charger_ac_device_info(charger);
        else
                return -ENXIO;
@@ -816,7 +816,7 @@ static int pm2xxx_charger_ac_en(struct ux500_charger *charger,
 
                dev_dbg(pm2->dev, "PM2301: " "Disabled AC charging\n");
        }
-       power_supply_changed(&pm2->ac_chg.psy);
+       power_supply_changed(pm2->ac_chg.psy);
 
 error_occured:
        return ret;
@@ -827,7 +827,7 @@ static int pm2xxx_charger_watchdog_kick(struct ux500_charger *charger)
        int ret;
        struct pm2xxx_charger *pm2;
 
-       if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS)
+       if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
                pm2 = to_pm2xxx_charger_ac_device_info(charger);
        else
                return -ENXIO;
@@ -845,8 +845,8 @@ static void pm2xxx_charger_ac_work(struct work_struct *work)
                struct pm2xxx_charger, ac_work);
 
 
-       power_supply_changed(&pm2->ac_chg.psy);
-       sysfs_notify(&pm2->ac_chg.psy.dev->kobj, NULL, "present");
+       power_supply_changed(pm2->ac_chg.psy);
+       sysfs_notify(&pm2->ac_chg.psy->dev.kobj, NULL, "present");
 };
 
 static void pm2xxx_charger_check_hw_failure_work(struct work_struct *work)
@@ -862,7 +862,7 @@ static void pm2xxx_charger_check_hw_failure_work(struct work_struct *work)
                if (!(reg_value & (PM2XXX_INT4_S_ITVPWR1OVV |
                                        PM2XXX_INT4_S_ITVPWR2OVV))) {
                        pm2->flags.ovv = false;
-                       power_supply_changed(&pm2->ac_chg.psy);
+                       power_supply_changed(pm2->ac_chg.psy);
                }
        }
 
@@ -895,7 +895,7 @@ static void pm2xxx_charger_check_main_thermal_prot_work(
                                | PM2XXX_INT5_S_ITTHERMALSHUTDOWNFALL))
                pm2->flags.main_thermal_prot = false;
 
-       power_supply_changed(&pm2->ac_chg.psy);
+       power_supply_changed(pm2->ac_chg.psy);
 }
 
 static struct pm2xxx_interrupts pm2xxx_int = {
@@ -989,6 +989,7 @@ static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
                const struct i2c_device_id *id)
 {
        struct pm2xxx_platform_data *pl_data = i2c_client->dev.platform_data;
+       struct power_supply_config psy_cfg = {};
        struct pm2xxx_charger *pm2;
        int ret = 0;
        u8 val;
@@ -1042,13 +1043,14 @@ static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
 
        /* AC supply */
        /* power_supply base class */
-       pm2->ac_chg.psy.name = pm2->pdata->label;
-       pm2->ac_chg.psy.type = POWER_SUPPLY_TYPE_MAINS;
-       pm2->ac_chg.psy.properties = pm2xxx_charger_ac_props;
-       pm2->ac_chg.psy.num_properties = ARRAY_SIZE(pm2xxx_charger_ac_props);
-       pm2->ac_chg.psy.get_property = pm2xxx_charger_ac_get_property;
-       pm2->ac_chg.psy.supplied_to = pm2->pdata->supplied_to;
-       pm2->ac_chg.psy.num_supplicants = pm2->pdata->num_supplicants;
+       pm2->ac_chg_desc.name = pm2->pdata->label;
+       pm2->ac_chg_desc.type = POWER_SUPPLY_TYPE_MAINS;
+       pm2->ac_chg_desc.properties = pm2xxx_charger_ac_props;
+       pm2->ac_chg_desc.num_properties = ARRAY_SIZE(pm2xxx_charger_ac_props);
+       pm2->ac_chg_desc.get_property = pm2xxx_charger_ac_get_property;
+
+       psy_cfg.supplied_to = pm2->pdata->supplied_to;
+       psy_cfg.num_supplicants = pm2->pdata->num_supplicants;
        /* pm2xxx_charger sub-class */
        pm2->ac_chg.ops.enable = &pm2xxx_charger_ac_en;
        pm2->ac_chg.ops.kick_wd = &pm2xxx_charger_watchdog_kick;
@@ -1093,9 +1095,11 @@ static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
        }
 
        /* Register AC charger class */
-       ret = power_supply_register(pm2->dev, &pm2->ac_chg.psy);
-       if (ret) {
+       pm2->ac_chg.psy = power_supply_register(pm2->dev, &pm2->ac_chg_desc,
+                                               &psy_cfg);
+       if (IS_ERR(pm2->ac_chg.psy)) {
                dev_err(pm2->dev, "failed to register AC charger\n");
+               ret = PTR_ERR(pm2->ac_chg.psy);
                goto free_regulator;
        }
 
@@ -1167,8 +1171,8 @@ static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
                ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
                                             AB8500_MAIN_CH_DET);
                pm2->ac_conn = true;
-               power_supply_changed(&pm2->ac_chg.psy);
-               sysfs_notify(&pm2->ac_chg.psy.dev->kobj, NULL, "present");
+               power_supply_changed(pm2->ac_chg.psy);
+               sysfs_notify(&pm2->ac_chg.psy->dev.kobj, NULL, "present");
        }
 
        return 0;
@@ -1183,7 +1187,7 @@ unregister_pm2xxx_interrupt:
        free_irq(gpio_to_irq(pm2->pdata->gpio_irq_number), pm2);
 unregister_pm2xxx_charger:
        /* unregister power supply */
-       power_supply_unregister(&pm2->ac_chg.psy);
+       power_supply_unregister(pm2->ac_chg.psy);
 free_regulator:
        /* disable the regulator */
        regulator_put(pm2->regu);
@@ -1218,7 +1222,7 @@ static int pm2xxx_wall_charger_remove(struct i2c_client *i2c_client)
        /* disable the regulator */
        regulator_put(pm2->regu);
 
-       power_supply_unregister(&pm2->ac_chg.psy);
+       power_supply_unregister(pm2->ac_chg.psy);
 
        if (gpio_is_valid(pm2->lpn_pin))
                gpio_free(pm2->lpn_pin);
index 8ce3cc0195df084e065c4c1d3ad0da55ce70b584..24181cf9717bef8c4a30f6d6f732057bb9536215 100644 (file)
@@ -486,6 +486,7 @@ struct pm2xxx_charger {
        struct work_struct check_main_thermal_prot_work;
        struct delayed_work check_hw_failure_work;
        struct ux500_charger ac_chg;
+       struct power_supply_desc ac_chg_desc;
        struct pm2xxx_charger_event_flags flags;
 };
 
index 023d24993b871de656da8a631b8f73fc827acbfc..9c8d5253812c64c1a50e757b019ff1d7731b3aea 100644 (file)
 #include <linux/slab.h>
 
 static struct pmu_battery_dev {
-       struct power_supply bat;
+       struct power_supply *bat;
+       struct power_supply_desc bat_desc;
        struct pmu_battery_info *pbi;
        char name[16];
        int propval;
 } *pbats[PMU_MAX_BATTERIES];
 
-#define to_pmu_battery_dev(x) container_of(x, struct pmu_battery_dev, bat)
+#define to_pmu_battery_dev(x) power_supply_get_drvdata(x)
 
 /*********************************************************************
  *             Power
@@ -49,7 +50,7 @@ static enum power_supply_property pmu_ac_props[] = {
        POWER_SUPPLY_PROP_ONLINE,
 };
 
-static struct power_supply pmu_ac = {
+static const struct power_supply_desc pmu_ac_desc = {
        .name = "pmu-ac",
        .type = POWER_SUPPLY_TYPE_MAINS,
        .properties = pmu_ac_props,
@@ -57,6 +58,8 @@ static struct power_supply pmu_ac = {
        .get_property = pmu_get_ac_prop,
 };
 
+static struct power_supply *pmu_ac;
+
 /*********************************************************************
  *             Battery properties
  *********************************************************************/
@@ -142,7 +145,7 @@ static struct platform_device *bat_pdev;
 
 static int __init pmu_bat_init(void)
 {
-       int ret;
+       int ret = 0;
        int i;
 
        bat_pdev = platform_device_register_simple("pmu-battery",
@@ -152,25 +155,32 @@ static int __init pmu_bat_init(void)
                goto pdev_register_failed;
        }
 
-       ret = power_supply_register(&bat_pdev->dev, &pmu_ac);
-       if (ret)
+       pmu_ac = power_supply_register(&bat_pdev->dev, &pmu_ac_desc, NULL);
+       if (IS_ERR(pmu_ac)) {
+               ret = PTR_ERR(pmu_ac);
                goto ac_register_failed;
+       }
 
        for (i = 0; i < pmu_battery_count; i++) {
+               struct power_supply_config psy_cfg = {};
                struct pmu_battery_dev *pbat = kzalloc(sizeof(*pbat),
                                                       GFP_KERNEL);
                if (!pbat)
                        break;
 
                sprintf(pbat->name, "PMU_battery_%d", i);
-               pbat->bat.name = pbat->name;
-               pbat->bat.properties = pmu_bat_props;
-               pbat->bat.num_properties = ARRAY_SIZE(pmu_bat_props);
-               pbat->bat.get_property = pmu_bat_get_property;
+               pbat->bat_desc.name = pbat->name;
+               pbat->bat_desc.properties = pmu_bat_props;
+               pbat->bat_desc.num_properties = ARRAY_SIZE(pmu_bat_props);
+               pbat->bat_desc.get_property = pmu_bat_get_property;
                pbat->pbi = &pmu_batteries[i];
+               psy_cfg.drv_data = pbat;
 
-               ret = power_supply_register(&bat_pdev->dev, &pbat->bat);
-               if (ret) {
+               pbat->bat = power_supply_register(&bat_pdev->dev,
+                                                 &pbat->bat_desc,
+                                                 &psy_cfg);
+               if (IS_ERR(pbat->bat)) {
+                       ret = PTR_ERR(pbat->bat);
                        kfree(pbat);
                        goto battery_register_failed;
                }
@@ -183,10 +193,10 @@ battery_register_failed:
        while (i--) {
                if (!pbats[i])
                        continue;
-               power_supply_unregister(&pbats[i]->bat);
+               power_supply_unregister(pbats[i]->bat);
                kfree(pbats[i]);
        }
-       power_supply_unregister(&pmu_ac);
+       power_supply_unregister(pmu_ac);
 ac_register_failed:
        platform_device_unregister(bat_pdev);
 pdev_register_failed:
@@ -201,10 +211,10 @@ static void __exit pmu_bat_exit(void)
        for (i = 0; i < PMU_MAX_BATTERIES; i++) {
                if (!pbats[i])
                        continue;
-               power_supply_unregister(&pbats[i]->bat);
+               power_supply_unregister(pbats[i]->bat);
                kfree(pbats[i]);
        }
-       power_supply_unregister(&pmu_ac);
+       power_supply_unregister(pmu_ac);
        platform_device_unregister(bat_pdev);
 }
 
index 694e8cddd5c13e1760e7c9cd5fc0170876a9df04..2ed4a4a6b3c5cb32037904d33ecf1b16adfa41c9 100644 (file)
@@ -40,16 +40,16 @@ static bool __power_supply_is_supplied_by(struct power_supply *supplier,
 
        /* Support both supplied_to and supplied_from modes */
        if (supply->supplied_from) {
-               if (!supplier->name)
+               if (!supplier->desc->name)
                        return false;
                for (i = 0; i < supply->num_supplies; i++)
-                       if (!strcmp(supplier->name, supply->supplied_from[i]))
+                       if (!strcmp(supplier->desc->name, supply->supplied_from[i]))
                                return true;
        } else {
-               if (!supply->name)
+               if (!supply->desc->name)
                        return false;
                for (i = 0; i < supplier->num_supplicants; i++)
-                       if (!strcmp(supplier->supplied_to[i], supply->name))
+                       if (!strcmp(supplier->supplied_to[i], supply->desc->name))
                                return true;
        }
 
@@ -62,8 +62,8 @@ static int __power_supply_changed_work(struct device *dev, void *data)
        struct power_supply *pst = dev_get_drvdata(dev);
 
        if (__power_supply_is_supplied_by(psy, pst)) {
-               if (pst->external_power_changed)
-                       pst->external_power_changed(pst);
+               if (pst->desc->external_power_changed)
+                       pst->desc->external_power_changed(pst);
        }
 
        return 0;
@@ -75,7 +75,7 @@ static void power_supply_changed_work(struct work_struct *work)
        struct power_supply *psy = container_of(work, struct power_supply,
                                                changed_work);
 
-       dev_dbg(psy->dev, "%s\n", __func__);
+       dev_dbg(&psy->dev, "%s\n", __func__);
 
        spin_lock_irqsave(&psy->changed_lock, flags);
        /*
@@ -93,7 +93,7 @@ static void power_supply_changed_work(struct work_struct *work)
                power_supply_update_leds(psy);
                atomic_notifier_call_chain(&power_supply_notifier,
                                PSY_EVENT_PROP_CHANGED, psy);
-               kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
+               kobject_uevent(&psy->dev.kobj, KOBJ_CHANGE);
                spin_lock_irqsave(&psy->changed_lock, flags);
        }
 
@@ -103,7 +103,7 @@ static void power_supply_changed_work(struct work_struct *work)
         * to true.
         */
        if (likely(!psy->changed))
-               pm_relax(psy->dev);
+               pm_relax(&psy->dev);
        spin_unlock_irqrestore(&psy->changed_lock, flags);
 }
 
@@ -111,11 +111,11 @@ void power_supply_changed(struct power_supply *psy)
 {
        unsigned long flags;
 
-       dev_dbg(psy->dev, "%s\n", __func__);
+       dev_dbg(&psy->dev, "%s\n", __func__);
 
        spin_lock_irqsave(&psy->changed_lock, flags);
        psy->changed = true;
-       pm_stay_awake(psy->dev);
+       pm_stay_awake(&psy->dev);
        spin_unlock_irqrestore(&psy->changed_lock, flags);
        schedule_work(&psy->changed_work);
 }
@@ -138,9 +138,9 @@ static int __power_supply_populate_supplied_from(struct device *dev,
                        break;
 
                if (np == epsy->of_node) {
-                       dev_info(psy->dev, "%s: Found supply : %s\n",
-                               psy->name, epsy->name);
-                       psy->supplied_from[i-1] = (char *)epsy->name;
+                       dev_info(&psy->dev, "%s: Found supply : %s\n",
+                               psy->desc->name, epsy->desc->name);
+                       psy->supplied_from[i-1] = (char *)epsy->desc->name;
                        psy->num_supplies++;
                        of_node_put(np);
                        break;
@@ -158,7 +158,7 @@ static int power_supply_populate_supplied_from(struct power_supply *psy)
        error = class_for_each_device(power_supply_class, NULL, psy,
                                      __power_supply_populate_supplied_from);
 
-       dev_dbg(psy->dev, "%s %d\n", __func__, error);
+       dev_dbg(&psy->dev, "%s %d\n", __func__, error);
 
        return error;
 }
@@ -220,7 +220,7 @@ static int power_supply_check_supplies(struct power_supply *psy)
                of_node_put(np);
 
                if (ret) {
-                       dev_dbg(psy->dev, "Failed to find supply!\n");
+                       dev_dbg(&psy->dev, "Failed to find supply!\n");
                        return ret;
                }
        } while (np);
@@ -230,17 +230,18 @@ static int power_supply_check_supplies(struct power_supply *psy)
                return 0;
 
        /* All supplies found, allocate char ** array for filling */
-       psy->supplied_from = devm_kzalloc(psy->dev, sizeof(psy->supplied_from),
+       psy->supplied_from = devm_kzalloc(&psy->dev, sizeof(psy->supplied_from),
                                          GFP_KERNEL);
        if (!psy->supplied_from) {
-               dev_err(psy->dev, "Couldn't allocate memory for supply list\n");
+               dev_err(&psy->dev, "Couldn't allocate memory for supply list\n");
                return -ENOMEM;
        }
 
-       *psy->supplied_from = devm_kzalloc(psy->dev, sizeof(char *) * (cnt - 1),
+       *psy->supplied_from = devm_kzalloc(&psy->dev,
+                                          sizeof(char *) * (cnt - 1),
                                           GFP_KERNEL);
        if (!*psy->supplied_from) {
-               dev_err(psy->dev, "Couldn't allocate memory for supply list\n");
+               dev_err(&psy->dev, "Couldn't allocate memory for supply list\n");
                return -ENOMEM;
        }
 
@@ -260,7 +261,8 @@ static int __power_supply_am_i_supplied(struct device *dev, void *data)
        struct power_supply *epsy = dev_get_drvdata(dev);
 
        if (__power_supply_is_supplied_by(epsy, psy))
-               if (!epsy->get_property(epsy, POWER_SUPPLY_PROP_ONLINE, &ret))
+               if (!epsy->desc->get_property(epsy, POWER_SUPPLY_PROP_ONLINE,
+                                       &ret))
                        return ret.intval;
 
        return 0;
@@ -273,7 +275,7 @@ int power_supply_am_i_supplied(struct power_supply *psy)
        error = class_for_each_device(power_supply_class, NULL, psy,
                                      __power_supply_am_i_supplied);
 
-       dev_dbg(psy->dev, "%s %d\n", __func__, error);
+       dev_dbg(&psy->dev, "%s %d\n", __func__, error);
 
        return error;
 }
@@ -286,8 +288,9 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data)
        unsigned int *count = data;
 
        (*count)++;
-       if (psy->type != POWER_SUPPLY_TYPE_BATTERY)
-               if (!psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret))
+       if (psy->desc->type != POWER_SUPPLY_TYPE_BATTERY)
+               if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE,
+                                       &ret))
                        return ret.intval;
 
        return 0;
@@ -314,8 +317,10 @@ EXPORT_SYMBOL_GPL(power_supply_is_system_supplied);
 
 int power_supply_set_battery_charged(struct power_supply *psy)
 {
-       if (psy->type == POWER_SUPPLY_TYPE_BATTERY && psy->set_charged) {
-               psy->set_charged(psy);
+       if (atomic_read(&psy->use_cnt) >= 0 &&
+                       psy->desc->type == POWER_SUPPLY_TYPE_BATTERY &&
+                       psy->desc->set_charged) {
+               psy->desc->set_charged(psy);
                return 0;
        }
 
@@ -328,28 +333,74 @@ static int power_supply_match_device_by_name(struct device *dev, const void *dat
        const char *name = data;
        struct power_supply *psy = dev_get_drvdata(dev);
 
-       return strcmp(psy->name, name) == 0;
+       return strcmp(psy->desc->name, name) == 0;
 }
 
+/**
+ * power_supply_get_by_name() - Search for a power supply and returns its ref
+ * @name: Power supply name to fetch
+ *
+ * If power supply was found, it increases reference count for the
+ * internal power supply's device. The user should power_supply_put()
+ * after usage.
+ *
+ * Return: On success returns a reference to a power supply with
+ * matching name equals to @name, a NULL otherwise.
+ */
 struct power_supply *power_supply_get_by_name(const char *name)
 {
+       struct power_supply *psy = NULL;
        struct device *dev = class_find_device(power_supply_class, NULL, name,
                                        power_supply_match_device_by_name);
 
-       return dev ? dev_get_drvdata(dev) : NULL;
+       if (dev) {
+               psy = dev_get_drvdata(dev);
+               atomic_inc(&psy->use_cnt);
+       }
+
+       return psy;
 }
 EXPORT_SYMBOL_GPL(power_supply_get_by_name);
 
+/**
+ * power_supply_put() - Drop reference obtained with power_supply_get_by_name
+ * @psy: Reference to put
+ *
+ * The reference to power supply should be put before unregistering
+ * the power supply.
+ */
+void power_supply_put(struct power_supply *psy)
+{
+       might_sleep();
+
+       atomic_dec(&psy->use_cnt);
+       put_device(&psy->dev);
+}
+EXPORT_SYMBOL_GPL(power_supply_put);
+
 #ifdef CONFIG_OF
 static int power_supply_match_device_node(struct device *dev, const void *data)
 {
        return dev->parent && dev->parent->of_node == data;
 }
 
+/**
+ * power_supply_get_by_phandle() - Search for a power supply and returns its ref
+ * @np: Pointer to device node holding phandle property
+ * @phandle_name: Name of property holding a power supply name
+ *
+ * If power supply was found, it increases reference count for the
+ * internal power supply's device. The user should power_supply_put()
+ * after usage.
+ *
+ * Return: On success returns a reference to a power supply with
+ * matching name equals to value under @property, NULL or ERR_PTR otherwise.
+ */
 struct power_supply *power_supply_get_by_phandle(struct device_node *np,
                                                        const char *property)
 {
        struct device_node *power_supply_np;
+       struct power_supply *psy = NULL;
        struct device *dev;
 
        power_supply_np = of_parse_phandle(np, property, 0);
@@ -361,21 +412,70 @@ struct power_supply *power_supply_get_by_phandle(struct device_node *np,
 
        of_node_put(power_supply_np);
 
-       return dev ? dev_get_drvdata(dev) : NULL;
+       if (dev) {
+               psy = dev_get_drvdata(dev);
+               atomic_inc(&psy->use_cnt);
+       }
+
+       return psy;
 }
 EXPORT_SYMBOL_GPL(power_supply_get_by_phandle);
 #endif /* CONFIG_OF */
 
+int power_supply_get_property(struct power_supply *psy,
+                           enum power_supply_property psp,
+                           union power_supply_propval *val)
+{
+       if (atomic_read(&psy->use_cnt) <= 0)
+               return -ENODEV;
+
+       return psy->desc->get_property(psy, psp, val);
+}
+EXPORT_SYMBOL_GPL(power_supply_get_property);
+
+int power_supply_set_property(struct power_supply *psy,
+                           enum power_supply_property psp,
+                           const union power_supply_propval *val)
+{
+       if (atomic_read(&psy->use_cnt) <= 0 || !psy->desc->set_property)
+               return -ENODEV;
+
+       return psy->desc->set_property(psy, psp, val);
+}
+EXPORT_SYMBOL_GPL(power_supply_set_property);
+
+int power_supply_property_is_writeable(struct power_supply *psy,
+                                       enum power_supply_property psp)
+{
+       if (atomic_read(&psy->use_cnt) <= 0 ||
+                       !psy->desc->property_is_writeable)
+               return -ENODEV;
+
+       return psy->desc->property_is_writeable(psy, psp);
+}
+EXPORT_SYMBOL_GPL(power_supply_property_is_writeable);
+
+void power_supply_external_power_changed(struct power_supply *psy)
+{
+       if (atomic_read(&psy->use_cnt) <= 0 ||
+                       !psy->desc->external_power_changed)
+               return;
+
+       psy->desc->external_power_changed(psy);
+}
+EXPORT_SYMBOL_GPL(power_supply_external_power_changed);
+
 int power_supply_powers(struct power_supply *psy, struct device *dev)
 {
-       return sysfs_create_link(&psy->dev->kobj, &dev->kobj, "powers");
+       return sysfs_create_link(&psy->dev.kobj, &dev->kobj, "powers");
 }
 EXPORT_SYMBOL_GPL(power_supply_powers);
 
 static void power_supply_dev_release(struct device *dev)
 {
+       struct power_supply *psy = container_of(dev, struct power_supply, dev);
        pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
-       kfree(dev);
+       kfree(psy);
 }
 
 int power_supply_reg_notifier(struct notifier_block *nb)
@@ -400,7 +500,7 @@ static int power_supply_read_temp(struct thermal_zone_device *tzd,
 
        WARN_ON(tzd == NULL);
        psy = tzd->devdata;
-       ret = psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &val);
+       ret = psy->desc->get_property(psy, POWER_SUPPLY_PROP_TEMP, &val);
 
        /* Convert tenths of degree Celsius to milli degree Celsius. */
        if (!ret)
@@ -417,14 +517,14 @@ static int psy_register_thermal(struct power_supply *psy)
 {
        int i;
 
-       if (psy->no_thermal)
+       if (psy->desc->no_thermal)
                return 0;
 
        /* Register battery zone device psy reports temperature */
-       for (i = 0; i < psy->num_properties; i++) {
-               if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) {
-                       psy->tzd = thermal_zone_device_register(psy->name, 0, 0,
-                                       psy, &psy_tzd_ops, NULL, 0, 0);
+       for (i = 0; i < psy->desc->num_properties; i++) {
+               if (psy->desc->properties[i] == POWER_SUPPLY_PROP_TEMP) {
+                       psy->tzd = thermal_zone_device_register(psy->desc->name,
+                                       0, 0, psy, &psy_tzd_ops, NULL, 0, 0);
                        return PTR_ERR_OR_ZERO(psy->tzd);
                }
        }
@@ -447,7 +547,7 @@ static int ps_get_max_charge_cntl_limit(struct thermal_cooling_device *tcd,
        int ret;
 
        psy = tcd->devdata;
-       ret = psy->get_property(psy,
+       ret = psy->desc->get_property(psy,
                POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, &val);
        if (!ret)
                *state = val.intval;
@@ -463,7 +563,7 @@ static int ps_get_cur_chrage_cntl_limit(struct thermal_cooling_device *tcd,
        int ret;
 
        psy = tcd->devdata;
-       ret = psy->get_property(psy,
+       ret = psy->desc->get_property(psy,
                POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val);
        if (!ret)
                *state = val.intval;
@@ -480,7 +580,7 @@ static int ps_set_cur_charge_cntl_limit(struct thermal_cooling_device *tcd,
 
        psy = tcd->devdata;
        val.intval = state;
-       ret = psy->set_property(psy,
+       ret = psy->desc->set_property(psy,
                POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val);
 
        return ret;
@@ -497,11 +597,11 @@ static int psy_register_cooler(struct power_supply *psy)
        int i;
 
        /* Register for cooling device if psy can control charging */
-       for (i = 0; i < psy->num_properties; i++) {
-               if (psy->properties[i] ==
+       for (i = 0; i < psy->desc->num_properties; i++) {
+               if (psy->desc->properties[i] ==
                                POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT) {
                        psy->tcd = thermal_cooling_device_register(
-                                                       (char *)psy->name,
+                                                       (char *)psy->desc->name,
                                                        psy, &psy_tcd_ops);
                        return PTR_ERR_OR_ZERO(psy->tcd);
                }
@@ -535,15 +635,21 @@ static void psy_unregister_cooler(struct power_supply *psy)
 }
 #endif
 
-static int __power_supply_register(struct device *parent,
-                                  struct power_supply *psy, bool ws)
+static struct power_supply *__must_check
+__power_supply_register(struct device *parent,
+                                  const struct power_supply_desc *desc,
+                                  const struct power_supply_config *cfg,
+                                  bool ws)
 {
        struct device *dev;
+       struct power_supply *psy;
        int rc;
 
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (!dev)
-               return -ENOMEM;
+       psy = kzalloc(sizeof(*psy), GFP_KERNEL);
+       if (!psy)
+               return ERR_PTR(-ENOMEM);
+
+       dev = &psy->dev;
 
        device_initialize(dev);
 
@@ -552,9 +658,16 @@ static int __power_supply_register(struct device *parent,
        dev->parent = parent;
        dev->release = power_supply_dev_release;
        dev_set_drvdata(dev, psy);
-       psy->dev = dev;
+       psy->desc = desc;
+       atomic_inc(&psy->use_cnt);
+       if (cfg) {
+               psy->drv_data = cfg->drv_data;
+               psy->of_node = cfg->of_node;
+               psy->supplied_to = cfg->supplied_to;
+               psy->num_supplicants = cfg->num_supplicants;
+       }
 
-       rc = dev_set_name(dev, "%s", psy->name);
+       rc = dev_set_name(dev, "%s", desc->name);
        if (rc)
                goto dev_set_name_failed;
 
@@ -589,7 +702,7 @@ static int __power_supply_register(struct device *parent,
 
        power_supply_changed(psy);
 
-       return 0;
+       return psy;
 
 create_triggers_failed:
        psy_unregister_cooler(psy);
@@ -602,33 +715,155 @@ wakeup_init_failed:
 check_supplies_failed:
 dev_set_name_failed:
        put_device(dev);
-       return rc;
+       return ERR_PTR(rc);
 }
 
-int power_supply_register(struct device *parent, struct power_supply *psy)
+/**
+ * power_supply_register() - Register new power supply
+ * @parent:    Device to be a parent of power supply's device
+ * @desc:      Description of power supply, must be valid through whole
+ *             lifetime of this power supply
+ * @cfg:       Run-time specific configuration accessed during registering,
+ *             may be NULL
+ *
+ * Return: A pointer to newly allocated power_supply on success
+ * or ERR_PTR otherwise.
+ * Use power_supply_unregister() on returned power_supply pointer to release
+ * resources.
+ */
+struct power_supply *__must_check power_supply_register(struct device *parent,
+               const struct power_supply_desc *desc,
+               const struct power_supply_config *cfg)
 {
-       return __power_supply_register(parent, psy, true);
+       return __power_supply_register(parent, desc, cfg, true);
 }
 EXPORT_SYMBOL_GPL(power_supply_register);
 
-int power_supply_register_no_ws(struct device *parent, struct power_supply *psy)
+/**
+ * power_supply_register() - Register new non-waking-source power supply
+ * @parent:    Device to be a parent of power supply's device
+ * @desc:      Description of power supply, must be valid through whole
+ *             lifetime of this power supply
+ * @cfg:       Run-time specific configuration accessed during registering,
+ *             may be NULL
+ *
+ * Return: A pointer to newly allocated power_supply on success
+ * or ERR_PTR otherwise.
+ * Use power_supply_unregister() on returned power_supply pointer to release
+ * resources.
+ */
+struct power_supply *__must_check
+power_supply_register_no_ws(struct device *parent,
+               const struct power_supply_desc *desc,
+               const struct power_supply_config *cfg)
 {
-       return __power_supply_register(parent, psy, false);
+       return __power_supply_register(parent, desc, cfg, false);
 }
 EXPORT_SYMBOL_GPL(power_supply_register_no_ws);
 
+static void devm_power_supply_release(struct device *dev, void *res)
+{
+       struct power_supply **psy = res;
+
+       power_supply_unregister(*psy);
+}
+
+/**
+ * power_supply_register() - Register managed power supply
+ * @parent:    Device to be a parent of power supply's device
+ * @desc:      Description of power supply, must be valid through whole
+ *             lifetime of this power supply
+ * @cfg:       Run-time specific configuration accessed during registering,
+ *             may be NULL
+ *
+ * Return: A pointer to newly allocated power_supply on success
+ * or ERR_PTR otherwise.
+ * The returned power_supply pointer will be automatically unregistered
+ * on driver detach.
+ */
+struct power_supply *__must_check
+devm_power_supply_register(struct device *parent,
+               const struct power_supply_desc *desc,
+               const struct power_supply_config *cfg)
+{
+       struct power_supply **ptr, *psy;
+
+       ptr = devres_alloc(devm_power_supply_release, sizeof(*ptr), GFP_KERNEL);
+
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+       psy = __power_supply_register(parent, desc, cfg, true);
+       if (IS_ERR(psy)) {
+               devres_free(ptr);
+       } else {
+               *ptr = psy;
+               devres_add(parent, ptr);
+       }
+       return psy;
+}
+EXPORT_SYMBOL_GPL(devm_power_supply_register);
+
+/**
+ * power_supply_register() - Register managed non-waking-source power supply
+ * @parent:    Device to be a parent of power supply's device
+ * @desc:      Description of power supply, must be valid through whole
+ *             lifetime of this power supply
+ * @cfg:       Run-time specific configuration accessed during registering,
+ *             may be NULL
+ *
+ * Return: A pointer to newly allocated power_supply on success
+ * or ERR_PTR otherwise.
+ * The returned power_supply pointer will be automatically unregistered
+ * on driver detach.
+ */
+struct power_supply *__must_check
+devm_power_supply_register_no_ws(struct device *parent,
+               const struct power_supply_desc *desc,
+               const struct power_supply_config *cfg)
+{
+       struct power_supply **ptr, *psy;
+
+       ptr = devres_alloc(devm_power_supply_release, sizeof(*ptr), GFP_KERNEL);
+
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+       psy = __power_supply_register(parent, desc, cfg, false);
+       if (IS_ERR(psy)) {
+               devres_free(ptr);
+       } else {
+               *ptr = psy;
+               devres_add(parent, ptr);
+       }
+       return psy;
+}
+EXPORT_SYMBOL_GPL(devm_power_supply_register_no_ws);
+
+/**
+ * power_supply_unregister() - Remove this power supply from system
+ * @psy:       Pointer to power supply to unregister
+ *
+ * Remove this power supply from the system. The resources of power supply
+ * will be freed here or on last power_supply_put() call.
+ */
 void power_supply_unregister(struct power_supply *psy)
 {
+       WARN_ON(atomic_dec_return(&psy->use_cnt));
        cancel_work_sync(&psy->changed_work);
-       sysfs_remove_link(&psy->dev->kobj, "powers");
+       sysfs_remove_link(&psy->dev.kobj, "powers");
        power_supply_remove_triggers(psy);
        psy_unregister_cooler(psy);
        psy_unregister_thermal(psy);
-       device_init_wakeup(psy->dev, false);
-       device_unregister(psy->dev);
+       device_init_wakeup(&psy->dev, false);
+       device_unregister(&psy->dev);
 }
 EXPORT_SYMBOL_GPL(power_supply_unregister);
 
+void *power_supply_get_drvdata(struct power_supply *psy)
+{
+       return psy->drv_data;
+}
+EXPORT_SYMBOL_GPL(power_supply_get_drvdata);
+
 static int __init power_supply_class_init(void)
 {
        power_supply_class = class_create(THIS_MODULE, "power_supply");
index effa093c37b0ac7042351aa7acc9118613bf74e5..2d41a43fc81acb967639b012b4e7811bab29572e 100644 (file)
@@ -25,10 +25,10 @@ static void power_supply_update_bat_leds(struct power_supply *psy)
        unsigned long delay_on = 0;
        unsigned long delay_off = 0;
 
-       if (psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
+       if (psy->desc->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
                return;
 
-       dev_dbg(psy->dev, "%s %d\n", __func__, status.intval);
+       dev_dbg(&psy->dev, "%s %d\n", __func__, status.intval);
 
        switch (status.intval) {
        case POWER_SUPPLY_STATUS_FULL:
@@ -58,21 +58,21 @@ static void power_supply_update_bat_leds(struct power_supply *psy)
 static int power_supply_create_bat_triggers(struct power_supply *psy)
 {
        psy->charging_full_trig_name = kasprintf(GFP_KERNEL,
-                                       "%s-charging-or-full", psy->name);
+                                       "%s-charging-or-full", psy->desc->name);
        if (!psy->charging_full_trig_name)
                goto charging_full_failed;
 
        psy->charging_trig_name = kasprintf(GFP_KERNEL,
-                                       "%s-charging", psy->name);
+                                       "%s-charging", psy->desc->name);
        if (!psy->charging_trig_name)
                goto charging_failed;
 
-       psy->full_trig_name = kasprintf(GFP_KERNEL, "%s-full", psy->name);
+       psy->full_trig_name = kasprintf(GFP_KERNEL, "%s-full", psy->desc->name);
        if (!psy->full_trig_name)
                goto full_failed;
 
        psy->charging_blink_full_solid_trig_name = kasprintf(GFP_KERNEL,
-               "%s-charging-blink-full-solid", psy->name);
+               "%s-charging-blink-full-solid", psy->desc->name);
        if (!psy->charging_blink_full_solid_trig_name)
                goto charging_blink_full_solid_failed;
 
@@ -115,10 +115,10 @@ static void power_supply_update_gen_leds(struct power_supply *psy)
 {
        union power_supply_propval online;
 
-       if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
+       if (psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
                return;
 
-       dev_dbg(psy->dev, "%s %d\n", __func__, online.intval);
+       dev_dbg(&psy->dev, "%s %d\n", __func__, online.intval);
 
        if (online.intval)
                led_trigger_event(psy->online_trig, LED_FULL);
@@ -128,7 +128,8 @@ static void power_supply_update_gen_leds(struct power_supply *psy)
 
 static int power_supply_create_gen_triggers(struct power_supply *psy)
 {
-       psy->online_trig_name = kasprintf(GFP_KERNEL, "%s-online", psy->name);
+       psy->online_trig_name = kasprintf(GFP_KERNEL, "%s-online",
+                                         psy->desc->name);
        if (!psy->online_trig_name)
                return -ENOMEM;
 
@@ -147,7 +148,7 @@ static void power_supply_remove_gen_triggers(struct power_supply *psy)
 
 void power_supply_update_leds(struct power_supply *psy)
 {
-       if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+       if (psy->desc->type == POWER_SUPPLY_TYPE_BATTERY)
                power_supply_update_bat_leds(psy);
        else
                power_supply_update_gen_leds(psy);
@@ -155,14 +156,14 @@ void power_supply_update_leds(struct power_supply *psy)
 
 int power_supply_create_triggers(struct power_supply *psy)
 {
-       if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+       if (psy->desc->type == POWER_SUPPLY_TYPE_BATTERY)
                return power_supply_create_bat_triggers(psy);
        return power_supply_create_gen_triggers(psy);
 }
 
 void power_supply_remove_triggers(struct power_supply *psy)
 {
-       if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+       if (psy->desc->type == POWER_SUPPLY_TYPE_BATTERY)
                power_supply_remove_bat_triggers(psy);
        else
                power_supply_remove_gen_triggers(psy);
index 62653f50a524537c7e2f45dca9f22657417146ed..9134e3d2d95ef9bfbfca479fd276d93ad2e8e7fb 100644 (file)
@@ -74,9 +74,9 @@ static ssize_t power_supply_show_property(struct device *dev,
        union power_supply_propval value;
 
        if (off == POWER_SUPPLY_PROP_TYPE) {
-               value.intval = psy->type;
+               value.intval = psy->desc->type;
        } else {
-               ret = psy->get_property(psy, off, &value);
+               ret = power_supply_get_property(psy, off, &value);
 
                if (ret < 0) {
                        if (ret == -ENODATA)
@@ -125,7 +125,7 @@ static ssize_t power_supply_store_property(struct device *dev,
 
        value.intval = long_val;
 
-       ret = psy->set_property(psy, off, &value);
+       ret = psy->desc->set_property(psy, off, &value);
        if (ret < 0)
                return ret;
 
@@ -218,12 +218,12 @@ static umode_t power_supply_attr_is_visible(struct kobject *kobj,
        if (attrno == POWER_SUPPLY_PROP_TYPE)
                return mode;
 
-       for (i = 0; i < psy->num_properties; i++) {
-               int property = psy->properties[i];
+       for (i = 0; i < psy->desc->num_properties; i++) {
+               int property = psy->desc->properties[i];
 
                if (property == attrno) {
-                       if (psy->property_is_writeable &&
-                           psy->property_is_writeable(psy, property) > 0)
+                       if (psy->desc->property_is_writeable &&
+                           power_supply_property_is_writeable(psy, property) > 0)
                                mode |= S_IWUSR;
 
                        return mode;
@@ -279,14 +279,14 @@ int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
 
        dev_dbg(dev, "uevent\n");
 
-       if (!psy || !psy->dev) {
+       if (!psy || !psy->desc) {
                dev_dbg(dev, "No power supply yet\n");
                return ret;
        }
 
-       dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name);
+       dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->desc->name);
 
-       ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->name);
+       ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->desc->name);
        if (ret)
                return ret;
 
@@ -294,11 +294,11 @@ int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
        if (!prop_buf)
                return -ENOMEM;
 
-       for (j = 0; j < psy->num_properties; j++) {
+       for (j = 0; j < psy->desc->num_properties; j++) {
                struct device_attribute *attr;
                char *line;
 
-               attr = &power_supply_attrs[psy->properties[j]];
+               attr = &power_supply_attrs[psy->desc->properties[j]];
 
                ret = power_supply_show_property(dev, attr, prop_buf);
                if (ret == -ENODEV || ret == -ENODATA) {
index 27f6646731b0d3e7f829f1828f3b5ce904219aae..aad9c3318c02a271a864da8866b9b38c4623768c 100644 (file)
@@ -151,9 +151,17 @@ config POWER_RESET_SYSCON
        help
          Reboot support for generic SYSCON mapped register reset.
 
+config POWER_RESET_SYSCON_POWEROFF
+       bool "Generic SYSCON regmap poweroff driver"
+       depends on OF
+       select MFD_SYSCON
+       help
+         Poweroff support for generic SYSCON mapped register poweroff.
+
 config POWER_RESET_RMOBILE
        tristate "Renesas R-Mobile reset driver"
        depends on ARCH_RMOBILE || COMPILE_TEST
+       depends on HAS_IOMEM
        help
          Reboot support for Renesas R-Mobile and SH-Mobile SoCs.
 
index 11de15bae52ea2e034fb46c53c96fb49274c02e6..dbe06c368743220ede4be9dbb9c2dfb814205bdc 100644 (file)
@@ -17,4 +17,5 @@ obj-$(CONFIG_POWER_RESET_VEXPRESS) += vexpress-poweroff.o
 obj-$(CONFIG_POWER_RESET_XGENE) += xgene-reboot.o
 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
index 4b72ea51c3648b5a470b1eb7d3fd8e60741f4f63..9847cfb7e23dd3a27f9ac94c3185667b970d5de9 100644 (file)
@@ -140,7 +140,7 @@ static int at91_poweroff_probe(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id at91_poweroff_of_match[] = {
+static const struct of_device_id at91_poweroff_of_match[] = {
        { .compatible = "atmel,at91sam9260-shdwc", },
        { .compatible = "atmel,at91sam9rl-shdwc", },
        { .compatible = "atmel,at91sam9x5-shdwc", },
index 13584e24736a37ba682ba1db3ef7aeb46a0650cd..01c7055c4200e3d9a7333ac7c0bcaccc3ac2d4a5 100644 (file)
@@ -73,8 +73,8 @@ static int at91sam9260_restart(struct notifier_block *this, unsigned long mode,
                : "r" (at91_ramc_base[0]),
                  "r" (at91_rstc_base),
                  "r" (1),
-                 "r" (AT91_SDRAMC_LPCB_POWER_DOWN),
-                 "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
+                 "r" cpu_to_le32(AT91_SDRAMC_LPCB_POWER_DOWN),
+                 "r" cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
 
        return NOTIFY_DONE;
 }
@@ -116,8 +116,8 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode,
                  "r" (at91_ramc_base[1]),
                  "r" (at91_rstc_base),
                  "r" (1),
-                 "r" (AT91_DDRSDRC_LPCB_POWER_DOWN),
-                 "r" (AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
+                 "r" cpu_to_le32(AT91_DDRSDRC_LPCB_POWER_DOWN),
+                 "r" cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
                : "r0");
 
        return NOTIFY_DONE;
@@ -152,14 +152,14 @@ static void __init at91_reset_status(struct platform_device *pdev)
        pr_info("AT91: Starting after %s\n", reason);
 }
 
-static struct of_device_id at91_ramc_of_match[] = {
+static const struct of_device_id at91_ramc_of_match[] = {
        { .compatible = "atmel,at91sam9260-sdramc", },
        { .compatible = "atmel,at91sam9g45-ddramc", },
        { .compatible = "atmel,sama5d3-ddramc", },
        { /* sentinel */ }
 };
 
-static struct of_device_id at91_reset_of_match[] = {
+static const struct of_device_id at91_reset_of_match[] = {
        { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9260_restart },
        { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
        { /* sentinel */ }
index 5385460e23bb20f17cc4e4da8eea81b9dd4bda80..9ab7f562a83ba6538054e1e39a8b758489a4f8d7 100644 (file)
@@ -64,7 +64,7 @@ static int hisi_reboot_probe(struct platform_device *pdev)
        return err;
 }
 
-static struct of_device_id hisi_reboot_of_match[] = {
+static const struct of_device_id hisi_reboot_of_match[] = {
        { .compatible = "hisilicon,sysctrl" },
        {}
 };
index faedf16c8111895a84b0724e32d2fb219b84fb38..c70f1bffe038b8ad02c6c4980b62e039090c15a4 100644 (file)
@@ -70,7 +70,7 @@ static struct notifier_block rsctrl_restart_nb = {
        .priority = 128,
 };
 
-static struct of_device_id rsctrl_of_match[] = {
+static const struct of_device_id rsctrl_of_match[] = {
        {.compatible = "ti,keystone-reset", },
        {},
 };
index 27383de9caa87b952a270512bd3d497d1f6a7321..a488877a3538c8c9761d1c8e468cdf1c3edb91de 100644 (file)
@@ -97,7 +97,7 @@ static struct notifier_block st_restart_nb = {
        .priority = 192,
 };
 
-static struct of_device_id st_reset_of_match[] = {
+static const struct of_device_id st_reset_of_match[] = {
        {
                .compatible = "st,stih415-restart",
                .data = (void *)&stih415_reset,
diff --git a/drivers/power/reset/syscon-poweroff.c b/drivers/power/reset/syscon-poweroff.c
new file mode 100644 (file)
index 0000000..5560b0d
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Generic Syscon Poweroff Driver
+ *
+ * Copyright (c) 2015, National Instruments Corp.
+ * Author: Moritz Fischer <moritz.fischer@ettus.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/kallsyms.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/notifier.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+
+static struct regmap *map;
+static u32 offset;
+static u32 mask;
+
+void syscon_poweroff(void)
+{
+       /* Issue the poweroff */
+       regmap_write(map, offset, mask);
+
+       mdelay(1000);
+
+       pr_emerg("Unable to poweroff system\n");
+}
+
+static int syscon_poweroff_probe(struct platform_device *pdev)
+{
+       char symname[KSYM_NAME_LEN];
+
+       map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "regmap");
+       if (IS_ERR(map)) {
+               dev_err(&pdev->dev, "unable to get syscon");
+               return PTR_ERR(map);
+       }
+
+       if (of_property_read_u32(pdev->dev.of_node, "offset", &offset)) {
+               dev_err(&pdev->dev, "unable to read 'offset'");
+               return -EINVAL;
+       }
+
+       if (of_property_read_u32(pdev->dev.of_node, "mask", &mask)) {
+               dev_err(&pdev->dev, "unable to read 'mask'");
+               return -EINVAL;
+       }
+
+       if (pm_power_off) {
+               lookup_symbol_name((ulong)pm_power_off, symname);
+               dev_err(&pdev->dev,
+               "pm_power_off already claimed %p %s",
+               pm_power_off, symname);
+               return -EBUSY;
+       }
+
+       pm_power_off = syscon_poweroff;
+
+       return 0;
+}
+
+static int syscon_poweroff_remove(struct platform_device *pdev)
+{
+       if (pm_power_off == syscon_poweroff)
+               pm_power_off = NULL;
+
+       return 0;
+}
+
+static const struct of_device_id syscon_poweroff_of_match[] = {
+       { .compatible = "syscon-poweroff" },
+       {}
+};
+
+static struct platform_driver syscon_poweroff_driver = {
+       .probe = syscon_poweroff_probe,
+       .remove = syscon_poweroff_remove,
+       .driver = {
+               .name = "syscon-poweroff",
+               .of_match_table = syscon_poweroff_of_match,
+       },
+};
+
+static int __init syscon_poweroff_register(void)
+{
+       return platform_driver_register(&syscon_poweroff_driver);
+}
+device_initcall(syscon_poweroff_register);
index c4049f45663f4b929a679e9ea548ed7bb4d18295..d3c7d245ae63d93c5ec36617e69331b25f9b570c 100644 (file)
@@ -76,7 +76,7 @@ static int syscon_reboot_probe(struct platform_device *pdev)
        return err;
 }
 
-static struct of_device_id syscon_reboot_of_match[] = {
+static const struct of_device_id syscon_reboot_of_match[] = {
        { .compatible = "syscon-reboot" },
        {}
 };
index be12d9b92957d07c9da3f52335016b3c417f96a6..6a9bf7089373600120739f8f51829ba07344f8aa 100644 (file)
@@ -80,7 +80,7 @@ DEVICE_ATTR(active, S_IRUGO | S_IWUSR, vexpress_reset_active_show,
 
 enum vexpress_reset_func { FUNC_RESET, FUNC_SHUTDOWN, FUNC_REBOOT };
 
-static struct of_device_id vexpress_reset_of_match[] = {
+static const struct of_device_id vexpress_reset_of_match[] = {
        {
                .compatible = "arm,vexpress-reset",
                .data = (void *)FUNC_RESET,
index b0e5002f8debee0c95515bfd217e8d3a85844675..f07e93c97ba337624d202b19b55ab46fda170b21 100644 (file)
@@ -87,7 +87,7 @@ static int xgene_reboot_probe(struct platform_device *pdev)
        return err;
 }
 
-static struct of_device_id xgene_reboot_of_match[] = {
+static const struct of_device_id xgene_reboot_of_match[] = {
        { .compatible = "apm,xgene-reboot" },
        {}
 };
index 7b898f41c59540b6560e735a73466d73423d5371..a7a6877b4e1660fdf39841e4491c07be2d903a57 100644 (file)
@@ -72,8 +72,7 @@ static int rt5033_battery_get_property(struct power_supply *psy,
                enum power_supply_property psp,
                union power_supply_propval *val)
 {
-       struct rt5033_battery *battery = container_of(psy,
-                               struct rt5033_battery, psy);
+       struct rt5033_battery *battery = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
@@ -102,16 +101,25 @@ static enum power_supply_property rt5033_battery_props[] = {
        POWER_SUPPLY_PROP_CAPACITY,
 };
 
-static struct regmap_config rt5033_battery_regmap_config = {
+static const struct regmap_config rt5033_battery_regmap_config = {
        .reg_bits       = 8,
        .val_bits       = 8,
        .max_register   = RT5033_FUEL_REG_END,
 };
 
+static const struct power_supply_desc rt5033_battery_desc = {
+       .name           = "rt5033-battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .get_property   = rt5033_battery_get_property,
+       .properties     = rt5033_battery_props,
+       .num_properties = ARRAY_SIZE(rt5033_battery_props),
+};
+
 static int rt5033_battery_probe(struct i2c_client *client,
                const struct i2c_device_id *id)
 {
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       struct power_supply_config psy_cfg = {};
        struct rt5033_battery *battery;
        u32 ret;
 
@@ -131,16 +139,13 @@ static int rt5033_battery_probe(struct i2c_client *client,
        }
 
        i2c_set_clientdata(client, battery);
+       psy_cfg.drv_data = battery;
 
-       battery->psy.name               = "rt5033-battery";
-       battery->psy.type               = POWER_SUPPLY_TYPE_BATTERY;
-       battery->psy.get_property       = rt5033_battery_get_property;
-       battery->psy.properties         = rt5033_battery_props;
-       battery->psy.num_properties     = ARRAY_SIZE(rt5033_battery_props);
-
-       ret = power_supply_register(&client->dev, &battery->psy);
-       if (ret) {
+       battery->psy = power_supply_register(&client->dev,
+                                            &rt5033_battery_desc, &psy_cfg);
+       if (IS_ERR(battery->psy)) {
                dev_err(&client->dev, "Failed to register power supply\n");
+               ret = PTR_ERR(battery->psy);
                return ret;
        }
 
@@ -151,7 +156,7 @@ static int rt5033_battery_remove(struct i2c_client *client)
 {
        struct rt5033_battery *battery = i2c_get_clientdata(client);
 
-       power_supply_unregister(&battery->psy);
+       power_supply_unregister(battery->psy);
 
        return 0;
 }
index a01aacb32f5910b58e45ba4bcd57e6fa8c8382b5..ac6206951d5842235cdf167a69bca0f93c6b5bd3 100644 (file)
@@ -29,7 +29,8 @@
 
 struct rx51_device_info {
        struct device *dev;
-       struct power_supply bat;
+       struct power_supply *bat;
+       struct power_supply_desc bat_desc;
        struct iio_channel *channel_temp;
        struct iio_channel *channel_bsi;
        struct iio_channel *channel_vbat;
@@ -161,8 +162,7 @@ static int rx51_battery_get_property(struct power_supply *psy,
                                        enum power_supply_property psp,
                                        union power_supply_propval *val)
 {
-       struct rx51_device_info *di = container_of((psy),
-                               struct rx51_device_info, bat);
+       struct rx51_device_info *di = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_TECHNOLOGY:
@@ -204,6 +204,7 @@ static enum power_supply_property rx51_battery_props[] = {
 
 static int rx51_battery_probe(struct platform_device *pdev)
 {
+       struct power_supply_config psy_cfg = {};
        struct rx51_device_info *di;
        int ret;
 
@@ -214,11 +215,13 @@ static int rx51_battery_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, di);
 
        di->dev = &pdev->dev;
-       di->bat.name = dev_name(&pdev->dev);
-       di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
-       di->bat.properties = rx51_battery_props;
-       di->bat.num_properties = ARRAY_SIZE(rx51_battery_props);
-       di->bat.get_property = rx51_battery_get_property;
+       di->bat_desc.name = dev_name(&pdev->dev);
+       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);
+       di->bat_desc.get_property = rx51_battery_get_property;
+
+       psy_cfg.drv_data = di;
 
        di->channel_temp = iio_channel_get(di->dev, "temp");
        if (IS_ERR(di->channel_temp)) {
@@ -238,9 +241,11 @@ static int rx51_battery_probe(struct platform_device *pdev)
                goto error_channel_bsi;
        }
 
-       ret = power_supply_register(di->dev, &di->bat);
-       if (ret)
+       di->bat = power_supply_register(di->dev, &di->bat_desc, &psy_cfg);
+       if (IS_ERR(di->bat)) {
+               ret = PTR_ERR(di->bat);
                goto error_channel_vbat;
+       }
 
        return 0;
 
@@ -259,7 +264,7 @@ static int rx51_battery_remove(struct platform_device *pdev)
 {
        struct rx51_device_info *di = platform_get_drvdata(pdev);
 
-       power_supply_unregister(&di->bat);
+       power_supply_unregister(di->bat);
 
        iio_channel_release(di->channel_vbat);
        iio_channel_release(di->channel_bsi);
index 5948ce058bdddefaed394a7fcf3039876946c062..0ffe5cd3abf627fc14516384e7718601604571c8 100644 (file)
@@ -28,7 +28,7 @@
 #define JITTER_DELAY                   500 /* ms */
 
 struct s3c_adc_bat {
-       struct power_supply             psy;
+       struct power_supply             *psy;
        struct s3c_adc_client           *client;
        struct s3c_adc_bat_pdata        *pdata;
        int                             volt_value;
@@ -73,10 +73,10 @@ static int s3c_adc_backup_bat_get_property(struct power_supply *psy,
                                enum power_supply_property psp,
                                union power_supply_propval *val)
 {
-       struct s3c_adc_bat *bat = container_of(psy, struct s3c_adc_bat, psy);
+       struct s3c_adc_bat *bat = power_supply_get_drvdata(psy);
 
        if (!bat) {
-               dev_err(psy->dev, "%s: no battery infos ?!\n", __func__);
+               dev_err(&psy->dev, "%s: no battery infos ?!\n", __func__);
                return -EINVAL;
        }
 
@@ -105,17 +105,17 @@ static int s3c_adc_backup_bat_get_property(struct power_supply *psy,
        }
 }
 
-static struct s3c_adc_bat backup_bat = {
-       .psy = {
-               .name           = "backup-battery",
-               .type           = POWER_SUPPLY_TYPE_BATTERY,
-               .properties     = s3c_adc_backup_bat_props,
-               .num_properties = ARRAY_SIZE(s3c_adc_backup_bat_props),
-               .get_property   = s3c_adc_backup_bat_get_property,
-               .use_for_apm    = 1,
-       },
+static const struct power_supply_desc backup_bat_desc = {
+       .name           = "backup-battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .properties     = s3c_adc_backup_bat_props,
+       .num_properties = ARRAY_SIZE(s3c_adc_backup_bat_props),
+       .get_property   = s3c_adc_backup_bat_get_property,
+       .use_for_apm    = 1,
 };
 
+static struct s3c_adc_bat backup_bat;
+
 static enum power_supply_property s3c_adc_main_bat_props[] = {
        POWER_SUPPLY_PROP_STATUS,
        POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
@@ -141,7 +141,7 @@ static int s3c_adc_bat_get_property(struct power_supply *psy,
                                    enum power_supply_property psp,
                                    union power_supply_propval *val)
 {
-       struct s3c_adc_bat *bat = container_of(psy, struct s3c_adc_bat, psy);
+       struct s3c_adc_bat *bat = power_supply_get_drvdata(psy);
 
        int new_level;
        int full_volt;
@@ -149,7 +149,7 @@ static int s3c_adc_bat_get_property(struct power_supply *psy,
        unsigned int lut_size;
 
        if (!bat) {
-               dev_err(psy->dev, "no battery infos ?!\n");
+               dev_err(&psy->dev, "no battery infos ?!\n");
                return -EINVAL;
        }
 
@@ -232,18 +232,18 @@ static int s3c_adc_bat_get_property(struct power_supply *psy,
        }
 }
 
-static struct s3c_adc_bat main_bat = {
-       .psy = {
-               .name                   = "main-battery",
-               .type                   = POWER_SUPPLY_TYPE_BATTERY,
-               .properties             = s3c_adc_main_bat_props,
-               .num_properties         = ARRAY_SIZE(s3c_adc_main_bat_props),
-               .get_property           = s3c_adc_bat_get_property,
-               .external_power_changed = s3c_adc_bat_ext_power_changed,
-               .use_for_apm            = 1,
-       },
+static const struct power_supply_desc main_bat_desc = {
+       .name                   = "main-battery",
+       .type                   = POWER_SUPPLY_TYPE_BATTERY,
+       .properties             = s3c_adc_main_bat_props,
+       .num_properties         = ARRAY_SIZE(s3c_adc_main_bat_props),
+       .get_property           = s3c_adc_bat_get_property,
+       .external_power_changed = s3c_adc_bat_ext_power_changed,
+       .use_for_apm            = 1,
 };
 
+static struct s3c_adc_bat main_bat;
+
 static void s3c_adc_bat_work(struct work_struct *work)
 {
        struct s3c_adc_bat *bat = &main_bat;
@@ -251,7 +251,7 @@ static void s3c_adc_bat_work(struct work_struct *work)
        int is_plugged;
        static int was_plugged;
 
-       is_plugged = power_supply_am_i_supplied(&bat->psy);
+       is_plugged = power_supply_am_i_supplied(bat->psy);
        bat->cable_plugged = is_plugged;
        if (is_plugged != was_plugged) {
                was_plugged = is_plugged;
@@ -279,7 +279,7 @@ static void s3c_adc_bat_work(struct work_struct *work)
                }
        }
 
-       power_supply_changed(&bat->psy);
+       power_supply_changed(bat->psy);
 }
 
 static irqreturn_t s3c_adc_bat_charged(int irq, void *dev_id)
@@ -310,16 +310,25 @@ static int s3c_adc_bat_probe(struct platform_device *pdev)
        main_bat.cable_plugged = 0;
        main_bat.status = POWER_SUPPLY_STATUS_DISCHARGING;
 
-       ret = power_supply_register(&pdev->dev, &main_bat.psy);
-       if (ret)
+       main_bat.psy = power_supply_register(&pdev->dev, &main_bat_desc, NULL);
+       if (IS_ERR(main_bat.psy)) {
+               ret = PTR_ERR(main_bat.psy);
                goto err_reg_main;
+       }
        if (pdata->backup_volt_mult) {
+               const struct power_supply_config psy_cfg
+                                               = { .drv_data = &backup_bat, };
+
                backup_bat.client = client;
                backup_bat.pdata = pdev->dev.platform_data;
                backup_bat.volt_value = -1;
-               ret = power_supply_register(&pdev->dev, &backup_bat.psy);
-               if (ret)
+               backup_bat.psy = power_supply_register(&pdev->dev,
+                                                      &backup_bat_desc,
+                                                      &psy_cfg);
+               if (IS_ERR(backup_bat.psy)) {
+                       ret = PTR_ERR(backup_bat.psy);
                        goto err_reg_backup;
+               }
        }
 
        INIT_DELAYED_WORK(&bat_work, s3c_adc_bat_work);
@@ -360,9 +369,9 @@ err_irq:
                gpio_free(pdata->gpio_charge_finished);
 err_gpio:
        if (pdata->backup_volt_mult)
-               power_supply_unregister(&backup_bat.psy);
+               power_supply_unregister(backup_bat.psy);
 err_reg_backup:
-       power_supply_unregister(&main_bat.psy);
+       power_supply_unregister(main_bat.psy);
 err_reg_main:
        return ret;
 }
@@ -372,9 +381,9 @@ static int s3c_adc_bat_remove(struct platform_device *pdev)
        struct s3c_adc_client *client = platform_get_drvdata(pdev);
        struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data;
 
-       power_supply_unregister(&main_bat.psy);
+       power_supply_unregister(main_bat.psy);
        if (pdata->backup_volt_mult)
-               power_supply_unregister(&backup_bat.psy);
+               power_supply_unregister(backup_bat.psy);
 
        s3c_adc_release(client);
 
index c7b7b4018df32eea576abda6ed6d321552cd3ec7..de1178659d4b45beaee2ddcd04b1580236c0a3a1 100644 (file)
@@ -156,7 +156,7 @@ static enum power_supply_property sbs_properties[] = {
 
 struct sbs_info {
        struct i2c_client               *client;
-       struct power_supply             power_supply;
+       struct power_supply             *power_supply;
        struct sbs_platform_data        *pdata;
        bool                            is_present;
        bool                            gpio_detect;
@@ -391,7 +391,7 @@ static int sbs_get_battery_property(struct i2c_client *client,
                        chip->last_state = val->intval;
                else if (chip->last_state != val->intval) {
                        cancel_delayed_work_sync(&chip->work);
-                       power_supply_changed(&chip->power_supply);
+                       power_supply_changed(chip->power_supply);
                        chip->poll_time = 0;
                }
        } else {
@@ -556,8 +556,7 @@ static int sbs_get_property(struct power_supply *psy,
        union power_supply_propval *val)
 {
        int ret = 0;
-       struct sbs_info *chip = container_of(psy,
-                               struct sbs_info, power_supply);
+       struct sbs_info *chip = power_supply_get_drvdata(psy);
        struct i2c_client *client = chip->client;
 
        switch (psp) {
@@ -638,7 +637,7 @@ static int sbs_get_property(struct power_supply *psy,
        if (!chip->gpio_detect &&
                chip->is_present != (ret >= 0)) {
                chip->is_present = (ret >= 0);
-               power_supply_changed(&chip->power_supply);
+               power_supply_changed(chip->power_supply);
        }
 
 done:
@@ -671,9 +670,7 @@ static irqreturn_t sbs_irq(int irq, void *devid)
 
 static void sbs_external_power_changed(struct power_supply *psy)
 {
-       struct sbs_info *chip;
-
-       chip = container_of(psy, struct sbs_info, power_supply);
+       struct sbs_info *chip = power_supply_get_drvdata(psy);
 
        if (chip->ignore_changes > 0) {
                chip->ignore_changes--;
@@ -712,7 +709,7 @@ static void sbs_delayed_work(struct work_struct *work)
 
        if (chip->last_state != ret) {
                chip->poll_time = 0;
-               power_supply_changed(&chip->power_supply);
+               power_supply_changed(chip->power_supply);
                return;
        }
        if (chip->poll_time > 0) {
@@ -796,42 +793,48 @@ static struct sbs_platform_data *sbs_of_populate_pdata(
 }
 #endif
 
+static const struct power_supply_desc sbs_default_desc = {
+       .type = POWER_SUPPLY_TYPE_BATTERY,
+       .properties = sbs_properties,
+       .num_properties = ARRAY_SIZE(sbs_properties),
+       .get_property = sbs_get_property,
+       .external_power_changed = sbs_external_power_changed,
+};
+
 static int sbs_probe(struct i2c_client *client,
        const struct i2c_device_id *id)
 {
        struct sbs_info *chip;
+       struct power_supply_desc *sbs_desc;
        struct sbs_platform_data *pdata = client->dev.platform_data;
+       struct power_supply_config psy_cfg = {};
        int rc;
        int irq;
-       char *name;
 
-       name = kasprintf(GFP_KERNEL, "sbs-%s", dev_name(&client->dev));
-       if (!name) {
-               dev_err(&client->dev, "Failed to allocate device name\n");
+       sbs_desc = devm_kmemdup(&client->dev, &sbs_default_desc,
+                       sizeof(*sbs_desc), GFP_KERNEL);
+       if (!sbs_desc)
+               return -ENOMEM;
+
+       sbs_desc->name = devm_kasprintf(&client->dev, GFP_KERNEL, "sbs-%s",
+                       dev_name(&client->dev));
+       if (!sbs_desc->name)
                return -ENOMEM;
-       }
 
        chip = kzalloc(sizeof(struct sbs_info), GFP_KERNEL);
-       if (!chip) {
-               rc = -ENOMEM;
-               goto exit_free_name;
-       }
+       if (!chip)
+               return -ENOMEM;
 
        chip->client = client;
        chip->enable_detection = false;
        chip->gpio_detect = false;
-       chip->power_supply.name = name;
-       chip->power_supply.type = POWER_SUPPLY_TYPE_BATTERY;
-       chip->power_supply.properties = sbs_properties;
-       chip->power_supply.num_properties = ARRAY_SIZE(sbs_properties);
-       chip->power_supply.get_property = sbs_get_property;
-       chip->power_supply.of_node = client->dev.of_node;
+       psy_cfg.of_node = client->dev.of_node;
+       psy_cfg.drv_data = chip;
        /* ignore first notification of external change, it is generated
         * from the power_supply_register call back
         */
        chip->ignore_changes = 1;
        chip->last_state = POWER_SUPPLY_STATUS_UNKNOWN;
-       chip->power_supply.external_power_changed = sbs_external_power_changed;
 
        pdata = sbs_of_populate_pdata(client);
 
@@ -870,7 +873,7 @@ static int sbs_probe(struct i2c_client *client,
 
        rc = request_irq(irq, sbs_irq,
                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-               dev_name(&client->dev), &chip->power_supply);
+               dev_name(&client->dev), chip->power_supply);
        if (rc) {
                dev_warn(&client->dev, "Failed to request irq: %d\n", rc);
                gpio_free(pdata->battery_detect);
@@ -892,10 +895,12 @@ skip_gpio:
                goto exit_psupply;
        }
 
-       rc = power_supply_register(&client->dev, &chip->power_supply);
-       if (rc) {
+       chip->power_supply = power_supply_register(&client->dev, sbs_desc,
+                                                  &psy_cfg);
+       if (IS_ERR(chip->power_supply)) {
                dev_err(&client->dev,
                        "%s: Failed to register power supply\n", __func__);
+               rc = PTR_ERR(chip->power_supply);
                goto exit_psupply;
        }
 
@@ -910,15 +915,12 @@ skip_gpio:
 
 exit_psupply:
        if (chip->irq)
-               free_irq(chip->irq, &chip->power_supply);
+               free_irq(chip->irq, chip->power_supply);
        if (chip->gpio_detect)
                gpio_free(pdata->battery_detect);
 
        kfree(chip);
 
-exit_free_name:
-       kfree(name);
-
        return rc;
 }
 
@@ -927,15 +929,14 @@ static int sbs_remove(struct i2c_client *client)
        struct sbs_info *chip = i2c_get_clientdata(client);
 
        if (chip->irq)
-               free_irq(chip->irq, &chip->power_supply);
+               free_irq(chip->irq, chip->power_supply);
        if (chip->gpio_detect)
                gpio_free(chip->pdata->battery_detect);
 
-       power_supply_unregister(&chip->power_supply);
+       power_supply_unregister(chip->power_supply);
 
        cancel_delayed_work_sync(&chip->work);
 
-       kfree(chip->power_supply.name);
        kfree(chip);
        chip = NULL;
 
index acf84e80fe986c2c577f7b0d789510c62801c9c1..0b60a0b5878bd4ccc99972644b3552ae15bff4a1 100644 (file)
@@ -139,9 +139,9 @@ struct smb347_charger {
        struct mutex            lock;
        struct device           *dev;
        struct regmap           *regmap;
-       struct power_supply     mains;
-       struct power_supply     usb;
-       struct power_supply     battery;
+       struct power_supply     *mains;
+       struct power_supply     *usb;
+       struct power_supply     *battery;
        bool                    mains_online;
        bool                    usb_online;
        bool                    charging_enabled;
@@ -741,7 +741,7 @@ static irqreturn_t smb347_interrupt(int irq, void *data)
         */
        if (stat_c & STAT_C_CHARGER_ERROR) {
                dev_err(smb->dev, "charging stopped due to charger error\n");
-               power_supply_changed(&smb->battery);
+               power_supply_changed(smb->battery);
                handled = true;
        }
 
@@ -752,7 +752,7 @@ static irqreturn_t smb347_interrupt(int irq, void *data)
         */
        if (irqstat_c & (IRQSTAT_C_TERMINATION_IRQ | IRQSTAT_C_TAPER_IRQ)) {
                if (irqstat_c & IRQSTAT_C_TERMINATION_STAT)
-                       power_supply_changed(&smb->battery);
+                       power_supply_changed(smb->battery);
                dev_dbg(smb->dev, "going to HW maintenance mode\n");
                handled = true;
        }
@@ -766,7 +766,7 @@ static irqreturn_t smb347_interrupt(int irq, void *data)
 
                if (irqstat_d & IRQSTAT_D_CHARGE_TIMEOUT_STAT)
                        dev_warn(smb->dev, "charging stopped due to timeout\n");
-               power_supply_changed(&smb->battery);
+               power_supply_changed(smb->battery);
                handled = true;
        }
 
@@ -778,9 +778,9 @@ static irqreturn_t smb347_interrupt(int irq, void *data)
                if (smb347_update_ps_status(smb) > 0) {
                        smb347_start_stop_charging(smb);
                        if (smb->pdata->use_mains)
-                               power_supply_changed(&smb->mains);
+                               power_supply_changed(smb->mains);
                        if (smb->pdata->use_usb)
-                               power_supply_changed(&smb->usb);
+                               power_supply_changed(smb->usb);
                }
                handled = true;
        }
@@ -842,7 +842,8 @@ static int smb347_irq_init(struct smb347_charger *smb,
                goto fail;
 
        ret = request_threaded_irq(irq, NULL, smb347_interrupt,
-                                  IRQF_TRIGGER_FALLING, client->name, smb);
+                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                  client->name, smb);
        if (ret < 0)
                goto fail_gpio;
 
@@ -934,8 +935,7 @@ static int smb347_mains_get_property(struct power_supply *psy,
                                     enum power_supply_property prop,
                                     union power_supply_propval *val)
 {
-       struct smb347_charger *smb =
-               container_of(psy, struct smb347_charger, mains);
+       struct smb347_charger *smb = power_supply_get_drvdata(psy);
        int ret;
 
        switch (prop) {
@@ -976,8 +976,7 @@ static int smb347_usb_get_property(struct power_supply *psy,
                                   enum power_supply_property prop,
                                   union power_supply_propval *val)
 {
-       struct smb347_charger *smb =
-               container_of(psy, struct smb347_charger, usb);
+       struct smb347_charger *smb = power_supply_get_drvdata(psy);
        int ret;
 
        switch (prop) {
@@ -1063,8 +1062,7 @@ static int smb347_battery_get_property(struct power_supply *psy,
                                       enum power_supply_property prop,
                                       union power_supply_propval *val)
 {
-       struct smb347_charger *smb =
-                       container_of(psy, struct smb347_charger, battery);
+       struct smb347_charger *smb = power_supply_get_drvdata(psy);
        const struct smb347_charger_platform_data *pdata = smb->pdata;
        int ret;
 
@@ -1188,11 +1186,36 @@ static const struct regmap_config smb347_regmap = {
        .readable_reg   = smb347_readable_reg,
 };
 
+static const struct power_supply_desc smb347_mains_desc = {
+       .name           = "smb347-mains",
+       .type           = POWER_SUPPLY_TYPE_MAINS,
+       .get_property   = smb347_mains_get_property,
+       .properties     = smb347_mains_properties,
+       .num_properties = ARRAY_SIZE(smb347_mains_properties),
+};
+
+static const struct power_supply_desc smb347_usb_desc = {
+       .name           = "smb347-usb",
+       .type           = POWER_SUPPLY_TYPE_USB,
+       .get_property   = smb347_usb_get_property,
+       .properties     = smb347_usb_properties,
+       .num_properties = ARRAY_SIZE(smb347_usb_properties),
+};
+
+static const struct power_supply_desc smb347_battery_desc = {
+       .name           = "smb347-battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .get_property   = smb347_battery_get_property,
+       .properties     = smb347_battery_properties,
+       .num_properties = ARRAY_SIZE(smb347_battery_properties),
+};
+
 static int smb347_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
        static char *battery[] = { "smb347-battery" };
        const struct smb347_charger_platform_data *pdata;
+       struct power_supply_config mains_usb_cfg = {}, battery_cfg = {};
        struct device *dev = &client->dev;
        struct smb347_charger *smb;
        int ret;
@@ -1222,49 +1245,35 @@ static int smb347_probe(struct i2c_client *client,
        if (ret < 0)
                return ret;
 
+       mains_usb_cfg.supplied_to = battery;
+       mains_usb_cfg.num_supplicants = ARRAY_SIZE(battery);
+       mains_usb_cfg.drv_data = smb;
        if (smb->pdata->use_mains) {
-               smb->mains.name = "smb347-mains";
-               smb->mains.type = POWER_SUPPLY_TYPE_MAINS;
-               smb->mains.get_property = smb347_mains_get_property;
-               smb->mains.properties = smb347_mains_properties;
-               smb->mains.num_properties = ARRAY_SIZE(smb347_mains_properties);
-               smb->mains.supplied_to = battery;
-               smb->mains.num_supplicants = ARRAY_SIZE(battery);
-               ret = power_supply_register(dev, &smb->mains);
-               if (ret < 0)
-                       return ret;
+               smb->mains = power_supply_register(dev, &smb347_mains_desc,
+                                                  &mains_usb_cfg);
+               if (IS_ERR(smb->mains))
+                       return PTR_ERR(smb->mains);
        }
 
        if (smb->pdata->use_usb) {
-               smb->usb.name = "smb347-usb";
-               smb->usb.type = POWER_SUPPLY_TYPE_USB;
-               smb->usb.get_property = smb347_usb_get_property;
-               smb->usb.properties = smb347_usb_properties;
-               smb->usb.num_properties = ARRAY_SIZE(smb347_usb_properties);
-               smb->usb.supplied_to = battery;
-               smb->usb.num_supplicants = ARRAY_SIZE(battery);
-               ret = power_supply_register(dev, &smb->usb);
-               if (ret < 0) {
+               smb->usb = power_supply_register(dev, &smb347_usb_desc,
+                                                &mains_usb_cfg);
+               if (IS_ERR(smb->usb)) {
                        if (smb->pdata->use_mains)
-                               power_supply_unregister(&smb->mains);
-                       return ret;
+                               power_supply_unregister(smb->mains);
+                       return PTR_ERR(smb->usb);
                }
        }
 
-       smb->battery.name = "smb347-battery";
-       smb->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-       smb->battery.get_property = smb347_battery_get_property;
-       smb->battery.properties = smb347_battery_properties;
-       smb->battery.num_properties = ARRAY_SIZE(smb347_battery_properties);
-
-
-       ret = power_supply_register(dev, &smb->battery);
-       if (ret < 0) {
+       battery_cfg.drv_data = smb;
+       smb->battery = power_supply_register(dev, &smb347_battery_desc,
+                                            &battery_cfg);
+       if (IS_ERR(smb->battery)) {
                if (smb->pdata->use_usb)
-                       power_supply_unregister(&smb->usb);
+                       power_supply_unregister(smb->usb);
                if (smb->pdata->use_mains)
-                       power_supply_unregister(&smb->mains);
-               return ret;
+                       power_supply_unregister(smb->mains);
+               return PTR_ERR(smb->battery);
        }
 
        /*
@@ -1294,11 +1303,11 @@ static int smb347_remove(struct i2c_client *client)
                gpio_free(smb->pdata->irq_gpio);
        }
 
-       power_supply_unregister(&smb->battery);
+       power_supply_unregister(smb->battery);
        if (smb->pdata->use_usb)
-               power_supply_unregister(&smb->usb);
+               power_supply_unregister(smb->usb);
        if (smb->pdata->use_mains)
-               power_supply_unregister(&smb->mains);
+               power_supply_unregister(smb->mains);
        return 0;
 }
 
index f26b1fa00fe154a5dd88a241e02a987a41ed4520..f986e0cca7acf68300796563b6a80ceebd3881e4 100644 (file)
@@ -153,12 +153,12 @@ static char *test_power_ac_supplied_to[] = {
        "test_battery",
 };
 
-static struct power_supply test_power_supplies[] = {
+static struct power_supply *test_power_supplies[TEST_POWER_NUM];
+
+static const struct power_supply_desc test_power_desc[] = {
        [TEST_AC] = {
                .name = "test_ac",
                .type = POWER_SUPPLY_TYPE_MAINS,
-               .supplied_to = test_power_ac_supplied_to,
-               .num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to),
                .properties = test_power_ac_props,
                .num_properties = ARRAY_SIZE(test_power_ac_props),
                .get_property = test_power_get_ac_property,
@@ -173,14 +173,25 @@ static struct power_supply test_power_supplies[] = {
        [TEST_USB] = {
                .name = "test_usb",
                .type = POWER_SUPPLY_TYPE_USB,
-               .supplied_to = test_power_ac_supplied_to,
-               .num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to),
                .properties = test_power_ac_props,
                .num_properties = ARRAY_SIZE(test_power_ac_props),
                .get_property = test_power_get_usb_property,
        },
 };
 
+static const struct power_supply_config test_power_configs[] = {
+       {
+               /* test_ac */
+               .supplied_to = test_power_ac_supplied_to,
+               .num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to),
+       }, {
+               /* test_battery */
+       }, {
+               /* test_usb */
+               .supplied_to = test_power_ac_supplied_to,
+               .num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to),
+       },
+};
 
 static int __init test_power_init(void)
 {
@@ -188,12 +199,16 @@ static int __init test_power_init(void)
        int ret;
 
        BUILD_BUG_ON(TEST_POWER_NUM != ARRAY_SIZE(test_power_supplies));
+       BUILD_BUG_ON(TEST_POWER_NUM != ARRAY_SIZE(test_power_configs));
 
        for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) {
-               ret = power_supply_register(NULL, &test_power_supplies[i]);
-               if (ret) {
+               test_power_supplies[i] = power_supply_register(NULL,
+                                               &test_power_desc[i],
+                                               &test_power_configs[i]);
+               if (IS_ERR(test_power_supplies[i])) {
                        pr_err("%s: failed to register %s\n", __func__,
-                               test_power_supplies[i].name);
+                               test_power_desc[i].name);
+                       ret = PTR_ERR(test_power_supplies[i]);
                        goto failed;
                }
        }
@@ -202,7 +217,7 @@ static int __init test_power_init(void)
        return 0;
 failed:
        while (--i >= 0)
-               power_supply_unregister(&test_power_supplies[i]);
+               power_supply_unregister(test_power_supplies[i]);
        return ret;
 }
 module_init(test_power_init);
@@ -216,13 +231,13 @@ static void __exit test_power_exit(void)
        usb_online = 0;
        battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
        for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++)
-               power_supply_changed(&test_power_supplies[i]);
+               power_supply_changed(test_power_supplies[i]);
        pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n",
                __func__);
        ssleep(10);
 
        for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++)
-               power_supply_unregister(&test_power_supplies[i]);
+               power_supply_unregister(test_power_supplies[i]);
 
        module_initialized = false;
 }
@@ -320,7 +335,7 @@ static inline void signal_power_supply_changed(struct power_supply *psy)
 static int param_set_ac_online(const char *key, const struct kernel_param *kp)
 {
        ac_online = map_get_value(map_ac_online, key, ac_online);
-       signal_power_supply_changed(&test_power_supplies[TEST_AC]);
+       signal_power_supply_changed(test_power_supplies[TEST_AC]);
        return 0;
 }
 
@@ -333,7 +348,7 @@ static int param_get_ac_online(char *buffer, const struct kernel_param *kp)
 static int param_set_usb_online(const char *key, const struct kernel_param *kp)
 {
        usb_online = map_get_value(map_ac_online, key, usb_online);
-       signal_power_supply_changed(&test_power_supplies[TEST_USB]);
+       signal_power_supply_changed(test_power_supplies[TEST_USB]);
        return 0;
 }
 
@@ -347,7 +362,7 @@ static int param_set_battery_status(const char *key,
                                        const struct kernel_param *kp)
 {
        battery_status = map_get_value(map_status, key, battery_status);
-       signal_power_supply_changed(&test_power_supplies[TEST_BATTERY]);
+       signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
        return 0;
 }
 
@@ -361,7 +376,7 @@ static int param_set_battery_health(const char *key,
                                        const struct kernel_param *kp)
 {
        battery_health = map_get_value(map_health, key, battery_health);
-       signal_power_supply_changed(&test_power_supplies[TEST_BATTERY]);
+       signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
        return 0;
 }
 
@@ -375,7 +390,7 @@ static int param_set_battery_present(const char *key,
                                        const struct kernel_param *kp)
 {
        battery_present = map_get_value(map_present, key, battery_present);
-       signal_power_supply_changed(&test_power_supplies[TEST_AC]);
+       signal_power_supply_changed(test_power_supplies[TEST_AC]);
        return 0;
 }
 
@@ -391,7 +406,7 @@ static int param_set_battery_technology(const char *key,
 {
        battery_technology = map_get_value(map_technology, key,
                                                battery_technology);
-       signal_power_supply_changed(&test_power_supplies[TEST_BATTERY]);
+       signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
        return 0;
 }
 
@@ -412,7 +427,7 @@ static int param_set_battery_capacity(const char *key,
                return -EINVAL;
 
        battery_capacity = tmp;
-       signal_power_supply_changed(&test_power_supplies[TEST_BATTERY]);
+       signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
        return 0;
 }
 
@@ -427,7 +442,7 @@ static int param_set_battery_voltage(const char *key,
                return -EINVAL;
 
        battery_voltage = tmp;
-       signal_power_supply_changed(&test_power_supplies[TEST_BATTERY]);
+       signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
        return 0;
 }
 
index f4d80df627c7097470a45638bf0392a688d50b93..6e88c1b37945537fa6a3b08489f65ea81b10a2a9 100644 (file)
@@ -26,7 +26,7 @@ static struct work_struct bat_work;
 
 struct tosa_bat {
        int status;
-       struct power_supply psy;
+       struct power_supply *psy;
        int full_chrg;
 
        struct mutex work_lock; /* protects data */
@@ -61,7 +61,7 @@ static unsigned long tosa_read_bat(struct tosa_bat *bat)
        mutex_lock(&bat_lock);
        gpio_set_value(bat->gpio_bat, 1);
        msleep(5);
-       value = wm97xx_read_aux_adc(dev_get_drvdata(bat->psy.dev->parent),
+       value = wm97xx_read_aux_adc(dev_get_drvdata(bat->psy->dev.parent),
                        bat->adc_bat);
        gpio_set_value(bat->gpio_bat, 0);
        mutex_unlock(&bat_lock);
@@ -81,7 +81,7 @@ static unsigned long tosa_read_temp(struct tosa_bat *bat)
        mutex_lock(&bat_lock);
        gpio_set_value(bat->gpio_temp, 1);
        msleep(5);
-       value = wm97xx_read_aux_adc(dev_get_drvdata(bat->psy.dev->parent),
+       value = wm97xx_read_aux_adc(dev_get_drvdata(bat->psy->dev.parent),
                        bat->adc_temp);
        gpio_set_value(bat->gpio_temp, 0);
        mutex_unlock(&bat_lock);
@@ -96,7 +96,7 @@ static int tosa_bat_get_property(struct power_supply *psy,
                            union power_supply_propval *val)
 {
        int ret = 0;
-       struct tosa_bat *bat = container_of(psy, struct tosa_bat, psy);
+       struct tosa_bat *bat = power_supply_get_drvdata(psy);
 
        if (bat->is_present && !bat->is_present(bat)
                        && psp != POWER_SUPPLY_PROP_PRESENT) {
@@ -158,14 +158,14 @@ static irqreturn_t tosa_bat_gpio_isr(int irq, void *data)
 static void tosa_bat_update(struct tosa_bat *bat)
 {
        int old;
-       struct power_supply *psy = &bat->psy;
+       struct power_supply *psy = bat->psy;
 
        mutex_lock(&bat->work_lock);
 
        old = bat->status;
 
        if (bat->is_present && !bat->is_present(bat)) {
-               printk(KERN_NOTICE "%s not present\n", psy->name);
+               printk(KERN_NOTICE "%s not present\n", psy->desc->name);
                bat->status = POWER_SUPPLY_STATUS_UNKNOWN;
                bat->full_chrg = -1;
        } else if (power_supply_am_i_supplied(psy)) {
@@ -222,18 +222,38 @@ static enum power_supply_property tosa_bat_bu_props[] = {
        POWER_SUPPLY_PROP_PRESENT,
 };
 
+static const struct power_supply_desc tosa_bat_main_desc = {
+       .name           = "main-battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .properties     = tosa_bat_main_props,
+       .num_properties = ARRAY_SIZE(tosa_bat_main_props),
+       .get_property   = tosa_bat_get_property,
+       .external_power_changed = tosa_bat_external_power_changed,
+       .use_for_apm    = 1,
+};
+
+static const struct power_supply_desc tosa_bat_jacket_desc = {
+       .name           = "jacket-battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .properties     = tosa_bat_main_props,
+       .num_properties = ARRAY_SIZE(tosa_bat_main_props),
+       .get_property   = tosa_bat_get_property,
+       .external_power_changed = tosa_bat_external_power_changed,
+};
+
+static const struct power_supply_desc tosa_bat_bu_desc = {
+       .name           = "backup-battery",
+       .type           = POWER_SUPPLY_TYPE_BATTERY,
+       .properties     = tosa_bat_bu_props,
+       .num_properties = ARRAY_SIZE(tosa_bat_bu_props),
+       .get_property   = tosa_bat_get_property,
+       .external_power_changed = tosa_bat_external_power_changed,
+};
+
 static struct tosa_bat tosa_bat_main = {
        .status = POWER_SUPPLY_STATUS_DISCHARGING,
        .full_chrg = -1,
-       .psy = {
-               .name           = "main-battery",
-               .type           = POWER_SUPPLY_TYPE_BATTERY,
-               .properties     = tosa_bat_main_props,
-               .num_properties = ARRAY_SIZE(tosa_bat_main_props),
-               .get_property   = tosa_bat_get_property,
-               .external_power_changed = tosa_bat_external_power_changed,
-               .use_for_apm    = 1,
-       },
+       .psy = NULL,
 
        .gpio_full = TOSA_GPIO_BAT0_CRG,
        .gpio_charge_off = TOSA_GPIO_CHARGE_OFF,
@@ -254,14 +274,7 @@ static struct tosa_bat tosa_bat_main = {
 static struct tosa_bat tosa_bat_jacket = {
        .status = POWER_SUPPLY_STATUS_DISCHARGING,
        .full_chrg = -1,
-       .psy = {
-               .name           = "jacket-battery",
-               .type           = POWER_SUPPLY_TYPE_BATTERY,
-               .properties     = tosa_bat_main_props,
-               .num_properties = ARRAY_SIZE(tosa_bat_main_props),
-               .get_property   = tosa_bat_get_property,
-               .external_power_changed = tosa_bat_external_power_changed,
-       },
+       .psy = NULL,
 
        .is_present = tosa_jacket_bat_is_present,
        .gpio_full = TOSA_GPIO_BAT1_CRG,
@@ -283,15 +296,7 @@ static struct tosa_bat tosa_bat_jacket = {
 static struct tosa_bat tosa_bat_bu = {
        .status = POWER_SUPPLY_STATUS_UNKNOWN,
        .full_chrg = -1,
-
-       .psy = {
-               .name           = "backup-battery",
-               .type           = POWER_SUPPLY_TYPE_BATTERY,
-               .properties     = tosa_bat_bu_props,
-               .num_properties = ARRAY_SIZE(tosa_bat_bu_props),
-               .get_property   = tosa_bat_get_property,
-               .external_power_changed = tosa_bat_external_power_changed,
-       },
+       .psy = NULL,
 
        .gpio_full = -1,
        .gpio_charge_off = -1,
@@ -345,6 +350,9 @@ static int tosa_bat_resume(struct platform_device *dev)
 static int tosa_bat_probe(struct platform_device *dev)
 {
        int ret;
+       struct power_supply_config main_psy_cfg = {},
+                                  jacket_psy_cfg = {},
+                                  bu_psy_cfg = {};
 
        if (!machine_is_tosa())
                return -ENODEV;
@@ -358,15 +366,31 @@ static int tosa_bat_probe(struct platform_device *dev)
 
        INIT_WORK(&bat_work, tosa_bat_work);
 
-       ret = power_supply_register(&dev->dev, &tosa_bat_main.psy);
-       if (ret)
+       main_psy_cfg.drv_data = &tosa_bat_main;
+       tosa_bat_main.psy = power_supply_register(&dev->dev,
+                                                 &tosa_bat_main_desc,
+                                                 &main_psy_cfg);
+       if (IS_ERR(tosa_bat_main.psy)) {
+               ret = PTR_ERR(tosa_bat_main.psy);
                goto err_psy_reg_main;
-       ret = power_supply_register(&dev->dev, &tosa_bat_jacket.psy);
-       if (ret)
+       }
+
+       jacket_psy_cfg.drv_data = &tosa_bat_jacket;
+       tosa_bat_jacket.psy = power_supply_register(&dev->dev,
+                                                   &tosa_bat_jacket_desc,
+                                                   &jacket_psy_cfg);
+       if (IS_ERR(tosa_bat_jacket.psy)) {
+               ret = PTR_ERR(tosa_bat_jacket.psy);
                goto err_psy_reg_jacket;
-       ret = power_supply_register(&dev->dev, &tosa_bat_bu.psy);
-       if (ret)
+       }
+
+       bu_psy_cfg.drv_data = &tosa_bat_bu;
+       tosa_bat_bu.psy = power_supply_register(&dev->dev, &tosa_bat_bu_desc,
+                                               &bu_psy_cfg);
+       if (IS_ERR(tosa_bat_bu.psy)) {
+               ret = PTR_ERR(tosa_bat_bu.psy);
                goto err_psy_reg_bu;
+       }
 
        ret = request_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG),
                                tosa_bat_gpio_isr,
@@ -395,11 +419,11 @@ static int tosa_bat_probe(struct platform_device *dev)
 err_req_jacket:
        free_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG), &tosa_bat_main);
 err_req_main:
-       power_supply_unregister(&tosa_bat_bu.psy);
+       power_supply_unregister(tosa_bat_bu.psy);
 err_psy_reg_bu:
-       power_supply_unregister(&tosa_bat_jacket.psy);
+       power_supply_unregister(tosa_bat_jacket.psy);
 err_psy_reg_jacket:
-       power_supply_unregister(&tosa_bat_main.psy);
+       power_supply_unregister(tosa_bat_main.psy);
 err_psy_reg_main:
 
        /* see comment in tosa_bat_remove */
@@ -415,9 +439,9 @@ static int tosa_bat_remove(struct platform_device *dev)
        free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket);
        free_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG), &tosa_bat_main);
 
-       power_supply_unregister(&tosa_bat_bu.psy);
-       power_supply_unregister(&tosa_bat_jacket.psy);
-       power_supply_unregister(&tosa_bat_main.psy);
+       power_supply_unregister(tosa_bat_bu.psy);
+       power_supply_unregister(tosa_bat_jacket.psy);
+       power_supply_unregister(tosa_bat_main.psy);
 
        /*
         * Now cancel the bat_work.  We won't get any more schedules,
index 0f4e5971dff5b979331753d08f53d6e27b4fbf33..7e8fbd29c30eee6874bda989e4552972040e8b52 100644 (file)
@@ -43,7 +43,7 @@ struct tps65090_charger {
        int     irq;
        struct task_struct      *poll_task;
        bool                    passive_mode;
-       struct power_supply     ac;
+       struct power_supply     *ac;
        struct tps65090_platform_data *pdata;
 };
 
@@ -135,8 +135,7 @@ static int tps65090_ac_get_property(struct power_supply *psy,
                        enum power_supply_property psp,
                        union power_supply_propval *val)
 {
-       struct tps65090_charger *charger = container_of(psy,
-                                       struct tps65090_charger, ac);
+       struct tps65090_charger *charger = power_supply_get_drvdata(psy);
 
        if (psp == POWER_SUPPLY_PROP_ONLINE) {
                val->intval = charger->ac_online;
@@ -190,7 +189,7 @@ static irqreturn_t tps65090_charger_isr(int irq, void *dev_id)
        }
 
        if (charger->prev_ac_online != charger->ac_online)
-               power_supply_changed(&charger->ac);
+               power_supply_changed(charger->ac);
 
        return IRQ_HANDLED;
 }
@@ -229,10 +228,19 @@ static int tps65090_charger_poll_task(void *data)
        return 0;
 }
 
+static const struct power_supply_desc tps65090_charger_desc = {
+       .name                   = "tps65090-ac",
+       .type                   = POWER_SUPPLY_TYPE_MAINS,
+       .get_property           = tps65090_ac_get_property,
+       .properties             = tps65090_ac_props,
+       .num_properties         = ARRAY_SIZE(tps65090_ac_props),
+};
+
 static int tps65090_charger_probe(struct platform_device *pdev)
 {
        struct tps65090_charger *cdata;
        struct tps65090_platform_data *pdata;
+       struct power_supply_config psy_cfg = {};
        uint8_t status1 = 0;
        int ret;
        int irq;
@@ -259,19 +267,16 @@ static int tps65090_charger_probe(struct platform_device *pdev)
        cdata->dev                      = &pdev->dev;
        cdata->pdata                    = pdata;
 
-       cdata->ac.name                  = "tps65090-ac";
-       cdata->ac.type                  = POWER_SUPPLY_TYPE_MAINS;
-       cdata->ac.get_property          = tps65090_ac_get_property;
-       cdata->ac.properties            = tps65090_ac_props;
-       cdata->ac.num_properties        = ARRAY_SIZE(tps65090_ac_props);
-       cdata->ac.supplied_to           = pdata->supplied_to;
-       cdata->ac.num_supplicants       = pdata->num_supplicants;
-       cdata->ac.of_node               = pdev->dev.of_node;
-
-       ret = power_supply_register(&pdev->dev, &cdata->ac);
-       if (ret) {
+       psy_cfg.supplied_to             = pdata->supplied_to;
+       psy_cfg.num_supplicants         = pdata->num_supplicants;
+       psy_cfg.of_node                 = pdev->dev.of_node;
+       psy_cfg.drv_data                = cdata;
+
+       cdata->ac = power_supply_register(&pdev->dev, &tps65090_charger_desc,
+                       &psy_cfg);
+       if (IS_ERR(cdata->ac)) {
                dev_err(&pdev->dev, "failed: power supply register\n");
-               return ret;
+               return PTR_ERR(cdata->ac);
        }
 
        irq = platform_get_irq(pdev, 0);
@@ -301,7 +306,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
                        goto fail_unregister_supply;
                }
                cdata->ac_online = 1;
-               power_supply_changed(&cdata->ac);
+               power_supply_changed(cdata->ac);
        }
 
        if (irq != -ENXIO) {
@@ -328,7 +333,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
        return 0;
 
 fail_unregister_supply:
-       power_supply_unregister(&cdata->ac);
+       power_supply_unregister(cdata->ac);
 
        return ret;
 }
@@ -339,12 +344,12 @@ static int tps65090_charger_remove(struct platform_device *pdev)
 
        if (cdata->irq == -ENXIO)
                kthread_stop(cdata->poll_task);
-       power_supply_unregister(&cdata->ac);
+       power_supply_unregister(cdata->ac);
 
        return 0;
 }
 
-static struct of_device_id of_tps65090_charger_match[] = {
+static const struct of_device_id of_tps65090_charger_match[] = {
        { .compatible = "ti,tps65090-charger", },
        { /* end */ }
 };
index d35b83e635b500188b79bb3ddbbd31df986f7b15..02a522cb775377177760b06f5bc40bed6506b5bf 100644 (file)
@@ -87,8 +87,8 @@ MODULE_PARM_DESC(allow_usb, "Allow USB charge drawing default current");
 
 struct twl4030_bci {
        struct device           *dev;
-       struct power_supply     ac;
-       struct power_supply     usb;
+       struct power_supply     *ac;
+       struct power_supply     *usb;
        struct usb_phy          *transceiver;
        struct notifier_block   usb_nb;
        struct work_struct      work;
@@ -318,8 +318,8 @@ static irqreturn_t twl4030_charger_interrupt(int irq, void *arg)
        struct twl4030_bci *bci = arg;
 
        dev_dbg(bci->dev, "CHG_PRES irq\n");
-       power_supply_changed(&bci->ac);
-       power_supply_changed(&bci->usb);
+       power_supply_changed(bci->ac);
+       power_supply_changed(bci->usb);
 
        return IRQ_HANDLED;
 }
@@ -347,8 +347,8 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg)
 
        if (irqs1 & (TWL4030_ICHGLOW | TWL4030_ICHGEOC)) {
                /* charger state change, inform the core */
-               power_supply_changed(&bci->ac);
-               power_supply_changed(&bci->usb);
+               power_supply_changed(bci->ac);
+               power_supply_changed(bci->usb);
        }
 
        /* various monitoring events, for now we just log them here */
@@ -463,7 +463,7 @@ static int twl4030_bci_get_property(struct power_supply *psy,
                                    enum power_supply_property psp,
                                    union power_supply_propval *val)
 {
-       struct twl4030_bci *bci = dev_get_drvdata(psy->dev->parent);
+       struct twl4030_bci *bci = dev_get_drvdata(psy->dev.parent);
        int is_charging;
        int state;
        int ret;
@@ -472,7 +472,7 @@ static int twl4030_bci_get_property(struct power_supply *psy,
        if (state < 0)
                return state;
 
-       if (psy->type == POWER_SUPPLY_TYPE_USB)
+       if (psy->desc->type == POWER_SUPPLY_TYPE_USB)
                is_charging = state & TWL4030_MSTATEC_USB;
        else
                is_charging = state & TWL4030_MSTATEC_AC;
@@ -488,7 +488,7 @@ static int twl4030_bci_get_property(struct power_supply *psy,
                /* charging must be active for meaningful result */
                if (!is_charging)
                        return -ENODATA;
-               if (psy->type == POWER_SUPPLY_TYPE_USB) {
+               if (psy->desc->type == POWER_SUPPLY_TYPE_USB) {
                        ret = twl4030bci_read_adc_val(TWL4030_BCIVBUS);
                        if (ret < 0)
                                return ret;
@@ -558,6 +558,22 @@ twl4030_bci_parse_dt(struct device *dev)
 }
 #endif
 
+static const struct power_supply_desc twl4030_bci_ac_desc = {
+       .name           = "twl4030_ac",
+       .type           = POWER_SUPPLY_TYPE_MAINS,
+       .properties     = twl4030_charger_props,
+       .num_properties = ARRAY_SIZE(twl4030_charger_props),
+       .get_property   = twl4030_bci_get_property,
+};
+
+static const struct power_supply_desc twl4030_bci_usb_desc = {
+       .name           = "twl4030_usb",
+       .type           = POWER_SUPPLY_TYPE_USB,
+       .properties     = twl4030_charger_props,
+       .num_properties = ARRAY_SIZE(twl4030_charger_props),
+       .get_property   = twl4030_bci_get_property,
+};
+
 static int __init twl4030_bci_probe(struct platform_device *pdev)
 {
        struct twl4030_bci *bci;
@@ -584,28 +600,21 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, bci);
-       bci->ac.name = "twl4030_ac";
-       bci->ac.type = POWER_SUPPLY_TYPE_MAINS;
-       bci->ac.properties = twl4030_charger_props;
-       bci->ac.num_properties = ARRAY_SIZE(twl4030_charger_props);
-       bci->ac.get_property = twl4030_bci_get_property;
 
-       ret = power_supply_register(&pdev->dev, &bci->ac);
-       if (ret) {
+       bci->ac = 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;
        }
 
-       bci->usb.name = "twl4030_usb";
-       bci->usb.type = POWER_SUPPLY_TYPE_USB;
-       bci->usb.properties = twl4030_charger_props;
-       bci->usb.num_properties = ARRAY_SIZE(twl4030_charger_props);
-       bci->usb.get_property = twl4030_bci_get_property;
-
        bci->usb_reg = regulator_get(bci->dev, "bci3v1");
 
-       ret = power_supply_register(&pdev->dev, &bci->usb);
-       if (ret) {
+       bci->usb = 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;
        }
@@ -670,9 +679,9 @@ fail_unmask_interrupts:
 fail_bci_irq:
        free_irq(bci->irq_chg, bci);
 fail_chg_irq:
-       power_supply_unregister(&bci->usb);
+       power_supply_unregister(bci->usb);
 fail_register_usb:
-       power_supply_unregister(&bci->ac);
+       power_supply_unregister(bci->ac);
 fail_register_ac:
 fail_no_battery:
        kfree(bci);
@@ -700,8 +709,8 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
        }
        free_irq(bci->irq_bci, bci);
        free_irq(bci->irq_chg, bci);
-       power_supply_unregister(&bci->usb);
-       power_supply_unregister(&bci->ac);
+       power_supply_unregister(bci->usb);
+       power_supply_unregister(bci->ac);
        kfree(bci);
 
        return 0;
index 7ef445a6cfa6d824f297c39ad0b93555126fd82e..f5817e422d6499aafc097791301092ce7d763751 100644 (file)
 #include <linux/sort.h>
 #include <linux/i2c/twl4030-madc.h>
 #include <linux/power/twl4030_madc_battery.h>
+#include <linux/iio/consumer.h>
 
 struct twl4030_madc_battery {
-       struct power_supply psy;
+       struct power_supply *psy;
        struct twl4030_madc_bat_platform_data *pdata;
+       struct iio_channel *channel_temp;
+       struct iio_channel *channel_ichg;
+       struct iio_channel *channel_vbat;
 };
 
 static enum power_supply_property twl4030_madc_bat_props[] = {
@@ -38,43 +42,34 @@ static enum power_supply_property twl4030_madc_bat_props[] = {
        POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
 };
 
-static int madc_read(int index)
+static int madc_read(struct iio_channel *channel)
 {
-       struct twl4030_madc_request req;
-       int val;
+       int val, err;
+       err = iio_read_channel_processed(channel, &val);
+       if (err < 0)
+               return err;
 
-       req.channels = index;
-       req.method = TWL4030_MADC_SW2;
-       req.type = TWL4030_MADC_WAIT;
-       req.do_avg = 0;
-       req.raw = false;
-       req.func_cb = NULL;
-
-       val = twl4030_madc_conversion(&req);
-       if (val < 0)
-               return val;
-
-       return req.rbuf[ffs(index) - 1];
+       return val;
 }
 
-static int twl4030_madc_bat_get_charging_status(void)
+static int twl4030_madc_bat_get_charging_status(struct twl4030_madc_battery *bt)
 {
-       return (madc_read(TWL4030_MADC_ICHG) > 0) ? 1 : 0;
+       return (madc_read(bt->channel_ichg) > 0) ? 1 : 0;
 }
 
-static int twl4030_madc_bat_get_voltage(void)
+static int twl4030_madc_bat_get_voltage(struct twl4030_madc_battery *bt)
 {
-       return madc_read(TWL4030_MADC_VBAT);
+       return madc_read(bt->channel_vbat);
 }
 
-static int twl4030_madc_bat_get_current(void)
+static int twl4030_madc_bat_get_current(struct twl4030_madc_battery *bt)
 {
-       return madc_read(TWL4030_MADC_ICHG) * 1000;
+       return madc_read(bt->channel_ichg) * 1000;
 }
 
-static int twl4030_madc_bat_get_temp(void)
+static int twl4030_madc_bat_get_temp(struct twl4030_madc_battery *bt)
 {
-       return madc_read(TWL4030_MADC_BTEMP) * 10;
+       return madc_read(bt->channel_temp) * 10;
 }
 
 static int twl4030_madc_bat_voltscale(struct twl4030_madc_battery *bat,
@@ -84,7 +79,7 @@ static int twl4030_madc_bat_voltscale(struct twl4030_madc_battery *bat,
        int i, res = 0;
 
        /* choose charging curve */
-       if (twl4030_madc_bat_get_charging_status())
+       if (twl4030_madc_bat_get_charging_status(bat))
                calibration = bat->pdata->charging;
        else
                calibration = bat->pdata->discharging;
@@ -113,29 +108,28 @@ static int twl4030_madc_bat_get_property(struct power_supply *psy,
                                        enum power_supply_property psp,
                                        union power_supply_propval *val)
 {
-       struct twl4030_madc_battery *bat = container_of(psy,
-                                       struct twl4030_madc_battery, psy);
+       struct twl4030_madc_battery *bat = power_supply_get_drvdata(psy);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
                if (twl4030_madc_bat_voltscale(bat,
-                               twl4030_madc_bat_get_voltage()) > 95)
+                               twl4030_madc_bat_get_voltage(bat)) > 95)
                        val->intval = POWER_SUPPLY_STATUS_FULL;
                else {
-                       if (twl4030_madc_bat_get_charging_status())
+                       if (twl4030_madc_bat_get_charging_status(bat))
                                val->intval = POWER_SUPPLY_STATUS_CHARGING;
                        else
                                val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
                }
                break;
        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-               val->intval = twl4030_madc_bat_get_voltage() * 1000;
+               val->intval = twl4030_madc_bat_get_voltage(bat) * 1000;
                break;
        case POWER_SUPPLY_PROP_TECHNOLOGY:
                val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
                break;
        case POWER_SUPPLY_PROP_CURRENT_NOW:
-               val->intval = twl4030_madc_bat_get_current();
+               val->intval = twl4030_madc_bat_get_current(bat);
                break;
        case POWER_SUPPLY_PROP_PRESENT:
                /* assume battery is always present */
@@ -143,23 +137,23 @@ static int twl4030_madc_bat_get_property(struct power_supply *psy,
                break;
        case POWER_SUPPLY_PROP_CHARGE_NOW: {
                        int percent = twl4030_madc_bat_voltscale(bat,
-                                       twl4030_madc_bat_get_voltage());
+                                       twl4030_madc_bat_get_voltage(bat));
                        val->intval = (percent * bat->pdata->capacity) / 100;
                        break;
                }
        case POWER_SUPPLY_PROP_CAPACITY:
                val->intval = twl4030_madc_bat_voltscale(bat,
-                                       twl4030_madc_bat_get_voltage());
+                                       twl4030_madc_bat_get_voltage(bat));
                break;
        case POWER_SUPPLY_PROP_CHARGE_FULL:
                val->intval = bat->pdata->capacity;
                break;
        case POWER_SUPPLY_PROP_TEMP:
-               val->intval = twl4030_madc_bat_get_temp();
+               val->intval = twl4030_madc_bat_get_temp(bat);
                break;
        case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: {
                        int percent = twl4030_madc_bat_voltscale(bat,
-                                       twl4030_madc_bat_get_voltage());
+                                       twl4030_madc_bat_get_voltage(bat));
                        /* in mAh */
                        int chg = (percent * (bat->pdata->capacity/1000))/100;
 
@@ -176,12 +170,19 @@ static int twl4030_madc_bat_get_property(struct power_supply *psy,
 
 static void twl4030_madc_bat_ext_changed(struct power_supply *psy)
 {
-       struct twl4030_madc_battery *bat = container_of(psy,
-                                       struct twl4030_madc_battery, psy);
-
-       power_supply_changed(&bat->psy);
+       power_supply_changed(psy);
 }
 
+static const struct power_supply_desc twl4030_madc_bat_desc = {
+       .name                   = "twl4030_battery",
+       .type                   = POWER_SUPPLY_TYPE_BATTERY,
+       .properties             = twl4030_madc_bat_props,
+       .num_properties         = ARRAY_SIZE(twl4030_madc_bat_props),
+       .get_property           = twl4030_madc_bat_get_property,
+       .external_power_changed = twl4030_madc_bat_ext_changed,
+
+};
+
 static int twl4030_cmp(const void *a, const void *b)
 {
        return ((struct twl4030_madc_bat_calibration *)b)->voltage -
@@ -192,19 +193,31 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev)
 {
        struct twl4030_madc_battery *twl4030_madc_bat;
        struct twl4030_madc_bat_platform_data *pdata = pdev->dev.platform_data;
+       struct power_supply_config psy_cfg = {};
+       int ret = 0;
 
-       twl4030_madc_bat = kzalloc(sizeof(*twl4030_madc_bat), GFP_KERNEL);
+       twl4030_madc_bat = devm_kzalloc(&pdev->dev, sizeof(*twl4030_madc_bat),
+                               GFP_KERNEL);
        if (!twl4030_madc_bat)
                return -ENOMEM;
 
-       twl4030_madc_bat->psy.name = "twl4030_battery";
-       twl4030_madc_bat->psy.type = POWER_SUPPLY_TYPE_BATTERY;
-       twl4030_madc_bat->psy.properties = twl4030_madc_bat_props;
-       twl4030_madc_bat->psy.num_properties =
-                                       ARRAY_SIZE(twl4030_madc_bat_props);
-       twl4030_madc_bat->psy.get_property = twl4030_madc_bat_get_property;
-       twl4030_madc_bat->psy.external_power_changed =
-                                       twl4030_madc_bat_ext_changed;
+       twl4030_madc_bat->channel_temp = iio_channel_get(&pdev->dev, "temp");
+       if (IS_ERR(twl4030_madc_bat->channel_temp)) {
+               ret = PTR_ERR(twl4030_madc_bat->channel_temp);
+               goto err;
+       }
+
+       twl4030_madc_bat->channel_ichg = iio_channel_get(&pdev->dev, "ichg");
+       if (IS_ERR(twl4030_madc_bat->channel_ichg)) {
+               ret = PTR_ERR(twl4030_madc_bat->channel_ichg);
+               goto err_temp;
+       }
+
+       twl4030_madc_bat->channel_vbat = iio_channel_get(&pdev->dev, "vbat");
+       if (IS_ERR(twl4030_madc_bat->channel_vbat)) {
+               ret = PTR_ERR(twl4030_madc_bat->channel_vbat);
+               goto err_ichg;
+       }
 
        /* sort charging and discharging calibration data */
        sort(pdata->charging, pdata->charging_size,
@@ -216,17 +229,36 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev)
 
        twl4030_madc_bat->pdata = pdata;
        platform_set_drvdata(pdev, twl4030_madc_bat);
-       power_supply_register(&pdev->dev, &twl4030_madc_bat->psy);
+       psy_cfg.drv_data = twl4030_madc_bat;
+       twl4030_madc_bat->psy = power_supply_register(&pdev->dev,
+                                                     &twl4030_madc_bat_desc,
+                                                     &psy_cfg);
+       if (IS_ERR(twl4030_madc_bat->psy)) {
+               ret = PTR_ERR(twl4030_madc_bat->psy);
+               goto err_vbat;
+       }
 
        return 0;
+
+err_vbat:
+       iio_channel_release(twl4030_madc_bat->channel_vbat);
+err_ichg:
+       iio_channel_release(twl4030_madc_bat->channel_ichg);
+err_temp:
+       iio_channel_release(twl4030_madc_bat->channel_temp);
+err:
+       return ret;
 }
 
 static int twl4030_madc_battery_remove(struct platform_device *pdev)
 {
        struct twl4030_madc_battery *bat = platform_get_drvdata(pdev);
 
-       power_supply_unregister(&bat->psy);
-       kfree(bat);
+       power_supply_unregister(bat->psy);
+
+       iio_channel_release(bat->channel_vbat);
+       iio_channel_release(bat->channel_ichg);
+       iio_channel_release(bat->channel_temp);
 
        return 0;
 }
@@ -243,3 +275,4 @@ module_platform_driver(twl4030_madc_battery_driver);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Lukas Märdian <lukas@goldelico.com>");
 MODULE_DESCRIPTION("twl4030_madc battery driver");
+MODULE_ALIAS("platform:twl4030_madc_battery");
index 56fb509f4be00834f964fa2636b35c97eebf6849..2e33109ca8c7b993247fb0f39a115254003dbbf7 100644 (file)
@@ -21,7 +21,8 @@
 
 struct wm831x_backup {
        struct wm831x *wm831x;
-       struct power_supply backup;
+       struct power_supply *backup;
+       struct power_supply_desc backup_desc;
        char name[20];
 };
 
@@ -115,7 +116,7 @@ static int wm831x_backup_get_prop(struct power_supply *psy,
                                  enum power_supply_property psp,
                                  union power_supply_propval *val)
 {
-       struct wm831x_backup *devdata = dev_get_drvdata(psy->dev->parent);
+       struct wm831x_backup *devdata = dev_get_drvdata(psy->dev.parent);
        struct wm831x *wm831x = devdata->wm831x;
        int ret = 0;
 
@@ -166,8 +167,6 @@ static int wm831x_backup_probe(struct platform_device *pdev)
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
        struct wm831x_backup *devdata;
-       struct power_supply *backup;
-       int ret;
 
        devdata = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_backup),
                                GFP_KERNEL);
@@ -177,8 +176,6 @@ static int wm831x_backup_probe(struct platform_device *pdev)
        devdata->wm831x = wm831x;
        platform_set_drvdata(pdev, devdata);
 
-       backup = &devdata->backup;
-
        /* We ignore configuration failures since we can still read
         * back the status without enabling the charger (which may
         * already be enabled anyway).
@@ -192,21 +189,22 @@ static int wm831x_backup_probe(struct platform_device *pdev)
                snprintf(devdata->name, sizeof(devdata->name),
                         "wm831x-backup");
 
-       backup->name = devdata->name;
-       backup->type = POWER_SUPPLY_TYPE_BATTERY;
-       backup->properties = wm831x_backup_props;
-       backup->num_properties = ARRAY_SIZE(wm831x_backup_props);
-       backup->get_property = wm831x_backup_get_prop;
-       ret = power_supply_register(&pdev->dev, backup);
+       devdata->backup_desc.name = devdata->name;
+       devdata->backup_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+       devdata->backup_desc.properties = wm831x_backup_props;
+       devdata->backup_desc.num_properties = ARRAY_SIZE(wm831x_backup_props);
+       devdata->backup_desc.get_property = wm831x_backup_get_prop;
+       devdata->backup = power_supply_register(&pdev->dev,
+                                               &devdata->backup_desc, NULL);
 
-       return ret;
+       return PTR_ERR_OR_ZERO(devdata->backup);
 }
 
 static int wm831x_backup_remove(struct platform_device *pdev)
 {
        struct wm831x_backup *devdata = platform_get_drvdata(pdev);
 
-       power_supply_unregister(&devdata->backup);
+       power_supply_unregister(devdata->backup);
 
        return 0;
 }
index 3bed2f55cf7d1532cfb1552c6c7c95a15d228098..0161bdabd5a3c31c07c0ebe088596a561b258f70 100644 (file)
 
 struct wm831x_power {
        struct wm831x *wm831x;
-       struct power_supply wall;
-       struct power_supply usb;
-       struct power_supply battery;
+       struct power_supply *wall;
+       struct power_supply *usb;
+       struct power_supply *battery;
+       struct power_supply_desc wall_desc;
+       struct power_supply_desc usb_desc;
+       struct power_supply_desc battery_desc;
        char wall_name[20];
        char usb_name[20];
        char battery_name[20];
@@ -67,7 +70,7 @@ static int wm831x_wall_get_prop(struct power_supply *psy,
                                enum power_supply_property psp,
                                union power_supply_propval *val)
 {
-       struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev->parent);
+       struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev.parent);
        struct wm831x *wm831x = wm831x_power->wm831x;
        int ret = 0;
 
@@ -98,7 +101,7 @@ static int wm831x_usb_get_prop(struct power_supply *psy,
                               enum power_supply_property psp,
                               union power_supply_propval *val)
 {
-       struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev->parent);
+       struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev.parent);
        struct wm831x *wm831x = wm831x_power->wm831x;
        int ret = 0;
 
@@ -393,7 +396,7 @@ static int wm831x_bat_get_prop(struct power_supply *psy,
                               enum power_supply_property psp,
                               union power_supply_propval *val)
 {
-       struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev->parent);
+       struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev.parent);
        struct wm831x *wm831x = wm831x_power->wm831x;
        int ret = 0;
 
@@ -451,7 +454,7 @@ static irqreturn_t wm831x_bat_irq(int irq, void *data)
        /* The battery charger is autonomous so we don't need to do
         * anything except kick user space */
        if (wm831x_power->have_battery)
-               power_supply_changed(&wm831x_power->battery);
+               power_supply_changed(wm831x_power->battery);
 
        return IRQ_HANDLED;
 }
@@ -482,9 +485,9 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
 
        /* Just notify for everything - little harm in overnotifying. */
        if (wm831x_power->have_battery)
-               power_supply_changed(&wm831x_power->battery);
-       power_supply_changed(&wm831x_power->usb);
-       power_supply_changed(&wm831x_power->wall);
+               power_supply_changed(wm831x_power->battery);
+       power_supply_changed(wm831x_power->usb);
+       power_supply_changed(wm831x_power->wall);
 
        return IRQ_HANDLED;
 }
@@ -494,9 +497,6 @@ static int wm831x_power_probe(struct platform_device *pdev)
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
        struct wm831x_power *power;
-       struct power_supply *usb;
-       struct power_supply *battery;
-       struct power_supply *wall;
        int ret, irq, i;
 
        power = kzalloc(sizeof(struct wm831x_power), GFP_KERNEL);
@@ -506,10 +506,6 @@ static int wm831x_power_probe(struct platform_device *pdev)
        power->wm831x = wm831x;
        platform_set_drvdata(pdev, power);
 
-       usb = &power->usb;
-       battery = &power->battery;
-       wall = &power->wall;
-
        if (wm831x_pdata && wm831x_pdata->wm831x_num) {
                snprintf(power->wall_name, sizeof(power->wall_name),
                         "wm831x-wall.%d", wm831x_pdata->wm831x_num);
@@ -531,23 +527,28 @@ static int wm831x_power_probe(struct platform_device *pdev)
         */
        wm831x_config_battery(wm831x);
 
-       wall->name = power->wall_name;
-       wall->type = POWER_SUPPLY_TYPE_MAINS;
-       wall->properties = wm831x_wall_props;
-       wall->num_properties = ARRAY_SIZE(wm831x_wall_props);
-       wall->get_property = wm831x_wall_get_prop;
-       ret = power_supply_register(&pdev->dev, wall);
-       if (ret)
+       power->wall_desc.name = power->wall_name;
+       power->wall_desc.type = POWER_SUPPLY_TYPE_MAINS;
+       power->wall_desc.properties = wm831x_wall_props;
+       power->wall_desc.num_properties = ARRAY_SIZE(wm831x_wall_props);
+       power->wall_desc.get_property = wm831x_wall_get_prop;
+       power->wall = power_supply_register(&pdev->dev, &power->wall_desc,
+                                           NULL);
+       if (IS_ERR(power->wall)) {
+               ret = PTR_ERR(power->wall);
                goto err_kmalloc;
+       }
 
-       usb->name = power->usb_name,
-       usb->type = POWER_SUPPLY_TYPE_USB;
-       usb->properties = wm831x_usb_props;
-       usb->num_properties = ARRAY_SIZE(wm831x_usb_props);
-       usb->get_property = wm831x_usb_get_prop;
-       ret = power_supply_register(&pdev->dev, usb);
-       if (ret)
+       power->usb_desc.name = power->usb_name,
+       power->usb_desc.type = POWER_SUPPLY_TYPE_USB;
+       power->usb_desc.properties = wm831x_usb_props;
+       power->usb_desc.num_properties = ARRAY_SIZE(wm831x_usb_props);
+       power->usb_desc.get_property = wm831x_usb_get_prop;
+       power->usb = power_supply_register(&pdev->dev, &power->usb_desc, NULL);
+       if (IS_ERR(power->usb)) {
+               ret = PTR_ERR(power->usb);
                goto err_wall;
+       }
 
        ret = wm831x_reg_read(wm831x, WM831X_CHARGER_CONTROL_1);
        if (ret < 0)
@@ -555,14 +556,18 @@ static int wm831x_power_probe(struct platform_device *pdev)
        power->have_battery = ret & WM831X_CHG_ENA;
 
        if (power->have_battery) {
-                   battery->name = power->battery_name;
-                   battery->properties = wm831x_bat_props;
-                   battery->num_properties = ARRAY_SIZE(wm831x_bat_props);
-                   battery->get_property = wm831x_bat_get_prop;
-                   battery->use_for_apm = 1;
-                   ret = power_supply_register(&pdev->dev, battery);
-                   if (ret)
-                           goto err_usb;
+               power->battery_desc.name = power->battery_name;
+               power->battery_desc.properties = wm831x_bat_props;
+               power->battery_desc.num_properties = ARRAY_SIZE(wm831x_bat_props);
+               power->battery_desc.get_property = wm831x_bat_get_prop;
+               power->battery_desc.use_for_apm = 1;
+               power->battery = power_supply_register(&pdev->dev,
+                                                      &power->battery_desc,
+                                                      NULL);
+               if (IS_ERR(power->battery)) {
+                       ret = PTR_ERR(power->battery);
+                       goto err_usb;
+               }
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
@@ -615,11 +620,11 @@ err_syslo:
        free_irq(irq, power);
 err_battery:
        if (power->have_battery)
-               power_supply_unregister(battery);
+               power_supply_unregister(power->battery);
 err_usb:
-       power_supply_unregister(usb);
+       power_supply_unregister(power->usb);
 err_wall:
-       power_supply_unregister(wall);
+       power_supply_unregister(power->wall);
 err_kmalloc:
        kfree(power);
        return ret;
@@ -645,9 +650,9 @@ static int wm831x_power_remove(struct platform_device *pdev)
        free_irq(irq, wm831x_power);
 
        if (wm831x_power->have_battery)
-               power_supply_unregister(&wm831x_power->battery);
-       power_supply_unregister(&wm831x_power->wall);
-       power_supply_unregister(&wm831x_power->usb);
+               power_supply_unregister(wm831x_power->battery);
+       power_supply_unregister(wm831x_power->wall);
+       power_supply_unregister(wm831x_power->usb);
        kfree(wm831x_power);
        return 0;
 }
index b3607e2906d2725f68cc57335431df2db42e006f..5c5880664e09b9c0072fdc9d6ccb91ee0525965e 100644 (file)
@@ -196,14 +196,14 @@ static irqreturn_t wm8350_charger_handler(int irq, void *data)
                break;
        case WM8350_IRQ_CHG_TO:
                dev_err(wm8350->dev, "charger timeout\n");
-               power_supply_changed(&power->battery);
+               power_supply_changed(power->battery);
                break;
 
        case WM8350_IRQ_CHG_BAT_HOT:
        case WM8350_IRQ_CHG_BAT_COLD:
        case WM8350_IRQ_CHG_START:
        case WM8350_IRQ_CHG_END:
-               power_supply_changed(&power->battery);
+               power_supply_changed(power->battery);
                break;
 
        case WM8350_IRQ_CHG_FAST_RDY:
@@ -231,9 +231,9 @@ static irqreturn_t wm8350_charger_handler(int irq, void *data)
        case WM8350_IRQ_EXT_WALL_FB:
                wm8350_charger_config(wm8350, policy);
        case WM8350_IRQ_EXT_BAT_FB:   /* Fall through */
-               power_supply_changed(&power->battery);
-               power_supply_changed(&power->usb);
-               power_supply_changed(&power->ac);
+               power_supply_changed(power->battery);
+               power_supply_changed(power->usb);
+               power_supply_changed(power->ac);
                break;
 
        default:
@@ -250,7 +250,7 @@ static int wm8350_ac_get_prop(struct power_supply *psy,
                              enum power_supply_property psp,
                              union power_supply_propval *val)
 {
-       struct wm8350 *wm8350 = dev_get_drvdata(psy->dev->parent);
+       struct wm8350 *wm8350 = dev_get_drvdata(psy->dev.parent);
        int ret = 0;
 
        switch (psp) {
@@ -280,7 +280,7 @@ static int wm8350_usb_get_prop(struct power_supply *psy,
                               enum power_supply_property psp,
                               union power_supply_propval *val)
 {
-       struct wm8350 *wm8350 = dev_get_drvdata(psy->dev->parent);
+       struct wm8350 *wm8350 = dev_get_drvdata(psy->dev.parent);
        int ret = 0;
 
        switch (psp) {
@@ -346,7 +346,7 @@ static int wm8350_bat_get_property(struct power_supply *psy,
                                   enum power_supply_property psp,
                                   union power_supply_propval *val)
 {
-       struct wm8350 *wm8350 = dev_get_drvdata(psy->dev->parent);
+       struct wm8350 *wm8350 = dev_get_drvdata(psy->dev.parent);
        int ret = 0;
 
        switch (psp) {
@@ -382,6 +382,30 @@ static enum power_supply_property wm8350_bat_props[] = {
        POWER_SUPPLY_PROP_CHARGE_TYPE,
 };
 
+static const struct power_supply_desc wm8350_ac_desc = {
+       .name           = "wm8350-ac",
+       .type           = POWER_SUPPLY_TYPE_MAINS,
+       .properties     = wm8350_ac_props,
+       .num_properties = ARRAY_SIZE(wm8350_ac_props),
+       .get_property   = wm8350_ac_get_prop,
+};
+
+static const struct power_supply_desc wm8350_battery_desc = {
+       .name           = "wm8350-battery",
+       .properties     = wm8350_bat_props,
+       .num_properties = ARRAY_SIZE(wm8350_bat_props),
+       .get_property   = wm8350_bat_get_property,
+       .use_for_apm    = 1,
+};
+
+static const struct power_supply_desc wm8350_usb_desc = {
+       .name           = "wm8350-usb",
+       .type           = POWER_SUPPLY_TYPE_USB,
+       .properties     = wm8350_usb_props,
+       .num_properties = ARRAY_SIZE(wm8350_usb_props),
+       .get_property   = wm8350_usb_get_prop,
+};
+
 /*********************************************************************
  *             Initialisation
  *********************************************************************/
@@ -447,37 +471,24 @@ static int wm8350_power_probe(struct platform_device *pdev)
        struct wm8350 *wm8350 = platform_get_drvdata(pdev);
        struct wm8350_power *power = &wm8350->power;
        struct wm8350_charger_policy *policy = power->policy;
-       struct power_supply *usb = &power->usb;
-       struct power_supply *battery = &power->battery;
-       struct power_supply *ac = &power->ac;
        int ret;
 
-       ac->name = "wm8350-ac";
-       ac->type = POWER_SUPPLY_TYPE_MAINS;
-       ac->properties = wm8350_ac_props;
-       ac->num_properties = ARRAY_SIZE(wm8350_ac_props);
-       ac->get_property = wm8350_ac_get_prop;
-       ret = power_supply_register(&pdev->dev, ac);
-       if (ret)
-               return ret;
-
-       battery->name = "wm8350-battery";
-       battery->properties = wm8350_bat_props;
-       battery->num_properties = ARRAY_SIZE(wm8350_bat_props);
-       battery->get_property = wm8350_bat_get_property;
-       battery->use_for_apm = 1;
-       ret = power_supply_register(&pdev->dev, battery);
-       if (ret)
+       power->ac = power_supply_register(&pdev->dev, &wm8350_ac_desc, NULL);
+       if (IS_ERR(power->ac))
+               return PTR_ERR(power->ac);
+
+       power->battery = power_supply_register(&pdev->dev, &wm8350_battery_desc,
+                                              NULL);
+       if (IS_ERR(power->battery)) {
+               ret = PTR_ERR(power->battery);
                goto battery_failed;
+       }
 
-       usb->name = "wm8350-usb",
-       usb->type = POWER_SUPPLY_TYPE_USB;
-       usb->properties = wm8350_usb_props;
-       usb->num_properties = ARRAY_SIZE(wm8350_usb_props);
-       usb->get_property = wm8350_usb_get_prop;
-       ret = power_supply_register(&pdev->dev, usb);
-       if (ret)
+       power->usb = power_supply_register(&pdev->dev, &wm8350_usb_desc, NULL);
+       if (IS_ERR(power->usb)) {
+               ret = PTR_ERR(power->usb);
                goto usb_failed;
+       }
 
        ret = device_create_file(&pdev->dev, &dev_attr_charger_state);
        if (ret < 0)
@@ -494,9 +505,9 @@ static int wm8350_power_probe(struct platform_device *pdev)
        return ret;
 
 usb_failed:
-       power_supply_unregister(battery);
+       power_supply_unregister(power->battery);
 battery_failed:
-       power_supply_unregister(ac);
+       power_supply_unregister(power->ac);
 
        return ret;
 }
@@ -508,9 +519,9 @@ static int wm8350_power_remove(struct platform_device *pdev)
 
        free_charger_irq(wm8350);
        device_remove_file(&pdev->dev, &dev_attr_charger_state);
-       power_supply_unregister(&power->battery);
-       power_supply_unregister(&power->ac);
-       power_supply_unregister(&power->usb);
+       power_supply_unregister(power->battery);
+       power_supply_unregister(power->ac);
+       power_supply_unregister(power->usb);
        return 0;
 }
 
index a8e6203673ade1bd24e124db09002242480b0369..c2f09ed35050a15d20148c4439614b8098ee90a7 100644 (file)
@@ -32,20 +32,20 @@ static enum power_supply_property *prop;
 
 static unsigned long wm97xx_read_bat(struct power_supply *bat_ps)
 {
-       struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data;
+       struct wm97xx_pdata *wmdata = bat_ps->dev.parent->platform_data;
        struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata;
 
-       return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev->parent),
+       return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev.parent),
                                        pdata->batt_aux) * pdata->batt_mult /
                                        pdata->batt_div;
 }
 
 static unsigned long wm97xx_read_temp(struct power_supply *bat_ps)
 {
-       struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data;
+       struct wm97xx_pdata *wmdata = bat_ps->dev.parent->platform_data;
        struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata;
 
-       return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev->parent),
+       return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev.parent),
                                        pdata->temp_aux) * pdata->temp_mult /
                                        pdata->temp_div;
 }
@@ -54,7 +54,7 @@ static int wm97xx_bat_get_property(struct power_supply *bat_ps,
                            enum power_supply_property psp,
                            union power_supply_propval *val)
 {
-       struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data;
+       struct wm97xx_pdata *wmdata = bat_ps->dev.parent->platform_data;
        struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata;
 
        switch (psp) {
@@ -105,7 +105,7 @@ static void wm97xx_bat_external_power_changed(struct power_supply *bat_ps)
 static void wm97xx_bat_update(struct power_supply *bat_ps)
 {
        int old_status = bat_status;
-       struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data;
+       struct wm97xx_pdata *wmdata = bat_ps->dev.parent->platform_data;
        struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata;
 
        mutex_lock(&work_lock);
@@ -117,7 +117,7 @@ static void wm97xx_bat_update(struct power_supply *bat_ps)
                        POWER_SUPPLY_STATUS_UNKNOWN;
 
        if (old_status != bat_status) {
-               pr_debug("%s: %i -> %i\n", bat_ps->name, old_status,
+               pr_debug("%s: %i -> %i\n", bat_ps->desc->name, old_status,
                                        bat_status);
                power_supply_changed(bat_ps);
        }
@@ -125,7 +125,8 @@ static void wm97xx_bat_update(struct power_supply *bat_ps)
        mutex_unlock(&work_lock);
 }
 
-static struct power_supply bat_ps = {
+static struct power_supply *bat_psy;
+static struct power_supply_desc bat_psy_desc = {
        .type                   = POWER_SUPPLY_TYPE_BATTERY,
        .get_property           = wm97xx_bat_get_property,
        .external_power_changed = wm97xx_bat_external_power_changed,
@@ -134,7 +135,7 @@ static struct power_supply bat_ps = {
 
 static void wm97xx_bat_work(struct work_struct *work)
 {
-       wm97xx_bat_update(&bat_ps);
+       wm97xx_bat_update(bat_psy);
 }
 
 static irqreturn_t wm97xx_chrg_irq(int irq, void *data)
@@ -237,18 +238,20 @@ static int wm97xx_bat_probe(struct platform_device *dev)
                dev_info(&dev->dev, "Please consider setting proper battery "
                                "name in platform definition file, falling "
                                "back to name \"wm97xx-batt\"\n");
-               bat_ps.name = "wm97xx-batt";
+               bat_psy_desc.name = "wm97xx-batt";
        } else
-               bat_ps.name = pdata->batt_name;
+               bat_psy_desc.name = pdata->batt_name;
 
-       bat_ps.properties = prop;
-       bat_ps.num_properties = props;
+       bat_psy_desc.properties = prop;
+       bat_psy_desc.num_properties = props;
 
-       ret = power_supply_register(&dev->dev, &bat_ps);
-       if (!ret)
+       bat_psy = power_supply_register(&dev->dev, &bat_psy_desc, NULL);
+       if (!IS_ERR(bat_psy)) {
                schedule_work(&bat_work);
-       else
+       } else {
+               ret = PTR_ERR(bat_psy);
                goto err4;
+       }
 
        return 0;
 err4:
@@ -273,7 +276,7 @@ static int wm97xx_bat_remove(struct platform_device *dev)
                gpio_free(pdata->charge_gpio);
        }
        cancel_work_sync(&bat_work);
-       power_supply_unregister(&bat_ps);
+       power_supply_unregister(bat_psy);
        kfree(prop);
        return 0;
 }
index 814d2e31f0c97efeb5b589476679c3a9e8cf3628..b201e3facf7343abe17439d93ea4eacd234a1e30 100644 (file)
 #define        Z2_DEFAULT_NAME "Z2"
 
 struct z2_charger {
-       struct z2_battery_info  *info;
-       int                     bat_status;
-       struct i2c_client       *client;
-       struct power_supply     batt_ps;
-       struct mutex            work_lock;
-       struct work_struct      bat_work;
+       struct z2_battery_info          *info;
+       int                             bat_status;
+       struct i2c_client               *client;
+       struct power_supply             *batt_ps;
+       struct power_supply_desc        batt_ps_desc;
+       struct mutex                    work_lock;
+       struct work_struct              bat_work;
 };
 
 static unsigned long z2_read_bat(struct z2_charger *charger)
@@ -44,8 +45,7 @@ static int z2_batt_get_property(struct power_supply *batt_ps,
                            enum power_supply_property psp,
                            union power_supply_propval *val)
 {
-       struct z2_charger *charger = container_of(batt_ps, struct z2_charger,
-                                               batt_ps);
+       struct z2_charger *charger = power_supply_get_drvdata(batt_ps);
        struct z2_battery_info *info = charger->info;
 
        switch (psp) {
@@ -85,8 +85,8 @@ static int z2_batt_get_property(struct power_supply *batt_ps,
 
 static void z2_batt_ext_power_changed(struct power_supply *batt_ps)
 {
-       struct z2_charger *charger = container_of(batt_ps, struct z2_charger,
-                                               batt_ps);
+       struct z2_charger *charger = power_supply_get_drvdata(batt_ps);
+
        schedule_work(&charger->bat_work);
 }
 
@@ -106,9 +106,10 @@ static void z2_batt_update(struct z2_charger *charger)
                POWER_SUPPLY_STATUS_UNKNOWN;
 
        if (old_status != charger->bat_status) {
-               pr_debug("%s: %i -> %i\n", charger->batt_ps.name, old_status,
-                       charger->bat_status);
-               power_supply_changed(&charger->batt_ps);
+               pr_debug("%s: %i -> %i\n", charger->batt_ps->desc->name,
+                               old_status,
+                               charger->bat_status);
+               power_supply_changed(charger->batt_ps);
        }
 
        mutex_unlock(&charger->work_lock);
@@ -166,16 +167,17 @@ static int z2_batt_ps_init(struct z2_charger *charger, int props)
                                "Please consider setting proper battery "
                                "name in platform definition file, falling "
                                "back to name \" Z2_DEFAULT_NAME \"\n");
-               charger->batt_ps.name = Z2_DEFAULT_NAME;
+               charger->batt_ps_desc.name = Z2_DEFAULT_NAME;
        } else
-               charger->batt_ps.name = info->batt_name;
+               charger->batt_ps_desc.name = info->batt_name;
 
-       charger->batt_ps.properties             = prop;
-       charger->batt_ps.num_properties         = props;
-       charger->batt_ps.type                   = POWER_SUPPLY_TYPE_BATTERY;
-       charger->batt_ps.get_property           = z2_batt_get_property;
-       charger->batt_ps.external_power_changed = z2_batt_ext_power_changed;
-       charger->batt_ps.use_for_apm            = 1;
+       charger->batt_ps_desc.properties        = prop;
+       charger->batt_ps_desc.num_properties    = props;
+       charger->batt_ps_desc.type              = POWER_SUPPLY_TYPE_BATTERY;
+       charger->batt_ps_desc.get_property      = z2_batt_get_property;
+       charger->batt_ps_desc.external_power_changed =
+                                               z2_batt_ext_power_changed;
+       charger->batt_ps_desc.use_for_apm       = 1;
 
        return 0;
 }
@@ -187,6 +189,7 @@ static int z2_batt_probe(struct i2c_client *client,
        int props = 1;  /* POWER_SUPPLY_PROP_PRESENT */
        struct z2_charger *charger;
        struct z2_battery_info *info = client->dev.platform_data;
+       struct power_supply_config psy_cfg = {};
 
        if (info == NULL) {
                dev_err(&client->dev,
@@ -203,6 +206,7 @@ static int z2_batt_probe(struct i2c_client *client,
        charger->info = info;
        charger->client = client;
        i2c_set_clientdata(client, charger);
+       psy_cfg.drv_data = charger;
 
        mutex_init(&charger->work_lock);
 
@@ -230,16 +234,20 @@ static int z2_batt_probe(struct i2c_client *client,
 
        INIT_WORK(&charger->bat_work, z2_batt_work);
 
-       ret = power_supply_register(&client->dev, &charger->batt_ps);
-       if (ret)
+       charger->batt_ps = power_supply_register(&client->dev,
+                                                &charger->batt_ps_desc,
+                                                &psy_cfg);
+       if (IS_ERR(charger->batt_ps)) {
+               ret = PTR_ERR(charger->batt_ps);
                goto err4;
+       }
 
        schedule_work(&charger->bat_work);
 
        return 0;
 
 err4:
-       kfree(charger->batt_ps.properties);
+       kfree(charger->batt_ps_desc.properties);
 err3:
        if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio))
                free_irq(gpio_to_irq(info->charge_gpio), charger);
@@ -257,9 +265,9 @@ static int z2_batt_remove(struct i2c_client *client)
        struct z2_battery_info *info = charger->info;
 
        cancel_work_sync(&charger->bat_work);
-       power_supply_unregister(&charger->batt_ps);
+       power_supply_unregister(charger->batt_ps);
 
-       kfree(charger->batt_ps.properties);
+       kfree(charger->batt_ps_desc.properties);
        if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio)) {
                free_irq(gpio_to_irq(info->charge_gpio), charger);
                gpio_free(info->charge_gpio);
index 9eec453b745d87facf2bb339194f0b6f32d80feb..2ff73d72ca34aca4d332fa1c7967d35f24471de0 100644 (file)
 #include <linux/regulator/of_regulator.h>
 #include <linux/regmap.h>
 
+/*
+ * ACT8600 Global Register Map.
+ */
+#define ACT8600_SYS_MODE       0x00
+#define ACT8600_SYS_CTRL       0x01
+#define ACT8600_DCDC1_VSET     0x10
+#define ACT8600_DCDC1_CTRL     0x12
+#define ACT8600_DCDC2_VSET     0x20
+#define ACT8600_DCDC2_CTRL     0x22
+#define ACT8600_DCDC3_VSET     0x30
+#define ACT8600_DCDC3_CTRL     0x32
+#define ACT8600_SUDCDC4_VSET   0x40
+#define ACT8600_SUDCDC4_CTRL   0x41
+#define ACT8600_LDO5_VSET      0x50
+#define ACT8600_LDO5_CTRL      0x51
+#define ACT8600_LDO6_VSET      0x60
+#define ACT8600_LDO6_CTRL      0x61
+#define ACT8600_LDO7_VSET      0x70
+#define ACT8600_LDO7_CTRL      0x71
+#define ACT8600_LDO8_VSET      0x80
+#define ACT8600_LDO8_CTRL      0x81
+#define ACT8600_LDO910_CTRL    0x91
+#define ACT8600_APCH0          0xA1
+#define ACT8600_APCH1          0xA8
+#define ACT8600_APCH2          0xA9
+#define ACT8600_APCH_STAT      0xAA
+#define ACT8600_OTG0           0xB0
+#define ACT8600_OTG1           0xB2
+
 /*
  * ACT8846 Global Register Map.
  */
 #define        ACT8865_ENA             0x80    /* ON - [7] */
 #define        ACT8865_VSEL_MASK       0x3F    /* VSET - [5:0] */
 
+
+#define ACT8600_LDO10_ENA              0x40    /* ON - [6] */
+#define ACT8600_SUDCDC_VSEL_MASK       0xFF    /* SUDCDC VSET - [7:0] */
+
 /*
  * ACT8865 voltage number
  */
 #define        ACT8865_VOLTAGE_NUM     64
+#define ACT8600_SUDCDC_VOLTAGE_NUM     255
 
 struct act8865 {
        struct regmap *regmap;
@@ -116,6 +150,13 @@ static const struct regulator_linear_range act8865_voltage_ranges[] = {
        REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
 };
 
+static const struct regulator_linear_range act8600_sudcdc_voltage_ranges[] = {
+       REGULATOR_LINEAR_RANGE(3000000, 0, 63, 0),
+       REGULATOR_LINEAR_RANGE(3000000, 64, 159, 100000),
+       REGULATOR_LINEAR_RANGE(12600000, 160, 191, 200000),
+       REGULATOR_LINEAR_RANGE(19000000, 191, 255, 400000),
+};
+
 static struct regulator_ops act8865_ops = {
        .list_voltage           = regulator_list_voltage_linear_range,
        .map_voltage            = regulator_map_voltage_linear_range,
@@ -126,9 +167,16 @@ static struct regulator_ops act8865_ops = {
        .is_enabled             = regulator_is_enabled_regmap,
 };
 
-#define ACT88xx_REG(_name, _family, _id, _vsel_reg)                    \
+static struct regulator_ops act8865_ldo_ops = {
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .is_enabled             = regulator_is_enabled_regmap,
+};
+
+#define ACT88xx_REG(_name, _family, _id, _vsel_reg, _supply)           \
        [_family##_ID_##_id] = {                                        \
                .name                   = _name,                        \
+               .supply_name            = _supply,                      \
                .id                     = _family##_ID_##_id,           \
                .type                   = REGULATOR_VOLTAGE,            \
                .ops                    = &act8865_ops,                 \
@@ -142,33 +190,80 @@ static struct regulator_ops act8865_ops = {
                .owner                  = THIS_MODULE,                  \
        }
 
+static const struct regulator_desc act8600_regulators[] = {
+       ACT88xx_REG("DCDC1", ACT8600, DCDC1, VSET, "vp1"),
+       ACT88xx_REG("DCDC2", ACT8600, DCDC2, VSET, "vp2"),
+       ACT88xx_REG("DCDC3", ACT8600, DCDC3, VSET, "vp3"),
+       {
+               .name = "SUDCDC_REG4",
+               .id = ACT8600_ID_SUDCDC4,
+               .ops = &act8865_ops,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = ACT8600_SUDCDC_VOLTAGE_NUM,
+               .linear_ranges = act8600_sudcdc_voltage_ranges,
+               .n_linear_ranges = ARRAY_SIZE(act8600_sudcdc_voltage_ranges),
+               .vsel_reg = ACT8600_SUDCDC4_VSET,
+               .vsel_mask = ACT8600_SUDCDC_VSEL_MASK,
+               .enable_reg = ACT8600_SUDCDC4_CTRL,
+               .enable_mask = ACT8865_ENA,
+               .owner = THIS_MODULE,
+       },
+       ACT88xx_REG("LDO5", ACT8600, LDO5, VSET, "inl"),
+       ACT88xx_REG("LDO6", ACT8600, LDO6, VSET, "inl"),
+       ACT88xx_REG("LDO7", ACT8600, LDO7, VSET, "inl"),
+       ACT88xx_REG("LDO8", ACT8600, LDO8, VSET, "inl"),
+       {
+               .name = "LDO_REG9",
+               .id = ACT8600_ID_LDO9,
+               .ops = &act8865_ldo_ops,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = 1,
+               .fixed_uV = 1800000,
+               .enable_reg = ACT8600_LDO910_CTRL,
+               .enable_mask = ACT8865_ENA,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "LDO_REG10",
+               .id = ACT8600_ID_LDO10,
+               .ops = &act8865_ldo_ops,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = 1,
+               .fixed_uV = 1200000,
+               .enable_reg = ACT8600_LDO910_CTRL,
+               .enable_mask = ACT8600_LDO10_ENA,
+               .owner = THIS_MODULE,
+       },
+};
+
 static const struct regulator_desc act8846_regulators[] = {
-       ACT88xx_REG("REG1", ACT8846, REG1, VSET),
-       ACT88xx_REG("REG2", ACT8846, REG2, VSET0),
-       ACT88xx_REG("REG3", ACT8846, REG3, VSET0),
-       ACT88xx_REG("REG4", ACT8846, REG4, VSET0),
-       ACT88xx_REG("REG5", ACT8846, REG5, VSET),
-       ACT88xx_REG("REG6", ACT8846, REG6, VSET),
-       ACT88xx_REG("REG7", ACT8846, REG7, VSET),
-       ACT88xx_REG("REG8", ACT8846, REG8, VSET),
-       ACT88xx_REG("REG9", ACT8846, REG9, VSET),
-       ACT88xx_REG("REG10", ACT8846, REG10, VSET),
-       ACT88xx_REG("REG11", ACT8846, REG11, VSET),
-       ACT88xx_REG("REG12", ACT8846, REG12, VSET),
+       ACT88xx_REG("REG1", ACT8846, REG1, VSET, "vp1"),
+       ACT88xx_REG("REG2", ACT8846, REG2, VSET0, "vp2"),
+       ACT88xx_REG("REG3", ACT8846, REG3, VSET0, "vp3"),
+       ACT88xx_REG("REG4", ACT8846, REG4, VSET0, "vp4"),
+       ACT88xx_REG("REG5", ACT8846, REG5, VSET, "inl1"),
+       ACT88xx_REG("REG6", ACT8846, REG6, VSET, "inl1"),
+       ACT88xx_REG("REG7", ACT8846, REG7, VSET, "inl1"),
+       ACT88xx_REG("REG8", ACT8846, REG8, VSET, "inl2"),
+       ACT88xx_REG("REG9", ACT8846, REG9, VSET, "inl2"),
+       ACT88xx_REG("REG10", ACT8846, REG10, VSET, "inl3"),
+       ACT88xx_REG("REG11", ACT8846, REG11, VSET, "inl3"),
+       ACT88xx_REG("REG12", ACT8846, REG12, VSET, "inl3"),
 };
 
 static const struct regulator_desc act8865_regulators[] = {
-       ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET1),
-       ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET1),
-       ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET1),
-       ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET),
-       ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET),
-       ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET),
-       ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET),
+       ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET1, "vp1"),
+       ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET1, "vp2"),
+       ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET1, "vp3"),
+       ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET, "inl45"),
+       ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET, "inl45"),
+       ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET, "inl67"),
+       ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET, "inl67"),
 };
 
 #ifdef CONFIG_OF
 static const struct of_device_id act8865_dt_ids[] = {
+       { .compatible = "active-semi,act8600", .data = (void *)ACT8600 },
        { .compatible = "active-semi,act8846", .data = (void *)ACT8846 },
        { .compatible = "active-semi,act8865", .data = (void *)ACT8865 },
        { }
@@ -200,6 +295,19 @@ static struct of_regulator_match act8865_matches[] = {
        [ACT8865_ID_LDO4]       = { .name = "LDO_REG4"},
 };
 
+static struct of_regulator_match act8600_matches[] = {
+       [ACT8600_ID_DCDC1]      = { .name = "DCDC_REG1"},
+       [ACT8600_ID_DCDC2]      = { .name = "DCDC_REG2"},
+       [ACT8600_ID_DCDC3]      = { .name = "DCDC_REG3"},
+       [ACT8600_ID_SUDCDC4]    = { .name = "SUDCDC_REG4"},
+       [ACT8600_ID_LDO5]       = { .name = "LDO_REG5"},
+       [ACT8600_ID_LDO6]       = { .name = "LDO_REG6"},
+       [ACT8600_ID_LDO7]       = { .name = "LDO_REG7"},
+       [ACT8600_ID_LDO8]       = { .name = "LDO_REG8"},
+       [ACT8600_ID_LDO9]       = { .name = "LDO_REG9"},
+       [ACT8600_ID_LDO10]      = { .name = "LDO_REG10"},
+};
+
 static int act8865_pdata_from_dt(struct device *dev,
                                 struct device_node **of_node,
                                 struct act8865_platform_data *pdata,
@@ -217,6 +325,10 @@ static int act8865_pdata_from_dt(struct device *dev,
        }
 
        switch (type) {
+       case ACT8600:
+               matches = act8600_matches;
+               num_matches = ARRAY_SIZE(act8600_matches);
+               break;
        case ACT8846:
                matches = act8846_matches;
                num_matches = ARRAY_SIZE(act8846_matches);
@@ -317,6 +429,12 @@ static int act8865_pmic_probe(struct i2c_client *client,
        }
 
        switch (type) {
+       case ACT8600:
+               regulators = act8600_regulators;
+               num_regulators = ARRAY_SIZE(act8600_regulators);
+               off_reg = -1;
+               off_mask = -1;
+               break;
        case ACT8846:
                regulators = act8846_regulators;
                num_regulators = ARRAY_SIZE(act8846_regulators);
@@ -366,7 +484,7 @@ static int act8865_pmic_probe(struct i2c_client *client,
        }
 
        if (of_device_is_system_power_controller(dev->of_node)) {
-               if (!pm_power_off) {
+               if (!pm_power_off && (off_reg > 0)) {
                        act8865_i2c_client = client;
                        act8865->off_reg = off_reg;
                        act8865->off_mask = off_mask;
@@ -402,6 +520,7 @@ static int act8865_pmic_probe(struct i2c_client *client,
 }
 
 static const struct i2c_device_id act8865_ids[] = {
+       { .name = "act8600", .driver_data = ACT8600 },
        { .name = "act8846", .driver_data = ACT8846 },
        { .name = "act8865", .driver_data = ACT8865 },
        { },
index 8169165904c0c67f0c04089121dee074bc8f49fa..a1d07d347c20e30af065d204d94a314d18c408e3 100644 (file)
@@ -282,6 +282,9 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
                arizona->external_dcvdd = true;
 
        ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config);
+
+       of_node_put(config.of_node);
+
        if (IS_ERR(ldo1->regulator)) {
                ret = PTR_ERR(ldo1->regulator);
                dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
@@ -289,8 +292,6 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
                return ret;
        }
 
-       of_node_put(config.of_node);
-
        platform_set_drvdata(pdev, ldo1);
 
        return 0;
index 20079006459af5a89e324e9e595e67d1df5a40d7..fcb98dbda8379c76f79372a0266056275ef8815a 100644 (file)
@@ -246,6 +246,7 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
         */
        switch (arizona->type) {
        case WM5110:
+       case WM8280:
                desc = &arizona_micsupp_ext;
                micsupp->init_data = arizona_micsupp_ext_default;
                break;
@@ -284,6 +285,9 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
        micsupp->regulator = devm_regulator_register(&pdev->dev,
                                                     desc,
                                                     &config);
+
+       of_node_put(config.of_node);
+
        if (IS_ERR(micsupp->regulator)) {
                ret = PTR_ERR(micsupp->regulator);
                dev_err(arizona->dev, "Failed to register mic supply: %d\n",
@@ -291,8 +295,6 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
                return ret;
        }
 
-       of_node_put(config.of_node);
-
        platform_set_drvdata(pdev, micsupp);
 
        return 0;
index a4a8a6dc60c470bf6911632a8b14f790cc415ef4..443eaab933fcfe680d5e402f72bbe7c55c3ae391 100644 (file)
@@ -648,10 +648,12 @@ static int drms_uA_update(struct regulator_dev *rdev)
        if (err < 0)
                return 0;
 
-       if (!rdev->desc->ops->get_optimum_mode)
+       if (!rdev->desc->ops->get_optimum_mode &&
+           !rdev->desc->ops->set_load)
                return 0;
 
-       if (!rdev->desc->ops->set_mode)
+       if (!rdev->desc->ops->set_mode &&
+           !rdev->desc->ops->set_load)
                return -EINVAL;
 
        /* get output voltage */
@@ -676,22 +678,29 @@ static int drms_uA_update(struct regulator_dev *rdev)
        list_for_each_entry(sibling, &rdev->consumer_list, list)
                current_uA += sibling->uA_load;
 
-       /* now get the optimum mode for our new total regulator load */
-       mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
-                                                 output_uV, current_uA);
+       if (rdev->desc->ops->set_load) {
+               /* set the optimum mode for our new total regulator load */
+               err = rdev->desc->ops->set_load(rdev, current_uA);
+               if (err < 0)
+                       rdev_err(rdev, "failed to set load %d\n", current_uA);
+       } else {
+               /* now get the optimum mode for our new total regulator load */
+               mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
+                                                        output_uV, current_uA);
+
+               /* check the new mode is allowed */
+               err = regulator_mode_constrain(rdev, &mode);
+               if (err < 0) {
+                       rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
+                                current_uA, input_uV, output_uV);
+                       return err;
+               }
 
-       /* check the new mode is allowed */
-       err = regulator_mode_constrain(rdev, &mode);
-       if (err < 0) {
-               rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
-                        current_uA, input_uV, output_uV);
-               return err;
+               err = rdev->desc->ops->set_mode(rdev, mode);
+               if (err < 0)
+                       rdev_err(rdev, "failed to set optimum mode %x\n", mode);
        }
 
-       err = rdev->desc->ops->set_mode(rdev, mode);
-       if (err < 0)
-               rdev_err(rdev, "failed to set optimum mode %x\n", mode);
-
        return err;
 }
 
@@ -1316,6 +1325,54 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
        return NULL;
 }
 
+static int regulator_resolve_supply(struct regulator_dev *rdev)
+{
+       struct regulator_dev *r;
+       struct device *dev = rdev->dev.parent;
+       int ret;
+
+       /* No supply to resovle? */
+       if (!rdev->supply_name)
+               return 0;
+
+       /* Supply already resolved? */
+       if (rdev->supply)
+               return 0;
+
+       r = regulator_dev_lookup(dev, rdev->supply_name, &ret);
+       if (ret == -ENODEV) {
+               /*
+                * No supply was specified for this regulator and
+                * there will never be one.
+                */
+               return 0;
+       }
+
+       if (!r) {
+               dev_err(dev, "Failed to resolve %s-supply for %s\n",
+                       rdev->supply_name, rdev->desc->name);
+               return -EPROBE_DEFER;
+       }
+
+       /* Recursively resolve the supply of the supply */
+       ret = regulator_resolve_supply(r);
+       if (ret < 0)
+               return ret;
+
+       ret = set_supply(rdev, r);
+       if (ret < 0)
+               return ret;
+
+       /* Cascade always-on state to supply */
+       if (_regulator_is_enabled(rdev)) {
+               ret = regulator_enable(rdev->supply);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
 /* Internal regulator request function */
 static struct regulator *_regulator_get(struct device *dev, const char *id,
                                        bool exclusive, bool allow_dummy)
@@ -1385,6 +1442,12 @@ found:
                goto out;
        }
 
+       ret = regulator_resolve_supply(rdev);
+       if (ret < 0) {
+               regulator = ERR_PTR(ret);
+               goto out;
+       }
+
        if (!try_module_get(rdev->owner))
                goto out;
 
@@ -2998,7 +3061,7 @@ unsigned int regulator_get_mode(struct regulator *regulator)
 EXPORT_SYMBOL_GPL(regulator_get_mode);
 
 /**
- * regulator_set_optimum_mode - set regulator optimum operating mode
+ * regulator_set_load - set regulator load
  * @regulator: regulator source
  * @uA_load: load current
  *
@@ -3021,9 +3084,9 @@ EXPORT_SYMBOL_GPL(regulator_get_mode);
  * DRMS will sum the total requested load on the regulator and change
  * to the most efficient operating mode if platform constraints allow.
  *
- * Returns the new regulator mode or error.
+ * On error a negative errno is returned.
  */
-int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
+int regulator_set_load(struct regulator *regulator, int uA_load)
 {
        struct regulator_dev *rdev = regulator->rdev;
        int ret;
@@ -3035,7 +3098,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(regulator_set_optimum_mode);
+EXPORT_SYMBOL_GPL(regulator_set_load);
 
 /**
  * regulator_allow_bypass - allow the regulator to go into bypass mode
@@ -3499,7 +3562,18 @@ static struct class regulator_class = {
 
 static void rdev_init_debugfs(struct regulator_dev *rdev)
 {
-       rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root);
+       struct device *parent = rdev->dev.parent;
+       const char *rname = rdev_get_name(rdev);
+       char name[NAME_MAX];
+
+       /* Avoid duplicate debugfs directory names */
+       if (parent && rname == rdev->desc->name) {
+               snprintf(name, sizeof(name), "%s-%s", dev_name(parent),
+                        rname);
+               rname = name;
+       }
+
+       rdev->debugfs = debugfs_create_dir(rname, debugfs_root);
        if (!rdev->debugfs) {
                rdev_warn(rdev, "Failed to create debugfs directory\n");
                return;
@@ -3533,7 +3607,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
        struct regulator_dev *rdev;
        struct device *dev;
        int ret, i;
-       const char *supply = NULL;
 
        if (regulator_desc == NULL || cfg == NULL)
                return ERR_PTR(-EINVAL);
@@ -3641,41 +3714,10 @@ regulator_register(const struct regulator_desc *regulator_desc,
                goto scrub;
 
        if (init_data && init_data->supply_regulator)
-               supply = init_data->supply_regulator;
+               rdev->supply_name = init_data->supply_regulator;
        else if (regulator_desc->supply_name)
-               supply = regulator_desc->supply_name;
-
-       if (supply) {
-               struct regulator_dev *r;
+               rdev->supply_name = regulator_desc->supply_name;
 
-               r = regulator_dev_lookup(dev, supply, &ret);
-
-               if (ret == -ENODEV) {
-                       /*
-                        * No supply was specified for this regulator and
-                        * there will never be one.
-                        */
-                       ret = 0;
-                       goto add_dev;
-               } else if (!r) {
-                       dev_err(dev, "Failed to find supply %s\n", supply);
-                       ret = -EPROBE_DEFER;
-                       goto scrub;
-               }
-
-               ret = set_supply(rdev, r);
-               if (ret < 0)
-                       goto scrub;
-
-               /* Enable supply if rail is enabled */
-               if (_regulator_is_enabled(rdev)) {
-                       ret = regulator_enable(rdev->supply);
-                       if (ret < 0)
-                               goto scrub;
-               }
-       }
-
-add_dev:
        /* add consumers devices */
        if (init_data) {
                for (i = 0; i < init_data->num_consumer_supplies; i++) {
@@ -3702,8 +3744,6 @@ unset_supplies:
        unset_regulator_supplies(rdev);
 
 scrub:
-       if (rdev->supply)
-               _regulator_put(rdev->supply);
        regulator_ena_gpio_free(rdev);
        kfree(rdev->constraints);
 wash:
@@ -3936,6 +3976,110 @@ static const struct file_operations supply_map_fops = {
 #endif
 };
 
+#ifdef CONFIG_DEBUG_FS
+static void regulator_summary_show_subtree(struct seq_file *s,
+                                          struct regulator_dev *rdev,
+                                          int level)
+{
+       struct list_head *list = s->private;
+       struct regulator_dev *child;
+       struct regulation_constraints *c;
+       struct regulator *consumer;
+
+       if (!rdev)
+               return;
+
+       seq_printf(s, "%*s%-*s %3d %4d %6d ",
+                  level * 3 + 1, "",
+                  30 - level * 3, rdev_get_name(rdev),
+                  rdev->use_count, rdev->open_count, rdev->bypass_count);
+
+       seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000);
+       seq_printf(s, "%5dmA ", _regulator_get_current_limit(rdev) / 1000);
+
+       c = rdev->constraints;
+       if (c) {
+               switch (rdev->desc->type) {
+               case REGULATOR_VOLTAGE:
+                       seq_printf(s, "%5dmV %5dmV ",
+                                  c->min_uV / 1000, c->max_uV / 1000);
+                       break;
+               case REGULATOR_CURRENT:
+                       seq_printf(s, "%5dmA %5dmA ",
+                                  c->min_uA / 1000, c->max_uA / 1000);
+                       break;
+               }
+       }
+
+       seq_puts(s, "\n");
+
+       list_for_each_entry(consumer, &rdev->consumer_list, list) {
+               if (consumer->dev->class == &regulator_class)
+                       continue;
+
+               seq_printf(s, "%*s%-*s ",
+                          (level + 1) * 3 + 1, "",
+                          30 - (level + 1) * 3, dev_name(consumer->dev));
+
+               switch (rdev->desc->type) {
+               case REGULATOR_VOLTAGE:
+                       seq_printf(s, "%37dmV %5dmV",
+                                  consumer->min_uV / 1000,
+                                  consumer->max_uV / 1000);
+                       break;
+               case REGULATOR_CURRENT:
+                       break;
+               }
+
+               seq_puts(s, "\n");
+       }
+
+       list_for_each_entry(child, list, list) {
+               /* handle only non-root regulators supplied by current rdev */
+               if (!child->supply || child->supply->rdev != rdev)
+                       continue;
+
+               regulator_summary_show_subtree(s, child, level + 1);
+       }
+}
+
+static int regulator_summary_show(struct seq_file *s, void *data)
+{
+       struct list_head *list = s->private;
+       struct regulator_dev *rdev;
+
+       seq_puts(s, " regulator                      use open bypass voltage current     min     max\n");
+       seq_puts(s, "-------------------------------------------------------------------------------\n");
+
+       mutex_lock(&regulator_list_mutex);
+
+       list_for_each_entry(rdev, list, list) {
+               if (rdev->supply)
+                       continue;
+
+               regulator_summary_show_subtree(s, rdev, 0);
+       }
+
+       mutex_unlock(&regulator_list_mutex);
+
+       return 0;
+}
+
+static int regulator_summary_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, regulator_summary_show, inode->i_private);
+}
+#endif
+
+static const struct file_operations regulator_summary_fops = {
+#ifdef CONFIG_DEBUG_FS
+       .open           = regulator_summary_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+#endif
+};
+
 static int __init regulator_init(void)
 {
        int ret;
@@ -3949,6 +4093,9 @@ static int __init regulator_init(void)
        debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
                            &supply_map_fops);
 
+       debugfs_create_file("regulator_summary", 0444, debugfs_root,
+                           &regulator_list, &regulator_summary_fops);
+
        regulator_dummy_init();
 
        return ret;
index 01343419555ee3363d7bc0d3c10df731fbd74587..df79e4b1946e7d6e966e5759e323f67fbacfb021 100644 (file)
@@ -305,8 +305,7 @@ static irqreturn_t da9211_irq_handler(int irq, void *data)
 
        if (reg_val & DA9211_E_OV_CURR_A) {
                regulator_notifier_call_chain(chip->rdev[0],
-                       REGULATOR_EVENT_OVER_CURRENT,
-                       rdev_get_drvdata(chip->rdev[0]));
+                       REGULATOR_EVENT_OVER_CURRENT, NULL);
 
                err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
                        DA9211_E_OV_CURR_A);
@@ -318,8 +317,7 @@ static irqreturn_t da9211_irq_handler(int irq, void *data)
 
        if (reg_val & DA9211_E_OV_CURR_B) {
                regulator_notifier_call_chain(chip->rdev[1],
-                       REGULATOR_EVENT_OVER_CURRENT,
-                       rdev_get_drvdata(chip->rdev[1]));
+                       REGULATOR_EVENT_OVER_CURRENT, NULL);
 
                err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
                        DA9211_E_OV_CURR_B);
@@ -344,7 +342,7 @@ static int da9211_regulator_init(struct da9211 *chip)
 
        ret = regmap_read(chip->regmap, DA9211_REG_CONFIG_E, &data);
        if (ret < 0) {
-               dev_err(chip->dev, "Failed to read CONTROL_E reg: %d\n", ret);
+               dev_err(chip->dev, "Failed to read CONFIG_E reg: %d\n", ret);
                return ret;
        }
 
index 2d16b9f16de73f5ce42ffb2370bba98c9bccf20b..3963dfad766c78a5c564927487fe20117898ab97 100644 (file)
@@ -95,14 +95,9 @@ void ux500_regulator_resume_debug(void)
 
 static int ux500_regulator_power_state_cnt_print(struct seq_file *s, void *p)
 {
-       struct device *dev = s->private;
-       int err;
-
        /* print power state count */
-       err = seq_printf(s, "ux500-regulator power state count: %i\n",
-               power_state_active_get());
-       if (err < 0)
-               dev_err(dev, "seq_printf overflow\n");
+       seq_printf(s, "ux500-regulator power state count: %i\n",
+                  power_state_active_get());
 
        return 0;
 }
@@ -124,19 +119,11 @@ static const struct file_operations ux500_regulator_power_state_cnt_fops = {
 
 static int ux500_regulator_status_print(struct seq_file *s, void *p)
 {
-       struct device *dev = s->private;
-       int err;
        int i;
 
        /* print dump header */
-       err = seq_puts(s, "ux500-regulator status:\n");
-       if (err < 0)
-               dev_err(dev, "seq_puts overflow\n");
-
-       err = seq_printf(s, "%31s : %8s : %8s\n", "current",
-               "before", "after");
-       if (err < 0)
-               dev_err(dev, "seq_printf overflow\n");
+       seq_puts(s, "ux500-regulator status:\n");
+       seq_printf(s, "%31s : %8s : %8s\n", "current", "before", "after");
 
        for (i = 0; i < rdebug.num_regulators; i++) {
                struct dbx500_regulator_info *info;
@@ -144,12 +131,11 @@ static int ux500_regulator_status_print(struct seq_file *s, void *p)
                info = &rdebug.regulator_array[i];
 
                /* print status */
-               err = seq_printf(s, "%20s : %8s : %8s : %8s\n", info->desc.name,
-                       info->is_enabled ? "enabled" : "disabled",
-                       rdebug.state_before_suspend[i] ? "enabled" : "disabled",
-                       rdebug.state_after_suspend[i] ? "enabled" : "disabled");
-               if (err < 0)
-                       dev_err(dev, "seq_printf overflow\n");
+               seq_printf(s, "%20s : %8s : %8s : %8s\n",
+                          info->desc.name,
+                          info->is_enabled ? "enabled" : "disabled",
+                          rdebug.state_before_suspend[i] ? "enabled" : "disabled",
+                          rdebug.state_after_suspend[i] ? "enabled" : "disabled");
        }
 
        return 0;
index 8f785bc9e5108519525f0908b3d3e3d097b67816..6ec1d400adae7e444102266385171c5d787110a3 100644 (file)
@@ -413,3 +413,88 @@ void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
                devm_regulator_unregister_supply_alias(dev, id[i]);
 }
 EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);
+
+struct regulator_notifier_match {
+       struct regulator *regulator;
+       struct notifier_block *nb;
+};
+
+static int devm_regulator_match_notifier(struct device *dev, void *res,
+                                        void *data)
+{
+       struct regulator_notifier_match *match = res;
+       struct regulator_notifier_match *target = data;
+
+       return match->regulator == target->regulator && match->nb == target->nb;
+}
+
+static void devm_regulator_destroy_notifier(struct device *dev, void *res)
+{
+       struct regulator_notifier_match *match = res;
+
+       regulator_unregister_notifier(match->regulator, match->nb);
+}
+
+/**
+ * devm_regulator_register_notifier - Resource managed
+ * regulator_register_notifier
+ *
+ * @regulator: regulator source
+ * @nb: notifier block
+ *
+ * The notifier will be registers under the consumer device and be
+ * automatically be unregistered when the source device is unbound.
+ */
+int devm_regulator_register_notifier(struct regulator *regulator,
+                                    struct notifier_block *nb)
+{
+       struct regulator_notifier_match *match;
+       int ret;
+
+       match = devres_alloc(devm_regulator_destroy_notifier,
+                            sizeof(struct regulator_notifier_match),
+                            GFP_KERNEL);
+       if (!match)
+               return -ENOMEM;
+
+       match->regulator = regulator;
+       match->nb = nb;
+
+       ret = regulator_register_notifier(regulator, nb);
+       if (ret < 0) {
+               devres_free(match);
+               return ret;
+       }
+
+       devres_add(regulator->dev, match);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_register_notifier);
+
+/**
+ * devm_regulator_unregister_notifier - Resource managed
+ * regulator_unregister_notifier()
+ *
+ * @regulator: regulator source
+ * @nb: notifier block
+ *
+ * Unregister a notifier registered with devm_regulator_register_notifier().
+ * Normally this function will not need to be called and the resource
+ * management code will ensure that the resource is freed.
+ */
+void devm_regulator_unregister_notifier(struct regulator *regulator,
+                                       struct notifier_block *nb)
+{
+       struct regulator_notifier_match match;
+       int rc;
+
+       match.regulator = regulator;
+       match.nb = nb;
+
+       rc = devres_release(regulator->dev, devm_regulator_destroy_notifier,
+                           devm_regulator_match_notifier, &match);
+       if (rc != 0)
+               WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);
index 07b313e51b2184dc706c754d16ddd48fdba08031..9665a488e2f16e7ffde015d9682521b63f822f62 100644 (file)
@@ -128,6 +128,8 @@ static struct regulator_ops max77693_charger_ops = {
 #define regulator_desc_esafeout(_num)  {                       \
        .name           = "ESAFEOUT"#_num,                      \
        .id             = MAX77693_ESAFEOUT##_num,              \
+       .of_match       = of_match_ptr("ESAFEOUT"#_num),        \
+       .regulators_node        = of_match_ptr("regulators"),   \
        .n_voltages     = 4,                                    \
        .ops            = &max77693_safeout_ops,                \
        .type           = REGULATOR_VOLTAGE,                    \
@@ -145,6 +147,8 @@ static const struct regulator_desc regulators[] = {
        {
                .name = "CHARGER",
                .id = MAX77693_CHARGER,
+               .of_match = of_match_ptr("CHARGER"),
+               .regulators_node = of_match_ptr("regulators"),
                .ops = &max77693_charger_ops,
                .type = REGULATOR_CURRENT,
                .owner = THIS_MODULE,
@@ -154,102 +158,23 @@ static const struct regulator_desc regulators[] = {
        },
 };
 
-#ifdef CONFIG_OF
-static int max77693_pmic_dt_parse_rdata(struct device *dev,
-                                       struct max77693_regulator_data **rdata)
-{
-       struct device_node *np;
-       struct of_regulator_match *rmatch;
-       struct max77693_regulator_data *tmp;
-       int i, matched = 0;
-
-       np = of_get_child_by_name(dev->parent->of_node, "regulators");
-       if (!np)
-               return -EINVAL;
-
-       rmatch = devm_kzalloc(dev,
-                sizeof(*rmatch) * ARRAY_SIZE(regulators), GFP_KERNEL);
-       if (!rmatch) {
-               of_node_put(np);
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(regulators); i++)
-               rmatch[i].name = regulators[i].name;
-
-       matched = of_regulator_match(dev, np, rmatch, ARRAY_SIZE(regulators));
-       of_node_put(np);
-       if (matched <= 0)
-               return matched;
-       *rdata = devm_kzalloc(dev, sizeof(**rdata) * matched, GFP_KERNEL);
-       if (!(*rdata))
-               return -ENOMEM;
-
-       tmp = *rdata;
-
-       for (i = 0; i < matched; i++) {
-               tmp->initdata = rmatch[i].init_data;
-               tmp->of_node = rmatch[i].of_node;
-               tmp->id = regulators[i].id;
-               tmp++;
-       }
-
-       return matched;
-}
-#else
-static int max77693_pmic_dt_parse_rdata(struct device *dev,
-                                       struct max77693_regulator_data **rdata)
-{
-       return 0;
-}
-#endif /* CONFIG_OF */
-
-static int max77693_pmic_init_rdata(struct device *dev,
-                                   struct max77693_regulator_data **rdata)
-{
-       struct max77693_platform_data *pdata;
-       int num_regulators = 0;
-
-       pdata = dev_get_platdata(dev->parent);
-       if (pdata) {
-               *rdata = pdata->regulators;
-               num_regulators = pdata->num_regulators;
-       }
-
-       if (!(*rdata) && dev->parent->of_node)
-               num_regulators = max77693_pmic_dt_parse_rdata(dev, rdata);
-
-       return num_regulators;
-}
-
 static int max77693_pmic_probe(struct platform_device *pdev)
 {
        struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-       struct max77693_regulator_data *rdata = NULL;
-       int num_rdata, i;
+       int i;
        struct regulator_config config = { };
 
-       num_rdata = max77693_pmic_init_rdata(&pdev->dev, &rdata);
-       if (!rdata || num_rdata <= 0) {
-               dev_err(&pdev->dev, "No init data supplied.\n");
-               return -ENODEV;
-       }
-
-       config.dev = &pdev->dev;
+       config.dev = iodev->dev;
        config.regmap = iodev->regmap;
 
-       for (i = 0; i < num_rdata; i++) {
-               int id = rdata[i].id;
+       for (i = 0; i < ARRAY_SIZE(regulators); i++) {
                struct regulator_dev *rdev;
 
-               config.init_data = rdata[i].initdata;
-               config.of_node = rdata[i].of_node;
-
                rdev = devm_regulator_register(&pdev->dev,
-                                               &regulators[id], &config);
+                                               &regulators[i], &config);
                if (IS_ERR(rdev)) {
                        dev_err(&pdev->dev,
-                               "Failed to initialize regulator-%d\n", id);
+                               "Failed to initialize regulator-%d\n", i);
                        return PTR_ERR(rdev);
                }
        }
index 7eee2ca1854183b05e4d4b08180020afc7337033..4071d74fa8288ce27d2cdd34505c006474e2f869 100644 (file)
@@ -382,7 +382,7 @@ static int max8660_probe(struct i2c_client *client,
                                   const struct i2c_device_id *i2c_id)
 {
        struct device *dev = &client->dev;
-       struct max8660_platform_data *pdata = dev_get_platdata(dev);
+       struct max8660_platform_data pdata_of, *pdata = dev_get_platdata(dev);
        struct regulator_config config = { };
        struct max8660 *max8660;
        int boot_on, i, id, ret = -EINVAL;
@@ -391,7 +391,6 @@ static int max8660_probe(struct i2c_client *client,
 
        if (dev->of_node && !pdata) {
                const struct of_device_id *id;
-               struct max8660_platform_data pdata_of;
 
                id = of_match_device(of_match_ptr(max8660_dt_ids), dev);
                if (!id)
@@ -443,9 +442,9 @@ static int max8660_probe(struct i2c_client *client,
        for (i = 0; i < pdata->num_subdevs; i++) {
 
                if (!pdata->subdevs[i].platform_data)
-                       return ret;
-
-               boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
+                       boot_on = false;
+               else
+                       boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
 
                switch (pdata->subdevs[i].id) {
                case MAX8660_V3:
index 18198316b6cf15c406c6f9eb243bc39601b97979..8217613807d37f3dfa2f90f796a394094fdebe16 100644 (file)
@@ -916,6 +916,9 @@ static int palmas_ldo_registration(struct palmas_pmic *pmic,
                            (id == PALMAS_REG_LDO6))
                                desc->enable_time = 2000;
                } else {
+                       if (!ddata->has_regen3 && id == PALMAS_REG_REGEN3)
+                               continue;
+
                        desc->n_voltages = 1;
                        if (reg_init && reg_init->roof_floor)
                                desc->ops = &palmas_ops_ext_control_extreg;
@@ -1398,6 +1401,7 @@ static struct palmas_pmic_driver_data palmas_ddata = {
        .ldo_begin = PALMAS_REG_LDO1,
        .ldo_end = PALMAS_REG_LDOUSB,
        .max_reg = PALMAS_NUM_REGS,
+       .has_regen3 = true,
        .palmas_regs_info = palmas_generic_regs_info,
        .palmas_matches = palmas_matches,
        .sleep_req_info = palma_sleep_req_info,
@@ -1411,6 +1415,7 @@ static struct palmas_pmic_driver_data tps65917_ddata = {
        .ldo_begin = TPS65917_REG_LDO1,
        .ldo_end = TPS65917_REG_LDO5,
        .max_reg = TPS65917_NUM_REGS,
+       .has_regen3 = true,
        .palmas_regs_info = tps65917_regs_info,
        .palmas_matches = tps65917_matches,
        .sleep_req_info = tps65917_sleep_req_info,
@@ -1505,7 +1510,7 @@ static void palmas_dt_to_pdata(struct device *dev,
        pdata->ldo6_vibrator = of_property_read_bool(node, "ti,ldo6-vibrator");
 }
 
-static struct of_device_id of_palmas_match_tbl[] = {
+static const struct of_device_id of_palmas_match_tbl[] = {
        {
                .compatible = "ti,palmas-pmic",
                .data = &palmas_ddata,
@@ -1572,9 +1577,11 @@ static int palmas_regulators_probe(struct platform_device *pdev)
        if (!pmic)
                return -ENOMEM;
 
-       if (of_device_is_compatible(node, "ti,tps659038-pmic"))
+       if (of_device_is_compatible(node, "ti,tps659038-pmic")) {
                palmas_generic_regs_info[PALMAS_REG_REGEN2].ctrl_addr =
                                                        TPS659038_REGEN2_CTRL;
+               palmas_ddata.has_regen3 = false;
+       }
 
        pmic->dev = &pdev->dev;
        pmic->palmas = palmas;
index 00c5cc3d954636784a14f5d3c03c7ffcff7896b5..e254272585b24f26b90382121de44ee8e7695565 100644 (file)
@@ -393,6 +393,28 @@ static int rpm_reg_is_enabled(struct regulator_dev *rdev)
        return vreg->is_enabled;
 }
 
+static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA)
+{
+       struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
+       const struct rpm_reg_parts *parts = vreg->parts;
+       const struct request_member *req = &parts->ia;
+       int load_mA = load_uA / 1000;
+       int max_mA = req->mask >> req->shift;
+       int ret;
+
+       if (req->mask == 0)
+               return -EINVAL;
+
+       if (load_mA > max_mA)
+               load_mA = max_mA;
+
+       mutex_lock(&vreg->lock);
+       ret = rpm_reg_write(vreg, req, load_mA);
+       mutex_unlock(&vreg->lock);
+
+       return ret;
+}
+
 static struct regulator_ops uV_ops = {
        .list_voltage = regulator_list_voltage_linear_range,
 
@@ -402,6 +424,8 @@ static struct regulator_ops uV_ops = {
        .enable = rpm_reg_uV_enable,
        .disable = rpm_reg_uV_disable,
        .is_enabled = rpm_reg_is_enabled,
+
+       .set_load = rpm_reg_set_load,
 };
 
 static struct regulator_ops mV_ops = {
@@ -413,6 +437,8 @@ static struct regulator_ops mV_ops = {
        .enable = rpm_reg_mV_enable,
        .disable = rpm_reg_mV_disable,
        .is_enabled = rpm_reg_is_enabled,
+
+       .set_load = rpm_reg_set_load,
 };
 
 static struct regulator_ops switch_ops = {
@@ -581,31 +607,6 @@ static const struct qcom_rpm_reg smb208_smps = {
        .supports_force_mode_bypass = false,
 };
 
-static const struct of_device_id rpm_of_match[] = {
-       { .compatible = "qcom,rpm-pm8058-pldo",     .data = &pm8058_pldo },
-       { .compatible = "qcom,rpm-pm8058-nldo",     .data = &pm8058_nldo },
-       { .compatible = "qcom,rpm-pm8058-smps",     .data = &pm8058_smps },
-       { .compatible = "qcom,rpm-pm8058-ncp",      .data = &pm8058_ncp },
-       { .compatible = "qcom,rpm-pm8058-switch",   .data = &pm8058_switch },
-
-       { .compatible = "qcom,rpm-pm8901-pldo",     .data = &pm8901_pldo },
-       { .compatible = "qcom,rpm-pm8901-nldo",     .data = &pm8901_nldo },
-       { .compatible = "qcom,rpm-pm8901-ftsmps",   .data = &pm8901_ftsmps },
-       { .compatible = "qcom,rpm-pm8901-switch",   .data = &pm8901_switch },
-
-       { .compatible = "qcom,rpm-pm8921-pldo",     .data = &pm8921_pldo },
-       { .compatible = "qcom,rpm-pm8921-nldo",     .data = &pm8921_nldo },
-       { .compatible = "qcom,rpm-pm8921-nldo1200", .data = &pm8921_nldo1200 },
-       { .compatible = "qcom,rpm-pm8921-smps",     .data = &pm8921_smps },
-       { .compatible = "qcom,rpm-pm8921-ftsmps",   .data = &pm8921_ftsmps },
-       { .compatible = "qcom,rpm-pm8921-ncp",      .data = &pm8921_ncp },
-       { .compatible = "qcom,rpm-pm8921-switch",   .data = &pm8921_switch },
-
-       { .compatible = "qcom,rpm-smb208", .data = &smb208_smps },
-       { }
-};
-MODULE_DEVICE_TABLE(of, rpm_of_match);
-
 static int rpm_reg_set(struct qcom_rpm_reg *vreg,
                       const struct request_member *req,
                       const int value)
@@ -619,7 +620,9 @@ static int rpm_reg_set(struct qcom_rpm_reg *vreg,
        return 0;
 }
 
-static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg)
+static int rpm_reg_of_parse_freq(struct device *dev,
+                                struct device_node *node,
+                                struct qcom_rpm_reg *vreg)
 {
        static const int freq_table[] = {
                19200000, 9600000, 6400000, 4800000, 3840000, 3200000, 2740000,
@@ -633,7 +636,7 @@ static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg)
        int i;
 
        key = "qcom,switch-mode-frequency";
-       ret = of_property_read_u32(dev->of_node, key, &freq);
+       ret = of_property_read_u32(node, key, &freq);
        if (ret) {
                dev_err(dev, "regulator requires %s property\n", key);
                return -EINVAL;
@@ -650,84 +653,40 @@ static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg)
        return -EINVAL;
 }
 
-static int rpm_reg_probe(struct platform_device *pdev)
+static int rpm_reg_of_parse(struct device_node *node,
+                           const struct regulator_desc *desc,
+                           struct regulator_config *config)
 {
-       struct regulator_init_data *initdata;
-       const struct qcom_rpm_reg *template;
-       const struct of_device_id *match;
-       struct regulator_config config = { };
-       struct regulator_dev *rdev;
-       struct qcom_rpm_reg *vreg;
+       struct qcom_rpm_reg *vreg = config->driver_data;
+       struct device *dev = config->dev;
        const char *key;
        u32 force_mode;
        bool pwm;
        u32 val;
        int ret;
 
-       match = of_match_device(rpm_of_match, &pdev->dev);
-       template = match->data;
-
-       vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
-       if (!vreg) {
-               dev_err(&pdev->dev, "failed to allocate vreg\n");
-               return -ENOMEM;
-       }
-       memcpy(vreg, template, sizeof(*vreg));
-       mutex_init(&vreg->lock);
-       vreg->dev = &pdev->dev;
-       vreg->desc.id = -1;
-       vreg->desc.owner = THIS_MODULE;
-       vreg->desc.type = REGULATOR_VOLTAGE;
-       vreg->desc.name = pdev->dev.of_node->name;
-       vreg->desc.supply_name = "vin";
-
-       vreg->rpm = dev_get_drvdata(pdev->dev.parent);
-       if (!vreg->rpm) {
-               dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
-               return -ENODEV;
-       }
-
-       initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
-                                             &vreg->desc);
-       if (!initdata)
-               return -EINVAL;
-
-       key = "reg";
-       ret = of_property_read_u32(pdev->dev.of_node, key, &val);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to read %s\n", key);
-               return ret;
-       }
-       vreg->resource = val;
-
-       if ((vreg->parts->uV.mask || vreg->parts->mV.mask) &&
-           (!initdata->constraints.min_uV || !initdata->constraints.max_uV)) {
-               dev_err(&pdev->dev, "no voltage specified for regulator\n");
-               return -EINVAL;
-       }
-
        key = "bias-pull-down";
-       if (of_property_read_bool(pdev->dev.of_node, key)) {
+       if (of_property_read_bool(node, key)) {
                ret = rpm_reg_set(vreg, &vreg->parts->pd, 1);
                if (ret) {
-                       dev_err(&pdev->dev, "%s is invalid", key);
+                       dev_err(dev, "%s is invalid", key);
                        return ret;
                }
        }
 
        if (vreg->parts->freq.mask) {
-               ret = rpm_reg_of_parse_freq(&pdev->dev, vreg);
+               ret = rpm_reg_of_parse_freq(dev, node, vreg);
                if (ret < 0)
                        return ret;
        }
 
        if (vreg->parts->pm.mask) {
                key = "qcom,power-mode-hysteretic";
-               pwm = !of_property_read_bool(pdev->dev.of_node, key);
+               pwm = !of_property_read_bool(node, key);
 
                ret = rpm_reg_set(vreg, &vreg->parts->pm, pwm);
                if (ret) {
-                       dev_err(&pdev->dev, "failed to set power mode\n");
+                       dev_err(dev, "failed to set power mode\n");
                        return ret;
                }
        }
@@ -736,11 +695,11 @@ static int rpm_reg_probe(struct platform_device *pdev)
                force_mode = -1;
 
                key = "qcom,force-mode";
-               ret = of_property_read_u32(pdev->dev.of_node, key, &val);
+               ret = of_property_read_u32(node, key, &val);
                if (ret == -EINVAL) {
                        val = QCOM_RPM_FORCE_MODE_NONE;
                } else if (ret < 0) {
-                       dev_err(&pdev->dev, "failed to read %s\n", key);
+                       dev_err(dev, "failed to read %s\n", key);
                        return ret;
                }
 
@@ -775,25 +734,192 @@ static int rpm_reg_probe(struct platform_device *pdev)
                }
 
                if (force_mode == -1) {
-                       dev_err(&pdev->dev, "invalid force mode\n");
+                       dev_err(dev, "invalid force mode\n");
                        return -EINVAL;
                }
 
                ret = rpm_reg_set(vreg, &vreg->parts->fm, force_mode);
                if (ret) {
-                       dev_err(&pdev->dev, "failed to set force mode\n");
+                       dev_err(dev, "failed to set force mode\n");
                        return ret;
                }
        }
 
-       config.dev = &pdev->dev;
-       config.init_data = initdata;
-       config.driver_data = vreg;
-       config.of_node = pdev->dev.of_node;
-       rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
-       if (IS_ERR(rdev)) {
-               dev_err(&pdev->dev, "can't register regulator\n");
-               return PTR_ERR(rdev);
+       return 0;
+}
+
+struct rpm_regulator_data {
+       const char *name;
+       int resource;
+       const struct qcom_rpm_reg *template;
+       const char *supply;
+};
+
+static const struct rpm_regulator_data rpm_pm8058_regulators[] = {
+       { "l0",   QCOM_RPM_PM8058_LDO0,   &pm8058_nldo, "vdd_l0_l1_lvs" },
+       { "l1",   QCOM_RPM_PM8058_LDO1,   &pm8058_nldo, "vdd_l0_l1_lvs" },
+       { "l2",   QCOM_RPM_PM8058_LDO2,   &pm8058_pldo, "vdd_l2_l11_l12" },
+       { "l3",   QCOM_RPM_PM8058_LDO3,   &pm8058_pldo, "vdd_l3_l4_l5" },
+       { "l4",   QCOM_RPM_PM8058_LDO4,   &pm8058_pldo, "vdd_l3_l4_l5" },
+       { "l5",   QCOM_RPM_PM8058_LDO5,   &pm8058_pldo, "vdd_l3_l4_l5" },
+       { "l6",   QCOM_RPM_PM8058_LDO6,   &pm8058_pldo, "vdd_l6_l7" },
+       { "l7",   QCOM_RPM_PM8058_LDO7,   &pm8058_pldo, "vdd_l6_l7" },
+       { "l8",   QCOM_RPM_PM8058_LDO8,   &pm8058_pldo, "vdd_l8" },
+       { "l9",   QCOM_RPM_PM8058_LDO9,   &pm8058_pldo, "vdd_l9" },
+       { "l10",  QCOM_RPM_PM8058_LDO10,  &pm8058_pldo, "vdd_l10" },
+       { "l11",  QCOM_RPM_PM8058_LDO11,  &pm8058_pldo, "vdd_l2_l11_l12" },
+       { "l12",  QCOM_RPM_PM8058_LDO12,  &pm8058_pldo, "vdd_l2_l11_l12" },
+       { "l13",  QCOM_RPM_PM8058_LDO13,  &pm8058_pldo, "vdd_l13_l16" },
+       { "l14",  QCOM_RPM_PM8058_LDO14,  &pm8058_pldo, "vdd_l14_l15" },
+       { "l15",  QCOM_RPM_PM8058_LDO15,  &pm8058_pldo, "vdd_l14_l15" },
+       { "l16",  QCOM_RPM_PM8058_LDO16,  &pm8058_pldo, "vdd_l13_l16" },
+       { "l17",  QCOM_RPM_PM8058_LDO17,  &pm8058_pldo, "vdd_l17_l18" },
+       { "l18",  QCOM_RPM_PM8058_LDO18,  &pm8058_pldo, "vdd_l17_l18" },
+       { "l19",  QCOM_RPM_PM8058_LDO19,  &pm8058_pldo, "vdd_l19_l20" },
+       { "l20",  QCOM_RPM_PM8058_LDO20,  &pm8058_pldo, "vdd_l19_l20" },
+       { "l21",  QCOM_RPM_PM8058_LDO21,  &pm8058_nldo, "vdd_l21" },
+       { "l22",  QCOM_RPM_PM8058_LDO22,  &pm8058_nldo, "vdd_l22" },
+       { "l23",  QCOM_RPM_PM8058_LDO23,  &pm8058_nldo, "vdd_l23_l24_l25" },
+       { "l24",  QCOM_RPM_PM8058_LDO24,  &pm8058_nldo, "vdd_l23_l24_l25" },
+       { "l25",  QCOM_RPM_PM8058_LDO25,  &pm8058_nldo, "vdd_l23_l24_l25" },
+
+       { "s0",   QCOM_RPM_PM8058_SMPS0,  &pm8058_smps, "vdd_s0" },
+       { "s1",   QCOM_RPM_PM8058_SMPS1,  &pm8058_smps, "vdd_s1" },
+       { "s2",   QCOM_RPM_PM8058_SMPS2,  &pm8058_smps, "vdd_s2" },
+       { "s3",   QCOM_RPM_PM8058_SMPS3,  &pm8058_smps, "vdd_s3" },
+       { "s4",   QCOM_RPM_PM8058_SMPS4,  &pm8058_smps, "vdd_s4" },
+
+       { "lvs0", QCOM_RPM_PM8058_LVS0, &pm8058_switch, "vdd_l0_l1_lvs" },
+       { "lvs1", QCOM_RPM_PM8058_LVS1, &pm8058_switch, "vdd_l0_l1_lvs" },
+
+       { "ncp",  QCOM_RPM_PM8058_NCP, &pm8058_ncp, "vdd_ncp" },
+       { }
+};
+
+static const struct rpm_regulator_data rpm_pm8901_regulators[] = {
+       { "l0",   QCOM_RPM_PM8901_LDO0, &pm8901_nldo, "vdd_l0" },
+       { "l1",   QCOM_RPM_PM8901_LDO1, &pm8901_pldo, "vdd_l1" },
+       { "l2",   QCOM_RPM_PM8901_LDO2, &pm8901_pldo, "vdd_l2" },
+       { "l3",   QCOM_RPM_PM8901_LDO3, &pm8901_pldo, "vdd_l3" },
+       { "l4",   QCOM_RPM_PM8901_LDO4, &pm8901_pldo, "vdd_l4" },
+       { "l5",   QCOM_RPM_PM8901_LDO5, &pm8901_pldo, "vdd_l5" },
+       { "l6",   QCOM_RPM_PM8901_LDO6, &pm8901_pldo, "vdd_l6" },
+
+       { "s0",   QCOM_RPM_PM8901_SMPS0, &pm8901_ftsmps, "vdd_s0" },
+       { "s1",   QCOM_RPM_PM8901_SMPS1, &pm8901_ftsmps, "vdd_s1" },
+       { "s2",   QCOM_RPM_PM8901_SMPS2, &pm8901_ftsmps, "vdd_s2" },
+       { "s3",   QCOM_RPM_PM8901_SMPS3, &pm8901_ftsmps, "vdd_s3" },
+       { "s4",   QCOM_RPM_PM8901_SMPS4, &pm8901_ftsmps, "vdd_s4" },
+
+       { "lvs0", QCOM_RPM_PM8901_LVS0, &pm8901_switch, "lvs0_in" },
+       { "lvs1", QCOM_RPM_PM8901_LVS1, &pm8901_switch, "lvs1_in" },
+       { "lvs2", QCOM_RPM_PM8901_LVS2, &pm8901_switch, "lvs2_in" },
+       { "lvs3", QCOM_RPM_PM8901_LVS3, &pm8901_switch, "lvs3_in" },
+
+       { "mvs", QCOM_RPM_PM8901_MVS, &pm8901_switch, "mvs_in" },
+       { }
+};
+
+static const struct rpm_regulator_data rpm_pm8921_regulators[] = {
+       { "s1",  QCOM_RPM_PM8921_SMPS1, &pm8921_smps, "vdd_s1" },
+       { "s2",  QCOM_RPM_PM8921_SMPS2, &pm8921_smps, "vdd_s2" },
+       { "s3",  QCOM_RPM_PM8921_SMPS3, &pm8921_smps },
+       { "s4",  QCOM_RPM_PM8921_SMPS4, &pm8921_smps, "vdd_s4" },
+       { "s7",  QCOM_RPM_PM8921_SMPS7, &pm8921_smps, "vdd_s7" },
+       { "s8",  QCOM_RPM_PM8921_SMPS8, &pm8921_smps, "vdd_s8"  },
+
+       { "l1",  QCOM_RPM_PM8921_LDO1, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
+       { "l2",  QCOM_RPM_PM8921_LDO2, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
+       { "l3",  QCOM_RPM_PM8921_LDO3, &pm8921_pldo, "vdd_l3_l15_l17" },
+       { "l4",  QCOM_RPM_PM8921_LDO4, &pm8921_pldo, "vdd_l4_l14" },
+       { "l5",  QCOM_RPM_PM8921_LDO5, &pm8921_pldo, "vdd_l5_l8_l16" },
+       { "l6",  QCOM_RPM_PM8921_LDO6, &pm8921_pldo, "vdd_l6_l7" },
+       { "l7",  QCOM_RPM_PM8921_LDO7, &pm8921_pldo, "vdd_l6_l7" },
+       { "l8",  QCOM_RPM_PM8921_LDO8, &pm8921_pldo, "vdd_l5_l8_l16" },
+       { "l9",  QCOM_RPM_PM8921_LDO9, &pm8921_pldo, "vdd_l9_l11" },
+       { "l10", QCOM_RPM_PM8921_LDO10, &pm8921_pldo, "vdd_l10_l22" },
+       { "l11", QCOM_RPM_PM8921_LDO11, &pm8921_pldo, "vdd_l9_l11" },
+       { "l12", QCOM_RPM_PM8921_LDO12, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
+       { "l14", QCOM_RPM_PM8921_LDO14, &pm8921_pldo, "vdd_l4_l14" },
+       { "l15", QCOM_RPM_PM8921_LDO15, &pm8921_pldo, "vdd_l3_l15_l17" },
+       { "l16", QCOM_RPM_PM8921_LDO16, &pm8921_pldo, "vdd_l5_l8_l16" },
+       { "l17", QCOM_RPM_PM8921_LDO17, &pm8921_pldo, "vdd_l3_l15_l17" },
+       { "l18", QCOM_RPM_PM8921_LDO18, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
+       { "l21", QCOM_RPM_PM8921_LDO21, &pm8921_pldo, "vdd_l21_l23_l29" },
+       { "l22", QCOM_RPM_PM8921_LDO22, &pm8921_pldo, "vdd_l10_l22" },
+       { "l23", QCOM_RPM_PM8921_LDO23, &pm8921_pldo, "vdd_l21_l23_l29" },
+       { "l24", QCOM_RPM_PM8921_LDO24, &pm8921_nldo1200, "vdd_l24" },
+       { "l25", QCOM_RPM_PM8921_LDO25, &pm8921_nldo1200, "vdd_l25" },
+       { "l26", QCOM_RPM_PM8921_LDO26, &pm8921_nldo1200, "vdd_l26" },
+       { "l27", QCOM_RPM_PM8921_LDO27, &pm8921_nldo1200, "vdd_l27" },
+       { "l28", QCOM_RPM_PM8921_LDO28, &pm8921_nldo1200, "vdd_l28" },
+       { "l29", QCOM_RPM_PM8921_LDO29, &pm8921_pldo, "vdd_l21_l23_l29" },
+
+       { "lvs1", QCOM_RPM_PM8921_LVS1, &pm8921_switch, "vin_lvs1_3_6" },
+       { "lvs2", QCOM_RPM_PM8921_LVS2, &pm8921_switch, "vin_lvs2" },
+       { "lvs3", QCOM_RPM_PM8921_LVS3, &pm8921_switch, "vin_lvs1_3_6" },
+       { "lvs4", QCOM_RPM_PM8921_LVS4, &pm8921_switch, "vin_lvs4_5_7" },
+       { "lvs5", QCOM_RPM_PM8921_LVS5, &pm8921_switch, "vin_lvs4_5_7" },
+       { "lvs6", QCOM_RPM_PM8921_LVS6, &pm8921_switch, "vin_lvs1_3_6" },
+       { "lvs7", QCOM_RPM_PM8921_LVS7, &pm8921_switch, "vin_lvs4_5_7" },
+
+       { "usb-switch", QCOM_RPM_USB_OTG_SWITCH, &pm8921_switch, "vin_5vs" },
+       { "hdmi-switch", QCOM_RPM_HDMI_SWITCH, &pm8921_switch, "vin_5vs" },
+       { "ncp", QCOM_RPM_PM8921_NCP, &pm8921_ncp, "vdd_ncp" },
+       { }
+};
+
+static const struct of_device_id rpm_of_match[] = {
+       { .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators },
+       { .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators },
+       { .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_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_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_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
+               if (!vreg)
+                       return -ENOMEM;
+
+               memcpy(vreg, reg->template, sizeof(*vreg));
+               mutex_init(&vreg->lock);
+
+               vreg->dev = &pdev->dev;
+               vreg->resource = reg->resource;
+               vreg->rpm = rpm;
+
+               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;
+               vreg->desc.of_parse_cb = rpm_reg_of_parse;
+
+               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;
index 89025f5602590dbc03f5fa0c3b55dad6a347aab3..7d2ae3e9e942f26f302f526450487213da2cc44d 100644 (file)
@@ -56,6 +56,7 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
 {
        struct stw481x *stw481x = dev_get_platdata(&pdev->dev);
        struct regulator_config config = { };
+       struct regulator_dev *rdev;
        int ret;
 
        /* First disable the external VMMC if it's active */
@@ -75,12 +76,11 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
                                                      pdev->dev.of_node,
                                                      &vmmc_regulator);
 
-       stw481x->vmmc_regulator = devm_regulator_register(&pdev->dev,
-                                               &vmmc_regulator, &config);
-       if (IS_ERR(stw481x->vmmc_regulator)) {
+       rdev = devm_regulator_register(&pdev->dev, &vmmc_regulator, &config);
+       if (IS_ERR(rdev)) {
                dev_err(&pdev->dev,
                        "error initializing STw481x VMMC regulator\n");
-               return PTR_ERR(stw481x->vmmc_regulator);
+               return PTR_ERR(rdev);
        }
 
        dev_info(&pdev->dev, "initialized STw481x VMMC regulator\n");
index 7ec7c390eedaa1085eeb03d4adfce33f7f1b4531..95f6b040186eee1cc8407da82379fe686e7594cc 100644 (file)
@@ -1151,17 +1151,16 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
 static irqreturn_t pmic_uv_handler(int irq, void *data)
 {
        struct regulator_dev *rdev = (struct regulator_dev *)data;
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
 
        mutex_lock(&rdev->mutex);
        if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
                regulator_notifier_call_chain(rdev,
                                              REGULATOR_EVENT_REGULATION_OUT,
-                                             wm8350);
+                                             NULL);
        else
                regulator_notifier_call_chain(rdev,
                                              REGULATOR_EVENT_UNDER_VOLTAGE,
-                                             wm8350);
+                                             NULL);
        mutex_unlock(&rdev->mutex);
 
        return IRQ_HANDLED;
index 472a5adc4642790d2ff1df9eab73aaaf2c4b064d..c29ba7e1430482c1ffe6c6ec92e1bd5cc7b06743 100644 (file)
@@ -55,7 +55,7 @@ static int rtc_suspend(struct device *dev)
        struct timespec64       delta, delta_delta;
        int err;
 
-       if (has_persistent_clock())
+       if (timekeeping_rtc_skipsuspend())
                return 0;
 
        if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
@@ -102,7 +102,7 @@ static int rtc_resume(struct device *dev)
        struct timespec64       sleep_time;
        int err;
 
-       if (has_persistent_clock())
+       if (timekeeping_rtc_skipresume())
                return 0;
 
        rtc_hctosys_ret = -ENODEV;
@@ -117,10 +117,6 @@ static int rtc_resume(struct device *dev)
                return 0;
        }
 
-       if (rtc_valid_tm(&tm) != 0) {
-               pr_debug("%s:  bogus resume time\n", dev_name(&rtc->dev));
-               return 0;
-       }
        new_rtc.tv_sec = rtc_tm_to_time64(&tm);
        new_rtc.tv_nsec = 0;
 
index 37215cf983e92926653d1f3206aa8c4c8842a55a..d43ee409a5f29c8ba344232577f56eab6121a6b2 100644 (file)
@@ -72,7 +72,11 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
                err = -ENODEV;
        else if (rtc->ops->set_time)
                err = rtc->ops->set_time(rtc->dev.parent, tm);
-       else if (rtc->ops->set_mmss) {
+       else if (rtc->ops->set_mmss64) {
+               time64_t secs64 = rtc_tm_to_time64(tm);
+
+               err = rtc->ops->set_mmss64(rtc->dev.parent, secs64);
+       } else if (rtc->ops->set_mmss) {
                time64_t secs64 = rtc_tm_to_time64(tm);
                err = rtc->ops->set_mmss(rtc->dev.parent, secs64);
        } else
@@ -96,6 +100,8 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)
 
        if (!rtc->ops)
                err = -ENODEV;
+       else if (rtc->ops->set_mmss64)
+               err = rtc->ops->set_mmss64(rtc->dev.parent, secs);
        else if (rtc->ops->set_mmss)
                err = rtc->ops->set_mmss(rtc->dev.parent, secs);
        else if (rtc->ops->read_time && rtc->ops->set_time) {
index 1d0340fdb82021b5326182b4a517c4763b0818e8..9b725c55305859b48f5e6f2ffe45088d4b6f0659 100644 (file)
 /*
  * RTC clock functions and device struct declaration
  */
-static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs)
+static int ab3100_rtc_set_mmss(struct device *dev, time64_t secs)
 {
        u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2,
                     AB3100_TI3, AB3100_TI4, AB3100_TI5};
        unsigned char buf[6];
-       u64 fat_time = (u64) secs * AB3100_RTC_CLOCK_RATE * 2;
+       u64 hw_counter = secs * AB3100_RTC_CLOCK_RATE * 2;
        int err = 0;
        int i;
 
-       buf[0] = (fat_time) & 0xFF;
-       buf[1] = (fat_time >> 8) & 0xFF;
-       buf[2] = (fat_time >> 16) & 0xFF;
-       buf[3] = (fat_time >> 24) & 0xFF;
-       buf[4] = (fat_time >> 32) & 0xFF;
-       buf[5] = (fat_time >> 40) & 0xFF;
+       buf[0] = (hw_counter) & 0xFF;
+       buf[1] = (hw_counter >> 8) & 0xFF;
+       buf[2] = (hw_counter >> 16) & 0xFF;
+       buf[3] = (hw_counter >> 24) & 0xFF;
+       buf[4] = (hw_counter >> 32) & 0xFF;
+       buf[5] = (hw_counter >> 40) & 0xFF;
 
        for (i = 0; i < 6; i++) {
                err = abx500_set_register_interruptible(dev, 0,
@@ -75,7 +75,7 @@ static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs)
 
 static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-       unsigned long time;
+       time64_t time;
        u8 rtcval;
        int err;
 
@@ -88,7 +88,7 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
                dev_info(dev, "clock not set (lost power)");
                return -EINVAL;
        } else {
-               u64 fat_time;
+               u64 hw_counter;
                u8 buf[6];
 
                /* Read out time registers */
@@ -98,22 +98,21 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
                if (err != 0)
                        return err;
 
-               fat_time = ((u64) buf[5] << 40) | ((u64) buf[4] << 32) |
+               hw_counter = ((u64) buf[5] << 40) | ((u64) buf[4] << 32) |
                        ((u64) buf[3] << 24) | ((u64) buf[2] << 16) |
                        ((u64) buf[1] << 8) | (u64) buf[0];
-               time = (unsigned long) (fat_time /
-                                       (u64) (AB3100_RTC_CLOCK_RATE * 2));
+               time = hw_counter / (u64) (AB3100_RTC_CLOCK_RATE * 2);
        }
 
-       rtc_time_to_tm(time, tm);
+       rtc_time64_to_tm(time, tm);
 
        return rtc_valid_tm(tm);
 }
 
 static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
-       unsigned long time;
-       u64 fat_time;
+       time64_t time;
+       u64 hw_counter;
        u8 buf[6];
        u8 rtcval;
        int err;
@@ -134,11 +133,11 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
                                                     AB3100_AL0, buf, 4);
        if (err)
                return err;
-       fat_time = ((u64) buf[3] << 40) | ((u64) buf[2] << 32) |
+       hw_counter = ((u64) buf[3] << 40) | ((u64) buf[2] << 32) |
                ((u64) buf[1] << 24) | ((u64) buf[0] << 16);
-       time = (unsigned long) (fat_time / (u64) (AB3100_RTC_CLOCK_RATE * 2));
+       time = hw_counter / (u64) (AB3100_RTC_CLOCK_RATE * 2);
 
-       rtc_time_to_tm(time, &alarm->time);
+       rtc_time64_to_tm(time, &alarm->time);
 
        return rtc_valid_tm(&alarm->time);
 }
@@ -147,17 +146,17 @@ static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
        u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3};
        unsigned char buf[4];
-       unsigned long secs;
-       u64 fat_time;
+       time64_t secs;
+       u64 hw_counter;
        int err;
        int i;
 
-       rtc_tm_to_time(&alarm->time, &secs);
-       fat_time = (u64) secs * AB3100_RTC_CLOCK_RATE * 2;
-       buf[0] = (fat_time >> 16) & 0xFF;
-       buf[1] = (fat_time >> 24) & 0xFF;
-       buf[2] = (fat_time >> 32) & 0xFF;
-       buf[3] = (fat_time >> 40) & 0xFF;
+       secs = rtc_tm_to_time64(&alarm->time);
+       hw_counter = secs * AB3100_RTC_CLOCK_RATE * 2;
+       buf[0] = (hw_counter >> 16) & 0xFF;
+       buf[1] = (hw_counter >> 24) & 0xFF;
+       buf[2] = (hw_counter >> 32) & 0xFF;
+       buf[3] = (hw_counter >> 40) & 0xFF;
 
        /* Set the alarm */
        for (i = 0; i < 4; i++) {
@@ -193,7 +192,7 @@ static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled)
 
 static const struct rtc_class_ops ab3100_rtc_ops = {
        .read_time      = ab3100_rtc_read_time,
-       .set_mmss       = ab3100_rtc_set_mmss,
+       .set_mmss64     = ab3100_rtc_set_mmss,
        .read_alarm     = ab3100_rtc_read_alarm,
        .set_alarm      = ab3100_rtc_set_alarm,
        .alarm_irq_enable = ab3100_rtc_irq_enable,
index ae7c2ba440cf45e9ca2cf234ac17409645d2b5be..af4f85a66b39f0ed9689db01bfe05f9656471468 100644 (file)
@@ -213,7 +213,7 @@ static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm)
        /* get a report with all values through requesting one value */
        sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev,
                        HID_USAGE_SENSOR_TIME, hid_time_addresses[0],
-                       time_state->info[0].report_id);
+                       time_state->info[0].report_id, SENSOR_HUB_SYNC);
        /* wait for all values (event) */
        ret = wait_for_completion_killable_timeout(
                        &time_state->comp_last_time, HZ*6);
index 5bce904b7ee617cb2e3991cd4893ad493a75cbbd..32df1d812367c58acf3ebcd8445597fc8bdac014 100644 (file)
@@ -83,20 +83,19 @@ static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
                        return ret;
        } while (days1 != days2);
 
-       rtc_time_to_tm(days1 * SEC_PER_DAY + seconds, tm);
+       rtc_time64_to_tm((time64_t)days1 * SEC_PER_DAY + seconds, tm);
 
        return rtc_valid_tm(tm);
 }
 
-static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs)
+static int mc13xxx_rtc_set_mmss(struct device *dev, time64_t secs)
 {
        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
        unsigned int seconds, days;
        unsigned int alarmseconds;
        int ret;
 
-       seconds = secs % SEC_PER_DAY;
-       days = secs / SEC_PER_DAY;
+       days = div_s64_rem(secs, SEC_PER_DAY, &seconds);
 
        mc13xxx_lock(priv->mc13xxx);
 
@@ -159,7 +158,7 @@ static int mc13xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
        unsigned seconds, days;
-       unsigned long s1970;
+       time64_t s1970;
        int enabled, pending;
        int ret;
 
@@ -189,10 +188,10 @@ out:
        alarm->enabled = enabled;
        alarm->pending = pending;
 
-       s1970 = days * SEC_PER_DAY + seconds;
+       s1970 = (time64_t)days * SEC_PER_DAY + seconds;
 
-       rtc_time_to_tm(s1970, &alarm->time);
-       dev_dbg(dev, "%s: %lu\n", __func__, s1970);
+       rtc_time64_to_tm(s1970, &alarm->time);
+       dev_dbg(dev, "%s: %lld\n", __func__, (long long)s1970);
 
        return 0;
 }
@@ -200,8 +199,8 @@ out:
 static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
-       unsigned long s1970;
-       unsigned seconds, days;
+       time64_t s1970;
+       u32 seconds, days;
        int ret;
 
        mc13xxx_lock(priv->mc13xxx);
@@ -215,20 +214,17 @@ static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        if (unlikely(ret))
                goto out;
 
-       ret = rtc_tm_to_time(&alarm->time, &s1970);
-       if (unlikely(ret))
-               goto out;
+       s1970 = rtc_tm_to_time64(&alarm->time);
 
-       dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff",
-                       s1970);
+       dev_dbg(dev, "%s: o%2.s %lld\n", __func__, alarm->enabled ? "n" : "ff",
+                       (long long)s1970);
 
        ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled,
                        MC13XXX_IRQ_TODA);
        if (unlikely(ret))
                goto out;
 
-       seconds = s1970 % SEC_PER_DAY;
-       days = s1970 / SEC_PER_DAY;
+       days = div_s64_rem(s1970, SEC_PER_DAY, &seconds);
 
        ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days);
        if (unlikely(ret))
@@ -268,7 +264,7 @@ static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev)
 
 static const struct rtc_class_ops mc13xxx_rtc_ops = {
        .read_time = mc13xxx_rtc_read_time,
-       .set_mmss = mc13xxx_rtc_set_mmss,
+       .set_mmss64 = mc13xxx_rtc_set_mmss,
        .read_alarm = mc13xxx_rtc_read_alarm,
        .set_alarm = mc13xxx_rtc_set_alarm,
        .alarm_irq_enable = mc13xxx_rtc_alarm_irq_enable,
index 3c3f8d10ab439c83fe93ec2041e8a3e29d9e0fc4..09d422b9f7f737d6ba4a0c990212e7f33f1d4038 100644 (file)
@@ -106,7 +106,7 @@ static inline int is_imx1_rtc(struct rtc_plat_data *data)
  * This function is used to obtain the RTC time or the alarm value in
  * second.
  */
-static u32 get_alarm_or_time(struct device *dev, int time_alarm)
+static time64_t get_alarm_or_time(struct device *dev, int time_alarm)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
@@ -129,29 +129,28 @@ static u32 get_alarm_or_time(struct device *dev, int time_alarm)
        hr = hr_min >> 8;
        min = hr_min & 0xff;
 
-       return (((day * 24 + hr) * 60) + min) * 60 + sec;
+       return ((((time64_t)day * 24 + hr) * 60) + min) * 60 + sec;
 }
 
 /*
  * This function sets the RTC alarm value or the time value.
  */
-static void set_alarm_or_time(struct device *dev, int time_alarm, u32 time)
+static void set_alarm_or_time(struct device *dev, int time_alarm, time64_t time)
 {
-       u32 day, hr, min, sec, temp;
+       u32 tod, day, hr, min, sec, temp;
        struct platform_device *pdev = to_platform_device(dev);
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
        void __iomem *ioaddr = pdata->ioaddr;
 
-       day = time / 86400;
-       time -= day * 86400;
+       day = div_s64_rem(time, 86400, &tod);
 
        /* time is within a day now */
-       hr = time / 3600;
-       time -= hr * 3600;
+       hr = tod / 3600;
+       tod -= hr * 3600;
 
        /* time is within an hour now */
-       min = time / 60;
-       sec = time - min * 60;
+       min = tod / 60;
+       sec = tod - min * 60;
 
        temp = (hr << 8) + min;
 
@@ -173,29 +172,18 @@ static void set_alarm_or_time(struct device *dev, int time_alarm, u32 time)
  * This function updates the RTC alarm registers and then clears all the
  * interrupt status bits.
  */
-static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm)
+static void rtc_update_alarm(struct device *dev, struct rtc_time *alrm)
 {
-       struct rtc_time alarm_tm, now_tm;
-       unsigned long now, time;
+       time64_t time;
        struct platform_device *pdev = to_platform_device(dev);
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
        void __iomem *ioaddr = pdata->ioaddr;
 
-       now = get_alarm_or_time(dev, MXC_RTC_TIME);
-       rtc_time_to_tm(now, &now_tm);
-       alarm_tm.tm_year = now_tm.tm_year;
-       alarm_tm.tm_mon = now_tm.tm_mon;
-       alarm_tm.tm_mday = now_tm.tm_mday;
-       alarm_tm.tm_hour = alrm->tm_hour;
-       alarm_tm.tm_min = alrm->tm_min;
-       alarm_tm.tm_sec = alrm->tm_sec;
-       rtc_tm_to_time(&alarm_tm, &time);
+       time = rtc_tm_to_time64(alrm);
 
        /* clear all the interrupt status bits */
        writew(readw(ioaddr + RTC_RTCISR), ioaddr + RTC_RTCISR);
        set_alarm_or_time(dev, MXC_RTC_ALARM, time);
-
-       return 0;
 }
 
 static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit,
@@ -283,14 +271,14 @@ static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
  */
 static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-       u32 val;
+       time64_t val;
 
        /* Avoid roll-over from reading the different registers */
        do {
                val = get_alarm_or_time(dev, MXC_RTC_TIME);
        } while (val != get_alarm_or_time(dev, MXC_RTC_TIME));
 
-       rtc_time_to_tm(val, tm);
+       rtc_time64_to_tm(val, tm);
 
        return 0;
 }
@@ -298,7 +286,7 @@ static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
 /*
  * This function sets the internal RTC time based on tm in Gregorian date.
  */
-static int mxc_rtc_set_mmss(struct device *dev, unsigned long time)
+static int mxc_rtc_set_mmss(struct device *dev, time64_t time)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
@@ -309,9 +297,9 @@ static int mxc_rtc_set_mmss(struct device *dev, unsigned long time)
        if (is_imx1_rtc(pdata)) {
                struct rtc_time tm;
 
-               rtc_time_to_tm(time, &tm);
+               rtc_time64_to_tm(time, &tm);
                tm.tm_year = 70;
-               rtc_tm_to_time(&tm, &time);
+               time = rtc_tm_to_time64(&tm);
        }
 
        /* Avoid roll-over from reading the different registers */
@@ -333,7 +321,7 @@ static int mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
        void __iomem *ioaddr = pdata->ioaddr;
 
-       rtc_time_to_tm(get_alarm_or_time(dev, MXC_RTC_ALARM), &alrm->time);
+       rtc_time64_to_tm(get_alarm_or_time(dev, MXC_RTC_ALARM), &alrm->time);
        alrm->pending = ((readw(ioaddr + RTC_RTCISR) & RTC_ALM_BIT)) ? 1 : 0;
 
        return 0;
@@ -346,11 +334,8 @@ static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-       int ret;
 
-       ret = rtc_update_alarm(dev, &alrm->time);
-       if (ret)
-               return ret;
+       rtc_update_alarm(dev, &alrm->time);
 
        memcpy(&pdata->g_rtc_alarm, &alrm->time, sizeof(struct rtc_time));
        mxc_rtc_irq_enable(dev, RTC_ALM_BIT, alrm->enabled);
@@ -362,7 +347,7 @@ static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 static struct rtc_class_ops mxc_rtc_ops = {
        .release                = mxc_rtc_release,
        .read_time              = mxc_rtc_read_time,
-       .set_mmss               = mxc_rtc_set_mmss,
+       .set_mmss64             = mxc_rtc_set_mmss,
        .read_alarm             = mxc_rtc_read_alarm,
        .set_alarm              = mxc_rtc_set_alarm,
        .alarm_irq_enable       = mxc_rtc_alarm_irq_enable,
index 89ac1d5083c66093b63caa973e37ff4897a1bb6b..4008b84246ca75abb50d1a7895081f39be0f9ac5 100644 (file)
@@ -48,8 +48,6 @@ struct s5m_rtc_reg_config {
        unsigned int alarm0;
        /* First register for alarm 1, seconds */
        unsigned int alarm1;
-       /* SMPL/WTSR register */
-       unsigned int smpl_wtsr;
        /*
         * Register for update flag (UDR). Typically setting UDR field to 1
         * will enable update of time or alarm register. Then it will be
@@ -67,7 +65,6 @@ static const struct s5m_rtc_reg_config s5m_rtc_regs = {
        .ctrl                   = S5M_ALARM1_CONF,
        .alarm0                 = S5M_ALARM0_SEC,
        .alarm1                 = S5M_ALARM1_SEC,
-       .smpl_wtsr              = S5M_WTSR_SMPL_CNTL,
        .rtc_udr_update         = S5M_RTC_UDR_CON,
        .rtc_udr_mask           = S5M_RTC_UDR_MASK,
 };
@@ -82,7 +79,6 @@ static const struct s5m_rtc_reg_config s2mps_rtc_regs = {
        .ctrl                   = S2MPS_RTC_CTRL,
        .alarm0                 = S2MPS_ALARM0_SEC,
        .alarm1                 = S2MPS_ALARM1_SEC,
-       .smpl_wtsr              = S2MPS_WTSR_SMPL_CNTL,
        .rtc_udr_update         = S2MPS_RTC_UDR_CON,
        .rtc_udr_mask           = S2MPS_RTC_WUDR_MASK,
 };
@@ -96,7 +92,6 @@ struct s5m_rtc_info {
        int irq;
        int device_type;
        int rtc_24hr_mode;
-       bool wtsr_smpl;
        const struct s5m_rtc_reg_config *regs;
 };
 
@@ -597,28 +592,6 @@ static const struct rtc_class_ops s5m_rtc_ops = {
        .alarm_irq_enable = s5m_rtc_alarm_irq_enable,
 };
 
-static void s5m_rtc_enable_wtsr(struct s5m_rtc_info *info, bool enable)
-{
-       int ret;
-       ret = regmap_update_bits(info->regmap, info->regs->smpl_wtsr,
-                                WTSR_ENABLE_MASK,
-                                enable ? WTSR_ENABLE_MASK : 0);
-       if (ret < 0)
-               dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
-                       __func__, ret);
-}
-
-static void s5m_rtc_enable_smpl(struct s5m_rtc_info *info, bool enable)
-{
-       int ret;
-       ret = regmap_update_bits(info->regmap, info->regs->smpl_wtsr,
-                                SMPL_ENABLE_MASK,
-                                enable ? SMPL_ENABLE_MASK : 0);
-       if (ret < 0)
-               dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
-                       __func__, ret);
-}
-
 static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
 {
        u8 data[2];
@@ -715,7 +688,6 @@ static int s5m_rtc_probe(struct platform_device *pdev)
        info->dev = &pdev->dev;
        info->s5m87xx = s5m87xx;
        info->device_type = s5m87xx->device_type;
-       info->wtsr_smpl = s5m87xx->wtsr_smpl;
 
        if (s5m87xx->irq_data) {
                info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq);
@@ -731,11 +703,6 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 
        ret = s5m8767_rtc_init_reg(info);
 
-       if (info->wtsr_smpl) {
-               s5m_rtc_enable_wtsr(info, true);
-               s5m_rtc_enable_smpl(info, true);
-       }
-
        device_init_wakeup(&pdev->dev, 1);
 
        info->rtc_dev = devm_rtc_device_register(&pdev->dev, "s5m-rtc",
@@ -768,36 +735,10 @@ err:
        return ret;
 }
 
-static void s5m_rtc_shutdown(struct platform_device *pdev)
-{
-       struct s5m_rtc_info *info = platform_get_drvdata(pdev);
-       int i;
-       unsigned int val = 0;
-       if (info->wtsr_smpl) {
-               for (i = 0; i < 3; i++) {
-                       s5m_rtc_enable_wtsr(info, false);
-                       regmap_read(info->regmap, info->regs->smpl_wtsr, &val);
-                       pr_debug("%s: WTSR_SMPL reg(0x%02x)\n", __func__, val);
-                       if (val & WTSR_ENABLE_MASK)
-                               pr_emerg("%s: fail to disable WTSR\n",
-                                        __func__);
-                       else {
-                               pr_info("%s: success to disable WTSR\n",
-                                       __func__);
-                               break;
-                       }
-               }
-       }
-       /* Disable SMPL when power off */
-       s5m_rtc_enable_smpl(info, false);
-}
-
 static int s5m_rtc_remove(struct platform_device *pdev)
 {
        struct s5m_rtc_info *info = platform_get_drvdata(pdev);
 
-       /* Perform also all shutdown steps when removing */
-       s5m_rtc_shutdown(pdev);
        i2c_unregister_device(info->i2c);
 
        return 0;
@@ -842,7 +783,6 @@ static struct platform_driver s5m_rtc_driver = {
        },
        .probe          = s5m_rtc_probe,
        .remove         = s5m_rtc_remove,
-       .shutdown       = s5m_rtc_shutdown,
        .id_table       = s5m_rtc_id,
 };
 
index 8f86fa91de1a80e4e7d1a60a58c3acd3a27bd1ce..3a2da4c892d65f25c597f1872932d639108bd57a 100644 (file)
 #include <linux/rtc.h>
 #include <linux/platform_device.h>
 
+static int test_mmss64;
+module_param(test_mmss64, int, 0644);
+MODULE_PARM_DESC(test_mmss64, "Test struct rtc_class_ops.set_mmss64().");
+
 static struct platform_device *test0 = NULL, *test1 = NULL;
 
 static int test_rtc_read_alarm(struct device *dev,
@@ -30,7 +34,13 @@ static int test_rtc_set_alarm(struct device *dev,
 static int test_rtc_read_time(struct device *dev,
        struct rtc_time *tm)
 {
-       rtc_time_to_tm(get_seconds(), tm);
+       rtc_time64_to_tm(ktime_get_real_seconds(), tm);
+       return 0;
+}
+
+static int test_rtc_set_mmss64(struct device *dev, time64_t secs)
+{
+       dev_info(dev, "%s, secs = %lld\n", __func__, (long long)secs);
        return 0;
 }
 
@@ -55,7 +65,7 @@ static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
        return 0;
 }
 
-static const struct rtc_class_ops test_rtc_ops = {
+static struct rtc_class_ops test_rtc_ops = {
        .proc = test_rtc_proc,
        .read_time = test_rtc_read_time,
        .read_alarm = test_rtc_read_alarm,
@@ -101,6 +111,11 @@ static int test_probe(struct platform_device *plat_dev)
        int err;
        struct rtc_device *rtc;
 
+       if (test_mmss64) {
+               test_rtc_ops.set_mmss64 = test_rtc_set_mmss64;
+               test_rtc_ops.set_mmss = NULL;
+       }
+
        rtc = devm_rtc_device_register(&plat_dev->dev, "test",
                                &test_rtc_ops, THIS_MODULE);
        if (IS_ERR(rtc)) {
index eb71872d0361c0dbedd8f994aae72ce6bd0d2c7e..7728d5e32bf4921d7bfd02cabe4b5c1ea124a6bd 100644 (file)
@@ -11,7 +11,7 @@
  * rtc_set_ntp_time - Save NTP synchronized time to the RTC
  * @now: Current time of day
  *
- * Replacement for the NTP platform function update_persistent_clock
+ * Replacement for the NTP platform function update_persistent_clock64
  * that stores time for later retrieval by rtc_hctosys.
  *
  * Returns 0 on successful RTC update, -ENODEV if a RTC update is not
@@ -35,7 +35,10 @@ int rtc_set_ntp_time(struct timespec64 now)
        if (rtc) {
                /* rtc_hctosys exclusively uses UTC, so we call set_time here,
                 * not set_mmss. */
-               if (rtc->ops && (rtc->ops->set_time || rtc->ops->set_mmss))
+               if (rtc->ops &&
+                   (rtc->ops->set_time ||
+                    rtc->ops->set_mmss64 ||
+                    rtc->ops->set_mmss))
                        err = rtc_set_time(rtc, &tm);
                rtc_class_close(rtc);
        }
index 2c5d4567d1da3d024a008112a5b4176ce9876e4d..acde3f5d6e9e7f3bb015bb21d494ec1a0acb9049 100644 (file)
@@ -738,11 +738,11 @@ static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act)
                return ZFCP_ERP_FAILED;
 
        if (mempool_resize(act->adapter->pool.sr_data,
-                          act->adapter->stat_read_buf_num, GFP_KERNEL))
+                          act->adapter->stat_read_buf_num))
                return ZFCP_ERP_FAILED;
 
        if (mempool_resize(act->adapter->pool.status_read_req,
-                          act->adapter->stat_read_buf_num, GFP_KERNEL))
+                          act->adapter->stat_read_buf_num))
                return ZFCP_ERP_FAILED;
 
        atomic_set(&act->adapter->stat_miss, act->adapter->stat_read_buf_num);
index 80d97f3d2ed9b36753f8beaac4448a361fd2b3c5..1028760b8a22145e792de569862641d627d5b89f 100644 (file)
@@ -237,7 +237,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
                        beiscsi_log(phba, KERN_WARNING,
                                    BEISCSI_LOG_INIT | BEISCSI_LOG_EH |
                                    BEISCSI_LOG_CONFIG,
-                                   "BC_%d : Insufficent Buffer Error "
+                                   "BC_%d : Insufficient Buffer Error "
                                    "Resp_Len : %d Actual_Resp_Len : %d\n",
                                    mbx_resp_hdr->response_length,
                                    mbx_resp_hdr->actual_resp_len);
index a7cc618378187fb7d38e504d51befb93e78b223c..923a2b5a24395547212207312588b125f19de3a2 100644 (file)
@@ -5734,9 +5734,9 @@ free_port:
 hba_free:
        if (phba->msix_enabled)
                pci_disable_msix(phba->pcidev);
-       iscsi_host_remove(phba->shost);
        pci_dev_put(phba->pcidev);
        iscsi_host_free(phba->shost);
+       pci_set_drvdata(pcidev, NULL);
 disable_pci:
        pci_disable_device(pcidev);
        return ret;
index 0045742fab7d22005bb1f707738ba8176738bd25..dad959fcf6d8e2513369437e1bbd175f582daaad 100644 (file)
@@ -339,7 +339,7 @@ ch_readconfig(scsi_changer *ch)
                        ch->firsts[CHET_DT],
                        ch->counts[CHET_DT]);
        } else {
-               VPRINTK(KERN_INFO, "reading element address assigment page failed!\n");
+               VPRINTK(KERN_INFO, "reading element address assignment page failed!\n");
        }
 
        /* vendor specific element types */
index 488c3929f19a95b84377d9ae522fb9b236857d3c..0cccd6033feb6b477366fc3343e665d1ed68562e 100644 (file)
@@ -186,7 +186,7 @@ static int _osd_get_print_system_info(struct osd_dev *od,
 
                if (unlikely(len > sizeof(odi->systemid))) {
                        OSD_ERR("OSD Target error: OSD_SYSTEM_ID too long(%d). "
-                               "device idetification might not work\n", len);
+                               "device identification might not work\n", len);
                        len = sizeof(odi->systemid);
                }
                odi->systemid_len = len;
index e59f25bff7abbb49a9f2478b8e1cf59e9d8fe399..5bb57c5282c94e9526ffd37cf71688248004463e 100644 (file)
@@ -5364,7 +5364,7 @@ qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
        blob = qla2x00_request_firmware(vha);
        if (!blob) {
                ql_log(ql_log_info, vha, 0x0083,
-                   "Fimware image unavailable.\n");
+                   "Firmware image unavailable.\n");
                ql_log(ql_log_info, vha, 0x0084,
                    "Firmware images can be retrieved from: "QLA_FW_URL ".\n");
                return QLA_FUNCTION_FAILED;
@@ -5467,7 +5467,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
        blob = qla2x00_request_firmware(vha);
        if (!blob) {
                ql_log(ql_log_warn, vha, 0x0090,
-                   "Fimware image unavailable.\n");
+                   "Firmware image unavailable.\n");
                ql_log(ql_log_warn, vha, 0x0091,
                    "Firmware images can be retrieved from: "
                    QLA_FW_URL ".\n");
index 5c2e0317f1c0a31e408f89788536352c19c4c7fa..ca3804e34833eb709adcb8099377925b2ed7aeda 100644 (file)
@@ -788,7 +788,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
                rsp->msix = &ha->msix_entries[que_id + 1];
        else
                ql_log(ql_log_warn, base_vha, 0x00e3,
-                   "MSIX not enalbled.\n");
+                   "MSIX not enabled.\n");
 
        ha->rsp_q_map[que_id] = rsp;
        rsp->rid = rid;
index 54cb2ac9339bdd4441b9125333222bbfefb3732c..7d2b18f2675ce2ef28b41db6cce442e5ba3ad390 100644 (file)
@@ -1274,7 +1274,7 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
 
                if (off == ADDR_ERROR) {
                        ql_log(ql_log_fatal, vha, 0x0116,
-                           "Unknow addr: 0x%08lx.\n", buf[i].addr);
+                           "Unknown addr: 0x%08lx.\n", buf[i].addr);
                        continue;
                }
 
index cce1cbc1a9276f4492d6efa16996313c00daabd6..5319b3cb219e33f4f4cf69740b2bf5386b7a0491 100644 (file)
@@ -446,11 +446,11 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha)
                }
                ha->flags.cpu_affinity_enabled = 1;
                ql_dbg(ql_dbg_multiq, vha, 0xc007,
-                   "CPU affinity mode enalbed, "
+                   "CPU affinity mode enabled, "
                    "no. of response queues:%d no. of request queues:%d.\n",
                    ha->max_rsp_queues, ha->max_req_queues);
                ql_dbg(ql_dbg_init, vha, 0x00e9,
-                   "CPU affinity mode enalbed, "
+                   "CPU affinity mode enabled, "
                    "no. of response queues:%d no. of request queues:%d.\n",
                    ha->max_rsp_queues, ha->max_req_queues);
        }
@@ -4102,7 +4102,7 @@ qla83xx_schedule_work(scsi_qla_host_t *base_vha, int work_code)
                break;
        default:
                ql_log(ql_log_warn, base_vha, 0xb05f,
-                   "Unknow work-code=0x%x.\n", work_code);
+                   "Unknown work-code=0x%x.\n", work_code);
        }
 
        return;
@@ -4702,7 +4702,7 @@ qla83xx_idc_state_handler(scsi_qla_host_t *base_vha)
                        break;
                default:
                        ql_log(ql_log_warn, base_vha, 0xb071,
-                           "Unknow Device State: %x.\n", dev_state);
+                           "Unknown Device State: %x.\n", dev_state);
                        qla83xx_idc_unlock(base_vha, 0);
                        qla8xxx_dev_failed_handler(base_vha);
                        rval = QLA_FUNCTION_FAILED;
index 4cdaffca17fc8dddbbc8478d0af60bb186bcff87..c95a4e943fc6843b78d8120955318d76547a956e 100644 (file)
@@ -26,6 +26,7 @@
 #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>
@@ -2586,3 +2587,33 @@ 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 54d7a6cbb98a48d06b932cce40c488488760da08..b1a263137a23391a1e19c2589f35fdaf2c4f514f 100644 (file)
@@ -1311,9 +1311,11 @@ scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
                                    "rejecting I/O to dead device\n");
                        ret = BLKPREP_KILL;
                        break;
-               case SDEV_QUIESCE:
                case SDEV_BLOCK:
                case SDEV_CREATED_BLOCK:
+                       ret = BLKPREP_DEFER;
+                       break;
+               case SDEV_QUIESCE:
                        /*
                         * If the devices is blocked we defer normal commands.
                         */
index 2270bd51f9c2c240c669e562eb77052f89425a83..9d7b7db75e4b96b6fbb33bf24b91c205add07d79 100644 (file)
@@ -33,7 +33,6 @@ static int sg_version_num = 30536;    /* 2 digits for each component */
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/aio.h>
 #include <linux/errno.h>
 #include <linux/mtio.h>
 #include <linux/ioctl.h>
@@ -51,6 +50,7 @@ static int sg_version_num = 30536;    /* 2 digits for each component */
 #include <linux/mutex.h>
 #include <linux/atomic.h>
 #include <linux/ratelimit.h>
+#include <linux/uio.h>
 
 #include "scsi.h"
 #include <scsi/scsi_dbg.h>
@@ -1745,17 +1745,14 @@ sg_start_req(Sg_request *srp, unsigned char *cmd)
        }
 
        if (iov_count) {
-               int size = sizeof(struct iovec) * iov_count;
-               struct iovec *iov;
+               struct iovec *iov = NULL;
                struct iov_iter i;
 
-               iov = memdup_user(hp->dxferp, size);
-               if (IS_ERR(iov))
-                       return PTR_ERR(iov);
+               res = import_iovec(rw, hp->dxferp, iov_count, 0, &iov, &i);
+               if (res < 0)
+                       return res;
 
-               iov_iter_init(&i, rw, iov, iov_count,
-                             min_t(size_t, hp->dxfer_len,
-                                   iov_length(iov, iov_count)));
+               iov_iter_truncate(&i, hp->dxfer_len);
 
                res = blk_rq_map_user_iov(q, rq, md, &i, GFP_ATOMIC);
                kfree(iov);
index 5d60a868830dafe126d7d5bcdf73e959325919be..2aa85e398f769e66f14838dbfee94759089c1fea 100644 (file)
@@ -4225,22 +4225,15 @@ static struct scsi_host_template ufshcd_driver_template = {
 static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg,
                                   int ua)
 {
-       int ret = 0;
-       struct regulator *reg = vreg->reg;
-       const char *name = vreg->name;
+       int ret;
 
-       BUG_ON(!vreg);
+       if (!vreg)
+               return 0;
 
-       ret = regulator_set_optimum_mode(reg, ua);
-       if (ret >= 0) {
-               /*
-                * regulator_set_optimum_mode() returns new regulator
-                * mode upon success.
-                */
-               ret = 0;
-       } else {
-               dev_err(dev, "%s: %s set optimum mode(ua=%d) failed, err=%d\n",
-                               __func__, name, ua, ret);
+       ret = regulator_set_load(vreg->reg, ua);
+       if (ret < 0) {
+               dev_err(dev, "%s: %s set load (ua=%d) failed, err=%d\n",
+                               __func__, vreg->name, ua, ret);
        }
 
        return ret;
@@ -4249,18 +4242,12 @@ static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg,
 static inline int ufshcd_config_vreg_lpm(struct ufs_hba *hba,
                                         struct ufs_vreg *vreg)
 {
-       if (!vreg)
-               return 0;
-
        return ufshcd_config_vreg_load(hba->dev, vreg, UFS_VREG_LPM_LOAD_UA);
 }
 
 static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
                                         struct ufs_vreg *vreg)
 {
-       if (!vreg)
-               return 0;
-
        return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA);
 }
 
index ab8dfbef6f1bb681a9ff14ca1e7ca09749b6a199..198f96b7fb45dab78845ba1fcde123ea680e2082 100644 (file)
@@ -159,10 +159,9 @@ config SPI_BUTTERFLY
 
 config SPI_CADENCE
        tristate "Cadence SPI controller"
-       depends on ARM
        help
          This selects the Cadence SPI controller master driver
-         used by Xilinx Zynq.
+         used by Xilinx Zynq and ZynqMP.
 
 config SPI_CLPS711X
        tristate "CLPS711X host SPI controller"
@@ -632,7 +631,7 @@ config SPI_DW_PCI
 
 config SPI_DW_MID_DMA
        bool "DMA support for DW SPI controller on Intel MID platform"
-       depends on SPI_DW_PCI && INTEL_MID_DMAC
+       depends on SPI_DW_PCI && DW_DMAC_PCI
 
 config SPI_DW_MMIO
        tristate "Memory-mapped io interface driver for DW SPI core"
index 06de34001c6695a5a741925e862d7baa05853c98..a2f40b1b222500eb53d14c681ab58f3d3c445af8 100644 (file)
          | SPI_BF(name, value))
 
 /* Register access macros */
+#ifdef CONFIG_AVR32
 #define spi_readl(port, reg) \
        __raw_readl((port)->regs + SPI_##reg)
 #define spi_writel(port, reg, value) \
        __raw_writel((value), (port)->regs + SPI_##reg)
-
+#else
+#define spi_readl(port, reg) \
+       readl_relaxed((port)->regs + SPI_##reg)
+#define spi_writel(port, reg, value) \
+       writel_relaxed((value), (port)->regs + SPI_##reg)
+#endif
 /* use PIO for small transfers, avoiding DMA setup/teardown overhead and
  * cache operations; better heuristics consider wordsize and bitrate.
  */
index 419a782ab6d50541809f0c8b10b3d8eaeeb1ae89..f63864a893c520c40d9c79f1c8ca838b15dedc8c 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2012 Chris Boot
  * Copyright (C) 2013 Stephen Warren
+ * Copyright (C) 2015 Martin Sperl
  *
  * This driver is inspired by:
  * spi-ath79.c, Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
@@ -29,6 +30,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/of_gpio.h>
 #include <linux/of_device.h>
 #include <linux/spi/spi.h>
 
 #define BCM2835_SPI_CS_CS_10           0x00000002
 #define BCM2835_SPI_CS_CS_01           0x00000001
 
-#define BCM2835_SPI_TIMEOUT_MS 30000
-#define BCM2835_SPI_MODE_BITS  (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS)
+#define BCM2835_SPI_POLLING_LIMIT_US   30
+#define BCM2835_SPI_TIMEOUT_MS         30000
+#define BCM2835_SPI_MODE_BITS  (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
+                               | SPI_NO_CS | SPI_3WIRE)
 
 #define DRV_NAME       "spi-bcm2835"
 
@@ -75,10 +79,10 @@ struct bcm2835_spi {
        void __iomem *regs;
        struct clk *clk;
        int irq;
-       struct completion done;
        const u8 *tx_buf;
        u8 *rx_buf;
-       int len;
+       int tx_len;
+       int rx_len;
 };
 
 static inline u32 bcm2835_rd(struct bcm2835_spi *bs, unsigned reg)
@@ -91,205 +95,315 @@ static inline void bcm2835_wr(struct bcm2835_spi *bs, unsigned reg, u32 val)
        writel(val, bs->regs + reg);
 }
 
-static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs, int len)
+static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs)
 {
        u8 byte;
 
-       while (len--) {
+       while ((bs->rx_len) &&
+              (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD)) {
                byte = bcm2835_rd(bs, BCM2835_SPI_FIFO);
                if (bs->rx_buf)
                        *bs->rx_buf++ = byte;
+               bs->rx_len--;
        }
 }
 
-static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs, int len)
+static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs)
 {
        u8 byte;
 
-       if (len > bs->len)
-               len = bs->len;
-
-       while (len--) {
+       while ((bs->tx_len) &&
+              (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_TXD)) {
                byte = bs->tx_buf ? *bs->tx_buf++ : 0;
                bcm2835_wr(bs, BCM2835_SPI_FIFO, byte);
-               bs->len--;
+               bs->tx_len--;
        }
 }
 
+static void bcm2835_spi_reset_hw(struct spi_master *master)
+{
+       struct bcm2835_spi *bs = spi_master_get_devdata(master);
+       u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+
+       /* Disable SPI interrupts and transfer */
+       cs &= ~(BCM2835_SPI_CS_INTR |
+               BCM2835_SPI_CS_INTD |
+               BCM2835_SPI_CS_TA);
+       /* and reset RX/TX FIFOS */
+       cs |= BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX;
+
+       /* and reset the SPI_HW */
+       bcm2835_wr(bs, BCM2835_SPI_CS, cs);
+}
+
 static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id)
 {
        struct spi_master *master = dev_id;
        struct bcm2835_spi *bs = spi_master_get_devdata(master);
-       u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
 
-       /*
-        * RXR - RX needs Reading. This means 12 (or more) bytes have been
-        * transmitted and hence 12 (or more) bytes have been received.
-        *
-        * The FIFO is 16-bytes deep. We check for this interrupt to keep the
-        * FIFO full; we have a 4-byte-time buffer for IRQ latency. We check
-        * this before DONE (TX empty) just in case we delayed processing this
-        * interrupt for some reason.
-        *
-        * We only check for this case if we have more bytes to TX; at the end
-        * of the transfer, we ignore this pipelining optimization, and let
-        * bcm2835_spi_finish_transfer() drain the RX FIFO.
+       /* Read as many bytes as possible from FIFO */
+       bcm2835_rd_fifo(bs);
+       /* Write as many bytes as possible to FIFO */
+       bcm2835_wr_fifo(bs);
+
+       /* based on flags decide if we can finish the transfer */
+       if (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE) {
+               /* Transfer complete - reset SPI HW */
+               bcm2835_spi_reset_hw(master);
+               /* wake up the framework */
+               complete(&master->xfer_completion);
+       }
+
+       return IRQ_HANDLED;
+}
+
+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)
+{
+       struct bcm2835_spi *bs = spi_master_get_devdata(master);
+       unsigned long timeout = jiffies +
+               max(4 * xfer_time_us * HZ / 1000000, 2uL);
+
+       /* enable HW block without interrupts */
+       bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA);
+
+       /* set timeout to 4x the expected time, or 2 jiffies */
+       /* loop until finished the transfer */
+       while (bs->rx_len) {
+               /* read from fifo as much as possible */
+               bcm2835_rd_fifo(bs);
+               /* fill in tx fifo as much as possible */
+               bcm2835_wr_fifo(bs);
+               /* if we still expect some data after the read,
+                * check for a possible timeout
+                */
+               if (bs->rx_len && time_after(jiffies, timeout)) {
+                       /* Transfer complete - reset SPI HW */
+                       bcm2835_spi_reset_hw(master);
+                       /* and return timeout */
+                       return -ETIMEDOUT;
+               }
+       }
+
+       /* Transfer complete - reset SPI HW */
+       bcm2835_spi_reset_hw(master);
+       /* and return without waiting for completion */
+       return 0;
+}
+
+static int bcm2835_spi_transfer_one_irq(struct spi_master *master,
+                                       struct spi_device *spi,
+                                       struct spi_transfer *tfr,
+                                       u32 cs)
+{
+       struct bcm2835_spi *bs = spi_master_get_devdata(master);
+
+       /* fill in fifo if we have gpio-cs
+        * note that there have been rare events where the native-CS
+        * flapped for <1us which may change the behaviour
+        * with gpio-cs this does not happen, so it is implemented
+        * only for this case
         */
-       if (bs->len && (cs & BCM2835_SPI_CS_RXR)) {
-               /* Read 12 bytes of data */
-               bcm2835_rd_fifo(bs, 12);
-
-               /* Write up to 12 bytes */
-               bcm2835_wr_fifo(bs, 12);
-
-               /*
-                * We must have written something to the TX FIFO due to the
-                * bs->len check above, so cannot be DONE. Hence, return
-                * early. Note that DONE could also be set if we serviced an
-                * RXR interrupt really late.
+       if (gpio_is_valid(spi->cs_gpio)) {
+               /* enable HW block, but without interrupts enabled
+                * this would triggern an immediate interrupt
                 */
-               return IRQ_HANDLED;
+               bcm2835_wr(bs, BCM2835_SPI_CS,
+                          cs | BCM2835_SPI_CS_TA);
+               /* fill in tx fifo as much as possible */
+               bcm2835_wr_fifo(bs);
        }
 
        /*
-        * DONE - TX empty. This occurs when we first enable the transfer
-        * since we do not pre-fill the TX FIFO. At any other time, given that
-        * we refill the TX FIFO above based on RXR, and hence ignore DONE if
-        * RXR is set, DONE really does mean end-of-transfer.
+        * Enable the HW block. This will immediately trigger a DONE (TX
+        * empty) interrupt, upon which we will fill the TX FIFO with the
+        * first TX bytes. Pre-filling the TX FIFO here to avoid the
+        * interrupt doesn't work:-(
         */
-       if (cs & BCM2835_SPI_CS_DONE) {
-               if (bs->len) { /* First interrupt in a transfer */
-                       bcm2835_wr_fifo(bs, 16);
-               } else { /* Transfer complete */
-                       /* Disable SPI interrupts */
-                       cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD);
-                       bcm2835_wr(bs, BCM2835_SPI_CS, cs);
-
-                       /*
-                        * Wake up bcm2835_spi_transfer_one(), which will call
-                        * bcm2835_spi_finish_transfer(), to drain the RX FIFO.
-                        */
-                       complete(&bs->done);
-               }
-
-               return IRQ_HANDLED;
-       }
+       cs |= BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA;
+       bcm2835_wr(bs, BCM2835_SPI_CS, cs);
 
-       return IRQ_NONE;
+       /* signal that we need to wait for completion */
+       return 1;
 }
 
-static int bcm2835_spi_start_transfer(struct spi_device *spi,
-               struct spi_transfer *tfr)
+static int bcm2835_spi_transfer_one(struct spi_master *master,
+                                   struct spi_device *spi,
+                                   struct spi_transfer *tfr)
 {
-       struct bcm2835_spi *bs = spi_master_get_devdata(spi->master);
+       struct bcm2835_spi *bs = spi_master_get_devdata(master);
        unsigned long spi_hz, clk_hz, cdiv;
-       u32 cs = BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA;
+       unsigned long spi_used_hz, xfer_time_us;
+       u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
 
+       /* set clock */
        spi_hz = tfr->speed_hz;
        clk_hz = clk_get_rate(bs->clk);
 
        if (spi_hz >= clk_hz / 2) {
                cdiv = 2; /* clk_hz/2 is the fastest we can go */
        } else if (spi_hz) {
-               /* CDIV must be a power of two */
-               cdiv = roundup_pow_of_two(DIV_ROUND_UP(clk_hz, spi_hz));
+               /* CDIV must be a multiple of two */
+               cdiv = DIV_ROUND_UP(clk_hz, spi_hz);
+               cdiv += (cdiv % 2);
 
                if (cdiv >= 65536)
                        cdiv = 0; /* 0 is the slowest we can go */
-       } else
+       } else {
                cdiv = 0; /* 0 is the slowest we can go */
+       }
+       spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536);
+       bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
 
+       /* handle all the modes */
+       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;
 
-       if (!(spi->mode & SPI_NO_CS)) {
-               if (spi->mode & SPI_CS_HIGH) {
-                       cs |= BCM2835_SPI_CS_CSPOL;
-                       cs |= BCM2835_SPI_CS_CSPOL0 << spi->chip_select;
-               }
-
-               cs |= spi->chip_select;
-       }
+       /* 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
+        * not get called for cs_gpio cases, so we need to do it here
+        */
+       if (gpio_is_valid(spi->cs_gpio) || (spi->mode & SPI_NO_CS))
+               cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01;
 
-       reinit_completion(&bs->done);
+       /* set transmit buffers and length */
        bs->tx_buf = tfr->tx_buf;
        bs->rx_buf = tfr->rx_buf;
-       bs->len = tfr->len;
+       bs->tx_len = tfr->len;
+       bs->rx_len = tfr->len;
 
-       bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
-       /*
-        * Enable the HW block. This will immediately trigger a DONE (TX
-        * empty) interrupt, upon which we will fill the TX FIFO with the
-        * first TX bytes. Pre-filling the TX FIFO here to avoid the
-        * interrupt doesn't work:-(
-        */
-       bcm2835_wr(bs, BCM2835_SPI_CS, cs);
+       /* calculate the estimated time in us the transfer runs */
+       xfer_time_us = tfr->len
+               * 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */
+               * 1000000 / spi_used_hz;
 
-       return 0;
+       /* for short requests run polling*/
+       if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US)
+               return bcm2835_spi_transfer_one_poll(master, spi, tfr,
+                                                    cs, xfer_time_us);
+
+       return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs);
 }
 
-static int bcm2835_spi_finish_transfer(struct spi_device *spi,
-               struct spi_transfer *tfr, bool cs_change)
+static void bcm2835_spi_handle_err(struct spi_master *master,
+                                  struct spi_message *msg)
 {
-       struct bcm2835_spi *bs = spi_master_get_devdata(spi->master);
-       u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+       bcm2835_spi_reset_hw(master);
+}
+
+static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level)
+{
+       /*
+        * we can assume that we are "native" as per spi_set_cs
+        *   calling us ONLY when cs_gpio is not set
+        * we can also assume that we are CS < 3 as per bcm2835_spi_setup
+        *   we would not get called because of error handling there.
+        * the level passed is the electrical level not enabled/disabled
+        *   so it has to get translated back to enable/disable
+        *   see spi_set_cs in spi.c for the implementation
+        */
 
-       /* Drain RX FIFO */
-       while (cs & BCM2835_SPI_CS_RXD) {
-               bcm2835_rd_fifo(bs, 1);
-               cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+       struct spi_master *master = spi->master;
+       struct bcm2835_spi *bs = spi_master_get_devdata(master);
+       u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+       bool enable;
+
+       /* calculate the enable flag from the passed gpio_level */
+       enable = (spi->mode & SPI_CS_HIGH) ? gpio_level : !gpio_level;
+
+       /* set flags for "reverse" polarity in the registers */
+       if (spi->mode & SPI_CS_HIGH) {
+               /* set the correct CS-bits */
+               cs |= BCM2835_SPI_CS_CSPOL;
+               cs |= BCM2835_SPI_CS_CSPOL0 << spi->chip_select;
+       } else {
+               /* clean the CS-bits */
+               cs &= ~BCM2835_SPI_CS_CSPOL;
+               cs &= ~(BCM2835_SPI_CS_CSPOL0 << spi->chip_select);
        }
 
-       if (tfr->delay_usecs)
-               udelay(tfr->delay_usecs);
+       /* select the correct chip_select depending on disabled/enabled */
+       if (enable) {
+               /* set cs correctly */
+               if (spi->mode & SPI_NO_CS) {
+                       /* use the "undefined" chip-select */
+                       cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01;
+               } else {
+                       /* set the chip select */
+                       cs &= ~(BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01);
+                       cs |= spi->chip_select;
+               }
+       } else {
+               /* disable CSPOL which puts HW-CS into deselected state */
+               cs &= ~BCM2835_SPI_CS_CSPOL;
+               /* use the "undefined" chip-select as precaution */
+               cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01;
+       }
 
-       if (cs_change)
-               /* Clear TA flag */
-               bcm2835_wr(bs, BCM2835_SPI_CS, cs & ~BCM2835_SPI_CS_TA);
+       /* finally set the calculated flags in SPI_CS */
+       bcm2835_wr(bs, BCM2835_SPI_CS, cs);
+}
 
-       return 0;
+static int chip_match_name(struct gpio_chip *chip, void *data)
+{
+       return !strcmp(chip->label, data);
 }
 
-static int bcm2835_spi_transfer_one(struct spi_master *master,
-               struct spi_message *mesg)
+static int bcm2835_spi_setup(struct spi_device *spi)
 {
-       struct bcm2835_spi *bs = spi_master_get_devdata(master);
-       struct spi_transfer *tfr;
-       struct spi_device *spi = mesg->spi;
-       int err = 0;
-       unsigned int timeout;
-       bool cs_change;
-
-       list_for_each_entry(tfr, &mesg->transfers, transfer_list) {
-               err = bcm2835_spi_start_transfer(spi, tfr);
-               if (err)
-                       goto out;
-
-               timeout = wait_for_completion_timeout(&bs->done,
-                               msecs_to_jiffies(BCM2835_SPI_TIMEOUT_MS));
-               if (!timeout) {
-                       err = -ETIMEDOUT;
-                       goto out;
-               }
+       int err;
+       struct gpio_chip *chip;
+       /*
+        * sanity checking the native-chipselects
+        */
+       if (spi->mode & SPI_NO_CS)
+               return 0;
+       if (gpio_is_valid(spi->cs_gpio))
+               return 0;
+       if (spi->chip_select > 1) {
+               /* error in the case of native CS requested with CS > 1
+                * officially there is a CS2, but it is not documented
+                * which GPIO is connected with that...
+                */
+               dev_err(&spi->dev,
+                       "setup: only two native chip-selects are supported\n");
+               return -EINVAL;
+       }
+       /* now translate native cs to GPIO */
 
-               cs_change = tfr->cs_change ||
-                       list_is_last(&tfr->transfer_list, &mesg->transfers);
+       /* get the gpio chip for the base */
+       chip = gpiochip_find("pinctrl-bcm2835", chip_match_name);
+       if (!chip)
+               return 0;
 
-               err = bcm2835_spi_finish_transfer(spi, tfr, cs_change);
-               if (err)
-                       goto out;
+       /* and calculate the real CS */
+       spi->cs_gpio = chip->base + 8 - spi->chip_select;
 
-               mesg->actual_length += (tfr->len - bs->len);
-       }
+       /* and set up the "mode" and level */
+       dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n",
+                spi->chip_select, spi->cs_gpio);
 
-out:
-       /* Clear FIFOs, and disable the HW block */
-       bcm2835_wr(bs, BCM2835_SPI_CS,
-                  BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
-       mesg->status = err;
-       spi_finalize_current_message(master);
+       /* set up GPIO as output and pull to the correct level */
+       err = gpio_direction_output(spi->cs_gpio,
+                                   (spi->mode & SPI_CS_HIGH) ? 0 : 1);
+       if (err) {
+               dev_err(&spi->dev,
+                       "could not set CS%i gpio %i as output: %i",
+                       spi->chip_select, spi->cs_gpio, err);
+               return err;
+       }
+       /* the implementation of pinctrl-bcm2835 currently does not
+        * set the GPIO value when using gpio_direction_output
+        * so we are setting it here explicitly
+        */
+       gpio_set_value(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
 
        return 0;
 }
@@ -312,13 +426,14 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
        master->mode_bits = BCM2835_SPI_MODE_BITS;
        master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->num_chipselect = 3;
-       master->transfer_one_message = bcm2835_spi_transfer_one;
+       master->setup = bcm2835_spi_setup;
+       master->set_cs = bcm2835_spi_set_cs;
+       master->transfer_one = bcm2835_spi_transfer_one;
+       master->handle_err = bcm2835_spi_handle_err;
        master->dev.of_node = pdev->dev.of_node;
 
        bs = spi_master_get_devdata(master);
 
-       init_completion(&bs->done);
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        bs->regs = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(bs->regs)) {
@@ -343,13 +458,13 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
        clk_prepare_enable(bs->clk);
 
        err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
-                               dev_name(&pdev->dev), master);
+                              dev_name(&pdev->dev), master);
        if (err) {
                dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
                goto out_clk_disable;
        }
 
-       /* initialise the hardware */
+       /* initialise the hardware with the default polarities */
        bcm2835_wr(bs, BCM2835_SPI_CS,
                   BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
 
index 3fb91c81015a39a670afc818d90a9f3c8ae54521..1520554978a31373126829025a45f37b75a73702 100644 (file)
@@ -44,7 +44,7 @@ static int bcm53xxspi_wait(struct bcm53xxspi *b53spi, unsigned int timeout_ms)
        u32 tmp;
 
        /* SPE bit has to be 0 before we read MSPI STATUS */
-       deadline = jiffies + BCM53XXSPI_SPE_TIMEOUT_MS * HZ / 1000;
+       deadline = jiffies + msecs_to_jiffies(BCM53XXSPI_SPE_TIMEOUT_MS);
        do {
                tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2);
                if (!(tmp & B53SPI_MSPI_SPCR2_SPE))
@@ -56,7 +56,7 @@ static int bcm53xxspi_wait(struct bcm53xxspi *b53spi, unsigned int timeout_ms)
                goto spi_timeout;
 
        /* Check status */
-       deadline = jiffies + timeout_ms * HZ / 1000;
+       deadline = jiffies + msecs_to_jiffies(timeout_ms);
        do {
                tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_MSPI_STATUS);
                if (tmp & B53SPI_MSPI_MSPI_STATUS_SPIF) {
index 37079937d2f77a5b33e20086b6d2a1c6d4fe5331..a3d65b4f49445d144fcba077ce3413630300e8c8 100644 (file)
@@ -559,7 +559,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
        struct spi_transfer *previous = NULL;
        struct bfin_spi_slave_data *chip = NULL;
        unsigned int bits_per_word;
-       u16 cr, cr_width, dma_width, dma_config;
+       u16 cr, cr_width = 0, dma_width, dma_config;
        u32 tranf_success = 1;
        u8 full_duplex = 0;
 
@@ -648,7 +648,6 @@ static void bfin_spi_pump_transfers(unsigned long data)
        } else if (bits_per_word == 8) {
                drv_data->n_bytes = bits_per_word/8;
                drv_data->len = transfer->len;
-               cr_width = 0;
                drv_data->ops = &bfin_bfin_spi_transfer_ops_u8;
        }
        cr = bfin_read(&drv_data->regs->ctl) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);
index c616e41521be18589ec89ab68dcfeec9cd477da7..06b34e5bcfa37eaf9eba3e9ff8d1d017454dc81d 100644 (file)
@@ -49,12 +49,17 @@ 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);
        /* clock starts at inactive polarity */
        for (word <<= (32 - bits); likely(bits); bits--) {
 
                /* setup MSB (to slave) on trailing edge */
-               if ((flags & SPI_MASTER_NO_TX) == 0)
-                       setmosi(spi, word & (1 << 31));
+               if ((flags & SPI_MASTER_NO_TX) == 0) {
+                       if ((word & (1 << 31)) != oldbit) {
+                               setmosi(spi, word & (1 << 31));
+                               oldbit = word & (1 << 31);
+                       }
+               }
                spidelay(nsecs);        /* T(setup) */
 
                setsck(spi, !cpol);
@@ -76,13 +81,18 @@ 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));
        /* clock starts at inactive polarity */
        for (word <<= (32 - bits); likely(bits); bits--) {
 
                /* setup MSB (to slave) on leading edge */
                setsck(spi, !cpol);
-               if ((flags & SPI_MASTER_NO_TX) == 0)
-                       setmosi(spi, word & (1 << 31));
+               if ((flags & SPI_MASTER_NO_TX) == 0) {
+                       if ((word & (1 << 31)) != oldbit) {
+                               setmosi(spi, word & (1 << 31));
+                               oldbit = word & (1 << 31);
+                       }
+               }
                spidelay(nsecs); /* T(setup) */
 
                setsck(spi, cpol);
index 4f8c798e0633a81483c3b05af46805b1848ba386..bb1052e748f28269b3cdde6390c6998b43b98d37 100644 (file)
 #include "spi-dw.h"
 
 #ifdef CONFIG_SPI_DW_MID_DMA
-#include <linux/intel_mid_dma.h>
 #include <linux/pci.h>
+#include <linux/platform_data/dma-dw.h>
 
 #define RX_BUSY                0
 #define TX_BUSY                1
 
-struct mid_dma {
-       struct intel_mid_dma_slave      dmas_tx;
-       struct intel_mid_dma_slave      dmas_rx;
-};
+static struct dw_dma_slave mid_dma_tx = { .dst_id = 1 };
+static struct dw_dma_slave mid_dma_rx = { .src_id = 0 };
 
 static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param)
 {
-       struct dw_spi *dws = param;
+       struct dw_dma_slave *s = param;
+
+       if (s->dma_dev != chan->device->dev)
+               return false;
 
-       return dws->dma_dev == chan->device->dev;
+       chan->private = s;
+       return true;
 }
 
 static int mid_spi_dma_init(struct dw_spi *dws)
 {
-       struct mid_dma *dw_dma = dws->dma_priv;
        struct pci_dev *dma_dev;
-       struct intel_mid_dma_slave *rxs, *txs;
+       struct dw_dma_slave *tx = dws->dma_tx;
+       struct dw_dma_slave *rx = dws->dma_rx;
        dma_cap_mask_t mask;
 
        /*
@@ -56,28 +58,22 @@ static int mid_spi_dma_init(struct dw_spi *dws)
        if (!dma_dev)
                return -ENODEV;
 
-       dws->dma_dev = &dma_dev->dev;
-
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE, mask);
 
        /* 1. Init rx channel */
-       dws->rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
+       rx->dma_dev = &dma_dev->dev;
+       dws->rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, rx);
        if (!dws->rxchan)
                goto err_exit;
-       rxs = &dw_dma->dmas_rx;
-       rxs->hs_mode = LNW_DMA_HW_HS;
-       rxs->cfg_mode = LNW_DMA_PER_TO_MEM;
-       dws->rxchan->private = rxs;
+       dws->master->dma_rx = dws->rxchan;
 
        /* 2. Init tx channel */
-       dws->txchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
+       tx->dma_dev = &dma_dev->dev;
+       dws->txchan = dma_request_channel(mask, mid_spi_dma_chan_filter, tx);
        if (!dws->txchan)
                goto free_rxchan;
-       txs = &dw_dma->dmas_tx;
-       txs->hs_mode = LNW_DMA_HW_HS;
-       txs->cfg_mode = LNW_DMA_MEM_TO_PER;
-       dws->txchan->private = txs;
+       dws->master->dma_tx = dws->txchan;
 
        dws->dma_inited = 1;
        return 0;
@@ -100,6 +96,42 @@ static void mid_spi_dma_exit(struct dw_spi *dws)
        dma_release_channel(dws->rxchan);
 }
 
+static irqreturn_t dma_transfer(struct dw_spi *dws)
+{
+       u16 irq_status = dw_readl(dws, DW_SPI_ISR);
+
+       if (!irq_status)
+               return IRQ_NONE;
+
+       dw_readl(dws, DW_SPI_ICR);
+       spi_reset_chip(dws);
+
+       dev_err(&dws->master->dev, "%s: FIFO overrun/underrun\n", __func__);
+       dws->master->cur_msg->status = -EIO;
+       spi_finalize_current_transfer(dws->master);
+       return IRQ_HANDLED;
+}
+
+static bool mid_spi_can_dma(struct spi_master *master, struct spi_device *spi,
+               struct spi_transfer *xfer)
+{
+       struct dw_spi *dws = spi_master_get_devdata(master);
+
+       if (!dws->dma_inited)
+               return false;
+
+       return xfer->len > dws->fifo_len;
+}
+
+static enum dma_slave_buswidth convert_dma_width(u32 dma_width) {
+       if (dma_width == 1)
+               return DMA_SLAVE_BUSWIDTH_1_BYTE;
+       else if (dma_width == 2)
+               return DMA_SLAVE_BUSWIDTH_2_BYTES;
+
+       return DMA_SLAVE_BUSWIDTH_UNDEFINED;
+}
+
 /*
  * dws->dma_chan_busy is set before the dma transfer starts, callback for tx
  * channel will clear a corresponding bit.
@@ -111,33 +143,30 @@ static void dw_spi_dma_tx_done(void *arg)
        clear_bit(TX_BUSY, &dws->dma_chan_busy);
        if (test_bit(RX_BUSY, &dws->dma_chan_busy))
                return;
-       dw_spi_xfer_done(dws);
+       spi_finalize_current_transfer(dws->master);
 }
 
-static struct dma_async_tx_descriptor *dw_spi_dma_prepare_tx(struct dw_spi *dws)
+static struct dma_async_tx_descriptor *dw_spi_dma_prepare_tx(struct dw_spi *dws,
+               struct spi_transfer *xfer)
 {
        struct dma_slave_config txconf;
        struct dma_async_tx_descriptor *txdesc;
 
-       if (!dws->tx_dma)
+       if (!xfer->tx_buf)
                return NULL;
 
        txconf.direction = DMA_MEM_TO_DEV;
        txconf.dst_addr = dws->dma_addr;
-       txconf.dst_maxburst = LNW_DMA_MSIZE_16;
+       txconf.dst_maxburst = 16;
        txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       txconf.dst_addr_width = dws->dma_width;
+       txconf.dst_addr_width = convert_dma_width(dws->dma_width);
        txconf.device_fc = false;
 
        dmaengine_slave_config(dws->txchan, &txconf);
 
-       memset(&dws->tx_sgl, 0, sizeof(dws->tx_sgl));
-       dws->tx_sgl.dma_address = dws->tx_dma;
-       dws->tx_sgl.length = dws->len;
-
        txdesc = dmaengine_prep_slave_sg(dws->txchan,
-                               &dws->tx_sgl,
-                               1,
+                               xfer->tx_sg.sgl,
+                               xfer->tx_sg.nents,
                                DMA_MEM_TO_DEV,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!txdesc)
@@ -160,33 +189,30 @@ static void dw_spi_dma_rx_done(void *arg)
        clear_bit(RX_BUSY, &dws->dma_chan_busy);
        if (test_bit(TX_BUSY, &dws->dma_chan_busy))
                return;
-       dw_spi_xfer_done(dws);
+       spi_finalize_current_transfer(dws->master);
 }
 
-static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx(struct dw_spi *dws)
+static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx(struct dw_spi *dws,
+               struct spi_transfer *xfer)
 {
        struct dma_slave_config rxconf;
        struct dma_async_tx_descriptor *rxdesc;
 
-       if (!dws->rx_dma)
+       if (!xfer->rx_buf)
                return NULL;
 
        rxconf.direction = DMA_DEV_TO_MEM;
        rxconf.src_addr = dws->dma_addr;
-       rxconf.src_maxburst = LNW_DMA_MSIZE_16;
+       rxconf.src_maxburst = 16;
        rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       rxconf.src_addr_width = dws->dma_width;
+       rxconf.src_addr_width = convert_dma_width(dws->dma_width);
        rxconf.device_fc = false;
 
        dmaengine_slave_config(dws->rxchan, &rxconf);
 
-       memset(&dws->rx_sgl, 0, sizeof(dws->rx_sgl));
-       dws->rx_sgl.dma_address = dws->rx_dma;
-       dws->rx_sgl.length = dws->len;
-
        rxdesc = dmaengine_prep_slave_sg(dws->rxchan,
-                               &dws->rx_sgl,
-                               1,
+                               xfer->rx_sg.sgl,
+                               xfer->rx_sg.nents,
                                DMA_DEV_TO_MEM,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!rxdesc)
@@ -198,37 +224,36 @@ static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx(struct dw_spi *dws)
        return rxdesc;
 }
 
-static void dw_spi_dma_setup(struct dw_spi *dws)
+static int mid_spi_dma_setup(struct dw_spi *dws, struct spi_transfer *xfer)
 {
        u16 dma_ctrl = 0;
 
-       spi_enable_chip(dws, 0);
+       dw_writel(dws, DW_SPI_DMARDLR, 0xf);
+       dw_writel(dws, DW_SPI_DMATDLR, 0x10);
 
-       dw_writew(dws, DW_SPI_DMARDLR, 0xf);
-       dw_writew(dws, DW_SPI_DMATDLR, 0x10);
-
-       if (dws->tx_dma)
+       if (xfer->tx_buf)
                dma_ctrl |= SPI_DMA_TDMAE;
-       if (dws->rx_dma)
+       if (xfer->rx_buf)
                dma_ctrl |= SPI_DMA_RDMAE;
-       dw_writew(dws, DW_SPI_DMACR, dma_ctrl);
+       dw_writel(dws, DW_SPI_DMACR, dma_ctrl);
+
+       /* Set the interrupt mask */
+       spi_umask_intr(dws, SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI);
 
-       spi_enable_chip(dws, 1);
+       dws->transfer_handler = dma_transfer;
+
+       return 0;
 }
 
-static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
+static int mid_spi_dma_transfer(struct dw_spi *dws, struct spi_transfer *xfer)
 {
        struct dma_async_tx_descriptor *txdesc, *rxdesc;
 
-       /* 1. setup DMA related registers */
-       if (cs_change)
-               dw_spi_dma_setup(dws);
+       /* Prepare the TX dma transfer */
+       txdesc = dw_spi_dma_prepare_tx(dws, xfer);
 
-       /* 2. Prepare the TX dma transfer */
-       txdesc = dw_spi_dma_prepare_tx(dws);
-
-       /* 3. Prepare the RX dma transfer */
-       rxdesc = dw_spi_dma_prepare_rx(dws);
+       /* Prepare the RX dma transfer */
+       rxdesc = dw_spi_dma_prepare_rx(dws, xfer);
 
        /* rx must be started before tx due to spi instinct */
        if (rxdesc) {
@@ -246,10 +271,25 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
        return 0;
 }
 
+static void mid_spi_dma_stop(struct dw_spi *dws)
+{
+       if (test_bit(TX_BUSY, &dws->dma_chan_busy)) {
+               dmaengine_terminate_all(dws->txchan);
+               clear_bit(TX_BUSY, &dws->dma_chan_busy);
+       }
+       if (test_bit(RX_BUSY, &dws->dma_chan_busy)) {
+               dmaengine_terminate_all(dws->rxchan);
+               clear_bit(RX_BUSY, &dws->dma_chan_busy);
+       }
+}
+
 static struct dw_spi_dma_ops mid_dma_ops = {
        .dma_init       = mid_spi_dma_init,
        .dma_exit       = mid_spi_dma_exit,
+       .dma_setup      = mid_spi_dma_setup,
+       .can_dma        = mid_spi_can_dma,
        .dma_transfer   = mid_spi_dma_transfer,
+       .dma_stop       = mid_spi_dma_stop,
 };
 #endif
 
@@ -282,9 +322,8 @@ int dw_spi_mid_init(struct dw_spi *dws)
        iounmap(clk_reg);
 
 #ifdef CONFIG_SPI_DW_MID_DMA
-       dws->dma_priv = kzalloc(sizeof(struct mid_dma), GFP_KERNEL);
-       if (!dws->dma_priv)
-               return -ENOMEM;
+       dws->dma_tx = &mid_dma_tx;
+       dws->dma_rx = &mid_dma_rx;
        dws->dma_ops = &mid_dma_ops;
 #endif
        return 0;
index 4847afba89f4e933e5a5d778c5f94e1a14ffe156..8d67d03c71ebcdec375023f8db910d3d0d8469ec 100644 (file)
 #include <linux/debugfs.h>
 #endif
 
-#define START_STATE    ((void *)0)
-#define RUNNING_STATE  ((void *)1)
-#define DONE_STATE     ((void *)2)
-#define ERROR_STATE    ((void *)-1)
-
 /* Slave spi_dev related */
 struct chip_data {
        u16 cr0;
@@ -143,13 +138,26 @@ static inline void dw_spi_debugfs_remove(struct dw_spi *dws)
 }
 #endif /* CONFIG_DEBUG_FS */
 
+static void dw_spi_set_cs(struct spi_device *spi, bool enable)
+{
+       struct dw_spi *dws = spi_master_get_devdata(spi->master);
+       struct chip_data *chip = spi_get_ctldata(spi);
+
+       /* Chip select logic is inverted from spi_set_cs() */
+       if (chip && chip->cs_control)
+               chip->cs_control(!enable);
+
+       if (!enable)
+               dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select));
+}
+
 /* Return the max entries we can fill into tx fifo */
 static inline u32 tx_max(struct dw_spi *dws)
 {
        u32 tx_left, tx_room, rxtx_gap;
 
        tx_left = (dws->tx_end - dws->tx) / dws->n_bytes;
-       tx_room = dws->fifo_len - dw_readw(dws, DW_SPI_TXFLR);
+       tx_room = dws->fifo_len - dw_readl(dws, DW_SPI_TXFLR);
 
        /*
         * Another concern is about the tx/rx mismatch, we
@@ -170,7 +178,7 @@ static inline u32 rx_max(struct dw_spi *dws)
 {
        u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes;
 
-       return min_t(u32, rx_left, dw_readw(dws, DW_SPI_RXFLR));
+       return min_t(u32, rx_left, dw_readl(dws, DW_SPI_RXFLR));
 }
 
 static void dw_writer(struct dw_spi *dws)
@@ -186,7 +194,7 @@ static void dw_writer(struct dw_spi *dws)
                        else
                                txw = *(u16 *)(dws->tx);
                }
-               dw_writew(dws, DW_SPI_DR, txw);
+               dw_writel(dws, DW_SPI_DR, txw);
                dws->tx += dws->n_bytes;
        }
 }
@@ -197,7 +205,7 @@ static void dw_reader(struct dw_spi *dws)
        u16 rxw;
 
        while (max--) {
-               rxw = dw_readw(dws, DW_SPI_DR);
+               rxw = dw_readl(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)
@@ -209,103 +217,22 @@ static void dw_reader(struct dw_spi *dws)
        }
 }
 
-static void *next_transfer(struct dw_spi *dws)
-{
-       struct spi_message *msg = dws->cur_msg;
-       struct spi_transfer *trans = dws->cur_transfer;
-
-       /* Move to next transfer */
-       if (trans->transfer_list.next != &msg->transfers) {
-               dws->cur_transfer =
-                       list_entry(trans->transfer_list.next,
-                                       struct spi_transfer,
-                                       transfer_list);
-               return RUNNING_STATE;
-       }
-
-       return DONE_STATE;
-}
-
-/*
- * Note: first step is the protocol driver prepares
- * a dma-capable memory, and this func just need translate
- * the virt addr to physical
- */
-static int map_dma_buffers(struct dw_spi *dws)
-{
-       if (!dws->cur_msg->is_dma_mapped
-               || !dws->dma_inited
-               || !dws->cur_chip->enable_dma
-               || !dws->dma_ops)
-               return 0;
-
-       if (dws->cur_transfer->tx_dma)
-               dws->tx_dma = dws->cur_transfer->tx_dma;
-
-       if (dws->cur_transfer->rx_dma)
-               dws->rx_dma = dws->cur_transfer->rx_dma;
-
-       return 1;
-}
-
-/* Caller already set message->status; dma and pio irqs are blocked */
-static void giveback(struct dw_spi *dws)
-{
-       struct spi_transfer *last_transfer;
-       struct spi_message *msg;
-
-       msg = dws->cur_msg;
-       dws->cur_msg = NULL;
-       dws->cur_transfer = NULL;
-       dws->prev_chip = dws->cur_chip;
-       dws->cur_chip = NULL;
-       dws->dma_mapped = 0;
-
-       last_transfer = list_last_entry(&msg->transfers, struct spi_transfer,
-                                       transfer_list);
-
-       if (!last_transfer->cs_change)
-               spi_chip_sel(dws, msg->spi, 0);
-
-       spi_finalize_current_message(dws->master);
-}
-
 static void int_error_stop(struct dw_spi *dws, const char *msg)
 {
-       /* Stop the hw */
-       spi_enable_chip(dws, 0);
+       spi_reset_chip(dws);
 
        dev_err(&dws->master->dev, "%s\n", msg);
-       dws->cur_msg->state = ERROR_STATE;
-       tasklet_schedule(&dws->pump_transfers);
+       dws->master->cur_msg->status = -EIO;
+       spi_finalize_current_transfer(dws->master);
 }
 
-void dw_spi_xfer_done(struct dw_spi *dws)
-{
-       /* Update total byte transferred return count actual bytes read */
-       dws->cur_msg->actual_length += dws->len;
-
-       /* Move to next transfer */
-       dws->cur_msg->state = next_transfer(dws);
-
-       /* Handle end of message */
-       if (dws->cur_msg->state == DONE_STATE) {
-               dws->cur_msg->status = 0;
-               giveback(dws);
-       } else
-               tasklet_schedule(&dws->pump_transfers);
-}
-EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
-
 static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 {
-       u16 irq_status = dw_readw(dws, DW_SPI_ISR);
+       u16 irq_status = dw_readl(dws, DW_SPI_ISR);
 
        /* Error handling */
        if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {
-               dw_readw(dws, DW_SPI_TXOICR);
-               dw_readw(dws, DW_SPI_RXOICR);
-               dw_readw(dws, DW_SPI_RXUICR);
+               dw_readl(dws, DW_SPI_ICR);
                int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun");
                return IRQ_HANDLED;
        }
@@ -313,7 +240,7 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
        dw_reader(dws);
        if (dws->rx_end == dws->rx) {
                spi_mask_intr(dws, SPI_INT_TXEI);
-               dw_spi_xfer_done(dws);
+               spi_finalize_current_transfer(dws->master);
                return IRQ_HANDLED;
        }
        if (irq_status & SPI_INT_TXEI) {
@@ -328,13 +255,14 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 
 static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 {
-       struct dw_spi *dws = dev_id;
-       u16 irq_status = dw_readw(dws, DW_SPI_ISR) & 0x3f;
+       struct spi_master *master = dev_id;
+       struct dw_spi *dws = spi_master_get_devdata(master);
+       u16 irq_status = dw_readl(dws, DW_SPI_ISR) & 0x3f;
 
        if (!irq_status)
                return IRQ_NONE;
 
-       if (!dws->cur_msg) {
+       if (!master->cur_msg) {
                spi_mask_intr(dws, SPI_INT_TXEI);
                return IRQ_HANDLED;
        }
@@ -343,7 +271,7 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 }
 
 /* Must be called inside pump_transfers() */
-static void poll_transfer(struct dw_spi *dws)
+static int poll_transfer(struct dw_spi *dws)
 {
        do {
                dw_writer(dws);
@@ -351,64 +279,32 @@ static void poll_transfer(struct dw_spi *dws)
                cpu_relax();
        } while (dws->rx_end > dws->rx);
 
-       dw_spi_xfer_done(dws);
+       return 0;
 }
 
-static void pump_transfers(unsigned long data)
+static int dw_spi_transfer_one(struct spi_master *master,
+               struct spi_device *spi, struct spi_transfer *transfer)
 {
-       struct dw_spi *dws = (struct dw_spi *)data;
-       struct spi_message *message = NULL;
-       struct spi_transfer *transfer = NULL;
-       struct spi_transfer *previous = NULL;
-       struct spi_device *spi = NULL;
-       struct chip_data *chip = NULL;
-       u8 bits = 0;
+       struct dw_spi *dws = spi_master_get_devdata(master);
+       struct chip_data *chip = spi_get_ctldata(spi);
        u8 imask = 0;
-       u8 cs_change = 0;
-       u16 txint_level = 0;
+       u16 txlevel = 0;
        u16 clk_div = 0;
        u32 speed = 0;
        u32 cr0 = 0;
+       int ret;
 
-       /* Get current state information */
-       message = dws->cur_msg;
-       transfer = dws->cur_transfer;
-       chip = dws->cur_chip;
-       spi = message->spi;
-
-       if (message->state == ERROR_STATE) {
-               message->status = -EIO;
-               goto early_exit;
-       }
-
-       /* Handle end of message */
-       if (message->state == DONE_STATE) {
-               message->status = 0;
-               goto early_exit;
-       }
-
-       /* Delay if requested at end of transfer */
-       if (message->state == RUNNING_STATE) {
-               previous = list_entry(transfer->transfer_list.prev,
-                                       struct spi_transfer,
-                                       transfer_list);
-               if (previous->delay_usecs)
-                       udelay(previous->delay_usecs);
-       }
-
+       dws->dma_mapped = 0;
        dws->n_bytes = chip->n_bytes;
        dws->dma_width = chip->dma_width;
-       dws->cs_control = chip->cs_control;
 
-       dws->rx_dma = transfer->rx_dma;
-       dws->tx_dma = transfer->tx_dma;
        dws->tx = (void *)transfer->tx_buf;
        dws->tx_end = dws->tx + transfer->len;
        dws->rx = transfer->rx_buf;
        dws->rx_end = dws->rx + transfer->len;
-       dws->len = dws->cur_transfer->len;
-       if (chip != dws->prev_chip)
-               cs_change = 1;
+       dws->len = transfer->len;
+
+       spi_enable_chip(dws, 0);
 
        cr0 = chip->cr0;
 
@@ -416,32 +312,37 @@ static void pump_transfers(unsigned long data)
        if (transfer->speed_hz) {
                speed = chip->speed_hz;
 
-               if ((transfer->speed_hz != speed) || (!chip->clk_div)) {
+               if ((transfer->speed_hz != speed) || !chip->clk_div) {
                        speed = transfer->speed_hz;
 
                        /* clk_div doesn't support odd number */
-                       clk_div = dws->max_freq / speed;
-                       clk_div = (clk_div + 1) & 0xfffe;
+                       clk_div = (dws->max_freq / speed + 1) & 0xfffe;
 
                        chip->speed_hz = speed;
                        chip->clk_div = clk_div;
+
+                       spi_set_clk(dws, chip->clk_div);
                }
        }
        if (transfer->bits_per_word) {
-               bits = transfer->bits_per_word;
-               dws->n_bytes = dws->dma_width = bits >> 3;
-               cr0 = (bits - 1)
+               if (transfer->bits_per_word == 8) {
+                       dws->n_bytes = 1;
+                       dws->dma_width = 1;
+               } else if (transfer->bits_per_word == 16) {
+                       dws->n_bytes = 2;
+                       dws->dma_width = 2;
+               }
+               cr0 = (transfer->bits_per_word - 1)
                        | (chip->type << SPI_FRF_OFFSET)
                        | (spi->mode << SPI_MODE_OFFSET)
                        | (chip->tmode << SPI_TMOD_OFFSET);
        }
-       message->state = RUNNING_STATE;
 
        /*
         * Adjust transfer mode if necessary. Requires platform dependent
         * chipselect mechanism.
         */
-       if (dws->cs_control) {
+       if (chip->cs_control) {
                if (dws->rx && dws->tx)
                        chip->tmode = SPI_TMOD_TR;
                else if (dws->rx)
@@ -453,80 +354,60 @@ static void pump_transfers(unsigned long data)
                cr0 |= (chip->tmode << SPI_TMOD_OFFSET);
        }
 
+       dw_writel(dws, DW_SPI_CTRL0, cr0);
+
        /* Check if current transfer is a DMA transaction */
-       dws->dma_mapped = map_dma_buffers(dws);
+       if (master->can_dma && master->can_dma(master, spi, transfer))
+               dws->dma_mapped = master->cur_msg_mapped;
+
+       /* For poll mode just disable all interrupts */
+       spi_mask_intr(dws, 0xff);
 
        /*
         * Interrupt mode
         * we only need set the TXEI IRQ, as TX/RX always happen syncronizely
         */
-       if (!dws->dma_mapped && !chip->poll_mode) {
-               int templen = dws->len / dws->n_bytes;
-
-               txint_level = dws->fifo_len / 2;
-               txint_level = (templen > txint_level) ? txint_level : templen;
+       if (dws->dma_mapped) {
+               ret = dws->dma_ops->dma_setup(dws, transfer);
+               if (ret < 0) {
+                       spi_enable_chip(dws, 1);
+                       return ret;
+               }
+       } else if (!chip->poll_mode) {
+               txlevel = min_t(u16, dws->fifo_len / 2, dws->len / dws->n_bytes);
+               dw_writel(dws, DW_SPI_TXFLTR, txlevel);
 
+               /* Set the interrupt mask */
                imask |= SPI_INT_TXEI | SPI_INT_TXOI |
                         SPI_INT_RXUI | SPI_INT_RXOI;
+               spi_umask_intr(dws, imask);
+
                dws->transfer_handler = interrupt_transfer;
        }
 
-       /*
-        * Reprogram registers only if
-        *      1. chip select changes
-        *      2. clk_div is changed
-        *      3. control value changes
-        */
-       if (dw_readw(dws, DW_SPI_CTRL0) != cr0 || cs_change || clk_div || imask) {
-               spi_enable_chip(dws, 0);
-
-               if (dw_readw(dws, DW_SPI_CTRL0) != cr0)
-                       dw_writew(dws, DW_SPI_CTRL0, cr0);
-
-               spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
-               spi_chip_sel(dws, spi, 1);
-
-               /* Set the interrupt mask, for poll mode just disable all int */
-               spi_mask_intr(dws, 0xff);
-               if (imask)
-                       spi_umask_intr(dws, imask);
-               if (txint_level)
-                       dw_writew(dws, DW_SPI_TXFLTR, txint_level);
+       spi_enable_chip(dws, 1);
 
-               spi_enable_chip(dws, 1);
-               if (cs_change)
-                       dws->prev_chip = chip;
+       if (dws->dma_mapped) {
+               ret = dws->dma_ops->dma_transfer(dws, transfer);
+               if (ret < 0)
+                       return ret;
        }
 
-       if (dws->dma_mapped)
-               dws->dma_ops->dma_transfer(dws, cs_change);
-
        if (chip->poll_mode)
-               poll_transfer(dws);
-
-       return;
+               return poll_transfer(dws);
 
-early_exit:
-       giveback(dws);
+       return 1;
 }
 
-static int dw_spi_transfer_one_message(struct spi_master *master,
+static void dw_spi_handle_err(struct spi_master *master,
                struct spi_message *msg)
 {
        struct dw_spi *dws = spi_master_get_devdata(master);
 
-       dws->cur_msg = msg;
-       /* Initial message state */
-       dws->cur_msg->state = START_STATE;
-       dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,
-                                               struct spi_transfer,
-                                               transfer_list);
-       dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);
-
-       /* Launch transfers */
-       tasklet_schedule(&dws->pump_transfers);
+       if (dws->dma_mapped)
+               dws->dma_ops->dma_stop(dws);
 
-       return 0;
+       spi_reset_chip(dws);
 }
 
 /* This may be called twice for each spi dev */
@@ -561,8 +442,6 @@ static int dw_spi_setup(struct spi_device *spi)
 
                chip->rx_threshold = 0;
                chip->tx_threshold = 0;
-
-               chip->enable_dma = chip_info->enable_dma;
        }
 
        if (spi->bits_per_word == 8) {
@@ -610,9 +489,7 @@ static void dw_spi_cleanup(struct spi_device *spi)
 /* Restart the controller, disable all interrupts, clean rx fifo */
 static void spi_hw_init(struct device *dev, struct dw_spi *dws)
 {
-       spi_enable_chip(dws, 0);
-       spi_mask_intr(dws, 0xff);
-       spi_enable_chip(dws, 1);
+       spi_reset_chip(dws);
 
        /*
         * Try to detect the FIFO depth if not set by interface driver,
@@ -622,11 +499,11 @@ static void spi_hw_init(struct device *dev, struct dw_spi *dws)
                u32 fifo;
 
                for (fifo = 1; fifo < 256; fifo++) {
-                       dw_writew(dws, DW_SPI_TXFLTR, fifo);
-                       if (fifo != dw_readw(dws, DW_SPI_TXFLTR))
+                       dw_writel(dws, DW_SPI_TXFLTR, fifo);
+                       if (fifo != dw_readl(dws, DW_SPI_TXFLTR))
                                break;
                }
-               dw_writew(dws, DW_SPI_TXFLTR, 0);
+               dw_writel(dws, DW_SPI_TXFLTR, 0);
 
                dws->fifo_len = (fifo == 1) ? 0 : fifo;
                dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
@@ -646,13 +523,12 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
 
        dws->master = master;
        dws->type = SSI_MOTO_SPI;
-       dws->prev_chip = NULL;
        dws->dma_inited = 0;
        dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
        snprintf(dws->name, sizeof(dws->name), "dw_spi%d", dws->bus_num);
 
        ret = devm_request_irq(dev, dws->irq, dw_spi_irq, IRQF_SHARED,
-                       dws->name, dws);
+                       dws->name, master);
        if (ret < 0) {
                dev_err(&master->dev, "can not get IRQ\n");
                goto err_free_master;
@@ -664,7 +540,9 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
        master->num_chipselect = dws->num_cs;
        master->setup = dw_spi_setup;
        master->cleanup = dw_spi_cleanup;
-       master->transfer_one_message = dw_spi_transfer_one_message;
+       master->set_cs = dw_spi_set_cs;
+       master->transfer_one = dw_spi_transfer_one;
+       master->handle_err = dw_spi_handle_err;
        master->max_speed_hz = dws->max_freq;
        master->dev.of_node = dev->of_node;
 
@@ -676,11 +554,11 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
                if (ret) {
                        dev_warn(dev, "DMA init failed\n");
                        dws->dma_inited = 0;
+               } else {
+                       master->can_dma = dws->dma_ops->can_dma;
                }
        }
 
-       tasklet_init(&dws->pump_transfers, pump_transfers, (unsigned long)dws);
-
        spi_master_set_devdata(master, dws);
        ret = devm_spi_register_master(dev, master);
        if (ret) {
index 3d32be68c14210c93e0ae3a6c87e65c7e5c38759..6c91391c1a4f8f07b40cb546de3eb169c44670f3 100644 (file)
@@ -91,12 +91,15 @@ struct dw_spi;
 struct dw_spi_dma_ops {
        int (*dma_init)(struct dw_spi *dws);
        void (*dma_exit)(struct dw_spi *dws);
-       int (*dma_transfer)(struct dw_spi *dws, int cs_change);
+       int (*dma_setup)(struct dw_spi *dws, struct spi_transfer *xfer);
+       bool (*can_dma)(struct spi_master *master, struct spi_device *spi,
+                       struct spi_transfer *xfer);
+       int (*dma_transfer)(struct dw_spi *dws, struct spi_transfer *xfer);
+       void (*dma_stop)(struct dw_spi *dws);
 };
 
 struct dw_spi {
        struct spi_master       *master;
-       struct spi_device       *cur_dev;
        enum dw_ssi_type        type;
        char                    name[16];
 
@@ -109,41 +112,26 @@ struct dw_spi {
        u16                     bus_num;
        u16                     num_cs;         /* supported slave numbers */
 
-       /* Message Transfer pump */
-       struct tasklet_struct   pump_transfers;
-
        /* Current message transfer state info */
-       struct spi_message      *cur_msg;
-       struct spi_transfer     *cur_transfer;
-       struct chip_data        *cur_chip;
-       struct chip_data        *prev_chip;
        size_t                  len;
        void                    *tx;
        void                    *tx_end;
        void                    *rx;
        void                    *rx_end;
        int                     dma_mapped;
-       dma_addr_t              rx_dma;
-       dma_addr_t              tx_dma;
-       size_t                  rx_map_len;
-       size_t                  tx_map_len;
        u8                      n_bytes;        /* current is a 1/2 bytes op */
-       u8                      max_bits_per_word;      /* maxim is 16b */
        u32                     dma_width;
        irqreturn_t             (*transfer_handler)(struct dw_spi *dws);
-       void                    (*cs_control)(u32 command);
 
-       /* Dma info */
+       /* DMA info */
        int                     dma_inited;
        struct dma_chan         *txchan;
-       struct scatterlist      tx_sgl;
        struct dma_chan         *rxchan;
-       struct scatterlist      rx_sgl;
        unsigned long           dma_chan_busy;
-       struct device           *dma_dev;
        dma_addr_t              dma_addr; /* phy address of the Data register */
        struct dw_spi_dma_ops   *dma_ops;
-       void                    *dma_priv; /* platform relate info */
+       void                    *dma_tx;
+       void                    *dma_rx;
 
        /* Bus interface info */
        void                    *priv;
@@ -162,16 +150,6 @@ static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val)
        __raw_writel(val, dws->regs + offset);
 }
 
-static inline u16 dw_readw(struct dw_spi *dws, u32 offset)
-{
-       return __raw_readw(dws->regs + offset);
-}
-
-static inline void dw_writew(struct dw_spi *dws, u32 offset, u16 val)
-{
-       __raw_writew(val, dws->regs + offset);
-}
-
 static inline void spi_enable_chip(struct dw_spi *dws, int enable)
 {
        dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0));
@@ -182,22 +160,6 @@ static inline void spi_set_clk(struct dw_spi *dws, u16 div)
        dw_writel(dws, DW_SPI_BAUDR, div);
 }
 
-static inline void spi_chip_sel(struct dw_spi *dws, struct spi_device *spi,
-               int active)
-{
-       u16 cs = spi->chip_select;
-       int gpio_val = active ? (spi->mode & SPI_CS_HIGH) :
-               !(spi->mode & SPI_CS_HIGH);
-
-       if (dws->cs_control)
-               dws->cs_control(active);
-       if (gpio_is_valid(spi->cs_gpio))
-               gpio_set_value(spi->cs_gpio, gpio_val);
-
-       if (active)
-               dw_writel(dws, DW_SPI_SER, 1 << cs);
-}
-
 /* Disable IRQ bits */
 static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
 {
@@ -216,16 +178,27 @@ static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
        dw_writel(dws, DW_SPI_IMR, new_mask);
 }
 
+/*
+ * This does disable the SPI controller, interrupts, and re-enable the
+ * controller back. Transmit and receive FIFO buffers are cleared when the
+ * device is disabled.
+ */
+static inline void spi_reset_chip(struct dw_spi *dws)
+{
+       spi_enable_chip(dws, 0);
+       spi_mask_intr(dws, 0xff);
+       spi_enable_chip(dws, 1);
+}
+
 /*
  * Each SPI slave device to work with dw_api controller should
- * has such a structure claiming its working mode (PIO/DMA etc),
+ * has such a structure claiming its working mode (poll or PIO/DMA),
  * which can be save in the "controller_data" member of the
  * struct spi_device.
  */
 struct dw_spi_chip {
        u8 poll_mode;   /* 1 for controller polling mode */
        u8 type;        /* SPI/SSP/MicroWire */
-       u8 enable_dma;
        void (*cs_control)(u32 command);
 };
 
@@ -233,7 +206,6 @@ extern int dw_spi_add_host(struct device *dev, struct dw_spi *dws);
 extern void dw_spi_remove_host(struct dw_spi *dws);
 extern int dw_spi_suspend_host(struct dw_spi *dws);
 extern int dw_spi_resume_host(struct dw_spi *dws);
-extern void dw_spi_xfer_done(struct dw_spi *dws);
 
 /* platform related setup */
 extern int dw_spi_mid_init(struct dw_spi *dws); /* Intel MID platforms */
index d1a39249704a7e3a16bcd861bc7f16f5a9ed02dd..5fe54cda309f5e7523c39f44245e6374c134fb08 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/math64.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -29,6 +30,7 @@
 #include <linux/sched.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
+#include <linux/time.h>
 
 #define DRIVER_NAME "fsl-dspi"
 
@@ -51,7 +53,7 @@
 #define SPI_CTAR_CPOL(x)       ((x) << 26)
 #define SPI_CTAR_CPHA(x)       ((x) << 25)
 #define SPI_CTAR_LSBFE(x)      ((x) << 24)
-#define SPI_CTAR_PCSSCR(x)     (((x) & 0x00000003) << 22)
+#define SPI_CTAR_PCSSCK(x)     (((x) & 0x00000003) << 22)
 #define SPI_CTAR_PASC(x)       (((x) & 0x00000003) << 20)
 #define SPI_CTAR_PDT(x)        (((x) & 0x00000003) << 18)
 #define SPI_CTAR_PBR(x)        (((x) & 0x00000003) << 16)
@@ -59,6 +61,7 @@
 #define SPI_CTAR_ASC(x)        (((x) & 0x0000000f) << 8)
 #define SPI_CTAR_DT(x)         (((x) & 0x0000000f) << 4)
 #define SPI_CTAR_BR(x)         ((x) & 0x0000000f)
+#define SPI_CTAR_SCALE_BITS    0xf
 
 #define SPI_CTAR0_SLAVE        0x0c
 
@@ -148,23 +151,66 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
                16,     32,     64,     128,
                256,    512,    1024,   2048,
                4096,   8192,   16384,  32768 };
-       int temp, i = 0, j = 0;
+       int scale_needed, scale, minscale = INT_MAX;
+       int i, j;
+
+       scale_needed = clkrate / speed_hz;
+       if (clkrate % speed_hz)
+               scale_needed++;
+
+       for (i = 0; i < ARRAY_SIZE(brs); i++)
+               for (j = 0; j < ARRAY_SIZE(pbr_tbl); j++) {
+                       scale = brs[i] * pbr_tbl[j];
+                       if (scale >= scale_needed) {
+                               if (scale < minscale) {
+                                       minscale = scale;
+                                       *br = i;
+                                       *pbr = j;
+                               }
+                               break;
+                       }
+               }
 
-       temp = clkrate / 2 / speed_hz;
+       if (minscale == INT_MAX) {
+               pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld, we use the max prescaler value.\n",
+                       speed_hz, clkrate);
+               *pbr = ARRAY_SIZE(pbr_tbl) - 1;
+               *br =  ARRAY_SIZE(brs) - 1;
+       }
+}
 
-       for (i = 0; i < ARRAY_SIZE(pbr_tbl); i++)
-               for (j = 0; j < ARRAY_SIZE(brs); j++) {
-                       if (pbr_tbl[i] * brs[j] >= temp) {
-                               *pbr = i;
-                               *br = j;
-                               return;
+static void ns_delay_scale(char *psc, char *sc, int delay_ns,
+               unsigned long clkrate)
+{
+       int pscale_tbl[4] = {1, 3, 5, 7};
+       int scale_needed, scale, minscale = INT_MAX;
+       int i, j;
+       u32 remainder;
+
+       scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC,
+                       &remainder);
+       if (remainder)
+               scale_needed++;
+
+       for (i = 0; i < ARRAY_SIZE(pscale_tbl); i++)
+               for (j = 0; j <= SPI_CTAR_SCALE_BITS; j++) {
+                       scale = pscale_tbl[i] * (2 << j);
+                       if (scale >= scale_needed) {
+                               if (scale < minscale) {
+                                       minscale = scale;
+                                       *psc = i;
+                                       *sc = j;
+                               }
+                               break;
                        }
                }
 
-       pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld\
-               ,we use the max prescaler value.\n", speed_hz, clkrate);
-       *pbr = ARRAY_SIZE(pbr_tbl) - 1;
-       *br =  ARRAY_SIZE(brs) - 1;
+       if (minscale == INT_MAX) {
+               pr_warn("Cannot find correct scale values for %dns delay at clkrate %ld, using max prescaler value",
+                       delay_ns, clkrate);
+               *psc = ARRAY_SIZE(pscale_tbl) - 1;
+               *sc = SPI_CTAR_SCALE_BITS;
+       }
 }
 
 static int dspi_transfer_write(struct fsl_dspi *dspi)
@@ -345,7 +391,10 @@ static int dspi_setup(struct spi_device *spi)
 {
        struct chip_data *chip;
        struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
-       unsigned char br = 0, pbr = 0, fmsz = 0;
+       u32 cs_sck_delay = 0, sck_cs_delay = 0;
+       unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0;
+       unsigned char pasc = 0, asc = 0, fmsz = 0;
+       unsigned long clkrate;
 
        if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) {
                fmsz = spi->bits_per_word - 1;
@@ -362,18 +411,34 @@ static int dspi_setup(struct spi_device *spi)
                        return -ENOMEM;
        }
 
+       of_property_read_u32(spi->dev.of_node, "fsl,spi-cs-sck-delay",
+                       &cs_sck_delay);
+
+       of_property_read_u32(spi->dev.of_node, "fsl,spi-sck-cs-delay",
+                       &sck_cs_delay);
+
        chip->mcr_val = SPI_MCR_MASTER | SPI_MCR_PCSIS |
                SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
 
        chip->void_write_data = 0;
 
-       hz_to_spi_baud(&pbr, &br,
-                       spi->max_speed_hz, clk_get_rate(dspi->clk));
+       clkrate = clk_get_rate(dspi->clk);
+       hz_to_spi_baud(&pbr, &br, spi->max_speed_hz, clkrate);
+
+       /* Set PCS to SCK delay scale values */
+       ns_delay_scale(&pcssck, &cssck, cs_sck_delay, clkrate);
+
+       /* Set After SCK delay scale values */
+       ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate);
 
        chip->ctar_val =  SPI_CTAR_FMSZ(fmsz)
                | SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
                | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
                | SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
+               | SPI_CTAR_PCSSCK(pcssck)
+               | SPI_CTAR_CSSCK(cssck)
+               | SPI_CTAR_PASC(pasc)
+               | SPI_CTAR_ASC(asc)
                | SPI_CTAR_PBR(pbr)
                | SPI_CTAR_BR(br);
 
index e649bc7d4c086bb789d2dc1803c621bebdc29a19..788e2b176a4f7707051bcc325538e7d2a6d599f4 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/dmaengine.h>
+#include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -122,36 +123,31 @@ static inline void spfi_start(struct img_spfi *spfi)
        spfi_writel(spfi, val, SPFI_CONTROL);
 }
 
-static inline void spfi_stop(struct img_spfi *spfi)
-{
-       u32 val;
-
-       val = spfi_readl(spfi, SPFI_CONTROL);
-       val &= ~SPFI_CONTROL_SPFI_EN;
-       spfi_writel(spfi, val, SPFI_CONTROL);
-}
-
 static inline void spfi_reset(struct img_spfi *spfi)
 {
        spfi_writel(spfi, SPFI_CONTROL_SOFT_RESET, SPFI_CONTROL);
-       udelay(1);
        spfi_writel(spfi, 0, SPFI_CONTROL);
 }
 
-static void spfi_flush_tx_fifo(struct img_spfi *spfi)
+static int spfi_wait_all_done(struct img_spfi *spfi)
 {
-       unsigned long timeout = jiffies + msecs_to_jiffies(10);
+       unsigned long timeout = jiffies + msecs_to_jiffies(50);
 
-       spfi_writel(spfi, SPFI_INTERRUPT_SDE, SPFI_INTERRUPT_CLEAR);
        while (time_before(jiffies, timeout)) {
-               if (spfi_readl(spfi, SPFI_INTERRUPT_STATUS) &
-                   SPFI_INTERRUPT_SDE)
-                       return;
+               u32 status = spfi_readl(spfi, SPFI_INTERRUPT_STATUS);
+
+               if (status & SPFI_INTERRUPT_ALLDONETRIG) {
+                       spfi_writel(spfi, SPFI_INTERRUPT_ALLDONETRIG,
+                                   SPFI_INTERRUPT_CLEAR);
+                       return 0;
+               }
                cpu_relax();
        }
 
-       dev_err(spfi->dev, "Timed out waiting for FIFO to drain\n");
+       dev_err(spfi->dev, "Timed out waiting for transaction to complete\n");
        spfi_reset(spfi);
+
+       return -ETIMEDOUT;
 }
 
 static unsigned int spfi_pio_write32(struct img_spfi *spfi, const u32 *buf,
@@ -237,6 +233,7 @@ static int img_spfi_start_pio(struct spi_master *master,
        const void *tx_buf = xfer->tx_buf;
        void *rx_buf = xfer->rx_buf;
        unsigned long timeout;
+       int ret;
 
        if (tx_buf)
                tx_bytes = xfer->len;
@@ -269,16 +266,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");
-               spfi_reset(spfi);
                return -ETIMEDOUT;
        }
 
-       if (tx_buf)
-               spfi_flush_tx_fifo(spfi);
-       spfi_stop(spfi);
-
        return 0;
 }
 
@@ -287,14 +283,12 @@ static void img_spfi_dma_rx_cb(void *data)
        struct img_spfi *spfi = data;
        unsigned long flags;
 
-       spin_lock_irqsave(&spfi->lock, flags);
+       spfi_wait_all_done(spfi);
 
+       spin_lock_irqsave(&spfi->lock, flags);
        spfi->rx_dma_busy = false;
-       if (!spfi->tx_dma_busy) {
-               spfi_stop(spfi);
+       if (!spfi->tx_dma_busy)
                spi_finalize_current_transfer(spfi->master);
-       }
-
        spin_unlock_irqrestore(&spfi->lock, flags);
 }
 
@@ -303,16 +297,12 @@ static void img_spfi_dma_tx_cb(void *data)
        struct img_spfi *spfi = data;
        unsigned long flags;
 
-       spfi_flush_tx_fifo(spfi);
+       spfi_wait_all_done(spfi);
 
        spin_lock_irqsave(&spfi->lock, flags);
-
        spfi->tx_dma_busy = false;
-       if (!spfi->rx_dma_busy) {
-               spfi_stop(spfi);
+       if (!spfi->rx_dma_busy)
                spi_finalize_current_transfer(spfi->master);
-       }
-
        spin_unlock_irqrestore(&spfi->lock, flags);
 }
 
@@ -397,6 +387,75 @@ stop_dma:
        return -EIO;
 }
 
+static void img_spfi_handle_err(struct spi_master *master,
+                               struct spi_message *msg)
+{
+       struct img_spfi *spfi = spi_master_get_devdata(master);
+       unsigned long flags;
+
+       /*
+        * Stop all DMA and reset the controller if the previous transaction
+        * timed-out and never completed it's DMA.
+        */
+       spin_lock_irqsave(&spfi->lock, flags);
+       if (spfi->tx_dma_busy || spfi->rx_dma_busy) {
+               spfi->tx_dma_busy = false;
+               spfi->rx_dma_busy = false;
+
+               dmaengine_terminate_all(spfi->tx_ch);
+               dmaengine_terminate_all(spfi->rx_ch);
+       }
+       spin_unlock_irqrestore(&spfi->lock, flags);
+}
+
+static int img_spfi_prepare(struct spi_master *master, struct spi_message *msg)
+{
+       struct img_spfi *spfi = spi_master_get_devdata(master);
+       u32 val;
+
+       val = spfi_readl(spfi, SPFI_PORT_STATE);
+       if (msg->spi->mode & SPI_CPHA)
+               val |= SPFI_PORT_STATE_CK_PHASE(msg->spi->chip_select);
+       else
+               val &= ~SPFI_PORT_STATE_CK_PHASE(msg->spi->chip_select);
+       if (msg->spi->mode & SPI_CPOL)
+               val |= SPFI_PORT_STATE_CK_POL(msg->spi->chip_select);
+       else
+               val &= ~SPFI_PORT_STATE_CK_POL(msg->spi->chip_select);
+       spfi_writel(spfi, val, SPFI_PORT_STATE);
+
+       return 0;
+}
+
+static int img_spfi_unprepare(struct spi_master *master,
+                             struct spi_message *msg)
+{
+       struct img_spfi *spfi = spi_master_get_devdata(master);
+
+       spfi_reset(spfi);
+
+       return 0;
+}
+
+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",
+                               spi->cs_gpio);
+
+       return ret;
+}
+
+static void img_spfi_cleanup(struct spi_device *spi)
+{
+       gpio_free(spi->cs_gpio);
+}
+
 static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
                            struct spi_transfer *xfer)
 {
@@ -405,10 +464,10 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
 
        /*
         * output = spfi_clk * (BITCLK / 512), where BITCLK must be a
-        * power of 2 up to 256 (where 255 == 256 since BITCLK is 8 bits)
+        * power of 2 up to 128
         */
-       div = DIV_ROUND_UP(master->max_speed_hz, xfer->speed_hz);
-       div = clamp(512 / (1 << get_count_order(div)), 1, 255);
+       div = DIV_ROUND_UP(clk_get_rate(spfi->spfi_clk), xfer->speed_hz);
+       div = clamp(512 / (1 << get_count_order(div)), 1, 128);
 
        val = spfi_readl(spfi, SPFI_DEVICE_PARAMETER(spi->chip_select));
        val &= ~(SPFI_DEVICE_PARAMETER_BITCLK_MASK <<
@@ -416,6 +475,9 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
        val |= div << SPFI_DEVICE_PARAMETER_BITCLK_SHIFT;
        spfi_writel(spfi, val, SPFI_DEVICE_PARAMETER(spi->chip_select));
 
+       spfi_writel(spfi, xfer->len << SPFI_TRANSACTION_TSIZE_SHIFT,
+                   SPFI_TRANSACTION);
+
        val = spfi_readl(spfi, SPFI_CONTROL);
        val &= ~(SPFI_CONTROL_SEND_DMA | SPFI_CONTROL_GET_DMA);
        if (xfer->tx_buf)
@@ -429,25 +491,7 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
        else if (xfer->tx_nbits == SPI_NBITS_QUAD &&
                 xfer->rx_nbits == SPI_NBITS_QUAD)
                val |= SPFI_CONTROL_TMODE_QUAD << SPFI_CONTROL_TMODE_SHIFT;
-       val &= ~SPFI_CONTROL_CONTINUE;
-       if (!xfer->cs_change && !list_is_last(&xfer->transfer_list,
-                                             &master->cur_msg->transfers))
-               val |= SPFI_CONTROL_CONTINUE;
        spfi_writel(spfi, val, SPFI_CONTROL);
-
-       val = spfi_readl(spfi, SPFI_PORT_STATE);
-       if (spi->mode & SPI_CPHA)
-               val |= SPFI_PORT_STATE_CK_PHASE(spi->chip_select);
-       else
-               val &= ~SPFI_PORT_STATE_CK_PHASE(spi->chip_select);
-       if (spi->mode & SPI_CPOL)
-               val |= SPFI_PORT_STATE_CK_POL(spi->chip_select);
-       else
-               val &= ~SPFI_PORT_STATE_CK_POL(spi->chip_select);
-       spfi_writel(spfi, val, SPFI_PORT_STATE);
-
-       spfi_writel(spfi, xfer->len << SPFI_TRANSACTION_TSIZE_SHIFT,
-                   SPFI_TRANSACTION);
 }
 
 static int img_spfi_transfer_one(struct spi_master *master,
@@ -455,8 +499,6 @@ static int img_spfi_transfer_one(struct spi_master *master,
                                 struct spi_transfer *xfer)
 {
        struct img_spfi *spfi = spi_master_get_devdata(spi->master);
-       bool dma_reset = false;
-       unsigned long flags;
        int ret;
 
        if (xfer->len > SPFI_TRANSACTION_TSIZE_MASK) {
@@ -466,23 +508,6 @@ static int img_spfi_transfer_one(struct spi_master *master,
                return -EINVAL;
        }
 
-       /*
-        * Stop all DMA and reset the controller if the previous transaction
-        * timed-out and never completed it's DMA.
-        */
-       spin_lock_irqsave(&spfi->lock, flags);
-       if (spfi->tx_dma_busy || spfi->rx_dma_busy) {
-               dev_err(spfi->dev, "SPI DMA still busy\n");
-               dma_reset = true;
-       }
-       spin_unlock_irqrestore(&spfi->lock, flags);
-
-       if (dma_reset) {
-               dmaengine_terminate_all(spfi->tx_ch);
-               dmaengine_terminate_all(spfi->rx_ch);
-               spfi_reset(spfi);
-       }
-
        img_spfi_config(master, spi, xfer);
        if (master->can_dma && master->can_dma(master, spi, xfer))
                ret = img_spfi_start_dma(master, spi, xfer);
@@ -492,17 +517,6 @@ static int img_spfi_transfer_one(struct spi_master *master,
        return ret;
 }
 
-static void img_spfi_set_cs(struct spi_device *spi, bool enable)
-{
-       struct img_spfi *spfi = spi_master_get_devdata(spi->master);
-       u32 val;
-
-       val = spfi_readl(spfi, SPFI_PORT_STATE);
-       val &= ~(SPFI_PORT_STATE_DEV_SEL_MASK << SPFI_PORT_STATE_DEV_SEL_SHIFT);
-       val |= spi->chip_select << SPFI_PORT_STATE_DEV_SEL_SHIFT;
-       spfi_writel(spfi, val, SPFI_PORT_STATE);
-}
-
 static bool img_spfi_can_dma(struct spi_master *master, struct spi_device *spi,
                             struct spi_transfer *xfer)
 {
@@ -591,14 +605,17 @@ static int img_spfi_probe(struct platform_device *pdev)
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_DUAL | SPI_RX_DUAL;
        if (of_property_read_bool(spfi->dev->of_node, "img,supports-quad-mode"))
                master->mode_bits |= SPI_TX_QUAD | SPI_RX_QUAD;
-       master->num_chipselect = 5;
        master->dev.of_node = pdev->dev.of_node;
        master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(8);
-       master->max_speed_hz = clk_get_rate(spfi->spfi_clk);
-       master->min_speed_hz = master->max_speed_hz / 512;
+       master->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4;
+       master->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512;
 
-       master->set_cs = img_spfi_set_cs;
+       master->setup = img_spfi_setup;
+       master->cleanup = img_spfi_cleanup;
        master->transfer_one = img_spfi_transfer_one;
+       master->prepare_message = img_spfi_prepare;
+       master->unprepare_message = img_spfi_unprepare;
+       master->handle_err = img_spfi_handle_err;
 
        spfi->tx_ch = dma_request_slave_channel(spfi->dev, "tx");
        spfi->rx_ch = dma_request_slave_channel(spfi->dev, "rx");
index 6fea4af51c413f27640c626ad61a2bcdca0b6bac..f08e812b29847bd3ba5f44ab1c5b02aae8437258 100644 (file)
@@ -370,8 +370,6 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
        if (spi_imx->dma_is_inited) {
                dma = readl(spi_imx->base + MX51_ECSPI_DMA);
 
-               spi_imx->tx_wml = spi_imx_get_fifosize(spi_imx) / 2;
-               spi_imx->rx_wml = spi_imx_get_fifosize(spi_imx) / 2;
                spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2;
                rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
                tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
@@ -868,6 +866,8 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
        master->max_dma_len = MAX_SDMA_BD_BYTES;
        spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX |
                                         SPI_MASTER_MUST_TX;
+       spi_imx->tx_wml = spi_imx_get_fifosize(spi_imx) / 2;
+       spi_imx->rx_wml = spi_imx_get_fifosize(spi_imx) / 2;
        spi_imx->dma_is_inited = 1;
 
        return 0;
@@ -903,7 +903,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 
        if (tx) {
                desc_tx = dmaengine_prep_slave_sg(master->dma_tx,
-                                       tx->sgl, tx->nents, DMA_TO_DEVICE,
+                                       tx->sgl, tx->nents, DMA_MEM_TO_DEV,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
                if (!desc_tx)
                        goto no_dma;
@@ -915,7 +915,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 
        if (rx) {
                desc_rx = dmaengine_prep_slave_sg(master->dma_rx,
-                                       rx->sgl, rx->nents, DMA_FROM_DEVICE,
+                                       rx->sgl, rx->nents, DMA_DEV_TO_MEM,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
                if (!desc_rx)
                        goto no_dma;
index ecae0d4e29459048679aa30aa3e30c4a1eac55d8..965d2bdcfdcc710e4c8f0374fffe4e9570b117b7 100644 (file)
@@ -588,7 +588,7 @@ static int mpc512x_psc_spi_of_remove(struct platform_device *op)
        return mpc512x_psc_spi_do_remove(&op->dev);
 }
 
-static struct of_device_id mpc512x_psc_spi_of_match[] = {
+static const struct of_device_id mpc512x_psc_spi_of_match[] = {
        { .compatible = "fsl,mpc5121-psc-spi", },
        {},
 };
index b283d537d16aaacc2b57e402b0dd6e3cd078a7e9..e99d6a93d3943c8b578fbd4a00ecba152d0881c5 100644 (file)
@@ -238,7 +238,7 @@ static int octeon_spi_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id octeon_spi_match[] = {
+static const struct of_device_id octeon_spi_match[] = {
        { .compatible = "cavium,octeon-3010-spi", },
        {},
 };
index d890d309dff9b553364654ae343f322c65d1c51a..35b332dacb13a1e7d91c868dab37ac8a5abc4dac 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
@@ -294,16 +295,6 @@ static int omap1_spi100k_setup(struct spi_device *spi)
        return ret;
 }
 
-static int omap1_spi100k_prepare_hardware(struct spi_master *master)
-{
-       struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
-
-       clk_prepare_enable(spi100k->ick);
-       clk_prepare_enable(spi100k->fck);
-
-       return 0;
-}
-
 static int omap1_spi100k_transfer_one_message(struct spi_master *master,
                                              struct spi_message *m)
 {
@@ -372,16 +363,6 @@ static int omap1_spi100k_transfer_one_message(struct spi_master *master,
        return status;
 }
 
-static int omap1_spi100k_unprepare_hardware(struct spi_master *master)
-{
-       struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
-
-       clk_disable_unprepare(spi100k->ick);
-       clk_disable_unprepare(spi100k->fck);
-
-       return 0;
-}
-
 static int omap1_spi100k_probe(struct platform_device *pdev)
 {
        struct spi_master       *master;
@@ -402,14 +383,12 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
 
        master->setup = omap1_spi100k_setup;
        master->transfer_one_message = omap1_spi100k_transfer_one_message;
-       master->prepare_transfer_hardware = omap1_spi100k_prepare_hardware;
-       master->unprepare_transfer_hardware = omap1_spi100k_unprepare_hardware;
-       master->cleanup = NULL;
        master->num_chipselect = 2;
        master->mode_bits = MODEBITS;
        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
        master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16);
        master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ;
+       master->auto_runtime_pm = true;
 
        spi100k = spi_master_get_devdata(master);
 
@@ -434,22 +413,96 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
                goto err;
        }
 
+       status = clk_prepare_enable(spi100k->ick);
+       if (status != 0) {
+               dev_err(&pdev->dev, "failed to enable ick: %d\n", status);
+               goto err;
+       }
+
+       status = clk_prepare_enable(spi100k->fck);
+       if (status != 0) {
+               dev_err(&pdev->dev, "failed to enable fck: %d\n", status);
+               goto err_ick;
+       }
+
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_set_active(&pdev->dev);
+
        status = devm_spi_register_master(&pdev->dev, master);
        if (status < 0)
-               goto err;
+               goto err_fck;
 
        return status;
 
+err_fck:
+       clk_disable_unprepare(spi100k->fck);
+err_ick:
+       clk_disable_unprepare(spi100k->ick);
 err:
        spi_master_put(master);
        return status;
 }
 
+static int omap1_spi100k_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+       struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
+
+       pm_runtime_disable(&pdev->dev);
+
+       clk_disable_unprepare(spi100k->fck);
+       clk_disable_unprepare(spi100k->ick);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int omap1_spi100k_runtime_suspend(struct device *dev)
+{
+       struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
+       struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
+
+       clk_disable_unprepare(spi100k->ick);
+       clk_disable_unprepare(spi100k->fck);
+
+       return 0;
+}
+
+static int omap1_spi100k_runtime_resume(struct device *dev)
+{
+       struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
+       struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
+       int ret;
+
+       ret = clk_prepare_enable(spi100k->ick);
+       if (ret != 0) {
+               dev_err(dev, "Failed to enable ick: %d\n", ret);
+               return ret;
+       }
+
+       ret = clk_prepare_enable(spi100k->fck);
+       if (ret != 0) {
+               dev_err(dev, "Failed to enable fck: %d\n", ret);
+               clk_disable_unprepare(spi100k->ick);
+               return ret;
+       }
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops omap1_spi100k_pm = {
+       SET_RUNTIME_PM_OPS(omap1_spi100k_runtime_suspend,
+                          omap1_spi100k_runtime_resume, NULL)
+};
+
 static struct platform_driver omap1_spi100k_driver = {
        .driver = {
                .name           = "omap1_spi100k",
+               .pm             = &omap1_spi100k_pm,
        },
        .probe          = omap1_spi100k_probe,
+       .remove         = omap1_spi100k_remove,
 };
 
 module_platform_driver(omap1_spi100k_driver);
index 3c0844457c075d0c5f3ed98fce96dd7951888f05..55576db315497379d73d6f2513b2bbfadb32d2d0 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/module.h>
 #include <linux/io.h>
 
-#include <asm/irq.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
index ee513a85296b19a3c57aad4daef4ec42ee3d90b1..94af80676684e4708d373e1551b8a6c46ea118fa 100644 (file)
  */
 #define DEFAULT_SSP_REG_IMSC  0x0UL
 #define DISABLE_ALL_INTERRUPTS DEFAULT_SSP_REG_IMSC
-#define ENABLE_ALL_INTERRUPTS (~DEFAULT_SSP_REG_IMSC)
+#define ENABLE_ALL_INTERRUPTS ( \
+       SSP_IMSC_MASK_RORIM | \
+       SSP_IMSC_MASK_RTIM | \
+       SSP_IMSC_MASK_RXIM | \
+       SSP_IMSC_MASK_TXIM \
+)
 
 #define CLEAR_ALL_INTERRUPTS  0x3
 
@@ -1251,7 +1256,6 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
        struct pl022 *pl022 = dev_id;
        struct spi_message *msg = pl022->cur_msg;
        u16 irq_status = 0;
-       u16 flag = 0;
 
        if (unlikely(!msg)) {
                dev_err(&pl022->adev->dev,
@@ -1280,9 +1284,6 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
                if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF)
                        dev_err(&pl022->adev->dev,
                                "RXFIFO is full\n");
-               if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF)
-                       dev_err(&pl022->adev->dev,
-                               "TXFIFO is full\n");
 
                /*
                 * Disable and clear interrupts, disable SSP,
@@ -1303,8 +1304,7 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
 
        readwriter(pl022);
 
-       if ((pl022->tx == pl022->tx_end) && (flag == 0)) {
-               flag = 1;
+       if (pl022->tx == pl022->tx_end) {
                /* Disable Transmit interrupt, enable receive interrupt */
                writew((readw(SSP_IMSC(pl022->virtbase)) &
                       ~SSP_IMSC_MASK_TXIM) | SSP_IMSC_MASK_RXIM,
index 6f72ad01e0410257a42bc8739f8962abfbaf3b5e..e3223ac75a7c57d55e1c56e90dfac2aea877f8d5 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
+#include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/spi/spi.h>
 #include <linux/pm_runtime.h>
 #include <linux/acpi.h>
 
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/delay.h>
-
 #include "spi-pxa2xx.h"
 
 MODULE_AUTHOR("Stephen Street");
@@ -67,54 +64,6 @@ MODULE_ALIAS("platform:pxa2xx-spi");
 #define LPSS_TX_LOTHRESH_DFLT  160
 #define LPSS_TX_HITHRESH_DFLT  224
 
-struct quark_spi_rate {
-       u32 bitrate;
-       u32 dds_clk_rate;
-       u32 clk_div;
-};
-
-/*
- * 'rate', 'dds', 'clk_div' lookup table, which is defined in
- * the Quark SPI datasheet.
- */
-static const struct quark_spi_rate quark_spi_rate_table[] = {
-/*     bitrate,        dds_clk_rate,   clk_div */
-       {50000000,      0x800000,       0},
-       {40000000,      0x666666,       0},
-       {25000000,      0x400000,       0},
-       {20000000,      0x666666,       1},
-       {16667000,      0x800000,       2},
-       {13333000,      0x666666,       2},
-       {12500000,      0x200000,       0},
-       {10000000,      0x800000,       4},
-       {8000000,       0x666666,       4},
-       {6250000,       0x400000,       3},
-       {5000000,       0x400000,       4},
-       {4000000,       0x666666,       9},
-       {3125000,       0x80000,        0},
-       {2500000,       0x400000,       9},
-       {2000000,       0x666666,       19},
-       {1563000,       0x40000,        0},
-       {1250000,       0x200000,       9},
-       {1000000,       0x400000,       24},
-       {800000,        0x666666,       49},
-       {781250,        0x20000,        0},
-       {625000,        0x200000,       19},
-       {500000,        0x400000,       49},
-       {400000,        0x666666,       99},
-       {390625,        0x10000,        0},
-       {250000,        0x400000,       99},
-       {200000,        0x666666,       199},
-       {195313,        0x8000,         0},
-       {125000,        0x100000,       49},
-       {100000,        0x200000,       124},
-       {50000,         0x100000,       124},
-       {25000,         0x80000,        124},
-       {10016,         0x20000,        77},
-       {5040,          0x20000,        154},
-       {1002,          0x8000,         194},
-};
-
 /* Offset from drv_data->lpss_base */
 #define GENERAL_REG            0x08
 #define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
@@ -701,25 +650,124 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
 }
 
 /*
- * The Quark SPI data sheet gives a table, and for the given 'rate',
- * the 'dds' and 'clk_div' can be found in the table.
+ * The Quark SPI has an additional 24 bit register (DDS_CLK_RATE) to multiply
+ * input frequency by fractions of 2^24. It also has a divider by 5.
+ *
+ * There are formulas to get baud rate value for given input frequency and
+ * divider parameters, such as DDS_CLK_RATE and SCR:
+ *
+ * Fsys = 200MHz
+ *
+ * Fssp = Fsys * DDS_CLK_RATE / 2^24                   (1)
+ * Baud rate = Fsclk = Fssp / (2 * (SCR + 1))          (2)
+ *
+ * DDS_CLK_RATE either 2^n or 2^n / 5.
+ * SCR is in range 0 .. 255
+ *
+ * Divisor = 5^i * 2^j * 2 * k
+ *       i = [0, 1]      i = 1 iff j = 0 or j > 3
+ *       j = [0, 23]     j = 0 iff i = 1
+ *       k = [1, 256]
+ * Special case: j = 0, i = 1: Divisor = 2 / 5
+ *
+ * Accordingly to the specification the recommended values for DDS_CLK_RATE
+ * are:
+ *     Case 1:         2^n, n = [0, 23]
+ *     Case 2:         2^24 * 2 / 5 (0x666666)
+ *     Case 3:         less than or equal to 2^24 / 5 / 16 (0x33333)
+ *
+ * In all cases the lowest possible value is better.
+ *
+ * The function calculates parameters for all cases and chooses the one closest
+ * to the asked baud rate.
  */
-static u32 quark_x1000_set_clk_regvals(u32 rate, u32 *dds, u32 *clk_div)
+static unsigned int quark_x1000_get_clk_div(int rate, u32 *dds)
 {
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(quark_spi_rate_table); i++) {
-               if (rate >= quark_spi_rate_table[i].bitrate) {
-                       *dds = quark_spi_rate_table[i].dds_clk_rate;
-                       *clk_div = quark_spi_rate_table[i].clk_div;
-                       return quark_spi_rate_table[i].bitrate;
+       unsigned long xtal = 200000000;
+       unsigned long fref = xtal / 2;          /* mandatory division by 2,
+                                                  see (2) */
+                                               /* case 3 */
+       unsigned long fref1 = fref / 2;         /* case 1 */
+       unsigned long fref2 = fref * 2 / 5;     /* case 2 */
+       unsigned long scale;
+       unsigned long q, q1, q2;
+       long r, r1, r2;
+       u32 mul;
+
+       /* Case 1 */
+
+       /* Set initial value for DDS_CLK_RATE */
+       mul = (1 << 24) >> 1;
+
+       /* Calculate initial quot */
+       q1 = DIV_ROUND_CLOSEST(fref1, rate);
+
+       /* Scale q1 if it's too big */
+       if (q1 > 256) {
+               /* Scale q1 to range [1, 512] */
+               scale = fls_long(q1 - 1);
+               if (scale > 9) {
+                       q1 >>= scale - 9;
+                       mul >>= scale - 9;
                }
+
+               /* Round the result if we have a remainder */
+               q1 += q1 & 1;
        }
 
-       *dds = quark_spi_rate_table[i-1].dds_clk_rate;
-       *clk_div = quark_spi_rate_table[i-1].clk_div;
+       /* Decrease DDS_CLK_RATE as much as we can without loss in precision */
+       scale = __ffs(q1);
+       q1 >>= scale;
+       mul >>= scale;
+
+       /* Get the remainder */
+       r1 = abs(fref1 / (1 << (24 - fls_long(mul))) / q1 - rate);
+
+       /* Case 2 */
+
+       q2 = DIV_ROUND_CLOSEST(fref2, rate);
+       r2 = abs(fref2 / q2 - rate);
 
-       return quark_spi_rate_table[i-1].bitrate;
+       /*
+        * Choose the best between two: less remainder we have the better. We
+        * can't go case 2 if q2 is greater than 256 since SCR register can
+        * hold only values 0 .. 255.
+        */
+       if (r2 >= r1 || q2 > 256) {
+               /* case 1 is better */
+               r = r1;
+               q = q1;
+       } else {
+               /* case 2 is better */
+               r = r2;
+               q = q2;
+               mul = (1 << 24) * 2 / 5;
+       }
+
+       /* Check case 3 only If the divisor is big enough */
+       if (fref / rate >= 80) {
+               u64 fssp;
+               u32 m;
+
+               /* Calculate initial quot */
+               q1 = DIV_ROUND_CLOSEST(fref, rate);
+               m = (1 << 24) / q1;
+
+               /* Get the remainder */
+               fssp = (u64)fref * m;
+               do_div(fssp, 1 << 24);
+               r1 = abs(fssp - rate);
+
+               /* Choose this one if it suits better */
+               if (r1 < r) {
+                       /* case 3 is better */
+                       q = 1;
+                       mul = m;
+               }
+       }
+
+       *dds = mul;
+       return q - 1;
 }
 
 static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
@@ -730,23 +778,25 @@ static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
        rate = min_t(int, ssp_clk, rate);
 
        if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
-               return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
+               return (ssp_clk / (2 * rate) - 1) & 0xff;
        else
-               return ((ssp_clk / rate - 1) & 0xfff) << 8;
+               return (ssp_clk / rate - 1) & 0xfff;
 }
 
 static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data,
                                           struct chip_data *chip, int rate)
 {
-       u32 clk_div;
+       unsigned int clk_div;
 
        switch (drv_data->ssp_type) {
        case QUARK_X1000_SSP:
-               quark_x1000_set_clk_regvals(rate, &chip->dds_rate, &clk_div);
-               return clk_div << 8;
+               clk_div = quark_x1000_get_clk_div(rate, &chip->dds_rate);
+               break;
        default:
-               return ssp_get_clk_div(drv_data, rate);
+               clk_div = ssp_get_clk_div(drv_data, rate);
+               break;
        }
+       return clk_div << 8;
 }
 
 static void pump_transfers(unsigned long data)
index 2b2c359f5a501da32a38af38cfe0c0956b0e23c9..810a7fae347988a7d9dc1101586234b8ef8efc77 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/spi/spi.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
 
 #define QUP_CONFIG                     0x0000
 #define QUP_STATE                      0x0004
 
 #define SPI_NUM_CHIPSELECTS            4
 
+#define SPI_MAX_DMA_XFER               (SZ_64K - 64)
+
 /* high speed mode is when bus rate is greater then 26MHz */
 #define SPI_HS_MIN_RATE                        26000000
 #define SPI_MAX_RATE                   50000000
@@ -140,9 +144,14 @@ struct spi_qup {
        struct completion       done;
        int                     error;
        int                     w_size; /* bytes per SPI word */
+       int                     n_words;
        int                     tx_bytes;
        int                     rx_bytes;
        int                     qup_v1;
+
+       int                     use_dma;
+       struct dma_slave_config rx_conf;
+       struct dma_slave_config tx_conf;
 };
 
 
@@ -198,7 +207,6 @@ static int spi_qup_set_state(struct spi_qup *controller, u32 state)
        return 0;
 }
 
-
 static void spi_qup_fifo_read(struct spi_qup *controller,
                            struct spi_transfer *xfer)
 {
@@ -266,6 +274,107 @@ static void spi_qup_fifo_write(struct spi_qup *controller,
        }
 }
 
+static void spi_qup_dma_done(void *data)
+{
+       struct spi_qup *qup = data;
+
+       complete(&qup->done);
+}
+
+static int spi_qup_prep_sg(struct spi_master *master, struct spi_transfer *xfer,
+                          enum dma_transfer_direction dir,
+                          dma_async_tx_callback callback)
+{
+       struct spi_qup *qup = spi_master_get_devdata(master);
+       unsigned long flags = DMA_PREP_INTERRUPT | DMA_PREP_FENCE;
+       struct dma_async_tx_descriptor *desc;
+       struct scatterlist *sgl;
+       struct dma_chan *chan;
+       dma_cookie_t cookie;
+       unsigned int nents;
+
+       if (dir == DMA_MEM_TO_DEV) {
+               chan = master->dma_tx;
+               nents = xfer->tx_sg.nents;
+               sgl = xfer->tx_sg.sgl;
+       } else {
+               chan = master->dma_rx;
+               nents = xfer->rx_sg.nents;
+               sgl = xfer->rx_sg.sgl;
+       }
+
+       desc = dmaengine_prep_slave_sg(chan, sgl, nents, dir, flags);
+       if (!desc)
+               return -EINVAL;
+
+       desc->callback = callback;
+       desc->callback_param = qup;
+
+       cookie = dmaengine_submit(desc);
+
+       return dma_submit_error(cookie);
+}
+
+static void spi_qup_dma_terminate(struct spi_master *master,
+                                 struct spi_transfer *xfer)
+{
+       if (xfer->tx_buf)
+               dmaengine_terminate_all(master->dma_tx);
+       if (xfer->rx_buf)
+               dmaengine_terminate_all(master->dma_rx);
+}
+
+static int spi_qup_do_dma(struct spi_master *master, struct spi_transfer *xfer)
+{
+       dma_async_tx_callback rx_done = NULL, tx_done = NULL;
+       int ret;
+
+       if (xfer->rx_buf)
+               rx_done = spi_qup_dma_done;
+       else if (xfer->tx_buf)
+               tx_done = spi_qup_dma_done;
+
+       if (xfer->rx_buf) {
+               ret = spi_qup_prep_sg(master, xfer, DMA_DEV_TO_MEM, rx_done);
+               if (ret)
+                       return ret;
+
+               dma_async_issue_pending(master->dma_rx);
+       }
+
+       if (xfer->tx_buf) {
+               ret = spi_qup_prep_sg(master, xfer, DMA_MEM_TO_DEV, tx_done);
+               if (ret)
+                       return ret;
+
+               dma_async_issue_pending(master->dma_tx);
+       }
+
+       return 0;
+}
+
+static int spi_qup_do_pio(struct spi_master *master, struct spi_transfer *xfer)
+{
+       struct spi_qup *qup = spi_master_get_devdata(master);
+       int ret;
+
+       ret = spi_qup_set_state(qup, QUP_STATE_RUN);
+       if (ret) {
+               dev_warn(qup->dev, "cannot set RUN state\n");
+               return ret;
+       }
+
+       ret = spi_qup_set_state(qup, QUP_STATE_PAUSE);
+       if (ret) {
+               dev_warn(qup->dev, "cannot set PAUSE state\n");
+               return ret;
+       }
+
+       spi_qup_fifo_write(qup, xfer);
+
+       return 0;
+}
+
 static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
 {
        struct spi_qup *controller = dev_id;
@@ -315,11 +424,13 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
                error = -EIO;
        }
 
-       if (opflags & QUP_OP_IN_SERVICE_FLAG)
-               spi_qup_fifo_read(controller, xfer);
+       if (!controller->use_dma) {
+               if (opflags & QUP_OP_IN_SERVICE_FLAG)
+                       spi_qup_fifo_read(controller, xfer);
 
-       if (opflags & QUP_OP_OUT_SERVICE_FLAG)
-               spi_qup_fifo_write(controller, xfer);
+               if (opflags & QUP_OP_OUT_SERVICE_FLAG)
+                       spi_qup_fifo_write(controller, xfer);
+       }
 
        spin_lock_irqsave(&controller->lock, flags);
        controller->error = error;
@@ -332,13 +443,35 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static u32
+spi_qup_get_mode(struct spi_master *master, struct spi_transfer *xfer)
+{
+       struct spi_qup *qup = spi_master_get_devdata(master);
+       u32 mode;
+
+       qup->w_size = 4;
+
+       if (xfer->bits_per_word <= 8)
+               qup->w_size = 1;
+       else if (xfer->bits_per_word <= 16)
+               qup->w_size = 2;
+
+       qup->n_words = xfer->len / qup->w_size;
+
+       if (qup->n_words <= (qup->in_fifo_sz / sizeof(u32)))
+               mode = QUP_IO_M_MODE_FIFO;
+       else
+               mode = QUP_IO_M_MODE_BLOCK;
+
+       return mode;
+}
 
 /* set clock freq ... bits per word */
 static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
 {
        struct spi_qup *controller = spi_master_get_devdata(spi->master);
        u32 config, iomode, mode, control;
-       int ret, n_words, w_size;
+       int ret, n_words;
 
        if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) {
                dev_err(controller->dev, "too big size for loopback %d > %d\n",
@@ -358,35 +491,54 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
                return -EIO;
        }
 
-       w_size = 4;
-       if (xfer->bits_per_word <= 8)
-               w_size = 1;
-       else if (xfer->bits_per_word <= 16)
-               w_size = 2;
-
-       n_words = xfer->len / w_size;
-       controller->w_size = w_size;
+       mode = spi_qup_get_mode(spi->master, xfer);
+       n_words = controller->n_words;
 
-       if (n_words <= (controller->in_fifo_sz / sizeof(u32))) {
-               mode = QUP_IO_M_MODE_FIFO;
+       if (mode == QUP_IO_M_MODE_FIFO) {
                writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT);
                writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT);
                /* must be zero for FIFO */
                writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT);
                writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
-       } else {
-               mode = QUP_IO_M_MODE_BLOCK;
+       } else if (!controller->use_dma) {
                writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT);
                writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT);
                /* must be zero for BLOCK and BAM */
                writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
                writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
+       } else {
+               mode = QUP_IO_M_MODE_BAM;
+               writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
+               writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
+
+               if (!controller->qup_v1) {
+                       void __iomem *input_cnt;
+
+                       input_cnt = controller->base + QUP_MX_INPUT_CNT;
+                       /*
+                        * for DMA transfers, both QUP_MX_INPUT_CNT and
+                        * QUP_MX_OUTPUT_CNT must be zero to all cases but one.
+                        * That case is a non-balanced transfer when there is
+                        * only a rx_buf.
+                        */
+                       if (xfer->tx_buf)
+                               writel_relaxed(0, input_cnt);
+                       else
+                               writel_relaxed(n_words, input_cnt);
+
+                       writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
+               }
        }
 
        iomode = readl_relaxed(controller->base + QUP_IO_M_MODES);
        /* Set input and output transfer mode */
        iomode &= ~(QUP_IO_M_INPUT_MODE_MASK | QUP_IO_M_OUTPUT_MODE_MASK);
-       iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN);
+
+       if (!controller->use_dma)
+               iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN);
+       else
+               iomode |= QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN;
+
        iomode |= (mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT);
        iomode |= (mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT);
 
@@ -428,11 +580,31 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
        config &= ~(QUP_CONFIG_NO_INPUT | QUP_CONFIG_NO_OUTPUT | QUP_CONFIG_N);
        config |= xfer->bits_per_word - 1;
        config |= QUP_CONFIG_SPI_MODE;
+
+       if (controller->use_dma) {
+               if (!xfer->tx_buf)
+                       config |= QUP_CONFIG_NO_OUTPUT;
+               if (!xfer->rx_buf)
+                       config |= QUP_CONFIG_NO_INPUT;
+       }
+
        writel_relaxed(config, controller->base + QUP_CONFIG);
 
        /* only write to OPERATIONAL_MASK when register is present */
-       if (!controller->qup_v1)
-               writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK);
+       if (!controller->qup_v1) {
+               u32 mask = 0;
+
+               /*
+                * mask INPUT and OUTPUT service flags to prevent IRQs on FIFO
+                * status change in BAM mode
+                */
+
+               if (mode == QUP_IO_M_MODE_BAM)
+                       mask = QUP_OP_IN_SERVICE_FLAG | QUP_OP_OUT_SERVICE_FLAG;
+
+               writel_relaxed(mask, controller->base + QUP_OPERATIONAL_MASK);
+       }
+
        return 0;
 }
 
@@ -461,17 +633,13 @@ static int spi_qup_transfer_one(struct spi_master *master,
        controller->tx_bytes = 0;
        spin_unlock_irqrestore(&controller->lock, flags);
 
-       if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
-               dev_warn(controller->dev, "cannot set RUN state\n");
-               goto exit;
-       }
+       if (controller->use_dma)
+               ret = spi_qup_do_dma(master, xfer);
+       else
+               ret = spi_qup_do_pio(master, xfer);
 
-       if (spi_qup_set_state(controller, QUP_STATE_PAUSE)) {
-               dev_warn(controller->dev, "cannot set PAUSE state\n");
+       if (ret)
                goto exit;
-       }
-
-       spi_qup_fifo_write(controller, xfer);
 
        if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
                dev_warn(controller->dev, "cannot set EXECUTE state\n");
@@ -480,6 +648,7 @@ static int spi_qup_transfer_one(struct spi_master *master,
 
        if (!wait_for_completion_timeout(&controller->done, timeout))
                ret = -ETIMEDOUT;
+
 exit:
        spi_qup_set_state(controller, QUP_STATE_RESET);
        spin_lock_irqsave(&controller->lock, flags);
@@ -487,6 +656,97 @@ exit:
        if (!ret)
                ret = controller->error;
        spin_unlock_irqrestore(&controller->lock, flags);
+
+       if (ret && controller->use_dma)
+               spi_qup_dma_terminate(master, xfer);
+
+       return ret;
+}
+
+static bool spi_qup_can_dma(struct spi_master *master, struct spi_device *spi,
+                           struct spi_transfer *xfer)
+{
+       struct spi_qup *qup = spi_master_get_devdata(master);
+       size_t dma_align = dma_get_cache_alignment();
+       u32 mode;
+
+       qup->use_dma = 0;
+
+       if (xfer->rx_buf && (xfer->len % qup->in_blk_sz ||
+           IS_ERR_OR_NULL(master->dma_rx) ||
+           !IS_ALIGNED((size_t)xfer->rx_buf, dma_align)))
+               return false;
+
+       if (xfer->tx_buf && (xfer->len % qup->out_blk_sz ||
+           IS_ERR_OR_NULL(master->dma_tx) ||
+           !IS_ALIGNED((size_t)xfer->tx_buf, dma_align)))
+               return false;
+
+       mode = spi_qup_get_mode(master, xfer);
+       if (mode == QUP_IO_M_MODE_FIFO)
+               return false;
+
+       qup->use_dma = 1;
+
+       return true;
+}
+
+static void spi_qup_release_dma(struct spi_master *master)
+{
+       if (!IS_ERR_OR_NULL(master->dma_rx))
+               dma_release_channel(master->dma_rx);
+       if (!IS_ERR_OR_NULL(master->dma_tx))
+               dma_release_channel(master->dma_tx);
+}
+
+static int spi_qup_init_dma(struct spi_master *master, resource_size_t base)
+{
+       struct spi_qup *spi = spi_master_get_devdata(master);
+       struct dma_slave_config *rx_conf = &spi->rx_conf,
+                               *tx_conf = &spi->tx_conf;
+       struct device *dev = spi->dev;
+       int ret;
+
+       /* allocate dma resources, if available */
+       master->dma_rx = dma_request_slave_channel_reason(dev, "rx");
+       if (IS_ERR(master->dma_rx))
+               return PTR_ERR(master->dma_rx);
+
+       master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
+       if (IS_ERR(master->dma_tx)) {
+               ret = PTR_ERR(master->dma_tx);
+               goto err_tx;
+       }
+
+       /* set DMA parameters */
+       rx_conf->direction = DMA_DEV_TO_MEM;
+       rx_conf->device_fc = 1;
+       rx_conf->src_addr = base + QUP_INPUT_FIFO;
+       rx_conf->src_maxburst = spi->in_blk_sz;
+
+       tx_conf->direction = DMA_MEM_TO_DEV;
+       tx_conf->device_fc = 1;
+       tx_conf->dst_addr = base + QUP_OUTPUT_FIFO;
+       tx_conf->dst_maxburst = spi->out_blk_sz;
+
+       ret = dmaengine_slave_config(master->dma_rx, rx_conf);
+       if (ret) {
+               dev_err(dev, "failed to configure RX channel\n");
+               goto err;
+       }
+
+       ret = dmaengine_slave_config(master->dma_tx, tx_conf);
+       if (ret) {
+               dev_err(dev, "failed to configure TX channel\n");
+               goto err;
+       }
+
+       return 0;
+
+err:
+       dma_release_channel(master->dma_tx);
+err_tx:
+       dma_release_channel(master->dma_rx);
        return ret;
 }
 
@@ -563,6 +823,8 @@ static int spi_qup_probe(struct platform_device *pdev)
        master->transfer_one = spi_qup_transfer_one;
        master->dev.of_node = pdev->dev.of_node;
        master->auto_runtime_pm = true;
+       master->dma_alignment = dma_get_cache_alignment();
+       master->max_dma_len = SPI_MAX_DMA_XFER;
 
        platform_set_drvdata(pdev, master);
 
@@ -574,6 +836,12 @@ static int spi_qup_probe(struct platform_device *pdev)
        controller->cclk = cclk;
        controller->irq = irq;
 
+       ret = spi_qup_init_dma(master, res->start);
+       if (ret == -EPROBE_DEFER)
+               goto error;
+       else if (!ret)
+               master->can_dma = spi_qup_can_dma;
+
        /* set v1 flag if device is version 1 */
        if (of_device_is_compatible(dev->of_node, "qcom,spi-qup-v1.1.1"))
                controller->qup_v1 = 1;
@@ -610,7 +878,7 @@ static int spi_qup_probe(struct platform_device *pdev)
        ret = spi_qup_set_state(controller, QUP_STATE_RESET);
        if (ret) {
                dev_err(dev, "cannot set RESET state\n");
-               goto error;
+               goto error_dma;
        }
 
        writel_relaxed(0, base + QUP_OPERATIONAL);
@@ -634,7 +902,7 @@ static int spi_qup_probe(struct platform_device *pdev)
        ret = devm_request_irq(dev, irq, spi_qup_qup_irq,
                               IRQF_TRIGGER_HIGH, pdev->name, controller);
        if (ret)
-               goto error;
+               goto error_dma;
 
        pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC);
        pm_runtime_use_autosuspend(dev);
@@ -649,6 +917,8 @@ static int spi_qup_probe(struct platform_device *pdev)
 
 disable_pm:
        pm_runtime_disable(&pdev->dev);
+error_dma:
+       spi_qup_release_dma(master);
 error:
        clk_disable_unprepare(cclk);
        clk_disable_unprepare(iclk);
@@ -740,6 +1010,8 @@ static int spi_qup_remove(struct platform_device *pdev)
        if (ret)
                return ret;
 
+       spi_qup_release_dma(master);
+
        clk_disable_unprepare(controller->cclk);
        clk_disable_unprepare(controller->iclk);
 
index 1a777dc261d6f5bfa2e56dc437fb7d957d2b0891..68e7efeb9a27a6751d49ad3a6583b2fe5d97a811 100644 (file)
@@ -179,6 +179,7 @@ struct rockchip_spi {
        u8 tmode;
        u8 bpw;
        u8 n_bytes;
+       u8 rsd_nsecs;
        unsigned len;
        u32 speed;
 
@@ -302,8 +303,8 @@ static int rockchip_spi_prepare_message(struct spi_master *master,
        return 0;
 }
 
-static int rockchip_spi_unprepare_message(struct spi_master *master,
-                                         struct spi_message *msg)
+static void rockchip_spi_handle_err(struct spi_master *master,
+                                   struct spi_message *msg)
 {
        unsigned long flags;
        struct rockchip_spi *rs = spi_master_get_devdata(master);
@@ -313,8 +314,8 @@ static int rockchip_spi_unprepare_message(struct spi_master *master,
        /*
         * For DMA mode, we need terminate DMA channel and flush
         * fifo for the next transfer if DMA thansfer timeout.
-        * unprepare_message() was called by core if transfer complete
-        * or timeout. Maybe it is reasonable for error handling here.
+        * handle_err() was called by core if transfer failed.
+        * Maybe it is reasonable for error handling here.
         */
        if (rs->use_dma) {
                if (rs->state & RXBUSY) {
@@ -327,6 +328,12 @@ static int rockchip_spi_unprepare_message(struct spi_master *master,
        }
 
        spin_unlock_irqrestore(&rs->lock, flags);
+}
+
+static int rockchip_spi_unprepare_message(struct spi_master *master,
+                                         struct spi_message *msg)
+{
+       struct rockchip_spi *rs = spi_master_get_devdata(master);
 
        spi_enable_chip(rs, 0);
 
@@ -493,6 +500,7 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
 {
        u32 div = 0;
        u32 dmacr = 0;
+       int rsd = 0;
 
        u32 cr0 = (CR0_BHT_8BIT << CR0_BHT_OFFSET)
                | (CR0_SSD_ONE << CR0_SSD_OFFSET);
@@ -519,9 +527,23 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
        }
 
        /* div doesn't support odd number */
-       div = max_t(u32, rs->max_freq / rs->speed, 1);
+       div = DIV_ROUND_UP(rs->max_freq, rs->speed);
        div = (div + 1) & 0xfffe;
 
+       /* Rx sample delay is expressed in parent clock cycles (max 3) */
+       rsd = DIV_ROUND_CLOSEST(rs->rsd_nsecs * (rs->max_freq >> 8),
+                               1000000000 >> 8);
+       if (!rsd && rs->rsd_nsecs) {
+               pr_warn_once("rockchip-spi: %u Hz are too slow to express %u ns delay\n",
+                            rs->max_freq, rs->rsd_nsecs);
+       } else if (rsd > 3) {
+               rsd = 3;
+               pr_warn_once("rockchip-spi: %u Hz are too fast to express %u ns delay, clamping at %u ns\n",
+                            rs->max_freq, rs->rsd_nsecs,
+                            rsd * 1000000000U / rs->max_freq);
+       }
+       cr0 |= rsd << CR0_RSD_OFFSET;
+
        writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
 
        writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
@@ -614,6 +636,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
        struct rockchip_spi *rs;
        struct spi_master *master;
        struct resource *mem;
+       u32 rsd_nsecs;
 
        master = spi_alloc_master(&pdev->dev, sizeof(struct rockchip_spi));
        if (!master)
@@ -665,6 +688,10 @@ static int rockchip_spi_probe(struct platform_device *pdev)
        rs->dev = &pdev->dev;
        rs->max_freq = clk_get_rate(rs->spiclk);
 
+       if (!of_property_read_u32(pdev->dev.of_node, "rx-sample-delay-ns",
+                                 &rsd_nsecs))
+               rs->rsd_nsecs = rsd_nsecs;
+
        rs->fifo_len = get_fifo_len(rs);
        if (!rs->fifo_len) {
                dev_err(&pdev->dev, "Failed to get fifo length\n");
@@ -688,6 +715,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
        master->prepare_message = rockchip_spi_prepare_message;
        master->unprepare_message = rockchip_spi_unprepare_message;
        master->transfer_one = rockchip_spi_transfer_one;
+       master->handle_err = rockchip_spi_handle_err;
 
        rs->dma_tx.ch = dma_request_slave_channel(rs->dev, "tx");
        if (!rs->dma_tx.ch)
index 46ce47076e63d143f10b298f386877bb960b8f56..186924aa4740e758af2075f417745487825b6163 100644 (file)
 #define SPBFCR_RXRST           0x40    /* Receive Buffer Data Reset */
 #define SPBFCR_TXTRG_MASK      0x30    /* Transmit Buffer Data Triggering Number */
 #define SPBFCR_RXTRG_MASK      0x07    /* Receive Buffer Data Triggering Number */
+/* QSPI on R-Car Gen2 */
+#define SPBFCR_TXTRG_1B                0x00    /* 31 bytes (1 byte available) */
+#define SPBFCR_TXTRG_32B       0x30    /* 0 byte (32 bytes available) */
+#define SPBFCR_RXTRG_1B                0x00    /* 1 byte (31 bytes available) */
+#define SPBFCR_RXTRG_32B       0x07    /* 32 bytes (0 byte available) */
+
+#define QSPI_BUFFER_SIZE        32u
 
 struct rspi_data {
        void __iomem *addr;
@@ -366,6 +373,52 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
        return 0;
 }
 
+static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg)
+{
+       u8 data;
+
+       data = rspi_read8(rspi, reg);
+       data &= ~mask;
+       data |= (val & mask);
+       rspi_write8(rspi, data, reg);
+}
+
+static int qspi_set_send_trigger(struct rspi_data *rspi, unsigned int len)
+{
+       unsigned int n;
+
+       n = min(len, QSPI_BUFFER_SIZE);
+
+       if (len >= QSPI_BUFFER_SIZE) {
+               /* sets triggering number to 32 bytes */
+               qspi_update(rspi, SPBFCR_TXTRG_MASK,
+                            SPBFCR_TXTRG_32B, QSPI_SPBFCR);
+       } else {
+               /* sets triggering number to 1 byte */
+               qspi_update(rspi, SPBFCR_TXTRG_MASK,
+                            SPBFCR_TXTRG_1B, QSPI_SPBFCR);
+       }
+
+       return n;
+}
+
+static void qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len)
+{
+       unsigned int n;
+
+       n = min(len, QSPI_BUFFER_SIZE);
+
+       if (len >= QSPI_BUFFER_SIZE) {
+               /* sets triggering number to 32 bytes */
+               qspi_update(rspi, SPBFCR_RXTRG_MASK,
+                            SPBFCR_RXTRG_32B, QSPI_SPBFCR);
+       } else {
+               /* sets triggering number to 1 byte */
+               qspi_update(rspi, SPBFCR_RXTRG_MASK,
+                            SPBFCR_RXTRG_1B, QSPI_SPBFCR);
+       }
+}
+
 #define set_config_register(spi, n) spi->ops->set_config_register(spi, n)
 
 static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable)
@@ -609,19 +662,29 @@ static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi,
        return __rspi_can_dma(rspi, xfer);
 }
 
-static int rspi_common_transfer(struct rspi_data *rspi,
-                               struct spi_transfer *xfer)
+static int rspi_dma_check_then_transfer(struct rspi_data *rspi,
+                                        struct spi_transfer *xfer)
 {
-       int ret;
-
        if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
                /* rx_buf can be NULL on RSPI on SH in TX-only Mode */
-               ret = rspi_dma_transfer(rspi, &xfer->tx_sg,
+               int ret = rspi_dma_transfer(rspi, &xfer->tx_sg,
                                        xfer->rx_buf ? &xfer->rx_sg : NULL);
                if (ret != -EAGAIN)
-                       return ret;
+                       return 0;
        }
 
+       return -EAGAIN;
+}
+
+static int rspi_common_transfer(struct rspi_data *rspi,
+                               struct spi_transfer *xfer)
+{
+       int ret;
+
+       ret = rspi_dma_check_then_transfer(rspi, xfer);
+       if (ret != -EAGAIN)
+               return ret;
+
        ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
        if (ret < 0)
                return ret;
@@ -661,12 +724,59 @@ static int rspi_rz_transfer_one(struct spi_master *master,
        return rspi_common_transfer(rspi, xfer);
 }
 
+static int qspi_trigger_transfer_out_int(struct rspi_data *rspi, const u8 *tx,
+                                       u8 *rx, unsigned int len)
+{
+       int i, n, ret;
+       int error;
+
+       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) {
+                               dev_err(&rspi->master->dev, "transmit timeout\n");
+                               return error;
+                       }
+                       for (i = 0; i < n; i++)
+                               rspi_write_data(rspi, *tx++);
+
+                       error = rspi_wait_for_rx_full(rspi);
+                       if (error < 0) {
+                               dev_err(&rspi->master->dev, "receive timeout\n");
+                               return error;
+                       }
+                       for (i = 0; i < n; i++)
+                               *rx++ = rspi_read_data(rspi);
+               } else {
+                       ret = rspi_pio_transfer(rspi, tx, rx, n);
+                       if (ret < 0)
+                               return ret;
+               }
+               len -= n;
+       }
+
+       return 0;
+}
+
 static int qspi_transfer_out_in(struct rspi_data *rspi,
                                struct spi_transfer *xfer)
 {
+       int ret;
+
        qspi_receive_init(rspi);
 
-       return rspi_common_transfer(rspi, xfer);
+       ret = rspi_dma_check_then_transfer(rspi, xfer);
+       if (ret != -EAGAIN)
+               return ret;
+
+       ret = qspi_trigger_transfer_out_int(rspi, xfer->tx_buf,
+                                           xfer->rx_buf, xfer->len);
+       if (ret < 0)
+               return ret;
+
+       return 0;
 }
 
 static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
index 9231c34b5a5c73bc9c32175d346cdb4e9c232cd6..b1c6731fbf2755199669fe204747330b985b4733 100644 (file)
@@ -324,7 +324,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
 
                /* Acquire DMA channels */
                sdd->rx_dma.ch = dma_request_slave_channel_compat(mask, filter,
-                                  (void *)sdd->rx_dma.dmach, dev, "rx");
+                                  (void *)(long)sdd->rx_dma.dmach, dev, "rx");
                if (!sdd->rx_dma.ch) {
                        dev_err(dev, "Failed to get RX DMA channel\n");
                        ret = -EBUSY;
@@ -333,7 +333,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
                spi->dma_rx = sdd->rx_dma.ch;
 
                sdd->tx_dma.ch = dma_request_slave_channel_compat(mask, filter,
-                                  (void *)sdd->tx_dma.dmach, dev, "tx");
+                                  (void *)(long)sdd->tx_dma.dmach, dev, "tx");
                if (!sdd->tx_dma.ch) {
                        dev_err(dev, "Failed to get TX DMA channel\n");
                        ret = -EBUSY;
index 5a56acf8a43e697f6e569e1ee768bc3a9cf6120a..36af4d48a700520bc3bdea7aaf987b1cf9dff057 100644 (file)
@@ -286,7 +286,7 @@ static int sc18is602_probe(struct i2c_client *client,
                        hw->freq = SC18IS602_CLOCK;
                break;
        }
-       master->bus_num = client->adapter->nr;
+       master->bus_num = np ? -1 : client->adapter->nr;
        master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST;
        master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->setup = sc18is602_setup;
index 2faeaa7b57a8568c4a34003a7e7f65e18e42bf57..f17c0abe299f418697774fa9351e724600442d51 100644 (file)
@@ -482,7 +482,7 @@ static const struct dev_pm_ops spi_st_pm = {
        SET_RUNTIME_PM_OPS(spi_st_runtime_suspend, spi_st_runtime_resume, NULL)
 };
 
-static struct of_device_id stm_spi_match[] = {
+static const struct of_device_id stm_spi_match[] = {
        { .compatible = "st,comms-ssc4-spi", },
        {},
 };
index 57a195041dc72e019a02b3c7c4b6f4c2a6fac59b..d5d7d2235163f9ef8c6430d99544ec7f2c791c6b 100644 (file)
@@ -16,7 +16,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/kmod.h>
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/cache.h>
@@ -129,125 +128,11 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int spi_legacy_suspend(struct device *dev, pm_message_t message)
-{
-       int                     value = 0;
-       struct spi_driver       *drv = to_spi_driver(dev->driver);
-
-       /* suspend will stop irqs and dma; no more i/o */
-       if (drv) {
-               if (drv->suspend)
-                       value = drv->suspend(to_spi_device(dev), message);
-               else
-                       dev_dbg(dev, "... can't suspend\n");
-       }
-       return value;
-}
-
-static int spi_legacy_resume(struct device *dev)
-{
-       int                     value = 0;
-       struct spi_driver       *drv = to_spi_driver(dev->driver);
-
-       /* resume may restart the i/o queue */
-       if (drv) {
-               if (drv->resume)
-                       value = drv->resume(to_spi_device(dev));
-               else
-                       dev_dbg(dev, "... can't resume\n");
-       }
-       return value;
-}
-
-static int spi_pm_suspend(struct device *dev)
-{
-       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
-       if (pm)
-               return pm_generic_suspend(dev);
-       else
-               return spi_legacy_suspend(dev, PMSG_SUSPEND);
-}
-
-static int spi_pm_resume(struct device *dev)
-{
-       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
-       if (pm)
-               return pm_generic_resume(dev);
-       else
-               return spi_legacy_resume(dev);
-}
-
-static int spi_pm_freeze(struct device *dev)
-{
-       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
-       if (pm)
-               return pm_generic_freeze(dev);
-       else
-               return spi_legacy_suspend(dev, PMSG_FREEZE);
-}
-
-static int spi_pm_thaw(struct device *dev)
-{
-       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
-       if (pm)
-               return pm_generic_thaw(dev);
-       else
-               return spi_legacy_resume(dev);
-}
-
-static int spi_pm_poweroff(struct device *dev)
-{
-       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
-       if (pm)
-               return pm_generic_poweroff(dev);
-       else
-               return spi_legacy_suspend(dev, PMSG_HIBERNATE);
-}
-
-static int spi_pm_restore(struct device *dev)
-{
-       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
-       if (pm)
-               return pm_generic_restore(dev);
-       else
-               return spi_legacy_resume(dev);
-}
-#else
-#define spi_pm_suspend NULL
-#define spi_pm_resume  NULL
-#define spi_pm_freeze  NULL
-#define spi_pm_thaw    NULL
-#define spi_pm_poweroff        NULL
-#define spi_pm_restore NULL
-#endif
-
-static const struct dev_pm_ops spi_pm = {
-       .suspend = spi_pm_suspend,
-       .resume = spi_pm_resume,
-       .freeze = spi_pm_freeze,
-       .thaw = spi_pm_thaw,
-       .poweroff = spi_pm_poweroff,
-       .restore = spi_pm_restore,
-       SET_RUNTIME_PM_OPS(
-               pm_generic_runtime_suspend,
-               pm_generic_runtime_resume,
-               NULL
-       )
-};
-
 struct bus_type spi_bus_type = {
        .name           = "spi",
        .dev_groups     = spi_dev_groups,
        .match          = spi_match_device,
        .uevent         = spi_uevent,
-       .pm             = &spi_pm,
 };
 EXPORT_SYMBOL_GPL(spi_bus_type);
 
@@ -851,6 +736,9 @@ out:
        if (msg->status == -EINPROGRESS)
                msg->status = ret;
 
+       if (msg->status && master->handle_err)
+               master->handle_err(master, msg);
+
        spi_finalize_current_message(master);
 
        return ret;
@@ -1360,7 +1248,6 @@ of_register_spi_device(struct spi_master *master, struct device_node *nc)
        spi->dev.of_node = nc;
 
        /* Register the new device */
-       request_module("%s%s", SPI_MODULE_PREFIX, spi->modalias);
        rc = spi_add_device(spi);
        if (rc) {
                dev_err(&master->dev, "spi_device register error %s\n",
@@ -1894,6 +1781,8 @@ int spi_setup(struct spi_device *spi)
        if (!spi->max_speed_hz)
                spi->max_speed_hz = spi->master->max_speed_hz;
 
+       spi_set_cs(spi, false);
+
        if (spi->master->setup)
                status = spi->master->setup(spi);
 
index 4eb7a980e67075a018a9be2dd4146927a3f38a6c..92c909eed6b504b01086e4775143128069f33261 100644 (file)
@@ -223,7 +223,7 @@ static int spidev_message(struct spidev_data *spidev,
        struct spi_transfer     *k_xfers;
        struct spi_transfer     *k_tmp;
        struct spi_ioc_transfer *u_tmp;
-       unsigned                n, total;
+       unsigned                n, total, tx_total, rx_total;
        u8                      *tx_buf, *rx_buf;
        int                     status = -EFAULT;
 
@@ -239,33 +239,52 @@ static int spidev_message(struct spidev_data *spidev,
        tx_buf = spidev->tx_buffer;
        rx_buf = spidev->rx_buffer;
        total = 0;
+       tx_total = 0;
+       rx_total = 0;
        for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
                        n;
                        n--, k_tmp++, u_tmp++) {
                k_tmp->len = u_tmp->len;
 
                total += k_tmp->len;
-               if (total > bufsiz) {
+               /* Since the function returns the total length of transfers
+                * on success, restrict the total to positive int values to
+                * avoid the return value looking like an error.  Also check
+                * each transfer length to avoid arithmetic overflow.
+                */
+               if (total > INT_MAX || k_tmp->len > INT_MAX) {
                        status = -EMSGSIZE;
                        goto done;
                }
 
                if (u_tmp->rx_buf) {
+                       /* this transfer needs space in RX bounce buffer */
+                       rx_total += k_tmp->len;
+                       if (rx_total > bufsiz) {
+                               status = -EMSGSIZE;
+                               goto done;
+                       }
                        k_tmp->rx_buf = rx_buf;
                        if (!access_ok(VERIFY_WRITE, (u8 __user *)
                                                (uintptr_t) u_tmp->rx_buf,
                                                u_tmp->len))
                                goto done;
+                       rx_buf += k_tmp->len;
                }
                if (u_tmp->tx_buf) {
+                       /* this transfer needs space in TX bounce buffer */
+                       tx_total += k_tmp->len;
+                       if (tx_total > bufsiz) {
+                               status = -EMSGSIZE;
+                               goto done;
+                       }
                        k_tmp->tx_buf = tx_buf;
                        if (copy_from_user(tx_buf, (const u8 __user *)
                                                (uintptr_t) u_tmp->tx_buf,
                                        u_tmp->len))
                                goto done;
+                       tx_buf += k_tmp->len;
                }
-               tx_buf += k_tmp->len;
-               rx_buf += k_tmp->len;
 
                k_tmp->cs_change = !!u_tmp->cs_change;
                k_tmp->tx_nbits = u_tmp->tx_nbits;
@@ -303,8 +322,8 @@ static int spidev_message(struct spidev_data *spidev,
                                status = -EFAULT;
                                goto done;
                        }
+                       rx_buf += u_tmp->len;
                }
-               rx_buf += u_tmp->len;
        }
        status = total;
 
@@ -684,6 +703,14 @@ static const struct file_operations spidev_fops = {
 
 static struct class *spidev_class;
 
+#ifdef CONFIG_OF
+static const struct of_device_id spidev_dt_ids[] = {
+       { .compatible = "rohm,dh2228fv" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, spidev_dt_ids);
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static int spidev_probe(struct spi_device *spi)
@@ -692,6 +719,17 @@ static int spidev_probe(struct spi_device *spi)
        int                     status;
        unsigned long           minor;
 
+       /*
+        * spidev should never be referenced in DT without a specific
+        * compatbile 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)) {
+               dev_err(&spi->dev, "buggy DT: spidev listed directly in DT\n");
+               WARN_ON(spi->dev.of_node &&
+                       !of_match_device(spidev_dt_ids, &spi->dev));
+       }
+
        /* Allocate driver data */
        spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);
        if (!spidev)
@@ -758,13 +796,6 @@ static int spidev_remove(struct spi_device *spi)
        return 0;
 }
 
-static const struct of_device_id spidev_dt_ids[] = {
-       { .compatible = "rohm,dh2228fv" },
-       {},
-};
-
-MODULE_DEVICE_TABLE(of, spidev_dt_ids);
-
 static struct spi_driver spidev_spi_driver = {
        .driver = {
                .name =         "spidev",
index 45baa83be7cefa74e9ba2d6814cc6bc62d9e073c..bfacf69f68f4c5044f723f6d48b16015ed2b0b5c 100644 (file)
@@ -58,6 +58,8 @@ source "drivers/staging/iio/Kconfig"
 
 source "drivers/staging/sm7xxfb/Kconfig"
 
+source "drivers/staging/sm750fb/Kconfig"
+
 source "drivers/staging/xgifb/Kconfig"
 
 source "drivers/staging/emxx_udc/Kconfig"
@@ -108,4 +110,6 @@ source "drivers/staging/fbtft/Kconfig"
 
 source "drivers/staging/i2o/Kconfig"
 
+source "drivers/staging/fsl-mc/Kconfig"
+
 endif # STAGING
index 29160790841f76ee909c325cd336b937f47faf4e..2bbd1bf04c55d5b5050ef6dca63d246db461b286 100644 (file)
@@ -23,6 +23,7 @@ obj-$(CONFIG_VT6656)          += vt6656/
 obj-$(CONFIG_VME_BUS)          += vme/
 obj-$(CONFIG_IIO)              += iio/
 obj-$(CONFIG_FB_SM7XX)         += sm7xxfb/
+obj-$(CONFIG_FB_SM7XX)         += sm750fb/
 obj-$(CONFIG_FB_XGI)           += xgifb/
 obj-$(CONFIG_USB_EMXX)         += emxx_udc/
 obj-$(CONFIG_FT1000)           += ft1000/
@@ -46,3 +47,4 @@ obj-$(CONFIG_UNISYSSPAR)      += unisys/
 obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD)  += clocking-wizard/
 obj-$(CONFIG_FB_TFT)           += fbtft/
 obj-$(CONFIG_I2O)              += i2o/
+obj-$(CONFIG_FSL_MC_BUS)       += fsl-mc/
index b8f1c491553e2619bfbbbbb9ff52318e2f8017cc..0e3d8c7add24e1955e2bd480075df0caf09b1a94 100644 (file)
@@ -566,8 +566,8 @@ int ion_phys(struct ion_client *client, struct ion_handle *handle,
        buffer = handle->buffer;
 
        if (!buffer->heap->ops->phys) {
-               pr_err("%s: ion_phys is not implemented by this heap.\n",
-                      __func__);
+               pr_err("%s: ion_phys is not implemented by this heap (name=%s, type=%d).\n",
+                       __func__, buffer->heap->name, buffer->heap->type);
                mutex_unlock(&client->lock);
                return -ENODEV;
        }
@@ -1395,7 +1395,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused)
        size_t total_size = 0;
        size_t total_orphaned_size = 0;
 
-       seq_printf(s, "%16.s %16.s %16.s\n", "client", "pid", "size");
+       seq_printf(s, "%16s %16s %16s\n", "client", "pid", "size");
        seq_puts(s, "----------------------------------------------------\n");
 
        for (n = rb_first(&dev->clients); n; n = rb_next(n)) {
@@ -1409,10 +1409,10 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused)
                        char task_comm[TASK_COMM_LEN];
 
                        get_task_comm(task_comm, client->task);
-                       seq_printf(s, "%16.s %16u %16zu\n", task_comm,
+                       seq_printf(s, "%16s %16u %16zu\n", task_comm,
                                   client->pid, size);
                } else {
-                       seq_printf(s, "%16.s %16u %16zu\n", client->name,
+                       seq_printf(s, "%16s %16u %16zu\n", client->name,
                                   client->pid, size);
                }
        }
@@ -1426,7 +1426,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused)
                        continue;
                total_size += buffer->size;
                if (!buffer->handle_count) {
-                       seq_printf(s, "%16.s %16u %16zu %d %d\n",
+                       seq_printf(s, "%16s %16u %16zu %d %d\n",
                                   buffer->task_comm, buffer->pid,
                                   buffer->size, buffer->kmap_cnt,
                                   atomic_read(&buffer->ref.refcount));
@@ -1435,11 +1435,11 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused)
        }
        mutex_unlock(&dev->buffer_lock);
        seq_puts(s, "----------------------------------------------------\n");
-       seq_printf(s, "%16.s %16zu\n", "total orphaned",
+       seq_printf(s, "%16s %16zu\n", "total orphaned",
                   total_orphaned_size);
-       seq_printf(s, "%16.s %16zu\n", "total ", total_size);
+       seq_printf(s, "%16s %16zu\n", "total ", total_size);
        if (heap->flags & ION_HEAP_FLAG_DEFER_FREE)
-               seq_printf(s, "%16.s %16zu\n", "deferred free",
+               seq_printf(s, "%16s %16zu\n", "deferred free",
                                heap->free_list_size);
        seq_puts(s, "----------------------------------------------------\n");
 
index 654acb5c8eba12f11b53bfb9ab8602aef9830440..3bc461cbbfa3d06fc9f5c2dfc292eef8a34edbd6 100644 (file)
@@ -280,3 +280,4 @@ static void __exit ion_test_exit(void)
 
 module_init(ion_test_init);
 module_exit(ion_test_exit);
+MODULE_LICENSE("GPL v2");
index 7bdb62bf6b4054068094590a861f254f76c8b5c8..f83e00c7805130e1ab6dda8d853c2b642b8a4f92 100644 (file)
@@ -114,7 +114,7 @@ void sync_timeline_signal(struct sync_timeline *obj)
        list_for_each_entry_safe(pt, next, &obj->active_list_head,
                                 active_list) {
                if (fence_is_signaled_locked(&pt->base))
-                       list_del(&pt->active_list);
+                       list_del_init(&pt->active_list);
        }
 
        spin_unlock_irqrestore(&obj->child_list_lock, flags);
index 593fcb1783b463ebe08f0cfcc55c15bb17771c74..61c6351f55ac4c2a4886645fb276ef54d74eee9f 100644 (file)
@@ -108,6 +108,7 @@ if COMEDI_ISA_DRIVERS
 
 config COMEDI_PCL711
        tristate "Advantech PCL-711/711b and ADlink ACL-8112 ISA card support"
+       select COMEDI_8254
        ---help---
          Enable support for Advantech PCL-711 and 711b, ADlink ACL-8112
 
@@ -169,6 +170,7 @@ config COMEDI_PCL730
 config COMEDI_PCL812
        tristate "Advantech PCL-812/813 and ADlink ACL-8112/8113/8113/8216"
        select COMEDI_ISADMA if ISA_DMA_API
+       select COMEDI_8254
        ---help---
          Enable support for Advantech PCL-812/PG, PCL-813/B, ADLink
          ACL-8112DG/HG/PG, ACL-8113, ACL-8216, ICP DAS A-821PGH/PGL/PGL-NDA,
@@ -180,6 +182,7 @@ config COMEDI_PCL812
 config COMEDI_PCL816
        tristate "Advantech PCL-814 and PCL-816 ISA card support"
        select COMEDI_ISADMA if ISA_DMA_API
+       select COMEDI_8254
        ---help---
          Enable support for Advantech PCL-814 and PCL-816 ISA cards
 
@@ -189,6 +192,7 @@ config COMEDI_PCL816
 config COMEDI_PCL818
        tristate "Advantech PCL-718 and PCL-818 ISA card support"
        select COMEDI_ISADMA if ISA_DMA_API
+       select COMEDI_8254
        ---help---
          Enable support for Advantech PCL-818 ISA cards
          PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818 and PCL-718
@@ -259,6 +263,7 @@ config COMEDI_DAC02
 
 config COMEDI_DAS16M1
        tristate "MeasurementComputing CIO-DAS16/M1DAS-16 ISA card support"
+       select COMEDI_8254
        select COMEDI_8255
        ---help---
          Enable support for Measurement Computing CIO-DAS16/M1 ISA cards.
@@ -282,6 +287,7 @@ config COMEDI_DAS08_ISA
 config COMEDI_DAS16
        tristate "DAS-16 compatible ISA and PC/104 card support"
        select COMEDI_ISADMA if ISA_DMA_API
+       select COMEDI_8254
        select COMEDI_8255
        ---help---
          Enable support for Keithley Metrabyte/ComputerBoards DAS16
@@ -298,6 +304,7 @@ config COMEDI_DAS16
 
 config COMEDI_DAS800
        tristate "DAS800 and compatible ISA card support"
+       select COMEDI_8254
        ---help---
          Enable support for Keithley Metrabyte DAS800 and compatible ISA cards
          Keithley Metrabyte DAS-800, DAS-801, DAS-802
@@ -310,6 +317,7 @@ config COMEDI_DAS800
 config COMEDI_DAS1800
        tristate "DAS1800 and compatible ISA card support"
        select COMEDI_ISADMA if ISA_DMA_API
+       select COMEDI_8254
        ---help---
          Enable support for DAS1800 and compatible ISA cards
          Keithley Metrabyte DAS-1701ST, DAS-1701ST-DA, DAS-1701/AO,
@@ -323,6 +331,7 @@ config COMEDI_DAS1800
 
 config COMEDI_DAS6402
        tristate "DAS6402 and compatible ISA card support"
+       select COMEDI_8254
        ---help---
          Enable support for DAS6402 and compatible ISA cards
          Computerboards, Keithley Metrabyte DAS6402 and compatibles
@@ -463,6 +472,7 @@ config COMEDI_ADQ12B
 config COMEDI_NI_AT_A2150
        tristate "NI AT-A2150 ISA card support"
        select COMEDI_ISADMA if ISA_DMA_API
+       select COMEDI_8254
        ---help---
          Enable support for National Instruments AT-A2150 cards
 
@@ -471,6 +481,7 @@ config COMEDI_NI_AT_A2150
 
 config COMEDI_NI_AT_AO
        tristate "NI AT-AO-6/10 EISA card support"
+       select COMEDI_8254
        ---help---
          Enable support for National Instruments AT-AO-6/10 cards
 
@@ -715,6 +726,7 @@ config COMEDI_ADL_PCI8164
 
 config COMEDI_ADL_PCI9111
        tristate "ADLink PCI-9111HR support"
+       select COMEDI_8254
        ---help---
          Enable support for ADlink PCI9111 cards
 
@@ -724,6 +736,7 @@ config COMEDI_ADL_PCI9111
 config COMEDI_ADL_PCI9118
        tristate "ADLink PCI-9118DG, PCI-9118HG, PCI-9118HR support"
        depends on HAS_DMA
+       select COMEDI_8254
        ---help---
          Enable support for ADlink PCI-9118DG, PCI-9118HG, PCI-9118HR cards
 
@@ -732,6 +745,7 @@ config COMEDI_ADL_PCI9118
 
 config COMEDI_ADV_PCI1710
        tristate "Advantech PCI-171x, PCI-1720 and PCI-1731 support"
+       select COMEDI_8254
        ---help---
          Enable support for Advantech PCI-1710, PCI-1710HG, PCI-1711,
          PCI-1713, PCI-1720 and PCI-1731
@@ -759,6 +773,7 @@ config COMEDI_ADV_PCI1724
 
 config COMEDI_ADV_PCI_DIO
        tristate "Advantech PCI DIO card support"
+       select COMEDI_8254
        select COMEDI_8255
        ---help---
          Enable support for Advantech PCI DIO cards
@@ -799,6 +814,7 @@ config COMEDI_AMPLC_PC263_PCI
 
 config COMEDI_AMPLC_PCI224
        tristate "Amplicon PCI224 and PCI234 support"
+       select COMEDI_8254
        ---help---
          Enable support for Amplicon PCI224 and PCI234 AO boards
 
@@ -807,6 +823,7 @@ config COMEDI_AMPLC_PCI224
 
 config COMEDI_AMPLC_PCI230
        tristate "Amplicon PCI230 and PCI260 support"
+       select COMEDI_8254
        select COMEDI_8255
        ---help---
          Enable support for Amplicon PCI230 and PCI260 Multifunction I/O
@@ -912,6 +929,7 @@ config COMEDI_CB_PCIDAS64
 
 config COMEDI_CB_PCIDAS
        tristate "MeasurementComputing PCI-DAS support"
+       select COMEDI_8254
        select COMEDI_8255
        ---help---
          Enable support for ComputerBoards/MeasurementComputing PCI-DAS with
@@ -935,6 +953,7 @@ config COMEDI_CB_PCIDDA
 
 config COMEDI_CB_PCIMDAS
        tristate "MeasurementComputing PCIM-DAS1602/16, PCIe-DAS1602/16 support"
+       select COMEDI_8254
        select COMEDI_8255
        ---help---
          Enable support for ComputerBoards/MeasurementComputing PCI Migration
@@ -954,6 +973,7 @@ config COMEDI_CB_PCIMDDA
 
 config COMEDI_ME4000
        tristate "Meilhaus ME-4000 support"
+       select COMEDI_8254
        ---help---
          Enable support for Meilhaus PCI data acquisition cards
          ME-4650, ME-4670i, ME-4680, ME-4680i and ME-4680is
@@ -1091,6 +1111,7 @@ if COMEDI_PCMCIA_DRIVERS
 
 config COMEDI_CB_DAS16_CS
        tristate "CB DAS16 series PCMCIA support"
+       select COMEDI_8254
        ---help---
          Enable support for the ComputerBoards/MeasurementComputing PCMCIA
          cards DAS16/16, PCM-DAS16D/12 and PCM-DAS16s/16
@@ -1222,6 +1243,9 @@ config COMEDI_VMK80XX
 
 endif # COMEDI_USB_DRIVERS
 
+config COMEDI_8254
+       tristate
+
 config COMEDI_8255
        tristate "Generic 8255 support"
        ---help---
@@ -1252,6 +1276,7 @@ config COMEDI_KCOMEDILIB
          called kcomedilib.
 
 config COMEDI_AMPLC_DIO200
+       select COMEDI_8254
        tristate
 
 config COMEDI_AMPLC_PC236
@@ -1260,6 +1285,7 @@ config COMEDI_AMPLC_PC236
 
 config COMEDI_DAS08
        tristate
+       select COMEDI_8254
        select COMEDI_8255
 
 config COMEDI_ISADMA
@@ -1267,6 +1293,7 @@ config COMEDI_ISADMA
 
 config COMEDI_NI_LABPC
        tristate
+       select COMEDI_8254
        select COMEDI_8255
 
 config COMEDI_NI_LABPC_ISADMA
index 727640e89c73ad53e39fcf1f720ae6e92fb3b0f0..e78ddbe5a954f9e048d7afca15cbf0171c15e8f1 100644 (file)
@@ -144,7 +144,7 @@ static void comedi_device_cleanup(struct comedi_device *dev)
 {
        struct module *driver_module = NULL;
 
-       if (dev == NULL)
+       if (!dev)
                return;
        mutex_lock(&dev->mutex);
        if (dev->attached)
@@ -260,7 +260,7 @@ comedi_read_subdevice(const struct comedi_device *dev, unsigned int minor)
 
        if (minor >= COMEDI_NUM_BOARD_MINORS) {
                s = comedi_subdevice_from_minor(dev, minor);
-               if (s == NULL || (s->subdev_flags & SDF_CMD_READ))
+               if (!s || (s->subdev_flags & SDF_CMD_READ))
                        return s;
        }
        return dev->read_subdev;
@@ -273,7 +273,7 @@ comedi_write_subdevice(const struct comedi_device *dev, unsigned int minor)
 
        if (minor >= COMEDI_NUM_BOARD_MINORS) {
                s = comedi_subdevice_from_minor(dev, minor);
-               if (s == NULL || (s->subdev_flags & SDF_CMD_WRITE))
+               if (!s || (s->subdev_flags & SDF_CMD_WRITE))
                        return s;
        }
        return dev->write_subdev;
@@ -290,9 +290,9 @@ static void comedi_file_reset(struct file *file)
        write_s = dev->write_subdev;
        if (minor >= COMEDI_NUM_BOARD_MINORS) {
                s = comedi_subdevice_from_minor(dev, minor);
-               if (s == NULL || s->subdev_flags & SDF_CMD_READ)
+               if (!s || s->subdev_flags & SDF_CMD_READ)
                        read_s = s;
-               if (s == NULL || s->subdev_flags & SDF_CMD_WRITE)
+               if (!s || s->subdev_flags & SDF_CMD_WRITE)
                        write_s = s;
        }
        cfp->last_attached = dev->attached;
@@ -601,28 +601,55 @@ static struct attribute *comedi_dev_attrs[] = {
 };
 ATTRIBUTE_GROUPS(comedi_dev);
 
-static void comedi_set_subdevice_runflags(struct comedi_subdevice *s,
-                                         unsigned mask, unsigned bits)
+static void __comedi_clear_subdevice_runflags(struct comedi_subdevice *s,
+                                             unsigned bits)
+{
+       s->runflags &= ~bits;
+}
+
+static void __comedi_set_subdevice_runflags(struct comedi_subdevice *s,
+                                           unsigned bits)
+{
+       s->runflags |= bits;
+}
+
+static void comedi_update_subdevice_runflags(struct comedi_subdevice *s,
+                                            unsigned mask, unsigned bits)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&s->spin_lock, flags);
-       s->runflags &= ~mask;
-       s->runflags |= (bits & mask);
+       __comedi_clear_subdevice_runflags(s, mask);
+       __comedi_set_subdevice_runflags(s, bits & mask);
        spin_unlock_irqrestore(&s->spin_lock, flags);
 }
 
+static unsigned __comedi_get_subdevice_runflags(struct comedi_subdevice *s)
+{
+       return s->runflags;
+}
+
 static unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s)
 {
        unsigned long flags;
        unsigned runflags;
 
        spin_lock_irqsave(&s->spin_lock, flags);
-       runflags = s->runflags;
+       runflags = __comedi_get_subdevice_runflags(s);
        spin_unlock_irqrestore(&s->spin_lock, flags);
        return runflags;
 }
 
+static bool comedi_is_runflags_running(unsigned runflags)
+{
+       return runflags & COMEDI_SRF_RUNNING;
+}
+
+static bool comedi_is_runflags_in_error(unsigned runflags)
+{
+       return runflags & COMEDI_SRF_ERROR;
+}
+
 /**
  * comedi_is_subdevice_running - check if async command running on subdevice
  * @s: comedi_subdevice struct
@@ -634,22 +661,22 @@ bool comedi_is_subdevice_running(struct comedi_subdevice *s)
 {
        unsigned runflags = comedi_get_subdevice_runflags(s);
 
-       return (runflags & COMEDI_SRF_RUNNING) ? true : false;
+       return comedi_is_runflags_running(runflags);
 }
 EXPORT_SYMBOL_GPL(comedi_is_subdevice_running);
 
-static bool comedi_is_subdevice_in_error(struct comedi_subdevice *s)
+static bool __comedi_is_subdevice_running(struct comedi_subdevice *s)
 {
-       unsigned runflags = comedi_get_subdevice_runflags(s);
+       unsigned runflags = __comedi_get_subdevice_runflags(s);
 
-       return (runflags & COMEDI_SRF_ERROR) ? true : false;
+       return comedi_is_runflags_running(runflags);
 }
 
 static bool comedi_is_subdevice_idle(struct comedi_subdevice *s)
 {
        unsigned runflags = comedi_get_subdevice_runflags(s);
 
-       return (runflags & COMEDI_SRF_BUSY_MASK) ? false : true;
+       return !(runflags & COMEDI_SRF_BUSY_MASK);
 }
 
 /**
@@ -677,14 +704,14 @@ static void do_become_nonbusy(struct comedi_device *dev,
 {
        struct comedi_async *async = s->async;
 
-       comedi_set_subdevice_runflags(s, COMEDI_SRF_RUNNING, 0);
+       comedi_update_subdevice_runflags(s, COMEDI_SRF_RUNNING, 0);
        if (async) {
                comedi_buf_reset(s);
                async->inttrig = NULL;
                kfree(async->cmd.chanlist);
                async->cmd.chanlist = NULL;
                s->busy = NULL;
-               wake_up_interruptible_all(&s->async->wait_head);
+               wake_up_interruptible_all(&async->wait_head);
        } else {
                dev_err(dev->class_dev,
                        "BUG: (?) do_become_nonbusy called with async=NULL\n");
@@ -759,7 +786,7 @@ static int do_devconfig_ioctl(struct comedi_device *dev,
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       if (arg == NULL) {
+       if (!arg) {
                if (is_device_busy(dev))
                        return -EBUSY;
                if (dev->attached) {
@@ -1678,8 +1705,8 @@ static int do_cmd_ioctl(struct comedi_device *dev,
        if (async->cmd.flags & CMDF_WAKE_EOS)
                async->cb_mask |= COMEDI_CB_EOS;
 
-       comedi_set_subdevice_runflags(s, COMEDI_SRF_BUSY_MASK,
-                                     COMEDI_SRF_RUNNING);
+       comedi_update_subdevice_runflags(s, COMEDI_SRF_BUSY_MASK,
+                                        COMEDI_SRF_RUNNING);
 
        /*
         * Set s->busy _after_ setting COMEDI_SRF_RUNNING flag to avoid
@@ -1840,7 +1867,7 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg,
        if (arg >= dev->n_subdevices)
                return -EINVAL;
        s = &dev->subdevices[arg];
-       if (s->async == NULL)
+       if (!s->async)
                return -EINVAL;
 
        if (!s->busy)
@@ -2282,13 +2309,16 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
        add_wait_queue(&async->wait_head, &wait);
        on_wait_queue = true;
        while (nbytes > 0 && !retval) {
+               unsigned runflags;
+
                set_current_state(TASK_INTERRUPTIBLE);
 
-               if (!comedi_is_subdevice_running(s)) {
+               runflags = comedi_get_subdevice_runflags(s);
+               if (!comedi_is_runflags_running(runflags)) {
                        if (count == 0) {
                                struct comedi_subdevice *new_s;
 
-                               if (comedi_is_subdevice_in_error(s))
+                               if (comedi_is_runflags_in_error(runflags))
                                        retval = -EPIPE;
                                else
                                        retval = 0;
@@ -2435,8 +2465,10 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
                        n = m;
 
                if (n == 0) {
-                       if (!comedi_is_subdevice_running(s)) {
-                               if (comedi_is_subdevice_in_error(s))
+                       unsigned runflags = comedi_get_subdevice_runflags(s);
+
+                       if (!comedi_is_runflags_running(runflags)) {
+                               if (comedi_is_runflags_in_error(runflags))
                                        retval = -EPIPE;
                                else
                                        retval = 0;
@@ -2638,39 +2670,38 @@ static const struct file_operations comedi_fops = {
 void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
 {
        struct comedi_async *async = s->async;
-       unsigned runflags = 0;
-       unsigned runflags_mask = 0;
+       unsigned int events;
+       int si_code = 0;
+       unsigned long flags;
 
-       if (!comedi_is_subdevice_running(s))
+       spin_lock_irqsave(&s->spin_lock, flags);
+
+       events = async->events;
+       async->events = 0;
+       if (!__comedi_is_subdevice_running(s)) {
+               spin_unlock_irqrestore(&s->spin_lock, flags);
                return;
+       }
 
-       if (s->async->events & COMEDI_CB_CANCEL_MASK)
-               runflags_mask |= COMEDI_SRF_RUNNING;
+       if (events & COMEDI_CB_CANCEL_MASK)
+               __comedi_clear_subdevice_runflags(s, COMEDI_SRF_RUNNING);
 
        /*
-        * Remember if an error event has occurred, so an error
-        * can be returned the next time the user does a read().
+        * Remember if an error event has occurred, so an error can be
+        * returned the next time the user does a read() or write().
         */
-       if (s->async->events & COMEDI_CB_ERROR_MASK) {
-               runflags_mask |= COMEDI_SRF_ERROR;
-               runflags |= COMEDI_SRF_ERROR;
-       }
-       if (runflags_mask) {
-               /*
-                * Sets COMEDI_SRF_ERROR and COMEDI_SRF_RUNNING together
-                * atomically.
-                */
-               comedi_set_subdevice_runflags(s, runflags_mask, runflags);
-       }
+       if (events & COMEDI_CB_ERROR_MASK)
+               __comedi_set_subdevice_runflags(s, COMEDI_SRF_ERROR);
 
-       if (async->cb_mask & s->async->events) {
+       if (async->cb_mask & events) {
                wake_up_interruptible(&async->wait_head);
-               if (s->subdev_flags & SDF_CMD_READ)
-                       kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
-               if (s->subdev_flags & SDF_CMD_WRITE)
-                       kill_fasync(&dev->async_queue, SIGIO, POLL_OUT);
+               si_code = async->cmd.flags & CMDF_WRITE ? POLL_OUT : POLL_IN;
        }
-       s->async->events = 0;
+
+       spin_unlock_irqrestore(&s->spin_lock, flags);
+
+       if (si_code)
+               kill_fasync(&dev->async_queue, SIGIO, si_code);
 }
 EXPORT_SYMBOL_GPL(comedi_event);
 
@@ -2682,7 +2713,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
        unsigned i;
 
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL)
+       if (!dev)
                return ERR_PTR(-ENOMEM);
        comedi_device_init(dev);
        comedi_set_hw_dev(dev, hardware_device);
@@ -2690,7 +2721,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
        mutex_lock(&comedi_board_minor_table_lock);
        for (i = hardware_device ? comedi_num_legacy_minors : 0;
             i < COMEDI_NUM_BOARD_MINORS; ++i) {
-               if (comedi_board_minor_table[i] == NULL) {
+               if (!comedi_board_minor_table[i]) {
                        comedi_board_minor_table[i] = dev;
                        break;
                }
@@ -2700,7 +2731,8 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
                mutex_unlock(&dev->mutex);
                comedi_device_cleanup(dev);
                comedi_dev_put(dev);
-               pr_err("ran out of minor numbers for board device files\n");
+               dev_err(hardware_device,
+                       "ran out of minor numbers for board device files\n");
                return ERR_PTR(-EBUSY);
        }
        dev->minor = i;
@@ -2746,14 +2778,15 @@ int comedi_alloc_subdevice_minor(struct comedi_subdevice *s)
 
        mutex_lock(&comedi_subdevice_minor_table_lock);
        for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i) {
-               if (comedi_subdevice_minor_table[i] == NULL) {
+               if (!comedi_subdevice_minor_table[i]) {
                        comedi_subdevice_minor_table[i] = s;
                        break;
                }
        }
        mutex_unlock(&comedi_subdevice_minor_table_lock);
        if (i == COMEDI_NUM_SUBDEVICE_MINORS) {
-               pr_err("ran out of minor numbers for subdevice files\n");
+               dev_err(dev->class_dev,
+                       "ran out of minor numbers for subdevice files\n");
                return -EBUSY;
        }
        i += COMEDI_NUM_BOARD_MINORS;
@@ -2771,7 +2804,7 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s)
 {
        unsigned int i;
 
-       if (s == NULL)
+       if (!s)
                return;
        if (s->minor < 0)
                return;
index d57817c19aea1f17ea60f8f2017154bbbe798235..3b918538847e614a700019e044fa4456a220696f 100644 (file)
@@ -1,11 +1,21 @@
 #ifndef _COMEDI_INTERNAL_H
 #define _COMEDI_INTERNAL_H
 
+#include <linux/compiler.h>
 #include <linux/types.h>
 
 /*
  * various internal comedi stuff
  */
+
+struct comedi_buf_map;
+struct comedi_devconfig;
+struct comedi_device;
+struct comedi_insn;
+struct comedi_rangeinfo;
+struct comedi_subdevice;
+struct device;
+
 int do_rangeinfo_ioctl(struct comedi_device *dev,
                       struct comedi_rangeinfo __user *arg);
 struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device);
index 6ba59c9770067d4976c6f9590be96ec734752322..027f0f4e59c15a35d3190df836b01969666739d1 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 
-#include "comedidev.h"
+#include "comedi_pci.h"
 
 /**
  * comedi_to_pci_dev() - comedi_device pointer to pci_dev pointer.
diff --git a/drivers/staging/comedi/comedi_pci.h b/drivers/staging/comedi/comedi_pci.h
new file mode 100644 (file)
index 0000000..4005cc9
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * comedi_pci.h
+ * header file for Comedi PCI drivers
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1997-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.
+ */
+
+#ifndef _COMEDI_PCI_H
+#define _COMEDI_PCI_H
+
+#include <linux/pci.h>
+
+#include "comedidev.h"
+
+/*
+ * PCI Vendor IDs not in <linux/pci_ids.h>
+ */
+#define PCI_VENDOR_ID_KOLTER           0x1001
+#define PCI_VENDOR_ID_ICP              0x104c
+#define PCI_VENDOR_ID_DT               0x1116
+#define PCI_VENDOR_ID_IOTECH           0x1616
+#define PCI_VENDOR_ID_CONTEC           0x1221
+#define PCI_VENDOR_ID_RTD              0x1435
+#define PCI_VENDOR_ID_HUMUSOFT         0x186c
+
+struct pci_dev *comedi_to_pci_dev(struct comedi_device *);
+
+int comedi_pci_enable(struct comedi_device *);
+void comedi_pci_disable(struct comedi_device *);
+void comedi_pci_detach(struct comedi_device *);
+
+int comedi_pci_auto_config(struct pci_dev *, struct comedi_driver *,
+                          unsigned long context);
+void comedi_pci_auto_unconfig(struct pci_dev *);
+
+int comedi_pci_driver_register(struct comedi_driver *, struct pci_driver *);
+void comedi_pci_driver_unregister(struct comedi_driver *, struct pci_driver *);
+
+/**
+ * module_comedi_pci_driver() - Helper macro for registering a comedi PCI driver
+ * @__comedi_driver: comedi_driver struct
+ * @__pci_driver: pci_driver struct
+ *
+ * Helper macro for comedi PCI drivers which do not do anything special
+ * in module init/exit. This eliminates a lot of boilerplate. Each
+ * module may only use this macro once, and calling it replaces
+ * module_init() and module_exit()
+ */
+#define module_comedi_pci_driver(__comedi_driver, __pci_driver) \
+       module_driver(__comedi_driver, comedi_pci_driver_register, \
+                       comedi_pci_driver_unregister, &(__pci_driver))
+
+#endif /* _COMEDI_PCI_H */
index e138eb0dc374c24b6cf360eddeda716fa7cf476d..dfab5a84b011f50215d626a92d2a31ebc877b835 100644 (file)
@@ -256,6 +256,7 @@ struct comedi_driver {
 struct comedi_device {
        int use_count;
        struct comedi_driver *driver;
+       struct comedi_8254 *pacer;
        void *private;
 
        struct device *class_dev;
@@ -463,6 +464,84 @@ static inline unsigned int comedi_samples_to_bytes(struct comedi_subdevice *s,
        return nsamples << comedi_sample_shift(s);
 }
 
+/**
+ * comedi_check_trigger_src() - trivially validate a comedi_cmd trigger source
+ * @src: pointer to the trigger source to validate
+ * @flags: bitmask of valid TRIG_* for the trigger
+ *
+ * This is used in "step 1" of the do_cmdtest functions of comedi drivers
+ * to vaildate the comedi_cmd triggers. The mask of the @src against the
+ * @flags allows the userspace comedilib to pass all the comedi_cmd
+ * triggers as TRIG_ANY and get back a bitmask of the valid trigger sources.
+ */
+static inline int comedi_check_trigger_src(unsigned int *src,
+                                          unsigned int flags)
+{
+       unsigned int orig_src = *src;
+
+       *src = orig_src & flags;
+       if (*src == TRIG_INVALID || *src != orig_src)
+               return -EINVAL;
+       return 0;
+}
+
+/**
+ * comedi_check_trigger_is_unique() - make sure a trigger source is unique
+ * @src: the trigger source to check
+ */
+static inline int comedi_check_trigger_is_unique(unsigned int src)
+{
+       /* this test is true if more than one _src bit is set */
+       if ((src & (src - 1)) != 0)
+               return -EINVAL;
+       return 0;
+}
+
+/**
+ * comedi_check_trigger_arg_is() - trivially validate a trigger argument
+ * @arg: pointer to the trigger arg to validate
+ * @val: the value the argument should be
+ */
+static inline int comedi_check_trigger_arg_is(unsigned int *arg,
+                                             unsigned int val)
+{
+       if (*arg != val) {
+               *arg = val;
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/**
+ * comedi_check_trigger_arg_min() - trivially validate a trigger argument
+ * @arg: pointer to the trigger arg to validate
+ * @val: the minimum value the argument should be
+ */
+static inline int comedi_check_trigger_arg_min(unsigned int *arg,
+                                              unsigned int val)
+{
+       if (*arg < val) {
+               *arg = val;
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/**
+ * comedi_check_trigger_arg_max() - trivially validate a trigger argument
+ * @arg: pointer to the trigger arg to validate
+ * @val: the maximum value the argument should be
+ */
+static inline int comedi_check_trigger_arg_max(unsigned int *arg,
+                                              unsigned int val)
+{
+       if (*arg > val) {
+               *arg = val;
+               return -EINVAL;
+       }
+       return 0;
+}
+
 /*
  * Must set dev->hw_dev if you wish to dma directly into comedi's buffer.
  * Also useful for retrieving a previously configured hardware device of
@@ -553,47 +632,4 @@ void comedi_driver_unregister(struct comedi_driver *);
        module_driver(__comedi_driver, comedi_driver_register, \
                        comedi_driver_unregister)
 
-/* comedi_pci.c - comedi PCI driver specific functions */
-
-/*
- * PCI Vendor IDs not in <linux/pci_ids.h>
- */
-#define PCI_VENDOR_ID_KOLTER           0x1001
-#define PCI_VENDOR_ID_ICP              0x104c
-#define PCI_VENDOR_ID_DT               0x1116
-#define PCI_VENDOR_ID_IOTECH           0x1616
-#define PCI_VENDOR_ID_CONTEC           0x1221
-#define PCI_VENDOR_ID_RTD              0x1435
-#define PCI_VENDOR_ID_HUMUSOFT         0x186c
-
-struct pci_dev;
-struct pci_driver;
-
-struct pci_dev *comedi_to_pci_dev(struct comedi_device *);
-
-int comedi_pci_enable(struct comedi_device *);
-void comedi_pci_disable(struct comedi_device *);
-void comedi_pci_detach(struct comedi_device *);
-
-int comedi_pci_auto_config(struct pci_dev *, struct comedi_driver *,
-                          unsigned long context);
-void comedi_pci_auto_unconfig(struct pci_dev *);
-
-int comedi_pci_driver_register(struct comedi_driver *, struct pci_driver *);
-void comedi_pci_driver_unregister(struct comedi_driver *, struct pci_driver *);
-
-/**
- * module_comedi_pci_driver() - Helper macro for registering a comedi PCI driver
- * @__comedi_driver: comedi_driver struct
- * @__pci_driver: pci_driver struct
- *
- * Helper macro for comedi PCI drivers which do not do anything special
- * in module init/exit. This eliminates a lot of boilerplate. Each
- * module may only use this macro once, and calling it replaces
- * module_init() and module_exit()
- */
-#define module_comedi_pci_driver(__comedi_driver, __pci_driver) \
-       module_driver(__comedi_driver, comedi_pci_driver_register, \
-                       comedi_pci_driver_unregister, &(__pci_driver))
-
 #endif /* _COMEDIDEV_H */
index f32e71438948a999bfa661f8cfad23dbf969a089..57dcffe00204580129478a202527b56362078726 100644 (file)
@@ -46,7 +46,7 @@ int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev)
 {
        if (hw_dev == dev->hw_dev)
                return 0;
-       if (dev->hw_dev != NULL)
+       if (dev->hw_dev)
                return -EEXIST;
        dev->hw_dev = get_device(hw_dev);
        return 0;
@@ -139,7 +139,9 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
                dev->n_subdevices = 0;
        }
        kfree(dev->private);
+       kfree(dev->pacer);
        dev->private = NULL;
+       dev->pacer = NULL;
        dev->driver = NULL;
        dev->board_name = NULL;
        dev->board_ptr = NULL;
@@ -800,7 +802,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                }
                module_put(driv->module);
        }
-       if (driv == NULL) {
+       if (!driv) {
                /*  recognize has failed if we get here */
                /*  report valid board names before returning error */
                for (driv = comedi_drivers; driv; driv = driv->next) {
@@ -812,7 +814,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                ret = -EIO;
                goto out;
        }
-       if (driv->attach == NULL) {
+       if (!driv->attach) {
                /* driver does not support manual configuration */
                dev_warn(dev->class_dev,
                         "driver '%s' does not support attach using comedi_config\n",
@@ -896,7 +898,7 @@ EXPORT_SYMBOL_GPL(comedi_auto_config);
 
 void comedi_auto_unconfig(struct device *hardware_device)
 {
-       if (hardware_device == NULL)
+       if (!hardware_device)
                return;
        comedi_release_hardware_device(hardware_device);
 }
diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h
deleted file mode 100644 (file)
index 51b9c8d..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * comedi/drivers/8253.h
- * Header file for 8253
- *
- * 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.
- */
-
-#ifndef _8253_H
-#define _8253_H
-
-#include "../comedi.h"
-
-/*
- * Common oscillator base values in nanoseconds
- */
-#define I8254_OSC_BASE_10MHZ           100
-#define I8254_OSC_BASE_5MHZ            200
-#define I8254_OSC_BASE_4MHZ            250
-#define I8254_OSC_BASE_2MHZ            500
-#define I8254_OSC_BASE_1MHZ            1000
-
-static inline void i8253_cascade_ns_to_timer(int i8253_osc_base,
-                                            unsigned int *d1,
-                                            unsigned int *d2,
-                                            unsigned int *nanosec,
-                                            unsigned int flags)
-{
-       unsigned int divider;
-       unsigned int div1, div2;
-       unsigned int div1_glb, div2_glb, ns_glb;
-       unsigned int div1_lub, div2_lub, ns_lub;
-       unsigned int ns;
-       unsigned int start;
-       unsigned int ns_low, ns_high;
-       static const unsigned int max_count = 0x10000;
-       /*
-        * exit early if everything is already correct (this can save time
-        * since this function may be called repeatedly during command tests
-        * and execution)
-        */
-       div1 = *d1 ? *d1 : max_count;
-       div2 = *d2 ? *d2 : max_count;
-       divider = div1 * div2;
-       if (div1 * div2 * i8253_osc_base == *nanosec &&
-           div1 > 1 && div1 <= max_count && div2 > 1 && div2 <= max_count &&
-           /* check for overflow */
-           divider > div1 && divider > div2 &&
-           divider * i8253_osc_base > divider &&
-           divider * i8253_osc_base > i8253_osc_base) {
-               return;
-       }
-
-       divider = *nanosec / i8253_osc_base;
-
-       div1_lub = div2_lub = 0;
-       div1_glb = div2_glb = 0;
-
-       ns_glb = 0;
-       ns_lub = 0xffffffff;
-
-       div2 = max_count;
-       start = divider / div2;
-       if (start < 2)
-               start = 2;
-       for (div1 = start; div1 <= divider / div1 + 1 && div1 <= max_count;
-            div1++) {
-               for (div2 = divider / div1;
-                    div1 * div2 <= divider + div1 + 1 && div2 <= max_count;
-                    div2++) {
-                       ns = i8253_osc_base * div1 * div2;
-                       if (ns <= *nanosec && ns > ns_glb) {
-                               ns_glb = ns;
-                               div1_glb = div1;
-                               div2_glb = div2;
-                       }
-                       if (ns >= *nanosec && ns < ns_lub) {
-                               ns_lub = ns;
-                               div1_lub = div1;
-                               div2_lub = div2;
-                       }
-               }
-       }
-
-       switch (flags & CMDF_ROUND_MASK) {
-       case CMDF_ROUND_NEAREST:
-       default:
-               ns_high = div1_lub * div2_lub * i8253_osc_base;
-               ns_low = div1_glb * div2_glb * i8253_osc_base;
-               if (ns_high - *nanosec < *nanosec - ns_low) {
-                       div1 = div1_lub;
-                       div2 = div2_lub;
-               } else {
-                       div1 = div1_glb;
-                       div2 = div2_glb;
-               }
-               break;
-       case CMDF_ROUND_UP:
-               div1 = div1_lub;
-               div2 = div2_lub;
-               break;
-       case CMDF_ROUND_DOWN:
-               div1 = div1_glb;
-               div2 = div2_glb;
-               break;
-       }
-
-       *nanosec = div1 * div2 * i8253_osc_base;
-       /* masking is done since counter maps zero to 0x10000 */
-       *d1 = div1 & 0xffff;
-       *d2 = div2 & 0xffff;
-}
-
-#ifndef CMDTEST
-/*
- * i8254_load programs 8254 counter chip.  It should also work for the 8253.
- * base_address is the lowest io address
- * for the chip (the address of counter 0).
- * counter_number is the counter you want to load (0,1 or 2)
- * count is the number to load into the counter.
- *
- * You probably want to use mode 2.
- *
- * Use i8254_mm_load() if you board uses memory-mapped io, it is
- * the same as i8254_load() except it uses writeb() instead of outb().
- *
- * Neither i8254_load() or i8254_read() do their loading/reading
- * atomically.  The 16 bit read/writes are performed with two successive
- * 8 bit read/writes.  So if two parts of your driver do a load/read on
- * the same counter, it may be necessary to protect these functions
- * with a spinlock.
- *
- * FMH
- */
-
-#define i8254_control_reg      3
-
-static inline int i8254_load(unsigned long base_address, unsigned int regshift,
-                            unsigned int counter_number, unsigned int count,
-                            unsigned int mode)
-{
-       unsigned int byte;
-
-       if (counter_number > 2)
-               return -1;
-       if (count > 0xffff)
-               return -1;
-       if (mode > 5)
-               return -1;
-       if ((mode == 2 || mode == 3) && count == 1)
-               return -1;
-
-       byte = counter_number << 6;
-       byte |= 0x30;           /* load low then high byte */
-       byte |= (mode << 1);    /* set counter mode */
-       outb(byte, base_address + (i8254_control_reg << regshift));
-       byte = count & 0xff;    /* lsb of counter value */
-       outb(byte, base_address + (counter_number << regshift));
-       byte = (count >> 8) & 0xff;     /* msb of counter value */
-       outb(byte, base_address + (counter_number << regshift));
-
-       return 0;
-}
-
-static inline int i8254_mm_load(void __iomem *base_address,
-                               unsigned int regshift,
-                               unsigned int counter_number,
-                               unsigned int count,
-                               unsigned int mode)
-{
-       unsigned int byte;
-
-       if (counter_number > 2)
-               return -1;
-       if (count > 0xffff)
-               return -1;
-       if (mode > 5)
-               return -1;
-       if ((mode == 2 || mode == 3) && count == 1)
-               return -1;
-
-       byte = counter_number << 6;
-       byte |= 0x30;           /* load low then high byte */
-       byte |= (mode << 1);    /* set counter mode */
-       writeb(byte, base_address + (i8254_control_reg << regshift));
-       byte = count & 0xff;    /* lsb of counter value */
-       writeb(byte, base_address + (counter_number << regshift));
-       byte = (count >> 8) & 0xff;     /* msb of counter value */
-       writeb(byte, base_address + (counter_number << regshift));
-
-       return 0;
-}
-
-/* Returns 16 bit counter value, should work for 8253 also. */
-static inline int i8254_read(unsigned long base_address, unsigned int regshift,
-                            unsigned int counter_number)
-{
-       unsigned int byte;
-       int ret;
-
-       if (counter_number > 2)
-               return -1;
-
-       /* latch counter */
-       byte = counter_number << 6;
-       outb(byte, base_address + (i8254_control_reg << regshift));
-
-       /* read lsb */
-       ret = inb(base_address + (counter_number << regshift));
-       /* read msb */
-       ret += inb(base_address + (counter_number << regshift)) << 8;
-
-       return ret;
-}
-
-static inline int i8254_mm_read(void __iomem *base_address,
-                               unsigned int regshift,
-                               unsigned int counter_number)
-{
-       unsigned int byte;
-       int ret;
-
-       if (counter_number > 2)
-               return -1;
-
-       /* latch counter */
-       byte = counter_number << 6;
-       writeb(byte, base_address + (i8254_control_reg << regshift));
-
-       /* read lsb */
-       ret = readb(base_address + (counter_number << regshift));
-       /* read msb */
-       ret += readb(base_address + (counter_number << regshift)) << 8;
-
-       return ret;
-}
-
-/* Loads 16 bit initial counter value, should work for 8253 also. */
-static inline void i8254_write(unsigned long base_address,
-                              unsigned int regshift,
-                              unsigned int counter_number, unsigned int count)
-{
-       unsigned int byte;
-
-       if (counter_number > 2)
-               return;
-
-       byte = count & 0xff;    /* lsb of counter value */
-       outb(byte, base_address + (counter_number << regshift));
-       byte = (count >> 8) & 0xff;     /* msb of counter value */
-       outb(byte, base_address + (counter_number << regshift));
-}
-
-static inline void i8254_mm_write(void __iomem *base_address,
-                                 unsigned int regshift,
-                                 unsigned int counter_number,
-                                 unsigned int count)
-{
-       unsigned int byte;
-
-       if (counter_number > 2)
-               return;
-
-       byte = count & 0xff;    /* lsb of counter value */
-       writeb(byte, base_address + (counter_number << regshift));
-       byte = (count >> 8) & 0xff;     /* msb of counter value */
-       writeb(byte, base_address + (counter_number << regshift));
-}
-
-/*
- * Set counter mode, should work for 8253 also.
- * Note: the 'mode' value is different to that for i8254_load() and comes
- * from the INSN_CONFIG_8254_SET_MODE command:
- *   I8254_MODE0, I8254_MODE1, ..., I8254_MODE5
- * OR'ed with:
- *   I8254_BCD, I8254_BINARY
- */
-static inline int i8254_set_mode(unsigned long base_address,
-                                unsigned int regshift,
-                                unsigned int counter_number, unsigned int mode)
-{
-       unsigned int byte;
-
-       if (counter_number > 2)
-               return -1;
-       if (mode > (I8254_MODE5 | I8254_BCD))
-               return -1;
-
-       byte = counter_number << 6;
-       byte |= 0x30;           /* load low then high byte */
-       byte |= mode;           /* set counter mode and BCD|binary */
-       outb(byte, base_address + (i8254_control_reg << regshift));
-
-       return 0;
-}
-
-static inline int i8254_mm_set_mode(void __iomem *base_address,
-                                   unsigned int regshift,
-                                   unsigned int counter_number,
-                                   unsigned int mode)
-{
-       unsigned int byte;
-
-       if (counter_number > 2)
-               return -1;
-       if (mode > (I8254_MODE5 | I8254_BCD))
-               return -1;
-
-       byte = counter_number << 6;
-       byte |= 0x30;           /* load low then high byte */
-       byte |= mode;           /* set counter mode and BCD|binary */
-       writeb(byte, base_address + (i8254_control_reg << regshift));
-
-       return 0;
-}
-
-static inline int i8254_status(unsigned long base_address,
-                              unsigned int regshift,
-                              unsigned int counter_number)
-{
-       outb(0xE0 | (2 << counter_number),
-            base_address + (i8254_control_reg << regshift));
-       return inb(base_address + (counter_number << regshift));
-}
-
-static inline int i8254_mm_status(void __iomem *base_address,
-                                 unsigned int regshift,
-                                 unsigned int counter_number)
-{
-       writeb(0xE0 | (2 << counter_number),
-              base_address + (i8254_control_reg << regshift));
-       return readb(base_address + (counter_number << regshift));
-}
-
-#endif
-
-#endif
index c2f15de6a547a6a2cca8c44339dfb00067475f5c..ba89321df65d8ef97afad5bf471149e1934fd5ae 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/module.h>
 #include "../comedidev.h"
 
-#include "comedi_fc.h"
 #include "8255.h"
 
 struct subdev_8255_private {
index 984764211a2df11533fecf54e6ebf2f47ab8b594..bb9854b568077b80f5203c3861e70ab6c1eb71b9 100644 (file)
@@ -62,9 +62,8 @@
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #include "8255.h"
 
@@ -178,7 +177,7 @@ static const struct pci_8255_boardinfo pci_8255_boards[] = {
        },
 };
 
-/* ripped from mite.h and mite_setup2() to avoid mite dependancy */
+/* ripped from mite.h and mite_setup2() to avoid mite dependency */
 #define MITE_IODWBSR   0xc0     /* IO Device Window Base Size Register */
 #define WENAB          (1 << 7) /* window enable */
 
index 7d1fbd53a8abdbfd8a80340a0308cbd6fe448bd5..d6d834006015836996ed752c186edf502cdbc38d 100644 (file)
@@ -3,6 +3,7 @@
 ccflags-$(CONFIG_COMEDI_DEBUG)         := -DDEBUG
 
 # Comedi "helper" modules
+obj-$(CONFIG_COMEDI_8254)              += comedi_8254.o
 obj-$(CONFIG_COMEDI_ISADMA)            += comedi_isadma.o
 
 # Comedi misc drivers
index 4911b627203bf83f79472fcdfc3b38f3963f7c84..b37166d57b64cd277e7484b2be22afe72ba20c54 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
-#include "comedi_fc.h"
+#include "../comedi_pci.h"
 #include "amcc_s5933.h"
 
 /*
@@ -196,11 +194,11 @@ static int apci1032_cos_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);
 
        if (err)
                return 1;
@@ -210,11 +208,12 @@ static int apci1032_cos_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-       err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -238,7 +237,7 @@ static int apci1032_cos_cmd(struct comedi_device *dev,
 
        if (!devpriv->ctrl) {
                dev_warn(dev->class_dev,
-                       "Interrupts disabled due to mode configuration!\n");
+                        "Interrupts disabled due to mode configuration!\n");
                return -EINVAL;
        }
 
@@ -296,7 +295,7 @@ static int apci1032_di_insn_bits(struct comedi_device *dev,
 }
 
 static int apci1032_auto_attach(struct comedi_device *dev,
-                                         unsigned long context_unused)
+                               unsigned long context_unused)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        struct apci1032_private *devpriv;
index f15aa1f6b4762eb2bbb1921c388e8ff735415f9a..63991c49ff2309e8a00bdd1bf28e4ad16eefcce4 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
-#include "comedi_fc.h"
+#include "../comedi_pci.h"
 #include "amcc_s5933.h"
 #include "z8536.h"
 
@@ -249,8 +247,8 @@ static irqreturn_t apci1500_interrupt(int irq, void *d)
         *
         *    Mask     Meaning
         * ----------  ------------------------------------------
-        * 0x00000001  Event 1 has occured
-        * 0x00000010  Event 2 has occured
+        * 0x00000001  Event 1 has occurred
+        * 0x00000010  Event 2 has occurred
         * 0x00000100  Counter/timer 1 has run down (not implemented)
         * 0x00001000  Counter/timer 2 has run down (not implemented)
         * 0x00010000  Counter 3 has run down (not implemented)
@@ -386,11 +384,11 @@ static int apci1500_di_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);
 
        if (err)
                return 1;
@@ -415,12 +413,13 @@ static int apci1500_di_cmdtest(struct comedi_device *dev,
         *   3  OR mode for Port A (digital inputs 0-7)
         *      OR mode for Port B (digital inputs 8-13 and internal signals)
         */
-       err |= cfc_check_trigger_arg_max(&cmd->start_arg, 3);
+       err |= comedi_check_trigger_arg_max(&cmd->start_arg, 3);
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-       err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -514,11 +513,11 @@ static int apci1500_di_cfg_trig(struct comedi_device *dev,
 
                src = pt & 0xff;
                if (src)
-                       ret |= cfc_check_trigger_is_unique(src);
+                       ret |= comedi_check_trigger_is_unique(src);
 
                src = (pt >> 8) & 0xff;
                if (src)
-                       ret |= cfc_check_trigger_is_unique(src);
+                       ret |= comedi_check_trigger_is_unique(src);
 
                if (ret) {
                        dev_dbg(dev->class_dev,
index d8410415cc90e5901771090df02f0dfddefb2881..9c516d1fe896fd351233ca73d24f8a8dbb8f0b00 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 #include "addi_watchdog.h"
-#include "comedi_fc.h"
 
 /*
  * PCI bar 1 I/O Register map - Digital input/output
index 6872b69da5dbf730b981b2cbb8fce95636be50f3..33e58b9a21b296895332fc7df5e0834dffc4f78e 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 
-#include "../comedidev.h"
-#include "comedi_fc.h"
+#include "../comedi_pci.h"
 #include "addi_tcw.h"
 #include "addi_watchdog.h"
 
 #define APCI1564_COUNTER(x)                    ((x) * 0x20)
 
 struct apci1564_private {
-       unsigned long eeprom;           /* base address of EEPROM register */
-       unsigned long timer;            /* base address of 12-bit timer */
-       unsigned long counters;         /* base address of 32-bit counters */
-       unsigned int mode1;             /* riding-edge/high level channels */
-       unsigned int mode2;             /* falling-edge/low level channels */
-       unsigned int ctrl;              /* interrupt mode OR (edge) . AND (level) */
+       unsigned long eeprom;   /* base address of EEPROM register */
+       unsigned long timer;    /* base address of 12-bit timer */
+       unsigned long counters; /* base address of 32-bit counters */
+       unsigned int mode1;     /* riding-edge/high level channels */
+       unsigned int mode2;     /* falling-edge/low level channels */
+       unsigned int ctrl;      /* interrupt mode OR (edge) . AND (level) */
        struct task_struct *tsk_current;
 };
 
@@ -365,11 +363,11 @@ static int apci1564_cos_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);
 
        if (err)
                return 1;
@@ -379,11 +377,12 @@ static int apci1564_cos_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-       err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -407,7 +406,7 @@ static int apci1564_cos_cmd(struct comedi_device *dev,
 
        if (!devpriv->ctrl) {
                dev_warn(dev->class_dev,
-                       "Interrupts disabled due to mode configuration!\n");
+                        "Interrupts disabled due to mode configuration!\n");
                return -EINVAL;
        }
 
@@ -430,7 +429,7 @@ static int apci1564_cos_cancel(struct comedi_device *dev,
 }
 
 static int apci1564_auto_attach(struct comedi_device *dev,
-                                     unsigned long context_unused)
+                               unsigned long context_unused)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        struct apci1564_private *devpriv;
index a1248dab369f30f3e8ca63c6049fd0d9277c391c..c63133a12a4e12aa3a63c57cc42e307bd9ac614a 100644 (file)
@@ -23,9 +23,8 @@
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 /*
  * Register I/O map
index eebf4f151b39ce7d6a3a47126c733b113101c72b..ad715253bdccdfdbeb04993c5ad9ee264ce5f615 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 #include "addi_watchdog.h"
-#include "comedi_fc.h"
 
 /*
  * PCI bar 1 I/O Register map
@@ -93,17 +91,17 @@ static int apci2032_int_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -112,14 +110,15 @@ static int apci2032_int_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
index 1f9d13661ac902ca8c5435084c478a934f97b4d5..2b382a52d80d41c0679857eef6fb03e3df12e986 100644 (file)
@@ -23,9 +23,8 @@
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 #include "addi_watchdog.h"
 
 /*
index c65f9407fd068c872944b0d3ac27249d76558e6a..95dc64bfec73b85d2644f9469b1e66ed07686fbf 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
-#include "comedi_fc.h"
+#include "../comedi_pci.h"
 #include "amcc_s5933.h"
 
 /*
@@ -612,21 +610,21 @@ static int apci3120_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_TIMER | TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -635,21 +633,24 @@ static int apci3120_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
-       if (cmd->scan_begin_src == TRIG_TIMER)  /* Test Delay timing */
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 100000);
+       if (cmd->scan_begin_src == TRIG_TIMER) {        /* Test Delay timing */
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   100000);
+       }
 
        /* minimum conversion time per sample is 10us */
-       err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000);
+       err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 10000);
 
-       err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /*  TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -659,7 +660,7 @@ static int apci3120_ai_cmdtest(struct comedi_device *dev,
        if (cmd->scan_begin_src == TRIG_TIMER) {
                /* scan begin must be larger than the scan time */
                arg = cmd->convert_arg * cmd->scan_end_arg;
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
        }
 
        if (err)
index 5961f195ba0bfaacc811109eba14b3da98100f0e..73786a3f3df98e60fee1b4843ad145a931f22406 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 
-#include "../comedidev.h"
-#include "comedi_fc.h"
+#include "../comedi_pci.h"
 #include "amcc_s5933.h"
 
 /*
@@ -203,7 +201,7 @@ static unsigned short apci3501_eeprom_readw(unsigned long iobase,
                outb(NVCMD_LOAD_HIGH, iobase + AMCC_OP_REG_MCSR_NVCMD);
                apci3501_eeprom_wait(iobase);
                outb(((addr + i) >> 8) & 0xff,
-                       iobase + AMCC_OP_REG_MCSR_NVDATA);
+                    iobase + AMCC_OP_REG_MCSR_NVDATA);
                apci3501_eeprom_wait(iobase);
 
                /* Read the eeprom data byte */
@@ -270,7 +268,7 @@ static irqreturn_t apci3501_interrupt(int irq, void *d)
 
        /*  Disable Interrupt */
        ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
-       ul_Command1 = (ul_Command1 & 0xFFFFF9FDul);
+       ul_Command1 = ul_Command1 & 0xFFFFF9FDul;
        outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
 
        ui_Timer_AOWatchdog = inl(dev->iobase + APCI3501_TIMER_IRQ_REG) & 0x1;
@@ -282,7 +280,7 @@ static irqreturn_t apci3501_interrupt(int irq, void *d)
        /* 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);
+       ul_Command1 = (ul_Command1 & 0xFFFFF9FDul) | 1 << 1;
        outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
        inl(dev->iobase + APCI3501_TIMER_STATUS_REG);
 
index c173810a3b5b5d044907fd8536d9a50dd1f06474..bef6efc84efde1c9a83596a7eaa48fc584e09ea8 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
-
-#include "comedi_fc.h"
+#include "../comedi_pci.h"
 
 #define CONV_UNIT_NS           (1 << 0)
 #define CONV_UNIT_US           (1 << 1)
@@ -529,18 +526,18 @@ static int apci3xxx_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -549,16 +546,17 @@ static int apci3xxx_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                        board->ai_min_acq_ns);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                           board->ai_min_acq_ns);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -567,7 +565,7 @@ static int apci3xxx_ai_cmdtest(struct comedi_device *dev,
 
        arg = cmd->convert_arg;
        err |= apci3xxx_ai_ns_to_timer(dev, &arg, cmd->flags);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
 
        if (err)
                return 4;
index c5b082d4e51e3ccce736af728d8a5e17d6dfb5f0..9d9853fe54a006cd8316ea20e4fb6cbfae090c33 100644 (file)
@@ -54,7 +54,7 @@ static int addi_watchdog_insn_config(struct comedi_device *dev,
 
                /* Time base is 20ms, let the user know the timeout */
                dev_info(dev->class_dev, "watchdog enabled, timeout:%dms\n",
-                       20 * reload + 20);
+                        20 * reload + 20);
                break;
        case INSN_CONFIG_DISARM:
                spriv->wdog_ctrl = 0;
index a3ea4b7c18dda50975d0d51dd7c908eb5eda9dc9..7ed3fd6fbd3ec24ceb1f321c13b23aaebf8071de 100644 (file)
 /*
  * Driver: adl_pci6208
  * Description: ADLink PCI-6208/6216 Series Multi-channel Analog Output Cards
- * Devices: [ADLink] PCI-6208 (adl_pci6208), PCI-6216 (adl_pci6216)
+ * Devices: [ADLink] PCI-6208 (adl_pci6208), PCI-6216
  * Author: nsyeow <nsyeow@pd.jaring.my>
- * Updated: Fri, 30 Jan 2004 14:44:27 +0800
+ * Updated: Wed, 11 Feb 2015 11:37:18 +0000
  * Status: untested
  *
  * Configuration Options: not applicable, uses PCI auto config
+ *
+ * All supported devices share the same PCI device ID and are treated as a
+ * PCI-6216 with 16 analog output channels.  On a PCI-6208, the upper 8
+ * channels exist in registers, but don't go to DAC chips.
  */
 
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 /*
  * PCI-6208/6216-GL register map
 #define PCI6208_DIO_DI_MASK            (0xf0)
 #define PCI6208_DIO_DI_SHIFT           (4)
 
-enum pci6208_boardid {
-       BOARD_PCI6208,
-       BOARD_PCI6216,
-};
-
-struct pci6208_board {
-       const char *name;
-       int ao_chans;
-};
-
-static const struct pci6208_board pci6208_boards[] = {
-       [BOARD_PCI6208] = {
-               .name           = "adl_pci6208",
-               .ao_chans       = 8,
-       },
-       [BOARD_PCI6216] = {
-               .name           = "adl_pci6216",
-               .ao_chans       = 16,
-       },
-};
-
 static int pci6208_ao_eoc(struct comedi_device *dev,
                          struct comedi_subdevice *s,
                          struct comedi_insn *insn,
@@ -136,21 +118,13 @@ static int pci6208_do_insn_bits(struct comedi_device *dev,
 }
 
 static int pci6208_auto_attach(struct comedi_device *dev,
-                              unsigned long context)
+                              unsigned long context_unused)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-       const struct pci6208_board *boardinfo = NULL;
        struct comedi_subdevice *s;
        unsigned int val;
        int ret;
 
-       if (context < ARRAY_SIZE(pci6208_boards))
-               boardinfo = &pci6208_boards[context];
-       if (!boardinfo)
-               return -ENODEV;
-       dev->board_ptr = boardinfo;
-       dev->board_name = boardinfo->name;
-
        ret = comedi_pci_enable(dev);
        if (ret)
                return ret;
@@ -164,7 +138,7 @@ static int pci6208_auto_attach(struct comedi_device *dev,
        /* analog output subdevice */
        s->type         = COMEDI_SUBD_AO;
        s->subdev_flags = SDF_WRITABLE;
-       s->n_chan       = boardinfo->ao_chans;
+       s->n_chan       = 16;   /* Only 8 usable on PCI-6208 */
        s->maxdata      = 0xffff;
        s->range_table  = &range_bipolar10;
        s->insn_write   = pci6208_ao_insn_write;
@@ -217,8 +191,9 @@ static int adl_pci6208_pci_probe(struct pci_dev *dev,
 }
 
 static const struct pci_device_id adl_pci6208_pci_table[] = {
-       { PCI_VDEVICE(ADLINK, 0x6208), BOARD_PCI6208 },
-       { PCI_VDEVICE(ADLINK, 0x6216), BOARD_PCI6216 },
+       { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x6208) },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+                        0x9999, 0x6208) },
        { 0 }
 };
 MODULE_DEVICE_TABLE(pci, adl_pci6208_pci_table);
index 618e641ffaac6a7f6673ee088d8f45a9da92b812..934af3ff789732f4aeb4928997e72318ad609f7b 100644 (file)
@@ -53,9 +53,8 @@
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 /*
  * Register I/O map (32-bit access only)
index cc6c53b800a7dfbe289a68cdc388c33919972d27..da901c8dec0e2ade20d736136a30d48f8821822b 100644 (file)
@@ -28,9 +28,8 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #define PCI8164_AXIS(x)                ((x) * 0x08)
 #define PCI8164_CMD_MSTS_REG   0x00
@@ -69,7 +68,7 @@ static int adl_pci8164_insn_write(struct comedi_device *dev,
 }
 
 static int adl_pci8164_auto_attach(struct comedi_device *dev,
-                                            unsigned long context_unused)
+                                  unsigned long context_unused)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        struct comedi_subdevice *s;
index f68dc99f8e277a2031f12dff57090b2f1a76c6e0..c9df3afe97f6f60d2309a935771966bcbc75a5f5 100644 (file)
@@ -65,15 +65,13 @@ TODO:
 */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
-#include "8253.h"
 #include "plx9052.h"
-#include "comedi_fc.h"
+#include "comedi_8254.h"
 
 #define PCI9111_FIFO_HALF_SIZE 512
 
@@ -137,9 +135,6 @@ struct pci9111_private_data {
        unsigned int chunk_counter;
        unsigned int chunk_num_samples;
 
-       unsigned int div1;
-       unsigned int div2;
-
        unsigned short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
 };
 
@@ -167,21 +162,6 @@ static void plx9050_interrupt_control(unsigned long io_base,
        outb(flags, io_base + PLX9052_INTCSR);
 }
 
-static void pci9111_timer_set(struct comedi_device *dev)
-{
-       struct pci9111_private_data *dev_private = dev->private;
-       unsigned long timer_base = dev->iobase + PCI9111_8254_BASE_REG;
-
-       i8254_set_mode(timer_base, 1, 0, I8254_MODE0 | I8254_BINARY);
-       i8254_set_mode(timer_base, 1, 1, I8254_MODE2 | I8254_BINARY);
-       i8254_set_mode(timer_base, 1, 2, I8254_MODE2 | I8254_BINARY);
-
-       udelay(1);
-
-       i8254_write(timer_base, 1, 2, dev_private->div2);
-       i8254_write(timer_base, 1, 1, dev_private->div1);
-}
-
 enum pci9111_ISC0_sources {
        irq_on_eoc,
        irq_on_fifo_half_full
@@ -281,19 +261,18 @@ static int pci9111_ai_do_cmd_test(struct comedi_device *dev,
                                  struct comedi_subdevice *s,
                                  struct comedi_cmd *cmd)
 {
-       struct pci9111_private_data *dev_private = dev->private;
        int err = 0;
        unsigned int arg;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src,
+       err |= comedi_check_trigger_src(&cmd->convert_src,
                                        TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src,
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src,
                                        TRIG_COUNT | TRIG_NONE);
 
        if (err)
@@ -301,9 +280,9 @@ static int pci9111_ai_do_cmd_test(struct comedi_device *dev,
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -317,26 +296,29 @@ static int pci9111_ai_do_cmd_test(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
-       if (cmd->convert_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+       if (cmd->convert_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
                                        PCI9111_AI_ACQUISITION_PERIOD_MIN_NS);
-       else    /* TRIG_EXT */
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+       } else {        /* TRIG_EXT */
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       }
 
-       if (cmd->scan_begin_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+       if (cmd->scan_begin_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
                                        PCI9111_AI_ACQUISITION_PERIOD_MIN_NS);
-       else    /* TRIG_FOLLOW || TRIG_EXT */
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       } else {        /* TRIG_FOLLOW || TRIG_EXT */
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       }
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -345,11 +327,8 @@ static int pci9111_ai_do_cmd_test(struct comedi_device *dev,
 
        if (cmd->convert_src == TRIG_TIMER) {
                arg = cmd->convert_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
-                                         &dev_private->div1,
-                                         &dev_private->div2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
        }
 
        /*
@@ -362,7 +341,7 @@ static int pci9111_ai_do_cmd_test(struct comedi_device *dev,
                if (arg < cmd->scan_begin_arg)
                        arg *= (cmd->scan_begin_arg / arg);
 
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
 
        if (err)
@@ -376,7 +355,6 @@ static int pci9111_ai_do_cmd_test(struct comedi_device *dev,
                return 5;
 
        return 0;
-
 }
 
 static int pci9111_ai_do_cmd(struct comedi_device *dev,
@@ -400,13 +378,14 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
        /*  This is the same gain on every channel */
 
        outb(CR_RANGE(cmd->chanlist[0]) & PCI9111_AI_RANGE_MASK,
-               dev->iobase + PCI9111_AI_RANGE_STAT_REG);
+            dev->iobase + PCI9111_AI_RANGE_STAT_REG);
 
        /*  Set timer pacer */
        dev_private->scan_delay = 0;
        if (cmd->convert_src == TRIG_TIMER) {
                trig |= PCI9111_AI_TRIG_CTRL_TPST;
-               pci9111_timer_set(dev);
+               comedi_8254_update_divisors(dev->pacer);
+               comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
                pci9111_fifo_reset(dev);
                pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
                                             irq_on_timer_tick);
@@ -593,7 +572,7 @@ static int pci9111_ai_insn_read(struct comedi_device *dev,
        status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG);
        if ((status & PCI9111_AI_RANGE_MASK) != range) {
                outb(range & PCI9111_AI_RANGE_MASK,
-                       dev->iobase + PCI9111_AI_RANGE_STAT_REG);
+                    dev->iobase + PCI9111_AI_RANGE_STAT_REG);
        }
 
        pci9111_fifo_reset(dev);
@@ -667,16 +646,11 @@ static int pci9111_reset(struct comedi_device *dev)
        /* disable A/D triggers (software trigger mode) and auto scan off */
        outb(0, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
 
-       /* Reset 8254 chip */
-       dev_private->div1 = 0;
-       dev_private->div2 = 0;
-       pci9111_timer_set(dev);
-
        return 0;
 }
 
 static int pci9111_auto_attach(struct comedi_device *dev,
-                                        unsigned long context_unused)
+                              unsigned long context_unused)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        struct pci9111_private_data *dev_private;
@@ -702,6 +676,11 @@ static int pci9111_auto_attach(struct comedi_device *dev,
                        dev->irq = pcidev->irq;
        }
 
+       dev->pacer = comedi_8254_init(dev->iobase + PCI9111_8254_BASE_REG,
+                                     I8254_OSC_BASE_2MHZ, I8254_IO16, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
                return ret;
index f61e392c2d3ef4ba93be7708d48ac17ab1343bb5..fb3043dcfff1e62b9cc318df55e82c3dceea308c 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #include "amcc_s5933.h"
-#include "8253.h"
-#include "comedi_fc.h"
+#include "comedi_8254.h"
 
 #define IORANGE_9118   64      /* I hope */
 #define PCI9118_CHANLEN        255     /*
@@ -94,8 +92,7 @@
 /*
  * PCI BAR2 Register map (dev->iobase)
  */
-#define PCI9118_TIMER_REG(x)           (0x00 + ((x) * 4))
-#define PCI9118_TIMER_CTRL_REG         0x0c
+#define PCI9118_TIMER_BASE             0x00
 #define PCI9118_AI_FIFO_REG            0x10
 #define PCI9118_AO_REG(x)              (0x10 + ((x) * 4))
 #define PCI9118_AI_STATUS_REG          0x18
@@ -239,10 +236,6 @@ struct pci9118_private {
                                         * measure can start/stop
                                         * on external trigger
                                         */
-       unsigned int ai_divisor1, ai_divisor2;  /*
-                                                * divisors for start of measure
-                                                * on external start
-                                                */
        unsigned int dma_actbuf;                /* which buffer is used now */
        struct pci9118_dmabuf dmabuf[2];
        int softsshdelay;               /*
@@ -297,24 +290,6 @@ static void pci9118_amcc_int_ena(struct comedi_device *dev, bool enable)
        outl(intcsr, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
 }
 
-static void pci9118_timer_write(struct comedi_device *dev,
-                               unsigned int timer, unsigned int val)
-{
-       outl(val & 0xff, dev->iobase + PCI9118_TIMER_REG(timer));
-       outl((val >> 8) & 0xff, dev->iobase + PCI9118_TIMER_REG(timer));
-}
-
-static void pci9118_timer_set_mode(struct comedi_device *dev,
-                                  unsigned int timer, unsigned int mode)
-{
-       unsigned int val;
-
-       val = timer << 6;       /* select timer */
-       val |= 0x30;            /* load low then high byte */
-       val |= mode;            /* set timer mode and BCD|binary */
-       outl(val, dev->iobase + PCI9118_TIMER_CTRL_REG);
-}
-
 static void pci9118_ai_reset_fifo(struct comedi_device *dev)
 {
        /* writing any value resets the A/D FIFO */
@@ -440,8 +415,8 @@ static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev,
        devpriv->ai_cfg = PCI9118_AI_CFG_PDTRG | PCI9118_AI_CFG_PETRG |
                          PCI9118_AI_CFG_AM;
        outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
-       pci9118_timer_set_mode(dev, 0, I8254_MODE0);
-       pci9118_timer_write(dev, 0, dmabuf->hw >> 1);
+       comedi_8254_load(dev->pacer, 0, dmabuf->hw >> 1,
+                        I8254_MODE0 | I8254_BINARY);
        devpriv->ai_cfg |= PCI9118_AI_CFG_START;
        outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
 }
@@ -577,15 +552,16 @@ static void pci9118_calc_divisors(struct comedi_device *dev,
                                  unsigned int *div1, unsigned int *div2,
                                  unsigned int chnsshfront)
 {
+       struct comedi_8254 *pacer = dev->pacer;
        struct comedi_cmd *cmd = &s->async->cmd;
 
-       *div1 = *tim2 / I8254_OSC_BASE_4MHZ;    /* convert timer (burst) */
-       *div2 = *tim1 / I8254_OSC_BASE_4MHZ;    /* scan timer */
+       *div1 = *tim2 / pacer->osc_base;        /* convert timer (burst) */
+       *div2 = *tim1 / pacer->osc_base;        /* scan timer */
        *div2 = *div2 / *div1;                  /* major timer is c1*c2 */
        if (*div2 < chans)
                *div2 = chans;
 
-       *tim2 = *div1 * I8254_OSC_BASE_4MHZ;    /* real convert timer */
+       *tim2 = *div1 * pacer->osc_base;        /* real convert timer */
 
        if (cmd->convert_src == TRIG_NOW && !chnsshfront) {
                /* use BSSH signal */
@@ -593,21 +569,13 @@ static void pci9118_calc_divisors(struct comedi_device *dev,
                        *div2 = chans + 2;
        }
 
-       *tim1 = *div1 * *div2 * I8254_OSC_BASE_4MHZ;
+       *tim1 = *div1 * *div2 * pacer->osc_base;
 }
 
 static void pci9118_start_pacer(struct comedi_device *dev, int mode)
 {
-       struct pci9118_private *devpriv = dev->private;
-
-       pci9118_timer_set_mode(dev, 1, I8254_MODE2);
-       pci9118_timer_set_mode(dev, 2, I8254_MODE2);
-       udelay(1);
-
-       if ((mode == 1) || (mode == 2) || (mode == 4)) {
-               pci9118_timer_write(dev, 2, devpriv->ai_divisor2);
-               pci9118_timer_write(dev, 1, devpriv->ai_divisor1);
-       }
+       if (mode == 1 || mode == 2 || mode == 4)
+               comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
 }
 
 static int pci9118_ai_cancel(struct comedi_device *dev,
@@ -618,7 +586,7 @@ static int pci9118_ai_cancel(struct comedi_device *dev,
        if (devpriv->usedma)
                pci9118_amcc_dma_ena(dev, false);
        pci9118_exttrg_enable(dev, false);
-       pci9118_start_pacer(dev, 0);    /* stop 8254 counters */
+       comedi_8254_pacer_enable(dev->pacer, 1, 2, false);
        /* set default config (disable burst and triggers) */
        devpriv->ai_cfg = PCI9118_AI_CFG_PDTRG | PCI9118_AI_CFG_PETRG;
        outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
@@ -663,7 +631,6 @@ static void pci9118_ai_munge(struct comedi_device *dev,
                        array[i] ^= 0x8000;
                else
                        array[i] = (array[i] >> 4) & 0x0fff;
-
        }
 }
 
@@ -966,7 +933,7 @@ static int Compute_and_setup_dma(struct comedi_device *dev,
 /* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
        pci9118_amcc_dma_ena(dev, true);
        outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS,
-                       devpriv->iobase_a + AMCC_OP_REG_INTCSR);
+            devpriv->iobase_a + AMCC_OP_REG_INTCSR);
                                                /* allow bus mastering */
 
        return 0;
@@ -975,6 +942,7 @@ static int Compute_and_setup_dma(struct comedi_device *dev,
 static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
        struct pci9118_private *devpriv = dev->private;
+       struct comedi_8254 *pacer = dev->pacer;
        struct comedi_cmd *cmd = &s->async->cmd;
        unsigned int addchans = 0;
 
@@ -1093,12 +1061,10 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                else
                        devpriv->ai_do = 1;
 
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ,
-                                         &devpriv->ai_divisor1,
-                                         &devpriv->ai_divisor2,
-                                         &cmd->convert_arg,
-                                         devpriv->ai_flags &
-                                         CMDF_ROUND_NEAREST);
+               comedi_8254_cascade_ns_to_timer(pacer, &cmd->convert_arg,
+                                               devpriv->ai_flags &
+                                               CMDF_ROUND_NEAREST);
+               comedi_8254_update_divisors(pacer);
 
                devpriv->ai_ctrl |= PCI9118_AI_CTRL_TMRTR;
 
@@ -1112,8 +1078,8 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
                        devpriv->ai_cfg |= PCI9118_AI_CFG_AM;
                        outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
-                       pci9118_timer_set_mode(dev, 0, I8254_MODE0);
-                       pci9118_timer_write(dev, 0, dmabuf->hw >> 1);
+                       comedi_8254_load(pacer, 0, dmabuf->hw >> 1,
+                                        I8254_MODE0 | I8254_BINARY);
                        devpriv->ai_cfg |= PCI9118_AI_CFG_START;
                }
        }
@@ -1133,8 +1099,8 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                                      &cmd->scan_begin_arg, &cmd->convert_arg,
                                      devpriv->ai_flags,
                                      devpriv->ai_n_realscanlen,
-                                     &devpriv->ai_divisor1,
-                                     &devpriv->ai_divisor2,
+                                     &pacer->divisor1,
+                                     &pacer->divisor2,
                                      devpriv->ai_add_front);
 
                devpriv->ai_ctrl |= PCI9118_AI_CTRL_TMRTR;
@@ -1162,8 +1128,6 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        if (devpriv->usedma)
                devpriv->ai_ctrl |= PCI9118_AI_CTRL_DMA;
 
-       pci9118_start_pacer(dev, -1);   /* stop pacer */
-
        /* set default config (disable burst and triggers) */
        devpriv->ai_cfg = PCI9118_AI_CFG_PDTRG | PCI9118_AI_CFG_PETRG;
        outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
@@ -1206,25 +1170,24 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
        int err = 0;
        unsigned int flags;
        unsigned int arg;
-       unsigned int divisor1 = 0, divisor2 = 0;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src,
+       err |= comedi_check_trigger_src(&cmd->start_src,
                                        TRIG_NOW | TRIG_EXT | TRIG_INT);
 
        flags = TRIG_FOLLOW;
        if (devpriv->master)
                flags |= TRIG_TIMER | TRIG_EXT;
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, flags);
 
        flags = TRIG_TIMER | TRIG_EXT;
        if (devpriv->master)
                flags |= TRIG_NOW;
-       err |= cfc_check_trigger_src(&cmd->convert_src, flags);
+       err |= comedi_check_trigger_src(&cmd->convert_src, flags);
 
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src,
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src,
                                        TRIG_COUNT | TRIG_NONE | TRIG_EXT);
 
        if (err)
@@ -1232,10 +1195,10 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -1264,7 +1227,7 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
        switch (cmd->start_src) {
        case TRIG_NOW:
        case TRIG_EXT:
-               err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
                break;
        case TRIG_INT:
                /* start_arg is the internal trigger (any value) */
@@ -1272,7 +1235,7 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
        }
 
        if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
        if ((cmd->scan_begin_src == TRIG_TIMER) &&
            (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
@@ -1281,34 +1244,37 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
                cmd->scan_begin_arg = 0;
        }
 
-       if (cmd->scan_begin_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                devpriv->ai_ns_min);
+       if (cmd->scan_begin_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   devpriv->ai_ns_min);
+       }
 
-       if (cmd->scan_begin_src == TRIG_EXT)
+       if (cmd->scan_begin_src == TRIG_EXT) {
                if (cmd->scan_begin_arg) {
                        cmd->scan_begin_arg = 0;
                        err |= -EINVAL;
-                       err |= cfc_check_trigger_arg_max(&cmd->scan_end_arg,
-                                                        65535);
+                       err |= comedi_check_trigger_arg_max(&cmd->scan_end_arg,
+                                                           65535);
                }
+       }
 
-       if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW))
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                devpriv->ai_ns_min);
+       if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                   devpriv->ai_ns_min);
+       }
 
        if (cmd->convert_src == TRIG_EXT)
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
-       err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
+       err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
 
-       err |= cfc_check_trigger_arg_min(&cmd->scan_end_arg,
-                                        cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_min(&cmd->scan_end_arg,
+                                           cmd->chanlist_len);
 
        if ((cmd->scan_end_arg % cmd->chanlist_len)) {
                cmd->scan_end_arg =
@@ -1323,18 +1289,14 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
                arg = cmd->scan_begin_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ,
-                                         &divisor1, &divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
 
        if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
                arg = cmd->convert_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ,
-                                         &divisor1, &divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
 
                if (cmd->scan_begin_src == TRIG_TIMER &&
                    cmd->convert_src == TRIG_NOW) {
@@ -1344,8 +1306,9 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
                        } else {
                                arg = cmd->convert_arg * cmd->chanlist_len;
                        }
-                       err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                        arg);
+                       err |= comedi_check_trigger_arg_min(&cmd->
+                                                           scan_begin_arg,
+                                                           arg);
                }
        }
 
@@ -1482,10 +1445,6 @@ static void pci9118_reset(struct comedi_device *dev)
        inl(dev->iobase + PCI9118_INT_CTRL_REG);
        inl(dev->iobase + PCI9118_AI_STATUS_REG);
 
-       /* reset and stop counters */
-       pci9118_timer_set_mode(dev, 0, I8254_MODE0);
-       pci9118_start_pacer(dev, 0);
-
        /* reset DMA and scan queue */
        outl(0, dev->iobase + PCI9118_AI_BURST_NUM_REG);
        outl(1, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
@@ -1590,6 +1549,11 @@ static int pci9118_common_attach(struct comedi_device *dev,
        devpriv->iobase_a = pci_resource_start(pcidev, 0);
        dev->iobase = pci_resource_start(pcidev, 2);
 
+       dev->pacer = comedi_8254_init(dev->iobase + PCI9118_TIMER_BASE,
+                                     I8254_OSC_BASE_4MHZ, I8254_IO32, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        pci9118_reset(dev);
 
        if (pcidev->irq) {
index 8b15cbec9891996dedf11502d74c43ed9486c696..bc5f97f50f9a478b6af4aed56137c64252b310a3 100644 (file)
@@ -69,8 +69,6 @@ If you do not specify any options, they will default to
 
    13-oct-2007
      + first try
-
-
 */
 
 #include <linux/module.h>
@@ -170,7 +168,6 @@ static int adq12b_di_insn_bits(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
-
        /* only bits 0-4 have information about digital inputs */
        data[1] = (inb(dev->iobase + ADQ12B_STINR) & ADQ12B_STINR_IN_MASK);
 
index 3f72451d2de01aa44d1b16f633ddd8999894db25..0c6aa964c884f274de3cd0e194ffe0f90edc630f 100644 (file)
@@ -4,7 +4,7 @@
  * Author: Michal Dobes <dobes@tesnet.cz>
  *
  * Thanks to ZhenGang Shang <ZhenGang.Shang@Advantech.com.cn>
- * for testing and informations.
+ * for testing and information.
  *
  *  hardware driver for Advantech cards:
  *   card:   PCI-1710, PCI-1710HG, PCI-1711, PCI-1713, PCI-1720, PCI-1731
@@ -42,13 +42,11 @@ Configuration options:
 */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
-#include "comedi_fc.h"
-#include "8253.h"
+#include "comedi_8254.h"
 #include "amcc_s5933.h"
 
 #define PCI171x_AD_DATA         0      /* R:   A/D data */
@@ -67,11 +65,6 @@ Configuration options:
 
 #define PCI171X_TIMER_BASE     0x18
 
-#define PCI171x_CNT0   24      /* R/W: 8254 counter 0 */
-#define PCI171x_CNT1   26      /* R/W: 8254 counter 1 */
-#define PCI171x_CNT2   28      /* R/W: 8254 counter 2 */
-#define PCI171x_CNTCTRL        30      /* W:   8254 counter control */
-
 /* upper bits from status register (PCI171x_STATUS) (lower is same with control
  * reg) */
 #define        Status_FE       0x0100  /* 1=FIFO is empty */
@@ -87,16 +80,6 @@ Configuration options:
 #define Control_EXT    0x0004  /* 1=external trigger source */
 #define Control_PACER  0x0002  /* 1=enable internal 8254 trigger source */
 #define Control_SW     0x0001  /* 1=enable software trigger source */
-/* bits from counter control register (PCI171x_CNTCTRL) */
-#define Counter_BCD     0x0001 /* 0 = binary counter, 1 = BCD counter */
-#define Counter_M0      0x0002 /* M0-M2 select modes 0-5 */
-#define Counter_M1      0x0004 /* 000 = mode 0, 010 = mode 2 ... */
-#define Counter_M2      0x0008
-#define Counter_RW0     0x0010 /* RW0/RW1 select read/write mode */
-#define Counter_RW1     0x0020
-#define Counter_SC0     0x0040 /* Select Counter. Only 00 or 11 may */
-#define Counter_SC1     0x0080 /* be used, 00 for CNT0,
-                                * 11 for read-back command */
 
 #define PCI1720_DA0     0      /* W:   D/A register 0 */
 #define PCI1720_DA1     2      /* W:   D/A register 1 */
@@ -265,15 +248,9 @@ struct pci1710_private {
        unsigned char ai_et;
        unsigned int ai_et_CntrlReg;
        unsigned int ai_et_MuxVal;
-       unsigned int next_divisor1;
-       unsigned int next_divisor2;
-       unsigned int divisor1;
-       unsigned int divisor2;
        unsigned int act_chanlist[32];  /*  list of scanned channel */
        unsigned char saved_seglen;     /* len of the non-repeating chanlist */
        unsigned char da_ranges;        /*  copy of D/A outpit range register */
-       unsigned int cnt0_write_wait;   /* after a write, wait for update of the
-                                        * internal state */
 };
 
 static int pci171x_ai_check_chanlist(struct comedi_device *dev,
@@ -508,105 +485,6 @@ static int pci171x_do_insn_bits(struct comedi_device *dev,
        return insn->n;
 }
 
-static void pci171x_start_pacer(struct comedi_device *dev,
-                               bool load_counters)
-{
-       struct pci1710_private *devpriv = dev->private;
-       unsigned long timer_base = dev->iobase + PCI171X_TIMER_BASE;
-
-       i8254_set_mode(timer_base, 1, 2, I8254_MODE2 | I8254_BINARY);
-       i8254_set_mode(timer_base, 1, 1, I8254_MODE2 | I8254_BINARY);
-
-       if (load_counters) {
-               i8254_write(timer_base, 1, 2, devpriv->divisor2);
-               i8254_write(timer_base, 1, 1, devpriv->divisor1);
-       }
-}
-
-static int pci171x_counter_insn_read(struct comedi_device *dev,
-                                    struct comedi_subdevice *s,
-                                    struct comedi_insn *insn,
-                                    unsigned int *data)
-{
-       unsigned int msb, lsb, ccntrl;
-       int i;
-
-       ccntrl = 0xD2;          /* count only */
-       for (i = 0; i < insn->n; i++) {
-               outw(ccntrl, dev->iobase + PCI171x_CNTCTRL);
-
-               lsb = inw(dev->iobase + PCI171x_CNT0) & 0xFF;
-               msb = inw(dev->iobase + PCI171x_CNT0) & 0xFF;
-
-               data[0] = lsb | (msb << 8);
-       }
-
-       return insn->n;
-}
-
-static int pci171x_counter_insn_write(struct comedi_device *dev,
-                                     struct comedi_subdevice *s,
-                                     struct comedi_insn *insn,
-                                     unsigned int *data)
-{
-       struct pci1710_private *devpriv = dev->private;
-       uint msb, lsb, ccntrl, status;
-
-       lsb = data[0] & 0x00FF;
-       msb = (data[0] & 0xFF00) >> 8;
-
-       /* write lsb, then msb */
-       outw(lsb, dev->iobase + PCI171x_CNT0);
-       outw(msb, dev->iobase + PCI171x_CNT0);
-
-       if (devpriv->cnt0_write_wait) {
-               /* wait for the new count to be loaded */
-               ccntrl = 0xE2;
-               do {
-                       outw(ccntrl, dev->iobase + PCI171x_CNTCTRL);
-                       status = inw(dev->iobase + PCI171x_CNT0) & 0xFF;
-               } while (status & 0x40);
-       }
-
-       return insn->n;
-}
-
-static int pci171x_counter_insn_config(struct comedi_device *dev,
-                                      struct comedi_subdevice *s,
-                                      struct comedi_insn *insn,
-                                      unsigned int *data)
-{
-#ifdef unused
-       /* This doesn't work like a normal Comedi counter config */
-       struct pci1710_private *devpriv = dev->private;
-       uint ccntrl = 0;
-
-       devpriv->cnt0_write_wait = data[0] & 0x20;
-
-       /* internal or external clock? */
-       if (!(data[0] & 0x10)) {        /* internal */
-               devpriv->CntrlReg &= ~Control_CNT0;
-       } else {
-               devpriv->CntrlReg |= Control_CNT0;
-       }
-       outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
-
-       if (data[0] & 0x01)
-               ccntrl |= Counter_M0;
-       if (data[0] & 0x02)
-               ccntrl |= Counter_M1;
-       if (data[0] & 0x04)
-               ccntrl |= Counter_M2;
-       if (data[0] & 0x08)
-               ccntrl |= Counter_BCD;
-       ccntrl |= Counter_RW0;  /* set read/write mode */
-       ccntrl |= Counter_RW1;
-       outw(ccntrl, dev->iobase + PCI171x_CNTCTRL);
-#endif
-
-       return 1;
-}
-
 static int pci1720_ao_insn_write(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_insn *insn,
@@ -646,7 +524,7 @@ static int pci171x_ai_cancel(struct comedi_device *dev,
        devpriv->CntrlReg |= Control_SW;
        /* reset any operations */
        outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
-       pci171x_start_pacer(dev, false);
+       comedi_8254_pacer_enable(dev->pacer, 1, 2, false);
        outb(0, dev->iobase + PCI171x_CLRFIFO);
        outb(0, dev->iobase + PCI171x_CLRINT);
 
@@ -767,7 +645,7 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d)
                outb(0, dev->iobase + PCI171x_CLRINT);
                outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX);
                outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
-               pci171x_start_pacer(dev, true);
+               comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
                return IRQ_HANDLED;
        }
 
@@ -786,8 +664,6 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        struct pci1710_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
 
-       pci171x_start_pacer(dev, false);
-
        pci171x_ai_setup_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len,
                                  devpriv->saved_seglen);
 
@@ -798,10 +674,9 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        if ((cmd->flags & CMDF_WAKE_EOS) == 0)
                devpriv->CntrlReg |= Control_ONEFH;
 
-       devpriv->divisor1 = devpriv->next_divisor1;
-       devpriv->divisor2 = devpriv->next_divisor2;
-
        if (cmd->convert_src == TRIG_TIMER) {
+               comedi_8254_update_divisors(dev->pacer);
+
                devpriv->CntrlReg |= Control_PACER | Control_IRQEN;
                if (cmd->start_src == TRIG_EXT) {
                        devpriv->ai_et_CntrlReg = devpriv->CntrlReg;
@@ -815,7 +690,7 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
 
                if (cmd->start_src == TRIG_NOW)
-                       pci171x_start_pacer(dev, true);
+                       comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
        } else {        /* TRIG_EXT */
                devpriv->CntrlReg |= Control_EXT | Control_IRQEN;
                outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
@@ -828,26 +703,25 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
                              struct comedi_subdevice *s,
                              struct comedi_cmd *cmd)
 {
-       struct pci1710_private *devpriv = dev->private;
        int err = 0;
-       unsigned int arg;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->convert_src,
+                                       TRIG_TIMER | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* step 2a: make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* step 2b: and mutually compatible */
 
@@ -856,20 +730,21 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
        if (cmd->convert_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000);
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 10000);
        else    /* TRIG_FOLLOW */
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -877,12 +752,10 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
        /* step 4: fix up any arguments */
 
        if (cmd->convert_src == TRIG_TIMER) {
-               arg = cmd->convert_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
-                                         &devpriv->next_divisor1,
-                                         &devpriv->next_divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               unsigned int arg = cmd->convert_arg;
+
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
        }
 
        if (err)
@@ -898,19 +771,54 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
        return 0;
 }
 
+static int pci171x_insn_counter_config(struct comedi_device *dev,
+                                      struct comedi_subdevice *s,
+                                      struct comedi_insn *insn,
+                                      unsigned int *data)
+{
+       struct pci1710_private *devpriv = dev->private;
+
+       switch (data[0]) {
+       case INSN_CONFIG_SET_CLOCK_SRC:
+               switch (data[1]) {
+               case 0: /* internal */
+                       devpriv->ai_et_CntrlReg &= ~Control_CNT0;
+                       break;
+               case 1: /* external */
+                       devpriv->ai_et_CntrlReg |= Control_CNT0;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               outw(devpriv->ai_et_CntrlReg, dev->iobase + PCI171x_CONTROL);
+               break;
+       case INSN_CONFIG_GET_CLOCK_SRC:
+               if (devpriv->ai_et_CntrlReg & Control_CNT0) {
+                       data[1] = 1;
+                       data[2] = 0;
+               } else {
+                       data[1] = 0;
+                       data[2] = I8254_OSC_BASE_10MHZ;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return insn->n;
+}
+
 static int pci171x_reset(struct comedi_device *dev)
 {
        const struct boardtype *board = dev->board_ptr;
        struct pci1710_private *devpriv = dev->private;
 
-       outw(0x30, dev->iobase + PCI171x_CNTCTRL);
        /* Software trigger, CNT0=external */
        devpriv->CntrlReg = Control_SW | Control_CNT0;
        /* reset any operations */
        outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
        outb(0, dev->iobase + PCI171x_CLRFIFO); /*  clear FIFO */
        outb(0, dev->iobase + PCI171x_CLRINT);  /*  clear INT request */
-       pci171x_start_pacer(dev, false);
        devpriv->da_ranges = 0;
        if (board->has_ao) {
                /* set DACs to 0..5V */
@@ -977,6 +885,11 @@ static int pci1710_auto_attach(struct comedi_device *dev,
                return ret;
        dev->iobase = pci_resource_start(pcidev, 2);
 
+       dev->pacer = comedi_8254_init(dev->iobase + PCI171X_TIMER_BASE,
+                                     I8254_OSC_BASE_10MHZ, I8254_IO16, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        n_subdevices = 0;
        if (board->n_aichan)
                n_subdevices++;
@@ -1073,16 +986,17 @@ static int pci1710_auto_attach(struct comedi_device *dev,
                subdev++;
        }
 
+       /* Counter subdevice (8254) */
        if (board->has_counter) {
                s = &dev->subdevices[subdev];
-               s->type         = COMEDI_SUBD_COUNTER;
-               s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-               s->n_chan       = 1;
-               s->maxdata      = 0xffff;
-               s->range_table  = &range_unknown;
-               s->insn_read    = pci171x_counter_insn_read;
-               s->insn_write   = pci171x_counter_insn_write;
-               s->insn_config  = pci171x_counter_insn_config;
+               comedi_8254_subdevice_init(s, dev->pacer);
+
+               dev->pacer->insn_config = pci171x_insn_counter_config;
+
+               /* counters 1 and 2 are used internally for the pacer */
+               comedi_8254_set_busy(dev->pacer, 1, true);
+               comedi_8254_set_busy(dev->pacer, 2, true);
+
                subdev++;
        }
 
index f1945be89eff1468425b981550d185338b1a6ff8..1921a97cc5ca3b7d18c26dd1bbe8bd717cf189b2 100644 (file)
@@ -41,9 +41,8 @@
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 /*
  * PCI Bar 2 I/O Register map (dev->iobase)
index a3573ea6f9c0f77b00447bf8b3ebd81f048b377e..f7a7dab013db152bb7bfca43177eb350bb67ae46 100644 (file)
@@ -47,9 +47,8 @@
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 /*
  * PCI bar 2 Register I/O map (dev->iobase)
index 09609d6d02da283210493b9c25ed981ccd693e88..456e87013063e73eaf35724f2310d76ea6cdf50f 100644 (file)
@@ -30,13 +30,12 @@ Configuration options:
 */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #include "8255.h"
-#include "8253.h"
+#include "comedi_8254.h"
 
 /* hardware types of the cards */
 enum hw_cards_id {
@@ -60,12 +59,6 @@ enum hw_io_access {
 #define MAX_DO_SUBDEVS 2       /* max number of DO subdevices per card */
 #define MAX_DIO_SUBDEVG        2       /* max number of DIO subdevices group per
                                 * card */
-#define MAX_8254_SUBDEVS   1   /* max number of 8254 counter subdevs per
-                                * card */
-                               /* (could be more than one 8254 per
-                                * subdevice) */
-
-#define SIZE_8254         4    /* 8254 IO space length */
 
 #define PCIDIO_MAINREG    2    /* main I/O region for all Advantech cards? */
 
@@ -230,7 +223,7 @@ struct diosubd_data {
        int chans;              /*  num of chans */
        int addr;               /*  PCI address ofset */
        int regs;               /*  number of registers to read or 8255
-                                   subdevices or 8254 chips */
+                                   subdevices */
        unsigned int specflags; /*  addon subdevice flags */
 };
 
@@ -243,7 +236,7 @@ struct dio_boardtype {
        struct diosubd_data sdo[MAX_DO_SUBDEVS];        /*  DO chans */
        struct diosubd_data sdio[MAX_DIO_SUBDEVG];      /*  DIO 8255 chans */
        struct diosubd_data boardid;    /*  card supports board ID switch */
-       struct diosubd_data s8254[MAX_8254_SUBDEVS];    /* 8254 subdevices */
+       unsigned long timer_regbase;
        enum hw_io_access io_access;
 };
 
@@ -286,7 +279,7 @@ static const struct dio_boardtype boardtypes[] = {
                .sdi[0]         = { 32, PCI1735_DI, 4, 0, },
                .sdo[0]         = { 32, PCI1735_DO, 4, 0, },
                .boardid        = { 4, PCI1735_BOARDID, 1, SDF_INTERNAL, },
-               .s8254[0]       = { 3, PCI1735_C8254, 1, 0, },
+               .timer_regbase  = PCI1735_C8254,
                .io_access      = IO_8b,
        },
        [TYPE_PCI1736] = {
@@ -322,7 +315,7 @@ static const struct dio_boardtype boardtypes[] = {
                .cardtype       = TYPE_PCI1751,
                .nsubdevs       = 3,
                .sdio[0]        = { 48, PCI1751_DIO, 2, 0, },
-               .s8254[0]       = { 3, PCI1751_CNT, 1, 0, },
+               .timer_regbase  = PCI1751_CNT,
                .io_access      = IO_8b,
        },
        [TYPE_PCI1752] = {
@@ -425,7 +418,6 @@ static int pci_dio_insn_bits_di_b(struct comedi_device *dev,
        for (i = 0; i < d->regs; i++)
                data[1] |= inb(dev->iobase + d->addr + i) << (8 * i);
 
-
        return insn->n;
 }
 
@@ -484,83 +476,6 @@ static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
        return insn->n;
 }
 
-/*
-==============================================================================
-*/
-static int pci_8254_insn_read(struct comedi_device *dev,
-                             struct comedi_subdevice *s,
-                             struct comedi_insn *insn, unsigned int *data)
-{
-       const struct diosubd_data *d = (const struct diosubd_data *)s->private;
-       unsigned int chan, chip, chipchan;
-       unsigned long flags;
-
-       chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
-       chip = chan / 3;                /* chip on subdevice */
-       chipchan = chan - (3 * chip);   /* channel on chip on subdevice */
-       spin_lock_irqsave(&s->spin_lock, flags);
-       data[0] = i8254_read(dev->iobase + d->addr + (SIZE_8254 * chip),
-                       0, chipchan);
-       spin_unlock_irqrestore(&s->spin_lock, flags);
-       return 1;
-}
-
-/*
-==============================================================================
-*/
-static int pci_8254_insn_write(struct comedi_device *dev,
-                              struct comedi_subdevice *s,
-                              struct comedi_insn *insn, unsigned int *data)
-{
-       const struct diosubd_data *d = (const struct diosubd_data *)s->private;
-       unsigned int chan, chip, chipchan;
-       unsigned long flags;
-
-       chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
-       chip = chan / 3;                /* chip on subdevice */
-       chipchan = chan - (3 * chip);   /* channel on chip on subdevice */
-       spin_lock_irqsave(&s->spin_lock, flags);
-       i8254_write(dev->iobase + d->addr + (SIZE_8254 * chip),
-                       0, chipchan, data[0]);
-       spin_unlock_irqrestore(&s->spin_lock, flags);
-       return 1;
-}
-
-/*
-==============================================================================
-*/
-static int pci_8254_insn_config(struct comedi_device *dev,
-                               struct comedi_subdevice *s,
-                               struct comedi_insn *insn, unsigned int *data)
-{
-       const struct diosubd_data *d = (const struct diosubd_data *)s->private;
-       unsigned int chan, chip, chipchan;
-       unsigned long iobase;
-       int ret = 0;
-       unsigned long flags;
-
-       chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
-       chip = chan / 3;                /* chip on subdevice */
-       chipchan = chan - (3 * chip);   /* channel on chip on subdevice */
-       iobase = dev->iobase + d->addr + (SIZE_8254 * chip);
-       spin_lock_irqsave(&s->spin_lock, flags);
-       switch (data[0]) {
-       case INSN_CONFIG_SET_COUNTER_MODE:
-               ret = i8254_set_mode(iobase, 0, chipchan, data[1]);
-               if (ret < 0)
-                       ret = -EINVAL;
-               break;
-       case INSN_CONFIG_8254_READ_STATUS:
-               data[1] = i8254_status(iobase, 0, chipchan);
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-       spin_unlock_irqrestore(&s->spin_lock, flags);
-       return ret < 0 ? ret : insn->n;
-}
-
 /*
 ==============================================================================
 */
@@ -845,9 +760,6 @@ static int pci_dio_reset(struct comedi_device *dev)
                outb(0, dev->iobase + PCI1735_DO + 1);
                outb(0, dev->iobase + PCI1735_DO + 2);
                outb(0, dev->iobase + PCI1735_DO + 3);
-               i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 0, I8254_MODE0);
-               i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 1, I8254_MODE0);
-               i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 2, I8254_MODE0);
                break;
 
        case TYPE_PCI1736:
@@ -1029,26 +941,6 @@ static int pci_dio_add_do(struct comedi_device *dev,
        return 0;
 }
 
-/*
-==============================================================================
-*/
-static int pci_dio_add_8254(struct comedi_device *dev,
-                           struct comedi_subdevice *s,
-                           const struct diosubd_data *d)
-{
-       s->type = COMEDI_SUBD_COUNTER;
-       s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-       s->n_chan = d->chans;
-       s->maxdata = 65535;
-       s->len_chanlist = d->chans;
-       s->insn_read = pci_8254_insn_read;
-       s->insn_write = pci_8254_insn_write;
-       s->insn_config = pci_8254_insn_config;
-       s->private = (void *)d;
-
-       return 0;
-}
-
 static unsigned long pci_dio_override_cardtype(struct pci_dev *pcidev,
                                               unsigned long cardtype)
 {
@@ -1144,12 +1036,19 @@ static int pci_dio_auto_attach(struct comedi_device *dev,
                subdev++;
        }
 
-       for (i = 0; i < MAX_8254_SUBDEVS; i++)
-               if (this_board->s8254[i].chans) {
-                       s = &dev->subdevices[subdev];
-                       pci_dio_add_8254(dev, s, &this_board->s8254[i]);
-                       subdev++;
-               }
+       if (this_board->timer_regbase) {
+               s = &dev->subdevices[subdev];
+
+               dev->pacer = comedi_8254_init(dev->iobase +
+                                             this_board->timer_regbase,
+                                             0, I8254_IO8, 0);
+               if (!dev->pacer)
+                       return -ENOMEM;
+
+               comedi_8254_subdevice_init(s, dev->pacer);
+
+               subdev++;
+       }
 
        if (this_board->cardtype == TYPE_PCI1760)
                pci1760_attach(dev);
index 1c7b325a373cb8141b67a5de47617f2cc6b42c41..35b2f98f0de951a93b069cf450c8cac4e7dfc517 100644 (file)
@@ -42,8 +42,6 @@
 
 #include "../comedidev.h"
 
-#include "comedi_fc.h"
-
 #define AIO_IIRO_16_RELAY_0_7          0x00
 #define AIO_IIRO_16_INPUT_0_7          0x01
 #define AIO_IIRO_16_IRQ                        0x02
@@ -116,11 +114,11 @@ static int aio_iiro_16_cos_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);
 
        if (err)
                return 1;
@@ -130,11 +128,12 @@ static int aio_iiro_16_cos_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-       err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
index 26aad705aad30d83539dc704d9deacff8ee78b68..d15a3dc1216a0a8bc073c469c4a2e3e01e4f597a 100644 (file)
 #include "../comedidev.h"
 
 #include "amplc_dio200.h"
-#include "comedi_fc.h"
-#include "8253.h"
+#include "comedi_8254.h"
 #include "8255.h"              /* only for register defines */
 
 /* 200 series registers */
 #define DIO200_IO_SIZE         0x20
 #define DIO200_PCIE_IO_SIZE    0x4000
-#define DIO200_XCLK_SCE                0x18    /* Group X clock selection register */
-#define DIO200_YCLK_SCE                0x19    /* Group Y clock selection register */
-#define DIO200_ZCLK_SCE                0x1a    /* Group Z clock selection register */
-#define DIO200_XGAT_SCE                0x1b    /* Group X gate selection register */
-#define DIO200_YGAT_SCE                0x1c    /* Group Y gate selection register */
-#define DIO200_ZGAT_SCE                0x1d    /* Group Z gate selection register */
+#define DIO200_CLK_SCE(x)      (0x18 + (x))    /* Group X/Y/Z clock sel reg */
+#define DIO200_GAT_SCE(x)      (0x1b + (x))    /* Group X/Y/Z gate sel reg */
 #define DIO200_INT_SCE         0x1e    /* Interrupt enable/status register */
 /* Extra registers for new PCIe boards */
 #define DIO200_ENHANCE         0x20    /* 1 to enable enhanced features */
@@ -101,16 +96,6 @@ static const unsigned int ts_clock_period[TS_CONFIG_MAX_CLK_SRC + 1] = {
        1000000,                /* 1 millisecond. */
 };
 
-struct dio200_subdev_8254 {
-       unsigned int ofs;               /* Counter base offset */
-       unsigned int clk_sce_ofs;       /* CLK_SCE base address */
-       unsigned int gat_sce_ofs;       /* GAT_SCE base address */
-       int which;                      /* Bit 5 of CLK_SCE or GAT_SCE */
-       unsigned int clock_src[3];      /* Current clock sources */
-       unsigned int gate_src[3];       /* Current gate sources */
-       spinlock_t spinlock;
-};
-
 struct dio200_subdev_8255 {
        unsigned int ofs;               /* DIO base offset */
 };
@@ -177,6 +162,27 @@ static void dio200_write32(struct comedi_device *dev,
                outl(val, dev->iobase + offset);
 }
 
+static unsigned int dio200_subdev_8254_offset(struct comedi_device *dev,
+                                             struct comedi_subdevice *s)
+{
+       const struct dio200_board *board = dev->board_ptr;
+       struct comedi_8254 *i8254 = s->private;
+       unsigned int offset;
+
+       /* get the offset that was passed to comedi_8254_*_init() */
+       if (dev->mmio)
+               offset = i8254->mmio - dev->mmio;
+       else
+               offset = i8254->iobase - dev->iobase;
+
+       /* remove the shift that was added for PCIe boards */
+       if (board->is_pcie)
+               offset >>= 3;
+
+       /* this offset now works for the dio200_{read,write} helpers */
+       return offset;
+}
+
 static int dio200_subdev_intr_insn_bits(struct comedi_device *dev,
                                        struct comedi_subdevice *s,
                                        struct comedi_insn *insn,
@@ -366,19 +372,19 @@ static int dio200_subdev_intr_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -387,15 +393,16 @@ static int dio200_subdev_intr_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -482,175 +489,26 @@ static irqreturn_t dio200_interrupt(int irq, void *d)
        return IRQ_RETVAL(handled);
 }
 
-static unsigned int dio200_subdev_8254_read_chan(struct comedi_device *dev,
-                                                struct comedi_subdevice *s,
-                                                unsigned int chan)
-{
-       struct dio200_subdev_8254 *subpriv = s->private;
-       unsigned int val;
-
-       /* latch counter */
-       val = chan << 6;
-       dio200_write8(dev, subpriv->ofs + i8254_control_reg, val);
-       /* read lsb, msb */
-       val = dio200_read8(dev, subpriv->ofs + chan);
-       val += dio200_read8(dev, subpriv->ofs + chan) << 8;
-       return val;
-}
-
-static void dio200_subdev_8254_write_chan(struct comedi_device *dev,
-                                         struct comedi_subdevice *s,
-                                         unsigned int chan,
-                                         unsigned int count)
-{
-       struct dio200_subdev_8254 *subpriv = s->private;
-
-       /* write lsb, msb */
-       dio200_write8(dev, subpriv->ofs + chan, count & 0xff);
-       dio200_write8(dev, subpriv->ofs + chan, (count >> 8) & 0xff);
-}
-
-static void dio200_subdev_8254_set_mode(struct comedi_device *dev,
-                                       struct comedi_subdevice *s,
-                                       unsigned int chan,
-                                       unsigned int mode)
-{
-       struct dio200_subdev_8254 *subpriv = s->private;
-       unsigned int byte;
-
-       byte = chan << 6;
-       byte |= 0x30;           /* access order: lsb, msb */
-       byte |= (mode & 0xf);   /* counter mode and BCD|binary */
-       dio200_write8(dev, subpriv->ofs + i8254_control_reg, byte);
-}
-
-static unsigned int dio200_subdev_8254_status(struct comedi_device *dev,
-                                             struct comedi_subdevice *s,
-                                             unsigned int chan)
-{
-       struct dio200_subdev_8254 *subpriv = s->private;
-
-       /* latch status */
-       dio200_write8(dev, subpriv->ofs + i8254_control_reg,
-                     0xe0 | (2 << chan));
-       /* read status */
-       return dio200_read8(dev, subpriv->ofs + chan);
-}
-
-static int dio200_subdev_8254_read(struct comedi_device *dev,
-                                  struct comedi_subdevice *s,
-                                  struct comedi_insn *insn,
-                                  unsigned int *data)
-{
-       struct dio200_subdev_8254 *subpriv = s->private;
-       int chan = CR_CHAN(insn->chanspec);
-       unsigned int n;
-       unsigned long flags;
-
-       for (n = 0; n < insn->n; n++) {
-               spin_lock_irqsave(&subpriv->spinlock, flags);
-               data[n] = dio200_subdev_8254_read_chan(dev, s, chan);
-               spin_unlock_irqrestore(&subpriv->spinlock, flags);
-       }
-       return insn->n;
-}
-
-static int dio200_subdev_8254_write(struct comedi_device *dev,
-                                   struct comedi_subdevice *s,
-                                   struct comedi_insn *insn,
-                                   unsigned int *data)
-{
-       struct dio200_subdev_8254 *subpriv = s->private;
-       int chan = CR_CHAN(insn->chanspec);
-       unsigned int n;
-       unsigned long flags;
-
-       for (n = 0; n < insn->n; n++) {
-               spin_lock_irqsave(&subpriv->spinlock, flags);
-               dio200_subdev_8254_write_chan(dev, s, chan, data[n]);
-               spin_unlock_irqrestore(&subpriv->spinlock, flags);
-       }
-       return insn->n;
-}
-
-static int dio200_subdev_8254_set_gate_src(struct comedi_device *dev,
-                                          struct comedi_subdevice *s,
-                                          unsigned int counter_number,
-                                          unsigned int gate_src)
-{
-       const struct dio200_board *board = dev->board_ptr;
-       struct dio200_subdev_8254 *subpriv = s->private;
-       unsigned char byte;
-
-       if (!board->has_clk_gat_sce)
-               return -1;
-       if (counter_number > 2)
-               return -1;
-       if (gate_src > (board->is_pcie ? 31 : 7))
-               return -1;
-
-       subpriv->gate_src[counter_number] = gate_src;
-       byte = gat_sce(subpriv->which, counter_number, gate_src);
-       dio200_write8(dev, subpriv->gat_sce_ofs, byte);
-
-       return 0;
-}
-
-static int dio200_subdev_8254_get_gate_src(struct comedi_device *dev,
-                                          struct comedi_subdevice *s,
-                                          unsigned int counter_number)
-{
-       const struct dio200_board *board = dev->board_ptr;
-       struct dio200_subdev_8254 *subpriv = s->private;
-
-       if (!board->has_clk_gat_sce)
-               return -1;
-       if (counter_number > 2)
-               return -1;
-
-       return subpriv->gate_src[counter_number];
-}
-
-static int dio200_subdev_8254_set_clock_src(struct comedi_device *dev,
+static void dio200_subdev_8254_set_gate_src(struct comedi_device *dev,
                                            struct comedi_subdevice *s,
-                                           unsigned int counter_number,
-                                           unsigned int clock_src)
+                                           unsigned int chan,
+                                           unsigned int src)
 {
-       const struct dio200_board *board = dev->board_ptr;
-       struct dio200_subdev_8254 *subpriv = s->private;
-       unsigned char byte;
-
-       if (!board->has_clk_gat_sce)
-               return -1;
-       if (counter_number > 2)
-               return -1;
-       if (clock_src > (board->is_pcie ? 31 : 7))
-               return -1;
-
-       subpriv->clock_src[counter_number] = clock_src;
-       byte = clk_sce(subpriv->which, counter_number, clock_src);
-       dio200_write8(dev, subpriv->clk_sce_ofs, byte);
+       unsigned int offset = dio200_subdev_8254_offset(dev, s);
 
-       return 0;
+       dio200_write8(dev, DIO200_GAT_SCE(offset >> 3),
+                     gat_sce((offset >> 2) & 1, chan, src));
 }
 
-static int dio200_subdev_8254_get_clock_src(struct comedi_device *dev,
-                                           struct comedi_subdevice *s,
-                                           unsigned int counter_number,
-                                           unsigned int *period_ns)
+static void dio200_subdev_8254_set_clock_src(struct comedi_device *dev,
+                                            struct comedi_subdevice *s,
+                                            unsigned int chan,
+                                            unsigned int src)
 {
-       const struct dio200_board *board = dev->board_ptr;
-       struct dio200_subdev_8254 *subpriv = s->private;
-       unsigned clock_src;
-
-       if (!board->has_clk_gat_sce)
-               return -1;
-       if (counter_number > 2)
-               return -1;
+       unsigned int offset = dio200_subdev_8254_offset(dev, s);
 
-       clock_src = subpriv->clock_src[counter_number];
-       *period_ns = clock_period[clock_src];
-       return clock_src;
+       dio200_write8(dev, DIO200_CLK_SCE(offset >> 3),
+                     clk_sce((offset >> 2) & 1, chan, src));
 }
 
 static int dio200_subdev_8254_config(struct comedi_device *dev,
@@ -658,54 +516,44 @@ static int dio200_subdev_8254_config(struct comedi_device *dev,
                                     struct comedi_insn *insn,
                                     unsigned int *data)
 {
-       struct dio200_subdev_8254 *subpriv = s->private;
-       int ret = 0;
-       int chan = CR_CHAN(insn->chanspec);
-       unsigned long flags;
+       const struct dio200_board *board = dev->board_ptr;
+       struct comedi_8254 *i8254 = s->private;
+       unsigned int chan = CR_CHAN(insn->chanspec);
+       unsigned int max_src = board->is_pcie ? 31 : 7;
+       unsigned int src;
+
+       if (!board->has_clk_gat_sce)
+               return -EINVAL;
 
-       spin_lock_irqsave(&subpriv->spinlock, flags);
        switch (data[0]) {
-       case INSN_CONFIG_SET_COUNTER_MODE:
-               if (data[1] > (I8254_MODE5 | I8254_BCD))
-                       ret = -EINVAL;
-               else
-                       dio200_subdev_8254_set_mode(dev, s, chan, data[1]);
-               break;
-       case INSN_CONFIG_8254_READ_STATUS:
-               data[1] = dio200_subdev_8254_status(dev, s, chan);
-               break;
        case INSN_CONFIG_SET_GATE_SRC:
-               ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]);
-               if (ret < 0)
-                       ret = -EINVAL;
+               src = data[2];
+               if (src > max_src)
+                       return -EINVAL;
+
+               dio200_subdev_8254_set_gate_src(dev, s, chan, src);
+               i8254->gate_src[chan] = src;
                break;
        case INSN_CONFIG_GET_GATE_SRC:
-               ret = dio200_subdev_8254_get_gate_src(dev, s, chan);
-               if (ret < 0) {
-                       ret = -EINVAL;
-                       break;
-               }
-               data[2] = ret;
+               data[2] = i8254->gate_src[chan];
                break;
        case INSN_CONFIG_SET_CLOCK_SRC:
-               ret = dio200_subdev_8254_set_clock_src(dev, s, chan, data[1]);
-               if (ret < 0)
-                       ret = -EINVAL;
+               src = data[1];
+               if (src > max_src)
+                       return -EINVAL;
+
+               dio200_subdev_8254_set_clock_src(dev, s, chan, src);
+               i8254->clock_src[chan] = src;
                break;
        case INSN_CONFIG_GET_CLOCK_SRC:
-               ret = dio200_subdev_8254_get_clock_src(dev, s, chan, &data[2]);
-               if (ret < 0) {
-                       ret = -EINVAL;
-                       break;
-               }
-               data[1] = ret;
+               data[1] = i8254->clock_src[chan];
+               data[2] = clock_period[i8254->clock_src[chan]];
                break;
        default:
-               ret = -EINVAL;
-               break;
+               return -EINVAL;
        }
-       spin_unlock_irqrestore(&subpriv->spinlock, flags);
-       return ret < 0 ? ret : insn->n;
+
+       return insn->n;
 }
 
 static int dio200_subdev_8254_init(struct comedi_device *dev,
@@ -713,36 +561,46 @@ static int dio200_subdev_8254_init(struct comedi_device *dev,
                                   unsigned int offset)
 {
        const struct dio200_board *board = dev->board_ptr;
-       struct dio200_subdev_8254 *subpriv;
-       unsigned int chan;
+       struct comedi_8254 *i8254;
+       unsigned int regshift;
+       int chan;
+
+       /*
+        * PCIe boards need the offset shifted in order to get the
+        * correct base address of the timer.
+        */
+       if (board->is_pcie) {
+               offset <<= 3;
+               regshift = 3;
+       } else {
+               regshift = 0;
+       }
 
-       subpriv = comedi_alloc_spriv(s, sizeof(*subpriv));
-       if (!subpriv)
+       if (dev->mmio)
+               i8254 = comedi_8254_mm_init(dev->mmio + offset,
+                                           0, I8254_IO8, regshift);
+       else
+               i8254 = comedi_8254_init(dev->iobase + offset,
+                                        0, I8254_IO8, regshift);
+       if (!i8254)
                return -ENOMEM;
 
-       s->type = COMEDI_SUBD_COUNTER;
-       s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-       s->n_chan = 3;
-       s->maxdata = 0xFFFF;
-       s->insn_read = dio200_subdev_8254_read;
-       s->insn_write = dio200_subdev_8254_write;
-       s->insn_config = dio200_subdev_8254_config;
+       comedi_8254_subdevice_init(s, i8254);
 
-       spin_lock_init(&subpriv->spinlock);
-       subpriv->ofs = offset;
-       if (board->has_clk_gat_sce) {
-               /* Derive CLK_SCE and GAT_SCE register offsets from
-                * 8254 offset. */
-               subpriv->clk_sce_ofs = DIO200_XCLK_SCE + (offset >> 3);
-               subpriv->gat_sce_ofs = DIO200_XGAT_SCE + (offset >> 3);
-               subpriv->which = (offset >> 2) & 1;
-       }
+       i8254->insn_config = dio200_subdev_8254_config;
+
+       /*
+        * There could be multiple timers so this driver does not
+        * use dev->pacer to save the i8254 pointer. Instead,
+        * comedi_8254_subdevice_init() saved the i8254 pointer in
+        * s->private. Set the runflag bit so that the core will
+        * automatically free it when the driver is detached.
+        */
+       s->runflags |= COMEDI_SRF_FREE_SPRIV;
 
        /* Initialize channels. */
-       for (chan = 0; chan < 3; chan++) {
-               dio200_subdev_8254_set_mode(dev, s, chan,
-                                           I8254_MODE0 | I8254_BINARY);
-               if (board->has_clk_gat_sce) {
+       if (board->has_clk_gat_sce) {
+               for (chan = 0; chan < 3; chan++) {
                        /* Gate source 0 is VCC (logic 1). */
                        dio200_subdev_8254_set_gate_src(dev, s, chan, 0);
                        /* Clock source 0 is the dedicated clock input. */
index b83d1f5a8fb999395dbaa34789e3daeeddfe4079..d9850c917163ae426385a3bed28dac254fbdcb27 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #include "amplc_dio200.h"
 
index be87172d1f3f22de766dfb4de9785e2f147bd291..245f932a75a8fd60bb0c3fba459b650518fbb89d 100644 (file)
@@ -24,7 +24,6 @@
 #include "../comedidev.h"
 
 #include "amplc_pc236.h"
-#include "comedi_fc.h"
 #include "8255.h"
 
 static void pc236_intr_update(struct comedi_device *dev, bool enable)
@@ -82,11 +81,11 @@ static int pc236_intr_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);
 
        if (err)
                return 1;
@@ -96,11 +95,12 @@ static int pc236_intr_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check it arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-       err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -195,7 +195,6 @@ static void __exit amplc_pc236_common_exit(void)
 }
 module_exit(amplc_pc236_common_exit);
 
-
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi helper for amplc_pc236 and amplc_pci236");
 MODULE_LICENSE("GPL");
index 924c8298c7a04b4ad3fdb7868bae1a0f49e19e23..08a91854837ab183c307bdfb0c94dab09afcf46e 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
-#include "comedi_fc.h"
-#include "8253.h"
+#include "comedi_8254.h"
 
 /*
  * PCI224/234 i/o space 1 (PCIBAR2) registers.
  */
-#define PCI224_Z2_CT0  0x14    /* 82C54 counter/timer 0 */
-#define PCI224_Z2_CT1  0x15    /* 82C54 counter/timer 1 */
-#define PCI224_Z2_CT2  0x16    /* 82C54 counter/timer 2 */
-#define PCI224_Z2_CTC  0x17    /* 82C54 counter/timer control word */
+#define PCI224_Z2_BASE 0x14    /* 82C54 counter/timer */
 #define PCI224_ZCLK_SCE        0x1A    /* Group Z Clock Configuration Register */
 #define PCI224_ZGAT_SCE        0x1D    /* Group Z Gate Configuration Register */
 #define PCI224_INT_SCE 0x1E    /* ISR Interrupt source mask register */
@@ -379,8 +374,6 @@ struct pci224_private {
        int intr_cpuid;
        short intr_running;
        unsigned short daccon;
-       unsigned int cached_div1;
-       unsigned int cached_div2;
        unsigned short ao_enab; /* max 16 channels so 'short' will do */
        unsigned char intsce;
 };
@@ -451,7 +444,6 @@ static void pci224_ao_stop(struct comedi_device *dev,
        if (!test_and_clear_bit(AO_CMD_STARTED, &devpriv->state))
                return;
 
-
        spin_lock_irqsave(&devpriv->ao_spinlock, flags);
        /* Kill the interrupts. */
        devpriv->intsce = 0;
@@ -668,28 +660,27 @@ static int
 pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
                  struct comedi_cmd *cmd)
 {
-       struct pci224_private *devpriv = dev->private;
        int err = 0;
        unsigned int arg;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
-                                    TRIG_EXT | TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src,
-                                    TRIG_COUNT | TRIG_EXT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
+                                       TRIG_EXT | 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_EXT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -714,7 +705,7 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
        switch (cmd->start_src) {
        case TRIG_INT:
-               err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
                break;
        case TRIG_EXT:
                /* Force to external trigger 0. */
@@ -734,13 +725,13 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
        switch (cmd->scan_begin_src) {
        case TRIG_TIMER:
-               err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
-                                                MAX_SCAN_PERIOD);
+               err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
+                                                   MAX_SCAN_PERIOD);
 
                arg = cmd->chanlist_len * CONVERT_PERIOD;
                if (arg < MIN_SCAN_PERIOD)
                        arg = MIN_SCAN_PERIOD;
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
                break;
        case TRIG_EXT:
                /* Force to external trigger 0. */
@@ -760,12 +751,13 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
                break;
        }
 
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        switch (cmd->stop_src) {
        case TRIG_COUNT:
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
                break;
        case TRIG_EXT:
                /* Force to external trigger 0. */
@@ -781,7 +773,7 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
                }
                break;
        case TRIG_NONE:
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
                break;
        }
 
@@ -793,11 +785,8 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
        if (cmd->scan_begin_src == TRIG_TIMER) {
                arg = cmd->scan_begin_arg;
                /* Use two timers. */
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
-                                         &devpriv->cached_div1,
-                                         &devpriv->cached_div2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
 
        if (err)
@@ -817,7 +806,6 @@ static void pci224_ao_start_pacer(struct comedi_device *dev,
                                  struct comedi_subdevice *s)
 {
        struct pci224_private *devpriv = dev->private;
-       unsigned long timer_base = devpriv->iobase1 + PCI224_Z2_CT0;
 
        /*
         * The output of timer Z2-0 will be used as the scan trigger
@@ -830,14 +818,10 @@ static void pci224_ao_start_pacer(struct comedi_device *dev,
        outb(GAT_CONFIG(2, GAT_VCC), devpriv->iobase1 + PCI224_ZGAT_SCE);
        /* Z2-2 needs 10 MHz clock. */
        outb(CLK_CONFIG(2, CLK_10MHZ), devpriv->iobase1 + PCI224_ZCLK_SCE);
-       /* Load Z2-2 mode (2) and counter (div1). */
-       i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
-       i8254_write(timer_base, 0, 2, devpriv->cached_div1);
        /* Z2-0 is clocked from Z2-2's output. */
        outb(CLK_CONFIG(0, CLK_OUTNM1), devpriv->iobase1 + PCI224_ZCLK_SCE);
-       /* Load Z2-0 mode (2) and counter (div2). */
-       i8254_set_mode(timer_base, 0, 0, I8254_MODE2 | I8254_BINARY);
-       i8254_write(timer_base, 0, 0, devpriv->cached_div2);
+
+       comedi_8254_pacer_enable(dev->pacer, 2, 0, false);
 }
 
 static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
@@ -852,10 +836,9 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        unsigned long flags;
 
        /* Cannot handle null/empty chanlist. */
-       if (cmd->chanlist == NULL || cmd->chanlist_len == 0)
+       if (!cmd->chanlist || cmd->chanlist_len == 0)
                return -EINVAL;
 
-
        /* Determine which channels are enabled and their load order.  */
        devpriv->ao_enab = 0;
 
@@ -893,8 +876,10 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
             dev->iobase + PCI224_DACCON);
 
-       if (cmd->scan_begin_src == TRIG_TIMER)
+       if (cmd->scan_begin_src == TRIG_TIMER) {
+               comedi_8254_update_divisors(dev->pacer);
                pci224_ao_start_pacer(dev, s);
+       }
 
        spin_lock_irqsave(&devpriv->ao_spinlock, flags);
        if (cmd->start_src == TRIG_INT) {
@@ -1042,14 +1027,12 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_model)
        if (!devpriv->ao_scan_vals)
                return -ENOMEM;
 
-
        /* Allocate buffer to hold AO channel scan order. */
        devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) *
                                         thisboard->ao_chans, GFP_KERNEL);
        if (!devpriv->ao_scan_order)
                return -ENOMEM;
 
-
        /* Disable interrupt sources. */
        devpriv->intsce = 0;
        outb(0, devpriv->iobase1 + PCI224_INT_SCE);
@@ -1063,6 +1046,11 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_model)
        outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
             dev->iobase + PCI224_DACCON);
 
+       dev->pacer = comedi_8254_init(devpriv->iobase1 + PCI224_Z2_BASE,
+                                     I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        ret = comedi_alloc_subdevices(dev, 1);
        if (ret)
                return ret;
index 49806a5e514c71faa0a8be2d569186b432c89445..20d592002557a36c49b52937a31df2fa6a3fbd06 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
-#include "comedi_fc.h"
-#include "8253.h"
+#include "comedi_8254.h"
 #include "8255.h"
 
 /*
 #define PCI230_PPI_X_C         0x02    /* User PPI (82C55) port C */
 #define PCI230_PPI_X_CMD       0x03    /* User PPI (82C55) control word */
 #define PCI230_Z2_CT_BASE      0x14    /* 82C54 counter/timer base */
-#define PCI230_Z2_CT0          0x14    /* 82C54 counter/timer 0 */
-#define PCI230_Z2_CT1          0x15    /* 82C54 counter/timer 1 */
-#define PCI230_Z2_CT2          0x16    /* 82C54 counter/timer 2 */
-#define PCI230_Z2_CTC          0x17    /* 82C54 counter/timer control word */
 #define PCI230_ZCLK_SCE                0x1A    /* Group Z Clock Configuration */
 #define PCI230_ZGAT_SCE                0x1D    /* Group Z Gate Configuration */
 #define PCI230_INT_SCE         0x1E    /* Interrupt source mask (w) */
 #define CLK_EXT                7       /* external clock */
 /* Macro to construct clock input configuration register value. */
 #define CLK_CONFIG(chan, src)  ((((chan) & 3) << 3) | ((src) & 7))
-/* Timebases in ns. */
-#define TIMEBASE_10MHZ         100
-#define TIMEBASE_1MHZ          1000
-#define TIMEBASE_100KHZ                10000
-#define TIMEBASE_10KHZ         100000
-#define TIMEBASE_1KHZ          1000000
 
 /*
  * Counter/timer gate input configuration sources.
@@ -507,11 +495,11 @@ struct pci230_private {
 
 /* PCI230 clock source periods in ns */
 static const unsigned int pci230_timebase[8] = {
-       [CLK_10MHZ] = TIMEBASE_10MHZ,
-       [CLK_1MHZ] = TIMEBASE_1MHZ,
-       [CLK_100KHZ] = TIMEBASE_100KHZ,
-       [CLK_10KHZ] = TIMEBASE_10KHZ,
-       [CLK_1KHZ] = TIMEBASE_1KHZ,
+       [CLK_10MHZ]     = I8254_OSC_BASE_10MHZ,
+       [CLK_1MHZ]      = I8254_OSC_BASE_1MHZ,
+       [CLK_100KHZ]    = I8254_OSC_BASE_100KHZ,
+       [CLK_10KHZ]     = I8254_OSC_BASE_10KHZ,
+       [CLK_1KHZ]      = I8254_OSC_BASE_1KHZ,
 };
 
 /* PCI230 analogue input range table */
@@ -695,7 +683,7 @@ static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
        unsigned int count;
 
        /* Set mode. */
-       i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, ct, mode);
+       comedi_8254_set_mode(dev->pacer, ct, mode);
        /* Determine clock source and count. */
        clk_src = pci230_choose_clk_count(ns, &count, flags);
        /* Program clock source. */
@@ -704,13 +692,13 @@ static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
        if (count >= 65536)
                count = 0;
 
-       i8254_write(dev->iobase + PCI230_Z2_CT_BASE, 0, ct, count);
+       comedi_8254_write(dev->pacer, ct, count);
 }
 
 static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct)
 {
-       i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, ct, I8254_MODE1);
        /* Counter ct, 8254 mode 1, initial count not written. */
+       comedi_8254_set_mode(dev->pacer, ct, I8254_MODE1);
 }
 
 static int pci230_ai_eoc(struct comedi_device *dev,
@@ -760,7 +748,7 @@ static int pci230_ai_insn_read(struct comedi_device *dev,
         */
        adccon = PCI230_ADC_TRIG_Z2CT2 | PCI230_ADC_FIFO_EN;
        /* Set Z2-CT2 output low to avoid any false triggers. */
-       i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
+       comedi_8254_set_mode(dev->pacer, 2, I8254_MODE0);
        devpriv->ai_bipolar = comedi_range_is_bipolar(s, range);
        if (aref == AREF_DIFF) {
                /* Differential. */
@@ -811,10 +799,8 @@ static int pci230_ai_insn_read(struct comedi_device *dev,
                 * Trigger conversion by toggling Z2-CT2 output
                 * (finish with output high).
                 */
-               i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0,
-                              2, I8254_MODE0);
-               i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0,
-                              2, I8254_MODE1);
+               comedi_8254_set_mode(dev->pacer, 2, I8254_MODE0);
+               comedi_8254_set_mode(dev->pacer, 2, I8254_MODE1);
 
                /* wait for conversion to end */
                ret = comedi_timeout(dev, s, insn, pci230_ai_eoc, 0);
@@ -898,7 +884,7 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT);
 
        tmp = TRIG_TIMER | TRIG_INT;
        if (thisboard->min_hwver > 0 && devpriv->hwver >= 2) {
@@ -918,19 +904,19 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
                 */
                tmp |= TRIG_EXT;
        }
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, tmp);
 
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -939,7 +925,7 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
 #define MAX_SPEED_AO   8000    /* 8000 ns => 125 kHz */
 /*
@@ -950,10 +936,10 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
 
        switch (cmd->scan_begin_src) {
        case TRIG_TIMER:
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                MAX_SPEED_AO);
-               err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
-                                                MIN_SPEED_AO);
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   MAX_SPEED_AO);
+               err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
+                                                   MIN_SPEED_AO);
                break;
        case TRIG_EXT:
                /*
@@ -978,16 +964,17 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
                }
                break;
        default:
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
                break;
        }
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -1520,7 +1507,7 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 
        tmp = TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
        if (thisboard->have_dio || thisboard->min_hwver > 0) {
@@ -1532,21 +1519,21 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
                 */
                tmp |= TRIG_EXT;
        }
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp);
-       err |= cfc_check_trigger_src(&cmd->convert_src,
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, tmp);
+       err |= comedi_check_trigger_src(&cmd->convert_src,
                                        TRIG_TIMER | TRIG_INT | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -1563,7 +1550,7 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
 #define MAX_SPEED_AI_SE                3200    /* PCI230 SE:   3200 ns => 312.5 kHz */
 #define MAX_SPEED_AI_DIFF      8000    /* PCI230 DIFF: 8000 ns => 125 kHz */
@@ -1598,10 +1585,10 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
                        max_speed_ai = MAX_SPEED_AI_PLUS;
                }
 
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                max_speed_ai);
-               err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
-                                                MIN_SPEED_AI);
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                   max_speed_ai);
+               err |= comedi_check_trigger_arg_max(&cmd->convert_arg,
+                                                   MIN_SPEED_AI);
        } else if (cmd->convert_src == TRIG_EXT) {
                /*
                 * external trigger
@@ -1636,18 +1623,20 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
                         * convert_arg == 0 => trigger on -ve edge.
                         * convert_arg == 1 => trigger on +ve edge.
                         */
-                       err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 1);
+                       err |= comedi_check_trigger_arg_max(&cmd->convert_arg,
+                                                           1);
                }
        } else {
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
        }
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_EXT) {
                /*
@@ -1672,7 +1661,7 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
                        err |= -EINVAL;
 
        } else {
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
        }
 
        if (err)
@@ -1767,8 +1756,8 @@ static int pci230_ai_inttrig_convert(struct comedi_device *dev,
         * Trigger conversion by toggling Z2-CT2 output.
         * Finish with output high.
         */
-       i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
-       i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
+       comedi_8254_set_mode(dev->pacer, 2, I8254_MODE0);
+       comedi_8254_set_mode(dev->pacer, 2, I8254_MODE1);
        /*
         * Delay.  Should driver be responsible for this?  An
         * alternative would be to wait until conversion is complete,
@@ -2189,7 +2178,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
         * Set counter/timer 2 output high for use as the initial start
         * conversion source.
         */
-       i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
+       comedi_8254_set_mode(dev->pacer, 2, I8254_MODE1);
 
        /*
         * Temporarily use CT2 output as conversion trigger source and
@@ -2393,7 +2382,7 @@ static int pci230_auto_attach(struct comedi_device *dev,
        spin_lock_init(&devpriv->ao_stop_spinlock);
 
        dev->board_ptr = pci230_find_pci_board(pci_dev);
-       if (dev->board_ptr == NULL) {
+       if (!dev->board_ptr) {
                dev_err(dev->class_dev,
                        "amplc_pci230: BUG! cannot determine board type!\n");
                return -EINVAL;
@@ -2481,6 +2470,11 @@ static int pci230_auto_attach(struct comedi_device *dev,
                        dev->irq = pci_dev->irq;
        }
 
+       dev->pacer = comedi_8254_init(dev->iobase + PCI230_Z2_CT_BASE,
+                                     0, I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        rc = comedi_alloc_subdevices(dev, 3);
        if (rc)
                return rc;
index ad1e93dd13a0132b88c2cf0be405236139d5e4f7..31cc38b4bcadf6154445e4a951074f05123991db 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #include "amplc_pc236.h"
 #include "plx9052.h"
index 0d2224b832ac6665256bb8ef799d81511109f46c..b6768aa905473e32cbd559d896f5b024f31782d9 100644 (file)
@@ -33,9 +33,8 @@ The state of the outputs can be read.
 */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 static int pci263_do_insn_bits(struct comedi_device *dev,
                               struct comedi_subdevice *s,
index 1079b6c72b15d8c7034d88cc46bdc333ff8c433c..ae84f2c0cc9c3bd2569b36e1e29bed9fc9055de5 100644 (file)
@@ -30,8 +30,6 @@ Devices: [ComputerBoards] PC-CARD DAS16/16 (cb_das16_cs), PC-CARD DAS16/16-AO
 Author: ds
 Updated: Mon, 04 Nov 2002 20:04:21 -0800
 Status: experimental
-
-
 */
 
 #include <linux/module.h>
@@ -40,17 +38,13 @@ Status: experimental
 
 #include "../comedi_pcmcia.h"
 
-#include "comedi_fc.h"
-#include "8253.h"
+#include "comedi_8254.h"
 
 #define DAS16CS_ADC_DATA               0
 #define DAS16CS_DIO_MUX                        2
 #define DAS16CS_MISC1                  4
 #define DAS16CS_MISC2                  6
-#define DAS16CS_CTR0                   8
-#define DAS16CS_CTR1                   10
-#define DAS16CS_CTR2                   12
-#define DAS16CS_CTR_CONTROL            14
+#define DAS16CS_TIMER_BASE             8
 #define DAS16CS_DIO                    16
 
 struct das16cs_board {
@@ -279,6 +273,11 @@ static int das16cs_auto_attach(struct comedi_device *dev,
        if (!devpriv)
                return -ENOMEM;
 
+       dev->pacer = comedi_8254_init(dev->iobase + DAS16CS_TIMER_BASE,
+                                     I8254_OSC_BASE_10MHZ, I8254_IO16, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        ret = comedi_alloc_subdevices(dev, 3);
        if (ret)
                return ret;
index dd0c65a5b5a0a22e29098a877b0776c21f814b86..e3591a5824fe9b7a945913cc07a379261f3c7f2c 100644 (file)
@@ -62,16 +62,14 @@ analog triggering on 1602 series
 */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
-#include "8253.h"
+#include "comedi_8254.h"
 #include "8255.h"
 #include "amcc_s5933.h"
-#include "comedi_fc.h"
 
 #define AI_BUFFER_SIZE         1024    /* max ai fifo size */
 #define AO_BUFFER_SIZE         1024    /* max ao fifo size */
@@ -338,14 +336,12 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 };
 
 struct cb_pcidas_private {
+       struct comedi_8254 *ao_pacer;
        /* base addresses */
        unsigned long s5933_config;
        unsigned long control_status;
        unsigned long adc_fifo;
        unsigned long ao_registers;
-       /* divisors of master clock for analog input pacing */
-       unsigned int divisor1;
-       unsigned int divisor2;
        /* bits to write to registers */
        unsigned int adc_fifo_bits;
        unsigned int s5933_intcsr_bits;
@@ -353,9 +349,6 @@ struct cb_pcidas_private {
        /* fifo buffers */
        unsigned short ai_buffer[AI_BUFFER_SIZE];
        unsigned short ao_buffer[AO_BUFFER_SIZE];
-       /* divisors of master clock for analog output pacing */
-       unsigned int ao_divisor1;
-       unsigned int ao_divisor2;
        unsigned int calibration_source;
 };
 
@@ -530,7 +523,7 @@ static int wait_for_nvram_ready(unsigned long s5933_base_addr)
 }
 
 static int nvram_read(struct comedi_device *dev, unsigned int address,
-                       uint8_t *data)
+                     uint8_t *data)
 {
        struct cb_pcidas_private *devpriv = dev->private;
        unsigned long iobase = devpriv->s5933_config;
@@ -778,29 +771,28 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
                                struct comedi_cmd *cmd)
 {
        const struct cb_pcidas_board *thisboard = dev->board_ptr;
-       struct cb_pcidas_private *devpriv = dev->private;
        int err = 0;
        unsigned int arg;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src,
+       err |= comedi_check_trigger_src(&cmd->convert_src,
                                        TRIG_TIMER | TRIG_NOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -819,7 +811,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
 
        switch (cmd->start_src) {
        case TRIG_NOW:
-               err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
                break;
        case TRIG_EXT:
                /* External trigger, only CR_EDGE and CR_INVERT flags allowed */
@@ -836,20 +828,24 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
                break;
        }
 
-       if (cmd->scan_begin_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                               thisboard->ai_speed * cmd->chanlist_len);
+       if (cmd->scan_begin_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   thisboard->ai_speed *
+                                                   cmd->chanlist_len);
+       }
 
-       if (cmd->convert_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                thisboard->ai_speed);
+       if (cmd->convert_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                   thisboard->ai_speed);
+       }
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -858,19 +854,13 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
                arg = cmd->scan_begin_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
-                                         &devpriv->divisor1,
-                                         &devpriv->divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
        if (cmd->convert_src == TRIG_TIMER) {
                arg = cmd->convert_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
-                                         &devpriv->divisor1,
-                                         &devpriv->divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
        }
 
        if (err)
@@ -886,18 +876,6 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
        return 0;
 }
 
-static void cb_pcidas_ai_load_counters(struct comedi_device *dev)
-{
-       struct cb_pcidas_private *devpriv = dev->private;
-       unsigned long timer_base = dev->iobase + ADC8254;
-
-       i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
-
-       i8254_write(timer_base, 0, 1, devpriv->divisor1);
-       i8254_write(timer_base, 0, 2, devpriv->divisor2);
-}
-
 static int cb_pcidas_ai_cmd(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
@@ -933,8 +911,11 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev,
        outw(bits, devpriv->control_status + ADCMUX_CONT);
 
        /*  load counters */
-       if (cmd->scan_begin_src == TRIG_TIMER || cmd->convert_src == TRIG_TIMER)
-               cb_pcidas_ai_load_counters(dev);
+       if (cmd->scan_begin_src == TRIG_TIMER ||
+           cmd->convert_src == TRIG_TIMER) {
+               comedi_8254_update_divisors(dev->pacer);
+               comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
+       }
 
        /*  enable interrupts */
        spin_lock_irqsave(&dev->spinlock, flags);
@@ -1004,24 +985,23 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
        const struct cb_pcidas_board *thisboard = dev->board_ptr;
        struct cb_pcidas_private *devpriv = dev->private;
        int err = 0;
-       unsigned int arg;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -1030,18 +1010,20 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
-       if (cmd->scan_begin_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                thisboard->ao_scan_speed);
+       if (cmd->scan_begin_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   thisboard->ao_scan_speed);
+       }
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -1049,12 +1031,11 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
        /* step 4: fix up any arguments */
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
-               arg = cmd->scan_begin_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
-                                         &devpriv->ao_divisor1,
-                                         &devpriv->ao_divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               unsigned int arg = cmd->scan_begin_arg;
+
+               comedi_8254_cascade_ns_to_timer(devpriv->ao_pacer,
+                                               &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
 
        if (err)
@@ -1139,18 +1120,6 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
        return 0;
 }
 
-static void cb_pcidas_ao_load_counters(struct comedi_device *dev)
-{
-       struct cb_pcidas_private *devpriv = dev->private;
-       unsigned long timer_base = dev->iobase + DAC8254;
-
-       i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
-
-       i8254_write(timer_base, 0, 1, devpriv->ao_divisor1);
-       i8254_write(timer_base, 0, 2, devpriv->ao_divisor2);
-}
-
 static int cb_pcidas_ao_cmd(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
@@ -1180,8 +1149,10 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev,
        outw(0, devpriv->ao_registers + DACFIFOCLR);
 
        /*  load counters */
-       if (cmd->scan_begin_src == TRIG_TIMER)
-               cb_pcidas_ao_load_counters(dev);
+       if (cmd->scan_begin_src == TRIG_TIMER) {
+               comedi_8254_update_divisors(devpriv->ao_pacer);
+               comedi_8254_pacer_enable(devpriv->ao_pacer, 1, 2, true);
+       }
 
        /*  set pacer source */
        spin_lock_irqsave(&dev->spinlock, flags);
@@ -1408,6 +1379,17 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
        }
        dev->irq = pcidev->irq;
 
+       dev->pacer = comedi_8254_init(dev->iobase + ADC8254,
+                                     I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
+       devpriv->ao_pacer = comedi_8254_init(dev->iobase + DAC8254,
+                                            I8254_OSC_BASE_10MHZ,
+                                            I8254_IO8, 0);
+       if (!devpriv->ao_pacer)
+               return -ENOMEM;
+
        ret = comedi_alloc_subdevices(dev, 7);
        if (ret)
                return ret;
@@ -1530,8 +1512,9 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
                        dac08_write(dev, s->maxdata / 2);
                        s->readback[i] = s->maxdata / 2;
                }
-       } else
+       } else {
                s->type = COMEDI_SUBD_UNUSED;
+       }
 
        /*  make sure mailbox 4 is empty */
        inl(devpriv->s5933_config + AMCC_OP_REG_IMB4);
@@ -1550,9 +1533,11 @@ static void cb_pcidas_detach(struct comedi_device *dev)
 {
        struct cb_pcidas_private *devpriv = dev->private;
 
-       if (devpriv && devpriv->s5933_config) {
-               outl(INTCSR_INBOX_INTR_STATUS,
-                    devpriv->s5933_config + AMCC_OP_REG_INTCSR);
+       if (devpriv) {
+               if (devpriv->s5933_config)
+                       outl(INTCSR_INBOX_INTR_STATUS,
+                            devpriv->s5933_config + AMCC_OP_REG_INTCSR);
+               kfree(devpriv->ao_pacer);
        }
        comedi_pci_detach(dev);
 }
index 5b43e4e6d037793ca295d05c2420e8bf3c64857b..a94c33c3d962d8dd4c48b1273aa7aad40c5dbb47 100644 (file)
@@ -81,16 +81,13 @@ TODO:
 */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
-#include "8253.h"
 #include "8255.h"
 #include "plx9080.h"
-#include "comedi_fc.h"
 
 #define TIMER_BASE 25          /*  40MHz master clock */
 /* 100kHz 'prescaled' clock for slow acquisition,
@@ -1474,9 +1471,8 @@ static int alloc_and_init_dma_members(struct comedi_device *dev)
                devpriv->ai_buffer[i] =
                        pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE,
                                             &devpriv->ai_buffer_bus_addr[i]);
-               if (devpriv->ai_buffer[i] == NULL)
+               if (!devpriv->ai_buffer[i])
                        return -ENOMEM;
-
        }
        for (i = 0; i < AO_DMA_RING_COUNT; i++) {
                if (ao_cmd_is_supported(thisboard)) {
@@ -1484,9 +1480,8 @@ static int alloc_and_init_dma_members(struct comedi_device *dev)
                                pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE,
                                                     &devpriv->
                                                      ao_buffer_bus_addr[i]);
-                       if (devpriv->ao_buffer[i] == NULL)
+                       if (!devpriv->ao_buffer[i])
                                return -ENOMEM;
-
                }
        }
        /*  allocate dma descriptors */
@@ -1494,7 +1489,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev)
                pci_alloc_consistent(pcidev, sizeof(struct plx_dma_desc) *
                                     ai_dma_ring_count(thisboard),
                                     &devpriv->ai_dma_desc_bus_addr);
-       if (devpriv->ai_dma_desc == NULL)
+       if (!devpriv->ai_dma_desc)
                return -ENOMEM;
 
        if (ao_cmd_is_supported(thisboard)) {
@@ -1503,7 +1498,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev)
                                             sizeof(struct plx_dma_desc) *
                                             AO_DMA_RING_COUNT,
                                             &devpriv->ao_dma_desc_bus_addr);
-               if (devpriv->ao_dma_desc == NULL)
+               if (!devpriv->ao_dma_desc)
                        return -ENOMEM;
        }
        /*  initialize dma descriptors */
@@ -1704,8 +1699,7 @@ static void i2c_write(struct comedi_device *dev, unsigned int address,
 
        /*  get acknowledge */
        if (i2c_read_ack(dev) != 0) {
-               dev_err(dev->class_dev, "%s failed: no acknowledge\n",
-                       __func__);
+               dev_err(dev->class_dev, "failed: no acknowledge\n");
                i2c_stop(dev);
                return;
        }
@@ -1713,8 +1707,7 @@ static void i2c_write(struct comedi_device *dev, unsigned int address,
        for (i = 0; i < length; i++) {
                i2c_write_byte(dev, data[i]);
                if (i2c_read_ack(dev) != 0) {
-                       dev_err(dev->class_dev, "%s failed: no acknowledge\n",
-                               __func__);
+                       dev_err(dev->class_dev, "failed: no acknowledge\n");
                        i2c_stop(dev);
                        return;
                }
@@ -1841,7 +1834,6 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
        }
 
        for (n = 0; n < insn->n; n++) {
-
                /*  clear adc buffer (inside loop for 4020 sake) */
                writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG);
 
@@ -1903,7 +1895,6 @@ static int ai_config_block_size(struct comedi_device *dev, unsigned int *data)
                retval = set_ai_fifo_size(dev, fifo_size);
                if (retval < 0)
                        return retval;
-
        }
 
        block_size = ai_fifo_size(dev) / fifo->num_segments * bytes_in_sample;
@@ -2001,7 +1992,8 @@ static unsigned int get_divisor(unsigned int ns, unsigned int flags)
 static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
 {
        const struct pcidas64_board *thisboard = dev->board_ptr;
-       unsigned int convert_divisor = 0, scan_divisor;
+       unsigned long long convert_divisor = 0;
+       unsigned int scan_divisor;
        static const int min_convert_divisor = 3;
        static const int max_convert_divisor =
                max_counter_value + min_convert_divisor;
@@ -2027,7 +2019,6 @@ static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
        if (cmd->scan_begin_src == TRIG_TIMER) {
                scan_divisor = get_divisor(cmd->scan_begin_arg, cmd->flags);
                if (cmd->convert_src == TRIG_TIMER) {
-                       /*  XXX check for integer overflows */
                        min_scan_divisor = convert_divisor * cmd->chanlist_len;
                        max_scan_divisor =
                                (convert_divisor * cmd->chanlist_len - 1) +
@@ -2094,34 +2085,34 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
 
        triggers = TRIG_TIMER;
        if (thisboard->layout == LAYOUT_4020)
                triggers |= TRIG_OTHER;
        else
                triggers |= TRIG_FOLLOW;
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, triggers);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, triggers);
 
        triggers = TRIG_TIMER;
        if (thisboard->layout == LAYOUT_4020)
                triggers |= TRIG_NOW;
        else
                triggers |= TRIG_EXT;
-       err |= cfc_check_trigger_src(&cmd->convert_src, triggers);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src,
-                                    TRIG_COUNT | TRIG_EXT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->convert_src, triggers);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src,
+                                       TRIG_COUNT | TRIG_EXT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -2135,7 +2126,7 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
        switch (cmd->start_src) {
        case TRIG_NOW:
-               err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
                break;
        case TRIG_EXT:
                /*
@@ -2147,30 +2138,37 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
        if (cmd->convert_src == TRIG_TIMER) {
                if (thisboard->layout == LAYOUT_4020) {
-                       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+                       err |= comedi_check_trigger_arg_is(&cmd->convert_arg,
+                                                          0);
                } else {
-                       err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                        thisboard->ai_speed);
-                       /* if scans are timed faster than conversion rate allows */
-                       if (cmd->scan_begin_src == TRIG_TIMER)
-                               err |= cfc_check_trigger_arg_min(
+                       err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                           thisboard->
+                                                           ai_speed);
+                       /*
+                        * if scans are timed faster than conversion rate
+                        * allows
+                        */
+                       if (cmd->scan_begin_src == TRIG_TIMER) {
+                               err |= comedi_check_trigger_arg_min(
                                                &cmd->scan_begin_arg,
                                                cmd->convert_arg *
                                                cmd->chanlist_len);
+                       }
                }
        }
 
-       err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        switch (cmd->stop_src) {
        case TRIG_EXT:
                break;
        case TRIG_COUNT:
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
                break;
        case TRIG_NONE:
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
                break;
        default:
                break;
@@ -2637,8 +2635,9 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                bits |= ADC_START_TRIG_EXT_BITS;
                if (cmd->start_arg & CR_INVERT)
                        bits |= ADC_START_TRIG_FALLING_BIT;
-       } else if (cmd->start_src == TRIG_NOW)
+       } else if (cmd->start_src == TRIG_NOW) {
                bits |= ADC_START_TRIG_SOFT_BITS;
+       }
        if (use_hw_sample_counter(cmd))
                bits |= ADC_SAMPLE_COUNTER_EN_BIT;
        writew(bits, devpriv->main_iobase + ADC_CONTROL0_REG);
@@ -2827,8 +2826,9 @@ static void handle_ai_interrupt(struct comedi_device *dev,
                if (devpriv->ai_cmd_running) {
                        spin_unlock_irqrestore(&dev->spinlock, flags);
                        pio_drain_ai_fifo(dev);
-               } else
+               } else {
                        spin_unlock_irqrestore(&dev->spinlock, flags);
+               }
        }
        /*  if we are have all the data, then quit */
        if ((cmd->stop_src == TRIG_COUNT &&
@@ -2978,7 +2978,7 @@ static void handle_ao_interrupt(struct comedi_device *dev,
        unsigned long flags;
 
        /* board might not support ao, in which case write_subdev is NULL */
-       if (s == NULL)
+       if (!s)
                return;
        async = s->async;
        cmd = &async->cmd;
@@ -3312,20 +3312,20 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
-                                    TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
+                                       TRIG_TIMER | TRIG_EXT);
+       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_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -3340,11 +3340,11 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                thisboard->ao_scan_speed);
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   thisboard->ao_scan_speed);
                if (get_ao_divisor(cmd->scan_begin_arg, cmd->flags) >
                    max_counter_value) {
                        cmd->scan_begin_arg = (max_counter_value + 2) *
@@ -3353,8 +3353,9 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
                }
        }
 
-       err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (err)
                return 3;
@@ -3817,8 +3818,9 @@ static int setup_subdevices(struct comedi_device *dev)
                s->maxdata = 1;
                s->range_table = &range_digital;
                s->insn_bits = di_rbits;
-       } else
+       } else {
                s->type = COMEDI_SUBD_UNUSED;
+       }
 
        /*  digital output */
        if (thisboard->layout == LAYOUT_64XX) {
@@ -3829,8 +3831,9 @@ static int setup_subdevices(struct comedi_device *dev)
                s->maxdata = 1;
                s->range_table = &range_digital;
                s->insn_bits = do_wbits;
-       } else
+       } else {
                s->type = COMEDI_SUBD_UNUSED;
+       }
 
        /* 8255 */
        s = &dev->subdevices[4];
@@ -3858,8 +3861,9 @@ static int setup_subdevices(struct comedi_device *dev)
                s->range_table = &range_digital;
                s->insn_config = dio_60xx_config_insn;
                s->insn_bits = dio_60xx_wbits;
-       } else
+       } else {
                s->type = COMEDI_SUBD_UNUSED;
+       }
 
        /*  caldac */
        s = &dev->subdevices[6];
@@ -3898,8 +3902,9 @@ static int setup_subdevices(struct comedi_device *dev)
                        ad8402_write(dev, i, s->maxdata / 2);
                        s->readback[i] = s->maxdata / 2;
                }
-       } else
+       } else {
                s->type = COMEDI_SUBD_UNUSED;
+       }
 
        /* serial EEPROM, if present */
        s = &dev->subdevices[8];
@@ -3909,8 +3914,9 @@ static int setup_subdevices(struct comedi_device *dev)
                s->n_chan = 128;
                s->maxdata = 0xffff;
                s->insn_read = eeprom_read_insn;
-       } else
+       } else {
                s->type = COMEDI_SUBD_UNUSED;
+       }
 
        /*  user counter subd XXX */
        s = &dev->subdevices[9];
index 2b2cfcdda5bdd938035c35ff362f41812e7cc474..30c9e27d1ed90743c9254a293707cb18a03429fa 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
-#include "comedi_fc.h"
 #include "8255.h"
 
 #define EEPROM_SIZE    128     /*  number of entries in eeprom */
index 70dd2c9eecdba21174c2d9bc7595f2eb609a3654..c458e5010a745cb631013374e3c2f0b881ea07d3 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
+#include "comedi_8254.h"
 #include "plx9052.h"
 #include "8255.h"
 
-/* Registers for the PCIM-DAS1602/16 and PCIe-DAS1602/16 */
-
-/* DAC Offsets */
-#define ADC_TRIG 0
-#define DAC0_OFFSET 2
-#define DAC1_OFFSET 4
-
-/* AI and Counter Constants */
-#define MUX_LIMITS 0
-#define MAIN_CONN_DIO 1
-#define ADC_STAT 2
-#define ADC_CONV_STAT 3
-#define ADC_INT 4
-#define ADC_PACER 5
-#define BURST_MODE 6
-#define PROG_GAIN 7
-#define CLK8254_1_DATA 8
-#define CLK8254_2_DATA 9
-#define CLK8254_3_DATA 10
-#define CLK8254_CONTROL 11
-#define USER_COUNTER 12
-#define RESID_COUNT_H 13
-#define RESID_COUNT_L 14
+/*
+ * PCI Bar 1 Register map
+ * see plx9052.h for register and bit defines
+ */
+
+/*
+ * PCI Bar 2 Register map (devpriv->daqio)
+ */
+#define PCIMDAS_AI_REG                 0x00
+#define PCIMDAS_AI_SOFTTRIG_REG                0x00
+#define PCIMDAS_AO_REG(x)              (0x02 + ((x) * 2))
+
+/*
+ * PCI Bar 3 Register map (devpriv->BADR3)
+ */
+#define PCIMDAS_MUX_REG                        0x00
+#define PCIMDAS_MUX(_lo, _hi)          ((_lo) | ((_hi) << 4))
+#define PCIMDAS_DI_DO_REG              0x01
+#define PCIMDAS_STATUS_REG             0x02
+#define PCIMDAS_STATUS_EOC             BIT(7)
+#define PCIMDAS_STATUS_UB              BIT(6)
+#define PCIMDAS_STATUS_MUX             BIT(5)
+#define PCIMDAS_STATUS_CLK             BIT(4)
+#define PCIMDAS_STATUS_TO_CURR_MUX(x)  ((x) & 0xf)
+#define PCIMDAS_CONV_STATUS_REG                0x03
+#define PCIMDAS_CONV_STATUS_EOC                BIT(7)
+#define PCIMDAS_CONV_STATUS_EOB                BIT(6)
+#define PCIMDAS_CONV_STATUS_EOA                BIT(5)
+#define PCIMDAS_CONV_STATUS_FNE                BIT(4)
+#define PCIMDAS_CONV_STATUS_FHF                BIT(3)
+#define PCIMDAS_CONV_STATUS_OVERRUN    BIT(2)
+#define PCIMDAS_IRQ_REG                        0x04
+#define PCIMDAS_IRQ_INTE               BIT(7)
+#define PCIMDAS_IRQ_INT                        BIT(6)
+#define PCIMDAS_IRQ_OVERRUN            BIT(4)
+#define PCIMDAS_IRQ_EOA                        BIT(3)
+#define PCIMDAS_IRQ_EOA_INT_SEL                BIT(2)
+#define PCIMDAS_IRQ_INTSEL(x)          ((x) << 0)
+#define PCIMDAS_IRQ_INTSEL_EOC         PCIMDAS_IRQ_INTSEL(0)
+#define PCIMDAS_IRQ_INTSEL_FNE         PCIMDAS_IRQ_INTSEL(1)
+#define PCIMDAS_IRQ_INTSEL_EOB         PCIMDAS_IRQ_INTSEL(2)
+#define PCIMDAS_IRQ_INTSEL_FHF_EOA     PCIMDAS_IRQ_INTSEL(3)
+#define PCIMDAS_PACER_REG              0x05
+#define PCIMDAS_PACER_GATE_STATUS      BIT(6)
+#define PCIMDAS_PACER_GATE_POL         BIT(5)
+#define PCIMDAS_PACER_GATE_LATCH       BIT(4)
+#define PCIMDAS_PACER_GATE_EN          BIT(3)
+#define PCIMDAS_PACER_EXT_PACER_POL    BIT(2)
+#define PCIMDAS_PACER_SRC(x)           ((x) << 0)
+#define PCIMDAS_PACER_SRC_POLLED       PCIMDAS_PACER_SRC(0)
+#define PCIMDAS_PACER_SRC_EXT          PCIMDAS_PACER_SRC(2)
+#define PCIMDAS_PACER_SRC_INT          PCIMDAS_PACER_SRC(3)
+#define PCIMDAS_PACER_SRC_MASK         (3 << 0)
+#define PCIMDAS_BURST_REG              0x06
+#define PCIMDAS_BURST_BME              BIT(1)
+#define PCIMDAS_BURST_CONV_EN          BIT(0)
+#define PCIMDAS_GAIN_REG               0x07
+#define PCIMDAS_8254_BASE              0x08
+#define PCIMDAS_USER_CNTR_REG          0x0c
+#define PCIMDAS_USER_CNTR_CTR1_CLK_SEL BIT(0)
+#define PCIMDAS_RESIDUE_MSB_REG                0x0d
+#define PCIMDAS_RESIDUE_LSB_REG                0x0e
+
+/*
+ * PCI Bar 4 Register map (dev->iobase)
+ */
+#define PCIMDAS_8255_BASE              0x00
+
+static const struct comedi_lrange cb_pcimdas_ai_bip_range = {
+       4, {
+               BIP_RANGE(10),
+               BIP_RANGE(5),
+               BIP_RANGE(2.5),
+               BIP_RANGE(1.25)
+       }
+};
+
+static const struct comedi_lrange cb_pcimdas_ai_uni_range = {
+       4, {
+               UNI_RANGE(10),
+               UNI_RANGE(5),
+               UNI_RANGE(2.5),
+               UNI_RANGE(1.25)
+       }
+};
+
+/*
+ * The Analog Output range is not programmable. The DAC ranges are
+ * jumper-settable on the board. The settings are not software-readable.
+ */
+static const struct comedi_lrange cb_pcimdas_ao_range = {
+       4, {
+               BIP_RANGE(10),
+               BIP_RANGE(5),
+               UNI_RANGE(10),
+               UNI_RANGE(5)
+       }
+};
 
 /*
  * this structure is for data unique to this hardware driver.  If
@@ -94,59 +169,47 @@ static int cb_pcimdas_ai_eoc(struct comedi_device *dev,
        struct cb_pcimdas_private *devpriv = dev->private;
        unsigned int status;
 
-       status = inb(devpriv->BADR3 + 2);
-       if ((status & 0x80) == 0)
+       status = inb(devpriv->BADR3 + PCIMDAS_STATUS_REG);
+       if ((status & PCIMDAS_STATUS_EOC) == 0)
                return 0;
        return -EBUSY;
 }
 
-static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
-                              struct comedi_subdevice *s,
-                              struct comedi_insn *insn, unsigned int *data)
+static int cb_pcimdas_ai_insn_read(struct comedi_device *dev,
+                                  struct comedi_subdevice *s,
+                                  struct comedi_insn *insn,
+                                  unsigned int *data)
 {
        struct cb_pcimdas_private *devpriv = dev->private;
+       unsigned int chan = CR_CHAN(insn->chanspec);
+       unsigned int range = CR_RANGE(insn->chanspec);
        int n;
        unsigned int d;
-       int chan = CR_CHAN(insn->chanspec);
-       unsigned short chanlims;
-       int maxchans;
        int ret;
 
        /*  only support sw initiated reads from a single channel */
 
-       /* check channel number */
-       if ((inb(devpriv->BADR3 + 2) & 0x20) == 0)      /* differential mode */
-               maxchans = s->n_chan / 2;
-       else
-               maxchans = s->n_chan;
-
-       if (chan > (maxchans - 1))
-               return -ETIMEDOUT;      /* *** Wrong error code. Fixme. */
-
        /* configure for sw initiated read */
-       d = inb(devpriv->BADR3 + 5);
-       if ((d & 0x03) > 0) {   /* only reset if needed. */
-               d = d & 0xfd;
-               outb(d, devpriv->BADR3 + 5);
+       d = inb(devpriv->BADR3 + PCIMDAS_PACER_REG);
+       if ((d & PCIMDAS_PACER_SRC_MASK) != PCIMDAS_PACER_SRC_POLLED) {
+               d &= ~PCIMDAS_PACER_SRC_MASK;
+               d |= PCIMDAS_PACER_SRC_POLLED;
+               outb(d, devpriv->BADR3 + PCIMDAS_PACER_REG);
        }
 
        /* set bursting off, conversions on */
-       outb(0x01, devpriv->BADR3 + 6);
+       outb(PCIMDAS_BURST_CONV_EN, devpriv->BADR3 + PCIMDAS_BURST_REG);
 
-       /* set range to 10V. UP/BP is controlled by a switch on the board */
-       outb(0x00, devpriv->BADR3 + 7);
+       /* set range */
+       outb(range, devpriv->BADR3 + PCIMDAS_GAIN_REG);
 
-       /*
-        * write channel limits to multiplexer, set Low (bits 0-3) and
-        * High (bits 4-7) channels to chan.
-        */
-       chanlims = chan | (chan << 4);
-       outb(chanlims, devpriv->BADR3 + 0);
+       /* set mux for single channel scan */
+       outb(PCIMDAS_MUX(chan, chan), devpriv->BADR3 + PCIMDAS_MUX_REG);
 
        /* convert n samples */
        for (n = 0; n < insn->n; n++) {
                /* trigger conversion */
-               outw(0, devpriv->daqio + 0);
+               outw(0, devpriv->daqio + PCIMDAS_AI_SOFTTRIG_REG);
 
                /* wait for conversion to end */
                ret = comedi_timeout(dev, s, insn, cb_pcimdas_ai_eoc, 0);
@@ -154,7 +217,7 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
                        return ret;
 
                /* read data */
-               data[n] = inw(devpriv->daqio + 0);
+               data[n] = inw(devpriv->daqio + PCIMDAS_AI_REG);
        }
 
        /* return the number of samples read/written */
@@ -169,20 +232,128 @@ static int cb_pcimdas_ao_insn_write(struct comedi_device *dev,
        struct cb_pcimdas_private *devpriv = dev->private;
        unsigned int chan = CR_CHAN(insn->chanspec);
        unsigned int val = s->readback[chan];
-       unsigned int reg = (chan) ? DAC1_OFFSET : DAC0_OFFSET;
        int i;
 
        for (i = 0; i < insn->n; i++) {
                val = data[i];
-               outw(val, devpriv->daqio + reg);
+               outw(val, devpriv->daqio + PCIMDAS_AO_REG(chan));
        }
        s->readback[chan] = val;
 
        return insn->n;
 }
 
+static int cb_pcimdas_di_insn_read(struct comedi_device *dev,
+                                  struct comedi_subdevice *s,
+                                  struct comedi_insn *insn,
+                                  unsigned int *data)
+{
+       struct cb_pcimdas_private *devpriv = dev->private;
+       unsigned int val;
+
+       val = inb(devpriv->BADR3 + PCIMDAS_DI_DO_REG);
+
+       data[1] = val & 0x0f;
+
+       return insn->n;
+}
+
+static int cb_pcimdas_do_insn_write(struct comedi_device *dev,
+                                   struct comedi_subdevice *s,
+                                   struct comedi_insn *insn,
+                                   unsigned int *data)
+{
+       struct cb_pcimdas_private *devpriv = dev->private;
+
+       if (comedi_dio_update_state(s, data))
+               outb(s->state, devpriv->BADR3 + PCIMDAS_DI_DO_REG);
+
+       data[1] = s->state;
+
+       return insn->n;
+}
+
+static int cb_pcimdas_counter_insn_config(struct comedi_device *dev,
+                                         struct comedi_subdevice *s,
+                                         struct comedi_insn *insn,
+                                         unsigned int *data)
+{
+       struct cb_pcimdas_private *devpriv = dev->private;
+       unsigned int ctrl;
+
+       switch (data[0]) {
+       case INSN_CONFIG_SET_CLOCK_SRC:
+               switch (data[1]) {
+               case 0: /* internal 100 kHz clock */
+                       ctrl = PCIMDAS_USER_CNTR_CTR1_CLK_SEL;
+                       break;
+               case 1: /* external clk on pin 21 */
+                       ctrl = 0;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               outb(ctrl, devpriv->BADR3 + PCIMDAS_USER_CNTR_REG);
+               break;
+       case INSN_CONFIG_GET_CLOCK_SRC:
+               ctrl = inb(devpriv->BADR3 + PCIMDAS_USER_CNTR_REG);
+               if (ctrl & PCIMDAS_USER_CNTR_CTR1_CLK_SEL) {
+                       data[1] = 0;
+                       data[2] = I8254_OSC_BASE_100KHZ;
+               } else {
+                       data[1] = 1;
+                       data[2] = 0;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return insn->n;
+}
+
+static unsigned int cb_pcimdas_pacer_clk(struct comedi_device *dev)
+{
+       struct cb_pcimdas_private *devpriv = dev->private;
+       unsigned int status;
+
+       /* The Pacer Clock jumper selects a 10 MHz or 1 MHz clock */
+       status = inb(devpriv->BADR3 + PCIMDAS_STATUS_REG);
+       if (status & PCIMDAS_STATUS_CLK)
+               return I8254_OSC_BASE_10MHZ;
+       return I8254_OSC_BASE_1MHZ;
+}
+
+static bool cb_pcimdas_is_ai_se(struct comedi_device *dev)
+{
+       struct cb_pcimdas_private *devpriv = dev->private;
+       unsigned int status;
+
+       /*
+        * The number of Analog Input channels is set with the
+        * Analog Input Mode Switch on the board. The board can
+        * have 16 single-ended or 8 differential channels.
+        */
+       status = inb(devpriv->BADR3 + PCIMDAS_STATUS_REG);
+       return status & PCIMDAS_STATUS_MUX;
+}
+
+static bool cb_pcimdas_is_ai_uni(struct comedi_device *dev)
+{
+       struct cb_pcimdas_private *devpriv = dev->private;
+       unsigned int status;
+
+       /*
+        * The Analog Input range polarity is set with the
+        * Analog Input Polarity Switch on the board. The
+        * inputs can be set to Unipolar or Bipolar ranges.
+        */
+       status = inb(devpriv->BADR3 + PCIMDAS_STATUS_REG);
+       return status & PCIMDAS_STATUS_UB;
+}
+
 static int cb_pcimdas_auto_attach(struct comedi_device *dev,
-                                           unsigned long context_unused)
+                                 unsigned long context_unused)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        struct cb_pcimdas_private *devpriv;
@@ -201,42 +372,79 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev,
        devpriv->BADR3 = pci_resource_start(pcidev, 3);
        dev->iobase = pci_resource_start(pcidev, 4);
 
-       ret = comedi_alloc_subdevices(dev, 3);
+       dev->pacer = comedi_8254_init(devpriv->BADR3 + PCIMDAS_8254_BASE,
+                                     cb_pcimdas_pacer_clk(dev),
+                                     I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
+       ret = comedi_alloc_subdevices(dev, 6);
        if (ret)
                return ret;
 
+       /* Analog Input subdevice */
        s = &dev->subdevices[0];
-       /* dev->read_subdev=s; */
-       /*  analog input subdevice */
-       s->type = COMEDI_SUBD_AI;
-       s->subdev_flags = SDF_READABLE | SDF_GROUND;
-       s->n_chan = 16;
-       s->maxdata = 0xffff;
-       s->range_table = &range_unknown;
-       s->len_chanlist = 1;    /*  This is the maximum chanlist length that */
-       /*  the board can handle */
-       s->insn_read = cb_pcimdas_ai_rinsn;
+       s->type         = COMEDI_SUBD_AI;
+       s->subdev_flags = SDF_READABLE;
+       if (cb_pcimdas_is_ai_se(dev)) {
+               s->subdev_flags |= SDF_GROUND;
+               s->n_chan       = 16;
+       } else {
+               s->subdev_flags |= SDF_DIFF;
+               s->n_chan       = 8;
+       }
+       s->maxdata      = 0xffff;
+       s->range_table  = cb_pcimdas_is_ai_uni(dev) ? &cb_pcimdas_ai_uni_range
+                                                   : &cb_pcimdas_ai_bip_range;
+       s->insn_read    = cb_pcimdas_ai_insn_read;
 
+       /* Analog Output subdevice */
        s = &dev->subdevices[1];
-       /*  analog output subdevice */
-       s->type = COMEDI_SUBD_AO;
-       s->subdev_flags = SDF_WRITABLE;
-       s->n_chan = 2;
-       s->maxdata = 0xfff;
-       /* ranges are hardware settable, but not software readable. */
-       s->range_table = &range_unknown;
-       s->insn_write = cb_pcimdas_ao_insn_write;
+       s->type         = COMEDI_SUBD_AO;
+       s->subdev_flags = SDF_WRITABLE;
+       s->n_chan       = 2;
+       s->maxdata      = 0xfff;
+       s->range_table  = &cb_pcimdas_ao_range;
+       s->insn_write   = cb_pcimdas_ao_insn_write;
 
        ret = comedi_alloc_subdev_readback(s);
        if (ret)
                return ret;
 
+       /* Digital I/O subdevice */
        s = &dev->subdevices[2];
-       /* digital i/o subdevice */
-       ret = subdev_8255_init(dev, s, NULL, 0x00);
+       ret = subdev_8255_init(dev, s, NULL, PCIMDAS_8255_BASE);
        if (ret)
                return ret;
 
+       /* Digital Input subdevice (main connector) */
+       s = &dev->subdevices[3];
+       s->type         = COMEDI_SUBD_DI;
+       s->subdev_flags = SDF_READABLE;
+       s->n_chan       = 4;
+       s->maxdata      = 1;
+       s->range_table  = &range_digital;
+       s->insn_read    = cb_pcimdas_di_insn_read;
+
+       /* Digital Output subdevice (main connector) */
+       s = &dev->subdevices[4];
+       s->type         = COMEDI_SUBD_DO;
+       s->subdev_flags = SDF_WRITABLE;
+       s->n_chan       = 4;
+       s->maxdata      = 1;
+       s->range_table  = &range_digital;
+       s->insn_write   = cb_pcimdas_do_insn_write;
+
+       /* Counter subdevice (8254) */
+       s = &dev->subdevices[5];
+       comedi_8254_subdevice_init(s, dev->pacer);
+
+       dev->pacer->insn_config = cb_pcimdas_counter_insn_config;
+
+       /* counters 1 and 2 are used internally for the pacer */
+       comedi_8254_set_busy(dev->pacer, 1, true);
+       comedi_8254_set_busy(dev->pacer, 2, true);
+
        return 0;
 }
 
index 03043e7b9b589109fd256674fa056f6f8e018c7a..a4781dbbdd82e6469f6e5a1060ff0a2375b89bbf 100644 (file)
@@ -75,9 +75,8 @@ Configuration Options: not applicable, uses PCI auto config
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #include "8255.h"
 
@@ -134,7 +133,7 @@ static int cb_pcimdda_ao_insn_read(struct comedi_device *dev,
 }
 
 static int cb_pcimdda_auto_attach(struct comedi_device *dev,
-                                           unsigned long context_unused)
+                                 unsigned long context_unused)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        struct comedi_subdevice *s;
diff --git a/drivers/staging/comedi/drivers/comedi_8254.c b/drivers/staging/comedi/drivers/comedi_8254.c
new file mode 100644 (file)
index 0000000..0d5d56b
--- /dev/null
@@ -0,0 +1,664 @@
+/*
+ * comedi_8254.c
+ * Generic 8254 timer/counter support
+ * Copyright (C) 2014 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * Based on 8253.h and various subdevice implementations in comedi drivers.
+ *
+ * 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.
+ */
+
+/*
+ * Module: comedi_8254
+ * Description: Generic 8254 timer/counter support
+ * Author: H Hartley Sweeten <hsweeten@visionengravers.com>
+ * Updated: Thu Jan 8 16:45:45 MST 2015
+ * Status: works
+ *
+ * This module is not used directly by end-users. Rather, it is used by other
+ * drivers to provide support for an 8254 Programmable Interval Timer. These
+ * counters are typically used to generate the pacer clock used for data
+ * acquisition. Some drivers also expose the counters for general purpose use.
+ *
+ * This module provides the following basic functions:
+ *
+ * comedi_8254_init() / comedi_8254_mm_init()
+ *     Initializes this module to access the 8254 registers. The _mm version
+ *     sets up the module for MMIO register access the other for PIO access.
+ *     The pointer returned from these functions is normally stored in the
+ *     comedi_device dev->pacer and will be freed by the comedi core during
+ *     the driver (*detach). If a driver has multiple 8254 devices, they need
+ *     to be stored in the drivers private data and freed when the driver is
+ *     detached.
+ *
+ *     NOTE: The counters are reset by setting them to I8254_MODE0 as part of
+ *     this initialization.
+ *
+ * comedi_8254_set_mode()
+ *     Sets a counters operation mode:
+ *             I8254_MODE0     Interrupt on terminal count
+ *             I8254_MODE1     Hardware retriggerable one-shot
+ *             I8254_MODE2     Rate generator
+ *             I8254_MODE3     Square wave mode
+ *             I8254_MODE4     Software triggered strobe
+ *             I8254_MODE5     Hardware triggered strobe (retriggerable)
+ *
+ *     In addition I8254_BCD and I8254_BINARY specify the counting mode:
+ *             I8254_BCD       BCD counting
+ *             I8254_BINARY    Binary counting
+ *
+ * comedi_8254_write()
+ *     Writes an initial value to a counter.
+ *
+ *     The largest possible initial count is 0; this is equivalent to 2^16
+ *     for binary counting and 10^4 for BCD counting.
+ *
+ *     NOTE: The counter does not stop when it reaches zero. In Mode 0, 1, 4,
+ *     and 5 the counter "wraps around" to the highest count, either 0xffff
+ *     for binary counting or 9999 for BCD counting, and continues counting.
+ *     Modes 2 and 3 are periodic; the counter reloads itself with the initial
+ *     count and continues counting from there.
+ *
+ * comedi_8254_read()
+ *     Reads the current value from a counter.
+ *
+ * comedi_8254_status()
+ *     Reads the status of a counter.
+ *
+ * comedi_8254_load()
+ *     Sets a counters operation mode and writes the initial value.
+ *
+ * Typically the pacer clock is created by cascading two of the 16-bit counters
+ * to create a 32-bit rate generator (I8254_MODE2). These functions are
+ * provided to handle the cascaded counters:
+ *
+ * comedi_8254_ns_to_timer()
+ *     Calculates the divisor value needed for a single counter to generate
+ *     ns timing.
+ *
+ * comedi_8254_cascade_ns_to_timer()
+ *     Calculates the two divisor values needed to the generate the pacer
+ *     clock (in ns).
+ *
+ * comedi_8254_update_divisors()
+ *     Transfers the intermediate divisor values to the current divisors.
+ *
+ * comedi_8254_pacer_enable()
+ *     Programs the mode of the cascaded counters and writes the current
+ *     divisor values.
+ *
+ * To expose the counters as a subdevice for general purpose use the following
+ * functions a provided:
+ *
+ * comedi_8254_subdevice_init()
+ *     Initializes a comedi_subdevice to use the 8254 timer.
+ *
+ * comedi_8254_set_busy()
+ *     Internally flags a counter as "busy". This is done to protect the
+ *     counters that are used for the cascaded 32-bit pacer.
+ *
+ * The subdevice provides (*insn_read) and (*insn_write) operations to read
+ * the current value and write an initial value to a counter. A (*insn_config)
+ * operation is also provided to handle the following comedi instructions:
+ *
+ *     INSN_CONFIG_SET_COUNTER_MODE    calls comedi_8254_set_mode()
+ *     INSN_CONFIG_8254_READ_STATUS    calls comedi_8254_status()
+ *
+ * The (*insn_config) member of comedi_8254 can be initialized by the external
+ * driver to handle any additional instructions.
+ *
+ * NOTE: Gate control, clock routing, and any interrupt handling for the
+ * counters is not handled by this module. These features are driver dependent.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+#include "../comedidev.h"
+
+#include "comedi_8254.h"
+
+static unsigned int __i8254_read(struct comedi_8254 *i8254, unsigned int reg)
+{
+       unsigned int reg_offset = (reg * i8254->iosize) << i8254->regshift;
+       unsigned int val;
+
+       switch (i8254->iosize) {
+       default:
+       case I8254_IO8:
+               if (i8254->mmio)
+                       val = readb(i8254->mmio + reg_offset);
+               else
+                       val = inb(i8254->iobase + reg_offset);
+               break;
+       case I8254_IO16:
+               if (i8254->mmio)
+                       val = readw(i8254->mmio + reg_offset);
+               else
+                       val = inw(i8254->iobase + reg_offset);
+               break;
+       case I8254_IO32:
+               if (i8254->mmio)
+                       val = readl(i8254->mmio + reg_offset);
+               else
+                       val = inl(i8254->iobase + reg_offset);
+               break;
+       }
+       return val & 0xff;
+}
+
+static void __i8254_write(struct comedi_8254 *i8254,
+                         unsigned int val, unsigned int reg)
+{
+       unsigned int reg_offset = (reg * i8254->iosize) << i8254->regshift;
+
+       switch (i8254->iosize) {
+       default:
+       case I8254_IO8:
+               if (i8254->mmio)
+                       writeb(val, i8254->mmio + reg_offset);
+               else
+                       outb(val, i8254->iobase + reg_offset);
+               break;
+       case I8254_IO16:
+               if (i8254->mmio)
+                       writew(val, i8254->mmio + reg_offset);
+               else
+                       outw(val, i8254->iobase + reg_offset);
+               break;
+       case I8254_IO32:
+               if (i8254->mmio)
+                       writel(val, i8254->mmio + reg_offset);
+               else
+                       outl(val, i8254->iobase + reg_offset);
+               break;
+       }
+}
+
+/**
+ * comedi_8254_status - return the status of a counter
+ * @i8254:     comedi_8254 struct for the timer
+ * @counter:   the counter number
+ */
+unsigned int comedi_8254_status(struct comedi_8254 *i8254, unsigned int counter)
+{
+       unsigned int cmd;
+
+       if (counter > 2)
+               return 0;
+
+       cmd = I8254_CTRL_READBACK_STATUS | I8254_CTRL_READBACK_SEL_CTR(counter);
+       __i8254_write(i8254, cmd, I8254_CTRL_REG);
+
+       return __i8254_read(i8254, counter);
+}
+EXPORT_SYMBOL_GPL(comedi_8254_status);
+
+/**
+ * comedi_8254_read - read the current counter value
+ * @i8254:     comedi_8254 struct for the timer
+ * @counter:   the counter number
+ */
+unsigned int comedi_8254_read(struct comedi_8254 *i8254, unsigned int counter)
+{
+       unsigned int val;
+
+       if (counter > 2)
+               return 0;
+
+       /* latch counter */
+       __i8254_write(i8254, I8254_CTRL_SEL_CTR(counter) | I8254_CTRL_LATCH,
+                     I8254_CTRL_REG);
+
+       /* read LSB then MSB */
+       val = __i8254_read(i8254, counter);
+       val |= (__i8254_read(i8254, counter) << 8);
+
+       return val;
+}
+EXPORT_SYMBOL_GPL(comedi_8254_read);
+
+/**
+ * comedi_8254_write - load a 16-bit initial counter value
+ * @i8254:     comedi_8254 struct for the timer
+ * @counter:   the counter number
+ * @val:       the initial value
+ */
+void comedi_8254_write(struct comedi_8254 *i8254,
+                      unsigned int counter, unsigned int val)
+{
+       unsigned int byte;
+
+       if (counter > 2)
+               return;
+       if (val > 0xffff)
+               return;
+
+       /* load LSB then MSB */
+       byte = val & 0xff;
+       __i8254_write(i8254, byte, counter);
+       byte = (val >> 8) & 0xff;
+       __i8254_write(i8254, byte, counter);
+}
+EXPORT_SYMBOL_GPL(comedi_8254_write);
+
+/**
+ * comedi_8254_set_mode - set the mode of a counter
+ * @i8254:     comedi_8254 struct for the timer
+ * @counter:   the counter number
+ * @mode:      the I8254_MODEx and I8254_BCD|I8254_BINARY
+ */
+int comedi_8254_set_mode(struct comedi_8254 *i8254, unsigned int counter,
+                        unsigned int mode)
+{
+       unsigned int byte;
+
+       if (counter > 2)
+               return -EINVAL;
+       if (mode > (I8254_MODE5 | I8254_BCD))
+               return -EINVAL;
+
+       byte = I8254_CTRL_SEL_CTR(counter) |    /* select counter */
+              I8254_CTRL_LSB_MSB |             /* load LSB then MSB */
+              mode;                            /* mode and BCD|binary */
+       __i8254_write(i8254, byte, I8254_CTRL_REG);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(comedi_8254_set_mode);
+
+/**
+ * comedi_8254_load - program the mode and initial count of a counter
+ * @i8254:     comedi_8254 struct for the timer
+ * @counter:   the counter number
+ * @mode:      the I8254_MODEx and I8254_BCD|I8254_BINARY
+ * @val:       the initial value
+ */
+int comedi_8254_load(struct comedi_8254 *i8254, unsigned int counter,
+                    unsigned int val, unsigned int mode)
+{
+       if (counter > 2)
+               return -EINVAL;
+       if (val > 0xffff)
+               return -EINVAL;
+       if (mode > (I8254_MODE5 | I8254_BCD))
+               return -EINVAL;
+
+       comedi_8254_set_mode(i8254, counter, mode);
+       comedi_8254_write(i8254, counter, val);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(comedi_8254_load);
+
+/**
+ * comedi_8254_pacer_enable - set the mode and load the cascaded counters
+ * @i8254:     comedi_8254 struct for the timer
+ * @counter1:  the counter number for the first divisor
+ * @counter2:  the counter number for the second divisor
+ * @enable:    flag to enable (load) the counters
+ */
+void comedi_8254_pacer_enable(struct comedi_8254 *i8254,
+                             unsigned int counter1,
+                             unsigned int counter2,
+                             bool enable)
+{
+       unsigned int mode;
+
+       if (counter1 > 2 || counter2 > 2 || counter1 == counter2)
+               return;
+
+       if (enable)
+               mode = I8254_MODE2 | I8254_BINARY;
+       else
+               mode = I8254_MODE0 | I8254_BINARY;
+
+       comedi_8254_set_mode(i8254, counter1, mode);
+       comedi_8254_set_mode(i8254, counter2, mode);
+
+       if (enable) {
+               /*
+                * Divisors are loaded second counter then first counter to
+                * avoid possible issues with the first counter expiring
+                * before the second counter is loaded.
+                */
+               comedi_8254_write(i8254, counter2, i8254->divisor2);
+               comedi_8254_write(i8254, counter1, i8254->divisor1);
+       }
+}
+EXPORT_SYMBOL_GPL(comedi_8254_pacer_enable);
+
+/**
+ * comedi_8254_update_divisors - update the divisors for the cascaded counters
+ * @i8254:     comedi_8254 struct for the timer
+ */
+void comedi_8254_update_divisors(struct comedi_8254 *i8254)
+{
+       /* masking is done since counter maps zero to 0x10000 */
+       i8254->divisor = i8254->next_div & 0xffff;
+       i8254->divisor1 = i8254->next_div1 & 0xffff;
+       i8254->divisor2 = i8254->next_div2 & 0xffff;
+}
+EXPORT_SYMBOL_GPL(comedi_8254_update_divisors);
+
+/**
+ * comedi_8254_cascade_ns_to_timer - calculate the cascaded divisor values
+ * @i8254:     comedi_8254 struct for the timer
+ * @nanosec:   the desired ns time
+ * @flags:     comedi_cmd flags
+ */
+void comedi_8254_cascade_ns_to_timer(struct comedi_8254 *i8254,
+                                    unsigned int *nanosec,
+                                    unsigned int flags)
+{
+       unsigned int d1 = i8254->next_div1 ? i8254->next_div1 : I8254_MAX_COUNT;
+       unsigned int d2 = i8254->next_div2 ? i8254->next_div2 : I8254_MAX_COUNT;
+       unsigned int div = d1 * d2;
+       unsigned int ns_lub = 0xffffffff;
+       unsigned int ns_glb = 0;
+       unsigned int d1_lub = 0;
+       unsigned int d1_glb = 0;
+       unsigned int d2_lub = 0;
+       unsigned int d2_glb = 0;
+       unsigned int start;
+       unsigned int ns;
+       unsigned int ns_low;
+       unsigned int ns_high;
+
+       /* exit early if everything is already correct */
+       if (div * i8254->osc_base == *nanosec &&
+           d1 > 1 && d1 <= I8254_MAX_COUNT &&
+           d2 > 1 && d2 <= I8254_MAX_COUNT &&
+           /* check for overflow */
+           div > d1 && div > d2 &&
+           div * i8254->osc_base > div &&
+           div * i8254->osc_base > i8254->osc_base)
+               return;
+
+       div = *nanosec / i8254->osc_base;
+       d2 = I8254_MAX_COUNT;
+       start = div / d2;
+       if (start < 2)
+               start = 2;
+       for (d1 = start; d1 <= div / d1 + 1 && d1 <= I8254_MAX_COUNT; d1++) {
+               for (d2 = div / d1;
+                    d1 * d2 <= div + d1 + 1 && d2 <= I8254_MAX_COUNT; d2++) {
+                       ns = i8254->osc_base * d1 * d2;
+                       if (ns <= *nanosec && ns > ns_glb) {
+                               ns_glb = ns;
+                               d1_glb = d1;
+                               d2_glb = d2;
+                       }
+                       if (ns >= *nanosec && ns < ns_lub) {
+                               ns_lub = ns;
+                               d1_lub = d1;
+                               d2_lub = d2;
+                       }
+               }
+       }
+
+       switch (flags & CMDF_ROUND_MASK) {
+       case CMDF_ROUND_NEAREST:
+       default:
+               ns_high = d1_lub * d2_lub * i8254->osc_base;
+               ns_low = d1_glb * d2_glb * i8254->osc_base;
+               if (ns_high - *nanosec < *nanosec - ns_low) {
+                       d1 = d1_lub;
+                       d2 = d2_lub;
+               } else {
+                       d1 = d1_glb;
+                       d2 = d2_glb;
+               }
+               break;
+       case CMDF_ROUND_UP:
+               d1 = d1_lub;
+               d2 = d2_lub;
+               break;
+       case CMDF_ROUND_DOWN:
+               d1 = d1_glb;
+               d2 = d2_glb;
+               break;
+       }
+
+       *nanosec = d1 * d2 * i8254->osc_base;
+       i8254->next_div1 = d1;
+       i8254->next_div2 = d2;
+}
+EXPORT_SYMBOL_GPL(comedi_8254_cascade_ns_to_timer);
+
+/**
+ * comedi_8254_ns_to_timer - calculate the divisor value for nanosec timing
+ * @i8254:     comedi_8254 struct for the timer
+ * @nanosec:   the desired ns time
+ * @flags:     comedi_cmd flags
+ */
+void comedi_8254_ns_to_timer(struct comedi_8254 *i8254,
+                            unsigned int *nanosec, unsigned int flags)
+{
+       unsigned int divisor;
+
+       switch (flags & CMDF_ROUND_MASK) {
+       default:
+       case CMDF_ROUND_NEAREST:
+               divisor = DIV_ROUND_CLOSEST(*nanosec, i8254->osc_base);
+               break;
+       case CMDF_ROUND_UP:
+               divisor = DIV_ROUND_UP(*nanosec, i8254->osc_base);
+               break;
+       case CMDF_ROUND_DOWN:
+               divisor = *nanosec / i8254->osc_base;
+               break;
+       }
+       if (divisor < 2)
+               divisor = 2;
+       if (divisor > I8254_MAX_COUNT)
+               divisor = I8254_MAX_COUNT;
+
+       *nanosec = divisor * i8254->osc_base;
+       i8254->next_div = divisor;
+}
+EXPORT_SYMBOL_GPL(comedi_8254_ns_to_timer);
+
+/**
+ * comedi_8254_set_busy - set/clear the "busy" flag for a given counter
+ * @i8254:     comedi_8254 struct for the timer
+ * @counter:   the counter number
+ * @busy:      set/clear flag
+ */
+void comedi_8254_set_busy(struct comedi_8254 *i8254,
+                         unsigned int counter, bool busy)
+{
+       if (counter < 3)
+               i8254->busy[counter] = busy;
+}
+EXPORT_SYMBOL_GPL(comedi_8254_set_busy);
+
+static int comedi_8254_insn_read(struct comedi_device *dev,
+                                struct comedi_subdevice *s,
+                                struct comedi_insn *insn,
+                                unsigned int *data)
+{
+       struct comedi_8254 *i8254 = s->private;
+       unsigned int chan = CR_CHAN(insn->chanspec);
+       int i;
+
+       if (i8254->busy[chan])
+               return -EBUSY;
+
+       for (i = 0; i < insn->n; i++)
+               data[i] = comedi_8254_read(i8254, chan);
+
+       return insn->n;
+}
+
+static int comedi_8254_insn_write(struct comedi_device *dev,
+                                 struct comedi_subdevice *s,
+                                 struct comedi_insn *insn,
+                                 unsigned int *data)
+{
+       struct comedi_8254 *i8254 = s->private;
+       unsigned int chan = CR_CHAN(insn->chanspec);
+
+       if (i8254->busy[chan])
+               return -EBUSY;
+
+       if (insn->n)
+               comedi_8254_write(i8254, chan, data[insn->n - 1]);
+
+       return insn->n;
+}
+
+static int comedi_8254_insn_config(struct comedi_device *dev,
+                                  struct comedi_subdevice *s,
+                                  struct comedi_insn *insn,
+                                  unsigned int *data)
+{
+       struct comedi_8254 *i8254 = s->private;
+       unsigned int chan = CR_CHAN(insn->chanspec);
+       int ret;
+
+       if (i8254->busy[chan])
+               return -EBUSY;
+
+       switch (data[0]) {
+       case INSN_CONFIG_RESET:
+               ret = comedi_8254_set_mode(i8254, chan,
+                                          I8254_MODE0 | I8254_BINARY);
+               if (ret)
+                       return ret;
+               break;
+       case INSN_CONFIG_SET_COUNTER_MODE:
+               ret = comedi_8254_set_mode(i8254, chan, data[1]);
+               if (ret)
+                       return ret;
+               break;
+       case INSN_CONFIG_8254_READ_STATUS:
+               data[1] = comedi_8254_status(i8254, chan);
+               break;
+       default:
+               /*
+                * If available, call the driver provided (*insn_config)
+                * to handle any driver implemented instructions.
+                */
+               if (i8254->insn_config)
+                       return i8254->insn_config(dev, s, insn, data);
+
+               return -EINVAL;
+       }
+
+       return insn->n;
+}
+
+/**
+ * comedi_8254_subdevice_init - initialize a comedi_subdevice for the 8254 timer
+ * @s:         comedi_subdevice struct
+ */
+void comedi_8254_subdevice_init(struct comedi_subdevice *s,
+                               struct comedi_8254 *i8254)
+{
+       s->type         = COMEDI_SUBD_COUNTER;
+       s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+       s->n_chan       = 3;
+       s->maxdata      = 0xffff;
+       s->range_table  = &range_unknown;
+       s->insn_read    = comedi_8254_insn_read;
+       s->insn_write   = comedi_8254_insn_write;
+       s->insn_config  = comedi_8254_insn_config;
+
+       s->private      = i8254;
+}
+EXPORT_SYMBOL_GPL(comedi_8254_subdevice_init);
+
+static struct comedi_8254 *__i8254_init(unsigned long iobase,
+                                       void __iomem *mmio,
+                                       unsigned int osc_base,
+                                       unsigned int iosize,
+                                       unsigned int regshift)
+{
+       struct comedi_8254 *i8254;
+       int i;
+
+       /* sanity check that the iosize is valid */
+       if (!(iosize == I8254_IO8 || iosize == I8254_IO16 ||
+             iosize == I8254_IO32))
+               return NULL;
+
+       i8254 = kzalloc(sizeof(*i8254), GFP_KERNEL);
+       if (!i8254)
+               return NULL;
+
+       i8254->iobase   = iobase;
+       i8254->mmio     = mmio;
+       i8254->iosize   = iosize;
+       i8254->regshift = regshift;
+
+       /* default osc_base to the max speed of a generic 8254 timer */
+       i8254->osc_base = osc_base ? osc_base : I8254_OSC_BASE_10MHZ;
+
+       /* reset all the counters by setting them to I8254_MODE0 */
+       for (i = 0; i < 3; i++)
+               comedi_8254_set_mode(i8254, i, I8254_MODE0 | I8254_BINARY);
+
+       return i8254;
+}
+
+/**
+ * comedi_8254_init - allocate and initialize the 8254 device for pio access
+ * @mmio:      port I/O base address
+ * @osc_base:  base time of the counter in ns
+ *             OPTIONAL - only used by comedi_8254_cascade_ns_to_timer()
+ * @iosize:    I/O register size
+ * @regshift:  register gap shift
+ */
+struct comedi_8254 *comedi_8254_init(unsigned long iobase,
+                                    unsigned int osc_base,
+                                    unsigned int iosize,
+                                    unsigned int regshift)
+{
+       return __i8254_init(iobase, NULL, osc_base, iosize, regshift);
+}
+EXPORT_SYMBOL_GPL(comedi_8254_init);
+
+/**
+ * comedi_8254_mm_init - allocate and initialize the 8254 device for mmio access
+ * @mmio:      memory mapped I/O base address
+ * @osc_base:  base time of the counter in ns
+ *             OPTIONAL - only used by comedi_8254_cascade_ns_to_timer()
+ * @iosize:    I/O register size
+ * @regshift:  register gap shift
+ */
+struct comedi_8254 *comedi_8254_mm_init(void __iomem *mmio,
+                                       unsigned int osc_base,
+                                       unsigned int iosize,
+                                       unsigned int regshift)
+{
+       return __i8254_init(0, mmio, osc_base, iosize, regshift);
+}
+EXPORT_SYMBOL_GPL(comedi_8254_mm_init);
+
+static int __init comedi_8254_module_init(void)
+{
+       return 0;
+}
+module_init(comedi_8254_module_init);
+
+static void __exit comedi_8254_module_exit(void)
+{
+}
+module_exit(comedi_8254_module_exit);
+
+MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
+MODULE_DESCRIPTION("Comedi: Generic 8254 timer/counter support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/comedi_8254.h b/drivers/staging/comedi/drivers/comedi_8254.h
new file mode 100644 (file)
index 0000000..d89f6d9
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * comedi_8254.h
+ * Generic 8254 timer/counter support
+ * Copyright (C) 2014 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * 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.
+ */
+
+#ifndef _COMEDI_8254_H
+#define _COMEDI_8254_H
+
+/*
+ * Common oscillator base values in nanoseconds
+ */
+#define I8254_OSC_BASE_10MHZ   100
+#define I8254_OSC_BASE_5MHZ    200
+#define I8254_OSC_BASE_4MHZ    250
+#define I8254_OSC_BASE_2MHZ    500
+#define I8254_OSC_BASE_1MHZ    1000
+#define I8254_OSC_BASE_100KHZ  10000
+#define I8254_OSC_BASE_10KHZ   100000
+#define I8254_OSC_BASE_1KHZ    1000000
+
+/*
+ * I/O access size used to read/write registers
+ */
+#define I8254_IO8              1
+#define I8254_IO16             2
+#define I8254_IO32             4
+
+/*
+ * Register map for generic 8254 timer (I8254_IO8 with 0 regshift)
+ */
+#define I8254_COUNTER0_REG             0x00
+#define I8254_COUNTER1_REG             0x01
+#define I8254_COUNTER2_REG             0x02
+#define I8254_CTRL_REG                 0x03
+#define I8254_CTRL_SEL_CTR(x)          ((x) << 6)
+#define I8254_CTRL_READBACK_COUNT      ((3 << 6) | (1 << 4))
+#define I8254_CTRL_READBACK_STATUS     ((3 << 6) | (1 << 5))
+#define I8254_CTRL_READBACK_SEL_CTR(x) (2 << (x))
+#define I8254_CTRL_LATCH               (0 << 4)
+#define I8254_CTRL_LSB_ONLY            (1 << 4)
+#define I8254_CTRL_MSB_ONLY            (2 << 4)
+#define I8254_CTRL_LSB_MSB             (3 << 4)
+
+/* counter maps zero to 0x10000 */
+#define I8254_MAX_COUNT                        0x10000
+
+/**
+ * struct comedi_8254 - private data used by this module
+ * @iobase:            PIO base address of the registers (in/out)
+ * @mmio:              MMIO base address of the registers (read/write)
+ * @iosize:            I/O size used to access the registers (b/w/l)
+ * @regshift:          register gap shift
+ * @osc_base:          cascaded oscillator speed in ns
+ * @divisor:           divisor for single counter
+ * @divisor1:          divisor loaded into first cascaded counter
+ * @divisor2:          divisor loaded into second cascaded counter
+ * #next_div:          next divisor for single counter
+ * @next_div1:         next divisor to use for first cascaded counter
+ * @next_div2:         next divisor to use for second cascaded counter
+ * @clock_src;         current clock source for each counter (driver specific)
+ * @gate_src;          current gate source  for each counter (driver specific)
+ * @busy:              flags used to indicate that a counter is "busy"
+ * @insn_config:       driver specific (*insn_config) callback
+ */
+struct comedi_8254 {
+       unsigned long iobase;
+       void __iomem *mmio;
+       unsigned int iosize;
+       unsigned int regshift;
+       unsigned int osc_base;
+       unsigned int divisor;
+       unsigned int divisor1;
+       unsigned int divisor2;
+       unsigned int next_div;
+       unsigned int next_div1;
+       unsigned int next_div2;
+       unsigned int clock_src[3];
+       unsigned int gate_src[3];
+       bool busy[3];
+
+       int (*insn_config)(struct comedi_device *, struct comedi_subdevice *s,
+                          struct comedi_insn *, unsigned int *data);
+};
+
+unsigned int comedi_8254_status(struct comedi_8254 *, unsigned int counter);
+unsigned int comedi_8254_read(struct comedi_8254 *, unsigned int counter);
+void comedi_8254_write(struct comedi_8254 *,
+                      unsigned int counter, unsigned int val);
+
+int comedi_8254_set_mode(struct comedi_8254 *,
+                        unsigned int counter, unsigned int mode);
+int comedi_8254_load(struct comedi_8254 *,
+                    unsigned int counter, unsigned int val, unsigned int mode);
+
+void comedi_8254_pacer_enable(struct comedi_8254 *,
+                             unsigned int counter1, unsigned int counter2,
+                             bool enable);
+void comedi_8254_update_divisors(struct comedi_8254 *);
+void comedi_8254_cascade_ns_to_timer(struct comedi_8254 *,
+                                    unsigned int *nanosec, unsigned int flags);
+void comedi_8254_ns_to_timer(struct comedi_8254 *,
+                            unsigned int *nanosec, unsigned int flags);
+
+void comedi_8254_set_busy(struct comedi_8254 *,
+                         unsigned int counter, bool busy);
+
+void comedi_8254_subdevice_init(struct comedi_subdevice *,
+                               struct comedi_8254 *);
+
+struct comedi_8254 *comedi_8254_init(unsigned long iobase,
+                                    unsigned int osc_base,
+                                    unsigned int iosize,
+                                    unsigned int regshift);
+struct comedi_8254 *comedi_8254_mm_init(void __iomem *mmio,
+                                       unsigned int osc_base,
+                                       unsigned int iosize,
+                                       unsigned int regshift);
+
+#endif /* _COMEDI_8254_H */
index 221d3819c96744711fd2fe2c018317dd4691d389..96db0c2686a1e6971478ee74c23412049fb654cf 100644 (file)
@@ -267,7 +267,6 @@ static int do_dev_config(struct comedi_device *dev, struct comedi_devconfig *it)
                                strlcat(devpriv->name, buf,
                                        sizeof(devpriv->name));
                        }
-
                }
        }
 
@@ -313,9 +312,9 @@ static int bonding_attach(struct comedi_device *dev,
        s->insn_config = bonding_dio_insn_config;
 
        dev_info(dev->class_dev,
-               "%s: %s attached, %u channels from %u devices\n",
-               dev->driver->driver_name, dev->board_name,
-               devpriv->nchans, devpriv->ndevs);
+                "%s: %s attached, %u channels from %u devices\n",
+                dev->driver->driver_name, dev->board_name,
+                devpriv->nchans, devpriv->ndevs);
 
        return 0;
 }
diff --git a/drivers/staging/comedi/drivers/comedi_fc.h b/drivers/staging/comedi/drivers/comedi_fc.h
deleted file mode 100644 (file)
index 756be93..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * comedi_fc.h
- * This is a place for code driver writers wish to share between
- * two or more drivers. These functions are meant to be used only
- * by drivers, they are NOT part of the kcomedilib API!
- *
- * Author: Frank Mori Hess <fmhess@users.sourceforge.net>
- * Copyright (C) 2002 Frank Mori Hess
- *
- * 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 _COMEDI_FC_H
-#define _COMEDI_FC_H
-
-#include "../comedidev.h"
-
-/**
- * cfc_check_trigger_src() - trivially validate a comedi_cmd trigger source
- * @src: pointer to the trigger source to validate
- * @flags: bitmask of valid TRIG_* for the trigger
- *
- * This is used in "step 1" of the do_cmdtest functions of comedi drivers
- * to vaildate the comedi_cmd triggers. The mask of the @src against the
- * @flags allows the userspace comedilib to pass all the comedi_cmd
- * triggers as TRIG_ANY and get back a bitmask of the valid trigger sources.
- */
-static inline int cfc_check_trigger_src(unsigned int *src, unsigned int flags)
-{
-       unsigned int orig_src = *src;
-
-       *src = orig_src & flags;
-       if (*src == TRIG_INVALID || *src != orig_src)
-               return -EINVAL;
-       return 0;
-}
-
-/**
- * cfc_check_trigger_is_unique() - make sure a trigger source is unique
- * @src: the trigger source to check
- */
-static inline int cfc_check_trigger_is_unique(unsigned int src)
-{
-       /* this test is true if more than one _src bit is set */
-       if ((src & (src - 1)) != 0)
-               return -EINVAL;
-       return 0;
-}
-
-/**
- * cfc_check_trigger_arg_is() - trivially validate a trigger argument
- * @arg: pointer to the trigger arg to validate
- * @val: the value the argument should be
- */
-static inline int cfc_check_trigger_arg_is(unsigned int *arg, unsigned int val)
-{
-       if (*arg != val) {
-               *arg = val;
-               return -EINVAL;
-       }
-       return 0;
-}
-
-/**
- * cfc_check_trigger_arg_min() - trivially validate a trigger argument
- * @arg: pointer to the trigger arg to validate
- * @val: the minimum value the argument should be
- */
-static inline int cfc_check_trigger_arg_min(unsigned int *arg,
-                                           unsigned int val)
-{
-       if (*arg < val) {
-               *arg = val;
-               return -EINVAL;
-       }
-       return 0;
-}
-
-/**
- * cfc_check_trigger_arg_max() - trivially validate a trigger argument
- * @arg: pointer to the trigger arg to validate
- * @val: the maximum value the argument should be
- */
-static inline int cfc_check_trigger_arg_max(unsigned int *arg,
-                                           unsigned int val)
-{
-       if (*arg > val) {
-               *arg = val;
-               return -EINVAL;
-       }
-       return 0;
-}
-
-#endif /* _COMEDI_FC_H */
index e856f01ca07716c8acb3881bbe8e4373a64beab5..6ba71d114a95c180f95eebb6d1af93707cd50818 100644 (file)
@@ -235,7 +235,8 @@ void comedi_isadma_free(struct comedi_isadma *dma)
                        desc = &dma->desc[i];
                        if (desc->virt_addr)
                                dma_free_coherent(NULL, desc->maxsize,
-                                               desc->virt_addr, desc->hw_addr);
+                                                 desc->virt_addr,
+                                                 desc->hw_addr);
                }
                kfree(dma->desc);
        }
index ceef6931edbe019bd52d688a6e5dab6b5de7179b..15a4093efda13869c0be6be98429ff03fdf5cbd4 100644 (file)
@@ -69,8 +69,6 @@
 
 #include "../comedidev.h"
 
-#include "comedi_fc.h"
-
 /*
  * Register map
  */
@@ -161,11 +159,11 @@ static int parport_intr_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);
 
        if (err)
                return 1;
@@ -175,11 +173,12 @@ static int parport_intr_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-       err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
index e56525a1c8f3bf55571e04ed4caae6ce011f9c5b..80d613c0fbc65b85477460f388bcc337ddafed1c 100644 (file)
@@ -50,7 +50,6 @@ zero volts).
 
 #include <asm/div64.h>
 
-#include "comedi_fc.h"
 #include <linux/timer.h>
 #include <linux/ktime.h>
 
@@ -225,19 +224,20 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW | TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
+       err |= comedi_check_trigger_src(&cmd->convert_src,
+                                       TRIG_NOW | TRIG_TIMER);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -246,26 +246,30 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (cmd->convert_src == TRIG_NOW)
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                nano_per_micro);
-               if (cmd->convert_src == TRIG_TIMER)
-                       err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                       cmd->convert_arg * cmd->chanlist_len);
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   nano_per_micro);
+               if (cmd->convert_src == TRIG_TIMER) {
+                       err |= comedi_check_trigger_arg_min(&cmd->
+                                                           scan_begin_arg,
+                                                           cmd->convert_arg *
+                                                           cmd->chanlist_len);
+               }
        }
 
-       err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -277,14 +281,14 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
                /* round to nearest microsec */
                arg = nano_per_micro *
                      ((arg + (nano_per_micro / 2)) / nano_per_micro);
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
        if (cmd->convert_src == TRIG_TIMER) {
                arg = cmd->convert_arg;
                /* round to nearest microsec */
                arg = nano_per_micro *
                      ((arg + (nano_per_micro / 2)) / nano_per_micro);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
        }
 
        if (err)
@@ -420,9 +424,8 @@ static int waveform_attach(struct comedi_device *dev,
        for (i = 0; i < s->n_chan; i++)
                devpriv->ao_loopbacks[i] = s->maxdata / 2;
 
-       init_timer(&devpriv->timer);
-       devpriv->timer.function = waveform_ai_interrupt;
-       devpriv->timer.data = (unsigned long)dev;
+       setup_timer(&devpriv->timer, waveform_ai_interrupt,
+                   (unsigned long)dev);
 
        dev_info(dev->class_dev,
                 "%s: %i microvolt, %li microsecond waveform attached\n",
index 205f9df345a212d9beafde891ce2c125617b863c..4956a49a61400aab2dd228a6fe282f381cb20aa3 100644 (file)
@@ -26,9 +26,8 @@ Configuration Options: not applicable, uses comedi PCI auto config
 */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 /*
  * Register map
@@ -59,7 +58,7 @@ static int contec_di_insn_bits(struct comedi_device *dev,
 }
 
 static int contec_auto_attach(struct comedi_device *dev,
-                                       unsigned long context_unused)
+                             unsigned long context_unused)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        struct comedi_subdevice *s;
index 96697fbb5239af57df6dc6ba93da02cd0d7b0a52..f97d18d92255bf6b6047d29610975a3a22aff4ae 100644 (file)
@@ -103,11 +103,10 @@ Configuration options: not applicable, uses PCI auto config
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #include "8255.h"
 
@@ -649,7 +648,7 @@ static const void *daqboard2000_find_boardinfo(struct comedi_device *dev,
 }
 
 static int daqboard2000_auto_attach(struct comedi_device *dev,
-                                             unsigned long context_unused)
+                                   unsigned long context_unused)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        const struct daq200_boardtype *board;
index c78c0df9bbe30e731403db335be53262862b8ff5..73f4c8dbbde3ff926eba8e3280d7dc72a985aaa1 100644 (file)
@@ -23,7 +23,7 @@
 #include "../comedidev.h"
 
 #include "8255.h"
-#include "8253.h"
+#include "comedi_8254.h"
 #include "das08.h"
 
 /*
@@ -359,62 +359,6 @@ static int das08_ao_insn_write(struct comedi_device *dev,
        return insn->n;
 }
 
-static void i8254_initialize(struct comedi_device *dev)
-{
-       const struct das08_board_struct *thisboard = dev->board_ptr;
-       unsigned long i8254_iobase = dev->iobase + thisboard->i8254_offset;
-       unsigned int mode = I8254_MODE0 | I8254_BINARY;
-       int i;
-
-       for (i = 0; i < 3; ++i)
-               i8254_set_mode(i8254_iobase, 0, i, mode);
-}
-
-static int das08_counter_read(struct comedi_device *dev,
-                             struct comedi_subdevice *s,
-                             struct comedi_insn *insn, unsigned int *data)
-{
-       const struct das08_board_struct *thisboard = dev->board_ptr;
-       unsigned long i8254_iobase = dev->iobase + thisboard->i8254_offset;
-       int chan = insn->chanspec;
-
-       data[0] = i8254_read(i8254_iobase, 0, chan);
-       return 1;
-}
-
-static int das08_counter_write(struct comedi_device *dev,
-                              struct comedi_subdevice *s,
-                              struct comedi_insn *insn, unsigned int *data)
-{
-       const struct das08_board_struct *thisboard = dev->board_ptr;
-       unsigned long i8254_iobase = dev->iobase + thisboard->i8254_offset;
-       int chan = insn->chanspec;
-
-       i8254_write(i8254_iobase, 0, chan, data[0]);
-       return 1;
-}
-
-static int das08_counter_config(struct comedi_device *dev,
-                               struct comedi_subdevice *s,
-                               struct comedi_insn *insn, unsigned int *data)
-{
-       const struct das08_board_struct *thisboard = dev->board_ptr;
-       unsigned long i8254_iobase = dev->iobase + thisboard->i8254_offset;
-       int chan = insn->chanspec;
-
-       switch (data[0]) {
-       case INSN_CONFIG_SET_COUNTER_MODE:
-               i8254_set_mode(i8254_iobase, 0, chan, data[1]);
-               break;
-       case INSN_CONFIG_8254_READ_STATUS:
-               data[1] = i8254_status(i8254_iobase, 0, chan);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 2;
-}
-
 int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
 {
        const struct das08_board_struct *thisboard = dev->board_ptr;
@@ -464,7 +408,7 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
                if (ret)
                        return ret;
 
-               /* intialize all channels to 0V */
+               /* initialize all channels to 0V */
                for (i = 0; i < s->n_chan; i++) {
                        s->readback[i] = s->maxdata / 2;
                        das08_ao_set_data(dev, i, s->readback[i]);
@@ -511,17 +455,16 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
                s->type = COMEDI_SUBD_UNUSED;
        }
 
+       /* Counter subdevice (8254) */
        s = &dev->subdevices[5];
-       /* 8254 */
-       if (thisboard->i8254_offset != 0) {
-               s->type = COMEDI_SUBD_COUNTER;
-               s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-               s->n_chan = 3;
-               s->maxdata = 0xFFFF;
-               s->insn_read = das08_counter_read;
-               s->insn_write = das08_counter_write;
-               s->insn_config = das08_counter_config;
-               i8254_initialize(dev);
+       if (thisboard->i8254_offset) {
+               dev->pacer = comedi_8254_init(dev->iobase +
+                                             thisboard->i8254_offset,
+                                             0, I8254_IO8, 0);
+               if (!dev->pacer)
+                       return -ENOMEM;
+
+               comedi_8254_subdevice_init(s, dev->pacer);
        } else {
                s->type = COMEDI_SUBD_UNUSED;
        }
index b2ea10b848c354a3c3dff92697003a372f2f6f28..d8d27fa4449133720189cf1e681877d571f9b968 100644 (file)
@@ -32,9 +32,8 @@
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #include "das08.h"
 
index 2c20311120f18638d251225a79bf88f36d69a11a..d7cf4b153f7c37889efd8032712ee64a33f27426 100644 (file)
@@ -76,8 +76,7 @@
 #include "../comedidev.h"
 
 #include "comedi_isadma.h"
-#include "comedi_fc.h"
-#include "8253.h"
+#include "comedi_8254.h"
 #include "8255.h"
 
 #define DAS16_DMA_SIZE 0xff00  /*  size in bytes of allocated dma buffer */
@@ -599,29 +598,29 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
 
        trig_mask = TRIG_FOLLOW;
        if (devpriv->can_burst)
                trig_mask |= TRIG_TIMER | TRIG_EXT;
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, trig_mask);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, trig_mask);
 
        trig_mask = TRIG_TIMER | TRIG_EXT;
        if (devpriv->can_burst)
                trig_mask |= TRIG_NOW;
-       err |= cfc_check_trigger_src(&cmd->convert_src, trig_mask);
+       err |= comedi_check_trigger_src(&cmd->convert_src, trig_mask);
 
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -636,26 +635,30 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        /* check against maximum frequency */
-       if (cmd->scan_begin_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                       board->ai_speed * cmd->chanlist_len);
+       if (cmd->scan_begin_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   board->ai_speed *
+                                                   cmd->chanlist_len);
+       }
 
-       if (cmd->convert_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                board->ai_speed);
+       if (cmd->convert_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                   board->ai_speed);
+       }
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -663,19 +666,13 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
        /*  step 4: fix up arguments */
        if (cmd->scan_begin_src == TRIG_TIMER) {
                arg = cmd->scan_begin_arg;
-               i8253_cascade_ns_to_timer(devpriv->clockbase,
-                                         &devpriv->divisor1,
-                                         &devpriv->divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
        if (cmd->convert_src == TRIG_TIMER) {
                arg = cmd->convert_arg;
-               i8253_cascade_ns_to_timer(devpriv->clockbase,
-                                         &devpriv->divisor1,
-                                         &devpriv->divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
        }
        if (err)
                return 4;
@@ -693,17 +690,9 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
                                    unsigned int flags)
 {
-       struct das16_private_struct *devpriv = dev->private;
-       unsigned long timer_base = dev->iobase + DAS16_TIMER_BASE_REG;
-
-       i8253_cascade_ns_to_timer(devpriv->clockbase,
-                                 &devpriv->divisor1, &devpriv->divisor2,
-                                 &ns, flags);
-
-       i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
-       i8254_write(timer_base, 0, 1, devpriv->divisor1);
-       i8254_write(timer_base, 0, 2, devpriv->divisor2);
+       comedi_8254_cascade_ns_to_timer(dev->pacer, &ns, flags);
+       comedi_8254_update_divisors(dev->pacer);
+       comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
 
        return ns;
 }
@@ -722,7 +711,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
 
        if (cmd->flags & CMDF_PRIORITY) {
                dev_err(dev->class_dev,
-                        "isa dma transfers cannot be performed with CMDF_PRIORITY, aborting\n");
+                       "isa dma transfers cannot be performed with CMDF_PRIORITY, aborting\n");
                return -1;
        }
 
@@ -935,7 +924,6 @@ static void das16_reset(struct comedi_device *dev)
        outb(0, dev->iobase + DAS16_STATUS_REG);
        outb(0, dev->iobase + DAS16_CTRL_REG);
        outb(0, dev->iobase + DAS16_PACER_REG);
-       outb(0, dev->iobase + DAS16_TIMER_BASE_REG + i8254_control_reg);
 }
 
 static void das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan)
@@ -950,9 +938,8 @@ static void das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan)
        devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan,
                                           DAS16_DMA_SIZE, COMEDI_ISADMA_READ);
        if (devpriv->dma) {
-               init_timer(&devpriv->timer);
-               devpriv->timer.function = das16_timer_interrupt;
-               devpriv->timer.data = (unsigned long)dev;
+               setup_timer(&devpriv->timer, das16_timer_interrupt,
+                           (unsigned long)dev);
        }
 }
 
@@ -1039,6 +1026,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        const struct das16_board *board = dev->board_ptr;
        struct das16_private_struct *devpriv;
        struct comedi_subdevice *s;
+       unsigned int osc_base;
        unsigned int status;
        int ret;
 
@@ -1078,21 +1066,21 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                return -EINVAL;
 
        /*  get master clock speed */
+       osc_base = I8254_OSC_BASE_1MHZ;
        if (devpriv->can_burst) {
                status = inb(dev->iobase + DAS1600_STATUS_REG);
-
                if (status & DAS1600_STATUS_CLK_10MHZ)
-                       devpriv->clockbase = I8254_OSC_BASE_10MHZ;
-               else
-                       devpriv->clockbase = I8254_OSC_BASE_1MHZ;
+                       osc_base = I8254_OSC_BASE_10MHZ;
        } else {
                if (it->options[3])
-                       devpriv->clockbase = I8254_OSC_BASE_1MHZ /
-                                            it->options[3];
-               else
-                       devpriv->clockbase = I8254_OSC_BASE_1MHZ;
+                       osc_base = I8254_OSC_BASE_1MHZ / it->options[3];
        }
 
+       dev->pacer = comedi_8254_init(dev->iobase + DAS16_TIMER_BASE_REG,
+                                     osc_base, I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        das16_alloc_dma(dev, it->options[2]);
 
        ret = comedi_alloc_subdevices(dev, 4 + board->has_8255);
index 3666a68979fb65379b894b89a5d834141c77e9d0..1adf6a71a9f3f00089753f829b069ca47bd82b35 100644 (file)
@@ -53,12 +53,12 @@ irq can be omitted, although the cmd interface will not work without it.
 */
 
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include "../comedidev.h"
 
 #include "8255.h"
-#include "8253.h"
-#include "comedi_fc.h"
+#include "comedi_8254.h"
 
 #define DAS16M1_SIZE2 8
 
@@ -103,8 +103,6 @@ irq can be omitted, although the cmd interface will not work without it.
 #define   Q_RANGE(x)             (((x) & 0xf) << 4)
 #define   UNIPOLAR               0x40
 #define DAS16M1_8254_FIRST             0x8
-#define DAS16M1_8254_FIRST_CNTRL       0xb
-#define   TOTAL_CLEAR                    0x30
 #define DAS16M1_8254_SECOND            0xc
 #define DAS16M1_82C55                  0x400
 #define DAS16M1_8254_THIRD             0x404
@@ -124,6 +122,7 @@ static const struct comedi_lrange range_das16m1 = {
 };
 
 struct das16m1_private_struct {
+       struct comedi_8254 *counter;
        unsigned int control_state;
        unsigned int adc_count; /*  number of samples completed */
        /* initial value in lower half of hardware conversion counter,
@@ -131,8 +130,6 @@ struct das16m1_private_struct {
         * counter yet (loaded by first sample conversion) */
        u16 initial_hw_count;
        unsigned short ai_buffer[FIFO_SIZE];
-       unsigned int divisor1;  /*  divides master clock to obtain conversion speed */
-       unsigned int divisor2;  /*  divides master clock to obtain conversion speed */
        unsigned long extra_iobase;
 };
 
@@ -169,7 +166,7 @@ static int das16m1_ai_check_chanlist(struct comedi_device *dev,
 
                if ((i % 2) != (chan % 2)) {
                        dev_dbg(dev->class_dev,
-                                "even/odd channels must go have even/odd chanlist indices\n");
+                               "even/odd channels must go have even/odd chanlist indices\n");
                        return -EINVAL;
                }
        }
@@ -180,26 +177,25 @@ static int das16m1_ai_check_chanlist(struct comedi_device *dev,
 static int das16m1_cmd_test(struct comedi_device *dev,
                            struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
-       struct das16m1_private_struct *devpriv = dev->private;
        int err = 0;
-       unsigned int arg;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->convert_src,
+                                       TRIG_TIMER | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -208,20 +204,21 @@ static int das16m1_cmd_test(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
        if (cmd->convert_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 1000);
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 1000);
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -229,12 +226,10 @@ static int das16m1_cmd_test(struct comedi_device *dev,
        /* step 4: fix up arguments */
 
        if (cmd->convert_src == TRIG_TIMER) {
-               arg = cmd->convert_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
-                                         &devpriv->divisor1,
-                                         &devpriv->divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               unsigned int arg = cmd->convert_arg;
+
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
        }
 
        if (err)
@@ -250,25 +245,12 @@ static int das16m1_cmd_test(struct comedi_device *dev,
        return 0;
 }
 
-static void das16m1_set_pacer(struct comedi_device *dev)
-{
-       struct das16m1_private_struct *devpriv = dev->private;
-       unsigned long timer_base = dev->iobase + DAS16M1_8254_SECOND;
-
-       i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
-
-       i8254_write(timer_base, 0, 1, devpriv->divisor1);
-       i8254_write(timer_base, 0, 2, devpriv->divisor2);
-}
-
 static int das16m1_cmd_exec(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
        struct das16m1_private_struct *devpriv = dev->private;
        struct comedi_async *async = s->async;
        struct comedi_cmd *cmd = &async->cmd;
-       unsigned long timer_base = dev->iobase + DAS16M1_8254_FIRST;
        unsigned int byte, i;
 
        /* disable interrupts and internal pacer */
@@ -277,14 +259,21 @@ static int das16m1_cmd_exec(struct comedi_device *dev,
 
        /*  set software count */
        devpriv->adc_count = 0;
-       /* Initialize lower half of hardware counter, used to determine how
+
+       /*
+        * Initialize lower half of hardware counter, used to determine how
         * many samples are in fifo.  Value doesn't actually load into counter
-        * until counter's next clock (the next a/d conversion) */
-       i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
-       i8254_write(timer_base, 0, 1, 0);
-       /* remember current reading of counter so we know when counter has
-        * actually been loaded */
-       devpriv->initial_hw_count = i8254_read(timer_base, 0, 1);
+        * until counter's next clock (the next a/d conversion).
+        */
+       comedi_8254_set_mode(devpriv->counter, 1, I8254_MODE2 | I8254_BINARY);
+       comedi_8254_write(devpriv->counter, 1, 0);
+
+       /*
+        * Remember current reading of counter so we know when counter has
+        * actually been loaded.
+        */
+       devpriv->initial_hw_count = comedi_8254_read(devpriv->counter, 1);
+
        /* setup channel/gain queue */
        for (i = 0; i < cmd->chanlist_len; i++) {
                outb(i, dev->iobase + DAS16M1_QUEUE_ADDR);
@@ -297,7 +286,8 @@ static int das16m1_cmd_exec(struct comedi_device *dev,
        /* enable interrupts and set internal pacer counter mode and counts */
        devpriv->control_state &= ~PACER_MASK;
        if (cmd->convert_src == TRIG_TIMER) {
-               das16m1_set_pacer(dev);
+               comedi_8254_update_divisors(dev->pacer);
+               comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
                devpriv->control_state |= INT_PACER;
        } else {        /* TRIG_EXT */
                devpriv->control_state |= EXT_PACER;
@@ -417,8 +407,8 @@ static void das16m1_handler(struct comedi_device *dev, unsigned int status)
        async = s->async;
        cmd = &async->cmd;
 
-       /*  figure out how many samples are in fifo */
-       hw_counter = i8254_read(dev->iobase + DAS16M1_8254_FIRST, 0, 1);
+       /* figure out how many samples are in fifo */
+       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) {
@@ -563,6 +553,16 @@ static int das16m1_attach(struct comedi_device *dev,
                        dev->irq = it->options[1];
        }
 
+       dev->pacer = comedi_8254_init(dev->iobase + DAS16M1_8254_SECOND,
+                                     I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
+       devpriv->counter = comedi_8254_init(dev->iobase + DAS16M1_8254_FIRST,
+                                           0, I8254_IO8, 0);
+       if (!devpriv->counter)
+               return -ENOMEM;
+
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
                return ret;
@@ -609,9 +609,6 @@ static int das16m1_attach(struct comedi_device *dev,
        if (ret)
                return ret;
 
-       /*  disable upper half of hardware conversion counter so it doesn't mess with us */
-       outb(TOTAL_CLEAR, dev->iobase + DAS16M1_8254_FIRST_CNTRL);
-
        /*  initialize digital output lines */
        outb(0, dev->iobase + DAS16M1_DIO);
 
@@ -626,8 +623,11 @@ static void das16m1_detach(struct comedi_device *dev)
 {
        struct das16m1_private_struct *devpriv = dev->private;
 
-       if (devpriv && devpriv->extra_iobase)
-               release_region(devpriv->extra_iobase, DAS16M1_SIZE2);
+       if (devpriv) {
+               if (devpriv->extra_iobase)
+                       release_region(devpriv->extra_iobase, DAS16M1_SIZE2);
+               kfree(devpriv->counter);
+       }
        comedi_legacy_detach(dev);
 }
 
index 0790a28828de79f3c5625d3739ff2972f669cca1..53baf37cd21a6ab71e6eea8bb66a524e51f8e24e 100644 (file)
@@ -102,8 +102,7 @@ TODO:
 #include "../comedidev.h"
 
 #include "comedi_isadma.h"
-#include "comedi_fc.h"
-#include "8253.h"
+#include "comedi_8254.h"
 
 /* misc. defines */
 #define DAS1800_SIZE           16      /* uses 16 io addresses */
@@ -422,8 +421,6 @@ static const struct das1800_board das1800_boards[] = {
 
 struct das1800_private {
        struct comedi_isadma *dma;
-       unsigned int divisor1;  /* value to load into board's counter 1 for timed conversions */
-       unsigned int divisor2;  /* value to load into board's counter 2 for timed conversions */
        int irq_dma_bits;       /* bits for control register b */
        /* dma bits for control register b, stored so that dma can be
         * turned on and off */
@@ -491,9 +488,7 @@ static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
 
        while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
                dpnt = inw(dev->iobase + DAS1800_FIFO);
-               /* convert to unsigned type if we are in a bipolar mode */
-               if (!unipolar)
-                       ;
+               /* convert to unsigned type */
                dpnt = munge_bipolar_sample(dev, dpnt);
                comedi_buf_write_samples(s, &dpnt, 1);
 
@@ -731,18 +726,18 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev,
                                 struct comedi_cmd *cmd)
 {
        const struct das1800_board *thisboard = dev->board_ptr;
-       struct das1800_private *devpriv = dev->private;
        int err = 0;
        unsigned int arg;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src,
+       err |= comedi_check_trigger_src(&cmd->convert_src,
+                                       TRIG_TIMER | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src,
                                        TRIG_COUNT | TRIG_EXT | TRIG_NONE);
 
        if (err)
@@ -750,10 +745,10 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev,
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -766,21 +761,23 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
-       if (cmd->convert_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                thisboard->ai_speed);
+       if (cmd->convert_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                   thisboard->ai_speed);
+       }
 
-       err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        switch (cmd->stop_src) {
        case TRIG_COUNT:
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
                break;
        case TRIG_NONE:
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
                break;
        default:
                break;
@@ -795,35 +792,24 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev,
            cmd->convert_src == TRIG_TIMER) {
                /* we are not in burst mode */
                arg = cmd->convert_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
-                                         &devpriv->divisor1,
-                                         &devpriv->divisor2,
-                                         &cmd->convert_arg, cmd->flags);
-               if (arg != cmd->convert_arg)
-                       err++;
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
        } else if (cmd->convert_src == TRIG_TIMER) {
                /* we are in burst mode */
-               arg = cmd->convert_arg;
-               cmd->convert_arg = burst_convert_arg(cmd->convert_arg,
-                                                    cmd->flags);
-               if (arg != cmd->convert_arg)
-                       err++;
+               arg = burst_convert_arg(cmd->convert_arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
 
                if (cmd->scan_begin_src == TRIG_TIMER) {
                        arg = cmd->convert_arg * cmd->chanlist_len;
-                       if (arg > cmd->scan_begin_arg) {
-                               cmd->scan_begin_arg = arg;
-                               err++;
-                       }
+                       err |= comedi_check_trigger_arg_max(&cmd->
+                                                           scan_begin_arg,
+                                                           arg);
 
                        arg = cmd->scan_begin_arg;
-                       i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
-                                                 &devpriv->divisor1,
-                                                 &devpriv->divisor2,
-                                                 &cmd->scan_begin_arg,
-                                                 cmd->flags);
-                       if (arg != cmd->scan_begin_arg)
-                               err++;
+                       comedi_8254_cascade_ns_to_timer(dev->pacer, &arg,
+                                                       cmd->flags);
+                       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg,
+                                                          arg);
                }
        }
 
@@ -910,31 +896,6 @@ static int control_c_bits(const struct comedi_cmd *cmd)
        return control_c;
 }
 
-static void das1800_setup_counters(struct comedi_device *dev,
-                                  const struct comedi_cmd *cmd)
-{
-       struct das1800_private *devpriv = dev->private;
-       unsigned long timer_base = dev->iobase + DAS1800_COUNTER;
-
-       /* setup cascaded counters for conversion/scan frequency */
-       if ((cmd->scan_begin_src == TRIG_FOLLOW ||
-            cmd->scan_begin_src == TRIG_TIMER) &&
-           cmd->convert_src == TRIG_TIMER) {
-               i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
-               i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
-
-               i8254_write(timer_base, 0, 1, devpriv->divisor1);
-               i8254_write(timer_base, 0, 2, devpriv->divisor2);
-       }
-
-       /* setup counter 0 for 'about triggering' */
-       if (cmd->stop_src == TRIG_EXT) {
-               i8254_set_mode(timer_base, 0, 0, I8254_MODE0 | I8254_BINARY);
-
-               i8254_write(timer_base, 0, 0, 1);
-       }
-}
-
 static unsigned int das1800_ai_transfer_size(struct comedi_device *dev,
                                             struct comedi_subdevice *s,
                                             unsigned int maxbytes,
@@ -1053,7 +1014,19 @@ static int das1800_ai_do_cmd(struct comedi_device *dev,
 
        /* setup card and start */
        program_chanlist(dev, cmd);
-       das1800_setup_counters(dev, cmd);
+
+       /* setup cascaded counters for conversion/scan frequency */
+       if ((cmd->scan_begin_src == TRIG_FOLLOW ||
+            cmd->scan_begin_src == TRIG_TIMER) &&
+           cmd->convert_src == TRIG_TIMER) {
+               comedi_8254_update_divisors(dev->pacer);
+               comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
+       }
+
+       /* setup counter 0 for 'about triggering' */
+       if (cmd->stop_src == TRIG_EXT)
+               comedi_8254_load(dev->pacer, 0, 1, I8254_MODE0 | I8254_BINARY);
+
        das1800_ai_setup_dma(dev, s);
        outb(control_c, dev->iobase + DAS1800_CONTROL_C);
        /*  set conversion rate and length for burst mode */
@@ -1171,7 +1144,6 @@ static int das1800_di_rbits(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
-
        data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
        data[0] = 0;
 
@@ -1378,6 +1350,11 @@ static int das1800_attach(struct comedi_device *dev,
        if (!devpriv->fifo_buf)
                return -ENOMEM;
 
+       dev->pacer = comedi_8254_init(dev->iobase + DAS1800_COUNTER,
+                                     I8254_OSC_BASE_5MHZ, I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
                return ret;
index b8755b50a11e42d64bb103aa3ea27d0c0e2af79f..1701294b79cdd59eee72612de6ec278c950b0a05 100644 (file)
@@ -35,8 +35,8 @@
 #include <linux/interrupt.h>
 
 #include "../comedidev.h"
-#include "comedi_fc.h"
-#include "8253.h"
+
+#include "comedi_8254.h"
 
 /*
  * Register I/O map
@@ -138,11 +138,6 @@ static struct das6402_boardinfo das6402_boards[] = {
 
 struct das6402_private {
        unsigned int irq;
-
-       unsigned int count;
-       unsigned int divider1;
-       unsigned int divider2;
-
        unsigned int ao_range;
 };
 
@@ -172,27 +167,6 @@ static void das6402_ai_clear_eoc(struct comedi_device *dev)
        outb(DAS6402_STATUS_W_CLRINT, dev->iobase + DAS6402_STATUS_REG);
 }
 
-static void das6402_enable_counter(struct comedi_device *dev, bool load)
-{
-       struct das6402_private *devpriv = dev->private;
-       unsigned long timer_iobase = dev->iobase + DAS6402_TIMER_BASE;
-
-       if (load) {
-               i8254_set_mode(timer_iobase, 0, 0, I8254_MODE0 | I8254_BINARY);
-               i8254_set_mode(timer_iobase, 0, 1, I8254_MODE2 | I8254_BINARY);
-               i8254_set_mode(timer_iobase, 0, 2, I8254_MODE2 | I8254_BINARY);
-
-               i8254_write(timer_iobase, 0, 0, devpriv->count);
-               i8254_write(timer_iobase, 0, 1, devpriv->divider1);
-               i8254_write(timer_iobase, 0, 2, devpriv->divider2);
-
-       } else {
-               i8254_set_mode(timer_iobase, 0, 0, I8254_MODE0 | I8254_BINARY);
-               i8254_set_mode(timer_iobase, 0, 1, I8254_MODE0 | I8254_BINARY);
-               i8254_set_mode(timer_iobase, 0, 2, I8254_MODE0 | I8254_BINARY);
-       }
-}
-
 static unsigned int das6402_ai_read_sample(struct comedi_device *dev,
                                           struct comedi_subdevice *s)
 {
@@ -267,7 +241,8 @@ static int das6402_ai_cmd(struct comedi_device *dev,
        outw(DAS6402_AI_MUX_HI(chan_hi) | DAS6402_AI_MUX_LO(chan_lo),
             dev->iobase + DAS6402_AI_MUX_REG);
 
-       das6402_enable_counter(dev, true);
+       comedi_8254_update_divisors(dev->pacer);
+       comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
 
        /* enable interrupt and pacer trigger */
        outb(DAS6402_CTRL_INTE |
@@ -322,24 +297,23 @@ static int das6402_ai_cmdtest(struct comedi_device *dev,
                              struct comedi_subdevice *s,
                              struct comedi_cmd *cmd)
 {
-       struct das6402_private *devpriv = dev->private;
        int err = 0;
        unsigned int arg;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -348,30 +322,26 @@ static int das6402_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000);
-       err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 10000);
+       err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
 
        /* step 4: fix up any arguments */
 
-       if (cmd->convert_src == TRIG_TIMER) {
-               arg = cmd->convert_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
-                                         &devpriv->divider1,
-                                         &devpriv->divider2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
-       }
+       arg = cmd->convert_arg;
+       comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
 
        if (err)
                return 4;
@@ -581,8 +551,6 @@ static void das6402_reset(struct comedi_device *dev)
        outw(0, dev->iobase + DAS6402_AO_DATA_REG(0));
        inw(dev->iobase + DAS6402_AO_LSB_REG(0));
 
-       das6402_enable_counter(dev, false);
-
        /* set all digital outputs low */
        outb(0, dev->iobase + DAS6402_DI_DO_REG);
 
@@ -631,6 +599,11 @@ static int das6402_attach(struct comedi_device *dev,
                }
        }
 
+       dev->pacer = comedi_8254_init(dev->iobase + DAS6402_TIMER_BASE,
+                                     I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
                return ret;
index ff7f4be3f31432c67a50510b883df360b2d06510..39d304a1259f4fe2e9be0dad8675f1e2af4f21b7 100644 (file)
@@ -43,8 +43,6 @@ Notes:
 
        The cio-das802/16 does not have a fifo-empty status bit!  Therefore
        only fifo-half-full transfers are possible with this card.
-*/
-/*
 
 cmd triggers supported:
        start_src:      TRIG_NOW | TRIG_EXT
@@ -52,18 +50,15 @@ cmd triggers supported:
        scan_end_src:   TRIG_COUNT
        convert_src:    TRIG_TIMER | TRIG_EXT
        stop_src:       TRIG_NONE | TRIG_COUNT
-
-
 */
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include "../comedidev.h"
-
 #include <linux/delay.h>
 
-#include "8253.h"
-#include "comedi_fc.h"
+#include "../comedidev.h"
+
+#include "comedi_8254.h"
 
 #define N_CHAN_AI             8        /*  number of analog input channels */
 
@@ -219,8 +214,6 @@ static const struct das800_board das800_boards[] = {
 };
 
 struct das800_private {
-       unsigned int divisor1;  /* counter 1 value for timed conversions */
-       unsigned int divisor2;  /* counter 2 value for timed conversions */
        unsigned int do_bits;   /* digital output bits */
 };
 
@@ -272,17 +265,6 @@ static void das800_disable(struct comedi_device *dev)
        spin_unlock_irqrestore(&dev->spinlock, irq_flags);
 }
 
-static void das800_set_frequency(struct comedi_device *dev)
-{
-       struct das800_private *devpriv = dev->private;
-       unsigned long timer_base = dev->iobase + DAS800_8254;
-
-       i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
-       i8254_write(timer_base, 0, 1, devpriv->divisor1);
-       i8254_write(timer_base, 0, 2, devpriv->divisor2);
-}
-
 static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
        das800_disable(dev);
@@ -322,26 +304,25 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev,
                                struct comedi_cmd *cmd)
 {
        const struct das800_board *thisboard = dev->board_ptr;
-       struct das800_private *devpriv = dev->private;
        int err = 0;
-       unsigned int arg;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->convert_src,
+                                       TRIG_TIMER | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -350,19 +331,21 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
-       if (cmd->convert_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                thisboard->ai_speed);
+       if (cmd->convert_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                   thisboard->ai_speed);
+       }
 
-       err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -370,12 +353,10 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev,
        /* step 4: fix up any arguments */
 
        if (cmd->convert_src == TRIG_TIMER) {
-               arg = cmd->convert_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_1MHZ,
-                                         &devpriv->divisor1,
-                                         &devpriv->divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               unsigned int arg = cmd->convert_arg;
+
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
        }
 
        if (err)
@@ -426,8 +407,8 @@ static int das800_ai_do_cmd(struct comedi_device *dev,
                conv_bits |= DTEN;
        if (cmd->convert_src == TRIG_TIMER) {
                conv_bits |= CASC | ITE;
-               /* set conversion frequency */
-               das800_set_frequency(dev);
+               comedi_8254_update_divisors(dev->pacer);
+               comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
        }
 
        spin_lock_irqsave(&dev->spinlock, irq_flags);
@@ -697,6 +678,11 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                        dev->irq = irq;
        }
 
+       dev->pacer = comedi_8254_init(dev->iobase + DAS800_8254,
+                                     I8254_OSC_BASE_1MHZ, I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        ret = comedi_alloc_subdevices(dev, 3);
        if (ret)
                return ret;
index 1af006609fc1b70d700eaa18e47e4cb5a428eafc..bb2883c83afaa010b713e51fc96ff346208b824b 100644 (file)
@@ -30,7 +30,7 @@
  * This driver is for the Diamond Systems MM-32-AT board
  *     http://www.diamondsystems.com/products/diamondmm32at
  *
- * It is being used on serveral projects inside NASA, without
+ * It is being used on several projects inside NASA, without
  * problems so far. For analog input commands, TRIG_EXT is not
  * yet supported.
  */
@@ -41,7 +41,6 @@
 #include "../comedidev.h"
 
 #include "8255.h"
-#include "comedi_fc.h"
 
 /* Board register addresses */
 #define DMM32AT_AI_START_CONV_REG      0x00
@@ -274,18 +273,18 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -294,10 +293,10 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
-       err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 1000000);
-       err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 1000000000);
+       err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, 1000000);
+       err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg, 1000000000);
 
        if (cmd->convert_arg >= 17500)
                cmd->convert_arg = 20000;
@@ -308,12 +307,13 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev,
        else
                cmd->convert_arg = 5000;
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -321,7 +321,7 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev,
        /* Step 4: fix up any arguments */
 
        arg = cmd->convert_arg * cmd->scan_end_arg;
-       err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
+       err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
 
        if (err)
                return 4;
@@ -391,13 +391,12 @@ static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                /* start the clock and enable the interrupts */
                dmm32at_setaitimer(dev, cmd->scan_begin_arg);
        } else {
-               /* start the interrups and initiate a single scan */
+               /* start the interrupts and initiate a single scan */
                outb(DMM32AT_INTCLK_ADINT, dev->iobase + DMM32AT_INTCLK_REG);
                outb(0xff, dev->iobase + DMM32AT_AI_START_CONV_REG);
        }
 
        return 0;
-
 }
 
 static int dmm32at_ai_cancel(struct comedi_device *dev,
index b96e60ffad73bcd58d9e3d1bec19d461a160199e..80e38dedd359ec3ac86a768ac402d4aa11d1d639 100644 (file)
@@ -126,7 +126,6 @@ static const struct comedi_lrange range_dt2801_ai_pgl_unipolar = {
 };
 
 struct dt2801_board {
-
        const char *name;
        int boardcode;
        int ad_diff;
@@ -280,7 +279,7 @@ static int dt2801_writedata2(struct comedi_device *dev, unsigned int data)
        ret = dt2801_writedata(dev, data & 0xff);
        if (ret < 0)
                return ret;
-       ret = dt2801_writedata(dev, (data >> 8));
+       ret = dt2801_writedata(dev, data >> 8);
        if (ret < 0)
                return ret;
 
index d660f277487eb94545b51eb64089ecc4d6664ffd..a80773291fdc8bc0e865f42b43ebcc4dfe273aa3 100644 (file)
@@ -194,7 +194,6 @@ static const struct comedi_lrange range_dt2811_pgl_ai_5_bipolar = {
 #define DT2811_ADMODE   0x03
 
 struct dt2811_board {
-
        const char *name;
        const struct comedi_lrange *bip_5;
        const struct comedi_lrange *bip_2_5;
index 9805be13005a89a1b4d32a9c98f19568a708c521..66705f9a0621f928488f4f450fa1d00ed2df33c5 100644 (file)
@@ -40,8 +40,6 @@ addition, the clock does not seem to be very accurate.
 
 #include <linux/delay.h>
 
-#include "comedi_fc.h"
-
 #define DT2814_CSR 0
 #define DT2814_DATA 1
 
@@ -56,7 +54,6 @@ addition, the clock does not seem to be very accurate.
 #define DT2814_CHANMASK 0x0f
 
 struct dt2814_private {
-
        int ntrig;
        int curadchan;
 };
@@ -130,18 +127,18 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -150,18 +147,19 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
-       err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 1000000000);
-       err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                        DT2814_MAX_SPEED);
+       err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg, 1000000000);
+       err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                           DT2814_MAX_SPEED);
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 2);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 2);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -170,7 +168,7 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev,
 
        arg = cmd->scan_begin_arg;
        dt2814_ns_to_timer(&arg, cmd->flags);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 
        if (err)
                return 4;
@@ -193,7 +191,6 @@ static int dt2814_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        outb(chan | DT2814_ENB | (trigvar << 5), dev->iobase + DT2814_CSR);
 
        return 0;
-
 }
 
 static irqreturn_t dt2814_interrupt(int irq, void *d)
index a98fb66fdd53f3b093b3710a9e1eaa9f09185bb8..fb08569c1ac1fd4b582f7b46d7599f8010c95e30 100644 (file)
@@ -60,7 +60,6 @@ Configuration options:
 #define DT2815_STATUS 1
 
 struct dt2815_private {
-
        const struct comedi_lrange *range_type_list[8];
        unsigned int ao_readback[8];
 };
index db21d213585607f50a5acf7a5f7875f078459ec8..5a536a00066f9ff4340813d85b68854044715d3d 100644 (file)
@@ -64,7 +64,6 @@
 #include "../comedidev.h"
 
 #include "comedi_isadma.h"
-#include "comedi_fc.h"
 
 /*
  * Register map
@@ -661,20 +660,20 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_FOLLOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -683,21 +682,22 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
-       err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 4000);
+       err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 4000);
 
 #define SLOWEST_TIMER  (250*(1<<15)*255)
-       err |= cfc_check_trigger_arg_max(&cmd->convert_arg, SLOWEST_TIMER);
-       err |= cfc_check_trigger_arg_min(&cmd->convert_arg, board->ai_speed);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_max(&cmd->convert_arg, SLOWEST_TIMER);
+       err |= comedi_check_trigger_arg_min(&cmd->convert_arg, board->ai_speed);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_EXT | TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -706,7 +706,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev,
 
        arg = cmd->convert_arg;
        devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
 
        if (err)
                return 4;
@@ -764,7 +764,7 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
        if (cmd->scan_begin_src == TRIG_FOLLOW) {
                outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
-                       dev->iobase + DT2821_SUPCSR_REG);
+                    dev->iobase + DT2821_SUPCSR_REG);
        } else {
                devpriv->supcsr |= DT2821_SUPCSR_XTRIG;
                outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG);
@@ -831,18 +831,18 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -851,15 +851,16 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 5000);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, 5000);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_EXT | TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -868,13 +869,12 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev,
 
        arg = cmd->scan_begin_arg;
        devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 
        if (err)
                return 4;
 
        return 0;
-
 }
 
 static int dt282x_ao_inttrig(struct comedi_device *dev,
index 0aa51980e32778e267eaf2d2c440c55465ac91f8..031282c82f43a2f1e4826648068ddc7e52fae85b 100644 (file)
@@ -49,13 +49,10 @@ AO commands are not supported.
 */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
-
-#include "comedi_fc.h"
+#include "../comedi_pci.h"
 
 static const struct comedi_lrange range_dt3000_ai = {
        4, {
@@ -409,11 +406,11 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT);
 
        if (err)
                return 1;
@@ -423,28 +420,29 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                this_board->ai_speed);
-               err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
-                                                100 * 16 * 65535);
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   this_board->ai_speed);
+               err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
+                                                   100 * 16 * 65535);
        }
 
        if (cmd->convert_src == TRIG_TIMER) {
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                this_board->ai_speed);
-               err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
-                                                50 * 16 * 65535);
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                   this_board->ai_speed);
+               err |= comedi_check_trigger_arg_max(&cmd->convert_arg,
+                                                   50 * 16 * 65535);
        }
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
+               err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -454,18 +452,19 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev,
        if (cmd->scan_begin_src == TRIG_TIMER) {
                arg = cmd->scan_begin_arg;
                dt3k_ns_to_timer(100, &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
 
        if (cmd->convert_src == TRIG_TIMER) {
                arg = cmd->convert_arg;
                dt3k_ns_to_timer(50, &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
 
                if (cmd->scan_begin_src == TRIG_TIMER) {
                        arg = cmd->convert_arg * cmd->scan_end_arg;
-                       err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                        arg);
+                       err |= comedi_check_trigger_arg_min(&cmd->
+                                                           scan_begin_arg,
+                                                           arg);
                }
        }
 
index 6c1e442f6c81c71ec6a4885ed0fc34c0d1d9bf2e..c9eb26fab44e7d02951287d9d48f3d3f74e0f5d5 100644 (file)
 
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 #include <linux/mutex.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #define READ_TIMEOUT 50
 
@@ -70,8 +69,9 @@ static int dyna_pci10xx_ai_eoc(struct comedi_device *dev,
 }
 
 static int dyna_pci10xx_insn_read_ai(struct comedi_device *dev,
-                       struct comedi_subdevice *s,
-                       struct comedi_insn *insn, unsigned int *data)
+                                    struct comedi_subdevice *s,
+                                    struct comedi_insn *insn,
+                                    unsigned int *data)
 {
        struct dyna_pci10xx_private *devpriv = dev->private;
        int n;
@@ -109,8 +109,9 @@ static int dyna_pci10xx_insn_read_ai(struct comedi_device *dev,
 
 /* analog output callback */
 static int dyna_pci10xx_insn_write_ao(struct comedi_device *dev,
-                                struct comedi_subdevice *s,
-                                struct comedi_insn *insn, unsigned int *data)
+                                     struct comedi_subdevice *s,
+                                     struct comedi_insn *insn,
+                                     unsigned int *data)
 {
        struct dyna_pci10xx_private *devpriv = dev->private;
        int n;
@@ -132,8 +133,9 @@ static int dyna_pci10xx_insn_write_ao(struct comedi_device *dev,
 
 /* digital input bit interface */
 static int dyna_pci10xx_di_insn_bits(struct comedi_device *dev,
-                             struct comedi_subdevice *s,
-                             struct comedi_insn *insn, unsigned int *data)
+                                    struct comedi_subdevice *s,
+                                    struct comedi_insn *insn,
+                                    unsigned int *data)
 {
        struct dyna_pci10xx_private *devpriv = dev->private;
        u16 d = 0;
@@ -171,7 +173,7 @@ static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev,
 }
 
 static int dyna_pci10xx_auto_attach(struct comedi_device *dev,
-                                             unsigned long context_unused)
+                                   unsigned long context_unused)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        struct dyna_pci10xx_private *devpriv;
index deada9784b693bdef49dc36a631470c8172c34e3..3cb6409c4f0183e530b43cdb913cf9ab5e2bb49c 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #include "plx9080.h"
-#include "comedi_fc.h"
 
 /*
  * PCI BAR2 Register map (dev->mmio)
@@ -386,18 +384,18 @@ static int gsc_hpdi_cmd_test(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -406,18 +404,19 @@ static int gsc_hpdi_cmd_test(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (!cmd->chanlist_len || !cmd->chanlist) {
                cmd->chanlist_len = 32;
                err |= -EINVAL;
        }
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -433,7 +432,6 @@ static int gsc_hpdi_cmd_test(struct comedi_device *dev,
                return 5;
 
        return 0;
-
 }
 
 /* setup dma descriptors so a link completes every 'len' bytes */
index 1ea1686201031eace09cf9c395ee05071d99d44c..1e104ebf80576e472f3792666c8756a54fa1e32c 100644 (file)
@@ -43,11 +43,10 @@ Configuration options: not applicable, uses PCI auto config
 */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #define ICP_MULTI_ADC_CSR      0       /* R/W: ADC command/status register */
 #define ICP_MULTI_AI           2       /* R:   Analogue input data */
@@ -370,7 +369,6 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d)
                break;
        default:
                break;
-
        }
 
        return IRQ_HANDLED;
@@ -445,7 +443,7 @@ static int icp_multi_reset(struct comedi_device *dev)
 }
 
 static int icp_multi_auto_attach(struct comedi_device *dev,
-                                          unsigned long context_unused)
+                                unsigned long context_unused)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        struct icp_multi_private *devpriv;
index 81fab2dfafa43b3b277ff22945d7623115d92fb4..b87192e0f9aa8ba93217aef26fb16b031cc1e469 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/ctype.h>
 #include <linux/jiffies.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #include "jr3_pci.h"
 
@@ -706,8 +705,6 @@ static int jr3_pci_auto_attach(struct comedi_device *dev,
        if (!devpriv)
                return -ENOMEM;
 
-       init_timer(&devpriv->timer);
-
        ret = comedi_pci_enable(dev);
        if (ret)
                return ret;
@@ -775,8 +772,7 @@ static int jr3_pci_auto_attach(struct comedi_device *dev,
                spriv->next_time_max = jiffies + msecs_to_jiffies(2000);
        }
 
-       devpriv->timer.data = (unsigned long)dev;
-       devpriv->timer.function = jr3_pci_poll_dev;
+       setup_timer(&devpriv->timer, jr3_pci_poll_dev, (unsigned long)dev);
        devpriv->timer.expires = jiffies + msecs_to_jiffies(1000);
        add_timer(&devpriv->timer);
 
index 3c19e0f178ca28a207897706f19b5f7e92d844db..dc642edf4f655c7ae7eeee6473c937445dcda901 100644 (file)
@@ -28,9 +28,8 @@
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 /*
  * PCI BAR 0 Register I/O map
index d120aa244cf9a303f8804015d481a8eaeff97de1..7a8c27dd71541b976ca0dafa55df4c0b7ab4c7d7 100644 (file)
@@ -41,14 +41,12 @@ broken.
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
-#include "comedi_fc.h"
-#include "8253.h"
+#include "comedi_8254.h"
 #include "plx9052.h"
 
 #define ME4000_FIRMWARE                "me4000_firmware.bin"
@@ -170,7 +168,6 @@ broken.
 
 struct me4000_info {
        unsigned long plx_regbase;
-       unsigned long timer_regbase;
 };
 
 enum me4000_boardid {
@@ -424,7 +421,7 @@ static void me4000_reset(struct comedi_device *dev)
 
        /* 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);
+            dev->iobase + ME4000_AI_CTRL_REG);
 
        /* Set both stop bits in the analog output control register */
        val = ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP;
@@ -438,7 +435,7 @@ static void me4000_reset(struct comedi_device *dev)
 
        /* Set the adustment register for AO demux */
        outl(ME4000_AO_DEMUX_ADJUST_VALUE,
-                   dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
+            dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
 
        /*
         * Set digital I/O direction for port 0
@@ -609,7 +606,7 @@ static int me4000_ai_check_chanlist(struct comedi_device *dev,
 
                        if (!comedi_range_is_bipolar(s, range)) {
                                dev_dbg(dev->class_dev,
-                                      "Bipolar is not selected in differential mode\n");
+                                       "Bipolar is not selected in differential mode\n");
                                return -EINVAL;
                        }
                }
@@ -624,7 +621,6 @@ static int ai_round_cmd_args(struct comedi_device *dev,
                             unsigned int *init_ticks,
                             unsigned int *scan_ticks, unsigned int *chan_ticks)
 {
-
        int rest;
 
        *init_ticks = 0;
@@ -731,7 +727,6 @@ static int ai_prepare(struct comedi_device *dev,
                      unsigned int init_ticks,
                      unsigned int scan_ticks, unsigned int chan_ticks)
 {
-
        unsigned int tmp = 0;
 
        /* Write timer arguments */
@@ -772,12 +767,12 @@ static int ai_prepare(struct comedi_device *dev,
        /* Stop triggers */
        if (cmd->stop_src == TRIG_COUNT) {
                outl(cmd->chanlist_len * cmd->stop_arg,
-                           dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
+                    dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
                tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_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);
+                    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;
@@ -827,7 +822,6 @@ 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;
@@ -838,24 +832,25 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src,
+       err |= comedi_check_trigger_src(&cmd->convert_src,
+                                       TRIG_TIMER | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src,
                                        TRIG_NONE | TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE | TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE | TRIG_COUNT);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_end_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_end_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -886,7 +881,7 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (cmd->chanlist_len < 1) {
                cmd->chanlist_len = 1;
@@ -906,9 +901,9 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
        }
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -919,7 +914,6 @@ 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) {
-
                /* Check timer arguments */
                if (init_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid start arg\n");
@@ -941,7 +935,6 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
        } else if (cmd->start_src == TRIG_NOW &&
                   cmd->scan_begin_src == TRIG_FOLLOW &&
                   cmd->convert_src == TRIG_TIMER) {
-
                /* Check timer arguments */
                if (init_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid start arg\n");
@@ -956,7 +949,6 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
        } else if (cmd->start_src == TRIG_EXT &&
                   cmd->scan_begin_src == TRIG_TIMER &&
                   cmd->convert_src == TRIG_TIMER) {
-
                /* Check timer arguments */
                if (init_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid start arg\n");
@@ -978,7 +970,6 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
        } else if (cmd->start_src == TRIG_EXT &&
                   cmd->scan_begin_src == TRIG_FOLLOW &&
                   cmd->convert_src == TRIG_TIMER) {
-
                /* Check timer arguments */
                if (init_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid start arg\n");
@@ -993,7 +984,6 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
        } else if (cmd->start_src == TRIG_EXT &&
                   cmd->scan_begin_src == TRIG_EXT &&
                   cmd->convert_src == TRIG_TIMER) {
-
                /* Check timer arguments */
                if (init_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid start arg\n");
@@ -1008,7 +998,6 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
        } else if (cmd->start_src == TRIG_EXT &&
                   cmd->scan_begin_src == TRIG_EXT &&
                   cmd->convert_src == TRIG_EXT) {
-
                /* Check timer arguments */
                if (init_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid start arg\n");
@@ -1187,13 +1176,13 @@ static int me4000_dio_insn_bits(struct comedi_device *dev,
 {
        if (comedi_dio_update_state(s, data)) {
                outl((s->state >> 0) & 0xFF,
-                           dev->iobase + ME4000_DIO_PORT_0_REG);
+                    dev->iobase + ME4000_DIO_PORT_0_REG);
                outl((s->state >> 8) & 0xFF,
-                           dev->iobase + ME4000_DIO_PORT_1_REG);
+                    dev->iobase + ME4000_DIO_PORT_1_REG);
                outl((s->state >> 16) & 0xFF,
-                           dev->iobase + ME4000_DIO_PORT_2_REG);
+                    dev->iobase + ME4000_DIO_PORT_2_REG);
                outl((s->state >> 24) & 0xFF,
-                           dev->iobase + ME4000_DIO_PORT_3_REG);
+                    dev->iobase + ME4000_DIO_PORT_3_REG);
        }
 
        data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) |
@@ -1259,85 +1248,6 @@ static int me4000_dio_insn_config(struct comedi_device *dev,
        return insn->n;
 }
 
-/*=============================================================================
-  Counter section
-  ===========================================================================*/
-
-static int me4000_cnt_insn_config(struct comedi_device *dev,
-                                 struct comedi_subdevice *s,
-                                 struct comedi_insn *insn,
-                                 unsigned int *data)
-{
-       struct me4000_info *info = dev->private;
-       unsigned int chan = CR_CHAN(insn->chanspec);
-       int err;
-
-       switch (data[0]) {
-       case GPCT_RESET:
-               if (insn->n != 1)
-                       return -EINVAL;
-
-               err = i8254_set_mode(info->timer_regbase, 0, chan,
-                                    I8254_MODE0 | I8254_BINARY);
-               if (err)
-                       return err;
-               i8254_write(info->timer_regbase, 0, chan, 0);
-               break;
-       case GPCT_SET_OPERATION:
-               if (insn->n != 2)
-                       return -EINVAL;
-
-               err = i8254_set_mode(info->timer_regbase, 0, chan,
-                               (data[1] << 1) | I8254_BINARY);
-               if (err)
-                       return err;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return insn->n;
-}
-
-static int me4000_cnt_insn_read(struct comedi_device *dev,
-                               struct comedi_subdevice *s,
-                               struct comedi_insn *insn, unsigned int *data)
-{
-       struct me4000_info *info = dev->private;
-
-       if (insn->n == 0)
-               return 0;
-
-       if (insn->n > 1) {
-               dev_err(dev->class_dev, "Invalid instruction length %d\n",
-                       insn->n);
-               return -EINVAL;
-       }
-
-       data[0] = i8254_read(info->timer_regbase, 0, insn->chanspec);
-
-       return 1;
-}
-
-static int me4000_cnt_insn_write(struct comedi_device *dev,
-                                struct comedi_subdevice *s,
-                                struct comedi_insn *insn, unsigned int *data)
-{
-       struct me4000_info *info = dev->private;
-
-       if (insn->n == 0) {
-               return 0;
-       } else if (insn->n > 1) {
-               dev_err(dev->class_dev, "Invalid instruction length %d\n",
-                       insn->n);
-               return -EINVAL;
-       }
-
-       i8254_write(info->timer_regbase, 0, insn->chanspec, data[0]);
-
-       return 1;
-}
-
 static int me4000_auto_attach(struct comedi_device *dev,
                              unsigned long context)
 {
@@ -1364,8 +1274,7 @@ static int me4000_auto_attach(struct comedi_device *dev,
 
        info->plx_regbase = pci_resource_start(pcidev, 1);
        dev->iobase = pci_resource_start(pcidev, 2);
-       info->timer_regbase = pci_resource_start(pcidev, 3);
-       if (!info->plx_regbase || !dev->iobase || !info->timer_regbase)
+       if (!info->plx_regbase || !dev->iobase)
                return -ENODEV;
 
        result = comedi_load_firmware(dev, &pcidev->dev, ME4000_FIRMWARE,
@@ -1377,7 +1286,7 @@ 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);
+                                    dev->board_name, dev);
                if (result == 0)
                        dev->irq = pcidev->irq;
        }
@@ -1459,23 +1368,22 @@ 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,
-                       dev->iobase + ME4000_DIO_DIR_REG);
+                    dev->iobase + ME4000_DIO_DIR_REG);
        }
 
-    /*=========================================================================
-      Counter subdevice
-      ========================================================================*/
-
+       /* Counter subdevice (8254) */
        s = &dev->subdevices[3];
-
        if (thisboard->has_counter) {
-               s->type = COMEDI_SUBD_COUNTER;
-               s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-               s->n_chan = 3;
-               s->maxdata = 0xFFFF;    /*  16 bit counters */
-               s->insn_read = me4000_cnt_insn_read;
-               s->insn_write = me4000_cnt_insn_write;
-               s->insn_config = me4000_cnt_insn_config;
+               unsigned long timer_base = pci_resource_start(pcidev, 3);
+
+               if (!timer_base)
+                       return -ENODEV;
+
+               dev->pacer = comedi_8254_init(timer_base, 0, I8254_IO8, 0);
+               if (!dev->pacer)
+                       return -ENOMEM;
+
+               comedi_8254_subdevice_init(s, dev->pacer);
        } else {
                s->type = COMEDI_SUBD_UNUSED;
        }
index 92e23527f2cb3c09703197450a2a399f6eff867e..d78e9195fbce305bbd272240371edec79edf4cd3 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #include "plx9052.h"
 
index db972bce2b5b1f6724022741d4a3b6bd7f526228..a675e2ef9b4553e4ba950a06d22f0d61040002a6 100644 (file)
@@ -26,9 +26,9 @@
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
-#include "../comedidev.h"
+
+#include "../comedi_pci.h"
 
 /* Registers present in BAR0 memory region */
 #define MF624_GPIOC_R                                  0x54
@@ -237,7 +237,6 @@ static int mf6x4_auto_attach(struct comedi_device *dev, unsigned long context)
        else
                devpriv->gpioc_R = devpriv->bar0_mem + MF624_GPIOC_R;
 
-
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
                return ret;
index 1e537a5cf86286eeb646836f471968caaa2213fb..e43a0c8323c18e7715df21b875d07191dff702ff 100644 (file)
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
-#include "comedi_fc.h"
 #include "mite.h"
 
 #define TOP_OF_PAGE(x) ((x)|(~(PAGE_MASK)))
@@ -186,10 +184,10 @@ struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite)
        struct mite_dma_descriptor_ring *ring =
            kmalloc(sizeof(struct mite_dma_descriptor_ring), GFP_KERNEL);
 
-       if (ring == NULL)
-               return ring;
+       if (!ring)
+               return NULL;
        ring->hw_dev = get_device(&mite->pcidev->dev);
-       if (ring->hw_dev == NULL) {
+       if (!ring->hw_dev) {
                kfree(ring);
                return NULL;
        }
index b2b12045b3a5f0054efcd1850db6f16f1d90c01a..b3ca7fc3a31e7de83a261c189093711531b99575 100644 (file)
 #ifndef _MITE_H_
 #define _MITE_H_
 
-#include <linux/pci.h>
 #include <linux/log2.h>
 #include <linux/slab.h>
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #define PCIMIO_COMPAT
 
index 1241f9987cab2c01715da3b1d1297648dc8860f7..0207b8edfcb4534f8742ba840de1bd196c950c30 100644 (file)
@@ -115,7 +115,6 @@ Configuration Options:
        (MPC624_OSR4 | MPC624_OSR3 | MPC624_OSR2 | MPC624_OSR1 | MPC624_OSR0)
 /* -------------------------------------------------------------------------- */
 struct mpc624_private {
-
        /*  set by mpc624_attach() from driver's parameters */
        unsigned long int ulConvertionRate;
 };
index 530f716f65863a962a6c284bd6e095aa35dcf3a9..62a817e4cd64582b14e3afe1c101066d89276695 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
-
-#include "comedi_fc.h"
+#include "../comedi_pci.h"
 
 /*
  * PCI BAR1 - Register memory map
@@ -224,11 +221,11 @@ static int ni6527_intr_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_OTHER);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_OTHER);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT);
 
        if (err)
                return 1;
@@ -238,11 +235,12 @@ static int ni6527_intr_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-       err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
index 67cb758eb0cd9293e41abbcd7d91e50daafa0b75..800d57426070409b27ebaebed6292cb77135d89b 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
-
-#include "comedi_fc.h"
+#include "../comedi_pci.h"
 
 /*
  * PCI BAR1 Register Map
@@ -508,11 +505,11 @@ static int ni_65xx_intr_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_OTHER);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_OTHER);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT);
 
        if (err)
                return 1;
@@ -522,11 +519,12 @@ static int ni_65xx_intr_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-       err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -613,7 +611,7 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev,
        return insn->n;
 }
 
-/* ripped from mite.h and mite_setup2() to avoid mite dependancy */
+/* ripped from mite.h and mite_setup2() to avoid mite dependency */
 #define MITE_IODWBSR   0xc0     /* IO Device Window Base Size Register */
 #define WENAB          (1 << 7) /* window enable */
 
@@ -676,7 +674,7 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
        }
 
        dev_info(dev->class_dev, "board: %s, ID=0x%02x", dev->board_name,
-              readb(dev->mmio + NI_65XX_ID_REG));
+                readb(dev->mmio + NI_65XX_ID_REG));
 
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
index 1e4dd82b12ea7d082d1d595d71ac6e96347443ec..46647c64f3692d6853276aecb933f698d523316c 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
-#include "comedi_fc.h"
 #include "mite.h"
 #include "ni_tio.h"
 
@@ -195,7 +193,6 @@ static inline unsigned NI_660X_GPCT_SUBDEV(unsigned index)
 }
 
 struct NI_660xRegisterData {
-
        const char *name;       /*  Register Name */
        int offset;             /*  Offset from base address from GPCT chip */
        enum ni_660x_register_direction direction;
@@ -702,7 +699,7 @@ static int ni_660x_request_mite_channel(struct comedi_device *dev,
        BUG_ON(counter->mite_chan);
        mite_chan = mite_request_channel(devpriv->mite,
                                         mite_ring(devpriv, counter));
-       if (mite_chan == NULL) {
+       if (!mite_chan) {
                spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
                dev_err(dev->class_dev,
                        "failed to reserve mite dma channel for counter\n");
@@ -861,7 +858,7 @@ static int ni_660x_alloc_mite_rings(struct comedi_device *dev)
                for (j = 0; j < counters_per_chip; ++j) {
                        devpriv->mite_rings[i][j] =
                            mite_alloc_ring(devpriv->mite);
-                       if (devpriv->mite_rings[i][j] == NULL)
+                       if (!devpriv->mite_rings[i][j])
                                return -ENOMEM;
                }
        }
@@ -1107,7 +1104,7 @@ static int ni_660x_auto_attach(struct comedi_device *dev,
                                                     ni_gpct_variant_660x,
                                                     ni_660x_num_counters
                                                     (dev));
-       if (devpriv->counter_dev == NULL)
+       if (!devpriv->counter_dev)
                return -ENOMEM;
        for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) {
                s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)];
index c42a81c0bfa1cd3fd9f444ac7b405cc5869213c3..13c6ccb1fdea4abcc4f4c6c05005b784edf31734 100644 (file)
@@ -37,11 +37,10 @@ Commands are not supported.
 */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #define AO_VALUE_OFFSET                        0x00
 #define        AO_CHAN_OFFSET                  0x0c
@@ -146,7 +145,7 @@ static int ni_670x_dio_insn_config(struct comedi_device *dev,
        return insn->n;
 }
 
-/* ripped from mite.h and mite_setup2() to avoid mite dependancy */
+/* ripped from mite.h and mite_setup2() to avoid mite dependency */
 #define MITE_IODWBSR   0xc0     /* IO Device Window Base Size Register */
 #define WENAB          (1 << 7) /* window enable */
 
index a1ce0b0b8c41c340180990ca022b2442e3b07144..3a972d1538ab6f9d8d3092e123c74ff8d56bba38 100644 (file)
@@ -67,8 +67,7 @@ TRIG_WAKE_EOS
 #include "../comedidev.h"
 
 #include "comedi_isadma.h"
-#include "comedi_fc.h"
-#include "8253.h"
+#include "comedi_8254.h"
 
 #define A2150_DMA_BUFFER_SIZE  0xff00  /*  size in bytes of dma buffer */
 
@@ -110,8 +109,6 @@ TRIG_WAKE_EOS
 #define   DMA_INTR_EN_BIT              0x800   /*  enable interrupt on dma terminal count */
 #define   DMA_DEM_EN_BIT       0x1000  /*  enables demand mode dma */
 #define I8253_BASE_REG         0x14
-#define I8253_MODE_REG         0x17
-#define   HW_COUNT_DISABLE             0x30    /*  disable hardware counting of conversions */
 
 struct a2150_board {
        const char *name;
@@ -422,19 +419,19 @@ static int a2150_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -443,19 +440,21 @@ static int a2150_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
-       if (cmd->convert_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                thisboard->ai_speed);
+       if (cmd->convert_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                   thisboard->ai_speed);
+       }
 
-       err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -465,7 +464,7 @@ static int a2150_ai_cmdtest(struct comedi_device *dev,
        if (cmd->scan_begin_src == TRIG_TIMER) {
                arg = cmd->scan_begin_arg;
                a2150_get_timing(dev, &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
 
        if (err)
@@ -488,7 +487,6 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        struct comedi_isadma_desc *desc = &dma->desc[0];
        struct comedi_async *async = s->async;
        struct comedi_cmd *cmd = &async->cmd;
-       unsigned long timer_base = dev->iobase + I8253_BASE_REG;
        unsigned int old_config_bits = devpriv->config_bits;
        unsigned int trigger_bits;
 
@@ -547,8 +545,7 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
 
        /*  may need to wait 72 sampling periods if timing was changed */
-       i8254_set_mode(timer_base, 0, 2, I8254_MODE0 | I8254_BINARY);
-       i8254_write(timer_base, 0, 2, 72);
+       comedi_8254_load(dev->pacer, 2, 72, I8254_MODE0 | I8254_BINARY);
 
        /*  setup start triggering */
        trigger_bits = 0;
@@ -726,6 +723,11 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        /* an IRQ and DMA are required to support async commands */
        a2150_alloc_irq_and_dma(dev, it);
 
+       dev->pacer = comedi_8254_init(dev->iobase + I8253_BASE_REG,
+                                     0, I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        ret = comedi_alloc_subdevices(dev, 1);
        if (ret)
                return ret;
@@ -747,10 +749,6 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                s->cancel = a2150_cancel;
        }
 
-       /* need to do this for software counting of completed conversions, to
-        * prevent hardware count from stopping acquisition */
-       outw(HW_COUNT_DISABLE, dev->iobase + I8253_MODE_REG);
-
        /*  set card's irq and dma levels */
        outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
 
index 9eeaf3c5a85828b34195488087d98a868b4b8d7f..f27aa0e822346e2e486cdac34905540a1fedb0af 100644 (file)
@@ -37,7 +37,7 @@
 
 #include "../comedidev.h"
 
-#include "8253.h"
+#include "comedi_8254.h"
 
 /*
  * Register map
@@ -274,7 +274,6 @@ static int atao_calib_insn_write(struct comedi_device *dev,
 static void atao_reset(struct comedi_device *dev)
 {
        struct atao_private *devpriv = dev->private;
-       unsigned long timer_base = dev->iobase + ATAO_82C53_BASE;
 
        /* This is the reset sequence described in the manual */
 
@@ -282,9 +281,9 @@ static void atao_reset(struct comedi_device *dev)
        outw(devpriv->cfg1, dev->iobase + ATAO_CFG1_REG);
 
        /* Put outputs of counter 1 and counter 2 in a high state */
-       i8254_set_mode(timer_base, 0, 0, I8254_MODE4 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 1, I8254_MODE4 | I8254_BINARY);
-       i8254_write(timer_base, 0, 0, 0x0003);
+       comedi_8254_set_mode(dev->pacer, 0, I8254_MODE4 | I8254_BINARY);
+       comedi_8254_set_mode(dev->pacer, 1, I8254_MODE4 | I8254_BINARY);
+       comedi_8254_write(dev->pacer, 0, 0x0003);
 
        outw(ATAO_CFG2_CALLD_NOP, dev->iobase + ATAO_CFG2_REG);
 
@@ -315,6 +314,11 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (!devpriv)
                return -ENOMEM;
 
+       dev->pacer = comedi_8254_init(dev->iobase + ATAO_82C53_BASE,
+                                     0, I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
                return ret;
index 301f154be8138a9cf6c23a8c182c3ed791922e0b..1304b06980a6ad55c626a32cbe8d02869ab88a99 100644 (file)
@@ -250,7 +250,7 @@ static int ni_isapnp_find_board(struct pnp_dev **dev)
                                          ISAPNP_FUNCTION(ni_boards[i].
                                                          isapnp_id), NULL);
 
-               if (isapnp_dev == NULL || isapnp_dev->card == NULL)
+               if (!isapnp_dev || !isapnp_dev->card)
                        continue;
 
                if (pnp_device_attach(isapnp_dev) < 0)
@@ -282,7 +282,6 @@ static int ni_getboardtype(struct comedi_device *dev)
        for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
                if (ni_boards[i].device_id == device_id)
                        return i;
-
        }
        if (device_id == 255)
                dev_err(dev->class_dev, "can't find board\n");
@@ -355,7 +354,6 @@ static int ni_atmio_attach(struct comedi_device *dev,
        if (ret < 0)
                return ret;
 
-
        return 0;
 }
 
index c484c89c94b53631252bc7c0d28fdce2986c3892..c3eb54622bc37c46a5c37d84e0436757b4a37d30 100644 (file)
@@ -34,7 +34,6 @@ Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d)
 #include <linux/interrupt.h>
 #include "../comedidev.h"
 
-#include "comedi_fc.h"
 #include "8255.h"
 
 /* Configuration and Status Registers */
@@ -96,7 +95,6 @@ Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d)
 #define CLOCK_100_HZ   0x8F25
 
 struct atmio16_board_t {
-
        const char *name;
        int has_8255;
 };
@@ -234,20 +232,20 @@ static int atmio16d_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_FOLLOW | TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -256,30 +254,31 @@ static int atmio16d_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_FOLLOW) {
                /* internal trigger */
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
        } else {
 #if 0
                /* external trigger */
                /* should be level/edge, hi/lo specification here */
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 #endif
        }
 
-       err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000);
+       err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 10000);
 #if 0
-       err |= cfc_check_trigger_arg_max(&cmd->convert_arg, SLOWEST_TIMER);
+       err |= comedi_check_trigger_arg_max(&cmd->convert_arg, SLOWEST_TIMER);
 #endif
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
index a916047791b86bc733d4b1d275476c52220e918a..51e5e942b442975daf4abcb33956289672207a47 100644 (file)
@@ -105,6 +105,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 static void labpc_detach(struct comedi_device *dev)
 {
        labpc_free_dma_chan(dev);
+       labpc_common_detach(dev);
        comedi_legacy_detach(dev);
 }
 
index be89ae479afcd265ec7b4990a1b8312448320343..83f878adbd5365e17dad60f686a3bfed7b13e596 100644 (file)
@@ -36,6 +36,7 @@ struct labpc_boardinfo {
 
 struct labpc_private {
        struct comedi_isadma *dma;
+       struct comedi_8254 *counter;
 
        /*  number of data points left to be taken */
        unsigned long long count;
@@ -49,20 +50,6 @@ struct labpc_private {
        /*  store last read of board status registers */
        unsigned int stat1;
        unsigned int stat2;
-       /*
-        * value to load into board's counter a0 (conversion pacing) for timed
-        * conversions
-        */
-       unsigned int divisor_a0;
-       /*
-        * value to load into board's counter b0 (master) for timed conversions
-        */
-       unsigned int divisor_b0;
-       /*
-        * value to load into board's counter b1 (scan pacing) for timed
-        * conversions
-        */
-       unsigned int divisor_b1;
 
        /* we are using dma/fifo-half-full/etc. */
        enum transfer_type current_transfer;
@@ -77,5 +64,6 @@ struct labpc_private {
 
 int labpc_common_attach(struct comedi_device *dev,
                        unsigned int irq, unsigned long isr_flags);
+void labpc_common_detach(struct comedi_device *dev);
 
 #endif /* _NI_LABPC_H */
index b88ee2614bfe5df7f7e5fff2a1cd3a5fea364a63..863afb28ee286c8271b260a68958eaba8a9c4a9b 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
 
 #include "../comedidev.h"
 
-#include "8253.h"
+#include "comedi_8254.h"
 #include "8255.h"
-#include "comedi_fc.h"
 #include "ni_labpc.h"
 #include "ni_labpc_regs.h"
 #include "ni_labpc_isadma.h"
@@ -108,32 +108,6 @@ static void labpc_writeb(struct comedi_device *dev,
        writeb(byte, dev->mmio + reg);
 }
 
-static void labpc_counter_load(struct comedi_device *dev,
-                              unsigned long reg,
-                              unsigned int counter_number,
-                              unsigned int count,
-                              unsigned int mode)
-{
-       if (dev->mmio) {
-               i8254_mm_set_mode(dev->mmio + reg, 0, counter_number, mode);
-               i8254_mm_write(dev->mmio + reg, 0, counter_number, count);
-       } else {
-               i8254_set_mode(dev->iobase + reg, 0, counter_number, mode);
-               i8254_write(dev->iobase + reg, 0, counter_number, count);
-       }
-}
-
-static void labpc_counter_set_mode(struct comedi_device *dev,
-                                  unsigned long reg,
-                                  unsigned int counter_number,
-                                  unsigned int mode)
-{
-       if (dev->mmio)
-               i8254_mm_set_mode(dev->mmio + reg, 0, counter_number, mode);
-       else
-               i8254_set_mode(dev->iobase + reg, 0, counter_number, mode);
-}
-
 static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
        struct labpc_private *devpriv = dev->private;
@@ -284,7 +258,7 @@ static int labpc_ai_insn_read(struct comedi_device *dev,
        devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG);
 
        /* initialize pacer counter to prevent any problems */
-       labpc_counter_set_mode(dev, COUNTER_A_BASE_REG, 0, I8254_MODE2);
+       comedi_8254_set_mode(devpriv->counter, 0, I8254_MODE2 | I8254_BINARY);
 
        labpc_clear_adc_fifo(dev);
 
@@ -367,83 +341,81 @@ static void labpc_set_ai_scan_period(struct comedi_cmd *cmd,
 static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd,
                             enum scan_mode mode)
 {
-       struct labpc_private *devpriv = dev->private;
+       struct comedi_8254 *pacer = dev->pacer;
+       unsigned int convert_period = labpc_ai_convert_period(cmd, mode);
+       unsigned int scan_period = labpc_ai_scan_period(cmd, mode);
        unsigned int base_period;
-       unsigned int scan_period;
-       unsigned int convert_period;
 
        /*
-        * if both convert and scan triggers are TRIG_TIMER, then they
-        * both rely on counter b0
+        * If both convert and scan triggers are TRIG_TIMER, then they
+        * both rely on counter b0. If only one TRIG_TIMER is used, we
+        * can use the generic cascaded timing functions.
         */
-       convert_period = labpc_ai_convert_period(cmd, mode);
-       scan_period = labpc_ai_scan_period(cmd, mode);
        if (convert_period && scan_period) {
                /*
-                * pick the lowest b0 divisor value we can (for maximum input
+                * pick the lowest divisor value we can (for maximum input
                 * clock speed on convert and scan counters)
                 */
-               devpriv->divisor_b0 = (scan_period - 1) /
-                   (I8254_OSC_BASE_2MHZ * 0x10000) + 1;
+               pacer->next_div1 = (scan_period - 1) /
+                                  (pacer->osc_base * I8254_MAX_COUNT) + 1;
 
-               cfc_check_trigger_arg_min(&devpriv->divisor_b0, 2);
-               cfc_check_trigger_arg_max(&devpriv->divisor_b0, 0x10000);
+               comedi_check_trigger_arg_min(&pacer->next_div1, 2);
+               comedi_check_trigger_arg_max(&pacer->next_div1,
+                                            I8254_MAX_COUNT);
 
-               base_period = I8254_OSC_BASE_2MHZ * devpriv->divisor_b0;
+               base_period = pacer->osc_base * pacer->next_div1;
 
                /*  set a0 for conversion frequency and b1 for scan frequency */
                switch (cmd->flags & CMDF_ROUND_MASK) {
                default:
                case CMDF_ROUND_NEAREST:
-                       devpriv->divisor_a0 = DIV_ROUND_CLOSEST(convert_period,
-                                                               base_period);
-                       devpriv->divisor_b1 = DIV_ROUND_CLOSEST(scan_period,
-                                                               base_period);
+                       pacer->next_div = DIV_ROUND_CLOSEST(convert_period,
+                                                           base_period);
+                       pacer->next_div2 = DIV_ROUND_CLOSEST(scan_period,
+                                                            base_period);
                        break;
                case CMDF_ROUND_UP:
-                       devpriv->divisor_a0 = DIV_ROUND_UP(convert_period,
-                                                          base_period);
-                       devpriv->divisor_b1 = DIV_ROUND_UP(scan_period,
-                                                          base_period);
+                       pacer->next_div = DIV_ROUND_UP(convert_period,
+                                                      base_period);
+                       pacer->next_div2 = DIV_ROUND_UP(scan_period,
+                                                       base_period);
                        break;
                case CMDF_ROUND_DOWN:
-                       devpriv->divisor_a0 = convert_period / base_period;
-                       devpriv->divisor_b1 = scan_period / base_period;
+                       pacer->next_div = convert_period / base_period;
+                       pacer->next_div2 = scan_period / base_period;
                        break;
                }
                /*  make sure a0 and b1 values are acceptable */
-               cfc_check_trigger_arg_min(&devpriv->divisor_a0, 2);
-               cfc_check_trigger_arg_max(&devpriv->divisor_a0, 0x10000);
-               cfc_check_trigger_arg_min(&devpriv->divisor_b1, 2);
-               cfc_check_trigger_arg_max(&devpriv->divisor_b1, 0x10000);
+               comedi_check_trigger_arg_min(&pacer->next_div, 2);
+               comedi_check_trigger_arg_max(&pacer->next_div, I8254_MAX_COUNT);
+               comedi_check_trigger_arg_min(&pacer->next_div2, 2);
+               comedi_check_trigger_arg_max(&pacer->next_div2,
+                                            I8254_MAX_COUNT);
+
                /*  write corrected timings to command */
                labpc_set_ai_convert_period(cmd, mode,
-                                           base_period * devpriv->divisor_a0);
+                                           base_period * pacer->next_div);
                labpc_set_ai_scan_period(cmd, mode,
-                                        base_period * devpriv->divisor_b1);
-               /*
-                * if only one TRIG_TIMER is used, we can employ the generic
-                * cascaded timing functions
-                */
+                                        base_period * pacer->next_div2);
        } else if (scan_period) {
                /*
                 * calculate cascaded counter values
                 * that give desired scan timing
+                * (pacer->next_div2 / pacer->next_div1)
                 */
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
-                                         &devpriv->divisor_b1,
-                                         &devpriv->divisor_b0,
-                                         &scan_period, cmd->flags);
+               comedi_8254_cascade_ns_to_timer(pacer, &scan_period,
+                                               cmd->flags);
                labpc_set_ai_scan_period(cmd, mode, scan_period);
        } else if (convert_period) {
                /*
                 * calculate cascaded counter values
                 * that give desired conversion timing
+                * (pacer->next_div / pacer->next_div1)
                 */
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
-                                         &devpriv->divisor_a0,
-                                         &devpriv->divisor_b0,
-                                         &convert_period, cmd->flags);
+               comedi_8254_cascade_ns_to_timer(pacer, &convert_period,
+                                               cmd->flags);
+               /* transfer div2 value so correct timer gets updated */
+               pacer->next_div = pacer->next_div2;
                labpc_set_ai_convert_period(cmd, mode, convert_period);
        }
 }
@@ -457,7 +429,7 @@ static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd)
                return MODE_SINGLE_CHAN;
 
        /* chanlist may be NULL during cmdtest */
-       if (cmd->chanlist == NULL)
+       if (!cmd->chanlist)
                return MODE_MULT_CHAN_UP;
 
        chan0 = CR_CHAN(cmd->chanlist[0]);
@@ -482,9 +454,6 @@ static int labpc_ai_check_chanlist(struct comedi_device *dev,
        unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
        int i;
 
-       if (mode == MODE_SINGLE_CHAN)
-               return 0;
-
        for (i = 0; i < cmd->chanlist_len; i++) {
                unsigned int chan = CR_CHAN(cmd->chanlist[i]);
                unsigned int range = CR_RANGE(cmd->chanlist[i]);
@@ -543,26 +512,27 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->convert_src,
+                                       TRIG_TIMER | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 
        stop_mask = TRIG_COUNT | TRIG_NONE;
        if (board->is_labpc1200)
                stop_mask |= TRIG_EXT;
-       err |= cfc_check_trigger_src(&cmd->stop_src, stop_mask);
+       err |= comedi_check_trigger_src(&cmd->stop_src, stop_mask);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -577,7 +547,7 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
 
        switch (cmd->start_src) {
        case TRIG_NOW:
-               err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
                break;
        case TRIG_EXT:
                /* start_arg value is ignored */
@@ -586,27 +556,33 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
 
        if (!cmd->chanlist_len)
                err |= -EINVAL;
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
-       if (cmd->convert_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                board->ai_speed);
+       if (cmd->convert_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                   board->ai_speed);
+       }
 
        /* make sure scan timing is not too fast */
        if (cmd->scan_begin_src == TRIG_TIMER) {
-               if (cmd->convert_src == TRIG_TIMER)
-                       err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                       cmd->convert_arg * cmd->chanlist_len);
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                               board->ai_speed * cmd->chanlist_len);
+               if (cmd->convert_src == TRIG_TIMER) {
+                       err |= comedi_check_trigger_arg_min(&cmd->
+                                                           scan_begin_arg,
+                                                           cmd->convert_arg *
+                                                           cmd->chanlist_len);
+               }
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   board->ai_speed *
+                                                   cmd->chanlist_len);
        }
 
        switch (cmd->stop_src) {
        case TRIG_COUNT:
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
                break;
        case TRIG_NONE:
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
                break;
                /*
                 * TRIG_EXT doesn't care since it doesn't
@@ -670,11 +646,12 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                 * load counter a1 with count of 3
                 * (pc+ manual says this is minimum allowed) using mode 0
                 */
-               labpc_counter_load(dev, COUNTER_A_BASE_REG,
-                                  1, 3, I8254_MODE0);
+               comedi_8254_load(devpriv->counter, 1,
+                                3, I8254_MODE0 | I8254_BINARY);
        } else  {
                /* just put counter a1 in mode 0 to set its output low */
-               labpc_counter_set_mode(dev, COUNTER_A_BASE_REG, 1, I8254_MODE0);
+               comedi_8254_set_mode(devpriv->counter, 1,
+                                    I8254_MODE0 | I8254_BINARY);
        }
 
        /* figure out what method we will use to transfer data */
@@ -715,27 +692,24 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
        if (cmd->convert_src == TRIG_TIMER ||
            cmd->scan_begin_src == TRIG_TIMER) {
-               /*  set up pacing */
-               labpc_adc_timing(dev, cmd, mode);
-               /*  load counter b0 in mode 3 */
-               labpc_counter_load(dev, COUNTER_B_BASE_REG,
-                                  0, devpriv->divisor_b0, I8254_MODE3);
-       }
-       /*  set up conversion pacing */
-       if (labpc_ai_convert_period(cmd, mode)) {
-               /*  load counter a0 in mode 2 */
-               labpc_counter_load(dev, COUNTER_A_BASE_REG,
-                                  0, devpriv->divisor_a0, I8254_MODE2);
-       } else {
-               /* initialize pacer counter to prevent any problems */
-               labpc_counter_set_mode(dev, COUNTER_A_BASE_REG, 0, I8254_MODE2);
-       }
+               struct comedi_8254 *pacer = dev->pacer;
+               struct comedi_8254 *counter = devpriv->counter;
+
+               comedi_8254_update_divisors(pacer);
 
-       /*  set up scan pacing */
-       if (labpc_ai_scan_period(cmd, mode)) {
-               /*  load counter b1 in mode 2 */
-               labpc_counter_load(dev, COUNTER_B_BASE_REG,
-                                  1, devpriv->divisor_b1, I8254_MODE2);
+               /* set up pacing */
+               comedi_8254_load(pacer, 0, pacer->divisor1,
+                                I8254_MODE3 | I8254_BINARY);
+
+               /* set up conversion pacing */
+               comedi_8254_set_mode(counter, 0, I8254_MODE2 | I8254_BINARY);
+               if (labpc_ai_convert_period(cmd, mode))
+                       comedi_8254_write(counter, 0, pacer->divisor);
+
+               /* set up scan pacing */
+               if (labpc_ai_scan_period(cmd, mode))
+                       comedi_8254_load(pacer, 1, pacer->divisor2,
+                                        I8254_MODE2 | I8254_BINARY);
        }
 
        labpc_clear_adc_fifo(dev);
@@ -1240,6 +1214,26 @@ int labpc_common_attach(struct comedi_device *dev,
                        dev->irq = irq;
        }
 
+       if (dev->mmio) {
+               dev->pacer = comedi_8254_mm_init(dev->mmio + COUNTER_B_BASE_REG,
+                                                I8254_OSC_BASE_2MHZ,
+                                                I8254_IO8, 0);
+               devpriv->counter = comedi_8254_mm_init(dev->mmio +
+                                                      COUNTER_A_BASE_REG,
+                                                      I8254_OSC_BASE_2MHZ,
+                                                      I8254_IO8, 0);
+       } else {
+               dev->pacer = comedi_8254_init(dev->iobase + COUNTER_B_BASE_REG,
+                                             I8254_OSC_BASE_2MHZ,
+                                             I8254_IO8, 0);
+               devpriv->counter = comedi_8254_init(dev->iobase +
+                                                   COUNTER_A_BASE_REG,
+                                                   I8254_OSC_BASE_2MHZ,
+                                                   I8254_IO8, 0);
+       }
+       if (!dev->pacer || !devpriv->counter)
+               return -ENOMEM;
+
        ret = comedi_alloc_subdevices(dev, 5);
        if (ret)
                return ret;
@@ -1336,6 +1330,15 @@ int labpc_common_attach(struct comedi_device *dev,
 }
 EXPORT_SYMBOL_GPL(labpc_common_attach);
 
+void labpc_common_detach(struct comedi_device *dev)
+{
+       struct labpc_private *devpriv = dev->private;
+
+       if (devpriv)
+               kfree(devpriv->counter);
+}
+EXPORT_SYMBOL_GPL(labpc_common_detach);
+
 static int __init labpc_common_init(void)
 {
        return 0;
index 746c4cd9978dead43d9b0252793de9f08a28522d..a1c69ac075d517ffa3035d5748ecd514082d1290 100644 (file)
@@ -68,8 +68,8 @@ static const struct labpc_boardinfo labpc_cs_boards[] = {
        },
 };
 
-static int labpc_auto_attach(struct comedi_device *dev,
-                            unsigned long context)
+static int labpc_cs_auto_attach(struct comedi_device *dev,
+                               unsigned long context)
 {
        struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
        int ret;
@@ -90,11 +90,17 @@ static int labpc_auto_attach(struct comedi_device *dev,
        return labpc_common_attach(dev, link->irq, IRQF_SHARED);
 }
 
+static void labpc_cs_detach(struct comedi_device *dev)
+{
+       labpc_common_detach(dev);
+       comedi_pcmcia_disable(dev);
+}
+
 static struct comedi_driver driver_labpc_cs = {
        .driver_name    = "ni_labpc_cs",
        .module         = THIS_MODULE,
-       .auto_attach    = labpc_auto_attach,
-       .detach         = comedi_pcmcia_disable,
+       .auto_attach    = labpc_cs_auto_attach,
+       .detach         = labpc_cs_detach,
 };
 
 static int labpc_cs_attach(struct pcmcia_device *link)
index 6b4ccd86b3d093b7603bfafafede0264c0bdcadb..29dbdf5ec25dfb37d4de072946d8d6d878543af8 100644 (file)
@@ -23,7 +23,6 @@
 #include "../comedidev.h"
 
 #include "comedi_isadma.h"
-#include "comedi_fc.h"
 #include "ni_labpc.h"
 #include "ni_labpc_regs.h"
 #include "ni_labpc_isadma.h"
index 0407ff681dfd507cf731053a9d2f415cf09b9500..77d403801db505fae0390e9d58920118e29ed1db 100644 (file)
@@ -31,9 +31,8 @@
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #include "ni_labpc.h"
 
@@ -51,7 +50,7 @@ static const struct labpc_boardinfo labpc_pci_boards[] = {
        },
 };
 
-/* ripped from mite.h and mite_setup2() to avoid mite dependancy */
+/* ripped from mite.h and mite_setup2() to avoid mite dependency */
 #define MITE_IODWBSR   0xc0     /* IO Device Window Base Size Register */
 #define WENAB          (1 << 7) /* window enable */
 
@@ -103,11 +102,17 @@ static int labpc_pci_auto_attach(struct comedi_device *dev,
        return labpc_common_attach(dev, pcidev->irq, IRQF_SHARED);
 }
 
+static void labpc_pci_detach(struct comedi_device *dev)
+{
+       labpc_common_detach(dev);
+       comedi_pci_detach(dev);
+}
+
 static struct comedi_driver labpc_pci_comedi_driver = {
        .driver_name    = "labpc_pci",
        .module         = THIS_MODULE,
        .auto_attach    = labpc_pci_auto_attach,
-       .detach         = comedi_pci_detach,
+       .detach         = labpc_pci_detach,
 };
 
 static const struct pci_device_id labpc_pci_table[] = {
index b6ddc015dedf733e2903d5f4f59b0cd970e61d50..c66affd993aa987b0748bad42c708051804840ce 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/delay.h>
 #include "8255.h"
 #include "mite.h"
-#include "comedi_fc.h"
 
 /* A timeout count */
 #define NI_TIMEOUT 1000
@@ -670,8 +669,8 @@ static inline void ni_set_bitfield(struct comedi_device *dev, int reg,
                ni_writeb(dev, devpriv->g0_g1_select_reg, G0_G1_Select);
                break;
        default:
-               dev_err(dev->class_dev,
-                       "%s called with invalid register %d\n", __func__, reg);
+               dev_err(dev->class_dev, "called with invalid register %d\n",
+                       reg);
                break;
        }
        mmiowb();
@@ -755,7 +754,7 @@ static int ni_request_ai_mite_channel(struct comedi_device *dev)
        BUG_ON(devpriv->ai_mite_chan);
        devpriv->ai_mite_chan =
            mite_request_channel(devpriv->mite, devpriv->ai_mite_ring);
-       if (devpriv->ai_mite_chan == NULL) {
+       if (!devpriv->ai_mite_chan) {
                spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
                dev_err(dev->class_dev,
                        "failed to reserve mite dma channel for analog input\n");
@@ -776,7 +775,7 @@ static int ni_request_ao_mite_channel(struct comedi_device *dev)
        BUG_ON(devpriv->ao_mite_chan);
        devpriv->ao_mite_chan =
            mite_request_channel(devpriv->mite, devpriv->ao_mite_ring);
-       if (devpriv->ao_mite_chan == NULL) {
+       if (!devpriv->ao_mite_chan) {
                spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
                dev_err(dev->class_dev,
                        "failed to reserve mite dma channel for analog outut\n");
@@ -802,7 +801,7 @@ static int ni_request_gpct_mite_channel(struct comedi_device *dev,
        mite_chan =
            mite_request_channel(devpriv->mite,
                                 devpriv->gpct_mite_ring[gpct_index]);
-       if (mite_chan == NULL) {
+       if (!mite_chan) {
                spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
                dev_err(dev->class_dev,
                        "failed to reserve mite dma channel for counter\n");
@@ -828,7 +827,7 @@ static int ni_request_cdo_mite_channel(struct comedi_device *dev)
        BUG_ON(devpriv->cdo_mite_chan);
        devpriv->cdo_mite_chan =
            mite_request_channel(devpriv->mite, devpriv->cdo_mite_ring);
-       if (devpriv->cdo_mite_chan == NULL) {
+       if (!devpriv->cdo_mite_chan) {
                spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
                dev_err(dev->class_dev,
                        "failed to reserve mite dma channel for correlated digital output\n");
@@ -1068,7 +1067,7 @@ static int ni_ai_drain_dma(struct comedi_device *dev)
                        udelay(5);
                }
                if (i == timeout) {
-                       dev_err(dev->class_dev, "%s timed out\n", __func__);
+                       dev_err(dev->class_dev, "timed out\n");
                        dev_err(dev->class_dev,
                                "mite_bytes_in_transit=%i, AI_Status1_Register=0x%x\n",
                                mite_bytes_in_transit(devpriv->ai_mite_chan),
@@ -1360,7 +1359,7 @@ static void get_last_sample_611x(struct comedi_device *dev)
        /* Check if there's a single sample stuck in the FIFO */
        if (ni_readb(dev, XXX_Status) & 0x80) {
                dl = ni_readl(dev, ADC_FIFO_Data_611x);
-               data = (dl & 0xffff);
+               data = dl & 0xffff;
                comedi_buf_write_samples(s, &data, 1);
        }
 }
@@ -1657,7 +1656,7 @@ static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
        comedi_buf_write_alloc(s, s->async->prealloc_bufsz);
 
        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
-       if (devpriv->ai_mite_chan == NULL) {
+       if (!devpriv->ai_mite_chan) {
                spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
                return -EIO;
        }
@@ -1700,8 +1699,9 @@ static int ni_ao_setup_MITE_dma(struct comedi_device *dev)
                        mite_prep_dma(devpriv->ao_mite_chan, 16, 32);
                }
                mite_dma_arm(devpriv->ao_mite_chan);
-       } else
+       } else {
                retval = -EIO;
+       }
        spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 
        return retval;
@@ -1870,7 +1870,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
                chan = CR_CHAN(list[0]);
                range = CR_RANGE(list[0]);
                range_code = ni_gainlkup[board->gainlkup][range];
-               dither = ((list[0] & CR_ALT_FILTER) != 0);
+               dither = (list[0] & CR_ALT_FILTER) != 0;
                bypass_bits = MSeries_AI_Bypass_Config_FIFO_Bit;
                bypass_bits |= chan;
                bypass_bits |=
@@ -1894,7 +1894,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
                chan = CR_CHAN(list[i]);
                aref = CR_AREF(list[i]);
                range = CR_RANGE(list[i]);
-               dither = ((list[i] & CR_ALT_FILTER) != 0);
+               dither = (list[i] & CR_ALT_FILTER) != 0;
 
                range_code = ni_gainlkup[board->gainlkup][range];
                devpriv->ai_offset[i] = 0;
@@ -2020,7 +2020,7 @@ static void ni_load_channelgain_list(struct comedi_device *dev,
                        chan = CR_CHAN(list[i]);
                aref = CR_AREF(list[i]);
                range = CR_RANGE(list[i]);
-               dither = ((list[i] & CR_ALT_FILTER) != 0);
+               dither = (list[i] & CR_ALT_FILTER) != 0;
 
                /* fix the external/internal range differences */
                range = ni_gainlkup[board->gainlkup][range];
@@ -2116,8 +2116,7 @@ static int ni_ai_insn_read(struct comedi_device *dev,
                                }
                        }
                        if (i == NI_TIMEOUT) {
-                               dev_err(dev->class_dev, "%s timeout\n",
-                                       __func__);
+                               dev_err(dev->class_dev, "timeout\n");
                                return -ETIME;
                        }
                        d += signbits;
@@ -2140,8 +2139,7 @@ static int ni_ai_insn_read(struct comedi_device *dev,
                                }
                        }
                        if (i == NI_TIMEOUT) {
-                               dev_err(dev->class_dev, "%s timeout\n",
-                                       __func__);
+                               dev_err(dev->class_dev, "timeout\n");
                                return -ETIME;
                        }
                        data[n] = (((dl >> 16) & 0xFFFF) + signbits) & 0xFFFF;
@@ -2156,8 +2154,7 @@ static int ni_ai_insn_read(struct comedi_device *dev,
                                        break;
                        }
                        if (i == NI_TIMEOUT) {
-                               dev_err(dev->class_dev, "%s timeout\n",
-                                       __func__);
+                               dev_err(dev->class_dev, "timeout\n");
                                return -ETIME;
                        }
                        if (devpriv->is_m_series) {
@@ -2227,28 +2224,28 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src,
+       err |= comedi_check_trigger_src(&cmd->start_src,
                                        TRIG_NOW | TRIG_INT | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_TIMER | TRIG_EXT);
 
        sources = TRIG_TIMER | TRIG_EXT;
        if (devpriv->is_611x || devpriv->is_6143)
                sources |= TRIG_NOW;
-       err |= cfc_check_trigger_src(&cmd->convert_src, sources);
+       err |= comedi_check_trigger_src(&cmd->convert_src, sources);
 
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -2260,7 +2257,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
        switch (cmd->start_src) {
        case TRIG_NOW:
        case TRIG_INT:
-               err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
                break;
        case TRIG_EXT:
                tmp = CR_CHAN(cmd->start_arg);
@@ -2268,15 +2265,16 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
                if (tmp > 16)
                        tmp = 16;
                tmp |= (cmd->start_arg & (CR_INVERT | CR_EDGE));
-               err |= cfc_check_trigger_arg_is(&cmd->start_arg, tmp);
+               err |= comedi_check_trigger_arg_is(&cmd->start_arg, tmp);
                break;
        }
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
                        ni_min_ai_scan_period_ns(dev, cmd->chanlist_len));
-               err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
-                                                devpriv->clock_ns * 0xffffff);
+               err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
+                                                   devpriv->clock_ns *
+                                                   0xffffff);
        } else if (cmd->scan_begin_src == TRIG_EXT) {
                /* external trigger */
                unsigned int tmp = CR_CHAN(cmd->scan_begin_arg);
@@ -2284,19 +2282,21 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
                if (tmp > 16)
                        tmp = 16;
                tmp |= (cmd->scan_begin_arg & (CR_INVERT | CR_EDGE));
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
        } else {                /* TRIG_OTHER */
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
        }
 
        if (cmd->convert_src == TRIG_TIMER) {
                if (devpriv->is_611x || devpriv->is_6143) {
-                       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+                       err |= comedi_check_trigger_arg_is(&cmd->convert_arg,
+                                                          0);
                } else {
-                       err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                        board->ai_speed);
-                       err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
-                                               devpriv->clock_ns * 0xffff);
+                       err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                           board->ai_speed);
+                       err |= comedi_check_trigger_arg_max(&cmd->convert_arg,
+                                                           devpriv->clock_ns *
+                                                           0xffff);
                }
        } else if (cmd->convert_src == TRIG_EXT) {
                /* external trigger */
@@ -2305,23 +2305,24 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
                if (tmp > 16)
                        tmp = 16;
                tmp |= (cmd->convert_arg & (CR_ALT_FILTER | CR_INVERT));
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, tmp);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, tmp);
        } else if (cmd->convert_src == TRIG_NOW) {
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
        }
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT) {
                unsigned int max_count = 0x01000000;
 
                if (devpriv->is_611x)
                        max_count -= num_adc_stages_611x;
-               err |= cfc_check_trigger_arg_max(&cmd->stop_arg, max_count);
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_max(&cmd->stop_arg, max_count);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        } else {
                /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
        }
 
        if (err)
@@ -2529,7 +2530,7 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                start_stop_select |=
                    AI_START_Select(1 + CR_CHAN(cmd->scan_begin_arg));
                ni_stc_writew(dev, start_stop_select,
-                                   AI_START_STOP_Select_Register);
+                             AI_START_STOP_Select_Register);
                break;
        }
 
@@ -2572,7 +2573,6 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        }
 
        if (dev->irq) {
-
                /* interrupt on FIFO, errors, SC_TC */
                interrupt_a_enable |= AI_Error_Interrupt_Enable |
                    AI_SC_TC_Interrupt_Enable;
@@ -2808,8 +2808,7 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev,
                        break;
                default:
                        dev_err(dev->class_dev,
-                               "%s: bug! unhandled ao reference voltage\n",
-                               __func__);
+                               "bug! unhandled ao reference voltage\n");
                        break;
                }
                switch (krange->max + krange->min) {
@@ -2821,8 +2820,7 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev,
                        break;
                default:
                        dev_err(dev->class_dev,
-                               "%s: bug! unhandled ao offset voltage\n",
-                               __func__);
+                               "bug! unhandled ao offset voltage\n");
                        break;
                }
                if (timed)
@@ -3262,21 +3260,21 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -3287,7 +3285,7 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
        switch (cmd->start_src) {
        case TRIG_INT:
-               err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
                break;
        case TRIG_EXT:
                tmp = CR_CHAN(cmd->start_arg);
@@ -3295,24 +3293,26 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
                if (tmp > 18)
                        tmp = 18;
                tmp |= (cmd->start_arg & (CR_INVERT | CR_EDGE));
-               err |= cfc_check_trigger_arg_is(&cmd->start_arg, tmp);
+               err |= comedi_check_trigger_arg_is(&cmd->start_arg, tmp);
                break;
        }
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                board->ao_speed);
-               err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
-                                                devpriv->clock_ns * 0xffffff);
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   board->ao_speed);
+               err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
+                                                   devpriv->clock_ns *
+                                                   0xffffff);
        }
 
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
+               err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -3474,11 +3474,11 @@ static int ni_cdio_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+       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_NONE);
 
        if (err)
                return 1;
@@ -3488,16 +3488,17 @@ static int ni_cdio_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        tmp = cmd->scan_begin_arg;
        tmp &= CR_PACK_FLAGS(CDO_Sample_Source_Select_Mask, 0, 0, CR_INVERT);
        if (tmp != cmd->scan_begin_arg)
                err |= -EINVAL;
 
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-       err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -3694,8 +3695,7 @@ static int ni_serial_hw_readwrite8(struct comedi_device *dev,
                udelay((devpriv->serial_interval_ns + 999) / 1000);
                if (--count < 0) {
                        dev_err(dev->class_dev,
-                               "%s: SPI serial I/O didn't finish in time!\n",
-                               __func__);
+                               "SPI serial I/O didn't finish in time!\n");
                        err = -ETIME;
                        goto Error;
                }
@@ -3705,7 +3705,7 @@ static int ni_serial_hw_readwrite8(struct comedi_device *dev,
           DIO_Serial_IO_In_Progress_St goes high one bit too early. */
        udelay((devpriv->serial_interval_ns + 999) / 1000);
 
-       if (data_in != NULL)
+       if (data_in)
                *data_in = ni_stc_readw(dev, DIO_Serial_Input_Register);
 
 Error:
@@ -3817,8 +3817,6 @@ static int ni_serial_insn_config(struct comedi_device *dev,
                              Clock_and_FOUT_Register);
                return 1;
 
-               break;
-
        case INSN_CONFIG_BIDIRECTIONAL_DATA:
 
                if (devpriv->serial_interval_ns == 0)
@@ -3833,8 +3831,7 @@ static int ni_serial_insn_config(struct comedi_device *dev,
                        err = ni_serial_sw_readwrite8(dev, s, byte_out,
                                                      &byte_in);
                } else {
-                       dev_err(dev->class_dev, "%s: serial disabled!\n",
-                               __func__);
+                       dev_err(dev->class_dev, "serial disabled!\n");
                        return -EINVAL;
                }
                if (err < 0)
@@ -3846,7 +3843,6 @@ static int ni_serial_insn_config(struct comedi_device *dev,
        default:
                return -EINVAL;
        }
-
 }
 
 static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s)
@@ -4520,8 +4516,7 @@ static unsigned ni_old_get_pfi_routing(struct comedi_device *dev,
        case 9:
                return NI_PFI_OUTPUT_G_GATE0;
        default:
-               dev_err(dev->class_dev,
-                       "%s: bug, unhandled case in switch.\n", __func__);
+               dev_err(dev->class_dev, "bug, unhandled case in switch.\n");
                break;
        }
        return 0;
@@ -4673,7 +4668,7 @@ static int cs5529_wait_for_idle(struct comedi_device *dev)
                        return -EIO;
        }
        if (i == timeout) {
-               dev_err(dev->class_dev, "%s timeout\n", __func__);
+               dev_err(dev->class_dev, "timeout\n");
                return -ETIME;
        }
        return 0;
@@ -4908,7 +4903,7 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device *dev,
                                               &devpriv->clock_ns);
        if (retval < 0) {
                dev_err(dev->class_dev,
-                       "%s: bug, failed to find pll parameters\n", __func__);
+                       "bug, failed to find pll parameters\n");
                return retval;
        }
 
@@ -4966,14 +4961,14 @@ static int ni_set_master_clock(struct comedi_device *dev,
                                              RTSI_Trig_Direction_Register);
                                if (period_ns == 0) {
                                        dev_err(dev->class_dev,
-                                               "%s: we don't handle an unspecified clock period correctly yet, returning error\n",
-                                               __func__);
+                                               "we don't handle an unspecified clock period correctly yet, returning error\n");
                                        return -EINVAL;
                                }
                                devpriv->clock_ns = period_ns;
                                devpriv->clock_source = source;
-                       } else
+                       } else {
                                return -EINVAL;
+                       }
                }
        }
        return 3;
@@ -5057,8 +5052,7 @@ static unsigned ni_get_rtsi_routing(struct comedi_device *dev, unsigned chan)
        } else {
                if (chan == old_RTSI_clock_channel)
                        return NI_RTSI_OUTPUT_RTSI_OSC;
-               dev_err(dev->class_dev, "%s: bug! should never get here?\n",
-                       __func__);
+               dev_err(dev->class_dev, "bug! should never get here?\n");
                return 0;
        }
 }
index db399fe8c301049143009a602401e9a9f01916a7..ac79099bc23e4d94a09ad99cca01c352a8aacbc9 100644 (file)
@@ -53,9 +53,8 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
-#include "comedi_fc.h"
 #include "mite.h"
 
 /* defines for the PCI-DIO-32HS */
@@ -304,7 +303,7 @@ static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
        devpriv->di_mite_chan =
            mite_request_channel_in_range(devpriv->mite,
                                          devpriv->di_mite_ring, 1, 2);
-       if (devpriv->di_mite_chan == NULL) {
+       if (!devpriv->di_mite_chan) {
                spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
                dev_err(dev->class_dev, "failed to reserve mite dma channel\n");
                return -EBUSY;
@@ -354,8 +353,9 @@ static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
        if (devpriv->di_mite_chan) {
                mite_prep_dma(devpriv->di_mite_chan, 32, 32);
                mite_dma_arm(devpriv->di_mite_chan);
-       } else
+       } else {
                retval = -EIO;
+       }
        spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 
        return retval;
@@ -547,21 +547,21 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -570,13 +570,13 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
 #define MAX_SPEED      (TIMER_BASE)    /* in nanoseconds */
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                MAX_SPEED);
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   MAX_SPEED);
                /* no minimum speed */
        } else {
                /* TRIG_EXT */
@@ -587,13 +587,14 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev,
                }
        }
 
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -603,7 +604,7 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev,
        if (cmd->scan_begin_src == TRIG_TIMER) {
                arg = cmd->scan_begin_arg;
                ni_pcidio_ns_to_timer(&arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
 
        if (err)
@@ -924,7 +925,7 @@ static int nidio_auto_attach(struct comedi_device *dev,
                return ret;
 
        devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite);
-       if (devpriv->di_mite_ring == NULL)
+       if (!devpriv->di_mite_ring)
                return -ENOMEM;
 
        if (board->uses_firmware) {
index 3b2bdebbca5983ae2cc87f552301101ae930f32a..1481f71a31b1b3e8fd36914e4edcea405650952b 100644 (file)
@@ -109,7 +109,7 @@ Bugs:
 #include <linux/module.h>
 #include <linux/delay.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
 #include <asm/byteorder.h>
 
@@ -1041,7 +1041,6 @@ static int pcimio_dio_change(struct comedi_device *dev,
        return 0;
 }
 
-
 static void m_series_init_eeprom_buffer(struct comedi_device *dev)
 {
        struct ni_private *devpriv = dev->private;
@@ -1183,19 +1182,19 @@ static int pcimio_auto_attach(struct comedi_device *dev,
                return ret;
 
        devpriv->ai_mite_ring = mite_alloc_ring(devpriv->mite);
-       if (devpriv->ai_mite_ring == NULL)
+       if (!devpriv->ai_mite_ring)
                return -ENOMEM;
        devpriv->ao_mite_ring = mite_alloc_ring(devpriv->mite);
-       if (devpriv->ao_mite_ring == NULL)
+       if (!devpriv->ao_mite_ring)
                return -ENOMEM;
        devpriv->cdo_mite_ring = mite_alloc_ring(devpriv->mite);
-       if (devpriv->cdo_mite_ring == NULL)
+       if (!devpriv->cdo_mite_ring)
                return -ENOMEM;
        devpriv->gpct_mite_ring[0] = mite_alloc_ring(devpriv->mite);
-       if (devpriv->gpct_mite_ring[0] == NULL)
+       if (!devpriv->gpct_mite_ring[0])
                return -ENOMEM;
        devpriv->gpct_mite_ring[1] = mite_alloc_ring(devpriv->mite);
-       if (devpriv->gpct_mite_ring[1] == NULL)
+       if (!devpriv->gpct_mite_ring[1])
                return -ENOMEM;
 
        if (devpriv->is_m_series)
index d36c3abd31209dd42e6651183ecf5f3a64bddb8a..9b124b09e9140aee5cad69aa9ab75a542acd0436 100644 (file)
@@ -44,7 +44,6 @@ TODO:
 */
 
 #include <linux/module.h>
-#include "comedi_fc.h"
 #include "ni_tio_internal.h"
 #include "mite.h"
 
@@ -201,7 +200,7 @@ int ni_tio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        unsigned long flags;
 
        spin_lock_irqsave(&counter->lock, flags);
-       if (counter->mite_chan == NULL) {
+       if (!counter->mite_chan) {
                dev_err(counter->counter_dev->dev->class_dev,
                        "commands only supported with DMA.  ");
                dev_err(counter->counter_dev->dev->class_dev,
@@ -234,23 +233,23 @@ int ni_tio_cmdtest(struct comedi_device *dev,
        sources = TRIG_NOW | TRIG_INT | TRIG_OTHER;
        if (ni_tio_counting_mode_registers_present(counter->counter_dev))
                sources |= TRIG_EXT;
-       err |= cfc_check_trigger_src(&cmd->start_src, sources);
+       err |= comedi_check_trigger_src(&cmd->start_src, sources);
 
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_FOLLOW | TRIG_EXT | TRIG_OTHER);
-       err |= cfc_check_trigger_src(&cmd->convert_src,
+       err |= comedi_check_trigger_src(&cmd->convert_src,
                                        TRIG_NOW | TRIG_EXT | TRIG_OTHER);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -266,7 +265,7 @@ int ni_tio_cmdtest(struct comedi_device *dev,
        case TRIG_NOW:
        case TRIG_INT:
        case TRIG_OTHER:
-               err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
                break;
        case TRIG_EXT:
                /* start_arg is the start_trigger passed to ni_tio_arm() */
@@ -274,13 +273,14 @@ int ni_tio_cmdtest(struct comedi_device *dev,
        }
 
        if (cmd->scan_begin_src != TRIG_EXT)
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
        if (cmd->convert_src != TRIG_EXT)
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-       err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -329,7 +329,7 @@ static int should_ack_gate(struct ni_gpct *counter)
        case ni_gpct_variant_e_series:
                spin_lock_irqsave(&counter->lock, flags);
                {
-                       if (counter->mite_chan == NULL ||
+                       if (!counter->mite_chan ||
                            counter->mite_chan->dir != COMEDI_INPUT ||
                            (mite_done(counter->mite_chan))) {
                                retval = 1;
@@ -366,7 +366,7 @@ static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter,
        if (gxx_status & GI_GATE_ERROR(cidx)) {
                ack |= GI_GATE_ERROR_CONFIRM(cidx);
                if (gate_error) {
-                       /*660x don't support automatic acknowledgement
+                       /*660x don't support automatic acknowledgment
                          of gate interrupt via dma read/write
                           and report bogus gate errors */
                        if (counter->counter_dev->variant !=
@@ -443,7 +443,7 @@ void ni_tio_handle_interrupt(struct ni_gpct *counter,
                break;
        }
        spin_lock_irqsave(&counter->lock, flags);
-       if (counter->mite_chan == NULL) {
+       if (!counter->mite_chan) {
                spin_unlock_irqrestore(&counter->lock, flags);
                return;
        }
index cb7e4c37b8b9957923f1ed414585eada582afd19..cfc3a627d0ca3673c35cfd975283e692ceffc41e 100644 (file)
@@ -41,8 +41,7 @@
 
 #include "../comedidev.h"
 
-#include "comedi_fc.h"
-#include "8253.h"
+#include "comedi_8254.h"
 
 /*
  * I/O port register map
@@ -153,11 +152,6 @@ static const struct pcl711_board boardtypes[] = {
        },
 };
 
-struct pcl711_private {
-       unsigned int divisor1;
-       unsigned int divisor2;
-};
-
 static void pcl711_ai_set_mode(struct comedi_device *dev, unsigned int mode)
 {
        /*
@@ -287,26 +281,24 @@ static int pcl711_ai_insn_read(struct comedi_device *dev,
 static int pcl711_ai_cmdtest(struct comedi_device *dev,
                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
-       struct pcl711_private *devpriv = dev->private;
        int err = 0;
-       unsigned int arg;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -315,23 +307,24 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_EXT) {
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
        } else {
 #define MAX_SPEED 1000
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                MAX_SPEED);
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   MAX_SPEED);
        }
 
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -339,12 +332,10 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev,
        /* step 4 */
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
-               arg = cmd->scan_begin_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
-                                         &devpriv->divisor1,
-                                         &devpriv->divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               unsigned int arg = cmd->scan_begin_arg;
+
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
 
        if (err)
@@ -353,18 +344,6 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev,
        return 0;
 }
 
-static void pcl711_ai_load_counters(struct comedi_device *dev)
-{
-       struct pcl711_private *devpriv = dev->private;
-       unsigned long timer_base = dev->iobase + PCL711_TIMER_BASE;
-
-       i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
-
-       i8254_write(timer_base, 0, 1, devpriv->divisor1);
-       i8254_write(timer_base, 0, 2, devpriv->divisor2);
-}
-
 static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
        struct comedi_cmd *cmd = &s->async->cmd;
@@ -372,7 +351,8 @@ static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        pcl711_set_changain(dev, s, cmd->chanlist[0]);
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
-               pcl711_ai_load_counters(dev);
+               comedi_8254_update_divisors(dev->pacer);
+               comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
                outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG);
                pcl711_ai_set_mode(dev, PCL711_MODE_PACER_IRQ);
        } else {
@@ -445,14 +425,9 @@ static int pcl711_do_insn_bits(struct comedi_device *dev,
 static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct pcl711_board *board = dev->board_ptr;
-       struct pcl711_private *devpriv;
        struct comedi_subdevice *s;
        int ret;
 
-       devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
-       if (!devpriv)
-               return -ENOMEM;
-
        ret = comedi_request_region(dev, it->options[0], 0x10);
        if (ret)
                return ret;
@@ -464,6 +439,11 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                        dev->irq = it->options[1];
        }
 
+       dev->pacer = comedi_8254_init(dev->iobase + PCL711_TIMER_BASE,
+                                     I8254_OSC_BASE_2MHZ, I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
                return ret;
index 40798150cfd8d20d6668742d85ba12860ab0d6bb..256850ccb6fa21d09389ed3ae341171716fb633c 100644 (file)
@@ -62,8 +62,6 @@
 
 #include "../comedidev.h"
 
-#include "comedi_fc.h"
-
 #define PCL726_AO_MSB_REG(x)   (0x00 + ((x) * 2))
 #define PCL726_AO_LSB_REG(x)   (0x01 + ((x) * 2))
 #define PCL726_DO_MSB_REG      0x0c
@@ -173,11 +171,11 @@ static int pcl726_intr_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);
 
        if (err)
                return 1;
@@ -187,11 +185,12 @@ static int pcl726_intr_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
-       err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
index 3ffb1ea2ecc87ba462d4a472c3bde08ed95d442f..03a3fd6cd918b4e59d42da3b9fe9052172d3686d 100644 (file)
 #include "../comedidev.h"
 
 #include "comedi_isadma.h"
-#include "comedi_fc.h"
-#include "8253.h"
+#include "comedi_8254.h"
 
 /* hardware types of the cards */
 #define boardPCL812PG        0 /* and ACL-8112PG */
@@ -513,8 +512,6 @@ struct pcl812_private {
        unsigned char mode_reg_int;     /*  there is stored INT number for some card */
        unsigned int ai_poll_ptr;       /*  how many sampes transfer poll */
        unsigned int max_812_ai_mode0_rangewait;        /*  setling time for gain */
-       unsigned int divisor1;
-       unsigned int divisor2;
        unsigned int use_diff:1;
        unsigned int use_mpc508:1;
        unsigned int use_ext_trg:1;
@@ -522,21 +519,6 @@ struct pcl812_private {
        unsigned int ai_eos:1;
 };
 
-static void pcl812_start_pacer(struct comedi_device *dev, bool load_timers)
-{
-       struct pcl812_private *devpriv = dev->private;
-       unsigned long timer_base = dev->iobase + PCL812_TIMER_BASE;
-
-       i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
-       udelay(1);
-
-       if (load_timers) {
-               i8254_write(timer_base, 0, 2, devpriv->divisor2);
-               i8254_write(timer_base, 0, 1, devpriv->divisor1);
-       }
-}
-
 static void pcl812_ai_setup_dma(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                unsigned int unread_samples)
@@ -650,28 +632,27 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
        struct pcl812_private *devpriv = dev->private;
        int err = 0;
        unsigned int flags;
-       unsigned int arg;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
 
        if (devpriv->use_ext_trg)
                flags = TRIG_EXT;
        else
                flags = TRIG_TIMER;
-       err |= cfc_check_trigger_src(&cmd->convert_src, flags);
+       err |= comedi_check_trigger_src(&cmd->convert_src, flags);
 
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -680,22 +661,24 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
-       if (cmd->convert_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                board->ai_ns_min);
-       else    /* TRIG_EXT */
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+       if (cmd->convert_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                   board->ai_ns_min);
+       } else {        /* TRIG_EXT */
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       }
 
-       err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -703,12 +686,10 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
        /* step 4: fix up any arguments */
 
        if (cmd->convert_src == TRIG_TIMER) {
-               arg = cmd->convert_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
-                                         &devpriv->divisor1,
-                                         &devpriv->divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               unsigned int arg = cmd->convert_arg;
+
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
        }
 
        if (err)
@@ -725,8 +706,6 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        unsigned int ctrl = 0;
        unsigned int i;
 
-       pcl812_start_pacer(dev, false);
-
        pcl812_ai_set_chan_range(dev, cmd->chanlist[0], 1);
 
        if (dma) {      /*  check if we can use DMA transfer */
@@ -760,7 +739,8 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
        switch (cmd->convert_src) {
        case TRIG_TIMER:
-               pcl812_start_pacer(dev, true);
+               comedi_8254_update_divisors(dev->pacer);
+               comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
                break;
        }
 
@@ -918,7 +898,7 @@ static int pcl812_ai_cancel(struct comedi_device *dev,
 
        outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG,
             dev->iobase + PCL812_CTRL_REG);
-       pcl812_start_pacer(dev, false);
+       comedi_8254_pacer_enable(dev->pacer, 1, 2, false);
        pcl812_ai_clear_eoc(dev);
        return 0;
 }
@@ -1010,10 +990,6 @@ static void pcl812_reset(struct comedi_device *dev)
             dev->iobase + PCL812_CTRL_REG);
        pcl812_ai_clear_eoc(dev);
 
-       /* stop pacer */
-       if (board->IRQbits)
-               pcl812_start_pacer(dev, false);
-
        /*
         * Invalidate last_ai_chanspec then set analog input to
         * known channel/range.
@@ -1162,11 +1138,19 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (ret)
                return ret;
 
-       if ((1 << it->options[1]) & board->IRQbits) {
-               ret = request_irq(it->options[1], pcl812_interrupt, 0,
-                                 dev->board_name, dev);
-               if (ret == 0)
-                       dev->irq = it->options[1];
+       if (board->IRQbits) {
+               dev->pacer = comedi_8254_init(dev->iobase + PCL812_TIMER_BASE,
+                                             I8254_OSC_BASE_2MHZ,
+                                             I8254_IO8, 0);
+               if (!dev->pacer)
+                       return -ENOMEM;
+
+               if ((1 << it->options[1]) & board->IRQbits) {
+                       ret = request_irq(it->options[1], pcl812_interrupt, 0,
+                                         dev->board_name, dev);
+                       if (ret == 0)
+                               dev->irq = it->options[1];
+               }
        }
 
        /* we need an IRQ to do DMA on channel 3 or 1 */
index da35edfccbc3bb5fb570ea0c606da236eb559e8f..1ccb2f19f4be6876d00824ad6fdb57811aa9a902 100644 (file)
@@ -41,8 +41,7 @@ Configuration Options:
 #include "../comedidev.h"
 
 #include "comedi_isadma.h"
-#include "comedi_fc.h"
-#include "8253.h"
+#include "comedi_8254.h"
 
 /*
  * Register I/O map
@@ -116,31 +115,10 @@ static const struct pcl816_board boardtypes[] = {
 struct pcl816_private {
        struct comedi_isadma *dma;
        unsigned int ai_poll_ptr;       /*  how many sampes transfer poll */
-       unsigned int divisor1;
-       unsigned int divisor2;
        unsigned int ai_cmd_running:1;
        unsigned int ai_cmd_canceled:1;
 };
 
-static void pcl816_start_pacer(struct comedi_device *dev, bool load_counters)
-{
-       struct pcl816_private *devpriv = dev->private;
-       unsigned long timer_base = dev->iobase + PCL816_TIMER_BASE;
-
-       i8254_set_mode(timer_base, 0, 0, I8254_MODE1 | I8254_BINARY);
-       i8254_write(timer_base, 0, 0, 0x00ff);
-       udelay(1);
-
-       i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
-       udelay(1);
-
-       if (load_counters) {
-               i8254_write(timer_base, 0, 2, devpriv->divisor2);
-               i8254_write(timer_base, 0, 1, devpriv->divisor1);
-       }
-}
-
 static void pcl816_ai_setup_dma(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                unsigned int unread_samples)
@@ -367,67 +345,62 @@ static int check_channel_list(struct comedi_device *dev,
 static int pcl816_ai_cmdtest(struct comedi_device *dev,
                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
-       struct pcl816_private *devpriv = dev->private;
        int err = 0;
-       unsigned int arg;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_EXT | TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->convert_src,
+                                       TRIG_EXT | TRIG_TIMER);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
        if (err)
                return 2;
 
-
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
        if (cmd->convert_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000);
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 10000);
        else    /* TRIG_EXT */
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
 
-
        /* step 4: fix up any arguments */
        if (cmd->convert_src == TRIG_TIMER) {
-               arg = cmd->convert_arg;
-               i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
-                                         &devpriv->divisor1,
-                                         &devpriv->divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               unsigned int arg = cmd->convert_arg;
+
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
        }
 
        if (err)
                return 4;
 
-
        /* step 5: complain about special chanlist considerations */
 
        if (cmd->chanlist) {
@@ -450,8 +423,6 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        if (devpriv->ai_cmd_running)
                return -EBUSY;
 
-       pcl816_start_pacer(dev, false);
-
        seglen = check_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len);
        if (seglen < 1)
                return -EINVAL;
@@ -466,7 +437,11 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        dma->cur_dma = 0;
        pcl816_ai_setup_dma(dev, s, 0);
 
-       pcl816_start_pacer(dev, true);
+       comedi_8254_set_mode(dev->pacer, 0, I8254_MODE1 | I8254_BINARY);
+       comedi_8254_write(dev->pacer, 0, 0x0ff);
+       udelay(1);
+       comedi_8254_update_divisors(dev->pacer);
+       comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
 
        ctrl = PCL816_CTRL_INTEN | PCL816_CTRL_DMAEN | PCL816_CTRL_DMASRC_SLOT0;
        if (cmd->convert_src == TRIG_TIMER)
@@ -525,11 +500,7 @@ static int pcl816_ai_cancel(struct comedi_device *dev,
        outb(PCL816_CTRL_DISABLE_TRIG, dev->iobase + PCL816_CTRL_REG);
        pcl816_ai_clear_eoc(dev);
 
-       /* Stop pacer */
-       i8254_set_mode(dev->iobase + PCL816_TIMER_BASE, 0,
-                       2, I8254_MODE0 | I8254_BINARY);
-       i8254_set_mode(dev->iobase + PCL816_TIMER_BASE, 0,
-                       1, I8254_MODE0 | I8254_BINARY);
+       comedi_8254_pacer_enable(dev->pacer, 1, 2, false);
 
        devpriv->ai_cmd_running = 0;
        devpriv->ai_cmd_canceled = 1;
@@ -596,17 +567,10 @@ static int pcl816_do_insn_bits(struct comedi_device *dev,
 
 static void pcl816_reset(struct comedi_device *dev)
 {
-       unsigned long timer_base = dev->iobase + PCL816_TIMER_BASE;
-
        outb(PCL816_CTRL_DISABLE_TRIG, dev->iobase + PCL816_CTRL_REG);
        pcl816_ai_set_chan_range(dev, 0, 0);
        pcl816_ai_clear_eoc(dev);
 
-       /* Stop pacer */
-       i8254_set_mode(timer_base, 0, 2, I8254_MODE0 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 1, I8254_MODE0 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 0, I8254_MODE0 | I8254_BINARY);
-
        /* set all digital outputs low */
        outb(0, dev->iobase + PCL816_DO_DI_LSB_REG);
        outb(0, dev->iobase + PCL816_DO_DI_MSB_REG);
@@ -662,6 +626,11 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        /* an IRQ and DMA are required to support async commands */
        pcl816_alloc_irq_and_dma(dev, it);
 
+       dev->pacer = comedi_8254_init(dev->iobase + PCL816_TIMER_BASE,
+                                     I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
                return ret;
index 7e4cdea5fe59f95f4f5285512a739b821421130d..e1bdde9773023466ab6624fefa190baf302e1b1f 100644 (file)
 #include "../comedidev.h"
 
 #include "comedi_isadma.h"
-#include "comedi_fc.h"
-#include "8253.h"
+#include "comedi_8254.h"
 
 /* boards constants */
 
@@ -299,33 +298,15 @@ struct pcl818_private {
        struct comedi_isadma *dma;
        /*  manimal allowed delay between samples (in us) for actual card */
        unsigned int ns_min;
-       int i8253_osc_base;     /*  1/frequency of on board oscilator in ns */
        /*  MUX setting for actual AI operations */
        unsigned int act_chanlist[16];
        unsigned int act_chanlist_len;  /*  how long is actual MUX list */
        unsigned int act_chanlist_pos;  /*  actual position in MUX list */
-       unsigned int divisor1;
-       unsigned int divisor2;
        unsigned int usefifo:1;
        unsigned int ai_cmd_running:1;
        unsigned int ai_cmd_canceled:1;
 };
 
-static void pcl818_start_pacer(struct comedi_device *dev, bool load_counters)
-{
-       struct pcl818_private *devpriv = dev->private;
-       unsigned long timer_base = dev->iobase + PCL818_TIMER_BASE;
-
-       i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
-       udelay(1);
-
-       if (load_counters) {
-               i8254_write(timer_base, 0, 2, devpriv->divisor2);
-               i8254_write(timer_base, 0, 1, devpriv->divisor1);
-       }
-}
-
 static void pcl818_ai_setup_dma(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                unsigned int unread_samples)
@@ -663,25 +644,24 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
                      struct comedi_cmd *cmd)
 {
        const struct pcl818_board *board = dev->board_ptr;
-       struct pcl818_private *devpriv = dev->private;
        int err = 0;
-       unsigned int arg;
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->convert_src,
+                                       TRIG_TIMER | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -690,21 +670,23 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
-       if (cmd->convert_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                board->ns_min);
-       else    /* TRIG_EXT */
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+       if (cmd->convert_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                   board->ns_min);
+       } else {        /* TRIG_EXT */
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       }
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -712,12 +694,10 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
        /* step 4: fix up any arguments */
 
        if (cmd->convert_src == TRIG_TIMER) {
-               arg = cmd->convert_arg;
-               i8253_cascade_ns_to_timer(devpriv->i8253_osc_base,
-                                         &devpriv->divisor1,
-                                         &devpriv->divisor2,
-                                         &arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               unsigned int arg = cmd->convert_arg;
+
+               comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
        }
 
        if (err)
@@ -746,8 +726,6 @@ static int pcl818_ai_cmd(struct comedi_device *dev,
        if (devpriv->ai_cmd_running)
                return -EBUSY;
 
-       pcl818_start_pacer(dev, false);
-
        seglen = check_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len);
        if (seglen < 1)
                return -EINVAL;
@@ -779,8 +757,10 @@ static int pcl818_ai_cmd(struct comedi_device *dev,
        }
        outb(ctrl, dev->iobase + PCL818_CTRL_REG);
 
-       if (cmd->convert_src == TRIG_TIMER)
-               pcl818_start_pacer(dev, true);
+       if (cmd->convert_src == TRIG_TIMER) {
+               comedi_8254_update_divisors(dev->pacer);
+               comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
+       }
 
        return 0;
 }
@@ -812,7 +792,7 @@ static int pcl818_ai_cancel(struct comedi_device *dev,
        }
 
        outb(PCL818_CTRL_DISABLE_TRIG, dev->iobase + PCL818_CTRL_REG);
-       pcl818_start_pacer(dev, false);
+       comedi_8254_pacer_enable(dev->pacer, 1, 2, false);
        pcl818_ai_clear_eoc(dev);
 
        if (devpriv->usefifo) { /*  FIFO shutdown */
@@ -906,7 +886,6 @@ static int pcl818_do_insn_bits(struct comedi_device *dev,
 static void pcl818_reset(struct comedi_device *dev)
 {
        const struct pcl818_board *board = dev->board_ptr;
-       unsigned long timer_base = dev->iobase + PCL818_TIMER_BASE;
        unsigned int chan;
 
        /* flush and disable the FIFO */
@@ -924,9 +903,6 @@ static void pcl818_reset(struct comedi_device *dev)
 
        /* stop pacer */
        outb(PCL818_CNTENABLE_PACER_ENA, dev->iobase + PCL818_CNTENABLE_REG);
-       i8254_set_mode(timer_base, 0, 2, I8254_MODE0 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 1, I8254_MODE0 | I8254_BINARY);
-       i8254_set_mode(timer_base, 0, 0, I8254_MODE0 | I8254_BINARY);
 
        /* set analog output channels to 0V */
        for (chan = 0; chan < board->n_aochan; chan++) {
@@ -1016,6 +992,7 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        const struct pcl818_board *board = dev->board_ptr;
        struct pcl818_private *devpriv;
        struct comedi_subdevice *s;
+       unsigned int osc_base;
        int ret;
 
        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
@@ -1043,6 +1020,25 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (dev->irq && board->has_dma)
                pcl818_alloc_dma(dev, it->options[2]);
 
+       /* use 1MHz or 10MHz oscilator */
+       if ((it->options[3] == 0) || (it->options[3] == 10))
+               osc_base = I8254_OSC_BASE_10MHZ;
+       else
+               osc_base = I8254_OSC_BASE_1MHZ;
+
+       dev->pacer = comedi_8254_init(dev->iobase + PCL818_TIMER_BASE,
+                                     osc_base, I8254_IO8, 0);
+       if (!dev->pacer)
+               return -ENOMEM;
+
+       /* max sampling speed */
+       devpriv->ns_min = board->ns_min;
+       if (!board->is_818) {
+               /* extended PCL718 to 100kHz DAC */
+               if ((it->options[6] == 1) || (it->options[6] == 100))
+                       devpriv->ns_min = 10000;
+       }
+
        ret = comedi_alloc_subdevices(dev, 4);
        if (ret)
                return ret;
@@ -1117,22 +1113,6 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        s->range_table  = &range_digital;
        s->insn_bits    = pcl818_do_insn_bits;
 
-       /* select 1/10MHz oscilator */
-       if ((it->options[3] == 0) || (it->options[3] == 10))
-               devpriv->i8253_osc_base = I8254_OSC_BASE_10MHZ;
-       else
-               devpriv->i8253_osc_base = I8254_OSC_BASE_1MHZ;
-
-       /* max sampling speed */
-       devpriv->ns_min = board->ns_min;
-
-       if (!board->is_818) {
-               if ((it->options[6] == 1) || (it->options[6] == 100)) {
-                       /* extended PCL718 to 100kHz DAC */
-                       devpriv->ns_min = 10000;
-               }
-       }
-
        pcl818_reset(dev);
 
        return 0;
index 2c0e7ecbf494c1b2cc6bc56f414e2cc85dbb8a04..10472e6dd002e1c03e4b3919de551829c4233480 100644 (file)
@@ -78,8 +78,6 @@
 
 #include "../comedidev.h"
 
-#include "comedi_fc.h"
-
 /*
  * Register I/O map
  */
@@ -483,19 +481,19 @@ static int pcmmio_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -504,15 +502,16 @@ static int pcmmio_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
index a1641d98181245eee97662f7f20d1054ac3df567..7ea813022ff6f86513f85fc7e8ca54bc5fe77c65 100644 (file)
@@ -77,8 +77,6 @@
 
 #include "../comedidev.h"
 
-#include "comedi_fc.h"
-
 /*
  * Register I/O map
  *
@@ -486,19 +484,19 @@ static int pcmuio_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -507,15 +505,16 @@ static int pcmuio_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -568,7 +567,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                } else if (it->options[2]) {
                        /* request the irq for the 2nd asic */
                        ret = request_irq(it->options[2], pcmuio_interrupt, 0,
-                                       dev->board_name, dev);
+                                         dev->board_name, dev);
                        if (ret == 0)
                                devpriv->irq2 = it->options[2];
                }
@@ -588,7 +587,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                s->insn_bits    = pcmuio_dio_insn_bits;
                s->insn_config  = pcmuio_dio_insn_config;
 
-               /* subdevices 0 and 2 can suppport interrupts */
+               /* subdevices 0 and 2 can support interrupts */
                if ((i == 0 && dev->irq) || (i == 2 && devpriv->irq2)) {
                        /* setup the interrupt subdevice */
                        dev->read_subdev = s;
index 8387fd0e4b7e12f09b553a3b16c7b219bd02fd76..152cb146fc161fa62cfdd9b194bf9d0cc7edb08a 100644 (file)
@@ -52,7 +52,6 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308
 #include <linux/completion.h>
 
 #include "../comedi_pcmcia.h"
-#include "comedi_fc.h"
 
 struct daqp_private {
        int stop;
@@ -315,7 +314,6 @@ static int daqp_ai_insn_read(struct comedi_device *dev,
        devpriv->interrupt_mode = semaphore;
 
        for (i = 0; i < insn->n; i++) {
-
                /* Start conversion */
                outb(DAQP_COMMAND_ARM | DAQP_COMMAND_FIFO_DATA,
                     dev->iobase + DAQP_COMMAND);
@@ -366,22 +364,22 @@ static int daqp_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_TIMER | TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->convert_src,
+       err |= comedi_check_trigger_src(&cmd->convert_src,
                                        TRIG_TIMER | TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -390,13 +388,14 @@ static int daqp_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
 #define MAX_SPEED      10000   /* 100 kHz - in nanoseconds */
 
-       if (cmd->scan_begin_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                MAX_SPEED);
+       if (cmd->scan_begin_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   MAX_SPEED);
+       }
 
        /* If both scan_begin and convert are both timer values, the only
         * way that can make sense is if the scan time is the number of
@@ -408,15 +407,18 @@ static int daqp_ai_cmdtest(struct comedi_device *dev,
                err |= -EINVAL;
        }
 
-       if (cmd->convert_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg, MAX_SPEED);
+       if (cmd->convert_src == TRIG_TIMER) {
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                   MAX_SPEED);
+       }
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
+               err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -426,13 +428,13 @@ static int daqp_ai_cmdtest(struct comedi_device *dev,
        if (cmd->scan_begin_src == TRIG_TIMER) {
                arg = cmd->scan_begin_arg;
                daqp_ns_to_timer(&arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
 
        if (cmd->convert_src == TRIG_TIMER) {
                arg = cmd->convert_arg;
                daqp_ns_to_timer(&arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
        }
 
        if (err)
index c94ad12ed446bea7250ccb4c0772076681406f4a..4c13f5eb0c842ec692dbfc580e6820fbeded8ca4 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
-#include "comedi_fc.h"
 #include "plx9080.h"
 
 /*
@@ -579,7 +577,7 @@ static int rtd_ai_rinsn(struct comedi_device *dev,
 
                /* read data */
                d = readw(devpriv->las1 + LAS1_ADC_FIFO);
-               d = d >> 3;     /* low 3 bits are marker lines */
+               d >>= 3;        /* low 3 bits are marker lines */
 
                /* convert bipolar data to comedi unsigned data */
                if (comedi_range_is_bipolar(s, range))
@@ -616,7 +614,7 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s,
                }
 
                d = readw(devpriv->las1 + LAS1_ADC_FIFO);
-               d = d >> 3;     /* low 3 bits are marker lines */
+               d >>= 3;        /* low 3 bits are marker lines */
 
                /* convert bipolar data to comedi unsigned data */
                if (comedi_range_is_bipolar(s, range))
@@ -734,21 +732,22 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->convert_src,
+                                       TRIG_TIMER | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -757,32 +756,32 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
                /* Note: these are time periods, not actual rates */
                if (1 == cmd->chanlist_len) {   /* no scanning */
-                       if (cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                     RTD_MAX_SPEED_1)) {
+                       if (comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                        RTD_MAX_SPEED_1)) {
                                rtd_ns_to_timer(&cmd->scan_begin_arg,
                                                CMDF_ROUND_UP);
                                err |= -EINVAL;
                        }
-                       if (cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
-                                                     RTD_MIN_SPEED_1)) {
+                       if (comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
+                                                        RTD_MIN_SPEED_1)) {
                                rtd_ns_to_timer(&cmd->scan_begin_arg,
                                                CMDF_ROUND_DOWN);
                                err |= -EINVAL;
                        }
                } else {
-                       if (cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                     RTD_MAX_SPEED)) {
+                       if (comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                        RTD_MAX_SPEED)) {
                                rtd_ns_to_timer(&cmd->scan_begin_arg,
                                                CMDF_ROUND_UP);
                                err |= -EINVAL;
                        }
-                       if (cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
-                                                     RTD_MIN_SPEED)) {
+                       if (comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
+                                                        RTD_MIN_SPEED)) {
                                rtd_ns_to_timer(&cmd->scan_begin_arg,
                                                CMDF_ROUND_DOWN);
                                err |= -EINVAL;
@@ -792,32 +791,32 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
                /* external trigger */
                /* should be level/edge, hi/lo specification here */
                /* should specify multiple external triggers */
-               err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9);
+               err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg, 9);
        }
 
        if (cmd->convert_src == TRIG_TIMER) {
                if (1 == cmd->chanlist_len) {   /* no scanning */
-                       if (cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                     RTD_MAX_SPEED_1)) {
+                       if (comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                        RTD_MAX_SPEED_1)) {
                                rtd_ns_to_timer(&cmd->convert_arg,
                                                CMDF_ROUND_UP);
                                err |= -EINVAL;
                        }
-                       if (cfc_check_trigger_arg_max(&cmd->convert_arg,
-                                                     RTD_MIN_SPEED_1)) {
+                       if (comedi_check_trigger_arg_max(&cmd->convert_arg,
+                                                        RTD_MIN_SPEED_1)) {
                                rtd_ns_to_timer(&cmd->convert_arg,
                                                CMDF_ROUND_DOWN);
                                err |= -EINVAL;
                        }
                } else {
-                       if (cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                     RTD_MAX_SPEED)) {
+                       if (comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                        RTD_MAX_SPEED)) {
                                rtd_ns_to_timer(&cmd->convert_arg,
                                                CMDF_ROUND_UP);
                                err |= -EINVAL;
                        }
-                       if (cfc_check_trigger_arg_max(&cmd->convert_arg,
-                                                     RTD_MIN_SPEED)) {
+                       if (comedi_check_trigger_arg_max(&cmd->convert_arg,
+                                                        RTD_MIN_SPEED)) {
                                rtd_ns_to_timer(&cmd->convert_arg,
                                                CMDF_ROUND_DOWN);
                                err |= -EINVAL;
@@ -826,37 +825,38 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
        } else {
                /* external trigger */
                /* see above */
-               err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 9);
+               err |= comedi_check_trigger_arg_max(&cmd->convert_arg, 9);
        }
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
 
-
        /* step 4: fix up any arguments */
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
                arg = cmd->scan_begin_arg;
                rtd_ns_to_timer(&arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
 
        if (cmd->convert_src == TRIG_TIMER) {
                arg = cmd->convert_arg;
                rtd_ns_to_timer(&arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
 
                if (cmd->scan_begin_src == TRIG_TIMER) {
                        arg = cmd->convert_arg * cmd->scan_end_arg;
-                       err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                        arg);
+                       err |= comedi_check_trigger_arg_min(&cmd->
+                                                           scan_begin_arg,
+                                                           arg);
                }
        }
 
@@ -1181,8 +1181,8 @@ static void rtd_pci_latency_quirk(struct comedi_device *dev,
        pci_read_config_byte(pcidev, PCI_LATENCY_TIMER, &pci_latency);
        if (pci_latency < 32) {
                dev_info(dev->class_dev,
-                       "PCI latency changed from %d to %d\n",
-                       pci_latency, 32);
+                        "PCI latency changed from %d to %d\n",
+                        pci_latency, 32);
                pci_write_config_byte(pcidev, PCI_LATENCY_TIMER, 32);
        }
 }
@@ -1299,12 +1299,8 @@ static void rtd_detach(struct comedi_device *dev)
                /* Shut down any board ops by resetting it */
                if (dev->mmio && devpriv->lcfg)
                        rtd_reset(dev);
-               if (dev->irq) {
-                       writel(readl(devpriv->lcfg + PLX_INTRCS_REG) &
-                               ~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E),
-                               devpriv->lcfg + PLX_INTRCS_REG);
+               if (dev->irq)
                        free_irq(dev->irq, dev);
-               }
                if (dev->mmio)
                        iounmap(dev->mmio);
                if (devpriv->las1)
index fc497dd920219553458c300f1624e7a07edc4379..781918d8d85f5452ad9d61fb28b2c95a9b4da13d 100644 (file)
 
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 
-#include "../comedidev.h"
+#include "../comedi_pci.h"
 
-#include "comedi_fc.h"
 #include "s626.h"
 
 struct s626_buffer_dma {
@@ -231,9 +229,9 @@ static void s626_debi_replace(struct comedi_device *dev, unsigned int addr,
 /* **************  EEPROM ACCESS FUNCTIONS  ************** */
 
 static int s626_i2c_handshake_eoc(struct comedi_device *dev,
-                                struct comedi_subdevice *s,
-                                struct comedi_insn *insn,
-                                unsigned long context)
+                                 struct comedi_subdevice *s,
+                                 struct comedi_insn *insn,
+                                 unsigned long context)
 {
        bool status;
 
@@ -294,7 +292,7 @@ static uint8_t s626_i2c_read(struct comedi_device *dev, uint8_t addr)
         *  Byte0 = Not sent.
         */
        if (s626_i2c_handshake(dev, S626_I2C_B2(S626_I2C_ATTRSTART,
-                                          (devpriv->i2c_adrs | 1)) |
+                                               (devpriv->i2c_adrs | 1)) |
                                    S626_I2C_B1(S626_I2C_ATTRSTOP, 0) |
                                    S626_I2C_B0(S626_I2C_ATTRNOP, 0)))
                /* Abort function and declare error if handshake failed. */
@@ -517,8 +515,8 @@ static int s626_send_dac(struct comedi_device *dev, uint32_t val)
 /*
  * Private helper function: Write setpoint to an application DAC channel.
  */
-static int s626_set_dac(struct comedi_device *dev, uint16_t chan,
-                        int16_t dacdata)
+static int s626_set_dac(struct comedi_device *dev,
+                       uint16_t chan, int16_t dacdata)
 {
        struct s626_private *devpriv = dev->private;
        uint16_t signmask;
@@ -583,8 +581,8 @@ static int s626_set_dac(struct comedi_device *dev, uint16_t chan,
        return s626_send_dac(dev, val);
 }
 
-static int s626_write_trim_dac(struct comedi_device *dev, uint8_t logical_chan,
-                               uint8_t dac_data)
+static int s626_write_trim_dac(struct comedi_device *dev,
+                              uint8_t logical_chan, uint8_t dac_data)
 {
        struct s626_private *devpriv = dev->private;
        uint32_t chan;
@@ -641,7 +639,7 @@ static int s626_load_trim_dacs(struct comedi_device *dev)
        /* Copy TrimDac setpoint values from EEPROM to TrimDacs. */
        for (i = 0; i < ARRAY_SIZE(s626_trimchan); i++) {
                ret = s626_write_trim_dac(dev, i,
-                                   s626_i2c_read(dev, s626_trimadrs[i]));
+                                         s626_i2c_read(dev, s626_trimadrs[i]));
                if (ret)
                        return ret;
        }
@@ -1576,7 +1574,7 @@ static void s626_reset_adc(struct comedi_device *dev, uint8_t *ppl)
               dev->mmio + S626_P_RPSADDR1);
 
        /* Construct RPS program in rps_buf DMA buffer */
-       if (cmd != NULL && cmd->scan_begin_src != TRIG_FOLLOW) {
+       if (cmd->scan_begin_src != TRIG_FOLLOW) {
                /* Wait for Start trigger. */
                *rps++ = S626_RPS_PAUSE | S626_RPS_SIGADC;
                *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_SIGADC;
@@ -1665,7 +1663,7 @@ static void s626_reset_adc(struct comedi_device *dev, uint8_t *ppl)
                        *rps++ = jmp_adrs;
                }
 
-               if (cmd != NULL && cmd->convert_src != TRIG_NOW) {
+               if (cmd->convert_src != TRIG_NOW) {
                        /* Wait for Start trigger. */
                        *rps++ = S626_RPS_PAUSE | S626_RPS_SIGADC;
                        *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_SIGADC;
@@ -2034,10 +2032,6 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        /* reset ai_cmd_running flag */
        devpriv->ai_cmd_running = 0;
 
-       /* test if cmd is valid */
-       if (cmd == NULL)
-               return -EINVAL;
-
        s626_ai_load_polllist(ppl, cmd);
        devpriv->ai_cmd_running = 1;
        devpriv->ai_convert_count = 0;
@@ -2120,24 +2114,24 @@ static int s626_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src,
-                                    TRIG_NOW | TRIG_INT | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
-                                    TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW);
-       err |= cfc_check_trigger_src(&cmd->convert_src,
-                                    TRIG_TIMER | TRIG_EXT | TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src,
+                                       TRIG_NOW | TRIG_INT | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
+                                       TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW);
+       err |= comedi_check_trigger_src(&cmd->convert_src,
+                                       TRIG_TIMER | TRIG_EXT | 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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -2149,49 +2143,53 @@ static int s626_ai_cmdtest(struct comedi_device *dev,
        switch (cmd->start_src) {
        case TRIG_NOW:
        case TRIG_INT:
-               err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
                break;
        case TRIG_EXT:
-               err |= cfc_check_trigger_arg_max(&cmd->start_arg, 39);
+               err |= comedi_check_trigger_arg_max(&cmd->start_arg, 39);
                break;
        }
 
        if (cmd->scan_begin_src == TRIG_EXT)
-               err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 39);
+               err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg, 39);
        if (cmd->convert_src == TRIG_EXT)
-               err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 39);
+               err |= comedi_check_trigger_arg_max(&cmd->convert_arg, 39);
 
 #define S626_MAX_SPEED 200000  /* in nanoseconds */
 #define S626_MIN_SPEED 2000000000      /* in nanoseconds */
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                S626_MAX_SPEED);
-               err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
-                                                S626_MIN_SPEED);
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   S626_MAX_SPEED);
+               err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
+                                                   S626_MIN_SPEED);
        } else {
-               /* external trigger */
-               /* should be level/edge, hi/lo specification here */
-               /* should specify multiple external triggers */
-               /* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */
+               /*
+                * external trigger
+                * should be level/edge, hi/lo specification here
+                * should specify multiple external triggers
+                * err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg, 9);
+                */
        }
        if (cmd->convert_src == TRIG_TIMER) {
-               err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
-                                                S626_MAX_SPEED);
-               err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
-                                                S626_MIN_SPEED);
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
+                                                   S626_MAX_SPEED);
+               err |= comedi_check_trigger_arg_max(&cmd->convert_arg,
+                                                   S626_MIN_SPEED);
        } else {
-               /* external trigger */
-               /* see above */
-               /* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */
+               /*
+                * external trigger - see above
+                * err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg, 9);
+                */
        }
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -2201,18 +2199,19 @@ static int s626_ai_cmdtest(struct comedi_device *dev,
        if (cmd->scan_begin_src == TRIG_TIMER) {
                arg = cmd->scan_begin_arg;
                s626_ns_to_timer(&arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
        }
 
        if (cmd->convert_src == TRIG_TIMER) {
                arg = cmd->convert_arg;
                s626_ns_to_timer(&arg, cmd->flags);
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
 
                if (cmd->scan_begin_src == TRIG_TIMER) {
                        arg = cmd->convert_arg * cmd->scan_end_arg;
-                       err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                        arg);
+                       err |= comedi_check_trigger_arg_min(&cmd->
+                                                           scan_begin_arg,
+                                                           arg);
                }
        }
 
@@ -2733,7 +2732,7 @@ static int s626_initialize(struct comedi_device *dev)
 }
 
 static int s626_auto_attach(struct comedi_device *dev,
-                                     unsigned long context_unused)
+                           unsigned long context_unused)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        struct s626_private *devpriv;
index 71226ee9064efc4c829a6b8804ac620df61551ac..ad35ed6e93f0a26554348922ee02f04e758f6f04 100644 (file)
@@ -39,14 +39,12 @@ Status: in development
 #include <linux/poll.h>
 
 struct serial2002_range_table_t {
-
        /*  HACK... */
        int length;
        struct comedi_krange range;
 };
 
 struct serial2002_private {
-
        int port;               /*  /dev/ttyS<port> */
        int speed;              /*  baudrate */
        struct file *tty;
@@ -145,8 +143,8 @@ static void serial2002_tty_read_poll_wait(struct file *f, int timeout)
                        break;
                }
                do_gettimeofday(&now);
-               elapsed = (1000000 * (now.tv_sec - start.tv_sec) +
-                         now.tv_usec - start.tv_usec);
+               elapsed = 1000000 * (now.tv_sec - start.tv_sec) +
+                         now.tv_usec - start.tv_usec;
                if (elapsed > timeout)
                        break;
                set_current_state(TASK_INTERRUPTIBLE);
@@ -300,7 +298,6 @@ static struct serial_data serial2002_read(struct file *f, int timeout)
                }
        }
        return result;
-
 }
 
 static void serial2002_write(struct file *f, struct serial_data data)
index 848c3080158073a2ff1a263f5747f45f0b9bc4f2..acc7f3445c583e426253138f7fba68e36e9c7b98 100644 (file)
@@ -127,7 +127,6 @@ static int dnp_dio_insn_config(struct comedi_device *dev,
        outb(val, CSCDR);
 
        return insn->n;
-
 }
 
 static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
index 7c2276a086ac8c3e2d8a2fa4caa0f92142226453..51498b889c6c178fc7e5f63e46952abe7d770445 100644 (file)
@@ -38,7 +38,6 @@ Devices: [Fastwel] UNIOxx-5 (unioxx5),
 
 */
 
-
 #include <linux/module.h>
 #include <linux/delay.h>
 #include "../comedidev.h"
@@ -81,7 +80,6 @@ struct unioxx5_subd_priv {
 
 static int __unioxx5_define_chan_offset(int chan_num)
 {
-
        if (chan_num < 0 || chan_num > 23)
                return -1;
 
@@ -266,7 +264,7 @@ static int __unioxx5_analog_write(struct comedi_subdevice *s,
        /* sending for bytes to module(one byte per cycle iteration) */
        for (i = 0; i < 4; i++) {
                while (!((inb(usp->usp_iobase + 0)) & TxBE))
-                       ;       /* waits while writting will be allowed */
+                       ;       /* waits while writing will be allowed */
                outb(usp->usp_extra_data[module][i], usp->usp_iobase + 6);
        }
 
@@ -399,7 +397,7 @@ static int __unioxx5_subdev_init(struct comedi_device *dev,
                outb(i + 1, iobase + 5);
                outb('H', iobase + 6);  /* requests EEPROM world */
                while (!(inb(iobase + 0) & TxBE))
-                       ;       /* waits while writting will be allowed */
+                       ;       /* waits while writing will be allowed */
                outb(0, iobase + 6);
 
                /* waits while reading of two bytes will be allowed */
@@ -413,8 +411,9 @@ static int __unioxx5_subdev_init(struct comedi_device *dev,
                if (ndef_flag) {
                        usp->usp_module_type[i] = 0;
                        ndef_flag = 0;
-               } else
+               } else {
                        usp->usp_module_type[i] = inb(iobase + 6);
+               }
 
                udelay(1);
        }
index 1cd7403a4e9c741a0cb7137cdec134579924c343..ced05e581620997646d021005f7cf8629f2131c9 100644 (file)
@@ -85,8 +85,6 @@
 
 #include "../comedi_usb.h"
 
-#include "comedi_fc.h"
-
 /* constants for firmware upload and download */
 #define USBDUX_FIRMWARE                "usbdux_firmware.bin"
 #define USBDUX_FIRMWARE_MAX_LEN        0x2000
@@ -524,19 +522,19 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -545,10 +543,10 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
                if (this_usbduxsub->high_speed) {
@@ -563,8 +561,9 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
                        while (i < (cmd->chanlist_len))
                                i = i * 2;
 
-                       err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                        1000000 / 8 * i);
+                       err |= comedi_check_trigger_arg_min(&cmd->
+                                                           scan_begin_arg,
+                                                           1000000 / 8 * i);
                        /* now calc the real sampling rate with all the
                         * rounding errors */
                        tmp_timer =
@@ -573,24 +572,26 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
                } else {
                        /* full speed */
                        /* 1kHz scans every USB frame */
-                       err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                        1000000);
+                       err |= comedi_check_trigger_arg_min(&cmd->
+                                                           scan_begin_arg,
+                                                           1000000);
                        /*
                         * calc the real sampling rate with the rounding errors
                         */
                        tmp_timer = ((unsigned int)(cmd->scan_begin_arg /
                                                   1000000)) * 1000000;
                }
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg,
-                                               tmp_timer);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg,
+                                                  tmp_timer);
        }
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -633,8 +634,8 @@ static int receive_dux_commands(struct comedi_device *dev, unsigned int command)
 
        for (i = 0; i < RETRIES; i++) {
                ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, 8),
-                                     devpriv->insn_buf, SIZEINSNBUF,
-                                     &nrec, BULK_TIMEOUT);
+                                  devpriv->insn_buf, SIZEINSNBUF,
+                                  &nrec, BULK_TIMEOUT);
                if (ret < 0)
                        return ret;
                if (le16_to_cpu(devpriv->insn_buf[0]) == command)
@@ -895,7 +896,7 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 
        if (0) {                /* (this_usbduxsub->high_speed) */
                /* the sampling rate is set by the coversion rate */
@@ -904,7 +905,7 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
                /* start a new scan (output at once) with a timer */
                flags = TRIG_TIMER;
        }
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, flags);
 
        if (0) {                /* (this_usbduxsub->high_speed) */
                /*
@@ -919,18 +920,18 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
                 */
                flags = TRIG_NOW;
        }
-       err |= cfc_check_trigger_src(&cmd->convert_src, flags);
+       err |= comedi_check_trigger_src(&cmd->convert_src, flags);
 
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -939,25 +940,27 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
-       if (cmd->scan_begin_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                1000000);
+       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 |= cfc_check_trigger_arg_min(&cmd->convert_arg, 125000);
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 125000);
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -1041,7 +1044,6 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev,
                                struct comedi_insn *insn,
                                unsigned int *data)
 {
-
        struct usbdux_private *devpriv = dev->private;
        int ret;
 
index 7ce27c16c2f99e107265dee703d027e0ba11e9bc..d90dc59982be6e146d412ac07fa369fcc42f9de1 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/input.h>
 #include <linux/fcntl.h>
 #include <linux/compiler.h>
-#include "comedi_fc.h"
 #include "../comedi_usb.h"
 
 /*
@@ -343,23 +342,24 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src,
+       err |= comedi_check_trigger_src(&cmd->start_src,
                                        TRIG_NOW | TRIG_EXT | TRIG_INT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src,
                                        TRIG_FOLLOW | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->convert_src,
+                                       TRIG_TIMER | TRIG_EXT);
+       err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-       err |= cfc_check_trigger_is_unique(cmd->convert_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
+       err |= comedi_check_trigger_is_unique(cmd->convert_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -372,12 +372,13 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (!cmd->chanlist_len)
                err |= -EINVAL;
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->chanlist_len == 1)
                min_sample_period = 1;
@@ -394,16 +395,16 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
 
                /* calc arg again */
                tmp = steps / 30;
-               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, tmp);
+               err |= comedi_check_trigger_arg_is(&cmd->convert_arg, tmp);
        }
 
        /* stop source */
        switch (cmd->stop_src) {
        case TRIG_COUNT:
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
                break;
        case TRIG_NONE:
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
                break;
                /*
                 * TRIG_EXT doesn't care since it doesn't trigger
@@ -419,7 +420,6 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
        /* step 4: fix up any arguments */
 
        return 0;
-
 }
 
 static int usbduxfast_ai_inttrig(struct comedi_device *dev,
index 394969b7458c19df240d52cb1ad83bd2b61e1c7b..eaa9add491df7cbade63ee3786f36540aac71606 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/compiler.h>
 #include <asm/unaligned.h>
 
-#include "comedi_fc.h"
 #include "../comedi_usb.h"
 
 /* timeout for the USB-transfer in ms*/
@@ -243,9 +242,8 @@ static void usbduxsigma_ai_handle_urb(struct comedi_device *dev,
                urb->dev = comedi_to_usb_dev(dev);
                ret = usb_submit_urb(urb, GFP_ATOMIC);
                if (ret < 0) {
-                       dev_err(dev->class_dev,
-                               "%s: urb resubmit failed (%d)\n",
-                               __func__, ret);
+                       dev_err(dev->class_dev, "urb resubmit failed (%d)\n",
+                               ret);
                        if (ret == -EL2NSYNC)
                                dev_err(dev->class_dev,
                                        "buggy USB host controller or bug in IRQ handler\n");
@@ -292,8 +290,8 @@ static void usbduxsigma_ai_urb_complete(struct urb *urb)
 
        default:
                /* a real error */
-               dev_err(dev->class_dev, "%s: non-zero urb status (%d)\n",
-                       __func__, urb->status);
+               dev_err(dev->class_dev, "non-zero urb status (%d)\n",
+                       urb->status);
                async->events |= COMEDI_CB_ERROR;
                break;
        }
@@ -386,9 +384,8 @@ static void usbduxsigma_ao_handle_urb(struct comedi_device *dev,
                urb->iso_frame_desc[0].status = 0;
                ret = usb_submit_urb(urb, GFP_ATOMIC);
                if (ret < 0) {
-                       dev_err(dev->class_dev,
-                               "%s: urb resubmit failed (%d)\n",
-                               __func__, ret);
+                       dev_err(dev->class_dev, "urb resubmit failed (%d)\n",
+                               ret);
                        if (ret == -EL2NSYNC)
                                dev_err(dev->class_dev,
                                        "buggy USB host controller or bug in IRQ handler\n");
@@ -423,8 +420,8 @@ static void usbduxsigma_ao_urb_complete(struct urb *urb)
 
        default:
                /* a real error */
-               dev_err(dev->class_dev, "%s: non-zero urb status (%d)\n",
-                       __func__, urb->status);
+               dev_err(dev->class_dev, "non-zero urb status (%d)\n",
+                       urb->status);
                async->events |= COMEDI_CB_ERROR;
                break;
        }
@@ -488,19 +485,19 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+       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);
 
        if (err)
                return 1;
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -509,10 +506,10 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
                unsigned int tmp;
@@ -524,27 +521,31 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev,
                         * sample two channels. Thus, the more channels
                         * are in the channel list the more time we need.
                         */
-                       err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                               (1000000 / 8 * interval));
+                       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 |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                        1000000);
+                       err |= comedi_check_trigger_arg_min(&cmd->
+                                                           scan_begin_arg,
+                                                           1000000);
 
                        tmp = (cmd->scan_begin_arg / 1000000) * 1000000;
                }
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
        }
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -856,7 +857,7 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev,
 
        /* Step 1 : check if triggers are trivially valid */
 
-       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
+       err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 
        if (high_speed) {
                /*
@@ -868,11 +869,11 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev,
                /* start a new scan (output at once) with a timer */
                flags = TRIG_TIMER;
        }
-       err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, flags);
 
-       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
-       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       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);
 
        if (err) {
                up(&devpriv->sem);
@@ -881,8 +882,8 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev,
 
        /* Step 2a : make sure trigger sources are unique */
 
-       err |= cfc_check_trigger_is_unique(cmd->start_src);
-       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+       err |= comedi_check_trigger_is_unique(cmd->start_src);
+       err |= comedi_check_trigger_is_unique(cmd->stop_src);
 
        /* Step 2b : and mutually compatible */
 
@@ -891,25 +892,27 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev,
 
        /* Step 3: check if arguments are trivially valid */
 
-       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
-               err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
-       if (cmd->scan_begin_src == TRIG_TIMER)
-               err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                1000000);
+       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 |= cfc_check_trigger_arg_min(&cmd->convert_arg, 125000);
+               err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 125000);
 
-       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
+                                          cmd->chanlist_len);
 
        if (cmd->stop_src == TRIG_COUNT)
-               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+               err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
        else    /* TRIG_NONE */
-               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+               err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 
        if (err)
                return 3;
@@ -1071,9 +1074,8 @@ static void usbduxsigma_pwm_urb_complete(struct urb *urb)
        default:
                /* a real error */
                if (devpriv->pwm_cmd_running) {
-                       dev_err(dev->class_dev,
-                               "%s: non-zero urb status (%d)\n",
-                               __func__, urb->status);
+                       dev_err(dev->class_dev, "non-zero urb status (%d)\n",
+                               urb->status);
                        usbduxsigma_pwm_stop(dev, 0);   /* w/o unlink */
                }
                return;
@@ -1087,8 +1089,7 @@ static void usbduxsigma_pwm_urb_complete(struct urb *urb)
        urb->status = 0;
        ret = usb_submit_urb(urb, GFP_ATOMIC);
        if (ret < 0) {
-               dev_err(dev->class_dev, "%s: urb resubmit failed (%d)\n",
-                       __func__, ret);
+               dev_err(dev->class_dev, "urb resubmit failed (%d)\n", ret);
                if (ret == -EL2NSYNC)
                        dev_err(dev->class_dev,
                                "buggy USB host controller or bug in IRQ handler\n");
index 973f544e85e1aaa5f457c7fe79735d2feae50189..76bf5619fdd522f121793b994331236268298c0b 100644 (file)
@@ -58,7 +58,7 @@ struct comedi_device *comedi_open(const char *filename)
                retval = NULL;
        up_read(&dev->attach_lock);
 
-       if (retval == NULL)
+       if (!retval)
                comedi_dev_put(dev);
 
        return retval;
index 7184747e0652ca39799a1b104888a4205297db38..6766d5a91a90805329b60efed81ccc0e64e5af02 100644 (file)
@@ -1361,7 +1361,6 @@ static uint dgap_get_custom_baud(struct channel_t *ch)
 {
        u8 __iomem *vaddr;
        ulong offset;
-       uint value;
 
        if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
                return 0;
@@ -1384,8 +1383,7 @@ static uint dgap_get_custom_baud(struct channel_t *ch)
        offset = (ioread16(vaddr + ECS_SEG) << 4) + (ch->ch_portnum * 0x28)
               + LINE_SPEED;
 
-       value = readw(vaddr + offset);
-       return value;
+       return readw(vaddr + offset);
 }
 
 /*
@@ -2196,7 +2194,7 @@ static struct board_t *dgap_found_board(struct pci_dev *pdev, int id,
         * will be mapped into the low 2MB of the 4MB memory space
         */
        brd->port = brd->membase + PCI_IO_OFFSET;
-       brd->port_end = brd->port + PCI_IO_SIZE;
+       brd->port_end = brd->port + PCI_IO_SIZE_DGAP;
 
        /*
         * Special initialization for non-PLX boards
@@ -3979,7 +3977,6 @@ static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value)
        int result;
        u8 mstat;
        ulong lock_flags;
-       int rc;
 
        spin_lock_irqsave(&ch->ch_lock, lock_flags);
 
@@ -4004,9 +4001,7 @@ static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value)
        if (mstat & D_CD(ch))
                result |= TIOCM_CD;
 
-       rc = put_user(result, value);
-
-       return rc;
+       return put_user(result, value);
 }
 
 /*
@@ -7044,8 +7039,7 @@ static int dgap_start(void)
 
        /* Start the poller */
        spin_lock_irqsave(&dgap_poll_lock, flags);
-       init_timer(&dgap_poll_timer);
-       dgap_poll_timer.function = dgap_poll_handler;
+       setup_timer(&dgap_poll_timer, dgap_poll_handler, 0);
        dgap_poll_timer.data = 0;
        dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick);
        dgap_poll_timer.expires = dgap_poll_time;
index 684033156e8c3f9a9db6c0563bcddbf6e7d08d0a..a2e5b26c673ad151361a8f8820f66022d577cdf4 100644 (file)
 #define PCI_IO_OFFSET          0x00200000
 
 /* Size of IO (2MB) */
-#define PCI_IO_SIZE            0x00200000
+#define PCI_IO_SIZE_DGAP       0x00200000
 
 /* Number of boards we support at once. */
 #define        MAXBOARDS       32
index b69f7b6b11430d74716327ac80506bac2c967623..995c874f40eb138ce0af15eb6c97acd2e5730707 100644 (file)
@@ -1,5 +1,3 @@
-EXTRA_CFLAGS += -DDG_NAME=\"dgnc-1.3-16\" -DDG_PART=\"40002369_F\"
-
 obj-$(CONFIG_DGNC) += dgnc.o
 
 dgnc-objs :=   dgnc_cls.o dgnc_driver.o\
index 22adff1078f39acaeee86157e702970bed67190e..2b2c6ea03c615e19bb04b7128cfbae6a715c496f 100644 (file)
@@ -1,10 +1,10 @@
 * checkpatch fixes
 * remove unecessary comments
-* remove unecessary error messages. Example kzalloc() has its 
+* remove unecessary error messages. Example kzalloc() has its
   own error message. Adding an extra one is useless.
 * use goto statements for error handling when appropriate
-* there is a lot of unecessary code in the driver. It was 
+* there is a lot of unecessary code in the driver. It was
   originally a standalone driver. Remove uneeded code.
 
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and 
+Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
 Cc: Lidza Louina <lidza.louina@gmail.com>
index bedc5221b6fc6e73279f15171dec8d63de53bbf4..e3564d278d917d71613bce0d85fd999768c42590 100644 (file)
  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *     NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *     This is shared code between Digi's CVS archive and the
- *     Linux Kernel sources.
- *     Changing the source just for reformatting needlessly breaks
- *     our CVS diff history.
- *
- *     Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *     Thank you.
- *
  */
 
 #include <linux/kernel.h>
@@ -92,14 +76,12 @@ struct board_ops dgnc_cls_ops = {
        .send_immediate_char =          cls_send_immediate_char
 };
 
-
 static inline void cls_set_cts_flow_control(struct channel_t *ch)
 {
        unsigned char lcrb = readb(&ch->ch_cls_uart->lcr);
        unsigned char ier = readb(&ch->ch_cls_uart->ier);
        unsigned char isr_fcr = 0;
 
-
        /*
         * The Enhanced Register Set may only be accessed when
         * the Line Control Register is set to 0xBFh.
@@ -136,14 +118,12 @@ static inline void cls_set_cts_flow_control(struct channel_t *ch)
 
 }
 
-
 static inline void cls_set_ixon_flow_control(struct channel_t *ch)
 {
        unsigned char lcrb = readb(&ch->ch_cls_uart->lcr);
        unsigned char ier = readb(&ch->ch_cls_uart->ier);
        unsigned char isr_fcr = 0;
 
-
        /*
         * The Enhanced Register Set may only be accessed when
         * the Line Control Register is set to 0xBFh.
@@ -184,14 +164,12 @@ static inline void cls_set_ixon_flow_control(struct channel_t *ch)
 
 }
 
-
 static inline void cls_set_no_output_flow_control(struct channel_t *ch)
 {
        unsigned char lcrb = readb(&ch->ch_cls_uart->lcr);
        unsigned char ier = readb(&ch->ch_cls_uart->ier);
        unsigned char isr_fcr = 0;
 
-
        /*
         * The Enhanced Register Set may only be accessed when
         * the Line Control Register is set to 0xBFh.
@@ -230,14 +208,12 @@ static inline void cls_set_no_output_flow_control(struct channel_t *ch)
 
 }
 
-
 static inline void cls_set_rts_flow_control(struct channel_t *ch)
 {
        unsigned char lcrb = readb(&ch->ch_cls_uart->lcr);
        unsigned char ier = readb(&ch->ch_cls_uart->ier);
        unsigned char isr_fcr = 0;
 
-
        /*
         * The Enhanced Register Set may only be accessed when
         * the Line Control Register is set to 0xBFh.
@@ -266,20 +242,17 @@ static inline void cls_set_rts_flow_control(struct channel_t *ch)
                UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
                &ch->ch_cls_uart->isr_fcr);
 
-
        ch->ch_r_watermark = 4;
        ch->ch_r_tlevel = 8;
 
 }
 
-
 static inline void cls_set_ixoff_flow_control(struct channel_t *ch)
 {
        unsigned char lcrb = readb(&ch->ch_cls_uart->lcr);
        unsigned char ier = readb(&ch->ch_cls_uart->ier);
        unsigned char isr_fcr = 0;
 
-
        /*
         * The Enhanced Register Set may only be accessed when
         * the Line Control Register is set to 0xBFh.
@@ -316,14 +289,12 @@ static inline void cls_set_ixoff_flow_control(struct channel_t *ch)
 
 }
 
-
 static inline void cls_set_no_input_flow_control(struct channel_t *ch)
 {
        unsigned char lcrb = readb(&ch->ch_cls_uart->lcr);
        unsigned char ier = readb(&ch->ch_cls_uart->ier);
        unsigned char isr_fcr = 0;
 
-
        /*
         * The Enhanced Register Set may only be accessed when
         * the Line Control Register is set to 0xBFh.
@@ -357,7 +328,6 @@ static inline void cls_set_no_input_flow_control(struct channel_t *ch)
 
 }
 
-
 /*
  * cls_clear_break.
  * Determines whether its time to shut off break condition.
@@ -393,7 +363,6 @@ static inline void cls_clear_break(struct channel_t *ch, int force)
        spin_unlock_irqrestore(&ch->ch_lock, flags);
 }
 
-
 /* Parse the ISR register for the specific port */
 static inline void cls_parse_isr(struct dgnc_board *brd, uint port)
 {
@@ -406,7 +375,7 @@ static inline void cls_parse_isr(struct dgnc_board *brd, uint port)
         * verified in the interrupt routine.
         */
 
-       if (port > brd->nasync)
+       if (port >= brd->nasync)
                return;
 
        ch = brd->channels[port];
@@ -457,7 +426,6 @@ static inline void cls_parse_isr(struct dgnc_board *brd, uint port)
        }
 }
 
-
 /*
  * cls_param()
  * Send any/all changes to the line to the UART.
@@ -711,7 +679,6 @@ static void cls_param(struct tty_struct *tty)
        cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr));
 }
 
-
 /*
  * Our board poller function.
  */
@@ -784,7 +751,6 @@ static void cls_tasklet(unsigned long data)
 
 }
 
-
 /*
  * cls_intr()
  *
@@ -834,7 +800,6 @@ static irqreturn_t cls_intr(int irq, void *voidbrd)
        return IRQ_HANDLED;
 }
 
-
 static void cls_disable_receiver(struct channel_t *ch)
 {
        unsigned char tmp = readb(&ch->ch_cls_uart->ier);
@@ -843,7 +808,6 @@ static void cls_disable_receiver(struct channel_t *ch)
        writeb(tmp, &ch->ch_cls_uart->ier);
 }
 
-
 static void cls_enable_receiver(struct channel_t *ch)
 {
        unsigned char tmp = readb(&ch->ch_cls_uart->ier);
@@ -852,7 +816,6 @@ static void cls_enable_receiver(struct channel_t *ch)
        writeb(tmp, &ch->ch_cls_uart->ier);
 }
 
-
 static void cls_copy_data_from_uart_to_queue(struct channel_t *ch)
 {
        int qleft = 0;
@@ -942,7 +905,6 @@ static void cls_copy_data_from_uart_to_queue(struct channel_t *ch)
        spin_unlock_irqrestore(&ch->ch_lock, flags);
 }
 
-
 /*
  * This function basically goes to sleep for secs, or until
  * it gets signalled that the port has fully drained.
@@ -978,7 +940,6 @@ static int cls_drain(struct tty_struct *tty, uint seconds)
                                         ((un->un_flags & UN_EMPTY) == 0));
 }
 
-
 /* Channel lock MUST be held before calling this function! */
 static void cls_flush_uart_write(struct channel_t *ch)
 {
@@ -992,7 +953,6 @@ static void cls_flush_uart_write(struct channel_t *ch)
        ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
 }
 
-
 /* Channel lock MUST be held before calling this function! */
 static void cls_flush_uart_read(struct channel_t *ch)
 {
@@ -1013,7 +973,6 @@ static void cls_flush_uart_read(struct channel_t *ch)
        udelay(10);
 }
 
-
 static void cls_copy_data_from_queue_to_uart(struct channel_t *ch)
 {
        ushort head;
@@ -1029,22 +988,16 @@ static void cls_copy_data_from_queue_to_uart(struct channel_t *ch)
        spin_lock_irqsave(&ch->ch_lock, flags);
 
        /* No data to write to the UART */
-       if (ch->ch_w_tail == ch->ch_w_head) {
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-               return;
-       }
+       if (ch->ch_w_tail == ch->ch_w_head)
+               goto exit_unlock;
 
        /* If port is "stopped", don't send any data to the UART */
        if ((ch->ch_flags & CH_FORCED_STOP) ||
-                                (ch->ch_flags & CH_BREAK_SENDING)) {
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-               return;
-       }
+                                (ch->ch_flags & CH_BREAK_SENDING))
+               goto exit_unlock;
 
-       if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM))) {
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-               return;
-       }
+       if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM)))
+               goto exit_unlock;
 
        n = 32;
 
@@ -1094,10 +1047,10 @@ static void cls_copy_data_from_queue_to_uart(struct channel_t *ch)
        if (len_written > 0)
                ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
 
+exit_unlock:
        spin_unlock_irqrestore(&ch->ch_lock, flags);
 }
 
-
 static void cls_parse_modem(struct channel_t *ch, unsigned char signals)
 {
        unsigned char msignals = signals;
@@ -1162,7 +1115,6 @@ static void cls_parse_modem(struct channel_t *ch, unsigned char signals)
        spin_unlock_irqrestore(&ch->ch_lock, flags);
 }
 
-
 /* Make the UART raise any of the output signals we want up */
 static void cls_assert_modem_signals(struct channel_t *ch)
 {
@@ -1182,7 +1134,6 @@ static void cls_assert_modem_signals(struct channel_t *ch)
        udelay(10);
 }
 
-
 static void cls_send_start_character(struct channel_t *ch)
 {
        if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
@@ -1194,7 +1145,6 @@ static void cls_send_start_character(struct channel_t *ch)
        }
 }
 
-
 static void cls_send_stop_character(struct channel_t *ch)
 {
        if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
@@ -1206,7 +1156,6 @@ static void cls_send_stop_character(struct channel_t *ch)
        }
 }
 
-
 /* Inits UART */
 static void cls_uart_init(struct channel_t *ch)
 {
@@ -1244,7 +1193,6 @@ static void cls_uart_init(struct channel_t *ch)
        readb(&ch->ch_cls_uart->msr);
 }
 
-
 /*
  * Turns off UART.
  */
@@ -1253,7 +1201,6 @@ static void cls_uart_off(struct channel_t *ch)
        writeb(0, &ch->ch_cls_uart->ier);
 }
 
-
 /*
  * cls_get_uarts_bytes_left.
  * Returns 0 is nothing left in the FIFO, returns 1 otherwise.
@@ -1283,7 +1230,6 @@ static uint cls_get_uart_bytes_left(struct channel_t *ch)
        return left;
 }
 
-
 /*
  * cls_send_break.
  * Starts sending a break thru the UART.
@@ -1326,7 +1272,6 @@ static void cls_send_break(struct channel_t *ch, int msecs)
        }
 }
 
-
 /*
  * cls_send_immediate_char.
  * Sends a specific character as soon as possible to the UART,
@@ -1348,7 +1293,6 @@ static void cls_vpd(struct dgnc_board *brd)
        u8 __iomem           *re_map_vpdbase;/* Remapped memory of the card */
        int i = 0;
 
-
        vpdbase = pci_resource_start(brd->pdev, 3);
 
        /* No VPD */
@@ -1370,4 +1314,3 @@ static void cls_vpd(struct dgnc_board *brd)
        if (re_map_vpdbase)
                iounmap(re_map_vpdbase);
 }
-
index 465d79a6f75f6c138f6b5d12909f8962b01226c1..2597e36d38c47798999bd8c4bbaa0e1b53a0f3b5 100644 (file)
  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
  */
 
 #ifndef __DGNC_CLS_H
 #define __DGNC_CLS_H
 
-#include "dgnc_types.h"
-
-
 /************************************************************************
  * Per channel/port Classic UART structure                             *
  ************************************************************************
  *                     U = Unused.                                     *
  ************************************************************************/
 
+/*
+ * txrx    : WR RHR/THR - Holding reg
+ * ier     : WR IER - Interrupt Enable Reg
+ * isr_fcr : WR ISR/FCR - Interrupt Status Reg/Fifo Control Reg
+ * lcr     : WR LCR - Line Control Reg
+ * mcr     : WR MCR - Modem Control Reg
+ * lsr     : WR LSR - Line Status Reg
+ * msr     : WR MSG - Modem Status Reg
+ * spr     : WR SPR - Scratch pad Reg
+ */
 struct cls_uart_struct {
-       u8 txrx;                /* WR  RHR/THR - Holding Reg */
-       u8 ier;         /* WR  IER - Interrupt Enable Reg */
-       u8 isr_fcr;             /* WR  ISR/FCR - Interrupt Status Reg/Fifo Control Reg */
-       u8 lcr;         /* WR  LCR - Line Control Reg */
-       u8 mcr;         /* WR  MCR - Modem Control Reg */
-       u8 lsr;         /* WR  LSR - Line Status Reg */
-       u8 msr;         /* WR  MSR - Modem Status Reg */
-       u8 spr;         /* WR  SPR - Scratch Pad Reg */
+       u8 txrx;
+       u8 ier;
+       u8 isr_fcr;
+       u8 lcr;
+       u8 mcr;
+       u8 lsr;
+       u8 msr;
+       u8 spr;
 };
 
 /* Where to read the interrupt register (8bits) */
@@ -51,18 +51,15 @@ struct cls_uart_struct {
 
 #define UART_EXAR654_ENHANCED_REGISTER_SET 0xBF
 
-#define UART_16654_FCR_TXTRIGGER_8     0x0
 #define UART_16654_FCR_TXTRIGGER_16    0x10
-#define UART_16654_FCR_TXTRIGGER_32    0x20
-#define UART_16654_FCR_TXTRIGGER_56    0x30
-
-#define UART_16654_FCR_RXTRIGGER_8     0x0
 #define UART_16654_FCR_RXTRIGGER_16    0x40
 #define UART_16654_FCR_RXTRIGGER_56    0x80
-#define UART_16654_FCR_RXTRIGGER_60     0xC0
 
-#define UART_IIR_CTSRTS                        0x20    /* Received CTS/RTS change of state */
-#define UART_IIR_RDI_TIMEOUT           0x0C    /* Receiver data TIMEOUT */
+/* Received CTS/RTS change of state */
+#define UART_IIR_CTSRTS                        0x20
+
+/* Receiver data TIMEOUT */
+#define UART_IIR_RDI_TIMEOUT           0x0C
 
 /*
  * These are the EXTENDED definitions for the Exar 654's Interrupt
@@ -73,10 +70,6 @@ struct cls_uart_struct {
 #define UART_EXAR654_EFR_IXOFF    0x8     /* Transmit Xon1/Xoff1 */
 #define UART_EXAR654_EFR_RTSDTR   0x40    /* Auto RTS/DTR Flow Control Enable */
 #define UART_EXAR654_EFR_CTSDSR   0x80    /* Auto CTS/DSR Flow COntrol Enable */
-
-#define UART_EXAR654_XOFF_DETECT  0x1     /* Indicates whether chip saw an incoming XOFF char  */
-#define UART_EXAR654_XON_DETECT   0x2     /* Indicates whether chip saw an incoming XON char */
-
 #define UART_EXAR654_IER_XOFF     0x20    /* Xoff Interrupt Enable */
 #define UART_EXAR654_IER_RTSDTR   0x40    /* Output Interrupt Enable */
 #define UART_EXAR654_IER_CTSDSR   0x80    /* Input Interrupt Enable */
index f177d3a258c2cf8bce2c2f18182b19167e6155f7..805dc617e3a787b86a38142d2760fa8cdc2e4ed5 100644 (file)
  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *     NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *     This is shared code between Digi's CVS archive and the
- *     Linux Kernel sources.
- *     Changing the source just for reformatting needlessly breaks
- *     our CVS diff history.
- *
- *     Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *     Thank you.
- *
  */
 
 
@@ -37,7 +21,6 @@
 #include <linux/sched.h>
 #include "dgnc_driver.h"
 #include "dgnc_pci.h"
-#include "dpacompat.h"
 #include "dgnc_mgmt.h"
 #include "dgnc_tty.h"
 #include "dgnc_cls.h"
@@ -60,7 +43,8 @@ static void           dgnc_init_globals(void);
 static int             dgnc_found_board(struct pci_dev *pdev, int id);
 static void            dgnc_cleanup_board(struct dgnc_board *brd);
 static void            dgnc_poll_handler(ulong dummy);
-static int             dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int             dgnc_init_one(struct pci_dev *pdev,
+                                     const struct pci_device_id *ent);
 static void            dgnc_do_remap(struct dgnc_board *brd);
 
 /*
@@ -92,8 +76,8 @@ static struct class *dgnc_class;
  * Poller stuff
  */
 static DEFINE_SPINLOCK(dgnc_poll_lock); /* Poll scheduling lock */
-static ulong           dgnc_poll_time;                         /* Time of next poll */
-static uint            dgnc_poll_stop;                         /* Used to tell poller to stop */
+static ulong           dgnc_poll_time; /* Time of next poll */
+static uint            dgnc_poll_stop; /* Used to tell poller to stop */
 static struct timer_list dgnc_poll_timer;
 
 
@@ -139,14 +123,6 @@ static struct pci_driver dgnc_driver = {
        .id_table       = dgnc_pci_tbl,
 };
 
-
-char *dgnc_state_text[] = {
-       "Board Failed",
-       "Board Found",
-       "Board READY",
-};
-
-
 /************************************************************************
  *
  * Driver load/unload functions
@@ -214,7 +190,7 @@ static int __init dgnc_init_module(void)
         * If something went wrong in the scan, bail out of driver.
         */
        if (rc < 0) {
-               /* Only unregister the pci driver if it was actually registered. */
+               /* Only unregister if it was actually registered. */
                if (dgnc_NumBoards)
                        pci_unregister_driver(&dgnc_driver);
                else
@@ -251,9 +227,9 @@ static int dgnc_start(void)
         * Register management/dpa devices
         */
        rc = register_chrdev(0, "dgnc", &dgnc_BoardFops);
-       if (rc <= 0) {
+       if (rc < 0) {
                pr_err(DRVSTR ": Can't register dgnc driver device (%d)\n", rc);
-               return -ENXIO;
+               return rc;
        }
        dgnc_Major = rc;
 
@@ -285,9 +261,7 @@ static int dgnc_start(void)
 
        /* Start the poller */
        spin_lock_irqsave(&dgnc_poll_lock, flags);
-       init_timer(&dgnc_poll_timer);
-       dgnc_poll_timer.function = dgnc_poll_handler;
-       dgnc_poll_timer.data = 0;
+       setup_timer(&dgnc_poll_timer, dgnc_poll_handler, 0);
        dgnc_poll_time = jiffies + dgnc_jiffies_from_ms(dgnc_poll_tick);
        dgnc_poll_timer.expires = dgnc_poll_time;
        spin_unlock_irqrestore(&dgnc_poll_lock, flags);
@@ -364,7 +338,7 @@ static void dgnc_cleanup_board(struct dgnc_board *brd)
 
                spin_lock_irqsave(&dgnc_global_lock, flags);
                brd->msgbuf = NULL;
-               printk("%s", brd->msgbuf_head);
+               dev_dbg(&brd->pdev->dev, "%s\n", brd->msgbuf_head);
                kfree(brd->msgbuf_head);
                brd->msgbuf_head = NULL;
                spin_unlock_irqrestore(&dgnc_global_lock, flags);
@@ -410,7 +384,7 @@ static int dgnc_found_board(struct pci_dev *pdev, int id)
                return -ENOMEM;
 
        /* make a temporary message buffer for the boot messages */
-       brd->msgbuf_head = kzalloc(sizeof(u8) * 8192, GFP_KERNEL);
+       brd->msgbuf_head = kcalloc(8192, sizeof(u8), GFP_KERNEL);
        brd->msgbuf = brd->msgbuf_head;
 
        if (!brd->msgbuf) {
@@ -553,7 +527,7 @@ static int dgnc_found_board(struct pci_dev *pdev, int id)
 
                if (brd->re_map_membase) {
 
-                       /* After remap is complete, we need to read and store the dvid */
+                       /* Read and store the dvid after remapping */
                        brd->dvid = readb(brd->re_map_membase + 0x8D);
 
                        /* Get and store the board VPD, if it exists */
@@ -574,29 +548,19 @@ static int dgnc_found_board(struct pci_dev *pdev, int id)
 
        rc = dgnc_tty_register(brd);
        if (rc < 0) {
-               dgnc_tty_uninit(brd);
                pr_err(DRVSTR ": Can't register tty devices (%d)\n", rc);
-               brd->state = BOARD_FAILED;
-               brd->dpastatus = BD_NOFEP;
                goto failed;
        }
 
        rc = dgnc_finalize_board_init(brd);
        if (rc < 0) {
                pr_err(DRVSTR ": Can't finalize board init (%d)\n", rc);
-               brd->state = BOARD_FAILED;
-               brd->dpastatus = BD_NOFEP;
-
                goto failed;
        }
 
        rc = dgnc_tty_init(brd);
        if (rc < 0) {
-               dgnc_tty_uninit(brd);
                pr_err(DRVSTR ": Can't init tty devices (%d)\n", rc);
-               brd->state = BOARD_FAILED;
-               brd->dpastatus = BD_NOFEP;
-
                goto failed;
        }
 
@@ -606,11 +570,13 @@ static int dgnc_found_board(struct pci_dev *pdev, int id)
        dgnc_create_ports_sysfiles(brd);
 
        /* init our poll helper tasklet */
-       tasklet_init(&brd->helper_tasklet, brd->bd_ops->tasklet, (unsigned long) brd);
+       tasklet_init(&brd->helper_tasklet,
+                    brd->bd_ops->tasklet,
+                    (unsigned long) brd);
 
        spin_lock_irqsave(&dgnc_global_lock, flags);
        brd->msgbuf = NULL;
-       printk("%s", brd->msgbuf_head);
+       dev_dbg(&brd->pdev->dev, "%s\n", brd->msgbuf_head);
        kfree(brd->msgbuf_head);
        brd->msgbuf_head = NULL;
        spin_unlock_irqrestore(&dgnc_global_lock, flags);
@@ -628,6 +594,9 @@ static int dgnc_found_board(struct pci_dev *pdev, int id)
        return 0;
 
 failed:
+       dgnc_tty_uninit(brd);
+       brd->state = BOARD_FAILED;
+       brd->dpastatus = BD_NOFEP;
 
        return -ENXIO;
 
@@ -708,7 +677,7 @@ static void dgnc_poll_handler(ulong dummy)
 
                spin_lock_irqsave(&brd->bd_lock, flags);
 
-               /* If board is in a failed state, don't bother scheduling a tasklet */
+               /* If board is in a failed state don't schedule a tasklet */
                if (brd->state == BOARD_FAILED) {
                        spin_unlock_irqrestore(&brd->bd_lock, flags);
                        continue;
@@ -729,11 +698,9 @@ static void dgnc_poll_handler(ulong dummy)
        new_time = dgnc_poll_time - jiffies;
 
        if ((ulong) new_time >= 2 * dgnc_poll_tick)
-               dgnc_poll_time = jiffies +  dgnc_jiffies_from_ms(dgnc_poll_tick);
+               dgnc_poll_time = jiffies + dgnc_jiffies_from_ms(dgnc_poll_tick);
 
-       init_timer(&dgnc_poll_timer);
-       dgnc_poll_timer.function = dgnc_poll_handler;
-       dgnc_poll_timer.data = 0;
+       setup_timer(&dgnc_poll_timer, dgnc_poll_handler, 0);
        dgnc_poll_timer.expires = dgnc_poll_time;
        spin_unlock_irqrestore(&dgnc_poll_lock, flags);
 
index a8157eba28dac470ac5ae5c5d92c9843bd7f096b..f77fed57b873623745bb5818536b31f257aa22a8 100644 (file)
  * 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.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
  *************************************************************************
  *
  * Driver includes
@@ -31,9 +25,7 @@
 #include <linux/tty.h>   /* To pick up the various tty structs/defines */
 #include <linux/interrupt.h>   /* For irqreturn_t type */
 
-#include "dgnc_types.h"                /* Additional types needed by the Digi header files */
 #include "digi.h"              /* Digi specific ioctl header */
-#include "dgnc_kcompat.h"      /* Kernel 2.4/2.6 compat includes */
 #include "dgnc_sysfs.h"                /* Support for SYSFS */
 
 /*************************************************************************
@@ -46,6 +38,7 @@
 #define        PROCSTR         "dgnc"                  /* /proc entries         */
 #define        DEVSTR          "/dev/dg/dgnc"          /* /dev entries          */
 #define        DRVSTR          "dgnc"                  /* Driver name string    */
+#define        DG_PART         "40002369_F"            /* RPM part number       */
 
 #define TRC_TO_CONSOLE 1
 
@@ -211,8 +204,8 @@ struct dgnc_board {
        struct tty_driver       PrintDriver;
        char            PrintName[200];
 
-       uint            dgnc_Major_Serial_Registered;
-       uint            dgnc_Major_TransparentPrint_Registered;
+       bool            dgnc_Major_Serial_Registered;
+       bool            dgnc_Major_TransparentPrint_Registered;
 
        uint            dgnc_Serial_Major;
        uint            dgnc_TransparentPrint_Major;
@@ -398,11 +391,10 @@ struct channel_t {
 /*
  * Our Global Variables.
  */
-extern uint            dgnc_Major;             /* Our driver/mgmt major        */
-extern int             dgnc_poll_tick;         /* Poll interval - 20 ms        */
-extern spinlock_t      dgnc_global_lock;       /* Driver global spinlock       */
-extern uint            dgnc_NumBoards;         /* Total number of boards       */
-extern struct dgnc_board       *dgnc_Board[MAXBOARDS]; /* Array of board structs       */
-extern char            *dgnc_state_text[];     /* Array of state text          */
+extern uint            dgnc_Major;             /* Our driver/mgmt major */
+extern int             dgnc_poll_tick;         /* Poll interval - 20 ms */
+extern spinlock_t      dgnc_global_lock;       /* Driver global spinlock */
+extern uint            dgnc_NumBoards;         /* Total number of boards */
+extern struct dgnc_board       *dgnc_Board[MAXBOARDS]; /* Array of board structs */
 
 #endif
diff --git a/drivers/staging/dgnc/dgnc_kcompat.h b/drivers/staging/dgnc/dgnc_kcompat.h
deleted file mode 100644 (file)
index 566cad0..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2004 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- *************************************************************************
- *
- * This file is intended to contain all the kernel "differences" between the
- * various kernels that we support.
- *
- *************************************************************************/
-
-#ifndef __DGNC_KCOMPAT_H
-#define __DGNC_KCOMPAT_H
-
-#if !defined(TTY_FLIPBUF_SIZE)
-# define TTY_FLIPBUF_SIZE 512
-#endif
-
-
-/* Sparse stuff */
-# ifndef __user
-#  define __user
-#  define __kernel
-#  define __safe
-#  define __force
-#  define __chk_user_ptr(x) (void)0
-# endif
-
-
-#endif /* ! __DGNC_KCOMPAT_H */
index 5544a8e7f4bc405195130417f31927f72cf42a59..b13318a82fe1970fa64fb8d1856fc65db39539ec 100644 (file)
  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *     NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *     This is shared code between Digi's CVS archive and the
- *     Linux Kernel sources.
- *     Changing the source just for reformatting needlessly breaks
- *     our CVS diff history.
- *
- *     Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *     Thank you.
- *
  */
 
 /************************************************************************
@@ -46,9 +30,7 @@
 
 #include "dgnc_driver.h"
 #include "dgnc_pci.h"
-#include "dgnc_kcompat.h"      /* Kernel 2.4/2.6 compat includes */
 #include "dgnc_mgmt.h"
-#include "dpacompat.h"
 
 
 /* Our "in use" variables, to enforce 1 open only */
@@ -153,8 +135,7 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                if (copy_from_user(&brd, uarg, sizeof(int)))
                        return -EFAULT;
 
-               if ((brd < 0) || (brd > dgnc_NumBoards) ||
-                   (dgnc_NumBoards == 0))
+               if (brd < 0 || brd >= dgnc_NumBoards)
                        return -ENODEV;
 
                memset(&di, 0, sizeof(di));
@@ -196,11 +177,11 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                channel = ni.channel;
 
                /* Verify boundaries on board */
-               if ((board > dgnc_NumBoards) || (dgnc_NumBoards == 0))
+               if (board >= dgnc_NumBoards)
                        return -ENODEV;
 
                /* Verify boundaries on channel */
-               if ((channel < 0) || (channel > dgnc_Board[board]->nasync))
+               if (channel >= dgnc_Board[board]->nasync)
                        return -ENODEV;
 
                ch = dgnc_Board[board]->channels[channel];
index 567f687b18ddb79bc0dae4124be9f6f1ede2f46f..708abe9594d41a2c91bfe3e6de77117c113a46be 100644 (file)
  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
  */
 
 #ifndef __DGNC_MGMT_H
index c9a8a9825cfb25fa4d3392e7c23eea8bfecbf7c6..f5a4d365115fdcb85b6d5dc3c4d70a2067845c58 100644 (file)
  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *     NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *     This is shared code between Digi's CVS archive and the
- *     Linux Kernel sources.
- *     Changing the source just for reformatting needlessly breaks
- *     our CVS diff history.
- *
- *     Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *     Thank you.
- *
  */
 
 
@@ -119,7 +103,7 @@ static inline void neo_set_cts_flow_control(struct channel_t *ch)
 
        /* Turn on auto CTS flow control */
 #if 1
-       ier |= (UART_17158_IER_CTSDSR);
+       ier |= UART_17158_IER_CTSDSR;
 #else
        ier &= ~(UART_17158_IER_CTSDSR);
 #endif
@@ -127,7 +111,7 @@ static inline void neo_set_cts_flow_control(struct channel_t *ch)
        efr |= (UART_17158_EFR_ECB | UART_17158_EFR_CTSDSR);
 
        /* Turn off auto Xon flow control */
-       efr &= ~(UART_17158_EFR_IXON);
+       efr &= ~UART_17158_EFR_IXON;
 
        /* Why? Becuz Exar's spec says we have to zero it out before setting it */
        writeb(0, &ch->ch_neo_uart->efr);
@@ -155,15 +139,15 @@ static inline void neo_set_rts_flow_control(struct channel_t *ch)
 
        /* Turn on auto RTS flow control */
 #if 1
-       ier |= (UART_17158_IER_RTSDTR);
+       ier |= UART_17158_IER_RTSDTR;
 #else
        ier &= ~(UART_17158_IER_RTSDTR);
 #endif
        efr |= (UART_17158_EFR_ECB | UART_17158_EFR_RTSDTR);
 
        /* Turn off auto Xoff flow control */
-       ier &= ~(UART_17158_IER_XOFF);
-       efr &= ~(UART_17158_EFR_IXOFF);
+       ier &= ~UART_17158_IER_XOFF;
+       efr &= ~UART_17158_EFR_IXOFF;
 
        /* Why? Becuz Exar's spec says we have to zero it out before setting it */
        writeb(0, &ch->ch_neo_uart->efr);
@@ -185,7 +169,7 @@ static inline void neo_set_rts_flow_control(struct channel_t *ch)
         * RTS/DTR# output pin (MCR bit-0 or 1 to logic 1 after
         * it is enabled.
         */
-       ch->ch_mostat |= (UART_MCR_RTS);
+       ch->ch_mostat |= UART_MCR_RTS;
 
        neo_pci_posting_flush(ch->ch_bd);
 }
@@ -197,8 +181,8 @@ static inline void neo_set_ixon_flow_control(struct channel_t *ch)
        unsigned char efr = readb(&ch->ch_neo_uart->efr);
 
        /* Turn off auto CTS flow control */
-       ier &= ~(UART_17158_IER_CTSDSR);
-       efr &= ~(UART_17158_EFR_CTSDSR);
+       ier &= ~UART_17158_IER_CTSDSR;
+       efr &= ~UART_17158_EFR_CTSDSR;
 
        /* Turn on auto Xon flow control */
        efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXON);
@@ -234,11 +218,11 @@ static inline void neo_set_ixoff_flow_control(struct channel_t *ch)
        unsigned char efr = readb(&ch->ch_neo_uart->efr);
 
        /* Turn off auto RTS flow control */
-       ier &= ~(UART_17158_IER_RTSDTR);
-       efr &= ~(UART_17158_EFR_RTSDTR);
+       ier &= ~UART_17158_IER_RTSDTR;
+       efr &= ~UART_17158_EFR_RTSDTR;
 
        /* Turn on auto Xoff flow control */
-       ier |= (UART_17158_IER_XOFF);
+       ier |= UART_17158_IER_XOFF;
        efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
 
        /* Why? Becuz Exar's spec says we have to zero it out before setting it */
@@ -272,11 +256,11 @@ static inline void neo_set_no_input_flow_control(struct channel_t *ch)
        unsigned char efr = readb(&ch->ch_neo_uart->efr);
 
        /* Turn off auto RTS flow control */
-       ier &= ~(UART_17158_IER_RTSDTR);
-       efr &= ~(UART_17158_EFR_RTSDTR);
+       ier &= ~UART_17158_IER_RTSDTR;
+       efr &= ~UART_17158_EFR_RTSDTR;
 
        /* Turn off auto Xoff flow control */
-       ier &= ~(UART_17158_IER_XOFF);
+       ier &= ~UART_17158_IER_XOFF;
        if (ch->ch_c_iflag & IXON)
                efr &= ~(UART_17158_EFR_IXOFF);
        else
@@ -312,12 +296,12 @@ static inline void neo_set_no_output_flow_control(struct channel_t *ch)
        unsigned char efr = readb(&ch->ch_neo_uart->efr);
 
        /* Turn off auto CTS flow control */
-       ier &= ~(UART_17158_IER_CTSDSR);
-       efr &= ~(UART_17158_EFR_CTSDSR);
+       ier &= ~UART_17158_IER_CTSDSR;
+       efr &= ~UART_17158_EFR_CTSDSR;
 
        /* Turn off auto Xon flow control */
        if (ch->ch_c_iflag & IXOFF)
-               efr &= ~(UART_17158_EFR_IXON);
+               efr &= ~UART_17158_EFR_IXON;
        else
                efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXON);
 
@@ -407,7 +391,7 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port)
        if (!brd || brd->magic != DGNC_BOARD_MAGIC)
                return;
 
-       if (port > brd->maxports)
+       if (port >= brd->maxports)
                return;
 
        ch = brd->channels[port];
@@ -537,7 +521,7 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port)
        if (!brd || brd->magic != DGNC_BOARD_MAGIC)
                return;
 
-       if (port > brd->maxports)
+       if (port >= brd->maxports)
                return;
 
        ch = brd->channels[port];
@@ -1019,7 +1003,7 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
                         */
 
                        /* Verify the port is in range. */
-                       if (port > brd->nasync)
+                       if (port >= brd->nasync)
                                continue;
 
                        ch = brd->channels[port];
@@ -1203,7 +1187,7 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch)
                 * IBM pSeries platform.
                 * 15 bytes max appears to be the magic number.
                 */
-               n = min((uint) n, (uint) 12);
+               n = min_t(uint, n, 12);
 
                /*
                 * Since we are grabbing the linestatus register, which
@@ -1436,16 +1420,13 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch)
        spin_lock_irqsave(&ch->ch_lock, flags);
 
        /* No data to write to the UART */
-       if (ch->ch_w_tail == ch->ch_w_head) {
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-               return;
-       }
+       if (ch->ch_w_tail == ch->ch_w_head)
+               goto exit_unlock;
 
        /* If port is "stopped", don't send any data to the UART */
-       if ((ch->ch_flags & CH_FORCED_STOP) || (ch->ch_flags & CH_BREAK_SENDING)) {
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-               return;
-       }
+       if ((ch->ch_flags & CH_FORCED_STOP) ||
+                (ch->ch_flags & CH_BREAK_SENDING))
+               goto exit_unlock;
 
        /*
         * If FIFOs are disabled. Send data directly to txrx register
@@ -1486,27 +1467,23 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch)
                        ch->ch_w_tail &= WQUEUEMASK;
                        ch->ch_txcount++;
                }
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-               return;
+
+               goto exit_unlock;
        }
 
        /*
         * We have to do it this way, because of the EXAR TXFIFO count bug.
         */
        if ((ch->ch_bd->dvid & 0xf0) < UART_XR17E158_DVID) {
-               if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM))) {
-                       spin_unlock_irqrestore(&ch->ch_lock, flags);
-                       return;
-               }
+               if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM)))
+                       goto exit_unlock;
 
                len_written = 0;
 
                n = readb(&ch->ch_neo_uart->tfifo);
 
-               if ((unsigned int) n > ch->ch_t_tlevel) {
-                       spin_unlock_irqrestore(&ch->ch_lock, flags);
-                       return;
-               }
+               if ((unsigned int) n > ch->ch_t_tlevel)
+                       goto exit_unlock;
 
                n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel;
        } else {
@@ -1570,6 +1547,7 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch)
                ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
        }
 
+exit_unlock:
        spin_unlock_irqrestore(&ch->ch_lock, flags);
 }
 
index 1a4abb128693657bfc1fcfc7520f313fe18317b6..c528df5a0e5af10a315da11b643d565bf87615e7 100644 (file)
  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
  */
 
 #ifndef __DGNC_NEO_H
 #define __DGNC_NEO_H
 
-#include "dgnc_types.h"
 #include "dgnc_driver.h"
 
 /************************************************************************
index 5b6f76d98aa72a8ea5b826ce1ffe98037ad6be60..617d40d1ec190cda7163b7e47634b9e665cc7ccd 100644 (file)
  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
  */
 
 #ifndef __DGNC_PCI_H
index 2fd34ca70c599a260c0a9bacdea3923a86c9a032..65551d19051529fc669f1aab29cb1f68bf31e601 100644 (file)
  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *      NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *      This is shared code between Digi's CVS archive and the
- *      Linux Kernel sources.
- *      Changing the source just for reformatting needlessly breaks
- *      our CVS diff history.
- *
- *      Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *      Thank you.
- *
  */
 
 
@@ -91,7 +75,7 @@ void dgnc_create_driver_sysfiles(struct pci_driver *dgnc_driver)
        rc |= driver_create_file(driverfs, &driver_attr_maxboards);
        rc |= driver_create_file(driverfs, &driver_attr_pollrate);
        if (rc)
-               printk(KERN_ERR "DGNC: sysfs driver_create_file failed!\n");
+               pr_err("DGNC: sysfs driver_create_file failed!\n");
 }
 
 
@@ -360,7 +344,7 @@ void dgnc_create_ports_sysfiles(struct dgnc_board *bd)
        rc |= device_create_file(&(bd->pdev->dev), &dev_attr_vpd);
        rc |= device_create_file(&(bd->pdev->dev), &dev_attr_serial_number);
        if (rc)
-               printk(KERN_ERR "DGNC: sysfs device_create_file failed!\n");
+               dev_err(&bd->pdev->dev, "dgnc: sysfs device_create_file failed!\n");
 }
 
 
index 68c0de5898a483c6c918c7cd10d69932e56f7129..be0f90a6768b0b822f94a8cb548c42e0041d5bd9 100644 (file)
  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
  */
 
 #ifndef __DGNC_SYSFS_H
 #define __DGNC_SYSFS_H
 
-#include "dgnc_driver.h"
-
 #include <linux/device.h>
+#include "dgnc_driver.h"
 
 struct dgnc_board;
 struct channel_t;
@@ -44,6 +37,4 @@ extern 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);
 
-
-
 #endif
index f81a375f8bc17e87cf23d6ffe793bb782edb019c..ce4187f60cb457f70ca9f141e5a9f240e758b7e3 100644 (file)
  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *     NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
- *
- *     This is shared code between Digi's CVS archive and the
- *     Linux Kernel sources.
- *     Changing the source just for reformatting needlessly breaks
- *     our CVS diff history.
- *
- *     Send any bug fixes/changes to:  Eng.Linux at digi dot com.
- *     Thank you.
  */
 
 /************************************************************************
@@ -44,6 +29,7 @@
 #include <linux/ctype.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
+#include <linux/types.h>
 #include <linux/serial_reg.h>
 #include <linux/slab.h>
 #include <linux/delay.h>       /* For udelay */
 #include <linux/pci.h>
 #include "dgnc_driver.h"
 #include "dgnc_tty.h"
-#include "dgnc_types.h"
 #include "dgnc_neo.h"
 #include "dgnc_cls.h"
-#include "dpacompat.h"
 #include "dgnc_sysfs.h"
 #include "dgnc_utils.h"
 
@@ -236,7 +220,7 @@ int dgnc_tty_register(struct dgnc_board *brd)
                                "Can't register tty device (%d)\n", rc);
                        return rc;
                }
-               brd->dgnc_Major_Serial_Registered = TRUE;
+               brd->dgnc_Major_Serial_Registered = true;
        }
 
        /*
@@ -286,7 +270,7 @@ int dgnc_tty_register(struct dgnc_board *brd)
                                rc);
                        return rc;
                }
-               brd->dgnc_Major_TransparentPrint_Registered = TRUE;
+               brd->dgnc_Major_TransparentPrint_Registered = true;
        }
 
        dgnc_BoardsByMajor[brd->SerialDriver.major] = brd;
@@ -424,7 +408,7 @@ void dgnc_tty_uninit(struct dgnc_board *brd)
                        tty_unregister_device(&brd->SerialDriver, i);
                }
                tty_unregister_driver(&brd->SerialDriver);
-               brd->dgnc_Major_Serial_Registered = FALSE;
+               brd->dgnc_Major_Serial_Registered = false;
        }
 
        if (brd->dgnc_Major_TransparentPrint_Registered) {
@@ -435,7 +419,7 @@ void dgnc_tty_uninit(struct dgnc_board *brd)
                        tty_unregister_device(&brd->PrintDriver, i);
                }
                tty_unregister_driver(&brd->PrintDriver);
-               brd->dgnc_Major_TransparentPrint_Registered = FALSE;
+               brd->dgnc_Major_TransparentPrint_Registered = false;
        }
 
        kfree(brd->SerialDriver.ttys);
@@ -507,7 +491,7 @@ void dgnc_input(struct channel_t *ch)
 {
        struct dgnc_board *bd;
        struct tty_struct *tp;
-       struct tty_ldisc *ld;
+       struct tty_ldisc *ld = NULL;
        uint    rmask;
        ushort  head;
        ushort  tail;
@@ -539,10 +523,8 @@ void dgnc_input(struct channel_t *ch)
        tail = ch->ch_r_tail & rmask;
        data_len = (head - tail) & rmask;
 
-       if (data_len == 0) {
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-               return;
-       }
+       if (data_len == 0)
+               goto exit_unlock;
 
        /*
         * If the device is not open, or CREAD is off,
@@ -556,17 +538,14 @@ void dgnc_input(struct channel_t *ch)
                /* Force queue flow control to be released, if needed */
                dgnc_check_queue_flow_control(ch);
 
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-               return;
+               goto exit_unlock;
        }
 
        /*
         * If we are throttled, simply don't read any data.
         */
-       if (ch->ch_flags & CH_FORCED_STOPI) {
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-               return;
-       }
+       if (ch->ch_flags & CH_FORCED_STOPI)
+               goto exit_unlock;
 
        flip_len = TTY_FLIPBUF_SIZE;
 
@@ -604,12 +583,8 @@ void dgnc_input(struct channel_t *ch)
                }
        }
 
-       if (len <= 0) {
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-               if (ld)
-                       tty_ldisc_deref(ld);
-               return;
-       }
+       if (len <= 0)
+               goto exit_unlock;
 
        /*
         * The tty layer in the kernel has changed in 2.6.16+.
@@ -675,6 +650,12 @@ void dgnc_input(struct channel_t *ch)
        /* Tell the tty layer its okay to "eat" the data now */
        tty_flip_buffer_push(tp->port);
 
+       if (ld)
+               tty_ldisc_deref(ld);
+       return;
+
+exit_unlock:
+       spin_unlock_irqrestore(&ch->ch_lock, flags);
        if (ld)
                tty_ldisc_deref(ld);
 }
@@ -886,10 +867,6 @@ void dgnc_check_queue_flow_control(struct channel_t *ch)
                                ch->ch_stops_sent++;
                        }
                }
-               /* No FLOW */
-               else {
-                       /* Empty... Can't do anything about the impending overflow... */
-               }
        }
 
        /*
@@ -1064,7 +1041,7 @@ static int dgnc_tty_open(struct tty_struct *tty, struct file *file)
        spin_lock_irqsave(&brd->bd_lock, flags);
 
        /* If opened device is greater than our number of ports, bail. */
-       if (PORT_NUM(minor) > brd->nasync) {
+       if (PORT_NUM(minor) >= brd->nasync) {
                spin_unlock_irqrestore(&brd->bd_lock, flags);
                return -ENXIO;
        }
@@ -1777,10 +1754,8 @@ static int dgnc_tty_write(struct tty_struct *tty,
        /*
         * Bail if no space left.
         */
-       if (count <= 0) {
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-               return 0;
-       }
+       if (count <= 0)
+               goto exit_retry;
 
        /*
         * Output the printer ON string, if we are in terminal mode, but
@@ -1807,10 +1782,8 @@ static int dgnc_tty_write(struct tty_struct *tty,
        /*
         * If there is nothing left to copy, or I can't handle any more data, leave.
         */
-       if (count <= 0) {
-               spin_unlock_irqrestore(&ch->ch_lock, flags);
-               return 0;
-       }
+       if (count <= 0)
+               goto exit_retry;
 
        if (from_user) {
 
@@ -1896,6 +1869,11 @@ static int dgnc_tty_write(struct tty_struct *tty,
        }
 
        return count;
+
+exit_retry:
+
+       spin_unlock_irqrestore(&ch->ch_lock, flags);
+       return 0;
 }
 
 
index 3975f040714334fb6296b4a38a8342fc83a17073..21d3369b875ce147fcf6285ecd996e970b3958c1 100644 (file)
  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
  */
 
 #ifndef __DGNC_TTY_H
diff --git a/drivers/staging/dgnc/dgnc_types.h b/drivers/staging/dgnc/dgnc_types.h
deleted file mode 100644 (file)
index 3aafced..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *     Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-#ifndef __DGNC_TYPES_H
-#define __DGNC_TYPES_H
-
-#ifndef TRUE
-# define TRUE 1
-#endif
-
-#ifndef FALSE
-# define FALSE 0
-#endif
-
-#endif
index 80b51332292cfe6bebf5198d21a6cf14c9b051d1..f76de82908d3d536af9550f8dae19517a7ce70cb 100644 (file)
@@ -16,55 +16,3 @@ int dgnc_ms_sleep(ulong ms)
        schedule_timeout((ms * HZ) / 1000);
        return signal_pending(current);
 }
-
-/*
- *      dgnc_ioctl_name() : Returns a text version of each ioctl value.
- */
-char *dgnc_ioctl_name(int cmd)
-{
-       switch (cmd) {
-
-       case TCGETA:            return "TCGETA";
-       case TCGETS:            return "TCGETS";
-       case TCSETA:            return "TCSETA";
-       case TCSETS:            return "TCSETS";
-       case TCSETAW:           return "TCSETAW";
-       case TCSETSW:           return "TCSETSW";
-       case TCSETAF:           return "TCSETAF";
-       case TCSETSF:           return "TCSETSF";
-       case TCSBRK:            return "TCSBRK";
-       case TCXONC:            return "TCXONC";
-       case TCFLSH:            return "TCFLSH";
-       case TIOCGSID:          return "TIOCGSID";
-
-       case TIOCGETD:          return "TIOCGETD";
-       case TIOCSETD:          return "TIOCSETD";
-       case TIOCGWINSZ:        return "TIOCGWINSZ";
-       case TIOCSWINSZ:        return "TIOCSWINSZ";
-
-       case TIOCMGET:          return "TIOCMGET";
-       case TIOCMSET:          return "TIOCMSET";
-       case TIOCMBIS:          return "TIOCMBIS";
-       case TIOCMBIC:          return "TIOCMBIC";
-
-       /* from digi.h */
-       case DIGI_SETA:         return "DIGI_SETA";
-       case DIGI_SETAW:        return "DIGI_SETAW";
-       case DIGI_SETAF:        return "DIGI_SETAF";
-       case DIGI_SETFLOW:      return "DIGI_SETFLOW";
-       case DIGI_SETAFLOW:     return "DIGI_SETAFLOW";
-       case DIGI_GETFLOW:      return "DIGI_GETFLOW";
-       case DIGI_GETAFLOW:     return "DIGI_GETAFLOW";
-       case DIGI_GETA:         return "DIGI_GETA";
-       case DIGI_GEDELAY:      return "DIGI_GEDELAY";
-       case DIGI_SEDELAY:      return "DIGI_SEDELAY";
-       case DIGI_GETCUSTOMBAUD: return "DIGI_GETCUSTOMBAUD";
-       case DIGI_SETCUSTOMBAUD: return "DIGI_SETCUSTOMBAUD";
-       case TIOCMODG:          return "TIOCMODG";
-       case TIOCMODS:          return "TIOCMODS";
-       case TIOCSDTR:          return "TIOCSDTR";
-       case TIOCCDTR:          return "TIOCCDTR";
-
-       default:                return "unknown";
-       }
-}
index cebf60163a2674b6ab601847a1e816bac209d683..1164c3a09c6bed0b1e6d34225f5e26410e1a2917 100644 (file)
@@ -2,6 +2,5 @@
 #define __DGNC_UTILS_H
 
 int dgnc_ms_sleep(ulong ms);
-char *dgnc_ioctl_name(int cmd);
 
 #endif
index d6e0b9f6b24a3896811556d91f110f011654c8a5..d637a7802168e163187911c277c2778bc7464521 100644 (file)
  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *     NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
  */
 
 #ifndef __DIGI_H
 #define __DIGI_H
 
-/************************************************************************
- ***   Definitions for Digi ditty(1) command.
- ************************************************************************/
-
-
-/*
- * Copyright (c) 1988-96 Digi International Inc., All Rights Reserved.
- */
-
-/************************************************************************
- * This module provides application access to special Digi
- * serial line enhancements which are not standard UNIX(tm) features.
- ************************************************************************/
-
-#if !defined(TIOCMODG)
-
-#define        TIOCMODG        (('d'<<8) | 250)        /* get modem ctrl state */
-#define        TIOCMODS        (('d'<<8) | 251)        /* set modem ctrl state */
-
 #ifndef TIOCM_LE
 #define                TIOCM_LE        0x01            /* line enable          */
 #define                TIOCM_DTR       0x02            /* data terminal ready  */
@@ -55,8 +30,6 @@
 #define                TIOCM_CD        TIOCM_CAR       /* carrier detect (alt) */
 #endif
 
-#endif
-
 #if !defined(TIOCMSET)
 #define        TIOCMSET        (('d'<<8) | 252)        /* set modem ctrl state */
 #define        TIOCMGET        (('d'<<8) | 253)        /* set modem ctrl state */
 #define        TIOCMBIS        (('d'<<8) | 255)        /* set modem ctrl state */
 #endif
 
-
-#if !defined(TIOCSDTR)
-#define        TIOCSDTR        (('e'<<8) | 0)          /* set DTR              */
-#define        TIOCCDTR        (('e'<<8) | 1)          /* clear DTR            */
-#endif
-
-/************************************************************************
- * Ioctl command arguments for DIGI parameters.
- ************************************************************************/
 #define DIGI_GETA      (('e'<<8) | 94)         /* Read params          */
-
 #define DIGI_SETA      (('e'<<8) | 95)         /* Set params           */
 #define DIGI_SETAW     (('e'<<8) | 96)         /* Drain & set params   */
 #define DIGI_SETAF     (('e'<<8) | 97)         /* Drain, flush & set params */
-
-#define DIGI_KME       (('e'<<8) | 98)         /* Read/Write Host      */
-                                               /* Adapter Memory       */
-
-#define        DIGI_GETFLOW    (('e'<<8) | 99)         /* Get startc/stopc flow */
-                                               /* control characters    */
-#define        DIGI_SETFLOW    (('e'<<8) | 100)        /* Set startc/stopc flow */
-                                               /* control characters    */
-#define        DIGI_GETAFLOW   (('e'<<8) | 101)        /* Get Aux. startc/stopc */
-                                               /* flow control chars    */
-#define        DIGI_SETAFLOW   (('e'<<8) | 102)        /* Set Aux. startc/stopc */
-                                               /* flow control chars    */
-
-#define DIGI_GEDELAY   (('d'<<8) | 246)        /* Get edelay */
-#define DIGI_SEDELAY   (('d'<<8) | 247)        /* Set edelay */
-
-struct digiflow_t {
-       unsigned char   startc;                         /* flow cntl start char */
-       unsigned char   stopc;                          /* flow cntl stop char  */
-};
-
-
-#ifdef FLOW_2200
-#define        F2200_GETA      (('e'<<8) | 104)        /* Get 2x36 flow cntl flags */
-#define        F2200_SETAW     (('e'<<8) | 105)        /* Set 2x36 flow cntl flags */
-#define                F2200_MASK      0x03            /* 2200 flow cntl bit mask  */
-#define                FCNTL_2200      0x01            /* 2x36 terminal flow cntl  */
-#define                PCNTL_2200      0x02            /* 2x36 printer flow cntl   */
-#define        F2200_XON       0xf8
-#define        P2200_XON       0xf9
-#define        F2200_XOFF      0xfa
-#define        P2200_XOFF      0xfb
-
-#define        FXOFF_MASK      0x03                    /* 2200 flow status mask    */
-#define        RCVD_FXOFF      0x01                    /* 2x36 Terminal XOFF rcvd  */
-#define        RCVD_PXOFF      0x02                    /* 2x36 Printer XOFF rcvd   */
-#endif
-
-/************************************************************************
- * Values for digi_flags
- ************************************************************************/
-#define DIGI_IXON      0x0001          /* Handle IXON in the FEP       */
+#define DIGI_GET_NI_INFO (('d'<<8) | 250) /* Non-intelligent state info */
+#define DIGI_LOOPBACK (('d'<<8) | 252) /*
+                                       * Enable/disable UART
+                                       * internal loopback
+                                       */
 #define DIGI_FAST      0x0002          /* Fast baud rates              */
 #define RTSPACE                0x0004          /* RTS input flow control       */
 #define CTSPACE                0x0008          /* CTS output flow control      */
-#define DSRPACE                0x0010          /* DSR output flow control      */
-#define DCDPACE                0x0020          /* DCD output flow control      */
-#define DTRPACE                0x0040          /* DTR input flow control       */
 #define DIGI_COOK      0x0080          /* Cooked processing done in FEP */
 #define DIGI_FORCEDCD  0x0100          /* Force carrier                */
 #define        DIGI_ALTPIN     0x0200          /* Alternate RJ-45 pin config   */
-#define        DIGI_AIXON      0x0400          /* Aux flow control in fep      */
 #define        DIGI_PRINTER    0x0800          /* Hold port open for flow cntrl*/
-#define DIGI_PP_INPUT  0x1000          /* Change parallel port to input*/
 #define DIGI_DTR_TOGGLE        0x2000          /* Support DTR Toggle           */
-#define DIGI_422       0x4000          /* for 422/232 selectable panel */
 #define DIGI_RTS_TOGGLE        0x8000          /* Support RTS Toggle           */
-
-/************************************************************************
- * These options are not supported on the comxi.
- ************************************************************************/
-#define        DIGI_COMXI      (DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE)
-
 #define DIGI_PLEN      28              /* String length                */
 #define        DIGI_TSIZ       10              /* Terminal string len          */
 
@@ -162,76 +76,6 @@ struct digi_t {
        char            digi_term[DIGI_TSIZ];   /* terminal string      */
 };
 
-/************************************************************************
- * KME definitions and structures.
- ************************************************************************/
-#define        RW_IDLE         0       /* Operation complete                   */
-#define        RW_READ         1       /* Read Concentrator Memory             */
-#define        RW_WRITE        2       /* Write Concentrator Memory            */
-
-struct rw_t {
-       unsigned char   rw_req;         /* Request type                 */
-       unsigned char   rw_board;       /* Host Adapter board number    */
-       unsigned char   rw_conc;        /* Concentrator number          */
-       unsigned char   rw_reserved;    /* Reserved for expansion       */
-       unsigned int    rw_addr;        /* Address in concentrator      */
-       unsigned short  rw_size;        /* Read/write request length    */
-       unsigned char   rw_data[128];   /* Data to read/write           */
-};
-
-/***********************************************************************
- * Shrink Buffer and Board Information definitions and structures.
-
- ************************************************************************/
-                       /* Board type return codes */
-#define        PCXI_TYPE 1     /* Board type at the designated port is a PC/Xi */
-#define PCXM_TYPE 2     /* Board type at the designated port is a PC/Xm */
-#define        PCXE_TYPE 3     /* Board type at the designated port is a PC/Xe */
-#define        MCXI_TYPE 4     /* Board type at the designated port is a MC/Xi */
-#define COMXI_TYPE 5     /* Board type at the designated port is a COM/Xi */
-
-                        /* Non-Zero Result codes. */
-#define RESULT_NOBDFND 1 /* A Digi product at that port is not config installed */
-#define RESULT_NODESCT 2 /* A memory descriptor was not obtainable */
-#define RESULT_NOOSSIG 3 /* FEP/OS signature was not detected on the board */
-#define RESULT_TOOSML  4 /* Too small an area to shrink.  */
-#define RESULT_NOCHAN  5 /* Channel structure for the board was not found */
-
-struct shrink_buf_struct {
-       unsigned int    shrink_buf_vaddr;       /* Virtual address of board */
-       unsigned int    shrink_buf_phys;        /* Physical address of board */
-       unsigned int    shrink_buf_bseg;        /* Amount of board memory */
-       unsigned int    shrink_buf_hseg;        /* '186 Beginning of Dual-Port */
-
-       unsigned int    shrink_buf_lseg;        /* '186 Beginning of freed memory */
-       unsigned int    shrink_buf_mseg;        /* Linear address from start of
-                                                  dual-port were freed memory
-                                                  begins, host viewpoint. */
-
-       unsigned int    shrink_buf_bdparam;     /* Parameter for xxmemon and
-                                                  xxmemoff */
-
-       unsigned int    shrink_buf_reserva;     /* Reserved */
-       unsigned int    shrink_buf_reservb;     /* Reserved */
-       unsigned int    shrink_buf_reservc;     /* Reserved */
-       unsigned int    shrink_buf_reservd;     /* Reserved */
-
-       unsigned char   shrink_buf_result;      /* Reason for call failing
-                                                  Zero is Good return */
-       unsigned char   shrink_buf_init;        /* Non-Zero if it caused an
-                                                  xxinit call. */
-
-       unsigned char   shrink_buf_anports;     /* Number of async ports  */
-       unsigned char   shrink_buf_snports;     /* Number of sync  ports */
-       unsigned char   shrink_buf_type;        /* Board type 1 = PC/Xi,
-                                                             2 = PC/Xm,
-                                                             3 = PC/Xe
-                                                             4 = MC/Xi
-                                                             5 = COMX/i */
-       unsigned char   shrink_buf_card;        /* Card number */
-
-};
-
 /************************************************************************
  * Structure to get driver status information
  ************************************************************************/
@@ -263,52 +107,6 @@ struct digi_info {
 
 #define        DIGI_GETBD      (('d'<<8) | 249)        /* get board info          */
 
-struct digi_stat {
-       unsigned int    info_chan;              /* Channel number (0 based)  */
-       unsigned int    info_brd;               /* Board number (0 based)  */
-       unsigned int    info_cflag;             /* cflag for channel       */
-       unsigned int    info_iflag;             /* iflag for channel       */
-       unsigned int    info_oflag;             /* oflag for channel       */
-       unsigned int    info_mstat;             /* mstat for channel       */
-       unsigned int    info_tx_data;           /* tx_data for channel       */
-       unsigned int    info_rx_data;           /* rx_data for channel       */
-       unsigned int    info_hflow;             /* hflow for channel       */
-       unsigned int    info_reserved[8];       /* for future expansion    */
-};
-
-#define        DIGI_GETSTAT    (('d'<<8) | 244)        /* get board info          */
-/************************************************************************
- *
- * Structure used with ioctl commands for per-channel information
- *
- ************************************************************************/
-struct digi_ch {
-       unsigned int    info_bdnum;             /* Board number (0 based)  */
-       unsigned int    info_channel;           /* Channel index number    */
-       unsigned int    info_ch_cflag;          /* Channel cflag           */
-       unsigned int    info_ch_iflag;          /* Channel iflag           */
-       unsigned int    info_ch_oflag;          /* Channel oflag           */
-       unsigned int    info_chsize;            /* Channel structure size  */
-       unsigned int    info_sleep_stat;        /* sleep status            */
-       dev_t           info_dev;               /* device number           */
-       unsigned char   info_initstate;         /* Channel init state      */
-       unsigned char   info_running;           /* Channel running state   */
-       int             reserved[8];            /* reserved for future use */
-};
-
-/*
-* This structure is used with the DIGI_FEPCMD ioctl to
-* tell the driver which port to send the command for.
-*/
-struct digi_cmd {
-       int     cmd;
-       int     word;
-       int     ncmds;
-       int     chan; /* channel index (zero based) */
-       int     bdid; /* board index (zero based) */
-};
-
-
 struct digi_getbuffer /* Struct for holding buffer use counts */
 {
        unsigned long tIn;
@@ -328,63 +126,9 @@ struct digi_getcounter {
        unsigned long tbytes;           /* number of bytes transmitted fully */
 };
 
-/*
-*  info_sleep_stat defines
-*/
-#define INFO_RUNWAIT   0x0001
-#define INFO_WOPEN     0x0002
-#define INFO_TTIOW     0x0004
-#define INFO_CH_RWAIT  0x0008
-#define INFO_CH_WEMPTY 0x0010
-#define INFO_CH_WLOW   0x0020
-#define INFO_XXBUF_BUSY 0x0040
-
-#define        DIGI_GETCH      (('d'<<8) | 245)        /* get board info          */
-
-/* Board type definitions */
-
-#define        SUBTYPE         0007
-#define        T_PCXI          0000
-#define T_PCXM         0001
-#define T_PCXE         0002
-#define T_PCXR         0003
-#define T_SP           0004
-#define T_SP_PLUS      0005
-#      define T_HERC   0000
-#      define T_HOU    0001
-#      define T_LON    0002
-#      define T_CHA    0003
-#define FAMILY         0070
-#define T_COMXI                0000
-#define T_PCXX         0010
-#define T_CX           0020
-#define T_EPC          0030
-#define        T_PCLITE        0040
-#define        T_SPXX          0050
-#define        T_AVXX          0060
-#define T_DXB          0070
-#define T_A2K_4_8      0070
-#define BUSTYPE                0700
-#define T_ISABUS       0000
-#define T_MCBUS                0100
-#define        T_EISABUS       0200
-#define        T_PCIBUS        0400
-
 /* Board State Definitions */
-
 #define        BD_RUNNING      0x0
-#define        BD_REASON       0x7f
-#define        BD_NOTFOUND     0x1
-#define        BD_NOIOPORT     0x2
-#define        BD_NOMEM        0x3
-#define        BD_NOBIOS       0x4
 #define        BD_NOFEP        0x5
-#define        BD_FAILED       0x6
-#define BD_ALLOCATED   0x7
-#define BD_TRIBOOT     0x8
-#define        BD_BADKME       0x80
-
-#define DIGI_SPOLL            (('d'<<8) | 254)  /* change poller rate   */
 
 #define DIGI_SETCUSTOMBAUD     _IOW('e', 106, int)     /* Set integer baud rate */
 #define DIGI_GETCUSTOMBAUD     _IOR('e', 107, int)     /* Get integer baud rate */
@@ -396,20 +140,40 @@ struct digi_getcounter {
 
 #define EV_OPU         0x0001          /* !<Output paused by client */
 #define EV_OPS         0x0002          /* !<Output paused by reqular sw flowctrl */
-#define EV_OPX         0x0004          /* !<Output paused by extra sw flowctrl */
-#define EV_OPH         0x0008          /* !<Output paused by hw flowctrl */
-#define EV_OPT         0x0800          /* !<Output paused for RTS Toggle predelay */
-
 #define EV_IPU         0x0010          /* !<Input paused unconditionally by user */
 #define EV_IPS         0x0020          /* !<Input paused by high/low water marks */
-#define EV_IPA         0x0400          /* !<Input paused by pattern alarm module */
-
 #define EV_TXB         0x0040          /* !<Transmit break pending */
-#define EV_TXI         0x0080          /* !<Transmit immediate pending */
-#define EV_TXF         0x0100          /* !<Transmit flowctrl char pending */
-#define EV_RXB         0x0200          /* !<Break received */
 
-#define EV_OPALL       0x080f          /* !<Output pause flags */
-#define EV_IPALL       0x0430          /* !<Input pause flags */
+/*
+ * This structure holds data needed for the intelligent <--> nonintelligent
+ * DPA translation
+ */
+struct ni_info {
+       int board;
+       int channel;
+       int dtr;
+       int rts;
+       int cts;
+       int dsr;
+       int ri;
+       int dcd;
+       int curtx;
+       int currx;
+       unsigned short iflag;
+       unsigned short oflag;
+       unsigned short cflag;
+       unsigned short lflag;
+       unsigned int mstat;
+       unsigned char hflow;
+       unsigned char xmit_stopped;
+       unsigned char recv_stopped;
+       unsigned int baud;
+};
+
+#define T_CLASSIC 0002
+#define T_PCIBUS 0400
+#define T_NEO_EXPRESS 0001
+#define T_NEO 0000
 
+#define TTY_FLIPBUF_SIZE 512
 #endif /* DIGI_H */
diff --git a/drivers/staging/dgnc/dpacompat.h b/drivers/staging/dgnc/dpacompat.h
deleted file mode 100644 (file)
index 33cb394..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2003 Digi International (www.digi.com)
- *      Scott H Kilau <Scott_Kilau at digi dot com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *      NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- */
-
-
-/*
- * This structure holds data needed for the intelligent <--> nonintelligent
- * DPA translation
- */
-struct ni_info {
-       int board;
-       int channel;
-       int dtr;
-       int rts;
-       int cts;
-       int dsr;
-       int ri;
-       int dcd;
-       int curtx;
-       int currx;
-       unsigned short iflag;
-       unsigned short oflag;
-       unsigned short cflag;
-       unsigned short lflag;
-
-       unsigned int mstat;
-       unsigned char hflow;
-
-       unsigned char xmit_stopped;
-       unsigned char recv_stopped;
-
-       unsigned int baud;
-};
-
-#define RW_READ                1
-#define RW_WRITE        2
-#define DIGI_KME        (('e'<<8) | 98)         /* Read/Write Host */
-
-#define SUBTYPE         0007
-#define T_PCXI          0000
-#define T_PCXEM         0001
-#define T_PCXE          0002
-#define T_PCXR          0003
-#define T_SP            0004
-#define T_SP_PLUS       0005
-
-#define T_HERC   0000
-#define T_HOU    0001
-#define T_LON    0002
-#define T_CHA    0003
-
-#define T_NEO   0000
-#define T_NEO_EXPRESS  0001
-#define T_CLASSIC 0002
-
-#define FAMILY          0070
-#define T_COMXI         0000
-#define        T_NI            0000
-#define T_PCXX          0010
-#define T_CX            0020
-#define T_EPC           0030
-#define T_PCLITE        0040
-#define T_SPXX          0050
-#define T_AVXX          0060
-#define T_DXB           0070
-#define T_A2K_4_8       0070
-
-#define BUSTYPE         0700
-#define T_ISABUS        0000
-#define T_MCBUS         0100
-#define T_EISABUS       0200
-#define T_PCIBUS        0400
-
-/* Board State Definitions */
-
-#define BD_RUNNING      0x0
-#define BD_REASON       0x7f
-#define BD_NOTFOUND     0x1
-#define BD_NOIOPORT     0x2
-#define BD_NOMEM        0x3
-#define BD_NOBIOS       0x4
-#define BD_NOFEP        0x5
-#define BD_FAILED       0x6
-#define BD_ALLOCATED    0x7
-#define BD_TRIBOOT      0x8
-#define BD_BADKME       0x80
-
-#define DIGI_AIXON      0x0400          /* Aux flow control in fep */
-
-/* Ioctls needed for dpa operation */
-
-#define DIGI_GETDD      (('d'<<8) | 248)       /* get driver info      */
-#define DIGI_GETBD      (('d'<<8) | 249)       /* get board info       */
-#define DIGI_GET_NI_INFO (('d'<<8) | 250)      /* nonintelligent state snfo */
-
-/* Other special ioctls */
-#define DIGI_TIMERIRQ (('d'<<8) | 251)         /* Enable/disable RS_TIMER use */
-#define DIGI_LOOPBACK (('d'<<8) | 252)         /* Enable/disable UART internal loopback */
index 4be646ce8a12215aac76d6326e2832ee34d26f0f..fbf82bc735cff6c6249ddae0c923b29e640699f8 100644 (file)
@@ -115,7 +115,7 @@ static void _nbu2ss_dump_register(struct nbu2ss_udc *udc)
        pr_info("=== %s()\n", __func__);
 
        if (udc == NULL) {
-               ERR("%s udc == NULL\n", __func__);
+               pr_err("%s udc == NULL\n", __func__);
                return;
        }
 
@@ -201,7 +201,7 @@ static u32 _nbu2ss_get_begin_ram_address(struct nbu2ss_udc *udc)
        u32             num, buf_type;
        u32             data, last_ram_adr, use_ram_size;
 
-       PT_EP_REGS      p_ep_regs;
+       struct ep_regs *p_ep_regs;
 
        last_ram_adr = (D_RAM_SIZE_CTRL / sizeof(u32)) * 2;
        use_ram_size = 0;
@@ -394,7 +394,7 @@ static void _nbu2ss_ep_dma_exit(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
 {
        u32             num;
        u32             data;
-       PT_FC_REGS      preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        if (udc->vbus_active == 0)
                return;         /* VBUS OFF */
@@ -425,7 +425,7 @@ static void _nbu2ss_ep_dma_exit(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
 /* Abort DMA */
 static void _nbu2ss_ep_dma_abort(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
 {
-       PT_FC_REGS      preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        _nbu2ss_bitclr(&preg->EP_DCR[ep->epnum-1].EP_DCR1, DCR1_EPn_REQEN);
        mdelay(DMA_DISABLE_TIME);       /* DCR1_EPn_REQEN Clear */
@@ -443,7 +443,7 @@ static void _nbu2ss_ep_in_end(
 {
        u32             data;
        u32             num;
-       PT_FC_REGS      preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        if (length >= sizeof(u32))
                return;
@@ -567,7 +567,7 @@ static int EP0_out_PIO(struct nbu2ss_udc *udc, u8 *pBuf, u32 length)
        u32             i;
        int             nret   = 0;
        u32             iWordLength = 0;
-       USB_REG_ACCESS *pBuf32 = (USB_REG_ACCESS *)pBuf;
+       union usb_reg_access *pBuf32 = (union usb_reg_access *)pBuf;
 
        /*------------------------------------------------------------*/
        /* Read Length */
@@ -592,8 +592,8 @@ static int EP0_out_OverBytes(struct nbu2ss_udc *udc, u8 *pBuf, u32 length)
 {
        u32             i;
        u32             iReadSize = 0;
-       USB_REG_ACCESS  Temp32;
-       USB_REG_ACCESS *pBuf32 = (USB_REG_ACCESS *)pBuf;
+       union usb_reg_access  Temp32;
+       union usb_reg_access  *pBuf32 = (union usb_reg_access *)pBuf;
 
        if ((0 < length) && (length < sizeof(u32))) {
                Temp32.dw = _nbu2ss_readl(&udc->p_regs->EP0_READ);
@@ -613,7 +613,7 @@ static int EP0_in_PIO(struct nbu2ss_udc *udc, u8 *pBuf, u32 length)
        u32             iMaxLength   = EP0_PACKETSIZE;
        u32             iWordLength  = 0;
        u32             iWriteLength = 0;
-       USB_REG_ACCESS *pBuf32 = (USB_REG_ACCESS *)pBuf;
+       union usb_reg_access  *pBuf32 = (union usb_reg_access *)pBuf;
 
        /*------------------------------------------------------------*/
        /* Transfer Length */
@@ -638,8 +638,8 @@ static int EP0_in_PIO(struct nbu2ss_udc *udc, u8 *pBuf, u32 length)
 static int EP0_in_OverBytes(struct nbu2ss_udc *udc, u8 *pBuf, u32 iRemainSize)
 {
        u32             i;
-       USB_REG_ACCESS Temp32;
-       USB_REG_ACCESS *pBuf32 = (USB_REG_ACCESS *)pBuf;
+       union usb_reg_access  Temp32;
+       union usb_reg_access  *pBuf32 = (union usb_reg_access *)pBuf;
 
        if ((0 < iRemainSize) && (iRemainSize < sizeof(u32))) {
                for (i = 0 ; i < iRemainSize ; i++)
@@ -808,7 +808,7 @@ static int _nbu2ss_ep0_out_transfer(
                return 0;               /* Short Packet Transfer End */
 
        if (req->req.actual > req->req.length) {
-               ERR(" *** Overrun Error\n");
+               dev_err(udc->dev, " *** Overrun Error\n");
                return -EOVERFLOW;
        }
 
@@ -840,7 +840,7 @@ static int _nbu2ss_out_dma(
        u32             burst = 1;
        u32             data;
        int             result = -EINVAL;
-       PT_FC_REGS      preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        if (req->dma_flag)
                return 1;               /* DMA is forwarded */
@@ -900,10 +900,10 @@ static int _nbu2ss_epn_out_pio(
        u32             i;
        u32             data;
        u32             iWordLength;
-       USB_REG_ACCESS  Temp32;
-       USB_REG_ACCESS  *pBuf32;
+       union usb_reg_access    Temp32;
+       union usb_reg_access    *pBuf32;
        int             result = 0;
-       PT_FC_REGS      preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        if (req->dma_flag)
                return 1;               /* DMA is forwarded */
@@ -912,7 +912,7 @@ static int _nbu2ss_epn_out_pio(
                return 0;
 
        pBuffer = (u8 *)req->req.buf;
-       pBuf32 = (USB_REG_ACCESS *)(pBuffer + req->req.actual);
+       pBuf32 = (union usb_reg_access *)(pBuffer + req->req.actual);
 
        iWordLength = length / sizeof(u32);
        if (iWordLength > 0) {
@@ -988,7 +988,7 @@ static int _nbu2ss_epn_out_transfer(
        u32             num;
        u32             iRecvLength;
        int             result = 1;
-       PT_FC_REGS      preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        if (ep->epnum == 0)
                return -EINVAL;
@@ -1026,8 +1026,8 @@ static int _nbu2ss_epn_out_transfer(
        }
 
        if (req->req.actual > req->req.length) {
-               ERR(" *** Overrun Error\n");
-               ERR(" *** actual = %d, length = %d\n",
+               dev_err(udc->dev, " Overrun Error\n");
+               dev_err(udc->dev, " actual = %d, length = %d\n",
                        req->req.actual, req->req.length);
                result = -EOVERFLOW;
        }
@@ -1051,7 +1051,7 @@ static int _nbu2ss_in_dma(
        u32             iWriteLength;
        u32             data;
        int             result = -EINVAL;
-       PT_FC_REGS      preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        if (req->dma_flag)
                return 1;               /* DMA is forwarded */
@@ -1123,17 +1123,17 @@ static int _nbu2ss_epn_in_pio(
        u32             i;
        u32             data;
        u32             iWordLength;
-       USB_REG_ACCESS  Temp32;
-       USB_REG_ACCESS  *pBuf32 = NULL;
+       union usb_reg_access    Temp32;
+       union usb_reg_access    *pBuf32 = NULL;
        int             result = 0;
-       PT_FC_REGS      preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        if (req->dma_flag)
                return 1;               /* DMA is forwarded */
 
        if (length > 0) {
                pBuffer = (u8 *)req->req.buf;
-               pBuf32 = (USB_REG_ACCESS *)(pBuffer + req->req.actual);
+               pBuf32 = (union usb_reg_access *)(pBuffer + req->req.actual);
 
                iWordLength = length / sizeof(u32);
                if (iWordLength > 0) {
@@ -1347,7 +1347,7 @@ static void _nbu2ss_set_endpoint_stall(
        u8              num, epnum;
        u32             data;
        struct nbu2ss_ep *ep;
-       PT_FC_REGS      preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        if ((ep_adrs == 0) || (ep_adrs == 0x80)) {
                if (bstall) {
@@ -1426,7 +1426,7 @@ static void _nbu2ss_set_test_mode(struct nbu2ss_udc *udc, u32 mode)
        if (mode > MAX_TEST_MODE_NUM)
                return;
 
-       pr_info("SET FEATURE : test mode = %d\n", mode);
+       dev_info(udc->dev, "SET FEATURE : test mode = %d\n", mode);
 
        data = _nbu2ss_readl(&udc->p_regs->USB_CONTROL);
        data &= ~TEST_FORCE_ENABLE;
@@ -1454,7 +1454,7 @@ static int _nbu2ss_set_feature_device(
                break;
 
        case USB_DEVICE_TEST_MODE:
-               wIndex = wIndex >> 8;
+               wIndex >>= 8;
                if (wIndex <= MAX_TEST_MODE_NUM)
                        result = 0;
                break;
@@ -1471,7 +1471,7 @@ static int _nbu2ss_get_ep_stall(struct nbu2ss_udc *udc, u8 ep_adrs)
 {
        u8              epnum;
        u32             data = 0, bit_data;
-       PT_FC_REGS      preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        epnum = ep_adrs & ~USB_ENDPOINT_DIR_MASK;
        if (epnum == 0) {
@@ -1566,7 +1566,7 @@ static void _nbu2ss_epn_set_stall(
        u32     regdata;
        int     limit_cnt = 0;
 
-       PT_FC_REGS      preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        if (ep->direct == USB_DIR_IN) {
                for (limit_cnt = 0
@@ -1638,7 +1638,7 @@ static int std_req_get_status(struct nbu2ss_udc *udc)
                _nbu2ss_ep0_in_transfer(udc, &udc->ep[0], &udc->ep0_req);
 
        } else {
-               ERR("*** Error GET_STATUS\n");
+               dev_err(udc->dev, " Error GET_STATUS\n");
        }
 
        return result;
@@ -1671,7 +1671,7 @@ static int std_req_set_address(struct nbu2ss_udc *udc)
        if (wValue != (wValue & 0x007F))
                return -EINVAL;
 
-       wValue = wValue << USB_ADRS_SHIFT;
+       wValue <<= USB_ADRS_SHIFT;
 
        _nbu2ss_writel(&udc->p_regs->USB_ADDRESS, wValue);
        _nbu2ss_create_ep0_packet(udc, udc->ep0_buf, 0);
@@ -1885,8 +1885,8 @@ static inline void _nbu2ss_ep0_int(struct nbu2ss_udc *udc)
                        | STG_END_INT | EP0_OUT_NULL_INT);
 
        if (status == 0) {
-               pr_info("--- %s Not Decode Interrupt\n", __func__);
-               pr_info("--- EP0_STATUS = 0x%08x\n", intr);
+               dev_info(udc->dev, "%s Not Decode Interrupt\n", __func__);
+               dev_info(udc->dev, "EP0_STATUS = 0x%08x\n", intr);
                return;
        }
 
@@ -1994,7 +1994,7 @@ static inline void _nbu2ss_epn_in_int(
        int     result = 0;
        u32     status;
 
-       PT_FC_REGS      preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        if (req->dma_flag)
                return;         /* DMA is forwarded */
@@ -2090,7 +2090,7 @@ static inline void _nbu2ss_epn_out_dma_int(
        u32             num;
        u32             dmacnt, ep_dmacnt;
        u32             mpkt;
-       PT_FC_REGS      preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        num = ep->epnum - 1;
 
@@ -2229,8 +2229,7 @@ static int _nbu2ss_nuke(struct nbu2ss_udc *udc,
                return 0;
 
        /* called with irqs blocked */
-       while (!list_empty(&ep->queue)) {
-               req = list_entry(ep->queue.next, struct nbu2ss_req, queue);
+       list_for_each_entry(req, &ep->queue, queue) {
                _nbu2ss_ep_done(ep, req, status);
        }
 
@@ -2257,11 +2256,6 @@ static int _nbu2ss_pullup(struct nbu2ss_udc *udc, int is_on)
 {
        u32     reg_dt;
 
-       if (!udc) {
-               ERR("%s, bad param\n", __func__);
-               return -EINVAL;
-       }
-
        if (udc->vbus_active == 0)
                return -ESHUTDOWN;
 
@@ -2293,7 +2287,7 @@ static int _nbu2ss_pullup(struct nbu2ss_udc *udc, int is_on)
 /*-------------------------------------------------------------------------*/
 static void _nbu2ss_fifo_flush(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep)
 {
-       PT_FC_REGS      p = udc->p_regs;
+       struct fc_regs  *p = udc->p_regs;
 
        if (udc->vbus_active == 0)
                return;
@@ -2350,7 +2344,7 @@ static int _nbu2ss_enable_controller(struct nbu2ss_udc *udc)
                waitcnt++;
                udelay(1);      /* 1us wait */
                if (waitcnt == EPC_PLL_LOCK_COUNT) {
-                       ERR("*** Reset Cancel failed\n");
+                       dev_err(udc->dev, "*** Reset Cancel failed\n");
                        return -EINVAL;
                }
        };
@@ -2412,7 +2406,7 @@ static inline void _nbu2ss_check_vbus(struct nbu2ss_udc *udc)
                udc->linux_suspended = 0;
 
                _nbu2ss_reset_controller(udc);
-               pr_info(" ----- VBUS OFF\n");
+               dev_info(udc->dev, " ----- VBUS OFF\n");
 
                if (udc->vbus_active == 1) {
                        /* VBUS OFF */
@@ -2438,7 +2432,7 @@ static inline void _nbu2ss_check_vbus(struct nbu2ss_udc *udc)
                if (reg_dt == 0)
                        return;
 
-               pr_info(" ----- VBUS ON\n");
+               dev_info(udc->dev, " ----- VBUS ON\n");
 
                if (udc->linux_suspended)
                        return;
@@ -2536,7 +2530,7 @@ static irqreturn_t _nbu2ss_udc_irq(int irq, void *_udc)
        u32     epnum, int_bit;
 
        struct nbu2ss_udc       *udc = (struct nbu2ss_udc *)_udc;
-       PT_FC_REGS              preg = udc->p_regs;
+       struct fc_regs  *preg = udc->p_regs;
 
        if (gpio_get_value(VBUS_VALUE) == 0) {
                _nbu2ss_writel(&preg->USB_INT_STA, ~USB_INT_STA_RW);
@@ -2612,13 +2606,13 @@ static int nbu2ss_ep_enable(
        struct nbu2ss_udc       *udc;
 
        if ((_ep == NULL) || (desc == NULL)) {
-               ERR(" *** %s, bad param\n", __func__);
+               pr_err(" *** %s, bad param\n", __func__);
                return -EINVAL;
        }
 
        ep = container_of(_ep, struct nbu2ss_ep, ep);
        if ((ep == NULL) || (ep->udc == NULL)) {
-               ERR(" *** %s, ep == NULL !!\n", __func__);
+               pr_err(" *** %s, ep == NULL !!\n", __func__);
                return -EINVAL;
        }
 
@@ -2626,7 +2620,7 @@ static int nbu2ss_ep_enable(
        if ((ep_type == USB_ENDPOINT_XFER_CONTROL)
                || (ep_type == USB_ENDPOINT_XFER_ISOC)) {
 
-               ERR(" *** %s, bat bmAttributes\n", __func__);
+               pr_err(" *** %s, bat bmAttributes\n", __func__);
                return -EINVAL;
        }
 
@@ -2637,7 +2631,7 @@ static int nbu2ss_ep_enable(
        if ((udc->driver == NULL)
                || (udc->gadget.speed == USB_SPEED_UNKNOWN)) {
 
-               ERR(" *** %s, udc !!\n", __func__);
+               dev_err(ep->udc->dev, " *** %s, udc !!\n", __func__);
                return -ESHUTDOWN;
        }
 
@@ -2672,13 +2666,13 @@ static int nbu2ss_ep_disable(struct usb_ep *_ep)
        unsigned long           flags;
 
        if (_ep == NULL) {
-               ERR(" *** %s, bad param\n", __func__);
+               pr_err(" *** %s, bad param\n", __func__);
                return -EINVAL;
        }
 
        ep = container_of(_ep, struct nbu2ss_ep, ep);
        if ((ep == NULL) || (ep->udc == NULL)) {
-               ERR(" *** %s, ep == NULL !!\n", __func__);
+               pr_err("udc: *** %s, ep == NULL !!\n", __func__);
                return -EINVAL;
        }
 
@@ -2742,10 +2736,10 @@ static int nbu2ss_ep_queue(
        /* catch various bogus parameters */
        if ((_ep == NULL) || (_req == NULL)) {
                if (_ep == NULL)
-                       ERR("*** %s --- _ep == NULL\n", __func__);
+                       pr_err("udc: %s --- _ep == NULL\n", __func__);
 
                if (_req == NULL)
-                       ERR("*** %s --- _req == NULL\n", __func__);
+                       pr_err("udc: %s --- _req == NULL\n", __func__);
 
                return -EINVAL;
        }
@@ -2756,13 +2750,13 @@ static int nbu2ss_ep_queue(
             || !list_empty(&req->queue))) {
 
                if (!_req->complete)
-                       ERR("*** %s --- !_req->complete\n", __func__);
+                       pr_err("udc: %s --- !_req->complete\n", __func__);
 
                if (!_req->buf)
-                       ERR("*** %s --- !_req->buf\n", __func__);
+                       pr_err("udc:%s --- !_req->buf\n", __func__);
 
                if (!list_empty(&req->queue))
-                       ERR("*** %s --- !list_empty(&req->queue)\n", __func__);
+                       pr_err("%s --- !list_empty(&req->queue)\n", __func__);
 
                return -EINVAL;
        }
@@ -2773,12 +2767,13 @@ static int nbu2ss_ep_queue(
 /*     INFO("=== %s(ep%d), zero=%d\n", __func__, ep->epnum, _req->zero); */
 
        if (udc->vbus_active == 0) {
-               pr_info("Can't ep_queue (VBUS OFF)\n");
+               dev_info(udc->dev, "Can't ep_queue (VBUS OFF)\n");
                return -ESHUTDOWN;
        }
 
        if (unlikely(!udc->driver)) {
-               ERR("%s, bogus device state %p\n", __func__, udc->driver);
+               dev_err(udc->dev, "%s, bogus device state %p\n", __func__,
+                               udc->driver);
                return -ESHUTDOWN;
        }
 
@@ -2794,7 +2789,7 @@ static int nbu2ss_ep_queue(
                if (ep->virt_buf == NULL)
                        ep->virt_buf = (u8 *)dma_alloc_coherent(
                                NULL, PAGE_SIZE,
-                               &ep->phys_buf, GFP_KERNEL | GFP_DMA);
+                               &ep->phys_buf, GFP_ATOMIC | GFP_DMA);
                if (ep->epnum > 0)  {
                        if (ep->direct == USB_DIR_IN)
                                memcpy(ep->virt_buf, req->req.buf,
@@ -2817,7 +2812,8 @@ static int nbu2ss_ep_queue(
 
                result = _nbu2ss_start_transfer(udc, ep, req, FALSE);
                if (result < 0) {
-                       ERR(" *** %s, result = %d\n", __func__, result);
+                       dev_err(udc->dev, " *** %s, result = %d\n", __func__,
+                                       result);
                        list_del(&req->queue);
                } else if ((ep->epnum > 0) && (ep->direct == USB_DIR_OUT)) {
 #ifdef USE_DMA
@@ -2849,13 +2845,13 @@ static int nbu2ss_ep_dequeue(
 
        /* catch various bogus parameters */
        if ((_ep == NULL) || (_req == NULL)) {
-               /* ERR("%s, bad param(1)\n", __func__); */
+               /* pr_err("%s, bad param(1)\n", __func__); */
                return -EINVAL;
        }
 
        ep = container_of(_ep, struct nbu2ss_ep, ep);
        if (!ep) {
-               ERR("%s, ep == NULL !!\n", __func__);
+               pr_err("%s, ep == NULL !!\n", __func__);
                return -EINVAL;
        }
 
@@ -2895,19 +2891,19 @@ static int nbu2ss_ep_set_halt(struct usb_ep *_ep, int value)
 /*     INFO("=== %s()\n", __func__); */
 
        if (!_ep) {
-               ERR("%s, bad param\n", __func__);
+               pr_err("%s, bad param\n", __func__);
                return -EINVAL;
        }
 
        ep = container_of(_ep, struct nbu2ss_ep, ep);
        if (!ep) {
-               ERR("%s, bad ep\n", __func__);
+               pr_err("%s, bad ep\n", __func__);
                return -EINVAL;
        }
 
        udc = ep->udc;
        if (!udc) {
-               ERR(" *** %s, bad udc\n", __func__);
+               dev_err(ep->udc->dev, " *** %s, bad udc\n", __func__);
                return -EINVAL;
        }
 
@@ -2944,24 +2940,24 @@ static int nbu2ss_ep_fifo_status(struct usb_ep *_ep)
        struct nbu2ss_ep        *ep;
        struct nbu2ss_udc       *udc;
        unsigned long           flags;
-       PT_FC_REGS              preg;
+       struct fc_regs          *preg;
 
 /*     INFO("=== %s()\n", __func__); */
 
        if (!_ep) {
-               ERR("%s, bad param\n", __func__);
+               pr_err("%s, bad param\n", __func__);
                return -EINVAL;
        }
 
        ep = container_of(_ep, struct nbu2ss_ep, ep);
        if (!ep) {
-               ERR("%s, bad ep\n", __func__);
+               pr_err("%s, bad ep\n", __func__);
                return -EINVAL;
        }
 
        udc = ep->udc;
        if (!udc) {
-               ERR("%s, bad udc\n", __func__);
+               dev_err(ep->udc->dev, "%s, bad udc\n", __func__);
                return -EINVAL;
        }
 
@@ -2997,19 +2993,19 @@ static void  nbu2ss_ep_fifo_flush(struct usb_ep *_ep)
 /*     INFO("=== %s()\n", __func__); */
 
        if (!_ep) {
-               ERR("%s, bad param\n", __func__);
+               pr_err("udc: %s, bad param\n", __func__);
                return;
        }
 
        ep = container_of(_ep, struct nbu2ss_ep, ep);
        if (!_ep) {
-               ERR("%s, bad ep\n", __func__);
+               pr_err("udc: %s, bad ep\n", __func__);
                return;
        }
 
        udc = ep->udc;
        if (!udc) {
-               ERR("%s, bad udc\n", __func__);
+               dev_err(ep->udc->dev, "%s, bad udc\n", __func__);
                return;
        }
 
@@ -3053,13 +3049,13 @@ static int nbu2ss_gad_get_frame(struct usb_gadget *pgadget)
 /*     INFO("=== %s()\n", __func__); */
 
        if (pgadget == NULL) {
-               ERR("%s, bad param\n", __func__);
+               pr_err("udc: %s, bad param\n", __func__);
                return -EINVAL;
        }
 
        udc = container_of(pgadget, struct nbu2ss_udc, gadget);
        if (udc == NULL) {
-               ERR("%s, udc == NULL\n", __func__);
+               dev_err(&pgadget->dev, "%s, udc == NULL\n", __func__);
                return -EINVAL;
        }
 
@@ -3083,19 +3079,19 @@ static int nbu2ss_gad_wakeup(struct usb_gadget *pgadget)
 /*     INFO("=== %s()\n", __func__); */
 
        if (pgadget == NULL) {
-               ERR("%s, bad param\n", __func__);
+               pr_err("%s, bad param\n", __func__);
                return -EINVAL;
        }
 
        udc = container_of(pgadget, struct nbu2ss_udc, gadget);
        if (udc == NULL) {
-               ERR("%s, udc == NULL\n", __func__);
+               dev_err(&pgadget->dev, "%s, udc == NULL\n", __func__);
                return -EINVAL;
        }
 
        data = gpio_get_value(VBUS_VALUE);
        if (data == 0) {
-               pr_warn("VBUS LEVEL = %d\n", data);
+               dev_warn(&pgadget->dev, "VBUS LEVEL = %d\n", data);
                return -EINVAL;
        }
 
@@ -3123,7 +3119,7 @@ static int nbu2ss_gad_set_selfpowered(struct usb_gadget *pgadget,
 /*     INFO("=== %s()\n", __func__); */
 
        if (pgadget == NULL) {
-               ERR("%s, bad param\n", __func__);
+               pr_err("%s, bad param\n", __func__);
                return -EINVAL;
        }
 
@@ -3152,7 +3148,7 @@ static int nbu2ss_gad_vbus_draw(struct usb_gadget *pgadget, unsigned mA)
 /*     INFO("=== %s()\n", __func__); */
 
        if (pgadget == NULL) {
-               ERR("%s, bad param\n", __func__);
+               pr_err("%s, bad param\n", __func__);
                return -EINVAL;
        }
 
@@ -3174,7 +3170,7 @@ static int nbu2ss_gad_pullup(struct usb_gadget *pgadget, int is_on)
 /*     INFO("=== %s()\n", __func__); */
 
        if (pgadget == NULL) {
-               ERR("%s, bad param\n", __func__);
+               pr_err("%s, bad param\n", __func__);
                return -EINVAL;
        }
 
@@ -3341,11 +3337,11 @@ static int nbu2ss_drv_probe(struct platform_device *pdev)
                                  0, driver_name, udc);
 
        /* IO Memory */
-       udc->p_regs = (PT_FC_REGS)mmio_base;
+       udc->p_regs = (struct fc_regs *)mmio_base;
 
        /* USB Function Controller Interrupt */
        if (status != 0) {
-               ERR("request_irq(USB_UDC_IRQ_1) failed\n");
+               dev_err(udc->dev, "request_irq(USB_UDC_IRQ_1) failed\n");
                goto cleanup1;
        }
 
@@ -3365,7 +3361,7 @@ static int nbu2ss_drv_probe(struct platform_device *pdev)
                                udc);
 
        if (status != 0) {
-               ERR("request_irq(INT_VBUS) failed\n");
+               dev_err(udc->dev, "request_irq(INT_VBUS) failed\n");
                goto cleanup1;
        }
 
index 202e2dc72bba4d6605eddafbf1e343f3a6bb47fc..c19168f7835461c8bf08902965c4f6119924489f 100644 (file)
 
 /*===========================================================================*/
 /* Struct */
-/*------- T_EP_REGS */
-typedef struct _T_EP_REGS {
+/*------- ep_regs */
+struct ep_regs {
        u32 EP_CONTROL;                 /* EP Control */
        u32 EP_STATUS;                  /* EP Status */
        u32 EP_INT_ENA;                 /* EP Interrupt Enable */
@@ -484,18 +484,18 @@ typedef struct _T_EP_REGS {
        u32 EP_LEN_DCNT;                /* EP Length & DMA count */
        u32 EP_READ;                    /* EP Read */
        u32 EP_WRITE;                   /* EP Write */
-} T_EP_REGS, *PT_EP_REGS;
+};
 
-/*------- T_EP_DCR */
-typedef struct _T_EP_DCR {
+/*------- ep_dcr */
+struct ep_dcr {
        u32 EP_DCR1;                    /* EP_DCR1 */
        u32 EP_DCR2;                    /* EP_DCR2 */
        u32 EP_TADR;                    /* EP_TADR */
        u32 Reserved;                   /* Reserved */
-} T_EP_DCR, *PT_EP_DCR;
+};
 
 /*------- Function Registers */
-typedef struct _T_FC_REGS {
+struct fc_regs {
        u32 USB_CONTROL;                /* (0x0000) USB Control */
        u32 USB_STATUS;                 /* (0x0004) USB Status */
        u32 USB_ADDRESS;                /* (0x0008) USB Address */
@@ -513,7 +513,7 @@ typedef struct _T_FC_REGS {
        u32 EP0_READ;                   /* (0x0038) EP0 Read */
        u32 EP0_WRITE;                  /* (0x003C) EP0 Write */
 
-       T_EP_REGS EP_REGS[REG_EP_NUM];  /* Endpoint Register */
+       struct ep_regs EP_REGS[REG_EP_NUM];     /* Endpoint Register */
 
        u8 Reserved220[0x1000-0x220];   /* (0x0220:0x0FFF) Reserved */
 
@@ -531,11 +531,10 @@ typedef struct _T_FC_REGS {
 
        u8 Reserved1028[0x110-0x28];    /* (0x1028:0x110F) Reserved */
 
-       T_EP_DCR EP_DCR[REG_EP_NUM];    /* */
+       struct ep_dcr EP_DCR[REG_EP_NUM];       /* */
 
        u8 Reserved1200[0x1000-0x200];  /* Reserved */
-
-} __attribute__ ((aligned(32))) T_FC_REGS, *PT_FC_REGS;
+} __aligned(32);
 
 
 
@@ -631,18 +630,17 @@ struct nbu2ss_udc {
 
        u32             curr_config;    /* Current Configuration Number */
 
-       PT_FC_REGS              p_regs;
+       struct fc_regs          *p_regs;
 };
 
 /* USB register access structure */
-typedef volatile union {
+union usb_reg_access {
        struct {
                unsigned char   DATA[4];
        } byte;
        unsigned int            dw;
-} USB_REG_ACCESS;
+};
 
 /*-------------------------------------------------------------------------*/
-#define ERR(stuff...)          printk(KERN_ERR "udc: " stuff)
 
 #endif  /* _LINUX_EMXX_H */
index 995a9101a080829b456d38a10f4b6a9cd9da1ca8..6cf0c58f538bc7a3848042f8a67b48fac1540b69 100644 (file)
@@ -38,6 +38,12 @@ config FB_TFT_HX8353D
        help
          Generic Framebuffer support for HX8353D
 
+config FB_TFT_ILI9163
+       tristate "FB driver for the ILI9163 LCD Controller"
+       depends on FB_TFT
+       help
+         Generic Framebuffer support for ILI9163
+
 config FB_TFT_ILI9320
        tristate "FB driver for the ILI9320 LCD Controller"
        depends on FB_TFT
index e773f0fdcfe81e3a15933358d20b0c430b9da940..9e73beee23f4bd7e114a6ce8860054c113d64b7b 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_FB_TFT_BD663474)    += fb_bd663474.o
 obj-$(CONFIG_FB_TFT_HX8340BN)    += fb_hx8340bn.o
 obj-$(CONFIG_FB_TFT_HX8347D)     += fb_hx8347d.o
 obj-$(CONFIG_FB_TFT_HX8353D)     += fb_hx8353d.o
+obj-$(CONFIG_FB_TFT_ILI9163)     += fb_ili9163.o
 obj-$(CONFIG_FB_TFT_ILI9320)     += fb_ili9320.o
 obj-$(CONFIG_FB_TFT_ILI9325)     += fb_ili9325.o
 obj-$(CONFIG_FB_TFT_ILI9340)     += fb_ili9340.o
index bc89b5805f7bcf15beefc08656e3dcd608af4a39..ba4c74c92e4c3eff8c9b9b9f3c776703ba443d50 100644 (file)
@@ -9,20 +9,20 @@ Development is done on a Raspberry Pi running the Raspbian "wheezy" distribution
 INSTALLATION
   Download kernel sources
 
-  From Linux 3.15  
+  From Linux 3.15
     cd drivers/video/fbdev/fbtft
     git clone https://github.com/notro/fbtft.git
-    
+
     Add to drivers/video/fbdev/Kconfig:   source "drivers/video/fbdev/fbtft/Kconfig"
     Add to drivers/video/fbdev/Makefile:  obj-y += fbtft/
-  
-  Before Linux 3.15  
+
+  Before Linux 3.15
     cd drivers/video
     git clone https://github.com/notro/fbtft.git
-    
+
     Add to drivers/video/Kconfig:   source "drivers/video/fbtft/Kconfig"
     Add to drivers/video/Makefile:  obj-y += fbtft/
-  
+
   Enable driver(s) in menuconfig and build the kernel
 
 
index 9cc7d25cf0e5cbfd3e188c62e92d9893b2f79980..8f5af1db852c2dfcdc05f4701a59c659164b40f1 100644 (file)
@@ -174,7 +174,7 @@ request_gpios_match(struct fbtft_par *par, const struct fbtft_gpio *gpio)
 
 /* This function oses to enter commands
  * first byte - destination controller 0 or 1
- * folowing - commands
+ * following - commands
  */
 static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
 {
@@ -198,8 +198,8 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
 
        if (*buf > 1) {
                va_end(args);
-               dev_err(par->info->device, "%s: Incorrect chip sellect request (%d)\n",
-                       __func__, *buf);
+               dev_err(par->info->device,
+                       "Incorrect chip select request (%d)\n", *buf);
                return;
        }
 
@@ -224,8 +224,8 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
                ret = par->fbtftops.write(par, par->buf, len * (sizeof(u8)));
                if (ret < 0) {
                        va_end(args);
-                       dev_err(par->info->device, "%s: write() failed and returned %d\n",
-                               __func__, ret);
+                       dev_err(par->info->device,
+                               "write() failed and returned %d\n", ret);
                        return;
                }
        }
@@ -278,10 +278,13 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
        int x, y;
        int ret = 0;
 
-       /* buffer to convert RGB565 -> grayscale16 -> Ditherd image 1bpp */
+       /* buffer to convert RGB565 -> grayscale16 -> Dithered image 1bpp */
        signed short *convert_buf = kmalloc(par->info->var.xres *
                par->info->var.yres * sizeof(signed short), GFP_NOIO);
 
+       if (!convert_buf)
+               return -ENOMEM;
+
        fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__);
 
        /* converting to grayscale16 */
@@ -376,8 +379,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
                        ret = par->fbtftops.write(par, buf, len);
                        if (ret < 0)
                                dev_err(par->info->device,
-                                       "%s: write failed and returned: %d\n",
-                                       __func__, ret);
+                                       "write failed and returned: %d\n",
+                                       ret);
                }
                /* right half of display */
                if (addr_win.xe >= par->info->var.xres / 2) {
@@ -390,7 +393,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
                        /* select right side (sc1)
                         * set addr
                         */
-                       write_reg(par, 0x01, (1 << 6));
+                       write_reg(par, 0x01, 1 << 6);
                        write_reg(par, 0x01, (0x17 << 3) | (u8)y);
 
                        /* write bitmap */
@@ -398,8 +401,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
                        par->fbtftops.write(par, buf, len);
                        if (ret < 0)
                                dev_err(par->info->device,
-                                       "%s: write failed and returned: %d\n",
-                                       __func__, ret);
+                                       "write failed and returned: %d\n",
+                                       ret);
                }
        }
        kfree(convert_buf);
index 7e00c609c7fe22f8611a320fe7c313b30ed804e9..17a2162a7e5b10f08ab0d29d88fc7f7f23d5a904 100644 (file)
@@ -47,49 +47,49 @@ static int init_display(struct fbtft_par *par)
        /* Initialization sequence from Lib_UTFT */
 
        /* oscillator start */
-       write_reg(par, 0x000,0x0001);   /*oscillator 0: stop, 1: operation */
+       write_reg(par, 0x000, 0x0001);  /*oscillator 0: stop, 1: operation */
        mdelay(10);
 
        /* Power settings */
-       write_reg(par, 0x100, 0x0000 ); /* power supply setup */
-       write_reg(par, 0x101, 0x0000 );
-       write_reg(par, 0x102, 0x3110 );
-       write_reg(par, 0x103, 0xe200 );
-       write_reg(par, 0x110, 0x009d );
-       write_reg(par, 0x111, 0x0022 );
-       write_reg(par, 0x100, 0x0120 );
-       mdelay( 20 );
-
-       write_reg(par, 0x100, 0x3120 );
-       mdelay( 80 );
+       write_reg(par, 0x100, 0x0000); /* power supply setup */
+       write_reg(par, 0x101, 0x0000);
+       write_reg(par, 0x102, 0x3110);
+       write_reg(par, 0x103, 0xe200);
+       write_reg(par, 0x110, 0x009d);
+       write_reg(par, 0x111, 0x0022);
+       write_reg(par, 0x100, 0x0120);
+       mdelay(20);
+
+       write_reg(par, 0x100, 0x3120);
+       mdelay(80);
        /* Display control */
-       write_reg(par, 0x001, 0x0100 );
-       write_reg(par, 0x002, 0x0000 );
-       write_reg(par, 0x003, 0x1230 );
-       write_reg(par, 0x006, 0x0000 );
-       write_reg(par, 0x007, 0x0101 );
-       write_reg(par, 0x008, 0x0808 );
-       write_reg(par, 0x009, 0x0000 );
-       write_reg(par, 0x00b, 0x0000 );
-       write_reg(par, 0x00c, 0x0000 );
-       write_reg(par, 0x00d, 0x0018 );
+       write_reg(par, 0x001, 0x0100);
+       write_reg(par, 0x002, 0x0000);
+       write_reg(par, 0x003, 0x1230);
+       write_reg(par, 0x006, 0x0000);
+       write_reg(par, 0x007, 0x0101);
+       write_reg(par, 0x008, 0x0808);
+       write_reg(par, 0x009, 0x0000);
+       write_reg(par, 0x00b, 0x0000);
+       write_reg(par, 0x00c, 0x0000);
+       write_reg(par, 0x00d, 0x0018);
        /* LTPS control settings */
-       write_reg(par, 0x012, 0x0000 );
-       write_reg(par, 0x013, 0x0000 );
-       write_reg(par, 0x018, 0x0000 );
-       write_reg(par, 0x019, 0x0000 );
-
-       write_reg(par, 0x203, 0x0000 );
-       write_reg(par, 0x204, 0x0000 );
-
-       write_reg(par, 0x210, 0x0000 );
-       write_reg(par, 0x211, 0x00ef );
-       write_reg(par, 0x212, 0x0000 );
-       write_reg(par, 0x213, 0x013f );
-       write_reg(par, 0x214, 0x0000 );
-       write_reg(par, 0x215, 0x0000 );
-       write_reg(par, 0x216, 0x0000 );
-       write_reg(par, 0x217, 0x0000 );
+       write_reg(par, 0x012, 0x0000);
+       write_reg(par, 0x013, 0x0000);
+       write_reg(par, 0x018, 0x0000);
+       write_reg(par, 0x019, 0x0000);
+
+       write_reg(par, 0x203, 0x0000);
+       write_reg(par, 0x204, 0x0000);
+
+       write_reg(par, 0x210, 0x0000);
+       write_reg(par, 0x211, 0x00ef);
+       write_reg(par, 0x212, 0x0000);
+       write_reg(par, 0x213, 0x013f);
+       write_reg(par, 0x214, 0x0000);
+       write_reg(par, 0x215, 0x0000);
+       write_reg(par, 0x216, 0x0000);
+       write_reg(par, 0x217, 0x0000);
 
        /* Gray scale settings */
        write_reg(par, 0x300, 0x5343);
@@ -104,18 +104,18 @@ static int init_display(struct fbtft_par *par)
        write_reg(par, 0x309, 0x050a);
 
        /* RAM access settings */
-       write_reg(par, 0x400, 0x4027 );
-       write_reg(par, 0x401, 0x0000 );
-       write_reg(par, 0x402, 0x0000 );  /* First screen drive position (1) */
-       write_reg(par, 0x403, 0x013f );  /* First screen drive position (2) */
-       write_reg(par, 0x404, 0x0000 );
-
-       write_reg(par, 0x200, 0x0000 );
-       write_reg(par, 0x201, 0x0000 );
-       write_reg(par, 0x100, 0x7120 );
-       write_reg(par, 0x007, 0x0103 );
-       mdelay( 10 );
-       write_reg(par, 0x007, 0x0113 );
+       write_reg(par, 0x400, 0x4027);
+       write_reg(par, 0x401, 0x0000);
+       write_reg(par, 0x402, 0x0000);  /* First screen drive position (1) */
+       write_reg(par, 0x403, 0x013f);  /* First screen drive position (2) */
+       write_reg(par, 0x404, 0x0000);
+
+       write_reg(par, 0x200, 0x0000);
+       write_reg(par, 0x201, 0x0000);
+       write_reg(par, 0x100, 0x7120);
+       write_reg(par, 0x007, 0x0103);
+       mdelay(10);
+       write_reg(par, 0x007, 0x0113);
 
        return 0;
 }
index 3939502f2c81c3d4afe2077819f0bba1326c43df..54528aa0c0efe2f5ed130c5869e291cb743eb626 100644 (file)
@@ -4,7 +4,7 @@
  * This display uses 9-bit SPI: Data/Command bit + 8 data bits
  * For platforms that doesn't support 9-bit, the driver is capable
  * of emulating this using 8-bit transfer.
- * This is done by transfering eight 9-bit words in 9 bytes.
+ * This is done by transferring eight 9-bit words in 9 bytes.
  *
  * Copyright (C) 2013 Noralf Tronnes
  *
@@ -47,8 +47,6 @@ MODULE_PARM_DESC(emulate, "Force emulation in 9-bit mode");
 
 static int init_display(struct fbtft_par *par)
 {
-       fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
-
        par->fbtftops.reset(par);
 
        /* BTL221722-276L startup sequence, from datasheet */
@@ -108,11 +106,8 @@ static int init_display(struct fbtft_par *par)
        return 0;
 }
 
-void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
+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);
-
        write_reg(par, FBTFT_CASET, 0x00, xs, 0x00, xe);
        write_reg(par, FBTFT_RASET, 0x00, ys, 0x00, ye);
        write_reg(par, FBTFT_RAMWR);
@@ -120,8 +115,6 @@ void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
 
 static int set_var(struct fbtft_par *par)
 {
-       fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
-
        /* MADCTL - Memory data access control */
        /* RGB/BGR can be set with H/W pin SRGB and MADCTL BGR bit */
 #define MY (1 << 7)
@@ -129,7 +122,7 @@ static int set_var(struct fbtft_par *par)
 #define MV (1 << 5)
        switch (par->info->var.rotate) {
        case 0:
-               write_reg(par, 0x36, (par->bgr << 3));
+               write_reg(par, 0x36, par->bgr << 3);
                break;
        case 270:
                write_reg(par, 0x36, MX | MV | (par->bgr << 3));
@@ -156,14 +149,12 @@ static int set_var(struct fbtft_par *par)
 static int set_gamma(struct fbtft_par *par, unsigned long *curves)
 {
        unsigned long mask[] = {
-               0b1111, 0b1111, 0b11111, 0b1111, 0b1111, 0b1111, 0b11111,
-               0b111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b11, 0b11,
-               0b1111, 0b1111, 0b11111, 0b1111, 0b1111, 0b1111, 0b11111,
-               0b111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b0, 0b0 };
+               0x0f, 0x0f, 0x1f, 0x0f, 0x0f, 0x0f, 0x1f, 0x07, 0x07, 0x07,
+               0x07, 0x07, 0x07, 0x03, 0x03, 0x0f, 0x0f, 0x1f, 0x0f, 0x0f,
+               0x0f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00,
+       };
        int i, j;
 
-       fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
-
        /* apply mask */
        for (i = 0; i < par->gamma.num_curves; i++)
                for (j = 0; j < par->gamma.num_values; j++)
index 8139a8f587b75549d4c1297883f109d6f41e07d7..03ae95b4f79e80e174ee4a2c9c733e97fd783be6 100644 (file)
@@ -115,10 +115,9 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
 static int set_gamma(struct fbtft_par *par, unsigned long *curves)
 {
        unsigned long mask[] = {
-               0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111,
-               0b1111111, 0b1111111,
-               0b11111, 0b11111, 0b11111, 0b11111, 0b11111,
-               0b1111};
+               0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x1f, 0x1f,
+               0x1f, 0x1f, 0x1f, 0x0f,
+       };
        int i, j;
        int acc = 0;
 
index c9512dc5f4d349478cac23ead77286a9351904b9..d7f4308e124985a5eaaa0622600bc2ad5d07bdbf 100644 (file)
@@ -84,7 +84,7 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
        /* column address */
        write_reg(par, 0x2a, xs >> 8, xs & 0xff, xe >> 8, xe & 0xff);
 
-       /* row adress */
+       /* Row address */
        write_reg(par, 0x2b, ys >> 8, ys & 0xff, ye >> 8, ye & 0xff);
 
        /* memory write */
@@ -112,7 +112,7 @@ static int set_var(struct fbtft_par *par)
                write_reg(par, 0x36, my | mv | (par->bgr << 3));
                break;
        case 180:
-               write_reg(par, 0x36, (par->bgr << 3));
+               write_reg(par, 0x36, par->bgr << 3);
                break;
        case 90:
                write_reg(par, 0x36, mx | mv | (par->bgr << 3));
diff --git a/drivers/staging/fbtft/fb_ili9163.c b/drivers/staging/fbtft/fb_ili9163.c
new file mode 100644 (file)
index 0000000..ed92a64
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * FB driver for the ILI9163 LCD Controller
+ *
+ * Copyright (C) 2015 Kozhevnikov Anatoly
+ *
+ * Based on ili9325.c by Noralf Tronnes and
+ * .S.U.M.O.T.O.Y. by Max MC Costa (https://github.com/sumotoy/TFT_ILI9163C).
+ *
+ * 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/delay.h>
+
+#include "fbtft.h"
+
+#define DRVNAME                "fb_ili9163"
+#define WIDTH          128
+#define HEIGHT         128
+#define BPP            16
+#define FPS            30
+
+#ifdef GAMMA_ADJ
+#define GAMMA_LEN      15
+#define GAMMA_NUM      1
+#define DEFAULT_GAMMA  "36 29 12 22 1C 15 42 B7 2F 13 12 0A 11 0B 06\n"
+#endif
+
+/* ILI9163C commands */
+#define CMD_NOP                0x00 /* Non operation*/
+#define CMD_SWRESET    0x01 /* Soft Reset */
+#define CMD_SLPIN      0x10 /* Sleep ON */
+#define CMD_SLPOUT     0x11 /* Sleep OFF */
+#define CMD_PTLON      0x12 /* Partial Mode ON */
+#define CMD_NORML      0x13 /* Normal Display ON */
+#define CMD_DINVOF     0x20 /* Display Inversion OFF */
+#define CMD_DINVON     0x21 /* Display Inversion ON */
+#define CMD_GAMMASET   0x26 /* Gamma Set (0x01[1],0x02[2],0x04[3],0x08[4]) */
+#define CMD_DISPOFF    0x28 /* Display OFF */
+#define CMD_DISPON     0x29 /* Display ON */
+#define CMD_IDLEON     0x39 /* Idle Mode ON */
+#define CMD_IDLEOF     0x38 /* Idle Mode OFF */
+#define CMD_CLMADRS    0x2A /* Column Address Set */
+#define CMD_PGEADRS    0x2B /* Page Address Set */
+
+#define CMD_RAMWR      0x2C /* Memory Write */
+#define CMD_RAMRD      0x2E /* Memory Read */
+#define CMD_CLRSPACE   0x2D /* Color Space : 4K/65K/262K */
+#define CMD_PARTAREA   0x30 /* Partial Area */
+#define CMD_VSCLLDEF   0x33 /* Vertical Scroll Definition */
+#define CMD_TEFXLON    0x34 /* Tearing Effect Line ON */
+#define CMD_TEFXLOF    0x35 /* Tearing Effect Line OFF */
+#define CMD_MADCTL     0x36 /* Memory Access Control */
+
+#define CMD_PIXFMT     0x3A /* Interface Pixel Format */
+#define CMD_FRMCTR1    0xB1 /* Frame Rate Control
+                               (In normal mode/Full colors) */
+#define CMD_FRMCTR2    0xB2 /* Frame Rate Control (In Idle mode/8-colors) */
+#define CMD_FRMCTR3    0xB3 /* Frame Rate Control
+                               (In Partial mode/full colors) */
+#define CMD_DINVCTR    0xB4 /* Display Inversion Control */
+#define CMD_RGBBLK     0xB5 /* RGB Interface Blanking Porch setting */
+#define CMD_DFUNCTR    0xB6 /* Display Function set 5 */
+#define CMD_SDRVDIR    0xB7 /* Source Driver Direction Control */
+#define CMD_GDRVDIR    0xB8 /* Gate Driver Direction Control  */
+
+#define CMD_PWCTR1     0xC0 /* Power_Control1 */
+#define CMD_PWCTR2     0xC1 /* Power_Control2 */
+#define CMD_PWCTR3     0xC2 /* Power_Control3 */
+#define CMD_PWCTR4     0xC3 /* Power_Control4 */
+#define CMD_PWCTR5     0xC4 /* Power_Control5 */
+#define CMD_VCOMCTR1   0xC5 /* VCOM_Control 1 */
+#define CMD_VCOMCTR2   0xC6 /* VCOM_Control 2 */
+#define CMD_VCOMOFFS   0xC7 /* VCOM Offset Control */
+#define CMD_PGAMMAC    0xE0 /* Positive Gamma Correction Setting */
+#define CMD_NGAMMAC    0xE1 /* Negative Gamma Correction Setting */
+#define CMD_GAMRSEL    0xF2 /* GAM_R_SEL */
+
+/*
+This display:
+http://www.ebay.com/itm/Replace-Nokia-5110-LCD-1-44-Red-Serial-128X128-SPI-Color-TFT-LCD-Display-Module-/271422122271
+This particular display has a design error! The controller has 3 pins to
+configure to constrain the memory and resolution to a fixed dimension (in
+that case 128x128) but they leaved those pins configured for 128x160 so
+there was several pixel memory addressing problems.
+I solved by setup several parameters that dinamically fix the resolution as
+needit so below the parameters for this display. If you have a strain or a
+correct display (can happen with chinese) you can copy those parameters and
+create setup for different displays.
+*/
+
+#ifdef RED
+#define __OFFSET               32 /*see note 2 - this is the red version */
+#else
+#define __OFFSET               0  /*see note 2 - this is the black version */
+#endif
+
+static int init_display(struct fbtft_par *par)
+{
+       fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
+
+       par->fbtftops.reset(par);
+
+       if (par->gpio.cs != -1)
+               gpio_set_value(par->gpio.cs, 0);  /* Activate chip */
+
+       write_reg(par, CMD_SWRESET); /* software reset */
+       mdelay(500);
+       write_reg(par, CMD_SLPOUT); /* exit sleep */
+       mdelay(5);
+       write_reg(par, CMD_PIXFMT, 0x05); /* Set Color Format 16bit */
+       write_reg(par, CMD_GAMMASET, 0x02); /* default gamma curve 3 */
+#ifdef GAMMA_ADJ
+       write_reg(par, CMD_GAMRSEL, 0x01); /* Enable Gamma adj */
+#endif
+       write_reg(par, CMD_NORML);
+       write_reg(par, CMD_DFUNCTR, 0xff, 0x06);
+       /* Frame Rate Control (In normal mode/Full colors) */
+       write_reg(par, CMD_FRMCTR1, 0x08, 0x02);
+       write_reg(par, CMD_DINVCTR, 0x07); /* display inversion  */
+       /* Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD */
+       write_reg(par, CMD_PWCTR1, 0x0A, 0x02);
+       /* Set BT[2:0] for AVDD & VCL & VGH & VGL  */
+       write_reg(par, CMD_PWCTR2, 0x02);
+       /* Set VMH[6:0] & VML[6:0] for VOMH & VCOML */
+       write_reg(par, CMD_VCOMCTR1, 0x50, 0x63);
+       write_reg(par, CMD_VCOMOFFS, 0);
+
+       write_reg(par, CMD_CLMADRS, 0, 0, 0, WIDTH); /* Set Column Address */
+       write_reg(par, CMD_PGEADRS, 0, 0, 0, HEIGHT); /* Set Page Address */
+
+       write_reg(par, CMD_DISPON); /* display ON */
+       write_reg(par, CMD_RAMWR); /* Memory Write */
+
+       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 0:
+               write_reg(par, CMD_CLMADRS, xs >> 8, xs & 0xff, xe >> 8,
+                               xe & 0xff);
+               write_reg(par, CMD_PGEADRS,
+                               (ys + __OFFSET) >> 8, (ys + __OFFSET) & 0xff,
+                               (ye + __OFFSET) >> 8, (ye + __OFFSET) & 0xff);
+               break;
+       case 90:
+               write_reg(par, CMD_CLMADRS,
+                               (xs + __OFFSET) >> 8, (xs + __OFFSET) & 0xff,
+                               (xe + __OFFSET) >> 8, (xe + __OFFSET) & 0xff);
+               write_reg(par, CMD_PGEADRS, ys >> 8, ys & 0xff, ye >> 8,
+                               ye & 0xff);
+               break;
+       case 180:
+       case 270:
+               write_reg(par, CMD_CLMADRS, xs >> 8, xs & 0xff, xe >> 8,
+                               xe & 0xff);
+               write_reg(par, CMD_PGEADRS, ys >> 8, ys & 0xff, ye >> 8,
+                               ye & 0xff);
+               break;
+       default:
+               par->info->var.rotate = 0; /* Fix incorrect setting */
+       }
+       write_reg(par, CMD_RAMWR); /* Write Data to GRAM mode */
+}
+
+/*
+7) MY:  1(bottom to top),      0(top to bottom)    Row Address Order
+6) MX:  1(R to L),             0(L to R)           Column Address Order
+5) MV:  1(Exchanged),          0(normal)           Row/Column exchange
+4) ML:  1(bottom to top),      0(top to bottom)    Vertical Refresh Order
+3) RGB: 1(BGR),                        0(RGB)              Color Space
+2) MH:  1(R to L),             0(L to R)           Horizontal Refresh Order
+1)
+0)
+
+       MY, MX, MV, ML,RGB, MH, D1, D0
+       0 | 0 | 0 | 0 | 1 | 0 | 0 | 0   //normal
+       1 | 0 | 0 | 0 | 1 | 0 | 0 | 0   //Y-Mirror
+       0 | 1 | 0 | 0 | 1 | 0 | 0 | 0   //X-Mirror
+       1 | 1 | 0 | 0 | 1 | 0 | 0 | 0   //X-Y-Mirror
+       0 | 0 | 1 | 0 | 1 | 0 | 0 | 0   //X-Y Exchange
+       1 | 0 | 1 | 0 | 1 | 0 | 0 | 0   //X-Y Exchange, Y-Mirror
+       0 | 1 | 1 | 0 | 1 | 0 | 0 | 0   //XY exchange
+       1 | 1 | 1 | 0 | 1 | 0 | 0 | 0
+*/
+static int set_var(struct fbtft_par *par)
+{
+       u8 mactrl_data = 0; /* Avoid compiler warning */
+
+       fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
+
+       switch (par->info->var.rotate) {
+       case 0:
+               mactrl_data = 0x08;
+               break;
+       case 180:
+               mactrl_data = 0xC8;
+               break;
+       case 270:
+               mactrl_data = 0xA8;
+               break;
+       case 90:
+               mactrl_data = 0x68;
+               break;
+       }
+
+       /* Colorspcae */
+       if (par->bgr)
+               mactrl_data |= (1 << 2);
+       write_reg(par, CMD_MADCTL, mactrl_data);
+       write_reg(par, CMD_RAMWR); /* Write Data to GRAM mode */
+       return 0;
+}
+
+#ifdef GAMMA_ADJ
+#define CURVE(num, idx)  curves[num*par->gamma.num_values + idx]
+static int gamma_adj(struct fbtft_par *par, unsigned long *curves)
+{
+       unsigned long mask[] = {
+               0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+               0x1f, 0x3f, 0x0f, 0x0f, 0x7f, 0x1f,
+               0x3F, 0x3F, 0x3F, 0x3F, 0x3F};
+       int i, j;
+
+       fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
+
+       for (i = 0; i < GAMMA_NUM; i++)
+               for (j = 0; j < GAMMA_LEN; j++)
+                       CURVE(i, j) &= mask[i*par->gamma.num_values + j];
+
+       write_reg(par, CMD_PGAMMAC,
+                               CURVE(0, 0),
+                               CURVE(0, 1),
+                               CURVE(0, 2),
+                               CURVE(0, 3),
+                               CURVE(0, 4),
+                               CURVE(0, 5),
+                               CURVE(0, 6),
+                               (CURVE(0, 7) << 4) | CURVE(0, 8),
+                               CURVE(0, 9),
+                               CURVE(0, 10),
+                               CURVE(0, 11),
+                               CURVE(0, 12),
+                               CURVE(0, 13),
+                               CURVE(0, 14),
+                               CURVE(0, 15)
+                               );
+
+       write_reg(par, CMD_RAMWR); /* Write Data to GRAM mode */
+
+       return 0;
+}
+#undef CURVE
+#endif
+
+static struct fbtft_display display = {
+       .regwidth = 8,
+       .width = WIDTH,
+       .height = HEIGHT,
+       .bpp = BPP,
+       .fps = FPS,
+#ifdef GAMMA_ADJ
+       .gamma_num = GAMMA_NUM,
+       .gamma_len = GAMMA_LEN,
+       .gamma = DEFAULT_GAMMA,
+#endif
+       .fbtftops = {
+               .init_display = init_display,
+               .set_addr_win = set_addr_win,
+               .set_var = set_var,
+#ifdef GAMMA_ADJ
+               .set_gamma = gamma_adj,
+#endif
+       },
+};
+
+FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9163", &display);
+
+MODULE_ALIAS("spi:" DRVNAME);
+MODULE_ALIAS("platform:" DRVNAME);
+MODULE_ALIAS("spi:ili9163");
+MODULE_ALIAS("platform:ili9163");
+
+MODULE_DESCRIPTION("FB driver for the ILI9163 LCD Controller");
+MODULE_AUTHOR("Kozhevnikov Anatoly");
+MODULE_LICENSE("GPL");
index b26d89368da7ca831192e7c322d5de8cc8424e4c..3a02edd447d4908b585f5e58ad24bd54e47b5a66 100644 (file)
@@ -47,6 +47,7 @@ static unsigned read_devicecode(struct fbtft_par *par)
 static int init_display(struct fbtft_par *par)
 {
        unsigned devcode;
+
        fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
 
        par->fbtftops.reset(par);
@@ -178,10 +179,9 @@ static int set_var(struct fbtft_par *par)
 static int set_gamma(struct fbtft_par *par, unsigned long *curves)
 {
        unsigned long mask[] = {
-               0b11111, 0b11111, 0b111, 0b111, 0b111,
-               0b111, 0b111, 0b111, 0b111, 0b111,
-               0b11111, 0b11111, 0b111, 0b111, 0b111,
-               0b111, 0b111, 0b111, 0b111, 0b111 };
+               0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+               0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+       };
        int i, j;
 
        fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
index 5f88145fac9be568702a0c7d24ad26141cf1c190..19d254e9a4206c729a777cff079318f6ee7cc7e8 100644 (file)
@@ -41,22 +41,22 @@ static unsigned bt = 6; /* VGL=Vci*4 , VGH=Vci*4 */
 module_param(bt, uint, 0);
 MODULE_PARM_DESC(bt, "Sets the factor used in the step-up circuits");
 
-static unsigned vc = 0b011; /* Vci1=Vci*0.80 */
+static unsigned vc = 0x03; /* Vci1=Vci*0.80 */
 module_param(vc, uint, 0);
 MODULE_PARM_DESC(vc,
 "Sets the ratio factor of Vci to generate the reference voltages Vci1");
 
-static unsigned vrh = 0b1101; /* VREG1OUT=Vci*1.85 */
+static unsigned vrh = 0x0d; /* VREG1OUT=Vci*1.85 */
 module_param(vrh, uint, 0);
 MODULE_PARM_DESC(vrh,
 "Set the amplifying rate (1.6 ~ 1.9) of Vci applied to output the VREG1OUT");
 
-static unsigned vdv = 0b10010; /* VCOMH amplitude=VREG1OUT*0.98 */
+static unsigned vdv = 0x12; /* VCOMH amplitude=VREG1OUT*0.98 */
 module_param(vdv, uint, 0);
 MODULE_PARM_DESC(vdv,
 "Select the factor of VREG1OUT to set the amplitude of Vcom");
 
-static unsigned vcm = 0b001010; /* VCOMH=VREG1OUT*0.735 */
+static unsigned vcm = 0x0a; /* VCOMH=VREG1OUT*0.735 */
 module_param(vcm, uint, 0);
 MODULE_PARM_DESC(vcm, "Set the internal VcomH voltage");
 
@@ -108,11 +108,11 @@ static int init_display(struct fbtft_par *par)
        if (par->gpio.cs != -1)
                gpio_set_value(par->gpio.cs, 0);  /* Activate chip */
 
-       bt &= 0b111;
-       vc &= 0b111;
-       vrh &= 0b1111;
-       vdv &= 0b11111;
-       vcm &= 0b111111;
+       bt &= 0x07;
+       vc &= 0x07;
+       vrh &= 0x0f;
+       vdv &= 0x1f;
+       vcm &= 0x3f;
 
        /* Initialization sequence from ILI9325 Application Notes */
 
@@ -137,7 +137,7 @@ static int init_display(struct fbtft_par *par)
        write_reg(par, 0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
        mdelay(200); /* Dis-charge capacitor power voltage */
        write_reg(par, 0x0010, /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-               (1 << 12) | (bt << 8) | (1 << 7) | (0b001 << 4));
+               (1 << 12) | (bt << 8) | (1 << 7) | (0x01 << 4));
        write_reg(par, 0x0011, 0x220 | vc); /* DC1[2:0], DC0[2:0], VC[2:0] */
        mdelay(50); /* Delay 50ms */
        write_reg(par, 0x0012, vrh); /* Internal reference voltage= Vci; */
@@ -233,10 +233,9 @@ static int set_var(struct fbtft_par *par)
 static int set_gamma(struct fbtft_par *par, unsigned long *curves)
 {
        unsigned long mask[] = {
-               0b11111, 0b11111, 0b111, 0b111, 0b111,
-               0b111, 0b111, 0b111, 0b111, 0b111,
-               0b11111, 0b11111, 0b111, 0b111, 0b111,
-               0b111, 0b111, 0b111, 0b111, 0b111 };
+               0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+               0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+       };
        int i, j;
 
        fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
index 985687d94ec238622a29ce78d41051550a4e53b6..0f4a42f89e5e2cfb0ba5a94331d3f582fb2352d7 100644 (file)
@@ -39,12 +39,12 @@ static int init_display(struct fbtft_par *par)
        par->fbtftops.reset(par);
 
        write_reg(par, 0xEF, 0x03, 0x80, 0x02);
-       write_reg(par, 0xCF, 0x00 , 0XC1 , 0X30);
-       write_reg(par, 0xED, 0x64 , 0x03 , 0X12 , 0X81);
-       write_reg(par, 0xE8, 0x85 , 0x00 , 0x78);
-       write_reg(par, 0xCB, 0x39 , 0x2C , 0x00 , 0x34 , 0x02);
+       write_reg(par, 0xCF, 0x00, 0XC1, 0X30);
+       write_reg(par, 0xED, 0x64, 0x03, 0X12, 0X81);
+       write_reg(par, 0xE8, 0x85, 0x00, 0x78);
+       write_reg(par, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02);
        write_reg(par, 0xF7, 0x20);
-       write_reg(par, 0xEA, 0x00 , 0x00);
+       write_reg(par, 0xEA, 0x00, 0x00);
 
        /* Power Control 1 */
        write_reg(par, 0xC0, 0x23);
@@ -104,7 +104,7 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
        /* Column address */
        write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
 
-       /* Row adress */
+       /* Row address */
        write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
 
        /* Memory write */
index 225b2d84371fbcbc0caf05721a9dc5b4215213f4..709492e560b61b64a52502e360d0fdbcebd05ee2 100644 (file)
@@ -4,7 +4,7 @@
  * This display uses 9-bit SPI: Data/Command bit + 8 data bits
  * For platforms that doesn't support 9-bit, the driver is capable
  * of emulating this using 8-bit transfer.
- * This is done by transfering eight 9-bit words in 9 bytes.
+ * This is done by transferring eight 9-bit words in 9 bytes.
  *
  * Copyright (C) 2013 Christian Vogelgsang
  * Based on adafruit22fb.c by Noralf Tronnes
@@ -89,7 +89,7 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
        write_reg(par, 0x2A,
                (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF);
 
-       /* Row adress set */
+       /* Row address set */
        write_reg(par, 0x2B,
                (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF);
 
index 725157a1ac4194a6b0469ca658910ca124fc53ce..8bae09c2d5cecdb1bcf2a8d3f84f3bf4512885c3 100644 (file)
@@ -63,7 +63,7 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
        /* column address */
        write_reg(par, 0x2a, xs >> 8, xs & 0xff, xe >> 8, xe & 0xff);
 
-       /* row adress */
+       /* Row address */
        write_reg(par, 0x2b, ys >> 8, ys & 0xff, ye >> 8, ye & 0xff);
 
        /* memory write */
index 95b89999d32a840b3a4235dfc2427926975c0167..dd4ddca384ad75dd208ec315e374c54b1865603c 100644 (file)
@@ -44,13 +44,13 @@ static int default_init_sequence[] = {
        -1, 0xC5, 0x00, 0x00, 0x00, 0x00,
        /* PGAMCTRL(Positive Gamma Control) */
        -1, 0xE0, 0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98,
-                 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00,
+                 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00,
        /* NGAMCTRL(Negative Gamma Control) */
        -1, 0xE1, 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75,
-                 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00,
+                 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00,
        /* Digital Gamma Control 1 */
        -1, 0xE2, 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75,
-                 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00,
+                 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00,
        /* Sleep OUT */
        -1, 0x11,
        /* Display ON */
@@ -67,7 +67,7 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
        /* Column address */
        write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
 
-       /* Row adress */
+       /* Row address */
        write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
 
        /* Memory write */
index 8b9ebfb49ef8e733c5d1030e9db54f314a68c6b0..15da0ec77513a464b348c1123a7e57629cc7b0a4 100644 (file)
@@ -34,7 +34,7 @@
 #define WIDTH          84
 #define HEIGHT         48
 #define TXBUFLEN       (84*6)
-#define DEFAULT_GAMMA  "40" /* gamma is used to control contrast in this driver */
+#define DEFAULT_GAMMA  "40" /* gamma controls the contrast in this driver */
 
 static unsigned tc;
 module_param(tc, uint, 0);
@@ -51,61 +51,73 @@ static int init_display(struct fbtft_par *par)
 
        par->fbtftops.reset(par);
 
-       /* Function set */
-       write_reg(par, 0x21); /* 5:1  1
-                                2:0  PD - Powerdown control: chip is active
-                                                        1:0  V  - Entry mode: horizontal addressing
-                                                        0:1  H  - Extended instruction set control: extended
-                                                 */
-
-       /* H=1 Temperature control */
-       write_reg(par, 0x04 | (tc & 0x3)); /*
-                                2:1  1
-                                1:x  TC1 - Temperature Coefficient: 0x10
-                                                        0:x  TC0
-                                                 */
-
-       /* H=1 Bias system */
-       write_reg(par, 0x10 | (bs & 0x7)); /*
-                                4:1  1
-                                3:0  0
-                                                        2:x  BS2 - Bias System
-                                                        1:x  BS1
-                                                        0:x  BS0
-                             */
-
-       /* Function set */
-       write_reg(par, 0x22); /* 5:1  1
-                                2:0  PD - Powerdown control: chip is active
-                                                        1:1  V  - Entry mode: vertical addressing
-                                                        0:0  H  - Extended instruction set control: basic
-                                                 */
-
-       /* H=0 Display control */
-       write_reg(par, 0x08 | 4); /*
-                                3:1  1
-                                2:1  D  - DE: 10=normal mode
-                                                        1:0  0
-                                                        0:0  E
-                                                 */
+       /* Function set
+        *
+        * 5:1  1
+        * 2:0  PD - Powerdown control: chip is active
+        * 1:0  V  - Entry mode: horizontal addressing
+        * 0:1  H  - Extended instruction set control: extended
+        */
+       write_reg(par, 0x21);
+
+       /* H=1 Temperature control
+        *
+        * 2:1  1
+        * 1:x  TC1 - Temperature Coefficient: 0x10
+        * 0:x  TC0
+        */
+       write_reg(par, 0x04 | (tc & 0x3));
+
+       /* H=1 Bias system
+        *
+        * 4:1  1
+        * 3:0  0
+        * 2:x  BS2 - Bias System
+        * 1:x  BS1
+        * 0:x  BS0
+        */
+       write_reg(par, 0x10 | (bs & 0x7));
+
+       /* Function set
+        *
+        * 5:1  1
+        * 2:0  PD - Powerdown control: chip is active
+        * 1:1  V  - Entry mode: vertical addressing
+        * 0:0  H  - Extended instruction set control: basic
+        */
+       write_reg(par, 0x22);
+
+       /* H=0 Display control
+        *
+        * 3:1  1
+        * 2:1  D  - DE: 10=normal mode
+        * 1:0  0
+        * 0:0  E
+        */
+       write_reg(par, 0x08 | 4);
 
        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);
-
-       /* H=0 Set X address of RAM */
-       write_reg(par, 0x80); /* 7:1  1
-                                6-0: X[6:0] - 0x00
-                             */
-
-       /* H=0 Set Y address of RAM */
-       write_reg(par, 0x40); /* 7:0  0
-                                6:1  1
-                                2-0: Y[2:0] - 0x0
-                             */
+       fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n",
+                     __func__, xs, ys, xe, ye);
+
+       /* H=0 Set X address of RAM
+        *
+        * 7:1  1
+        * 6-0: X[6:0] - 0x00
+        */
+       write_reg(par, 0x80);
+
+       /* H=0 Set Y address of RAM
+        *
+        * 7:0  0
+        * 6:1  1
+        * 2-0: Y[2:0] - 0x0
+        */
+       write_reg(par, 0x40);
 }
 
 static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
@@ -120,9 +132,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
        for (x = 0; x < 84; x++) {
                for (y = 0; y < 6; y++) {
                        *buf = 0x00;
-                       for (i = 0; i < 8; i++) {
+                       for (i = 0; i < 8; i++)
                                *buf |= (vmem16[(y*8+i)*84+x] ? 1 : 0) << i;
-                       }
                        buf++;
                }
        }
@@ -131,7 +142,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
        gpio_set_value(par->gpio.dc, 1);
        ret = par->fbtftops.write(par, par->txbuf.buf, 6*84);
        if (ret < 0)
-               dev_err(par->info->device, "%s: write failed and returned: %d\n", __func__, ret);
+               dev_err(par->info->device, "write failed and returned: %d\n",
+                       ret);
 
        return ret;
 }
index c323c06344fdeff47f73374e27769b7588959e41..2c4d4dc70c51e5d941f5a0e9d03741bdfb11aa54 100644 (file)
@@ -11,7 +11,7 @@
                                                  *****      *   *
   Date    : 10.06.2014                                      *   *
   Version : V1.13                                          *****
-  Revison : 5
+  Revision : 5
 
 *******************************************************************************
  * This program is free software; you can redistribute it and/or modify
@@ -79,112 +79,112 @@ static int init_display(struct fbtft_par *par)
 
        if ((par->info->var.xres == 320) && (par->info->var.yres == 240)) {
                /* PLL clock frequency */
-               write_reg(par, 0x88 , 0x0A);
-               write_reg(par, 0x89 , 0x02);
+               write_reg(par, 0x88, 0x0A);
+               write_reg(par, 0x89, 0x02);
                mdelay(10);
                /* color deep / MCU Interface */
-               write_reg(par, 0x10 , 0x0C);
+               write_reg(par, 0x10, 0x0C);
                /* pixel clock period  */
-               write_reg(par, 0x04 , 0x03);
+               write_reg(par, 0x04, 0x03);
                mdelay(1);
                /* horizontal settings */
-               write_reg(par, 0x14 , 0x27);
-               write_reg(par, 0x15 , 0x00);
-               write_reg(par, 0x16 , 0x05);
-               write_reg(par, 0x17 , 0x04);
-               write_reg(par, 0x18 , 0x03);
+               write_reg(par, 0x14, 0x27);
+               write_reg(par, 0x15, 0x00);
+               write_reg(par, 0x16, 0x05);
+               write_reg(par, 0x17, 0x04);
+               write_reg(par, 0x18, 0x03);
                /* vertical settings */
-               write_reg(par, 0x19 , 0xEF);
-               write_reg(par, 0x1A , 0x00);
-               write_reg(par, 0x1B , 0x05);
-               write_reg(par, 0x1C , 0x00);
-               write_reg(par, 0x1D , 0x0E);
-               write_reg(par, 0x1E , 0x00);
-               write_reg(par, 0x1F , 0x02);
+               write_reg(par, 0x19, 0xEF);
+               write_reg(par, 0x1A, 0x00);
+               write_reg(par, 0x1B, 0x05);
+               write_reg(par, 0x1C, 0x00);
+               write_reg(par, 0x1D, 0x0E);
+               write_reg(par, 0x1E, 0x00);
+               write_reg(par, 0x1F, 0x02);
        } else if ((par->info->var.xres == 480) && (par->info->var.yres == 272)) {
                /* PLL clock frequency  */
-               write_reg(par, 0x88 , 0x0A);
-               write_reg(par, 0x89 , 0x02);
+               write_reg(par, 0x88, 0x0A);
+               write_reg(par, 0x89, 0x02);
                mdelay(10);
                /* color deep / MCU Interface */
-               write_reg(par, 0x10 , 0x0C);
+               write_reg(par, 0x10, 0x0C);
                /* pixel clock period  */
-               write_reg(par, 0x04 , 0x82);
+               write_reg(par, 0x04, 0x82);
                mdelay(1);
                /* horizontal settings */
-               write_reg(par, 0x14 , 0x3B);
-               write_reg(par, 0x15 , 0x00);
-               write_reg(par, 0x16 , 0x01);
-               write_reg(par, 0x17 , 0x00);
-               write_reg(par, 0x18 , 0x05);
+               write_reg(par, 0x14, 0x3B);
+               write_reg(par, 0x15, 0x00);
+               write_reg(par, 0x16, 0x01);
+               write_reg(par, 0x17, 0x00);
+               write_reg(par, 0x18, 0x05);
                /* vertical settings */
-               write_reg(par, 0x19 , 0x0F);
-               write_reg(par, 0x1A , 0x01);
-               write_reg(par, 0x1B , 0x02);
-               write_reg(par, 0x1C , 0x00);
-               write_reg(par, 0x1D , 0x07);
-               write_reg(par, 0x1E , 0x00);
-               write_reg(par, 0x1F , 0x09);
+               write_reg(par, 0x19, 0x0F);
+               write_reg(par, 0x1A, 0x01);
+               write_reg(par, 0x1B, 0x02);
+               write_reg(par, 0x1C, 0x00);
+               write_reg(par, 0x1D, 0x07);
+               write_reg(par, 0x1E, 0x00);
+               write_reg(par, 0x1F, 0x09);
        } else if ((par->info->var.xres == 640) && (par->info->var.yres == 480)) {
                /* PLL clock frequency */
-               write_reg(par, 0x88 , 0x0B);
-               write_reg(par, 0x89 , 0x02);
+               write_reg(par, 0x88, 0x0B);
+               write_reg(par, 0x89, 0x02);
                mdelay(10);
                /* color deep / MCU Interface */
-               write_reg(par, 0x10 , 0x0C);
+               write_reg(par, 0x10, 0x0C);
                /* pixel clock period */
-               write_reg(par, 0x04 , 0x01);
+               write_reg(par, 0x04, 0x01);
                mdelay(1);
                /* horizontal settings */
-               write_reg(par, 0x14 , 0x4F);
-               write_reg(par, 0x15 , 0x05);
-               write_reg(par, 0x16 , 0x0F);
-               write_reg(par, 0x17 , 0x01);
-               write_reg(par, 0x18 , 0x00);
+               write_reg(par, 0x14, 0x4F);
+               write_reg(par, 0x15, 0x05);
+               write_reg(par, 0x16, 0x0F);
+               write_reg(par, 0x17, 0x01);
+               write_reg(par, 0x18, 0x00);
                /* vertical settings */
-               write_reg(par, 0x19 , 0xDF);
-               write_reg(par, 0x1A , 0x01);
-               write_reg(par, 0x1B , 0x0A);
-               write_reg(par, 0x1C , 0x00);
-               write_reg(par, 0x1D , 0x0E);
-               write_reg(par, 0x1E , 0x00);
-               write_reg(par, 0x1F , 0x01);
+               write_reg(par, 0x19, 0xDF);
+               write_reg(par, 0x1A, 0x01);
+               write_reg(par, 0x1B, 0x0A);
+               write_reg(par, 0x1C, 0x00);
+               write_reg(par, 0x1D, 0x0E);
+               write_reg(par, 0x1E, 0x00);
+               write_reg(par, 0x1F, 0x01);
        } else if ((par->info->var.xres == 800) && (par->info->var.yres == 480)) {
                /* PLL clock frequency */
-               write_reg(par, 0x88 , 0x0B);
-               write_reg(par, 0x89 , 0x02);
+               write_reg(par, 0x88, 0x0B);
+               write_reg(par, 0x89, 0x02);
                mdelay(10);
                /* color deep / MCU Interface */
-               write_reg(par, 0x10 , 0x0C);
+               write_reg(par, 0x10, 0x0C);
                /* pixel clock period */
-               write_reg(par, 0x04 , 0x81);
+               write_reg(par, 0x04, 0x81);
                mdelay(1);
                /* horizontal settings */
-               write_reg(par, 0x14 , 0x63);
-               write_reg(par, 0x15 , 0x03);
-               write_reg(par, 0x16 , 0x03);
-               write_reg(par, 0x17 , 0x02);
-               write_reg(par, 0x18 , 0x00);
+               write_reg(par, 0x14, 0x63);
+               write_reg(par, 0x15, 0x03);
+               write_reg(par, 0x16, 0x03);
+               write_reg(par, 0x17, 0x02);
+               write_reg(par, 0x18, 0x00);
                /* vertical settings */
-               write_reg(par, 0x19 , 0xDF);
-               write_reg(par, 0x1A , 0x01);
-               write_reg(par, 0x1B , 0x14);
-               write_reg(par, 0x1C , 0x00);
-               write_reg(par, 0x1D , 0x06);
-               write_reg(par, 0x1E , 0x00);
-               write_reg(par, 0x1F , 0x01);
+               write_reg(par, 0x19, 0xDF);
+               write_reg(par, 0x1A, 0x01);
+               write_reg(par, 0x1B, 0x14);
+               write_reg(par, 0x1C, 0x00);
+               write_reg(par, 0x1D, 0x06);
+               write_reg(par, 0x1E, 0x00);
+               write_reg(par, 0x1F, 0x01);
        } else {
                dev_err(par->info->device, "display size is not supported!!");
                return -1;
        }
 
        /* PWM clock */
-       write_reg(par, 0x8a , 0x81);
-       write_reg(par, 0x8b , 0xFF);
+       write_reg(par, 0x8a, 0x81);
+       write_reg(par, 0x8b, 0xFF);
        mdelay(10);
 
        /* Display ON */
-       write_reg(par, 0x01 , 0x80);
+       write_reg(par, 0x01, 0x80);
        mdelay(10);
 
        return 0;
@@ -196,14 +196,14 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
                "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye);
 
        /* Set_Active_Window */
-       write_reg(par, 0x30 , xs & 0x00FF);
-       write_reg(par, 0x31 , (xs & 0xFF00) >> 8);
-       write_reg(par, 0x32 , ys & 0x00FF);
-       write_reg(par, 0x33 , (ys & 0xFF00) >> 8);
-       write_reg(par, 0x34 , (xs+xe) & 0x00FF);
-       write_reg(par, 0x35 , ((xs+xe) & 0xFF00) >> 8);
-       write_reg(par, 0x36 , (ys+ye) & 0x00FF);
-       write_reg(par, 0x37 , ((ys+ye) & 0xFF00) >> 8);
+       write_reg(par, 0x30, xs & 0x00FF);
+       write_reg(par, 0x31, (xs & 0xFF00) >> 8);
+       write_reg(par, 0x32, ys & 0x00FF);
+       write_reg(par, 0x33, (ys & 0xFF00) >> 8);
+       write_reg(par, 0x34, (xs+xe) & 0x00FF);
+       write_reg(par, 0x35, ((xs+xe) & 0xFF00) >> 8);
+       write_reg(par, 0x36, (ys+ye) & 0x00FF);
+       write_reg(par, 0x37, ((ys+ye) & 0xFF00) >> 8);
 
        /* Set_Memory_Write_Cursor */
        write_reg(par, 0x46,  xs & 0xff);
@@ -238,8 +238,8 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
        ret = par->fbtftops.write(par, par->buf, 2);
        if (ret < 0) {
                va_end(args);
-               dev_err(par->info->device, "%s: write() failed and returned %dn",
-                       __func__, ret);
+               dev_err(par->info->device, "write() failed and returned %dn",
+                       ret);
                return;
        }
        len--;
@@ -256,8 +256,8 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
                ret = par->fbtftops.write(par, par->buf, len + 1);
                if (ret < 0) {
                        va_end(args);
-                       dev_err(par->info->device, "%s: write() failed and returned %dn",
-                               __func__, ret);
+                       dev_err(par->info->device,
+                               "write() failed and returned %dn", ret);
                        return;
                }
        }
index e412a42443e5d2436e7bc9ecad190907fbcddbdb..f3302525ec0092992e2dc872de7cd143890f0f74 100644 (file)
@@ -108,7 +108,7 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
        /* Column address */
        write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
 
-       /* Row adress */
+       /* Row address */
        write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
 
        /* Memory write */
@@ -136,7 +136,7 @@ static int set_var(struct fbtft_par *par)
                write_reg(par, 0x36, MY | MV | (par->bgr << 3));
                break;
        case 180:
-               write_reg(par, 0x36, (par->bgr << 3));
+               write_reg(par, 0x36, par->bgr << 3);
                break;
        case 90:
                write_reg(par, 0x36, MX | MV | (par->bgr << 3));
index 1ef8c1ad827e249260a99a841129dd381666fffa..2e1b72ad54aa95e408136002442ac3584052df1a 100644 (file)
@@ -143,12 +143,10 @@ static int set_var(struct fbtft_par *par)
 static int set_gamma(struct fbtft_par *par, unsigned long *curves)
 {
        unsigned long mask[] = {
-               0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 
-               0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111,
-               0b11111, 0b11111,
-               0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111,
-               0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111,
-               0b11111, 0b11111 };
+               0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+               0x3f, 0x3f, 0x1f, 0x1f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+               0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x1f, 0x1f,
+       };
        int i, j;
 
        fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
index ef46fbca27004c89b03f4e8a3f5ea5938dd48a4e..17a77e0614987d5ad021dbedab11dce48d6e258b 100644 (file)
@@ -126,16 +126,16 @@ static int set_var(struct fbtft_par *par)
 
        switch (par->info->var.rotate) {
        case 0:
-               write_reg(par, 0x11, reg11 | 0b110000);
+               write_reg(par, 0x11, reg11 | 0x30);
                break;
        case 270:
-               write_reg(par, 0x11, reg11 | 0b101000);
+               write_reg(par, 0x11, reg11 | 0x28);
                break;
        case 180:
-               write_reg(par, 0x11, reg11 | 0b000000);
+               write_reg(par, 0x11, reg11 | 0x00);
                break;
        case 90:
-               write_reg(par, 0x11, reg11 | 0b011000);
+               write_reg(par, 0x11, reg11 | 0x18);
                break;
        }
 
@@ -151,10 +151,9 @@ static int set_var(struct fbtft_par *par)
 static int set_gamma(struct fbtft_par *par, unsigned long *curves)
 {
        unsigned long mask[] = {
-               0b11111, 0b11111, 0b111, 0b111, 0b111,
-               0b111, 0b111, 0b111, 0b111, 0b111,
-               0b11111, 0b11111, 0b111, 0b111, 0b111,
-               0b111, 0b111, 0b111, 0b111, 0b111 };
+               0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+               0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+       };
        int i, j;
 
        fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
index 5ea195b0de1b3de8ec39e0ef71ad73d92b6ca7ca..15ee44dd130bddfd282849631964b2cf23ea2d3c 100644 (file)
@@ -193,8 +193,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
        ret = par->fbtftops.write(par, par->txbuf.buf,
                                par->info->var.xres*par->info->var.yres/8);
        if (ret < 0)
-               dev_err(par->info->device,
-                       "%s: write failed and returned: %d\n", __func__, ret);
+               dev_err(par->info->device, "write failed and returned: %d\n",
+                       ret);
 
        return ret;
 }
index da7464f90e37c93849b05224daeb494c61cb846b..5bb741046c85264104c4160f17d2b2be3d3d31e5 100644 (file)
@@ -29,24 +29,24 @@ static int init_display(struct fbtft_par *par)
 
        write_reg(par, 0xae); /* Display Off */
        write_reg(par, 0xa0, 0x70 | (par->bgr << 2)); /* Set Colour Depth */
-       write_reg(par, 0x72); // RGB colour
+       write_reg(par, 0x72); /* RGB colour */
        write_reg(par, 0xa1, 0x00); /* Set Display Start Line */
        write_reg(par, 0xa2, 0x00); /* Set Display Offset */
        write_reg(par, 0xa4); /* NORMALDISPLAY */
-       write_reg(par, 0xa8, 0x3f); // Set multiplex
-       write_reg(par, 0xad, 0x8e); // Set master
-       // write_reg(par, 0xb0, 0x0b); // Set power mode
-       write_reg(par, 0xb1, 0x31); // Precharge
-       write_reg(par, 0xb3, 0xf0); // Clock div
-       write_reg(par, 0x8a, 0x64); // Precharge A
-       write_reg(par, 0x8b, 0x78); // Precharge B
-       write_reg(par, 0x8c, 0x64); // Precharge C
-       write_reg(par, 0xbb, 0x3a); // Precharge level
-       write_reg(par, 0xbe, 0x3e); // vcomh
-       write_reg(par, 0x87, 0x06); // Master current
-       write_reg(par, 0x81, 0x91); // Contrast A
-       write_reg(par, 0x82, 0x50); // Contrast B
-       write_reg(par, 0x83, 0x7d); // Contrast C
+       write_reg(par, 0xa8, 0x3f); /* Set multiplex */
+       write_reg(par, 0xad, 0x8e); /* Set master */
+       /* write_reg(par, 0xb0, 0x0b);  Set power mode */
+       write_reg(par, 0xb1, 0x31); /* Precharge */
+       write_reg(par, 0xb3, 0xf0); /* Clock div */
+       write_reg(par, 0x8a, 0x64); /* Precharge A */
+       write_reg(par, 0x8b, 0x78); /* Precharge B */
+       write_reg(par, 0x8c, 0x64); /* Precharge C */
+       write_reg(par, 0xbb, 0x3a); /* Precharge level */
+       write_reg(par, 0xbe, 0x3e); /* vcomh */
+       write_reg(par, 0x87, 0x06); /* Master current */
+       write_reg(par, 0x81, 0x91); /* Contrast A */
+       write_reg(par, 0x82, 0x50); /* Contrast B */
+       write_reg(par, 0x83, 0x7d); /* Contrast C */
        write_reg(par, 0xaf); /* Set Sleep Mode Display On */
 
        return 0;
@@ -69,9 +69,8 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
 
        if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) {
                va_start(args, len);
-               for (i = 0; i < len; i++) {
+               for (i = 0; i < len; i++)
                        buf[i] = (u8)va_arg(args, unsigned int);
-               }
                va_end(args);
                fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, par->info->device, u8, buf, len, "%s: ", __func__);
        }
@@ -84,20 +83,21 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
        ret = par->fbtftops.write(par, par->buf, sizeof(u8));
        if (ret < 0) {
                va_end(args);
-               dev_err(par->info->device, "%s: write() failed and returned %d\n", __func__, ret);
+               dev_err(par->info->device,
+                       "write() failed and returned %d\n", ret);
                return;
        }
        len--;
 
        if (len) {
                i = len;
-               while (i--) {
+               while (i--)
                        *buf++ = (u8)va_arg(args, unsigned int);
-               }
                ret = par->fbtftops.write(par, par->buf, len * (sizeof(u8)));
                if (ret < 0) {
                        va_end(args);
-                       dev_err(par->info->device, "%s: write() failed and returned %d\n", __func__, ret);
+                       dev_err(par->info->device,
+                               "write() failed and returned %d\n", ret);
                        return;
                }
        }
index 062d98660f6378eafde788880b547424093037ec..9bcd7a0aeed4b035caac6d00a0e2dc195fc4c834 100644 (file)
@@ -72,6 +72,7 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
 static int set_var(struct fbtft_par *par)
 {
        unsigned remap;
+
        fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
 
        if (par->fbtftops.init_display != init_display) {
@@ -86,16 +87,16 @@ static int set_var(struct fbtft_par *par)
 
        switch (par->info->var.rotate) {
        case 0:
-               write_reg(par, 0xA0, remap | 0b00 | 1<<4);
+               write_reg(par, 0xA0, remap | 0x00 | 1<<4);
                break;
        case 270:
-               write_reg(par, 0xA0, remap | 0b11 | 1<<4);
+               write_reg(par, 0xA0, remap | 0x03 | 1<<4);
                break;
        case 180:
-               write_reg(par, 0xA0, remap | 0b10);
+               write_reg(par, 0xA0, remap | 0x02);
                break;
        case 90:
-               write_reg(par, 0xA0, remap | 0b01);
+               write_reg(par, 0xA0, remap | 0x01);
                break;
        }
 
@@ -217,12 +218,8 @@ static void register_onboard_backlight(struct fbtft_par *par)
 
        bl_ops = devm_kzalloc(par->info->device, sizeof(struct backlight_ops),
                                GFP_KERNEL);
-       if (!bl_ops) {
-               dev_err(par->info->device,
-                       "%s: could not allocate memory for backlight operations.\n",
-                       __func__);
+       if (!bl_ops)
                return;
-       }
 
        bl_ops->update_status = update_onboard_backlight;
        bl_props.type = BACKLIGHT_RAW;
index b63aa38e51cf3629ca50d26e1b87c237ff2697bd..9d874308447e05b0c9f15fa4b34d903c170cf859 100644 (file)
 
 static int default_init_sequence[] = {
        /* SWRESET - Software reset */
-       -1, 0x01,                                
+       -1, 0x01,
        -2, 150,                               /* delay */
 
        /* SLPOUT - Sleep out & booster on */
-       -1, 0x11,                          
+       -1, 0x11,
        -2, 500,                               /* delay */
 
        /* FRMCTR1 - frame rate control: normal mode
             frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) */
-       -1, 0xB1, 0x01, 0x2C, 0x2D, 
+       -1, 0xB1, 0x01, 0x2C, 0x2D,
 
        /* FRMCTR2 - frame rate control: idle mode
             frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) */
-       -1, 0xB2, 0x01, 0x2C, 0x2D, 
+       -1, 0xB2, 0x01, 0x2C, 0x2D,
 
        /* FRMCTR3 - frame rate control - partial mode
             dot inversion mode, line inversion mode */
@@ -68,7 +68,7 @@ static int default_init_sequence[] = {
 
        /* PWCTR4 - Power Control
             BCLK/2, Opamp current small & Medium low */
-       -1, 0xC3,0x8A,0x2A,
+       -1, 0xC3, 0x8A, 0x2A,
 
        /* PWCTR5 - Power Control */
        -1, 0xC4, 0x8A, 0xEE,
@@ -91,7 +91,7 @@ static int default_init_sequence[] = {
        -2, 10,                               /* delay */
 
        /* end marker */
-       -3                                  
+       -3
 };
 
 static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
@@ -102,7 +102,7 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
        /* Column address */
        write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
 
-       /* Row adress */
+       /* Row address */
        write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
 
        /* Memory write */
@@ -130,7 +130,7 @@ static int set_var(struct fbtft_par *par)
                write_reg(par, 0x36, MY | MV | (par->bgr << 3));
                break;
        case 180:
-               write_reg(par, 0x36, (par->bgr << 3));
+               write_reg(par, 0x36, par->bgr << 3);
                break;
        case 90:
                write_reg(par, 0x36, MX | MV | (par->bgr << 3));
@@ -148,21 +148,21 @@ static int set_var(struct fbtft_par *par)
 #define CURVE(num, idx)  curves[num*par->gamma.num_values + idx]
 static int set_gamma(struct fbtft_par *par, unsigned long *curves)
 {
-       int i,j;
+       int i, j;
 
        fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
 
        /* apply mask */
        for (i = 0; i < par->gamma.num_curves; i++)
                for (j = 0; j < par->gamma.num_values; j++)
-                       CURVE(i,j) &= 0b111111;
+                       CURVE(i, j) &= 0x3f;
 
        for (i = 0; i < par->gamma.num_curves; i++)
                write_reg(par, 0xE0 + i,
                        CURVE(i, 0), CURVE(i, 1), CURVE(i, 2), CURVE(i, 3),
                        CURVE(i, 4), CURVE(i, 5), CURVE(i, 6), CURVE(i, 7),
                        CURVE(i, 8), CURVE(i, 9), CURVE(i, 10), CURVE(i, 11),
-                       CURVE(i, 12), CURVE(i, 13), CURVE(i, 14), CURVE(i,15));
+                       CURVE(i, 12), CURVE(i, 13), CURVE(i, 14), CURVE(i, 15));
 
        return 0;
 }
index ca98bfb5c7df907454c75ad443ba29c37c377097..c0b1a337fafdb525938dcb47d78441665752b6b9 100644 (file)
@@ -70,7 +70,7 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
        /* Column address */
        write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
 
-       /* Row adress */
+       /* Row address */
        write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
 
        /* Memory write */
index 8738c7a7bfda31119d0275e4f74e3f151d1b7598..fcd38bf2ed79f9f66f37a1fa2811ebfb89c4586e 100644 (file)
@@ -127,7 +127,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
                ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH);
                if (ret < 0) {
                        dev_err(par->info->device,
-                               "%s: write failed and returned: %d\n", __func__, ret);
+                               "write failed and returned: %d\n", ret);
                        break;
                }
        }
index d70ac524278c79d88732cc2349ba5e14304309d8..26d669b57916c659c09c88f8cd1ac6fc0381f02c 100644 (file)
@@ -183,7 +183,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
        }
 
        if (ret < 0)
-               dev_err(par->info->device, "%s: write failed and returned: %d\n", __func__, ret);
+               dev_err(par->info->device, "write failed and returned: %d\n",
+                       ret);
 
        return ret;
 }
index fff57b330ba20711359d37c1c77ea51e36bbca0d..176c2106d7245e2e37804393a2d35e3a981c4270 100644 (file)
@@ -47,84 +47,84 @@ static int init_display(struct fbtft_par *par)
        /* Initialization sequence from Lib_UTFT */
 
        /* register reset */
-       write_reg(par, 0x0003,0x0001);  /* Soft reset */
+       write_reg(par, 0x0003, 0x0001); /* Soft reset */
 
        /* oscillator start */
-       write_reg(par, 0x003A,0x0001);  /*Oscillator 0: stop, 1: operation */
+       write_reg(par, 0x003A, 0x0001); /*Oscillator 0: stop, 1: operation */
        udelay(100);
 
        /* y-setting */
-       write_reg(par, 0x0024,0x007B);  /* amplitude setting */
+       write_reg(par, 0x0024, 0x007B); /* amplitude setting */
        udelay(10);
-       write_reg(par, 0x0025,0x003B);  /* amplitude setting */
-       write_reg(par, 0x0026,0x0034);  /* amplitude setting */
+       write_reg(par, 0x0025, 0x003B); /* amplitude setting */
+       write_reg(par, 0x0026, 0x0034); /* amplitude setting */
        udelay(10);
-       write_reg(par, 0x0027,0x0004);  /* amplitude setting */
-       write_reg(par, 0x0052,0x0025);  /* circuit setting 1 */
+       write_reg(par, 0x0027, 0x0004); /* amplitude setting */
+       write_reg(par, 0x0052, 0x0025); /* circuit setting 1 */
        udelay(10);
-       write_reg(par, 0x0053,0x0033);  /* circuit setting 2 */
-       write_reg(par, 0x0061,0x001C);  /* adjustment V10 positive polarity */
+       write_reg(par, 0x0053, 0x0033); /* circuit setting 2 */
+       write_reg(par, 0x0061, 0x001C); /* adjustment V10 positive polarity */
        udelay(10);
-       write_reg(par, 0x0062,0x002C);  /* adjustment V9 negative polarity */
-       write_reg(par, 0x0063,0x0022);  /* adjustment V34 positive polarity */
+       write_reg(par, 0x0062, 0x002C); /* adjustment V9 negative polarity */
+       write_reg(par, 0x0063, 0x0022); /* adjustment V34 positive polarity */
        udelay(10);
-       write_reg(par, 0x0064,0x0027);  /* adjustment V31 negative polarity */
+       write_reg(par, 0x0064, 0x0027); /* adjustment V31 negative polarity */
        udelay(10);
-       write_reg(par, 0x0065,0x0014);  /* adjustment V61 negative polarity */
+       write_reg(par, 0x0065, 0x0014); /* adjustment V61 negative polarity */
        udelay(10);
-       write_reg(par, 0x0066,0x0010);  /* adjustment V61 negative polarity */
-       
+       write_reg(par, 0x0066, 0x0010); /* adjustment V61 negative polarity */
+
        /* Basical clock for 1 line (BASECOUNT[7:0]) number specified */
-       write_reg(par, 0x002E,0x002D);
-       
+       write_reg(par, 0x002E, 0x002D);
+
        /* Power supply setting */
-       write_reg(par, 0x0019,0x0000);  /* DC/DC output setting */
+       write_reg(par, 0x0019, 0x0000); /* DC/DC output setting */
        udelay(200);
-       write_reg(par, 0x001A,0x1000);  /* DC/DC frequency setting */
-       write_reg(par, 0x001B,0x0023);  /* DC/DC rising setting */
-       write_reg(par, 0x001C,0x0C01);  /* Regulator voltage setting */
-       write_reg(par, 0x001D,0x0000);  /* Regulator current setting */
-       write_reg(par, 0x001E,0x0009);  /* VCOM output setting */
-       write_reg(par, 0x001F,0x0035);  /* VCOM amplitude setting */
-       write_reg(par, 0x0020,0x0015);  /* VCOMM cencter setting */
-       write_reg(par, 0x0018,0x1E7B);  /* DC/DC operation setting */
+       write_reg(par, 0x001A, 0x1000); /* DC/DC frequency setting */
+       write_reg(par, 0x001B, 0x0023); /* DC/DC rising setting */
+       write_reg(par, 0x001C, 0x0C01); /* Regulator voltage setting */
+       write_reg(par, 0x001D, 0x0000); /* Regulator current setting */
+       write_reg(par, 0x001E, 0x0009); /* VCOM output setting */
+       write_reg(par, 0x001F, 0x0035); /* VCOM amplitude setting */
+       write_reg(par, 0x0020, 0x0015); /* VCOMM cencter setting */
+       write_reg(par, 0x0018, 0x1E7B); /* DC/DC operation setting */
 
        /* windows setting */
-       write_reg(par, 0x0008,0x0000);  /* Minimum X address */
-       write_reg(par, 0x0009,0x00EF);  /* Maximum X address */
-       write_reg(par, 0x000a,0x0000);  /* Minimum Y address */
-       write_reg(par, 0x000b,0x013F);  /* Maximum Y address */
+       write_reg(par, 0x0008, 0x0000); /* Minimum X address */
+       write_reg(par, 0x0009, 0x00EF); /* Maximum X address */
+       write_reg(par, 0x000a, 0x0000); /* Minimum Y address */
+       write_reg(par, 0x000b, 0x013F); /* Maximum Y address */
 
        /* LCD display area setting */
-       write_reg(par, 0x0029,0x0000);  /* [LCDSIZE]  X MIN. size set */
-       write_reg(par, 0x002A,0x0000);  /* [LCDSIZE]  Y MIN. size set */
-       write_reg(par, 0x002B,0x00EF);  /* [LCDSIZE]  X MAX. size set */
-       write_reg(par, 0x002C,0x013F);  /* [LCDSIZE]  Y MAX. size set */
+       write_reg(par, 0x0029, 0x0000); /* [LCDSIZE]  X MIN. size set */
+       write_reg(par, 0x002A, 0x0000); /* [LCDSIZE]  Y MIN. size set */
+       write_reg(par, 0x002B, 0x00EF); /* [LCDSIZE]  X MAX. size set */
+       write_reg(par, 0x002C, 0x013F); /* [LCDSIZE]  Y MAX. size set */
 
        /* Gate scan setting */
-       write_reg(par, 0x0032,0x0002);
-       
+       write_reg(par, 0x0032, 0x0002);
+
        /* n line inversion line number */
-       write_reg(par, 0x0033,0x0000);
+       write_reg(par, 0x0033, 0x0000);
 
        /* Line inversion/frame inversion/interlace setting */
-       write_reg(par, 0x0037,0x0000);
-       
+       write_reg(par, 0x0037, 0x0000);
+
        /* Gate scan operation setting register */
-       write_reg(par, 0x003B,0x0001);
-       
+       write_reg(par, 0x003B, 0x0001);
+
        /* Color mode */
        /*GS = 0: 260-k color (64 gray scale), GS = 1: 8 color (2 gray scale) */
-       write_reg(par, 0x0004,0x0000);
+       write_reg(par, 0x0004, 0x0000);
 
        /* RAM control register */
-       write_reg(par, 0x0005,0x0000);  /*Window access 00:Normal, 10:Window */
+       write_reg(par, 0x0005, 0x0000); /*Window access 00:Normal, 10:Window */
 
        /* Display setting register 2 */
-       write_reg(par, 0x0001,0x0000);
+       write_reg(par, 0x0001, 0x0000);
 
        /* display setting */
-       write_reg(par, 0x0000,0x0000);  /* display on */
+       write_reg(par, 0x0000, 0x0000); /* display on */
 
        return 0;
 }
index 975b579359f367af94c10b7976ccb3dcfba5796c..88fb2c0132d5257542c9e75964c47f164c5e36f5 100644 (file)
@@ -65,7 +65,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
        ret = par->fbtftops.write(par, par->buf, len);
        if (ret < 0) {
                dev_err(par->info->device,
-                       "%s: write() failed and returned %d\n", __func__, ret);
+                       "write() failed and returned %d\n", ret);
                return;
        }
 }
index b3cddb0b3d698a9d606ece34e49288348f9e769b..52af9cbbc2a688c8bb8d18e918ba1469821928c9 100644 (file)
@@ -111,7 +111,7 @@ void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...)
        ret = par->fbtftops.write(par, par->buf, (len + pad) * sizeof(u16));
        if (ret < 0) {
                dev_err(par->info->device,
-                       "%s: write() failed and returned %d\n", __func__, ret);
+                       "write() failed and returned %d\n", ret);
                return;
        }
 }
index 37dcf7eb191a22c5c3b6abb14040d76ae9bcd689..53b748be2712479368e20c75d0c188f6b6630d5b 100644 (file)
 #include <linux/of_gpio.h>
 
 #include "fbtft.h"
-
-extern void fbtft_sysfs_init(struct fbtft_par *par);
-extern void fbtft_sysfs_exit(struct fbtft_par *par);
-extern void fbtft_expand_debug_value(unsigned long *debug);
-extern int fbtft_gamma_parse_str(struct fbtft_par *par, unsigned long *curves,
-                                               const char *str, int size);
+#include "internal.h"
 
 static unsigned long debug;
-module_param(debug, ulong , 0);
+module_param(debug, ulong, 0);
 MODULE_PARM_DESC(debug, "override device debug level");
 
 static bool dma = true;
@@ -302,12 +297,8 @@ void fbtft_register_backlight(struct fbtft_par *par)
 
        bl_ops = devm_kzalloc(par->info->device, sizeof(struct backlight_ops),
                                GFP_KERNEL);
-       if (!bl_ops) {
-               dev_err(par->info->device,
-                       "%s: could not allocate memeory for backlight operations.\n",
-                       __func__);
+       if (!bl_ops)
                return;
-       }
 
        bl_ops->get_brightness = fbtft_backlight_get_brightness;
        bl_ops->update_status = fbtft_backlight_update_status;
@@ -347,7 +338,7 @@ static void fbtft_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe,
        write_reg(par, 0x2A,
                (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF);
 
-       /* Row adress set */
+       /* Row address set */
        write_reg(par, 0x2B,
                (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF);
 
@@ -379,7 +370,7 @@ static void fbtft_update_display(struct fbtft_par *par, unsigned start_line,
        int ret = 0;
 
        if (unlikely(par->debug & (DEBUG_TIME_FIRST_UPDATE | DEBUG_TIME_EACH_UPDATE))) {
-               if ((par->debug & DEBUG_TIME_EACH_UPDATE) || \
+               if ((par->debug & DEBUG_TIME_EACH_UPDATE) ||
                                ((par->debug & DEBUG_TIME_FIRST_UPDATE) && !par->first_update_done)) {
                        getnstimeofday(&ts_start);
                        timeit = true;
@@ -707,9 +698,8 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
 
        /* sanity check */
        if (display->gamma_num * display->gamma_len > FBTFT_GAMMA_MAX_VALUES_TOTAL) {
-               dev_err(dev,
-                       "%s: FBTFT_GAMMA_MAX_VALUES_TOTAL=%d is exceeded\n",
-                       __func__, FBTFT_GAMMA_MAX_VALUES_TOTAL);
+               dev_err(dev, "FBTFT_GAMMA_MAX_VALUES_TOTAL=%d is exceeded\n",
+                       FBTFT_GAMMA_MAX_VALUES_TOTAL);
                return NULL;
        }
 
@@ -1000,7 +990,7 @@ int fbtft_register_framebuffer(struct fb_info *fb_info)
        fbtft_sysfs_init(par);
 
        if (par->txbuf.buf)
-               sprintf(text1, ", %d KiB %sbuffer memory",
+               sprintf(text1, ", %zu KiB %sbuffer memory",
                        par->txbuf.len >> 10, par->txbuf.dma ? "DMA " : "");
        if (spi)
                sprintf(text2, ", spi%d.%d at %d MHz", spi->master->bus_num,
@@ -1046,7 +1036,6 @@ int fbtft_unregister_framebuffer(struct fb_info *fb_info)
 {
        struct fbtft_par *par = fb_info->par;
        struct spi_device *spi = par->spi;
-       int ret;
 
        if (spi)
                spi_set_drvdata(spi, NULL);
@@ -1055,8 +1044,7 @@ int fbtft_unregister_framebuffer(struct fb_info *fb_info)
        if (par->fbtftops.unregister_backlight)
                par->fbtftops.unregister_backlight(par);
        fbtft_sysfs_exit(par);
-       ret = unregister_framebuffer(fb_info);
-       return ret;
+       return unregister_framebuffer(fb_info);
 }
 EXPORT_SYMBOL(fbtft_unregister_framebuffer);
 
@@ -1278,7 +1266,7 @@ static int fbtft_verify_gpios(struct fbtft_par *par)
        fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__);
 
        pdata = par->info->device->platform_data;
-       if (pdata->display.buswidth != 9 && par->startbyte == 0 && \
+       if (pdata->display.buswidth != 9 && par->startbyte == 0 &&
                                                        par->gpio.dc < 0) {
                dev_err(par->info->device,
                        "Missing info about 'dc' gpio. Aborting.\n");
index 32155a7b2a624099f8d7d1bee727ff6dc44f58af..a6f091fb975c71262dade439dad5b22e48d2fe5b 100644 (file)
@@ -59,8 +59,7 @@ int fbtft_write_spi_emulate_9(struct fbtft_par *par, void *buf, size_t len)
        }
        if ((len % 8) != 0) {
                dev_err(par->info->device,
-                       "%s: error: len=%d must be divisible by 8\n",
-                       __func__, len);
+                       "error: len=%zu must be divisible by 8\n", len);
                return -EINVAL;
        }
 
@@ -106,8 +105,8 @@ int fbtft_read_spi(struct fbtft_par *par, void *buf, size_t len)
        if (par->startbyte) {
                if (len > 32) {
                        dev_err(par->info->device,
-                               "%s: len=%d can't be larger than 32 when using 'startbyte'\n",
-                               __func__, len);
+                               "len=%zu can't be larger than 32 when using 'startbyte'\n",
+                               len);
                        return -EINVAL;
                }
                txbuf[0] = par->startbyte | 0x3;
@@ -155,14 +154,14 @@ int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len)
                        for (i = 0; i < 8; i++) {
                                if ((data & 1) != (prev_data & 1))
                                        gpio_set_value(par->gpio.db[i],
-                                                               (data & 1));
+                                                               data & 1);
                                data >>= 1;
                                prev_data >>= 1;
                        }
                }
 #else
                for (i = 0; i < 8; i++) {
-                       gpio_set_value(par->gpio.db[i], (data & 1));
+                       gpio_set_value(par->gpio.db[i], data & 1);
                        data >>= 1;
                }
 #endif
@@ -205,14 +204,14 @@ int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len)
                        for (i = 0; i < 16; i++) {
                                if ((data & 1) != (prev_data & 1))
                                        gpio_set_value(par->gpio.db[i],
-                                                               (data & 1));
+                                                               data & 1);
                                data >>= 1;
                                prev_data >>= 1;
                        }
                }
 #else
                for (i = 0; i < 16; i++) {
-                       gpio_set_value(par->gpio.db[i], (data & 1));
+                       gpio_set_value(par->gpio.db[i], data & 1);
                        data >>= 1;
                }
 #endif
index 45f8de3d11ad45d0b9e49364550e957f23f9d1e2..c4cc452f9f2bf654ba019a71072e65a9ec3cdb28 100644 (file)
@@ -1,5 +1,5 @@
 #include "fbtft.h"
-
+#include "internal.h"
 
 static int get_next_ulong(char **str_p, unsigned long *val, char *sep, int base)
 {
@@ -37,10 +37,9 @@ int fbtft_gamma_parse_str(struct fbtft_par *par, unsigned long *curves,
 
        fbtft_par_dbg(DEBUG_SYSFS, par, "%s\n", str);
 
-       tmp = kmalloc(size+1, GFP_KERNEL);
+       tmp = kmemdup(str, size + 1, GFP_KERNEL);
        if (!tmp)
                return -ENOMEM;
-       memcpy(tmp, str, size+1);
 
        /* replace optional separators */
        str_p = tmp;
@@ -153,7 +152,7 @@ static struct device_attribute gamma_device_attrs[] = {
 
 void fbtft_expand_debug_value(unsigned long *debug)
 {
-       switch (*debug & 0b111) {
+       switch (*debug & 0x7) {
        case 1:
                *debug |= DEBUG_LEVEL_1;
                break;
index 0dbf3f95fe786ce50a9206cd754c4e78b58c45ee..9fd98cb534186776f25a289bc07b90bbb65e22f3 100644 (file)
@@ -147,7 +147,7 @@ struct fbtft_display {
 /**
  * struct fbtft_platform_data - Passes display specific data to the driver
  * @display: Display properties
- * @gpios: Pointer to an array of piname to gpio mappings
+ * @gpios: Pointer to an array of pinname to gpio mappings
  * @rotate: Display rotation angle
  * @bgr: LCD Controller BGR bit
  * @fps: Frames per second (this will go away, use @fps in @fbtft_display)
@@ -200,7 +200,7 @@ struct fbtft_platform_data {
  * @gpio.cs: LCD Chip Select with parallel interface bus
  * @gpio.db[16]: Parallel databus
  * @gpio.led[16]: Led control signals
- * @gpio.aux[16]: Auxillary signals, not used by core
+ * @gpio.aux[16]: Auxiliary signals, not used by core
  * @init_sequence: Pointer to LCD initialization array
  * @gamma.lock: Mutex for Gamma curve locking
  * @gamma.curves: Pointer to Gamma curve array
@@ -259,9 +259,7 @@ struct fbtft_par {
 #define NUMARGS(...)  (sizeof((int[]){__VA_ARGS__})/sizeof(int))
 
 #define write_reg(par, ...)                                              \
-do {                                                                     \
-       par->fbtftops.write_register(par, NUMARGS(__VA_ARGS__), __VA_ARGS__); \
-} while (0)
+       par->fbtftops.write_register(par, NUMARGS(__VA_ARGS__), __VA_ARGS__)
 
 /* fbtft-core.c */
 extern void fbtft_dbg_hex(const struct device *dev,
@@ -326,8 +324,8 @@ static int fbtft_driver_remove_pdev(struct platform_device *pdev)          \
 }                                                                          \
                                                                           \
 static const struct of_device_id dt_ids[] = {                              \
-        { .compatible = _compatible },                                     \
-        {},                                                                \
+       { .compatible = _compatible },                                     \
+       {},                                                                \
 };                                                                         \
                                                                           \
 MODULE_DEVICE_TABLE(of, dt_ids);                                           \
@@ -337,7 +335,7 @@ static struct spi_driver fbtft_driver_spi_driver = {                       \
        .driver = {                                                        \
                .name   = _name,                                           \
                .owner  = THIS_MODULE,                                     \
-                .of_match_table = of_match_ptr(dt_ids),                    \
+               .of_match_table = of_match_ptr(dt_ids),                    \
        },                                                                 \
        .probe  = fbtft_driver_probe_spi,                                  \
        .remove = fbtft_driver_remove_spi,                                 \
@@ -347,7 +345,7 @@ static struct platform_driver fbtft_driver_platform_driver = {             \
        .driver = {                                                        \
                .name   = _name,                                           \
                .owner  = THIS_MODULE,                                     \
-                .of_match_table = of_match_ptr(dt_ids),                    \
+               .of_match_table = of_match_ptr(dt_ids),                    \
        },                                                                 \
        .probe  = fbtft_driver_probe_pdev,                                 \
        .remove = fbtft_driver_remove_pdev,                                \
index b9f4c30e39c6a3a91882c07078fd948a66390d70..df6cd775ac1eb5eabebf19c782df3488e9ad192c 100644 (file)
@@ -29,8 +29,8 @@
 
 #define MAX_GPIOS 32
 
-struct spi_device *spi_device;
-struct platform_device *p_device;
+static struct spi_device *spi_device;
+static struct platform_device *p_device;
 
 static char *name;
 module_param(name, charp, 0);
@@ -109,7 +109,7 @@ module_param_array(init, int, &init_num, 0);
 MODULE_PARM_DESC(init, "Init sequence, used with the custom argument");
 
 static unsigned long debug;
-module_param(debug, ulong , 0);
+module_param(debug, ulong, 0);
 MODULE_PARM_DESC(debug,
 "level: 0-7 (the remaining 29 bits is for advanced usage)");
 
@@ -136,43 +136,69 @@ static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par,
                "03 1d 07 06 2E 2C 29 2D 2E 2E 37 3F 00 00 02 10"
 
 static int hy28b_init_sequence[] = {
-       -1,0x00e7,0x0010,-1,0x0000,0x0001,-1,0x0001,0x0100,-1,0x0002,0x0700,
-       -1,0x0003,0x1030,-1,0x0004,0x0000,-1,0x0008,0x0207,-1,0x0009,0x0000,
-       -1,0x000a,0x0000,-1,0x000c,0x0001,-1,0x000d,0x0000,-1,0x000f,0x0000,
-       -1,0x0010,0x0000,-1,0x0011,0x0007,-1,0x0012,0x0000,-1,0x0013,0x0000,
-       -2,50,-1,0x0010,0x1590,-1,0x0011,0x0227,-2,50,-1,0x0012,0x009c,-2,50,
-       -1,0x0013,0x1900,-1,0x0029,0x0023,-1,0x002b,0x000e,-2,50,
-       -1,0x0020,0x0000,-1,0x0021,0x0000,-2,50,-1,0x0050,0x0000,
-       -1,0x0051,0x00ef,-1,0x0052,0x0000,-1,0x0053,0x013f,-1,0x0060,0xa700,
-       -1,0x0061,0x0001,-1,0x006a,0x0000,-1,0x0080,0x0000,-1,0x0081,0x0000,
-       -1,0x0082,0x0000,-1,0x0083,0x0000,-1,0x0084,0x0000,-1,0x0085,0x0000,
-       -1,0x0090,0x0010,-1,0x0092,0x0000,-1,0x0093,0x0003,-1,0x0095,0x0110,
-       -1,0x0097,0x0000,-1,0x0098,0x0000,-1,0x0007,0x0133,-1,0x0020,0x0000,
-       -1,0x0021,0x0000,-2,100,-3 };
+       -1, 0x00e7, 0x0010, -1, 0x0000, 0x0001,
+       -1, 0x0001, 0x0100, -1, 0x0002, 0x0700,
+       -1, 0x0003, 0x1030, -1, 0x0004, 0x0000,
+       -1, 0x0008, 0x0207, -1, 0x0009, 0x0000,
+       -1, 0x000a, 0x0000, -1, 0x000c, 0x0001,
+       -1, 0x000d, 0x0000, -1, 0x000f, 0x0000,
+       -1, 0x0010, 0x0000, -1, 0x0011, 0x0007,
+       -1, 0x0012, 0x0000, -1, 0x0013, 0x0000,
+       -2, 50, -1, 0x0010, 0x1590, -1, 0x0011,
+       0x0227, -2, 50, -1, 0x0012, 0x009c, -2, 50,
+       -1, 0x0013, 0x1900, -1, 0x0029, 0x0023,
+       -1, 0x002b, 0x000e, -2, 50,
+       -1, 0x0020, 0x0000, -1, 0x0021, 0x0000,
+       -2, 50, -1, 0x0050, 0x0000,
+       -1, 0x0051, 0x00ef, -1, 0x0052, 0x0000,
+       -1, 0x0053, 0x013f, -1, 0x0060, 0xa700,
+       -1, 0x0061, 0x0001, -1, 0x006a, 0x0000,
+       -1, 0x0080, 0x0000, -1, 0x0081, 0x0000,
+       -1, 0x0082, 0x0000, -1, 0x0083, 0x0000,
+       -1, 0x0084, 0x0000, -1, 0x0085, 0x0000,
+       -1, 0x0090, 0x0010, -1, 0x0092, 0x0000,
+       -1, 0x0093, 0x0003, -1, 0x0095, 0x0110,
+       -1, 0x0097, 0x0000, -1, 0x0098, 0x0000,
+       -1, 0x0007, 0x0133, -1, 0x0020, 0x0000,
+       -1, 0x0021, 0x0000, -2, 100, -3 };
 
 #define HY28B_GAMMA \
        "04 1F 4 7 7 0 7 7 6 0\n" \
        "0F 00 1 7 4 0 0 0 6 7"
 
 static int pitft_init_sequence[] = {
-       -1,0x01,-2,5,-1,0x28,-1,0xEF,0x03,0x80,0x02,-1,0xCF,0x00,0xC1,0x30,
-       -1,0xED,0x64,0x03,0x12,0x81,-1,0xE8,0x85,0x00,0x78,
-       -1,0xCB,0x39,0x2C,0x00,0x34,0x02,-1,0xF7,0x20,-1,0xEA,0x00,0x00,
-       -1,0xC0,0x23,-1,0xC1,0x10,-1,0xC5,0x3e,0x28,-1,0xC7,0x86,-1,0x3A,0x55,
-       -1,0xB1,0x00,0x18,-1,0xB6,0x08,0x82,0x27,-1,0xF2,0x00,-1,0x26,0x01,
-       -1,0xE0,0x0F,0x31,0x2B,0x0C,0x0E,0x08,0x4E,0xF1,0x37,0x07,0x10,0x03,
-       0x0E,0x09,0x00,-1,0xE1,0x00,0x0E,0x14,0x03,0x11,0x07,0x31,0xC1,0x48,
-       0x08,0x0F,0x0C,0x31,0x36,0x0F,-1,0x11,-2,100,-1,0x29,-2,20,-3 };
+       -1, 0x01, -2, 5, -1, 0x28, -1, 0xEF,
+       0x03, 0x80, 0x02, -1, 0xCF, 0x00, 0xC1, 0x30,
+       -1, 0xED, 0x64, 0x03, 0x12, 0x81,
+       -1, 0xE8, 0x85, 0x00, 0x78,
+       -1, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02,
+       -1, 0xF7, 0x20, -1, 0xEA, 0x00, 0x00,
+       -1, 0xC0, 0x23, -1, 0xC1, 0x10, -1, 0xC5,
+       0x3e, 0x28, -1, 0xC7, 0x86, -1, 0x3A, 0x55,
+       -1, 0xB1, 0x00, 0x18, -1, 0xB6, 0x08, 0x82,
+       0x27, -1, 0xF2, 0x00, -1, 0x26, 0x01,
+       -1, 0xE0, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08,
+       0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03,
+       0x0E, 0x09, 0x00, -1, 0xE1, 0x00, 0x0E, 0x14,
+       0x03, 0x11, 0x07, 0x31, 0xC1, 0x48,
+       0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, -1,
+       0x11, -2, 100, -1, 0x29, -2, 20, -3 };
 
 static int waveshare32b_init_sequence[] = {
-       -1,0xCB,0x39,0x2C,0x00,0x34,0x02,-1,0xCF,0x00,0xC1,0x30,
-       -1,0xE8,0x85,0x00,0x78,-1,0xEA,0x00,0x00,-1,0xED,0x64,0x03,0x12,0x81,
-       -1,0xF7,0x20,-1,0xC0,0x23,-1,0xC1,0x10,-1,0xC5,0x3e,0x28,-1,0xC7,0x86,
-       -1,0x36,0x28,-1,0x3A,0x55,-1,0xB1,0x00,0x18,-1,0xB6,0x08,0x82,0x27,
-       -1,0xF2,0x00,-1,0x26,0x01,
-       -1,0xE0,0x0F,0x31,0x2B,0x0C,0x0E,0x08,0x4E,0xF1,0x37,0x07,0x10,0x03,0x0E,0x09,0x00,
-       -1,0xE1,0x00,0x0E,0x14,0x03,0x11,0x07,0x31,0xC1,0x48,0x08,0x0F,0x0C,0x31,0x36,0x0F,
-       -1,0x11,-2,120,-1,0x29,-1,0x2c,-3 };
+       -1, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02,
+       -1, 0xCF, 0x00, 0xC1, 0x30,
+       -1, 0xE8, 0x85, 0x00, 0x78, -1, 0xEA, 0x00,
+       0x00, -1, 0xED, 0x64, 0x03, 0x12, 0x81,
+       -1, 0xF7, 0x20, -1, 0xC0, 0x23, -1, 0xC1,
+       0x10, -1, 0xC5, 0x3e, 0x28, -1, 0xC7, 0x86,
+       -1, 0x36, 0x28, -1, 0x3A, 0x55, -1, 0xB1, 0x00,
+       0x18, -1, 0xB6, 0x08, 0x82, 0x27,
+       -1, 0xF2, 0x00, -1, 0x26, 0x01,
+       -1, 0xE0, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E,
+       0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00,
+       -1, 0xE1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31,
+       0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F,
+       -1, 0x11, -2, 120, -1, 0x29, -1, 0x2c, -3 };
 
 /* Supported displays in alphabetical order */
 static struct fbtft_device_display displays[] = {
@@ -463,7 +489,7 @@ static struct fbtft_device_display displays[] = {
                                        .buswidth = 8,
                                        .backlight = 1,
                                },
-                               .startbyte = 0b01110000,
+                               .startbyte = 0x70,
                                .bgr = true,
                                .gpios = (const struct fbtft_gpio []) {
                                        { "reset", 25 },
@@ -484,9 +510,9 @@ static struct fbtft_device_display displays[] = {
                                        .backlight = 1,
                                        .init_sequence = hy28b_init_sequence,
                                },
-                               .startbyte = 0b01110000,
+                               .startbyte = 0x70,
                                .bgr = true,
-                               .fps= 50,
+                               .fps = 50,
                                .gpios = (const struct fbtft_gpio []) {
                                        { "reset", 25 },
                                        { "led", 18 },
@@ -597,7 +623,7 @@ static struct fbtft_device_display displays[] = {
                                        .buswidth = 8,
                                        .backlight = 1,
                                },
-                               .startbyte = 0b01110000,
+                               .startbyte = 0x70,
                                .bgr = true,
                                .gpios = (const struct fbtft_gpio []) {
                                        { "reset", 25 },
@@ -676,6 +702,24 @@ static struct fbtft_device_display displays[] = {
                        }
                }
        }, {
+               .name = "nokia5110",
+               .spi = &(struct spi_board_info) {
+                       .modalias = "fb_ili9163",
+                       .max_speed_hz = 12000000,
+                       .mode = SPI_MODE_0,
+                       .platform_data = &(struct fbtft_platform_data) {
+                               .display = {
+                                       .buswidth = 8,
+                                       .backlight = 1,
+                               },
+                               .bgr = true,
+                               .gpios = (const struct fbtft_gpio []) {
+                                       {},
+                               },
+                       }
+               }
+       }, {
+
                .name = "piscreen",
                .spi = &(struct spi_board_info) {
                        .modalias = "fb_ili9486",
@@ -1100,14 +1144,14 @@ static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len)
                        for (i = 0; i < 16; i++) {
                                if ((data & 1) != (prev_data & 1))
                                        gpio_set_value(par->gpio.db[i],
-                                                               (data & 1));
+                                                               data & 1);
                                data >>= 1;
                                prev_data >>= 1;
                        }
                }
 #else
                for (i = 0; i < 16; i++) {
-                       gpio_set_value(par->gpio.db[i], (data & 1));
+                       gpio_set_value(par->gpio.db[i], data & 1);
                        data >>= 1;
                }
 #endif
index 90832c36e557e7e122001547344310549c426fd9..ca39fe90d1b8b2d3a9981d64ec0ae4c657b275f4 100644 (file)
@@ -423,7 +423,7 @@ static int flexfb_probe_common(struct spi_device *sdev, struct platform_device *
                        }
                        par->fbtftops.write_register = fbtft_write_reg8_bus9;
                        par->fbtftops.write_vmem = fbtft_write_vmem16_bus9;
-                       sdev->bits_per_word=9;
+                       sdev->bits_per_word = 9;
                        ret = sdev->master->setup(sdev);
                        if (ret) {
                                dev_warn(dev,
diff --git a/drivers/staging/fbtft/internal.h b/drivers/staging/fbtft/internal.h
new file mode 100644 (file)
index 0000000..f69db82
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2013 Noralf Tronnes
+ *
+ * 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 __LINUX_FBTFT__INTERNAL_H
+#define __LINUX_FBTFT_INTERNAL_H
+
+void fbtft_sysfs_init(struct fbtft_par *par);
+void fbtft_sysfs_exit(struct fbtft_par *par);
+void fbtft_expand_debug_value(unsigned long *debug);
+int fbtft_gamma_parse_str(struct fbtft_par *par, unsigned long *curves,
+                         const char *str, int size);
+
+#endif /* __LINUX_FBTFT_INTERNAL_H */
diff --git a/drivers/staging/fsl-mc/Kconfig b/drivers/staging/fsl-mc/Kconfig
new file mode 100644 (file)
index 0000000..32df07b
--- /dev/null
@@ -0,0 +1 @@
+source "drivers/staging/fsl-mc/bus/Kconfig"
diff --git a/drivers/staging/fsl-mc/Makefile b/drivers/staging/fsl-mc/Makefile
new file mode 100644 (file)
index 0000000..9c6a001
--- /dev/null
@@ -0,0 +1,2 @@
+# Freescale Management Complex (MC) bus drivers
+obj-$(CONFIG_FSL_MC_BUS)       += bus/
diff --git a/drivers/staging/fsl-mc/TODO b/drivers/staging/fsl-mc/TODO
new file mode 100644 (file)
index 0000000..d78288b
--- /dev/null
@@ -0,0 +1,13 @@
+* 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).
+
+Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
+german.rivera@freescale.com, devel@driverdev.osuosl.org,
+linux-kernel@vger.kernel.org
diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/staging/fsl-mc/bus/Kconfig
new file mode 100644 (file)
index 0000000..0d779d9
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Freescale Management Complex (MC) bus drivers
+#
+# Copyright (C) 2014 Freescale Semiconductor, Inc.
+#
+# This file is released under the GPLv2
+#
+
+config FSL_MC_BUS
+       tristate "Freescale Management Complex (MC) bus driver"
+       depends on OF && ARM64
+       help
+         Driver to enable the bus infrastructure for the Freescale
+          QorIQ Management Complex (fsl-mc). The fsl-mc is a hardware
+         module of the QorIQ LS2 SoCs, that does resource management
+         for hardware building-blocks in the SoC that can be used
+         to dynamically create networking hardware objects such as
+         network interfaces (NICs), crypto accelerator instances,
+         or L2 switches.
+
+         Only enable this option when building the kernel for
+         Freescale QorQIQ LS2xxxx SoCs.
+
+
diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile
new file mode 100644 (file)
index 0000000..25433a9
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# Freescale Management Complex (MC) bus drivers
+#
+# Copyright (C) 2014 Freescale Semiconductor, Inc.
+#
+# This file is released under the GPLv2
+#
+obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o
+
+mc-bus-driver-objs := mc-bus.o \
+                     mc-sys.o \
+                     dprc.o \
+                     dpmng.o \
+                     dprc-driver.o \
+                     mc-allocator.o \
+                     dpmcp.o \
+                     dpbp.o
diff --git a/drivers/staging/fsl-mc/bus/dpbp.c b/drivers/staging/fsl-mc/bus/dpbp.c
new file mode 100644 (file)
index 0000000..d99ab6d
--- /dev/null
@@ -0,0 +1,358 @@
+/* Copyright 2013-2014 Freescale Semiconductor Inc.
+*
+* 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 the above-listed copyright holders nor the
+* names of any contributors may be used to endorse or promote products
+* derived from this software without specific prior written permission.
+*
+*
+* ALTERNATIVELY, this software may be distributed under the terms of the
+* GNU General Public License ("GPL") as published by the Free Software
+* Foundation, either version 2 of that License or (at your option) any
+* later version.
+*
+* THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 "../include/mc-sys.h"
+#include "../include/mc-cmd.h"
+#include "../include/dpbp.h"
+#include "../include/dpbp-cmd.h"
+
+int dpbp_open(struct fsl_mc_io *mc_io, int dpbp_id, uint16_t *token)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
+                                         MC_CMD_PRI_LOW, 0);
+       cmd.params[0] |= mc_enc(0, 32, dpbp_id);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+
+       return err;
+}
+EXPORT_SYMBOL(dpbp_open);
+
+int dpbp_close(struct fsl_mc_io *mc_io, uint16_t token)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, MC_CMD_PRI_HIGH,
+                                         token);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+EXPORT_SYMBOL(dpbp_close);
+
+int dpbp_create(struct fsl_mc_io *mc_io,
+               const struct dpbp_cfg *cfg,
+               uint16_t *token)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       (void)(cfg); /* unused */
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_CREATE,
+                                         MC_CMD_PRI_LOW, 0);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+
+       return 0;
+}
+
+int dpbp_destroy(struct fsl_mc_io *mc_io, uint16_t token)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_DESTROY,
+                                         MC_CMD_PRI_LOW, token);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dpbp_enable(struct fsl_mc_io *mc_io, uint16_t token)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, MC_CMD_PRI_LOW,
+                                         token);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+EXPORT_SYMBOL(dpbp_enable);
+
+int dpbp_disable(struct fsl_mc_io *mc_io, uint16_t token)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
+                                         MC_CMD_PRI_LOW, token);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+EXPORT_SYMBOL(dpbp_disable);
+
+int dpbp_is_enabled(struct fsl_mc_io *mc_io, uint16_t token, int *en)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, MC_CMD_PRI_LOW,
+                                         token);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *en = (int)mc_dec(cmd.params[0], 0, 1);
+
+       return 0;
+}
+
+int dpbp_reset(struct fsl_mc_io *mc_io, uint16_t token)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
+                                         MC_CMD_PRI_LOW, token);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dpbp_set_irq(struct fsl_mc_io *mc_io,
+                uint16_t token,
+                uint8_t irq_index,
+                uint64_t irq_paddr,
+                uint32_t irq_val,
+                int user_irq_id)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 8, irq_index);
+       cmd.params[0] |= mc_enc(32, 32, irq_val);
+       cmd.params[1] |= mc_enc(0, 64, irq_paddr);
+       cmd.params[2] |= mc_enc(0, 32, user_irq_id);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dpbp_get_irq(struct fsl_mc_io *mc_io,
+                uint16_t token,
+                uint8_t irq_index,
+                int *type,
+                uint64_t *irq_paddr,
+                uint32_t *irq_val,
+                int *user_irq_id)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *irq_val = (uint32_t)mc_dec(cmd.params[0], 0, 32);
+       *irq_paddr = (uint64_t)mc_dec(cmd.params[1], 0, 64);
+       *user_irq_id = (int)mc_dec(cmd.params[2], 0, 32);
+       *type = (int)mc_dec(cmd.params[2], 32, 32);
+       return 0;
+}
+
+int dpbp_set_irq_enable(struct fsl_mc_io *mc_io,
+                       uint16_t token,
+                       uint8_t irq_index,
+                       uint8_t en)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_ENABLE,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 8, en);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dpbp_get_irq_enable(struct fsl_mc_io *mc_io,
+                       uint16_t token,
+                       uint8_t irq_index,
+                       uint8_t *en)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_ENABLE,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *en = (uint8_t)mc_dec(cmd.params[0], 0, 8);
+       return 0;
+}
+
+int dpbp_set_irq_mask(struct fsl_mc_io *mc_io,
+                     uint16_t token,
+                     uint8_t irq_index,
+                     uint32_t mask)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_MASK,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 32, mask);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dpbp_get_irq_mask(struct fsl_mc_io *mc_io,
+                     uint16_t token,
+                     uint8_t irq_index,
+                     uint32_t *mask)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_MASK,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *mask = (uint32_t)mc_dec(cmd.params[0], 0, 32);
+       return 0;
+}
+
+int dpbp_get_irq_status(struct fsl_mc_io *mc_io,
+                       uint16_t token,
+                       uint8_t irq_index,
+                       uint32_t *status)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_STATUS,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *status = (uint32_t)mc_dec(cmd.params[0], 0, 32);
+       return 0;
+}
+
+int dpbp_clear_irq_status(struct fsl_mc_io *mc_io,
+                         uint16_t token,
+                         uint8_t irq_index,
+                         uint32_t status)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLEAR_IRQ_STATUS,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 32, status);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dpbp_get_attributes(struct fsl_mc_io *mc_io,
+                       uint16_t token,
+                       struct dpbp_attr *attr)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR,
+                                         MC_CMD_PRI_LOW, token);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       attr->bpid = (uint16_t)mc_dec(cmd.params[0], 16, 16);
+       attr->id = (int)mc_dec(cmd.params[0], 32, 32);
+       attr->version.major = (uint16_t)mc_dec(cmd.params[1], 0, 16);
+       attr->version.minor = (uint16_t)mc_dec(cmd.params[1], 16, 16);
+       return 0;
+}
+EXPORT_SYMBOL(dpbp_get_attributes);
diff --git a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
new file mode 100644 (file)
index 0000000..57f326b
--- /dev/null
@@ -0,0 +1,136 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * 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 the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 _FSL_DPMCP_CMD_H
+#define _FSL_DPMCP_CMD_H
+
+/* DPMCP Version */
+#define DPMCP_VER_MAJOR                                2
+#define DPMCP_VER_MINOR                                0
+
+/* Command IDs */
+#define DPMCP_CMDID_CLOSE                              0x800
+#define DPMCP_CMDID_OPEN                               0x80b
+#define DPMCP_CMDID_CREATE                             0x90b
+#define DPMCP_CMDID_DESTROY                            0x900
+
+#define DPMCP_CMDID_GET_ATTR                           0x004
+#define DPMCP_CMDID_RESET                              0x005
+
+#define DPMCP_CMDID_SET_IRQ                            0x010
+#define DPMCP_CMDID_GET_IRQ                            0x011
+#define DPMCP_CMDID_SET_IRQ_ENABLE                     0x012
+#define DPMCP_CMDID_GET_IRQ_ENABLE                     0x013
+#define DPMCP_CMDID_SET_IRQ_MASK                       0x014
+#define DPMCP_CMDID_GET_IRQ_MASK                       0x015
+#define DPMCP_CMDID_GET_IRQ_STATUS                     0x016
+#define DPMCP_CMDID_CLEAR_IRQ_STATUS                   0x017
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMCP_CMD_CREATE(cmd, cfg) \
+       MC_CMD_OP(cmd, 0, 0,  32, int,      cfg->portal_id)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMCP_CMD_SET_IRQ(cmd, irq_index, irq_addr, irq_val, user_irq_id) \
+do { \
+       MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  irq_index);\
+       MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_val);\
+       MC_CMD_OP(cmd, 1, 0,  64, uint64_t, irq_addr); \
+       MC_CMD_OP(cmd, 2, 0,  32, int,      user_irq_id); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMCP_CMD_GET_IRQ(cmd, irq_index) \
+       MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMCP_RSP_GET_IRQ(cmd, type, irq_addr, irq_val, user_irq_id) \
+do { \
+       MC_RSP_OP(cmd, 0, 0,  32, uint32_t, irq_val); \
+       MC_RSP_OP(cmd, 1, 0,  64, uint64_t, irq_addr); \
+       MC_RSP_OP(cmd, 2, 0,  32, int,      user_irq_id); \
+       MC_RSP_OP(cmd, 2, 32, 32, int,      type); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMCP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \
+do { \
+       MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  en); \
+       MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMCP_CMD_GET_IRQ_ENABLE(cmd, irq_index) \
+       MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMCP_RSP_GET_IRQ_ENABLE(cmd, en) \
+       MC_RSP_OP(cmd, 0, 0,  8,  uint8_t,  en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMCP_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \
+do { \
+       MC_CMD_OP(cmd, 0, 0,  32, uint32_t, mask);\
+       MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMCP_CMD_GET_IRQ_MASK(cmd, irq_index) \
+       MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMCP_RSP_GET_IRQ_MASK(cmd, mask) \
+       MC_RSP_OP(cmd, 0, 0,  32, uint32_t, mask)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMCP_CMD_GET_IRQ_STATUS(cmd, irq_index) \
+       MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMCP_RSP_GET_IRQ_STATUS(cmd, status) \
+       MC_RSP_OP(cmd, 0, 0,  32, uint32_t, status)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPMCP_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \
+do { \
+       MC_CMD_OP(cmd, 0, 0,  32, uint32_t, status); \
+       MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
+} while (0)
+
+/*                cmd, param, offset, width, type,     arg_name */
+#define DPMCP_RSP_GET_ATTRIBUTES(cmd, attr) \
+do { \
+       MC_RSP_OP(cmd, 0, 32, 32, int,      attr->id);\
+       MC_RSP_OP(cmd, 1, 0,  16, uint16_t, attr->version.major);\
+       MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\
+} while (0)
+
+#endif /* _FSL_DPMCP_CMD_H */
diff --git a/drivers/staging/fsl-mc/bus/dpmcp.c b/drivers/staging/fsl-mc/bus/dpmcp.c
new file mode 100644 (file)
index 0000000..6b9da5b
--- /dev/null
@@ -0,0 +1,308 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * 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 the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 "../include/mc-sys.h"
+#include "../include/mc-cmd.h"
+#include "dpmcp.h"
+#include "dpmcp-cmd.h"
+
+int dpmcp_open(struct fsl_mc_io *mc_io, int dpmcp_id, uint16_t *token)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN,
+                                         MC_CMD_PRI_LOW, 0);
+       cmd.params[0] |= mc_enc(0, 32, dpmcp_id);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+
+       return err;
+}
+
+int dpmcp_close(struct fsl_mc_io *mc_io, uint16_t token)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE, MC_CMD_PRI_HIGH,
+                                         token);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dpmcp_create(struct fsl_mc_io *mc_io,
+                const struct dpmcp_cfg *cfg,
+               uint16_t *token)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CREATE,
+                                         MC_CMD_PRI_LOW, 0);
+       cmd.params[0] |= mc_enc(0, 32, cfg->portal_id);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+
+       return 0;
+}
+
+int dpmcp_destroy(struct fsl_mc_io *mc_io, uint16_t token)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_DESTROY,
+                                         MC_CMD_PRI_LOW, token);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dpmcp_reset(struct fsl_mc_io *mc_io, uint16_t token)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET,
+                                         MC_CMD_PRI_LOW, token);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dpmcp_set_irq(struct fsl_mc_io *mc_io,
+                 uint16_t token,
+                uint8_t irq_index,
+                uint64_t irq_addr,
+                uint32_t irq_val,
+                int user_irq_id)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 8, irq_index);
+       cmd.params[0] |= mc_enc(32, 32, irq_val);
+       cmd.params[1] |= mc_enc(0, 64, irq_addr);
+       cmd.params[2] |= mc_enc(0, 32, user_irq_id);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dpmcp_get_irq(struct fsl_mc_io *mc_io,
+                 uint16_t token,
+                uint8_t irq_index,
+                int *type,
+                uint64_t *irq_addr,
+                uint32_t *irq_val,
+                int *user_irq_id)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *irq_val = (uint32_t)mc_dec(cmd.params[0], 0, 32);
+       *irq_addr = (uint64_t)mc_dec(cmd.params[1], 0, 64);
+       *user_irq_id = (int)mc_dec(cmd.params[2], 0, 32);
+       *type = (int)mc_dec(cmd.params[2], 32, 32);
+       return 0;
+}
+
+int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io,
+                        uint16_t token,
+                       uint8_t irq_index,
+                       uint8_t en)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_ENABLE,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 8, en);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io,
+                        uint16_t token,
+                       uint8_t irq_index,
+                       uint8_t *en)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_ENABLE,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *en = (uint8_t)mc_dec(cmd.params[0], 0, 8);
+       return 0;
+}
+
+int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io,
+                      uint16_t token,
+                     uint8_t irq_index,
+                     uint32_t mask)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_MASK,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 32, mask);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io,
+                      uint16_t token,
+                     uint8_t irq_index,
+                     uint32_t *mask)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_MASK,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *mask = (uint32_t)mc_dec(cmd.params[0], 0, 32);
+       return 0;
+}
+
+int dpmcp_get_irq_status(struct fsl_mc_io *mc_io,
+                        uint16_t token,
+                       uint8_t irq_index,
+                       uint32_t *status)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_STATUS,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *status = (uint32_t)mc_dec(cmd.params[0], 0, 32);
+       return 0;
+}
+
+int dpmcp_clear_irq_status(struct fsl_mc_io *mc_io,
+                          uint16_t token,
+                         uint8_t irq_index,
+                         uint32_t status)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLEAR_IRQ_STATUS,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 32, status);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dpmcp_get_attributes(struct fsl_mc_io *mc_io,
+                        uint16_t token,
+                       struct dpmcp_attr *attr)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_ATTR,
+                                         MC_CMD_PRI_LOW, token);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       attr->id = (int)mc_dec(cmd.params[0], 32, 32);
+       attr->version.major = (uint16_t)mc_dec(cmd.params[1], 0, 16);
+       attr->version.minor = (uint16_t)mc_dec(cmd.params[1], 16, 16);
+       return 0;
+}
diff --git a/drivers/staging/fsl-mc/bus/dpmcp.h b/drivers/staging/fsl-mc/bus/dpmcp.h
new file mode 100644 (file)
index 0000000..5e7c219
--- /dev/null
@@ -0,0 +1,311 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * 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 the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 __FSL_DPMCP_H
+#define __FSL_DPMCP_H
+
+/* Data Path Management Command Portal API
+ * Contains initialization APIs and runtime control APIs for DPMCP
+ */
+
+struct fsl_mc_io;
+
+/**
+ * dpmcp_open() - Open a control session for the specified object.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @dpmcp_id:  DPMCP unique ID
+ * @token:     Returned token; use in subsequent API calls
+ *
+ * This function can be used to open a control session for an
+ * already created object; an object may have been declared in
+ * the DPL or by calling the dpmcp_create function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent commands for
+ * this specific object
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmcp_open(struct fsl_mc_io *mc_io, int dpmcp_id, uint16_t *token);
+
+/* Get portal ID from pool */
+#define DPMCP_GET_PORTAL_ID_FROM_POOL (-1)
+
+/**
+ * dpmcp_close() - Close the control session of the object
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPMCP object
+ *
+ * After this function is called, no further operations are
+ * allowed on the object without opening a new control session.
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmcp_close(struct fsl_mc_io *mc_io, uint16_t token);
+
+/**
+ * struct dpmcp_cfg() - Structure representing DPMCP configuration
+ * @portal_id: Portal ID; 'DPMCP_GET_PORTAL_ID_FROM_POOL' to get the portal ID
+ *             from pool
+ */
+struct dpmcp_cfg {
+       int portal_id;
+};
+
+/**
+ * dpmcp_create() - Create the DPMCP object.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @cfg:       Configuration structure
+ * @token:     Returned token; use in subsequent API calls
+ *
+ * Create the DPMCP object, allocate required resources and
+ * perform required initialization.
+ *
+ * The object can be created either by declaring it in the
+ * DPL file, or by calling this function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent calls to
+ * this specific object. For objects that are created using the
+ * DPL file, call dpmcp_open function to get an authentication
+ * token first.
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmcp_create(struct fsl_mc_io      *mc_io,
+                const struct dpmcp_cfg *cfg,
+               uint16_t                *token);
+
+/**
+ * dpmcp_destroy() - Destroy the DPMCP object and release all its resources.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPMCP object
+ *
+ * Return:     '0' on Success; error code otherwise.
+ */
+int dpmcp_destroy(struct fsl_mc_io *mc_io, uint16_t token);
+
+/**
+ * dpmcp_reset() - Reset the DPMCP, returns the object to initial state.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPMCP object
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmcp_reset(struct fsl_mc_io *mc_io, uint16_t token);
+
+/* IRQ */
+/*!
+ * @name dpmcp IRQ Index and Events
+ */
+#define DPMCP_IRQ_INDEX                             0
+/*!< Irq index */
+#define DPMCP_IRQ_EVENT_CMD_DONE                    0x00000001
+/*!< irq event - Indicates that the link state changed */
+/* @} */
+
+/**
+ * dpmcp_set_irq() - Set IRQ information for the DPMCP to trigger an interrupt.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPMCP object
+ * @irq_index: Identifies the interrupt index to configure
+ * @irq_addr:  Address that must be written to
+ *                             signal a message-based interrupt
+ * @irq_val:   Value to write into irq_addr address
+ * @user_irq_id: A user defined number associated with this IRQ
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmcp_set_irq(struct fsl_mc_io     *mc_io,
+                 uint16_t              token,
+                uint8_t                irq_index,
+                uint64_t               irq_addr,
+                uint32_t               irq_val,
+                int                    user_irq_id);
+
+/**
+ * dpmcp_get_irq() - Get IRQ information from the DPMCP.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPMCP object
+ * @irq_index: The interrupt index to configure
+ * @type:      Interrupt type: 0 represents message interrupt
+ *                             type (both irq_addr and irq_val are valid)
+ * @irq_addr:  Returned address that must be written to
+ *                             signal the message-based interrupt
+ * @irq_val:   Value to write into irq_addr address
+ * @user_irq_id: A user defined number associated with this IRQ
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmcp_get_irq(struct fsl_mc_io     *mc_io,
+                 uint16_t              token,
+                uint8_t                irq_index,
+                int                    *type,
+                uint64_t               *irq_addr,
+                uint32_t               *irq_val,
+                int                    *user_irq_id);
+
+/**
+ * dpmcp_set_irq_enable() - Set overall interrupt state.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPMCP object
+ * @irq_index: The interrupt index to configure
+ * @en:        Interrupt state - enable = 1, disable = 0
+ *
+ * Allows GPP software to control when interrupts are generated.
+ * Each interrupt can have up to 32 causes.  The enable/disable control's the
+ * overall interrupt state. if the interrupt is disabled no causes will cause
+ * an interrupt.
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmcp_set_irq_enable(struct fsl_mc_io      *mc_io,
+                        uint16_t               token,
+                       uint8_t                 irq_index,
+                       uint8_t                 en);
+
+/**
+ * dpmcp_get_irq_enable() - Get overall interrupt state
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPMCP object
+ * @irq_index: The interrupt index to configure
+ * @en:                Returned interrupt state - enable = 1, disable = 0
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmcp_get_irq_enable(struct fsl_mc_io      *mc_io,
+                        uint16_t               token,
+                       uint8_t                 irq_index,
+                       uint8_t                 *en);
+
+/**
+ * dpmcp_set_irq_mask() - Set interrupt mask.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPMCP object
+ * @irq_index: The interrupt index to configure
+ * @mask:      Event mask to trigger interrupt;
+ *                     each bit:
+ *                             0 = ignore event
+ *                             1 = consider event for asserting IRQ
+ *
+ * Every interrupt can have up to 32 causes and the interrupt model supports
+ * masking/unmasking each cause independently
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmcp_set_irq_mask(struct fsl_mc_io        *mc_io,
+                      uint16_t         token,
+                     uint8_t           irq_index,
+                     uint32_t          mask);
+
+/**
+ * dpmcp_get_irq_mask() - Get interrupt mask.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPMCP object
+ * @irq_index: The interrupt index to configure
+ * @mask:      Returned event mask to trigger interrupt
+ *
+ * Every interrupt can have up to 32 causes and the interrupt model supports
+ * masking/unmasking each cause independently
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmcp_get_irq_mask(struct fsl_mc_io        *mc_io,
+                      uint16_t         token,
+                     uint8_t           irq_index,
+                     uint32_t          *mask);
+
+/**
+ * dpmcp_get_irq_status() - Get the current status of any pending interrupts.
+ *
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPMCP object
+ * @irq_index: The interrupt index to configure
+ * @status:    Returned interrupts status - one bit per cause:
+ *                     0 = no interrupt pending
+ *                     1 = interrupt pending
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmcp_get_irq_status(struct fsl_mc_io      *mc_io,
+                        uint16_t               token,
+                       uint8_t                 irq_index,
+                       uint32_t                *status);
+
+/**
+ * dpmcp_clear_irq_status() - Clear a pending interrupt's status
+ *
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPMCP object
+ * @irq_index: The interrupt index to configure
+ * @status:    Bits to clear (W1C) - one bit per cause:
+ *                                     0 = don't change
+ *                                     1 = clear status bit
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmcp_clear_irq_status(struct fsl_mc_io    *mc_io,
+                          uint16_t             token,
+                         uint8_t               irq_index,
+                         uint32_t              status);
+
+/**
+ * struct dpmcp_attr - Structure representing DPMCP attributes
+ * @id:                DPMCP object ID
+ * @version:   DPMCP version
+ */
+struct dpmcp_attr {
+       int id;
+       /**
+        * struct version - Structure representing DPMCP version
+        * @major:      DPMCP major version
+        * @minor:      DPMCP minor version
+        */
+       struct {
+               uint16_t major;
+               uint16_t minor;
+       } version;
+};
+
+/**
+ * dpmcp_get_attributes - Retrieve DPMCP attributes.
+ *
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPMCP object
+ * @attr:      Returned object's attributes
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmcp_get_attributes(struct fsl_mc_io      *mc_io,
+                        uint16_t               token,
+                       struct dpmcp_attr       *attr);
+
+#endif /* __FSL_DPMCP_H */
diff --git a/drivers/staging/fsl-mc/bus/dpmng-cmd.h b/drivers/staging/fsl-mc/bus/dpmng-cmd.h
new file mode 100644 (file)
index 0000000..ba8cfa9
--- /dev/null
@@ -0,0 +1,47 @@
+/* Copyright 2013-2014 Freescale Semiconductor Inc.
+ *
+ * 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 the above-listed copyright holders nor the
+ *       names of any contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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.
+ */
+
+/*************************************************************************//*
+ dpmng-cmd.h
+
+ defines portal commands
+
+ *//**************************************************************************/
+
+#ifndef __FSL_DPMNG_CMD_H
+#define __FSL_DPMNG_CMD_H
+
+/* Command IDs */
+#define DPMNG_CMDID_GET_CONT_ID                        0x830
+#define DPMNG_CMDID_GET_VERSION                        0x831
+
+#endif /* __FSL_DPMNG_CMD_H */
diff --git a/drivers/staging/fsl-mc/bus/dpmng.c b/drivers/staging/fsl-mc/bus/dpmng.c
new file mode 100644 (file)
index 0000000..58328e8
--- /dev/null
@@ -0,0 +1,78 @@
+/* Copyright 2013-2014 Freescale Semiconductor Inc.
+*
+* 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 the above-listed copyright holders nor the
+* names of any contributors may be used to endorse or promote products
+* derived from this software without specific prior written permission.
+*
+*
+* ALTERNATIVELY, this software may be distributed under the terms of the
+* GNU General Public License ("GPL") as published by the Free Software
+* Foundation, either version 2 of that License or (at your option) any
+* later version.
+*
+* THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 "../include/mc-sys.h"
+#include "../include/mc-cmd.h"
+#include "../include/dpmng.h"
+#include "dpmng-cmd.h"
+
+int mc_get_version(struct fsl_mc_io *mc_io, struct mc_version *mc_ver_info)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION,
+                                         MC_CMD_PRI_LOW, 0);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       mc_ver_info->revision = mc_dec(cmd.params[0], 0, 32);
+       mc_ver_info->major = mc_dec(cmd.params[0], 32, 32);
+       mc_ver_info->minor = mc_dec(cmd.params[1], 0, 32);
+
+       return 0;
+}
+
+int dpmng_get_container_id(struct fsl_mc_io *mc_io, int *container_id)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_CONT_ID,
+                                         MC_CMD_PRI_LOW, 0);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *container_id = mc_dec(cmd.params[0], 0, 32);
+
+       return 0;
+}
+
diff --git a/drivers/staging/fsl-mc/bus/dprc-cmd.h b/drivers/staging/fsl-mc/bus/dprc-cmd.h
new file mode 100644 (file)
index 0000000..0920248
--- /dev/null
@@ -0,0 +1,84 @@
+/* Copyright 2013-2014 Freescale Semiconductor Inc.
+ *
+ * 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 the above-listed copyright holders nor the
+ *       names of any contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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.
+ */
+
+/*************************************************************************//*
+ dprc-cmd.h
+
+ defines dprc portal commands
+
+ *//**************************************************************************/
+
+#ifndef _FSL_DPRC_CMD_H
+#define _FSL_DPRC_CMD_H
+
+/* DPRC Version */
+#define DPRC_VER_MAJOR                         3
+#define DPRC_VER_MINOR                         0
+
+/* Command IDs */
+#define DPRC_CMDID_CLOSE                       0x800
+#define DPRC_CMDID_OPEN                                0x805
+#define DPRC_CMDID_CREATE                      0x905
+
+#define DPRC_CMDID_GET_ATTR                    0x004
+#define DPRC_CMDID_RESET_CONT                  0x005
+
+#define DPRC_CMDID_SET_IRQ                     0x010
+#define DPRC_CMDID_GET_IRQ                     0x011
+#define DPRC_CMDID_SET_IRQ_ENABLE              0x012
+#define DPRC_CMDID_GET_IRQ_ENABLE              0x013
+#define DPRC_CMDID_SET_IRQ_MASK                        0x014
+#define DPRC_CMDID_GET_IRQ_MASK                        0x015
+#define DPRC_CMDID_GET_IRQ_STATUS              0x016
+#define DPRC_CMDID_CLEAR_IRQ_STATUS            0x017
+
+#define DPRC_CMDID_CREATE_CONT                 0x151
+#define DPRC_CMDID_DESTROY_CONT                        0x152
+#define DPRC_CMDID_SET_RES_QUOTA               0x155
+#define DPRC_CMDID_GET_RES_QUOTA               0x156
+#define DPRC_CMDID_ASSIGN                      0x157
+#define DPRC_CMDID_UNASSIGN                    0x158
+#define DPRC_CMDID_GET_OBJ_COUNT               0x159
+#define DPRC_CMDID_GET_OBJ                     0x15A
+#define DPRC_CMDID_GET_RES_COUNT               0x15B
+#define DPRC_CMDID_GET_RES_IDS                 0x15C
+#define DPRC_CMDID_GET_OBJ_REG                 0x15E
+
+#define DPRC_CMDID_CONNECT                     0x167
+#define DPRC_CMDID_DISCONNECT                  0x168
+#define DPRC_CMDID_GET_POOL                    0x169
+#define DPRC_CMDID_GET_POOL_COUNT              0x16A
+#define DPRC_CMDID_GET_PORTAL_PADDR            0x16B
+
+#define DPRC_CMDID_GET_CONNECTION              0x16C
+
+#endif /* _FSL_DPRC_CMD_H */
diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c
new file mode 100644 (file)
index 0000000..35c06cf
--- /dev/null
@@ -0,0 +1,486 @@
+/*
+ * Freescale data path resource container (DPRC) driver
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Author: German Rivera <German.Rivera@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include "../include/mc-private.h"
+#include "../include/mc-sys.h"
+#include <linux/module.h>
+#include <linux/slab.h>
+#include "dprc-cmd.h"
+
+struct dprc_child_objs {
+       int child_count;
+       struct dprc_obj_desc *child_array;
+};
+
+static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
+{
+       int i;
+       struct dprc_child_objs *objs;
+       struct fsl_mc_device *mc_dev;
+
+       WARN_ON(!dev);
+       WARN_ON(!data);
+       mc_dev = to_fsl_mc_device(dev);
+       objs = data;
+
+       for (i = 0; i < objs->child_count; i++) {
+               struct dprc_obj_desc *obj_desc = &objs->child_array[i];
+
+               if (strlen(obj_desc->type) != 0 &&
+                   FSL_MC_DEVICE_MATCH(mc_dev, obj_desc))
+                       break;
+       }
+
+       if (i == objs->child_count)
+               fsl_mc_device_remove(mc_dev);
+
+       return 0;
+}
+
+static int __fsl_mc_device_remove(struct device *dev, void *data)
+{
+       WARN_ON(!dev);
+       WARN_ON(data);
+       fsl_mc_device_remove(to_fsl_mc_device(dev));
+       return 0;
+}
+
+/**
+ * dprc_remove_devices - Removes devices for objects removed from a DPRC
+ *
+ * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
+ * @obj_desc_array: array of object descriptors for child objects currently
+ * present in the DPRC in the MC.
+ * @num_child_objects_in_mc: number of entries in obj_desc_array
+ *
+ * Synchronizes the state of the Linux bus driver with the actual state of
+ * the MC by removing devices that represent MC objects that have
+ * been dynamically removed in the physical DPRC.
+ */
+static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev,
+                               struct dprc_obj_desc *obj_desc_array,
+                               int num_child_objects_in_mc)
+{
+       if (num_child_objects_in_mc != 0) {
+               /*
+                * Remove child objects that are in the DPRC in Linux,
+                * but not in the MC:
+                */
+               struct dprc_child_objs objs;
+
+               objs.child_count = num_child_objects_in_mc;
+               objs.child_array = obj_desc_array;
+               device_for_each_child(&mc_bus_dev->dev, &objs,
+                                     __fsl_mc_device_remove_if_not_in_mc);
+       } else {
+               /*
+                * There are no child objects for this DPRC in the MC.
+                * So, remove all the child devices from Linux:
+                */
+               device_for_each_child(&mc_bus_dev->dev, NULL,
+                                     __fsl_mc_device_remove);
+       }
+}
+
+static int __fsl_mc_device_match(struct device *dev, void *data)
+{
+       struct dprc_obj_desc *obj_desc = data;
+       struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+
+       return FSL_MC_DEVICE_MATCH(mc_dev, obj_desc);
+}
+
+static struct fsl_mc_device *fsl_mc_device_lookup(struct dprc_obj_desc
+                                                               *obj_desc,
+                                                 struct fsl_mc_device
+                                                               *mc_bus_dev)
+{
+       struct device *dev;
+
+       dev = device_find_child(&mc_bus_dev->dev, obj_desc,
+                               __fsl_mc_device_match);
+
+       return dev ? to_fsl_mc_device(dev) : NULL;
+}
+
+/**
+ * check_plugged_state_change - Check change in an MC object's plugged state
+ *
+ * @mc_dev: pointer to the fsl-mc device for a given MC object
+ * @obj_desc: pointer to the MC object's descriptor in the MC
+ *
+ * If the plugged state has changed from unplugged to plugged, the fsl-mc
+ * device is bound to the corresponding device driver.
+ * If the plugged state has changed from plugged to unplugged, the fsl-mc
+ * device is unbound from the corresponding device driver.
+ */
+static void check_plugged_state_change(struct fsl_mc_device *mc_dev,
+                                      struct dprc_obj_desc *obj_desc)
+{
+       int error;
+       uint32_t plugged_flag_at_mc =
+                       (obj_desc->state & DPRC_OBJ_STATE_PLUGGED);
+
+       if (plugged_flag_at_mc !=
+           (mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED)) {
+               if (plugged_flag_at_mc) {
+                       mc_dev->obj_desc.state |= DPRC_OBJ_STATE_PLUGGED;
+                       error = device_attach(&mc_dev->dev);
+                       if (error < 0) {
+                               dev_err(&mc_dev->dev,
+                                       "device_attach() failed: %d\n",
+                                       error);
+                       }
+               } else {
+                       mc_dev->obj_desc.state &= ~DPRC_OBJ_STATE_PLUGGED;
+                       device_release_driver(&mc_dev->dev);
+               }
+       }
+}
+
+/**
+ * dprc_add_new_devices - Adds devices to the logical bus for a DPRC
+ *
+ * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
+ * @obj_desc_array: array of device descriptors for child devices currently
+ * present in the physical DPRC.
+ * @num_child_objects_in_mc: number of entries in obj_desc_array
+ *
+ * Synchronizes the state of the Linux bus driver with the actual
+ * state of the MC by adding objects that have been newly discovered
+ * in the physical DPRC.
+ */
+static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
+                                struct dprc_obj_desc *obj_desc_array,
+                                int num_child_objects_in_mc)
+{
+       int error;
+       int i;
+
+       for (i = 0; i < num_child_objects_in_mc; i++) {
+               struct fsl_mc_device *child_dev;
+               struct dprc_obj_desc *obj_desc = &obj_desc_array[i];
+
+               if (strlen(obj_desc->type) == 0)
+                       continue;
+
+               /*
+                * Check if device is already known to Linux:
+                */
+               child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev);
+               if (child_dev) {
+                       check_plugged_state_change(child_dev, obj_desc);
+                       continue;
+               }
+
+               error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev,
+                                         &child_dev);
+               if (error < 0)
+                       continue;
+       }
+}
+
+static void dprc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
+{
+       int pool_type;
+       struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
+
+       for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) {
+               struct fsl_mc_resource_pool *res_pool =
+                   &mc_bus->resource_pools[pool_type];
+
+               res_pool->type = pool_type;
+               res_pool->max_count = 0;
+               res_pool->free_count = 0;
+               res_pool->mc_bus = mc_bus;
+               INIT_LIST_HEAD(&res_pool->free_list);
+               mutex_init(&res_pool->mutex);
+       }
+}
+
+static void dprc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
+                                      enum fsl_mc_pool_type pool_type)
+{
+       struct fsl_mc_resource *resource;
+       struct fsl_mc_resource *next;
+       struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
+       struct fsl_mc_resource_pool *res_pool =
+                                       &mc_bus->resource_pools[pool_type];
+       int free_count = 0;
+
+       WARN_ON(res_pool->type != pool_type);
+       WARN_ON(res_pool->free_count != res_pool->max_count);
+
+       list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
+               free_count++;
+               WARN_ON(resource->type != res_pool->type);
+               WARN_ON(resource->parent_pool != res_pool);
+               devm_kfree(&mc_bus_dev->dev, resource);
+       }
+
+       WARN_ON(free_count != res_pool->free_count);
+}
+
+static void dprc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
+{
+       int pool_type;
+
+       for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++)
+               dprc_cleanup_resource_pool(mc_bus_dev, pool_type);
+}
+
+/**
+ * dprc_scan_objects - Discover objects in a DPRC
+ *
+ * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
+ *
+ * Detects objects added and removed from a DPRC and synchronizes the
+ * state of the Linux bus driver, MC by adding and removing
+ * devices accordingly.
+ * Two types of devices can be found in a DPRC: allocatable objects (e.g.,
+ * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni).
+ * All allocatable devices needed to be probed before all non-allocatable
+ * devices, to ensure that device drivers for non-allocatable
+ * devices can allocate any type of allocatable devices.
+ * That is, we need to ensure that the corresponding resource pools are
+ * populated before they can get allocation requests from probe callbacks
+ * of the device drivers for the non-allocatable devices.
+ */
+int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev)
+{
+       int num_child_objects;
+       int dprc_get_obj_failures;
+       int error;
+       struct dprc_obj_desc *child_obj_desc_array = NULL;
+
+       error = dprc_get_obj_count(mc_bus_dev->mc_io,
+                                  mc_bus_dev->mc_handle,
+                                  &num_child_objects);
+       if (error < 0) {
+               dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n",
+                       error);
+               return error;
+       }
+
+       if (num_child_objects != 0) {
+               int i;
+
+               child_obj_desc_array =
+                   devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects,
+                                      sizeof(*child_obj_desc_array),
+                                      GFP_KERNEL);
+               if (!child_obj_desc_array)
+                       return -ENOMEM;
+
+               /*
+                * Discover objects currently present in the physical DPRC:
+                */
+               dprc_get_obj_failures = 0;
+               for (i = 0; i < num_child_objects; i++) {
+                       struct dprc_obj_desc *obj_desc =
+                           &child_obj_desc_array[i];
+
+                       error = dprc_get_obj(mc_bus_dev->mc_io,
+                                            mc_bus_dev->mc_handle,
+                                            i, obj_desc);
+                       if (error < 0) {
+                               dev_err(&mc_bus_dev->dev,
+                                       "dprc_get_obj(i=%d) failed: %d\n",
+                                       i, error);
+                               /*
+                                * Mark the obj entry as "invalid", by using the
+                                * empty string as obj type:
+                                */
+                               obj_desc->type[0] = '\0';
+                               obj_desc->id = error;
+                               dprc_get_obj_failures++;
+                               continue;
+                       }
+
+                       dev_dbg(&mc_bus_dev->dev,
+                               "Discovered object: type %s, id %d\n",
+                               obj_desc->type, obj_desc->id);
+               }
+
+               if (dprc_get_obj_failures != 0) {
+                       dev_err(&mc_bus_dev->dev,
+                               "%d out of %d devices could not be retrieved\n",
+                               dprc_get_obj_failures, num_child_objects);
+               }
+       }
+
+       dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
+                           num_child_objects);
+
+       dprc_add_new_devices(mc_bus_dev, child_obj_desc_array,
+                            num_child_objects);
+
+       if (child_obj_desc_array)
+               devm_kfree(&mc_bus_dev->dev, child_obj_desc_array);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dprc_scan_objects);
+
+/**
+ * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state
+ *
+ * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
+ *
+ * Scans the physical DPRC and synchronizes the state of the Linux
+ * bus driver with the actual state of the MC by adding and removing
+ * devices as appropriate.
+ */
+int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
+{
+       int error;
+       struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
+
+       dprc_init_all_resource_pools(mc_bus_dev);
+
+       /*
+        * Discover objects in the DPRC:
+        */
+       mutex_lock(&mc_bus->scan_mutex);
+       error = dprc_scan_objects(mc_bus_dev);
+       mutex_unlock(&mc_bus->scan_mutex);
+       if (error < 0)
+               goto error;
+
+       return 0;
+error:
+       dprc_cleanup_all_resource_pools(mc_bus_dev);
+       return error;
+}
+EXPORT_SYMBOL_GPL(dprc_scan_container);
+
+/**
+ * dprc_probe - callback invoked when a DPRC is being bound to this driver
+ *
+ * @mc_dev: Pointer to fsl-mc device representing a DPRC
+ *
+ * It opens the physical DPRC in the MC.
+ * It scans the DPRC to discover the MC objects contained in it.
+ * It creates the interrupt pool for the MC bus associated with the DPRC.
+ * It configures the interrupts for the DPRC device itself.
+ */
+static int dprc_probe(struct fsl_mc_device *mc_dev)
+{
+       int error;
+       size_t region_size;
+       struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
+
+       if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
+               return -EINVAL;
+
+       if (!mc_dev->mc_io) {
+               /*
+                * This is a child DPRC:
+                */
+               if (WARN_ON(mc_dev->obj_desc.region_count == 0))
+                       return -EINVAL;
+
+               region_size = mc_dev->regions[0].end -
+                             mc_dev->regions[0].start + 1;
+
+               error = fsl_create_mc_io(&mc_dev->dev,
+                                        mc_dev->regions[0].start,
+                                        region_size,
+                                        NULL, 0, &mc_dev->mc_io);
+               if (error < 0)
+                       return error;
+       }
+
+       error = dprc_open(mc_dev->mc_io, mc_dev->obj_desc.id,
+                         &mc_dev->mc_handle);
+       if (error < 0) {
+               dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error);
+               goto error_cleanup_mc_io;
+       }
+
+       mutex_init(&mc_bus->scan_mutex);
+
+       /*
+        * Discover MC objects in DPRC object:
+        */
+       error = dprc_scan_container(mc_dev);
+       if (error < 0)
+               goto error_cleanup_open;
+
+       dev_info(&mc_dev->dev, "DPRC device bound to driver");
+       return 0;
+
+error_cleanup_open:
+       (void)dprc_close(mc_dev->mc_io, mc_dev->mc_handle);
+
+error_cleanup_mc_io:
+       fsl_destroy_mc_io(mc_dev->mc_io);
+       return error;
+}
+
+/**
+ * dprc_remove - callback invoked when a DPRC is being unbound from this driver
+ *
+ * @mc_dev: Pointer to fsl-mc device representing the DPRC
+ *
+ * It removes the DPRC's child objects from Linux (not from the MC) and
+ * closes the DPRC device in the MC.
+ * It tears down the interrupts that were configured for the DPRC device.
+ * It destroys the interrupt pool associated with this MC bus.
+ */
+static int dprc_remove(struct fsl_mc_device *mc_dev)
+{
+       int error;
+
+       if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
+               return -EINVAL;
+       if (WARN_ON(!mc_dev->mc_io))
+               return -EINVAL;
+
+       device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
+       dprc_cleanup_all_resource_pools(mc_dev);
+       error = dprc_close(mc_dev->mc_io, mc_dev->mc_handle);
+       if (error < 0)
+               dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error);
+
+       dev_info(&mc_dev->dev, "DPRC device unbound from driver");
+       return 0;
+}
+
+static const struct fsl_mc_device_match_id match_id_table[] = {
+       {
+        .vendor = FSL_MC_VENDOR_FREESCALE,
+        .obj_type = "dprc",
+        .ver_major = DPRC_VER_MAJOR,
+        .ver_minor = DPRC_VER_MINOR},
+       {.vendor = 0x0},
+};
+
+static struct fsl_mc_driver dprc_driver = {
+       .driver = {
+                  .name = FSL_MC_DPRC_DRIVER_NAME,
+                  .owner = THIS_MODULE,
+                  .pm = NULL,
+                  },
+       .match_id_table = match_id_table,
+       .probe = dprc_probe,
+       .remove = dprc_remove,
+};
+
+int __init dprc_driver_init(void)
+{
+       return fsl_mc_driver_register(&dprc_driver);
+}
+
+void __exit dprc_driver_exit(void)
+{
+       fsl_mc_driver_unregister(&dprc_driver);
+}
diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/staging/fsl-mc/bus/dprc.c
new file mode 100644 (file)
index 0000000..19b26e6
--- /dev/null
@@ -0,0 +1,913 @@
+/* Copyright 2013-2014 Freescale Semiconductor Inc.
+*
+* 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 the above-listed copyright holders nor the
+* names of any contributors may be used to endorse or promote products
+* derived from this software without specific prior written permission.
+*
+*
+* ALTERNATIVELY, this software may be distributed under the terms of the
+* GNU General Public License ("GPL") as published by the Free Software
+* Foundation, either version 2 of that License or (at your option) any
+* later version.
+*
+* THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 "../include/mc-sys.h"
+#include "../include/mc-cmd.h"
+#include "../include/dprc.h"
+#include "dprc-cmd.h"
+
+int dprc_open(struct fsl_mc_io *mc_io, int container_id, uint16_t *token)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, MC_CMD_PRI_LOW,
+                                         0);
+       cmd.params[0] |= mc_enc(0, 32, container_id);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+
+       return 0;
+}
+EXPORT_SYMBOL(dprc_open);
+
+int dprc_close(struct fsl_mc_io *mc_io, uint16_t token)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, MC_CMD_PRI_HIGH,
+                                         token);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+EXPORT_SYMBOL(dprc_close);
+
+int dprc_create_container(struct fsl_mc_io *mc_io,
+                         uint16_t token,
+                         struct dprc_cfg *cfg,
+                         int *child_container_id,
+                         uint64_t *child_portal_paddr)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.params[0] |= mc_enc(32, 16, cfg->icid);
+       cmd.params[0] |= mc_enc(0, 32, cfg->options);
+       cmd.params[1] |= mc_enc(32, 32, cfg->portal_id);
+
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_CREATE_CONT,
+                                         MC_CMD_PRI_LOW, token);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *child_container_id = mc_dec(cmd.params[1], 0, 32);
+       *child_portal_paddr = mc_dec(cmd.params[2], 0, 64);
+
+       return 0;
+}
+
+int dprc_destroy_container(struct fsl_mc_io *mc_io,
+                          uint16_t token,
+                          int child_container_id)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_DESTROY_CONT,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 32, child_container_id);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_reset_container(struct fsl_mc_io *mc_io,
+                        uint16_t token,
+                        int child_container_id)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 32, child_container_id);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_get_irq(struct fsl_mc_io *mc_io,
+                uint16_t token,
+                uint8_t irq_index,
+                int *type,
+                uint64_t *irq_paddr,
+                uint32_t *irq_val,
+                int *user_irq_id)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ,
+                                         MC_CMD_PRI_LOW,
+                                         token);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *irq_val = mc_dec(cmd.params[0], 0, 32);
+       *irq_paddr = mc_dec(cmd.params[1], 0, 64);
+       *user_irq_id = mc_dec(cmd.params[2], 0, 32);
+       *type = mc_dec(cmd.params[2], 32, 32);
+
+       return 0;
+}
+
+int dprc_set_irq(struct fsl_mc_io *mc_io,
+                uint16_t token,
+                uint8_t irq_index,
+                uint64_t irq_paddr,
+                uint32_t irq_val,
+                int user_irq_id)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ,
+                                         MC_CMD_PRI_LOW,
+                                         token);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+       cmd.params[0] |= mc_enc(0, 32, irq_val);
+       cmd.params[1] |= mc_enc(0, 64, irq_paddr);
+       cmd.params[2] |= mc_enc(0, 32, user_irq_id);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_get_irq_enable(struct fsl_mc_io *mc_io,
+                       uint16_t token,
+                       uint8_t irq_index,
+                       uint8_t *en)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_ENABLE,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *en = mc_dec(cmd.params[0], 0, 8);
+
+       return 0;
+}
+
+int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
+                       uint16_t token,
+                       uint8_t irq_index,
+                       uint8_t en)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 8, en);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_get_irq_mask(struct fsl_mc_io *mc_io,
+                     uint16_t token,
+                     uint8_t irq_index,
+                     uint32_t *mask)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_MASK,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *mask = mc_dec(cmd.params[0], 0, 32);
+
+       return 0;
+}
+
+int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
+                     uint16_t token,
+                     uint8_t irq_index,
+                     uint32_t mask)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 32, mask);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_get_irq_status(struct fsl_mc_io *mc_io,
+                       uint16_t token,
+                       uint8_t irq_index,
+                       uint32_t *status)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *status = mc_dec(cmd.params[0], 0, 32);
+
+       return 0;
+}
+
+int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
+                         uint16_t token,
+                         uint8_t irq_index,
+                         uint32_t status)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 32, status);
+       cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_get_attributes(struct fsl_mc_io *mc_io,
+                       uint16_t token,
+                       struct dprc_attributes *attr)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR,
+                                         MC_CMD_PRI_LOW,
+                                         token);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       attr->container_id = mc_dec(cmd.params[0], 0, 32);
+       attr->icid = mc_dec(cmd.params[0], 32, 16);
+       attr->options = mc_dec(cmd.params[1], 0, 32);
+       attr->portal_id = mc_dec(cmd.params[1], 32, 32);
+       attr->version.major = mc_dec(cmd.params[2], 0, 16);
+       attr->version.minor = mc_dec(cmd.params[2], 16, 16);
+
+       return 0;
+}
+
+int dprc_set_res_quota(struct fsl_mc_io *mc_io,
+                      uint16_t token,
+                      int child_container_id,
+                      char *type,
+                      uint16_t quota)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_RES_QUOTA,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 32, child_container_id);
+       cmd.params[0] |= mc_enc(32, 16, quota);
+       cmd.params[1] |= mc_enc(0, 8, type[0]);
+       cmd.params[1] |= mc_enc(8, 8, type[1]);
+       cmd.params[1] |= mc_enc(16, 8, type[2]);
+       cmd.params[1] |= mc_enc(24, 8, type[3]);
+       cmd.params[1] |= mc_enc(32, 8, type[4]);
+       cmd.params[1] |= mc_enc(40, 8, type[5]);
+       cmd.params[1] |= mc_enc(48, 8, type[6]);
+       cmd.params[1] |= mc_enc(56, 8, type[7]);
+       cmd.params[2] |= mc_enc(0, 8, type[8]);
+       cmd.params[2] |= mc_enc(8, 8, type[9]);
+       cmd.params[2] |= mc_enc(16, 8, type[10]);
+       cmd.params[2] |= mc_enc(24, 8, type[11]);
+       cmd.params[2] |= mc_enc(32, 8, type[12]);
+       cmd.params[2] |= mc_enc(40, 8, type[13]);
+       cmd.params[2] |= mc_enc(48, 8, type[14]);
+       cmd.params[2] |= mc_enc(56, 8, '\0');
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_get_res_quota(struct fsl_mc_io *mc_io,
+                      uint16_t token,
+                      int child_container_id,
+                      char *type,
+                      uint16_t *quota)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_QUOTA,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 32, child_container_id);
+       cmd.params[1] |= mc_enc(0, 8, type[0]);
+       cmd.params[1] |= mc_enc(8, 8, type[1]);
+       cmd.params[1] |= mc_enc(16, 8, type[2]);
+       cmd.params[1] |= mc_enc(24, 8, type[3]);
+       cmd.params[1] |= mc_enc(32, 8, type[4]);
+       cmd.params[1] |= mc_enc(40, 8, type[5]);
+       cmd.params[1] |= mc_enc(48, 8, type[6]);
+       cmd.params[1] |= mc_enc(56, 8, type[7]);
+       cmd.params[2] |= mc_enc(0, 8, type[8]);
+       cmd.params[2] |= mc_enc(8, 8, type[9]);
+       cmd.params[2] |= mc_enc(16, 8, type[10]);
+       cmd.params[2] |= mc_enc(24, 8, type[11]);
+       cmd.params[2] |= mc_enc(32, 8, type[12]);
+       cmd.params[2] |= mc_enc(40, 8, type[13]);
+       cmd.params[2] |= mc_enc(48, 8, type[14]);
+       cmd.params[2] |= mc_enc(56, 8, '\0');
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *quota = mc_dec(cmd.params[0], 32, 16);
+
+       return 0;
+}
+
+int dprc_assign(struct fsl_mc_io *mc_io,
+               uint16_t token,
+               int container_id,
+               struct dprc_res_req *res_req)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_ASSIGN,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 32, container_id);
+       cmd.params[0] |= mc_enc(32, 32, res_req->options);
+       cmd.params[1] |= mc_enc(0, 32, res_req->num);
+       cmd.params[1] |= mc_enc(32, 32, res_req->id_base_align);
+       cmd.params[2] |= mc_enc(0, 8, res_req->type[0]);
+       cmd.params[2] |= mc_enc(8, 8, res_req->type[1]);
+       cmd.params[2] |= mc_enc(16, 8, res_req->type[2]);
+       cmd.params[2] |= mc_enc(24, 8, res_req->type[3]);
+       cmd.params[2] |= mc_enc(32, 8, res_req->type[4]);
+       cmd.params[2] |= mc_enc(40, 8, res_req->type[5]);
+       cmd.params[2] |= mc_enc(48, 8, res_req->type[6]);
+       cmd.params[2] |= mc_enc(56, 8, res_req->type[7]);
+       cmd.params[3] |= mc_enc(0, 8, res_req->type[8]);
+       cmd.params[3] |= mc_enc(8, 8, res_req->type[9]);
+       cmd.params[3] |= mc_enc(16, 8, res_req->type[10]);
+       cmd.params[3] |= mc_enc(24, 8, res_req->type[11]);
+       cmd.params[3] |= mc_enc(32, 8, res_req->type[12]);
+       cmd.params[3] |= mc_enc(40, 8, res_req->type[13]);
+       cmd.params[3] |= mc_enc(48, 8, res_req->type[14]);
+       cmd.params[3] |= mc_enc(56, 8, res_req->type[15]);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_unassign(struct fsl_mc_io *mc_io,
+                 uint16_t token,
+                 int child_container_id,
+                 struct dprc_res_req *res_req)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_UNASSIGN,
+                                         MC_CMD_PRI_LOW,
+                                         token);
+       cmd.params[0] |= mc_enc(0, 32, child_container_id);
+       cmd.params[0] |= mc_enc(32, 32, res_req->options);
+       cmd.params[1] |= mc_enc(0, 32, res_req->num);
+       cmd.params[1] |= mc_enc(32, 32, res_req->id_base_align);
+       cmd.params[2] |= mc_enc(0, 8, res_req->type[0]);
+       cmd.params[2] |= mc_enc(8, 8, res_req->type[1]);
+       cmd.params[2] |= mc_enc(16, 8, res_req->type[2]);
+       cmd.params[2] |= mc_enc(24, 8, res_req->type[3]);
+       cmd.params[2] |= mc_enc(32, 8, res_req->type[4]);
+       cmd.params[2] |= mc_enc(40, 8, res_req->type[5]);
+       cmd.params[2] |= mc_enc(48, 8, res_req->type[6]);
+       cmd.params[2] |= mc_enc(56, 8, res_req->type[7]);
+       cmd.params[3] |= mc_enc(0, 8, res_req->type[8]);
+       cmd.params[3] |= mc_enc(8, 8, res_req->type[9]);
+       cmd.params[3] |= mc_enc(16, 8, res_req->type[10]);
+       cmd.params[3] |= mc_enc(24, 8, res_req->type[11]);
+       cmd.params[3] |= mc_enc(32, 8, res_req->type[12]);
+       cmd.params[3] |= mc_enc(40, 8, res_req->type[13]);
+       cmd.params[3] |= mc_enc(48, 8, res_req->type[14]);
+       cmd.params[3] |= mc_enc(56, 8, res_req->type[15]);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_get_pool_count(struct fsl_mc_io *mc_io,
+                       uint16_t token,
+                       int *pool_count)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_POOL_COUNT,
+                                         MC_CMD_PRI_LOW, token);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *pool_count = mc_dec(cmd.params[0], 0, 32);
+
+       return 0;
+}
+
+int dprc_get_pool(struct fsl_mc_io *mc_io,
+                 uint16_t token,
+                 int pool_index,
+                 char *type)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_POOL,
+                                         MC_CMD_PRI_LOW,
+                                         token);
+       cmd.params[0] |= mc_enc(0, 32, pool_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       type[0] = mc_dec(cmd.params[1], 0, 8);
+       type[1] = mc_dec(cmd.params[1], 8, 8);
+       type[2] = mc_dec(cmd.params[1], 16, 8);
+       type[3] = mc_dec(cmd.params[1], 24, 8);
+       type[4] = mc_dec(cmd.params[1], 32, 8);
+       type[5] = mc_dec(cmd.params[1], 40, 8);
+       type[6] = mc_dec(cmd.params[1], 48, 8);
+       type[7] = mc_dec(cmd.params[1], 56, 8);
+       type[8] = mc_dec(cmd.params[2], 0, 8);
+       type[9] = mc_dec(cmd.params[2], 8, 8);
+       type[10] = mc_dec(cmd.params[2], 16, 8);
+       type[11] = mc_dec(cmd.params[2], 24, 8);
+       type[12] = mc_dec(cmd.params[2], 32, 8);
+       type[13] = mc_dec(cmd.params[2], 40, 8);
+       type[14] = mc_dec(cmd.params[2], 48, 8);
+       type[15] = '\0';
+
+       return 0;
+}
+
+int dprc_get_obj_count(struct fsl_mc_io *mc_io, uint16_t token, int *obj_count)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT,
+                                         MC_CMD_PRI_LOW, token);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *obj_count = mc_dec(cmd.params[0], 32, 32);
+
+       return 0;
+}
+EXPORT_SYMBOL(dprc_get_obj_count);
+
+int dprc_get_obj(struct fsl_mc_io *mc_io,
+                uint16_t token,
+                int obj_index,
+                struct dprc_obj_desc *obj_desc)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ,
+                                         MC_CMD_PRI_LOW,
+                                         token);
+       cmd.params[0] |= mc_enc(0, 32, obj_index);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       obj_desc->id = mc_dec(cmd.params[0], 32, 32);
+       obj_desc->vendor = mc_dec(cmd.params[1], 0, 16);
+       obj_desc->irq_count = mc_dec(cmd.params[1], 16, 8);
+       obj_desc->region_count = mc_dec(cmd.params[1], 24, 8);
+       obj_desc->state = mc_dec(cmd.params[1], 32, 32);
+       obj_desc->ver_major = mc_dec(cmd.params[2], 0, 16);
+       obj_desc->ver_minor = mc_dec(cmd.params[2], 16, 16);
+       obj_desc->type[0] = mc_dec(cmd.params[3], 0, 8);
+       obj_desc->type[1] = mc_dec(cmd.params[3], 8, 8);
+       obj_desc->type[2] = mc_dec(cmd.params[3], 16, 8);
+       obj_desc->type[3] = mc_dec(cmd.params[3], 24, 8);
+       obj_desc->type[4] = mc_dec(cmd.params[3], 32, 8);
+       obj_desc->type[5] = mc_dec(cmd.params[3], 40, 8);
+       obj_desc->type[6] = mc_dec(cmd.params[3], 48, 8);
+       obj_desc->type[7] = mc_dec(cmd.params[3], 56, 8);
+       obj_desc->type[8] = mc_dec(cmd.params[4], 0, 8);
+       obj_desc->type[9] = mc_dec(cmd.params[4], 8, 8);
+       obj_desc->type[10] = mc_dec(cmd.params[4], 16, 8);
+       obj_desc->type[11] = mc_dec(cmd.params[4], 24, 8);
+       obj_desc->type[12] = mc_dec(cmd.params[4], 32, 8);
+       obj_desc->type[13] = mc_dec(cmd.params[4], 40, 8);
+       obj_desc->type[14] = mc_dec(cmd.params[4], 48, 8);
+       obj_desc->type[15] = '\0';
+
+       return 0;
+}
+EXPORT_SYMBOL(dprc_get_obj);
+
+int dprc_get_res_count(struct fsl_mc_io *mc_io,
+                      uint16_t token,
+                      char *type,
+                      int *res_count)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       *res_count = 0;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[1] |= mc_enc(0, 8, type[0]);
+       cmd.params[1] |= mc_enc(8, 8, type[1]);
+       cmd.params[1] |= mc_enc(16, 8, type[2]);
+       cmd.params[1] |= mc_enc(24, 8, type[3]);
+       cmd.params[1] |= mc_enc(32, 8, type[4]);
+       cmd.params[1] |= mc_enc(40, 8, type[5]);
+       cmd.params[1] |= mc_enc(48, 8, type[6]);
+       cmd.params[1] |= mc_enc(56, 8, type[7]);
+       cmd.params[2] |= mc_enc(0, 8, type[8]);
+       cmd.params[2] |= mc_enc(8, 8, type[9]);
+       cmd.params[2] |= mc_enc(16, 8, type[10]);
+       cmd.params[2] |= mc_enc(24, 8, type[11]);
+       cmd.params[2] |= mc_enc(32, 8, type[12]);
+       cmd.params[2] |= mc_enc(40, 8, type[13]);
+       cmd.params[2] |= mc_enc(48, 8, type[14]);
+       cmd.params[2] |= mc_enc(56, 8, '\0');
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *res_count = mc_dec(cmd.params[0], 0, 32);
+
+       return 0;
+}
+EXPORT_SYMBOL(dprc_get_res_count);
+
+int dprc_get_res_ids(struct fsl_mc_io *mc_io,
+                    uint16_t token,
+                    char *type,
+                    struct dprc_res_ids_range_desc *range_desc)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_IDS,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(42, 7, range_desc->iter_status);
+       cmd.params[1] |= mc_enc(0, 32, range_desc->base_id);
+       cmd.params[1] |= mc_enc(32, 32, range_desc->last_id);
+       cmd.params[2] |= mc_enc(0, 8, type[0]);
+       cmd.params[2] |= mc_enc(8, 8, type[1]);
+       cmd.params[2] |= mc_enc(16, 8, type[2]);
+       cmd.params[2] |= mc_enc(24, 8, type[3]);
+       cmd.params[2] |= mc_enc(32, 8, type[4]);
+       cmd.params[2] |= mc_enc(40, 8, type[5]);
+       cmd.params[2] |= mc_enc(48, 8, type[6]);
+       cmd.params[2] |= mc_enc(56, 8, type[7]);
+       cmd.params[3] |= mc_enc(0, 8, type[8]);
+       cmd.params[3] |= mc_enc(8, 8, type[9]);
+       cmd.params[3] |= mc_enc(16, 8, type[10]);
+       cmd.params[3] |= mc_enc(24, 8, type[11]);
+       cmd.params[3] |= mc_enc(32, 8, type[12]);
+       cmd.params[3] |= mc_enc(40, 8, type[13]);
+       cmd.params[3] |= mc_enc(48, 8, type[14]);
+       cmd.params[3] |= mc_enc(56, 8, '\0');
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       range_desc->iter_status = mc_dec(cmd.params[0], 42, 7);
+       range_desc->base_id = mc_dec(cmd.params[1], 0, 32);
+       range_desc->last_id = mc_dec(cmd.params[1], 32, 32);
+
+       return 0;
+}
+EXPORT_SYMBOL(dprc_get_res_ids);
+
+int dprc_get_portal_paddr(struct fsl_mc_io *mc_io,
+                         uint16_t token,
+                         int portal_id,
+                         uint64_t *portal_addr)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_PORTAL_PADDR,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 32, portal_id);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       *portal_addr = mc_dec(cmd.params[1], 0, 64);
+
+       return 0;
+}
+EXPORT_SYMBOL(dprc_get_portal_paddr);
+
+int dprc_get_obj_region(struct fsl_mc_io *mc_io,
+                       uint16_t token,
+                       char *obj_type,
+                       int obj_id,
+                       uint8_t region_index,
+                       struct dprc_region_desc *region_desc)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG,
+                                         MC_CMD_PRI_LOW, token);
+       cmd.params[0] |= mc_enc(0, 32, obj_id);
+       cmd.params[0] |= mc_enc(48, 8, region_index);
+       cmd.params[3] |= mc_enc(0, 8, obj_type[0]);
+       cmd.params[3] |= mc_enc(8, 8, obj_type[1]);
+       cmd.params[3] |= mc_enc(16, 8, obj_type[2]);
+       cmd.params[3] |= mc_enc(24, 8, obj_type[3]);
+       cmd.params[3] |= mc_enc(32, 8, obj_type[4]);
+       cmd.params[3] |= mc_enc(40, 8, obj_type[5]);
+       cmd.params[3] |= mc_enc(48, 8, obj_type[6]);
+       cmd.params[3] |= mc_enc(56, 8, obj_type[7]);
+       cmd.params[4] |= mc_enc(0, 8, obj_type[8]);
+       cmd.params[4] |= mc_enc(8, 8, obj_type[9]);
+       cmd.params[4] |= mc_enc(16, 8, obj_type[10]);
+       cmd.params[4] |= mc_enc(24, 8, obj_type[11]);
+       cmd.params[4] |= mc_enc(32, 8, obj_type[12]);
+       cmd.params[4] |= mc_enc(40, 8, obj_type[13]);
+       cmd.params[4] |= mc_enc(48, 8, obj_type[14]);
+       cmd.params[4] |= mc_enc(56, 8, '\0');
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       region_desc->base_paddr = mc_dec(cmd.params[1], 0, 64);
+       region_desc->size = mc_dec(cmd.params[2], 0, 32);
+
+       return 0;
+}
+EXPORT_SYMBOL(dprc_get_obj_region);
+
+int dprc_connect(struct fsl_mc_io *mc_io,
+                uint16_t token,
+                const struct dprc_endpoint *endpoint1,
+                const struct dprc_endpoint *endpoint2)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_CONNECT,
+                                         MC_CMD_PRI_LOW,
+                                         token);
+       cmd.params[0] |= mc_enc(0, 32, endpoint1->id);
+       cmd.params[0] |= mc_enc(32, 32, endpoint1->interface_id);
+       cmd.params[1] |= mc_enc(0, 32, endpoint2->id);
+       cmd.params[1] |= mc_enc(32, 32, endpoint2->interface_id);
+       cmd.params[2] |= mc_enc(0, 8, endpoint1->type[0]);
+       cmd.params[2] |= mc_enc(8, 8, endpoint1->type[1]);
+       cmd.params[2] |= mc_enc(16, 8, endpoint1->type[2]);
+       cmd.params[2] |= mc_enc(24, 8, endpoint1->type[3]);
+       cmd.params[2] |= mc_enc(32, 8, endpoint1->type[4]);
+       cmd.params[2] |= mc_enc(40, 8, endpoint1->type[5]);
+       cmd.params[2] |= mc_enc(48, 8, endpoint1->type[6]);
+       cmd.params[2] |= mc_enc(56, 8, endpoint1->type[7]);
+       cmd.params[3] |= mc_enc(0, 8, endpoint1->type[8]);
+       cmd.params[3] |= mc_enc(8, 8, endpoint1->type[9]);
+       cmd.params[3] |= mc_enc(16, 8, endpoint1->type[10]);
+       cmd.params[3] |= mc_enc(24, 8, endpoint1->type[11]);
+       cmd.params[3] |= mc_enc(32, 8, endpoint1->type[12]);
+       cmd.params[3] |= mc_enc(40, 8, endpoint1->type[13]);
+       cmd.params[3] |= mc_enc(48, 8, endpoint1->type[14]);
+       cmd.params[3] |= mc_enc(56, 8, endpoint1->type[15]);
+       cmd.params[5] |= mc_enc(0, 8, endpoint2->type[0]);
+       cmd.params[5] |= mc_enc(8, 8, endpoint2->type[1]);
+       cmd.params[5] |= mc_enc(16, 8, endpoint2->type[2]);
+       cmd.params[5] |= mc_enc(24, 8, endpoint2->type[3]);
+       cmd.params[5] |= mc_enc(32, 8, endpoint2->type[4]);
+       cmd.params[5] |= mc_enc(40, 8, endpoint2->type[5]);
+       cmd.params[5] |= mc_enc(48, 8, endpoint2->type[6]);
+       cmd.params[5] |= mc_enc(56, 8, endpoint2->type[7]);
+       cmd.params[6] |= mc_enc(0, 8, endpoint2->type[8]);
+       cmd.params[6] |= mc_enc(8, 8, endpoint2->type[9]);
+       cmd.params[6] |= mc_enc(16, 8, endpoint2->type[10]);
+       cmd.params[6] |= mc_enc(24, 8, endpoint2->type[11]);
+       cmd.params[6] |= mc_enc(32, 8, endpoint2->type[12]);
+       cmd.params[6] |= mc_enc(40, 8, endpoint2->type[13]);
+       cmd.params[6] |= mc_enc(48, 8, endpoint2->type[14]);
+       cmd.params[6] |= mc_enc(56, 8, endpoint2->type[15]);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_disconnect(struct fsl_mc_io *mc_io,
+                   uint16_t token,
+                   const struct dprc_endpoint *endpoint)
+{
+       struct mc_command cmd = { 0 };
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_DISCONNECT,
+                                         MC_CMD_PRI_LOW,
+                                         token);
+       cmd.params[0] |= mc_enc(0, 32, endpoint->id);
+       cmd.params[0] |= mc_enc(32, 32, endpoint->interface_id);
+       cmd.params[1] |= mc_enc(0, 8, endpoint->type[0]);
+       cmd.params[1] |= mc_enc(8, 8, endpoint->type[1]);
+       cmd.params[1] |= mc_enc(16, 8, endpoint->type[2]);
+       cmd.params[1] |= mc_enc(24, 8, endpoint->type[3]);
+       cmd.params[1] |= mc_enc(32, 8, endpoint->type[4]);
+       cmd.params[1] |= mc_enc(40, 8, endpoint->type[5]);
+       cmd.params[1] |= mc_enc(48, 8, endpoint->type[6]);
+       cmd.params[1] |= mc_enc(56, 8, endpoint->type[7]);
+       cmd.params[2] |= mc_enc(0, 8, endpoint->type[8]);
+       cmd.params[2] |= mc_enc(8, 8, endpoint->type[9]);
+       cmd.params[2] |= mc_enc(16, 8, endpoint->type[10]);
+       cmd.params[2] |= mc_enc(24, 8, endpoint->type[11]);
+       cmd.params[2] |= mc_enc(32, 8, endpoint->type[12]);
+       cmd.params[2] |= mc_enc(40, 8, endpoint->type[13]);
+       cmd.params[2] |= mc_enc(48, 8, endpoint->type[14]);
+       cmd.params[2] |= mc_enc(56, 8, endpoint->type[15]);
+
+       /* send command to mc*/
+       return mc_send_command(mc_io, &cmd);
+}
+
+int dprc_get_connection(struct fsl_mc_io *mc_io,
+                       uint16_t token,
+                                       const struct dprc_endpoint *endpoint1,
+                                       struct dprc_endpoint *endpoint2,
+                                       int *state)
+{
+       struct mc_command cmd = { 0 };
+       int err;
+
+       /* prepare command */
+       cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION,
+                                         MC_CMD_PRI_LOW,
+                                         token);
+       cmd.params[0] |= mc_enc(0, 32, endpoint1->id);
+       cmd.params[0] |= mc_enc(32, 32, endpoint1->interface_id);
+       cmd.params[1] |= mc_enc(0, 8, endpoint1->type[0]);
+       cmd.params[1] |= mc_enc(8, 8, endpoint1->type[1]);
+       cmd.params[1] |= mc_enc(16, 8, endpoint1->type[2]);
+       cmd.params[1] |= mc_enc(24, 8, endpoint1->type[3]);
+       cmd.params[1] |= mc_enc(32, 8, endpoint1->type[4]);
+       cmd.params[1] |= mc_enc(40, 8, endpoint1->type[5]);
+       cmd.params[1] |= mc_enc(48, 8, endpoint1->type[6]);
+       cmd.params[1] |= mc_enc(56, 8, endpoint1->type[7]);
+       cmd.params[2] |= mc_enc(0, 8, endpoint1->type[8]);
+       cmd.params[2] |= mc_enc(8, 8, endpoint1->type[9]);
+       cmd.params[2] |= mc_enc(16, 8, endpoint1->type[10]);
+       cmd.params[2] |= mc_enc(24, 8, endpoint1->type[11]);
+       cmd.params[2] |= mc_enc(32, 8, endpoint1->type[12]);
+       cmd.params[2] |= mc_enc(40, 8, endpoint1->type[13]);
+       cmd.params[2] |= mc_enc(48, 8, endpoint1->type[14]);
+       cmd.params[2] |= mc_enc(56, 8, endpoint1->type[15]);
+
+       /* send command to mc*/
+       err = mc_send_command(mc_io, &cmd);
+       if (err)
+               return err;
+
+       /* retrieve response parameters */
+       endpoint2->id = mc_dec(cmd.params[3], 0, 32);
+       endpoint2->interface_id = mc_dec(cmd.params[3], 32, 32);
+       endpoint2->type[0] = mc_dec(cmd.params[4], 0, 8);
+       endpoint2->type[1] = mc_dec(cmd.params[4], 8, 8);
+       endpoint2->type[2] = mc_dec(cmd.params[4], 16, 8);
+       endpoint2->type[3] = mc_dec(cmd.params[4], 24, 8);
+       endpoint2->type[4] = mc_dec(cmd.params[4], 32, 8);
+       endpoint2->type[5] = mc_dec(cmd.params[4], 40, 8);
+       endpoint2->type[6] = mc_dec(cmd.params[4], 48, 8);
+       endpoint2->type[7] = mc_dec(cmd.params[4], 56, 8);
+       endpoint2->type[8] = mc_dec(cmd.params[5], 0, 8);
+       endpoint2->type[9] = mc_dec(cmd.params[5], 8, 8);
+       endpoint2->type[10] = mc_dec(cmd.params[5], 16, 8);
+       endpoint2->type[11] = mc_dec(cmd.params[5], 24, 8);
+       endpoint2->type[12] = mc_dec(cmd.params[5], 32, 8);
+       endpoint2->type[13] = mc_dec(cmd.params[5], 40, 8);
+       endpoint2->type[14] = mc_dec(cmd.params[5], 48, 8);
+       endpoint2->type[15] = mc_dec(cmd.params[5], 56, 8);
+       *state = mc_dec(cmd.params[6], 0, 32);
+
+       return 0;
+}
diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c
new file mode 100644 (file)
index 0000000..e36235d
--- /dev/null
@@ -0,0 +1,573 @@
+/*
+ * Freescale MC object device allocator driver
+ *
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include "../include/mc-private.h"
+#include "../include/mc-sys.h"
+#include <linux/module.h>
+#include "../include/dpbp-cmd.h"
+#include "../include/dpcon-cmd.h"
+#include "dpmcp-cmd.h"
+#include "dpmcp.h"
+
+/**
+ * fsl_mc_resource_pool_add_device - add allocatable device to a resource
+ * pool of a given MC bus
+ *
+ * @mc_bus: pointer to the MC bus
+ * @pool_type: MC bus pool type
+ * @mc_dev: Pointer to allocatable MC object device
+ *
+ * It adds an allocatable MC object device to a container's resource pool of
+ * the given resource type
+ */
+static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
+                                                               *mc_bus,
+                                                       enum fsl_mc_pool_type
+                                                               pool_type,
+                                                       struct fsl_mc_device
+                                                               *mc_dev)
+{
+       struct fsl_mc_resource_pool *res_pool;
+       struct fsl_mc_resource *resource;
+       struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
+       int error = -EINVAL;
+       bool mutex_locked = false;
+
+       if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
+               goto out;
+       if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
+               goto out;
+       if (WARN_ON(mc_dev->resource))
+               goto out;
+
+       res_pool = &mc_bus->resource_pools[pool_type];
+       if (WARN_ON(res_pool->type != pool_type))
+               goto out;
+       if (WARN_ON(res_pool->mc_bus != mc_bus))
+               goto out;
+
+       mutex_lock(&res_pool->mutex);
+       mutex_locked = true;
+
+       if (WARN_ON(res_pool->max_count < 0))
+               goto out;
+       if (WARN_ON(res_pool->free_count < 0 ||
+                   res_pool->free_count > res_pool->max_count))
+               goto out;
+
+       resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
+                               GFP_KERNEL);
+       if (!resource) {
+               error = -ENOMEM;
+               dev_err(&mc_bus_dev->dev,
+                       "Failed to allocate memory for fsl_mc_resource\n");
+               goto out;
+       }
+
+       resource->type = pool_type;
+       resource->id = mc_dev->obj_desc.id;
+       resource->data = mc_dev;
+       resource->parent_pool = res_pool;
+       INIT_LIST_HEAD(&resource->node);
+       list_add_tail(&resource->node, &res_pool->free_list);
+       mc_dev->resource = resource;
+       res_pool->free_count++;
+       res_pool->max_count++;
+       error = 0;
+out:
+       if (mutex_locked)
+               mutex_unlock(&res_pool->mutex);
+
+       return error;
+}
+
+/**
+ * fsl_mc_resource_pool_remove_device - remove an allocatable device from a
+ * resource pool
+ *
+ * @mc_dev: Pointer to allocatable MC object device
+ *
+ * It permanently removes an allocatable MC object device from the resource
+ * pool, the device is currently in, as long as it is in the pool's free list.
+ */
+static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
+                                                                  *mc_dev)
+{
+       struct fsl_mc_device *mc_bus_dev;
+       struct fsl_mc_bus *mc_bus;
+       struct fsl_mc_resource_pool *res_pool;
+       struct fsl_mc_resource *resource;
+       int error = -EINVAL;
+       bool mutex_locked = false;
+
+       if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
+               goto out;
+
+       resource = mc_dev->resource;
+       if (WARN_ON(resource->data != mc_dev))
+               goto out;
+
+       mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
+       mc_bus = to_fsl_mc_bus(mc_bus_dev);
+       res_pool = resource->parent_pool;
+       if (WARN_ON(res_pool != &mc_bus->resource_pools[resource->type]))
+               goto out;
+
+       mutex_lock(&res_pool->mutex);
+       mutex_locked = true;
+
+       if (WARN_ON(res_pool->max_count <= 0))
+               goto out;
+       if (WARN_ON(res_pool->free_count <= 0 ||
+                   res_pool->free_count > res_pool->max_count))
+               goto out;
+
+       /*
+        * If the device is currently allocated, its resource is not
+        * in the free list and thus, the device cannot be removed.
+        */
+       if (list_empty(&resource->node)) {
+               error = -EBUSY;
+               dev_err(&mc_bus_dev->dev,
+                       "Device %s cannot be removed from resource pool\n",
+                       dev_name(&mc_dev->dev));
+               goto out;
+       }
+
+       list_del(&resource->node);
+       INIT_LIST_HEAD(&resource->node);
+       res_pool->free_count--;
+       res_pool->max_count--;
+
+       devm_kfree(&mc_bus_dev->dev, resource);
+       mc_dev->resource = NULL;
+       error = 0;
+out:
+       if (mutex_locked)
+               mutex_unlock(&res_pool->mutex);
+
+       return error;
+}
+
+static const char *const fsl_mc_pool_type_strings[] = {
+       [FSL_MC_POOL_DPMCP] = "dpmcp",
+       [FSL_MC_POOL_DPBP] = "dpbp",
+       [FSL_MC_POOL_DPCON] = "dpcon",
+};
+
+static int __must_check object_type_to_pool_type(const char *object_type,
+                                                enum fsl_mc_pool_type
+                                                               *pool_type)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) {
+               if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) {
+                       *pool_type = i;
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
+                                         enum fsl_mc_pool_type pool_type,
+                                         struct fsl_mc_resource **new_resource)
+{
+       struct fsl_mc_resource_pool *res_pool;
+       struct fsl_mc_resource *resource;
+       struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
+       int error = -EINVAL;
+       bool mutex_locked = false;
+
+       BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) !=
+                    FSL_MC_NUM_POOL_TYPES);
+
+       *new_resource = NULL;
+       if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
+               goto error;
+
+       res_pool = &mc_bus->resource_pools[pool_type];
+       if (WARN_ON(res_pool->mc_bus != mc_bus))
+               goto error;
+
+       mutex_lock(&res_pool->mutex);
+       mutex_locked = true;
+       resource = list_first_entry_or_null(&res_pool->free_list,
+                                           struct fsl_mc_resource, node);
+
+       if (!resource) {
+               WARN_ON(res_pool->free_count != 0);
+               error = -ENXIO;
+               dev_err(&mc_bus_dev->dev,
+                       "No more resources of type %s left\n",
+                       fsl_mc_pool_type_strings[pool_type]);
+               goto error;
+       }
+
+       if (WARN_ON(resource->type != pool_type))
+               goto error;
+       if (WARN_ON(resource->parent_pool != res_pool))
+               goto error;
+       if (WARN_ON(res_pool->free_count <= 0 ||
+                   res_pool->free_count > res_pool->max_count))
+               goto error;
+
+       list_del(&resource->node);
+       INIT_LIST_HEAD(&resource->node);
+
+       res_pool->free_count--;
+       mutex_unlock(&res_pool->mutex);
+       *new_resource = resource;
+       return 0;
+error:
+       if (mutex_locked)
+               mutex_unlock(&res_pool->mutex);
+
+       return error;
+}
+EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
+
+void fsl_mc_resource_free(struct fsl_mc_resource *resource)
+{
+       struct fsl_mc_resource_pool *res_pool;
+       bool mutex_locked = false;
+
+       res_pool = resource->parent_pool;
+       if (WARN_ON(resource->type != res_pool->type))
+               goto out;
+
+       mutex_lock(&res_pool->mutex);
+       mutex_locked = true;
+       if (WARN_ON(res_pool->free_count < 0 ||
+                   res_pool->free_count >= res_pool->max_count))
+               goto out;
+
+       if (WARN_ON(!list_empty(&resource->node)))
+               goto out;
+
+       list_add_tail(&resource->node, &res_pool->free_list);
+       res_pool->free_count++;
+out:
+       if (mutex_locked)
+               mutex_unlock(&res_pool->mutex);
+}
+EXPORT_SYMBOL_GPL(fsl_mc_resource_free);
+
+/**
+ * fsl_mc_portal_allocate - Allocates an MC portal
+ *
+ * @mc_dev: MC device for which the MC portal is to be allocated
+ * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated
+ * MC portal.
+ * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object
+ * that wraps the allocated MC portal is to be returned
+ *
+ * This function allocates an MC portal from the device's parent DPRC,
+ * from the corresponding MC bus' pool of MC portals and wraps
+ * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the
+ * portal is allocated from its own MC bus.
+ */
+int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
+                                       uint16_t mc_io_flags,
+                                       struct fsl_mc_io **new_mc_io)
+{
+       struct fsl_mc_device *mc_bus_dev;
+       struct fsl_mc_bus *mc_bus;
+       phys_addr_t mc_portal_phys_addr;
+       size_t mc_portal_size;
+       struct fsl_mc_device *mc_adev;
+       int error = -EINVAL;
+       struct fsl_mc_resource *resource = NULL;
+       struct fsl_mc_io *mc_io = NULL;
+
+       if (mc_dev->flags & FSL_MC_IS_DPRC) {
+               mc_bus_dev = mc_dev;
+       } else {
+               if (WARN_ON(mc_dev->dev.parent->bus != &fsl_mc_bus_type))
+                       return error;
+
+               mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
+       }
+
+       mc_bus = to_fsl_mc_bus(mc_bus_dev);
+       *new_mc_io = NULL;
+       error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource);
+       if (error < 0)
+               return error;
+
+       mc_adev = resource->data;
+       if (WARN_ON(!mc_adev))
+               goto error_cleanup_resource;
+
+       if (WARN_ON(mc_adev->obj_desc.region_count == 0))
+               goto error_cleanup_resource;
+
+       mc_portal_phys_addr = mc_adev->regions[0].start;
+       mc_portal_size = mc_adev->regions[0].end -
+                        mc_adev->regions[0].start + 1;
+
+       if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size))
+               goto error_cleanup_resource;
+
+       error = fsl_create_mc_io(&mc_bus_dev->dev,
+                                mc_portal_phys_addr,
+                                mc_portal_size, resource,
+                                mc_io_flags, &mc_io);
+       if (error < 0)
+               goto error_cleanup_resource;
+
+       *new_mc_io = mc_io;
+       return 0;
+
+error_cleanup_resource:
+       fsl_mc_resource_free(resource);
+       return error;
+}
+EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate);
+
+/**
+ * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals
+ * of a given MC bus
+ *
+ * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
+ */
+void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
+{
+       struct fsl_mc_resource *resource;
+
+       resource = mc_io->resource;
+       if (WARN_ON(resource->type != FSL_MC_POOL_DPMCP))
+               return;
+       if (WARN_ON(!resource->data))
+               return;
+
+       fsl_destroy_mc_io(mc_io);
+       fsl_mc_resource_free(resource);
+}
+EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
+
+/**
+ * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
+ *
+ * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
+ */
+int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
+{
+       int error;
+       uint16_t token;
+       struct fsl_mc_resource *resource = mc_io->resource;
+       struct fsl_mc_device *mc_dev = resource->data;
+
+       if (WARN_ON(resource->type != FSL_MC_POOL_DPMCP))
+               return -EINVAL;
+
+       if (WARN_ON(!mc_dev))
+               return -EINVAL;
+
+       error = dpmcp_open(mc_io, mc_dev->obj_desc.id, &token);
+       if (error < 0) {
+               dev_err(&mc_dev->dev, "dpmcp_open() failed: %d\n", error);
+               return error;
+       }
+
+       error = dpmcp_reset(mc_io, token);
+       if (error < 0) {
+               dev_err(&mc_dev->dev, "dpmcp_reset() failed: %d\n", error);
+               return error;
+       }
+
+       error = dpmcp_close(mc_io, token);
+       if (error < 0) {
+               dev_err(&mc_dev->dev, "dpmcp_close() failed: %d\n", error);
+               return error;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
+
+/**
+ * fsl_mc_object_allocate - Allocates a MC object device of the given
+ * pool type from a given MC bus
+ *
+ * @mc_dev: MC device for which the MC object device is to be allocated
+ * @pool_type: MC bus resource pool type
+ * @new_mc_dev: Pointer to area where the pointer to the allocated
+ * MC object device is to be returned
+ *
+ * This function allocates a MC object device from the device's parent DPRC,
+ * from the corresponding MC bus' pool of allocatable MC object devices of
+ * the given resource type. mc_dev cannot be a DPRC itself.
+ *
+ * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC
+ * portals are allocated using fsl_mc_portal_allocate(), instead of
+ * this function.
+ */
+int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
+                                       enum fsl_mc_pool_type pool_type,
+                                       struct fsl_mc_device **new_mc_adev)
+{
+       struct fsl_mc_device *mc_bus_dev;
+       struct fsl_mc_bus *mc_bus;
+       struct fsl_mc_device *mc_adev;
+       int error = -EINVAL;
+       struct fsl_mc_resource *resource = NULL;
+
+       *new_mc_adev = NULL;
+       if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC))
+               goto error;
+
+       if (WARN_ON(mc_dev->dev.parent->bus != &fsl_mc_bus_type))
+               goto error;
+
+       if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP))
+               goto error;
+
+       mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
+       mc_bus = to_fsl_mc_bus(mc_bus_dev);
+       error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource);
+       if (error < 0)
+               goto error;
+
+       mc_adev = resource->data;
+       if (WARN_ON(!mc_adev))
+               goto error;
+
+       *new_mc_adev = mc_adev;
+       return 0;
+error:
+       if (resource)
+               fsl_mc_resource_free(resource);
+
+       return error;
+}
+EXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
+
+/**
+ * fsl_mc_object_free - Returns an allocatable MC object device to the
+ * corresponding resource pool of a given MC bus.
+ *
+ * @mc_adev: Pointer to the MC object device
+ */
+void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
+{
+       struct fsl_mc_resource *resource;
+
+       resource = mc_adev->resource;
+       if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP))
+               return;
+       if (WARN_ON(resource->data != mc_adev))
+               return;
+
+       fsl_mc_resource_free(resource);
+}
+EXPORT_SYMBOL_GPL(fsl_mc_object_free);
+
+/**
+ * fsl_mc_allocator_probe - callback invoked when an allocatable device is
+ * being added to the system
+ */
+static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
+{
+       enum fsl_mc_pool_type pool_type;
+       struct fsl_mc_device *mc_bus_dev;
+       struct fsl_mc_bus *mc_bus;
+       int error = -EINVAL;
+
+       if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
+               goto error;
+
+       mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
+       if (WARN_ON(mc_bus_dev->dev.bus != &fsl_mc_bus_type))
+               goto error;
+
+       mc_bus = to_fsl_mc_bus(mc_bus_dev);
+       error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
+       if (error < 0)
+               goto error;
+
+       error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
+       if (error < 0)
+               goto error;
+
+       dev_info(&mc_dev->dev,
+                "Allocatable MC object device bound to fsl_mc_allocator driver");
+       return 0;
+error:
+
+       return error;
+}
+
+/**
+ * fsl_mc_allocator_remove - callback invoked when an allocatable device is
+ * being removed from the system
+ */
+static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
+{
+       int error = -EINVAL;
+
+       if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
+               goto out;
+
+       error = fsl_mc_resource_pool_remove_device(mc_dev);
+       if (error < 0)
+               goto out;
+
+       dev_info(&mc_dev->dev,
+                "Allocatable MC object device unbound from fsl_mc_allocator driver");
+       error = 0;
+out:
+       return error;
+}
+
+static const struct fsl_mc_device_match_id match_id_table[] = {
+       {
+        .vendor = FSL_MC_VENDOR_FREESCALE,
+        .obj_type = "dpbp",
+        .ver_major = DPBP_VER_MAJOR,
+        .ver_minor = DPBP_VER_MINOR
+       },
+       {
+        .vendor = FSL_MC_VENDOR_FREESCALE,
+        .obj_type = "dpmcp",
+        .ver_major = DPMCP_VER_MAJOR,
+        .ver_minor = DPMCP_VER_MINOR
+       },
+       {
+        .vendor = FSL_MC_VENDOR_FREESCALE,
+        .obj_type = "dpcon",
+        .ver_major = DPCON_VER_MAJOR,
+        .ver_minor = DPCON_VER_MINOR
+       },
+       {.vendor = 0x0},
+};
+
+static struct fsl_mc_driver fsl_mc_allocator_driver = {
+       .driver = {
+                  .name = "fsl_mc_allocator",
+                  .owner = THIS_MODULE,
+                  .pm = NULL,
+                  },
+       .match_id_table = match_id_table,
+       .probe = fsl_mc_allocator_probe,
+       .remove = fsl_mc_allocator_remove,
+};
+
+int __init fsl_mc_allocator_driver_init(void)
+{
+       return fsl_mc_driver_register(&fsl_mc_allocator_driver);
+}
+
+void __exit fsl_mc_allocator_driver_exit(void)
+{
+       fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
+}
diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
new file mode 100644 (file)
index 0000000..23512d0
--- /dev/null
@@ -0,0 +1,793 @@
+/*
+ * Freescale Management Complex (MC) bus driver
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Author: German Rivera <German.Rivera@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include "../include/mc-private.h"
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/limits.h>
+#include "../include/dpmng.h"
+#include "../include/mc-sys.h"
+#include "dprc-cmd.h"
+
+static struct kmem_cache *mc_dev_cache;
+
+/**
+ * fsl_mc_bus_match - device to driver matching callback
+ * @dev: the MC object device structure to match against
+ * @drv: the device driver to search for matching MC object device id
+ * structures
+ *
+ * Returns 1 on success, 0 otherwise.
+ */
+static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
+{
+       const struct fsl_mc_device_match_id *id;
+       struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+       struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
+       bool found = false;
+       bool major_version_mismatch = false;
+       bool minor_version_mismatch = false;
+
+       if (WARN_ON(!fsl_mc_bus_type.dev_root))
+               goto out;
+
+       if (!mc_drv->match_id_table)
+               goto out;
+
+       /*
+        * If the object is not 'plugged' don't match.
+        * Only exception is the root DPRC, which is a special case.
+        */
+       if ((mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED) == 0 &&
+           &mc_dev->dev != fsl_mc_bus_type.dev_root)
+               goto out;
+
+       /*
+        * Traverse the match_id table of the given driver, trying to find
+        * a matching for the given MC object device.
+        */
+       for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) {
+               if (id->vendor == mc_dev->obj_desc.vendor &&
+                   strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) {
+                       if (id->ver_major == mc_dev->obj_desc.ver_major) {
+                               found = true;
+                               if (id->ver_minor != mc_dev->obj_desc.ver_minor)
+                                       minor_version_mismatch = true;
+                       } else {
+                               major_version_mismatch = true;
+                       }
+
+                       break;
+               }
+       }
+
+       if (major_version_mismatch) {
+               dev_warn(dev,
+                        "Major version mismatch: driver version %u.%u, MC object version %u.%u\n",
+                        id->ver_major, id->ver_minor,
+                        mc_dev->obj_desc.ver_major,
+                        mc_dev->obj_desc.ver_minor);
+       } else if (minor_version_mismatch) {
+               dev_warn(dev,
+                        "Minor version mismatch: driver version %u.%u, MC object version %u.%u\n",
+                        id->ver_major, id->ver_minor,
+                        mc_dev->obj_desc.ver_major,
+                        mc_dev->obj_desc.ver_minor);
+       }
+
+out:
+       dev_dbg(dev, "%smatched\n", found ? "" : "not ");
+       return found;
+}
+
+/**
+ * fsl_mc_bus_uevent - callback invoked when a device is added
+ */
+static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       pr_debug("%s invoked\n", __func__);
+       return 0;
+}
+
+struct bus_type fsl_mc_bus_type = {
+       .name = "fsl-mc",
+       .match = fsl_mc_bus_match,
+       .uevent = fsl_mc_bus_uevent,
+};
+EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
+
+static int fsl_mc_driver_probe(struct device *dev)
+{
+       struct fsl_mc_driver *mc_drv;
+       struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+       int error;
+
+       if (WARN_ON(!dev->driver))
+               return -EINVAL;
+
+       mc_drv = to_fsl_mc_driver(dev->driver);
+       if (WARN_ON(!mc_drv->probe))
+               return -EINVAL;
+
+       error = mc_drv->probe(mc_dev);
+       if (error < 0) {
+               dev_err(dev, "MC object device probe callback failed: %d\n",
+                       error);
+               return error;
+       }
+
+       return 0;
+}
+
+static int fsl_mc_driver_remove(struct device *dev)
+{
+       struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
+       struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+       int error;
+
+       if (WARN_ON(!dev->driver))
+               return -EINVAL;
+
+       error = mc_drv->remove(mc_dev);
+       if (error < 0) {
+               dev_err(dev,
+                       "MC object device remove callback failed: %d\n",
+                       error);
+               return error;
+       }
+
+       return 0;
+}
+
+static void fsl_mc_driver_shutdown(struct device *dev)
+{
+       struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
+       struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+
+       mc_drv->shutdown(mc_dev);
+}
+
+/**
+ * __fsl_mc_driver_register - registers a child device driver with the
+ * MC bus
+ *
+ * This function is implicitly invoked from the registration function of
+ * fsl_mc device drivers, which is generated by the
+ * module_fsl_mc_driver() macro.
+ */
+int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver,
+                            struct module *owner)
+{
+       int error;
+
+       mc_driver->driver.owner = owner;
+       mc_driver->driver.bus = &fsl_mc_bus_type;
+
+       if (mc_driver->probe)
+               mc_driver->driver.probe = fsl_mc_driver_probe;
+
+       if (mc_driver->remove)
+               mc_driver->driver.remove = fsl_mc_driver_remove;
+
+       if (mc_driver->shutdown)
+               mc_driver->driver.shutdown = fsl_mc_driver_shutdown;
+
+       error = driver_register(&mc_driver->driver);
+       if (error < 0) {
+               pr_err("driver_register() failed for %s: %d\n",
+                      mc_driver->driver.name, error);
+               return error;
+       }
+
+       pr_info("MC object device driver %s registered\n",
+               mc_driver->driver.name);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(__fsl_mc_driver_register);
+
+/**
+ * fsl_mc_driver_unregister - unregisters a device driver from the
+ * MC bus
+ */
+void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver)
+{
+       driver_unregister(&mc_driver->driver);
+}
+EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister);
+
+static int get_dprc_icid(struct fsl_mc_io *mc_io,
+                        int container_id, uint16_t *icid)
+{
+       uint16_t dprc_handle;
+       struct dprc_attributes attr;
+       int error;
+
+       error = dprc_open(mc_io, container_id, &dprc_handle);
+       if (error < 0) {
+               pr_err("dprc_open() failed: %d\n", error);
+               return error;
+       }
+
+       memset(&attr, 0, sizeof(attr));
+       error = dprc_get_attributes(mc_io, dprc_handle, &attr);
+       if (error < 0) {
+               pr_err("dprc_get_attributes() failed: %d\n", error);
+               goto common_cleanup;
+       }
+
+       *icid = attr.icid;
+       error = 0;
+
+common_cleanup:
+       (void)dprc_close(mc_io, dprc_handle);
+       return error;
+}
+
+static int translate_mc_addr(uint64_t mc_addr, phys_addr_t *phys_addr)
+{
+       int i;
+       struct fsl_mc *mc = dev_get_drvdata(fsl_mc_bus_type.dev_root->parent);
+
+       if (mc->num_translation_ranges == 0) {
+               /*
+                * Do identity mapping:
+                */
+               *phys_addr = mc_addr;
+               return 0;
+       }
+
+       for (i = 0; i < mc->num_translation_ranges; i++) {
+               struct fsl_mc_addr_translation_range *range =
+                       &mc->translation_ranges[i];
+
+               if (mc_addr >= range->start_mc_addr &&
+                   mc_addr < range->end_mc_addr) {
+                       *phys_addr = range->start_phys_addr +
+                                    (mc_addr - range->start_mc_addr);
+                       return 0;
+               }
+       }
+
+       return -EFAULT;
+}
+
+static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
+                                         struct fsl_mc_device *mc_bus_dev)
+{
+       int i;
+       int error;
+       struct resource *regions;
+       struct dprc_obj_desc *obj_desc = &mc_dev->obj_desc;
+       struct device *parent_dev = mc_dev->dev.parent;
+
+       regions = kmalloc_array(obj_desc->region_count,
+                               sizeof(regions[0]), GFP_KERNEL);
+       if (!regions)
+               return -ENOMEM;
+
+       for (i = 0; i < obj_desc->region_count; i++) {
+               struct dprc_region_desc region_desc;
+
+               error = dprc_get_obj_region(mc_bus_dev->mc_io,
+                                           mc_bus_dev->mc_handle,
+                                           obj_desc->type,
+                                           obj_desc->id, i, &region_desc);
+               if (error < 0) {
+                       dev_err(parent_dev,
+                               "dprc_get_obj_region() failed: %d\n", error);
+                       goto error_cleanup_regions;
+               }
+
+               WARN_ON(region_desc.base_paddr == 0x0);
+               WARN_ON(region_desc.size == 0);
+               error = translate_mc_addr(region_desc.base_paddr,
+                                         &regions[i].start);
+               if (error < 0) {
+                       dev_err(parent_dev,
+                               "Invalid MC address: %#llx\n",
+                               region_desc.base_paddr);
+                       goto error_cleanup_regions;
+               }
+
+               regions[i].end = regions[i].start + region_desc.size - 1;
+               regions[i].name = "fsl-mc object MMIO region";
+               regions[i].flags = IORESOURCE_IO;
+       }
+
+       mc_dev->regions = regions;
+       return 0;
+
+error_cleanup_regions:
+       kfree(regions);
+       return error;
+}
+
+/**
+ * Add a newly discovered MC object device to be visible in Linux
+ */
+int fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
+                     struct fsl_mc_io *mc_io,
+                     struct device *parent_dev,
+                     struct fsl_mc_device **new_mc_dev)
+{
+       int error;
+       struct fsl_mc_device *mc_dev = NULL;
+       struct fsl_mc_bus *mc_bus = NULL;
+       struct fsl_mc_device *parent_mc_dev;
+
+       if (parent_dev->bus == &fsl_mc_bus_type)
+               parent_mc_dev = to_fsl_mc_device(parent_dev);
+       else
+               parent_mc_dev = NULL;
+
+       if (strcmp(obj_desc->type, "dprc") == 0) {
+               /*
+                * Allocate an MC bus device object:
+                */
+               mc_bus = devm_kzalloc(parent_dev, sizeof(*mc_bus), GFP_KERNEL);
+               if (!mc_bus)
+                       return -ENOMEM;
+
+               mc_dev = &mc_bus->mc_dev;
+       } else {
+               /*
+                * Allocate a regular fsl_mc_device object:
+                */
+               mc_dev = kmem_cache_zalloc(mc_dev_cache, GFP_KERNEL);
+               if (!mc_dev)
+                       return -ENOMEM;
+       }
+
+       mc_dev->obj_desc = *obj_desc;
+       mc_dev->mc_io = mc_io;
+       device_initialize(&mc_dev->dev);
+       mc_dev->dev.parent = parent_dev;
+       mc_dev->dev.bus = &fsl_mc_bus_type;
+       dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id);
+
+       if (strcmp(obj_desc->type, "dprc") == 0) {
+               struct fsl_mc_io *mc_io2;
+
+               mc_dev->flags |= FSL_MC_IS_DPRC;
+
+               /*
+                * To get the DPRC's ICID, we need to open the DPRC
+                * in get_dprc_icid(). For child DPRCs, we do so using the
+                * parent DPRC's MC portal instead of the child DPRC's MC
+                * portal, in case the child DPRC is already opened with
+                * its own portal (e.g., the DPRC used by AIOP).
+                *
+                * NOTE: There cannot be more than one active open for a
+                * given MC object, using the same MC portal.
+                */
+               if (parent_mc_dev) {
+                       /*
+                        * device being added is a child DPRC device
+                        */
+                       mc_io2 = parent_mc_dev->mc_io;
+               } else {
+                       /*
+                        * device being added is the root DPRC device
+                        */
+                       if (WARN_ON(!mc_io)) {
+                               error = -EINVAL;
+                               goto error_cleanup_dev;
+                       }
+
+                       mc_io2 = mc_io;
+
+                       if (!fsl_mc_bus_type.dev_root)
+                               fsl_mc_bus_type.dev_root = &mc_dev->dev;
+               }
+
+               error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid);
+               if (error < 0)
+                       goto error_cleanup_dev;
+       } else {
+               /*
+                * A non-DPRC MC object device has to be a child of another
+                * MC object (specifically a DPRC object)
+                */
+               mc_dev->icid = parent_mc_dev->icid;
+               mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK;
+               mc_dev->dev.dma_mask = &mc_dev->dma_mask;
+       }
+
+       /*
+        * Get MMIO regions for the device from the MC:
+        *
+        * NOTE: the root DPRC is a special case as its MMIO region is
+        * obtained from the device tree
+        */
+       if (parent_mc_dev && obj_desc->region_count != 0) {
+               error = fsl_mc_device_get_mmio_regions(mc_dev,
+                                                      parent_mc_dev);
+               if (error < 0)
+                       goto error_cleanup_dev;
+       }
+
+       /*
+        * The device-specific probe callback will get invoked by device_add()
+        */
+       error = device_add(&mc_dev->dev);
+       if (error < 0) {
+               dev_err(parent_dev,
+                       "device_add() failed for device %s: %d\n",
+                       dev_name(&mc_dev->dev), error);
+               goto error_cleanup_dev;
+       }
+
+       (void)get_device(&mc_dev->dev);
+       dev_dbg(parent_dev, "Added MC object device %s\n",
+               dev_name(&mc_dev->dev));
+
+       *new_mc_dev = mc_dev;
+       return 0;
+
+error_cleanup_dev:
+       kfree(mc_dev->regions);
+       if (mc_bus)
+               devm_kfree(parent_dev, mc_bus);
+       else
+               kmem_cache_free(mc_dev_cache, mc_dev);
+
+       return error;
+}
+EXPORT_SYMBOL_GPL(fsl_mc_device_add);
+
+/**
+ * fsl_mc_device_remove - Remove a MC object device from being visible to
+ * Linux
+ *
+ * @mc_dev: Pointer to a MC object device object
+ */
+void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
+{
+       struct fsl_mc_bus *mc_bus = NULL;
+
+       kfree(mc_dev->regions);
+
+       /*
+        * The device-specific remove callback will get invoked by device_del()
+        */
+       device_del(&mc_dev->dev);
+       put_device(&mc_dev->dev);
+
+       if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) {
+               mc_bus = to_fsl_mc_bus(mc_dev);
+               if (mc_dev->mc_io) {
+                       fsl_destroy_mc_io(mc_dev->mc_io);
+                       mc_dev->mc_io = NULL;
+               }
+
+               if (&mc_dev->dev == fsl_mc_bus_type.dev_root)
+                       fsl_mc_bus_type.dev_root = NULL;
+       }
+
+       if (mc_bus)
+               devm_kfree(mc_dev->dev.parent, mc_bus);
+       else
+               kmem_cache_free(mc_dev_cache, mc_dev);
+}
+EXPORT_SYMBOL_GPL(fsl_mc_device_remove);
+
+static int parse_mc_ranges(struct device *dev,
+                          int *paddr_cells,
+                          int *mc_addr_cells,
+                          int *mc_size_cells,
+                          const __be32 **ranges_start,
+                          uint8_t *num_ranges)
+{
+       const __be32 *prop;
+       int range_tuple_cell_count;
+       int ranges_len;
+       int tuple_len;
+       struct device_node *mc_node = dev->of_node;
+
+       *ranges_start = of_get_property(mc_node, "ranges", &ranges_len);
+       if (!(*ranges_start) || !ranges_len) {
+               dev_warn(dev,
+                        "missing or empty ranges property for device tree node '%s'\n",
+                        mc_node->name);
+
+               *num_ranges = 0;
+               return 0;
+       }
+
+       *paddr_cells = of_n_addr_cells(mc_node);
+
+       prop = of_get_property(mc_node, "#address-cells", NULL);
+       if (prop)
+               *mc_addr_cells = be32_to_cpup(prop);
+       else
+               *mc_addr_cells = *paddr_cells;
+
+       prop = of_get_property(mc_node, "#size-cells", NULL);
+       if (prop)
+               *mc_size_cells = be32_to_cpup(prop);
+       else
+               *mc_size_cells = of_n_size_cells(mc_node);
+
+       range_tuple_cell_count = *paddr_cells + *mc_addr_cells +
+                                *mc_size_cells;
+
+       tuple_len = range_tuple_cell_count * sizeof(__be32);
+       if (ranges_len % tuple_len != 0) {
+               dev_err(dev, "malformed ranges property '%s'\n", mc_node->name);
+               return -EINVAL;
+       }
+
+       *num_ranges = ranges_len / tuple_len;
+       return 0;
+}
+
+static int get_mc_addr_translation_ranges(struct device *dev,
+                                         struct fsl_mc_addr_translation_range
+                                               **ranges,
+                                         uint8_t *num_ranges)
+{
+       int error;
+       int paddr_cells;
+       int mc_addr_cells;
+       int mc_size_cells;
+       int i;
+       const __be32 *ranges_start;
+       const __be32 *cell;
+
+       error = parse_mc_ranges(dev,
+                               &paddr_cells,
+                               &mc_addr_cells,
+                               &mc_size_cells,
+                               &ranges_start,
+                               num_ranges);
+       if (error < 0)
+               return error;
+
+       if (!(*num_ranges)) {
+               /*
+                * Missing or empty ranges property ("ranges;") for the
+                * 'fsl,qoriq-mc' node. In this case, identity mapping
+                * will be used.
+                */
+               *ranges = NULL;
+               return 0;
+       }
+
+       *ranges = devm_kcalloc(dev, *num_ranges,
+                              sizeof(struct fsl_mc_addr_translation_range),
+                              GFP_KERNEL);
+       if (!(*ranges))
+               return -ENOMEM;
+
+       cell = ranges_start;
+       for (i = 0; i < *num_ranges; ++i) {
+               struct fsl_mc_addr_translation_range *range = &(*ranges)[i];
+
+               range->start_mc_addr = of_read_number(cell, mc_addr_cells);
+               cell += mc_addr_cells;
+               range->start_phys_addr = of_read_number(cell, paddr_cells);
+               cell += paddr_cells;
+               range->end_mc_addr = range->start_mc_addr +
+                                    of_read_number(cell, mc_size_cells);
+
+               cell += mc_size_cells;
+       }
+
+       return 0;
+}
+
+/**
+ * fsl_mc_bus_probe - callback invoked when the root MC bus is being
+ * added
+ */
+static int fsl_mc_bus_probe(struct platform_device *pdev)
+{
+       struct dprc_obj_desc obj_desc;
+       int error;
+       struct fsl_mc *mc;
+       struct fsl_mc_device *mc_bus_dev = NULL;
+       struct fsl_mc_io *mc_io = NULL;
+       int container_id;
+       phys_addr_t mc_portal_phys_addr;
+       uint32_t mc_portal_size;
+       struct mc_version mc_version;
+       struct resource res;
+
+       dev_info(&pdev->dev, "Root MC bus device probed");
+
+       mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
+       if (!mc)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, mc);
+
+       /*
+        * Get physical address of MC portal for the root DPRC:
+        */
+       error = of_address_to_resource(pdev->dev.of_node, 0, &res);
+       if (error < 0) {
+               dev_err(&pdev->dev,
+                       "of_address_to_resource() failed for %s\n",
+                       pdev->dev.of_node->full_name);
+               return error;
+       }
+
+       mc_portal_phys_addr = res.start;
+       mc_portal_size = resource_size(&res);
+       error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
+                                mc_portal_size, NULL, 0, &mc_io);
+       if (error < 0)
+               return error;
+
+       error = mc_get_version(mc_io, &mc_version);
+       if (error != 0) {
+               dev_err(&pdev->dev,
+                       "mc_get_version() failed with error %d\n", error);
+               goto error_cleanup_mc_io;
+       }
+
+       dev_info(&pdev->dev,
+                "Freescale Management Complex Firmware version: %u.%u.%u\n",
+                mc_version.major, mc_version.minor, mc_version.revision);
+
+       if (mc_version.major < MC_VER_MAJOR) {
+               dev_err(&pdev->dev,
+                       "ERROR: MC firmware version not supported by driver (driver version: %u.%u)\n",
+                       MC_VER_MAJOR, MC_VER_MINOR);
+               error = -ENOTSUPP;
+               goto error_cleanup_mc_io;
+       }
+
+       if (mc_version.major > MC_VER_MAJOR) {
+               dev_warn(&pdev->dev,
+                        "WARNING: driver may not support newer MC firmware features (driver version: %u.%u)\n",
+                        MC_VER_MAJOR, MC_VER_MINOR);
+       }
+
+       error = get_mc_addr_translation_ranges(&pdev->dev,
+                                              &mc->translation_ranges,
+                                              &mc->num_translation_ranges);
+       if (error < 0)
+               goto error_cleanup_mc_io;
+
+       error = dpmng_get_container_id(mc_io, &container_id);
+       if (error < 0) {
+               dev_err(&pdev->dev,
+                       "dpmng_get_container_id() failed: %d\n", error);
+               goto error_cleanup_mc_io;
+       }
+
+       obj_desc.vendor = FSL_MC_VENDOR_FREESCALE;
+       strcpy(obj_desc.type, "dprc");
+       obj_desc.id = container_id;
+       obj_desc.ver_major = DPRC_VER_MAJOR;
+       obj_desc.ver_minor = DPRC_VER_MINOR;
+       obj_desc.region_count = 0;
+
+       error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev);
+       if (error < 0)
+               goto error_cleanup_mc_io;
+
+       mc->root_mc_bus_dev = mc_bus_dev;
+       return 0;
+
+error_cleanup_mc_io:
+       fsl_destroy_mc_io(mc_io);
+       return error;
+}
+
+/**
+ * fsl_mc_bus_remove - callback invoked when the root MC bus is being
+ * removed
+ */
+static int fsl_mc_bus_remove(struct platform_device *pdev)
+{
+       struct fsl_mc *mc = platform_get_drvdata(pdev);
+
+       if (WARN_ON(&mc->root_mc_bus_dev->dev != fsl_mc_bus_type.dev_root))
+               return -EINVAL;
+
+       fsl_mc_device_remove(mc->root_mc_bus_dev);
+       dev_info(&pdev->dev, "Root MC bus device removed");
+       return 0;
+}
+
+static const struct of_device_id fsl_mc_bus_match_table[] = {
+       {.compatible = "fsl,qoriq-mc",},
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table);
+
+static struct platform_driver fsl_mc_bus_driver = {
+       .driver = {
+                  .name = "fsl_mc_bus",
+                  .owner = THIS_MODULE,
+                  .pm = NULL,
+                  .of_match_table = fsl_mc_bus_match_table,
+                  },
+       .probe = fsl_mc_bus_probe,
+       .remove = fsl_mc_bus_remove,
+};
+
+static int __init fsl_mc_bus_driver_init(void)
+{
+       int error;
+
+       mc_dev_cache = kmem_cache_create("fsl_mc_device",
+                                        sizeof(struct fsl_mc_device), 0, 0,
+                                        NULL);
+       if (!mc_dev_cache) {
+               pr_err("Could not create fsl_mc_device cache\n");
+               return -ENOMEM;
+       }
+
+       error = bus_register(&fsl_mc_bus_type);
+       if (error < 0) {
+               pr_err("fsl-mc bus type registration failed: %d\n", error);
+               goto error_cleanup_cache;
+       }
+
+       pr_info("fsl-mc bus type registered\n");
+
+       error = platform_driver_register(&fsl_mc_bus_driver);
+       if (error < 0) {
+               pr_err("platform_driver_register() failed: %d\n", error);
+               goto error_cleanup_bus;
+       }
+
+       error = dprc_driver_init();
+       if (error < 0)
+               goto error_cleanup_driver;
+
+       error = fsl_mc_allocator_driver_init();
+       if (error < 0)
+               goto error_cleanup_dprc_driver;
+
+       return 0;
+
+error_cleanup_dprc_driver:
+       dprc_driver_exit();
+
+error_cleanup_driver:
+       platform_driver_unregister(&fsl_mc_bus_driver);
+
+error_cleanup_bus:
+       bus_unregister(&fsl_mc_bus_type);
+
+error_cleanup_cache:
+       kmem_cache_destroy(mc_dev_cache);
+       return error;
+}
+
+postcore_initcall(fsl_mc_bus_driver_init);
+
+static void __exit fsl_mc_bus_driver_exit(void)
+{
+       if (WARN_ON(!mc_dev_cache))
+               return;
+
+       fsl_mc_allocator_driver_exit();
+       dprc_driver_exit();
+       platform_driver_unregister(&fsl_mc_bus_driver);
+       bus_unregister(&fsl_mc_bus_type);
+       kmem_cache_destroy(mc_dev_cache);
+       pr_info("MC bus unregistered\n");
+}
+
+module_exit(fsl_mc_bus_driver_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor Inc.");
+MODULE_DESCRIPTION("Freescale Management Complex (MC) bus driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c
new file mode 100644 (file)
index 0000000..5737f59
--- /dev/null
@@ -0,0 +1,287 @@
+/* Copyright 2013-2014 Freescale Semiconductor Inc.
+ *
+ * I/O services to send MC commands to the MC hardware
+ *
+ * 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 the above-listed copyright holders nor the
+ *       names of any contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 "../include/mc-sys.h"
+#include "../include/mc-cmd.h"
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+
+/**
+ * Timeout in jiffies to wait for the completion of an MC command
+ */
+#define MC_CMD_COMPLETION_TIMEOUT_JIFFIES   (HZ / 2)   /* 500 ms */
+
+/*
+ * usleep_range() min and max values used to throttle down polling
+ * iterations while waiting for MC command completion
+ */
+#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS    10
+#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS    500
+
+#define MC_CMD_HDR_READ_CMDID(_hdr) \
+       ((uint16_t)mc_dec((_hdr), MC_CMD_HDR_CMDID_O, MC_CMD_HDR_CMDID_S))
+
+/**
+ * Creates an MC I/O object
+ *
+ * @dev: device to be associated with the MC I/O object
+ * @mc_portal_phys_addr: physical address of the MC portal to use
+ * @mc_portal_size: size in bytes of the MC portal
+ * @resource: Pointer to MC bus object allocator resource associated
+ * with this MC I/O object or NULL if none.
+ * @flags: flags for the new MC I/O object
+ * @new_mc_io: Area to return pointer to newly created MC I/O object
+ *
+ * Returns '0' on Success; Error code otherwise.
+ */
+int __must_check fsl_create_mc_io(struct device *dev,
+                                 phys_addr_t mc_portal_phys_addr,
+                                 uint32_t mc_portal_size,
+                                 struct fsl_mc_resource *resource,
+                                 uint32_t flags, struct fsl_mc_io **new_mc_io)
+{
+       struct fsl_mc_io *mc_io;
+       void __iomem *mc_portal_virt_addr;
+       struct resource *res;
+
+       mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL);
+       if (!mc_io)
+               return -ENOMEM;
+
+       mc_io->dev = dev;
+       mc_io->flags = flags;
+       mc_io->portal_phys_addr = mc_portal_phys_addr;
+       mc_io->portal_size = mc_portal_size;
+       mc_io->resource = resource;
+       res = devm_request_mem_region(dev,
+                                     mc_portal_phys_addr,
+                                     mc_portal_size,
+                                     "mc_portal");
+       if (!res) {
+               dev_err(dev,
+                       "devm_request_mem_region failed for MC portal %#llx\n",
+                       mc_portal_phys_addr);
+               return -EBUSY;
+       }
+
+       mc_portal_virt_addr = devm_ioremap_nocache(dev,
+                                                  mc_portal_phys_addr,
+                                                  mc_portal_size);
+       if (!mc_portal_virt_addr) {
+               dev_err(dev,
+                       "devm_ioremap_nocache failed for MC portal %#llx\n",
+                       mc_portal_phys_addr);
+               return -ENXIO;
+       }
+
+       mc_io->portal_virt_addr = mc_portal_virt_addr;
+       *new_mc_io = mc_io;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(fsl_create_mc_io);
+
+/**
+ * Destroys an MC I/O object
+ *
+ * @mc_io: MC I/O object to destroy
+ */
+void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
+{
+       devm_iounmap(mc_io->dev, mc_io->portal_virt_addr);
+       devm_release_mem_region(mc_io->dev,
+                               mc_io->portal_phys_addr,
+                               mc_io->portal_size);
+
+       mc_io->portal_virt_addr = NULL;
+       devm_kfree(mc_io->dev, mc_io);
+}
+EXPORT_SYMBOL_GPL(fsl_destroy_mc_io);
+
+static int mc_status_to_error(enum mc_cmd_status status)
+{
+       static const int mc_status_to_error_map[] = {
+               [MC_CMD_STATUS_OK] = 0,
+               [MC_CMD_STATUS_AUTH_ERR] = -EACCES,
+               [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM,
+               [MC_CMD_STATUS_DMA_ERR] = -EIO,
+               [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO,
+               [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT,
+               [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL,
+               [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM,
+               [MC_CMD_STATUS_BUSY] = -EBUSY,
+               [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP,
+               [MC_CMD_STATUS_INVALID_STATE] = -ENODEV,
+       };
+
+       if (WARN_ON((u32)status >= ARRAY_SIZE(mc_status_to_error_map)))
+               return -EINVAL;
+
+       return mc_status_to_error_map[status];
+}
+
+static const char *mc_status_to_string(enum mc_cmd_status status)
+{
+       static const char *const status_strings[] = {
+               [MC_CMD_STATUS_OK] = "Command completed successfully",
+               [MC_CMD_STATUS_READY] = "Command ready to be processed",
+               [MC_CMD_STATUS_AUTH_ERR] = "Authentication error",
+               [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege",
+               [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error",
+               [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error",
+               [MC_CMD_STATUS_TIMEOUT] = "Operation timed out",
+               [MC_CMD_STATUS_NO_RESOURCE] = "No resources",
+               [MC_CMD_STATUS_NO_MEMORY] = "No memory available",
+               [MC_CMD_STATUS_BUSY] = "Device is busy",
+               [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation",
+               [MC_CMD_STATUS_INVALID_STATE] = "Invalid state"
+       };
+
+       if ((unsigned int)status >= ARRAY_SIZE(status_strings))
+               return "Unknown MC error";
+
+       return status_strings[status];
+}
+
+/**
+ * mc_write_command - writes a command to a Management Complex (MC) portal
+ *
+ * @portal: pointer to an MC portal
+ * @cmd: pointer to a filled command
+ */
+static inline void mc_write_command(struct mc_command __iomem *portal,
+                                   struct mc_command *cmd)
+{
+       int i;
+
+       /* copy command parameters into the portal */
+       for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
+               writeq(cmd->params[i], &portal->params[i]);
+
+       /* submit the command by writing the header */
+       writeq(cmd->header, &portal->header);
+}
+
+/**
+ * mc_read_response - reads the response for the last MC command from a
+ * Management Complex (MC) portal
+ *
+ * @portal: pointer to an MC portal
+ * @resp: pointer to command response buffer
+ *
+ * Returns MC_CMD_STATUS_OK on Success; Error code otherwise.
+ */
+static inline enum mc_cmd_status mc_read_response(struct mc_command __iomem *
+                                                 portal,
+                                                 struct mc_command *resp)
+{
+       int i;
+       enum mc_cmd_status status;
+
+       /* Copy command response header from MC portal: */
+       resp->header = readq(&portal->header);
+       status = MC_CMD_HDR_READ_STATUS(resp->header);
+       if (status != MC_CMD_STATUS_OK)
+               return status;
+
+       /* Copy command response data from MC portal: */
+       for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
+               resp->params[i] = readq(&portal->params[i]);
+
+       return status;
+}
+
+/**
+ * Sends an command to the MC device using the given MC I/O object
+ *
+ * @mc_io: MC I/O object to be used
+ * @cmd: command to be sent
+ *
+ * Returns '0' on Success; Error code otherwise.
+ *
+ * NOTE: This function cannot be invoked from from atomic contexts.
+ */
+int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd)
+{
+       enum mc_cmd_status status;
+       unsigned long jiffies_until_timeout =
+           jiffies + MC_CMD_COMPLETION_TIMEOUT_JIFFIES;
+
+       /*
+        * Send command to the MC hardware:
+        */
+       mc_write_command(mc_io->portal_virt_addr, cmd);
+
+       /*
+        * Wait for response from the MC hardware:
+        */
+       for (;;) {
+               status = mc_read_response(mc_io->portal_virt_addr, cmd);
+               if (status != MC_CMD_STATUS_READY)
+                       break;
+
+               /*
+                * TODO: When MC command completion interrupts are supported
+                * call wait function here instead of usleep_range()
+                */
+               usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS,
+                            MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
+
+               if (time_after_eq(jiffies, jiffies_until_timeout)) {
+                       pr_debug("MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n",
+                                mc_io->portal_phys_addr,
+                                (unsigned int)
+                                       MC_CMD_HDR_READ_TOKEN(cmd->header),
+                                (unsigned int)
+                                       MC_CMD_HDR_READ_CMDID(cmd->header));
+
+                       return -ETIMEDOUT;
+               }
+       }
+
+       if (status != MC_CMD_STATUS_OK) {
+               pr_debug("MC command failed: portal: %#llx, obj handle: %#x, command: %#x, status: %s (%#x)\n",
+                        mc_io->portal_phys_addr,
+                        (unsigned int)MC_CMD_HDR_READ_TOKEN(cmd->header),
+                        (unsigned int)MC_CMD_HDR_READ_CMDID(cmd->header),
+                        mc_status_to_string(status),
+                        (unsigned int)status);
+
+               return mc_status_to_error(status);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(mc_send_command);
diff --git a/drivers/staging/fsl-mc/include/dpbp-cmd.h b/drivers/staging/fsl-mc/include/dpbp-cmd.h
new file mode 100644 (file)
index 0000000..1fd70a2
--- /dev/null
@@ -0,0 +1,60 @@
+/* Copyright 2013-2014 Freescale Semiconductor Inc.
+*
+* 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 the above-listed copyright holders nor the
+* names of any contributors may be used to endorse or promote products
+* derived from this software without specific prior written permission.
+*
+*
+* ALTERNATIVELY, this software may be distributed under the terms of the
+* GNU General Public License ("GPL") as published by the Free Software
+* Foundation, either version 2 of that License or (at your option) any
+* later version.
+*
+* THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 _FSL_DPBP_CMD_H
+#define _FSL_DPBP_CMD_H
+
+/* DPBP Version */
+#define DPBP_VER_MAJOR                         2
+#define DPBP_VER_MINOR                         0
+
+/* Command IDs */
+#define DPBP_CMDID_CLOSE                               0x800
+#define DPBP_CMDID_OPEN                                        0x804
+#define DPBP_CMDID_CREATE                              0x904
+#define DPBP_CMDID_DESTROY                             0x900
+
+#define DPBP_CMDID_ENABLE                              0x002
+#define DPBP_CMDID_DISABLE                             0x003
+#define DPBP_CMDID_GET_ATTR                            0x004
+#define DPBP_CMDID_RESET                               0x005
+#define DPBP_CMDID_IS_ENABLED                          0x006
+
+#define DPBP_CMDID_SET_IRQ                             0x010
+#define DPBP_CMDID_GET_IRQ                             0x011
+#define DPBP_CMDID_SET_IRQ_ENABLE                      0x012
+#define DPBP_CMDID_GET_IRQ_ENABLE                      0x013
+#define DPBP_CMDID_SET_IRQ_MASK                                0x014
+#define DPBP_CMDID_GET_IRQ_MASK                                0x015
+#define DPBP_CMDID_GET_IRQ_STATUS                      0x016
+#define DPBP_CMDID_CLEAR_IRQ_STATUS                    0x017
+
+#endif /* _FSL_DPBP_CMD_H */
diff --git a/drivers/staging/fsl-mc/include/dpbp.h b/drivers/staging/fsl-mc/include/dpbp.h
new file mode 100644 (file)
index 0000000..5f3c8e7
--- /dev/null
@@ -0,0 +1,330 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * 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 the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 __FSL_DPBP_H
+#define __FSL_DPBP_H
+
+/* Data Path Buffer Pool API
+ * Contains initialization APIs and runtime control APIs for DPBP
+ */
+
+struct fsl_mc_io;
+
+/**
+ * dpbp_open() - Open a control session for the specified object.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @dpbp_id:   DPBP unique ID
+ * @token:     Returned token; use in subsequent API calls
+ *
+ * This function can be used to open a control session for an
+ * already created object; an object may have been declared in
+ * the DPL or by calling the dpbp_create function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent commands for
+ * this specific object
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_open(struct fsl_mc_io *mc_io, int dpbp_id, uint16_t *token);
+
+/**
+ * dpbp_close() - Close the control session of the object
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ *
+ * After this function is called, no further operations are
+ * allowed on the object without opening a new control session.
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_close(struct fsl_mc_io *mc_io, uint16_t token);
+
+/**
+ * struct dpbp_cfg() - Structure representing DPBP configuration
+ * @options:   place holder
+ */
+struct dpbp_cfg {
+       uint32_t options;
+};
+
+/**
+ * dpbp_create() - Create the DPBP object.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @cfg:       Configuration structure
+ * @token:     Returned token; use in subsequent API calls
+ *
+ * Create the DPBP object, allocate required resources and
+ * perform required initialization.
+ *
+ * The object can be created either by declaring it in the
+ * DPL file, or by calling this function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent calls to
+ * this specific object. For objects that are created using the
+ * DPL file, call dpbp_open function to get an authentication
+ * token first.
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_create(struct fsl_mc_io       *mc_io,
+               const struct dpbp_cfg   *cfg,
+               uint16_t                *token);
+
+/**
+ * dpbp_destroy() - Destroy the DPBP object and release all its resources.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ *
+ * Return:     '0' on Success; error code otherwise.
+ */
+int dpbp_destroy(struct fsl_mc_io *mc_io, uint16_t token);
+
+/**
+ * dpbp_enable() - Enable the DPBP.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_enable(struct fsl_mc_io *mc_io, uint16_t token);
+
+/**
+ * dpbp_disable() - Disable the DPBP.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_disable(struct fsl_mc_io *mc_io, uint16_t token);
+
+/**
+ * dpbp_is_enabled() - Check if the DPBP is enabled.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ * @en:                Returns '1' if object is enabled; '0' otherwise
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_is_enabled(struct fsl_mc_io *mc_io, uint16_t token, int *en);
+
+/**
+ * dpbp_reset() - Reset the DPBP, returns the object to initial state.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_reset(struct fsl_mc_io *mc_io, uint16_t token);
+
+/**
+ * dpbp_set_irq() - Set IRQ information for the DPBP to trigger an interrupt.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ * @irq_index: Identifies the interrupt index to configure
+ * @irq_addr:  Address that must be written to
+ *                             signal a message-based interrupt
+ * @irq_val:   Value to write into irq_addr address
+ * @user_irq_id: A user defined number associated with this IRQ
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_set_irq(struct fsl_mc_io      *mc_io,
+                uint16_t               token,
+                uint8_t                irq_index,
+                uint64_t               irq_addr,
+                uint32_t               irq_val,
+                int                    user_irq_id);
+
+/**
+ * dpbp_get_irq() - Get IRQ information from the DPBP.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ * @irq_index: The interrupt index to configure
+ * @type:      Interrupt type: 0 represents message interrupt
+ *                             type (both irq_addr and irq_val are valid)
+ * @irq_addr:  Returned address that must be written to
+ *                             signal the message-based interrupt
+ * @irq_val:   Value to write into irq_addr address
+ * @user_irq_id: A user defined number associated with this IRQ
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_get_irq(struct fsl_mc_io      *mc_io,
+                uint16_t               token,
+                uint8_t                irq_index,
+                int                    *type,
+                uint64_t               *irq_addr,
+                uint32_t               *irq_val,
+                int                    *user_irq_id);
+
+/**
+ * dpbp_set_irq_enable() - Set overall interrupt state.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ * @irq_index: The interrupt index to configure
+ * @en:        Interrupt state - enable = 1, disable = 0
+ *
+ * Allows GPP software to control when interrupts are generated.
+ * Each interrupt can have up to 32 causes.  The enable/disable control's the
+ * overall interrupt state. if the interrupt is disabled no causes will cause
+ * an interrupt.
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_set_irq_enable(struct fsl_mc_io       *mc_io,
+                       uint16_t                token,
+                       uint8_t                 irq_index,
+                       uint8_t                 en);
+
+/**
+ * dpbp_get_irq_enable() - Get overall interrupt state
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ * @irq_index: The interrupt index to configure
+ * @en:                Returned interrupt state - enable = 1, disable = 0
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_get_irq_enable(struct fsl_mc_io       *mc_io,
+                       uint16_t                token,
+                       uint8_t                 irq_index,
+                       uint8_t                 *en);
+
+/**
+ * dpbp_set_irq_mask() - Set interrupt mask.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ * @irq_index: The interrupt index to configure
+ * @mask:      Event mask to trigger interrupt;
+ *                     each bit:
+ *                             0 = ignore event
+ *                             1 = consider event for asserting IRQ
+ *
+ * Every interrupt can have up to 32 causes and the interrupt model supports
+ * masking/unmasking each cause independently
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_set_irq_mask(struct fsl_mc_io *mc_io,
+                     uint16_t          token,
+                     uint8_t           irq_index,
+                     uint32_t          mask);
+
+/**
+ * dpbp_get_irq_mask() - Get interrupt mask.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ * @irq_index: The interrupt index to configure
+ * @mask:      Returned event mask to trigger interrupt
+ *
+ * Every interrupt can have up to 32 causes and the interrupt model supports
+ * masking/unmasking each cause independently
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_get_irq_mask(struct fsl_mc_io *mc_io,
+                     uint16_t          token,
+                     uint8_t           irq_index,
+                     uint32_t          *mask);
+
+/**
+ * dpbp_get_irq_status() - Get the current status of any pending interrupts.
+ *
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ * @irq_index: The interrupt index to configure
+ * @status:    Returned interrupts status - one bit per cause:
+ *                     0 = no interrupt pending
+ *                     1 = interrupt pending
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_get_irq_status(struct fsl_mc_io       *mc_io,
+                       uint16_t                token,
+                       uint8_t                 irq_index,
+                       uint32_t                *status);
+
+/**
+ * dpbp_clear_irq_status() - Clear a pending interrupt's status
+ *
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ * @irq_index: The interrupt index to configure
+ * @status:    Bits to clear (W1C) - one bit per cause:
+ *                                     0 = don't change
+ *                                     1 = clear status bit
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_clear_irq_status(struct fsl_mc_io     *mc_io,
+                         uint16_t              token,
+                         uint8_t               irq_index,
+                         uint32_t              status);
+
+/**
+ * struct dpbp_attr - Structure representing DPBP attributes
+ * @id:                DPBP object ID
+ * @version:   DPBP version
+ * @bpid:      Hardware buffer pool ID; should be used as an argument in
+ *             acquire/release operations on buffers
+ */
+struct dpbp_attr {
+       int id;
+       /**
+        * struct version - Structure representing DPBP version
+        * @major:      DPBP major version
+        * @minor:      DPBP minor version
+        */
+       struct {
+               uint16_t major;
+               uint16_t minor;
+       } version;
+       uint16_t bpid;
+};
+
+/**
+ * dpbp_get_attributes - Retrieve DPBP attributes.
+ *
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPBP object
+ * @attr:      Returned object's attributes
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpbp_get_attributes(struct fsl_mc_io       *mc_io,
+                       uint16_t                token,
+                       struct dpbp_attr        *attr);
+
+/** @} */
+
+#endif /* __FSL_DPBP_H */
diff --git a/drivers/staging/fsl-mc/include/dpcon-cmd.h b/drivers/staging/fsl-mc/include/dpcon-cmd.h
new file mode 100644 (file)
index 0000000..c878d33
--- /dev/null
@@ -0,0 +1,62 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+*
+* 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 the above-listed copyright holders nor the
+* names of any contributors may be used to endorse or promote products
+* derived from this software without specific prior written permission.
+*
+*
+* ALTERNATIVELY, this software may be distributed under the terms of the
+* GNU General Public License ("GPL") as published by the Free Software
+* Foundation, either version 2 of that License or (at your option) any
+* later version.
+*
+* THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 _FSL_DPCON_CMD_H
+#define _FSL_DPCON_CMD_H
+
+/* DPCON Version */
+#define DPCON_VER_MAJOR                                2
+#define DPCON_VER_MINOR                                0
+
+/* Command IDs */
+#define DPCON_CMDID_CLOSE                              0x800
+#define DPCON_CMDID_OPEN                               0x808
+#define DPCON_CMDID_CREATE                             0x908
+#define DPCON_CMDID_DESTROY                            0x900
+
+#define DPCON_CMDID_ENABLE                             0x002
+#define DPCON_CMDID_DISABLE                            0x003
+#define DPCON_CMDID_GET_ATTR                           0x004
+#define DPCON_CMDID_RESET                              0x005
+#define DPCON_CMDID_IS_ENABLED                         0x006
+
+#define DPCON_CMDID_SET_IRQ                            0x010
+#define DPCON_CMDID_GET_IRQ                            0x011
+#define DPCON_CMDID_SET_IRQ_ENABLE                     0x012
+#define DPCON_CMDID_GET_IRQ_ENABLE                     0x013
+#define DPCON_CMDID_SET_IRQ_MASK                       0x014
+#define DPCON_CMDID_GET_IRQ_MASK                       0x015
+#define DPCON_CMDID_GET_IRQ_STATUS                     0x016
+#define DPCON_CMDID_CLEAR_IRQ_STATUS                   0x017
+
+#define DPCON_CMDID_SET_NOTIFICATION                   0x100
+
+#endif /* _FSL_DPCON_CMD_H */
diff --git a/drivers/staging/fsl-mc/include/dpmng.h b/drivers/staging/fsl-mc/include/dpmng.h
new file mode 100644 (file)
index 0000000..1b052b8
--- /dev/null
@@ -0,0 +1,80 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * 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 the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 __FSL_DPMNG_H
+#define __FSL_DPMNG_H
+
+/* Management Complex General API
+ * Contains general API for the Management Complex firmware
+ */
+
+struct fsl_mc_io;
+
+/**
+ * Management Complex firmware version information
+ */
+#define MC_VER_MAJOR 6
+#define MC_VER_MINOR 0
+
+/**
+ * struct mc_versoin
+ * @major: Major version number: incremented on API compatibility changes
+ * @minor: Minor version number: incremented on API additions (that are
+ *             backward compatible); reset when major version is incremented
+ * @revision: Internal revision number: incremented on implementation changes
+ *             and/or bug fixes that have no impact on API
+ */
+struct mc_version {
+       uint32_t major;
+       uint32_t minor;
+       uint32_t revision;
+};
+
+/**
+ * mc_get_version() - Retrieves the Management Complex firmware
+ *                     version information
+ * @mc_io:             Pointer to opaque I/O object
+ * @mc_ver_info:       Returned version information structure
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int mc_get_version(struct fsl_mc_io *mc_io, struct mc_version *mc_ver_info);
+
+/**
+ * dpmng_get_container_id() - Get container ID associated with a given portal.
+ * @mc_io:             Pointer to MC portal's I/O object
+ * @container_id:      Requested container ID
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dpmng_get_container_id(struct fsl_mc_io *mc_io, int *container_id);
+
+#endif /* __FSL_DPMNG_H */
diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/include/dprc.h
new file mode 100644 (file)
index 0000000..f1862a7
--- /dev/null
@@ -0,0 +1,801 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * 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 the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 _FSL_DPRC_H
+#define _FSL_DPRC_H
+
+/* Data Path Resource Container API
+ * Contains DPRC API for managing and querying DPAA resources
+ */
+
+struct fsl_mc_io;
+
+/**
+ * Set this value as the icid value in dprc_cfg structure when creating a
+ * container, in case the ICID is not selected by the user and should be
+ * allocated by the DPRC from the pool of ICIDs.
+ */
+#define DPRC_GET_ICID_FROM_POOL                        (uint16_t)(~(0))
+
+/**
+ * Set this value as the portal_id value in dprc_cfg structure when creating a
+ * container, in case the portal ID is not specifically selected by the
+ * user and should be allocated by the DPRC from the pool of portal ids.
+ */
+#define DPRC_GET_PORTAL_ID_FROM_POOL   (int)(~(0))
+
+/**
+ * dprc_open() - Open DPRC object for use
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @container_id: Container ID to open
+ * @token:     Returned token of DPRC object
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ *
+ * @warning    Required before any operation on the object.
+ */
+int dprc_open(struct fsl_mc_io *mc_io, int container_id, uint16_t *token);
+
+/**
+ * dprc_close() - Close the control session of the object
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ *
+ * After this function is called, no further operations are
+ * allowed on the object without opening a new control session.
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_close(struct fsl_mc_io *mc_io, uint16_t token);
+
+/**
+ * Container general options
+ *
+ * These options may be selected at container creation by the container creator
+ * and can be retrieved using dprc_get_attributes()
+ */
+
+/* Spawn Policy Option allowed - Indicates that the new container is allowed
+ * to spawn and have its own child containers.
+ */
+#define DPRC_CFG_OPT_SPAWN_ALLOWED             0x00000001
+
+/* General Container allocation policy - Indicates that the new container is
+ * allowed to allocate requested resources from its parent container; if not
+ * set, the container is only allowed to use resources in its own pools; Note
+ * that this is a container's global policy, but the parent container may
+ * override it and set specific quota per resource type.
+ */
+#define DPRC_CFG_OPT_ALLOC_ALLOWED             0x00000002
+
+/* Object initialization allowed - software context associated with this
+ * container is allowed to invoke object initialization operations.
+ */
+#define DPRC_CFG_OPT_OBJ_CREATE_ALLOWED        0x00000004
+
+/* Topology change allowed - software context associated with this
+ * container is allowed to invoke topology operations, such as attach/detach
+ * of network objects.
+ */
+#define DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED  0x00000008
+
+/* IOMMU bypass - indicates whether objects of this container are permitted
+ * to bypass the IOMMU.
+ */
+#define DPRC_CFG_OPT_IOMMU_BYPASS              0x00000010
+
+/* AIOP - Indicates that container belongs to AIOP.  */
+#define DPRC_CFG_OPT_AIOP                      0x00000020
+
+/**
+ * struct dprc_cfg - Container configuration options
+ * @icid: Container's ICID; if set to 'DPRC_GET_ICID_FROM_POOL', a free
+ *             ICID value is allocated by the DPRC
+ * @portal_id: Portal ID; if set to 'DPRC_GET_PORTAL_ID_FROM_POOL', a free
+ *             portal ID is allocated by the DPRC
+ * @options: Combination of 'DPRC_CFG_OPT_<X>' options
+ */
+struct dprc_cfg {
+       uint16_t icid;
+       int portal_id;
+       uint64_t options;
+};
+
+/**
+ * dprc_create_container() - Create child container
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @cfg:       Child container configuration
+ * @child_container_id:        Returned child container ID
+ * @child_portal_paddr:        Returned base physical address of the
+ *                                     child portal
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_create_container(struct fsl_mc_io     *mc_io,
+                         uint16_t              token,
+                         struct dprc_cfg       *cfg,
+                         int                   *child_container_id,
+                         uint64_t              *child_portal_paddr);
+
+/**
+ * dprc_destroy_container() - Destroy child container.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @child_container_id:        ID of the container to destroy
+ *
+ * This function terminates the child container, so following this call the
+ * child container ID becomes invalid.
+ *
+ * Notes:
+ * - All resources and objects of the destroyed container are returned to the
+ * parent container or destroyed if were created be the destroyed container.
+ * - This function destroy all the child containers of the specified
+ *   container prior to destroying the container itself.
+ *
+ * warning: Only the parent container is allowed to destroy a child policy
+ *             Container 0 can't be destroyed
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ *
+ */
+int dprc_destroy_container(struct fsl_mc_io    *mc_io,
+                          uint16_t             token,
+                          int                  child_container_id);
+
+/**
+ * dprc_reset_container - Reset child container.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @child_container_id:        ID of the container to reset
+ *
+ * In case a software context crashes or becomes non-responsive, the parent
+ * may wish to reset its resources container before the software context is
+ * restarted.
+ *
+ * This routine informs all objects assigned to the child container that the
+ * container is being reset, so they may perform any cleanup operations that are
+ * needed. All objects handles that were owned by the child container shall be
+ * closed.
+ *
+ * Note that such request may be submitted even if the child software context
+ * has not crashed, but the resulting object cleanup operations will not be
+ * aware of that.
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_reset_container(struct fsl_mc_io *mc_io,
+                        uint16_t token,
+                        int child_container_id);
+
+/* IRQ */
+
+/* Number of dprc's IRQs */
+#define DPRC_NUM_OF_IRQS               1
+
+/* Object irq events */
+
+/* IRQ event - Indicates that a new object assigned to the container */
+#define DPRC_IRQ_EVENT_OBJ_ADDED               0x00000001
+/* IRQ event - Indicates that an object was unassigned from the container */
+#define DPRC_IRQ_EVENT_OBJ_REMOVED             0x00000002
+/* IRQ event - Indicates that resources assigned to the container */
+#define DPRC_IRQ_EVENT_RES_ADDED               0x00000004
+/* IRQ event - Indicates that resources unassigned from the container */
+#define DPRC_IRQ_EVENT_RES_REMOVED             0x00000008
+/* IRQ event - Indicates that one of the descendant containers that opened by
+ * this container is destroyed
+ */
+#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED     0x00000010
+
+/* IRQ event - Indicates that on one of the container's opened object is
+ * destroyed
+ */
+#define DPRC_IRQ_EVENT_OBJ_DESTROYED           0x00000020
+
+/* Irq event - Indicates that object is created at the container */
+#define DPRC_IRQ_EVENT_OBJ_CREATED             0x00000040
+
+/**
+ * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @irq_index: Identifies the interrupt index to configure
+ * @irq_addr:  Address that must be written to
+ *                     signal a message-based interrupt
+ * @irq_val:   Value to write into irq_addr address
+ * @user_irq_id: Returned a user defined number associated with this IRQ
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_set_irq(struct fsl_mc_io      *mc_io,
+                uint16_t               token,
+                uint8_t                irq_index,
+                uint64_t               irq_addr,
+                uint32_t               irq_val,
+                int                    user_irq_id);
+
+/**
+ * dprc_get_irq() - Get IRQ information from the DPRC.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @irq_index: The interrupt index to configure
+ * @type:      Returned interrupt type: 0 represents message interrupt
+ *                     type (both irq_addr and irq_val are valid)
+ * @irq_addr:  Returned address that must be written to
+ *                     signal the message-based interrupt
+ * @irq_val:   Value to write into irq_addr address
+ * @user_irq_id: A user defined number associated with this IRQ
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_irq(struct fsl_mc_io      *mc_io,
+                uint16_t               token,
+                uint8_t                irq_index,
+                int                    *type,
+                uint64_t               *irq_addr,
+                uint32_t               *irq_val,
+                int                    *user_irq_id);
+
+/**
+ * dprc_set_irq_enable() - Set overall interrupt state.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @irq_index: The interrupt index to configure
+ * @en:                Interrupt state - enable = 1, disable = 0
+ *
+ * Allows GPP software to control when interrupts are generated.
+ * Each interrupt can have up to 32 causes.  The enable/disable control's the
+ * overall interrupt state. if the interrupt is disabled no causes will cause
+ * an interrupt.
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_set_irq_enable(struct fsl_mc_io       *mc_io,
+                       uint16_t                token,
+                       uint8_t                 irq_index,
+                       uint8_t                 en);
+
+/**
+ * dprc_get_irq_enable() - Get overall interrupt state.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @irq_index:  The interrupt index to configure
+ * @en:                Returned interrupt state - enable = 1, disable = 0
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_irq_enable(struct fsl_mc_io       *mc_io,
+                       uint16_t                token,
+                       uint8_t                 irq_index,
+                       uint8_t                 *en);
+
+/**
+ * dprc_set_irq_mask() - Set interrupt mask.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @irq_index: The interrupt index to configure
+ * @mask:      event mask to trigger interrupt;
+ *                     each bit:
+ *                             0 = ignore event
+ *                             1 = consider event for asserting irq
+ *
+ * Every interrupt can have up to 32 causes and the interrupt model supports
+ * masking/unmasking each cause independently
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
+                     uint16_t          token,
+                     uint8_t           irq_index,
+                     uint32_t          mask);
+
+/**
+ * dprc_get_irq_mask() - Get interrupt mask.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @irq_index: The interrupt index to configure
+ * @mask:      Returned event mask to trigger interrupt
+ *
+ * Every interrupt can have up to 32 causes and the interrupt model supports
+ * masking/unmasking each cause independently
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_irq_mask(struct fsl_mc_io *mc_io,
+                     uint16_t          token,
+                     uint8_t           irq_index,
+                     uint32_t          *mask);
+
+/**
+ * dprc_get_irq_status() - Get the current status of any pending interrupts.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @irq_index: The interrupt index to configure
+ * @status:    Returned interrupts status - one bit per cause:
+ *                     0 = no interrupt pending
+ *                     1 = interrupt pending
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_irq_status(struct fsl_mc_io       *mc_io,
+                       uint16_t                token,
+                       uint8_t                 irq_index,
+                       uint32_t                *status);
+
+/**
+ * dprc_clear_irq_status() - Clear a pending interrupt's status
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @irq_index: The interrupt index to configure
+ * @status:    bits to clear (W1C) - one bit per cause:
+ *                                     0 = don't change
+ *                                     1 = clear status bit
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_clear_irq_status(struct fsl_mc_io     *mc_io,
+                         uint16_t              token,
+                         uint8_t               irq_index,
+                         uint32_t              status);
+
+/**
+ * struct dprc_attributes - Container attributes
+ * @container_id: Container's ID
+ * @icid: Container's ICID
+ * @portal_id: Container's portal ID
+ * @options: Container's options as set at container's creation
+ * @version: DPRC version
+ */
+struct dprc_attributes {
+       int container_id;
+       uint16_t icid;
+       int portal_id;
+       uint64_t options;
+       /**
+        * struct version - DPRC version
+        * @major: DPRC major version
+        * @minor: DPRC minor version
+        */
+       struct {
+               uint16_t major;
+               uint16_t minor;
+       } version;
+};
+
+/**
+ * dprc_get_attributes() - Obtains container attributes
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @attributes Returned container attributes
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_attributes(struct fsl_mc_io       *mc_io,
+                       uint16_t                token,
+                       struct dprc_attributes  *attributes);
+
+/**
+ * dprc_set_res_quota() - Set allocation policy for a specific resource/object
+ *             type in a child container
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @child_container_id:        ID of the child container
+ * @type:      Resource/object type
+ * @quota:     Sets the maximum number of resources of the selected type
+ *             that the child container is allowed to allocate from its parent;
+ *             when quota is set to -1, the policy is the same as container's
+ *             general policy.
+ *
+ * Allocation policy determines whether or not a container may allocate
+ * resources from its parent. Each container has a 'global' allocation policy
+ * that is set when the container is created.
+ *
+ * This function sets allocation policy for a specific resource type.
+ * The default policy for all resource types matches the container's 'global'
+ * allocation policy.
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ *
+ * @warning    Only the parent container is allowed to change a child policy.
+ */
+int dprc_set_res_quota(struct fsl_mc_io        *mc_io,
+                      uint16_t         token,
+                      int              child_container_id,
+                      char             *type,
+                      uint16_t         quota);
+
+/**
+ * dprc_get_res_quota() - Gets the allocation policy of a specific
+ *             resource/object type in a child container
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @child_container_id;        ID of the child container
+ * @type:      resource/object type
+ * @quota:     Returnes the maximum number of resources of the selected type
+ *             that the child container is allowed to allocate from the parent;
+ *             when quota is set to -1, the policy is the same as container's
+ *             general policy.
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_res_quota(struct fsl_mc_io        *mc_io,
+                      uint16_t         token,
+                      int              child_container_id,
+                      char             *type,
+                      uint16_t         *quota);
+
+/* Resource request options */
+
+/* Explicit resource ID request - The requested objects/resources
+ * are explicit and sequential (in case of resources).
+ * The base ID is given at res_req at base_align field
+ */
+#define DPRC_RES_REQ_OPT_EXPLICIT              0x00000001
+
+/* Aligned resources request - Relevant only for resources
+ * request (and not objects). Indicates that resources base ID should be
+ * sequential and aligned to the value given at dprc_res_req base_align field
+ */
+#define DPRC_RES_REQ_OPT_ALIGNED               0x00000002
+
+/* Plugged Flag - Relevant only for object assignment request.
+ * Indicates that after all objects assigned. An interrupt will be invoked at
+ * the relevant GPP. The assigned object will be marked as plugged.
+ * plugged objects can't be assigned from their container
+ */
+#define DPRC_RES_REQ_OPT_PLUGGED               0x00000004
+
+/**
+ * struct dprc_res_req - Resource request descriptor, to be used in assignment
+ *                     or un-assignment of resources and objects.
+ * @type: Resource/object type: Represent as a NULL terminated string.
+ *     This string may received by using dprc_get_pool() to get resource
+ *     type and dprc_get_obj() to get object type;
+ *     Note: it is not possible to assign/un-assign DPRC objects
+ * @num: Number of resources
+ * @options: Request options: combination of DPRC_RES_REQ_OPT_ options
+ * @id_base_align: In case of explicit assignment (DPRC_RES_REQ_OPT_EXPLICIT
+ *             is set at option), this field represents the required base ID
+ *             for resource allocation; In case of aligned assignment
+ *             (DPRC_RES_REQ_OPT_ALIGNED is set at option), this field
+ *             indicates the required alignment for the resource ID(s) -
+ *             use 0 if there is no alignment or explicit ID requirements
+ */
+struct dprc_res_req {
+       char type[16];
+       uint32_t num;
+       uint32_t options;
+       int id_base_align;
+};
+
+/**
+ * dprc_assign() - Assigns objects or resource to a child container.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @container_id: ID of the child container
+ * @res_req:   Describes the type and amount of resources to
+ *                     assign to the given container
+ *
+ * Assignment is usually done by a parent (this DPRC) to one of its child
+ * containers.
+ *
+ * According to the DPRC allocation policy, the assigned resources may be taken
+ * (allocated) from the container's ancestors, if not enough resources are
+ * available in the container itself.
+ *
+ * The type of assignment depends on the dprc_res_req options, as follows:
+ * - DPRC_RES_REQ_OPT_EXPLICIT: indicates that assigned resources should have
+ *   the explicit base ID specified at the id_base_align field of res_req.
+ * - DPRC_RES_REQ_OPT_ALIGNED: indicates that the assigned resources should be
+ *   aligned to the value given at id_base_align field of res_req.
+ * - DPRC_RES_REQ_OPT_PLUGGED: Relevant only for object assignment,
+ *   and indicates that the object must be set to the plugged state.
+ *
+ * A container may use this function with its own ID in order to change a
+ * object state to plugged or unplugged.
+ *
+ * If IRQ information has been set in the child DPRC, it will signal an
+ * interrupt following every change in its object assignment.
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_assign(struct fsl_mc_io       *mc_io,
+               uint16_t                token,
+               int                     container_id,
+               struct dprc_res_req     *res_req);
+
+/**
+ * dprc_unassign() - Un-assigns objects or resources from a child container
+ *             and moves them into this (parent) DPRC.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @child_container_id:        ID of the child container
+ * @res_req:   Describes the type and amount of resources to un-assign from
+ *             the child container
+ *
+ * Un-assignment of objects can succeed only if the object is not in the
+ * plugged or opened state.
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_unassign(struct fsl_mc_io     *mc_io,
+                 uint16_t              token,
+                 int                   child_container_id,
+                 struct dprc_res_req   *res_req);
+
+/**
+ * dprc_get_pool_count() - Get the number of dprc's pools
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @pool_count:        Returned number of resource pools in the dprc
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_pool_count(struct fsl_mc_io       *mc_io,
+                       uint16_t                token,
+                       int                     *pool_count);
+
+/**
+ * dprc_get_pool() - Get the type (string) of a certain dprc's pool
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @pool_index;        Index of the pool to be queried (< pool_count)
+ * @type:      The type of the pool
+ *
+ * The pool types retrieved one by one by incrementing
+ * pool_index up to (not including) the value of pool_count returned
+ * from dprc_get_pool_count(). dprc_get_pool_count() must
+ * be called prior to dprc_get_pool().
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_pool(struct fsl_mc_io     *mc_io,
+                 uint16_t              token,
+                 int                   pool_index,
+                 char                  *type);
+
+/**
+ * dprc_get_obj_count() - Obtains the number of objects in the DPRC
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @obj_count: Number of objects assigned to the DPRC
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_obj_count(struct fsl_mc_io *mc_io, uint16_t token, int *obj_count);
+
+/* Objects Attributes Flags */
+
+/* Opened state - Indicates that an object is open by at least one owner */
+#define DPRC_OBJ_STATE_OPEN            0x00000001
+/* Plugged state - Indicates that the object is plugged */
+#define DPRC_OBJ_STATE_PLUGGED         0x00000002
+
+/**
+ * struct dprc_obj_desc - Object descriptor, returned from dprc_get_obj()
+ * @type: Type of object: NULL terminated string
+ * @id: ID of logical object resource
+ * @vendor: Object vendor identifier
+ * @ver_major: Major version number
+ * @ver_minor:  Minor version number
+ * @irq_count: Number of interrupts supported by the object
+ * @region_count: Number of mappable regions supported by the object
+ * @state: Object state: combination of DPRC_OBJ_STATE_ states
+ */
+struct dprc_obj_desc {
+       char type[16];
+       int id;
+       uint16_t vendor;
+       uint16_t ver_major;
+       uint16_t ver_minor;
+       uint8_t irq_count;
+       uint8_t region_count;
+       uint32_t state;
+};
+
+/**
+ * dprc_get_obj() - Get general information on an object
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @obj_index: Index of the object to be queried (< obj_count)
+ * @obj_desc:  Returns the requested object descriptor
+ *
+ * The object descriptors are retrieved one by one by incrementing
+ * obj_index up to (not including) the value of obj_count returned
+ * from dprc_get_obj_count(). dprc_get_obj_count() must
+ * be called prior to dprc_get_obj().
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_obj(struct fsl_mc_io      *mc_io,
+                uint16_t               token,
+                int                    obj_index,
+                struct dprc_obj_desc   *obj_desc);
+
+/**
+ * dprc_get_res_count() - Obtains the number of free resources that are assigned
+ *             to this container, by pool type
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @type:      pool type
+ * @res_count: Returned number of free resources of the given
+ *                     resource type that are assigned to this DPRC
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_res_count(struct fsl_mc_io        *mc_io,
+                      uint16_t         token,
+                      char             *type,
+                      int              *res_count);
+
+/**
+ * enum dprc_iter_status - Iteration status
+ * @DPRC_ITER_STATUS_FIRST: Perform first iteration
+ * @DPRC_ITER_STATUS_MORE: Indicates more/next iteration is needed
+ * @DPRC_ITER_STATUS_LAST: Indicates last iteration
+ */
+enum dprc_iter_status {
+       DPRC_ITER_STATUS_FIRST = 0,
+       DPRC_ITER_STATUS_MORE = 1,
+       DPRC_ITER_STATUS_LAST = 2
+};
+
+/**
+ * struct dprc_res_ids_range_desc - Resource ID range descriptor
+ * @base_id: Base resource ID of this range
+ * @last_id: Last resource ID of this range
+ * @iter_status: Iteration status - should be set to DPRC_ITER_STATUS_FIRST at
+ *     first iteration; while the returned marker is DPRC_ITER_STATUS_MORE,
+ *     additional iterations are needed, until the returned marker is
+ *     DPRC_ITER_STATUS_LAST
+ */
+struct dprc_res_ids_range_desc {
+       int base_id;
+       int last_id;
+       enum dprc_iter_status iter_status;
+};
+
+/**
+ * dprc_get_res_ids() - Obtains IDs of free resources in the container
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @type:      pool type
+ * @range_desc:        range descriptor
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_res_ids(struct fsl_mc_io                  *mc_io,
+                    uint16_t                           token,
+                    char                               *type,
+                    struct dprc_res_ids_range_desc     *range_desc);
+
+/**
+ * dprc_get_portal_paddr() - Get the physical address of MC portals
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @portal_id: MC portal ID
+ * @portal_addr: The physical address of the MC portal ID
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_portal_paddr(struct fsl_mc_io     *mc_io,
+                         uint16_t              token,
+                         int                   portal_id,
+                         uint64_t              *portal_addr);
+
+/**
+ * struct dprc_region_desc - Mappable region descriptor
+ * @base_paddr: Region base physical address
+ * @size: Region size (in bytes)
+ */
+struct dprc_region_desc {
+       uint64_t base_paddr;
+       uint32_t size;
+};
+
+/**
+ * dprc_get_obj_region() - Get region information for a specified object.
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @obj_type;  Object type as returned in dprc_get_obj()
+ * @obj_id:    Unique object instance as returned in dprc_get_obj()
+ * @region_index: The specific region to query
+ * @region_desc:  Returns the requested region descriptor
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_get_obj_region(struct fsl_mc_io       *mc_io,
+                       uint16_t                token,
+                       char                    *obj_type,
+                       int                     obj_id,
+                       uint8_t                 region_index,
+                       struct dprc_region_desc *region_desc);
+
+/**
+ * struct dprc_endpoint - Endpoint description for link connect/disconnect
+ *                     operations
+ * @type: Endpoint object type: NULL terminated string
+ * @id: Endpoint object ID
+ * @interface_id: Interface ID; should be set for endpoints with multiple
+ *             interfaces ("dpsw", "dpdmux"); for others, always set to 0
+ */
+struct dprc_endpoint {
+       char type[16];
+       int id;
+       int interface_id;
+};
+
+/**
+ * dprc_connect() - Connect two endpoints to create a network link between them
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @endpoint1: Endpoint 1 configuration parameters
+ * @endpoint2: Endpoint 2 configuration parameters
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_connect(struct fsl_mc_io              *mc_io,
+                uint16_t                       token,
+                const struct dprc_endpoint     *endpoint1,
+                const struct dprc_endpoint     *endpoint2);
+
+/**
+ * dprc_disconnect() - Disconnect one endpoint to remove its network connection
+ * @mc_io:     Pointer to MC portal's I/O object
+ * @token:     Token of DPRC object
+ * @endpoint:  Endpoint configuration parameters
+ *
+ * Return:     '0' on Success; Error code otherwise.
+ */
+int dprc_disconnect(struct fsl_mc_io           *mc_io,
+                   uint16_t                    token,
+                   const struct dprc_endpoint  *endpoint);
+
+/**
+* dprc_get_connection() - Get connected endpoint and link status if connection
+*                      exists.
+* @mc_io               Pointer to MC portal's I/O object
+* @token               Token of DPRC object
+* @endpoint1   Endpoint 1 configuration parameters
+* @endpoint2   Returned endpoint 2 configuration parameters
+* @state:      Returned link state: 1 - link is up, 0 - link is down
+*
+* Return:     '0' on Success; -ENAVAIL if connection does not exist.
+*/
+int dprc_get_connection(struct fsl_mc_io               *mc_io,
+                       uint16_t                        token,
+                       const struct dprc_endpoint      *endpoint1,
+                       struct dprc_endpoint            *endpoint2,
+                       int                             *state);
+
+#endif /* _FSL_DPRC_H */
+
diff --git a/drivers/staging/fsl-mc/include/mc-cmd.h b/drivers/staging/fsl-mc/include/mc-cmd.h
new file mode 100644 (file)
index 0000000..32501e0
--- /dev/null
@@ -0,0 +1,113 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * 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 the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 __FSL_MC_CMD_H
+#define __FSL_MC_CMD_H
+
+#define MC_CMD_NUM_OF_PARAMS   7
+
+#define MAKE_UMASK64(_width) \
+       ((uint64_t)((_width) < 64 ? ((uint64_t)1 << (_width)) - 1 : -1))
+
+static inline uint64_t mc_enc(int lsoffset, int width, uint64_t val)
+{
+       return (uint64_t)(((uint64_t)val & MAKE_UMASK64(width)) << lsoffset);
+}
+
+static inline uint64_t mc_dec(uint64_t val, int lsoffset, int width)
+{
+       return (uint64_t)((val >> lsoffset) & MAKE_UMASK64(width));
+}
+
+struct mc_command {
+       uint64_t header;
+       uint64_t params[MC_CMD_NUM_OF_PARAMS];
+};
+
+enum mc_cmd_status {
+       MC_CMD_STATUS_OK = 0x0, /* Completed successfully */
+       MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */
+       MC_CMD_STATUS_AUTH_ERR = 0x3, /* Authentication error */
+       MC_CMD_STATUS_NO_PRIVILEGE = 0x4, /* No privilege */
+       MC_CMD_STATUS_DMA_ERR = 0x5, /* DMA or I/O error */
+       MC_CMD_STATUS_CONFIG_ERR = 0x6, /* Configuration error */
+       MC_CMD_STATUS_TIMEOUT = 0x7, /* Operation timed out */
+       MC_CMD_STATUS_NO_RESOURCE = 0x8, /* No resources */
+       MC_CMD_STATUS_NO_MEMORY = 0x9, /* No memory available */
+       MC_CMD_STATUS_BUSY = 0xA, /* Device is busy */
+       MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, /* Unsupported operation */
+       MC_CMD_STATUS_INVALID_STATE = 0xC /* Invalid state */
+};
+
+#define MC_CMD_HDR_CMDID_O     52      /* Command ID field offset */
+#define MC_CMD_HDR_CMDID_S     12      /* Command ID field size */
+#define MC_CMD_HDR_TOKEN_O     38      /* Token field offset */
+#define MC_CMD_HDR_TOKEN_S     10      /* Token field size */
+#define MC_CMD_HDR_STATUS_O    16      /* Status field offset */
+#define MC_CMD_HDR_STATUS_S    8       /* Status field size*/
+#define MC_CMD_HDR_PRI_O       15      /* Priority field offset */
+#define MC_CMD_HDR_PRI_S       1       /* Priority field size */
+
+#define MC_CMD_HDR_READ_STATUS(_hdr) \
+       ((enum mc_cmd_status)mc_dec((_hdr), \
+               MC_CMD_HDR_STATUS_O, MC_CMD_HDR_STATUS_S))
+
+#define MC_CMD_HDR_READ_TOKEN(_hdr) \
+       ((uint16_t)mc_dec((_hdr), MC_CMD_HDR_TOKEN_O, MC_CMD_HDR_TOKEN_S))
+
+#define MC_CMD_PRI_LOW         0 /* Low Priority command indication */
+#define MC_CMD_PRI_HIGH                1 /* High Priority command indication */
+
+#define MC_EXT_OP(_ext, _param, _offset, _width, _type, _arg) \
+       ((_ext)[_param] |= mc_enc((_offset), (_width), _arg))
+
+#define MC_CMD_OP(_cmd, _param, _offset, _width, _type, _arg) \
+       ((_cmd).params[_param] |= mc_enc((_offset), (_width), _arg))
+
+#define MC_RSP_OP(_cmd, _param, _offset, _width, _type, _arg) \
+       (_arg = (_type)mc_dec(_cmd.params[_param], (_offset), (_width)))
+
+static inline uint64_t mc_encode_cmd_header(uint16_t cmd_id,
+                                           uint8_t priority,
+                                           uint16_t token)
+{
+       uint64_t hdr;
+
+       hdr = mc_enc(MC_CMD_HDR_CMDID_O, MC_CMD_HDR_CMDID_S, cmd_id);
+       hdr |= mc_enc(MC_CMD_HDR_TOKEN_O, MC_CMD_HDR_TOKEN_S, token);
+       hdr |= mc_enc(MC_CMD_HDR_PRI_O, MC_CMD_HDR_PRI_S, priority);
+       hdr |= mc_enc(MC_CMD_HDR_STATUS_O, MC_CMD_HDR_STATUS_S,
+                      MC_CMD_STATUS_READY);
+
+       return hdr;
+}
+
+#endif /* __FSL_MC_CMD_H */
diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h
new file mode 100644 (file)
index 0000000..c045f49
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Freescale Management Complex (MC) bus private declarations
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Author: German Rivera <German.Rivera@freescale.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 _FSL_MC_PRIVATE_H_
+#define _FSL_MC_PRIVATE_H_
+
+#include "../include/mc.h"
+#include <linux/mutex.h>
+#include <linux/stringify.h>
+
+#define FSL_MC_DPRC_DRIVER_NAME    "fsl_mc_dprc"
+
+#define FSL_MC_DEVICE_MATCH(_mc_dev, _obj_desc) \
+       (strcmp((_mc_dev)->obj_desc.type, (_obj_desc)->type) == 0 && \
+        (_mc_dev)->obj_desc.id == (_obj_desc)->id)
+
+#define FSL_MC_IS_ALLOCATABLE(_obj_type) \
+       (strcmp(_obj_type, "dpbp") == 0 || \
+        strcmp(_obj_type, "dpmcp") == 0 || \
+        strcmp(_obj_type, "dpcon") == 0)
+
+/**
+ * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device
+ * @root_mc_bus_dev: MC object device representing the root DPRC
+ * @addr_translation_ranges: array of bus to system address translation ranges
+ */
+struct fsl_mc {
+       struct fsl_mc_device *root_mc_bus_dev;
+       uint8_t num_translation_ranges;
+       struct fsl_mc_addr_translation_range *translation_ranges;
+};
+
+/**
+ * struct fsl_mc_addr_translation_range - bus to system address translation
+ * range
+ * @start_mc_addr: Start MC address of the range being translated
+ * @end_mc_addr: MC address of the first byte after the range (last MC
+ * address of the range is end_mc_addr - 1)
+ * @start_phys_addr: system physical address corresponding to start_mc_addr
+ */
+struct fsl_mc_addr_translation_range {
+       uint64_t start_mc_addr;
+       uint64_t end_mc_addr;
+       phys_addr_t start_phys_addr;
+};
+
+/**
+ * struct fsl_mc_resource_pool - Pool of MC resources of a given
+ * type
+ * @type: type of resources in the pool
+ * @max_count: maximum number of resources in the pool
+ * @free_count: number of free resources in the pool
+ * @mutex: mutex to serialize access to the pool's free list
+ * @free_list: anchor node of list of free resources in the pool
+ * @mc_bus: pointer to the MC bus that owns this resource pool
+ */
+struct fsl_mc_resource_pool {
+       enum fsl_mc_pool_type type;
+       int16_t max_count;
+       int16_t free_count;
+       struct mutex mutex;     /* serializes access to free_list */
+       struct list_head free_list;
+       struct fsl_mc_bus *mc_bus;
+};
+
+/**
+ * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC
+ * @mc_dev: fsl-mc device for the bus device itself.
+ * @resource_pools: array of resource pools (one pool per resource type)
+ * for this MC bus. These resources represent allocatable entities
+ * from the physical DPRC.
+ * @scan_mutex: Serializes bus scanning
+ */
+struct fsl_mc_bus {
+       struct fsl_mc_device mc_dev;
+       struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES];
+       struct mutex scan_mutex;    /* serializes bus scanning */
+};
+
+#define to_fsl_mc_bus(_mc_dev) \
+       container_of(_mc_dev, struct fsl_mc_bus, mc_dev)
+
+int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
+                                  struct fsl_mc_io *mc_io,
+                                  struct device *parent_dev,
+                                  struct fsl_mc_device **new_mc_dev);
+
+void fsl_mc_device_remove(struct fsl_mc_device *mc_dev);
+
+int dprc_scan_container(struct fsl_mc_device *mc_bus_dev);
+
+int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev);
+
+int __init dprc_driver_init(void);
+
+void __exit dprc_driver_exit(void);
+
+int __init fsl_mc_allocator_driver_init(void);
+
+void __exit fsl_mc_allocator_driver_exit(void);
+
+int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
+                                         enum fsl_mc_pool_type pool_type,
+                                         struct fsl_mc_resource
+                                                         **new_resource);
+
+void fsl_mc_resource_free(struct fsl_mc_resource *resource);
+
+#endif /* _FSL_MC_PRIVATE_H_ */
diff --git a/drivers/staging/fsl-mc/include/mc-sys.h b/drivers/staging/fsl-mc/include/mc-sys.h
new file mode 100644 (file)
index 0000000..cb3b5a2
--- /dev/null
@@ -0,0 +1,76 @@
+/* Copyright 2013-2014 Freescale Semiconductor Inc.
+ *
+ * Interface of the I/O services to send MC commands to the MC hardware
+ *
+ * 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 the above-listed copyright holders nor the
+ *       names of any contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 HOLDERS 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 _FSL_MC_SYS_H
+#define _FSL_MC_SYS_H
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
+struct fsl_mc_resource;
+struct mc_command;
+
+/**
+ * struct fsl_mc_io - MC I/O object to be passed-in to mc_send_command()
+ * @dev: device associated with this Mc I/O object
+ * @flags: flags for mc_send_command()
+ * @portal_size: MC command portal size in bytes
+ * @portal_phys_addr: MC command portal physical address
+ * @portal_virt_addr: MC command portal virtual address
+ * @resource: generic resource associated with the MC portal if
+ * the MC portal came from a resource pool, or NULL if the MC portal
+ * is permanently bound to a device (e.g., a DPRC)
+ */
+struct fsl_mc_io {
+       struct device *dev;
+       uint32_t flags;
+       uint32_t portal_size;
+       phys_addr_t portal_phys_addr;
+       void __iomem *portal_virt_addr;
+       struct fsl_mc_resource *resource;
+};
+
+int __must_check fsl_create_mc_io(struct device *dev,
+                                 phys_addr_t mc_portal_phys_addr,
+                                 uint32_t mc_portal_size,
+                                 struct fsl_mc_resource *resource,
+                                 uint32_t flags, struct fsl_mc_io **new_mc_io);
+
+void fsl_destroy_mc_io(struct fsl_mc_io *mc_io);
+
+int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd);
+
+#endif /* _FSL_MC_SYS_H */
diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h
new file mode 100644 (file)
index 0000000..fa02ef0
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Freescale Management Complex (MC) bus public interface
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Author: German Rivera <German.Rivera@freescale.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 _FSL_MC_H_
+#define _FSL_MC_H_
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/list.h>
+#include "../include/dprc.h"
+
+#define FSL_MC_VENDOR_FREESCALE        0x1957
+
+struct fsl_mc_device;
+struct fsl_mc_io;
+
+/**
+ * struct fsl_mc_driver - MC object device driver object
+ * @driver: Generic device driver
+ * @match_id_table: table of supported device matching Ids
+ * @probe: Function called when a device is added
+ * @remove: Function called when a device is removed
+ * @shutdown: Function called at shutdown time to quiesce the device
+ * @suspend: Function called when a device is stopped
+ * @resume: Function called when a device is resumed
+ *
+ * Generic DPAA device driver object for device drivers that are registered
+ * with a DPRC bus. This structure is to be embedded in each device-specific
+ * driver structure.
+ */
+struct fsl_mc_driver {
+       struct device_driver driver;
+       const struct fsl_mc_device_match_id *match_id_table;
+       int (*probe)(struct fsl_mc_device *dev);
+       int (*remove)(struct fsl_mc_device *dev);
+       void (*shutdown)(struct fsl_mc_device *dev);
+       int (*suspend)(struct fsl_mc_device *dev, pm_message_t state);
+       int (*resume)(struct fsl_mc_device *dev);
+};
+
+#define to_fsl_mc_driver(_drv) \
+       container_of(_drv, struct fsl_mc_driver, driver)
+
+/**
+ * struct fsl_mc_device_match_id - MC object device Id entry for driver matching
+ * @vendor: vendor ID
+ * @obj_type: MC object type
+ * @ver_major: MC object version major number
+ * @ver_minor: MC object version minor number
+ *
+ * Type of entries in the "device Id" table for MC object devices supported by
+ * a MC object device driver. The last entry of the table has vendor set to 0x0
+ */
+struct fsl_mc_device_match_id {
+       uint16_t vendor;
+       const char obj_type[16];
+       uint32_t ver_major;
+       uint32_t ver_minor;
+};
+
+/**
+ * enum fsl_mc_pool_type - Types of allocatable MC bus resources
+ *
+ * Entries in these enum are used as indices in the array of resource
+ * pools of an fsl_mc_bus object.
+ */
+enum fsl_mc_pool_type {
+       FSL_MC_POOL_DPMCP = 0x0,    /* corresponds to "dpmcp" in the MC */
+       FSL_MC_POOL_DPBP,           /* corresponds to "dpbp" in the MC */
+       FSL_MC_POOL_DPCON,          /* corresponds to "dpcon" in the MC */
+
+       /*
+        * NOTE: New resource pool types must be added before this entry
+        */
+       FSL_MC_NUM_POOL_TYPES
+};
+
+/**
+ * struct fsl_mc_resource - MC generic resource
+ * @type: type of resource
+ * @id: unique MC resource Id within the resources of the same type
+ * @data: pointer to resource-specific data if the resource is currently
+ * allocated, or NULL if the resource is not currently allocated.
+ * @parent_pool: pointer to the parent resource pool from which this
+ * resource is allocated from.
+ * @node: Node in the free list of the corresponding resource pool
+ *
+ * NOTE: This structure is to be embedded as a field of specific
+ * MC resource structures.
+ */
+struct fsl_mc_resource {
+       enum fsl_mc_pool_type type;
+       int32_t id;
+       void *data;
+       struct fsl_mc_resource_pool *parent_pool;
+       struct list_head node;
+};
+
+/**
+ * Bit masks for a MC object device (struct fsl_mc_device) flags
+ */
+#define FSL_MC_IS_DPRC 0x0001
+
+/**
+ * Default DMA mask for devices on a fsl-mc bus
+ */
+#define FSL_MC_DEFAULT_DMA_MASK        (~0ULL)
+
+/**
+ * struct fsl_mc_device - MC object device object
+ * @dev: Linux driver model device object
+ * @dma_mask: Default DMA mask
+ * @flags: MC object device flags
+ * @icid: Isolation context ID for the device
+ * @mc_handle: MC handle for the corresponding MC object opened
+ * @mc_io: Pointer to MC IO object assigned to this device or
+ * NULL if none.
+ * @obj_desc: MC description of the DPAA device
+ * @regions: pointer to array of MMIO region entries
+ * @resource: generic resource associated with this MC object device, if any.
+ *
+ * Generic device object for MC object devices that are "attached" to a
+ * MC bus.
+ *
+ * NOTES:
+ * - For a non-DPRC object its icid is the same as its parent DPRC's icid.
+ * - The SMMU notifier callback gets invoked after device_add() has been
+ *   called for an MC object device, but before the device-specific probe
+ *   callback gets called.
+ * - DP_OBJ_DPRC objects are the only MC objects that have built-in MC
+ *   portals. For all other MC objects, their device drivers are responsible for
+ *   allocating MC portals for them by calling fsl_mc_portal_allocate().
+ * - Some types of MC objects (e.g., DP_OBJ_DPBP, DP_OBJ_DPCON) are
+ *   treated as resources that can be allocated/deallocated from the
+ *   corresponding resource pool in the object's parent DPRC, using the
+ *   fsl_mc_object_allocate()/fsl_mc_object_free() functions. These MC objects
+ *   are known as "allocatable" objects. For them, the corresponding
+ *   fsl_mc_device's 'resource' points to the associated resource object.
+ *   For MC objects that are not allocatable (e.g., DP_OBJ_DPRC, DP_OBJ_DPNI),
+ *   'resource' is NULL.
+ */
+struct fsl_mc_device {
+       struct device dev;
+       uint64_t dma_mask;
+       uint16_t flags;
+       uint16_t icid;
+       uint16_t mc_handle;
+       struct fsl_mc_io *mc_io;
+       struct dprc_obj_desc obj_desc;
+       struct resource *regions;
+       struct fsl_mc_resource *resource;
+};
+
+#define to_fsl_mc_device(_dev) \
+       container_of(_dev, struct fsl_mc_device, dev)
+
+/*
+ * module_fsl_mc_driver() - Helper macro for drivers that don't do
+ * anything special in module init/exit.  This eliminates a lot of
+ * boilerplate.  Each module may only use this macro once, and
+ * calling it replaces module_init() and module_exit()
+ */
+#define module_fsl_mc_driver(__fsl_mc_driver) \
+       module_driver(__fsl_mc_driver, fsl_mc_driver_register, \
+                     fsl_mc_driver_unregister)
+
+/*
+ * Macro to avoid include chaining to get THIS_MODULE
+ */
+#define fsl_mc_driver_register(drv) \
+       __fsl_mc_driver_register(drv, THIS_MODULE)
+
+int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver,
+                                         struct module *owner);
+
+void fsl_mc_driver_unregister(struct fsl_mc_driver *driver);
+
+int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
+                                       uint16_t mc_io_flags,
+                                       struct fsl_mc_io **new_mc_io);
+
+void fsl_mc_portal_free(struct fsl_mc_io *mc_io);
+
+int fsl_mc_portal_reset(struct fsl_mc_io *mc_io);
+
+int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
+                                       enum fsl_mc_pool_type pool_type,
+                                       struct fsl_mc_device **new_mc_adev);
+
+void fsl_mc_object_free(struct fsl_mc_device *mc_adev);
+
+extern struct bus_type fsl_mc_bus_type;
+
+#endif /* _FSL_MC_H_ */
index 922478e1cb576cd87a41ae70e544318910b40ff7..e5cc5bedf031e3f061d04c4aab8f80b6ec47cde4 100644 (file)
@@ -155,15 +155,4 @@ static struct pcmcia_driver ft1000_cs_driver = {
        .resume         = ft1000_resume,
 };
 
-static int __init init_ft1000_cs(void)
-{
-       return pcmcia_register_driver(&ft1000_cs_driver);
-}
-
-static void __exit exit_ft1000_cs(void)
-{
-       pcmcia_unregister_driver(&ft1000_cs_driver);
-}
-
-module_init(init_ft1000_cs);
-module_exit(exit_ft1000_cs);
+module_pcmcia_driver(ft1000_cs_driver);
index 06b0e9cfb9b17011a579b18ed1c948ced4f5565a..83683e9a145137cf625549d0926426e0a4b8d229 100644 (file)
@@ -116,7 +116,7 @@ struct dsp_image_info {
 
 void card_bootload(struct net_device *dev)
 {
-       struct ft1000_info *info = (struct ft1000_info *)netdev_priv(dev);
+       struct ft1000_info *info = netdev_priv(dev);
        unsigned long flags;
        u32 *pdata;
        u32 size;
@@ -148,7 +148,7 @@ void card_bootload(struct net_device *dev)
 
 u16 get_handshake(struct net_device *dev, u16 expected_value)
 {
-       struct ft1000_info *info = (struct ft1000_info *)netdev_priv(dev);
+       struct ft1000_info *info = netdev_priv(dev);
        u16 handshake;
        u32 tempx;
        int loopcnt;
@@ -182,7 +182,7 @@ u16 get_handshake(struct net_device *dev, u16 expected_value)
 
 void put_handshake(struct net_device *dev, u16 handshake_value)
 {
-       struct ft1000_info *info = (struct ft1000_info *)netdev_priv(dev);
+       struct ft1000_info *info = netdev_priv(dev);
        u32 tempx;
 
        if (info->AsicID == ELECTRABUZZ_ID) {
@@ -198,7 +198,7 @@ void put_handshake(struct net_device *dev, u16 handshake_value)
 
 u16 get_request_type(struct net_device *dev)
 {
-       struct ft1000_info *info = (struct ft1000_info *)netdev_priv(dev);
+       struct ft1000_info *info = netdev_priv(dev);
        u16 request_type;
        u32 tempx;
 
@@ -217,7 +217,7 @@ u16 get_request_type(struct net_device *dev)
 
 long get_request_value(struct net_device *dev)
 {
-       struct ft1000_info *info = (struct ft1000_info *)netdev_priv(dev);
+       struct ft1000_info *info = netdev_priv(dev);
        long value;
        u16 w_val;
 
@@ -246,7 +246,7 @@ long get_request_value(struct net_device *dev)
 
 void put_request_value(struct net_device *dev, long lvalue)
 {
-       struct ft1000_info *info = (struct ft1000_info *)netdev_priv(dev);
+       struct ft1000_info *info = netdev_priv(dev);
        u16 size;
        u32 tempx;
 
@@ -276,8 +276,8 @@ u16 hdr_checksum(struct pseudo_hdr *pHdr)
        u16 *usPtr = (u16 *)pHdr;
        u16 chksum;
 
-       chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
-                   usPtr[4]) ^ usPtr[5]) ^ usPtr[6]);
+       chksum = (((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
+                   usPtr[4]) ^ usPtr[5]) ^ usPtr[6];
 
        return chksum;
 }
@@ -285,7 +285,7 @@ u16 hdr_checksum(struct pseudo_hdr *pHdr)
 int card_download(struct net_device *dev, const u8 *pFileStart,
                  size_t FileLength)
 {
-       struct ft1000_info *info = (struct ft1000_info *)netdev_priv(dev);
+       struct ft1000_info *info = netdev_priv(dev);
        int Status = SUCCESS;
        u32 uiState;
        u16 handshake;
@@ -713,10 +713,10 @@ int card_download(struct net_device *dev, const u8 *pFileStart,
 
                                /* Get buffer for provisioning data */
                                pbuffer =
-                                       kmalloc((usHdrLength + sizeof(struct pseudo_hdr)),
+                                       kmalloc(usHdrLength + sizeof(struct pseudo_hdr),
                                                GFP_ATOMIC);
                                if (pbuffer) {
-                                       memcpy(pbuffer, (void *)pUcFile,
+                                       memcpy(pbuffer, pUcFile,
                                               (u32) (usHdrLength +
                                                      sizeof(struct pseudo_hdr)));
                                        /* link provisioning data */
index 017c3b92f51bff3d4835dd0f83ccd0eab43f19bd..eecfa377054dcc88fe50009c9041dd9200db1616 100644 (file)
@@ -28,8 +28,8 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/in.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -67,8 +67,7 @@ static void ft1000_disable_interrupts(struct net_device *dev);
 
 /* new kernel */
 MODULE_AUTHOR("");
-MODULE_DESCRIPTION
-("Support for Flarion Flash OFDM NIC Device. Support for PCMCIA when used with ft1000_cs.");
+MODULE_DESCRIPTION("Support for Flarion Flash OFDM NIC Device. Support for PCMCIA when used with ft1000_cs.");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("FT1000");
 
@@ -267,7 +266,8 @@ void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value)
 /*---------------------------------------------------------------------------
 
   Function:   ft1000_enable_interrupts
-  Description: This function will enable interrupts base on the current interrupt mask.
+  Description: This function will enable interrupts base on the current
+              interrupt mask.
   Input:
   dev    - device structure
   Output:
@@ -302,6 +302,41 @@ static void ft1000_disable_interrupts(struct net_device *dev)
        pr_debug("current interrupt enable mask = 0x%x\n", tempword);
 }
 
+/*---------------------------------------------------------------------------
+  Function:    ft1000_read_dsp_timer
+  Description: This function reads the DSP timer and stores its value in the
+               DSP_TIME field of the ft1000_info struct passed as argument
+  Input:
+  dev    - device structure
+  info   - ft1000_info structure
+  Output:
+  None.
+
+  -------------------------------------------------------------------------*/
+static void ft1000_read_dsp_timer(struct net_device *dev,
+                                 struct ft1000_info *info)
+{
+       if (info->AsicID == ELECTRABUZZ_ID) {
+               info->DSP_TIME[0] = ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
+               info->DSP_TIME[1] = ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
+               info->DSP_TIME[2] = ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
+               info->DSP_TIME[3] = ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
+       } else {
+               info->DSP_TIME[0] =
+                       ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER0,
+                                                FT1000_MAG_DSP_TIMER0_INDX);
+               info->DSP_TIME[1] =
+                       ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER1,
+                                                FT1000_MAG_DSP_TIMER1_INDX);
+               info->DSP_TIME[2] =
+                       ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER2,
+                                                FT1000_MAG_DSP_TIMER2_INDX);
+               info->DSP_TIME[3] =
+                       ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER3,
+                                                FT1000_MAG_DSP_TIMER3_INDX);
+       }
+}
+
 /*---------------------------------------------------------------------------
 
   Function:   ft1000_reset_asic
@@ -327,7 +362,7 @@ static void ft1000_reset_asic(struct net_device *dev)
         */
        if (info->AsicID == MAGNEMITE_ID) {
                ft1000_write_reg(dev, FT1000_REG_RESET,
-                                (DSP_RESET_BIT | ASIC_RESET_BIT));
+                                DSP_RESET_BIT | ASIC_RESET_BIT);
        }
        mdelay(1);
        if (info->AsicID == ELECTRABUZZ_ID) {
@@ -364,6 +399,7 @@ static int ft1000_reset_card(struct net_device *dev)
        int i;
        unsigned long flags;
        struct prov_record *ptr;
+       struct prov_record *tmp;
 
        info->CardReady = 0;
        info->ProgConStat = 0;
@@ -373,9 +409,8 @@ static int ft1000_reset_card(struct net_device *dev)
        /* del_timer(&poll_timer); */
 
        /* Make sure we free any memory reserve for provisioning */
-       while (list_empty(&info->prov_list) == 0) {
+       list_for_each_entry_safe(ptr, tmp, &info->prov_list, list) {
                pr_debug("deleting provisioning record\n");
-               ptr = list_entry(info->prov_list.next, struct prov_record, list);
                list_del(&ptr->list);
                kfree(ptr->pprov_data);
                kfree(ptr);
@@ -387,7 +422,7 @@ static int ft1000_reset_card(struct net_device *dev)
        } else {
                pr_debug("resetting ASIC and DSP\n");
                ft1000_write_reg(dev, FT1000_REG_RESET,
-                                (DSP_RESET_BIT | ASIC_RESET_BIT));
+                                DSP_RESET_BIT | ASIC_RESET_BIT);
        }
 
        /* Copy DSP session record into info block if this is not a coldstart */
@@ -406,7 +441,8 @@ static int ft1000_reset_card(struct net_device *dev)
                                         FT1000_DPRAM_MAG_RX_BASE);
                        for (i = 0; i < MAX_DSP_SESS_REC / 2; i++) {
                                info->DSPSess.MagRec[i] =
-                                       inl(dev->base_addr + FT1000_REG_MAG_DPDATA);
+                                       inl(dev->base_addr
+                                               + FT1000_REG_MAG_DPDATA);
                        }
                }
                spin_unlock_irqrestore(&info->dpram_lock, flags);
@@ -435,11 +471,14 @@ static int ft1000_reset_card(struct net_device *dev)
                mdelay(10);
                pr_debug("Take DSP out of reset\n");
 
-               /* Wait for 0xfefe indicating dsp ready before starting download */
+               /*
+                * Wait for 0xfefe indicating dsp ready before starting
+                * download
+                */
                for (i = 0; i < 50; i++) {
-                       tempword =
-                               ft1000_read_dpram_mag_16(dev, FT1000_MAG_DPRAM_FEFE,
-                                                        FT1000_MAG_DPRAM_FEFE_INDX);
+                       tempword = ft1000_read_dpram_mag_16(dev,
+                                               FT1000_MAG_DPRAM_FEFE,
+                                               FT1000_MAG_DPRAM_FEFE_INDX);
                        if (tempword == 0xfefe)
                                break;
                        mdelay(20);
@@ -459,16 +498,15 @@ static int ft1000_reset_card(struct net_device *dev)
        if (card_download(dev, fw_entry->data, fw_entry->size)) {
                pr_debug("card download unsuccessful\n");
                return false;
-       } else {
-               pr_debug("card download successful\n");
        }
+       pr_debug("card download successful\n");
 
        mdelay(10);
 
        if (info->AsicID == ELECTRABUZZ_ID) {
                /*
-                * Need to initialize the FIFO length counter to zero in order to sync up
-                * with the DSP
+                * Need to initialize the FIFO length counter to zero in order
+                * to sync up with the DSP
                 */
                info->fifo_cnt = 0;
                ft1000_write_dpram(dev, FT1000_FIFO_LEN, info->fifo_cnt);
@@ -578,33 +616,7 @@ static void ft1000_hbchk(u_long data)
                }
                if (tempword != ho) {
                        pr_info("heartbeat failed - no ho detected\n");
-                       if (info->AsicID == ELECTRABUZZ_ID) {
-                               info->DSP_TIME[0] =
-                                       ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
-                               info->DSP_TIME[1] =
-                                       ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
-                               info->DSP_TIME[2] =
-                                       ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
-                               info->DSP_TIME[3] =
-                                       ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
-                       } else {
-                               info->DSP_TIME[0] =
-                                       ft1000_read_dpram_mag_16(dev,
-                                                                FT1000_MAG_DSP_TIMER0,
-                                                                FT1000_MAG_DSP_TIMER0_INDX);
-                               info->DSP_TIME[1] =
-                                       ft1000_read_dpram_mag_16(dev,
-                                                                FT1000_MAG_DSP_TIMER1,
-                                                                FT1000_MAG_DSP_TIMER1_INDX);
-                               info->DSP_TIME[2] =
-                                       ft1000_read_dpram_mag_16(dev,
-                                                                FT1000_MAG_DSP_TIMER2,
-                                                                FT1000_MAG_DSP_TIMER2_INDX);
-                               info->DSP_TIME[3] =
-                                       ft1000_read_dpram_mag_16(dev,
-                                                                FT1000_MAG_DSP_TIMER3,
-                                                                FT1000_MAG_DSP_TIMER3_INDX);
-                       }
+                       ft1000_read_dsp_timer(dev, info);
                        info->DrvErrNum = DSP_HB_INFO;
                        if (ft1000_reset_card(dev) == 0) {
                                pr_info("Hardware Failure Detected - PC Card disabled\n");
@@ -625,33 +637,7 @@ static void ft1000_hbchk(u_long data)
 
                if (tempword & FT1000_DB_HB) {
                        pr_info("heartbeat doorbell not clear by firmware\n");
-                       if (info->AsicID == ELECTRABUZZ_ID) {
-                               info->DSP_TIME[0] =
-                                       ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
-                               info->DSP_TIME[1] =
-                                       ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
-                               info->DSP_TIME[2] =
-                                       ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
-                               info->DSP_TIME[3] =
-                                       ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
-                       } else {
-                               info->DSP_TIME[0] =
-                                       ft1000_read_dpram_mag_16(dev,
-                                                                FT1000_MAG_DSP_TIMER0,
-                                                                FT1000_MAG_DSP_TIMER0_INDX);
-                               info->DSP_TIME[1] =
-                                       ft1000_read_dpram_mag_16(dev,
-                                                                FT1000_MAG_DSP_TIMER1,
-                                                                FT1000_MAG_DSP_TIMER1_INDX);
-                               info->DSP_TIME[2] =
-                                       ft1000_read_dpram_mag_16(dev,
-                                                                FT1000_MAG_DSP_TIMER2,
-                                                                FT1000_MAG_DSP_TIMER2_INDX);
-                               info->DSP_TIME[3] =
-                                       ft1000_read_dpram_mag_16(dev,
-                                                                FT1000_MAG_DSP_TIMER3,
-                                                                FT1000_MAG_DSP_TIMER3_INDX);
-                       }
+                       ft1000_read_dsp_timer(dev, info);
                        info->DrvErrNum = DSP_HB_INFO;
                        if (ft1000_reset_card(dev) == 0) {
                                pr_info("Hardware Failure Detected - PC Card disabled\n");
@@ -665,8 +651,8 @@ static void ft1000_hbchk(u_long data)
                        return;
                }
                /*
-                * Set dedicated area to hi and ring appropriate doorbell according
-                * to hi/ho heartbeat protocol
+                * Set dedicated area to hi and ring appropriate doorbell
+                * according to hi/ho heartbeat protocol
                 */
                if (info->AsicID == ELECTRABUZZ_ID) {
                        ft1000_write_dpram(dev, FT1000_HI_HO, hi);
@@ -688,44 +674,20 @@ static void ft1000_hbchk(u_long data)
                        if (info->AsicID == ELECTRABUZZ_ID)
                                ft1000_write_dpram(dev, FT1000_HI_HO, hi);
                        else
-                               ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, hi_mag, FT1000_MAG_HI_HO_INDX);
+                               ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO,
+                                               hi_mag, FT1000_MAG_HI_HO_INDX);
 
                        if (info->AsicID == ELECTRABUZZ_ID)
                                tempword = ft1000_read_dpram(dev, FT1000_HI_HO);
                        else
-                               tempword = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX));
-
+                               tempword = ntohs(ft1000_read_dpram_mag_16(dev,
+                                                       FT1000_MAG_HI_HO,
+                                                       FT1000_MAG_HI_HO_INDX));
                }
 
                if (tempword != hi) {
                        pr_info("heartbeat failed - cannot write hi into DPRAM\n");
-                       if (info->AsicID == ELECTRABUZZ_ID) {
-                               info->DSP_TIME[0] =
-                                       ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
-                               info->DSP_TIME[1] =
-                                       ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
-                               info->DSP_TIME[2] =
-                                       ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
-                               info->DSP_TIME[3] =
-                                       ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
-                       } else {
-                               info->DSP_TIME[0] =
-                                       ft1000_read_dpram_mag_16(dev,
-                                                                FT1000_MAG_DSP_TIMER0,
-                                                                FT1000_MAG_DSP_TIMER0_INDX);
-                               info->DSP_TIME[1] =
-                                       ft1000_read_dpram_mag_16(dev,
-                                                                FT1000_MAG_DSP_TIMER1,
-                                                                FT1000_MAG_DSP_TIMER1_INDX);
-                               info->DSP_TIME[2] =
-                                       ft1000_read_dpram_mag_16(dev,
-                                                                FT1000_MAG_DSP_TIMER2,
-                                                                FT1000_MAG_DSP_TIMER2_INDX);
-                               info->DSP_TIME[3] =
-                                       ft1000_read_dpram_mag_16(dev,
-                                                                FT1000_MAG_DSP_TIMER3,
-                                                                FT1000_MAG_DSP_TIMER3_INDX);
-                       }
+                       ft1000_read_dsp_timer(dev, info);
                        info->DrvErrNum = DSP_HB_INFO;
                        if (ft1000_reset_card(dev) == 0) {
                                pr_info("Hardware Failure Detected - PC Card disabled\n");
@@ -756,7 +718,8 @@ static void ft1000_hbchk(u_long data)
   Output:
 
   -------------------------------------------------------------------------*/
-static void ft1000_send_cmd(struct net_device *dev, u16 *ptempbuffer, int size, u16 qtype)
+static void ft1000_send_cmd(struct net_device *dev, u16 *ptempbuffer, int size,
+                           u16 qtype)
 {
        struct ft1000_info *info = netdev_priv(dev);
        int i;
@@ -850,74 +813,73 @@ static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer,
        unsigned long flags;
 
        if (info->AsicID == ELECTRABUZZ_ID) {
-               size = (ft1000_read_dpram(dev, *pnxtph)) + sizeof(struct pseudo_hdr);
+               size = ft1000_read_dpram(dev, *pnxtph)
+                       + sizeof(struct pseudo_hdr);
        } else {
-               size =
-                       ntohs(ft1000_read_dpram_mag_16
-                             (dev, FT1000_MAG_PH_LEN,
-                              FT1000_MAG_PH_LEN_INDX)) + sizeof(struct pseudo_hdr);
+               size = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_PH_LEN,
+                                                     FT1000_MAG_PH_LEN_INDX))
+                               + sizeof(struct pseudo_hdr);
        }
        if (size > maxsz) {
                pr_debug("Invalid command length = %d\n", size);
                return false;
+       }
+       ppseudohdr = (u16 *)pbuffer;
+       spin_lock_irqsave(&info->dpram_lock, flags);
+       if (info->AsicID == ELECTRABUZZ_ID) {
+               ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
+                                FT1000_DPRAM_RX_BASE + 2);
+               for (i = 0; i <= (size >> 1); i++) {
+                       tempword =
+                               ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
+                       *pbuffer++ = ntohs(tempword);
+               }
        } else {
-               ppseudohdr = (u16 *)pbuffer;
-               spin_lock_irqsave(&info->dpram_lock, flags);
-               if (info->AsicID == ELECTRABUZZ_ID) {
-                       ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
-                                        FT1000_DPRAM_RX_BASE + 2);
-                       for (i = 0; i <= (size >> 1); i++) {
-                               tempword =
-                                       ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
-                               *pbuffer++ = ntohs(tempword);
-                       }
-               } else {
-                       ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
-                                        FT1000_DPRAM_MAG_RX_BASE);
-                       *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
-                       pr_debug("received data = 0x%x\n", *pbuffer);
-                       pbuffer++;
-                       ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
-                                        FT1000_DPRAM_MAG_RX_BASE + 1);
-                       for (i = 0; i <= (size >> 2); i++) {
-                               *pbuffer =
-                                       inw(dev->base_addr +
-                                           FT1000_REG_MAG_DPDATAL);
-                               pbuffer++;
-                               *pbuffer =
-                                       inw(dev->base_addr +
-                                           FT1000_REG_MAG_DPDATAH);
-                               pbuffer++;
-                       }
-                       /* copy odd aligned word */
-                       *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAL);
-                       pr_debug("received data = 0x%x\n", *pbuffer);
+               ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
+                                FT1000_DPRAM_MAG_RX_BASE);
+               *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
+               pr_debug("received data = 0x%x\n", *pbuffer);
+               pbuffer++;
+               ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
+                                FT1000_DPRAM_MAG_RX_BASE + 1);
+               for (i = 0; i <= (size >> 2); i++) {
+                       *pbuffer =
+                               inw(dev->base_addr +
+                                   FT1000_REG_MAG_DPDATAL);
                        pbuffer++;
-                       *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
-                       pr_debug("received data = 0x%x\n", *pbuffer);
+                       *pbuffer =
+                               inw(dev->base_addr +
+                                   FT1000_REG_MAG_DPDATAH);
                        pbuffer++;
                }
-               if (size & 0x0001) {
-                       /* copy odd byte from fifo */
-                       tempword = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
-                       *pbuffer = ntohs(tempword);
-               }
-               spin_unlock_irqrestore(&info->dpram_lock, flags);
+               /* copy odd aligned word */
+               *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAL);
+               pr_debug("received data = 0x%x\n", *pbuffer);
+               pbuffer++;
+               *pbuffer = inw(dev->base_addr + FT1000_REG_MAG_DPDATAH);
+               pr_debug("received data = 0x%x\n", *pbuffer);
+               pbuffer++;
+       }
+       if (size & 0x0001) {
+               /* copy odd byte from fifo */
+               tempword = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
+               *pbuffer = ntohs(tempword);
+       }
+       spin_unlock_irqrestore(&info->dpram_lock, flags);
 
-               /*
-                * Check if pseudo header checksum is good
-                * Calculate pseudo header checksum
-                */
-               tempword = *ppseudohdr++;
-               for (i = 1; i < 7; i++)
-                       tempword ^= *ppseudohdr++;
-               if ((tempword != *ppseudohdr)) {
-                       pr_debug("Pseudo header checksum mismatch\n");
-                       /* Drop this message */
-                       return false;
-               }
-               return true;
+       /*
+        * Check if pseudo header checksum is good
+        * Calculate pseudo header checksum
+        */
+       tempword = *ppseudohdr++;
+       for (i = 1; i < 7; i++)
+               tempword ^= *ppseudohdr++;
+       if (tempword != *ppseudohdr) {
+               pr_debug("Pseudo header checksum mismatch\n");
+               /* Drop this message */
+               return false;
        }
+       return true;
 }
 
 /*---------------------------------------------------------------------------
@@ -957,7 +919,10 @@ static void ft1000_proc_drvmsg(struct net_device *dev)
 
        if (ft1000_receive_cmd(dev, &cmdbuffer[0], MAX_CMD_SQSIZE, &tempword)) {
 
-               /* Get the message type which is total_len + PSEUDO header + msgtype + message body */
+               /*
+                * Get the message type which is total_len + PSEUDO header
+                * + msgtype + message body
+                */
                pdrvmsg = (struct drv_msg *)&cmdbuffer[0];
                msgtype = ntohs(pdrvmsg->type);
                pr_debug("Command message type = 0x%x\n", msgtype);
@@ -968,8 +933,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev)
                        while (list_empty(&info->prov_list) == 0) {
                                pr_debug("Sending a provisioning message\n");
                                /* Make sure SLOWQ doorbell is clear */
-                               tempword =
-                                       ft1000_read_reg(dev, FT1000_REG_DOORBELL);
+                               tempword = ft1000_read_reg(dev,
+                                                          FT1000_REG_DOORBELL);
                                i = 0;
                                while (tempword & FT1000_DB_DPRAM_TX) {
                                        mdelay(5);
@@ -977,9 +942,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev)
                                        if (i == 10)
                                                break;
                                }
-                               ptr =
-                                       list_entry(info->prov_list.next,
-                                                  struct prov_record, list);
+                               ptr = list_entry(info->prov_list.next,
+                                                struct prov_record, list);
                                len = *(u16 *)ptr->pprov_data;
                                len = htons(len);
 
@@ -998,14 +962,15 @@ static void ft1000_proc_drvmsg(struct net_device *dev)
                                                 ppseudo_hdr->checksum);
                                }
 
-                               ft1000_send_cmd(dev, (u16 *)ptr->pprov_data, len, SLOWQ_TYPE);
+                               ft1000_send_cmd(dev, (u16 *)ptr->pprov_data,
+                                               len, SLOWQ_TYPE);
                                list_del(&ptr->list);
                                kfree(ptr->pprov_data);
                                kfree(ptr);
                        }
                        /*
-                        * Indicate adapter is ready to take application messages after all
-                        * provisioning messages are sent
+                        * Indicate adapter is ready to take application
+                        * messages after all provisioning messages are sent
                         */
                        info->CardReady = 1;
                        break;
@@ -1093,8 +1058,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev)
                        tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
                        if (tempword & FT1000_DB_DPRAM_TX) {
                                mdelay(10);
-                               tempword =
-                                       ft1000_read_reg(dev, FT1000_REG_DOORBELL);
+                               tempword = ft1000_read_reg(dev,
+                                                          FT1000_REG_DOORBELL);
                                if (tempword & FT1000_DB_DPRAM_TX)
                                        mdelay(10);
                        }
@@ -1129,7 +1094,9 @@ static void ft1000_proc_drvmsg(struct net_device *dev)
                                info->DSPInfoBlk[8] = 0x7200;
                                info->DSPInfoBlk[9] =
                                        htons(info->DSPInfoBlklen);
-                               ft1000_send_cmd(dev, (u16 *)info->DSPInfoBlk, (u16)(info->DSPInfoBlklen+4), 0);
+                               ft1000_send_cmd(dev, info->DSPInfoBlk,
+                                               (u16)(info->DSPInfoBlklen+4),
+                                               0);
                        }
 
                        break;
@@ -1143,8 +1110,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev)
                        tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
                        if (tempword & FT1000_DB_DPRAM_TX) {
                                mdelay(10);
-                               tempword =
-                                       ft1000_read_reg(dev, FT1000_REG_DOORBELL);
+                               tempword = ft1000_read_reg(dev,
+                                                          FT1000_REG_DOORBELL);
                                if (tempword & FT1000_DB_DPRAM_TX)
                                        mdelay(10);
                        }
@@ -1190,7 +1157,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev)
                                *pmsg++ = convert.wrd;
                                *pmsg++ = htons(info->DrvErrNum);
 
-                               ft1000_send_cmd(dev, (u16 *)&tempbuffer[0], (u16)(0x0012), 0);
+                               ft1000_send_cmd(dev, (u16 *)&tempbuffer[0],
+                                               (u16)(0x0012), 0);
                                info->DrvErrNum = 0;
                        }
 
@@ -1281,28 +1249,30 @@ static int ft1000_parse_dpram_msg(struct net_device *dev)
                                       FT1000_MAG_TOTAL_LEN_INDX));
                }
                pr_debug("total length = %d\n", total_len);
-               if ((total_len < MAX_CMD_SQSIZE) && (total_len > sizeof(struct pseudo_hdr))) {
+               if ((total_len < MAX_CMD_SQSIZE)
+                               && (total_len > sizeof(struct pseudo_hdr))) {
                        total_len += nxtph;
                        /*
-                        * ft1000_read_reg will return a value that needs to be byteswap
-                        * in order to get DSP_QID_OFFSET.
+                        * ft1000_read_reg will return a value that needs to be
+                        * byteswap in order to get DSP_QID_OFFSET.
                         */
                        if (info->AsicID == ELECTRABUZZ_ID) {
-                               portid =
-                                       (ft1000_read_dpram
-                                        (dev,
-                                         DSP_QID_OFFSET + FT1000_DPRAM_RX_BASE +
-                                         2) >> 8) & 0xff;
+                               portid = (ft1000_read_dpram(dev, DSP_QID_OFFSET
+                                               + FT1000_DPRAM_RX_BASE + 2)
+                                               >> 8) & 0xff;
                        } else {
                                portid =
-                                       (ft1000_read_dpram_mag_16
+                                       ft1000_read_dpram_mag_16
                                         (dev, FT1000_MAG_PORT_ID,
-                                         FT1000_MAG_PORT_ID_INDX) & 0xff);
+                                         FT1000_MAG_PORT_ID_INDX) & 0xff;
                        }
                        pr_debug("DSP_QID = 0x%x\n", portid);
 
                        if (portid == DRIVERID) {
-                               /* We are assumming one driver message from the DSP at a time. */
+                               /*
+                                * We are assumming one driver message from the
+                                * DSP at a time.
+                                */
                                ft1000_proc_drvmsg(dev);
                        }
                }
@@ -1311,29 +1281,7 @@ static int ft1000_parse_dpram_msg(struct net_device *dev)
 
        if (doorbell & FT1000_DB_COND_RESET) {
                /* Reset ASIC and DSP */
-               if (info->AsicID == ELECTRABUZZ_ID) {
-                       info->DSP_TIME[0] =
-                               ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
-                       info->DSP_TIME[1] =
-                               ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
-                       info->DSP_TIME[2] =
-                               ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
-                       info->DSP_TIME[3] =
-                               ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
-               } else {
-                       info->DSP_TIME[0] =
-                               ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER0,
-                                                        FT1000_MAG_DSP_TIMER0_INDX);
-                       info->DSP_TIME[1] =
-                               ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER1,
-                                                        FT1000_MAG_DSP_TIMER1_INDX);
-                       info->DSP_TIME[2] =
-                               ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER2,
-                                                        FT1000_MAG_DSP_TIMER2_INDX);
-                       info->DSP_TIME[3] =
-                               ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER3,
-                                                        FT1000_MAG_DSP_TIMER3_INDX);
-               }
+               ft1000_read_dsp_timer(dev, info);
                info->DrvErrNum = DSP_CONDRESET_INFO;
                pr_debug("DSP conditional reset requested\n");
                ft1000_reset_card(dev);
@@ -1374,131 +1322,84 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum)
        u16 tempword;
 
        if (pcmcia->PktIntfErr > MAX_PH_ERR) {
-               if (info->AsicID == ELECTRABUZZ_ID) {
-                       info->DSP_TIME[0] =
-                               ft1000_read_dpram(dev, FT1000_DSP_TIMER0);
-                       info->DSP_TIME[1] =
-                               ft1000_read_dpram(dev, FT1000_DSP_TIMER1);
-                       info->DSP_TIME[2] =
-                               ft1000_read_dpram(dev, FT1000_DSP_TIMER2);
-                       info->DSP_TIME[3] =
-                               ft1000_read_dpram(dev, FT1000_DSP_TIMER3);
-               } else {
-                       info->DSP_TIME[0] =
-                               ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER0,
-                                                        FT1000_MAG_DSP_TIMER0_INDX);
-                       info->DSP_TIME[1] =
-                               ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER1,
-                                                        FT1000_MAG_DSP_TIMER1_INDX);
-                       info->DSP_TIME[2] =
-                               ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER2,
-                                                        FT1000_MAG_DSP_TIMER2_INDX);
-                       info->DSP_TIME[3] =
-                               ft1000_read_dpram_mag_16(dev, FT1000_MAG_DSP_TIMER3,
-                                                        FT1000_MAG_DSP_TIMER3_INDX);
-               }
+               ft1000_read_dsp_timer(dev, info);
                info->DrvErrNum = DrvErrNum;
                ft1000_reset_card(dev);
                return;
-       } else {
-               /* Flush corrupted pkt from FIFO */
-               i = 0;
-               do {
-                       if (info->AsicID == ELECTRABUZZ_ID) {
-                               tempword =
-                                       ft1000_read_reg(dev, FT1000_REG_DFIFO);
-                               tempword =
-                                       ft1000_read_reg(dev, FT1000_REG_DFIFO_STAT);
-                       } else {
-                               templong =
-                                       inl(dev->base_addr + FT1000_REG_MAG_DFR);
+       }
+       /* Flush corrupted pkt from FIFO */
+       i = 0;
+       do {
+               if (info->AsicID == ELECTRABUZZ_ID) {
+                       tempword =
+                               ft1000_read_reg(dev, FT1000_REG_DFIFO);
+                       tempword =
+                               ft1000_read_reg(dev, FT1000_REG_DFIFO_STAT);
+               } else {
+                       templong =
+                               inl(dev->base_addr + FT1000_REG_MAG_DFR);
+                       tempword =
+                               inw(dev->base_addr + FT1000_REG_MAG_DFSR);
+               }
+               i++;
+               /*
+                * This should never happen unless the ASIC is broken.
+                * We must reset to recover.
+                */
+               if ((i > 2048) || (tempword == 0)) {
+                       ft1000_read_dsp_timer(dev, info);
+                       if (tempword == 0) {
+                               /*
+                                * Let's check if ASIC reads are still ok by
+                                * reading the Mask register which is never zero
+                                * at this point of the code.
+                                */
                                tempword =
-                                       inw(dev->base_addr + FT1000_REG_MAG_DFSR);
-                       }
-                       i++;
-                       /*
-                        * This should never happen unless the ASIC is broken.
-                        * We must reset to recover.
-                        */
-                       if ((i > 2048) || (tempword == 0)) {
-                               if (info->AsicID == ELECTRABUZZ_ID) {
-                                       info->DSP_TIME[0] =
-                                               ft1000_read_dpram(dev,
-                                                                 FT1000_DSP_TIMER0);
-                                       info->DSP_TIME[1] =
-                                               ft1000_read_dpram(dev,
-                                                                 FT1000_DSP_TIMER1);
-                                       info->DSP_TIME[2] =
-                                               ft1000_read_dpram(dev,
-                                                                 FT1000_DSP_TIMER2);
-                                       info->DSP_TIME[3] =
-                                               ft1000_read_dpram(dev,
-                                                                 FT1000_DSP_TIMER3);
-                               } else {
-                                       info->DSP_TIME[0] =
-                                               ft1000_read_dpram_mag_16(dev,
-                                                                        FT1000_MAG_DSP_TIMER0,
-                                                                        FT1000_MAG_DSP_TIMER0_INDX);
-                                       info->DSP_TIME[1] =
-                                               ft1000_read_dpram_mag_16(dev,
-                                                                        FT1000_MAG_DSP_TIMER1,
-                                                                        FT1000_MAG_DSP_TIMER1_INDX);
-                                       info->DSP_TIME[2] =
-                                               ft1000_read_dpram_mag_16(dev,
-                                                                        FT1000_MAG_DSP_TIMER2,
-                                                                        FT1000_MAG_DSP_TIMER2_INDX);
-                                       info->DSP_TIME[3] =
-                                               ft1000_read_dpram_mag_16(dev,
-                                                                        FT1000_MAG_DSP_TIMER3,
-                                                                        FT1000_MAG_DSP_TIMER3_INDX);
-                               }
+                                       inw(dev->base_addr +
+                                           FT1000_REG_SUP_IMASK);
                                if (tempword == 0) {
                                        /*
-                                        * Let's check if ASIC reads are still ok by reading the Mask register
-                                        * which is never zero at this point of the code.
+                                        * This indicates that we can not
+                                        * communicate with the ASIC
                                         */
-                                       tempword =
-                                               inw(dev->base_addr +
-                                                   FT1000_REG_SUP_IMASK);
-                                       if (tempword == 0) {
-                                               /* This indicates that we can not communicate with the ASIC */
-                                               info->DrvErrNum =
-                                                       FIFO_FLUSH_BADCNT;
-                                       } else {
-                                               /* Let's assume that we really flush the FIFO */
-                                               pcmcia->PktIntfErr++;
-                                               return;
-                                       }
+                                       info->DrvErrNum = FIFO_FLUSH_BADCNT;
                                } else {
-                                       info->DrvErrNum = FIFO_FLUSH_MAXLIMIT;
+                                       /*
+                                        * Let's assume that we really flush
+                                        * the FIFO
+                                        */
+                                       pcmcia->PktIntfErr++;
+                                       return;
                                }
-                               return;
+                       } else {
+                               info->DrvErrNum = FIFO_FLUSH_MAXLIMIT;
                        }
-                       tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
-               } while ((tempword & 0x03) != 0x03);
-               if (info->AsicID == ELECTRABUZZ_ID) {
-                       i++;
-                       pr_debug("Flushing FIFO complete = %x\n", tempword);
-                       /* Flush last word in FIFO. */
-                       tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
-                       /* Update FIFO counter for DSP */
-                       i = i * 2;
-                       pr_debug("Flush Data byte count to dsp = %d\n", i);
-                       info->fifo_cnt += i;
-                       ft1000_write_dpram(dev, FT1000_FIFO_LEN,
-                                          info->fifo_cnt);
-               } else {
-                       pr_debug("Flushing FIFO complete = %x\n", tempword);
-                       /* Flush last word in FIFO */
-                       templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
-                       tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
-                       pr_debug("FT1000_REG_SUP_STAT = 0x%x\n", tempword);
-                       tempword = inw(dev->base_addr + FT1000_REG_MAG_DFSR);
-                       pr_debug("FT1000_REG_MAG_DFSR = 0x%x\n", tempword);
+                       return;
                }
-               if (DrvErrNum)
-                       pcmcia->PktIntfErr++;
+               tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
+       } while ((tempword & 0x03) != 0x03);
+       if (info->AsicID == ELECTRABUZZ_ID) {
+               i++;
+               pr_debug("Flushing FIFO complete = %x\n", tempword);
+               /* Flush last word in FIFO. */
+               tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
+               /* Update FIFO counter for DSP */
+               i = i * 2;
+               pr_debug("Flush Data byte count to dsp = %d\n", i);
+               info->fifo_cnt += i;
+               ft1000_write_dpram(dev, FT1000_FIFO_LEN,
+                                  info->fifo_cnt);
+       } else {
+               pr_debug("Flushing FIFO complete = %x\n", tempword);
+               /* Flush last word in FIFO */
+               templong = inl(dev->base_addr + FT1000_REG_MAG_DFR);
+               tempword = inw(dev->base_addr + FT1000_REG_SUP_STAT);
+               pr_debug("FT1000_REG_SUP_STAT = 0x%x\n", tempword);
+               tempword = inw(dev->base_addr + FT1000_REG_MAG_DFSR);
+               pr_debug("FT1000_REG_MAG_DFSR = 0x%x\n", tempword);
        }
+       if (DrvErrNum)
+               pcmcia->PktIntfErr++;
 }
 
 /*---------------------------------------------------------------------------
@@ -1552,7 +1453,6 @@ static int ft1000_copy_up_pkt(struct net_device *dev)
        skb = dev_alloc_skb(len + 12 + 2);
 
        if (skb == NULL) {
-               pr_debug("No Network buffers available\n");
                /* Read High word to complete 32 bit access */
                if (info->AsicID == MAGNEMITE_ID)
                        tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH);
@@ -1673,7 +1573,8 @@ static int ft1000_copy_up_pkt(struct net_device *dev)
        info->stats.rx_bytes += (len + 12);
 
        if (info->AsicID == ELECTRABUZZ_ID) {
-               /* track how many bytes have been read from FIFO - round up to 16 bit word */
+               /* track how many bytes have been read from FIFO - round up to
+                * 16 bit word */
                tempword = len + 16;
                if (tempword & 0x01)
                        tempword++;
@@ -1737,9 +1638,11 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len)
        else
                pseudo.blk.length = ntohs(len);
 
-       pseudo.blk.source = DSPID;      /* Need to swap to get in correct order */
+       pseudo.blk.source = DSPID;      /* Need to swap to get in correct
+                                          order */
        pseudo.blk.destination = HOSTID;
-       pseudo.blk.portdest = NETWORKID;        /* Need to swap to get in correct order */
+       pseudo.blk.portdest = NETWORKID;        /* Need to swap to get in
+                                                  correct order */
        pseudo.blk.portsrc = DSPAIRID;
        pseudo.blk.sh_str_id = 0;
        pseudo.blk.control = 0;
@@ -1843,7 +1746,8 @@ static int ft1000_open(struct net_device *dev)
 {
        ft1000_reset_card(dev);
 
-       /* schedule ft1000_hbchk to perform periodic heartbeat checks on DSP and ASIC */
+       /* schedule ft1000_hbchk to perform periodic heartbeat checks on DSP
+        * and ASIC */
        init_timer(&poll_timer);
        poll_timer.expires = jiffies + (2 * HZ);
        poll_timer.data = (u_long)dev;
@@ -1928,7 +1832,8 @@ static irqreturn_t ft1000_interrupt(int irq, void *dev_id)
        /* Read interrupt type */
        inttype = ft1000_read_reg(dev, FT1000_REG_SUP_ISR);
 
-       /* Make sure we process all interrupt before leaving the ISR due to the edge trigger interrupt type */
+       /* Make sure we process all interrupt before leaving the ISR due to the
+        * edge trigger interrupt type */
        while (inttype) {
                if (inttype & ISR_DOORBELL_PEND)
                        ft1000_parse_dpram_msg(dev);
@@ -1938,21 +1843,18 @@ static irqreturn_t ft1000_interrupt(int irq, void *dev_id)
 
                        cnt = 0;
                        do {
-                               /* Check if we have packets in the Downlink FIFO */
+                               /* Check if we have packets in the Downlink
+                                * FIFO */
                                if (info->AsicID == ELECTRABUZZ_ID) {
-                                       tempword =
-                                               ft1000_read_reg(dev,
-                                                               FT1000_REG_DFIFO_STAT);
+                                       tempword = ft1000_read_reg(dev,
+                                                       FT1000_REG_DFIFO_STAT);
                                } else {
-                                       tempword =
-                                               ft1000_read_reg(dev,
-                                                               FT1000_REG_MAG_DFSR);
+                                       tempword = ft1000_read_reg(dev,
+                                                       FT1000_REG_MAG_DFSR);
                                }
-                               if (tempword & 0x1f) {
-                                       ft1000_copy_up_pkt(dev);
-                               } else {
+                               if (!(tempword & 0x1f))
                                        break;
-                               }
+                               ft1000_copy_up_pkt(dev);
                                cnt++;
                        } while (cnt < MAX_RCV_LOOP);
 
@@ -1975,6 +1877,7 @@ void stop_ft1000_card(struct net_device *dev)
 {
        struct ft1000_info *info = netdev_priv(dev);
        struct prov_record *ptr;
+       struct prov_record *tmp;
        /* int cnt; */
 
        info->CardReady = 0;
@@ -1983,8 +1886,7 @@ void stop_ft1000_card(struct net_device *dev)
        ft1000_disable_interrupts(dev);
 
        /* Make sure we free any memory reserve for provisioning */
-       while (list_empty(&info->prov_list) == 0) {
-               ptr = list_entry(info->prov_list.next, struct prov_record, list);
+       list_for_each_entry_safe(ptr, tmp, &info->prov_list, list) {
                list_del(&ptr->list);
                kfree(ptr->pprov_data);
                kfree(ptr);
@@ -2008,6 +1910,7 @@ static void ft1000_get_drvinfo(struct net_device *dev,
                               struct ethtool_drvinfo *info)
 {
        struct ft1000_info *ft_info;
+
        ft_info = netdev_priv(dev);
 
        strlcpy(info->driver, "ft1000", sizeof(info->driver));
@@ -2038,8 +1941,7 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
        struct ft1000_pcmcia *pcmcia;
        struct net_device *dev;
 
-       static const struct net_device_ops ft1000ops =          /* Slavius 21.10.2009 due to kernel changes */
-               {
+       static const struct net_device_ops ft1000ops = {
                        .ndo_open = &ft1000_open,
                        .ndo_stop = &ft1000_close,
                        .ndo_start_xmit = &ft1000_start_xmit,
@@ -2102,7 +2004,7 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
        /* dev->open = &ft1000_open; */
        /* dev->stop = &ft1000_close; */
 
-       dev->netdev_ops = &ft1000ops;           /* Slavius 21.10.2009 due to kernel changes */
+       dev->netdev_ops = &ft1000ops;
 
        pr_debug("device name = %s\n", dev->name);
 
@@ -2113,7 +2015,8 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
                goto err_dev;
        }
 
-       if (request_irq(dev->irq, ft1000_interrupt, IRQF_SHARED, dev->name, dev)) {
+       if (request_irq(dev->irq, ft1000_interrupt, IRQF_SHARED, dev->name,
+                       dev)) {
                netdev_err(dev, "Could not request_irq\n");
                goto err_dev;
        }
@@ -2123,7 +2026,7 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
                goto err_irq;
        }
 
-       if (register_netdev(dev) != 0) {
+       if (register_netdev(dev)) {
                pr_debug("Could not register netdev\n");
                goto err_reg;
        }
@@ -2131,13 +2034,15 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
        info->AsicID = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
        if (info->AsicID == ELECTRABUZZ_ID) {
                pr_debug("ELECTRABUZZ ASIC\n");
-               if (request_firmware(&fw_entry, "ft1000.img", &link->dev) != 0) {
+               if (request_firmware(&fw_entry, "ft1000.img",
+                                    &link->dev) != 0) {
                        pr_info("Could not open ft1000.img\n");
                        goto err_unreg;
                }
        } else {
                pr_debug("MAGNEMITE ASIC\n");
-               if (request_firmware(&fw_entry, "ft2000.img", &link->dev) != 0) {
+               if (request_firmware(&fw_entry, "ft2000.img",
+                                    &link->dev) != 0) {
                        pr_info("Could not open ft2000.img\n");
                        goto err_unreg;
                }
index c8d2782299403349a22f8be34cbe54178712f5b5..2d758fb26eac3c818f5e6adb91f08ec9171a7487 100644 (file)
@@ -190,7 +190,7 @@ int ft1000_create_dev(struct ft1000_usb *dev)
        tmp->dent = dir;
        tmp->file = file;
        tmp->int_number = dev->CardNumber;
-       list_add(&(tmp->list), &(dev->nodes.list));
+       list_add(&tmp->list, &dev->nodes.list);
 
        pr_debug("registered debugfs directory \"%s\"\n", dev->DeviceName);
 
@@ -301,7 +301,7 @@ static int ft1000_open(struct inode *inode, struct file *file)
        struct ft1000_usb *dev = (struct ft1000_usb *)inode->i_private;
        int i, num;
 
-       num = (MINOR(inode->i_rdev) & 0xf);
+       num = MINOR(inode->i_rdev) & 0xf;
        pr_debug("minor number=%d\n", num);
 
        info = file->private_data = netdev_priv(dev->net);
@@ -317,9 +317,8 @@ static int ft1000_open(struct inode *inode, struct file *file)
 
        /* Search for available application info block */
        for (i = 0; i < MAX_NUM_APP; i++) {
-               if ((dev->app_info[i].fileobject == NULL)) {
+               if ((dev->app_info[i].fileobject == NULL))
                        break;
-               }
        }
 
        /* Fail due to lack of application info block */
@@ -478,14 +477,14 @@ static long ft1000_ioctl(struct file *file, unsigned int command,
                /* Connect Message */
                pr_debug("IOCTL_FT1000_CONNECT\n");
                ConnectionMsg[79] = 0xfc;
-               result = card_send_command(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
+               result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
 
                break;
        case IOCTL_DISCONNECT:
                /* Disconnect Message */
                pr_debug("IOCTL_FT1000_DISCONNECT\n");
                ConnectionMsg[79] = 0xfd;
-               result = card_send_command(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
+               result = card_send_command(ft1000dev, ConnectionMsg, 0x4c);
                break;
        case IOCTL_GET_DSP_STAT_CMD:
                /* pr_debug("IOCTL_FT1000_GET_DSP_STAT\n"); */
@@ -545,7 +544,7 @@ static long ft1000_ioctl(struct file *file, unsigned int command,
                if (ft1000dev->fProvComplete == 0)
                        return -EACCES;
 
-               ft1000dev->fAppMsgPend = 1;
+               ft1000dev->fAppMsgPend = true;
 
                if (info->CardReady) {
 
@@ -575,9 +574,8 @@ static long ft1000_ioctl(struct file *file, unsigned int command,
                        } else {
                                /* Check if this message came from a registered application */
                                for (i = 0; i < MAX_NUM_APP; i++) {
-                                       if (ft1000dev->app_info[i].fileobject == &file->f_owner) {
+                                       if (ft1000dev->app_info[i].fileobject == &file->f_owner)
                                                break;
-                                       }
                                }
                                if (i == MAX_NUM_APP) {
                                        pr_debug("No matching application fileobject\n");
@@ -629,9 +627,8 @@ static long ft1000_ioctl(struct file *file, unsigned int command,
                                                pmsg = (u16 *)&dpram_data->pseudohdr;
                                                ppseudo_hdr = (struct pseudo_hdr *)pmsg;
                                                total_len = msgsz+2;
-                                               if (total_len & 0x1) {
+                                               if (total_len & 0x1)
                                                        total_len++;
-                                               }
 
                                                /* Insert slow queue sequence number */
                                                ppseudo_hdr->seq_num = info->squeseqnum++;
@@ -645,7 +642,7 @@ static long ft1000_ioctl(struct file *file, unsigned int command,
                                                }
                                                pmsg++;
                                                ppseudo_hdr = (struct pseudo_hdr *)pmsg;
-                                               result = card_send_command(ft1000dev, (unsigned short *)dpram_data, total_len+2);
+                                               result = card_send_command(ft1000dev, dpram_data, total_len+2);
 
 
                                                ft1000dev->app_info[app_index].nTxMsg++;
@@ -722,7 +719,7 @@ static long ft1000_ioctl(struct file *file, unsigned int command,
                result = -ENOTTY;
                break;
        }
-       ft1000dev->fAppMsgPend = 0;
+       ft1000dev->fAppMsgPend = false;
        return result;
 }
 
@@ -745,6 +742,7 @@ static int ft1000_release(struct inode *inode, struct file *file)
        struct ft1000_usb *ft1000dev;
        int i;
        struct dpram_blk *pdpram_blk;
+       struct dpram_blk *tmp;
 
        dev = file->private_data;
        info = netdev_priv(dev);
@@ -766,9 +764,8 @@ static int ft1000_release(struct inode *inode, struct file *file)
        if (i == MAX_NUM_APP)
                return 0;
 
-       while (list_empty(&ft1000dev->app_info[i].app_sqlist) == 0) {
+       list_for_each_entry_safe(pdpram_blk, tmp, &ft1000dev->app_info[i].app_sqlist, list) {
                pr_debug("Remove and free memory queue up on slow queue\n");
-               pdpram_blk = list_entry(ft1000dev->app_info[i].app_sqlist.next, struct dpram_blk, list);
                list_del(&pdpram_blk->list);
                ft1000_free_buffer(pdpram_blk, &freercvpool);
        }
index e8126325877b4bc1616fcbedc10d40177b3523fe..5def347beb082df3bd442e9f8c9a47713c47feaf 100644 (file)
@@ -230,7 +230,7 @@ static u16 get_handshake_usb(struct ft1000_usb *ft1000dev, u16 expected_value)
        while (loopcnt < 100) {
                if (ft1000dev->usbboot == 2) {
                        status = ft1000_read_dpram32(ft1000dev, 0,
-                                                    (u8 *)&(ft1000dev->tempbuf[0]), 64);
+                                                    (u8 *)&ft1000dev->tempbuf[0], 64);
                        for (temp = 0; temp < 16; temp++) {
                                pr_debug("tempbuf %d = 0x%x\n",
                                         temp, ft1000dev->tempbuf[temp]);
@@ -368,8 +368,8 @@ static u16 hdr_checksum(struct pseudo_hdr *pHdr)
        u16   chksum;
 
 
-       chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
-                   usPtr[4]) ^ usPtr[5]) ^ usPtr[6]);
+       chksum = (((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
+                   usPtr[4]) ^ usPtr[5]) ^ usPtr[6];
 
        return chksum;
 }
@@ -538,7 +538,7 @@ static int write_blk_fifo(struct ft1000_usb *ft1000dev, u16 **pUsFile,
                          usb_sndbulkpipe(ft1000dev->dev,
                                          ft1000dev->bulk_out_endpointAddr),
                          ft1000dev->tx_buf, byte_length, usb_dnld_complete,
-                         (void *)ft1000dev);
+                         ft1000dev);
 
        usb_submit_urb(ft1000dev->tx_urb, GFP_ATOMIC);
 
@@ -704,7 +704,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
                                case REQUEST_CODE_SEGMENT:
                                        status = request_code_segment(ft1000dev,
                                                                      &s_file, &c_file,
-                                                                     (const u8 *)boot_end,
+                                                                     boot_end,
                                                                      true);
                                        break;
                                default:
@@ -799,7 +799,7 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
 
                                        status = request_code_segment(ft1000dev,
                                                                      &s_file, &c_file,
-                                                                     (const u8 *)code_end,
+                                                                     code_end,
                                                                      false);
 
                                        break;
@@ -971,11 +971,11 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
 
                                /* Get buffer for provisioning data */
                                pbuffer =
-                                       kmalloc((pseudo_header_len +
-                                                sizeof(struct pseudo_hdr)),
+                                       kmalloc(pseudo_header_len +
+                                                sizeof(struct pseudo_hdr),
                                                GFP_ATOMIC);
                                if (pbuffer) {
-                                       memcpy(pbuffer, (void *)c_file,
+                                       memcpy(pbuffer, c_file,
                                               (u32) (pseudo_header_len +
                                                      sizeof(struct
                                                             pseudo_hdr)));
index f0ac438384617f81b9d0d067ef64a74b03808f38..e6fb066e0dd23c77acde3c677753a26a7763c13c 100644 (file)
@@ -339,7 +339,7 @@ int card_send_command(struct ft1000_usb *ft1000dev, void *ptempbuffer,
        commandbuf = kmalloc(size + 2, GFP_KERNEL);
        if (!commandbuf)
                return -ENOMEM;
-       memcpy((void *)commandbuf + 2, (void *)ptempbuffer, size);
+       memcpy((void *)commandbuf + 2, ptempbuffer, size);
 
        if (temp & 0x0100)
                usleep_range(900, 1100);
@@ -429,7 +429,7 @@ static void ft1000_reset_asic(struct net_device *dev)
        /* Let's use the register provided by the Magnemite ASIC to reset the
         * ASIC and DSP.
         */
-       ft1000_write_register(ft1000dev, (DSP_RESET_BIT | ASIC_RESET_BIT),
+       ft1000_write_register(ft1000dev, DSP_RESET_BIT | ASIC_RESET_BIT,
                              FT1000_REG_RESET);
 
        mdelay(1);
@@ -451,16 +451,15 @@ static int ft1000_reset_card(struct net_device *dev)
        struct ft1000_usb *ft1000dev = info->priv;
        u16 tempword;
        struct prov_record *ptr;
+       struct prov_record *tmp;
 
        ft1000dev->fCondResetPend = true;
        info->CardReady = 0;
        ft1000dev->fProvComplete = false;
 
        /* Make sure we free any memory reserve for provisioning */
-       while (list_empty(&info->prov_list) == 0) {
+       list_for_each_entry_safe(ptr, tmp, &info->prov_list, list) {
                pr_debug("deleting provisioning record\n");
-               ptr =
-                       list_entry(info->prov_list.next, struct prov_record, list);
                list_del(&ptr->list);
                kfree(ptr->pprov_data);
                kfree(ptr);
@@ -542,7 +541,7 @@ static int ft1000_copy_down_pkt(struct net_device *netdev, u8 *packet, u16 len)
                hdr.portdest ^ hdr.portsrc ^ hdr.sh_str_id ^ hdr.control;
 
        memcpy(&pFt1000Dev->tx_buf[0], &hdr, sizeof(hdr));
-       memcpy(&(pFt1000Dev->tx_buf[sizeof(struct pseudo_hdr)]), packet, len);
+       memcpy(&pFt1000Dev->tx_buf[sizeof(struct pseudo_hdr)], packet, len);
 
        netif_stop_queue(netdev);
 
@@ -551,7 +550,7 @@ static int ft1000_copy_down_pkt(struct net_device *netdev, u8 *packet, u16 len)
                          usb_sndbulkpipe(pFt1000Dev->dev,
                                          pFt1000Dev->bulk_out_endpointAddr),
                          pFt1000Dev->tx_buf, count,
-                         ft1000_usb_transmit_complete, (void *)pFt1000Dev);
+                         ft1000_usb_transmit_complete, pFt1000Dev);
 
        t = (u8 *)pFt1000Dev->tx_urb->transfer_buffer;
 
@@ -606,7 +605,7 @@ static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
                goto err;
        }
 
-       ft1000_copy_down_pkt(dev, (pdata + ENET_HEADER_SIZE - 2),
+       ft1000_copy_down_pkt(dev, pdata + ENET_HEADER_SIZE - 2,
                             skb->len - ENET_HEADER_SIZE + 2);
 
 err:
@@ -1558,19 +1557,19 @@ int ft1000_poll(void *dev_id)
                                /* Reset ASIC and DSP */
                                status = ft1000_read_dpram16(dev,
                                                             FT1000_MAG_DSP_TIMER0,
-                                                            (u8 *)&(info->DSP_TIME[0]),
+                                                            (u8 *)&info->DSP_TIME[0],
                                                             FT1000_MAG_DSP_TIMER0_INDX);
                                status = ft1000_read_dpram16(dev,
                                                             FT1000_MAG_DSP_TIMER1,
-                                                            (u8 *)&(info->DSP_TIME[1]),
+                                                            (u8 *)&info->DSP_TIME[1],
                                                             FT1000_MAG_DSP_TIMER1_INDX);
                                status = ft1000_read_dpram16(dev,
                                                             FT1000_MAG_DSP_TIMER2,
-                                                            (u8 *)&(info->DSP_TIME[2]),
+                                                            (u8 *)&info->DSP_TIME[2],
                                                             FT1000_MAG_DSP_TIMER2_INDX);
                                status = ft1000_read_dpram16(dev,
                                                             FT1000_MAG_DSP_TIMER3,
-                                                            (u8 *)&(info->DSP_TIME[3]),
+                                                            (u8 *)&info->DSP_TIME[3],
                                                             FT1000_MAG_DSP_TIMER3_INDX);
                                info->CardReady = 0;
                                info->DrvErrNum = DSP_CONDRESET_INFO;
index a6b55f42c07c177ee29aa69fd2a09cea52c3a01d..3b303b6b1b272da247f06533d3242c9e59ef5115 100644 (file)
@@ -136,7 +136,7 @@ static int ft1000_probe(struct usb_interface *interface,
 
        ret = request_firmware(&dsp_fw, "ft3000.img", &dev->dev);
        if (ret < 0) {
-               pr_err("Error request_firmware()\n");
+               dev_err(interface->usb_dev, "Error request_firmware()\n");
                goto err_fw;
        }
 
@@ -164,7 +164,8 @@ static int ft1000_probe(struct usb_interface *interface,
        pr_debug("pft1000info=%p\n", pft1000info);
        ret = dsp_reload(ft1000dev);
        if (ret) {
-               pr_err("Problem with DSP image loading\n");
+               dev_err(interface->usb_dev,
+                       "Problem with DSP image loading\n");
                goto err_load;
        }
 
index 73deae3cd9ebf6178c73c6309aa7ca125e0d2184..fdb2418c5f888b070111ab38a98f7898e9b060e6 100644 (file)
@@ -1186,7 +1186,7 @@ static void fwtty_unthrottle(struct tty_struct *tty)
 {
        struct fwtty_port *port = tty->driver_data;
 
-       fwtty_dbg(port, "CRTSCTS: %d\n", (C_CRTSCTS(tty) != 0));
+       fwtty_dbg(port, "CRTSCTS: %d\n", C_CRTSCTS(tty) != 0);
 
        fwtty_profile_fifo(port, port->stats.unthrottle);
 
index 7c4a77bb94aa991913e35f1f49f54aa425a60af8..a8d2cffb411cb8bf7460dfb2b6537343ba10e37c 100644 (file)
@@ -889,7 +889,7 @@ int register_lte_device(struct phy_dev *phy_dev,
                /* Allocate netdev */
                net = alloc_netdev(sizeof(struct nic), pdn_dev_name,
                                   NET_NAME_UNKNOWN, ether_setup);
-               if (net == NULL) {
+               if (!net) {
                        pr_err("alloc_netdev failed\n");
                        ret = -ENOMEM;
                        goto err;
index d1ab996b3305af1a9c4d45a2343184e3bafe9503..8199b0a697bb5f8b672aabad8f9685c8c51a8f5e 100644 (file)
@@ -270,7 +270,7 @@ static void gdm_mux_rcv_complete(struct urb *urb)
 
        if (urb->status) {
                if (mux_dev->usb_state == PM_NORMAL)
-                       pr_err("%s: urb status error %d\n",
+                       dev_err(&urb->dev->dev, "%s: urb status error %d\n",
                               __func__, urb->status);
                put_rx_struct(rx, r);
        } else {
@@ -342,7 +342,7 @@ static void gdm_mux_send_complete(struct urb *urb)
        struct mux_tx *t = urb->context;
 
        if (urb->status == -ECONNRESET) {
-               pr_info("CONNRESET\n");
+               dev_info(&urb->dev->dev, "CONNRESET\n");
                free_mux_tx(t);
                return;
        }
@@ -608,7 +608,7 @@ static int gdm_mux_suspend(struct usb_interface *intf, pm_message_t pm_msg)
        rx = &mux_dev->rx;
 
        if (mux_dev->usb_state != PM_NORMAL) {
-               pr_err("usb suspend - invalid state\n");
+               dev_err(intf->usb_dev, "usb suspend - invalid state\n");
                return -1;
        }
 
@@ -637,7 +637,7 @@ static int gdm_mux_resume(struct usb_interface *intf)
        mux_dev = tty_dev->priv_dev;
 
        if (mux_dev->usb_state != PM_SUSPEND) {
-               pr_err("usb resume - invalid state\n");
+               dev_err(intf->usb_dev, "usb resume - invalid state\n");
                return -1;
        }
 
index d2a3b350ba6d10ca77728c7cb5eb8c792f6612e2..ed1a12f504e2183e459bc3e43e171255caaf9c38 100644 (file)
@@ -480,7 +480,7 @@ static void gdm_usb_rcv_complete(struct urb *urb)
                spin_unlock_irqrestore(&rx->to_host_lock, flags);
        } else {
                if (urb->status && udev->usb_state == PM_NORMAL)
-                       pr_err("%s: urb status error %d\n",
+                       dev_err(&urb->dev->dev, "%s: urb status error %d\n",
                               __func__, urb->status);
 
                put_rx_struct(rx, r);
@@ -557,7 +557,7 @@ static void gdm_usb_send_complete(struct urb *urb)
        unsigned long flags;
 
        if (urb->status == -ECONNRESET) {
-               pr_info("CONNRESET\n");
+               dev_info(&urb->dev->dev, "CONNRESET\n");
                return;
        }
 
@@ -590,7 +590,8 @@ static int send_tx_packet(struct usb_device *usbdev, struct usb_tx *t, u32 len)
        ret = usb_submit_urb(t->urb, GFP_ATOMIC);
 
        if (ret)
-               pr_err("usb_submit_urb failed: %d\n", ret);
+               dev_err(&usbdev->dev, "usb_submit_urb failed: %d\n",
+                       ret);
 
        usb_mark_last_busy(usbdev);
 
@@ -848,7 +849,7 @@ static int gdm_usb_probe(struct usb_interface *intf,
        udev->usbdev = usbdev;
        ret = init_usb(udev);
        if (ret < 0) {
-               pr_err("init_usb func failed\n");
+               dev_err(intf->usb_dev, "init_usb func failed\n");
                goto err_init_usb;
        }
        udev->intf = intf;
@@ -867,7 +868,7 @@ static int gdm_usb_probe(struct usb_interface *intf,
 
        ret = request_mac_address(udev);
        if (ret < 0) {
-               pr_err("request Mac address failed\n");
+               dev_err(intf->usb_dev, "request Mac address failed\n");
                goto err_mac_address;
        }
 
@@ -928,7 +929,7 @@ static int gdm_usb_suspend(struct usb_interface *intf, pm_message_t pm_msg)
        udev = phy_dev->priv_dev;
        rx = &udev->rx;
        if (udev->usb_state != PM_NORMAL) {
-               pr_err("usb suspend - invalid state\n");
+               dev_err(intf->usb_dev, "usb suspend - invalid state\n");
                return -1;
        }
 
@@ -961,7 +962,7 @@ static int gdm_usb_resume(struct usb_interface *intf)
        rx = &udev->rx;
 
        if (udev->usb_state != PM_SUSPEND) {
-               pr_err("usb resume - invalid state\n");
+               dev_err(intf->usb_dev, "usb resume - invalid state\n");
                return -1;
        }
        udev->usb_state = PM_NORMAL;
index af24c57b82322a8cac7a1712125fe40a8a0ea51e..96bf2bf87ff4b657a8ba9770e553543a74878378 100644 (file)
@@ -54,8 +54,7 @@ static void *alloc_qos_entry(void)
        }
        spin_unlock_irqrestore(&qos_free_list.lock, flags);
 
-       entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
-       return entry;
+       return kmalloc(sizeof(*entry), GFP_ATOMIC);
 }
 
 static void free_qos_entry(void *entry)
index 7a0a0f2214180dc2da684e3df31f6ba480bbc346..a5fd0794842ee0a9af21577a62b6b2f5ddc83e86 100644 (file)
@@ -223,8 +223,7 @@ static void send_sdio_pkt(struct sdio_func *func, u8 *data, int len)
                if (ret < 0) {
                        if (ret != -ENOMEDIUM)
                                dev_err(&func->dev,
-                                       "gdmwms: %s error: ret = %d\n",
-                                       __func__, ret);
+                                       "gdmwms:  error: ret = %d\n", ret);
                        goto end_io;
                }
        }
@@ -237,8 +236,7 @@ static void send_sdio_pkt(struct sdio_func *func, u8 *data, int len)
                if (ret < 0) {
                        if (ret != -ENOMEDIUM)
                                dev_err(&func->dev,
-                                       "gdmwms: %s error: ret = %d\n",
-                                       __func__, ret);
+                                       "gdmwms:  error: ret = %d\n", ret);
                        goto end_io;
                }
        }
index 9cab54bfa6f4d6f21f42dd257743d546d6d5baa4..61d168e820110d6ddacdad0481a7672f3a831d65 100644 (file)
@@ -129,11 +129,11 @@ static void __gdm_wimax_event_send(struct work_struct *work)
        int idx;
        unsigned long flags;
        struct evt_entry *e;
+       struct evt_entry *tmp;
 
        spin_lock_irqsave(&wm_event.evt_lock, flags);
 
-       while (!list_empty(&wm_event.evtq)) {
-               e = list_entry(wm_event.evtq.next, struct evt_entry, list);
+       list_for_each_entry_safe(e, tmp, &wm_event.evtq, list) {
                spin_unlock_irqrestore(&wm_event.evt_lock, flags);
 
                if (sscanf(e->dev->name, "wm%d", &idx) == 1)
@@ -749,7 +749,7 @@ int register_wimax_device(struct phy_dev *phy_dev, struct device *pdev)
        dev = alloc_netdev(sizeof(*nic), "wm%d", NET_NAME_UNKNOWN,
                           ether_setup);
 
-       if (dev == NULL) {
+       if (!dev) {
                pr_err("alloc_etherdev failed\n");
                return -ENOMEM;
        }
index f200359c44439d5cd4d00decdcd50afbf31d5dad..702ae04df91227603426e8d7a70e3ab45a8ec880 100644 (file)
@@ -40,12 +40,12 @@ struct goldfish_audio {
        spinlock_t lock;
        wait_queue_head_t wait;
 
-       char __iomem *buffer_virt;      /* combined buffer virtual address */
+       char *buffer_virt;              /* combined buffer virtual address */
        unsigned long buffer_phys;      /* combined buffer physical address */
 
-       char __iomem *write_buffer1;    /* write buffer 1 virtual address */
-       char __iomem *write_buffer2;    /* write buffer 2 virtual address */
-       char __iomem *read_buffer;      /* read buffer virtual address */
+       char *write_buffer1;            /* write buffer 1 virtual address */
+       char *write_buffer2;            /* write buffer 2 virtual address */
+       char *read_buffer;              /* read buffer virtual address */
        int buffer_status;
        int read_supported;         /* true if we have audio input support */
 };
@@ -125,8 +125,8 @@ static ssize_t goldfish_audio_read(struct file *fp, char __user *buf,
                length = (count > READ_BUFFER_SIZE ? READ_BUFFER_SIZE : count);
                AUDIO_WRITE(data, AUDIO_START_READ, length);
 
-               wait_event_interruptible(data->wait, (data->buffer_status &
-                                        AUDIO_INT_READ_BUFFER_FULL));
+               wait_event_interruptible(data->wait, data->buffer_status &
+                                        AUDIO_INT_READ_BUFFER_FULL);
 
                length = AUDIO_READ(data, AUDIO_READ_BUFFER_AVAILABLE);
 
@@ -147,16 +147,16 @@ static ssize_t goldfish_audio_write(struct file *fp, const char __user *buf,
        struct goldfish_audio *data = fp->private_data;
        unsigned long irq_flags;
        ssize_t result = 0;
-       char __iomem *kbuf;
+       char *kbuf;
 
        while (count > 0) {
                ssize_t copy = count;
 
                if (copy > WRITE_BUFFER_SIZE)
                        copy = WRITE_BUFFER_SIZE;
-               wait_event_interruptible(data->wait, (data->buffer_status &
+               wait_event_interruptible(data->wait, data->buffer_status &
                                        (AUDIO_INT_WRITE_BUFFER_1_EMPTY |
-                                       AUDIO_INT_WRITE_BUFFER_2_EMPTY)));
+                                       AUDIO_INT_WRITE_BUFFER_2_EMPTY));
 
                if ((data->buffer_status & AUDIO_INT_WRITE_BUFFER_1_EMPTY) != 0)
                        kbuf = data->write_buffer1;
@@ -273,7 +273,7 @@ static int goldfish_audio_probe(struct platform_device *pdev)
        dma_addr_t buf_addr;
 
        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
-       if (data == NULL)
+       if (!data)
                return -ENOMEM;
        spin_lock_init(&data->lock);
        init_waitqueue_head(&data->wait);
index d68f216a7e77f7c9e51079d628adb2f61d77bc09..213877a2c43039a7a999fb141462ed79159bd0e7 100644 (file)
@@ -330,7 +330,7 @@ static int goldfish_nand_init_device(struct platform_device *pdev,
        mtd->priv = nand;
 
        name = devm_kzalloc(&pdev->dev, name_len + 1, GFP_KERNEL);
-       if (name == NULL)
+       if (!name)
                return -ENOMEM;
        mtd->name = name;
 
@@ -383,7 +383,7 @@ static int goldfish_nand_probe(struct platform_device *pdev)
                return -ENODEV;
 
        base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE);
-       if (base == NULL)
+       if (!base)
                return -ENOMEM;
 
        version = readl(base + NAND_VERSION);
@@ -399,7 +399,7 @@ static int goldfish_nand_probe(struct platform_device *pdev)
 
        nand = devm_kzalloc(&pdev->dev, sizeof(*nand) +
                                sizeof(struct mtd_info) * num_dev, GFP_KERNEL);
-       if (nand == NULL)
+       if (!nand)
                return -ENOMEM;
 
        mutex_init(&nand->lock);
index 6da72858d28c87c89ff9633f14aa3063819ce7c7..a3a10f9a2a2b684c33481a1e8582649041f6f23f 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/device.h>
 #include <linux/string.h>
index 7aa0339aea056f3ec723f4ef3baa63b80da21f4e..43e357eeeb672a5325538a1f0c25bf43c7dacaf0 100644 (file)
@@ -69,7 +69,8 @@ static ssize_t i2o_bus_store_scan(struct device *d,
        struct i2o_device *i2o_dev = to_i2o_device(d);
        int rc;
 
-       if ((rc = i2o_bus_scan(i2o_dev)))
+       rc = i2o_bus_scan(i2o_dev);
+       if (rc)
                osm_warn("bus scan failed %d\n", rc);
 
        return count;
index 519f52f9f68819ade9816ec6e89610fbe2adb826..45091ac66154b27c614443f4381f2a3d39d25f9d 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/namei.h>
 #include <linux/fs.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define OSM_NAME       "config-osm"
 #define OSM_VERSION    "1.323"
index 7a16114ed8ea39cf70c9dd8e241e5b8e8babf824..12b783b2a86c8f37afbf8618ddbea2b4bbfbffee 100644 (file)
@@ -5,7 +5,7 @@
 
 static void i2o_report_util_cmd(u8 cmd);
 static void i2o_report_exec_cmd(u8 cmd);
-static void i2o_report_fail_status(u8 req_status, u32 * msg);
+static void i2o_report_fail_status(u8 req_status, u32 *msg);
 static void i2o_report_common_status(u8 req_status);
 static void i2o_report_common_dsc(u16 detailed_status);
 
@@ -22,7 +22,7 @@ void i2o_report_status(const char *severity, const char *str,
        u16 detailed_status = msg[4] & 0xFFFF;
 
        if (cmd == I2O_CMD_UTIL_EVT_REGISTER)
-               return;         // No status in this reply
+               return;         /* No status in this reply */
 
        printk("%s%s: ", severity, str);
 
@@ -54,6 +54,7 @@ void i2o_dump_message(struct i2o_message *m)
 #ifdef DEBUG
        u32 *msg = (u32 *) m;
        int i;
+
        printk(KERN_INFO "Dumping I2O message size %d @ %p\n",
               msg[0] >> 16 & 0xffff, msg);
        for (i = 0; i < ((msg[0] >> 16) & 0xffff); i++)
@@ -66,7 +67,7 @@ void i2o_dump_message(struct i2o_message *m)
  * Following fail status are common to all classes.
  * The preserved message must be handled in the reply handler.
  */
-static void i2o_report_fail_status(u8 req_status, u32 * msg)
+static void i2o_report_fail_status(u8 req_status, u32 *msg)
 {
        static char *FAIL_STATUS[] = {
                "0x80",         /* not used */
index 2af22553dd4e8fdbf7c4bde3bcceabb5ed23e44c..e47496cb0ac21864afcfcf9476a848a2ee292453 100644 (file)
@@ -565,10 +565,8 @@ int i2o_parm_table_get(struct i2o_device *dev, int oper, int group,
                size += 4 - size % 4;
 
        opblk = kmalloc(size, GFP_KERNEL);
-       if (opblk == NULL) {
-               printk(KERN_ERR "i2o: no memory for query buffer.\n");
+       if (opblk == NULL)
                return -ENOMEM;
-       }
 
        opblk[0] = 1;           /* operation count */
        opblk[1] = 0;           /* pad */
index 111c3edde035d5bee7ca8e5b659a126c06e87ff0..06119bb3eb5fb56d62afdb64e5503254433a0076 100644 (file)
@@ -102,8 +102,7 @@ int i2o_driver_register(struct i2o_driver *drv)
 
        for (i = 0; i2o_drivers[i]; i++)
                if (i >= i2o_max_drivers) {
-                       osm_err("too many drivers registered, increase "
-                               "max_drivers\n");
+                       osm_err("too many drivers registered, increase max_drivers\n");
                        spin_unlock_irqrestore(&i2o_drivers_lock, flags);
                        rc = -EFAULT;
                        goto out;
@@ -244,8 +243,8 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
        }
 
        if (unlikely(!drv->reply)) {
-               osm_debug("%s: Reply to driver %s, but no reply function"
-                         " defined!\n", c->name, drv->name);
+               osm_debug("%s: Reply to driver %s, but no reply function defined!\n",
+                       c->name, drv->name);
                return -EIO;
        }
 
index 16d857d5e65541738c1fecb9db03d5cd04084f67..dce16e425a6e5f9bb723832c14ce774d270afe21 100644 (file)
@@ -507,8 +507,8 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
         * to aid in debugging.
         *
         */
-       printk(KERN_WARNING "%s: Unsolicited message reply sent to core!"
-              "Message dumped to syslog\n", c->name);
+       printk(KERN_WARNING "%s: Unsolicited message reply sent to core! Message dumped to syslog\n",
+                       c->name);
        i2o_dump_message(msg);
 
        return -EFAULT;
index 0a13c64ce000b9884132eae097af5c343aa4d9d0..406758f755ee43ba59231b11c2a618e7e27c19a0 100644 (file)
@@ -871,13 +871,13 @@ static int i2o_block_transfer(struct request *req)
 
        return 0;
 
-      context_remove:
+context_remove:
        i2o_cntxt_list_remove(c, req);
 
-      nop_msg:
+nop_msg:
        i2o_msg_nop(c, msg);
 
-      exit:
+exit:
        return rc;
 };
 
@@ -1002,13 +1002,13 @@ static struct i2o_block_device *i2o_block_device_alloc(void)
 
        return dev;
 
-      cleanup_queue:
+cleanup_queue:
        put_disk(gd);
 
-      cleanup_dev:
+cleanup_dev:
        kfree(dev);
 
-      exit:
+exit:
        return ERR_PTR(rc);
 };
 
@@ -1028,7 +1028,7 @@ static int i2o_block_probe(struct device *dev)
        struct i2o_block_device *i2o_blk_dev;
        struct gendisk *gd;
        struct request_queue *queue;
-       static int unit = 0;
+       static int unit;
        int rc;
        u64 size;
        u32 blocksize;
@@ -1115,10 +1115,10 @@ static int i2o_block_probe(struct device *dev)
 
        return 0;
 
-      claim_release:
+claim_release:
        i2o_device_claim_release(i2o_dev);
 
-      exit:
+exit:
        return rc;
 };
 
@@ -1187,16 +1187,16 @@ static int __init i2o_block_init(void)
 
        return 0;
 
-      unregister_blkdev:
+unregister_blkdev:
        unregister_blkdev(I2O_MAJOR, "i2o_block");
 
-      free_mempool:
+free_mempool:
        mempool_destroy(i2o_blk_req_pool.pool);
 
-      free_slab:
+free_slab:
        kmem_cache_destroy(i2o_blk_req_pool.slab);
 
-      exit:
+exit:
        return rc;
 };
 
index 04bd3b6de40188bebf7f083750ed547c38265ec2..cd7ca5eb18ff30e00dfaef9252c476ad966c0a5e 100644 (file)
@@ -34,8 +34,7 @@
 #include <linux/mutex.h>
 #include <linux/compat.h>
 #include <linux/slab.h>
-
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "core.h"
 
@@ -65,7 +64,7 @@ struct i2o_cfg_info {
        struct i2o_cfg_info *next;
 };
 static struct i2o_cfg_info *open_files = NULL;
-static ulong i2o_cfg_info_id = 0;
+static ulong i2o_cfg_info_id;
 
 static int i2o_cfg_getiops(unsigned long arg)
 {
index ad84f3304f3cd3ea2b1863e87e360d06f8a77ced..780fee3224ead8beb1397c626d20de53955aeb87 100644 (file)
@@ -48,9 +48,9 @@
 #include <linux/errno.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
+#include <linux/uaccess.h>
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
 /* Structure used to define /proc entries */
@@ -85,9 +85,8 @@ static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len)
        switch (serialno[0]) {
        case I2O_SNFORMAT_BINARY:       /* Binary */
                seq_printf(seq, "0x");
-               for (i = 0; i < serialno[1]; i++) {
+               for (i = 0; i < serialno[1]; i++)
                        seq_printf(seq, "%02X", serialno[2 + i]);
-               }
                break;
 
        case I2O_SNFORMAT_ASCII:        /* ASCII */
@@ -101,9 +100,8 @@ static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len)
                        seq_printf(seq, "%s", &serialno[2]);
                } else {
                        /* print chars for specified length */
-                       for (i = 0; i < serialno[1]; i++) {
+                       for (i = 0; i < serialno[1]; i++)
                                seq_printf(seq, "%c", serialno[2 + i]);
-                       }
                }
                break;
 
@@ -266,16 +264,22 @@ static int i2o_report_query_status(struct seq_file *seq, int block_status,
 {
        switch (block_status) {
        case -ETIMEDOUT:
-               return seq_printf(seq, "Timeout reading group %s.\n", group);
+               seq_printf(seq, "Timeout reading group %s.\n", group);
+               break;
        case -ENOMEM:
-               return seq_printf(seq, "No free memory to read the table.\n");
+               seq_puts(seq, "No free memory to read the table.\n");
+               break;
        case -I2O_PARAMS_STATUS_INVALID_GROUP_ID:
-               return seq_printf(seq, "Group %s not supported.\n", group);
+               seq_printf(seq, "Group %s not supported.\n", group);
+               break;
        default:
-               return seq_printf(seq,
-                                 "Error reading group %s. BlockStatus 0x%02X\n",
-                                 group, -block_status);
+               seq_printf(seq,
+                          "Error reading group %s. BlockStatus 0x%02X\n",
+                          group, -block_status);
+               break;
        }
+
+       return 0;
 }
 
 static char *bus_strings[] = {
index 52334fc8b547002857c015380b50f1ecd612fc7d..23bdbe4aa480216845cf7d58f185799f4990aaf7 100644 (file)
@@ -1042,7 +1042,7 @@ static void i2o_iop_release(struct device *dev)
  */
 struct i2o_controller *i2o_iop_alloc(void)
 {
-       static int unit = 0;    /* 0 and 1 are NULL IOP and Local Host */
+       static int unit;        /* 0 and 1 are NULL IOP and Local Host */
        struct i2o_controller *c;
        char poolname[32];
 
@@ -1096,7 +1096,8 @@ int i2o_iop_add(struct i2o_controller *c)
 {
        int rc;
 
-       if ((rc = device_add(&c->device))) {
+       rc = device_add(&c->device);
+       if (rc) {
                osm_err("%s: could not add controller\n", c->name);
                goto iop_reset;
        }
@@ -1105,24 +1106,28 @@ int i2o_iop_add(struct i2o_controller *c)
        osm_info("%s: This may take a few minutes if there are many devices\n",
                 c->name);
 
-       if ((rc = i2o_iop_activate(c))) {
+       rc = i2o_iop_activate(c);
+       if (rc) {
                osm_err("%s: could not activate controller\n", c->name);
                goto device_del;
        }
 
        osm_debug("%s: building sys table...\n", c->name);
 
-       if ((rc = i2o_systab_build()))
+       rc = i2o_systab_build();
+       if (rc)
                goto device_del;
 
        osm_debug("%s: online controller...\n", c->name);
 
-       if ((rc = i2o_iop_online(c)))
+       rc = i2o_iop_online(c);
+       if (rc)
                goto device_del;
 
        osm_debug("%s: getting LCT...\n", c->name);
 
-       if ((rc = i2o_exec_lct_get(c)))
+       rc = i2o_exec_lct_get(c);
+       if (rc)
                goto device_del;
 
        list_add(&c->list, &i2o_controllers);
@@ -1192,13 +1197,16 @@ static int __init i2o_iop_init(void)
 
        printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
 
-       if ((rc = i2o_driver_init()))
+       rc = i2o_driver_init();
+       if (rc)
                goto exit;
 
-       if ((rc = i2o_exec_init()))
+       rc = i2o_exec_init();
+       if (rc)
                goto driver_exit;
 
-       if ((rc = i2o_pci_init()))
+       rc = i2o_pci_init();
+       if (rc)
                goto exec_exit;
 
        return 0;
index 8f9509d275a46f4b66d399d932d5a472a9639741..78b702c185371b464c4a884a9eeb1131b3ee61bc 100644 (file)
@@ -270,10 +270,9 @@ EXPORT_SYMBOL_GPL(i2o_dma_realloc);
 int i2o_pool_alloc(struct i2o_pool *pool, const char *name,
                                 size_t size, int min_nr)
 {
-       pool->name = kmalloc(strlen(name) + 1, GFP_KERNEL);
+       pool->name = kstrdup(name, GFP_KERNEL);
        if (!pool->name)
                goto exit;
-       strcpy(pool->name, name);
 
        pool->slab =
            kmem_cache_create(pool->name, size, 0, SLAB_HWCACHE_ALIGN, NULL);
index b3b8a61dd4a6d7e25d2def976995b8dddf298205..49804c9cf74f23722cad7492f3099900e425dd63 100644 (file)
@@ -329,7 +329,8 @@ static int i2o_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                return -ENODEV;
        }
 
-       if ((rc = pci_enable_device(pdev))) {
+       rc = pci_enable_device(pdev);
+       if (rc) {
                printk(KERN_WARNING "i2o: couldn't enable device %s\n",
                       pci_name(pdev));
                return rc;
@@ -410,7 +411,8 @@ static int i2o_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 #endif
        }
 
-       if ((rc = i2o_pci_alloc(c))) {
+       rc = i2o_pci_alloc(c);
+       if (rc) {
                printk(KERN_ERR "%s: DMA / IO allocation for I2O controller "
                       "failed\n", c->name);
                goto free_controller;
@@ -422,7 +424,8 @@ static int i2o_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto free_pci;
        }
 
-       if ((rc = i2o_iop_add(c)))
+       rc = i2o_iop_add(c);
+       if (rc)
                goto uninstall;
 
        if (i960)
diff --git a/drivers/staging/iio/Documentation/generic_buffer.c b/drivers/staging/iio/Documentation/generic_buffer.c
deleted file mode 100644 (file)
index de4647e..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-/* Industrialio buffer test code.
- *
- * Copyright (c) 2008 Jonathan Cameron
- *
- * 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 primarily intended as an example application.
- * Reads the current buffer setup from sysfs and starts a short capture
- * from the specified device, pretty printing the result after appropriate
- * conversion.
- *
- * Command line parameters
- * generic_buffer -n <device_name> -t <trigger_name>
- * If trigger name is not specified the program assumes you want a dataready
- * trigger associated with the device and goes looking for it.
- *
- */
-
-#define _GNU_SOURCE
-
-#include <unistd.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/dir.h>
-#include <linux/types.h>
-#include <string.h>
-#include <poll.h>
-#include <endian.h>
-#include <getopt.h>
-#include <inttypes.h>
-#include "iio_utils.h"
-
-/**
- * size_from_channelarray() - calculate the storage size of a scan
- * @channels:          the channel info array
- * @num_channels:      number of channels
- *
- * Has the side effect of filling the channels[i].location values used
- * in processing the buffer output.
- **/
-int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
-{
-       int bytes = 0;
-       int i = 0;
-
-       while (i < num_channels) {
-               if (bytes % channels[i].bytes == 0)
-                       channels[i].location = bytes;
-               else
-                       channels[i].location = bytes - bytes%channels[i].bytes
-                               + channels[i].bytes;
-               bytes = channels[i].location + channels[i].bytes;
-               i++;
-       }
-       return bytes;
-}
-
-void print2byte(int input, struct iio_channel_info *info)
-{
-       /* First swap if incorrect endian */
-       if (info->be)
-               input = be16toh((uint16_t)input);
-       else
-               input = le16toh((uint16_t)input);
-
-       /*
-        * Shift before conversion to avoid sign extension
-        * of left aligned data
-        */
-       input = input >> info->shift;
-       if (info->is_signed) {
-               int16_t val = input;
-
-               val &= (1 << info->bits_used) - 1;
-               val = (int16_t)(val << (16 - info->bits_used)) >>
-                       (16 - info->bits_used);
-               printf("%05f ", ((float)val + info->offset)*info->scale);
-       } else {
-               uint16_t val = input;
-
-               val &= (1 << info->bits_used) - 1;
-               printf("%05f ", ((float)val + info->offset)*info->scale);
-       }
-}
-/**
- * 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.
- * @num_channels:      number of channels
- **/
-void process_scan(char *data,
-                 struct iio_channel_info *channels,
-                 int num_channels)
-{
-       int k;
-
-       for (k = 0; k < num_channels; k++)
-               switch (channels[k].bytes) {
-                       /* only a few cases implemented so far */
-               case 2:
-                       print2byte(*(uint16_t *)(data + channels[k].location),
-                                  &channels[k]);
-                       break;
-               case 4:
-                       if (!channels[k].is_signed) {
-                               uint32_t val = *(uint32_t *)
-                                       (data + channels[k].location);
-                               printf("%05f ", ((float)val +
-                                                channels[k].offset)*
-                                      channels[k].scale);
-
-                       }
-                       break;
-               case 8:
-                       if (channels[k].is_signed) {
-                               int64_t val = *(int64_t *)
-                                       (data +
-                                        channels[k].location);
-                               if ((val >> channels[k].bits_used) & 1)
-                                       val = (val & channels[k].mask) |
-                                               ~channels[k].mask;
-                               /* special case for timestamp */
-                               if (channels[k].scale == 1.0f &&
-                                   channels[k].offset == 0.0f)
-                                       printf("%" PRId64 " ", val);
-                               else
-                                       printf("%05f ", ((float)val +
-                                                        channels[k].offset)*
-                                              channels[k].scale);
-                       }
-                       break;
-               default:
-                       break;
-               }
-       printf("\n");
-}
-
-int main(int argc, char **argv)
-{
-       unsigned long num_loops = 2;
-       unsigned long timedelay = 1000000;
-       unsigned long buf_len = 128;
-
-       int ret, c, i, j, toread;
-       int fp;
-
-       int num_channels;
-       char *trigger_name = NULL, *device_name = NULL;
-       char *dev_dir_name, *buf_dir_name;
-
-       int datardytrigger = 1;
-       char *data;
-       ssize_t read_size;
-       int dev_num, trig_num;
-       char *buffer_access;
-       int scan_size;
-       int noevents = 0;
-       int notrigger = 0;
-       char *dummy;
-
-       struct iio_channel_info *channels;
-
-       while ((c = getopt(argc, argv, "l:w:c:et:n:g")) != -1) {
-               switch (c) {
-               case 'n':
-                       device_name = optarg;
-                       break;
-               case 't':
-                       trigger_name = optarg;
-                       datardytrigger = 0;
-                       break;
-               case 'e':
-                       noevents = 1;
-                       break;
-               case 'c':
-                       num_loops = strtoul(optarg, &dummy, 10);
-                       break;
-               case 'w':
-                       timedelay = strtoul(optarg, &dummy, 10);
-                       break;
-               case 'l':
-                       buf_len = strtoul(optarg, &dummy, 10);
-                       break;
-               case 'g':
-                       notrigger = 1;
-                       break;
-               case '?':
-                       return -1;
-               }
-       }
-
-       if (device_name == NULL)
-               return -1;
-
-       /* 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);
-               ret = -ENODEV;
-               goto error_ret;
-       }
-       printf("iio device number being used is %d\n", dev_num);
-
-       asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
-
-       if (!notrigger) {
-               if (trigger_name == NULL) {
-                       /*
-                        * Build the trigger name. If it is device associated
-                        * its name is <device_name>_dev[n] where n matches
-                        * the device number found above.
-                        */
-                       ret = asprintf(&trigger_name,
-                                      "%s-dev%d", device_name, dev_num);
-                       if (ret < 0) {
-                               ret = -ENOMEM;
-                               goto error_ret;
-                       }
-               }
-
-               /* 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);
-                       ret = -ENODEV;
-                       goto error_free_triggername;
-               }
-               printf("iio trigger number being used is %d\n", trig_num);
-       } else
-               printf("trigger-less mode selected\n");
-
-       /*
-        * Parse the files in scan_elements to identify what channels are
-        * present
-        */
-       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);
-               goto error_free_triggername;
-       }
-
-       /*
-        * Construct the directory name for the associated buffer.
-        * As we know that the lis3l02dq has only one buffer this may
-        * be built rather than found.
-        */
-       ret = asprintf(&buf_dir_name,
-                      "%siio:device%d/buffer", iio_dir, dev_num);
-       if (ret < 0) {
-               ret = -ENOMEM;
-               goto error_free_triggername;
-       }
-
-       if (!notrigger) {
-               printf("%s %s\n", dev_dir_name, trigger_name);
-               /* 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");
-                       goto error_free_buf_dir_name;
-               }
-       }
-
-       /* Setup ring buffer parameters */
-       ret = write_sysfs_int("length", buf_dir_name, buf_len);
-       if (ret < 0)
-               goto error_free_buf_dir_name;
-
-       /* Enable the buffer */
-       ret = write_sysfs_int("enable", buf_dir_name, 1);
-       if (ret < 0)
-               goto error_free_buf_dir_name;
-       scan_size = size_from_channelarray(channels, num_channels);
-       data = malloc(scan_size*buf_len);
-       if (!data) {
-               ret = -ENOMEM;
-               goto error_free_buf_dir_name;
-       }
-
-       ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
-       if (ret < 0) {
-               ret = -ENOMEM;
-               goto error_free_data;
-       }
-
-       /* 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 */
-               printf("Failed to open %s\n", buffer_access);
-               ret = -errno;
-               goto error_free_buffer_access;
-       }
-
-       /* Wait for events 10 times */
-       for (j = 0; j < num_loops; j++) {
-               if (!noevents) {
-                       struct pollfd pfd = {
-                               .fd = fp,
-                               .events = POLLIN,
-                       };
-
-                       poll(&pfd, 1, -1);
-                       toread = buf_len;
-
-               } else {
-                       usleep(timedelay);
-                       toread = 64;
-               }
-
-               read_size = read(fp,
-                                data,
-                                toread*scan_size);
-               if (read_size < 0) {
-                       if (errno == -EAGAIN) {
-                               printf("nothing available\n");
-                               continue;
-                       } else
-                               break;
-               }
-               for (i = 0; i < read_size/scan_size; i++)
-                       process_scan(data + scan_size*i,
-                                    channels,
-                                    num_channels);
-       }
-
-       /* Stop the buffer */
-       ret = write_sysfs_int("enable", buf_dir_name, 0);
-       if (ret < 0)
-               goto error_close_buffer_access;
-
-       if (!notrigger)
-               /* Disconnect the trigger - just write a dummy name. */
-               write_sysfs_string("trigger/current_trigger",
-                                  dev_dir_name, "NULL");
-
-error_close_buffer_access:
-       close(fp);
-error_free_data:
-       free(data);
-error_free_buffer_access:
-       free(buffer_access);
-error_free_buf_dir_name:
-       free(buf_dir_name);
-error_free_triggername:
-       if (datardytrigger)
-               free(trigger_name);
-error_ret:
-       return ret;
-}
diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c
deleted file mode 100644 (file)
index 72c96aa..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-/* Industrialio event test code.
- *
- * Copyright (c) 2011-2012 Lars-Peter Clausen <lars@metafoo.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.
- *
- * This program is primarily intended as an example application.
- * Reads the current buffer setup from sysfs and starts a short capture
- * from the specified device, pretty printing the result after appropriate
- * conversion.
- *
- * Usage:
- *     iio_event_monitor <device_name>
- *
- */
-
-#define _GNU_SOURCE
-
-#include <unistd.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <poll.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include "iio_utils.h"
-#include <linux/iio/events.h>
-
-static const char * const iio_chan_type_name_spec[] = {
-       [IIO_VOLTAGE] = "voltage",
-       [IIO_CURRENT] = "current",
-       [IIO_POWER] = "power",
-       [IIO_ACCEL] = "accel",
-       [IIO_ANGL_VEL] = "anglvel",
-       [IIO_MAGN] = "magn",
-       [IIO_LIGHT] = "illuminance",
-       [IIO_INTENSITY] = "intensity",
-       [IIO_PROXIMITY] = "proximity",
-       [IIO_TEMP] = "temp",
-       [IIO_INCLI] = "incli",
-       [IIO_ROT] = "rot",
-       [IIO_ANGL] = "angl",
-       [IIO_TIMESTAMP] = "timestamp",
-       [IIO_CAPACITANCE] = "capacitance",
-       [IIO_ALTVOLTAGE] = "altvoltage",
-       [IIO_CCT] = "cct",
-       [IIO_PRESSURE] = "pressure",
-       [IIO_HUMIDITYRELATIVE] = "humidityrelative",
-       [IIO_ACTIVITY] = "activity",
-       [IIO_STEPS] = "steps",
-};
-
-static const char * const iio_ev_type_text[] = {
-       [IIO_EV_TYPE_THRESH] = "thresh",
-       [IIO_EV_TYPE_MAG] = "mag",
-       [IIO_EV_TYPE_ROC] = "roc",
-       [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive",
-       [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive",
-       [IIO_EV_TYPE_CHANGE] = "change",
-};
-
-static const char * const iio_ev_dir_text[] = {
-       [IIO_EV_DIR_EITHER] = "either",
-       [IIO_EV_DIR_RISING] = "rising",
-       [IIO_EV_DIR_FALLING] = "falling"
-};
-
-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_LIGHT_BOTH] = "both",
-       [IIO_MOD_LIGHT_IR] = "ir",
-       [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_CLEAR] = "clear",
-       [IIO_MOD_LIGHT_RED] = "red",
-       [IIO_MOD_LIGHT_GREEN] = "green",
-       [IIO_MOD_LIGHT_BLUE] = "blue",
-       [IIO_MOD_QUATERNION] = "quaternion",
-       [IIO_MOD_TEMP_AMBIENT] = "ambient",
-       [IIO_MOD_TEMP_OBJECT] = "object",
-       [IIO_MOD_NORTH_MAGN] = "from_north_magnetic",
-       [IIO_MOD_NORTH_TRUE] = "from_north_true",
-       [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp",
-       [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp",
-       [IIO_MOD_RUNNING] = "running",
-       [IIO_MOD_JOGGING] = "jogging",
-       [IIO_MOD_WALKING] = "walking",
-       [IIO_MOD_STILL] = "still",
-};
-
-static bool event_is_known(struct iio_event_data *event)
-{
-       enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id);
-       enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id);
-       enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id);
-       enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id);
-
-       switch (type) {
-       case IIO_VOLTAGE:
-       case IIO_CURRENT:
-       case IIO_POWER:
-       case IIO_ACCEL:
-       case IIO_ANGL_VEL:
-       case IIO_MAGN:
-       case IIO_LIGHT:
-       case IIO_INTENSITY:
-       case IIO_PROXIMITY:
-       case IIO_TEMP:
-       case IIO_INCLI:
-       case IIO_ROT:
-       case IIO_ANGL:
-       case IIO_TIMESTAMP:
-       case IIO_CAPACITANCE:
-       case IIO_ALTVOLTAGE:
-       case IIO_CCT:
-       case IIO_PRESSURE:
-       case IIO_HUMIDITYRELATIVE:
-       case IIO_ACTIVITY:
-       case IIO_STEPS:
-               break;
-       default:
-               return false;
-       }
-
-       switch (mod) {
-       case IIO_NO_MOD:
-       case IIO_MOD_X:
-       case IIO_MOD_Y:
-       case IIO_MOD_Z:
-       case IIO_MOD_X_AND_Y:
-       case IIO_MOD_X_AND_Z:
-       case IIO_MOD_Y_AND_Z:
-       case IIO_MOD_X_AND_Y_AND_Z:
-       case IIO_MOD_X_OR_Y:
-       case IIO_MOD_X_OR_Z:
-       case IIO_MOD_Y_OR_Z:
-       case IIO_MOD_X_OR_Y_OR_Z:
-       case IIO_MOD_LIGHT_BOTH:
-       case IIO_MOD_LIGHT_IR:
-       case IIO_MOD_ROOT_SUM_SQUARED_X_Y:
-       case IIO_MOD_SUM_SQUARED_X_Y_Z:
-       case IIO_MOD_LIGHT_CLEAR:
-       case IIO_MOD_LIGHT_RED:
-       case IIO_MOD_LIGHT_GREEN:
-       case IIO_MOD_LIGHT_BLUE:
-       case IIO_MOD_QUATERNION:
-       case IIO_MOD_TEMP_AMBIENT:
-       case IIO_MOD_TEMP_OBJECT:
-       case IIO_MOD_NORTH_MAGN:
-       case IIO_MOD_NORTH_TRUE:
-       case IIO_MOD_NORTH_MAGN_TILT_COMP:
-       case IIO_MOD_NORTH_TRUE_TILT_COMP:
-       case IIO_MOD_RUNNING:
-       case IIO_MOD_JOGGING:
-       case IIO_MOD_WALKING:
-       case IIO_MOD_STILL:
-               break;
-       default:
-               return false;
-       }
-
-       switch (ev_type) {
-       case IIO_EV_TYPE_THRESH:
-       case IIO_EV_TYPE_MAG:
-       case IIO_EV_TYPE_ROC:
-       case IIO_EV_TYPE_THRESH_ADAPTIVE:
-       case IIO_EV_TYPE_MAG_ADAPTIVE:
-       case IIO_EV_TYPE_CHANGE:
-               break;
-       default:
-               return false;
-       }
-
-       switch (dir) {
-       case IIO_EV_DIR_EITHER:
-       case IIO_EV_DIR_RISING:
-       case IIO_EV_DIR_FALLING:
-       case IIO_EV_DIR_NONE:
-               break;
-       default:
-               return false;
-       }
-
-       return true;
-}
-
-static void print_event(struct iio_event_data *event)
-{
-       enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id);
-       enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id);
-       enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id);
-       enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id);
-       int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event->id);
-       int chan2 = IIO_EVENT_CODE_EXTRACT_CHAN2(event->id);
-       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);
-               return;
-       }
-
-       printf("Event: time: %lld, ", event->timestamp);
-
-       if (mod != IIO_NO_MOD) {
-               printf("type: %s(%s), ",
-                       iio_chan_type_name_spec[type],
-                       iio_modifier_names[mod]);
-       } else {
-               printf("type: %s, ",
-                       iio_chan_type_name_spec[type]);
-       }
-
-       if (diff && chan >= 0 && chan2 >= 0)
-               printf("channel: %d-%d, ", chan, chan2);
-       else if (chan >= 0)
-               printf("channel: %d, ", chan);
-
-       printf("evtype: %s", iio_ev_type_text[ev_type]);
-
-       if (dir != IIO_EV_DIR_NONE)
-               printf(", direction: %s", iio_ev_dir_text[dir]);
-       printf("\n");
-}
-
-int main(int argc, char **argv)
-{
-       struct iio_event_data event;
-       const char *device_name;
-       char *chrdev_name;
-       int ret;
-       int dev_num;
-       int fd, event_fd;
-
-       if (argc <= 1) {
-               printf("Usage: %s <device_name>\n", argv[0]);
-               return -1;
-       }
-
-       device_name = argv[1];
-
-       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);
-               ret = asprintf(&chrdev_name, "/dev/iio:device%d", dev_num);
-               if (ret < 0) {
-                       ret = -ENOMEM;
-                       goto error_ret;
-               }
-       } else {
-               /* If we can't find a IIO device by name assume device_name is a
-                  IIO chrdev */
-               chrdev_name = strdup(device_name);
-       }
-
-       fd = open(chrdev_name, 0);
-       if (fd == -1) {
-               fprintf(stdout, "Failed to open %s\n", chrdev_name);
-               ret = -errno;
-               goto error_free_chrdev_name;
-       }
-
-       ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd);
-
-       close(fd);
-
-       if (ret == -1 || event_fd == -1) {
-               fprintf(stdout, "Failed to retrieve event fd\n");
-               ret = -errno;
-               goto error_free_chrdev_name;
-       }
-
-       while (true) {
-               ret = read(event_fd, &event, sizeof(event));
-               if (ret == -1) {
-                       if (errno == EAGAIN) {
-                               printf("nothing available\n");
-                               continue;
-                       } else {
-                               perror("Failed to read event from device");
-                               ret = -errno;
-                               break;
-                       }
-               }
-
-               print_event(&event);
-       }
-
-       close(event_fd);
-error_free_chrdev_name:
-       free(chrdev_name);
-error_ret:
-       return ret;
-}
diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h
deleted file mode 100644 (file)
index 568eff0..0000000
+++ /dev/null
@@ -1,683 +0,0 @@
-/* IIO - useful set of util functionality
- *
- * Copyright (c) 2008 Jonathan Cameron
- *
- * 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 <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <dirent.h>
-#include <errno.h>
-
-/* Made up value to limit allocation sizes */
-#define IIO_MAX_NAME_LENGTH 30
-
-#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
-#define FORMAT_TYPE_FILE "%s_type"
-
-const char *iio_dir = "/sys/bus/iio/devices/";
-
-/**
- * iioutils_break_up_name() - extract generic name from full channel name
- * @full_name: the full channel name
- * @generic_name: the output generic channel name
- **/
-inline int iioutils_break_up_name(const char *full_name,
-                                 char **generic_name)
-{
-       char *current;
-       char *w, *r;
-       char *working;
-
-       current = strdup(full_name);
-       working = strtok(current, "_\0");
-       w = working;
-       r = working;
-
-       while (*r != '\0') {
-               if (!isdigit(*r)) {
-                       *w = *r;
-                       w++;
-               }
-               r++;
-       }
-       *w = '\0';
-       *generic_name = strdup(working);
-       free(current);
-
-       return 0;
-}
-
-/**
- * struct iio_channel_info - information about a given channel
- * @name: channel name
- * @generic_name: general name for channel type
- * @scale: scale factor to be applied for conversion to si units
- * @offset: offset to be applied for conversion to si units
- * @index: the channel index in the buffer output
- * @bytes: number of bytes occupied in buffer output
- * @mask: a bit mask for the raw output
- * @is_signed: is the raw value stored signed
- * @enabled: is this channel enabled
- **/
-struct iio_channel_info {
-       char *name;
-       char *generic_name;
-       float scale;
-       float offset;
-       unsigned index;
-       unsigned bytes;
-       unsigned bits_used;
-       unsigned shift;
-       uint64_t mask;
-       unsigned be;
-       unsigned is_signed;
-       unsigned location;
-};
-
-/**
- * iioutils_get_type() - find and process _type attribute data
- * @is_signed: output whether channel is signed
- * @bytes: output how many bytes the channel storage occupies
- * @mask: output a bit mask for the raw data
- * @be: big endian
- * @device_dir: the iio device directory
- * @name: the channel name
- * @generic_name: the channel type name
- **/
-inline 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;
-       DIR *dp;
-       char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
-       char signchar, endianchar;
-       unsigned padint;
-       const struct dirent *ent;
-
-       ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
-       if (ret < 0) {
-               ret = -ENOMEM;
-               goto error_ret;
-       }
-       ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
-       if (ret < 0) {
-               ret = -ENOMEM;
-               goto error_free_scan_el_dir;
-       }
-       ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
-       if (ret < 0) {
-               ret = -ENOMEM;
-               goto error_free_builtname;
-       }
-
-       dp = opendir(scan_el_dir);
-       if (dp == NULL) {
-               ret = -errno;
-               goto error_free_builtname_generic;
-       }
-       while (ent = readdir(dp), ent != NULL)
-               /*
-                * Do we allow devices to override a generic name with
-                * a specific one?
-                */
-               if ((strcmp(builtname, ent->d_name) == 0) ||
-                   (strcmp(builtname_generic, ent->d_name) == 0)) {
-                       ret = asprintf(&filename,
-                                      "%s/%s", scan_el_dir, ent->d_name);
-                       if (ret < 0) {
-                               ret = -ENOMEM;
-                               goto error_closedir;
-                       }
-                       sysfsfp = fopen(filename, "r");
-                       if (sysfsfp == NULL) {
-                               printf("failed to open %s\n", filename);
-                               ret = -errno;
-                               goto error_free_filename;
-                       }
-
-                       ret = fscanf(sysfsfp,
-                                    "%ce:%c%u/%u>>%u",
-                                    &endianchar,
-                                    &signchar,
-                                    bits_used,
-                                    &padint, shift);
-                       if (ret < 0) {
-                               printf("failed to pass scan type description\n");
-                               ret = -errno;
-                               goto error_close_sysfsfp;
-                       }
-                       *be = (endianchar == 'b');
-                       *bytes = padint / 8;
-                       if (*bits_used == 64)
-                               *mask = ~0;
-                       else
-                               *mask = (1 << *bits_used) - 1;
-                       if (signchar == 's')
-                               *is_signed = 1;
-                       else
-                               *is_signed = 0;
-                       fclose(sysfsfp);
-                       free(filename);
-
-                       filename = 0;
-                       sysfsfp = 0;
-               }
-error_close_sysfsfp:
-       if (sysfsfp)
-               fclose(sysfsfp);
-error_free_filename:
-       if (filename)
-               free(filename);
-error_closedir:
-       closedir(dp);
-error_free_builtname_generic:
-       free(builtname_generic);
-error_free_builtname:
-       free(builtname);
-error_free_scan_el_dir:
-       free(scan_el_dir);
-error_ret:
-       return ret;
-}
-
-inline 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;
-       DIR *dp;
-       char *builtname, *builtname_generic;
-       char *filename = NULL;
-       const struct dirent *ent;
-
-       ret = asprintf(&builtname, "%s_%s", name, param_name);
-       if (ret < 0) {
-               ret = -ENOMEM;
-               goto error_ret;
-       }
-       ret = asprintf(&builtname_generic,
-                      "%s_%s", generic_name, param_name);
-       if (ret < 0) {
-               ret = -ENOMEM;
-               goto error_free_builtname;
-       }
-       dp = opendir(device_dir);
-       if (dp == NULL) {
-               ret = -errno;
-               goto error_free_builtname_generic;
-       }
-       while (ent = readdir(dp), ent != NULL)
-               if ((strcmp(builtname, ent->d_name) == 0) ||
-                   (strcmp(builtname_generic, ent->d_name) == 0)) {
-                       ret = asprintf(&filename,
-                                      "%s/%s", device_dir, ent->d_name);
-                       if (ret < 0) {
-                               ret = -ENOMEM;
-                               goto error_closedir;
-                       }
-                       sysfsfp = fopen(filename, "r");
-                       if (!sysfsfp) {
-                               ret = -errno;
-                               goto error_free_filename;
-                       }
-                       fscanf(sysfsfp, "%f", output);
-                       break;
-               }
-error_free_filename:
-       if (filename)
-               free(filename);
-error_closedir:
-       closedir(dp);
-error_free_builtname_generic:
-       free(builtname_generic);
-error_free_builtname:
-       free(builtname);
-error_ret:
-       return ret;
-}
-
-/**
- * bsort_channel_array_by_index() - reorder so that the array is in index order
- *
- **/
-
-inline 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;
-                       }
-}
-
-/**
- * build_channel_array() - function to figure out what channels are present
- * @device_dir: the IIO device directory in sysfs
- * @
- **/
-inline int build_channel_array(const char *device_dir,
-                             struct iio_channel_info **ci_array,
-                             int *counter)
-{
-       DIR *dp;
-       FILE *sysfsfp;
-       int count, i;
-       struct iio_channel_info *current;
-       int ret;
-       const struct dirent *ent;
-       char *scan_el_dir;
-       char *filename;
-
-       *counter = 0;
-       ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
-       if (ret < 0) {
-               ret = -ENOMEM;
-               goto error_ret;
-       }
-       dp = opendir(scan_el_dir);
-       if (dp == NULL) {
-               ret = -errno;
-               goto error_free_name;
-       }
-       while (ent = readdir(dp), ent != NULL)
-               if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
-                          "_en") == 0) {
-                       ret = asprintf(&filename,
-                                      "%s/%s", scan_el_dir, ent->d_name);
-                       if (ret < 0) {
-                               ret = -ENOMEM;
-                               goto error_close_dir;
-                       }
-                       sysfsfp = fopen(filename, "r");
-                       if (sysfsfp == NULL) {
-                               ret = -errno;
-                               free(filename);
-                               goto error_close_dir;
-                       }
-                       fscanf(sysfsfp, "%i", &ret);
-                       if (ret == 1)
-                               (*counter)++;
-                       fclose(sysfsfp);
-                       free(filename);
-               }
-       *ci_array = malloc(sizeof(**ci_array) * (*counter));
-       if (*ci_array == NULL) {
-               ret = -ENOMEM;
-               goto error_close_dir;
-       }
-       seekdir(dp, 0);
-       count = 0;
-       while (ent = readdir(dp), ent != NULL) {
-               if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
-                          "_en") == 0) {
-                       int current_enabled = 0;
-
-                       current = &(*ci_array)[count++];
-                       ret = asprintf(&filename,
-                                      "%s/%s", scan_el_dir, ent->d_name);
-                       if (ret < 0) {
-                               ret = -ENOMEM;
-                               /* decrement count to avoid freeing name */
-                               count--;
-                               goto error_cleanup_array;
-                       }
-                       sysfsfp = fopen(filename, "r");
-                       if (sysfsfp == NULL) {
-                               free(filename);
-                               ret = -errno;
-                               goto error_cleanup_array;
-                       }
-                       fscanf(sysfsfp, "%i", &current_enabled);
-                       fclose(sysfsfp);
-
-                       if (!current_enabled) {
-                               free(filename);
-                               count--;
-                               continue;
-                       }
-
-                       current->scale = 1.0;
-                       current->offset = 0;
-                       current->name = strndup(ent->d_name,
-                                               strlen(ent->d_name) -
-                                               strlen("_en"));
-                       if (current->name == NULL) {
-                               free(filename);
-                               ret = -ENOMEM;
-                               goto error_cleanup_array;
-                       }
-                       /* Get the generic and specific name elements */
-                       ret = iioutils_break_up_name(current->name,
-                                                    &current->generic_name);
-                       if (ret) {
-                               free(filename);
-                               goto error_cleanup_array;
-                       }
-                       ret = asprintf(&filename,
-                                      "%s/%s_index",
-                                      scan_el_dir,
-                                      current->name);
-                       if (ret < 0) {
-                               free(filename);
-                               ret = -ENOMEM;
-                               goto error_cleanup_array;
-                       }
-                       sysfsfp = fopen(filename, "r");
-                       fscanf(sysfsfp, "%u", &current->index);
-                       fclose(sysfsfp);
-                       free(filename);
-                       /* Find the scale */
-                       ret = iioutils_get_param_float(&current->scale,
-                                                      "scale",
-                                                      device_dir,
-                                                      current->name,
-                                                      current->generic_name);
-                       if (ret < 0)
-                               goto error_cleanup_array;
-                       ret = iioutils_get_param_float(&current->offset,
-                                                      "offset",
-                                                      device_dir,
-                                                      current->name,
-                                                      current->generic_name);
-                       if (ret < 0)
-                               goto error_cleanup_array;
-                       ret = iioutils_get_type(&current->is_signed,
-                                               &current->bytes,
-                                               &current->bits_used,
-                                               &current->shift,
-                                               &current->mask,
-                                               &current->be,
-                                               device_dir,
-                                               current->name,
-                                               current->generic_name);
-               }
-       }
-
-       closedir(dp);
-       /* reorder so that the array is in index order */
-       bsort_channel_array_by_index(ci_array, *counter);
-
-       return 0;
-
-error_cleanup_array:
-       for (i = count - 1;  i >= 0; i--)
-               free((*ci_array)[i].name);
-       free(*ci_array);
-error_close_dir:
-       closedir(dp);
-error_free_name:
-       free(scan_el_dir);
-error_ret:
-       return ret;
-}
-
-/**
- * find_type_by_name() - function to match top level types by name
- * @name: top level type instance name
- * @type: the type of top level instance being sort
- *
- * Typical types this is used for are device and trigger.
- **/
-inline int find_type_by_name(const char *name, const char *type)
-{
-       const struct dirent *ent;
-       int number, numstrlen;
-
-       FILE *nameFile;
-       DIR *dp;
-       char thisname[IIO_MAX_NAME_LENGTH];
-       char *filename;
-
-       dp = opendir(iio_dir);
-       if (dp == NULL) {
-               printf("No industrialio devices available\n");
-               return -ENODEV;
-       }
-
-       while (ent = readdir(dp), ent != NULL) {
-               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) {
-                       numstrlen = sscanf(ent->d_name + strlen(type),
-                                          "%d",
-                                          &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) {
-                                       closedir(dp);
-                                       return -ENOMEM;
-                               }
-                               sprintf(filename, "%s%s%d/name",
-                                       iio_dir,
-                                       type,
-                                       number);
-                               nameFile = fopen(filename, "r");
-                               if (!nameFile) {
-                                       free(filename);
-                                       continue;
-                               }
-                               free(filename);
-                               fscanf(nameFile, "%s", thisname);
-                               fclose(nameFile);
-                               if (strcmp(name, thisname) == 0) {
-                                       closedir(dp);
-                                       return number;
-                               }
-                       }
-               }
-       }
-       closedir(dp);
-       return -ENODEV;
-}
-
-inline int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
-{
-       int ret = 0;
-       FILE *sysfsfp;
-       int test;
-       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
-
-       if (temp == NULL)
-               return -ENOMEM;
-       sprintf(temp, "%s/%s", basedir, filename);
-       sysfsfp = fopen(temp, "w");
-       if (sysfsfp == NULL) {
-               printf("failed to open %s\n", temp);
-               ret = -errno;
-               goto error_free;
-       }
-       fprintf(sysfsfp, "%d", val);
-       fclose(sysfsfp);
-       if (verify) {
-               sysfsfp = fopen(temp, "r");
-               if (sysfsfp == NULL) {
-                       printf("failed to open %s\n", temp);
-                       ret = -errno;
-                       goto error_free;
-               }
-               fscanf(sysfsfp, "%d", &test);
-               fclose(sysfsfp);
-               if (test != val) {
-                       printf("Possible failure in int write %d to %s%s\n",
-                               val,
-                               basedir,
-                               filename);
-                       ret = -1;
-               }
-       }
-error_free:
-       free(temp);
-       return ret;
-}
-
-int write_sysfs_int(char *filename, char *basedir, int val)
-{
-       return _write_sysfs_int(filename, basedir, val, 0);
-}
-
-int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
-{
-       return _write_sysfs_int(filename, basedir, val, 1);
-}
-
-int _write_sysfs_string(char *filename, char *basedir, char *val, int verify)
-{
-       int ret = 0;
-       FILE  *sysfsfp;
-       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
-
-       if (temp == NULL) {
-               printf("Memory allocation failed\n");
-               return -ENOMEM;
-       }
-       sprintf(temp, "%s/%s", basedir, filename);
-       sysfsfp = fopen(temp, "w");
-       if (sysfsfp == NULL) {
-               printf("Could not open %s\n", temp);
-               ret = -errno;
-               goto error_free;
-       }
-       fprintf(sysfsfp, "%s", val);
-       fclose(sysfsfp);
-       if (verify) {
-               sysfsfp = fopen(temp, "r");
-               if (sysfsfp == NULL) {
-                       printf("could not open file to verify\n");
-                       ret = -errno;
-                       goto error_free;
-               }
-               fscanf(sysfsfp, "%s", temp);
-               fclose(sysfsfp);
-               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);
-                       ret = -1;
-               }
-       }
-error_free:
-       free(temp);
-
-       return ret;
-}
-
-/**
- * write_sysfs_string_and_verify() - string write, readback and verify
- * @filename: name of file to write to
- * @basedir: the sysfs directory in which the file is to be found
- * @val: the string to write
- **/
-int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
-{
-       return _write_sysfs_string(filename, basedir, val, 1);
-}
-
-int write_sysfs_string(char *filename, char *basedir, char *val)
-{
-       return _write_sysfs_string(filename, basedir, val, 0);
-}
-
-int read_sysfs_posint(char *filename, char *basedir)
-{
-       int ret;
-       FILE  *sysfsfp;
-       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
-
-       if (temp == NULL) {
-               printf("Memory allocation failed");
-               return -ENOMEM;
-       }
-       sprintf(temp, "%s/%s", basedir, filename);
-       sysfsfp = fopen(temp, "r");
-       if (sysfsfp == NULL) {
-               ret = -errno;
-               goto error_free;
-       }
-       fscanf(sysfsfp, "%d\n", &ret);
-       fclose(sysfsfp);
-error_free:
-       free(temp);
-       return ret;
-}
-
-int read_sysfs_float(char *filename, char *basedir, float *val)
-{
-       int ret = 0;
-       FILE  *sysfsfp;
-       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
-
-       if (temp == NULL) {
-               printf("Memory allocation failed");
-               return -ENOMEM;
-       }
-       sprintf(temp, "%s/%s", basedir, filename);
-       sysfsfp = fopen(temp, "r");
-       if (sysfsfp == NULL) {
-               ret = -errno;
-               goto error_free;
-       }
-       fscanf(sysfsfp, "%f\n", val);
-       fclose(sysfsfp);
-error_free:
-       free(temp);
-       return ret;
-}
-
-int read_sysfs_string(const char *filename, const char *basedir, char *str)
-{
-       int ret = 0;
-       FILE  *sysfsfp;
-       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
-
-       if (temp == NULL) {
-               printf("Memory allocation failed");
-               return -ENOMEM;
-       }
-       sprintf(temp, "%s/%s", basedir, filename);
-       sysfsfp = fopen(temp, "r");
-       if (sysfsfp == NULL) {
-               ret = -errno;
-               goto error_free;
-       }
-       fscanf(sysfsfp, "%s\n", str);
-       fclose(sysfsfp);
-error_free:
-       free(temp);
-       return ret;
-}
diff --git a/drivers/staging/iio/Documentation/lsiio.c b/drivers/staging/iio/Documentation/lsiio.c
deleted file mode 100644 (file)
index 98a0de0..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Industrial I/O utilities - lsiio.c
- *
- * Copyright (c) 2010 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <string.h>
-#include <dirent.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/dir.h>
-#include "iio_utils.h"
-
-
-static enum verbosity {
-       VERBLEVEL_DEFAULT,      /* 0 gives lspci behaviour */
-       VERBLEVEL_SENSORS,      /* 1 lists sensors */
-} verblevel = VERBLEVEL_DEFAULT;
-
-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;
-}
-
-static inline int check_postfix(const char *str, const char *postfix)
-{
-       return strlen(str) > strlen(postfix) &&
-               strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
-}
-
-static int dump_channels(const char *dev_dir_name)
-{
-       DIR *dp;
-       const struct dirent *ent;
-
-       dp = opendir(dev_dir_name);
-       if (dp == NULL)
-               return -errno;
-       while (ent = readdir(dp), ent != NULL)
-               if (check_prefix(ent->d_name, "in_") &&
-                   check_postfix(ent->d_name, "_raw")) {
-                       printf("   %-10s\n", ent->d_name);
-               }
-
-       return 0;
-}
-
-static int dump_one_device(const char *dev_dir_name)
-{
-       char name[IIO_MAX_NAME_LENGTH];
-       int dev_idx;
-       int retval;
-
-       retval = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device),
-                       "%i", &dev_idx);
-       if (retval != 1)
-               return -EINVAL;
-       read_sysfs_string("name", dev_dir_name, name);
-       printf("Device %03d: %s\n", dev_idx, name);
-
-       if (verblevel >= VERBLEVEL_SENSORS)
-               return dump_channels(dev_dir_name);
-       return 0;
-}
-
-static int dump_one_trigger(const char *dev_dir_name)
-{
-       char name[IIO_MAX_NAME_LENGTH];
-       int dev_idx;
-       int retval;
-
-       retval = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger),
-                       "%i", &dev_idx);
-       if (retval != 1)
-               return -EINVAL;
-       read_sysfs_string("name", dev_dir_name, name);
-       printf("Trigger %03d: %s\n", dev_idx, name);
-       return 0;
-}
-
-static void dump_devices(void)
-{
-       const struct dirent *ent;
-       int number, numstrlen;
-
-       FILE *nameFile;
-       DIR *dp;
-       char thisname[IIO_MAX_NAME_LENGTH];
-       char *filename;
-
-       dp = opendir(iio_dir);
-       if (dp == NULL) {
-               printf("No industrial I/O devices available\n");
-               return;
-       }
-
-       while (ent = readdir(dp), ent != NULL) {
-               if (check_prefix(ent->d_name, type_device)) {
-                       char *dev_dir_name;
-
-                       asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name);
-                       dump_one_device(dev_dir_name);
-                       free(dev_dir_name);
-                       if (verblevel >= VERBLEVEL_SENSORS)
-                               printf("\n");
-               }
-       }
-       rewinddir(dp);
-       while (ent = readdir(dp), ent != NULL) {
-               if (check_prefix(ent->d_name, type_trigger)) {
-                       char *dev_dir_name;
-
-                       asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name);
-                       dump_one_trigger(dev_dir_name);
-                       free(dev_dir_name);
-               }
-       }
-       closedir(dp);
-}
-
-int main(int argc, char **argv)
-{
-       int c, err = 0;
-
-       while ((c = getopt(argc, argv, "d:D:v")) != EOF) {
-               switch (c) {
-               case 'v':
-                       verblevel++;
-                       break;
-
-               case '?':
-               default:
-                       err++;
-                       break;
-               }
-       }
-       if (err || argc > optind) {
-               fprintf(stderr, "Usage: lsiio [options]...\n"
-                       "List industrial I/O devices\n"
-                       "  -v, --verbose\n"
-                       "      Increase verbosity (may be given multiple times)\n"
-                       );
-               exit(1);
-       }
-
-       dump_devices();
-
-       return 0;
-}
index 8747de5a98055b9bba8fdda9b18146bfd51beea1..e6b8c9af6e222007dea910a5d34f9bb71ad5a59e 100644 (file)
 #define ADIS16201_GLOB_CMD       0x3E /* Operation, system command register */
 
 /* MSC_CTRL */
-#define ADIS16201_MSC_CTRL_SELF_TEST_EN                (1 << 8)  /* Self-test enable */
-#define ADIS16201_MSC_CTRL_DATA_RDY_EN         (1 << 2)  /* Data-ready enable: 1 = enabled, 0 = disabled */
-#define ADIS16201_MSC_CTRL_ACTIVE_HIGH         (1 << 1)  /* Data-ready polarity: 1 = active high, 0 = active low */
-#define ADIS16201_MSC_CTRL_DATA_RDY_DIO1       (1 << 0)  /* Data-ready line selection: 1 = DIO1, 0 = DIO0 */
+#define ADIS16201_MSC_CTRL_SELF_TEST_EN                BIT(8)  /* Self-test enable */
+#define ADIS16201_MSC_CTRL_DATA_RDY_EN         BIT(2)  /* Data-ready enable: 1 = enabled, 0 = disabled */
+#define ADIS16201_MSC_CTRL_ACTIVE_HIGH         BIT(1)  /* Data-ready polarity: 1 = active high, 0 = active low */
+#define ADIS16201_MSC_CTRL_DATA_RDY_DIO1       BIT(0)  /* Data-ready line selection: 1 = DIO1, 0 = DIO0 */
 
 /* DIAG_STAT */
-#define ADIS16201_DIAG_STAT_ALARM2        (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16201_DIAG_STAT_ALARM1        (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
+#define ADIS16201_DIAG_STAT_ALARM2        BIT(9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
+#define ADIS16201_DIAG_STAT_ALARM1        BIT(8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
 #define ADIS16201_DIAG_STAT_SPI_FAIL_BIT   3 /* SPI communications failure */
 #define ADIS16201_DIAG_STAT_FLASH_UPT_BIT  2 /* Flash update failure */
 #define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply above 3.625 V */
 #define ADIS16201_DIAG_STAT_POWER_LOW_BIT  0 /* Power supply below 3.15 V */
 
 /* GLOB_CMD */
-#define ADIS16201_GLOB_CMD_SW_RESET    (1<<7)
-#define ADIS16201_GLOB_CMD_FACTORY_CAL (1<<1)
+#define ADIS16201_GLOB_CMD_SW_RESET    BIT(7)
+#define ADIS16201_GLOB_CMD_FACTORY_CAL BIT(1)
 
-#define ADIS16201_ERROR_ACTIVE          (1<<14)
+#define ADIS16201_ERROR_ACTIVE          BIT(14)
 
 enum adis16201_scan {
        ADIS16201_SCAN_ACC_X,
index 7eae5fd0f39339c139c68e5f7cfb39ad8904d034..10db685813c9b839a9f837726eeab1ed56fae13c 100644 (file)
@@ -135,14 +135,14 @@ static const struct iio_chan_spec adis16201_channels[] = {
        ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 0, 12),
        ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 0, 12),
        ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X,
-               BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
+                       BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
        ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y,
-               BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
+                       BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
        ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 0, 12),
        ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT, ADIS16201_SCAN_INCLI_X,
-               BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
+                       BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
        ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT, ADIS16201_SCAN_INCLI_Y,
-               BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
+                       BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
        IIO_CHAN_SOFT_TIMESTAMP(7)
 };
 
index acc688d7ea9eda68a72a33f1d032a46fe05ffd13..6426e38bf00680171858e957735e5703dc4ee104 100644 (file)
 #define ADIS16203_GLOB_CMD       0x3E /* Operation, system command register */
 
 /* MSC_CTRL */
-#define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST     (1 << 10) /* Self-test at power-on: 1 = disabled, 0 = enabled */
-#define ADIS16203_MSC_CTRL_REVERSE_ROT_EN      (1 << 9)  /* Reverses rotation of both inclination outputs */
-#define ADIS16203_MSC_CTRL_SELF_TEST_EN                (1 << 8)  /* Self-test enable */
-#define ADIS16203_MSC_CTRL_DATA_RDY_EN         (1 << 2)  /* Data-ready enable: 1 = enabled, 0 = disabled */
-#define ADIS16203_MSC_CTRL_ACTIVE_HIGH         (1 << 1)  /* Data-ready polarity: 1 = active high, 0 = active low */
-#define ADIS16203_MSC_CTRL_DATA_RDY_DIO1       (1 << 0)  /* Data-ready line selection: 1 = DIO1, 0 = DIO0 */
+#define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST     BIT(10) /* Self-test at power-on: 1 = disabled, 0 = enabled */
+#define ADIS16203_MSC_CTRL_REVERSE_ROT_EN      BIT(9)  /* Reverses rotation of both inclination outputs */
+#define ADIS16203_MSC_CTRL_SELF_TEST_EN                BIT(8)  /* Self-test enable */
+#define ADIS16203_MSC_CTRL_DATA_RDY_EN         BIT(2)  /* Data-ready enable: 1 = enabled, 0 = disabled */
+#define ADIS16203_MSC_CTRL_ACTIVE_HIGH         BIT(1)  /* Data-ready polarity: 1 = active high, 0 = active low */
+#define ADIS16203_MSC_CTRL_DATA_RDY_DIO1       BIT(0)  /* Data-ready line selection: 1 = DIO1, 0 = DIO0 */
 
 /* DIAG_STAT */
-#define ADIS16203_DIAG_STAT_ALARM2        (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16203_DIAG_STAT_ALARM1        (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
+#define ADIS16203_DIAG_STAT_ALARM2        BIT(9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
+#define ADIS16203_DIAG_STAT_ALARM1        BIT(8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
 #define ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* Self-test diagnostic error flag */
 #define ADIS16203_DIAG_STAT_SPI_FAIL_BIT      3 /* SPI communications failure */
 #define ADIS16203_DIAG_STAT_FLASH_UPT_BIT     2 /* Flash update failure */
 #define ADIS16203_DIAG_STAT_POWER_LOW_BIT     0 /* Power supply below 3.15 V */
 
 /* GLOB_CMD */
-#define ADIS16203_GLOB_CMD_SW_RESET    (1<<7)
-#define ADIS16203_GLOB_CMD_CLEAR_STAT  (1<<4)
-#define ADIS16203_GLOB_CMD_FACTORY_CAL (1<<1)
+#define ADIS16203_GLOB_CMD_SW_RESET    BIT(7)
+#define ADIS16203_GLOB_CMD_CLEAR_STAT  BIT(4)
+#define ADIS16203_GLOB_CMD_FACTORY_CAL BIT(1)
 
-#define ADIS16203_ERROR_ACTIVE          (1<<14)
+#define ADIS16203_ERROR_ACTIVE          BIT(14)
 
 enum adis16203_scan {
        ADIS16203_SCAN_INCLI_X,
index fbbe93f26bbe6c074d9110fa4433755a5e95a201..fb593d23d5bcbccb6e9084145e04adc7b9360f9e 100644 (file)
@@ -104,10 +104,10 @@ static const struct iio_chan_spec adis16203_channels[] = {
        ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 0, 12),
        ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 0, 12),
        ADIS_INCLI_CHAN(X, ADIS16203_XINCL_OUT, ADIS16203_SCAN_INCLI_X,
-               BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
+                       BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
        /* Fixme: Not what it appears to be - see data sheet */
        ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y,
-               0, 0, 14),
+                       0, 0, 14),
        ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 0, 12),
        IIO_CHAN_SOFT_TIMESTAMP(5),
 };
index 9ff950c1e8dbff21a5400892db375ea45a8e4463..0b23f0b5c52ffed194d0aa71133a5c4dfa4302ae 100644 (file)
 #define ADIS16204_GLOB_CMD       0x3E /* Operation, system command register */
 
 /* MSC_CTRL */
-#define ADIS16204_MSC_CTRL_PWRUP_SELF_TEST     (1 << 10) /* Self-test at power-on: 1 = disabled, 0 = enabled */
-#define ADIS16204_MSC_CTRL_SELF_TEST_EN                (1 << 8)  /* Self-test enable */
-#define ADIS16204_MSC_CTRL_DATA_RDY_EN         (1 << 2)  /* Data-ready enable: 1 = enabled, 0 = disabled */
-#define ADIS16204_MSC_CTRL_ACTIVE_HIGH         (1 << 1)  /* Data-ready polarity: 1 = active high, 0 = active low */
-#define ADIS16204_MSC_CTRL_DATA_RDY_DIO2       (1 << 0)  /* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
+#define ADIS16204_MSC_CTRL_PWRUP_SELF_TEST     BIT(10) /* Self-test at power-on: 1 = disabled, 0 = enabled */
+#define ADIS16204_MSC_CTRL_SELF_TEST_EN                BIT(8)  /* Self-test enable */
+#define ADIS16204_MSC_CTRL_DATA_RDY_EN         BIT(2)  /* Data-ready enable: 1 = enabled, 0 = disabled */
+#define ADIS16204_MSC_CTRL_ACTIVE_HIGH         BIT(1)  /* Data-ready polarity: 1 = active high, 0 = active low */
+#define ADIS16204_MSC_CTRL_DATA_RDY_DIO2       BIT(0)  /* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
 
 /* DIAG_STAT */
-#define ADIS16204_DIAG_STAT_ALARM2        (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16204_DIAG_STAT_ALARM1        (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
+#define ADIS16204_DIAG_STAT_ALARM2        BIT(9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
+#define ADIS16204_DIAG_STAT_ALARM1        BIT(8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
 #define ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* Self-test diagnostic error flag: 1 = error condition,
                                                0 = normal operation */
 #define ADIS16204_DIAG_STAT_SPI_FAIL_BIT      3 /* SPI communications failure */
 #define ADIS16204_DIAG_STAT_POWER_LOW_BIT     0 /* Power supply below 2.975 V */
 
 /* GLOB_CMD */
-#define ADIS16204_GLOB_CMD_SW_RESET    (1<<7)
-#define ADIS16204_GLOB_CMD_CLEAR_STAT  (1<<4)
-#define ADIS16204_GLOB_CMD_FACTORY_CAL (1<<1)
+#define ADIS16204_GLOB_CMD_SW_RESET    BIT(7)
+#define ADIS16204_GLOB_CMD_CLEAR_STAT  BIT(4)
+#define ADIS16204_GLOB_CMD_FACTORY_CAL BIT(1)
 
-#define ADIS16204_ERROR_ACTIVE          (1<<14)
+#define ADIS16204_ERROR_ACTIVE          BIT(14)
 
 enum adis16204_scan {
        ADIS16204_SCAN_ACC_X,
index 4c8acbc2e44ea722429b2d27060395cb575a4640..ea0ac2467ac2d1c28a029d3891685c183e4f397f 100644 (file)
@@ -141,11 +141,13 @@ static const struct iio_chan_spec adis16204_channels[] = {
        ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 0, 12),
        ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 0, 12),
        ADIS_ACCEL_CHAN(X, ADIS16204_XACCL_OUT, ADIS16204_SCAN_ACC_X,
-               BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 14),
+                       BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK),
+                       0, 14),
        ADIS_ACCEL_CHAN(Y, ADIS16204_YACCL_OUT, ADIS16204_SCAN_ACC_Y,
-               BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 14),
+                       BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK),
+                       0, 14),
        ADIS_ACCEL_CHAN(ROOT_SUM_SQUARED_X_Y, ADIS16204_XY_RSS_OUT,
-               ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 0, 14),
+                       ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 0, 14),
        IIO_CHAN_SOFT_TIMESTAMP(5),
 };
 
index ad3945a06292f98259943e0bc83f9d56a3e06212..813698d18ec8ecd395bbf258cae701dbd9f8e985 100644 (file)
 
 /* MSC_CTRL */
 /* Self-test at power-on: 1 = disabled, 0 = enabled */
-#define ADIS16209_MSC_CTRL_PWRUP_SELF_TEST     (1 << 10)
+#define ADIS16209_MSC_CTRL_PWRUP_SELF_TEST     BIT(10)
 /* Self-test enable */
-#define ADIS16209_MSC_CTRL_SELF_TEST_EN                (1 << 8)
+#define ADIS16209_MSC_CTRL_SELF_TEST_EN                BIT(8)
 /* Data-ready enable: 1 = enabled, 0 = disabled */
-#define ADIS16209_MSC_CTRL_DATA_RDY_EN         (1 << 2)
+#define ADIS16209_MSC_CTRL_DATA_RDY_EN         BIT(2)
 /* Data-ready polarity: 1 = active high, 0 = active low */
-#define ADIS16209_MSC_CTRL_ACTIVE_HIGH         (1 << 1)
+#define ADIS16209_MSC_CTRL_ACTIVE_HIGH         BIT(1)
 /* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
-#define ADIS16209_MSC_CTRL_DATA_RDY_DIO2       (1 << 0)
+#define ADIS16209_MSC_CTRL_DATA_RDY_DIO2       BIT(0)
 
 /* DIAG_STAT */
 /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16209_DIAG_STAT_ALARM2        (1<<9)
+#define ADIS16209_DIAG_STAT_ALARM2        BIT(9)
 /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16209_DIAG_STAT_ALARM1        (1<<8)
+#define ADIS16209_DIAG_STAT_ALARM1        BIT(8)
 /* Self-test diagnostic error flag: 1 = error condition, 0 = normal operation */
 #define ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT  5
 /* SPI communications failure */
 #define ADIS16209_DIAG_STAT_POWER_LOW_BIT      0
 
 /* GLOB_CMD */
-#define ADIS16209_GLOB_CMD_SW_RESET    (1<<7)
-#define ADIS16209_GLOB_CMD_CLEAR_STAT  (1<<4)
-#define ADIS16209_GLOB_CMD_FACTORY_CAL (1<<1)
+#define ADIS16209_GLOB_CMD_SW_RESET    BIT(7)
+#define ADIS16209_GLOB_CMD_CLEAR_STAT  BIT(4)
+#define ADIS16209_GLOB_CMD_FACTORY_CAL BIT(1)
 
-#define ADIS16209_ERROR_ACTIVE          (1<<14)
+#define ADIS16209_ERROR_ACTIVE          BIT(14)
 
 #define ADIS16209_SCAN_SUPPLY  0
 #define ADIS16209_SCAN_ACC_X   1
index b2c7aeda75f04b2f58b0372bed51443e97cf5d70..d1dc1a3cb3ce64e82b74ff2bba256838edba1bb1 100644 (file)
@@ -134,14 +134,14 @@ static const struct iio_chan_spec adis16209_channels[] = {
        ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 0, 14),
        ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 0, 12),
        ADIS_ACCEL_CHAN(X, ADIS16209_XACCL_OUT, ADIS16209_SCAN_ACC_X,
-               BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
+                       BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
        ADIS_ACCEL_CHAN(Y, ADIS16209_YACCL_OUT, ADIS16209_SCAN_ACC_Y,
-               BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
+                       BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
        ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 0, 12),
        ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X,
-               0, 0, 14),
+                       0, 0, 14),
        ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y,
-               0, 0, 14),
+                       0, 0, 14),
        ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT, ADIS16209_SCAN_ROT, 0, 0, 14),
        IIO_CHAN_SOFT_TIMESTAMP(8)
 };
@@ -178,7 +178,6 @@ static const struct adis_data adis16209_data = {
                BIT(ADIS16209_DIAG_STAT_POWER_LOW_BIT),
 };
 
-
 static int adis16209_probe(struct spi_device *spi)
 {
        int ret;
index a894ad7fb26dc7d21ad6278969855f9ec19028ad..eab86331124fd87e1c47e379601690f741a2df67 100644 (file)
 #define ADIS16220_CAPTURE_SIZE  2048
 
 /* MSC_CTRL */
-#define ADIS16220_MSC_CTRL_SELF_TEST_EN                (1 << 8)
-#define ADIS16220_MSC_CTRL_POWER_SUP_COM_AIN1  (1 << 1)
-#define ADIS16220_MSC_CTRL_POWER_SUP_COM_AIN2  (1 << 0)
+#define ADIS16220_MSC_CTRL_SELF_TEST_EN                BIT(8)
+#define ADIS16220_MSC_CTRL_POWER_SUP_COM_AIN1  BIT(1)
+#define ADIS16220_MSC_CTRL_POWER_SUP_COM_AIN2  BIT(0)
 
 /* DIO_CTRL */
-#define ADIS16220_MSC_CTRL_DIO2_BUSY_IND     (3<<4)
-#define ADIS16220_MSC_CTRL_DIO1_BUSY_IND     (3<<2)
-#define ADIS16220_MSC_CTRL_DIO2_ACT_HIGH     (1<<1)
-#define ADIS16220_MSC_CTRL_DIO1_ACT_HIGH     (1<<0)
+#define ADIS16220_MSC_CTRL_DIO2_BUSY_IND     (BIT(5) | BIT(4))
+#define ADIS16220_MSC_CTRL_DIO1_BUSY_IND     (BIT(3) | BIT(2))
+#define ADIS16220_MSC_CTRL_DIO2_ACT_HIGH     BIT(1)
+#define ADIS16220_MSC_CTRL_DIO1_ACT_HIGH     BIT(0)
 
 /* DIAG_STAT */
 /* AIN2 sample > ALM_MAG2 */
-#define ADIS16220_DIAG_STAT_ALM_MAG2    (1<<14)
+#define ADIS16220_DIAG_STAT_ALM_MAG2    BIT(14)
 /* AIN1 sample > ALM_MAG1 */
-#define ADIS16220_DIAG_STAT_ALM_MAG1    (1<<13)
+#define ADIS16220_DIAG_STAT_ALM_MAG1    BIT(13)
 /* Acceleration sample > ALM_MAGA */
-#define ADIS16220_DIAG_STAT_ALM_MAGA    (1<<12)
+#define ADIS16220_DIAG_STAT_ALM_MAGA    BIT(12)
 /* Error condition programmed into ALM_MAGS[11:0] and ALM_CTRL[5:4] is true */
-#define ADIS16220_DIAG_STAT_ALM_MAGS    (1<<11)
+#define ADIS16220_DIAG_STAT_ALM_MAGS    BIT(11)
 /* |Peak value in AIN2 data capture| > ALM_MAG2 */
-#define ADIS16220_DIAG_STAT_PEAK_AIN2   (1<<10)
+#define ADIS16220_DIAG_STAT_PEAK_AIN2   BIT(10)
 /* |Peak value in AIN1 data capture| > ALM_MAG1 */
-#define ADIS16220_DIAG_STAT_PEAK_AIN1   (1<<9)
+#define ADIS16220_DIAG_STAT_PEAK_AIN1   BIT(9)
 /* |Peak value in acceleration data capture| > ALM_MAGA */
-#define ADIS16220_DIAG_STAT_PEAK_ACCEL  (1<<8)
+#define ADIS16220_DIAG_STAT_PEAK_ACCEL  BIT(8)
 /* Data ready, capture complete */
-#define ADIS16220_DIAG_STAT_DATA_RDY    (1<<7)
-#define ADIS16220_DIAG_STAT_FLASH_CHK  (1<<6)
-#define ADIS16220_DIAG_STAT_SELF_TEST  (1<<5)
+#define ADIS16220_DIAG_STAT_DATA_RDY    BIT(7)
+#define ADIS16220_DIAG_STAT_FLASH_CHK  BIT(6)
+#define ADIS16220_DIAG_STAT_SELF_TEST  BIT(5)
 /* Capture period violation/interruption */
 #define ADIS16220_DIAG_STAT_VIOLATION_BIT      4
 /* SPI communications failure */
 #define ADIS16220_DIAG_STAT_POWER_LOW_BIT      0
 
 /* GLOB_CMD */
-#define ADIS16220_GLOB_CMD_SW_RESET    (1<<7)
-#define ADIS16220_GLOB_CMD_SELF_TEST   (1<<2)
-#define ADIS16220_GLOB_CMD_PWR_DOWN    (1<<1)
+#define ADIS16220_GLOB_CMD_SW_RESET    BIT(7)
+#define ADIS16220_GLOB_CMD_SELF_TEST   BIT(2)
+#define ADIS16220_GLOB_CMD_PWR_DOWN    BIT(1)
 
 #define ADIS16220_MAX_TX 2048
 #define ADIS16220_MAX_RX 2048
index d478f5130a0fb461ff039a72cb48a75f79e7beff..e46a91c69a3170a5f42d3eb867492541d2fbdc85 100644 (file)
 #include "adis16220.h"
 
 static ssize_t adis16220_read_16bit(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
+                                   struct device_attribute *attr,
+                                   char *buf)
 {
        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct adis16220_state *st = iio_priv(indio_dev);
        ssize_t ret;
-       s16 val = 0;
+       u16 val;
 
        /* Take the iio_dev status lock */
        mutex_lock(&indio_dev->mlock);
-       ret = adis_read_reg_16(&st->adis, this_attr->address,
-                                       (u16 *)&val);
+       ret = adis_read_reg_16(&st->adis, this_attr->address, &val);
        mutex_unlock(&indio_dev->mlock);
        if (ret)
                return ret;
-       return sprintf(buf, "%d\n", val);
+       return sprintf(buf, "%u\n", val);
 }
 
 static ssize_t adis16220_write_16bit(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t len)
+                                    struct device_attribute *attr,
+                                    const char *buf,
+                                    size_t len)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -76,8 +75,8 @@ static int adis16220_capture(struct iio_dev *indio_dev)
 }
 
 static ssize_t adis16220_write_capture(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf, size_t len)
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t len)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        bool val;
@@ -96,10 +95,10 @@ static ssize_t adis16220_write_capture(struct device *dev,
 }
 
 static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
-                                       char *buf,
-                                       loff_t off,
-                                       size_t count,
-                                       int addr)
+                                            char *buf,
+                                            loff_t off,
+                                            size_t count,
+                                            int addr)
 {
        struct adis16220_state *st = iio_priv(indio_dev);
        struct spi_transfer xfers[] = {
@@ -131,15 +130,14 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
 
        /* write the begin position of capture buffer */
        ret = adis_write_reg_16(&st->adis,
-                                       ADIS16220_CAPT_PNTR,
-                                       off > 1);
+                               ADIS16220_CAPT_PNTR,
+                               off > 1);
        if (ret)
                return -EIO;
 
        /* read count/2 values from capture buffer */
        mutex_lock(&st->buf_lock);
 
-
        for (i = 0; i < count; i += 2) {
                st->tx[i] = ADIS_READ_REG(addr);
                st->tx[i + 1] = 0;
@@ -148,7 +146,6 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
 
        ret = spi_sync_transfer(st->adis.spi, xfers, ARRAY_SIZE(xfers));
        if (ret) {
-
                mutex_unlock(&st->buf_lock);
                return -EIO;
        }
@@ -182,9 +179,9 @@ static struct bin_attribute accel_bin = {
 };
 
 static ssize_t adis16220_adc1_bin_read(struct file *filp, struct kobject *kobj,
-                               struct bin_attribute *attr,
-                               char *buf, loff_t off,
-                               size_t count)
+                                      struct bin_attribute *attr,
+                                      char *buf, loff_t off,
+                                      size_t count)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj));
 
@@ -203,9 +200,9 @@ static struct bin_attribute adc1_bin = {
 };
 
 static ssize_t adis16220_adc2_bin_read(struct file *filp, struct kobject *kobj,
-                               struct bin_attribute *attr,
-                               char *buf, loff_t off,
-                               size_t count)
+                                      struct bin_attribute *attr,
+                                      char *buf, loff_t off,
+                                      size_t count)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj));
 
@@ -214,7 +211,6 @@ static ssize_t adis16220_adc2_bin_read(struct file *filp, struct kobject *kobj,
                                        ADIS16220_CAPT_BUF2);
 }
 
-
 static struct bin_attribute adc2_bin = {
        .attr = {
                .name = "in1_bin",
index d442d49f51f4a5a1280a3b5d66eb5cb5aa19c8be..66b5ad2f42c5043d93fb192974e6919e0d2df4af 100644 (file)
 
 /* MSC_CTRL */
 /* Enables sum-of-squares output (XYZPEAK_OUT) */
-#define ADIS16240_MSC_CTRL_XYZPEAK_OUT_EN      (1 << 15)
+#define ADIS16240_MSC_CTRL_XYZPEAK_OUT_EN      BIT(15)
 /* Enables peak tracking output (XPEAK_OUT, YPEAK_OUT, and ZPEAK_OUT) */
-#define ADIS16240_MSC_CTRL_X_Y_ZPEAK_OUT_EN    (1 << 14)
+#define ADIS16240_MSC_CTRL_X_Y_ZPEAK_OUT_EN    BIT(14)
 /* Self-test enable: 1 = apply electrostatic force, 0 = disabled */
-#define ADIS16240_MSC_CTRL_SELF_TEST_EN                (1 << 8)
+#define ADIS16240_MSC_CTRL_SELF_TEST_EN                BIT(8)
 /* Data-ready enable: 1 = enabled, 0 = disabled */
-#define ADIS16240_MSC_CTRL_DATA_RDY_EN         (1 << 2)
+#define ADIS16240_MSC_CTRL_DATA_RDY_EN         BIT(2)
 /* Data-ready polarity: 1 = active high, 0 = active low */
-#define ADIS16240_MSC_CTRL_ACTIVE_HIGH         (1 << 1)
+#define ADIS16240_MSC_CTRL_ACTIVE_HIGH         BIT(1)
 /* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
-#define ADIS16240_MSC_CTRL_DATA_RDY_DIO2       (1 << 0)
+#define ADIS16240_MSC_CTRL_DATA_RDY_DIO2       BIT(0)
 
 /* DIAG_STAT */
 /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16240_DIAG_STAT_ALARM2      (1<<9)
+#define ADIS16240_DIAG_STAT_ALARM2      BIT(9)
 /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16240_DIAG_STAT_ALARM1      (1<<8)
+#define ADIS16240_DIAG_STAT_ALARM1      BIT(8)
 /* Capture buffer full: 1 = capture buffer is full */
-#define ADIS16240_DIAG_STAT_CPT_BUF_FUL (1<<7)
+#define ADIS16240_DIAG_STAT_CPT_BUF_FUL BIT(7)
 /* Flash test, checksum flag: 1 = mismatch, 0 = match */
-#define ADIS16240_DIAG_STAT_CHKSUM      (1<<6)
+#define ADIS16240_DIAG_STAT_CHKSUM      BIT(6)
 /* Power-on, self-test flag: 1 = failure, 0 = pass */
 #define ADIS16240_DIAG_STAT_PWRON_FAIL_BIT  5
 /* Power-on self-test: 1 = in-progress, 0 = complete */
-#define ADIS16240_DIAG_STAT_PWRON_BUSY  (1<<4)
+#define ADIS16240_DIAG_STAT_PWRON_BUSY  BIT(4)
 /* SPI communications failure */
 #define ADIS16240_DIAG_STAT_SPI_FAIL_BIT       3
 /* Flash update failure */
 #define ADIS16240_DIAG_STAT_POWER_LOW_BIT      0
 
 /* GLOB_CMD */
-#define ADIS16240_GLOB_CMD_RESUME      (1<<8)
-#define ADIS16240_GLOB_CMD_SW_RESET    (1<<7)
-#define ADIS16240_GLOB_CMD_STANDBY     (1<<2)
+#define ADIS16240_GLOB_CMD_RESUME      BIT(8)
+#define ADIS16240_GLOB_CMD_SW_RESET    BIT(7)
+#define ADIS16240_GLOB_CMD_STANDBY     BIT(2)
 
-#define ADIS16240_ERROR_ACTIVE          (1<<14)
+#define ADIS16240_ERROR_ACTIVE          BIT(14)
 
 /* At the moment triggers are only used for ring buffer
  * filling. This may change!
index 3f46086eab3a30d86c464d2016255e7edb46f91c..cb074e864408abc1ff33f4fc4b4725526b49e836 100644 (file)
@@ -27,9 +27,9 @@
 #include "adis16240.h"
 
 static ssize_t adis16240_spi_read_signed(struct device *dev,
-               struct device_attribute *attr,
-               char *buf,
-               unsigned bits)
+                                        struct device_attribute *attr,
+                                        char *buf,
+                                        unsigned bits)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct adis *st = iio_priv(indio_dev);
@@ -39,20 +39,20 @@ static ssize_t adis16240_spi_read_signed(struct device *dev,
        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
        ret = adis_read_reg_16(st,
-                                       this_attr->address, (u16 *)&val);
+                              this_attr->address, (u16 *)&val);
        if (ret)
                return ret;
 
        if (val & ADIS16240_ERROR_ACTIVE)
                adis_check_status(st);
 
-       val = ((s16)(val << shift) >> shift);
+       val = (s16)(val << shift) >> shift;
        return sprintf(buf, "%d\n", val);
 }
 
 static ssize_t adis16240_read_12bit_signed(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
+                                          struct device_attribute *attr,
+                                          char *buf)
 {
        ssize_t ret;
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
@@ -176,11 +176,14 @@ static const struct iio_chan_spec adis16240_channels[] = {
        ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 0, 10),
        ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 0, 10),
        ADIS_ACCEL_CHAN(X, ADIS16240_XACCL_OUT, ADIS16240_SCAN_ACC_X,
-               BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10),
+                       BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK),
+                       0, 10),
        ADIS_ACCEL_CHAN(Y, ADIS16240_YACCL_OUT, ADIS16240_SCAN_ACC_Y,
-               BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10),
+                       BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK),
+                       0, 10),
        ADIS_ACCEL_CHAN(Z, ADIS16240_ZACCL_OUT, ADIS16240_SCAN_ACC_Z,
-               BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10),
+                       BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK),
+                       0, 10),
        ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 0, 10),
        IIO_CHAN_SOFT_TIMESTAMP(6)
 };
index 0a8ea827086647fb36543271593c34f3bdbc5356..3f24c629be6f4f98208890739577ac6d21bd4ef3 100644 (file)
@@ -194,6 +194,7 @@ irqreturn_t lis3l02dq_data_rdy_trig_poll(int irq, void *private);
 static inline void lis3l02dq_remove_trigger(struct iio_dev *indio_dev)
 {
 }
+
 static inline int lis3l02dq_probe_trigger(struct iio_dev *indio_dev)
 {
        return 0;
@@ -203,6 +204,7 @@ static int lis3l02dq_configure_buffer(struct iio_dev *indio_dev)
 {
        return 0;
 }
+
 static inline void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev)
 {
 }
index b78c9c5d55886d08f015021bc8f954475dcce1c3..ebcab56c81b9c641bbfa1de413ec0dfa1ec2ad99 100644 (file)
@@ -558,13 +558,11 @@ static const struct iio_chan_spec lis3l02dq_channels[] = {
        IIO_CHAN_SOFT_TIMESTAMP(3)
 };
 
-
 static int lis3l02dq_read_event_config(struct iio_dev *indio_dev,
                                       const struct iio_chan_spec *chan,
                                       enum iio_event_type type,
                                       enum iio_event_direction dir)
 {
-
        u8 val;
        int ret;
        u8 mask = (1 << (chan->channel2*2 + (dir == IIO_EV_DIR_RISING)));
@@ -656,8 +654,8 @@ static int lis3l02dq_write_event_config(struct iio_dev *indio_dev,
                        (control | LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT) :
                        (control & ~LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT);
                ret = lis3l02dq_spi_write_reg_8(indio_dev,
-                                              LIS3L02DQ_REG_CTRL_2_ADDR,
-                                              control);
+                                               LIS3L02DQ_REG_CTRL_2_ADDR,
+                                               control);
                if (ret)
                        goto error_ret;
        }
index 1fd90090a633580dbc2dbbd1cd985ffc06d49f8e..b892f2cf5f9ef1bd2ed7acf8197c4ceece3ec4c3 100644 (file)
@@ -110,7 +110,7 @@ static int lis3l02dq_read_all(struct iio_dev *indio_dev, u8 *rx_array)
 }
 
 static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev,
-                               u8 *buf)
+                                       u8 *buf)
 {
        int ret, i;
        u8 *rx_array;
@@ -118,8 +118,8 @@ static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev,
        int scan_count = bitmap_weight(indio_dev->active_scan_mask,
                                       indio_dev->masklength);
 
-       rx_array = kzalloc(4 * scan_count, GFP_KERNEL);
-       if (rx_array == NULL)
+       rx_array = kcalloc(4, scan_count, GFP_KERNEL);
+       if (!rx_array)
                return -ENOMEM;
        ret = lis3l02dq_read_all(indio_dev, rx_array);
        if (ret < 0) {
@@ -142,7 +142,7 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p)
        char *data;
 
        data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-       if (data == NULL)
+       if (!data)
                goto done;
 
        if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
@@ -330,19 +330,21 @@ static int lis3l02dq_buffer_postenable(struct iio_dev *indio_dev)
        if (test_bit(0, indio_dev->active_scan_mask)) {
                t |= LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE;
                oneenabled = true;
-       } else
+       } else {
                t &= ~LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE;
+       }
        if (test_bit(1, indio_dev->active_scan_mask)) {
                t |= LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE;
                oneenabled = true;
-       } else
+       } else {
                t &= ~LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE;
+       }
        if (test_bit(2, indio_dev->active_scan_mask)) {
                t |= LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE;
                oneenabled = true;
-       } else
+       } else {
                t &= ~LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE;
-
+       }
        if (!oneenabled) /* what happens in this case is unknown */
                return -EINVAL;
        ret = lis3l02dq_spi_write_reg_8(indio_dev,
@@ -410,7 +412,7 @@ int lis3l02dq_configure_buffer(struct iio_dev *indio_dev)
                                                 "lis3l02dq_consumer%d",
                                                 indio_dev->id);
 
-       if (indio_dev->pollfunc == NULL) {
+       if (!indio_dev->pollfunc) {
                ret = -ENOMEM;
                goto error_iio_sw_rb_free;
        }
index b284e5a6cac1d3d4b5e38a0127fde360ac516196..9c8a9587df7d6fa3e79163bff8a2b2dc18027b26 100644 (file)
@@ -38,6 +38,9 @@
  * Can probably alleviate this by reading the interrupt register on start, but
  * that is really just brushing the problem under the carpet.
  */
+#ifndef _SCA3000
+#define _SCA3000
+
 #define SCA3000_WRITE_REG(a) (((a) << 2) | 0x02)
 #define SCA3000_READ_REG(a) ((a) << 2)
 
@@ -272,4 +275,4 @@ static inline void sca3000_ring_int_process(u8 val, void *ring)
 }
 
 #endif
-
+#endif /* _SCA3000 */
index 31fb2182c198267caff8af6554767d37146c4072..b614f272b5f4b1b40071d4ea5e11678453a1f431 100644 (file)
@@ -870,7 +870,7 @@ static ssize_t sca3000_query_free_fall_mode(struct device *dev,
                                            struct device_attribute *attr,
                                            char *buf)
 {
-       int ret, len;
+       int ret;
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct sca3000_state *st = iio_priv(indio_dev);
        int val;
@@ -881,9 +881,7 @@ static ssize_t sca3000_query_free_fall_mode(struct device *dev,
        mutex_unlock(&st->lock);
        if (ret < 0)
                return ret;
-       len = sprintf(buf, "%d\n",
-                     !!(val & SCA3000_FREE_FALL_DETECT));
-       return len;
+       return sprintf(buf, "%d\n", !!(val & SCA3000_FREE_FALL_DETECT));
 }
 
 /**
index f76a268858080163bdd5a745997a5cae81ed64d3..8589eade1057efd56eb31a0a10555d5be63e25b0 100644 (file)
@@ -129,9 +129,9 @@ error_ret:
        return ret ? ret : num_read;
 }
 
-static bool sca3000_ring_buf_data_available(struct iio_buffer *r)
+static size_t sca3000_ring_buf_data_available(struct iio_buffer *r)
 {
-       return r->stufftoread;
+       return r->stufftoread ? r->watermark : 0;
 }
 
 /**
index 6f8ce6c6574babed56e1b7277cb04c76849be73a..fe56fb6c7d3030979a3070c38411d8b132a53ddd 100644 (file)
                                   * (RW, 16-bit (AD7792)/24-bit (AD7192)) */
 
 /* Communications Register Bit Designations (AD7192_REG_COMM) */
-#define AD7192_COMM_WEN                (1 << 7) /* Write Enable */
-#define AD7192_COMM_WRITE      (0 << 6) /* Write Operation */
-#define AD7192_COMM_READ       (1 << 6) /* Read Operation */
+#define AD7192_COMM_WEN                BIT(7) /* Write Enable */
+#define AD7192_COMM_WRITE      0 /* Write Operation */
+#define AD7192_COMM_READ       BIT(6) /* Read Operation */
 #define AD7192_COMM_ADDR(x)    (((x) & 0x7) << 3) /* Register Address */
-#define AD7192_COMM_CREAD      (1 << 2) /* Continuous Read of Data Register */
+#define AD7192_COMM_CREAD      BIT(2) /* Continuous Read of Data Register */
 
 /* Status Register Bit Designations (AD7192_REG_STAT) */
-#define AD7192_STAT_RDY                (1 << 7) /* Ready */
-#define AD7192_STAT_ERR                (1 << 6) /* Error (Overrange, Underrange) */
-#define AD7192_STAT_NOREF      (1 << 5) /* Error no external reference */
-#define AD7192_STAT_PARITY     (1 << 4) /* Parity */
-#define AD7192_STAT_CH3                (1 << 2) /* Channel 3 */
-#define AD7192_STAT_CH2                (1 << 1) /* Channel 2 */
-#define AD7192_STAT_CH1                (1 << 0) /* Channel 1 */
+#define AD7192_STAT_RDY                BIT(7) /* Ready */
+#define AD7192_STAT_ERR                BIT(6) /* Error (Overrange, Underrange) */
+#define AD7192_STAT_NOREF      BIT(5) /* Error no external reference */
+#define AD7192_STAT_PARITY     BIT(4) /* Parity */
+#define AD7192_STAT_CH3                BIT(2) /* Channel 3 */
+#define AD7192_STAT_CH2                BIT(1) /* Channel 2 */
+#define AD7192_STAT_CH1                BIT(0) /* Channel 1 */
 
 /* Mode Register Bit Designations (AD7192_REG_MODE) */
 #define AD7192_MODE_SEL(x)     (((x) & 0x7) << 21) /* Operation Mode Select */
 #define AD7192_MODE_SEL_MASK   (0x7 << 21) /* Operation Mode Select Mask */
-#define AD7192_MODE_DAT_STA    (1 << 20) /* Status Register transmission */
+#define AD7192_MODE_DAT_STA    BIT(20) /* Status Register transmission */
 #define AD7192_MODE_CLKSRC(x)  (((x) & 0x3) << 18) /* Clock Source Select */
-#define AD7192_MODE_SINC3      (1 << 15) /* SINC3 Filter Select */
-#define AD7192_MODE_ACX                (1 << 14) /* AC excitation enable(AD7195 only)*/
-#define AD7192_MODE_ENPAR      (1 << 13) /* Parity Enable */
-#define AD7192_MODE_CLKDIV     (1 << 12) /* Clock divide by 2 (AD7190/2 only)*/
-#define AD7192_MODE_SCYCLE     (1 << 11) /* Single cycle conversion */
-#define AD7192_MODE_REJ60      (1 << 10) /* 50/60Hz notch filter */
+#define AD7192_MODE_SINC3      BIT(15) /* SINC3 Filter Select */
+#define AD7192_MODE_ACX                BIT(14) /* AC excitation enable(AD7195 only)*/
+#define AD7192_MODE_ENPAR      BIT(13) /* Parity Enable */
+#define AD7192_MODE_CLKDIV     BIT(12) /* Clock divide by 2 (AD7190/2 only)*/
+#define AD7192_MODE_SCYCLE     BIT(11) /* Single cycle conversion */
+#define AD7192_MODE_REJ60      BIT(10) /* 50/60Hz notch filter */
 #define AD7192_MODE_RATE(x)    ((x) & 0x3FF) /* Filter Update Rate Select */
 
 /* Mode Register: AD7192_MODE_SEL options */
 
 /* Configuration Register Bit Designations (AD7192_REG_CONF) */
 
-#define AD7192_CONF_CHOP       (1 << 23) /* CHOP enable */
-#define AD7192_CONF_REFSEL     (1 << 20) /* REFIN1/REFIN2 Reference Select */
+#define AD7192_CONF_CHOP       BIT(23) /* CHOP enable */
+#define AD7192_CONF_REFSEL     BIT(20) /* REFIN1/REFIN2 Reference Select */
 #define AD7192_CONF_CHAN(x)    (((1 << (x)) & 0xFF) << 8) /* Channel select */
 #define AD7192_CONF_CHAN_MASK  (0xFF << 8) /* Channel select mask */
-#define AD7192_CONF_BURN       (1 << 7) /* Burnout current enable */
-#define AD7192_CONF_REFDET     (1 << 6) /* Reference detect enable */
-#define AD7192_CONF_BUF                (1 << 4) /* Buffered Mode Enable */
-#define AD7192_CONF_UNIPOLAR   (1 << 3) /* Unipolar/Bipolar Enable */
+#define AD7192_CONF_BURN       BIT(7) /* Burnout current enable */
+#define AD7192_CONF_REFDET     BIT(6) /* Reference detect enable */
+#define AD7192_CONF_BUF                BIT(4) /* Buffered Mode Enable */
+#define AD7192_CONF_UNIPOLAR   BIT(3) /* Unipolar/Bipolar Enable */
 #define AD7192_CONF_GAIN(x)    ((x) & 0x7) /* Gain Select */
 
 #define AD7192_CH_AIN1P_AIN2M  0 /* AIN1(+) - AIN2(-) */
 #define AD7192_ID_MASK         0x0F
 
 /* GPOCON Register Bit Designations (AD7192_REG_GPOCON) */
-#define AD7192_GPOCON_BPDSW    (1 << 6) /* Bridge power-down switch enable */
-#define AD7192_GPOCON_GP32EN   (1 << 5) /* Digital Output P3 and P2 enable */
-#define AD7192_GPOCON_GP10EN   (1 << 4) /* Digital Output P1 and P0 enable */
-#define AD7192_GPOCON_P3DAT    (1 << 3) /* P3 state */
-#define AD7192_GPOCON_P2DAT    (1 << 2) /* P2 state */
-#define AD7192_GPOCON_P1DAT    (1 << 1) /* P1 state */
-#define AD7192_GPOCON_P0DAT    (1 << 0) /* P0 state */
+#define AD7192_GPOCON_BPDSW    BIT(6) /* Bridge power-down switch enable */
+#define AD7192_GPOCON_GP32EN   BIT(5) /* Digital Output P3 and P2 enable */
+#define AD7192_GPOCON_GP10EN   BIT(4) /* Digital Output P1 and P0 enable */
+#define AD7192_GPOCON_P3DAT    BIT(3) /* P3 state */
+#define AD7192_GPOCON_P2DAT    BIT(2) /* P2 state */
+#define AD7192_GPOCON_P1DAT    BIT(1) /* P1 state */
+#define AD7192_GPOCON_P0DAT    BIT(0) /* P0 state */
 
 #define AD7192_INT_FREQ_MHz    4915200
 
index 4d4870787eede59fd6a73d23ba4ca29df48bbe2e..d98e229c46bfd4047e2799457e62aa1528acec4e 100644 (file)
 #define AD7280A_CNVST_CONTROL          0x1D /* D7 to D0, Read/write */
 
 /* Bits and Masks */
-#define AD7280A_CTRL_HB_CONV_INPUT_ALL                 (0 << 6)
-#define AD7280A_CTRL_HB_CONV_INPUT_6CELL_AUX1_3_4      (1 << 6)
-#define AD7280A_CTRL_HB_CONV_INPUT_6CELL               (2 << 6)
-#define AD7280A_CTRL_HB_CONV_INPUT_SELF_TEST           (3 << 6)
-#define AD7280A_CTRL_HB_CONV_RES_READ_ALL              (0 << 4)
-#define AD7280A_CTRL_HB_CONV_RES_READ_6CELL_AUX1_3_4   (1 << 4)
-#define AD7280A_CTRL_HB_CONV_RES_READ_6CELL            (2 << 4)
-#define AD7280A_CTRL_HB_CONV_RES_READ_NO               (3 << 4)
-#define AD7280A_CTRL_HB_CONV_START_CNVST               (0 << 3)
-#define AD7280A_CTRL_HB_CONV_START_CS                  (1 << 3)
-#define AD7280A_CTRL_HB_CONV_AVG_DIS                   (0 << 1)
-#define AD7280A_CTRL_HB_CONV_AVG_2                     (1 << 1)
-#define AD7280A_CTRL_HB_CONV_AVG_4                     (2 << 1)
-#define AD7280A_CTRL_HB_CONV_AVG_8                     (3 << 1)
+#define AD7280A_CTRL_HB_CONV_INPUT_ALL                 0
+#define AD7280A_CTRL_HB_CONV_INPUT_6CELL_AUX1_3_4      BIT(6)
+#define AD7280A_CTRL_HB_CONV_INPUT_6CELL               BIT(7)
+#define AD7280A_CTRL_HB_CONV_INPUT_SELF_TEST           (BIT(7) | BIT(6))
+#define AD7280A_CTRL_HB_CONV_RES_READ_ALL              0
+#define AD7280A_CTRL_HB_CONV_RES_READ_6CELL_AUX1_3_4   BIT(4)
+#define AD7280A_CTRL_HB_CONV_RES_READ_6CELL            BIT(5)
+#define AD7280A_CTRL_HB_CONV_RES_READ_NO               (BIT(5) | BIT(4))
+#define AD7280A_CTRL_HB_CONV_START_CNVST               0
+#define AD7280A_CTRL_HB_CONV_START_CS                  BIT(3)
+#define AD7280A_CTRL_HB_CONV_AVG_DIS                   0
+#define AD7280A_CTRL_HB_CONV_AVG_2                     BIT(1)
+#define AD7280A_CTRL_HB_CONV_AVG_4                     BIT(2)
+#define AD7280A_CTRL_HB_CONV_AVG_8                     (BIT(2) | BIT(1))
 #define AD7280A_CTRL_HB_CONV_AVG(x)                    ((x) << 1)
-#define AD7280A_CTRL_HB_PWRDN_SW                       (1 << 0)
+#define AD7280A_CTRL_HB_PWRDN_SW                       BIT(0)
 
-#define AD7280A_CTRL_LB_SWRST                          (1 << 7)
-#define AD7280A_CTRL_LB_ACQ_TIME_400ns                 (0 << 5)
-#define AD7280A_CTRL_LB_ACQ_TIME_800ns                 (1 << 5)
-#define AD7280A_CTRL_LB_ACQ_TIME_1200ns                        (2 << 5)
-#define AD7280A_CTRL_LB_ACQ_TIME_1600ns                        (3 << 5)
+#define AD7280A_CTRL_LB_SWRST                          BIT(7)
+#define AD7280A_CTRL_LB_ACQ_TIME_400ns                 0
+#define AD7280A_CTRL_LB_ACQ_TIME_800ns                 BIT(5)
+#define AD7280A_CTRL_LB_ACQ_TIME_1200ns                        BIT(6)
+#define AD7280A_CTRL_LB_ACQ_TIME_1600ns                        (BIT(6) | BIT(5))
 #define AD7280A_CTRL_LB_ACQ_TIME(x)                    ((x) << 5)
-#define AD7280A_CTRL_LB_MUST_SET                       (1 << 4)
-#define AD7280A_CTRL_LB_THERMISTOR_EN                  (1 << 3)
-#define AD7280A_CTRL_LB_LOCK_DEV_ADDR                  (1 << 2)
-#define AD7280A_CTRL_LB_INC_DEV_ADDR                   (1 << 1)
-#define AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN              (1 << 0)
+#define AD7280A_CTRL_LB_MUST_SET                       BIT(4)
+#define AD7280A_CTRL_LB_THERMISTOR_EN                  BIT(3)
+#define AD7280A_CTRL_LB_LOCK_DEV_ADDR                  BIT(2)
+#define AD7280A_CTRL_LB_INC_DEV_ADDR                   BIT(1)
+#define AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN              BIT(0)
 
-#define AD7280A_ALERT_GEN_STATIC_HIGH                  (1 << 6)
-#define AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN             (3 << 6)
+#define AD7280A_ALERT_GEN_STATIC_HIGH                  BIT(6)
+#define AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN             (BIT(7) | BIT(6))
 
 #define AD7280A_ALL_CELLS                              (0xAD << 16)
 
@@ -547,8 +547,9 @@ static int ad7280_attr_init(struct ad7280_state *st)
 {
        int dev, ch, cnt;
 
-       st->iio_attr = kzalloc(sizeof(*st->iio_attr) * (st->slave_num + 1) *
-                               AD7280A_CELLS_PER_DEV * 2, GFP_KERNEL);
+       st->iio_attr = kcalloc(2, sizeof(*st->iio_attr) *
+                              (st->slave_num + 1) * AD7280A_CELLS_PER_DEV,
+                              GFP_KERNEL);
        if (st->iio_attr == NULL)
                return -ENOMEM;
 
index 20400b0045e5819600e8553fa42057b932ad7a2d..732347a9bce4f68fe7c22e9f8a64f25bb370f946 100644 (file)
 #define AD7280A_CONV_AVG_4                     2
 #define AD7280A_CONV_AVG_8                     3
 
-#define AD7280A_ALERT_REMOVE_VIN5              (1 << 2)
-#define AD7280A_ALERT_REMOVE_VIN4_VIN5         (2 << 2)
-#define AD7280A_ALERT_REMOVE_AUX5              (1 << 0)
-#define AD7280A_ALERT_REMOVE_AUX4_AUX5         (2 << 0)
+#define AD7280A_ALERT_REMOVE_VIN5              BIT(2)
+#define AD7280A_ALERT_REMOVE_VIN4_VIN5         BIT(3)
+#define AD7280A_ALERT_REMOVE_AUX5              BIT(0)
+#define AD7280A_ALERT_REMOVE_AUX4_AUX5         BIT(1)
 
 struct ad7280_platform_data {
        unsigned acquisition_time;
index 3bf174cb19b1ef3573482896fef1848a3f7941ff..a6f8eb11242c124cc292e74594e16320bf092f9f 100644 (file)
@@ -50,7 +50,7 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
        int ret;
 
        buf = kzalloc(indio_dev->scan_bytes, GFP_KERNEL);
-       if (buf == NULL)
+       if (!buf)
                return;
 
        if (gpio_is_valid(st->pdata->gpio_frstdata)) {
index 273add3ed63fd8e80532110a1f793b218175caf0..9f03fe3ee3d93ee34c78ca23be867fdc59d7f706 100644 (file)
 
 #include "ad7780.h"
 
-#define AD7780_RDY     (1 << 7)
-#define AD7780_FILTER  (1 << 6)
-#define AD7780_ERR     (1 << 5)
-#define AD7780_ID1     (1 << 4)
-#define AD7780_ID0     (1 << 3)
-#define AD7780_GAIN    (1 << 2)
-#define AD7780_PAT1    (1 << 1)
-#define AD7780_PAT0    (1 << 0)
+#define AD7780_RDY     BIT(7)
+#define AD7780_FILTER  BIT(6)
+#define AD7780_ERR     BIT(5)
+#define AD7780_ID1     BIT(4)
+#define AD7780_ID0     BIT(3)
+#define AD7780_GAIN    BIT(2)
+#define AD7780_PAT1    BIT(1)
+#define AD7780_PAT0    BIT(0)
 
 struct ad7780_chip_info {
        struct iio_chan_spec    channel;
@@ -169,7 +169,7 @@ static int ad7780_probe(struct spi_device *spi)
        int ret, voltage_uv = 0;
 
        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
-       if (indio_dev == NULL)
+       if (!indio_dev)
                return -ENOMEM;
 
        st = iio_priv(indio_dev);
index 816174388f13347447c495700e3dad85e7c269db..d7c5223f1c3e78abfe759cca374873bda0b70068 100644 (file)
@@ -243,7 +243,7 @@ struct mxs_lradc {
         * be sampled as regular LRADC channels. The driver will refuse any
         * attempt to sample these channels.
         */
-#define CHAN_MASK_TOUCHBUTTON          (0x3 << 0)
+#define CHAN_MASK_TOUCHBUTTON          (BIT(1) | BIT(0))
 #define CHAN_MASK_TOUCHSCREEN_4WIRE    (0xf << 2)
 #define CHAN_MASK_TOUCHSCREEN_5WIRE    (0x1f << 2)
        enum mxs_lradc_ts       use_touchscreen;
@@ -268,20 +268,20 @@ struct mxs_lradc {
 };
 
 #define        LRADC_CTRL0                             0x00
-# define LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE  (1 << 23)
-# define LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE    (1 << 22)
-# define LRADC_CTRL0_MX28_YNNSW        /* YM */        (1 << 21)
-# define LRADC_CTRL0_MX28_YPNSW        /* YP */        (1 << 20)
-# define LRADC_CTRL0_MX28_YPPSW        /* YP */        (1 << 19)
-# define LRADC_CTRL0_MX28_XNNSW        /* XM */        (1 << 18)
-# define LRADC_CTRL0_MX28_XNPSW        /* XM */        (1 << 17)
-# define LRADC_CTRL0_MX28_XPPSW        /* XP */        (1 << 16)
-
-# define LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE  (1 << 20)
-# define LRADC_CTRL0_MX23_YM                   (1 << 19)
-# define LRADC_CTRL0_MX23_XM                   (1 << 18)
-# define LRADC_CTRL0_MX23_YP                   (1 << 17)
-# define LRADC_CTRL0_MX23_XP                   (1 << 16)
+# define LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE  BIT(23)
+# define LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE    BIT(22)
+# define LRADC_CTRL0_MX28_YNNSW        /* YM */        BIT(21)
+# define LRADC_CTRL0_MX28_YPNSW        /* YP */        BIT(20)
+# define LRADC_CTRL0_MX28_YPPSW        /* YP */        BIT(19)
+# define LRADC_CTRL0_MX28_XNNSW        /* XM */        BIT(18)
+# define LRADC_CTRL0_MX28_XNPSW        /* XM */        BIT(17)
+# define LRADC_CTRL0_MX28_XPPSW        /* XP */        BIT(16)
+
+# define LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE  BIT(20)
+# define LRADC_CTRL0_MX23_YM                   BIT(19)
+# define LRADC_CTRL0_MX23_XM                   BIT(18)
+# define LRADC_CTRL0_MX23_YP                   BIT(17)
+# define LRADC_CTRL0_MX23_XP                   BIT(16)
 
 # define LRADC_CTRL0_MX28_PLATE_MASK \
                (LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE | \
@@ -295,12 +295,12 @@ struct mxs_lradc {
                LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XP)
 
 #define        LRADC_CTRL1                             0x10
-#define        LRADC_CTRL1_TOUCH_DETECT_IRQ_EN         (1 << 24)
+#define        LRADC_CTRL1_TOUCH_DETECT_IRQ_EN         BIT(24)
 #define        LRADC_CTRL1_LRADC_IRQ_EN(n)             (1 << ((n) + 16))
 #define        LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK      (0x1fff << 16)
 #define        LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK      (0x01ff << 16)
 #define        LRADC_CTRL1_LRADC_IRQ_EN_OFFSET         16
-#define        LRADC_CTRL1_TOUCH_DETECT_IRQ            (1 << 8)
+#define        LRADC_CTRL1_TOUCH_DETECT_IRQ            BIT(8)
 #define        LRADC_CTRL1_LRADC_IRQ(n)                (1 << (n))
 #define        LRADC_CTRL1_MX28_LRADC_IRQ_MASK         0x1fff
 #define        LRADC_CTRL1_MX23_LRADC_IRQ_MASK         0x01ff
@@ -308,13 +308,13 @@ struct mxs_lradc {
 
 #define        LRADC_CTRL2                             0x20
 #define        LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET        24
-#define        LRADC_CTRL2_TEMPSENSE_PWD               (1 << 15)
+#define        LRADC_CTRL2_TEMPSENSE_PWD               BIT(15)
 
 #define        LRADC_STATUS                            0x40
-#define        LRADC_STATUS_TOUCH_DETECT_RAW           (1 << 0)
+#define        LRADC_STATUS_TOUCH_DETECT_RAW           BIT(0)
 
 #define        LRADC_CH(n)                             (0x50 + (0x10 * (n)))
-#define        LRADC_CH_ACCUMULATE                     (1 << 29)
+#define        LRADC_CH_ACCUMULATE                     BIT(29)
 #define        LRADC_CH_NUM_SAMPLES_MASK               (0x1f << 24)
 #define        LRADC_CH_NUM_SAMPLES_OFFSET             24
 #define        LRADC_CH_NUM_SAMPLES(x) \
@@ -477,7 +477,7 @@ static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
         */
        mxs_lradc_reg_wrt(lradc,
                LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */
-               LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */
+               LRADC_DELAY_TRIGGER_DELAYS(BIT(3)) | /* trigger DELAY unit#3 */
                LRADC_DELAY_KICK |
                LRADC_DELAY_DELAY(lradc->settling_delay),
                        LRADC_DELAY(2));
@@ -532,7 +532,7 @@ static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1,
         */
        mxs_lradc_reg_wrt(lradc,
                LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */
-               LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */
+               LRADC_DELAY_TRIGGER_DELAYS(BIT(3)) | /* trigger DELAY unit#3 */
                LRADC_DELAY_KICK |
                LRADC_DELAY_DELAY(lradc->settling_delay), LRADC_DELAY(2));
 }
@@ -850,7 +850,7 @@ static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val)
 
        /* Enable the IRQ and start sampling the channel. */
        mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1);
-       mxs_lradc_reg_set(lradc, 1 << 0, LRADC_CTRL0);
+       mxs_lradc_reg_set(lradc, BIT(0), LRADC_CTRL0);
 
        /* Wait for completion on the channel, 1 second max. */
        ret = wait_for_completion_killable_timeout(&lradc->completion, HZ);
@@ -993,7 +993,7 @@ static ssize_t mxs_lradc_show_scale_available_ch(struct device *dev,
        int i, len = 0;
 
        for (i = 0; i < ARRAY_SIZE(lradc->scale_avail[ch]); i++)
-               len += sprintf(buf + len, "%d.%09u ",
+               len += sprintf(buf + len, "%u.%09u ",
                               lradc->scale_avail[ch][i].integer,
                               lradc->scale_avail[ch][i].nano);
 
index 8ad71691fc090cf183f158291f8a352810a17075..c5382374ddf6903f37d248e2f69d8f4b4da4dbcd 100644 (file)
 #define SPEAR_ADC_CLK_HIGH(x)          (((x) & 0xf) << 4)
 
 /* Bit definitions for SPEAR_ADC_STATUS */
-#define SPEAR_ADC_STATUS_START_CONVERSION      (1 << 0)
+#define SPEAR_ADC_STATUS_START_CONVERSION      BIT(0)
 #define SPEAR_ADC_STATUS_CHANNEL_NUM(x)                ((x) << 1)
-#define SPEAR_ADC_STATUS_ADC_ENABLE            (1 << 4)
+#define SPEAR_ADC_STATUS_ADC_ENABLE            BIT(4)
 #define SPEAR_ADC_STATUS_AVG_SAMPLE(x)         ((x) << 5)
-#define SPEAR_ADC_STATUS_VREF_INTERNAL         (1 << 9)
+#define SPEAR_ADC_STATUS_VREF_INTERNAL         BIT(9)
 
 #define SPEAR_ADC_DATA_MASK            0x03ff
 #define SPEAR_ADC_DATA_BITS            10
index cf68159a584815aef3afdb73d24a7680ff3f8935..a861fe0149b1b3f8e706acece201d760942ba71f 100644 (file)
@@ -24,8 +24,8 @@
 
 static unsigned long ad9832_calc_freqreg(unsigned long mclk, unsigned long fout)
 {
-       unsigned long long freqreg = (u64) fout *
-                                    (u64) ((u64) 1L << AD9832_FREQ_BITS);
+       unsigned long long freqreg = (u64)fout *
+                                    (u64)((u64)1L << AD9832_FREQ_BITS);
        do_div(freqreg, mclk);
        return freqreg;
 }
@@ -59,7 +59,7 @@ static int ad9832_write_frequency(struct ad9832_state *st,
 static int ad9832_write_phase(struct ad9832_state *st,
                              unsigned long addr, unsigned long phase)
 {
-       if (phase > (1 << AD9832_PHASE_BITS))
+       if (phase > BIT(AD9832_PHASE_BITS))
                return -EINVAL;
 
        st->phase_data[0] = cpu_to_be16((AD9832_CMD_PHA8BITSW << CMD_SHIFT) |
@@ -86,7 +86,7 @@ static ssize_t ad9832_write(struct device *dev, struct device_attribute *attr,
                goto error_ret;
 
        mutex_lock(&indio_dev->mlock);
-       switch ((u32) this_attr->address) {
+       switch ((u32)this_attr->address) {
        case AD9832_FREQ0HM:
        case AD9832_FREQ1HM:
                ret = ad9832_write_frequency(st, this_attr->address, val);
@@ -220,7 +220,7 @@ static int ad9832_probe(struct spi_device *spi)
        }
 
        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
-       if (indio_dev == NULL) {
+       if (!indio_dev) {
                ret = -ENOMEM;
                goto error_disable_reg;
        }
index 386f4dc8c9a11bb9b7043019b8c3454b41fd64c3..d32323b46be68f70888de6de1852c1e15eaa387c 100644 (file)
 #define AD9832_CMD_SYNCSELSRC  0x8
 #define AD9832_CMD_SLEEPRESCLR 0xC
 
-#define AD9832_FREQ            (1 << 11)
+#define AD9832_FREQ            BIT(11)
 #define AD9832_PHASE(x)                (((x) & 3) << 9)
-#define AD9832_SYNC            (1 << 13)
-#define AD9832_SELSRC          (1 << 12)
-#define AD9832_SLEEP           (1 << 13)
-#define AD9832_RESET           (1 << 12)
-#define AD9832_CLR             (1 << 11)
+#define AD9832_SYNC            BIT(13)
+#define AD9832_SELSRC          BIT(12)
+#define AD9832_SLEEP           BIT(13)
+#define AD9832_RESET           BIT(12)
+#define AD9832_CLR             BIT(11)
 #define CMD_SHIFT              12
 #define ADD_SHIFT              8
 #define AD9832_FREQ_BITS       32
index 5c803191c2cea9a4ed9567d7e0799d7738b1884b..d02bb44fb8fc1bbec82882bf7a4910bc1b7f94c7 100644 (file)
@@ -27,7 +27,7 @@
 
 static unsigned int ad9834_calc_freqreg(unsigned long mclk, unsigned long fout)
 {
-       unsigned long long freqreg = (u64) fout * (u64) (1 << AD9834_FREQ_BITS);
+       unsigned long long freqreg = (u64)fout * (u64)BIT(AD9834_FREQ_BITS);
 
        do_div(freqreg, mclk);
        return freqreg;
@@ -53,9 +53,9 @@ static int ad9834_write_frequency(struct ad9834_state *st,
 }
 
 static int ad9834_write_phase(struct ad9834_state *st,
-                                 unsigned long addr, unsigned long phase)
+                             unsigned long addr, unsigned long phase)
 {
-       if (phase > (1 << AD9834_PHASE_BITS))
+       if (phase > BIT(AD9834_PHASE_BITS))
                return -EINVAL;
        st->data = cpu_to_be16(addr | phase);
 
@@ -63,9 +63,9 @@ static int ad9834_write_phase(struct ad9834_state *st,
 }
 
 static ssize_t ad9834_write(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t len)
+                           struct device_attribute *attr,
+                           const char *buf,
+                           size_t len)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct ad9834_state *st = iio_priv(indio_dev);
@@ -78,7 +78,7 @@ static ssize_t ad9834_write(struct device *dev,
                goto error_ret;
 
        mutex_lock(&indio_dev->mlock);
-       switch ((u32) this_attr->address) {
+       switch ((u32)this_attr->address) {
        case AD9834_REG_FREQ0:
        case AD9834_REG_FREQ1:
                ret = ad9834_write_frequency(st, this_attr->address, val);
@@ -111,9 +111,9 @@ static ssize_t ad9834_write(struct device *dev,
                break;
        case AD9834_FSEL:
        case AD9834_PSEL:
-               if (val == 0)
+               if (val == 0) {
                        st->control &= ~(this_attr->address | AD9834_PIN_SW);
-               else if (val == 1) {
+               else if (val == 1) {
                        st->control |= this_attr->address;
                        st->control &= ~AD9834_PIN_SW;
                } else {
@@ -142,9 +142,9 @@ error_ret:
 }
 
 static ssize_t ad9834_store_wavetype(struct device *dev,
-                                struct device_attribute *attr,
-                                const char *buf,
-                                size_t len)
+                                    struct device_attribute *attr,
+                                    const char *buf,
+                                    size_t len)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct ad9834_state *st = iio_priv(indio_dev);
@@ -154,7 +154,7 @@ static ssize_t ad9834_store_wavetype(struct device *dev,
 
        mutex_lock(&indio_dev->mlock);
 
-       switch ((u32) this_attr->address) {
+       switch ((u32)this_attr->address) {
        case 0:
                if (sysfs_streq(buf, "sine")) {
                        st->control &= ~AD9834_MODE;
@@ -179,7 +179,7 @@ static ssize_t ad9834_store_wavetype(struct device *dev,
                break;
        case 1:
                if (sysfs_streq(buf, "square") &&
-                       !(st->control & AD9834_MODE)) {
+                   !(st->control & AD9834_MODE)) {
                        st->control &= ~AD9834_MODE;
                        st->control |= AD9834_OPBITEN;
                } else {
@@ -200,9 +200,10 @@ static ssize_t ad9834_store_wavetype(struct device *dev,
        return ret ? ret : len;
 }
 
-static ssize_t ad9834_show_out0_wavetype_available(struct device *dev,
-                                               struct device_attribute *attr,
-                                               char *buf)
+static
+ssize_t ad9834_show_out0_wavetype_available(struct device *dev,
+                                           struct device_attribute *attr,
+                                           char *buf)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct ad9834_state *st = iio_priv(indio_dev);
@@ -218,13 +219,13 @@ static ssize_t ad9834_show_out0_wavetype_available(struct device *dev,
        return sprintf(buf, "%s\n", str);
 }
 
-
 static IIO_DEVICE_ATTR(out_altvoltage0_out0_wavetype_available, S_IRUGO,
                       ad9834_show_out0_wavetype_available, NULL, 0);
 
-static ssize_t ad9834_show_out1_wavetype_available(struct device *dev,
-                                               struct device_attribute *attr,
-                                               char *buf)
+static
+ssize_t ad9834_show_out1_wavetype_available(struct device *dev,
+                                           struct device_attribute *attr,
+                                           char *buf)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct ad9834_state *st = iio_priv(indio_dev);
@@ -336,7 +337,7 @@ static int ad9834_probe(struct spi_device *spi)
        }
 
        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
-       if (indio_dev == NULL) {
+       if (!indio_dev) {
                ret = -ENOMEM;
                goto error_disable_reg;
        }
index 8ca6e52bae6ba67fa7dd7b65b110dc1f57029221..40fdd5da7bd0038fc1ff3d43676d377798084283 100644 (file)
 
 /* Registers */
 
-#define AD9834_REG_CMD         (0 << 14)
-#define AD9834_REG_FREQ0       (1 << 14)
-#define AD9834_REG_FREQ1       (2 << 14)
-#define AD9834_REG_PHASE0      (6 << 13)
-#define AD9834_REG_PHASE1      (7 << 13)
+#define AD9834_REG_CMD         0
+#define AD9834_REG_FREQ0       BIT(14)
+#define AD9834_REG_FREQ1       BIT(15)
+#define AD9834_REG_PHASE0      (BIT(15) | BIT(14))
+#define AD9834_REG_PHASE1      (BIT(15) | BIT(14) | BIT(13))
 
 /* Command Control Bits */
 
-#define AD9834_B28             (1 << 13)
-#define AD9834_HLB             (1 << 12)
-#define AD9834_FSEL            (1 << 11)
-#define AD9834_PSEL            (1 << 10)
-#define AD9834_PIN_SW          (1 << 9)
-#define AD9834_RESET           (1 << 8)
-#define AD9834_SLEEP1          (1 << 7)
-#define AD9834_SLEEP12         (1 << 6)
-#define AD9834_OPBITEN         (1 << 5)
-#define AD9834_SIGN_PIB                (1 << 4)
-#define AD9834_DIV2            (1 << 3)
-#define AD9834_MODE            (1 << 1)
+#define AD9834_B28             BIT(13)
+#define AD9834_HLB             BIT(12)
+#define AD9834_FSEL            BIT(11)
+#define AD9834_PSEL            BIT(10)
+#define AD9834_PIN_SW          BIT(9)
+#define AD9834_RESET           BIT(8)
+#define AD9834_SLEEP1          BIT(7)
+#define AD9834_SLEEP12         BIT(6)
+#define AD9834_OPBITEN         BIT(5)
+#define AD9834_SIGN_PIB                BIT(4)
+#define AD9834_DIV2            BIT(3)
+#define AD9834_MODE            BIT(1)
 
 #define AD9834_FREQ_BITS       28
 #define AD9834_PHASE_BITS      12
 
-#define RES_MASK(bits) ((1 << (bits)) - 1)
+#define RES_MASK(bits) (BIT(bits) - 1)
 
 /**
  * struct ad9834_state - driver instance specific data
@@ -69,7 +69,6 @@ struct ad9834_state {
        __be16                          freq_data[2];
 };
 
-
 /*
  * TODO: struct ad7887_platform_data needs to go into include/linux/iio
  */
index 611e2b0cfc4cde3614080f07ff8018fd2dbb702f..fe53e7324c9458fb64d69b85b80e0d18b85474c0 100644 (file)
@@ -5,6 +5,8 @@
  *
  * Licensed under the GPL-2 or later.
  */
+#ifndef IIO_DDS_H_
+#define IIO_DDS_H_
 
 /**
  * /sys/bus/iio/devices/.../out_altvoltageX_frequencyY
 #define IIO_CONST_ATTR_OUT_WAVETYPES_AVAILABLE(_channel, _output, _modes)\
        IIO_CONST_ATTR(                                                 \
        out_altvoltage##_channel##_out##_output##_wavetype_available, _modes)
+
+#endif /* IIO_DDS_H_ */
index 59ad5a3efe9cb3cf1a7a1f2e8fcab693421d64c4..0c9c86d7b5095b96a6248aff0d045bd3f3206008 100644 (file)
@@ -72,7 +72,7 @@ static int iio_dummy_evgen_create(void)
        int ret, i;
 
        iio_evgen = kzalloc(sizeof(*iio_evgen), GFP_KERNEL);
-       if (iio_evgen == NULL)
+       if (!iio_evgen)
                return -ENOMEM;
 
        iio_evgen->base = irq_alloc_descs(-1, 0, IIO_EVENTGEN_NO, 0);
@@ -105,7 +105,7 @@ int iio_dummy_evgen_get_irq(void)
 {
        int i, ret = 0;
 
-       if (iio_evgen == NULL)
+       if (!iio_evgen)
                return -ENODEV;
 
        mutex_lock(&iio_evgen->lock);
index e4520213f627fe431597817ac8c4099bde40f1c4..b47bf9fb64be02fd2ad7cf4b3f8b428e52cf4999 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -589,7 +588,7 @@ static int iio_dummy_probe(int index)
         * for chip specific state information.
         */
        indio_dev = iio_device_alloc(sizeof(*st));
-       if (indio_dev == NULL) {
+       if (!indio_dev) {
                ret = -ENOMEM;
                goto error_ret;
        }
index 360a4c980722267d8dc2dba1f7288fbbd7666376..a651b8922d0a93039eb8ef6c71a35e7dd9ea0f48 100644 (file)
@@ -50,7 +50,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
        u16 *data;
 
        data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-       if (data == NULL)
+       if (!data)
                goto done;
 
        if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) {
@@ -122,7 +122,7 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev)
 
        /* Allocate a buffer to use - here a kfifo */
        buffer = iio_kfifo_allocate();
-       if (buffer == NULL) {
+       if (!buffer) {
                ret = -ENOMEM;
                goto error_ret;
        }
@@ -161,7 +161,7 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev)
                                                 "iio_simple_dummy_consumer%d",
                                                 indio_dev->id);
 
-       if (indio_dev->pollfunc == NULL) {
+       if (!indio_dev->pollfunc) {
                ret = -ENOMEM;
                goto error_free_buffer;
        }
index 79194399e0404fae6a4e3ea7dee42dd78f5918d6..c18109c55497087076df8f780fe81c1270524676 100644 (file)
@@ -703,7 +703,7 @@ static int ad5933_probe(struct i2c_client *client,
        struct iio_dev *indio_dev;
 
        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
-       if (indio_dev == NULL)
+       if (!indio_dev)
                return -ENOMEM;
 
        st = iio_priv(indio_dev);
index 6440e3b293ca53201714b57ea590a5f397368abf..e5b2fdc2334b71792355b718b209606be04c73f6 100644 (file)
@@ -441,15 +441,15 @@ static int isl29028_chip_init(struct isl29028_chip *chip)
 
        ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling);
        if (ret < 0) {
-               dev_err(chip->dev, "%s(): setting the proximity, err = %d\n",
-                       __func__, ret);
+               dev_err(chip->dev, "setting the proximity, err = %d\n",
+                       ret);
                return ret;
        }
 
        ret = isl29028_set_als_scale(chip, chip->lux_scale);
        if (ret < 0)
-               dev_err(chip->dev, "%s(): setting als scale failed, err = %d\n",
-                       __func__, ret);
+               dev_err(chip->dev,
+                       "setting als scale failed, err = %d\n", ret);
        return ret;
 }
 
index 8afae8e33d56e0fcd32f81d862ad5a60ba56870d..b5e1b8b0a6f0db24d7a5da3f1e51d2dbc2cc50ce 100644 (file)
@@ -471,14 +471,12 @@ static int taos_chip_on(struct iio_dev *indio_dev)
 static int taos_chip_off(struct iio_dev *indio_dev)
 {
        struct tsl2583_chip *chip = iio_priv(indio_dev);
-       int ret;
 
        /* turn device off */
        chip->taos_chip_status = TSL258X_CHIP_SUSPENDED;
-       ret = i2c_smbus_write_byte_data(chip->client,
+       return i2c_smbus_write_byte_data(chip->client,
                                        TSL258X_CMD_REG | TSL258X_CNTRL,
                                        0x00);
-       return ret;
 }
 
 /* Sysfs Interface Functions */
index 4a5dc26fed4c2a20078a48061d45108e16db23b2..010e607dd8804fb1f74ef56fc8c3555cc66af22e 100644 (file)
@@ -301,8 +301,7 @@ tsl2x7x_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
        /* select register to write */
        ret = i2c_smbus_write_byte(client, (TSL2X7X_CMD_REG | reg));
        if (ret < 0) {
-               dev_err(&client->dev, "%s: failed to write register %x\n"
-                               , __func__, reg);
+               dev_err(&client->dev, "failed to write register %x\n", reg);
                return ret;
        }
 
@@ -311,8 +310,7 @@ tsl2x7x_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
        if (ret >= 0)
                *val = (u8)ret;
        else
-               dev_err(&client->dev, "%s: failed to read register %x\n"
-                                               , __func__, reg);
+               dev_err(&client->dev, "failed to read register %x\n", reg);
 
        return ret;
 }
@@ -377,7 +375,7 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev)
                        &buf[i]);
                if (ret < 0) {
                        dev_err(&chip->client->dev,
-                               "%s: failed to read. err=%x\n", __func__, ret);
+                               "failed to read. err=%x\n", ret);
                        goto out_unlock;
                }
        }
@@ -389,8 +387,7 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev)
                                TSL2X7X_CMD_ALS_INT_CLR));
        if (ret < 0) {
                dev_err(&chip->client->dev,
-               "%s: i2c_write_command failed - err = %d\n",
-                       __func__, ret);
+                       "i2c_write_command failed - err = %d\n", ret);
                goto out_unlock; /* have no data, so return failure */
        }
 
@@ -493,8 +490,7 @@ static int tsl2x7x_get_prox(struct iio_dev *indio_dev)
        ret = tsl2x7x_i2c_read(chip->client,
                (TSL2X7X_CMD_REG | TSL2X7X_STATUS), &status);
        if (ret < 0) {
-               dev_err(&chip->client->dev,
-               "%s: i2c err=%d\n", __func__, ret);
+               dev_err(&chip->client->dev, "i2c err=%d\n", ret);
                goto prox_poll_err;
        }
 
@@ -583,8 +579,7 @@ static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev)
                        (TSL2X7X_CMD_REG | TSL2X7X_CNTRL));
        if (ret < 0) {
                dev_err(&chip->client->dev,
-               "%s: failed to write CNTRL register, ret=%d\n",
-               __func__, ret);
+                       "failed to write CNTRL register, ret=%d\n", ret);
                return ret;
        }
 
@@ -600,8 +595,7 @@ static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev)
                        (TSL2X7X_CMD_REG | TSL2X7X_CNTRL));
        if (ret < 0) {
                dev_err(&chip->client->dev,
-                       "%s: failed to write ctrl reg: ret=%d\n",
-                       __func__, ret);
+                       "failed to write ctrl reg: ret=%d\n", ret);
                return ret;
        }
 
@@ -619,8 +613,8 @@ static int tsl2x7x_als_calibrate(struct iio_dev *indio_dev)
                return lux_val;
        }
 
-       gain_trim_val =  (((chip->tsl2x7x_settings.als_cal_target)
-                       * chip->tsl2x7x_settings.als_gain_trim) / lux_val);
+       gain_trim_val =  ((chip->tsl2x7x_settings.als_cal_target)
+                       * chip->tsl2x7x_settings.als_gain_trim) / lux_val;
        if ((gain_trim_val < 250) || (gain_trim_val > 4000))
                return -ERANGE;
 
@@ -720,7 +714,7 @@ static int tsl2x7x_chip_on(struct iio_dev *indio_dev)
                                TSL2X7X_CMD_REG + i, *dev_reg++);
                if (ret < 0) {
                        dev_err(&chip->client->dev,
-                       "%s: failed on write to reg %d.\n", __func__, i);
+                               "failed on write to reg %d.\n", i);
                        return ret;
                }
        }
@@ -871,8 +865,8 @@ static void tsl2x7x_prox_cal(struct iio_dev *indio_dev)
 
        if (chip->tsl2x7x_settings.prox_max_samples_cal > MAX_SAMPLES_CAL) {
                dev_err(&chip->client->dev,
-                       "%s: max prox samples cal is too big: %d\n",
-                       __func__, chip->tsl2x7x_settings.prox_max_samples_cal);
+                       "max prox samples cal is too big: %d\n",
+                       chip->tsl2x7x_settings.prox_max_samples_cal);
                chip->tsl2x7x_settings.prox_max_samples_cal = MAX_SAMPLES_CAL;
        }
 
@@ -1563,8 +1557,8 @@ static irqreturn_t tsl2x7x_event_handler(int irq, void *private)
                TSL2X7X_CMD_PROXALS_INT_CLR);
        if (ret < 0)
                dev_err(&chip->client->dev,
-                       "%s: Failed to clear irq from event handler. err = %d\n",
-                       __func__, ret);
+                       "Failed to clear irq from event handler. err = %d\n",
+                       ret);
 
        return IRQ_HANDLED;
 }
@@ -1893,8 +1887,8 @@ static int tsl2x7x_probe(struct i2c_client *clientp,
 
        ret = i2c_smbus_write_byte(clientp, (TSL2X7X_CMD_REG | TSL2X7X_CNTRL));
        if (ret < 0) {
-               dev_err(&clientp->dev, "%s: write to cmd reg failed. err = %d\n",
-                               __func__, ret);
+               dev_err(&clientp->dev, "write to cmd reg failed. err = %d\n",
+                       ret);
                return ret;
        }
 
index b784e3eb4591edec159129f709f5a72672bfe460..f3d0da2fe4589c29c9ff318cb64555f05ab46e1a 100644 (file)
@@ -10,7 +10,6 @@
  *
  * */
 
-
 #ifndef HMC5843_CORE_H
 #define HMC5843_CORE_H
 
@@ -32,16 +31,24 @@ enum hmc5843_ids {
        HMC5983_ID,
 };
 
+/**
+ * struct hcm5843_data - device specific data
+ * @dev:               actual device
+ * @lock:              update and read regmap data
+ * @regmap:            hardware access register maps
+ * @variant:           describe chip variants
+ * @buffer:            3x 16-bit channels + padding + 64-bit timestamp
+ **/
 struct hmc5843_data {
        struct device *dev;
        struct mutex lock;
        struct regmap *regmap;
        const struct hmc5843_chip_info *variant;
-       __be16 buffer[8]; /* 3x 16-bit channels + padding + 64-bit timestamp */
+       __be16 buffer[8];
 };
 
 int hmc5843_common_probe(struct device *dev, struct regmap *regmap,
-               enum hmc5843_ids id);
+                        enum hmc5843_ids id);
 int hmc5843_common_remove(struct device *dev);
 
 int hmc5843_common_suspend(struct device *dev);
index 90cc18b703cf67ae6c089c36d51d8ebde6f28106..fffca3a9f637b868b00ec57126b84f4c72c64d7e 100644 (file)
@@ -1,25 +1,25 @@
-/*  Copyright (C) 2010 Texas Instruments
-    Author: Shubhrajyoti Datta <shubhrajyoti@ti.com>
   Acknowledgement: Jonathan Cameron <jic23@kernel.org> for valuable inputs.
-
-    Support for HMC5883 and HMC5883L by Peter Meerwald <pmeerw@pmeerw.net>.
-
-    Split to multiple files by Josef Gajdusek <atx@atx.name> - 2014
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
   You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+/*
+ * Device driver for the the HMC5843 multi-chip module designed
* for low field magnetic sensing.
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * Author: Shubhrajyoti Datta <shubhrajyoti@ti.com>
+ * Acknowledgment: Jonathan Cameron <jic23@kernel.org> for valuable inputs.
+ * Support for HMC5883 and HMC5883L by Peter Meerwald <pmeerw@pmeerw.net>.
+ * Split to multiple files by Josef Gajdusek <atx@atx.name> - 2014
+ *
+ * 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/regmap.h>
@@ -122,7 +122,7 @@ static s32 hmc5843_set_mode(struct hmc5843_data *data, u8 operating_mode)
 
        mutex_lock(&data->lock);
        ret = regmap_update_bits(data->regmap, HMC5843_MODE_REG,
-                       HMC5843_MODE_MASK, operating_mode);
+                                HMC5843_MODE_MASK, operating_mode);
        mutex_unlock(&data->lock);
 
        return ret;
@@ -165,7 +165,7 @@ static int hmc5843_read_measurement(struct hmc5843_data *data,
                return ret;
        }
        ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS,
-                       values, sizeof(values));
+                              values, sizeof(values));
        mutex_unlock(&data->lock);
        if (ret < 0)
                return ret;
@@ -198,15 +198,16 @@ static int hmc5843_set_meas_conf(struct hmc5843_data *data, u8 meas_conf)
 
        mutex_lock(&data->lock);
        ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_A,
-                       HMC5843_MEAS_CONF_MASK, meas_conf);
+                                HMC5843_MEAS_CONF_MASK, meas_conf);
        mutex_unlock(&data->lock);
 
        return ret;
 }
 
-static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
-                                               struct device_attribute *attr,
-                                               char *buf)
+static
+ssize_t hmc5843_show_measurement_configuration(struct device *dev,
+                                              struct device_attribute *attr,
+                                              char *buf)
 {
        struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
        unsigned int val;
@@ -220,10 +221,11 @@ static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
        return sprintf(buf, "%d\n", val);
 }
 
-static ssize_t hmc5843_set_measurement_configuration(struct device *dev,
-                                               struct device_attribute *attr,
-                                               const char *buf,
-                                               size_t count)
+static
+ssize_t hmc5843_set_measurement_configuration(struct device *dev,
+                                             struct device_attribute *attr,
+                                             const char *buf,
+                                             size_t count)
 {
        struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
        unsigned long meas_conf = 0;
@@ -246,8 +248,9 @@ static IIO_DEVICE_ATTR(meas_conf,
                        hmc5843_set_measurement_configuration,
                        0);
 
-static ssize_t hmc5843_show_samp_freq_avail(struct device *dev,
-                               struct device_attribute *attr, char *buf)
+static
+ssize_t hmc5843_show_samp_freq_avail(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
 {
        struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
        size_t len = 0;
@@ -272,20 +275,21 @@ static int hmc5843_set_samp_freq(struct hmc5843_data *data, u8 rate)
 
        mutex_lock(&data->lock);
        ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_A,
-                       HMC5843_RATE_MASK, rate << HMC5843_RATE_OFFSET);
+                                HMC5843_RATE_MASK,
+                                rate << HMC5843_RATE_OFFSET);
        mutex_unlock(&data->lock);
 
        return ret;
 }
 
 static int hmc5843_get_samp_freq_index(struct hmc5843_data *data,
-                                  int val, int val2)
+                                      int val, int val2)
 {
        int i;
 
        for (i = 0; i < data->variant->n_regval_to_samp_freq; i++)
                if (val == data->variant->regval_to_samp_freq[i][0] &&
-                       val2 == data->variant->regval_to_samp_freq[i][1])
+                   val2 == data->variant->regval_to_samp_freq[i][1])
                        return i;
 
        return -EINVAL;
@@ -297,15 +301,16 @@ static int hmc5843_set_range_gain(struct hmc5843_data *data, u8 range)
 
        mutex_lock(&data->lock);
        ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_B,
-                       HMC5843_RANGE_GAIN_MASK,
-                       range << HMC5843_RANGE_GAIN_OFFSET);
+                                HMC5843_RANGE_GAIN_MASK,
+                                range << HMC5843_RANGE_GAIN_OFFSET);
        mutex_unlock(&data->lock);
 
        return ret;
 }
 
 static ssize_t hmc5843_show_scale_avail(struct device *dev,
-                               struct device_attribute *attr, char *buf)
+                                       struct device_attribute *attr,
+                                       char *buf)
 {
        struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
 
@@ -396,7 +401,8 @@ static int hmc5843_write_raw(struct iio_dev *indio_dev,
 }
 
 static int hmc5843_write_raw_get_fmt(struct iio_dev *indio_dev,
-                              struct iio_chan_spec const *chan, long mask)
+                                    struct iio_chan_spec const *chan,
+                                    long mask)
 {
        switch (mask) {
        case IIO_CHAN_INFO_SAMP_FREQ:
@@ -423,14 +429,14 @@ static irqreturn_t hmc5843_trigger_handler(int irq, void *p)
        }
 
        ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS,
-                       data->buffer, 3 * sizeof(__be16));
+                              data->buffer, 3 * sizeof(__be16));
 
        mutex_unlock(&data->lock);
        if (ret < 0)
                goto done;
 
        iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
-               iio_get_time_ns());
+                                          iio_get_time_ns());
 
 done:
        iio_trigger_notify_done(indio_dev->trig);
@@ -526,7 +532,7 @@ static int hmc5843_init(struct hmc5843_data *data)
        u8 id[3];
 
        ret = regmap_bulk_read(data->regmap, HMC5843_ID_REG,
-                       id, ARRAY_SIZE(id));
+                              id, ARRAY_SIZE(id));
        if (ret < 0)
                return ret;
        if (id[0] != 'H' || id[1] != '4' || id[2] != '3') {
@@ -556,7 +562,6 @@ static const struct iio_info hmc5843_info = {
 
 static const unsigned long hmc5843_scan_masks[] = {0x7, 0};
 
-
 int hmc5843_common_suspend(struct device *dev)
 {
        return hmc5843_set_mode(iio_priv(dev_get_drvdata(dev)),
@@ -567,19 +572,19 @@ EXPORT_SYMBOL(hmc5843_common_suspend);
 int hmc5843_common_resume(struct device *dev)
 {
        return hmc5843_set_mode(iio_priv(dev_get_drvdata(dev)),
-                       HMC5843_MODE_SLEEP);
+                               HMC5843_MODE_SLEEP);
 }
 EXPORT_SYMBOL(hmc5843_common_resume);
 
 int hmc5843_common_probe(struct device *dev, struct regmap *regmap,
-               enum hmc5843_ids id)
+                        enum hmc5843_ids id)
 {
        struct hmc5843_data *data;
        struct iio_dev *indio_dev;
        int ret;
 
        indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
-       if (indio_dev == NULL)
+       if (!indio_dev)
                return -ENOMEM;
 
        dev_set_drvdata(dev, indio_dev);
@@ -604,9 +609,9 @@ int hmc5843_common_probe(struct device *dev, struct regmap *regmap,
                return ret;
 
        ret = iio_triggered_buffer_setup(indio_dev, NULL,
-               hmc5843_trigger_handler, NULL);
+                                        hmc5843_trigger_handler, NULL);
        if (ret < 0)
-               return ret;
+               goto buffer_setup_err;
 
        ret = iio_device_register(indio_dev);
        if (ret < 0)
@@ -616,6 +621,8 @@ int hmc5843_common_probe(struct device *dev, struct regmap *regmap,
 
 buffer_cleanup:
        iio_triggered_buffer_cleanup(indio_dev);
+buffer_setup_err:
+       hmc5843_set_mode(iio_priv(indio_dev), HMC5843_MODE_SLEEP);
        return ret;
 }
 EXPORT_SYMBOL(hmc5843_common_probe);
index 6acd614cdbc6529ae22d4df7c53548f1e3852455..ff08667fa2f60071ab6a5dd800830db2ae03b224 100644 (file)
 #include "hmc5843.h"
 
 static const struct regmap_range hmc5843_readable_ranges[] = {
-               regmap_reg_range(0, HMC5843_ID_END),
+       regmap_reg_range(0, HMC5843_ID_END),
 };
 
-static struct regmap_access_table hmc5843_readable_table = {
-               .yes_ranges = hmc5843_readable_ranges,
-               .n_yes_ranges = ARRAY_SIZE(hmc5843_readable_ranges),
+static const struct regmap_access_table hmc5843_readable_table = {
+       .yes_ranges = hmc5843_readable_ranges,
+       .n_yes_ranges = ARRAY_SIZE(hmc5843_readable_ranges),
 };
 
 static const struct regmap_range hmc5843_writable_ranges[] = {
-               regmap_reg_range(0, HMC5843_MODE_REG),
+       regmap_reg_range(0, HMC5843_MODE_REG),
 };
 
-static struct regmap_access_table hmc5843_writable_table = {
-               .yes_ranges = hmc5843_writable_ranges,
-               .n_yes_ranges = ARRAY_SIZE(hmc5843_writable_ranges),
+static const struct regmap_access_table hmc5843_writable_table = {
+       .yes_ranges = hmc5843_writable_ranges,
+       .n_yes_ranges = ARRAY_SIZE(hmc5843_writable_ranges),
 };
 
 static const struct regmap_range hmc5843_volatile_ranges[] = {
-               regmap_reg_range(HMC5843_DATA_OUT_MSB_REGS, HMC5843_STATUS_REG),
+       regmap_reg_range(HMC5843_DATA_OUT_MSB_REGS, HMC5843_STATUS_REG),
 };
 
-static struct regmap_access_table hmc5843_volatile_table = {
-               .yes_ranges = hmc5843_volatile_ranges,
-               .n_yes_ranges = ARRAY_SIZE(hmc5843_volatile_ranges),
+static const struct regmap_access_table hmc5843_volatile_table = {
+       .yes_ranges = hmc5843_volatile_ranges,
+       .n_yes_ranges = ARRAY_SIZE(hmc5843_volatile_ranges),
 };
 
-static struct regmap_config hmc5843_i2c_regmap_config = {
-               .reg_bits = 8,
-               .val_bits = 8,
+static const struct regmap_config hmc5843_i2c_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
 
-               .rd_table = &hmc5843_readable_table,
-               .wr_table = &hmc5843_writable_table,
-               .volatile_table = &hmc5843_volatile_table,
+       .rd_table = &hmc5843_readable_table,
+       .wr_table = &hmc5843_writable_table,
+       .volatile_table = &hmc5843_volatile_table,
 
-               .cache_type = REGCACHE_RBTREE,
+       .cache_type = REGCACHE_RBTREE,
 };
 
-static int hmc5843_i2c_probe(struct i2c_client *client,
-                        const struct i2c_device_id *id)
+static int hmc5843_i2c_probe(struct i2c_client *cli,
+                            const struct i2c_device_id *id)
 {
-       return hmc5843_common_probe(&client->dev,
-                       devm_regmap_init_i2c(client, &hmc5843_i2c_regmap_config),
+       return hmc5843_common_probe(&cli->dev,
+                       devm_regmap_init_i2c(cli, &hmc5843_i2c_regmap_config),
                        id->driver_data);
 }
 
index 98c4b57101c9d91bc494fb209a416d3dd37d5fc8..8e658f736e1f6278d33eb13ec3ae256e1ad2c1d7 100644 (file)
@@ -19,7 +19,7 @@ static const struct regmap_range hmc5843_readable_ranges[] = {
                regmap_reg_range(0, HMC5843_ID_END),
 };
 
-static struct regmap_access_table hmc5843_readable_table = {
+static const struct regmap_access_table hmc5843_readable_table = {
                .yes_ranges = hmc5843_readable_ranges,
                .n_yes_ranges = ARRAY_SIZE(hmc5843_readable_ranges),
 };
@@ -28,7 +28,7 @@ static const struct regmap_range hmc5843_writable_ranges[] = {
                regmap_reg_range(0, HMC5843_MODE_REG),
 };
 
-static struct regmap_access_table hmc5843_writable_table = {
+static const struct regmap_access_table hmc5843_writable_table = {
                .yes_ranges = hmc5843_writable_ranges,
                .n_yes_ranges = ARRAY_SIZE(hmc5843_writable_ranges),
 };
@@ -37,12 +37,12 @@ static const struct regmap_range hmc5843_volatile_ranges[] = {
                regmap_reg_range(HMC5843_DATA_OUT_MSB_REGS, HMC5843_STATUS_REG),
 };
 
-static struct regmap_access_table hmc5843_volatile_table = {
+static const struct regmap_access_table hmc5843_volatile_table = {
                .yes_ranges = hmc5843_volatile_ranges,
                .n_yes_ranges = ARRAY_SIZE(hmc5843_volatile_ranges),
 };
 
-static struct regmap_config hmc5843_spi_regmap_config = {
+static const struct regmap_config hmc5843_spi_regmap_config = {
                .reg_bits = 8,
                .val_bits = 8,
 
index 78e8f560eeec564aa19e94fb5e1f103b76236b4c..ffc7f0ddff14c7cc24eee0c109b6f6beefa1a928 100644 (file)
@@ -411,7 +411,7 @@ static ssize_t ade7753_write_frequency(struct device *dev,
 
        mutex_lock(&indio_dev->mlock);
 
-       t = (27900 / val);
+       t = 27900 / val;
        if (t > 0)
                t--;
 
@@ -517,11 +517,7 @@ static int ade7753_probe(struct spi_device *spi)
        if (ret)
                return ret;
 
-       ret = iio_device_register(indio_dev);
-       if (ret)
-               return ret;
-
-       return 0;
+       return iio_device_register(indio_dev);
 }
 
 /* fixme, confirm ordering in this function */
index 81f67318974ad77322c3f66138f25d3385463af9..f12b2e50329b6a209af4e95cebaa10a8722ad74b 100644 (file)
@@ -216,9 +216,13 @@ error_ret:
 
 static int ade7754_reset(struct device *dev)
 {
+       int ret;
        u8 val;
 
-       ade7754_spi_read_reg_8(dev, ADE7754_OPMODE, &val);
+       ret = ade7754_spi_read_reg_8(dev, ADE7754_OPMODE, &val);
+       if (ret < 0)
+               return ret;
+
        val |= 1 << 6; /* Software Chip Reset */
        return ade7754_spi_write_reg_8(dev, ADE7754_OPMODE, val);
 }
@@ -362,9 +366,16 @@ error_ret:
 /* Power down the device */
 static int ade7754_stop_device(struct device *dev)
 {
+       int ret;
        u8 val;
 
-       ade7754_spi_read_reg_8(dev, ADE7754_OPMODE, &val);
+       ret = ade7754_spi_read_reg_8(dev, ADE7754_OPMODE, &val);
+       if (ret < 0) {
+               dev_err(dev, "unable to power down the device, error: %d",
+                       ret);
+               return ret;
+       }
+
        val |= 7 << 3;  /* ADE7754 powered down */
        return ade7754_spi_write_reg_8(dev, ADE7754_OPMODE, val);
 }
@@ -432,7 +443,7 @@ static ssize_t ade7754_write_frequency(struct device *dev,
 
        mutex_lock(&indio_dev->mlock);
 
-       t = (26000 / val);
+       t = 26000 / val;
        if (t > 0)
                t--;
 
@@ -539,12 +550,15 @@ static int ade7754_probe(struct spi_device *spi)
        /* Get the device into a sane initial state */
        ret = ade7754_initial_setup(indio_dev);
        if (ret)
-               return ret;
+               goto powerdown_on_error;
        ret = iio_device_register(indio_dev);
        if (ret)
-               return ret;
+               goto powerdown_on_error;
+       return ret;
 
-       return 0;
+powerdown_on_error:
+       ade7754_stop_device(&indio_dev->dev);
+       return ret;
 }
 
 /* fixme, confirm ordering in this function */
index 70e96b20c2ebfbc8f57e6f280ddc4a9989bffce3..77141ae1349dfdb9e359d1976254ddc351b110a6 100644 (file)
@@ -303,14 +303,15 @@ static int ade7758_reset(struct device *dev)
        int ret;
        u8 val;
 
-       ade7758_spi_read_reg_8(dev,
-                       ADE7758_OPMODE,
-                       &val);
+       ret = ade7758_spi_read_reg_8(dev, ADE7758_OPMODE, &val);
+       if (ret < 0) {
+               dev_err(dev, "Failed to read opmode reg\n");
+               return ret;
+       }
        val |= 1 << 6; /* Software Chip Reset */
-       ret = ade7758_spi_write_reg_8(dev,
-                       ADE7758_OPMODE,
-                       val);
-
+       ret = ade7758_spi_write_reg_8(dev, ADE7758_OPMODE, val);
+       if (ret < 0)
+               dev_err(dev, "Failed to write opmode reg\n");
        return ret;
 }
 
@@ -444,14 +445,15 @@ static int ade7758_stop_device(struct device *dev)
        int ret;
        u8 val;
 
-       ade7758_spi_read_reg_8(dev,
-                       ADE7758_OPMODE,
-                       &val);
+       ret = ade7758_spi_read_reg_8(dev, ADE7758_OPMODE, &val);
+       if (ret < 0) {
+               dev_err(dev, "Failed to read opmode reg\n");
+               return ret;
+       }
        val |= 7 << 3;  /* ADE7758 powered down */
-       ret = ade7758_spi_write_reg_8(dev,
-                       ADE7758_OPMODE,
-                       val);
-
+       ret = ade7758_spi_write_reg_8(dev, ADE7758_OPMODE, val);
+       if (ret < 0)
+               dev_err(dev, "Failed to write opmode reg\n");
        return ret;
 }
 
@@ -483,7 +485,7 @@ static ssize_t ade7758_read_frequency(struct device *dev,
                struct device_attribute *attr,
                char *buf)
 {
-       int ret, len = 0;
+       int ret;
        u8 t;
        int sps;
 
@@ -496,8 +498,7 @@ static ssize_t ade7758_read_frequency(struct device *dev,
        t = (t >> 5) & 0x3;
        sps = 26040 / (1 << t);
 
-       len = sprintf(buf, "%d SPS\n", sps);
-       return len;
+       return sprintf(buf, "%d SPS\n", sps);
 }
 
 static ssize_t ade7758_write_frequency(struct device *dev,
@@ -832,7 +833,7 @@ static int ade7758_probe(struct spi_device *spi)
        if (!st->rx)
                return -ENOMEM;
        st->tx = kcalloc(ADE7758_MAX_TX, sizeof(*st->tx), GFP_KERNEL);
-       if (st->tx == NULL) {
+       if (!st->tx) {
                ret = -ENOMEM;
                goto error_free_rx;
        }
index 3792b57616456c99c55ac6a35cb7b8adc97671dc..9a24e0226f8baba43153801fae7df9292b266a1d 100644 (file)
@@ -119,10 +119,8 @@ int ade7758_configure_ring(struct iio_dev *indio_dev)
        int ret = 0;
 
        buffer = iio_kfifo_allocate();
-       if (!buffer) {
-               ret = -ENOMEM;
-               return ret;
-       }
+       if (!buffer)
+               return -ENOMEM;
 
        iio_device_attach_buffer(indio_dev, buffer);
 
@@ -134,7 +132,7 @@ int ade7758_configure_ring(struct iio_dev *indio_dev)
                                                 indio_dev,
                                                 "ade7759_consumer%d",
                                                 indio_dev->id);
-       if (indio_dev->pollfunc == NULL) {
+       if (!indio_dev->pollfunc) {
                ret = -ENOMEM;
                goto error_iio_kfifo_free;
        }
index 6f45ce0478d760bd80aee3f2551ee12a7af2be76..5b35a7f08f4f7588803b1255d4c7748a11b6ed84 100644 (file)
@@ -66,7 +66,7 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev)
        st->trig = iio_trigger_alloc("%s-dev%d",
                                        spi_get_device_id(st->us)->name,
                                        indio_dev->id);
-       if (st->trig == NULL) {
+       if (!st->trig) {
                ret = -ENOMEM;
                goto error_ret;
        }
index b0c7dbc8a4283c88de229bc2332676a82412e9a5..dbceda1e67eaba530687b131bdfddb014d86181d 100644 (file)
@@ -218,15 +218,16 @@ static int ade7759_reset(struct device *dev)
        int ret;
        u16 val;
 
-       ade7759_spi_read_reg_16(dev,
+       ret = ade7759_spi_read_reg_16(dev,
                        ADE7759_MODE,
                        &val);
+       if (ret < 0)
+               return ret;
+
        val |= 1 << 6; /* Software Chip Reset */
-       ret = ade7759_spi_write_reg_16(dev,
+       return ade7759_spi_write_reg_16(dev,
                        ADE7759_MODE,
                        val);
-
-       return ret;
 }
 
 static IIO_DEV_ATTR_AENERGY(ade7759_read_40bit, ADE7759_AENERGY);
@@ -301,11 +302,18 @@ error_ret:
 /* Power down the device */
 static int ade7759_stop_device(struct device *dev)
 {
+       int ret;
        u16 val;
 
-       ade7759_spi_read_reg_16(dev,
+       ret = ade7759_spi_read_reg_16(dev,
                        ADE7759_MODE,
                        &val);
+       if (ret < 0) {
+               dev_err(dev, "unable to power down the device, error: %d\n",
+                       ret);
+               return ret;
+       }
+
        val |= 1 << 4;  /* AD converters can be turned off */
 
        return ade7759_spi_write_reg_16(dev, ADE7759_MODE, val);
@@ -374,7 +382,7 @@ static ssize_t ade7759_write_frequency(struct device *dev,
 
        mutex_lock(&indio_dev->mlock);
 
-       t = (27900 / val);
+       t = 27900 / val;
        if (t > 0)
                t--;
 
@@ -465,11 +473,7 @@ static int ade7759_probe(struct spi_device *spi)
        if (ret)
                return ret;
 
-       ret = iio_device_register(indio_dev);
-       if (ret)
-               return ret;
-
-       return 0;
+       return iio_device_register(indio_dev);
 }
 
 /* fixme, confirm ordering in this function */
index 5b33c7f1aa9108652fb4d6f7d8ceb81048646113..07cfe28b24e2a2c1ebcc03e3b98d494167498d8e 100644 (file)
@@ -16,8 +16,8 @@
 #include "ade7854.h"
 
 static int ade7854_i2c_write_reg_8(struct device *dev,
-               u16 reg_address,
-               u8 value)
+                                  u16 reg_address,
+                                  u8 value)
 {
        int ret;
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
@@ -35,8 +35,8 @@ static int ade7854_i2c_write_reg_8(struct device *dev,
 }
 
 static int ade7854_i2c_write_reg_16(struct device *dev,
-               u16 reg_address,
-               u16 value)
+                                   u16 reg_address,
+                                   u16 value)
 {
        int ret;
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
@@ -55,8 +55,8 @@ static int ade7854_i2c_write_reg_16(struct device *dev,
 }
 
 static int ade7854_i2c_write_reg_24(struct device *dev,
-               u16 reg_address,
-               u32 value)
+                                   u16 reg_address,
+                                   u32 value)
 {
        int ret;
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
@@ -76,8 +76,8 @@ static int ade7854_i2c_write_reg_24(struct device *dev,
 }
 
 static int ade7854_i2c_write_reg_32(struct device *dev,
-               u16 reg_address,
-               u32 value)
+                                   u16 reg_address,
+                                   u32 value)
 {
        int ret;
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
@@ -98,8 +98,8 @@ static int ade7854_i2c_write_reg_32(struct device *dev,
 }
 
 static int ade7854_i2c_read_reg_8(struct device *dev,
-               u16 reg_address,
-               u8 *val)
+                                 u16 reg_address,
+                                 u8 *val)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct ade7854_state *st = iio_priv(indio_dev);
@@ -124,8 +124,8 @@ out:
 }
 
 static int ade7854_i2c_read_reg_16(struct device *dev,
-               u16 reg_address,
-               u16 *val)
+                                  u16 reg_address,
+                                  u16 *val)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct ade7854_state *st = iio_priv(indio_dev);
@@ -150,8 +150,8 @@ out:
 }
 
 static int ade7854_i2c_read_reg_24(struct device *dev,
-               u16 reg_address,
-               u32 *val)
+                                  u16 reg_address,
+                                  u32 *val)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct ade7854_state *st = iio_priv(indio_dev);
@@ -176,8 +176,8 @@ out:
 }
 
 static int ade7854_i2c_read_reg_32(struct device *dev,
-               u16 reg_address,
-               u32 *val)
+                                  u16 reg_address,
+                                  u32 *val)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct ade7854_state *st = iio_priv(indio_dev);
@@ -195,21 +195,21 @@ static int ade7854_i2c_read_reg_32(struct device *dev,
        if (ret)
                goto out;
 
-       *val = (st->rx[0] << 24) | (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3];
+       *val = (st->rx[0] << 24) | (st->rx[1] << 16) |
+               (st->rx[2] << 8) | st->rx[3];
 out:
        mutex_unlock(&st->buf_lock);
        return ret;
 }
 
 static int ade7854_i2c_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
+                            const struct i2c_device_id *id)
 {
-       int ret;
        struct ade7854_state *st;
        struct iio_dev *indio_dev;
 
        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
-       if (indio_dev == NULL)
+       if (!indio_dev)
                return -ENOMEM;
        st = iio_priv(indio_dev);
        i2c_set_clientdata(client, indio_dev);
@@ -224,9 +224,7 @@ static int ade7854_i2c_probe(struct i2c_client *client,
        st->i2c = client;
        st->irq = client->irq;
 
-       ret = ade7854_probe(indio_dev, &client->dev);
-
-       return ret;
+       return ade7854_probe(indio_dev, &client->dev);
 }
 
 static int ade7854_i2c_remove(struct i2c_client *client)
index 94f73bbbc0fd28ec65153b401ef5a401d32d24d2..9b255a5f62c33822ecb8d255799887c6a4ee7cf6 100644 (file)
@@ -274,7 +274,6 @@ error_ret:
 
 static int ade7854_spi_probe(struct spi_device *spi)
 {
-       int ret;
        struct ade7854_state *st;
        struct iio_dev *indio_dev;
 
@@ -294,10 +293,7 @@ static int ade7854_spi_probe(struct spi_device *spi)
        st->irq = spi->irq;
        st->spi = spi;
 
-
-       ret = ade7854_probe(indio_dev, &spi->dev);
-
-       return ret;
+       return ade7854_probe(indio_dev, &spi->dev);
 }
 
 static int ade7854_spi_remove(struct spi_device *spi)
index 8f0de02839b73c72d7ff83998133e8801c91979a..dfba510f29be6c764a42f94e538a7ab7ab910e93 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef _METER_H
+#define _METER_H
+
 #include <linux/iio/sysfs.h>
 
 /* metering ic types of attribute */
 #define IIO_EVENT_ATTR_VPKLVL_EXC(_evlist, _show, _store, _mask) \
        IIO_EVENT_ATTR_SH(vpklvl_exc, _evlist, _show, _store, _mask)
 
+#endif /* _METER_H */
index b4c14ba5fdee3dca1a2585b43e5858f03b53af5c..7bc3e4a73834d5e305b47d93f83e8d2e96e95f4f 100644 (file)
@@ -151,7 +151,7 @@ int ad2s1210_update_frequency_control_word(struct ad2s1210_state *st)
 
        fcw = (unsigned char)(st->fexcit * (1 << 15) / st->fclkin);
        if (fcw < AD2S1210_MIN_FCW || fcw > AD2S1210_MAX_FCW) {
-               pr_err("ad2s1210: FCW out of range\n");
+               dev_err(&st->sdev->dev, "ad2s1210: FCW out of range\n");
                return -ERANGE;
        }
 
@@ -198,7 +198,7 @@ static ssize_t ad2s1210_show_fclkin(struct device *dev,
 {
        struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
 
-       return sprintf(buf, "%d\n", st->fclkin);
+       return sprintf(buf, "%u\n", st->fclkin);
 }
 
 static ssize_t ad2s1210_store_fclkin(struct device *dev,
@@ -214,7 +214,7 @@ static ssize_t ad2s1210_store_fclkin(struct device *dev,
        if (ret)
                return ret;
        if (fclkin < AD2S1210_MIN_CLKIN || fclkin > AD2S1210_MAX_CLKIN) {
-               pr_err("ad2s1210: fclkin out of range\n");
+               dev_err(dev, "ad2s1210: fclkin out of range\n");
                return -EINVAL;
        }
 
@@ -237,7 +237,7 @@ static ssize_t ad2s1210_show_fexcit(struct device *dev,
 {
        struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
 
-       return sprintf(buf, "%d\n", st->fexcit);
+       return sprintf(buf, "%u\n", st->fexcit);
 }
 
 static ssize_t ad2s1210_store_fexcit(struct device *dev,
@@ -252,7 +252,8 @@ static ssize_t ad2s1210_store_fexcit(struct device *dev,
        if (ret < 0)
                return ret;
        if (fexcit < AD2S1210_MIN_EXCIT || fexcit > AD2S1210_MAX_EXCIT) {
-               pr_err("ad2s1210: excitation frequency out of range\n");
+               dev_err(dev,
+                       "ad2s1210: excitation frequency out of range\n");
                return -EINVAL;
        }
        mutex_lock(&st->lock);
@@ -307,7 +308,8 @@ static ssize_t ad2s1210_store_control(struct device *dev,
                goto error_ret;
        if (ret & AD2S1210_MSB_IS_HIGH) {
                ret = -EIO;
-               pr_err("ad2s1210: write control register fail\n");
+               dev_err(dev,
+                       "ad2s1210: write control register fail\n");
                goto error_ret;
        }
        st->resolution
@@ -315,7 +317,7 @@ static ssize_t ad2s1210_store_control(struct device *dev,
        if (st->pdata->gpioin) {
                data = ad2s1210_read_resolution_pin(st);
                if (data != st->resolution)
-                       pr_warn("ad2s1210: resolution settings not match\n");
+                       dev_warn(dev, "ad2s1210: resolution settings not match\n");
        } else
                ad2s1210_set_resolution_pin(st);
 
@@ -346,7 +348,7 @@ static ssize_t ad2s1210_store_resolution(struct device *dev,
 
        ret = kstrtou8(buf, 10, &udata);
        if (ret || udata < 10 || udata > 16) {
-               pr_err("ad2s1210: resolution out of range\n");
+               dev_err(dev, "ad2s1210: resolution out of range\n");
                return -EINVAL;
        }
        mutex_lock(&st->lock);
@@ -368,7 +370,7 @@ static ssize_t ad2s1210_store_resolution(struct device *dev,
        data = ret;
        if (data & AD2S1210_MSB_IS_HIGH) {
                ret = -EIO;
-               pr_err("ad2s1210: setting resolution fail\n");
+               dev_err(dev, "ad2s1210: setting resolution fail\n");
                goto error_ret;
        }
        st->resolution
@@ -376,7 +378,7 @@ static ssize_t ad2s1210_store_resolution(struct device *dev,
        if (st->pdata->gpioin) {
                data = ad2s1210_read_resolution_pin(st);
                if (data != st->resolution)
-                       pr_warn("ad2s1210: resolution settings not match\n");
+                       dev_warn(dev, "ad2s1210: resolution settings not match\n");
        } else
                ad2s1210_set_resolution_pin(st);
        ret = len;
index aec0bdca16a48d13de38b8196a722fc3537c65a4..c7158f6e61c23c7fa0090bc2f19f63f19acbcb62 100644 (file)
@@ -8,6 +8,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#ifndef _AD2S1210_H
+#define _AD2S1210_H
 
 struct ad2s1210_platform_data {
        unsigned sample;
@@ -15,3 +17,4 @@ struct ad2s1210_platform_data {
        unsigned res[2];
        bool gpioin;
 };
+#endif /* _AD2S1210_H */
index 2af8d677d4ed88b59b094a62a4e7bc9ef4064a47..3c1c8c6c4a6c8ea224edab37c1f64f8d87f8d9e2 100644 (file)
@@ -183,7 +183,7 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
        int ret;
 
        st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL);
-       if (st == NULL)
+       if (!st)
                return -ENOMEM;
 
        st->irq = platform_get_irq(pdev, 0);
index a24caf73ae0b97aec156bc97be60b21d939800a9..0c1976ddee7489c6d4165e3e4e01990e0b7952e3 100644 (file)
@@ -24,7 +24,7 @@ static DEFINE_MUTEX(iio_prtc_trigger_list_lock);
 
 struct iio_prtc_trigger_info {
        struct rtc_device *rtc;
-       int frequency;
+       unsigned int frequency;
        struct rtc_task task;
        bool state;
 };
@@ -36,7 +36,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 %d\n",
+       dev_dbg(&trig_info->rtc->dev, "trigger frequency is %u\n",
                        trig_info->frequency);
        ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, state);
        if (ret == 0)
@@ -62,10 +62,10 @@ static ssize_t iio_trig_periodic_write_freq(struct device *dev,
 {
        struct iio_trigger *trig = to_iio_trigger(dev);
        struct iio_prtc_trigger_info *trig_info = iio_trigger_get_drvdata(trig);
-       int val;
+       unsigned int val;
        int ret;
 
-       ret = kstrtoint(buf, 10, &val);
+       ret = kstrtouint(buf, 10, &val);
        if (ret)
                goto error_ret;
 
@@ -74,10 +74,8 @@ 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 if (val == 0) {
-               ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, 0);
        } else
-               ret = -EINVAL;
+               ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, 0);
        if (ret)
                goto error_ret;
 
@@ -126,7 +124,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev)
        int i, ret;
 
        for (i = 0;; i++) {
-               if (pdata[i] == NULL)
+               if (!pdata[i])
                        break;
                trig = iio_trigger_alloc("periodic%s", pdata[i]);
                if (!trig) {
@@ -144,7 +142,7 @@ static int iio_trig_periodic_rtc_probe(struct platform_device *dev)
                trig->ops = &iio_prtc_trigger_ops;
                /* RTC access */
                trig_info->rtc = rtc_class_open(pdata[i]);
-               if (trig_info->rtc == NULL) {
+               if (!trig_info->rtc) {
                        ret = -EINVAL;
                        goto error_free_trig_info;
                }
index 2e5a9e5965b13883cf89cac70da77264e5b2cf26..8251ac932e37b22110c0cf5deacde6c53ecc4e78 100644 (file)
@@ -196,7 +196,7 @@ do {                                                                \
               .msg_fn     = __func__,                          \
               .msg_line   = __LINE__,                          \
               .msg_cdls   = (cdls)      };                     \
-       dataname.msg_mask   = (mask);
+       dataname.msg_mask   = (mask)
 
 /**
  * Filters out logging messages based on mask and subsystem.
@@ -244,12 +244,12 @@ do {                                                                      \
 
 int libcfs_debug_msg(struct libcfs_debug_msg_data *msgdata,
                            const char *format1, ...)
-       __attribute__ ((format (printf, 2, 3)));
+       __printf(2, 3);
 
 int libcfs_debug_vmsg2(struct libcfs_debug_msg_data *msgdata,
                              const char *format1,
                              va_list args, const char *format2, ...)
-       __attribute__ ((format (printf, 4, 5)));
+       __printf(4, 5);
 
 /* other external symbols that tracefile provides: */
 int cfs_trace_copyin_string(char *knl_buffer, int knl_buffer_nob,
index 808e49411a300a1c4f8f9b079ee7f88d442f5997..c408145911899d353cbb5e589369b3663108cd09 100644 (file)
@@ -469,7 +469,7 @@ cfs_hash_key(struct cfs_hash *hs, struct hlist_node *hnode)
 static inline void
 cfs_hash_keycpy(struct cfs_hash *hs, struct hlist_node *hnode, void *key)
 {
-        if (hs->hs_ops->hs_keycpy)
+       if (hs->hs_ops->hs_keycpy)
                hs->hs_ops->hs_keycpy(hnode, key);
 }
 
@@ -785,8 +785,8 @@ static inline void __cfs_hash_set_theta(struct cfs_hash *hs, int min, int max)
 
 /* Generic debug formatting routines mainly for proc handler */
 struct seq_file;
-int cfs_hash_debug_header(struct seq_file *m);
-int cfs_hash_debug_str(struct cfs_hash *hs, struct seq_file *m);
+void cfs_hash_debug_header(struct seq_file *m);
+void cfs_hash_debug_str(struct cfs_hash *hs, struct seq_file *m);
 
 /*
  * Generic djb2 hash algorithm for character arrays.
index f19a121a37cd5fb4f8a090284eea39f22165af0e..a989d2666230e9d70371c25c0869fc47a8e28deb 100644 (file)
@@ -58,7 +58,7 @@ struct kuc_hdr {
        __u8  kuc_flags;
        __u16 kuc_msgtype;    /* Message type or opcode, transport-specific */
        __u16 kuc_msglen;     /* Including header */
-} __attribute__((aligned(sizeof(__u64))));
+} __aligned(sizeof(__u64));
 
 #define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr)+CR_MAXSIZE)
 
@@ -107,7 +107,7 @@ typedef struct lustre_kernelcomm {
        __u32 lk_group;
        __u32 lk_data;
        __u32 lk_flags;
-} __attribute__((packed)) lustre_kernelcomm;
+} __packed lustre_kernelcomm;
 
 /* Userspace methods */
 int libcfs_ukuc_start(lustre_kernelcomm *l, int groups);
index 3d86fb5b548192678f675cf6c7a7ab98101bfe88..fef882530455f2b4f6c8c57daf8f66638f68a0ad 100644 (file)
@@ -335,8 +335,8 @@ do {                                                            \
 #define LASSERT_ATOMIC_ZERO(a)           LASSERT_ATOMIC_EQ(a, 0)
 #define LASSERT_ATOMIC_POS(a)             LASSERT_ATOMIC_GT(a, 0)
 
-#define CFS_ALLOC_PTR(ptr)      LIBCFS_ALLOC(ptr, sizeof(*(ptr)));
-#define CFS_FREE_PTR(ptr)       LIBCFS_FREE(ptr, sizeof(*(ptr)));
+#define CFS_ALLOC_PTR(ptr)      LIBCFS_ALLOC(ptr, sizeof(*(ptr)))
+#define CFS_FREE_PTR(ptr)       LIBCFS_FREE(ptr, sizeof(*(ptr)))
 
 /*
  * percpu partition lock
index 65101691966915d2ace2204b18e6a4590696ff8d..3bad441de8dc90df646caecb64e40e54b83c15bc 100644 (file)
@@ -53,8 +53,7 @@ static lnd_t the_o2iblnd = {
 
 kib_data_t           kiblnd_data;
 
-static __u32
-kiblnd_cksum(void *ptr, int nob)
+static __u32 kiblnd_cksum(void *ptr, int nob)
 {
        char  *c  = ptr;
        __u32  sum = 0;
@@ -66,8 +65,7 @@ kiblnd_cksum(void *ptr, int nob)
        return (sum == 0) ? 1 : sum;
 }
 
-static char *
-kiblnd_msgtype2str(int type)
+static char *kiblnd_msgtype2str(int type)
 {
        switch (type) {
        case IBLND_MSG_CONNREQ:
@@ -105,8 +103,7 @@ kiblnd_msgtype2str(int type)
        }
 }
 
-static int
-kiblnd_msgtype2size(int type)
+static int kiblnd_msgtype2size(int type)
 {
        const int hdr_size = offsetof(kib_msg_t, ibm_u);
 
@@ -139,15 +136,14 @@ kiblnd_msgtype2size(int type)
        }
 }
 
-static int
-kiblnd_unpack_rd(kib_msg_t *msg, int flip)
+static int kiblnd_unpack_rd(kib_msg_t *msg, int flip)
 {
        kib_rdma_desc_t   *rd;
        int             nob;
        int             n;
        int             i;
 
-       LASSERT (msg->ibm_type == IBLND_MSG_GET_REQ ||
+       LASSERT(msg->ibm_type == IBLND_MSG_GET_REQ ||
                 msg->ibm_type == IBLND_MSG_PUT_ACK);
 
        rd = msg->ibm_type == IBLND_MSG_GET_REQ ?
@@ -167,7 +163,7 @@ kiblnd_unpack_rd(kib_msg_t *msg, int flip)
                return 1;
        }
 
-       nob = offsetof (kib_msg_t, ibm_u) +
+       nob = offsetof(kib_msg_t, ibm_u) +
              kiblnd_rd_msg_size(rd, msg->ibm_type, n);
 
        if (msg->ibm_nob < nob) {
@@ -187,9 +183,8 @@ kiblnd_unpack_rd(kib_msg_t *msg, int flip)
        return 0;
 }
 
-void
-kiblnd_pack_msg (lnet_ni_t *ni, kib_msg_t *msg, int version,
-                int credits, lnet_nid_t dstnid, __u64 dststamp)
+void kiblnd_pack_msg(lnet_ni_t *ni, kib_msg_t *msg, int version,
+                    int credits, lnet_nid_t dstnid, __u64 dststamp)
 {
        kib_net_t *net = ni->ni_data;
 
@@ -212,8 +207,7 @@ kiblnd_pack_msg (lnet_ni_t *ni, kib_msg_t *msg, int version,
        }
 }
 
-int
-kiblnd_unpack_msg(kib_msg_t *msg, int nob)
+int kiblnd_unpack_msg(kib_msg_t *msg, int nob)
 {
        const int hdr_size = offsetof(kib_msg_t, ibm_u);
        __u32     msg_cksum;
@@ -269,8 +263,8 @@ kiblnd_unpack_msg(kib_msg_t *msg, int nob)
        if (flip) {
                /* leave magic unflipped as a clue to peer endianness */
                msg->ibm_version = version;
-               CLASSERT (sizeof(msg->ibm_type) == 1);
-               CLASSERT (sizeof(msg->ibm_credits) == 1);
+               CLASSERT(sizeof(msg->ibm_type) == 1);
+               CLASSERT(sizeof(msg->ibm_credits) == 1);
                msg->ibm_nob     = msg_nob;
                __swab64s(&msg->ibm_srcnid);
                __swab64s(&msg->ibm_srcstamp);
@@ -324,8 +318,7 @@ kiblnd_unpack_msg(kib_msg_t *msg, int nob)
        return 0;
 }
 
-int
-kiblnd_create_peer(lnet_ni_t *ni, kib_peer_t **peerp, lnet_nid_t nid)
+int kiblnd_create_peer(lnet_ni_t *ni, kib_peer_t **peerp, lnet_nid_t nid)
 {
        kib_peer_t      *peer;
        kib_net_t       *net = ni->ni_data;
@@ -356,7 +349,7 @@ kiblnd_create_peer(lnet_ni_t *ni, kib_peer_t **peerp, lnet_nid_t nid)
        write_lock_irqsave(&kiblnd_data.kib_global_lock, flags);
 
        /* always called with a ref on ni, which prevents ni being shutdown */
-       LASSERT (net->ibn_shutdown == 0);
+       LASSERT(net->ibn_shutdown == 0);
 
        /* npeers only grows with the global lock held */
        atomic_inc(&net->ibn_npeers);
@@ -367,18 +360,17 @@ kiblnd_create_peer(lnet_ni_t *ni, kib_peer_t **peerp, lnet_nid_t nid)
        return 0;
 }
 
-void
-kiblnd_destroy_peer (kib_peer_t *peer)
+void kiblnd_destroy_peer(kib_peer_t *peer)
 {
        kib_net_t *net = peer->ibp_ni->ni_data;
 
-       LASSERT (net != NULL);
-       LASSERT (atomic_read(&peer->ibp_refcount) == 0);
-       LASSERT (!kiblnd_peer_active(peer));
-       LASSERT (peer->ibp_connecting == 0);
-       LASSERT (peer->ibp_accepting == 0);
-       LASSERT (list_empty(&peer->ibp_conns));
-       LASSERT (list_empty(&peer->ibp_tx_queue));
+       LASSERT(net != NULL);
+       LASSERT(atomic_read(&peer->ibp_refcount) == 0);
+       LASSERT(!kiblnd_peer_active(peer));
+       LASSERT(peer->ibp_connecting == 0);
+       LASSERT(peer->ibp_accepting == 0);
+       LASSERT(list_empty(&peer->ibp_conns));
+       LASSERT(list_empty(&peer->ibp_tx_queue));
 
        LIBCFS_FREE(peer, sizeof(*peer));
 
@@ -389,8 +381,7 @@ kiblnd_destroy_peer (kib_peer_t *peer)
        atomic_dec(&net->ibn_npeers);
 }
 
-kib_peer_t *
-kiblnd_find_peer_locked (lnet_nid_t nid)
+kib_peer_t *kiblnd_find_peer_locked(lnet_nid_t nid)
 {
        /* the caller is responsible for accounting the additional reference
         * that this creates */
@@ -398,11 +389,11 @@ kiblnd_find_peer_locked (lnet_nid_t nid)
        struct list_head       *tmp;
        kib_peer_t       *peer;
 
-       list_for_each (tmp, peer_list) {
+       list_for_each(tmp, peer_list) {
 
                peer = list_entry(tmp, kib_peer_t, ibp_list);
 
-               LASSERT (peer->ibp_connecting > 0 || /* creating conns */
+               LASSERT(peer->ibp_connecting > 0 || /* creating conns */
                         peer->ibp_accepting > 0 ||
                         !list_empty(&peer->ibp_conns));  /* active conn */
 
@@ -418,20 +409,18 @@ kiblnd_find_peer_locked (lnet_nid_t nid)
        return NULL;
 }
 
-void
-kiblnd_unlink_peer_locked (kib_peer_t *peer)
+void kiblnd_unlink_peer_locked(kib_peer_t *peer)
 {
-       LASSERT (list_empty(&peer->ibp_conns));
+       LASSERT(list_empty(&peer->ibp_conns));
 
-       LASSERT (kiblnd_peer_active(peer));
+       LASSERT(kiblnd_peer_active(peer));
        list_del_init(&peer->ibp_list);
        /* lose peerlist's ref */
        kiblnd_peer_decref(peer);
 }
 
-static int
-kiblnd_get_peer_info(lnet_ni_t *ni, int index,
-                     lnet_nid_t *nidp, int *count)
+static int kiblnd_get_peer_info(lnet_ni_t *ni, int index,
+                               lnet_nid_t *nidp, int *count)
 {
        kib_peer_t          *peer;
        struct list_head            *ptmp;
@@ -442,10 +431,10 @@ kiblnd_get_peer_info(lnet_ni_t *ni, int index,
 
        for (i = 0; i < kiblnd_data.kib_peer_hash_size; i++) {
 
-               list_for_each (ptmp, &kiblnd_data.kib_peers[i]) {
+               list_for_each(ptmp, &kiblnd_data.kib_peers[i]) {
 
                        peer = list_entry(ptmp, kib_peer_t, ibp_list);
-                       LASSERT (peer->ibp_connecting > 0 ||
+                       LASSERT(peer->ibp_connecting > 0 ||
                                 peer->ibp_accepting > 0 ||
                                 !list_empty(&peer->ibp_conns));
 
@@ -468,8 +457,7 @@ kiblnd_get_peer_info(lnet_ni_t *ni, int index,
        return -ENOENT;
 }
 
-static void
-kiblnd_del_peer_locked(kib_peer_t *peer)
+static void kiblnd_del_peer_locked(kib_peer_t *peer)
 {
        struct list_head           *ctmp;
        struct list_head           *cnxt;
@@ -478,7 +466,7 @@ kiblnd_del_peer_locked(kib_peer_t *peer)
        if (list_empty(&peer->ibp_conns)) {
                kiblnd_unlink_peer_locked(peer);
        } else {
-               list_for_each_safe (ctmp, cnxt, &peer->ibp_conns) {
+               list_for_each_safe(ctmp, cnxt, &peer->ibp_conns) {
                        conn = list_entry(ctmp, kib_conn_t, ibc_list);
 
                        kiblnd_close_conn_locked(conn, 0);
@@ -489,10 +477,9 @@ kiblnd_del_peer_locked(kib_peer_t *peer)
         * last ref on it. */
 }
 
-static int
-kiblnd_del_peer(lnet_ni_t *ni, lnet_nid_t nid)
+static int kiblnd_del_peer(lnet_ni_t *ni, lnet_nid_t nid)
 {
-       LIST_HEAD        (zombies);
+       LIST_HEAD(zombies);
        struct list_head            *ptmp;
        struct list_head            *pnxt;
        kib_peer_t          *peer;
@@ -512,9 +499,9 @@ kiblnd_del_peer(lnet_ni_t *ni, lnet_nid_t nid)
        }
 
        for (i = lo; i <= hi; i++) {
-               list_for_each_safe (ptmp, pnxt, &kiblnd_data.kib_peers[i]) {
+               list_for_each_safe(ptmp, pnxt, &kiblnd_data.kib_peers[i]) {
                        peer = list_entry(ptmp, kib_peer_t, ibp_list);
-                       LASSERT (peer->ibp_connecting > 0 ||
+                       LASSERT(peer->ibp_connecting > 0 ||
                                 peer->ibp_accepting > 0 ||
                                 !list_empty(&peer->ibp_conns));
 
@@ -525,7 +512,7 @@ kiblnd_del_peer(lnet_ni_t *ni, lnet_nid_t nid)
                                continue;
 
                        if (!list_empty(&peer->ibp_tx_queue)) {
-                               LASSERT (list_empty(&peer->ibp_conns));
+                               LASSERT(list_empty(&peer->ibp_conns));
 
                                list_splice_init(&peer->ibp_tx_queue,
                                                     &zombies);
@@ -543,8 +530,7 @@ kiblnd_del_peer(lnet_ni_t *ni, lnet_nid_t nid)
        return rc;
 }
 
-static kib_conn_t *
-kiblnd_get_conn_by_idx(lnet_ni_t *ni, int index)
+static kib_conn_t *kiblnd_get_conn_by_idx(lnet_ni_t *ni, int index)
 {
        kib_peer_t          *peer;
        struct list_head            *ptmp;
@@ -556,25 +542,26 @@ kiblnd_get_conn_by_idx(lnet_ni_t *ni, int index)
        read_lock_irqsave(&kiblnd_data.kib_global_lock, flags);
 
        for (i = 0; i < kiblnd_data.kib_peer_hash_size; i++) {
-               list_for_each (ptmp, &kiblnd_data.kib_peers[i]) {
+               list_for_each(ptmp, &kiblnd_data.kib_peers[i]) {
 
                        peer = list_entry(ptmp, kib_peer_t, ibp_list);
-                       LASSERT (peer->ibp_connecting > 0 ||
+                       LASSERT(peer->ibp_connecting > 0 ||
                                 peer->ibp_accepting > 0 ||
                                 !list_empty(&peer->ibp_conns));
 
                        if (peer->ibp_ni != ni)
                                continue;
 
-                       list_for_each (ctmp, &peer->ibp_conns) {
+                       list_for_each(ctmp, &peer->ibp_conns) {
                                if (index-- > 0)
                                        continue;
 
                                conn = list_entry(ctmp, kib_conn_t,
                                                      ibc_list);
                                kiblnd_conn_addref(conn);
-                               read_unlock_irqrestore(&kiblnd_data.kib_global_lock,
-                                                      flags);
+                               read_unlock_irqrestore(
+                                       &kiblnd_data.kib_global_lock,
+                                       flags);
                                return conn;
                        }
                }
@@ -584,8 +571,7 @@ kiblnd_get_conn_by_idx(lnet_ni_t *ni, int index)
        return NULL;
 }
 
-int
-kiblnd_translate_mtu(int value)
+int kiblnd_translate_mtu(int value)
 {
        switch (value) {
        default:
@@ -605,8 +591,7 @@ kiblnd_translate_mtu(int value)
        }
 }
 
-static void
-kiblnd_setup_mtu_locked(struct rdma_cm_id *cmid)
+static void kiblnd_setup_mtu_locked(struct rdma_cm_id *cmid)
 {
        int        mtu;
 
@@ -615,13 +600,12 @@ kiblnd_setup_mtu_locked(struct rdma_cm_id *cmid)
                return;
 
        mtu = kiblnd_translate_mtu(*kiblnd_tunables.kib_ib_mtu);
-       LASSERT (mtu >= 0);
+       LASSERT(mtu >= 0);
        if (mtu != 0)
                cmid->route.path_rec->mtu = mtu;
 }
 
-static int
-kiblnd_get_completion_vector(kib_conn_t *conn, int cpt)
+static int kiblnd_get_completion_vector(kib_conn_t *conn, int cpt)
 {
        cpumask_t       *mask;
        int             vectors;
@@ -638,8 +622,8 @@ kiblnd_get_completion_vector(kib_conn_t *conn, int cpt)
                return 0;
 
        /* hash NID to CPU id in this partition... */
-       off = do_div(nid, cpus_weight(*mask));
-       for_each_cpu_mask(i, *mask) {
+       off = do_div(nid, cpumask_weight(mask));
+       for_each_cpu(i, mask) {
                if (off-- == 0)
                        return i % vectors;
        }
@@ -648,9 +632,8 @@ kiblnd_get_completion_vector(kib_conn_t *conn, int cpt)
        return 1;
 }
 
-kib_conn_t *
-kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid,
-                  int state, int version)
+kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid,
+                               int state, int version)
 {
        /* CAVEAT EMPTOR:
         * If the new conn is created successfully it takes over the caller's
@@ -835,7 +818,7 @@ kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid,
        }
 
        /* Init successful! */
-       LASSERT (state == IBLND_CONN_ACTIVE_CONNECT ||
+       LASSERT(state == IBLND_CONN_ACTIVE_CONNECT ||
                 state == IBLND_CONN_PASSIVE_WAIT);
        conn->ibc_state = state;
 
@@ -851,23 +834,22 @@ kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid,
        return NULL;
 }
 
-void
-kiblnd_destroy_conn (kib_conn_t *conn)
+void kiblnd_destroy_conn(kib_conn_t *conn)
 {
        struct rdma_cm_id *cmid = conn->ibc_cmid;
        kib_peer_t      *peer = conn->ibc_peer;
        int             rc;
 
-       LASSERT (!in_interrupt());
-       LASSERT (atomic_read(&conn->ibc_refcount) == 0);
-       LASSERT (list_empty(&conn->ibc_early_rxs));
-       LASSERT (list_empty(&conn->ibc_tx_noops));
-       LASSERT (list_empty(&conn->ibc_tx_queue));
-       LASSERT (list_empty(&conn->ibc_tx_queue_rsrvd));
-       LASSERT (list_empty(&conn->ibc_tx_queue_nocred));
-       LASSERT (list_empty(&conn->ibc_active_txs));
-       LASSERT (conn->ibc_noops_posted == 0);
-       LASSERT (conn->ibc_nsends_posted == 0);
+       LASSERT(!in_interrupt());
+       LASSERT(atomic_read(&conn->ibc_refcount) == 0);
+       LASSERT(list_empty(&conn->ibc_early_rxs));
+       LASSERT(list_empty(&conn->ibc_tx_noops));
+       LASSERT(list_empty(&conn->ibc_tx_queue));
+       LASSERT(list_empty(&conn->ibc_tx_queue_rsrvd));
+       LASSERT(list_empty(&conn->ibc_tx_queue_nocred));
+       LASSERT(list_empty(&conn->ibc_active_txs));
+       LASSERT(conn->ibc_noops_posted == 0);
+       LASSERT(conn->ibc_nsends_posted == 0);
 
        switch (conn->ibc_state) {
        default:
@@ -876,7 +858,7 @@ kiblnd_destroy_conn (kib_conn_t *conn)
 
        case IBLND_CONN_DISCONNECTED:
                /* connvars should have been freed already */
-               LASSERT (conn->ibc_connvars == NULL);
+               LASSERT(conn->ibc_connvars == NULL);
                break;
 
        case IBLND_CONN_INIT:
@@ -898,7 +880,8 @@ kiblnd_destroy_conn (kib_conn_t *conn)
 
        if (conn->ibc_rxs != NULL) {
                LIBCFS_FREE(conn->ibc_rxs,
-                           IBLND_RX_MSGS(conn->ibc_version) * sizeof(kib_rx_t));
+                           IBLND_RX_MSGS(conn->ibc_version)
+                             * sizeof(kib_rx_t));
        }
 
        if (conn->ibc_connvars != NULL)
@@ -919,15 +902,14 @@ kiblnd_destroy_conn (kib_conn_t *conn)
        LIBCFS_FREE(conn, sizeof(*conn));
 }
 
-int
-kiblnd_close_peer_conns_locked (kib_peer_t *peer, int why)
+int kiblnd_close_peer_conns_locked(kib_peer_t *peer, int why)
 {
        kib_conn_t           *conn;
        struct list_head             *ctmp;
        struct list_head             *cnxt;
        int                  count = 0;
 
-       list_for_each_safe (ctmp, cnxt, &peer->ibp_conns) {
+       list_for_each_safe(ctmp, cnxt, &peer->ibp_conns) {
                conn = list_entry(ctmp, kib_conn_t, ibc_list);
 
                CDEBUG(D_NET, "Closing conn -> %s, version: %x, reason: %d\n",
@@ -941,23 +923,23 @@ kiblnd_close_peer_conns_locked (kib_peer_t *peer, int why)
        return count;
 }
 
-int
-kiblnd_close_stale_conns_locked (kib_peer_t *peer,
-                                int version, __u64 incarnation)
+int kiblnd_close_stale_conns_locked(kib_peer_t *peer,
+                                    int version, __u64 incarnation)
 {
        kib_conn_t           *conn;
        struct list_head             *ctmp;
        struct list_head             *cnxt;
        int                  count = 0;
 
-       list_for_each_safe (ctmp, cnxt, &peer->ibp_conns) {
+       list_for_each_safe(ctmp, cnxt, &peer->ibp_conns) {
                conn = list_entry(ctmp, kib_conn_t, ibc_list);
 
                if (conn->ibc_version     == version &&
                    conn->ibc_incarnation == incarnation)
                        continue;
 
-               CDEBUG(D_NET, "Closing stale conn -> %s version: %x, incarnation:%#llx(%x, %#llx)\n",
+               CDEBUG(D_NET,
+                      "Closing stale conn -> %s version: %x, incarnation:%#llx(%x, %#llx)\n",
                       libcfs_nid2str(peer->ibp_nid),
                       conn->ibc_version, conn->ibc_incarnation,
                       version, incarnation);
@@ -969,8 +951,7 @@ kiblnd_close_stale_conns_locked (kib_peer_t *peer,
        return count;
 }
 
-static int
-kiblnd_close_matching_conns(lnet_ni_t *ni, lnet_nid_t nid)
+static int kiblnd_close_matching_conns(lnet_ni_t *ni, lnet_nid_t nid)
 {
        kib_peer_t           *peer;
        struct list_head             *ptmp;
@@ -991,10 +972,10 @@ kiblnd_close_matching_conns(lnet_ni_t *ni, lnet_nid_t nid)
        }
 
        for (i = lo; i <= hi; i++) {
-               list_for_each_safe (ptmp, pnxt, &kiblnd_data.kib_peers[i]) {
+               list_for_each_safe(ptmp, pnxt, &kiblnd_data.kib_peers[i]) {
 
                        peer = list_entry(ptmp, kib_peer_t, ibp_list);
-                       LASSERT (peer->ibp_connecting > 0 ||
+                       LASSERT(peer->ibp_connecting > 0 ||
                                 peer->ibp_accepting > 0 ||
                                 !list_empty(&peer->ibp_conns));
 
@@ -1017,8 +998,7 @@ kiblnd_close_matching_conns(lnet_ni_t *ni, lnet_nid_t nid)
        return (count == 0) ? -ENOENT : 0;
 }
 
-int
-kiblnd_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg)
+int kiblnd_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg)
 {
        struct libcfs_ioctl_data *data = arg;
        int                    rc = -EINVAL;
@@ -1049,7 +1029,7 @@ kiblnd_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg)
                        break;
                }
 
-               LASSERT (conn->ibc_cmid != NULL);
+               LASSERT(conn->ibc_cmid != NULL);
                data->ioc_nid = conn->ibc_peer->ibp_nid;
                if (conn->ibc_cmid->route.path_rec == NULL)
                        data->ioc_u32[0] = 0; /* iWarp has no path MTU */
@@ -1071,8 +1051,7 @@ kiblnd_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg)
        return rc;
 }
 
-void
-kiblnd_query (lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when)
+void kiblnd_query(lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when)
 {
        unsigned long   last_alive = 0;
        unsigned long   now = cfs_time_current();
@@ -1084,7 +1063,7 @@ kiblnd_query (lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when)
 
        peer = kiblnd_find_peer_locked(nid);
        if (peer != NULL) {
-               LASSERT (peer->ibp_connecting > 0 || /* creating conns */
+               LASSERT(peer->ibp_connecting > 0 || /* creating conns */
                         peer->ibp_accepting > 0 ||
                         !list_empty(&peer->ibp_conns));  /* active conn */
                last_alive = peer->ibp_last_alive;
@@ -1103,11 +1082,9 @@ kiblnd_query (lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when)
        CDEBUG(D_NET, "Peer %s %p, alive %ld secs ago\n",
               libcfs_nid2str(nid), peer,
               last_alive ? cfs_duration_sec(now - last_alive) : -1);
-       return;
 }
 
-void
-kiblnd_free_pages(kib_pages_t *p)
+void kiblnd_free_pages(kib_pages_t *p)
 {
        int     npages = p->ibp_npages;
        int     i;
@@ -1120,8 +1097,7 @@ kiblnd_free_pages(kib_pages_t *p)
        LIBCFS_FREE(p, offsetof(kib_pages_t, ibp_pages[npages]));
 }
 
-int
-kiblnd_alloc_pages(kib_pages_t **pp, int cpt, int npages)
+int kiblnd_alloc_pages(kib_pages_t **pp, int cpt, int npages)
 {
        kib_pages_t     *p;
        int             i;
@@ -1151,19 +1127,18 @@ kiblnd_alloc_pages(kib_pages_t **pp, int cpt, int npages)
        return 0;
 }
 
-void
-kiblnd_unmap_rx_descs(kib_conn_t *conn)
+void kiblnd_unmap_rx_descs(kib_conn_t *conn)
 {
        kib_rx_t *rx;
        int       i;
 
-       LASSERT (conn->ibc_rxs != NULL);
-       LASSERT (conn->ibc_hdev != NULL);
+       LASSERT(conn->ibc_rxs != NULL);
+       LASSERT(conn->ibc_hdev != NULL);
 
        for (i = 0; i < IBLND_RX_MSGS(conn->ibc_version); i++) {
                rx = &conn->ibc_rxs[i];
 
-               LASSERT (rx->rx_nob >= 0); /* not posted */
+               LASSERT(rx->rx_nob >= 0); /* not posted */
 
                kiblnd_dma_unmap_single(conn->ibc_hdev->ibh_ibdev,
                                        KIBLND_UNMAP_ADDR(rx, rx_msgunmap,
@@ -1176,8 +1151,7 @@ kiblnd_unmap_rx_descs(kib_conn_t *conn)
        conn->ibc_rx_pages = NULL;
 }
 
-void
-kiblnd_map_rx_descs(kib_conn_t *conn)
+void kiblnd_map_rx_descs(kib_conn_t *conn)
 {
        kib_rx_t       *rx;
        struct page    *pg;
@@ -1194,9 +1168,10 @@ kiblnd_map_rx_descs(kib_conn_t *conn)
                rx->rx_msg = (kib_msg_t *)(((char *)page_address(pg)) + pg_off);
 
                rx->rx_msgaddr = kiblnd_dma_map_single(conn->ibc_hdev->ibh_ibdev,
-                                                      rx->rx_msg, IBLND_MSG_SIZE,
+                                                      rx->rx_msg,
+                                                      IBLND_MSG_SIZE,
                                                       DMA_FROM_DEVICE);
-               LASSERT (!kiblnd_dma_mapping_error(conn->ibc_hdev->ibh_ibdev,
+               LASSERT(!kiblnd_dma_mapping_error(conn->ibc_hdev->ibh_ibdev,
                                                   rx->rx_msgaddr));
                KIBLND_UNMAP_ADDR_SET(rx, rx_msgunmap, rx->rx_msgaddr);
 
@@ -1205,24 +1180,23 @@ kiblnd_map_rx_descs(kib_conn_t *conn)
                       lnet_page2phys(pg) + pg_off);
 
                pg_off += IBLND_MSG_SIZE;
-               LASSERT (pg_off <= PAGE_SIZE);
+               LASSERT(pg_off <= PAGE_SIZE);
 
                if (pg_off == PAGE_SIZE) {
                        pg_off = 0;
                        ipg++;
-                       LASSERT (ipg <= IBLND_RX_MSG_PAGES(conn->ibc_version));
+                       LASSERT(ipg <= IBLND_RX_MSG_PAGES(conn->ibc_version));
                }
        }
 }
 
-static void
-kiblnd_unmap_tx_pool(kib_tx_pool_t *tpo)
+static void kiblnd_unmap_tx_pool(kib_tx_pool_t *tpo)
 {
        kib_hca_dev_t  *hdev = tpo->tpo_hdev;
        kib_tx_t       *tx;
        int          i;
 
-       LASSERT (tpo->tpo_pool.po_allocated == 0);
+       LASSERT(tpo->tpo_pool.po_allocated == 0);
 
        if (hdev == NULL)
                return;
@@ -1239,8 +1213,7 @@ kiblnd_unmap_tx_pool(kib_tx_pool_t *tpo)
        tpo->tpo_hdev = NULL;
 }
 
-static kib_hca_dev_t *
-kiblnd_current_hdev(kib_dev_t *dev)
+static kib_hca_dev_t *kiblnd_current_hdev(kib_dev_t *dev)
 {
        kib_hca_dev_t *hdev;
        unsigned long  flags;
@@ -1265,8 +1238,7 @@ kiblnd_current_hdev(kib_dev_t *dev)
        return hdev;
 }
 
-static void
-kiblnd_map_tx_pool(kib_tx_pool_t *tpo)
+static void kiblnd_map_tx_pool(kib_tx_pool_t *tpo)
 {
        kib_pages_t    *txpgs = tpo->tpo_tx_pages;
        kib_pool_t     *pool  = &tpo->tpo_pool;
@@ -1278,15 +1250,15 @@ kiblnd_map_tx_pool(kib_tx_pool_t *tpo)
        int          ipage;
        int          i;
 
-       LASSERT (net != NULL);
+       LASSERT(net != NULL);
 
        dev = net->ibn_dev;
 
        /* pre-mapped messages are not bigger than 1 page */
-       CLASSERT (IBLND_MSG_SIZE <= PAGE_SIZE);
+       CLASSERT(IBLND_MSG_SIZE <= PAGE_SIZE);
 
        /* No fancy arithmetic when we do the buffer calculations */
-       CLASSERT (PAGE_SIZE % IBLND_MSG_SIZE == 0);
+       CLASSERT(PAGE_SIZE % IBLND_MSG_SIZE == 0);
 
        tpo->tpo_hdev = kiblnd_current_hdev(dev);
 
@@ -1300,29 +1272,28 @@ kiblnd_map_tx_pool(kib_tx_pool_t *tpo)
                tx->tx_msgaddr = kiblnd_dma_map_single(
                        tpo->tpo_hdev->ibh_ibdev, tx->tx_msg,
                        IBLND_MSG_SIZE, DMA_TO_DEVICE);
-               LASSERT (!kiblnd_dma_mapping_error(tpo->tpo_hdev->ibh_ibdev,
+               LASSERT(!kiblnd_dma_mapping_error(tpo->tpo_hdev->ibh_ibdev,
                                                   tx->tx_msgaddr));
                KIBLND_UNMAP_ADDR_SET(tx, tx_msgunmap, tx->tx_msgaddr);
 
                list_add(&tx->tx_list, &pool->po_free_list);
 
                page_offset += IBLND_MSG_SIZE;
-               LASSERT (page_offset <= PAGE_SIZE);
+               LASSERT(page_offset <= PAGE_SIZE);
 
                if (page_offset == PAGE_SIZE) {
                        page_offset = 0;
                        ipage++;
-                       LASSERT (ipage <= txpgs->ibp_npages);
+                       LASSERT(ipage <= txpgs->ibp_npages);
                }
        }
 }
 
-struct ib_mr *
-kiblnd_find_dma_mr(kib_hca_dev_t *hdev, __u64 addr, __u64 size)
+struct ib_mr *kiblnd_find_dma_mr(kib_hca_dev_t *hdev, __u64 addr, __u64 size)
 {
        __u64   index;
 
-       LASSERT (hdev->ibh_mrs[0] != NULL);
+       LASSERT(hdev->ibh_mrs[0] != NULL);
 
        if (hdev->ibh_nmrs == 1)
                return hdev->ibh_mrs[0];
@@ -1336,14 +1307,13 @@ kiblnd_find_dma_mr(kib_hca_dev_t *hdev, __u64 addr, __u64 size)
        return NULL;
 }
 
-struct ib_mr *
-kiblnd_find_rd_dma_mr(kib_hca_dev_t *hdev, kib_rdma_desc_t *rd)
+struct ib_mr *kiblnd_find_rd_dma_mr(kib_hca_dev_t *hdev, kib_rdma_desc_t *rd)
 {
        struct ib_mr *prev_mr;
        struct ib_mr *mr;
        int        i;
 
-       LASSERT (hdev->ibh_mrs[0] != NULL);
+       LASSERT(hdev->ibh_mrs[0] != NULL);
 
        if (*kiblnd_tunables.kib_map_on_demand > 0 &&
            *kiblnd_tunables.kib_map_on_demand <= rd->rd_nfrags)
@@ -1370,10 +1340,9 @@ kiblnd_find_rd_dma_mr(kib_hca_dev_t *hdev, kib_rdma_desc_t *rd)
        return mr;
 }
 
-static void
-kiblnd_destroy_fmr_pool(kib_fmr_pool_t *pool)
+static void kiblnd_destroy_fmr_pool(kib_fmr_pool_t *pool)
 {
-       LASSERT (pool->fpo_map_count == 0);
+       LASSERT(pool->fpo_map_count == 0);
 
        if (pool->fpo_fmr_pool != NULL)
                ib_destroy_fmr_pool(pool->fpo_fmr_pool);
@@ -1384,8 +1353,7 @@ kiblnd_destroy_fmr_pool(kib_fmr_pool_t *pool)
        LIBCFS_FREE(pool, sizeof(kib_fmr_pool_t));
 }
 
-static void
-kiblnd_destroy_fmr_pool_list(struct list_head *head)
+static void kiblnd_destroy_fmr_pool_list(struct list_head *head)
 {
        kib_fmr_pool_t *pool;
 
@@ -1410,8 +1378,8 @@ static int kiblnd_fmr_flush_trigger(int ncpts)
        return max(IBLND_FMR_POOL_FLUSH, size);
 }
 
-static int
-kiblnd_create_fmr_pool(kib_fmr_poolset_t *fps, kib_fmr_pool_t **pp_fpo)
+static int kiblnd_create_fmr_pool(kib_fmr_poolset_t *fps,
+                                 kib_fmr_pool_t **pp_fpo)
 {
        /* FMR pool for RDMA */
        kib_dev_t              *dev = fps->fps_net->ibn_dev;
@@ -1451,8 +1419,8 @@ kiblnd_create_fmr_pool(kib_fmr_poolset_t *fps, kib_fmr_pool_t **pp_fpo)
        return 0;
 }
 
-static void
-kiblnd_fail_fmr_poolset(kib_fmr_poolset_t *fps, struct list_head *zombies)
+static void kiblnd_fail_fmr_poolset(kib_fmr_poolset_t *fps,
+                                   struct list_head *zombies)
 {
        if (fps->fps_net == NULL) /* intialized? */
                return;
@@ -1473,8 +1441,7 @@ kiblnd_fail_fmr_poolset(kib_fmr_poolset_t *fps, struct list_head *zombies)
        spin_unlock(&fps->fps_lock);
 }
 
-static void
-kiblnd_fini_fmr_poolset(kib_fmr_poolset_t *fps)
+static void kiblnd_fini_fmr_poolset(kib_fmr_poolset_t *fps)
 {
        if (fps->fps_net != NULL) { /* initialized? */
                kiblnd_destroy_fmr_pool_list(&fps->fps_failed_pool_list);
@@ -1482,9 +1449,9 @@ kiblnd_fini_fmr_poolset(kib_fmr_poolset_t *fps)
        }
 }
 
-static int
-kiblnd_init_fmr_poolset(kib_fmr_poolset_t *fps, int cpt, kib_net_t *net,
-                       int pool_size, int flush_trigger)
+static int kiblnd_init_fmr_poolset(kib_fmr_poolset_t *fps, int cpt,
+                                  kib_net_t *net, int pool_size,
+                                  int flush_trigger)
 {
        kib_fmr_pool_t *fpo;
        int          rc;
@@ -1506,8 +1473,7 @@ kiblnd_init_fmr_poolset(kib_fmr_poolset_t *fps, int cpt, kib_net_t *net,
        return rc;
 }
 
-static int
-kiblnd_fmr_pool_is_idle(kib_fmr_pool_t *fpo, unsigned long now)
+static int kiblnd_fmr_pool_is_idle(kib_fmr_pool_t *fpo, unsigned long now)
 {
        if (fpo->fpo_map_count != 0) /* still in use */
                return 0;
@@ -1516,10 +1482,9 @@ kiblnd_fmr_pool_is_idle(kib_fmr_pool_t *fpo, unsigned long now)
        return cfs_time_aftereq(now, fpo->fpo_deadline);
 }
 
-void
-kiblnd_fmr_pool_unmap(kib_fmr_t *fmr, int status)
+void kiblnd_fmr_pool_unmap(kib_fmr_t *fmr, int status)
 {
-       LIST_HEAD     (zombies);
+       LIST_HEAD(zombies);
        kib_fmr_pool_t    *fpo = fmr->fmr_pool;
        kib_fmr_poolset_t *fps = fpo->fpo_owner;
        unsigned long    now = cfs_time_current();
@@ -1527,11 +1492,11 @@ kiblnd_fmr_pool_unmap(kib_fmr_t *fmr, int status)
        int             rc;
 
        rc = ib_fmr_pool_unmap(fmr->fmr_pfmr);
-       LASSERT (rc == 0);
+       LASSERT(rc == 0);
 
        if (status != 0) {
                rc = ib_flush_fmr_pool(fpo->fpo_fmr_pool);
-               LASSERT (rc == 0);
+               LASSERT(rc == 0);
        }
 
        fmr->fmr_pool = NULL;
@@ -1556,9 +1521,8 @@ kiblnd_fmr_pool_unmap(kib_fmr_t *fmr, int status)
                kiblnd_destroy_fmr_pool_list(&zombies);
 }
 
-int
-kiblnd_fmr_pool_map(kib_fmr_poolset_t *fps, __u64 *pages, int npages,
-                   __u64 iov, kib_fmr_t *fmr)
+int kiblnd_fmr_pool_map(kib_fmr_poolset_t *fps, __u64 *pages, int npages,
+                       __u64 iov, kib_fmr_t *fmr)
 {
        struct ib_pool_fmr *pfmr;
        kib_fmr_pool_t     *fpo;
@@ -1597,7 +1561,8 @@ kiblnd_fmr_pool_map(kib_fmr_poolset_t *fps, __u64 *pages, int npages,
 
        if (fps->fps_increasing) {
                spin_unlock(&fps->fps_lock);
-               CDEBUG(D_NET, "Another thread is allocating new FMR pool, waiting for her to complete\n");
+               CDEBUG(D_NET,
+                       "Another thread is allocating new FMR pool, waiting for her to complete\n");
                schedule();
                goto again;
 
@@ -1627,17 +1592,15 @@ kiblnd_fmr_pool_map(kib_fmr_poolset_t *fps, __u64 *pages, int npages,
        goto again;
 }
 
-static void
-kiblnd_fini_pool(kib_pool_t *pool)
+static void kiblnd_fini_pool(kib_pool_t *pool)
 {
-       LASSERT (list_empty(&pool->po_free_list));
-       LASSERT (pool->po_allocated == 0);
+       LASSERT(list_empty(&pool->po_free_list));
+       LASSERT(pool->po_allocated == 0);
 
        CDEBUG(D_NET, "Finalize %s pool\n", pool->po_owner->ps_name);
 }
 
-static void
-kiblnd_init_pool(kib_poolset_t *ps, kib_pool_t *pool, int size)
+static void kiblnd_init_pool(kib_poolset_t *ps, kib_pool_t *pool, int size)
 {
        CDEBUG(D_NET, "Initialize %s pool\n", ps->ps_name);
 
@@ -1648,8 +1611,7 @@ kiblnd_init_pool(kib_poolset_t *ps, kib_pool_t *pool, int size)
        pool->po_size     = size;
 }
 
-static void
-kiblnd_destroy_pool_list(struct list_head *head)
+static void kiblnd_destroy_pool_list(struct list_head *head)
 {
        kib_pool_t *pool;
 
@@ -1657,13 +1619,12 @@ kiblnd_destroy_pool_list(struct list_head *head)
                pool = list_entry(head->next, kib_pool_t, po_list);
                list_del(&pool->po_list);
 
-               LASSERT (pool->po_owner != NULL);
+               LASSERT(pool->po_owner != NULL);
                pool->po_owner->ps_pool_destroy(pool);
        }
 }
 
-static void
-kiblnd_fail_poolset(kib_poolset_t *ps, struct list_head *zombies)
+static void kiblnd_fail_poolset(kib_poolset_t *ps, struct list_head *zombies)
 {
        if (ps->ps_net == NULL) /* intialized? */
                return;
@@ -1682,8 +1643,7 @@ kiblnd_fail_poolset(kib_poolset_t *ps, struct list_head *zombies)
        spin_unlock(&ps->ps_lock);
 }
 
-static void
-kiblnd_fini_poolset(kib_poolset_t *ps)
+static void kiblnd_fini_poolset(kib_poolset_t *ps)
 {
        if (ps->ps_net != NULL) { /* initialized? */
                kiblnd_destroy_pool_list(&ps->ps_failed_pool_list);
@@ -1691,13 +1651,12 @@ kiblnd_fini_poolset(kib_poolset_t *ps)
        }
 }
 
-static int
-kiblnd_init_poolset(kib_poolset_t *ps, int cpt,
-                   kib_net_t *net, char *name, int size,
-                   kib_ps_pool_create_t po_create,
-                   kib_ps_pool_destroy_t po_destroy,
-                   kib_ps_node_init_t nd_init,
-                   kib_ps_node_fini_t nd_fini)
+static int kiblnd_init_poolset(kib_poolset_t *ps, int cpt,
+                              kib_net_t *net, char *name, int size,
+                              kib_ps_pool_create_t po_create,
+                              kib_ps_pool_destroy_t po_destroy,
+                              kib_ps_node_init_t nd_init,
+                              kib_ps_node_fini_t nd_fini)
 {
        kib_pool_t      *pool;
        int             rc;
@@ -1727,8 +1686,7 @@ kiblnd_init_poolset(kib_poolset_t *ps, int cpt,
        return rc;
 }
 
-static int
-kiblnd_pool_is_idle(kib_pool_t *pool, unsigned long now)
+static int kiblnd_pool_is_idle(kib_pool_t *pool, unsigned long now)
 {
        if (pool->po_allocated != 0) /* still in use */
                return 0;
@@ -1737,10 +1695,9 @@ kiblnd_pool_is_idle(kib_pool_t *pool, unsigned long now)
        return cfs_time_aftereq(now, pool->po_deadline);
 }
 
-void
-kiblnd_pool_free_node(kib_pool_t *pool, struct list_head *node)
+void kiblnd_pool_free_node(kib_pool_t *pool, struct list_head *node)
 {
-       LIST_HEAD  (zombies);
+       LIST_HEAD(zombies);
        kib_poolset_t  *ps = pool->po_owner;
        kib_pool_t     *tmp;
        unsigned long      now = cfs_time_current();
@@ -1750,7 +1707,7 @@ kiblnd_pool_free_node(kib_pool_t *pool, struct list_head *node)
        if (ps->ps_node_fini != NULL)
                ps->ps_node_fini(pool, node);
 
-       LASSERT (pool->po_allocated > 0);
+       LASSERT(pool->po_allocated > 0);
        list_add(node, &pool->po_free_list);
        pool->po_allocated--;
 
@@ -1768,8 +1725,7 @@ kiblnd_pool_free_node(kib_pool_t *pool, struct list_head *node)
                kiblnd_destroy_pool_list(&zombies);
 }
 
-struct list_head *
-kiblnd_pool_alloc_node(kib_poolset_t *ps)
+struct list_head *kiblnd_pool_alloc_node(kib_poolset_t *ps)
 {
        struct list_head            *node;
        kib_pool_t          *pool;
@@ -1831,8 +1787,7 @@ kiblnd_pool_alloc_node(kib_poolset_t *ps)
        goto again;
 }
 
-void
-kiblnd_pmr_pool_unmap(kib_phys_mr_t *pmr)
+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;
@@ -1843,8 +1798,7 @@ kiblnd_pmr_pool_unmap(kib_phys_mr_t *pmr)
                ib_dereg_mr(mr);
 }
 
-int
-kiblnd_pmr_pool_map(kib_pmr_poolset_t *pps, kib_hca_dev_t *hdev,
+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;
@@ -1889,19 +1843,16 @@ kiblnd_pmr_pool_map(kib_pmr_poolset_t *pps, kib_hca_dev_t *hdev,
        return rc;
 }
 
-static void
-kiblnd_destroy_pmr_pool(kib_pool_t *pool)
+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);
-
-       while (!list_empty(&pool->po_free_list)) {
-               pmr = list_entry(pool->po_free_list.next,
-                                    kib_phys_mr_t, pmr_list);
+       LASSERT(pool->po_allocated == 0);
 
-               LASSERT (pmr->pmr_mr == NULL);
+       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) {
@@ -1927,8 +1878,8 @@ static inline int kiblnd_pmr_pool_size(int ncpts)
        return max(IBLND_PMR_POOL, size);
 }
 
-static int
-kiblnd_create_pmr_pool(kib_poolset_t *ps, int size, kib_pool_t **pp_po)
+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;
@@ -1970,13 +1921,12 @@ kiblnd_create_pmr_pool(kib_poolset_t *ps, int size, kib_pool_t **pp_po)
        return 0;
 }
 
-static void
-kiblnd_destroy_tx_pool(kib_pool_t *pool)
+static void kiblnd_destroy_tx_pool(kib_pool_t *pool)
 {
        kib_tx_pool_t  *tpo = container_of(pool, kib_tx_pool_t, tpo_pool);
        int          i;
 
-       LASSERT (pool->po_allocated == 0);
+       LASSERT(pool->po_allocated == 0);
 
        if (tpo->tpo_tx_pages != NULL) {
                kiblnd_unmap_tx_pool(tpo);
@@ -2026,8 +1976,8 @@ static int kiblnd_tx_pool_size(int ncpts)
        return max(IBLND_TX_POOL, ntx);
 }
 
-static int
-kiblnd_create_tx_pool(kib_poolset_t *ps, int size, kib_pool_t **pp_po)
+static int kiblnd_create_tx_pool(kib_poolset_t *ps, int size,
+                                kib_pool_t **pp_po)
 {
        int         i;
        int         npg;
@@ -2110,8 +2060,7 @@ kiblnd_create_tx_pool(kib_poolset_t *ps, int size, kib_pool_t **pp_po)
        return -ENOMEM;
 }
 
-static void
-kiblnd_tx_init(kib_pool_t *pool, struct list_head *node)
+static void kiblnd_tx_init(kib_pool_t *pool, struct list_head *node)
 {
        kib_tx_poolset_t *tps = container_of(pool->po_owner, kib_tx_poolset_t,
                                             tps_poolset);
@@ -2120,8 +2069,7 @@ kiblnd_tx_init(kib_pool_t *pool, struct list_head *node)
        tx->tx_cookie = tps->tps_next_tx_cookie++;
 }
 
-static void
-kiblnd_net_fini_pools(kib_net_t *net)
+static void kiblnd_net_fini_pools(kib_net_t *net)
 {
        int     i;
 
@@ -2162,8 +2110,7 @@ kiblnd_net_fini_pools(kib_net_t *net)
        }
 }
 
-static int
-kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts)
+static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts)
 {
        unsigned long   flags;
        int             cpt;
@@ -2291,8 +2238,7 @@ kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts)
        return rc;
 }
 
-static int
-kiblnd_hdev_get_attr(kib_hca_dev_t *hdev)
+static int kiblnd_hdev_get_attr(kib_hca_dev_t *hdev)
 {
        struct ib_device_attr *attr;
        int                 rc;
@@ -2336,8 +2282,7 @@ kiblnd_hdev_get_attr(kib_hca_dev_t *hdev)
        return -EINVAL;
 }
 
-static void
-kiblnd_hdev_cleanup_mrs(kib_hca_dev_t *hdev)
+static void kiblnd_hdev_cleanup_mrs(kib_hca_dev_t *hdev)
 {
        int     i;
 
@@ -2356,8 +2301,7 @@ kiblnd_hdev_cleanup_mrs(kib_hca_dev_t *hdev)
        hdev->ibh_nmrs = 0;
 }
 
-void
-kiblnd_hdev_destroy(kib_hca_dev_t *hdev)
+void kiblnd_hdev_destroy(kib_hca_dev_t *hdev)
 {
        kiblnd_hdev_cleanup_mrs(hdev);
 
@@ -2370,8 +2314,7 @@ kiblnd_hdev_destroy(kib_hca_dev_t *hdev)
        LIBCFS_FREE(hdev, sizeof(*hdev));
 }
 
-static int
-kiblnd_hdev_setup_mrs(kib_hca_dev_t *hdev)
+static int kiblnd_hdev_setup_mrs(kib_hca_dev_t *hdev)
 {
        struct ib_mr *mr;
        int        i;
@@ -2442,7 +2385,7 @@ kiblnd_hdev_setup_mrs(kib_hca_dev_t *hdev)
                        return PTR_ERR(mr);
                }
 
-               LASSERT (iova == ipb.addr);
+               LASSERT(iova == ipb.addr);
 
                hdev->ibh_mrs[i] = mr;
        }
@@ -2454,14 +2397,14 @@ out:
        return 0;
 }
 
-static int
-kiblnd_dummy_callback(struct rdma_cm_id *cmid, struct rdma_cm_event *event)
-{       /* DUMMY */
+/* DUMMY */
+static int kiblnd_dummy_callback(struct rdma_cm_id *cmid,
+                                struct rdma_cm_event *event)
+{
        return 0;
 }
 
-static int
-kiblnd_dev_need_failover(kib_dev_t *dev)
+static int kiblnd_dev_need_failover(kib_dev_t *dev)
 {
        struct rdma_cm_id  *cmid;
        struct sockaddr_in  srcaddr;
@@ -2516,12 +2459,11 @@ kiblnd_dev_need_failover(kib_dev_t *dev)
        return 1;
 }
 
-int
-kiblnd_dev_failover(kib_dev_t *dev)
+int kiblnd_dev_failover(kib_dev_t *dev)
 {
-       LIST_HEAD      (zombie_tpo);
-       LIST_HEAD      (zombie_ppo);
-       LIST_HEAD      (zombie_fpo);
+       LIST_HEAD(zombie_tpo);
+       LIST_HEAD(zombie_ppo);
+       LIST_HEAD(zombie_fpo);
        struct rdma_cm_id  *cmid  = NULL;
        kib_hca_dev_t      *hdev  = NULL;
        kib_hca_dev_t      *old;
@@ -2532,7 +2474,7 @@ kiblnd_dev_failover(kib_dev_t *dev)
        int              rc = 0;
        int                 i;
 
-       LASSERT (*kiblnd_tunables.kib_dev_failover > 1 ||
+       LASSERT(*kiblnd_tunables.kib_dev_failover > 1 ||
                 dev->ibd_can_failover ||
                 dev->ibd_hdev == NULL);
 
@@ -2655,11 +2597,10 @@ kiblnd_dev_failover(kib_dev_t *dev)
        return rc;
 }
 
-void
-kiblnd_destroy_dev (kib_dev_t *dev)
+void kiblnd_destroy_dev(kib_dev_t *dev)
 {
-       LASSERT (dev->ibd_nnets == 0);
-       LASSERT (list_empty(&dev->ibd_nets));
+       LASSERT(dev->ibd_nnets == 0);
+       LASSERT(list_empty(&dev->ibd_nets));
 
        list_del(&dev->ibd_fail_list);
        list_del(&dev->ibd_list);
@@ -2670,8 +2611,7 @@ kiblnd_destroy_dev (kib_dev_t *dev)
        LIBCFS_FREE(dev, sizeof(*dev));
 }
 
-static kib_dev_t *
-kiblnd_create_dev(char *ifname)
+static kib_dev_t *kiblnd_create_dev(char *ifname)
 {
        struct net_device *netdev;
        kib_dev_t        *dev;
@@ -2723,13 +2663,12 @@ kiblnd_create_dev(char *ifname)
        return dev;
 }
 
-static void
-kiblnd_base_shutdown(void)
+static void kiblnd_base_shutdown(void)
 {
        struct kib_sched_info   *sched;
        int                     i;
 
-       LASSERT (list_empty(&kiblnd_data.kib_devs));
+       LASSERT(list_empty(&kiblnd_data.kib_devs));
 
        CDEBUG(D_MALLOC, "before LND base cleanup: kmem %d\n",
               atomic_read(&libcfs_kmemory));
@@ -2740,12 +2679,11 @@ kiblnd_base_shutdown(void)
 
        case IBLND_INIT_ALL:
        case IBLND_INIT_DATA:
-               LASSERT (kiblnd_data.kib_peers != NULL);
-               for (i = 0; i < kiblnd_data.kib_peer_hash_size; i++) {
-                       LASSERT (list_empty(&kiblnd_data.kib_peers[i]));
-               }
-               LASSERT (list_empty(&kiblnd_data.kib_connd_zombies));
-               LASSERT (list_empty(&kiblnd_data.kib_connd_conns));
+               LASSERT(kiblnd_data.kib_peers != NULL);
+               for (i = 0; i < kiblnd_data.kib_peer_hash_size; i++)
+                       LASSERT(list_empty(&kiblnd_data.kib_peers[i]));
+               LASSERT(list_empty(&kiblnd_data.kib_connd_zombies));
+               LASSERT(list_empty(&kiblnd_data.kib_connd_conns));
 
                /* flag threads to terminate; wake and wait for them to die */
                kiblnd_data.kib_shutdown = 1;
@@ -2762,7 +2700,8 @@ kiblnd_base_shutdown(void)
                i = 2;
                while (atomic_read(&kiblnd_data.kib_nthreads) != 0) {
                        i++;
-                       CDEBUG(((i & (-i)) == i) ? D_WARNING : D_NET, /* power of 2? */
+                       /* power of 2 ? */
+                       CDEBUG(((i & (-i)) == i) ? D_WARNING : D_NET,
                               "Waiting for %d threads to terminate\n",
                               atomic_read(&kiblnd_data.kib_nthreads));
                        set_current_state(TASK_UNINTERRUPTIBLE);
@@ -2791,8 +2730,7 @@ kiblnd_base_shutdown(void)
        module_put(THIS_MODULE);
 }
 
-void
-kiblnd_shutdown (lnet_ni_t *ni)
+void kiblnd_shutdown(lnet_ni_t *ni)
 {
        kib_net_t       *net = ni->ni_data;
        rwlock_t     *g_lock = &kiblnd_data.kib_global_lock;
@@ -2842,7 +2780,7 @@ kiblnd_shutdown (lnet_ni_t *ni)
                /* fall through */
 
        case IBLND_INIT_NOTHING:
-               LASSERT (atomic_read(&net->ibn_nconns) == 0);
+               LASSERT(atomic_read(&net->ibn_nconns) == 0);
 
                if (net->ibn_dev != NULL &&
                    net->ibn_dev->ibd_nnets == 0)
@@ -2862,20 +2800,19 @@ kiblnd_shutdown (lnet_ni_t *ni)
 out:
        if (list_empty(&kiblnd_data.kib_devs))
                kiblnd_base_shutdown();
-       return;
 }
 
-static int
-kiblnd_base_startup(void)
+static int kiblnd_base_startup(void)
 {
        struct kib_sched_info   *sched;
        int                     rc;
        int                     i;
 
-       LASSERT (kiblnd_data.kib_init == IBLND_INIT_NOTHING);
+       LASSERT(kiblnd_data.kib_init == IBLND_INIT_NOTHING);
 
        try_module_get(THIS_MODULE);
-       memset(&kiblnd_data, 0, sizeof(kiblnd_data)); /* zero pointers, flags etc */
+       /* zero pointers, flags etc */
+       memset(&kiblnd_data, 0, sizeof(kiblnd_data));
 
        rwlock_init(&kiblnd_data.kib_global_lock);
 
@@ -2886,9 +2823,8 @@ kiblnd_base_startup(void)
        LIBCFS_ALLOC(kiblnd_data.kib_peers,
                     sizeof(struct list_head) *
                            kiblnd_data.kib_peer_hash_size);
-       if (kiblnd_data.kib_peers == NULL) {
+       if (kiblnd_data.kib_peers == NULL)
                goto failed;
-       }
        for (i = 0; i < kiblnd_data.kib_peer_hash_size; i++)
                INIT_LIST_HEAD(&kiblnd_data.kib_peers[i]);
 
@@ -2955,8 +2891,7 @@ kiblnd_base_startup(void)
        return -ENETDOWN;
 }
 
-static int
-kiblnd_start_schedulers(struct kib_sched_info *sched)
+static int kiblnd_start_schedulers(struct kib_sched_info *sched)
 {
        int     rc = 0;
        int     nthrs;
@@ -2974,12 +2909,13 @@ kiblnd_start_schedulers(struct kib_sched_info *sched)
        } else {
                LASSERT(sched->ibs_nthreads <= sched->ibs_nthreads_max);
                /* increase one thread if there is new interface */
-               nthrs = (sched->ibs_nthreads < sched->ibs_nthreads_max);
+               nthrs = sched->ibs_nthreads < sched->ibs_nthreads_max;
        }
 
        for (i = 0; i < nthrs; i++) {
                long    id;
                char    name[20];
+
                id = KIB_THREAD_ID(sched->ibs_cpt, sched->ibs_nthreads + i);
                snprintf(name, sizeof(name), "kiblnd_sd_%02ld_%02ld",
                         KIB_THREAD_CPT(id), KIB_THREAD_TID(id));
@@ -2996,8 +2932,8 @@ kiblnd_start_schedulers(struct kib_sched_info *sched)
        return rc;
 }
 
-static int
-kiblnd_dev_start_threads(kib_dev_t *dev, int newdev, __u32 *cpts, int ncpts)
+static int kiblnd_dev_start_threads(kib_dev_t *dev, int newdev, __u32 *cpts,
+                                   int ncpts)
 {
        int     cpt;
        int     rc;
@@ -3022,8 +2958,7 @@ kiblnd_dev_start_threads(kib_dev_t *dev, int newdev, __u32 *cpts, int ncpts)
        return 0;
 }
 
-static kib_dev_t *
-kiblnd_dev_search(char *ifname)
+static kib_dev_t *kiblnd_dev_search(char *ifname)
 {
        kib_dev_t       *alias = NULL;
        kib_dev_t       *dev;
@@ -3055,8 +2990,7 @@ kiblnd_dev_search(char *ifname)
        return alias;
 }
 
-int
-kiblnd_startup (lnet_ni_t *ni)
+int kiblnd_startup(lnet_ni_t *ni)
 {
        char                 *ifname;
        kib_dev_t               *ibdev = NULL;
@@ -3066,7 +3000,7 @@ kiblnd_startup (lnet_ni_t *ni)
        int                    rc;
        int                       newdev;
 
-       LASSERT (ni->ni_lnd == &the_o2iblnd);
+       LASSERT(ni->ni_lnd == &the_o2iblnd);
 
        if (kiblnd_data.kib_init == IBLND_INIT_NOTHING) {
                rc = kiblnd_base_startup();
@@ -3090,7 +3024,7 @@ kiblnd_startup (lnet_ni_t *ni)
        if (ni->ni_interfaces[0] != NULL) {
                /* Use the IPoIB interface specified in 'networks=' */
 
-               CLASSERT (LNET_MAX_INTERFACES > 1);
+               CLASSERT(LNET_MAX_INTERFACES > 1);
                if (ni->ni_interfaces[1] != NULL) {
                        CERROR("Multiple interfaces not supported\n");
                        goto failed;
@@ -3150,22 +3084,22 @@ net_failed:
        return -ENETDOWN;
 }
 
-static void __exit
-kiblnd_module_fini (void)
+static void __exit kiblnd_module_fini(void)
 {
        lnet_unregister_lnd(&the_o2iblnd);
 }
 
-static int __init
-kiblnd_module_init (void)
+static int __init kiblnd_module_init(void)
 {
        int    rc;
 
-       CLASSERT (sizeof(kib_msg_t) <= IBLND_MSG_SIZE);
-       CLASSERT (offsetof(kib_msg_t, ibm_u.get.ibgm_rd.rd_frags[IBLND_MAX_RDMA_FRAGS])
-                 <= IBLND_MSG_SIZE);
-       CLASSERT (offsetof(kib_msg_t, ibm_u.putack.ibpam_rd.rd_frags[IBLND_MAX_RDMA_FRAGS])
-                 <= IBLND_MSG_SIZE);
+       CLASSERT(sizeof(kib_msg_t) <= IBLND_MSG_SIZE);
+       CLASSERT(offsetof(kib_msg_t,
+               ibm_u.get.ibgm_rd.rd_frags[IBLND_MAX_RDMA_FRAGS])
+               <= IBLND_MSG_SIZE);
+       CLASSERT(offsetof(kib_msg_t,
+               ibm_u.putack.ibpam_rd.rd_frags[IBLND_MAX_RDMA_FRAGS])
+               <= IBLND_MSG_SIZE);
 
        rc = kiblnd_tunables_init();
        if (rc != 0)
index ab128dee9483bb7784e6ede69256f449e8d26dab..cd664d025f418da9f118423061f01d6670adfd36 100644 (file)
@@ -46,8 +46,8 @@
 #include <linux/errno.h>
 #include <linux/unistd.h>
 #include <linux/uio.h>
+#include <linux/uaccess.h>
 
-#include <asm/uaccess.h>
 #include <asm/io.h>
 
 #include <linux/fs.h>
index 48d885dc51d93abf9c3504de3ea319433ef46388..dbf3749831f9c5993c44e25c6b5f7908347f227f 100644 (file)
 #include "o2iblnd.h"
 
 static void
-kiblnd_tx_done (lnet_ni_t *ni, kib_tx_t *tx)
+kiblnd_tx_done(lnet_ni_t *ni, kib_tx_t *tx)
 {
        lnet_msg_t *lntmsg[2];
        kib_net_t  *net = ni->ni_data;
        int      rc;
        int      i;
 
-       LASSERT (net != NULL);
-       LASSERT (!in_interrupt());
-       LASSERT (!tx->tx_queued);              /* mustn't be queued for sending */
-       LASSERT (tx->tx_sending == 0);    /* mustn't be awaiting sent callback */
-       LASSERT (!tx->tx_waiting);            /* mustn't be awaiting peer response */
-       LASSERT (tx->tx_pool != NULL);
+       LASSERT(net != NULL);
+       LASSERT(!in_interrupt());
+       LASSERT(!tx->tx_queued);               /* mustn't be queued for sending */
+       LASSERT(tx->tx_sending == 0);     /* mustn't be awaiting sent callback */
+       LASSERT(!tx->tx_waiting);             /* mustn't be awaiting peer response */
+       LASSERT(tx->tx_pool != NULL);
 
        kiblnd_unmap_tx(ni, tx);
 
@@ -63,7 +63,7 @@ kiblnd_tx_done (lnet_ni_t *ni, kib_tx_t *tx)
        rc = tx->tx_status;
 
        if (tx->tx_conn != NULL) {
-               LASSERT (ni == tx->tx_conn->ibc_peer->ibp_ni);
+               LASSERT(ni == tx->tx_conn->ibc_peer->ibp_ni);
 
                kiblnd_conn_decref(tx->tx_conn);
                tx->tx_conn = NULL;
@@ -84,12 +84,12 @@ kiblnd_tx_done (lnet_ni_t *ni, kib_tx_t *tx)
 }
 
 void
-kiblnd_txlist_done (lnet_ni_t *ni, struct list_head *txlist, int status)
+kiblnd_txlist_done(lnet_ni_t *ni, struct list_head *txlist, int status)
 {
        kib_tx_t *tx;
 
-       while (!list_empty (txlist)) {
-               tx = list_entry (txlist->next, kib_tx_t, tx_list);
+       while (!list_empty(txlist)) {
+               tx = list_entry(txlist->next, kib_tx_t, tx_list);
 
                list_del(&tx->tx_list);
                /* complete now */
@@ -113,16 +113,16 @@ kiblnd_get_idle_tx(lnet_ni_t *ni, lnet_nid_t target)
                return NULL;
        tx = container_of(node, kib_tx_t, tx_list);
 
-       LASSERT (tx->tx_nwrq == 0);
-       LASSERT (!tx->tx_queued);
-       LASSERT (tx->tx_sending == 0);
-       LASSERT (!tx->tx_waiting);
-       LASSERT (tx->tx_status == 0);
-       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);
+       LASSERT(tx->tx_nwrq == 0);
+       LASSERT(!tx->tx_queued);
+       LASSERT(tx->tx_sending == 0);
+       LASSERT(!tx->tx_waiting);
+       LASSERT(tx->tx_status == 0);
+       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;
 }
@@ -143,7 +143,7 @@ kiblnd_drop_rx(kib_rx_t *rx)
 }
 
 int
-kiblnd_post_rx (kib_rx_t *rx, int credit)
+kiblnd_post_rx(kib_rx_t *rx, int credit)
 {
        kib_conn_t       *conn = rx->rx_conn;
        kib_net_t         *net = conn->ibc_peer->ibp_ni->ni_data;
@@ -151,14 +151,14 @@ kiblnd_post_rx (kib_rx_t *rx, int credit)
        struct ib_mr       *mr;
        int              rc;
 
-       LASSERT (net != NULL);
-       LASSERT (!in_interrupt());
-       LASSERT (credit == IBLND_POSTRX_NO_CREDIT ||
-                credit == IBLND_POSTRX_PEER_CREDIT ||
-                credit == IBLND_POSTRX_RSRVD_CREDIT);
+       LASSERT(net != NULL);
+       LASSERT(!in_interrupt());
+       LASSERT(credit == IBLND_POSTRX_NO_CREDIT ||
+               credit == IBLND_POSTRX_PEER_CREDIT ||
+               credit == IBLND_POSTRX_RSRVD_CREDIT);
 
        mr = kiblnd_find_dma_mr(conn->ibc_hdev, rx->rx_msgaddr, IBLND_MSG_SIZE);
-       LASSERT (mr != NULL);
+       LASSERT(mr != NULL);
 
        rx->rx_sge.lkey   = mr->lkey;
        rx->rx_sge.addr   = rx->rx_msgaddr;
@@ -169,8 +169,8 @@ kiblnd_post_rx (kib_rx_t *rx, int credit)
        rx->rx_wrq.num_sge = 1;
        rx->rx_wrq.wr_id = kiblnd_ptr2wreqid(rx, IBLND_WID_RX);
 
-       LASSERT (conn->ibc_state >= IBLND_CONN_INIT);
-       LASSERT (rx->rx_nob >= 0);            /* not posted */
+       LASSERT(conn->ibc_state >= IBLND_CONN_INIT);
+       LASSERT(rx->rx_nob >= 0);             /* not posted */
 
        if (conn->ibc_state > IBLND_CONN_ESTABLISHED) {
                kiblnd_drop_rx(rx);          /* No more posts for this rx */
@@ -217,8 +217,8 @@ kiblnd_find_waiting_tx_locked(kib_conn_t *conn, int txtype, __u64 cookie)
        list_for_each(tmp, &conn->ibc_active_txs) {
                kib_tx_t *tx = list_entry(tmp, kib_tx_t, tx_list);
 
-               LASSERT (!tx->tx_queued);
-               LASSERT (tx->tx_sending != 0 || tx->tx_waiting);
+               LASSERT(!tx->tx_queued);
+               LASSERT(tx->tx_sending != 0 || tx->tx_waiting);
 
                if (tx->tx_cookie != cookie)
                        continue;
@@ -293,7 +293,7 @@ kiblnd_send_completion(kib_conn_t *conn, int type, int status, __u64 cookie)
 }
 
 static void
-kiblnd_handle_rx (kib_rx_t *rx)
+kiblnd_handle_rx(kib_rx_t *rx)
 {
        kib_msg_t    *msg = rx->rx_msg;
        kib_conn_t   *conn = rx->rx_conn;
@@ -304,11 +304,11 @@ kiblnd_handle_rx (kib_rx_t *rx)
        int        rc2;
        int        post_credit;
 
-       LASSERT (conn->ibc_state >= IBLND_CONN_ESTABLISHED);
+       LASSERT(conn->ibc_state >= IBLND_CONN_ESTABLISHED);
 
-       CDEBUG (D_NET, "Received %x[%d] from %s\n",
-               msg->ibm_type, credits,
-               libcfs_nid2str(conn->ibc_peer->ibp_nid));
+       CDEBUG(D_NET, "Received %x[%d] from %s\n",
+              msg->ibm_type, credits,
+              libcfs_nid2str(conn->ibc_peer->ibp_nid));
 
        if (credits != 0) {
                /* Have I received credits that will let me send? */
@@ -377,8 +377,8 @@ kiblnd_handle_rx (kib_rx_t *rx)
                break;
 
        case IBLND_MSG_PUT_NAK:
-               CWARN ("PUT_NACK from %s\n",
-                      libcfs_nid2str(conn->ibc_peer->ibp_nid));
+               CWARN("PUT_NACK from %s\n",
+                     libcfs_nid2str(conn->ibc_peer->ibp_nid));
                post_credit = IBLND_POSTRX_RSRVD_CREDIT;
                kiblnd_handle_completion(conn, IBLND_MSG_PUT_REQ,
                                         msg->ibm_u.completion.ibcm_status,
@@ -402,7 +402,7 @@ kiblnd_handle_rx (kib_rx_t *rx)
                        break;
                }
 
-               LASSERT (tx->tx_waiting);
+               LASSERT(tx->tx_waiting);
                /* CAVEAT EMPTOR: I could be racing with tx_complete, but...
                 * (a) I can overwrite tx_msg since my peer has received it!
                 * (b) tx_waiting set tells tx_complete() it's not done. */
@@ -454,7 +454,7 @@ kiblnd_handle_rx (kib_rx_t *rx)
 }
 
 static void
-kiblnd_rx_complete (kib_rx_t *rx, int status, int nob)
+kiblnd_rx_complete(kib_rx_t *rx, int status, int nob)
 {
        kib_msg_t    *msg = rx->rx_msg;
        kib_conn_t   *conn = rx->rx_conn;
@@ -463,8 +463,8 @@ kiblnd_rx_complete (kib_rx_t *rx, int status, int nob)
        int        rc;
        int        err = -EIO;
 
-       LASSERT (net != NULL);
-       LASSERT (rx->rx_nob < 0);              /* was posted */
+       LASSERT(net != NULL);
+       LASSERT(rx->rx_nob < 0);               /* was posted */
        rx->rx_nob = 0;                  /* isn't now */
 
        if (conn->ibc_state > IBLND_CONN_ESTABLISHED)
@@ -476,12 +476,12 @@ kiblnd_rx_complete (kib_rx_t *rx, int status, int nob)
                goto failed;
        }
 
-       LASSERT (nob >= 0);
+       LASSERT(nob >= 0);
        rx->rx_nob = nob;
 
        rc = kiblnd_unpack_msg(msg, rx->rx_nob);
        if (rc != 0) {
-               CERROR ("Error %d unpacking rx from %s\n",
+               CERROR("Error %d unpacking rx from %s\n",
                        rc, libcfs_nid2str(conn->ibc_peer->ibp_nid));
                goto failed;
        }
@@ -490,7 +490,7 @@ kiblnd_rx_complete (kib_rx_t *rx, int status, int nob)
            msg->ibm_dstnid != ni->ni_nid ||
            msg->ibm_srcstamp != conn->ibc_incarnation ||
            msg->ibm_dststamp != net->ibn_incarnation) {
-               CERROR ("Stale rx from %s\n",
+               CERROR("Stale rx from %s\n",
                        libcfs_nid2str(conn->ibc_peer->ibp_nid));
                err = -ESTALE;
                goto failed;
@@ -525,13 +525,13 @@ kiblnd_rx_complete (kib_rx_t *rx, int status, int nob)
 }
 
 static struct page *
-kiblnd_kvaddr_to_page (unsigned long vaddr)
+kiblnd_kvaddr_to_page(unsigned long vaddr)
 {
        struct page *page;
 
        if (is_vmalloc_addr((void *)vaddr)) {
-               page = vmalloc_to_page ((void *)vaddr);
-               LASSERT (page != NULL);
+               page = vmalloc_to_page((void *)vaddr);
+               LASSERT(page != NULL);
                return page;
        }
 #ifdef CONFIG_HIGHMEM
@@ -542,8 +542,8 @@ kiblnd_kvaddr_to_page (unsigned long vaddr)
                LBUG();
        }
 #endif
-       page = virt_to_page (vaddr);
-       LASSERT (page != NULL);
+       page = virt_to_page(vaddr);
+       LASSERT(page != NULL);
        return page;
 }
 
@@ -567,7 +567,7 @@ kiblnd_fmr_map_tx(kib_net_t *net, kib_tx_t *tx, kib_rdma_desc_t *rd, int nob)
        for (i = 0, npages = 0; i < rd->rd_nfrags; i++) {
                for (size = 0; size <  rd->rd_frags[i].rf_nob;
                               size += hdev->ibh_page_size) {
-                       pages[npages ++] = (rd->rd_frags[i].rf_addr &
+                       pages[npages++] = (rd->rd_frags[i].rf_addr &
                                            hdev->ibh_page_mask) + size;
                }
        }
@@ -577,7 +577,7 @@ kiblnd_fmr_map_tx(kib_net_t *net, kib_tx_t *tx, kib_rdma_desc_t *rd, int nob)
        fps = net->ibn_fmr_ps[cpt];
        rc = kiblnd_fmr_pool_map(fps, pages, npages, 0, &tx->tx_u.fmr);
        if (rc != 0) {
-               CERROR ("Can't map %d pages: %d\n", npages, rc);
+               CERROR("Can't map %d pages: %d\n", npages, rc);
                return rc;
        }
 
@@ -706,26 +706,26 @@ kiblnd_setup_rd_iov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd,
        int              fragnob;
        int              page_offset;
 
-       LASSERT (nob > 0);
-       LASSERT (niov > 0);
-       LASSERT (net != NULL);
+       LASSERT(nob > 0);
+       LASSERT(niov > 0);
+       LASSERT(net != NULL);
 
        while (offset >= iov->iov_len) {
                offset -= iov->iov_len;
                niov--;
                iov++;
-               LASSERT (niov > 0);
+               LASSERT(niov > 0);
        }
 
        sg = tx->tx_frags;
        do {
-               LASSERT (niov > 0);
+               LASSERT(niov > 0);
 
                vaddr = ((unsigned long)iov->iov_base) + offset;
                page_offset = vaddr & (PAGE_SIZE - 1);
                page = kiblnd_kvaddr_to_page(vaddr);
                if (page == NULL) {
-                       CERROR ("Can't find page\n");
+                       CERROR("Can't find page\n");
                        return -EFAULT;
                }
 
@@ -749,7 +749,7 @@ kiblnd_setup_rd_iov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd,
 }
 
 static int
-kiblnd_setup_rd_kiov (lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd,
+kiblnd_setup_rd_kiov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd,
                      int nkiov, lnet_kiov_t *kiov, int offset, int nob)
 {
        kib_net_t         *net = ni->ni_data;
@@ -758,20 +758,20 @@ kiblnd_setup_rd_kiov (lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd,
 
        CDEBUG(D_NET, "niov %d offset %d nob %d\n", nkiov, offset, nob);
 
-       LASSERT (nob > 0);
-       LASSERT (nkiov > 0);
-       LASSERT (net != NULL);
+       LASSERT(nob > 0);
+       LASSERT(nkiov > 0);
+       LASSERT(net != NULL);
 
        while (offset >= kiov->kiov_len) {
                offset -= kiov->kiov_len;
                nkiov--;
                kiov++;
-               LASSERT (nkiov > 0);
+               LASSERT(nkiov > 0);
        }
 
        sg = tx->tx_frags;
        do {
-               LASSERT (nkiov > 0);
+               LASSERT(nkiov > 0);
 
                fragnob = min((int)(kiov->kiov_len - offset), nob);
 
@@ -789,7 +789,7 @@ kiblnd_setup_rd_kiov (lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd,
 }
 
 static int
-kiblnd_post_tx_locked (kib_conn_t *conn, kib_tx_t *tx, int credit)
+kiblnd_post_tx_locked(kib_conn_t *conn, kib_tx_t *tx, int credit)
        __releases(conn->ibc_lock)
        __acquires(conn->ibc_lock)
 {
@@ -800,16 +800,16 @@ kiblnd_post_tx_locked (kib_conn_t *conn, kib_tx_t *tx, int credit)
        int             done;
        struct ib_send_wr *bad_wrq;
 
-       LASSERT (tx->tx_queued);
+       LASSERT(tx->tx_queued);
        /* We rely on this for QP sizing */
-       LASSERT (tx->tx_nwrq > 0);
-       LASSERT (tx->tx_nwrq <= 1 + IBLND_RDMA_FRAGS(ver));
+       LASSERT(tx->tx_nwrq > 0);
+       LASSERT(tx->tx_nwrq <= 1 + IBLND_RDMA_FRAGS(ver));
 
-       LASSERT (credit == 0 || credit == 1);
-       LASSERT (conn->ibc_outstanding_credits >= 0);
-       LASSERT (conn->ibc_outstanding_credits <= IBLND_MSG_QUEUE_SIZE(ver));
-       LASSERT (conn->ibc_credits >= 0);
-       LASSERT (conn->ibc_credits <= IBLND_MSG_QUEUE_SIZE(ver));
+       LASSERT(credit == 0 || credit == 1);
+       LASSERT(conn->ibc_outstanding_credits >= 0);
+       LASSERT(conn->ibc_outstanding_credits <= IBLND_MSG_QUEUE_SIZE(ver));
+       LASSERT(conn->ibc_credits >= 0);
+       LASSERT(conn->ibc_credits <= IBLND_MSG_QUEUE_SIZE(ver));
 
        if (conn->ibc_nsends_posted == IBLND_CONCURRENT_SENDS(ver)) {
                /* tx completions outstanding... */
@@ -923,7 +923,7 @@ kiblnd_post_tx_locked (kib_conn_t *conn, kib_tx_t *tx, int credit)
 }
 
 void
-kiblnd_check_sends (kib_conn_t *conn)
+kiblnd_check_sends(kib_conn_t *conn)
 {
        int     ver = conn->ibc_version;
        lnet_ni_t *ni = conn->ibc_peer->ibp_ni;
@@ -938,10 +938,10 @@ kiblnd_check_sends (kib_conn_t *conn)
 
        spin_lock(&conn->ibc_lock);
 
-       LASSERT (conn->ibc_nsends_posted <= IBLND_CONCURRENT_SENDS(ver));
-       LASSERT (!IBLND_OOB_CAPABLE(ver) ||
+       LASSERT(conn->ibc_nsends_posted <= IBLND_CONCURRENT_SENDS(ver));
+       LASSERT(!IBLND_OOB_CAPABLE(ver) ||
                 conn->ibc_noops_posted <= IBLND_OOB_MSGS(ver));
-       LASSERT (conn->ibc_reserved_credits >= 0);
+       LASSERT(conn->ibc_reserved_credits >= 0);
 
        while (conn->ibc_reserved_credits > 0 &&
               !list_empty(&conn->ibc_tx_queue_rsrvd)) {
@@ -974,7 +974,7 @@ kiblnd_check_sends (kib_conn_t *conn)
                        tx = list_entry(conn->ibc_tx_queue_nocred.next,
                                            kib_tx_t, tx_list);
                } else if (!list_empty(&conn->ibc_tx_noops)) {
-                       LASSERT (!IBLND_OOB_CAPABLE(ver));
+                       LASSERT(!IBLND_OOB_CAPABLE(ver));
                        credit = 1;
                        tx = list_entry(conn->ibc_tx_noops.next,
                                        kib_tx_t, tx_list);
@@ -995,13 +995,13 @@ kiblnd_check_sends (kib_conn_t *conn)
 }
 
 static void
-kiblnd_tx_complete (kib_tx_t *tx, int status)
+kiblnd_tx_complete(kib_tx_t *tx, int status)
 {
        int        failed = (status != IB_WC_SUCCESS);
        kib_conn_t   *conn = tx->tx_conn;
        int        idle;
 
-       LASSERT (tx->tx_sending > 0);
+       LASSERT(tx->tx_sending > 0);
 
        if (failed) {
                if (conn->ibc_state == IBLND_CONN_ESTABLISHED)
@@ -1049,22 +1049,22 @@ kiblnd_tx_complete (kib_tx_t *tx, int status)
 }
 
 void
-kiblnd_init_tx_msg (lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob)
+kiblnd_init_tx_msg(lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob)
 {
        kib_hca_dev_t     *hdev = tx->tx_pool->tpo_hdev;
        struct ib_sge     *sge = &tx->tx_sge[tx->tx_nwrq];
        struct ib_send_wr *wrq = &tx->tx_wrq[tx->tx_nwrq];
-       int             nob = offsetof (kib_msg_t, ibm_u) + body_nob;
+       int             nob = offsetof(kib_msg_t, ibm_u) + body_nob;
        struct ib_mr      *mr;
 
-       LASSERT (tx->tx_nwrq >= 0);
-       LASSERT (tx->tx_nwrq < IBLND_MAX_RDMA_FRAGS + 1);
-       LASSERT (nob <= IBLND_MSG_SIZE);
+       LASSERT(tx->tx_nwrq >= 0);
+       LASSERT(tx->tx_nwrq < IBLND_MAX_RDMA_FRAGS + 1);
+       LASSERT(nob <= IBLND_MSG_SIZE);
 
        kiblnd_init_msg(tx->tx_msg, type, body_nob);
 
        mr = kiblnd_find_dma_mr(hdev, tx->tx_msgaddr, nob);
-       LASSERT (mr != NULL);
+       LASSERT(mr != NULL);
 
        sge->lkey   = mr->lkey;
        sge->addr   = tx->tx_msgaddr;
@@ -1083,7 +1083,7 @@ kiblnd_init_tx_msg (lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob)
 }
 
 int
-kiblnd_init_rdma (kib_conn_t *conn, kib_tx_t *tx, int type,
+kiblnd_init_rdma(kib_conn_t *conn, kib_tx_t *tx, int type,
                  int resid, kib_rdma_desc_t *dstrd, __u64 dstcookie)
 {
        kib_msg_t        *ibmsg = tx->tx_msg;
@@ -1095,9 +1095,9 @@ kiblnd_init_rdma (kib_conn_t *conn, kib_tx_t *tx, int type,
        int             dstidx;
        int             wrknob;
 
-       LASSERT (!in_interrupt());
-       LASSERT (tx->tx_nwrq == 0);
-       LASSERT (type == IBLND_MSG_GET_DONE ||
+       LASSERT(!in_interrupt());
+       LASSERT(tx->tx_nwrq == 0);
+       LASSERT(type == IBLND_MSG_GET_DONE ||
                 type == IBLND_MSG_PUT_DONE);
 
        srcidx = dstidx = 0;
@@ -1162,19 +1162,19 @@ kiblnd_init_rdma (kib_conn_t *conn, kib_tx_t *tx, int type,
        ibmsg->ibm_u.completion.ibcm_status = rc;
        ibmsg->ibm_u.completion.ibcm_cookie = dstcookie;
        kiblnd_init_tx_msg(conn->ibc_peer->ibp_ni, tx,
-                          type, sizeof (kib_completion_msg_t));
+                          type, sizeof(kib_completion_msg_t));
 
        return rc;
 }
 
 void
-kiblnd_queue_tx_locked (kib_tx_t *tx, kib_conn_t *conn)
+kiblnd_queue_tx_locked(kib_tx_t *tx, kib_conn_t *conn)
 {
        struct list_head   *q;
 
-       LASSERT (tx->tx_nwrq > 0);            /* work items set up */
-       LASSERT (!tx->tx_queued);              /* not queued for sending already */
-       LASSERT (conn->ibc_state >= IBLND_CONN_ESTABLISHED);
+       LASSERT(tx->tx_nwrq > 0);             /* work items set up */
+       LASSERT(!tx->tx_queued);               /* not queued for sending already */
+       LASSERT(conn->ibc_state >= IBLND_CONN_ESTABLISHED);
 
        tx->tx_queued = 1;
        tx->tx_deadline = jiffies + (*kiblnd_tunables.kib_timeout * HZ);
@@ -1182,11 +1182,11 @@ kiblnd_queue_tx_locked (kib_tx_t *tx, kib_conn_t *conn)
        if (tx->tx_conn == NULL) {
                kiblnd_conn_addref(conn);
                tx->tx_conn = conn;
-               LASSERT (tx->tx_msg->ibm_type != IBLND_MSG_PUT_DONE);
+               LASSERT(tx->tx_msg->ibm_type != IBLND_MSG_PUT_DONE);
        } else {
                /* PUT_DONE first attached to conn as a PUT_REQ */
-               LASSERT (tx->tx_conn == conn);
-               LASSERT (tx->tx_msg->ibm_type == IBLND_MSG_PUT_DONE);
+               LASSERT(tx->tx_conn == conn);
+               LASSERT(tx->tx_msg->ibm_type == IBLND_MSG_PUT_DONE);
        }
 
        switch (tx->tx_msg->ibm_type) {
@@ -1221,7 +1221,7 @@ kiblnd_queue_tx_locked (kib_tx_t *tx, kib_conn_t *conn)
 }
 
 void
-kiblnd_queue_tx (kib_tx_t *tx, kib_conn_t *conn)
+kiblnd_queue_tx(kib_tx_t *tx, kib_conn_t *conn)
 {
        spin_lock(&conn->ibc_lock);
        kiblnd_queue_tx_locked(tx, conn);
@@ -1268,7 +1268,7 @@ static int kiblnd_resolve_addr(struct rdma_cm_id *cmid,
 }
 
 static void
-kiblnd_connect_peer (kib_peer_t *peer)
+kiblnd_connect_peer(kib_peer_t *peer)
 {
        struct rdma_cm_id *cmid;
        kib_dev_t        *dev;
@@ -1277,8 +1277,8 @@ kiblnd_connect_peer (kib_peer_t *peer)
        struct sockaddr_in dstaddr;
        int             rc;
 
-       LASSERT (net != NULL);
-       LASSERT (peer->ibp_connecting > 0);
+       LASSERT(net != NULL);
+       LASSERT(peer->ibp_connecting > 0);
 
        cmid = kiblnd_rdma_create_id(kiblnd_cm_callback, peer, RDMA_PS_TCP,
                                     IB_QPT_RC);
@@ -1318,7 +1318,7 @@ kiblnd_connect_peer (kib_peer_t *peer)
                goto failed2;
        }
 
-       LASSERT (cmid->device != NULL);
+       LASSERT(cmid->device != NULL);
        CDEBUG(D_NET, "%s: connection bound to %s:%pI4h:%s\n",
               libcfs_nid2str(peer->ibp_nid), dev->ibd_ifname,
               &dev->ibd_ifip, cmid->device->name);
@@ -1333,7 +1333,7 @@ kiblnd_connect_peer (kib_peer_t *peer)
 }
 
 void
-kiblnd_launch_tx (lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid)
+kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid)
 {
        kib_peer_t      *peer;
        kib_peer_t      *peer2;
@@ -1345,8 +1345,8 @@ kiblnd_launch_tx (lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid)
        /* If I get here, I've committed to send, so I complete the tx with
         * failure on any problems */
 
-       LASSERT (tx == NULL || tx->tx_conn == NULL); /* only set when assigned a conn */
-       LASSERT (tx == NULL || tx->tx_nwrq > 0);     /* work items have been set up */
+       LASSERT(tx == NULL || tx->tx_conn == NULL); /* only set when assigned a conn */
+       LASSERT(tx == NULL || tx->tx_nwrq > 0);     /* work items have been set up */
 
        /* First time, just use a read lock since I expect to find my peer
         * connected */
@@ -1374,7 +1374,7 @@ kiblnd_launch_tx (lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid)
        if (peer != NULL) {
                if (list_empty(&peer->ibp_conns)) {
                        /* found a peer, but it's still connecting... */
-                       LASSERT (peer->ibp_connecting != 0 ||
+                       LASSERT(peer->ibp_connecting != 0 ||
                                 peer->ibp_accepting != 0);
                        if (tx != NULL)
                                list_add_tail(&tx->tx_list,
@@ -1413,7 +1413,7 @@ kiblnd_launch_tx (lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid)
        if (peer2 != NULL) {
                if (list_empty(&peer2->ibp_conns)) {
                        /* found a peer, but it's still connecting... */
-                       LASSERT (peer2->ibp_connecting != 0 ||
+                       LASSERT(peer2->ibp_connecting != 0 ||
                                 peer2->ibp_accepting != 0);
                        if (tx != NULL)
                                list_add_tail(&tx->tx_list,
@@ -1435,11 +1435,11 @@ kiblnd_launch_tx (lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid)
        }
 
        /* Brand new peer */
-       LASSERT (peer->ibp_connecting == 0);
+       LASSERT(peer->ibp_connecting == 0);
        peer->ibp_connecting = 1;
 
        /* always called with a ref on ni, which prevents ni being shutdown */
-       LASSERT (((kib_net_t *)ni->ni_data)->ibn_shutdown == 0);
+       LASSERT(((kib_net_t *)ni->ni_data)->ibn_shutdown == 0);
 
        if (tx != NULL)
                list_add_tail(&tx->tx_list, &peer->ibp_tx_queue);
@@ -1454,7 +1454,7 @@ kiblnd_launch_tx (lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid)
 }
 
 int
-kiblnd_send (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg)
+kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg)
 {
        lnet_hdr_t       *hdr = &lntmsg->msg_hdr;
        int            type = lntmsg->msg_type;
@@ -1476,13 +1476,13 @@ kiblnd_send (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg)
        CDEBUG(D_NET, "sending %d bytes in %d frags to %s\n",
               payload_nob, payload_niov, libcfs_id2str(target));
 
-       LASSERT (payload_nob == 0 || payload_niov > 0);
-       LASSERT (payload_niov <= LNET_MAX_IOV);
+       LASSERT(payload_nob == 0 || payload_niov > 0);
+       LASSERT(payload_niov <= LNET_MAX_IOV);
 
        /* Thread context */
-       LASSERT (!in_interrupt());
+       LASSERT(!in_interrupt());
        /* payload is either all vaddrs or all pages */
-       LASSERT (!(payload_kiov != NULL && payload_iov != NULL));
+       LASSERT(!(payload_kiov != NULL && payload_iov != NULL));
 
        switch (type) {
        default:
@@ -1490,7 +1490,7 @@ kiblnd_send (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg)
                return -EIO;
 
        case LNET_MSG_ACK:
-               LASSERT (payload_nob == 0);
+               LASSERT(payload_nob == 0);
                break;
 
        case LNET_MSG_GET:
@@ -1592,12 +1592,12 @@ kiblnd_send (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg)
 
        /* send IMMEDIATE */
 
-       LASSERT (offsetof(kib_msg_t, ibm_u.immediate.ibim_payload[payload_nob])
+       LASSERT(offsetof(kib_msg_t, ibm_u.immediate.ibim_payload[payload_nob])
                 <= IBLND_MSG_SIZE);
 
        tx = kiblnd_get_idle_tx(ni, target.nid);
        if (tx == NULL) {
-               CERROR ("Can't send %d to %s: tx descs exhausted\n",
+               CERROR("Can't send %d to %s: tx descs exhausted\n",
                        type, libcfs_nid2str(target.nid));
                return -ENOMEM;
        }
@@ -1625,7 +1625,7 @@ kiblnd_send (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg)
 }
 
 static void
-kiblnd_reply (lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg)
+kiblnd_reply(lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg)
 {
        lnet_process_id_t target = lntmsg->msg_target;
        unsigned int      niov = lntmsg->msg_niov;
@@ -1687,7 +1687,7 @@ kiblnd_reply (lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg)
 }
 
 int
-kiblnd_recv (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed,
+kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed,
             unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov,
             unsigned int offset, unsigned int mlen, unsigned int rlen)
 {
@@ -1700,10 +1700,10 @@ kiblnd_recv (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed,
        int       post_credit = IBLND_POSTRX_PEER_CREDIT;
        int       rc = 0;
 
-       LASSERT (mlen <= rlen);
-       LASSERT (!in_interrupt());
+       LASSERT(mlen <= rlen);
+       LASSERT(!in_interrupt());
        /* Either all pages or all vaddrs */
-       LASSERT (!(kiov != NULL && iov != NULL));
+       LASSERT(!(kiov != NULL && iov != NULL));
 
        switch (rxmsg->ibm_type) {
        default:
@@ -1712,7 +1712,7 @@ kiblnd_recv (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed,
        case IBLND_MSG_IMMEDIATE:
                nob = offsetof(kib_msg_t, ibm_u.immediate.ibim_payload[rlen]);
                if (nob > rx->rx_nob) {
-                       CERROR ("Immediate message from %s too big: %d(%d)\n",
+                       CERROR("Immediate message from %s too big: %d(%d)\n",
                                libcfs_nid2str(rxmsg->ibm_u.immediate.ibim_hdr.src_nid),
                                nob, rx->rx_nob);
                        rc = -EPROTO;
@@ -1729,7 +1729,7 @@ kiblnd_recv (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed,
                                           IBLND_MSG_SIZE, rxmsg,
                                           offsetof(kib_msg_t, ibm_u.immediate.ibim_payload),
                                           mlen);
-               lnet_finalize (ni, lntmsg, 0);
+               lnet_finalize(ni, lntmsg, 0);
                break;
 
        case IBLND_MSG_PUT_REQ:
@@ -1812,13 +1812,13 @@ kiblnd_thread_start(int (*fn)(void *arg), void *arg, char *name)
 }
 
 static void
-kiblnd_thread_fini (void)
+kiblnd_thread_fini(void)
 {
-       atomic_dec (&kiblnd_data.kib_nthreads);
+       atomic_dec(&kiblnd_data.kib_nthreads);
 }
 
 void
-kiblnd_peer_alive (kib_peer_t *peer)
+kiblnd_peer_alive(kib_peer_t *peer)
 {
        /* This is racy, but everyone's only writing cfs_time_current() */
        peer->ibp_last_alive = cfs_time_current();
@@ -1826,7 +1826,7 @@ kiblnd_peer_alive (kib_peer_t *peer)
 }
 
 static void
-kiblnd_peer_notify (kib_peer_t *peer)
+kiblnd_peer_notify(kib_peer_t *peer)
 {
        int        error = 0;
        unsigned long    last_alive = 0;
@@ -1852,7 +1852,7 @@ kiblnd_peer_notify (kib_peer_t *peer)
 }
 
 void
-kiblnd_close_conn_locked (kib_conn_t *conn, int error)
+kiblnd_close_conn_locked(kib_conn_t *conn, int error)
 {
        /* This just does the immediate housekeeping.  'error' is zero for a
         * normal shutdown which can happen only after the connection has been
@@ -1864,7 +1864,7 @@ kiblnd_close_conn_locked (kib_conn_t *conn, int error)
        kib_dev_t       *dev;
        unsigned long     flags;
 
-       LASSERT (error != 0 || conn->ibc_state >= IBLND_CONN_ESTABLISHED);
+       LASSERT(error != 0 || conn->ibc_state >= IBLND_CONN_ESTABLISHED);
 
        if (error != 0 && conn->ibc_comms_error == 0)
                conn->ibc_comms_error = error;
@@ -1894,7 +1894,7 @@ kiblnd_close_conn_locked (kib_conn_t *conn, int error)
        list_del(&conn->ibc_list);
        /* connd (see below) takes over ibc_list's ref */
 
-       if (list_empty (&peer->ibp_conns) &&    /* no more conns */
+       if (list_empty(&peer->ibp_conns) &&    /* no more conns */
            kiblnd_peer_active(peer)) {  /* still in peer table */
                kiblnd_unlink_peer_locked(peer);
 
@@ -1936,14 +1936,13 @@ kiblnd_handle_early_rxs(kib_conn_t *conn)
 {
        unsigned long    flags;
        kib_rx_t        *rx;
+       kib_rx_t *tmp;
 
        LASSERT(!in_interrupt());
        LASSERT(conn->ibc_state >= IBLND_CONN_ESTABLISHED);
 
        write_lock_irqsave(&kiblnd_data.kib_global_lock, flags);
-       while (!list_empty(&conn->ibc_early_rxs)) {
-               rx = list_entry(conn->ibc_early_rxs.next,
-                                   kib_rx_t, rx_list);
+       list_for_each_entry_safe(rx, tmp, &conn->ibc_early_rxs, rx_list) {
                list_del(&rx->rx_list);
                write_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags);
 
@@ -1957,22 +1956,22 @@ kiblnd_handle_early_rxs(kib_conn_t *conn)
 static void
 kiblnd_abort_txs(kib_conn_t *conn, struct list_head *txs)
 {
-       LIST_HEAD       (zombies);
+       LIST_HEAD(zombies);
        struct list_head          *tmp;
        struct list_head          *nxt;
        kib_tx_t            *tx;
 
        spin_lock(&conn->ibc_lock);
 
-       list_for_each_safe (tmp, nxt, txs) {
-               tx = list_entry (tmp, kib_tx_t, tx_list);
+       list_for_each_safe(tmp, nxt, txs) {
+               tx = list_entry(tmp, kib_tx_t, tx_list);
 
                if (txs == &conn->ibc_active_txs) {
-                       LASSERT (!tx->tx_queued);
-                       LASSERT (tx->tx_waiting ||
+                       LASSERT(!tx->tx_queued);
+                       LASSERT(tx->tx_waiting ||
                                 tx->tx_sending != 0);
                } else {
-                       LASSERT (tx->tx_queued);
+                       LASSERT(tx->tx_queued);
                }
 
                tx->tx_status = -ECONNABORTED;
@@ -1980,8 +1979,8 @@ kiblnd_abort_txs(kib_conn_t *conn, struct list_head *txs)
 
                if (tx->tx_sending == 0) {
                        tx->tx_queued = 0;
-                       list_del (&tx->tx_list);
-                       list_add (&tx->tx_list, &zombies);
+                       list_del(&tx->tx_list);
+                       list_add(&tx->tx_list, &zombies);
                }
        }
 
@@ -1991,10 +1990,10 @@ kiblnd_abort_txs(kib_conn_t *conn, struct list_head *txs)
 }
 
 static void
-kiblnd_finalise_conn (kib_conn_t *conn)
+kiblnd_finalise_conn(kib_conn_t *conn)
 {
-       LASSERT (!in_interrupt());
-       LASSERT (conn->ibc_state > IBLND_CONN_INIT);
+       LASSERT(!in_interrupt());
+       LASSERT(conn->ibc_state > IBLND_CONN_INIT);
 
        kiblnd_set_conn_state(conn, IBLND_CONN_DISCONNECTED);
 
@@ -2016,21 +2015,21 @@ kiblnd_finalise_conn (kib_conn_t *conn)
 }
 
 void
-kiblnd_peer_connect_failed (kib_peer_t *peer, int active, int error)
+kiblnd_peer_connect_failed(kib_peer_t *peer, int active, int error)
 {
-       LIST_HEAD    (zombies);
+       LIST_HEAD(zombies);
        unsigned long     flags;
 
-       LASSERT (error != 0);
-       LASSERT (!in_interrupt());
+       LASSERT(error != 0);
+       LASSERT(!in_interrupt());
 
        write_lock_irqsave(&kiblnd_data.kib_global_lock, flags);
 
        if (active) {
-               LASSERT (peer->ibp_connecting > 0);
+               LASSERT(peer->ibp_connecting > 0);
                peer->ibp_connecting--;
        } else {
-               LASSERT (peer->ibp_accepting > 0);
+               LASSERT(peer->ibp_accepting > 0);
                peer->ibp_accepting--;
        }
 
@@ -2053,14 +2052,14 @@ kiblnd_peer_connect_failed (kib_peer_t *peer, int active, int error)
                peer->ibp_error = error;
        } else {
                /* Can't have blocked transmits if there are connections */
-               LASSERT (list_empty(&peer->ibp_tx_queue));
+               LASSERT(list_empty(&peer->ibp_tx_queue));
        }
 
        write_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags);
 
        kiblnd_peer_notify(peer);
 
-       if (list_empty (&zombies))
+       if (list_empty(&zombies))
                return;
 
        CNETERR("Deleting messages for %s: connection failed\n",
@@ -2074,6 +2073,7 @@ kiblnd_connreq_done(kib_conn_t *conn, int status)
 {
        kib_peer_t      *peer = conn->ibc_peer;
        kib_tx_t          *tx;
+       kib_tx_t *tmp;
        struct list_head         txs;
        unsigned long      flags;
        int             active;
@@ -2084,8 +2084,8 @@ kiblnd_connreq_done(kib_conn_t *conn, int status)
               libcfs_nid2str(peer->ibp_nid), active,
               conn->ibc_version, status);
 
-       LASSERT (!in_interrupt());
-       LASSERT ((conn->ibc_state == IBLND_CONN_ACTIVE_CONNECT &&
+       LASSERT(!in_interrupt());
+       LASSERT((conn->ibc_state == IBLND_CONN_ACTIVE_CONNECT &&
                  peer->ibp_connecting > 0) ||
                 (conn->ibc_state == IBLND_CONN_PASSIVE_WAIT &&
                  peer->ibp_accepting > 0));
@@ -2150,8 +2150,7 @@ kiblnd_connreq_done(kib_conn_t *conn, int status)
 
        /* Schedule blocked txs */
        spin_lock(&conn->ibc_lock);
-       while (!list_empty(&txs)) {
-               tx = list_entry(txs.next, kib_tx_t, tx_list);
+       list_for_each_entry_safe(tx, tmp, &txs, tx_list) {
                list_del(&tx->tx_list);
 
                kiblnd_queue_tx_locked(tx, conn);
@@ -2176,7 +2175,7 @@ kiblnd_reject(struct rdma_cm_id *cmid, kib_rej_t *rej)
 }
 
 static int
-kiblnd_passive_connect (struct rdma_cm_id *cmid, void *priv, int priv_nob)
+kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob)
 {
        rwlock_t                *g_lock = &kiblnd_data.kib_global_lock;
        kib_msg_t            *reqmsg = priv;
@@ -2194,11 +2193,11 @@ kiblnd_passive_connect (struct rdma_cm_id *cmid, void *priv, int priv_nob)
        unsigned long     flags;
        int                 rc;
        struct sockaddr_in    *peer_addr;
-       LASSERT (!in_interrupt());
+       LASSERT(!in_interrupt());
 
        /* cmid inherits 'context' from the corresponding listener id */
        ibdev = (kib_dev_t *)cmid->context;
-       LASSERT (ibdev != NULL);
+       LASSERT(ibdev != NULL);
 
        memset(&rej, 0, sizeof(rej));
        rej.ibr_magic           = IBLND_MSG_MAGIC;
@@ -2366,8 +2365,8 @@ kiblnd_passive_connect (struct rdma_cm_id *cmid, void *priv, int priv_nob)
                peer = peer2;
        } else {
                /* Brand new peer */
-               LASSERT (peer->ibp_accepting == 0);
-               LASSERT (peer->ibp_version == 0 &&
+               LASSERT(peer->ibp_accepting == 0);
+               LASSERT(peer->ibp_version == 0 &&
                         peer->ibp_incarnation == 0);
 
                peer->ibp_accepting   = 1;
@@ -2375,7 +2374,7 @@ kiblnd_passive_connect (struct rdma_cm_id *cmid, void *priv, int priv_nob)
                peer->ibp_incarnation = reqmsg->ibm_srcstamp;
 
                /* I have a ref on ni that prevents it being shutdown */
-               LASSERT (net->ibn_shutdown == 0);
+               LASSERT(net->ibn_shutdown == 0);
 
                kiblnd_peer_addref(peer);
                list_add_tail(&peer->ibp_list, kiblnd_nid2peerlist(nid));
@@ -2397,7 +2396,7 @@ kiblnd_passive_connect (struct rdma_cm_id *cmid, void *priv, int priv_nob)
        conn->ibc_incarnation      = reqmsg->ibm_srcstamp;
        conn->ibc_credits         = IBLND_MSG_QUEUE_SIZE(version);
        conn->ibc_reserved_credits = IBLND_MSG_QUEUE_SIZE(version);
-       LASSERT (conn->ibc_credits + conn->ibc_reserved_credits + IBLND_OOB_MSGS(version)
+       LASSERT(conn->ibc_credits + conn->ibc_reserved_credits + IBLND_OOB_MSGS(version)
                 <= IBLND_RX_MSGS(version));
 
        ackmsg = &conn->ibc_connvars->cv_msg;
@@ -2449,7 +2448,7 @@ kiblnd_passive_connect (struct rdma_cm_id *cmid, void *priv, int priv_nob)
 }
 
 static void
-kiblnd_reconnect (kib_conn_t *conn, int version,
+kiblnd_reconnect(kib_conn_t *conn, int version,
                  __u64 incarnation, int why, kib_connparams_t *cp)
 {
        kib_peer_t    *peer = conn->ibc_peer;
@@ -2457,8 +2456,8 @@ kiblnd_reconnect (kib_conn_t *conn, int version,
        int         retry = 0;
        unsigned long  flags;
 
-       LASSERT (conn->ibc_state == IBLND_CONN_ACTIVE_CONNECT);
-       LASSERT (peer->ibp_connecting > 0);     /* 'conn' at least */
+       LASSERT(conn->ibc_state == IBLND_CONN_ACTIVE_CONNECT);
+       LASSERT(peer->ibp_connecting > 0);     /* 'conn' at least */
 
        write_lock_irqsave(&kiblnd_data.kib_global_lock, flags);
 
@@ -2504,20 +2503,20 @@ kiblnd_reconnect (kib_conn_t *conn, int version,
        CNETERR("%s: retrying (%s), %x, %x, queue_dep: %d, max_frag: %d, msg_size: %d\n",
                libcfs_nid2str(peer->ibp_nid),
                reason, IBLND_MSG_VERSION, version,
-               cp != NULL? cp->ibcp_queue_depth :IBLND_MSG_QUEUE_SIZE(version),
-               cp != NULL? cp->ibcp_max_frags   : IBLND_RDMA_FRAGS(version),
-               cp != NULL? cp->ibcp_max_msg_size: IBLND_MSG_SIZE);
+               cp != NULL ? cp->ibcp_queue_depth  : IBLND_MSG_QUEUE_SIZE(version),
+               cp != NULL ? cp->ibcp_max_frags    : IBLND_RDMA_FRAGS(version),
+               cp != NULL ? cp->ibcp_max_msg_size : IBLND_MSG_SIZE);
 
        kiblnd_connect_peer(peer);
 }
 
 static void
-kiblnd_rejected (kib_conn_t *conn, int reason, void *priv, int priv_nob)
+kiblnd_rejected(kib_conn_t *conn, int reason, void *priv, int priv_nob)
 {
        kib_peer_t    *peer = conn->ibc_peer;
 
-       LASSERT (!in_interrupt());
-       LASSERT (conn->ibc_state == IBLND_CONN_ACTIVE_CONNECT);
+       LASSERT(!in_interrupt());
+       LASSERT(conn->ibc_state == IBLND_CONN_ACTIVE_CONNECT);
 
        switch (reason) {
        case IB_CM_REJ_STALE_CONN:
@@ -2651,7 +2650,7 @@ kiblnd_rejected (kib_conn_t *conn, int reason, void *priv, int priv_nob)
 }
 
 static void
-kiblnd_check_connreply (kib_conn_t *conn, void *priv, int priv_nob)
+kiblnd_check_connreply(kib_conn_t *conn, void *priv, int priv_nob)
 {
        kib_peer_t    *peer = conn->ibc_peer;
        lnet_ni_t     *ni   = peer->ibp_ni;
@@ -2661,7 +2660,7 @@ kiblnd_check_connreply (kib_conn_t *conn, void *priv, int priv_nob)
        int         rc   = kiblnd_unpack_msg(msg, priv_nob);
        unsigned long  flags;
 
-       LASSERT (net != NULL);
+       LASSERT(net != NULL);
 
        if (rc != 0) {
                CERROR("Can't unpack connack from %s: %d\n",
@@ -2730,7 +2729,7 @@ kiblnd_check_connreply (kib_conn_t *conn, void *priv, int priv_nob)
        conn->ibc_incarnation      = msg->ibm_srcstamp;
        conn->ibc_credits         =
        conn->ibc_reserved_credits = IBLND_MSG_QUEUE_SIZE(ver);
-       LASSERT (conn->ibc_credits + conn->ibc_reserved_credits + IBLND_OOB_MSGS(ver)
+       LASSERT(conn->ibc_credits + conn->ibc_reserved_credits + IBLND_OOB_MSGS(ver)
                 <= IBLND_RX_MSGS(ver));
 
        kiblnd_connreq_done(conn, 0);
@@ -2742,13 +2741,13 @@ kiblnd_check_connreply (kib_conn_t *conn, void *priv, int priv_nob)
         * kiblnd_connreq_done(0) moves the conn state to ESTABLISHED, but then
         * immediately tears it down. */
 
-       LASSERT (rc != 0);
+       LASSERT(rc != 0);
        conn->ibc_comms_error = rc;
        kiblnd_connreq_done(conn, 0);
 }
 
 static int
-kiblnd_active_connect (struct rdma_cm_id *cmid)
+kiblnd_active_connect(struct rdma_cm_id *cmid)
 {
        kib_peer_t            *peer = (kib_peer_t *)cmid->context;
        kib_conn_t            *conn;
@@ -2913,7 +2912,7 @@ kiblnd_cm_callback(struct rdma_cm_id *cmid, struct rdma_cm_event *event)
                        LBUG();
 
                case IBLND_CONN_PASSIVE_WAIT:
-                       CERROR ("%s: REJECTED %d\n",
+                       CERROR("%s: REJECTED %d\n",
                                libcfs_nid2str(conn->ibc_peer->ibp_nid),
                                event->status);
                        kiblnd_connreq_done(conn, -ECONNRESET);
@@ -2987,17 +2986,17 @@ kiblnd_check_txs_locked(kib_conn_t *conn, struct list_head *txs)
        kib_tx_t          *tx;
        struct list_head        *ttmp;
 
-       list_for_each (ttmp, txs) {
-               tx = list_entry (ttmp, kib_tx_t, tx_list);
+       list_for_each(ttmp, txs) {
+               tx = list_entry(ttmp, kib_tx_t, tx_list);
 
                if (txs != &conn->ibc_active_txs) {
-                       LASSERT (tx->tx_queued);
+                       LASSERT(tx->tx_queued);
                } else {
-                       LASSERT (!tx->tx_queued);
-                       LASSERT (tx->tx_waiting || tx->tx_sending != 0);
+                       LASSERT(!tx->tx_queued);
+                       LASSERT(tx->tx_waiting || tx->tx_sending != 0);
                }
 
-               if (cfs_time_aftereq (jiffies, tx->tx_deadline)) {
+               if (cfs_time_aftereq(jiffies, tx->tx_deadline)) {
                        CERROR("Timed out tx: %s, %lu seconds\n",
                               kiblnd_queue2str(conn, txs),
                               cfs_duration_sec(jiffies - tx->tx_deadline));
@@ -3019,14 +3018,15 @@ kiblnd_conn_timed_out_locked(kib_conn_t *conn)
 }
 
 static void
-kiblnd_check_conns (int idx)
+kiblnd_check_conns(int idx)
 {
-       LIST_HEAD (closes);
-       LIST_HEAD (checksends);
+       LIST_HEAD(closes);
+       LIST_HEAD(checksends);
        struct list_head    *peers = &kiblnd_data.kib_peers[idx];
        struct list_head    *ptmp;
        kib_peer_t    *peer;
        kib_conn_t    *conn;
+       kib_conn_t *tmp;
        struct list_head    *ctmp;
        unsigned long  flags;
 
@@ -3035,16 +3035,16 @@ kiblnd_check_conns (int idx)
         * take a look... */
        read_lock_irqsave(&kiblnd_data.kib_global_lock, flags);
 
-       list_for_each (ptmp, peers) {
-               peer = list_entry (ptmp, kib_peer_t, ibp_list);
+       list_for_each(ptmp, peers) {
+               peer = list_entry(ptmp, kib_peer_t, ibp_list);
 
-               list_for_each (ctmp, &peer->ibp_conns) {
+               list_for_each(ctmp, &peer->ibp_conns) {
                        int timedout;
                        int sendnoop;
 
                        conn = list_entry(ctmp, kib_conn_t, ibc_list);
 
-                       LASSERT (conn->ibc_state == IBLND_CONN_ESTABLISHED);
+                       LASSERT(conn->ibc_state == IBLND_CONN_ESTABLISHED);
 
                        spin_lock(&conn->ibc_lock);
 
@@ -3080,9 +3080,7 @@ kiblnd_check_conns (int idx)
        /* Handle timeout by closing the whole
         * connection. We can only be sure RDMA activity
         * has ceased once the QP has been modified. */
-       while (!list_empty(&closes)) {
-               conn = list_entry(closes.next,
-                                     kib_conn_t, ibc_connd_list);
+       list_for_each_entry_safe(conn, tmp, &closes, ibc_connd_list) {
                list_del(&conn->ibc_connd_list);
                kiblnd_close_conn(conn, -ETIMEDOUT);
                kiblnd_conn_decref(conn);
@@ -3101,11 +3099,11 @@ kiblnd_check_conns (int idx)
 }
 
 static void
-kiblnd_disconnect_conn (kib_conn_t *conn)
+kiblnd_disconnect_conn(kib_conn_t *conn)
 {
-       LASSERT (!in_interrupt());
-       LASSERT (current == kiblnd_data.kib_connd);
-       LASSERT (conn->ibc_state == IBLND_CONN_CLOSING);
+       LASSERT(!in_interrupt());
+       LASSERT(current == kiblnd_data.kib_connd);
+       LASSERT(conn->ibc_state == IBLND_CONN_CLOSING);
 
        rdma_disconnect(conn->ibc_cmid);
        kiblnd_finalise_conn(conn);
@@ -3114,7 +3112,7 @@ kiblnd_disconnect_conn (kib_conn_t *conn)
 }
 
 int
-kiblnd_connd (void *arg)
+kiblnd_connd(void *arg)
 {
        wait_queue_t     wait;
        unsigned long      flags;
@@ -3125,7 +3123,7 @@ kiblnd_connd (void *arg)
        int             peer_index = 0;
        unsigned long      deadline = jiffies;
 
-       cfs_block_allsigs ();
+       cfs_block_allsigs();
 
        init_waitqueue_entry(&wait, current);
        kiblnd_data.kib_connd = current;
@@ -3136,7 +3134,7 @@ kiblnd_connd (void *arg)
 
                dropped_lock = 0;
 
-               if (!list_empty (&kiblnd_data.kib_connd_zombies)) {
+               if (!list_empty(&kiblnd_data.kib_connd_zombies)) {
                        conn = list_entry(kiblnd_data. \
                                              kib_connd_zombies.next,
                                              kib_conn_t, ibc_list);
@@ -3239,7 +3237,7 @@ kiblnd_qp_event(struct ib_event *event, void *arg)
 }
 
 static void
-kiblnd_complete (struct ib_wc *wc)
+kiblnd_complete(struct ib_wc *wc)
 {
        switch (kiblnd_wreqid2type(wc->wr_id)) {
        default:
@@ -3440,9 +3438,9 @@ kiblnd_failover_thread(void *arg)
        unsigned long      flags;
        int             rc;
 
-       LASSERT (*kiblnd_tunables.kib_dev_failover != 0);
+       LASSERT(*kiblnd_tunables.kib_dev_failover != 0);
 
-       cfs_block_allsigs ();
+       cfs_block_allsigs();
 
        init_waitqueue_entry(&wait, current);
        write_lock_irqsave(glock, flags);
@@ -3469,7 +3467,7 @@ kiblnd_failover_thread(void *arg)
 
                        write_lock_irqsave(glock, flags);
 
-                       LASSERT (dev->ibd_failover);
+                       LASSERT(dev->ibd_failover);
                        dev->ibd_failover = 0;
                        if (rc >= 0) { /* Device is OK or failover succeed */
                                dev->ibd_next_failover = cfs_time_shift(3);
index 8b4a8e9a29b4dddb0f79bfefb785d8b1a37c779e..eedf01afd57f72d74a91e55e88d2a28b4774c75d 100644 (file)
@@ -44,7 +44,7 @@ static int service = 987;
 module_param(service, int, 0444);
 MODULE_PARM_DESC(service, "service number (within RDMA_PS_TCP)");
 
-static int cksum = 0;
+static int cksum;
 module_param(cksum, int, 0644);
 MODULE_PARM_DESC(cksum, "set non-zero to enable message (not RDMA) checksums");
 
@@ -72,11 +72,11 @@ static int peer_credits = 8;
 module_param(peer_credits, int, 0444);
 MODULE_PARM_DESC(peer_credits, "# concurrent sends to 1 peer");
 
-static int peer_credits_hiw = 0;
+static int peer_credits_hiw;
 module_param(peer_credits_hiw, int, 0444);
 MODULE_PARM_DESC(peer_credits_hiw, "when eagerly to return credits");
 
-static int peer_buffer_credits = 0;
+static int peer_buffer_credits;
 module_param(peer_buffer_credits, int, 0444);
 MODULE_PARM_DESC(peer_buffer_credits, "# per-peer router buffer credits");
 
@@ -100,15 +100,15 @@ static int keepalive = 100;
 module_param(keepalive, int, 0644);
 MODULE_PARM_DESC(keepalive, "Idle time in seconds before sending a keepalive");
 
-static int ib_mtu = 0;
+static int ib_mtu;
 module_param(ib_mtu, int, 0444);
 MODULE_PARM_DESC(ib_mtu, "IB MTU 256/512/1024/2048/4096");
 
-static int concurrent_sends = 0;
+static int concurrent_sends;
 module_param(concurrent_sends, int, 0444);
 MODULE_PARM_DESC(concurrent_sends, "send work-queue sizing");
 
-static int map_on_demand = 0;
+static int map_on_demand;
 module_param(map_on_demand, int, 0444);
 MODULE_PARM_DESC(map_on_demand, "map on demand");
 
@@ -136,12 +136,12 @@ MODULE_PARM_DESC(pmr_pool_size, "size of MR cache pmr pool on each CPT");
  * 1: enable failover if necessary
  * 2: force to failover (for debug)
  */
-static int dev_failover = 0;
+static int dev_failover;
 module_param(dev_failover, int, 0444);
 MODULE_PARM_DESC(dev_failover, "HCA failover for bonding (0 off, 1 on, other values reserved)");
 
 
-static int require_privileged_port = 0;
+static int require_privileged_port;
 module_param(require_privileged_port, int, 0644);
 MODULE_PARM_DESC(require_privileged_port, "require privileged port when accepting connection");
 
@@ -177,7 +177,7 @@ kib_tunables_t kiblnd_tunables = {
 };
 
 int
-kiblnd_tunables_init (void)
+kiblnd_tunables_init(void)
 {
        if (kiblnd_translate_mtu(*kiblnd_tunables.kib_ib_mtu) < 0) {
                CERROR("Invalid ib_mtu %d, expected 256/512/1024/2048/4096\n",
index 5956dbac5d047c116872843f7e7ed7514e40ac15..7586b7e4040bdc1d6c476c162eea3b19e257cfd8 100644 (file)
@@ -65,15 +65,15 @@ ksocknal_ip2iface(lnet_ni_t *ni, __u32 ip)
 }
 
 static ksock_route_t *
-ksocknal_create_route (__u32 ipaddr, int port)
+ksocknal_create_route(__u32 ipaddr, int port)
 {
        ksock_route_t *route;
 
-       LIBCFS_ALLOC (route, sizeof (*route));
+       LIBCFS_ALLOC(route, sizeof(*route));
        if (route == NULL)
                return NULL;
 
-       atomic_set (&route->ksnr_refcount, 1);
+       atomic_set(&route->ksnr_refcount, 1);
        route->ksnr_peer = NULL;
        route->ksnr_retry_interval = 0;  /* OK to connect at any time */
        route->ksnr_ipaddr = ipaddr;
@@ -89,43 +89,43 @@ ksocknal_create_route (__u32 ipaddr, int port)
 }
 
 void
-ksocknal_destroy_route (ksock_route_t *route)
+ksocknal_destroy_route(ksock_route_t *route)
 {
-       LASSERT (atomic_read(&route->ksnr_refcount) == 0);
+       LASSERT(atomic_read(&route->ksnr_refcount) == 0);
 
        if (route->ksnr_peer != NULL)
                ksocknal_peer_decref(route->ksnr_peer);
 
-       LIBCFS_FREE (route, sizeof (*route));
+       LIBCFS_FREE(route, sizeof(*route));
 }
 
 static int
-ksocknal_create_peer (ksock_peer_t **peerp, lnet_ni_t *ni, lnet_process_id_t id)
+ksocknal_create_peer(ksock_peer_t **peerp, lnet_ni_t *ni, lnet_process_id_t id)
 {
        ksock_net_t   *net = ni->ni_data;
        ksock_peer_t  *peer;
 
-       LASSERT (id.nid != LNET_NID_ANY);
-       LASSERT (id.pid != LNET_PID_ANY);
-       LASSERT (!in_interrupt());
+       LASSERT(id.nid != LNET_NID_ANY);
+       LASSERT(id.pid != LNET_PID_ANY);
+       LASSERT(!in_interrupt());
 
-       LIBCFS_ALLOC (peer, sizeof (*peer));
+       LIBCFS_ALLOC(peer, sizeof(*peer));
        if (peer == NULL)
                return -ENOMEM;
 
        peer->ksnp_ni = ni;
        peer->ksnp_id = id;
-       atomic_set (&peer->ksnp_refcount, 1);   /* 1 ref for caller */
+       atomic_set(&peer->ksnp_refcount, 1);   /* 1 ref for caller */
        peer->ksnp_closing = 0;
        peer->ksnp_accepting = 0;
        peer->ksnp_proto = NULL;
        peer->ksnp_last_alive = 0;
        peer->ksnp_zc_next_cookie = SOCKNAL_KEEPALIVE_PING + 1;
 
-       INIT_LIST_HEAD (&peer->ksnp_conns);
-       INIT_LIST_HEAD (&peer->ksnp_routes);
-       INIT_LIST_HEAD (&peer->ksnp_tx_queue);
-       INIT_LIST_HEAD (&peer->ksnp_zc_req_list);
+       INIT_LIST_HEAD(&peer->ksnp_conns);
+       INIT_LIST_HEAD(&peer->ksnp_routes);
+       INIT_LIST_HEAD(&peer->ksnp_tx_queue);
+       INIT_LIST_HEAD(&peer->ksnp_zc_req_list);
        spin_lock_init(&peer->ksnp_lock);
 
        spin_lock_bh(&net->ksnn_lock);
@@ -147,21 +147,21 @@ ksocknal_create_peer (ksock_peer_t **peerp, lnet_ni_t *ni, lnet_process_id_t id)
 }
 
 void
-ksocknal_destroy_peer (ksock_peer_t *peer)
+ksocknal_destroy_peer(ksock_peer_t *peer)
 {
        ksock_net_t    *net = peer->ksnp_ni->ni_data;
 
-       CDEBUG (D_NET, "peer %s %p deleted\n",
+       CDEBUG(D_NET, "peer %s %p deleted\n",
                libcfs_id2str(peer->ksnp_id), peer);
 
-       LASSERT (atomic_read (&peer->ksnp_refcount) == 0);
-       LASSERT (peer->ksnp_accepting == 0);
-       LASSERT (list_empty (&peer->ksnp_conns));
-       LASSERT (list_empty (&peer->ksnp_routes));
-       LASSERT (list_empty (&peer->ksnp_tx_queue));
-       LASSERT (list_empty (&peer->ksnp_zc_req_list));
+       LASSERT(atomic_read(&peer->ksnp_refcount) == 0);
+       LASSERT(peer->ksnp_accepting == 0);
+       LASSERT(list_empty(&peer->ksnp_conns));
+       LASSERT(list_empty(&peer->ksnp_routes));
+       LASSERT(list_empty(&peer->ksnp_tx_queue));
+       LASSERT(list_empty(&peer->ksnp_zc_req_list));
 
-       LIBCFS_FREE (peer, sizeof (*peer));
+       LIBCFS_FREE(peer, sizeof(*peer));
 
        /* NB a peer's connections and routes keep a reference on their peer
         * until they are destroyed, so we can be assured that _all_ state to
@@ -173,17 +173,17 @@ ksocknal_destroy_peer (ksock_peer_t *peer)
 }
 
 ksock_peer_t *
-ksocknal_find_peer_locked (lnet_ni_t *ni, lnet_process_id_t id)
+ksocknal_find_peer_locked(lnet_ni_t *ni, lnet_process_id_t id)
 {
        struct list_head       *peer_list = ksocknal_nid2peerlist(id.nid);
        struct list_head       *tmp;
        ksock_peer_t     *peer;
 
-       list_for_each (tmp, peer_list) {
+       list_for_each(tmp, peer_list) {
 
-               peer = list_entry (tmp, ksock_peer_t, ksnp_list);
+               peer = list_entry(tmp, ksock_peer_t, ksnp_list);
 
-               LASSERT (!peer->ksnp_closing);
+               LASSERT(!peer->ksnp_closing);
 
                if (peer->ksnp_ni != ni)
                        continue;
@@ -201,7 +201,7 @@ 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)
+ksocknal_find_peer(lnet_ni_t *ni, lnet_process_id_t id)
 {
        ksock_peer_t     *peer;
 
@@ -215,37 +215,37 @@ ksocknal_find_peer (lnet_ni_t *ni, lnet_process_id_t id)
 }
 
 static void
-ksocknal_unlink_peer_locked (ksock_peer_t *peer)
+ksocknal_unlink_peer_locked(ksock_peer_t *peer)
 {
        int             i;
        __u32         ip;
        ksock_interface_t *iface;
 
        for (i = 0; i < peer->ksnp_n_passive_ips; i++) {
-               LASSERT (i < LNET_MAX_INTERFACES);
+               LASSERT(i < LNET_MAX_INTERFACES);
                ip = peer->ksnp_passive_ips[i];
 
                iface = ksocknal_ip2iface(peer->ksnp_ni, ip);
                /* All IPs in peer->ksnp_passive_ips[] come from the
                 * interface list, therefore the call must succeed. */
-               LASSERT (iface != NULL);
+               LASSERT(iface != NULL);
 
                CDEBUG(D_NET, "peer=%p iface=%p ksni_nroutes=%d\n",
                       peer, iface, iface->ksni_nroutes);
                iface->ksni_npeers--;
        }
 
-       LASSERT (list_empty(&peer->ksnp_conns));
-       LASSERT (list_empty(&peer->ksnp_routes));
-       LASSERT (!peer->ksnp_closing);
+       LASSERT(list_empty(&peer->ksnp_conns));
+       LASSERT(list_empty(&peer->ksnp_routes));
+       LASSERT(!peer->ksnp_closing);
        peer->ksnp_closing = 1;
-       list_del (&peer->ksnp_list);
+       list_del(&peer->ksnp_list);
        /* lose peerlist's ref */
        ksocknal_peer_decref(peer);
 }
 
 static int
-ksocknal_get_peer_info (lnet_ni_t *ni, int index,
+ksocknal_get_peer_info(lnet_ni_t *ni, int index,
                        lnet_process_id_t *id, __u32 *myip, __u32 *peer_ip,
                        int *port, int *conn_count, int *share_count)
 {
@@ -261,8 +261,8 @@ ksocknal_get_peer_info (lnet_ni_t *ni, int index,
 
        for (i = 0; i < ksocknal_data.ksnd_peer_hash_size; i++) {
 
-               list_for_each (ptmp, &ksocknal_data.ksnd_peers[i]) {
-                       peer = list_entry (ptmp, ksock_peer_t, ksnp_list);
+               list_for_each(ptmp, &ksocknal_data.ksnd_peers[i]) {
+                       peer = list_entry(ptmp, ksock_peer_t, ksnp_list);
 
                        if (peer->ksnp_ni != ni)
                                continue;
@@ -296,7 +296,7 @@ ksocknal_get_peer_info (lnet_ni_t *ni, int index,
                                goto out;
                        }
 
-                       list_for_each (rtmp, &peer->ksnp_routes) {
+                       list_for_each(rtmp, &peer->ksnp_routes) {
                                if (index-- > 0)
                                        continue;
 
@@ -364,17 +364,17 @@ ksocknal_associate_route_conn_locked(ksock_route_t *route, ksock_conn_t *conn)
 }
 
 static void
-ksocknal_add_route_locked (ksock_peer_t *peer, ksock_route_t *route)
+ksocknal_add_route_locked(ksock_peer_t *peer, ksock_route_t *route)
 {
        struct list_head        *tmp;
        ksock_conn_t      *conn;
        ksock_route_t     *route2;
 
-       LASSERT (!peer->ksnp_closing);
-       LASSERT (route->ksnr_peer == NULL);
-       LASSERT (!route->ksnr_scheduled);
-       LASSERT (!route->ksnr_connecting);
-       LASSERT (route->ksnr_connected == 0);
+       LASSERT(!peer->ksnp_closing);
+       LASSERT(route->ksnr_peer == NULL);
+       LASSERT(!route->ksnr_scheduled);
+       LASSERT(!route->ksnr_connecting);
+       LASSERT(route->ksnr_connected == 0);
 
        /* LASSERT(unique) */
        list_for_each(tmp, &peer->ksnp_routes) {
@@ -405,7 +405,7 @@ ksocknal_add_route_locked (ksock_peer_t *peer, ksock_route_t *route)
 }
 
 static void
-ksocknal_del_route_locked (ksock_route_t *route)
+ksocknal_del_route_locked(ksock_route_t *route)
 {
        ksock_peer_t      *peer = route->ksnr_peer;
        ksock_interface_t *iface;
@@ -413,16 +413,16 @@ ksocknal_del_route_locked (ksock_route_t *route)
        struct list_head        *ctmp;
        struct list_head        *cnxt;
 
-       LASSERT (!route->ksnr_deleted);
+       LASSERT(!route->ksnr_deleted);
 
        /* Close associated conns */
-       list_for_each_safe (ctmp, cnxt, &peer->ksnp_conns) {
+       list_for_each_safe(ctmp, cnxt, &peer->ksnp_conns) {
                conn = list_entry(ctmp, ksock_conn_t, ksnc_list);
 
                if (conn->ksnc_route != route)
                        continue;
 
-               ksocknal_close_conn_locked (conn, 0);
+               ksocknal_close_conn_locked(conn, 0);
        }
 
        if (route->ksnr_myipaddr != 0) {
@@ -433,19 +433,19 @@ ksocknal_del_route_locked (ksock_route_t *route)
        }
 
        route->ksnr_deleted = 1;
-       list_del (&route->ksnr_list);
+       list_del(&route->ksnr_list);
        ksocknal_route_decref(route);        /* drop peer's ref */
 
-       if (list_empty (&peer->ksnp_routes) &&
-           list_empty (&peer->ksnp_conns)) {
+       if (list_empty(&peer->ksnp_routes) &&
+           list_empty(&peer->ksnp_conns)) {
                /* I've just removed the last route to a peer with no active
                 * connections */
-               ksocknal_unlink_peer_locked (peer);
+               ksocknal_unlink_peer_locked(peer);
        }
 }
 
 int
-ksocknal_add_peer (lnet_ni_t *ni, lnet_process_id_t id, __u32 ipaddr, int port)
+ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ipaddr, int port)
 {
        struct list_head        *tmp;
        ksock_peer_t      *peer;
@@ -463,7 +463,7 @@ ksocknal_add_peer (lnet_ni_t *ni, lnet_process_id_t id, __u32 ipaddr, int port)
        if (rc != 0)
                return rc;
 
-       route = ksocknal_create_route (ipaddr, port);
+       route = ksocknal_create_route(ipaddr, port);
        if (route == NULL) {
                ksocknal_peer_decref(peer);
                return -ENOMEM;
@@ -472,20 +472,20 @@ ksocknal_add_peer (lnet_ni_t *ni, lnet_process_id_t id, __u32 ipaddr, int port)
        write_lock_bh(&ksocknal_data.ksnd_global_lock);
 
        /* always called with a ref on ni, so shutdown can't have started */
-       LASSERT (((ksock_net_t *) ni->ni_data)->ksnn_shutdown == 0);
+       LASSERT(((ksock_net_t *) ni->ni_data)->ksnn_shutdown == 0);
 
-       peer2 = ksocknal_find_peer_locked (ni, id);
+       peer2 = ksocknal_find_peer_locked(ni, id);
        if (peer2 != NULL) {
                ksocknal_peer_decref(peer);
                peer = peer2;
        } else {
                /* peer table takes my ref on peer */
-               list_add_tail (&peer->ksnp_list,
-                                  ksocknal_nid2peerlist (id.nid));
+               list_add_tail(&peer->ksnp_list,
+                                  ksocknal_nid2peerlist(id.nid));
        }
 
        route2 = NULL;
-       list_for_each (tmp, &peer->ksnp_routes) {
+       list_for_each(tmp, &peer->ksnp_routes) {
                route2 = list_entry(tmp, ksock_route_t, ksnr_list);
 
                if (route2->ksnr_ipaddr == ipaddr)
@@ -507,7 +507,7 @@ ksocknal_add_peer (lnet_ni_t *ni, lnet_process_id_t id, __u32 ipaddr, int port)
 }
 
 static void
-ksocknal_del_peer_locked (ksock_peer_t *peer, __u32 ip)
+ksocknal_del_peer_locked(ksock_peer_t *peer, __u32 ip)
 {
        ksock_conn_t     *conn;
        ksock_route_t    *route;
@@ -515,12 +515,12 @@ ksocknal_del_peer_locked (ksock_peer_t *peer, __u32 ip)
        struct list_head       *nxt;
        int            nshared;
 
-       LASSERT (!peer->ksnp_closing);
+       LASSERT(!peer->ksnp_closing);
 
        /* Extra ref prevents peer disappearing until I'm done with it */
        ksocknal_peer_addref(peer);
 
-       list_for_each_safe (tmp, nxt, &peer->ksnp_routes) {
+       list_for_each_safe(tmp, nxt, &peer->ksnp_routes) {
                route = list_entry(tmp, ksock_route_t, ksnr_list);
 
                /* no match */
@@ -529,11 +529,11 @@ ksocknal_del_peer_locked (ksock_peer_t *peer, __u32 ip)
 
                route->ksnr_share_count = 0;
                /* This deletes associated conns too */
-               ksocknal_del_route_locked (route);
+               ksocknal_del_route_locked(route);
        }
 
        nshared = 0;
-       list_for_each_safe (tmp, nxt, &peer->ksnp_routes) {
+       list_for_each_safe(tmp, nxt, &peer->ksnp_routes) {
                route = list_entry(tmp, ksock_route_t, ksnr_list);
                nshared += route->ksnr_share_count;
        }
@@ -542,15 +542,15 @@ ksocknal_del_peer_locked (ksock_peer_t *peer, __u32 ip)
                /* remove everything else if there are no explicit entries
                 * left */
 
-               list_for_each_safe (tmp, nxt, &peer->ksnp_routes) {
+               list_for_each_safe(tmp, nxt, &peer->ksnp_routes) {
                        route = list_entry(tmp, ksock_route_t, ksnr_list);
 
                        /* we should only be removing auto-entries */
                        LASSERT(route->ksnr_share_count == 0);
-                       ksocknal_del_route_locked (route);
+                       ksocknal_del_route_locked(route);
                }
 
-               list_for_each_safe (tmp, nxt, &peer->ksnp_conns) {
+               list_for_each_safe(tmp, nxt, &peer->ksnp_conns) {
                        conn = list_entry(tmp, ksock_conn_t, ksnc_list);
 
                        ksocknal_close_conn_locked(conn, 0);
@@ -562,9 +562,9 @@ ksocknal_del_peer_locked (ksock_peer_t *peer, __u32 ip)
 }
 
 static int
-ksocknal_del_peer (lnet_ni_t *ni, lnet_process_id_t id, __u32 ip)
+ksocknal_del_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ip)
 {
-       LIST_HEAD     (zombies);
+       LIST_HEAD(zombies);
        struct list_head        *ptmp;
        struct list_head        *pnxt;
        ksock_peer_t      *peer;
@@ -583,9 +583,9 @@ ksocknal_del_peer (lnet_ni_t *ni, lnet_process_id_t id, __u32 ip)
        }
 
        for (i = lo; i <= hi; i++) {
-               list_for_each_safe (ptmp, pnxt,
+               list_for_each_safe(ptmp, pnxt,
                                        &ksocknal_data.ksnd_peers[i]) {
-                       peer = list_entry (ptmp, ksock_peer_t, ksnp_list);
+                       peer = list_entry(ptmp, ksock_peer_t, ksnp_list);
 
                        if (peer->ksnp_ni != ni)
                                continue;
@@ -596,12 +596,12 @@ ksocknal_del_peer (lnet_ni_t *ni, lnet_process_id_t id, __u32 ip)
 
                        ksocknal_peer_addref(peer);     /* a ref for me... */
 
-                       ksocknal_del_peer_locked (peer, ip);
+                       ksocknal_del_peer_locked(peer, ip);
 
                        if (peer->ksnp_closing &&
                            !list_empty(&peer->ksnp_tx_queue)) {
-                               LASSERT (list_empty(&peer->ksnp_conns));
-                               LASSERT (list_empty(&peer->ksnp_routes));
+                               LASSERT(list_empty(&peer->ksnp_conns));
+                               LASSERT(list_empty(&peer->ksnp_routes));
 
                                list_splice_init(&peer->ksnp_tx_queue,
                                                     &zombies);
@@ -621,7 +621,7 @@ ksocknal_del_peer (lnet_ni_t *ni, lnet_process_id_t id, __u32 ip)
 }
 
 static ksock_conn_t *
-ksocknal_get_conn_by_idx (lnet_ni_t *ni, int index)
+ksocknal_get_conn_by_idx(lnet_ni_t *ni, int index)
 {
        ksock_peer_t      *peer;
        struct list_head        *ptmp;
@@ -632,19 +632,19 @@ ksocknal_get_conn_by_idx (lnet_ni_t *ni, int index)
        read_lock(&ksocknal_data.ksnd_global_lock);
 
        for (i = 0; i < ksocknal_data.ksnd_peer_hash_size; i++) {
-               list_for_each (ptmp, &ksocknal_data.ksnd_peers[i]) {
-                       peer = list_entry (ptmp, ksock_peer_t, ksnp_list);
+               list_for_each(ptmp, &ksocknal_data.ksnd_peers[i]) {
+                       peer = list_entry(ptmp, ksock_peer_t, ksnp_list);
 
-                       LASSERT (!peer->ksnp_closing);
+                       LASSERT(!peer->ksnp_closing);
 
                        if (peer->ksnp_ni != ni)
                                continue;
 
-                       list_for_each (ctmp, &peer->ksnp_conns) {
+                       list_for_each(ctmp, &peer->ksnp_conns) {
                                if (index-- > 0)
                                        continue;
 
-                               conn = list_entry (ctmp, ksock_conn_t,
+                               conn = list_entry(ctmp, ksock_conn_t,
                                                       ksnc_list);
                                ksocknal_conn_addref(conn);
                                read_unlock(&ksocknal_data.ksnd_global_lock);
@@ -681,7 +681,7 @@ ksocknal_choose_scheduler_locked(unsigned int cpt)
 }
 
 static int
-ksocknal_local_ipvec (lnet_ni_t *ni, __u32 *ipaddrs)
+ksocknal_local_ipvec(lnet_ni_t *ni, __u32 *ipaddrs)
 {
        ksock_net_t       *net = ni->ni_data;
        int             i;
@@ -690,7 +690,7 @@ ksocknal_local_ipvec (lnet_ni_t *ni, __u32 *ipaddrs)
        read_lock(&ksocknal_data.ksnd_global_lock);
 
        nip = net->ksnn_ninterfaces;
-       LASSERT (nip <= LNET_MAX_INTERFACES);
+       LASSERT(nip <= LNET_MAX_INTERFACES);
 
        /* Only offer interfaces for additional connections if I have
         * more than one. */
@@ -701,7 +701,7 @@ ksocknal_local_ipvec (lnet_ni_t *ni, __u32 *ipaddrs)
 
        for (i = 0; i < nip; i++) {
                ipaddrs[i] = net->ksnn_interfaces[i].ksni_ipaddr;
-               LASSERT (ipaddrs[i] != 0);
+               LASSERT(ipaddrs[i] != 0);
        }
 
        read_unlock(&ksocknal_data.ksnd_global_lock);
@@ -709,7 +709,7 @@ ksocknal_local_ipvec (lnet_ni_t *ni, __u32 *ipaddrs)
 }
 
 static int
-ksocknal_match_peerip (ksock_interface_t *iface, __u32 *ips, int nips)
+ksocknal_match_peerip(ksock_interface_t *iface, __u32 *ips, int nips)
 {
        int   best_netmatch = 0;
        int   best_xor      = 0;
@@ -722,7 +722,7 @@ ksocknal_match_peerip (ksock_interface_t *iface, __u32 *ips, int nips)
                if (ips[i] == 0)
                        continue;
 
-               this_xor = (ips[i] ^ iface->ksni_ipaddr);
+               this_xor = ips[i] ^ iface->ksni_ipaddr;
                this_netmatch = ((this_xor & iface->ksni_netmask) == 0) ? 1 : 0;
 
                if (!(best < 0 ||
@@ -736,7 +736,7 @@ ksocknal_match_peerip (ksock_interface_t *iface, __u32 *ips, int nips)
                best_xor = this_xor;
        }
 
-       LASSERT (best >= 0);
+       LASSERT(best >= 0);
        return best;
 }
 
@@ -767,8 +767,8 @@ ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips)
 
        write_lock_bh(global_lock);
 
-       LASSERT (n_peerips <= LNET_MAX_INTERFACES);
-       LASSERT (net->ksnn_ninterfaces <= LNET_MAX_INTERFACES);
+       LASSERT(n_peerips <= LNET_MAX_INTERFACES);
+       LASSERT(net->ksnn_ninterfaces <= LNET_MAX_INTERFACES);
 
        /* Only match interfaces for additional connections
         * if I have > 1 interface */
@@ -791,7 +791,7 @@ ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips)
 
                } else {
                        /* choose a new interface */
-                       LASSERT (i == peer->ksnp_n_passive_ips);
+                       LASSERT(i == peer->ksnp_n_passive_ips);
 
                        best_iface = NULL;
                        best_netmatch = 0;
@@ -809,7 +809,7 @@ ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips)
                                        continue;
 
                                k = ksocknal_match_peerip(iface, peerips, n_peerips);
-                               xor = (ip ^ peerips[k]);
+                               xor = ip ^ peerips[k];
                                this_netmatch = ((xor & iface->ksni_netmask) == 0) ? 1 : 0;
 
                                if (!(best_iface == NULL ||
@@ -874,7 +874,7 @@ ksocknal_create_routes(ksock_peer_t *peer, int port,
                return;
        }
 
-       LASSERT (npeer_ipaddrs <= LNET_MAX_INTERFACES);
+       LASSERT(npeer_ipaddrs <= LNET_MAX_INTERFACES);
 
        for (i = 0; i < npeer_ipaddrs; i++) {
                if (newroute != NULL) {
@@ -911,7 +911,7 @@ ksocknal_create_routes(ksock_peer_t *peer, int port,
                best_nroutes = 0;
                best_netmatch = 0;
 
-               LASSERT (net->ksnn_ninterfaces <= LNET_MAX_INTERFACES);
+               LASSERT(net->ksnn_ninterfaces <= LNET_MAX_INTERFACES);
 
                /* Select interface to connect from */
                for (j = 0; j < net->ksnn_ninterfaces; j++) {
@@ -961,7 +961,7 @@ ksocknal_create_routes(ksock_peer_t *peer, int port,
 }
 
 int
-ksocknal_accept (lnet_ni_t *ni, struct socket *sock)
+ksocknal_accept(lnet_ni_t *ni, struct socket *sock)
 {
        ksock_connreq_t    *cr;
        int              rc;
@@ -969,7 +969,7 @@ ksocknal_accept (lnet_ni_t *ni, struct socket *sock)
        int              peer_port;
 
        rc = libcfs_sock_getaddr(sock, 1, &peer_ip, &peer_port);
-       LASSERT (rc == 0);                    /* we succeeded before */
+       LASSERT(rc == 0);                     /* we succeeded before */
 
        LIBCFS_ALLOC(cr, sizeof(*cr));
        if (cr == NULL) {
@@ -992,11 +992,11 @@ ksocknal_accept (lnet_ni_t *ni, struct socket *sock)
 }
 
 static int
-ksocknal_connecting (ksock_peer_t *peer, __u32 ipaddr)
+ksocknal_connecting(ksock_peer_t *peer, __u32 ipaddr)
 {
        ksock_route_t   *route;
 
-       list_for_each_entry (route, &peer->ksnp_routes, ksnr_list) {
+       list_for_each_entry(route, &peer->ksnp_routes, ksnr_list) {
 
                if (route->ksnr_ipaddr == ipaddr)
                        return route->ksnr_connecting;
@@ -1005,11 +1005,11 @@ ksocknal_connecting (ksock_peer_t *peer, __u32 ipaddr)
 }
 
 int
-ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
+ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route,
                      struct socket *sock, int type)
 {
        rwlock_t                *global_lock = &ksocknal_data.ksnd_global_lock;
-       LIST_HEAD     (zombies);
+       LIST_HEAD(zombies);
        lnet_process_id_t  peerid;
        struct list_head        *tmp;
        __u64         incarnation;
@@ -1028,7 +1028,7 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
 
        active = (route != NULL);
 
-       LASSERT (active == (type != SOCKLND_CONN_NONE));
+       LASSERT(active == (type != SOCKLND_CONN_NONE));
 
        LIBCFS_ALLOC(conn, sizeof(*conn));
        if (conn == NULL) {
@@ -1041,19 +1041,19 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
        conn->ksnc_sock = sock;
        /* 2 ref, 1 for conn, another extra ref prevents socket
         * being closed before establishment of connection */
-       atomic_set (&conn->ksnc_sock_refcount, 2);
+       atomic_set(&conn->ksnc_sock_refcount, 2);
        conn->ksnc_type = type;
        ksocknal_lib_save_callback(sock, conn);
-       atomic_set (&conn->ksnc_conn_refcount, 1); /* 1 ref for me */
+       atomic_set(&conn->ksnc_conn_refcount, 1); /* 1 ref for me */
 
        conn->ksnc_rx_ready = 0;
        conn->ksnc_rx_scheduled = 0;
 
-       INIT_LIST_HEAD (&conn->ksnc_tx_queue);
+       INIT_LIST_HEAD(&conn->ksnc_tx_queue);
        conn->ksnc_tx_ready = 0;
        conn->ksnc_tx_scheduled = 0;
        conn->ksnc_tx_carrier = NULL;
-       atomic_set (&conn->ksnc_tx_nob, 0);
+       atomic_set(&conn->ksnc_tx_nob, 0);
 
        LIBCFS_ALLOC(hello, offsetof(ksock_hello_msg_t,
                                     kshm_ips[LNET_MAX_INTERFACES]));
@@ -1063,7 +1063,7 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
        }
 
        /* stash conn's local and remote addrs */
-       rc = ksocknal_lib_get_conn_addrs (conn);
+       rc = ksocknal_lib_get_conn_addrs(conn);
        if (rc != 0)
                goto failed_1;
 
@@ -1094,7 +1094,7 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
 #endif
                }
 
-               rc = ksocknal_send_hello (ni, conn, peerid.nid, hello);
+               rc = ksocknal_send_hello(ni, conn, peerid.nid, hello);
                if (rc != 0)
                        goto failed_1;
        } else {
@@ -1105,13 +1105,13 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
                conn->ksnc_proto = NULL;
        }
 
-       rc = ksocknal_recv_hello (ni, conn, hello, &peerid, &incarnation);
+       rc = ksocknal_recv_hello(ni, conn, hello, &peerid, &incarnation);
        if (rc < 0)
                goto failed_1;
 
-       LASSERT (rc == 0 || active);
-       LASSERT (conn->ksnc_proto != NULL);
-       LASSERT (peerid.nid != LNET_NID_ANY);
+       LASSERT(rc == 0 || active);
+       LASSERT(conn->ksnc_proto != NULL);
+       LASSERT(peerid.nid != LNET_NID_ANY);
 
        cpt = lnet_cpt_of_nid(peerid.nid);
 
@@ -1126,7 +1126,7 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
                write_lock_bh(global_lock);
 
                /* called with a ref on ni, so shutdown can't have started */
-               LASSERT (((ksock_net_t *) ni->ni_data)->ksnn_shutdown == 0);
+               LASSERT(((ksock_net_t *) ni->ni_data)->ksnn_shutdown == 0);
 
                peer2 = ksocknal_find_peer_locked(ni, peerid);
                if (peer2 == NULL) {
@@ -1166,7 +1166,7 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
                 * NB recv_hello may have returned EPROTO to signal my peer
                 * wants a different protocol than the one I asked for.
                 */
-               LASSERT (list_empty(&peer->ksnp_conns));
+               LASSERT(list_empty(&peer->ksnp_conns));
 
                peer->ksnp_proto = conn->ksnc_proto;
                peer->ksnp_incarnation = incarnation;
@@ -1211,7 +1211,7 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
 
                        /* Reply on a passive connection attempt so the peer
                         * realises we're connected. */
-                       LASSERT (rc == 0);
+                       LASSERT(rc == 0);
                        if (!active)
                                rc = EALREADY;
 
@@ -1235,7 +1235,7 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
         * create an association.  This allows incoming connections created
         * by routes in my peer to match my own route entries so I don't
         * continually create duplicate routes. */
-       list_for_each (tmp, &peer->ksnp_routes) {
+       list_for_each(tmp, &peer->ksnp_routes) {
                route = list_entry(tmp, ksock_route_t, ksnr_list);
 
                if (route->ksnr_ipaddr != conn->ksnc_ipaddr)
@@ -1260,7 +1260,7 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
        conn->ksnc_tx_deadline = cfs_time_shift(*ksocknal_tunables.ksnd_timeout);
        mb();   /* order with adding to peer's conn list */
 
-       list_add (&conn->ksnc_list, &peer->ksnp_conns);
+       list_add(&conn->ksnc_list, &peer->ksnp_conns);
        ksocknal_conn_addref(conn);
 
        ksocknal_new_packet(conn, 0);
@@ -1272,8 +1272,8 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
                if (conn->ksnc_proto->pro_match_tx(conn, tx, tx->tx_nonblk) == SOCKNAL_MATCH_NO)
                                continue;
 
-               list_del (&tx->tx_list);
-               ksocknal_queue_tx_locked (tx, conn);
+               list_del(&tx->tx_list);
+               ksocknal_queue_tx_locked(tx, conn);
        }
 
        write_unlock_bh(global_lock);
@@ -1343,8 +1343,8 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
 
  failed_2:
        if (!peer->ksnp_closing &&
-           list_empty (&peer->ksnp_conns) &&
-           list_empty (&peer->ksnp_routes)) {
+           list_empty(&peer->ksnp_conns) &&
+           list_empty(&peer->ksnp_routes)) {
                list_add(&zombies, &peer->ksnp_tx_queue);
                list_del_init(&peer->ksnp_tx_queue);
                ksocknal_unlink_peer_locked(peer);
@@ -1383,7 +1383,7 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
                LIBCFS_FREE(hello, offsetof(ksock_hello_msg_t,
                                            kshm_ips[LNET_MAX_INTERFACES]));
 
-       LIBCFS_FREE (conn, sizeof(*conn));
+       LIBCFS_FREE(conn, sizeof(*conn));
 
  failed_0:
        libcfs_sock_release(sock);
@@ -1391,7 +1391,7 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route,
 }
 
 void
-ksocknal_close_conn_locked (ksock_conn_t *conn, int error)
+ksocknal_close_conn_locked(ksock_conn_t *conn, int error)
 {
        /* This just does the immmediate housekeeping, and queues the
         * connection for the reaper to terminate.
@@ -1401,18 +1401,18 @@ ksocknal_close_conn_locked (ksock_conn_t *conn, int error)
        ksock_conn_t      *conn2;
        struct list_head        *tmp;
 
-       LASSERT (peer->ksnp_error == 0);
-       LASSERT (!conn->ksnc_closing);
+       LASSERT(peer->ksnp_error == 0);
+       LASSERT(!conn->ksnc_closing);
        conn->ksnc_closing = 1;
 
        /* ksnd_deathrow_conns takes over peer's ref */
-       list_del (&conn->ksnc_list);
+       list_del(&conn->ksnc_list);
 
        route = conn->ksnc_route;
        if (route != NULL) {
                /* dissociate conn from route... */
-               LASSERT (!route->ksnr_deleted);
-               LASSERT ((route->ksnr_connected & (1 << conn->ksnc_type)) != 0);
+               LASSERT(!route->ksnr_deleted);
+               LASSERT((route->ksnr_connected & (1 << conn->ksnc_type)) != 0);
 
                conn2 = NULL;
                list_for_each(tmp, &peer->ksnp_conns) {
@@ -1431,19 +1431,19 @@ ksocknal_close_conn_locked (ksock_conn_t *conn, int error)
 
 #if 0     /* irrelevant with only eager routes */
                /* make route least favourite */
-               list_del (&route->ksnr_list);
-               list_add_tail (&route->ksnr_list, &peer->ksnp_routes);
+               list_del(&route->ksnr_list);
+               list_add_tail(&route->ksnr_list, &peer->ksnp_routes);
 #endif
                ksocknal_route_decref(route);     /* drop conn's ref on route */
        }
 
-       if (list_empty (&peer->ksnp_conns)) {
+       if (list_empty(&peer->ksnp_conns)) {
                /* No more connections to this peer */
 
                if (!list_empty(&peer->ksnp_tx_queue)) {
                        ksock_tx_t *tx;
 
-                       LASSERT (conn->ksnc_proto == &ksocknal_protocol_v3x);
+                       LASSERT(conn->ksnc_proto == &ksocknal_protocol_v3x);
 
                        /* throw them to the last connection...,
                         * these TXs will be send to /dev/null by scheduler */
@@ -1460,10 +1460,10 @@ ksocknal_close_conn_locked (ksock_conn_t *conn, int error)
                peer->ksnp_proto = NULL;        /* renegotiate protocol version */
                peer->ksnp_error = error;       /* stash last conn close reason */
 
-               if (list_empty (&peer->ksnp_routes)) {
+               if (list_empty(&peer->ksnp_routes)) {
                        /* I've just closed last conn belonging to a
                         * peer with no routes to it */
-                       ksocknal_unlink_peer_locked (peer);
+                       ksocknal_unlink_peer_locked(peer);
                }
        }
 
@@ -1477,7 +1477,7 @@ ksocknal_close_conn_locked (ksock_conn_t *conn, int error)
 }
 
 void
-ksocknal_peer_failed (ksock_peer_t *peer)
+ksocknal_peer_failed(ksock_peer_t *peer)
 {
        int     notify = 0;
        unsigned long last_alive = 0;
@@ -1499,7 +1499,7 @@ ksocknal_peer_failed (ksock_peer_t *peer)
        read_unlock(&ksocknal_data.ksnd_global_lock);
 
        if (notify)
-               lnet_notify (peer->ksnp_ni, peer->ksnp_id.nid, 0,
+               lnet_notify(peer->ksnp_ni, peer->ksnp_id.nid, 0,
                             last_alive);
 }
 
@@ -1509,11 +1509,11 @@ ksocknal_finalize_zcreq(ksock_conn_t *conn)
        ksock_peer_t     *peer = conn->ksnc_peer;
        ksock_tx_t       *tx;
        ksock_tx_t       *tmp;
-       LIST_HEAD    (zlist);
+       LIST_HEAD(zlist);
 
        /* NB safe to finalize TXs because closing of socket will
         * abort all buffered data */
-       LASSERT (conn->ksnc_sock == NULL);
+       LASSERT(conn->ksnc_sock == NULL);
 
        spin_lock(&peer->ksnp_lock);
 
@@ -1521,7 +1521,7 @@ ksocknal_finalize_zcreq(ksock_conn_t *conn)
                if (tx->tx_conn != conn)
                        continue;
 
-               LASSERT (tx->tx_msg.ksm_zc_cookies[0] != 0);
+               LASSERT(tx->tx_msg.ksm_zc_cookies[0] != 0);
 
                tx->tx_msg.ksm_zc_cookies[0] = 0;
                tx->tx_zc_aborted = 1; /* mark it as not-acked */
@@ -1540,7 +1540,7 @@ ksocknal_finalize_zcreq(ksock_conn_t *conn)
 }
 
 void
-ksocknal_terminate_conn (ksock_conn_t *conn)
+ksocknal_terminate_conn(ksock_conn_t *conn)
 {
        /* This gets called by the reaper (guaranteed thread context) to
         * disengage the socket from its callbacks and close it.
@@ -1560,13 +1560,13 @@ ksocknal_terminate_conn (ksock_conn_t *conn)
 
        if (!conn->ksnc_tx_scheduled &&
            !list_empty(&conn->ksnc_tx_queue)) {
-               list_add_tail (&conn->ksnc_tx_list,
+               list_add_tail(&conn->ksnc_tx_list,
                               &sched->kss_tx_conns);
                conn->ksnc_tx_scheduled = 1;
                /* extra ref for scheduler */
                ksocknal_conn_addref(conn);
 
-               wake_up (&sched->kss_waitq);
+               wake_up(&sched->kss_waitq);
        }
 
        spin_unlock_bh(&sched->kss_lock);
@@ -1582,7 +1582,7 @@ ksocknal_terminate_conn (ksock_conn_t *conn)
 
        if (peer->ksnp_error != 0) {
                /* peer's last conn closed in error */
-               LASSERT (list_empty (&peer->ksnp_conns));
+               LASSERT(list_empty(&peer->ksnp_conns));
                failed = 1;
                peer->ksnp_error = 0;     /* avoid multiple notifications */
        }
@@ -1601,7 +1601,7 @@ ksocknal_terminate_conn (ksock_conn_t *conn)
 }
 
 void
-ksocknal_queue_zombie_conn (ksock_conn_t *conn)
+ksocknal_queue_zombie_conn(ksock_conn_t *conn)
 {
        /* Queue the conn for the reaper to destroy */
 
@@ -1615,20 +1615,20 @@ ksocknal_queue_zombie_conn (ksock_conn_t *conn)
 }
 
 void
-ksocknal_destroy_conn (ksock_conn_t *conn)
+ksocknal_destroy_conn(ksock_conn_t *conn)
 {
        unsigned long      last_rcv;
 
        /* Final coup-de-grace of the reaper */
-       CDEBUG (D_NET, "connection %p\n", conn);
+       CDEBUG(D_NET, "connection %p\n", conn);
 
-       LASSERT (atomic_read (&conn->ksnc_conn_refcount) == 0);
-       LASSERT (atomic_read (&conn->ksnc_sock_refcount) == 0);
-       LASSERT (conn->ksnc_sock == NULL);
-       LASSERT (conn->ksnc_route == NULL);
-       LASSERT (!conn->ksnc_tx_scheduled);
-       LASSERT (!conn->ksnc_rx_scheduled);
-       LASSERT (list_empty(&conn->ksnc_tx_queue));
+       LASSERT(atomic_read(&conn->ksnc_conn_refcount) == 0);
+       LASSERT(atomic_read(&conn->ksnc_sock_refcount) == 0);
+       LASSERT(conn->ksnc_sock == NULL);
+       LASSERT(conn->ksnc_route == NULL);
+       LASSERT(!conn->ksnc_tx_scheduled);
+       LASSERT(!conn->ksnc_rx_scheduled);
+       LASSERT(list_empty(&conn->ksnc_tx_queue));
 
        /* complete current receive if any */
        switch (conn->ksnc_rx_state) {
@@ -1641,7 +1641,7 @@ ksocknal_destroy_conn (ksock_conn_t *conn)
                       conn->ksnc_rx_nob_wanted, conn->ksnc_rx_nob_left,
                       cfs_duration_sec(cfs_time_sub(cfs_time_current(),
                                                     last_rcv)));
-               lnet_finalize (conn->ksnc_peer->ksnp_ni,
+               lnet_finalize(conn->ksnc_peer->ksnp_ni,
                               conn->ksnc_cookie, -EIO);
                break;
        case SOCKNAL_RX_LNET_HEADER:
@@ -1665,30 +1665,30 @@ ksocknal_destroy_conn (ksock_conn_t *conn)
                               &conn->ksnc_ipaddr, conn->ksnc_port);
               break;
        default:
-               LBUG ();
+               LBUG();
                break;
        }
 
        ksocknal_peer_decref(conn->ksnc_peer);
 
-       LIBCFS_FREE (conn, sizeof (*conn));
+       LIBCFS_FREE(conn, sizeof(*conn));
 }
 
 int
-ksocknal_close_peer_conns_locked (ksock_peer_t *peer, __u32 ipaddr, int why)
+ksocknal_close_peer_conns_locked(ksock_peer_t *peer, __u32 ipaddr, int why)
 {
        ksock_conn_t       *conn;
        struct list_head         *ctmp;
        struct list_head         *cnxt;
        int              count = 0;
 
-       list_for_each_safe (ctmp, cnxt, &peer->ksnp_conns) {
-               conn = list_entry (ctmp, ksock_conn_t, ksnc_list);
+       list_for_each_safe(ctmp, cnxt, &peer->ksnp_conns) {
+               conn = list_entry(ctmp, ksock_conn_t, ksnc_list);
 
                if (ipaddr == 0 ||
                    conn->ksnc_ipaddr == ipaddr) {
                        count++;
-                       ksocknal_close_conn_locked (conn, why);
+                       ksocknal_close_conn_locked(conn, why);
                }
        }
 
@@ -1696,7 +1696,7 @@ 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)
+ksocknal_close_conn_and_siblings(ksock_conn_t *conn, int why)
 {
        ksock_peer_t     *peer = conn->ksnc_peer;
        __u32        ipaddr = conn->ksnc_ipaddr;
@@ -1704,7 +1704,7 @@ ksocknal_close_conn_and_siblings (ksock_conn_t *conn, int why)
 
        write_lock_bh(&ksocknal_data.ksnd_global_lock);
 
-       count = ksocknal_close_peer_conns_locked (peer, ipaddr, why);
+       count = ksocknal_close_peer_conns_locked(peer, ipaddr, why);
 
        write_unlock_bh(&ksocknal_data.ksnd_global_lock);
 
@@ -1712,7 +1712,7 @@ ksocknal_close_conn_and_siblings (ksock_conn_t *conn, int why)
 }
 
 int
-ksocknal_close_matching_conns (lnet_process_id_t id, __u32 ipaddr)
+ksocknal_close_matching_conns(lnet_process_id_t id, __u32 ipaddr)
 {
        ksock_peer_t       *peer;
        struct list_head         *ptmp;
@@ -1732,16 +1732,16 @@ ksocknal_close_matching_conns (lnet_process_id_t id, __u32 ipaddr)
        }
 
        for (i = lo; i <= hi; i++) {
-               list_for_each_safe (ptmp, pnxt,
+               list_for_each_safe(ptmp, pnxt,
                                        &ksocknal_data.ksnd_peers[i]) {
 
-                       peer = list_entry (ptmp, ksock_peer_t, ksnp_list);
+                       peer = list_entry(ptmp, ksock_peer_t, ksnp_list);
 
                        if (!((id.nid == LNET_NID_ANY || id.nid == peer->ksnp_id.nid) &&
                              (id.pid == LNET_PID_ANY || id.pid == peer->ksnp_id.pid)))
                                continue;
 
-                       count += ksocknal_close_peer_conns_locked (peer, ipaddr, 0);
+                       count += ksocknal_close_peer_conns_locked(peer, ipaddr, 0);
                }
        }
 
@@ -1758,7 +1758,7 @@ ksocknal_close_matching_conns (lnet_process_id_t id, __u32 ipaddr)
 }
 
 void
-ksocknal_notify (lnet_ni_t *ni, lnet_nid_t gw_nid, int alive)
+ksocknal_notify(lnet_ni_t *ni, lnet_nid_t gw_nid, int alive)
 {
        /* The router is telling me she's been notified of a change in
         * gateway state.... */
@@ -1767,12 +1767,12 @@ ksocknal_notify (lnet_ni_t *ni, lnet_nid_t gw_nid, int alive)
        id.nid = gw_nid;
        id.pid = LNET_PID_ANY;
 
-       CDEBUG (D_NET, "gw %s %s\n", libcfs_nid2str(gw_nid),
+       CDEBUG(D_NET, "gw %s %s\n", libcfs_nid2str(gw_nid),
                alive ? "up" : "down");
 
        if (!alive) {
                /* If the gateway crashed, close all open connections... */
-               ksocknal_close_matching_conns (id, 0);
+               ksocknal_close_matching_conns(id, 0);
                return;
        }
 
@@ -1781,7 +1781,7 @@ ksocknal_notify (lnet_ni_t *ni, lnet_nid_t gw_nid, int alive)
 }
 
 void
-ksocknal_query (lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when)
+ksocknal_query(lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when)
 {
        int             connect = 1;
        unsigned long    last_alive = 0;
@@ -1798,7 +1798,7 @@ ksocknal_query (lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when)
                ksock_conn_t     *conn;
                int            bufnob;
 
-               list_for_each (tmp, &peer->ksnp_conns) {
+               list_for_each(tmp, &peer->ksnp_conns) {
                        conn = list_entry(tmp, ksock_conn_t, ksnc_list);
                        bufnob = conn->ksnc_sock->sk->sk_wmem_queued;
 
@@ -1842,7 +1842,7 @@ ksocknal_query (lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when)
 }
 
 static void
-ksocknal_push_peer (ksock_peer_t *peer)
+ksocknal_push_peer(ksock_peer_t *peer)
 {
        int            index;
        int            i;
@@ -1855,9 +1855,9 @@ ksocknal_push_peer (ksock_peer_t *peer)
                i = 0;
                conn = NULL;
 
-               list_for_each (tmp, &peer->ksnp_conns) {
+               list_for_each(tmp, &peer->ksnp_conns) {
                        if (i++ == index) {
-                               conn = list_entry (tmp, ksock_conn_t,
+                               conn = list_entry(tmp, ksock_conn_t,
                                                       ksnc_list);
                                ksocknal_conn_addref(conn);
                                break;
@@ -1869,13 +1869,13 @@ ksocknal_push_peer (ksock_peer_t *peer)
                if (conn == NULL)
                        break;
 
-               ksocknal_lib_push_conn (conn);
+               ksocknal_lib_push_conn(conn);
                ksocknal_conn_decref(conn);
        }
 }
 
 static int
-ksocknal_push (lnet_ni_t *ni, lnet_process_id_t id)
+ksocknal_push(lnet_ni_t *ni, lnet_process_id_t id)
 {
        ksock_peer_t      *peer;
        struct list_head        *tmp;
@@ -1891,7 +1891,7 @@ ksocknal_push (lnet_ni_t *ni, lnet_process_id_t id)
                        index = 0;
                        peer = NULL;
 
-                       list_for_each (tmp, &ksocknal_data.ksnd_peers[i]) {
+                       list_for_each(tmp, &ksocknal_data.ksnd_peers[i]) {
                                peer = list_entry(tmp, ksock_peer_t,
                                                      ksnp_list);
 
@@ -1913,7 +1913,7 @@ ksocknal_push (lnet_ni_t *ni, lnet_process_id_t id)
 
                        if (peer != NULL) {
                                rc = 0;
-                               ksocknal_push_peer (peer);
+                               ksocknal_push_peer(peer);
                                ksocknal_peer_decref(peer);
                        }
                }
@@ -2005,7 +2005,7 @@ ksocknal_peer_del_interface_locked(ksock_peer_t *peer, __u32 ipaddr)
                }
 
        list_for_each_safe(tmp, nxt, &peer->ksnp_routes) {
-               route = list_entry (tmp, ksock_route_t, ksnr_list);
+               route = list_entry(tmp, ksock_route_t, ksnr_list);
 
                if (route->ksnr_myipaddr != ipaddr)
                        continue;
@@ -2022,7 +2022,7 @@ ksocknal_peer_del_interface_locked(ksock_peer_t *peer, __u32 ipaddr)
                conn = list_entry(tmp, ksock_conn_t, ksnc_list);
 
                if (conn->ksnc_myipaddr == ipaddr)
-                       ksocknal_close_conn_locked (conn, 0);
+                       ksocknal_close_conn_locked(conn, 0);
        }
 }
 
@@ -2139,21 +2139,21 @@ ksocknal_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg)
        case IOC_LIBCFS_ADD_PEER:
                id.nid = data->ioc_nid;
                id.pid = LUSTRE_SRV_LNET_PID;
-               return ksocknal_add_peer (ni, id,
+               return ksocknal_add_peer(ni, id,
                                          data->ioc_u32[0], /* IP */
                                          data->ioc_u32[1]); /* port */
 
        case IOC_LIBCFS_DEL_PEER:
                id.nid = data->ioc_nid;
                id.pid = LNET_PID_ANY;
-               return ksocknal_del_peer (ni, id,
+               return ksocknal_del_peer(ni, id,
                                          data->ioc_u32[0]); /* IP */
 
        case IOC_LIBCFS_GET_CONN: {
                int        txmem;
                int        rxmem;
                int        nagle;
-               ksock_conn_t *conn = ksocknal_get_conn_by_idx (ni, data->ioc_count);
+               ksock_conn_t *conn = ksocknal_get_conn_by_idx(ni, data->ioc_count);
 
                if (conn == NULL)
                        return -ENOENT;
@@ -2177,7 +2177,7 @@ ksocknal_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg)
        case IOC_LIBCFS_CLOSE_CONNECTION:
                id.nid = data->ioc_nid;
                id.pid = LNET_PID_ANY;
-               return ksocknal_close_matching_conns (id,
+               return ksocknal_close_matching_conns(id,
                                                      data->ioc_u32[0]);
 
        case IOC_LIBCFS_REGISTER_MYNID:
@@ -2202,9 +2202,9 @@ ksocknal_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg)
 }
 
 static void
-ksocknal_free_buffers (void)
+ksocknal_free_buffers(void)
 {
-       LASSERT (atomic_read(&ksocknal_data.ksnd_nactive_txs) == 0);
+       LASSERT(atomic_read(&ksocknal_data.ksnd_nactive_txs) == 0);
 
        if (ksocknal_data.ksnd_sched_info != NULL) {
                struct ksock_sched_info *info;
@@ -2220,8 +2220,8 @@ ksocknal_free_buffers (void)
                cfs_percpt_free(ksocknal_data.ksnd_sched_info);
        }
 
-       LIBCFS_FREE (ksocknal_data.ksnd_peers,
-                    sizeof (struct list_head) *
+       LIBCFS_FREE(ksocknal_data.ksnd_peers,
+                    sizeof(struct list_head) *
                     ksocknal_data.ksnd_peer_hash_size);
 
        spin_lock(&ksocknal_data.ksnd_tx_lock);
@@ -2253,25 +2253,25 @@ ksocknal_base_shutdown(void)
        int                     j;
 
        CDEBUG(D_MALLOC, "before NAL cleanup: kmem %d\n",
-              atomic_read (&libcfs_kmemory));
-       LASSERT (ksocknal_data.ksnd_nnets == 0);
+              atomic_read(&libcfs_kmemory));
+       LASSERT(ksocknal_data.ksnd_nnets == 0);
 
        switch (ksocknal_data.ksnd_init) {
        default:
-               LASSERT (0);
+               LASSERT(0);
 
        case SOCKNAL_INIT_ALL:
        case SOCKNAL_INIT_DATA:
-               LASSERT (ksocknal_data.ksnd_peers != NULL);
+               LASSERT(ksocknal_data.ksnd_peers != NULL);
                for (i = 0; i < ksocknal_data.ksnd_peer_hash_size; i++) {
-                       LASSERT (list_empty (&ksocknal_data.ksnd_peers[i]));
+                       LASSERT(list_empty(&ksocknal_data.ksnd_peers[i]));
                }
 
                LASSERT(list_empty(&ksocknal_data.ksnd_nets));
-               LASSERT (list_empty (&ksocknal_data.ksnd_enomem_conns));
-               LASSERT (list_empty (&ksocknal_data.ksnd_zombie_conns));
-               LASSERT (list_empty (&ksocknal_data.ksnd_connd_connreqs));
-               LASSERT (list_empty (&ksocknal_data.ksnd_connd_routes));
+               LASSERT(list_empty(&ksocknal_data.ksnd_enomem_conns));
+               LASSERT(list_empty(&ksocknal_data.ksnd_zombie_conns));
+               LASSERT(list_empty(&ksocknal_data.ksnd_connd_connreqs));
+               LASSERT(list_empty(&ksocknal_data.ksnd_connd_routes));
 
                if (ksocknal_data.ksnd_sched_info != NULL) {
                        cfs_percpt_for_each(info, i,
@@ -2332,13 +2332,13 @@ ksocknal_base_shutdown(void)
        }
 
        CDEBUG(D_MALLOC, "after NAL cleanup: kmem %d\n",
-              atomic_read (&libcfs_kmemory));
+              atomic_read(&libcfs_kmemory));
 
        module_put(THIS_MODULE);
 }
 
 static __u64
-ksocknal_new_incarnation (void)
+ksocknal_new_incarnation(void)
 {
 
        /* The incarnation number is the time this module loaded and it
@@ -2354,14 +2354,14 @@ ksocknal_base_startup(void)
        int                     rc;
        int                     i;
 
-       LASSERT (ksocknal_data.ksnd_init == SOCKNAL_INIT_NOTHING);
-       LASSERT (ksocknal_data.ksnd_nnets == 0);
+       LASSERT(ksocknal_data.ksnd_init == SOCKNAL_INIT_NOTHING);
+       LASSERT(ksocknal_data.ksnd_nnets == 0);
 
-       memset (&ksocknal_data, 0, sizeof (ksocknal_data)); /* zero pointers */
+       memset(&ksocknal_data, 0, sizeof(ksocknal_data)); /* zero pointers */
 
        ksocknal_data.ksnd_peer_hash_size = SOCKNAL_PEER_HASH_SIZE;
-       LIBCFS_ALLOC (ksocknal_data.ksnd_peers,
-                     sizeof (struct list_head) *
+       LIBCFS_ALLOC(ksocknal_data.ksnd_peers,
+                     sizeof(struct list_head) *
                      ksocknal_data.ksnd_peer_hash_size);
        if (ksocknal_data.ksnd_peers == NULL)
                return -ENOMEM;
@@ -2373,18 +2373,18 @@ ksocknal_base_startup(void)
        INIT_LIST_HEAD(&ksocknal_data.ksnd_nets);
 
        spin_lock_init(&ksocknal_data.ksnd_reaper_lock);
-       INIT_LIST_HEAD (&ksocknal_data.ksnd_enomem_conns);
-       INIT_LIST_HEAD (&ksocknal_data.ksnd_zombie_conns);
-       INIT_LIST_HEAD (&ksocknal_data.ksnd_deathrow_conns);
+       INIT_LIST_HEAD(&ksocknal_data.ksnd_enomem_conns);
+       INIT_LIST_HEAD(&ksocknal_data.ksnd_zombie_conns);
+       INIT_LIST_HEAD(&ksocknal_data.ksnd_deathrow_conns);
        init_waitqueue_head(&ksocknal_data.ksnd_reaper_waitq);
 
        spin_lock_init(&ksocknal_data.ksnd_connd_lock);
-       INIT_LIST_HEAD (&ksocknal_data.ksnd_connd_connreqs);
-       INIT_LIST_HEAD (&ksocknal_data.ksnd_connd_routes);
+       INIT_LIST_HEAD(&ksocknal_data.ksnd_connd_connreqs);
+       INIT_LIST_HEAD(&ksocknal_data.ksnd_connd_routes);
        init_waitqueue_head(&ksocknal_data.ksnd_connd_waitq);
 
        spin_lock_init(&ksocknal_data.ksnd_tx_lock);
-       INIT_LIST_HEAD (&ksocknal_data.ksnd_idle_noop_txs);
+       INIT_LIST_HEAD(&ksocknal_data.ksnd_idle_noop_txs);
 
        /* NB memset above zeros whole of ksocknal_data */
 
@@ -2465,7 +2465,7 @@ ksocknal_base_startup(void)
 
        rc = ksocknal_thread_start(ksocknal_reaper, NULL, "socknal_reaper");
        if (rc != 0) {
-               CERROR ("Can't spawn socknal reaper: %d\n", rc);
+               CERROR("Can't spawn socknal reaper: %d\n", rc);
                goto failed;
        }
 
@@ -2480,7 +2480,7 @@ ksocknal_base_startup(void)
 }
 
 static void
-ksocknal_debug_peerhash (lnet_ni_t *ni)
+ksocknal_debug_peerhash(lnet_ni_t *ni)
 {
        ksock_peer_t    *peer = NULL;
        struct list_head        *tmp;
@@ -2489,8 +2489,8 @@ ksocknal_debug_peerhash (lnet_ni_t *ni)
        read_lock(&ksocknal_data.ksnd_global_lock);
 
        for (i = 0; i < ksocknal_data.ksnd_peer_hash_size; i++) {
-               list_for_each (tmp, &ksocknal_data.ksnd_peers[i]) {
-                       peer = list_entry (tmp, ksock_peer_t, ksnp_list);
+               list_for_each(tmp, &ksocknal_data.ksnd_peers[i]) {
+                       peer = list_entry(tmp, ksock_peer_t, ksnp_list);
 
                        if (peer->ksnp_ni == ni)
                                break;
@@ -2512,7 +2512,7 @@ ksocknal_debug_peerhash (lnet_ni_t *ni)
                      !list_empty(&peer->ksnp_tx_queue),
                      !list_empty(&peer->ksnp_zc_req_list));
 
-               list_for_each (tmp, &peer->ksnp_routes) {
+               list_for_each(tmp, &peer->ksnp_routes) {
                        route = list_entry(tmp, ksock_route_t, ksnr_list);
                        CWARN("Route: ref %d, schd %d, conn %d, cnted %d, del %d\n",
                              atomic_read(&route->ksnr_refcount),
@@ -2520,9 +2520,9 @@ ksocknal_debug_peerhash (lnet_ni_t *ni)
                              route->ksnr_connected, route->ksnr_deleted);
                }
 
-               list_for_each (tmp, &peer->ksnp_conns) {
+               list_for_each(tmp, &peer->ksnp_conns) {
                        conn = list_entry(tmp, ksock_conn_t, ksnc_list);
-                       CWARN ("Conn: ref %d, sref %d, t %d, c %d\n",
+                       CWARN("Conn: ref %d, sref %d, t %d, c %d\n",
                               atomic_read(&conn->ksnc_conn_refcount),
                               atomic_read(&conn->ksnc_sock_refcount),
                               conn->ksnc_type, conn->ksnc_closing);
@@ -2534,7 +2534,7 @@ ksocknal_debug_peerhash (lnet_ni_t *ni)
 }
 
 void
-ksocknal_shutdown (lnet_ni_t *ni)
+ksocknal_shutdown(lnet_ni_t *ni)
 {
        ksock_net_t      *net = ni->ni_data;
        int            i;
@@ -2573,8 +2573,8 @@ ksocknal_shutdown (lnet_ni_t *ni)
        spin_unlock_bh(&net->ksnn_lock);
 
        for (i = 0; i < net->ksnn_ninterfaces; i++) {
-               LASSERT (net->ksnn_interfaces[i].ksni_npeers == 0);
-               LASSERT (net->ksnn_interfaces[i].ksni_nroutes == 0);
+               LASSERT(net->ksnn_interfaces[i].ksni_npeers == 0);
+               LASSERT(net->ksnn_interfaces[i].ksni_nroutes == 0);
        }
 
        list_del(&net->ksnn_list);
@@ -2757,13 +2757,13 @@ ksocknal_net_start_threads(ksock_net_t *net, __u32 *cpts, int ncpts)
 }
 
 int
-ksocknal_startup (lnet_ni_t *ni)
+ksocknal_startup(lnet_ni_t *ni)
 {
        ksock_net_t  *net;
        int        rc;
        int        i;
 
-       LASSERT (ni->ni_lnd == &the_ksocklnd);
+       LASSERT(ni->ni_lnd == &the_ksocklnd);
 
        if (ksocknal_data.ksnd_init == SOCKNAL_INIT_NOTHING) {
                rc = ksocknal_base_startup();
@@ -2843,19 +2843,19 @@ ksocknal_startup (lnet_ni_t *ni)
 
 
 static void __exit
-ksocknal_module_fini (void)
+ksocknal_module_fini(void)
 {
        lnet_unregister_lnd(&the_ksocklnd);
 }
 
 static int __init
-ksocknal_module_init (void)
+ksocknal_module_init(void)
 {
        int    rc;
 
        /* check ksnr_connected/connecting field large enough */
-       CLASSERT (SOCKLND_CONN_NTYPES <= 4);
-       CLASSERT (SOCKLND_CONN_ACK == SOCKLND_CONN_BULK_IN);
+       CLASSERT(SOCKLND_CONN_NTYPES <= 4);
+       CLASSERT(SOCKLND_CONN_ACK == SOCKLND_CONN_BULK_IN);
 
        /* initialize the_ksocklnd */
        the_ksocklnd.lnd_type     = SOCKLND;
index 03488d289c74be6425a8fa955c2fb6012fbdacb3..c54c9955164eda319d9ac277cf9c6d04949790a5 100644 (file)
@@ -406,7 +406,7 @@ ksocknal_route_mask(void)
 }
 
 static inline struct list_head *
-ksocknal_nid2peerlist (lnet_nid_t nid)
+ksocknal_nid2peerlist(lnet_nid_t nid)
 {
        unsigned int hash = ((unsigned int)nid) % ksocknal_data.ksnd_peer_hash_size;
 
@@ -414,25 +414,25 @@ ksocknal_nid2peerlist (lnet_nid_t nid)
 }
 
 static inline void
-ksocknal_conn_addref (ksock_conn_t *conn)
+ksocknal_conn_addref(ksock_conn_t *conn)
 {
-       LASSERT (atomic_read(&conn->ksnc_conn_refcount) > 0);
+       LASSERT(atomic_read(&conn->ksnc_conn_refcount) > 0);
        atomic_inc(&conn->ksnc_conn_refcount);
 }
 
-extern void ksocknal_queue_zombie_conn (ksock_conn_t *conn);
+extern void ksocknal_queue_zombie_conn(ksock_conn_t *conn);
 extern void ksocknal_finalize_zcreq(ksock_conn_t *conn);
 
 static inline void
-ksocknal_conn_decref (ksock_conn_t *conn)
+ksocknal_conn_decref(ksock_conn_t *conn)
 {
-       LASSERT (atomic_read(&conn->ksnc_conn_refcount) > 0);
+       LASSERT(atomic_read(&conn->ksnc_conn_refcount) > 0);
        if (atomic_dec_and_test(&conn->ksnc_conn_refcount))
                ksocknal_queue_zombie_conn(conn);
 }
 
 static inline int
-ksocknal_connsock_addref (ksock_conn_t *conn)
+ksocknal_connsock_addref(ksock_conn_t *conn)
 {
        int   rc = -ESHUTDOWN;
 
@@ -448,11 +448,11 @@ ksocknal_connsock_addref (ksock_conn_t *conn)
 }
 
 static inline void
-ksocknal_connsock_decref (ksock_conn_t *conn)
+ksocknal_connsock_decref(ksock_conn_t *conn)
 {
-       LASSERT (atomic_read(&conn->ksnc_sock_refcount) > 0);
+       LASSERT(atomic_read(&conn->ksnc_sock_refcount) > 0);
        if (atomic_dec_and_test(&conn->ksnc_sock_refcount)) {
-               LASSERT (conn->ksnc_closing);
+               LASSERT(conn->ksnc_closing);
                libcfs_sock_release(conn->ksnc_sock);
                conn->ksnc_sock = NULL;
                ksocknal_finalize_zcreq(conn);
@@ -460,61 +460,61 @@ ksocknal_connsock_decref (ksock_conn_t *conn)
 }
 
 static inline void
-ksocknal_tx_addref (ksock_tx_t *tx)
+ksocknal_tx_addref(ksock_tx_t *tx)
 {
-       LASSERT (atomic_read(&tx->tx_refcount) > 0);
+       LASSERT(atomic_read(&tx->tx_refcount) > 0);
        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);
+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);
 
 static inline void
-ksocknal_tx_decref (ksock_tx_t *tx)
+ksocknal_tx_decref(ksock_tx_t *tx)
 {
-       LASSERT (atomic_read(&tx->tx_refcount) > 0);
+       LASSERT(atomic_read(&tx->tx_refcount) > 0);
        if (atomic_dec_and_test(&tx->tx_refcount))
                ksocknal_tx_done(NULL, tx);
 }
 
 static inline void
-ksocknal_route_addref (ksock_route_t *route)
+ksocknal_route_addref(ksock_route_t *route)
 {
-       LASSERT (atomic_read(&route->ksnr_refcount) > 0);
+       LASSERT(atomic_read(&route->ksnr_refcount) > 0);
        atomic_inc(&route->ksnr_refcount);
 }
 
-extern void ksocknal_destroy_route (ksock_route_t *route);
+extern void ksocknal_destroy_route(ksock_route_t *route);
 
 static inline void
-ksocknal_route_decref (ksock_route_t *route)
+ksocknal_route_decref(ksock_route_t *route)
 {
-       LASSERT (atomic_read (&route->ksnr_refcount) > 0);
+       LASSERT(atomic_read(&route->ksnr_refcount) > 0);
        if (atomic_dec_and_test(&route->ksnr_refcount))
-               ksocknal_destroy_route (route);
+               ksocknal_destroy_route(route);
 }
 
 static inline void
-ksocknal_peer_addref (ksock_peer_t *peer)
+ksocknal_peer_addref(ksock_peer_t *peer)
 {
-       LASSERT (atomic_read (&peer->ksnp_refcount) > 0);
+       LASSERT(atomic_read(&peer->ksnp_refcount) > 0);
        atomic_inc(&peer->ksnp_refcount);
 }
 
-extern void ksocknal_destroy_peer (ksock_peer_t *peer);
+extern void ksocknal_destroy_peer(ksock_peer_t *peer);
 
 static inline void
-ksocknal_peer_decref (ksock_peer_t *peer)
+ksocknal_peer_decref(ksock_peer_t *peer)
 {
-       LASSERT (atomic_read (&peer->ksnp_refcount) > 0);
+       LASSERT(atomic_read(&peer->ksnp_refcount) > 0);
        if (atomic_dec_and_test(&peer->ksnp_refcount))
-               ksocknal_destroy_peer (peer);
+               ksocknal_destroy_peer(peer);
 }
 
-int ksocknal_startup (lnet_ni_t *ni);
-void ksocknal_shutdown (lnet_ni_t *ni);
+int ksocknal_startup(lnet_ni_t *ni);
+void ksocknal_shutdown(lnet_ni_t *ni);
 int ksocknal_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg);
-int ksocknal_send (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg);
+int ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg);
 int ksocknal_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg,
                  int delayed, unsigned int niov,
                  struct kvec *iov, lnet_kiov_t *kiov,
@@ -522,44 +522,44 @@ int ksocknal_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg,
 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,
+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,
+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 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 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,
+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 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,
+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,
+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);
@@ -569,15 +569,15 @@ 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,
+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);
index 92760fe94184cf7ee2455ac64364d155cbc3944e..fa7ad883bda9332509d433b3a7524fd15b2d6813 100644 (file)
@@ -1374,9 +1374,9 @@ ksocknal_sched_cansleep(ksock_sched_t *sched)
 
        spin_lock_bh(&sched->kss_lock);
 
-       rc = (!ksocknal_data.ksnd_shuttingdown &&
+       rc = !ksocknal_data.ksnd_shuttingdown &&
              list_empty(&sched->kss_rx_conns) &&
-             list_empty(&sched->kss_tx_conns));
+             list_empty(&sched->kss_tx_conns);
 
        spin_unlock_bh(&sched->kss_lock);
        return rc;
index 66cc509295e5f81339bc424d36a3b36267ab0587..f5e8ab06070c1ab45864f7855f5783225aecd730 100644 (file)
 #include "socklnd.h"
 
 int
-ksocknal_lib_get_conn_addrs (ksock_conn_t *conn)
+ksocknal_lib_get_conn_addrs(ksock_conn_t *conn)
 {
        int rc = libcfs_sock_getaddr(conn->ksnc_sock, 1,
                                     &conn->ksnc_ipaddr,
                                     &conn->ksnc_port);
 
        /* Didn't need the {get,put}connsock dance to deref ksnc_sock... */
-       LASSERT (!conn->ksnc_closing);
+       LASSERT(!conn->ksnc_closing);
 
        if (rc != 0) {
-               CERROR ("Error %d getting sock peer IP\n", rc);
+               CERROR("Error %d getting sock peer IP\n", rc);
                return rc;
        }
 
        rc = libcfs_sock_getaddr(conn->ksnc_sock, 0,
                                 &conn->ksnc_myipaddr, NULL);
        if (rc != 0) {
-               CERROR ("Error %d getting sock local IP\n", rc);
+               CERROR("Error %d getting sock local IP\n", rc);
                return rc;
        }
 
@@ -75,7 +75,7 @@ ksocknal_lib_zc_capable(ksock_conn_t *conn)
 }
 
 int
-ksocknal_lib_send_iov (ksock_conn_t *conn, ksock_tx_t *tx)
+ksocknal_lib_send_iov(ksock_conn_t *conn, ksock_tx_t *tx)
 {
        struct socket *sock = conn->ksnc_sock;
        int         nob;
@@ -117,7 +117,7 @@ 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)
+ksocknal_lib_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx)
 {
        struct socket *sock = conn->ksnc_sock;
        lnet_kiov_t   *kiov = tx->tx_kiov;
@@ -125,7 +125,7 @@ ksocknal_lib_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx)
        int         nob;
 
        /* Not NOOP message */
-       LASSERT (tx->tx_lnetmsg != NULL);
+       LASSERT(tx->tx_lnetmsg != NULL);
 
        /* NB we can't trust socket ops to either consume our iovs
         * or leave them alone. */
@@ -185,7 +185,7 @@ ksocknal_lib_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx)
 }
 
 void
-ksocknal_lib_eager_ack (ksock_conn_t *conn)
+ksocknal_lib_eager_ack(ksock_conn_t *conn)
 {
        int         opt = 1;
        struct socket *sock = conn->ksnc_sock;
@@ -196,11 +196,11 @@ ksocknal_lib_eager_ack (ksock_conn_t *conn)
         * peer. */
 
        kernel_setsockopt(sock, SOL_TCP, TCP_QUICKACK,
-                              (char *)&opt, sizeof (opt));
+                              (char *)&opt, sizeof(opt));
 }
 
 int
-ksocknal_lib_recv_iov (ksock_conn_t *conn)
+ksocknal_lib_recv_iov(ksock_conn_t *conn)
 {
 #if SOCKNAL_SINGLE_FRAG_RX
        struct kvec  scratch;
@@ -223,13 +223,13 @@ ksocknal_lib_recv_iov (ksock_conn_t *conn)
 
        /* NB we can't trust socket ops to either consume our iovs
         * or leave them alone. */
-       LASSERT (niov > 0);
+       LASSERT(niov > 0);
 
        for (nob = i = 0; i < niov; i++) {
                scratchiov[i] = iov[i];
                nob += scratchiov[i].iov_len;
        }
-       LASSERT (nob <= conn->ksnc_rx_nob_wanted);
+       LASSERT(nob <= conn->ksnc_rx_nob_wanted);
 
        rc = kernel_recvmsg(conn->ksnc_sock, &msg,
                scratchiov, niov, nob, MSG_DONTWAIT);
@@ -243,7 +243,7 @@ ksocknal_lib_recv_iov (ksock_conn_t *conn)
        if (saved_csum != 0) {
                /* accumulate checksum */
                for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) {
-                       LASSERT (i < niov);
+                       LASSERT(i < niov);
 
                        fragnob = iov[i].iov_len;
                        if (fragnob > sum)
@@ -278,7 +278,7 @@ ksocknal_lib_kiov_vmap(lnet_kiov_t *kiov, int niov,
        if (!*ksocknal_tunables.ksnd_zc_recv || pages == NULL)
                return NULL;
 
-       LASSERT (niov <= LNET_MAX_IOV);
+       LASSERT(niov <= LNET_MAX_IOV);
 
        if (niov < 2 ||
            niov < *ksocknal_tunables.ksnd_zc_recv_min_nfrags)
@@ -304,7 +304,7 @@ ksocknal_lib_kiov_vmap(lnet_kiov_t *kiov, int niov,
 }
 
 int
-ksocknal_lib_recv_kiov (ksock_conn_t *conn)
+ksocknal_lib_recv_kiov(ksock_conn_t *conn)
 {
 #if SOCKNAL_SINGLE_FRAG_RX || !SOCKNAL_RISK_KMAP_DEADLOCK
        struct kvec   scratch;
@@ -348,14 +348,14 @@ ksocknal_lib_recv_kiov (ksock_conn_t *conn)
                n = niov;
        }
 
-       LASSERT (nob <= conn->ksnc_rx_nob_wanted);
+       LASSERT(nob <= conn->ksnc_rx_nob_wanted);
 
        rc = kernel_recvmsg(conn->ksnc_sock, &msg,
                        (struct kvec *)scratchiov, n, nob, MSG_DONTWAIT);
 
        if (conn->ksnc_msg.ksm_csum != 0) {
                for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) {
-                       LASSERT (i < niov);
+                       LASSERT(i < niov);
 
                        /* Dang! have to kmap again because I have nowhere to stash the
                         * mapped address.  But by doing it while the page is still
@@ -423,7 +423,7 @@ ksocknal_lib_csum_tx(ksock_tx_t *tx)
 }
 
 int
-ksocknal_lib_get_conn_tunables (ksock_conn_t *conn, int *txmem, int *rxmem, int *nagle)
+ksocknal_lib_get_conn_tunables(ksock_conn_t *conn, int *txmem, int *rxmem, int *nagle)
 {
        struct socket *sock = conn->ksnc_sock;
        int         len;
@@ -431,7 +431,7 @@ ksocknal_lib_get_conn_tunables (ksock_conn_t *conn, int *txmem, int *rxmem, int
 
        rc = ksocknal_connsock_addref(conn);
        if (rc != 0) {
-               LASSERT (conn->ksnc_closing);
+               LASSERT(conn->ksnc_closing);
                *txmem = *rxmem = *nagle = 0;
                return -ESHUTDOWN;
        }
@@ -454,7 +454,7 @@ ksocknal_lib_get_conn_tunables (ksock_conn_t *conn, int *txmem, int *rxmem, int
 }
 
 int
-ksocknal_lib_setup_sock (struct socket *sock)
+ksocknal_lib_setup_sock(struct socket *sock)
 {
        int          rc;
        int          option;
@@ -473,17 +473,17 @@ ksocknal_lib_setup_sock (struct socket *sock)
        linger.l_linger = 0;
 
        rc = kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER,
-                             (char *)&linger, sizeof (linger));
+                             (char *)&linger, sizeof(linger));
        if (rc != 0) {
-               CERROR ("Can't set SO_LINGER: %d\n", rc);
+               CERROR("Can't set SO_LINGER: %d\n", rc);
                return rc;
        }
 
        option = -1;
        rc = kernel_setsockopt(sock, SOL_TCP, TCP_LINGER2,
-                                   (char *)&option, sizeof (option));
+                                   (char *)&option, sizeof(option));
        if (rc != 0) {
-               CERROR ("Can't set SO_LINGER2: %d\n", rc);
+               CERROR("Can't set SO_LINGER2: %d\n", rc);
                return rc;
        }
 
@@ -491,9 +491,9 @@ ksocknal_lib_setup_sock (struct socket *sock)
                option = 1;
 
                rc = kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
-                                           (char *)&option, sizeof (option));
+                                           (char *)&option, sizeof(option));
                if (rc != 0) {
-                       CERROR ("Can't disable nagle: %d\n", rc);
+                       CERROR("Can't disable nagle: %d\n", rc);
                        return rc;
                }
        }
@@ -502,7 +502,7 @@ ksocknal_lib_setup_sock (struct socket *sock)
                                *ksocknal_tunables.ksnd_tx_buffer_size,
                                *ksocknal_tunables.ksnd_rx_buffer_size);
        if (rc != 0) {
-               CERROR ("Can't set buffer tx %d, rx %d buffers: %d\n",
+               CERROR("Can't set buffer tx %d, rx %d buffers: %d\n",
                        *ksocknal_tunables.ksnd_tx_buffer_size,
                        *ksocknal_tunables.ksnd_rx_buffer_size, rc);
                return rc;
@@ -519,9 +519,9 @@ ksocknal_lib_setup_sock (struct socket *sock)
 
        option = (do_keepalive ? 1 : 0);
        rc = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
-                             (char *)&option, sizeof (option));
+                             (char *)&option, sizeof(option));
        if (rc != 0) {
-               CERROR ("Can't set SO_KEEPALIVE: %d\n", rc);
+               CERROR("Can't set SO_KEEPALIVE: %d\n", rc);
                return rc;
        }
 
@@ -529,23 +529,23 @@ ksocknal_lib_setup_sock (struct socket *sock)
                return 0;
 
        rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE,
-                                   (char *)&keep_idle, sizeof (keep_idle));
+                                   (char *)&keep_idle, sizeof(keep_idle));
        if (rc != 0) {
-               CERROR ("Can't set TCP_KEEPIDLE: %d\n", rc);
+               CERROR("Can't set TCP_KEEPIDLE: %d\n", rc);
                return rc;
        }
 
        rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,
-                                   (char *)&keep_intvl, sizeof (keep_intvl));
+                                   (char *)&keep_intvl, sizeof(keep_intvl));
        if (rc != 0) {
-               CERROR ("Can't set TCP_KEEPINTVL: %d\n", rc);
+               CERROR("Can't set TCP_KEEPINTVL: %d\n", rc);
                return rc;
        }
 
        rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
-                                   (char *)&keep_count, sizeof (keep_count));
+                                   (char *)&keep_count, sizeof(keep_count));
        if (rc != 0) {
-               CERROR ("Can't set TCP_KEEPCNT: %d\n", rc);
+               CERROR("Can't set TCP_KEEPCNT: %d\n", rc);
                return rc;
        }
 
@@ -553,7 +553,7 @@ ksocknal_lib_setup_sock (struct socket *sock)
 }
 
 void
-ksocknal_lib_push_conn (ksock_conn_t *conn)
+ksocknal_lib_push_conn(ksock_conn_t *conn)
 {
        struct sock    *sk;
        struct tcp_sock *tp;
@@ -568,29 +568,29 @@ ksocknal_lib_push_conn (ksock_conn_t *conn)
        sk = conn->ksnc_sock->sk;
        tp = tcp_sk(sk);
 
-       lock_sock (sk);
+       lock_sock(sk);
        nonagle = tp->nonagle;
        tp->nonagle = 1;
-       release_sock (sk);
+       release_sock(sk);
 
        rc = kernel_setsockopt(conn->ksnc_sock, SOL_TCP, TCP_NODELAY,
-                                     (char *)&val, sizeof (val));
-       LASSERT (rc == 0);
+                                     (char *)&val, sizeof(val));
+       LASSERT(rc == 0);
 
-       lock_sock (sk);
+       lock_sock(sk);
        tp->nonagle = nonagle;
-       release_sock (sk);
+       release_sock(sk);
 
        ksocknal_connsock_decref(conn);
 }
 
-extern void ksocknal_read_callback (ksock_conn_t *conn);
-extern void ksocknal_write_callback (ksock_conn_t *conn);
+extern void ksocknal_read_callback(ksock_conn_t *conn);
+extern void ksocknal_write_callback(ksock_conn_t *conn);
 /*
  * socket call back in Linux
  */
 static void
-ksocknal_data_ready (struct sock *sk)
+ksocknal_data_ready(struct sock *sk)
 {
        ksock_conn_t  *conn;
 
@@ -600,8 +600,8 @@ ksocknal_data_ready (struct sock *sk)
 
        conn = sk->sk_user_data;
        if (conn == NULL) {          /* raced with ksocknal_terminate_conn */
-               LASSERT (sk->sk_data_ready != &ksocknal_data_ready);
-               sk->sk_data_ready (sk);
+               LASSERT(sk->sk_data_ready != &ksocknal_data_ready);
+               sk->sk_data_ready(sk);
        } else
                ksocknal_read_callback(conn);
 
@@ -609,7 +609,7 @@ ksocknal_data_ready (struct sock *sk)
 }
 
 static void
-ksocknal_write_space (struct sock *sk)
+ksocknal_write_space(struct sock *sk)
 {
        ksock_conn_t  *conn;
        int         wspace;
@@ -629,12 +629,12 @@ ksocknal_write_space (struct sock *sk)
                                      " ready" : " blocked"),
               (conn == NULL) ? "" : (conn->ksnc_tx_scheduled ?
                                      " scheduled" : " idle"),
-              (conn == NULL) ? "" : (list_empty (&conn->ksnc_tx_queue) ?
+              (conn == NULL) ? "" : (list_empty(&conn->ksnc_tx_queue) ?
                                      " empty" : " queued"));
 
        if (conn == NULL) {          /* raced with ksocknal_terminate_conn */
-               LASSERT (sk->sk_write_space != &ksocknal_write_space);
-               sk->sk_write_space (sk);
+               LASSERT(sk->sk_write_space != &ksocknal_write_space);
+               sk->sk_write_space(sk);
 
                read_unlock(&ksocknal_data.ksnd_global_lock);
                return;
@@ -647,7 +647,7 @@ ksocknal_write_space (struct sock *sk)
                 * ENOMEM check in ksocknal_transmit is race-free (think about
                 * it). */
 
-               clear_bit (SOCK_NOSPACE, &sk->sk_socket->flags);
+               clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
        }
 
        read_unlock(&ksocknal_data.ksnd_global_lock);
index 7a793d2d3582b14bdac5e73e65ab6c020d522e2c..f5563881b25c0cceba0f68a608841a3d1de40220 100644 (file)
@@ -50,8 +50,8 @@
 #include <net/tcp.h>
 #include <linux/uio.h>
 #include <linux/if.h>
+#include <linux/uaccess.h>
 
-#include <asm/uaccess.h>
 #include <asm/irq.h>
 
 #include <linux/fs.h>
index 66d78c9be650a8e4606d5d085806f18b5f21e235..86b88db1cf2086c6842c45725018e4132385ade1 100644 (file)
@@ -72,7 +72,7 @@ static int typed_conns = 1;
 module_param(typed_conns, int, 0444);
 MODULE_PARM_DESC(typed_conns, "use different sockets for bulk");
 
-static int min_bulk = (1<<10);
+static int min_bulk = 1<<10;
 module_param(min_bulk, int, 0644);
 MODULE_PARM_DESC(min_bulk, "smallest 'large' message");
 
@@ -122,7 +122,7 @@ static int nonblk_zcack = 1;
 module_param(nonblk_zcack, int, 0644);
 MODULE_PARM_DESC(nonblk_zcack, "always send ZC-ACK on non-blocking connection");
 
-static unsigned int zc_min_payload = (16 << 10);
+static unsigned int zc_min_payload = 16 << 10;
 module_param(zc_min_payload, int, 0644);
 MODULE_PARM_DESC(zc_min_payload, "minimum payload size to zero copy");
 
@@ -182,7 +182,7 @@ int ksocknal_tunables_init(void)
 #endif
 
        if (*ksocknal_tunables.ksnd_zc_min_payload < (2 << 10))
-               *ksocknal_tunables.ksnd_zc_min_payload = (2 << 10);
+               *ksocknal_tunables.ksnd_zc_min_payload = 2 << 10;
 
        return 0;
 };
index b2f88eb47bbad8171c76551f2ce9e14542f42620..8596581f54ff6056c334347b80fe29af20c2be33 100644 (file)
@@ -55,8 +55,8 @@ ksocknal_next_tx_carrier(ksock_conn_t *conn)
        ksock_tx_t     *tx = conn->ksnc_tx_carrier;
 
        /* Called holding BH lock: conn->ksnc_scheduler->kss_lock */
-       LASSERT (!list_empty(&conn->ksnc_tx_queue));
-       LASSERT (tx != NULL);
+       LASSERT(!list_empty(&conn->ksnc_tx_queue));
+       LASSERT(tx != NULL);
 
        /* Next TX that can carry ZC-ACK or LNet message */
        if (tx->tx_list.next == &conn->ksnc_tx_queue) {
@@ -65,7 +65,7 @@ ksocknal_next_tx_carrier(ksock_conn_t *conn)
        } else {
                conn->ksnc_tx_carrier = list_entry(tx->tx_list.next,
                                                       ksock_tx_t, tx_list);
-               LASSERT (conn->ksnc_tx_carrier->tx_msg.ksm_type == tx->tx_msg.ksm_type);
+               LASSERT(conn->ksnc_tx_carrier->tx_msg.ksm_type == tx->tx_msg.ksm_type);
        }
 }
 
@@ -75,7 +75,7 @@ ksocknal_queue_tx_zcack_v2(ksock_conn_t *conn,
 {
        ksock_tx_t *tx = conn->ksnc_tx_carrier;
 
-       LASSERT (tx_ack == NULL ||
+       LASSERT(tx_ack == NULL ||
                 tx_ack->tx_msg.ksm_type == KSOCK_MSG_NOOP);
 
        /*
@@ -139,7 +139,7 @@ ksocknal_queue_tx_msg_v2(ksock_conn_t *conn, ksock_tx_t *tx_msg)
                return NULL;
        }
 
-       LASSERT (tx->tx_msg.ksm_type == KSOCK_MSG_NOOP);
+       LASSERT(tx->tx_msg.ksm_type == KSOCK_MSG_NOOP);
 
        /* There is a noop zc-ack can be piggybacked */
        tx_msg->tx_msg.ksm_zc_cookies[1] = tx->tx_msg.ksm_zc_cookies[1];
@@ -162,7 +162,7 @@ ksocknal_queue_tx_zcack_v3(ksock_conn_t *conn,
                return ksocknal_queue_tx_zcack_v2(conn, tx_ack, cookie);
 
        /* non-blocking ZC-ACK (to router) */
-       LASSERT (tx_ack == NULL ||
+       LASSERT(tx_ack == NULL ||
                 tx_ack->tx_msg.ksm_type == KSOCK_MSG_NOOP);
 
        tx = conn->ksnc_tx_carrier;
@@ -185,7 +185,7 @@ ksocknal_queue_tx_zcack_v3(ksock_conn_t *conn,
 
        if (tx->tx_msg.ksm_zc_cookies[1] == SOCKNAL_KEEPALIVE_PING) {
                /* replace the keepalive PING with a real ACK */
-               LASSERT (tx->tx_msg.ksm_zc_cookies[0] == 0);
+               LASSERT(tx->tx_msg.ksm_zc_cookies[0] == 0);
                tx->tx_msg.ksm_zc_cookies[1] = cookie;
                return 1;
        }
@@ -220,7 +220,7 @@ ksocknal_queue_tx_zcack_v3(ksock_conn_t *conn,
                __u64   tmp = 0;
 
                /* two separated cookies: (a+2, a) or (a+1, a) */
-               LASSERT (tx->tx_msg.ksm_zc_cookies[0] -
+               LASSERT(tx->tx_msg.ksm_zc_cookies[0] -
                         tx->tx_msg.ksm_zc_cookies[1] <= 2);
 
                if (tx->tx_msg.ksm_zc_cookies[0] -
@@ -408,7 +408,7 @@ ksocknal_handle_zcack(ksock_conn_t *conn, __u64 cookie1, __u64 cookie2)
        ksock_peer_t      *peer = conn->ksnc_peer;
        ksock_tx_t      *tx;
        ksock_tx_t      *tmp;
-       LIST_HEAD     (zlist);
+       LIST_HEAD(zlist);
        int             count;
 
        if (cookie1 == 0)
@@ -450,7 +450,7 @@ ksocknal_handle_zcack(ksock_conn_t *conn, __u64 cookie1, __u64 cookie2)
 }
 
 static int
-ksocknal_send_hello_v1 (ksock_conn_t *conn, ksock_hello_msg_t *hello)
+ksocknal_send_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello)
 {
        struct socket   *sock = conn->ksnc_sock;
        lnet_hdr_t        *hdr;
@@ -526,7 +526,7 @@ out:
 }
 
 static int
-ksocknal_send_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello)
+ksocknal_send_hello_v2(ksock_conn_t *conn, ksock_hello_msg_t *hello)
 {
        struct socket *sock = conn->ksnc_sock;
        int          rc;
@@ -584,12 +584,12 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello,
        }
 
        rc = libcfs_sock_read(sock, &hdr->src_nid,
-                             sizeof (*hdr) - offsetof (lnet_hdr_t, src_nid),
+                             sizeof(*hdr) - offsetof(lnet_hdr_t, src_nid),
                              timeout);
        if (rc != 0) {
                CERROR("Error %d reading rest of HELLO hdr from %pI4h\n",
                        rc, &conn->ksnc_ipaddr);
-               LASSERT (rc < 0 && rc != -EALREADY);
+               LASSERT(rc < 0 && rc != -EALREADY);
                goto out;
        }
 
@@ -602,12 +602,12 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello,
                goto out;
        }
 
-       hello->kshm_src_nid      = le64_to_cpu (hdr->src_nid);
-       hello->kshm_src_pid      = le32_to_cpu (hdr->src_pid);
-       hello->kshm_src_incarnation = le64_to_cpu (hdr->msg.hello.incarnation);
-       hello->kshm_ctype          = le32_to_cpu (hdr->msg.hello.type);
-       hello->kshm_nips            = le32_to_cpu (hdr->payload_length) /
-                                        sizeof (__u32);
+       hello->kshm_src_nid      = le64_to_cpu(hdr->src_nid);
+       hello->kshm_src_pid      = le32_to_cpu(hdr->src_pid);
+       hello->kshm_src_incarnation = le64_to_cpu(hdr->msg.hello.incarnation);
+       hello->kshm_ctype          = le32_to_cpu(hdr->msg.hello.type);
+       hello->kshm_nips            = le32_to_cpu(hdr->payload_length) /
+                                        sizeof(__u32);
 
        if (hello->kshm_nips > LNET_MAX_INTERFACES) {
                CERROR("Bad nips %d from ip %pI4h\n",
@@ -645,7 +645,7 @@ out:
 }
 
 static int
-ksocknal_recv_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeout)
+ksocknal_recv_hello_v2(ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeout)
 {
        struct socket   *sock = conn->ksnc_sock;
        int             rc;
index faceb9505d84919630675a37f374077fb126b51a..4a14e5109821784374c2d2bc75a430abab826687 100644 (file)
@@ -650,15 +650,19 @@ lnet_prepare(lnet_pid_t requested_pid)
 
        recs = lnet_res_containers_create(LNET_COOKIE_TYPE_ME, LNET_FL_MAX_MES,
                                          sizeof(lnet_me_t));
-       if (recs == NULL)
+       if (recs == NULL) {
+               rc = -ENOMEM;
                goto failed;
+       }
 
        the_lnet.ln_me_containers = recs;
 
        recs = lnet_res_containers_create(LNET_COOKIE_TYPE_MD, LNET_FL_MAX_MDS,
                                          sizeof(lnet_libmd_t));
-       if (recs == NULL)
+       if (recs == NULL) {
+               rc = -ENOMEM;
                goto failed;
+       }
 
        the_lnet.ln_md_containers = recs;
 
index af171e25a5ecdfcd5fb24813adfc648b07b9443c..2dc4c4a1afd0cf1d97d9ab2d50bdbff3f550d8ab 100644 (file)
 #define DEBUG_SUBSYSTEM S_LNET
 #include "../../include/linux/lnet/lib-lnet.h"
 
-typedef struct {                           /* tmp struct for parsing routes */
+struct lnet_text_buf_t {           /* tmp struct for parsing routes */
        struct list_head         ltb_list;      /* stash on lists */
        int             ltb_size;       /* allocated size */
        char           ltb_text[0];     /* text buffer */
-} lnet_text_buf_t;
+};
 
 static int lnet_tbnob;                 /* track text buf allocation */
 #define LNET_MAX_TEXTBUF_NOB     (64<<10)      /* bound allocation */
@@ -365,14 +365,14 @@ lnet_parse_networks(struct list_head *nilist, char *networks)
        return -EINVAL;
 }
 
-static lnet_text_buf_t *
+static struct lnet_text_buf_t *
 lnet_new_text_buf(int str_len)
 {
-       lnet_text_buf_t *ltb;
+       struct lnet_text_buf_t *ltb;
        int           nob;
 
        /* NB allocate space for the terminating 0 */
-       nob = offsetof(lnet_text_buf_t, ltb_text[str_len + 1]);
+       nob = offsetof(struct lnet_text_buf_t, ltb_text[str_len + 1]);
        if (nob > LNET_SINGLE_TEXTBUF_NOB) {
                /* _way_ conservative for "route net gateway..." */
                CERROR("text buffer too big\n");
@@ -395,7 +395,7 @@ lnet_new_text_buf(int str_len)
 }
 
 static void
-lnet_free_text_buf(lnet_text_buf_t *ltb)
+lnet_free_text_buf(struct lnet_text_buf_t *ltb)
 {
        lnet_tbnob -= ltb->ltb_size;
        LIBCFS_FREE(ltb, ltb->ltb_size);
@@ -404,10 +404,10 @@ lnet_free_text_buf(lnet_text_buf_t *ltb)
 static void
 lnet_free_text_bufs(struct list_head *tbs)
 {
-       lnet_text_buf_t  *ltb;
+       struct lnet_text_buf_t  *ltb;
 
        while (!list_empty(tbs)) {
-               ltb = list_entry(tbs->next, lnet_text_buf_t, ltb_list);
+               ltb = list_entry(tbs->next, struct lnet_text_buf_t, ltb_list);
 
                list_del(&ltb->ltb_list);
                lnet_free_text_buf(ltb);
@@ -421,7 +421,7 @@ lnet_str2tbs_sep(struct list_head *tbs, char *str)
        char         *sep;
        int            nob;
        int            i;
-       lnet_text_buf_t  *ltb;
+       struct lnet_text_buf_t  *ltb;
 
        INIT_LIST_HEAD(&pending);
 
@@ -479,7 +479,7 @@ lnet_expand1tb(struct list_head *list,
 {
        int           len1 = (int)(sep1 - str);
        int           len2 = strlen(sep2 + 1);
-       lnet_text_buf_t *ltb;
+       struct lnet_text_buf_t *ltb;
 
        LASSERT(*sep1 == '[');
        LASSERT(*sep2 == ']');
@@ -532,14 +532,18 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str)
                if (enditem == parsed)          /* no empty items */
                        goto failed;
 
-               if (sscanf(parsed, "%d-%d/%d%n", &lo, &hi, &stride, &scanned) < 3) {
+               if (sscanf(parsed, "%d-%d/%d%n", &lo, &hi,
+                          &stride, &scanned) < 3) {
 
                        if (sscanf(parsed, "%d-%d%n", &lo, &hi, &scanned) < 2) {
 
                                /* simple string enumeration */
-                               if (lnet_expand1tb(&pending, str, sep, sep2,
-                                                  parsed, (int)(enditem - parsed)) != 0)
+                               if (lnet_expand1tb(
+                                    &pending, str, sep, sep2,
+                                    parsed,
+                                    (int)(enditem - parsed)) != 0) {
                                        goto failed;
+                               }
 
                                continue;
                        }
@@ -632,7 +636,7 @@ lnet_parse_route(char *str, int *im_a_router)
        struct list_head       *tmp2;
        __u32        net;
        lnet_nid_t      nid;
-       lnet_text_buf_t  *ltb;
+       struct lnet_text_buf_t  *ltb;
        int            rc;
        char         *sep;
        char         *token = str;
@@ -688,7 +692,8 @@ lnet_parse_route(char *str, int *im_a_router)
                list_add_tail(tmp1, tmp2);
 
                while (tmp1 != tmp2) {
-                       ltb = list_entry(tmp1, lnet_text_buf_t, ltb_list);
+                       ltb = list_entry(tmp1, struct lnet_text_buf_t,
+                                        ltb_list);
 
                        rc = lnet_str2tbs_expand(tmp1->next, ltb->ltb_text);
                        if (rc < 0)
@@ -728,12 +733,13 @@ lnet_parse_route(char *str, int *im_a_router)
        LASSERT(!list_empty(&gateways));
 
        list_for_each(tmp1, &nets) {
-               ltb = list_entry(tmp1, lnet_text_buf_t, ltb_list);
+               ltb = list_entry(tmp1, struct lnet_text_buf_t, ltb_list);
                net = libcfs_str2net(ltb->ltb_text);
                LASSERT(net != LNET_NIDNET(LNET_NID_ANY));
 
                list_for_each(tmp2, &gateways) {
-                       ltb = list_entry(tmp2, lnet_text_buf_t, ltb_list);
+                       ltb = list_entry(tmp2, struct lnet_text_buf_t,
+                                        ltb_list);
                        nid = libcfs_str2nid(ltb->ltb_text);
                        LASSERT(nid != LNET_NID_ANY);
 
@@ -766,10 +772,10 @@ lnet_parse_route(char *str, int *im_a_router)
 static int
 lnet_parse_route_tbs(struct list_head *tbs, int *im_a_router)
 {
-       lnet_text_buf_t   *ltb;
+       struct lnet_text_buf_t   *ltb;
 
        while (!list_empty(tbs)) {
-               ltb = list_entry(tbs->next, lnet_text_buf_t, ltb_list);
+               ltb = list_entry(tbs->next, struct lnet_text_buf_t, ltb_list);
 
                if (lnet_parse_route(ltb->ltb_text, im_a_router) < 0) {
                        lnet_free_text_bufs(tbs);
@@ -903,8 +909,8 @@ lnet_splitnets(char *source, struct list_head *nets)
        int            offset = 0;
        int            offset2;
        int            len;
-       lnet_text_buf_t  *tb;
-       lnet_text_buf_t  *tb2;
+       struct lnet_text_buf_t  *tb;
+       struct lnet_text_buf_t  *tb2;
        struct list_head       *t;
        char         *sep;
        char         *bracket;
@@ -913,7 +919,7 @@ lnet_splitnets(char *source, struct list_head *nets)
        LASSERT(!list_empty(nets));
        LASSERT(nets->next == nets->prev);     /* single entry */
 
-       tb = list_entry(nets->next, lnet_text_buf_t, ltb_list);
+       tb = list_entry(nets->next, struct lnet_text_buf_t, ltb_list);
 
        for (;;) {
                sep = strchr(tb->ltb_text, ',');
@@ -949,7 +955,7 @@ lnet_splitnets(char *source, struct list_head *nets)
                }
 
                list_for_each(t, nets) {
-                       tb2 = list_entry(t, lnet_text_buf_t, ltb_list);
+                       tb2 = list_entry(t, struct lnet_text_buf_t, ltb_list);
 
                        if (tb2 == tb)
                                continue;
@@ -988,8 +994,8 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip)
        struct list_head          current_nets;
        struct list_head         *t;
        struct list_head         *t2;
-       lnet_text_buf_t    *tb;
-       lnet_text_buf_t    *tb2;
+       struct lnet_text_buf_t    *tb;
+       struct lnet_text_buf_t    *tb2;
        __u32          net1;
        __u32          net2;
        int              len;
@@ -1012,7 +1018,7 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip)
        rc = 0;
 
        while (!list_empty(&raw_entries)) {
-               tb = list_entry(raw_entries.next, lnet_text_buf_t,
+               tb = list_entry(raw_entries.next, struct lnet_text_buf_t,
                                    ltb_list);
 
                strncpy(source, tb->ltb_text, sizeof(source)-1);
@@ -1039,12 +1045,12 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip)
 
                dup = 0;
                list_for_each(t, &current_nets) {
-                       tb = list_entry(t, lnet_text_buf_t, ltb_list);
+                       tb = list_entry(t, struct lnet_text_buf_t, ltb_list);
                        net1 = lnet_netspec2net(tb->ltb_text);
                        LASSERT(net1 != LNET_NIDNET(LNET_NID_ANY));
 
                        list_for_each(t2, &matched_nets) {
-                               tb2 = list_entry(t2, lnet_text_buf_t,
+                               tb2 = list_entry(t2, struct lnet_text_buf_t,
                                                     ltb_list);
                                net2 = lnet_netspec2net(tb2->ltb_text);
                                LASSERT(net2 != LNET_NIDNET(LNET_NID_ANY));
@@ -1065,7 +1071,7 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip)
                }
 
                list_for_each_safe(t, t2, &current_nets) {
-                       tb = list_entry(t, lnet_text_buf_t, ltb_list);
+                       tb = list_entry(t, struct lnet_text_buf_t, ltb_list);
 
                        list_del(&tb->ltb_list);
                        list_add_tail(&tb->ltb_list, &matched_nets);
index 863cc3735edfdf9714920cb5d0414c52d98aec0b..5470148f5b64a235fa9c6d35ebca7542cc1a658d 100644 (file)
@@ -81,9 +81,8 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback,
 
        count = cfs_power2_roundup(count);
 
-       if (callback != LNET_EQ_HANDLER_NONE && count != 0) {
+       if (callback != LNET_EQ_HANDLER_NONE && count != 0)
                CWARN("EQ callback is guaranteed to get every event, do you still want to set eqcount %d for polling event which will have locking overhead? Please contact with developer to confirm\n", count);
-       }
 
        /* count can be 0 if only need callback, we can eliminate
         * overhead of enqueue event */
index 3225c069637dc767f09759110792029eb5649799..89d660fefd4896be1331972caae5f22f92bcc9f9 100644 (file)
@@ -123,7 +123,7 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink)
 
                lmd->md_length = total_length;
 
-               if ((umd->options & LNET_MD_MAX_SIZE) != 0 && /* max size used */
+               if ((umd->options & LNET_MD_MAX_SIZE) != 0 && /* use max size */
                    (umd->max_size < 0 ||
                     umd->max_size > total_length)) /* illegal max_size */
                        return -EINVAL;
index 0f53c761f1a99285bf46e3b9f52128c11058b553..c2fb70e5fc4e08545e0c22056b0f4f3114d40279 100644 (file)
@@ -1530,7 +1530,7 @@ lnet_parse_reply(lnet_ni_t *ni, lnet_msg_t *msg)
        LASSERT(md->md_offset == 0);
 
        rlength = hdr->payload_length;
-       mlength = min_t(int, rlength, md->md_length);
+       mlength = min_t(uint, rlength, md->md_length);
 
        if (mlength < rlength &&
            (md->md_options & LNET_MD_TRUNCATE) == 0) {
index c93ae8510530b218ed89d3c0fde72d3ff0933e7a..45b5742f1bd270db5ca2ff5c428e874b771025da 100644 (file)
@@ -87,7 +87,7 @@ lnet_peer_tables_destroy(void)
 
        cfs_percpt_for_each(ptable, i, the_lnet.ln_peer_tables) {
                hash = ptable->pt_hash;
-               if (hash == NULL) /* not intialized */
+               if (hash == NULL) /* not initialized */
                        break;
 
                LASSERT(list_empty(&ptable->pt_deathrow));
@@ -132,7 +132,7 @@ lnet_peer_tables_cleanup(void)
        }
 
        cfs_percpt_for_each(ptable, i, the_lnet.ln_peer_tables) {
-               LIST_HEAD       (deathrow);
+               LIST_HEAD(deathrow);
                lnet_peer_t     *lp;
 
                lnet_net_lock(i);
index 52ec0ab7e3c3960184fe403bd008e8f296e0bb98..8510bae4822a8f593f166fbdcd0bb24034801039 100644 (file)
@@ -107,7 +107,8 @@ lnet_peers_start_down(void)
 }
 
 void
-lnet_notify_locked(lnet_peer_t *lp, int notifylnd, int alive, unsigned long when)
+lnet_notify_locked(lnet_peer_t *lp, int notifylnd, int alive,
+                  unsigned long when)
 {
        if (time_before(when, lp->lp_timestamp)) { /* out of date information */
                CDEBUG(D_NET, "Out of date\n");
@@ -225,7 +226,7 @@ lnet_rtr_decref_locked(lnet_peer_t *lp)
 }
 
 lnet_remotenet_t *
-lnet_find_net_locked (__u32 net)
+lnet_find_net_locked(__u32 net)
 {
        lnet_remotenet_t        *rnet;
        struct list_head                *tmp;
@@ -269,12 +270,11 @@ static void lnet_shuffle_seed(void)
        do_gettimeofday(&tv);
        cfs_srand(tv.tv_sec ^ seed[0], tv.tv_usec ^ seed[1]);
        seeded = 1;
-       return;
 }
 
 /* NB expects LNET_LOCK held */
 static void
-lnet_add_route_to_rnet (lnet_remotenet_t *rnet, lnet_route_t *route)
+lnet_add_route_to_rnet(lnet_remotenet_t *rnet, lnet_route_t *route)
 {
        unsigned int      len = 0;
        unsigned int      offset = 0;
@@ -282,13 +282,13 @@ lnet_add_route_to_rnet (lnet_remotenet_t *rnet, lnet_route_t *route)
 
        lnet_shuffle_seed();
 
-       list_for_each (e, &rnet->lrn_routes) {
+       list_for_each(e, &rnet->lrn_routes) {
                len++;
        }
 
        /* len+1 positions to add a new entry, also prevents division by 0 */
        offset = cfs_rand() % (len + 1);
-       list_for_each (e, &rnet->lrn_routes) {
+       list_for_each(e, &rnet->lrn_routes) {
                if (offset == 0)
                        break;
                offset--;
@@ -354,17 +354,16 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway,
                LIBCFS_FREE(route, sizeof(*route));
                LIBCFS_FREE(rnet, sizeof(*rnet));
 
-               if (rc == -EHOSTUNREACH) /* gateway is not on a local net */
+               if (rc == -EHOSTUNREACH) /* gateway is not on a local net */
                        return 0;       /* ignore the route entry */
-               } else {
-                       CERROR("Error %d creating route %s %d %s\n", rc,
-                              libcfs_net2str(net), hops,
-                              libcfs_nid2str(gateway));
-               }
+               CERROR("Error %d creating route %s %d %s\n", rc,
+                      libcfs_net2str(net), hops,
+                      libcfs_nid2str(gateway));
+
                return rc;
        }
 
-       LASSERT (!the_lnet.ln_shutdown);
+       LASSERT(!the_lnet.ln_shutdown);
 
        rnet2 = lnet_find_net_locked(net);
        if (rnet2 == NULL) {
@@ -375,7 +374,7 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway,
 
        /* Search for a duplicate route (it's a NOOP if it is) */
        add_route = 1;
-       list_for_each (e, &rnet2->lrn_routes) {
+       list_for_each(e, &rnet2->lrn_routes) {
                lnet_route_t *route2 = list_entry(e, lnet_route_t, lr_list);
 
                if (route2->lr_gateway == route->lr_gateway) {
@@ -384,7 +383,7 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway,
                }
 
                /* our lookups must be true */
-               LASSERT (route2->lr_gateway->lp_nid != gateway);
+               LASSERT(route2->lr_gateway->lp_nid != gateway);
        }
 
        if (add_route) {
@@ -546,7 +545,7 @@ lnet_del_route(__u32 net, lnet_nid_t gw_nid)
 }
 
 void
-lnet_destroy_routes (void)
+lnet_destroy_routes(void)
 {
        lnet_del_route(LNET_NIDNET(LNET_NID_ANY), LNET_NID_ANY);
 }
@@ -606,7 +605,6 @@ lnet_swap_pinginfo(lnet_ping_info_t *info)
                __swab64s(&stat->ns_nid);
                __swab32s(&stat->ns_status);
        }
-       return;
 }
 
 /**
@@ -758,13 +756,13 @@ lnet_wait_known_routerstate(void)
        struct list_head          *entry;
        int               all_known;
 
-       LASSERT (the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING);
+       LASSERT(the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING);
 
        for (;;) {
                int     cpt = lnet_net_lock_current();
 
                all_known = 1;
-               list_for_each (entry, &the_lnet.ln_routers) {
+               list_for_each(entry, &the_lnet.ln_routers) {
                        rtr = list_entry(entry, lnet_peer_t, lp_rtr_list);
 
                        if (rtr->lp_alive_count == 0) {
@@ -886,7 +884,7 @@ lnet_create_rc_data_locked(lnet_peer_t *gateway)
        }
        rcd->rcd_pinginfo = pi;
 
-       LASSERT (!LNetHandleIsInvalid(the_lnet.ln_rc_eqh));
+       LASSERT(!LNetHandleIsInvalid(the_lnet.ln_rc_eqh));
        rc = LNetMDBind((lnet_md_t){.start     = pi,
                                    .user_ptr  = rcd,
                                    .length    = LNET_PINGINFO_SIZE,
@@ -929,7 +927,7 @@ lnet_create_rc_data_locked(lnet_peer_t *gateway)
 }
 
 static int
-lnet_router_check_interval (lnet_peer_t *rtr)
+lnet_router_check_interval(lnet_peer_t *rtr)
 {
        int secs;
 
@@ -942,7 +940,7 @@ lnet_router_check_interval (lnet_peer_t *rtr)
 }
 
 static void
-lnet_ping_router_locked (lnet_peer_t *rtr)
+lnet_ping_router_locked(lnet_peer_t *rtr)
 {
        lnet_rc_data_t *rcd = NULL;
        unsigned long      now = cfs_time_current();
@@ -1010,7 +1008,6 @@ lnet_ping_router_locked (lnet_peer_t *rtr)
        }
 
        lnet_peer_decref_locked(rtr);
-       return;
 }
 
 int
@@ -1019,7 +1016,7 @@ lnet_router_checker_start(void)
        int       rc;
        int       eqsz;
 
-       LASSERT (the_lnet.ln_rc_state == LNET_RC_STATE_SHUTDOWN);
+       LASSERT(the_lnet.ln_rc_state == LNET_RC_STATE_SHUTDOWN);
 
        if (check_routers_before_use &&
            dead_router_check_interval <= 0) {
@@ -1067,14 +1064,14 @@ lnet_router_checker_start(void)
 }
 
 void
-lnet_router_checker_stop (void)
+lnet_router_checker_stop(void)
 {
        int rc;
 
        if (the_lnet.ln_rc_state == LNET_RC_STATE_SHUTDOWN)
                return;
 
-       LASSERT (the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING);
+       LASSERT(the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING);
        the_lnet.ln_rc_state = LNET_RC_STATE_STOPPING;
 
        /* block until event callback signals exit */
@@ -1082,8 +1079,7 @@ lnet_router_checker_stop (void)
        LASSERT(the_lnet.ln_rc_state == LNET_RC_STATE_SHUTDOWN);
 
        rc = LNetEQFree(the_lnet.ln_rc_eqh);
-       LASSERT (rc == 0);
-       return;
+       LASSERT(rc == 0);
 }
 
 static void
@@ -1178,7 +1174,7 @@ lnet_router_checker(void *arg)
 
        cfs_block_allsigs();
 
-       LASSERT (the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING);
+       LASSERT(the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING);
 
        while (the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING) {
                __u64   version;
@@ -1291,11 +1287,11 @@ lnet_rtrpool_free_bufs(lnet_rtrbufpool_t *rbp)
        if (rbp->rbp_nbuffers == 0) /* not initialized or already freed */
                return;
 
-       LASSERT (list_empty(&rbp->rbp_msgs));
-       LASSERT (rbp->rbp_credits == rbp->rbp_nbuffers);
+       LASSERT(list_empty(&rbp->rbp_msgs));
+       LASSERT(rbp->rbp_credits == rbp->rbp_nbuffers);
 
        while (!list_empty(&rbp->rbp_bufs)) {
-               LASSERT (rbp->rbp_credits > 0);
+               LASSERT(rbp->rbp_credits > 0);
 
                rb = list_entry(rbp->rbp_bufs.next,
                                    lnet_rtrbuf_t, rb_list);
@@ -1304,8 +1300,8 @@ lnet_rtrpool_free_bufs(lnet_rtrbufpool_t *rbp)
                nbuffers++;
        }
 
-       LASSERT (rbp->rbp_nbuffers == nbuffers);
-       LASSERT (rbp->rbp_credits == nbuffers);
+       LASSERT(rbp->rbp_nbuffers == nbuffers);
+       LASSERT(rbp->rbp_credits == nbuffers);
 
        rbp->rbp_nbuffers = rbp->rbp_credits = 0;
 }
@@ -1317,7 +1313,7 @@ lnet_rtrpool_alloc_bufs(lnet_rtrbufpool_t *rbp, int nbufs, int cpt)
        int         i;
 
        if (rbp->rbp_nbuffers != 0) {
-               LASSERT (rbp->rbp_nbuffers == nbufs);
+               LASSERT(rbp->rbp_nbuffers == nbufs);
                return 0;
        }
 
@@ -1337,10 +1333,10 @@ lnet_rtrpool_alloc_bufs(lnet_rtrbufpool_t *rbp, int nbufs, int cpt)
 
                /* No allocation "under fire" */
                /* Otherwise we'd need code to schedule blocked msgs etc */
-               LASSERT (!the_lnet.ln_routing);
+               LASSERT(!the_lnet.ln_routing);
        }
 
-       LASSERT (rbp->rbp_credits == nbufs);
+       LASSERT(rbp->rbp_credits == nbufs);
        return 0;
 }
 
@@ -1435,7 +1431,7 @@ int
 lnet_rtrpools_alloc(int im_a_router)
 {
        lnet_rtrbufpool_t *rtrp;
-       int     large_pages = (LNET_MTU + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       int     large_pages;
        int     small_pages = 1;
        int     nrb_tiny;
        int     nrb_small;
@@ -1443,6 +1439,8 @@ lnet_rtrpools_alloc(int im_a_router)
        int     rc;
        int     i;
 
+       large_pages = (LNET_MTU + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
        if (!strcmp(forwarding, "")) {
                /* not set either way */
                if (!im_a_router)
@@ -1513,16 +1511,16 @@ lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when)
        unsigned long           now = cfs_time_current();
        int                     cpt = lnet_cpt_of_nid(nid);
 
-       LASSERT (!in_interrupt ());
+       LASSERT(!in_interrupt ());
 
-       CDEBUG (D_NET, "%s notifying %s: %s\n",
+       CDEBUG(D_NET, "%s notifying %s: %s\n",
                (ni == NULL) ? "userspace" : libcfs_nid2str(ni->ni_nid),
                libcfs_nid2str(nid),
                alive ? "up" : "down");
 
        if (ni != NULL &&
            LNET_NIDNET(ni->ni_nid) != LNET_NIDNET(nid)) {
-               CWARN ("Ignoring notification of %s %s by %s (different net)\n",
+               CWARN("Ignoring notification of %s %s by %s (different net)\n",
                        libcfs_nid2str(nid), alive ? "birth" : "death",
                        libcfs_nid2str(ni->ni_nid));
                return -EINVAL;
@@ -1577,21 +1575,20 @@ lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when)
 EXPORT_SYMBOL(lnet_notify);
 
 void
-lnet_get_tunables (void)
+lnet_get_tunables(void)
 {
-       return;
 }
 
 #else
 
 int
-lnet_notify (lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when)
+lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when)
 {
        return -EOPNOTSUPP;
 }
 
 void
-lnet_router_checker (void)
+lnet_router_checker(void)
 {
        static time_t last;
        static int    running;
@@ -1643,7 +1640,7 @@ lnet_router_checker (void)
                        abort();
                }
 
-               LASSERT (rc == 1);
+               LASSERT(rc == 1);
 
                lnet_router_checker_event(&ev);
        }
@@ -1655,26 +1652,25 @@ lnet_router_checker (void)
                return;
        }
 
-       LASSERT (the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING);
+       LASSERT(the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING);
 
        lnet_net_lock(0);
 
        version = the_lnet.ln_routers_version;
-       list_for_each_entry (rtr, &the_lnet.ln_routers, lp_rtr_list) {
+       list_for_each_entry(rtr, &the_lnet.ln_routers, lp_rtr_list) {
                lnet_ping_router_locked(rtr);
-               LASSERT (version == the_lnet.ln_routers_version);
+               LASSERT(version == the_lnet.ln_routers_version);
        }
 
        lnet_net_unlock(0);
 
        running = 0; /* lock only needed for the recursion check */
-       return;
 }
 
 /* NB lnet_peers_start_down depends on me,
  * so must be called before any peer creation */
 void
-lnet_get_tunables (void)
+lnet_get_tunables(void)
 {
        char *s;
 
index 463da076fa703ca04c7311d47f06f12b5ff596b7..658f4584fff868252b8c8d128b0039f23c96f2ab 100644 (file)
@@ -175,7 +175,6 @@ brw_fill_page(struct page *pg, int pattern, __u64 magic)
        }
 
        LBUG();
-       return;
 }
 
 static int
index fbff84cea52fc65774b2548c5c22ca220922d012..045fe295ad5409a181cbbb21844a0bbdf6a0939e 100644 (file)
@@ -203,7 +203,7 @@ lst_group_add_ioctl(lstio_group_add_args_t *args)
        if (args->lstio_grp_key != console_session.ses_key)
                return -EACCES;
 
-       if (args->lstio_grp_namep == NULL||
+       if (args->lstio_grp_namep == NULL ||
            args->lstio_grp_nmlen <= 0 ||
            args->lstio_grp_nmlen > LST_NAME_SIZE)
                return -EINVAL;
@@ -857,62 +857,62 @@ lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_data *data)
        memset(&console_session.ses_trans_stat, 0, sizeof(lstcon_trans_stat_t));
 
        switch (opc) {
-               case LSTIO_SESSION_NEW:
-                       rc = lst_session_new_ioctl((lstio_session_new_args_t *)buf);
-                       break;
-               case LSTIO_SESSION_END:
-                       rc = lst_session_end_ioctl((lstio_session_end_args_t *)buf);
-                       break;
-               case LSTIO_SESSION_INFO:
-                       rc = lst_session_info_ioctl((lstio_session_info_args_t *)buf);
-                       break;
-               case LSTIO_DEBUG:
-                       rc = lst_debug_ioctl((lstio_debug_args_t *)buf);
-                       break;
-               case LSTIO_GROUP_ADD:
-                       rc = lst_group_add_ioctl((lstio_group_add_args_t *)buf);
-                       break;
-               case LSTIO_GROUP_DEL:
-                       rc = lst_group_del_ioctl((lstio_group_del_args_t *)buf);
-                       break;
-               case LSTIO_GROUP_UPDATE:
-                       rc = lst_group_update_ioctl((lstio_group_update_args_t *)buf);
-                       break;
-               case LSTIO_NODES_ADD:
-                       rc = lst_nodes_add_ioctl((lstio_group_nodes_args_t *)buf);
-                       break;
-               case LSTIO_GROUP_LIST:
-                       rc = lst_group_list_ioctl((lstio_group_list_args_t *)buf);
-                       break;
-               case LSTIO_GROUP_INFO:
-                       rc = lst_group_info_ioctl((lstio_group_info_args_t *)buf);
-                       break;
-               case LSTIO_BATCH_ADD:
-                       rc = lst_batch_add_ioctl((lstio_batch_add_args_t *)buf);
-                       break;
-               case LSTIO_BATCH_START:
-                       rc = lst_batch_run_ioctl((lstio_batch_run_args_t *)buf);
-                       break;
-               case LSTIO_BATCH_STOP:
-                       rc = lst_batch_stop_ioctl((lstio_batch_stop_args_t *)buf);
-                       break;
-               case LSTIO_BATCH_QUERY:
-                       rc = lst_batch_query_ioctl((lstio_batch_query_args_t *)buf);
-                       break;
-               case LSTIO_BATCH_LIST:
-                       rc = lst_batch_list_ioctl((lstio_batch_list_args_t *)buf);
-                       break;
-               case LSTIO_BATCH_INFO:
-                       rc = lst_batch_info_ioctl((lstio_batch_info_args_t *)buf);
-                       break;
-               case LSTIO_TEST_ADD:
-                       rc = lst_test_add_ioctl((lstio_test_args_t *)buf);
-                       break;
-               case LSTIO_STAT_QUERY:
-                       rc = lst_stat_query_ioctl((lstio_stat_args_t *)buf);
-                       break;
-               default:
-                       rc = -EINVAL;
+       case LSTIO_SESSION_NEW:
+               rc = lst_session_new_ioctl((lstio_session_new_args_t *)buf);
+               break;
+       case LSTIO_SESSION_END:
+               rc = lst_session_end_ioctl((lstio_session_end_args_t *)buf);
+               break;
+       case LSTIO_SESSION_INFO:
+               rc = lst_session_info_ioctl((lstio_session_info_args_t *)buf);
+               break;
+       case LSTIO_DEBUG:
+               rc = lst_debug_ioctl((lstio_debug_args_t *)buf);
+               break;
+       case LSTIO_GROUP_ADD:
+               rc = lst_group_add_ioctl((lstio_group_add_args_t *)buf);
+               break;
+       case LSTIO_GROUP_DEL:
+               rc = lst_group_del_ioctl((lstio_group_del_args_t *)buf);
+               break;
+       case LSTIO_GROUP_UPDATE:
+               rc = lst_group_update_ioctl((lstio_group_update_args_t *)buf);
+               break;
+       case LSTIO_NODES_ADD:
+               rc = lst_nodes_add_ioctl((lstio_group_nodes_args_t *)buf);
+               break;
+       case LSTIO_GROUP_LIST:
+               rc = lst_group_list_ioctl((lstio_group_list_args_t *)buf);
+               break;
+       case LSTIO_GROUP_INFO:
+               rc = lst_group_info_ioctl((lstio_group_info_args_t *)buf);
+               break;
+       case LSTIO_BATCH_ADD:
+               rc = lst_batch_add_ioctl((lstio_batch_add_args_t *)buf);
+               break;
+       case LSTIO_BATCH_START:
+               rc = lst_batch_run_ioctl((lstio_batch_run_args_t *)buf);
+               break;
+       case LSTIO_BATCH_STOP:
+               rc = lst_batch_stop_ioctl((lstio_batch_stop_args_t *)buf);
+               break;
+       case LSTIO_BATCH_QUERY:
+               rc = lst_batch_query_ioctl((lstio_batch_query_args_t *)buf);
+               break;
+       case LSTIO_BATCH_LIST:
+               rc = lst_batch_list_ioctl((lstio_batch_list_args_t *)buf);
+               break;
+       case LSTIO_BATCH_INFO:
+               rc = lst_batch_info_ioctl((lstio_batch_info_args_t *)buf);
+               break;
+       case LSTIO_TEST_ADD:
+               rc = lst_test_add_ioctl((lstio_test_args_t *)buf);
+               break;
+       case LSTIO_STAT_QUERY:
+               rc = lst_stat_query_ioctl((lstio_stat_args_t *)buf);
+               break;
+       default:
+               rc = -EINVAL;
        }
 
        if (copy_to_user(data->ioc_pbuf2, &console_session.ses_trans_stat,
index 1e0afc2868479739e1e6c211a2c4aebd9451760c..2b5f53c7a730013a4d804417608ce55052f7c74f 100644 (file)
@@ -64,7 +64,7 @@ lstcon_session_t      console_session;
 static void
 lstcon_node_get(lstcon_node_t *nd)
 {
-       LASSERT (nd->nd_ref >= 1);
+       LASSERT(nd->nd_ref >= 1);
 
        nd->nd_ref++;
 }
@@ -75,7 +75,7 @@ lstcon_node_find(lnet_process_id_t id, lstcon_node_t **ndpp, int create)
        lstcon_ndlink_t *ndl;
        unsigned int     idx = LNET_NIDADDR(id.nid) % LST_GLOBAL_HASHSIZE;
 
-       LASSERT (id.nid != LNET_NID_ANY);
+       LASSERT(id.nid != LNET_NID_ANY);
 
        list_for_each_entry(ndl, &console_session.ses_ndl_hash[idx], ndl_hlink) {
                if (ndl->ndl_node->nd_id.nid != id.nid ||
@@ -119,15 +119,15 @@ lstcon_node_put(lstcon_node_t *nd)
 {
        lstcon_ndlink_t  *ndl;
 
-       LASSERT (nd->nd_ref > 0);
+       LASSERT(nd->nd_ref > 0);
 
        if (--nd->nd_ref > 0)
                return;
 
        ndl = (lstcon_ndlink_t *)(nd + 1);
 
-       LASSERT (!list_empty(&ndl->ndl_link));
-       LASSERT (!list_empty(&ndl->ndl_hlink));
+       LASSERT(!list_empty(&ndl->ndl_link));
+       LASSERT(!list_empty(&ndl->ndl_hlink));
 
        /* remove from session */
        list_del(&ndl->ndl_link);
@@ -184,8 +184,8 @@ lstcon_ndlink_find(struct list_head *hash,
 static void
 lstcon_ndlink_release(lstcon_ndlink_t *ndl)
 {
-       LASSERT (list_empty(&ndl->ndl_link));
-       LASSERT (!list_empty(&ndl->ndl_hlink));
+       LASSERT(list_empty(&ndl->ndl_link));
+       LASSERT(!list_empty(&ndl->ndl_hlink));
 
        list_del(&ndl->ndl_hlink); /* delete from hash */
        lstcon_node_put(ndl->ndl_node);
@@ -254,7 +254,7 @@ lstcon_group_decref(lstcon_group_t *grp)
        lstcon_group_drain(grp, 0);
 
        for (i = 0; i < LST_NODE_HASHSIZE; i++) {
-               LASSERT (list_empty(&grp->grp_ndl_hash[i]));
+               LASSERT(list_empty(&grp->grp_ndl_hash[i]));
        }
 
        LIBCFS_FREE(grp, offsetof(lstcon_group_t,
@@ -552,8 +552,8 @@ lstcon_nodes_add(char *name, int count, lnet_process_id_t *ids_up,
        lstcon_group_t   *grp;
        int                  rc;
 
-       LASSERT (count > 0);
-       LASSERT (ids_up != NULL);
+       LASSERT(count > 0);
+       LASSERT(ids_up != NULL);
 
        rc = lstcon_group_find(name, &grp);
        if (rc != 0) {
@@ -726,8 +726,8 @@ lstcon_group_list(int index, int len, char *name_up)
 {
        lstcon_group_t *grp;
 
-       LASSERT (index >= 0);
-       LASSERT (name_up != NULL);
+       LASSERT(index >= 0);
+       LASSERT(name_up != NULL);
 
        list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
                if (index-- == 0) {
@@ -748,10 +748,10 @@ lstcon_nodes_getent(struct list_head *head, int *index_p,
        int            count = 0;
        int            index = 0;
 
-       LASSERT (index_p != NULL && count_p != NULL);
-       LASSERT (dents_up != NULL);
-       LASSERT (*index_p >= 0);
-       LASSERT (*count_p > 0);
+       LASSERT(index_p != NULL && count_p != NULL);
+       LASSERT(dents_up != NULL);
+       LASSERT(*index_p >= 0);
+       LASSERT(*count_p > 0);
 
        list_for_each_entry(ndl, head, ndl_link) {
                if (index++ < *index_p)
@@ -905,8 +905,8 @@ lstcon_batch_list(int index, int len, char *name_up)
 {
        lstcon_batch_t    *bat;
 
-       LASSERT (name_up != NULL);
-       LASSERT (index >= 0);
+       LASSERT(name_up != NULL);
+       LASSERT(index >= 0);
 
        list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
                if (index-- == 0) {
@@ -1093,7 +1093,7 @@ lstcon_batch_destroy(lstcon_batch_t *bat)
        while (!list_empty(&bat->bat_test_list)) {
                test = list_entry(bat->bat_test_list.next,
                                      lstcon_test_t, tes_link);
-               LASSERT (list_empty(&test->tes_trans_list));
+               LASSERT(list_empty(&test->tes_trans_list));
 
                list_del(&test->tes_link);
 
@@ -1104,7 +1104,7 @@ lstcon_batch_destroy(lstcon_batch_t *bat)
                                           tes_param[test->tes_paramlen]));
        }
 
-       LASSERT (list_empty(&bat->bat_trans_list));
+       LASSERT(list_empty(&bat->bat_trans_list));
 
        while (!list_empty(&bat->bat_cli_list)) {
                ndl = list_entry(bat->bat_cli_list.next,
@@ -1123,8 +1123,8 @@ lstcon_batch_destroy(lstcon_batch_t *bat)
        }
 
        for (i = 0; i < LST_NODE_HASHSIZE; i++) {
-               LASSERT (list_empty(&bat->bat_cli_hash[i]));
-               LASSERT (list_empty(&bat->bat_srv_hash[i]));
+               LASSERT(list_empty(&bat->bat_cli_hash[i]));
+               LASSERT(list_empty(&bat->bat_srv_hash[i]));
        }
 
        LIBCFS_FREE(bat->bat_cli_hash,
@@ -1144,10 +1144,10 @@ lstcon_testrpc_condition(int transop, lstcon_node_t *nd, void *arg)
        struct list_head       *head;
 
        test = (lstcon_test_t *)arg;
-       LASSERT (test != NULL);
+       LASSERT(test != NULL);
 
        batch = test->tes_batch;
-       LASSERT (batch != NULL);
+       LASSERT(batch != NULL);
 
        if (test->tes_oneside &&
            transop == LST_TRANS_TSBSRVADD)
@@ -1161,13 +1161,13 @@ lstcon_testrpc_condition(int transop, lstcon_node_t *nd, void *arg)
                head = &batch->bat_cli_list;
 
        } else {
-               LASSERT (transop == LST_TRANS_TSBSRVADD);
+               LASSERT(transop == LST_TRANS_TSBSRVADD);
 
                hash = batch->bat_srv_hash;
                head = &batch->bat_srv_list;
        }
 
-       LASSERT (nd->nd_id.nid != LNET_NID_ANY);
+       LASSERT(nd->nd_id.nid != LNET_NID_ANY);
 
        if (lstcon_ndlink_find(hash, nd->nd_id, &ndl, 1) != 0)
                return -ENOMEM;
@@ -1186,8 +1186,8 @@ lstcon_test_nodes_add(lstcon_test_t *test, struct list_head *result_up)
        int                  transop;
        int                  rc;
 
-       LASSERT (test->tes_src_grp != NULL);
-       LASSERT (test->tes_dst_grp != NULL);
+       LASSERT(test->tes_src_grp != NULL);
+       LASSERT(test->tes_dst_grp != NULL);
 
        transop = LST_TRANS_TSBSRVADD;
        grp  = test->tes_dst_grp;
@@ -1382,7 +1382,7 @@ lstcon_tsbrpc_readent(int transop, srpc_msg_t *msg,
 {
        srpc_batch_reply_t *rep = &msg->msg_body.bat_reply;
 
-       LASSERT (transop == LST_TRANS_TSBCLIQRY ||
+       LASSERT(transop == LST_TRANS_TSBCLIQRY ||
                 transop == LST_TRANS_TSBSRVQRY);
 
        /* positive errno, framework error code */
@@ -1691,7 +1691,7 @@ lstcon_new_session_id(lst_sid_t *sid)
 {
        lnet_process_id_t      id;
 
-       LASSERT (console_session.ses_state == LST_SESSION_NONE);
+       LASSERT(console_session.ses_state == LST_SESSION_NONE);
 
        LNetGetId(1, &id);
        sid->ses_nid   = id.nid;
@@ -1806,7 +1806,7 @@ lstcon_session_end(void)
        lstcon_batch_t     *bat;
        int              rc = 0;
 
-       LASSERT (console_session.ses_state == LST_SESSION_ACTIVE);
+       LASSERT(console_session.ses_state == LST_SESSION_ACTIVE);
 
        rc = lstcon_rpc_trans_ndlist(&console_session.ses_ndl_list,
                                     NULL, LST_TRANS_SESEND, NULL,
@@ -1846,13 +1846,13 @@ lstcon_session_end(void)
        while (!list_empty(&console_session.ses_grp_list)) {
                grp = list_entry(console_session.ses_grp_list.next,
                                     lstcon_group_t, grp_link);
-               LASSERT (grp->grp_ref == 1);
+               LASSERT(grp->grp_ref == 1);
 
                lstcon_group_put(grp);
        }
 
        /* all nodes should be released */
-       LASSERT (list_empty(&console_session.ses_ndl_list));
+       LASSERT(list_empty(&console_session.ses_ndl_list));
 
        console_session.ses_shutdown = 0;
        console_session.ses_expired  = 0;
@@ -1892,7 +1892,7 @@ lstcon_session_feats_check(unsigned feats)
 }
 
 static int
-lstcon_acceptor_handle (srpc_server_rpc_t *rpc)
+lstcon_acceptor_handle(srpc_server_rpc_t *rpc)
 {
        srpc_msg_t      *rep  = &rpc->srpc_replymsg;
        srpc_msg_t      *req  = &rpc->srpc_reqstbuf->buf_msg;
@@ -2026,7 +2026,7 @@ lstcon_console_init(void)
        lstcon_init_acceptor_service();
 
        rc = srpc_add_service(&lstcon_acceptor_service);
-       LASSERT (rc != -EBUSY);
+       LASSERT(rc != -EBUSY);
        if (rc != 0) {
                LIBCFS_FREE(console_session.ses_ndl_hash,
                            sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
@@ -2078,13 +2078,13 @@ lstcon_console_fini(void)
 
        mutex_unlock(&console_session.ses_mutex);
 
-       LASSERT (list_empty(&console_session.ses_ndl_list));
-       LASSERT (list_empty(&console_session.ses_grp_list));
-       LASSERT (list_empty(&console_session.ses_bat_list));
-       LASSERT (list_empty(&console_session.ses_trans_list));
+       LASSERT(list_empty(&console_session.ses_ndl_list));
+       LASSERT(list_empty(&console_session.ses_grp_list));
+       LASSERT(list_empty(&console_session.ses_bat_list));
+       LASSERT(list_empty(&console_session.ses_trans_list));
 
        for (i = 0; i < LST_NODE_HASHSIZE; i++) {
-               LASSERT (list_empty(&console_session.ses_ndl_hash[i]));
+               LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
        }
 
        LIBCFS_FREE(console_session.ses_ndl_hash,
index f960174ceff8069d9ee9d64a1b61111921645787..e41ca89f10ba0cf817fdfe03e4a9ce2a5452f401 100644 (file)
@@ -182,6 +182,9 @@ lstcon_id2hash (lnet_process_id_t id, struct list_head *hash)
        return &hash[idx];
 }
 
+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);
index 570914828b8c959cd0059c9bb06afc1e40d46c29..a93a90de0f8580be538f4d9d7f1a2d38633387f2 100644 (file)
@@ -115,18 +115,18 @@ static struct smoketest_framework {
 } sfw_data;
 
 /* forward ref's */
-int sfw_stop_batch (sfw_batch_t *tsb, int force);
-void sfw_destroy_session (sfw_session_t *sn);
+int sfw_stop_batch(sfw_batch_t *tsb, int force);
+void sfw_destroy_session(sfw_session_t *sn);
 
 static inline sfw_test_case_t *
 sfw_find_test_case(int id)
 {
        sfw_test_case_t *tsc;
 
-       LASSERT (id <= SRPC_SERVICE_MAX_ID);
-       LASSERT (id > SRPC_FRAMEWORK_SERVICE_MAX_ID);
+       LASSERT(id <= SRPC_SERVICE_MAX_ID);
+       LASSERT(id > SRPC_FRAMEWORK_SERVICE_MAX_ID);
 
-       list_for_each_entry (tsc, &sfw_data.fw_tests, tsc_list) {
+       list_for_each_entry(tsc, &sfw_data.fw_tests, tsc_list) {
                if (tsc->tsc_srv_service->sv_id == id)
                        return tsc;
        }
@@ -135,12 +135,12 @@ sfw_find_test_case(int id)
 }
 
 static int
-sfw_register_test (srpc_service_t *service, sfw_test_client_ops_t *cliops)
+sfw_register_test(srpc_service_t *service, sfw_test_client_ops_t *cliops)
 {
        sfw_test_case_t *tsc;
 
        if (sfw_find_test_case(service->sv_id) != NULL) {
-               CERROR ("Failed to register test %s (%d)\n",
+               CERROR("Failed to register test %s (%d)\n",
                        service->sv_name, service->sv_id);
                return -EEXIST;
        }
@@ -157,17 +157,17 @@ sfw_register_test (srpc_service_t *service, sfw_test_client_ops_t *cliops)
 }
 
 static void
-sfw_add_session_timer (void)
+sfw_add_session_timer(void)
 {
        sfw_session_t *sn = sfw_data.fw_session;
        stt_timer_t   *timer = &sn->sn_timer;
 
-       LASSERT (!sfw_data.fw_shuttingdown);
+       LASSERT(!sfw_data.fw_shuttingdown);
 
        if (sn == NULL || sn->sn_timeout == 0)
                return;
 
-       LASSERT (!sn->sn_timer_active);
+       LASSERT(!sn->sn_timer_active);
 
        sn->sn_timer_active = 1;
        timer->stt_expires = cfs_time_add(sn->sn_timeout,
@@ -177,14 +177,14 @@ sfw_add_session_timer (void)
 }
 
 static int
-sfw_del_session_timer (void)
+sfw_del_session_timer(void)
 {
        sfw_session_t *sn = sfw_data.fw_session;
 
        if (sn == NULL || !sn->sn_timer_active)
                return 0;
 
-       LASSERT (sn->sn_timeout != 0);
+       LASSERT(sn->sn_timeout != 0);
 
        if (stt_del_timer(&sn->sn_timer)) { /* timer defused */
                sn->sn_timer_active = 0;
@@ -195,7 +195,7 @@ sfw_del_session_timer (void)
 }
 
 static void
-sfw_deactivate_session (void)
+sfw_deactivate_session(void)
        __must_hold(&sfw_data.fw_lock)
 {
        sfw_session_t *sn = sfw_data.fw_session;
@@ -205,7 +205,7 @@ sfw_deactivate_session (void)
 
        if (sn == NULL) return;
 
-       LASSERT (!sn->sn_timer_active);
+       LASSERT(!sn->sn_timer_active);
 
        sfw_data.fw_session = NULL;
        atomic_inc(&sfw_data.fw_nzombies);
@@ -219,7 +219,7 @@ sfw_deactivate_session (void)
 
        spin_lock(&sfw_data.fw_lock);
 
-       list_for_each_entry (tsb, &sn->sn_batches, bat_list) {
+       list_for_each_entry(tsb, &sn->sn_batches, bat_list) {
                if (sfw_batch_active(tsb)) {
                        nactive++;
                        sfw_stop_batch(tsb, 1);
@@ -239,16 +239,16 @@ sfw_deactivate_session (void)
 
 
 static void
-sfw_session_expired (void *data)
+sfw_session_expired(void *data)
 {
        sfw_session_t *sn = data;
 
        spin_lock(&sfw_data.fw_lock);
 
-       LASSERT (sn->sn_timer_active);
-       LASSERT (sn == sfw_data.fw_session);
+       LASSERT(sn->sn_timer_active);
+       LASSERT(sn == sfw_data.fw_session);
 
-       CWARN ("Session expired! sid: %s-%llu, name: %s\n",
+       CWARN("Session expired! sid: %s-%llu, name: %s\n",
               libcfs_nid2str(sn->sn_id.ses_nid),
               sn->sn_id.ses_stamp, &sn->sn_name[0]);
 
@@ -290,7 +290,7 @@ sfw_server_rpc_done(struct srpc_server_rpc *rpc)
        struct srpc_service     *sv     = rpc->srpc_scd->scd_svc;
        int                     status  = rpc->srpc_status;
 
-       CDEBUG (D_NET,
+       CDEBUG(D_NET,
                "Incoming framework RPC done: service %s, peer %s, status %s:%d\n",
                sv->sv_name, libcfs_id2str(rpc->srpc_peer),
                swi_state2str(rpc->srpc_wi.swi_state),
@@ -302,13 +302,13 @@ sfw_server_rpc_done(struct srpc_server_rpc *rpc)
 }
 
 static void
-sfw_client_rpc_fini (srpc_client_rpc_t *rpc)
+sfw_client_rpc_fini(srpc_client_rpc_t *rpc)
 {
-       LASSERT (rpc->crpc_bulk.bk_niov == 0);
-       LASSERT (list_empty(&rpc->crpc_list));
-       LASSERT (atomic_read(&rpc->crpc_refcount) == 0);
+       LASSERT(rpc->crpc_bulk.bk_niov == 0);
+       LASSERT(list_empty(&rpc->crpc_list));
+       LASSERT(atomic_read(&rpc->crpc_refcount) == 0);
 
-       CDEBUG (D_NET,
+       CDEBUG(D_NET,
                "Outgoing framework RPC done: service %d, peer %s, status %s:%d:%d\n",
                rpc->crpc_service, libcfs_id2str(rpc->crpc_dest),
                swi_state2str(rpc->crpc_wi.swi_state),
@@ -324,14 +324,14 @@ sfw_client_rpc_fini (srpc_client_rpc_t *rpc)
 }
 
 static sfw_batch_t *
-sfw_find_batch (lst_bid_t bid)
+sfw_find_batch(lst_bid_t bid)
 {
        sfw_session_t *sn = sfw_data.fw_session;
        sfw_batch_t   *bat;
 
-       LASSERT (sn != NULL);
+       LASSERT(sn != NULL);
 
-       list_for_each_entry (bat, &sn->sn_batches, bat_list) {
+       list_for_each_entry(bat, &sn->sn_batches, bat_list) {
                if (bat->bat_id.bat_id == bid.bat_id)
                        return bat;
        }
@@ -340,12 +340,12 @@ sfw_find_batch (lst_bid_t bid)
 }
 
 static sfw_batch_t *
-sfw_bid2batch (lst_bid_t bid)
+sfw_bid2batch(lst_bid_t bid)
 {
        sfw_session_t *sn = sfw_data.fw_session;
        sfw_batch_t   *bat;
 
-       LASSERT (sn != NULL);
+       LASSERT(sn != NULL);
 
        bat = sfw_find_batch(bid);
        if (bat != NULL)
@@ -366,7 +366,7 @@ sfw_bid2batch (lst_bid_t bid)
 }
 
 static int
-sfw_get_stats (srpc_stat_reqst_t *request, srpc_stat_reply_t *reply)
+sfw_get_stats(srpc_stat_reqst_t *request, srpc_stat_reply_t *reply)
 {
        sfw_session_t  *sn = sfw_data.fw_session;
        sfw_counters_t *cnt = &reply->str_fw;
@@ -399,7 +399,7 @@ sfw_get_stats (srpc_stat_reqst_t *request, srpc_stat_reply_t *reply)
        cnt->zombie_sessions = atomic_read(&sfw_data.fw_nzombies);
 
        cnt->active_batches = 0;
-       list_for_each_entry (bat, &sn->sn_batches, bat_list) {
+       list_for_each_entry(bat, &sn->sn_batches, bat_list) {
                if (atomic_read(&bat->bat_nactive) > 0)
                        cnt->active_batches++;
        }
@@ -456,7 +456,7 @@ sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply)
        /* brand new or create by force */
        LIBCFS_ALLOC(sn, sizeof(sfw_session_t));
        if (sn == NULL) {
-               CERROR ("Dropping RPC (mksn) under memory pressure.\n");
+               CERROR("Dropping RPC (mksn) under memory pressure.\n");
                return -ENOMEM;
        }
 
@@ -478,7 +478,7 @@ sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply)
 }
 
 static int
-sfw_remove_session (srpc_rmsn_reqst_t *request, srpc_rmsn_reply_t *reply)
+sfw_remove_session(srpc_rmsn_reqst_t *request, srpc_rmsn_reply_t *reply)
 {
        sfw_session_t *sn = sfw_data.fw_session;
 
@@ -510,7 +510,7 @@ sfw_remove_session (srpc_rmsn_reqst_t *request, srpc_rmsn_reply_t *reply)
 }
 
 static int
-sfw_debug_session (srpc_debug_reqst_t *request, srpc_debug_reply_t *reply)
+sfw_debug_session(srpc_debug_reqst_t *request, srpc_debug_reply_t *reply)
 {
        sfw_session_t *sn = sfw_data.fw_session;
 
@@ -531,13 +531,13 @@ sfw_debug_session (srpc_debug_reqst_t *request, srpc_debug_reply_t *reply)
 }
 
 static void
-sfw_test_rpc_fini (srpc_client_rpc_t *rpc)
+sfw_test_rpc_fini(srpc_client_rpc_t *rpc)
 {
        sfw_test_unit_t     *tsu = rpc->crpc_priv;
        sfw_test_instance_t *tsi = tsu->tsu_instance;
 
        /* Called with hold of tsi->tsi_lock */
-       LASSERT (list_empty(&rpc->crpc_list));
+       LASSERT(list_empty(&rpc->crpc_list));
        list_add(&rpc->crpc_list, &tsi->tsi_free_rpcs);
 }
 
@@ -608,7 +608,7 @@ sfw_unload_test(struct sfw_test_instance *tsi)
 }
 
 static void
-sfw_destroy_test_instance (sfw_test_instance_t *tsi)
+sfw_destroy_test_instance(sfw_test_instance_t *tsi)
 {
        srpc_client_rpc_t *rpc;
        sfw_test_unit_t   *tsu;
@@ -617,9 +617,9 @@ sfw_destroy_test_instance (sfw_test_instance_t *tsi)
 
        tsi->tsi_ops->tso_fini(tsi);
 
-       LASSERT (!tsi->tsi_stopping);
-       LASSERT (list_empty(&tsi->tsi_active_rpcs));
-       LASSERT (!sfw_test_active(tsi));
+       LASSERT(!tsi->tsi_stopping);
+       LASSERT(list_empty(&tsi->tsi_active_rpcs));
+       LASSERT(!sfw_test_active(tsi));
 
        while (!list_empty(&tsi->tsi_units)) {
                tsu = list_entry(tsi->tsi_units.next,
@@ -642,12 +642,12 @@ clean:
 }
 
 static void
-sfw_destroy_batch (sfw_batch_t *tsb)
+sfw_destroy_batch(sfw_batch_t *tsb)
 {
        sfw_test_instance_t *tsi;
 
-       LASSERT (!sfw_batch_active(tsb));
-       LASSERT (list_empty(&tsb->bat_list));
+       LASSERT(!sfw_batch_active(tsb));
+       LASSERT(list_empty(&tsb->bat_list));
 
        while (!list_empty(&tsb->bat_tests)) {
                tsi = list_entry(tsb->bat_tests.next,
@@ -661,12 +661,12 @@ sfw_destroy_batch (sfw_batch_t *tsb)
 }
 
 void
-sfw_destroy_session (sfw_session_t *sn)
+sfw_destroy_session(sfw_session_t *sn)
 {
        sfw_batch_t *batch;
 
-       LASSERT (list_empty(&sn->sn_list));
-       LASSERT (sn != sfw_data.fw_session);
+       LASSERT(list_empty(&sn->sn_list));
+       LASSERT(sn != sfw_data.fw_session);
 
        while (!list_empty(&sn->sn_batches)) {
                batch = list_entry(sn->sn_batches.next,
@@ -685,13 +685,13 @@ sfw_unpack_addtest_req(srpc_msg_t *msg)
 {
        srpc_test_reqst_t *req = &msg->msg_body.tes_reqst;
 
-       LASSERT (msg->msg_type == SRPC_MSG_TEST_REQST);
-       LASSERT (req->tsr_is_client);
+       LASSERT(msg->msg_type == SRPC_MSG_TEST_REQST);
+       LASSERT(req->tsr_is_client);
 
        if (msg->msg_magic == SRPC_MSG_MAGIC)
                return; /* no flipping needed */
 
-       LASSERT (msg->msg_magic == __swab32(SRPC_MSG_MAGIC));
+       LASSERT(msg->msg_magic == __swab32(SRPC_MSG_MAGIC));
 
        if (req->tsr_service == SRPC_SERVICE_BRW) {
                if ((msg->msg_ses_feats & LST_FEAT_BULK_LEN) == 0) {
@@ -721,12 +721,12 @@ sfw_unpack_addtest_req(srpc_msg_t *msg)
                return;
        }
 
-       LBUG ();
+       LBUG();
        return;
 }
 
 static int
-sfw_add_test_instance (sfw_batch_t *tsb, srpc_server_rpc_t *rpc)
+sfw_add_test_instance(sfw_batch_t *tsb, srpc_server_rpc_t *rpc)
 {
        srpc_msg_t        *msg = &rpc->srpc_reqstbuf->buf_msg;
        srpc_test_reqst_t   *req = &msg->msg_body.tes_reqst;
@@ -739,7 +739,7 @@ sfw_add_test_instance (sfw_batch_t *tsb, srpc_server_rpc_t *rpc)
 
        LIBCFS_ALLOC(tsi, sizeof(*tsi));
        if (tsi == NULL) {
-               CERROR ("Can't allocate test instance for batch: %llu\n",
+               CERROR("Can't allocate test instance for batch: %llu\n",
                        tsb->bat_id.bat_id);
                return -ENOMEM;
        }
@@ -764,7 +764,7 @@ sfw_add_test_instance (sfw_batch_t *tsb, srpc_server_rpc_t *rpc)
                return rc;
        }
 
-       LASSERT (!sfw_batch_active(tsb));
+       LASSERT(!sfw_batch_active(tsb));
 
        if (!tsi->tsi_is_client) {
                /* it's test server, just add it to tsb */
@@ -772,8 +772,8 @@ sfw_add_test_instance (sfw_batch_t *tsb, srpc_server_rpc_t *rpc)
                return 0;
        }
 
-       LASSERT (bk != NULL);
-       LASSERT (bk->bk_niov * SFW_ID_PER_PAGE >= (unsigned int)ndest);
+       LASSERT(bk != NULL);
+       LASSERT(bk->bk_niov * SFW_ID_PER_PAGE >= (unsigned int)ndest);
        LASSERT((unsigned int)bk->bk_len >=
                sizeof(lnet_process_id_packed_t) * ndest);
 
@@ -786,7 +786,7 @@ sfw_add_test_instance (sfw_batch_t *tsb, srpc_server_rpc_t *rpc)
                int                    j;
 
                dests = page_address(bk->bk_iovs[i / SFW_ID_PER_PAGE].kiov_page);
-               LASSERT (dests != NULL);  /* my pages are within KVM always */
+               LASSERT(dests != NULL);  /* my pages are within KVM always */
                id = dests[i % SFW_ID_PER_PAGE];
                if (msg->msg_magic != SRPC_MSG_MAGIC)
                        sfw_unpack_id(id);
@@ -795,7 +795,7 @@ sfw_add_test_instance (sfw_batch_t *tsb, srpc_server_rpc_t *rpc)
                        LIBCFS_ALLOC(tsu, sizeof(sfw_test_unit_t));
                        if (tsu == NULL) {
                                rc = -ENOMEM;
-                               CERROR ("Can't allocate tsu for %d\n",
+                               CERROR("Can't allocate tsu for %d\n",
                                        tsi->tsi_service);
                                goto error;
                        }
@@ -815,19 +815,19 @@ sfw_add_test_instance (sfw_batch_t *tsb, srpc_server_rpc_t *rpc)
        }
 
 error:
-       LASSERT (rc != 0);
+       LASSERT(rc != 0);
        sfw_destroy_test_instance(tsi);
        return rc;
 }
 
 static void
-sfw_test_unit_done (sfw_test_unit_t *tsu)
+sfw_test_unit_done(sfw_test_unit_t *tsu)
 {
        sfw_test_instance_t *tsi = tsu->tsu_instance;
        sfw_batch_t      *tsb = tsi->tsi_batch;
        sfw_session_t       *sn = tsb->bat_session;
 
-       LASSERT (sfw_test_active(tsi));
+       LASSERT(sfw_test_active(tsi));
 
        if (!atomic_dec_and_test(&tsi->tsi_nactive))
                return;
@@ -847,9 +847,9 @@ sfw_test_unit_done (sfw_test_unit_t *tsu)
                return;
        }
 
-       LASSERT (!list_empty(&sn->sn_list)); /* I'm a zombie! */
+       LASSERT(!list_empty(&sn->sn_list)); /* I'm a zombie! */
 
-       list_for_each_entry (tsb, &sn->sn_batches, bat_list) {
+       list_for_each_entry(tsb, &sn->sn_batches, bat_list) {
                if (sfw_batch_active(tsb)) {
                        spin_unlock(&sfw_data.fw_lock);
                        return;
@@ -864,7 +864,7 @@ sfw_test_unit_done (sfw_test_unit_t *tsu)
 }
 
 static void
-sfw_test_rpc_done (srpc_client_rpc_t *rpc)
+sfw_test_rpc_done(srpc_client_rpc_t *rpc)
 {
        sfw_test_unit_t     *tsu = rpc->crpc_priv;
        sfw_test_instance_t *tsi = tsu->tsu_instance;
@@ -874,8 +874,8 @@ sfw_test_rpc_done (srpc_client_rpc_t *rpc)
 
        spin_lock(&tsi->tsi_lock);
 
-       LASSERT (sfw_test_active(tsi));
-       LASSERT (!list_empty(&rpc->crpc_list));
+       LASSERT(sfw_test_active(tsi));
+       LASSERT(!list_empty(&rpc->crpc_list));
 
        list_del_init(&rpc->crpc_list);
 
@@ -909,13 +909,13 @@ sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer,
 
        spin_lock(&tsi->tsi_lock);
 
-       LASSERT (sfw_test_active(tsi));
+       LASSERT(sfw_test_active(tsi));
 
        if (!list_empty(&tsi->tsi_free_rpcs)) {
                /* pick request from buffer */
                rpc = list_entry(tsi->tsi_free_rpcs.next,
                                     srpc_client_rpc_t, crpc_list);
-               LASSERT (nblk == rpc->crpc_bulk.bk_niov);
+               LASSERT(nblk == rpc->crpc_bulk.bk_niov);
                list_del_init(&rpc->crpc_list);
        }
 
@@ -943,20 +943,20 @@ sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer,
 }
 
 static int
-sfw_run_test (swi_workitem_t *wi)
+sfw_run_test(swi_workitem_t *wi)
 {
        sfw_test_unit_t     *tsu = wi->swi_workitem.wi_data;
        sfw_test_instance_t *tsi = tsu->tsu_instance;
        srpc_client_rpc_t   *rpc = NULL;
 
-       LASSERT (wi == &tsu->tsu_worker);
+       LASSERT(wi == &tsu->tsu_worker);
 
        if (tsi->tsi_ops->tso_prep_rpc(tsu, tsu->tsu_dest, &rpc) != 0) {
-               LASSERT (rpc == NULL);
+               LASSERT(rpc == NULL);
                goto test_done;
        }
 
-       LASSERT (rpc != NULL);
+       LASSERT(rpc != NULL);
 
        spin_lock(&tsi->tsi_lock);
 
@@ -993,7 +993,7 @@ test_done:
 }
 
 static int
-sfw_run_batch (sfw_batch_t *tsb)
+sfw_run_batch(sfw_batch_t *tsb)
 {
        swi_workitem_t      *wi;
        sfw_test_unit_t     *tsu;
@@ -1005,16 +1005,16 @@ sfw_run_batch (sfw_batch_t *tsb)
                return 0;
        }
 
-       list_for_each_entry (tsi, &tsb->bat_tests, tsi_list) {
+       list_for_each_entry(tsi, &tsb->bat_tests, tsi_list) {
                if (!tsi->tsi_is_client) /* skip server instances */
                        continue;
 
-               LASSERT (!tsi->tsi_stopping);
-               LASSERT (!sfw_test_active(tsi));
+               LASSERT(!tsi->tsi_stopping);
+               LASSERT(!sfw_test_active(tsi));
 
                atomic_inc(&tsb->bat_nactive);
 
-               list_for_each_entry (tsu, &tsi->tsi_units, tsu_list) {
+               list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) {
                        atomic_inc(&tsi->tsi_nactive);
                        tsu->tsu_loop = tsi->tsi_loop;
                        wi = &tsu->tsu_worker;
@@ -1029,7 +1029,7 @@ sfw_run_batch (sfw_batch_t *tsb)
 }
 
 int
-sfw_stop_batch (sfw_batch_t *tsb, int force)
+sfw_stop_batch(sfw_batch_t *tsb, int force)
 {
        sfw_test_instance_t *tsi;
        srpc_client_rpc_t   *rpc;
@@ -1039,7 +1039,7 @@ sfw_stop_batch (sfw_batch_t *tsb, int force)
                return 0;
        }
 
-       list_for_each_entry (tsi, &tsb->bat_tests, tsi_list) {
+       list_for_each_entry(tsi, &tsb->bat_tests, tsi_list) {
                spin_lock(&tsi->tsi_lock);
 
                if (!tsi->tsi_is_client ||
@@ -1071,7 +1071,7 @@ sfw_stop_batch (sfw_batch_t *tsb, int force)
 }
 
 static int
-sfw_query_batch (sfw_batch_t *tsb, int testidx, srpc_batch_reply_t *reply)
+sfw_query_batch(sfw_batch_t *tsb, int testidx, srpc_batch_reply_t *reply)
 {
        sfw_test_instance_t *tsi;
 
@@ -1083,7 +1083,7 @@ sfw_query_batch (sfw_batch_t *tsb, int testidx, srpc_batch_reply_t *reply)
                return 0;
        }
 
-       list_for_each_entry (tsi, &tsb->bat_tests, tsi_list) {
+       list_for_each_entry(tsi, &tsb->bat_tests, tsi_list) {
                if (testidx-- > 1)
                        continue;
 
@@ -1095,7 +1095,7 @@ sfw_query_batch (sfw_batch_t *tsb, int testidx, srpc_batch_reply_t *reply)
 }
 
 void
-sfw_free_pages (srpc_server_rpc_t *rpc)
+sfw_free_pages(srpc_server_rpc_t *rpc)
 {
        srpc_free_bulk(rpc->srpc_bulk);
        rpc->srpc_bulk = NULL;
@@ -1116,7 +1116,7 @@ sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len,
 }
 
 static int
-sfw_add_test (srpc_server_rpc_t *rpc)
+sfw_add_test(srpc_server_rpc_t *rpc)
 {
        sfw_session_t     *sn = sfw_data.fw_session;
        srpc_test_reply_t *reply = &rpc->srpc_replymsg.msg_body.tes_reply;
@@ -1147,7 +1147,7 @@ sfw_add_test (srpc_server_rpc_t *rpc)
 
        bat = sfw_bid2batch(request->tsr_bid);
        if (bat == NULL) {
-               CERROR ("Dropping RPC (%s) from %s under memory pressure.\n",
+               CERROR("Dropping RPC (%s) from %s under memory pressure.\n",
                        rpc->srpc_scd->scd_svc->sv_name,
                        libcfs_id2str(rpc->srpc_peer));
                return -ENOMEM;
@@ -1175,7 +1175,7 @@ sfw_add_test (srpc_server_rpc_t *rpc)
        }
 
        rc = sfw_add_test_instance(bat, rpc);
-       CDEBUG (rc == 0 ? D_NET : D_WARNING,
+       CDEBUG(rc == 0 ? D_NET : D_WARNING,
                "%s test: sv %d %s, loop %d, concur %d, ndest %d\n",
                rc == 0 ? "Added" : "Failed to add", request->tsr_service,
                request->tsr_is_client ? "client" : "server",
@@ -1186,7 +1186,7 @@ sfw_add_test (srpc_server_rpc_t *rpc)
 }
 
 static int
-sfw_control_batch (srpc_batch_reqst_t *request, srpc_batch_reply_t *reply)
+sfw_control_batch(srpc_batch_reqst_t *request, srpc_batch_reply_t *reply)
 {
        sfw_session_t *sn = sfw_data.fw_session;
        int         rc = 0;
@@ -1285,7 +1285,7 @@ sfw_handle_server_rpc(struct srpc_server_rpc *rpc)
 
        switch (sv->sv_id) {
        default:
-               LBUG ();
+               LBUG();
        case SRPC_SERVICE_TEST:
                rc = sfw_add_test(rpc);
                break;
@@ -1387,8 +1387,8 @@ sfw_create_rpc(lnet_process_id_t peer, int service,
 
        spin_lock(&sfw_data.fw_lock);
 
-       LASSERT (!sfw_data.fw_shuttingdown);
-       LASSERT (service <= SRPC_FRAMEWORK_SERVICE_MAX_ID);
+       LASSERT(!sfw_data.fw_shuttingdown);
+       LASSERT(service <= SRPC_FRAMEWORK_SERVICE_MAX_ID);
 
        if (nbulkiov == 0 && !list_empty(&sfw_data.fw_zombie_rpcs)) {
                rpc = list_entry(sfw_data.fw_zombie_rpcs.next,
@@ -1416,13 +1416,13 @@ sfw_create_rpc(lnet_process_id_t peer, int service,
 }
 
 void
-sfw_unpack_message (srpc_msg_t *msg)
+sfw_unpack_message(srpc_msg_t *msg)
 {
        if (msg->msg_magic == SRPC_MSG_MAGIC)
                return; /* no flipping needed */
 
        /* srpc module should guarantee I wouldn't get crap */
-       LASSERT (msg->msg_magic == __swab32(SRPC_MSG_MAGIC));
+       LASSERT(msg->msg_magic == __swab32(SRPC_MSG_MAGIC));
 
        if (msg->msg_type == SRPC_MSG_STAT_REQST) {
                srpc_stat_reqst_t *req = &msg->msg_body.stat_reqst;
@@ -1555,12 +1555,12 @@ sfw_unpack_message (srpc_msg_t *msg)
                return;
        }
 
-       LBUG ();
+       LBUG();
        return;
 }
 
 void
-sfw_abort_rpc (srpc_client_rpc_t *rpc)
+sfw_abort_rpc(srpc_client_rpc_t *rpc)
 {
        LASSERT(atomic_read(&rpc->crpc_refcount) > 0);
        LASSERT(rpc->crpc_service <= SRPC_FRAMEWORK_SERVICE_MAX_ID);
@@ -1572,14 +1572,14 @@ sfw_abort_rpc (srpc_client_rpc_t *rpc)
 }
 
 void
-sfw_post_rpc (srpc_client_rpc_t *rpc)
+sfw_post_rpc(srpc_client_rpc_t *rpc)
 {
        spin_lock(&rpc->crpc_lock);
 
-       LASSERT (!rpc->crpc_closed);
-       LASSERT (!rpc->crpc_aborted);
-       LASSERT (list_empty(&rpc->crpc_list));
-       LASSERT (!sfw_data.fw_shuttingdown);
+       LASSERT(!rpc->crpc_closed);
+       LASSERT(!rpc->crpc_aborted);
+       LASSERT(list_empty(&rpc->crpc_list));
+       LASSERT(!sfw_data.fw_shuttingdown);
 
        rpc->crpc_timeout = rpc_timeout;
        srpc_post_rpc(rpc);
@@ -1638,7 +1638,7 @@ extern void brw_init_test_service(void);
 
 
 int
-sfw_startup (void)
+sfw_startup(void)
 {
        int           i;
        int           rc;
@@ -1648,13 +1648,13 @@ sfw_startup (void)
 
 
        if (session_timeout < 0) {
-               CERROR ("Session timeout must be non-negative: %d\n",
+               CERROR("Session timeout must be non-negative: %d\n",
                        session_timeout);
                return -EINVAL;
        }
 
        if (rpc_timeout < 0) {
-               CERROR ("RPC timeout must be non-negative: %d\n",
+               CERROR("RPC timeout must be non-negative: %d\n",
                        rpc_timeout);
                return -EINVAL;
        }
@@ -1678,21 +1678,21 @@ sfw_startup (void)
        brw_init_test_client();
        brw_init_test_service();
        rc = sfw_register_test(&brw_test_service, &brw_test_client);
-       LASSERT (rc == 0);
+       LASSERT(rc == 0);
 
        ping_init_test_client();
        ping_init_test_service();
        rc = sfw_register_test(&ping_test_service, &ping_test_client);
-       LASSERT (rc == 0);
+       LASSERT(rc == 0);
 
        error = 0;
-       list_for_each_entry (tsc, &sfw_data.fw_tests, tsc_list) {
+       list_for_each_entry(tsc, &sfw_data.fw_tests, tsc_list) {
                sv = tsc->tsc_srv_service;
 
                rc = srpc_add_service(sv);
-               LASSERT (rc != -EBUSY);
+               LASSERT(rc != -EBUSY);
                if (rc != 0) {
-                       CWARN ("Failed to add %s service: %d\n",
+                       CWARN("Failed to add %s service: %d\n",
                               sv->sv_name, rc);
                        error = rc;
                }
@@ -1709,9 +1709,9 @@ sfw_startup (void)
                        sv->sv_bulk_ready = sfw_bulk_ready;
 
                rc = srpc_add_service(sv);
-               LASSERT (rc != -EBUSY);
+               LASSERT(rc != -EBUSY);
                if (rc != 0) {
-                       CWARN ("Failed to add %s service: %d\n",
+                       CWARN("Failed to add %s service: %d\n",
                               sv->sv_name, rc);
                        error = rc;
                }
@@ -1733,7 +1733,7 @@ sfw_startup (void)
 }
 
 void
-sfw_shutdown (void)
+sfw_shutdown(void)
 {
        srpc_service_t  *sv;
        sfw_test_case_t *tsc;
@@ -1766,7 +1766,7 @@ sfw_shutdown (void)
                srpc_remove_service(sv);
        }
 
-       list_for_each_entry (tsc, &sfw_data.fw_tests, tsc_list) {
+       list_for_each_entry(tsc, &sfw_data.fw_tests, tsc_list) {
                sv = tsc->tsc_srv_service;
                srpc_shutdown_service(sv);
                srpc_remove_service(sv);
index faf4098023726a073f959f06887fe35ccb4b778c..7ad62f167ceaa0fae63b3c9caa93aa6c9dbdbe99 100644 (file)
@@ -87,7 +87,6 @@ lnet_selftest_fini(void)
        default:
                LBUG();
        }
-       return;
 }
 
 static int
index d8c0df6e68528e8ad998ebd688370106495aebf1..644069a9fe4e93b5144361e012f2a2e1c43a3ef0 100644 (file)
@@ -70,19 +70,19 @@ ping_client_init(sfw_test_instance_t *tsi)
 }
 
 static void
-ping_client_fini (sfw_test_instance_t *tsi)
+ping_client_fini(sfw_test_instance_t *tsi)
 {
        sfw_session_t *sn = tsi->tsi_batch->bat_session;
        int         errors;
 
-       LASSERT (sn != NULL);
-       LASSERT (tsi->tsi_is_client);
+       LASSERT(sn != NULL);
+       LASSERT(tsi->tsi_is_client);
 
        errors = atomic_read(&sn->sn_ping_errors);
        if (errors)
-               CWARN ("%d pings have failed.\n", errors);
+               CWARN("%d pings have failed.\n", errors);
        else
-               CDEBUG (D_NET, "Ping test finished OK.\n");
+               CDEBUG(D_NET, "Ping test finished OK.\n");
 }
 
 static int
@@ -118,7 +118,7 @@ ping_client_prep_rpc(sfw_test_unit_t *tsu,
 }
 
 static void
-ping_client_done_rpc (sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc)
+ping_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc)
 {
        sfw_test_instance_t *tsi = tsu->tsu_instance;
        sfw_session_t       *sn = tsi->tsi_batch->bat_session;
@@ -126,12 +126,12 @@ ping_client_done_rpc (sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc)
        srpc_ping_reply_t   *reply = &rpc->crpc_replymsg.msg_body.ping_reply;
        struct timeval       tv;
 
-       LASSERT (sn != NULL);
+       LASSERT(sn != NULL);
 
        if (rpc->crpc_status != 0) {
                if (!tsi->tsi_stopping) /* rpc could have been aborted */
                        atomic_inc(&sn->sn_ping_errors);
-               CERROR ("Unable to ping %s (%d): %d\n",
+               CERROR("Unable to ping %s (%d): %d\n",
                        libcfs_id2str(rpc->crpc_dest),
                        reqst->pnr_seq, rpc->crpc_status);
                return;
@@ -146,7 +146,7 @@ ping_client_done_rpc (sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc)
        if (reply->pnr_magic != LST_PING_TEST_MAGIC) {
                rpc->crpc_status = -EBADMSG;
                atomic_inc(&sn->sn_ping_errors);
-               CERROR ("Bad magic %u from %s, %u expected.\n",
+               CERROR("Bad magic %u from %s, %u expected.\n",
                        reply->pnr_magic, libcfs_id2str(rpc->crpc_dest),
                        LST_PING_TEST_MAGIC);
                return;
@@ -155,14 +155,14 @@ ping_client_done_rpc (sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc)
        if (reply->pnr_seq != reqst->pnr_seq) {
                rpc->crpc_status = -EBADMSG;
                atomic_inc(&sn->sn_ping_errors);
-               CERROR ("Bad seq %u from %s, %u expected.\n",
+               CERROR("Bad seq %u from %s, %u expected.\n",
                        reply->pnr_seq, libcfs_id2str(rpc->crpc_dest),
                        reqst->pnr_seq);
                return;
        }
 
        cfs_fs_timeval(&tv);
-       CDEBUG (D_NET, "%d reply in %u usec\n", reply->pnr_seq,
+       CDEBUG(D_NET, "%d reply in %u usec\n", reply->pnr_seq,
                (unsigned)((tv.tv_sec - (unsigned)reqst->pnr_time_sec) * 1000000
                           + (tv.tv_usec - reqst->pnr_time_usec)));
        return;
@@ -177,20 +177,20 @@ ping_server_handle(struct srpc_server_rpc *rpc)
        srpc_ping_reqst_t *req = &reqstmsg->msg_body.ping_reqst;
        srpc_ping_reply_t *rep = &rpc->srpc_replymsg.msg_body.ping_reply;
 
-       LASSERT (sv->sv_id == SRPC_SERVICE_PING);
+       LASSERT(sv->sv_id == SRPC_SERVICE_PING);
 
        if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) {
-               LASSERT (reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC));
+               LASSERT(reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC));
 
                __swab32s(&req->pnr_seq);
                __swab32s(&req->pnr_magic);
                __swab64s(&req->pnr_time_sec);
                __swab64s(&req->pnr_time_usec);
        }
-       LASSERT (reqstmsg->msg_type == srpc_service2request(sv->sv_id));
+       LASSERT(reqstmsg->msg_type == srpc_service2request(sv->sv_id));
 
        if (req->pnr_magic != LST_PING_TEST_MAGIC) {
-               CERROR ("Unexpected magic %08x from %s\n",
+               CERROR("Unexpected magic %08x from %s\n",
                        req->pnr_magic, libcfs_id2str(rpc->srpc_peer));
                return -EINVAL;
        }
index 1f7d9a6248db870b585ba09e8798a8769084f44c..080788ab749ef969fec02cf30cacb6729608d445 100644 (file)
@@ -71,16 +71,16 @@ srpc_serv_portal(int svc_id)
 }
 
 /* forward ref's */
-int srpc_handle_rpc (swi_workitem_t *wi);
+int srpc_handle_rpc(swi_workitem_t *wi);
 
-void srpc_get_counters (srpc_counters_t *cnt)
+void srpc_get_counters(srpc_counters_t *cnt)
 {
        spin_lock(&srpc_data.rpc_glock);
        *cnt = srpc_data.rpc_counters;
        spin_unlock(&srpc_data.rpc_glock);
 }
 
-void srpc_set_counters (const srpc_counters_t *cnt)
+void srpc_set_counters(const srpc_counters_t *cnt)
 {
        spin_lock(&srpc_data.rpc_glock);
        srpc_data.rpc_counters = *cnt;
@@ -102,16 +102,17 @@ srpc_add_bulk_page(srpc_bulk_t *bk, struct page *pg, int i, int nob)
 }
 
 void
-srpc_free_bulk (srpc_bulk_t *bk)
+srpc_free_bulk(srpc_bulk_t *bk)
 {
        int      i;
        struct page *pg;
 
-       LASSERT (bk != NULL);
+       LASSERT(bk != NULL);
 
        for (i = 0; i < bk->bk_niov; i++) {
                pg = bk->bk_iovs[i].kiov_page;
-               if (pg == NULL) break;
+               if (pg == NULL)
+                       break;
 
                __free_page(pg);
        }
@@ -160,7 +161,7 @@ srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, int sink)
 }
 
 static inline __u64
-srpc_next_id (void)
+srpc_next_id(void)
 {
        __u64 id;
 
@@ -335,7 +336,7 @@ srpc_add_service(struct srpc_service *sv)
 }
 
 int
-srpc_remove_service (srpc_service_t *sv)
+srpc_remove_service(srpc_service_t *sv)
 {
        int id = sv->sv_id;
 
@@ -363,8 +364,8 @@ srpc_post_passive_rdma(int portal, int local, __u64 matchbits, void *buf,
        rc = LNetMEAttach(portal, peer, matchbits, 0, LNET_UNLINK,
                          local ? LNET_INS_LOCAL : LNET_INS_AFTER, &meh);
        if (rc != 0) {
-               CERROR ("LNetMEAttach failed: %d\n", rc);
-               LASSERT (rc == -ENOMEM);
+               CERROR("LNetMEAttach failed: %d\n", rc);
+               LASSERT(rc == -ENOMEM);
                return -ENOMEM;
        }
 
@@ -377,15 +378,15 @@ srpc_post_passive_rdma(int portal, int local, __u64 matchbits, void *buf,
 
        rc = LNetMDAttach(meh, md, LNET_UNLINK, mdh);
        if (rc != 0) {
-               CERROR ("LNetMDAttach failed: %d\n", rc);
-               LASSERT (rc == -ENOMEM);
+               CERROR("LNetMDAttach failed: %d\n", rc);
+               LASSERT(rc == -ENOMEM);
 
                rc = LNetMEUnlink(meh);
-               LASSERT (rc == 0);
+               LASSERT(rc == 0);
                return -ENOMEM;
        }
 
-       CDEBUG (D_NET,
+       CDEBUG(D_NET,
                "Posted passive RDMA: peer %s, portal %d, matchbits %#llx\n",
                libcfs_id2str(peer), portal, matchbits);
        return 0;
@@ -408,8 +409,8 @@ srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len,
 
        rc = LNetMDBind(md, LNET_UNLINK, mdh);
        if (rc != 0) {
-               CERROR ("LNetMDBind failed: %d\n", rc);
-               LASSERT (rc == -ENOMEM);
+               CERROR("LNetMDBind failed: %d\n", rc);
+               LASSERT(rc == -ENOMEM);
                return -ENOMEM;
        }
 
@@ -420,13 +421,13 @@ srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len,
                rc = LNetPut(self, *mdh, LNET_NOACK_REQ, peer,
                             portal, matchbits, 0, 0);
        } else {
-               LASSERT ((options & LNET_MD_OP_GET) != 0);
+               LASSERT((options & LNET_MD_OP_GET) != 0);
 
                rc = LNetGet(self, *mdh, peer, portal, matchbits, 0);
        }
 
        if (rc != 0) {
-               CERROR ("LNet%s(%s, %d, %lld) failed: %d\n",
+               CERROR("LNet%s(%s, %d, %lld) failed: %d\n",
                        ((options & LNET_MD_OP_PUT) != 0) ? "Put" : "Get",
                        libcfs_id2str(peer), portal, matchbits, rc);
 
@@ -434,9 +435,9 @@ srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len,
                 * with failure, so fall through and return success here.
                 */
                rc = LNetMDUnlink(*mdh);
-               LASSERT (rc == 0);
+               LASSERT(rc == 0);
        } else {
-               CDEBUG (D_NET,
+               CDEBUG(D_NET,
                        "Posted active RDMA: peer %s, portal %u, matchbits %#llx\n",
                        libcfs_id2str(peer), portal, matchbits);
        }
@@ -788,7 +789,7 @@ srpc_shutdown_service(srpc_service_t *sv)
 }
 
 static int
-srpc_send_request (srpc_client_rpc_t *rpc)
+srpc_send_request(srpc_client_rpc_t *rpc)
 {
        srpc_event_t *ev = &rpc->crpc_reqstev;
        int        rc;
@@ -801,14 +802,14 @@ srpc_send_request (srpc_client_rpc_t *rpc)
                                     &rpc->crpc_reqstmsg, sizeof(srpc_msg_t),
                                     &rpc->crpc_reqstmdh, ev);
        if (rc != 0) {
-               LASSERT (rc == -ENOMEM);
+               LASSERT(rc == -ENOMEM);
                ev->ev_fired = 1;  /* no more event expected */
        }
        return rc;
 }
 
 static int
-srpc_prepare_reply (srpc_client_rpc_t *rpc)
+srpc_prepare_reply(srpc_client_rpc_t *rpc)
 {
        srpc_event_t *ev = &rpc->crpc_replyev;
        __u64   *id = &rpc->crpc_reqstmsg.msg_body.reqst.rpyid;
@@ -825,14 +826,14 @@ srpc_prepare_reply (srpc_client_rpc_t *rpc)
                                    LNET_MD_OP_PUT, rpc->crpc_dest,
                                    &rpc->crpc_replymdh, ev);
        if (rc != 0) {
-               LASSERT (rc == -ENOMEM);
+               LASSERT(rc == -ENOMEM);
                ev->ev_fired = 1;  /* no more event expected */
        }
        return rc;
 }
 
 static int
-srpc_prepare_bulk (srpc_client_rpc_t *rpc)
+srpc_prepare_bulk(srpc_client_rpc_t *rpc)
 {
        srpc_bulk_t  *bk = &rpc->crpc_bulk;
        srpc_event_t *ev = &rpc->crpc_bulkev;
@@ -840,9 +841,10 @@ srpc_prepare_bulk (srpc_client_rpc_t *rpc)
        int        rc;
        int        opt;
 
-       LASSERT (bk->bk_niov <= LNET_MAX_IOV);
+       LASSERT(bk->bk_niov <= LNET_MAX_IOV);
 
-       if (bk->bk_niov == 0) return 0; /* nothing to do */
+       if (bk->bk_niov == 0)
+               return 0; /* nothing to do */
 
        opt = bk->bk_sink ? LNET_MD_OP_PUT : LNET_MD_OP_GET;
        opt |= LNET_MD_KIOV;
@@ -857,14 +859,14 @@ srpc_prepare_bulk (srpc_client_rpc_t *rpc)
                                    &bk->bk_iovs[0], bk->bk_niov, opt,
                                    rpc->crpc_dest, &bk->bk_mdh, ev);
        if (rc != 0) {
-               LASSERT (rc == -ENOMEM);
+               LASSERT(rc == -ENOMEM);
                ev->ev_fired = 1;  /* no more event expected */
        }
        return rc;
 }
 
 static int
-srpc_do_bulk (srpc_server_rpc_t *rpc)
+srpc_do_bulk(srpc_server_rpc_t *rpc)
 {
        srpc_event_t  *ev = &rpc->srpc_ev;
        srpc_bulk_t   *bk = rpc->srpc_bulk;
@@ -872,7 +874,7 @@ srpc_do_bulk (srpc_server_rpc_t *rpc)
        int         rc;
        int         opt;
 
-       LASSERT (bk != NULL);
+       LASSERT(bk != NULL);
 
        opt = bk->bk_sink ? LNET_MD_OP_GET : LNET_MD_OP_PUT;
        opt |= LNET_MD_KIOV;
@@ -898,11 +900,11 @@ srpc_server_rpc_done(srpc_server_rpc_t *rpc, int status)
        struct srpc_service     *sv  = scd->scd_svc;
        srpc_buffer_t           *buffer;
 
-       LASSERT (status != 0 || rpc->srpc_wi.swi_state == SWI_STATE_DONE);
+       LASSERT(status != 0 || rpc->srpc_wi.swi_state == SWI_STATE_DONE);
 
        rpc->srpc_status = status;
 
-       CDEBUG_LIMIT (status == 0 ? D_NET : D_NETERROR,
+       CDEBUG_LIMIT(status == 0 ? D_NET : D_NETERROR,
                "Server RPC %p done: service %s, peer %s, status %s:%d\n",
                rpc, sv->sv_name, libcfs_id2str(rpc->srpc_peer),
                swi_state2str(rpc->srpc_wi.swi_state), status);
@@ -985,7 +987,7 @@ srpc_handle_rpc(swi_workitem_t *wi)
 
        switch (wi->swi_state) {
        default:
-               LBUG ();
+               LBUG();
        case SWI_STATE_NEWBORN: {
                srpc_msg_t         *msg;
                srpc_generic_reply_t *reply;
@@ -1023,12 +1025,12 @@ srpc_handle_rpc(swi_workitem_t *wi)
                        if (rc == 0)
                                return 0; /* wait for bulk */
 
-                       LASSERT (ev->ev_fired);
+                       LASSERT(ev->ev_fired);
                        ev->ev_status = rc;
                }
        }
        case SWI_STATE_BULK_STARTED:
-               LASSERT (rpc->srpc_bulk == NULL || ev->ev_fired);
+               LASSERT(rpc->srpc_bulk == NULL || ev->ev_fired);
 
                if (rpc->srpc_bulk != NULL) {
                        rc = ev->ev_status;
@@ -1055,7 +1057,7 @@ srpc_handle_rpc(swi_workitem_t *wi)
                               rpc, rpc->srpc_bulk, sv->sv_id);
                        CERROR("Event: status %d, type %d, lnet %d\n",
                               ev->ev_status, ev->ev_type, ev->ev_lnet);
-                       LASSERT (ev->ev_fired);
+                       LASSERT(ev->ev_fired);
                }
 
                wi->swi_state = SWI_STATE_DONE;
@@ -1067,11 +1069,11 @@ srpc_handle_rpc(swi_workitem_t *wi)
 }
 
 static void
-srpc_client_rpc_expired (void *data)
+srpc_client_rpc_expired(void *data)
 {
        srpc_client_rpc_t *rpc = data;
 
-       CWARN ("Client RPC expired: service %d, peer %s, timeout %d.\n",
+       CWARN("Client RPC expired: service %d, peer %s, timeout %d.\n",
               rpc->crpc_service, libcfs_id2str(rpc->crpc_dest),
               rpc->crpc_timeout);
 
@@ -1088,11 +1090,12 @@ srpc_client_rpc_expired (void *data)
 }
 
 inline void
-srpc_add_client_rpc_timer (srpc_client_rpc_t *rpc)
+srpc_add_client_rpc_timer(srpc_client_rpc_t *rpc)
 {
        stt_timer_t *timer = &rpc->crpc_timer;
 
-       if (rpc->crpc_timeout == 0) return;
+       if (rpc->crpc_timeout == 0)
+               return;
 
        INIT_LIST_HEAD(&timer->stt_list);
        timer->stt_data    = rpc;
@@ -1109,7 +1112,7 @@ srpc_add_client_rpc_timer (srpc_client_rpc_t *rpc)
  * Upon exit the RPC expiry timer is not queued and the handler is not
  * running on any CPU. */
 static void
-srpc_del_client_rpc_timer (srpc_client_rpc_t *rpc)
+srpc_del_client_rpc_timer(srpc_client_rpc_t *rpc)
 {
        /* timer not planted or already exploded */
        if (rpc->crpc_timeout == 0)
@@ -1130,7 +1133,7 @@ srpc_del_client_rpc_timer (srpc_client_rpc_t *rpc)
 }
 
 static void
-srpc_client_rpc_done (srpc_client_rpc_t *rpc, int status)
+srpc_client_rpc_done(srpc_client_rpc_t *rpc, int status)
 {
        swi_workitem_t *wi = &rpc->crpc_wi;
 
@@ -1144,7 +1147,7 @@ srpc_client_rpc_done (srpc_client_rpc_t *rpc, int status)
 
        srpc_del_client_rpc_timer(rpc);
 
-       CDEBUG_LIMIT ((status == 0) ? D_NET : D_NETERROR,
+       CDEBUG_LIMIT((status == 0) ? D_NET : D_NETERROR,
                "Client RPC done: service %d, peer %s, status %s:%d:%d\n",
                rpc->crpc_service, libcfs_id2str(rpc->crpc_dest),
                swi_state2str(wi->swi_state), rpc->crpc_aborted, status);
@@ -1157,7 +1160,7 @@ srpc_client_rpc_done (srpc_client_rpc_t *rpc, int status)
         *   scheduling me.
         * Cancel pending schedules and prevent future schedule attempts:
         */
-       LASSERT (!srpc_event_pending(rpc));
+       LASSERT(!srpc_event_pending(rpc));
        swi_exit_workitem(wi);
 
        spin_unlock(&rpc->crpc_lock);
@@ -1168,7 +1171,7 @@ srpc_client_rpc_done (srpc_client_rpc_t *rpc, int status)
 
 /* sends an outgoing RPC */
 int
-srpc_send_rpc (swi_workitem_t *wi)
+srpc_send_rpc(swi_workitem_t *wi)
 {
        int             rc = 0;
        srpc_client_rpc_t *rpc;
@@ -1179,8 +1182,8 @@ srpc_send_rpc (swi_workitem_t *wi)
 
        rpc = wi->swi_workitem.wi_data;
 
-       LASSERT (rpc != NULL);
-       LASSERT (wi == &rpc->crpc_wi);
+       LASSERT(rpc != NULL);
+       LASSERT(wi == &rpc->crpc_wi);
 
        reply = &rpc->crpc_replymsg;
        do_bulk = rpc->crpc_bulk.bk_niov > 0;
@@ -1196,9 +1199,9 @@ srpc_send_rpc (swi_workitem_t *wi)
 
        switch (wi->swi_state) {
        default:
-               LBUG ();
+               LBUG();
        case SWI_STATE_NEWBORN:
-               LASSERT (!srpc_event_pending(rpc));
+               LASSERT(!srpc_event_pending(rpc));
 
                rc = srpc_prepare_reply(rpc);
                if (rc != 0) {
@@ -1207,7 +1210,8 @@ srpc_send_rpc (swi_workitem_t *wi)
                }
 
                rc = srpc_prepare_bulk(rpc);
-               if (rc != 0) break;
+               if (rc != 0)
+                       break;
 
                wi->swi_state = SWI_STATE_REQUEST_SUBMITTED;
                rc = srpc_send_request(rpc);
@@ -1217,20 +1221,24 @@ srpc_send_rpc (swi_workitem_t *wi)
                /* CAVEAT EMPTOR: rqtev, rpyev, and bulkev may come in any
                 * order; however, they're processed in a strict order:
                 * rqt, rpy, and bulk. */
-               if (!rpc->crpc_reqstev.ev_fired) break;
+               if (!rpc->crpc_reqstev.ev_fired)
+                       break;
 
                rc = rpc->crpc_reqstev.ev_status;
-               if (rc != 0) break;
+               if (rc != 0)
+                       break;
 
                wi->swi_state = SWI_STATE_REQUEST_SENT;
                /* perhaps more events, fall thru */
        case SWI_STATE_REQUEST_SENT: {
                srpc_msg_type_t type = srpc_service2reply(rpc->crpc_service);
 
-               if (!rpc->crpc_replyev.ev_fired) break;
+               if (!rpc->crpc_replyev.ev_fired)
+                       break;
 
                rc = rpc->crpc_replyev.ev_status;
-               if (rc != 0) break;
+               if (rc != 0)
+                       break;
 
                srpc_unpack_msg_hdr(reply);
                if (reply->msg_type != type ||
@@ -1254,7 +1262,8 @@ srpc_send_rpc (swi_workitem_t *wi)
                wi->swi_state = SWI_STATE_REPLY_RECEIVED;
        }
        case SWI_STATE_REPLY_RECEIVED:
-               if (do_bulk && !rpc->crpc_bulkev.ev_fired) break;
+               if (do_bulk && !rpc->crpc_bulkev.ev_fired)
+                       break;
 
                rc = do_bulk ? rpc->crpc_bulkev.ev_status : 0;
 
@@ -1292,7 +1301,7 @@ abort:
 }
 
 srpc_client_rpc_t *
-srpc_create_client_rpc (lnet_process_id_t peer, int service,
+srpc_create_client_rpc(lnet_process_id_t peer, int service,
                        int nbulkiov, int bulklen,
                        void (*rpc_done)(srpc_client_rpc_t *),
                        void (*rpc_fini)(srpc_client_rpc_t *), void *priv)
@@ -1311,15 +1320,15 @@ srpc_create_client_rpc (lnet_process_id_t peer, int service,
 
 /* called with rpc->crpc_lock held */
 void
-srpc_abort_rpc (srpc_client_rpc_t *rpc, int why)
+srpc_abort_rpc(srpc_client_rpc_t *rpc, int why)
 {
-       LASSERT (why != 0);
+       LASSERT(why != 0);
 
        if (rpc->crpc_aborted || /* already aborted */
            rpc->crpc_closed)    /* callback imminent */
                return;
 
-       CDEBUG (D_NET,
+       CDEBUG(D_NET,
                "Aborting RPC: service %d, peer %s, state %s, why %d\n",
                rpc->crpc_service, libcfs_id2str(rpc->crpc_dest),
                swi_state2str(rpc->crpc_wi.swi_state), why);
@@ -1332,12 +1341,12 @@ srpc_abort_rpc (srpc_client_rpc_t *rpc, int why)
 
 /* called with rpc->crpc_lock held */
 void
-srpc_post_rpc (srpc_client_rpc_t *rpc)
+srpc_post_rpc(srpc_client_rpc_t *rpc)
 {
-       LASSERT (!rpc->crpc_aborted);
-       LASSERT (srpc_data.rpc_state == SRPC_STATE_RUNNING);
+       LASSERT(!rpc->crpc_aborted);
+       LASSERT(srpc_data.rpc_state == SRPC_STATE_RUNNING);
 
-       CDEBUG (D_NET, "Posting RPC: peer %s, service %d, timeout %d\n",
+       CDEBUG(D_NET, "Posting RPC: peer %s, service %d, timeout %d\n",
                libcfs_id2str(rpc->crpc_dest), rpc->crpc_service,
                rpc->crpc_timeout);
 
@@ -1403,7 +1412,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev)
        srpc_msg_t      *msg;
        srpc_msg_type_t    type;
 
-       LASSERT (!in_interrupt());
+       LASSERT(!in_interrupt());
 
        if (ev->status != 0) {
                spin_lock(&srpc_data.rpc_glock);
@@ -1417,7 +1426,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev)
        default:
                CERROR("Unknown event: status %d, type %d, lnet %d\n",
                       rpcev->ev_status, rpcev->ev_type, rpcev->ev_lnet);
-               LBUG ();
+               LBUG();
        case SRPC_REQUEST_SENT:
                if (ev->status == 0 && ev->type != LNET_EVENT_UNLINK) {
                        spin_lock(&srpc_data.rpc_glock);
@@ -1436,7 +1445,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev)
                               &crpc->crpc_replyev, &crpc->crpc_bulkev);
                        CERROR("Bad event: status %d, type %d, lnet %d\n",
                               rpcev->ev_status, rpcev->ev_type, rpcev->ev_lnet);
-                       LBUG ();
+                       LBUG();
                }
 
                spin_lock(&crpc->crpc_lock);
@@ -1458,10 +1467,10 @@ srpc_lnet_ev_handler(lnet_event_t *ev)
 
                spin_lock(&scd->scd_lock);
 
-               LASSERT (ev->unlinked);
-               LASSERT (ev->type == LNET_EVENT_PUT ||
+               LASSERT(ev->unlinked);
+               LASSERT(ev->type == LNET_EVENT_PUT ||
                         ev->type == LNET_EVENT_UNLINK);
-               LASSERT (ev->type != LNET_EVENT_UNLINK ||
+               LASSERT(ev->type != LNET_EVENT_UNLINK ||
                         sv->sv_shuttingdown);
 
                buffer = container_of(ev->md.start, srpc_buffer_t, buf_msg);
@@ -1536,7 +1545,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev)
                break;
 
        case SRPC_BULK_GET_RPLD:
-               LASSERT (ev->type == LNET_EVENT_SEND ||
+               LASSERT(ev->type == LNET_EVENT_SEND ||
                         ev->type == LNET_EVENT_REPLY ||
                         ev->type == LNET_EVENT_UNLINK);
 
@@ -1574,7 +1583,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev)
 
 
 int
-srpc_startup (void)
+srpc_startup(void)
 {
        int rc;
 
@@ -1590,7 +1599,7 @@ srpc_startup (void)
 
        rc = LNetNIInit(LUSTRE_SRV_LNET_PID);
        if (rc < 0) {
-               CERROR ("LNetNIInit() has failed: %d\n", rc);
+               CERROR("LNetNIInit() has failed: %d\n", rc);
                return rc;
        }
 
@@ -1622,7 +1631,7 @@ bail:
 }
 
 void
-srpc_shutdown (void)
+srpc_shutdown(void)
 {
        int i;
        int rc;
@@ -1633,14 +1642,14 @@ srpc_shutdown (void)
 
        switch (state) {
        default:
-               LBUG ();
+               LBUG();
        case SRPC_STATE_RUNNING:
                spin_lock(&srpc_data.rpc_glock);
 
                for (i = 0; i <= SRPC_SERVICE_MAX_ID; i++) {
                        srpc_service_t *sv = srpc_data.rpc_services[i];
 
-                       LASSERTF (sv == NULL,
+                       LASSERTF(sv == NULL,
                                  "service not empty: id %d, name %s\n",
                                  i, sv->sv_name);
                }
@@ -1652,9 +1661,9 @@ srpc_shutdown (void)
        case SRPC_STATE_EQ_INIT:
                rc = LNetClearLazyPortal(SRPC_FRAMEWORK_REQUEST_PORTAL);
                rc = LNetClearLazyPortal(SRPC_REQUEST_PORTAL);
-               LASSERT (rc == 0);
+               LASSERT(rc == 0);
                rc = LNetEQFree(srpc_data.rpc_lnet_eq);
-               LASSERT (rc == 0); /* the EQ should have no user by now */
+               LASSERT(rc == 0); /* the EQ should have no user by now */
 
        case SRPC_STATE_NI_INIT:
                LNetNIFini();
index 6a21f078fefa310491ece705544e31d784cd8867..783939dbd4db134c4494f272eaeec00fd36a7eb8 100644 (file)
@@ -120,15 +120,14 @@ static int
 lprocfs_fid_space_seq_show(struct seq_file *m, void *unused)
 {
        struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
-       int rc;
 
        LASSERT(seq != NULL);
 
        mutex_lock(&seq->lcs_mutex);
-       rc = seq_printf(m, "[%#llx - %#llx]:%x:%s\n", PRANGE(&seq->lcs_space));
+       seq_printf(m, "[%#llx - %#llx]:%x:%s\n", PRANGE(&seq->lcs_space));
        mutex_unlock(&seq->lcs_mutex);
 
-       return rc;
+       return 0;
 }
 
 static ssize_t lprocfs_fid_width_seq_write(struct file *file,
@@ -170,30 +169,28 @@ static int
 lprocfs_fid_width_seq_show(struct seq_file *m, void *unused)
 {
        struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
-       int rc;
 
        LASSERT(seq != NULL);
 
        mutex_lock(&seq->lcs_mutex);
-       rc = seq_printf(m, "%llu\n", seq->lcs_width);
+       seq_printf(m, "%llu\n", seq->lcs_width);
        mutex_unlock(&seq->lcs_mutex);
 
-       return rc;
+       return 0;
 }
 
 static int
 lprocfs_fid_fid_seq_show(struct seq_file *m, void *unused)
 {
        struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
-       int rc;
 
        LASSERT(seq != NULL);
 
        mutex_lock(&seq->lcs_mutex);
-       rc = seq_printf(m, DFID"\n", PFID(&seq->lcs_fid));
+       seq_printf(m, DFID "\n", PFID(&seq->lcs_fid));
        mutex_unlock(&seq->lcs_mutex);
 
-       return rc;
+       return 0;
 }
 
 static int
@@ -201,17 +198,17 @@ lprocfs_fid_server_seq_show(struct seq_file *m, void *unused)
 {
        struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
        struct client_obd *cli;
-       int rc;
 
        LASSERT(seq != NULL);
 
        if (seq->lcs_exp != NULL) {
                cli = &seq->lcs_exp->exp_obd->u.cli;
-               rc = seq_printf(m, "%s\n", cli->cl_target_uuid.uuid);
+               seq_printf(m, "%s\n", cli->cl_target_uuid.uuid);
        } else {
-               rc = seq_printf(m, "%s\n", seq->lcs_srv->lss_name);
+               seq_printf(m, "%s\n", seq->lcs_srv->lss_name);
        }
-       return rc;
+
+       return 0;
 }
 
 LPROC_SEQ_FOPS(lprocfs_fid_space);
index 6125bbe822b55f72c23979daafc5a029c29ebd95..68bec76584632a0a75445991ad268770aebb1bf9 100644 (file)
@@ -142,7 +142,7 @@ extern struct lu_fld_hash fld_hash[];
 int fld_client_rpc(struct obd_export *exp,
                   struct lu_seq_range *range, __u32 fld_op);
 
-#if defined (CONFIG_PROC_FS)
+#if defined(CONFIG_PROC_FS)
 extern struct lprocfs_vars fld_client_proc_list[];
 #endif
 
index b8d17e109a961a1d30e3b016173a42378eff0d25..6ac225e90ee079ab29df68cff3abd133512b36be 100644 (file)
@@ -217,10 +217,9 @@ int fld_client_add_target(struct lu_client_fld *fld,
                CERROR("%s: Attempt to add target %s (idx %llu) on fly - skip it\n",
                        fld->lcf_name, name, tar->ft_idx);
                return 0;
-       } else {
-               CDEBUG(D_INFO, "%s: Adding target %s (idx %llu)\n",
-                      fld->lcf_name, name, tar->ft_idx);
        }
+       CDEBUG(D_INFO, "%s: Adding target %s (idx %llu)\n",
+                       fld->lcf_name, name, tar->ft_idx);
 
        OBD_ALLOC_PTR(target);
        if (target == NULL)
@@ -280,7 +279,7 @@ EXPORT_SYMBOL(fld_client_del_target);
 
 static struct proc_dir_entry *fld_type_proc_dir;
 
-#if defined (CONFIG_PROC_FS)
+#if defined(CONFIG_PROC_FS)
 static int fld_client_proc_init(struct lu_client_fld *fld)
 {
        int rc;
@@ -327,7 +326,6 @@ static int fld_client_proc_init(struct lu_client_fld *fld)
 
 void fld_client_proc_fini(struct lu_client_fld *fld)
 {
-       return;
 }
 #endif
 EXPORT_SYMBOL(fld_client_proc_fini);
index 8c5a65704a37173117c01b1f4995ef5e1ac33596..f53fdcfae34e2ad7ed10a4f183fed38a867d8e70 100644 (file)
@@ -168,4 +168,5 @@ struct lprocfs_vars fld_client_proc_list[] = {
        { "targets", &fld_proc_targets_fops },
        { "hash", &fld_proc_hash_fops },
        { "cache_flush", &fld_proc_cache_flush_fops },
-       { NULL }};
+       { NULL }
+};
index a260e99a4447ee8b45e6c0f33c9ef18712c41220..d72605864b0a66adecf278a21a3ae8efc9c9255c 100644 (file)
@@ -55,7 +55,9 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
        if (PagePrivate(page))
                page->mapping->a_ops->invalidatepage(page, 0, PAGE_CACHE_SIZE);
 
-       cancel_dirty_page(page, PAGE_SIZE);
+       if (TestClearPageDirty(page))
+               account_page_cleaned(page, mapping);
+
        ClearPageMappedToDisk(page);
        ll_delete_from_page_cache(page);
 }
index 8a25cf6f6825be6bd58fbf476ea25a7250c56714..d030847e51bada4637fbbc11abfa3492033bc59c 100644 (file)
@@ -679,7 +679,7 @@ extern int lprocfs_seq_release(struct inode *, struct file *);
        }                                      \
 } while (0)
 #define LPROCFS_CLIMP_EXIT(obd)                 \
-       up_read(&(obd)->u.cli.cl_sem);
+       up_read(&(obd)->u.cli.cl_sem)
 
 
 /* write the name##_seq_show function, call LPROC_SEQ_FOPS_RO for read-only
@@ -723,7 +723,7 @@ static struct file_operations name##_fops = {                               \
                return lprocfs_wr_##type(file, buffer,                  \
                                         count, seq->private);          \
        }                                                               \
-       LPROC_SEQ_FOPS(name##_##type);
+       LPROC_SEQ_FOPS(name##_##type)
 
 #define LPROC_SEQ_FOPS_WR_ONLY(name, type)                             \
        static ssize_t name##_##type##_write(struct file *file,         \
@@ -740,7 +740,7 @@ static struct file_operations name##_fops = {                               \
                .open   = name##_##type##_open,                         \
                .write  = name##_##type##_write,                        \
                .release = lprocfs_single_release,                      \
-       };
+       }
 
 /* lproc_ptlrpc.c */
 struct ptlrpc_request;
index 2ddb2b054d8d5ac618ebaff9765990f6ed7da36f..c8cc48f0002690f130a1b246fdfb3870d1c99781 100644 (file)
@@ -192,7 +192,7 @@ struct lu_object_conf {
  */
 typedef int (*lu_printer_t)(const struct lu_env *env,
                            void *cookie, const char *format, ...)
-       __attribute__ ((format (printf, 3, 4)));
+       __printf(3, 4);
 
 /**
  * Operations specific for particular lu_object.
index 83bc0a9d7d4cd380c7779f9691c31989543d50d5..bac9902b56bbf48a4840116fe9efd154acb36a06 100644 (file)
@@ -1075,7 +1075,7 @@ extern char *ldlm_it2str(int it);
 void _ldlm_lock_debug(struct ldlm_lock *lock,
                      struct libcfs_debug_msg_data *data,
                      const char *fmt, ...)
-       __attribute__ ((format (printf, 3, 4)));
+       __printf(3, 4);
 
 /**
  * Rate-limited version of lock printing function.
index 51f3e98f94e288be73c2f8bb22729dbc2d4aa28a..dcc807676c490ec44e09467795e3c3f2c3aed863 100644 (file)
@@ -218,6 +218,8 @@ struct obd_import {
        atomic_t              imp_timeouts;
        /** Current import state */
        enum lustre_imp_state     imp_state;
+       /** Last replay state */
+       enum lustre_imp_state     imp_replay_state;
        /** History of import states */
        struct import_state_hist  imp_state_hist[IMP_STATE_HIST_LEN];
        int                    imp_state_hist_idx;
index 36396d1c94dc9eecc81e4f2446462ff23122e6c8..e2805bd1acf1070b176b22f974515dd567f9e2a9 100644 (file)
@@ -1673,7 +1673,7 @@ ptlrpc_rqphase2str(struct ptlrpc_request *req)
 
 void _debug_req(struct ptlrpc_request *req,
                struct libcfs_debug_msg_data *data, const char *fmt, ...)
-       __attribute__ ((format (printf, 3, 4)));
+       __printf(3, 4);
 
 /**
  * Helper that decides if we need to print request according to current debug
index 4a29261c514d9e61210419a7691be1d13d354197..34b5fa3f081ce3c2641a0b217b2d7b6fd10b1ca8 100644 (file)
@@ -72,6 +72,7 @@ extern int lustre_get_jobid(char *jobid);
 struct lu_device_type;
 
 /* genops.c */
+extern struct list_head obd_types;
 struct obd_export *class_conn2export(struct lustre_handle *);
 int class_register_type(struct obd_ops *, struct md_ops *,
                        struct lprocfs_vars *, const char *nm,
@@ -222,20 +223,20 @@ extern void (*class_export_dump_hook)(struct obd_export *);
 
 #endif
 
-#define class_export_rpc_inc(exp)                                     \
-({                                                                   \
-       atomic_inc(&(exp)->exp_rpc_count);                        \
-       CDEBUG(D_INFO, "RPC GETting export %p : new rpc_count %d\n",    \
-              (exp), atomic_read(&(exp)->exp_rpc_count));        \
-})
+static inline void class_export_rpc_inc(struct obd_export *exp)
+{
+       atomic_inc(&(exp)->exp_rpc_count);
+       CDEBUG(D_INFO, "RPC GETting export %p : new rpc_count %d\n",
+              (exp), atomic_read(&(exp)->exp_rpc_count));
+}
 
-#define class_export_rpc_dec(exp)                                     \
-({                                                                   \
-       LASSERT_ATOMIC_POS(&exp->exp_rpc_count);                        \
-       atomic_dec(&(exp)->exp_rpc_count);                        \
-       CDEBUG(D_INFO, "RPC PUTting export %p : new rpc_count %d\n",    \
-              (exp), atomic_read(&(exp)->exp_rpc_count));        \
-})
+static inline void class_export_rpc_dec(struct obd_export *exp)
+{
+       LASSERT_ATOMIC_POS(&exp->exp_rpc_count);
+       atomic_dec(&(exp)->exp_rpc_count);
+       CDEBUG(D_INFO, "RPC PUTting export %p : new rpc_count %d\n",
+              (exp), atomic_read(&(exp)->exp_rpc_count));
+}
 
 #define class_export_lock_get(exp, lock)                               \
 ({                                                                   \
@@ -332,25 +333,29 @@ void obdo_le_to_cpu(struct obdo *dobdo, struct obdo *sobdo);
 
 /* Ensure obd_setup: used for cleanup which must be called
    while obd is stopping */
-#define OBD_CHECK_DEV(obd)                                   \
-do {                                                       \
-       if (!(obd)) {                                      \
-               CERROR("NULL device\n");                        \
-               return -ENODEV;                         \
-       }                                                      \
-} while (0)
+static inline int obd_check_dev(struct obd_device *obd)
+{
+       if (!obd) {
+               CERROR("NULL device\n");
+               return -ENODEV;
+       }
+       return 0;
+}
 
 /* ensure obd_setup and !obd_stopping */
-#define OBD_CHECK_DEV_ACTIVE(obd)                             \
-do {                                                       \
-       OBD_CHECK_DEV(obd);                                  \
-       if (!(obd)->obd_set_up || (obd)->obd_stopping) {        \
-               CERROR("Device %d not setup\n",          \
-                      (obd)->obd_minor);                      \
-               return -ENODEV;                         \
-       }                                                      \
-} while (0)
+static inline int obd_check_dev_active(struct obd_device *obd)
+{
+       int rc;
 
+       rc = obd_check_dev(obd);
+       if (rc)
+               return rc;
+       if (!obd->obd_set_up || obd->obd_stopping) {
+               CERROR("Device %d not setup\n", obd->obd_minor);
+               return -ENODEV;
+       }
+       return rc;
+}
 
 #if defined (CONFIG_PROC_FS)
 #define OBD_COUNTER_OFFSET(op)                           \
@@ -593,7 +598,9 @@ static inline int obd_precleanup(struct obd_device *obd,
        int rc;
        DECLARE_LU_VARS(ldt, d);
 
-       OBD_CHECK_DEV(obd);
+       rc = obd_check_dev(obd);
+       if (rc)
+               return rc;
        ldt = obd->obd_type->typ_lu;
        d = obd->obd_lu_dev;
        if (ldt != NULL && d != NULL) {
@@ -619,7 +626,9 @@ static inline int obd_cleanup(struct obd_device *obd)
        int rc;
        DECLARE_LU_VARS(ldt, d);
 
-       OBD_CHECK_DEV(obd);
+       rc = obd_check_dev(obd);
+       if (rc)
+               return rc;
 
        ldt = obd->obd_type->typ_lu;
        d = obd->obd_lu_dev;
@@ -667,7 +676,9 @@ obd_process_config(struct obd_device *obd, int datalen, void *data)
        int rc;
        DECLARE_LU_VARS(ldt, d);
 
-       OBD_CHECK_DEV(obd);
+       rc = obd_check_dev(obd);
+       if (rc)
+               return rc;
 
        obd->obd_process_conf = 1;
        ldt = obd->obd_type->typ_lu;
@@ -885,7 +896,9 @@ static inline int obd_add_conn(struct obd_import *imp, struct obd_uuid *uuid,
        struct obd_device *obd = imp->imp_obd;
        int rc;
 
-       OBD_CHECK_DEV_ACTIVE(obd);
+       rc = obd_check_dev_active(obd);
+       if (rc)
+               return rc;
        OBD_CHECK_DT_OP(obd, add_conn, -EOPNOTSUPP);
        OBD_COUNTER_INCREMENT(obd, add_conn);
 
@@ -898,7 +911,9 @@ static inline int obd_del_conn(struct obd_import *imp, struct obd_uuid *uuid)
        struct obd_device *obd = imp->imp_obd;
        int rc;
 
-       OBD_CHECK_DEV_ACTIVE(obd);
+       rc = obd_check_dev_active(obd);
+       if (rc)
+               return rc;
        OBD_CHECK_DT_OP(obd, del_conn, -EOPNOTSUPP);
        OBD_COUNTER_INCREMENT(obd, del_conn);
 
@@ -932,7 +947,9 @@ static inline int obd_connect(const struct lu_env *env,
        __u64 ocf = data ? data->ocd_connect_flags : 0; /* for post-condition
                                                   * check */
 
-       OBD_CHECK_DEV_ACTIVE(obd);
+       rc = obd_check_dev_active(obd);
+       if (rc)
+               return rc;
        OBD_CHECK_DT_OP(obd, connect, -EOPNOTSUPP);
        OBD_COUNTER_INCREMENT(obd, connect);
 
@@ -954,7 +971,9 @@ static inline int obd_reconnect(const struct lu_env *env,
        __u64 ocf = d ? d->ocd_connect_flags : 0; /* for post-condition
                                                   * check */
 
-       OBD_CHECK_DEV_ACTIVE(obd);
+       rc = obd_check_dev_active(obd);
+       if (rc)
+               return rc;
        OBD_CHECK_DT_OP(obd, reconnect, 0);
        OBD_COUNTER_INCREMENT(obd, reconnect);
 
@@ -1279,7 +1298,9 @@ static inline int obd_notify(struct obd_device *obd,
 {
        int rc;
 
-       OBD_CHECK_DEV(obd);
+       rc = obd_check_dev(obd);
+       if (rc)
+               return rc;
 
        /* the check for async_recov is a complete hack - I'm hereby
           overloading the meaning to also mean "this was called from
@@ -1380,7 +1401,11 @@ static inline int obd_health_check(const struct lu_env *env,
 static inline int obd_register_observer(struct obd_device *obd,
                                        struct obd_device *observer)
 {
-       OBD_CHECK_DEV(obd);
+       int rc;
+
+       rc = obd_check_dev(obd);
+       if (rc)
+               return rc;
        down_write(&obd->obd_observer_link_sem);
        if (obd->obd_observer && observer) {
                up_write(&obd->obd_observer_link_sem);
@@ -1895,6 +1920,8 @@ void class_exit_uuidlist(void);
 
 /* class_obd.c */
 extern char obd_jobid_node[];
+extern struct miscdevice obd_psdev;
+extern spinlock_t obd_types_lock;
 
 /* prng.c */
 #define ll_generate_random_uuid(uuid_out) cfs_get_random_bytes(uuid_out, sizeof(class_uuid_t))
index 23095bb75226b1aace10df936ba754e3803e806c..ab6cb419302fb2f0cf7cff2c3e9d97b4d8678575 100644 (file)
@@ -828,7 +828,8 @@ int ccc_prep_size(const struct lu_env *env, struct cl_object *obj,
                                 * --bug 17336 */
                                loff_t size = cl_isize_read(inode);
                                loff_t cur_index = start >> PAGE_CACHE_SHIFT;
-                               loff_t size_index = ((size - 1) >> PAGE_CACHE_SHIFT);
+                               loff_t size_index = (size - 1) >>
+                                                   PAGE_CACHE_SHIFT;
 
                                if ((size == 0 && cur_index != 0) ||
                                    size_index < cur_index)
@@ -1263,7 +1264,7 @@ __u32 cl_fid_build_gen(const struct lu_fid *fid)
                return gen;
        }
 
-       gen = (fid_flatten(fid) >> 32);
+       gen = fid_flatten(fid) >> 32;
        return gen;
 }
 
index a89eebaedabfe54fa9391fcc531ea88f42f8d9b1..fd9b059361f934ea2c67ca191d82c24b691626a2 100644 (file)
@@ -151,7 +151,8 @@ static inline int lock_mode_to_index(ldlm_mode_t mode)
 
        LASSERT(mode != 0);
        LASSERT(IS_PO2(mode));
-       for (index = -1; mode; index++, mode >>= 1) ;
+       for (index = -1; mode; index++)
+               mode >>= 1;
        LASSERT(index < LCK_MODE_NUM);
        return index;
 }
index 20e64cddb1f4ef53a3da6381a14217a29d249677..70b909f55861a8b6fdca9215d5dceda5f0a3351a 100644 (file)
@@ -131,12 +131,12 @@ struct ldlm_cb_set_arg {
        union ldlm_gl_desc              *gl_desc; /* glimpse AST descriptor */
 };
 
-typedef enum {
+enum ldlm_desc_ast_t {
        LDLM_WORK_BL_AST,
        LDLM_WORK_CP_AST,
        LDLM_WORK_REVOKE_AST,
        LDLM_WORK_GL_AST
-} ldlm_desc_ast_t;
+};
 
 void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list);
 int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill,
@@ -155,7 +155,7 @@ void ldlm_lock_decref_internal_nolock(struct ldlm_lock *, __u32 mode);
 void ldlm_add_ast_work_item(struct ldlm_lock *lock, struct ldlm_lock *new,
                            struct list_head *work_list);
 int ldlm_run_ast_work(struct ldlm_namespace *ns, struct list_head *rpc_list,
-                     ldlm_desc_ast_t ast_type);
+                     enum ldlm_desc_ast_t ast_type);
 int ldlm_work_gl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq);
 int ldlm_lock_remove_from_lru(struct ldlm_lock *lock);
 int ldlm_lock_remove_from_lru_nolock(struct ldlm_lock *lock);
@@ -177,6 +177,10 @@ int ldlm_bl_to_thread_list(struct ldlm_namespace *ns,
 void ldlm_handle_bl_callback(struct ldlm_namespace *ns,
                             struct ldlm_lock_desc *ld, struct ldlm_lock *lock);
 
+extern struct kmem_cache *ldlm_resource_slab;
+
+/* ldlm_lockd.c & ldlm_lock.c */
+extern struct kmem_cache *ldlm_lock_slab;
 
 /* ldlm_extent.c */
 void ldlm_extent_add_lock(struct ldlm_resource *res, struct ldlm_lock *lock);
@@ -207,9 +211,9 @@ 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);
-extern struct ldlm_interval *ldlm_interval_detach(struct ldlm_lock *l);
-extern struct ldlm_interval *ldlm_interval_alloc(struct ldlm_lock *lock);
-extern void ldlm_interval_free(struct ldlm_interval *node);
+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);
 /* this function must be called with res lock held */
 static inline struct ldlm_extent *
 ldlm_interval_extent(struct ldlm_interval *node)
index 8191005464b165f8d660ed90229b76c1825d4455..84b111eb48fad5060a0b32565d46662de3170cc8 100644 (file)
@@ -151,8 +151,6 @@ char *ldlm_it2str(int it)
 }
 EXPORT_SYMBOL(ldlm_it2str);
 
-extern struct kmem_cache *ldlm_lock_slab;
-
 
 void ldlm_register_intent(struct ldlm_namespace *ns, ldlm_res_policy arg)
 {
@@ -1805,7 +1803,7 @@ int ldlm_work_gl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq)
  * one.
  */
 int ldlm_run_ast_work(struct ldlm_namespace *ns, struct list_head *rpc_list,
-                     ldlm_desc_ast_t ast_type)
+                     enum ldlm_desc_ast_t ast_type)
 {
        struct ldlm_cb_set_arg *arg;
        set_producer_func       work_ast_lock;
index 98fbd3f7e751e248b1aacd06dfe47b28d437fda6..08a91f5d91b1663514889833796fdf6786c554c1 100644 (file)
@@ -55,8 +55,6 @@ static char *ldlm_cpts;
 module_param(ldlm_cpts, charp, 0444);
 MODULE_PARM_DESC(ldlm_cpts, "CPU partitions ldlm threads should run on");
 
-extern struct kmem_cache *ldlm_resource_slab;
-extern struct kmem_cache *ldlm_lock_slab;
 static struct mutex    ldlm_ref_mutex;
 static int ldlm_refcount;
 
@@ -154,7 +152,7 @@ void ldlm_handle_bl_callback(struct ldlm_namespace *ns,
        if (lock->l_flags & LDLM_FL_CANCEL_ON_BLOCK)
                lock->l_flags |= LDLM_FL_CANCEL;
 
-       do_ast = (!lock->l_readers && !lock->l_writers);
+       do_ast = !lock->l_readers && !lock->l_writers;
        unlock_res_and_lock(lock);
 
        if (do_ast) {
index d20d277dc2f7648a99640ce7d8a8fc6c4dd87836..a9f4833e03e5f623d3666e81c012fb86cbaff8d4 100644 (file)
  */
 #define LDLM_POOL_SLV_SHIFT (10)
 
-extern struct proc_dir_entry *ldlm_ns_proc_dir;
-
 static inline __u64 dru(__u64 val, __u32 shift, int round_up)
 {
        return (val + (round_up ? (1 << shift) - 1 : 0)) >> shift;
@@ -689,8 +687,8 @@ static int lprocfs_pool_state_seq_show(struct seq_file *m, void *unused)
                              "  GP:  %d\n",
                              grant_step, grant_plan);
        }
-       seq_printf(m, "  GR:  %d\n" "  CR:  %d\n" "  GS:  %d\n"
-                     "  G:   %d\n" "  L:   %d\n",
+       seq_printf(m, "  GR:  %d\n  CR:  %d\n  GS:  %d\n"
+                     "  G:   %d\n  L:   %d\n",
                      grant_rate, cancel_rate, grant_speed,
                      granted, limit);
 
index 287da325d92874291c47186ade8a2d761805fbcd..4f713183145bb823a955a51b4dff94cb8ba17cbb 100644 (file)
@@ -307,7 +307,7 @@ int ldlm_blocking_ast_nocheck(struct ldlm_lock *lock)
        int do_ast;
 
        lock->l_flags |= LDLM_FL_CBPENDING;
-       do_ast = (!lock->l_readers && !lock->l_writers);
+       do_ast = !lock->l_readers && !lock->l_writers;
        unlock_res_and_lock(lock);
 
        if (do_ast) {
@@ -1779,7 +1779,6 @@ int ldlm_cancel_resource_local(struct ldlm_resource *res,
                if (opaque != NULL && lock->l_ast_data != opaque) {
                        LDLM_ERROR(lock, "data %p doesn't match opaque %p",
                                   lock->l_ast_data, opaque);
-                       //LBUG();
                        continue;
                }
 
index c6f62a91b233f280a8bb6956315b0185a1adf4fa..f750d42a7ad5558a19de8db0a53956f982c35b48 100644 (file)
@@ -62,7 +62,7 @@ LIST_HEAD(ldlm_cli_active_namespace_list);
 LIST_HEAD(ldlm_cli_inactive_namespace_list);
 
 struct proc_dir_entry *ldlm_type_proc_dir = NULL;
-struct proc_dir_entry *ldlm_ns_proc_dir = NULL;
+static struct proc_dir_entry *ldlm_ns_proc_dir = NULL;
 struct proc_dir_entry *ldlm_svc_proc_dir = NULL;
 
 extern unsigned int ldlm_cancel_unused_locks_before_replay;
index fcecbd2271afcbd1fc0c2eb51307c48822f8f140..2996a48a31fb673c668b8a329050e065a4c5020c 100644 (file)
@@ -3,7 +3,7 @@ obj-$(CONFIG_LUSTRE_FS) += libcfs.o
 libcfs-linux-objs := linux-tracefile.o linux-debug.o
 libcfs-linux-objs += linux-prim.o linux-cpu.o
 libcfs-linux-objs += linux-tcpip.o
-libcfs-linux-objs += linux-proc.o linux-curproc.o
+libcfs-linux-objs += linux-curproc.o
 libcfs-linux-objs += linux-module.o
 libcfs-linux-objs += linux-crypto.o
 libcfs-linux-objs += linux-crypto-adler.o
index 76c62e87a415afd1bd7f7d9e60bdec9b94299894..021c92fa0333f2cd92c91b10762fcbceac7ed723 100644 (file)
@@ -409,8 +409,8 @@ int libcfs_debug_init(unsigned long bufsize)
        if (max > cfs_trace_max_debug_mb() || max < num_possible_cpus()) {
                max = TCD_MAX_PAGES;
        } else {
-               max = (max / num_possible_cpus());
-               max = max << (20 - PAGE_CACHE_SHIFT);
+               max = max / num_possible_cpus();
+               max <<= (20 - PAGE_CACHE_SHIFT);
        }
        rc = cfs_tracefile_init(max);
 
index ec3a2a8b8b2cdbae9799475f5351662c7b5d88b7..a55567e0de9eee87c055c5c2fdf85b08bf70fcc3 100644 (file)
@@ -2008,13 +2008,10 @@ void cfs_hash_rehash_key(struct cfs_hash *hs, const void *old_key,
 }
 EXPORT_SYMBOL(cfs_hash_rehash_key);
 
-int cfs_hash_debug_header(struct seq_file *m)
+void cfs_hash_debug_header(struct seq_file *m)
 {
-       return seq_printf(m, "%-*s%6s%6s%6s%6s%6s%6s%6s%7s%8s%8s%8s%s\n",
-                CFS_HASH_BIGNAME_LEN,
-                "name", "cur", "min", "max", "theta", "t-min", "t-max",
-                "flags", "rehash", "count", "maxdep", "maxdepb",
-                " distribution");
+       seq_printf(m, "%-*s   cur   min   max theta t-min t-max flags rehash   count  maxdep maxdepb distribution\n",
+                  CFS_HASH_BIGNAME_LEN, "name");
 }
 EXPORT_SYMBOL(cfs_hash_debug_header);
 
@@ -2042,7 +2039,7 @@ cfs_hash_full_nbkt(struct cfs_hash *hs)
               CFS_HASH_RH_NBKT(hs) : CFS_HASH_NBKT(hs);
 }
 
-int cfs_hash_debug_str(struct cfs_hash *hs, struct seq_file *m)
+void cfs_hash_debug_str(struct cfs_hash *hs, struct seq_file *m)
 {
        int                 dist[8] = { 0, };
        int                 maxdep  = -1;
@@ -2097,7 +2094,5 @@ int cfs_hash_debug_str(struct cfs_hash *hs, struct seq_file *m)
                seq_printf(m, "%d%c",  dist[i], (i == 7) ? '\n' : '/');
 
        cfs_hash_unlock(hs, 0);
-
-       return 0;
 }
 EXPORT_SYMBOL(cfs_hash_debug_str);
index 05f7595f18aa55f51ba8c86c3aec2b4d572a48de..cc3ab351943e195a454d33d3f8d8529694f5ac0d 100644 (file)
@@ -204,7 +204,7 @@ cfs_cpt_table_print(struct cfs_cpt_table *cptab, char *buf, int len)
                }
 
                tmp += rc;
-               for_each_cpu_mask(j, *cptab->ctb_parts[i].cpt_cpumask) {
+               for_each_cpu(j, cptab->ctb_parts[i].cpt_cpumask) {
                        rc = snprintf(tmp, len, "%d ", j);
                        len -= rc;
                        if (len <= 0) {
@@ -240,8 +240,8 @@ cfs_cpt_weight(struct cfs_cpt_table *cptab, int cpt)
        LASSERT(cpt == CFS_CPT_ANY || (cpt >= 0 && cpt < cptab->ctb_nparts));
 
        return cpt == CFS_CPT_ANY ?
-              cpus_weight(*cptab->ctb_cpumask) :
-              cpus_weight(*cptab->ctb_parts[cpt].cpt_cpumask);
+              cpumask_weight(cptab->ctb_cpumask) :
+              cpumask_weight(cptab->ctb_parts[cpt].cpt_cpumask);
 }
 EXPORT_SYMBOL(cfs_cpt_weight);
 
@@ -251,8 +251,10 @@ cfs_cpt_online(struct cfs_cpt_table *cptab, int cpt)
        LASSERT(cpt == CFS_CPT_ANY || (cpt >= 0 && cpt < cptab->ctb_nparts));
 
        return cpt == CFS_CPT_ANY ?
-              any_online_cpu(*cptab->ctb_cpumask) != NR_CPUS :
-              any_online_cpu(*cptab->ctb_parts[cpt].cpt_cpumask) != NR_CPUS;
+              cpumask_any_and(cptab->ctb_cpumask,
+                              cpu_online_mask) < nr_cpu_ids :
+              cpumask_any_and(cptab->ctb_parts[cpt].cpt_cpumask,
+                              cpu_online_mask) < nr_cpu_ids;
 }
 EXPORT_SYMBOL(cfs_cpt_online);
 
@@ -283,7 +285,7 @@ cfs_cpt_set_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu)
 
        LASSERT(cpt >= 0 && cpt < cptab->ctb_nparts);
 
-       if (cpu < 0 || cpu >= NR_CPUS || !cpu_online(cpu)) {
+       if (cpu < 0 || cpu >= nr_cpu_ids || !cpu_online(cpu)) {
                CDEBUG(D_INFO, "CPU %d is invalid or it's offline\n", cpu);
                return 0;
        }
@@ -296,11 +298,11 @@ cfs_cpt_set_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu)
 
        cptab->ctb_cpu2cpt[cpu] = cpt;
 
-       LASSERT(!cpu_isset(cpu, *cptab->ctb_cpumask));
-       LASSERT(!cpu_isset(cpu, *cptab->ctb_parts[cpt].cpt_cpumask));
+       LASSERT(!cpumask_test_cpu(cpu, cptab->ctb_cpumask));
+       LASSERT(!cpumask_test_cpu(cpu, cptab->ctb_parts[cpt].cpt_cpumask));
 
-       cpu_set(cpu, *cptab->ctb_cpumask);
-       cpu_set(cpu, *cptab->ctb_parts[cpt].cpt_cpumask);
+       cpumask_set_cpu(cpu, cptab->ctb_cpumask);
+       cpumask_set_cpu(cpu, cptab->ctb_parts[cpt].cpt_cpumask);
 
        node = cpu_to_node(cpu);
 
@@ -324,7 +326,7 @@ cfs_cpt_unset_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu)
 
        LASSERT(cpt == CFS_CPT_ANY || (cpt >= 0 && cpt < cptab->ctb_nparts));
 
-       if (cpu < 0 || cpu >= NR_CPUS) {
+       if (cpu < 0 || cpu >= nr_cpu_ids) {
                CDEBUG(D_INFO, "Invalid CPU id %d\n", cpu);
                return;
        }
@@ -344,11 +346,11 @@ cfs_cpt_unset_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu)
                return;
        }
 
-       LASSERT(cpu_isset(cpu, *cptab->ctb_parts[cpt].cpt_cpumask));
-       LASSERT(cpu_isset(cpu, *cptab->ctb_cpumask));
+       LASSERT(cpumask_test_cpu(cpu, cptab->ctb_parts[cpt].cpt_cpumask));
+       LASSERT(cpumask_test_cpu(cpu, cptab->ctb_cpumask));
 
-       cpu_clear(cpu, *cptab->ctb_parts[cpt].cpt_cpumask);
-       cpu_clear(cpu, *cptab->ctb_cpumask);
+       cpumask_clear_cpu(cpu, cptab->ctb_parts[cpt].cpt_cpumask);
+       cpumask_clear_cpu(cpu, cptab->ctb_cpumask);
        cptab->ctb_cpu2cpt[cpu] = -1;
 
        node = cpu_to_node(cpu);
@@ -356,22 +358,22 @@ cfs_cpt_unset_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu)
        LASSERT(node_isset(node, *cptab->ctb_parts[cpt].cpt_nodemask));
        LASSERT(node_isset(node, *cptab->ctb_nodemask));
 
-       for_each_cpu_mask(i, *cptab->ctb_parts[cpt].cpt_cpumask) {
+       for_each_cpu(i, cptab->ctb_parts[cpt].cpt_cpumask) {
                /* this CPT has other CPU belonging to this node? */
                if (cpu_to_node(i) == node)
                        break;
        }
 
-       if (i == NR_CPUS)
+       if (i >= nr_cpu_ids)
                node_clear(node, *cptab->ctb_parts[cpt].cpt_nodemask);
 
-       for_each_cpu_mask(i, *cptab->ctb_cpumask) {
+       for_each_cpu(i, cptab->ctb_cpumask) {
                /* this CPT-table has other CPU belonging to this node? */
                if (cpu_to_node(i) == node)
                        break;
        }
 
-       if (i == NR_CPUS)
+       if (i >= nr_cpu_ids)
                node_clear(node, *cptab->ctb_nodemask);
 
        return;
@@ -383,13 +385,14 @@ cfs_cpt_set_cpumask(struct cfs_cpt_table *cptab, int cpt, cpumask_t *mask)
 {
        int     i;
 
-       if (cpus_weight(*mask) == 0 || any_online_cpu(*mask) == NR_CPUS) {
+       if (cpumask_weight(mask) == 0 ||
+           cpumask_any_and(mask, cpu_online_mask) >= nr_cpu_ids) {
                CDEBUG(D_INFO, "No online CPU is found in the CPU mask for CPU partition %d\n",
                       cpt);
                return 0;
        }
 
-       for_each_cpu_mask(i, *mask) {
+       for_each_cpu(i, mask) {
                if (!cfs_cpt_set_cpu(cptab, cpt, i))
                        return 0;
        }
@@ -403,7 +406,7 @@ cfs_cpt_unset_cpumask(struct cfs_cpt_table *cptab, int cpt, cpumask_t *mask)
 {
        int     i;
 
-       for_each_cpu_mask(i, *mask)
+       for_each_cpu(i, mask)
                cfs_cpt_unset_cpu(cptab, cpt, i);
 }
 EXPORT_SYMBOL(cfs_cpt_unset_cpumask);
@@ -493,7 +496,7 @@ cfs_cpt_clear(struct cfs_cpt_table *cptab, int cpt)
        }
 
        for (; cpt <= last; cpt++) {
-               for_each_cpu_mask(i, *cptab->ctb_parts[cpt].cpt_cpumask)
+               for_each_cpu(i, cptab->ctb_parts[cpt].cpt_cpumask)
                        cfs_cpt_unset_cpu(cptab, cpt, i);
        }
 }
@@ -554,7 +557,7 @@ EXPORT_SYMBOL(cfs_cpt_current);
 int
 cfs_cpt_of_cpu(struct cfs_cpt_table *cptab, int cpu)
 {
-       LASSERT(cpu >= 0 && cpu < NR_CPUS);
+       LASSERT(cpu >= 0 && cpu < nr_cpu_ids);
 
        return cptab->ctb_cpu2cpt[cpu];
 }
@@ -578,14 +581,14 @@ cfs_cpt_bind(struct cfs_cpt_table *cptab, int cpt)
                nodemask = cptab->ctb_parts[cpt].cpt_nodemask;
        }
 
-       if (any_online_cpu(*cpumask) == NR_CPUS) {
+       if (cpumask_any_and(cpumask, cpu_online_mask) >= nr_cpu_ids) {
                CERROR("No online CPU found in CPU partition %d, did someone do CPU hotplug on system? You might need to reload Lustre modules to keep system working well.\n",
                       cpt);
                return -EINVAL;
        }
 
        for_each_online_cpu(i) {
-               if (cpu_isset(i, *cpumask))
+               if (cpumask_test_cpu(i, cpumask))
                        continue;
 
                rc = set_cpus_allowed_ptr(current, cpumask);
@@ -616,14 +619,14 @@ cfs_cpt_choose_ncpus(struct cfs_cpt_table *cptab, int cpt,
 
        LASSERT(number > 0);
 
-       if (number >= cpus_weight(*node)) {
-               while (!cpus_empty(*node)) {
-                       cpu = first_cpu(*node);
+       if (number >= cpumask_weight(node)) {
+               while (!cpumask_empty(node)) {
+                       cpu = cpumask_first(node);
 
                        rc = cfs_cpt_set_cpu(cptab, cpt, cpu);
                        if (!rc)
                                return -EINVAL;
-                       cpu_clear(cpu, *node);
+                       cpumask_clear_cpu(cpu, node);
                }
                return 0;
        }
@@ -636,27 +639,27 @@ cfs_cpt_choose_ncpus(struct cfs_cpt_table *cptab, int cpt,
                goto out;
        }
 
-       while (!cpus_empty(*node)) {
-               cpu = first_cpu(*node);
+       while (!cpumask_empty(node)) {
+               cpu = cpumask_first(node);
 
                /* get cpumask for cores in the same socket */
                cfs_cpu_core_siblings(cpu, socket);
-               cpus_and(*socket, *socket, *node);
+               cpumask_and(socket, socket, node);
 
-               LASSERT(!cpus_empty(*socket));
+               LASSERT(!cpumask_empty(socket));
 
-               while (!cpus_empty(*socket)) {
+               while (!cpumask_empty(socket)) {
                        int     i;
 
                        /* get cpumask for hts in the same core */
                        cfs_cpu_ht_siblings(cpu, core);
-                       cpus_and(*core, *core, *node);
+                       cpumask_and(core, core, node);
 
-                       LASSERT(!cpus_empty(*core));
+                       LASSERT(!cpumask_empty(core));
 
-                       for_each_cpu_mask(i, *core) {
-                               cpu_clear(i, *socket);
-                               cpu_clear(i, *node);
+                       for_each_cpu(i, core) {
+                               cpumask_clear_cpu(i, socket);
+                               cpumask_clear_cpu(i, node);
 
                                rc = cfs_cpt_set_cpu(cptab, cpt, i);
                                if (!rc) {
@@ -667,7 +670,7 @@ cfs_cpt_choose_ncpus(struct cfs_cpt_table *cptab, int cpt,
                                if (--number == 0)
                                        goto out;
                        }
-                       cpu = first_cpu(*socket);
+                       cpu = cpumask_first(socket);
                }
        }
 
@@ -767,7 +770,7 @@ cfs_cpt_table_create(int ncpt)
        for_each_online_node(i) {
                cfs_node_to_cpumask(i, mask);
 
-               while (!cpus_empty(*mask)) {
+               while (!cpumask_empty(mask)) {
                        struct cfs_cpu_partition *part;
                        int    n;
 
@@ -776,24 +779,24 @@ cfs_cpt_table_create(int ncpt)
 
                        part = &cptab->ctb_parts[cpt];
 
-                       n = num - cpus_weight(*part->cpt_cpumask);
+                       n = num - cpumask_weight(part->cpt_cpumask);
                        LASSERT(n > 0);
 
                        rc = cfs_cpt_choose_ncpus(cptab, cpt, mask, n);
                        if (rc < 0)
                                goto failed;
 
-                       LASSERT(num >= cpus_weight(*part->cpt_cpumask));
-                       if (num == cpus_weight(*part->cpt_cpumask))
+                       LASSERT(num >= cpumask_weight(part->cpt_cpumask));
+                       if (num == cpumask_weight(part->cpt_cpumask))
                                cpt++;
                }
        }
 
        if (cpt != ncpt ||
-           num != cpus_weight(*cptab->ctb_parts[ncpt - 1].cpt_cpumask)) {
+           num != cpumask_weight(cptab->ctb_parts[ncpt - 1].cpt_cpumask)) {
                CERROR("Expect %d(%d) CPU partitions but got %d(%d), CPU hotplug/unplug while setting?\n",
                       cptab->ctb_nparts, num, cpt,
-                      cpus_weight(*cptab->ctb_parts[ncpt - 1].cpt_cpumask));
+                      cpumask_weight(cptab->ctb_parts[ncpt - 1].cpt_cpumask));
                goto failed;
        }
 
@@ -845,7 +848,7 @@ cfs_cpt_table_create_pattern(char *pattern)
                return NULL;
        }
 
-       high = node ? MAX_NUMNODES - 1 : NR_CPUS - 1;
+       high = node ? MAX_NUMNODES - 1 : nr_cpu_ids - 1;
 
        cptab = cfs_cpt_table_alloc(ncpt);
        if (cptab == NULL) {
@@ -965,7 +968,8 @@ cfs_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
                mutex_lock(&cpt_data.cpt_mutex);
                /* if all HTs in a core are offline, it may break affinity */
                cfs_cpu_ht_siblings(cpu, cpt_data.cpt_cpumask);
-               warn = any_online_cpu(*cpt_data.cpt_cpumask) >= nr_cpu_ids;
+               warn = cpumask_any_and(cpt_data.cpt_cpumask,
+                                      cpu_online_mask) >= nr_cpu_ids;
                mutex_unlock(&cpt_data.cpt_mutex);
                CDEBUG(warn ? D_WARNING : D_INFO,
                       "Lustre: can't support CPU plug-out well now, performance and stability could be impacted [CPU %u action: %lx]\n",
index 12005a71aa736599d0813fde935fed9d28534866..4545d54f71c6f3d93cbbb6ed3c021ba82d6c483e 100644 (file)
@@ -50,7 +50,7 @@
 #include <linux/interrupt.h>
 #include <linux/completion.h>
 #include <linux/fs.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/miscdevice.h>
 
 # define DEBUG_SUBSYSTEM S_LNET
index a5effcd9c6794b6197cd4260b561e7308a794614..e962f89683a60cdb68ee67b3070bc185d783027e 100644 (file)
@@ -57,7 +57,7 @@ int libcfs_ioctl_getdata(char *buf, char *end, void *arg)
                return -EINVAL;
        }
 
-       if (hdr->ioc_len + buf >= end) {
+       if (hdr->ioc_len >= end - buf) {
                CERROR("PORTALS: user buffer exceeds kernel buffer\n");
                return -EINVAL;
        }
index 19f405e64e6811d4773a0952645d5541104e503e..838f5f3bd6af450579b7cedb2fe08713d882c65f 100644 (file)
@@ -43,7 +43,7 @@
 #include "../../../include/linux/libcfs/libcfs.h"
 
 #if defined(CONFIG_KGDB)
-#include <asm/kgdb.h>
+#include <linux/kgdb.h>
 #endif
 
 /**
@@ -117,11 +117,12 @@ EXPORT_SYMBOL(cfs_timer_deadline);
 void cfs_enter_debugger(void)
 {
 #if defined(CONFIG_KGDB)
-//     BREAKPOINT();
+       /* BREAKPOINT(); */
 #else
        /* nothing */
 #endif
 }
+EXPORT_SYMBOL(cfs_enter_debugger);
 
 
 sigset_t
@@ -138,6 +139,7 @@ cfs_block_allsigs(void)
 
        return old;
 }
+EXPORT_SYMBOL(cfs_block_allsigs);
 
 sigset_t cfs_block_sigs(unsigned long sigs)
 {
@@ -151,6 +153,7 @@ sigset_t cfs_block_sigs(unsigned long sigs)
        spin_unlock_irqrestore(&current->sighand->siglock, flags);
        return old;
 }
+EXPORT_SYMBOL(cfs_block_sigs);
 
 /* Block all signals except for the @sigs */
 sigset_t cfs_block_sigsinv(unsigned long sigs)
@@ -166,9 +169,10 @@ sigset_t cfs_block_sigsinv(unsigned long sigs)
 
        return old;
 }
+EXPORT_SYMBOL(cfs_block_sigsinv);
 
 void
-cfs_restore_sigs (sigset_t old)
+cfs_restore_sigs(sigset_t old)
 {
        unsigned long  flags;
 
@@ -177,12 +181,14 @@ cfs_restore_sigs (sigset_t old)
        recalc_sigpending();
        spin_unlock_irqrestore(&current->sighand->siglock, flags);
 }
+EXPORT_SYMBOL(cfs_restore_sigs);
 
 int
 cfs_signal_pending(void)
 {
        return signal_pending(current);
 }
+EXPORT_SYMBOL(cfs_signal_pending);
 
 void
 cfs_clear_sigpending(void)
@@ -193,25 +199,19 @@ cfs_clear_sigpending(void)
        clear_tsk_thread_flag(current, TIF_SIGPENDING);
        spin_unlock_irqrestore(&current->sighand->siglock, flags);
 }
+EXPORT_SYMBOL(cfs_clear_sigpending);
 
 int
 libcfs_arch_init(void)
 {
        return 0;
 }
+EXPORT_SYMBOL(libcfs_arch_init);
 
 void
 libcfs_arch_cleanup(void)
 {
        return;
 }
-
-EXPORT_SYMBOL(libcfs_arch_init);
 EXPORT_SYMBOL(libcfs_arch_cleanup);
-EXPORT_SYMBOL(cfs_enter_debugger);
-EXPORT_SYMBOL(cfs_block_allsigs);
-EXPORT_SYMBOL(cfs_block_sigs);
-EXPORT_SYMBOL(cfs_block_sigsinv);
-EXPORT_SYMBOL(cfs_restore_sigs);
-EXPORT_SYMBOL(cfs_signal_pending);
-EXPORT_SYMBOL(cfs_clear_sigpending);
+
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c
deleted file mode 100644 (file)
index c539e37..0000000
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * libcfs/libcfs/linux/linux-proc.c
- *
- * Author: Zach Brown <zab@zabbo.net>
- * Author: Peter J. Braam <braam@clusterfs.com>
- * Author: Phil Schwan <phil@clusterfs.com>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/unistd.h>
-#include <net/sock.h>
-#include <linux/uio.h>
-
-#include <asm/uaccess.h>
-
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/list.h>
-
-#include <linux/proc_fs.h>
-#include <linux/sysctl.h>
-
-# define DEBUG_SUBSYSTEM S_LNET
-
-#include "../../../include/linux/libcfs/libcfs.h"
-#include <asm/div64.h>
-#include "../tracefile.h"
-
-static struct ctl_table_header *lnet_table_header = NULL;
-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 int proc_call_handler(void *data, int write, loff_t *ppos,
-               void __user *buffer, size_t *lenp,
-               int (*handler)(void *data, int write,
-               loff_t pos, void __user *buffer, int len))
-{
-       int rc = handler(data, write, *ppos, buffer, *lenp);
-
-       if (rc < 0)
-               return rc;
-
-       if (write) {
-               *ppos += *lenp;
-       } else {
-               *lenp = rc;
-               *ppos += rc;
-       }
-       return 0;
-}
-
-static int __proc_dobitmasks(void *data, int write,
-                            loff_t pos, void __user *buffer, int nob)
-{
-       const int     tmpstrlen = 512;
-       char     *tmpstr;
-       int        rc;
-       unsigned int *mask = data;
-       int        is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
-       int        is_printk = (mask == &libcfs_printk) ? 1 : 0;
-
-       rc = cfs_trace_allocate_string_buffer(&tmpstr, tmpstrlen);
-       if (rc < 0)
-               return rc;
-
-       if (!write) {
-               libcfs_debug_mask2str(tmpstr, tmpstrlen, *mask, is_subsys);
-               rc = strlen(tmpstr);
-
-               if (pos >= rc) {
-                       rc = 0;
-               } else {
-                       rc = cfs_trace_copyout_string(buffer, nob,
-                                                     tmpstr + pos, "\n");
-               }
-       } else {
-               rc = cfs_trace_copyin_string(tmpstr, tmpstrlen, buffer, nob);
-               if (rc < 0) {
-                       cfs_trace_free_string_buffer(tmpstr, tmpstrlen);
-                       return rc;
-               }
-
-               rc = libcfs_debug_str2mask(mask, tmpstr, is_subsys);
-               /* Always print LBUG/LASSERT to console, so keep this mask */
-               if (is_printk)
-                       *mask |= D_EMERG;
-       }
-
-       cfs_trace_free_string_buffer(tmpstr, tmpstrlen);
-       return rc;
-}
-
-static int proc_dobitmasks(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_dobitmasks);
-}
-
-static int min_watchdog_ratelimit = 0;   /* 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)
-{
-       if (!write)
-               return 0;
-
-       return cfs_trace_dump_debug_buffer_usrstr(buffer, nob);
-}
-
-static int proc_dump_kernel(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_dump_kernel);
-}
-
-static int __proc_daemon_file(void *data, int write,
-                             loff_t pos, void __user *buffer, int nob)
-{
-       if (!write) {
-               int len = strlen(cfs_tracefile);
-
-               if (pos >= len)
-                       return 0;
-
-               return cfs_trace_copyout_string(buffer, nob,
-                                               cfs_tracefile + pos, "\n");
-       }
-
-       return cfs_trace_daemon_command_usrstr(buffer, nob);
-}
-
-static int proc_daemon_file(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_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)
-{
-       if (write)
-               LBUG();
-       return 0;
-}
-
-static int proc_fail_loc(struct ctl_table *table, int write,
-                        void __user *buffer,
-                        size_t *lenp, loff_t *ppos)
-{
-       int rc;
-       long old_fail_loc = cfs_fail_loc;
-
-       rc = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
-       if (old_fail_loc != cfs_fail_loc)
-               wake_up(&cfs_race_waitq);
-       return rc;
-}
-
-static int __proc_cpt_table(void *data, int write,
-                           loff_t pos, void __user *buffer, int nob)
-{
-       char *buf = NULL;
-       int   len = 4096;
-       int   rc  = 0;
-
-       if (write)
-               return -EPERM;
-
-       LASSERT(cfs_cpt_table != NULL);
-
-       while (1) {
-               LIBCFS_ALLOC(buf, len);
-               if (buf == NULL)
-                       return -ENOMEM;
-
-               rc = cfs_cpt_table_print(cfs_cpt_table, buf, len);
-               if (rc >= 0)
-                       break;
-
-               if (rc == -EFBIG) {
-                       LIBCFS_FREE(buf, len);
-                       len <<= 1;
-                       continue;
-               }
-               goto out;
-       }
-
-       if (pos >= rc) {
-               rc = 0;
-               goto out;
-       }
-
-       rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
- out:
-       if (buf != NULL)
-               LIBCFS_FREE(buf, len);
-       return rc;
-}
-
-static int proc_cpt_table(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_cpt_table);
-}
-
-static struct ctl_table lnet_table[] = {
-       /*
-        * NB No .strategy entries have been provided since sysctl(8) prefers
-        * to go via /proc for portability.
-        */
-       {
-               .procname = "debug",
-               .data     = &libcfs_debug,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dobitmasks,
-       },
-       {
-               .procname = "subsystem_debug",
-               .data     = &libcfs_subsystem_debug,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dobitmasks,
-       },
-       {
-               .procname = "printk",
-               .data     = &libcfs_printk,
-               .maxlen   = sizeof(int),
-               .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,
-               .mode     = 0444,
-               .proc_handler = &proc_cpt_table,
-       },
-
-       {
-               .procname = "upcall",
-               .data     = lnet_upcall,
-               .maxlen   = sizeof(lnet_upcall),
-               .mode     = 0644,
-               .proc_handler = &proc_dostring,
-       },
-       {
-               .procname = "debug_log_upcall",
-               .data     = lnet_debug_log_upcall,
-               .maxlen   = sizeof(lnet_debug_log_upcall),
-               .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,
-               .maxlen   = sizeof(int),
-               .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,
-               .mode     = 0200,
-               .proc_handler = &proc_dump_kernel,
-       },
-       {
-               .procname = "daemon_file",
-               .mode     = 0644,
-               .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,
-               .maxlen   = 0,
-               .mode     = 0200,
-               .proc_handler = &libcfs_force_lbug
-       },
-       {
-               .procname = "fail_loc",
-               .data     = &cfs_fail_loc,
-               .maxlen   = sizeof(cfs_fail_loc),
-               .mode     = 0644,
-               .proc_handler = &proc_fail_loc
-       },
-       {
-               .procname = "fail_val",
-               .data     = &cfs_fail_val,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dointvec
-       },
-       {
-       }
-};
-
-static struct ctl_table top_table[] = {
-       {
-               .procname = "lnet",
-               .mode     = 0555,
-               .data     = NULL,
-               .maxlen   = 0,
-               .child    = lnet_table,
-       },
-       {
-       }
-};
-
-int insert_proc(void)
-{
-       if (lnet_table_header == NULL)
-               lnet_table_header = register_sysctl_table(top_table);
-       return 0;
-}
-
-void remove_proc(void)
-{
-       if (lnet_table_header != NULL)
-               unregister_sysctl_table(lnet_table_header);
-
-       lnet_table_header = NULL;
-}
index cd2fc01dea4cfb446851a47a61bd40e0ea412a3b..f2462e7f04bc40dd4b4dd3798eecdad08b52f3ff 100644 (file)
@@ -543,19 +543,17 @@ libcfs_sock_accept (struct socket **newsockp, struct socket *sock)
 
        newsock->ops = sock->ops;
 
-       set_current_state(TASK_INTERRUPTIBLE);
-       add_wait_queue(sk_sleep(sock->sk), &wait);
-
        rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
        if (rc == -EAGAIN) {
                /* Nothing ready, so wait for activity */
+               set_current_state(TASK_INTERRUPTIBLE);
+               add_wait_queue(sk_sleep(sock->sk), &wait);
                schedule();
+               remove_wait_queue(sk_sleep(sock->sk), &wait);
+               set_current_state(TASK_RUNNING);
                rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
        }
 
-       remove_wait_queue(sk_sleep(sock->sk), &wait);
-       set_current_state(TASK_RUNNING);
-
        if (rc != 0)
                goto failed;
 
index 7dc77dd402b857df067c92f8937353fe6959d9d2..f0ee76abfd5a4ad8d2d34096688fbafb5c7e3f90 100644 (file)
  * This file is part of Lustre, http://www.lustre.org/
  * Lustre is a trademark of Sun Microsystems, Inc.
  */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <net/sock.h>
+#include <linux/uio.h>
 
-#define DEBUG_SUBSYSTEM S_LNET
+#include <linux/uaccess.h>
+
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/list.h>
+
+#include <linux/proc_fs.h>
+#include <linux/sysctl.h>
+
+# define DEBUG_SUBSYSTEM S_LNET
 
 #include "../../include/linux/libcfs/libcfs.h"
+#include <asm/div64.h>
+
 #include "../../include/linux/libcfs/libcfs_crypto.h"
 #include "../../include/linux/lnet/lib-lnet.h"
 #include "../../include/linux/lnet/lnet.h"
 #include "tracefile.h"
 
+MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
+MODULE_DESCRIPTION("Portals v3.1");
+MODULE_LICENSE("GPL");
+
+extern struct miscdevice libcfs_dev;
+extern struct rw_semaphore cfs_tracefile_sem;
+extern struct mutex cfs_trace_thread_mutex;
+extern struct cfs_wi_sched *cfs_sched_rehash;
+extern void libcfs_init_nidstrings(void);
+
+static int insert_proc(void);
+static void remove_proc(void);
+
+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)
 {
        struct page **level0p = &ldu->ldu_memhog_root_page;
@@ -320,19 +387,6 @@ struct cfs_psdev_ops libcfs_psdev_ops = {
        libcfs_ioctl
 };
 
-extern int insert_proc(void);
-extern void remove_proc(void);
-MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
-MODULE_DESCRIPTION("Portals v3.1");
-MODULE_LICENSE("GPL");
-
-extern struct miscdevice libcfs_dev;
-extern struct rw_semaphore cfs_tracefile_sem;
-extern struct mutex cfs_trace_thread_mutex;
-extern struct cfs_wi_sched *cfs_sched_rehash;
-
-extern void libcfs_init_nidstrings(void);
-
 static int init_libcfs_module(void)
 {
        int rc;
@@ -347,7 +401,7 @@ static int init_libcfs_module(void)
 
        rc = libcfs_debug_init(5 * 1024 * 1024);
        if (rc < 0) {
-               printk(KERN_ERR "LustreError: libcfs_debug_init: %d\n", rc);
+               pr_err("LustreError: libcfs_debug_init: %d\n", rc);
                return rc;
        }
 
@@ -433,12 +487,490 @@ static void exit_libcfs_module(void)
 
        rc = libcfs_debug_cleanup();
        if (rc)
-               printk(KERN_ERR "LustreError: libcfs_debug_cleanup: %d\n",
-                      rc);
+               pr_err("LustreError: libcfs_debug_cleanup: %d\n", rc);
 
        libcfs_arch_cleanup();
 }
 
+static int proc_call_handler(void *data, int write, loff_t *ppos,
+               void __user *buffer, size_t *lenp,
+               int (*handler)(void *data, int write,
+               loff_t pos, void __user *buffer, int len))
+{
+       int rc = handler(data, write, *ppos, buffer, *lenp);
+
+       if (rc < 0)
+               return rc;
+
+       if (write) {
+               *ppos += *lenp;
+       } else {
+               *lenp = rc;
+               *ppos += rc;
+       }
+       return 0;
+}
+
+static int __proc_dobitmasks(void *data, int write,
+                            loff_t pos, void __user *buffer, int nob)
+{
+       const int     tmpstrlen = 512;
+       char     *tmpstr;
+       int        rc;
+       unsigned int *mask = data;
+       int        is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
+       int        is_printk = (mask == &libcfs_printk) ? 1 : 0;
+
+       rc = cfs_trace_allocate_string_buffer(&tmpstr, tmpstrlen);
+       if (rc < 0)
+               return rc;
+
+       if (!write) {
+               libcfs_debug_mask2str(tmpstr, tmpstrlen, *mask, is_subsys);
+               rc = strlen(tmpstr);
+
+               if (pos >= rc) {
+                       rc = 0;
+               } else {
+                       rc = cfs_trace_copyout_string(buffer, nob,
+                                                     tmpstr + pos, "\n");
+               }
+       } else {
+               rc = cfs_trace_copyin_string(tmpstr, tmpstrlen, buffer, nob);
+               if (rc < 0) {
+                       cfs_trace_free_string_buffer(tmpstr, tmpstrlen);
+                       return rc;
+               }
+
+               rc = libcfs_debug_str2mask(mask, tmpstr, is_subsys);
+               /* Always print LBUG/LASSERT to console, so keep this mask */
+               if (is_printk)
+                       *mask |= D_EMERG;
+       }
+
+       cfs_trace_free_string_buffer(tmpstr, tmpstrlen);
+       return rc;
+}
+
+static int proc_dobitmasks(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_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)
+{
+       if (!write)
+               return 0;
+
+       return cfs_trace_dump_debug_buffer_usrstr(buffer, nob);
+}
+
+static int proc_dump_kernel(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_dump_kernel);
+}
+
+static int __proc_daemon_file(void *data, int write,
+                             loff_t pos, void __user *buffer, int nob)
+{
+       if (!write) {
+               int len = strlen(cfs_tracefile);
+
+               if (pos >= len)
+                       return 0;
+
+               return cfs_trace_copyout_string(buffer, nob,
+                                               cfs_tracefile + pos, "\n");
+       }
+
+       return cfs_trace_daemon_command_usrstr(buffer, nob);
+}
+
+static int proc_daemon_file(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_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)
+{
+       if (write)
+               LBUG();
+       return 0;
+}
+
+static int proc_fail_loc(struct ctl_table *table, int write,
+                        void __user *buffer,
+                        size_t *lenp, loff_t *ppos)
+{
+       int rc;
+       long old_fail_loc = cfs_fail_loc;
+
+       rc = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
+       if (old_fail_loc != cfs_fail_loc)
+               wake_up(&cfs_race_waitq);
+       return rc;
+}
+
+static int __proc_cpt_table(void *data, int write,
+                           loff_t pos, void __user *buffer, int nob)
+{
+       char *buf = NULL;
+       int   len = 4096;
+       int   rc  = 0;
+
+       if (write)
+               return -EPERM;
+
+       LASSERT(cfs_cpt_table != NULL);
+
+       while (1) {
+               LIBCFS_ALLOC(buf, len);
+               if (buf == NULL)
+                       return -ENOMEM;
+
+               rc = cfs_cpt_table_print(cfs_cpt_table, buf, len);
+               if (rc >= 0)
+                       break;
+
+               if (rc == -EFBIG) {
+                       LIBCFS_FREE(buf, len);
+                       len <<= 1;
+                       continue;
+               }
+               goto out;
+       }
+
+       if (pos >= rc) {
+               rc = 0;
+               goto out;
+       }
+
+       rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
+ out:
+       if (buf != NULL)
+               LIBCFS_FREE(buf, len);
+       return rc;
+}
+
+static int proc_cpt_table(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_cpt_table);
+}
+
+static struct ctl_table lnet_table[] = {
+       /*
+        * NB No .strategy entries have been provided since sysctl(8) prefers
+        * to go via /proc for portability.
+        */
+       {
+               .procname = "debug",
+               .data     = &libcfs_debug,
+               .maxlen   = sizeof(int),
+               .mode     = 0644,
+               .proc_handler = &proc_dobitmasks,
+       },
+       {
+               .procname = "subsystem_debug",
+               .data     = &libcfs_subsystem_debug,
+               .maxlen   = sizeof(int),
+               .mode     = 0644,
+               .proc_handler = &proc_dobitmasks,
+       },
+       {
+               .procname = "printk",
+               .data     = &libcfs_printk,
+               .maxlen   = sizeof(int),
+               .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,
+               .mode     = 0444,
+               .proc_handler = &proc_cpt_table,
+       },
+
+       {
+               .procname = "upcall",
+               .data     = lnet_upcall,
+               .maxlen   = sizeof(lnet_upcall),
+               .mode     = 0644,
+               .proc_handler = &proc_dostring,
+       },
+       {
+               .procname = "debug_log_upcall",
+               .data     = lnet_debug_log_upcall,
+               .maxlen   = sizeof(lnet_debug_log_upcall),
+               .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,
+               .maxlen   = sizeof(int),
+               .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,
+               .mode     = 0200,
+               .proc_handler = &proc_dump_kernel,
+       },
+       {
+               .procname = "daemon_file",
+               .mode     = 0644,
+               .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,
+               .maxlen   = 0,
+               .mode     = 0200,
+               .proc_handler = &libcfs_force_lbug
+       },
+       {
+               .procname = "fail_loc",
+               .data     = &cfs_fail_loc,
+               .maxlen   = sizeof(cfs_fail_loc),
+               .mode     = 0644,
+               .proc_handler = &proc_fail_loc
+       },
+       {
+               .procname = "fail_val",
+               .data     = &cfs_fail_val,
+               .maxlen   = sizeof(int),
+               .mode     = 0644,
+               .proc_handler = &proc_dointvec
+       },
+       {
+       }
+};
+
+static struct ctl_table top_table[] = {
+       {
+               .procname = "lnet",
+               .mode     = 0555,
+               .data     = NULL,
+               .maxlen   = 0,
+               .child    = lnet_table,
+       },
+       {
+       }
+};
+
+static int insert_proc(void)
+{
+       if (lnet_table_header == NULL)
+               lnet_table_header = register_sysctl_table(top_table);
+       return 0;
+}
+
+static void remove_proc(void)
+{
+       if (lnet_table_header != NULL)
+               unregister_sysctl_table(lnet_table_header);
+
+       lnet_table_header = NULL;
+}
+
 MODULE_VERSION("1.0.0");
+
 module_init(init_libcfs_module);
 module_exit(exit_libcfs_module);
index eb65b50f832deb36a2e8b3227ef54de58bc85176..c86394f7f4d9c32294eeb52a650255e4c24d208d 100644 (file)
@@ -53,7 +53,7 @@ char cfs_tracefile[TRACEFILE_NAME_SIZE];
 long long cfs_tracefile_size = CFS_TRACEFILE_SIZE;
 static struct tracefiled_ctl trace_tctl;
 struct mutex cfs_trace_thread_mutex;
-static int thread_running = 0;
+static int thread_running;
 
 static atomic_t cfs_tage_allocated = ATOMIC_INIT(0);
 
@@ -224,8 +224,7 @@ static struct cfs_trace_page *cfs_trace_get_tage(struct cfs_trace_cpu_data *tcd,
         */
 
        if (len > PAGE_CACHE_SIZE) {
-               printk(KERN_ERR
-                      "cowardly refusing to write %lu bytes in a page\n", len);
+               pr_err("cowardly refusing to write %lu bytes in a page\n", len);
                return NULL;
        }
 
@@ -688,8 +687,8 @@ int cfs_tracefile_dump_all_pages(char *filename)
        if (IS_ERR(filp)) {
                rc = PTR_ERR(filp);
                filp = NULL;
-               printk(KERN_ERR "LustreError: can't open %s for dump: rc %d\n",
-                     filename, rc);
+               pr_err("LustreError: can't open %s for dump: rc %d\n",
+                       filename, rc);
                goto out;
        }
 
@@ -726,7 +725,7 @@ int cfs_tracefile_dump_all_pages(char *filename)
        MMSPACE_CLOSE;
        rc = vfs_fsync(filp, 1);
        if (rc)
-               printk(KERN_ERR "sync returns %d\n", rc);
+               pr_err("sync returns %d\n", rc);
 close:
        filp_close(filp, NULL);
 out:
@@ -1048,22 +1047,21 @@ static int tracefiled(void *arg)
                        int i;
 
                        printk(KERN_ALERT "Lustre: trace pages aren't empty\n");
-                       printk(KERN_ERR "total cpus(%d): ",
-                              num_possible_cpus());
+                       pr_err("total cpus(%d): ",
+                               num_possible_cpus());
                        for (i = 0; i < num_possible_cpus(); i++)
                                if (cpu_online(i))
-                                       printk(KERN_ERR "%d(on) ", i);
+                                       pr_cont("%d(on) ", i);
                                else
-                                       printk(KERN_ERR "%d(off) ", i);
-                       printk(KERN_ERR "\n");
+                                       pr_cont("%d(off) ", i);
+                       pr_cont("\n");
 
                        i = 0;
                        list_for_each_entry_safe(tage, tmp, &pc.pc_pages,
                                                     linkage)
-                               printk(KERN_ERR "page %d belongs to cpu %d\n",
-                                      ++i, tage->cpu);
-                       printk(KERN_ERR "There are %d pages unwritten\n",
-                              i);
+                               pr_err("page %d belongs to cpu %d\n",
+                                       ++i, tage->cpu);
+                       pr_err("There are %d pages unwritten\n", i);
                }
                __LASSERT(list_empty(&pc.pc_pages));
 end_loop:
index c4afaeaf83105d42b59d920351fb4582a7867700..48009b7758456acae626aa1ae576acea5c20078d 100644 (file)
@@ -442,7 +442,7 @@ cfs_wi_startup(void)
 }
 
 void
-cfs_wi_shutdown (void)
+cfs_wi_shutdown(void)
 {
        struct cfs_wi_sched     *sched;
 
index ddf1fa9f67f8f80fbb8237260a0b4bef3a74b0d4..fe1fd05423e9b6aec1d1cd55e38937a3d1f32d73 100644 (file)
@@ -128,7 +128,7 @@ static int find_cbdata(struct inode *inode)
        rc = md_find_cbdata(sbi->ll_md_exp, ll_inode2fid(inode),
                            return_if_equal, NULL);
        if (rc != 0)
-                return rc;
+               return rc;
 
        lsm = ccc_inode_lsm_get(inode);
        if (lsm == NULL)
@@ -339,13 +339,10 @@ static int ll_revalidate_dentry(struct dentry *dentry,
  */
 static int ll_revalidate_nd(struct dentry *dentry, unsigned int flags)
 {
-       int rc;
-
        CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, flags=%u\n",
               dentry, flags);
 
-       rc = ll_revalidate_dentry(dentry, flags);
-       return rc;
+       return ll_revalidate_dentry(dentry, flags);
 }
 
 
index a18201913273d0ddd444de2ed5561ec27f1bbe6f..a5bc694dcb64aa1193b66a6f8614fd71a0d2b43b 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/mm.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/buffer_head.h>   /* for wait_on_buffer */
 #include <linux/pagevec.h>
 #include <linux/prefetch.h>
@@ -1518,6 +1518,7 @@ out_rmdir:
                        lump = (struct lov_user_md *)arg;
                } else {
                        struct lov_user_mds_data *lmdp;
+
                        lmdp = (struct lov_user_mds_data *)arg;
                        lump = &lmdp->lmd_lmm;
                }
@@ -1909,21 +1910,21 @@ static loff_t ll_dir_seek(struct file *file, loff_t offset, int origin)
 
        mutex_lock(&inode->i_mutex);
        switch (origin) {
-               case SEEK_SET:
-                       break;
-               case SEEK_CUR:
-                       offset += file->f_pos;
-                       break;
-               case SEEK_END:
-                       if (offset > 0)
-                               goto out;
-                       if (api32)
-                               offset += LL_DIR_END_OFF_32BIT;
-                       else
-                               offset += LL_DIR_END_OFF;
-                       break;
-               default:
+       case SEEK_SET:
+               break;
+       case SEEK_CUR:
+               offset += file->f_pos;
+               break;
+       case SEEK_END:
+               if (offset > 0)
                        goto out;
+               if (api32)
+                       offset += LL_DIR_END_OFF_32BIT;
+               else
+                       offset += LL_DIR_END_OFF;
+               break;
+       default:
+               goto out;
        }
 
        if (offset >= 0 &&
index 5ebee6ca0a108330711cd02aefea5f87eaccd771..85e74d18d1c70bdeae1e639d6cd3b4ecdbd1782b 100644 (file)
@@ -161,7 +161,7 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp,
                op_data->op_lease_handle = och->och_lease_handle;
                op_data->op_attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS;
        }
-       epoch_close = (op_data->op_flags & MF_EPOCH_CLOSE);
+       epoch_close = op_data->op_flags & MF_EPOCH_CLOSE;
        rc = md_close(md_exp, op_data, och->och_mod, &req);
        if (rc == -EAGAIN) {
                /* This close must have the epoch closed. */
@@ -197,6 +197,7 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp,
        }
        if (rc == 0 && op_data->op_bias & MDS_HSM_RELEASE) {
                struct mdt_body *body;
+
                body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
                if (!(body->valid & OBD_MD_FLRELEASED))
                        rc = -EBUSY;
@@ -269,7 +270,7 @@ static int ll_md_close(struct obd_export *md_exp, struct inode *inode,
        int lockmode;
        __u64 flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_TEST_LOCK;
        struct lustre_handle lockh;
-       ldlm_policy_data_t policy = {.l_inodebits={MDS_INODELOCK_OPEN}};
+       ldlm_policy_data_t policy = {.l_inodebits = {MDS_INODELOCK_OPEN}};
        int rc = 0;
 
        /* clear group lock, if present */
@@ -692,7 +693,7 @@ restart:
 out_och_free:
        if (rc) {
                if (och_p && *och_p) {
-                       OBD_FREE(*och_p, sizeof (struct obd_client_handle));
+                       OBD_FREE(*och_p, sizeof(struct obd_client_handle));
                        *och_p = NULL; /* OBD_FREE writes some magic there */
                        (*och_usecount)--;
                }
@@ -1711,6 +1712,12 @@ static int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap,
        fm_key.oa.o_oi = lsm->lsm_oi;
        fm_key.oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
 
+       if (i_size_read(inode) == 0) {
+               rc = ll_glimpse_size(inode);
+               if (rc)
+                       goto out;
+       }
+
        obdo_from_inode(&fm_key.oa, inode, OBD_MD_FLSIZE);
        obdo_set_parent_fid(&fm_key.oa, &ll_i2info(inode)->lli_fid);
        /* If filesize is 0, then there would be no objects for mapping */
@@ -2821,7 +2828,7 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits,  ldlm_mode_t l_req_mode)
        int i;
 
        if (!inode)
-              return 0;
+               return 0;
 
        fid = &ll_i2info(inode)->lli_fid;
        CDEBUG(D_INFO, "trying to match res "DFID" mode %s\n", PFID(fid),
@@ -3233,6 +3240,7 @@ void *ll_iocontrol_register(llioc_callback_t cb, int count, unsigned int *cmd)
 
        return in_data;
 }
+EXPORT_SYMBOL(ll_iocontrol_register);
 
 void ll_iocontrol_unregister(void *magic)
 {
@@ -3257,8 +3265,6 @@ void ll_iocontrol_unregister(void *magic)
 
        CWARN("didn't find iocontrol register block with magic: %p\n", magic);
 }
-
-EXPORT_SYMBOL(ll_iocontrol_register);
 EXPORT_SYMBOL(ll_iocontrol_unregister);
 
 static enum llioc_iter
index 21b4a50267765d1f214b934be5221d83b6c9bb0d..a94ba02ccf02ea843db696875eb8a8cd1fef1cbe 100644 (file)
@@ -284,10 +284,8 @@ static void ll_done_writing(struct inode *inode)
        LASSERT(exp_connect_som(ll_i2mdexp(inode)));
 
        op_data = kzalloc(sizeof(*op_data), GFP_NOFS);
-       if (!op_data) {
-               CERROR("can't allocate op_data\n");
+       if (!op_data)
                return;
-       }
 
        ll_prepare_done_writing(inode, op_data, &och);
        /* If there is no @och, we do not do D_W yet. */
index 0c1b583a4ea1fe77fd5e694e2f35e312cf0ae271..bf1ec277a1dc72072592551563e4b534f1ef7532 100644 (file)
@@ -87,11 +87,10 @@ static struct ll_sb_info *ll_init_sbi(void)
 
        si_meminfo(&si);
        pages = si.totalram - si.totalhigh;
-       if (pages >> (20 - PAGE_CACHE_SHIFT) < 512) {
+       if (pages >> (20 - PAGE_CACHE_SHIFT) < 512)
                lru_page_max = pages / 2;
-       } else {
+       else
                lru_page_max = (pages / 4) * 3;
-       }
 
        /* initialize lru data */
        atomic_set(&sbi->ll_cache.ccc_users, 0);
@@ -621,7 +620,7 @@ int ll_get_max_mdsize(struct ll_sb_info *sbi, int *lmmsize)
        rc = obd_get_info(NULL, sbi->ll_md_exp, sizeof(KEY_MAX_EASIZE),
                          KEY_MAX_EASIZE, &size, lmmsize, NULL);
        if (rc)
-               CERROR("Get max mdsize error rc %d \n", rc);
+               CERROR("Get max mdsize error rc %d\n", rc);
 
        return rc;
 }
@@ -978,19 +977,17 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt)
        CDEBUG(D_CONFIG, "Found profile %s: mdc=%s osc=%s\n", profilenm,
               lprof->lp_md, lprof->lp_dt);
 
-       dt = kzalloc(strlen(lprof->lp_dt) + instlen + 2, GFP_NOFS);
+       dt = kasprintf(GFP_NOFS, "%s-%p", lprof->lp_dt, cfg->cfg_instance);
        if (!dt) {
                err = -ENOMEM;
                goto out_free;
        }
-       sprintf(dt, "%s-%p", lprof->lp_dt, cfg->cfg_instance);
 
-       md = kzalloc(strlen(lprof->lp_md) + instlen + 2, GFP_NOFS);
+       md = kasprintf(GFP_NOFS, "%s-%p", lprof->lp_md, cfg->cfg_instance);
        if (!md) {
                err = -ENOMEM;
                goto out_free;
        }
-       sprintf(md, "%s-%p", lprof->lp_md, cfg->cfg_instance);
 
        /* connections, registrations, sb setup */
        err = client_common_fill_super(sb, md, dt, mnt);
@@ -1432,7 +1429,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import)
 
        if (attr->ia_valid & (ATTR_SIZE |
                              ATTR_ATIME | ATTR_ATIME_SET |
-                             ATTR_MTIME | ATTR_MTIME_SET))
+                             ATTR_MTIME | ATTR_MTIME_SET)) {
                /* For truncate and utimes sending attributes to OSTs, setting
                 * mtime/atime to the past will be performed under PW [0:EOF]
                 * extent lock (new_size:EOF for truncate).  It may seem
@@ -1444,6 +1441,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import)
                rc = ll_setattr_ost(inode, attr);
                if (attr->ia_valid & ATTR_SIZE)
                        up_write(&lli->lli_trunc_sem);
+       }
 out:
        if (op_data) {
                if (op_data->op_ioepoch) {
@@ -1608,7 +1606,7 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md)
        struct lov_stripe_md *lsm = md->lsm;
        struct ll_sb_info *sbi = ll_i2sbi(inode);
 
-       LASSERT ((lsm != NULL) == ((body->valid & OBD_MD_FLEASIZE) != 0));
+       LASSERT((lsm != NULL) == ((body->valid & OBD_MD_FLEASIZE) != 0));
        if (lsm != NULL) {
                if (!lli->lli_has_smd &&
                    !(sbi->ll_flags & LL_SBI_LAYOUT_LOCK))
@@ -2152,7 +2150,8 @@ int ll_process_config(struct lustre_cfg *lcfg)
        ptr = strrchr(lustre_cfg_string(lcfg, 0), '-');
        if (!ptr || !*(++ptr))
                return -EINVAL;
-       if (sscanf(ptr, "%lx", &x) != 1)
+       rc = kstrtoul(ptr, 16, &x);
+       if (rc != 0)
                return -EINVAL;
        sb = (void *)x;
        /* This better be a real Lustre superblock! */
index 479bf428780ce766c18faaf211372126f732a28d..a90214bb84ddfe7f3e32d47d8a901935c1af97bd 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <linux/fs.h>
 #include <linux/pagemap.h>
@@ -312,7 +312,7 @@ static int ll_fault0(struct vm_area_struct *vma, struct vm_fault *vmf)
                vio->u.fault.ft_vmpage    = NULL;
                vio->u.fault.fault.ft_vmf = vmf;
                vio->u.fault.fault.ft_flags = 0;
-               vio->u.fault.fault.ft_flags_valid = 0;
+               vio->u.fault.fault.ft_flags_valid = false;
 
                result = cl_io_loop(env, io);
 
index 031248840642a5dc3d40d6d3b03c1f589db4f625..413a8408e3f5b97cb74518a82aaeb3e25d2b8d0d 100644 (file)
 #include <linux/highmem.h>
 #include <linux/gfp.h>
 #include <linux/pagevec.h>
-
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "../include/lustre_lib.h"
 #include "../include/lustre_lite.h"
@@ -349,7 +348,7 @@ static void loop_make_request(struct request_queue *q, struct bio *old_bio)
               old_bio->bi_iter.bi_size);
 
        spin_lock_irq(&lo->lo_lock);
-       inactive = (lo->lo_state != LLOOP_BOUND);
+       inactive = lo->lo_state != LLOOP_BOUND;
        spin_unlock_irq(&lo->lo_lock);
        if (inactive)
                goto err;
index aaa13bd3e8dea86eab9c3980c442183f532bedcc..83a9b85474e1291ec45257aa0d83a94fdfb48606 100644 (file)
@@ -59,7 +59,7 @@ static int ll_blksize_seq_show(struct seq_file *m, void *v)
                                cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
                                OBD_STATFS_NODELAY);
        if (!rc)
-             rc = seq_printf(m, "%u\n", osfs.os_bsize);
+               seq_printf(m, "%u\n", osfs.os_bsize);
 
        return rc;
 }
@@ -82,8 +82,9 @@ static int ll_kbytestotal_seq_show(struct seq_file *m, void *v)
                while (blk_size >>= 1)
                        result <<= 1;
 
-               rc = seq_printf(m, "%llu\n", result);
+               seq_printf(m, "%llu\n", result);
        }
+
        return rc;
 }
 LPROC_SEQ_FOPS_RO(ll_kbytestotal);
@@ -105,8 +106,9 @@ static int ll_kbytesfree_seq_show(struct seq_file *m, void *v)
                while (blk_size >>= 1)
                        result <<= 1;
 
-               rc = seq_printf(m, "%llu\n", result);
+               seq_printf(m, "%llu\n", result);
        }
+
        return rc;
 }
 LPROC_SEQ_FOPS_RO(ll_kbytesfree);
@@ -128,8 +130,9 @@ static int ll_kbytesavail_seq_show(struct seq_file *m, void *v)
                while (blk_size >>= 1)
                        result <<= 1;
 
-               rc = seq_printf(m, "%llu\n", result);
+               seq_printf(m, "%llu\n", result);
        }
+
        return rc;
 }
 LPROC_SEQ_FOPS_RO(ll_kbytesavail);
@@ -145,7 +148,8 @@ static int ll_filestotal_seq_show(struct seq_file *m, void *v)
                                cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
                                OBD_STATFS_NODELAY);
        if (!rc)
-                rc = seq_printf(m, "%llu\n", osfs.os_files);
+               seq_printf(m, "%llu\n", osfs.os_files);
+
        return rc;
 }
 LPROC_SEQ_FOPS_RO(ll_filestotal);
@@ -161,7 +165,8 @@ static int ll_filesfree_seq_show(struct seq_file *m, void *v)
                                cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
                                OBD_STATFS_NODELAY);
        if (!rc)
-                rc = seq_printf(m, "%llu\n", osfs.os_ffree);
+               seq_printf(m, "%llu\n", osfs.os_ffree);
+
        return rc;
 }
 LPROC_SEQ_FOPS_RO(ll_filesfree);
@@ -169,16 +174,15 @@ LPROC_SEQ_FOPS_RO(ll_filesfree);
 static int ll_client_type_seq_show(struct seq_file *m, void *v)
 {
        struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private);
-       int rc;
 
        LASSERT(sbi != NULL);
 
        if (sbi->ll_flags & LL_SBI_RMT_CLIENT)
-               rc = seq_printf(m, "remote client\n");
+               seq_puts(m, "remote client\n");
        else
-               rc = seq_printf(m, "local client\n");
+               seq_puts(m, "local client\n");
 
-       return rc;
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(ll_client_type);
 
@@ -187,7 +191,8 @@ static int ll_fstype_seq_show(struct seq_file *m, void *v)
        struct super_block *sb = (struct super_block *)m->private;
 
        LASSERT(sb != NULL);
-       return seq_printf(m, "%s\n", sb->s_type->name);
+       seq_printf(m, "%s\n", sb->s_type->name);
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(ll_fstype);
 
@@ -196,7 +201,8 @@ static int ll_sb_uuid_seq_show(struct seq_file *m, void *v)
        struct super_block *sb = (struct super_block *)m->private;
 
        LASSERT(sb != NULL);
-       return seq_printf(m, "%s\n", ll_s2sbi(sb)->ll_sb_uuid.uuid);
+       seq_printf(m, "%s\n", ll_s2sbi(sb)->ll_sb_uuid.uuid);
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(ll_sb_uuid);
 
@@ -353,17 +359,18 @@ static int ll_max_cached_mb_seq_show(struct seq_file *m, void *v)
 
        max_cached_mb = cache->ccc_lru_max >> shift;
        unused_mb = atomic_read(&cache->ccc_lru_left) >> shift;
-       return seq_printf(m,
-                       "users: %d\n"
-                       "max_cached_mb: %d\n"
-                       "used_mb: %d\n"
-                       "unused_mb: %d\n"
-                       "reclaim_count: %u\n",
-                       atomic_read(&cache->ccc_users),
-                       max_cached_mb,
-                       max_cached_mb - unused_mb,
-                       unused_mb,
-                       cache->ccc_lru_shrinkers);
+       seq_printf(m,
+                  "users: %d\n"
+                  "max_cached_mb: %d\n"
+                  "used_mb: %d\n"
+                  "unused_mb: %d\n"
+                  "reclaim_count: %u\n",
+                  atomic_read(&cache->ccc_users),
+                  max_cached_mb,
+                  max_cached_mb - unused_mb,
+                  unused_mb,
+                  cache->ccc_lru_shrinkers);
+       return 0;
 }
 
 static ssize_t ll_max_cached_mb_seq_write(struct file *file,
@@ -467,7 +474,8 @@ static int ll_checksum_seq_show(struct seq_file *m, void *v)
        struct super_block *sb = m->private;
        struct ll_sb_info *sbi = ll_s2sbi(sb);
 
-       return seq_printf(m, "%u\n", (sbi->ll_flags & LL_SBI_CHECKSUM) ? 1 : 0);
+       seq_printf(m, "%u\n", (sbi->ll_flags & LL_SBI_CHECKSUM) ? 1 : 0);
+       return 0;
 }
 
 static ssize_t ll_checksum_seq_write(struct file *file,
@@ -503,7 +511,8 @@ static int ll_max_rw_chunk_seq_show(struct seq_file *m, void *v)
 {
        struct super_block *sb = m->private;
 
-       return seq_printf(m, "%lu\n", ll_s2sbi(sb)->ll_max_rw_chunk);
+       seq_printf(m, "%lu\n", ll_s2sbi(sb)->ll_max_rw_chunk);
+       return 0;
 }
 
 static ssize_t ll_max_rw_chunk_seq_write(struct file *file,
@@ -525,15 +534,14 @@ static int ll_rd_track_id(struct seq_file *m, enum stats_track_type type)
 {
        struct super_block *sb = m->private;
 
-       if (ll_s2sbi(sb)->ll_stats_track_type == type) {
-               return seq_printf(m, "%d\n",
-                               ll_s2sbi(sb)->ll_stats_track_id);
+       if (ll_s2sbi(sb)->ll_stats_track_type == type)
+               seq_printf(m, "%d\n", ll_s2sbi(sb)->ll_stats_track_id);
+       else if (ll_s2sbi(sb)->ll_stats_track_type == STATS_TRACK_ALL)
+               seq_puts(m, "0 (all)\n");
+       else
+               seq_puts(m, "untracked\n");
 
-       } else if (ll_s2sbi(sb)->ll_stats_track_type == STATS_TRACK_ALL) {
-               return seq_printf(m, "0 (all)\n");
-       } else {
-               return seq_printf(m, "untracked\n");
-       }
+       return 0;
 }
 
 static int ll_wr_track_id(const char __user *buffer, unsigned long count,
@@ -601,7 +609,8 @@ static int ll_statahead_max_seq_show(struct seq_file *m, void *v)
        struct super_block *sb = m->private;
        struct ll_sb_info *sbi = ll_s2sbi(sb);
 
-       return seq_printf(m, "%u\n", sbi->ll_sa_max);
+       seq_printf(m, "%u\n", sbi->ll_sa_max);
+       return 0;
 }
 
 static ssize_t ll_statahead_max_seq_write(struct file *file,
@@ -631,8 +640,8 @@ static int ll_statahead_agl_seq_show(struct seq_file *m, void *v)
        struct super_block *sb = m->private;
        struct ll_sb_info *sbi = ll_s2sbi(sb);
 
-       return seq_printf(m, "%u\n",
-                       sbi->ll_flags & LL_SBI_AGL_ENABLED ? 1 : 0);
+       seq_printf(m, "%u\n", sbi->ll_flags & LL_SBI_AGL_ENABLED ? 1 : 0);
+       return 0;
 }
 
 static ssize_t ll_statahead_agl_seq_write(struct file *file,
@@ -661,13 +670,14 @@ static int ll_statahead_stats_seq_show(struct seq_file *m, void *v)
        struct super_block *sb = m->private;
        struct ll_sb_info *sbi = ll_s2sbi(sb);
 
-       return seq_printf(m,
-                       "statahead total: %u\n"
-                       "statahead wrong: %u\n"
-                       "agl total: %u\n",
-                       atomic_read(&sbi->ll_sa_total),
-                       atomic_read(&sbi->ll_sa_wrong),
-                       atomic_read(&sbi->ll_agl_total));
+       seq_printf(m,
+                  "statahead total: %u\n"
+                  "statahead wrong: %u\n"
+                  "agl total: %u\n",
+                  atomic_read(&sbi->ll_sa_total),
+                  atomic_read(&sbi->ll_sa_wrong),
+                  atomic_read(&sbi->ll_agl_total));
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(ll_statahead_stats);
 
@@ -676,8 +686,8 @@ static int ll_lazystatfs_seq_show(struct seq_file *m, void *v)
        struct super_block *sb = m->private;
        struct ll_sb_info *sbi = ll_s2sbi(sb);
 
-       return seq_printf(m, "%u\n",
-                       (sbi->ll_flags & LL_SBI_LAZYSTATFS) ? 1 : 0);
+       seq_printf(m, "%u\n", sbi->ll_flags & LL_SBI_LAZYSTATFS ? 1 : 0);
+       return 0;
 }
 
 static ssize_t ll_lazystatfs_seq_write(struct file *file,
@@ -712,11 +722,12 @@ static int ll_max_easize_seq_show(struct seq_file *m, void *v)
        if (rc)
                return rc;
 
-       return seq_printf(m, "%u\n", ealen);
+       seq_printf(m, "%u\n", ealen);
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(ll_max_easize);
 
-static int ll_defult_easize_seq_show(struct seq_file *m, void *v)
+static int ll_default_easize_seq_show(struct seq_file *m, void *v)
 {
        struct super_block *sb = m->private;
        struct ll_sb_info *sbi = ll_s2sbi(sb);
@@ -727,9 +738,10 @@ static int ll_defult_easize_seq_show(struct seq_file *m, void *v)
        if (rc)
                return rc;
 
-       return seq_printf(m, "%u\n", ealen);
+       seq_printf(m, "%u\n", ealen);
+       return 0;
 }
-LPROC_SEQ_FOPS_RO(ll_defult_easize);
+LPROC_SEQ_FOPS_RO(ll_default_easize);
 
 static int ll_max_cookiesize_seq_show(struct seq_file *m, void *v)
 {
@@ -742,11 +754,12 @@ static int ll_max_cookiesize_seq_show(struct seq_file *m, void *v)
        if (rc)
                return rc;
 
-       return seq_printf(m, "%u\n", cookielen);
+       seq_printf(m, "%u\n", cookielen);
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(ll_max_cookiesize);
 
-static int ll_defult_cookiesize_seq_show(struct seq_file *m, void *v)
+static int ll_default_cookiesize_seq_show(struct seq_file *m, void *v)
 {
        struct super_block *sb = m->private;
        struct ll_sb_info *sbi = ll_s2sbi(sb);
@@ -757,9 +770,10 @@ static int ll_defult_cookiesize_seq_show(struct seq_file *m, void *v)
        if (rc)
                return rc;
 
-       return seq_printf(m, "%u\n", cookielen);
+       seq_printf(m, "%u\n", cookielen);
+       return 0;
 }
-LPROC_SEQ_FOPS_RO(ll_defult_cookiesize);
+LPROC_SEQ_FOPS_RO(ll_default_cookiesize);
 
 static int ll_sbi_flags_seq_show(struct seq_file *m, void *v)
 {
@@ -789,11 +803,10 @@ static int ll_xattr_cache_seq_show(struct seq_file *m, void *v)
 {
        struct super_block *sb = m->private;
        struct ll_sb_info *sbi = ll_s2sbi(sb);
-       int rc;
 
-       rc = seq_printf(m, "%u\n", sbi->ll_xattr_cache_enabled);
+       seq_printf(m, "%u\n", sbi->ll_xattr_cache_enabled);
 
-       return rc;
+       return 0;
 }
 
 static ssize_t ll_xattr_cache_seq_write(struct file *file,
@@ -849,9 +862,9 @@ static struct lprocfs_vars lprocfs_llite_obd_vars[] = {
        { "statahead_stats",  &ll_statahead_stats_fops, NULL, 0 },
        { "lazystatfs",       &ll_lazystatfs_fops, NULL },
        { "max_easize",       &ll_max_easize_fops, NULL, 0 },
-       { "default_easize",   &ll_defult_easize_fops, NULL, 0 },
+       { "default_easize",   &ll_default_easize_fops, NULL, 0 },
        { "max_cookiesize",   &ll_max_cookiesize_fops, NULL, 0 },
-       { "default_cookiesize", &ll_defult_cookiesize_fops, NULL, 0 },
+       { "default_cookiesize", &ll_default_cookiesize_fops, NULL, 0 },
        { "sbi_flags",        &ll_sbi_flags_fops, NULL, 0 },
        { "xattr_cache",      &ll_xattr_cache_fops, NULL, 0 },
        { NULL }
index 890ac190f5faf3300ab8461f08cfe63182078c27..49f1cb067ea2d8514e977ccfc8add30095dd51fc 100644 (file)
@@ -83,7 +83,8 @@ static int ll_set_inode(struct inode *inode, void *opaque)
 
        lli->lli_fid = body->fid1;
        if (unlikely(!(body->valid & OBD_MD_FLTYPE))) {
-               CERROR("Can not initialize inode " DFID " without object type: valid = %#llx\n",
+               CERROR("Can not initialize inode " DFID
+                      " without object type: valid = %#llx\n",
                       PFID(&lli->lli_fid), body->valid);
                return -EINVAL;
        }
@@ -600,7 +601,8 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
        long long lookup_flags = LOOKUP_OPEN;
        int rc = 0;
 
-       CDEBUG(D_VFSTRACE, "VFS Op:name=%pd,dir=%lu/%u(%p),file %p,open_flags %x,mode %x opened %d\n",
+       CDEBUG(D_VFSTRACE,
+              "VFS Op:name=%pd,dir=%lu/%u(%p),file %p,open_flags %x,mode %x opened %d\n",
               dentry, dir->i_ino,
               dir->i_generation, dir, file, open_flags, mode, *opened);
 
@@ -974,11 +976,12 @@ out:
  * Instead, ll_ddelete() and ll_d_iput() will update it based upon if there
  * is any lock existing. They will recycle dentries and inodes based upon locks
  * too. b=20433 */
-static int ll_unlink(struct inode * dir, struct dentry *dentry)
+static int ll_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct ptlrpc_request *request = NULL;
        struct md_op_data *op_data;
        int rc;
+
        CDEBUG(D_VFSTRACE, "VFS Op:name=%pd,dir=%lu/%u(%p)\n",
               dentry, dir->i_ino, dir->i_generation, dir);
 
@@ -1033,7 +1036,7 @@ static int ll_rmdir(struct inode *dir, struct dentry *dentry)
               dentry, dir->i_ino, dir->i_generation, dir);
 
        op_data = ll_prep_md_op_data(NULL, dir, NULL,
-                                    dentry->d_name.name, 
+                                    dentry->d_name.name,
                                     dentry->d_name.len,
                                     S_IFDIR, LUSTRE_OPC_ANY, NULL);
        if (IS_ERR(op_data))
@@ -1111,10 +1114,9 @@ static int ll_rename(struct inode *old_dir, struct dentry *old_dentry,
        int err;
 
        CDEBUG(D_VFSTRACE,
-              "VFS Op:oldname=%pd,src_dir=%lu/%u(%p),newname=%pd,"
-              "tgt_dir=%lu/%u(%p)\n", old_dentry,
-              old_dir->i_ino, old_dir->i_generation, old_dir, new_dentry,
-              new_dir->i_ino, new_dir->i_generation, new_dir);
+              "VFS Op:oldname=%pd,src_dir=%lu/%u(%p),newname=%pd,tgt_dir=%lu/%u(%p)\n",
+              old_dentry, old_dir->i_ino, old_dir->i_generation, old_dir,
+              new_dentry, new_dir->i_ino, new_dir->i_generation, new_dir);
 
        op_data = ll_prep_md_op_data(NULL, old_dir, new_dir, NULL, 0, 0,
                                     LUSTRE_OPC_ANY, NULL);
index 10a0421366d08941415eda26c6f65ab14b3a6e87..991d20c5065d3d0e83b169614cc474c54fa6d46d 100644 (file)
@@ -45,7 +45,7 @@
 #include <linux/errno.h>
 #include <linux/unistd.h>
 #include <linux/writeback.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <linux/fs.h>
 #include <linux/pagemap.h>
@@ -750,7 +750,7 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io,
                /* Note: we only trim the RPC, instead of extending the RPC
                 * to the boundary, so to avoid reading too much pages during
                 * random reading. */
-               rpc_boundary = ((end + 1) & (~(PTLRPC_MAX_BRW_PAGES - 1)));
+               rpc_boundary = (end + 1) & (~(PTLRPC_MAX_BRW_PAGES - 1));
                if (rpc_boundary > 0)
                        rpc_boundary--;
 
index 2f21304046aa9335e438b36f462be4aa62cbebd3..91442fab57255df1f4ebd41fa0bfaaf83b24dca2 100644 (file)
@@ -44,7 +44,7 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <linux/migrate.h>
 #include <linux/fs.h>
index 6ad9dd0fe2b3d9d7da842e9af2d895a1097c42e6..b75562c6b5de95700b6ee1ee8eeae6e6e54931a6 100644 (file)
@@ -84,7 +84,7 @@ struct ll_sa_entry {
        struct qstr          se_qstr;
 };
 
-static unsigned int sai_generation = 0;
+static unsigned int sai_generation;
 static DEFINE_SPINLOCK(sai_generation_lock);
 
 static inline int ll_sa_entry_unhashed(struct ll_sa_entry *entry)
@@ -706,11 +706,21 @@ static int ll_statahead_interpret(struct ptlrpc_request *req,
        struct ll_inode_info     *lli = ll_i2info(dir);
        struct ll_statahead_info *sai = NULL;
        struct ll_sa_entry       *entry;
+       __u64                     handle = 0;
        int                    wakeup;
 
        if (it_disposition(it, DISP_LOOKUP_NEG))
                rc = -ENOENT;
 
+       if (rc == 0) {
+               /* release ibits lock ASAP to avoid deadlock when statahead
+                * thread enqueues lock on parent in readdir and another
+                * process enqueues lock on child with parent lock held, eg.
+                * unlink. */
+               handle = it->d.lustre.it_lock_handle;
+               ll_intent_drop_lock(it);
+       }
+
        spin_lock(&lli->lli_sa_lock);
        /* stale entry */
        if (unlikely(lli->lli_sai == NULL ||
@@ -745,8 +755,7 @@ static int ll_statahead_interpret(struct ptlrpc_request *req,
                         * when statahead thread tries to enqueue lock on parent
                         * for readpage and other tries to enqueue lock on child
                         * with parent's lock held, for example: unlink. */
-                       entry->se_handle = it->d.lustre.it_lock_handle;
-                       ll_intent_drop_lock(it);
+                       entry->se_handle = handle;
                        wakeup = sa_received_empty(sai);
                        list_add_tail(&entry->se_list,
                                          &sai->sai_entries_received);
index 7c1e02a031ba1705bd8462337494e0de8ce5fc08..a494f6271fa0b6394e4d182b4f47725b88ca86d4 100644 (file)
@@ -152,9 +152,7 @@ static int __init init_lustre_lite(void)
 
        do_gettimeofday(&tv);
        cfs_srand(tv.tv_sec ^ seed[0], tv.tv_usec ^ seed[1]);
-
-       init_timer(&ll_capa_timer);
-       ll_capa_timer.function = ll_capa_timer_callback;
+       setup_timer(&ll_capa_timer, ll_capa_timer_callback, 0);
        rc = ll_capa_thread_start();
        if (rc != 0)
                goto out_proc;
index 5a1078a4198d7b94d61431a04dabb4c810ceb629..fde41d7c5e3d8e1aaa12da5514281732d0c8cb25 100644 (file)
@@ -63,12 +63,12 @@ static struct lu_kmem_descr vvp_caches[] = {
        {
                .ckd_cache = &vvp_thread_kmem,
                .ckd_name  = "vvp_thread_kmem",
-               .ckd_size  = sizeof (struct vvp_thread_info),
+               .ckd_size  = sizeof(struct vvp_thread_info),
        },
        {
                .ckd_cache = &vvp_session_kmem,
                .ckd_name  = "vvp_session_kmem",
-               .ckd_size  = sizeof (struct vvp_session)
+               .ckd_size  = sizeof(struct vvp_session)
        },
        {
                .ckd_cache = NULL
@@ -90,6 +90,7 @@ static void vvp_key_fini(const struct lu_context *ctx,
                         struct lu_context_key *key, void *data)
 {
        struct vvp_thread_info *info = data;
+
        OBD_SLAB_FREE_PTR(info, vvp_thread_kmem);
 }
 
@@ -108,6 +109,7 @@ static void vvp_session_key_fini(const struct lu_context *ctx,
                                 struct lu_context_key *key, void *data)
 {
        struct vvp_session *session = data;
+
        OBD_SLAB_FREE_PTR(session, vvp_session_kmem);
 }
 
@@ -286,7 +288,7 @@ static void vvp_pgcache_id_unpack(loff_t pos, struct vvp_pgcache_id *id)
 
        id->vpi_index  = pos & 0xffffffff;
        id->vpi_depth  = (pos >> PGC_DEPTH_SHIFT) & 0xf;
-       id->vpi_bucket = ((unsigned long long)pos >> PGC_OBJ_SHIFT);
+       id->vpi_bucket = (unsigned long long)pos >> PGC_OBJ_SHIFT;
 }
 
 static loff_t vvp_pgcache_id_pack(struct vvp_pgcache_id *id)
index e2badf17d95e6b439d21c5214b2f3be07e80c6c4..69ea92adf4f1ffbdbc1e1607d1aee25cdc93c07e 100644 (file)
@@ -132,14 +132,10 @@ static int ll_xattr_cache_add(struct list_head *cache,
                       xattr->xe_namelen);
                goto err_name;
        }
-       xattr->xe_value = kzalloc(xattr_val_len, GFP_NOFS);
-       if (!xattr->xe_value) {
-               CDEBUG(D_CACHE, "failed to alloc xattr value %d\n",
-                      xattr_val_len);
+       xattr->xe_value = kmemdup(xattr_val, xattr_val_len, GFP_NOFS);
+       if (!xattr->xe_value)
                goto err_value;
-       }
 
-       memcpy(xattr->xe_value, xattr_val, xattr_val_len);
        xattr->xe_vallen = xattr_val_len;
        list_add(&xattr->xe_list, cache);
 
@@ -299,13 +295,18 @@ static int ll_xattr_find_get_lock(struct inode *inode,
 
 
        mutex_lock(&lli->lli_xattrs_enq_lock);
-       /* Try matching first. */
-       mode = ll_take_md_lock(inode, MDS_INODELOCK_XATTR, &lockh, 0, LCK_PR);
-       if (mode != 0) {
-               /* fake oit in mdc_revalidate_lock() manner */
-               oit->d.lustre.it_lock_handle = lockh.cookie;
-               oit->d.lustre.it_lock_mode = mode;
-               goto out;
+       /* inode may have been shrunk and recreated, so data is gone, match lock
+        * only when data exists. */
+       if (ll_xattr_cache_valid(lli)) {
+               /* Try matching first. */
+               mode = ll_take_md_lock(inode, MDS_INODELOCK_XATTR, &lockh, 0,
+                                      LCK_PR);
+               if (mode != 0) {
+                       /* fake oit in mdc_revalidate_lock() manner */
+                       oit->d.lustre.it_lock_handle = lockh.cookie;
+                       oit->d.lustre.it_lock_mode = mode;
+                       goto out;
+               }
        }
 
        /* Enqueue if the lock isn't cached locally. */
index b779f47384c52053eeee5a3147280ad141e85f5a..b9459faf8645a6dffe781c2e05f82ae3e9cbc514 100644 (file)
@@ -43,7 +43,7 @@
 #include <asm/div64.h>
 #include <linux/seq_file.h>
 #include <linux/namei.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "../include/lustre/lustre_idl.h"
 #include "../include/obd_support.h"
@@ -487,7 +487,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
                __u32 oldsize = 0;
 
                while (newsize < index + 1)
-                       newsize = newsize << 1;
+                       newsize <<= 1;
                OBD_ALLOC(newtgts, sizeof(*newtgts) * newsize);
                if (newtgts == NULL) {
                        lmv_init_unlock(lmv);
index 5be4176829d314076766cf4230190103d906bb67..22e5c315faa42de69bf3cea27bc11c3546c7c262 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/statfs.h>
 #include "../include/lprocfs_status.h"
 #include "../include/obd_class.h"
+#include "lmv_internal.h"
 
 static int lmv_numobd_seq_show(struct seq_file *m, void *v)
 {
@@ -48,7 +49,8 @@ static int lmv_numobd_seq_show(struct seq_file *m, void *v)
 
        LASSERT(dev != NULL);
        desc = &dev->u.lmv.desc;
-       return seq_printf(m, "%u\n", desc->ld_tgt_count);
+       seq_printf(m, "%u\n", desc->ld_tgt_count);
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(lmv_numobd);
 
@@ -82,7 +84,8 @@ static int lmv_placement_seq_show(struct seq_file *m, void *v)
 
        LASSERT(dev != NULL);
        lmv = &dev->u.lmv;
-       return seq_printf(m, "%s\n", placement_policy2name(lmv->lmv_placement));
+       seq_printf(m, "%s\n", placement_policy2name(lmv->lmv_placement));
+       return 0;
 }
 
 #define MAX_POLICY_STRING_SIZE 64
@@ -130,7 +133,8 @@ static int lmv_activeobd_seq_show(struct seq_file *m, void *v)
 
        LASSERT(dev != NULL);
        desc = &dev->u.lmv.desc;
-       return seq_printf(m, "%u\n", desc->ld_active_tgt_count);
+       seq_printf(m, "%u\n", desc->ld_active_tgt_count);
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(lmv_activeobd);
 
@@ -141,7 +145,8 @@ static int lmv_desc_uuid_seq_show(struct seq_file *m, void *v)
 
        LASSERT(dev != NULL);
        lmv = &dev->u.lmv;
-       return seq_printf(m, "%s\n", lmv->desc.ld_uuid.uuid);
+       seq_printf(m, "%s\n", lmv->desc.ld_uuid.uuid);
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(lmv_desc_uuid);
 
@@ -171,8 +176,10 @@ static int lmv_tgt_seq_show(struct seq_file *p, void *v)
 
        if (tgt == NULL)
                return 0;
-       return seq_printf(p, "%d: %s %sACTIVE\n", tgt->ltd_idx,
-                         tgt->ltd_uuid.uuid, tgt->ltd_active ? "" : "IN");
+       seq_printf(p, "%d: %s %sACTIVE\n",
+                  tgt->ltd_idx, tgt->ltd_uuid.uuid,
+                  tgt->ltd_active ? "" : "IN");
+       return 0;
 }
 
 static struct seq_operations lmv_tgt_sops = {
index 796a015d070ca50143161779566913c3cff2d1e2..711b837ddba23aa8fa6028a828f06f8753ce979b 100644 (file)
@@ -60,7 +60,7 @@ struct kmem_cache *lovsub_req_kmem;
 struct kmem_cache *lov_lock_link_kmem;
 
 /** Lock class of lov_device::ld_mutex. */
-struct lock_class_key cl_lov_device_mutex_class;
+static struct lock_class_key cl_lov_device_mutex_class;
 
 struct lu_kmem_descr lov_caches[] = {
        {
index e9ec39c5a6c2eb506e7d24a49a15b50b5fccbe66..2bcfaeaff6fa586efe924ed1edf182d0c980177b 100644 (file)
@@ -209,8 +209,8 @@ static int lsm_lmm_verify_v1(struct lov_mds_md_v1 *lmm, int lmm_bytes,
        return lsm_lmm_verify_common(lmm, lmm_bytes, *stripe_count);
 }
 
-int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm,
-                   struct lov_mds_md_v1 *lmm)
+static int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm,
+                          struct lov_mds_md_v1 *lmm)
 {
        struct lov_oinfo *loi;
        int i;
@@ -227,6 +227,9 @@ int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm,
                ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi);
                loi->loi_ost_idx = le32_to_cpu(lmm->lmm_objects[i].l_ost_idx);
                loi->loi_ost_gen = le32_to_cpu(lmm->lmm_objects[i].l_ost_gen);
+               if (lov_oinfo_is_dummy(loi))
+                       continue;
+
                if (loi->loi_ost_idx >= lov->desc.ld_tgt_count) {
                        CERROR("OST index %d more than OST count %d\n",
                               loi->loi_ost_idx, lov->desc.ld_tgt_count);
@@ -287,8 +290,8 @@ static int lsm_lmm_verify_v3(struct lov_mds_md *lmmv1, int lmm_bytes,
                                     *stripe_count);
 }
 
-int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm,
-                   struct lov_mds_md *lmmv1)
+static int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm,
+                          struct lov_mds_md *lmmv1)
 {
        struct lov_mds_md_v3 *lmm;
        struct lov_oinfo *loi;
@@ -314,6 +317,9 @@ int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm,
                ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi);
                loi->loi_ost_idx = le32_to_cpu(lmm->lmm_objects[i].l_ost_idx);
                loi->loi_ost_gen = le32_to_cpu(lmm->lmm_objects[i].l_ost_gen);
+               if (lov_oinfo_is_dummy(loi))
+                       continue;
+
                if (loi->loi_ost_idx >= lov->desc.ld_tgt_count) {
                        CERROR("OST index %d more than OST count %d\n",
                               loi->loi_ost_idx, lov->desc.ld_tgt_count);
index 8c8508bbbb808750b36411841683f0583cc0de8e..b644acc9b034c0c36cf726aecfbd65e33f8d995e 100644 (file)
@@ -304,4 +304,16 @@ static inline struct lov_stripe_md *lsm_addref(struct lov_stripe_md *lsm)
        return lsm;
 }
 
+static inline bool lov_oinfo_is_dummy(const struct lov_oinfo *loi)
+{
+       if (unlikely(loi->loi_oi.oi.oi_id == 0 &&
+                    loi->loi_oi.oi.oi_seq == 0 &&
+                    loi->loi_ost_idx == 0 &&
+                    loi->loi_ost_gen == 0))
+               return true;
+
+       return false;
+}
+
+
 #endif
index f1f6db3f664a06952f73992f23c0bc62ce335aa3..cf96e0d01e22d5d000304d46a24cc75ff2596a8e 100644 (file)
@@ -148,6 +148,9 @@ static int lov_io_sub_init(const struct lu_env *env, struct lov_io *lio,
        LASSERT(sub->sub_env == NULL);
        LASSERT(sub->sub_stripe < lio->lis_stripe_count);
 
+       if (unlikely(lov_r0(lov)->lo_sub[stripe] == NULL))
+               return -EIO;
+
        result = 0;
        sub->sub_io_initialized = 0;
        sub->sub_borrowed = 0;
@@ -391,7 +394,16 @@ static int lov_io_iter_init(const struct lu_env *env,
                                           endpos, &start, &end))
                        continue;
 
-               end = lov_offset_mod(end, +1);
+               if (unlikely(lov_r0(lio->lis_object)->lo_sub[stripe] == NULL)) {
+                       if (ios->cis_io->ci_type == CIT_READ ||
+                           ios->cis_io->ci_type == CIT_WRITE ||
+                           ios->cis_io->ci_type == CIT_FAULT)
+                               return -EIO;
+
+                       continue;
+               }
+
+               end = lov_offset_mod(end, 1);
                sub = lov_sub_get(env, lio, stripe);
                if (!IS_ERR(sub)) {
                        lov_io_sub_inherit(sub->sub_io, lio, stripe,
@@ -913,7 +925,7 @@ int lov_io_init_empty(const struct lu_env *env, struct cl_object *obj,
                break;
        case CIT_FSYNC:
        case CIT_SETATTR:
-               result = +1;
+               result = 1;
                break;
        case CIT_WRITE:
                result = -EBADF;
index 49e694222ac839416327779de74d25de31b9e38c..f2eca565bddab0130ea80f470458e71c349b8245 100644 (file)
@@ -308,7 +308,8 @@ static int lov_lock_sub_init(const struct lu_env *env,
                 * XXX for wide striping smarter algorithm is desirable,
                 * breaking out of the loop, early.
                 */
-               if (lov_stripe_intersects(loo->lo_lsm, i,
+               if (likely(r0->lo_sub[i] != NULL) &&
+                   lov_stripe_intersects(loo->lo_lsm, i,
                                          file_start, file_end, &start, &end))
                        nr++;
        }
@@ -326,7 +327,8 @@ static int lov_lock_sub_init(const struct lu_env *env,
         * top-lock.
         */
        for (i = 0, nr = 0; i < r0->lo_nr; ++i) {
-               if (lov_stripe_intersects(loo->lo_lsm, i,
+               if (likely(r0->lo_sub[i] != NULL) &&
+                   lov_stripe_intersects(loo->lo_lsm, i,
                                          file_start, file_end, &start, &end)) {
                        struct cl_lock_descr *descr;
 
@@ -914,10 +916,22 @@ static int lov_lock_stripe_is_matching(const struct lu_env *env,
         */
        start = cl_offset(&lov->lo_cl, descr->cld_start);
        end   = cl_offset(&lov->lo_cl, descr->cld_end + 1) - 1;
-       result = end - start <= lsm->lsm_stripe_size &&
-                stripe == lov_stripe_number(lsm, start) &&
-                stripe == lov_stripe_number(lsm, end);
-       if (result) {
+       result = 0;
+       /* glimpse should work on the object with LOV EA hole. */
+       if (end - start <= lsm->lsm_stripe_size) {
+               int idx;
+
+               idx = lov_stripe_number(lsm, start);
+               if (idx == stripe ||
+                   unlikely(lov_r0(lov)->lo_sub[idx] == NULL)) {
+                       idx = lov_stripe_number(lsm, end);
+                       if (idx == stripe ||
+                           unlikely(lov_r0(lov)->lo_sub[idx] == NULL))
+                               result = 1;
+               }
+       }
+
+       if (result != 0) {
                struct cl_lock_descr *subd = &lov_env_info(env)->lti_ldescr;
                u64 sub_start;
                u64 sub_end;
index ea503d2a19f8bc90d2d54844279c10631109cf6b..02781576637edd64657486d548fc8364a75550d5 100644 (file)
@@ -553,7 +553,7 @@ static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
 
                newsize = max_t(__u32, lov->lov_tgt_size, 2);
                while (newsize < index + 1)
-                       newsize = newsize << 1;
+                       newsize <<= 1;
                OBD_ALLOC(newtgts, sizeof(*newtgts) * newsize);
                if (newtgts == NULL) {
                        mutex_unlock(&lov->lov_lock);
@@ -1011,9 +1011,13 @@ static int lov_recreate(struct obd_export *exp, struct obdo *src_oa,
        }
 
        for (i = 0; i < lsm->lsm_stripe_count; i++) {
-               if (lsm->lsm_oinfo[i]->loi_ost_idx == ost_idx) {
-                       if (ostid_id(&lsm->lsm_oinfo[i]->loi_oi) !=
-                                       ostid_id(&src_oa->o_oi)) {
+               struct lov_oinfo *loi = lsm->lsm_oinfo[i];
+
+               if (lov_oinfo_is_dummy(loi))
+                       continue;
+
+               if (loi->loi_ost_idx == ost_idx) {
+                       if (ostid_id(&loi->loi_oi) != ostid_id(&src_oa->o_oi)) {
                                rc = -EINVAL;
                                goto out;
                        }
@@ -1305,10 +1309,14 @@ static int lov_find_cbdata(struct obd_export *exp,
                struct lov_stripe_md submd;
                struct lov_oinfo *loi = lsm->lsm_oinfo[i];
 
+               if (lov_oinfo_is_dummy(loi))
+                       continue;
+
                if (!lov->lov_tgts[loi->loi_ost_idx]) {
-                       CDEBUG(D_HA, "lov idx %d NULL \n", loi->loi_ost_idx);
+                       CDEBUG(D_HA, "lov idx %d NULL\n", loi->loi_ost_idx);
                        continue;
                }
+
                submd.lsm_oi = loi->loi_oi;
                submd.lsm_stripe_count = 0;
                rc = obd_find_cbdata(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp,
@@ -1601,9 +1609,9 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
  * \param fm_end logical end of mapping
  * \param start_stripe starting stripe will be returned in this
  */
-u64 fiemap_calc_fm_end_offset(struct ll_user_fiemap *fiemap,
-                                  struct lov_stripe_md *lsm, u64 fm_start,
-                                  u64 fm_end, int *start_stripe)
+static u64 fiemap_calc_fm_end_offset(struct ll_user_fiemap *fiemap,
+                                    struct lov_stripe_md *lsm, u64 fm_start,
+                                    u64 fm_end, int *start_stripe)
 {
        u64 local_end = fiemap->fm_extents[0].fe_logical;
        u64 lun_start, lun_end;
@@ -1616,8 +1624,12 @@ u64 fiemap_calc_fm_end_offset(struct ll_user_fiemap *fiemap,
 
        /* Find out stripe_no from ost_index saved in the fe_device */
        for (i = 0; i < lsm->lsm_stripe_count; i++) {
-               if (lsm->lsm_oinfo[i]->loi_ost_idx ==
-                                       fiemap->fm_extents[0].fe_device) {
+               struct lov_oinfo *oinfo = lsm->lsm_oinfo[i];
+
+               if (lov_oinfo_is_dummy(oinfo))
+                       continue;
+
+               if (oinfo->loi_ost_idx == fiemap->fm_extents[0].fe_device) {
                        stripe_no = i;
                        break;
                }
@@ -1658,17 +1670,17 @@ u64 fiemap_calc_fm_end_offset(struct ll_user_fiemap *fiemap,
  *
  * \retval last_stripe return the last stripe of the mapping
  */
-int fiemap_calc_last_stripe(struct lov_stripe_md *lsm, u64 fm_start,
-                           u64 fm_end, int start_stripe,
-                           int *stripe_count)
+static int fiemap_calc_last_stripe(struct lov_stripe_md *lsm, u64 fm_start,
+                                  u64 fm_end, int start_stripe,
+                                  int *stripe_count)
 {
        int last_stripe;
        u64 obd_start, obd_end;
        int i, j;
 
        if (fm_end - fm_start > lsm->lsm_stripe_size * lsm->lsm_stripe_count) {
-               last_stripe = (start_stripe < 1 ? lsm->lsm_stripe_count - 1 :
-                                                             start_stripe - 1);
+               last_stripe = start_stripe < 1 ? lsm->lsm_stripe_count - 1 :
+                                                             start_stripe - 1;
                *stripe_count = lsm->lsm_stripe_count;
        } else {
                for (j = 0, i = start_stripe; j < lsm->lsm_stripe_count;
@@ -1694,10 +1706,10 @@ int fiemap_calc_last_stripe(struct lov_stripe_md *lsm, u64 fm_start,
  * \param ext_count number of extents to be copied
  * \param current_extent where to start copying in main extent array
  */
-void fiemap_prepare_and_copy_exts(struct ll_user_fiemap *fiemap,
-                                 struct ll_fiemap_extent *lcl_fm_ext,
-                                 int ost_index, unsigned int ext_count,
-                                 int current_extent)
+static void fiemap_prepare_and_copy_exts(struct ll_user_fiemap *fiemap,
+                                        struct ll_fiemap_extent *lcl_fm_ext,
+                                        int ost_index, unsigned int ext_count,
+                                        int current_extent)
 {
        char *to;
        int ext;
@@ -1795,6 +1807,11 @@ static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key,
                                           &lun_start, &obd_object_end)) == 0)
                        continue;
 
+               if (lov_oinfo_is_dummy(lsm->lsm_oinfo[cur_stripe])) {
+                       rc = -EIO;
+                       goto out;
+               }
+
                /* If this is a continuation FIEMAP call and we are on
                 * starting stripe then lun_start needs to be set to
                 * fm_end_offset */
@@ -1985,6 +2002,9 @@ static int lov_get_info(const struct lu_env *env, struct obd_export *exp,
                 * be NULL and won't match the lock's export. */
                for (i = 0; i < lsm->lsm_stripe_count; i++) {
                        loi = lsm->lsm_oinfo[i];
+                       if (lov_oinfo_is_dummy(loi))
+                               continue;
+
                        if (!lov->lov_tgts[loi->loi_ost_idx])
                                continue;
                        if (lov->lov_tgts[loi->loi_ost_idx]->ltd_exp ==
@@ -2290,7 +2310,7 @@ out:
        return rc;
 }
 
-struct obd_ops lov_obd_ops = {
+static struct obd_ops lov_obd_ops = {
        .o_owner               = THIS_MODULE,
        .o_setup               = lov_setup,
        .o_precleanup     = lov_precleanup,
@@ -2324,7 +2344,7 @@ struct obd_ops lov_obd_ops = {
 
 struct kmem_cache *lov_oinfo_slab;
 
-int __init lov_init(void)
+static int __init lov_init(void)
 {
        struct lprocfs_static_vars lvars = { NULL };
        int rc;
index 4cab730ab429b2898e6a1d9312c977e3d0caf696..a22342fa792d010d12f8fea811c9d05a44b41639 100644 (file)
@@ -42,6 +42,7 @@
 #define DEBUG_SUBSYSTEM S_LOV
 
 #include "lov_cl_internal.h"
+#include "../include/lclient.h"
 
 /** \addtogroup lov
  *  @{
@@ -230,6 +231,9 @@ static int lov_init_raid0(const struct lu_env *env,
                        struct lov_oinfo *oinfo = lsm->lsm_oinfo[i];
                        int ost_idx = oinfo->loi_ost_idx;
 
+                       if (lov_oinfo_is_dummy(oinfo))
+                               continue;
+
                        result = ostid_to_fid(ofid, &oinfo->loi_oi,
                                              oinfo->loi_ost_idx);
                        if (result != 0)
@@ -563,7 +567,7 @@ static const struct lov_layout_operations lov_dispatch[] = {
 /**
  * Return lov_layout_type associated with a given lsm
  */
-enum lov_layout_type lov_type(struct lov_stripe_md *lsm)
+static enum lov_layout_type lov_type(struct lov_stripe_md *lsm)
 {
        if (lsm == NULL)
                return LLT_EMPTY;
@@ -973,6 +977,10 @@ int lov_read_and_clear_async_rc(struct cl_object *clob)
                        LASSERT(lsm != NULL);
                        for (i = 0; i < lsm->lsm_stripe_count; i++) {
                                struct lov_oinfo *loi = lsm->lsm_oinfo[i];
+
+                               if (lov_oinfo_is_dummy(loi))
+                                       continue;
+
                                if (loi->loi_ar.ar_rc && !rc)
                                        rc = loi->loi_ar.ar_rc;
                                loi->loi_ar.ar_rc = 0;
index 0e0ea60de4c867b68bfff83e2d481a8e19bc6ce7..d96163de773f75542eadad37d740164eac60bb35 100644 (file)
@@ -71,7 +71,7 @@ void lov_pool_putref(struct pool_desc *pool)
        }
 }
 
-void lov_pool_putref_locked(struct pool_desc *pool)
+static void lov_pool_putref_locked(struct pool_desc *pool)
 {
        CDEBUG(D_INFO, "pool %p\n", pool);
        LASSERT(atomic_read(&pool->pool_refcount) > 1);
index 7358b9d29103c89dbff7719e69c92186c4bde1db..933e2d1f8127e13a37c116b3737a61bd188635e1 100644 (file)
@@ -299,6 +299,9 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo,
                struct lov_request *req;
 
                loi = oinfo->oi_md->lsm_oinfo[i];
+               if (lov_oinfo_is_dummy(loi))
+                       continue;
+
                if (!lov_check_and_wait_active(lov, loi->loi_ost_idx)) {
                        CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                        if (oinfo->oi_oa->o_valid & OBD_MD_FLEPOCH) {
@@ -384,6 +387,9 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo,
                struct lov_request *req;
 
                loi = lsm->lsm_oinfo[i];
+               if (lov_oinfo_is_dummy(loi))
+                       continue;
+
                if (!lov_check_and_wait_active(lov, loi->loi_ost_idx)) {
                        CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                        continue;
@@ -497,6 +503,9 @@ int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo,
                struct lov_oinfo *loi = oinfo->oi_md->lsm_oinfo[i];
                struct lov_request *req;
 
+               if (lov_oinfo_is_dummy(loi))
+                       continue;
+
                if (!lov_check_and_wait_active(lov, loi->loi_ost_idx)) {
                        CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                        continue;
index c99f2f44ec62e2b69a25c6155550e4636263f337..174cbf5c138f87f7be3591d288c32ef07d2805b9 100644 (file)
@@ -35,7 +35,7 @@
  */
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <asm/statfs.h>
+#include <linux/statfs.h>
 #include "../include/lprocfs_status.h"
 #include "../include/obd_class.h"
 #include <linux/seq_file.h>
@@ -48,7 +48,8 @@ static int lov_stripesize_seq_show(struct seq_file *m, void *v)
 
        LASSERT(dev != NULL);
        desc = &dev->u.lov.desc;
-       return seq_printf(m, "%llu\n", desc->ld_default_stripe_size);
+       seq_printf(m, "%llu\n", desc->ld_default_stripe_size);
+       return 0;
 }
 
 static ssize_t lov_stripesize_seq_write(struct file *file,
@@ -79,7 +80,8 @@ static int lov_stripeoffset_seq_show(struct seq_file *m, void *v)
 
        LASSERT(dev != NULL);
        desc = &dev->u.lov.desc;
-       return seq_printf(m, "%llu\n", desc->ld_default_stripe_offset);
+       seq_printf(m, "%llu\n", desc->ld_default_stripe_offset);
+       return 0;
 }
 
 static ssize_t lov_stripeoffset_seq_write(struct file *file,
@@ -109,7 +111,8 @@ static int lov_stripetype_seq_show(struct seq_file *m, void *v)
 
        LASSERT(dev != NULL);
        desc = &dev->u.lov.desc;
-       return seq_printf(m, "%u\n", desc->ld_pattern);
+       seq_printf(m, "%u\n", desc->ld_pattern);
+       return 0;
 }
 
 static ssize_t lov_stripetype_seq_write(struct file *file,
@@ -139,8 +142,8 @@ static int lov_stripecount_seq_show(struct seq_file *m, void *v)
 
        LASSERT(dev != NULL);
        desc = &dev->u.lov.desc;
-       return seq_printf(m, "%d\n",
-                       (__s16)(desc->ld_default_stripe_count + 1) - 1);
+       seq_printf(m, "%d\n", (__s16)(desc->ld_default_stripe_count + 1) - 1);
+       return 0;
 }
 
 static ssize_t lov_stripecount_seq_write(struct file *file,
@@ -170,7 +173,8 @@ static int lov_numobd_seq_show(struct seq_file *m, void *v)
 
        LASSERT(dev != NULL);
        desc = &dev->u.lov.desc;
-       return seq_printf(m, "%u\n", desc->ld_tgt_count);
+       seq_printf(m, "%u\n", desc->ld_tgt_count);
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(lov_numobd);
 
@@ -181,7 +185,8 @@ static int lov_activeobd_seq_show(struct seq_file *m, void *v)
 
        LASSERT(dev != NULL);
        desc = &dev->u.lov.desc;
-       return seq_printf(m, "%u\n", desc->ld_active_tgt_count);
+       seq_printf(m, "%u\n", desc->ld_active_tgt_count);
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(lov_activeobd);
 
@@ -192,7 +197,8 @@ static int lov_desc_uuid_seq_show(struct seq_file *m, void *v)
 
        LASSERT(dev != NULL);
        lov = &dev->u.lov;
-       return seq_printf(m, "%s\n", lov->desc.ld_uuid.uuid);
+       seq_printf(m, "%s\n", lov->desc.ld_uuid.uuid);
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(lov_desc_uuid);
 
@@ -228,12 +234,14 @@ static void *lov_tgt_seq_next(struct seq_file *p, void *v, loff_t *pos)
 static int lov_tgt_seq_show(struct seq_file *p, void *v)
 {
        struct lov_tgt_desc *tgt = v;
-       return seq_printf(p, "%d: %s %sACTIVE\n", tgt->ltd_index,
-                         obd_uuid2str(&tgt->ltd_uuid),
-                         tgt->ltd_active ? "" : "IN");
+
+       seq_printf(p, "%d: %s %sACTIVE\n",
+                  tgt->ltd_index, obd_uuid2str(&tgt->ltd_uuid),
+                  tgt->ltd_active ? "" : "IN");
+       return 0;
 }
 
-struct seq_operations lov_tgt_sops = {
+static const struct seq_operations lov_tgt_sops = {
        .start = lov_tgt_seq_start,
        .stop = lov_tgt_seq_stop,
        .next = lov_tgt_seq_next,
@@ -262,7 +270,7 @@ LPROC_SEQ_FOPS_RO_TYPE(lov, kbytestotal);
 LPROC_SEQ_FOPS_RO_TYPE(lov, kbytesfree);
 LPROC_SEQ_FOPS_RO_TYPE(lov, kbytesavail);
 
-struct lprocfs_vars lprocfs_lov_obd_vars[] = {
+static struct lprocfs_vars lprocfs_lov_obd_vars[] = {
        { "uuid",         &lov_uuid_fops,         NULL, 0 },
        { "stripesize",   &lov_stripesize_fops,   NULL },
        { "stripeoffset", &lov_stripeoffset_fops, NULL },
index c791941bd810426346220ca47e526725f126ceb5..acfe08e459c0c5bfb84a610ba6144f2faaec2379 100644 (file)
 #include <linux/vfs.h>
 #include "../include/obd_class.h"
 #include "../include/lprocfs_status.h"
+#include "mdc_internal.h"
 
 static int mdc_max_rpcs_in_flight_seq_show(struct seq_file *m, void *v)
 {
        struct obd_device *dev = m->private;
        struct client_obd *cli = &dev->u.cli;
-       int rc;
 
        client_obd_list_lock(&cli->cl_loi_list_lock);
-       rc = seq_printf(m, "%u\n", cli->cl_max_rpcs_in_flight);
+       seq_printf(m, "%u\n", cli->cl_max_rpcs_in_flight);
        client_obd_list_unlock(&cli->cl_loi_list_lock);
-       return rc;
+
+       return 0;
 }
 
 static ssize_t mdc_max_rpcs_in_flight_seq_write(struct file *file,
index ef2744700d8bb7c55537b4601226b1b435cc3fc8..f8ef5fe5e771d091f49e53026f61f36a6e2823f8 100644 (file)
@@ -481,6 +481,9 @@ static int mdc_unpack_acl(struct ptlrpc_request *req, struct lustre_md *md)
                return -EPROTO;
 
        acl = posix_acl_from_xattr(&init_user_ns, buf, body->aclsize);
+       if (acl == NULL)
+               return 0;
+
        if (IS_ERR(acl)) {
                rc = PTR_ERR(acl);
                CERROR("convert xattr to acl: %d\n", rc);
@@ -2707,14 +2710,12 @@ static struct md_ops mdc_md_ops = {
 
 static int __init mdc_init(void)
 {
-       int rc;
        struct lprocfs_static_vars lvars = { NULL };
 
        lprocfs_mdc_init_vars(&lvars);
 
-       rc = class_register_type(&mdc_obd_ops, &mdc_md_ops, lvars.module_vars,
+       return class_register_type(&mdc_obd_ops, &mdc_md_ops, lvars.module_vars,
                                 LUSTRE_MDC_NAME, NULL);
-       return rc;
 }
 
 static void /*__exit*/ mdc_exit(void)
index 60d2b0f12693939191a45b0701557a93ff6fb8a4..7947aec5c847ca2c9d65e02667d8b79105459175 100644 (file)
@@ -95,7 +95,7 @@ int mgc_fsname2resid(char *fsname, struct ldlm_res_id *res_id, int type)
 }
 EXPORT_SYMBOL(mgc_fsname2resid);
 
-int mgc_logname2resid(char *logname, struct ldlm_res_id *res_id, int type)
+static int mgc_logname2resid(char *logname, struct ldlm_res_id *res_id, int type)
 {
        char *name_end;
        int len;
@@ -160,7 +160,7 @@ struct config_llog_data *config_log_find(char *logname,
 {
        struct config_llog_data *cld;
        struct config_llog_data *found = NULL;
-       void *             instance;
+       void *instance;
 
        LASSERT(logname != NULL);
 
@@ -452,10 +452,14 @@ static int config_log_end(char *logname, struct config_llog_instance *cfg)
 int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data)
 {
        struct obd_device       *obd = data;
-       struct obd_import       *imp = obd->u.cli.cl_import;
-       struct obd_connect_data *ocd = &imp->imp_connect_data;
+       struct obd_import       *imp;
+       struct obd_connect_data *ocd;
        struct config_llog_data *cld;
 
+       LPROCFS_CLIMP_CHECK(obd);
+       imp = obd->u.cli.cl_import;
+       ocd = &imp->imp_connect_data;
+
        seq_printf(m, "imperative_recovery: %s\n",
                      OCD_HAS_FLAG(ocd, IMP_RECOV) ? "ENABLED" : "DISABLED");
        seq_printf(m, "client_state:\n");
@@ -470,6 +474,7 @@ int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data)
        }
        spin_unlock(&config_list_lock);
 
+       LPROCFS_CLIMP_EXIT(obd);
        return 0;
 }
 #endif
@@ -479,9 +484,11 @@ int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data)
 #define RQ_NOW     0x2
 #define RQ_LATER   0x4
 #define RQ_STOP    0x8
-static int                 rq_state = 0;
+#define RQ_PRECLEANUP  0x10
+static int rq_state;
 static wait_queue_head_t           rq_waitq;
 static DECLARE_COMPLETION(rq_exit);
+static DECLARE_COMPLETION(rq_start);
 
 static void do_requeue(struct config_llog_data *cld)
 {
@@ -510,6 +517,8 @@ static void do_requeue(struct config_llog_data *cld)
 
 static int mgc_requeue_thread(void *data)
 {
+       bool first = true;
+
        CDEBUG(D_MGC, "Starting requeue thread\n");
 
        /* Keep trying failed locks periodically */
@@ -526,13 +535,19 @@ static int mgc_requeue_thread(void *data)
                rq_state &= ~(RQ_NOW | RQ_LATER);
                spin_unlock(&config_list_lock);
 
+               if (first) {
+                       first = false;
+                       complete(&rq_start);
+               }
+
                /* Always wait a few seconds to allow the server who
                   caused the lock revocation to finish its setup, plus some
                   random so everyone doesn't try to reconnect at once. */
                to = MGC_TIMEOUT_MIN_SECONDS * HZ;
                to += rand * HZ / 100; /* rand is centi-seconds */
                lwi = LWI_TIMEOUT(to, NULL, NULL);
-               l_wait_event(rq_waitq, rq_state & RQ_STOP, &lwi);
+               l_wait_event(rq_waitq, rq_state & (RQ_STOP | RQ_PRECLEANUP),
+                            &lwi);
 
                /*
                 * iterate & processing through the list. for each cld, process
@@ -545,6 +560,7 @@ static int mgc_requeue_thread(void *data)
                cld_prev = NULL;
 
                spin_lock(&config_list_lock);
+               rq_state &= ~RQ_PRECLEANUP;
                list_for_each_entry(cld, &config_llog_list,
                                        cld_list_chain) {
                        if (!cld->cld_lostlock)
@@ -661,24 +677,26 @@ static atomic_t mgc_count = ATOMIC_INIT(0);
 static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 {
        int rc = 0;
+       int temp;
 
        switch (stage) {
        case OBD_CLEANUP_EARLY:
                break;
        case OBD_CLEANUP_EXPORTS:
                if (atomic_dec_and_test(&mgc_count)) {
-                       int running;
+                       LASSERT(rq_state & RQ_RUNNING);
                        /* stop requeue thread */
-                       spin_lock(&config_list_lock);
-                       running = rq_state & RQ_RUNNING;
-                       if (running)
-                               rq_state |= RQ_STOP;
-                       spin_unlock(&config_list_lock);
-                       if (running) {
-                               wake_up(&rq_waitq);
-                               wait_for_completion(&rq_exit);
-                       }
+                       temp = RQ_STOP;
+               } else {
+                       /* wakeup requeue thread to clean our cld */
+                       temp = RQ_NOW | RQ_PRECLEANUP;
                }
+               spin_lock(&config_list_lock);
+               rq_state |= temp;
+               spin_unlock(&config_list_lock);
+               wake_up(&rq_waitq);
+               if (temp & RQ_STOP)
+                       wait_for_completion(&rq_exit);
                obd_cleanup_client_import(obd);
                rc = mgc_llog_fini(NULL, obd);
                if (rc != 0)
@@ -690,8 +708,6 @@ static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
 
 static int mgc_cleanup(struct obd_device *obd)
 {
-       int rc;
-
        /* COMPAT_146 - old config logs may have added profiles we don't
           know about */
        if (obd->obd_type->typ_refcnt <= 1)
@@ -701,8 +717,7 @@ static int mgc_cleanup(struct obd_device *obd)
        lprocfs_obd_cleanup(obd);
        ptlrpcd_decref();
 
-       rc = client_obd_cleanup(obd);
-       return rc;
+       return client_obd_cleanup(obd);
 }
 
 static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
@@ -740,6 +755,7 @@ static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
                }
                /* rc is the task_struct pointer of mgc_requeue_thread. */
                rc = 0;
+               wait_for_completion(&rq_start);
        }
 
        return rc;
@@ -951,7 +967,7 @@ static int mgc_target_register(struct obd_export *exp,
        return rc;
 }
 
-int mgc_set_info_async(const struct lu_env *env, struct obd_export *exp,
+static int mgc_set_info_async(const struct lu_env *env, struct obd_export *exp,
                       u32 keylen, void *key, u32 vallen,
                       void *val, struct ptlrpc_request_set *set)
 {
@@ -1727,7 +1743,7 @@ struct obd_ops mgc_obd_ops = {
        .o_process_config = mgc_process_config,
 };
 
-int __init mgc_init(void)
+static int __init mgc_init(void)
 {
        return class_register_type(&mgc_obd_ops, NULL, NULL,
                                   LUSTRE_MGC_NAME, NULL);
index 29456e1ad2250d4e47c6d37a189033a7f3da52c5..d4b74b670c43df281f6161c17df9d4f15b11e058 100644 (file)
@@ -437,8 +437,6 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg)
        return err;
 } /* class_handle_ioctl */
 
-extern struct miscdevice obd_psdev;
-
 #define OBD_INIT_CHECK
 int obd_init_checks(void)
 {
@@ -508,7 +506,6 @@ int obd_init_checks(void)
        return ret;
 }
 
-extern spinlock_t obd_types_lock;
 #if defined (CONFIG_PROC_FS)
 extern int class_procfs_init(void);
 extern int class_procfs_clean(void);
index e7be26ec7521e397f2bce877c27414adb93021df..b1eee0a6dc9a1effdae32918133e46d16834321a 100644 (file)
@@ -424,11 +424,8 @@ EXPORT_SYMBOL(dt_find_or_create);
 /* dt class init function. */
 int dt_global_init(void)
 {
-       int result;
-
        LU_CONTEXT_KEY_INIT(&dt_key);
-       result = lu_context_key_register(&dt_key);
-       return result;
+       return lu_context_key_register(&dt_key);
 }
 
 void dt_global_fini(void)
index 82508210465eeb7090aee285725d4b7156319836..66b56784f674e21c049e499bd2d03b8e3d38e6ca 100644 (file)
 #include "../include/obd_class.h"
 #include "../include/lprocfs_status.h"
 
-extern struct list_head obd_types;
 spinlock_t obd_types_lock;
 
 struct kmem_cache *obd_device_cachep;
 struct kmem_cache *obdo_cachep;
 EXPORT_SYMBOL(obdo_cachep);
-struct kmem_cache *import_cachep;
+static struct kmem_cache *import_cachep;
 
-struct list_head      obd_zombie_imports;
-struct list_head      obd_zombie_exports;
-spinlock_t  obd_zombie_impexp_lock;
+static struct list_head      obd_zombie_imports;
+static struct list_head      obd_zombie_exports;
+static spinlock_t  obd_zombie_impexp_lock;
 static void obd_zombie_impexp_notify(void);
 static void obd_zombie_export_add(struct obd_export *exp);
 static void obd_zombie_import_add(struct obd_import *imp);
@@ -930,7 +929,7 @@ void class_unlink_export(struct obd_export *exp)
 EXPORT_SYMBOL(class_unlink_export);
 
 /* Import management functions */
-void class_import_destroy(struct obd_import *imp)
+static void class_import_destroy(struct obd_import *imp)
 {
        CDEBUG(D_IOCTL, "destroying import %p for %s\n", imp,
                imp->imp_obd->obd_name);
@@ -1127,7 +1126,7 @@ int class_connect(struct lustre_handle *conn, struct obd_device *obd,
 EXPORT_SYMBOL(class_connect);
 
 /* if export is involved in recovery then clean up related things */
-void class_export_recovery_cleanup(struct obd_export *exp)
+static void class_export_recovery_cleanup(struct obd_export *exp)
 {
        struct obd_device *obd = exp->exp_obd;
 
@@ -1221,7 +1220,7 @@ int class_connected_export(struct obd_export *exp)
        if (exp) {
                int connected;
                spin_lock(&exp->exp_lock);
-               connected = (exp->exp_conn_cnt > 0);
+               connected = exp->exp_conn_cnt > 0;
                spin_unlock(&exp->exp_lock);
                return connected;
        }
@@ -1559,7 +1558,7 @@ void obd_exports_barrier(struct obd_device *obd)
 EXPORT_SYMBOL(obd_exports_barrier);
 
 /* Total amount of zombies to be destroyed */
-static int zombies_count = 0;
+static int zombies_count;
 
 /**
  * kill zombie imports and exports
index b94aeac18a37759bb71b0d448ebfc7fdcec9099d..06944b863d16ec08c9f7a065e2a7f00218774dd7 100644 (file)
@@ -217,23 +217,25 @@ struct miscdevice obd_psdev = {
 
 
 #if defined (CONFIG_PROC_FS)
-int obd_proc_version_seq_show(struct seq_file *m, void *v)
+static int obd_proc_version_seq_show(struct seq_file *m, void *v)
 {
-       return seq_printf(m, "lustre: %s\nkernel: %s\nbuild:  %s\n",
-                       LUSTRE_VERSION_STRING, "patchless_client",
-                       BUILD_VERSION);
+       seq_printf(m, "lustre: %s\nkernel: %s\nbuild:  %s\n",
+                  LUSTRE_VERSION_STRING, "patchless_client", BUILD_VERSION);
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(obd_proc_version);
 
 int obd_proc_pinger_seq_show(struct seq_file *m, void *v)
 {
-       return seq_printf(m, "%s\n", "on");
+       seq_printf(m, "%s\n", "on");
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(obd_proc_pinger);
 
 static int obd_proc_health_seq_show(struct seq_file *m, void *v)
 {
-       int rc = 0, i;
+       bool healthy = true;
+       int i;
 
        if (libcfs_catastrophe)
                seq_printf(m, "LBUG\n");
@@ -255,25 +257,27 @@ static int obd_proc_health_seq_show(struct seq_file *m, void *v)
 
                if (obd_health_check(NULL, obd)) {
                        seq_printf(m, "device %s reported unhealthy\n",
-                                     obd->obd_name);
-                       rc++;
+                                  obd->obd_name);
+                       healthy = false;
                }
                class_decref(obd, __func__, current);
                read_lock(&obd_dev_lock);
        }
        read_unlock(&obd_dev_lock);
 
-       if (rc == 0)
-               return seq_printf(m, "healthy\n");
+       if (healthy)
+               seq_puts(m, "healthy\n");
+       else
+               seq_puts(m, "NOT HEALTHY\n");
 
-       seq_printf(m, "NOT HEALTHY\n");
        return 0;
 }
 LPROC_SEQ_FOPS_RO(obd_proc_health);
 
 static int obd_proc_jobid_var_seq_show(struct seq_file *m, void *v)
 {
-       return seq_printf(m, "%s\n", obd_jobid_var);
+       seq_printf(m, "%s\n", obd_jobid_var);
+       return 0;
 }
 
 static ssize_t obd_proc_jobid_var_seq_write(struct file *file,
@@ -299,7 +303,8 @@ LPROC_SEQ_FOPS(obd_proc_jobid_var);
 
 static int obd_proc_jobid_name_seq_show(struct seq_file *m, void *v)
 {
-       return seq_printf(m, "%s\n", obd_jobid_var);
+       seq_printf(m, "%s\n", obd_jobid_var);
+       return 0;
 }
 
 static ssize_t obd_proc_jobid_name_seq_write(struct file *file,
@@ -378,10 +383,11 @@ static int obd_device_list_seq_show(struct seq_file *p, void *v)
        else
                status = "--";
 
-       return seq_printf(p, "%3d %s %s %s %s %d\n",
-                         (int)index, status, obd->obd_type->typ_name,
-                         obd->obd_name, obd->obd_uuid.uuid,
-                         atomic_read(&obd->obd_refcount));
+       seq_printf(p, "%3d %s %s %s %s %d\n",
+                  (int)index, status, obd->obd_type->typ_name,
+                  obd->obd_name, obd->obd_uuid.uuid,
+                  atomic_read(&obd->obd_refcount));
+       return 0;
 }
 
 struct seq_operations obd_device_list_sops = {
index dd46e73581608bc6a73cdb4314dd2a79fb55f02e..4b62d25764ad79423979c7f52add70580c49a627 100644 (file)
@@ -79,6 +79,7 @@ enum {
 };
 
 
+#ifdef CONFIG_SYSCTL
 static int proc_set_timeout(struct ctl_table *table, int write,
                        void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -205,7 +206,7 @@ static int proc_max_dirty_pages_in_mb(struct ctl_table *table, int write,
                        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);
+                       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);
                }
@@ -258,7 +259,6 @@ static int proc_alloc_fail_rate(struct ctl_table *table, int write,
        return rc;
 }
 
-#ifdef CONFIG_SYSCTL
 static struct ctl_table obd_table[] = {
        {
                .procname = "timeout",
index 4b850fc5f5d9aeb1dab4fb921ef4d65928e1c858..c8f6ab006124f742f933fdc661b5a272c2e86c8e 100644 (file)
@@ -526,8 +526,9 @@ int llog_cat_cancel_records(const struct lu_env *env,
 }
 EXPORT_SYMBOL(llog_cat_cancel_records);
 
-int llog_cat_process_cb(const struct lu_env *env, struct llog_handle *cat_llh,
-                       struct llog_rec_hdr *rec, void *data)
+static int llog_cat_process_cb(const struct lu_env *env,
+                              struct llog_handle *cat_llh,
+                              struct llog_rec_hdr *rec, void *data)
 {
        struct llog_process_data *d = data;
        struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
@@ -691,7 +692,7 @@ int llog_cat_reverse_process(const struct lu_env *env,
 }
 EXPORT_SYMBOL(llog_cat_reverse_process);
 
-int llog_cat_set_first_idx(struct llog_handle *cathandle, int index)
+static int llog_cat_set_first_idx(struct llog_handle *cathandle, int index)
 {
        struct llog_log_hdr *llh = cathandle->lgh_hdr;
        int i, bitmap_size, idx;
@@ -750,7 +751,7 @@ int llog_cat_cleanup(const struct lu_env *env, struct llog_handle *cathandle,
        return rc;
 }
 
-int cat_cancel_cb(const struct lu_env *env, struct llog_handle *cathandle,
+static int cat_cancel_cb(const struct lu_env *env, struct llog_handle *cathandle,
                  struct llog_rec_hdr *rec, void *data)
 {
        struct llog_logid_rec   *lir = (struct llog_logid_rec *)rec;
@@ -794,7 +795,6 @@ int cat_cancel_cb(const struct lu_env *env, struct llog_handle *cathandle,
 
        return rc;
 }
-EXPORT_SYMBOL(cat_cancel_cb);
 
 /* helper to initialize catalog llog and process it to cancel */
 int llog_cat_init_and_process(const struct lu_env *env,
index ddab94d7ee82649cf2764e6a66fa4b0b5f07523c..c171c6c6c457cda82fedc82c29880ae3e0618dcd 100644 (file)
@@ -223,7 +223,7 @@ EXPORT_SYMBOL(lprocfs_write_frac_helper);
 
 #if defined (CONFIG_PROC_FS)
 
-static int lprocfs_no_percpu_stats = 0;
+static int lprocfs_no_percpu_stats;
 module_param(lprocfs_no_percpu_stats, int, 0644);
 MODULE_PARM_DESC(lprocfs_no_percpu_stats, "Do not alloc percpu data for lprocfs stats");
 
@@ -377,7 +377,8 @@ EXPORT_SYMBOL(lprocfs_register);
 /* Generic callbacks */
 int lprocfs_rd_uint(struct seq_file *m, void *data)
 {
-       return seq_printf(m, "%u\n", *(unsigned int *)data);
+       seq_printf(m, "%u\n", *(unsigned int *)data);
+       return 0;
 }
 EXPORT_SYMBOL(lprocfs_rd_uint);
 
@@ -403,7 +404,8 @@ EXPORT_SYMBOL(lprocfs_wr_uint);
 
 int lprocfs_rd_u64(struct seq_file *m, void *data)
 {
-       return seq_printf(m, "%llu\n", *(__u64 *)data);
+       seq_printf(m, "%llu\n", *(__u64 *)data);
+       return 0;
 }
 EXPORT_SYMBOL(lprocfs_rd_u64);
 
@@ -411,7 +413,8 @@ int lprocfs_rd_atomic(struct seq_file *m, void *data)
 {
        atomic_t *atom = data;
        LASSERT(atom != NULL);
-       return seq_printf(m, "%d\n", atomic_read(atom));
+       seq_printf(m, "%d\n", atomic_read(atom));
+       return 0;
 }
 EXPORT_SYMBOL(lprocfs_rd_atomic);
 
@@ -439,7 +442,8 @@ int lprocfs_rd_uuid(struct seq_file *m, void *data)
        struct obd_device *obd = data;
 
        LASSERT(obd != NULL);
-       return seq_printf(m, "%s\n", obd->obd_uuid.uuid);
+       seq_printf(m, "%s\n", obd->obd_uuid.uuid);
+       return 0;
 }
 EXPORT_SYMBOL(lprocfs_rd_uuid);
 
@@ -448,7 +452,8 @@ int lprocfs_rd_name(struct seq_file *m, void *data)
        struct obd_device *dev = data;
 
        LASSERT(dev != NULL);
-       return seq_printf(m, "%s\n", dev->obd_name);
+       seq_printf(m, "%s\n", dev->obd_name);
+       return 0;
 }
 EXPORT_SYMBOL(lprocfs_rd_name);
 
@@ -460,7 +465,8 @@ int lprocfs_rd_blksize(struct seq_file *m, void *data)
                            cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
                            OBD_STATFS_NODELAY);
        if (!rc)
-               rc = seq_printf(m, "%u\n", osfs.os_bsize);
+               seq_printf(m, "%u\n", osfs.os_bsize);
+
        return rc;
 }
 EXPORT_SYMBOL(lprocfs_rd_blksize);
@@ -479,8 +485,9 @@ int lprocfs_rd_kbytestotal(struct seq_file *m, void *data)
                while (blk_size >>= 1)
                        result <<= 1;
 
-               rc = seq_printf(m, "%llu\n", result);
+               seq_printf(m, "%llu\n", result);
        }
+
        return rc;
 }
 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
@@ -499,8 +506,9 @@ int lprocfs_rd_kbytesfree(struct seq_file *m, void *data)
                while (blk_size >>= 1)
                        result <<= 1;
 
-               rc = seq_printf(m, "%llu\n", result);
+               seq_printf(m, "%llu\n", result);
        }
+
        return rc;
 }
 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
@@ -519,8 +527,9 @@ int lprocfs_rd_kbytesavail(struct seq_file *m, void *data)
                while (blk_size >>= 1)
                        result <<= 1;
 
-               rc = seq_printf(m, "%llu\n", result);
+               seq_printf(m, "%llu\n", result);
        }
+
        return rc;
 }
 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
@@ -533,7 +542,7 @@ int lprocfs_rd_filestotal(struct seq_file *m, void *data)
                            cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
                            OBD_STATFS_NODELAY);
        if (!rc)
-               rc = seq_printf(m, "%llu\n", osfs.os_files);
+               seq_printf(m, "%llu\n", osfs.os_files);
 
        return rc;
 }
@@ -547,7 +556,8 @@ int lprocfs_rd_filesfree(struct seq_file *m, void *data)
                            cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
                            OBD_STATFS_NODELAY);
        if (!rc)
-               rc = seq_printf(m, "%llu\n", osfs.os_ffree);
+               seq_printf(m, "%llu\n", osfs.os_ffree);
+
        return rc;
 }
 EXPORT_SYMBOL(lprocfs_rd_filesfree);
@@ -557,17 +567,18 @@ int lprocfs_rd_server_uuid(struct seq_file *m, void *data)
        struct obd_device *obd = data;
        struct obd_import *imp;
        char *imp_state_name = NULL;
-       int rc = 0;
 
        LASSERT(obd != NULL);
        LPROCFS_CLIMP_CHECK(obd);
        imp = obd->u.cli.cl_import;
        imp_state_name = ptlrpc_import_state_name(imp->imp_state);
-       rc = seq_printf(m, "%s\t%s%s\n", obd2cli_tgt(obd), imp_state_name,
-                       imp->imp_deactive ? "\tDEACTIVATED" : "");
+       seq_printf(m, "%s\t%s%s\n",
+                  obd2cli_tgt(obd), imp_state_name,
+                  imp->imp_deactive ? "\tDEACTIVATED" : "");
 
        LPROCFS_CLIMP_EXIT(obd);
-       return rc;
+
+       return 0;
 }
 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
 
@@ -575,19 +586,19 @@ int lprocfs_rd_conn_uuid(struct seq_file *m, void *data)
 {
        struct obd_device *obd = data;
        struct ptlrpc_connection *conn;
-       int rc = 0;
 
        LASSERT(obd != NULL);
 
        LPROCFS_CLIMP_CHECK(obd);
        conn = obd->u.cli.cl_import->imp_connection;
        if (conn && obd->u.cli.cl_import)
-               rc = seq_printf(m, "%s\n", conn->c_remote_uuid.uuid);
+               seq_printf(m, "%s\n", conn->c_remote_uuid.uuid);
        else
-               rc = seq_printf(m, "%s\n", "<none>");
+               seq_puts(m, "<none>\n");
 
        LPROCFS_CLIMP_EXIT(obd);
-       return rc;
+
+       return 0;
 }
 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
 
@@ -924,7 +935,8 @@ int lprocfs_rd_num_exports(struct seq_file *m, void *data)
        struct obd_device *obd = data;
 
        LASSERT(obd != NULL);
-       return seq_printf(m, "%u\n", obd->obd_num_exports);
+       seq_printf(m, "%u\n", obd->obd_num_exports);
+       return 0;
 }
 EXPORT_SYMBOL(lprocfs_rd_num_exports);
 
@@ -933,7 +945,8 @@ int lprocfs_rd_numrefs(struct seq_file *m, void *data)
        struct obd_type *class = (struct obd_type *) data;
 
        LASSERT(class != NULL);
-       return seq_printf(m, "%d\n", class->typ_refcnt);
+       seq_printf(m, "%d\n", class->typ_refcnt);
+       return 0;
 }
 EXPORT_SYMBOL(lprocfs_rd_numrefs);
 
@@ -1200,41 +1213,33 @@ static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
        struct lprocfs_counter_header   *hdr;
        struct lprocfs_counter           ctr;
        int                              idx    = *(loff_t *)v;
-       int                              rc     = 0;
 
        if (idx == 0) {
                struct timeval now;
                do_gettimeofday(&now);
-               rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
-                               "snapshot_time", now.tv_sec, (unsigned long)now.tv_usec);
-               if (rc < 0)
-                       return rc;
+               seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
+                          "snapshot_time",
+                          now.tv_sec, (unsigned long)now.tv_usec);
        }
+
        hdr = &stats->ls_cnt_header[idx];
        lprocfs_stats_collect(stats, idx, &ctr);
 
-       if (ctr.lc_count == 0)
-               goto out;
-
-       rc = seq_printf(p, "%-25s %lld samples [%s]", hdr->lc_name,
-                       ctr.lc_count, hdr->lc_units);
+       if (ctr.lc_count != 0) {
+               seq_printf(p, "%-25s %lld samples [%s]",
+                          hdr->lc_name, ctr.lc_count, hdr->lc_units);
 
-       if (rc < 0)
-               goto out;
-
-       if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ctr.lc_count > 0)) {
-               rc = seq_printf(p, " %lld %lld %lld",
-                               ctr.lc_min, ctr.lc_max, ctr.lc_sum);
-               if (rc < 0)
-                       goto out;
-               if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
-                       rc = seq_printf(p, " %lld", ctr.lc_sumsquare);
-               if (rc < 0)
-                       goto out;
+               if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) &&
+                   (ctr.lc_count > 0)) {
+                       seq_printf(p, " %lld %lld %lld",
+                                  ctr.lc_min, ctr.lc_max, ctr.lc_sum);
+                       if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
+                               seq_printf(p, " %lld", ctr.lc_sumsquare);
+               }
+               seq_putc(p, '\n');
        }
-       rc = seq_printf(p, "\n");
-out:
-       return (rc < 0) ? rc : 0;
+
+       return 0;
 }
 
 static const struct seq_operations lprocfs_stats_seq_sops = {
@@ -1606,8 +1611,9 @@ LPROC_SEQ_FOPS_RO(lproc_exp_hash);
 
 int lprocfs_nid_stats_clear_read(struct seq_file *m, void *data)
 {
-       return seq_printf(m, "%s\n",
-                         "Write into this file to clear all nid stats and stale nid entries");
+       seq_printf(m, "%s\n",
+                  "Write into this file to clear all nid stats and stale nid entries");
+       return 0;
 }
 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
 
@@ -2041,12 +2047,12 @@ int lprocfs_obd_rd_max_pages_per_rpc(struct seq_file *m, void *data)
 {
        struct obd_device *dev = data;
        struct client_obd *cli = &dev->u.cli;
-       int rc;
 
        client_obd_list_lock(&cli->cl_loi_list_lock);
-       rc = seq_printf(m, "%d\n", cli->cl_max_pages_per_rpc);
+       seq_printf(m, "%d\n", cli->cl_max_pages_per_rpc);
        client_obd_list_unlock(&cli->cl_loi_list_lock);
-       return rc;
+
+       return 0;
 }
 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
 
index 83bf168c2939f0bd6bd4d6f21c8f520e78a54ac1..20c0779951fd7c7db9d21513eb5e5ebb820ecb2c 100644 (file)
@@ -1308,7 +1308,7 @@ static DEFINE_SPINLOCK(lu_keys_guard);
  * lu_context_refill(). No locking is provided, as initialization and shutdown
  * are supposed to be externally serialized.
  */
-static unsigned key_set_version = 0;
+static unsigned key_set_version;
 
 /**
  * Register new key.
@@ -1769,8 +1769,6 @@ EXPORT_SYMBOL(lu_env_refill);
 int lu_env_refill_by_tags(struct lu_env *env, __u32 ctags,
                          __u32 stags)
 {
-       int    result;
-
        if ((env->le_ctx.lc_tags & ctags) != ctags) {
                env->le_ctx.lc_version = 0;
                env->le_ctx.lc_tags |= ctags;
@@ -1781,9 +1779,7 @@ int lu_env_refill_by_tags(struct lu_env *env, __u32 ctags,
                env->le_ses->lc_tags |= stags;
        }
 
-       result = lu_env_refill(env);
-
-       return result;
+       return lu_env_refill(env);
 }
 EXPORT_SYMBOL(lu_env_refill_by_tags);
 
@@ -2014,18 +2010,19 @@ int lu_site_stats_print(const struct lu_site *s, struct seq_file *m)
        memset(&stats, 0, sizeof(stats));
        lu_site_stats_get(s->ls_obj_hash, &stats, 1);
 
-       return seq_printf(m, "%d/%d %d/%d %d %d %d %d %d %d %d\n",
-                       stats.lss_busy,
-                       stats.lss_total,
-                       stats.lss_populated,
-                       CFS_HASH_NHLIST(s->ls_obj_hash),
-                       stats.lss_max_search,
-                       ls_stats_read(s->ls_stats, LU_SS_CREATED),
-                       ls_stats_read(s->ls_stats, LU_SS_CACHE_HIT),
-                       ls_stats_read(s->ls_stats, LU_SS_CACHE_MISS),
-                       ls_stats_read(s->ls_stats, LU_SS_CACHE_RACE),
-                       ls_stats_read(s->ls_stats, LU_SS_CACHE_DEATH_RACE),
-                       ls_stats_read(s->ls_stats, LU_SS_LRU_PURGED));
+       seq_printf(m, "%d/%d %d/%d %d %d %d %d %d %d %d\n",
+                  stats.lss_busy,
+                  stats.lss_total,
+                  stats.lss_populated,
+                  CFS_HASH_NHLIST(s->ls_obj_hash),
+                  stats.lss_max_search,
+                  ls_stats_read(s->ls_stats, LU_SS_CREATED),
+                  ls_stats_read(s->ls_stats, LU_SS_CACHE_HIT),
+                  ls_stats_read(s->ls_stats, LU_SS_CACHE_MISS),
+                  ls_stats_read(s->ls_stats, LU_SS_CACHE_RACE),
+                  ls_stats_read(s->ls_stats, LU_SS_CACHE_DEATH_RACE),
+                  ls_stats_read(s->ls_stats, LU_SS_LRU_PURGED));
+       return 0;
 }
 EXPORT_SYMBOL(lu_site_stats_print);
 
index 3c0c9109cefd31ffd6946977cbfc2933272cdc3d..3437b2ecfc02873937ad9ee4eb1ffcb57b4fdf0e 100644 (file)
@@ -645,10 +645,10 @@ int lustre_put_lsi(struct super_block *sb)
 }
 
 /*** SERVER NAME ***
- * <FSNAME><SEPERATOR><TYPE><INDEX>
+ * <FSNAME><SEPARATOR><TYPE><INDEX>
  * FSNAME is between 1 and 8 characters (inclusive).
  *     Excluded characters are '/' and ':'
- * SEPERATOR is either ':' or '-'
+ * SEPARATOR is either ':' or '-'
  * TYPE: "OST", "MDT", etc.
  * INDEX: Hex representation of the index
  */
@@ -1286,7 +1286,7 @@ struct dentry *lustre_mount(struct file_system_type *fs_type, int flags,
        return mount_nodev(fs_type, flags, &lmd2, lustre_fill_super);
 }
 
-void lustre_kill_super(struct super_block *sb)
+static void lustre_kill_super(struct super_block *sb)
 {
        struct lustre_sb_info *lsi = s2lsi(sb);
 
index 5f6d9441bc4435698e17efad3d3aa78a26c7213d..d542e06d6cd38ef8cb394a4758038d77721fb5b7 100644 (file)
@@ -146,6 +146,7 @@ static struct lu_context_key echo_thread_key;
 static inline struct echo_thread_info *echo_env_info(const struct lu_env *env)
 {
        struct echo_thread_info *info;
+
        info = lu_context_key_get(&env->le_ctx, &echo_thread_key);
        LASSERT(info != NULL);
        return info;
@@ -195,22 +196,22 @@ static struct lu_kmem_descr echo_caches[] = {
        {
                .ckd_cache = &echo_lock_kmem,
                .ckd_name  = "echo_lock_kmem",
-               .ckd_size  = sizeof (struct echo_lock)
+               .ckd_size  = sizeof(struct echo_lock)
        },
        {
                .ckd_cache = &echo_object_kmem,
                .ckd_name  = "echo_object_kmem",
-               .ckd_size  = sizeof (struct echo_object)
+               .ckd_size  = sizeof(struct echo_object)
        },
        {
                .ckd_cache = &echo_thread_kmem,
                .ckd_name  = "echo_thread_kmem",
-               .ckd_size  = sizeof (struct echo_thread_info)
+               .ckd_size  = sizeof(struct echo_thread_info)
        },
        {
                .ckd_cache = &echo_session_kmem,
                .ckd_name  = "echo_session_kmem",
-               .ckd_size  = sizeof (struct echo_session_info)
+               .ckd_size  = sizeof(struct echo_session_info)
        },
        {
                .ckd_cache = NULL
@@ -637,6 +638,7 @@ static void echo_thread_key_fini(const struct lu_context *ctx,
                         struct lu_context_key *key, void *data)
 {
        struct echo_thread_info *info = data;
+
        OBD_SLAB_FREE_PTR(info, echo_thread_kmem);
 }
 
@@ -667,6 +669,7 @@ static void echo_session_key_fini(const struct lu_context *ctx,
                                 struct lu_context_key *key, void *data)
 {
        struct echo_session_info *session = data;
+
        OBD_SLAB_FREE_PTR(session, echo_session_kmem);
 }
 
@@ -783,6 +786,7 @@ out:
        switch (cleanup) {
        case 4: {
                int rc2;
+
                rc2 = echo_client_cleanup(obd);
                if (rc2)
                        CERROR("Cleanup obd device %s error(%d)\n",
@@ -958,11 +962,13 @@ static struct echo_object *cl_echo_object_find(struct echo_device *d,
        if (d->ed_next) {
                if (!d->ed_next_islov) {
                        struct lov_oinfo *oinfo = lsm->lsm_oinfo[0];
+
                        LASSERT(oinfo != NULL);
                        oinfo->loi_oi = lsm->lsm_oi;
                        conf->eoc_cl.u.coc_oinfo = oinfo;
                } else {
                        struct lustre_md *md;
+
                        md = &info->eti_md;
                        memset(md, 0, sizeof(*md));
                        md->lsm = lsm;
@@ -1011,6 +1017,7 @@ static int cl_echo_object_put(struct echo_object *eco)
        /* an external function to kill an object? */
        if (eco->eo_deleted) {
                struct lu_object_header *loh = obj->co_lu.lo_header;
+
                LASSERT(&eco->eo_hdr == luh2coh(loh));
                set_bit(LU_OBJECT_HEARD_BANSHEE, &loh->loh_flags);
        }
@@ -1022,7 +1029,7 @@ static int cl_echo_object_put(struct echo_object *eco)
 
 static int cl_echo_enqueue0(struct lu_env *env, struct echo_object *eco,
                            u64 start, u64 end, int mode,
-                           __u64 *cookie , __u32 enqflags)
+                           __u64 *cookie, __u32 enqflags)
 {
        struct cl_io *io;
        struct cl_lock *lck;
@@ -1106,8 +1113,8 @@ static int cl_echo_cancel0(struct lu_env *env, struct echo_device *ed,
 
        LASSERT(ec != NULL);
        spin_lock(&ec->ec_lock);
-       list_for_each (el, &ec->ec_locks) {
-               ecl = list_entry (el, struct echo_lock, el_chain);
+       list_for_each(el, &ec->ec_locks) {
+               ecl = list_entry(el, struct echo_lock, el_chain);
                CDEBUG(D_INFO, "ecl: %p, cookie: %#llx\n", ecl, ecl->el_cookie);
                found = (ecl->el_cookie == cookie);
                if (found) {
@@ -1152,6 +1159,7 @@ static int cl_echo_async_brw(const struct lu_env *env, struct cl_io *io,
 
        cl_page_list_for_each_safe(clp, temp, &queue->c2_qin) {
                int rc;
+
                rc = cl_page_cache_add(env, io, clp, CRT_WRITE);
                if (rc == 0)
                        continue;
@@ -1257,20 +1265,20 @@ out:
 static u64 last_object_id;
 
 static int
-echo_copyout_lsm (struct lov_stripe_md *lsm, void *_ulsm, int ulsm_nob)
+echo_copyout_lsm(struct lov_stripe_md *lsm, void *_ulsm, int ulsm_nob)
 {
        struct lov_stripe_md *ulsm = _ulsm;
        int nob, i;
 
-       nob = offsetof (struct lov_stripe_md, lsm_oinfo[lsm->lsm_stripe_count]);
+       nob = offsetof(struct lov_stripe_md, lsm_oinfo[lsm->lsm_stripe_count]);
        if (nob > ulsm_nob)
                return -EINVAL;
 
-       if (copy_to_user (ulsm, lsm, sizeof(*ulsm)))
+       if (copy_to_user(ulsm, lsm, sizeof(*ulsm)))
                return -EFAULT;
 
        for (i = 0; i < lsm->lsm_stripe_count; i++) {
-               if (copy_to_user (ulsm->lsm_oinfo[i], lsm->lsm_oinfo[i],
+               if (copy_to_user(ulsm->lsm_oinfo[i], lsm->lsm_oinfo[i],
                                      sizeof(lsm->lsm_oinfo[0])))
                        return -EFAULT;
        }
@@ -1278,16 +1286,16 @@ echo_copyout_lsm (struct lov_stripe_md *lsm, void *_ulsm, int ulsm_nob)
 }
 
 static int
-echo_copyin_lsm (struct echo_device *ed, struct lov_stripe_md *lsm,
+echo_copyin_lsm(struct echo_device *ed, struct lov_stripe_md *lsm,
                 void *ulsm, int ulsm_nob)
 {
        struct echo_client_obd *ec = ed->ed_ec;
        int                  i;
 
-       if (ulsm_nob < sizeof (*lsm))
+       if (ulsm_nob < sizeof(*lsm))
                return -EINVAL;
 
-       if (copy_from_user (lsm, ulsm, sizeof (*lsm)))
+       if (copy_from_user(lsm, ulsm, sizeof(*lsm)))
                return -EFAULT;
 
        if (lsm->lsm_stripe_count > ec->ec_nstripes ||
@@ -1320,7 +1328,7 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed,
        if ((oa->o_valid & OBD_MD_FLID) == 0 && /* no obj id */
            (on_target ||                      /* set_stripe */
             ec->ec_nstripes != 0)) {      /* LOV */
-               CERROR ("No valid oid\n");
+               CERROR("No valid oid\n");
                return -EINVAL;
        }
 
@@ -1333,7 +1341,7 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed,
        if (ulsm != NULL) {
                int i, idx;
 
-               rc = echo_copyin_lsm (ed, lsm, ulsm, ulsm_nob);
+               rc = echo_copyin_lsm(ed, lsm, ulsm, ulsm_nob);
                if (rc != 0)
                        goto failed;
 
@@ -1409,7 +1417,7 @@ static int echo_get_object(struct echo_object **ecop, struct echo_device *ed,
 
        if ((oa->o_valid & OBD_MD_FLID) == 0 || ostid_id(&oa->o_oi) == 0) {
                /* disallow use of object id 0 */
-               CERROR ("No valid oid\n");
+               CERROR("No valid oid\n");
                return -EINVAL;
        }
 
@@ -1459,7 +1467,7 @@ echo_get_stripe_off_id(struct lov_stripe_md *lsm, u64 *offp, u64 *idp)
        width = stripe_size * stripe_count;
 
        /* woffset = offset within a width; offset = whole number of widths */
-       woffset = do_div (offset, width);
+       woffset = do_div(offset, width);
 
        stripe_index = woffset / stripe_size;
 
@@ -1517,13 +1525,13 @@ static int echo_client_page_debug_check(struct lov_stripe_md *lsm,
        for (rc = delta = 0; delta < PAGE_CACHE_SIZE; delta += OBD_ECHO_BLOCK_SIZE) {
                stripe_off = offset + delta;
                stripe_id = id;
-               echo_get_stripe_off_id (lsm, &stripe_off, &stripe_id);
+               echo_get_stripe_off_id(lsm, &stripe_off, &stripe_id);
 
                rc2 = block_debug_check("test_brw",
                                        addr + delta, OBD_ECHO_BLOCK_SIZE,
                                        stripe_off, stripe_id);
                if (rc2 != 0) {
-                       CERROR ("Error in echo object %#llx\n", id);
+                       CERROR("Error in echo object %#llx\n", id);
                        rc = rc2;
                }
        }
@@ -1583,7 +1591,7 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa,
             i < npages;
             i++, pgp++, off += PAGE_CACHE_SIZE) {
 
-               LASSERT (pgp->pg == NULL);      /* for cleanup */
+               LASSERT(pgp->pg == NULL);      /* for cleanup */
 
                rc = -ENOMEM;
                OBD_PAGE_ALLOC(pgp->pg, gfp_mask);
@@ -1615,6 +1623,7 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa,
 
                if (verify) {
                        int vrc;
+
                        vrc = echo_client_page_debug_check(lsm, pgp->pg,
                                                           ostid_id(&oa->o_oi),
                                                           pgp->off, pgp->count);
@@ -1812,7 +1821,7 @@ echo_client_enqueue(struct obd_export *exp, struct obdo *oa,
            (nob & (~CFS_PAGE_MASK)) != 0)
                return -EINVAL;
 
-       rc = echo_get_object (&eco, ed, oa);
+       rc = echo_get_object(&eco, ed, oa);
        if (rc != 0)
                return rc;
 
@@ -1911,6 +1920,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                rc = echo_get_object(&eco, ed, oa);
                if (rc == 0) {
                        struct obd_info oinfo = { { { 0 } } };
+
                        oinfo.oi_md = eco->eo_lsm;
                        oinfo.oi_oa = oa;
                        rc = obd_getattr(env, ec->ec_exp, &oinfo);
@@ -1927,6 +1937,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                rc = echo_get_object(&eco, ed, oa);
                if (rc == 0) {
                        struct obd_info oinfo = { { { 0 } } };
+
                        oinfo.oi_oa = oa;
                        oinfo.oi_md = eco->eo_lsm;
 
@@ -1992,7 +2003,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                goto out;
 
        default:
-               CERROR ("echo_ioctl(): unrecognised ioctl %#x\n", cmd);
+               CERROR("echo_ioctl(): unrecognised ioctl %#x\n", cmd);
                rc = -ENOTTY;
                goto out;
        }
@@ -2034,8 +2045,8 @@ static int echo_client_setup(const struct lu_env *env,
        }
 
        spin_lock_init(&ec->ec_lock);
-       INIT_LIST_HEAD (&ec->ec_objects);
-       INIT_LIST_HEAD (&ec->ec_locks);
+       INIT_LIST_HEAD(&ec->ec_objects);
+       INIT_LIST_HEAD(&ec->ec_locks);
        ec->ec_unique = 0;
        ec->ec_nstripes = 0;
 
@@ -2158,7 +2169,6 @@ void echo_client_exit(void)
 static int __init obdecho_init(void)
 {
        struct lprocfs_static_vars lvars;
-       int rc;
 
        LCONSOLE_INFO("Echo OBD driver; http://www.lustre.org/\n");
 
@@ -2167,9 +2177,7 @@ static int __init obdecho_init(void)
        lprocfs_echo_init_vars(&lvars);
 
 
-       rc = echo_client_init();
-
-       return rc;
+       return echo_client_init();
 }
 
 static void /*__exit*/ obdecho_exit(void)
index 1d3bf6c931297aef5bd905adc54525558ab3f91b..0beb97db7c7d9d377bee945139eccc242bd9bc52 100644 (file)
@@ -36,7 +36,7 @@
 #include "../include/lprocfs_status.h"
 #include "../include/obd_class.h"
 
-#if defined (CONFIG_PROC_FS)
+#if defined(CONFIG_PROC_FS)
 LPROC_SEQ_FOPS_RO_TYPE(echo, uuid);
 static struct lprocfs_vars lprocfs_echo_obd_vars[] = {
        { "uuid",        &echo_uuid_fops,       NULL, 0 },
index 1795d3a7a02954d28a5de04e8e9c220a4045a75f..15a66209831c56b38beb5b3393b8c32f2b0c4e87 100644 (file)
@@ -35,7 +35,7 @@
  */
 #define DEBUG_SUBSYSTEM S_CLASS
 
-#include <asm/statfs.h>
+#include <linux/statfs.h>
 #include "../include/obd_cksum.h"
 #include "../include/obd_class.h"
 #include "../include/lprocfs_status.h"
 static int osc_active_seq_show(struct seq_file *m, void *v)
 {
        struct obd_device *dev = m->private;
-       int rc;
 
        LPROCFS_CLIMP_CHECK(dev);
-       rc = seq_printf(m, "%d\n", !dev->u.cli.cl_import->imp_deactive);
+       seq_printf(m, "%d\n", !dev->u.cli.cl_import->imp_deactive);
        LPROCFS_CLIMP_EXIT(dev);
-       return rc;
+
+       return 0;
 }
 
 static ssize_t osc_active_seq_write(struct file *file,
@@ -80,12 +80,12 @@ static int osc_max_rpcs_in_flight_seq_show(struct seq_file *m, void *v)
 {
        struct obd_device *dev = m->private;
        struct client_obd *cli = &dev->u.cli;
-       int rc;
 
        client_obd_list_lock(&cli->cl_loi_list_lock);
-       rc = seq_printf(m, "%u\n", cli->cl_max_rpcs_in_flight);
+       seq_printf(m, "%u\n", cli->cl_max_rpcs_in_flight);
        client_obd_list_unlock(&cli->cl_loi_list_lock);
-       return rc;
+
+       return 0;
 }
 
 static ssize_t osc_max_rpcs_in_flight_seq_write(struct file *file,
@@ -164,16 +164,15 @@ static int osc_cached_mb_seq_show(struct seq_file *m, void *v)
        struct obd_device *dev = m->private;
        struct client_obd *cli = &dev->u.cli;
        int shift = 20 - PAGE_CACHE_SHIFT;
-       int rc;
 
-       rc = seq_printf(m,
-                     "used_mb: %d\n"
-                     "busy_cnt: %d\n",
-                     (atomic_read(&cli->cl_lru_in_list) +
-                       atomic_read(&cli->cl_lru_busy)) >> shift,
-                     atomic_read(&cli->cl_lru_busy));
+       seq_printf(m,
+                  "used_mb: %d\n"
+                  "busy_cnt: %d\n",
+                  (atomic_read(&cli->cl_lru_in_list) +
+                   atomic_read(&cli->cl_lru_busy)) >> shift,
+                  atomic_read(&cli->cl_lru_busy));
 
-       return rc;
+       return 0;
 }
 
 /* shrink the number of caching pages to a specific number */
@@ -215,12 +214,12 @@ static int osc_cur_dirty_bytes_seq_show(struct seq_file *m, void *v)
 {
        struct obd_device *dev = m->private;
        struct client_obd *cli = &dev->u.cli;
-       int rc;
 
        client_obd_list_lock(&cli->cl_loi_list_lock);
-       rc = seq_printf(m, "%lu\n", cli->cl_dirty);
+       seq_printf(m, "%lu\n", cli->cl_dirty);
        client_obd_list_unlock(&cli->cl_loi_list_lock);
-       return rc;
+
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(osc_cur_dirty_bytes);
 
@@ -228,12 +227,12 @@ static int osc_cur_grant_bytes_seq_show(struct seq_file *m, void *v)
 {
        struct obd_device *dev = m->private;
        struct client_obd *cli = &dev->u.cli;
-       int rc;
 
        client_obd_list_lock(&cli->cl_loi_list_lock);
-       rc = seq_printf(m, "%lu\n", cli->cl_avail_grant);
+       seq_printf(m, "%lu\n", cli->cl_avail_grant);
        client_obd_list_unlock(&cli->cl_loi_list_lock);
-       return rc;
+
+       return 0;
 }
 
 static ssize_t osc_cur_grant_bytes_seq_write(struct file *file,
@@ -274,12 +273,12 @@ static int osc_cur_lost_grant_bytes_seq_show(struct seq_file *m, void *v)
 {
        struct obd_device *dev = m->private;
        struct client_obd *cli = &dev->u.cli;
-       int rc;
 
        client_obd_list_lock(&cli->cl_loi_list_lock);
-       rc = seq_printf(m, "%lu\n", cli->cl_lost_grant);
+       seq_printf(m, "%lu\n", cli->cl_lost_grant);
        client_obd_list_unlock(&cli->cl_loi_list_lock);
-       return rc;
+
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(osc_cur_lost_grant_bytes);
 
@@ -289,8 +288,8 @@ static int osc_grant_shrink_interval_seq_show(struct seq_file *m, void *v)
 
        if (obd == NULL)
                return 0;
-       return seq_printf(m, "%d\n",
-                       obd->u.cli.cl_grant_shrink_interval);
+       seq_printf(m, "%d\n", obd->u.cli.cl_grant_shrink_interval);
+       return 0;
 }
 
 static ssize_t osc_grant_shrink_interval_seq_write(struct file *file,
@@ -323,8 +322,8 @@ static int osc_checksum_seq_show(struct seq_file *m, void *v)
        if (obd == NULL)
                return 0;
 
-       return seq_printf(m, "%d\n",
-                       obd->u.cli.cl_checksum ? 1 : 0);
+       seq_printf(m, "%d\n", obd->u.cli.cl_checksum ? 1 : 0);
+       return 0;
 }
 
 static ssize_t osc_checksum_seq_write(struct file *file,
@@ -405,7 +404,8 @@ static int osc_resend_count_seq_show(struct seq_file *m, void *v)
 {
        struct obd_device *obd = m->private;
 
-       return seq_printf(m, "%u\n", atomic_read(&obd->u.cli.cl_resends));
+       seq_printf(m, "%u\n", atomic_read(&obd->u.cli.cl_resends));
+       return 0;
 }
 
 static ssize_t osc_resend_count_seq_write(struct file *file,
@@ -433,7 +433,8 @@ static int osc_contention_seconds_seq_show(struct seq_file *m, void *v)
        struct obd_device *obd = m->private;
        struct osc_device *od  = obd2osc_dev(obd);
 
-       return seq_printf(m, "%u\n", od->od_contention_time);
+       seq_printf(m, "%u\n", od->od_contention_time);
+       return 0;
 }
 
 static ssize_t osc_contention_seconds_seq_write(struct file *file,
@@ -453,7 +454,8 @@ static int osc_lockless_truncate_seq_show(struct seq_file *m, void *v)
        struct obd_device *obd = m->private;
        struct osc_device *od  = obd2osc_dev(obd);
 
-       return seq_printf(m, "%u\n", od->od_lockless_truncate);
+       seq_printf(m, "%u\n", od->od_lockless_truncate);
+       return 0;
 }
 
 static ssize_t osc_lockless_truncate_seq_write(struct file *file,
@@ -471,8 +473,9 @@ LPROC_SEQ_FOPS(osc_lockless_truncate);
 static int osc_destroys_in_flight_seq_show(struct seq_file *m, void *v)
 {
        struct obd_device *obd = m->private;
-       return seq_printf(m, "%u\n",
-                       atomic_read(&obd->u.cli.cl_destroy_in_flight));
+
+       seq_printf(m, "%u\n", atomic_read(&obd->u.cli.cl_destroy_in_flight));
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(osc_destroys_in_flight);
 
index 7022ed42d2d124104530a343c456a833bb6ceaa9..d44b3d4ffe4d152ff2e32b3740a3d2aa9790ddd8 100644 (file)
@@ -2613,7 +2613,7 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj,
        }
        osc_object_unlock(obj);
 
-       osc_io_unplug(env, cli, obj, PDL_POLICY_ROUND);
+       osc_io_unplug_async(env, cli, obj);
        return 0;
 }
 
index fad4c135f9284dda5bf7ad744fa9d86b0b2a2b93..3c7300b0651dbf94788b2de1e68458e8abd9908e 100644 (file)
@@ -417,7 +417,7 @@ static int osc_io_setattr_start(const struct lu_env *env,
 
                        if (ia_valid & ATTR_SIZE) {
                                attr->cat_size = attr->cat_kms = size;
-                               cl_valid = (CAT_SIZE | CAT_KMS);
+                               cl_valid = CAT_SIZE | CAT_KMS;
                        }
                        if (ia_valid & ATTR_MTIME_SET) {
                                attr->cat_mtime = lvb->lvb_mtime;
index 445655724904648aa90dcdf26f68a54b0aaabb8b..350ad49550ab308b9628d437be81e616bbae68ca 100644 (file)
@@ -1010,7 +1010,7 @@ static int osc_lock_enqueue_wait(const struct lu_env *env,
        struct cl_lock_descr    *descr   = &lock->cll_descr;
        struct cl_object_header *hdr     = cl_object_header(descr->cld_obj);
        struct cl_lock    *scan;
-       struct cl_lock    *conflict= NULL;
+       struct cl_lock    *conflict = NULL;
        int lockless                 = osc_lock_is_lockless(olck);
        int rc                     = 0;
 
index 0adfa707a76333364942f97cb835c74f649cf1e4..d7a9b650df09cefa2044b010b5f2abc6bed1b3e9 100644 (file)
@@ -1165,8 +1165,8 @@ static int check_write_rcs(struct ptlrpc_request *req,
 static inline int can_merge_pages(struct brw_page *p1, struct brw_page *p2)
 {
        if (p1->flag != p2->flag) {
-               unsigned mask = ~(OBD_BRW_FROM_GRANT| OBD_BRW_NOCACHE|
-                                 OBD_BRW_SYNC|OBD_BRW_ASYNC|OBD_BRW_NOQUOTA);
+               unsigned mask = ~(OBD_BRW_FROM_GRANT | OBD_BRW_NOCACHE |
+                                 OBD_BRW_SYNC | OBD_BRW_ASYNC|OBD_BRW_NOQUOTA);
 
                /* warn if we try to combine flags that we don't know to be
                 * safe to combine */
@@ -1880,6 +1880,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli,
        int                             page_count = 0;
        int                             i;
        int                             rc;
+       struct ost_body                 *body;
        LIST_HEAD(rpc_list);
 
        LASSERT(!list_empty(ext_list));
@@ -1981,6 +1982,8 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli,
         * later setattr before earlier BRW (as determined by the request xid),
         * the OST will not use BRW timestamps.  Sadly, there is no obvious
         * way to do this in a single call.  bug 10150 */
+       body = req_capsule_client_get(&req->rq_pill, &RMF_OST_BODY);
+       crattr->cra_oa = &body->oa;
        cl_req_attr_set(env, clerq, crattr,
                        OBD_MD_FLMTIME|OBD_MD_FLCTIME|OBD_MD_FLATIME);
 
index 4882dd0a448378fdadf536ef0edd3b2afc5d8a84..0357f1d4532f3763b5601ccbdad857a9ba6392af 100644 (file)
@@ -285,14 +285,27 @@ static void ptlrpc_at_adj_net_latency(struct ptlrpc_request *req,
        time_t now = get_seconds();
 
        LASSERT(req->rq_import);
-       at = &req->rq_import->imp_at;
+
+       if (service_time > now - req->rq_sent + 3) {
+               /* bz16408, however, this can also happen if early reply
+                * is lost and client RPC is expired and resent, early reply
+                * or reply of original RPC can still be fit in reply buffer
+                * of resent RPC, now client is measuring time from the
+                * resent time, but server sent back service time of original
+                * RPC.
+                */
+               CDEBUG((lustre_msg_get_flags(req->rq_reqmsg) & MSG_RESENT) ?
+                      D_ADAPTTO : D_WARNING,
+                      "Reported service time %u > total measured time "
+                      CFS_DURATION_T"\n", service_time,
+                      cfs_time_sub(now, req->rq_sent));
+               return;
+       }
 
        /* Network latency is total time less server processing time */
-       nl = max_t(int, now - req->rq_sent - service_time, 0) + 1/*st rounding*/;
-       if (service_time > now - req->rq_sent + 3 /* bz16408 */)
-               CWARN("Reported service time %u > total measured time "
-                     CFS_DURATION_T"\n", service_time,
-                     cfs_time_sub(now, req->rq_sent));
+       nl = max_t(int, now - req->rq_sent -
+                       service_time, 0) + 1; /* st rounding */
+       at = &req->rq_import->imp_at;
 
        oldnl = at_measured(&at->iat_net_latency, nl);
        if (oldnl != 0)
@@ -468,7 +481,6 @@ void ptlrpc_add_rqs_to_pool(struct ptlrpc_request_pool *pool, int num_rq)
                list_add_tail(&req->rq_list, &pool->prp_req_list);
        }
        spin_unlock(&pool->prp_lock);
-       return;
 }
 EXPORT_SYMBOL(ptlrpc_add_rqs_to_pool);
 
@@ -1439,12 +1451,11 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
                if (req->rq_err) {
                        req->rq_status = rc;
                        return 1;
-               } else {
-                       spin_lock(&req->rq_lock);
-                       req->rq_wait_ctx = 1;
-                       spin_unlock(&req->rq_lock);
-                       return 0;
                }
+               spin_lock(&req->rq_lock);
+               req->rq_wait_ctx = 1;
+               spin_unlock(&req->rq_lock);
+               return 0;
        }
 
        CDEBUG(D_RPCTRACE, "Sending RPC pname:cluuid:pid:xid:nid:opc %s:%s:%d:%llu:%s:%d\n",
@@ -2192,7 +2203,7 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set)
        if (set->set_interpret != NULL) {
                int (*interpreter)(struct ptlrpc_request_set *set, void *, int) =
                        set->set_interpret;
-               rc = interpreter (set, set->set_arg, rc);
+               rc = interpreter(set, set->set_arg, rc);
        } else {
                struct ptlrpc_set_cbdata *cbdata, *n;
                int err;
index 2a875ab579118100cbf6637fd0b0e3d02b91123d..7e27397ce384c258976d53bed4e84a1c39801234 100644 (file)
@@ -184,6 +184,7 @@ static void *
 conn_key(struct hlist_node *hnode)
 {
        struct ptlrpc_connection *conn;
+
        conn = hlist_entry(hnode, struct ptlrpc_connection, c_hash);
        return &conn->c_peer;
 }
index 4ceb90db02a3f3f84cbfcabdf0f7f175b3aa6515..d5fc689c008b55cc474d7924e4ccb6f1c4c539c5 100644 (file)
@@ -63,6 +63,19 @@ struct ptlrpc_connect_async_args {
 static void __import_set_state(struct obd_import *imp,
                               enum lustre_imp_state state)
 {
+       switch (state) {
+       case LUSTRE_IMP_CLOSED:
+       case LUSTRE_IMP_NEW:
+       case LUSTRE_IMP_DISCON:
+       case LUSTRE_IMP_CONNECTING:
+               break;
+       case LUSTRE_IMP_REPLAY_WAIT:
+               imp->imp_replay_state = LUSTRE_IMP_REPLAY_LOCKS;
+               break;
+       default:
+               imp->imp_replay_state = LUSTRE_IMP_REPLAY;
+       }
+
        imp->imp_state = state;
        imp->imp_state_hist[imp->imp_state_hist_idx].ish_state = state;
        imp->imp_state_hist[imp->imp_state_hist_idx].ish_time =
@@ -966,7 +979,7 @@ static int ptlrpc_connect_interpret(const struct lu_env *env,
                        imp->imp_resend_replay = 1;
                        spin_unlock(&imp->imp_lock);
 
-                       IMPORT_SET_STATE(imp, LUSTRE_IMP_REPLAY);
+                       IMPORT_SET_STATE(imp, imp->imp_replay_state);
                } else {
                        IMPORT_SET_STATE(imp, LUSTRE_IMP_RECOVER);
                }
index bbef666b1d167b1f3dfce82e38490faa6304ea11..a42335e26de908de88dd0438fc4cbc69ad255925 100644 (file)
@@ -811,8 +811,8 @@ struct req_capsule;
        .rmf_name    = (name),                            \
        .rmf_flags   = (flags),                          \
        .rmf_size    = (size),                            \
-       .rmf_swabber = (void (*)(void*))(swabber),            \
-       .rmf_dumper  = (void (*)(void*))(dumper)                \
+       .rmf_swabber = (void (*)(void *))(swabber),           \
+       .rmf_dumper  = (void (*)(void *))(dumper)               \
 }
 
 struct req_msg_field RMF_GENERIC_DATA =
@@ -1839,7 +1839,7 @@ static int __req_capsule_offset(const struct req_capsule *pill,
        LASSERTF(offset > 0, "%s:%s, off=%d, loc=%d\n",
                            pill->rc_fmt->rf_name,
                            field->rmf_name, offset, loc);
-       offset --;
+       offset--;
 
        LASSERT(0 <= offset && offset < REQ_MAX_FIELD_NR);
        return offset;
index 0e2071b8a36e97c09353bff50802ac196fd35d2f..9533ab976a33a21c23ec43e26f77420939b87fac 100644 (file)
@@ -181,7 +181,7 @@ static const char *ll_eopcode2str(__u32 opcode)
        return ll_eopcode_table[opcode].opname;
 }
 
-#if defined (CONFIG_PROC_FS)
+#if defined(CONFIG_PROC_FS)
 static void ptlrpc_lprocfs_register(struct proc_dir_entry *root, char *dir,
                                    char *name,
                                    struct proc_dir_entry **procroot_ret,
@@ -267,7 +267,8 @@ ptlrpc_lprocfs_req_history_len_seq_show(struct seq_file *m, void *v)
        ptlrpc_service_for_each_part(svcpt, i, svc)
                total += svcpt->scp_hist_nrqbds;
 
-       return seq_printf(m, "%d\n", total);
+       seq_printf(m, "%d\n", total);
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_req_history_len);
 
@@ -282,7 +283,8 @@ ptlrpc_lprocfs_req_history_max_seq_show(struct seq_file *m, void *n)
        ptlrpc_service_for_each_part(svcpt, i, svc)
                total += svc->srv_hist_nrqbds_cpt_max;
 
-       return seq_printf(m, "%d\n", total);
+       seq_printf(m, "%d\n", total);
+       return 0;
 }
 
 static ssize_t
@@ -327,8 +329,8 @@ ptlrpc_lprocfs_threads_min_seq_show(struct seq_file *m, void *n)
 {
        struct ptlrpc_service *svc = m->private;
 
-       return seq_printf(m, "%d\n",
-                       svc->srv_nthrs_cpt_init * svc->srv_ncpts);
+       seq_printf(m, "%d\n", svc->srv_nthrs_cpt_init * svc->srv_ncpts);
+       return 0;
 }
 
 static ssize_t
@@ -371,7 +373,8 @@ ptlrpc_lprocfs_threads_started_seq_show(struct seq_file *m, void *n)
        ptlrpc_service_for_each_part(svcpt, i, svc)
                total += svcpt->scp_nthrs_running;
 
-       return seq_printf(m, "%d\n", total);
+       seq_printf(m, "%d\n", total);
+       return 0;
 }
 LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_threads_started);
 
@@ -380,8 +383,8 @@ ptlrpc_lprocfs_threads_max_seq_show(struct seq_file *m, void *n)
 {
        struct ptlrpc_service *svc = m->private;
 
-       return seq_printf(m, "%d\n",
-                       svc->srv_nthrs_cpt_limit * svc->srv_ncpts);
+       seq_printf(m, "%d\n", svc->srv_nthrs_cpt_limit * svc->srv_ncpts);
+       return 0;
 }
 
 static ssize_t
@@ -1026,7 +1029,8 @@ LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_timeouts);
 static int ptlrpc_lprocfs_hp_ratio_seq_show(struct seq_file *m, void *v)
 {
        struct ptlrpc_service *svc = m->private;
-       return seq_printf(m, "%d", svc->srv_hpreq_ratio);
+       seq_printf(m, "%d", svc->srv_hpreq_ratio);
+       return 0;
 }
 
 static ssize_t ptlrpc_lprocfs_hp_ratio_seq_write(struct file *file,
@@ -1083,7 +1087,7 @@ void ptlrpc_lprocfs_register_service(struct proc_dir_entry *entry,
                 .data       = svc},
                {NULL}
        };
-       static struct file_operations req_history_fops = {
+       static const struct file_operations req_history_fops = {
                .owner       = THIS_MODULE,
                .open   = ptlrpc_lprocfs_svc_req_history_open,
                .read   = seq_read,
@@ -1324,13 +1328,12 @@ int lprocfs_rd_pinger_recov(struct seq_file *m, void *n)
 {
        struct obd_device *obd = m->private;
        struct obd_import *imp = obd->u.cli.cl_import;
-       int rc;
 
        LPROCFS_CLIMP_CHECK(obd);
-       rc = seq_printf(m, "%d\n", !imp->imp_no_pinger_recover);
+       seq_printf(m, "%d\n", !imp->imp_no_pinger_recover);
        LPROCFS_CLIMP_EXIT(obd);
 
-       return rc;
+       return 0;
 }
 EXPORT_SYMBOL(lprocfs_rd_pinger_recov);
 
index f715e9a8b996119f58183bc7e986cdca2abadbf3..2fa2585584a3d81b33341a4d7a4ed9c2d639a261 100644 (file)
@@ -383,12 +383,13 @@ int ptlrpc_send_reply(struct ptlrpc_request *req, int flags)
                       req->rq_export->exp_obd->obd_minor);
        }
 
-       /* In order to keep interoprability with the client (< 2.3) which
+       /* In order to keep interoperability with the client (< 2.3) which
         * doesn't have pb_jobid in ptlrpc_body, We have to shrink the
         * ptlrpc_body in reply buffer to ptlrpc_body_v2, otherwise, the
         * reply buffer on client will be overflow.
         *
-        * XXX Remove this whenever we drop the interoprability with such client.
+        * XXX Remove this whenever we drop the interoperability with
+        * such client.
         */
        req->rq_replen = lustre_shrink_msg(req->rq_repmsg, 0,
                                           sizeof(struct ptlrpc_body_v2), 1);
index d5fd7215c72f9dcc24d2e1210d8876937f817da4..81ad7473242eda90394aa7bc432fb6ab5574948c 100644 (file)
@@ -155,9 +155,8 @@ static void nrs_policy_stop_primary(struct ptlrpc_nrs *nrs)
 {
        struct ptlrpc_nrs_policy *tmp = nrs->nrs_policy_primary;
 
-       if (tmp == NULL) {
+       if (tmp == NULL)
                return;
-       }
 
        nrs->nrs_policy_primary = NULL;
 
@@ -912,7 +911,6 @@ static int nrs_register_policies_locked(struct ptlrpc_nrs *nrs)
 static int nrs_svcpt_setup_locked0(struct ptlrpc_nrs *nrs,
                                   struct ptlrpc_service_part *svcpt)
 {
-       int                             rc;
        enum ptlrpc_nrs_queue_type      queue;
 
        LASSERT(mutex_is_locked(&nrs_core.nrs_mutex));
@@ -930,9 +928,7 @@ static int nrs_svcpt_setup_locked0(struct ptlrpc_nrs *nrs,
        INIT_LIST_HEAD(&nrs->nrs_policy_list);
        INIT_LIST_HEAD(&nrs->nrs_policy_queued);
 
-       rc = nrs_register_policies_locked(nrs);
-
-       return rc;
+       return nrs_register_policies_locked(nrs);
 }
 
 /**
index 2f45f765783040994c2271db210834092a02eeef..b51af9bf37b70cd5bdefa892875f3e21f504f620 100644 (file)
@@ -117,13 +117,13 @@ EXPORT_SYMBOL(lustre_msg_check_version);
 /* early reply size */
 int lustre_msg_early_size(void)
 {
-       static int size = 0;
+       static int size;
        if (!size) {
-               /* Always reply old ptlrpc_body_v2 to keep interoprability
+               /* Always reply old ptlrpc_body_v2 to keep interoperability
                 * with the old client (< 2.3) which doesn't have pb_jobid
                 * in the ptlrpc_body.
                 *
-                * XXX Remove this whenever we drop interoprability with such
+                * XXX Remove this whenever we drop interoperability with such
                 *     client.
                 */
                __u32 pblen = sizeof(struct ptlrpc_body_v2);
index 340d98a64137adc25291a7ae4242a4cbbd5836f9..9dbda9332dd828289c963cc49a64b8a07ac347c3 100644 (file)
@@ -545,7 +545,7 @@ void ptlrpc_pinger_wake_up(void)
 #define PET_READY     1
 #define PET_TERMINATE 2
 
-static int            pet_refcount = 0;
+static int pet_refcount;
 static int            pet_state;
 static wait_queue_head_t       pet_waitq;
 LIST_HEAD(pet_list);
index 7fe2e584ffd7d6c27667215c17be182a251da303..a66dc3c6da419d6fa80b06a19100a4bb83647557 100644 (file)
@@ -76,7 +76,7 @@ void ptlrpc_initiate_recovery(struct obd_import *imp);
 int lustre_unpack_req_ptlrpc_body(struct ptlrpc_request *req, int offset);
 int lustre_unpack_rep_ptlrpc_body(struct ptlrpc_request *req, int offset);
 
-#if defined (CONFIG_PROC_FS)
+#if defined(CONFIG_PROC_FS)
 void ptlrpc_lprocfs_register_service(struct proc_dir_entry *proc_entry,
                                     struct ptlrpc_service *svc);
 void ptlrpc_lprocfs_unregister_service(struct ptlrpc_service *svc);
@@ -263,7 +263,7 @@ void sptlrpc_enc_pool_fini(void);
 int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v);
 
 /* sec_lproc.c */
-#if defined (CONFIG_PROC_FS)
+#if defined(CONFIG_PROC_FS)
 int  sptlrpc_lproc_init(void);
 void sptlrpc_lproc_fini(void);
 #else
index 4621b71fe0b6bc971db94d2b32643faa09436f80..0c178ec0e48796756202b8acdd1188277b0dcf43 100644 (file)
@@ -85,7 +85,7 @@ MODULE_PARM_DESC(ptlrpcd_bind_policy, "Ptlrpcd threads binding mode.");
 static struct ptlrpcd *ptlrpcds;
 
 struct mutex ptlrpcd_mutex;
-static int ptlrpcd_users = 0;
+static int ptlrpcd_users;
 
 void ptlrpcd_wake(struct ptlrpc_request *req)
 {
@@ -511,10 +511,10 @@ static int ptlrpcd_bind(int index, int max)
 #if defined(CONFIG_NUMA)
        {
                int i;
-               mask = *cpumask_of_node(cpu_to_node(index));
+               cpumask_copy(&mask, cpumask_of_node(cpu_to_node(index)));
                for (i = max; i < num_online_cpus(); i++)
-                       cpu_clear(i, mask);
-               pc->pc_npartners = cpus_weight(mask) - 1;
+                       cpumask_clear_cpu(i, &mask);
+               pc->pc_npartners = cpumask_weight(&mask) - 1;
                set_bit(LIOD_BIND, &pc->pc_flags);
        }
 #else
@@ -554,7 +554,7 @@ static int ptlrpcd_bind(int index, int max)
                                 * that are already initialized
                                 */
                                for (pidx = 0, i = 0; i < index; i++) {
-                                       if (cpu_isset(i, mask)) {
+                                       if (cpumask_test_cpu(i, &mask)) {
                                                ppc = &ptlrpcds->pd_threads[i];
                                                pc->pc_partners[pidx++] = ppc;
                                                ppc->pc_partners[ppc->
index 0dabd83fd46ffbcf60a63ddf993c8e7936019420..c05a8554d737dcea467e945537299ce9a0ab4446 100644 (file)
@@ -125,52 +125,50 @@ static struct ptlrpc_enc_page_pool {
  */
 int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v)
 {
-       int     rc;
-
        spin_lock(&page_pools.epp_lock);
 
-       rc = seq_printf(m,
-                     "physical pages:    %lu\n"
-                     "pages per pool:    %lu\n"
-                     "max pages:              %lu\n"
-                     "max pools:              %u\n"
-                     "total pages:          %lu\n"
-                     "total free:            %lu\n"
-                     "idle index:            %lu/100\n"
-                     "last shrink:          %lds\n"
-                     "last access:          %lds\n"
-                     "max pages reached:       %lu\n"
-                     "grows:              %u\n"
-                     "grows failure:      %u\n"
-                     "shrinks:          %u\n"
-                     "cache access:        %lu\n"
-                     "cache missing:      %lu\n"
-                     "low free mark:      %lu\n"
-                     "max waitqueue depth:     %u\n"
-                     "max wait time:      "CFS_TIME_T"/%u\n"
-                     ,
-                     totalram_pages,
-                     PAGES_PER_POOL,
-                     page_pools.epp_max_pages,
-                     page_pools.epp_max_pools,
-                     page_pools.epp_total_pages,
-                     page_pools.epp_free_pages,
-                     page_pools.epp_idle_idx,
-                     get_seconds() - page_pools.epp_last_shrink,
-                     get_seconds() - page_pools.epp_last_access,
-                     page_pools.epp_st_max_pages,
-                     page_pools.epp_st_grows,
-                     page_pools.epp_st_grow_fails,
-                     page_pools.epp_st_shrinks,
-                     page_pools.epp_st_access,
-                     page_pools.epp_st_missings,
-                     page_pools.epp_st_lowfree,
-                     page_pools.epp_st_max_wqlen,
-                     page_pools.epp_st_max_wait, HZ
-                    );
+       seq_printf(m,
+                  "physical pages:       %lu\n"
+                  "pages per pool:       %lu\n"
+                  "max pages:         %lu\n"
+                  "max pools:         %u\n"
+                  "total pages:             %lu\n"
+                  "total free:       %lu\n"
+                  "idle index:       %lu/100\n"
+                  "last shrink:             %lds\n"
+                  "last access:             %lds\n"
+                  "max pages reached:       %lu\n"
+                  "grows:                 %u\n"
+                  "grows failure:         %u\n"
+                  "shrinks:             %u\n"
+                  "cache access:           %lu\n"
+                  "cache missing:         %lu\n"
+                  "low free mark:         %lu\n"
+                  "max waitqueue depth:     %u\n"
+                  "max wait time:         " CFS_TIME_T "/%u\n",
+                  totalram_pages,
+                  PAGES_PER_POOL,
+                  page_pools.epp_max_pages,
+                  page_pools.epp_max_pools,
+                  page_pools.epp_total_pages,
+                  page_pools.epp_free_pages,
+                  page_pools.epp_idle_idx,
+                  get_seconds() - page_pools.epp_last_shrink,
+                  get_seconds() - page_pools.epp_last_access,
+                  page_pools.epp_st_max_pages,
+                  page_pools.epp_st_grows,
+                  page_pools.epp_st_grow_fails,
+                  page_pools.epp_st_shrinks,
+                  page_pools.epp_st_access,
+                  page_pools.epp_st_missings,
+                  page_pools.epp_st_lowfree,
+                  page_pools.epp_st_max_wqlen,
+                  page_pools.epp_st_max_wait,
+                  HZ);
 
        spin_unlock(&page_pools.epp_lock);
-       return rc;
+
+       return 0;
 }
 
 static void enc_pools_release_free_pages(long npages)
@@ -365,8 +363,8 @@ static void enc_pools_insert(struct page ***pools, int npools, int npages)
         */
        cur_npools = (page_pools.epp_total_pages + PAGES_PER_POOL - 1) /
                     PAGES_PER_POOL;
-       end_npools = (page_pools.epp_total_pages + npages + PAGES_PER_POOL - 1) /
-                    PAGES_PER_POOL;
+       end_npools = (page_pools.epp_total_pages + npages + PAGES_PER_POOL - 1)
+                    PAGES_PER_POOL;
        LASSERT(end_npools <= page_pools.epp_max_pools);
 
        np_idx = 0;
@@ -816,9 +814,8 @@ int bulk_sec_desc_unpack(struct lustre_msg *msg, int offset, int swabbed)
                return -EINVAL;
        }
 
-       if (swabbed) {
+       if (swabbed)
                __swab32s(&bsd->bsd_nob);
-       }
 
        if (unlikely(bsd->bsd_version != 0)) {
                CERROR("Unexpected version %u\n", bsd->bsd_version);
index 635b12b22cef3623352810bae476fcfa4f0a4271..8e61421515cb689e205681257fe634f9baeb72bc 100644 (file)
@@ -543,7 +543,6 @@ ptlrpc_server_nthreads_check(struct ptlrpc_service *svc,
        if (tc->tc_thr_factor != 0) {
                int       factor = tc->tc_thr_factor;
                const int fade = 4;
-               cpumask_t mask;
 
                /*
                 * User wants to increase number of threads with for
@@ -557,8 +556,8 @@ ptlrpc_server_nthreads_check(struct ptlrpc_service *svc,
                 * have too many threads no matter how many cores/HTs
                 * there are.
                 */
-               cpumask_copy(&mask, topology_thread_cpumask(0));
-               if (cpus_weight(mask) > 1) { /* weight is # of HTs */
+               /* weight is # of HTs */
+               if (cpumask_weight(topology_thread_cpumask(0)) > 1) {
                        /* depress thread factor for hyper-thread */
                        factor = factor - (factor >> 1) + (factor >> 3);
                }
@@ -2752,7 +2751,6 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait)
 
 int ptlrpc_hr_init(void)
 {
-       cpumask_t                       mask;
        struct ptlrpc_hr_partition      *hrp;
        struct ptlrpc_hr_thread         *hrt;
        int                             rc;
@@ -2770,8 +2768,7 @@ int ptlrpc_hr_init(void)
 
        init_waitqueue_head(&ptlrpc_hr.hr_waitq);
 
-       cpumask_copy(&mask, topology_thread_cpumask(0));
-       weight = cpus_weight(mask);
+       weight = cpumask_weight(topology_thread_cpumask(0));
 
        cfs_percpt_for_each(hrp, i, ptlrpc_hr.hr_partitions) {
                hrp->hrp_cpt = i;
index 53825066791875d20f7b289cfaa56e1b79ba189d..f28ffef0d1f0caada0f02d5e2d6ed7ea07aea3bf 100644 (file)
@@ -1448,8 +1448,8 @@ static void bcm2048_parse_rds_pi(struct bcm2048_device *bdev)
                /* Block A match, only data without crc errors taken */
                if (bdev->rds_info.radio_text[i] == BCM2048_RDS_BLOCK_A) {
 
-                       pi = ((bdev->rds_info.radio_text[i+1] << 8) +
-                               bdev->rds_info.radio_text[i+2]);
+                       pi = (bdev->rds_info.radio_text[i+1] << 8) +
+                               bdev->rds_info.radio_text[i+2];
 
                        if (!bdev->rds_info.rds_pi) {
                                bdev->rds_info.rds_pi = pi;
@@ -1503,8 +1503,8 @@ static int bcm2048_parse_rt_match_b(struct bcm2048_device *bdev, int i)
        if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
                BCM2048_RDS_BLOCK_B) {
 
-               rt_id = (bdev->rds_info.radio_text[i+1] &
-                       BCM2048_RDS_BLOCK_MASK);
+               rt_id = bdev->rds_info.radio_text[i+1] &
+                       BCM2048_RDS_BLOCK_MASK;
                rt_group_b = bdev->rds_info.radio_text[i+1] &
                        BCM2048_RDS_GROUP_AB_MASK;
                rt_ab = bdev->rds_info.radio_text[i+2] &
@@ -1792,7 +1792,7 @@ static int bcm2048_get_rds_data(struct bcm2048_device *bdev, char *data)
                goto unlock;
        }
 
-       data_buffer = kzalloc(BCM2048_MAX_RDS_RADIO_TEXT*5, GFP_KERNEL);
+       data_buffer = kcalloc(BCM2048_MAX_RDS_RADIO_TEXT, 5, GFP_KERNEL);
        if (!data_buffer) {
                err = -ENOMEM;
                goto unlock;
@@ -2245,8 +2245,7 @@ static ssize_t bcm2048_fops_read(struct file *file, char __user *buf,
 
                tmpbuf[i] = bdev->rds_info.radio_text[bdev->rd_index+i+2];
                tmpbuf[i+1] = bdev->rds_info.radio_text[bdev->rd_index+i+1];
-               tmpbuf[i+2] = ((bdev->rds_info.radio_text[bdev->rd_index+i]
-                               & 0xf0) >> 4);
+               tmpbuf[i+2] = (bdev->rds_info.radio_text[bdev->rd_index + i] & 0xf0) >> 4;
                if ((bdev->rds_info.radio_text[bdev->rd_index+i] &
                        BCM2048_RDS_CRC_MASK) == BCM2048_RDS_CRC_UNRECOVARABLE)
                        tmpbuf[i+2] |= 0x80;
@@ -2718,22 +2717,7 @@ static struct i2c_driver bcm2048_i2c_driver = {
        .id_table       = bcm2048_id,
 };
 
-/*
- *     Module Interface
- */
-static int __init bcm2048_module_init(void)
-{
-       pr_info(BCM2048_DRIVER_DESC "\n");
-
-       return i2c_add_driver(&bcm2048_i2c_driver);
-}
-module_init(bcm2048_module_init);
-
-static void __exit bcm2048_module_exit(void)
-{
-       i2c_del_driver(&bcm2048_i2c_driver);
-}
-module_exit(bcm2048_module_exit);
+module_i2c_driver(bcm2048_i2c_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR(BCM2048_DRIVER_AUTHOR);
index 657ea480c6e7bed0944ea1502939860aaed589a6..692ba3e63e141dba87e8c612bbdae8bcc1f6aecc 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/i2c.h>
 #include <linux/wait.h>
 #include <linux/delay.h>
index 87d42e18377d5e3aa7a914594e7c5f02ff8faa22..17e105e7d892db8c02945f5db4c66926e0f0dbff 100644 (file)
@@ -209,10 +209,10 @@ static int ipipeif_hw_setup(struct v4l2_subdev *sd)
        /* Combine all the fields to make CFG1 register of IPIPEIF */
        tmp = val = get_oneshot_mode(ipipeif->input);
        if (tmp < 0) {
-               pr_err("ipipeif: links setup required");
+               dev_err(&sd->devnode->dev, "ipipeif: links setup required");
                return -EINVAL;
        }
-       val = val << ONESHOT_SHIFT;
+       val <<= ONESHOT_SHIFT;
 
        ipipeif_source = ipipeif_get_source(ipipeif);
        val |= ipipeif_source << INPSRC_SHIFT;
@@ -747,7 +747,6 @@ static void ipipeif_set_default_config(struct vpfe_ipipeif_device *ipipeif)
                        .clip = 4095,
                },
        };
-       memset(&ipipeif->config, 0, sizeof(struct ipipeif_params));
        memcpy(&ipipeif->config, &ipipeif_defaults,
               sizeof(struct ipipeif_params));
 }
index 75e70e14b7246dc38dd22942f1c1a443fc06ec6c..7cc8d1b4d737c4d03718862a0145568ec0a1a842 100644 (file)
@@ -907,7 +907,6 @@ resizer_set_defualt_configuration(struct vpfe_resizer_device *resizer)
                        .out_chr_pos = VPFE_IPIPE_YUV422_CHR_POS_COSITE,
                },
        };
-       memset(&resizer->config, 0, sizeof(struct resizer_params));
        memcpy(&resizer->config, &rsz_default_config,
               sizeof(struct resizer_params));
 }
index a350a20955f1a88c1e180d6ea125eee9896db496..57426199ad7af48203a349afe66eaa407db120bf 100644 (file)
@@ -226,8 +226,8 @@ static int vpfe_enable_clock(struct vpfe_device *vpfe_dev)
        if (!vpfe_cfg->num_clocks)
                return 0;
 
-       vpfe_dev->clks = kzalloc(vpfe_cfg->num_clocks *
-                                  sizeof(struct clock *), GFP_KERNEL);
+       vpfe_dev->clks = kcalloc(vpfe_cfg->num_clocks,
+                                sizeof(struct clock *), GFP_KERNEL);
        if (vpfe_dev->clks == NULL)
                return -ENOMEM;
 
@@ -346,7 +346,8 @@ static int register_i2c_devices(struct vpfe_device *vpfe_dev)
        i2c_adap = i2c_get_adapter(1);
        num_subdevs = vpfe_cfg->num_subdevs;
        vpfe_dev->sd =
-                 kzalloc(sizeof(struct v4l2_subdev *)*num_subdevs, GFP_KERNEL);
+                 kcalloc(num_subdevs, sizeof(struct v4l2_subdev *),
+                         GFP_KERNEL);
        if (vpfe_dev->sd == NULL)
                return -ENOMEM;
 
index 9ce7d9990e3e86981e7bd1bbd63b2ae0aae5a927..335b98a54237707c0d17823dc2cdac5b4dcec44d 100644 (file)
@@ -208,8 +208,7 @@ static void deregister_from_lirc(struct imon_context *context)
        retval = lirc_unregister_driver(minor);
        if (retval)
                dev_err(&context->usbdev->dev,
-                       ": %s: unable to deregister from lirc(%d)",
-                       __func__, retval);
+                       "unable to deregister from lirc(%d)", retval);
        else
                dev_info(&context->usbdev->dev,
                         "Deregistered iMON driver (minor:%d)\n", minor);
@@ -241,9 +240,8 @@ static int display_open(struct inode *inode, struct file *file)
        context = usb_get_intfdata(interface);
 
        if (!context) {
-               dev_err(&interface->dev,
-                       "%s: no context found for minor %d\n",
-                       __func__, subminor);
+               dev_err(&interface->dev, "no context found for minor %d\n",
+                       subminor);
                retval = -ENODEV;
                goto exit;
        }
@@ -339,13 +337,13 @@ static int send_packet(struct imon_context *context)
        context->tx_urb->actual_length = 0;
 
        init_completion(&context->tx.finished);
-       atomic_set(&(context->tx.busy), 1);
+       atomic_set(&context->tx.busy, 1);
 
        retval = usb_submit_urb(context->tx_urb, GFP_KERNEL);
        if (retval) {
-               atomic_set(&(context->tx.busy), 0);
-               dev_err(&context->usbdev->dev,
-                       "%s: error submitting urb(%d)\n", __func__, retval);
+               atomic_set(&context->tx.busy, 0);
+               dev_err(&context->usbdev->dev, "error submitting urb(%d)\n",
+                       retval);
        } else {
                /* Wait for transmission to complete (or abort) */
                mutex_unlock(&context->ctx_lock);
@@ -359,8 +357,7 @@ static int send_packet(struct imon_context *context)
                retval = context->tx.status;
                if (retval)
                        dev_err(&context->usbdev->dev,
-                               "%s: packet tx failed (%d)\n",
-                               __func__, retval);
+                               "packet tx failed (%d)\n", retval);
        }
 
        return retval;
@@ -437,8 +434,8 @@ static ssize_t vfd_write(struct file *file, const char __user *buf,
                retval = send_packet(context);
                if (retval) {
                        dev_err(&context->usbdev->dev,
-                               "%s: send packet failed for packet #%d\n",
-                               __func__, seq/2);
+                               "send packet failed for packet #%d\n",
+                               seq / 2);
                        goto exit;
                } else {
                        seq += 2;
@@ -454,8 +451,8 @@ static ssize_t vfd_write(struct file *file, const char __user *buf,
                retval = send_packet(context);
                if (retval)
                        dev_err(&context->usbdev->dev,
-                               "%s: send packet failed for packet #%d\n",
-                                       __func__, seq/2);
+                               "send packet failed for packet #%d\n",
+                               seq / 2);
        }
 
 exit:
@@ -877,8 +874,7 @@ static int imon_probe(struct usb_interface *interface,
        retval = usb_submit_urb(context->rx_urb, GFP_KERNEL);
 
        if (retval) {
-               dev_err(dev, "%s: usb_submit_urb failed for intf0 (%d)\n",
-                       __func__, retval);
+               dev_err(dev, "usb_submit_urb failed for intf0 (%d)\n", retval);
                alloc_status = 8;
                goto unlock;
        }
index 19c5c21babf557fed108abe5939e535fe45fceec..c1408342b1d0ebe35e35d5996a49ddec9f3c2828 100644 (file)
@@ -161,8 +161,8 @@ static unsigned int init_lirc_timer(void)
                             || (now.tv_sec == tv.tv_sec
                                 && now.tv_usec < tv.tv_usec)));
 
-       timeelapsed = ((now.tv_sec + 1 - tv.tv_sec)*1000000
-                    + (now.tv_usec - tv.tv_usec));
+       timeelapsed = (now.tv_sec + 1 - tv.tv_sec)*1000000
+                    + (now.tv_usec - tv.tv_usec);
        if (count >= 1000 && timeelapsed > 0) {
                if (default_timer == 0) {
                        /* autodetect timer */
@@ -336,7 +336,7 @@ static ssize_t lirc_read(struct file *filep, char __user *buf, size_t n,
        set_current_state(TASK_INTERRUPTIBLE);
        while (count < n) {
                if (rptr != wptr) {
-                       if (copy_to_user(buf+count, (char *) &rbuf[rptr],
+                       if (copy_to_user(buf+count, &rbuf[rptr],
                                         sizeof(int))) {
                                result = -EFAULT;
                                break;
index 4a268200cbf55ce8d5d2cf3633697fc8fdaa8647..9e5674341abe7368e5ec228f737e4c2d766f7d80 100644 (file)
@@ -170,9 +170,6 @@ static void delete_context(struct sasem_context *context)
        kfree(context->driver->rbuf);
        kfree(context->driver);
        kfree(context);
-
-       if (debug)
-               pr_info("%s: context deleted\n", __func__);
 }
 
 static void deregister_from_lirc(struct sasem_context *context)
@@ -182,10 +179,12 @@ static void deregister_from_lirc(struct sasem_context *context)
 
        retval = lirc_unregister_driver(minor);
        if (retval)
-               pr_err("%s: unable to deregister from lirc (%d)\n",
+               dev_err(&context->dev->dev,
+                       "%s: unable to deregister from lirc (%d)\n",
                       __func__, retval);
        else
-               pr_info("Deregistered Sasem driver (minor:%d)\n", minor);
+               dev_info(&context->dev->dev,
+                        "Deregistered Sasem driver (minor:%d)\n", minor);
 
 }
 
@@ -214,9 +213,8 @@ static int vfd_open(struct inode *inode, struct file *file)
        context = usb_get_intfdata(interface);
 
        if (!context) {
-               dev_err(&interface->dev,
-                       "%s: no context found for minor %d\n",
-                       __func__, subminor);
+               dev_err(&interface->dev, "no context found for minor %d\n",
+                       subminor);
                retval = -ENODEV;
                goto exit;
        }
@@ -332,13 +330,13 @@ static int send_packet(struct sasem_context *context)
        context->tx_urb->actual_length = 0;
 
        init_completion(&context->tx.finished);
-       atomic_set(&(context->tx.busy), 1);
+       atomic_set(&context->tx.busy, 1);
 
        retval =  usb_submit_urb(context->tx_urb, GFP_KERNEL);
        if (retval) {
-               atomic_set(&(context->tx.busy), 0);
-               dev_err(&context->dev->dev, "%s: error submitting urb (%d)\n",
-                       __func__, retval);
+               atomic_set(&context->tx.busy, 0);
+               dev_err(&context->dev->dev, "error submitting urb (%d)\n",
+                       retval);
        } else {
                /* Wait for transmission to complete (or abort) */
                mutex_unlock(&context->ctx_lock);
@@ -348,8 +346,7 @@ static int send_packet(struct sasem_context *context)
                retval = context->tx.status;
                if (retval)
                        dev_err(&context->dev->dev,
-                               "%s: packet tx failed (%d)\n",
-                               __func__, retval);
+                               "packet tx failed (%d)\n", retval);
        }
 
        return retval;
@@ -389,7 +386,7 @@ static ssize_t vfd_write(struct file *file, const char __user *buf,
                goto exit;
        }
 
-       data_buf = memdup_user((void const __user *)buf, n_bytes);
+       data_buf = memdup_user(buf, n_bytes);
        if (IS_ERR(data_buf)) {
                retval = PTR_ERR(data_buf);
                data_buf = NULL;
@@ -444,8 +441,7 @@ static ssize_t vfd_write(struct file *file, const char __user *buf,
                retval = send_packet(context);
                if (retval) {
                        dev_err(&context->dev->dev,
-                               "%s: send packet failed for packet #%d\n",
-                               __func__, i);
+                               "send packet failed for packet #%d\n", i);
                        goto exit;
                }
        }
@@ -509,8 +505,7 @@ static int ir_open(void *data)
 
        if (retval)
                dev_err(&context->dev->dev,
-                       "%s: usb_submit_urb failed for ir_open (%d)\n",
-                       __func__, retval);
+                       "usb_submit_urb failed for ir_open (%d)\n", retval);
        else {
                context->ir_isopen = 1;
                dev_info(&context->dev->dev, "IR port opened\n");
index 19628d0104ab88a8408182b837376f985b2fce2f..dc7984455c3a7a051ea8db668c2fbeb9f64b43f3 100644 (file)
@@ -344,7 +344,7 @@ static int init_timing_params(unsigned int new_duty_cycle,
        /* How many clocks in a microsecond?, avoiding long long divide */
        work = loops_per_sec;
        work *= 4295;  /* 4295 = 2^32 / 1e6 */
-       conv_us_to_clocks = (work >> 32);
+       conv_us_to_clocks = work >> 32;
 
        /*
         * Carrier period in clocks, approach good up to 32GHz clock,
@@ -784,7 +784,7 @@ static int lirc_serial_probe(struct platform_device *dev)
 
        result = devm_request_irq(&dev->dev, irq, lirc_irq_handler,
                             (share_irq ? IRQF_SHARED : 0),
-                            LIRC_DRIVER_NAME, (void *)&hardware);
+                            LIRC_DRIVER_NAME, &hardware);
        if (result < 0) {
                if (result == -EBUSY)
                        dev_err(&dev->dev, "IRQ %d busy\n", irq);
@@ -838,7 +838,7 @@ static int lirc_serial_probe(struct platform_device *dev)
                                nhigh++;
                        msleep(40);
                }
-               sense = (nlow >= nhigh ? 1 : 0);
+               sense = nlow >= nhigh ? 1 : 0;
                dev_info(&dev->dev, "auto-detected active %s receiver\n",
                         sense ? "low" : "high");
        } else
index 39f4733fb1ee25fea623120441d989c6624bc235..29087f66e2f40126f608babc0d4e36f568987643 100644 (file)
@@ -683,9 +683,7 @@ static int init_port(void)
        }
        pr_info("I/O port 0x%.4x, IRQ %d.\n", io, irq);
 
-       init_timer(&timerlist);
-       timerlist.function = sir_timeout;
-       timerlist.data = 0xabadcafe;
+       setup_timer(&timerlist, sir_timeout, 0);
 
        return 0;
 }
index e16627ca488e654011a00e38fe84d5d36019c9ce..261e27d6b054c183c9886eb752fdee57111d7c42 100644 (file)
@@ -1341,8 +1341,7 @@ static int close(struct inode *node, struct file *filep)
        struct IR *ir = filep->private_data;
 
        if (ir == NULL) {
-               dev_err(ir->l.dev,
-                       "close: no private_data attached to the file!\n");
+               pr_err("ir: close: no private_data attached to the file!\n");
                return -ENODEV;
        }
 
index 6eebe564e5573e6187d30777f247f084f8421eba..2a68582e7f71abc9d5c658147e1add98925d1384 100644 (file)
@@ -276,7 +276,7 @@ static int mn88472_init(struct dvb_frontend *fe)
                        remaining -= (dev->i2c_wr_max - 1)) {
                len = remaining;
                if (len > (dev->i2c_wr_max - 1))
-                       len = (dev->i2c_wr_max - 1);
+                       len = dev->i2c_wr_max - 1;
 
                ret = regmap_bulk_write(dev->regmap[0], 0xf6,
                                &fw->data[fw->size - remaining], len);
index a333744b76b958df4cfc7fb002696548f0709b90..5baeb03ab3d12d220db8f97b23d72e29b0575b3b 100644 (file)
@@ -17,7 +17,7 @@
 #include "mn88473_priv.h"
 
 static int mn88473_get_tune_settings(struct dvb_frontend *fe,
-       struct dvb_frontend_tune_settings *s)
+                                    struct dvb_frontend_tune_settings *s)
 {
        s->min_delay_ms = 1000;
        return 0;
@@ -33,10 +33,14 @@ static int mn88473_set_frontend(struct dvb_frontend *fe)
        u8 delivery_system_val, if_val[3], bw_val[7];
 
        dev_dbg(&client->dev,
-                       "delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%d stream_id=%d\n",
-                       c->delivery_system, c->modulation,
-                       c->frequency, c->bandwidth_hz, c->symbol_rate,
-                       c->inversion, c->stream_id);
+               "delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%d stream_id=%d\n",
+               c->delivery_system,
+               c->modulation,
+               c->frequency,
+               c->bandwidth_hz,
+               c->symbol_rate,
+               c->inversion,
+               c->stream_id);
 
        if (!dev->warm) {
                ret = -EAGAIN;
@@ -112,7 +116,7 @@ static int mn88473_set_frontend(struct dvb_frontend *fe)
                break;
        default:
                dev_err(&client->dev, "IF frequency %d not supported\n",
-                               if_frequency);
+                       if_frequency);
                ret = -EINVAL;
                goto err;
        }
@@ -229,7 +233,7 @@ static int mn88473_init(struct dvb_frontend *fe)
        }
 
        dev_info(&client->dev, "downloading firmware from file '%s'\n",
-                       fw_file);
+                fw_file);
 
        ret = regmap_write(dev->regmap[0], 0xf5, 0x03);
        if (ret)
@@ -239,13 +243,13 @@ static int mn88473_init(struct dvb_frontend *fe)
                        remaining -= (dev->i2c_wr_max - 1)) {
                len = remaining;
                if (len > (dev->i2c_wr_max - 1))
-                       len = (dev->i2c_wr_max - 1);
+                       len = dev->i2c_wr_max - 1;
 
                ret = regmap_bulk_write(dev->regmap[0], 0xf6,
-                               &fw->data[fw->size - remaining], len);
+                                       &fw->data[fw->size - remaining], len);
                if (ret) {
                        dev_err(&client->dev, "firmware download failed=%d\n",
-                                       ret);
+                               ret);
                        goto err;
                }
        }
@@ -325,7 +329,7 @@ static struct dvb_frontend_ops mn88473_ops = {
 };
 
 static int mn88473_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
+                        const struct i2c_device_id *id)
 {
        struct mn88473_config *config = client->dev.platform_data;
        struct mn88473_dev *dev;
index 44b81a2c8b6f651a09d49c0c4da16019a52eabce..e0ad5e520e2d26705f43d1862de128ea428f20a6 100644 (file)
@@ -1160,8 +1160,8 @@ iss_register_subdev_group(struct iss_device *iss,
                subdev = v4l2_i2c_new_subdev_board(&iss->v4l2_dev, adapter,
                                board_info->board_info, NULL);
                if (subdev == NULL) {
-                       dev_err(iss->dev, "%s: Unable to register subdev %s\n",
-                               __func__, board_info->board_info->type);
+                       dev_err(iss->dev, "Unable to register subdev %s\n",
+                               board_info->board_info->type);
                        continue;
                }
 
@@ -1185,16 +1185,16 @@ static int iss_register_entities(struct iss_device *iss)
        iss->media_dev.link_notify = iss_pipeline_link_notify;
        ret = media_device_register(&iss->media_dev);
        if (ret < 0) {
-               dev_err(iss->dev, "%s: Media device registration failed (%d)\n",
-                       __func__, ret);
+               dev_err(iss->dev, "Media device registration failed (%d)\n",
+                       ret);
                return ret;
        }
 
        iss->v4l2_dev.mdev = &iss->media_dev;
        ret = v4l2_device_register(iss->dev, &iss->v4l2_dev);
        if (ret < 0) {
-               dev_err(iss->dev, "%s: V4L2 device registration failed (%d)\n",
-                       __func__, ret);
+               dev_err(iss->dev, "V4L2 device registration failed (%d)\n",
+                       ret);
                goto done;
        }
 
@@ -1252,8 +1252,8 @@ static int iss_register_entities(struct iss_device *iss)
                        break;
 
                default:
-                       dev_err(iss->dev, "%s: invalid interface type %u\n",
-                               __func__, subdevs->interface);
+                       dev_err(iss->dev, "invalid interface type %u\n",
+                               subdevs->interface);
                        ret = -EINVAL;
                        goto done;
                }
index 69550445a341ff6f39a571a9c72c37ecab435a04..55938cccde7f0114c395e03e8d39ddc060a9de56 100644 (file)
@@ -1221,8 +1221,7 @@ int omap4iss_video_register(struct iss_video *video, struct v4l2_device *vdev)
        ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1);
        if (ret < 0)
                dev_err(video->iss->dev,
-                       "%s: could not register video device (%d)\n",
-                       __func__, ret);
+                       "could not register video device (%d)\n", ret);
 
        return ret;
 }
index 3b191fce45ec912d318c45892db0bdd09443ab20..7285c64bac240099743f4427d9aa50e9a4dd77c4 100644 (file)
@@ -770,7 +770,7 @@ static void spinand_cmdfunc(struct mtd_info *mtd, unsigned int command,
                break;
        case NAND_CMD_READID:
                state->buf_ptr = 0;
-               spinand_read_id(info->spi, (u8 *)state->buf);
+               spinand_read_id(info->spi, state->buf);
                break;
        case NAND_CMD_PARAM:
                state->buf_ptr = 0;
index e8aae09d16242b9fe08fc0ddec58372a67d9709d..8ae01753b011a39cd015f9e050eebd3f9cbc17ef 100644 (file)
@@ -1012,7 +1012,7 @@ static int xlr_net_probe(struct platform_device *pdev)
         * Allocate our adapter data structure and attach it to the device.
         */
        adapter = (struct xlr_adapter *)
-               devm_kzalloc(&pdev->dev, sizeof(adapter), GFP_KERNEL);
+               devm_kzalloc(&pdev->dev, sizeof(*adapter), GFP_KERNEL);
        if (!adapter) {
                err = -ENOMEM;
                return err;
index 9475e20c3d646f85c2e1d164aaf4c8c3dbe84c63..e3a89fb1a4a2547f77c5ea469b06bf76e1e76e57 100644 (file)
@@ -6,6 +6,9 @@ config MFD_NVEC
            Say Y here to enable support for a nVidia compliant embedded
            controller.
 
+           To compile this driver as a module, say M here: the module will be
+            called mfd-nvec
+
 config KEYBOARD_NVEC
        tristate "Keyboard on nVidia compliant EC"
        depends on MFD_NVEC && INPUT
@@ -13,6 +16,9 @@ config KEYBOARD_NVEC
          Say Y here to enable support for a keyboard connected to
          a nVidia compliant embedded controller.
 
+         To compile this driver as a module, say M here: the module will be
+          called keyboard-nvec
+
 config SERIO_NVEC_PS2
        tristate "PS2 on nVidia EC"
        depends on MFD_NVEC && SERIO
@@ -20,6 +26,10 @@ config SERIO_NVEC_PS2
          Say Y here to enable support for a Touchpad / Mouse connected
          to a nVidia compliant embedded controller.
 
+         To compile this driver as a module, say M here: the module will be
+          called serio-nvec-ps2
+
+
 config NVEC_POWER
        tristate "NVEC charger and battery"
        depends on MFD_NVEC && POWER_SUPPLY
@@ -27,9 +37,17 @@ config NVEC_POWER
          Say Y to enable support for battery and charger interface for
          nVidia compliant embedded controllers.
 
+         To compile this driver as a module, say M here: the module will be
+          called nvec-power
+
+
 config NVEC_PAZ00
        tristate "Support for OEM specific functions on Compal PAZ00 based devices"
        depends on MFD_NVEC && LEDS_CLASS
        help
          Say Y to enable control of the yellow side leds on Compal PAZ00 based
          devices, e.g. Toshbia AC100 and Dynabooks AZ netbooks.
+
+         To compile this driver as a module, say M here: the module will be
+          called nvec-paz00
+
index 5868ebb8389e54948f3e1efde3449343d8e320ce..1bdc8d001e65da929f6e797cf494b282f7f2f66b 100644 (file)
@@ -803,7 +803,7 @@ static int tegra_nvec_probe(struct platform_device *pdev)
        }
 
        nvec = devm_kzalloc(&pdev->dev, sizeof(struct nvec_chip), GFP_KERNEL);
-       if (nvec == NULL)
+       if (!nvec)
                return -ENOMEM;
 
        platform_set_drvdata(pdev, nvec);
index f0cea0e43c96bb21b8bc9137d42bb38e27a036fb..68146bfee2b34ec01d0dfb88db1bd44fa6a85eab 100644 (file)
@@ -51,7 +51,7 @@ static int nvec_paz00_probe(struct platform_device *pdev)
        int ret = 0;
 
        led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
-       if (led == NULL)
+       if (!led)
                return -ENOMEM;
 
        led->cdev.max_brightness = NVEC_LED_MAX;
index 6a1459d4f8fbab1da3d1203c2f727ada62131e4c..04a7402ae2df4531fee978a24c1fc82e3e712095 100644 (file)
@@ -82,8 +82,8 @@ struct bat_response {
        };
 };
 
-static struct power_supply nvec_bat_psy;
-static struct power_supply nvec_psy;
+static struct power_supply *nvec_bat_psy;
+static struct power_supply *nvec_psy;
 
 static int nvec_power_notifier(struct notifier_block *nb,
                               unsigned long event_type, void *data)
@@ -98,7 +98,7 @@ static int nvec_power_notifier(struct notifier_block *nb,
        if (res->sub_type == 0) {
                if (power->on != res->plu) {
                        power->on = res->plu;
-                       power_supply_changed(&nvec_psy);
+                       power_supply_changed(nvec_psy);
                }
                return NOTIFY_STOP;
        }
@@ -167,7 +167,7 @@ static int nvec_power_bat_notifier(struct notifier_block *nb,
                }
                power->bat_cap = res->plc[1];
                if (status_changed)
-                       power_supply_changed(&nvec_bat_psy);
+                       power_supply_changed(nvec_bat_psy);
                break;
        case VOLTAGE:
                power->bat_voltage_now = res->plu * 1000;
@@ -225,7 +225,7 @@ static int nvec_power_get_property(struct power_supply *psy,
                                   enum power_supply_property psp,
                                   union power_supply_propval *val)
 {
-       struct nvec_power *power = dev_get_drvdata(psy->dev->parent);
+       struct nvec_power *power = dev_get_drvdata(psy->dev.parent);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_ONLINE:
@@ -241,7 +241,7 @@ static int nvec_battery_get_property(struct power_supply *psy,
                                     enum power_supply_property psp,
                                     union power_supply_propval *val)
 {
-       struct nvec_power *power = dev_get_drvdata(psy->dev->parent);
+       struct nvec_power *power = dev_get_drvdata(psy->dev.parent);
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
@@ -323,7 +323,7 @@ static char *nvec_power_supplied_to[] = {
        "battery",
 };
 
-static struct power_supply nvec_bat_psy = {
+static const struct power_supply_desc nvec_bat_psy_desc = {
        .name = "battery",
        .type = POWER_SUPPLY_TYPE_BATTERY,
        .properties = nvec_battery_props,
@@ -331,11 +331,9 @@ static struct power_supply nvec_bat_psy = {
        .get_property = nvec_battery_get_property,
 };
 
-static struct power_supply nvec_psy = {
+static const struct power_supply_desc nvec_psy_desc = {
        .name = "ac",
        .type = POWER_SUPPLY_TYPE_MAINS,
-       .supplied_to = nvec_power_supplied_to,
-       .num_supplicants = ARRAY_SIZE(nvec_power_supplied_to),
        .properties = nvec_power_props,
        .num_properties = ARRAY_SIZE(nvec_power_props),
        .get_property = nvec_power_get_property,
@@ -373,12 +371,14 @@ static void nvec_power_poll(struct work_struct *work)
 
 static int nvec_power_probe(struct platform_device *pdev)
 {
-       struct power_supply *psy;
+       struct power_supply **psy;
+       const struct power_supply_desc *psy_desc;
        struct nvec_power *power;
        struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
+       struct power_supply_config psy_cfg = {};
 
        power = devm_kzalloc(&pdev->dev, sizeof(struct nvec_power), GFP_NOWAIT);
-       if (power == NULL)
+       if (!power)
                return -ENOMEM;
 
        dev_set_drvdata(&pdev->dev, power);
@@ -387,6 +387,9 @@ static int nvec_power_probe(struct platform_device *pdev)
        switch (pdev->id) {
        case AC:
                psy = &nvec_psy;
+               psy_desc = &nvec_psy_desc;
+               psy_cfg.supplied_to = nvec_power_supplied_to;
+               psy_cfg.num_supplicants = ARRAY_SIZE(nvec_power_supplied_to);
 
                power->notifier.notifier_call = nvec_power_notifier;
 
@@ -395,6 +398,7 @@ static int nvec_power_probe(struct platform_device *pdev)
                break;
        case BAT:
                psy = &nvec_bat_psy;
+               psy_desc = &nvec_bat_psy_desc;
 
                power->notifier.notifier_call = nvec_power_bat_notifier;
                break;
@@ -407,7 +411,9 @@ static int nvec_power_probe(struct platform_device *pdev)
        if (pdev->id == BAT)
                get_bat_mfg_data(power);
 
-       return power_supply_register(&pdev->dev, psy);
+       *psy = power_supply_register(&pdev->dev, psy_desc, &psy_cfg);
+
+       return PTR_ERR_OR_ZERO(*psy);
 }
 
 static int nvec_power_remove(struct platform_device *pdev)
@@ -418,10 +424,10 @@ static int nvec_power_remove(struct platform_device *pdev)
        nvec_unregister_notifier(power->nvec, &power->notifier);
        switch (pdev->id) {
        case AC:
-               power_supply_unregister(&nvec_psy);
+               power_supply_unregister(nvec_psy);
                break;
        case BAT:
-               power_supply_unregister(&nvec_bat_psy);
+               power_supply_unregister(nvec_bat_psy);
        }
 
        return 0;
index 4fd63c239454ce5fda1499262a50e3812c3cfdd3..6ebbc82323c3f75f751d95b6bcfcebf935ca8357 100644 (file)
@@ -109,7 +109,7 @@ static int nvec_mouse_probe(struct platform_device *pdev)
        char mouse_reset[] = { NVEC_PS2, SEND_COMMAND, PSMOUSE_RST, 3 };
 
        ser_dev = devm_kzalloc(&pdev->dev, sizeof(struct serio), GFP_KERNEL);
-       if (ser_dev == NULL)
+       if (!ser_dev)
                return -ENOMEM;
 
        ser_dev->id.type = SERIO_PS_PSTHRU;
index 1daeb3125a1ff979662fc317b8ac0d303c0368e5..9e5476e352b4b3ca3c0f8175883324c769c7a664 100644 (file)
@@ -214,15 +214,14 @@ enum cvmx_usb_initialize_flags {
 /**
  * enum cvmx_usb_pipe_flags - internal flags for a pipe.
  *
- * @__CVMX_USB_PIPE_FLAGS_SCHEDULED: Used internally to determine if a pipe is
- *                                  actively using hardware. Do not use.
- * @__CVMX_USB_PIPE_FLAGS_NEED_PING: Used internally to determine if a high
- *                                  speed pipe is in the ping state. Do not
- *                                  use.
+ * @CVMX_USB_PIPE_FLAGS_SCHEDULED: Used internally to determine if a pipe is
+ *                                actively using hardware.
+ * @CVMX_USB_PIPE_FLAGS_NEED_PING: Used internally to determine if a high speed
+ *                                pipe is in the ping state.
  */
 enum cvmx_usb_pipe_flags {
-       __CVMX_USB_PIPE_FLAGS_SCHEDULED = 1 << 17,
-       __CVMX_USB_PIPE_FLAGS_NEED_PING = 1 << 18,
+       CVMX_USB_PIPE_FLAGS_SCHEDULED   = 1 << 17,
+       CVMX_USB_PIPE_FLAGS_NEED_PING   = 1 << 18,
 };
 
 /* Maximum number of times to retry failed transactions */
@@ -231,15 +230,6 @@ enum cvmx_usb_pipe_flags {
 /* Maximum number of hardware channels supported by the USB block */
 #define MAX_CHANNELS           8
 
-/* The highest valid USB device address */
-#define MAX_USB_ADDRESS                127
-
-/* The highest valid USB endpoint number */
-#define MAX_USB_ENDPOINT       15
-
-/* The highest valid port number on a hub */
-#define MAX_USB_HUB_PORT       15
-
 /*
  * The low level hardware can transfer a maximum of this number of bytes in each
  * transfer. The field is 19 bits wide
@@ -403,16 +393,18 @@ struct octeon_hcd {
        struct cvmx_usb_state usb;
 };
 
-/* This macro spins on a field waiting for it to reach a value */
-#define CVMX_WAIT_FOR_FIELD32(address, type, field, op, value, timeout_usec)\
+/* This macro spins on a register waiting for it to reach a condition. */
+#define CVMX_WAIT_FOR_FIELD32(address, _union, cond, timeout_usec)         \
        ({int result;                                                       \
        do {                                                                \
                uint64_t done = cvmx_get_cycle() + (uint64_t)timeout_usec * \
                        octeon_get_clock_rate() / 1000000;                  \
-               type c;                                                     \
+               union _union c;                                             \
+                                                                           \
                while (1) {                                                 \
-                       c.u32 = __cvmx_usb_read_csr32(usb, address);        \
-                       if (c.s.field op (value)) {                         \
+                       c.u32 = cvmx_usb_read_csr32(usb, address);          \
+                                                                           \
+                       if (cond) {                                         \
                                result = 0;                                 \
                                break;                                      \
                        } else if (cvmx_get_cycle() > done) {               \
@@ -428,12 +420,13 @@ struct octeon_hcd {
  * This macro logically sets a single field in a CSR. It does the sequence
  * read, modify, and write
  */
-#define USB_SET_FIELD32(address, type, field, value)           \
+#define USB_SET_FIELD32(address, _union, field, value)         \
        do {                                                    \
-               type c;                                         \
-               c.u32 = __cvmx_usb_read_csr32(usb, address);    \
+               union _union c;                                 \
+                                                               \
+               c.u32 = cvmx_usb_read_csr32(usb, address);      \
                c.s.field = value;                              \
-               __cvmx_usb_write_csr32(usb, address, c.u32);    \
+               cvmx_usb_write_csr32(usb, address, c.u32);      \
        } while (0)
 
 /* Returns the IO address to push/pop stuff data from the FIFOs */
@@ -442,7 +435,6 @@ struct octeon_hcd {
 
 /**
  * struct octeon_temp_buffer - a bounce buffer for USB transfers
- * @temp_buffer: the newly allocated temporary buffer (including meta-data)
  * @orig_buffer: the original buffer passed by the USB stack
  * @data:       the newly allocated temporary buffer (excluding meta-data)
  *
@@ -451,7 +443,6 @@ struct octeon_hcd {
  * represents it.
  */
 struct octeon_temp_buffer {
-       void *temp_buffer;
        void *orig_buffer;
        u8 data[0];
 };
@@ -489,7 +480,6 @@ static int octeon_alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
        if (!temp)
                return -ENOMEM;
 
-       temp->temp_buffer = temp;
        temp->orig_buffer = urb->transfer_buffer;
        if (usb_urb_dir_out(urb))
                memcpy(temp->data, urb->transfer_buffer,
@@ -520,7 +510,7 @@ static void octeon_free_temp_buffer(struct urb *urb)
                       urb->actual_length);
        urb->transfer_buffer = temp->orig_buffer;
        urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
-       kfree(temp->temp_buffer);
+       kfree(temp);
 }
 
 /**
@@ -566,8 +556,8 @@ static void octeon_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
  *
  * Returns: Result of the read
  */
-static inline uint32_t __cvmx_usb_read_csr32(struct cvmx_usb_state *usb,
-                                            uint64_t address)
+static inline uint32_t cvmx_usb_read_csr32(struct cvmx_usb_state *usb,
+                                          uint64_t address)
 {
        uint32_t result = cvmx_read64_uint32(address ^ 4);
        return result;
@@ -583,45 +573,13 @@ static inline uint32_t __cvmx_usb_read_csr32(struct cvmx_usb_state *usb,
  * @address: 64bit address to write
  * @value:   Value to write
  */
-static inline void __cvmx_usb_write_csr32(struct cvmx_usb_state *usb,
-                                         uint64_t address, uint32_t value)
+static inline void cvmx_usb_write_csr32(struct cvmx_usb_state *usb,
+                                       uint64_t address, uint32_t value)
 {
        cvmx_write64_uint32(address ^ 4, value);
        cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
 }
 
-
-/**
- * Read a USB 64bit CSR. It logs the value in a readable format if
- * debugging is on.
- *
- * @usb:     USB block this access is for
- * @address: 64bit address to read
- *
- * Returns: Result of the read
- */
-static inline uint64_t __cvmx_usb_read_csr64(struct cvmx_usb_state *usb,
-                                            uint64_t address)
-{
-       uint64_t result = cvmx_read64_uint64(address);
-       return result;
-}
-
-
-/**
- * Write a USB 64bit CSR. It logs the value in a readable format
- * if debugging is on.
- *
- * @usb:     USB block this access is for
- * @address: 64bit address to write
- * @value:   Value to write
- */
-static inline void __cvmx_usb_write_csr64(struct cvmx_usb_state *usb,
-                                         uint64_t address, uint64_t value)
-{
-       cvmx_write64_uint64(address, value);
-}
-
 /**
  * Return non zero if this pipe connects to a non HIGH speed
  * device through a high speed hub.
@@ -631,8 +589,8 @@ static inline void __cvmx_usb_write_csr64(struct cvmx_usb_state *usb,
  *
  * Returns: Non zero if we need to do split transactions
  */
-static inline int __cvmx_usb_pipe_needs_split(struct cvmx_usb_state *usb,
-                                             struct cvmx_usb_pipe *pipe)
+static inline int cvmx_usb_pipe_needs_split(struct cvmx_usb_state *usb,
+                                           struct cvmx_usb_pipe *pipe)
 {
        return pipe->device_speed != CVMX_USB_SPEED_HIGH &&
               usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_HIGH;
@@ -646,48 +604,119 @@ static inline int __cvmx_usb_pipe_needs_split(struct cvmx_usb_state *usb,
  *
  * Returns: PID for pipe
  */
-static inline int __cvmx_usb_get_data_pid(struct cvmx_usb_pipe *pipe)
+static inline int cvmx_usb_get_data_pid(struct cvmx_usb_pipe *pipe)
 {
        if (pipe->pid_toggle)
                return 2; /* Data1 */
        return 0; /* Data0 */
 }
 
+static void cvmx_fifo_setup(struct cvmx_usb_state *usb)
+{
+       union cvmx_usbcx_ghwcfg3 usbcx_ghwcfg3;
+       union cvmx_usbcx_gnptxfsiz npsiz;
+       union cvmx_usbcx_hptxfsiz psiz;
+
+       usbcx_ghwcfg3.u32 = cvmx_usb_read_csr32(usb,
+                                               CVMX_USBCX_GHWCFG3(usb->index));
+
+       /*
+        * Program the USBC_GRXFSIZ register to select the size of the receive
+        * FIFO (25%).
+        */
+       USB_SET_FIELD32(CVMX_USBCX_GRXFSIZ(usb->index), cvmx_usbcx_grxfsiz,
+                       rxfdep, usbcx_ghwcfg3.s.dfifodepth / 4);
+
+       /*
+        * Program the USBC_GNPTXFSIZ register to select the size and the start
+        * address of the non-periodic transmit FIFO for nonperiodic
+        * transactions (50%).
+        */
+       npsiz.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index));
+       npsiz.s.nptxfdep = usbcx_ghwcfg3.s.dfifodepth / 2;
+       npsiz.s.nptxfstaddr = usbcx_ghwcfg3.s.dfifodepth / 4;
+       cvmx_usb_write_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index), npsiz.u32);
+
+       /*
+        * Program the USBC_HPTXFSIZ register to select the size and start
+        * address of the periodic transmit FIFO for periodic transactions
+        * (25%).
+        */
+       psiz.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index));
+       psiz.s.ptxfsize = usbcx_ghwcfg3.s.dfifodepth / 4;
+       psiz.s.ptxfstaddr = 3 * usbcx_ghwcfg3.s.dfifodepth / 4;
+       cvmx_usb_write_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index), psiz.u32);
+
+       /* Flush all FIFOs */
+       USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index),
+                       cvmx_usbcx_grstctl, txfnum, 0x10);
+       USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index),
+                       cvmx_usbcx_grstctl, txfflsh, 1);
+       CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index),
+                             cvmx_usbcx_grstctl, c.s.txfflsh == 0, 100);
+       USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index),
+                       cvmx_usbcx_grstctl, rxfflsh, 1);
+       CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index),
+                             cvmx_usbcx_grstctl, c.s.rxfflsh == 0, 100);
+}
+
+/**
+ * Shutdown a USB port after a call to cvmx_usb_initialize().
+ * The port should be disabled with all pipes closed when this
+ * function is called.
+ *
+ * @usb: USB device state populated by cvmx_usb_initialize().
+ *
+ * Returns: 0 or a negative error code.
+ */
+static int cvmx_usb_shutdown(struct cvmx_usb_state *usb)
+{
+       union cvmx_usbnx_clk_ctl usbn_clk_ctl;
+
+       /* Make sure all pipes are closed */
+       if (!list_empty(&usb->idle_pipes) ||
+           !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_ISOCHRONOUS]) ||
+           !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT]) ||
+           !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_CONTROL]) ||
+           !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_BULK]))
+               return -EBUSY;
+
+       /* Disable the clocks and put them in power on reset */
+       usbn_clk_ctl.u64 = cvmx_read64_uint64(CVMX_USBNX_CLK_CTL(usb->index));
+       usbn_clk_ctl.s.enable = 1;
+       usbn_clk_ctl.s.por = 1;
+       usbn_clk_ctl.s.hclk_rst = 1;
+       usbn_clk_ctl.s.prst = 0;
+       usbn_clk_ctl.s.hrst = 0;
+       cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
+       return 0;
+}
+
 /**
  * Initialize a USB port for use. This must be called before any
  * other access to the Octeon USB port is made. The port starts
  * off in the disabled state.
  *
- * @usb:        Pointer to an empty struct cvmx_usb_state
- *              that will be populated by the initialize call.
- *              This structure is then passed to all other USB
- *              functions.
- * @usb_port_number:
- *              Which Octeon USB port to initialize.
+ * @dev:        Pointer to struct device for logging purposes.
+ * @usb:        Pointer to struct cvmx_usb_state.
  *
  * Returns: 0 or a negative error code.
  */
-static int cvmx_usb_initialize(struct cvmx_usb_state *usb,
-                              int usb_port_number,
-                              enum cvmx_usb_initialize_flags flags)
+static int cvmx_usb_initialize(struct device *dev,
+                              struct cvmx_usb_state *usb)
 {
+       int channel;
+       int divisor;
+       int retries = 0;
+       union cvmx_usbcx_hcfg usbcx_hcfg;
        union cvmx_usbnx_clk_ctl usbn_clk_ctl;
+       union cvmx_usbcx_gintsts usbc_gintsts;
+       union cvmx_usbcx_gahbcfg usbcx_gahbcfg;
+       union cvmx_usbcx_gintmsk usbcx_gintmsk;
+       union cvmx_usbcx_gusbcfg usbcx_gusbcfg;
        union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status;
-       int i;
-
-       /* At first allow 0-1 for the usb port number */
-       if ((usb_port_number < 0) || (usb_port_number > 1))
-               return -EINVAL;
-
-       memset(usb, 0, sizeof(*usb));
-       usb->init_flags = flags;
-
-       /* Initialize the USB state structure */
-       usb->index = usb_port_number;
-       INIT_LIST_HEAD(&usb->idle_pipes);
-       for (i = 0; i < ARRAY_SIZE(usb->active_pipes); i++)
-               INIT_LIST_HEAD(&usb->active_pipes[i]);
 
+retry:
        /*
         * Power On Reset and PHY Initialization
         *
@@ -696,8 +725,7 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb,
         * 2a. Write USBN0/1_CLK_CTL[POR] = 1 and
         *     USBN0/1_CLK_CTL[HRST,PRST,HCLK_RST] = 0
         */
-       usbn_clk_ctl.u64 =
-               __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index));
+       usbn_clk_ctl.u64 = cvmx_read64_uint64(CVMX_USBNX_CLK_CTL(usb->index));
        usbn_clk_ctl.s.por = 1;
        usbn_clk_ctl.s.hrst = 0;
        usbn_clk_ctl.s.prst = 0;
@@ -722,7 +750,8 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb,
                        /* From CN52XX manual */
                        usbn_clk_ctl.s.p_rtype = 1;
 
-               switch (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK) {
+               switch (usb->init_flags &
+                       CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK) {
                case CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ:
                        usbn_clk_ctl.s.p_c_sel = 0;
                        break;
@@ -752,20 +781,17 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb,
         *     setting USBN0/1_CLK_CTL[ENABLE] = 1. Divide the core clock down
         *     such that USB is as close as possible to 125Mhz
         */
-       {
-               int divisor = DIV_ROUND_UP(octeon_get_clock_rate(), 125000000);
-               /* Lower than 4 doesn't seem to work properly */
-               if (divisor < 4)
-                       divisor = 4;
-               usbn_clk_ctl.s.divide = divisor;
-               usbn_clk_ctl.s.divide2 = 0;
-       }
-       __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                              usbn_clk_ctl.u64);
+       divisor = DIV_ROUND_UP(octeon_get_clock_rate(), 125000000);
+       /* Lower than 4 doesn't seem to work properly */
+       if (divisor < 4)
+               divisor = 4;
+       usbn_clk_ctl.s.divide = divisor;
+       usbn_clk_ctl.s.divide2 = 0;
+       cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
+
        /* 2d. Write USBN0/1_CLK_CTL[HCLK_RST] = 1 */
        usbn_clk_ctl.s.hclk_rst = 1;
-       __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                              usbn_clk_ctl.u64);
+       cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
        /* 2e.  Wait 64 core-clock cycles for HCLK to stabilize */
        cvmx_wait(64);
        /*
@@ -774,8 +800,7 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb,
         *    USBN_CLK_CTL[POR] = 0
         */
        usbn_clk_ctl.s.por = 0;
-       __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                              usbn_clk_ctl.u64);
+       cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
        /* 4. Wait 1 ms for PHY clock to start */
        mdelay(1);
        /*
@@ -783,11 +808,11 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb,
         *    USBP control and status register:
         *    USBN_USBP_CTL_STATUS[ATE_RESET] = 1
         */
-       usbn_usbp_ctl_status.u64 = __cvmx_usb_read_csr64(usb,
-                       CVMX_USBNX_USBP_CTL_STATUS(usb->index));
+       usbn_usbp_ctl_status.u64 =
+               cvmx_read64_uint64(CVMX_USBNX_USBP_CTL_STATUS(usb->index));
        usbn_usbp_ctl_status.s.ate_reset = 1;
-       __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
-                              usbn_usbp_ctl_status.u64);
+       cvmx_write64_uint64(CVMX_USBNX_USBP_CTL_STATUS(usb->index),
+                           usbn_usbp_ctl_status.u64);
        /* 6. Wait 10 cycles */
        cvmx_wait(10);
        /*
@@ -795,23 +820,22 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb,
         *    USBN_USBP_CTL_STATUS[ATE_RESET] = 0
         */
        usbn_usbp_ctl_status.s.ate_reset = 0;
-       __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
-                              usbn_usbp_ctl_status.u64);
+       cvmx_write64_uint64(CVMX_USBNX_USBP_CTL_STATUS(usb->index),
+                           usbn_usbp_ctl_status.u64);
        /*
         * 8. Program the PHY reset field in the USBN clock-control register:
         *    USBN_CLK_CTL[PRST] = 1
         */
        usbn_clk_ctl.s.prst = 1;
-       __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                              usbn_clk_ctl.u64);
+       cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
        /*
         * 9. Program the USBP control and status register to select host or
         *    device mode. USBN_USBP_CTL_STATUS[HST_MODE] = 0 for host, = 1 for
         *    device
         */
        usbn_usbp_ctl_status.s.hst_mode = 0;
-       __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
-                              usbn_usbp_ctl_status.u64);
+       cvmx_write64_uint64(CVMX_USBNX_USBP_CTL_STATUS(usb->index),
+                           usbn_usbp_ctl_status.u64);
        /* 10. Wait 1 us */
        udelay(1);
        /*
@@ -819,12 +843,10 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb,
         *     USBN_CLK_CTL[HRST] = 1
         */
        usbn_clk_ctl.s.hrst = 1;
-       __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                              usbn_clk_ctl.u64);
+       cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
        /* 12. Proceed to USB core initialization */
        usbn_clk_ctl.s.enable = 1;
-       __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                              usbn_clk_ctl.u64);
+       cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
        udelay(1);
 
        /*
@@ -845,29 +867,16 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb,
         *    USBC_GAHBCFG[PTXFEMPLVL]
         *    Global interrupt mask, USBC_GAHBCFG[GLBLINTRMSK] = 1
         */
-       {
-               union cvmx_usbcx_gahbcfg usbcx_gahbcfg;
-               /* Due to an errata, CN31XX doesn't support DMA */
-               if (OCTEON_IS_MODEL(OCTEON_CN31XX))
-                       usb->init_flags |= CVMX_USB_INITIALIZE_FLAGS_NO_DMA;
-               usbcx_gahbcfg.u32 = 0;
-               usbcx_gahbcfg.s.dmaen = !(usb->init_flags &
-                                         CVMX_USB_INITIALIZE_FLAGS_NO_DMA);
-               if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-                       /* Only use one channel with non DMA */
-                       usb->idle_hardware_channels = 0x1;
-               else if (OCTEON_IS_MODEL(OCTEON_CN5XXX))
-                       /* CN5XXX have an errata with channel 3 */
-                       usb->idle_hardware_channels = 0xf7;
-               else
-                       usb->idle_hardware_channels = 0xff;
-               usbcx_gahbcfg.s.hbstlen = 0;
-               usbcx_gahbcfg.s.nptxfemplvl = 1;
-               usbcx_gahbcfg.s.ptxfemplvl = 1;
-               usbcx_gahbcfg.s.glblintrmsk = 1;
-               __cvmx_usb_write_csr32(usb, CVMX_USBCX_GAHBCFG(usb->index),
-                                      usbcx_gahbcfg.u32);
-       }
+       usbcx_gahbcfg.u32 = 0;
+       usbcx_gahbcfg.s.dmaen = !(usb->init_flags &
+                                 CVMX_USB_INITIALIZE_FLAGS_NO_DMA);
+       usbcx_gahbcfg.s.hbstlen = 0;
+       usbcx_gahbcfg.s.nptxfemplvl = 1;
+       usbcx_gahbcfg.s.ptxfemplvl = 1;
+       usbcx_gahbcfg.s.glblintrmsk = 1;
+       cvmx_usb_write_csr32(usb, CVMX_USBCX_GAHBCFG(usb->index),
+                            usbcx_gahbcfg.u32);
+
        /*
         * 3. Program the following fields in USBC_GUSBCFG register.
         *    HS/FS timeout calibration, USBC_GUSBCFG[TOUTCAL] = 0
@@ -875,154 +884,98 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb,
         *    USB turnaround time, USBC_GUSBCFG[USBTRDTIM] = 0x5
         *    PHY low-power clock select, USBC_GUSBCFG[PHYLPWRCLKSEL] = 0
         */
-       {
-               union cvmx_usbcx_gusbcfg usbcx_gusbcfg;
-
-               usbcx_gusbcfg.u32 = __cvmx_usb_read_csr32(usb,
-                               CVMX_USBCX_GUSBCFG(usb->index));
-               usbcx_gusbcfg.s.toutcal = 0;
-               usbcx_gusbcfg.s.ddrsel = 0;
-               usbcx_gusbcfg.s.usbtrdtim = 0x5;
-               usbcx_gusbcfg.s.phylpwrclksel = 0;
-               __cvmx_usb_write_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index),
-                                      usbcx_gusbcfg.u32);
-       }
+       usbcx_gusbcfg.u32 = cvmx_usb_read_csr32(usb,
+                                               CVMX_USBCX_GUSBCFG(usb->index));
+       usbcx_gusbcfg.s.toutcal = 0;
+       usbcx_gusbcfg.s.ddrsel = 0;
+       usbcx_gusbcfg.s.usbtrdtim = 0x5;
+       usbcx_gusbcfg.s.phylpwrclksel = 0;
+       cvmx_usb_write_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index),
+                            usbcx_gusbcfg.u32);
+
        /*
         * 4. The software must unmask the following bits in the USBC_GINTMSK
         *    register.
         *    OTG interrupt mask, USBC_GINTMSK[OTGINTMSK] = 1
         *    Mode mismatch interrupt mask, USBC_GINTMSK[MODEMISMSK] = 1
         */
-       {
-               union cvmx_usbcx_gintmsk usbcx_gintmsk;
-               int channel;
-
-               usbcx_gintmsk.u32 = __cvmx_usb_read_csr32(usb,
-                               CVMX_USBCX_GINTMSK(usb->index));
-               usbcx_gintmsk.s.otgintmsk = 1;
-               usbcx_gintmsk.s.modemismsk = 1;
-               usbcx_gintmsk.s.hchintmsk = 1;
-               usbcx_gintmsk.s.sofmsk = 0;
-               /* We need RX FIFO interrupts if we don't have DMA */
-               if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-                       usbcx_gintmsk.s.rxflvlmsk = 1;
-               __cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTMSK(usb->index),
-                                      usbcx_gintmsk.u32);
-
-               /*
-                * Disable all channel interrupts. We'll enable them per channel
-                * later.
-                */
-               for (channel = 0; channel < 8; channel++)
-                       __cvmx_usb_write_csr32(usb,
-                               CVMX_USBCX_HCINTMSKX(channel, usb->index), 0);
-       }
-
-       {
-               /*
-                * Host Port Initialization
-                *
-                * 1. Program the host-port interrupt-mask field to unmask,
-                *    USBC_GINTMSK[PRTINT] = 1
-                */
-               USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
-                               union cvmx_usbcx_gintmsk, prtintmsk, 1);
-               USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
-                               union cvmx_usbcx_gintmsk, disconnintmsk, 1);
-               /*
-                * 2. Program the USBC_HCFG register to select full-speed host
-                *    or high-speed host.
-                */
-               {
-                       union cvmx_usbcx_hcfg usbcx_hcfg;
-
-                       usbcx_hcfg.u32 = __cvmx_usb_read_csr32(usb,
-                                       CVMX_USBCX_HCFG(usb->index));
-                       usbcx_hcfg.s.fslssupp = 0;
-                       usbcx_hcfg.s.fslspclksel = 0;
-                       __cvmx_usb_write_csr32(usb,
-                                       CVMX_USBCX_HCFG(usb->index),
-                                       usbcx_hcfg.u32);
-               }
-               /*
-                * 3. Program the port power bit to drive VBUS on the USB,
-                *    USBC_HPRT[PRTPWR] = 1
-                */
-               USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index),
-                               union cvmx_usbcx_hprt, prtpwr, 1);
-
-               /*
-                * Steps 4-15 from the manual are done later in the port enable
-                */
-       }
+       usbcx_gintmsk.u32 = cvmx_usb_read_csr32(usb,
+                                               CVMX_USBCX_GINTMSK(usb->index));
+       usbcx_gintmsk.s.otgintmsk = 1;
+       usbcx_gintmsk.s.modemismsk = 1;
+       usbcx_gintmsk.s.hchintmsk = 1;
+       usbcx_gintmsk.s.sofmsk = 0;
+       /* We need RX FIFO interrupts if we don't have DMA */
+       if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
+               usbcx_gintmsk.s.rxflvlmsk = 1;
+       cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTMSK(usb->index),
+                            usbcx_gintmsk.u32);
 
-       return 0;
-}
+       /*
+        * Disable all channel interrupts. We'll enable them per channel later.
+        */
+       for (channel = 0; channel < 8; channel++)
+               cvmx_usb_write_csr32(usb,
+                                    CVMX_USBCX_HCINTMSKX(channel, usb->index),
+                                    0);
 
+       /*
+        * Host Port Initialization
+        *
+        * 1. Program the host-port interrupt-mask field to unmask,
+        *    USBC_GINTMSK[PRTINT] = 1
+        */
+       USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
+                       cvmx_usbcx_gintmsk, prtintmsk, 1);
+       USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
+                       cvmx_usbcx_gintmsk, disconnintmsk, 1);
 
-/**
- * Shutdown a USB port after a call to cvmx_usb_initialize().
- * The port should be disabled with all pipes closed when this
- * function is called.
- *
- * @usb: USB device state populated by cvmx_usb_initialize().
- *
- * Returns: 0 or a negative error code.
- */
-static int cvmx_usb_shutdown(struct cvmx_usb_state *usb)
-{
-       union cvmx_usbnx_clk_ctl usbn_clk_ctl;
+       /*
+        * 2. Program the USBC_HCFG register to select full-speed host
+        *    or high-speed host.
+        */
+       usbcx_hcfg.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HCFG(usb->index));
+       usbcx_hcfg.s.fslssupp = 0;
+       usbcx_hcfg.s.fslspclksel = 0;
+       cvmx_usb_write_csr32(usb, CVMX_USBCX_HCFG(usb->index), usbcx_hcfg.u32);
 
-       /* Make sure all pipes are closed */
-       if (!list_empty(&usb->idle_pipes) ||
-           !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_ISOCHRONOUS]) ||
-           !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT]) ||
-           !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_CONTROL]) ||
-           !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_BULK]))
-               return -EBUSY;
+       cvmx_fifo_setup(usb);
 
-       /* Disable the clocks and put them in power on reset */
-       usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb,
-                       CVMX_USBNX_CLK_CTL(usb->index));
-       usbn_clk_ctl.s.enable = 1;
-       usbn_clk_ctl.s.por = 1;
-       usbn_clk_ctl.s.hclk_rst = 1;
-       usbn_clk_ctl.s.prst = 0;
-       usbn_clk_ctl.s.hrst = 0;
-       __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-                              usbn_clk_ctl.u64);
-       return 0;
+       /*
+        * If the controller is getting port events right after the reset, it
+        * means the initialization failed. Try resetting the controller again
+        * in such case. This is seen to happen after cold boot on DSR-1000N.
+        */
+       usbc_gintsts.u32 = cvmx_usb_read_csr32(usb,
+                                              CVMX_USBCX_GINTSTS(usb->index));
+       cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index),
+                            usbc_gintsts.u32);
+       dev_dbg(dev, "gintsts after reset: 0x%x\n", (int)usbc_gintsts.u32);
+       if (!usbc_gintsts.s.disconnint && !usbc_gintsts.s.prtint)
+               return 0;
+       if (retries++ >= 5)
+               return -EAGAIN;
+       dev_info(dev, "controller reset failed (gintsts=0x%x) - retrying\n",
+                (int)usbc_gintsts.u32);
+       msleep(50);
+       cvmx_usb_shutdown(usb);
+       msleep(50);
+       goto retry;
 }
 
-
 /**
- * Enable a USB port. After this call succeeds, the USB port is
+ * Reset a USB port. After this call succeeds, the USB port is
  * online and servicing requests.
  *
  * @usb: USB device state populated by cvmx_usb_initialize().
- *
- * Returns: 0 or a negative error code.
  */
-static int cvmx_usb_enable(struct cvmx_usb_state *usb)
+static void cvmx_usb_reset_port(struct cvmx_usb_state *usb)
 {
-       union cvmx_usbcx_ghwcfg3 usbcx_ghwcfg3;
-
-       usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb,
-                       CVMX_USBCX_HPRT(usb->index));
-
-       /*
-        * If the port is already enabled the just return. We don't need to do
-        * anything
-        */
-       if (usb->usbcx_hprt.s.prtena)
-               return 0;
-
-       /* If there is nothing plugged into the port then fail immediately */
-       if (!usb->usbcx_hprt.s.prtconnsts)
-               return -ETIMEDOUT;
+       usb->usbcx_hprt.u32 = cvmx_usb_read_csr32(usb,
+                                                 CVMX_USBCX_HPRT(usb->index));
 
        /* Program the port reset bit to start the reset process */
-       USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt,
+       USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt,
                        prtrst, 1);
 
        /*
@@ -1032,75 +985,15 @@ static int cvmx_usb_enable(struct cvmx_usb_state *usb)
        mdelay(50);
 
        /* Program the port reset bit to 0, USBC_HPRT[PRTRST] = 0 */
-       USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt,
+       USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt,
                        prtrst, 0);
 
-       /* Wait for the USBC_HPRT[PRTENA]. */
-       if (CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_HPRT(usb->index),
-                               union cvmx_usbcx_hprt, prtena, ==, 1, 100000))
-               return -ETIMEDOUT;
-
        /*
         * Read the port speed field to get the enumerated speed,
         * USBC_HPRT[PRTSPD].
         */
-       usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb,
-                       CVMX_USBCX_HPRT(usb->index));
-       usbcx_ghwcfg3.u32 = __cvmx_usb_read_csr32(usb,
-                       CVMX_USBCX_GHWCFG3(usb->index));
-
-       /*
-        * 13. Program the USBC_GRXFSIZ register to select the size of the
-        *     receive FIFO (25%).
-        */
-       USB_SET_FIELD32(CVMX_USBCX_GRXFSIZ(usb->index),
-                       union cvmx_usbcx_grxfsiz, rxfdep,
-                       usbcx_ghwcfg3.s.dfifodepth / 4);
-       /*
-        * 14. Program the USBC_GNPTXFSIZ register to select the size and the
-        *     start address of the non- periodic transmit FIFO for nonperiodic
-        *     transactions (50%).
-        */
-       {
-               union cvmx_usbcx_gnptxfsiz siz;
-
-               siz.u32 = __cvmx_usb_read_csr32(usb,
-                               CVMX_USBCX_GNPTXFSIZ(usb->index));
-               siz.s.nptxfdep = usbcx_ghwcfg3.s.dfifodepth / 2;
-               siz.s.nptxfstaddr = usbcx_ghwcfg3.s.dfifodepth / 4;
-               __cvmx_usb_write_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index),
-                                      siz.u32);
-       }
-       /*
-        * 15. Program the USBC_HPTXFSIZ register to select the size and start
-        *     address of the periodic transmit FIFO for periodic transactions
-        *     (25%).
-        */
-       {
-               union cvmx_usbcx_hptxfsiz siz;
-
-               siz.u32 = __cvmx_usb_read_csr32(usb,
-                               CVMX_USBCX_HPTXFSIZ(usb->index));
-               siz.s.ptxfsize = usbcx_ghwcfg3.s.dfifodepth / 4;
-               siz.s.ptxfstaddr = 3 * usbcx_ghwcfg3.s.dfifodepth / 4;
-               __cvmx_usb_write_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index),
-                                      siz.u32);
-       }
-       /* Flush all FIFOs */
-       USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index),
-                       union cvmx_usbcx_grstctl, txfnum, 0x10);
-       USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index),
-                       union cvmx_usbcx_grstctl, txfflsh, 1);
-       CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index),
-                             union cvmx_usbcx_grstctl,
-                             txfflsh, ==, 0, 100);
-       USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index),
-                       union cvmx_usbcx_grstctl, rxfflsh, 1);
-       CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index),
-                             union cvmx_usbcx_grstctl,
-                             rxfflsh, ==, 0, 100);
-
-       return 0;
+       usb->usbcx_hprt.u32 = cvmx_usb_read_csr32(usb,
+                                                 CVMX_USBCX_HPRT(usb->index));
 }
 
 
@@ -1117,7 +1010,7 @@ static int cvmx_usb_enable(struct cvmx_usb_state *usb)
 static int cvmx_usb_disable(struct cvmx_usb_state *usb)
 {
        /* Disable the port */
-       USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt,
+       USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt,
                        prtena, 1);
        return 0;
 }
@@ -1142,8 +1035,7 @@ static struct cvmx_usb_port_status cvmx_usb_get_status(
 
        memset(&result, 0, sizeof(result));
 
-       usbc_hprt.u32 = __cvmx_usb_read_csr32(usb,
-                       CVMX_USBCX_HPRT(usb->index));
+       usbc_hprt.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
        result.port_enabled = usbc_hprt.s.prtena;
        result.port_over_current = usbc_hprt.s.prtovrcurract;
        result.port_powered = usbc_hprt.s.prtpwr;
@@ -1223,41 +1115,13 @@ static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct cvmx_usb_state *usb,
 {
        struct cvmx_usb_pipe *pipe;
 
-       if (unlikely((device_addr < 0) || (device_addr > MAX_USB_ADDRESS)))
-               return NULL;
-       if (unlikely((endpoint_num < 0) || (endpoint_num > MAX_USB_ENDPOINT)))
-               return NULL;
-       if (unlikely(device_speed > CVMX_USB_SPEED_LOW))
-               return NULL;
-       if (unlikely((max_packet <= 0) || (max_packet > 1024)))
-               return NULL;
-       if (unlikely(transfer_type > CVMX_USB_TRANSFER_INTERRUPT))
-               return NULL;
-       if (unlikely((transfer_dir != CVMX_USB_DIRECTION_OUT) &&
-               (transfer_dir != CVMX_USB_DIRECTION_IN)))
-               return NULL;
-       if (unlikely(interval < 0))
-               return NULL;
-       if (unlikely((transfer_type == CVMX_USB_TRANSFER_CONTROL) && interval))
-               return NULL;
-       if (unlikely(multi_count < 0))
-               return NULL;
-       if (unlikely((device_speed != CVMX_USB_SPEED_HIGH) &&
-               (multi_count != 0)))
-               return NULL;
-       if (unlikely((hub_device_addr < 0) ||
-               (hub_device_addr > MAX_USB_ADDRESS)))
-               return NULL;
-       if (unlikely((hub_port < 0) || (hub_port > MAX_USB_HUB_PORT)))
-               return NULL;
-
        pipe = kzalloc(sizeof(*pipe), GFP_ATOMIC);
        if (!pipe)
                return NULL;
        if ((device_speed == CVMX_USB_SPEED_HIGH) &&
                (transfer_dir == CVMX_USB_DIRECTION_OUT) &&
                (transfer_type == CVMX_USB_TRANSFER_BULK))
-               pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
+               pipe->flags |= CVMX_USB_PIPE_FLAGS_NEED_PING;
        pipe->device_addr = device_addr;
        pipe->endpoint_num = endpoint_num;
        pipe->device_speed = device_speed;
@@ -1272,7 +1136,7 @@ static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct cvmx_usb_state *usb,
         */
        if (!interval)
                interval = 1;
-       if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+       if (cvmx_usb_pipe_needs_split(usb, pipe)) {
                pipe->interval = interval*8;
                /* Force start splits to be schedule on uFrame 0 */
                pipe->next_tx_frame = ((usb->frame_number+7)&~7) +
@@ -1304,7 +1168,7 @@ static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct cvmx_usb_state *usb,
  *
  * @usb:       USB device state populated by cvmx_usb_initialize().
  */
-static void __cvmx_usb_poll_rx_fifo(struct cvmx_usb_state *usb)
+static void cvmx_usb_poll_rx_fifo(struct cvmx_usb_state *usb)
 {
        union cvmx_usbcx_grxstsph rx_status;
        int channel;
@@ -1312,8 +1176,8 @@ static void __cvmx_usb_poll_rx_fifo(struct cvmx_usb_state *usb)
        uint64_t address;
        uint32_t *ptr;
 
-       rx_status.u32 = __cvmx_usb_read_csr32(usb,
-                       CVMX_USBCX_GRXSTSPH(usb->index));
+       rx_status.u32 = cvmx_usb_read_csr32(usb,
+                                           CVMX_USBCX_GRXSTSPH(usb->index));
        /* Only read data if IN data is there */
        if (rx_status.s.pktsts != 2)
                return;
@@ -1327,18 +1191,17 @@ static void __cvmx_usb_poll_rx_fifo(struct cvmx_usb_state *usb)
                return;
 
        /* Get where the DMA engine would have written this data */
-       address = __cvmx_usb_read_csr64(usb,
-                       CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8);
+       address = cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index) +
+                                    channel * 8);
 
        ptr = cvmx_phys_to_ptr(address);
-       __cvmx_usb_write_csr64(usb,
-                              CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8,
-                              address + bytes);
+       cvmx_write64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel * 8,
+                           address + bytes);
 
        /* Loop writing the FIFO data for this packet into memory */
        while (bytes > 0) {
-               *ptr++ = __cvmx_usb_read_csr32(usb,
-                               USB_FIFO_ADDRESS(channel, usb->index));
+               *ptr++ = cvmx_usb_read_csr32(usb,
+                                       USB_FIFO_ADDRESS(channel, usb->index));
                bytes -= 4;
        }
        CVMX_SYNCW;
@@ -1356,8 +1219,8 @@ static void __cvmx_usb_poll_rx_fifo(struct cvmx_usb_state *usb)
  * Returns: Non zero if the hardware fifo was too small and needs
  *         to be serviced again.
  */
-static int __cvmx_usb_fill_tx_hw(struct cvmx_usb_state *usb,
-                                struct cvmx_usb_tx_fifo *fifo, int available)
+static int cvmx_usb_fill_tx_hw(struct cvmx_usb_state *usb,
+                              struct cvmx_usb_tx_fifo *fifo, int available)
 {
        /*
         * We're done either when there isn't anymore space or the software FIFO
@@ -1412,38 +1275,34 @@ static int __cvmx_usb_fill_tx_hw(struct cvmx_usb_state *usb,
  *
  * @usb:       USB device state populated by cvmx_usb_initialize().
  */
-static void __cvmx_usb_poll_tx_fifo(struct cvmx_usb_state *usb)
+static void cvmx_usb_poll_tx_fifo(struct cvmx_usb_state *usb)
 {
        if (usb->periodic.head != usb->periodic.tail) {
                union cvmx_usbcx_hptxsts tx_status;
 
-               tx_status.u32 = __cvmx_usb_read_csr32(usb,
-                               CVMX_USBCX_HPTXSTS(usb->index));
-               if (__cvmx_usb_fill_tx_hw(usb, &usb->periodic,
-                                         tx_status.s.ptxfspcavail))
+               tx_status.u32 = cvmx_usb_read_csr32(usb,
+                                       CVMX_USBCX_HPTXSTS(usb->index));
+               if (cvmx_usb_fill_tx_hw(usb, &usb->periodic,
+                                       tx_status.s.ptxfspcavail))
                        USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
-                                       union cvmx_usbcx_gintmsk,
-                                       ptxfempmsk, 1);
+                                       cvmx_usbcx_gintmsk, ptxfempmsk, 1);
                else
                        USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
-                                       union cvmx_usbcx_gintmsk,
-                                       ptxfempmsk, 0);
+                                       cvmx_usbcx_gintmsk, ptxfempmsk, 0);
        }
 
        if (usb->nonperiodic.head != usb->nonperiodic.tail) {
                union cvmx_usbcx_gnptxsts tx_status;
 
-               tx_status.u32 = __cvmx_usb_read_csr32(usb,
-                               CVMX_USBCX_GNPTXSTS(usb->index));
-               if (__cvmx_usb_fill_tx_hw(usb, &usb->nonperiodic,
-                                         tx_status.s.nptxfspcavail))
+               tx_status.u32 = cvmx_usb_read_csr32(usb,
+                                       CVMX_USBCX_GNPTXSTS(usb->index));
+               if (cvmx_usb_fill_tx_hw(usb, &usb->nonperiodic,
+                                       tx_status.s.nptxfspcavail))
                        USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
-                                       union cvmx_usbcx_gintmsk,
-                                       nptxfempmsk, 1);
+                                       cvmx_usbcx_gintmsk, nptxfempmsk, 1);
                else
                        USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
-                                       union cvmx_usbcx_gintmsk,
-                                       nptxfempmsk, 0);
+                                       cvmx_usbcx_gintmsk, nptxfempmsk, 0);
        }
 }
 
@@ -1454,7 +1313,7 @@ static void __cvmx_usb_poll_tx_fifo(struct cvmx_usb_state *usb)
  * @usb:         USB device state populated by cvmx_usb_initialize().
  * @channel:     Channel number to get packet from
  */
-static void __cvmx_usb_fill_tx_fifo(struct cvmx_usb_state *usb, int channel)
+static void cvmx_usb_fill_tx_fifo(struct cvmx_usb_state *usb, int channel)
 {
        union cvmx_usbcx_hccharx hcchar;
        union cvmx_usbcx_hcspltx usbc_hcsplt;
@@ -1462,14 +1321,14 @@ static void __cvmx_usb_fill_tx_fifo(struct cvmx_usb_state *usb, int channel)
        struct cvmx_usb_tx_fifo *fifo;
 
        /* We only need to fill data on outbound channels */
-       hcchar.u32 = __cvmx_usb_read_csr32(usb,
+       hcchar.u32 = cvmx_usb_read_csr32(usb,
                        CVMX_USBCX_HCCHARX(channel, usb->index));
        if (hcchar.s.epdir != CVMX_USB_DIRECTION_OUT)
                return;
 
        /* OUT Splits only have data on the start and not the complete */
-       usbc_hcsplt.u32 = __cvmx_usb_read_csr32(usb,
-                       CVMX_USBCX_HCSPLTX(channel, usb->index));
+       usbc_hcsplt.u32 = cvmx_usb_read_csr32(usb,
+                               CVMX_USBCX_HCSPLTX(channel, usb->index));
        if (usbc_hcsplt.s.spltena && usbc_hcsplt.s.compsplt)
                return;
 
@@ -1477,8 +1336,8 @@ static void __cvmx_usb_fill_tx_fifo(struct cvmx_usb_state *usb, int channel)
         * Find out how many bytes we need to fill and convert it into 32bit
         * words.
         */
-       usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb,
-                       CVMX_USBCX_HCTSIZX(channel, usb->index));
+       usbc_hctsiz.u32 = cvmx_usb_read_csr32(usb,
+                               CVMX_USBCX_HCTSIZX(channel, usb->index));
        if (!usbc_hctsiz.s.xfersize)
                return;
 
@@ -1489,28 +1348,28 @@ static void __cvmx_usb_fill_tx_fifo(struct cvmx_usb_state *usb, int channel)
                fifo = &usb->nonperiodic;
 
        fifo->entry[fifo->head].channel = channel;
-       fifo->entry[fifo->head].address = __cvmx_usb_read_csr64(usb,
-                       CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8);
+       fifo->entry[fifo->head].address =
+               cvmx_read64_uint64(CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) +
+                                  channel * 8);
        fifo->entry[fifo->head].size = (usbc_hctsiz.s.xfersize+3)>>2;
        fifo->head++;
        if (fifo->head > MAX_CHANNELS)
                fifo->head = 0;
 
-       __cvmx_usb_poll_tx_fifo(usb);
+       cvmx_usb_poll_tx_fifo(usb);
 }
 
 /**
  * Perform channel specific setup for Control transactions. All
- * the generic stuff will already have been done in
- * __cvmx_usb_start_channel()
+ * the generic stuff will already have been done in cvmx_usb_start_channel().
  *
  * @usb:         USB device state populated by cvmx_usb_initialize().
  * @channel:     Channel to setup
  * @pipe:        Pipe for control transaction
  */
-static void __cvmx_usb_start_channel_control(struct cvmx_usb_state *usb,
-                                            int channel,
-                                            struct cvmx_usb_pipe *pipe)
+static void cvmx_usb_start_channel_control(struct cvmx_usb_state *usb,
+                                          int channel,
+                                          struct cvmx_usb_pipe *pipe)
 {
        struct octeon_hcd *priv = cvmx_usb_to_octeon(usb);
        struct usb_hcd *hcd = octeon_to_hcd(priv);
@@ -1525,8 +1384,8 @@ static void __cvmx_usb_start_channel_control(struct cvmx_usb_state *usb,
        int packets_to_transfer;
        union cvmx_usbcx_hctsizx usbc_hctsiz;
 
-       usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb,
-                       CVMX_USBCX_HCTSIZX(channel, usb->index));
+       usbc_hctsiz.u32 = cvmx_usb_read_csr32(usb,
+                               CVMX_USBCX_HCTSIZX(channel, usb->index));
 
        switch (transaction->stage) {
        case CVMX_USB_STAGE_NON_CONTROL:
@@ -1538,72 +1397,72 @@ static void __cvmx_usb_start_channel_control(struct cvmx_usb_state *usb,
                bytes_to_transfer = sizeof(*header);
                /* All Control operations start with a setup going OUT */
                USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
-                               union cvmx_usbcx_hccharx, epdir,
+                               cvmx_usbcx_hccharx, epdir,
                                CVMX_USB_DIRECTION_OUT);
                /*
                 * Setup send the control header instead of the buffer data. The
                 * buffer data will be used in the next stage
                 */
-               __cvmx_usb_write_csr64(usb,
-                       CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8,
-                       transaction->control_header);
+               cvmx_write64_uint64(CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) +
+                                       channel * 8,
+                                   transaction->control_header);
                break;
        case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE:
                usbc_hctsiz.s.pid = 3; /* Setup */
                bytes_to_transfer = 0;
                /* All Control operations start with a setup going OUT */
                USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
-                               union cvmx_usbcx_hccharx, epdir,
+                               cvmx_usbcx_hccharx, epdir,
                                CVMX_USB_DIRECTION_OUT);
 
                USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index),
-                               union cvmx_usbcx_hcspltx, compsplt, 1);
+                               cvmx_usbcx_hcspltx, compsplt, 1);
                break;
        case CVMX_USB_STAGE_DATA:
-               usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
-               if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+               usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe);
+               if (cvmx_usb_pipe_needs_split(usb, pipe)) {
                        if (header->bRequestType & USB_DIR_IN)
                                bytes_to_transfer = 0;
                        else if (bytes_to_transfer > pipe->max_packet)
                                bytes_to_transfer = pipe->max_packet;
                }
                USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
-                               union cvmx_usbcx_hccharx, epdir,
+                               cvmx_usbcx_hccharx, epdir,
                                ((header->bRequestType & USB_DIR_IN) ?
                                        CVMX_USB_DIRECTION_IN :
                                        CVMX_USB_DIRECTION_OUT));
                break;
        case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE:
-               usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+               usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe);
                if (!(header->bRequestType & USB_DIR_IN))
                        bytes_to_transfer = 0;
                USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
-                               union cvmx_usbcx_hccharx, epdir,
+                               cvmx_usbcx_hccharx, epdir,
                                ((header->bRequestType & USB_DIR_IN) ?
                                        CVMX_USB_DIRECTION_IN :
                                        CVMX_USB_DIRECTION_OUT));
                USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index),
-                               union cvmx_usbcx_hcspltx, compsplt, 1);
+                               cvmx_usbcx_hcspltx, compsplt, 1);
                break;
        case CVMX_USB_STAGE_STATUS:
-               usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+               usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe);
                bytes_to_transfer = 0;
                USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
-                               union cvmx_usbcx_hccharx, epdir,
+                               cvmx_usbcx_hccharx, epdir,
                                ((header->bRequestType & USB_DIR_IN) ?
                                        CVMX_USB_DIRECTION_OUT :
                                        CVMX_USB_DIRECTION_IN));
                break;
        case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
-               usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+               usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe);
                bytes_to_transfer = 0;
                USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
-                               union cvmx_usbcx_hccharx, epdir,
+                               cvmx_usbcx_hccharx, epdir,
                                ((header->bRequestType & USB_DIR_IN) ?
                                        CVMX_USB_DIRECTION_OUT :
                                        CVMX_USB_DIRECTION_IN));
                USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index),
-                               union cvmx_usbcx_hcspltx, compsplt, 1);
+                               cvmx_usbcx_hcspltx, compsplt, 1);
                break;
        }
 
@@ -1646,8 +1505,8 @@ static void __cvmx_usb_start_channel_control(struct cvmx_usb_state *usb,
        usbc_hctsiz.s.xfersize = bytes_to_transfer;
        usbc_hctsiz.s.pktcnt = packets_to_transfer;
 
-       __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index),
-                              usbc_hctsiz.u32);
+       cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index),
+                            usbc_hctsiz.u32);
 }
 
 
@@ -1658,9 +1517,8 @@ static void __cvmx_usb_start_channel_control(struct cvmx_usb_state *usb,
  * @channel:     Channel to setup
  * @pipe:        Pipe to start
  */
-static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
-                                    int channel,
-                                    struct cvmx_usb_pipe *pipe)
+static void cvmx_usb_start_channel(struct cvmx_usb_state *usb, int channel,
+                                  struct cvmx_usb_pipe *pipe)
 {
        struct cvmx_usb_transaction *transaction =
                list_first_entry(&pipe->transactions, typeof(*transaction),
@@ -1672,7 +1530,7 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
        /* Attach the channel to the pipe */
        usb->pipe_for_channel[channel] = pipe;
        pipe->channel = channel;
-       pipe->flags |= __CVMX_USB_PIPE_FLAGS_SCHEDULED;
+       pipe->flags |= CVMX_USB_PIPE_FLAGS_SCHEDULED;
 
        /* Mark this channel as in use */
        usb->idle_hardware_channels &= ~(1<<channel);
@@ -1684,12 +1542,12 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
                union cvmx_usbcx_haintmsk usbc_haintmsk;
 
                /* Clear all channel status bits */
-               usbc_hcint.u32 = __cvmx_usb_read_csr32(usb,
-                               CVMX_USBCX_HCINTX(channel, usb->index));
+               usbc_hcint.u32 = cvmx_usb_read_csr32(usb,
+                                       CVMX_USBCX_HCINTX(channel, usb->index));
 
-               __cvmx_usb_write_csr32(usb,
-                                      CVMX_USBCX_HCINTX(channel, usb->index),
-                                      usbc_hcint.u32);
+               cvmx_usb_write_csr32(usb,
+                                    CVMX_USBCX_HCINTX(channel, usb->index),
+                                    usbc_hcint.u32);
 
                usbc_hcintmsk.u32 = 0;
                usbc_hcintmsk.s.chhltdmsk = 1;
@@ -1702,7 +1560,7 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
                        usbc_hcintmsk.s.frmovrunmsk = 1;
                        usbc_hcintmsk.s.bblerrmsk = 1;
                        usbc_hcintmsk.s.xacterrmsk = 1;
-                       if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+                       if (cvmx_usb_pipe_needs_split(usb, pipe)) {
                                /*
                                 * Splits don't generate xfercompl, so we need
                                 * ACK and NYET.
@@ -1714,21 +1572,21 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
                        usbc_hcintmsk.s.stallmsk = 1;
                        usbc_hcintmsk.s.xfercomplmsk = 1;
                }
-               __cvmx_usb_write_csr32(usb,
+               cvmx_usb_write_csr32(usb,
                                CVMX_USBCX_HCINTMSKX(channel, usb->index),
                                usbc_hcintmsk.u32);
 
                /* Enable the channel interrupt to propagate */
-               usbc_haintmsk.u32 = __cvmx_usb_read_csr32(usb,
+               usbc_haintmsk.u32 = cvmx_usb_read_csr32(usb,
                                        CVMX_USBCX_HAINTMSK(usb->index));
                usbc_haintmsk.s.haintmsk |= 1<<channel;
-               __cvmx_usb_write_csr32(usb,
-                                       CVMX_USBCX_HAINTMSK(usb->index),
-                                       usbc_haintmsk.u32);
+               cvmx_usb_write_csr32(usb, CVMX_USBCX_HAINTMSK(usb->index),
+                                    usbc_haintmsk.u32);
        }
 
-       /* Setup the locations the DMA engines use  */
+       /* Setup the location the DMA engine uses. */
        {
+               uint64_t reg;
                uint64_t dma_address = transaction->buffer +
                                        transaction->actual_bytes;
 
@@ -1737,13 +1595,11 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
                                        transaction->iso_packets[0].offset +
                                        transaction->actual_bytes;
 
-               __cvmx_usb_write_csr64(usb,
-                       CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8,
-                       dma_address);
-
-               __cvmx_usb_write_csr64(usb,
-                       CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8,
-                       dma_address);
+               if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT)
+                       reg = CVMX_USBNX_DMA0_OUTB_CHN0(usb->index);
+               else
+                       reg = CVMX_USBNX_DMA0_INB_CHN0(usb->index);
+               cvmx_write64_uint64(reg + channel * 8, dma_address);
        }
 
        /* Setup both the size of the transfer and the SPLIT characteristics */
@@ -1767,7 +1623,7 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
                 * We need to do split transactions when we are talking to non
                 * high speed devices that are behind a high speed hub
                 */
-               if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+               if (cvmx_usb_pipe_needs_split(usb, pipe)) {
                        /*
                         * On the start split phase (stage is even) record the
                         * frame number we will need to send the split complete.
@@ -1898,18 +1754,19 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
                usbc_hctsiz.s.pktcnt = packets_to_transfer;
 
                /* Update the DATA0/DATA1 toggle */
-               usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+               usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe);
                /*
                 * High speed pipes may need a hardware ping before they start
                 */
-               if (pipe->flags & __CVMX_USB_PIPE_FLAGS_NEED_PING)
+               if (pipe->flags & CVMX_USB_PIPE_FLAGS_NEED_PING)
                        usbc_hctsiz.s.dopng = 1;
 
-               __cvmx_usb_write_csr32(usb,
-                                      CVMX_USBCX_HCSPLTX(channel, usb->index),
-                                      usbc_hcsplt.u32);
-               __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel,
-                                       usb->index), usbc_hctsiz.u32);
+               cvmx_usb_write_csr32(usb,
+                                    CVMX_USBCX_HCSPLTX(channel, usb->index),
+                                    usbc_hcsplt.u32);
+               cvmx_usb_write_csr32(usb,
+                                    CVMX_USBCX_HCTSIZX(channel, usb->index),
+                                    usbc_hctsiz.u32);
        }
 
        /* Setup the Host Channel Characteristics Register */
@@ -1928,7 +1785,7 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
                 * immediate retries of failure. These retries happen too
                 * quickly, so we disable these entirely for splits
                 */
-               if (__cvmx_usb_pipe_needs_split(usb, pipe))
+               if (cvmx_usb_pipe_needs_split(usb, pipe))
                        usbc_hcchar.s.ec = 1;
                else if (pipe->multi_count < 1)
                        usbc_hcchar.s.ec = 1;
@@ -1945,21 +1802,21 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
                usbc_hcchar.s.epdir = pipe->transfer_dir;
                usbc_hcchar.s.epnum = pipe->endpoint_num;
                usbc_hcchar.s.mps = pipe->max_packet;
-               __cvmx_usb_write_csr32(usb,
-                                      CVMX_USBCX_HCCHARX(channel, usb->index),
-                                      usbc_hcchar.u32);
+               cvmx_usb_write_csr32(usb,
+                                    CVMX_USBCX_HCCHARX(channel, usb->index),
+                                    usbc_hcchar.u32);
        }
 
        /* Do transaction type specific fixups as needed */
        switch (transaction->type) {
        case CVMX_USB_TRANSFER_CONTROL:
-               __cvmx_usb_start_channel_control(usb, channel, pipe);
+               cvmx_usb_start_channel_control(usb, channel, pipe);
                break;
        case CVMX_USB_TRANSFER_BULK:
        case CVMX_USB_TRANSFER_INTERRUPT:
                break;
        case CVMX_USB_TRANSFER_ISOCHRONOUS:
-               if (!__cvmx_usb_pipe_needs_split(usb, pipe)) {
+               if (!cvmx_usb_pipe_needs_split(usb, pipe)) {
                        /*
                         * ISO transactions require different PIDs depending on
                         * direction and how many packets are needed
@@ -1969,32 +1826,30 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
                                        USB_SET_FIELD32(
                                                CVMX_USBCX_HCTSIZX(channel,
                                                                   usb->index),
-                                               union cvmx_usbcx_hctsizx,
-                                               pid, 0);
+                                               cvmx_usbcx_hctsizx, pid, 0);
                                else /* Need MDATA */
                                        USB_SET_FIELD32(
                                                CVMX_USBCX_HCTSIZX(channel,
                                                                   usb->index),
-                                               union cvmx_usbcx_hctsizx,
-                                               pid, 3);
+                                               cvmx_usbcx_hctsizx, pid, 3);
                        }
                }
                break;
        }
        {
                union cvmx_usbcx_hctsizx usbc_hctsiz = {.u32 =
-                       __cvmx_usb_read_csr32(usb,
+                       cvmx_usb_read_csr32(usb,
                                CVMX_USBCX_HCTSIZX(channel, usb->index))};
                transaction->xfersize = usbc_hctsiz.s.xfersize;
                transaction->pktcnt = usbc_hctsiz.s.pktcnt;
        }
        /* Remeber when we start a split transaction */
-       if (__cvmx_usb_pipe_needs_split(usb, pipe))
+       if (cvmx_usb_pipe_needs_split(usb, pipe))
                usb->active_split = transaction;
        USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
-                       union cvmx_usbcx_hccharx, chena, 1);
+                       cvmx_usbcx_hccharx, chena, 1);
        if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-               __cvmx_usb_fill_tx_fifo(usb, channel);
+               cvmx_usb_fill_tx_fifo(usb, channel);
 }
 
 
@@ -2007,7 +1862,7 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
  *
  * Returns: Pipe or NULL if none are ready
  */
-static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(
+static struct cvmx_usb_pipe *cvmx_usb_find_ready_pipe(
                struct cvmx_usb_state *usb,
                struct list_head *list,
                uint64_t current_frame)
@@ -2018,7 +1873,7 @@ static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(
                struct cvmx_usb_transaction *t =
                        list_first_entry(&pipe->transactions, typeof(*t),
                                         node);
-               if (!(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED) && t &&
+               if (!(pipe->flags & CVMX_USB_PIPE_FLAGS_SCHEDULED) && t &&
                        (pipe->next_tx_frame <= current_frame) &&
                        ((pipe->split_sc_frame == -1) ||
                         ((((int)current_frame - (int)pipe->split_sc_frame)
@@ -2039,7 +1894,7 @@ static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(
  * @usb:        USB device state populated by cvmx_usb_initialize().
  * @is_sof:     True if this schedule was called on a SOF interrupt.
  */
-static void __cvmx_usb_schedule(struct cvmx_usb_state *usb, int is_sof)
+static void cvmx_usb_schedule(struct cvmx_usb_state *usb, int is_sof)
 {
        int channel;
        struct cvmx_usb_pipe *pipe;
@@ -2052,12 +1907,12 @@ static void __cvmx_usb_schedule(struct cvmx_usb_state *usb, int is_sof)
                 * at the end of a frame and cause an overrun.
                 */
                union cvmx_usbcx_hfnum hfnum = {
-                       .u32 = __cvmx_usb_read_csr32(usb,
+                       .u32 = cvmx_usb_read_csr32(usb,
                                                CVMX_USBCX_HFNUM(usb->index))
                };
 
                union cvmx_usbcx_hfir hfir = {
-                       .u32 = __cvmx_usb_read_csr32(usb,
+                       .u32 = cvmx_usb_read_csr32(usb,
                                                CVMX_USBCX_HFIR(usb->index))
                };
 
@@ -2079,23 +1934,23 @@ static void __cvmx_usb_schedule(struct cvmx_usb_state *usb, int is_sof)
                         * way we are sure that the periodic data is sent in the
                         * beginning of the frame
                         */
-                       pipe = __cvmx_usb_find_ready_pipe(usb,
+                       pipe = cvmx_usb_find_ready_pipe(usb,
                                        usb->active_pipes +
                                        CVMX_USB_TRANSFER_ISOCHRONOUS,
                                        usb->frame_number);
                        if (likely(!pipe))
-                               pipe = __cvmx_usb_find_ready_pipe(usb,
+                               pipe = cvmx_usb_find_ready_pipe(usb,
                                                usb->active_pipes +
                                                CVMX_USB_TRANSFER_INTERRUPT,
                                                usb->frame_number);
                }
                if (likely(!pipe)) {
-                       pipe = __cvmx_usb_find_ready_pipe(usb,
+                       pipe = cvmx_usb_find_ready_pipe(usb,
                                        usb->active_pipes +
                                        CVMX_USB_TRANSFER_CONTROL,
                                        usb->frame_number);
                        if (likely(!pipe))
-                               pipe = __cvmx_usb_find_ready_pipe(usb,
+                               pipe = cvmx_usb_find_ready_pipe(usb,
                                                usb->active_pipes +
                                                CVMX_USB_TRANSFER_BULK,
                                                usb->frame_number);
@@ -2103,7 +1958,7 @@ static void __cvmx_usb_schedule(struct cvmx_usb_state *usb, int is_sof)
                if (!pipe)
                        break;
 
-               __cvmx_usb_start_channel(usb, channel, pipe);
+               cvmx_usb_start_channel(usb, channel, pipe);
        }
 
 done:
@@ -2122,7 +1977,7 @@ done:
                }
        }
        USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
-                       union cvmx_usbcx_gintmsk, sofmsk, need_sof);
+                       cvmx_usbcx_gintmsk, sofmsk, need_sof);
 }
 
 static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb,
@@ -2226,11 +2081,10 @@ static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb,
  * @complete_code:
  *              Completion code
  */
-static void __cvmx_usb_perform_complete(
-                               struct cvmx_usb_state *usb,
-                               struct cvmx_usb_pipe *pipe,
-                               struct cvmx_usb_transaction *transaction,
-                               enum cvmx_usb_complete complete_code)
+static void cvmx_usb_perform_complete(struct cvmx_usb_state *usb,
+                                     struct cvmx_usb_pipe *pipe,
+                                     struct cvmx_usb_transaction *transaction,
+                                     enum cvmx_usb_complete complete_code)
 {
        /* If this was a split then clear our split in progress marker */
        if (usb->active_split == transaction)
@@ -2296,7 +2150,7 @@ static void __cvmx_usb_perform_complete(
  *
  * Returns: Transaction or NULL on failure.
  */
-static struct cvmx_usb_transaction *__cvmx_usb_submit_transaction(
+static struct cvmx_usb_transaction *cvmx_usb_submit_transaction(
                                struct cvmx_usb_state *usb,
                                struct cvmx_usb_pipe *pipe,
                                enum cvmx_usb_transfer type,
@@ -2342,7 +2196,7 @@ static struct cvmx_usb_transaction *__cvmx_usb_submit_transaction(
                 * We may need to schedule the pipe if this was the head of the
                 * pipe.
                 */
-               __cvmx_usb_schedule(usb, 0);
+               cvmx_usb_schedule(usb, 0);
        }
 
        return transaction;
@@ -2363,14 +2217,14 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_bulk(
                                                struct cvmx_usb_pipe *pipe,
                                                struct urb *urb)
 {
-       return __cvmx_usb_submit_transaction(usb, pipe, CVMX_USB_TRANSFER_BULK,
-                                            urb->transfer_dma,
-                                            urb->transfer_buffer_length,
-                                            0, /* control_header */
-                                            0, /* iso_start_frame */
-                                            0, /* iso_number_packets */
-                                            NULL, /* iso_packets */
-                                            urb);
+       return cvmx_usb_submit_transaction(usb, pipe, CVMX_USB_TRANSFER_BULK,
+                                          urb->transfer_dma,
+                                          urb->transfer_buffer_length,
+                                          0, /* control_header */
+                                          0, /* iso_start_frame */
+                                          0, /* iso_number_packets */
+                                          NULL, /* iso_packets */
+                                          urb);
 }
 
 
@@ -2388,15 +2242,15 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_interrupt(
                                                struct cvmx_usb_pipe *pipe,
                                                struct urb *urb)
 {
-       return __cvmx_usb_submit_transaction(usb, pipe,
-                                            CVMX_USB_TRANSFER_INTERRUPT,
-                                            urb->transfer_dma,
-                                            urb->transfer_buffer_length,
-                                            0, /* control_header */
-                                            0, /* iso_start_frame */
-                                            0, /* iso_number_packets */
-                                            NULL, /* iso_packets */
-                                            urb);
+       return cvmx_usb_submit_transaction(usb, pipe,
+                                          CVMX_USB_TRANSFER_INTERRUPT,
+                                          urb->transfer_dma,
+                                          urb->transfer_buffer_length,
+                                          0, /* control_header */
+                                          0, /* iso_start_frame */
+                                          0, /* iso_number_packets */
+                                          NULL, /* iso_packets */
+                                          urb);
 }
 
 
@@ -2421,14 +2275,14 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_control(
        if ((header->bRequestType & USB_DIR_IN) == 0)
                buffer_length = le16_to_cpu(header->wLength);
 
-       return __cvmx_usb_submit_transaction(usb, pipe,
-                                            CVMX_USB_TRANSFER_CONTROL,
-                                            urb->transfer_dma, buffer_length,
-                                            control_header,
-                                            0, /* iso_start_frame */
-                                            0, /* iso_number_packets */
-                                            NULL, /* iso_packets */
-                                            urb);
+       return cvmx_usb_submit_transaction(usb, pipe,
+                                          CVMX_USB_TRANSFER_CONTROL,
+                                          urb->transfer_dma, buffer_length,
+                                          control_header,
+                                          0, /* iso_start_frame */
+                                          0, /* iso_number_packets */
+                                          NULL, /* iso_packets */
+                                          urb);
 }
 
 
@@ -2449,14 +2303,14 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_isochronous(
        struct cvmx_usb_iso_packet *packets;
 
        packets = (struct cvmx_usb_iso_packet *) urb->setup_packet;
-       return __cvmx_usb_submit_transaction(usb, pipe,
-                                            CVMX_USB_TRANSFER_ISOCHRONOUS,
-                                            urb->transfer_dma,
-                                            urb->transfer_buffer_length,
-                                            0, /* control_header */
-                                            urb->start_frame,
-                                            urb->number_of_packets,
-                                            packets, urb);
+       return cvmx_usb_submit_transaction(usb, pipe,
+                                          CVMX_USB_TRANSFER_ISOCHRONOUS,
+                                          urb->transfer_dma,
+                                          urb->transfer_buffer_length,
+                                          0, /* control_header */
+                                          urb->start_frame,
+                                          urb->number_of_packets,
+                                          packets, urb);
 }
 
 
@@ -2482,15 +2336,15 @@ static int cvmx_usb_cancel(struct cvmx_usb_state *usb,
         * treat it special
         */
        if (list_first_entry(&pipe->transactions, typeof(*transaction), node) ==
-           transaction && (pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED)) {
+           transaction && (pipe->flags & CVMX_USB_PIPE_FLAGS_SCHEDULED)) {
                union cvmx_usbcx_hccharx usbc_hcchar;
 
                usb->pipe_for_channel[pipe->channel] = NULL;
-               pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED;
+               pipe->flags &= ~CVMX_USB_PIPE_FLAGS_SCHEDULED;
 
                CVMX_SYNCW;
 
-               usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb,
+               usbc_hcchar.u32 = cvmx_usb_read_csr32(usb,
                                CVMX_USBCX_HCCHARX(pipe->channel, usb->index));
                /*
                 * If the channel isn't enabled then the transaction already
@@ -2498,14 +2352,14 @@ static int cvmx_usb_cancel(struct cvmx_usb_state *usb,
                 */
                if (usbc_hcchar.s.chena) {
                        usbc_hcchar.s.chdis = 1;
-                       __cvmx_usb_write_csr32(usb,
+                       cvmx_usb_write_csr32(usb,
                                        CVMX_USBCX_HCCHARX(pipe->channel,
                                                usb->index),
                                        usbc_hcchar.u32);
                }
        }
-       __cvmx_usb_perform_complete(usb, pipe, transaction,
-                                   CVMX_USB_COMPLETE_CANCEL);
+       cvmx_usb_perform_complete(usb, pipe, transaction,
+                                 CVMX_USB_COMPLETE_CANCEL);
        return 0;
 }
 
@@ -2570,8 +2424,7 @@ static int cvmx_usb_get_frame_number(struct cvmx_usb_state *usb)
        int frame_number;
        union cvmx_usbcx_hfnum usbc_hfnum;
 
-       usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb,
-                       CVMX_USBCX_HFNUM(usb->index));
+       usbc_hfnum.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index));
        frame_number = usbc_hfnum.s.frnum;
 
        return frame_number;
@@ -2586,7 +2439,7 @@ static int cvmx_usb_get_frame_number(struct cvmx_usb_state *usb)
  *
  * Returns: Zero on success
  */
-static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
+static int cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
 {
        struct octeon_hcd *priv = cvmx_usb_to_octeon(usb);
        struct usb_hcd *hcd = octeon_to_hcd(priv);
@@ -2602,11 +2455,11 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
        int buffer_space_left;
 
        /* Read the interrupt status bits for the channel */
-       usbc_hcint.u32 = __cvmx_usb_read_csr32(usb,
-                       CVMX_USBCX_HCINTX(channel, usb->index));
+       usbc_hcint.u32 = cvmx_usb_read_csr32(usb,
+                               CVMX_USBCX_HCINTX(channel, usb->index));
 
        if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
-               usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb,
+               usbc_hcchar.u32 = cvmx_usb_read_csr32(usb,
                                CVMX_USBCX_HCCHARX(channel, usb->index));
 
                if (usbc_hcchar.s.chena && usbc_hcchar.s.chdis) {
@@ -2615,7 +2468,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                         * interrupt IN transfers to get stuck until we do a
                         * write of HCCHARX without changing things
                         */
-                       __cvmx_usb_write_csr32(usb,
+                       cvmx_usb_write_csr32(usb,
                                        CVMX_USBCX_HCCHARX(channel,
                                                           usb->index),
                                        usbc_hcchar.u32);
@@ -2632,12 +2485,12 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                                /* Disable all interrupts except CHHLTD */
                                hcintmsk.u32 = 0;
                                hcintmsk.s.chhltdmsk = 1;
-                               __cvmx_usb_write_csr32(usb,
+                               cvmx_usb_write_csr32(usb,
                                                CVMX_USBCX_HCINTMSKX(channel,
                                                        usb->index),
                                                hcintmsk.u32);
                                usbc_hcchar.s.chdis = 1;
-                               __cvmx_usb_write_csr32(usb,
+                               cvmx_usb_write_csr32(usb,
                                                CVMX_USBCX_HCCHARX(channel,
                                                        usb->index),
                                                usbc_hcchar.u32);
@@ -2663,9 +2516,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
        }
 
        /* Disable the channel interrupts now that it is done */
-       __cvmx_usb_write_csr32(usb,
-                               CVMX_USBCX_HCINTMSKX(channel, usb->index),
-                               0);
+       cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0);
        usb->idle_hardware_channels |= (1<<channel);
 
        /* Make sure this channel is tied to a valid pipe */
@@ -2683,15 +2534,15 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
         * function will figure out which pipe needs to go
         */
        usb->pipe_for_channel[channel] = NULL;
-       pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED;
+       pipe->flags &= ~CVMX_USB_PIPE_FLAGS_SCHEDULED;
 
        /*
         * Read the channel config info so we can figure out how much data
         * transferred
         */
-       usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb,
+       usbc_hcchar.u32 = cvmx_usb_read_csr32(usb,
                        CVMX_USBCX_HCCHARX(channel, usb->index));
-       usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb,
+       usbc_hctsiz.u32 = cvmx_usb_read_csr32(usb,
                        CVMX_USBCX_HCTSIZX(channel, usb->index));
 
        /*
@@ -2766,7 +2617,18 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
        if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) &&
                (pipe->transfer_type == CVMX_USB_TRANSFER_BULK) &&
                (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT))
-               pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
+               pipe->flags |= CVMX_USB_PIPE_FLAGS_NEED_PING;
+
+       if (unlikely(WARN_ON_ONCE(bytes_this_transfer < 0))) {
+               /*
+                * In some rare cases the DMA engine seems to get stuck and
+                * keeps substracting same byte count over and over again. In
+                * such case we just need to fail every transaction.
+                */
+               cvmx_usb_perform_complete(usb, pipe, transaction,
+                                         CVMX_USB_COMPLETE_ERROR);
+               return 0;
+       }
 
        if (usbc_hcint.s.stall) {
                /*
@@ -2776,52 +2638,24 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                 * the actual bytes transferred
                 */
                pipe->pid_toggle = 0;
-               __cvmx_usb_perform_complete(usb, pipe, transaction,
-                                           CVMX_USB_COMPLETE_STALL);
+               cvmx_usb_perform_complete(usb, pipe, transaction,
+                                         CVMX_USB_COMPLETE_STALL);
        } else if (usbc_hcint.s.xacterr) {
                /*
-                * We know at least one packet worked if we get a ACK or NAK.
-                * Reset the retry counter
+                * XactErr as a response means the device signaled
+                * something wrong with the transfer. For example, PID
+                * toggle errors cause these.
                 */
-               if (usbc_hcint.s.nak || usbc_hcint.s.ack)
-                       transaction->retries = 0;
-               transaction->retries++;
-               if (transaction->retries > MAX_RETRIES) {
-                       /*
-                        * XactErr as a response means the device signaled
-                        * something wrong with the transfer. For example, PID
-                        * toggle errors cause these
-                        */
-                       __cvmx_usb_perform_complete(usb, pipe, transaction,
-                                                   CVMX_USB_COMPLETE_XACTERR);
-               } else {
-                       /*
-                        * If this was a split then clear our split in progress
-                        * marker
-                        */
-                       if (usb->active_split == transaction)
-                               usb->active_split = NULL;
-                       /*
-                        * Rewind to the beginning of the transaction by anding
-                        * off the split complete bit
-                        */
-                       transaction->stage &= ~1;
-                       pipe->split_sc_frame = -1;
-                       pipe->next_tx_frame += pipe->interval;
-                       if (pipe->next_tx_frame < usb->frame_number)
-                               pipe->next_tx_frame =
-                                       usb->frame_number + pipe->interval -
-                                       (usb->frame_number -
-                                        pipe->next_tx_frame) % pipe->interval;
-               }
+               cvmx_usb_perform_complete(usb, pipe, transaction,
+                                         CVMX_USB_COMPLETE_XACTERR);
        } else if (usbc_hcint.s.bblerr) {
                /* Babble Error (BblErr) */
-               __cvmx_usb_perform_complete(usb, pipe, transaction,
-                                           CVMX_USB_COMPLETE_BABBLEERR);
+               cvmx_usb_perform_complete(usb, pipe, transaction,
+                                         CVMX_USB_COMPLETE_BABBLEERR);
        } else if (usbc_hcint.s.datatglerr) {
                /* Data toggle error */
-               __cvmx_usb_perform_complete(usb, pipe, transaction,
-                                           CVMX_USB_COMPLETE_DATATGLERR);
+               cvmx_usb_perform_complete(usb, pipe, transaction,
+                                         CVMX_USB_COMPLETE_DATATGLERR);
        } else if (usbc_hcint.s.nyet) {
                /*
                 * NYET as a response is only allowed in three cases: as a
@@ -2829,7 +2663,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                 * as a response to a bulk out. The ping case is handled by
                 * hardware, so we only have splits and bulk out
                 */
-               if (!__cvmx_usb_pipe_needs_split(usb, pipe)) {
+               if (!cvmx_usb_pipe_needs_split(usb, pipe)) {
                        transaction->retries = 0;
                        /*
                         * If there is more data to go then we need to try
@@ -2837,7 +2671,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                         */
                        if ((buffer_space_left == 0) ||
                                (bytes_in_last_packet < pipe->max_packet))
-                               __cvmx_usb_perform_complete(usb, pipe,
+                               cvmx_usb_perform_complete(usb, pipe,
                                                transaction,
                                                CVMX_USB_COMPLETE_SUCCESS);
                } else {
@@ -2869,7 +2703,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                 * Since we got an ACK, we know we don't need to do a ping on
                 * this pipe
                 */
-               pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_NEED_PING;
+               pipe->flags &= ~CVMX_USB_PIPE_FLAGS_NEED_PING;
 
                switch (transaction->type) {
                case CVMX_USB_TRANSFER_CONTROL:
@@ -2877,12 +2711,12 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                        case CVMX_USB_STAGE_NON_CONTROL:
                        case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
                                /* This should be impossible */
-                               __cvmx_usb_perform_complete(usb, pipe,
+                               cvmx_usb_perform_complete(usb, pipe,
                                        transaction, CVMX_USB_COMPLETE_ERROR);
                                break;
                        case CVMX_USB_STAGE_SETUP:
                                pipe->pid_toggle = 1;
-                               if (__cvmx_usb_pipe_needs_split(usb, pipe))
+                               if (cvmx_usb_pipe_needs_split(usb, pipe))
                                        transaction->stage =
                                                CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE;
                                else {
@@ -2909,7 +2743,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                                }
                                break;
                        case CVMX_USB_STAGE_DATA:
-                               if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+                               if (cvmx_usb_pipe_needs_split(usb, pipe)) {
                                        transaction->stage =
                                                CVMX_USB_STAGE_DATA_SPLIT_COMPLETE;
                                        /*
@@ -2947,16 +2781,16 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                                }
                                break;
                        case CVMX_USB_STAGE_STATUS:
-                               if (__cvmx_usb_pipe_needs_split(usb, pipe))
+                               if (cvmx_usb_pipe_needs_split(usb, pipe))
                                        transaction->stage =
                                                CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE;
                                else
-                                       __cvmx_usb_perform_complete(usb, pipe,
+                                       cvmx_usb_perform_complete(usb, pipe,
                                                transaction,
                                                CVMX_USB_COMPLETE_SUCCESS);
                                break;
                        case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
-                               __cvmx_usb_perform_complete(usb, pipe,
+                               cvmx_usb_perform_complete(usb, pipe,
                                                transaction,
                                                CVMX_USB_COMPLETE_SUCCESS);
                                break;
@@ -2970,7 +2804,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                         * For splits we need to continue the transfer if more
                         * data is needed
                         */
-                       if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+                       if (cvmx_usb_pipe_needs_split(usb, pipe)) {
                                if (transaction->stage ==
                                                CVMX_USB_STAGE_NON_CONTROL)
                                        transaction->stage =
@@ -2986,7 +2820,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                                                        CVMX_USB_TRANSFER_INTERRUPT)
                                                        pipe->next_tx_frame +=
                                                                pipe->interval;
-                                                       __cvmx_usb_perform_complete(
+                                                       cvmx_usb_perform_complete(
                                                                usb,
                                                                pipe,
                                                                transaction,
@@ -3002,7 +2836,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                                     CVMX_USB_DIRECTION_OUT) &&
                                    (usbc_hcint.s.nak))
                                        pipe->flags |=
-                                               __CVMX_USB_PIPE_FLAGS_NEED_PING;
+                                               CVMX_USB_PIPE_FLAGS_NEED_PING;
                                if (!buffer_space_left ||
                                        (bytes_in_last_packet <
                                         pipe->max_packet)) {
@@ -3010,15 +2844,14 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                                                CVMX_USB_TRANSFER_INTERRUPT)
                                                pipe->next_tx_frame +=
                                                        pipe->interval;
-                                       __cvmx_usb_perform_complete(usb,
-                                               pipe,
+                                       cvmx_usb_perform_complete(usb, pipe,
                                                transaction,
                                                CVMX_USB_COMPLETE_SUCCESS);
                                }
                        }
                        break;
                case CVMX_USB_TRANSFER_ISOCHRONOUS:
-                       if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+                       if (cvmx_usb_pipe_needs_split(usb, pipe)) {
                                /*
                                 * ISOCHRONOUS OUT splits don't require a
                                 * complete split stage. Instead they use a
@@ -3039,10 +2872,8 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                                                (bytes_this_transfer < 188)) {
                                                pipe->next_tx_frame +=
                                                        pipe->interval;
-                                               __cvmx_usb_perform_complete(
-                                                       usb,
-                                                       pipe,
-                                                       transaction,
+                                               cvmx_usb_perform_complete(usb,
+                                                       pipe, transaction,
                                                        CVMX_USB_COMPLETE_SUCCESS);
                                        }
                                } else {
@@ -3059,7 +2890,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                                                         pipe->max_packet)) {
                                                        pipe->next_tx_frame +=
                                                                pipe->interval;
-                                                       __cvmx_usb_perform_complete(
+                                                       cvmx_usb_perform_complete(
                                                                usb,
                                                                pipe,
                                                                transaction,
@@ -3071,8 +2902,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                                }
                        } else {
                                pipe->next_tx_frame += pipe->interval;
-                               __cvmx_usb_perform_complete(usb,
-                                               pipe,
+                               cvmx_usb_perform_complete(usb, pipe,
                                                transaction,
                                                CVMX_USB_COMPLETE_SUCCESS);
                        }
@@ -3110,7 +2940,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
                         * We get channel halted interrupts with no result bits
                         * sets when the cable is unplugged
                         */
-                       __cvmx_usb_perform_complete(usb, pipe, transaction,
+                       cvmx_usb_perform_complete(usb, pipe, transaction,
                                        CVMX_USB_COMPLETE_ERROR);
                }
        }
@@ -3144,21 +2974,19 @@ static int cvmx_usb_poll(struct cvmx_usb_state *usb)
        prefetch_range(usb, sizeof(*usb));
 
        /* Update the frame counter */
-       usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb,
-                                               CVMX_USBCX_HFNUM(usb->index));
+       usbc_hfnum.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index));
        if ((usb->frame_number&0x3fff) > usbc_hfnum.s.frnum)
                usb->frame_number += 0x4000;
        usb->frame_number &= ~0x3fffull;
        usb->frame_number |= usbc_hfnum.s.frnum;
 
        /* Read the pending interrupts */
-       usbc_gintsts.u32 = __cvmx_usb_read_csr32(usb,
-                                               CVMX_USBCX_GINTSTS(usb->index));
+       usbc_gintsts.u32 = cvmx_usb_read_csr32(usb,
+                                              CVMX_USBCX_GINTSTS(usb->index));
 
        /* Clear the interrupts now that we know about them */
-       __cvmx_usb_write_csr32(usb,
-                               CVMX_USBCX_GINTSTS(usb->index),
-                               usbc_gintsts.u32);
+       cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index),
+                            usbc_gintsts.u32);
 
        if (usbc_gintsts.s.rxflvl) {
                /*
@@ -3169,12 +2997,12 @@ static int cvmx_usb_poll(struct cvmx_usb_state *usb)
                 * In DMA mode this is handled by hardware
                 */
                if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-                       __cvmx_usb_poll_rx_fifo(usb);
+                       cvmx_usb_poll_rx_fifo(usb);
        }
        if (usbc_gintsts.s.ptxfemp || usbc_gintsts.s.nptxfemp) {
                /* Fill the Tx FIFOs when not in DMA mode */
                if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-                       __cvmx_usb_poll_tx_fifo(usb);
+                       cvmx_usb_poll_tx_fifo(usb);
        }
        if (usbc_gintsts.s.disconnint || usbc_gintsts.s.prtint) {
                union cvmx_usbcx_hprt usbc_hprt;
@@ -3194,11 +3022,11 @@ static int cvmx_usb_poll(struct cvmx_usb_state *usb)
                 */
                octeon_usb_port_callback(usb);
                /* Clear the port change bits */
-               usbc_hprt.u32 = __cvmx_usb_read_csr32(usb,
-                               CVMX_USBCX_HPRT(usb->index));
+               usbc_hprt.u32 = cvmx_usb_read_csr32(usb,
+                                       CVMX_USBCX_HPRT(usb->index));
                usbc_hprt.s.prtena = 0;
-               __cvmx_usb_write_csr32(usb, CVMX_USBCX_HPRT(usb->index),
-                                      usbc_hprt.u32);
+               cvmx_usb_write_csr32(usb, CVMX_USBCX_HPRT(usb->index),
+                                    usbc_hprt.u32);
        }
        if (usbc_gintsts.s.hchint) {
                /*
@@ -3215,18 +3043,18 @@ static int cvmx_usb_poll(struct cvmx_usb_state *usb)
                 */
                union cvmx_usbcx_haint usbc_haint;
 
-               usbc_haint.u32 = __cvmx_usb_read_csr32(usb,
+               usbc_haint.u32 = cvmx_usb_read_csr32(usb,
                                        CVMX_USBCX_HAINT(usb->index));
                while (usbc_haint.u32) {
                        int channel;
 
                        channel = __fls(usbc_haint.u32);
-                       __cvmx_usb_poll_channel(usb, channel);
+                       cvmx_usb_poll_channel(usb, channel);
                        usbc_haint.u32 ^= 1<<channel;
                }
        }
 
-       __cvmx_usb_schedule(usb, usbc_gintsts.s.sof);
+       cvmx_usb_schedule(usb, usbc_gintsts.s.sof);
 
        return 0;
 }
@@ -3510,6 +3338,7 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
        struct octeon_hcd *priv = hcd_to_octeon(hcd);
        struct device *dev = hcd->self.controller;
        struct cvmx_usb_port_status usb_port_status;
+       struct cvmx_usb_state *usb = &priv->usb;
        int port_status;
        struct usb_hub_descriptor *desc;
        unsigned long flags;
@@ -3687,13 +3516,18 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        return -EINVAL;
                case USB_PORT_FEAT_POWER:
                        dev_dbg(dev, " POWER\n");
-                       return -EINVAL;
+                       /*
+                        * Program the port power bit to drive VBUS on the USB.
+                        */
+                       spin_lock_irqsave(&priv->lock, flags);
+                       USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index),
+                                       cvmx_usbcx_hprt, prtpwr, 1);
+                       spin_unlock_irqrestore(&priv->lock, flags);
+                       return 0;
                case USB_PORT_FEAT_RESET:
                        dev_dbg(dev, " RESET\n");
                        spin_lock_irqsave(&priv->lock, flags);
-                       cvmx_usb_disable(&priv->usb);
-                       if (cvmx_usb_enable(&priv->usb))
-                               dev_dbg(dev, "Failed to enable the port\n");
+                       cvmx_usb_reset_port(&priv->usb);
                        spin_unlock_irqrestore(&priv->lock, flags);
                        return 0;
                case USB_PORT_FEAT_INDICATOR:
@@ -3741,7 +3575,6 @@ static int octeon_usb_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct octeon_hcd *priv;
        struct usb_hcd *hcd;
-       unsigned long flags;
        u32 clock_rate = 48000000;
        bool is_crystal_clock = false;
        const char *clock_type;
@@ -3838,20 +3671,33 @@ static int octeon_usb_probe(struct platform_device *pdev)
 
        spin_lock_init(&priv->lock);
 
-       status = cvmx_usb_initialize(&priv->usb, usb_num, initialize_flags);
+       priv->usb.init_flags = initialize_flags;
+
+       /* Initialize the USB state structure */
+       priv->usb.index = usb_num;
+       INIT_LIST_HEAD(&priv->usb.idle_pipes);
+       for (i = 0; i < ARRAY_SIZE(priv->usb.active_pipes); i++)
+               INIT_LIST_HEAD(&priv->usb.active_pipes[i]);
+
+       /* Due to an errata, CN31XX doesn't support DMA */
+       if (OCTEON_IS_MODEL(OCTEON_CN31XX)) {
+               priv->usb.init_flags |= CVMX_USB_INITIALIZE_FLAGS_NO_DMA;
+               /* Only use one channel with non DMA */
+               priv->usb.idle_hardware_channels = 0x1;
+       } else if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) {
+               /* CN5XXX have an errata with channel 3 */
+               priv->usb.idle_hardware_channels = 0xf7;
+       } else {
+               priv->usb.idle_hardware_channels = 0xff;
+       }
+
+       status = cvmx_usb_initialize(dev, &priv->usb);
        if (status) {
                dev_dbg(dev, "USB initialization failed with %d\n", status);
                kfree(hcd);
                return -1;
        }
 
-       /* This delay is needed for CN3010, but I don't know why... */
-       mdelay(10);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       cvmx_usb_poll(&priv->usb);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
        status = usb_add_hcd(hcd, irq, 0);
        if (status) {
                dev_dbg(dev, "USB add HCD failed with %d\n", status);
@@ -3885,7 +3731,7 @@ static int octeon_usb_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id octeon_usb_match[] = {
+static const struct of_device_id octeon_usb_match[] = {
        {
                .compatible = "cavium,octeon-5750-usbc",
        },
index 42fe4fec7d5d842e697283d86a97289a63513605..3e351ab7465acef075cf0861debc952ef4897371 100644 (file)
@@ -47,6 +47,8 @@
 #ifndef __OCTEON_HCD_H__
 #define __OCTEON_HCD_H__
 
+#include <asm/bitfield.h>
+
 #define CVMX_USBCXBASE 0x00016F0010000000ull
 #define CVMX_USBCXREG1(reg, bid) \
        (CVMX_ADD_IO_SEG(CVMX_USBCXBASE | reg) + \
@@ -143,13 +145,14 @@ union cvmx_usbcx_gahbcfg {
         *      * 1'b1: Unmask the interrupt assertion to the application.
         */
        struct cvmx_usbcx_gahbcfg_s {
-               uint32_t reserved_9_31  : 23;
-               uint32_t ptxfemplvl     : 1;
-               uint32_t nptxfemplvl    : 1;
-               uint32_t reserved_6_6   : 1;
-               uint32_t dmaen          : 1;
-               uint32_t hbstlen        : 4;
-               uint32_t glblintrmsk    : 1;
+               __BITFIELD_FIELD(uint32_t reserved_9_31 : 23,
+               __BITFIELD_FIELD(uint32_t ptxfemplvl    : 1,
+               __BITFIELD_FIELD(uint32_t nptxfemplvl   : 1,
+               __BITFIELD_FIELD(uint32_t reserved_6_6  : 1,
+               __BITFIELD_FIELD(uint32_t dmaen         : 1,
+               __BITFIELD_FIELD(uint32_t hbstlen       : 4,
+               __BITFIELD_FIELD(uint32_t glblintrmsk   : 1,
+               ;)))))))
        } s;
 };
 
@@ -209,16 +212,17 @@ union cvmx_usbcx_ghwcfg3 {
         *      * Others: Reserved
         */
        struct cvmx_usbcx_ghwcfg3_s {
-               uint32_t dfifodepth                             : 16;
-               uint32_t reserved_13_15                         : 3;
-               uint32_t ahbphysync                             : 1;
-               uint32_t rsttype                                : 1;
-               uint32_t optfeature                             : 1;
-               uint32_t vendor_control_interface_support       : 1;
-               uint32_t i2c_selection                          : 1;
-               uint32_t otgen                                  : 1;
-               uint32_t pktsizewidth                           : 3;
-               uint32_t xfersizewidth                          : 4;
+               __BITFIELD_FIELD(uint32_t dfifodepth                    : 16,
+               __BITFIELD_FIELD(uint32_t reserved_13_15                : 3,
+               __BITFIELD_FIELD(uint32_t ahbphysync                    : 1,
+               __BITFIELD_FIELD(uint32_t rsttype                       : 1,
+               __BITFIELD_FIELD(uint32_t optfeature                    : 1,
+               __BITFIELD_FIELD(uint32_t vendor_control_interface_support : 1,
+               __BITFIELD_FIELD(uint32_t i2c_selection                 : 1,
+               __BITFIELD_FIELD(uint32_t otgen                         : 1,
+               __BITFIELD_FIELD(uint32_t pktsizewidth                  : 3,
+               __BITFIELD_FIELD(uint32_t xfersizewidth                 : 4,
+               ;))))))))))
        } s;
 };
 
@@ -275,38 +279,39 @@ union cvmx_usbcx_gintmsk {
         * @modemismsk: Mode Mismatch Interrupt Mask (ModeMisMsk)
         */
        struct cvmx_usbcx_gintmsk_s {
-               uint32_t wkupintmsk             : 1;
-               uint32_t sessreqintmsk          : 1;
-               uint32_t disconnintmsk          : 1;
-               uint32_t conidstschngmsk        : 1;
-               uint32_t reserved_27_27         : 1;
-               uint32_t ptxfempmsk             : 1;
-               uint32_t hchintmsk              : 1;
-               uint32_t prtintmsk              : 1;
-               uint32_t reserved_23_23         : 1;
-               uint32_t fetsuspmsk             : 1;
-               uint32_t incomplpmsk            : 1;
-               uint32_t incompisoinmsk         : 1;
-               uint32_t oepintmsk              : 1;
-               uint32_t inepintmsk             : 1;
-               uint32_t epmismsk               : 1;
-               uint32_t reserved_16_16         : 1;
-               uint32_t eopfmsk                : 1;
-               uint32_t isooutdropmsk          : 1;
-               uint32_t enumdonemsk            : 1;
-               uint32_t usbrstmsk              : 1;
-               uint32_t usbsuspmsk             : 1;
-               uint32_t erlysuspmsk            : 1;
-               uint32_t i2cint                 : 1;
-               uint32_t ulpickintmsk           : 1;
-               uint32_t goutnakeffmsk          : 1;
-               uint32_t ginnakeffmsk           : 1;
-               uint32_t nptxfempmsk            : 1;
-               uint32_t rxflvlmsk              : 1;
-               uint32_t sofmsk                 : 1;
-               uint32_t otgintmsk              : 1;
-               uint32_t modemismsk             : 1;
-               uint32_t reserved_0_0           : 1;
+               __BITFIELD_FIELD(uint32_t wkupintmsk            : 1,
+               __BITFIELD_FIELD(uint32_t sessreqintmsk         : 1,
+               __BITFIELD_FIELD(uint32_t disconnintmsk         : 1,
+               __BITFIELD_FIELD(uint32_t conidstschngmsk       : 1,
+               __BITFIELD_FIELD(uint32_t reserved_27_27        : 1,
+               __BITFIELD_FIELD(uint32_t ptxfempmsk            : 1,
+               __BITFIELD_FIELD(uint32_t hchintmsk             : 1,
+               __BITFIELD_FIELD(uint32_t prtintmsk             : 1,
+               __BITFIELD_FIELD(uint32_t reserved_23_23        : 1,
+               __BITFIELD_FIELD(uint32_t fetsuspmsk            : 1,
+               __BITFIELD_FIELD(uint32_t incomplpmsk           : 1,
+               __BITFIELD_FIELD(uint32_t incompisoinmsk        : 1,
+               __BITFIELD_FIELD(uint32_t oepintmsk             : 1,
+               __BITFIELD_FIELD(uint32_t inepintmsk            : 1,
+               __BITFIELD_FIELD(uint32_t epmismsk              : 1,
+               __BITFIELD_FIELD(uint32_t reserved_16_16        : 1,
+               __BITFIELD_FIELD(uint32_t eopfmsk               : 1,
+               __BITFIELD_FIELD(uint32_t isooutdropmsk         : 1,
+               __BITFIELD_FIELD(uint32_t enumdonemsk           : 1,
+               __BITFIELD_FIELD(uint32_t usbrstmsk             : 1,
+               __BITFIELD_FIELD(uint32_t usbsuspmsk            : 1,
+               __BITFIELD_FIELD(uint32_t erlysuspmsk           : 1,
+               __BITFIELD_FIELD(uint32_t i2cint                : 1,
+               __BITFIELD_FIELD(uint32_t ulpickintmsk          : 1,
+               __BITFIELD_FIELD(uint32_t goutnakeffmsk         : 1,
+               __BITFIELD_FIELD(uint32_t ginnakeffmsk          : 1,
+               __BITFIELD_FIELD(uint32_t nptxfempmsk           : 1,
+               __BITFIELD_FIELD(uint32_t rxflvlmsk             : 1,
+               __BITFIELD_FIELD(uint32_t sofmsk                : 1,
+               __BITFIELD_FIELD(uint32_t otgintmsk             : 1,
+               __BITFIELD_FIELD(uint32_t modemismsk            : 1,
+               __BITFIELD_FIELD(uint32_t reserved_0_0          : 1,
+               ;))))))))))))))))))))))))))))))))
        } s;
 };
 
@@ -504,38 +509,39 @@ union cvmx_usbcx_gintsts {
         *      * 1'b1: Host mode
         */
        struct cvmx_usbcx_gintsts_s {
-               uint32_t wkupint        : 1;
-               uint32_t sessreqint     : 1;
-               uint32_t disconnint     : 1;
-               uint32_t conidstschng   : 1;
-               uint32_t reserved_27_27 : 1;
-               uint32_t ptxfemp        : 1;
-               uint32_t hchint         : 1;
-               uint32_t prtint         : 1;
-               uint32_t reserved_23_23 : 1;
-               uint32_t fetsusp        : 1;
-               uint32_t incomplp       : 1;
-               uint32_t incompisoin    : 1;
-               uint32_t oepint         : 1;
-               uint32_t iepint         : 1;
-               uint32_t epmis          : 1;
-               uint32_t reserved_16_16 : 1;
-               uint32_t eopf           : 1;
-               uint32_t isooutdrop     : 1;
-               uint32_t enumdone       : 1;
-               uint32_t usbrst         : 1;
-               uint32_t usbsusp        : 1;
-               uint32_t erlysusp       : 1;
-               uint32_t i2cint         : 1;
-               uint32_t ulpickint      : 1;
-               uint32_t goutnakeff     : 1;
-               uint32_t ginnakeff      : 1;
-               uint32_t nptxfemp       : 1;
-               uint32_t rxflvl         : 1;
-               uint32_t sof            : 1;
-               uint32_t otgint         : 1;
-               uint32_t modemis        : 1;
-               uint32_t curmod         : 1;
+               __BITFIELD_FIELD(uint32_t wkupint               : 1,
+               __BITFIELD_FIELD(uint32_t sessreqint            : 1,
+               __BITFIELD_FIELD(uint32_t disconnint            : 1,
+               __BITFIELD_FIELD(uint32_t conidstschng          : 1,
+               __BITFIELD_FIELD(uint32_t reserved_27_27        : 1,
+               __BITFIELD_FIELD(uint32_t ptxfemp               : 1,
+               __BITFIELD_FIELD(uint32_t hchint                : 1,
+               __BITFIELD_FIELD(uint32_t prtint                : 1,
+               __BITFIELD_FIELD(uint32_t reserved_23_23        : 1,
+               __BITFIELD_FIELD(uint32_t fetsusp               : 1,
+               __BITFIELD_FIELD(uint32_t incomplp              : 1,
+               __BITFIELD_FIELD(uint32_t incompisoin           : 1,
+               __BITFIELD_FIELD(uint32_t oepint                : 1,
+               __BITFIELD_FIELD(uint32_t iepint                : 1,
+               __BITFIELD_FIELD(uint32_t epmis                 : 1,
+               __BITFIELD_FIELD(uint32_t reserved_16_16        : 1,
+               __BITFIELD_FIELD(uint32_t eopf                  : 1,
+               __BITFIELD_FIELD(uint32_t isooutdrop            : 1,
+               __BITFIELD_FIELD(uint32_t enumdone              : 1,
+               __BITFIELD_FIELD(uint32_t usbrst                : 1,
+               __BITFIELD_FIELD(uint32_t usbsusp               : 1,
+               __BITFIELD_FIELD(uint32_t erlysusp              : 1,
+               __BITFIELD_FIELD(uint32_t i2cint                : 1,
+               __BITFIELD_FIELD(uint32_t ulpickint             : 1,
+               __BITFIELD_FIELD(uint32_t goutnakeff            : 1,
+               __BITFIELD_FIELD(uint32_t ginnakeff             : 1,
+               __BITFIELD_FIELD(uint32_t nptxfemp              : 1,
+               __BITFIELD_FIELD(uint32_t rxflvl                : 1,
+               __BITFIELD_FIELD(uint32_t sof                   : 1,
+               __BITFIELD_FIELD(uint32_t otgint                : 1,
+               __BITFIELD_FIELD(uint32_t modemis               : 1,
+               __BITFIELD_FIELD(uint32_t curmod                : 1,
+               ;))))))))))))))))))))))))))))))))
        } s;
 };
 
@@ -560,8 +566,9 @@ union cvmx_usbcx_gnptxfsiz {
         *      Transmit FIFO RAM.
         */
        struct cvmx_usbcx_gnptxfsiz_s {
-               uint32_t nptxfdep       : 16;
-               uint32_t nptxfstaddr    : 16;
+               __BITFIELD_FIELD(uint32_t nptxfdep      : 16,
+               __BITFIELD_FIELD(uint32_t nptxfstaddr   : 16,
+               ;))
        } s;
 };
 
@@ -610,10 +617,11 @@ union cvmx_usbcx_gnptxsts {
         *      * Others: Reserved
         */
        struct cvmx_usbcx_gnptxsts_s {
-               uint32_t reserved_31_31 : 1;
-               uint32_t nptxqtop       : 7;
-               uint32_t nptxqspcavail  : 8;
-               uint32_t nptxfspcavail  : 16;
+               __BITFIELD_FIELD(uint32_t reserved_31_31        : 1,
+               __BITFIELD_FIELD(uint32_t nptxqtop              : 7,
+               __BITFIELD_FIELD(uint32_t nptxqspcavail         : 8,
+               __BITFIELD_FIELD(uint32_t nptxfspcavail         : 16,
+               ;))))
        } s;
 };
 
@@ -731,16 +739,17 @@ union cvmx_usbcx_grstctl {
         *      selected, the PHY domain has to be reset for proper operation.
         */
        struct cvmx_usbcx_grstctl_s {
-               uint32_t ahbidle        : 1;
-               uint32_t dmareq         : 1;
-               uint32_t reserved_11_29 : 19;
-               uint32_t txfnum         : 5;
-               uint32_t txfflsh        : 1;
-               uint32_t rxfflsh        : 1;
-               uint32_t intknqflsh     : 1;
-               uint32_t frmcntrrst     : 1;
-               uint32_t hsftrst        : 1;
-               uint32_t csftrst        : 1;
+               __BITFIELD_FIELD(uint32_t ahbidle               : 1,
+               __BITFIELD_FIELD(uint32_t dmareq                : 1,
+               __BITFIELD_FIELD(uint32_t reserved_11_29        : 19,
+               __BITFIELD_FIELD(uint32_t txfnum                : 5,
+               __BITFIELD_FIELD(uint32_t txfflsh               : 1,
+               __BITFIELD_FIELD(uint32_t rxfflsh               : 1,
+               __BITFIELD_FIELD(uint32_t intknqflsh            : 1,
+               __BITFIELD_FIELD(uint32_t frmcntrrst            : 1,
+               __BITFIELD_FIELD(uint32_t hsftrst               : 1,
+               __BITFIELD_FIELD(uint32_t csftrst               : 1,
+               ;))))))))))
        } s;
 };
 
@@ -762,8 +771,9 @@ union cvmx_usbcx_grxfsiz {
         *      * Maximum value is 32768
         */
        struct cvmx_usbcx_grxfsiz_s {
-               uint32_t reserved_16_31 : 16;
-               uint32_t rxfdep         : 16;
+               __BITFIELD_FIELD(uint32_t reserved_16_31        : 16,
+               __BITFIELD_FIELD(uint32_t rxfdep                : 16,
+               ;))
        } s;
 };
 
@@ -804,11 +814,12 @@ union cvmx_usbcx_grxstsph {
         *      packet belongs.
         */
        struct cvmx_usbcx_grxstsph_s {
-               uint32_t reserved_21_31 : 11;
-               uint32_t pktsts         : 4;
-               uint32_t dpid           : 2;
-               uint32_t bcnt           : 11;
-               uint32_t chnum          : 4;
+               __BITFIELD_FIELD(uint32_t reserved_21_31        : 11,
+               __BITFIELD_FIELD(uint32_t pktsts                : 4,
+               __BITFIELD_FIELD(uint32_t dpid                  : 2,
+               __BITFIELD_FIELD(uint32_t bcnt                  : 11,
+               __BITFIELD_FIELD(uint32_t chnum                 : 4,
+               ;)))))
        } s;
 };
 
@@ -884,19 +895,20 @@ union cvmx_usbcx_gusbcfg {
         *      * One 48-MHz PHY clock = 0.25 bit times
         */
        struct cvmx_usbcx_gusbcfg_s {
-               uint32_t reserved_17_31 : 15;
-               uint32_t otgi2csel      : 1;
-               uint32_t phylpwrclksel  : 1;
-               uint32_t reserved_14_14 : 1;
-               uint32_t usbtrdtim      : 4;
-               uint32_t hnpcap         : 1;
-               uint32_t srpcap         : 1;
-               uint32_t ddrsel         : 1;
-               uint32_t physel         : 1;
-               uint32_t fsintf         : 1;
-               uint32_t ulpi_utmi_sel  : 1;
-               uint32_t phyif          : 1;
-               uint32_t toutcal        : 3;
+               __BITFIELD_FIELD(uint32_t reserved_17_31        : 15,
+               __BITFIELD_FIELD(uint32_t otgi2csel             : 1,
+               __BITFIELD_FIELD(uint32_t phylpwrclksel         : 1,
+               __BITFIELD_FIELD(uint32_t reserved_14_14        : 1,
+               __BITFIELD_FIELD(uint32_t usbtrdtim             : 4,
+               __BITFIELD_FIELD(uint32_t hnpcap                : 1,
+               __BITFIELD_FIELD(uint32_t srpcap                : 1,
+               __BITFIELD_FIELD(uint32_t ddrsel                : 1,
+               __BITFIELD_FIELD(uint32_t physel                : 1,
+               __BITFIELD_FIELD(uint32_t fsintf                : 1,
+               __BITFIELD_FIELD(uint32_t ulpi_utmi_sel         : 1,
+               __BITFIELD_FIELD(uint32_t phyif                 : 1,
+               __BITFIELD_FIELD(uint32_t toutcal               : 3,
+               ;)))))))))))))
        } s;
 };
 
@@ -920,8 +932,9 @@ union cvmx_usbcx_haint {
         *      One bit per channel: Bit 0 for Channel 0, bit 15 for Channel 15
         */
        struct cvmx_usbcx_haint_s {
-               uint32_t reserved_16_31 : 16;
-               uint32_t haint          : 16;
+               __BITFIELD_FIELD(uint32_t reserved_16_31        : 16,
+               __BITFIELD_FIELD(uint32_t haint                 : 16,
+               ;))
        } s;
 };
 
@@ -944,8 +957,9 @@ union cvmx_usbcx_haintmsk {
         *      One bit per channel: Bit 0 for channel 0, bit 15 for channel 15
         */
        struct cvmx_usbcx_haintmsk_s {
-               uint32_t reserved_16_31 : 16;
-               uint32_t haintmsk       : 16;
+               __BITFIELD_FIELD(uint32_t reserved_16_31        : 16,
+               __BITFIELD_FIELD(uint32_t haintmsk              : 16,
+               ;))
        } s;
 };
 
@@ -1014,17 +1028,18 @@ union cvmx_usbcx_hccharx {
         *      Indicates the maximum packet size of the associated endpoint.
         */
        struct cvmx_usbcx_hccharx_s {
-               uint32_t chena          : 1;
-               uint32_t chdis          : 1;
-               uint32_t oddfrm         : 1;
-               uint32_t devaddr        : 7;
-               uint32_t ec             : 2;
-               uint32_t eptype         : 2;
-               uint32_t lspddev        : 1;
-               uint32_t reserved_16_16 : 1;
-               uint32_t epdir          : 1;
-               uint32_t epnum          : 4;
-               uint32_t mps            : 11;
+               __BITFIELD_FIELD(uint32_t chena                 : 1,
+               __BITFIELD_FIELD(uint32_t chdis                 : 1,
+               __BITFIELD_FIELD(uint32_t oddfrm                : 1,
+               __BITFIELD_FIELD(uint32_t devaddr               : 7,
+               __BITFIELD_FIELD(uint32_t ec                    : 2,
+               __BITFIELD_FIELD(uint32_t eptype                : 2,
+               __BITFIELD_FIELD(uint32_t lspddev               : 1,
+               __BITFIELD_FIELD(uint32_t reserved_16_16        : 1,
+               __BITFIELD_FIELD(uint32_t epdir                 : 1,
+               __BITFIELD_FIELD(uint32_t epnum                 : 4,
+               __BITFIELD_FIELD(uint32_t mps                   : 11,
+               ;)))))))))))
        } s;
 };
 
@@ -1069,9 +1084,10 @@ union cvmx_usbcx_hcfg {
         *      * 2'b11: Reserved
         */
        struct cvmx_usbcx_hcfg_s {
-               uint32_t reserved_3_31  : 29;
-               uint32_t fslssupp       : 1;
-               uint32_t fslspclksel    : 2;
+               __BITFIELD_FIELD(uint32_t reserved_3_31 : 29,
+               __BITFIELD_FIELD(uint32_t fslssupp      : 1,
+               __BITFIELD_FIELD(uint32_t fslspclksel   : 2,
+               ;)))
        } s;
 };
 
@@ -1110,18 +1126,19 @@ union cvmx_usbcx_hcintx {
         *      Transfer completed normally without any errors.
         */
        struct cvmx_usbcx_hcintx_s {
-               uint32_t reserved_11_31 : 21;
-               uint32_t datatglerr     : 1;
-               uint32_t frmovrun       : 1;
-               uint32_t bblerr         : 1;
-               uint32_t xacterr        : 1;
-               uint32_t nyet           : 1;
-               uint32_t ack            : 1;
-               uint32_t nak            : 1;
-               uint32_t stall          : 1;
-               uint32_t ahberr         : 1;
-               uint32_t chhltd         : 1;
-               uint32_t xfercompl      : 1;
+               __BITFIELD_FIELD(uint32_t reserved_11_31        : 21,
+               __BITFIELD_FIELD(uint32_t datatglerr            : 1,
+               __BITFIELD_FIELD(uint32_t frmovrun              : 1,
+               __BITFIELD_FIELD(uint32_t bblerr                : 1,
+               __BITFIELD_FIELD(uint32_t xacterr               : 1,
+               __BITFIELD_FIELD(uint32_t nyet                  : 1,
+               __BITFIELD_FIELD(uint32_t ack                   : 1,
+               __BITFIELD_FIELD(uint32_t nak                   : 1,
+               __BITFIELD_FIELD(uint32_t stall                 : 1,
+               __BITFIELD_FIELD(uint32_t ahberr                : 1,
+               __BITFIELD_FIELD(uint32_t chhltd                : 1,
+               __BITFIELD_FIELD(uint32_t xfercompl             : 1,
+               ;))))))))))))
        } s;
 };
 
@@ -1151,18 +1168,19 @@ union cvmx_usbcx_hcintmskx {
         * @xfercomplmsk: Transfer Completed Mask (XferComplMsk)
         */
        struct cvmx_usbcx_hcintmskx_s {
-               uint32_t reserved_11_31 : 21;
-               uint32_t datatglerrmsk  : 1;
-               uint32_t frmovrunmsk    : 1;
-               uint32_t bblerrmsk      : 1;
-               uint32_t xacterrmsk     : 1;
-               uint32_t nyetmsk        : 1;
-               uint32_t ackmsk         : 1;
-               uint32_t nakmsk         : 1;
-               uint32_t stallmsk       : 1;
-               uint32_t ahberrmsk      : 1;
-               uint32_t chhltdmsk      : 1;
-               uint32_t xfercomplmsk   : 1;
+               __BITFIELD_FIELD(uint32_t reserved_11_31                : 21,
+               __BITFIELD_FIELD(uint32_t datatglerrmsk                 : 1,
+               __BITFIELD_FIELD(uint32_t frmovrunmsk                   : 1,
+               __BITFIELD_FIELD(uint32_t bblerrmsk                     : 1,
+               __BITFIELD_FIELD(uint32_t xacterrmsk                    : 1,
+               __BITFIELD_FIELD(uint32_t nyetmsk                       : 1,
+               __BITFIELD_FIELD(uint32_t ackmsk                        : 1,
+               __BITFIELD_FIELD(uint32_t nakmsk                        : 1,
+               __BITFIELD_FIELD(uint32_t stallmsk                      : 1,
+               __BITFIELD_FIELD(uint32_t ahberrmsk                     : 1,
+               __BITFIELD_FIELD(uint32_t chhltdmsk                     : 1,
+               __BITFIELD_FIELD(uint32_t xfercomplmsk                  : 1,
+               ;))))))))))))
        } s;
 };
 
@@ -1201,12 +1219,13 @@ union cvmx_usbcx_hcspltx {
         *      translator.
         */
        struct cvmx_usbcx_hcspltx_s {
-               uint32_t spltena        : 1;
-               uint32_t reserved_17_30 : 14;
-               uint32_t compsplt       : 1;
-               uint32_t xactpos        : 2;
-               uint32_t hubaddr        : 7;
-               uint32_t prtaddr        : 7;
+               __BITFIELD_FIELD(uint32_t spltena                       : 1,
+               __BITFIELD_FIELD(uint32_t reserved_17_30                : 14,
+               __BITFIELD_FIELD(uint32_t compsplt                      : 1,
+               __BITFIELD_FIELD(uint32_t xactpos                       : 2,
+               __BITFIELD_FIELD(uint32_t hubaddr                       : 7,
+               __BITFIELD_FIELD(uint32_t prtaddr                       : 7,
+               ;))))))
        } s;
 };
 
@@ -1246,10 +1265,11 @@ union cvmx_usbcx_hctsizx {
         *      size for IN transactions (periodic and non-periodic).
         */
        struct cvmx_usbcx_hctsizx_s {
-               uint32_t dopng          : 1;
-               uint32_t pid            : 2;
-               uint32_t pktcnt         : 10;
-               uint32_t xfersize       : 19;
+               __BITFIELD_FIELD(uint32_t dopng                 : 1,
+               __BITFIELD_FIELD(uint32_t pid                   : 2,
+               __BITFIELD_FIELD(uint32_t pktcnt                : 10,
+               __BITFIELD_FIELD(uint32_t xfersize              : 19,
+               ;))))
        } s;
 };
 
@@ -1283,8 +1303,9 @@ union cvmx_usbcx_hfir {
         *      * 1 ms (PHY clock frequency for FS/LS)
         */
        struct cvmx_usbcx_hfir_s {
-               uint32_t reserved_16_31 : 16;
-               uint32_t frint          : 16;
+               __BITFIELD_FIELD(uint32_t reserved_16_31                : 16,
+               __BITFIELD_FIELD(uint32_t frint                         : 16,
+               ;))
        } s;
 };
 
@@ -1312,8 +1333,9 @@ union cvmx_usbcx_hfnum {
         *      USB, and is reset to 0 when it reaches 16'h3FFF.
         */
        struct cvmx_usbcx_hfnum_s {
-               uint32_t frrem  : 16;
-               uint32_t frnum  : 16;
+               __BITFIELD_FIELD(uint32_t frrem         : 16,
+               __BITFIELD_FIELD(uint32_t frnum         : 16,
+               ;))
        } s;
 };
 
@@ -1439,21 +1461,22 @@ union cvmx_usbcx_hprt {
         *      * 1: A device is attached to the port.
         */
        struct cvmx_usbcx_hprt_s {
-               uint32_t reserved_19_31 : 13;
-               uint32_t prtspd         : 2;
-               uint32_t prttstctl      : 4;
-               uint32_t prtpwr         : 1;
-               uint32_t prtlnsts       : 2;
-               uint32_t reserved_9_9   : 1;
-               uint32_t prtrst         : 1;
-               uint32_t prtsusp        : 1;
-               uint32_t prtres         : 1;
-               uint32_t prtovrcurrchng : 1;
-               uint32_t prtovrcurract  : 1;
-               uint32_t prtenchng      : 1;
-               uint32_t prtena         : 1;
-               uint32_t prtconndet     : 1;
-               uint32_t prtconnsts     : 1;
+               __BITFIELD_FIELD(uint32_t reserved_19_31        : 13,
+               __BITFIELD_FIELD(uint32_t prtspd                : 2,
+               __BITFIELD_FIELD(uint32_t prttstctl             : 4,
+               __BITFIELD_FIELD(uint32_t prtpwr                : 1,
+               __BITFIELD_FIELD(uint32_t prtlnsts              : 2,
+               __BITFIELD_FIELD(uint32_t reserved_9_9          : 1,
+               __BITFIELD_FIELD(uint32_t prtrst                : 1,
+               __BITFIELD_FIELD(uint32_t prtsusp               : 1,
+               __BITFIELD_FIELD(uint32_t prtres                : 1,
+               __BITFIELD_FIELD(uint32_t prtovrcurrchng        : 1,
+               __BITFIELD_FIELD(uint32_t prtovrcurract         : 1,
+               __BITFIELD_FIELD(uint32_t prtenchng             : 1,
+               __BITFIELD_FIELD(uint32_t prtena                : 1,
+               __BITFIELD_FIELD(uint32_t prtconndet            : 1,
+               __BITFIELD_FIELD(uint32_t prtconnsts            : 1,
+               ;)))))))))))))))
        } s;
 };
 
@@ -1476,8 +1499,9 @@ union cvmx_usbcx_hptxfsiz {
         * @ptxfstaddr: Host Periodic TxFIFO Start Address (PTxFStAddr)
         */
        struct cvmx_usbcx_hptxfsiz_s {
-               uint32_t ptxfsize       : 16;
-               uint32_t ptxfstaddr     : 16;
+               __BITFIELD_FIELD(uint32_t ptxfsize      : 16,
+               __BITFIELD_FIELD(uint32_t ptxfstaddr    : 16,
+               ;))
        } s;
 };
 
@@ -1531,9 +1555,10 @@ union cvmx_usbcx_hptxsts {
         *      * Others: Reserved
         */
        struct cvmx_usbcx_hptxsts_s {
-               uint32_t ptxqtop        : 8;
-               uint32_t ptxqspcavail   : 8;
-               uint32_t ptxfspcavail   : 16;
+               __BITFIELD_FIELD(uint32_t ptxqtop       : 8,
+               __BITFIELD_FIELD(uint32_t ptxqspcavail  : 8,
+               __BITFIELD_FIELD(uint32_t ptxfspcavail  : 16,
+               ;)))
        } s;
 };
 
@@ -1636,21 +1661,22 @@ union cvmx_usbnx_clk_ctl {
         *      until AFTER this field is set and then read.
         */
        struct cvmx_usbnx_clk_ctl_s {
-               uint64_t reserved_20_63 : 44;
-               uint64_t divide2        : 2;
-               uint64_t hclk_rst       : 1;
-               uint64_t p_x_on         : 1;
-               uint64_t p_rtype        : 2;
-               uint64_t p_com_on       : 1;
-               uint64_t p_c_sel        : 2;
-               uint64_t cdiv_byp       : 1;
-               uint64_t sd_mode        : 2;
-               uint64_t s_bist         : 1;
-               uint64_t por            : 1;
-               uint64_t enable         : 1;
-               uint64_t prst           : 1;
-               uint64_t hrst           : 1;
-               uint64_t divide         : 3;
+               __BITFIELD_FIELD(uint64_t reserved_20_63        : 44,
+               __BITFIELD_FIELD(uint64_t divide2               : 2,
+               __BITFIELD_FIELD(uint64_t hclk_rst              : 1,
+               __BITFIELD_FIELD(uint64_t p_x_on                : 1,
+               __BITFIELD_FIELD(uint64_t p_rtype               : 2,
+               __BITFIELD_FIELD(uint64_t p_com_on              : 1,
+               __BITFIELD_FIELD(uint64_t p_c_sel               : 2,
+               __BITFIELD_FIELD(uint64_t cdiv_byp              : 1,
+               __BITFIELD_FIELD(uint64_t sd_mode               : 2,
+               __BITFIELD_FIELD(uint64_t s_bist                : 1,
+               __BITFIELD_FIELD(uint64_t por                   : 1,
+               __BITFIELD_FIELD(uint64_t enable                : 1,
+               __BITFIELD_FIELD(uint64_t prst                  : 1,
+               __BITFIELD_FIELD(uint64_t hrst                  : 1,
+               __BITFIELD_FIELD(uint64_t divide                : 3,
+               ;)))))))))))))))
        } s;
 };
 
@@ -1778,41 +1804,42 @@ union cvmx_usbnx_usbp_ctl_status {
         *      de-assertion.
         */
        struct cvmx_usbnx_usbp_ctl_status_s {
-               uint64_t txrisetune             : 1;
-               uint64_t txvreftune             : 4;
-               uint64_t txfslstune             : 4;
-               uint64_t txhsxvtune             : 2;
-               uint64_t sqrxtune               : 3;
-               uint64_t compdistune            : 3;
-               uint64_t otgtune                : 3;
-               uint64_t otgdisable             : 1;
-               uint64_t portreset              : 1;
-               uint64_t drvvbus                : 1;
-               uint64_t lsbist                 : 1;
-               uint64_t fsbist                 : 1;
-               uint64_t hsbist                 : 1;
-               uint64_t bist_done              : 1;
-               uint64_t bist_err               : 1;
-               uint64_t tdata_out              : 4;
-               uint64_t siddq                  : 1;
-               uint64_t txpreemphasistune      : 1;
-               uint64_t dma_bmode              : 1;
-               uint64_t usbc_end               : 1;
-               uint64_t usbp_bist              : 1;
-               uint64_t tclk                   : 1;
-               uint64_t dp_pulld               : 1;
-               uint64_t dm_pulld               : 1;
-               uint64_t hst_mode               : 1;
-               uint64_t tuning                 : 4;
-               uint64_t tx_bs_enh              : 1;
-               uint64_t tx_bs_en               : 1;
-               uint64_t loop_enb               : 1;
-               uint64_t vtest_enb              : 1;
-               uint64_t bist_enb               : 1;
-               uint64_t tdata_sel              : 1;
-               uint64_t taddr_in               : 4;
-               uint64_t tdata_in               : 8;
-               uint64_t ate_reset              : 1;
+               __BITFIELD_FIELD(uint64_t txrisetune            : 1,
+               __BITFIELD_FIELD(uint64_t txvreftune            : 4,
+               __BITFIELD_FIELD(uint64_t txfslstune            : 4,
+               __BITFIELD_FIELD(uint64_t txhsxvtune            : 2,
+               __BITFIELD_FIELD(uint64_t sqrxtune              : 3,
+               __BITFIELD_FIELD(uint64_t compdistune           : 3,
+               __BITFIELD_FIELD(uint64_t otgtune               : 3,
+               __BITFIELD_FIELD(uint64_t otgdisable            : 1,
+               __BITFIELD_FIELD(uint64_t portreset             : 1,
+               __BITFIELD_FIELD(uint64_t drvvbus               : 1,
+               __BITFIELD_FIELD(uint64_t lsbist                : 1,
+               __BITFIELD_FIELD(uint64_t fsbist                : 1,
+               __BITFIELD_FIELD(uint64_t hsbist                : 1,
+               __BITFIELD_FIELD(uint64_t bist_done             : 1,
+               __BITFIELD_FIELD(uint64_t bist_err              : 1,
+               __BITFIELD_FIELD(uint64_t tdata_out             : 4,
+               __BITFIELD_FIELD(uint64_t siddq                 : 1,
+               __BITFIELD_FIELD(uint64_t txpreemphasistune     : 1,
+               __BITFIELD_FIELD(uint64_t dma_bmode             : 1,
+               __BITFIELD_FIELD(uint64_t usbc_end              : 1,
+               __BITFIELD_FIELD(uint64_t usbp_bist             : 1,
+               __BITFIELD_FIELD(uint64_t tclk                  : 1,
+               __BITFIELD_FIELD(uint64_t dp_pulld              : 1,
+               __BITFIELD_FIELD(uint64_t dm_pulld              : 1,
+               __BITFIELD_FIELD(uint64_t hst_mode              : 1,
+               __BITFIELD_FIELD(uint64_t tuning                : 4,
+               __BITFIELD_FIELD(uint64_t tx_bs_enh             : 1,
+               __BITFIELD_FIELD(uint64_t tx_bs_en              : 1,
+               __BITFIELD_FIELD(uint64_t loop_enb              : 1,
+               __BITFIELD_FIELD(uint64_t vtest_enb             : 1,
+               __BITFIELD_FIELD(uint64_t bist_enb              : 1,
+               __BITFIELD_FIELD(uint64_t tdata_sel             : 1,
+               __BITFIELD_FIELD(uint64_t taddr_in              : 4,
+               __BITFIELD_FIELD(uint64_t tdata_in              : 8,
+               __BITFIELD_FIELD(uint64_t ate_reset             : 1,
+               ;)))))))))))))))))))))))))))))))))))
        } s;
 };
 
index ebfa9c9e71b1580e629ab00e09475db1f3b47b00..40dab11e5333829092d32e5988ccae3d686ac5e3 100644 (file)
@@ -130,19 +130,6 @@ static void cvm_oct_note_carrier(struct octeon_ethernet *priv,
        }
 }
 
-void cvm_oct_set_carrier(struct octeon_ethernet *priv,
-                        cvmx_helper_link_info_t link_info)
-{
-       cvm_oct_note_carrier(priv, link_info);
-       if (link_info.s.link_up) {
-               if (!netif_carrier_ok(priv->netdev))
-                       netif_carrier_on(priv->netdev);
-       } else {
-               if (netif_carrier_ok(priv->netdev))
-                       netif_carrier_off(priv->netdev);
-       }
-}
-
 void cvm_oct_adjust_link(struct net_device *dev)
 {
        struct octeon_ethernet *priv = netdev_priv(dev);
index eccfcc54cea8e907c74c117903e982c7067c4691..6191b0850646062e47c205734e0b884277da42c6 100644 (file)
@@ -40,5 +40,8 @@
 #endif /* CONFIG_XFRM */
 
 extern const struct ethtool_ops cvm_oct_ethtool_ops;
+
+extern 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 460e8545904fe174dc21cb68e81f9b22b0cd5e75..f539d82f2f111683c76c0ed0c0e18a9dc58bfdec 100644 (file)
@@ -573,8 +573,6 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = {
 #endif
 };
 
-extern void octeon_mdiobus_force_mod_depencency(void);
-
 static struct device_node *cvm_oct_of_get_child(
                                const struct device_node *parent, int reg_val)
 {
@@ -859,7 +857,7 @@ static int cvm_oct_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id cvm_oct_match[] = {
+static const struct of_device_id cvm_oct_match[] = {
        {
                .compatible = "cavium,octeon-3860-pip",
        },
index bc7e664cc8a7fffdeb761bf6e2dce41ca7201807..d115f5c0e3415dcb8f6084fdcc0636522550501c 100644 (file)
@@ -18,8 +18,6 @@
 #include <linux/console.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/module.h>
index 8543bb29a138c232748c0bd13f2811a5ba494e99..5ff4716b72c311485084005b9e09a36021157530 100644 (file)
@@ -280,17 +280,20 @@ static void oz_free_urb_link(struct oz_urb_link *urbl)
  */
 static struct oz_endpoint *oz_ep_alloc(int buffer_size, gfp_t mem_flags)
 {
-       struct oz_endpoint *ep =
-               kzalloc(sizeof(struct oz_endpoint)+buffer_size, mem_flags);
-       if (ep) {
-               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);
-               }
+       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;
 }
 
index 7d6ef4cadf1a5f6f03465ae4cca73b6ce0e0bc9f..74ef34815b985df4d3650c0eabfce1dfe6d4794f 100644 (file)
@@ -34,11 +34,21 @@ MODULE_PARM_DESC(g_net_dev, "The device(s) to bind to; "
  */
 static int __init ozwpan_init(void)
 {
-       oz_cdev_register();
-       oz_protocol_init(g_net_dev);
+       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;
 }
 
 /*
index 852c288aaf13132398263c3c3d24b49627a29892..021d74a132ddf5f4e16512321c44ac0afa88f25a 100644 (file)
@@ -102,34 +102,36 @@ void oz_pd_put(struct oz_pd *pd)
  */
 struct oz_pd *oz_pd_alloc(const u8 *mac_addr)
 {
-       struct oz_pd *pd = kzalloc(sizeof(struct oz_pd), GFP_ATOMIC);
-
-       if (pd) {
-               int i;
-
-               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;
-       }
+       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;
 }
 
@@ -652,8 +654,9 @@ static struct oz_isoc_stream *pd_stream_find(struct oz_pd *pd, u8 ep_num)
  */
 int oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num)
 {
-       struct oz_isoc_stream *st =
-               kzalloc(sizeof(struct oz_isoc_stream), GFP_ATOMIC);
+       struct oz_isoc_stream *st;
+
+       st = kzalloc(sizeof(struct oz_isoc_stream), GFP_ATOMIC);
        if (!st)
                return -ENOMEM;
        st->ep_num = ep_num;
index 3d3a3a890f73341206bc64527cbecd9e82720b24..1ba24a2aef835bca872f892b9d2a70c2c7a1d674 100644 (file)
@@ -98,7 +98,7 @@ static void oz_send_conn_rsp(struct oz_pd *pd, u8 status)
                kfree_skb(skb);
                return;
        }
-       oz_hdr->control = (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT);
+       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;
index 6ed35b6ecf0d1a3bf2795d4dd5d01678aa365bf7..ea54fb4ec837ea737653fc77fff786d2d38e7d2a 100644 (file)
@@ -335,11 +335,11 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES];
  * LCD types
  */
 #define LCD_TYPE_NONE          0
-#define LCD_TYPE_OLD           1
-#define LCD_TYPE_KS0074                2
-#define LCD_TYPE_HANTRONIX     3
-#define LCD_TYPE_NEXCOM                4
-#define LCD_TYPE_CUSTOM                5
+#define LCD_TYPE_CUSTOM                1
+#define LCD_TYPE_OLD           2
+#define LCD_TYPE_KS0074                3
+#define LCD_TYPE_HANTRONIX     4
+#define LCD_TYPE_NEXCOM                5
 
 /*
  * keypad types
@@ -473,8 +473,6 @@ static struct pardevice *pprt;
 
 static int keypad_initialized;
 
-static char init_in_progress;
-
 static void (*lcd_write_cmd)(int);
 static void (*lcd_write_data)(int);
 static void (*lcd_clear_fast)(void);
@@ -502,7 +500,7 @@ MODULE_PARM_DESC(keypad_type,
 static int lcd_type = NOT_SET;
 module_param(lcd_type, int, 0000);
 MODULE_PARM_DESC(lcd_type,
-                "LCD type: 0=none, 1=old //, 2=serial ks0074, 3=hantronix //, 4=nexcom //, 5=compiled-in");
+                "LCD type: 0=none, 1=compiled-in, 2=old, 3=serial ks0074, 4=hantronix, 5=nexcom");
 
 static int lcd_height = NOT_SET;
 module_param(lcd_height, int, 0000);
@@ -1718,9 +1716,6 @@ static struct miscdevice keypad_dev = {
 
 static void keypad_send_key(const char *string, int max_len)
 {
-       if (init_in_progress)
-               return;
-
        /* send the key to the device only if a process is attached to it. */
        if (!atomic_read(&keypad_available)) {
                while (max_len-- && keypad_buflen < KEYPAD_BUFFER && *string) {
@@ -2010,10 +2005,8 @@ static void init_scan_timer(void)
        if (scan_timer.function != NULL)
                return;         /* already started */
 
-       init_timer(&scan_timer);
+       setup_timer(&scan_timer, (void *)&panel_scan_timer, 0);
        scan_timer.expires = jiffies + INPUT_POLL_TIME;
-       scan_timer.data = 0;
-       scan_timer.function = (void *)&panel_scan_timer;
        add_timer(&scan_timer);
 }
 
@@ -2236,6 +2229,7 @@ static void panel_attach(struct parport *port)
                if (misc_register(&keypad_dev))
                        goto err_lcd_unreg;
        }
+       register_reboot_notifier(&panel_notifier);
        return;
 
 err_lcd_unreg:
@@ -2257,6 +2251,8 @@ static void panel_detach(struct parport *port)
                return;
        }
 
+       unregister_reboot_notifier(&panel_notifier);
+
        if (keypad.enabled && keypad_initialized) {
                misc_deregister(&keypad_dev);
                keypad_initialized = 0;
@@ -2281,7 +2277,7 @@ static struct parport_driver panel_driver = {
 /* init function */
 static int __init panel_init_module(void)
 {
-       int selected_keypad_type = NOT_SET;
+       int selected_keypad_type = NOT_SET, err;
 
        /* take care of an eventual profile */
        switch (profile) {
@@ -2323,26 +2319,6 @@ static int __init panel_init_module(void)
                break;
        }
 
-       /*
-        * Init lcd struct with load-time values to preserve exact current
-        * functionality (at least for now).
-        */
-       lcd.height = lcd_height;
-       lcd.width = lcd_width;
-       lcd.bwidth = lcd_bwidth;
-       lcd.hwidth = lcd_hwidth;
-       lcd.charset = lcd_charset;
-       lcd.proto = lcd_proto;
-       lcd.pins.e = lcd_e_pin;
-       lcd.pins.rs = lcd_rs_pin;
-       lcd.pins.rw = lcd_rw_pin;
-       lcd.pins.cl = lcd_cl_pin;
-       lcd.pins.da = lcd_da_pin;
-       lcd.pins.bl = lcd_bl_pin;
-
-       /* Leave it for now, just in case */
-       lcd.esc_seq.len = -1;
-
        /*
         * Overwrite selection with module param values (both keypad and lcd),
         * where the deprecated params have lower prio.
@@ -2361,6 +2337,28 @@ static int __init panel_init_module(void)
 
        lcd.enabled = (selected_lcd_type > 0);
 
+       if (lcd.enabled) {
+               /*
+                * Init lcd struct with load-time values to preserve exact
+                * current functionality (at least for now).
+                */
+               lcd.height = lcd_height;
+               lcd.width = lcd_width;
+               lcd.bwidth = lcd_bwidth;
+               lcd.hwidth = lcd_hwidth;
+               lcd.charset = lcd_charset;
+               lcd.proto = lcd_proto;
+               lcd.pins.e = lcd_e_pin;
+               lcd.pins.rs = lcd_rs_pin;
+               lcd.pins.rw = lcd_rw_pin;
+               lcd.pins.cl = lcd_cl_pin;
+               lcd.pins.da = lcd_da_pin;
+               lcd.pins.bl = lcd_bl_pin;
+
+               /* Leave it for now, just in case */
+               lcd.esc_seq.len = -1;
+       }
+
        switch (selected_keypad_type) {
        case KEYPAD_TYPE_OLD:
                keypad_profile = old_keypad_profile;
@@ -2376,27 +2374,17 @@ static int __init panel_init_module(void)
                break;
        }
 
-       /* tells various subsystems about the fact that we are initializing */
-       init_in_progress = 1;
-
-       if (parport_register_driver(&panel_driver)) {
-               pr_err("could not register with parport. Aborting.\n");
-               return -EIO;
-       }
-
        if (!lcd.enabled && !keypad.enabled) {
-               /* no device enabled, let's release the parport */
-               if (pprt) {
-                       parport_release(pprt);
-                       parport_unregister_device(pprt);
-                       pprt = NULL;
-               }
-               parport_unregister_driver(&panel_driver);
+               /* no device enabled, let's exit */
                pr_err("driver version " PANEL_VERSION " disabled.\n");
                return -ENODEV;
        }
 
-       register_reboot_notifier(&panel_notifier);
+       err = parport_register_driver(&panel_driver);
+       if (err) {
+               pr_err("could not register with parport. Aborting.\n");
+               return err;
+       }
 
        if (pprt)
                pr_info("driver version " PANEL_VERSION
@@ -2405,15 +2393,11 @@ static int __init panel_init_module(void)
        else
                pr_info("driver version " PANEL_VERSION
                        " not yet registered\n");
-       /* tells various subsystems about the fact that initialization
-          is finished */
-       init_in_progress = 0;
        return 0;
 }
 
 static void __exit panel_cleanup_module(void)
 {
-       unregister_reboot_notifier(&panel_notifier);
 
        if (scan_timer.function != NULL)
                del_timer_sync(&scan_timer);
index da19145c49c576146851306d44a629d838ba8558..e65ee6e858a8b15455bdd646d9fc5e5ba169f712 100644 (file)
@@ -23,6 +23,7 @@
 #include <drv_types.h>
 #include <wifi.h>
 #include <ieee80211.h>
+#include <asm/unaligned.h>
 
 #ifdef CONFIG_88EU_AP_MODE
 
@@ -78,11 +79,8 @@ static void update_BCNTIM(struct adapter *padapter)
        if (true) {
                u8 *p, *dst_ie, *premainder_ie = NULL;
                u8 *pbackup_remainder_ie = NULL;
-               __le16 tim_bitmap_le;
                uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
 
-               tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);
-
                p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
                if (p != NULL && tim_ielen > 0) {
                        tim_ielen += 2;
@@ -137,9 +135,9 @@ static void update_BCNTIM(struct adapter *padapter)
                        *dst_ie++ = 0;
 
                if (tim_ielen == 4) {
-                       *dst_ie++ = *(u8 *)&tim_bitmap_le;
+                       *dst_ie++ = pstapriv->tim_bitmap & 0xff;
                } else if (tim_ielen == 5) {
-                       memcpy(dst_ie, &tim_bitmap_le, 2);
+                       put_unaligned_le16(pstapriv->tim_bitmap, dst_ie);
                        dst_ie += 2;
                }
 
index 4b43462449538e4fabf837d2c8b7dda850eca885..89b5e48ed68a08fe313406b0b189ab8e999b954c 100644 (file)
@@ -325,7 +325,8 @@ u8 rtw_sitesurvey_cmd(struct adapter  *padapter, struct ndis_802_11_ssid *ssid,
        if (res == _SUCCESS) {
                pmlmepriv->scan_start_time = jiffies;
 
-               _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT);
+               mod_timer(&pmlmepriv->scan_to_timer,
+                         jiffies + msecs_to_jiffies(SCANNING_TIMEOUT));
 
                rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
 
@@ -1234,9 +1235,11 @@ void rtw_survey_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
        if (pcmd->res == H2C_DROPPED) {
                /* TODO: cancel timer and do timeout handler directly... */
                /* need to make timeout handlerOS independent */
-               _set_timer(&pmlmepriv->scan_to_timer, 1);
+               mod_timer(&pmlmepriv->scan_to_timer,
+                         jiffies + msecs_to_jiffies(1));
        } else if (pcmd->res != H2C_SUCCESS) {
-               _set_timer(&pmlmepriv->scan_to_timer, 1);
+               mod_timer(&pmlmepriv->scan_to_timer,
+                         jiffies + msecs_to_jiffies(1));
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n."));
        }
 
@@ -1270,10 +1273,12 @@ void rtw_joinbss_cmd_callback(struct adapter *padapter,  struct cmd_obj *pcmd)
        if (pcmd->res == H2C_DROPPED) {
                /* TODO: cancel timer and do timeout handler directly... */
                /* need to make timeout handlerOS independent */
-               _set_timer(&pmlmepriv->assoc_timer, 1);
+               mod_timer(&pmlmepriv->assoc_timer,
+                         jiffies + msecs_to_jiffies(1));
        } else if (pcmd->res != H2C_SUCCESS) {
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("********Error:rtw_select_and_join_from_scanned_queue Wait Sema  Fail ************\n"));
-               _set_timer(&pmlmepriv->assoc_timer, 1);
+               mod_timer(&pmlmepriv->assoc_timer,
+                         jiffies + msecs_to_jiffies(1));
        }
 
        rtw_free_cmd_obj(pcmd);
@@ -1291,7 +1296,8 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
 
        if (pcmd->res != H2C_SUCCESS) {
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: rtw_createbss_cmd_callback  Fail ************\n\n."));
-               _set_timer(&pmlmepriv->assoc_timer, 1);
+               mod_timer(&pmlmepriv->assoc_timer,
+                         jiffies + msecs_to_jiffies(1));
        }
 
        del_timer_sync(&pmlmepriv->assoc_timer);
index 8816d116a8b8d641032602c23eaf0ffe8f70e9b9..b66746160223ab51823836ffa0fc8510e321c240 100644 (file)
@@ -139,7 +139,7 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8  *pbuf)
        while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
                /*  Check PG header for section num. */
                if ((rtemp8 & 0x1F) == 0x0F) {          /* extended header */
-                       u1temp = ((rtemp8 & 0xE0) >> 5);
+                       u1temp = (rtemp8 & 0xE0) >> 5;
                        rtemp8 = *(phymap+eFuse_Addr);
                        if ((rtemp8 & 0x0F) == 0x0F) {
                                eFuse_Addr++;
@@ -150,12 +150,12 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8  *pbuf)
                                continue;
                        } else {
                                offset = ((rtemp8 & 0xF0) >> 1) | u1temp;
-                               wren = (rtemp8 & 0x0F);
+                               wren = rtemp8 & 0x0F;
                                eFuse_Addr++;
                        }
                } else {
-                       offset = ((rtemp8 >> 4) & 0x0f);
-                       wren = (rtemp8 & 0x0f);
+                       offset = (rtemp8 >> 4) & 0x0f;
+                       wren = rtemp8 & 0x0f;
                }
 
                if (offset < EFUSE_MAX_SECTION_88E) {
index f2c3ca79c0c93026f142635028e6802d166e9976..11b780d6c4ab6bbea68e8ccdb60ba1ba800840b2 100644 (file)
@@ -27,7 +27,6 @@
 #include <wlan_bssdef.h>
 
 u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
-u16 RTW_WPA_VERSION = 1;
 u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 };
 u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 };
 u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 };
@@ -663,7 +662,7 @@ int rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie,
 
        /* Search required WPA or WPA2 IE and copy to sec_ie[] */
 
-       cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
+       cnt = _TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_;
 
        sec_idx = 0;
 
@@ -789,7 +788,7 @@ u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
  *
  * Returns: the address of the specific WPS attribute found, or NULL
  */
-u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id , u8 *buf_attr, u32 *len_attr)
+u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_attr, u32 *len_attr)
 {
        u8 *attr_ptr = NULL;
        u8 *target_attr_ptr = NULL;
@@ -799,7 +798,7 @@ u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id , u8 *buf_at
                *len_attr = 0;
 
        if ((wps_ie[0] != _VENDOR_SPECIFIC_IE_) ||
-           (memcmp(wps_ie + 2, wps_oui , 4)))
+           (memcmp(wps_ie + 2, wps_oui, 4)))
                return attr_ptr;
 
        /*  6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
@@ -835,7 +834,7 @@ u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id , u8 *buf_at
  *
  * Returns: the address of the specific WPS attribute content found, or NULL
  */
-u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id , u8 *buf_content, uint *len_content)
+u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_content, uint *len_content)
 {
        u8 *attr_ptr;
        u32 attr_len;
@@ -1239,7 +1238,7 @@ void rtw_get_bcn_info(struct wlan_network *pnetwork)
        } else {
                pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
        }
-       rtw_get_sec_ie(pnetwork->network.IEs , pnetwork->network.IELength, NULL, &rsn_len, NULL, &wpa_len);
+       rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &rsn_len, NULL, &wpa_len);
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: ssid =%s\n", pnetwork->network.Ssid.Ssid));
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len));
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: ssid =%s\n", pnetwork->network.Ssid.Ssid));
index 2faf6b2e812915ace02727b5b8cd702fff52611d..969150a48661344387dbf16e840f9c7adfceaf03 100644 (file)
@@ -86,7 +86,8 @@ u8 rtw_do_join(struct adapter *padapter)
                select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
                if (select_ret == _SUCCESS) {
                        pmlmepriv->to_join = false;
-                       _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
+                       mod_timer(&pmlmepriv->assoc_timer,
+                                 jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
                } else {
                        if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
                                /*  submit createbss_cmd to change to a ADHOC_MASTER */
index 1b8264b978da2e22d9ba93025cb45d4a87ae0e5d..94405dc44220f6f7a53a2486b23bbb6665bdb0da 100644 (file)
@@ -22,9 +22,9 @@
 /*             Callback function of LED BlinkTimer, */
 /*             it just schedules to corresponding BlinkWorkItem/led_blink_hdl */
 /*  */
-void BlinkTimerCallback(void *data)
+void BlinkTimerCallback(unsigned long data)
 {
-       struct LED_871x *pLed = data;
+       struct LED_871x *pLed = (struct LED_871x *)data;
        struct adapter *padapter = pLed->padapter;
 
        if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
@@ -72,7 +72,8 @@ void InitLed871x(struct adapter *padapter, struct LED_871x *pLed)
 
        ResetLedStatus(pLed);
 
-       _init_timer(&(pLed->BlinkTimer), padapter->pnetdev, BlinkTimerCallback, pLed);
+       setup_timer(&(pLed->BlinkTimer), BlinkTimerCallback,
+                   (unsigned long)pLed);
 
        INIT_WORK(&(pLed->BlinkWorkItem), BlinkWorkItemCallback);
 }
@@ -122,14 +123,16 @@ static void SwLedBlink1(struct LED_871x *pLed)
                        pLed->BlinkingLedState = RTW_LED_OFF;
                else
                        pLed->BlinkingLedState = RTW_LED_ON;
-               _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                break;
        case LED_BLINK_NORMAL:
                if (pLed->bLedOn)
                        pLed->BlinkingLedState = RTW_LED_OFF;
                else
                        pLed->BlinkingLedState = RTW_LED_ON;
-               _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
                break;
        case LED_BLINK_SCAN:
                pLed->BlinkTimes--;
@@ -143,7 +146,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                        pLed->BlinkingLedState = RTW_LED_OFF;
                                else
                                        pLed->BlinkingLedState = RTW_LED_ON;
-                               _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
                                RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
                        } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
                                pLed->bLedNoLinkBlinkInProgress = true;
@@ -152,7 +156,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                        pLed->BlinkingLedState = RTW_LED_OFF;
                                else
                                        pLed->BlinkingLedState = RTW_LED_ON;
-                               _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                                RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
                        }
                        pLed->bLedScanBlinkInProgress = false;
@@ -161,7 +166,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                pLed->BlinkingLedState = RTW_LED_OFF;
                        else
                                pLed->BlinkingLedState = RTW_LED_ON;
-                       _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                }
                break;
        case LED_BLINK_TXRX:
@@ -176,7 +182,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                        pLed->BlinkingLedState = RTW_LED_OFF;
                                else
                                        pLed->BlinkingLedState = RTW_LED_ON;
-                               _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
                                RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
                        } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
                                pLed->bLedNoLinkBlinkInProgress = true;
@@ -185,7 +192,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                        pLed->BlinkingLedState = RTW_LED_OFF;
                                else
                                        pLed->BlinkingLedState = RTW_LED_ON;
-                               _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                                RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
                        }
                        pLed->BlinkTimes = 0;
@@ -195,7 +203,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                pLed->BlinkingLedState = RTW_LED_OFF;
                        else
                                pLed->BlinkingLedState = RTW_LED_ON;
-                       _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
        case LED_BLINK_WPS:
@@ -203,7 +212,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                        pLed->BlinkingLedState = RTW_LED_OFF;
                else
                        pLed->BlinkingLedState = RTW_LED_ON;
-               _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                break;
        case LED_BLINK_WPS_STOP:        /* WPS success */
                if (pLed->BlinkingLedState == RTW_LED_ON)
@@ -218,14 +228,15 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                pLed->BlinkingLedState = RTW_LED_OFF;
                        else
                                pLed->BlinkingLedState = RTW_LED_ON;
-                       _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
                        RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
 
                        pLed->bLedWPSBlinkInProgress = false;
                } else {
                        pLed->BlinkingLedState = RTW_LED_OFF;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
                }
                break;
        default:
@@ -262,7 +273,8 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct
                                pLed->BlinkingLedState = RTW_LED_OFF;
                        else
                                pLed->BlinkingLedState = RTW_LED_ON;
-                       _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_LINK:
@@ -283,7 +295,8 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct
                                pLed->BlinkingLedState = RTW_LED_OFF;
                        else
                                pLed->BlinkingLedState = RTW_LED_ON;
-                       _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_SITE_SURVEY:
@@ -311,7 +324,8 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct
                                pLed->BlinkingLedState = RTW_LED_OFF;
                        else
                                pLed->BlinkingLedState = RTW_LED_ON;
-                       _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                 }
                break;
        case LED_CTL_TX:
@@ -334,7 +348,8 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct
                                pLed->BlinkingLedState = RTW_LED_OFF;
                        else
                                pLed->BlinkingLedState = RTW_LED_ON;
-                       _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_START_WPS: /* wait until xinpin finish */
@@ -362,7 +377,8 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct
                                pLed->BlinkingLedState = RTW_LED_OFF;
                        else
                                pLed->BlinkingLedState = RTW_LED_ON;
-                       _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                 }
                break;
        case LED_CTL_STOP_WPS:
@@ -389,11 +405,12 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct
                pLed->CurrLedState = LED_BLINK_WPS_STOP;
                if (pLed->bLedOn) {
                        pLed->BlinkingLedState = RTW_LED_OFF;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
                } else {
                        pLed->BlinkingLedState = RTW_LED_ON;
-                       _set_timer(&(pLed->BlinkTimer), 0);
+                       mod_timer(&pLed->BlinkTimer,
+                                 jiffies + msecs_to_jiffies(0));
                }
                break;
        case LED_CTL_STOP_WPS_FAIL:
@@ -407,7 +424,8 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct
                        pLed->BlinkingLedState = RTW_LED_OFF;
                else
                        pLed->BlinkingLedState = RTW_LED_ON;
-               _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                break;
        case LED_CTL_POWER_OFF:
                pLed->CurrLedState = RTW_LED_OFF;
index d4632da50c1dd460306840576e99c299b6248be0..6c91aa58d924dc316022d9c7549490f176c27260 100644 (file)
@@ -665,7 +665,8 @@ void rtw_surveydone_event_callback(struct adapter   *adapter, u8 *pbuf)
                                set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 
                                if (rtw_select_and_join_from_scanned_queue(pmlmepriv) == _SUCCESS) {
-                                       _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
+                                       mod_timer(&pmlmepriv->assoc_timer,
+                                                 jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
                                } else {
                                        struct wlan_bssid_ex    *pdev_network = &(adapter->registrypriv.dev_network);
                                        u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
@@ -692,7 +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) {
-                            _set_timer(&pmlmepriv->assoc_timer, 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);
@@ -1127,14 +1129,16 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
 
        } else if (pnetwork->join_res == -4) {
                rtw_reset_securitypriv(adapter);
-               _set_timer(&pmlmepriv->assoc_timer, 1);
+               mod_timer(&pmlmepriv->assoc_timer,
+                         jiffies + msecs_to_jiffies(1));
 
                if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == true) {
                        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("fail! clear _FW_UNDER_LINKING ^^^fw_state=%x\n", get_fwstate(pmlmepriv)));
                        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
                }
        } else { /* if join_res < 0 (join fails), then try again */
-               _set_timer(&pmlmepriv->assoc_timer, 1);
+               mod_timer(&pmlmepriv->assoc_timer,
+                         jiffies + msecs_to_jiffies(1));
                _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
        }
 
@@ -1360,9 +1364,9 @@ void rtw_cpwm_event_callback(struct adapter *padapter, u8 *pbuf)
 * _rtw_join_timeout_handler - Timeout/faliure handler for CMD JoinBss
 * @adapter: pointer to struct adapter structure
 */
-void _rtw_join_timeout_handler (void *function_context)
+void _rtw_join_timeout_handler (unsigned long data)
 {
-       struct adapter *adapter = function_context;
+       struct adapter *adapter = (struct adapter *)data;
        struct  mlme_priv *pmlmepriv = &adapter->mlmepriv;
        int do_join_r;
 
@@ -1402,9 +1406,9 @@ void _rtw_join_timeout_handler (void *function_context)
 * rtw_scan_timeout_handler - Timeout/Faliure handler for CMD SiteSurvey
 * @adapter: pointer to struct adapter structure
 */
-void rtw_scan_timeout_handler (void *function_context)
+void rtw_scan_timeout_handler (unsigned long data)
 {
-       struct adapter *adapter = function_context;
+       struct adapter *adapter = (struct adapter *)data;
        struct  mlme_priv *pmlmepriv = &adapter->mlmepriv;
 
        DBG_88E(FUNC_ADPT_FMT" fw_state=%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
@@ -1429,9 +1433,9 @@ static void rtw_auto_scan_handler(struct adapter *padapter)
        }
 }
 
-void rtw_dynamic_check_timer_handlder(void *function_context)
+void rtw_dynamic_check_timer_handlder(unsigned long data)
 {
-       struct adapter *adapter = (struct adapter *)function_context;
+       struct adapter *adapter = (struct adapter *)data;
        struct registry_priv *pregistrypriv = &adapter->registrypriv;
 
        if (!adapter)
@@ -1449,7 +1453,8 @@ void rtw_dynamic_check_timer_handlder(void *function_context)
                rtw_auto_scan_handler(adapter);
        }
 exit:
-       _set_timer(&adapter->mlmepriv.dynamic_chk_timer, 2000);
+       mod_timer(&adapter->mlmepriv.dynamic_chk_timer,
+                 jiffies + msecs_to_jiffies(2000));
 }
 
 #define RTW_SCAN_RESULT_EXPIRE 2000
@@ -2037,7 +2042,7 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len)
        p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fixed_ie), _HT_CAPABILITY_IE_, &len, ie_len-sizeof(struct ndis_802_11_fixed_ie));
        if (p && len > 0) {
                pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);
-               max_ampdu_sz = (pht_capie->ampdu_params_info & IEEE80211_HT_CAP_AMPDU_FACTOR);
+               max_ampdu_sz = pht_capie->ampdu_params_info & IEEE80211_HT_CAP_AMPDU_FACTOR;
                max_ampdu_sz = 1 << (max_ampdu_sz+3); /*  max_ampdu_sz (kbytes); */
                phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
        }
index cd12dd70dd8804065c42e4e587a644fa8b474aee..be9e34a0daef836baa7330fe92c2a8379052dc19 100644 (file)
@@ -1639,7 +1639,7 @@ unsigned int OnAction_back(struct adapter *padapter, struct recv_frame *precv_fr
                        break;
                case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
                        status = get_unaligned_le16(&frame_body[3]);
-                       tid = ((frame_body[5] >> 2) & 0x7);
+                       tid = (frame_body[5] >> 2) & 0x7;
                        if (status == 0) {      /* successful */
                                DBG_88E("agg_enable for TID=%d\n", tid);
                                psta->htpriv.agg_enable_bitmap |= 1 << tid;
@@ -2491,7 +2491,7 @@ void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short
 
                /* setting IV for auth seq #3 */
                if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
-                       val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
+                       val32 = (pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30);
                        le_tmp32 = cpu_to_le32(val32);
                        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen));
 
@@ -3331,7 +3331,7 @@ void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned ch
                        } while (pmlmeinfo->dialogToken == 0);
                        pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
 
-                       BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */
+                       BA_para_set = 0x1002 | ((status & 0xf) << 2); /* immediate ack & 64 buffer size */
                        le_tmp = cpu_to_le16(BA_para_set);
                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
 
@@ -3972,8 +3972,8 @@ void start_clnt_join(struct adapter *padapter)
                /* and enable a timer */
                beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
                set_link_timer(pmlmeext, beacon_timeout);
-               _set_timer(&padapter->mlmepriv.assoc_timer,
-                          (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout);
+               mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
+                         msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO * REASSOC_LIMIT) + beacon_timeout));
 
                pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
        } else if (caps&cap_IBSS) { /* adhoc client */
@@ -4247,7 +4247,7 @@ void report_survey_event(struct adapter *padapter,
        if (pcmd_obj == NULL)
                return;
 
-       cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
+       cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header);
        pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
        if (pevtcmd == NULL) {
                kfree(pcmd_obj);
@@ -4299,7 +4299,7 @@ void report_surveydone_event(struct adapter *padapter)
        if (pcmd_obj == NULL)
                return;
 
-       cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
+       cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header);
        pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
        if (pevtcmd == NULL) {
                kfree(pcmd_obj);
@@ -4345,7 +4345,7 @@ void report_join_res(struct adapter *padapter, int res)
        if (pcmd_obj == NULL)
                return;
 
-       cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
+       cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header);
        pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
        if (pevtcmd == NULL) {
                kfree(pcmd_obj);
@@ -4398,7 +4398,7 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsi
        if (pcmd_obj == NULL)
                return;
 
-       cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
+       cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header);
        pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
        if (pevtcmd == NULL) {
                kfree(pcmd_obj);
@@ -4428,7 +4428,7 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsi
        if (psta)
                mac_id = (int)psta->mac_id;
        else
-               mac_id = (-1);
+               mac_id = -1;
 
        pdel_sta_evt->mac_id = mac_id;
 
@@ -4453,7 +4453,7 @@ void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int
        if (pcmd_obj == NULL)
                return;
 
-       cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
+       cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header);
        pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
        if (pevtcmd == NULL) {
                kfree(pcmd_obj);
@@ -4835,9 +4835,9 @@ void linked_status_chk(struct adapter *padapter)
        }
 }
 
-void survey_timer_hdl(void *function_context)
+void survey_timer_hdl(unsigned long data)
 {
-       struct adapter *padapter = function_context;
+       struct adapter *padapter = (struct adapter *)data;
        struct cmd_obj  *ph2c;
        struct sitesurvey_parm  *psurveyPara;
        struct cmd_priv                                 *pcmdpriv = &padapter->cmdpriv;
@@ -4875,9 +4875,9 @@ exit_survey_timer_hdl:
        return;
 }
 
-void link_timer_hdl(void *function_context)
+void link_timer_hdl(unsigned long data)
 {
-       struct adapter *padapter = (struct adapter *)function_context;
+       struct adapter *padapter = (struct adapter *)data;
        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
 
@@ -4912,9 +4912,9 @@ void link_timer_hdl(void *function_context)
        return;
 }
 
-void addba_timer_hdl(void *function_context)
+void addba_timer_hdl(unsigned long data)
 {
-       struct sta_info *psta = function_context;
+       struct sta_info *psta = (struct sta_info *)data;
        struct ht_priv  *phtpriv;
 
        if (!psta)
@@ -5356,7 +5356,7 @@ u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
 
                psta = rtw_get_stainfo(pstapriv, pparm->addr);
                if (psta) {
-                       ctrl = (BIT(15) | ((pparm->algorithm) << 2));
+                       ctrl = BIT(15) | ((pparm->algorithm) << 2);
 
                        DBG_88E("r871x_set_stakey_hdl(): enc_algorithm=%d\n", pparm->algorithm);
 
@@ -5365,7 +5365,7 @@ u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
                                return H2C_REJECTED;
                        }
 
-                       cam_id = (psta->mac_id + 3);/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
+                       cam_id = psta->mac_id + 3;/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
 
                        DBG_88E("Write CAM, mac_addr =%x:%x:%x:%x:%x:%x, cam_entry=%d\n", pparm->addr[0],
                                pparm->addr[1], pparm->addr[2], pparm->addr[3], pparm->addr[4],
@@ -5406,7 +5406,8 @@ u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
        if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
            ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
                issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
-               _set_timer(&psta->addba_retry_timer, ADDBA_TO);
+               mod_timer(&psta->addba_retry_timer,
+                         jiffies + msecs_to_jiffies(ADDBA_TO));
        } else {
                psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
        }
@@ -5430,15 +5431,14 @@ u8 set_tx_beacon_cmd(struct adapter *padapter)
                goto exit;
        }
 
-       ptxBeacon_parm = kzalloc(sizeof(struct wlan_bssid_ex), GFP_KERNEL);
+       ptxBeacon_parm = kmemdup(&(pmlmeinfo->network),
+                               sizeof(struct wlan_bssid_ex), GFP_KERNEL);
        if (ptxBeacon_parm == NULL) {
                kfree(ph2c);
                res = _FAIL;
                goto exit;
        }
 
-       memcpy(ptxBeacon_parm, &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
-
        len_diff = update_hidden_ssid(ptxBeacon_parm->IEs+_BEACON_IE_OFFSET_,
                                      ptxBeacon_parm->IELength-_BEACON_IE_OFFSET_,
                                      pmlmeinfo->hidden_ssid_mode);
index df463a29b6410182b9d3f7aede6f1f38f18216b1..ec0a8a4cdc6e65c29aa9b6b42b752028090d7b6f 100644 (file)
@@ -281,9 +281,9 @@ exit:
        pwrpriv->ps_processing = false;
 }
 
-static void pwr_state_check_handler(void *FunctionContext)
+static void pwr_state_check_handler(unsigned long data)
 {
-       struct adapter *padapter = FunctionContext;
+       struct adapter *padapter = (struct adapter *)data;
        rtw_ps_cmd(padapter);
 }
 
@@ -544,7 +544,9 @@ void rtw_init_pwrctrl_priv(struct adapter *padapter)
 
        pwrctrlpriv->btcoex_rfon = false;
 
-       _init_timer(&(pwrctrlpriv->pwr_state_check_timer), padapter->pnetdev, pwr_state_check_handler, (u8 *)padapter);
+       setup_timer(&pwrctrlpriv->pwr_state_check_timer,
+                   pwr_state_check_handler,
+                   (unsigned long)padapter);
 }
 
 inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
index bd79e9e7105acc5820439fa7fa6ab9ebea890f9f..cda725a8f9cdf22af090f6a0e35bf7a62cfa949b 100644 (file)
@@ -41,7 +41,7 @@ static u8 rtw_rfc1042_header[] = {
        0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
 };
 
-void rtw_signal_stat_timer_hdl(RTW_TIMER_HDL_ARGS);
+void rtw_signal_stat_timer_hdl(unsigned long data);
 
 void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)
 {
@@ -98,7 +98,9 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter)
 
        res = rtw_hal_init_recv_priv(padapter);
 
-       _init_timer(&precvpriv->signal_stat_timer, padapter->pnetdev, RTW_TIMER_HDL_NAME(signal_stat), padapter);
+       setup_timer(&precvpriv->signal_stat_timer,
+                   rtw_signal_stat_timer_hdl,
+                   (unsigned long)padapter);
 
        precvpriv->signal_stat_sampling_interval = 1000; /* ms */
 
@@ -1927,7 +1929,8 @@ static int recv_indicatepkt_reorder(struct adapter *padapter,
 
        /* recv_indicatepkts_in_order(padapter, preorder_ctrl, true); */
        if (recv_indicatepkts_in_order(padapter, preorder_ctrl, false)) {
-               _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);
+               mod_timer(&preorder_ctrl->reordering_ctrl_timer,
+                         jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
                spin_unlock_bh(&ppending_recvframe_queue->lock);
        } else {
                spin_unlock_bh(&ppending_recvframe_queue->lock);
@@ -1945,9 +1948,9 @@ _err_exit:
        return _FAIL;
 }
 
-void rtw_reordering_ctrl_timeout_handler(void *pcontext)
+void rtw_reordering_ctrl_timeout_handler(unsigned long data)
 {
-       struct recv_reorder_ctrl *preorder_ctrl = pcontext;
+       struct recv_reorder_ctrl *preorder_ctrl = (struct recv_reorder_ctrl *)data;
        struct adapter *padapter = preorder_ctrl->padapter;
        struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
 
@@ -1957,7 +1960,8 @@ void rtw_reordering_ctrl_timeout_handler(void *pcontext)
        spin_lock_bh(&ppending_recvframe_queue->lock);
 
        if (recv_indicatepkts_in_order(padapter, preorder_ctrl, true) == true)
-               _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);
+               mod_timer(&preorder_ctrl->reordering_ctrl_timer,
+                         jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
 
        spin_unlock_bh(&ppending_recvframe_queue->lock);
 }
@@ -2130,9 +2134,9 @@ _recv_entry_drop:
        return ret;
 }
 
-void rtw_signal_stat_timer_hdl(RTW_TIMER_HDL_ARGS)
+void rtw_signal_stat_timer_hdl(unsigned long data)
 {
-       struct adapter *adapter = (struct adapter *)FunctionContext;
+       struct adapter *adapter = (struct adapter *)data;
        struct recv_priv *recvpriv = &adapter->recvpriv;
 
        u32 tmp_s, tmp_q;
@@ -2159,7 +2163,7 @@ void rtw_signal_stat_timer_hdl(RTW_TIMER_HDL_ARGS)
 
                /* update value of signal_strength, rssi, signal_qual */
                if (check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY) == false) {
-                       tmp_s = (avg_signal_strength+(_alpha-1)*recvpriv->signal_strength);
+                       tmp_s = avg_signal_strength+(_alpha-1)*recvpriv->signal_strength;
                        if (tmp_s % _alpha)
                                tmp_s = tmp_s/_alpha + 1;
                        else
@@ -2167,7 +2171,7 @@ void rtw_signal_stat_timer_hdl(RTW_TIMER_HDL_ARGS)
                        if (tmp_s > 100)
                                tmp_s = 100;
 
-                       tmp_q = (avg_signal_qual+(_alpha-1)*recvpriv->signal_qual);
+                       tmp_q = avg_signal_qual+(_alpha-1)*recvpriv->signal_qual;
                        if (tmp_q % _alpha)
                                tmp_q = tmp_q/_alpha + 1;
                        else
index bd8d60a230e9b0fdad18e7c16cd9af17b02c5b5c..d870a5ce858533a4fa2e16e3e12000fe00e24e8d 100644 (file)
@@ -854,7 +854,7 @@ static void mix_column(u8 *in, u8 *out)
        u8 add1b[4];
        u8 add1bf7[4];
        u8 rotl[4];
-       u8 swap_halfs[4];
+       u8 swap_halves[4];
        u8 andf7[4];
        u8 rotr[4];
        u8 temp[4];
@@ -866,10 +866,10 @@ static void mix_column(u8 *in, u8 *out)
                        add1b[i] = 0x00;
        }
 
-       swap_halfs[0] = in[2];    /* Swap halves */
-       swap_halfs[1] = in[3];
-       swap_halfs[2] = in[0];
-       swap_halfs[3] = in[1];
+       swap_halves[0] = in[2];    /* Swap halves */
+       swap_halves[1] = in[3];
+       swap_halves[2] = in[0];
+       swap_halves[3] = in[1];
 
        rotl[0] = in[3];        /* Rotate left 8 bits */
        rotl[1] = in[0];
@@ -900,7 +900,7 @@ static void mix_column(u8 *in, u8 *out)
        rotr[3] = temp[0];
 
        xor_32(add1bf7, rotr, temp);
-       xor_32(swap_halfs, rotl, tempb);
+       xor_32(swap_halves, rotl, tempb);
        xor_32(temp, tempb, out);
 }
 
@@ -1079,7 +1079,7 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
        uint    frtype  = GetFrameType(pframe);
        uint    frsubtype  = GetFrameSubType(pframe);
 
-       frsubtype = frsubtype>>4;
+       frsubtype >>= 4;
 
        memset((void *)mic_iv, 0, 16);
        memset((void *)mic_header1, 0, 16);
@@ -1122,7 +1122,7 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
        num_blocks = plen / 16;
 
        /* Find start of payload */
-       payload_index = (hdrlen + 8);
+       payload_index = hdrlen + 8;
 
        /* Calculate MIC */
        aes128k128d(key, mic_iv, aes_out);
@@ -1277,7 +1277,7 @@ static int aes_decipher(u8 *key, uint     hdrlen,
 /*     uint    offset = 0; */
        uint    frtype  = GetFrameType(pframe);
        uint    frsubtype  = GetFrameSubType(pframe);
-       frsubtype = frsubtype>>4;
+       frsubtype >>= 4;
 
        memset((void *)mic_iv, 0, 16);
        memset((void *)mic_header1, 0, 16);
@@ -1366,7 +1366,7 @@ static int aes_decipher(u8 *key, uint     hdrlen,
        num_blocks = (plen-8) / 16;
 
        /* Find start of payload */
-       payload_index = (hdrlen + 8);
+       payload_index = hdrlen + 8;
 
        /* Calculate MIC */
        aes128k128d(key, mic_iv, aes_out);
index cd4e344e6ffd0c93c94bc6d74c1539cc089910f4..e725a4708775cf7af72119680d09bf551406ae81 100644 (file)
@@ -47,7 +47,7 @@ u8 sreset_get_wifi_status(struct adapter *padapter)
 
        if (WIFI_STATUS_SUCCESS != psrtpriv->Wifi_Error_Status) {
                DBG_88E("==>%s error_status(0x%x)\n", __func__, psrtpriv->Wifi_Error_Status);
-               status = (psrtpriv->Wifi_Error_Status & (~(USB_READ_PORT_FAIL|USB_WRITE_PORT_FAIL)));
+               status = psrtpriv->Wifi_Error_Status & (~(USB_READ_PORT_FAIL|USB_WRITE_PORT_FAIL));
        }
        DBG_88E("==> %s wifi_status(0x%x)\n", __func__, status);
 
index a3ffc691be9a24396e9967750916e0af5ee03a2b..2b371757cbfe03dc81e5ccba52326e578b5d0faf 100644 (file)
@@ -88,35 +88,25 @@ int cckratesonly_included(unsigned char *rate, int ratelen)
 
 unsigned char networktype_to_raid(unsigned char network_type)
 {
-       unsigned char raid;
-
        switch (network_type) {
        case WIRELESS_11B:
-               raid = RATR_INX_WIRELESS_B;
-               break;
+               return RATR_INX_WIRELESS_B;
        case WIRELESS_11A:
        case WIRELESS_11G:
-               raid = RATR_INX_WIRELESS_G;
-               break;
+               return RATR_INX_WIRELESS_G;
        case WIRELESS_11BG:
-               raid = RATR_INX_WIRELESS_GB;
-               break;
+               return RATR_INX_WIRELESS_GB;
        case WIRELESS_11_24N:
        case WIRELESS_11_5N:
-               raid = RATR_INX_WIRELESS_N;
-               break;
+               return RATR_INX_WIRELESS_N;
        case WIRELESS_11A_5N:
        case WIRELESS_11G_24N:
-               raid = RATR_INX_WIRELESS_NG;
-               break;
+               return  RATR_INX_WIRELESS_NG;
        case WIRELESS_11BG_24N:
-               raid = RATR_INX_WIRELESS_NGB;
-               break;
+               return RATR_INX_WIRELESS_NGB;
        default:
-               raid = RATR_INX_WIRELESS_GB;
-               break;
+               return RATR_INX_WIRELESS_GB;
        }
-       return raid;
 }
 
 u8 judge_network_type(struct adapter *padapter, unsigned char *rate, int ratelen)
@@ -146,47 +136,34 @@ u8 judge_network_type(struct adapter *padapter, unsigned char *rate, int ratelen
 
 static unsigned char ratetbl_val_2wifirate(unsigned char rate)
 {
-       unsigned char val = 0;
-
        switch (rate & 0x7f) {
        case 0:
-               val = IEEE80211_CCK_RATE_1MB;
-               break;
+               return IEEE80211_CCK_RATE_1MB;
        case 1:
-               val = IEEE80211_CCK_RATE_2MB;
-               break;
+               return IEEE80211_CCK_RATE_2MB;
        case 2:
-               val = IEEE80211_CCK_RATE_5MB;
-               break;
+               return IEEE80211_CCK_RATE_5MB;
        case 3:
-               val = IEEE80211_CCK_RATE_11MB;
-               break;
+               return IEEE80211_CCK_RATE_11MB;
        case 4:
-               val = IEEE80211_OFDM_RATE_6MB;
-               break;
+               return IEEE80211_OFDM_RATE_6MB;
        case 5:
-               val = IEEE80211_OFDM_RATE_9MB;
-               break;
+               return IEEE80211_OFDM_RATE_9MB;
        case 6:
-               val = IEEE80211_OFDM_RATE_12MB;
-               break;
+               return IEEE80211_OFDM_RATE_12MB;
        case 7:
-               val = IEEE80211_OFDM_RATE_18MB;
-               break;
+               return IEEE80211_OFDM_RATE_18MB;
        case 8:
-               val = IEEE80211_OFDM_RATE_24MB;
-               break;
+               return IEEE80211_OFDM_RATE_24MB;
        case 9:
-               val = IEEE80211_OFDM_RATE_36MB;
-               break;
+               return IEEE80211_OFDM_RATE_36MB;
        case 10:
-               val = IEEE80211_OFDM_RATE_48MB;
-               break;
+               return IEEE80211_OFDM_RATE_48MB;
        case 11:
-               val = IEEE80211_OFDM_RATE_54MB;
-               break;
+               return IEEE80211_OFDM_RATE_54MB;
+       default:
+               return 0;
        }
-       return val;
 }
 
 static int is_basicrate(struct adapter *padapter, unsigned char rate)
@@ -485,14 +462,14 @@ void write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key)
        for (j = 5; j >= 0; j--) {
                switch (j) {
                case 0:
-                       val = (ctrl | (mac[0] << 16) | (mac[1] << 24));
+                       val = ctrl | (mac[0] << 16) | (mac[1] << 24);
                        break;
                case 1:
-                       val = (mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24));
+                       val = mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24);
                        break;
                default:
                        i = (j - 2) << 2;
-                       val = (key[i] | (key[i+1] << 8) | (key[i+2] << 16) | (key[i+3] << 24));
+                       val = key[i] | (key[i+1] << 8) | (key[i+2] << 16) | (key[i+3] << 24);
                        break;
                }
 
@@ -587,7 +564,7 @@ void WMMOnAssocRsp(struct adapter *padapter)
                /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */
                AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * pmlmeinfo->slotTime + aSifsTime;
 
-               ECWMin = (pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f);
+               ECWMin = pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f;
                ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4;
                TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit);
 
@@ -659,8 +636,6 @@ void WMMOnAssocRsp(struct adapter *padapter)
                pxmitpriv->wmm_para_seq[i] = inx[i];
                DBG_88E("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);
        }
-
-       return;
 }
 
 static void bwmode_update_check(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
@@ -766,14 +741,14 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
                } else {
                        /* modify from  fw by Thomas 2010/11/17 */
                        if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (pIE->data[i] & 0x3))
-                               max_AMPDU_len = (pIE->data[i] & 0x3);
+                               max_AMPDU_len = pIE->data[i] & 0x3;
                        else
-                               max_AMPDU_len = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3);
+                               max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3;
 
                        if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (pIE->data[i] & 0x1c))
-                               min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c);
+                               min_MPDU_spacing = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c;
                        else
-                               min_MPDU_spacing = (pIE->data[i] & 0x1c);
+                               min_MPDU_spacing = pIE->data[i] & 0x1c;
 
                        pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para = max_AMPDU_len | min_MPDU_spacing;
                }
@@ -788,7 +763,6 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
                else
                        pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R[i];
        }
-       return;
 }
 
 void HT_info_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
@@ -809,7 +783,6 @@ void HT_info_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
 
        pmlmeinfo->HT_info_enable = 1;
        memcpy(&(pmlmeinfo->HT_info), pIE->data, pIE->Length);
-       return;
 }
 
 void HTOnAssocRsp(struct adapter *padapter)
@@ -1221,48 +1194,36 @@ unsigned int is_ap_in_wep(struct adapter *padapter)
 
 static int wifirate2_ratetbl_inx(unsigned char rate)
 {
-       int     inx = 0;
        rate = rate & 0x7f;
 
        switch (rate) {
        case 54*2:
-               inx = 11;
-               break;
+               return 11;
        case 48*2:
-               inx = 10;
-               break;
+               return 10;
        case 36*2:
-               inx = 9;
-               break;
+               return 9;
        case 24*2:
-               inx = 8;
-               break;
+               return 8;
        case 18*2:
-               inx = 7;
-               break;
+               return 7;
        case 12*2:
-               inx = 6;
-               break;
+               return 6;
        case 9*2:
-               inx = 5;
-               break;
+               return 5;
        case 6*2:
-               inx = 4;
-               break;
+               return 4;
        case 11*2:
-               inx = 3;
-               break;
+               return 3;
        case 11:
-               inx = 2;
-               break;
+               return 2;
        case 2*2:
-               inx = 1;
-               break;
+               return 1;
        case 1*2:
-               inx = 0;
-               break;
+               return 0;
+       default:
+               return 0;
        }
-       return inx;
 }
 
 unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz)
@@ -1295,7 +1256,7 @@ unsigned int update_MSC_rate(struct HT_caps_element *pHT_caps)
 {
        unsigned int mask = 0;
 
-       mask = ((pHT_caps->u.HT_cap_element.MCS_rate[0] << 12) | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 20));
+       mask = (pHT_caps->u.HT_cap_element.MCS_rate[0] << 12) | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 20);
 
        return mask;
 }
@@ -1309,7 +1270,7 @@ int support_short_GI(struct adapter *padapter, struct HT_caps_element *pHT_caps)
        if (!(pmlmeinfo->HT_enable))
                return _FAIL;
 
-       if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK))
+       if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK)
                return _FAIL;
 
        bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40) ? 6 : 5;
index 7a71df167464ea0ce622936806e13498c9d965b8..fda169d377714e52eac42b470387c286d97063de 100644 (file)
@@ -1634,23 +1634,15 @@ void rtw_alloc_hwxmits(struct adapter *padapter)
 
        pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;
 
-       pxmitpriv->hwxmits = kzalloc(sizeof(struct hw_xmit) * pxmitpriv->hwxmit_entry, GFP_KERNEL);
+       pxmitpriv->hwxmits = kcalloc(pxmitpriv->hwxmit_entry,
+                                    sizeof(struct hw_xmit), GFP_KERNEL);
 
        hwxmits = pxmitpriv->hwxmits;
 
-       if (pxmitpriv->hwxmit_entry == 5) {
-               hwxmits[0] .sta_queue = &pxmitpriv->bm_pending;
-               hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;
-               hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;
-               hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
-               hwxmits[4] .sta_queue = &pxmitpriv->be_pending;
-       } else if (pxmitpriv->hwxmit_entry == 4) {
-               hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
-               hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
-               hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
-               hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
-       } else {
-       }
+       hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
+       hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
+       hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
+       hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
 }
 
 void rtw_free_hwxmits(struct adapter *padapter)
index 3c651d5c6824e19799f656a2add99b73a1dca9d7..082f0ca198ef6d1e81f2765554cd903da72b2bc0 100644 (file)
@@ -115,17 +115,21 @@ static void odm_SetTxRPTTiming_8188E(
        }
        pRaInfo->RptTime = DynamicTxRPTTiming[idx];
 
-       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("pRaInfo->RptTime = 0x%x\n", pRaInfo->RptTime));
+       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+                       ("pRaInfo->RptTime = 0x%x\n", pRaInfo->RptTime));
 }
 
-static int odm_RateDown_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_info *pRaInfo)
+static int odm_RateDown_8188E(struct odm_dm_struct *dm_odm,
+                               struct odm_ra_info *pRaInfo)
 {
        u8 RateID, LowestRate, HighestRate;
        u8 i;
 
-       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("=====>odm_RateDown_8188E()\n"));
+       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
+                       ODM_DBG_TRACE, ("=====>odm_RateDown_8188E()\n"));
        if (NULL == pRaInfo) {
-               ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("odm_RateDown_8188E(): pRaInfo is NULL\n"));
+               ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+                               ("odm_RateDown_8188E(): pRaInfo is NULL\n"));
                return -1;
        }
        RateID = pRaInfo->PreRate;
@@ -167,10 +171,15 @@ RateDownFinish:
 
        pRaInfo->DecisionRate = RateID;
        odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 2);
-       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("Rate down, RPT Timing default\n"));
-       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("RAWaitingCounter %d, RAPendingCounter %d", pRaInfo->RAWaitingCounter, pRaInfo->RAPendingCounter));
-       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("Rate down to RateID %d RateSGI %d\n", RateID, pRaInfo->RateSGI));
-       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("<===== odm_RateDown_8188E()\n"));
+       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
+                       ODM_DBG_LOUD, ("Rate down, RPT Timing default\n"));
+       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+                       ("RAWaitingCounter %d, RAPendingCounter %d",
+                        pRaInfo->RAWaitingCounter, pRaInfo->RAPendingCounter));
+       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+                       ("Rate down to RateID %d RateSGI %d\n", RateID, pRaInfo->RateSGI));
+       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+                       ("<===== odm_RateDown_8188E()\n"));
        return 0;
 }
 
@@ -182,9 +191,11 @@ static int odm_RateUp_8188E(
        u8 RateID, HighestRate;
        u8 i;
 
-       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("=====>odm_RateUp_8188E()\n"));
+       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
+                       ODM_DBG_TRACE, ("=====>odm_RateUp_8188E()\n"));
        if (NULL == pRaInfo) {
-               ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("odm_RateUp_8188E(): pRaInfo is NULL\n"));
+               ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+                               ("odm_RateUp_8188E(): pRaInfo is NULL\n"));
                return -1;
        }
        RateID = pRaInfo->PreRate;
@@ -200,7 +211,8 @@ static int odm_RateUp_8188E(
                goto RateUpfinish;
        }
        odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 0);
-       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("odm_RateUp_8188E():Decrease RPT Timing\n"));
+       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+                       ("odm_RateUp_8188E():Decrease RPT Timing\n"));
 
        if (RateID < HighestRate) {
                for (i = RateID+1; i <= HighestRate; i++) {
@@ -218,15 +230,20 @@ static int odm_RateUp_8188E(
                RateID = HighestRate;
        }
 RateUpfinish:
-       if (pRaInfo->RAWaitingCounter == (4+PendingForRateUpFail[pRaInfo->RAPendingCounter]))
+       if (pRaInfo->RAWaitingCounter ==
+               (4+PendingForRateUpFail[pRaInfo->RAPendingCounter]))
                pRaInfo->RAWaitingCounter = 0;
        else
                pRaInfo->RAWaitingCounter++;
 
        pRaInfo->DecisionRate = RateID;
-       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("Rate up to RateID %d\n", RateID));
-       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("RAWaitingCounter %d, RAPendingCounter %d", pRaInfo->RAWaitingCounter, pRaInfo->RAPendingCounter));
-       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("<===== odm_RateUp_8188E()\n"));
+       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+                       ("Rate up to RateID %d\n", RateID));
+       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+                       ("RAWaitingCounter %d, RAPendingCounter %d",
+                        pRaInfo->RAWaitingCounter, pRaInfo->RAPendingCounter));
+       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
+                       ODM_DBG_TRACE, ("<===== odm_RateUp_8188E()\n"));
        return 0;
 }
 
@@ -243,11 +260,12 @@ static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm,
                struct odm_ra_info *pRaInfo
        )
 {
-       u8 RateID = 0, RtyPtID = 0, PenaltyID1 = 0, PenaltyID2 = 0;
+       u8 RateID = 0, RtyPtID = 0, PenaltyID1 = 0, PenaltyID2 = 0, i = 0;
        /* u32 pool_retry; */
        static u8 DynamicTxRPTTimingCounter;
 
-       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("=====>odm_RateDecision_8188E()\n"));
+       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+                       ("=====>odm_RateDecision_8188E()\n"));
 
        if (pRaInfo->Active && (pRaInfo->TOTAL > 0)) { /*  STA used and data packet exits */
                if ((pRaInfo->RssiStaRA < (pRaInfo->PreRssiStaRA - 3)) ||
@@ -268,14 +286,14 @@ static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm,
 
                ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
                             (" NscDown init is %d\n", pRaInfo->NscDown));
-               pRaInfo->NscDown += pRaInfo->RTY[0] * RETRY_PENALTY[PenaltyID1][0];
-               pRaInfo->NscDown += pRaInfo->RTY[1] * RETRY_PENALTY[PenaltyID1][1];
-               pRaInfo->NscDown += pRaInfo->RTY[2] * RETRY_PENALTY[PenaltyID1][2];
-               pRaInfo->NscDown += pRaInfo->RTY[3] * RETRY_PENALTY[PenaltyID1][3];
-               pRaInfo->NscDown += pRaInfo->RTY[4] * RETRY_PENALTY[PenaltyID1][4];
+
+               for (i = 0 ; i <= 4 ; i++)
+                       pRaInfo->NscDown += pRaInfo->RTY[i] * RETRY_PENALTY[PenaltyID1][i];
+
                ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
-                            (" NscDown is %d, total*penalty[5] is %d\n",
-                            pRaInfo->NscDown, (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5])));
+                            (" NscDown is %d, total*penalty[5] is %d\n", pRaInfo->NscDown,
+                             (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5])));
+
                if (pRaInfo->NscDown > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5]))
                        pRaInfo->NscDown -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5];
                else
@@ -285,14 +303,14 @@ static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm,
                PenaltyID2 = RETRY_PENALTY_UP_IDX[RateID];
                ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
                             (" NscUp init is %d\n", pRaInfo->NscUp));
-               pRaInfo->NscUp += pRaInfo->RTY[0] * RETRY_PENALTY[PenaltyID2][0];
-               pRaInfo->NscUp += pRaInfo->RTY[1] * RETRY_PENALTY[PenaltyID2][1];
-               pRaInfo->NscUp += pRaInfo->RTY[2] * RETRY_PENALTY[PenaltyID2][2];
-               pRaInfo->NscUp += pRaInfo->RTY[3] * RETRY_PENALTY[PenaltyID2][3];
-               pRaInfo->NscUp += pRaInfo->RTY[4] * RETRY_PENALTY[PenaltyID2][4];
+
+               for (i = 0 ; i <= 4 ; i++)
+                       pRaInfo->NscUp += pRaInfo->RTY[i] * RETRY_PENALTY[PenaltyID2][i];
+
                ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
                             ("NscUp is %d, total*up[5] is %d\n",
                             pRaInfo->NscUp, (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5])));
+
                if (pRaInfo->NscUp > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5]))
                        pRaInfo->NscUp -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5];
                else
@@ -487,7 +505,7 @@ static void odm_PTDecision_8188E(struct odm_ra_info *pRaInfo)
                        break;
        }
 
-       j = j >> 1;
+       j >>= 1;
        temp_stage = (pRaInfo->PTStage + 1) >> 1;
        if (temp_stage > j)
                stage_id = temp_stage-j;
@@ -538,6 +556,7 @@ int ODM_RAInfo_Init(struct odm_dm_struct *dm_odm, u8 macid)
        struct odm_ra_info *pRaInfo = &dm_odm->RAInfo[macid];
        u8 WirelessMode = 0xFF; /* invalid value */
        u8 max_rate_idx = 0x13; /* MCS7 */
+
        if (dm_odm->pWirelessMode != NULL)
                WirelessMode = *(dm_odm->pWirelessMode);
 
@@ -618,7 +637,7 @@ u8 ODM_RA_GetDecisionRate_8188E(struct odm_dm_struct *dm_odm, u8 macid)
 
        if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
                return 0;
-       DecisionRate = (dm_odm->RAInfo[macid].DecisionRate);
+       DecisionRate = dm_odm->RAInfo[macid].DecisionRate;
        ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
                (" macid =%d DecisionRate = 0x%x\n", macid, DecisionRate));
        return DecisionRate;
@@ -630,7 +649,7 @@ u8 ODM_RA_GetHwPwrStatus_8188E(struct odm_dm_struct *dm_odm, u8 macid)
 
        if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
                return 0;
-       PTStage = (dm_odm->RAInfo[macid].PTStage);
+       PTStage = dm_odm->RAInfo[macid].PTStage;
        ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
                     ("macid =%d PTStage = 0x%x\n", macid, PTStage));
        return PTStage;
index 1e963bf9e48bc928347ff156d7be1adbd960fbec..8eb2b39a0b6737008867f2032cd8371ced743fee 100644 (file)
@@ -511,62 +511,71 @@ static u32 array_phy_reg_pg_8188e[] = {
 static void store_pwrindex_offset(struct adapter *Adapter, u32 regaddr, u32 bitmask, u32 data)
 {
        struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
+        u8 pwrGrpCnt = hal_data->pwrGroupCnt;
 
        if (regaddr == rTxAGC_A_Rate18_06)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][0] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][0] = data;
        if (regaddr == rTxAGC_A_Rate54_24)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][1] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][1] = data;
        if (regaddr == rTxAGC_A_CCK1_Mcs32)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][6] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][6] = data;
        if (regaddr == rTxAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][7] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][7] = data;
        if (regaddr == rTxAGC_A_Mcs03_Mcs00)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][2] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][2] = data;
        if (regaddr == rTxAGC_A_Mcs07_Mcs04)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][3] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][3] = data;
        if (regaddr == rTxAGC_A_Mcs11_Mcs08)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][4] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][4] = data;
        if (regaddr == rTxAGC_A_Mcs15_Mcs12) {
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][5] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][5] = data;
                if (hal_data->rf_type == RF_1T1R)
                        hal_data->pwrGroupCnt++;
        }
        if (regaddr == rTxAGC_B_Rate18_06)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][8] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][8] = data;
        if (regaddr == rTxAGC_B_Rate54_24)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][9] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][9] = data;
        if (regaddr == rTxAGC_B_CCK1_55_Mcs32)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][14] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][14] = data;
        if (regaddr == rTxAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][15] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][15] = data;
        if (regaddr == rTxAGC_B_Mcs03_Mcs00)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][10] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][10] = data;
        if (regaddr == rTxAGC_B_Mcs07_Mcs04)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][11] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][11] = data;
        if (regaddr == rTxAGC_B_Mcs11_Mcs08)
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][12] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][12] = data;
        if (regaddr == rTxAGC_B_Mcs15_Mcs12) {
-               hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt][13] = data;
+               hal_data->MCSTxPowerLevelOriginalOffset[pwrGrpCnt][13] = data;
                if (hal_data->rf_type != RF_1T1R)
                        hal_data->pwrGroupCnt++;
        }
 }
 
-static void rtl_addr_delay(struct adapter *adapt, u32 addr, u32 bit_mask, u32 data)
+static void rtl_addr_delay(struct adapter *adapt,
+                       u32 addr, u32 bit_mask, u32 data)
 {
-       if (addr == 0xfe) {
+       switch (addr) {
+       case 0xfe:
                msleep(50);
-       } else if (addr == 0xfd) {
+               break;
+       case 0xfd:
                mdelay(5);
-       } else if (addr == 0xfc) {
+               break;
+       case 0xfc:
                mdelay(1);
-       } else if (addr == 0xfb) {
+               break;
+       case 0xfb:
                udelay(50);
-       } else if (addr == 0xfa) {
+               break;
+       case 0xfa:
                udelay(5);
-       } else if (addr == 0xf9) {
+               break;
+       case 0xf9:
                udelay(1);
-       } else{
+               break;
+       default:
                store_pwrindex_offset(adapt, addr, bit_mask, data);
        }
 }
@@ -591,84 +600,90 @@ static bool config_bb_with_pgheader(struct adapter *adapt)
 static void rtl88e_phy_init_bb_rf_register_definition(struct adapter *Adapter)
 {
        struct hal_data_8188e           *hal_data = GET_HAL_DATA(Adapter);
-
-       hal_data->PHYRegDef[RF_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW;
-       hal_data->PHYRegDef[RF_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW;
-       hal_data->PHYRegDef[RF_PATH_C].rfintfs = rFPGA0_XCD_RFInterfaceSW;
-       hal_data->PHYRegDef[RF_PATH_D].rfintfs = rFPGA0_XCD_RFInterfaceSW;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfintfi = rFPGA0_XAB_RFInterfaceRB;
-       hal_data->PHYRegDef[RF_PATH_B].rfintfi = rFPGA0_XAB_RFInterfaceRB;
-       hal_data->PHYRegDef[RF_PATH_C].rfintfi = rFPGA0_XCD_RFInterfaceRB;
-       hal_data->PHYRegDef[RF_PATH_D].rfintfi = rFPGA0_XCD_RFInterfaceRB;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE;
-       hal_data->PHYRegDef[RF_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE;
-       hal_data->PHYRegDef[RF_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE;
-
-       hal_data->PHYRegDef[RF_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter;
-       hal_data->PHYRegDef[RF_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfLSSI_Select = rFPGA0_XAB_RFParameter;
-       hal_data->PHYRegDef[RF_PATH_B].rfLSSI_Select = rFPGA0_XAB_RFParameter;
-       hal_data->PHYRegDef[RF_PATH_C].rfLSSI_Select = rFPGA0_XCD_RFParameter;
-       hal_data->PHYRegDef[RF_PATH_D].rfLSSI_Select = rFPGA0_XCD_RFParameter;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfTxGainStage = rFPGA0_TxGainStage;
-       hal_data->PHYRegDef[RF_PATH_B].rfTxGainStage = rFPGA0_TxGainStage;
-       hal_data->PHYRegDef[RF_PATH_C].rfTxGainStage = rFPGA0_TxGainStage;
-       hal_data->PHYRegDef[RF_PATH_D].rfTxGainStage = rFPGA0_TxGainStage;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfHSSIPara1 = rFPGA0_XA_HSSIParameter1;
-       hal_data->PHYRegDef[RF_PATH_B].rfHSSIPara1 = rFPGA0_XB_HSSIParameter1;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2;
-       hal_data->PHYRegDef[RF_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfSwitchControl = rFPGA0_XAB_SwitchControl;
-       hal_data->PHYRegDef[RF_PATH_B].rfSwitchControl = rFPGA0_XAB_SwitchControl;
-       hal_data->PHYRegDef[RF_PATH_C].rfSwitchControl = rFPGA0_XCD_SwitchControl;
-       hal_data->PHYRegDef[RF_PATH_D].rfSwitchControl = rFPGA0_XCD_SwitchControl;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfAGCControl1 = rOFDM0_XAAGCCore1;
-       hal_data->PHYRegDef[RF_PATH_B].rfAGCControl1 = rOFDM0_XBAGCCore1;
-       hal_data->PHYRegDef[RF_PATH_C].rfAGCControl1 = rOFDM0_XCAGCCore1;
-       hal_data->PHYRegDef[RF_PATH_D].rfAGCControl1 = rOFDM0_XDAGCCore1;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfAGCControl2 = rOFDM0_XAAGCCore2;
-       hal_data->PHYRegDef[RF_PATH_B].rfAGCControl2 = rOFDM0_XBAGCCore2;
-       hal_data->PHYRegDef[RF_PATH_C].rfAGCControl2 = rOFDM0_XCAGCCore2;
-       hal_data->PHYRegDef[RF_PATH_D].rfAGCControl2 = rOFDM0_XDAGCCore2;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfRxIQImbalance = rOFDM0_XARxIQImbalance;
-       hal_data->PHYRegDef[RF_PATH_B].rfRxIQImbalance = rOFDM0_XBRxIQImbalance;
-       hal_data->PHYRegDef[RF_PATH_C].rfRxIQImbalance = rOFDM0_XCRxIQImbalance;
-       hal_data->PHYRegDef[RF_PATH_D].rfRxIQImbalance = rOFDM0_XDRxIQImbalance;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfRxAFE = rOFDM0_XARxAFE;
-       hal_data->PHYRegDef[RF_PATH_B].rfRxAFE = rOFDM0_XBRxAFE;
-       hal_data->PHYRegDef[RF_PATH_C].rfRxAFE = rOFDM0_XCRxAFE;
-       hal_data->PHYRegDef[RF_PATH_D].rfRxAFE = rOFDM0_XDRxAFE;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfTxIQImbalance = rOFDM0_XATxIQImbalance;
-       hal_data->PHYRegDef[RF_PATH_B].rfTxIQImbalance = rOFDM0_XBTxIQImbalance;
-       hal_data->PHYRegDef[RF_PATH_C].rfTxIQImbalance = rOFDM0_XCTxIQImbalance;
-       hal_data->PHYRegDef[RF_PATH_D].rfTxIQImbalance = rOFDM0_XDTxIQImbalance;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfTxAFE = rOFDM0_XATxAFE;
-       hal_data->PHYRegDef[RF_PATH_B].rfTxAFE = rOFDM0_XBTxAFE;
-       hal_data->PHYRegDef[RF_PATH_C].rfTxAFE = rOFDM0_XCTxAFE;
-       hal_data->PHYRegDef[RF_PATH_D].rfTxAFE = rOFDM0_XDTxAFE;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
-       hal_data->PHYRegDef[RF_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
-       hal_data->PHYRegDef[RF_PATH_C].rfLSSIReadBack = rFPGA0_XC_LSSIReadBack;
-       hal_data->PHYRegDef[RF_PATH_D].rfLSSIReadBack = rFPGA0_XD_LSSIReadBack;
-
-       hal_data->PHYRegDef[RF_PATH_A].rfLSSIReadBackPi = TransceiverA_HSPI_Readback;
-       hal_data->PHYRegDef[RF_PATH_B].rfLSSIReadBackPi = TransceiverB_HSPI_Readback;
+       struct bb_reg_def               *reg[4];
+
+       reg[RF_PATH_A] = &(hal_data->PHYRegDef[RF_PATH_A]);
+       reg[RF_PATH_B] = &(hal_data->PHYRegDef[RF_PATH_B]);
+       reg[RF_PATH_C] = &(hal_data->PHYRegDef[RF_PATH_C]);
+       reg[RF_PATH_D] = &(hal_data->PHYRegDef[RF_PATH_D]);
+
+       reg[RF_PATH_A]->rfintfs = rFPGA0_XAB_RFInterfaceSW;
+       reg[RF_PATH_B]->rfintfs = rFPGA0_XAB_RFInterfaceSW;
+       reg[RF_PATH_C]->rfintfs = rFPGA0_XCD_RFInterfaceSW;
+       reg[RF_PATH_D]->rfintfs = rFPGA0_XCD_RFInterfaceSW;
+
+       reg[RF_PATH_A]->rfintfi = rFPGA0_XAB_RFInterfaceRB;
+       reg[RF_PATH_B]->rfintfi = rFPGA0_XAB_RFInterfaceRB;
+       reg[RF_PATH_C]->rfintfi = rFPGA0_XCD_RFInterfaceRB;
+       reg[RF_PATH_D]->rfintfi = rFPGA0_XCD_RFInterfaceRB;
+
+       reg[RF_PATH_A]->rfintfo = rFPGA0_XA_RFInterfaceOE;
+       reg[RF_PATH_B]->rfintfo = rFPGA0_XB_RFInterfaceOE;
+
+       reg[RF_PATH_A]->rfintfe = rFPGA0_XA_RFInterfaceOE;
+       reg[RF_PATH_B]->rfintfe = rFPGA0_XB_RFInterfaceOE;
+
+       reg[RF_PATH_A]->rf3wireOffset = rFPGA0_XA_LSSIParameter;
+       reg[RF_PATH_B]->rf3wireOffset = rFPGA0_XB_LSSIParameter;
+
+       reg[RF_PATH_A]->rfLSSI_Select = rFPGA0_XAB_RFParameter;
+       reg[RF_PATH_B]->rfLSSI_Select = rFPGA0_XAB_RFParameter;
+       reg[RF_PATH_C]->rfLSSI_Select = rFPGA0_XCD_RFParameter;
+       reg[RF_PATH_D]->rfLSSI_Select = rFPGA0_XCD_RFParameter;
+
+       reg[RF_PATH_A]->rfTxGainStage = rFPGA0_TxGainStage;
+       reg[RF_PATH_B]->rfTxGainStage = rFPGA0_TxGainStage;
+       reg[RF_PATH_C]->rfTxGainStage = rFPGA0_TxGainStage;
+       reg[RF_PATH_D]->rfTxGainStage = rFPGA0_TxGainStage;
+
+       reg[RF_PATH_A]->rfHSSIPara1 = rFPGA0_XA_HSSIParameter1;
+       reg[RF_PATH_B]->rfHSSIPara1 = rFPGA0_XB_HSSIParameter1;
+
+       reg[RF_PATH_A]->rfHSSIPara2 = rFPGA0_XA_HSSIParameter2;
+       reg[RF_PATH_B]->rfHSSIPara2 = rFPGA0_XB_HSSIParameter2;
+
+       reg[RF_PATH_A]->rfSwitchControl = rFPGA0_XAB_SwitchControl;
+       reg[RF_PATH_B]->rfSwitchControl = rFPGA0_XAB_SwitchControl;
+       reg[RF_PATH_C]->rfSwitchControl = rFPGA0_XCD_SwitchControl;
+       reg[RF_PATH_D]->rfSwitchControl = rFPGA0_XCD_SwitchControl;
+
+       reg[RF_PATH_A]->rfAGCControl1 = rOFDM0_XAAGCCore1;
+       reg[RF_PATH_B]->rfAGCControl1 = rOFDM0_XBAGCCore1;
+       reg[RF_PATH_C]->rfAGCControl1 = rOFDM0_XCAGCCore1;
+       reg[RF_PATH_D]->rfAGCControl1 = rOFDM0_XDAGCCore1;
+
+       reg[RF_PATH_A]->rfAGCControl2 = rOFDM0_XAAGCCore2;
+       reg[RF_PATH_B]->rfAGCControl2 = rOFDM0_XBAGCCore2;
+       reg[RF_PATH_C]->rfAGCControl2 = rOFDM0_XCAGCCore2;
+       reg[RF_PATH_D]->rfAGCControl2 = rOFDM0_XDAGCCore2;
+
+       reg[RF_PATH_A]->rfRxIQImbalance = rOFDM0_XARxIQImbalance;
+       reg[RF_PATH_B]->rfRxIQImbalance = rOFDM0_XBRxIQImbalance;
+       reg[RF_PATH_C]->rfRxIQImbalance = rOFDM0_XCRxIQImbalance;
+       reg[RF_PATH_D]->rfRxIQImbalance = rOFDM0_XDRxIQImbalance;
+
+       reg[RF_PATH_A]->rfRxAFE = rOFDM0_XARxAFE;
+       reg[RF_PATH_B]->rfRxAFE = rOFDM0_XBRxAFE;
+       reg[RF_PATH_C]->rfRxAFE = rOFDM0_XCRxAFE;
+       reg[RF_PATH_D]->rfRxAFE = rOFDM0_XDRxAFE;
+
+       reg[RF_PATH_A]->rfTxIQImbalance = rOFDM0_XATxIQImbalance;
+       reg[RF_PATH_B]->rfTxIQImbalance = rOFDM0_XBTxIQImbalance;
+       reg[RF_PATH_C]->rfTxIQImbalance = rOFDM0_XCTxIQImbalance;
+       reg[RF_PATH_D]->rfTxIQImbalance = rOFDM0_XDTxIQImbalance;
+
+       reg[RF_PATH_A]->rfTxAFE = rOFDM0_XATxAFE;
+       reg[RF_PATH_B]->rfTxAFE = rOFDM0_XBTxAFE;
+       reg[RF_PATH_C]->rfTxAFE = rOFDM0_XCTxAFE;
+       reg[RF_PATH_D]->rfTxAFE = rOFDM0_XDTxAFE;
+
+       reg[RF_PATH_A]->rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
+       reg[RF_PATH_B]->rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
+       reg[RF_PATH_C]->rfLSSIReadBack = rFPGA0_XC_LSSIReadBack;
+       reg[RF_PATH_D]->rfLSSIReadBack = rFPGA0_XD_LSSIReadBack;
+
+       reg[RF_PATH_A]->rfLSSIReadBackPi = TransceiverA_HSPI_Readback;
+       reg[RF_PATH_B]->rfLSSIReadBackPi = TransceiverB_HSPI_Readback;
 }
 
 static bool config_parafile(struct adapter *adapt)
index 3b2875481fc5bb7e6819e8fd0e5be105a72dba5b..a71c54295508b05e245b5de1a7dce1105ba0be69 100644 (file)
@@ -154,9 +154,8 @@ static int _rtl88e_fw_free_to_go(struct adapter *adapt)
                        break;
        } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
 
-       if (counter >= POLLING_READY_TIMEOUT_COUNT) {
+       if (counter >= POLLING_READY_TIMEOUT_COUNT)
                goto exit;
-       }
 
        value32 = usb_read32(adapt, REG_MCUFWDL);
        value32 |= MCUFWDL_RDY;
index 06477e8346535cd60a50ebba8e08c74406e62cef..28b5e7bd4fc0223beddd07102ce3d116bf0b116b 100644 (file)
@@ -741,13 +741,13 @@ void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm)
 
        ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord);
        FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
-       FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16);
+       FalseAlmCnt->Cnt_SB_Search_fail = (ret_value & 0xffff0000)>>16;
        ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord);
        FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff);
-       FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16);
+       FalseAlmCnt->Cnt_Parity_Fail = (ret_value & 0xffff0000)>>16;
        ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord);
        FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
-       FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16);
+       FalseAlmCnt->Cnt_Crc8_fail = (ret_value & 0xffff0000)>>16;
        ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord);
        FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
 
@@ -757,7 +757,7 @@ void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm)
 
        ret_value = phy_query_bb_reg(adapter, ODM_REG_SC_CNT_11N, bMaskDWord);
        FalseAlmCnt->Cnt_BW_LSC = (ret_value&0xffff);
-       FalseAlmCnt->Cnt_BW_USC = ((ret_value&0xffff0000)>>16);
+       FalseAlmCnt->Cnt_BW_USC = (ret_value & 0xffff0000)>>16;
 
        /* hold cck counter */
        phy_set_bb_reg(adapter, ODM_REG_CCK_FA_RST_11N, BIT12, 1);
index 29f87dffbad374857a9ea755afc76e9b5f61abfb..36afe45d1c9a6dc11102cbbb3ee13cf1df4572c6 100644 (file)
@@ -123,8 +123,8 @@ static void odm_RxPhyStatus92CSeries_Parsing(struct odm_dm_struct *dm_odm,
                /* 2011.11.28 LukeLee: 88E use different LNA & VGA gain table */
                /* The RSSI formula should be modified according to the gain table */
                /* In 88E, cck_highpwr is always set to 1 */
-               LNA_idx = ((cck_agc_rpt & 0xE0) >> 5);
-               VGA_idx = (cck_agc_rpt & 0x1F);
+               LNA_idx = (cck_agc_rpt & 0xE0) >> 5;
+               VGA_idx = cck_agc_rpt & 0x1F;
                switch (LNA_idx) {
                case 7:
                        if (VGA_idx <= 27)
index 3f663fe151ba9125c7e1c8754c8ce4d139d42870..6e4c3ee0399a42b579cb421b381ad8dc7444c346 100644 (file)
@@ -60,7 +60,7 @@ void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data)
        if (bitmask != bMaskDWord) { /* if not "double word" write */
                original_value = usb_read32(adapt, regaddr);
                bit_shift = cal_bit_shift(bitmask);
-               data = ((original_value & (~bitmask)) | (data << bit_shift));
+               data = (original_value & (~bitmask)) | (data << bit_shift);
        }
 
        usb_write32(adapt, regaddr, data);
@@ -72,12 +72,10 @@ static u32 rf_serial_read(struct adapter *adapt,
        u32 ret = 0;
        struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
        struct bb_reg_def *phyreg = &hal_data->PHYRegDef[rfpath];
-       u32 newoffset;
        u32 tmplong, tmplong2;
        u8 rfpi_enable = 0;
 
        offset &= 0xff;
-       newoffset = offset;
 
        tmplong = phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord);
        if (rfpath == RF_PATH_A)
@@ -87,7 +85,7 @@ static u32 rf_serial_read(struct adapter *adapt,
                                            bMaskDWord);
 
        tmplong2 = (tmplong2 & (~bLSSIReadAddress)) |
-                  (newoffset<<23) | bLSSIReadEdge;
+                  (offset<<23) | bLSSIReadEdge;
 
        phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord,
                       tmplong&(~bLSSIReadEdge));
@@ -119,10 +117,9 @@ static void rf_serial_write(struct adapter *adapt,
        u32 data_and_addr = 0;
        struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
        struct bb_reg_def *phyreg = &hal_data->PHYRegDef[rfpath];
-       u32 newoffset;
 
-       newoffset = offset & 0xff;
-       data_and_addr = ((newoffset<<20) | (data&0x000fffff)) & 0x0fffffff;
+       offset &= 0xff;
+       data_and_addr = ((offset<<20) | (data&0x000fffff)) & 0x0fffffff;
        phy_set_bb_reg(adapt, phyreg->rf3wireOffset, bMaskDWord, data_and_addr);
 }
 
@@ -146,7 +143,7 @@ void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
        if (bit_mask != bRFRegOffsetMask) {
                original_value = rf_serial_read(adapt, rf_path, reg_addr);
                bit_shift =  cal_bit_shift(bit_mask);
-               data = ((original_value & (~bit_mask)) | (data << bit_shift));
+               data = (original_value & (~bit_mask)) | (data << bit_shift);
        }
 
        rf_serial_write(adapt, rf_path, reg_addr, data);
@@ -304,21 +301,8 @@ static void phy_set_bw_mode_callback(struct adapter *adapt)
        }
 
        /* Set RF related register */
-       switch (hal_data->rf_chip) {
-       case RF_8225:
-               break;
-       case RF_8256:
-               break;
-       case RF_8258:
-               break;
-       case RF_PSEUDO_11N:
-               break;
-       case RF_6052:
+       if (hal_data->rf_chip == RF_6052)
                rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW);
-               break;
-       default:
-               break;
-       }
 }
 
 void phy_set_bw_mode(struct adapter *adapt, enum ht_channel_width bandwidth,
@@ -361,7 +345,6 @@ void phy_sw_chnl(struct adapter *adapt, u8 channel)
 {
        struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
        u8 tmpchannel = hal_data->CurrentChannel;
-       bool  result = true;
 
        if (hal_data->rf_chip == RF_PSEUDO_11N)
                return;
@@ -371,34 +354,28 @@ void phy_sw_chnl(struct adapter *adapt, u8 channel)
 
        hal_data->CurrentChannel = channel;
 
-       if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved)) {
+       if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
                phy_sw_chnl_callback(adapt, channel);
-
-               if (!result)
-                       hal_data->CurrentChannel = tmpchannel;
-
-       } else {
+       else
                hal_data->CurrentChannel = tmpchannel;
-       }
 }
 
 #define ODM_TXPWRTRACK_MAX_IDX_88E  6
 
 static u8 get_right_chnl_for_iqk(u8 chnl)
 {
+       u8 place;
        u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
-               1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
                36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64,
                100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
                124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153,
                155, 157, 159, 161, 163, 165
        };
-       u8 place = chnl;
 
        if (chnl > 14) {
-               for (place = 14; place < sizeof(channel_all); place++) {
+               for (place = 0; place < sizeof(channel_all); place++) {
                        if (channel_all[place] == chnl)
-                               return place-13;
+                               return ++place;
                }
        }
        return 0;
@@ -416,12 +393,12 @@ void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type,
 
                if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) {
                        *direction = 1;
-                       pwr_value = (dm_odm->BbSwingIdxOfdmBase -
-                                    dm_odm->BbSwingIdxOfdm);
+                       pwr_value = dm_odm->BbSwingIdxOfdmBase -
+                                    dm_odm->BbSwingIdxOfdm;
                } else {
                        *direction = 2;
-                       pwr_value = (dm_odm->BbSwingIdxOfdm -
-                                    dm_odm->BbSwingIdxOfdmBase);
+                       pwr_value = dm_odm->BbSwingIdxOfdm -
+                                    dm_odm->BbSwingIdxOfdmBase;
                }
 
        } else if (type == 1) { /* For CCK adjust. */
@@ -431,12 +408,12 @@ void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type,
 
                if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) {
                        *direction = 1;
-                       pwr_value = (dm_odm->BbSwingIdxCckBase -
-                                    dm_odm->BbSwingIdxCck);
+                       pwr_value = dm_odm->BbSwingIdxCckBase -
+                                    dm_odm->BbSwingIdxCck;
                } else {
                        *direction = 2;
-                       pwr_value = (dm_odm->BbSwingIdxCck -
-                                    dm_odm->BbSwingIdxCckBase);
+                       pwr_value = dm_odm->BbSwingIdxCck -
+                                    dm_odm->BbSwingIdxCckBase;
                }
 
        }
@@ -465,15 +442,13 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
        u8 thermal_val = 0, delta, delta_lck, delta_iqk, offset;
        u8 thermal_avg_count = 0;
        u32 thermal_avg = 0;
-       s32 ele_a = 0, ele_d, temp_cck, x, value32;
-       s32 y, ele_c = 0;
+       s32 ele_d, temp_cck;
        s8 ofdm_index[2], cck_index = 0;
        s8 ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
        u32 i = 0, j = 0;
        bool is2t = false;
 
        u8 ofdm_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB */
-       u8 indexforchannel = 0;
        s8 ofdm_index_mapping[2][index_mapping_NUM_88E] = {
                /* 2.4G, decrease power */
                {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11},
@@ -529,18 +504,12 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
                temp_cck = dm_odm->RFCalibrateInfo.RegA24;
 
                for (i = 0; i < CCK_TABLE_SIZE; i++) {
-                       if (dm_odm->RFCalibrateInfo.bCCKinCH14) {
-                               if (memcmp(&temp_cck, &CCKSwingTable_Ch14[i][2], 4)) {
-                                       cck_index_old = (u8)i;
-                                       dm_odm->BbSwingIdxCckBase = (u8)i;
-                                       break;
-                               }
-                       } else {
-                               if (memcmp(&temp_cck, &CCKSwingTable_Ch1_Ch13[i][2], 4)) {
+                       if ((dm_odm->RFCalibrateInfo.bCCKinCH14 &&
+                               memcmp(&temp_cck, &CCKSwingTable_Ch14[i][2], 4)) ||
+                               memcmp(&temp_cck, &CCKSwingTable_Ch1_Ch13[i][2], 4)) {
                                        cck_index_old = (u8)i;
                                        dm_odm->BbSwingIdxCckBase = (u8)i;
                                        break;
-                               }
                        }
                }
 
@@ -570,27 +539,19 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
                if (thermal_avg_count)
                        thermal_val = (u8)(thermal_avg / thermal_avg_count);
 
-               if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
-                       delta = thermal_val > hal_data->EEPROMThermalMeter ?
-                               (thermal_val - hal_data->EEPROMThermalMeter) :
-                               (hal_data->EEPROMThermalMeter - thermal_val);
-                       dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false;
-                       dm_odm->RFCalibrateInfo.bDoneTxpower = false;
-               } else if (dm_odm->RFCalibrateInfo.bDoneTxpower) {
-                       delta = (thermal_val > dm_odm->RFCalibrateInfo.ThermalValue) ?
-                               (thermal_val - dm_odm->RFCalibrateInfo.ThermalValue) :
-                               (dm_odm->RFCalibrateInfo.ThermalValue - thermal_val);
-               } else {
-                       delta = thermal_val > hal_data->EEPROMThermalMeter ?
-                               (thermal_val - hal_data->EEPROMThermalMeter) :
-                               (hal_data->EEPROMThermalMeter - thermal_val);
+               if (dm_odm->RFCalibrateInfo.bDoneTxpower &&
+                       !dm_odm->RFCalibrateInfo.bReloadtxpowerindex)
+                       delta = abs(thermal_val - dm_odm->RFCalibrateInfo.ThermalValue);
+               else {
+                       delta = abs(thermal_val - hal_data->EEPROMThermalMeter);
+                       if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
+                               dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false;
+                               dm_odm->RFCalibrateInfo.bDoneTxpower = false;
+                       }
                }
-               delta_lck = (thermal_val > dm_odm->RFCalibrateInfo.ThermalValue_LCK) ?
-                           (thermal_val - dm_odm->RFCalibrateInfo.ThermalValue_LCK) :
-                           (dm_odm->RFCalibrateInfo.ThermalValue_LCK - thermal_val);
-               delta_iqk = (thermal_val > dm_odm->RFCalibrateInfo.ThermalValue_IQK) ?
-                           (thermal_val - dm_odm->RFCalibrateInfo.ThermalValue_IQK) :
-                           (dm_odm->RFCalibrateInfo.ThermalValue_IQK - thermal_val);
+
+               delta_lck = abs(dm_odm->RFCalibrateInfo.ThermalValue_LCK - thermal_val);
+               delta_iqk = abs(dm_odm->RFCalibrateInfo.ThermalValue_IQK - thermal_val);
 
                /* Delta temperature is equal to or larger than 20 centigrade.*/
                if ((delta_lck >= 8)) {
@@ -599,9 +560,8 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
                }
 
                if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
-                       delta = thermal_val > hal_data->EEPROMThermalMeter ?
-                               (thermal_val - hal_data->EEPROMThermalMeter) :
-                               (hal_data->EEPROMThermalMeter - thermal_val);
+                       delta = abs(hal_data->EEPROMThermalMeter - thermal_val);
+
                        /* calculate new OFDM / CCK offset */
                        if (thermal_val > hal_data->EEPROMThermalMeter)
                                j = 1;
@@ -616,17 +576,17 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
                        }
                        if (offset >= index_mapping_NUM_88E)
                                offset = index_mapping_NUM_88E-1;
-                       for (i = 0; i < rf; i++)
-                               ofdm_index[i] = dm_odm->RFCalibrateInfo.OFDM_index[i] + ofdm_index_mapping[j][offset];
-                       cck_index = dm_odm->RFCalibrateInfo.CCK_index + ofdm_index_mapping[j][offset];
 
+                       /* Updating ofdm_index values with new OFDM / CCK offset */
                        for (i = 0; i < rf; i++) {
+                               ofdm_index[i] = dm_odm->RFCalibrateInfo.OFDM_index[i] + ofdm_index_mapping[j][offset];
                                if (ofdm_index[i] > OFDM_TABLE_SIZE_92D-1)
                                        ofdm_index[i] = OFDM_TABLE_SIZE_92D-1;
                                else if (ofdm_index[i] < ofdm_min_index)
                                        ofdm_index[i] = ofdm_min_index;
                        }
 
+                       cck_index = dm_odm->RFCalibrateInfo.CCK_index + ofdm_index_mapping[j][offset];
                        if (cck_index > CCK_TABLE_SIZE-1)
                                cck_index = CCK_TABLE_SIZE-1;
                        else if (cck_index < 0)
@@ -637,11 +597,6 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
                        if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
                                dm_odm->RFCalibrateInfo.bDoneTxpower = true;
 
-                               /* Adujst OFDM Ant_A according to IQK result */
-                               ele_d = (OFDMSwingTable[(u8)ofdm_index[0]] & 0xFFC00000)>>22;
-                               x = dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[indexforchannel].Value[0][0];
-                               y = dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[indexforchannel].Value[0][1];
-
                                /*  Revse TX power table. */
                                dm_odm->BbSwingIdxOfdm = (u8)ofdm_index[0];
                                dm_odm->BbSwingIdxCck = (u8)cck_index;
@@ -655,53 +610,6 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
                                        dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck;
                                        dm_odm->BbSwingFlagCck = true;
                                }
-
-                               if (x != 0) {
-                                       if ((x & 0x00000200) != 0)
-                                               x = x | 0xFFFFFC00;
-                                       ele_a = ((x * ele_d)>>8)&0x000003FF;
-
-                                       /* new element C = element D x Y */
-                                       if ((y & 0x00000200) != 0)
-                                               y = y | 0xFFFFFC00;
-                                       ele_c = ((y * ele_d)>>8)&0x000003FF;
-
-                               }
-
-                               if (is2t) {
-                                       ele_d = (OFDMSwingTable[(u8)ofdm_index[1]] & 0xFFC00000)>>22;
-
-                                       /* new element A = element D x X */
-                                       x = dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[indexforchannel].Value[0][4];
-                                       y = dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[indexforchannel].Value[0][5];
-
-                                       if ((x != 0) && (*(dm_odm->pBandType) == ODM_BAND_2_4G)) {
-                                               if ((x & 0x00000200) != 0)      /* consider minus */
-                                                       x = x | 0xFFFFFC00;
-                                               ele_a = ((x * ele_d)>>8)&0x000003FF;
-
-                                               /* new element C = element D x Y */
-                                               if ((y & 0x00000200) != 0)
-                                                       y = y | 0xFFFFFC00;
-                                               ele_c = ((y * ele_d)>>8)&0x00003FF;
-
-                                               /* wtite new elements A, C, D to regC88 and regC9C, element B is always 0 */
-                                               value32 = (ele_d<<22) | ((ele_c&0x3F)<<16) | ele_a;
-                                               phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord, value32);
-
-                                               value32 = (ele_c&0x000003C0)>>6;
-                                               phy_set_bb_reg(adapt, rOFDM0_XDTxAFE, bMaskH4Bits, value32);
-
-                                               value32 = ((x * ele_d)>>7)&0x01;
-                                               phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT28, value32);
-                                       } else {
-                                               phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable[(u8)ofdm_index[1]]);
-                                               phy_set_bb_reg(adapt, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00);
-                                               phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT28, 0x00);
-                                       }
-
-                               }
-
                        }
                }
 
@@ -1033,11 +941,11 @@ static void path_adda_on(struct adapter *adapt, u32 *adda_reg,
        u32 path_on;
        u32 i;
 
-       path_on = is_path_a_on ? 0x04db25a4 : 0x0b1b25a4;
        if (!is2t) {
                path_on = 0x0bdb25a0;
                phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, 0x0b1b25a0);
        } else {
+               path_on = is_path_a_on ? 0x04db25a4 : 0x0b1b25a4;
                phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, path_on);
        }
 
@@ -1077,27 +985,19 @@ static void pi_mode_switch(struct adapter *adapt, bool pi_mode)
 static bool simularity_compare(struct adapter *adapt, s32 resulta[][8],
                               u8 c1, u8 c2)
 {
-       u32 i, j, diff, sim_bitmap, bound = 0;
+       u32 i, j, diff, sim_bitmap = 0, bound;
        struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
        struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
        u8 final_candidate[2] = {0xFF, 0xFF};   /* for path A and path B */
        bool result = true;
-       bool is2t;
        s32 tmp1 = 0, tmp2 = 0;
 
        if ((dm_odm->RFType == ODM_2T2R) || (dm_odm->RFType == ODM_2T3R) ||
            (dm_odm->RFType == ODM_2T4R))
-               is2t = true;
-       else
-               is2t = false;
-
-       if (is2t)
                bound = 8;
        else
                bound = 4;
 
-       sim_bitmap = 0;
-
        for (i = 0; i < bound; i++) {
                if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
                        if ((resulta[c1][i] & 0x00000200) != 0)
index be0663e93f611d9ea1d0f756153483fe60c80ea6..73e1f8b36b37d255e6c6e08b8f22b505ebcce5ff 100644 (file)
@@ -109,7 +109,6 @@ u8 rtl88eu_pwrseqcmdparsing(struct adapter *padapter, u8 cut_vers, u8 fab_vers,
                                RT_TRACE(_module_hal_init_c_, _drv_info_,
                                         ("rtl88eu_pwrseqcmdparsing: PWR_CMD_END\n"));
                                return true;
-                               break;
                        default:
                                RT_TRACE(_module_hal_init_c_, _drv_err_,
                                         ("rtl88eu_pwrseqcmdparsing: Unknown CMD!!\n"));
index eea4c8a6022b6643d6164a09102ceb6ed07bc8d1..097092772a860d4b66845394ab0ca46e3b005b09 100644 (file)
@@ -201,7 +201,7 @@ static void get_rx_power_val_by_reg(struct adapter *adapt, u8 channel,
                        break;
                case 2: /*  Better regulatory */
                                /*  don't increase any power diff */
-                       write_val = ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
+                       write_val = (index < 2) ? powerbase0[rf] : powerbase1[rf];
                        break;
                case 3: /*  Customer defined power diff. */
                                /*  increase power diff defined by customer. */
index 5dc11cae2ef992e6e541161ac67423ba9bc629e5..455ecdc8d9fa7c8a0d78c5d11a4049a9142f4d11 100644 (file)
@@ -38,12 +38,12 @@ static bool check_condition(struct adapter *adapt, const u32  condition)
                return false;
 
        cond = condition & 0x0000FF00;
-       cond = cond >> 8;
+       cond >>= 8;
        if ((_interface & cond) == 0 && cond != 0x07)
                return false;
 
        cond = condition & 0x00FF0000;
-       cond = cond >> 16;
+       cond >>= 16;
        if ((_platform & cond) == 0 && cond != 0x0F)
                return false;
        return true;
index 3222d8d08b5b2d306ebf1e94ef5d8436c00e6e67..7904d2260f2cfd6b0f0e2eafeb1727ddab5683e7 100644 (file)
@@ -596,7 +596,8 @@ void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo, bool AutoL
        struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
 
        if (!AutoLoadFail)
-               pHalData->BoardType = ((hwinfo[EEPROM_RF_BOARD_OPTION_88E]&0xE0)>>5);
+               pHalData->BoardType = (hwinfo[EEPROM_RF_BOARD_OPTION_88E]
+                                       & 0xE0) >> 5;
        else
                pHalData->BoardType = 0;
        DBG_88E("Board Type: 0x%2x\n", pHalData->BoardType);
index bc275b2a7d37f66431268ee0629e73dca34046b6..06d1e654483e2c4426a4c9c25dd0b830275aed2a 100644 (file)
@@ -42,7 +42,7 @@ int   rtl8188eu_init_recv_priv(struct adapter *padapter)
        _rtw_init_queue(&precvpriv->free_recv_buf_queue);
 
        precvpriv->pallocated_recv_buf =
-               kzalloc(NR_RECVBUFF * sizeof(struct recv_buf), GFP_KERNEL);
+               kcalloc(NR_RECVBUFF, sizeof(struct recv_buf), GFP_KERNEL);
        if (precvpriv->pallocated_recv_buf == NULL) {
                res = _FAIL;
                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
index 14650e91c78a55f4765e520a9c3c58b9275b4a4c..7b01d5aa6b23e023f61c6f9fe74de93a4690405c 100644 (file)
@@ -1096,10 +1096,8 @@ static void Hal_EfuseParseMACAddr_8188EU(struct adapter *adapt, u8 *hwinfo, bool
                memcpy(eeprom->mac_addr, &hwinfo[EEPROM_MAC_ADDR_88EU], ETH_ALEN);
        }
        RT_TRACE(_module_hci_hal_init_c_, _drv_notice_,
-                ("Hal_EfuseParseMACAddr_8188EU: Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
-                eeprom->mac_addr[0], eeprom->mac_addr[1],
-                eeprom->mac_addr[2], eeprom->mac_addr[3],
-                eeprom->mac_addr[4], eeprom->mac_addr[5]));
+                ("Hal_EfuseParseMACAddr_8188EU: Permanent Address = %pM\n",
+                eeprom->mac_addr));
 }
 
 static void
@@ -1352,7 +1350,7 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
 
                        /*  Set RTS initial rate */
                        while (BrateCfg > 0x1) {
-                               BrateCfg = (BrateCfg >> 1);
+                               BrateCfg >>= 1;
                                RateIndex++;
                        }
                        /*  Ziv - Check */
index 3299571e339f891b781cc04071ec50a8919bcbf2..8fd35dcdbb94b28fb387c260ea4df4f6f090938e 100644 (file)
@@ -122,7 +122,6 @@ enum {
 
 #define WPA_SELECTOR_LEN 4
 extern u8 RTW_WPA_OUI_TYPE[];
-extern u16 RTW_WPA_VERSION;
 extern u8 WPA_AUTH_KEY_MGMT_NONE[];
 extern u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[];
 extern u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[];
index 3a274770364b01023303e6236c9419f956df84ff..515e949629e27886376fdb3ee9c6eb21bd86e3c4 100644 (file)
@@ -76,25 +76,6 @@ static inline int _enter_critical_mutex(struct mutex *pmutex,
        return ret;
 }
 
-static inline void _init_timer(struct timer_list *ptimer,
-                              struct  net_device *nic_hdl,
-                              void *pfunc, void *cntx)
-{
-       ptimer->function = pfunc;
-       ptimer->data = (unsigned long)cntx;
-       init_timer(ptimer);
-}
-
-static inline void _set_timer(struct timer_list *ptimer, u32 delay_time)
-{
-       mod_timer(ptimer , (jiffies+msecs_to_jiffies(delay_time)));
-}
-
-#define RTW_TIMER_HDL_ARGS void *FunctionContext
-#define RTW_TIMER_HDL_NAME(name) rtw_##name##_timer_hdl
-#define RTW_DECLARE_TIMER_HDL(name) \
-       void RTW_TIMER_HDL_NAME(name)(RTW_TIMER_HDL_ARGS)
-
 static inline int rtw_netif_queue_stopped(struct net_device *pnetdev)
 {
        return  netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 0)) &&
index 23f0cfe312f365963ba397bb7e593634b247290f..7a5303d50d4978daaf2a55f713a851be29fc7792 100644 (file)
@@ -103,7 +103,7 @@ struct led_priv {
                        (adapt)->ledpriv.LedControlHandler((adapt), (action)); \
        } while (0)
 
-void BlinkTimerCallback(void *data);
+void BlinkTimerCallback(unsigned long data);
 void BlinkWorkItemCallback(struct work_struct *work);
 
 void ResetLedStatus(struct LED_871x *pLed);
index 8d83f7ceda760207c352b5323eec8522ff74b5b2..3f7d1e631ef9636173d8de3270ead75ebb50096c 100644 (file)
@@ -551,10 +551,10 @@ void rtw_update_registrypriv_dev_network(struct adapter *adapter);
 
 void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter);
 
-void _rtw_join_timeout_handler(void *function_context);
-void rtw_scan_timeout_handler(void *function_context);
+void _rtw_join_timeout_handler(unsigned long data);
+void rtw_scan_timeout_handler(unsigned long data);
 
-void rtw_dynamic_check_timer_handlder(void *function_context);
+void rtw_dynamic_check_timer_handlder(unsigned long data);
 #define rtw_is_scan_deny(adapter) false
 #define rtw_clear_scan_deny(adapter) do {} while (0)
 #define rtw_set_scan_deny_timer_hdl(adapter) do {} while (0)
index 4f05aee93c9cb5edbb1968c3474fb182230ac9c5..2bebf46b053af68a34ed97952786cfe8512d6336 100644 (file)
@@ -645,19 +645,17 @@ void mlmeext_sta_add_event_callback(struct adapter *padapter,
 
 void linked_status_chk(struct adapter *padapter);
 
-void survey_timer_hdl(void *function_context);
-void link_timer_hdl(void *funtion_context);
-void addba_timer_hdl(void *function_context);
+void survey_timer_hdl(unsigned long data);
+void link_timer_hdl(unsigned long data);
+void addba_timer_hdl(unsigned long data);
 
 #define set_survey_timer(mlmeext, ms) \
-       do { \
-               _set_timer(&(mlmeext)->survey_timer, (ms)); \
-       } while (0)
+       mod_timer(&mlmeext->survey_timer, jiffies +     \
+                 msecs_to_jiffies(ms))
 
 #define set_link_timer(mlmeext, ms) \
-       do { \
-               _set_timer(&(mlmeext)->link_timer, (ms)); \
-       } while (0)
+       mod_timer(&mlmeext->link_timer, jiffies +       \
+                 msecs_to_jiffies(ms))
 
 int cckrates_included(unsigned char *rate, int ratelen);
 int cckratesonly_included(unsigned char *rate, int ratelen);
index 54dfbf07564bc1b7938402aa36eeb3a6efeca027..aa1fd87c47fba84c561b386f42117176d833ccc0 100644 (file)
@@ -233,9 +233,8 @@ struct pwrctrl_priv {
 #define RTW_PWR_STATE_CHK_INTERVAL 2000
 
 #define _rtw_set_pwr_state_check_timer(pwrctrlpriv, ms) \
-       do { \
-               _set_timer(&(pwrctrlpriv)->pwr_state_check_timer, (ms)); \
-       } while (0)
+       mod_timer(&pwrctrlpriv->pwr_state_check_timer,  \
+                 jiffies + msecs_to_jiffies(ms))
 
 #define rtw_set_pwr_state_check_timer(pwrctrl)                 \
        _rtw_set_pwr_state_check_timer((pwrctrl),               \
index f0c26ef8f66a08afd06d6fbb0d5f7ffc16044813..eb1ac3d03123f952da9db9008f72e24a17b3e086 100644 (file)
@@ -216,8 +216,8 @@ struct recv_priv {
 };
 
 #define rtw_set_signal_stat_timer(recvpriv)                    \
-       _set_timer(&(recvpriv)->signal_stat_timer,              \
-                  (recvpriv)->signal_stat_sampling_interval)
+       mod_timer(&(recvpriv)->signal_stat_timer, jiffies +     \
+                 msecs_to_jiffies((recvpriv)->signal_stat_sampling_interval))
 
 struct sta_recv_priv {
        spinlock_t lock;
@@ -278,7 +278,7 @@ void rtw_free_recvframe_queue(struct __queue *pframequeue,
                              struct __queue *pfree_recv_queue);
 u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter);
 
-void rtw_reordering_ctrl_timeout_handler(void *pcontext);
+void rtw_reordering_ctrl_timeout_handler(unsigned long data);
 
 static inline u8 *get_rxmem(struct recv_frame *precvframe)
 {
index 66d60aaf4ae8545727b9918adfe209374a5eb29c..e9723a72af5e5269de655e2188e2c1484444d473 100644 (file)
@@ -245,10 +245,6 @@ struct mic_data {
 };
 
 extern const u32 Te0[256];
-extern const u32 Te1[256];
-extern const u32 Te2[256];
-extern const u32 Te3[256];
-extern const u32 Te4[256];
 extern const u32 Td0[256];
 extern const u32 Td1[256];
 extern const u32 Td2[256];
@@ -269,28 +265,6 @@ static inline u32 rotr(u32 val, int bits)
 #define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8)
 #define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16)
 #define TE3(i) rotr(Te0[(i) & 0xff], 24)
-#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
-#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
-#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
-#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
-#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000)
-#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000)
-#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00)
-#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff)
-#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff)
-
-#define TD0(i) Td0[((i) >> 24) & 0xff]
-#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8)
-#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16)
-#define TD3(i) rotr(Td0[(i) & 0xff], 24)
-#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24)
-#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16)
-#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8)
-#define TD44(i) (Td4s[(i) & 0xff])
-#define TD0_(i) Td0[(i) & 0xff]
-#define TD1_(i) rotr(Td0[(i) & 0xff], 8)
-#define TD2_(i) rotr(Td0[(i) & 0xff], 16)
-#define TD3_(i) rotr(Td0[(i) & 0xff], 24)
 
 #define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \
                        ((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
index 8dbdfafd52b55e3a86db5632c00511d9891a1a34..a89275e0e0e054053707b9277efd4a7fa98dab6c 100644 (file)
@@ -301,22 +301,12 @@ enum WIFI_REG_DOMAIN {
 #define GetPrivacy(pbuf)                                       \
        (((*(__le16 *)(pbuf)) & cpu_to_le16(_PRIVACY_)) != 0)
 
-#define ClearPrivacy(pbuf)     \
-       *(__le16 *)(pbuf) &= (~cpu_to_le16(_PRIVACY_))
-
-
 #define GetOrder(pbuf)                                 \
        (((*(__le16 *)(pbuf)) & cpu_to_le16(_ORDER_)) != 0)
 
 #define GetFrameType(pbuf)                             \
        (le16_to_cpu(*(__le16 *)(pbuf)) & (BIT(3) | BIT(2)))
 
-#define SetFrameType(pbuf, type)       \
-       do {    \
-               *(unsigned short *)(pbuf) &= __constant_cpu_to_le16(~(BIT(3) | BIT(2))); \
-               *(unsigned short *)(pbuf) |= __constant_cpu_to_le16(type); \
-       } while (0)
-
 #define GetFrameSubType(pbuf)  (le16_to_cpu(*(__le16 *)(pbuf)) & (BIT(7) |\
         BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2)))
 
@@ -333,17 +323,6 @@ enum WIFI_REG_DOMAIN {
 #define GetFragNum(pbuf)                       \
        (le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 22)) & 0x0f)
 
-#define GetTupleCache(pbuf)                    \
-       (cpu_to_le16(*(unsigned short *)((size_t)(pbuf) + 22)))
-
-#define SetFragNum(pbuf, num) \
-       do {    \
-               *(unsigned short *)((size_t)(pbuf) + 22) = \
-                       ((*(unsigned short *)((size_t)(pbuf) + 22)) &   \
-                       le16_to_cpu(~(0x000f))) | \
-                       cpu_to_le16(0x0f & (num));     \
-       } while (0)
-
 #define SetSeqNum(pbuf, num) \
        do {    \
                *(__le16 *)((size_t)(pbuf) + 22) = \
@@ -370,15 +349,8 @@ enum WIFI_REG_DOMAIN {
 
 #define GetAMsdu(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 7) & 0x1)
 
-#define SetAMsdu(pbuf, amsdu)  \
-       *(__le16 *)(pbuf) |= cpu_to_le16((amsdu & 1) << 7)
-
 #define GetAid(pbuf)   (le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 2)) & 0x3fff)
 
-#define GetTid(pbuf)   (le16_to_cpu(*(__le16 *)((size_t)(pbuf) +       \
-                       (((GetToDs(pbuf)<<1) | GetFrDs(pbuf)) == 3 ?    \
-                       30 : 24))) & 0x000f)
-
 #define GetAddr1Ptr(pbuf)      ((unsigned char *)((size_t)(pbuf) + 4))
 
 #define GetAddr2Ptr(pbuf)      ((unsigned char *)((size_t)(pbuf) + 10))
@@ -916,7 +888,7 @@ enum ht_cap_ampdu_factor {
 #define        P2P_STATUS_FAIL_INCOMPATIBLE_PROVSION           0x0A
 #define        P2P_STATUS_FAIL_USER_REJECT                     0x0B
 
-/*     Value of Inviation Flags Attribute */
+/*     Value of Invitation Flags Attribute */
 #define        P2P_INVITATION_FLAGS_PERSISTENT                 BIT(0)
 
 #define        DMP_P2P_DEVCAP_SUPPORT  (P2P_DEVCAP_SERVICE_DISCOVERY | \
@@ -970,7 +942,7 @@ enum ht_cap_ampdu_factor {
 
 #define        P2P_WILDCARD_SSID_LEN                   7
 
-/* default value, used when: (1)p2p disabed or (2)p2p enabled
+/* default value, used when: (1)p2p disabled or (2)p2p enabled
  * but only do 1 scan phase */
 #define        P2P_FINDPHASE_EX_NONE           0
 /*  used when p2p enabled and want to do 1 scan phase and
@@ -1035,13 +1007,13 @@ enum P2P_STATE {
        P2P_STATE_TX_PROVISION_DIS_REQ = 6,
        P2P_STATE_RX_PROVISION_DIS_RSP = 7,
        P2P_STATE_RX_PROVISION_DIS_REQ = 8,
-       /* Doing the group owner negoitation handshake */
+       /* Doing the group owner negotiation handshake */
        P2P_STATE_GONEGO_ING = 9,
-       /* finish the group negoitation handshake with success */
+       /* finish the group negotiation handshake with success */
        P2P_STATE_GONEGO_OK = 10,
-       /* finish the group negoitation handshake with failure */
+       /* finish the group negotiation handshake with failure */
        P2P_STATE_GONEGO_FAIL = 11,
-       /* receiving the P2P Inviation request and match with the profile. */
+       /* receiving the P2P Invitation request and match with the profile. */
        P2P_STATE_RECV_INVITE_REQ_MATCH = 12,
        /* Doing the P2P WPS */
        P2P_STATE_PROVISIONING_ING = 13,
@@ -1051,17 +1023,17 @@ enum P2P_STATE {
        P2P_STATE_TX_INVITE_REQ = 15,
        /* Receiving the P2P Invitation response */
        P2P_STATE_RX_INVITE_RESP_OK = 16,
-       /* receiving the P2P Inviation request and dismatch with the profile. */
+       /* receiving the P2P Invitation request and dismatch with the profile. */
        P2P_STATE_RECV_INVITE_REQ_DISMATCH = 17,
-       /* receiving the P2P Inviation request and this wifi is GO. */
+       /* receiving the P2P Invitation request and this wifi is GO. */
        P2P_STATE_RECV_INVITE_REQ_GO = 18,
-       /* receiving the P2P Inviation request to join an existing P2P Group. */
+       /* receiving the P2P Invitation request to join an existing P2P Group. */
        P2P_STATE_RECV_INVITE_REQ_JOIN = 19,
-       /* recveing the P2P Inviation response with failure */
+       /* receiving the P2P Invitation response with failure */
        P2P_STATE_RX_INVITE_RESP_FAIL = 20,
-       /* receiving p2p negoitation response with information is not available */
+       /* receiving p2p negotiation response with information is not available */
        P2P_STATE_RX_INFOR_NOREADY = 21,
-       /* sending p2p negoitation response with information is not available */
+       /* sending p2p negotiation response with information is not available */
        P2P_STATE_TX_INFOR_NOREADY = 22,
 };
 
index 53b1bd8e99468068c78bec93f386aaa999d63e81..85b99da49a2d66c64862f2af0e002e9d00f5439a 100644 (file)
@@ -156,16 +156,6 @@ enum ndis_802_11_reload_def {
        Ndis802_11ReloadWEPKeys
 };
 
-/*  Key mapping keys require a BSSID */
-struct ndis_802_11_key {
-       u32           Length;             /*  Length of this structure */
-       u32           KeyIndex;
-       u32           KeyLength;          /*  length of key in bytes */
-       unsigned char BSSID[ETH_ALEN];
-       unsigned long long KeyRSC;
-       u8           KeyMaterial[32];  /* var len depending on above field */
-};
-
 struct ndis_802_11_remove_key {
        u32                   Length;        /*  Length */
        u32                   KeyIndex;
index 24a8f5ac96e56b103b527fd2813ec54026b85542..96c1c2d4a112c2b741ae63c35aa0d83ae8e6d79f 100644 (file)
@@ -32,6 +32,8 @@
 
 #include <rtw_iol.h>
 #include <linux/vmalloc.h>
+#include <linux/etherdevice.h>
+
 #include "osdep_intf.h"
 
 #define RTL_IOCTL_WPA_SUPPLICANT       (SIOCIWFIRSTPRIV + 30)
@@ -92,7 +94,7 @@ void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
        memset(&wrqu, 0, sizeof(union iwreq_data));
 
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-       memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+       eth_zero_addr(wrqu.ap_addr.sa_data);
 
        DBG_88E_LEVEL(_drv_always_, "indicate disassoc\n");
        wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
@@ -827,7 +829,7 @@ static int rtw_wx_set_pmkid(struct net_device *dev,
                for (j = 0; j < NUM_PMKID_CACHE; j++) {
                        if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
                                /*  BSSID is matched, the same AP => Remove this PMKID information and reset it. */
-                               memset(psecuritypriv->PMKIDList[j].Bssid, 0x00, ETH_ALEN);
+                               eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
                                psecuritypriv->PMKIDList[j].bUsed = false;
                                break;
                        }
@@ -1028,7 +1030,7 @@ static int rtw_wx_get_wap(struct net_device *dev,
 
        wrqu->ap_addr.sa_family = ARPHRD_ETHER;
 
-       memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+       eth_zero_addr(wrqu->ap_addr.sa_data);
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_wap\n"));
 
@@ -1037,7 +1039,7 @@ static int rtw_wx_get_wap(struct net_device *dev,
            ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) == true))
                memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
        else
-               memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+               eth_zero_addr(wrqu->ap_addr.sa_data);
        return 0;
 }
 
@@ -1796,11 +1798,9 @@ static int rtw_wx_set_gen_ie(struct net_device *dev,
                             struct iw_request_info *info,
                             union iwreq_data *wrqu, char *extra)
 {
-       int ret;
        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 
-       ret = rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
-       return ret;
+       return rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
 }
 
 static int rtw_wx_set_auth(struct net_device *dev,
index 1b892c424cb8be54c9cf70c94acca67530462697..baff1e2661d55b60ac88b5664f705dc87d4de835 100644 (file)
@@ -29,9 +29,12 @@ void rtw_init_mlme_timer(struct adapter *padapter)
 {
        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-       _init_timer(&(pmlmepriv->assoc_timer), padapter->pnetdev, _rtw_join_timeout_handler, padapter);
-       _init_timer(&(pmlmepriv->scan_to_timer), padapter->pnetdev, rtw_scan_timeout_handler, padapter);
-       _init_timer(&(pmlmepriv->dynamic_chk_timer), padapter->pnetdev, rtw_dynamic_check_timer_handlder, padapter);
+       setup_timer(&pmlmepriv->assoc_timer, _rtw_join_timeout_handler,
+                   (unsigned long)padapter);
+       setup_timer(&pmlmepriv->scan_to_timer, rtw_scan_timeout_handler,
+                   (unsigned long)padapter);
+       setup_timer(&pmlmepriv->dynamic_chk_timer,
+                   rtw_dynamic_check_timer_handlder, (unsigned long)padapter);
 }
 
 void rtw_os_indicate_connect(struct adapter *adapter)
@@ -60,7 +63,6 @@ void rtw_reset_securitypriv(struct adapter *adapter)
                /*  We have to backup the PMK information for WiFi PMK Caching test item. */
                /*  Backup the btkip_countermeasure information. */
                /*  When the countermeasure is trigger, the driver have to disconnect with AP for 60 seconds. */
-               memset(&backup_pmkid[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
                memcpy(&backup_pmkid[0], &adapter->securitypriv.PMKIDList[0], sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
                backup_index = adapter->securitypriv.PMKIDIndex;
                backup_counter = adapter->securitypriv.btkip_countermeasure;
@@ -131,15 +133,18 @@ void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie)
 
 void init_addba_retry_timer(struct adapter *padapter, struct sta_info *psta)
 {
-       _init_timer(&psta->addba_retry_timer, padapter->pnetdev, addba_timer_hdl, psta);
+       setup_timer(&psta->addba_retry_timer, addba_timer_hdl,
+                   (unsigned long)psta);
 }
 
 void init_mlme_ext_timer(struct adapter *padapter)
 {
        struct  mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 
-       _init_timer(&pmlmeext->survey_timer, padapter->pnetdev, survey_timer_hdl, padapter);
-       _init_timer(&pmlmeext->link_timer, padapter->pnetdev, link_timer_hdl, padapter);
+       setup_timer(&pmlmeext->survey_timer, survey_timer_hdl,
+                   (unsigned long)padapter);
+       setup_timer(&pmlmeext->link_timer, link_timer_hdl,
+                   (unsigned long)padapter);
 }
 
 #ifdef CONFIG_88EU_AP_MODE
index 88a909c9e4577c26548e3e254a8f227305827941..750c87b46365bd317201280beb8b7a6c703579f5 100644 (file)
@@ -38,7 +38,7 @@ MODULE_VERSION(DRIVERVERSION);
 #define RTW_NOTCH_FILTER 0 /* 0:Disable, 1:Enable, */
 
 /* module param defaults */
-static int rtw_chip_version = 0x00;
+static int rtw_chip_version;
 static int rtw_rfintfs = HWPI;
 static int rtw_lbkmode;/* RTL8712_AIR_TRX; */
 static int rtw_network_mode = Ndis802_11IBSS;/* Ndis802_11Infrastructure; infra, ad-hoc, auto */
@@ -998,7 +998,8 @@ int _netdev_open(struct net_device *pnetdev)
        }
        padapter->net_closed = false;
 
-       _set_timer(&padapter->mlmepriv.dynamic_chk_timer, 2000);
+       mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
+                 jiffies + msecs_to_jiffies(2000));
 
        padapter->pwrctrlpriv.bips_processing = false;
        rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
@@ -1052,7 +1053,8 @@ static int  ips_netdrv_open(struct adapter *padapter)
                padapter->intf_start(padapter);
 
        rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
-       _set_timer(&padapter->mlmepriv.dynamic_chk_timer, 5000);
+       mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
+                 jiffies + msecs_to_jiffies(5000));
 
         return _SUCCESS;
 
index 05427c489b3f7d6010c79660b3de8803976565eb..05701328dce408bf63d9827b42f39d998f49095b 100644 (file)
@@ -193,7 +193,8 @@ _recv_indicatepkt_drop:
 
 void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
 {
-       struct adapter *padapter = preorder_ctrl->padapter;
 
-       _init_timer(&(preorder_ctrl->reordering_ctrl_timer), padapter->pnetdev, rtw_reordering_ctrl_timeout_handler, preorder_ctrl);
+       setup_timer(&preorder_ctrl->reordering_ctrl_timer,
+                   rtw_reordering_ctrl_timeout_handler,
+                   (unsigned long)preorder_ctrl);
 }
index bee39c2278f18115935601ad4c985d031c235ce0..ef3c73e38172589147749a67ba3ca4c8e7fe799e 100644 (file)
@@ -179,7 +179,7 @@ static void usb_intf_stop(struct adapter *padapter)
 {
        RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_stop\n"));
 
-       /* disabel_hw_interrupt */
+       /* disable_hw_interrupt */
        if (!padapter->bSurpriseRemoved) {
                /* device still exists, so driver can do i/o operation */
                /* TODO: */
index 80e7ef96d807e4f7d5fae5439102fd413b9d3042..7e599bc5b2d3c9f515bb2c3bb94eb1e702a8cd12 100644 (file)
@@ -530,6 +530,7 @@ void usb_read_port_cancel(struct adapter *padapter)
 {
        int i;
        struct recv_buf *precvbuf;
+
        precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
 
        DBG_88E("%s\n", __func__);
@@ -552,7 +553,6 @@ int usb_write8(struct adapter *adapter, u32 addr, u8 val)
        u16 index;
        u16 len;
        u8 data;
-       int ret;
 
        request = 0x05;
        requesttype = 0x00;/* write_out */
@@ -560,8 +560,8 @@ int usb_write8(struct adapter *adapter, u32 addr, u8 val)
        wvalue = (u16)(addr&0x0000ffff);
        len = 1;
        data = val;
-       ret = usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
-       return ret;
+       return usbctrl_vendorreq(adapter, request, wvalue,
+                                index, &data, len, requesttype);
 }
 
 int usb_write16(struct adapter *adapter, u32 addr, u16 val)
@@ -572,7 +572,6 @@ int usb_write16(struct adapter *adapter, u32 addr, u16 val)
        u16 index;
        u16 len;
        __le32 data;
-       int ret;
 
 
        request = 0x05;
@@ -584,10 +583,10 @@ int usb_write16(struct adapter *adapter, u32 addr, u16 val)
 
        data = cpu_to_le32(val & 0x0000ffff);
 
-       ret = usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
+       return usbctrl_vendorreq(adapter, request, wvalue,
+                                index, &data, len, requesttype);
 
 
-       return ret;
 }
 
 int usb_write32(struct adapter *adapter, u32 addr, u32 val)
@@ -598,7 +597,6 @@ int usb_write32(struct adapter *adapter, u32 addr, u32 val)
        u16 index;
        u16 len;
        __le32 data;
-       int ret;
 
 
        request = 0x05;
@@ -609,10 +607,10 @@ int usb_write32(struct adapter *adapter, u32 addr, u32 val)
        len = 4;
        data = cpu_to_le32(val);
 
-       ret = usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
+       return usbctrl_vendorreq(adapter, request, wvalue,
+                                index, &data, len, requesttype);
 
 
-       return ret;
 }
 
 static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
index eeea50260f1d08368ade615e22420945b97c6581..aad3394392fee282d2680d1ac0f78f244c38ff0a 100644 (file)
@@ -74,16 +74,11 @@ static inline void cpMacAddr(unsigned char *des, unsigned char *src)
        (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
 
 #define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa)            \
-        eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
+        ether_addr_equal_unaligned(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, \
+       __pTa)
 #define UPDATE_CIE_SRC(__pIeeeDev, __pTa)              \
        cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
 
-#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \
-       (((__Ie).Length == 0 || (__Ie).Length !=        \
-       GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ?    \
-       false : (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf,     \
-       (__Ie).Octet, (__Ie).Length)))
-
 #define CIE_WATCHDOG_TH 1
 #define GET_CIE_WATCHDOG(__pIeeeDev)                           \
         (GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog)
index 0e6bdd222e75350f45f7ad305dd0ce9572c14190..01d2201afc94da23a5ebc7db3204ea320fce1ab3 100644 (file)
@@ -47,8 +47,8 @@ void PHY_SetRF8256Bandwidth(struct net_device *dev,
                                                0x0e, bMask12Bits, 0x021);
 
                        } else {
-                               RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): "
-                                        "unknown hardware version\n");
+                               RT_TRACE(COMP_ERR,
+                                        "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
                        }
 
                        break;
@@ -66,15 +66,16 @@ void PHY_SetRF8256Bandwidth(struct net_device *dev,
                                                 0x0e, bMask12Bits, 0x0e1);
 
                        } else {
-                               RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): "
-                                        "unknown hardware version\n");
+                               RT_TRACE(COMP_ERR,
+                                        "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
                        }
 
 
                        break;
                default:
-                       RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown "
-                                "Bandwidth: %#X\n", Bandwidth);
+                       RT_TRACE(COMP_ERR,
+                                "PHY_SetRF8256Bandwidth(): unknown Bandwidth: %#X\n",
+                                Bandwidth);
                        break;
 
                }
@@ -138,8 +139,9 @@ bool phy_RF8256_Config_ParaFile(struct net_device *dev)
                rtStatus = rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF,
                                                (enum rf90_radio_path)eRFPath);
                if (!rtStatus) {
-                       RT_TRACE(COMP_ERR, "PHY_RF8256_Config():Check "
-                                "Radio[%d] Fail!!\n", eRFPath);
+                       RT_TRACE(COMP_ERR,
+                                "PHY_RF8256_Config():Check Radio[%d] Fail!!\n",
+                                eRFPath);
                        goto phy_RF8256_Config_ParaFile_Fail;
                }
 
@@ -155,9 +157,10 @@ bool phy_RF8256_Config_ParaFile(struct net_device *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);
+                               RT_TRACE(COMP_RF,
+                                        "RF %d %d register final value: %x\n",
+                                        eRFPath, RegOffSetToBeCheck,
+                                        RF3_Final_Value);
                                RetryTimes--;
                        }
                        break;
@@ -170,9 +173,10 @@ bool phy_RF8256_Config_ParaFile(struct net_device *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);
+                               RT_TRACE(COMP_RF,
+                                        "RF %d %d register final value: %x\n",
+                                        eRFPath, RegOffSetToBeCheck,
+                                        RF3_Final_Value);
                                RetryTimes--;
                        }
                        break;
@@ -185,9 +189,10 @@ bool phy_RF8256_Config_ParaFile(struct net_device *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);
+                               RT_TRACE(COMP_RF,
+                                        "RF %d %d register final value: %x\n",
+                                        eRFPath, RegOffSetToBeCheck,
+                                        RF3_Final_Value);
                                RetryTimes--;
                        }
                        break;
@@ -199,9 +204,10 @@ bool phy_RF8256_Config_ParaFile(struct net_device *dev)
                                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);
+                               RT_TRACE(COMP_RF,
+                                        "RF %d %d register final value: %x\n",
+                                        eRFPath, RegOffSetToBeCheck,
+                                        RF3_Final_Value);
                                RetryTimes--;
                        }
                        break;
@@ -221,8 +227,9 @@ bool phy_RF8256_Config_ParaFile(struct net_device *dev)
                }
 
                if (ret) {
-                       RT_TRACE(COMP_ERR, "phy_RF8256_Config_ParaFile():"
-                                "Radio[%d] Fail!!", eRFPath);
+                       RT_TRACE(COMP_ERR,
+                                "phy_RF8256_Config_ParaFile():Radio[%d] Fail!!",
+                                eRFPath);
                        goto phy_RF8256_Config_ParaFile_Fail;
                }
 
index 2b1430d66adb211d04540ce32dc414db9ff67de8..ecdd2e5c6baccbf0aae4b3c1eb53fdae2546cf61 100644 (file)
@@ -46,7 +46,7 @@ bool cmpk_message_handle_tx(
 
        do {
                if ((buffer_len - frag_offset) > frag_threshold) {
-                       frag_length = frag_threshold ;
+                       frag_length = frag_threshold;
                        bLastIniPkt = 0;
 
                } else {
@@ -165,7 +165,7 @@ static void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev)
 
 static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg)
 {
-       struct cmpk_intr_sta rx_intr_status;    /* */
+       struct cmpk_intr_sta rx_intr_status;
        struct r8192_priv *priv = rtllib_priv(dev);
 
        DMESG("---> cmpk_Handle_Interrupt_Status()\n");
@@ -332,44 +332,44 @@ u32 cmpk_message_handle_rx(struct net_device *dev,
 
                switch (element_id) {
                case RX_TX_FEEDBACK:
-                       RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
-                                "RX_TX_FEEDBACK\n");
+                       RT_TRACE(COMP_CMDPKT,
+                                "---->cmpk_message_handle_rx():RX_TX_FEEDBACK\n");
                        cmpk_handle_tx_feedback(dev, pcmd_buff);
                        cmd_length = CMPK_RX_TX_FB_SIZE;
                        break;
                case RX_INTERRUPT_STATUS:
-                       RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
-                                "RX_INTERRUPT_STATUS\n");
+                       RT_TRACE(COMP_CMDPKT,
+                                "---->cmpk_message_handle_rx():RX_INTERRUPT_STATUS\n");
                        cmpk_handle_interrupt_status(dev, pcmd_buff);
                        cmd_length = sizeof(struct cmpk_intr_sta);
                        break;
                case BOTH_QUERY_CONFIG:
-                       RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
-                                "BOTH_QUERY_CONFIG\n");
+                       RT_TRACE(COMP_CMDPKT,
+                                "---->cmpk_message_handle_rx():BOTH_QUERY_CONFIG\n");
                        cmpk_handle_query_config_rx(dev, pcmd_buff);
                        cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
                        break;
                case RX_TX_STATUS:
-                       RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
-                                "RX_TX_STATUS\n");
+                       RT_TRACE(COMP_CMDPKT,
+                                "---->cmpk_message_handle_rx():RX_TX_STATUS\n");
                        cmpk_handle_tx_status(dev, pcmd_buff);
                        cmd_length = CMPK_RX_TX_STS_SIZE;
                        break;
                case RX_TX_PER_PKT_FEEDBACK:
-                       RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
-                                "RX_TX_PER_PKT_FEEDBACK\n");
+                       RT_TRACE(COMP_CMDPKT,
+                                "---->cmpk_message_handle_rx():RX_TX_PER_PKT_FEEDBACK\n");
                        cmd_length = CMPK_RX_TX_FB_SIZE;
                        break;
                case RX_TX_RATE_HISTORY:
-                       RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
-                                "RX_TX_HISTORY\n");
+                       RT_TRACE(COMP_CMDPKT,
+                                "---->cmpk_message_handle_rx():RX_TX_HISTORY\n");
                        cmpk_handle_tx_rate_history(dev, pcmd_buff);
                        cmd_length = CMPK_TX_RAHIS_SIZE;
                        break;
                default:
 
-                       RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
-                                "unknown CMD Element\n");
+                       RT_TRACE(COMP_CMDPKT,
+                                "---->cmpk_message_handle_rx():unknown CMD Element\n");
                        return 1;
                }
 
index 23219e17e5a192ad0b6a91ed39da863401142613..2693682644df87a2de57dfa73b6adbd461d81855 100644 (file)
 struct cmpk_txfb {
        u8      element_id;
        u8      length;
-       u8      TID:4;                          /* */
-       u8      fail_reason:3;          /* */
+       u8      TID:4;
+       u8      fail_reason:3;
        u8      tok:1;
-       u8      reserve1:4;                     /* */
-       u8      pkt_type:2;             /* */
-       u8      bandwidth:1;            /* */
-       u8      qos_pkt:1;                      /* */
+       u8      reserve1:4;
+       u8      pkt_type:2;
+       u8      bandwidth:1;
+       u8      qos_pkt:1;
 
-       u8      reserve2;                       /* */
-       u8      retry_cnt;                      /* */
-       u16     pkt_id;                         /* */
+       u8      reserve2;
+       u8      retry_cnt;
+       u16     pkt_id;
 
-       u16     seq_num;                        /* */
+       u16     seq_num;
        u8      s_rate;
        u8      f_rate;
 
-       u8      s_rts_rate;                     /* */
-       u8      f_rts_rate;                     /* */
-       u16     pkt_length;                     /* */
+       u8      s_rts_rate;
+       u8      f_rts_rate;
+       u16     pkt_length;
 
-       u16     reserve3;                       /* */
-       u16     duration;                       /* */
+       u16     reserve3;
+       u16     duration;
 };
 
 struct cmpk_intr_sta {
index 552d943b1761c459a86dd25a6b6c33a6ee1abfa8..2869602436ef15a7dd58c8d5b1625c6cd5a83996 100644 (file)
@@ -224,8 +224,8 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
                        break;
 
                default:
-                       printk(KERN_INFO "SetHwReg8185(): invalid ACI: %d !\n",
-                              eACI);
+                       netdev_info(dev, "SetHwReg8185(): invalid ACI: %d !\n",
+                                   eACI);
                        break;
                }
                priv->rtllib->SetHwRegHandler(dev, HW_VAR_ACM_CTRL,
@@ -263,9 +263,9 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
                                break;
 
                        default:
-                               RT_TRACE(COMP_QOS, "SetHwReg8185(): [HW_VAR_"
-                                        "ACM_CTRL] acm set failed: eACI is "
-                                        "%d\n", eACI);
+                               RT_TRACE(COMP_QOS,
+                                        "SetHwReg8185(): [HW_VAR_ACM_CTRL] acm set failed: eACI is %d\n",
+                                        eACI);
                                break;
                        }
                } else {
@@ -287,8 +287,9 @@ 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);
+               RT_TRACE(COMP_QOS,
+                        "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n",
+                        AcmCtrl);
                write_nic_byte(dev, AcmHwCtrl, AcmCtrl);
                break;
        }
@@ -334,17 +335,17 @@ 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 = eprom_read(dev, EEPROM_VID >> 1);
+               priv->eeprom_did = eprom_read(dev, EEPROM_DID >> 1);
 
                usValue = eprom_read(dev, (u16)(EEPROM_Customer_ID>>1)) >> 8;
                priv->eeprom_CustomerID = (u8)(usValue & 0xff);
-               usValue = eprom_read(dev, (EEPROM_ICVersion_ChannelPlan>>1));
+               usValue = eprom_read(dev, EEPROM_ICVersion_ChannelPlan>>1);
                priv->eeprom_ChannelPlan = usValue&0xff;
-               IC_Version = ((usValue&0xff00)>>8);
+               IC_Version = (usValue & 0xff00)>>8;
 
                ICVer8192 = (IC_Version&0xf);
-               ICVer8256 = ((IC_Version&0xf0)>>4);
+               ICVer8256 = (IC_Version & 0xf0)>>4;
                RT_TRACE(COMP_INIT, "\nICVer8192 = 0x%x\n", ICVer8192);
                RT_TRACE(COMP_INIT, "\nICVer8256 = 0x%x\n", ICVer8256);
                if (ICVer8192 == 0x2) {
@@ -424,7 +425,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
                if (priv->epromtype == EEPROM_93C46) {
                        if (!priv->AutoloadFailFlag) {
                                usValue = eprom_read(dev,
-                                         (EEPROM_TxPwDiff_CrystalCap >> 1));
+                                         EEPROM_TxPwDiff_CrystalCap >> 1);
                                priv->EEPROMAntPwDiff = (usValue&0x0fff);
                                priv->EEPROMCrystalCap = (u8)((usValue & 0xf000)
                                                         >> 12);
@@ -448,12 +449,12 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
                                        usValue = EEPROM_Default_TxPower;
                                *((u16 *)(&priv->EEPROMTxPowerLevelCCK[i])) =
                                                                 usValue;
-                               RT_TRACE(COMP_INIT, "CCK Tx Power Level, Index"
-                                        " %d = 0x%02x\n", i,
-                                        priv->EEPROMTxPowerLevelCCK[i]);
-                               RT_TRACE(COMP_INIT, "CCK Tx Power Level, Index"
-                                        " %d = 0x%02x\n", i+1,
-                                        priv->EEPROMTxPowerLevelCCK[i+1]);
+                               RT_TRACE(COMP_INIT,
+                                        "CCK Tx Power Level, Index %d = 0x%02x\n",
+                                        i, priv->EEPROMTxPowerLevelCCK[i]);
+                               RT_TRACE(COMP_INIT,
+                                        "CCK Tx Power Level, Index %d = 0x%02x\n",
+                                        i+1, priv->EEPROMTxPowerLevelCCK[i+1]);
                        }
                        for (i = 0; i < 14; i += 2) {
                                if (!priv->AutoloadFailFlag)
@@ -464,11 +465,12 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
                                        usValue = EEPROM_Default_TxPower;
                                *((u16 *)(&priv->EEPROMTxPowerLevelOFDM24G[i]))
                                                         = usValue;
-                               RT_TRACE(COMP_INIT, "OFDM 2.4G Tx Power Level,"
-                                        " Index %d = 0x%02x\n", i,
-                                        priv->EEPROMTxPowerLevelOFDM24G[i]);
-                               RT_TRACE(COMP_INIT, "OFDM 2.4G Tx Power Level,"
-                                        " Index %d = 0x%02x\n", i + 1,
+                               RT_TRACE(COMP_INIT,
+                                        "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n",
+                                        i, priv->EEPROMTxPowerLevelOFDM24G[i]);
+                               RT_TRACE(COMP_INIT,
+                                        "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n",
+                                        i + 1,
                                         priv->EEPROMTxPowerLevelOFDM24G[i+1]);
                        }
                }
@@ -483,15 +485,15 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
                                         priv->EEPROMLegacyHTTxPowerDiff;
                        priv->AntennaTxPwDiff[0] = (priv->EEPROMAntPwDiff &
                                                    0xf);
-                       priv->AntennaTxPwDiff[1] = ((priv->EEPROMAntPwDiff &
-                                                   0xf0)>>4);
-                       priv->AntennaTxPwDiff[2] = ((priv->EEPROMAntPwDiff &
-                                                   0xf00)>>8);
+                       priv->AntennaTxPwDiff[1] = (priv->EEPROMAntPwDiff &
+                                                       0xf0) >> 4;
+                       priv->AntennaTxPwDiff[2] = (priv->EEPROMAntPwDiff &
+                                                       0xf00) >> 8;
                        priv->CrystalCap = priv->EEPROMCrystalCap;
                        priv->ThermalMeter[0] = (priv->EEPROMThermalMeter &
                                                 0xf);
-                       priv->ThermalMeter[1] = ((priv->EEPROMThermalMeter &
-                                                0xf0)>>4);
+                       priv->ThermalMeter[1] = (priv->EEPROMThermalMeter &
+                                                    0xf0) >> 4;
                } else if (priv->epromtype == EEPROM_93C56) {
 
                        for (i = 0; i < 3; i++) {
@@ -525,21 +527,21 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
                                         priv->EEPROMRfCOfdmChnlTxPwLevel[2];
                        }
                        for (i = 0; i < 14; i++)
-                               RT_TRACE(COMP_INIT, "priv->TxPowerLevelCCK_A"
-                                        "[%d] = 0x%x\n", i,
-                                        priv->TxPowerLevelCCK_A[i]);
+                               RT_TRACE(COMP_INIT,
+                                        "priv->TxPowerLevelCCK_A[%d] = 0x%x\n",
+                                        i, priv->TxPowerLevelCCK_A[i]);
                        for (i = 0; i < 14; i++)
-                               RT_TRACE(COMP_INIT, "priv->TxPowerLevelOFDM"
-                                        "24G_A[%d] = 0x%x\n", i,
-                                        priv->TxPowerLevelOFDM24G_A[i]);
+                               RT_TRACE(COMP_INIT,
+                                        "priv->TxPowerLevelOFDM24G_A[%d] = 0x%x\n",
+                                        i, priv->TxPowerLevelOFDM24G_A[i]);
                        for (i = 0; i < 14; i++)
-                               RT_TRACE(COMP_INIT, "priv->TxPowerLevelCCK_C"
-                                        "[%d] = 0x%x\n", i,
-                                        priv->TxPowerLevelCCK_C[i]);
+                               RT_TRACE(COMP_INIT,
+                                        "priv->TxPowerLevelCCK_C[%d] = 0x%x\n",
+                                        i, priv->TxPowerLevelCCK_C[i]);
                        for (i = 0; i < 14; i++)
-                               RT_TRACE(COMP_INIT, "priv->TxPowerLevelOFDM"
-                                        "24G_C[%d] = 0x%x\n", i,
-                                        priv->TxPowerLevelOFDM24G_C[i]);
+                               RT_TRACE(COMP_INIT,
+                                        "priv->TxPowerLevelOFDM24G_C[%d] = 0x%x\n",
+                                        i, priv->TxPowerLevelOFDM24G_C[i]);
                        priv->LegacyHTTxPowerDiff =
                                 priv->EEPROMLegacyHTTxPowerDiff;
                        priv->AntennaTxPwDiff[0] = 0;
@@ -548,8 +550,8 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
                        priv->CrystalCap = priv->EEPROMCrystalCap;
                        priv->ThermalMeter[0] = (priv->EEPROMThermalMeter &
                                                 0xf);
-                       priv->ThermalMeter[1] = ((priv->EEPROMThermalMeter &
-                                                0xf0)>>4);
+                       priv->ThermalMeter[1] = (priv->EEPROMThermalMeter &
+                                                    0xf0) >> 4;
                }
        }
 
@@ -735,8 +737,9 @@ start:
        else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
                ulRegRead |= CPU_GEN_FIRMWARE_RESET;
        else
-               RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)"
-                        "\n", __func__,   priv->pFirmware->firmware_status);
+               RT_TRACE(COMP_ERR,
+                        "ERROR in %s(): undefined firmware state(%d)\n",
+                        __func__,   priv->pFirmware->firmware_status);
 
        write_nic_dword(dev, CPU_GEN, ulRegRead);
 
@@ -766,8 +769,8 @@ start:
                else if (priv->LoopbackMode == RTL819X_MAC_LOOPBACK)
                        ulRegRead |= CPU_CCK_LOOPBACK;
                else
-                       RT_TRACE(COMP_ERR, "Serious error: wrong loopback"
-                                " mode setting\n");
+                       RT_TRACE(COMP_ERR,
+                                "Serious error: wrong loopback mode setting\n");
 
                write_nic_dword(dev, CPU_GEN, ulRegRead);
 
@@ -883,15 +886,15 @@ start:
                          __func__);
                MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_SW, true);
        } 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);
+               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);
        } 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);
+               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);
        } else {
@@ -939,17 +942,17 @@ start:
                        priv->CCKPresentAttentuation_difference = 0;
                        priv->CCKPresentAttentuation =
                                  priv->CCKPresentAttentuation_20Mdefault;
-                       RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpower"
-                                "trackingindex_initial = %d\n",
+                       RT_TRACE(COMP_POWER_TRACKING,
+                                "priv->rfa_txpowertrackingindex_initial = %d\n",
                                 priv->rfa_txpowertrackingindex);
-                       RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpower"
-                                "trackingindex_real__initial = %d\n",
+                       RT_TRACE(COMP_POWER_TRACKING,
+                                "priv->rfa_txpowertrackingindex_real__initial = %d\n",
                                 priv->rfa_txpowertrackingindex_real);
-                       RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresent"
-                                "Attentuation_difference_initial = %d\n",
+                       RT_TRACE(COMP_POWER_TRACKING,
+                                "priv->CCKPresentAttentuation_difference_initial = %d\n",
                                  priv->CCKPresentAttentuation_difference);
-                       RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresent"
-                                "Attentuation_initial = %d\n",
+                       RT_TRACE(COMP_POWER_TRACKING,
+                                "priv->CCKPresentAttentuation_initial = %d\n",
                                 priv->CCKPresentAttentuation);
                        priv->btxpower_tracking = false;
                }
@@ -1169,8 +1172,9 @@ static u8 rtl8192_MapHwQueueToFirmwareQueue(u8 QueueID, u8 priority)
                QueueSelect = QSLT_HIGH;
                break;
        default:
-               RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection:"
-                        " %d\n", QueueID);
+               RT_TRACE(COMP_ERR,
+                        "TransmitTCB(): Impossible Queue Selection: %d\n",
+                        QueueID);
                break;
        }
        return QueueSelect;
@@ -1361,9 +1365,10 @@ static u8 HwRateToMRate90(bool bIsHT, u8 rate)
                        break;
 
                default:
-                       RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported"
-                                "Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
-                                                 break;
+                       RT_TRACE(COMP_RECV,
+                                "HwRateToMRate90(): Non supportedRate [%x], bIsHT = %d!!!\n",
+                                rate, bIsHT);
+                       break;
                }
 
        } else {
@@ -1421,8 +1426,9 @@ static u8 HwRateToMRate90(bool bIsHT, u8 rate)
                        break;
 
                default:
-                       RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported "
-                                "Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
+                       RT_TRACE(COMP_RECV,
+                                "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n",
+                                rate, bIsHT);
                        break;
                }
        }
@@ -1527,7 +1533,7 @@ static void rtl8192_query_rxphystatus(
                priv->stats.numqry_phystatusCCK++;
                if (!reg824_bit9) {
                        report = pcck_buf->cck_agc_rpt & 0xc0;
-                       report = report>>6;
+                       report >>= 6;
                        switch (report) {
                        case 0x3:
                                rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt &
@@ -1547,7 +1553,7 @@ static void rtl8192_query_rxphystatus(
                        }
                } else {
                        report = pcck_buf->cck_agc_rpt & 0x60;
-                       report = report>>5;
+                       report >>= 5;
                        switch (report) {
                        case 0x3:
                                rx_pwr_all = -35 -
@@ -1737,8 +1743,8 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
                        if (!rtl8192_phy_CheckIsLegalRFPath(priv->rtllib->dev,
                            rfpath))
                                continue;
-                       RT_TRACE(COMP_DBG, "Jacken -> pPreviousstats->RxMIMO"
-                                "SignalStrength[rfpath]  = %d\n",
+                       RT_TRACE(COMP_DBG,
+                                "Jacken -> pPreviousstats->RxMIMOSignalStrength[rfpath]  = %d\n",
                                 prev_st->RxMIMOSignalStrength[rfpath]);
                        if (priv->stats.rx_rssi_percentage[rfpath] == 0) {
                                priv->stats.rx_rssi_percentage[rfpath] =
@@ -1761,8 +1767,8 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
                                   (prev_st->RxMIMOSignalStrength[rfpath])) /
                                   (RX_SMOOTH);
                        }
-                       RT_TRACE(COMP_DBG, "Jacken -> priv->RxStats.RxRSSI"
-                                "Percentage[rfPath]  = %d\n",
+                       RT_TRACE(COMP_DBG,
+                                "Jacken -> priv->RxStats.RxRSSIPercentage[rfPath]  = %d\n",
                                 priv->stats.rx_rssi_percentage[rfpath]);
                }
        }
@@ -2019,6 +2025,7 @@ bool rtl8192_rx_query_status_desc(struct net_device *dev,
                                  struct sk_buff *skb)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
+       struct rx_fwinfo *pDrvInfo = NULL;
 
        stats->bICV = pdesc->ICV;
        stats->bCRC = pdesc->CRC32;
@@ -2040,51 +2047,49 @@ bool rtl8192_rx_query_status_desc(struct net_device *dev,
                                priv->stats.rxcrcerrmid++;
                }
                return false;
-       } else {
-               struct rx_fwinfo *pDrvInfo = NULL;
+       }
 
-               stats->RxDrvInfoSize = pdesc->RxDrvInfoSize;
-               stats->RxBufShift = ((pdesc->Shift)&0x03);
-               stats->Decrypted = !pdesc->SWDec;
+       stats->RxDrvInfoSize = pdesc->RxDrvInfoSize;
+       stats->RxBufShift = ((pdesc->Shift)&0x03);
+       stats->Decrypted = !pdesc->SWDec;
 
-               pDrvInfo = (struct rx_fwinfo *)(skb->data + stats->RxBufShift);
+       pDrvInfo = (struct rx_fwinfo *)(skb->data + stats->RxBufShift);
 
-               stats->rate = HwRateToMRate90((bool)pDrvInfo->RxHT,
-                                            (u8)pDrvInfo->RxRate);
-               stats->bShortPreamble = pDrvInfo->SPLCP;
+       stats->rate = HwRateToMRate90((bool)pDrvInfo->RxHT,
+                                    (u8)pDrvInfo->RxRate);
+       stats->bShortPreamble = pDrvInfo->SPLCP;
 
-               rtl8192_UpdateReceivedRateHistogramStatistics(dev, stats);
+       rtl8192_UpdateReceivedRateHistogramStatistics(dev, stats);
 
-               stats->bIsAMPDU = (pDrvInfo->PartAggr == 1);
-               stats->bFirstMPDU = (pDrvInfo->PartAggr == 1) &&
-                                   (pDrvInfo->FirstAGGR == 1);
+       stats->bIsAMPDU = (pDrvInfo->PartAggr == 1);
+       stats->bFirstMPDU = (pDrvInfo->PartAggr == 1) &&
+                           (pDrvInfo->FirstAGGR == 1);
 
-               stats->TimeStampLow = pDrvInfo->TSFL;
-               stats->TimeStampHigh = read_nic_dword(dev, TSFR+4);
+       stats->TimeStampLow = pDrvInfo->TSFL;
+       stats->TimeStampHigh = read_nic_dword(dev, TSFR+4);
 
-               rtl819x_UpdateRxPktTimeStamp(dev, stats);
+       rtl819x_UpdateRxPktTimeStamp(dev, stats);
 
-               if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0)
-                       stats->bShift = 1;
+       if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0)
+               stats->bShift = 1;
 
-               stats->RxIs40MHzPacket = pDrvInfo->BW;
+       stats->RxIs40MHzPacket = pDrvInfo->BW;
 
-               rtl8192_TranslateRxSignalStuff(dev, skb, stats, pdesc,
-                                              pDrvInfo);
+       rtl8192_TranslateRxSignalStuff(dev, skb, stats, pdesc,
+                                      pDrvInfo);
 
-               if (pDrvInfo->FirstAGGR == 1 || pDrvInfo->PartAggr == 1)
-                       RT_TRACE(COMP_RXDESC, "pDrvInfo->FirstAGGR = %d,"
-                                " pDrvInfo->PartAggr = %d\n",
-                                pDrvInfo->FirstAGGR, pDrvInfo->PartAggr);
-               skb_trim(skb, skb->len - 4/*sCrcLng*/);
+       if (pDrvInfo->FirstAGGR == 1 || pDrvInfo->PartAggr == 1)
+               RT_TRACE(COMP_RXDESC,
+                        "pDrvInfo->FirstAGGR = %d, pDrvInfo->PartAggr = %d\n",
+                        pDrvInfo->FirstAGGR, pDrvInfo->PartAggr);
+       skb_trim(skb, skb->len - 4/*sCrcLng*/);
 
 
-               stats->packetlength = stats->Length-4;
-               stats->fraglength = stats->packetlength;
-               stats->fragoffset = 0;
-               stats->ntotalfrag = 1;
-               return true;
-       }
+       stats->packetlength = stats->Length-4;
+       stats->fraglength = stats->packetlength;
+       stats->fragoffset = 0;
+       stats->ntotalfrag = 1;
+       return true;
 }
 
 void rtl8192_halt_adapter(struct net_device *dev, bool reset)
@@ -2132,7 +2137,6 @@ void rtl8192_halt_adapter(struct net_device *dev, bool reset)
                skb_queue_purge(&priv->rtllib->skb_aggQ[i]);
 
        skb_queue_purge(&priv->skb_queue);
-       return;
 }
 
 void rtl8192_update_ratr_table(struct net_device *dev)
@@ -2191,8 +2195,7 @@ rtl8192_InitializeVariables(struct net_device  *dev)
 
        priv->rtllib->softmac_features  = IEEE_SOFTMAC_SCAN |
                IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
-               IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE /* |
-               IEEE_SOFTMAC_BEACONS*/;
+               IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE;
 
        priv->rtllib->tx_headroom = sizeof(struct tx_fwinfo_8190pci);
 
@@ -2308,8 +2311,7 @@ bool rtl8192_HalRxCheckStuck(struct net_device *dev)
          (priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_20M)))) {
                if (rx_chk_cnt < 2)
                        return bStuck;
-               else
-                       rx_chk_cnt = 0;
+               rx_chk_cnt = 0;
        } else if ((((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) &&
                  (priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_40M)) ||
                ((priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) &&
@@ -2317,13 +2319,11 @@ bool rtl8192_HalRxCheckStuck(struct net_device *dev)
                priv->undecorated_smoothed_pwdb >= VeryLowRSSI) {
                if (rx_chk_cnt < 4)
                        return bStuck;
-               else
-                       rx_chk_cnt = 0;
+               rx_chk_cnt = 0;
        } else {
                if (rx_chk_cnt < 8)
                        return bStuck;
-               else
-                       rx_chk_cnt = 0;
+               rx_chk_cnt = 0;
        }
 
 
@@ -2413,5 +2413,4 @@ void ActUpdateChannelAccessSetting(struct net_device *dev,
        enum wireless_mode WirelessMode,
        struct channel_access_setting *ChnlAccessSetting)
 {
-       return;
 }
index 2e28744b9aab630ec5120512cbfa4d0ecad79ebb..c465f8749acda2781d64d54e6d785efef4064c0c 100644 (file)
@@ -36,7 +36,6 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
                             u32 buffer_len)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
-       bool                rt_status = true;
        u16                 frag_threshold;
        u16                 frag_length, frag_offset = 0;
        int                 i;
@@ -51,7 +50,7 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
        frag_threshold = pfirmware->cmdpacket_frag_thresold;
        do {
                if ((buffer_len - frag_offset) > frag_threshold) {
-                       frag_length = frag_threshold ;
+                       frag_length = frag_threshold;
                        bLastIniPkt = 0;
 
                } else {
@@ -84,8 +83,8 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
                if (!priv->rtllib->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
                    (!skb_queue_empty(&priv->rtllib->skb_waitQ[tcb_desc->queue_index])) ||
                    (priv->rtllib->queue_stop)) {
-                       RT_TRACE(COMP_FIRMWARE, "===================> tx "
-                                "full!\n");
+                       RT_TRACE(COMP_FIRMWARE,
+                                "===================> tx full!\n");
                        skb_queue_tail(&priv->rtllib->skb_waitQ
                                        [tcb_desc->queue_index], skb);
                } else {
@@ -99,7 +98,7 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
 
        write_nic_byte(dev, TPPoll, TPPoll_CQ);
 
-       return rt_status;
+       return true;
 }
 
 static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
@@ -108,7 +107,7 @@ static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
        u32             CPU_status = 0;
        unsigned long   timeout;
 
-       timeout = jiffies + MSECS(200);
+       timeout = jiffies + msecs_to_jiffies(200);
        while (time_before(jiffies, timeout)) {
                CPU_status = read_nic_dword(dev, CPU_GEN);
                if (CPU_status & CPU_GEN_PUT_CODE_OK)
@@ -128,7 +127,7 @@ static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
                       (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
        mdelay(1);
 
-       timeout = jiffies + MSECS(200);
+       timeout = jiffies + msecs_to_jiffies(200);
        while (time_before(jiffies, timeout)) {
                CPU_status = read_nic_dword(dev, CPU_GEN);
                if (CPU_status&CPU_GEN_BOOT_RDY)
@@ -156,7 +155,7 @@ static bool CPUcheck_firmware_ready(struct net_device *dev)
        u32     CPU_status = 0;
        unsigned long timeout;
 
-       timeout = jiffies + MSECS(20);
+       timeout = jiffies + msecs_to_jiffies(20);
        while (time_before(jiffies, timeout)) {
                CPU_status = read_nic_dword(dev, CPU_GEN);
                if (CPU_status&CPU_GEN_FIRM_RDY)
@@ -197,8 +196,8 @@ static bool firmware_check_ready(struct net_device *dev,
                if (rt_status)
                        pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
                else
-                       RT_TRACE(COMP_FIRMWARE, "CPUcheck_maincodeok_turnon"
-                                "CPU fail!\n");
+                       RT_TRACE(COMP_FIRMWARE,
+                                "CPUcheck_maincodeok_turnonCPU fail!\n");
 
                break;
 
@@ -210,8 +209,9 @@ static bool firmware_check_ready(struct net_device *dev,
                if (rt_status)
                        pfirmware->firmware_status = FW_STATUS_5_READY;
                else
-                       RT_TRACE(COMP_FIRMWARE, "CPUcheck_firmware_ready fail"
-                                "(%d)!\n", rt_status);
+                       RT_TRACE(COMP_FIRMWARE,
+                                "CPUcheck_firmware_ready fail(%d)!\n",
+                                rt_status);
 
                break;
        default:
@@ -246,8 +246,8 @@ bool init_firmware(struct net_device *dev)
                rst_opt = OPT_FIRMWARE_RESET;
                starting_state = FW_INIT_STEP2_DATA;
        } else {
-               RT_TRACE(COMP_FIRMWARE, "PlatformInitFirmware: undefined"
-                        " firmware state\n");
+               RT_TRACE(COMP_FIRMWARE,
+                        "PlatformInitFirmware: undefined firmware state\n");
        }
 
        for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA;
@@ -266,14 +266,14 @@ bool init_firmware(struct net_device *dev)
                                                      fw_name[init_step],
                                                      &priv->pdev->dev);
                                if (rc < 0) {
-                                       RT_TRACE(COMP_FIRMWARE, "request firmware fail!\n");
+                                       RT_TRACE(COMP_FIRMWARE,
+                                                "request firmware fail!\n");
                                        goto download_firmware_fail;
                                }
                                if (fw_entry->size >
                                    sizeof(pfirmware->firmware_buf[init_step])) {
-                                       RT_TRACE(COMP_FIRMWARE, "img file size "
-                                                "exceed the container struct "
-                                                "buffer fail!\n");
+                                       RT_TRACE(COMP_FIRMWARE,
+                                                "img file size exceed the container struct buffer fail!\n");
                                        goto download_firmware_fail;
                                }
 
@@ -301,13 +301,11 @@ bool init_firmware(struct net_device *dev)
                file_length = pfirmware->firmware_buf_size[init_step];
 
                rt_status = fw_download_code(dev, mapped_file, file_length);
-               if (!rt_status) {
+               if (!rt_status)
                        goto download_firmware_fail;
-               }
 
-               if (!firmware_check_ready(dev, init_step)) {
+               if (!firmware_check_ready(dev, init_step))
                        goto download_firmware_fail;
-               }
        }
 
        RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
index 019836bb36c24d626af6ea42a75a40eac94dfce8..d804876dd92f82e795f296eabc4bdb325ed9bea8 100644 (file)
@@ -34,18 +34,18 @@ extern u32 Rtl8192PciEPHY_REGArray[PHY_REGArrayLengthPciE];
 #define PHY_REG_1T2RArrayLengthPciE 296
 extern u32 Rtl8192PciEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLengthPciE];
 #define RadioA_ArrayLengthPciE 246
-extern u32 Rtl8192PciERadioA_Array[RadioA_ArrayLengthPciE] ;
+extern u32 Rtl8192PciERadioA_Array[RadioA_ArrayLengthPciE];
 #define RadioB_ArrayLengthPciE 78
-extern u32 Rtl8192PciERadioB_Array[RadioB_ArrayLengthPciE] ;
+extern u32 Rtl8192PciERadioB_Array[RadioB_ArrayLengthPciE];
 #define RadioC_ArrayLengthPciE 2
-extern u32 Rtl8192PciERadioC_Array[RadioC_ArrayLengthPciE] ;
+extern u32 Rtl8192PciERadioC_Array[RadioC_ArrayLengthPciE];
 #define RadioD_ArrayLengthPciE 2
-extern u32 Rtl8192PciERadioD_Array[RadioD_ArrayLengthPciE] ;
+extern u32 Rtl8192PciERadioD_Array[RadioD_ArrayLengthPciE];
 #define MACPHY_ArrayLengthPciE 18
-extern u32 Rtl8192PciEMACPHY_Array[MACPHY_ArrayLengthPciE] ;
+extern u32 Rtl8192PciEMACPHY_Array[MACPHY_ArrayLengthPciE];
 #define MACPHY_Array_PGLengthPciE 30
-extern u32 Rtl8192PciEMACPHY_Array_PG[MACPHY_Array_PGLengthPciE] ;
+extern u32 Rtl8192PciEMACPHY_Array_PG[MACPHY_Array_PGLengthPciE];
 #define AGCTAB_ArrayLengthPciE 384
-extern u32 Rtl8192PciEAGCTAB_Array[AGCTAB_ArrayLengthPciE] ;
+extern u32 Rtl8192PciEAGCTAB_Array[AGCTAB_ArrayLengthPciE];
 
 #endif
index 8c08ef6a40a4443da823e577a7817b40bbf62958..4664a4fd1e48cd8b9cfa1c894ed481c1b8cc2612 100644 (file)
@@ -94,7 +94,6 @@ void rtl8192_setBBreg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask,
                write_nic_dword(dev, dwRegAddr, NewValue);
        } else
                write_nic_dword(dev, dwRegAddr, dwData);
-       return;
 }
 
 u32 rtl8192_QueryBBReg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask)
@@ -136,8 +135,8 @@ static u32 rtl8192_phy_RFSerialRead(struct net_device *dev,
                } else
                        NewOffset = Offset;
        } else {
-               RT_TRACE((COMP_PHY|COMP_ERR), "check RF type here, need"
-                        " to be 8256\n");
+               RT_TRACE((COMP_PHY|COMP_ERR),
+                        "check RF type here, need to be 8256\n");
                NewOffset = Offset;
        }
        rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadAddress,
@@ -192,8 +191,8 @@ static void rtl8192_phy_RFSerialWrite(struct net_device *dev,
                } else
                        NewOffset = Offset;
        } else {
-               RT_TRACE((COMP_PHY|COMP_ERR), "check RF type here, need to be"
-                        " 8256\n");
+               RT_TRACE((COMP_PHY|COMP_ERR),
+                        "check RF type here, need to be 8256\n");
                NewOffset = Offset;
        }
 
@@ -215,7 +214,6 @@ static void rtl8192_phy_RFSerialWrite(struct net_device *dev,
                }
                rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);
        }
-       return;
 }
 
 void rtl8192_phy_SetRFReg(struct net_device *dev, enum rf90_radio_path eRFPath,
@@ -256,7 +254,6 @@ void rtl8192_phy_SetRFReg(struct net_device *dev, enum rf90_radio_path eRFPath,
                } else
                        rtl8192_phy_RFSerialWrite(dev, eRFPath, RegAddr, Data);
        }
-       return;
 }
 
 u32 rtl8192_phy_QueryRFReg(struct net_device *dev, enum rf90_radio_path eRFPath,
@@ -307,7 +304,7 @@ static u32 phy_FwRFSerialRead(struct net_device *dev,
        }
        return read_nic_dword(dev, RF_DATA);
 
-}      /* phy_FwRFSerialRead */
+}
 
 static void phy_FwRFSerialWrite(struct net_device *dev,
                                enum rf90_radio_path eRFPath,
@@ -328,7 +325,7 @@ static void phy_FwRFSerialWrite(struct net_device *dev,
        }
        write_nic_dword(dev, QPNR, Data);
 
-}      /* phy_FwRFSerialWrite */
+}
 
 
 void rtl8192_phy_configmac(struct net_device *dev)
@@ -348,8 +345,8 @@ void rtl8192_phy_configmac(struct net_device *dev)
                pdwArray = Rtl819XMACPHY_Array;
        }
        for (i = 0; i < dwArrayLen; i += 3) {
-               RT_TRACE(COMP_DBG, "The Rtl8190MACPHY_Array[0] is %x Rtl8190MAC"
-                        "PHY_Array[1] is %x Rtl8190MACPHY_Array[2] is %x\n",
+               RT_TRACE(COMP_DBG,
+                        "The Rtl8190MACPHY_Array[0] is %x Rtl8190MACPHY_Array[1] is %x Rtl8190MACPHY_Array[2] is %x\n",
                         pdwArray[i], pdwArray[i+1], pdwArray[i+2]);
                if (pdwArray[i] == 0x318)
                        pdwArray[i+2] = 0x00000800;
@@ -383,8 +380,8 @@ void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType)
                        rtl8192_setBBreg(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",
+                       RT_TRACE(COMP_DBG,
+                                "i: %x, The Rtl819xUsbPHY_REGArray[0] is %x Rtl819xUsbPHY_REGArray[1] is %x\n",
                                 i, Rtl819XPHY_REGArray_Table[i],
                                 Rtl819XPHY_REGArray_Table[i+1]);
                }
@@ -393,13 +390,12 @@ void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType)
                        rtl8192_setBBreg(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],
+                       RT_TRACE(COMP_DBG,
+                                "i:%x, The rtl819XAGCTAB_Array[0] is %x rtl819XAGCTAB_Array[1] is %x\n",
+                                i, Rtl819XAGCTAB_Array_Table[i],
                                 Rtl819XAGCTAB_Array_Table[i+1]);
                }
        }
-       return;
 }
 
 static void rtl8192_InitBBRFRegDef(struct net_device *dev)
@@ -511,8 +507,8 @@ bool rtl8192_phy_checkBBAndRF(struct net_device *dev,
        for (i = 0; i < CheckTimes; i++) {
                switch (CheckBlock) {
                case HW90_BLOCK_MAC:
-                       RT_TRACE(COMP_ERR, "PHY_CheckBBRFOK(): Never Write "
-                                "0x100 here!");
+                       RT_TRACE(COMP_ERR,
+                                "PHY_CheckBBRFOK(): Never Write 0x100 here!");
                        break;
 
                case HW90_BLOCK_PHY0:
@@ -541,8 +537,9 @@ bool rtl8192_phy_checkBBAndRF(struct net_device *dev,
 
 
                if (dwRegRead != WriteData[i]) {
-                       RT_TRACE(COMP_ERR, "====>error=====dwRegRead: %x, "
-                                "WriteData: %x\n", dwRegRead, WriteData[i]);
+                       RT_TRACE(COMP_ERR,
+                                "====>error=====dwRegRead: %x, WriteData: %x\n",
+                                dwRegRead, WriteData[i]);
                        ret = false;
                        break;
                }
@@ -570,8 +567,9 @@ static bool rtl8192_BB_Config_ParaFile(struct net_device *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", eCheckItem-1);
+                       RT_TRACE((COMP_ERR | COMP_PHY),
+                                "PHY_RF8256_Config():Check PHY%d Fail!!\n",
+                                eCheckItem-1);
                        return rtStatus;
                }
        }
@@ -628,8 +626,8 @@ void rtl8192_phy_getTxPower(struct net_device *dev)
        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);
-       RT_TRACE(COMP_INIT, "Default initial gain (c50=0x%x, c58=0x%x, "
-               "c60=0x%x, c68=0x%x)\n",
+       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]);
 
@@ -638,7 +636,6 @@ void rtl8192_phy_getTxPower(struct net_device *dev)
        RT_TRACE(COMP_INIT, "Default framesync (0x%x) = 0x%x\n",
                rOFDM0_RxDetector3, priv->framesync);
        priv->SifsTime = read_nic_word(dev, SIFS);
-       return;
 }
 
 void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel)
@@ -692,7 +689,6 @@ void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel)
                         __func__);
                break;
        }
-       return;
 }
 
 bool rtl8192_phy_RFConfig(struct net_device *dev)
@@ -721,7 +717,6 @@ bool rtl8192_phy_RFConfig(struct net_device *dev)
 
 void rtl8192_phy_updateInitGain(struct net_device *dev)
 {
-       return;
 }
 
 u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
@@ -807,11 +802,10 @@ static void rtl8192_SetTxPowerLevel(struct net_device *dev, u8 channel)
        case RF_8258:
                break;
        default:
-               RT_TRACE(COMP_ERR, "unknown rf chip ID in rtl8192_SetTxPower"
-                        "Level()\n");
+               RT_TRACE(COMP_ERR,
+                        "unknown rf chip ID in rtl8192_SetTxPowerLevel()\n");
                break;
        }
-       return;
 }
 
 static u8 rtl8192_phy_SetSwChnlCmdArray(struct sw_chnl_cmd *CmdTable,
@@ -822,15 +816,14 @@ static u8 rtl8192_phy_SetSwChnlCmdArray(struct sw_chnl_cmd *CmdTable,
        struct sw_chnl_cmd *pCmd;
 
        if (CmdTable == NULL) {
-               RT_TRACE(COMP_ERR, "phy_SetSwChnlCmdArray(): CmdTable cannot "
-                        "be NULL.\n");
+               RT_TRACE(COMP_ERR,
+                        "phy_SetSwChnlCmdArray(): CmdTable cannot be NULL.\n");
                return false;
        }
        if (CmdTableIdx >= CmdTableSz) {
-               RT_TRACE(COMP_ERR, "phy_SetSwChnlCmdArray(): Access invalid"
-                        " index, please check size of the table, CmdTableIdx:"
-                        "%d, CmdTableSz:%d\n",
-                               CmdTableIdx, CmdTableSz);
+               RT_TRACE(COMP_ERR,
+                        "phy_SetSwChnlCmdArray(): Access invalid index, please check size of the table, CmdTableIdx:%d, CmdTableSz:%d\n",
+                        CmdTableIdx, CmdTableSz);
                return false;
        }
 
@@ -883,8 +876,9 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
                switch (priv->rf_chip) {
                case RF_8225:
                        if (!(channel >= 1 && channel <= 14)) {
-                               RT_TRACE(COMP_ERR, "illegal channel for Zebra "
-                                        "8225: %d\n", channel);
+                               RT_TRACE(COMP_ERR,
+                                        "illegal channel for Zebra 8225: %d\n",
+                                        channel);
                                return false;
                        }
                        rtl8192_phy_SetSwChnlCmdArray(ieee->RfDependCmd,
@@ -898,8 +892,9 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
 
                case RF_8256:
                        if (!(channel >= 1 && channel <= 14)) {
-                               RT_TRACE(COMP_ERR, "illegal channel for Zebra"
-                                        " 8256: %d\n", channel);
+                               RT_TRACE(COMP_ERR,
+                                        "illegal channel for Zebra 8256: %d\n",
+                                        channel);
                                return false;
                        }
                        rtl8192_phy_SetSwChnlCmdArray(ieee->RfDependCmd,
@@ -920,7 +915,6 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
                        RT_TRACE(COMP_ERR, "Unknown RFChipID: %d\n",
                                 priv->rf_chip);
                        return false;
-                       break;
                }
 
 
@@ -938,13 +932,11 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
                        }
 
                        if (CurrentCmd && CurrentCmd->CmdID == CmdID_End) {
-                               if ((*stage) == 2) {
+                               if ((*stage) == 2)
                                        return true;
-                               } else {
-                                       (*stage)++;
-                                       (*step) = 0;
-                                       continue;
-                               }
+                               (*stage)++;
+                               (*step) = 0;
+                               continue;
                        }
 
                        if (!CurrentCmd)
@@ -996,7 +988,7 @@ static void rtl8192_phy_FinishSwChnlNow(struct net_device *dev, u8 channel)
              &priv->SwChnlStep, &delay)) {
                if (delay > 0)
                        msleep(delay);
-               if (IS_NIC_DOWN(priv))
+               if (!priv->up)
                        break;
        }
 }
@@ -1020,7 +1012,7 @@ u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel)
        struct r8192_priv *priv = rtllib_priv(dev);
 
        RT_TRACE(COMP_PHY, "=====>%s()\n", __func__);
-       if (IS_NIC_DOWN(priv)) {
+       if (!priv->up) {
                RT_TRACE(COMP_ERR, "%s(): ERR !! driver is not up\n", __func__);
                return false;
        }
@@ -1060,7 +1052,7 @@ u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel)
        priv->SwChnlStage = 0;
        priv->SwChnlStep = 0;
 
-       if (!IS_NIC_DOWN(priv))
+       if (priv->up)
                rtl8192_SwChnl_WorkItem(dev);
        priv->SwChnlInProgress = false;
        return true;
@@ -1083,8 +1075,8 @@ static void CCK_Tx_Power_Track_BW_Switch_TSSI(struct net_device *dev)
                if (priv->CCKPresentAttentuation < 0)
                        priv->CCKPresentAttentuation = 0;
 
-               RT_TRACE(COMP_POWER_TRACKING, "20M, priv->CCKPresent"
-                        "Attentuation = %d\n",
+               RT_TRACE(COMP_POWER_TRACKING,
+                        "20M, priv->CCKPresentAttentuation = %d\n",
                         priv->CCKPresentAttentuation);
 
                if (priv->rtllib->current_network.channel == 14 &&
@@ -1105,8 +1097,8 @@ static void CCK_Tx_Power_Track_BW_Switch_TSSI(struct net_device *dev)
                        priv->CCKPresentAttentuation_40Mdefault +
                        priv->CCKPresentAttentuation_difference;
 
-               RT_TRACE(COMP_POWER_TRACKING, "40M, priv->CCKPresent"
-                        "Attentuation = %d\n",
+               RT_TRACE(COMP_POWER_TRACKING,
+                        "40M, priv->CCKPresentAttentuation = %d\n",
                         priv->CCKPresentAttentuation);
                if (priv->CCKPresentAttentuation >
                    (CCKTxBBGainTableLength - 1))
@@ -1146,15 +1138,15 @@ static void CCK_Tx_Power_Track_BW_Switch_ThermalMeter(struct net_device *dev)
                if (priv->Record_CCK_20Mindex == 0)
                        priv->Record_CCK_20Mindex = 6;
                priv->CCK_index = priv->Record_CCK_20Mindex;
-               RT_TRACE(COMP_POWER_TRACKING, "20MHz, CCK_Tx_Power_Track_BW_"
-                        "Switch_ThermalMeter(),CCK_index = %d\n",
+               RT_TRACE(COMP_POWER_TRACKING,
+                        "20MHz, CCK_Tx_Power_Track_BW_Switch_ThermalMeter(),CCK_index = %d\n",
                         priv->CCK_index);
        break;
 
        case HT_CHANNEL_WIDTH_20_40:
                priv->CCK_index = priv->Record_CCK_40Mindex;
-               RT_TRACE(COMP_POWER_TRACKING, "40MHz, CCK_Tx_Power_Track_BW_"
-                        "Switch_ThermalMeter(), CCK_index = %d\n",
+               RT_TRACE(COMP_POWER_TRACKING,
+                        "40MHz, CCK_Tx_Power_Track_BW_Switch_ThermalMeter(), CCK_index = %d\n",
                         priv->CCK_index);
        break;
        }
@@ -1177,16 +1169,17 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev)
        struct r8192_priv *priv = rtllib_priv(dev);
        u8 regBwOpMode;
 
-       RT_TRACE(COMP_SWBW, "==>rtl8192_SetBWModeWorkItem()  Switch to %s "
-                "bandwidth\n", priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ?
-                "20MHz" : "40MHz");
+       RT_TRACE(COMP_SWBW,
+                "==>rtl8192_SetBWModeWorkItem()  Switch to %s bandwidth\n",
+                priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ?
+                        "20MHz" : "40MHz");
 
 
        if (priv->rf_chip == RF_PSEUDO_11N) {
                priv->SetBWModeInProgress = false;
                return;
        }
-       if (IS_NIC_DOWN(priv)) {
+       if (!priv->up) {
                RT_TRACE(COMP_ERR, "%s(): ERR!! driver is not up\n", __func__);
                return;
        }
@@ -1204,8 +1197,9 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev)
                break;
 
        default:
-               RT_TRACE(COMP_ERR, "SetChannelBandwidth819xUsb(): unknown "
-                        "Bandwidth: %#X\n", priv->CurrentChannelBW);
+               RT_TRACE(COMP_ERR,
+                        "SetChannelBandwidth819xUsb(): unknown Bandwidth: %#X\n",
+                        priv->CurrentChannelBW);
                break;
        }
 
@@ -1245,8 +1239,9 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev)
                rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 0);
                break;
        default:
-               RT_TRACE(COMP_ERR, "SetChannelBandwidth819xUsb(): unknown "
-                        "Bandwidth: %#X\n", priv->CurrentChannelBW);
+               RT_TRACE(COMP_ERR,
+                        "SetChannelBandwidth819xUsb(): unknown Bandwidth: %#X\n",
+                        priv->CurrentChannelBW);
                break;
 
        }
@@ -1309,11 +1304,11 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation)
        u32 BitMask;
        u8 initial_gain;
 
-       if (!IS_NIC_DOWN(priv)) {
+       if (priv->up) {
                switch (Operation) {
                case IG_Backup:
-                       RT_TRACE(COMP_SCAN, "IG_Backup, backup the initial"
-                                " gain.\n");
+                       RT_TRACE(COMP_SCAN,
+                                "IG_Backup, backup the initial gain.\n");
                        initial_gain = SCAN_RX_INITIAL_GAIN;
                        BitMask = bMaskByte0;
                        if (dm_digtable.dig_algorithm ==
@@ -1335,16 +1330,21 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation)
                        priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev,
                                                    rCCK0_CCA, BitMask);
 
-                       RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc50 is"
-                                " %x\n", priv->initgain_backup.xaagccore1);
-                       RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc58 is"
-                                " %x\n", priv->initgain_backup.xbagccore1);
-                       RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc60 is"
-                                " %x\n", priv->initgain_backup.xcagccore1);
-                       RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc68 is"
-                                " %x\n", priv->initgain_backup.xdagccore1);
-                       RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xa0a is"
-                                " %x\n", priv->initgain_backup.cca);
+                       RT_TRACE(COMP_SCAN,
+                                "Scan InitialGainBackup 0xc50 is %x\n",
+                                priv->initgain_backup.xaagccore1);
+                       RT_TRACE(COMP_SCAN,
+                                "Scan InitialGainBackup 0xc58 is %x\n",
+                                priv->initgain_backup.xbagccore1);
+                       RT_TRACE(COMP_SCAN,
+                                "Scan InitialGainBackup 0xc60 is %x\n",
+                                priv->initgain_backup.xcagccore1);
+                       RT_TRACE(COMP_SCAN,
+                                "Scan InitialGainBackup 0xc68 is %x\n",
+                                priv->initgain_backup.xdagccore1);
+                       RT_TRACE(COMP_SCAN,
+                                "Scan InitialGainBackup 0xa0a is %x\n",
+                                priv->initgain_backup.cca);
 
                        RT_TRACE(COMP_SCAN, "Write scan initial gain = 0x%x\n",
                                 initial_gain);
@@ -1357,8 +1357,8 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation)
                        write_nic_byte(dev, 0xa0a, POWER_DETECTION_TH);
                        break;
                case IG_Restore:
-                       RT_TRACE(COMP_SCAN, "IG_Restore, restore the initial "
-                                "gain.\n");
+                       RT_TRACE(COMP_SCAN,
+                                "IG_Restore, restore the initial gain.\n");
                        BitMask = 0x7f;
                        if (dm_digtable.dig_algorithm ==
                            DIG_ALGO_BY_FALSE_ALARM)
@@ -1376,16 +1376,21 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation)
                        rtl8192_setBBreg(dev, rCCK0_CCA, BitMask,
                                         (u32)priv->initgain_backup.cca);
 
-                       RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc50"
-                                " is %x\n", priv->initgain_backup.xaagccore1);
-                       RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc58"
-                                " is %x\n", priv->initgain_backup.xbagccore1);
-                       RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc60"
-                                " is %x\n", priv->initgain_backup.xcagccore1);
-                       RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc68"
-                                " is %x\n", priv->initgain_backup.xdagccore1);
-                       RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xa0a"
-                                " is %x\n", priv->initgain_backup.cca);
+                       RT_TRACE(COMP_SCAN,
+                                "Scan BBInitialGainRestore 0xc50 is %x\n",
+                                priv->initgain_backup.xaagccore1);
+                       RT_TRACE(COMP_SCAN,
+                                "Scan BBInitialGainRestore 0xc58 is %x\n",
+                                priv->initgain_backup.xbagccore1);
+                       RT_TRACE(COMP_SCAN,
+                                "Scan BBInitialGainRestore 0xc60 is %x\n",
+                                priv->initgain_backup.xcagccore1);
+                       RT_TRACE(COMP_SCAN,
+                                "Scan BBInitialGainRestore 0xc68 is %x\n",
+                                priv->initgain_backup.xdagccore1);
+                       RT_TRACE(COMP_SCAN,
+                                "Scan BBInitialGainRestore 0xa0a is %x\n",
+                                priv->initgain_backup.cca);
 
                        rtl8192_phy_setTxPower(dev,
                                         priv->rtllib->current_network.channel);
@@ -1447,8 +1452,8 @@ static bool SetRFPowerState8190(struct net_device *dev,
                                } while (!rtstatus && (InitilizeCount > 0));
 
                                if (!rtstatus) {
-                                       RT_TRACE(COMP_ERR, "%s():Initialize Ada"
-                                                "pter fail,return\n",
+                                       RT_TRACE(COMP_ERR,
+                                                "%s():Initialize Adapter fail,return\n",
                                                 __func__);
                                        priv->SetRFPowerStateInProgress = false;
                                        return false;
@@ -1492,19 +1497,16 @@ static bool SetRFPowerState8190(struct net_device *dev,
                                        QueueID++;
                                        continue;
                                } else {
-                                       RT_TRACE((COMP_POWER|COMP_RF), "eRf Off"
-                                                "/Sleep: %d times TcbBusyQueue"
-                                                "[%d] !=0 before doze!\n",
+                                       RT_TRACE((COMP_POWER|COMP_RF),
+                                                "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n",
                                                 (i+1), QueueID);
                                        udelay(10);
                                        i++;
                                }
 
                                if (i >= MAX_DOZE_WAITING_TIMES_9x) {
-                                       RT_TRACE(COMP_POWER, "\n\n\n TimeOut!! "
-                                                "SetRFPowerState8190(): eRfOff"
-                                                ": %d times TcbBusyQueue[%d] "
-                                                "!= 0 !!!\n",
+                                       RT_TRACE(COMP_POWER,
+                                                "\n\n\n TimeOut!! SetRFPowerState8190(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n",
                                                 MAX_DOZE_WAITING_TIMES_9x,
                                                 QueueID);
                                        break;
@@ -1514,8 +1516,8 @@ static bool SetRFPowerState8190(struct net_device *dev,
                        break;
 
                case eRfOff:
-                       RT_TRACE(COMP_PS, "SetRFPowerState8190() eRfOff/"
-                                "Sleep !\n");
+                       RT_TRACE(COMP_PS,
+                                "SetRFPowerState8190() eRfOff/Sleep !\n");
 
                        for (QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; ) {
                                ring = &priv->tx_ring[QueueID];
@@ -1524,19 +1526,16 @@ static bool SetRFPowerState8190(struct net_device *dev,
                                        QueueID++;
                                        continue;
                                } else {
-                                       RT_TRACE(COMP_POWER, "eRf Off/Sleep: %d"
-                                                " times TcbBusyQueue[%d] !=0 b"
-                                                "efore doze!\n", (i+1),
-                                                QueueID);
+                                       RT_TRACE(COMP_POWER,
+                                                "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n",
+                                                (i+1), QueueID);
                                        udelay(10);
                                        i++;
                                }
 
                                if (i >= MAX_DOZE_WAITING_TIMES_9x) {
-                                       RT_TRACE(COMP_POWER, "\n\n\n SetZebra: "
-                                                "RFPowerState8185B(): eRfOff:"
-                                                " %d times TcbBusyQueue[%d] "
-                                                "!= 0 !!!\n",
+                                       RT_TRACE(COMP_POWER,
+                                                "\n\n\n SetZebra: RFPowerState8185B(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n",
                                                 MAX_DOZE_WAITING_TIMES_9x,
                                                 QueueID);
                                        break;
@@ -1556,8 +1555,9 @@ static bool SetRFPowerState8190(struct net_device *dev,
 
                default:
                        bResult = false;
-                       RT_TRACE(COMP_ERR, "SetRFPowerState8190(): unknown state"
-                                " to set: 0x%X!!!\n", eRFPowerState);
+                       RT_TRACE(COMP_ERR,
+                                "SetRFPowerState8190(): unknown state to set: 0x%X!!!\n",
+                                eRFPowerState);
                        break;
                }
 
@@ -1576,8 +1576,8 @@ static bool SetRFPowerState8190(struct net_device *dev,
                        break;
 
                default:
-                       RT_TRACE(COMP_ERR, "SetRFPowerState8190(): Unknown "
-                                "RF type\n");
+                       RT_TRACE(COMP_ERR,
+                                "SetRFPowerState8190(): Unknown RF type\n");
                        break;
                }
        }
@@ -1599,8 +1599,8 @@ bool SetRFPowerState(struct net_device *dev,
                 eRFPowerState);
        if (eRFPowerState == priv->rtllib->eRFPowerState &&
            priv->bHwRfOffAction == 0) {
-               RT_TRACE(COMP_PS, "<--------- SetRFPowerState(): discard the "
-                        "request for eRFPowerState(%d) is the same.\n",
+               RT_TRACE(COMP_PS,
+                        "<--------- SetRFPowerState(): discard the request for eRFPowerState(%d) is the same.\n",
                         eRFPowerState);
                return bResult;
        }
index 970298b07af7f5b39159bfb543ae72133796dcb9..03eee3d059c6f6b01e8b4e2169e21be2edd559f8 100644 (file)
 #define bOFDMPHY0_End             0xcff
 #define bOFDMPHY1_End             0xdff
 
-/*#define max debug item in each debug page
-#define bMaxItem_FPGA_PHY0        0x9
-#define bMaxItem_FPGA_PHY1        0x3
-#define bMaxItem_PHY_11B          0x16
-#define bMaxItem_OFDM_PHY0        0x29
-#define bMaxItem_OFDM_PHY1        0x0 */
-
 #define bPMACControl              0x0
 #define bWMACControl              0x1
 #define bWNICControl              0x2
index 89ea70b0d3aadd1e23ac130ff7fc7e80c85622f2..41b025e250fed6314835d6f097e421f120f39189 100644 (file)
@@ -86,9 +86,9 @@ void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rtllib_device *ieee = priv->rtllib;
 
-       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);
+       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 (!is_mesh) {
                ieee->swcamtable[EntryNo].bused = true;
                ieee->swcamtable[EntryNo].key_index = KeyIndex;
@@ -115,21 +115,20 @@ void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
                        if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) {
                                RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",
                                        __func__);
-                               return ;
-                       } else {
-                               down(&priv->rtllib->ips_sem);
-                               IPSLeave(dev);
-                               up(&priv->rtllib->ips_sem);
+                               return;
                        }
+                       down(&priv->rtllib->ips_sem);
+                       IPSLeave(dev);
+                       up(&priv->rtllib->ips_sem);
                }
        }
        priv->rtllib->is_set_key = true;
        if (EntryNo >= TOTAL_CAM_ENTRY)
                RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
 
-       RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d,"
-                "KeyType:%d, MacAddr %pM\n", dev, EntryNo, KeyIndex,
-                KeyType, MacAddr);
+       RT_TRACE(COMP_SEC,
+                "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n",
+                dev, EntryNo, KeyIndex, KeyType, MacAddr);
 
        if (DefaultKey)
                usConfig |= BIT15 | (KeyType<<2);
@@ -192,7 +191,7 @@ 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,
+                               setKey(dev, EntryId, EntryId,
                                       priv->rtllib->pairwise_key_type, MacAddr,
                                       0, (u32 *)(&priv->rtllib->swcamtable
                                      [EntryId].key_buf[0]));
@@ -244,8 +243,8 @@ void CamRestoreAllEntry(struct net_device *dev)
                                       (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])
                                     );
                        } else {
-                               RT_TRACE(COMP_ERR, "===>%s():ERR!! ADHOC TKIP "
-                                        ",but 0 entry is have no data\n",
+                               RT_TRACE(COMP_ERR,
+                                        "===>%s():ERR!! ADHOC TKIP ,but 0 entry is have no data\n",
                                         __func__);
                                return;
                        }
@@ -254,7 +253,7 @@ 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,
+                               setKey(dev, EntryId, EntryId,
                                       priv->rtllib->group_key_type,
                                       MacAddr, 0,
                                       (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
@@ -263,13 +262,13 @@ void CamRestoreAllEntry(struct net_device *dev)
 
                if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
                        if (priv->rtllib->swcamtable[0].bused) {
-                               setKey(dev, 0 , 0,
+                               setKey(dev, 0, 0,
                                        priv->rtllib->group_key_type,
                                        CAM_CONST_ADDR[0], 0,
                                        (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
                        } else {
-                               RT_TRACE(COMP_ERR, "===>%s():ERR!! ADHOC CCMP ,"
-                                        "but 0 entry is have no data\n",
+                               RT_TRACE(COMP_ERR,
+                                        "===>%s():ERR!! ADHOC CCMP ,but 0 entry is have no data\n",
                                         __func__);
                                return;
                        }
index 5615c80f614cab0c4860196117ab4d1f250e631a..352d381b7c4ae56297aaeddfccc193e224b2480b 100644 (file)
@@ -131,7 +131,7 @@ static bool PlatformIOCheckPageLegalAndGetRegMask(u32 u4bPage, u8 *pu1bPageMask)
 
 void write_nic_io_byte(struct net_device *dev, int x, u8 y)
 {
-       u32 u4bPage = (x >> 8);
+       u32 u4bPage = x >> 8;
        u8 u1PageMask = 0;
        bool    bIsLegalPage = false;
 
@@ -154,7 +154,7 @@ 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)
 {
-       u32 u4bPage = (x >> 8);
+       u32 u4bPage = x >> 8;
        u8 u1PageMask = 0;
        bool    bIsLegalPage = false;
 
@@ -177,7 +177,7 @@ 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)
 {
-       u32 u4bPage = (x >> 8);
+       u32 u4bPage = x >> 8;
        u8 u1PageMask = 0;
        bool    bIsLegalPage = false;
 
@@ -199,24 +199,23 @@ void write_nic_io_dword(struct net_device *dev, int x, u32 y)
 
 u8 read_nic_io_byte(struct net_device *dev, int x)
 {
-       u32 u4bPage = (x >> 8);
+       u32 u4bPage = x >> 8;
        u8 u1PageMask = 0;
        bool    bIsLegalPage = false;
        u8      Data = 0;
 
-       if (u4bPage == 0) {
+       if (u4bPage == 0)
                return 0xff&inb(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));
-                       Data = read_nic_io_byte(dev, (x & 0xff));
-                       write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
-               }
+       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;
@@ -224,25 +223,22 @@ u8 read_nic_io_byte(struct net_device *dev, int x)
 
 u16 read_nic_io_word(struct net_device *dev, int x)
 {
-       u32 u4bPage = (x >> 8);
+       u32 u4bPage = x >> 8;
        u8 u1PageMask = 0;
        bool    bIsLegalPage = false;
        u16     Data = 0;
 
-       if (u4bPage == 0) {
+       if (u4bPage == 0)
                return inw(dev->base_addr + x);
-       } else {
-               bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
-                              &u1PageMask);
-               if (bIsLegalPage) {
-                       u8 u1bPsr = read_nic_io_byte(dev, PSR);
+       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));
-
-               }
+               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;
@@ -250,25 +246,22 @@ u16 read_nic_io_word(struct net_device *dev, int x)
 
 u32 read_nic_io_dword(struct net_device *dev, int x)
 {
-       u32 u4bPage = (x >> 8);
+       u32 u4bPage = x >> 8;
        u8 u1PageMask = 0;
        bool    bIsLegalPage = false;
        u32     Data = 0;
 
-       if (u4bPage == 0) {
+       if (u4bPage == 0)
                return inl(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));
-                       Data = read_nic_io_dword(dev, (x & 0xff));
-                       write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
+       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;
@@ -326,8 +319,8 @@ bool MgntActSet_RF_State(struct net_device *dev,
        u16                     RFWaitCounter = 0;
        unsigned long flag;
 
-       RT_TRACE((COMP_PS | COMP_RF), "===>MgntActSet_RF_State(): "
-                "StateToSet(%d)\n", StateToSet);
+       RT_TRACE((COMP_PS | COMP_RF),
+                "===>MgntActSet_RF_State(): StateToSet(%d)\n", StateToSet);
 
        ProtectOrNot = false;
 
@@ -338,22 +331,19 @@ bool MgntActSet_RF_State(struct net_device *dev,
                        if (priv->RFChangeInProgress) {
                                spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
                                RT_TRACE((COMP_PS | COMP_RF),
-                                        "MgntActSet_RF_State(): RF Change in "
-                                        "progress! Wait to set..StateToSet"
-                                        "(%d).\n", StateToSet);
+                                        "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",
+                                                "MgntActSet_RF_State(): Wait 1 ms (%d times)...\n",
                                                 RFWaitCounter);
                                        mdelay(1);
 
                                        if (RFWaitCounter > 100) {
-                                               RT_TRACE(COMP_ERR, "MgntActSet_"
-                                                        "RF_State(): Wait too "
-                                                        "logn to set RF\n");
+                                               RT_TRACE(COMP_ERR,
+                                                        "MgntActSet_RF_State(): Wait too logn to set RF\n");
                                                return false;
                                        }
                                }
@@ -383,9 +373,8 @@ bool MgntActSet_RF_State(struct net_device *dev,
                            ChangeSource >= RF_CHANGE_BY_HW)
                                bConnectBySSID = true;
                } else {
-                       RT_TRACE((COMP_PS | COMP_RF), "MgntActSet_RF_State - "
-                                "eRfon reject pMgntInfo->RfOffReason= 0x%x,"
-                                " ChangeSource=0x%X\n",
+                       RT_TRACE((COMP_PS | COMP_RF),
+                                "MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n",
                                  priv->rtllib->RfOffReason, ChangeSource);
        }
 
@@ -421,8 +410,8 @@ 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",
+               RT_TRACE((COMP_PS | COMP_RF),
+                        "MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n",
                         StateToSet, priv->rtllib->RfOffReason);
                PHY_SetRFPowerState(dev, StateToSet);
                if (StateToSet == eRfOn) {
@@ -434,10 +423,9 @@ 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", StateToSet, ChangeSource,
-                        priv->rtllib->RfOffReason);
+               RT_TRACE((COMP_PS | COMP_RF),
+                        "MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n",
+                        StateToSet, ChangeSource, priv->rtllib->RfOffReason);
        }
 
        if (!ProtectOrNot) {
@@ -460,9 +448,9 @@ static short rtl8192_get_nic_desc_num(struct net_device *dev, int prio)
        * between the tail and the head
        */
        if ((prio == MGNT_QUEUE) && (skb_queue_len(&ring->queue) > 10))
-               RT_TRACE(COMP_DBG, "-----[%d]---------ring->idx=%d "
-                        "queue_len=%d---------\n", prio, ring->idx,
-                        skb_queue_len(&ring->queue));
+               RT_TRACE(COMP_DBG,
+                        "-----[%d]---------ring->idx=%d queue_len=%d---------\n",
+                        prio, ring->idx, skb_queue_len(&ring->queue));
        return skb_queue_len(&ring->queue);
 }
 
@@ -481,7 +469,7 @@ void rtl8192_tx_timeout(struct net_device *dev)
        struct r8192_priv *priv = rtllib_priv(dev);
 
        schedule_work(&priv->reset_wq);
-       printk(KERN_INFO "TXTIMEOUT");
+       netdev_info(dev, "TXTIMEOUT");
 }
 
 void rtl8192_irq_enable(struct net_device *dev)
@@ -526,8 +514,9 @@ void rtl8192_update_cap(struct net_device *dev, u16 cap)
                if (priv->dot11CurrentPreambleMode != PREAMBLE_SHORT) {
                        ShortPreamble = true;
                        priv->dot11CurrentPreambleMode = PREAMBLE_SHORT;
-                       RT_TRACE(COMP_DBG, "%s(): WLAN_CAPABILITY_SHORT_"
-                                "PREAMBLE\n", __func__);
+                       RT_TRACE(COMP_DBG,
+                                "%s(): WLAN_CAPABILITY_SHORT_PREAMBLE\n",
+                                __func__);
                        priv->rtllib->SetHwRegHandler(dev, HW_VAR_ACK_PREAMBLE,
                                        (unsigned char *)&ShortPreamble);
                }
@@ -535,8 +524,9 @@ void rtl8192_update_cap(struct net_device *dev, u16 cap)
                if (priv->dot11CurrentPreambleMode != PREAMBLE_LONG) {
                        ShortPreamble = false;
                        priv->dot11CurrentPreambleMode = PREAMBLE_LONG;
-                       RT_TRACE(COMP_DBG, "%s(): WLAN_CAPABILITY_LONG_"
-                                "PREAMBLE\n", __func__);
+                       RT_TRACE(COMP_DBG,
+                                "%s(): WLAN_CAPABILITY_LONG_PREAMBLE\n",
+                                __func__);
                        priv->rtllib->SetHwRegHandler(dev, HW_VAR_ACK_PREAMBLE,
                                              (unsigned char *)&ShortPreamble);
                }
@@ -597,8 +587,8 @@ static void rtl8192_qos_activate(void *data)
        mutex_lock(&priv->mutex);
        if (priv->rtllib->state != RTLLIB_LINKED)
                goto success;
-       RT_TRACE(COMP_QOS, "qos active process with associate response "
-                "received\n");
+       RT_TRACE(COMP_QOS,
+                "qos active process with associate response received\n");
 
        for (i = 0; i <  QOS_QUEUE_NUM; i++)
                priv->rtllib->SetHwRegHandler(dev, HW_VAR_AC_PARAM, (u8 *)(&i));
@@ -618,7 +608,7 @@ static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
        if (priv->rtllib->state != RTLLIB_LINKED)
                return ret;
 
-       if ((priv->rtllib->iw_mode != IW_MODE_INFRA))
+       if (priv->rtllib->iw_mode != IW_MODE_INFRA)
                return ret;
 
        if (network->flags & NETWORK_HAS_QOS_MASK) {
@@ -634,8 +624,8 @@ static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
                                network->qos_data.param_count;
        priv->rtllib->wmm_acm = network->qos_data.wmm_acm;
                        queue_work_rsl(priv->priv_wq, &priv->qos_activate);
-                       RT_TRACE(COMP_QOS, "QoS parameters change call "
-                                       "qos_activate\n");
+                       RT_TRACE(COMP_QOS,
+                                "QoS parameters change call qos_activate\n");
                }
        } else {
                memcpy(&priv->rtllib->current_network.qos_data.parameters,
@@ -643,8 +633,8 @@ static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
 
                if ((network->qos_data.active == 1) && (active_network == 1)) {
                        queue_work_rsl(priv->priv_wq, &priv->qos_activate);
-                       RT_TRACE(COMP_QOS, "QoS was disabled call qos_"
-                                "activate\n");
+                       RT_TRACE(COMP_QOS,
+                                "QoS was disabled call qos_activate\n");
                }
                network->qos_data.active = 0;
                network->qos_data.supported = 0;
@@ -679,7 +669,7 @@ static int rtl8192_qos_association_resp(struct r8192_priv *priv,
        if (priv->rtllib->state != RTLLIB_LINKED)
                return 0;
 
-       if ((priv->rtllib->iw_mode != IW_MODE_INFRA))
+       if (priv->rtllib->iw_mode != IW_MODE_INFRA)
                return 0;
 
        spin_lock_irqsave(&priv->rtllib->lock, flags);
@@ -751,8 +741,6 @@ static void rtl8192_prepare_beacon(struct r8192_priv *priv)
        priv->ops->tx_fill_descriptor(dev, pdesc, tcb_desc, pnewskb);
        __skb_queue_tail(&ring->queue, pnewskb);
        pdesc->OWN = 1;
-
-       return;
 }
 
 static void rtl8192_stop_beacon(struct net_device *dev)
@@ -866,7 +854,6 @@ static void rtl8192_refresh_supportrate(struct r8192_priv *priv)
        } else {
                memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
        }
-       return;
 }
 
 static u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
@@ -909,8 +896,9 @@ void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
                } else if ((bSupportMode & WIRELESS_MODE_B)) {
                        wireless_mode = WIRELESS_MODE_B;
                } else {
-                       RT_TRACE(COMP_ERR, "%s(), No valid wireless mode "
-                                "supported (%x)!!!\n", __func__, bSupportMode);
+                       RT_TRACE(COMP_ERR,
+                                "%s(), No valid wireless mode supported (%x)!!!\n",
+                                __func__, bSupportMode);
                        wireless_mode = WIRELESS_MODE_B;
                }
        }
@@ -1025,8 +1013,9 @@ static int rtl8192_sta_down(struct net_device *dev, bool shutdownrf)
                        spin_lock_irqsave(&priv->rf_ps_lock, flags);
                        break;
                }
-               RT_TRACE(COMP_DBG, "===>%s():RF is in progress, need to wait "
-                        "until rf change is done.\n", __func__);
+               RT_TRACE(COMP_DBG,
+                        "===>%s():RF is in progress, need to wait until rf change is done.\n",
+                        __func__);
                mdelay(1);
                RFInProgressTimeOut++;
                spin_lock_irqsave(&priv->rf_ps_lock, flags);
@@ -1212,8 +1201,8 @@ static void rtl8192_init_priv_variable(struct net_device *dev)
        priv->AcmControl = 0;
        priv->pFirmware = vzalloc(sizeof(struct rt_firmware));
        if (!priv->pFirmware)
-               printk(KERN_ERR "rtl8192e: Unable to allocate space "
-                      "for firmware\n");
+               netdev_err(dev,
+                          "rtl8192e: Unable to allocate space for firmware\n");
 
        skb_queue_head_init(&priv->rx_queue);
        skb_queue_head_init(&priv->skb_queue);
@@ -1278,14 +1267,15 @@ static short rtl8192_get_channel_map(struct net_device *dev)
 
        if ((priv->rf_chip != RF_8225) && (priv->rf_chip != RF_8256)
                        && (priv->rf_chip != RF_6052)) {
-               RT_TRACE(COMP_ERR, "%s: unknown rf chip, can't set channel "
-                        "map\n", __func__);
+               RT_TRACE(COMP_ERR,
+                        "%s: unknown rf chip, can't set channel map\n",
+                        __func__);
                return -1;
        }
 
        if (priv->ChannelPlan >= COUNTRY_CODE_MAX) {
-               printk(KERN_INFO "rtl819x_init:Error channel plan! Set to "
-                      "default.\n");
+               netdev_info(dev,
+                           "rtl819x_init:Error channel plan! Set to default.\n");
                priv->ChannelPlan = COUNTRY_CODE_FCC;
        }
        RT_TRACE(COMP_INIT, "Channel plan is %d\n", priv->ChannelPlan);
@@ -1329,15 +1319,15 @@ static short rtl8192_init(struct net_device *dev)
        rtl8192_irq_disable(dev);
        if (request_irq(dev->irq, rtl8192_interrupt, IRQF_SHARED,
            dev->name, dev)) {
-               printk(KERN_ERR "Error allocating IRQ %d", dev->irq);
+               netdev_err(dev, "Error allocating IRQ %d", dev->irq);
                return -1;
-       } else {
-               priv->irq = dev->irq;
-               RT_TRACE(COMP_INIT, "IRQ %d\n", dev->irq);
        }
 
+       priv->irq = dev->irq;
+       RT_TRACE(COMP_INIT, "IRQ %d\n", dev->irq);
+
        if (rtl8192_pci_initdescring(dev) != 0) {
-               printk(KERN_ERR "Endopoints initialization failed");
+               netdev_err(dev, "Endopoints initialization failed");
                free_irq(dev->irq, dev);
                return -1;
        }
@@ -1357,7 +1347,7 @@ short rtl8192_is_tx_queue_empty(struct net_device *dev)
                if ((i == TXCMD_QUEUE) || (i == HCCA_QUEUE))
                        continue;
                if (skb_queue_len(&(&priv->tx_ring[i])->queue) > 0) {
-                       printk(KERN_INFO "===>tx queue is not empty:%d, %d\n",
+                       netdev_info(dev, "===>tx queue is not empty:%d, %d\n",
                               i, skb_queue_len(&(&priv->tx_ring[i])->queue));
                        return 0;
                }
@@ -1406,17 +1396,18 @@ static enum reset_type rtl819x_TxCheckStuck(struct net_device *dev)
                        tcb_desc->nStuckCount++;
                        bCheckFwTxCnt = true;
                        if (tcb_desc->nStuckCount > 1)
-                               printk(KERN_INFO "%s: QueueID=%d tcb_desc->n"
-                                      "StuckCount=%d\n", __func__, QueueID,
-                                      tcb_desc->nStuckCount);
+                               netdev_info(dev,
+                                           "%s: QueueID=%d tcb_desc->nStuckCount=%d\n",
+                                           __func__, QueueID,
+                                           tcb_desc->nStuckCount);
                }
        }
        spin_unlock_irqrestore(&priv->irq_th_lock, flags);
 
        if (bCheckFwTxCnt) {
                if (priv->ops->TxCheckStuckHandler(dev)) {
-                       RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no"
-                                " Tx condition!\n");
+                       RT_TRACE(COMP_RESET,
+                                "TxCheckStuck(): Fw indicates no Tx condition!\n");
                        return RESET_TYPE_SILENT;
                }
        }
@@ -1455,13 +1446,13 @@ static enum reset_type rtl819x_ifcheck_resetornot(struct net_device *dev)
 
        if (TxResetType == RESET_TYPE_NORMAL ||
            RxResetType == RESET_TYPE_NORMAL) {
-               printk(KERN_INFO "%s(): TxResetType is %d, RxResetType is %d\n",
-                      __func__, TxResetType, RxResetType);
+               netdev_info(dev, "%s(): TxResetType is %d, RxResetType is %d\n",
+                           __func__, TxResetType, RxResetType);
                return RESET_TYPE_NORMAL;
        } else if (TxResetType == RESET_TYPE_SILENT ||
                   RxResetType == RESET_TYPE_SILENT) {
-               printk(KERN_INFO "%s(): TxResetType is %d, RxResetType is %d\n",
-                      __func__, TxResetType, RxResetType);
+               netdev_info(dev, "%s(): TxResetType is %d, RxResetType is %d\n",
+                           __func__, TxResetType, RxResetType);
                return RESET_TYPE_SILENT;
        } else {
                return RESET_TYPE_NORESET;
@@ -1506,9 +1497,10 @@ RESET_START:
                if (priv->rtllib->state == RTLLIB_LINKED)
                        LeisurePSLeave(dev);
 
-               if (IS_NIC_DOWN(priv)) {
-                       RT_TRACE(COMP_ERR, "%s():the driver is not up! "
-                                "return\n", __func__);
+               if (priv->up) {
+                       RT_TRACE(COMP_ERR,
+                                "%s():the driver is not up! return\n",
+                                __func__);
                        up(&priv->wx_sem);
                        return;
                }
@@ -1517,8 +1509,9 @@ RESET_START:
                RT_TRACE(COMP_RESET, "%s():======>start to down the driver\n",
                          __func__);
                mdelay(1000);
-               RT_TRACE(COMP_RESET, "%s():111111111111111111111111======>start"
-                        " to down the driver\n", __func__);
+               RT_TRACE(COMP_RESET,
+                        "%s():111111111111111111111111======>start to down the driver\n",
+                        __func__);
 
                if (!netif_queue_stopped(dev))
                        netif_stop_queue(dev);
@@ -1531,7 +1524,7 @@ RESET_START:
 
                if (ieee->state == RTLLIB_LINKED) {
                        SEM_DOWN_IEEE_WX(&ieee->wx_sem);
-                       printk(KERN_INFO "ieee->state is RTLLIB_LINKED\n");
+                       netdev_info(dev, "ieee->state is RTLLIB_LINKED\n");
                        rtllib_stop_send_beacons(priv->rtllib);
                        del_timer_sync(&ieee->associate_timer);
                        cancel_delayed_work(&ieee->associate_retry_wq);
@@ -1539,29 +1532,31 @@ RESET_START:
                        netif_carrier_off(dev);
                        SEM_UP_IEEE_WX(&ieee->wx_sem);
                } else {
-                       printk(KERN_INFO "ieee->state is NOT LINKED\n");
+                       netdev_info(dev, "ieee->state is NOT LINKED\n");
                        rtllib_softmac_stop_protocol(priv->rtllib, 0 , true);
                }
 
                dm_backup_dynamic_mechanism_state(dev);
 
                up(&priv->wx_sem);
-               RT_TRACE(COMP_RESET, "%s():<==========down process is "
-                        "finished\n", __func__);
+               RT_TRACE(COMP_RESET,
+                        "%s():<==========down process is finished\n",
+                        __func__);
 
                RT_TRACE(COMP_RESET, "%s():<===========up process start\n",
                         __func__);
                reset_status = _rtl8192_up(dev, true);
 
-               RT_TRACE(COMP_RESET, "%s():<===========up process is "
-                        "finished\n", __func__);
+               RT_TRACE(COMP_RESET,
+                        "%s():<===========up process is finished\n", __func__);
                if (reset_status == -1) {
                        if (reset_times < 3) {
                                reset_times++;
                                goto RESET_START;
                        } else {
-                               RT_TRACE(COMP_ERR, " ERR!!! %s():  Reset "
-                                        "Failed!!\n", __func__);
+                               RT_TRACE(COMP_ERR,
+                                        " ERR!!! %s():  Reset Failed!!\n",
+                                        __func__);
                        }
                }
 
@@ -1650,7 +1645,7 @@ void      rtl819x_watchdog_wqcallback(void *data)
        bool    bHigherBusyRxTraffic = false;
        bool bEnterPS = false;
 
-       if (IS_NIC_DOWN(priv) || priv->bHwRadioOff)
+       if (!priv->up || priv->bHwRadioOff)
                return;
 
        if (priv->rtllib->state >= RTLLIB_LINKED) {
@@ -1670,8 +1665,8 @@ void      rtl819x_watchdog_wqcallback(void *data)
                        if ((ieee->PowerSaveControl.ReturnPoint ==
                             IPS_CALLBACK_NONE) &&
                             (!ieee->bNetPromiscuousMode)) {
-                               RT_TRACE(COMP_PS, "====================>haha: "
-                                        "IPSEnter()\n");
+                               RT_TRACE(COMP_PS,
+                                        "====================>haha: IPSEnter()\n");
                                IPSEnter(dev);
                        }
                }
@@ -1736,8 +1731,9 @@ void      rtl819x_watchdog_wqcallback(void *data)
                        if (ieee->eRFPowerState == eRfOff)
                                RT_TRACE(COMP_ERR, "========>%s()\n", __func__);
 
-                       printk(KERN_INFO "===>%s(): AP is power off, chan:%d,"
-                              " connect another one\n", __func__, priv->chan);
+                       netdev_info(dev,
+                                   "===>%s(): AP is power off, chan:%d, connect another one\n",
+                                   __func__, priv->chan);
 
                        ieee->state = RTLLIB_ASSOCIATING;
 
@@ -1793,7 +1789,7 @@ void watch_dog_timer_callback(unsigned long data)
 
        queue_delayed_work_rsl(priv->priv_wq, &priv->watch_dog_wq, 0);
        mod_timer(&priv->watch_dog_timer, jiffies +
-                 MSECS(RTLLIB_WATCH_DOG_TIME));
+                 msecs_to_jiffies(RTLLIB_WATCH_DOG_TIME));
 }
 
 /****************************************************************************
@@ -1882,7 +1878,7 @@ void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
                                    MAX_DEV_ADDR_SIZE);
        u8 queue_index = tcb_desc->queue_index;
 
-       if ((priv->rtllib->eRFPowerState == eRfOff) || IS_NIC_DOWN(priv) ||
+       if ((priv->rtllib->eRFPowerState == eRfOff) || !priv->up ||
             priv->bResetInProgress) {
                kfree_skb(skb);
                return;
@@ -1902,8 +1898,6 @@ void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
                                                 priv->rtllib->tx_headroom);
                priv->rtllib->stats.tx_packets++;
        }
-
-       return;
 }
 
 int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -1916,7 +1910,7 @@ int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        if (queue_index != TXCMD_QUEUE) {
                if ((priv->rtllib->eRFPowerState == eRfOff) ||
-                    IS_NIC_DOWN(priv) || priv->bResetInProgress) {
+                    !priv->up || priv->bResetInProgress) {
                        kfree_skb(skb);
                        return 0;
                }
@@ -1926,17 +1920,16 @@ int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (queue_index == TXCMD_QUEUE) {
                rtl8192_tx_cmd(dev, skb);
                return 0;
-       } else {
-               tcb_desc->RATRIndex = 7;
-               tcb_desc->bTxDisableRateFallBack = 1;
-               tcb_desc->bTxUseDriverAssingedRate = 1;
-               tcb_desc->bTxEnableFwCalcDur = 1;
-               skb_push(skb, priv->rtllib->tx_headroom);
-               ret = rtl8192_tx(dev, skb);
-               if (ret != 0)
-                       kfree_skb(skb);
        }
 
+       tcb_desc->RATRIndex = 7;
+       tcb_desc->bTxDisableRateFallBack = 1;
+       tcb_desc->bTxUseDriverAssingedRate = 1;
+       tcb_desc->bTxEnableFwCalcDur = 1;
+       skb_push(skb, priv->rtllib->tx_headroom);
+       ret = rtl8192_tx(dev, skb);
+       if (ret != 0)
+               kfree_skb(skb);
        return ret;
 }
 
@@ -1987,8 +1980,6 @@ void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb)
 
        __skb_queue_tail(&ring->queue, skb);
        spin_unlock_irqrestore(&priv->irq_th_lock, flags);
-
-       return;
 }
 
 short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
@@ -2007,9 +1998,9 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
        u32 fwinfo_size = 0;
 
        if (priv->bdisable_nic) {
-               RT_TRACE(COMP_ERR, "%s: ERR!! Nic is disabled! Can't tx packet"
-                        " len=%d qidx=%d!!!\n", __func__, skb->len,
-                        tcb_desc->queue_index);
+               RT_TRACE(COMP_ERR,
+                        "%s: ERR!! Nic is disabled! Can't tx packet len=%d qidx=%d!!!\n",
+                        __func__, skb->len, tcb_desc->queue_index);
                return skb->len;
        }
 
@@ -2046,8 +2037,8 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
 
        pdesc = &ring->desc[idx];
        if ((pdesc->OWN == 1) && (tcb_desc->queue_index != BEACON_QUEUE)) {
-               RT_TRACE(COMP_ERR, "No more TX desc@%d, ring->idx = %d, idx = "
-                        "%d, skblen = 0x%x queuelen=%d",
+               RT_TRACE(COMP_ERR,
+                        "No more TX desc@%d, ring->idx = %d, idx = %d, skblen = 0x%x queuelen=%d",
                         tcb_desc->queue_index, ring->idx, idx, skb->len,
                         skb_queue_len(&ring->queue));
                spin_unlock_irqrestore(&priv->irq_th_lock, flags);
@@ -2332,76 +2323,74 @@ static void rtl8192_rx_normal(struct net_device *dev)
                                        [priv->rx_idx[rx_queue_idx]];
                struct sk_buff *skb = priv->rx_buf[rx_queue_idx]
                                      [priv->rx_idx[rx_queue_idx]];
+               struct sk_buff *new_skb;
 
-               if (pdesc->OWN) {
+               if (pdesc->OWN)
                        return;
-               } else {
-                       struct sk_buff *new_skb;
-
-                       if (!priv->ops->rx_query_status_descriptor(dev, &stats,
-                       pdesc, skb))
-                               goto done;
-                       new_skb = dev_alloc_skb(priv->rxbuffersize);
-                       /* if allocation of new skb failed - drop current packet
-                       * and reuse skb */
-                       if (unlikely(!new_skb))
-                               goto done;
-
-                       pci_unmap_single(priv->pdev,
-                                       *((dma_addr_t *)skb->cb),
-                                       priv->rxbuffersize,
-                                       PCI_DMA_FROMDEVICE);
-
-                       skb_put(skb, pdesc->Length);
-                       skb_reserve(skb, stats.RxDrvInfoSize +
-                               stats.RxBufShift);
-                       skb_trim(skb, skb->len - 4/*sCrcLng*/);
-                       rtllib_hdr = (struct rtllib_hdr_1addr *)skb->data;
-                       if (!is_multicast_ether_addr(rtllib_hdr->addr1)) {
-                               /* unicast packet */
-                               unicast_packet = true;
-                       }
-                       fc = le16_to_cpu(rtllib_hdr->frame_ctl);
-                       type = WLAN_FC_GET_TYPE(fc);
-                       if (type == RTLLIB_FTYPE_MGMT)
-                               bLedBlinking = false;
-
-                       if (bLedBlinking)
-                               if (priv->rtllib->LedControlHandler)
-                                       priv->rtllib->LedControlHandler(dev,
-                                                               LED_CTL_RX);
-
-                       if (stats.bCRC) {
-                               if (type != RTLLIB_FTYPE_MGMT)
-                                       priv->stats.rxdatacrcerr++;
-                               else
-                                       priv->stats.rxmgmtcrcerr++;
-                       }
-
-                       skb_len = skb->len;
+               if (!priv->ops->rx_query_status_descriptor(dev, &stats,
+               pdesc, skb))
+                       goto done;
+               new_skb = dev_alloc_skb(priv->rxbuffersize);
+               /* if allocation of new skb failed - drop current packet
+                * and reuse skb
+                */
+               if (unlikely(!new_skb))
+                       goto done;
+
+               pci_unmap_single(priv->pdev,
+                               *((dma_addr_t *)skb->cb),
+                               priv->rxbuffersize,
+                               PCI_DMA_FROMDEVICE);
+
+               skb_put(skb, pdesc->Length);
+               skb_reserve(skb, stats.RxDrvInfoSize +
+                       stats.RxBufShift);
+               skb_trim(skb, skb->len - 4/*sCrcLng*/);
+               rtllib_hdr = (struct rtllib_hdr_1addr *)skb->data;
+               if (!is_multicast_ether_addr(rtllib_hdr->addr1)) {
+                       /* unicast packet */
+                       unicast_packet = true;
+               }
+               fc = le16_to_cpu(rtllib_hdr->frame_ctl);
+               type = WLAN_FC_GET_TYPE(fc);
+               if (type == RTLLIB_FTYPE_MGMT)
+                       bLedBlinking = false;
+
+               if (bLedBlinking)
+                       if (priv->rtllib->LedControlHandler)
+                               priv->rtllib->LedControlHandler(dev,
+                                                       LED_CTL_RX);
+
+               if (stats.bCRC) {
+                       if (type != RTLLIB_FTYPE_MGMT)
+                               priv->stats.rxdatacrcerr++;
+                       else
+                               priv->stats.rxmgmtcrcerr++;
+               }
 
-                       if (!rtllib_rx(priv->rtllib, skb, &stats)) {
-                               dev_kfree_skb_any(skb);
-                       } else {
-                               priv->stats.rxok++;
-                               if (unicast_packet)
-                                       priv->stats.rxbytesunicast += skb_len;
-                       }
+               skb_len = skb->len;
 
-                       skb = new_skb;
-                       skb->dev = dev;
+               if (!rtllib_rx(priv->rtllib, skb, &stats)) {
+                       dev_kfree_skb_any(skb);
+               } else {
+                       priv->stats.rxok++;
+                       if (unicast_packet)
+                               priv->stats.rxbytesunicast += skb_len;
+               }
 
-                       priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]] =
-                                                                        skb;
-                       *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev,
-                                                   skb_tail_pointer_rsl(skb),
-                                                   priv->rxbuffersize,
-                                                   PCI_DMA_FROMDEVICE);
-                       if (pci_dma_mapping_error(priv->pdev,
-                                                 *((dma_addr_t *)skb->cb))) {
-                               dev_kfree_skb_any(skb);
-                               return;
-                       }
+               skb = new_skb;
+               skb->dev = dev;
+
+               priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]] =
+                                                                skb;
+               *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev,
+                                           skb_tail_pointer_rsl(skb),
+                                           priv->rxbuffersize,
+                                           PCI_DMA_FROMDEVICE);
+               if (pci_dma_mapping_error(priv->pdev,
+                                         *((dma_addr_t *)skb->cb))) {
+                       dev_kfree_skb_any(skb);
+                       return;
                }
 done:
                pdesc->BufferAddress = *((dma_addr_t *)skb->cb);
@@ -2567,7 +2556,7 @@ static int r8192_set_mac_adr(struct net_device *dev, void *mac)
 
        down(&priv->wx_sem);
 
-       memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+       ether_addr_copy(dev->dev_addr, addr->sa_data);
 
        schedule_work(&priv->reset_wq);
        up(&priv->wx_sem);
@@ -2869,7 +2858,8 @@ static int rtl8192_pci_probe(struct pci_dev *pdev,
 
        if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
                if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
-                       printk(KERN_INFO "Unable to obtain 32bit DMA for consistent allocations\n");
+                       dev_info(&pdev->dev,
+                                "Unable to obtain 32bit DMA for consistent allocations\n");
                        goto err_pci_disable;
                }
        }
@@ -2902,7 +2892,8 @@ static int rtl8192_pci_probe(struct pci_dev *pdev,
                goto err_rel_rtllib;
        }
 
-       printk(KERN_INFO "Memory mapped space start: 0x%08lx\n", pmem_start);
+       dev_info(&pdev->dev, "Memory mapped space start: 0x%08lx\n",
+                pmem_start);
        if (!request_mem_region(pmem_start, pmem_len, DRV_NAME)) {
                RT_TRACE(COMP_ERR, "request_mem_region failed!");
                goto err_rel_rtllib;
@@ -2940,8 +2931,8 @@ static int rtl8192_pci_probe(struct pci_dev *pdev,
        dev->watchdog_timeo = HZ * 3;
 
        if (dev_alloc_name(dev, ifname) < 0) {
-               RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying "
-                        "wlan%%d...\n");
+               RT_TRACE(COMP_INIT,
+                        "Oops: devname already taken! Trying wlan%%d...\n");
                        dev_alloc_name(dev, ifname);
        }
 
@@ -2981,7 +2972,7 @@ err_pci_disable:
 static void rtl8192_pci_disconnect(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
-       struct r8192_priv *priv ;
+       struct r8192_priv *priv;
        u32 i;
 
        if (dev) {
@@ -3004,7 +2995,7 @@ static void rtl8192_pci_disconnect(struct pci_dev *pdev)
                        rtl8192_free_tx_ring(dev, i);
 
                if (priv->irq) {
-                       printk(KERN_INFO "Freeing irq %d\n", dev->irq);
+                       dev_info(&pdev->dev, "Freeing irq %d\n", dev->irq);
                        free_irq(dev->irq, dev);
                        priv->irq = 0;
                }
@@ -3032,7 +3023,7 @@ bool NicIFEnableNIC(struct net_device *dev)
        struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
                                        (&(priv->rtllib->PowerSaveControl));
 
-       if (IS_NIC_DOWN(priv)) {
+       if (!priv->up) {
                RT_TRACE(COMP_ERR, "ERR!!! %s(): Driver is already down!\n",
                         __func__);
                priv->bdisable_nic = false;
@@ -3059,7 +3050,6 @@ bool NicIFEnableNIC(struct net_device *dev)
 }
 bool NicIFDisableNIC(struct net_device *dev)
 {
-       bool    status = true;
        struct r8192_priv *priv = rtllib_priv(dev);
        u8 tmp_state = 0;
 
@@ -3074,13 +3064,13 @@ bool NicIFDisableNIC(struct net_device *dev)
        priv->ops->stop_adapter(dev, false);
        RT_TRACE(COMP_PS, "<=========%s()\n", __func__);
 
-       return status;
+       return true;
 }
 
 static int __init rtl8192_pci_module_init(void)
 {
-       printk(KERN_INFO "\nLinux kernel driver for RTL8192E WLAN cards\n");
-       printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan Driver\n");
+       pr_info("\nLinux kernel driver for RTL8192E WLAN cards\n");
+       pr_info("Copyright (c) 2007-2008, Realsil Wlan Driver\n");
 
        if (0 != pci_register_driver(&rtl8192_pci_driver)) {
                DMESG("No device found");
@@ -3106,7 +3096,7 @@ void check_rfctrl_gpio_timer(unsigned long data)
        queue_delayed_work_rsl(priv->priv_wq, &priv->gpio_change_rf_wq, 0);
 
        mod_timer(&priv->gpio_polling_timer, jiffies +
-                 MSECS(RTLLIB_WATCH_DOG_TIME));
+                 msecs_to_jiffies(RTLLIB_WATCH_DOG_TIME));
 }
 
 /***************************************************************************
index d1438c2f8980e35b92351c7e0126886d3718075c..d365af6ebdc7b56bb71729d4e3e332e15eb9fbca 100644 (file)
 #define BIT(_i)                                (1<<(_i))
 #endif
 
-#define IS_NIC_DOWN(priv)      (!(priv)->up)
-
 #define IS_ADAPTER_SENDS_BEACON(dev) 0
 
-#define IS_UNDER_11N_AES_MODE(_rtllib)         \
-       ((_rtllib->pHTInfo->bCurrentHTSupport == true) && \
-       (_rtllib->pairwise_key_type == KEY_TYPE_CCMP))
-
 #define HAL_MEMORY_MAPPED_IO_RANGE_8190PCI     0x1000
 #define HAL_HW_PCI_REVISION_ID_8190PCI                 0x00
 #define HAL_MEMORY_MAPPED_IO_RANGE_8192PCIE    0x4000
@@ -1004,14 +998,14 @@ 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) ;
+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) ;
+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);
index b8891c62af3e3d116b7891ee7d89fa66c74a3159..df4bbcf38bae90c975cd96f8d1cc0b41d705b6aa 100644 (file)
@@ -267,7 +267,7 @@ static void dm_check_rate_adaptive(struct net_device *dev)
        bool bshort_gi_enabled = false;
        static u8 ping_rssi_state;
 
-       if (IS_NIC_DOWN(priv)) {
+       if (!priv->up) {
                RT_TRACE(COMP_RATE, "<---- dm_check_rate_adaptive(): driver is going to unload\n");
                return;
        }
@@ -378,19 +378,16 @@ static void dm_bandwidth_autoswitch(struct net_device *dev)
        struct r8192_priv *priv = rtllib_priv(dev);
 
        if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ||
-          !priv->rtllib->bandwidth_auto_switch.bautoswitch_enable) {
+          !priv->rtllib->bandwidth_auto_switch.bautoswitch_enable)
                return;
+       if (priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz == false) {
+               if (priv->undecorated_smoothed_pwdb <=
+                   priv->rtllib->bandwidth_auto_switch.threshold_40Mhzto20Mhz)
+                       priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = true;
        } else {
-               if (priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz == false) {
-                       if (priv->undecorated_smoothed_pwdb <=
-                           priv->rtllib->bandwidth_auto_switch.threshold_40Mhzto20Mhz)
-                               priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = true;
-               } else {
-                       if (priv->undecorated_smoothed_pwdb >=
-                           priv->rtllib->bandwidth_auto_switch.threshold_20Mhzto40Mhz)
-                               priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = false;
-
-               }
+               if (priv->undecorated_smoothed_pwdb >=
+                   priv->rtllib->bandwidth_auto_switch.threshold_20Mhzto40Mhz)
+                       priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = false;
        }
 }
 
@@ -501,7 +498,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
                                        write_nic_byte(dev, FW_Busy_Flag, 0);
                                        return;
                                }
-                               if ((priv->rtllib->eRFPowerState != eRfOn)) {
+                               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);
@@ -581,148 +578,148 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
                                         "priv->CCKPresentAttentuation = %d\n",
                                         priv->CCKPresentAttentuation);
                                return;
-                       } else {
-                               if (Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK) {
-                                       if (RF_Type == RF_2T4R) {
-
-                                               if ((priv->rfa_txpowertrackingindex > 0) &&
-                                                   (priv->rfc_txpowertrackingindex > 0)) {
-                                                       priv->rfa_txpowertrackingindex--;
-                                                       if (priv->rfa_txpowertrackingindex_real > 4) {
-                                                               priv->rfa_txpowertrackingindex_real--;
-                                                               rtl8192_setBBreg(dev,
-                                                                        rOFDM0_XATxIQImbalance,
-                                                                        bMaskDWord,
-                                                                        priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
-                                                       }
-
-                                                       priv->rfc_txpowertrackingindex--;
-                                                       if (priv->rfc_txpowertrackingindex_real > 4) {
-                                                               priv->rfc_txpowertrackingindex_real--;
-                                                               rtl8192_setBBreg(dev,
-                                                                        rOFDM0_XCTxIQImbalance,
-                                                                        bMaskDWord,
-                                                                        priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
-                                                       }
-                                               } else {
-                                                       rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
-                                                                        bMaskDWord,
-                                                                        priv->txbbgain_table[4].txbbgain_value);
-                                                       rtl8192_setBBreg(dev,
-                                                                        rOFDM0_XCTxIQImbalance,
-                                                                        bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
-                                               }
-                                       } else {
-                                               if (priv->rfa_txpowertrackingindex > 0) {
-                                                       priv->rfa_txpowertrackingindex--;
-                                                       if (priv->rfa_txpowertrackingindex_real > 4) {
-                                                               priv->rfa_txpowertrackingindex_real--;
-                                                               rtl8192_setBBreg(dev,
-                                                                                rOFDM0_XATxIQImbalance,
-                                                                                bMaskDWord,
-                                                                                priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
-                                                       }
-                                               } else
-                                                       rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
-                                                                        bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
+                       }
+                       if (Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK) {
+                               if (RF_Type == RF_2T4R) {
 
-                                       }
-                               } else {
-                                       if (RF_Type == RF_2T4R) {
-                                               if ((priv->rfa_txpowertrackingindex <
-                                                   TxBBGainTableLength - 1) &&
-                                                   (priv->rfc_txpowertrackingindex <
-                                                   TxBBGainTableLength - 1)) {
-                                                       priv->rfa_txpowertrackingindex++;
-                                                       priv->rfa_txpowertrackingindex_real++;
+                                       if ((priv->rfa_txpowertrackingindex > 0) &&
+                                           (priv->rfc_txpowertrackingindex > 0)) {
+                                               priv->rfa_txpowertrackingindex--;
+                                               if (priv->rfa_txpowertrackingindex_real > 4) {
+                                                       priv->rfa_txpowertrackingindex_real--;
                                                        rtl8192_setBBreg(dev,
                                                                 rOFDM0_XATxIQImbalance,
                                                                 bMaskDWord,
-                                                                priv->txbbgain_table
-                                                                [priv->rfa_txpowertrackingindex_real].txbbgain_value);
-                                                       priv->rfc_txpowertrackingindex++;
-                                                       priv->rfc_txpowertrackingindex_real++;
+                                                                priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
+                                               }
+
+                                               priv->rfc_txpowertrackingindex--;
+                                               if (priv->rfc_txpowertrackingindex_real > 4) {
+                                                       priv->rfc_txpowertrackingindex_real--;
                                                        rtl8192_setBBreg(dev,
                                                                 rOFDM0_XCTxIQImbalance,
                                                                 bMaskDWord,
                                                                 priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
-                                               } else {
-                                                       rtl8192_setBBreg(dev,
-                                                                rOFDM0_XATxIQImbalance,
-                                                                bMaskDWord,
-                                                                priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
-                                                       rtl8192_setBBreg(dev,
-                                                                rOFDM0_XCTxIQImbalance,
-                                                                bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
                                                }
                                        } else {
-                                               if (priv->rfa_txpowertrackingindex < (TxBBGainTableLength - 1)) {
-                                                       priv->rfa_txpowertrackingindex++;
-                                                       priv->rfa_txpowertrackingindex_real++;
-                                                       rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
+                                               rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
+                                                                bMaskDWord,
+                                                                priv->txbbgain_table[4].txbbgain_value);
+                                               rtl8192_setBBreg(dev,
+                                                                rOFDM0_XCTxIQImbalance,
+                                                                bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
+                                       }
+                               } else {
+                                       if (priv->rfa_txpowertrackingindex > 0) {
+                                               priv->rfa_txpowertrackingindex--;
+                                               if (priv->rfa_txpowertrackingindex_real > 4) {
+                                                       priv->rfa_txpowertrackingindex_real--;
+                                                       rtl8192_setBBreg(dev,
+                                                                        rOFDM0_XATxIQImbalance,
                                                                         bMaskDWord,
                                                                         priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
-                                               } else
-                                                       rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
-                                                                        bMaskDWord,
-                                                                        priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
-                                       }
+                                               }
+                                       } else
+                                               rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
+                                                                bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
+
                                }
+                       } else {
                                if (RF_Type == RF_2T4R) {
-                                       priv->CCKPresentAttentuation_difference
-                                               = priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default;
+                                       if ((priv->rfa_txpowertrackingindex <
+                                           TxBBGainTableLength - 1) &&
+                                           (priv->rfc_txpowertrackingindex <
+                                           TxBBGainTableLength - 1)) {
+                                               priv->rfa_txpowertrackingindex++;
+                                               priv->rfa_txpowertrackingindex_real++;
+                                               rtl8192_setBBreg(dev,
+                                                        rOFDM0_XATxIQImbalance,
+                                                        bMaskDWord,
+                                                        priv->txbbgain_table
+                                                        [priv->rfa_txpowertrackingindex_real].txbbgain_value);
+                                               priv->rfc_txpowertrackingindex++;
+                                               priv->rfc_txpowertrackingindex_real++;
+                                               rtl8192_setBBreg(dev,
+                                                        rOFDM0_XCTxIQImbalance,
+                                                        bMaskDWord,
+                                                        priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
+                                       } else {
+                                               rtl8192_setBBreg(dev,
+                                                        rOFDM0_XATxIQImbalance,
+                                                        bMaskDWord,
+                                                        priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
+                                               rtl8192_setBBreg(dev,
+                                                        rOFDM0_XCTxIQImbalance,
+                                                        bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
+                                       }
                                } else {
-                                       priv->CCKPresentAttentuation_difference
-                                               = priv->rfa_txpowertrackingindex_real - priv->rfa_txpowertracking_default;
-                               }
-
-                               if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
-                                       priv->CCKPresentAttentuation =
-                                                priv->CCKPresentAttentuation_20Mdefault +
-                                                priv->CCKPresentAttentuation_difference;
-                               else
-                                       priv->CCKPresentAttentuation =
-                                                priv->CCKPresentAttentuation_40Mdefault +
-                                                priv->CCKPresentAttentuation_difference;
-
-                               if (priv->CCKPresentAttentuation > (CCKTxBBGainTableLength-1))
-                                       priv->CCKPresentAttentuation = CCKTxBBGainTableLength-1;
-                               if (priv->CCKPresentAttentuation < 0)
-                                       priv->CCKPresentAttentuation = 0;
-
-                               if (priv->CCKPresentAttentuation > -1 &&
-                                   priv->CCKPresentAttentuation < CCKTxBBGainTableLength) {
-                                       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);
-                                       } 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);
+                                       if (priv->rfa_txpowertrackingindex < (TxBBGainTableLength - 1)) {
+                                               priv->rfa_txpowertrackingindex++;
+                                               priv->rfa_txpowertrackingindex_real++;
+                                               rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
+                                                                bMaskDWord,
+                                                                priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
                                        } else
-                                               dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+                                               rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
+                                                                bMaskDWord,
+                                                                priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
                                }
-                               RT_TRACE(COMP_POWER_TRACKING,
-                                        "priv->rfa_txpowertrackingindex = %d\n",
-                                        priv->rfa_txpowertrackingindex);
-                               RT_TRACE(COMP_POWER_TRACKING,
-                                        "priv->rfa_txpowertrackingindex_real = %d\n",
-                                        priv->rfa_txpowertrackingindex_real);
-                               RT_TRACE(COMP_POWER_TRACKING,
-                                        "priv->CCKPresentAttentuation_difference = %d\n",
-                                        priv->CCKPresentAttentuation_difference);
-                               RT_TRACE(COMP_POWER_TRACKING,
-                                        "priv->CCKPresentAttentuation = %d\n",
-                                        priv->CCKPresentAttentuation);
+                       }
+                       if (RF_Type == RF_2T4R) {
+                               priv->CCKPresentAttentuation_difference
+                                       = priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default;
+                       } else {
+                               priv->CCKPresentAttentuation_difference
+                                       = priv->rfa_txpowertrackingindex_real - priv->rfa_txpowertracking_default;
+                       }
 
-                               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);
-                                       RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n");
-                                       return;
-                               }
+                       if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
+                               priv->CCKPresentAttentuation =
+                                        priv->CCKPresentAttentuation_20Mdefault +
+                                        priv->CCKPresentAttentuation_difference;
+                       else
+                               priv->CCKPresentAttentuation =
+                                        priv->CCKPresentAttentuation_40Mdefault +
+                                        priv->CCKPresentAttentuation_difference;
+
+                       if (priv->CCKPresentAttentuation > (CCKTxBBGainTableLength-1))
+                               priv->CCKPresentAttentuation = CCKTxBBGainTableLength-1;
+                       if (priv->CCKPresentAttentuation < 0)
+                               priv->CCKPresentAttentuation = 0;
+
+                       if (priv->CCKPresentAttentuation > -1 &&
+                           priv->CCKPresentAttentuation < CCKTxBBGainTableLength) {
+                               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);
+                               } 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);
+                               } else
+                                       dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+                       }
+                       RT_TRACE(COMP_POWER_TRACKING,
+                                "priv->rfa_txpowertrackingindex = %d\n",
+                                priv->rfa_txpowertrackingindex);
+                       RT_TRACE(COMP_POWER_TRACKING,
+                                "priv->rfa_txpowertrackingindex_real = %d\n",
+                                priv->rfa_txpowertrackingindex_real);
+                       RT_TRACE(COMP_POWER_TRACKING,
+                                "priv->CCKPresentAttentuation_difference = %d\n",
+                                priv->CCKPresentAttentuation_difference);
+                       RT_TRACE(COMP_POWER_TRACKING,
+                                "priv->CCKPresentAttentuation = %d\n",
+                                priv->CCKPresentAttentuation);
+
+                       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);
+                               RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n");
+                               return;
                        }
+
                        write_nic_byte(dev, Pw_Track_Flag, 0);
                        Avg_TSSI_Meas_from_driver = 0;
                        for (k = 0; k < 5; k++)
@@ -757,8 +754,8 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
                for (i = 0; i < CCK_Table_length; i++) {
                        if (TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0]) {
                                priv->CCK_index = (u8) i;
-                               RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x"
-                                        " = 0x%x, CCK_index = 0x%x\n",
+                               RT_TRACE(COMP_POWER_TRACKING,
+                                        "Initial reg0x%x = 0x%x, CCK_index = 0x%x\n",
                                         rCCK0_TxFilter1, TempCCk,
                                         priv->CCK_index);
                                break;
@@ -803,8 +800,8 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
 
        priv->Record_CCK_20Mindex = tmpCCK20Mindex;
        priv->Record_CCK_40Mindex = tmpCCK40Mindex;
-       RT_TRACE(COMP_POWER_TRACKING, "Record_CCK_20Mindex / Record_CCK_40"
-                "Mindex = %d / %d.\n",
+       RT_TRACE(COMP_POWER_TRACKING,
+                "Record_CCK_20Mindex / Record_CCK_40Mindex = %d / %d.\n",
                 priv->Record_CCK_20Mindex, priv->Record_CCK_40Mindex);
 
        if (priv->rtllib->current_network.channel == 14 &&
@@ -1401,13 +1398,12 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev)
                TxPowerCheckCnt = 5;
        else
                TxPowerCheckCnt = 2;
-       if (!priv->btxpower_tracking) {
+       if (!priv->btxpower_tracking)
+               return;
+
+       if (priv->txpower_count  <= TxPowerCheckCnt) {
+               priv->txpower_count++;
                return;
-       } else {
-               if (priv->txpower_count  <= TxPowerCheckCnt) {
-                       priv->txpower_count++;
-                       return;
-               }
        }
 
        if (!TM_Trigger) {
@@ -1419,14 +1415,12 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev)
                }
                TM_Trigger = 1;
                return;
-       } else {
-           printk(KERN_INFO "===============>Schedule TxPowerTrackingWorkItem\n");
-
-               queue_delayed_work_rsl(priv->priv_wq, &priv->txpower_tracking_wq, 0);
-               TM_Trigger = 0;
-               }
-
        }
+       netdev_info(dev, "===============>Schedule TxPowerTrackingWorkItem\n");
+       queue_delayed_work_rsl(priv->priv_wq, &priv->txpower_tracking_wq, 0);
+       TM_Trigger = 0;
+
+}
 
 static void dm_check_txpower_tracking(struct net_device *dev)
 {
@@ -1446,7 +1440,7 @@ static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool  bInCH14)
        TempVal = 0;
        if (!bInCH14) {
                TempVal = (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
-                         (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ;
+                         (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8));
 
                rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
                TempVal = (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
@@ -1455,12 +1449,12 @@ static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool  bInCH14)
                          (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
                rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
                TempVal = (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
-                         (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ;
+                         (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8));
 
                rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
        } else {
                TempVal = (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
-                         (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ;
+                         (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8));
 
                rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
                TempVal = (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
@@ -1469,7 +1463,7 @@ static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool  bInCH14)
                          (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
                rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
                TempVal = (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
-                         (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ;
+                         (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8));
 
                rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
        }
@@ -1485,7 +1479,7 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,      bool  bInCH
        TempVal = 0;
        if (!bInCH14) {
                TempVal =       CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] +
-                                       (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8) ;
+                                       (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8);
                rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
                RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
                        rCCK0_TxFilter1, TempVal);
@@ -1497,14 +1491,14 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,    bool  bInCH
                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) ;
+                                       (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8);
 
                rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
                RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
                        rCCK0_DebugPort, TempVal);
        } else {
                TempVal =       CCKSwingTable_Ch14[priv->CCK_index][0] +
-                                       (CCKSwingTable_Ch14[priv->CCK_index][1]<<8) ;
+                                       (CCKSwingTable_Ch14[priv->CCK_index][1]<<8);
 
                rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
                RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
@@ -1517,7 +1511,7 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,      bool  bInCH
                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) ;
+                                       (CCKSwingTable_Ch14[priv->CCK_index][7]<<8);
 
                rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
                RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
@@ -1569,7 +1563,7 @@ void dm_restore_dynamic_mechanism_state(struct net_device *dev)
        u32     reg_ratr = priv->rate_adaptive.last_ratr;
        u32 ratr_value;
 
-       if (IS_NIC_DOWN(priv)) {
+       if (!priv->up) {
                RT_TRACE(COMP_RATE, "<---- dm_restore_dynamic_mechanism_state(): driver is going to unload\n");
                return;
        }
@@ -1830,12 +1824,11 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
        if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) &&
                (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_thresh))
                return;
-       if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh)) {
+       if (priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh) {
                if (dm_digtable.dig_state == DM_STA_DIG_OFF &&
                        (priv->reset_count == reset_cnt))
                        return;
-               else
-                       reset_cnt = priv->reset_count;
+               reset_cnt = priv->reset_count;
 
                dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX;
                dm_digtable.dig_state = DM_STA_DIG_OFF;
@@ -1857,19 +1850,18 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
                return;
        }
 
-       if ((priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh)) {
+       if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) {
                u8 reset_flag = 0;
 
                if (dm_digtable.dig_state == DM_STA_DIG_ON &&
                    (priv->reset_count == reset_cnt)) {
                        dm_ctrl_initgain_byrssi_highpwr(dev);
                        return;
-               } else {
-                       if (priv->reset_count != reset_cnt)
-                               reset_flag = 1;
-
-                       reset_cnt = priv->reset_count;
                }
+               if (priv->reset_count != reset_cnt)
+                       reset_flag = 1;
+
+               reset_cnt = priv->reset_count;
 
                dm_digtable.dig_state = DM_STA_DIG_ON;
 
@@ -1911,8 +1903,7 @@ static void dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev)
                if (dm_digtable.dig_highpwr_state == DM_STA_DIG_ON &&
                        (priv->reset_count == reset_cnt_highpwr))
                        return;
-               else
-                       dm_digtable.dig_highpwr_state = DM_STA_DIG_ON;
+               dm_digtable.dig_highpwr_state = DM_STA_DIG_ON;
 
                if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
                                write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
@@ -1922,8 +1913,7 @@ static void dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev)
                if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF &&
                        (priv->reset_count == reset_cnt_highpwr))
                        return;
-               else
-                       dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF;
+               dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF;
 
                if (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_lowthresh &&
                         priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) {
@@ -2008,7 +1998,7 @@ static void dm_pd_th(struct net_device *dev)
                if (dm_digtable.CurSTAConnectState == DIG_STA_CONNECT) {
                        if (dm_digtable.rssi_val >= dm_digtable.rssi_high_power_highthresh)
                                dm_digtable.curpd_thstate = DIG_PD_AT_HIGH_POWER;
-                       else if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh))
+                       else if (dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)
                                dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
                        else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) &&
                                        (dm_digtable.rssi_val < dm_digtable.rssi_high_power_lowthresh))
@@ -2065,9 +2055,9 @@ static    void dm_cs_ratio(struct net_device *dev)
 
        if (dm_digtable.PreSTAConnectState == dm_digtable.CurSTAConnectState) {
                if (dm_digtable.CurSTAConnectState == DIG_STA_CONNECT) {
-                       if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh))
+                       if (dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)
                                dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
-                       else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh))
+                       else if (dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh)
                                dm_digtable.curcs_ratio_state = DIG_CS_RATIO_HIGHER;
                        else
                                dm_digtable.curcs_ratio_state = dm_digtable.precs_ratio_state;
@@ -2131,10 +2121,10 @@ static void dm_check_edca_turbo(struct net_device *dev)
                static int wb_tmp;
 
                if (wb_tmp == 0) {
-                       printk(KERN_INFO "%s():iot peer is %s, bssid:"
-                              " %pM\n", __func__,
-                              peername[pHTInfo->IOTPeer],
-                              priv->rtllib->current_network.bssid);
+                       netdev_info(dev,
+                                   "%s():iot peer is %s, bssid: %pM\n",
+                                   __func__, peername[pHTInfo->IOTPeer],
+                                   priv->rtllib->current_network.bssid);
                        wb_tmp = 1;
                }
        }
@@ -2638,9 +2628,10 @@ void dm_fsync_timer_callback(unsigned long data)
                }
                priv->rate_record = rate_count;
                priv->rateCountDiffRecord = rate_count_diff;
-               RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rate"
-                        "Countdiff %d bSwitchFsync %d\n", priv->rate_record,
-                        rate_count, rate_count_diff, priv->bswitch_fsync);
+               RT_TRACE(COMP_HALDM,
+                        "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n",
+                        priv->rate_record, rate_count, rate_count_diff,
+                        priv->bswitch_fsync);
                if (priv->undecorated_smoothed_pwdb >
                    priv->rtllib->fsync_rssi_threshold &&
                    bSwitchFromCountDiff) {
@@ -2665,14 +2656,14 @@ void dm_fsync_timer_callback(unsigned long data)
                        if (timer_pending(&priv->fsync_timer))
                                del_timer_sync(&priv->fsync_timer);
                        priv->fsync_timer.expires = jiffies +
-                                MSECS(priv->rtllib->fsync_time_interval *
+                                msecs_to_jiffies(priv->rtllib->fsync_time_interval *
                                 priv->rtllib->fsync_multiple_timeinterval);
                        add_timer(&priv->fsync_timer);
                } else {
                        if (timer_pending(&priv->fsync_timer))
                                del_timer_sync(&priv->fsync_timer);
                        priv->fsync_timer.expires = jiffies +
-                                MSECS(priv->rtllib->fsync_time_interval);
+                                msecs_to_jiffies(priv->rtllib->fsync_time_interval);
                        add_timer(&priv->fsync_timer);
                }
        } else {
@@ -2685,9 +2676,10 @@ void dm_fsync_timer_callback(unsigned long data)
                write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
        }
        RT_TRACE(COMP_HALDM, "ContinueDiffCount %d\n", priv->ContinueDiffCount);
-       RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d "
-                "bSwitchFsync %d\n", priv->rate_record, rate_count,
-                rate_count_diff, priv->bswitch_fsync);
+       RT_TRACE(COMP_HALDM,
+                "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n",
+                priv->rate_record, rate_count, rate_count_diff,
+                priv->bswitch_fsync);
 }
 
 static void dm_StartHWFsync(struct net_device *dev)
@@ -2762,7 +2754,7 @@ static void dm_StartSWFsync(struct net_device *dev)
        if (timer_pending(&priv->fsync_timer))
                del_timer_sync(&priv->fsync_timer);
        priv->fsync_timer.expires = jiffies +
-                                   MSECS(priv->rtllib->fsync_time_interval);
+                                   msecs_to_jiffies(priv->rtllib->fsync_time_interval);
        add_timer(&priv->fsync_timer);
 
        write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd);
@@ -2778,12 +2770,14 @@ void dm_check_fsync(struct net_device *dev)
        static u8 reg_c38_State = RegC38_Default;
        static u32 reset_cnt;
 
-       RT_TRACE(COMP_HALDM, "RSSI %d TimeInterval %d MultipleTimeInterval "
-                "%d\n", priv->rtllib->fsync_rssi_threshold,
+       RT_TRACE(COMP_HALDM,
+                "RSSI %d TimeInterval %d MultipleTimeInterval %d\n",
+                priv->rtllib->fsync_rssi_threshold,
                 priv->rtllib->fsync_time_interval,
                 priv->rtllib->fsync_multiple_timeinterval);
-       RT_TRACE(COMP_HALDM, "RateBitmap 0x%x FirstDiffRateThreshold %d Second"
-                "DiffRateThreshold %d\n", priv->rtllib->fsync_rate_bitmap,
+       RT_TRACE(COMP_HALDM,
+                "RateBitmap 0x%x FirstDiffRateThreshold %d SecondDiffRateThreshold %d\n",
+                priv->rtllib->fsync_rate_bitmap,
                 priv->rtllib->fsync_firstdiff_ratethreshold,
                 priv->rtllib->fsync_seconddiff_ratethreshold);
 
index ab44a9a6927c7e5755814a6d1260f059d13e3b8a..3f02e11cfc57ec9d8599d797f5098871f909ded5 100644 (file)
@@ -255,14 +255,6 @@ extern     u8                      test_flag;
 /*------------------------Export global variable----------------------------*/
 
 
-/*------------------------Export Marco Definition---------------------------*/
-#define DM_APInitGainChangeNotify(Event)               \
-       {                                               \
-               dm_digtable.CurAPConnectState = Event;  \
-       }
-/*------------------------Export Marco Definition---------------------------*/
-
-
 /*--------------------------Exported Function prototype---------------------*/
 /*--------------------------Exported Function prototype---------------------*/
 extern  void    init_hal_dm(struct net_device *dev);
index 2ad92eee50c27dc47aa2be0922f70a740811f814..51f53be2de17f01e0b0090ce28ed3b90a142c2f7 100644 (file)
@@ -65,27 +65,32 @@ bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev)
        if (DeviceID == 0x8172) {
                switch (RevisionID) {
                case HAL_HW_PCI_REVISION_ID_8192PCIE:
-                       printk(KERN_INFO "Adapter(8192 PCI-E) is found - "
-                              "DeviceID=%x\n", DeviceID);
+                       dev_info(&pdev->dev,
+                                "Adapter(8192 PCI-E) is found - DeviceID=%x\n",
+                                DeviceID);
                        priv->card_8192 = NIC_8192E;
                        break;
                case HAL_HW_PCI_REVISION_ID_8192SE:
-                       printk(KERN_INFO "Adapter(8192SE) is found - "
-                              "DeviceID=%x\n", DeviceID);
+                       dev_info(&pdev->dev,
+                                "Adapter(8192SE) is found - DeviceID=%x\n",
+                                DeviceID);
                        priv->card_8192 = NIC_8192SE;
                        break;
                default:
-                       printk(KERN_INFO "UNKNOWN nic type(%4x:%4x)\n",
-                              pdev->vendor, pdev->device);
+                       dev_info(&pdev->dev,
+                                "UNKNOWN nic type(%4x:%4x)\n",
+                                pdev->vendor, pdev->device);
                        priv->card_8192 = NIC_UNKNOWN;
                        return false;
                }
        }
 
        if (priv->ops->nic_type != priv->card_8192) {
-               printk(KERN_INFO "Detect info(%x) and hardware info(%x) not match!\n",
-                               priv->ops->nic_type, priv->card_8192);
-               printk(KERN_INFO "Please select proper driver before install!!!!\n");
+               dev_info(&pdev->dev,
+                        "Detect info(%x) and hardware info(%x) not match!\n",
+                        priv->ops->nic_type, priv->card_8192);
+               dev_info(&pdev->dev,
+                        "Please select proper driver before install!!!!\n");
                return false;
        }
 
index 0b4f76481bf4322f7d764a5e33754628db618ece..ca6ecfc8299e88b75a5b0b9357afd51707c5494a 100644 (file)
@@ -29,14 +29,14 @@ int rtl8192E_suspend(struct pci_dev *pdev, pm_message_t state)
        struct r8192_priv *priv = rtllib_priv(dev);
        u32     ulRegRead;
 
-       printk(KERN_INFO "============> r8192E suspend call.\n");
+       netdev_info(dev, "============> r8192E suspend call.\n");
        del_timer_sync(&priv->gpio_polling_timer);
        cancel_delayed_work(&priv->gpio_change_rf_wq);
        priv->polling_timer_on = 0;
 
        if (!netif_running(dev)) {
-               printk(KERN_INFO "RTL819XE:UI is open out of suspend "
-                      "function\n");
+               netdev_info(dev,
+                           "RTL819XE:UI is open out of suspend function\n");
                goto out_pci_suspend;
        }
 
@@ -57,10 +57,10 @@ int rtl8192E_suspend(struct pci_dev *pdev, pm_message_t state)
                write_nic_byte(dev, MacBlkCtrl, 0xa);
        }
 out_pci_suspend:
-       printk("r8192E support WOL call??????????????????????\n");
+       netdev_info(dev, "r8192E support WOL call??????????????????????\n");
        if (priv->rtllib->bSupportRemoteWakeUp)
-               RT_TRACE(COMP_POWER, "r8192E support WOL call!!!!!!!"
-                        "!!!!!!!!!!!.\n");
+               RT_TRACE(COMP_POWER,
+                        "r8192E support WOL call!!!!!!!!!!!!!!!!!!.\n");
        pci_save_state(pdev);
        pci_disable_device(pdev);
        pci_enable_wake(pdev, pci_choose_state(pdev, state),
@@ -79,14 +79,13 @@ int rtl8192E_resume(struct pci_dev *pdev)
        int err;
        u32 val;
 
-       printk(KERN_INFO "================>r8192E resume call.\n");
+       netdev_info(dev, "================>r8192E resume call.\n");
 
        pci_set_power_state(pdev, PCI_D0);
 
        err = pci_enable_device(pdev);
        if (err) {
-               printk(KERN_ERR "%s: pci_enable_device failed on resume\n",
-                      dev->name);
+               netdev_err(dev, "pci_enable_device failed on resume\n");
                return err;
        }
        pci_restore_state(pdev);
@@ -101,8 +100,8 @@ int rtl8192E_resume(struct pci_dev *pdev)
                check_rfctrl_gpio_timer((unsigned long)dev);
 
        if (!netif_running(dev)) {
-               printk(KERN_INFO "RTL819XE:UI is open out of resume "
-                      "function\n");
+               netdev_info(dev,
+                           "RTL819XE:UI is open out of resume function\n");
                goto out;
        }
 
index 4856b76292f9a3507340c2f89139cf99b3856f07..0bbffec0c2ae2eca8f49c05fa21d8cc4f1a8adbd 100644 (file)
@@ -37,8 +37,8 @@ static void rtl8192_hw_sleep_down(struct net_device *dev)
        spin_lock_irqsave(&priv->rf_ps_lock, flags);
        if (priv->RFChangeInProgress) {
                spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
-               RT_TRACE(COMP_DBG, "rtl8192_hw_sleep_down(): RF Change in "
-                        "progress!\n");
+               RT_TRACE(COMP_DBG,
+                        "rtl8192_hw_sleep_down(): RF Change in progress!\n");
                return;
        }
        spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
@@ -64,10 +64,11 @@ void rtl8192_hw_wakeup(struct net_device *dev)
        spin_lock_irqsave(&priv->rf_ps_lock, flags);
        if (priv->RFChangeInProgress) {
                spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
-               RT_TRACE(COMP_DBG, "rtl8192_hw_wakeup(): RF Change in "
-                        "progress!\n");
+               RT_TRACE(COMP_DBG,
+                        "rtl8192_hw_wakeup(): RF Change in progress!\n");
                queue_delayed_work_rsl(priv->rtllib->wq,
-                                      &priv->rtllib->hw_wakeup_wq, MSECS(10));
+                                      &priv->rtllib->hw_wakeup_wq,
+                                      msecs_to_jiffies(10));
                return;
        }
        spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
@@ -95,18 +96,18 @@ void rtl8192_hw_to_sleep(struct net_device *dev, u64 time)
 
        spin_lock_irqsave(&priv->ps_lock, flags);
 
-       time -= MSECS(8+16+7);
+       time -= msecs_to_jiffies(8 + 16 + 7);
 
-       if ((time - jiffies) <= MSECS(MIN_SLEEP_TIME)) {
+       if ((time - jiffies) <= msecs_to_jiffies(MIN_SLEEP_TIME)) {
                spin_unlock_irqrestore(&priv->ps_lock, flags);
-               printk(KERN_INFO "too short to sleep::%lld < %ld\n",
-                      time - jiffies, MSECS(MIN_SLEEP_TIME));
+               netdev_info(dev, "too short to sleep::%lld < %ld\n",
+                           time - jiffies, msecs_to_jiffies(MIN_SLEEP_TIME));
                return;
        }
 
-       if ((time - jiffies) > MSECS(MAX_SLEEP_TIME)) {
-               printk(KERN_INFO "========>too long to sleep:%lld > %ld\n",
-                      time - jiffies,  MSECS(MAX_SLEEP_TIME));
+       if ((time - jiffies) > msecs_to_jiffies(MAX_SLEEP_TIME)) {
+               netdev_info(dev, "========>too long to sleep:%lld > %ld\n",
+                           time - jiffies, msecs_to_jiffies(MAX_SLEEP_TIME));
                spin_unlock_irqrestore(&priv->ps_lock, flags);
                return;
        }
@@ -201,12 +202,11 @@ void rtllib_ips_leave_wq(struct net_device *dev)
                                RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",
                                         __func__);
                                return;
-                       } else {
-                               printk(KERN_INFO "=========>%s(): IPSLeave\n",
-                                      __func__);
-                               queue_work_rsl(priv->rtllib->wq,
-                                              &priv->rtllib->ips_leave_wq);
                        }
+                       netdev_info(dev, "=========>%s(): IPSLeave\n",
+                                   __func__);
+                       queue_work_rsl(priv->rtllib->wq,
+                                      &priv->rtllib->ips_leave_wq);
                }
        }
 }
@@ -239,8 +239,8 @@ static bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev,
                priv->rtllib->sta_sleep = LPS_IS_WAKE;
 
                spin_lock_irqsave(&(priv->rtllib->mgmt_tx_lock), flags);
-               RT_TRACE(COMP_DBG, "LPS leave: notify AP we are awaked"
-                        " ++++++++++ SendNullFunctionData\n");
+               RT_TRACE(COMP_DBG,
+                        "LPS leave: notify AP we are awaked ++++++++++ SendNullFunctionData\n");
                rtllib_sta_ps_send_null_frame(priv->rtllib, 0);
                spin_unlock_irqrestore(&(priv->rtllib->mgmt_tx_lock), flags);
        }
@@ -255,8 +255,8 @@ void LeisurePSEnter(struct net_device *dev)
                                        &(priv->rtllib->PowerSaveControl);
 
        RT_TRACE(COMP_PS, "LeisurePSEnter()...\n");
-       RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d,pPSC->LpsIdle"
-                "Count is %d,RT_CHECK_FOR_HANG_PERIOD is %d\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,
                 RT_CHECK_FOR_HANG_PERIOD);
 
@@ -271,8 +271,8 @@ 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");
+                               RT_TRACE(COMP_LPS,
+                                        "LeisurePSEnter(): Enter 802.11 power save mode...\n");
 
                                if (!pPSC->bFwCtrlLPS) {
                                        if (priv->rtllib->SetFwCmdHandler)
@@ -301,8 +301,8 @@ void LeisurePSLeave(struct net_device *dev)
 
        if (pPSC->bLeisurePs) {
                if (priv->rtllib->ps != RTLLIB_PS_DISABLED) {
-                       RT_TRACE(COMP_LPS, "LeisurePSLeave(): Busy Traffic , "
-                                "Leave 802.11 power save..\n");
+                       RT_TRACE(COMP_LPS,
+                                "LeisurePSLeave(): Busy Traffic , Leave 802.11 power save..\n");
                        MgntActSet_802_11_PowerSaveMode(dev,
                                         RTLLIB_PS_DISABLED);
 
index df0323f00f69c1e808a9a1e790d49740bfba281c..8d6a109e023bd8d82e8a5239f113c89ee0722b6d 100644 (file)
@@ -67,7 +67,7 @@ static int r8192_wx_set_rate(struct net_device *dev,
        int ret;
        struct r8192_priv *priv = rtllib_priv(dev);
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        down(&priv->wx_sem);
@@ -87,7 +87,7 @@ static int r8192_wx_set_rts(struct net_device *dev,
        int ret;
        struct r8192_priv *priv = rtllib_priv(dev);
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        down(&priv->wx_sem);
@@ -115,9 +115,10 @@ static int r8192_wx_set_power(struct net_device *dev,
        int ret;
        struct r8192_priv *priv = rtllib_priv(dev);
 
-       if (priv->bHwRadioOff == true) {
-               RT_TRACE(COMP_ERR, "%s():Hw is Radio Off, we can't set "
-                        "Power,return\n", __func__);
+       if (priv->bHwRadioOff) {
+               RT_TRACE(COMP_ERR,
+                        "%s():Hw is Radio Off, we can't set Power,return\n",
+                        __func__);
                return 0;
        }
        down(&priv->wx_sem);
@@ -145,7 +146,7 @@ static int r8192_wx_set_rawtx(struct net_device *dev,
        struct r8192_priv *priv = rtllib_priv(dev);
        int ret;
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        down(&priv->wx_sem);
@@ -254,10 +255,11 @@ static int r8192se_wx_set_radio(struct net_device *dev,
 
        down(&priv->wx_sem);
 
-       printk(KERN_INFO "%s(): set radio ! extra is %d\n", __func__, *extra);
+       netdev_info(dev, "%s(): set radio ! extra is %d\n", __func__, *extra);
        if ((*extra != 0) && (*extra != 1)) {
-               RT_TRACE(COMP_ERR, "%s(): set radio an err value,must 0(radio "
-                        "off) or 1(radio on)\n", __func__);
+               RT_TRACE(COMP_ERR,
+                        "%s(): set radio an err value,must 0(radio off) or 1(radio on)\n",
+                        __func__);
                up(&priv->wx_sem);
                return -1;
        }
@@ -277,8 +279,8 @@ static int r8192se_wx_set_lps_awake_interval(struct net_device *dev,
 
        down(&priv->wx_sem);
 
-       printk(KERN_INFO "%s(): set lps awake interval ! extra is %d\n",
-              __func__, *extra);
+       netdev_info(dev, "%s(): set lps awake interval ! extra is %d\n",
+                   __func__, *extra);
 
        pPSC->RegMaxLPSAwakeIntvl = *extra;
        up(&priv->wx_sem);
@@ -293,8 +295,9 @@ static int r8192se_wx_set_force_lps(struct net_device *dev,
 
        down(&priv->wx_sem);
 
-       printk(KERN_INFO "%s(): force LPS ! extra is %d (1 is open 0 is "
-              "close)\n", __func__, *extra);
+       netdev_info(dev,
+                   "%s(): force LPS ! extra is %d (1 is open 0 is close)\n",
+                   __func__, *extra);
        priv->force_lps = *extra;
        up(&priv->wx_sem);
        return 0;
@@ -308,11 +311,11 @@ static int r8192_wx_set_debugflag(struct net_device *dev,
        struct r8192_priv *priv = rtllib_priv(dev);
        u8 c = *extra;
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
-       printk(KERN_INFO "=====>%s(), *extra:%x, debugflag:%x\n", __func__,
-              *extra, rt_global_debug_component);
+       netdev_info(dev, "=====>%s(), *extra:%x, debugflag:%x\n", __func__,
+                   *extra, rt_global_debug_component);
        if (c > 0)
                rt_global_debug_component |= (1<<c);
        else
@@ -329,7 +332,7 @@ static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
        enum rt_rf_power_state rtState;
        int ret;
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
        rtState = priv->rtllib->eRFPowerState;
        down(&priv->wx_sem);
@@ -343,13 +346,12 @@ static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
                                                 __func__);
                                        up(&priv->wx_sem);
                                        return -1;
-                               } else {
-                                       printk(KERN_INFO "=========>%s(): "
-                                              "IPSLeave\n", __func__);
-                                       down(&priv->rtllib->ips_sem);
-                                       IPSLeave(dev);
-                                       up(&priv->rtllib->ips_sem);
                                }
+                               netdev_info(dev,  "=========>%s(): IPSLeave\n",
+                                           __func__);
+                               down(&priv->rtllib->ips_sem);
+                               IPSLeave(dev);
+                               up(&priv->rtllib->ips_sem);
                        }
                }
        }
@@ -470,9 +472,9 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
                        return 0;
        }
 
-       if (priv->bHwRadioOff == true) {
-               printk(KERN_INFO "================>%s(): hwradio off\n",
-                      __func__);
+       if (priv->bHwRadioOff) {
+               netdev_info(dev, "================>%s(): hwradio off\n",
+                           __func__);
                return 0;
        }
        rtState = priv->rtllib->eRFPowerState;
@@ -500,17 +502,17 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
                        if (rtState == eRfOff) {
                                if (priv->rtllib->RfOffReason >
                                    RF_CHANGE_BY_IPS) {
-                                       RT_TRACE(COMP_ERR, "%s(): RF is "
-                                                "OFF.\n", __func__);
+                                       RT_TRACE(COMP_ERR,
+                                                "%s(): RF is OFF.\n",
+                                                __func__);
                                        up(&priv->wx_sem);
                                        return -1;
-                               } else {
-                                       RT_TRACE(COMP_PS, "=========>%s(): "
-                                                "IPSLeave\n", __func__);
-                                       down(&priv->rtllib->ips_sem);
-                                       IPSLeave(dev);
-                                       up(&priv->rtllib->ips_sem);
                                }
+                               RT_TRACE(COMP_PS, "=========>%s(): IPSLeave\n",
+                                        __func__);
+                               down(&priv->rtllib->ips_sem);
+                               IPSLeave(dev);
+                               up(&priv->rtllib->ips_sem);
                        }
                }
                rtllib_stop_scan(priv->rtllib);
@@ -552,7 +554,7 @@ static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
        if (!priv->up)
                return -ENETDOWN;
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
 
@@ -572,13 +574,10 @@ static int r8192_wx_set_essid(struct net_device *dev,
        struct r8192_priv *priv = rtllib_priv(dev);
        int ret;
 
-       if ((rtllib_act_scanning(priv->rtllib, false)) &&
-           !(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)) {
-               ;       /* TODO - get rid of if */
-       }
-       if (priv->bHwRadioOff == true) {
-               printk(KERN_INFO "=========>%s():hw radio off,or Rf state is "
-                      "eRfOff, return\n", __func__);
+       if (priv->bHwRadioOff) {
+               netdev_info(dev,
+                           "=========>%s():hw radio off,or Rf state is eRfOff, return\n",
+                           __func__);
                return 0;
        }
        down(&priv->wx_sem);
@@ -642,7 +641,7 @@ static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
        int ret;
        struct r8192_priv *priv = rtllib_priv(dev);
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        down(&priv->wx_sem);
@@ -669,7 +668,7 @@ static int r8192_wx_set_frag(struct net_device *dev,
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        if (wrqu->frag.disabled)
@@ -708,12 +707,7 @@ static int r8192_wx_set_wap(struct net_device *dev,
        int ret;
        struct r8192_priv *priv = rtllib_priv(dev);
 
-       if ((rtllib_act_scanning(priv->rtllib, false)) &&
-           !(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)) {
-               ;       /* TODO - get rid of if */
-       }
-
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        down(&priv->wx_sem);
@@ -763,10 +757,7 @@ static int r8192_wx_set_enc(struct net_device *dev,
                             {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
        int i;
 
-       if ((rtllib_act_scanning(priv->rtllib, false)) &&
-          !(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN))
-               ;       /* TODO - get rid of if */
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        if (!priv->up)
@@ -838,7 +829,8 @@ static int r8192_wx_set_enc(struct net_device *dev,
                        set_swcam(dev, key_idx, key_idx, KEY_TYPE_WEP104,
                                  zero_addr[key_idx], 0, hwkey, 0);
                } else {
-                        printk(KERN_INFO "wrong type in WEP, not WEP40 and WEP104\n");
+                       netdev_info(dev,
+                                   "wrong type in WEP, not WEP40 and WEP104\n");
                }
        }
 
@@ -855,7 +847,7 @@ static int r8192_wx_set_scan_type(struct net_device *dev,
        int *parms = (int *)p;
        int mode = parms[0];
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        priv->rtllib->active_scan = mode;
@@ -873,7 +865,7 @@ static int r8192_wx_set_retry(struct net_device *dev,
        struct r8192_priv *priv = rtllib_priv(dev);
        int err = 0;
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        down(&priv->wx_sem);
@@ -956,7 +948,7 @@ static int r8192_wx_set_sens(struct net_device *dev,
 
        short err = 0;
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        down(&priv->wx_sem);
@@ -983,7 +975,7 @@ static int r8192_wx_set_enc_ext(struct net_device *dev,
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rtllib_device *ieee = priv->rtllib;
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        down(&priv->wx_sem);
@@ -1064,7 +1056,7 @@ static int r8192_wx_set_auth(struct net_device *dev,
 
        struct r8192_priv *priv = rtllib_priv(dev);
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        down(&priv->wx_sem);
@@ -1082,7 +1074,7 @@ static int r8192_wx_set_mlme(struct net_device *dev,
 
        struct r8192_priv *priv = rtllib_priv(dev);
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        down(&priv->wx_sem);
@@ -1099,7 +1091,7 @@ static int r8192_wx_set_gen_ie(struct net_device *dev,
 
        struct r8192_priv *priv = rtllib_priv(dev);
 
-       if (priv->bHwRadioOff == true)
+       if (priv->bHwRadioOff)
                return 0;
 
        down(&priv->wx_sem);
@@ -1160,8 +1152,10 @@ static int r8192_wx_set_PromiscuousMode(struct net_device *dev,
                        (rtllib_EnableIntelPromiscuousMode(dev, false)) :
                        (rtllib_DisableIntelPromiscuousMode(dev, false));
 
-               printk(KERN_INFO "=======>%s(), on = %d, filter src sta = %d\n",
-                      __func__, bPromiscuousOn, bFilterSourceStationFrame);
+               netdev_info(dev,
+                           "=======>%s(), on = %d, filter src sta = %d\n",
+                           __func__, bPromiscuousOn,
+                           bFilterSourceStationFrame);
        } else {
                return -1;
        }
@@ -1227,11 +1221,10 @@ static iw_handler r8192_wx_handlers[] = {
        IW_IOCTL(SIOCSIWENCODEEXT) = r8192_wx_set_enc_ext,
 };
 
-/*
- * the following rule need to be following,
+/* the following rule need to be following,
  * Odd : get (world access),
  * even : set (root access)
- * */
+ */
 static const struct iw_priv_args r8192_private_args[] = {
        {
                SIOCIWFIRSTPRIV + 0x0,
index 0415e02b4eff4d23287d7e874fb1ee3d09cbee55..26258ea8de4aa540ca945e33cefdb87bc542f97c 100644 (file)
@@ -26,7 +26,7 @@ static void ActivateBAEntry(struct rtllib_device *ieee, struct ba_record *pBA,
 {
        pBA->bValid = true;
        if (Time != 0)
-               mod_timer(&pBA->Timer, jiffies + MSECS(Time));
+               mod_timer(&pBA->Timer, jiffies + msecs_to_jiffies(Time));
 }
 
 static void DeActivateBAEntry(struct rtllib_device *ieee, struct ba_record *pBA)
@@ -83,9 +83,9 @@ static struct sk_buff *rtllib_ADDBA(struct rtllib_device *ieee, u8 *Dst,
        u8 *tag = NULL;
        u16 len = ieee->tx_headroom + 9;
 
-       RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "========>%s(), frame(%d)"
-                    " sentd to: %pM, ieee->dev:%p\n", __func__,
-                    type, Dst, ieee->dev);
+       RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA,
+                    "========>%s(), frame(%d) sentd to: %pM, ieee->dev:%p\n",
+                    __func__, type, Dst, ieee->dev);
        if (pBA == NULL) {
                RTLLIB_DEBUG(RTLLIB_DL_ERR, "pBA is NULL\n");
                return NULL;
@@ -148,9 +148,8 @@ static struct sk_buff *rtllib_DELBA(struct rtllib_device *ieee, u8 *dst,
 
        if (net_ratelimit())
                RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA,
-                            "========>%s(), Reason"
-                            "Code(%d) sentd to: %pM\n", __func__,
-                            ReasonCode, dst);
+                            "========>%s(), ReasonCode(%d) sentd to: %pM\n",
+                            __func__, ReasonCode, dst);
 
        memset(&DelbaParamSet, 0, 2);
 
@@ -203,8 +202,8 @@ static void rtllib_send_ADDBAReq(struct rtllib_device *ieee, u8 *dst,
                RT_TRACE(COMP_DBG, "====>to send ADDBAREQ!!!!!\n");
                softmac_mgmt_xmit(skb, ieee);
        } else {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function"
-                            " %s()\n", __func__);
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "alloc skb error in function %s()\n", __func__);
        }
 }
 
@@ -217,8 +216,8 @@ static void rtllib_send_ADDBARsp(struct rtllib_device *ieee, u8 *dst,
        if (skb)
                softmac_mgmt_xmit(skb, ieee);
        else
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function"
-                            " %s()\n", __func__);
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "alloc skb error in function %s()\n", __func__);
 }
 
 static void rtllib_send_DELBA(struct rtllib_device *ieee, u8 *dst,
@@ -231,8 +230,8 @@ static void rtllib_send_DELBA(struct rtllib_device *ieee, u8 *dst,
        if (skb)
                softmac_mgmt_xmit(skb, ieee);
        else
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function"
-                            " %s()\n", __func__);
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "alloc skb error in function %s()\n", __func__);
 }
 
 int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb)
@@ -247,8 +246,9 @@ int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb)
        struct rx_ts_record *pTS = NULL;
 
        if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in BAREQ(%d / "
-                            "%d)\n", (int)skb->len,
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            " Invalid skb len in BAREQ(%d / %d)\n",
+                            (int)skb->len,
                             (int)(sizeof(struct rtllib_hdr_3addr) + 9));
                return -1;
        }
@@ -269,8 +269,8 @@ int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb)
            (ieee->pHTInfo->bCurrentHTSupport == false) ||
            (ieee->pHTInfo->IOTAction & HT_IOT_ACT_REJECT_ADDBA_REQ)) {
                rc = ADDBA_STATUS_REFUSED;
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "Failed to reply on ADDBA_REQ as "
-                            "some capability is not ready(%d, %d)\n",
+               RTLLIB_DEBUG(RTLLIB_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);
                goto OnADDBAReq_Fail;
@@ -285,8 +285,8 @@ int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb)
 
        if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
                rc = ADDBA_STATUS_INVALID_PARAM;
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "BA Policy is not correct in "
-                            "%s()\n", __func__);
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "BA Policy is not correct in %s()\n", __func__);
                goto OnADDBAReq_Fail;
        }
 
@@ -333,8 +333,9 @@ int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb)
        u16                     ReasonCode;
 
        if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in BARSP(%d / "
-                            "%d)\n", (int)skb->len,
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "Invalid skb len in BARSP(%d / %d)\n",
+                            (int)skb->len,
                             (int)(sizeof(struct rtllib_hdr_3addr) + 9));
                return -1;
        }
@@ -351,8 +352,8 @@ int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb)
        if (ieee->current_network.qos_data.active == 0  ||
            ieee->pHTInfo->bCurrentHTSupport == false ||
            ieee->pHTInfo->bCurrentAMPDUEnable == false) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "reject to ADDBA_RSP as some capab"
-                            "ility is not ready(%d, %d, %d)\n",
+               RTLLIB_DEBUG(RTLLIB_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);
@@ -374,18 +375,19 @@ int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb)
 
 
        if (pAdmittedBA->bValid == true) {
-               RTLLIB_DEBUG(RTLLIB_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp."
-                            " Drop because already admit it!\n");
+               RTLLIB_DEBUG(RTLLIB_DL_BA,
+                            "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it!\n");
                return -1;
        } else if ((pPendingBA->bValid == false) ||
                   (*pDialogToken != pPendingBA->DialogToken)) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR,  "OnADDBARsp(): Recv ADDBA Rsp. "
-                            "BA invalid, DELBA!\n");
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA!\n");
                ReasonCode = DELBA_REASON_UNKNOWN_BA;
                goto OnADDBARsp_Reject;
        } else {
-               RTLLIB_DEBUG(RTLLIB_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA "
-                            "is admitted! Status code:%X\n", *pStatusCode);
+               RTLLIB_DEBUG(RTLLIB_DL_BA,
+                            "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n",
+                            *pStatusCode);
                DeActivateBAEntry(ieee, pPendingBA);
        }
 
@@ -432,16 +434,17 @@ int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb)
        u8 *dst = NULL;
 
        if (skb->len < sizeof(struct rtllib_hdr_3addr) + 6) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in DELBA(%d /"
-                            " %d)\n", (int)skb->len,
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "Invalid skb len in DELBA(%d / %d)\n",
+                            (int)skb->len,
                             (int)(sizeof(struct rtllib_hdr_3addr) + 6));
                return -1;
        }
 
        if (ieee->current_network.qos_data.active == 0  ||
                ieee->pHTInfo->bCurrentHTSupport == false) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "received DELBA while QOS or HT "
-                            "is not supported(%d, %d)\n",
+               RTLLIB_DEBUG(RTLLIB_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;
@@ -459,8 +462,9 @@ int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb)
 
                if (!GetTs(ieee, (struct ts_common_info **)&pRxTs, dst,
                    (u8)pDelBaParamSet->field.TID, RX_DIR, false)) {
-                       RTLLIB_DEBUG(RTLLIB_DL_ERR,  "can't get TS for RXTS in "
-                                    "%s().dst: %pM TID:%d\n", __func__, dst,
+                       RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                                    "can't get TS for RXTS in %s().dst: %pM TID:%d\n",
+                                    __func__, dst,
                                     (u8)pDelBaParamSet->field.TID);
                        return -1;
                }
@@ -471,8 +475,9 @@ int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb)
 
                if (!GetTs(ieee, (struct ts_common_info **)&pTxTs, dst,
                           (u8)pDelBaParamSet->field.TID, TX_DIR, false)) {
-                       RTLLIB_DEBUG(RTLLIB_DL_ERR,  "can't get TS for TXTS in "
-                                    "%s()\n", __func__);
+                       RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                                    "can't get TS for TXTS in %s()\n",
+                                    __func__);
                        return -1;
                }
 
index 13f41057461a19938b0e36b9e8f3bf59fa10ca10..f7076d7ddc5357e71b04113dc90232a5e0e44787 100644 (file)
@@ -77,43 +77,6 @@ enum chnl_op {
        CHNLOP_SWCHNL = 3,
 };
 
-#define CHHLOP_IN_PROGRESS(_pHTInfo)   \
-               ((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? true : false
-
-/*
-union ht_capability {
-       u16     ShortData;
-       u8      CharData[2];
-       struct
-       {
-               u16     AdvCoding:1;
-               u16     ChlWidth:1;
-               u16     MimoPwrSave:2;
-               u16     GreenField:1;
-               u16     ShortGI20Mhz:1;
-               u16     ShortGI40Mhz:1;
-               u16     STBC:1;
-               u16     BeamForm:1;
-               u16     DelayBA:1;
-               u16     MaxAMSDUSize:1;
-               u16     DssCCk:1;
-               u16     PSMP:1;
-               u16     Rsvd:3;
-       }Field;
-};
-
-union ht_capability_macpara {
-       u8      ShortData;
-       u8      CharData[1];
-       struct
-       {
-               u8      MaxRxAMPDU:2;
-               u8      MPDUDensity:2;
-               u8      Rsvd:4;
-       }Field;
-};
-*/
-
 enum ht_action {
        ACT_RECOMMAND_WIDTH             = 0,
        ACT_MIMO_PWR_SAVE               = 1,
@@ -380,16 +343,6 @@ struct false_alarm_stats {
 extern u8 MCS_FILTER_ALL[16];
 extern u8 MCS_FILTER_1SS[16];
 
-#define PICK_RATE(_nLegacyRate, _nMcsRate)     \
-               ((_nMcsRate == 0) ? (_nLegacyRate&0x7f) : (_nMcsRate))
-#define        LEGACY_WIRELESS_MODE    IEEE_MODE_MASK
-
-#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate) \
-                       ((WirelessMode & (LEGACY_WIRELESS_MODE)) != 0) ? \
-                       (LegacyRate) : (PICK_RATE(LegacyRate, HTRate))
-
-
-
 #define        RATE_ADPT_1SS_MASK              0xFF
 #define        RATE_ADPT_2SS_MASK              0xF0
 #define        RATE_ADPT_MCS32_MASK            0x01
index 1ea426b7b7acd5401c172986811b5b5d689c02c5..7f103114d5d2a3dddc220074b464ced812dec360 100644 (file)
@@ -117,160 +117,6 @@ void HTUpdateDefaultSetting(struct rtllib_device *ieee)
        pHTInfo->RxReorderPendingTime = 30;
 }
 
-void HTDebugHTCapability(u8 *CapIE, u8 *TitleString)
-{
-
-       static u8       EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
-       struct ht_capab_ele *pCapELE;
-
-       if (!memcmp(CapIE, EWC11NHTCap, sizeof(EWC11NHTCap))) {
-               RTLLIB_DEBUG(RTLLIB_DL_HT, "EWC IE in %s()\n", __func__);
-               pCapELE = (struct ht_capab_ele *)(&CapIE[4]);
-       } else
-               pCapELE = (struct ht_capab_ele *)(&CapIE[0]);
-
-       RTLLIB_DEBUG(RTLLIB_DL_HT, "<Log HT Capability>. Called by %s\n",
-                    TitleString);
-
-       RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tSupported Channel Width = %s\n",
-                    (pCapELE->ChlWidth) ? "20MHz" : "20/40MHz");
-       RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tSupport Short GI for 20M = %s\n",
-                    (pCapELE->ShortGI20Mhz) ? "YES" : "NO");
-       RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tSupport Short GI for 40M = %s\n",
-                    (pCapELE->ShortGI40Mhz) ? "YES" : "NO");
-       RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tSupport TX STBC = %s\n",
-                    (pCapELE->TxSTBC) ? "YES" : "NO");
-       RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tMax AMSDU Size = %s\n",
-                    (pCapELE->MaxAMSDUSize) ? "3839" : "7935");
-       RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tSupport CCK in 20/40 mode = %s\n",
-                    (pCapELE->DssCCk) ? "YES" : "NO");
-       RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tMax AMPDU Factor = %d\n",
-                    pCapELE->MaxRxAMPDUFactor);
-       RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tMPDU Density = %d\n",
-                    pCapELE->MPDUDensity);
-       RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tMCS Rate Set = [%x][%x][%x][%x][%x]\n",
-                    pCapELE->MCS[0], pCapELE->MCS[1], pCapELE->MCS[2],
-                    pCapELE->MCS[3], pCapELE->MCS[4]);
-       return;
-
-}
-
-void HTDebugHTInfo(u8 *InfoIE, u8 *TitleString)
-{
-
-       static u8       EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34};
-       struct ht_info_ele *pHTInfoEle;
-
-       if (!memcmp(InfoIE, EWC11NHTInfo, sizeof(EWC11NHTInfo))) {
-               RTLLIB_DEBUG(RTLLIB_DL_HT, "EWC IE in %s()\n", __func__);
-               pHTInfoEle = (struct ht_info_ele *)(&InfoIE[4]);
-       } else
-               pHTInfoEle = (struct ht_info_ele *)(&InfoIE[0]);
-
-
-       RTLLIB_DEBUG(RTLLIB_DL_HT, "<Log HT Information Element>. "
-                    "Called by %s\n", TitleString);
-
-       RTLLIB_DEBUG(RTLLIB_DL_HT, "\tPrimary channel = %d\n",
-                    pHTInfoEle->ControlChl);
-       RTLLIB_DEBUG(RTLLIB_DL_HT, "\tSenondary channel =");
-       switch (pHTInfoEle->ExtChlOffset) {
-       case 0:
-               RTLLIB_DEBUG(RTLLIB_DL_HT, "Not Present\n");
-               break;
-       case 1:
-               RTLLIB_DEBUG(RTLLIB_DL_HT, "Upper channel\n");
-               break;
-       case 2:
-               RTLLIB_DEBUG(RTLLIB_DL_HT, "Reserved. Eooro!!!\n");
-               break;
-       case 3:
-               RTLLIB_DEBUG(RTLLIB_DL_HT, "Lower Channel\n");
-               break;
-       }
-       RTLLIB_DEBUG(RTLLIB_DL_HT, "\tRecommended channel width = %s\n",
-                    (pHTInfoEle->RecommemdedTxWidth) ? "20Mhz" : "40Mhz");
-
-       RTLLIB_DEBUG(RTLLIB_DL_HT, "\tOperation mode for protection = ");
-       switch (pHTInfoEle->OptMode) {
-       case 0:
-               RTLLIB_DEBUG(RTLLIB_DL_HT, "No Protection\n");
-               break;
-       case 1:
-               RTLLIB_DEBUG(RTLLIB_DL_HT, "HT non-member protection mode\n");
-               break;
-       case 2:
-               RTLLIB_DEBUG(RTLLIB_DL_HT, "Suggest to open protection\n");
-               break;
-       case 3:
-               RTLLIB_DEBUG(RTLLIB_DL_HT, "HT mixed mode\n");
-               break;
-       }
-
-       RTLLIB_DEBUG(RTLLIB_DL_HT, "\tBasic MCS Rate Set = [%x][%x][%x][%x]"
-                    "[%x]\n", pHTInfoEle->BasicMSC[0], pHTInfoEle->BasicMSC[1],
-                    pHTInfoEle->BasicMSC[2], pHTInfoEle->BasicMSC[3],
-                    pHTInfoEle->BasicMSC[4]);
-}
-
-static bool IsHTHalfNmode40Bandwidth(struct rtllib_device *ieee)
-{
-       bool                    retValue = false;
-       struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
-
-       if (pHTInfo->bCurrentHTSupport == false)
-               retValue = false;
-       else if (pHTInfo->bRegBW40MHz == false)
-               retValue = false;
-       else if (!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
-               retValue = false;
-       else if (((struct ht_capab_ele *)(pHTInfo->PeerHTCapBuf))->ChlWidth)
-               retValue = true;
-       else
-               retValue = false;
-
-       return retValue;
-}
-
-static bool IsHTHalfNmodeSGI(struct rtllib_device *ieee, bool is40MHz)
-{
-       bool                    retValue = false;
-       struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
-
-       if (pHTInfo->bCurrentHTSupport == false)
-               retValue = false;
-       else if (!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
-               retValue = false;
-       else if (is40MHz) {
-               if (((struct ht_capab_ele *)
-                   (pHTInfo->PeerHTCapBuf))->ShortGI40Mhz)
-                       retValue = true;
-               else
-                       retValue = false;
-       } else {
-               if (((struct ht_capab_ele *)
-                  (pHTInfo->PeerHTCapBuf))->ShortGI20Mhz)
-                       retValue = true;
-               else
-                       retValue = false;
-       }
-
-       return retValue;
-}
-
-u16 HTHalfMcsToDataRate(struct rtllib_device *ieee, u8 nMcsRate)
-{
-
-       u8      is40MHz;
-       u8      isShortGI;
-
-       is40MHz  =  (IsHTHalfNmode40Bandwidth(ieee)) ? 1 : 0;
-       isShortGI = (IsHTHalfNmodeSGI(ieee, is40MHz)) ? 1 : 0;
-
-       return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate & 0x7f)];
-}
-
-
 u16 HTMcsToDataRate(struct rtllib_device *ieee, u8 nMcsRate)
 {
        struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
@@ -289,25 +135,22 @@ u16  TxCountToDataRate(struct rtllib_device *ieee, u8 nDataRate)
        u8      is40MHz = 0;
        u8      isShortGI = 0;
 
-       if (nDataRate < 12) {
+       if (nDataRate < 12)
                return CCKOFDMRate[nDataRate];
-       } else {
-               if (nDataRate >= 0x10 && nDataRate <= 0x1f) {
-                       is40MHz = 0;
-                       isShortGI = 0;
-               } else if (nDataRate >= 0x20  && nDataRate <= 0x2f) {
-                       is40MHz = 1;
-                       isShortGI = 0;
-
-               } else if (nDataRate >= 0x30  && nDataRate <= 0x3f) {
-                       is40MHz = 0;
-                       isShortGI = 1;
-               } else if (nDataRate >= 0x40  && nDataRate <= 0x4f) {
-                       is40MHz = 1;
-                       isShortGI = 1;
-               }
-               return MCS_DATA_RATE[is40MHz][isShortGI][nDataRate&0xf];
+       if (nDataRate >= 0x10 && nDataRate <= 0x1f) {
+               is40MHz = 0;
+               isShortGI = 0;
+       } else if (nDataRate >= 0x20  && nDataRate <= 0x2f) {
+               is40MHz = 1;
+               isShortGI = 0;
+       } else if (nDataRate >= 0x30  && nDataRate <= 0x3f) {
+               is40MHz = 0;
+               isShortGI = 1;
+       } else if (nDataRate >= 0x40  && nDataRate <= 0x4f) {
+               is40MHz = 1;
+               isShortGI = 1;
        }
+       return MCS_DATA_RATE[is40MHz][isShortGI][nDataRate&0xf];
 }
 
 bool IsHTHalfNmodeAPs(struct rtllib_device *ieee)
@@ -386,9 +229,7 @@ static u8 HTIOTActIsDisableMCS14(struct rtllib_device *ieee, u8 *PeerMacAddr)
 
 static bool HTIOTActIsDisableMCS15(struct rtllib_device *ieee)
 {
-       bool retValue = false;
-
-       return retValue;
+       return false;
 }
 
 static bool HTIOTActIsDisableMCSTwoSpatialStream(struct rtllib_device *ieee)
@@ -450,8 +291,8 @@ void HTConstructCapabilityElement(struct rtllib_device *ieee, u8 *posHTCap,
        struct ht_capab_ele *pCapELE = NULL;
 
        if ((posHTCap == NULL) || (pHT == NULL)) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "posHTCap or pHTInfo can't be "
-                            "null in HTConstructCapabilityElement()\n");
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "posHTCap or pHTInfo can't be null in HTConstructCapabilityElement()\n");
                return;
        }
        memset(posHTCap, 0, *len);
@@ -487,9 +328,9 @@ void HTConstructCapabilityElement(struct rtllib_device *ieee, u8 *posHTCap,
        pCapELE->LSigTxopProtect = 0;
 
 
-       RTLLIB_DEBUG(RTLLIB_DL_HT, "TX HT cap/info ele BW=%d MaxAMSDUSize:%d "
-                    "DssCCk:%d\n", pCapELE->ChlWidth, pCapELE->MaxAMSDUSize,
-                    pCapELE->DssCCk);
+       RTLLIB_DEBUG(RTLLIB_DL_HT,
+                    "TX HT cap/info ele BW=%d MaxAMSDUSize:%d DssCCk:%d\n",
+                    pCapELE->ChlWidth, pCapELE->MaxAMSDUSize, pCapELE->DssCCk);
 
        if (IsEncrypt) {
                pCapELE->MPDUDensity    = 7;
@@ -532,8 +373,8 @@ void HTConstructInfoElement(struct rtllib_device *ieee, u8 *posHTInfo,
        struct ht_info_ele *pHTInfoEle = (struct ht_info_ele *)posHTInfo;
 
        if ((posHTInfo == NULL) || (pHTInfoEle == NULL)) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "posHTInfo or pHTInfoEle can't be "
-                            "null in HTConstructInfoElement()\n");
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "posHTInfo or pHTInfoEle can't be null in HTConstructInfoElement()\n");
                return;
        }
 
@@ -572,8 +413,8 @@ void HTConstructRT2RTAggElement(struct rtllib_device *ieee, u8 *posRT2RTAgg,
                                u8 *len)
 {
        if (posRT2RTAgg == NULL) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "posRT2RTAgg can't be null in "
-                            "HTConstructRT2RTAggElement()\n");
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "posRT2RTAgg can't be null in HTConstructRT2RTAggElement()\n");
                return;
        }
        memset(posRT2RTAgg, 0, *len);
@@ -596,8 +437,8 @@ static u8 HT_PickMCSRate(struct rtllib_device *ieee, u8 *pOperateMCS)
        u8 i;
 
        if (pOperateMCS == NULL) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "pOperateMCS can't be null"
-                            " in HT_PickMCSRate()\n");
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "pOperateMCS can't be null in HT_PickMCSRate()\n");
                return false;
        }
 
@@ -631,8 +472,8 @@ u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet,
        u8              availableMcsRate[16];
 
        if (pMCSRateSet == NULL || pMCSFilter == NULL) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "pMCSRateSet or pMCSFilter can't "
-                            "be null in HTGetHighestMCSRate()\n");
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "pMCSRateSet or pMCSFilter can't be null in HTGetHighestMCSRate()\n");
                return false;
        }
        for (i = 0; i < 16; i++)
@@ -654,7 +495,7 @@ u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet,
                                            HTMcsToDataRate(ieee, mcsRate))
                                                mcsRate = (8*i+j);
                                }
-                               bitMap = bitMap>>1;
+                               bitMap >>= 1;
                        }
                }
        }
@@ -697,8 +538,8 @@ void HTOnAssocRsp(struct rtllib_device *ieee)
        static u8 EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34};
 
        if (pHTInfo->bCurrentHTSupport == false) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "<=== HTOnAssocRsp(): "
-                            "HT_DISABLE\n");
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "<=== HTOnAssocRsp(): HT_DISABLE\n");
                return;
        }
        RTLLIB_DEBUG(RTLLIB_DL_HT, "===> HTOnAssocRsp_wq(): HT_ENABLE\n");
@@ -878,7 +719,8 @@ void HTResetSelfAndSavePeerSetting(struct rtllib_device *ieee,
 
        RTLLIB_DEBUG(RTLLIB_DL_HT, "==============>%s()\n", __func__);
        /* unmark bEnableHT flag here is the same reason why unmarked in
-        * function rtllib_softmac_new_net. WB 2008.09.10*/
+        * function rtllib_softmac_new_net. WB 2008.09.10
+        */
        if (pNetwork->bssht.bdSupportHT) {
                pHTInfo->bCurrentHTSupport = true;
                pHTInfo->ePeerHTSpecVer = pNetwork->bssht.bdHTSpecVer;
@@ -999,8 +841,8 @@ u8 HTCCheck(struct rtllib_device *ieee, u8 *pFrame)
 {
        if (ieee->pHTInfo->bCurrentHTSupport) {
                if ((IsQoSDataFrame(pFrame) && Frame_Order(pFrame)) == 1) {
-                       RTLLIB_DEBUG(RTLLIB_DL_HT, "HT CONTROL FILED "
-                                    "EXIST!!\n");
+                       RTLLIB_DEBUG(RTLLIB_DL_HT,
+                                    "HT CONTROL FILED EXIST!!\n");
                        return true;
                }
        }
index 973342b8a06da3dbe62e5f906af9b7dfc9e742f8..55ef7ec33f650f448e465e98971cd1a58d90c639 100644 (file)
@@ -19,8 +19,6 @@
 #ifndef __INC_QOS_TYPE_H
 #define __INC_QOS_TYPE_H
 
-#include "rtllib_endianfree.h"
-
 #define BIT0               0x00000001
 #define BIT1               0x00000002
 #define BIT2               0x00000004
@@ -340,18 +338,6 @@ struct sta_qos {
 };
 
 #define QBSS_LOAD_SIZE                         5
-#define GET_QBSS_LOAD_STA_COUNT(__pStart)      \
-               ReadEF2Byte(__pStart)
-#define SET_QBSS_LOAD_STA_COUNT(__pStart, __Value)     \
-               WriteEF2Byte(__pStart, __Value)
-#define GET_QBSS_LOAD_CHNL_UTILIZATION(__pStart)       \
-               ReadEF1Byte((u8 *)(__pStart) + 2)
-#define SET_QBSS_LOAD_CHNL_UTILIZATION(__pStart, __Value)      \
-               WriteEF1Byte((u8 *)(__pStart) + 2, __Value)
-#define GET_QBSS_LOAD_AVAILABLE_CAPACITY(__pStart)     \
-               ReadEF2Byte((u8 *)(__pStart) + 3)
-#define SET_QBSS_LOAD_AVAILABLE_CAPACITY(__pStart, __Value) \
-               WriteEF2Byte((u8 *)(__pStart) + 3, __Value)
 
 struct bss_qos {
        QOS_MODE bdQoSMode;
@@ -367,10 +353,6 @@ struct bss_qos {
        bool bQBssLoadValid;
 };
 
-#define sQoSCtlLng     2
-#define QOS_CTRL_LEN(_QosMode) ((_QosMode > QOS_DISABLE) ? sQoSCtlLng : 0)
-
-
 #define IsACValid(ac)          ((ac >= 0 && ac <= 7) ? true : false)
 
 
index 294847d1a90347a4eb524e706acdc7cc07e9ed07..7d77d056228d35fa3690421ac1cd37119ccf11a3 100644 (file)
@@ -58,9 +58,9 @@ static void RxPktPendingTimeout(unsigned long data)
                                        pRxTs->RxIndicateSeq =
                                              (pRxTs->RxIndicateSeq + 1) % 4096;
 
-                               RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Indicate"
-                                            " SeqNum: %d\n", __func__,
-                                            pReorderEntry->SeqNum);
+                               RTLLIB_DEBUG(RTLLIB_DL_REORDER,
+                                            "%s(): Indicate SeqNum: %d\n",
+                                            __func__, pReorderEntry->SeqNum);
                                ieee->stats_IndicateArray[index] =
                                                         pReorderEntry->prxb;
                                index++;
@@ -78,8 +78,8 @@ static void RxPktPendingTimeout(unsigned long data)
                pRxTs->RxTimeoutIndicateSeq = 0xffff;
 
                if (index > REORDER_WIN_SIZE) {
-                       RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket():"
-                                    " Rx Reorder struct buffer full!!\n");
+                       RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                                    "RxReorderIndicatePacket(): Rx Reorder struct buffer full!!\n");
                        spin_unlock_irqrestore(&(ieee->reorder_spinlock),
                                               flags);
                        return;
@@ -91,7 +91,7 @@ static void RxPktPendingTimeout(unsigned long data)
        if (bPktInBuf && (pRxTs->RxTimeoutIndicateSeq == 0xffff)) {
                pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq;
                mod_timer(&pRxTs->RxPktPendingTimer,  jiffies +
-                         MSECS(ieee->pHTInfo->RxReorderPendingTime));
+                         msecs_to_jiffies(ieee->pHTInfo->RxReorderPendingTime));
        }
        spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
 }
@@ -104,8 +104,8 @@ static void TsAddBaProcess(unsigned long data)
                                     TxTsRecord[num]);
 
        TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false);
-       RTLLIB_DEBUG(RTLLIB_DL_BA, "TsAddBaProcess(): ADDBA Req is "
-                    "started!!\n");
+       RTLLIB_DEBUG(RTLLIB_DL_BA,
+                    "TsAddBaProcess(): ADDBA Req is started!!\n");
 }
 
 static void ResetTsCommonInfo(struct ts_common_info *pTsCommonInfo)
@@ -223,7 +223,7 @@ static void AdmitTS(struct rtllib_device *ieee,
 
        if (InactTime != 0)
                mod_timer(&pTsCommonInfo->InactTimer, jiffies +
-                         MSECS(InactTime));
+                         msecs_to_jiffies(InactTime));
 }
 
 static struct ts_common_info *SearchAdmitTRStream(struct rtllib_device *ieee,
@@ -311,18 +311,24 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
           u8 *Addr, u8 TID, enum tr_select TxRxSelect, bool bAddNewTs)
 {
        u8      UP = 0;
+       union tspec_body TSpec;
+       union qos_tsinfo *pTSInfo = &TSpec.f.TSInfo;
+       struct list_head *pUnusedList;
+       struct list_head *pAddmitList;
+       enum direction_value Dir;
 
        if (is_multicast_ether_addr(Addr)) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR! get TS for Broadcast or "
-                            "Multicast\n");
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "ERR! get TS for Broadcast or Multicast\n");
                return false;
        }
        if (ieee->current_network.qos_data.supported == 0) {
                UP = 0;
        } else {
                if (!IsACValid(TID)) {
-                       RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR! in %s(), TID(%d) is "
-                                    "not valid\n", __func__, TID);
+                       RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                                    "ERR! in %s(), TID(%d) is not valid\n",
+                                    __func__, TID);
                        return false;
                }
 
@@ -347,77 +353,70 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
        }
 
        *ppTS = SearchAdmitTRStream(ieee, Addr, UP, TxRxSelect);
-       if (*ppTS != NULL) {
+       if (*ppTS != NULL)
                return true;
-       } else {
-               if (!bAddNewTs) {
-                       RTLLIB_DEBUG(RTLLIB_DL_TS, "add new TS failed"
-                                    "(tid:%d)\n", UP);
-                       return false;
-               } else {
-                       union tspec_body TSpec;
-                       union qos_tsinfo *pTSInfo = &TSpec.f.TSInfo;
-                       struct list_head *pUnusedList =
-                               (TxRxSelect == TX_DIR) ?
+
+       if (!bAddNewTs) {
+               RTLLIB_DEBUG(RTLLIB_DL_TS,
+                            "add new TS failed(tid:%d)\n", UP);
+               return false;
+       }
+
+       pUnusedList = (TxRxSelect == TX_DIR) ?
                                (&ieee->Tx_TS_Unused_List) :
                                (&ieee->Rx_TS_Unused_List);
 
-                       struct list_head *pAddmitList =
-                               (TxRxSelect == TX_DIR) ?
+       pAddmitList = (TxRxSelect == TX_DIR) ?
                                (&ieee->Tx_TS_Admit_List) :
                                (&ieee->Rx_TS_Admit_List);
 
-                       enum direction_value Dir =
-                                (ieee->iw_mode == IW_MODE_MASTER) ?
-                                ((TxRxSelect == TX_DIR) ? DIR_DOWN : DIR_UP) :
-                                ((TxRxSelect == TX_DIR) ? DIR_UP : DIR_DOWN);
-                       RTLLIB_DEBUG(RTLLIB_DL_TS, "to add Ts\n");
-                       if (!list_empty(pUnusedList)) {
-                               (*ppTS) = list_entry(pUnusedList->next,
-                                         struct ts_common_info, List);
-                               list_del_init(&(*ppTS)->List);
-                               if (TxRxSelect == TX_DIR) {
-                                       struct tx_ts_record *tmp =
-                                               container_of(*ppTS,
-                                               struct tx_ts_record,
-                                               TsCommonInfo);
-                                       ResetTxTsEntry(tmp);
-                               } else {
-                                       struct rx_ts_record *tmp =
-                                                container_of(*ppTS,
-                                                struct rx_ts_record,
-                                                TsCommonInfo);
-                                       ResetRxTsEntry(tmp);
-                               }
-
-                               RTLLIB_DEBUG(RTLLIB_DL_TS, "to init current TS"
-                                            ", UP:%d, Dir:%d, addr: %pM"
-                                            " ppTs=%p\n", UP, Dir,
-                                             Addr, *ppTS);
-                               pTSInfo->field.ucTrafficType = 0;
-                               pTSInfo->field.ucTSID = UP;
-                               pTSInfo->field.ucDirection = Dir;
-                               pTSInfo->field.ucAccessPolicy = 1;
-                               pTSInfo->field.ucAggregation = 0;
-                               pTSInfo->field.ucPSB = 0;
-                               pTSInfo->field.ucUP = UP;
-                               pTSInfo->field.ucTSInfoAckPolicy = 0;
-                               pTSInfo->field.ucSchedule = 0;
-
-                               MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0);
-                               AdmitTS(ieee, *ppTS, 0);
-                               list_add_tail(&((*ppTS)->List), pAddmitList);
-
-                               return true;
-                       } else {
-                               RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!in function "
-                                            "%s() There is not enough dir=%d"
-                                            "(0=up down=1) TS record to be "
-                                            "used!!", __func__, Dir);
-                               return false;
-                       }
+       Dir = (ieee->iw_mode == IW_MODE_MASTER) ?
+                               ((TxRxSelect == TX_DIR) ? DIR_DOWN : DIR_UP) :
+                               ((TxRxSelect == TX_DIR) ? DIR_UP : DIR_DOWN);
+
+       RTLLIB_DEBUG(RTLLIB_DL_TS, "to add Ts\n");
+       if (!list_empty(pUnusedList)) {
+               (*ppTS) = list_entry(pUnusedList->next,
+                         struct ts_common_info, List);
+               list_del_init(&(*ppTS)->List);
+               if (TxRxSelect == TX_DIR) {
+                       struct tx_ts_record *tmp =
+                               container_of(*ppTS,
+                               struct tx_ts_record,
+                               TsCommonInfo);
+                       ResetTxTsEntry(tmp);
+               } else {
+                       struct rx_ts_record *tmp =
+                                container_of(*ppTS,
+                                struct rx_ts_record,
+                                TsCommonInfo);
+                       ResetRxTsEntry(tmp);
                }
+
+               RTLLIB_DEBUG(RTLLIB_DL_TS,
+                            "to init current TS, UP:%d, Dir:%d, addr: %pM ppTs=%p\n",
+                            UP, Dir, Addr, *ppTS);
+               pTSInfo->field.ucTrafficType = 0;
+               pTSInfo->field.ucTSID = UP;
+               pTSInfo->field.ucDirection = Dir;
+               pTSInfo->field.ucAccessPolicy = 1;
+               pTSInfo->field.ucAggregation = 0;
+               pTSInfo->field.ucPSB = 0;
+               pTSInfo->field.ucUP = UP;
+               pTSInfo->field.ucTSInfoAckPolicy = 0;
+               pTSInfo->field.ucSchedule = 0;
+
+               MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0);
+               AdmitTS(ieee, *ppTS, 0);
+               list_add_tail(&((*ppTS)->List), pAddmitList);
+
+               return true;
        }
+
+       RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                    "ERR!!in function %s() There is not enough dir=%d(0=up down=1) TS record to be used!!",
+                    __func__, Dir);
+       return false;
 }
 
 static void RemoveTsEntry(struct rtllib_device *ieee, struct ts_common_info *pTs,
@@ -438,8 +437,8 @@ static void RemoveTsEntry(struct rtllib_device *ieee, struct ts_common_info *pTs
                        pRxReorderEntry = (struct rx_reorder_entry *)
                                        list_entry(pRxTS->RxPendingPktList.prev,
                                        struct rx_reorder_entry, List);
-                       RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Delete SeqNum "
-                                    "%d!\n", __func__,
+                       RTLLIB_DEBUG(RTLLIB_DL_REORDER,
+                                    "%s(): Delete SeqNum %d!\n", __func__,
                                     pRxReorderEntry->SeqNum);
                        list_del_init(&pRxReorderEntry->List);
                        {
@@ -467,7 +466,7 @@ void RemovePeerTS(struct rtllib_device *ieee, u8 *Addr)
 {
        struct ts_common_info *pTS, *pTmpTS;
 
-       printk(KERN_INFO "===========>RemovePeerTS, %pM\n", Addr);
+       netdev_info(ieee->dev, "===========>RemovePeerTS, %pM\n", Addr);
 
        list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) {
                if (memcmp(pTS->Addr, Addr, 6) == 0) {
@@ -479,7 +478,8 @@ void RemovePeerTS(struct rtllib_device *ieee, u8 *Addr)
 
        list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) {
                if (memcmp(pTS->Addr, Addr, 6) == 0) {
-                       printk(KERN_INFO "====>remove Tx_TS_admin_list\n");
+                       netdev_info(ieee->dev,
+                                   "====>remove Tx_TS_admin_list\n");
                        RemoveTsEntry(ieee, pTS, TX_DIR);
                        list_del_init(&pTS->List);
                        list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
@@ -539,13 +539,13 @@ void TsStartAddBaProcess(struct rtllib_device *ieee, struct tx_ts_record *pTxTS)
                pTxTS->bAddBaReqInProgress = true;
 
                if (pTxTS->bAddBaReqDelayed) {
-                       RTLLIB_DEBUG(RTLLIB_DL_BA, "TsStartAddBaProcess(): "
-                                    "Delayed Start ADDBA after 60 sec!!\n");
+                       RTLLIB_DEBUG(RTLLIB_DL_BA,
+                                    "TsStartAddBaProcess(): Delayed Start ADDBA after 60 sec!!\n");
                        mod_timer(&pTxTS->TsAddBaTimer, jiffies +
-                                 MSECS(TS_ADDBA_DELAY));
+                                 msecs_to_jiffies(TS_ADDBA_DELAY));
                } else {
-                       RTLLIB_DEBUG(RTLLIB_DL_BA, "TsStartAddBaProcess(): "
-                                    "Immediately Start ADDBA now!!\n");
+                       RTLLIB_DEBUG(RTLLIB_DL_BA,
+                                    "TsStartAddBaProcess(): Immediately Start ADDBA now!!\n");
                        mod_timer(&pTxTS->TsAddBaTimer, jiffies+10);
                }
        } else
index cef2dc27103f30223dd08cf4ddc770d5d158b8fd..3c8b708df5c37a975a9238874d800f90afecab38 100644 (file)
 #define IW_CUSTOM_MAX  256     /* In bytes */
 #endif
 
-#ifndef container_of
-/**
- * container_of - cast a member of a structure out to the containing structure
- *
- * @ptr:       the pointer to the member.
- * @type:       the type of the container struct this is embedded in.
- * @member:     the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({                   \
-       const typeof(((type *)0)->member)*__mptr = (ptr);    \
-       (type *)((char *)__mptr - offsetof(type, member)); })
-#endif
-
 #define skb_tail_pointer_rsl(skb) skb_tail_pointer(skb)
 
-#define EXPORT_SYMBOL_RSL(x) EXPORT_SYMBOL(x)
-
-
 #define queue_delayed_work_rsl(x, y, z) queue_delayed_work(x, y, z)
 #define INIT_DELAYED_WORK_RSL(x, y, z) INIT_DELAYED_WORK(x, y)
 
@@ -482,9 +465,6 @@ enum rt_op_mode {
 #define        IEEE_CRYPT_ALG_NAME_LEN                 16
 
 #define MAX_IE_LEN  0xff
-#define RT_ASSERT_RET(_Exp) do {} while (0)
-#define RT_ASSERT_RET_VALUE(_Exp, Ret)         \
-       do {} while (0)
 
 struct ieee_param {
        u32 cmd;
@@ -525,17 +505,17 @@ struct ieee_param {
 #define IW_QUAL_NOISE_UPDATED  0x4
 #endif
 
-#define MSECS(t) msecs_to_jiffies(t)
 #define msleep_interruptible_rsl  msleep_interruptible
 
 #define RTLLIB_DATA_LEN                2304
 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
-   6.2.1.1.2.
-
-   The figure in section 7.1.2 suggests a body size of up to 2312
-   bytes is allowed, which is a bit confusing, I suspect this
-   represents the 2304 bytes of real data, plus a possible 8 bytes of
-   WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
+ * 6.2.1.1.2.
+ *
+ * The figure in section 7.1.2 suggests a body size of up to 2312
+ * bytes is allowed, which is a bit confusing, I suspect this
+ * represents the 2304 bytes of real data, plus a possible 8 bytes of
+ * WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro)
+ */
 #define RTLLIB_1ADDR_LEN 10
 #define RTLLIB_2ADDR_LEN 16
 #define RTLLIB_3ADDR_LEN 24
@@ -711,20 +691,13 @@ do {                                                              \
 #define RTLLIB_DEBUG_DATA(level, data, datalen)        \
        do {                                                    \
                if ((rtllib_debug_level & (level)) == (level)) {        \
-                       int i;                                  \
-                       u8 *pdata = (u8 *)data;                 \
                        printk(KERN_DEBUG "rtllib: %s()\n", __func__);  \
-                       for (i = 0; i < (int)(datalen); i++)    {       \
-                               printk("%2.2x ", pdata[i]);             \
-                               if ((i+1)%16 == 0)                      \
-                                       printk("\n");   \
-                       }                               \
-                       printk("\n");                   \
+                       print_hex_dump_bytes(KERN_DEBUG, DUMP_PREFIX_NONE, \
+                                            data, datalen); \
                }                                       \
        } while (0)
 
-/*
- * To use the debug system;
+/* To use the debug system;
  *
  * If you are defining a new debug classification, simply add it to the #define
  * list here in the form of:
@@ -743,8 +716,6 @@ do {                                                                \
  * % cat /proc/net/ipw/debug_level
  *
  * you simply need to add your entry to the ipw_debug_levels array.
- *
- *
  */
 
 #define RTLLIB_DL_INFO   (1<<0)
@@ -769,8 +740,8 @@ do {                                                                \
 #define RTLLIB_DL_TRACE           (1<<29)
 #define RTLLIB_DL_DATA    (1<<30)
 #define RTLLIB_DL_ERR     (1<<31)
-#define RTLLIB_ERROR(f, a...) printk(KERN_ERR "rtllib: " f, ## a)
-#define RTLLIB_WARNING(f, a...) printk(KERN_WARNING "rtllib: " f, ## a)
+#define RTLLIB_ERROR(f, a...) pr_err("rtllib: " f, ## a)
+#define RTLLIB_WARNING(f, a...) pr_warn("rtllib: " f, ## a)
 #define RTLLIB_DEBUG_INFO(f, a...)   RTLLIB_DEBUG(RTLLIB_DL_INFO, f, ## a)
 
 #define RTLLIB_DEBUG_WX(f, a...)     RTLLIB_DEBUG(RTLLIB_DL_WX, f, ## a)
@@ -784,26 +755,6 @@ do {                                                               \
 #define RTLLIB_DEBUG_RX(f, a...)  RTLLIB_DEBUG(RTLLIB_DL_RX, f, ## a)
 #define RTLLIB_DEBUG_QOS(f, a...)  RTLLIB_DEBUG(RTLLIB_DL_QOS, f, ## a)
 
-/* Added by Annie, 2005-11-22. */
-#define MAX_STR_LEN     64
-/* I want to see ASCII 33 to 126 only. Otherwise, I print '?'. */
-#define PRINTABLE(_ch)  (_ch > '!' && _ch < '~')
-#define RTLLIB_PRINT_STR(_Comp, _TitleString, _Ptr, _Len)              \
-       if ((_Comp) & level) {                                         \
-               int          __i;                                   \
-               u8  struct buffer[MAX_STR_LEN];                         \
-               int length = (_Len < MAX_STR_LEN) ? _Len : (MAX_STR_LEN-1) ;\
-               memset(struct buffer, 0, MAX_STR_LEN);          \
-               memcpy(struct buffer, (u8 *)_Ptr, length);              \
-               for (__i = 0; __i < MAX_STR_LEN; __i++) {               \
-                       if (!PRINTABLE(struct buffer[__i]))             \
-                               struct buffer[__i] = '?';               \
-               }                                                       \
-               struct buffer[length] = '\0';                           \
-               printk(KERN_INFO "Rtl819x: ");                          \
-               printk(_TitleString);                                   \
-               printk(": %d, <%s>\n", _Len, struct buffer);            \
-       }
 #ifndef ETH_P_PAE
 #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
 #define ETH_P_IP       0x0800          /* Internet Protocol packet     */
@@ -1022,7 +973,8 @@ struct rtllib_rx_stats {
 /* IEEE 802.11 requires that STA supports concurrent reception of at least
  * three fragmented frames. This define can be increased to support more
  * concurrent frames, but it should be noted that each entry can consume about
- * 2 kB of RAM and increasing cache size will slow down frame reassembly. */
+ * 2 kB of RAM and increasing cache size will slow down frame reassembly.
+ */
 #define RTLLIB_FRAG_CACHE_LEN 4
 
 struct rtllib_frag_entry {
@@ -1100,16 +1052,15 @@ struct rtllib_security {
 } __packed;
 
 
-/*
- 802.11 data frame from AP
-      ,-------------------------------------------------------------------.
-Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
-      |------|------|---------|---------|---------|------|---------|------|
-Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  frame  |  fcs |
-      |      | tion | (BSSID) |         |       | ence |  data   |      |
-      `-------------------------------------------------------------------'
-Total: 28-2340 bytes
-*/
+/* 802.11 data frame from AP
+ *       ,-------------------------------------------------------------------.
+ * Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
+ *       |------|------|---------|---------|---------|------|---------|------|
+ * Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  frame  |  fcs |
+ *       |      | tion | (BSSID) |         |         | ence |  data   |      |
+ *       `-------------------------------------------------------------------'
+ * Total: 28-2340 bytes
+ */
 
 /* Management Frame Information Element Types */
 enum rtllib_mfie {
@@ -1147,7 +1098,8 @@ enum rtllib_mfie {
 
 /* Minimal header; can be used for passing 802.11 frames with sufficient
  * information to determine what type of underlying data type is actually
- * stored in the data. */
+ * stored in the data.
+ */
 struct rtllib_pspoll_hdr {
        __le16 frame_ctl;
        __le16 aid;
@@ -1257,7 +1209,8 @@ struct rtllib_probe_response {
        __le16 beacon_interval;
        __le16 capability;
        /* SSID, supported rates, FH params, DS params,
-        * CF params, IBSS params, TIM (if beacon), RSN */
+        * CF params, IBSS params, TIM (if beacon), RSN
+        */
        struct rtllib_info_element info_element[0];
 } __packed;
 
@@ -1332,7 +1285,8 @@ union frameqos {
 /* MAX_RATES_LENGTH needs to be 12.  The spec says 8, and many APs
  * only use 8, and then use extended rates for the remaining supported
  * rates.  Other APs, however, stick all of their supported rates on the
- * main rates information element... */
+ * main rates information element...
+ */
 #define MAX_RATES_LENGTH                 ((u8)12)
 #define MAX_RATES_EX_LENGTH           ((u8)16)
 #define MAX_NETWORK_COUNT                96
@@ -1519,22 +1473,21 @@ struct rtllib_info_element_hdr {
        u8 len;
 } __packed;
 
-/*
- * These are the data types that can make up management packets
+/* These are the data types that can make up management packets
  *
      u16 auth_algorithm;
      u16 auth_sequence;
      u16 beacon_interval;
      u16 capability;
      u8 current_ap[ETH_ALEN];
      u16 listen_interval;
      struct {
              u16 association_id:14, reserved:2;
      } __packed;
      u32 time_stamp[2];
      u16 reason;
      u16 status;
-*/
* u16 auth_algorithm;
* u16 auth_sequence;
* u16 beacon_interval;
* u16 capability;
* u8 current_ap[ETH_ALEN];
* u16 listen_interval;
* struct {
*   u16 association_id:14, reserved:2;
* } __packed;
* u32 time_stamp[2];
* u16 reason;
* u16 status;
+ */
 
 #define RTLLIB_DEFAULT_TX_ESSID "Penguin"
 #define RTLLIB_DEFAULT_BASIC_RATE 2
@@ -1670,7 +1623,6 @@ struct rtllib_network {
        struct list_head list;
 };
 
-#if 1
 enum rtllib_state {
 
        /* the card is not linked at all */
@@ -1708,17 +1660,6 @@ enum rtllib_state {
         */
        RTLLIB_LINKED_SCANNING,
 };
-#else
-enum rtllib_state {
-       RTLLIB_UNINITIALIZED = 0,
-       RTLLIB_INITIALIZED,
-       RTLLIB_ASSOCIATING,
-       RTLLIB_ASSOCIATED,
-       RTLLIB_AUTHENTICATING,
-       RTLLIB_AUTHENTICATED,
-       RTLLIB_SHUTDOWN
-};
-#endif
 
 #define DEFAULT_MAX_SCAN_AGE (15 * HZ)
 #define DEFAULT_FTS 2346
@@ -1736,11 +1677,6 @@ enum rtllib_state {
 #define RTLLIB_52GHZ_MAX_CHANNEL 165
 #define RTLLIB_52GHZ_CHANNELS (RTLLIB_52GHZ_MAX_CHANNEL - \
                                  RTLLIB_52GHZ_MIN_CHANNEL + 1)
-#ifndef eqMacAddr
-#define eqMacAddr(a, b)                                        \
-       (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] &&   \
-       (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1 : 0)
-#endif
 struct tx_pending {
        int frag;
        struct rtllib_txb *txb;
@@ -2149,14 +2085,16 @@ struct rtllib_device {
        spinlock_t wpax_suitlist_lock;
 
        int tx_headroom; /* Set to size of any additional room needed at front
-                         * of allocated Tx SKBs */
+                         * of allocated Tx SKBs
+                         */
        u32 config;
 
        /* WEP and other encryption related settings at the device level */
        int open_wep; /* Set to 1 to allow unencrypted frames */
        int auth_mode;
        int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
-                                * WEP key changes */
+                                * WEP key changes
+                                */
 
        /* If the host performs {en,de}cryption, then set to 1 */
        int host_encrypt;
@@ -2276,7 +2214,7 @@ struct rtllib_device {
        short raw_tx;
        /* used if IEEE_SOFTMAC_TX_QUEUE is set */
        short queue_stop;
-       short scanning_continue ;
+       short scanning_continue;
        short proto_started;
        short proto_stoppping;
 
@@ -2426,7 +2364,7 @@ struct rtllib_device {
        /* OK this is complementing to data_poll_hard_stop */
        void (*data_hard_resume)(struct net_device *dev);
 
-       /* ask to the driver to retune the radio .
+       /* ask to the driver to retune the radio.
         * This function can sleep. the driver should ensure
         * the radio has been switched before return.
         */
@@ -2520,7 +2458,8 @@ struct rtllib_device {
        void (*rtllib_rfkill_poll)(struct net_device *dev);
 
        /* This must be the last item so that it points to the data
-        * allocated beyond this structure by alloc_rtllib */
+        * allocated beyond this structure by alloc_rtllib
+        */
        u8 priv[0];
 };
 
@@ -2549,7 +2488,8 @@ struct rtllib_device {
 
 /* The ieee802.11 stack will manage the netif queue
  * wake/stop for the driver, taking care of 802.11
- * fragmentation. See softmac.c for details. */
+ * fragmentation. See softmac.c for details.
+ */
 #define IEEE_SOFTMAC_TX_QUEUE (1<<7)
 
 /* Uses only the softmac_data_hard_start_xmit
@@ -2586,11 +2526,9 @@ static inline int rtllib_is_empty_essid(const char *essid, int essid_len)
 
 static inline int rtllib_is_valid_mode(struct rtllib_device *ieee, int mode)
 {
-       /*
-        * It is possible for both access points and our device to support
+       /* It is possible for both access points and our device to support
         * combinations of modes, so as long as there is one valid combination
         * of ap/device supported modes, then return success
-        *
         */
        if ((mode & IEEE_A) &&
            (ieee->modulation & RTLLIB_OFDM_MODULATION) &&
@@ -2882,8 +2820,6 @@ extern 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
-extern void HTDebugHTCapability(u8 *CapIE, u8 *TitleString);
-extern void HTDebugHTInfo(u8 *InfoIE, u8 *TitleString);
 
 void HTSetConnectBwMode(struct rtllib_device *ieee,
                        enum ht_channel_width Bandwidth,
@@ -2906,11 +2842,10 @@ extern void HT_update_self_and_peer_setting(struct rtllib_device *ieee,
 extern u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet,
                              u8 *pMCSFilter);
 extern u8 MCS_FILTER_ALL[];
-extern u16 MCS_DATA_RATE[2][2][77] ;
+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 HTHalfMcsToDataRate(struct rtllib_device *ieee, u8 nMcsRate);
 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);
index 60c0cedefb86d94382f846c60ad91df173be326c..1e6ae9bead23318c79f30078fa9f295580acd880 100644 (file)
@@ -62,8 +62,9 @@ void rtllib_crypt_deinit_handler(unsigned long data)
        spin_lock_irqsave(info->lock, flags);
        rtllib_crypt_deinit_entries(info, 0);
        if (!list_empty(&info->crypt_deinit_list)) {
-               printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
-                      "deletion list\n", info->name);
+               printk(KERN_DEBUG
+                      "%s: entries remaining in delayed crypt deletion list\n",
+                      info->name);
                info->crypt_deinit_timer.expires = jiffies + HZ;
                add_timer(&info->crypt_deinit_timer);
        }
@@ -86,7 +87,8 @@ void rtllib_crypt_delayed_deinit(struct lib80211_crypt_info *info,
 
        /* must not run ops->deinit() while there may be pending encrypt or
         * decrypt operations. Use a list of delayed deinits to avoid needing
-        * locking. */
+        * locking.
+        */
 
        spin_lock_irqsave(info->lock, flags);
        list_add(&tmp->list, &info->crypt_deinit_list);
@@ -145,8 +147,8 @@ int rtllib_unregister_crypto_ops(struct lib80211_crypto_ops *ops)
        spin_unlock_irqrestore(&hcrypt->lock, flags);
 
        if (del_alg) {
-               printk(KERN_DEBUG "rtllib_crypt: unregistered algorithm "
-                      "'%s'\n", ops->name);
+               printk(KERN_DEBUG "rtllib_crypt: unregistered algorithm '%s'\n",
+                      ops->name);
                kfree(del_alg);
        }
 
@@ -237,8 +239,9 @@ void __exit rtllib_crypto_deinit(void)
                struct rtllib_crypto_alg *alg =
                        (struct rtllib_crypto_alg *) ptr;
                list_del(ptr);
-               printk(KERN_DEBUG "rtllib_crypt: unregistered algorithm "
-                      "'%s' (deinit)\n", alg->ops->name);
+               printk(KERN_DEBUG
+                      "rtllib_crypt: unregistered algorithm '%s' (deinit)\n",
+                      alg->ops->name);
                kfree(alg);
        }
 
index e177c9287b44e59284272ad5d1a7f25b502824e5..b8cf59f39a6093e6104776cc8c866064bf29456e 100644 (file)
@@ -17,8 +17,7 @@
  * more details.
  */
 
-/*
- * This file defines the interface to the rtllib crypto module.
+/* This file defines the interface to the rtllib crypto module.
  */
 #ifndef RTLLIB_CRYPT_H
 #define RTLLIB_CRYPT_H
index 01f85db98e0d2091702c8af3d6a0a38be4f1d3bc..7d486e8887f84cd8c3bf8b9538b29195999e07a2 100644 (file)
@@ -69,8 +69,7 @@ static void *rtllib_ccmp_init(int key_idx)
 
        priv->tfm = (void *)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->tfm)) {
-               pr_debug("rtllib_crypt_ccmp: could not allocate "
-                      "crypto API aes\n");
+               pr_debug("rtllib_crypt_ccmp: could not allocate crypto API aes\n");
                priv->tfm = NULL;
                goto fail;
        }
@@ -121,10 +120,7 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
        fc = le16_to_cpu(hdr->frame_ctl);
        a4_included = ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) ==
                       (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS));
-       /*
-       qc_included = ((WLAN_FC_GET_TYPE(fc) == RTLLIB_FTYPE_DATA) &&
-                      (WLAN_FC_GET_STYPE(fc) & 0x08));
-       */
+
        qc_included = ((WLAN_FC_GET_TYPE(fc) == RTLLIB_FTYPE_DATA) &&
                       (WLAN_FC_GET_STYPE(fc) & 0x80));
        aad_len = 22;
@@ -141,7 +137,8 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
         * Flag (Include authentication header, M=3 (8-octet MIC),
         *       L=1 (2-octet Dlen))
         * Nonce: 0x00 | A2 | PN
-        * Dlen */
+        * Dlen
+        */
        b0[0] = 0x59;
        b0[1] = qc;
        memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
@@ -278,23 +275,22 @@ static int rtllib_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
        keyidx = pos[3];
        if (!(keyidx & (1 << 5))) {
                if (net_ratelimit()) {
-                       pr_debug("CCMP: received packet without ExtIV"
-                              " flag from %pM\n", hdr->addr2);
+                       pr_debug("CCMP: received packet without ExtIV flag from %pM\n",
+                                hdr->addr2);
                }
                key->dot11RSNAStatsCCMPFormatErrors++;
                return -2;
        }
        keyidx >>= 6;
        if (key->key_idx != keyidx) {
-               pr_debug("CCMP: RX tkey->key_idx=%d frame "
-                      "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv);
+               pr_debug("CCMP: RX tkey->key_idx=%d frame keyidx=%d priv=%p\n",
+                        key->key_idx, keyidx, priv);
                return -6;
        }
        if (!key->key_set) {
                if (net_ratelimit()) {
-                       pr_debug("CCMP: received packet from %pM"
-                              " with keyid=%d that does not have a configured"
-                              " key\n", hdr->addr2, keyidx);
+                       pr_debug("CCMP: received packet from %pM with keyid=%d that does not have a configured key\n",
+                                hdr->addr2, keyidx);
                }
                return -3;
        }
@@ -341,8 +337,8 @@ static int rtllib_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 
                if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
                        if (net_ratelimit()) {
-                               pr_debug("CCMP: decrypt failed: STA="
-                               " %pM\n", hdr->addr2);
+                               pr_debug("CCMP: decrypt failed: STA= %pM\n",
+                                        hdr->addr2);
                        }
                        key->dot11RSNAStatsCCMPDecryptErrors++;
                        return -5;
@@ -419,9 +415,7 @@ static void rtllib_ccmp_print_stats(struct seq_file *m, void *priv)
        struct rtllib_ccmp_data *ccmp = priv;
 
        seq_printf(m,
-                  "key[%d] alg=CCMP key_set=%d "
-                  "tx_pn=%pM rx_pn=%pM "
-                  "format_errors=%d replays=%d decrypt_errors=%d\n",
+                  "key[%d] alg=CCMP key_set=%d tx_pn=%pM rx_pn=%pM format_errors=%d replays=%d decrypt_errors=%d\n",
                   ccmp->key_idx, ccmp->key_set,
                   ccmp->tx_pn, ccmp->rx_pn,
                   ccmp->dot11RSNAStatsCCMPFormatErrors,
index 78db2b6826f77c7cb62d850fbfc0cc858f58910a..656b4b359c50479098879528c8dd0d1477f5be11 100644 (file)
@@ -66,8 +66,8 @@ static void *rtllib_tkip_init(int key_idx)
        priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
                        CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->tx_tfm_arc4)) {
-               printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate "
-                               "crypto API arc4\n");
+               printk(KERN_DEBUG
+                      "rtllib_crypt_tkip: could not allocate crypto API arc4\n");
                priv->tx_tfm_arc4 = NULL;
                goto fail;
        }
@@ -75,8 +75,8 @@ static void *rtllib_tkip_init(int key_idx)
        priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
                        CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->tx_tfm_michael)) {
-               printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate "
-                               "crypto API michael_mic\n");
+               printk(KERN_DEBUG
+                      "rtllib_crypt_tkip: could not allocate crypto API michael_mic\n");
                priv->tx_tfm_michael = NULL;
                goto fail;
        }
@@ -84,8 +84,8 @@ static void *rtllib_tkip_init(int key_idx)
        priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
                        CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->rx_tfm_arc4)) {
-               printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate "
-                               "crypto API arc4\n");
+               printk(KERN_DEBUG
+                      "rtllib_crypt_tkip: could not allocate crypto API arc4\n");
                priv->rx_tfm_arc4 = NULL;
                goto fail;
        }
@@ -93,8 +93,8 @@ static void *rtllib_tkip_init(int key_idx)
        priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
                        CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->rx_tfm_michael)) {
-               printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate "
-                               "crypto API michael_mic\n");
+               printk(KERN_DEBUG
+                      "rtllib_crypt_tkip: could not allocate crypto API michael_mic\n");
                priv->rx_tfm_michael = NULL;
                goto fail;
        }
@@ -249,7 +249,8 @@ static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
                               u16 IV16)
 {
        /* Make temporary area overlap WEP seed so that the final copy can be
-        * avoided on little endian hosts. */
+        * avoided on little endian hosts.
+        */
        u16 *PPK = (u16 *) &WEPSeed[4];
 
        /* Step 1 - make copy of TTAK and bring in TSC */
@@ -276,7 +277,8 @@ static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
        PPK[5] += RotR1(PPK[4]);
 
        /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
-        * WEPSeed[0..2] is transmitted as WEP IV */
+        * WEPSeed[0..2] is transmitted as WEP IV
+        */
        WEPSeed[0] = Hi8(IV16);
        WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
        WEPSeed[2] = Lo8(IV16);
@@ -399,22 +401,24 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
        keyidx = pos[3];
        if (!(keyidx & (1 << 5))) {
                if (net_ratelimit()) {
-                       printk(KERN_DEBUG "TKIP: received packet without ExtIV"
-                              " flag from %pM\n", hdr->addr2);
+                       printk(KERN_DEBUG
+                              "TKIP: received packet without ExtIV flag from %pM\n",
+                              hdr->addr2);
                }
                return -2;
        }
        keyidx >>= 6;
        if (tkey->key_idx != keyidx) {
-               printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
-                      "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
+               printk(KERN_DEBUG
+                      "TKIP: RX tkey->key_idx=%d frame keyidx=%d priv=%p\n",
+                      tkey->key_idx, keyidx, priv);
                return -6;
        }
        if (!tkey->key_set) {
                if (net_ratelimit()) {
-                       printk(KERN_DEBUG "TKIP: received packet from %pM"
-                              " with keyid=%d that does not have a configured"
-                              " key\n", hdr->addr2, keyidx);
+                       printk(KERN_DEBUG
+                              "TKIP: received packet from %pM with keyid=%d that does not have a configured key\n",
+                              hdr->addr2, keyidx);
                }
                return -3;
        }
@@ -427,10 +431,10 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
                    (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) &&
                    tkey->initialized) {
                        if (net_ratelimit()) {
-                               printk(KERN_DEBUG "TKIP: replay detected: STA="
-                                      " %pM previous TSC %08x%04x received "
-                                     "TSC %08x%04x\n", hdr->addr2,
-                                     tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
+                               printk(KERN_DEBUG
+                                      "TKIP: replay detected: STA= %pM previous TSC %08x%04x received TSC %08x%04x\n",
+                                      hdr->addr2, tkey->rx_iv32, tkey->rx_iv16,
+                                      iv32, iv16);
                        }
                        tkey->dot11RSNAStatsTKIPReplays++;
                        return -4;
@@ -451,8 +455,8 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
                crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
                if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
                        if (net_ratelimit()) {
-                               printk(KERN_DEBUG ": TKIP: failed to decrypt "
-                                      "received packet from %pM\n",
+                               printk(KERN_DEBUG
+                                      ": TKIP: failed to decrypt received packet from %pM\n",
                                       hdr->addr2);
                        }
                        return -7;
@@ -468,12 +472,14 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
                        if (iv32 != tkey->rx_iv32) {
                                /* Previously cached Phase1 result was already
                                 * lost, so it needs to be recalculated for the
-                                * next packet. */
+                                * next packet.
+                                */
                                tkey->rx_phase1_done = 0;
                        }
                        if (net_ratelimit()) {
-                               printk(KERN_DEBUG "TKIP: ICV error detected: STA="
-                               " %pM\n", hdr->addr2);
+                               printk(KERN_DEBUG
+                                      "TKIP: ICV error detected: STA= %pM\n",
+                                      hdr->addr2);
                        }
                        tkey->dot11RSNAStatsTKIPICVErrors++;
                        return -5;
@@ -482,7 +488,8 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
        }
 
        /* Update real counters only after Michael MIC verification has
-        * completed */
+        * completed
+        */
        tkey->rx_iv32_new = iv32;
        tkey->rx_iv16_new = iv16;
 
@@ -502,7 +509,7 @@ static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr,
        struct scatterlist sg[2];
 
        if (tfm_michael == NULL) {
-               printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
+               pr_warn("michael_mic: tfm_michael == NULL\n");
                return -1;
        }
        sg_init_table(sg, 2);
@@ -557,8 +564,8 @@ static int rtllib_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv)
        hdr = (struct rtllib_hdr_4addr *) skb->data;
 
        if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
-               printk(KERN_DEBUG "Invalid packet for Michael MIC add "
-                      "(tailroom=%d hdr_len=%d skb->len=%d)\n",
+               printk(KERN_DEBUG
+                      "Invalid packet for Michael MIC add (tailroom=%d hdr_len=%d skb->len=%d)\n",
                       skb_tailroom(skb), hdr_len, skb->len);
                return -1;
        }
@@ -621,14 +628,14 @@ static int rtllib_michael_mic_verify(struct sk_buff *skb, int keyidx,
                struct rtllib_hdr_4addr *hdr;
 
                hdr = (struct rtllib_hdr_4addr *) skb->data;
-               printk(KERN_DEBUG "%s: Michael MIC verification failed for "
-                      "MSDU from %pM keyidx=%d\n",
+               printk(KERN_DEBUG
+                      "%s: Michael MIC verification failed for MSDU from %pM keyidx=%d\n",
                       skb->dev ? skb->dev->name : "N/A", hdr->addr2,
                       keyidx);
                printk(KERN_DEBUG "%d\n",
                       memcmp(mic, skb->data + skb->len - 8, 8) != 0);
                if (skb->dev) {
-                       printk(KERN_INFO "skb->dev != NULL\n");
+                       pr_info("skb->dev != NULL\n");
                        rtllib_michael_mic_failure(skb->dev, hdr, keyidx);
                }
                tkey->dot11RSNAStatsTKIPLocalMICFailures++;
@@ -636,7 +643,8 @@ static int rtllib_michael_mic_verify(struct sk_buff *skb, int keyidx,
        }
 
        /* Update TSC counters for RX now that the packet verification has
-        * completed. */
+        * completed.
+        */
        tkey->rx_iv32 = tkey->rx_iv32_new;
        tkey->rx_iv16 = tkey->rx_iv16_new;
 
@@ -717,10 +725,7 @@ static void rtllib_tkip_print_stats(struct seq_file *m, void *priv)
        struct rtllib_tkip_data *tkip = priv;
 
        seq_printf(m,
-                  "key[%d] alg=TKIP key_set=%d "
-                  "tx_pn=%02x%02x%02x%02x%02x%02x "
-                  "rx_pn=%02x%02x%02x%02x%02x%02x "
-                  "replays=%d icv_errors=%d local_mic_failures=%d\n",
+                  "key[%d] alg=TKIP key_set=%d tx_pn=%02x%02x%02x%02x%02x%02x rx_pn=%02x%02x%02x%02x%02x%02x replays=%d icv_errors=%d local_mic_failures=%d\n",
                   tkip->key_idx, tkip->key_set,
                   (tkip->tx_iv32 >> 24) & 0xff,
                   (tkip->tx_iv32 >> 16) & 0xff,
index 75e7b02a144abd3058f7545264be3f071a08ffb3..21d7eee4c9a92303b480a50c8b715b146bc618b4 100644 (file)
@@ -44,15 +44,13 @@ static void *prism2_wep_init(int keyidx)
 
        priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->tx_tfm)) {
-               pr_debug("rtllib_crypt_wep: could not allocate "
-                      "crypto API arc4\n");
+               pr_debug("rtllib_crypt_wep: could not allocate crypto API arc4\n");
                priv->tx_tfm = NULL;
                goto fail;
        }
        priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->rx_tfm)) {
-               pr_debug("rtllib_crypt_wep: could not allocate "
-                      "crypto API arc4\n");
+               pr_debug("rtllib_crypt_wep: could not allocate crypto API arc4\n");
                priv->rx_tfm = NULL;
                goto fail;
        }
@@ -108,9 +106,8 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 
        if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
            skb->len < hdr_len){
-               printk(KERN_ERR "Error!!! headroom=%d tailroom=%d skblen=%d"
-                      " hdr_len=%d\n", skb_headroom(skb), skb_tailroom(skb),
-                      skb->len, hdr_len);
+               pr_err("Error!!! headroom=%d tailroom=%d skblen=%d hdr_len=%d\n",
+                      skb_headroom(skb), skb_tailroom(skb), skb->len, hdr_len);
                return -1;
        }
        len = skb->len - hdr_len;
@@ -124,7 +121,8 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 
        /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
         * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
-        * can be used to speedup attacks, so avoid using them. */
+        * can be used to speedup attacks, so avoid using them.
+        */
        if ((wep->iv & 0xff00) == 0xff00) {
                u8 B = (wep->iv >> 16) & 0xff;
 
index 7537dae89a75ac3096970b0d506dcb35aa1e6797..119729d31c74705c0dd5ef8de04e84bb8c016f91 100644 (file)
@@ -80,9 +80,9 @@ do {                  \
 #define assert(expr) \
 do {   \
        if (!(expr)) {                            \
-               printk(KERN_INFO "Assertion failed! %s,%s,%s,line=%d\n", \
+               pr_info("Assertion failed! %s,%s,%s,line=%d\n", \
                #expr, __FILE__, __func__, __LINE__);     \
        }       \
-} while (0);
+} while (0)
 
 #endif
diff --git a/drivers/staging/rtl8192e/rtllib_endianfree.h b/drivers/staging/rtl8192e/rtllib_endianfree.h
deleted file mode 100644 (file)
index b189fa5..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-#ifndef __INC_ENDIANFREE_H
-#define __INC_ENDIANFREE_H
-
-/*
- *     Call endian free function when
- *             1. Read/write packet content.
- *             2. Before write integer to IO.
- *             3. After read integer from IO.
- */
-
-#define __MACHINE_LITTLE_ENDIAN 1234    /* LSB first: i386, vax */
-#define __MACHINE_BIG_ENDIAN    4321    /* MSB first: 68000, ibm, net, ppc */
-
-#define BYTE_ORDER __MACHINE_LITTLE_ENDIAN
-
-#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
-#define EF1Byte(_val)                  ((u8)(_val))
-#define EF2Byte(_val)                  ((u16)(_val))
-#define EF4Byte(_val)                  ((u32)(_val))
-
-#else
-#define EF1Byte(_val)                  ((u8)(_val))
-#define EF2Byte(_val)                  \
-       (((((u16)(_val))&0x00ff)<<8)|((((u16)(_val))&0xff00)>>8))
-#define EF4Byte(_val)                  \
-       (((((u32)(_val))&0x000000ff)<<24)|\
-       ((((u32)(_val))&0x0000ff00)<<8)|\
-       ((((u32)(_val))&0x00ff0000)>>8)|\
-       ((((u32)(_val))&0xff000000)>>24))
-#endif
-
-#define ReadEF1Byte(_ptr)              EF1Byte(*((u8 *)(_ptr)))
-#define ReadEF2Byte(_ptr)              EF2Byte(*((u16 *)(_ptr)))
-#define ReadEF4Byte(_ptr)              EF4Byte(*((u32 *)(_ptr)))
-
-#define WriteEF1Byte(_ptr, _val)       ((*((u8 *)(_ptr))) = EF1Byte(_val))
-#define WriteEF2Byte(_ptr, _val)       ((*((u16 *)(_ptr))) = EF2Byte(_val))
-#define WriteEF4Byte(_ptr, _val)       ((*((u32 *)(_ptr))) = EF4Byte(_val))
-#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
-#define H2N1BYTE(_val) ((u8)(_val))
-#define H2N2BYTE(_val) (((((u16)(_val))&0x00ff)<<8)|\
-                       ((((u16)(_val))&0xff00)>>8))
-#define H2N4BYTE(_val) (((((u32)(_val))&0x000000ff)<<24)|\
-                       ((((u32)(_val))&0x0000ff00)<<8) |\
-                       ((((u32)(_val))&0x00ff0000)>>8) |\
-                       ((((u32)(_val))&0xff000000)>>24))
-#else
-#define H2N1BYTE(_val)                 ((u8)(_val))
-#define H2N2BYTE(_val)                 ((u16)(_val))
-#define H2N4BYTE(_val)                 ((u32)(_val))
-#endif
-
-#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
-#define N2H1BYTE(_val) ((u8)(_val))
-#define N2H2BYTE(_val) (((((u16)(_val))&0x00ff)<<8)|\
-                       ((((u16)(_val))&0xff00)>>8))
-#define N2H4BYTE(_val) (((((u32)(_val))&0x000000ff)<<24)|\
-                       ((((u32)(_val))&0x0000ff00)<<8) |\
-                       ((((u32)(_val))&0x00ff0000)>>8) |\
-                       ((((u32)(_val))&0xff000000)>>24))
-#else
-#define N2H1BYTE(_val)                 ((u8)(_val))
-#define N2H2BYTE(_val)                 ((u16)(_val))
-#define N2H4BYTE(_val)                 ((u32)(_val))
-#endif
-
-#define BIT_LEN_MASK_32(__BitLen) (0xFFFFFFFF >> (32 - (__BitLen)))
-#define BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen)                  \
-       (BIT_LEN_MASK_32(__BitLen) << (__BitOffset))
-
-#define LE_P4BYTE_TO_HOST_4BYTE(__pStart) (EF4Byte(*((u32 *)(__pStart))))
-
-#define LE_BITS_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
-       ( \
-         (LE_P4BYTE_TO_HOST_4BYTE(__pStart) >> (__BitOffset)) \
-         & \
-         BIT_LEN_MASK_32(__BitLen) \
-       )
-
-#define LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
-       ( \
-         LE_P4BYTE_TO_HOST_4BYTE(__pStart) \
-         & \
-         (~BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen)) \
-       )
-
-#define BIT_LEN_MASK_16(__BitLen) \
-       (0xFFFF >> (16 - (__BitLen)))
-
-#define BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) \
-       (BIT_LEN_MASK_16(__BitLen) << (__BitOffset))
-
-#define LE_P2BYTE_TO_HOST_2BYTE(__pStart) \
-       (EF2Byte(*((u16 *)(__pStart))))
-
-#define LE_BITS_TO_2BYTE(__pStart, __BitOffset, __BitLen) \
-       ( \
-         (LE_P2BYTE_TO_HOST_2BYTE(__pStart) >> (__BitOffset)) \
-         & \
-         BIT_LEN_MASK_16(__BitLen) \
-       )
-
-#define BIT_LEN_MASK_8(__BitLen) \
-       (0xFF >> (8 - (__BitLen)))
-
-#define BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) \
-       (BIT_LEN_MASK_8(__BitLen) << (__BitOffset))
-
-#define LE_P1BYTE_TO_HOST_1BYTE(__pStart) \
-       (EF1Byte(*((u8 *)(__pStart))))
-
-#define LE_BITS_TO_1BYTE(__pStart, __BitOffset, __BitLen) \
-       ( \
-         (LE_P1BYTE_TO_HOST_1BYTE(__pStart) >> (__BitOffset)) \
-         & \
-         BIT_LEN_MASK_8(__BitLen) \
-       )
-
-#define        N_BYTE_ALIGMENT(__Value, __Aligment)                    \
-        ((__Aligment == 1) ? (__Value) : (((__Value + __Aligment - 1) / \
-       __Aligment) * __Aligment))
-#endif
index 0cf38091f8c51cd17123d1fe8d9e99c6608edaf1..32cc8df9d3a76a9efae7fac3491082fbf4c83e3d 100644 (file)
@@ -72,11 +72,8 @@ static inline int rtllib_networks_allocate(struct rtllib_device *ieee)
        ieee->networks = kzalloc(
                MAX_NETWORK_COUNT * sizeof(struct rtllib_network),
                GFP_KERNEL);
-       if (!ieee->networks) {
-               printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
-                      ieee->dev->name);
+       if (!ieee->networks)
                return -ENOMEM;
-       }
 
        return 0;
 }
@@ -161,10 +158,9 @@ struct net_device *alloc_rtllib(int sizeof_priv)
        rtllib_softmac_init(ieee);
 
        ieee->pHTInfo = kzalloc(sizeof(struct rt_hi_throughput), GFP_KERNEL);
-       if (ieee->pHTInfo == NULL) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc memory for HTInfo\n");
+       if (ieee->pHTInfo == NULL)
                return NULL;
-       }
+
        HTUpdateDefaultSetting(ieee);
        HTInitializeHTInfo(ieee);
        TSInitialize(ieee);
@@ -207,7 +203,9 @@ static struct proc_dir_entry *rtllib_proc;
 
 static int show_debug_level(struct seq_file *m, void *v)
 {
-       return seq_printf(m, "0x%08X\n", rtllib_debug_level);
+       seq_printf(m, "0x%08X\n", rtllib_debug_level);
+
+       return 0;
 }
 
 static ssize_t write_debug_level(struct file *file, const char __user *buffer,
index 1664040efdab916ae6fd60cd347183c4bf6d3b5d..fe3e7e1273ff82f7e70a367f0b9be22a6bd45833 100644 (file)
@@ -143,7 +143,8 @@ rtllib_frag_cache_get(struct rtllib_device *ieee,
                memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
        } else {
                /* received a fragment of a frame for which the head fragment
-                * should have already been received */
+                * should have already been received
+                */
                entry = rtllib_frag_cache_find(ieee, seq, frag, tid, hdr->addr2,
                                                  hdr->addr1);
                if (entry != NULL) {
@@ -199,7 +200,8 @@ static int rtllib_frag_cache_invalidate(struct rtllib_device *ieee,
  *
  * Responsible for handling management control frames
  *
- * Called by rtllib_rx */
+ * Called by rtllib_rx
+ */
 static inline int
 rtllib_rx_frame_mgmt(struct rtllib_device *ieee, struct sk_buff *skb,
                        struct rtllib_rx_stats *rx_stats, u16 type,
@@ -224,8 +226,9 @@ rtllib_rx_frame_mgmt(struct rtllib_device *ieee, struct sk_buff *skb,
        return 0;
 }
 
-/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
-/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation
+ * Ethernet-II snap header (RFC1042 for most EtherTypes)
+ */
 static unsigned char rfc1042_header[] = {
        0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
 };
@@ -394,10 +397,9 @@ static int is_duplicate_packet(struct rtllib_device *ieee,
                }
                if (p == &ieee->ibss_mac_hash[index]) {
                        entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
-                       if (!entry) {
-                               printk(KERN_WARNING "Cannot malloc new mac entry\n");
+                       if (!entry)
                                return 0;
-                       }
+
                        memcpy(entry->mac, mac, ETH_ALEN);
                        entry->seq_num[tid] = seq;
                        entry->frag_num[tid] = frag;
@@ -483,7 +485,8 @@ void rtllib_indicate_packets(struct rtllib_device *ieee, struct rtllib_rxb **prx
                            ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
                            memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
                                /* remove RFC1042 or Bridge-Tunnel encapsulation
-                                * and replace EtherType */
+                                * and replace EtherType
+                                */
                                skb_pull(sub_skb, SNAP_SIZE);
                                memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
                                memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
@@ -524,7 +527,9 @@ void rtllib_FlushRxTsPendingPkts(struct rtllib_device *ieee,        struct rx_ts_record
        del_timer_sync(&pTS->RxPktPendingTimer);
        while (!list_empty(&pTS->RxPendingPktList)) {
                if (RfdCnt >= REORDER_WIN_SIZE) {
-                       printk(KERN_INFO "-------------->%s() error! RfdCnt >= REORDER_WIN_SIZE\n", __func__);
+                       netdev_info(ieee->dev,
+                                   "-------------->%s() error! RfdCnt >= REORDER_WIN_SIZE\n",
+                                   __func__);
                        break;
                }
 
@@ -581,8 +586,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee,
                return;
        }
 
-       /*
-        * Sliding window manipulation. Conditions includes:
+       /* Sliding window manipulation. Conditions includes:
         * 1. Incoming SeqNum is equal to WinStart =>Window shift 1
         * 2. Incoming SeqNum is larger than the WinEnd => Window shift N
         */
@@ -597,13 +601,12 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee,
                RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum);
        }
 
-       /*
-        * Indication process.
+       /* Indication process.
         * After Packet dropping and Sliding Window shifting as above, we can
         * now just indicate the packets with the SeqNum smaller than latest
         * WinStart and struct buffer other packets.
-        */
-       /* For Rx Reorder condition:
+        *
+        * For Rx Reorder condition:
         * 1. All packets with SeqNum smaller than WinStart => Indicate
         * 2. All packets with SeqNum larger than or equal to
         *       WinStart => Buffer it.
@@ -646,8 +649,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee,
                                         pTS->RxIndicateSeq, SeqNum);
                        }
                } else {
-                       /*
-                        * Packets are dropped if there are not enough reorder
+                       /* Packets are dropped if there are not enough reorder
                         * entries. This part should be modified!! We can just
                         * indicate all the packets in struct buffer and get
                         * reorder entries.
@@ -697,7 +699,8 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee,
        }
 
        /* Handling pending timer. Set this timer to prevent from long time
-        * Rx buffering.*/
+        * Rx buffering.
+        */
        if (index > 0) {
                if (timer_pending(&pTS->RxPktPendingTimer))
                        del_timer_sync(&pTS->RxPktPendingTimer);
@@ -718,7 +721,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee,
                             __func__);
                pTS->RxTimeoutIndicateSeq = pTS->RxIndicateSeq;
                mod_timer(&pTS->RxPktPendingTimer, jiffies +
-                         MSECS(pHTInfo->RxReorderPendingTime));
+                         msecs_to_jiffies(pHTInfo->RxReorderPendingTime));
        }
        spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
 }
@@ -782,69 +785,74 @@ static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb,
                memcpy(rxb->dst, dst, ETH_ALEN);
                rxb->subframes[0]->dev = ieee->dev;
                return 1;
-       } else {
-               rxb->nr_subframes = 0;
-               memcpy(rxb->src, src, ETH_ALEN);
-               memcpy(rxb->dst, dst, ETH_ALEN);
-               while (skb->len > ETHERNET_HEADER_SIZE) {
-                       /* Offset 12 denote 2 mac address */
-                       nSubframe_Length = *((u16 *)(skb->data + 12));
-                       nSubframe_Length = (nSubframe_Length >> 8) +
-                                          (nSubframe_Length << 8);
-
-                       if (skb->len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {
-                               printk(KERN_INFO "%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\
-                                      __func__, rxb->nr_subframes);
-                               printk(KERN_INFO "%s: A-MSDU parse error!! Subframe Length: %d\n", __func__,
-                                      nSubframe_Length);
-                               printk(KERN_INFO "nRemain_Length is %d and nSubframe_Length is : %d\n", skb->len,
-                                      nSubframe_Length);
-                               printk(KERN_INFO "The Packet SeqNum is %d\n", SeqNum);
-                               return 0;
-                       }
+       }
 
-                       /* move the data point to data content */
-                       skb_pull(skb, ETHERNET_HEADER_SIZE);
+       rxb->nr_subframes = 0;
+       memcpy(rxb->src, src, ETH_ALEN);
+       memcpy(rxb->dst, dst, ETH_ALEN);
+       while (skb->len > ETHERNET_HEADER_SIZE) {
+               /* Offset 12 denote 2 mac address */
+               nSubframe_Length = *((u16 *)(skb->data + 12));
+               nSubframe_Length = (nSubframe_Length >> 8) +
+                                  (nSubframe_Length << 8);
+
+               if (skb->len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {
+                       netdev_info(ieee->dev,
+                                   "%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",
+                                   __func__, rxb->nr_subframes);
+                       netdev_info(ieee->dev,
+                                   "%s: A-MSDU parse error!! Subframe Length: %d\n",
+                                   __func__, nSubframe_Length);
+                       netdev_info(ieee->dev,
+                                   "nRemain_Length is %d and nSubframe_Length is : %d\n",
+                                   skb->len, nSubframe_Length);
+                       netdev_info(ieee->dev,
+                                   "The Packet SeqNum is %d\n",
+                                   SeqNum);
+                       return 0;
+               }
 
-                       /* altered by clark 3/30/2010
-                        * The struct buffer size of the skb indicated to upper layer
-                        * must be less than 5000, or the defraged IP datagram
-                        * in the IP layer will exceed "ipfrag_high_tresh" and be
-                        * discarded. so there must not use the function
-                        * "skb_copy" and "skb_clone" for "skb".
-                        */
+               /* move the data point to data content */
+               skb_pull(skb, ETHERNET_HEADER_SIZE);
 
-                       /* Allocate new skb for releasing to upper layer */
-                       sub_skb = dev_alloc_skb(nSubframe_Length + 12);
-                       if (!sub_skb)
-                               return 0;
-                       skb_reserve(sub_skb, 12);
-                       data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
-                       memcpy(data_ptr, skb->data, nSubframe_Length);
-
-                       sub_skb->dev = ieee->dev;
-                       rxb->subframes[rxb->nr_subframes++] = sub_skb;
-                       if (rxb->nr_subframes >= MAX_SUBFRAME_COUNT) {
-                               RTLLIB_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n");
-                               break;
-                       }
-                       skb_pull(skb, nSubframe_Length);
-
-                       if (skb->len != 0) {
-                               nPadding_Length = 4 - ((nSubframe_Length +
-                                                 ETHERNET_HEADER_SIZE) % 4);
-                               if (nPadding_Length == 4)
-                                       nPadding_Length = 0;
+               /* altered by clark 3/30/2010
+                * The struct buffer size of the skb indicated to upper layer
+                * must be less than 5000, or the defraged IP datagram
+                * in the IP layer will exceed "ipfrag_high_tresh" and be
+                * discarded. so there must not use the function
+                * "skb_copy" and "skb_clone" for "skb".
+                */
 
-                               if (skb->len < nPadding_Length)
-                                       return 0;
+               /* Allocate new skb for releasing to upper layer */
+               sub_skb = dev_alloc_skb(nSubframe_Length + 12);
+               if (!sub_skb)
+                       return 0;
+               skb_reserve(sub_skb, 12);
+               data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
+               memcpy(data_ptr, skb->data, nSubframe_Length);
 
-                               skb_pull(skb, nPadding_Length);
-                       }
+               sub_skb->dev = ieee->dev;
+               rxb->subframes[rxb->nr_subframes++] = sub_skb;
+               if (rxb->nr_subframes >= MAX_SUBFRAME_COUNT) {
+                       RTLLIB_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n");
+                       break;
                }
+               skb_pull(skb, nSubframe_Length);
 
-               return rxb->nr_subframes;
+               if (skb->len != 0) {
+                       nPadding_Length = 4 - ((nSubframe_Length +
+                                         ETHERNET_HEADER_SIZE) % 4);
+                       if (nPadding_Length == 4)
+                               nPadding_Length = 0;
+
+                       if (skb->len < nPadding_Length)
+                               return 0;
+
+                       skb_pull(skb, nPadding_Length);
+               }
        }
+
+       return rxb->nr_subframes;
 }
 
 
@@ -859,7 +867,8 @@ static size_t rtllib_rx_get_hdrlen(struct rtllib_device *ieee,
        hdrlen = rtllib_get_hdrlen(fc);
        if (HTCCheck(ieee, skb->data)) {
                if (net_ratelimit())
-                       printk(KERN_INFO "%s: find HTCControl!\n", __func__);
+                       netdev_info(ieee->dev, "%s: find HTCControl!\n",
+                                   __func__);
                hdrlen += 4;
                rx_stats->bContainHTC = true;
        }
@@ -966,7 +975,8 @@ static int rtllib_rx_data_filter(struct rtllib_device *ieee, u16 fc,
        }
 
        /* Nullfunc frames may have PS-bit set, so they must be passed to
-        * hostap_handle_sta_rx() before being dropped here. */
+        * hostap_handle_sta_rx() before being dropped here.
+        */
        if (!ieee->IntelPromiscuousModeInfo.bPromiscuousOn) {
                if (stype != RTLLIB_STYPE_DATA &&
                    stype != RTLLIB_STYPE_DATA_CFACK &&
@@ -1008,7 +1018,8 @@ static int rtllib_rx_get_crypt(struct rtllib_device *ieee, struct sk_buff *skb,
 
                *crypt = ieee->crypt_info.crypt[idx];
                /* allow NULL decrypt to indicate an station specific override
-                * for default encryption */
+                * for default encryption
+                */
                if (*crypt && ((*crypt)->ops == NULL ||
                              (*crypt)->ops->decrypt_mpdu == NULL))
                        *crypt = NULL;
@@ -1017,7 +1028,8 @@ static int rtllib_rx_get_crypt(struct rtllib_device *ieee, struct sk_buff *skb,
                        /* This seems to be triggered by some (multicast?)
                         * frames from other than current BSS, so just drop the
                         * frames silently instead of filling system log with
-                        * these reports. */
+                        * these reports.
+                        */
                        RTLLIB_DEBUG_DROP("Decryption failed (not set) (SA= %pM)\n",
                                             hdr->addr2);
                        ieee->ieee_stats.rx_discards_undecryptable++;
@@ -1049,7 +1061,7 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
 
        keyidx = rtllib_rx_frame_decrypt(ieee, skb, crypt);
        if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) && (keyidx < 0)) {
-               printk(KERN_INFO "%s: decrypt frame error\n", __func__);
+               netdev_info(ieee->dev, "%s: decrypt frame error\n", __func__);
                return -1;
        }
 
@@ -1072,19 +1084,22 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
                        flen -= hdrlen;
 
                if (frag_skb->tail + flen > frag_skb->end) {
-                       printk(KERN_WARNING "%s: host decrypted and reassembled frame did not fit skb\n",
-                              __func__);
+                       netdev_warn(ieee->dev,
+                                   "%s: host decrypted and reassembled frame did not fit skb\n",
+                                   __func__);
                        rtllib_frag_cache_invalidate(ieee, hdr);
                        return -1;
                }
 
                if (frag == 0) {
                        /* copy first fragment (including full headers) into
-                        * beginning of the fragment cache skb */
+                        * beginning of the fragment cache skb
+                        */
                        memcpy(skb_put(frag_skb, flen), skb->data, flen);
                } else {
                        /* append frame payload to the end of the fragment
-                        * cache skb */
+                        * cache skb
+                        */
                        memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
                               flen);
                }
@@ -1094,22 +1109,25 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
                if (fc & RTLLIB_FCTL_MOREFRAGS) {
                        /* more fragments expected - leave the skb in fragment
                         * cache for now; it will be delivered to upper layers
-                        * after all fragments have been received */
+                        * after all fragments have been received
+                        */
                        return -2;
                }
 
                /* this was the last fragment and the frame will be
-                * delivered, so remove skb from fragment cache */
+                * delivered, so remove skb from fragment cache
+                */
                skb = frag_skb;
                hdr = (struct rtllib_hdr_4addr *) skb->data;
                rtllib_frag_cache_invalidate(ieee, hdr);
        }
 
        /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
-        * encrypted/authenticated */
+        * encrypted/authenticated
+        */
        if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) &&
                rtllib_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) {
-               printk(KERN_INFO "%s: ==>decrypt msdu error\n", __func__);
+               netdev_info(ieee->dev, "%s: ==>decrypt msdu error\n", __func__);
                return -1;
        }
 
@@ -1119,7 +1137,8 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
                    rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
 
                        /* pass unencrypted EAPOL frames even if encryption is
-                        * configured */
+                        * configured
+                        */
                        struct eapol *eap = (struct eapol *)(skb->data +
                                24);
                        RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
@@ -1149,7 +1168,7 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
        }
 
        if (rtllib_is_eapol_frame(ieee, skb, hdrlen))
-               printk(KERN_WARNING "RX: IEEE802.1X EAPOL frame!\n");
+               netdev_warn(ieee->dev, "RX: IEEE802.1X EAPOL frame!\n");
 
        return 0;
 }
@@ -1158,7 +1177,7 @@ static void rtllib_rx_check_leave_lps(struct rtllib_device *ieee, u8 unicast, u8
 {
        if (unicast) {
 
-               if ((ieee->state == RTLLIB_LINKED)) {
+               if (ieee->state == RTLLIB_LINKED) {
                        if (((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +
                            ieee->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
                            (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)) {
@@ -1181,8 +1200,8 @@ static void rtllib_rx_indicate_pkt_legacy(struct rtllib_device *ieee,
        int i = 0;
 
        if (rxb == NULL) {
-               printk(KERN_INFO "%s: rxb is NULL!!\n", __func__);
-               return ;
+               netdev_info(dev, "%s: rxb is NULL!!\n", __func__);
+               return;
        }
 
        for (i = 0; i < rxb->nr_subframes; i++) {
@@ -1196,7 +1215,8 @@ static void rtllib_rx_indicate_pkt_legacy(struct rtllib_device *ieee,
                                ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
                                memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
                                /* remove RFC1042 or Bridge-Tunnel encapsulation and
-                                * replace EtherType */
+                                * replace EtherType
+                                */
                                skb_pull(sub_skb, SNAP_SIZE);
                                memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
                                memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
@@ -1226,7 +1246,6 @@ static void rtllib_rx_indicate_pkt_legacy(struct rtllib_device *ieee,
                }
        }
        kfree(rxb);
-       rxb = NULL;
 }
 
 static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb,
@@ -1263,7 +1282,8 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb,
        /*Filter pkt has too small length */
        hdrlen = rtllib_rx_get_hdrlen(ieee, skb, rx_stats);
        if (skb->len < hdrlen) {
-               printk(KERN_INFO "%s():ERR!!! skb->len is smaller than hdrlen\n", __func__);
+               netdev_info(dev, "%s():ERR!!! skb->len is smaller than hdrlen\n",
+                           __func__);
                goto rx_dropped;
        }
 
@@ -1345,11 +1365,9 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb,
        /* skb: hdr + (possible reassembled) full plaintext payload */
        payload = skb->data + hdrlen;
        rxb = kmalloc(sizeof(struct rtllib_rxb), GFP_ATOMIC);
-       if (rxb == NULL) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR,
-                            "%s(): kmalloc rxb error\n", __func__);
+       if (rxb == NULL)
                goto rx_dropped;
-       }
+
        /* to parse amsdu packets */
        /* qos data packets & reserved bit is 1 */
        if (parse_subframe(ieee, skb, rx_stats, rxb, src, dst) == 0) {
@@ -1390,7 +1408,8 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb,
 
        /* Returning 0 indicates to caller that we have not handled the SKB--
         * so it is still allocated and can be used again by underlying
-        * hardware as a DMA target */
+        * hardware as a DMA target
+        */
        return 0;
 }
 
@@ -1408,13 +1427,16 @@ static int rtllib_rx_Monitor(struct rtllib_device *ieee, struct sk_buff *skb,
        size_t hdrlen = rtllib_get_hdrlen(fc);
 
        if (skb->len < hdrlen) {
-               printk(KERN_INFO "%s():ERR!!! skb->len is smaller than hdrlen\n", __func__);
+               netdev_info(ieee->dev,
+                           "%s():ERR!!! skb->len is smaller than hdrlen\n",
+                           __func__);
                return 0;
        }
 
        if (HTCCheck(ieee, skb->data)) {
                if (net_ratelimit())
-                       printk(KERN_INFO "%s: Find HTCControl!\n", __func__);
+                       netdev_info(ieee->dev, "%s: Find HTCControl!\n",
+                                   __func__);
                hdrlen += 4;
        }
 
@@ -1433,18 +1455,19 @@ static int rtllib_rx_Mesh(struct rtllib_device *ieee, struct sk_buff *skb,
 
 /* All received frames are sent to this function. @skb contains the frame in
  * IEEE 802.11 format, i.e., in the format it was sent over air.
- * This function is called only as a tasklet (software IRQ). */
+ * This function is called only as a tasklet (software IRQ).
+ */
 int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
                 struct rtllib_rx_stats *rx_stats)
 {
        int ret = 0;
 
        if ((NULL == ieee) || (NULL == skb) || (NULL == rx_stats)) {
-               printk(KERN_INFO "%s: Input parameters NULL!\n", __func__);
+               pr_info("%s: Input parameters NULL!\n", __func__);
                goto rx_dropped;
        }
        if (skb->len < 10) {
-               printk(KERN_INFO "%s: SKB length < 10\n", __func__);
+               netdev_info(ieee->dev, "%s: SKB length < 10\n", __func__);
                goto rx_dropped;
        }
 
@@ -1464,7 +1487,7 @@ int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
                ret = rtllib_rx_Mesh(ieee, skb, rx_stats);
                break;
        default:
-               printk(KERN_INFO"%s: ERR iw mode!!!\n", __func__);
+               netdev_info(ieee->dev, "%s: ERR iw mode!!!\n", __func__);
                break;
        }
 
@@ -1479,10 +1502,7 @@ EXPORT_SYMBOL(rtllib_rx);
 
 static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
 
-/*
-* Make ther structure we read from the beacon packet has
-* the right values
-*/
+/* Make ther structure we read from the beacon packet has the right values */
 static int rtllib_verify_qos_info(struct rtllib_qos_information_element
                                     *info_element, int sub_type)
 {
@@ -1500,9 +1520,7 @@ static int rtllib_verify_qos_info(struct rtllib_qos_information_element
 }
 
 
-/*
- * Parse a QoS parameter element
- */
+/* Parse a QoS parameter element */
 static int rtllib_read_qos_param_element(struct rtllib_qos_parameter_info
                                            *element_param, struct rtllib_info_element
                                            *info_element)
@@ -1526,9 +1544,7 @@ static int rtllib_read_qos_param_element(struct rtllib_qos_parameter_info
        return ret;
 }
 
-/*
- * Parse a QoS information element
- */
+/* Parse a QoS information element */
 static int rtllib_read_qos_info_element(struct
                                           rtllib_qos_information_element
                                           *element_info, struct rtllib_info_element
@@ -1557,9 +1573,7 @@ static int rtllib_read_qos_info_element(struct
 }
 
 
-/*
- * Write QoS parameters from the ac parameters.
- */
+/* Write QoS parameters from the ac parameters. */
 static int rtllib_qos_convert_ac_to_parameters(struct rtllib_qos_parameter_info *param_elm,
                struct rtllib_qos_data *qos_data)
 {
@@ -1618,8 +1632,7 @@ static int rtllib_qos_convert_ac_to_parameters(struct rtllib_qos_parameter_info
        return 0;
 }
 
-/*
- * we have a generic data element which it may contain QoS information or
+/* we have a generic data element which it may contain QoS information or
  * parameters element. check the information element length to decide
  * which type to read
  */
@@ -1705,7 +1718,9 @@ static inline void rtllib_extract_country_ie(
 
                        if (!IS_COUNTRY_IE_VALID(ieee)) {
                                if (rtllib_act_scanning(ieee, false) && ieee->FirstIe_InScan)
-                                       printk(KERN_INFO "Received beacon ContryIE, SSID: <%s>\n", network->ssid);
+                                       netdev_info(ieee->dev,
+                                                   "Received beacon ContryIE, SSID: <%s>\n",
+                                                   network->ssid);
                                Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
                        }
                }
@@ -1739,7 +1754,8 @@ int rtllib_parse_info_param(struct rtllib_device *ieee,
                                             length, info_element->id);
                        /* We stop processing but don't return an error here
                         * because some misbehaviour APs break this rule. ie.
-                        * Orinoco AP1000. */
+                        * Orinoco AP1000.
+                        */
                        break;
                }
 
@@ -1908,7 +1924,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee,
                                   info_element->data[2] == 0x4c &&
                                   info_element->data[3] == 0x033) {
 
-                                               tmp_htcap_len = min(info_element->len, (u8)MAX_IE_LEN);
+                                               tmp_htcap_len = min_t(u8, info_element->len, MAX_IE_LEN);
                                                if (tmp_htcap_len != 0) {
                                                        network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
                                                        network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ?
@@ -1932,7 +1948,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee,
                                    info_element->data[1] == 0x90 &&
                                    info_element->data[2] == 0x4c &&
                                    info_element->data[3] == 0x034) {
-                                       tmp_htinfo_len = min(info_element->len, (u8)MAX_IE_LEN);
+                                       tmp_htinfo_len = min_t(u8, info_element->len, MAX_IE_LEN);
                                        if (tmp_htinfo_len != 0) {
                                                network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
                                                if (tmp_htinfo_len) {
@@ -1953,7 +1969,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee,
                                            info_element->data[1] == 0xe0 &&
                                            info_element->data[2] == 0x4c &&
                                            info_element->data[3] == 0x02) {
-                                               ht_realtek_agg_len = min(info_element->len, (u8)MAX_IE_LEN);
+                                               ht_realtek_agg_len = min_t(u8, info_element->len, MAX_IE_LEN);
                                                memcpy(ht_realtek_agg_buf, info_element->data, info_element->len);
                                        }
                                        if (ht_realtek_agg_len >= 5) {
@@ -2083,7 +2099,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee,
                case MFIE_TYPE_HT_CAP:
                        RTLLIB_DEBUG_SCAN("MFIE_TYPE_HT_CAP: %d bytes\n",
                                             info_element->len);
-                       tmp_htcap_len = min(info_element->len, (u8)MAX_IE_LEN);
+                       tmp_htcap_len = min_t(u8, info_element->len, MAX_IE_LEN);
                        if (tmp_htcap_len != 0) {
                                network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
                                network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ?
@@ -2110,7 +2126,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee,
                case MFIE_TYPE_HT_INFO:
                        RTLLIB_DEBUG_SCAN("MFIE_TYPE_HT_INFO: %d bytes\n",
                                             info_element->len);
-                       tmp_htinfo_len = min(info_element->len, (u8)MAX_IE_LEN);
+                       tmp_htinfo_len = min_t(u8, info_element->len, MAX_IE_LEN);
                        if (tmp_htinfo_len) {
                                network->bssht.bdHTSpecVer = HT_SPEC_VER_IEEE;
                                network->bssht.bdHTInfoLen = tmp_htinfo_len >
@@ -2142,8 +2158,8 @@ int rtllib_parse_info_param(struct rtllib_device *ieee,
                        }
                        break;
                case MFIE_TYPE_QOS_PARAMETER:
-                       printk(KERN_ERR
-                              "QoS Error need to parse QOS_PARAMETER IE\n");
+                       netdev_err(ieee->dev,
+                                  "QoS Error need to parse QOS_PARAMETER IE\n");
                        break;
 
                case MFIE_TYPE_COUNTRY:
@@ -2192,13 +2208,6 @@ static inline int rtllib_network_init(
        struct rtllib_network *network,
        struct rtllib_rx_stats *stats)
 {
-
-       /*
-       network->qos_data.active = 0;
-       network->qos_data.supported = 0;
-       network->qos_data.param_count = 0;
-       network->qos_data.old_param_count = 0;
-       */
        memset(&network->qos_data, 0, sizeof(struct rtllib_qos_data));
 
        /* Pull out fixed field data */
@@ -2291,7 +2300,8 @@ static inline int is_same_network(struct rtllib_network *src,
        /* A network is only a duplicate if the channel, BSSID, ESSID
         * and the capability field (in particular IBSS and BSS) all match.
         * We treat all <hidden> with the same BSSID and channel
-        * as one network */
+        * as one network
+        */
        return (((src->ssid_len == dst->ssid_len) || (!ssidbroad)) &&
                (src->channel == dst->channel) &&
                !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
@@ -2422,7 +2432,7 @@ static inline int is_beacon(__le16 fc)
 static int IsPassiveChannel(struct rtllib_device *rtllib, u8 channel)
 {
        if (MAX_CHANNEL_NUMBER < channel) {
-               printk(KERN_INFO "%s(): Invalid Channel\n", __func__);
+               netdev_info(rtllib->dev, "%s(): Invalid Channel\n", __func__);
                return 0;
        }
 
@@ -2435,7 +2445,7 @@ static int IsPassiveChannel(struct rtllib_device *rtllib, u8 channel)
 int rtllib_legal_channel(struct rtllib_device *rtllib, u8 channel)
 {
        if (MAX_CHANNEL_NUMBER < channel) {
-               printk(KERN_INFO "%s(): Invalid Channel\n", __func__);
+               netdev_info(rtllib->dev, "%s(): Invalid Channel\n", __func__);
                return 0;
        }
        if (rtllib->active_channel_map[channel] > 0)
@@ -2501,8 +2511,9 @@ static inline void rtllib_process_probe_response(
        if (WLAN_FC_GET_STYPE(le16_to_cpu(beacon->header.frame_ctl)) ==
            RTLLIB_STYPE_PROBE_RESP) {
                if (IsPassiveChannel(ieee, network->channel)) {
-                       printk(KERN_INFO "GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n",
-                              network->channel);
+                       netdev_info(ieee->dev,
+                                   "GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n",
+                                   network->channel);
                        goto free_network;
                }
        }
@@ -2512,10 +2523,12 @@ static inline void rtllib_process_probe_response(
         *
         * NOTE:  This search is definitely not optimized.  Once its doing
         *      the "right thing" we'll optimize it for efficiency if
-        *      necessary */
+        *      necessary
+        */
 
        /* Search for this entry in the list and update it if it is
-        * already there. */
+        * already there.
+        */
 
        spin_lock_irqsave(&ieee->lock, flags);
        if (is_same_network(&ieee->current_network, network,
@@ -2544,7 +2557,8 @@ static inline void rtllib_process_probe_response(
        }
 
        /* If we didn't find a match, then get a new network slot to initialize
-        * with this beacon's information */
+        * with this beacon's information
+        */
        if (&target->list == &ieee->network_list) {
                if (list_empty(&ieee->network_free_list)) {
                        /* If there are no more slots, expire the oldest */
@@ -2611,7 +2625,6 @@ static inline void rtllib_process_probe_response(
        }
 free_network:
        kfree(network);
-       return;
 }
 
 void rtllib_rx_mgt(struct rtllib_device *ieee,
index d992a754e72db17ec15061cec212e902349845d6..23b7a4c3b6993a91de02a08a46dd72e1ac43dc20 100644 (file)
@@ -68,7 +68,8 @@ static void rtllib_MFIE_Brate(struct rtllib_device *ieee, u8 **tag_p)
        }
 
        /* We may add an option for custom rates that specific HW
-        * might support */
+        * might support
+        */
        *tag_p = tag;
 }
 
@@ -89,7 +90,8 @@ static void rtllib_MFIE_Grate(struct rtllib_device *ieee, u8 **tag_p)
                *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_54MB;
        }
        /* We may add an option for custom rates that specific HW might
-        * support */
+        * support
+        */
        *tag_p = tag;
 }
 
@@ -124,7 +126,7 @@ void rtllib_TURBO_Info(struct rtllib_device *ieee, u8 **tag_p)
        *tag++ = 0x00;
 
        *tag_p = tag;
-       printk(KERN_ALERT "This is enable turbo mode IE process\n");
+       netdev_alert(ieee->dev, "This is enable turbo mode IE process\n");
 }
 
 static void enqueue_mgmt(struct rtllib_device *ieee, struct sk_buff *skb)
@@ -133,8 +135,7 @@ static void enqueue_mgmt(struct rtllib_device *ieee, struct sk_buff *skb)
 
        nh = (ieee->mgmt_queue_head + 1) % MGMT_QUEUE_NUM;
 
-/*
- * if the queue is full but we have newer frames then
+/* if the queue is full but we have newer frames then
  * just overwrites the oldest.
  *
  * if (nh == ieee->mgmt_queue_tail)
@@ -188,7 +189,7 @@ MgntQuery_TxRateExcludeCCKRates(struct rtllib_device *ieee)
 
        if (QueryRate == 0) {
                QueryRate = 12;
-               printk(KERN_INFO "No BasicRate found!!\n");
+               netdev_info(ieee->dev, "No BasicRate found!!\n");
        }
        return QueryRate;
 }
@@ -273,12 +274,14 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee)
                if (!ieee->check_nic_enough_desc(ieee->dev, tcb_desc->queue_index) ||
                    (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0) ||
                    (ieee->queue_stop)) {
-                       /* insert the skb packet to the management queue */
-                       /* as for the completion function, it does not need
+                       /* insert the skb packet to the management queue
+                        *
+                        * as for the completion function, it does not need
                         * to check it any more.
-                        * */
-                       printk(KERN_INFO "%s():insert to waitqueue, queue_index"
-                              ":%d!\n", __func__, tcb_desc->queue_index);
+                        */
+                       netdev_info(ieee->dev,
+                              "%s():insert to waitqueue, queue_index:%d!\n",
+                              __func__, tcb_desc->queue_index);
                        skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index],
                                       skb);
                } else {
@@ -401,7 +404,7 @@ static void rtllib_send_beacon(struct rtllib_device *ieee)
 
        if (ieee->beacon_txing && ieee->ieee_up)
                mod_timer(&ieee->beacon_timer, jiffies +
-                         (MSECS(ieee->current_network.beacon_interval - 5)));
+                         (msecs_to_jiffies(ieee->current_network.beacon_interval - 5)));
 }
 
 
@@ -416,40 +419,33 @@ static void rtllib_send_beacon_cb(unsigned long _ieee)
        spin_unlock_irqrestore(&ieee->beacon_lock, flags);
 }
 
-/*
- * Description:
- *           Enable network monitor mode, all rx packets will be received.
- */
+/* Enables network monitor mode, all rx packets will be received. */
 void rtllib_EnableNetMonitorMode(struct net_device *dev,
                bool bInitState)
 {
        struct rtllib_device *ieee = netdev_priv_rsl(dev);
 
-       printk(KERN_INFO "========>Enter Monitor Mode\n");
+       netdev_info(dev, "========>Enter Monitor Mode\n");
 
        ieee->AllowAllDestAddrHandler(dev, true, !bInitState);
 }
 
 
-/*
- *      Description:
- *           Disable network network monitor mode, only packets destinated to
- *           us will be received.
+/* Disables network monitor mode. Only packets destinated to
+ * us will be received.
  */
 void rtllib_DisableNetMonitorMode(struct net_device *dev,
                bool bInitState)
 {
        struct rtllib_device *ieee = netdev_priv_rsl(dev);
 
-       printk(KERN_INFO "========>Exit Monitor Mode\n");
+       netdev_info(dev, "========>Exit Monitor Mode\n");
 
        ieee->AllowAllDestAddrHandler(dev, false, !bInitState);
 }
 
 
-/*
- * Description:
- * This enables the specialized promiscuous mode required by Intel.
+/* Enables the specialized promiscuous mode required by Intel.
  * In this mode, Intel intends to hear traffics from/to other STAs in the
  * same BSS. Therefore we don't have to disable checking BSSID and we only need
  * to allow all dest. BUT: if we enable checking BSSID then we can't recv
@@ -462,7 +458,7 @@ void rtllib_EnableIntelPromiscuousMode(struct net_device *dev,
 
        struct rtllib_device *ieee = netdev_priv_rsl(dev);
 
-       printk(KERN_INFO "========>Enter Intel Promiscuous Mode\n");
+       netdev_info(dev, "========>Enter Intel Promiscuous Mode\n");
 
        ieee->AllowAllDestAddrHandler(dev, true, !bInitState);
        ieee->SetHwRegHandler(dev, HW_VAR_CECHK_BSSID,
@@ -473,10 +469,8 @@ void rtllib_EnableIntelPromiscuousMode(struct net_device *dev,
 EXPORT_SYMBOL(rtllib_EnableIntelPromiscuousMode);
 
 
-/*
- * Description:
- *           This disables the specialized promiscuous mode required by Intel.
- *           See MgntEnableIntelPromiscuousMode for detail.
+/* Disables the specialized promiscuous mode required by Intel.
+ * See MgntEnableIntelPromiscuousMode for detail.
  */
 void rtllib_DisableIntelPromiscuousMode(struct net_device *dev,
                bool bInitState)
@@ -485,7 +479,7 @@ void rtllib_DisableIntelPromiscuousMode(struct net_device *dev,
 
        struct rtllib_device *ieee = netdev_priv_rsl(dev);
 
-       printk(KERN_INFO "========>Exit Intel Promiscuous Mode\n");
+       netdev_info(dev, "========>Exit Intel Promiscuous Mode\n");
 
        ieee->AllowAllDestAddrHandler(dev, false, !bInitState);
        ieee->SetHwRegHandler(dev, HW_VAR_CECHK_BSSID,
@@ -569,7 +563,8 @@ void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
                if (ieee->state == RTLLIB_LINKED)
                        goto out;
                if (ieee->sync_scan_hurryup) {
-                       printk(KERN_INFO "============>sync_scan_hurryup out\n");
+                       netdev_info(ieee->dev,
+                                   "============>sync_scan_hurryup out\n");
                        goto out;
                }
 
@@ -614,8 +609,9 @@ static void rtllib_softmac_scan_wq(void *data)
        down(&ieee->scan_sem);
 
        if (ieee->eRFPowerState == eRfOff) {
-               printk(KERN_INFO "======>%s():rf state is eRfOff, return\n",
-                      __func__);
+               netdev_info(ieee->dev,
+                           "======>%s():rf state is eRfOff, return\n",
+                           __func__);
                goto out1;
        }
 
@@ -639,7 +635,7 @@ static void rtllib_softmac_scan_wq(void *data)
                rtllib_send_probe_requests(ieee, 0);
 
        queue_delayed_work_rsl(ieee->wq, &ieee->softmac_scan_wq,
-                              MSECS(RTLLIB_SOFTMAC_SCAN_TIME));
+                              msecs_to_jiffies(RTLLIB_SOFTMAC_SCAN_TIME));
 
        up(&ieee->scan_sem);
        return;
@@ -1238,8 +1234,8 @@ inline struct sk_buff *rtllib_association_req(struct rtllib_network *beacon,
        PMKCacheIdx = SecIsInPMKIDList(ieee, ieee->current_network.bssid);
        if (PMKCacheIdx >= 0) {
                wpa_ie_len += 18;
-               printk(KERN_INFO "[PMK cache]: WPA2 IE length: %x\n",
-                      wpa_ie_len);
+               netdev_info(ieee->dev, "[PMK cache]: WPA2 IE length: %x\n",
+                           wpa_ie_len);
        }
        len = sizeof(struct rtllib_assoc_request_frame) + 2
                + beacon->ssid_len
@@ -1418,8 +1414,9 @@ inline struct sk_buff *rtllib_association_req(struct rtllib_network *beacon,
        if (ieee->assocreq_ies)
                memcpy(ieee->assocreq_ies, ies, ieee->assocreq_ies_len);
        else {
-               printk(KERN_INFO "%s()Warning: can't alloc memory for assocreq"
-                      "_ies\n", __func__);
+               netdev_info(ieee->dev,
+                           "%s()Warning: can't alloc memory for assocreq_ies\n",
+                           __func__);
                ieee->assocreq_ies_len = 0;
        }
        return skb;
@@ -1474,7 +1471,7 @@ static void rtllib_associate_step1(struct rtllib_device *ieee, u8 *daddr)
        if (!skb)
                rtllib_associate_abort(ieee);
        else {
-               ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATING ;
+               ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATING;
                RTLLIB_DEBUG_MGMT("Sending authentication request\n");
                softmac_mgmt_xmit(skb, ieee);
                if (!timer_pending(&ieee->associate_timer)) {
@@ -1503,8 +1500,7 @@ static void rtllib_auth_challenge(struct rtllib_device *ieee, u8 *challenge, int
                *(c++) = chlen;
                memcpy(c, challenge, chlen);
 
-               RTLLIB_DEBUG_MGMT("Sending authentication challenge "
-                                 "response\n");
+               RTLLIB_DEBUG_MGMT("Sending authentication challenge response\n");
 
                rtllib_encrypt_fragment(ieee, skb,
                                        sizeof(struct rtllib_hdr_3addr));
@@ -1543,9 +1539,9 @@ static void rtllib_associate_complete_wq(void *data)
                                     associate_complete_wq);
        struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
                                        (&(ieee->PowerSaveControl));
-       printk(KERN_INFO "Associated successfully\n");
+       netdev_info(ieee->dev, "Associated successfully\n");
        if (!ieee->is_silent_reset) {
-               printk(KERN_INFO "normal associate\n");
+               netdev_info(ieee->dev, "normal associate\n");
                notify_wx_assoc_event(ieee);
        }
 
@@ -1554,20 +1550,20 @@ static void rtllib_associate_complete_wq(void *data)
        if (rtllib_is_54g(&ieee->current_network) &&
           (ieee->modulation & RTLLIB_OFDM_MODULATION)) {
                ieee->rate = 108;
-               printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
+               netdev_info(ieee->dev, "Using G rates:%d\n", ieee->rate);
        } else {
                ieee->rate = 22;
                ieee->SetWirelessMode(ieee->dev, IEEE_B);
-               printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
+               netdev_info(ieee->dev, "Using B rates:%d\n", ieee->rate);
        }
        if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
-               printk(KERN_INFO "Successfully associated, ht enabled\n");
+               netdev_info(ieee->dev, "Successfully associated, ht enabled\n");
                HTOnAssocRsp(ieee);
        } else {
-               printk(KERN_INFO "Successfully associated, ht not "
-                      "enabled(%d, %d)\n",
-                      ieee->pHTInfo->bCurrentHTSupport,
-                      ieee->pHTInfo->bEnableHT);
+               netdev_info(ieee->dev,
+                           "Successfully associated, ht not enabled(%d, %d)\n",
+                           ieee->pHTInfo->bCurrentHTSupport,
+                           ieee->pHTInfo->bEnableHT);
                memset(ieee->dot11HTOperationalRateSet, 0, 16);
        }
        ieee->LinkDetectInfo.SlotNum = 2 * (1 +
@@ -1582,7 +1578,7 @@ static void rtllib_associate_complete_wq(void *data)
        ieee->link_change(ieee->dev);
 
        if (ieee->is_silent_reset) {
-               printk(KERN_INFO "silent reset associate\n");
+               netdev_info(ieee->dev, "silent reset associate\n");
                ieee->is_silent_reset = false;
        }
 
@@ -1623,8 +1619,9 @@ static void rtllib_associate_procedure_wq(void *data)
                 ieee->current_network.channel);
        HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
        if (ieee->eRFPowerState == eRfOff) {
-               RT_TRACE(COMP_DBG, "=============>%s():Rf state is eRfOff,"
-                        " schedule ipsleave wq again,return\n", __func__);
+               RT_TRACE(COMP_DBG,
+                        "=============>%s():Rf state is eRfOff, schedule ipsleave wq again,return\n",
+                        __func__);
                if (ieee->rtllib_ips_leave_wq != NULL)
                        ieee->rtllib_ips_leave_wq(ieee->dev);
                up(&ieee->wx_sem);
@@ -1705,8 +1702,8 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee,
                   (!apset && ssidset && ssidbroad && ssidmatch) ||
                   (ieee->is_roaming && ssidset && ssidbroad && ssidmatch)) {
                        /* if the essid is hidden replace it with the
-                       * essid provided by the user.
-                       */
+                        * essid provided by the user.
+                        */
                        if (!ssidbroad) {
                                strncpy(tmp_ssid, ieee->current_network.ssid,
                                        IW_ESSID_MAX_SIZE);
@@ -1719,15 +1716,15 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee,
                                        IW_ESSID_MAX_SIZE);
                                ieee->current_network.ssid_len = tmp_ssid_len;
                        }
-                       printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, "
-                              "myHT:%d, networkHT:%d, mode:%x cur_net.flags"
-                              ":0x%x\n", ieee->current_network.ssid,
-                              ieee->current_network.channel,
-                              ieee->current_network.qos_data.supported,
-                              ieee->pHTInfo->bEnableHT,
-                              ieee->current_network.bssht.bdSupportHT,
-                              ieee->current_network.mode,
-                              ieee->current_network.flags);
+                       netdev_info(ieee->dev,
+                                   "Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d, mode:%x cur_net.flags:0x%x\n",
+                                   ieee->current_network.ssid,
+                                   ieee->current_network.channel,
+                                   ieee->current_network.qos_data.supported,
+                                   ieee->pHTInfo->bEnableHT,
+                                   ieee->current_network.bssht.bdSupportHT,
+                                   ieee->current_network.mode,
+                                   ieee->current_network.flags);
 
                        if ((rtllib_act_scanning(ieee, false)) &&
                           !(ieee->softmac_features & IEEE_SOFTMAC_SCAN))
@@ -1758,11 +1755,11 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee,
                                        (ieee->modulation & RTLLIB_OFDM_MODULATION)) {
                                        ieee->rate = 108;
                                        ieee->SetWirelessMode(ieee->dev, IEEE_G);
-                                       printk(KERN_INFO"Using G rates\n");
+                                       netdev_info(ieee->dev, "Using G rates\n");
                                } else {
                                        ieee->rate = 22;
                                        ieee->SetWirelessMode(ieee->dev, IEEE_B);
-                                       printk(KERN_INFO"Using B rates\n");
+                                       netdev_info(ieee->dev, "Using B rates\n");
                                }
                                memset(ieee->dot11HTOperationalRateSet, 0, 16);
                                ieee->state = RTLLIB_LINKED;
@@ -1965,7 +1962,7 @@ static inline void rtllib_rx_assoc_rq(struct rtllib_device *ieee,
        if (assoc_rq_parse(skb, dest) != -1)
                rtllib_resp_to_assoc_rq(ieee, dest);
 
-       printk(KERN_INFO"New client associated: %pM\n", dest);
+       netdev_info(ieee->dev, "New client associated: %pM\n", dest);
 }
 
 void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr)
@@ -2004,13 +2001,16 @@ static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time)
        timeout = ieee->current_network.beacon_interval;
        ieee->current_network.dtim_data = RTLLIB_DTIM_INVALID;
        /* there's no need to nofity AP that I find you buffered
-        * with broadcast packet */
+        * with broadcast packet
+        */
        if (dtim & (RTLLIB_DTIM_UCAST & ieee->ps))
                return 2;
 
-       if (!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
+       if (!time_after(jiffies,
+                       ieee->dev->trans_start + msecs_to_jiffies(timeout)))
                return 0;
-       if (!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
+       if (!time_after(jiffies,
+                       ieee->last_rx_ps_time + msecs_to_jiffies(timeout)))
                return 0;
        if ((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) &&
            (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
@@ -2060,7 +2060,7 @@ static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time)
                        }
 
                *time = ieee->current_network.last_dtim_sta_time
-                       + MSECS(ieee->current_network.beacon_interval *
+                       + msecs_to_jiffies(ieee->current_network.beacon_interval *
                        LPSAwakeIntvl_tmp);
        }
        }
@@ -2081,10 +2081,9 @@ static inline void rtllib_sta_ps(struct rtllib_device *ieee)
        if ((ieee->ps == RTLLIB_PS_DISABLED ||
             ieee->iw_mode != IW_MODE_INFRA ||
             ieee->state != RTLLIB_LINKED)) {
-               RT_TRACE(COMP_DBG, "=====>%s(): no need to ps,wake up!! "
-                        "ieee->ps is %d, ieee->iw_mode is %d, ieee->state"
-                        " is %d\n", __func__, ieee->ps, ieee->iw_mode,
-                         ieee->state);
+               RT_TRACE(COMP_DBG,
+                        "=====>%s(): no need to ps,wake up!! ieee->ps is %d, ieee->iw_mode is %d, ieee->state is %d\n",
+                        __func__, ieee->ps, ieee->iw_mode, ieee->state);
                spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
                rtllib_sta_wakeup(ieee, 1);
 
@@ -2199,8 +2198,8 @@ static void rtllib_process_action(struct rtllib_device *ieee, struct sk_buff *sk
        u8 category = 0;
 
        if (act == NULL) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "error to get payload of "
-                            "action frame\n");
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "error to get payload of action frame\n");
                return;
        }
 
@@ -2223,7 +2222,6 @@ static void rtllib_process_action(struct rtllib_device *ieee, struct sk_buff *sk
        default:
                break;
        }
-       return;
 }
 
 inline int rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb,
@@ -2285,16 +2283,18 @@ inline int rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb,
                                memcpy(ieee->assocresp_ies, ies,
                                       ieee->assocresp_ies_len);
                        else {
-                               printk(KERN_INFO "%s()Warning: can't alloc "
-                                      "memory for assocresp_ies\n", __func__);
+                               netdev_info(ieee->dev,
+                                           "%s()Warning: can't alloc memory for assocresp_ies\n",
+                                           __func__);
                                ieee->assocresp_ies_len = 0;
                        }
                        rtllib_associate_complete(ieee);
                } else {
                        /* aid could not been allocated */
                        ieee->softmac_stats.rx_ass_err++;
-                       printk(KERN_INFO "Association response status code 0x%x\n",
-                               errcode);
+                       netdev_info(ieee->dev,
+                                   "Association response status code 0x%x\n",
+                                   errcode);
                        RTLLIB_DEBUG_MGMT(
                                "Association response status code 0x%x\n",
                                errcode);
@@ -2308,72 +2308,71 @@ inline int rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb,
        return 0;
 }
 
-inline int rtllib_rx_auth(struct rtllib_device *ieee, struct sk_buff *skb,
-                         struct rtllib_rx_stats *rx_stats)
+static void rtllib_rx_auth_resp(struct rtllib_device *ieee, struct sk_buff *skb)
 {
        u16 errcode;
        u8 *challenge;
        int chlen = 0;
        bool bSupportNmode = true, bHalfSupportNmode = false;
 
-       if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
-               if (ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATING &&
-                   (ieee->iw_mode == IW_MODE_INFRA)) {
-                       RTLLIB_DEBUG_MGMT("Received authentication response");
+       errcode = auth_parse(skb, &challenge, &chlen);
 
-                       errcode = auth_parse(skb, &challenge, &chlen);
-                       if (0 == errcode) {
-                               if (ieee->open_wep || !challenge) {
-                                       ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATED;
-                                       ieee->softmac_stats.rx_auth_rs_ok++;
-                                       if (!(ieee->pHTInfo->IOTAction &
-                                           HT_IOT_ACT_PURE_N_MODE)) {
-                                               if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) {
-                                                       if (IsHTHalfNmodeAPs(ieee)) {
-                                                               bSupportNmode = true;
-                                                               bHalfSupportNmode = true;
-                                                       } else {
-                                                               bSupportNmode = false;
-                                                               bHalfSupportNmode = false;
-                                                       }
-                                               }
-                                       }
-                                       /* Dummy wirless mode setting to avoid
-                                        * encryption issue */
-                                       if (bSupportNmode) {
-                                               ieee->SetWirelessMode(ieee->dev,
-                                                  ieee->current_network.mode);
-                                       } else {
-                                               /*TODO*/
-                                               ieee->SetWirelessMode(ieee->dev,
-                                                                     IEEE_G);
-                                       }
-
-                                       if (ieee->current_network.mode ==
-                                           IEEE_N_24G && bHalfSupportNmode) {
-                                               printk(KERN_INFO "======>enter "
-                                                      "half N mode\n");
-                                               ieee->bHalfWirelessN24GMode =
-                                                                        true;
-                                       } else
-                                               ieee->bHalfWirelessN24GMode =
-                                                                        false;
-
-                                       rtllib_associate_step2(ieee);
+       if (errcode) {
+               ieee->softmac_stats.rx_auth_rs_err++;
+               RTLLIB_DEBUG_MGMT("Authentication respose status code 0x%x",
+                                 errcode);
+
+               netdev_info(ieee->dev,
+                           "Authentication respose status code 0x%x", errcode);
+               rtllib_associate_abort(ieee);
+               return;
+       }
+
+       if (ieee->open_wep || !challenge) {
+               ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATED;
+               ieee->softmac_stats.rx_auth_rs_ok++;
+               if (!(ieee->pHTInfo->IOTAction & HT_IOT_ACT_PURE_N_MODE)) {
+                       if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) {
+                               if (IsHTHalfNmodeAPs(ieee)) {
+                                       bSupportNmode = true;
+                                       bHalfSupportNmode = true;
                                } else {
-                                       rtllib_auth_challenge(ieee, challenge,
-                                                             chlen);
+                                       bSupportNmode = false;
+                                       bHalfSupportNmode = false;
                                }
-                       } else {
-                               ieee->softmac_stats.rx_auth_rs_err++;
-                               RTLLIB_DEBUG_MGMT("Authentication respose"
-                                                 " status code 0x%x", errcode);
-
-                               printk(KERN_INFO "Authentication respose "
-                                      "status code 0x%x", errcode);
-                               rtllib_associate_abort(ieee);
                        }
+               }
+               /* Dummy wirless mode setting to avoid encryption issue */
+               if (bSupportNmode) {
+                       ieee->SetWirelessMode(ieee->dev,
+                                             ieee->current_network.mode);
+               } else {
+                       /*TODO*/
+                       ieee->SetWirelessMode(ieee->dev, IEEE_G);
+               }
 
+               if ((ieee->current_network.mode == IEEE_N_24G) &&
+                   bHalfSupportNmode) {
+                       netdev_info(ieee->dev, "======>enter half N mode\n");
+                       ieee->bHalfWirelessN24GMode = true;
+               } else {
+                       ieee->bHalfWirelessN24GMode = false;
+               }
+               rtllib_associate_step2(ieee);
+       } else {
+               rtllib_auth_challenge(ieee, challenge,  chlen);
+       }
+}
+
+inline int rtllib_rx_auth(struct rtllib_device *ieee, struct sk_buff *skb,
+                         struct rtllib_rx_stats *rx_stats)
+{
+
+       if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
+               if (ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATING &&
+                   (ieee->iw_mode == IW_MODE_INFRA)) {
+                       RTLLIB_DEBUG_MGMT("Received authentication response");
+                       rtllib_rx_auth_resp(ieee, skb);
                } else if (ieee->iw_mode == IW_MODE_MASTER) {
                        rtllib_rx_auth_rq(ieee, skb);
                }
@@ -2389,15 +2388,15 @@ inline int rtllib_rx_deauth(struct rtllib_device *ieee, struct sk_buff *skb)
                return 0;
 
        /* FIXME for now repeat all the association procedure
-       * both for disassociation and deauthentication
-       */
+        * both for disassociation and deauthentication
+        */
        if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
            ieee->state == RTLLIB_LINKED &&
            (ieee->iw_mode == IW_MODE_INFRA)) {
-               printk(KERN_INFO "==========>received disassoc/deauth(%x) "
-                      "frame, reason code:%x\n",
-                      WLAN_FC_GET_STYPE(header->frame_ctl),
-                      ((struct rtllib_disassoc *)skb->data)->reason);
+               netdev_info(ieee->dev,
+                           "==========>received disassoc/deauth(%x) frame, reason code:%x\n",
+                           WLAN_FC_GET_STYPE(header->frame_ctl),
+                           ((struct rtllib_disassoc *)skb->data)->reason);
                ieee->state = RTLLIB_ASSOCIATING;
                ieee->softmac_stats.reassoc++;
                ieee->is_roaming = true;
@@ -2450,7 +2449,6 @@ inline int rtllib_rx_frame_softmac(struct rtllib_device *ieee,
                break;
        default:
                return -1;
-               break;
        }
        return 0;
 }
@@ -2494,16 +2492,17 @@ void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee)
                ieee->stats.multicast++;
 
        /* if xmit available, just xmit it immediately, else just insert it to
-        * the wait queue */
+        * the wait queue
+        */
        for (i = 0; i < txb->nr_frags; i++) {
                queue_len = skb_queue_len(&ieee->skb_waitQ[queue_index]);
-               if ((queue_len  != 0) ||\
+               if ((queue_len  != 0) ||
                    (!ieee->check_nic_enough_desc(ieee->dev, queue_index)) ||
                    (ieee->queue_stop)) {
-                       /* insert the skb packet to the wait queue */
-                       /* as for the completion function, it does not need
+                       /* insert the skb packet to the wait queue
+                        * as for the completion function, it does not need
                         * to check it any more.
-                        * */
+                        */
                        if (queue_len < 200)
                                skb_queue_tail(&ieee->skb_waitQ[queue_index],
                                               txb->fragments[i]);
@@ -2533,13 +2532,12 @@ static void rtllib_resume_tx(struct rtllib_device *ieee)
                if (ieee->queue_stop) {
                        ieee->tx_pending.frag = i;
                        return;
-               } else {
-
-                       ieee->softmac_data_hard_start_xmit(
-                               ieee->tx_pending.txb->fragments[i],
-                               ieee->dev, ieee->rate);
-                       ieee->stats.tx_packets++;
                }
+
+               ieee->softmac_data_hard_start_xmit(
+                       ieee->tx_pending.txb->fragments[i],
+                       ieee->dev, ieee->rate);
+               ieee->stats.tx_packets++;
        }
 
        rtllib_txb_free(ieee->tx_pending.txb);
@@ -2688,7 +2686,7 @@ static void rtllib_start_ibss_wq(void *data)
         * on the semaphore
         */
        if (!ieee->proto_started) {
-               printk(KERN_INFO "==========oh driver down return\n");
+               netdev_info(ieee->dev, "==========oh driver down return\n");
                return;
        }
        down(&ieee->wx_sem);
@@ -2724,7 +2722,7 @@ static void rtllib_start_ibss_wq(void *data)
 
        /* the network definitively is not here.. create a new cell */
        if (ieee->state == RTLLIB_NOLINK) {
-               printk(KERN_INFO "creating new IBSS cell\n");
+               netdev_info(ieee->dev, "creating new IBSS cell\n");
                ieee->current_network.channel = ieee->IbssStartChnl;
                if (!ieee->wap_set)
                        rtllib_randomize_cell(ieee);
@@ -2778,7 +2776,7 @@ static void rtllib_start_ibss_wq(void *data)
                ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
        }
 
-       printk(KERN_INFO "%s(): ieee->mode = %d\n", __func__, ieee->mode);
+       netdev_info(ieee->dev, "%s(): ieee->mode = %d\n", __func__, ieee->mode);
        if ((ieee->mode == IEEE_N_24G) || (ieee->mode == IEEE_N_5G))
                HTUseDefaultSetting(ieee);
        else
@@ -2808,7 +2806,8 @@ static void rtllib_start_ibss_wq(void *data)
 
 inline void rtllib_start_ibss(struct rtllib_device *ieee)
 {
-       queue_delayed_work_rsl(ieee->wq, &ieee->start_ibss_wq, MSECS(150));
+       queue_delayed_work_rsl(ieee->wq, &ieee->start_ibss_wq,
+                              msecs_to_jiffies(150));
 }
 
 /* this is called only in user context, with wx_sem held */
@@ -2881,18 +2880,18 @@ static void rtllib_associate_retry_wq(void *data)
                goto exit;
 
        /* until we do not set the state to RTLLIB_NOLINK
-       * there are no possibility to have someone else trying
-       * to start an association procedure (we get here with
-       * ieee->state = RTLLIB_ASSOCIATING).
-       * When we set the state to RTLLIB_NOLINK it is possible
-       * that the RX path run an attempt to associate, but
-       * both rtllib_softmac_check_all_nets and the
-       * RX path works with ieee->lock held so there are no
-       * problems. If we are still disassociated then start a scan.
-       * the lock here is necessary to ensure no one try to start
-       * an association procedure when we have just checked the
-       * state and we are going to start the scan.
-       */
+        * there are no possibility to have someone else trying
+        * to start an association procedure (we get here with
+        * ieee->state = RTLLIB_ASSOCIATING).
+        * When we set the state to RTLLIB_NOLINK it is possible
+        * that the RX path run an attempt to associate, but
+        * both rtllib_softmac_check_all_nets and the
+        * RX path works with ieee->lock held so there are no
+        * problems. If we are still disassociated then start a scan.
+        * the lock here is necessary to ensure no one try to start
+        * an association procedure when we have just checked the
+        * state and we are going to start the scan.
+        */
        ieee->beinretry = true;
        ieee->state = RTLLIB_NOLINK;
 
@@ -3180,8 +3179,9 @@ void rtllib_softmac_free(struct rtllib_device *ieee)
 static int rtllib_wpa_enable(struct rtllib_device *ieee, int value)
 {
        /* This is called when wpa_supplicant loads and closes the driver
-        * interface. */
-       printk(KERN_INFO "%s WPA\n", value ? "enabling" : "disabling");
+        * interface.
+        */
+       netdev_info(ieee->dev, "%s WPA\n", value ? "enabling" : "disabling");
        ieee->wpa_enabled = value;
        memset(ieee->ap_mac_addr, 0, 6);
        return 0;
@@ -3212,7 +3212,7 @@ static int rtllib_wpa_mlme(struct rtllib_device *ieee, int command, int reason)
                break;
 
        default:
-               printk(KERN_INFO "Unknown MLME request: %d\n", command);
+               netdev_info(ieee->dev, "Unknown MLME request: %d\n", command);
                ret = -EOPNOTSUPP;
        }
 
@@ -3343,7 +3343,7 @@ static int rtllib_wpa_set_param(struct rtllib_device *ieee, u8 name, u32 value)
                break;
 
        default:
-               printk(KERN_INFO "Unknown WPA param: %d\n", name);
+               netdev_info(ieee->dev, "Unknown WPA param: %d\n", name);
                ret = -EOPNOTSUPP;
        }
 
@@ -3369,8 +3369,8 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
        if (param_len !=
            (int) ((char *) param->u.crypt.key - (char *) param) +
            param->u.crypt.key_len) {
-               printk(KERN_INFO "Len mismatch %d, %d\n", param_len,
-                              param->u.crypt.key_len);
+               netdev_info(ieee->dev, "Len mismatch %d, %d\n", param_len,
+                           param->u.crypt.key_len);
                return -EINVAL;
        }
        if (is_broadcast_ether_addr(param->sta_addr)) {
@@ -3410,8 +3410,8 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
                ops = lib80211_get_crypto_ops(param->u.crypt.alg);
        }
        if (ops == NULL) {
-               printk(KERN_INFO "unknown crypto alg '%s'\n",
-                      param->u.crypt.alg);
+               netdev_info(ieee->dev, "unknown crypto alg '%s'\n",
+                           param->u.crypt.alg);
                param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
                ret = -EINVAL;
                goto done;
@@ -3421,12 +3421,11 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
 
                lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
 
-               new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
+               new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
                if (new_crypt == NULL) {
                        ret = -ENOMEM;
                        goto done;
                }
-               memset(new_crypt, 0, sizeof(struct lib80211_crypt_data));
                new_crypt->ops = ops;
                if (new_crypt->ops)
                        new_crypt->priv =
@@ -3446,7 +3445,7 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
            (*crypt)->ops->set_key(param->u.crypt.key,
            param->u.crypt.key_len, param->u.crypt.seq,
            (*crypt)->priv) < 0) {
-               printk(KERN_INFO "key setting failed\n");
+               netdev_info(ieee->dev, "key setting failed\n");
                param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
                ret = -EINVAL;
                goto done;
@@ -3486,12 +3485,13 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
         * generate new IEEE 802.11 authentication which may end up in looping
         * with IEEE 802.1X.  If your hardware requires a reset after WEP
         * configuration (for example... Prism2), implement the reset_port in
-        * the callbacks structures used to initialize the 802.11 stack. */
+        * the callbacks structures used to initialize the 802.11 stack.
+        */
        if (ieee->reset_on_keychange &&
            ieee->iw_mode != IW_MODE_INFRA &&
            ieee->reset_port &&
            ieee->reset_port(ieee->dev)) {
-               printk(KERN_INFO "reset_port failed\n");
+               netdev_info(ieee->dev, "reset_port failed\n");
                param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
                return -EINVAL;
        }
@@ -3634,8 +3634,8 @@ int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee, struct iw_point *p,
                break;
 
        default:
-               printk(KERN_INFO "Unknown WPA supplicant request: %d\n",
-                      param->cmd);
+               netdev_info(ieee->dev, "Unknown WPA supplicant request: %d\n",
+                           param->cmd);
                ret = -EOPNOTSUPP;
                break;
        }
@@ -3749,9 +3749,9 @@ void notify_wx_assoc_event(struct rtllib_device *ieee)
                       ETH_ALEN);
        else {
 
-               printk(KERN_INFO "%s(): Tell user space disconnected\n",
-                      __func__);
-               memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+               netdev_info(ieee->dev, "%s(): Tell user space disconnected\n",
+                           __func__);
+               eth_zero_addr(wrqu.ap_addr.sa_data);
        }
        wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
 }
index 835f3d78a16f44589719bddb7e962bae60baa359..9715a793fd3735615a9aca267fd5d120576c4fcc 100644 (file)
@@ -120,7 +120,7 @@ int rtllib_wx_get_wap(struct rtllib_device *ieee,
                ieee->state != RTLLIB_LINKED_SCANNING &&
                ieee->wap_set == 0)
 
-               memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+               eth_zero_addr(wrqu->ap_addr.sa_data);
        else
                memcpy(wrqu->ap_addr.sa_data,
                       ieee->current_network.bssid, ETH_ALEN);
@@ -527,8 +527,8 @@ int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
        else
                ieee->raw_tx = 0;
 
-       printk(KERN_INFO"raw TX is %s\n",
-             ieee->raw_tx ? "enabled" : "disabled");
+       netdev_info(ieee->dev, "raw TX is %s\n",
+                   ieee->raw_tx ? "enabled" : "disabled");
 
        if (ieee->iw_mode == IW_MODE_MONITOR) {
                if (prev == 0 && ieee->raw_tx) {
@@ -575,8 +575,9 @@ int rtllib_wx_set_power(struct rtllib_device *ieee,
        if ((!ieee->sta_wake_up) ||
            (!ieee->enter_sleep_state) ||
            (!ieee->ps_is_queue_empty)) {
-               RTLLIB_DEBUG(RTLLIB_DL_ERR, "%s(): PS mode is tried to be use "
-                            "but driver missed a callback\n\n", __func__);
+               RTLLIB_DEBUG(RTLLIB_DL_ERR,
+                            "%s(): PS mode is tried to be use but driver missed a callback\n\n",
+                            __func__);
                return -1;
        }
 
index 4f68ffe41475660f293299a613d19f8affff0771..3b159638bba2adb6d97e0146e024c2dc79d1001a 100644 (file)
 
 #include "rtllib.h"
 
-/*
-
-
-802.11 Data Frame
-
-
-802.11 frame_control for data frames - 2 bytes
-     ,-----------------------------------------------------------------------------------------.
-bits | 0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  a  |  b  |  c  |  d  |  e   |
-     |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
-val  | 0  |  0  |  0  |  1  |  x  |  0  |  0  |  0  |  1  |  0  |  x  |  x  |  x  |  x  |  x   |
-     |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
-desc | ^-ver-^  |  ^type-^  |  ^-----subtype-----^  | to  |from |more |retry| pwr |more |wep   |
-     |   |        | x=0 data,x=1 data+ack | DS  | DS  |frag |     | mgm |data |      |
-     '-----------------------------------------------------------------------------------------'
-                                                   /\
-                                                   |
-802.11 Data Frame                                 |
-          ,--------- 'ctrl' expands to >-----------'
-         |
-      ,--'---,-------------------------------------------------------------.
-Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
-      |------|------|---------|---------|---------|------|---------|------|
-Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  Frame  |  fcs |
-      |      | tion | (BSSID) |         |       | ence |  data   |      |
-      `--------------------------------------------------|      |------'
-Total: 28 non-data bytes                                `----.----'
-                                                             |
-       .- 'Frame data' expands to <---------------------------'
-       |
-       V
-      ,---------------------------------------------------.
-Bytes |  1   |  1   |    1    |    3     |  2   |  0-2304 |
-      |------|------|---------|----------|------|---------|
-Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP      |
-      | DSAP | SSAP |   |        |      | Packet  |
-      | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8|      |       |
-      `-----------------------------------------|       |
-Total: 8 non-data bytes                         `----.----'
-                                                    |
-       .- 'IP Packet' expands, if WEP enabled, to <--'
-       |
-       V
-      ,-----------------------.
-Bytes |  4  |   0-2296  |  4  |
-      |-----|-----------|-----|
-Desc. | IV  | Encrypted | ICV |
-      |     | IP Packet |     |
-      `-----------------------'
-Total: 8 non-data bytes
-
-
-802.3 Ethernet Data Frame
-
-      ,-----------------------------------------.
-Bytes |   6   |   6   |  2   |  Variable |   4  |
-      |-------|-------|------|-----------|------|
-Desc. | Dest. | Source| Type | IP Packet |  fcs |
-      |  MAC  |  MAC  |      |    |      |
-      `-----------------------------------------'
-Total: 18 non-data bytes
-
-In the event that fragmentation is required, the incoming payload is split into
-N parts of size ieee->fts.  The first fragment contains the SNAP header and the
-remaining packets are just data.
-
-If encryption is enabled, each fragment payload size is reduced by enough space
-to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
-So if you have 1500 bytes of payload with ieee->fts set to 500 without
-encryption it will take 3 frames.  With WEP it will take 4 frames as the
-payload of each frame is reduced to 492 bytes.
-
-* SKB visualization
-*
-*  ,- skb->data
-* |
-* |    ETHERNET HEADER ,-<-- PAYLOAD
-* |                       |     14 bytes from skb->data
-* |  2 bytes for Type --> ,T. |     (sizeof ethhdr)
-* |                   | | |
-* |,-Dest.--. ,--Src.---. | | |
-* |  6 bytes| | 6 bytes | | | |
-* v     | |     | | | |
-* 0     | v       1 | v | v       2
-* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
-*     ^     | ^         | ^ |
-*     |     | |         | | |
-*     |     | |         | `T' <---- 2 bytes for Type
-*     |     | |         |
-*     |     | '---SNAP--' <-------- 6 bytes for SNAP
-*     |     |
-*     `-IV--' <-------------------- 4 bytes for IV (WEP)
-*
-*      SNAP HEADER
-*
-*/
+/* 802.11 Data Frame
+ *
+ *
+ * 802.11 frame_control for data frames - 2 bytes
+ *      ,-----------------------------------------------------------------------------------------.
+ * bits | 0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  a  |  b  |  c  |  d  |  e   |
+ *      |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
+ * val  | 0  |  0  |  0  |  1  |  x  |  0  |  0  |  0  |  1  |  0  |  x  |  x  |  x  |  x  |  x   |
+ *      |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
+ * desc | ^-ver-^  |  ^type-^  |  ^-----subtype-----^  | to  |from |more |retry| pwr |more |wep   |
+ *      |          |           | x=0 data,x=1 data+ack | DS  | DS  |frag |     | mgm |data |      |
+ *      '-----------------------------------------------------------------------------------------'
+ *                                                   /\
+ *                                                   |
+ * 802.11 Data Frame                                 |
+ *          ,--------- 'ctrl' expands to >-----------'
+ *          |
+ *       ,--'---,-------------------------------------------------------------.
+ * Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
+ *       |------|------|---------|---------|---------|------|---------|------|
+ * Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  Frame  |  fcs |
+ *       |      | tion | (BSSID) |         |         | ence |  data   |      |
+ *       `--------------------------------------------------|         |------'
+ * Total: 28 non-data bytes                                 `----.----'
+ *                                                               |
+ *        .- 'Frame data' expands to <---------------------------'
+ *        |
+ *        V
+ *       ,---------------------------------------------------.
+ * Bytes |  1   |  1   |    1    |    3     |  2   |  0-2304 |
+ *       |------|------|---------|----------|------|---------|
+ * Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP      |
+ *       | DSAP | SSAP |         |          |      | Packet  |
+ *       | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8|      |         |
+ *       `-----------------------------------------|         |
+ * Total: 8 non-data bytes                         `----.----'
+ *                                                      |
+ *        .- 'IP Packet' expands, if WEP enabled, to <--'
+ *        |
+ *        V
+ *       ,-----------------------.
+ * Bytes |  4  |   0-2296  |  4  |
+ *       |-----|-----------|-----|
+ * Desc. | IV  | Encrypted | ICV |
+ *       |     | IP Packet |     |
+ *       `-----------------------'
+ * Total: 8 non-data bytes
+ *
+ *
+ * 802.3 Ethernet Data Frame
+ *
+ *       ,-----------------------------------------.
+ * Bytes |   6   |   6   |  2   |  Variable |   4  |
+ *       |-------|-------|------|-----------|------|
+ * Desc. | Dest. | Source| Type | IP Packet |  fcs |
+ *       |  MAC  |  MAC  |      |         |      |
+ *       `-----------------------------------------'
+ * Total: 18 non-data bytes
+ *
+ * In the event that fragmentation is required, the incoming payload is split into
+ * N parts of size ieee->fts.  The first fragment contains the SNAP header and the
+ * remaining packets are just data.
+ *
+ * If encryption is enabled, each fragment payload size is reduced by enough space
+ * to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
+ * So if you have 1500 bytes of payload with ieee->fts set to 500 without
+ * encryption it will take 3 frames.  With WEP it will take 4 frames as the
+ * payload of each frame is reduced to 492 bytes.
+ *
+ * SKB visualization
+ *
+ * ,- skb->data
+ * |
+ * |    ETHERNET HEADER        ,-<-- PAYLOAD
+ * |                           |     14 bytes from skb->data
+ * |  2 bytes for Type --> ,T. |     (sizeof ethhdr)
+ * |                       | | |
+ * |,-Dest.--. ,--Src.---. | | |
+ * |  6 bytes| | 6 bytes | | | |
+ * v         | |         | | | |
+ * 0         | v       1 | v | v           2
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ *     ^     | ^         | ^ |
+ *     |     | |         | | |
+ *     |     | |         | `T' <---- 2 bytes for Type
+ *     |     | |         |
+ *     |     | '---SNAP--' <-------- 6 bytes for SNAP
+ *     |     |
+ *     `-IV--' <-------------------- 4 bytes for IV (WEP)
+ *
+ *      SNAP HEADER
+ *
+ */
 
 static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
 static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
@@ -185,14 +182,17 @@ int rtllib_encrypt_fragment(struct rtllib_device *ieee, struct sk_buff *frag,
        crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
 
        if (!(crypt && crypt->ops)) {
-               printk(KERN_INFO "=========>%s(), crypt is null\n", __func__);
+               netdev_info(ieee->dev, "=========>%s(), crypt is null\n",
+                           __func__);
                return -1;
        }
        /* To encrypt, frame format is:
-        * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
+        * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes)
+        */
 
        /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
-        * call both MSDU and MPDU encryption functions from here. */
+        * call both MSDU and MPDU encryption functions from here.
+        */
        atomic_inc(&crypt->refcnt);
        res = 0;
        if (crypt->ops->encrypt_msdu)
@@ -202,8 +202,8 @@ int rtllib_encrypt_fragment(struct rtllib_device *ieee, struct sk_buff *frag,
 
        atomic_dec(&crypt->refcnt);
        if (res < 0) {
-               printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
-                      ieee->dev->name, frag->len);
+               netdev_info(ieee->dev, "%s: Encryption failed: len=%d.\n",
+                           ieee->dev->name, frag->len);
                ieee->ieee_stats.tx_discards++;
                return -1;
        }
@@ -311,7 +311,7 @@ static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee,
        if (pHTInfo->bCurrentAMPDUEnable) {
                if (!GetTs(ieee, (struct ts_common_info **)(&pTxTs), hdr->addr1,
                    skb->priority, TX_DIR, true)) {
-                       printk(KERN_INFO "%s: can't get TS\n", __func__);
+                       netdev_info(ieee->dev, "%s: can't get TS\n", __func__);
                        return;
                }
                if (pTxTs->TxAdmittedBARecord.bValid == false) {
@@ -412,6 +412,8 @@ static void rtllib_query_protectionmode(struct rtllib_device *ieee,
                                        struct cb_desc *tcb_desc,
                                        struct sk_buff *skb)
 {
+       struct rt_hi_throughput *pHTInfo;
+
        tcb_desc->bRTSSTBC                      = false;
        tcb_desc->bRTSUseShortGI                = false;
        tcb_desc->bCTSEnable                    = false;
@@ -434,50 +436,50 @@ static void rtllib_query_protectionmode(struct rtllib_device *ieee,
                        tcb_desc->rts_rate = MGN_24M;
                }
                return;
-       } else {
-               struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+       }
 
-               while (true) {
-                       if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) {
-                               tcb_desc->bCTSEnable    = true;
-                               tcb_desc->rts_rate  =   MGN_24M;
-                               tcb_desc->bRTSEnable = true;
-                               break;
-                       } else if (pHTInfo->IOTAction & (HT_IOT_ACT_FORCED_RTS |
-                                  HT_IOT_ACT_PURE_N_MODE)) {
-                               tcb_desc->bRTSEnable = true;
-                               tcb_desc->rts_rate  =   MGN_24M;
-                               break;
-                       }
-                       if (ieee->current_network.buseprotection) {
-                               tcb_desc->bRTSEnable = true;
-                               tcb_desc->bCTSEnable = true;
-                               tcb_desc->rts_rate = MGN_24M;
-                               break;
-                       }
-                       if (pHTInfo->bCurrentHTSupport  && pHTInfo->bEnableHT) {
-                               u8 HTOpMode = pHTInfo->CurrentOpMode;
-
-                               if ((pHTInfo->bCurBW40MHz && (HTOpMode == 2 ||
-                                    HTOpMode == 3)) ||
-                                    (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) {
-                                       tcb_desc->rts_rate = MGN_24M;
-                                       tcb_desc->bRTSEnable = true;
-                                       break;
-                               }
-                       }
-                       if (skb->len > ieee->rts) {
+       pHTInfo = ieee->pHTInfo;
+
+       while (true) {
+               if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) {
+                       tcb_desc->bCTSEnable    = true;
+                       tcb_desc->rts_rate  =   MGN_24M;
+                       tcb_desc->bRTSEnable = true;
+                       break;
+               } else if (pHTInfo->IOTAction & (HT_IOT_ACT_FORCED_RTS |
+                          HT_IOT_ACT_PURE_N_MODE)) {
+                       tcb_desc->bRTSEnable = true;
+                       tcb_desc->rts_rate  =   MGN_24M;
+                       break;
+               }
+               if (ieee->current_network.buseprotection) {
+                       tcb_desc->bRTSEnable = true;
+                       tcb_desc->bCTSEnable = true;
+                       tcb_desc->rts_rate = MGN_24M;
+                       break;
+               }
+               if (pHTInfo->bCurrentHTSupport  && pHTInfo->bEnableHT) {
+                       u8 HTOpMode = pHTInfo->CurrentOpMode;
+
+                       if ((pHTInfo->bCurBW40MHz && (HTOpMode == 2 ||
+                            HTOpMode == 3)) ||
+                            (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) {
                                tcb_desc->rts_rate = MGN_24M;
                                tcb_desc->bRTSEnable = true;
                                break;
                        }
-                       if (tcb_desc->bAMPDUEnable) {
-                               tcb_desc->rts_rate = MGN_24M;
-                               tcb_desc->bRTSEnable = false;
-                               break;
-                       }
-                       goto NO_PROTECTION;
                }
+               if (skb->len > ieee->rts) {
+                       tcb_desc->rts_rate = MGN_24M;
+                       tcb_desc->bRTSEnable = true;
+                       break;
+               }
+               if (tcb_desc->bAMPDUEnable) {
+                       tcb_desc->rts_rate = MGN_24M;
+                       tcb_desc->bRTSEnable = false;
+                       break;
+               }
+               goto NO_PROTECTION;
        }
        if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
                tcb_desc->bUseShortPreamble = true;
@@ -549,6 +551,17 @@ static int wme_downgrade_ac(struct sk_buff *skb)
        }
 }
 
+static u8 rtllib_current_rate(struct rtllib_device *ieee)
+{
+       if (ieee->mode & IEEE_MODE_MASK)
+               return ieee->rate;
+
+       if (ieee->HTCurrentOperaRate)
+               return ieee->HTCurrentOperaRate;
+       else
+               return ieee->rate & 0x7F;
+}
+
 int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
 {
        struct rtllib_device *ieee = (struct rtllib_device *)
@@ -577,21 +590,21 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
        spin_lock_irqsave(&ieee->lock, flags);
 
        /* If there is no driver handler to take the TXB, don't bother
-        * creating it... */
+        * creating it...
+        */
        if ((!ieee->hard_start_xmit && !(ieee->softmac_features &
           IEEE_SOFTMAC_TX_QUEUE)) ||
           ((!ieee->softmac_data_hard_start_xmit &&
           (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
-               printk(KERN_WARNING "%s: No xmit handler.\n",
-                      ieee->dev->name);
+               netdev_warn(ieee->dev, "No xmit handler.\n");
                goto success;
        }
 
 
        if (likely(ieee->raw_tx == 0)) {
                if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
-                       printk(KERN_WARNING "%s: skb too small (%d).\n",
-                       ieee->dev->name, skb->len);
+                       netdev_warn(ieee->dev, "skb too small (%d).\n",
+                                   skb->len);
                        goto success;
                }
                /* Save source and destination addresses */
@@ -604,9 +617,8 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
                if (ieee->iw_mode == IW_MODE_MONITOR) {
                        txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
                        if (unlikely(!txb)) {
-                               printk(KERN_WARNING "%s: Could not allocate "
-                                      "TXB\n",
-                               ieee->dev->name);
+                               netdev_warn(ieee->dev,
+                                           "Could not allocate TXB\n");
                                goto failed;
                        }
 
@@ -636,8 +648,8 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
                                        }
                                }
                        } else if (ETH_P_ARP == ether_type) {
-                               printk(KERN_INFO "=================>DHCP "
-                                      "Protocol start tx ARP pkt!!\n");
+                               netdev_info(ieee->dev,
+                                           "=================>DHCP Protocol start tx ARP pkt!!\n");
                                bdhcp = true;
                                ieee->LPSDelayCnt =
                                         ieee->current_network.tim.tim_count;
@@ -680,7 +692,8 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
                if (ieee->iw_mode == IW_MODE_INFRA) {
                        fc |= RTLLIB_FCTL_TODS;
                        /* To DS: Addr1 = BSSID, Addr2 = SA,
-                       Addr3 = DA */
+                        * Addr3 = DA
+                        */
                        memcpy(&header.addr1, ieee->current_network.bssid,
                               ETH_ALEN);
                        memcpy(&header.addr2, &src, ETH_ALEN);
@@ -691,7 +704,8 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
                                memcpy(&header.addr3, &dest, ETH_ALEN);
                } else if (ieee->iw_mode == IW_MODE_ADHOC) {
                        /* not From/To DS: Addr1 = DA, Addr2 = SA,
-                       Addr3 = BSSID */
+                        * Addr3 = BSSID
+                        */
                        memcpy(&header.addr1, dest, ETH_ALEN);
                        memcpy(&header.addr2, src, ETH_ALEN);
                        memcpy(&header.addr3, ieee->current_network.bssid,
@@ -703,7 +717,8 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
                header.frame_ctl = cpu_to_le16(fc);
 
                /* Determine fragmentation size based on destination (multicast
-               * and broadcast are not fragmented) */
+                * and broadcast are not fragmented)
+                */
                if (bIsMulticast) {
                        frag_size = MAX_FRAG_THRESHOLD;
                        qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
@@ -717,10 +732,11 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
 
                /* in case we are a client verify acm is not set for this ac */
                while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) {
-                       printk(KERN_INFO "skb->priority = %x\n", skb->priority);
+                       netdev_info(ieee->dev, "skb->priority = %x\n",
+                                   skb->priority);
                        if (wme_downgrade_ac(skb))
                                break;
-                       printk(KERN_INFO "converted skb->priority = %x\n",
+                       netdev_info(ieee->dev, "converted skb->priority = %x\n",
                               skb->priority);
                 }
                        qos_ctl |= skb->priority;
@@ -731,14 +747,16 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
                /* Determine amount of payload per fragment.  Regardless of if
                 * this stack is providing the full 802.11 header, one will
                 * eventually be affixed to this fragment -- so we must account
-                * for it when determining the amount of payload space. */
+                * for it when determining the amount of payload space.
+                */
                bytes_per_frag = frag_size - hdr_len;
                if (ieee->config &
                   (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
                        bytes_per_frag -= RTLLIB_FCS_LEN;
 
                /* Each fragment may need to have room for encrypting
-                * pre/postfix */
+                * pre/postfix
+                */
                if (encrypt) {
                        bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
                                crypt->ops->extra_mpdu_postfix_len +
@@ -746,7 +764,8 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
                                crypt->ops->extra_msdu_postfix_len;
                }
                /* Number of fragments is the total bytes_per_frag /
-               * payload_per_fragment */
+                * payload_per_fragment
+                */
                nr_frags = bytes / bytes_per_frag;
                bytes_last_frag = bytes % bytes_per_frag;
                if (bytes_last_frag)
@@ -756,12 +775,12 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
 
                /* When we allocate the TXB we allocate enough space for the
                 * reserve and full fragment bytes (bytes_per_frag doesn't
-                * include prefix, postfix, header, FCS, etc.) */
+                * include prefix, postfix, header, FCS, etc.)
+                */
                txb = rtllib_alloc_txb(nr_frags, frag_size +
                                       ieee->tx_headroom, GFP_ATOMIC);
                if (unlikely(!txb)) {
-                       printk(KERN_WARNING "%s: Could not allocate TXB\n",
-                       ieee->dev->name);
+                       netdev_warn(ieee->dev, "Could not allocate TXB\n");
                        goto failed;
                }
                txb->encrypted = encrypt;
@@ -801,7 +820,8 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
                        memcpy(frag_hdr, &header, hdr_len);
 
                        /* If this is not the last fragment, then add the
-                        * MOREFRAGS bit to the frame control */
+                        * MOREFRAGS bit to the frame control
+                        */
                        if (i != nr_frags - 1) {
                                frag_hdr->frame_ctl = cpu_to_le16(
                                        fc | RTLLIB_FCTL_MOREFRAGS);
@@ -836,7 +856,8 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
 
                        /* Encryption routine will move the header forward in
                         * order to insert the IV between the header and the
-                        * payload */
+                        * payload
+                        */
                        if (encrypt)
                                rtllib_encrypt_fragment(ieee, skb_frag,
                                                        hdr_len);
@@ -858,15 +879,14 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
                }
        } else {
                if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) {
-                       printk(KERN_WARNING "%s: skb too small (%d).\n",
-                       ieee->dev->name, skb->len);
+                       netdev_warn(ieee->dev, "skb too small (%d).\n",
+                                   skb->len);
                        goto success;
                }
 
                txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
                if (!txb) {
-                       printk(KERN_WARNING "%s: Could not allocate TXB\n",
-                       ieee->dev->name);
+                       netdev_warn(ieee->dev, "Could not allocate TXB\n");
                        goto failed;
                }
 
@@ -906,8 +926,7 @@ int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
                        if (tcb_desc->bMulticast ||  tcb_desc->bBroadcast)
                                tcb_desc->data_rate = ieee->basic_rate;
                        else
-                               tcb_desc->data_rate = CURRENT_RATE(ieee->mode,
-                                       ieee->rate, ieee->HTCurrentOperaRate);
+                               tcb_desc->data_rate = rtllib_current_rate(ieee);
 
                        if (bdhcp) {
                                if (ieee->pHTInfo->IOTAction &
index 9e0f975c152f13eaf19a9094067e370f3670c5b6..6234aae5b069ea4715cce087e86634586f9041d8 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/wireless.h>
 #include <linux/kmod.h>
 #include <linux/module.h>
-
+#include <linux/etherdevice.h>
 #include "rtllib.h"
 struct modes_unit {
        char *mode_string;
@@ -65,7 +65,7 @@ static inline char *rtl819x_translate_scan(struct rtllib_device *ieee,
        /* First entry *MUST* be the AP MAC address */
        iwe.cmd = SIOCGIWAP;
        iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-       memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
+       ether_addr_copy(iwe.u.ap_addr.sa_data, network->bssid);
        start = iwe_stream_add_event_rsl(info, start, stop,
                                         &iwe, IW_EV_ADDR_LEN);
        /* Remaining entries will be displayed in the order we provide them */
@@ -74,7 +74,7 @@ static inline char *rtl819x_translate_scan(struct rtllib_device *ieee,
        iwe.cmd = SIOCGIWESSID;
        iwe.u.data.flags = 1;
        if (network->ssid_len > 0) {
-               iwe.u.data.length = min(network->ssid_len, (u8)32);
+               iwe.u.data.length = min_t(u8, network->ssid_len, 32);
                start = iwe_stream_add_point_rsl(info, start, stop, &iwe,
                                                 network->ssid);
        } else if (network->hidden_ssid_len == 0) {
@@ -82,7 +82,7 @@ static inline char *rtl819x_translate_scan(struct rtllib_device *ieee,
                start = iwe_stream_add_point_rsl(info, start, stop,
                                                 &iwe, "<hidden>");
        } else {
-               iwe.u.data.length = min(network->hidden_ssid_len, (u8)32);
+               iwe.u.data.length = min_t(u8, network->hidden_ssid_len, 32);
                start = iwe_stream_add_point_rsl(info, start, stop, &iwe,
                                                 network->hidden_ssid);
        }
@@ -113,8 +113,6 @@ static inline char *rtl819x_translate_scan(struct rtllib_device *ieee,
 
        /* Add frequency/channel */
        iwe.cmd = SIOCGIWFREQ;
-/*     iwe.u.freq.m = rtllib_frequency(network->channel, network->mode);
-       iwe.u.freq.e = 3; */
        iwe.u.freq.m = network->channel;
        iwe.u.freq.e = 0;
        iwe.u.freq.i = 0;
@@ -241,7 +239,8 @@ static inline char *rtl819x_translate_scan(struct rtllib_device *ieee,
        }
 
        /* Add EXTRA: Age to display seconds since last beacon/probe response
-        * for given network. */
+        * for given network.
+        */
        iwe.cmd = IWEVCUSTOM;
        p = custom;
        p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
@@ -282,8 +281,7 @@ int rtllib_wx_get_scan(struct rtllib_device *ieee,
                        ev = rtl819x_translate_scan(ieee, ev, stop, network,
                                                    info);
                else
-                       RTLLIB_DEBUG_SCAN("Not showing network '%s ("
-                               " %pM)' due to age (%lums).\n",
+                       RTLLIB_DEBUG_SCAN("Not showing network '%s ( %pM)' due to age (%lums).\n",
                                escape_essid(network->ssid,
                                             network->ssid_len),
                                network->bssid,
@@ -338,13 +336,14 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
                        RTLLIB_DEBUG_WX("Disabling encryption.\n");
 
                /* Check all the keys to see if any are still configured,
-                * and if no key index was provided, de-init them all */
+                * and if no key index was provided, de-init them all
+                */
                for (i = 0; i < NUM_WEP_KEYS; i++) {
                        if (ieee->crypt_info.crypt[i] != NULL) {
                                if (key_provided)
                                        break;
                                lib80211_crypt_delayed_deinit(&ieee->crypt_info,
-                                                           &ieee->crypt_info.crypt[i]);
+                                                   &ieee->crypt_info.crypt[i]);
                        }
                }
 
@@ -365,7 +364,8 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
        if (*crypt != NULL && (*crypt)->ops != NULL &&
            strcmp((*crypt)->ops->name, "R-WEP") != 0) {
                /* changing to use WEP; deinit previously used algorithm
-                * on this key */
+                * on this key
+                */
                lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
        }
 
@@ -390,9 +390,9 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
                        kfree(new_crypt);
                        new_crypt = NULL;
 
-                       printk(KERN_WARNING "%s: could not initialize WEP: "
-                              "load module rtllib_crypt_wep\n",
-                              dev->name);
+                       netdev_warn(dev,
+                                   "%s: could not initialize WEP: load module rtllib_crypt_wep\n",
+                                   dev->name);
                        return -EOPNOTSUPP;
                }
                *crypt = new_crypt;
@@ -413,7 +413,8 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
                                       (*crypt)->priv);
                sec.flags |= (1 << key);
                /* This ensures a key will be activated if no key is
-                * explicitly set */
+                * explicitly set
+                */
                if (key == sec.active_key)
                        sec.flags |= SEC_ACTIVE_KEY;
                ieee->crypt_info.tx_keyidx = key;
@@ -423,11 +424,9 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
                                             NULL, (*crypt)->priv);
                if (len == 0) {
                        /* Set a default key of all 0 */
-                       printk(KERN_INFO "Setting key %d to all zero.\n",
+                       netdev_info(ieee->dev, "Setting key %d to all zero.\n",
                                           key);
 
-                       RTLLIB_DEBUG_WX("Setting key %d to all zero.\n",
-                                          key);
                        memset(sec.keys[key], 0, 13);
                        (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
                                               (*crypt)->priv);
@@ -437,8 +436,8 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
 
                /* No key data - just set the default TX key index */
                if (key_provided) {
-                       RTLLIB_DEBUG_WX(
-                               "Setting key %d to default Tx key.\n", key);
+                       RTLLIB_DEBUG_WX("Setting key %d to default Tx key.\n",
+                                       key);
                        ieee->crypt_info.tx_keyidx = key;
                        sec.active_key = key;
                        sec.flags |= SEC_ACTIVE_KEY;
@@ -454,7 +453,8 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
                           "OPEN" : "SHARED KEY");
 
        /* For now we just support WEP, so only set that security level...
-        * TODO: When WPA is added this is one place that needs to change */
+        * TODO: When WPA is added this is one place that needs to change
+        */
        sec.flags |= SEC_LEVEL;
        sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
 
@@ -465,11 +465,12 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee,
         * generate new IEEE 802.11 authentication which may end up in looping
         * with IEEE 802.1X.  If your hardware requires a reset after WEP
         * configuration (for example... Prism2), implement the reset_port in
-        * the callbacks structures used to initialize the 802.11 stack. */
+        * the callbacks structures used to initialize the 802.11 stack.
+        */
        if (ieee->reset_on_keychange &&
            ieee->iw_mode != IW_MODE_INFRA &&
            ieee->reset_port && ieee->reset_port(dev)) {
-               printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
+               netdev_dbg(dev, "%s: reset_port failed\n", dev->name);
                return -EINVAL;
        }
        return 0;
@@ -596,7 +597,7 @@ int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
                ret = -EINVAL;
                goto done;
        }
-       printk(KERN_INFO "alg name:%s\n", alg);
+       netdev_info(dev, "alg name:%s\n", alg);
 
        ops = lib80211_get_crypto_ops(alg);
        if (ops == NULL) {
@@ -608,9 +609,7 @@ int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
                ops = lib80211_get_crypto_ops(alg);
        }
        if (ops == NULL) {
-               RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
-                                  dev->name, ext->alg);
-               printk(KERN_INFO "========>unknown crypto alg %d\n", ext->alg);
+               netdev_info(dev, "========>unknown crypto alg %d\n", ext->alg);
                ret = -EINVAL;
                goto done;
        }
@@ -641,8 +640,7 @@ int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
        if (ext->key_len > 0 && (*crypt)->ops->set_key &&
            (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
                                   (*crypt)->priv) < 0) {
-               RTLLIB_DEBUG_WX("%s: key setting failed\n", dev->name);
-               printk(KERN_INFO "key setting failed\n");
+               netdev_info(dev, "key setting failed\n");
                ret = -EINVAL;
                goto done;
        }
@@ -759,9 +757,9 @@ int rtllib_wx_set_mlme(struct rtllib_device *ieee,
 
        case IW_MLME_DISASSOC:
                if (deauth)
-                       printk(KERN_INFO "disauth packet !\n");
+                       netdev_info(ieee->dev, "disauth packet !\n");
                else
-                       printk(KERN_INFO "dis associate packet!\n");
+                       netdev_info(ieee->dev, "dis associate packet!\n");
 
                ieee->cannot_notify = true;
 
@@ -797,8 +795,7 @@ int rtllib_wx_set_auth(struct rtllib_device *ieee,
        case IW_AUTH_CIPHER_PAIRWISE:
        case IW_AUTH_CIPHER_GROUP:
        case IW_AUTH_KEY_MGMT:
-               /*
-                * Host AP driver does not use these parameters and allows
+               /* Host AP driver does not use these parameters and allows
                 * wpa_supplicant to control them internally.
                 */
                break;
index 90ace791f2d77a9368143bf416188c0106184605..82d60380bb404a6c5c332c3b35ca5d423d538ca9 100644 (file)
@@ -6,7 +6,7 @@ void Dot11d_Init(struct ieee80211_device *ieee)
 {
        PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
 
-       pDot11dInfo->bEnabled = 0;
+       pDot11dInfo->bEnabled = false;
 
        pDot11dInfo->State = DOT11D_STATE_NONE;
        pDot11dInfo->CountryIeLen = 0;
index bd75e29adc2c41bfccb211e40130c64ae65185a4..8ae673b217d89e32c752451f63e03e41e1136900 100644 (file)
@@ -53,7 +53,7 @@ typedef struct _RT_DOT11D_INFO {
 
 #define CIE_WATCHDOG_TH 1
 #define GET_CIE_WATCHDOG(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog)
-#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
+#define RESET_CIE_WATCHDOG(__pIeeeDev) (GET_CIE_WATCHDOG(__pIeeeDev) = 0)
 #define UPDATE_CIE_WATCHDOG(__pIeeeDev) (++GET_CIE_WATCHDOG(__pIeeeDev))
 
 #define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
index b44aa17d30a764f429fad303d9c562d97975b8d4..0f53c6a97578504d0f4a31eb42a98d846e6c3ba3 100644 (file)
@@ -606,33 +606,6 @@ do { if (ieee80211_debug_level & (level)) \
 #define IEEE80211_DEBUG_RX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
 #define IEEE80211_DEBUG_QOS(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a)
 
-#ifdef CONFIG_IEEE80211_DEBUG
-/* Added by Annie, 2005-11-22. */
-#define MAX_STR_LEN     64
-/* I want to see ASCII 33 to 126 only. Otherwise, I print '?'. Annie, 2005-11-22.*/
-#define PRINTABLE(_ch)  (_ch>'!' && _ch<'~')
-#define IEEE80211_PRINT_STR(_Comp, _TitleString, _Ptr, _Len)                                   \
-                       if((_Comp) & level)                                                     \
-                       {                                                                       \
-                               int             __i;                                            \
-                               u8  buffer[MAX_STR_LEN];                                        \
-                               int length = (_Len<MAX_STR_LEN)? _Len : (MAX_STR_LEN-1) ;       \
-                               memset(buffer, 0, MAX_STR_LEN);                                 \
-                               memcpy(buffer, (u8 *)_Ptr, length );                            \
-                               for( __i=0; __i<MAX_STR_LEN; __i++ )                            \
-                               {                                                               \
-                                    if( !PRINTABLE(buffer[__i]) )   buffer[__i] = '?';         \
-                               }                                                               \
-                               buffer[length] = '\0';                                          \
-                               printk("Rtl819x: ");                                            \
-                               printk(_TitleString);                                         \
-                               printk(": %d, <%s>\n", _Len, buffer);                         \
-                       }
-#else
-#define IEEE80211_PRINT_STR(_Comp, _TitleString, _Ptr, _Len)  do {} while (0)
-#endif
-
-#include <linux/netdevice.h>
 #include <linux/if_arp.h> /* ARPHRD_ETHER */
 
 #ifndef WIRELESS_SPY
@@ -661,7 +634,7 @@ struct ieee80211_snap_hdr {
        u8    ctrl;   /* always 0x03 */
        u8    oui[P80211_OUI_LEN];    /* organizational universal id */
 
-} __attribute__ ((packed));
+} __packed;
 
 #define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
 
@@ -996,7 +969,7 @@ struct ieee80211_security {
        u8 keys[WEP_KEYS][SCM_KEY_LEN];
        u8 level;
        u16 flags;
-} __attribute__ ((packed));
+} __packed;
 
 
 /*
@@ -1051,14 +1024,14 @@ struct ieee80211_hdr {
        __le16 frame_ctl;
        __le16 duration_id;
        u8 payload[0];
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_hdr_1addr {
        __le16 frame_ctl;
        __le16 duration_id;
        u8 addr1[ETH_ALEN];
        u8 payload[0];
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_hdr_2addr {
        __le16 frame_ctl;
@@ -1066,7 +1039,7 @@ struct ieee80211_hdr_2addr {
        u8 addr1[ETH_ALEN];
        u8 addr2[ETH_ALEN];
        u8 payload[0];
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_hdr_3addr {
        __le16 frame_ctl;
@@ -1076,7 +1049,7 @@ struct ieee80211_hdr_3addr {
        u8 addr3[ETH_ALEN];
        __le16 seq_ctl;
        u8 payload[0];
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_hdr_4addr {
        __le16 frame_ctl;
@@ -1087,7 +1060,7 @@ struct ieee80211_hdr_4addr {
        __le16 seq_ctl;
        u8 addr4[ETH_ALEN];
        u8 payload[0];
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_hdr_3addrqos {
        __le16 frame_ctl;
@@ -1098,7 +1071,7 @@ struct ieee80211_hdr_3addrqos {
        __le16 seq_ctl;
        u8 payload[0];
        __le16 qos_ctl;
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_hdr_4addrqos {
        __le16 frame_ctl;
@@ -1110,13 +1083,13 @@ struct ieee80211_hdr_4addrqos {
        u8 addr4[ETH_ALEN];
        u8 payload[0];
        __le16 qos_ctl;
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_info_element {
        u8 id;
        u8 len;
        u8 data[0];
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_authentication {
        struct ieee80211_hdr_3addr header;
@@ -1125,18 +1098,18 @@ struct ieee80211_authentication {
        __le16 status;
        /*challenge*/
        struct ieee80211_info_element info_element[0];
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_disassoc {
        struct ieee80211_hdr_3addr header;
        __le16 reason;
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_probe_request {
        struct ieee80211_hdr_3addr header;
        /* SSID, supported rates */
        struct ieee80211_info_element info_element[0];
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_probe_response {
        struct ieee80211_hdr_3addr header;
@@ -1146,7 +1119,7 @@ struct ieee80211_probe_response {
        /* SSID, supported rates, FH params, DS params,
         * CF params, IBSS params, TIM (if beacon), RSN */
        struct ieee80211_info_element info_element[0];
-} __attribute__ ((packed));
+} __packed;
 
 /* Alias beacon for probe_response */
 #define ieee80211_beacon ieee80211_probe_response
@@ -1157,7 +1130,7 @@ struct ieee80211_assoc_request_frame {
        __le16 listen_interval;
        /* SSID, supported rates, RSN */
        struct ieee80211_info_element info_element[0];
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_reassoc_request_frame {
        struct ieee80211_hdr_3addr header;
@@ -1166,7 +1139,7 @@ struct ieee80211_reassoc_request_frame {
        u8 current_ap[ETH_ALEN];
        /* SSID, supported rates, RSN */
        struct ieee80211_info_element info_element[0];
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_assoc_response_frame {
        struct ieee80211_hdr_3addr header;
@@ -1174,7 +1147,7 @@ struct ieee80211_assoc_response_frame {
        __le16 status;
        __le16 aid;
        struct ieee80211_info_element info_element[0]; /* supported rates */
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_txb {
        u8 nr_frags;
@@ -1191,7 +1164,7 @@ struct ieee80211_txb {
 struct ieee80211_drv_agg_txb {
        u8 nr_drv_agg_frames;
        struct sk_buff *tx_agg_frames[MAX_TX_AGG_COUNT];
-}__attribute__((packed));
+} __packed;
 
 #define MAX_SUBFRAME_COUNT               64
 struct ieee80211_rxb {
@@ -1199,7 +1172,7 @@ struct ieee80211_rxb {
        struct sk_buff *subframes[MAX_SUBFRAME_COUNT];
        u8 dst[ETH_ALEN];
        u8 src[ETH_ALEN];
-}__attribute__((packed));
+} __packed;
 
 typedef union _frameqos {
        u16 shortdata;
@@ -1267,19 +1240,19 @@ struct ieee80211_qos_information_element {
        u8 qui_subtype;
        u8 version;
        u8 ac_info;
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_qos_ac_parameter {
        u8 aci_aifsn;
        u8 ecw_min_max;
        __le16 tx_op_limit;
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_qos_parameter_info {
        struct ieee80211_qos_information_element info_element;
        u8 reserved;
        struct ieee80211_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM];
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_qos_parameters {
        __le16 cw_min[QOS_QUEUE_NUM];
@@ -1287,7 +1260,7 @@ struct ieee80211_qos_parameters {
        u8 aifs[QOS_QUEUE_NUM];
        u8 flag[QOS_QUEUE_NUM];
        __le16 tx_op_limit[QOS_QUEUE_NUM];
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_qos_data {
        struct ieee80211_qos_parameters parameters;
@@ -1300,7 +1273,7 @@ struct ieee80211_qos_data {
 struct ieee80211_tim_parameters {
        u8 tim_count;
        u8 tim_period;
-} __attribute__ ((packed));
+} __packed;
 
 //#else
 struct ieee80211_wmm_ac_param {
@@ -1313,7 +1286,7 @@ struct ieee80211_wmm_ts_info {
        u8 ac_dir_tid;
        u8 ac_up_psb;
        u8 reserved;
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_wmm_tspec_elem {
        struct ieee80211_wmm_ts_info ts_info;
@@ -1332,7 +1305,7 @@ struct ieee80211_wmm_tspec_elem {
        u32 min_phy_rate;
        u16 surp_band_allow;
        u16 medium_time;
-}__attribute__((packed));
+} __packed;
 enum eap_type {
        EAP_PACKET = 0,
        EAPOL_START,
@@ -1371,7 +1344,7 @@ struct eapol {
        u8 version;
        u8 type;
        u16 length;
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_softmac_stats{
        unsigned int rx_ass_ok;
@@ -1401,7 +1374,7 @@ struct ieee80211_softmac_stats{
 struct ieee80211_info_element_hdr {
        u8 id;
        u8 len;
-} __attribute__ ((packed));
+} __packed;
 
 /*
  * These are the data types that can make up management packets
@@ -1414,7 +1387,7 @@ struct ieee80211_info_element_hdr {
        u16 listen_interval;
        struct {
                u16 association_id:14, reserved:2;
-       } __attribute__ ((packed));
+       } __packed;
        u32 time_stamp[2];
        u16 reason;
        u16 status;
@@ -1475,7 +1448,7 @@ struct    ether_header {
        u8 ether_dhost[ETHER_ADDR_LEN];
        u8 ether_shost[ETHER_ADDR_LEN];
        u16 ether_type;
-} __attribute__((packed));
+} __packed;
 
 #ifndef ETHERTYPE_PAE
 #define        ETHERTYPE_PAE   0x888e          /* EAPOL PAE/802.1x */
@@ -1484,24 +1457,6 @@ struct   ether_header {
 #define        ETHERTYPE_IP    0x0800          /* IP protocol */
 #endif
 
-typedef struct _bss_ht{
-
-       bool                            support_ht;
-
-       // HT related elements
-       u8                                      ht_cap_buf[32];
-       u16                                     ht_cap_len;
-       u8                                      ht_info_buf[32];
-       u16                                     ht_info_len;
-
-       HT_SPEC_VER                     ht_spec_ver;
-       //HT_CAPABILITY_ELE                     bdHTCapEle;
-       //HT_INFORMATION_ELE            bdHTInfoEle;
-
-       bool                            aggregation;
-       bool                            long_slot_time;
-}bss_ht, *pbss_ht;
-
 typedef enum _erp_t{
        ERP_NonERPpresent       = 0x01,
        ERP_UseProtection       = 0x02,
index 55332217c29fb211fceca01a7c08a4a8be453bca..3995620b3442deb0d8d73ed6e03a6b9e28ecbde5 100644 (file)
  *
  */
 
-//#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <asm/string.h>
-#include <asm/errno.h>
+#include <linux/string.h>
+#include <linux/errno.h>
 
 #include "ieee80211.h"
 
@@ -66,8 +65,8 @@ void ieee80211_crypt_deinit_handler(unsigned long data)
        spin_lock_irqsave(&ieee->lock, flags);
        ieee80211_crypt_deinit_entries(ieee, 0);
        if (!list_empty(&ieee->crypt_deinit_list)) {
-               printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
-                      "deletion list\n", ieee->dev->name);
+               netdev_dbg(ieee->dev, "%s: entries remaining in delayed crypt deletion list\n",
+                               ieee->dev->name);
                ieee->crypt_deinit_timer.expires = jiffies + HZ;
                add_timer(&ieee->crypt_deinit_timer);
        }
@@ -118,7 +117,7 @@ int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
        list_add(&alg->list, &hcrypt->algs);
        spin_unlock_irqrestore(&hcrypt->lock, flags);
 
-       printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n",
+       pr_debug("ieee80211_crypt: registered algorithm '%s'\n",
               ops->name);
 
        return 0;
@@ -146,8 +145,8 @@ int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
        spin_unlock_irqrestore(&hcrypt->lock, flags);
 
        if (del_alg) {
-               printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
-                      "'%s'\n", ops->name);
+               pr_debug("ieee80211_crypt: unregistered algorithm '%s'\n",
+                               ops->name);
                kfree(del_alg);
        }
 
@@ -232,8 +231,8 @@ void __exit ieee80211_crypto_deinit(void)
                struct ieee80211_crypto_alg *alg =
                        (struct ieee80211_crypto_alg *) ptr;
                list_del(ptr);
-               printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
-                      "'%s' (deinit)\n", alg->ops->name);
+               pr_debug("ieee80211_crypt: unregistered algorithm '%s' (deinit)\n",
+                               alg->ops->name);
                kfree(alg);
        }
 
index 143b682477e59f16954f6ab9a26cbac10021fb37..788704b800c4002405f1408dc575976dddd55d44 100644 (file)
@@ -9,7 +9,6 @@
  * more details.
  */
 
-//#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -18,7 +17,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_ether.h>
 #include <linux/if_arp.h>
-#include <asm/string.h>
+#include <linux/string.h>
 #include <linux/wireless.h>
 
 #include "ieee80211.h"
@@ -130,9 +129,9 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
        qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
                       (WLAN_FC_GET_STYPE(fc) & 0x08));
        */
-       // fixed by David :2006.9.6
-       qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
-                      (WLAN_FC_GET_STYPE(fc) & 0x80));
+       /* fixed by David :2006.9.6 */
+       qc_included = (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
+                      (WLAN_FC_GET_STYPE(fc) & 0x80);
        aad_len = 22;
        if (a4_included)
                aad_len += 6;
@@ -209,7 +208,7 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
        pos = skb_push(skb, CCMP_HDR_LEN);
        memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
        pos += hdr_len;
-//     mic = skb_put(skb, CCMP_MIC_LEN);
+       /* mic = skb_put(skb, CCMP_MIC_LEN); */
 
        i = CCMP_PN_LEN - 1;
        while (i >= 0) {
@@ -239,7 +238,7 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
                u8 *e = key->tx_e;
                u8 *s0 = key->tx_s0;
 
-               //mic is moved to here by john
+               /* mic is moved to here by john */
                mic = skb_put(skb, CCMP_MIC_LEN);
 
                ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
@@ -444,7 +443,7 @@ static char *ieee80211_ccmp_print_stats(char *p, void *priv)
 
 void ieee80211_ccmp_null(void)
 {
-//    printk("============>%s()\n", __func__);
+       /* printk("============>%s()\n", __func__); */
        return;
 }
 
index fcc90a5700d66784555d507b5e8a9192b7307046..e815c81b45dc59551341c981685794c721939a5e 100644 (file)
@@ -9,7 +9,6 @@
  * more details.
  */
 
-//#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -18,7 +17,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_ether.h>
 #include <linux/if_arp.h>
-#include <asm/string.h>
+#include <linux/string.h>
 
 #include "ieee80211.h"
 
index 8c1bf1f56883fb3d5dad053f0af747e0389ea2de..0a17f84bb809124ffe050eccff359b9cf927aa6c 100644 (file)
@@ -9,13 +9,12 @@
  * more details.
  */
 
-//#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/skbuff.h>
-#include <asm/string.h>
+#include <linux/string.h>
 
 #include "ieee80211.h"
 
@@ -49,14 +48,14 @@ static void *prism2_wep_init(int keyidx)
 
        priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->tx_tfm)) {
-               printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
+               pr_debug("ieee80211_crypt_wep: could not allocate "
                       "crypto API arc4\n");
                priv->tx_tfm = NULL;
                goto fail;
        }
        priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->rx_tfm)) {
-               printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
+               pr_debug("ieee80211_crypt_wep: could not allocate "
                       "crypto API arc4\n");
                priv->rx_tfm = NULL;
                goto fail;
@@ -110,6 +109,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
        u32 crc;
        u8 *icv;
        struct scatterlist sg;
+
        if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
            skb->len < hdr_len)
                return -1;
@@ -128,6 +128,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
         * can be used to speedup attacks, so avoid using them. */
        if ((wep->iv & 0xff00) == 0xff00) {
                u8 B = (wep->iv >> 16) & 0xff;
+
                if (B >= 3 && B < klen)
                        wep->iv += 0x0100;
        }
@@ -180,6 +181,7 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
        u32 crc;
        u8 icv[4];
        struct scatterlist sg;
+
        if (skb->len < hdr_len + 8)
                return -1;
 
@@ -256,6 +258,7 @@ static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
 static char *prism2_wep_print_stats(char *p, void *priv)
 {
        struct prism2_wep_data *wep = priv;
+
        p += sprintf(p, "key[%d] alg=WEP len=%d\n",
                     wep->key_idx, wep->key_len);
        return p;
index afbd09d7300a0e10c40631359ee9c646bf4ec982..31233d895ee9414c2206697d0d7e1dc3b1ae8613 100644 (file)
@@ -31,7 +31,7 @@
 *******************************************************************************/
 
 #include <linux/compiler.h>
-//#include <linux/config.h>
+/* #include <linux/config.h> */
 #include <linux/errno.h>
 #include <linux/if_arp.h>
 #include <linux/in6.h>
@@ -133,15 +133,14 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
        ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
 
        INIT_LIST_HEAD(&ieee->crypt_deinit_list);
-       init_timer(&ieee->crypt_deinit_timer);
-       ieee->crypt_deinit_timer.data = (unsigned long)ieee;
-       ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
+       setup_timer(&ieee->crypt_deinit_timer,
+                   ieee80211_crypt_deinit_handler, (unsigned long)ieee);
 
        spin_lock_init(&ieee->lock);
        spin_lock_init(&ieee->wpax_suitlist_lock);
        spin_lock_init(&ieee->bw_spinlock);
        spin_lock_init(&ieee->reorder_spinlock);
-       //added by WB
+       /* added by WB */
        atomic_set(&(ieee->atm_chnlop), 0);
        atomic_set(&(ieee->atm_swbw), 0);
 
@@ -153,7 +152,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
        ieee->ieee802_1x = 1;
        ieee->raw_tx = 0;
        //ieee->hwsec_support = 1; //defalt support hw security. //use module_param instead.
-       ieee->hwsec_active = 0; //disable hwsec, switch it on when necessary.
+       ieee->hwsec_active = 0; /* disable hwsec, switch it on when necessary. */
 
        ieee80211_softmac_init(ieee);
 
@@ -164,7 +163,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
                goto failed;
        }
        HTUpdateDefaultSetting(ieee);
-       HTInitializeHTInfo(ieee); //may move to other place.
+       HTInitializeHTInfo(ieee); /* may move to other place. */
        TSInitialize(ieee);
 
        for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
@@ -176,7 +175,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
          ieee->last_packet_time[i] = 0;
        }
 
-//These function were added to load crypte module autoly
+/* These function were added to load crypte module autoly */
        ieee80211_tkip_null();
        ieee80211_wep_null();
        ieee80211_ccmp_null();
@@ -195,7 +194,7 @@ void free_ieee80211(struct net_device *dev)
 {
        struct ieee80211_device *ieee = netdev_priv(dev);
        int i;
-       //struct list_head *p, *q;
+       /* struct list_head *p, *q; */
 //     del_timer_sync(&ieee->SwBwTimer);
        kfree(ieee->pHTInfo);
        ieee->pHTInfo = NULL;
@@ -239,13 +238,15 @@ static int debug = \
        //                  IEEE80211_DL_REORDER|
 //                         IEEE80211_DL_TRACE  |
                            //IEEE80211_DL_DATA |
-                           IEEE80211_DL_ERR      //awayls open this flags to show error out
+                           IEEE80211_DL_ERR      /* awayls open this flags to show error out */
                            ;
 static struct proc_dir_entry *ieee80211_proc;
 
 static int show_debug_level(struct seq_file *m, void *v)
 {
-       return seq_printf(m, "0x%08X\n", ieee80211_debug_level);
+       seq_printf(m, "0x%08X\n", ieee80211_debug_level);
+
+       return 0;
 }
 
 static ssize_t write_debug_level(struct file *file, const char __user *buffer,
@@ -284,7 +285,7 @@ int __init ieee80211_debug_init(void)
                                " proc directory\n");
                return -EIO;
        }
-       e = proc_create("debug_level", S_IRUGO | S_IWUSR, 
+       e = proc_create("debug_level", S_IRUGO | S_IWUSR,
                              ieee80211_proc, &fops);
        if (!e) {
                remove_proc_entry(DRV_NAME, init_net.proc_net);
@@ -303,7 +304,6 @@ void __exit ieee80211_debug_exit(void)
        }
 }
 
-#include <linux/moduleparam.h>
 module_param(debug, int, 0444);
 MODULE_PARM_DESC(debug, "debug output mask");
 #endif
index d401dbf4c7c608767d7c7b011d49e7f460799b2a..9fbb53d8c6bfb8ab3869c28c37861c806db9d7bb 100644 (file)
@@ -22,7 +22,6 @@
 
 
 #include <linux/compiler.h>
-//#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/if_arp.h>
 #include <linux/in6.h>
@@ -39,7 +38,7 @@
 #include <linux/types.h>
 #include <linux/wireless.h>
 #include <linux/etherdevice.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/ctype.h>
 
 #include "ieee80211.h"
@@ -56,7 +55,7 @@ static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
 
        skb_pull(skb, ieee80211_get_hdrlen(fc));
        skb->pkt_type = PACKET_OTHERHOST;
-       skb->protocol = __constant_htons(ETH_P_80211_RAW);
+       skb->protocol = htons(ETH_P_80211_RAW);
        memset(skb->cb, 0, sizeof(skb->cb));
        netif_rx(skb);
 }
@@ -222,8 +221,8 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
 
        rx_stats->len = skb->len;
        ieee80211_rx_mgt(ieee,(struct ieee80211_hdr_4addr *)skb->data,rx_stats);
-       //if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN)))
-       if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))//use ADDR1 to perform address matching for Management frames
+       /* if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) */
+       if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))/* use ADDR1 to perform address matching for Management frames */
        {
                dev_kfree_skb_any(skb);
                return 0;
@@ -609,12 +608,12 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee,
        bool                    bMatchWinStart = false, bPktInBuf = false;
        IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): Seq is %d,pTS->RxIndicateSeq is %d, WinSize is %d\n",__func__,SeqNum,pTS->RxIndicateSeq,WinSize);
        /* Rx Reorder initialize condition.*/
-       if(pTS->RxIndicateSeq == 0xffff) {
+       if (pTS->RxIndicateSeq == 0xffff) {
                pTS->RxIndicateSeq = SeqNum;
        }
 
        /* Drop out the packet which SeqNum is smaller than WinStart */
-       if(SN_LESS(SeqNum, pTS->RxIndicateSeq)) {
+       if (SN_LESS(SeqNum, pTS->RxIndicateSeq)) {
                IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packet Drop! IndicateSeq: %d, NewSeq: %d\n",
                                 pTS->RxIndicateSeq, SeqNum);
                pHTInfo->RxReorderDropCounter++;
@@ -717,7 +716,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee,
                    SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq))
                {
                        /* This protect buffer from overflow. */
-                       if(index >= REORDER_WIN_SIZE) {
+                       if (index >= REORDER_WIN_SIZE) {
                                IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!! \n");
                                bPktInBuf = true;
                                break;
@@ -741,7 +740,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee,
        }
 
        /* Handling pending timer. Set this timer to prevent from long time Rx buffering.*/
-       if(index>0) {
+       if (index>0) {
                // Cancel previous pending timer.
        //      del_timer_sync(&pTS->RxPktPendingTimer);
                pTS->RxTimeoutIndicateSeq = 0xffff;
@@ -754,7 +753,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee,
                ieee80211_indicate_packets(ieee, prxbIndicateArray, index);
        }
 
-       if(bPktInBuf && pTS->RxTimeoutIndicateSeq==0xffff) {
+       if (bPktInBuf && pTS->RxTimeoutIndicateSeq==0xffff) {
                // Set new pending timer.
                IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): SET rx timeout timer\n", __func__);
                pTS->RxTimeoutIndicateSeq = pTS->RxIndicateSeq;
@@ -784,16 +783,16 @@ static u8 parse_subframe(struct sk_buff *skb,
        /* just for debug purpose */
        SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl));
 
-       if((IEEE80211_QOS_HAS_SEQ(fc))&&\
+       if ((IEEE80211_QOS_HAS_SEQ(fc))&&\
                        (((frameqos *)(skb->data + IEEE80211_3ADDR_LEN))->field.reserved)) {
                bIsAggregateFrame = true;
        }
 
-       if(IEEE80211_QOS_HAS_SEQ(fc)) {
+       if (IEEE80211_QOS_HAS_SEQ(fc)) {
                LLCOffset += 2;
        }
 
-       if(rx_stats->bContainHTC) {
+       if (rx_stats->bContainHTC) {
                LLCOffset += sHTCLng;
        }
        //printk("ChkLength = %d\n", LLCOffset);
@@ -827,7 +826,7 @@ static u8 parse_subframe(struct sk_buff *skb,
                        //==m==>change the length order
                        nSubframe_Length = (nSubframe_Length>>8) + (nSubframe_Length<<8);
 
-                       if(skb->len<(ETHERNET_HEADER_SIZE + nSubframe_Length)) {
+                       if (skb->len<(ETHERNET_HEADER_SIZE + nSubframe_Length)) {
                                printk("%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\
                                                __func__, rxb->nr_subframes);
                                printk("%s: A-MSDU parse error!! Subframe Length: %d\n",__func__, nSubframe_Length);
@@ -853,19 +852,19 @@ static u8 parse_subframe(struct sk_buff *skb,
                        memcpy(data_ptr, skb->data, nSubframe_Length);
 #endif
                        rxb->subframes[rxb->nr_subframes++] = sub_skb;
-                       if(rxb->nr_subframes >= MAX_SUBFRAME_COUNT) {
+                       if (rxb->nr_subframes >= MAX_SUBFRAME_COUNT) {
                                IEEE80211_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n");
                                break;
                        }
                        skb_pull(skb, nSubframe_Length);
 
-                       if(skb->len != 0) {
+                       if (skb->len != 0) {
                                nPadding_Length = 4 - ((nSubframe_Length + ETHERNET_HEADER_SIZE) % 4);
-                               if(nPadding_Length == 4) {
+                               if (nPadding_Length == 4) {
                                        nPadding_Length = 0;
                                }
 
-                               if(skb->len < nPadding_Length) {
+                               if (skb->len < nPadding_Length) {
                                        return 0;
                                }
 
@@ -939,12 +938,12 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
        frag = WLAN_GET_SEQ_FRAG(sc);
        hdrlen = ieee80211_get_hdrlen(fc);
 
-       if(HTCCheck(ieee, skb->data))
+       if (HTCCheck(ieee, skb->data))
        {
                if(net_ratelimit())
                printk("find HTCControl\n");
                hdrlen += 4;
-               rx_stats->bContainHTC = 1;
+               rx_stats->bContainHTC = true;
        }
 
        //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
@@ -1274,13 +1273,13 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
        }
 */
 //added by amy for reorder
-       if(ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data)
+       if (ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data)
                && !is_multicast_ether_addr(hdr->addr1))
        {
                TID = Frame_QoSTID(skb->data);
                SeqNum = WLAN_GET_SEQ_SEQ(sc);
                GetTs(ieee,(PTS_COMMON_INFO *) &pTS,hdr->addr2,TID,RX_DIR,true);
-               if(TID !=0 && TID !=3)
+               if (TID !=0 && TID !=3)
                {
                        ieee->bis_any_nonbepkts = true;
                }
@@ -1290,7 +1289,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
        payload = skb->data + hdrlen;
        //ethertype = (payload[6] << 8) | payload[7];
        rxb = kmalloc(sizeof(struct ieee80211_rxb), GFP_ATOMIC);
-       if(rxb == NULL)
+       if (rxb == NULL)
        {
                IEEE80211_DEBUG(IEEE80211_DL_ERR,"%s(): kmalloc rxb error\n",__func__);
                goto rx_dropped;
@@ -1336,7 +1335,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 
                                stats->rx_packets++;
                                stats->rx_bytes += sub_skb->len;
-                               if(is_multicast_ether_addr(dst)) {
+                               if (is_multicast_ether_addr(dst)) {
                                        stats->multicast++;
                                }
 
@@ -1590,14 +1589,14 @@ static inline void ieee80211_extract_country_ie(
        u8 *addr2
 )
 {
-       if(IS_DOT11D_ENABLE(ieee))
+       if (IS_DOT11D_ENABLE(ieee))
        {
-               if(info_element->len!= 0)
+               if (info_element->len!= 0)
                {
                        memcpy(network->CountryIeBuf, info_element->data, info_element->len);
                        network->CountryIeLen = info_element->len;
 
-                       if(!IS_COUNTRY_IE_VALID(ieee))
+                       if (!IS_COUNTRY_IE_VALID(ieee))
                        {
                                Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
                        }
@@ -1608,7 +1607,7 @@ static inline void ieee80211_extract_country_ie(
                // some AP (e.g. Cisco 1242) don't include country IE in their
                // probe response frame.
                //
-               if(IS_EQUAL_CIE_SRC(ieee, addr2) )
+               if (IS_EQUAL_CIE_SRC(ieee, addr2) )
                {
                        UPDATE_CIE_WATCHDOG(ieee);
                }
@@ -1705,7 +1704,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
 #ifdef CONFIG_IEEE80211_DEBUG
                                p += snprintf(p, sizeof(rates_str) -
                                              (p - rates_str), "%02X ",
-                                             network->rates[i]);
+                                             network->rates_ex[i]);
 #endif
                                if (ieee80211_is_ofdm_rate
                                    (info_element->data[i])) {
@@ -1888,7 +1887,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
 
                        //if(tmp_htcap_len !=0  ||  tmp_htinfo_len != 0)
                        {
-                               if((info_element->len >= 3 &&
+                               if ((info_element->len >= 3 &&
                                         info_element->data[0] == 0x00 &&
                                         info_element->data[1] == 0x05 &&
                                         info_element->data[2] == 0xb5) ||
@@ -1940,7 +1939,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
                        else
                                network->cisco_cap_exist = false;
                        //added by amy for LEAP of cisco
-                       if(info_element->len > 4 &&
+                       if (info_element->len > 4 &&
                                info_element->data[0] == 0x00 &&
                                info_element->data[1] == 0x40 &&
                                info_element->data[2] == 0x96 &&
@@ -1976,7 +1975,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
                                        network->bCcxRmEnable = false;
                                }
                        }
-                       if(info_element->len > 4  &&
+                       if (info_element->len > 4  &&
                                info_element->data[0] == 0x00 &&
                                info_element->data[1] == 0x40 &&
                                info_element->data[2] == 0x96 &&
@@ -2296,7 +2295,7 @@ static inline void update_network(struct ieee80211_network *dst,
        dst->rates_len = src->rates_len;
        memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
        dst->rates_ex_len = src->rates_ex_len;
-       if(src->ssid_len > 0)
+       if (src->ssid_len > 0)
        {
                memset(dst->ssid, 0, dst->ssid_len);
                dst->ssid_len = src->ssid_len;
@@ -2352,7 +2351,7 @@ static inline void update_network(struct ieee80211_network *dst,
                dst->qos_data.param_count = src->qos_data.param_count;
        }
 
-       if(dst->qos_data.supported == 1) {
+       if (dst->qos_data.supported == 1) {
                dst->QoS_Enable = 1;
                if(dst->ssid_len)
                        IEEE80211_DEBUG_QOS
@@ -2367,7 +2366,7 @@ static inline void update_network(struct ieee80211_network *dst,
 
        /* dst->last_associate is not overwritten */
        dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame.
-       if(src->wmm_param[0].ac_aci_acm_aifsn|| \
+       if (src->wmm_param[0].ac_aci_acm_aifsn|| \
           src->wmm_param[1].ac_aci_acm_aifsn|| \
           src->wmm_param[2].ac_aci_acm_aifsn|| \
           src->wmm_param[3].ac_aci_acm_aifsn) {
@@ -2456,7 +2455,7 @@ static inline void ieee80211_process_probe_response(
 
        if (!IsLegalChannel(ieee, network.channel))
                return;
-       if(ieee->bGlobalDomain)
+       if (ieee->bGlobalDomain)
        {
                if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP)
                {
@@ -2472,7 +2471,7 @@ static inline void ieee80211_process_probe_response(
                        else
                        {
                                // Filter over channel ch12~14
-                               if(network.channel > 11)
+                               if (network.channel > 11)
                                {
                                        printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel);
                                        return;
@@ -2493,7 +2492,7 @@ static inline void ieee80211_process_probe_response(
                        else
                        {
                                // Filter over channel ch12~14
-                               if(network.channel > 14)
+                               if (network.channel > 14)
                                {
                                        printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network.channel);
                                        return;
@@ -2514,9 +2513,9 @@ static inline void ieee80211_process_probe_response(
 
        spin_lock_irqsave(&ieee->lock, flags);
 
-       if(is_same_network(&ieee->current_network, &network, ieee)) {
+       if (is_same_network(&ieee->current_network, &network, ieee)) {
                update_network(&ieee->current_network, &network);
-               if((ieee->current_network.mode == IEEE_N_24G || ieee->current_network.mode == IEEE_G)
+               if ((ieee->current_network.mode == IEEE_N_24G || ieee->current_network.mode == IEEE_G)
                && ieee->current_network.berp_info_valid){
                if(ieee->current_network.erp_value& ERP_UseProtection)
                        ieee->current_network.buseprotection = true;
@@ -2606,7 +2605,7 @@ static inline void ieee80211_process_probe_response(
        spin_unlock_irqrestore(&ieee->lock, flags);
        if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, &network, ieee)&&\
                (ieee->state == IEEE80211_LINKED)) {
-               if(ieee->handle_beacon != NULL) {
+               if (ieee->handle_beacon != NULL) {
                        ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network);
                }
        }
index d1471877e19d6e0b8ee127d7317f41124921ad7a..c2388812d4fd71d15015accb08c728f450b5a3d8 100644 (file)
@@ -62,7 +62,7 @@ static void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
 {
        u8 *tag = *tag_p;
 
-       if (ieee->modulation & IEEE80211_CCK_MODULATION){
+       if (ieee->modulation & IEEE80211_CCK_MODULATION) {
                *tag++ = MFIE_TYPE_RATES;
                *tag++ = 4;
                *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
@@ -79,7 +79,7 @@ static void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
 {
        u8 *tag = *tag_p;
 
-               if (ieee->modulation & IEEE80211_OFDM_MODULATION){
+               if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
 
                *tag++ = MFIE_TYPE_RATES_EX;
                *tag++ = 8;
@@ -192,7 +192,7 @@ static u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
        else
                rate = ieee->basic_rate & 0x7f;
 
-       if(rate == 0){
+       if (rate == 0) {
                // 2005.01.26, by rcnjko.
                if(ieee->mode == IEEE_A||
                   ieee->mode== IEEE_N_5G||
@@ -369,7 +369,7 @@ static void ieee80211_send_beacon(struct ieee80211_device *ieee)
        //unsigned long flags;
        skb = ieee80211_get_beacon_(ieee);
 
-       if (skb){
+       if (skb) {
                softmac_mgmt_xmit(skb, ieee);
                ieee->softmac_stats.tx_beacons++;
                //dev_kfree_skb_any(skb);//edit by thomas
@@ -378,7 +378,7 @@ static void ieee80211_send_beacon(struct ieee80211_device *ieee)
 //             (MSECS( ieee->current_network.beacon_interval -5));
 
        //spin_lock_irqsave(&ieee->beacon_lock,flags);
-       if(ieee->beacon_txing && ieee->ieee_up){
+       if (ieee->beacon_txing && ieee->ieee_up) {
 //             if(!timer_pending(&ieee->beacon_timer))
 //                     add_timer(&ieee->beacon_timer);
                mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
@@ -404,7 +404,7 @@ static void ieee80211_send_probe(struct ieee80211_device *ieee)
        struct sk_buff *skb;
 
        skb = ieee80211_probe_req(ieee);
-       if (skb){
+       if (skb) {
                softmac_mgmt_xmit(skb, ieee);
                ieee->softmac_stats.tx_probe_rq++;
                //dev_kfree_skb_any(skb);//edit by thomas
@@ -413,7 +413,7 @@ static void ieee80211_send_probe(struct ieee80211_device *ieee)
 
 static void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
 {
-       if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
+       if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)) {
                ieee80211_send_probe(ieee);
                ieee80211_send_probe(ieee);
        }
@@ -587,7 +587,7 @@ static void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
        down(&ieee->scan_sem);
 //     spin_lock_irqsave(&ieee->lock, flags);
 
-       if (ieee->scanning == 1){
+       if (ieee->scanning == 1) {
                ieee->scanning = 0;
 
                cancel_delayed_work(&ieee->softmac_scan_wq);
@@ -609,15 +609,15 @@ EXPORT_SYMBOL(ieee80211_stop_scan);
 /* called with ieee->lock held */
 static void ieee80211_start_scan(struct ieee80211_device *ieee)
 {
-       if(IS_DOT11D_ENABLE(ieee) )
+       if (IS_DOT11D_ENABLE(ieee) )
        {
-               if(IS_COUNTRY_IE_VALID(ieee))
+               if (IS_COUNTRY_IE_VALID(ieee))
                {
                        RESET_CIE_WATCHDOG(ieee);
                }
        }
        if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
-               if (ieee->scanning == 0){
+               if (ieee->scanning == 0) {
                        ieee->scanning = 1;
                        queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
                }
@@ -629,9 +629,9 @@ static void ieee80211_start_scan(struct ieee80211_device *ieee)
 /* called with wx_sem held */
 void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
 {
-       if(IS_DOT11D_ENABLE(ieee) )
+       if (IS_DOT11D_ENABLE(ieee) )
        {
-               if(IS_COUNTRY_IE_VALID(ieee))
+               if (IS_COUNTRY_IE_VALID(ieee))
                {
                        RESET_CIE_WATCHDOG(ieee);
                }
@@ -739,7 +739,7 @@ static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
        HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
 
 
-       if(pHTInfo->bRegRT2RTAggregation)
+       if (pHTInfo->bRegRT2RTAggregation)
        {
                tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
                tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
@@ -803,7 +803,7 @@ static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
        *(tag++) = 1;
        *(tag++) = ieee->current_network.channel;
 
-       if(atim_len){
+       if (atim_len) {
                *(tag++) = MFIE_TYPE_IBSS_SET;
                *(tag++) = 2;
 
@@ -812,12 +812,12 @@ static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
                tag+=2;
        }
 
-       if(erp_len){
+       if (erp_len) {
                *(tag++) = MFIE_TYPE_ERP;
                *(tag++) = 1;
                *(tag++) = erpinfo_content;
        }
-       if(rate_ex_len){
+       if (rate_ex_len) {
                *(tag++) = MFIE_TYPE_RATES_EX;
                *(tag++) = rate_ex_len-2;
                memcpy(tag, ieee->current_network.rates_ex, rate_ex_len-2);
@@ -877,7 +877,7 @@ static struct sk_buff *ieee80211_assoc_resp(struct ieee80211_device *ieee,
                crypt = ieee->crypt[ieee->tx_keyidx];
        else crypt = NULL;
 
-       encrypt = (crypt && crypt->ops);
+       encrypt = crypt && crypt->ops;
 
        if (encrypt)
                assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
@@ -1016,12 +1016,12 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco
        encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
 
        //Include High Throuput capability && Realtek proprietary
-       if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
+       if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
        {
                ht_cap_buf = (u8 *)&(ieee->pHTInfo->SelfHTCap);
                ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
                HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
-               if(ieee->pHTInfo->bCurrentRT2RTAggregation)
+               if (ieee->pHTInfo->bCurrentRT2RTAggregation)
                {
                        realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
                        realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
@@ -1029,16 +1029,16 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco
 
                }
        }
-       if(ieee->qos_support){
+       if (ieee->qos_support) {
                wmm_info_len = beacon->qos_data.supported?9:0;
        }
 
 
-       if(beacon->bCkipSupported)
+       if (beacon->bCkipSupported)
        {
                ckip_ie_len = 30+2;
        }
-       if(beacon->bCcxRmEnable)
+       if (beacon->bCcxRmEnable)
        {
                ccxrm_ie_len = 6+2;
        }
@@ -1141,7 +1141,7 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco
                tag += osCcxAironetIE.Length;
        }
 
-       if(beacon->bCcxRmEnable)
+       if (beacon->bCcxRmEnable)
        {
                static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
                OCTET_STRING osCcxRmCap;
@@ -1168,8 +1168,8 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco
                tag += osCcxVerNum.Length;
        }
        //HT cap element
-       if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
-               if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
+       if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
+               if (ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
                {
                        tag = skb_put(skb, ht_cap_len);
                        *tag++ = MFIE_TYPE_HT_CAP;
@@ -1182,22 +1182,22 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco
 
        //choose what wpa_supplicant gives to associate.
        tag = skb_put(skb, wpa_ie_len);
-       if (wpa_ie_len){
+       if (wpa_ie_len) {
                memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
        }
 
        tag = skb_put(skb, wmm_info_len);
-       if(wmm_info_len) {
+       if (wmm_info_len) {
          ieee80211_WMM_Info(ieee, &tag);
        }
 #ifdef THOMAS_TURBO
        tag = skb_put(skb, turbo_info_len);
-       if(turbo_info_len) {
+       if (turbo_info_len) {
                ieee80211_TURBO_Info(ieee, &tag);
        }
 #endif
 
-       if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
+       if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
                if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
                {
                        tag = skb_put(skb, ht_cap_len);
@@ -1207,7 +1207,7 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco
                        tag += ht_cap_len -2;
                }
 
-               if(ieee->pHTInfo->bCurrentRT2RTAggregation){
+               if (ieee->pHTInfo->bCurrentRT2RTAggregation) {
                        tag = skb_put(skb, realtek_ie_len);
                        *tag++ = MFIE_TYPE_GENERIC;
                        *tag++ = realtek_ie_len - 2;
@@ -1273,7 +1273,7 @@ static void ieee80211_associate_step1(struct ieee80211_device *ieee)
                //printk(KERN_WARNING "Sending authentication request\n");
                softmac_mgmt_xmit(skb, ieee);
                //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
-               if(!timer_pending(&ieee->associate_timer)){
+               if (!timer_pending(&ieee->associate_timer)) {
                        ieee->associate_timer.expires = jiffies + (HZ / 2);
                        add_timer(&ieee->associate_timer);
                }
@@ -1358,7 +1358,7 @@ static void ieee80211_associate_complete_wq(struct work_struct *work)
        }
        ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
        // To prevent the immediately calling watch_dog after association.
-       if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
+       if (ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
        {
                ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
                ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
@@ -1371,7 +1371,7 @@ static void ieee80211_associate_complete_wq(struct work_struct *work)
        else if(ieee->is_silent_reset == 1)
        {
                printk("==================>silent reset associate\n");
-               ieee->is_silent_reset = 0;
+               ieee->is_silent_reset = false;
        }
 
        if (ieee->data_hard_resume)
@@ -1430,7 +1430,7 @@ inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee
                return;
 
 
-       if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
+       if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
                /* if the user specified the AP MAC, we need also the essid
                 * This could be obtained by beacons or, if the network does not
                 * broadcast it, it can be put manually.
@@ -1458,13 +1458,13 @@ inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee
                                /* if the essid is hidden replace it with the
                                * essid provided by the user.
                                */
-                               if (!ssidbroad){
+                               if (!ssidbroad) {
                                        strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
                                        tmp_ssid_len = ieee->current_network.ssid_len;
                                }
                                memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
 
-                               if (!ssidbroad){
+                               if (!ssidbroad) {
                                        strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
                                        ieee->current_network.ssid_len = tmp_ssid_len;
                                }
@@ -1541,16 +1541,16 @@ static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen)
 {
        struct ieee80211_authentication *a;
        u8 *t;
-       if (skb->len <  (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
+       if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
                IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
                return 0xcafe;
        }
        *challenge = NULL;
        a = (struct ieee80211_authentication *) skb->data;
-       if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
+       if (skb->len > (sizeof(struct ieee80211_authentication) + 3)) {
                t = skb->data + sizeof(struct ieee80211_authentication);
 
-               if(*(t++) == MFIE_TYPE_CHALLENGE){
+               if (*(t++) == MFIE_TYPE_CHALLENGE) {
                        *chlen = *(t++);
                        *challenge = kmemdup(t, *chlen, GFP_ATOMIC);
                        if (!*challenge)
@@ -1567,7 +1567,7 @@ static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
 {
        struct ieee80211_authentication *a;
 
-       if (skb->len <  (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
+       if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
                IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
                return -1;
        }
@@ -1601,7 +1601,7 @@ static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb,
        tag = skb->data + sizeof (struct ieee80211_hdr_3addr  );
 
        while (tag+1 < skbend){
-               if (*tag == 0){
+               if (*tag == 0) {
                        ssid = tag+2;
                        ssidlen = *(tag+1);
                        break;
@@ -1642,7 +1642,7 @@ static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb
        struct ieee80211_assoc_response_frame *response_head;
        u16 status_code;
 
-       if (skb->len <  sizeof(struct ieee80211_assoc_response_frame)){
+       if (skb->len < sizeof(struct ieee80211_assoc_response_frame)) {
                IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
                return 0xcafe;
        }
@@ -1672,7 +1672,7 @@ ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
        //IEEE80211DMESG("Rx probe");
        ieee->softmac_stats.rx_probe_rq++;
        //DMESG("Dest is "MACSTR, MAC2STR(dest));
-       if (probe_rq_parse(ieee, skb, dest)){
+       if (probe_rq_parse(ieee, skb, dest)) {
                //IEEE80211DMESG("Was for me!");
                ieee->softmac_stats.tx_probe_rs++;
                ieee80211_resp_to_probe(ieee, dest);
@@ -1703,7 +1703,7 @@ ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
        //unsigned long flags;
 
        ieee->softmac_stats.rx_ass_rq++;
-       if (assoc_rq_parse(skb,dest) != -1){
+       if (assoc_rq_parse(skb, dest) != -1) {
                ieee80211_resp_to_assoc_rq(ieee, dest);
        }
 
@@ -1755,13 +1755,13 @@ static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
                (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
                return 0;
 
-       if(time_l){
+       if (time_l) {
                *time_l = ieee->current_network.last_dtim_sta_time[0]
                        + (ieee->current_network.beacon_interval
                        * ieee->current_network.dtim_period) * 1000;
        }
 
-       if(time_h){
+       if (time_h) {
                *time_h = ieee->current_network.last_dtim_sta_time[1];
                if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
                        *time_h += 1;
@@ -1782,7 +1782,7 @@ static inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
 
        spin_lock_irqsave(&ieee->lock, flags);
 
-       if((ieee->ps == IEEE80211_PS_DISABLED ||
+       if ((ieee->ps == IEEE80211_PS_DISABLED ||
                ieee->iw_mode != IW_MODE_INFRA ||
                ieee->state != IEEE80211_LINKED)){
 
@@ -1841,8 +1841,8 @@ out:
 
 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
 {
-       if(ieee->sta_sleep == 0){
-               if(nl){
+       if (ieee->sta_sleep == 0) {
+               if (nl) {
                        printk("Warning: driver is probably failing to report TX ps error\n");
                        ieee->ps_request_tx_ack(ieee->dev);
                        ieee80211_sta_ps_send_null_frame(ieee, 0);
@@ -1856,7 +1856,7 @@ void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
 
        ieee->sta_sleep = 0;
 
-       if(nl){
+       if (nl) {
                ieee->ps_request_tx_ack(ieee->dev);
                ieee80211_sta_ps_send_null_frame(ieee, 0);
        }
@@ -1870,7 +1870,7 @@ void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
 
        if(ieee->sta_sleep == 2){
                /* Null frame with PS bit set */
-               if(success){
+               if (success) {
                        ieee->sta_sleep = 1;
                        ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
                }
@@ -1881,7 +1881,7 @@ void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
        /* 21112005 - tx again null without PS bit if lost */
        else {
 
-               if((ieee->sta_sleep == 0) && !success){
+               if ((ieee->sta_sleep == 0) && !success) {
                        spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
                        ieee80211_sta_ps_send_null_frame(ieee, 0);
                        spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
@@ -1920,6 +1920,66 @@ static void ieee80211_process_action(struct ieee80211_device *ieee,
        return;
 
 }
+
+static void ieee80211_check_auth_response(struct ieee80211_device *ieee,
+                                         struct sk_buff *skb)
+{
+       /* default support N mode, disable halfNmode */
+       bool bSupportNmode = true, bHalfSupportNmode = false;
+       u16 errcode;
+       u8 *challenge;
+       int chlen = 0;
+       u32 iotAction;
+
+       errcode = auth_parse(skb, &challenge, &chlen);
+       if (!errcode) {
+               if (ieee->open_wep || !challenge) {
+                       ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
+                       ieee->softmac_stats.rx_auth_rs_ok++;
+                       iotAction = ieee->pHTInfo->IOTAction;
+                       if (!(iotAction & HT_IOT_ACT_PURE_N_MODE)) {
+                               if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) {
+                                       /* WEP or TKIP encryption */
+                                       if (IsHTHalfNmodeAPs(ieee)) {
+                                               bSupportNmode = true;
+                                               bHalfSupportNmode = true;
+                                       } else {
+                                               bSupportNmode = false;
+                                               bHalfSupportNmode = false;
+                                       }
+                                       netdev_dbg(ieee->dev, "SEC(%d, %d)\n",
+                                                       bSupportNmode,
+                                                       bHalfSupportNmode);
+                               }
+                       }
+                       /* Dummy wirless mode setting- avoid encryption issue */
+                       if (bSupportNmode) {
+                               /* N mode setting */
+                               ieee->SetWirelessMode(ieee->dev,
+                                               ieee->current_network.mode);
+                       } else {
+                               /* b/g mode setting - TODO */
+                               ieee->SetWirelessMode(ieee->dev, IEEE_G);
+                       }
+
+                       if (ieee->current_network.mode == IEEE_N_24G &&
+                                       bHalfSupportNmode == true) {
+                               netdev_dbg(ieee->dev, "enter half N mode\n");
+                               ieee->bHalfWirelessN24GMode = true;
+                       } else
+                               ieee->bHalfWirelessN24GMode = false;
+
+                       ieee80211_associate_step2(ieee);
+               } else {
+                       ieee80211_auth_challenge(ieee, challenge, chlen);
+               }
+       } else {
+               ieee->softmac_stats.rx_auth_rs_err++;
+               IEEE80211_DEBUG_MGMT("Auth response status code 0x%x", errcode);
+               ieee80211_associate_abort(ieee);
+       }
+}
+
 inline int
 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
                        struct ieee80211_rx_stats *rx_stats, u16 type,
@@ -1927,12 +1987,9 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
 {
        struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
        u16 errcode;
-       u8 *challenge;
-       int chlen=0;
        int aid;
        struct ieee80211_assoc_response_frame *assoc_resp;
 //     struct ieee80211_info_element *info_element;
-       bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
 
        if(!ieee->proto_started)
                return 0;
@@ -1967,7 +2024,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
                                ieee->softmac_stats.rx_ass_ok++;
                                /* station support qos */
                                /* Let the register setting defaultly with Legacy station */
-                               if(ieee->qos_support) {
+                               if (ieee->qos_support) {
                                        assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data;
                                        memset(network, 0, sizeof(*network));
                                        if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
@@ -2013,68 +2070,16 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
 
        case IEEE80211_STYPE_AUTH:
 
-               if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
-                       if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
-                       ieee->iw_mode == IW_MODE_INFRA){
+               if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
+                       if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING
+                               && ieee->iw_mode == IW_MODE_INFRA) {
 
-                                       IEEE80211_DEBUG_MGMT("Received authentication response");
-
-                                       errcode = auth_parse(skb, &challenge, &chlen);
-                                       if (!errcode) {
-                                               if(ieee->open_wep || !challenge){
-                                                       ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
-                                                       ieee->softmac_stats.rx_auth_rs_ok++;
-                                                       if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
-                                                       {
-                                                               if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
-                                                               {
-                                                                                       // WEP or TKIP encryption
-                                                                       if(IsHTHalfNmodeAPs(ieee))
-                                                                       {
-                                                                               bSupportNmode = true;
-                                                                               bHalfSupportNmode = true;
-                                                                       }
-                                                                       else
-                                                                       {
-                                                                               bSupportNmode = false;
-                                                                               bHalfSupportNmode = false;
-                                                                       }
-                                                               printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
-                                                               }
-                                                       }
-                                                       /* Dummy wirless mode setting to avoid encryption issue */
-                                                       if(bSupportNmode) {
-                                                               //N mode setting
-                                                               ieee->SetWirelessMode(ieee->dev, \
-                                                                               ieee->current_network.mode);
-                                                       }else{
-                                                               //b/g mode setting
-                                                               /*TODO*/
-                                                               ieee->SetWirelessMode(ieee->dev, IEEE_G);
-                                                       }
-
-                                                       if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
-                                                       {
-                                                               printk("===============>entern half N mode\n");
-                                                               ieee->bHalfWirelessN24GMode = true;
-                                                       }
-                                                       else
-                                                               ieee->bHalfWirelessN24GMode = false;
-
-                                                       ieee80211_associate_step2(ieee);
-                                               }else{
-                                                       ieee80211_auth_challenge(ieee, challenge, chlen);
-                                               }
-                                       }else{
-                                               ieee->softmac_stats.rx_auth_rs_err++;
-                                               IEEE80211_DEBUG_MGMT("Authentication response status code 0x%x",errcode);
-                                               ieee80211_associate_abort(ieee);
-                                       }
-
-                               }else if (ieee->iw_mode == IW_MODE_MASTER){
-                                       ieee80211_rx_auth_rq(ieee, skb);
-                               }
+                               IEEE80211_DEBUG_MGMT("Received auth response");
+                               ieee80211_check_auth_response(ieee, skb);
+                       } else if (ieee->iw_mode == IW_MODE_MASTER) {
+                               ieee80211_rx_auth_rq(ieee, skb);
                        }
+               }
                break;
 
        case IEEE80211_STYPE_PROBE_REQ:
@@ -2110,27 +2115,26 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
                break;
        default:
                return -1;
-               break;
        }
 
        //dev_kfree_skb_any(skb);
        return 0;
 }
 
-/* following are for a simpler TX queue management.
- * Instead of using netif_[stop/wake]_queue the driver
- * will uses these two function (plus a reset one), that
- * will internally uses the kernel netif_* and takes
- * care of the ieee802.11 fragmentation.
- * So the driver receives a fragment per time and might
- * call the stop function when it want without take care
- * to have enought room to TX an entire packet.
- * This might be useful if each fragment need it's own
- * descriptor, thus just keep a total free memory > than
- * the max fragmentation treshold is not enought.. If the
- * ieee802.11 stack passed a TXB struct then you needed
+/* The following are for a simpler TX queue management.
+ * Instead of using netif_[stop/wake]_queue, the driver
+ * will use these two functions (plus a reset one) that
+ * will internally call the kernel netif_* and take care
+ * of the ieee802.11 fragmentation.
+ * So, the driver receives a fragment at a time and might
+ * call the stop function when it wants, without taking
+ * care to have enough room to TX an entire packet.
+ * This might be useful if each fragment needs its own
+ * descriptor. Thus, just keeping a total free memory > than
+ * the max fragmentation threshold is not enough. If the
+ * ieee802.11 stack passed a TXB struct, then you would need
  * to keep N free descriptors where
- * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
+ * N = MAX_PACKET_SIZE / MIN_FRAG_THRESHOLD.
  * In this way you need just one and the 802.11 stack
  * will take care of buffering fragments and pass them to
  * to the driver later, when it wakes the queue.
@@ -2152,7 +2156,7 @@ void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *
        ieee->stats.tx_bytes += txb->payload_size;
        ieee->stats.tx_packets++;
        tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
-       if(tcb_desc->bMulticast) {
+       if (tcb_desc->bMulticast) {
                ieee->stats.multicast++;
        }
        /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
@@ -2224,7 +2228,7 @@ void ieee80211_reset_queue(struct ieee80211_device *ieee)
 
        spin_lock_irqsave(&ieee->lock, flags);
        init_mgmt_queue(ieee);
-       if (ieee->tx_pending.txb){
+       if (ieee->tx_pending.txb) {
                ieee80211_txb_free(ieee->tx_pending.txb);
                ieee->tx_pending.txb = NULL;
        }
@@ -2246,7 +2250,7 @@ void ieee80211_wake_queue(struct ieee80211_device *ieee)
 
        ieee->queue_stop = 0;
 
-       if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
+       if (ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) {
                while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
 
                        header = (struct ieee80211_hdr_3addr  *) skb->data;
@@ -2265,7 +2269,7 @@ void ieee80211_wake_queue(struct ieee80211_device *ieee)
        if (!ieee->queue_stop && ieee->tx_pending.txb)
                ieee80211_resume_tx(ieee);
 
-       if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
+       if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)) {
                ieee->softmac_stats.swtxawake++;
                netif_wake_queue(ieee->dev);
        }
@@ -2280,7 +2284,7 @@ void ieee80211_stop_queue(struct ieee80211_device *ieee)
        //unsigned long flags;
        //spin_lock_irqsave(&ieee->lock,flags);
 
-       if (! netif_queue_stopped(ieee->dev)){
+       if (!netif_queue_stopped(ieee->dev)) {
                netif_stop_queue(ieee->dev);
                ieee->softmac_stats.swtxstop++;
        }
@@ -2301,7 +2305,7 @@ void ieee80211_start_master_bss(struct ieee80211_device *ieee)
 {
        ieee->assoc_id = 1;
 
-       if (ieee->current_network.ssid_len == 0){
+       if (ieee->current_network.ssid_len == 0) {
                strncpy(ieee->current_network.ssid,
                        IEEE80211_DEFAULT_TX_ESSID,
                        IW_ESSID_MAX_SIZE);
@@ -2325,7 +2329,7 @@ void ieee80211_start_master_bss(struct ieee80211_device *ieee)
 
 static void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
 {
-       if(ieee->raw_tx){
+       if (ieee->raw_tx) {
 
                if (ieee->data_hard_resume)
                        ieee->data_hard_resume(ieee->dev);
@@ -2345,13 +2349,13 @@ static void ieee80211_start_ibss_wq(struct work_struct *work)
         * (abort) this wq (when syncro scanning) before sleeping
         * on the semaphore
         */
-       if(!ieee->proto_started){
+       if (!ieee->proto_started) {
                printk("==========oh driver down return\n");
                return;
        }
        down(&ieee->wx_sem);
 
-       if (ieee->current_network.ssid_len == 0){
+       if (ieee->current_network.ssid_len == 0) {
                strcpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID);
                ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
                ieee->ssid_set = 1;
@@ -2382,7 +2386,7 @@ static void ieee80211_start_ibss_wq(struct work_struct *work)
                ieee80211_start_scan_syncro(ieee);
 
        /* the network definitively is not here.. create a new cell */
-       if (ieee->state == IEEE80211_NOLINK){
+       if (ieee->state == IEEE80211_NOLINK) {
                printk("creating new IBSS cell\n");
                if(!ieee->wap_set)
                        ieee80211_randomize_cell(ieee);
@@ -2456,9 +2460,9 @@ void ieee80211_start_bss(struct ieee80211_device *ieee)
        // Ref: 802.11d 11.1.3.3
        // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
        //
-       if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
+       if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
        {
-               if(! ieee->bGlobalDomain)
+               if (! ieee->bGlobalDomain)
                {
                        return;
                }
@@ -2479,7 +2483,7 @@ void ieee80211_start_bss(struct ieee80211_device *ieee)
         */
        spin_lock_irqsave(&ieee->lock, flags);
 
-       if (ieee->state == IEEE80211_NOLINK){
+       if (ieee->state == IEEE80211_NOLINK) {
                ieee->actscanning = true;
                ieee80211_start_scan(ieee);
        }
@@ -2633,7 +2637,7 @@ void ieee80211_start_protocol(struct ieee80211_device *ieee)
 
        ieee->proto_started = 1;
 
-       if (ieee->current_network.channel == 0){
+       if (ieee->current_network.channel == 0) {
                do{
                        ch++;
                        if (ch > MAX_CHANNEL_NUMBER)
@@ -2719,16 +2723,14 @@ void ieee80211_softmac_init(struct ieee80211_device *ieee)
        ieee->sta_edca_param[2] = 0x005E4342;
        ieee->sta_edca_param[3] = 0x002F3262;
        ieee->aggregation = true;
-       ieee->enable_rx_imm_BA = 1;
+       ieee->enable_rx_imm_BA = true;
        ieee->tx_pending.txb = NULL;
 
-       init_timer(&ieee->associate_timer);
-       ieee->associate_timer.data = (unsigned long)ieee;
-       ieee->associate_timer.function = ieee80211_associate_abort_cb;
+       setup_timer(&ieee->associate_timer, ieee80211_associate_abort_cb,
+                   (unsigned long)ieee);
 
-       init_timer(&ieee->beacon_timer);
-       ieee->beacon_timer.data = (unsigned long) ieee;
-       ieee->beacon_timer.function = ieee80211_send_beacon_cb;
+       setup_timer(&ieee->beacon_timer, ieee80211_send_beacon_cb,
+                   (unsigned long)ieee);
 
        ieee->wq = create_workqueue(DRV_NAME);
 
@@ -3027,12 +3029,11 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
 
                ieee80211_crypt_delayed_deinit(ieee, crypt);
 
-               new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
+               new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
                if (new_crypt == NULL) {
                        ret = -ENOMEM;
                        goto done;
                }
-               memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
                new_crypt->ops = ops;
                if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
                        new_crypt->priv =
@@ -3140,7 +3141,7 @@ SendDisassociation(
                struct ieee80211_network *beacon = &ieee->current_network;
                struct sk_buff *skb;
                skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
-               if (skb){
+               if (skb) {
                                softmac_mgmt_xmit(skb, ieee);
                                //dev_kfree_skb_any(skb);//edit by thomas
                }
@@ -3155,7 +3156,7 @@ int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_poin
        down(&ieee->wx_sem);
        //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
 
-       if (p->length < sizeof(struct ieee_param) || !p->pointer){
+       if (p->length < sizeof(struct ieee_param) || !p->pointer) {
                ret = -EINVAL;
                goto out;
        }
@@ -3210,7 +3211,7 @@ void notify_wx_assoc_event(struct ieee80211_device *ieee)
        if (ieee->state == IEEE80211_LINKED)
                memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
        else
-               memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+               eth_zero_addr(wrqu.ap_addr.sa_data);
        wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
 }
 EXPORT_SYMBOL(notify_wx_assoc_event);
index 644368df634223c06e248d3aa50bc78b061b930d..714fbcace72b1bc12db648f4fb293eccf67d34bc 100644 (file)
@@ -36,7 +36,7 @@ int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info
 
        down(&ieee->wx_sem);
 
-       if(ieee->iw_mode == IW_MODE_INFRA){
+       if (ieee->iw_mode == IW_MODE_INFRA) {
                ret = -EOPNOTSUPP;
                goto out;
        }
@@ -121,7 +121,7 @@ int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
                ieee->state != IEEE80211_LINKED_SCANNING &&
                ieee->wap_set == 0)
 
-               memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+               eth_zero_addr(wrqu->ap_addr.sa_data);
        else
                memcpy(wrqu->ap_addr.sa_data,
                       ieee->current_network.bssid, ETH_ALEN);
@@ -148,12 +148,12 @@ int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
 
        down(&ieee->wx_sem);
        /* use ifconfig hw ether */
-       if (ieee->iw_mode == IW_MODE_MASTER){
+       if (ieee->iw_mode == IW_MODE_MASTER) {
                ret = -1;
                goto out;
        }
 
-       if (temp->sa_family != ARPHRD_ETHER){
+       if (temp->sa_family != ARPHRD_ETHER) {
                ret = -EINVAL;
                goto out;
        }
@@ -345,7 +345,7 @@ void ieee80211_wx_sync_scan_wq(struct work_struct *work)
        ieee->state = IEEE80211_LINKED;
        ieee->link_change(ieee->dev);
        // To prevent the immediately calling watch_dog after scan.
-       if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
+       if (ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
        {
                ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
                ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
@@ -369,7 +369,7 @@ int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info
 
        down(&ieee->wx_sem);
 
-       if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)){
+       if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) {
                ret = -1;
                goto out;
        }
@@ -400,12 +400,12 @@ int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
 
        proto_started = ieee->proto_started;
 
-       if (wrqu->essid.length > IW_ESSID_MAX_SIZE){
+       if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
                ret= -E2BIG;
                goto out;
        }
 
-       if (ieee->iw_mode == IW_MODE_MONITOR){
+       if (ieee->iw_mode == IW_MODE_MONITOR) {
                ret= -1;
                goto out;
        }
@@ -469,9 +469,9 @@ EXPORT_SYMBOL(ieee80211_wx_get_mode);
        printk(KERN_INFO"raw TX is %s\n",
              ieee->raw_tx ? "enabled" : "disabled");
 
-       if(ieee->iw_mode == IW_MODE_MONITOR)
+       if (ieee->iw_mode == IW_MODE_MONITOR)
        {
-               if(prev == 0 && ieee->raw_tx){
+               if (prev == 0 && ieee->raw_tx) {
                        if (ieee->data_hard_resume)
                                ieee->data_hard_resume(ieee->dev);
 
@@ -522,7 +522,7 @@ int ieee80211_wx_set_power(struct ieee80211_device *ieee,
        int ret = 0;
        down(&ieee->wx_sem);
 
-       if (wrqu->power.disabled){
+       if (wrqu->power.disabled) {
                ieee->ps = IEEE80211_PS_DISABLED;
                goto exit;
        }
@@ -572,7 +572,7 @@ int ieee80211_wx_get_power(struct ieee80211_device *ieee,
 {
        down(&ieee->wx_sem);
 
-       if(ieee->ps == IEEE80211_PS_DISABLED){
+       if (ieee->ps == IEEE80211_PS_DISABLED) {
                wrqu->power.disabled = 1;
                goto exit;
        }
index fca73c7c9fbe911c1f6d7dc3cf8824b1939e98d0..9f68c652fb2bf8b0807880a917135f1b338e0f26 100644 (file)
@@ -32,7 +32,6 @@
 ******************************************************************************/
 
 #include <linux/compiler.h>
-//#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/if_arp.h>
 #include <linux/in6.h>
@@ -554,16 +553,16 @@ static void ieee80211_txrate_selectmode(struct ieee80211_device *ieee,
 #ifdef TO_DO_LIST
        if(!IsDataFrame(pFrame))
        {
-               pTcb->bTxDisableRateFallBack = TRUE;
-               pTcb->bTxUseDriverAssingedRate = TRUE;
+               pTcb->bTxDisableRateFallBack = true;
+               pTcb->bTxUseDriverAssingedRate = true;
                pTcb->RATRIndex = 7;
                return;
        }
 
        if(pMgntInfo->ForcedDataRate!= 0)
        {
-               pTcb->bTxDisableRateFallBack = TRUE;
-               pTcb->bTxUseDriverAssingedRate = TRUE;
+               pTcb->bTxDisableRateFallBack = true;
+               pTcb->bTxUseDriverAssingedRate = true;
                return;
        }
 #endif
index 1b4623c3f95ef3c0272c1b3118eb56db4c3dc204..618d2cbc049ec0118d5bb2ccb24fdc345ed6f85f 100644 (file)
@@ -46,14 +46,14 @@ static u8 TxTsDeleteBA(struct ieee80211_device *ieee, PTX_TS_RECORD pTxTs)
        u8                      bSendDELBA = false;
 
        // Delete pending BA
-       if(pPendingBa->bValid)
+       if (pPendingBa->bValid)
        {
                DeActivateBAEntry(ieee, pPendingBa);
                bSendDELBA = true;
        }
 
        // Delete admitted BA
-       if(pAdmittedBa->bValid)
+       if (pAdmittedBa->bValid)
        {
                DeActivateBAEntry(ieee, pAdmittedBa);
                bSendDELBA = true;
@@ -74,7 +74,7 @@ static u8 RxTsDeleteBA(struct ieee80211_device *ieee, PRX_TS_RECORD pRxTs)
        PBA_RECORD              pBa = &pRxTs->RxAdmittedBARecord;
        u8                      bSendDELBA = false;
 
-       if(pBa->bValid)
+       if (pBa->bValid)
        {
                DeActivateBAEntry(ieee, pBa);
                bSendDELBA = true;
@@ -363,7 +363,7 @@ 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) ||
+       if ((ieee->current_network.qos_data.active == 0) ||
                (ieee->pHTInfo->bCurrentHTSupport == false)) //||
        //      (ieee->pStaQos->bEnableRxImmBA == false)        )
        {
@@ -373,7 +373,7 @@ int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb)
        }
        // Search for related traffic stream.
        // If there is no matched TS, reject the ADDBA request.
-       if(     !GetTs(
+       if (!GetTs(
                        ieee,
                        (PTS_COMMON_INFO *)(&pTS),
                        dst,
@@ -390,7 +390,7 @@ int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb)
        // We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl...
        // I want to check StartSeqCtrl to make sure when we start aggregation!!!
        //
-       if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
+       if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
        {
                rc = ADDBA_STATUS_INVALID_PARAM;
                IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __func__);
@@ -522,7 +522,7 @@ int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb)
                // We can compare the value of BA parameter set that Peer returned and Self sent.
                // If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
                //
-               if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
+               if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
                {
                        // Since this is a kind of ADDBA failed, we delay next ADDBA process.
                        pTS->bAddBaReqDelayed = true;
@@ -582,7 +582,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb)
                return -1;
        }
 
-       if(ieee->current_network.qos_data.active == 0 ||
+       if (ieee->current_network.qos_data.active == 0 ||
                ieee->pHTInfo->bCurrentHTSupport == false )
        {
                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);
@@ -600,7 +600,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb)
        {
                PRX_TS_RECORD   pRxTs;
 
-               if!GetTs(
+               if (!GetTs(
                                ieee,
                                (PTS_COMMON_INFO *)&pRxTs,
                                dst,
@@ -618,7 +618,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb)
        {
                PTX_TS_RECORD   pTxTs;
 
-               if(!GetTs(
+               if (!GetTs(
                        ieee,
                        (PTS_COMMON_INFO *)&pTxTs,
                        dst,
index e60d926a3973f42445ccb4437f75a336aacdce11..c2588f80625b99e23c9aaf519e35ef22f62c1746 100644 (file)
@@ -471,12 +471,10 @@ static bool HTIOTActIsDisableMCS15(struct ieee80211_device *ieee)
 static bool HTIOTActIsDisableMCSTwoSpatialStream(struct ieee80211_device *ieee,
                                                 u8 *PeerMacAddr)
 {
-       bool retValue = false;
-
 #ifdef TODO
        // Apply for 819u only
 #endif
-       return retValue;
+       return false;
 }
 
 /********************************************************************************************************************
@@ -488,11 +486,8 @@ static bool HTIOTActIsDisableMCSTwoSpatialStream(struct ieee80211_device *ieee,
   * *****************************************************************************************************************/
 static u8 HTIOTActIsDisableEDCATurbo(struct ieee80211_device *ieee,
                                     u8 *PeerMacAddr)
-{
-       u8      retValue = false;       // default enable EDCA Turbo mode.
-       // Set specific EDCA parameter for different AP in DM handler.
-
-       return retValue;
+{      /* default enable EDCA Turbo mode. */
+       return false;
 }
 
 /********************************************************************************************************************
@@ -508,7 +503,7 @@ static u8 HTIOTActIsMgntUseCCK6M(struct ieee80211_network *network)
        // 2008/01/25 MH Judeg if we need to use OFDM to sned MGNT frame for broadcom AP.
        // 2008/01/28 MH We must prevent that we select null bssid to link.
 
-       if(network->broadcom_cap_exist)
+       if (network->broadcom_cap_exist)
        {
                retValue = 1;
        }
@@ -625,7 +620,7 @@ void HTConstructCapabilityElement(struct ieee80211_device *ieee, u8 *posHTCap, u
 
        // 2008.06.12
        // For RTL819X, if pairwisekey = wep/tkip, ap is ralink, we support only MCS0~7.
-       if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
+       if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
        {
                int i;
                for(i = 1; i< 16; i++)
@@ -752,7 +747,7 @@ void HTConstructRT2RTAggElement(struct ieee80211_device *ieee, u8 *posRT2RTAgg,
        *posRT2RTAgg++ = 0x01;
        *posRT2RTAgg = 0x10;//*posRT2RTAgg = 0x02;
 
-       if(ieee->bSupportRemoteWakeUp) {
+       if (ieee->bSupportRemoteWakeUp) {
                *posRT2RTAgg |= 0x08;//RT_HT_CAP_USE_WOW;
        }
 
@@ -879,17 +874,17 @@ u8 HTGetHighestMCSRate(struct ieee80211_device *ieee, u8 *pMCSRateSet, u8 *pMCSF
 
        for(i = 0; i < 16; i++)
        {
-               if(availableMcsRate[i] != 0)
+               if (availableMcsRate[i] != 0)
                {
                        bitMap = availableMcsRate[i];
                        for(j = 0; j < 8; j++)
                        {
-                               if((bitMap%2) != 0)
+                               if ((bitMap%2) != 0)
                                {
                                        if(HTMcsToDataRate(ieee, (8*i+j)) > HTMcsToDataRate(ieee, mcsRate))
                                                mcsRate = (8*i+j);
                                }
-                               bitMap = bitMap>>1;
+                               bitMap >>= 1;
                        }
                }
        }
@@ -1067,7 +1062,7 @@ void HTOnAssocRsp(struct ieee80211_device *ieee)
 
        // Lanhsin: mark for tmp to avoid deauth by ap from  s3
        //if(memcmp(pMgntInfo->Bssid, NETGEAR834Bv2_BROADCOM, 3)==0)
-       if(0)
+       if (0)
                {
 
                        pHTInfo->bCurrentAMPDUEnable = false;
@@ -1303,7 +1298,7 @@ void HTUpdateSelfAndPeerSetting(struct ieee80211_device *ieee,    struct ieee80211_
 //     PHT_CAPABILITY_ELE              pPeerHTCap = (PHT_CAPABILITY_ELE)pNetwork->bssht.bdHTCapBuf;
        PHT_INFORMATION_ELE             pPeerHTInfo = (PHT_INFORMATION_ELE)pNetwork->bssht.bdHTInfoBuf;
 
-       if(pHTInfo->bCurrentHTSupport)
+       if (pHTInfo->bCurrentHTSupport)
        {
                //
                // Config current operation mode.
@@ -1328,7 +1323,7 @@ EXPORT_SYMBOL(HTUpdateSelfAndPeerSetting);
 ********************************************************************************************************************/
 u8 HTCCheck(struct ieee80211_device *ieee, u8 *pFrame)
 {
-       if(ieee->pHTInfo->bCurrentHTSupport)
+       if (ieee->pHTInfo->bCurrentHTSupport)
        {
                if ((IsQoSDataFrame(pFrame) && Frame_Order(pFrame)) == 1) {
                        IEEE80211_DEBUG(IEEE80211_DL_HT, "HT CONTROL FILED EXIST!!\n");
@@ -1357,7 +1352,7 @@ void HTSetConnectBwMode(struct ieee80211_device *ieee, HT_CHANNEL_WIDTH   Bandwidt
 //             return;
 
 //     spin_lock_irqsave(&(ieee->bw_spinlock), flags);
-       if(pHTInfo->bSwBwInProgress) {
+       if (pHTInfo->bSwBwInProgress) {
 //             spin_unlock_irqrestore(&(ieee->bw_spinlock), flags);
                return;
        }
index 7ed7243b1fb07e69b5edfe7e559e955d1c01a880..873969c9f226f74d8826d5f810c0614ea1d987ff 100644 (file)
@@ -1,14 +1,14 @@
 #ifndef _TSTYPE_H_
 #define _TSTYPE_H_
 #include "rtl819x_Qos.h"
-#define TS_SETUP_TIMEOUT       60  // In millisecond
+#define TS_SETUP_TIMEOUT       60  /*  In millisecond */
 #define TS_INACT_TIMEOUT       60
 #define TS_ADDBA_DELAY         60
 
 #define TOTAL_TS_NUM           16
 #define TCLAS_NUM              4
 
-// This define the Tx/Rx directions
+/*  This define the Tx/Rx directions */
 typedef enum _TR_SELECT {
        TX_DIR = 0,
        RX_DIR = 1,
@@ -28,9 +28,9 @@ typedef struct _TS_COMMON_INFO{
 typedef struct _TX_TS_RECORD{
        TS_COMMON_INFO          TsCommonInfo;
        u16                             TxCurSeq;
-       BA_RECORD                       TxPendingBARecord;      // For BA Originator
-       BA_RECORD                       TxAdmittedBARecord;     // For BA Originator
-//     QOS_DL_RECORD           DLRecord;
+       BA_RECORD                       TxPendingBARecord;      /*  For BA Originator */
+       BA_RECORD                       TxAdmittedBARecord;     /*  For BA Originator */
+/*     QOS_DL_RECORD           DLRecord; */
        u8                              bAddBaReqInProgress;
        u8                              bAddBaReqDelayed;
        u8                              bUsingBa;
@@ -44,11 +44,11 @@ typedef struct _RX_TS_RECORD {
        u16                             RxTimeoutIndicateSeq;
        struct list_head                RxPendingPktList;
        struct timer_list               RxPktPendingTimer;
-       BA_RECORD                       RxAdmittedBARecord;      // For BA Recipient
+       BA_RECORD                       RxAdmittedBARecord;      /*  For BA Recipient */
        u16                             RxLastSeqNum;
        u8                              RxLastFragNum;
        u8                              num;
-//     QOS_DL_RECORD           DLRecord;
+/*     QOS_DL_RECORD           DLRecord; */
 } RX_TS_RECORD, *PRX_TS_RECORD;
 
 
index acaa723817e709dd574ffeedd89bb980d0f27a2f..ea92fdebe5a748a9f762f482f97ad706d428271e 100644 (file)
@@ -156,26 +156,16 @@ void TSInitialize(struct ieee80211_device *ieee)
                pTxTS->num = count;
                // The timers for the operation of Traffic Stream and Block Ack.
                // DLS related timer will be add here in the future!!
-               init_timer(&pTxTS->TsCommonInfo.SetupTimer);
-               pTxTS->TsCommonInfo.SetupTimer.data = (unsigned long)pTxTS;
-               pTxTS->TsCommonInfo.SetupTimer.function = TsSetupTimeOut;
-
-               init_timer(&pTxTS->TsCommonInfo.InactTimer);
-               pTxTS->TsCommonInfo.InactTimer.data = (unsigned long)pTxTS;
-               pTxTS->TsCommonInfo.InactTimer.function = TsInactTimeout;
-
-               init_timer(&pTxTS->TsAddBaTimer);
-               pTxTS->TsAddBaTimer.data = (unsigned long)pTxTS;
-               pTxTS->TsAddBaTimer.function = TsAddBaProcess;
-
-               init_timer(&pTxTS->TxPendingBARecord.Timer);
-               pTxTS->TxPendingBARecord.Timer.data = (unsigned long)pTxTS;
-               pTxTS->TxPendingBARecord.Timer.function = BaSetupTimeOut;
-
-               init_timer(&pTxTS->TxAdmittedBARecord.Timer);
-               pTxTS->TxAdmittedBARecord.Timer.data = (unsigned long)pTxTS;
-               pTxTS->TxAdmittedBARecord.Timer.function = TxBaInactTimeout;
-
+               setup_timer(&pTxTS->TsCommonInfo.SetupTimer, TsSetupTimeOut,
+                           (unsigned long)pTxTS);
+               setup_timer(&pTxTS->TsCommonInfo.InactTimer, TsInactTimeout,
+                           (unsigned long)pTxTS);
+               setup_timer(&pTxTS->TsAddBaTimer, TsAddBaProcess,
+                           (unsigned long)pTxTS);
+               setup_timer(&pTxTS->TxPendingBARecord.Timer, BaSetupTimeOut,
+                           (unsigned long)pTxTS);
+               setup_timer(&pTxTS->TxAdmittedBARecord.Timer,
+                           TxBaInactTimeout, (unsigned long)pTxTS);
                ResetTxTsEntry(pTxTS);
                list_add_tail(&pTxTS->TsCommonInfo.List, &ieee->Tx_TS_Unused_List);
                pTxTS++;
@@ -189,23 +179,14 @@ void TSInitialize(struct ieee80211_device *ieee)
        {
                pRxTS->num = count;
                INIT_LIST_HEAD(&pRxTS->RxPendingPktList);
-
-               init_timer(&pRxTS->TsCommonInfo.SetupTimer);
-               pRxTS->TsCommonInfo.SetupTimer.data = (unsigned long)pRxTS;
-               pRxTS->TsCommonInfo.SetupTimer.function = TsSetupTimeOut;
-
-               init_timer(&pRxTS->TsCommonInfo.InactTimer);
-               pRxTS->TsCommonInfo.InactTimer.data = (unsigned long)pRxTS;
-               pRxTS->TsCommonInfo.InactTimer.function = TsInactTimeout;
-
-               init_timer(&pRxTS->RxAdmittedBARecord.Timer);
-               pRxTS->RxAdmittedBARecord.Timer.data = (unsigned long)pRxTS;
-               pRxTS->RxAdmittedBARecord.Timer.function = RxBaInactTimeout;
-
-               init_timer(&pRxTS->RxPktPendingTimer);
-               pRxTS->RxPktPendingTimer.data = (unsigned long)pRxTS;
-               pRxTS->RxPktPendingTimer.function = RxPktPendingTimeout;
-
+               setup_timer(&pRxTS->TsCommonInfo.SetupTimer, TsSetupTimeOut,
+                           (unsigned long)pRxTS);
+               setup_timer(&pRxTS->TsCommonInfo.InactTimer, TsInactTimeout,
+                           (unsigned long)pRxTS);
+               setup_timer(&pRxTS->RxAdmittedBARecord.Timer,
+                           RxBaInactTimeout, (unsigned long)pRxTS);
+               setup_timer(&pRxTS->RxPktPendingTimer, RxPktPendingTimeout,
+                           (unsigned long)pRxTS);
                ResetRxTsEntry(pRxTS);
                list_add_tail(&pRxTS->TsCommonInfo.List, &ieee->Rx_TS_Unused_List);
                pRxTS++;
@@ -288,7 +269,7 @@ static PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee,
        //for(dir = DIR_UP; dir <= DIR_BI_DIR; dir++)
        for(dir = 0; dir <= DIR_BI_DIR; dir++)
        {
-               if(search_dir[dir] ==false )
+               if (!search_dir[dir])
                        continue;
                list_for_each_entry(pRet, psearch_list, List){
        //              IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:%pM, TID:%d, dir:%d\n", pRet->Addr, pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
@@ -400,8 +381,7 @@ bool GetTs(
        }
        else
        {
-               if(bAddNewTs == false)
-               {
+               if (!bAddNewTs) {
                        IEEE80211_DEBUG(IEEE80211_DL_TS, "add new TS failed(tid:%d)\n", UP);
                        return false;
                }
index 1868352d3789ea784770e21ee3292bebf2fdcb7e..e00032947e0fc5aa893cb395bcbeacf1cda73512 100644 (file)
@@ -225,7 +225,7 @@ void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel)
        struct r8192_priv *priv = ieee80211_priv(dev);
        TxAGC = powerlevel;
 
-       if (priv->bDynamicTxLowPower == TRUE) {
+       if (priv->bDynamicTxLowPower) {
                if (priv->CustomerID == RT_CID_819x_Netcore)
                        TxAGC = 0x22;
                else
@@ -275,7 +275,7 @@ void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel)
                        priv->Pwr_Track = writeVal_tmp;
                }
 
-               if (priv->bDynamicTxHighPower == TRUE) {
+               if (priv->bDynamicTxHighPower) {
                        /*Add by Jacken 2008/03/06
                         *Emily, 20080613. Set low tx power for both MCS and legacy OFDM
                         */
index fa6dd37d85e6680d76aaa5909f9f9040d7930d7a..6e5662f7951c9ffd96c875173522eaec7e17e1ca 100644 (file)
@@ -13,8 +13,9 @@
 #ifndef RTL8225H
 #define RTL8225H
 
-#define RTL819X_TOTAL_RF_PATH 2 //for 8192U
-extern void PHY_SetRF8256Bandwidth(struct net_device *dev , HT_CHANNEL_WIDTH Bandwidth);
+#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);
index c9d8c102cca39d085143572ed8b69a2a883abdec..6c2e438c9af498fbcc63e9d251d1903d7e8452ee 100644 (file)
@@ -40,8 +40,6 @@
 #define RTL8192U
 #define RTL819xU_MODULE_NAME "rtl819xU"
 /* HW security */
-#define FALSE 0
-#define TRUE 1
 #define MAX_KEY_LEN     61
 #define KEY_BUF_SIZE    5
 
index e031a253e2ae3dd5d40550b5f2f80e53afff1ca2..a4795afeeb9ca619190802d744b6c49be3e7dd8d 100644 (file)
@@ -408,9 +408,8 @@ inline void force_pci_posting(struct net_device *dev)
 }
 
 static struct net_device_stats *rtl8192_stats(struct net_device *dev);
-void rtl8192_commit(struct net_device *dev);
-void rtl8192_restart(struct work_struct *work);
-void watch_dog_timer_callback(unsigned long data);
+static void rtl8192_restart(struct work_struct *work);
+static void watch_dog_timer_callback(unsigned long data);
 
 /****************************************************************************
  *   -----------------------------PROCFS STUFF-------------------------
@@ -827,7 +826,6 @@ void rtl8192_rtx_disable(struct net_device *dev)
                netdev_warn(dev, "skb_queue not empty\n");
 
        skb_queue_purge(&priv->skb_queue);
-       return;
 }
 
 inline u16 ieeerate2rtlrate(int rate)
@@ -966,8 +964,6 @@ static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
        ret = rtl8192_tx(dev, skb);
 
        spin_unlock_irqrestore(&priv->tx_lock, flags);
-
-       return;
 }
 
 /* This is a rough attempt to TX a frame
@@ -1766,7 +1762,7 @@ void rtl8192_usb_deleteendpoints(struct net_device *dev)
 }
 #endif
 
-extern void rtl8192_update_ratr_table(struct net_device *dev);
+static void rtl8192_update_ratr_table(struct net_device *dev);
 static void rtl8192_link_change(struct net_device *dev)
 {
        struct r8192_priv *priv = ieee80211_priv(dev);
@@ -1971,7 +1967,7 @@ static int rtl8192_handle_assoc_response(struct net_device *dev,
 }
 
 
-void rtl8192_update_ratr_table(struct net_device *dev)
+static void rtl8192_update_ratr_table(struct net_device *dev)
 {
        struct r8192_priv *priv = ieee80211_priv(dev);
        struct ieee80211_device *ieee = priv->ieee80211;
@@ -2067,7 +2063,6 @@ static void rtl8192_refresh_supportrate(struct r8192_priv *priv)
                memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
        else
                memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
-       return;
 }
 
 static u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
@@ -2078,10 +2073,10 @@ static u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
        case RF_8225:
        case RF_8256:
        case RF_PSEUDO_11N:
-               ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
+               ret = WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B;
                break;
        case RF_8258:
-               ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
+               ret = WIRELESS_MODE_A|WIRELESS_MODE_N_5G;
                break;
        default:
                ret = WIRELESS_MODE_B;
@@ -2143,7 +2138,7 @@ static void rtl8192_init_priv_variable(struct net_device *dev)
        //for silent reset
        priv->IrpPendingCount = 1;
        priv->ResetProgress = RESET_TYPE_NORESET;
-       priv->bForcedSilentReset = 0;
+       priv->bForcedSilentReset = false;
        priv->bDisableNormalResetCheck = false;
        priv->force_reset = false;
 
@@ -2247,9 +2242,9 @@ static void rtl8192_init_priv_lock(struct r8192_priv *priv)
        mutex_init(&priv->mutex);
 }
 
-extern  void    rtl819x_watchdog_wqcallback(struct work_struct *work);
+static void rtl819x_watchdog_wqcallback(struct work_struct *work);
 
-void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
+static void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
 //init tasklet and wait_queue here. only 2.6 above kernel is considered
 #define DRV_NAME "wlan0"
 static void rtl8192_init_priv_task(struct net_device *dev)
@@ -2310,11 +2305,11 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
        }
 
        if (bLoad_From_EEPOM) {
-               tmpValue = eprom_read(dev, (EEPROM_VID>>1));
+               tmpValue = eprom_read(dev, EEPROM_VID>>1);
                priv->eeprom_vid = endian_swap(&tmpValue);
-               priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1));
-               tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1));
-               priv->eeprom_ChannelPlan = ((tmpValue&0xff00)>>8);
+               priv->eeprom_pid = eprom_read(dev, EEPROM_PID>>1);
+               tmpValue = eprom_read(dev, EEPROM_ChannelPlan>>1);
+               priv->eeprom_ChannelPlan = (tmpValue & 0xff00)>>8;
                priv->btxpowerdata_readfromEEPORM = true;
                priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8;
        } else {
@@ -2397,7 +2392,8 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
                        }
                } else if (priv->EEPROM_Def_Ver == 1) {
                        if (bLoad_From_EEPOM) {
-                               tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1));
+                               tmpValue = eprom_read(dev,
+                                               EEPROM_TxPwIndex_CCK_V1 >> 1);
                                tmpValue = (tmpValue & 0xff00) >> 8;
                        } else {
                                tmpValue = 0x10;
@@ -2410,7 +2406,8 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
                                tmpValue = 0x1010;
                        *((u16 *)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue;
                        if (bLoad_From_EEPOM)
-                               tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1));
+                               tmpValue = eprom_read(dev,
+                                       EEPROM_TxPwIndex_OFDM_24G_V1 >> 1);
                        else
                                tmpValue = 0x1010;
                        *((u16 *)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue;
@@ -2453,7 +2450,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
                // Antenna B gain offset to antenna A, bit0~3
                priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf);
                // Antenna C gain offset to antenna A, bit4~7
-               priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4);
+               priv->AntennaTxPwDiff[1] = (priv->EEPROMTxPowerDiff & 0xf0)>>4;
                // CrystalCap, bit12~15
                priv->CrystalCap = priv->EEPROMCrystalCap;
                // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
@@ -2505,7 +2502,6 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
        //we need init DIG RATR table here again.
 
        RT_TRACE(COMP_EPROM, "<===========%s()\n", __func__);
-       return;
 }
 
 static short rtl8192_get_channel_map(struct net_device *dev)
@@ -2547,9 +2543,8 @@ static short rtl8192_init(struct net_device *dev)
        rtl8192_read_eeprom_info(dev);
        rtl8192_get_channel_map(dev);
        init_hal_dm(dev);
-       init_timer(&priv->watch_dog_timer);
-       priv->watch_dog_timer.data = (unsigned long)dev;
-       priv->watch_dog_timer.function = watch_dog_timer_callback;
+       setup_timer(&priv->watch_dog_timer, watch_dog_timer_callback,
+                   (unsigned long)dev);
        if (rtl8192_usb_initendpoints(dev) != 0) {
                DMESG("Endopoints initialization failed");
                return -ENOMEM;
@@ -2686,7 +2681,7 @@ static bool rtl8192_adapter_start(struct net_device *dev)
 
        read_nic_dword(dev, CPU_GEN, &dwRegRead);
        if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK)
-               dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
+               dwRegRead = (dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET;
        else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK)
                dwRegRead |= CPU_CCK_LOOPBACK;
        else
@@ -2767,7 +2762,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 == true) { /* 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
@@ -2814,15 +2809,15 @@ static bool rtl8192_adapter_start(struct net_device *dev)
                u8 tmpvalue;
                read_nic_byte(dev, 0x301, &tmpvalue);
                if (tmpvalue == 0x03) {
-                       priv->bDcut = TRUE;
+                       priv->bDcut = true;
                        RT_TRACE(COMP_POWER_TRACKING, "D-cut\n");
                } else {
-                       priv->bDcut = FALSE;
+                       priv->bDcut = false;
                        RT_TRACE(COMP_POWER_TRACKING, "C-cut\n");
                }
                dm_initialize_txpower_tracking(dev);
 
-               if (priv->bDcut == TRUE) {
+               if (priv->bDcut) {
                        u32 i, TempCCk;
                        u32 tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
                        for (i = 0; i < TxBBGainTableLength; i++) {
@@ -2874,11 +2869,11 @@ static bool HalTxCheckStuck819xUsb(struct net_device *dev)
 {
        struct r8192_priv *priv = ieee80211_priv(dev);
        u16             RegTxCounter;
-       bool            bStuck = FALSE;
+       bool            bStuck = false;
        read_nic_word(dev, 0x128, &RegTxCounter);
        RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n", __func__, RegTxCounter, priv->TxCounter);
        if (priv->TxCounter == RegTxCounter)
-               bStuck = TRUE;
+               bStuck = true;
 
        priv->TxCounter = RegTxCounter;
 
@@ -2920,7 +2915,7 @@ static bool HalRxCheckStuck819xUsb(struct net_device *dev)
 {
        u16     RegRxCounter;
        struct r8192_priv *priv = ieee80211_priv(dev);
-       bool bStuck = FALSE;
+       bool bStuck = false;
        static u8       rx_chk_cnt;
        read_nic_word(dev, 0x130, &RegRxCounter);
        RT_TRACE(COMP_RESET, "%s(): RegRxCounter is %d,RxCounter is %d\n", __func__, RegRxCounter, priv->RxCounter);
@@ -2951,7 +2946,7 @@ static bool HalRxCheckStuck819xUsb(struct net_device *dev)
        }
 
        if (priv->RxCounter == RegRxCounter)
-               bStuck = TRUE;
+               bStuck = true;
 
        priv->RxCounter = RegRxCounter;
 
@@ -2961,10 +2956,10 @@ static bool HalRxCheckStuck819xUsb(struct net_device *dev)
 static RESET_TYPE RxCheckStuck(struct net_device *dev)
 {
        struct r8192_priv *priv = ieee80211_priv(dev);
-       bool        bRxCheck = FALSE;
+       bool        bRxCheck = false;
 
        if (priv->IrpPendingCount > 1)
-               bRxCheck = TRUE;
+               bRxCheck = true;
 
        if (bRxCheck) {
                if (HalRxCheckStuck819xUsb(dev)) {
@@ -3021,9 +3016,9 @@ static RESET_TYPE rtl819x_ifcheck_resetornot(struct net_device *dev)
 
 }
 
-void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
-int _rtl8192_up(struct net_device *dev);
-int rtl8192_close(struct net_device *dev);
+static void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
+static int _rtl8192_up(struct net_device *dev);
+static int rtl8192_close(struct net_device *dev);
 
 
 
@@ -3642,7 +3637,7 @@ static u8 HwRateToMRate90(bool bIsHT, u8 rate)
                                ret_rate = MGN_MCS15;
                                break;
                        case DESC90_RATEMCS32:
-                               ret_rate = (0x80|0x20);
+                               ret_rate = 0x80|0x20;
                                break;
 
                        default:
@@ -4038,7 +4033,7 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
 
                if (!priv->bCckHighPower) {
                        report = pcck_buf->cck_agc_rpt & 0xc0;
-                       report = report>>6;
+                       report >>= 6;
                        switch (report) {
                                //Fixed by Jacken from Bryant 2008-03-20
                                //Original value is -38 , -26 , -14 , -2
@@ -4058,7 +4053,7 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
                        }
                } else {
                        report = pcck_buf->cck_agc_rpt & 0x60;
-                       report = report>>5;
+                       report >>= 5;
                        switch (report) {
                        case 0x3:
                                rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
@@ -4208,7 +4203,7 @@ static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
        struct net_device *dev = info->dev;
        struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
        bool bpacket_match_bssid, bpacket_toself;
-       bool bPacketBeacon = FALSE, bToSelfBA = FALSE;
+       bool bPacketBeacon = false, bToSelfBA = false;
        static struct ieee80211_rx_stats  previous_stats;
        struct ieee80211_hdr_3addr *hdr;//by amy
        u16 fc, type;
@@ -4227,9 +4222,9 @@ static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
        praddr = hdr->addr1;
 
        /* Check if the received packet is acceptable. */
-       bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
+       bpacket_match_bssid = (IEEE80211_FTYPE_CTL != type) &&
                               (eqMacAddr(priv->ieee80211->current_network.bssid,  (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
-                              && (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV));
+                              && (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV);
        bpacket_toself =  bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
 
        if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BEACON)
@@ -4474,13 +4469,10 @@ static void query_rxdesc_status(struct sk_buff *skb,
                skb_pull(skb, stats->RxBufShift + stats->RxDrvInfoSize);
        }
 
-       /* for debug 2008.5.29 */
-
-       //added by vivi, for MP, 20080108
-       stats->RxIs40MHzPacket = driver_info->BW;
-       if (stats->RxDrvInfoSize != 0)
+       if (driver_info) {
+               stats->RxIs40MHzPacket = driver_info->BW;
                TranslateRxSignalStuff819xUsb(skb, stats, driver_info);
-
+       }
 }
 
 static void rtl8192_rx_nomal(struct sk_buff *skb)
index ee6b936efef2e32702baf1e5bdeafb3b38283789..12dd19e1159bd4d9c1e7d0be971d6affebedef31 100644 (file)
@@ -36,11 +36,12 @@ static u32 edca_setting_UL[HT_IOT_PEER_MAX] = {
 
 /*------------------------Define global variable-----------------------------*/
 /* Debug variable ? */
-dig_t  dm_digtable;
+struct dig dm_digtable;
 /* Store current software write register content for MAC PHY. */
 u8             dm_shadow[16][256] = { {0} };
 /* For Dynamic Rx Path Selection by Signal Strength */
-DRxPathSel     DM_RxPathSelTable;
+struct dynamic_rx_path_sel DM_RxPathSelTable;
+
 /*------------------------Define global variable-----------------------------*/
 
 
@@ -502,7 +503,7 @@ static u8   CCKSwingTable_Ch14[CCK_Table_length][8] = {
 static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
 {
        struct r8192_priv *priv = ieee80211_priv(dev);
-       bool                                            bHighpowerstate, viviflag = FALSE;
+       bool                                            bHighpowerstate, viviflag = false;
        DCMD_TXCMD_T                    tx_cmd;
        u8                                              powerlevelOFDM24G;
        int                                             i = 0, j = 0, k = 0;
@@ -558,13 +559,13 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
                        /* check if the report value is right */
                        for (k = 0; k < 5; k++) {
                                if (tmp_report[k] <= 20) {
-                                       viviflag = TRUE;
+                                       viviflag = true;
                                        break;
                                }
                        }
-                       if (viviflag == TRUE) {
+                       if (viviflag == true) {
                                write_nic_byte(dev, 0x1ba, 0);
-                               viviflag = FALSE;
+                               viviflag = false;
                                RT_TRACE(COMP_POWER_TRACKING, "we filtered the data\n");
                                for (k = 0; k < 5; k++)
                                        tmp_report[k] = 0;
@@ -587,7 +588,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
                                delta = TSSI_13dBm - Avg_TSSI_Meas_from_driver;
 
                        if (delta <= E_FOR_TX_POWER_TRACK) {
-                               priv->ieee80211->bdynamic_txpower_enable = TRUE;
+                               priv->ieee80211->bdynamic_txpower_enable = true;
                                write_nic_byte(dev, 0x1ba, 0);
                                RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n");
                                RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
@@ -624,10 +625,10 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
 
                        if (priv->cck_present_attentuation > -1 && priv->cck_present_attentuation < 23) {
                                if (priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) {
-                                       priv->bcck_in_ch14 = TRUE;
+                                       priv->bcck_in_ch14 = true;
                                        dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
                                } else if (priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) {
-                                       priv->bcck_in_ch14 = FALSE;
+                                       priv->bcck_in_ch14 = false;
                                        dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
                                } else
                                        dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
@@ -638,7 +639,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
                        RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation);
 
                        if (priv->cck_present_attentuation_difference <= -12 || priv->cck_present_attentuation_difference >= 24) {
-                               priv->ieee80211->bdynamic_txpower_enable = TRUE;
+                               priv->ieee80211->bdynamic_txpower_enable = true;
                                write_nic_byte(dev, 0x1ba, 0);
                                RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n");
                                return;
@@ -651,7 +652,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
                        break;
                }
        }
-       priv->ieee80211->bdynamic_txpower_enable = TRUE;
+       priv->ieee80211->bdynamic_txpower_enable = true;
        write_nic_byte(dev, 0x1ba, 0);
 }
 
@@ -684,7 +685,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
                                break;
                        }
                }
-               priv->btxpower_trackingInit = TRUE;
+               priv->btxpower_trackingInit = true;
                /*pHalData->TXPowercount = 0;*/
                return;
        }
@@ -717,7 +718,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
                if (tmpCCK40Mindex >= CCK_Table_length)
                        tmpCCK40Mindex = CCK_Table_length-1;
        } else {
-               tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]);
+               tmpval = (u8)tmpRegA - priv->ThermalMeter[0];
 
                if (tmpval >= 6) /* higher temperature */
                        tmpOFDMindex = tmpCCK20Mindex = 0; /* max to +6dB */
@@ -734,10 +735,10 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
                tmpCCKindex = tmpCCK20Mindex;
 
        if (priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) {
-               priv->bcck_in_ch14 = TRUE;
+               priv->bcck_in_ch14 = true;
                CCKSwingNeedUpdate = 1;
        } else if (priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) {
-               priv->bcck_in_ch14 = FALSE;
+               priv->bcck_in_ch14 = false;
                CCKSwingNeedUpdate = 1;
        }
 
@@ -765,7 +766,7 @@ void dm_txpower_trackingcallback(struct work_struct *work)
        struct r8192_priv *priv = container_of(dwork, struct r8192_priv, txpower_tracking_wq);
        struct net_device *dev = priv->ieee80211->dev;
 
-       if (priv->bDcut == TRUE)
+       if (priv->bDcut == true)
                dm_TXPowerTrackingCallback_TSSI(dev);
        else
                dm_TXPowerTrackingCallback_ThermalMeter(dev);
@@ -1273,9 +1274,9 @@ static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev)
        priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[6] = 0x00;
        priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[7] = 0x00;
 
-       priv->btxpower_tracking = TRUE;
+       priv->btxpower_tracking = true;
        priv->txpower_count       = 0;
-       priv->btxpower_trackingInit = FALSE;
+       priv->btxpower_trackingInit = false;
 
 }
 
@@ -1289,18 +1290,18 @@ static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev)
         * 3-wire by driver causes RF to go into a wrong state.
         */
        if (priv->ieee80211->FwRWRF)
-               priv->btxpower_tracking = TRUE;
+               priv->btxpower_tracking = true;
        else
-               priv->btxpower_tracking = FALSE;
+               priv->btxpower_tracking = false;
        priv->txpower_count       = 0;
-       priv->btxpower_trackingInit = FALSE;
+       priv->btxpower_trackingInit = false;
 }
 
 void dm_initialize_txpower_tracking(struct net_device *dev)
 {
        struct r8192_priv *priv = ieee80211_priv(dev);
 
-       if (priv->bDcut == TRUE)
+       if (priv->bDcut == true)
                dm_InitializeTXPowerTracking_TSSI(dev);
        else
                dm_InitializeTXPowerTracking_ThermalMeter(dev);
@@ -1356,7 +1357,7 @@ static void dm_check_txpower_tracking(struct net_device *dev)
 #ifdef RTL8190P
        dm_CheckTXPowerTracking_TSSI(dev);
 #else
-       if (priv->bDcut == TRUE)
+       if (priv->bDcut == true)
                dm_CheckTXPowerTracking_TSSI(dev);
        else
                dm_CheckTXPowerTracking_ThermalMeter(dev);
@@ -1466,7 +1467,7 @@ void dm_cck_txpower_adjust(struct net_device *dev, bool binch14)
 {      /*  dm_CCKTxPowerAdjust */
        struct r8192_priv *priv = ieee80211_priv(dev);
 
-       if (priv->bDcut == TRUE)
+       if (priv->bDcut == true)
                dm_CCKTxPowerAdjust_TSSI(dev, binch14);
        else
                dm_CCKTxPowerAdjust_ThermalMeter(dev, binch14);
@@ -1628,8 +1629,8 @@ void dm_change_dynamic_initgain_thresh(struct net_device *dev, u32 dm_type,
                dm_digtable.rssi_low_thresh = dm_value;
        } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) {
                dm_digtable.rssi_high_power_highthresh = dm_value;
-       } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) {
-               dm_digtable.rssi_high_power_highthresh = dm_value;
+       } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_LOW) {
+               dm_digtable.rssi_high_power_lowthresh = dm_value;
        } else if (dm_type == DIG_TYPE_ENABLE) {
                dm_digtable.dig_state           = DM_STA_DIG_MAX;
                dm_digtable.dig_enable_flag     = true;
@@ -2270,10 +2271,10 @@ static void dm_check_edca_turbo(
                                /*  For Each time updating EDCA parameter, reset EDCA turbo mode status. */
                                dm_init_edca_turbo(dev);
                                u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
-                               u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[0])) << AC_PARAM_TXOP_LIMIT_OFFSET)|
+                               u4bAcParam = (((u32)(qos_parameters->tx_op_limit[0])) << AC_PARAM_TXOP_LIMIT_OFFSET)|
                                        (((u32)(qos_parameters->cw_max[0])) << AC_PARAM_ECW_MAX_OFFSET)|
                                        (((u32)(qos_parameters->cw_min[0])) << AC_PARAM_ECW_MIN_OFFSET)|
-                                       ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
+                                       ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET);
                                /*write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);*/
                                write_nic_dword(dev, EDCAPARA_BE,  u4bAcParam);
 
@@ -2314,7 +2315,7 @@ static void dm_init_ctstoself(struct net_device *dev)
 {
        struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev);
 
-       priv->ieee80211->bCTSToSelfEnable = TRUE;
+       priv->ieee80211->bCTSToSelfEnable = true;
        priv->ieee80211->CTSToSelfTH = CTSToSelfTHVal;
 }
 
@@ -2327,7 +2328,7 @@ static void dm_ctstoself(struct net_device *dev)
        unsigned long                                           curTxOkCnt = 0;
        unsigned long                                           curRxOkCnt = 0;
 
-       if (priv->ieee80211->bCTSToSelfEnable != TRUE) {
+       if (priv->ieee80211->bCTSToSelfEnable != true) {
                pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
                return;
        }
@@ -2419,9 +2420,9 @@ void dm_rf_pathcheck_workitemcallback(struct work_struct *work)
        /* Check Bit 0-3, it means if RF A-D is enabled. */
        for (i = 0; i < RF90_PATH_MAX; i++) {
                if (rfpath & (0x01<<i))
-                       priv->brfpath_rxenable[i] = 1;
+                       priv->brfpath_rxenable[i] = true;
                else
-                       priv->brfpath_rxenable[i] = 0;
+                       priv->brfpath_rxenable[i] = false;
        }
        if (!DM_RxPathSelTable.Enable)
                return;
@@ -2681,10 +2682,8 @@ static void dm_init_fsync(struct net_device *dev)
        priv->ieee80211->fsync_seconddiff_ratethreshold = 200;
        priv->ieee80211->fsync_state = Default_Fsync;
        priv->framesyncMonitor = 1;     /* current default 0xc38 monitor on */
-
-       init_timer(&priv->fsync_timer);
-       priv->fsync_timer.data = (unsigned long)dev;
-       priv->fsync_timer.function = dm_fsync_timer_callback;
+       setup_timer(&priv->fsync_timer, dm_fsync_timer_callback,
+                   (unsigned long)dev);
 }
 
 static void dm_deInit_fsync(struct net_device *dev)
index 3008f91ad4cf11d352fc8e8b685c42a78e40550a..6cd32eb440852e513b1cc2bc60b128447fb4612d 100644 (file)
@@ -67,7 +67,7 @@
 
 /*------------------------------Define structure----------------------------*/
 /* 2007/10/04 MH Define upper and lower threshold of DIG enable or disable. */
-typedef struct _dynamic_initial_gain_threshold_ {
+struct dig {
        u8              dig_enable_flag;
        u8              dig_algorithm;
        u8              dbg_mode;
@@ -98,7 +98,7 @@ typedef struct _dynamic_initial_gain_threshold_ {
        bool            initialgain_lowerbound_state;
 
        long            rssi_val;
-} dig_t;
+};
 
 typedef enum tag_dynamic_init_gain_state_definition {
        DM_STA_DIG_OFF = 0,
@@ -163,7 +163,7 @@ typedef enum tag_dig_cck_cs_ratio_state_definition {
        DIG_CS_RATIO_HIGHER = 1,
        DIG_CS_MAX
 } dm_dig_cs_ratio_e;
-typedef struct _Dynamic_Rx_Path_Selection_ {
+struct dynamic_rx_path_sel {
        u8              Enable;
        u8              DbgMode;
        u8              cck_method;
@@ -177,7 +177,7 @@ typedef struct _Dynamic_Rx_Path_Selection_ {
        u8              rf_rssi[4];
        u8              rf_enable_rssi_th[4];
        long            cck_pwdb_sta[4];
-} DRxPathSel;
+};
 
 typedef enum tag_CCK_Rx_Path_Method_Definition {
        CCK_Rx_Version_1 = 0,
@@ -200,9 +200,9 @@ typedef struct tag_Tx_Config_Cmd_Format {
 
 
 /*------------------------Export global variable----------------------------*/
-extern dig_t dm_digtable;
+extern struct dig dm_digtable;
 extern u8 dm_shadow[16][256];
-extern DRxPathSel DM_RxPathSelTable;
+extern struct dynamic_rx_path_sel DM_RxPathSelTable;
 /*------------------------Export global variable----------------------------*/
 
 
index 361d2d0c3df167284d168d8b22ff040f08061b4e..83597051a4485b5f541052cc80abea7981805b79 100644 (file)
@@ -139,7 +139,7 @@ static int r8192_wx_force_reset(struct net_device *dev,
 
        down(&priv->wx_sem);
 
-       printk("%s(): force reset ! extra is %d\n", __func__, *extra);
+       netdev_dbg(dev, "%s(): force reset ! extra is %d\n", __func__, *extra);
        priv->force_reset = *extra;
        up(&priv->wx_sem);
        return 0;
@@ -335,7 +335,7 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
        if (!priv->up)
                return -ENETDOWN;
 
-       if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
+       if (priv->ieee80211->LinkDetectInfo.bBusyTraffic)
                return -EAGAIN;
        if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
                struct iw_scan_req *req = (struct iw_scan_req *)b;
index ae7a617740a31ccc412924cc793d076dceb980a4..d6a2d975653166b8c07d0d7c5aa53abc6393054f 100644 (file)
@@ -1,20 +1,21 @@
 /*
-       This is part of rtl8180 OpenSource driver - v 0.3
-       Copyright (C) Andrea Merello 2004  <andrea.merello@gmail.com>
-       Released under the terms of GPL (General Public Licence)
+ * This is part of rtl8180 OpenSource driver - v 0.3
+ * Copyright (C) Andrea Merello 2004  <andrea.merello@gmail.com>
+ * Released under the terms of GPL (General Public Licence)
+ *
+ * Parts of this driver are based on the GPL part of the official realtek driver
+ * Parts of this driver are based on the rtl8180 driver skeleton from Patric
+ * Schenke & Andres Salomon
+ * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
+ *
+ * We want to thank the Authors of such projects and the Ndiswrapper project
+ * Authors.
+ */
 
-       Parts of this driver are based on the GPL part of the official realtek driver
-       Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
-       Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
-
-       We want to thank the Authors of such projects and the Ndiswrapper project Authors.
-*/
-
-/* this file (will) contains wireless extension handlers*/
+/* this file (will) contains wireless extension handlers */
 
 #ifndef R8180_WX_H
 #define R8180_WX_H
-//#include <linux/wireless.h>
 
 extern struct iw_handler_def r8192_wx_handlers_def;
 /* Enable  the rtl819x_core.c to share this function, david 2008.9.22 */
index c230be290ab61a9f4e19f452cc4004e90a99b355..d27b1e24ca4a1829141179bf7f2e617fa2eba79f 100644 (file)
@@ -37,7 +37,6 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
        bool                rt_status = true;
        u16                 frag_threshold;
        u16                 frag_length, frag_offset = 0;
-       //u16               total_size;
        int                 i;
 
        rt_firmware         *pfirmware = priv->pFirmware;
@@ -48,7 +47,7 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
        u8                  index;
 
        firmware_init_param(dev);
-       //Fragmentation might be required
+       /* Fragmentation might be required */
        frag_threshold = pfirmware->cmdpacket_frag_thresold;
        do {
                if ((buffer_len - frag_offset) > frag_threshold) {
@@ -107,19 +106,20 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
 
 }
 
-//-----------------------------------------------------------------------------
-// Procedure:    Check whether main code is download OK. If OK, turn on CPU
-//
-// Description:   CPU register locates in different page against general register.
-//                         Switch to CPU register in the begin and switch back before return
-//
-//
-// Arguments:   The pointer of the adapter
-//
-// Returns:
-//        NDIS_STATUS_FAILURE - the following initialization process should be terminated
-//        NDIS_STATUS_SUCCESS - if firmware initialization process success
-//-----------------------------------------------------------------------------
+/*
+ * Procedure:  Check whether main code is download OK. If OK, turn on CPU
+ *
+ * Description:        CPU register locates in different page against general register.
+ *         Switch to CPU register in the begin and switch back before return
+ *
+ *
+ * Arguments:   The pointer of the adapter
+ *
+ * Returns:
+ *        NDIS_STATUS_FAILURE - the following initialization process should
+ *                             be terminated
+ *        NDIS_STATUS_SUCCESS - if firmware initialization process success
+ */
 static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
 {
        bool            rt_status = true;
@@ -164,7 +164,7 @@ static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
 
 CPUCheckMainCodeOKAndTurnOnCPU_Fail:
        RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
-       rt_status = FALSE;
+       rt_status = false;
        return rt_status;
 }
 
@@ -201,7 +201,7 @@ CPUCheckFirmwareReady_Fail:
 bool init_firmware(struct net_device *dev)
 {
        struct r8192_priv       *priv = ieee80211_priv(dev);
-       bool                    rt_status = TRUE;
+       bool                    rt_status = true;
 
        u32                     file_length = 0;
        u8                      *mapped_file = NULL;
@@ -222,7 +222,7 @@ bool init_firmware(struct net_device *dev)
                /* it is called by reset */
                rst_opt = OPT_SYSTEM_RESET;
                starting_state = FW_INIT_STEP0_BOOT;
-               // TODO: system reset
+               /* TODO: system reset */
 
        } else if (pfirmware->firmware_status == FW_STATUS_5_READY) {
                /* it is called by Initialize */
@@ -281,7 +281,7 @@ bool init_firmware(struct net_device *dev)
                if (rst_opt == OPT_SYSTEM_RESET)
                        release_firmware(fw_entry);
 
-               if (rt_status != TRUE)
+               if (!rt_status)
                        goto download_firmware_fail;
 
                switch (init_step) {
@@ -291,7 +291,7 @@ bool init_firmware(struct net_device *dev)
                         * will set polling bit when firmware code is also configured
                         */
                        pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
-                       //mdelay(1000);
+                       /* mdelay(1000); */
                        /*
                         * To initialize IMEM, CPU move code  from 0x80000080,
                         * hence, we send 0x80 byte packet
@@ -304,7 +304,7 @@ bool init_firmware(struct net_device *dev)
 
                        /* Check Put Code OK and Turn On CPU */
                        rt_status = CPUcheck_maincodeok_turnonCPU(dev);
-                       if (rt_status != TRUE) {
+                       if (!rt_status) {
                                RT_TRACE(COMP_ERR, "CPUcheck_maincodeok_turnonCPU fail!\n");
                                goto download_firmware_fail;
                        }
@@ -318,7 +318,7 @@ bool init_firmware(struct net_device *dev)
                        mdelay(1);
 
                        rt_status = CPUcheck_firmware_ready(dev);
-                       if (rt_status != TRUE) {
+                       if (!rt_status) {
                                RT_TRACE(COMP_ERR, "CPUcheck_firmware_ready fail(%d)!\n",rt_status);
                                goto download_firmware_fail;
                        }
@@ -330,13 +330,11 @@ bool init_firmware(struct net_device *dev)
        }
 
        RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
-       //assert(pfirmware->firmware_status == FW_STATUS_5_READY, ("Firmware Download Fail\n"));
-
        return rt_status;
 
 download_firmware_fail:
        RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
-       rt_status = FALSE;
+       rt_status = false;
        return rt_status;
 
 }
index 058960251bacdd72a69b55df6a15a78de4d6c738..e5dbaca9e518e9cd8ca5ede123cbaa294bfb6e6e 100644 (file)
@@ -106,10 +106,10 @@ void rtl8192_setBBreg(struct net_device *dev, u32 reg_addr, u32 bitmask,
 /******************************************************************************
  * function:  This function reads specific bits from BB register
  * input:     net_device       *dev
- *            u32              reg_addr   //target addr to be readback
- *            u32              bitmask    //taget bit pos to be readback
+ *            u32              reg_addr   //target addr to be readback
+ *            u32              bitmask    //taget bit pos to be readback
  * output:    none
- * return:    u32              data       //the readback register value
+ * return:    u32              data       //the readback register value
  * notice:
  ******************************************************************************/
 u32 rtl8192_QueryBBReg(struct net_device *dev, u32 reg_addr, u32 bitmask)
@@ -352,16 +352,14 @@ u32 rtl8192_phy_QueryRFReg(struct net_device *dev, RF90_RADIO_PATH_E eRFPath,
                return 0;
        if (priv->Rf_Mode == RF_OP_By_FW) {
                reg = phy_FwRFSerialRead(dev, eRFPath, reg_addr);
-               bitshift =  rtl8192_CalculateBitShift(bitmask);
-               reg = (reg & bitmask) >> bitshift;
                udelay(200);
-               return reg;
        } else {
                reg = rtl8192_phy_RFSerialRead(dev, eRFPath, reg_addr);
-               bitshift =  rtl8192_CalculateBitShift(bitmask);
-               reg = (reg & bitmask) >> bitshift;
-               return reg;
        }
+       bitshift =  rtl8192_CalculateBitShift(bitmask);
+       reg = (reg & bitmask) >> bitshift;
+       return reg;
+
 }
 
 /******************************************************************************
@@ -478,7 +476,7 @@ static void phy_FwRFSerialWrite(struct net_device *dev,
 /******************************************************************************
  * function:  This function reads BB parameters from header file we generate,
  *            and do register read/write
- * input:     net_device       *dev
+ * input:     net_device       *dev
  * output:    none
  * return:    none
  * notice:    BB parameters may change all the time, so please make
@@ -825,8 +823,8 @@ static void rtl8192_BB_Config_ParaFile(struct net_device *dev)
        write_nic_byte_E(dev, 0x5e, 0x00);
        if (priv->card_8192_version == (u8)VERSION_819xU_A) {
                /* Antenna gain offset from B/C/D to A */
-               reg_u32 = (priv->AntennaTxPwDiff[1]<<4 |
-                          priv->AntennaTxPwDiff[0]);
+               reg_u32 = priv->AntennaTxPwDiff[1]<<4 |
+                          priv->AntennaTxPwDiff[0];
                rtl8192_setBBreg(dev, rFPGA0_TxGainStage, (bXBTxAGC|bXCTxAGC),
                                 reg_u32);
 
@@ -900,7 +898,7 @@ void rtl8192_phy_getTxPower(struct net_device *dev)
        read_nic_byte(dev, rOFDM0_RxDetector3, &priv->framesync);
        read_nic_byte(dev, rOFDM0_RxDetector2, &tmp);
        priv->framesyncC34 = tmp;
-       RT_TRACE(COMP_INIT, "Default framesync (0x%x) = 0x%x \n",
+       RT_TRACE(COMP_INIT, "Default framesync (0x%x) = 0x%x\n",
                rOFDM0_RxDetector3, priv->framesync);
 
        /* Read SIFS (save the value read fome MACPHY_REG.txt) */
@@ -1101,7 +1099,7 @@ bool rtl8192_SetRFPowerState(struct net_device *dev,
        if (eRFPowerState == priv->ieee80211->eRFPowerState)
                return false;
 
-       if (priv->SetRFPowerStateInProgress == true)
+       if (priv->SetRFPowerStateInProgress)
                return false;
 
        priv->SetRFPowerStateInProgress = true;
@@ -1187,7 +1185,7 @@ bool rtl8192_SetRFPowerState(struct net_device *dev,
                                /* Turn on RF we are still linked, which might
                                   happen when we quickly turn off and on HW RF.
                                 */
-                               if (pMgntInfo->bMediaConnect == TRUE)
+                               if (pMgntInfo->bMediaConnect)
                                        Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_LINK);
                                else
                                        /* Turn off LED if RF is not ON. */
@@ -1344,7 +1342,6 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
        default:
                RT_TRACE(COMP_ERR, "Unknown RFChipID: %d\n", priv->rf_chip);
                return true;
-               break;
        }
 
 
@@ -1365,11 +1362,10 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
                        if ((*stage) == 2) {
                                (*delay) = CurrentCmd->msDelay;
                                return true;
-                       } else {
-                               (*stage)++;
-                               (*step) = 0;
-                               continue;
                        }
+                       (*stage)++;
+                       (*step) = 0;
+                       continue;
                }
 
                switch (CurrentCmd->CmdID) {
@@ -1579,10 +1575,10 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev)
                         priv->cck_present_attentuation);
 
                if (priv->chan == 14 && !priv->bcck_in_ch14) {
-                       priv->bcck_in_ch14 = TRUE;
+                       priv->bcck_in_ch14 = true;
                        dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
                } else if (priv->chan != 14 && priv->bcck_in_ch14) {
-                       priv->bcck_in_ch14 = FALSE;
+                       priv->bcck_in_ch14 = false;
                        dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
                } else {
                        dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
@@ -1746,13 +1742,13 @@ void InitialGainOperateWorkItemCallBack(struct work_struct *work)
                RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xa0a is %x\n",
                         priv->initgain_backup.cca);
 
-               RT_TRACE(COMP_SCAN, "Write scan initial gain = 0x%x \n",
+               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);
-               RT_TRACE(COMP_SCAN, "Write scan 0xa0a = 0x%x \n",
+               RT_TRACE(COMP_SCAN, "Write scan 0xa0a = 0x%x\n",
                         POWER_DETECTION_TH);
                write_nic_byte(dev, 0xa0a, POWER_DETECTION_TH);
                break;
@@ -1793,7 +1789,7 @@ void InitialGainOperateWorkItemCallBack(struct work_struct *work)
                        rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);
                break;
        default:
-               RT_TRACE(COMP_SCAN, "Unknown IG Operation. \n");
+               RT_TRACE(COMP_SCAN, "Unknown IG Operation.\n");
                break;
        }
 }
index 324da34383eaac6a6a5b38a7d83206d9556559a8..0a1c6313e78156b708e570591fca431b0981f33e 100644 (file)
@@ -92,7 +92,7 @@ static u32 rtl871x_open_fw(struct _adapter *padapter, const u8 **ppmappedfw)
 
 static void fill_fwpriv(struct _adapter *padapter, struct fw_priv *pfwpriv)
 {
-       struct dvobj_priv *pdvobj = (struct dvobj_priv *)&padapter->dvobjpriv;
+       struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
        struct registry_priv *pregpriv = &padapter->registrypriv;
 
        memset(pfwpriv, 0, sizeof(struct fw_priv));
index 354bd03e700f7b8d2ce3c979b165e1296e76b0f2..8c5a475f05e7a546598071a84be324182af273c2 100644 (file)
 #include "drv_types.h"
 #include "mlme_osdep.h"
 
-static void sitesurvey_ctrl_handler(void *FunctionContext)
+static void sitesurvey_ctrl_handler(unsigned long data)
 {
-       struct _adapter *adapter = (struct _adapter *)FunctionContext;
+       struct _adapter *adapter = (struct _adapter *)data;
 
        _r8712_sitesurvey_ctrl_handler(adapter);
-       _set_timer(&adapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer,
-                  3000);
+       mod_timer(&adapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer,
+                 jiffies + msecs_to_jiffies(3000));
 }
 
-static void join_timeout_handler (void *FunctionContext)
+static void join_timeout_handler (unsigned long data)
 {
-       struct _adapter *adapter = (struct _adapter *)FunctionContext;
+       struct _adapter *adapter = (struct _adapter *)data;
 
        _r8712_join_timeout_handler(adapter);
 }
 
-static void _scan_timeout_handler (void *FunctionContext)
+static void _scan_timeout_handler (unsigned long data)
 {
-       struct _adapter *adapter = (struct _adapter *)FunctionContext;
+       struct _adapter *adapter = (struct _adapter *)data;
 
        r8712_scan_timeout_handler(adapter);
 }
 
-static void dhcp_timeout_handler (void *FunctionContext)
+static void dhcp_timeout_handler (unsigned long data)
 {
-       struct _adapter *adapter = (struct _adapter *)FunctionContext;
+       struct _adapter *adapter = (struct _adapter *)data;
 
        _r8712_dhcp_timeout_handler(adapter);
 }
 
-static void wdg_timeout_handler (void *FunctionContext)
+static void wdg_timeout_handler (unsigned long data)
 {
-       struct _adapter *adapter = (struct _adapter *)FunctionContext;
+       struct _adapter *adapter = (struct _adapter *)data;
 
        _r8712_wdg_timeout_handler(adapter);
 
-       _set_timer(&adapter->mlmepriv.wdg_timer, 2000);
+       mod_timer(&adapter->mlmepriv.wdg_timer,
+                 jiffies + msecs_to_jiffies(2000));
 }
 
 void r8712_init_mlme_timer(struct _adapter *padapter)
 {
        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
-       _init_timer(&(pmlmepriv->assoc_timer), padapter->pnetdev,
-                   join_timeout_handler, (pmlmepriv->nic_hdl));
-       _init_timer(&(pmlmepriv->sitesurveyctrl.sitesurvey_ctrl_timer),
-                   padapter->pnetdev, sitesurvey_ctrl_handler,
-                   (u8 *)(pmlmepriv->nic_hdl));
-       _init_timer(&(pmlmepriv->scan_to_timer), padapter->pnetdev,
-                   _scan_timeout_handler, (pmlmepriv->nic_hdl));
-       _init_timer(&(pmlmepriv->dhcp_timer), padapter->pnetdev,
-                   dhcp_timeout_handler, (u8 *)(pmlmepriv->nic_hdl));
-       _init_timer(&(pmlmepriv->wdg_timer), padapter->pnetdev,
-                   wdg_timeout_handler, (u8 *)(pmlmepriv->nic_hdl));
+       setup_timer(&pmlmepriv->assoc_timer, join_timeout_handler,
+                   (unsigned long)padapter);
+       setup_timer(&pmlmepriv->sitesurveyctrl.sitesurvey_ctrl_timer,
+                   sitesurvey_ctrl_handler,
+                   (unsigned long)padapter);
+       setup_timer(&pmlmepriv->scan_to_timer, _scan_timeout_handler,
+                   (unsigned long)padapter);
+       setup_timer(&pmlmepriv->dhcp_timer, dhcp_timeout_handler,
+                   (unsigned long)padapter);
+       setup_timer(&pmlmepriv->wdg_timer, wdg_timeout_handler,
+                   (unsigned long)padapter);
 }
 
 void r8712_os_indicate_connect(struct _adapter *adapter)
@@ -117,9 +118,9 @@ void r8712_os_indicate_disconnect(struct _adapter *adapter)
                                           btkip_countermeasure;
                memset((unsigned char *)&adapter->securitypriv, 0,
                         sizeof(struct security_priv));
-               _init_timer(&(adapter->securitypriv.tkip_timer),
-                           adapter->pnetdev, r8712_use_tkipkey_handler,
-                           adapter);
+               setup_timer(&adapter->securitypriv.tkip_timer,
+                           r8712_use_tkipkey_handler,
+                           (unsigned long)adapter);
                /* Restore the PMK information to securitypriv structure
                 * for the following connection. */
                memcpy(&adapter->securitypriv.PMKIDList[0],
index 13debb59ad97ac2f721b768c446fd732b1ab7790..6e776e5433f67bfb96e6a5dda56c46713842436e 100644 (file)
@@ -177,7 +177,7 @@ static uint loadparam(struct _adapter *padapter, struct  net_device *pnetdev)
 
 static int r871x_net_set_mac_address(struct net_device *pnetdev, void *p)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(pnetdev);
+       struct _adapter *padapter = netdev_priv(pnetdev);
        struct sockaddr *addr = p;
 
        if (padapter->bup == false)
@@ -187,7 +187,7 @@ static int r871x_net_set_mac_address(struct net_device *pnetdev, void *p)
 
 static struct net_device_stats *r871x_net_get_stats(struct net_device *pnetdev)
 {
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(pnetdev);
+       struct _adapter *padapter = netdev_priv(pnetdev);
        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
        struct recv_priv *precvpriv = &(padapter->recvpriv);
 
@@ -221,7 +221,7 @@ struct net_device *r8712_init_netdev(void)
                strcpy(ifname, "wlan%d");
                dev_alloc_name(pnetdev, ifname);
        }
-       padapter = (struct _adapter *) netdev_priv(pnetdev);
+       padapter = netdev_priv(pnetdev);
        padapter->pnetdev = pnetdev;
        pr_info("r8712u: register rtl8712_netdev_ops to netdev_ops\n");
        pnetdev->netdev_ops = &rtl8712_netdev_ops;
@@ -255,20 +255,20 @@ void r8712_stop_drv_threads(struct _adapter *padapter)
 
 static void start_drv_timers(struct _adapter *padapter)
 {
-       _set_timer(&padapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer,
-                  5000);
-       _set_timer(&padapter->mlmepriv.wdg_timer, 2000);
+       mod_timer(&padapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer,
+                 jiffies + msecs_to_jiffies(5000));
+       mod_timer(&padapter->mlmepriv.wdg_timer,
+                 jiffies + msecs_to_jiffies(2000));
 }
 
 void r8712_stop_drv_timers(struct _adapter *padapter)
 {
-       _cancel_timer_ex(&padapter->mlmepriv.assoc_timer);
-       _cancel_timer_ex(&padapter->securitypriv.tkip_timer);
-       _cancel_timer_ex(&padapter->mlmepriv.scan_to_timer);
-       _cancel_timer_ex(&padapter->mlmepriv.dhcp_timer);
-       _cancel_timer_ex(&padapter->mlmepriv.wdg_timer);
-       _cancel_timer_ex(&padapter->mlmepriv.sitesurveyctrl.
-                        sitesurvey_ctrl_timer);
+       del_timer_sync(&padapter->mlmepriv.assoc_timer);
+       del_timer_sync(&padapter->securitypriv.tkip_timer);
+       del_timer_sync(&padapter->mlmepriv.scan_to_timer);
+       del_timer_sync(&padapter->mlmepriv.dhcp_timer);
+       del_timer_sync(&padapter->mlmepriv.wdg_timer);
+       del_timer_sync(&padapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer);
 }
 
 static u8 init_default_value(struct _adapter *padapter)
@@ -322,8 +322,8 @@ u8 r8712_init_drv_sw(struct _adapter *padapter)
        _r8712_init_recv_priv(&padapter->recvpriv, padapter);
        memset((unsigned char *)&padapter->securitypriv, 0,
               sizeof(struct security_priv));
-       _init_timer(&(padapter->securitypriv.tkip_timer), padapter->pnetdev,
-                   r8712_use_tkipkey_handler, padapter);
+       setup_timer(&padapter->securitypriv.tkip_timer,
+                   r8712_use_tkipkey_handler, (unsigned long)padapter);
        _r8712_init_sta_priv(&padapter->stapriv);
        padapter->stapriv.padapter = padapter;
        r8712_init_bcmc_stainfo(padapter);
@@ -384,7 +384,7 @@ static void enable_video_mode(struct _adapter *padapter, int cbw40_value)
  */
 static int netdev_open(struct net_device *pnetdev)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(pnetdev);
+       struct _adapter *padapter = netdev_priv(pnetdev);
 
        mutex_lock(&padapter->mutex_start);
        if (padapter->bup == false) {
@@ -452,7 +452,7 @@ netdev_open_error:
  */
 static int netdev_close(struct net_device *pnetdev)
 {
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(pnetdev);
+       struct _adapter *padapter = netdev_priv(pnetdev);
 
        /* Close LED*/
        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_POWER_OFF);
index 36348d900d34b935ee0c789db0ad9f9d376e5589..0a7f58c59df521aab10911520a39810be8ff38b2 100644 (file)
@@ -60,26 +60,6 @@ struct       __queue {
 #define LIST_CONTAINOR(ptr, type, member) \
        ((type *)((char *)(ptr)-(SIZE_T)(&((type *)0)->member)))
 
-static inline void _init_timer(struct timer_list *ptimer,
-                              struct  net_device *padapter,
-                              void *pfunc, void *cntx)
-{
-       ptimer->function = pfunc;
-       ptimer->data = (addr_t)cntx;
-       init_timer(ptimer);
-}
-
-static inline void _set_timer(struct timer_list *ptimer, u32 delay_time)
-{
-       mod_timer(ptimer, (jiffies+msecs_to_jiffies(delay_time)));
-}
-
-static inline void _cancel_timer(struct timer_list *ptimer, u8 *bcancelled)
-{
-       del_timer(ptimer);
-       *bcancelled = true; /*true ==1; false==0*/
-}
-
 #ifndef BIT
        #define BIT(x)  (1 << (x))
 #endif
@@ -106,11 +86,6 @@ static inline void sleep_schedulable(int ms)
        schedule_timeout(delta);
 }
 
-static inline unsigned char _cancel_timer_ex(struct timer_list *ptimer)
-{
-       return del_timer(ptimer);
-}
-
 static inline void flush_signals_thread(void)
 {
        if (signal_pending(current))
index 409c8c897256ad4dd16494f0cb9bfac3f3c4ab91..799a0f9a5b2d27a089bfc5a87f3d0bbb99229ddd 100644 (file)
@@ -96,7 +96,7 @@ void r8712_handle_tkip_mic_err(struct _adapter *padapter, u8 bgroup)
        else
                ev.flags |= IW_MICFAILURE_PAIRWISE;
        ev.src_addr.sa_family = ARPHRD_ETHER;
-       memcpy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
+       ether_addr_copy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[0]);
        memset(&wrqu, 0x00, sizeof(wrqu));
        wrqu.data.length = sizeof(ev);
        wireless_send_event(padapter->pnetdev, IWEVMICHAELMICFAILURE, &wrqu,
@@ -137,18 +137,17 @@ _recv_indicatepkt_drop:
         precvpriv->rx_drop++;
 }
 
-static void _r8712_reordering_ctrl_timeout_handler (void *FunctionContext)
+static void _r8712_reordering_ctrl_timeout_handler (unsigned long data)
 {
        struct recv_reorder_ctrl *preorder_ctrl =
-                        (struct recv_reorder_ctrl *)FunctionContext;
+                        (struct recv_reorder_ctrl *)data;
 
        r8712_reordering_ctrl_timeout_handler(preorder_ctrl);
 }
 
 void r8712_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
 {
-       struct _adapter *padapter = preorder_ctrl->padapter;
-
-       _init_timer(&(preorder_ctrl->reordering_ctrl_timer), padapter->pnetdev,
-                   _r8712_reordering_ctrl_timeout_handler, preorder_ctrl);
+       setup_timer(&preorder_ctrl->reordering_ctrl_timer,
+                    _r8712_reordering_ctrl_timeout_handler,
+                    (unsigned long)preorder_ctrl);
 }
index 62e53cc1d8b9406ed1ffe4f103d88d92e51ae2b8..007f0a3ab13d5729739d17048e78ffc4b1ed3fdb 100644 (file)
@@ -95,7 +95,7 @@ static void query_fw_rx_phy_status(struct _adapter *padapter)
                        val32 = r8712_read32(padapter, IOCMD_DATA_REG);
                else /* time out */
                        val32 = 0;
-               val32 = val32 >> 4;
+               val32 >>= 4;
                padapter->recvpriv.fw_rssi =
                         (u8)r8712_signal_scale_mapping(val32);
        }
index 56e8add30a2061545106f68e71aadffa420f38dd..f1d47a0676c3e3ba29ea974754c77e8a32a3f950 100644 (file)
@@ -97,7 +97,8 @@ static void InitLed871x(struct _adapter *padapter, struct LED_871x *pLed,
        pLed->bLedBlinkInProgress = false;
        pLed->BlinkTimes = 0;
        pLed->BlinkingLedState = LED_UNKNOWN;
-       _init_timer(&(pLed->BlinkTimer), nic, BlinkTimerCallback, pLed);
+       setup_timer(&pLed->BlinkTimer, BlinkTimerCallback,
+                   (unsigned long)pLed);
        INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback);
 }
 
@@ -107,7 +108,7 @@ static void InitLed871x(struct _adapter *padapter, struct LED_871x *pLed,
  */
 static void DeInitLed871x(struct LED_871x *pLed)
 {
-       _cancel_timer_ex(&(pLed->BlinkTimer));
+       del_timer_sync(&pLed->BlinkTimer);
        /* We should reset bLedBlinkInProgress if we cancel
         * the LedControlTimer, */
        pLed->bLedBlinkInProgress = false;
@@ -258,21 +259,21 @@ static void SwLedBlink(struct LED_871x *pLed)
                /* Schedule a timer to toggle LED state. */
                switch (pLed->CurrLedState) {
                case LED_BLINK_NORMAL:
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_NORMAL_INTERVAL);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
                        break;
                case LED_BLINK_SLOWLY:
                case LED_BLINK_StartToBlink:
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SLOWLY_INTERVAL);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
                        break;
                case LED_BLINK_WPS:
-                       _set_timer(&(pLed->BlinkTimer),
-                                       LED_BLINK_LONG_INTERVAL);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_LONG_INTERVAL));
                        break;
                default:
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SLOWLY_INTERVAL);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
                        break;
                }
        }
@@ -315,16 +316,16 @@ static void SwLedBlink1(struct LED_871x *pLed)
                        pLed->BlinkingLedState = LED_OFF;
                else
                        pLed->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer),
-                          LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                break;
        case LED_BLINK_NORMAL:
                if (pLed->bLedOn)
                        pLed->BlinkingLedState = LED_OFF;
                else
                        pLed->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer),
-                          LED_BLINK_LINK_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
                break;
        case LED_SCAN_BLINK:
                pLed->BlinkTimes--;
@@ -338,8 +339,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                        pLed->BlinkingLedState = LED_OFF;
                                else
                                        pLed->BlinkingLedState = LED_ON;
-                               _set_timer(&(pLed->BlinkTimer),
-                                          LED_BLINK_LINK_INTERVAL_ALPHA);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
                        } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
                                pLed->bLedNoLinkBlinkInProgress = true;
                                pLed->CurrLedState = LED_BLINK_SLOWLY;
@@ -347,8 +348,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                        pLed->BlinkingLedState = LED_OFF;
                                else
                                        pLed->BlinkingLedState = LED_ON;
-                               _set_timer(&(pLed->BlinkTimer),
-                                          LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                        }
                        pLed->bLedScanBlinkInProgress = false;
                } else {
@@ -356,8 +357,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                }
                break;
        case LED_TXRX_BLINK:
@@ -372,8 +373,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                        pLed->BlinkingLedState = LED_OFF;
                                else
                                        pLed->BlinkingLedState = LED_ON;
-                               _set_timer(&(pLed->BlinkTimer),
-                                          LED_BLINK_LINK_INTERVAL_ALPHA);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
                        } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
                                pLed->bLedNoLinkBlinkInProgress = true;
                                pLed->CurrLedState = LED_BLINK_SLOWLY;
@@ -381,8 +382,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                        pLed->BlinkingLedState = LED_OFF;
                                else
                                        pLed->BlinkingLedState = LED_ON;
-                               _set_timer(&(pLed->BlinkTimer),
-                                          LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                        }
                        pLed->BlinkTimes = 0;
                        pLed->bLedBlinkInProgress = false;
@@ -391,8 +392,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
        case LED_BLINK_WPS:
@@ -400,14 +401,14 @@ static void SwLedBlink1(struct LED_871x *pLed)
                        pLed->BlinkingLedState = LED_OFF;
                else
                        pLed->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer),
-                          LED_BLINK_SCAN_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                break;
        case LED_BLINK_WPS_STOP:        /* WPS success */
                if (pLed->BlinkingLedState == LED_ON) {
                        pLed->BlinkingLedState = LED_OFF;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA));
                        bStopBlinking = false;
                } else
                        bStopBlinking = true;
@@ -418,8 +419,8 @@ static void SwLedBlink1(struct LED_871x *pLed)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_LINK_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
                }
                pLed->bLedWPSBlinkInProgress = false;
                break;
@@ -460,8 +461,8 @@ static void SwLedBlink2(struct LED_871x *pLed)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                }
                break;
        case LED_TXRX_BLINK:
@@ -484,8 +485,8 @@ static void SwLedBlink2(struct LED_871x *pLed)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
        default:
@@ -528,8 +529,8 @@ static void SwLedBlink3(struct LED_871x *pLed)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                }
                break;
        case LED_TXRX_BLINK:
@@ -554,8 +555,8 @@ static void SwLedBlink3(struct LED_871x *pLed)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
        case LED_BLINK_WPS:
@@ -563,14 +564,14 @@ static void SwLedBlink3(struct LED_871x *pLed)
                        pLed->BlinkingLedState = LED_OFF;
                else
                        pLed->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer),
-                          LED_BLINK_SCAN_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                break;
        case LED_BLINK_WPS_STOP:        /*WPS success*/
                if (pLed->BlinkingLedState == LED_ON) {
                        pLed->BlinkingLedState = LED_OFF;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA));
                        bStopBlinking = false;
                } else
                        bStopBlinking = true;
@@ -610,18 +611,18 @@ static void SwLedBlink4(struct LED_871x *pLed)
                        pLed->BlinkingLedState = LED_OFF;
                else
                        pLed->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer),
-                          LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                break;
        case LED_BLINK_StartToBlink:
                if (pLed->bLedOn) {
                        pLed->BlinkingLedState = LED_OFF;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SLOWLY_INTERVAL);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
                } else {
                        pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_NORMAL_INTERVAL);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
                }
                break;
        case LED_SCAN_BLINK:
@@ -635,16 +636,16 @@ static void SwLedBlink4(struct LED_871x *pLed)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                        pLed->bLedScanBlinkInProgress = false;
                } else {
                        if (pLed->bLedOn)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                }
                break;
        case LED_TXRX_BLINK:
@@ -658,27 +659,27 @@ static void SwLedBlink4(struct LED_871x *pLed)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                        pLed->bLedBlinkInProgress = false;
                } else {
                         if (pLed->bLedOn)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
        case LED_BLINK_WPS:
                if (pLed->bLedOn) {
                        pLed->BlinkingLedState = LED_OFF;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SLOWLY_INTERVAL);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
                } else {
                        pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_NORMAL_INTERVAL);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
                }
                break;
        case LED_BLINK_WPS_STOP:        /*WPS authentication fail*/
@@ -686,7 +687,8 @@ static void SwLedBlink4(struct LED_871x *pLed)
                        pLed->BlinkingLedState = LED_OFF;
                else
                        pLed->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
                break;
        case LED_BLINK_WPS_STOP_OVERLAP:        /*WPS session overlap */
                pLed->BlinkTimes--;
@@ -699,15 +701,15 @@ static void SwLedBlink4(struct LED_871x *pLed)
                if (bStopBlinking) {
                        pLed->BlinkTimes = 10;
                        pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_LINK_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
                } else {
                        if (pLed->bLedOn)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_NORMAL_INTERVAL);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
                }
                break;
        default:
@@ -734,16 +736,16 @@ static void SwLedBlink5(struct LED_871x *pLed)
                        pLed->CurrLedState = LED_ON;
                        pLed->BlinkingLedState = LED_ON;
                        if (!pLed->bLedOn)
-                               _set_timer(&(pLed->BlinkTimer),
-                                          LED_BLINK_FASTER_INTERVAL_ALPHA);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                        pLed->bLedScanBlinkInProgress = false;
                } else {
                        if (pLed->bLedOn)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                }
                break;
        case LED_TXRX_BLINK:
@@ -754,16 +756,16 @@ static void SwLedBlink5(struct LED_871x *pLed)
                        pLed->CurrLedState = LED_ON;
                        pLed->BlinkingLedState = LED_ON;
                        if (!pLed->bLedOn)
-                               _set_timer(&(pLed->BlinkTimer),
-                                          LED_BLINK_FASTER_INTERVAL_ALPHA);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                        pLed->bLedBlinkInProgress = false;
                } else {
                         if (pLed->bLedOn)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
        default:
@@ -797,8 +799,8 @@ static void SwLedBlink6(struct LED_871x *pLed)
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
        case LED_BLINK_WPS:
@@ -806,7 +808,8 @@ static void SwLedBlink6(struct LED_871x *pLed)
                        pLed->BlinkingLedState = LED_OFF;
                else
                        pLed->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                break;
 
        default:
@@ -895,11 +898,11 @@ static void SwLedControlMode1(struct _adapter *padapter,
                          IS_LED_WPS_BLINKING(pLed))
                                return;
                        if (pLed->bLedLinkBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedLinkBlinkInProgress = false;
                        }
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        pLed->bLedNoLinkBlinkInProgress = true;
@@ -908,8 +911,8 @@ static void SwLedControlMode1(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_LINK:
@@ -918,11 +921,11 @@ static void SwLedControlMode1(struct _adapter *padapter,
                            IS_LED_WPS_BLINKING(pLed))
                                return;
                        if (pLed->bLedNoLinkBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedNoLinkBlinkInProgress = false;
                        }
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        pLed->bLedLinkBlinkInProgress = true;
@@ -931,8 +934,8 @@ static void SwLedControlMode1(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_LINK_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_SITE_SURVEY:
@@ -943,15 +946,15 @@ static void SwLedControlMode1(struct _adapter *padapter,
                        if (IS_LED_WPS_BLINKING(pLed))
                                return;
                        if (pLed->bLedNoLinkBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedNoLinkBlinkInProgress = false;
                        }
                        if (pLed->bLedLinkBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                 pLed->bLedLinkBlinkInProgress = false;
                        }
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        pLed->bLedScanBlinkInProgress = true;
@@ -961,8 +964,8 @@ static void SwLedControlMode1(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                 }
                break;
        case LED_CTL_TX:
@@ -972,11 +975,11 @@ static void SwLedControlMode1(struct _adapter *padapter,
                            IS_LED_WPS_BLINKING(pLed))
                                return;
                        if (pLed->bLedNoLinkBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedNoLinkBlinkInProgress = false;
                        }
                        if (pLed->bLedLinkBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedLinkBlinkInProgress = false;
                        }
                        pLed->bLedBlinkInProgress = true;
@@ -986,8 +989,8 @@ static void SwLedControlMode1(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
 
@@ -995,19 +998,19 @@ static void SwLedControlMode1(struct _adapter *padapter,
        case LED_CTL_START_WPS_BOTTON:
                 if (pLed->bLedWPSBlinkInProgress == false) {
                        if (pLed->bLedNoLinkBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedNoLinkBlinkInProgress = false;
                        }
                        if (pLed->bLedLinkBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                 pLed->bLedLinkBlinkInProgress = false;
                        }
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        if (pLed->bLedScanBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedScanBlinkInProgress = false;
                        }
                        pLed->bLedWPSBlinkInProgress = true;
@@ -1016,44 +1019,45 @@ static void SwLedControlMode1(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_STOP_WPS:
                if (pLed->bLedNoLinkBlinkInProgress == true) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedNoLinkBlinkInProgress = false;
                }
                if (pLed->bLedLinkBlinkInProgress == true) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                         pLed->bLedLinkBlinkInProgress = false;
                }
                if (pLed->bLedBlinkInProgress == true) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedBlinkInProgress = false;
                }
                if (pLed->bLedScanBlinkInProgress == true) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedScanBlinkInProgress = false;
                }
                if (pLed->bLedWPSBlinkInProgress)
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                else
                        pLed->bLedWPSBlinkInProgress = true;
                pLed->CurrLedState = LED_BLINK_WPS_STOP;
                if (pLed->bLedOn) {
                        pLed->BlinkingLedState = LED_OFF;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA));
                } else {
                        pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer), 0);
+                       mod_timer(&pLed->BlinkTimer,
+                                 jiffies + msecs_to_jiffies(0));
                }
                break;
        case LED_CTL_STOP_WPS_FAIL:
                if (pLed->bLedWPSBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedWPSBlinkInProgress = false;
                }
                pLed->bLedNoLinkBlinkInProgress = true;
@@ -1062,33 +1066,34 @@ static void SwLedControlMode1(struct _adapter *padapter,
                        pLed->BlinkingLedState = LED_OFF;
                else
                        pLed->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer),
-                          LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                break;
        case LED_CTL_POWER_OFF:
                pLed->CurrLedState = LED_OFF;
                pLed->BlinkingLedState = LED_OFF;
                if (pLed->bLedNoLinkBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedNoLinkBlinkInProgress = false;
                }
                if (pLed->bLedLinkBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedLinkBlinkInProgress = false;
                }
                if (pLed->bLedBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedBlinkInProgress = false;
                }
                if (pLed->bLedWPSBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedWPSBlinkInProgress = false;
                }
                if (pLed->bLedScanBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedScanBlinkInProgress = false;
                }
-               _set_timer(&(pLed->BlinkTimer), 0);
+               mod_timer(&pLed->BlinkTimer,
+                         jiffies + msecs_to_jiffies(0));
                break;
        default:
                break;
@@ -1111,7 +1116,7 @@ static void SwLedControlMode2(struct _adapter *padapter,
                                return;
 
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        pLed->bLedScanBlinkInProgress = true;
@@ -1121,8 +1126,8 @@ static void SwLedControlMode2(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                 }
                break;
 
@@ -1140,8 +1145,8 @@ static void SwLedControlMode2(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
 
@@ -1149,32 +1154,34 @@ static void SwLedControlMode2(struct _adapter *padapter,
                pLed->CurrLedState = LED_ON;
                pLed->BlinkingLedState = LED_ON;
                if (pLed->bLedBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedBlinkInProgress = false;
                }
                if (pLed->bLedScanBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedScanBlinkInProgress = false;
                }
 
-               _set_timer(&(pLed->BlinkTimer), 0);
+               mod_timer(&pLed->BlinkTimer,
+                         jiffies + msecs_to_jiffies(0));
                break;
 
        case LED_CTL_START_WPS: /*wait until xinpin finish*/
        case LED_CTL_START_WPS_BOTTON:
                if (pLed->bLedWPSBlinkInProgress == false) {
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        if (pLed->bLedScanBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedScanBlinkInProgress = false;
                        }
                        pLed->bLedWPSBlinkInProgress = true;
                        pLed->CurrLedState = LED_ON;
                        pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer), 0);
+                       mod_timer(&pLed->BlinkTimer,
+                                 jiffies + msecs_to_jiffies(0));
                 }
                break;
 
@@ -1182,14 +1189,16 @@ static void SwLedControlMode2(struct _adapter *padapter,
                pLed->bLedWPSBlinkInProgress = false;
                pLed->CurrLedState = LED_ON;
                pLed->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer), 0);
+               mod_timer(&pLed->BlinkTimer,
+                         jiffies + msecs_to_jiffies(0));
                break;
 
        case LED_CTL_STOP_WPS_FAIL:
                pLed->bLedWPSBlinkInProgress = false;
                pLed->CurrLedState = LED_OFF;
                pLed->BlinkingLedState = LED_OFF;
-               _set_timer(&(pLed->BlinkTimer), 0);
+               mod_timer(&pLed->BlinkTimer,
+                         jiffies + msecs_to_jiffies(0));
                break;
 
        case LED_CTL_START_TO_LINK:
@@ -1197,25 +1206,27 @@ static void SwLedControlMode2(struct _adapter *padapter,
                if (!IS_LED_BLINKING(pLed)) {
                        pLed->CurrLedState = LED_OFF;
                        pLed->BlinkingLedState = LED_OFF;
-                       _set_timer(&(pLed->BlinkTimer), 0);
+                       mod_timer(&pLed->BlinkTimer,
+                                 jiffies + msecs_to_jiffies(0));
                }
                break;
        case LED_CTL_POWER_OFF:
                pLed->CurrLedState = LED_OFF;
                pLed->BlinkingLedState = LED_OFF;
                if (pLed->bLedBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedBlinkInProgress = false;
                }
                if (pLed->bLedScanBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedScanBlinkInProgress = false;
                }
                if (pLed->bLedWPSBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedWPSBlinkInProgress = false;
                }
-               _set_timer(&(pLed->BlinkTimer), 0);
+               mod_timer(&pLed->BlinkTimer,
+                         jiffies + msecs_to_jiffies(0));
                break;
        default:
                break;
@@ -1237,7 +1248,7 @@ static void SwLedControlMode3(struct _adapter *padapter,
                        if (IS_LED_WPS_BLINKING(pLed))
                                return;
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        pLed->bLedScanBlinkInProgress = true;
@@ -1247,8 +1258,8 @@ static void SwLedControlMode3(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_TX:
@@ -1265,8 +1276,8 @@ static void SwLedControlMode3(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_LINK:
@@ -1275,24 +1286,25 @@ static void SwLedControlMode3(struct _adapter *padapter,
                pLed->CurrLedState = LED_ON;
                pLed->BlinkingLedState = LED_ON;
                if (pLed->bLedBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedBlinkInProgress = false;
                }
                if (pLed->bLedScanBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedScanBlinkInProgress = false;
                }
-               _set_timer(&(pLed->BlinkTimer), 0);
+               mod_timer(&pLed->BlinkTimer,
+                         jiffies + msecs_to_jiffies(0));
                break;
        case LED_CTL_START_WPS: /* wait until xinpin finish */
        case LED_CTL_START_WPS_BOTTON:
                if (pLed->bLedWPSBlinkInProgress == false) {
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        if (pLed->bLedScanBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedScanBlinkInProgress = false;
                        }
                        pLed->bLedWPSBlinkInProgress = true;
@@ -1301,59 +1313,63 @@ static void SwLedControlMode3(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_STOP_WPS:
                if (pLed->bLedWPSBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&(pLed->BlinkTimer));
                        pLed->bLedWPSBlinkInProgress = false;
                } else
                        pLed->bLedWPSBlinkInProgress = true;
                pLed->CurrLedState = LED_BLINK_WPS_STOP;
                if (pLed->bLedOn) {
                        pLed->BlinkingLedState = LED_OFF;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA));
                } else {
                        pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer), 0);
+                       mod_timer(&pLed->BlinkTimer,
+                                 jiffies + msecs_to_jiffies(0));
                }
                break;
        case LED_CTL_STOP_WPS_FAIL:
                if (pLed->bLedWPSBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedWPSBlinkInProgress = false;
                }
                pLed->CurrLedState = LED_OFF;
                pLed->BlinkingLedState = LED_OFF;
-               _set_timer(&(pLed->BlinkTimer), 0);
+               mod_timer(&pLed->BlinkTimer,
+                         jiffies + msecs_to_jiffies(0));
                break;
        case LED_CTL_START_TO_LINK:
        case LED_CTL_NO_LINK:
                if (!IS_LED_BLINKING(pLed)) {
                        pLed->CurrLedState = LED_OFF;
                        pLed->BlinkingLedState = LED_OFF;
-                       _set_timer(&(pLed->BlinkTimer), 0);
+                       mod_timer(&pLed->BlinkTimer,
+                                 jiffies + msecs_to_jiffies(0));
                }
                break;
        case LED_CTL_POWER_OFF:
                pLed->CurrLedState = LED_OFF;
                pLed->BlinkingLedState = LED_OFF;
                if (pLed->bLedBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedBlinkInProgress = false;
                }
                if (pLed->bLedScanBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedScanBlinkInProgress = false;
                }
                if (pLed->bLedWPSBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedWPSBlinkInProgress = false;
                }
-               _set_timer(&(pLed->BlinkTimer), 0);
+               mod_timer(&pLed->BlinkTimer,
+                         jiffies + msecs_to_jiffies(0));
                break;
        default:
                break;
@@ -1372,34 +1388,35 @@ static void SwLedControlMode4(struct _adapter *padapter,
        case LED_CTL_START_TO_LINK:
                if (pLed1->bLedWPSBlinkInProgress) {
                        pLed1->bLedWPSBlinkInProgress = false;
-                       _cancel_timer_ex(&(pLed1->BlinkTimer));
+                       del_timer_sync(&pLed1->BlinkTimer);
                        pLed1->BlinkingLedState = LED_OFF;
                        pLed1->CurrLedState = LED_OFF;
                        if (pLed1->bLedOn)
-                               _set_timer(&(pLed->BlinkTimer), 0);
+                               mod_timer(&pLed->BlinkTimer,
+                                         jiffies + msecs_to_jiffies(0));
                }
                if (pLed->bLedStartToLinkBlinkInProgress == false) {
                        if (pLed->CurrLedState == LED_SCAN_BLINK ||
                            IS_LED_WPS_BLINKING(pLed))
                                return;
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        if (pLed->bLedNoLinkBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedNoLinkBlinkInProgress = false;
                        }
                        pLed->bLedStartToLinkBlinkInProgress = true;
                        pLed->CurrLedState = LED_BLINK_StartToBlink;
                        if (pLed->bLedOn) {
                                pLed->BlinkingLedState = LED_OFF;
-                               _set_timer(&(pLed->BlinkTimer),
-                                          LED_BLINK_SLOWLY_INTERVAL);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
                        } else {
                                pLed->BlinkingLedState = LED_ON;
-                               _set_timer(&(pLed->BlinkTimer),
-                                          LED_BLINK_NORMAL_INTERVAL);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
                        }
                }
                break;
@@ -1409,11 +1426,12 @@ static void SwLedControlMode4(struct _adapter *padapter,
                if (LedAction == LED_CTL_LINK) {
                        if (pLed1->bLedWPSBlinkInProgress) {
                                pLed1->bLedWPSBlinkInProgress = false;
-                               _cancel_timer_ex(&(pLed1->BlinkTimer));
+                               del_timer_sync(&pLed1->BlinkTimer);
                                pLed1->BlinkingLedState = LED_OFF;
                                pLed1->CurrLedState = LED_OFF;
                                if (pLed1->bLedOn)
-                                       _set_timer(&(pLed->BlinkTimer), 0);
+                                       mod_timer(&pLed->BlinkTimer,
+                                                 jiffies + msecs_to_jiffies(0));
                        }
                }
                if (pLed->bLedNoLinkBlinkInProgress == false) {
@@ -1421,7 +1439,7 @@ static void SwLedControlMode4(struct _adapter *padapter,
                            IS_LED_WPS_BLINKING(pLed))
                                return;
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        pLed->bLedNoLinkBlinkInProgress = true;
@@ -1430,8 +1448,8 @@ static void SwLedControlMode4(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_SITE_SURVEY:
@@ -1442,11 +1460,11 @@ static void SwLedControlMode4(struct _adapter *padapter,
                        if (IS_LED_WPS_BLINKING(pLed))
                                return;
                        if (pLed->bLedNoLinkBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedNoLinkBlinkInProgress = false;
                        }
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        pLed->bLedScanBlinkInProgress = true;
@@ -1456,8 +1474,8 @@ static void SwLedControlMode4(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_TX:
@@ -1467,7 +1485,7 @@ static void SwLedControlMode4(struct _adapter *padapter,
                            IS_LED_WPS_BLINKING(pLed))
                                return;
                        if (pLed->bLedNoLinkBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedNoLinkBlinkInProgress = false;
                        }
                        pLed->bLedBlinkInProgress = true;
@@ -1477,49 +1495,50 @@ static void SwLedControlMode4(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_START_WPS: /*wait until xinpin finish*/
        case LED_CTL_START_WPS_BOTTON:
                if (pLed1->bLedWPSBlinkInProgress) {
                        pLed1->bLedWPSBlinkInProgress = false;
-                       _cancel_timer_ex(&(pLed1->BlinkTimer));
+                       del_timer_sync(&(pLed1->BlinkTimer));
                        pLed1->BlinkingLedState = LED_OFF;
                        pLed1->CurrLedState = LED_OFF;
                        if (pLed1->bLedOn)
-                               _set_timer(&(pLed->BlinkTimer), 0);
+                               mod_timer(&pLed->BlinkTimer,
+                                         jiffies + msecs_to_jiffies(0));
                }
                if (pLed->bLedWPSBlinkInProgress == false) {
                        if (pLed->bLedNoLinkBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedNoLinkBlinkInProgress = false;
                        }
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        if (pLed->bLedScanBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedScanBlinkInProgress = false;
                        }
                        pLed->bLedWPSBlinkInProgress = true;
                        pLed->CurrLedState = LED_BLINK_WPS;
                        if (pLed->bLedOn) {
                                pLed->BlinkingLedState = LED_OFF;
-                               _set_timer(&(pLed->BlinkTimer),
-                                          LED_BLINK_SLOWLY_INTERVAL);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
                        } else {
                                pLed->BlinkingLedState = LED_ON;
-                               _set_timer(&(pLed->BlinkTimer),
-                                          LED_BLINK_NORMAL_INTERVAL);
+                               mod_timer(&pLed->BlinkTimer, jiffies +
+                                         msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
                        }
                }
                break;
        case LED_CTL_STOP_WPS:  /*WPS connect success*/
                if (pLed->bLedWPSBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedWPSBlinkInProgress = false;
                }
                pLed->bLedNoLinkBlinkInProgress = true;
@@ -1528,12 +1547,12 @@ static void SwLedControlMode4(struct _adapter *padapter,
                        pLed->BlinkingLedState = LED_OFF;
                else
                        pLed->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer),
-                          LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                break;
        case LED_CTL_STOP_WPS_FAIL:     /*WPS authentication fail*/
                if (pLed->bLedWPSBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedWPSBlinkInProgress = false;
                }
                pLed->bLedNoLinkBlinkInProgress = true;
@@ -1542,11 +1561,11 @@ static void SwLedControlMode4(struct _adapter *padapter,
                        pLed->BlinkingLedState = LED_OFF;
                else
                        pLed->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer),
-                          LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                /*LED1 settings*/
                if (pLed1->bLedWPSBlinkInProgress)
-                       _cancel_timer_ex(&(pLed1->BlinkTimer));
+                       del_timer_sync(&pLed1->BlinkTimer);
                else
                        pLed1->bLedWPSBlinkInProgress = true;
                pLed1->CurrLedState = LED_BLINK_WPS_STOP;
@@ -1554,11 +1573,12 @@ static void SwLedControlMode4(struct _adapter *padapter,
                        pLed1->BlinkingLedState = LED_OFF;
                else
                        pLed1->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
                break;
        case LED_CTL_STOP_WPS_FAIL_OVERLAP:     /*WPS session overlap*/
                if (pLed->bLedWPSBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedWPSBlinkInProgress = false;
                }
                pLed->bLedNoLinkBlinkInProgress = true;
@@ -1567,11 +1587,11 @@ static void SwLedControlMode4(struct _adapter *padapter,
                        pLed->BlinkingLedState = LED_OFF;
                else
                        pLed->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer),
-                          LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
                /*LED1 settings*/
                if (pLed1->bLedWPSBlinkInProgress)
-                       _cancel_timer_ex(&(pLed1->BlinkTimer));
+                       del_timer_sync(&pLed1->BlinkTimer);
                else
                        pLed1->bLedWPSBlinkInProgress = true;
                pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP;
@@ -1580,37 +1600,38 @@ static void SwLedControlMode4(struct _adapter *padapter,
                        pLed1->BlinkingLedState = LED_OFF;
                else
                        pLed1->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+               mod_timer(&pLed->BlinkTimer, jiffies +
+                         msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
                break;
        case LED_CTL_POWER_OFF:
                pLed->CurrLedState = LED_OFF;
                pLed->BlinkingLedState = LED_OFF;
                if (pLed->bLedNoLinkBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedNoLinkBlinkInProgress = false;
                }
                if (pLed->bLedLinkBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedLinkBlinkInProgress = false;
                }
                if (pLed->bLedBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedBlinkInProgress = false;
                }
                if (pLed->bLedWPSBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedWPSBlinkInProgress = false;
                }
                if (pLed->bLedScanBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedScanBlinkInProgress = false;
                }
                if (pLed->bLedStartToLinkBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedStartToLinkBlinkInProgress = false;
                }
                if (pLed1->bLedWPSBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed1->BlinkTimer));
+                       del_timer_sync(&pLed1->BlinkTimer);
                        pLed1->bLedWPSBlinkInProgress = false;
                }
                pLed1->BlinkingLedState = LED_UNKNOWN;
@@ -1641,7 +1662,8 @@ static void SwLedControlMode5(struct _adapter *padapter,
                pLed->CurrLedState = LED_ON;
                pLed->BlinkingLedState = LED_ON;
                pLed->bLedBlinkInProgress = false;
-               _set_timer(&(pLed->BlinkTimer), 0);
+               mod_timer(&pLed->BlinkTimer,
+                         jiffies + msecs_to_jiffies(0));
                break;
        case LED_CTL_SITE_SURVEY:
                if ((pmlmepriv->sitesurveyctrl.traffic_busy) &&
@@ -1649,7 +1671,7 @@ static void SwLedControlMode5(struct _adapter *padapter,
                        ; /* dummy branch */
                else if (pLed->bLedScanBlinkInProgress == false) {
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        pLed->bLedScanBlinkInProgress = true;
@@ -1659,8 +1681,8 @@ static void SwLedControlMode5(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_TX:
@@ -1675,15 +1697,15 @@ static void SwLedControlMode5(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_POWER_OFF:
                pLed->CurrLedState = LED_OFF;
                pLed->BlinkingLedState = LED_OFF;
                if (pLed->bLedBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedBlinkInProgress = false;
                }
                SwLedOff(padapter, pLed);
@@ -1711,7 +1733,7 @@ static void SwLedControlMode6(struct _adapter *padapter,
                pLed->CurrLedState = LED_ON;
                pLed->BlinkingLedState = LED_ON;
                pLed->bLedBlinkInProgress = false;
-               _set_timer(&(pLed->BlinkTimer), 0);
+               mod_timer(&(pLed->BlinkTimer), jiffies + msecs_to_jiffies(0));
                break;
        case LED_CTL_TX:
        case LED_CTL_RX:
@@ -1726,15 +1748,15 @@ static void SwLedControlMode6(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_FASTER_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_START_WPS: /*wait until xinpin finish*/
        case LED_CTL_START_WPS_BOTTON:
                if (pLed->bLedWPSBlinkInProgress == false) {
                        if (pLed->bLedBlinkInProgress == true) {
-                               _cancel_timer_ex(&(pLed->BlinkTimer));
+                               del_timer_sync(&pLed->BlinkTimer);
                                pLed->bLedBlinkInProgress = false;
                        }
                        pLed->bLedWPSBlinkInProgress = true;
@@ -1743,29 +1765,30 @@ static void SwLedControlMode6(struct _adapter *padapter,
                                pLed->BlinkingLedState = LED_OFF;
                        else
                                pLed->BlinkingLedState = LED_ON;
-                       _set_timer(&(pLed->BlinkTimer),
-                                  LED_BLINK_SCAN_INTERVAL_ALPHA);
+                       mod_timer(&pLed->BlinkTimer, jiffies +
+                                 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
                }
                break;
        case LED_CTL_STOP_WPS_FAIL:
        case LED_CTL_STOP_WPS:
                if (pLed->bLedWPSBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedWPSBlinkInProgress = false;
                }
                pLed->CurrLedState = LED_ON;
                pLed->BlinkingLedState = LED_ON;
-               _set_timer(&(pLed->BlinkTimer), 0);
+               mod_timer(&pLed->BlinkTimer,
+                         jiffies + msecs_to_jiffies(0));
                break;
        case LED_CTL_POWER_OFF:
                pLed->CurrLedState = LED_OFF;
                pLed->BlinkingLedState = LED_OFF;
                if (pLed->bLedBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedBlinkInProgress = false;
                }
                if (pLed->bLedWPSBlinkInProgress) {
-                       _cancel_timer_ex(&(pLed->BlinkTimer));
+                       del_timer_sync(&pLed->BlinkTimer);
                        pLed->bLedWPSBlinkInProgress = false;
                }
                SwLedOff(padapter, pLed);
index cd8b444b255b48161b087807ed9656e3d532a186..50227b598e0c3cecb0f7c07208fb04fe7f0aaa57 100644 (file)
@@ -161,12 +161,12 @@ static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib,
        u16 drvinfo_sz = 0;
 
        drvinfo_sz = (le32_to_cpu(prxstat->rxdw0)&0x000f0000)>>16;
-       drvinfo_sz = drvinfo_sz<<3;
+       drvinfo_sz <<= 3;
        /*TODO:
         * Offset 0 */
        pattrib->bdecrypted = ((le32_to_cpu(prxstat->rxdw0) & BIT(27)) >> 27)
                                 ? 0 : 1;
-       pattrib->crc_err = ((le32_to_cpu(prxstat->rxdw0) & BIT(14)) >> 14);
+       pattrib->crc_err = (le32_to_cpu(prxstat->rxdw0) & BIT(14)) >> 14;
        /*Offset 4*/
        /*Offset 8*/
        /*Offset 12*/
@@ -435,8 +435,8 @@ void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf)
        poffset = (u8 *)prxcmdbuf;
        voffset = *(uint *)poffset;
        prxstat = (struct recv_stat *)prxcmdbuf;
-       drvinfo_sz = ((le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16);
-       drvinfo_sz = drvinfo_sz << 3;
+       drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16;
+       drvinfo_sz <<= 3;
        poffset += RXDESC_SIZE + drvinfo_sz;
        do {
                voffset  = *(uint *)poffset;
@@ -604,12 +604,12 @@ static int recv_indicatepkt_reorder(struct _adapter *padapter,
         */
        if (r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, false) ==
            true) {
-               _set_timer(&preorder_ctrl->reordering_ctrl_timer,
-                          REORDER_WAIT_TIME);
+               mod_timer(&preorder_ctrl->reordering_ctrl_timer,
+                         jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
                spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
        } else {
                spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
-               _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
+               del_timer(&preorder_ctrl->reordering_ctrl_timer);
        }
        return _SUCCESS;
 _err_exit:
@@ -749,7 +749,7 @@ static void query_rx_phy_status(struct _adapter *padapter,
                 */
                if (!cck_highpwr) {
                        report = pcck_buf->cck_agc_rpt & 0xc0;
-                       report = report >> 6;
+                       report >>= 6;
                        switch (report) {
                        /* Modify the RF RNA gain value to -40, -20,
                         * -2, 14 by Jenyu's suggestion
@@ -775,7 +775,7 @@ static void query_rx_phy_status(struct _adapter *padapter,
                } else {
                        report = ((u8)(le32_to_cpu(pphy_stat->phydw1) >> 8)) &
                                 0x60;
-                       report = report >> 5;
+                       report >>= 5;
                        switch (report) {
                        case 0x3:
                                rx_pwr_all = -40 - ((pcck_buf->cck_agc_rpt &
@@ -1039,7 +1039,7 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb)
                frag = (le32_to_cpu(prxstat->rxdw2) >> 12) & 0xf;
                /* uint 2^3 = 8 bytes */
                drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16;
-               drvinfo_sz = drvinfo_sz<<3;
+               drvinfo_sz <<= 3;
                if (pkt_len <= 0)
                        goto  _exit_recvbuf2recvframe;
                /* Qos data, wireless lan header length is 26 */
index fe5e315319f7c7afb70494af935916df4b64c072..1a1c38f885d6b191d5a62b5fb1aae26713dd6cb3 100644 (file)
@@ -247,7 +247,8 @@ u8 r8712_sitesurvey_cmd(struct _adapter *padapter,
        }
        set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
        r8712_enqueue_cmd(pcmdpriv, ph2c);
-       _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT);
+       mod_timer(&pmlmepriv->scan_to_timer,
+                 jiffies + msecs_to_jiffies(SCANNING_TIMEOUT));
        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_SITE_SURVEY);
        padapter->blnEnableRxFF0Filter = 0;
        return _SUCCESS;
@@ -530,8 +531,8 @@ u8 r8712_joinbss_cmd(struct _adapter  *padapter, struct wlan_network *pnetwork)
         * the driver just has the bssid information for PMKIDList searching.
         */
        if (pmlmepriv->assoc_by_bssid == false)
-               memcpy(&pmlmepriv->assoc_bssid[0],
-                       &pnetwork->network.MacAddress[0], ETH_ALEN);
+               ether_addr_copy(&pmlmepriv->assoc_bssid[0],
+                               &pnetwork->network.MacAddress[0]);
        psecnetwork->IELength = r8712_restruct_sec_ie(padapter,
                                                &pnetwork->network.IEs[0],
                                                &psecnetwork->IEs[0],
@@ -682,7 +683,7 @@ u8 r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key)
        init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
        ph2c->rsp = (u8 *) psetstakey_rsp;
        ph2c->rspsz = sizeof(struct set_stakey_rsp);
-       memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
+       ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
                psetstakey_para->algorithm = (unsigned char)
                                            psecuritypriv->PrivacyAlgrthm;
@@ -784,7 +785,7 @@ u8 r8712_setMacAddr_cmd(struct _adapter *padapter, u8 *mac_addr)
        }
        init_h2fwcmd_w_parm_no_rsp(ph2c, psetMacAddr_para,
                                   _SetMacAddress_CMD_);
-       memcpy(psetMacAddr_para->MacAddr, mac_addr, ETH_ALEN);
+       ether_addr_copy(psetMacAddr_para->MacAddr, mac_addr);
        r8712_enqueue_cmd(pcmdpriv, ph2c);
        return _SUCCESS;
 }
@@ -813,7 +814,7 @@ u8 r8712_setassocsta_cmd(struct _adapter *padapter, u8 *mac_addr)
        init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_);
        ph2c->rsp = (u8 *) psetassocsta_rsp;
        ph2c->rspsz = sizeof(struct set_assocsta_rsp);
-       memcpy(psetassocsta_para->addr, mac_addr, ETH_ALEN);
+       ether_addr_copy(psetassocsta_para->addr, mac_addr);
        r8712_enqueue_cmd(pcmdpriv, ph2c);
        return _SUCCESS;
 }
@@ -890,7 +891,8 @@ void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
        if (pcmd->res != H2C_SUCCESS)
-               _set_timer(&pmlmepriv->assoc_timer, 1);
+               mod_timer(&pmlmepriv->assoc_timer,
+                         jiffies + msecs_to_jiffies(1));
        r8712_free_cmd_obj(pcmd);
 }
 
@@ -898,7 +900,6 @@ void r8712_createbss_cmd_callback(struct _adapter *padapter,
                                  struct cmd_obj *pcmd)
 {
        unsigned long irqL;
-       u8 timer_cancelled;
        struct sta_info *psta = NULL;
        struct wlan_network *pwlan = NULL;
        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
@@ -907,8 +908,9 @@ void r8712_createbss_cmd_callback(struct _adapter *padapter,
        struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
 
        if (pcmd->res != H2C_SUCCESS)
-               _set_timer(&pmlmepriv->assoc_timer, 1);
-       _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
+               mod_timer(&pmlmepriv->assoc_timer,
+                         jiffies + msecs_to_jiffies(1));
+       del_timer_sync(&pmlmepriv->assoc_timer);
 #ifdef __BIG_ENDIAN
        /* endian_convert */
        pnetwork->Length = le32_to_cpu(pnetwork->Length);
index 2f145d63fcecbf6b16898e35803c367033fce360..50339e67da071015a0e4c00a4693693fab08efcb 100644 (file)
@@ -64,7 +64,7 @@ static void shift_out_bits(struct _adapter *padapter, u16 data, u16 count)
                udelay(CLOCK_RATE);
                up_clk(padapter, &x);
                down_clk(padapter, &x);
-               mask = mask >> 1;
+               mask >>= 1;
        } while (mask);
        if (padapter->bSurpriseRemoved == true)
                goto out;
@@ -83,7 +83,7 @@ static u16 shift_in_bits(struct _adapter *padapter)
        x &= ~(_EEDO | _EEDI);
        d = 0;
        for (i = 0; i < 16; i++) {
-               d = d << 1;
+               d <<= 1;
                up_clk(padapter, &x);
                if (padapter->bSurpriseRemoved == true)
                        goto out;
index 9bb364f04fd49b59152fd0e792e33f161b937ee3..42fba3f5b593e08801a57269ede5e21da8c8841f 100644 (file)
@@ -46,6 +46,8 @@
 #include <linux/semaphore.h>
 #include <net/iw_handler.h>
 #include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+
 
 #define RTL_IOCTL_WPA_SUPPLICANT       (SIOCIWFIRSTPRIV + 0x1E)
 
@@ -112,7 +114,7 @@ void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
        union iwreq_data wrqu;
 
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-       memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+       eth_zero_addr(wrqu.ap_addr.sa_data);
        wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
 }
 
@@ -129,7 +131,8 @@ static inline void handle_pairwise_key(struct sta_info *psta,
                memcpy(psta->tkiprxmickey. skey, &(param->u.crypt.
                        key[24]), 8);
                padapter->securitypriv. busetkipkey = false;
-               _set_timer(&padapter->securitypriv.tkip_timer, 50);
+               mod_timer(&padapter->securitypriv.tkip_timer,
+                         jiffies + msecs_to_jiffies(50));
        }
        r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
 }
@@ -153,8 +156,8 @@ static inline void handle_group_key(struct ieee_param *param,
                if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
                        if (padapter->registrypriv.power_mgnt != padapter->
                            pwrctrlpriv.pwr_mode)
-                               _set_timer(&(padapter->mlmepriv.dhcp_timer),
-                                          60000);
+                               mod_timer(&padapter->mlmepriv.dhcp_timer,
+                                         jiffies + msecs_to_jiffies(60000));
                }
        }
 }
@@ -182,7 +185,7 @@ static inline char *translate_scan(struct _adapter *padapter,
        /* AP MAC address */
        iwe.cmd = SIOCGIWAP;
        iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-       memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
+       ether_addr_copy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress);
        start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
        /* Add the ESSID */
        iwe.cmd = SIOCGIWESSID;
@@ -360,7 +363,7 @@ static inline char *translate_scan(struct _adapter *padapter,
 
 static int wpa_set_auth_algs(struct net_device *dev, u32 value)
 {
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        int ret = 0;
 
        if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
@@ -392,7 +395,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
        int ret = 0;
        u32 wep_key_idx, wep_key_len = 0;
        struct NDIS_802_11_WEP   *pwep = NULL;
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
        struct security_priv *psecuritypriv = &padapter->securitypriv;
 
@@ -626,7 +629,7 @@ static int r8711_wx_get_name(struct net_device *dev,
                             struct iw_request_info *info,
                             union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        u32 ht_ielen = 0;
        char *p;
        u8 ht_cap = false;
@@ -682,7 +685,7 @@ static int r8711_wx_set_freq(struct net_device *dev,
                             struct iw_request_info *info,
                             union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct iw_freq *fwrq = &wrqu->freq;
        int rc = 0;
 
@@ -718,7 +721,7 @@ static int r8711_wx_get_freq(struct net_device *dev,
                             struct iw_request_info *info,
                             union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
        struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
 
@@ -737,7 +740,7 @@ static int r8711_wx_set_mode(struct net_device *dev,
                             struct iw_request_info *a,
                             union iwreq_data *wrqu, char *b)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
 
        switch (wrqu->mode) {
@@ -768,7 +771,7 @@ static int r8711_wx_set_mode(struct net_device *dev,
 static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
                             union iwreq_data *wrqu, char *b)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
@@ -787,7 +790,7 @@ static int r871x_wx_set_pmkid(struct net_device *dev,
                             struct iw_request_info *a,
                             union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct security_priv *psecuritypriv = &padapter->securitypriv;
        struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
        u8 strZeroMacAddress[ETH_ALEN] = {0x00};
@@ -851,8 +854,7 @@ static int r871x_wx_set_pmkid(struct net_device *dev,
                            strIssueBssid, ETH_ALEN)) {
                                /* BSSID is matched, the same AP => Remove
                                 * this PMKID information and reset it. */
-                               memset(psecuritypriv->PMKIDList[j].Bssid,
-                                       0x00, ETH_ALEN);
+                               eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
                                psecuritypriv->PMKIDList[j].bUsed = false;
                                break;
                        }
@@ -1059,7 +1061,7 @@ static int r8711_wx_set_wap(struct net_device *dev,
                         char *extra)
 {
        int ret = -EINPROGRESS;
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
        struct  __queue *queue = &pmlmepriv->scanned_queue;
        struct sockaddr *temp = (struct sockaddr *)awrq;
@@ -1108,16 +1110,16 @@ static int r8711_wx_get_wap(struct net_device *dev,
                                struct iw_request_info *info,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
        struct ndis_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 |
                                     WIFI_AP_STATE))
-               memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
+               ether_addr_copy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress);
        else
-               memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+               eth_zero_addr(wrqu->ap_addr.sa_data);
        return 0;
 }
 
@@ -1126,7 +1128,7 @@ static int r871x_wx_set_mlme(struct net_device *dev,
                             union iwreq_data *wrqu, char *extra)
 {
        int ret = 0;
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct iw_mlme *mlme = (struct iw_mlme *) extra;
 
        if (mlme == NULL)
@@ -1158,7 +1160,7 @@ static int r8711_wx_set_scan(struct net_device *dev,
                        struct iw_request_info *a,
                        union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
        u8 status = true;
 
@@ -1207,7 +1209,7 @@ static int r8711_wx_get_scan(struct net_device *dev,
                                struct iw_request_info *a,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
        struct  __queue *queue = &pmlmepriv->scanned_queue;
        struct wlan_network *pnetwork = NULL;
@@ -1261,7 +1263,7 @@ static int r8711_wx_set_essid(struct net_device *dev,
                                struct iw_request_info *a,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
        struct  __queue *queue = &pmlmepriv->scanned_queue;
        struct wlan_network *pnetwork = NULL;
@@ -1324,7 +1326,7 @@ static int r8711_wx_get_essid(struct net_device *dev,
                                struct iw_request_info *a,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
        struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
        u32 len, ret = 0;
@@ -1344,7 +1346,7 @@ static int r8711_wx_set_rate(struct net_device *dev,
                                struct iw_request_info *a,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        u32 target_rate = wrqu->bitrate.value;
        u32 fixed = wrqu->bitrate.fixed;
        u32 ratevalue = 0;
@@ -1416,7 +1418,7 @@ static int r8711_wx_get_rate(struct net_device *dev,
                             struct iw_request_info *info,
                             union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(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 ieee80211_ht_cap *pht_capie;
@@ -1473,7 +1475,7 @@ static int r8711_wx_get_rts(struct net_device *dev,
                                struct iw_request_info *info,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
 
        wrqu->rts.value = padapter->registrypriv.rts_thresh;
        wrqu->rts.fixed = 0;    /* no auto select */
@@ -1484,7 +1486,7 @@ static int r8711_wx_set_frag(struct net_device *dev,
                                struct iw_request_info *info,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
 
        if (wrqu->frag.disabled)
                padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
@@ -1501,7 +1503,7 @@ static int r8711_wx_get_frag(struct net_device *dev,
                                struct iw_request_info *info,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
 
        wrqu->frag.value = padapter->xmitpriv.frag_len;
        wrqu->frag.fixed = 0;   /* no auto select */
@@ -1527,7 +1529,7 @@ static int r8711_wx_set_enc(struct net_device *dev,
        struct NDIS_802_11_WEP   wep;
        enum NDIS_802_11_AUTHENTICATION_MODE authmode;
        struct iw_point *erq = &(wrqu->encoding);
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
 
        key = erq->flags & IW_ENCODE_INDEX;
        memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
@@ -1619,7 +1621,7 @@ static int r8711_wx_get_enc(struct net_device *dev,
                                union iwreq_data *wrqu, char *keybuf)
 {
        uint key, ret = 0;
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct iw_point *erq = &(wrqu->encoding);
        struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
 
@@ -1691,7 +1693,7 @@ static int r871x_wx_set_gen_ie(struct net_device *dev,
                                struct iw_request_info *info,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
 
        return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
 }
@@ -1700,7 +1702,7 @@ static int r871x_wx_set_auth(struct net_device *dev,
                                struct iw_request_info *info,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct iw_param *param = (struct iw_param *)&(wrqu->param);
        int paramid;
        int paramval;
@@ -1847,7 +1849,7 @@ static int r8711_wx_read32(struct net_device *dev,
                                struct iw_request_info *info,
                                union iwreq_data *wrqu, char *keybuf)
 {
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        u32 addr;
        u32 data32;
 
@@ -1864,7 +1866,7 @@ static int r8711_wx_write32(struct net_device *dev,
                                 struct iw_request_info *info,
                                 union iwreq_data *wrqu, char *keybuf)
 {
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        u32 addr;
        u32 data32;
 
@@ -1892,7 +1894,7 @@ static int r871x_mp_ioctl_hdl(struct net_device *dev,
                                struct iw_request_info *info,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct iw_point *p = &wrqu->data;
        struct oid_par_priv oid_par;
        struct mp_ioctl_handler *phandler;
@@ -1910,13 +1912,9 @@ static int r871x_mp_ioctl_hdl(struct net_device *dev,
        bset = (u8)(p->flags & 0xFFFF);
        len = p->length;
        pparmbuf = NULL;
-       pparmbuf = kmalloc(len, GFP_ATOMIC);
-       if (pparmbuf == NULL) {
-               ret = -ENOMEM;
-               goto _r871x_mp_ioctl_hdl_exit;
-       }
-       if (copy_from_user(pparmbuf, p->pointer, len)) {
-               ret = -EFAULT;
+       pparmbuf = memdup_user(p->pointer, len);
+       if (IS_ERR(pparmbuf)) {
+               ret = PTR_ERR(pparmbuf);
                goto _r871x_mp_ioctl_hdl_exit;
        }
        poidparam = (struct mp_ioctl_param *)pparmbuf;
@@ -1975,7 +1973,7 @@ static int r871x_get_ap_info(struct net_device *dev,
                                struct iw_request_info *info,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
        struct  __queue *queue = &pmlmepriv->scanned_queue;
        struct iw_point *pdata = &wrqu->data;
@@ -2046,7 +2044,7 @@ static int r871x_set_pid(struct net_device *dev,
                                struct iw_request_info *info,
                                union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct iw_point *pdata = &wrqu->data;
 
        if ((padapter->bDriverStopped) || (pdata == NULL))
@@ -2061,7 +2059,7 @@ static int r871x_set_chplan(struct net_device *dev,
                                union iwreq_data *wrqu, char *extra)
 {
        int ret = 0;
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct iw_point *pdata = &wrqu->data;
        int ch_plan = -1;
 
@@ -2081,7 +2079,7 @@ static int r871x_wps_start(struct net_device *dev,
                           struct iw_request_info *info,
                           union iwreq_data *wrqu, char *extra)
 {
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct iw_point *pdata = &wrqu->data;
        u32   u32wps_start = 0;
 
@@ -2105,7 +2103,7 @@ static int r871x_wps_start(struct net_device *dev,
 
 static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
 {
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
 
        switch (name) {
        case IEEE_PARAM_WPA_ENABLED:
@@ -2157,7 +2155,7 @@ static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
 
 static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
 {
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
 
        switch (command) {
        case IEEE_MLME_STA_DEAUTH:
@@ -2178,7 +2176,7 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
 {
        struct ieee_param *param;
        int ret = 0;
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
 
        if (p->length < sizeof(struct ieee_param) || !p->pointer)
                return -EINVAL;
@@ -2331,7 +2329,7 @@ static iw_handler r8711_private_handler[] = {
 
 static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
 {
-       struct _adapter *padapter = (struct _adapter *) netdev_priv(dev);
+       struct _adapter *padapter = netdev_priv(dev);
        struct iw_statistics *piwstats = &padapter->iwstats;
        int tmp_level = 0;
        int tmp_qual = 0;
index 6318a0e65e6e6c9831f07ccde9f90b3c25967707..22262b3558bacd5db51f174cd416fdbc0f332c4e 100644 (file)
@@ -85,7 +85,8 @@ static u8 do_join(struct _adapter *padapter)
 
                ret = r8712_select_and_join_from_scan(pmlmepriv);
                if (ret == _SUCCESS)
-                       _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
+                       mod_timer(&pmlmepriv->assoc_timer,
+                                 jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
                else {
                        if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
                                /* submit r8712_createbss_cmd to change to an
@@ -265,8 +266,7 @@ void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter,
                /* clear WIFI_STATION_STATE; WIFI_AP_STATE; WIFI_ADHOC_STATE;
                 * WIFI_ADHOC_MASTER_STATE */
                _clr_fwstate_(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE |
-                             WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE |
-                             WIFI_AP_STATE);
+                             WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE);
                switch (networktype) {
                case Ndis802_11IBSS:
                        set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
index 977a83358056a3ac7fe7b07661426bb935bdd48d..fb2b195b90af0d1690552dfccb6ec93b13960fdf 100644 (file)
@@ -582,9 +582,7 @@ void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 
        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
-               u8 timer_cancelled;
-
-               _cancel_timer(&pmlmepriv->scan_to_timer, &timer_cancelled);
+               del_timer_sync(&pmlmepriv->scan_to_timer);
 
                _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
        }
@@ -596,8 +594,8 @@ void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
 
                                if (r8712_select_and_join_from_scan(pmlmepriv)
                                    == _SUCCESS)
-                                       _set_timer(&pmlmepriv->assoc_timer,
-                                                  MAX_JOIN_TIMEOUT);
+                                       mod_timer(&pmlmepriv->assoc_timer, jiffies +
+                                                 msecs_to_jiffies(MAX_JOIN_TIMEOUT));
                                else {
                                        struct wlan_bssid_ex *pdev_network =
                                          &(adapter->registrypriv.dev_network);
@@ -622,8 +620,8 @@ void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
                        set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
                        if (r8712_select_and_join_from_scan(pmlmepriv) ==
                            _SUCCESS)
-                               _set_timer(&pmlmepriv->assoc_timer,
-                                          MAX_JOIN_TIMEOUT);
+                               mod_timer(&pmlmepriv->assoc_timer, jiffies +
+                                         msecs_to_jiffies(MAX_JOIN_TIMEOUT));
                        else
                                _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
                }
@@ -679,7 +677,8 @@ void r8712_indicate_connect(struct _adapter *padapter)
        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_LINK);
        r8712_os_indicate_connect(padapter);
        if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE)
-               _set_timer(&pmlmepriv->dhcp_timer, 60000);
+               mod_timer(&pmlmepriv->dhcp_timer,
+                         jiffies + msecs_to_jiffies(60000));
 }
 
 
@@ -697,7 +696,7 @@ void r8712_ind_disconnect(struct _adapter *padapter)
        }
        if (padapter->pwrctrlpriv.pwr_mode !=
            padapter->registrypriv.power_mgnt) {
-               _cancel_timer_ex(&pmlmepriv->dhcp_timer);
+               del_timer_sync(&pmlmepriv->dhcp_timer);
                r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
                                  padapter->registrypriv.smart_ps);
        }
@@ -716,7 +715,6 @@ void r8712_ind_disconnect(struct _adapter *padapter)
 void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
 {
        unsigned long irqL = 0, irqL2;
-       u8 timer_cancelled;
        struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
        struct sta_priv *pstapriv = &adapter->stapriv;
        struct mlme_priv        *pmlmepriv = &adapter->mlmepriv;
@@ -727,6 +725,8 @@ void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
 
        if (sizeof(struct list_head) == 4 * sizeof(u32)) {
                pnetwork = kmalloc(sizeof(struct wlan_network), GFP_ATOMIC);
+               if (!pnetwork)
+                       return;
                memcpy((u8 *)pnetwork+16, (u8 *)pbuf + 8,
                        sizeof(struct wlan_network) - 16);
        } else
@@ -910,13 +910,13 @@ void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
                        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
                                == true)
                                r8712_indicate_connect(adapter);
-                       _cancel_timer(&pmlmepriv->assoc_timer,
-                                     &timer_cancelled);
+                       del_timer_sync(&pmlmepriv->assoc_timer);
                } else
                        goto ignore_joinbss_callback;
        } else {
                if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
-                       _set_timer(&pmlmepriv->assoc_timer, 1);
+                       mod_timer(&pmlmepriv->assoc_timer,
+                                 jiffies + msecs_to_jiffies(1));
                        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
                }
        }
@@ -1599,17 +1599,15 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
        iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
        if (iEntry < 0)
                return ielength;
-       else {
-               if (authmode == _WPA2_IE_ID_) {
-                       out_ie[ielength] = 1;
-                       ielength++;
-                       out_ie[ielength] = 0;   /*PMKID count = 0x0100*/
-                       ielength++;
-                       memcpy(&out_ie[ielength],
-                               &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
-                       ielength += 16;
-                       out_ie[13] += 18;/*PMKID length = 2+16*/
-               }
+       if (authmode == _WPA2_IE_ID_) {
+               out_ie[ielength] = 1;
+               ielength++;
+               out_ie[ielength] = 0;   /*PMKID count = 0x0100*/
+               ielength++;
+               memcpy(&out_ie[ielength],
+                       &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
+               ielength += 16;
+               out_ie[13] += 18;/*PMKID length = 2+16*/
        }
        return ielength;
 }
index 3d913b9701bba873179b156aeca303861f01b0dd..26201ea3cca6594e6a2405821a0337426927d2a3 100644 (file)
@@ -327,8 +327,8 @@ void r8712_SetTxAGCOffset(struct _adapter *pAdapter, u32 ulTxAGCOffset)
        u32 TxAGCOffset_B, TxAGCOffset_C, TxAGCOffset_D, tmpAGC;
 
        TxAGCOffset_B = (ulTxAGCOffset&0x000000ff);
-       TxAGCOffset_C = ((ulTxAGCOffset&0x0000ff00)>>8);
-       TxAGCOffset_D = ((ulTxAGCOffset&0x00ff0000)>>16);
+       TxAGCOffset_C = (ulTxAGCOffset & 0x0000ff00)>>8;
+       TxAGCOffset_D = (ulTxAGCOffset & 0x00ff0000)>>16;
        tmpAGC = (TxAGCOffset_D<<8 | TxAGCOffset_C<<4 | TxAGCOffset_B);
        set_bb_reg(pAdapter, rFPGA0_TxGainStage,
                        (bXBTxAGC|bXCTxAGC|bXDTxAGC), tmpAGC);
index ed2844d2b02abcf3345bfba74e72dc98865d1410..aaa584435c87d25d3efb3bbbe794da6cf2096c24 100644 (file)
@@ -103,7 +103,7 @@ void r8712_cpwm_int_hdl(struct _adapter *padapter,
 
        if (pwrpriv->cpwm_tog == ((preportpwrstate->state) & 0x80))
                return;
-       _cancel_timer_ex(&padapter->pwrctrlpriv. rpwm_check_timer);
+       del_timer_sync(&padapter->pwrctrlpriv.rpwm_check_timer);
        _enter_pwrlock(&pwrpriv->lock);
        pwrpriv->cpwm = (preportpwrstate->state) & 0xf;
        if (pwrpriv->cpwm >= PS_STATE_S2) {
@@ -165,9 +165,9 @@ static void rpwm_workitem_callback(struct work_struct *work)
        }
 }
 
-static void rpwm_check_handler (void *FunctionContext)
+static void rpwm_check_handler (unsigned long data)
 {
-       struct _adapter *adapter = (struct _adapter *)FunctionContext;
+       struct _adapter *adapter = (struct _adapter *)data;
 
        _rpwm_check_handler(adapter);
 }
@@ -186,8 +186,8 @@ void r8712_init_pwrctrl_priv(struct _adapter *padapter)
        r8712_write8(padapter, 0x1025FE58, 0);
        INIT_WORK(&pwrctrlpriv->SetPSModeWorkItem, SetPSModeWorkItemCallback);
        INIT_WORK(&pwrctrlpriv->rpwm_workitem, rpwm_workitem_callback);
-       _init_timer(&(pwrctrlpriv->rpwm_check_timer),
-                   padapter->pnetdev, rpwm_check_handler, (u8 *)padapter);
+       setup_timer(&pwrctrlpriv->rpwm_check_timer, rpwm_check_handler,
+                   (unsigned long)padapter);
 }
 
 /*
index 06f15f81c4d86062c53f00e33617945e6688ace7..046a46c4cd7ff1e2f392f827ab6272569b5bff90 100644 (file)
@@ -517,8 +517,7 @@ static sint validate_recv_data_frame(struct _adapter *adapter,
                return _FAIL;
        if (psta == NULL)
                return _FAIL;
-       else
-               precv_frame->u.hdr.psta = psta;
+       precv_frame->u.hdr.psta = psta;
        pattrib->amsdu = 0;
        /* parsing QC field */
        if (pattrib->qos == 1) {
index c653ad6854b4d3776c978730b924e6ee02535704..bcd1a51288689d1043d069b3d96829baa87b8408 100644 (file)
@@ -153,7 +153,7 @@ static u32 getcrc32(u8 *buf, u32 len)
        u8 *p;
        u32  crc;
 
-       if (bcrc32initialized == 0)
+       if (!bcrc32initialized)
                crc32_init();
        crc = 0xffffffff; /* preload shift register, per CRC-32 spec */
        for (p = buf; len > 0; ++p, --len)
@@ -1045,7 +1045,7 @@ static sint aes_cipher(u8 *key, uint      hdrlen,
        uint    frtype  = GetFrameType(pframe);
        uint    frsubtype  = GetFrameSubType(pframe);
 
-       frsubtype = frsubtype >> 4;
+       frsubtype >>= 4;
        memset((void *)mic_iv, 0, 16);
        memset((void *)mic_header1, 0, 16);
        memset((void *)mic_header2, 0, 16);
@@ -1086,7 +1086,7 @@ static sint aes_cipher(u8 *key, uint      hdrlen,
        payload_remainder = plen % 16;
        num_blocks = plen / 16;
        /* Find start of payload */
-       payload_index = (hdrlen + 8);
+       payload_index = hdrlen + 8;
        /* Calculate MIC */
        aes128k128d(key, mic_iv, aes_out);
        bitwise_xor(aes_out, mic_header1, chain_buffer);
@@ -1216,7 +1216,7 @@ static sint aes_decipher(u8 *key, uint    hdrlen,
        uint frtype  = GetFrameType(pframe);
        uint frsubtype  = GetFrameSubType(pframe);
 
-       frsubtype = frsubtype >> 4;
+       frsubtype >>= 4;
        memset((void *)mic_iv, 0, 16);
        memset((void *)mic_header1, 0, 16);
        memset((void *)mic_header2, 0, 16);
@@ -1292,7 +1292,7 @@ static sint aes_decipher(u8 *key, uint    hdrlen,
        payload_remainder = (plen - 8) % 16;
        num_blocks = (plen - 8) / 16;
        /* Find start of payload */
-       payload_index = (hdrlen + 8);
+       payload_index = hdrlen + 8;
        /* Calculate MIC */
        aes128k128d(key, mic_iv, aes_out);
        bitwise_xor(aes_out, mic_header1, chain_buffer);
@@ -1392,9 +1392,9 @@ u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe)
        return _SUCCESS;
 }
 
-void r8712_use_tkipkey_handler(void *FunctionContext)
+void r8712_use_tkipkey_handler(unsigned long data)
 {
-       struct _adapter *padapter = (struct _adapter *)FunctionContext;
+       struct _adapter *padapter = (struct _adapter *)data;
 
        padapter->securitypriv.busetkipkey = true;
 }
index c732aeab8d2c67049900abce4fb48c150bb5605a..2295f0e64dc2c7d0ef867903324caf6cf379db65 100644 (file)
@@ -216,7 +216,7 @@ void r8712_wep_encrypt(struct _adapter *padapter, u8  *pxmitframe);
 u32 r8712_aes_decrypt(struct _adapter *padapter, u8  *precvframe);
 u32 r8712_tkip_decrypt(struct _adapter *padapter, u8  *precvframe);
 void r8712_wep_decrypt(struct _adapter *padapter, u8  *precvframe);
-void r8712_use_tkipkey_handler(void *FunctionContext);
+void r8712_use_tkipkey_handler(unsigned long data);
 
 #endif /*__RTL871X_SECURITY_H_ */
 
index 1752121ff494d5274325a2aacb6e2d4945e87fe1..7bb96c47f1883dad0c62e8618b2e98ac773fca27 100644 (file)
@@ -198,7 +198,7 @@ void r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta)
         * cancel reordering_ctrl_timer */
        for (i = 0; i < 16; i++) {
                preorder_ctrl = &psta->recvreorder_ctrl[i];
-               _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
+               del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
        }
        spin_lock(&(pfree_sta_queue->lock));
        /* insert into free_sta_queue; 20061114 */
index a28af03c9d8adb4e4b51e5c708cd3456b7e344c3..2e4fa88951ad88f4a622fe9a81e9641ca69ba7ea 100644 (file)
@@ -203,13 +203,12 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
        pattrib->ether_type = ntohs(etherhdr.h_proto);
 
 {
-       u8 bool;
        /*If driver xmit ARP packet, driver can set ps mode to initial
         * setting. It stands for getting DHCP or fix IP.*/
        if (pattrib->ether_type == 0x0806) {
                if (padapter->pwrctrlpriv.pwr_mode !=
                    padapter->registrypriv.power_mgnt) {
-                       _cancel_timer(&(pmlmepriv->dhcp_timer), &bool);
+                       del_timer_sync(&pmlmepriv->dhcp_timer);
                        r8712_set_ps_mode(padapter, padapter->registrypriv.
                                power_mgnt, padapter->registrypriv.smart_ps);
                }
index 73d7cd28060750e5114b9df332a8b3dea40c46bb..17f513122f48b79ec71ed03df80893af4a94b533 100644 (file)
@@ -235,11 +235,6 @@ enum WIFI_REG_DOMAIN {
 #define GetPrivacy(pbuf)       (((*(unsigned short *)(pbuf)) & \
                                le16_to_cpu(_PRIVACY_)) != 0)
 
-#define ClearPrivacy(pbuf) ({ \
-       *(unsigned short *)(pbuf) &= (~cpu_to_le16(_PRIVACY_)); \
-})
-
-
 #define GetOrder(pbuf) (((*(unsigned short *)(pbuf)) & \
                        le16_to_cpu(_ORDER_)) != 0)
 
@@ -248,9 +243,9 @@ enum WIFI_REG_DOMAIN {
 
 #define SetFrameType(pbuf, type)       \
        do {    \
-               *(unsigned short *)(pbuf) &= __constant_cpu_to_le16(~(BIT(3) | \
+               *(unsigned short *)(pbuf) &= cpu_to_le16(~(BIT(3) | \
                BIT(2))); \
-               *(unsigned short *)(pbuf) |= __constant_cpu_to_le16(type); \
+               *(unsigned short *)(pbuf) |= cpu_to_le16(type); \
        } while (0)
 
 #define GetFrameSubType(pbuf)  (cpu_to_le16(*(unsigned short *)(pbuf)) & \
@@ -270,16 +265,6 @@ enum WIFI_REG_DOMAIN {
 #define GetFragNum(pbuf)       (cpu_to_le16(*(unsigned short *)((addr_t)\
                                (pbuf) + 22)) & 0x0f)
 
-#define GetTupleCache(pbuf)    (cpu_to_le16(*(unsigned short *)\
-                               ((addr_t)(pbuf) + 22)))
-
-#define SetFragNum(pbuf, num) ({ \
-       *(unsigned short *)((addr_t)(pbuf) + 22) = \
-       ((*(unsigned short *)((addr_t)(pbuf) + 22)) & \
-       le16_to_cpu(~(0x000f))) | \
-       cpu_to_le16(0x0f & (num));     \
-})
-
 #define SetSeqNum(pbuf, num) ({ \
        *(unsigned short *)((addr_t)(pbuf) + 22) = \
        ((*(unsigned short *)((addr_t)(pbuf) + 22)) & \
@@ -306,17 +291,9 @@ enum WIFI_REG_DOMAIN {
 
 #define GetAMsdu(pbuf) (((le16_to_cpu(*(unsigned short *)pbuf)) >> 7) & 0x1)
 
-#define SetAMsdu(pbuf, amsdu) ({ \
-       *(unsigned short *)(pbuf) |= cpu_to_le16((amsdu & 1) << 7); \
-})
-
 #define GetAid(pbuf)   (cpu_to_le16(*(unsigned short *)((addr_t)(pbuf) + 2)) \
                        & 0x3fff)
 
-#define GetTid(pbuf)   (cpu_to_le16(*(unsigned short *)((addr_t)(pbuf) + \
-                       (((GetToDs(pbuf) << 1)|GetFrDs(pbuf)) == 3 ? \
-                       30 : 24))) & 0x000f)
-
 #define GetAddr1Ptr(pbuf)      ((unsigned char *)((addr_t)(pbuf) + 4))
 
 #define GetAddr2Ptr(pbuf)      ((unsigned char *)((addr_t)(pbuf) + 10))
index 039b598152bca572491e7020ac7abfddb504a7bc..d15fb1ad45b9f9128f924a96b56e32243aa12987 100644 (file)
@@ -162,7 +162,7 @@ void r8712_xmit_complete(struct _adapter *padapter, struct xmit_frame *pxframe)
 int r8712_xmit_entry(_pkt *pkt, struct  net_device *pnetdev)
 {
        struct xmit_frame *pxmitframe = NULL;
-       struct _adapter *padapter = (struct _adapter *)netdev_priv(pnetdev);
+       struct _adapter *padapter = netdev_priv(pnetdev);
        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
        int ret = 0;
 
index c6327c07291837396861062d23f3e0c1e40e3457..645668950e9cc817545ecb1a6f9279b1afcc9a38 100644 (file)
@@ -20,6 +20,7 @@
 #include <wifi.h>
 #include <rtl8723a_cmd.h>
 #include <rtl8723a_hal.h>
+#include <asm/unaligned.h>
 
 extern unsigned char WMM_OUI23A[];
 extern unsigned char WPS_OUI23A[];
@@ -72,11 +73,8 @@ static void update_BCNTIM(struct rtw_adapter *padapter)
        struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
        unsigned char *pie = pnetwork_mlmeext->IEs;
        u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
-       __le16 tim_bitmap_le;
        uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
 
-       tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);
-
        p = rtw_get_ie23a(pie, WLAN_EID_TIM, &tim_ielen,
                          pnetwork_mlmeext->IELength);
        if (p != NULL && tim_ielen > 0) {
@@ -143,9 +141,9 @@ static void update_BCNTIM(struct rtw_adapter *padapter)
                *dst_ie++ = 0;
 
        if (tim_ielen == 4) {
-               *dst_ie++ = *(u8 *)&tim_bitmap_le;
+               *dst_ie++ = pstapriv->tim_bitmap & 0xff;
        } else if (tim_ielen == 5) {
-               memcpy(dst_ie, &tim_bitmap_le, 2);
+               put_unaligned_le16(pstapriv->tim_bitmap, dst_ie);
                dst_ie += 2;
        }
 
@@ -262,15 +260,17 @@ void      expire_timeout_chk23a(struct rtw_adapter *padapter)
                        list_del_init(&psta->asoc_list);
                        pstapriv->asoc_list_cnt--;
 
-                       DBG_8723A("asoc expire "MAC_FMT", state = 0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
+                       DBG_8723A("asoc expire %pM, state = 0x%x\n",
+                                 psta->hwaddr, psta->state);
                        updated = ap_free_sta23a(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING);
                } else {
                        /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
                        if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt)
                                && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2)
                        ) {
-                               DBG_8723A("%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__,
-                                         MAC_ARG(psta->hwaddr),
+                               DBG_8723A("%s sta:%pM, sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n",
+                                         __func__,
+                                         psta->hwaddr,
                                          psta->sleepq_len,
                                          padapter->xmitpriv.free_xmitframe_cnt,
                                          pstapriv->asoc_list_cnt);
@@ -307,7 +307,8 @@ void        expire_timeout_chk23a(struct rtw_adapter *padapter)
 
                psta->keep_alive_trycnt++;
                if (ret == _SUCCESS) {
-                       DBG_8723A("asoc check, sta(" MAC_FMT ") is alive\n", MAC_ARG(psta->hwaddr));
+                       DBG_8723A("asoc check, sta(%pM) is alive\n",
+                                 psta->hwaddr);
                        psta->expire_to = pstapriv->expire_to;
                        psta->keep_alive_trycnt = 0;
                        continue;
@@ -319,7 +320,8 @@ void        expire_timeout_chk23a(struct rtw_adapter *padapter)
 
                psta->keep_alive_trycnt = 0;
 
-               DBG_8723A("asoc expire "MAC_FMT", state = 0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
+               DBG_8723A("asoc expire %pM, state = 0x%x\n",
+                         psta->hwaddr, psta->state);
                spin_lock_bh(&pstapriv->asoc_list_lock);
                if (!list_empty(&psta->asoc_list)) {
                        list_del_init(&psta->asoc_list);
@@ -785,6 +787,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter,
        struct wlan_bssid_ex *pbss_network = &pmlmepriv->cur_network.network;
        u8 *ie = pbss_network->IEs;
        u8 *pbuf = mgmt->u.beacon.variable;
+
        len -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
        /* SSID */
        /* Supported rates */
@@ -1045,7 +1048,7 @@ int rtw_acl_add_sta23a(struct rtw_adapter *padapter, u8 *addr)
        struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
        struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q;
 
-       DBG_8723A("%s(acl_num =%d) =" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));
+       DBG_8723A("%s(acl_num =%d) =%pM\n", __func__, pacl_list->num, addr);
 
        if ((NUM_ACL-1) < pacl_list->num)
                return -1;
@@ -1477,8 +1480,8 @@ void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info
        if (psta->flags & WLAN_STA_HT) {
                u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);
 
-               DBG_8723A("HT: STA " MAC_FMT " HT Capabilities "
-                          "Info: 0x%04x\n", MAC_ARG(psta->hwaddr), ht_capab);
+               DBG_8723A("HT: STA %pM HT Capabilities Info: 0x%04x\n",
+                         psta->hwaddr, ht_capab);
 
                if (psta->no_ht_set) {
                        psta->no_ht_set = 0;
@@ -1490,10 +1493,9 @@ void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info
                                psta->no_ht_gf_set = 1;
                                pmlmepriv->num_sta_ht_no_gf++;
                        }
-                       DBG_8723A("%s STA " MAC_FMT " - no "
-                                  "greenfield, num of non-gf stations %d\n",
-                                  __func__, MAC_ARG(psta->hwaddr),
-                                  pmlmepriv->num_sta_ht_no_gf);
+                       DBG_8723A("%s STA %pM - no greenfield, num of non-gf stations %d\n",
+                                 __func__, psta->hwaddr,
+                                 pmlmepriv->num_sta_ht_no_gf);
                }
 
                if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH_20_40) == 0) {
@@ -1501,10 +1503,9 @@ void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info
                                psta->ht_20mhz_set = 1;
                                pmlmepriv->num_sta_ht_20mhz++;
                        }
-                       DBG_8723A("%s STA " MAC_FMT " - 20 MHz HT, "
-                                  "num of 20MHz HT STAs %d\n",
-                                  __func__, MAC_ARG(psta->hwaddr),
-                                  pmlmepriv->num_sta_ht_20mhz);
+                       DBG_8723A("%s STA %pM - 20 MHz HT, num of 20MHz HT STAs %d\n",
+                                 __func__, psta->hwaddr,
+                                 pmlmepriv->num_sta_ht_20mhz);
                }
 
        } else {
@@ -1513,10 +1514,9 @@ void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info
                        pmlmepriv->num_sta_no_ht++;
                }
                if (pmlmepriv->htpriv.ht_option) {
-                       DBG_8723A("%s STA " MAC_FMT
-                                  " - no HT, num of non-HT stations %d\n",
-                                  __func__, MAC_ARG(psta->hwaddr),
-                                  pmlmepriv->num_sta_no_ht);
+                       DBG_8723A("%s STA %pM - no HT, num of non-HT stations %d\n",
+                                 __func__, psta->hwaddr,
+                                 pmlmepriv->num_sta_no_ht);
                }
        }
 
index 2447a56df8381c48eddac40fe3d7fcd1c05c6f6f..46aea16cbf7887c429c200aa3b11cb413b265c3e 100644 (file)
@@ -299,9 +299,8 @@ post_process:
                pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
                if (!pcmd_callback) {
                        RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
-                                ("mlme_cmd_hdl(): pcmd_callback = 0x%p, "
-                                 "cmdcode = 0x%x\n",
-                                 pcmd_callback, pcmd->cmdcode));
+                                "mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n",
+                                pcmd_callback, pcmd->cmdcode);
                        rtw_free_cmd_obj23a(pcmd);
                } else {
                        /* need consider that free cmd_obj in
@@ -310,8 +309,8 @@ post_process:
                }
        } else {
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                        ("%s: cmdcode = 0x%x callback not defined!\n",
-                         __func__, pcmd->cmdcode));
+                        "%s: cmdcode = 0x%x callback not defined!\n",
+                        __func__, pcmd->cmdcode);
                rtw_free_cmd_obj23a(pcmd);
        }
 }
@@ -343,7 +342,7 @@ int rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter,
        rtw_free_network_queue23a(padapter);
 
        RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
-                ("%s: flush network queue\n", __func__));
+                "%s: flush network queue\n", __func__);
 
        init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
                                   GEN_CMD_CODE(_SiteSurvey));
@@ -412,12 +411,12 @@ int rtw_createbss_cmd23a(struct rtw_adapter  *padapter)
 
        if (pmlmepriv->assoc_ssid.ssid_len == 0) {
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
-                        (" createbss for Any SSid:%s\n",
-                         pmlmepriv->assoc_ssid.ssid));
+                        "createbss for Any SSid:%s\n",
+                        pmlmepriv->assoc_ssid.ssid);
        } else {
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
-                        (" createbss for SSid:%s\n",
-                         pmlmepriv->assoc_ssid.ssid));
+                        "createbss for SSid:%s\n",
+                        pmlmepriv->assoc_ssid.ssid);
        }
 
        pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
@@ -460,19 +459,18 @@ int rtw_joinbss_cmd23a(struct rtw_adapter *padapter,
 
        if (pmlmepriv->assoc_ssid.ssid_len == 0) {
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
-                        ("+Join cmd: Any SSid\n"));
+                        "+Join cmd: Any SSid\n");
        } else {
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_,
-                        ("+Join cmd: SSid =[%s]\n",
-                         pmlmepriv->assoc_ssid.ssid));
+                        "+Join cmd: SSid =[%s]\n",
+                        pmlmepriv->assoc_ssid.ssid);
        }
 
        pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
        if (!pcmd) {
                res = _FAIL;
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                        ("rtw_joinbss_cmd23a: memory allocate for cmd_obj "
-                         "fail!!!\n"));
+                        "rtw_joinbss_cmd23a: memory allocate for cmd_obj fail!!!\n");
                goto exit;
        }
 
@@ -497,7 +495,7 @@ int rtw_joinbss_cmd23a(struct rtw_adapter *padapter,
                res = _FAIL;
 
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                        ("rtw_joinbss_cmd23a :psecnetwork == NULL!!!\n"));
+                        "rtw_joinbss_cmd23a :psecnetwork == NULL!!!\n");
 
                goto exit;
        }
@@ -599,7 +597,7 @@ int rtw_disassoc_cmd23a(struct rtw_adapter *padapter, u32 deauth_timeout_ms,
        int res = _SUCCESS;
 
        RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_,
-                ("+rtw_disassoc_cmd23a\n"));
+                "+rtw_disassoc_cmd23a\n");
 
        /* prepare cmd parameter */
        param = kzalloc(sizeof(*param), GFP_ATOMIC);
@@ -1291,8 +1289,7 @@ void rtw_survey_cmd_callback23a(struct rtw_adapter *padapter,
                mod_timer(&pmlmepriv->scan_to_timer,
                          jiffies + msecs_to_jiffies(1));
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                        ("\n ********Error: MgntActrtw_set_802_11_bssid23a_"
-                         "LIST_SCAN Fail ************\n\n."));
+                        "********Error: MgntActrtw_set_802_11_bssid23a_LIST_SCAN Fail ************\n");
        }
 
        /*  free cmd */
@@ -1309,7 +1306,7 @@ void rtw_disassoc_cmd23a_callback(struct rtw_adapter *padapter,
                set_fwstate(pmlmepriv, _FW_LINKED);
                spin_unlock_bh(&pmlmepriv->lock);
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                        ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
+                        "***Error: disconnect_cmd_callback Fail ***\n");
                return;
        }
 
@@ -1329,8 +1326,7 @@ void rtw_joinbss_cmd23a_callback(struct rtw_adapter *padapter,
                          jiffies + msecs_to_jiffies(1));
        } else if (pcmd->res != H2C_SUCCESS) {
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                        ("********Error:rtw_select_and_join_from_scanned_"
-                         "queue Wait Sema  Fail ************\n"));
+                        "********Error:rtw_select_and_join_from_scanned_queue Wait Sema  Fail ************\n");
                mod_timer(&pmlmepriv->assoc_timer,
                          jiffies + msecs_to_jiffies(1));
        }
@@ -1349,8 +1345,7 @@ void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter,
 
        if (pcmd->res != H2C_SUCCESS) {
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                        ("\n ********Error: rtw_createbss_cmd23a_callback  "
-                         "Fail ************\n\n."));
+                        "********Error: rtw_createbss_cmd23a_callback  Fail ************\n");
                mod_timer(&pmlmepriv->assoc_timer,
                          jiffies + msecs_to_jiffies(1));
        }
@@ -1366,9 +1361,8 @@ void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter,
                                                    GFP_KERNEL);
                        if (!psta) {
                                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                                        ("\nCan't alloc sta_info when "
-                                         "createbss_cmd_callback\n"));
-                               goto createbss_cmd_fail ;
+                                        "Can't alloc sta_info when createbss_cmd_callback\n");
+                               goto createbss_cmd_fail;
                        }
                }
 
@@ -1382,8 +1376,7 @@ void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter,
                        pwlan = rtw_get_oldest_wlan_network23a(&pmlmepriv->scanned_queue);
                        if (!pwlan) {
                                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                                        ("\n Error:  can't get pwlan in "
-                                         "rtw23a_joinbss_event_cb\n"));
+                                        "Error:  can't get pwlan in rtw23a_joinbss_event_cb\n");
                                spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
                                goto createbss_cmd_fail;
                        }
@@ -1432,8 +1425,7 @@ void rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter *padapter,
 
        if (!psta) {
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                        ("\nERROR: rtw_setstaKey_cmdrsp_callback23a => "
-                         "can't get sta_info\n\n"));
+                        "ERROR: rtw_setstaKey_cmdrsp_callback23a => can't get sta_info\n");
                goto exit;
        }
 
@@ -1457,8 +1449,7 @@ void rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter *padapter,
 
        if (psta == NULL) {
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                        ("\nERROR: setassocsta_cmdrsp_callbac => can't "
-                         "get sta_info\n\n"));
+                        "ERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n");
                goto exit;
        }
 
index a6deddc02291392017e02ffc8c47fde8d27872cb..92a34db3bd4e3a245b3d486ecf643a2497516843 100644 (file)
@@ -304,8 +304,7 @@ EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address)
                }
                data = rtl8723au_read8(Adapter, EFUSE_CTRL);
                return data;
-       }
-       else
+       } else
                return 0xFF;
 }/* EFUSE_Read1Byte23a */
 
@@ -336,7 +335,6 @@ EFUSE_Write1Byte(struct rtw_adapter *Adapter, u16 Address, u8 Value)
        u32     k = 0;
        u16     contentLen = 0;
 
-       /* RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr =%x Data =%x\n", Address, Value)); */
        EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
                                 TYPE_EFUSE_REAL_CONTENT_LEN,
                                 (void *)&contentLen);
@@ -405,8 +403,6 @@ efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data)
        u8      tmpidx = 0;
        int     bResult;
 
-       /* RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr = %x Data =%x\n", addr, data)); */
-
        /* return       0; */
 
        /*  -----------------e-fuse reg ctrl --------------------------------- */
index bbbcfc8257da9499e7ac76e6fae7bcf62eb428fe..cdd7bc402ece86a778059a83fc866acfab182489 100644 (file)
@@ -472,8 +472,8 @@ int rtw_parse_wpa_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int
                left -= WPA_SELECTOR_LEN;
        } else if (left > 0) {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("%s: ie length mismatch, %u too much",
-                         __func__, left));
+                        "%s: ie length mismatch, %u too much\n",
+                        __func__, left);
 
                return _FAIL;
        }
@@ -487,9 +487,8 @@ int rtw_parse_wpa_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int
 
                if (count == 0 || left < count * WPA_SELECTOR_LEN) {
                        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                                ("%s: ie count botch (pairwise), "
-                                 "count %u left %u", __func__,
-                                 count, left));
+                                "%s: ie count botch (pairwise), count %u left %u\n",
+                                __func__, count, left);
                        return _FAIL;
                }
 
@@ -501,7 +500,7 @@ int rtw_parse_wpa_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int
                }
        } else if (left == 1) {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("%s: ie too short (for key mgmt)", __func__));
+                        "%s: ie too short (for key mgmt)\n", __func__);
                return _FAIL;
        }
 
@@ -510,8 +509,8 @@ int rtw_parse_wpa_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int
                        pos += 2;
                        if (!memcmp(pos, RTW_WPA_OUI23A_TYPE, 4)) {
                                RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                                        ("%s : there has 802.1x auth\n",
-                                         __func__));
+                                        "%s : there has 802.1x auth\n",
+                                        __func__);
                                *is_8021x = 1;
                        }
                }
@@ -549,8 +548,8 @@ int rtw_parse_wpa2_ie23a(const u8 *rsn_ie, int rsn_ie_len, int *group_cipher,
                left -= RSN_SELECTOR_LEN;
        } else if (left > 0) {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("%s: ie length mismatch, %u too much",
-                         __func__, left));
+                        "%s: ie length mismatch, %u too much\n",
+                        __func__, left);
                return _FAIL;
        }
 
@@ -563,9 +562,8 @@ int rtw_parse_wpa2_ie23a(const u8 *rsn_ie, int rsn_ie_len, int *group_cipher,
 
                if (count == 0 || left < count * RSN_SELECTOR_LEN) {
                        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                                ("%s: ie count botch (pairwise), "
-                                 "count %u left %u",
-                                 __func__, count, left));
+                                "%s: ie count botch (pairwise), count %u left %u\n",
+                                __func__, count, left);
                        return _FAIL;
                }
 
@@ -577,7 +575,7 @@ int rtw_parse_wpa2_ie23a(const u8 *rsn_ie, int rsn_ie_len, int *group_cipher,
                }
        } else if (left == 1) {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("%s: ie too short (for key mgmt)",  __func__));
+                        "%s: ie too short (for key mgmt)\n",  __func__);
 
                return _FAIL;
        }
@@ -587,8 +585,8 @@ int rtw_parse_wpa2_ie23a(const u8 *rsn_ie, int rsn_ie_len, int *group_cipher,
                        pos += 2;
                        if (!memcmp(pos, SUITE_1X, 4)) {
                                RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                                        ("%s (): there has 802.1x auth\n",
-                                         __func__));
+                                        "%s (): there has 802.1x auth\n",
+                                        __func__);
                                *is_8021x = 1;
                        }
                }
@@ -700,7 +698,7 @@ static int rtw_get_cipher_info(struct wlan_network *pnetwork)
 
        if (pbuf && pbuf[1] > 0) {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                        ("rtw_get_cipher_info: wpa_ielen: %d", pbuf[1]));
+                        "rtw_get_cipher_info: wpa_ielen: %d\n", pbuf[1]);
                r = rtw_parse_wpa_ie23a(pbuf, pbuf[1] + 2, &group_cipher,
                                     &pairwise_cipher, &is8021x);
                if (r == _SUCCESS) {
@@ -708,10 +706,9 @@ static int rtw_get_cipher_info(struct wlan_network *pnetwork)
                        pnetwork->BcnInfo.group_cipher = group_cipher;
                        pnetwork->BcnInfo.is_8021x = is8021x;
                        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                                ("%s: pnetwork->pairwise_cipher: %d, is_"
-                                 "8021x is %d", __func__,
-                                 pnetwork->BcnInfo.pairwise_cipher,
-                                 pnetwork->BcnInfo.is_8021x));
+                                "%s: pnetwork->pairwise_cipher: %d, is_8021x is %d\n",
+                                __func__, pnetwork->BcnInfo.pairwise_cipher,
+                                pnetwork->BcnInfo.is_8021x);
                        ret = _SUCCESS;
                }
        } else {
@@ -719,24 +716,23 @@ static int rtw_get_cipher_info(struct wlan_network *pnetwork)
 
                if (pbuf && pbuf[1] > 0) {
                        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                                ("get RSN IE\n"));
+                                "get RSN IE\n");
                        r = rtw_parse_wpa2_ie23a(pbuf, pbuf[1] + 2,
                                              &group_cipher, &pairwise_cipher,
                                              &is8021x);
                        if (r == _SUCCESS) {
                                RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                                        ("get RSN IE  OK!!!\n"));
+                                        "get RSN IE  OK!!!\n");
                                pnetwork->BcnInfo.pairwise_cipher =
                                        pairwise_cipher;
                                pnetwork->BcnInfo.group_cipher = group_cipher;
                                pnetwork->BcnInfo.is_8021x = is8021x;
                                RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                                        ("%s: pnetwork->pairwise_cipher: %d,"
-                                         "pnetwork->group_cipher is %d, "
-                                         "is_8021x is %d", __func__,
-                                         pnetwork->BcnInfo.pairwise_cipher,
-                                         pnetwork->BcnInfo.group_cipher,
-                                         pnetwork->BcnInfo.is_8021x));
+                                        "%s: pnetwork->pairwise_cipher: %d,pnetwork->group_cipher is %d, is_8021x is %d\n",
+                                        __func__,
+                                        pnetwork->BcnInfo.pairwise_cipher,
+                                        pnetwork->BcnInfo.group_cipher,
+                                        pnetwork->BcnInfo.is_8021x);
                                ret = _SUCCESS;
                        }
                }
@@ -759,7 +755,7 @@ void rtw_get_bcn_info23a(struct wlan_network *pnetwork)
                pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                ("%s: ssid =%s\n", __func__, pnetwork->network.Ssid.ssid));
+                "%s: ssid =%s\n", __func__, pnetwork->network.Ssid.ssid);
 
        pie = pnetwork->network.IEs;
        pie_len = pnetwork->network.IELength;
@@ -776,11 +772,11 @@ void rtw_get_bcn_info23a(struct wlan_network *pnetwork)
                        pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
        }
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                ("%s: pnetwork->encryp_protocol is %x\n", __func__,
-                 pnetwork->BcnInfo.encryp_protocol));
+                "%s: pnetwork->encryp_protocol is %x\n", __func__,
+                pnetwork->BcnInfo.encryp_protocol);
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                ("%s: pnetwork->encryp_protocol is %x\n", __func__,
-                 pnetwork->BcnInfo.encryp_protocol));
+                "%s: pnetwork->encryp_protocol is %x\n", __func__,
+                pnetwork->BcnInfo.encryp_protocol);
        rtw_get_cipher_info(pnetwork);
 
        /* get bwmode and ch_offset */
index 7299ef0a2e54c735686102d4ad852565c6690d4f..3c09ea9b734804feba22bd632d6223b469ba84d9 100644 (file)
@@ -94,7 +94,7 @@ void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
 void rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv)
 {
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                ("rtw_free_mlme_priv23a\n"));
+                "rtw_free_mlme_priv23a\n");
 
        rtw23a_free_mlme_priv_ie_data(pmlmepriv);
 }
@@ -196,9 +196,8 @@ int rtw_if_up23a(struct rtw_adapter *padapter)
        if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
            !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                        ("rtw_if_up23a:bDriverStopped(%d) OR "
-                         "bSurpriseRemoved(%d)", padapter->bDriverStopped,
-                         padapter->bSurpriseRemoved));
+                        "rtw_if_up23a:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n",
+                        padapter->bDriverStopped, padapter->bSurpriseRemoved);
                res = false;
        } else
                res =  true;
@@ -238,9 +237,9 @@ static void _rtw_roaming(struct rtw_adapter *padapter,
                pnetwork = &pmlmepriv->cur_network;
 
        if (padapter->mlmepriv.to_roaming > 0) {
-               DBG_8723A("roaming from %s("MAC_FMT"), length:%d\n",
+               DBG_8723A("roaming from %s(%pM), length:%d\n",
                          pnetwork->network.Ssid.ssid,
-                         MAC_ARG(pnetwork->network.MacAddress),
+                         pnetwork->network.MacAddress,
                          pnetwork->network.Ssid.ssid_len);
                memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid,
                       sizeof(struct cfg80211_ssid));
@@ -466,7 +465,7 @@ static void rtw_update_scanned_network(struct rtw_adapter *adapter,
                if (!pnetwork) {
                        if (!oldest) {
                                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                                        ("\n\n\nsomething wrong here\n\n\n"));
+                                        "something wrong here\n");
                                goto exit;
                        }
                        pnetwork = oldest;
@@ -568,13 +567,6 @@ static int rtw_is_desired_network(struct rtw_adapter *adapter,
        return bselected;
 }
 
-/* TODO: Perry : For Power Management */
-void rtw_atimdone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
-{
-       RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                ("receive atimdone_evet\n"));
-}
-
 void rtw_survey_event_cb23a(struct rtw_adapter *adapter, const u8 *pbuf)
 {
        u32 len;
@@ -585,13 +577,12 @@ void rtw_survey_event_cb23a(struct rtw_adapter *adapter, const u8 *pbuf)
        pnetwork = survey->bss;
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                ("rtw_survey_event_cb23a, ssid=%s\n", pnetwork->Ssid.ssid));
+                "rtw_survey_event_cb23a, ssid=%s\n", pnetwork->Ssid.ssid);
 
        len = get_wlan_bssid_ex_sz(pnetwork);
        if (len > (sizeof(struct wlan_bssid_ex))) {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("\n ****rtw_survey_event_cb23a: return a wrong "
-                         "bss ***\n"));
+                        "****rtw_survey_event_cb23a: return a wrong bss ***\n");
                return;
        }
 
@@ -599,8 +590,6 @@ void rtw_survey_event_cb23a(struct rtw_adapter *adapter, const u8 *pbuf)
 
        /*  update IBSS_network 's timestamp */
        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
-               /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                  "rtw_survey_event_cb23a : WIFI_ADHOC_MASTER_STATE\n\n"); */
                if (ether_addr_equal(pmlmepriv->cur_network.network.MacAddress,
                                     pnetwork->MacAddress)) {
                        struct wlan_network *ibss_wlan;
@@ -660,8 +649,8 @@ rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
        }
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                ("rtw_surveydone_event_callback23a: fw_state:%x\n\n",
-                 get_fwstate(pmlmepriv)));
+                "rtw_surveydone_event_callback23a: fw_state:%x\n",
+                get_fwstate(pmlmepriv));
 
        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
                del_timer_sync(&pmlmepriv->scan_to_timer);
@@ -669,8 +658,8 @@ rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
                _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
        } else {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("nic status =%x, survey done event comes too late!\n",
-                         get_fwstate(pmlmepriv)));
+                        "nic status =%x, survey done event comes too late!\n",
+                        get_fwstate(pmlmepriv));
        }
 
        rtw_set_signal_stat_timer(&adapter->recvpriv);
@@ -725,7 +714,7 @@ static void free_scanqueue(struct mlme_priv *pmlmepriv)
        struct rtw_queue *scan_queue = &pmlmepriv->scanned_queue;
        struct list_head *plist, *phead, *ptemp;
 
-       RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+free_scanqueue\n"));
+       RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, "+free_scanqueue\n");
        spin_lock_bh(&scan_queue->lock);
 
        phead = get_list_head(scan_queue);
@@ -752,11 +741,11 @@ void rtw_free_assoc_resources23a(struct rtw_adapter *adapter,
        struct sta_info *psta;
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
-                ("+rtw_free_assoc_resources23a\n"));
+                "+rtw_free_assoc_resources23a\n");
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                ("tgt_network->network.MacAddress="MAC_FMT" ssid=%s\n",
-                 MAC_ARG(tgt_network->network.MacAddress),
-                 tgt_network->network.Ssid.ssid));
+                "tgt_network->network.MacAddress=%pM ssid=%s\n",
+                tgt_network->network.MacAddress,
+                tgt_network->network.Ssid.ssid);
 
        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) {
                psta = rtw_get_stainfo23a(&adapter->stapriv,
@@ -788,7 +777,7 @@ void rtw_free_assoc_resources23a(struct rtw_adapter *adapter,
                pwlan->fixed = false;
        else
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("rtw_free_assoc_resources23a : pwlan== NULL\n"));
+                        "rtw_free_assoc_resources23a : pwlan== NULL\n");
 
        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) &&
            adapter->stapriv.asoc_sta_count == 1)
@@ -808,7 +797,7 @@ void rtw_indicate_connect23a(struct rtw_adapter *padapter)
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                ("+rtw_indicate_connect23a\n"));
+                "+rtw_indicate_connect23a\n");
 
        pmlmepriv->to_join = false;
 
@@ -828,8 +817,8 @@ void rtw_indicate_connect23a(struct rtw_adapter *padapter)
        rtw_set_scan_deny(padapter, 3000);
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                ("-rtw_indicate_connect23a: fw_state=0x%08x\n",
-                 get_fwstate(pmlmepriv)));
+                "-rtw_indicate_connect23a: fw_state=0x%08x\n",
+                get_fwstate(pmlmepriv));
 }
 
 /*
@@ -840,7 +829,7 @@ void rtw_indicate_disconnect23a(struct rtw_adapter *padapter)
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                ("+rtw_indicate_disconnect23a\n"));
+                "+rtw_indicate_disconnect23a\n");
 
        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS);
 
@@ -998,8 +987,9 @@ rtw_joinbss_update_network23a(struct rtw_adapter *padapter,
        DBG_8723A("%s\n", __func__);
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                ("\nfw_state:%x, BSSID:"MAC_FMT"\n", get_fwstate(pmlmepriv),
-                 MAC_ARG(pnetwork->network.MacAddress)));
+                "fw_state:%x, BSSID:%pM\n",
+                get_fwstate(pmlmepriv),
+                pnetwork->network.MacAddress);
 
        /*  why not use ptarget_wlan?? */
        memcpy(&cur_network->network, &pnetwork->network,
@@ -1042,7 +1032,7 @@ rtw_joinbss_update_network23a(struct rtw_adapter *padapter,
        default:
                pmlmepriv->fw_state = WIFI_NULL_STATE;
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("Invalid network_mode\n"));
+                        "Invalid network_mode\n");
                break;
        }
 
@@ -1077,16 +1067,16 @@ void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
        bool the_same_macaddr;
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                ("joinbss event call back received with res=%d\n",
-                 pnetwork->join_res));
+                "joinbss event call back received with res=%d\n",
+                pnetwork->join_res);
 
        if (pmlmepriv->assoc_ssid.ssid_len == 0) {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("@@@@@   joinbss event call back  for Any SSid\n"));
+                        "@@@@@   joinbss event call back  for Any SSid\n");
        } else {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("@@@@@   rtw23a_joinbss_event_cb for SSid:%s\n",
-                         pmlmepriv->assoc_ssid.ssid));
+                        "@@@@@   rtw23a_joinbss_event_cb for SSid:%s\n",
+                        pmlmepriv->assoc_ssid.ssid);
        }
 
        if (ether_addr_equal(pnetwork->network.MacAddress,
@@ -1098,15 +1088,14 @@ void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
        pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
        if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("\n\n ***joinbss_evt_callback return a wrong bss "
-                         "***\n\n"));
+                        "***joinbss_evt_callback return a wrong bss ***\n");
                return;
        }
 
        spin_lock_bh(&pmlmepriv->lock);
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                ("\n rtw23a_joinbss_event_cb !! _enter_critical\n"));
+                "rtw23a_joinbss_event_cb !! _enter_critical\n");
 
        if (pnetwork->join_res > 0) {
                spin_lock_bh(&pmlmepriv->scanned_queue.lock);
@@ -1155,8 +1144,7 @@ void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
                                                              pnetwork);
                        else {
                                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                                        ("Can't find ptarget_wlan when "
-                                         "joinbss_event callback\n"));
+                                        "Can't find ptarget_wlan when joinbss_event callback\n");
                                spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
                                goto ignore_joinbss_callback;
                        }
@@ -1169,8 +1157,7 @@ void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
                                if (!ptarget_sta) {
                                        RT_TRACE(_module_rtl871x_mlme_c_,
                                                 _drv_err_,
-                                                ("Can't update stainfo when "
-                                                 "joinbss_event callback\n"));
+                                                "Can't update stainfo when joinbss_event callback\n");
                                        spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
                                        goto ignore_joinbss_callback;
                                }
@@ -1183,19 +1170,19 @@ void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
                                /* adhoc mode will rtw_indicate_connect23a
                                   when rtw_stassoc_event_callback23a */
                                RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                                        ("adhoc mode, fw_state:%x",
-                                         get_fwstate(pmlmepriv)));
+                                        "adhoc mode, fw_state:%x\n",
+                                        get_fwstate(pmlmepriv));
                        }
 
                        /* s5. Cancle assoc_timer */
                        del_timer_sync(&pmlmepriv->assoc_timer);
 
                        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                                ("Cancle assoc_timer\n"));
+                                "Cancle assoc_timer\n");
                } else {
                        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                                ("rtw23a_joinbss_event_cb err: fw_state:%x",
-                                get_fwstate(pmlmepriv)));
+                                "rtw23a_joinbss_event_cb err: fw_state:%x\n",
+                                get_fwstate(pmlmepriv));
                        spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
                        goto ignore_joinbss_callback;
                }
@@ -1209,8 +1196,8 @@ void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
 
                if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
                        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                                ("fail! clear _FW_UNDER_LINKING ^^^fw_state="
-                                 "%x\n", get_fwstate(pmlmepriv)));
+                                "fail! clear _FW_UNDER_LINKING ^^^fw_state=%x\n",
+                                get_fwstate(pmlmepriv));
                        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
                }
        } else {
@@ -1261,8 +1248,7 @@ void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
        if (psta != NULL) {
                /* the sta have been in sta_info_queue => do nothing */
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("Error: rtw_stassoc_event_callback23a: sta has "
-                         "been in sta_hash_queue\n"));
+                        "Error: rtw_stassoc_event_callback23a: sta has been in sta_hash_queue\n");
                /* between drv has received this event before and
                   fw have not yet to set key to CAM_ENTRY) */
                return;
@@ -1272,8 +1258,7 @@ void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
                GFP_KERNEL);
        if (!psta) {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("Can't alloc sta_info when "
-                         "rtw_stassoc_event_callback23a\n"));
+                        "Can't alloc sta_info when rtw_stassoc_event_callback23a\n");
                return;
        }
 
@@ -1330,8 +1315,7 @@ void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf)
        else
                mac_id = pstadel->mac_id;
 
-       DBG_8723A("%s(mac_id=%d)=" MAC_FMT "\n", __func__, mac_id,
-                 MAC_ARG(pstadel->macaddr));
+       DBG_8723A("%s(mac_id=%d)=%pM\n", __func__, mac_id, pstadel->macaddr);
 
        if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
                return;
@@ -1582,13 +1566,12 @@ static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv,
        }
 
        if (updated) {
-               DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] "
-                         "new candidate: %s("MAC_FMT") rssi:%d\n",
+               DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] new candidate: %s(%pM) rssi:%d\n",
                          pmlmepriv->assoc_by_bssid,
                          pmlmepriv->assoc_ssid.ssid,
                          adapter->mlmepriv.to_roaming,
                          (*candidate)->network.Ssid.ssid,
-                         MAC_ARG((*candidate)->network.MacAddress),
+                         (*candidate)->network.MacAddress,
                          (int)(*candidate)->network.Rssi);
        }
 
@@ -1653,8 +1636,8 @@ rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv)
                pnetwork = container_of(plist, struct wlan_network, list);
                if (!pnetwork) {
                        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                                ("%s: return _FAIL:(pnetwork == NULL)\n",
-                                 __func__));
+                                "%s: return _FAIL:(pnetwork == NULL)\n",
+                                __func__);
                        goto exit;
                }
 
@@ -1680,7 +1663,7 @@ int rtw_do_join_adhoc(struct rtw_adapter *adapter)
        _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                ("switching to adhoc master\n"));
+                "switching to adhoc master\n");
 
        memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid,
               sizeof(struct cfg80211_ssid));
@@ -1693,7 +1676,7 @@ int rtw_do_join_adhoc(struct rtw_adapter *adapter)
        ret = rtw_createbss_cmd23a(adapter);
        if (ret != _SUCCESS) {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("Error =>rtw_createbss_cmd23a status FAIL\n"));
+                        "Error =>rtw_createbss_cmd23a status FAIL\n");
        } else  {
                pmlmepriv->to_join = false;
        }
@@ -1739,9 +1722,10 @@ int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv)
                ret = _FAIL;
                goto exit;
        } else {
-               DBG_8723A("%s: candidate: %s("MAC_FMT", ch:%u)\n", __func__,
+               DBG_8723A("%s: candidate: %s(%pM, ch:%u)\n",
+                         __func__,
                          candidate->network.Ssid.ssid,
-                         MAC_ARG(candidate->network.MacAddress),
+                         candidate->network.MacAddress,
                          candidate->network.DSConfig);
        }
 
@@ -1781,8 +1765,8 @@ int rtw_set_auth23a(struct rtw_adapter *adapter,
        pcmd->rspsz = 0;
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                ("after enqueue set_auth_cmd, auth_mode=%x\n",
-                 psecuritypriv->dot11AuthAlgrthm));
+                "after enqueue set_auth_cmd, auth_mode=%x\n",
+                psecuritypriv->dot11AuthAlgrthm);
 
        res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
 
@@ -1822,15 +1806,13 @@ int rtw_set_key23a(struct rtw_adapter *adapter,
                psetkeyparm->algorithm = (unsigned char)
                        psecuritypriv->dot118021XGrpPrivacy;
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("\n rtw_set_key23a: psetkeyparm->algorithm = "
-                         "(unsigned char)psecuritypriv->dot118021XGrpPrivacy "
-                         "=%d\n", psetkeyparm->algorithm));
+                        "rtw_set_key23a: psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy =%d\n",
+                        psetkeyparm->algorithm);
        } else {
                psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("\n rtw_set_key23a: psetkeyparm->algorithm = (u8)"
-                         "psecuritypriv->dot11PrivacyAlgrthm =%d\n",
-                         psetkeyparm->algorithm));
+                        "rtw_set_key23a: psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm =%d\n",
+                        psetkeyparm->algorithm);
        }
        psetkeyparm->keyid = keyid;/* 0~3 */
        psetkeyparm->set_tx = set_tx;
@@ -1841,8 +1823,8 @@ int rtw_set_key23a(struct rtw_adapter *adapter,
                  psetkeyparm->algorithm, psetkeyparm->keyid,
                  pmlmepriv->key_mask);
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                ("\n rtw_set_key23a: psetkeyparm->algorithm =%d psetkeyparm->"
-                 "keyid = (u8)keyid =%d\n", psetkeyparm->algorithm, keyid));
+                "rtw_set_key23a: psetkeyparm->algorithm =%d psetkeyparm->keyid = (u8)keyid =%d\n",
+                psetkeyparm->algorithm, keyid);
 
        switch (psetkeyparm->algorithm) {
        case WLAN_CIPHER_SUITE_WEP40:
@@ -1869,9 +1851,8 @@ int rtw_set_key23a(struct rtw_adapter *adapter,
                break;
        default:
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("\n rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm"
-                         " = %x (must be 1 or 2 or 4 or 5)\n",
-                         psecuritypriv->dot11PrivacyAlgrthm));
+                        "rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm = %x (must be 1 or 2 or 4 or 5)\n",
+                        psecuritypriv->dot11PrivacyAlgrthm);
                res = _FAIL;
                kfree(pcmd);
                kfree(psetkeyparm);
@@ -1998,8 +1979,8 @@ int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie,
        uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
-                ("+rtw_restruct_sec_ie23a: ndisauthmode=%d "
-                 "ndissecuritytype=%d\n", ndisauthmode, ndissecuritytype));
+                "+rtw_restruct_sec_ie23a: ndisauthmode=%d ndissecuritytype=%d\n",
+                ndisauthmode, ndissecuritytype);
 
        ielength = 0;
        if (ndisauthmode == Ndis802_11AuthModeWPA ||
@@ -2065,8 +2046,8 @@ void rtw_update_registrypriv_dev_network23a(struct rtw_adapter *adapter)
 
        pdev_network->DSConfig = pregistrypriv->channel;
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                ("pregistrypriv->channel =%d, pdev_network->DSConfig = 0x%x\n",
-                 pregistrypriv->channel, pdev_network->DSConfig));
+                "pregistrypriv->channel =%d, pdev_network->DSConfig = 0x%x\n",
+                pregistrypriv->channel, pdev_network->DSConfig);
 
        if (cur_network->network.ifmode == NL80211_IFTYPE_ADHOC)
                pdev_network->ATIMWindow = 0;
index 0e0f73c86e53c5738dc5d728f2df0361d99c004e..196beafde6f077334adf6159edfa93090df5208c 100644 (file)
@@ -657,8 +657,8 @@ void mgt_dispatcher23a(struct rtw_adapter *padapter,
 
        if (index > 13) {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("Currently we do not support reserved sub-fr-type ="
-                         "%d\n", index));
+                        "Currently we do not support reserved sub-fr-type =%d\n",
+                        index);
                return;
        }
        ptable += index;
@@ -968,8 +968,7 @@ OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
        pstat = rtw_get_stainfo23a(pstapriv, sa);
        if (!pstat) {
                /*  allocate a new one */
-               DBG_8723A("going to alloc stainfo for sa ="MAC_FMT"\n",
-                         MAC_ARG(sa));
+               DBG_8723A("going to alloc stainfo for sa =%pM\n", sa);
                pstat = rtw_alloc_stainfo23a(pstapriv, sa, GFP_ATOMIC);
                if (!pstat) {
                        DBG_8723A(" Exceed the upper limit of supported "
@@ -1396,8 +1395,8 @@ OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
        /* now parse all ieee802_11 ie to point to elems */
 
        if (rtw_validate_frame_ies(pos, left)) {
-               DBG_8723A("STA " MAC_FMT " sent invalid association request\n",
-                         MAC_ARG(pstat->hwaddr));
+               DBG_8723A("STA %pM sent invalid association request\n",
+                         pstat->hwaddr);
                status = WLAN_STATUS_UNSPECIFIED_FAILURE;
                goto OnAssocReq23aFail;
        }
@@ -1407,8 +1406,8 @@ OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
        p = cfg80211_find_ie(WLAN_EID_SSID, pos, left);
        if (!p || p[1] == 0) {
                /*  broadcast ssid, however it is not allowed in assocreq */
-               DBG_8723A("STA " MAC_FMT " sent invalid association request "
-                         "lacking an SSID\n", MAC_ARG(pstat->hwaddr));
+               DBG_8723A("STA %pM sent invalid association request lacking an SSID\n",
+                         pstat->hwaddr);
                status = WLAN_STATUS_UNSPECIFIED_FAILURE;
                goto OnAssocReq23aFail;
        } else {
@@ -1537,9 +1536,8 @@ OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
                int copy_len;
 
                if (psecuritypriv->wpa_psk == 0) {
-                       DBG_8723A("STA " MAC_FMT ": WPA/RSN IE in association "
-                       "request, but AP don't support WPA/RSN\n",
-                                 MAC_ARG(pstat->hwaddr));
+                       DBG_8723A("STA %pM: WPA/RSN IE in association request, but AP don't support WPA/RSN\n",
+                                 pstat->hwaddr);
 
                        status = WLAN_STATUS_INVALID_IE;
 
@@ -1614,8 +1612,8 @@ OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
                                        else
                                                pstat->uapsd_be = 0;
 
+                                       break;
                                }
-                               break;
                        } else {
                                break;
                        }
@@ -1645,8 +1643,8 @@ OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
        if (pstat->flags & WLAN_STA_HT &&
            (pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP ||
             pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {
-               DBG_8723A("HT: " MAC_FMT " tried to use TKIP with HT "
-                         "association\n", MAC_ARG(pstat->hwaddr));
+               DBG_8723A("HT: %pM tried to use TKIP with HT association\n",
+                         pstat->hwaddr);
 
                /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
                /* goto OnAssocReq23aFail; */
@@ -2687,7 +2685,7 @@ static int _issue_probereq(struct rtw_adapter *padapter,
        u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
-                ("+%s\n", __func__));
+                "+%s\n", __func__);
 
        pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
        if (!pmgntframe)
@@ -2758,7 +2756,7 @@ static int _issue_probereq(struct rtw_adapter *padapter,
        pattrib->last_txcmdsz = pattrib->pktlen;
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
-                ("issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz));
+                "issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz);
 
        if (wait_ack) {
                ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
@@ -2806,17 +2804,16 @@ static int issue_probereq_ex(struct rtw_adapter *padapter,
 
        if (try_cnt && wait_ms) {
                if (da)
-                       DBG_8723A("%s(%s): to "MAC_FMT", ch:%u%s, %d/%d "
-                                 "in %u ms\n", __func__,
-                                 padapter->pnetdev->name,
-                                 MAC_ARG(da), rtw_get_oper_ch23a(padapter),
-                                 ret == _SUCCESS?", acked":"", i, try_cnt,
+                       DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
+                                 __func__, padapter->pnetdev->name,
+                                 da, rtw_get_oper_ch23a(padapter),
+                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
                                  jiffies_to_msecs(jiffies - start));
                else
                        DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
                                  __func__, padapter->pnetdev->name,
                                  rtw_get_oper_ch23a(padapter),
-                                 ret == _SUCCESS?", acked":"", i, try_cnt,
+                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
                                  jiffies_to_msecs(jiffies - start));
        }
 exit:
@@ -3460,17 +3457,16 @@ int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
 
        if (try_cnt && wait_ms) {
                if (da)
-                       DBG_8723A("%s(%s): to "MAC_FMT", ch:%u%s, %d/%d "
-                                 "in %u ms\n", __func__,
-                                 padapter->pnetdev->name,
-                                 MAC_ARG(da), rtw_get_oper_ch23a(padapter),
-                                 ret == _SUCCESS?", acked":"", i, try_cnt,
+                       DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
+                                 __func__, padapter->pnetdev->name,
+                                 da, rtw_get_oper_ch23a(padapter),
+                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
                                  jiffies_to_msecs(jiffies - start));
                else
                        DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
                                  __func__, padapter->pnetdev->name,
                                  rtw_get_oper_ch23a(padapter),
-                                 ret == _SUCCESS?", acked":"", i, try_cnt,
+                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
                                  jiffies_to_msecs(jiffies - start));
        }
 exit:
@@ -3587,17 +3583,16 @@ int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
 
        if (try_cnt && wait_ms) {
                if (da)
-                       DBG_8723A("%s(%s): to "MAC_FMT", ch:%u%s, %d/%d "
-                                 "in %u ms\n", __func__,
-                                 padapter->pnetdev->name,
-                                 MAC_ARG(da), rtw_get_oper_ch23a(padapter),
-                                 ret == _SUCCESS?", acked":"", i, try_cnt,
+                       DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
+                                 __func__, padapter->pnetdev->name,
+                                 da, rtw_get_oper_ch23a(padapter),
+                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
                                  jiffies_to_msecs(jiffies - start));
                else
                        DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
                                  __func__, padapter->pnetdev->name,
                                  rtw_get_oper_ch23a(padapter),
-                                 ret == _SUCCESS?", acked":"", i, try_cnt,
+                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
                                  jiffies_to_msecs(jiffies - start));
        }
 exit:
@@ -3615,7 +3610,7 @@ static int _issue_deauth(struct rtw_adapter *padapter, unsigned char *da,
        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
        int ret = _FAIL;
 
-       /* DBG_8723A("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); */
+       /* DBG_8723A("%s to %pM\n", __func__, da); */
 
        pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
        if (!pmgntframe)
@@ -3660,7 +3655,7 @@ exit:
 int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
                    unsigned short reason)
 {
-       DBG_8723A("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
+       DBG_8723A("%s to %pM\n", __func__, da);
        return _issue_deauth(padapter, da, reason, false);
 }
 
@@ -3692,17 +3687,16 @@ static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
 
        if (try_cnt && wait_ms) {
                if (da)
-                       DBG_8723A("%s(%s): to "MAC_FMT", ch:%u%s, %d/%d "
-                                 "in %u ms\n", __func__,
-                                 padapter->pnetdev->name,
-                                 MAC_ARG(da), rtw_get_oper_ch23a(padapter),
-                                 ret == _SUCCESS?", acked":"", i, try_cnt,
+                       DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
+                                 __func__, padapter->pnetdev->name,
+                                 da, rtw_get_oper_ch23a(padapter),
+                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
                                  jiffies_to_msecs(jiffies - start));
                else
                        DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
                                  __func__, padapter->pnetdev->name,
                                  rtw_get_oper_ch23a(padapter),
-                                 ret == _SUCCESS?", acked":"", i, try_cnt,
+                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
                                  jiffies_to_msecs(jiffies - start));
        }
 exit:
@@ -3719,8 +3713,8 @@ void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter,
        struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 
-       DBG_8723A("%s(%s): ra ="MAC_FMT", ch:%u, offset:%u\n", __func__,
-                 padapter->pnetdev->name, MAC_ARG(ra), new_ch, ch_offset);
+       DBG_8723A("%s(%s): ra=%pM, ch:%u, offset:%u\n",
+                 __func__, padapter->pnetdev->name, ra, new_ch, ch_offset);
 
        pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
        if (!pmgntframe)
@@ -3767,7 +3761,6 @@ void issue_action_BA23a(struct rtw_adapter *padapter,
 {
        u16 start_seq;
        u16 BA_para_set;
-       u16 BA_timeout_value;
        u16 BA_starting_seqctrl;
        u16 BA_para;
        int max_rx_ampdu_factor;
@@ -3842,16 +3835,14 @@ void issue_action_BA23a(struct rtw_adapter *padapter,
                                IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
                } else {
                        /* immediate ack & 64 buffer size */
-                       BA_para_set = (0x1002 | ((status & 0xf) << 2));
+                       BA_para_set = 0x1002 | ((status & 0xf) << 2);
                }
 
                put_unaligned_le16(BA_para_set,
                                   &mgmt->u.action.u.addba_req.capab);
 
-               BA_timeout_value = 5000;/*  5ms */
-               BA_timeout_value = cpu_to_le16(BA_timeout_value);
-               put_unaligned_le16(BA_timeout_value,
-                                  &mgmt->u.action.u.addba_req.timeout);
+               /*  5ms */
+               put_unaligned_le16(5000, &mgmt->u.action.u.addba_req.timeout);
 
                psta = rtw_get_stainfo23a(pstapriv, raddr);
                if (psta) {
@@ -4347,7 +4338,8 @@ static void start_create_ibss(struct rtw_adapter *padapter)
 
                /* issue beacon */
                if (send_beacon23a(padapter) == _FAIL) {
-                       RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
+                       RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+                                "issuing beacon frame fail....\n");
 
                        report_join_res23a(padapter, -1);
                        pmlmeinfo->state = MSR_NOLINK;
@@ -4531,7 +4523,7 @@ static void process_80211d(struct rtw_adapter *padapter,
 
                p += 3;
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
-                        ("%s: 802.11d country =%s\n", __func__, country));
+                        "%s: 802.11d country =%s\n", __func__, country);
 
                i = 0;
                while ((ie - p) >= 3) {
@@ -4708,9 +4700,8 @@ static void process_80211d(struct rtw_adapter *padapter,
 
                                chplan_new[i].ScanType = SCAN_ACTIVE;
                                RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
-                                        ("%s: change channel %d scan type "
-                                         "from passive to active\n",
-                                         __func__, channel));
+                                        "%s: change channel %d scan type from passive to active\n",
+                                        __func__, channel);
                        }
                        break;
                }
@@ -4745,7 +4736,7 @@ void report_survey_event23a(struct rtw_adapter *padapter,
        if (!pcmd_obj)
                return;
 
-       cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
+       cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header);
        pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
        if (!pevtcmd) {
                kfree(pcmd_obj);
@@ -4796,7 +4787,7 @@ void report_surveydone_event23a(struct rtw_adapter *padapter)
        if (!pcmd_obj)
                return;
 
-       cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
+       cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header);
        pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
        if (!pevtcmd) {
                kfree(pcmd_obj);
@@ -4840,7 +4831,7 @@ void report_join_res23a(struct rtw_adapter *padapter, int res)
        if (!pcmd_obj)
                return;
 
-       cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
+       cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header);
        pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
        if (!pevtcmd) {
                kfree(pcmd_obj);
@@ -4890,7 +4881,7 @@ void report_del_sta_event23a(struct rtw_adapter *padapter,
        if (!pcmd_obj)
                return;
 
-       cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
+       cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header);
        pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
        if (!pevtcmd) {
                kfree(pcmd_obj);
@@ -4918,7 +4909,7 @@ void report_del_sta_event23a(struct rtw_adapter *padapter,
        if (psta)
                mac_id = (int)psta->mac_id;
        else
-               mac_id = (-1);
+               mac_id = -1;
 
        pdel_sta_evt->mac_id = mac_id;
 
@@ -4944,7 +4935,7 @@ void report_add_sta_event23a(struct rtw_adapter *padapter,
        if (!pcmd_obj)
                return;
 
-       cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
+       cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header);
        pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
        if (!pevtcmd) {
                kfree(pcmd_obj);
@@ -5951,7 +5942,7 @@ int set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
 
                        /* 0~3 for default key, cmd_id = macid + 3,
                           macid = aid+1; */
-                       cam_id = (psta->mac_id + 3);
+                       cam_id = psta->mac_id + 3;
 
                        DBG_8723A("Write CAM, mac_addr =%x:%x:%x:%x:%x:%x, "
                                  "cam_entry =%d\n", pparm->addr[0],
@@ -6066,7 +6057,7 @@ int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
        /*  checking if event code is valid */
        if (evt_code >= MAX_C2HEVT) {
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                        ("\nEvent Code(%d) mismatch!\n", evt_code));
+                        "Event Code(%d) mismatch!\n", evt_code);
                goto _abort_event_;
        }
 
@@ -6074,8 +6065,8 @@ int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
        if (wlanevents[evt_code].parmsize != 0 &&
            wlanevents[evt_code].parmsize != evt_sz) {
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                        ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
-                         evt_code, wlanevents[evt_code].parmsize, evt_sz));
+                        "Event(%d) Parm Size mismatch (%d vs %d)!\n",
+                        evt_code, wlanevents[evt_code].parmsize, evt_sz);
                goto _abort_event_;
        }
 
index e2d51afe522c149862aababc5e0284fc9df66234..7488a104935b037427adbab657bbabb6607f9a3d 100644 (file)
@@ -202,17 +202,17 @@ void rtw_set_rpwm23a(struct rtw_adapter *padapter, u8 pslv)
 
        if (pwrpriv->rpwm == pslv) {
                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
-                       ("%s: Already set rpwm[0x%02X], new = 0x%02X!\n",
-                        __func__, pwrpriv->rpwm, pslv));
+                        "%s: Already set rpwm[0x%02X], new = 0x%02X!\n",
+                        __func__, pwrpriv->rpwm, pslv);
                return;
        }
 
        if (padapter->bSurpriseRemoved == true ||
            padapter->hw_init_completed == false) {
                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
-                        ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n",
-                         __func__, padapter->bSurpriseRemoved,
-                         padapter->hw_init_completed));
+                        "%s: SurpriseRemoved(%d) hw_init_completed(%d)\n",
+                        __func__, padapter->bSurpriseRemoved,
+                        padapter->hw_init_completed);
 
                pwrpriv->cpwm = PS_STATE_S4;
 
@@ -221,22 +221,21 @@ void rtw_set_rpwm23a(struct rtw_adapter *padapter, u8 pslv)
 
        if (padapter->bDriverStopped == true) {
                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
-                        ("%s: change power state(0x%02X) when DriverStopped\n",
-                         __func__, pslv));
+                        "%s: change power state(0x%02X) when DriverStopped\n",
+                        __func__, pslv);
 
                if (pslv < PS_STATE_S2) {
                        RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
-                                ("%s: Reject to enter PS_STATE(0x%02X) lower "
-                                 "than S2 when DriverStopped!!\n",
-                                 __func__, pslv));
+                                "%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n",
+                                __func__, pslv);
                        return;
                }
        }
 
        rpwm = pslv | pwrpriv->tog;
        RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
-                ("rtw_set_rpwm23a: rpwm = 0x%02x cpwm = 0x%02x\n",
-                 rpwm, pwrpriv->cpwm));
+                "rtw_set_rpwm23a: rpwm = 0x%02x cpwm = 0x%02x\n",
+                rpwm, pwrpriv->cpwm);
 
        pwrpriv->rpwm = pslv;
 
@@ -282,12 +281,12 @@ void rtw_set_ps_mode23a(struct rtw_adapter *padapter, u8 ps_mode,
        struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
 
        RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
-                        ("%s: PowerMode =%d Smart_PS =%d\n",
-                         __func__, ps_mode, smart_ps));
+                "%s: PowerMode =%d Smart_PS =%d\n",
+                __func__, ps_mode, smart_ps);
 
        if (ps_mode > PM_Card_Disable) {
                RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
-                        ("ps_mode:%d error\n", ps_mode));
+                        "ps_mode:%d error\n", ps_mode);
                return;
        }
 
index 559dddee26485df3ced453913850eb1b2e513e49..274a4b65c0226d33581f3cfde71e7ca04ad940ba 100644 (file)
@@ -299,12 +299,9 @@ int recvframe_chkmic(struct rtw_adapter *adapter,
 
        if (prxattrib->encrypt == WLAN_CIPHER_SUITE_TKIP) {
                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                        ("\n recvframe_chkmic:prxattrib->encrypt == WLAN_CIPHER_SUITE_TKIP\n"));
+                        "recvframe_chkmic:prxattrib->encrypt == WLAN_CIPHER_SUITE_TKIP\n");
                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                        ("\n recvframe_chkmic:da = 0x%02x:0x%02x:0x%02x:0x%02x:"
-                         "0x%02x:0x%02x\n", prxattrib->ra[0],
-                         prxattrib->ra[1], prxattrib->ra[2], prxattrib->ra[3],
-                         prxattrib->ra[4], prxattrib->ra[5]));
+                        "recvframe_chkmic:da = %pM\n", prxattrib->ra);
 
                /* calculate mic code */
                if (stainfo != NULL) {
@@ -312,14 +309,13 @@ int recvframe_chkmic(struct rtw_adapter *adapter,
                                mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];
 
                                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                                        ("\n recvframe_chkmic: bcmc key\n"));
+                                        "recvframe_chkmic: bcmc key\n");
 
                                if (!psecuritypriv->binstallGrpkey) {
                                        res = _FAIL;
                                        RT_TRACE(_module_rtl871x_recv_c_,
                                                 _drv_err_,
-                                                ("\n recvframe_chkmic:didn't "
-                                                 "install group key!!!!!!\n"));
+                                                "recvframe_chkmic:didn't install group key!\n");
                                        DBG_8723A("\n recvframe_chkmic:didn't "
                                                  "install group key!!!!!!\n");
                                        goto exit;
@@ -327,8 +323,7 @@ int recvframe_chkmic(struct rtw_adapter *adapter,
                        } else {
                                mickey = &stainfo->dot11tkiprxmickey.skey[0];
                                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                        ("\n recvframe_chkmic: unicast "
-                                         "key\n"));
+                                        "recvframe_chkmic: unicast key\n");
                        }
 
                        /* icv_len included the mic code */
@@ -339,9 +334,8 @@ int recvframe_chkmic(struct rtw_adapter *adapter,
                                prxattrib->iv_len;
 
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                                ("\n prxattrib->iv_len =%d prxattrib->icv_len ="
-                                 "%d\n", prxattrib->iv_len,
-                                 prxattrib->icv_len));
+                                "prxattrib->iv_len =%d prxattrib->icv_len =%d\n",
+                                prxattrib->iv_len, prxattrib->icv_len);
 
                        /* care the length of the data */
                        rtw_seccalctkipmic23a(mickey, pframe, payload,
@@ -356,10 +350,9 @@ int recvframe_chkmic(struct rtw_adapter *adapter,
                                if (miccode[i] != *(pframemic + i)) {
                                        RT_TRACE(_module_rtl871x_recv_c_,
                                                 _drv_err_,
-                                                ("recvframe_chkmic:miccode"
-                                                 "[%d](%02x) != *(pframemic+"
-                                                 "%d)(%02x) ", i, miccode[i],
-                                                 i, *(pframemic + i)));
+                                                "recvframe_chkmic:miccode[%d](%02x) != *(pframemic+%d)(%02x)\n",
+                                                i, miccode[i],
+                                                i, *(pframemic + i));
                                        bmic_err = true;
                                }
                        }
@@ -368,51 +361,44 @@ int recvframe_chkmic(struct rtw_adapter *adapter,
                                int i;
 
                                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                        ("\n *(pframemic-8)-*(pframemic-1) ="
-                                         "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:"
-                                         "0x%02x:0x%02x:0x%02x\n",
-                                         *(pframemic - 8), *(pframemic - 7),
-                                         *(pframemic - 6), *(pframemic - 5),
-                                         *(pframemic - 4), *(pframemic - 3),
-                                         *(pframemic - 2), *(pframemic - 1)));
+                                        "*(pframemic-8)-*(pframemic-1) =0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+                                        *(pframemic - 8), *(pframemic - 7),
+                                        *(pframemic - 6), *(pframemic - 5),
+                                        *(pframemic - 4), *(pframemic - 3),
+                                        *(pframemic - 2), *(pframemic - 1));
                                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                        ("\n *(pframemic-16)-*(pframemic-9) ="
-                                         "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:"
-                                         "0x%02x:0x%02x:0x%02x\n",
-                                         *(pframemic - 16), *(pframemic - 15),
-                                         *(pframemic - 14), *(pframemic - 13),
-                                         *(pframemic - 12), *(pframemic - 11),
-                                         *(pframemic - 10), *(pframemic - 9)));
+                                        "*(pframemic-16)-*(pframemic-9) =0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+                                        *(pframemic - 16), *(pframemic - 15),
+                                        *(pframemic - 14), *(pframemic - 13),
+                                        *(pframemic - 12), *(pframemic - 11),
+                                        *(pframemic - 10), *(pframemic - 9));
 
                                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                        ("\n ====== demp packet (len =%d) ======"
-                                         "\n", precvframe->pkt->len));
+                                        "====== demp packet (len =%d) ======\n",
+                                        precvframe->pkt->len);
                                for (i = 0; i < precvframe->pkt->len; i = i + 8) {
                                        RT_TRACE(_module_rtl871x_recv_c_,
-                                                _drv_err_, ("0x%02x:0x%02x:0x"
-                                                           "%02x:0x%02x:0x%0"
-                                                           "2x:0x%02x:0x%02x"
-                                                           ":0x%02x",
-                                                           *(precvframe->pkt->data+i),*(precvframe->pkt->data+i+1),
-                                                           *(precvframe->pkt->data+i+2),*(precvframe->pkt->data+i+3),
-                                                           *(precvframe->pkt->data+i+4),*(precvframe->pkt->data+i+5),
-                                                           *(precvframe->pkt->data+i+6),*(precvframe->pkt->data+i+7)));
+                                                _drv_err_,
+                                                "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+                                                *(precvframe->pkt->data+i),
+                                                *(precvframe->pkt->data+i+1),
+                                                *(precvframe->pkt->data+i+2),
+                                                *(precvframe->pkt->data+i+3),
+                                                *(precvframe->pkt->data+i+4),
+                                                *(precvframe->pkt->data+i+5),
+                                                *(precvframe->pkt->data+i+6),
+                                                *(precvframe->pkt->data+i+7));
                                }
                                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                        ("\n ====== demp packet end [len =%d]"
-                                         "======\n", precvframe->pkt->len));
+                                        "====== demp packet end [len =%d]======\n",
+                                        precvframe->pkt->len);
                                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                        ("\n hrdlen =%d,\n",
-                                         prxattrib->hdrlen));
+                                        "hrdlen =%d\n", prxattrib->hdrlen);
 
                                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                        ("ra = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%."
-                                         "2x 0x%.2x psecuritypriv->"
-                                         "binstallGrpkey =%d ",
-                                         prxattrib->ra[0], prxattrib->ra[1],
-                                         prxattrib->ra[2], prxattrib->ra[3],
-                                         prxattrib->ra[4], prxattrib->ra[5],
-                                         psecuritypriv->binstallGrpkey));
+                                        "ra = %pM psecuritypriv->binstallGrpkey =%d\n",
+                                        prxattrib->ra,
+                                        psecuritypriv->binstallGrpkey);
 
                                /*  double check key_index for some timing
                                    issue, cannot compare with
@@ -426,16 +412,17 @@ int recvframe_chkmic(struct rtw_adapter *adapter,
                                if ((prxattrib->bdecrypted == true) &&
                                    (brpt_micerror == true)) {
                                        rtw_handle_tkip_mic_err23a(adapter, (u8)is_multicast_ether_addr(prxattrib->ra));
-                                       RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted =%d ", prxattrib->bdecrypted));
+                                       RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+                                                "mic error :prxattrib->bdecrypted =%d\n",
+                                                prxattrib->bdecrypted);
                                        DBG_8723A(" mic error :prxattrib->"
                                                  "bdecrypted =%d\n",
                                                  prxattrib->bdecrypted);
                                } else {
                                        RT_TRACE(_module_rtl871x_recv_c_,
                                                 _drv_err_,
-                                                (" mic error :prxattrib->"
-                                                 "bdecrypted =%d ",
-                                                 prxattrib->bdecrypted));
+                                                "mic error :prxattrib->bdecrypted =%d\n",
+                                                prxattrib->bdecrypted);
                                        DBG_8723A(" mic error :prxattrib->"
                                                  "bdecrypted =%d\n",
                                                  prxattrib->bdecrypted);
@@ -449,14 +436,12 @@ int recvframe_chkmic(struct rtw_adapter *adapter,
                                        psecuritypriv->bcheck_grpkey = 1;
                                        RT_TRACE(_module_rtl871x_recv_c_,
                                                 _drv_err_,
-                                                ("psecuritypriv->bcheck_grp"
-                                                 "key = true"));
+                                                "psecuritypriv->bcheck_grpkey = true\n");
                                }
                        }
                } else {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                ("recvframe_chkmic: rtw_get_stainfo23a =="
-                                 "NULL!!!\n"));
+                                "recvframe_chkmic: rtw_get_stainfo23a ==NULL!!!\n");
                }
 
                skb_trim(precvframe->pkt, precvframe->pkt->len - 8);
@@ -481,8 +466,8 @@ struct recv_frame *decryptor(struct rtw_adapter *padapter,
        int res = _SUCCESS;
 
        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                ("prxstat->decrypted =%x prxattrib->encrypt = 0x%03x\n",
-                 prxattrib->bdecrypted, prxattrib->encrypt));
+                "prxstat->decrypted =%x prxattrib->encrypt = 0x%03x\n",
+                prxattrib->bdecrypted, prxattrib->encrypt);
 
        if (prxattrib->encrypt > 0) {
                u8 *iv = precv_frame->pkt->data + prxattrib->hdrlen;
@@ -565,8 +550,8 @@ static struct recv_frame *portctrl(struct rtw_adapter *adapter,
        psta = rtw_get_stainfo23a(pstapriv, psta_addr);
 
        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                ("########portctrl:adapter->securitypriv.dot11AuthAlgrthm ="
-                 "%d\n", adapter->securitypriv.dot11AuthAlgrthm));
+                "########portctrl:adapter->securitypriv.dot11AuthAlgrthm =%d\n",
+                adapter->securitypriv.dot11AuthAlgrthm);
 
        prtnframe = precv_frame;
 
@@ -580,8 +565,7 @@ static struct recv_frame *portctrl(struct rtw_adapter *adapter,
                        /* blocked */
                        /* only accept EAPOL frame */
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                                ("########portctrl:psta->ieee8021x_blocked =="
-                                 "1\n"));
+                                "########portctrl:psta->ieee8021x_blocked ==1\n");
 
                        if (ether_type != eapol_type) {
                                /* free this frame */
@@ -608,8 +592,8 @@ int recv_decache(struct recv_frame *precv_frame, u8 bretry,
 
        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));
+                        "recv_decache, (tid>15)! seq_ctrl = 0x%x, tid = 0x%x\n",
+                        seq_ctrl, tid);
 
                return _FAIL;
        }
@@ -617,9 +601,8 @@ int recv_decache(struct recv_frame *precv_frame, u8 bretry,
        if (1) { /* if (bretry) */
                if (seq_ctrl == prxcache->tid_rxseq[tid]) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
-                                ("recv_decache, seq_ctrl = 0x%x, tid = 0x%x, "
-                                 "tid_rxseq = 0x%x\n",
-                                 seq_ctrl, tid, prxcache->tid_rxseq[tid]));
+                                "recv_decache, seq_ctrl = 0x%x, tid = 0x%x, tid_rxseq = 0x%x\n",
+                                seq_ctrl, tid, prxcache->tid_rxseq[tid]);
 
                        return _FAIL;
                }
@@ -777,7 +760,7 @@ static int sta2sta_data_frame(struct rtw_adapter *adapter,
                /*  filter packets that SA is myself or multicast or broadcast */
                if (ether_addr_equal(myhwaddr, pattrib->src)) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                (" SA == myself\n"));
+                                "SA == myself\n");
                        ret = _FAIL;
                        goto exit;
                }
@@ -800,8 +783,7 @@ static int sta2sta_data_frame(struct rtw_adapter *adapter,
                    and DA is my mac-address */
                if (!ether_addr_equal(pattrib->bssid, pattrib->src)) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                ("bssid != TA under STATION_MODE; drop "
-                                 "pkt\n"));
+                                "bssid != TA under STATION_MODE; drop pkt\n");
                        ret = _FAIL;
                        goto exit;
                }
@@ -843,7 +825,8 @@ static int sta2sta_data_frame(struct rtw_adapter *adapter,
                *psta = rtw_get_stainfo23a(pstapriv, sta_addr); /*  get ap_info */
 
        if (*psta == NULL) {
-               RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under sta2sta_data_frame ; drop pkt\n"));
+               RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+                        "can't get psta under sta2sta_data_frame ; drop pkt\n");
                ret = _FAIL;
                goto exit;
        }
@@ -879,7 +862,7 @@ int ap2sta_data_frame(struct rtw_adapter *adapter,
                /* filter packets that SA is myself or multicast or broadcast */
                if (ether_addr_equal(myhwaddr, pattrib->src)) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                (" SA == myself\n"));
+                                "SA == myself\n");
                        ret = _FAIL;
                        goto exit;
                }
@@ -887,8 +870,8 @@ int ap2sta_data_frame(struct rtw_adapter *adapter,
                /*  da should be for me */
                if (!ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                               (" ap2sta_data_frame:  compare DA fail; DA ="
-                                MAC_FMT"\n", MAC_ARG(pattrib->dst)));
+                                "ap2sta_data_frame:  compare DA failed; DA=%pM\n",
+                                pattrib->dst);
                        ret = _FAIL;
                        goto exit;
                }
@@ -898,15 +881,14 @@ int ap2sta_data_frame(struct rtw_adapter *adapter,
                    ether_addr_equal(mybssid, "\x0\x0\x0\x0\x0\x0") ||
                    !ether_addr_equal(pattrib->bssid, mybssid)) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                               (" ap2sta_data_frame:  compare BSSID fail ; "
-                                "BSSID ="MAC_FMT"\n", MAC_ARG(pattrib->bssid)));
+                                "ap2sta_data_frame:  compare BSSID failed; BSSID=%pM\n",
+                                pattrib->bssid);
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                                ("mybssid ="MAC_FMT"\n", MAC_ARG(mybssid)));
+                                "mybssid=%pM\n", mybssid);
 
                        if (!bmcast) {
-                               DBG_8723A("issue_deauth23a to the nonassociated "
-                                         "ap =" MAC_FMT " for the reason(7)\n",
-                                         MAC_ARG(pattrib->bssid));
+                               DBG_8723A("issue_deauth23a to the nonassociated ap=%pM for the reason(7)\n",
+                                         pattrib->bssid);
                                issue_deauth23a(adapter, pattrib->bssid,
                                             WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
                        }
@@ -923,8 +905,7 @@ int ap2sta_data_frame(struct rtw_adapter *adapter,
 
                if (*psta == NULL) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                ("ap2sta: can't get psta under STATION_MODE ;"
-                                 " drop pkt\n"));
+                                "ap2sta: can't get psta under STATION_MODE; drop pkt\n");
                        ret = _FAIL;
                        goto exit;
                }
@@ -952,7 +933,7 @@ int ap2sta_data_frame(struct rtw_adapter *adapter,
                *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid);
                if (*psta == NULL) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                ("can't get psta under MP_MODE ; drop pkt\n"));
+                                "can't get psta under MP_MODE ; drop pkt\n");
                        ret = _FAIL;
                        goto exit;
                }
@@ -964,9 +945,8 @@ int ap2sta_data_frame(struct rtw_adapter *adapter,
                if (ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) {
                        *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid);
                        if (*psta == NULL) {
-                               DBG_8723A("issue_deauth23a to the ap =" MAC_FMT
-                                         " for the reason(7)\n",
-                                         MAC_ARG(pattrib->bssid));
+                               DBG_8723A("issue_deauth23a to the ap=%pM for the reason(7)\n",
+                                         pattrib->bssid);
 
                                issue_deauth23a(adapter, pattrib->bssid,
                                             WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
@@ -1010,10 +990,9 @@ int sta2ap_data_frame(struct rtw_adapter *adapter,
                *psta = rtw_get_stainfo23a(pstapriv, pattrib->src);
                if (*psta == NULL) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                ("can't get psta under AP_MODE; drop pkt\n"));
-                       DBG_8723A("issue_deauth23a to sta =" MAC_FMT
-                                 " for the reason(7)\n",
-                                 MAC_ARG(pattrib->src));
+                                "can't get psta under AP_MODE; drop pkt\n");
+                       DBG_8723A("issue_deauth23a to sta=%pM for the reason(7)\n",
+                                 pattrib->src);
 
                        issue_deauth23a(adapter, pattrib->src,
                                     WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
@@ -1043,8 +1022,8 @@ int sta2ap_data_frame(struct rtw_adapter *adapter,
                        ret = RTW_RX_HANDLED;
                        goto exit;
                }
-               DBG_8723A("issue_deauth23a to sta =" MAC_FMT " for the reason(7)\n",
-                         MAC_ARG(pattrib->src));
+               DBG_8723A("issue_deauth23a to sta=%pM for the reason(7)\n",
+                         pattrib->src);
                issue_deauth23a(adapter, pattrib->src,
                             WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
                ret = RTW_RX_HANDLED;
@@ -1214,12 +1193,12 @@ static int validate_recv_mgnt_frame(struct rtw_adapter *padapter,
        /* struct mlme_priv *pmlmepriv = &adapter->mlmepriv; */
 
        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                ("+validate_recv_mgnt_frame\n"));
+                "+validate_recv_mgnt_frame\n");
 
        precv_frame = recvframe_chk_defrag23a(padapter, precv_frame);
        if (precv_frame == NULL) {
                RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
-                        ("%s: fragment packet\n", __func__));
+                        "%s: fragment packet\n", __func__);
                return _SUCCESS;
        }
 
@@ -1305,7 +1284,7 @@ static int validate_recv_data_frame(struct rtw_adapter *adapter,
                ether_addr_copy(pattrib->ra, hdr->addr1);
                ether_addr_copy(pattrib->ta, hdr->addr2);
                ret = _FAIL;
-               RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" case 3\n"));
+               RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, "case 3\n");
                break;
        }
 
@@ -1314,7 +1293,7 @@ static int validate_recv_data_frame(struct rtw_adapter *adapter,
 
        if (!psta) {
                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                        (" after to_fr_ds_chk; psta == NULL\n"));
+                        "after to_fr_ds_chk; psta == NULL\n");
                ret = _FAIL;
                goto exit;
        }
@@ -1357,26 +1336,25 @@ static int validate_recv_data_frame(struct rtw_adapter *adapter,
        if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) ==
            _FAIL) {
                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                        ("decache : drop pkt\n"));
+                        "decache : drop pkt\n");
                ret = _FAIL;
                goto exit;
        }
 
        if (pattrib->privacy) {
                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                        ("validate_recv_data_frame:pattrib->privacy =%x\n",
-                        pattrib->privacy));
+                        "validate_recv_data_frame:pattrib->privacy =%x\n",
+                        pattrib->privacy);
                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                        ("\n ^^^^^^^^^^^is_multicast_ether_addr"
-                         "(pattrib->ra(0x%02x)) =%d^^^^^^^^^^^^^^^6\n",
-                         pattrib->ra[0],
-                         is_multicast_ether_addr(pattrib->ra)));
+                        "^^^^^^^^^^^is_multicast_ether_addr(pattrib->ra(0x%02x)) =%d^^^^^^^^^^^^^^^6\n",
+                        pattrib->ra[0],
+                        is_multicast_ether_addr(pattrib->ra));
 
                GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt,
                               is_multicast_ether_addr(pattrib->ra));
 
                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                        ("\n pattrib->encrypt =%d\n", pattrib->encrypt));
+                        "pattrib->encrypt =%d\n", pattrib->encrypt);
 
                switch (pattrib->encrypt) {
                case WLAN_CIPHER_SUITE_WEP40:
@@ -1457,7 +1435,7 @@ static int validate_recv_frame(struct rtw_adapter *adapter,
        /* add version chk */
        if (ver != 0) {
                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                        ("validate_recv_data_frame fail! (ver!= 0)\n"));
+                        "validate_recv_data_frame fail! (ver!= 0)\n");
                retval = _FAIL;
                goto exit;
        }
@@ -1482,7 +1460,7 @@ static int validate_recv_frame(struct rtw_adapter *adapter,
                retval = validate_recv_mgnt_frame(adapter, precv_frame);
                if (retval == _FAIL) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                ("validate_recv_mgnt_frame fail\n"));
+                                "validate_recv_mgnt_frame fail\n");
                }
                retval = _FAIL; /*  only data frame return _SUCCESS */
                break;
@@ -1490,7 +1468,7 @@ static int validate_recv_frame(struct rtw_adapter *adapter,
                retval = validate_recv_ctrl_frame(adapter, precv_frame);
                if (retval == _FAIL) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                ("validate_recv_ctrl_frame fail\n"));
+                                "validate_recv_ctrl_frame fail\n");
                }
                retval = _FAIL; /*  only data frame return _SUCCESS */
                break;
@@ -1499,13 +1477,13 @@ static int validate_recv_frame(struct rtw_adapter *adapter,
                retval = validate_recv_data_frame(adapter, precv_frame);
                if (retval == _FAIL) {
                        struct recv_priv *precvpriv = &adapter->recvpriv;
-                       /* RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail\n")); */
+
                        precvpriv->rx_drop++;
                }
                break;
        default:
                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                        ("validate_recv_data_frame fail! type = 0x%x\n", type));
+                        "validate_recv_data_frame fail! type = 0x%x\n", type);
                retval = _FAIL;
                break;
        }
@@ -1552,8 +1530,8 @@ static int wlanhdr_to_ethhdr (struct recv_frame *precvframe)
        len = skb->len - hdrlen;
 
        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                ("\n === pattrib->hdrlen: %x,  pattrib->iv_len:%x ===\n\n",
-                 pattrib->hdrlen,  pattrib->iv_len));
+                "=== pattrib->hdrlen: %x,  pattrib->iv_len:%x ===\n",
+                pattrib->hdrlen,  pattrib->iv_len);
 
        pattrib->eth_type = eth_type;
        if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
@@ -1665,7 +1643,7 @@ struct recv_frame *recvframe_defrag(struct rtw_adapter *adapter,
        rtw_free_recvframe23a_queue(defrag_q);
 
        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                ("Performance defrag!!!!!\n"));
+                "Performance defrag!!!!!\n");
 
 
 
@@ -1736,8 +1714,8 @@ struct recv_frame *recvframe_chk_defrag23a(struct rtw_adapter *padapter,
                        /* spin_unlock(&pdefrag_q->lock); */
 
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                                ("Enqueuq: ismfrag = %d, fragnum = %d\n",
-                                 ismfrag, fragnum));
+                                "Enqueuq: ismfrag = %d, fragnum = %d\n",
+                                ismfrag, fragnum);
 
                        prtnframe = NULL;
 
@@ -1747,8 +1725,8 @@ struct recv_frame *recvframe_chk_defrag23a(struct rtw_adapter *padapter,
                        rtw_free_recvframe23a(precv_frame);
                        prtnframe = NULL;
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                ("Free because pdefrag_q == NULL: ismfrag = "
-                                 "%d, fragnum = %d\n", ismfrag, fragnum));
+                                "Free because pdefrag_q == NULL: ismfrag = %d, fragnum = %d\n",
+                                ismfrag, fragnum);
                }
        }
 
@@ -1763,8 +1741,8 @@ struct recv_frame *recvframe_chk_defrag23a(struct rtw_adapter *padapter,
 
                        /* call recvframe_defrag to defrag */
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                                ("defrag: ismfrag = %d, fragnum = %d\n",
-                                 ismfrag, fragnum));
+                                "defrag: ismfrag = %d, fragnum = %d\n",
+                                ismfrag, fragnum);
                        precv_frame = recvframe_defrag(padapter, pdefrag_q);
                        prtnframe = precv_frame;
                } else {
@@ -1773,8 +1751,8 @@ struct recv_frame *recvframe_chk_defrag23a(struct rtw_adapter *padapter,
                        rtw_free_recvframe23a(precv_frame);
                        prtnframe = NULL;
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                ("Free because pdefrag_q == NULL: ismfrag = "
-                                 "%d, fragnum = %d\n", ismfrag, fragnum));
+                                "Free because pdefrag_q == NULL: ismfrag = %d, fragnum = %d\n",
+                                ismfrag, fragnum);
                }
 
        }
@@ -1783,8 +1761,7 @@ struct recv_frame *recvframe_chk_defrag23a(struct rtw_adapter *padapter,
                /* after defrag we must check tkip mic code */
                if (recvframe_chkmic(padapter,  prtnframe) == _FAIL) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                ("recvframe_chkmic(padapter,  prtnframe) =="
-                                 "_FAIL\n"));
+                                "recvframe_chkmic(padapter,  prtnframe) ==_FAIL\n");
                        rtw_free_recvframe23a(prtnframe);
                        prtnframe = NULL;
                }
@@ -1883,7 +1860,6 @@ static int enqueue_reorder_recvframe23a(struct recv_reorder_ctrl *preorder_ctrl,
                        continue;
                } else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) {
                        /* Duplicate entry is found!! Do not insert current entry. */
-                       /* RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); */
 
                        /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
                        return false;
@@ -1904,7 +1880,6 @@ static int enqueue_reorder_recvframe23a(struct recv_reorder_ctrl *preorder_ctrl,
        /* spin_unlock_ex(&ppending_recvframe_queue->lock); */
        /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
 
-       /* RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); */
        return true;
 }
 
@@ -1956,10 +1931,9 @@ int recv_indicatepkts_in_order(struct rtw_adapter *padapter,
 
                if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
-                                ("recv_indicatepkts_in_order: indicate =%d "
-                                 "seq =%d amsdu =%d\n",
-                                 preorder_ctrl->indicate_seq,
-                                 pattrib->seq_num, pattrib->amsdu));
+                                "recv_indicatepkts_in_order: indicate =%d seq =%d amsdu =%d\n",
+                                preorder_ctrl->indicate_seq,
+                                pattrib->seq_num, pattrib->amsdu);
 
                        plist = plist->next;
                        list_del_init(&prframe->list);
@@ -2021,8 +1995,7 @@ int recv_indicatepkt_reorder(struct rtw_adapter *padapter,
                        if ((padapter->bDriverStopped == false) &&
                            (padapter->bSurpriseRemoved == false)) {
                                RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
-                                        ("@@@@  recv_indicatepkt_reorder -"
-                                         "recv_func recv_indicatepkt\n"));
+                                        "@@@@  recv_indicatepkt_reorder -recv_func recv_indicatepkt\n");
 
                                rtw_recv_indicatepkt23a(padapter, prframe);
                                return _SUCCESS;
@@ -2055,8 +2028,8 @@ int recv_indicatepkt_reorder(struct rtw_adapter *padapter,
        spin_lock_bh(&ppending_recvframe_queue->lock);
 
        RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
-                ("recv_indicatepkt_reorder: indicate =%d seq =%d\n",
-                 preorder_ctrl->indicate_seq, pattrib->seq_num));
+                "recv_indicatepkt_reorder: indicate =%d seq =%d\n",
+                preorder_ctrl->indicate_seq, pattrib->seq_num);
 
        /* s2. check if winstart_b(indicate_seq) needs to been updated */
        if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) {
@@ -2149,7 +2122,7 @@ int process_recv_indicatepkts(struct rtw_adapter *padapter,
                retval = wlanhdr_to_ethhdr(prframe);
                if (retval != _SUCCESS) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                ("wlanhdr_to_ethhdr: drop pkt\n"));
+                                "wlanhdr_to_ethhdr: drop pkt\n");
                        return retval;
                }
 
@@ -2157,19 +2130,16 @@ int process_recv_indicatepkts(struct rtw_adapter *padapter,
                    (padapter->bSurpriseRemoved == false)) {
                        /* indicate this recv_frame */
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
-                                ("@@@@ process_recv_indicatepkts- "
-                                 "recv_func recv_indicatepkt\n"));
+                                "@@@@ process_recv_indicatepkts- recv_func recv_indicatepkt\n");
                        rtw_recv_indicatepkt23a(padapter, prframe);
                } else {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
-                                ("@@@@ process_recv_indicatepkts- "
-                                 "recv_func free_indicatepkt\n"));
+                                "@@@@ process_recv_indicatepkts- recv_func free_indicatepkt\n");
 
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
-                                ("recv_func:bDriverStopped(%d) OR "
-                                 "bSurpriseRemoved(%d)",
-                                 padapter->bDriverStopped,
-                                 padapter->bSurpriseRemoved));
+                                "recv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n",
+                                padapter->bDriverStopped,
+                                padapter->bSurpriseRemoved);
                        retval = _FAIL;
                        return retval;
                }
@@ -2188,7 +2158,7 @@ static int recv_func_prehandle(struct rtw_adapter *padapter,
        ret = validate_recv_frame(padapter, rframe);
        if (ret != _SUCCESS) {
                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                        ("recv_func: validate_recv_frame fail! drop pkt\n"));
+                        "recv_func: validate_recv_frame fail! drop pkt\n");
                rtw_free_recvframe23a(rframe);
                goto exit;
        }
@@ -2208,7 +2178,7 @@ static int recv_func_posthandle(struct rtw_adapter *padapter,
        prframe = decryptor(padapter, prframe);
        if (prframe == NULL) {
                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                        ("decryptor: drop pkt\n"));
+                        "decryptor: drop pkt\n");
                ret = _FAIL;
                goto _recv_data_drop;
        }
@@ -2216,7 +2186,7 @@ static int recv_func_posthandle(struct rtw_adapter *padapter,
        prframe = recvframe_chk_defrag23a(padapter, prframe);
        if (!prframe) {
                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                        ("recvframe_chk_defrag23a: drop pkt\n"));
+                        "recvframe_chk_defrag23a: drop pkt\n");
                goto _recv_data_drop;
        }
 
@@ -2235,7 +2205,7 @@ static int recv_func_posthandle(struct rtw_adapter *padapter,
        prframe = portctrl(padapter, prframe);
        if (!prframe) {
                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                        ("portctrl: drop pkt\n"));
+                        "portctrl: drop pkt\n");
                ret = _FAIL;
                goto _recv_data_drop;
        }
@@ -2245,7 +2215,7 @@ static int recv_func_posthandle(struct rtw_adapter *padapter,
        ret = process_recv_indicatepkts(padapter, prframe);
        if (ret != _SUCCESS) {
                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                        ("recv_func: process_recv_indicatepkts fail!\n"));
+                        "recv_func: process_recv_indicatepkts fail!\n");
                rtw_free_recvframe23a(orig_prframe);/* free this recv_frame */
                goto _recv_data_drop;
        }
@@ -2334,8 +2304,8 @@ void rtw_signal_stat_timer_hdl23a(unsigned long data)
 
        /* update value of signal_strength, rssi, signal_qual */
        if (!check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY)) {
-               tmp_s = (avg_signal_strength + (_alpha - 1) *
-                        recvpriv->signal_strength);
+               tmp_s = avg_signal_strength + (_alpha - 1) *
+                        recvpriv->signal_strength;
                if (tmp_s %_alpha)
                        tmp_s = tmp_s / _alpha + 1;
                else
index 715a47414bdd587ec58355edab079ebf3da52a86..af53c92fc3a29063c6e0ee9ddaf9a6db9f606d41 100644 (file)
@@ -31,11 +31,11 @@ struct arc4context {
 
 static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len)
 {
-       u32     t, u;
-       u32     keyindex;
-       u32     stateindex;
+       u32 t, u;
+       u32 keyindex;
+       u32 stateindex;
        u8 *state;
-       u32     counter;
+       u32 counter;
 
        state = parc4ctx->state;
        parc4ctx->x = 0;
@@ -55,7 +55,8 @@ static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len)
        }
 
 }
-static u32 arcfour_byte(       struct arc4context      *parc4ctx)
+
+static u32 arcfour_byte(struct arc4context *parc4ctx)
 {
        u32 x;
        u32 y;
@@ -75,19 +76,16 @@ static u32 arcfour_byte(    struct arc4context      *parc4ctx)
        return state[(sx + sy) & 0xff];
 }
 
-static void arcfour_encrypt(   struct arc4context      *parc4ctx,
-       u8 *dest,
-       u8 *src,
-       u32 len)
+static void arcfour_encrypt(struct arc4context *parc4ctx, u8 *dest,
+                           u8 *src, u32 len)
 {
-       u32     i;
+       u32 i;
 
        for (i = 0; i < len; i++)
                dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx);
-
 }
 
-static int bcrc32initialized = 0;
+static int bcrc32initialized;
 static u32 crc32_table[256];
 
 static u8 crc32_reverseBit(u8 data)
@@ -101,46 +99,48 @@ static u8 crc32_reverseBit(u8 data)
 
 static void crc32_init(void)
 {
+       int i, j;
+       u32 c;
+       u8 *p, *p1;
+       u8 k;
 
        if (bcrc32initialized == 1)
                return;
-       else{
-               int 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;
+
+       p = (u8 *) &c;
+       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;
 }
 
 static u32 getcrc32(u8 *buf, int len)
 {
        u8 *p;
-       u32  crc;
+       u32 crc;
 
-       if (bcrc32initialized == 0) crc32_init();
+       if (bcrc32initialized == 0)
+               crc32_init();
 
-       crc = 0xffffffff;       /* preload shift register, per CRC-32 spec */
+       crc = 0xffffffff; /* preload shift register, per CRC-32 spec */
 
        for (p = buf; len > 0; ++p, --len)
-               crc = crc32_table[ (crc ^ *p) & 0xff] ^ (crc >> 8);
+               crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8);
 
-       return ~crc;    /* transmit complement, per CRC-32 spec */
+       return ~crc; /* transmit complement, per CRC-32 spec */
 }
 
 /* Need to consider the fragment  situation */
@@ -152,7 +152,7 @@ void rtw_wep_encrypt23a(struct rtw_adapter *padapter,
        struct arc4context mycontext;
        int curfragnum, length, index;
        u32 keylength;
-       u8 *pframe, *payload, *iv;    /* wepkey */
+       u8 *pframe, *payload, *iv; /* wepkey */
        u8 wepkey[16];
        u8 hw_hdr_offset = 0;
        struct pkt_attrib *pattrib = &pxmitframe->attrib;
@@ -184,7 +184,7 @@ void rtw_wep_encrypt23a(struct rtw_adapter *padapter,
                if ((curfragnum + 1) == pattrib->nr_frags) {
                        /* the last fragment */
                        length = pattrib->last_txcmdsz - pattrib->hdrlen -
-                               pattrib->iv_len- pattrib->icv_len;
+                               pattrib->iv_len - pattrib->icv_len;
 
                        *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
 
@@ -210,7 +210,7 @@ void rtw_wep_decrypt23a(struct rtw_adapter *padapter,
                     struct recv_frame *precvframe)
 {
        /*  exclude ICV */
-       u8 crc[4];
+       u32 actual_crc, expected_crc;
        struct arc4context mycontext;
        int length;
        u32 keylength;
@@ -243,19 +243,14 @@ void rtw_wep_decrypt23a(struct rtw_adapter *padapter,
        arcfour_encrypt(&mycontext, payload, payload, length);
 
        /* calculate icv and compare the icv */
-       *((u32 *)crc) = le32_to_cpu(getcrc32(payload, length - 4));
+       actual_crc = le32_to_cpu(getcrc32(payload, length - 4));
+       expected_crc = le32_to_cpu(get_unaligned_le32(&payload[length - 4]));
 
-       if (crc[3] != payload[length - 1] || crc[2] != payload[length - 2] ||
-           crc[1] != payload[length - 3] || crc[0] != payload[length - 4]) {
+       if (actual_crc != expected_crc) {
                RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
-                        ("rtw_wep_decrypt23a:icv error crc[3](%x)!= payload"
-                         "[length-1](%x) || crc[2](%x)!= payload[length-2](%x)"
-                         " || crc[1](%x)!= payload[length-3](%x) || crc[0](%x)"
-                         "!= payload[length-4](%x)\n",
-                         crc[3], payload[length - 1],
-                         crc[2], payload[length - 2],
-                         crc[1], payload[length - 3],
-                         crc[0], payload[length - 4]));
+                        "%s:icv CRC mismatch: "
+                        "actual: %08x, expected: %08x\n",
+                        __func__, actual_crc, expected_crc);
        }
 }
 
@@ -267,9 +262,8 @@ static u32 secmicgetuint32(u8 *p)
        s32 i;
        u32 res = 0;
 
-       for (i = 0; i<4; i++) {
-               res |= ((u32)(*p++)) << (8*i);
-       }
+       for (i = 0; i < 4; i++)
+               res |= ((u32)(*p++)) << (8 * i);
 
        return res;
 }
@@ -279,7 +273,7 @@ static void secmicputuint32(u8 *p, u32 val)
 {
        long i;
 
-       for (i = 0; i<4; i++) {
+       for (i = 0; i < 4; i++) {
                *p++ = (u8) (val & 0xff);
                val >>= 8;
        }
@@ -312,7 +306,7 @@ void rtw_secmicappend23abyte23a(struct mic_data *pmicdata, u8 b)
 {
 
        /*  Append the byte to our word-sized buffer */
-       pmicdata->M |= ((unsigned long)b) << (8*pmicdata->nBytesInM);
+       pmicdata->M |= ((unsigned long)b) << (8 * pmicdata->nBytesInM);
        pmicdata->nBytesInM++;
        /*  Process the word if it is full. */
        if (pmicdata->nBytesInM >= 4) {
@@ -336,7 +330,7 @@ void rtw_secmicappend23a(struct mic_data *pmicdata, u8 *src, u32 nbytes)
 {
 
        /*  This is simple */
-       while(nbytes > 0) {
+       while (nbytes > 0) {
                rtw_secmicappend23abyte23a(pmicdata, *src++);
                nbytes--;
        }
@@ -353,12 +347,11 @@ void rtw_secgetmic23a(struct mic_data *pmicdata, u8 *dst)
        rtw_secmicappend23abyte23a(pmicdata, 0);
        rtw_secmicappend23abyte23a(pmicdata, 0);
        /*  and then zeroes until the length is a multiple of 4 */
-       while(pmicdata->nBytesInM != 0) {
+       while (pmicdata->nBytesInM != 0)
                rtw_secmicappend23abyte23a(pmicdata, 0);
-       }
        /*  The appendByte function has already computed the result. */
        secmicputuint32(dst, pmicdata->L);
-       secmicputuint32(dst+4, pmicdata->R);
+       secmicputuint32(dst + 4, pmicdata->R);
        /*  Reset to the empty message. */
        secmicclear(pmicdata);
 
@@ -368,23 +361,22 @@ void rtw_seccalctkipmic23a(u8 *key, u8 *header, u8 *data, u32 data_len,
                           u8 *mic_code, u8 pri)
 {
 
-       struct mic_data micdata;
-       u8 priority[4]={0x0, 0x0, 0x0, 0x0};
+       struct mic_data micdata;
+       u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
 
        rtw_secmicsetkey23a(&micdata, key);
-       priority[0]= pri;
+       priority[0] = pri;
 
        /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
-       if (header[1]&1) {   /* ToDS == 1 */
-                       rtw_secmicappend23a(&micdata, &header[16], 6);  /* DA */
-               if (header[1]&2)  /* From Ds == 1 */
+       if (header[1]&1) { /* ToDS == 1 */
+                       rtw_secmicappend23a(&micdata, &header[16], 6); /* DA */
+               if (header[1]&2) /* From Ds == 1 */
                        rtw_secmicappend23a(&micdata, &header[24], 6);
                else
                        rtw_secmicappend23a(&micdata, &header[10], 6);
-       }
-       else{   /* ToDS == 0 */
-               rtw_secmicappend23a(&micdata, &header[4], 6);   /* DA */
-               if (header[1]&2)  /* From Ds == 1 */
+       } else { /* ToDS == 0 */
+               rtw_secmicappend23a(&micdata, &header[4], 6); /* DA */
+               if (header[1]&2) /* From Ds == 1 */
                        rtw_secmicappend23a(&micdata, &header[16], 6);
                else
                        rtw_secmicappend23a(&micdata, &header[10], 6);
@@ -403,11 +395,11 @@ void rtw_seccalctkipmic23a(u8 *key, u8 *header, u8 *data, u32 data_len,
 #define   Lo8(v16)   ((u8)((v16)       & 0x00FF))
 #define   Hi8(v16)   ((u8)(((v16) >> 8) & 0x00FF))
 #define  Lo16(v32)   ((u16)((v32)       & 0xFFFF))
-#define  Hi16(v32)   ((u16)(((v32) >>16) & 0xFFFF))
+#define  Hi16(v32)   ((u16)(((v32) >> 16) & 0xFFFF))
 #define  Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8))
 
-/* select the Nth 16-bit word of the temporal key unsigned char array TK[]   */
-#define  TK16(N)     Mk16(tk[2*(N)+1], tk[2*(N)])
+/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */
+#define  TK16(N)     Mk16(tk[2 * (N) + 1], tk[2 * (N)])
 
 /* S-box lookup: 16 bits --> 16 bits */
 #define _S_(v16)     (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)])
@@ -420,76 +412,76 @@ void rtw_seccalctkipmic23a(u8 *key, u8 *header, u8 *data, u32 data_len,
 #define RC4_KEY_SIZE     16    /* 128-bit RC4KEY (104 bits unknown) */
 
 /* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */
-static const unsigned short Sbox1[2][256]=       /* Sbox for hash (can be in ROM)     */
-{ {
-   0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
-   0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
-   0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
-   0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
-   0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
-   0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
-   0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
-   0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
-   0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
-   0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
-   0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
-   0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
-   0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
-   0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
-   0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
-   0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
-   0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
-   0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
-   0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
-   0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
-   0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
-   0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
-   0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
-   0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
-   0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
-   0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
-   0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
-   0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
-   0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
-   0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
-   0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
-   0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
-  },
-
-   /* second half of table is unsigned char-reversed version of first! */
-   0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
-   0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
-   0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
-   0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
-   0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
-   0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
-   0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
-   0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
-   0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
-   0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
-   0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
-   0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
-   0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
-   0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
-   0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
-   0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
-   0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
-   0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
-   0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
-   0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
-   0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
-   0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
-   0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
-   0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
-   0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
-   0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
-   0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
-   0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
-   0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
-   0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
-   0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
-   0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C,
-  }
+static const unsigned short Sbox1[2][256] = {
+       /* Sbox for hash (can be in ROM) */
+       {
+               0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
+               0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
+               0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
+               0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
+               0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
+               0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
+               0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
+               0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
+               0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
+               0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
+               0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
+               0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
+               0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
+               0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
+               0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
+               0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
+               0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
+               0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
+               0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
+               0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
+               0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
+               0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
+               0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
+               0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
+               0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
+               0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
+               0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
+               0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
+               0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
+               0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
+               0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
+               0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
+       },
+       { /* second half of table is unsigned char-reversed version of first! */
+               0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
+               0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
+               0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
+               0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
+               0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
+               0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
+               0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
+               0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
+               0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
+               0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
+               0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
+               0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
+               0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
+               0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
+               0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
+               0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
+               0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
+               0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
+               0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
+               0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
+               0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
+               0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
+               0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
+               0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
+               0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
+               0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
+               0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
+               0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
+               0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
+               0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
+               0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
+               0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C,
+       }
 };
 
  /*
@@ -513,7 +505,7 @@ static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
 {
        int  i;
 
-       /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5]     */
+       /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */
        p1k[0]      = Lo16(iv32);
        p1k[1]      = Hi16(iv32);
        p1k[2]      = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */
@@ -522,14 +514,14 @@ static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
 
        /* Now compute an unbalanced Feistel cipher with 80-bit block */
        /* size on the 80-bit block P1K[], using the 128-bit key TK[] */
-       for (i = 0; i < PHASE1_LOOP_CNT ;i++) {
+       for (i = 0; i < PHASE1_LOOP_CNTi++) {
                /* Each add operation here is mod 2**16 */
-               p1k[0] += _S_(p1k[4] ^ TK16((i&1)+0));
-               p1k[1] += _S_(p1k[0] ^ TK16((i&1)+2));
-               p1k[2] += _S_(p1k[1] ^ TK16((i&1)+4));
-               p1k[3] += _S_(p1k[2] ^ TK16((i&1)+6));
-               p1k[4] += _S_(p1k[3] ^ TK16((i&1)+0));
-               p1k[4] +=  (unsigned short)i;                    /* avoid "slide attacks" */
+               p1k[0] += _S_(p1k[4] ^ TK16((i & 1) + 0));
+               p1k[1] += _S_(p1k[0] ^ TK16((i & 1) + 2));
+               p1k[2] += _S_(p1k[1] ^ TK16((i & 1) + 4));
+               p1k[3] += _S_(p1k[2] ^ TK16((i & 1) + 6));
+               p1k[4] += _S_(p1k[3] ^ TK16((i & 1) + 0));
+               p1k[4] +=  (unsigned short) i; /* avoid "slide attacks" */
                }
 
 }
@@ -560,42 +552,44 @@ static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
 static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16)
 {
        int  i;
-       u16 PPK[6];                          /* temporary key for mixing    */
+       u16 PPK[6]; /* temporary key for mixing    */
+
+       /* Note: all adds in the PPK[] equations below are mod 2**16 */
+       for (i = 0; i < 5; i++)
+               PPK[i] = p1k[i]; /* first, copy P1K to PPK */
 
-       /* Note: all adds in the PPK[] equations below are mod 2**16         */
-       for (i = 0;i<5;i++) PPK[i]= p1k[i];      /* first, copy P1K to PPK      */
-               PPK[5]  =  p1k[4] +iv16;             /* next,  add in IV16          */
+       PPK[5] = p1k[4] + iv16; /* next,  add in IV16 */
 
-       /* Bijective non-linear mixing of the 96 bits of PPK[0..5]           */
-       PPK[0] +=    _S_(PPK[5] ^ TK16(0));   /* Mix key in each "round"     */
-       PPK[1] +=    _S_(PPK[0] ^ TK16(1));
-       PPK[2] +=    _S_(PPK[1] ^ TK16(2));
-       PPK[3] +=    _S_(PPK[2] ^ TK16(3));
-       PPK[4] +=    _S_(PPK[3] ^ TK16(4));
-       PPK[5] +=    _S_(PPK[4] ^ TK16(5));   /* Total # S-box lookups == 6  */
+       /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */
+       PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */
+       PPK[1] += _S_(PPK[0] ^ TK16(1));
+       PPK[2] += _S_(PPK[1] ^ TK16(2));
+       PPK[3] += _S_(PPK[2] ^ TK16(3));
+       PPK[4] += _S_(PPK[3] ^ TK16(4));
+       PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */
 
-       /* Final sweep: bijective, "linear". Rotates kill LSB correlations   */
+       /* Final sweep: bijective, "linear". Rotates kill LSB correlations */
        PPK[0] +=  RotR1(PPK[5] ^ TK16(6));
-       PPK[1] +=  RotR1(PPK[0] ^ TK16(7));   /* Use all of TK[] in Phase2   */
+       PPK[1] +=  RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */
        PPK[2] +=  RotR1(PPK[1]);
        PPK[3] +=  RotR1(PPK[2]);
        PPK[4] +=  RotR1(PPK[3]);
        PPK[5] +=  RotR1(PPK[4]);
        /* Note: At this point, for a given key TK[0..15], the 96-bit output */
        /*       value PPK[0..5] is guaranteed to be unique, as a function   */
-       /*       of the 96-bit "input" value   {TA, IV32, IV16}. That is, P1K  */
-       /*       is now a keyed permutation of {TA, IV32, IV16}.               */
+       /*       of the 96-bit "input" value   {TA, IV32, IV16}. That is,    */
+       /*       P1K is now a keyed permutation of {TA, IV32, IV16}.         */
 
        /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key   */
-       rc4key[0] = Hi8(iv16);                /* RC4KEY[0..2] is the WEP IV  */
-       rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys  */
+       rc4key[0] = Hi8(iv16);                 /* RC4KEY[0..2] is the WEP IV */
+       rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */
        rc4key[2] = Lo8(iv16);
        rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1);
 
-       /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15]  (little-endian)       */
-       for (i = 0;i<6;i++) {
-               rc4key[4+2*i] = Lo8(PPK[i]);
-               rc4key[5+2*i] = Hi8(PPK[i]);
+       /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15]  (little-endian) */
+       for (i = 0; i < 6; i++) {
+               rc4key[4 + 2 * i] = Lo8(PPK[i]);
+               rc4key[5 + 2 * i] = Hi8(PPK[i]);
        }
 
 }
@@ -604,97 +598,107 @@ static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16)
 int rtw_tkip_encrypt23a(struct rtw_adapter *padapter,
                        struct xmit_frame *pxmitframe)
 {
-       u16     pnl;
-       u32     pnh;
-       u8      rc4key[16];
-       u8   ttkey[16];
-       u8      crc[4];
-       u8   hw_hdr_offset = 0;
+       u16 pnl;
+       u32 pnh;
+       u8 rc4key[16];
+       u8 ttkey[16];
+       u8 crc[4];
+       u8 hw_hdr_offset = 0;
        struct arc4context mycontext;
-       int                     curfragnum, length;
-       u32     prwskeylen;
-       u8      *pframe, *payload, *iv, *prwskey;
+       int curfragnum, length;
+       u32 prwskeylen;
+       u8 *pframe, *payload, *iv, *prwskey;
        union pn48 dot11txpn;
-       struct  sta_info                *stainfo;
-       struct  pkt_attrib       *pattrib = &pxmitframe->attrib;
-       struct  security_priv   *psecuritypriv = &padapter->securitypriv;
-       struct  xmit_priv               *pxmitpriv = &padapter->xmitpriv;
+       struct sta_info *stainfo;
+       struct pkt_attrib *pattrib = &pxmitframe->attrib;
+       struct security_priv *psecuritypriv = &padapter->securitypriv;
+       struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
        int res = _SUCCESS;
 
+       if (pattrib->encrypt != WLAN_CIPHER_SUITE_TKIP)
+               return _FAIL;
+
        if (!pxmitframe->buf_addr)
                return _FAIL;
 
        hw_hdr_offset = TXDESC_OFFSET;
 
        pframe = pxmitframe->buf_addr + hw_hdr_offset;
-       /* 4 start to encrypt each fragment */
-       if (pattrib->encrypt == WLAN_CIPHER_SUITE_TKIP) {
-               if (pattrib->psta)
-                       stainfo = pattrib->psta;
-               else {
-                       DBG_8723A("%s, call rtw_get_stainfo()\n", __func__);
-                       stainfo = rtw_get_stainfo23a(&padapter->stapriv,
-                                                    &pattrib->ra[0]);
-               }
 
-               if (stainfo!= NULL) {
+       if (pattrib->psta)
+               stainfo = pattrib->psta;
+       else {
+               DBG_8723A("%s, call rtw_get_stainfo()\n", __func__);
+               stainfo = rtw_get_stainfo23a(&padapter->stapriv,
+                                            &pattrib->ra[0]);
+       }
 
-                       if (!(stainfo->state &_FW_LINKED)) {
-                               DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state);
-                               return _FAIL;
-                       }
+       if (stainfo == NULL) {
+               RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
+                        "%s: stainfo == NULL!!!\n", __func__);
+               DBG_8723A("%s, psta == NUL\n", __func__);
+               return _FAIL;
+       }
 
-                       RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt23a: stainfo!= NULL!!!\n"));
+       RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
+                "%s: stainfo!= NULL!!!\n", __func__);
 
-                       if (is_multicast_ether_addr(pattrib->ra))
-                               prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
-                       else
-                               prwskey = &stainfo->dot118021x_UncstKey.skey[0];
+       if (!(stainfo->state & _FW_LINKED)) {
+               DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state);
+               return _FAIL;
+       }
 
-                       prwskeylen = 16;
+       if (is_multicast_ether_addr(pattrib->ra))
+               prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
+       else
+               prwskey = &stainfo->dot118021x_UncstKey.skey[0];
 
-                       for (curfragnum = 0;curfragnum<pattrib->nr_frags;curfragnum++) {
-                               iv = pframe+pattrib->hdrlen;
-                               payload = pframe+pattrib->iv_len+pattrib->hdrlen;
+       prwskeylen = 16;
 
-                               GET_TKIP_PN(iv, dot11txpn);
+       /* 4 start to encrypt each fragment */
+       for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
+               iv = pframe + pattrib->hdrlen;
+               payload = pframe + pattrib->iv_len + pattrib->hdrlen;
 
-                               pnl = (u16)(dot11txpn.val);
-                               pnh = (u32)(dot11txpn.val>>16);
+               GET_TKIP_PN(iv, dot11txpn);
 
-                               phase1((u16 *)&ttkey[0], prwskey,&pattrib->ta[0], pnh);
+               pnl = (u16)(dot11txpn.val);
+               pnh = (u32)(dot11txpn.val>>16);
 
-                               phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl);
+               phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh);
 
-                               if ((curfragnum+1) == pattrib->nr_frags) {      /* 4 the last fragment */
-                                       length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len- pattrib->icv_len;
-                                       RT_TRACE(_module_rtl871x_security_c_, _drv_info_, ("pattrib->iv_len =%x, pattrib->icv_len =%x\n", pattrib->iv_len, pattrib->icv_len));
-                                       *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));/* modified by Amy*/
+               phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl);
 
-                                       arcfour_init(&mycontext, rc4key, 16);
-                                       arcfour_encrypt(&mycontext, payload, payload, length);
-                                       arcfour_encrypt(&mycontext, payload+length, crc, 4);
+               if ((curfragnum + 1) == pattrib->nr_frags) { /* 4 the last fragment */
+                       length = (pattrib->last_txcmdsz -
+                                 pattrib->hdrlen -
+                                 pattrib->iv_len -
+                                 pattrib->icv_len);
 
-                               }
-                               else{
-                                       length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len ;
-                                       *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));/* modified by Amy*/
-                                       arcfour_init(&mycontext, rc4key, 16);
-                                       arcfour_encrypt(&mycontext, payload, payload, length);
-                                       arcfour_encrypt(&mycontext, payload+length, crc, 4);
+                       RT_TRACE(_module_rtl871x_security_c_, _drv_info_,
+                                "pattrib->iv_len =%x, pattrib->icv_len =%x\n",
+                                pattrib->iv_len,
+                                pattrib->icv_len);
+                       *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
 
-                               pframe+= pxmitpriv->frag_len;
-                               pframe = PTR_ALIGN(pframe, 4);
-                               }
-                       }
+                       arcfour_init(&mycontext, rc4key, 16);
+                       arcfour_encrypt(&mycontext, payload, payload, length);
+                       arcfour_encrypt(&mycontext, payload + length, crc, 4);
 
-               }
-               else{
-                       RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt23a: stainfo == NULL!!!\n"));
-                       DBG_8723A("%s, psta == NUL\n", __func__);
-                       res = _FAIL;
-               }
+               } else {
+                       length = (pxmitpriv->frag_len -
+                                 pattrib->hdrlen -
+                                 pattrib->iv_len -
+                                 pattrib->icv_len);
 
+                       *((u32 *)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);
+
+                       pframe += pxmitpriv->frag_len;
+                       pframe  = PTR_ALIGN(pframe, 4);
+               }
        }
 
        return res;
@@ -706,72 +710,76 @@ int rtw_tkip_decrypt23a(struct rtw_adapter *padapter,
 {
        u16 pnl;
        u32 pnh;
-       u8   rc4key[16];
-       u8   ttkey[16];
-       u8      crc[4];
+       u8 rc4key[16];
+       u8 ttkey[16];
+       u32 actual_crc, expected_crc;
        struct arc4context mycontext;
-       int     length;
-       u32     prwskeylen;
-       u8      *pframe, *payload, *iv, *prwskey;
+       int length;
+       u32 prwskeylen;
+       u8 *pframe, *payload, *iv, *prwskey;
        union pn48 dot11txpn;
-       struct  sta_info                *stainfo;
-       struct  rx_pkt_attrib *prxattrib = &precvframe->attrib;
-       struct  security_priv *psecuritypriv = &padapter->securitypriv;
+       struct sta_info *stainfo;
+       struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
+       struct security_priv *psecuritypriv = &padapter->securitypriv;
        struct sk_buff *skb = precvframe->pkt;
        int res = _SUCCESS;
 
+       if (prxattrib->encrypt != WLAN_CIPHER_SUITE_TKIP)
+               return _FAIL;
+
        pframe = skb->data;
 
+       stainfo = rtw_get_stainfo23a(&padapter->stapriv,
+                                    &prxattrib->ta[0]);
+       if (stainfo == NULL) {
+               RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
+                        "%s: stainfo == NULL!!!\n", __func__);
+               return _FAIL;
+       }
+
        /* 4 start to decrypt recvframe */
-       if (prxattrib->encrypt == WLAN_CIPHER_SUITE_TKIP) {
+       if (is_multicast_ether_addr(prxattrib->ra)) {
+               if (psecuritypriv->binstallGrpkey == 0) {
+                       res = _FAIL;
+                       DBG_8723A("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__);
+                       goto exit;
+               }
+               prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
+               prwskeylen = 16;
+       } else {
+               RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
+                        "%s: stainfo!= NULL!!!\n", __func__);
+               prwskey = &stainfo->dot118021x_UncstKey.skey[0];
+               prwskeylen = 16;
+       }
 
-               stainfo = rtw_get_stainfo23a(&padapter->stapriv,
-                                            &prxattrib->ta[0]);
-               if (stainfo!= NULL) {
-
-                       if (is_multicast_ether_addr(prxattrib->ra)) {
-                               if (psecuritypriv->binstallGrpkey == 0) {
-                                       res = _FAIL;
-                                       DBG_8723A("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__);
-                                       goto exit;
-                               }
-                               prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
-                               prwskeylen = 16;
-                       } else {
-                               RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt23a: stainfo!= NULL!!!\n"));
-                               prwskey = &stainfo->dot118021x_UncstKey.skey[0];
-                               prwskeylen = 16;
-                       }
-
-                       iv = pframe+prxattrib->hdrlen;
-                       payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
-                       length = skb->len - prxattrib->hdrlen-prxattrib->iv_len;
-
-                       GET_TKIP_PN(iv, dot11txpn);
-
-                       pnl = (u16)(dot11txpn.val);
-                       pnh = (u32)(dot11txpn.val>>16);
-
-                       phase1((u16 *)&ttkey[0], prwskey,&prxattrib->ta[0], pnh);
-                       phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl);
-
-                       /* 4 decrypt payload include icv */
-                       arcfour_init(&mycontext, rc4key, 16);
-                       arcfour_encrypt(&mycontext, payload, payload, length);
+       iv = pframe + prxattrib->hdrlen;
+       payload = pframe + prxattrib->iv_len + prxattrib->hdrlen;
+       length = skb->len - prxattrib->hdrlen - prxattrib->iv_len;
 
-                       *((u32 *)crc) = le32_to_cpu(getcrc32(payload, length-4));
+       GET_TKIP_PN(iv, dot11txpn);
 
-                       if (crc[3]!= payload[length-1] || crc[2]!= payload[length-2] || crc[1]!= payload[length-3] || crc[0]!= payload[length-4])
-                       {
-                           RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_wep_decrypt23a:icv error crc[3](%x)!= payload[length-1](%x) || crc[2](%x)!= payload[length-2](%x) || crc[1](%x)!= payload[length-3](%x) || crc[0](%x)!= payload[length-4](%x)\n",
-                                               crc[3], payload[length-1], crc[2], payload[length-2], crc[1], payload[length-3], crc[0], payload[length-4]));
-                               res = _FAIL;
-                       }
-               } else {
-                       RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt23a: stainfo == NULL!!!\n"));
-                       res = _FAIL;
-               }
+       pnl = (u16)(dot11txpn.val);
+       pnh = (u32)(dot11txpn.val>>16);
+
+       phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh);
+       phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl);
+
+       /* 4 decrypt payload include icv */
+       arcfour_init(&mycontext, rc4key, 16);
+       arcfour_encrypt(&mycontext, payload, payload, length);
+
+       actual_crc = le32_to_cpu(getcrc32(payload, length - 4));
+       expected_crc = le32_to_cpu(get_unaligned_le32(&payload[length - 4]));
+
+       if (actual_crc != expected_crc) {
+               RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
+                        "%s:icv CRC mismatch: "
+                        "actual: %08x, expected: %08x\n",
+                        __func__, actual_crc, expected_crc);
+               res = _FAIL;
        }
+
 exit:
        return res;
 }
@@ -829,7 +837,7 @@ static void xor_128(u8 *a, u8 *b, u8 *out)
 {
        int i;
 
-       for (i = 0;i<16; i++)
+       for (i = 0; i < 16; i++)
                out[i] = a[i] ^ b[i];
 }
 
@@ -850,8 +858,7 @@ static void next_key(u8 *key, int round)
 {
        u8 rcon;
        u8 sbox_key[4];
-       u8 rcon_table[12] =
-       {
+       u8 rcon_table[12] = {
                0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
                0x1b, 0x36, 0x36, 0x36
        };
@@ -876,10 +883,8 @@ static void byte_sub(u8 *in, u8 *out)
 {
        int i;
 
-       for (i = 0; i< 16; i++) {
+       for (i = 0; i < 16; i++)
                out[i] = sbox(in[i]);
-       }
-
 }
 
 static void shift_row(u8 *in, u8 *out)
@@ -916,19 +921,19 @@ static void mix_column(u8 *in, u8 *out)
        u8 temp[4];
        u8 tempb[4];
 
-       for (i = 0 ; i<4; i++) {
+       for (i = 0; i < 4; i++) {
                if ((in[i] & 0x80) == 0x80)
-                   add1b[i] = 0x1b;
+                       add1b[i] = 0x1b;
                else
-                   add1b[i] = 0x00;
+                       add1b[i] = 0x00;
        }
 
-       swap_halfs[0] = in[2];    /* Swap halfs */
+       swap_halfs[0] = in[2]; /* Swap halfs */
        swap_halfs[1] = in[3];
        swap_halfs[2] = in[0];
        swap_halfs[3] = in[1];
 
-       rotl[0] = in[3];        /* Rotate left 8 bits */
+       rotl[0] = in[3]; /* Rotate left 8 bits */
        rotl[1] = in[0];
        rotl[2] = in[1];
        rotl[3] = in[2];
@@ -938,11 +943,10 @@ static void mix_column(u8 *in, u8 *out)
        andf7[2] = in[2] & 0x7f;
        andf7[3] = in[3] & 0x7f;
 
-       for (i = 3; i>0; i--) { /* logical shift left 1 bit */
+       for (i = 3; i > 0; i--) { /* logical shift left 1 bit */
                andf7[i] = andf7[i] << 1;
-               if ((andf7[i-1] & 0x80) == 0x80) {
-                   andf7[i] = (andf7[i] | 0x01);
-               }
+               if ((andf7[i - 1] & 0x80) == 0x80)
+                       andf7[i] = (andf7[i] | 0x01);
        }
        andf7[0] = andf7[0] << 1;
        andf7[0] = andf7[0] & 0xfe;
@@ -951,7 +955,7 @@ static void mix_column(u8 *in, u8 *out)
 
        xor_32(in, add1bf7, rotr);
 
-       temp[0] = rotr[0];         /* Rotate right 8 bits */
+       temp[0] = rotr[0]; /* Rotate right 8 bits */
        rotr[0] = rotr[1];
        rotr[1] = rotr[2];
        rotr[2] = rotr[3];
@@ -971,25 +975,26 @@ static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext)
        u8 intermediateb[16];
        u8 round_key[16];
 
-       for (i = 0; i<16; i++) round_key[i] = key[i];
+       for (i = 0; i < 16; i++)
+               round_key[i] = key[i];
 
        for (round = 0; round < 11; round++) {
                if (round == 0) {
-                   xor_128(round_key, data, ciphertext);
-                   next_key(round_key, round);
+                       xor_128(round_key, data, ciphertext);
+                       next_key(round_key, round);
                } else if (round == 10) {
-                   byte_sub(ciphertext, intermediatea);
-                   shift_row(intermediatea, intermediateb);
-                   xor_128(intermediateb, round_key, ciphertext);
+                       byte_sub(ciphertext, intermediatea);
+                       shift_row(intermediatea, intermediateb);
+                       xor_128(intermediateb, round_key, ciphertext);
                } else { /* 1 - 9 */
-                   byte_sub(ciphertext, intermediatea);
-                   shift_row(intermediatea, intermediateb);
-                   mix_column(&intermediateb[0], &intermediatea[0]);
-                   mix_column(&intermediateb[4], &intermediatea[4]);
-                   mix_column(&intermediateb[8], &intermediatea[8]);
-                   mix_column(&intermediateb[12], &intermediatea[12]);
-                   xor_128(intermediatea, round_key, ciphertext);
-                   next_key(round_key, round);
+                       byte_sub(ciphertext, intermediatea);
+                       shift_row(intermediatea, intermediateb);
+                       mix_column(&intermediateb[0], &intermediatea[0]);
+                       mix_column(&intermediateb[4], &intermediatea[4]);
+                       mix_column(&intermediateb[8], &intermediatea[8]);
+                       mix_column(&intermediateb[12], &intermediatea[12]);
+                       xor_128(intermediatea, round_key, ciphertext);
+                       next_key(round_key, round);
                }
        }
 
@@ -1006,9 +1011,9 @@ static void construct_mic_iv(u8 *mic_iv, int qc_exists, int a4_exists, u8 *mpdu,
 
        mic_iv[0] = 0x59;
        if (qc_exists && a4_exists)
-               mic_iv[1] = mpdu[30] & 0x0f;    /* QoS_TC           */
+               mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC        */
        if (qc_exists && !a4_exists)
-               mic_iv[1] = mpdu[24] & 0x0f;   /* mute bits 7-4    */
+               mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */
        if (!qc_exists)
                mic_iv[1] = 0x00;
        for (i = 2; i < 8; i++)
@@ -1028,15 +1033,15 @@ static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu)
 {
        mic_header1[0] = (u8)((header_length - 2) / 256);
        mic_header1[1] = (u8)((header_length - 2) % 256);
-       mic_header1[2] = mpdu[0] & 0xcf;    /* Mute CF poll & CF ack bits */
-       mic_header1[3] = mpdu[1] & 0xc7;    /* Mute retry, more data and pwr mgt bits */
-       mic_header1[4] = mpdu[4];       /* A1 */
+       mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */
+       mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */
+       mic_header1[4] = mpdu[4]; /* A1 */
        mic_header1[5] = mpdu[5];
        mic_header1[6] = mpdu[6];
        mic_header1[7] = mpdu[7];
        mic_header1[8] = mpdu[8];
        mic_header1[9] = mpdu[9];
-       mic_header1[10] = mpdu[10];     /* A2 */
+       mic_header1[10] = mpdu[10]; /* A2 */
        mic_header1[11] = mpdu[11];
        mic_header1[12] = mpdu[12];
        mic_header1[13] = mpdu[13];
@@ -1046,7 +1051,7 @@ static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu)
 }
 
 /************************************************/
-       /* construct_mic_header2()                      */
+/* construct_mic_header2()                      */
 /* Builds the last MIC header block from        */
 /* header fields.                               */
 /************************************************/
@@ -1055,9 +1060,10 @@ static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists,
 {
        int i;
 
-       for (i = 0; i<16; i++) mic_header2[i]= 0x00;
+       for (i = 0; i < 16; i++)
+               mic_header2[i] = 0x00;
 
-       mic_header2[0] = mpdu[16];    /* A3 */
+       mic_header2[0] = mpdu[16]; /* A3 */
        mic_header2[1] = mpdu[17];
        mic_header2[2] = mpdu[18];
        mic_header2[3] = mpdu[19];
@@ -1068,8 +1074,8 @@ static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists,
        mic_header2[7] = 0x00; /* mpdu[23]; */
 
        if (!qc_exists && a4_exists) {
-               for (i = 0;i<6;i++) mic_header2[8+i] = mpdu[24+i];   /* A4 */
-
+               for (i = 0; i < 6; i++)
+                       mic_header2[8+i] = mpdu[24+i]; /* A4 */
        }
 
        if (qc_exists && !a4_exists) {
@@ -1078,7 +1084,8 @@ static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists,
        }
 
        if (qc_exists && a4_exists) {
-               for (i = 0;i<6;i++) mic_header2[8+i] = mpdu[24+i];   /* A4 */
+               for (i = 0; i < 6; i++)
+                       mic_header2[8+i] = mpdu[24+i]; /* A4 */
 
                mic_header2[14] = mpdu[30] & 0x0f;
                mic_header2[15] = mpdu[31] & 0x00;
@@ -1096,19 +1103,21 @@ static void construct_ctr_preload(u8 *ctr_preload, int a4_exists, int qc_exists,
 {
        int i = 0;
 
-       for (i = 0; i<16; i++) ctr_preload[i] = 0x00;
+       for (i = 0; i < 16; i++)
+               ctr_preload[i] = 0x00;
+
        i = 0;
 
-       ctr_preload[0] = 0x01;                                  /* flag */
+       ctr_preload[0] = 0x01; /* flag */
        if (qc_exists && a4_exists)
-               ctr_preload[1] = mpdu[30] & 0x0f;   /* QoC_Control */
+               ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */
        if (qc_exists && !a4_exists)
                ctr_preload[1] = mpdu[24] & 0x0f;
 
        for (i = 2; i < 8; i++)
-               ctr_preload[i] = mpdu[i + 8];                       /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
+               ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
        for (i = 8; i < 14; i++)
-               ctr_preload[i] =    pn_vector[13 - i];          /* ctr_preload[8:13] = PN[5:0] */
+               ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */
        ctr_preload[14] =  (unsigned char) (c / 256); /* Ctr */
        ctr_preload[15] =  (unsigned char) (c % 256);
 
@@ -1128,8 +1137,8 @@ static void bitwise_xor(u8 *ina, u8 *inb, u8 *out)
 
 static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
 {
-       uint    qc_exists, a4_exists, i, j, payload_remainder,
-               num_blocks, payload_index;
+       uint qc_exists, a4_exists, i, j, payload_remainder,
+            num_blocks, payload_index;
        u8 pn_vector[6];
        u8 mic_iv[16];
        u8 mic_header1[16];
@@ -1177,12 +1186,12 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
        } else {
                qc_exists = 0;
        }
-       pn_vector[0]= pframe[hdrlen];
-       pn_vector[1]= pframe[hdrlen+1];
-       pn_vector[2]= pframe[hdrlen+4];
-       pn_vector[3]= pframe[hdrlen+5];
-       pn_vector[4]= pframe[hdrlen+6];
-       pn_vector[5]= pframe[hdrlen+7];
+       pn_vector[0] = pframe[hdrlen];
+       pn_vector[1] = pframe[hdrlen + 1];
+       pn_vector[2] = pframe[hdrlen + 4];
+       pn_vector[3] = pframe[hdrlen + 5];
+       pn_vector[4] = pframe[hdrlen + 6];
+       pn_vector[5] = pframe[hdrlen + 7];
 
        construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector);
 
@@ -1193,7 +1202,7 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
        num_blocks = plen / 16;
 
        /* Find start of payload */
-       payload_index = (hdrlen + 8);
+       payload_index = hdrlen + 8;
 
        /* Calculate MIC */
        aes128k128d(key, mic_iv, aes_out);
@@ -1224,12 +1233,12 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
 
        /* Insert MIC into payload */
        for (j = 0; j < 8; j++)
-               pframe[payload_index+j] = mic[j];
+               pframe[payload_index + j] = mic[j];
 
        payload_index = hdrlen + 8;
        for (i = 0; i < num_blocks; i++) {
                construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
-                                     pframe, pn_vector, i+1);
+                                     pframe, pn_vector, i + 1);
                aes128k128d(key, ctr_preload, aes_out);
                bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
                for (j = 0; j < 16; j++)
@@ -1241,15 +1250,15 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
                 * encrypt it and copy the unpadded part back
                 */
                construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe,
-                                     pn_vector, num_blocks+1);
+                                     pn_vector, num_blocks + 1);
 
                for (j = 0; j < 16; j++)
                        padded_buffer[j] = 0x00;
                for (j = 0; j < payload_remainder; j++)
-                       padded_buffer[j] = pframe[payload_index+j];
+                       padded_buffer[j] = pframe[payload_index + j];
                aes128k128d(key, ctr_preload, aes_out);
                bitwise_xor(aes_out, padded_buffer, chain_buffer);
-               for (j = 0; j < payload_remainder;j++)
+               for (j = 0; j < payload_remainder; j++)
                        pframe[payload_index++] = chain_buffer[j];
        }
 
@@ -1260,11 +1269,11 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
        for (j = 0; j < 16; j++)
                padded_buffer[j] = 0x00;
        for (j = 0; j < 8; j++)
-               padded_buffer[j] = pframe[j+hdrlen+8+plen];
+               padded_buffer[j] = pframe[j + hdrlen + 8 + plen];
 
        aes128k128d(key, ctr_preload, aes_out);
        bitwise_xor(aes_out, padded_buffer, chain_buffer);
-       for (j = 0; j < 8;j++)
+       for (j = 0; j < 8; j++)
                pframe[payload_index++] = chain_buffer[j];
 
        return _SUCCESS;
@@ -1272,11 +1281,11 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
 
 int rtw_aes_encrypt23a(struct rtw_adapter *padapter,
                       struct xmit_frame *pxmitframe)
-{      /*  exclude ICV */
+{      /* exclude ICV */
        /* Intermediate Buffers */
        int curfragnum, length;
        u32 prwskeylen;
-       u8 *pframe, *prwskey;   /*  *payload,*iv */
+       u8 *pframe, *prwskey;
        u8 hw_hdr_offset = 0;
        struct sta_info *stainfo;
        struct pkt_attrib *pattrib = &pxmitframe->attrib;
@@ -1304,18 +1313,18 @@ int rtw_aes_encrypt23a(struct rtw_adapter *padapter,
 
        if (!stainfo) {
                RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
-                        ("rtw_aes_encrypt23a: stainfo == NULL!!!\n"));
+                        "%s: stainfo == NULL!!!\n", __func__);
                DBG_8723A("%s, psta == NUL\n", __func__);
                res = _FAIL;
                goto out;
        }
-       if (!(stainfo->state &_FW_LINKED)) {
+       if (!(stainfo->state & _FW_LINKED)) {
                DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n",
                          __func__, stainfo->state);
                return _FAIL;
        }
        RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
-                ("rtw_aes_encrypt23a: stainfo!= NULL!!!\n"));
+                "%s: stainfo!= NULL!!!\n", __func__);
 
        if (is_multicast_ether_addr(pattrib->ra))
                prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
@@ -1345,12 +1354,11 @@ out:
        return res;
 }
 
-static int aes_decipher(u8 *key, uint  hdrlen,
-                       u8 *pframe, uint plen)
+static int aes_decipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
 {
-       static u8       message[MAX_MSG_SIZE];
-       uint    qc_exists, a4_exists, i, j, payload_remainder,
-                       num_blocks, payload_index;
+       static u8 message[MAX_MSG_SIZE];
+       uint qc_exists, a4_exists, i, j, payload_remainder,
+            num_blocks, payload_index;
        int res = _SUCCESS;
        u8 pn_vector[6];
        u8 mic_iv[16];
@@ -1375,16 +1383,16 @@ static int aes_decipher(u8 *key, uint   hdrlen,
 
        /* start to decrypt the payload */
 
-       num_blocks = (plen-8) / 16; /* plen including llc, payload_length and mic) */
+       num_blocks = (plen - 8) / 16; /* plen including llc, payload_length and mic) */
 
-       payload_remainder = (plen-8) % 16;
+       payload_remainder = (plen - 8) % 16;
 
        pn_vector[0]  = pframe[hdrlen];
-       pn_vector[1]  = pframe[hdrlen+1];
-       pn_vector[2]  = pframe[hdrlen+4];
-       pn_vector[3]  = pframe[hdrlen+5];
-       pn_vector[4]  = pframe[hdrlen+6];
-       pn_vector[5]  = pframe[hdrlen+7];
+       pn_vector[1]  = pframe[hdrlen + 1];
+       pn_vector[2]  = pframe[hdrlen + 4];
+       pn_vector[3]  = pframe[hdrlen + 5];
+       pn_vector[4]  = pframe[hdrlen + 6];
+       pn_vector[5]  = pframe[hdrlen + 7];
 
        if ((hdrlen == sizeof(struct ieee80211_hdr_3addr) ||
            (hdrlen == sizeof(struct ieee80211_qos_hdr))))
@@ -1413,13 +1421,13 @@ static int aes_decipher(u8 *key, uint   hdrlen,
                qc_exists = 0;
        }
 
-       /*  now, decrypt pframe with hdrlen offset and plen long */
+       /* now, decrypt pframe with hdrlen offset and plen long */
 
        payload_index = hdrlen + 8; /*  8 is for extiv */
 
        for (i = 0; i < num_blocks; i++) {
                construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
-                                     pframe, pn_vector, i+1);
+                                     pframe, pn_vector, i + 1);
 
                aes128k128d(key, ctr_preload, aes_out);
                bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
@@ -1433,12 +1441,12 @@ static int aes_decipher(u8 *key, uint   hdrlen,
                 * encrypt it and copy the unpadded part back
                 */
                construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe,
-                                     pn_vector, num_blocks+1);
+                                     pn_vector, num_blocks + 1);
 
                for (j = 0; j < 16; j++)
                        padded_buffer[j] = 0x00;
                for (j = 0; j < payload_remainder; j++)
-                       padded_buffer[j] = pframe[payload_index+j];
+                       padded_buffer[j] = pframe[payload_index + j];
                aes128k128d(key, ctr_preload, aes_out);
                bitwise_xor(aes_out, padded_buffer, chain_buffer);
                for (j = 0; j < payload_remainder; j++)
@@ -1446,27 +1454,27 @@ static int aes_decipher(u8 *key, uint   hdrlen,
        }
 
        /* start to calculate the mic */
-       if ((hdrlen +plen+8) <= MAX_MSG_SIZE)
-               memcpy(message, pframe, (hdrlen+plen+8)); /* 8 is for ext iv len */
+       if ((hdrlen + plen + 8) <= MAX_MSG_SIZE)
+               memcpy(message, pframe, (hdrlen + plen + 8)); /* 8 is for ext iv len */
 
        pn_vector[0] = pframe[hdrlen];
-       pn_vector[1] = pframe[hdrlen+1];
-       pn_vector[2] = pframe[hdrlen+4];
-       pn_vector[3] = pframe[hdrlen+5];
-       pn_vector[4] = pframe[hdrlen+6];
-       pn_vector[5] = pframe[hdrlen+7];
+       pn_vector[1] = pframe[hdrlen + 1];
+       pn_vector[2] = pframe[hdrlen + 4];
+       pn_vector[3] = pframe[hdrlen + 5];
+       pn_vector[4] = pframe[hdrlen + 6];
+       pn_vector[5] = pframe[hdrlen + 7];
 
        construct_mic_iv(mic_iv, qc_exists, a4_exists, message,
-                        plen-8, pn_vector);
+                        plen - 8, pn_vector);
 
        construct_mic_header1(mic_header1, hdrlen, message);
        construct_mic_header2(mic_header2, message, a4_exists, qc_exists);
 
-       payload_remainder = (plen-8) % 16;
-       num_blocks = (plen-8) / 16;
+       payload_remainder = (plen - 8) % 16;
+       num_blocks = (plen - 8) / 16;
 
        /* Find start of payload */
-       payload_index = (hdrlen + 8);
+       payload_index = hdrlen + 8;
 
        /* Calculate MIC */
        aes128k128d(key, mic_iv, aes_out);
@@ -1487,7 +1495,7 @@ static int aes_decipher(u8 *key, uint     hdrlen,
                for (j = 0; j < 16; j++)
                        padded_buffer[j] = 0x00;
                for (j = 0; j < payload_remainder; j++)
-                   padded_buffer[j] = message[payload_index++];
+                       padded_buffer[j] = message[payload_index++];
                bitwise_xor(aes_out, padded_buffer, chain_buffer);
                aes128k128d(key, chain_buffer, aes_out);
        }
@@ -1497,12 +1505,12 @@ static int aes_decipher(u8 *key, uint   hdrlen,
 
        /* Insert MIC into payload */
        for (j = 0; j < 8; j++)
-               message[payload_index+j] = mic[j];
+               message[payload_index + j] = mic[j];
 
        payload_index = hdrlen + 8;
-       for (i = 0; i< num_blocks; i++) {
+       for (i = 0; i < num_blocks; i++) {
                construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
-                                     message, pn_vector, i+1);
+                                     message, pn_vector, i + 1);
                aes128k128d(key, ctr_preload, aes_out);
                bitwise_xor(aes_out, &message[payload_index], chain_buffer);
                for (j = 0; j < 16; j++)
@@ -1514,12 +1522,12 @@ static int aes_decipher(u8 *key, uint   hdrlen,
                 * encrypt it and copy the unpadded part back
                 */
                construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
-                                     message, pn_vector, num_blocks+1);
+                                     message, pn_vector, num_blocks + 1);
 
                for (j = 0; j < 16; j++)
-                        padded_buffer[j] = 0x00;
+                       padded_buffer[j] = 0x00;
                for (j = 0; j < payload_remainder; j++)
-                       padded_buffer[j] = message[payload_index+j];
+                       padded_buffer[j] = message[payload_index + j];
                aes128k128d(key, ctr_preload, aes_out);
                bitwise_xor(aes_out, padded_buffer, chain_buffer);
                for (j = 0; j < payload_remainder; j++)
@@ -1533,7 +1541,7 @@ static int aes_decipher(u8 *key, uint     hdrlen,
        for (j = 0; j < 16; j++)
                padded_buffer[j] = 0x00;
        for (j = 0; j < 8; j++)
-               padded_buffer[j] = message[j+hdrlen+8+plen-8];
+               padded_buffer[j] = message[j + hdrlen + 8 + plen - 8];
 
        aes128k128d(key, ctr_preload, aes_out);
        bitwise_xor(aes_out, padded_buffer, chain_buffer);
@@ -1542,12 +1550,16 @@ static int aes_decipher(u8 *key, uint   hdrlen,
 
        /* compare the mic */
        for (i = 0; i < 8; i++) {
-               if (pframe[hdrlen+8+plen-8+i] != message[hdrlen+8+plen-8+i]) {
+               if (pframe[hdrlen + 8 + plen - 8 + i] != message[hdrlen + 8 + plen - 8 + i]) {
                        RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
-                                ("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n",
-                                i, pframe[hdrlen+8+plen-8+i], message[hdrlen+8+plen-8+i]));
-                       DBG_8723A("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n",
-                                 i, pframe[hdrlen+8+plen-8+i], message[hdrlen+8+plen-8+i]);
+                                "%s:mic check error mic[%d]: pframe(%x) != message(%x)\n",
+                                __func__, i,
+                                pframe[hdrlen + 8 + plen - 8 + i],
+                                message[hdrlen + 8 + plen - 8 + i]);
+                       DBG_8723A("%s:mic check error mic[%d]: pframe(%x) != message(%x)\n",
+                                 __func__, i,
+                                 pframe[hdrlen + 8 + plen - 8 + i],
+                                 message[hdrlen + 8 + plen - 8 + i]);
                        res = _FAIL;
                }
        }
@@ -1562,7 +1574,7 @@ int rtw_aes_decrypt23a(struct rtw_adapter *padapter,
        struct security_priv *psecuritypriv = &padapter->securitypriv;
        struct sk_buff *skb = precvframe->pkt;
        int length;
-       u8 *pframe, *prwskey;   /*  *payload,*iv */
+       u8 *pframe, *prwskey;
        int res = _SUCCESS;
 
        pframe = skb->data;
@@ -1573,17 +1585,18 @@ int rtw_aes_decrypt23a(struct rtw_adapter *padapter,
        stainfo = rtw_get_stainfo23a(&padapter->stapriv, &prxattrib->ta[0]);
        if (!stainfo) {
                RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
-                        ("rtw_aes_encrypt23a: stainfo == NULL!!!\n"));
+                        "%s: stainfo == NULL!!!\n", __func__);
                res = _FAIL;
                goto exit;
        }
 
        RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
-                ("rtw_aes_decrypt23a: stainfo!= NULL!!!\n"));
+                "%s: stainfo!= NULL!!!\n", __func__);
 
        if (is_multicast_ether_addr(prxattrib->ra)) {
-               /* in concurrent we should use sw decrypt in group key,
-                  so we remove this message */
+               /* in concurrent we should use sw decrypt in
+                * group key, so we remove this message
+                */
                if (!psecuritypriv->binstallGrpkey) {
                        res = _FAIL;
                        DBG_8723A("%s:rx bc/mc packets, but didn't install "
@@ -1613,9 +1626,10 @@ void rtw_use_tkipkey_handler23a(void *FunctionContext)
 {
        struct rtw_adapter *padapter = (struct rtw_adapter *)FunctionContext;
 
-       RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("^^^rtw_use_tkipkey_handler23a ^^^\n"));
+       RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
+                "^^^%s ^^^\n", __func__);
        padapter->securitypriv.busetkipkey = 1;
        RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
-                ("^^^rtw_use_tkipkey_handler23a padapter->securitypriv.busetkipkey =%d^^^\n",
-                padapter->securitypriv.busetkipkey));
+                "^^^%s padapter->securitypriv.busetkipkey =%d^^^\n",
+                __func__, padapter->securitypriv.busetkipkey);
 }
index d17998da860030d1bbce436a605ab0b33d8b29c7..b06bff74502ab8ec8e6c7303e51f95c7172b149a 100644 (file)
@@ -136,10 +136,10 @@ rtw_alloc_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr, gfp_t gfp)
        index = wifi_mac_hash(hwaddr);
 
        RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
-                ("rtw_alloc_stainfo23a: index  = %x", index));
+                "rtw_alloc_stainfo23a: index  = %x\n", index);
        if (index >= NUM_STA) {
                RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
-                        ("ERROR => rtw_alloc_stainfo23a: index >= NUM_STA"));
+                        "ERROR => rtw_alloc_stainfo23a: index >= NUM_STA\n");
                psta = NULL;
                goto exit;
        }
@@ -160,8 +160,8 @@ rtw_alloc_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr, gfp_t gfp)
                        &wRxSeqInitialValue, 2);
 
        RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
-                ("alloc number_%d stainfo  with hwaddr = %pM\n",
-                pstapriv->asoc_sta_count, hwaddr));
+                "alloc number_%d stainfo  with hwaddr = %pM\n",
+                pstapriv->asoc_sta_count, hwaddr);
 
        init_addba_retry_timer23a(psta);
 
@@ -249,10 +249,8 @@ int rtw_free_stainfo23a(struct rtw_adapter *padapter, struct sta_info *psta)
 
        list_del_init(&psta->hash_list);
        RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
-               ("\n free number_%d stainfo  with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
-                       pstapriv->asoc_sta_count, psta->hwaddr[0],
-                       psta->hwaddr[1], psta->hwaddr[2], psta->hwaddr[3],
-                       psta->hwaddr[4], psta->hwaddr[5]));
+                "free number_%d stainfo  with hwaddr = %pM\n",
+                pstapriv->asoc_sta_count, psta->hwaddr);
        pstapriv->asoc_sta_count--;
 
        /*  re-init sta_info; 20061114  will be init in alloc_stainfo */
@@ -397,7 +395,7 @@ int rtw_init_bcmc_stainfo23a(struct rtw_adapter *padapter)
        if (psta == NULL) {
                res = _FAIL;
                RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
-                        ("rtw_alloc_stainfo23a fail"));
+                        "rtw_alloc_stainfo23a fail\n");
                return res;
        }
        /*  default broadcast & multicast use macid 1 */
index 69d9e0f17fd8390544409fd2a1dfa3ed9bbed2aa..5280338aa387639780d512abc30cb2b76cb08da8 100644 (file)
@@ -876,9 +876,9 @@ int rtw_check_bcn_info23a(struct rtw_adapter *Adapter,
        }
 
        if (!ether_addr_equal(cur_network->network.MacAddress, mgmt->bssid)) {
-               DBG_8723A("%s: linked but recv other bssid bcn"
-                         MAC_FMT MAC_FMT "\n", __func__, MAC_ARG(mgmt->bssid),
-                         MAC_ARG(cur_network->network.MacAddress));
+               DBG_8723A("%s: linked but recv other bssid bcn %pM %pM\n",
+                         __func__, mgmt->bssid,
+                         cur_network->network.MacAddress);
                return _FAIL;
        }
 
@@ -926,10 +926,9 @@ int rtw_check_bcn_info23a(struct rtw_adapter *Adapter,
        }
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                ("%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d "
-                 "cur_network->network.Ssid.Ssid:%s len:%d\n", __func__,
-                 ssid, ssid_len, cur_network->network.Ssid.ssid,
-                 cur_network->network.Ssid.ssid_len));
+                "%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d cur_network->network.Ssid.Ssid:%s len:%d\n",
+                __func__, ssid, ssid_len, cur_network->network.Ssid.ssid,
+                cur_network->network.Ssid.ssid_len);
 
        if (ssid_len != cur_network->network.Ssid.ssid_len || ssid_len > 32 ||
            (ssid_len &&
@@ -947,8 +946,8 @@ int rtw_check_bcn_info23a(struct rtw_adapter *Adapter,
                privacy = 0;
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                ("%s(): cur_network->network.Privacy is %d, bssid.Privacy "
-                 "is %d\n", __func__, cur_network->network.Privacy, privacy));
+                "%s(): cur_network->network.Privacy is %d, bssid.Privacy is %d\n",
+                __func__, cur_network->network.Privacy, privacy);
        if (cur_network->network.Privacy != privacy) {
                DBG_8723A("%s(), privacy is not match return FAIL\n", __func__);
                goto _mismatch;
@@ -962,10 +961,9 @@ int rtw_check_bcn_info23a(struct rtw_adapter *Adapter,
                                                 &pairwise_cipher, &is_8021x);
                        if (r == _SUCCESS)
                                RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                                        ("%s pnetwork->pairwise_cipher: %d, "
-                                         "pnetwork->group_cipher: %d, is_802x "
-                                         ": %d\n", __func__, pairwise_cipher,
-                                         group_cipher, is_8021x));
+                                        "%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher: %d, is_802x : %d\n",
+                                        __func__, pairwise_cipher,
+                                        group_cipher, is_8021x);
                        }
        } else {
                p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
@@ -977,10 +975,9 @@ int rtw_check_bcn_info23a(struct rtw_adapter *Adapter,
                                                &pairwise_cipher, &is_8021x);
                        if (r == _SUCCESS)
                                RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-                                        ("%s pnetwork->pairwise_cipher: %d, "
-                                         "group_cipher is %d, is_8021x is "
-                                         "%d\n", __func__, pairwise_cipher,
-                                         group_cipher, is_8021x));
+                                        "%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n",
+                                        __func__, pairwise_cipher,
+                                        group_cipher, is_8021x);
                } else {
                        if (privacy)
                                crypto = ENCRYP_PROTOCOL_WEP;
@@ -996,8 +993,8 @@ int rtw_check_bcn_info23a(struct rtw_adapter *Adapter,
 
        if (crypto == ENCRYP_PROTOCOL_WPA || crypto == ENCRYP_PROTOCOL_WPA2) {
                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-                        ("%s cur_network->group_cipher is %d: %d\n", __func__,
-                         cur_network->BcnInfo.group_cipher, group_cipher));
+                        "%s cur_network->group_cipher is %d: %d\n", __func__,
+                        cur_network->BcnInfo.group_cipher, group_cipher);
                if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher ||
                    group_cipher != cur_network->BcnInfo.group_cipher) {
                        DBG_8723A("%s pairwise_cipher(%x:%x) or group_cipher "
index 1c82dffcf59610d0b78cf6b9f9882a7c15471f74..a4b6bb6c79a969b8483ee3154ef54228e7a4fbf9 100644 (file)
@@ -463,9 +463,7 @@ static int update_attrib(struct rtw_adapter *padapter,
                                        /*  67 : UDP BOOTP server */
                                        RT_TRACE(_module_rtl871x_xmit_c_,
                                                 _drv_err_,
-                                                ("======================"
-                                                 "update_attrib: get DHCP "
-                                                 "Packet\n"));
+                                                "======================update_attrib: get DHCP Packet\n");
                                        pattrib->dhcp_pkt = 1;
                                }
                        }
@@ -493,8 +491,8 @@ static int update_attrib(struct rtw_adapter *padapter,
                psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
                if (psta == NULL) { /*  if we cannot get psta => drrp the pkt */
                        RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_,
-                                ("\nupdate_attrib => get sta_info fail, ra:"
-                                 MAC_FMT"\n", MAC_ARG(pattrib->ra)));
+                                "update_attrib => get sta_info fail, ra:%pM\n",
+                                pattrib->ra);
                        res = _FAIL;
                        goto exit;
                } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) &&
@@ -511,8 +509,8 @@ static int update_attrib(struct rtw_adapter *padapter,
        } else {
                /*  if we cannot get psta => drop the pkt */
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_,
-                        ("\nupdate_attrib => get sta_info fail, ra:" MAC_FMT
-                         "\n", MAC_ARG(pattrib->ra)));
+                        "update_attrib => get sta_info fail, ra:%pM\n",
+                        pattrib->ra);
                res = _FAIL;
                goto exit;
        }
@@ -544,16 +542,15 @@ static int update_attrib(struct rtw_adapter *padapter,
 
        if (psta->ieee8021x_blocked == true) {
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                        ("\n psta->ieee8021x_blocked == true\n"));
+                        "psta->ieee8021x_blocked == true\n");
 
                pattrib->encrypt = 0;
 
                if ((pattrib->ether_type != ETH_P_PAE) &&
                    !check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
                        RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                                ("\npsta->ieee8021x_blocked == true,  "
-                                 "pattrib->ether_type(%.4x) != 0x888e\n",
-                                 pattrib->ether_type));
+                                "psta->ieee8021x_blocked == true,  pattrib->ether_type(%.4x) != 0x888e\n",
+                                pattrib->ether_type);
                        res = _FAIL;
                        goto exit;
                }
@@ -594,9 +591,8 @@ static int update_attrib(struct rtw_adapter *padapter,
 
                if (!padapter->securitypriv.busetkipkey) {
                        RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                                ("\npadapter->securitypriv.busetkip"
-                                 "key(%d) == false drop packet\n",
-                                 padapter->securitypriv.busetkipkey));
+                                "padapter->securitypriv.busetkipkey(%d) == false drop packet\n",
+                                padapter->securitypriv.busetkipkey);
                        res = _FAIL;
                        goto exit;
                }
@@ -604,8 +600,8 @@ static int update_attrib(struct rtw_adapter *padapter,
                break;
        case WLAN_CIPHER_SUITE_CCMP:
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
-                        ("pattrib->encrypt =%d (WLAN_CIPHER_SUITE_CCMP)\n",
-                         pattrib->encrypt));
+                        "pattrib->encrypt =%d (WLAN_CIPHER_SUITE_CCMP)\n",
+                        pattrib->encrypt);
                pattrib->iv_len = IEEE80211_CCMP_HDR_LEN;
                pattrib->icv_len = IEEE80211_CCMP_MIC_LEN;
                break;
@@ -617,17 +613,17 @@ static int update_attrib(struct rtw_adapter *padapter,
        }
 
        RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
-                ("update_attrib: encrypt =%d\n", pattrib->encrypt));
+                "update_attrib: encrypt =%d\n", pattrib->encrypt);
 
        if (pattrib->encrypt && !psecuritypriv->hw_decrypted) {
                pattrib->bswenc = true;
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                        ("update_attrib: encrypt =%d bswenc = true\n",
-                         pattrib->encrypt));
+                        "update_attrib: encrypt =%d bswenc = true\n",
+                        pattrib->encrypt);
        } else {
                pattrib->bswenc = false;
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
-                        ("update_attrib: bswenc = false\n"));
+                        "update_attrib: bswenc = false\n");
        }
        update_attrib_phy_info(pattrib, psta);
 
@@ -726,20 +722,18 @@ static int xmitframe_addmic(struct rtw_adapter *padapter,
                             curfragnum++) {
                                payload = PTR_ALIGN(payload, 4);
                                RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                                        ("=== curfragnum =%d, pframe = 0x%.2x, "
-                                         "0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x"
-                                         "%.2x, 0x%.2x, 0x%.2x,!!!\n",
-                                         curfragnum, *payload, *(payload + 1),
-                                         *(payload + 2), *(payload + 3),
-                                         *(payload + 4), *(payload + 5),
-                                         *(payload + 6), *(payload + 7)));
+                                        "=== curfragnum =%d, pframe = 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x,!!!\n",
+                                        curfragnum, *payload, *(payload + 1),
+                                        *(payload + 2), *(payload + 3),
+                                        *(payload + 4), *(payload + 5),
+                                        *(payload + 6), *(payload + 7));
 
                                payload = payload + pattrib->hdrlen +
                                        pattrib->iv_len;
                                RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                                        ("curfragnum =%d pattrib->hdrlen =%d "
-                                         "pattrib->iv_len =%d", curfragnum,
-                                         pattrib->hdrlen, pattrib->iv_len));
+                                        "curfragnum =%d pattrib->hdrlen =%d pattrib->iv_len =%d\n",
+                                        curfragnum,
+                                        pattrib->hdrlen, pattrib->iv_len);
                                if ((curfragnum + 1) == pattrib->nr_frags) {
                                        length = pattrib->last_txcmdsz -
                                                pattrib->hdrlen -
@@ -761,25 +755,21 @@ static int xmitframe_addmic(struct rtw_adapter *padapter,
                                                pattrib->icv_len;
                                        RT_TRACE(_module_rtl871x_xmit_c_,
                                                 _drv_err_,
-                                                ("curfragnum =%d length =%d "
-                                                 "pattrib->icv_len =%d",
-                                                 curfragnum, length,
-                                                 pattrib->icv_len));
+                                                "curfragnum =%d length =%d pattrib->icv_len =%d\n",
+                                                curfragnum, length,
+                                                pattrib->icv_len);
                                }
                        }
                        rtw_secgetmic23a(&micdata, &mic[0]);
                        RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                                ("xmitframe_addmic: before add mic code!!\n"));
+                                "xmitframe_addmic: before add mic code!!\n");
                        RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                                ("xmitframe_addmic: pattrib->last_txcmdsz ="
-                                 "%d!!!\n", pattrib->last_txcmdsz));
+                                "xmitframe_addmic: pattrib->last_txcmdsz =%d!!!\n",
+                                pattrib->last_txcmdsz);
                        RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                                ("xmitframe_addmic: mic[0]= 0x%.2x , mic[1]="
-                                 "0x%.2x , mic[2]= 0x%.2x , mic[3]= 0x%.2x\n"
-                                 "mic[4]= 0x%.2x , mic[5]= 0x%.2x , mic[6]= 0x%.2x "
-                                 ", mic[7]= 0x%.2x !!!!\n", mic[0], mic[1],
-                                 mic[2], mic[3], mic[4], mic[5], mic[6],
-                                 mic[7]));
+                                "xmitframe_addmic: mic[0]= 0x%.2x , mic[1]=0x%.2x , mic[2]= 0x%.2x , mic[3]= 0x%.2x\nmic[4]= 0x%.2x , mic[5]= 0x%.2x , mic[6]= 0x%.2x , mic[7]= 0x%.2x !!!!\n",
+                                mic[0], mic[1], mic[2], mic[3],
+                                mic[4], mic[5], mic[6], mic[7]);
                        /* add mic code  and add the mic code length
                           in last_txcmdsz */
 
@@ -787,25 +777,24 @@ static int xmitframe_addmic(struct rtw_adapter *padapter,
                        pattrib->last_txcmdsz += 8;
 
                        RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
-                                ("\n ======== last pkt ========\n"));
+                                "======== last pkt ========\n");
                        payload = payload - pattrib->last_txcmdsz + 8;
                        for (curfragnum = 0; curfragnum < pattrib->last_txcmdsz;
-                            curfragnum = curfragnum + 8)
+                            curfragnum = curfragnum + 8) {
                                RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
-                                        (" %.2x,  %.2x,  %.2x,  %.2x,  %.2x, "
-                                         " %.2x,  %.2x,  %.2x ",
-                                         *(payload + curfragnum),
-                                         *(payload + curfragnum + 1),
-                                         *(payload + curfragnum + 2),
-                                         *(payload + curfragnum + 3),
-                                         *(payload + curfragnum + 4),
-                                         *(payload + curfragnum + 5),
-                                         *(payload + curfragnum + 6),
-                                         *(payload + curfragnum + 7)));
-                       } else {
-                               RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                                        ("xmitframe_addmic: rtw_get_stainfo23a =="
-                                         "NULL!!!\n"));
+                                        "%.2x,  %.2x,  %.2x,  %.2x,  %.2x,  %.2x,  %.2x,  %.2x\n",
+                                        *(payload + curfragnum),
+                                        *(payload + curfragnum + 1),
+                                        *(payload + curfragnum + 2),
+                                        *(payload + curfragnum + 3),
+                                        *(payload + curfragnum + 4),
+                                        *(payload + curfragnum + 5),
+                                        *(payload + curfragnum + 6),
+                                        *(payload + curfragnum + 7));
+                       }
+               } else {
+                       RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
+                                "xmitframe_addmic: rtw_get_stainfo23a ==NULL!!!\n");
                }
        }
 
@@ -821,7 +810,7 @@ static int xmitframe_swencrypt(struct rtw_adapter *padapter,
        if (pattrib->bswenc) {
                /* DBG_8723A("start xmitframe_swencrypt\n"); */
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_,
-                        ("### xmitframe_swencrypt\n"));
+                        "### xmitframe_swencrypt\n");
                switch (pattrib->encrypt) {
                case WLAN_CIPHER_SUITE_WEP40:
                case WLAN_CIPHER_SUITE_WEP104:
@@ -839,7 +828,7 @@ static int xmitframe_swencrypt(struct rtw_adapter *padapter,
 
        } else {
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_,
-                        ("### xmitframe_hwencrypt\n"));
+                        "### xmitframe_hwencrypt\n");
        }
 
        return _SUCCESS;
@@ -916,7 +905,9 @@ static int rtw_make_wlanhdr(struct rtw_adapter *padapter, u8 *hdr,
                                qos_option = true;
                }
                else {
-                       RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("fw_state:%x is not allowed to xmit frame\n", get_fwstate(pmlmepriv)));
+                       RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
+                                "fw_state:%x is not allowed to xmit frame\n",
+                                get_fwstate(pmlmepriv));
                        res = _FAIL;
                        goto exit;
                }
@@ -1117,7 +1108,7 @@ int rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *skb,
 
        if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) {
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                        ("%s: rtw_make_wlanhdr fail; drop pkt\n", __func__));
+                        "%s: rtw_make_wlanhdr fail; drop pkt\n", __func__);
                res = _FAIL;
                goto exit;
        }
@@ -1172,11 +1163,10 @@ int rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *skb,
                        memcpy(pframe, pattrib->iv, pattrib->iv_len);
 
                        RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_,
-                                ("rtw_xmiaframe_coalesce23a: keyid =%d pattrib"
-                                 "->iv[3]=%.2x pframe =%.2x %.2x %.2x %.2x\n",
-                                 padapter->securitypriv.dot11PrivacyKeyIndex,
-                                 pattrib->iv[3], *pframe, *(pframe+1),
-                                 *(pframe+2), *(pframe+3)));
+                                "rtw_xmiaframe_coalesce23a: keyid =%d pattrib->iv[3]=%.2x pframe =%.2x %.2x %.2x %.2x\n",
+                                padapter->securitypriv.dot11PrivacyKeyIndex,
+                                pattrib->iv[3], *pframe, *(pframe+1),
+                                *(pframe+2), *(pframe+3));
                        pframe += pattrib->iv_len;
                        mpdu_len -= pattrib->iv_len;
                }
@@ -1223,8 +1213,8 @@ int rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *skb,
                        break;
                } else {
                        RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                                ("%s: There're still something in packet!\n",
-                                 __func__));
+                                "%s: There're still something in packet!\n",
+                                __func__);
                }
                hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
 
@@ -1234,7 +1224,7 @@ int rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *skb,
 
        if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) {
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                        ("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"));
+                        "xmitframe_addmic(padapter, pxmitframe) == _FAIL\n");
                DBG_8723A("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n");
                res = _FAIL;
                goto exit;
@@ -1462,8 +1452,8 @@ static struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)
 
        if (list_empty(&pfree_xmit_queue->queue)) {
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
-                        ("rtw_alloc_xmitframe:%d\n",
-                         pxmitpriv->free_xmitframe_cnt));
+                        "rtw_alloc_xmitframe:%d\n",
+                        pxmitpriv->free_xmitframe_cnt);
                pxframe =  NULL;
        } else {
                phead = get_list_head(pfree_xmit_queue);
@@ -1475,8 +1465,8 @@ static struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)
                list_del_init(&pxframe->list);
                pxmitpriv->free_xmitframe_cnt--;
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
-                        ("rtw_alloc_xmitframe():free_xmitframe_cnt =%d\n",
-                         pxmitpriv->free_xmitframe_cnt));
+                        "rtw_alloc_xmitframe():free_xmitframe_cnt =%d\n",
+                        pxmitpriv->free_xmitframe_cnt);
        }
 
        spin_unlock_bh(&pfree_xmit_queue->lock);
@@ -1495,7 +1485,9 @@ struct xmit_frame *rtw_alloc_xmitframe23a_ext(struct xmit_priv *pxmitpriv)
        spin_lock_bh(&queue->lock);
 
        if (list_empty(&queue->queue)) {
-               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe23a_ext:%d\n", pxmitpriv->free_xframe_ext_cnt));
+               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+                        "rtw_alloc_xmitframe23a_ext:%d\n",
+                        pxmitpriv->free_xframe_ext_cnt);
                pxframe =  NULL;
        } else {
                phead = get_list_head(queue);
@@ -1504,7 +1496,9 @@ struct xmit_frame *rtw_alloc_xmitframe23a_ext(struct xmit_priv *pxmitpriv)
 
                list_del_init(&pxframe->list);
                pxmitpriv->free_xframe_ext_cnt--;
-               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe23a_ext():free_xmitframe_cnt =%d\n", pxmitpriv->free_xframe_ext_cnt));
+               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+                        "rtw_alloc_xmitframe23a_ext():free_xmitframe_cnt =%d\n",
+                        pxmitpriv->free_xframe_ext_cnt);
        }
 
        spin_unlock_bh(&queue->lock);
@@ -1521,7 +1515,8 @@ s32 rtw_free_xmitframe23a(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitf
        struct sk_buff *pndis_pkt = NULL;
 
        if (pxmitframe == NULL) {
-               RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("====== rtw_free_xmitframe23a():pxmitframe == NULL!!!!!!!!!!\n"));
+               RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
+                        "====== rtw_free_xmitframe23a():pxmitframe == NULL!!!!!!!!!!\n");
                goto exit;
        }
 
@@ -1543,10 +1538,14 @@ s32 rtw_free_xmitframe23a(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitf
        list_add_tail(&pxmitframe->list, get_list_head(queue));
        if (pxmitframe->ext_tag == 0) {
                pxmitpriv->free_xmitframe_cnt++;
-               RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("rtw_free_xmitframe23a():free_xmitframe_cnt =%d\n", pxmitpriv->free_xmitframe_cnt));
+               RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_,
+                        "rtw_free_xmitframe23a():free_xmitframe_cnt =%d\n",
+                        pxmitpriv->free_xmitframe_cnt);
        } else if (pxmitframe->ext_tag == 1) {
                pxmitpriv->free_xframe_ext_cnt++;
-               RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("rtw_free_xmitframe23a():free_xframe_ext_cnt =%d\n", pxmitpriv->free_xframe_ext_cnt));
+               RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_,
+                        "rtw_free_xmitframe23a():free_xframe_ext_cnt =%d\n",
+                        pxmitpriv->free_xframe_ext_cnt);
        }
 
        spin_unlock_bh(&queue->lock);
@@ -1585,8 +1584,7 @@ int rtw_xmitframe_enqueue23a(struct rtw_adapter *padapter,
 {
        if (rtw_xmit23a_classifier(padapter, pxmitframe) == _FAIL) {
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                        ("rtw_xmitframe_enqueue23a: drop xmit pkt for "
-                         "classifier fail\n"));
+                        "rtw_xmitframe_enqueue23a: drop xmit pkt for classifier fail\n");
                return _FAIL;
        }
 
@@ -1675,26 +1673,30 @@ struct tx_servq *rtw_get_sta_pending23a(struct rtw_adapter *padapter, struct sta
        case 2:
                ptxservq = &psta->sta_xmitpriv.bk_q;
                *(ac) = 3;
-               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : BK\n"));
+               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+                        "rtw_get_sta_pending23a : BK\n");
                break;
        case 4:
        case 5:
                ptxservq = &psta->sta_xmitpriv.vi_q;
                *(ac) = 1;
-               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : VI\n"));
+               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+                        "rtw_get_sta_pending23a : VI\n");
                break;
        case 6:
        case 7:
                ptxservq = &psta->sta_xmitpriv.vo_q;
                *(ac) = 0;
-               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : VO\n"));
+               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+                        "rtw_get_sta_pending23a : VO\n");
                break;
        case 0:
        case 3:
        default:
                ptxservq = &psta->sta_xmitpriv.be_q;
                *(ac) = 2;
-               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : BE\n"));
+               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+                        "rtw_get_sta_pending23a : BE\n");
                break;
        }
        return ptxservq;
@@ -1725,7 +1727,7 @@ int rtw_xmit23a_classifier(struct rtw_adapter *padapter,
                res = _FAIL;
                DBG_8723A("rtw_xmit23a_classifier: psta == NULL\n");
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                        ("rtw_xmit23a_classifier: psta == NULL\n"));
+                        "rtw_xmit23a_classifier: psta == NULL\n");
                goto exit;
        }
        if (!(psta->state & _FW_LINKED)) {
@@ -1876,14 +1878,15 @@ int rtw_xmit23a(struct rtw_adapter *padapter, struct sk_buff *skb)
 
        if (pxmitframe == NULL) {
                RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
-                        ("rtw_xmit23a: no more pxmitframe\n"));
+                        "rtw_xmit23a: no more pxmitframe\n");
                return -1;
        }
 
        res = update_attrib(padapter, skb, &pxmitframe->attrib);
 
        if (res == _FAIL) {
-               RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit23a: update attrib fail\n"));
+               RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
+                        "rtw_xmit23a: update attrib fail\n");
                rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
                return -1;
        }
index 179a1ba03029690bd4ca66d54c49b028e6e3fb46..3f9ec9e00e1681fec049ece1c10782631f9a13c2 100644 (file)
@@ -23,9 +23,8 @@
 #define                DPK_DELTA_MAPPING_NUM   13
 #define                index_mapping_HP_NUM    15
 /* 091212 chiyokolin */
-static void
-odm_TXPowerTrackingCallback_ThermalMeter_92C(
-       struct rtw_adapter *Adapter)
+static void
+odm_TXPowerTrackingCallback_ThermalMeter_92C(struct rtw_adapter *Adapter)
 {
        struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
        struct dm_priv *pdmpriv = &pHalData->dmpriv;
@@ -35,7 +34,6 @@ odm_TXPowerTrackingCallback_ThermalMeter_92C(
        s8 OFDM_index[2], CCK_index = 0, OFDM_index_old[2] = {0};
        s8 CCK_index_old = 0;
        int i = 0;
-       bool is2T = IS_92C_SERIAL(pHalData->VersionID);
        u8 OFDM_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB*/
        u8 ThermalValue_HP_count = 0;
        u32 ThermalValue_HP = 0;
@@ -60,15 +58,15 @@ odm_TXPowerTrackingCallback_ThermalMeter_92C(
        rtl8723a_phy_ap_calibrate(Adapter, (ThermalValue -
                                  pHalData->EEPROMThermalMeter));
 
-       if (is2T)
+       if (pHalData->rf_type == RF_2T2R)
                rf = 2;
        else
                rf = 1;
 
        if (ThermalValue) {
                /* Query OFDM path A default setting     */
-               ele_D = PHY_QueryBBReg(Adapter, rOFDM0_XATxIQImbalance,
-                                      bMaskDWord)&bMaskOFDM_D;
+               ele_D = rtl8723au_read32(Adapter, rOFDM0_XATxIQImbalance) &
+                       bMaskOFDM_D;
                for (i = 0; i < OFDM_TABLE_SIZE_92C; i++) {
                        /* find the index */
                        if (ele_D == (OFDMSwingTable23A[i]&bMaskOFDM_D)) {
@@ -78,9 +76,10 @@ odm_TXPowerTrackingCallback_ThermalMeter_92C(
                }
 
                /* Query OFDM path B default setting  */
-               if (is2T) {
-                       ele_D = PHY_QueryBBReg(Adapter, rOFDM0_XBTxIQImbalance,
-                                              bMaskDWord)&bMaskOFDM_D;
+               if (pHalData->rf_type == RF_2T2R) {
+                       ele_D = rtl8723au_read32(Adapter,
+                                                rOFDM0_XBTxIQImbalance);
+                       ele_D &= bMaskOFDM_D;
                        for (i = 0; i < OFDM_TABLE_SIZE_92C; i++) {     /* find the index  */
                                if (ele_D == (OFDMSwingTable23A[i]&bMaskOFDM_D)) {
                                        OFDM_index_old[1] = (u8)i;
@@ -90,8 +89,7 @@ odm_TXPowerTrackingCallback_ThermalMeter_92C(
                }
 
                /* Query CCK default setting From 0xa24 */
-               TempCCk = PHY_QueryBBReg(Adapter, rCCK0_TxFilter2,
-                                        bMaskDWord)&bMaskCCK;
+               TempCCk = rtl8723au_read32(Adapter, rCCK0_TxFilter2) & bMaskCCK;
                for (i = 0 ; i < CCK_TABLE_SIZE ; i++) {
                        if (pdmpriv->bCCKinCH14) {
                                if (!memcmp(&TempCCk,
@@ -224,12 +222,13 @@ odm_TXPowerTrackingCallback_ThermalMeter_92C(
                        }
 
                        if (CCK_index > (CCK_TABLE_SIZE-1))
-                               CCK_index = (CCK_TABLE_SIZE-1);
+                               CCK_index = CCK_TABLE_SIZE-1;
                        else if (CCK_index < 0)
                                CCK_index = 0;
                }
 
-               if (pdmpriv->TxPowerTrackControl && (delta != 0 || delta_HP != 0)) {
+               if (pdmpriv->TxPowerTrackControl &&
+                   (delta != 0 || delta_HP != 0)) {
                        /* Adujst OFDM Ant_A according to IQK result */
                        ele_D = (OFDMSwingTable23A[OFDM_index[0]] & 0xFFC00000)>>22;
                        X = pdmpriv->RegE94;
@@ -247,7 +246,9 @@ odm_TXPowerTrackingCallback_ThermalMeter_92C(
 
                                /* write new elements A, C, D to regC80 and regC94, element B is always 0 */
                                value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A;
-                               PHY_SetBBReg(Adapter, rOFDM0_XATxIQImbalance, bMaskDWord, value32);
+                               rtl8723au_write32(Adapter,
+                                                 rOFDM0_XATxIQImbalance,
+                                                 value32);
 
                                value32 = (ele_C&0x000003C0)>>6;
                                PHY_SetBBReg(Adapter, rOFDM0_XCTxAFE, bMaskH4Bits, value32);
@@ -260,9 +261,9 @@ odm_TXPowerTrackingCallback_ThermalMeter_92C(
                                PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold,
                                             BIT(29), value32);
                        } else {
-                               PHY_SetBBReg(Adapter, rOFDM0_XATxIQImbalance,
-                                            bMaskDWord,
-                                            OFDMSwingTable23A[OFDM_index[0]]);
+                               rtl8723au_write32(Adapter,
+                                                 rOFDM0_XATxIQImbalance,
+                                                 OFDMSwingTable23A[OFDM_index[0]]);
                                PHY_SetBBReg(Adapter, rOFDM0_XCTxAFE,
                                             bMaskH4Bits, 0x00);
                                PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold,
@@ -290,7 +291,7 @@ odm_TXPowerTrackingCallback_ThermalMeter_92C(
                                rtl8723au_write8(Adapter, 0xa29, CCKSwingTable_Ch1423A[CCK_index][7]);
                        }
 
-                       if (is2T) {
+                       if (pHalData->rf_type == RF_2T2R) {
                                ele_D = (OFDMSwingTable23A[(u8)OFDM_index[1]] & 0xFFC00000)>>22;
 
                                /* new element A = element D x X */
@@ -309,7 +310,7 @@ odm_TXPowerTrackingCallback_ThermalMeter_92C(
 
                                        /* write new elements A, C, D to regC88 and regC9C, element B is always 0 */
                                        value32 = (ele_D<<22)|((ele_C&0x3F)<<16) | ele_A;
-                                       PHY_SetBBReg(Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord, value32);
+                                       rtl8723au_write32(Adapter, rOFDM0_XBTxIQImbalance, value32);
 
                                        value32 = (ele_C&0x000003C0)>>6;
                                        PHY_SetBBReg(Adapter, rOFDM0_XDTxAFE, bMaskH4Bits, value32);
@@ -324,10 +325,9 @@ odm_TXPowerTrackingCallback_ThermalMeter_92C(
                                                     rOFDM0_ECCAThreshold,
                                                     BIT(25), value32);
                                } else {
-                                       PHY_SetBBReg(Adapter,
-                                                    rOFDM0_XBTxIQImbalance,
-                                                    bMaskDWord,
-                                                    OFDMSwingTable23A[OFDM_index[1]]);
+                                       rtl8723au_write32(Adapter,
+                                                         rOFDM0_XBTxIQImbalance,
+                                                         OFDMSwingTable23A[OFDM_index[1]]);
                                        PHY_SetBBReg(Adapter,
                                                     rOFDM0_XDTxAFE,
                                                     bMaskH4Bits, 0x00);
@@ -361,14 +361,10 @@ static void ODM_TXPowerTracking92CDirectCall(struct rtw_adapter *Adapter)
        odm_TXPowerTrackingCallback_ThermalMeter_92C(Adapter);
 }
 
-static void odm_CheckTXPowerTracking_ThermalMeter(struct rtw_adapter *Adapter)
+void rtl8723a_odm_check_tx_power_tracking(struct rtw_adapter *Adapter)
 {
        struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
        struct dm_priv *pdmpriv = &pHalData->dmpriv;
-       struct dm_odm_t *podmpriv = &pHalData->odmpriv;
-
-       if (!(podmpriv->SupportAbility & ODM_RF_TX_PWR_TRACK))
-               return;
 
        if (!pdmpriv->TM_Trigger) {             /* at least delay 1 sec */
                PHY_SetRFReg(Adapter, RF_PATH_A, RF_T_METER, bRFRegOffsetMask, 0x60);
@@ -381,11 +377,6 @@ static void odm_CheckTXPowerTracking_ThermalMeter(struct rtw_adapter *Adapter)
        }
 }
 
-void rtl8723a_odm_check_tx_power_tracking(struct rtw_adapter *Adapter)
-{
-       odm_CheckTXPowerTracking_ThermalMeter(Adapter);
-}
-
 /*     IQK */
 #define MAX_TOLERANCE          5
 #define IQK_DELAY_TIME         1       /* ms */
@@ -397,36 +388,37 @@ static u8 _PHY_PathA_IQK(struct rtw_adapter *pAdapter, bool configPathB)
        struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
 
        /* path-A IQK setting */
-       PHY_SetBBReg(pAdapter, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1f);
-       PHY_SetBBReg(pAdapter, rRx_IQK_Tone_A, bMaskDWord, 0x10008c1f);
-       PHY_SetBBReg(pAdapter, rTx_IQK_PI_A, bMaskDWord, 0x82140102);
+       rtl8723au_write32(pAdapter, rTx_IQK_Tone_A, 0x10008c1f);
+       rtl8723au_write32(pAdapter, rRx_IQK_Tone_A, 0x10008c1f);
+       rtl8723au_write32(pAdapter, rTx_IQK_PI_A, 0x82140102);
 
-       PHY_SetBBReg(pAdapter, rRx_IQK_PI_A, bMaskDWord, configPathB ? 0x28160202 :
+       rtl8723au_write32(pAdapter, rRx_IQK_PI_A, configPathB ? 0x28160202 :
                IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)?0x28160202:0x28160502);
 
        /* path-B IQK setting */
        if (configPathB) {
-               PHY_SetBBReg(pAdapter, rTx_IQK_Tone_B, bMaskDWord, 0x10008c22);
-               PHY_SetBBReg(pAdapter, rRx_IQK_Tone_B, bMaskDWord, 0x10008c22);
-               PHY_SetBBReg(pAdapter, rTx_IQK_PI_B, bMaskDWord, 0x82140102);
-               PHY_SetBBReg(pAdapter, rRx_IQK_PI_B, bMaskDWord, 0x28160202);
+               rtl8723au_write32(pAdapter, rTx_IQK_Tone_B, 0x10008c22);
+               rtl8723au_write32(pAdapter, rRx_IQK_Tone_B, 0x10008c22);
+               rtl8723au_write32(pAdapter, rTx_IQK_PI_B, 0x82140102);
+               rtl8723au_write32(pAdapter, rRx_IQK_PI_B, 0x28160202);
        }
 
        /* LO calibration setting */
-       PHY_SetBBReg(pAdapter, rIQK_AGC_Rsp, bMaskDWord, 0x001028d1);
+       rtl8723au_write32(pAdapter, rIQK_AGC_Rsp, 0x001028d1);
 
        /* One shot, path A LOK & IQK */
-       PHY_SetBBReg(pAdapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
-       PHY_SetBBReg(pAdapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+       rtl8723au_write32(pAdapter, rIQK_AGC_Pts, 0xf9000000);
+       rtl8723au_write32(pAdapter, rIQK_AGC_Pts, 0xf8000000);
 
        /*  delay x ms */
-       udelay(IQK_DELAY_TIME*1000);/* PlatformStallExecution(IQK_DELAY_TIME*1000); */
+       /* PlatformStallExecution(IQK_DELAY_TIME*1000); */
+       udelay(IQK_DELAY_TIME*1000);
 
        /*  Check failed */
-       regEAC = PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_A_2, bMaskDWord);
-       regE94 = PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_A, bMaskDWord);
-       regE9C = PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_A, bMaskDWord);
-       regEA4 = PHY_QueryBBReg(pAdapter, rRx_Power_Before_IQK_A_2, bMaskDWord);
+       regEAC = rtl8723au_read32(pAdapter, rRx_Power_After_IQK_A_2);
+       regE94 = rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_A);
+       regE9C = rtl8723au_read32(pAdapter, rTx_Power_After_IQK_A);
+       regEA4 = rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_A_2);
 
        if (!(regEAC & BIT(28)) &&
            (((regE94 & 0x03FF0000)>>16) != 0x142) &&
@@ -435,7 +427,7 @@ static u8 _PHY_PathA_IQK(struct rtw_adapter *pAdapter, bool configPathB)
        else                    /* if Tx not OK, ignore Rx */
                return result;
 
-       if (!(regEAC & BIT(27)) &&              /* if Tx is OK, check whether Rx is OK */
+       if (!(regEAC & BIT(27)) && /* if Tx is OK, check whether Rx is OK */
            (((regEA4 & 0x03FF0000)>>16) != 0x132) &&
            (((regEAC & 0x03FF0000)>>16) != 0x36))
                result |= 0x02;
@@ -450,18 +442,18 @@ static u8 _PHY_PathB_IQK(struct rtw_adapter *pAdapter)
        u8 result = 0x00;
 
        /* One shot, path B LOK & IQK */
-       PHY_SetBBReg(pAdapter, rIQK_AGC_Cont, bMaskDWord, 0x00000002);
-       PHY_SetBBReg(pAdapter, rIQK_AGC_Cont, bMaskDWord, 0x00000000);
+       rtl8723au_write32(pAdapter, rIQK_AGC_Cont, 0x00000002);
+       rtl8723au_write32(pAdapter, rIQK_AGC_Cont, 0x00000000);
 
        /*  delay x ms */
        udelay(IQK_DELAY_TIME*1000);
 
        /*  Check failed */
-       regEAC = PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_A_2, bMaskDWord);
-       regEB4 = PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_B, bMaskDWord);
-       regEBC = PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_B, bMaskDWord);
-       regEC4 = PHY_QueryBBReg(pAdapter, rRx_Power_Before_IQK_B_2, bMaskDWord);
-       regECC = PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_B_2, bMaskDWord);
+       regEAC = rtl8723au_read32(pAdapter, rRx_Power_After_IQK_A_2);
+       regEB4 = rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_B);
+       regEBC = rtl8723au_read32(pAdapter, rTx_Power_After_IQK_B);
+       regEC4 = rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_B_2);
+       regECC = rtl8723au_read32(pAdapter, rRx_Power_After_IQK_B_2);
 
        if (!(regEAC & BIT(31)) &&
            (((regEB4 & 0x03FF0000)>>16) != 0x142) &&
@@ -494,22 +486,27 @@ static void _PHY_PathAFillIQKMatrix(struct rtw_adapter *pAdapter,
        if (final_candidate == 0xFF) {
                return;
        } else if (bIQKOK) {
-               Oldval_0 = (PHY_QueryBBReg(pAdapter, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
+               Oldval_0 = rtl8723au_read32(pAdapter, rOFDM0_XATxIQImbalance);
+               Oldval_0 = (Oldval_0 >> 22) & 0x3FF;
 
                X = result[final_candidate][0];
                if ((X & 0x00000200) != 0)
                        X = X | 0xFFFFFC00;
                TX0_A = (X * Oldval_0) >> 8;
                PHY_SetBBReg(pAdapter, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A);
-               PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(31), ((X * Oldval_0>>7) & 0x1));
+               PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(31),
+                            ((X * Oldval_0>>7) & 0x1));
 
                Y = result[final_candidate][1];
                if ((Y & 0x00000200) != 0)
                        Y = Y | 0xFFFFFC00;
                TX0_C = (Y * Oldval_0) >> 8;
-               PHY_SetBBReg(pAdapter, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C&0x3C0)>>6));
-               PHY_SetBBReg(pAdapter, rOFDM0_XATxIQImbalance, 0x003F0000, (TX0_C&0x3F));
-               PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(29), ((Y * Oldval_0>>7) & 0x1));
+               PHY_SetBBReg(pAdapter, rOFDM0_XCTxAFE, 0xF0000000,
+                            ((TX0_C&0x3C0)>>6));
+               PHY_SetBBReg(pAdapter, rOFDM0_XATxIQImbalance, 0x003F0000,
+                            (TX0_C&0x3F));
+               PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(29),
+                            ((Y * Oldval_0>>7) & 0x1));
 
                if (bTxOnly) {
                        DBG_8723A("_PHY_PathAFillIQKMatrix only Tx OK\n");
@@ -537,22 +534,27 @@ static void _PHY_PathBFillIQKMatrix(struct rtw_adapter *pAdapter, bool bIQKOK, i
        if (final_candidate == 0xFF) {
                return;
        } else if (bIQKOK) {
-               Oldval_1 = (PHY_QueryBBReg(pAdapter, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
+               Oldval_1 = rtl8723au_read32(pAdapter, rOFDM0_XBTxIQImbalance);
+               Oldval_1 = (Oldval_1 >> 22) & 0x3FF;
 
                X = result[final_candidate][4];
                if ((X & 0x00000200) != 0)
                        X = X | 0xFFFFFC00;
                TX1_A = (X * Oldval_1) >> 8;
                PHY_SetBBReg(pAdapter, rOFDM0_XBTxIQImbalance, 0x3FF, TX1_A);
-               PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(27), ((X * Oldval_1>>7) & 0x1));
+               PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(27),
+                            ((X * Oldval_1 >> 7) & 0x1));
 
                Y = result[final_candidate][5];
                if ((Y & 0x00000200) != 0)
                        Y = Y | 0xFFFFFC00;
                TX1_C = (Y * Oldval_1) >> 8;
-               PHY_SetBBReg(pAdapter, rOFDM0_XDTxAFE, 0xF0000000, ((TX1_C&0x3C0)>>6));
-               PHY_SetBBReg(pAdapter, rOFDM0_XBTxIQImbalance, 0x003F0000, (TX1_C&0x3F));
-               PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(25), ((Y * Oldval_1>>7) & 0x1));
+               PHY_SetBBReg(pAdapter, rOFDM0_XDTxAFE, 0xF0000000,
+                            ((TX1_C & 0x3C0) >> 6));
+               PHY_SetBBReg(pAdapter, rOFDM0_XBTxIQImbalance, 0x003F0000,
+                            (TX1_C & 0x3F));
+               PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(25),
+                            ((Y * Oldval_1 >> 7) & 0x1));
 
                if (bTxOnly)
                        return;
@@ -573,11 +575,12 @@ static void _PHY_SaveADDARegisters(struct rtw_adapter *pAdapter, u32 *ADDAReg, u
        u32 i;
 
        for (i = 0 ; i < RegisterNum ; i++) {
-               ADDABackup[i] = PHY_QueryBBReg(pAdapter, ADDAReg[i], bMaskDWord);
+               ADDABackup[i] = rtl8723au_read32(pAdapter, ADDAReg[i]);
        }
 }
 
-static void _PHY_SaveMACRegisters(struct rtw_adapter *pAdapter, u32 *MACReg, u32 *MACBackup)
+static void _PHY_SaveMACRegisters(struct rtw_adapter *pAdapter, u32 *MACReg,
+                                 u32 *MACBackup)
 {
        u32 i;
 
@@ -587,16 +590,19 @@ static void _PHY_SaveMACRegisters(struct rtw_adapter *pAdapter, u32 *MACReg, u32
        MACBackup[i] = rtl8723au_read32(pAdapter, MACReg[i]);
 }
 
-static void _PHY_ReloadADDARegisters(struct rtw_adapter *pAdapter, u32 *ADDAReg, u32 *ADDABackup, u32 RegiesterNum)
+static void _PHY_ReloadADDARegisters(struct rtw_adapter *pAdapter,
+                                    u32 *ADDAReg, u32 *ADDABackup,
+                                    u32 RegiesterNum)
 {
        u32 i;
 
        for (i = 0 ; i < RegiesterNum ; i++) {
-               PHY_SetBBReg(pAdapter, ADDAReg[i], bMaskDWord, ADDABackup[i]);
+               rtl8723au_write32(pAdapter, ADDAReg[i], ADDABackup[i]);
        }
 }
 
-static void _PHY_ReloadMACRegisters(struct rtw_adapter *pAdapter, u32 *MACReg, u32 *MACBackup)
+static void _PHY_ReloadMACRegisters(struct rtw_adapter *pAdapter,
+                                   u32 *MACReg, u32 *MACBackup)
 {
        u32 i;
 
@@ -606,7 +612,8 @@ static void _PHY_ReloadMACRegisters(struct rtw_adapter *pAdapter, u32 *MACReg, u
        rtl8723au_write32(pAdapter, MACReg[i], MACBackup[i]);
 }
 
-static void _PHY_PathADDAOn(struct rtw_adapter *pAdapter, u32 *ADDAReg, bool isPathAOn, bool is2T)
+static void _PHY_PathADDAOn(struct rtw_adapter *pAdapter, u32 *ADDAReg,
+                           bool isPathAOn, bool is2T)
 {
        u32 pathOn;
        u32 i;
@@ -614,16 +621,17 @@ static void _PHY_PathADDAOn(struct rtw_adapter *pAdapter, u32 *ADDAReg, bool isP
        pathOn = isPathAOn ? 0x04db25a4 : 0x0b1b25a4;
        if (!is2T) {
                pathOn = 0x0bdb25a0;
-               PHY_SetBBReg(pAdapter, ADDAReg[0], bMaskDWord, 0x0b1b25a0);
+               rtl8723au_write32(pAdapter, ADDAReg[0], 0x0b1b25a0);
        } else {
-               PHY_SetBBReg(pAdapter, ADDAReg[0], bMaskDWord, pathOn);
+               rtl8723au_write32(pAdapter, ADDAReg[0], pathOn);
        }
 
        for (i = 1 ; i < IQK_ADDA_REG_NUM ; i++)
-               PHY_SetBBReg(pAdapter, ADDAReg[i], bMaskDWord, pathOn);
+               rtl8723au_write32(pAdapter, ADDAReg[i], pathOn);
 }
 
-static void _PHY_MACSettingCalibration(struct rtw_adapter *pAdapter, u32 *MACReg, u32 *MACBackup)
+static void _PHY_MACSettingCalibration(struct rtw_adapter *pAdapter,
+                                      u32 *MACReg, u32 *MACBackup)
 {
        u32 i = 0;
 
@@ -638,9 +646,9 @@ static void _PHY_MACSettingCalibration(struct rtw_adapter *pAdapter, u32 *MACReg
 
 static void _PHY_PathAStandBy(struct rtw_adapter *pAdapter)
 {
-       PHY_SetBBReg(pAdapter, rFPGA0_IQK, bMaskDWord, 0x0);
-       PHY_SetBBReg(pAdapter, 0x840, bMaskDWord, 0x00010000);
-       PHY_SetBBReg(pAdapter, rFPGA0_IQK, bMaskDWord, 0x80800000);
+       rtl8723au_write32(pAdapter, rFPGA0_IQK, 0x0);
+       rtl8723au_write32(pAdapter, 0x840, 0x00010000);
+       rtl8723au_write32(pAdapter, rFPGA0_IQK, 0x80800000);
 }
 
 static void _PHY_PIModeSwitch(struct rtw_adapter *pAdapter, bool PIMode)
@@ -648,8 +656,8 @@ static void _PHY_PIModeSwitch(struct rtw_adapter *pAdapter, bool PIMode)
        u32 mode;
 
        mode = PIMode ? 0x01000100 : 0x01000000;
-       PHY_SetBBReg(pAdapter, 0x820, bMaskDWord, mode);
-       PHY_SetBBReg(pAdapter, 0x828, bMaskDWord, mode);
+       rtl8723au_write32(pAdapter, 0x820, mode);
+       rtl8723au_write32(pAdapter, 0x828, mode);
 }
 
 /*
@@ -660,9 +668,9 @@ static bool _PHY_SimularityCompare(struct rtw_adapter *pAdapter, int result[][8]
        u32 i, j, diff, SimularityBitMap, bound = 0;
        struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
        u8 final_candidate[2] = {0xFF, 0xFF};   /* for path A and path B */
-       bool bResult = true, is2T = IS_92C_SERIAL(pHalData->VersionID);
+       bool bResult = true;
 
-       if (is2T)
+       if (pHalData->rf_type == RF_2T2R)
                bound = 8;
        else
                bound = 4;
@@ -699,7 +707,7 @@ static bool _PHY_SimularityCompare(struct rtw_adapter *pAdapter, int result[][8]
                for (i = 0; i < 4; i++)
                        result[3][i] = result[c1][i];
                return false;
-       } else if (!(SimularityBitMap & 0xF0) && is2T) {
+       } else if (!(SimularityBitMap & 0xF0) && pHalData->rf_type == RF_2T2R) {
                /* path B OK */
                for (i = 4; i < 8; i++)
                        result[3][i] = result[c1][i];
@@ -746,7 +754,7 @@ static void _PHY_IQCalibrate(struct rtw_adapter *pAdapter, int result[][8], u8 t
        u32 bbvalue;
 
        if (t == 0) {
-               bbvalue = PHY_QueryBBReg(pAdapter, rFPGA0_RFMOD, bMaskDWord);
+               bbvalue = rtl8723au_read32(pAdapter, rFPGA0_RFMOD);
 
                /*  Save ADDA parameters, turn Path A ADDA on */
                _PHY_SaveADDARegisters(pAdapter, ADDA_REG, pdmpriv->ADDA_backup, IQK_ADDA_REG_NUM);
@@ -766,48 +774,50 @@ static void _PHY_IQCalibrate(struct rtw_adapter *pAdapter, int result[][8], u8 t
        }
 
        PHY_SetBBReg(pAdapter, rFPGA0_RFMOD, BIT(24), 0x00);
-       PHY_SetBBReg(pAdapter, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
-       PHY_SetBBReg(pAdapter, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
-       PHY_SetBBReg(pAdapter, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
+       rtl8723au_write32(pAdapter, rOFDM0_TRxPathEnable, 0x03a05600);
+       rtl8723au_write32(pAdapter, rOFDM0_TRMuxPar, 0x000800e4);
+       rtl8723au_write32(pAdapter, rFPGA0_XCD_RFInterfaceSW, 0x22204000);
        PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
        PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
        PHY_SetBBReg(pAdapter, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
        PHY_SetBBReg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
 
        if (is2T) {
-               PHY_SetBBReg(pAdapter, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00010000);
-               PHY_SetBBReg(pAdapter, rFPGA0_XB_LSSIParameter, bMaskDWord, 0x00010000);
+               rtl8723au_write32(pAdapter,
+                                 rFPGA0_XA_LSSIParameter, 0x00010000);
+               rtl8723au_write32(pAdapter,
+                                 rFPGA0_XB_LSSIParameter, 0x00010000);
        }
 
        /* MAC settings */
        _PHY_MACSettingCalibration(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup);
 
        /* Page B init */
-       PHY_SetBBReg(pAdapter, rConfig_AntA, bMaskDWord, 0x00080000);
+       rtl8723au_write32(pAdapter, rConfig_AntA, 0x00080000);
 
        if (is2T)
-               PHY_SetBBReg(pAdapter, rConfig_AntB, bMaskDWord, 0x00080000);
+               rtl8723au_write32(pAdapter, rConfig_AntB, 0x00080000);
 
        /*  IQ calibration setting */
-       PHY_SetBBReg(pAdapter, rFPGA0_IQK, bMaskDWord, 0x80800000);
-       PHY_SetBBReg(pAdapter, rTx_IQK, bMaskDWord, 0x01007c00);
-       PHY_SetBBReg(pAdapter, rRx_IQK, bMaskDWord, 0x01004800);
+       rtl8723au_write32(pAdapter, rFPGA0_IQK, 0x80800000);
+       rtl8723au_write32(pAdapter, rTx_IQK, 0x01007c00);
+       rtl8723au_write32(pAdapter, rRx_IQK, 0x01004800);
 
        for (i = 0 ; i < retryCount ; i++) {
                PathAOK = _PHY_PathA_IQK(pAdapter, is2T);
                if (PathAOK == 0x03) {
                                DBG_8723A("Path A IQK Success!!\n");
-                               result[t][0] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
-                               result[t][1] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
-                               result[t][2] = (PHY_QueryBBReg(pAdapter, rRx_Power_Before_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
-                               result[t][3] = (PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
+                               result[t][0] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_A)&0x3FF0000)>>16;
+                               result[t][1] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_A)&0x3FF0000)>>16;
+                               result[t][2] = (rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_A_2)&0x3FF0000)>>16;
+                               result[t][3] = (rtl8723au_read32(pAdapter, rRx_Power_After_IQK_A_2)&0x3FF0000)>>16;
                        break;
                } else if (i == (retryCount-1) && PathAOK == 0x01) {
                        /* Tx IQK OK */
                        DBG_8723A("Path A IQK Only  Tx Success!!\n");
 
-                       result[t][0] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
-                       result[t][1] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
+                       result[t][0] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_A)&0x3FF0000)>>16;
+                       result[t][1] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_A)&0x3FF0000)>>16;
                }
        }
 
@@ -825,16 +835,16 @@ static void _PHY_IQCalibrate(struct rtw_adapter *pAdapter, int result[][8], u8 t
                        PathBOK = _PHY_PathB_IQK(pAdapter);
                        if (PathBOK == 0x03) {
                                DBG_8723A("Path B IQK Success!!\n");
-                               result[t][4] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_B, bMaskDWord)&0x3FF0000)>>16;
-                               result[t][5] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_B, bMaskDWord)&0x3FF0000)>>16;
-                               result[t][6] = (PHY_QueryBBReg(pAdapter, rRx_Power_Before_IQK_B_2, bMaskDWord)&0x3FF0000)>>16;
-                               result[t][7] = (PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_B_2, bMaskDWord)&0x3FF0000)>>16;
+                               result[t][4] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_B)&0x3FF0000)>>16;
+                               result[t][5] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_B)&0x3FF0000)>>16;
+                               result[t][6] = (rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_B_2)&0x3FF0000)>>16;
+                               result[t][7] = (rtl8723au_read32(pAdapter, rRx_Power_After_IQK_B_2)&0x3FF0000)>>16;
                                break;
                        } else if (i == (retryCount - 1) && PathBOK == 0x01) {
                                /* Tx IQK OK */
                                DBG_8723A("Path B Only Tx IQK Success!!\n");
-                               result[t][4] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_B, bMaskDWord)&0x3FF0000)>>16;
-                               result[t][5] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_B, bMaskDWord)&0x3FF0000)>>16;
+                               result[t][4] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_B)&0x3FF0000)>>16;
+                               result[t][5] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_B)&0x3FF0000)>>16;
                        }
                }
 
@@ -844,7 +854,7 @@ static void _PHY_IQCalibrate(struct rtw_adapter *pAdapter, int result[][8], u8 t
        }
 
        /* Back to BB mode, load original value */
-       PHY_SetBBReg(pAdapter, rFPGA0_IQK, bMaskDWord, 0);
+       rtl8723au_write32(pAdapter, rFPGA0_IQK, 0);
 
        if (t != 0) {
                if (!pdmpriv->bRfPiEnable) {
@@ -862,14 +872,16 @@ static void _PHY_IQCalibrate(struct rtw_adapter *pAdapter, int result[][8], u8 t
                _PHY_ReloadADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup, IQK_BB_REG_NUM);
 
                /*  Restore RX initial gain */
-               PHY_SetBBReg(pAdapter, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00032ed3);
+               rtl8723au_write32(pAdapter,
+                                 rFPGA0_XA_LSSIParameter, 0x00032ed3);
                if (is2T) {
-                       PHY_SetBBReg(pAdapter, rFPGA0_XB_LSSIParameter, bMaskDWord, 0x00032ed3);
+                       rtl8723au_write32(pAdapter,
+                                         rFPGA0_XB_LSSIParameter, 0x00032ed3);
                }
 
                /* load 0xe30 IQC default value */
-               PHY_SetBBReg(pAdapter, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
-               PHY_SetBBReg(pAdapter, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
+               rtl8723au_write32(pAdapter, rTx_IQK_Tone_A, 0x01008c00);
+               rtl8723au_write32(pAdapter, rRx_IQK_Tone_A, 0x01008c00);
 
        }
 }
@@ -980,12 +992,10 @@ void rtl8723a_phy_iq_calibrate(struct rtw_adapter *pAdapter, bool bReCovery)
        is13simular = false;
 
        for (i = 0; i < 3; i++) {
-               if (IS_92C_SERIAL(pHalData->VersionID)) {
-                        _PHY_IQCalibrate(pAdapter, result, i, true);
-               } else {
-                       /*  For 88C 1T1R */
+               if (pHalData->rf_type == RF_2T2R)
+                       _PHY_IQCalibrate(pAdapter, result, i, true);
+               else /*  For 88C 1T1R */
                        _PHY_IQCalibrate(pAdapter, result, i, false);
-               }
 
                if (i == 1) {
                        is12simular = _PHY_SimularityCompare(pAdapter, result, 0, 1);
@@ -1053,9 +1063,10 @@ void rtl8723a_phy_iq_calibrate(struct rtw_adapter *pAdapter, bool bReCovery)
        if ((RegE94 != 0)/*&&(RegEA4 != 0)*/)
                _PHY_PathAFillIQKMatrix(pAdapter, bPathAOK, result, final_candidate, (RegEA4 == 0));
 
-       if (IS_92C_SERIAL(pHalData->VersionID)) {
+       if (pHalData->rf_type == RF_2T2R) {
                if ((RegEB4 != 0)/*&&(RegEC4 != 0)*/)
-               _PHY_PathBFillIQKMatrix(pAdapter, bPathBOK, result, final_candidate, (RegEC4 == 0));
+                       _PHY_PathBFillIQKMatrix(pAdapter, bPathBOK, result,
+                                               final_candidate, (RegEC4 == 0));
        }
 
        _PHY_SaveADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup_recover, 9);
@@ -1074,12 +1085,10 @@ void rtl8723a_phy_lc_calibrate(struct rtw_adapter *pAdapter)
        if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
                return;
 
-       if (IS_92C_SERIAL(pHalData->VersionID)) {
+       if (pHalData->rf_type == RF_2T2R)
                _PHY_LCCalibrate(pAdapter, true);
-       } else {
-               /*  For 88C 1T1R */
+       else    /*  For 88C 1T1R */
                _PHY_LCCalibrate(pAdapter, false);
-       }
 }
 
 void
index 9d4f6bed4269d1566a53e97933006a82e5e48ce8..e8cab9e97385735cf730181f8f642a7603fd332e 100644 (file)
@@ -30,12 +30,12 @@ static bool CheckCondition(const u32  Condition, const u32  Hex)
                return false;
 
        cond = Condition & 0x0000FF00;
-       cond = cond >> 8;
+       cond >>= 8;
        if ((_interface & cond) == 0 && cond != 0x07)
                return false;
 
        cond = Condition & 0x00FF0000;
-       cond = cond >> 16;
+       cond >>= 16;
        if ((_platform & cond) == 0 && cond != 0x0F)
                return false;
        return true;
@@ -215,17 +215,15 @@ static u32 Array_AGC_TAB_1T_8723A[] = {
 
 void ODM_ReadAndConfig_AGC_TAB_1T_8723A(struct dm_odm_t *pDM_Odm)
 {
-
        u32 hex;
        u32 i;
        u8 platform = 0x04;
-       u8 interfaceValue   = pDM_Odm->SupportInterface;
        u8 board = pDM_Odm->BoardType;
        u32 ArrayLen = sizeof(Array_AGC_TAB_1T_8723A)/sizeof(u32);
        u32 *Array = Array_AGC_TAB_1T_8723A;
 
        hex = board;
-       hex += interfaceValue << 8;
+       hex += ODM_ITRF_USB << 8;
        hex += platform << 16;
        hex += 0xFF000000;
        for (i = 0; i < ArrayLen; i += 2) {
@@ -234,11 +232,11 @@ void ODM_ReadAndConfig_AGC_TAB_1T_8723A(struct dm_odm_t *pDM_Odm)
 
                /*  This (offset, data) pair meets the condition. */
                if (v1 < 0xCDCDCDCD) {
-                       odm_ConfigBB_AGC_8723A(pDM_Odm, v1, bMaskDWord, v2);
+                       odm_ConfigBB_AGC_8723A(pDM_Odm, v1, v2);
                        continue;
                } else {
                        if (!CheckCondition(Array[i], hex)) {
-                               /*  Discard the following (offset, data) pairs. */
+                               /* Discard the following (offset, data) pairs */
                                READ_NEXT_PAIR(v1, v2, i);
                                while (v2 != 0xDEAD &&
                                       v2 != 0xCDEF &&
@@ -246,12 +244,13 @@ void ODM_ReadAndConfig_AGC_TAB_1T_8723A(struct dm_odm_t *pDM_Odm)
                                        READ_NEXT_PAIR(v1, v2, i);
                                i -= 2; /*  prevent from for-loop += 2 */
                        } else {
-                               /*  Configure matched pairs and skip to end of if-else. */
+                               /*  Configure matched pairs and skip to
+                                   end of if-else. */
                                READ_NEXT_PAIR(v1, v2, i);
                                while (v2 != 0xDEAD &&
                                       v2 != 0xCDEF &&
                                       v2 != 0xCDCD && i < ArrayLen - 2) {
-                                       odm_ConfigBB_AGC_8723A(pDM_Odm, v1, bMaskDWord, v2);
+                                       odm_ConfigBB_AGC_8723A(pDM_Odm, v1, v2);
                                        READ_NEXT_PAIR(v1, v2, i);
                                }
                                while (v2 != 0xDEAD && i < ArrayLen - 2)
@@ -467,13 +466,12 @@ void ODM_ReadAndConfig_PHY_REG_1T_8723A(struct dm_odm_t *pDM_Odm)
        u32 hex = 0;
        u32 i = 0;
        u8  platform = 0x04;
-       u8  interfaceValue = pDM_Odm->SupportInterface;
        u8  board = pDM_Odm->BoardType;
        u32 ArrayLen = sizeof(Array_PHY_REG_1T_8723A)/sizeof(u32);
        u32 *Array = Array_PHY_REG_1T_8723A;
 
        hex += board;
-       hex += interfaceValue << 8;
+       hex += ODM_ITRF_USB << 8;
        hex += platform << 16;
        hex += 0xFF000000;
        for (i = 0; i < ArrayLen; i += 2) {
@@ -482,11 +480,11 @@ void ODM_ReadAndConfig_PHY_REG_1T_8723A(struct dm_odm_t *pDM_Odm)
 
                /*  This (offset, data) pair meets the condition. */
                if (v1 < 0xCDCDCDCD) {
-                       odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
+                       odm_ConfigBB_PHY_8723A(pDM_Odm, v1, v2);
                        continue;
                } else {
                        if (!CheckCondition(Array[i], hex)) {
-                               /*  Discard the following (offset, data) pairs. */
+                               /* Discard the following (offset, data) pairs */
                                READ_NEXT_PAIR(v1, v2, i);
                                while (v2 != 0xDEAD &&
                                       v2 != 0xCDEF &&
@@ -494,12 +492,13 @@ void ODM_ReadAndConfig_PHY_REG_1T_8723A(struct dm_odm_t *pDM_Odm)
                                        READ_NEXT_PAIR(v1, v2, i);
                                i -= 2; /*  prevent from for-loop += 2 */
                        } else {
-                               /*  Configure matched pairs and skip to end of if-else. */
+                               /*  Configure matched pairs and skip to
+                                   end of if-else. */
                                READ_NEXT_PAIR(v1, v2, i);
                                while (v2 != 0xDEAD &&
                                       v2 != 0xCDEF &&
                                       v2 != 0xCDCD && i < ArrayLen - 2) {
-                                       odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
+                                       odm_ConfigBB_PHY_8723A(pDM_Odm, v1, v2);
                                        READ_NEXT_PAIR(v1, v2, i);
                                }
                                while (v2 != 0xDEAD && i < ArrayLen - 2)
@@ -520,16 +519,15 @@ static u32 Array_PHY_REG_MP_8723A[] = {
 
 void ODM_ReadAndConfig_PHY_REG_MP_8723A(struct dm_odm_t *pDM_Odm)
 {
-       u32     hex         = 0;
-       u32     i           = 0;
-       u8     platform    = 0x04;
-       u8     interfaceValue   = pDM_Odm->SupportInterface;
-       u8     board       = pDM_Odm->BoardType;
-       u32     ArrayLen    = sizeof(Array_PHY_REG_MP_8723A)/sizeof(u32);
-       u32 *Array       = Array_PHY_REG_MP_8723A;
+       u32 hex = 0;
+       u32 i;
+       u8 platform = 0x04;
+       u8 board = pDM_Odm->BoardType;
+       u32 ArrayLen = sizeof(Array_PHY_REG_MP_8723A)/sizeof(u32);
+       u32 *Array = Array_PHY_REG_MP_8723A;
 
        hex += board;
-       hex += interfaceValue << 8;
+       hex += ODM_ITRF_USB << 8;
        hex += platform << 16;
        hex += 0xFF000000;
        for (i = 0; i < ArrayLen; i += 2) {
@@ -538,11 +536,11 @@ void ODM_ReadAndConfig_PHY_REG_MP_8723A(struct dm_odm_t *pDM_Odm)
 
                /*  This (offset, data) pair meets the condition. */
                if (v1 < 0xCDCDCDCD) {
-                       odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
+                       odm_ConfigBB_PHY_8723A(pDM_Odm, v1, v2);
                        continue;
                } else {
                        if (!CheckCondition(Array[i], hex)) {
-                               /* Discard the following (offset, data) pairs. */
+                               /* Discard the following (offset, data) pairs */
                                READ_NEXT_PAIR(v1, v2, i);
                                while (v2 != 0xDEAD &&
                                       v2 != 0xCDEF &&
@@ -550,12 +548,13 @@ void ODM_ReadAndConfig_PHY_REG_MP_8723A(struct dm_odm_t *pDM_Odm)
                                        READ_NEXT_PAIR(v1, v2, i);
                                i -= 2; /*  prevent from for-loop += 2 */
                        } else {
-                               /* Configure matched pairs and skip to end of if-else. */
+                               /* Configure matched pairs and skip to
+                                  end of if-else. */
                                READ_NEXT_PAIR(v1, v2, i);
                                while (v2 != 0xDEAD &&
                                       v2 != 0xCDEF &&
                                       v2 != 0xCDCD && i < ArrayLen - 2) {
-                                       odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
+                                       odm_ConfigBB_PHY_8723A(pDM_Odm, v1, v2);
                                        READ_NEXT_PAIR(v1, v2, i);
                                }
                                while (v2 != 0xDEAD && i < ArrayLen - 2)
index 12071453be97228d7761699f829310a532aa8e6b..93b2d183d6942e9295ff9c9ba65df03815de6075 100644 (file)
@@ -30,12 +30,12 @@ static bool CheckCondition(const u32  Condition, const u32  Hex)
                return false;
 
        cond = Condition & 0x0000FF00;
-       cond = cond >> 8;
+       cond >>= 8;
        if ((_interface & cond) == 0 && cond != 0x07)
                return false;
 
        cond = Condition & 0x00FF0000;
-       cond = cond >> 16;
+       cond >>= 16;
        if ((_platform & cond) == 0 && cond != 0x0F)
                return false;
        return true;
@@ -144,13 +144,12 @@ void ODM_ReadAndConfig_MAC_REG_8723A(struct dm_odm_t *pDM_Odm)
        u32     hex         = 0;
        u32     i           = 0;
        u8     platform    = 0x04;
-       u8     interfaceValue   = pDM_Odm->SupportInterface;
        u8     board       = pDM_Odm->BoardType;
        u32     ArrayLen    = sizeof(Array_MAC_REG_8723A)/sizeof(u32);
        u32 *Array       = Array_MAC_REG_8723A;
 
        hex += board;
-       hex += interfaceValue << 8;
+       hex += ODM_ITRF_USB << 8;
        hex += platform << 16;
        hex += 0xFF000000;
        for (i = 0; i < ArrayLen; i += 2) {
index 00480f5fcdab251ca353cd3864c6696dc1e3a9d9..dbf571e8b908599d2cb138ccc6879e4d2610019f 100644 (file)
@@ -30,12 +30,12 @@ static bool CheckCondition(const u32  Condition, const u32  Hex)
                return false;
 
        cond = Condition & 0x0000FF00;
-       cond = cond >> 8;
+       cond >>= 8;
        if ((_interface & cond) == 0 && cond != 0x07)
                return false;
 
        cond = Condition & 0x00FF0000;
-       cond = cond >> 16;
+       cond >>= 16;
        if ((_platform & cond) == 0 && cond != 0x0F)
                return false;
        return true;
@@ -214,13 +214,12 @@ void ODM_ReadAndConfig_RadioA_1T_8723A(struct dm_odm_t *pDM_Odm)
        u32     hex         = 0;
        u32     i           = 0;
        u8     platform    = 0x04;
-       u8     interfaceValue   = pDM_Odm->SupportInterface;
        u8     board       = pDM_Odm->BoardType;
        u32     ArrayLen    = sizeof(Array_RadioA_1T_8723A)/sizeof(u32);
        u32 *Array = Array_RadioA_1T_8723A;
 
        hex += board;
-       hex += interfaceValue << 8;
+       hex += ODM_ITRF_USB << 8;
        hex += platform << 16;
        hex += 0xFF000000;
 
index 33777d2852f49c02c1d11cd71f213d7d9751a42b..ae090ab115856dc7d5e893369f9efa90be2030c7 100644 (file)
@@ -59,17 +59,15 @@ u8 HalPwrSeqCmdParsing23a(struct rtw_adapter *padapter, u8 CutVersion,
                PwrCfgCmd = PwrSeqCmd[AryIdx];
 
                RT_TRACE(_module_hal_init_c_, _drv_info_,
-                        ("HalPwrSeqCmdParsing23a: offset(%#x) cut_msk(%#x) "
-                         "fab_msk(%#x) interface_msk(%#x) base(%#x) cmd(%#x) "
-                         "msk(%#x) value(%#x)\n",
-                         GET_PWR_CFG_OFFSET(PwrCfgCmd),
-                         GET_PWR_CFG_CUT_MASK(PwrCfgCmd),
-                         GET_PWR_CFG_FAB_MASK(PwrCfgCmd),
-                         GET_PWR_CFG_INTF_MASK(PwrCfgCmd),
-                         GET_PWR_CFG_BASE(PwrCfgCmd),
-                         GET_PWR_CFG_CMD(PwrCfgCmd),
-                         GET_PWR_CFG_MASK(PwrCfgCmd),
-                         GET_PWR_CFG_VALUE(PwrCfgCmd)));
+                        "HalPwrSeqCmdParsing23a: offset(%#x) cut_msk(%#x) fab_msk(%#x) interface_msk(%#x) base(%#x) cmd(%#x) msk(%#x) value(%#x)\n",
+                        GET_PWR_CFG_OFFSET(PwrCfgCmd),
+                        GET_PWR_CFG_CUT_MASK(PwrCfgCmd),
+                        GET_PWR_CFG_FAB_MASK(PwrCfgCmd),
+                        GET_PWR_CFG_INTF_MASK(PwrCfgCmd),
+                        GET_PWR_CFG_BASE(PwrCfgCmd),
+                        GET_PWR_CFG_CMD(PwrCfgCmd),
+                        GET_PWR_CFG_MASK(PwrCfgCmd),
+                        GET_PWR_CFG_VALUE(PwrCfgCmd));
 
                /* 2 Only Handle the command whose FAB, CUT, and Interface are
                   matched */
@@ -79,14 +77,12 @@ u8 HalPwrSeqCmdParsing23a(struct rtw_adapter *padapter, u8 CutVersion,
                        switch (GET_PWR_CFG_CMD(PwrCfgCmd)) {
                        case PWR_CMD_READ:
                                RT_TRACE(_module_hal_init_c_, _drv_info_,
-                                        ("HalPwrSeqCmdParsing23a: "
-                                         "PWR_CMD_READ\n"));
+                                        "HalPwrSeqCmdParsing23a: PWR_CMD_READ\n");
                                break;
 
                        case PWR_CMD_WRITE:
                                RT_TRACE(_module_hal_init_c_, _drv_info_,
-                                        ("HalPwrSeqCmdParsing23a: "
-                                         "PWR_CMD_WRITE\n"));
+                                        "HalPwrSeqCmdParsing23a: PWR_CMD_WRITE\n");
                                offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
 
                                /*  Read the value from system register */
@@ -102,8 +98,7 @@ u8 HalPwrSeqCmdParsing23a(struct rtw_adapter *padapter, u8 CutVersion,
 
                        case PWR_CMD_POLLING:
                                RT_TRACE(_module_hal_init_c_, _drv_info_,
-                                        ("HalPwrSeqCmdParsing23a: "
-                                         "PWR_CMD_POLLING\n"));
+                                        "HalPwrSeqCmdParsing23a: PWR_CMD_POLLING\n");
 
                                bPollingBit = false;
                                offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
@@ -131,8 +126,7 @@ u8 HalPwrSeqCmdParsing23a(struct rtw_adapter *padapter, u8 CutVersion,
 
                        case PWR_CMD_DELAY:
                                RT_TRACE(_module_hal_init_c_, _drv_info_,
-                                        ("HalPwrSeqCmdParsing23a: "
-                                         "PWR_CMD_DELAY\n"));
+                                        "HalPwrSeqCmdParsing23a: PWR_CMD_DELAY\n");
                                if (GET_PWR_CFG_VALUE(PwrCfgCmd) ==
                                    PWRSEQ_DELAY_US)
                                        udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd));
@@ -145,15 +139,12 @@ u8 HalPwrSeqCmdParsing23a(struct rtw_adapter *padapter, u8 CutVersion,
                                /*  When this command is parsed, end
                                    the process */
                                RT_TRACE(_module_hal_init_c_, _drv_info_,
-                                        ("HalPwrSeqCmdParsing23a: "
-                                         "PWR_CMD_END\n"));
+                                        "HalPwrSeqCmdParsing23a: PWR_CMD_END\n");
                                return true;
-                               break;
 
                        default:
                                RT_TRACE(_module_hal_init_c_, _drv_err_,
-                                        ("HalPwrSeqCmdParsing23a: "
-                                         "Unknown CMD!!\n"));
+                                        "HalPwrSeqCmdParsing23a: Unknown CMD!!\n");
                                break;
                        }
                }
index bf4cae20bd1273cb6673818f47af586dea685774..530db57e8842cc5f85b9bff1f7dd30ce77b57352 100644 (file)
 
 #define _HAL_INIT_C_
 
-void dump_chip_info23a(struct hal_version ChipVersion)
-{
-       int cnt = 0;
-       u8 buf[128];
-
-       cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8723A_");
-
-       cnt += sprintf((buf + cnt), "%s_", IS_NORMAL_CHIP(ChipVersion) ?
-                      "Normal_Chip" : "Test_Chip");
-       cnt += sprintf((buf + cnt), "%s_",
-                      IS_CHIP_VENDOR_TSMC(ChipVersion) ? "TSMC" : "UMC");
-       if (IS_A_CUT(ChipVersion))
-               cnt += sprintf((buf + cnt), "A_CUT_");
-       else if (IS_B_CUT(ChipVersion))
-               cnt += sprintf((buf + cnt), "B_CUT_");
-       else if (IS_C_CUT(ChipVersion))
-               cnt += sprintf((buf + cnt), "C_CUT_");
-       else if (IS_D_CUT(ChipVersion))
-               cnt += sprintf((buf + cnt), "D_CUT_");
-       else if (IS_E_CUT(ChipVersion))
-               cnt += sprintf((buf + cnt), "E_CUT_");
-       else
-               cnt += sprintf((buf + cnt), "UNKNOWN_CUT(%d)_",
-                              ChipVersion.CUTVersion);
-
-       if (IS_1T1R(ChipVersion))
-               cnt += sprintf((buf + cnt), "1T1R_");
-       else if (IS_1T2R(ChipVersion))
-               cnt += sprintf((buf + cnt), "1T2R_");
-       else if (IS_2T2R(ChipVersion))
-               cnt += sprintf((buf + cnt), "2T2R_");
-       else
-               cnt += sprintf((buf + cnt), "UNKNOWN_RFTYPE(%d)_",
-                              ChipVersion.RFType);
-
-       cnt += sprintf((buf + cnt), "RomVer(%d)\n", ChipVersion.ROMVer);
-
-       DBG_8723A("%s", buf);
-}
-
 #define        EEPROM_CHANNEL_PLAN_BY_HW_MASK  0x80
 
 /* return the final channel plan decision */
@@ -231,13 +191,11 @@ void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS)
        rate_index = 0;
        /*  Set RTS initial rate */
        while (brate_cfg > 0x1) {
-               brate_cfg = (brate_cfg >> 1);
+               brate_cfg >>= 1;
                rate_index++;
        }
                /*  Ziv - Check */
        rtl8723au_write8(padapter, REG_INIRTS_RATE_SEL, rate_index);
-
-       return;
 }
 
 static void _OneOutPipeMapping(struct rtw_adapter *pAdapter)
@@ -437,9 +395,6 @@ rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet)
                if (MinSpacingToSet < SecMinSpace)
                        MinSpacingToSet = SecMinSpace;
 
-               /* RT_TRACE(COMP_MLME, DBG_LOUD,
-                  ("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
-                  padapter->MgntInfo.MinSpaceCfg)); */
                MinSpacingToSet |=
                        rtl8723au_read8(padapter, REG_AMPDU_MIN_SPACE) & 0xf8;
                rtl8723au_write8(padapter, REG_AMPDU_MIN_SPACE,
@@ -479,9 +434,6 @@ void rtl8723a_set_ampdu_factor(struct rtw_adapter *padapter, u8 FactorToSet)
                        rtl8723au_write8(padapter, REG_AGGLEN_LMT + index,
                                         pRegToSet[index]);
                }
-
-               /* RT_TRACE(COMP_MLME, DBG_LOUD,
-                  ("Set HW_VAR_AMPDU_FACTOR: %#x\n", FactorToSet)); */
        }
 }
 
@@ -666,14 +618,8 @@ void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex)
                /*  write content 0 is equall to mark invalid */
                /* delay_ms(40); */
                rtl8723au_write32(padapter, WCAMI, ulContent);
-               /* RT_TRACE(COMP_SEC, DBG_LOUD,
-                  ("rtl8723a_cam_empty_entry(): WRITE A4: %lx\n",
-                  ulContent));*/
                /* delay_ms(40); */
                rtl8723au_write32(padapter, REG_CAMCMD, ulCommand);
-               /* RT_TRACE(COMP_SEC, DBG_LOUD,
-                  ("rtl8723a_cam_empty_entry(): WRITE A0: %lx\n",
-                  ulCommand));*/
        }
 }
 
index 5269b46445f4c236ad4e04d6ea4b0dfc6a7a40f5..ec543cfe1b45d2c1c6605c4c9ae9b7241133d45e 100644 (file)
@@ -189,25 +189,16 @@ void odm_DynamicBBPowerSaving23a(struct dm_odm_t *pDM_Odm);
 
 /* END---------BB POWER SAVE----------------------- */
 
-void odm_RefreshRateAdaptiveMask23aCE23a(struct dm_odm_t *pDM_Odm);
-
 void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm);
 
-void odm_RSSIMonitorCheck23aCE(struct dm_odm_t *pDM_Odm);
-void odm_RSSIMonitorCheck23a(struct dm_odm_t *pDM_Odm);
+static void odm_RSSIMonitorCheck(struct dm_odm_t *pDM_Odm);
 void odm_DynamicTxPower23a(struct dm_odm_t *pDM_Odm);
 
-void odm_RefreshRateAdaptiveMask23a(struct dm_odm_t *pDM_Odm);
-
-void ODM_TXPowerTrackingCheck23a(struct dm_odm_t *pDM_Odm);
+static void odm_RefreshRateAdaptiveMask(struct dm_odm_t *pDM_Odm);
 
 void odm_RateAdaptiveMaskInit23a(struct dm_odm_t *pDM_Odm);
 
-void odm_TXPowerTrackingThermalMeterInit23a(struct dm_odm_t *pDM_Odm);
-
-void odm_TXPowerTrackingInit23a(struct dm_odm_t *pDM_Odm);
-
-void odm_TXPowerTrackingCheckCE23a(struct dm_odm_t *pDM_Odm);
+static void odm_TXPowerTrackingInit(struct dm_odm_t *pDM_Odm);
 
 static void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm);
 static void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm);
@@ -216,16 +207,16 @@ static void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm);
 #define        RxDefaultAnt2           0x569a
 
 bool odm_StaDefAntSel(struct dm_odm_t *pDM_Odm,
- u32 OFDM_Ant1_Cnt,
- u32 OFDM_Ant2_Cnt,
- u32 CCK_Ant1_Cnt,
- u32 CCK_Ant2_Cnt,
- u8 *pDefAnt
      u32 OFDM_Ant1_Cnt,
      u32 OFDM_Ant2_Cnt,
      u32 CCK_Ant1_Cnt,
      u32 CCK_Ant2_Cnt,
      u8 *pDefAnt
        );
 
 void odm_SetRxIdleAnt(struct dm_odm_t *pDM_Odm,
        u8 Ant,
-   bool   bDualPath
+       bool   bDualPath
 );
 
 /* 3 Export Interface */
@@ -241,7 +232,7 @@ void ODM23a_DMInit(struct dm_odm_t *pDM_Odm)
 
        odm23a_DynBBPSInit(pDM_Odm);
        odm_DynamicTxPower23aInit(pDM_Odm);
-       odm_TXPowerTrackingInit23a(pDM_Odm);
+       odm_TXPowerTrackingInit(pDM_Odm);
        ODM_EdcaTurboInit23a(pDM_Odm);
 }
 
@@ -258,7 +249,7 @@ void ODM_DMWatchdog23a(struct rtw_adapter *adapter)
        odm_CmnInfoUpdate_Debug23a(pDM_Odm);
        odm_CommonInfoSelfUpdate(pHalData);
        odm_FalseAlarmCounterStatistics23a(pDM_Odm);
-       odm_RSSIMonitorCheck23a(pDM_Odm);
+       odm_RSSIMonitorCheck(pDM_Odm);
 
        /* 8723A or 8189ES platform */
        /* NeilChen--2012--08--24-- */
@@ -277,14 +268,11 @@ void ODM_DMWatchdog23a(struct rtw_adapter *adapter)
        if (pwrctrlpriv->bpower_saving)
                return;
 
-       odm_RefreshRateAdaptiveMask23a(pDM_Odm);
+       odm_RefreshRateAdaptiveMask(pDM_Odm);
 
        odm_DynamicBBPowerSaving23a(pDM_Odm);
 
-       ODM_TXPowerTrackingCheck23a(pDM_Odm);
        odm_EdcaTurboCheck23a(pDM_Odm);
-
-       odm_dtc(pDM_Odm);
 }
 
 /*  */
@@ -302,11 +290,6 @@ void ODM_CmnInfoInit23a(struct dm_odm_t *pDM_Odm,
        /*  */
        switch  (CmnInfo) {
        /*  Fixed ODM value. */
-       case    ODM_CMNINFO_PLATFORM:
-               break;
-       case    ODM_CMNINFO_INTERFACE:
-               pDM_Odm->SupportInterface = (u8)Value;
-               break;
        case    ODM_CMNINFO_MP_TEST_CHIP:
                pDM_Odm->bIsMPChip = (u8)Value;
                break;
@@ -319,9 +302,6 @@ void ODM_CmnInfoInit23a(struct dm_odm_t *pDM_Odm,
        case    ODM_CMNINFO_FAB_VER:
                pDM_Odm->FabVersion = (u8)Value;
                break;
-       case    ODM_CMNINFO_RF_TYPE:
-               pDM_Odm->RFType = (u8)Value;
-               break;
        case    ODM_CMNINFO_BOARD_TYPE:
                pDM_Odm->BoardType = (u8)Value;
                break;
@@ -334,9 +314,6 @@ void ODM_CmnInfoInit23a(struct dm_odm_t *pDM_Odm,
        case    ODM_CMNINFO_EXT_TRSW:
                pDM_Odm->ExtTRSW = (u8)Value;
                break;
-       case    ODM_CMNINFO_PATCH_ID:
-               pDM_Odm->PatchID = (u8)Value;
-               break;
        case    ODM_CMNINFO_BINHCT_TEST:
                pDM_Odm->bInHctTest = (bool)Value;
                break;
@@ -351,15 +328,6 @@ void ODM_CmnInfoInit23a(struct dm_odm_t *pDM_Odm,
                /* do nothing */
                break;
        }
-
-       /*  */
-       /*  Tx power tracking BB swing table. */
-       /*  The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */
-       /*  */
-       pDM_Odm->BbSwingIdxOfdm                 = 12; /*  Set defalut value as index 12. */
-       pDM_Odm->BbSwingIdxOfdmCurrent  = 12;
-       pDM_Odm->BbSwingFlagOfdm                = false;
-
 }
 
 void ODM_CmnInfoPtrArrayHook23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo CmnInfo,
@@ -383,9 +351,6 @@ void ODM_CmnInfoUpdate23a(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value)
 {
        /*  This init variable may be changed in run time. */
        switch  (CmnInfo) {
-       case    ODM_CMNINFO_RF_TYPE:
-               pDM_Odm->RFType = (u8)Value;
-               break;
        case    ODM_CMNINFO_WIFI_DIRECT:
                pDM_Odm->bWIFI_Direct = (bool)Value;
                break;
@@ -414,13 +379,18 @@ void ODM_CmnInfoUpdate23a(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value)
 
 }
 
-void odm_CommonInfoSelfInit23a(struct dm_odm_t *pDM_Odm
-       )
+void odm_CommonInfoSelfInit23a(struct dm_odm_t *pDM_Odm)
 {
-       pDM_Odm->bCckHighPower =
-               (bool) ODM_GetBBReg(pDM_Odm, rFPGA0_XA_HSSIParameter2, BIT(9));
+       u32 val32;
+
+       val32 = rtl8723au_read32(pDM_Odm->Adapter, rFPGA0_XA_HSSIParameter2);
+       if (val32 & BIT(9))
+               pDM_Odm->bCckHighPower = true;
+       else
+               pDM_Odm->bCckHighPower = false;
+               
        pDM_Odm->RFPathRxEnable =
-               (u8) ODM_GetBBReg(pDM_Odm, rOFDM0_TRxPathEnable, 0x0F);
+               rtl8723au_read32(pDM_Odm->Adapter, rOFDM0_TRxPathEnable) & 0x0F;
 
        ODM_InitDebugSetting23a(pDM_Odm);
 }
@@ -432,15 +402,6 @@ static void odm_CommonInfoSelfUpdate(struct hal_data_8723a *pHalData)
        u8 EntryCnt = 0;
        u8 i;
 
-       if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_40) {
-               if (pHalData->nCur40MhzPrimeSC == 1)
-                       pDM_Odm->ControlChannel = pHalData->CurrentChannel - 2;
-               else if (pHalData->nCur40MhzPrimeSC == 2)
-                       pDM_Odm->ControlChannel = pHalData->CurrentChannel + 2;
-       } else {
-               pDM_Odm->ControlChannel = pHalData->CurrentChannel;
-       }
-
        for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
                pEntry = pDM_Odm->pODM_StaInfo[i];
                if (pEntry)
@@ -456,16 +417,13 @@ void odm_CmnInfoInit_Debug23a(struct dm_odm_t *pDM_Odm)
 {
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoInit_Debug23a ==>\n"));
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportAbility = 0x%x\n", pDM_Odm->SupportAbility));
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportInterface =%d\n", pDM_Odm->SupportInterface));
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportICType = 0x%x\n", pDM_Odm->SupportICType));
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("CutVersion =%d\n", pDM_Odm->CutVersion));
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("FabVersion =%d\n", pDM_Odm->FabVersion));
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RFType =%d\n", pDM_Odm->RFType));
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("BoardType =%d\n", pDM_Odm->BoardType));
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtLNA =%d\n", pDM_Odm->ExtLNA));
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtPA =%d\n", pDM_Odm->ExtPA));
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtTRSW =%d\n", pDM_Odm->ExtTRSW));
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("PatchID =%d\n", pDM_Odm->PatchID));
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bInHctTest =%d\n", pDM_Odm->bInHctTest));
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFITest =%d\n", pDM_Odm->bWIFITest));
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bDualMacSmartConcurrent =%d\n", pDM_Odm->bDualMacSmartConcurrent));
@@ -481,18 +439,19 @@ void odm_CmnInfoUpdate_Debug23a(struct dm_odm_t *pDM_Odm)
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RSSI_Min =%d\n", pDM_Odm->RSSI_Min));
 }
 
-void ODM_Write_DIG23a(struct dm_odm_t *pDM_Odm,
-       u8 CurrentIGI
-       )
+void ODM_Write_DIG23a(struct dm_odm_t *pDM_Odm,        u8 CurrentIGI)
 {
+       struct rtw_adapter *adapter = pDM_Odm->Adapter;
        struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
-
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("ODM_REG(IGI_A, pDM_Odm) = 0x%x, ODM_BIT(IGI, pDM_Odm) = 0x%x \n",
-               ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm)));
+       u32 val32;
 
        if (pDM_DigTable->CurIGValue != CurrentIGI) {
-               ODM_SetBBReg(pDM_Odm, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
-               ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("CurrentIGI(0x%02x). \n", CurrentIGI));
+               val32 = rtl8723au_read32(adapter, ODM_REG_IGI_A_11N);
+               val32 &= ~ODM_BIT_IGI_11N;
+               val32 |= CurrentIGI;
+               rtl8723au_write32(adapter, ODM_REG_IGI_A_11N, val32);
+               ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
+                            ("CurrentIGI(0x%02x). \n", CurrentIGI));
                pDM_DigTable->CurIGValue = CurrentIGI;
        }
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
@@ -515,11 +474,10 @@ void odm_DIG23abyRSSI_LPS(struct dm_odm_t *pDM_Odm)
        CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG;
        bFwCurrentInPSMode = pAdapter->pwrctrlpriv.bFwCurrentInPSMode;
 
-       /* ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG_LPS, ODM_DBG_LOUD, ("odm_DIG23a() ==>\n")); */
-
        /*  Using FW PS mode to make IGI */
        if (bFwCurrentInPSMode) {
-               ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("---Neil---odm_DIG23a is in LPS mode\n"));
+               ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
+                            ("---Neil---odm_DIG23a is in LPS mode\n"));
                /* Adjust by  FA in LPS MODE */
                if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS)
                        CurrentIGI = CurrentIGI+2;
@@ -545,15 +503,17 @@ void odm_DIG23abyRSSI_LPS(struct dm_odm_t *pDM_Odm)
         else if (CurrentIGI < RSSI_Lower)
                CurrentIGI = RSSI_Lower;
 
-       ODM_Write_DIG23a(pDM_Odm, CurrentIGI);/* ODM_Write_DIG23a(pDM_Odm, pDM_DigTable->CurIGValue); */
-
+       ODM_Write_DIG23a(pDM_Odm, CurrentIGI);
 }
 
 void odm_DIG23aInit(struct dm_odm_t *pDM_Odm)
 {
        struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
+       u32 val32;
+
+       val32 = rtl8723au_read32(pDM_Odm->Adapter, ODM_REG_IGI_A_11N);
+       pDM_DigTable->CurIGValue = val32 & ODM_BIT_IGI_11N;
 
-       pDM_DigTable->CurIGValue = (u8) ODM_GetBBReg(pDM_Odm, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm));
        pDM_DigTable->RssiLowThresh     = DM_DIG_THRESH_LOW;
        pDM_DigTable->RssiHighThresh    = DM_DIG_THRESH_HIGH;
        pDM_DigTable->FALowThresh       = DM_FALSEALARM_THRESH_LOW;
@@ -591,26 +551,22 @@ void odm_DIG23a(struct rtw_adapter *adapter)
        u8 dm_dig_max, dm_dig_min;
        u8 CurrentIGI = pDM_DigTable->CurIGValue;
 
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a() ==>\n"));
-       /* if (!(pDM_Odm->SupportAbility & (ODM_BB_DIG|ODM_BB_FA_CNT))) */
-       if ((!(pDM_Odm->SupportAbility&ODM_BB_DIG)) || (!(pDM_Odm->SupportAbility&ODM_BB_FA_CNT))) {
-               ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
-                            ("odm_DIG23a() Return: SupportAbility ODM_BB_DIG or ODM_BB_FA_CNT is disabled\n"));
-               return;
-       }
-
+       ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
+                    ("odm_DIG23a() ==>\n"));
        if (adapter->mlmepriv.bScanInProcess) {
-               ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a() Return: In Scan Progress \n"));
+               ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
+                            ("odm_DIG23a() Return: In Scan Progress \n"));
                return;
        }
 
        DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0;
        FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_0);
-       FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0);
+       FirstDisConnect = (!pDM_Odm->bLinked) &&
+               (pDM_DigTable->bMediaConnect_0);
 
        /* 1 Boundary Decision */
        if ((pDM_Odm->SupportICType & ODM_RTL8723A) &&
-           ((pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) || pDM_Odm->ExtLNA)) {
+           (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR || pDM_Odm->ExtLNA)) {
                dm_dig_max = DM_DIG_MAX_NIC_HP;
                dm_dig_min = DM_DIG_MIN_NIC_HP;
                DIG_MaxOfMin = DM_DIG_MAX_AP_HP;
@@ -764,31 +720,29 @@ void odm_DIG23a(struct rtw_adapter *adapter)
 
 void odm_FalseAlarmCounterStatistics23a(struct dm_odm_t *pDM_Odm)
 {
-       u32 ret_value;
+       struct rtw_adapter *adapter = pDM_Odm->Adapter;
        struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
-
-       if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
-               return;
+       u32 ret_value, val32;
 
        /* hold ofdm counter */
-        /* hold page C counter */
-       ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1);
+       /* hold page C counter */
+       val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_HOLDC_11N);
+       val32 |= BIT(31);
+       rtl8723au_write32(adapter, ODM_REG_OFDM_FA_HOLDC_11N, val32);
        /* hold page D counter */
-       ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 1);
-       ret_value =
-               ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord);
+       val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTD_11N);
+       val32 |= BIT(31);
+       rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTD_11N, val32);
+       ret_value = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_TYPE1_11N);
        FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
-       FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16);
-       ret_value =
-               ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord);
+       FalseAlmCnt->Cnt_SB_Search_fail = (ret_value & 0xffff0000)>>16;
+       ret_value = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_TYPE2_11N);
        FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff);
-       FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16);
-       ret_value =
-               ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord);
+       FalseAlmCnt->Cnt_Parity_Fail = (ret_value & 0xffff0000)>>16;
+       ret_value = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_TYPE3_11N);
        FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
-       FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16);
-       ret_value =
-               ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord);
+       FalseAlmCnt->Cnt_Crc8_fail = (ret_value & 0xffff0000)>>16;
+       ret_value = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_TYPE4_11N);
        FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
 
        FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail +
@@ -798,15 +752,16 @@ void odm_FalseAlarmCounterStatistics23a(struct dm_odm_t *pDM_Odm)
                FalseAlmCnt->Cnt_Fast_Fsync +
                FalseAlmCnt->Cnt_SB_Search_fail;
        /* hold cck counter */
-       ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT(12), 1);
-       ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT(14), 1);
+       val32 = rtl8723au_read32(adapter, ODM_REG_CCK_FA_RST_11N);
+       val32 |= (BIT(12) | BIT(14));
+       rtl8723au_write32(adapter, ODM_REG_CCK_FA_RST_11N, val32);
 
-       ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_LSB_11N, bMaskByte0);
+       ret_value = rtl8723au_read32(adapter, ODM_REG_CCK_FA_LSB_11N) & 0xff;
        FalseAlmCnt->Cnt_Cck_fail = ret_value;
-       ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_MSB_11N, bMaskByte3);
-       FalseAlmCnt->Cnt_Cck_fail +=  (ret_value & 0xff) << 8;
+       ret_value = rtl8723au_read32(adapter, ODM_REG_CCK_FA_MSB_11N) >> 16;
+       FalseAlmCnt->Cnt_Cck_fail += (ret_value & 0xff00);
 
-       ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord);
+       ret_value = rtl8723au_read32(adapter, ODM_REG_CCK_CCA_CNT_11N);
        FalseAlmCnt->Cnt_CCK_CCA =
                ((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8);
 
@@ -823,26 +778,39 @@ void odm_FalseAlarmCounterStatistics23a(struct dm_odm_t *pDM_Odm)
 
        if (pDM_Odm->SupportICType >= ODM_RTL8723A) {
                /* reset false alarm counter registers */
-               ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTC_11N, BIT(31), 1);
-               ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTC_11N, BIT(31), 0);
-               ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(27), 1);
-               ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(27), 0);
+               val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTC_11N);
+               val32 |= BIT(31);
+               rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTC_11N, val32);
+               val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTC_11N);
+               val32 &= ~BIT(31);
+               rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTC_11N, val32);
+
+               val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTD_11N);
+               val32 |= BIT(27);
+               rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTD_11N, val32);
+               val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTD_11N);
+               val32 &= ~BIT(27);
+               rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTD_11N, val32);
+
                /* update ofdm counter */
                 /* update page C counter */
-               ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0);
+               val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_HOLDC_11N);
+               val32 &= ~BIT(31);
+               rtl8723au_write32(adapter, ODM_REG_OFDM_FA_HOLDC_11N, val32);
+
                 /* update page D counter */
-               ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 0);
+               val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTD_11N);
+               val32 &= ~BIT(31);
+               rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTD_11N, val32);
 
                /* reset CCK CCA counter */
-               ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N,
-                            BIT(13) | BIT(12), 0);
-               ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N,
-                            BIT(13) | BIT(12), 2);
-               /* reset CCK FA counter */
-               ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N,
-                            BIT(15) | BIT(14), 0);
-               ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N,
-                            BIT(15) | BIT(14), 2);
+               val32 = rtl8723au_read32(adapter, ODM_REG_CCK_FA_RST_11N);
+               val32 &= ~(BIT(12) | BIT(13) | BIT(14) | BIT(15));
+               rtl8723au_write32(adapter, ODM_REG_CCK_FA_RST_11N, val32);
+
+               val32 = rtl8723au_read32(adapter, ODM_REG_CCK_FA_RST_11N);
+               val32 |= (BIT(13) | BIT(15));
+               rtl8723au_write32(adapter, ODM_REG_CCK_FA_RST_11N, val32);
        }
 
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD,
@@ -859,9 +827,12 @@ void odm_FalseAlarmCounterStatistics23a(struct dm_odm_t *pDM_Odm)
                     ("Cnt_Crc8_fail =%d, Cnt_Mcs_fail =%d\n",
                      FalseAlmCnt->Cnt_Crc8_fail, FalseAlmCnt->Cnt_Mcs_fail));
 
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Cck_fail =%d\n", FalseAlmCnt->Cnt_Cck_fail));
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Ofdm_fail =%d\n", FalseAlmCnt->Cnt_Ofdm_fail));
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Total False Alarm =%d\n", FalseAlmCnt->Cnt_all));
+       ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD,
+                    ("Cnt_Cck_fail =%d\n", FalseAlmCnt->Cnt_Cck_fail));
+       ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD,
+                    ("Cnt_Ofdm_fail =%d\n", FalseAlmCnt->Cnt_Ofdm_fail));
+       ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD,
+                    ("Total False Alarm =%d\n", FalseAlmCnt->Cnt_all));
 }
 
 /* 3 ============================================================ */
@@ -873,16 +844,13 @@ void odm_CCKPacketDetectionThresh23a(struct dm_odm_t *pDM_Odm)
        struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
        u8 CurCCK_CCAThres;
 
-       if (!(pDM_Odm->SupportAbility & (ODM_BB_CCK_PD|ODM_BB_FA_CNT)))
-               return;
-
        if (pDM_Odm->ExtLNA)
                return;
 
        if (pDM_Odm->bLinked) {
                if (pDM_Odm->RSSI_Min > 25) {
                        CurCCK_CCAThres = 0xcd;
-               } else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10)) {
+               } else if (pDM_Odm->RSSI_Min <= 25 && pDM_Odm->RSSI_Min > 10) {
                        CurCCK_CCAThres = 0x83;
                } else {
                        if (FalseAlmCnt->Cnt_Cck_fail > 1000)
@@ -905,10 +873,10 @@ void ODM_Write_CCK_CCA_Thres23a(struct dm_odm_t *pDM_Odm, u8 CurCCK_CCAThres)
        struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
 
        if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres)
-               ODM_Write1Byte(pDM_Odm, ODM_REG(CCK_CCA, pDM_Odm), CurCCK_CCAThres);
+               rtl8723au_write8(pDM_Odm->Adapter, ODM_REG(CCK_CCA, pDM_Odm),
+                                CurCCK_CCAThres);
        pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
        pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
-
 }
 
 /* 3 ============================================================ */
@@ -934,20 +902,19 @@ void odm_DynamicBBPowerSaving23a(struct dm_odm_t *pDM_Odm)
 void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal)
 {
        struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable;
+       struct rtw_adapter *adapter = pDM_Odm->Adapter;
+       u32 val32;
        u8 Rssi_Up_bound = 30;
        u8 Rssi_Low_bound = 25;
-       if (pDM_Odm->PatchID == 40) { /* RT_CID_819x_FUNAI_TV */
-               Rssi_Up_bound = 50;
-               Rssi_Low_bound = 45;
-       }
        if (pDM_PSTable->initialize == 0) {
 
-               pDM_PSTable->Reg874 = (ODM_GetBBReg(pDM_Odm, 0x874, bMaskDWord)&0x1CC000)>>14;
+               pDM_PSTable->Reg874 =
+                       rtl8723au_read32(adapter, 0x874) & 0x1CC000;
                pDM_PSTable->RegC70 =
-                       (ODM_GetBBReg(pDM_Odm, 0xc70, bMaskDWord) & BIT(3)) >>3;
-               pDM_PSTable->Reg85C = (ODM_GetBBReg(pDM_Odm, 0x85c, bMaskDWord)&0xFF000000)>>24;
-               pDM_PSTable->RegA74 = (ODM_GetBBReg(pDM_Odm, 0xa74, bMaskDWord)&0xF000)>>12;
-               /* Reg818 = PHY_QueryBBReg(pAdapter, 0x818, bMaskDWord); */
+                       rtl8723au_read32(adapter, 0xc70) & BIT(3);
+               pDM_PSTable->Reg85C =
+                       rtl8723au_read32(adapter, 0x85c) & 0xFF000000;
+               pDM_PSTable->RegA74 = rtl8723au_read32(adapter, 0xa74) & 0xF000;
                pDM_PSTable->initialize = 1;
        }
 
@@ -973,26 +940,74 @@ void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal)
 
        if (pDM_PSTable->PreRFState != pDM_PSTable->CurRFState) {
                if (pDM_PSTable->CurRFState == RF_Save) {
-                       /*  <tynli_note> 8723 RSSI report will be wrong. Set 0x874[5]= 1 when enter BB power saving mode. */
+                       /*  <tynli_note> 8723 RSSI report will be wrong.
+                        * Set 0x874[5]= 1 when enter BB power saving mode. */
                        /*  Suggested by SD3 Yu-Nan. 2011.01.20. */
-                       if (pDM_Odm->SupportICType == ODM_RTL8723A)
-                               ODM_SetBBReg(pDM_Odm, 0x874, BIT(5), 0x1); /* Reg874[5]= 1b'1 */
-                       ODM_SetBBReg(pDM_Odm, 0x874, 0x1C0000, 0x2); /* Reg874[20:18]= 3'b010 */
-                       ODM_SetBBReg(pDM_Odm, 0xc70, BIT(3), 0); /* RegC70[3]= 1'b0 */
-                       ODM_SetBBReg(pDM_Odm, 0x85c, 0xFF000000, 0x63); /* Reg85C[31:24]= 0x63 */
-                       ODM_SetBBReg(pDM_Odm, 0x874, 0xC000, 0x2); /* Reg874[15:14]= 2'b10 */
-                       ODM_SetBBReg(pDM_Odm, 0xa74, 0xF000, 0x3); /* RegA75[7:4]= 0x3 */
-                       ODM_SetBBReg(pDM_Odm, 0x818, BIT(28), 0x0); /* Reg818[28]= 1'b0 */
-                       ODM_SetBBReg(pDM_Odm, 0x818, BIT(28), 0x1); /* Reg818[28]= 1'b1 */
+                       /* Reg874[5]= 1b'1 */
+                       if (pDM_Odm->SupportICType == ODM_RTL8723A) {
+                               val32 = rtl8723au_read32(adapter, 0x874);
+                               val32 |= BIT(5);
+                               rtl8723au_write32(adapter, 0x874, val32);
+                       }
+                       /* Reg874[20:18]= 3'b010 */
+                       val32 = rtl8723au_read32(adapter, 0x874);
+                       val32 &= ~(BIT(18) | BIT(20));
+                       val32 |= BIT(19);
+                       rtl8723au_write32(adapter, 0x874, val32);
+                       /* RegC70[3]= 1'b0 */
+                       val32 = rtl8723au_read32(adapter, 0xc70);
+                       val32 &= ~BIT(3);
+                       rtl8723au_write32(adapter, 0xc70, val32);
+                       /* Reg85C[31:24]= 0x63 */
+                       val32 = rtl8723au_read32(adapter, 0x85c);
+                       val32 &= 0x00ffffff;
+                       val32 |= 0x63000000;
+                       rtl8723au_write32(adapter, 0x85c, val32);
+                       /* Reg874[15:14]= 2'b10 */
+                       val32 = rtl8723au_read32(adapter, 0x874);
+                       val32 &= ~BIT(14);
+                       val32 |= BIT(15);
+                       rtl8723au_write32(adapter, 0x874, val32);
+                       /* RegA75[7:4]= 0x3 */
+                       val32 = rtl8723au_read32(adapter, 0xa74);
+                       val32 &= ~(BIT(14) | BIT(15));
+                       val32 |= (BIT(12) | BIT(13));
+                       rtl8723au_write32(adapter, 0xa74, val32);
+                       /* Reg818[28]= 1'b0 */
+                       val32 = rtl8723au_read32(adapter, 0x818);
+                       val32 &= ~BIT(28);
+                       rtl8723au_write32(adapter, 0x818, val32);
+                       /* Reg818[28]= 1'b1 */
+                       val32 = rtl8723au_read32(adapter, 0x818);
+                       val32 |= BIT(28);
+                       rtl8723au_write32(adapter, 0x818, val32);
                } else {
-                       ODM_SetBBReg(pDM_Odm, 0x874, 0x1CC000, pDM_PSTable->Reg874);
-                       ODM_SetBBReg(pDM_Odm, 0xc70, BIT(3), pDM_PSTable->RegC70);
-                       ODM_SetBBReg(pDM_Odm, 0x85c, 0xFF000000, pDM_PSTable->Reg85C);
-                       ODM_SetBBReg(pDM_Odm, 0xa74, 0xF000, pDM_PSTable->RegA74);
-                       ODM_SetBBReg(pDM_Odm, 0x818, BIT(28), 0x0);
-
-                       if (pDM_Odm->SupportICType == ODM_RTL8723A)
-                               ODM_SetBBReg(pDM_Odm, 0x874, BIT(5), 0x0); /* Reg874[5]= 1b'0 */
+                       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);
+
+                       val32 = rtl8723au_read32(adapter, 0x85c);
+                       val32 |= pDM_PSTable->Reg85C;
+                       rtl8723au_write32(adapter, 0x85c, val32);
+
+                       val32 = rtl8723au_read32(adapter, 0xa74);
+                       val32 |= pDM_PSTable->RegA74;
+                       rtl8723au_write32(adapter, 0xa74, val32);
+
+                       val32 = rtl8723au_read32(adapter, 0x818);
+                       val32 &= ~BIT(28);
+                       rtl8723au_write32(adapter, 0x818, val32);
+
+                       /* Reg874[5]= 1b'0 */
+                       if (pDM_Odm->SupportICType == ODM_RTL8723A) {
+                               val32 = rtl8723au_read32(adapter, 0x874);
+                               val32 &= ~BIT(5);
+                               rtl8723au_write32(adapter, 0x874, val32);
+                       }
                }
                pDM_PSTable->PreRFState = pDM_PSTable->CurRFState;
        }
@@ -1010,10 +1025,6 @@ void odm_RateAdaptiveMaskInit23a(struct dm_odm_t *pDM_Odm)
        struct odm_rate_adapt *pOdmRA = &pDM_Odm->RateAdaptive;
 
        pOdmRA->Type = DM_Type_ByDriver;
-       if (pOdmRA->Type == DM_Type_ByDriver)
-               pDM_Odm->bUseRAMask = true;
-       else
-               pDM_Odm->bUseRAMask = false;
 
        pOdmRA->RATRState = DM_RATR_STA_INIT;
        pOdmRA->HighRSSIThresh = 50;
@@ -1057,7 +1068,8 @@ u32 ODM_Get_Rate_Bitmap23a(struct hal_data_8723a *pHalData, u32 macid,
                break;
        case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G):
        case (ODM_WM_A|ODM_WM_B|ODM_WM_G|ODM_WM_N24G):
-               if (pDM_Odm->RFType == ODM_1T2R || pDM_Odm->RFType == ODM_1T1R) {
+               if (pHalData->rf_type == RF_1T2R ||
+                   pHalData->rf_type == RF_1T1R) {
                        if (rssi_level == DM_RATR_STA_HIGH) {
                                rate_bitmap = 0x000f0000;
                        } else if (rssi_level == DM_RATR_STA_MIDDLE) {
@@ -1086,22 +1098,22 @@ u32 ODM_Get_Rate_Bitmap23a(struct hal_data_8723a *pHalData, u32 macid,
        default:
                /* case WIRELESS_11_24N: */
                /* case WIRELESS_11_5N: */
-               if (pDM_Odm->RFType == RF_1T2R)
+               if (pHalData->rf_type == RF_1T2R)
                        rate_bitmap = 0x000fffff;
                else
                        rate_bitmap = 0x0fffffff;
                break;
        }
 
-       /* printk("%s ==> rssi_level:0x%02x, WirelessMode:0x%02x, rate_bitmap:0x%08x \n", __func__, rssi_level, WirelessMode, rate_bitmap); */
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, (" ==> rssi_level:0x%02x, WirelessMode:0x%02x, rate_bitmap:0x%08x \n", rssi_level, WirelessMode, rate_bitmap));
+       ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD,
+       (" ==> rssi_level:0x%02x, WirelessMode:0x%02x, rate_bitmap:0x%08x \n",
+        rssi_level, WirelessMode, rate_bitmap));
 
        return rate_bitmap;
-
 }
 
 /*-----------------------------------------------------------------------------
- * Function:   odm_RefreshRateAdaptiveMask23a()
+ * Function:   odm_RefreshRateAdaptiveMask()
  *
  * Overview:   Update rate table mask according to rssi
  *
@@ -1116,51 +1128,35 @@ u32 ODM_Get_Rate_Bitmap23a(struct hal_data_8723a *pHalData, u32 macid,
  *05/27/2009   hpfan   Create Version 0.
  *
  *---------------------------------------------------------------------------*/
-void odm_RefreshRateAdaptiveMask23a(struct dm_odm_t *pDM_Odm)
-{
-       if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK))
-               return;
-       /*  */
-       /*  2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
-       /*  at the same time. In the stage2/3, we need to prive universal interface and merge all */
-       /*  HW dynamic mechanism. */
-       /*  */
-       odm_RefreshRateAdaptiveMask23aCE23a(pDM_Odm);
-}
-
-void odm_RefreshRateAdaptiveMask23aCE23a(struct dm_odm_t *pDM_Odm)
+static void odm_RefreshRateAdaptiveMask(struct dm_odm_t *pDM_Odm)
 {
+       struct rtw_adapter *pAdapter = pDM_Odm->Adapter;
+       u32 smoothed;
        u8 i;
-       struct rtw_adapter *pAdapter     =  pDM_Odm->Adapter;
 
        if (pAdapter->bDriverStopped) {
                ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_TRACE,
-                            ("<---- odm_RefreshRateAdaptiveMask23a(): driver is going to unload\n"));
+                            ("<---- %s: driver is going to unload\n",
+                             __func__));
                return;
        }
 
-       if (!pDM_Odm->bUseRAMask) {
-               ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD,
-                            ("<---- odm_RefreshRateAdaptiveMask23a(): driver does not control rate adaptive mask\n"));
-               return;
-       }
-
-       /* printk("==> %s \n", __func__); */
-
        for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
                struct sta_info *pstat = pDM_Odm->pODM_StaInfo[i];
                if (pstat) {
-                       if (ODM_RAStateCheck23a(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) {
-                               ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD,
+                       smoothed = pstat->rssi_stat.UndecoratedSmoothedPWDB;
+                       if (ODM_RAStateCheck23a(pDM_Odm, smoothed, false,
+                                               &pstat->rssi_level)) {
+                               ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK,
+                                            ODM_DBG_LOUD,
                                             ("RSSI:%d, RSSI_LEVEL:%d\n",
-                                            pstat->rssi_stat.UndecoratedSmoothedPWDB,
-                                            pstat->rssi_level));
-                               rtw_hal_update_ra_mask23a(pstat, pstat->rssi_level);
+                                             smoothed,
+                                             pstat->rssi_level));
+                               rtw_hal_update_ra_mask23a(pstat,
+                                                         pstat->rssi_level);
                        }
-
                }
        }
-
 }
 
 /*  Return Value: bool */
@@ -1189,7 +1185,8 @@ bool ODM_RAStateCheck23a(struct dm_odm_t *pDM_Odm, s32 RSSI, bool bForceUpdate,
                LowRSSIThreshForRA += GoUpGap;
                break;
        default:
-               ODM_RT_ASSERT(pDM_Odm, false, ("wrong rssi level setting %d !", *pRATRState));
+               ODM_RT_ASSERT(pDM_Odm, false, ("wrong rssi level setting %d !",
+                                              *pRATRState));
                break;
        }
 
@@ -1227,24 +1224,8 @@ void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm)
        pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal;
 }
 
-void odm_RSSIMonitorCheck23a(struct dm_odm_t *pDM_Odm)
-{
-       /*  For AP/ADSL use struct rtl8723a_priv * */
-       /*  For CE/NIC use struct rtw_adapter * */
-
-       if (!(pDM_Odm->SupportAbility & ODM_BB_RSSI_MONITOR))
-               return;
-
-       /*  2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
-       /*  at the same time. In the stage2/3, we need to prive universal interface and merge all */
-       /*  HW dynamic mechanism. */
-       odm_RSSIMonitorCheck23aCE(pDM_Odm);
-}      /*  odm_RSSIMonitorCheck23a */
-
 static void
-FindMinimumRSSI(
-       struct rtw_adapter *pAdapter
-       )
+FindMinimumRSSI(struct rtw_adapter *pAdapter)
 {
        struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
        struct dm_priv *pdmpriv = &pHalData->dmpriv;
@@ -1252,21 +1233,22 @@ FindMinimumRSSI(
 
        /* 1 1.Determine the minimum RSSI */
 
-       if ((!pDM_Odm->bLinked) &&
-           (pdmpriv->EntryMinUndecoratedSmoothedPWDB == 0))
+       if (!pDM_Odm->bLinked && !pdmpriv->EntryMinUndecoratedSmoothedPWDB)
                pdmpriv->MinUndecoratedPWDBForDM = 0;
        else
-               pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB;
+               pdmpriv->MinUndecoratedPWDBForDM =
+                       pdmpriv->EntryMinUndecoratedSmoothedPWDB;
 }
 
-void odm_RSSIMonitorCheck23aCE(struct dm_odm_t *pDM_Odm)
+static void odm_RSSIMonitorCheck(struct dm_odm_t *pDM_Odm)
 {
        struct rtw_adapter *Adapter = pDM_Odm->Adapter;
        struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
        struct dm_priv *pdmpriv = &pHalData->dmpriv;
-       int     i;
-       int     tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff;
+       int i;
+       int MaxDB = 0, MinDB = 0xff;
        u8 sta_cnt = 0;
+       u32 tmpdb;
        u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */
        struct sta_info *psta;
 
@@ -1276,37 +1258,36 @@ void odm_RSSIMonitorCheck23aCE(struct dm_odm_t *pDM_Odm)
        for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
                psta = pDM_Odm->pODM_StaInfo[i];
                if (psta) {
-                       if (psta->rssi_stat.UndecoratedSmoothedPWDB < tmpEntryMinPWDB)
-                               tmpEntryMinPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
+                       if (psta->rssi_stat.UndecoratedSmoothedPWDB < MinDB)
+                               MinDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
 
-                       if (psta->rssi_stat.UndecoratedSmoothedPWDB > tmpEntryMaxPWDB)
-                               tmpEntryMaxPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
+                       if (psta->rssi_stat.UndecoratedSmoothedPWDB > MaxDB)
+                               MaxDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
 
-                       if (psta->rssi_stat.UndecoratedSmoothedPWDB != (-1))
-                               PWDB_rssi[sta_cnt++] = (psta->mac_id | (psta->rssi_stat.UndecoratedSmoothedPWDB<<16));
+                       if (psta->rssi_stat.UndecoratedSmoothedPWDB != -1) {
+                               tmpdb = psta->rssi_stat.UndecoratedSmoothedPWDB;
+                               PWDB_rssi[sta_cnt++] = psta->mac_id |
+                                       (tmpdb << 16);
+                       }
                }
        }
 
        for (i = 0; i < sta_cnt; i++) {
-               if (PWDB_rssi[i] != (0)) {
-                       if (pHalData->fw_ractrl) /*  Report every sta's RSSI to FW */
-                               rtl8723a_set_rssi_cmd(Adapter, (u8 *)&PWDB_rssi[i]);
-               }
+               if (PWDB_rssi[i] != (0))
+                       rtl8723a_set_rssi_cmd(Adapter, (u8 *)&PWDB_rssi[i]);
        }
 
-       if (tmpEntryMaxPWDB != 0)       /*  If associated entry is found */
-               pdmpriv->EntryMaxUndecoratedSmoothedPWDB = tmpEntryMaxPWDB;
-       else
-               pdmpriv->EntryMaxUndecoratedSmoothedPWDB = 0;
+       pdmpriv->EntryMaxUndecoratedSmoothedPWDB = MaxDB;
 
-       if (tmpEntryMinPWDB != 0xff) /*  If associated entry is found */
-               pdmpriv->EntryMinUndecoratedSmoothedPWDB = tmpEntryMinPWDB;
+       if (MinDB != 0xff) /*  If associated entry is found */
+               pdmpriv->EntryMinUndecoratedSmoothedPWDB = MinDB;
        else
                pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0;
 
        FindMinimumRSSI(Adapter);/* get pdmpriv->MinUndecoratedPWDBForDM */
 
-       ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_RSSI_MIN, pdmpriv->MinUndecoratedPWDBForDM);
+       ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_RSSI_MIN,
+                            pdmpriv->MinUndecoratedPWDBForDM);
 }
 
 /* endif */
@@ -1314,12 +1295,7 @@ void odm_RSSIMonitorCheck23aCE(struct dm_odm_t *pDM_Odm)
 /* 3 Tx Power Tracking */
 /* 3 ============================================================ */
 
-void odm_TXPowerTrackingInit23a(struct dm_odm_t *pDM_Odm)
-{
-       odm_TXPowerTrackingThermalMeterInit23a(pDM_Odm);
-}
-
-void odm_TXPowerTrackingThermalMeterInit23a(struct dm_odm_t *pDM_Odm)
+static void odm_TXPowerTrackingInit(struct dm_odm_t *pDM_Odm)
 {
        struct rtw_adapter *Adapter = pDM_Odm->Adapter;
        struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
@@ -1329,42 +1305,33 @@ void odm_TXPowerTrackingThermalMeterInit23a(struct dm_odm_t *pDM_Odm)
        pdmpriv->TXPowercount = 0;
        pdmpriv->bTXPowerTrackingInit = false;
        pdmpriv->TxPowerTrackControl = true;
-       MSG_8723A("pdmpriv->TxPowerTrackControl = %d\n", pdmpriv->TxPowerTrackControl);
+       MSG_8723A("pdmpriv->TxPowerTrackControl = %d\n",
+                 pdmpriv->TxPowerTrackControl);
 
        pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true;
 }
 
-void ODM_TXPowerTrackingCheck23a(struct dm_odm_t *pDM_Odm)
-{
-       /*  For AP/ADSL use struct rtl8723a_priv * */
-       /*  For CE/NIC use struct rtw_adapter * */
-
-       /*  2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
-       /*  at the same time. In the stage2/3, we need to prive universal interface and merge all */
-       /*  HW dynamic mechanism. */
-       odm_TXPowerTrackingCheckCE23a(pDM_Odm);
-}
-
-void odm_TXPowerTrackingCheckCE23a(struct dm_odm_t *pDM_Odm)
-{
-}
-
 /* EDCA Turbo */
 static void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm)
 {
-
        struct rtw_adapter *Adapter = pDM_Odm->Adapter;
 
        pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
-       pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false;
        Adapter->recvpriv.bIsAnyNonBEPkts = false;
 
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VO PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_VO_PARAM)));
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VI PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_VI_PARAM)));
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BE PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_BE_PARAM)));
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BK PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_BK_PARAM)));
-
-}      /*  ODM_InitEdcaTurbo */
+       ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD,
+                    ("Orginial VO PARAM: 0x%x\n",
+                     rtl8723au_read32(Adapter, ODM_EDCA_VO_PARAM)));
+       ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD,
+                    ("Orginial VI PARAM: 0x%x\n",
+                     rtl8723au_read32(Adapter, ODM_EDCA_VI_PARAM)));
+       ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD,
+                    ("Orginial BE PARAM: 0x%x\n",
+                     rtl8723au_read32(Adapter, ODM_EDCA_BE_PARAM)));
+       ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD,
+                    ("Orginial BK PARAM: 0x%x\n",
+                     rtl8723au_read32(Adapter, ODM_EDCA_BK_PARAM)));
+}
 
 static void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm)
 {
@@ -1377,19 +1344,18 @@ static void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm)
        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
        u32 trafficIndex;
        u32 edca_param;
-       u64 cur_tx_bytes = 0;
-       u64 cur_rx_bytes = 0;
-       u8 bbtchange = false;
+       u64 cur_tx_bytes;
+       u64 cur_rx_bytes;
 
        /*  For AP/ADSL use struct rtl8723a_priv * */
        /*  For CE/NIC use struct rtw_adapter * */
 
-       /*  2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
-       /*  at the same time. In the stage2/3, we need to prive universal interface and merge all */
-       /*  HW dynamic mechanism. */
-
-       if (!(pDM_Odm->SupportAbility & ODM_MAC_EDCA_TURBO))
-               return;
+       /*
+        * 2011/09/29 MH In HW integration first stage, we provide 4
+        * different handle to operate at the same time. In the stage2/3,
+        * we need to prive universal interface and merge all HW dynamic
+        * mechanism.
+        */
 
        if ((pregpriv->wifi_spec == 1))/*  (pmlmeinfo->HT_enable == 0)) */
                goto dm_CheckEdcaTurbo_EXIT;
@@ -1401,7 +1367,7 @@ static void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm)
                goto dm_CheckEdcaTurbo_EXIT;
 
        /*  Check if the status needs to be changed. */
-       if ((bbtchange) || (!precvpriv->bIsAnyNonBEPkts)) {
+       if (!precvpriv->bIsAnyNonBEPkts) {
                cur_tx_bytes = pxmitpriv->tx_bytes - pxmitpriv->last_tx_bytes;
                cur_rx_bytes = precvpriv->rx_bytes - precvpriv->last_rx_bytes;
 
@@ -1454,29 +1420,37 @@ dm_CheckEdcaTurbo_EXIT:
        precvpriv->last_rx_bytes = precvpriv->rx_bytes;
 }
 
-u32 GetPSDData(struct dm_odm_t *pDM_Odm, unsigned int point, u8 initial_gain_psd)
+u32 GetPSDData(struct dm_odm_t *pDM_Odm, unsigned int point,
+              u8 initial_gain_psd)
 {
-       u32 psd_report;
+       struct rtw_adapter *adapter = pDM_Odm->Adapter;
+       u32 psd_report, val32;
 
        /* Set DCO frequency index, offset = (40MHz/SamplePts)*point */
-       ODM_SetBBReg(pDM_Odm, 0x808, 0x3FF, point);
+       val32 = rtl8723au_read32(adapter, 0x808);
+       val32 &= ~0x3ff;
+       val32 |= (point & 0x3ff);
+       rtl8723au_write32(adapter, 0x808, val32);
 
        /* Start PSD calculation, Reg808[22]= 0->1 */
-       ODM_SetBBReg(pDM_Odm, 0x808, BIT(22), 1);
+       val32 = rtl8723au_read32(adapter, 0x808);
+       val32 |= BIT(22);
+       rtl8723au_write32(adapter, 0x808, val32);
        /* Need to wait for HW PSD report */
        udelay(30);
-       ODM_SetBBReg(pDM_Odm, 0x808, BIT(22), 0);
+       val32 = rtl8723au_read32(adapter, 0x808);
+       val32 &= ~BIT(22);
+       rtl8723au_write32(adapter, 0x808, val32);
        /* Read PSD report, Reg8B4[15:0] */
-       psd_report = ODM_GetBBReg(pDM_Odm, 0x8B4, bMaskDWord) & 0x0000FFFF;
+       psd_report = rtl8723au_read32(adapter, 0x8B4) & 0x0000FFFF;
 
-       psd_report = (u32)(ConvertTo_dB23a(psd_report))+(u32)(initial_gain_psd-0x1c);
+       psd_report = (u32)(ConvertTo_dB23a(psd_report)) +
+               (u32)(initial_gain_psd-0x1c);
 
        return psd_report;
 }
 
-u32
-ConvertTo_dB23a(
-       u32 Value)
+u32 ConvertTo_dB23a(u32 Value)
 {
        u8 i;
        u8 j;
@@ -1504,7 +1478,8 @@ ConvertTo_dB23a(
 
 /*  */
 /*  Description: */
-/*Set Single/Dual Antenna default setting for products that do not do detection in advance. */
+/* Set Single/Dual Antenna default setting for products that do not
+ * do detection in advance. */
 /*  */
 /*  Added by Joseph, 2012.03.22 */
 /*  */
@@ -1518,18 +1493,13 @@ void ODM_SingleDualAntennaDefaultSetting(struct dm_odm_t *pDM_Odm)
 
 /* 2 8723A ANT DETECT */
 
-static void odm_PHY_SaveAFERegisters(
-       struct dm_odm_t *pDM_Odm,
-       u32 *AFEReg,
-       u32 *AFEBackup,
-       u32 RegisterNum
-       )
+static void odm_PHY_SaveAFERegisters(struct dm_odm_t *pDM_Odm, u32 *AFEReg,
+                                    u32 *AFEBackup, u32 RegisterNum)
 {
        u32 i;
 
-       /* RTPRINT(FINIT, INIT_IQK, ("Save ADDA parameters.\n")); */
        for (i = 0 ; i < RegisterNum ; i++)
-               AFEBackup[i] = ODM_GetBBReg(pDM_Odm, AFEReg[i], bMaskDWord);
+               AFEBackup[i] = rtl8723au_read32(pDM_Odm->Adapter, AFEReg[i]);
 }
 
 static void odm_PHY_ReloadAFERegisters(struct dm_odm_t *pDM_Odm, u32 *AFEReg,
@@ -1538,7 +1508,7 @@ static void odm_PHY_ReloadAFERegisters(struct dm_odm_t *pDM_Odm, u32 *AFEReg,
        u32 i;
 
        for (i = 0 ; i < RegiesterNum; i++)
-               ODM_SetBBReg(pDM_Odm, AFEReg[i], bMaskDWord, AFEBackup[i]);
+               rtl8723au_write32(pDM_Odm->Adapter, AFEReg[i], AFEBackup[i]);
 }
 
 /* 2 8723A ANT DETECT */
@@ -1548,9 +1518,10 @@ static void odm_PHY_ReloadAFERegisters(struct dm_odm_t *pDM_Odm, u32 *AFEReg,
 bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode)
 {
        struct sw_ant_sw *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
+       struct rtw_adapter *adapter = pDM_Odm->Adapter;
        u32 CurrentChannel, RfLoopReg;
        u8 n;
-       u32 Reg88c, Regc08, Reg874, Regc50;
+       u32 Reg88c, Regc08, Reg874, Regc50, val32;
        u8 initial_gain = 0x5a;
        u32 PSD_report_tmp;
        u32 AntA_report = 0x0, AntB_report = 0x0, AntO_report = 0x0;
@@ -1573,72 +1544,80 @@ bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode)
                return bResult;
        /* 1 Backup Current RF/BB Settings */
 
-       CurrentChannel = ODM_GetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL, bRFRegOffsetMask);
+       CurrentChannel = ODM_GetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL,
+                                     bRFRegOffsetMask);
        RfLoopReg = ODM_GetRFReg(pDM_Odm, RF_PATH_A, 0x00, bRFRegOffsetMask);
-       ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, ODM_DPDT, Antenna_A);  /*  change to Antenna A */
+       /*  change to Antenna A */
+       val32 = rtl8723au_read32(adapter, rFPGA0_XA_RFInterfaceOE);
+       val32 &= ~0x300;
+       val32 |= 0x100;         /* Enable antenna A */
+       rtl8723au_write32(adapter, rFPGA0_XA_RFInterfaceOE, val32);
+
        /*  Step 1: USE IQK to transmitter single tone */
 
        udelay(10);
 
        /* Store A Path Register 88c, c08, 874, c50 */
-       Reg88c = ODM_GetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord);
-       Regc08 = ODM_GetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord);
-       Reg874 = ODM_GetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord);
-       Regc50 = ODM_GetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, bMaskDWord);
+       Reg88c = rtl8723au_read32(adapter, rFPGA0_AnalogParameter4);
+       Regc08 = rtl8723au_read32(adapter, rOFDM0_TRMuxPar);
+       Reg874 = rtl8723au_read32(adapter, rFPGA0_XCD_RFInterfaceSW);
+       Regc50 = rtl8723au_read32(adapter, rOFDM0_XAAGCCore1);
 
        /*  Store AFE Registers */
        odm_PHY_SaveAFERegisters(pDM_Odm, AFE_REG_8723A, AFE_Backup, 16);
 
        /* Set PSD 128 pts */
-       ODM_SetBBReg(pDM_Odm, rFPGA0_PSDFunction, BIT(14) | BIT(15), 0x0);
+       val32 = rtl8723au_read32(adapter, rFPGA0_PSDFunction);
+       val32 &= ~(BIT(14) | BIT(15));
+       rtl8723au_write32(adapter, rFPGA0_PSDFunction, val32);
 
        /*  To SET CH1 to do */
-       ODM_SetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL, bRFRegOffsetMask, 0x01);     /* Channel 1 */
+       ODM_SetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL, bRFRegOffsetMask, 0x01);
 
        /*  AFE all on step */
-       ODM_SetBBReg(pDM_Odm, rRx_Wait_CCA, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rTx_CCK_RFON, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rTx_CCK_BBON, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rTx_OFDM_RFON, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rTx_OFDM_BBON, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rTx_To_Rx, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rTx_To_Tx, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rRx_CCK, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rRx_OFDM, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rRx_Wait_RIFS, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rRx_TO_Rx, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rStandby, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rSleep, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rPMPD_ANAEN, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_SwitchControl, bMaskDWord, 0x6FDB25A4);
-       ODM_SetBBReg(pDM_Odm, rBlue_Tooth, bMaskDWord, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rRx_Wait_CCA, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rTx_CCK_RFON, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rTx_CCK_BBON, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rTx_OFDM_RFON, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rTx_OFDM_BBON, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rTx_To_Rx, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rTx_To_Tx, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rRx_CCK, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rRx_OFDM, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rRx_Wait_RIFS, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rRx_TO_Rx, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rStandby, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rSleep, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rPMPD_ANAEN, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rFPGA0_XCD_SwitchControl, 0x6FDB25A4);
+       rtl8723au_write32(adapter, rBlue_Tooth, 0x6FDB25A4);
 
        /*  3 wire Disable */
-       ODM_SetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord, 0xCCF000C0);
+       rtl8723au_write32(adapter, rFPGA0_AnalogParameter4, 0xCCF000C0);
 
        /* BB IQK Setting */
-       ODM_SetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord, 0x000800E4);
-       ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22208000);
+       rtl8723au_write32(adapter, rOFDM0_TRMuxPar, 0x000800E4);
+       rtl8723au_write32(adapter, rFPGA0_XCD_RFInterfaceSW, 0x22208000);
 
        /* IQK setting tone@ 4.34Mhz */
-       ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_A, bMaskDWord, 0x10008C1C);
-       ODM_SetBBReg(pDM_Odm, rTx_IQK, bMaskDWord, 0x01007c00);
+       rtl8723au_write32(adapter, rTx_IQK_Tone_A, 0x10008C1C);
+       rtl8723au_write32(adapter, rTx_IQK, 0x01007c00);
 
        /* Page B init */
-       ODM_SetBBReg(pDM_Odm, rConfig_AntA, bMaskDWord, 0x00080000);
-       ODM_SetBBReg(pDM_Odm, rConfig_AntA, bMaskDWord, 0x0f600000);
-       ODM_SetBBReg(pDM_Odm, rRx_IQK, bMaskDWord, 0x01004800);
-       ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_A, bMaskDWord, 0x10008c1f);
-       ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x82150008);
-       ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_A, bMaskDWord, 0x28150008);
-       ODM_SetBBReg(pDM_Odm, rIQK_AGC_Rsp, bMaskDWord, 0x001028d0);
+       rtl8723au_write32(adapter, rConfig_AntA, 0x00080000);
+       rtl8723au_write32(adapter, rConfig_AntA, 0x0f600000);
+       rtl8723au_write32(adapter, rRx_IQK, 0x01004800);
+       rtl8723au_write32(adapter, rRx_IQK_Tone_A, 0x10008c1f);
+       rtl8723au_write32(adapter, rTx_IQK_PI_A, 0x82150008);
+       rtl8723au_write32(adapter, rRx_IQK_PI_A, 0x28150008);
+       rtl8723au_write32(adapter, rIQK_AGC_Rsp, 0x001028d0);
 
        /* RF loop Setting */
        ODM_SetRFReg(pDM_Odm, RF_PATH_A, 0x0, 0xFFFFF, 0x50008);
 
        /* IQK Single tone start */
-       ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskDWord, 0x80800000);
-       ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+       rtl8723au_write32(adapter, rFPGA0_IQK, 0x80800000);
+       rtl8723au_write32(adapter, rIQK_AGC_Pts, 0xf8000000);
        udelay(1000);
        PSD_report_tmp = 0x0;
 
@@ -1650,7 +1629,10 @@ bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode)
 
        PSD_report_tmp = 0x0;
 
-       ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, Antenna_B);  /*  change to Antenna B */
+       val32 = rtl8723au_read32(adapter, rFPGA0_XA_RFInterfaceOE);
+       val32 &= ~0x300;
+       val32 |= 0x200;         /* Enable antenna B */
+       rtl8723au_write32(adapter, rFPGA0_XA_RFInterfaceOE, val32);
        udelay(10);
 
        for (n = 0; n < 2; n++) {
@@ -1660,7 +1642,10 @@ bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode)
        }
 
        /*  change to open case */
-       ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, 0);  /*  change to Ant A and B all open case */
+       /*  change to Ant A and B all open case */
+       val32 = rtl8723au_read32(adapter, rFPGA0_XA_RFInterfaceOE);
+       val32 &= ~0x300;
+       rtl8723au_write32(adapter, rFPGA0_XA_RFInterfaceOE, val32);
        udelay(10);
 
        for (n = 0; n < 2; n++) {
@@ -1670,25 +1655,36 @@ bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode)
        }
 
        /* Close IQK Single Tone function */
-       ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskDWord, 0x00000000);
+       rtl8723au_write32(adapter, rFPGA0_IQK, 0x00000000);
        PSD_report_tmp = 0x0;
 
        /* 1 Return to antanna A */
-       ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, Antenna_A);
-       ODM_SetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord, Reg88c);
-       ODM_SetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord, Regc08);
-       ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, Reg874);
-       ODM_SetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, 0x7F, 0x40);
-       ODM_SetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, bMaskDWord, Regc50);
-       ODM_SetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, CurrentChannel);
+       val32 = rtl8723au_read32(adapter, rFPGA0_XA_RFInterfaceOE);
+       val32 &= ~0x300;
+       val32 |= 0x100;         /* Enable antenna A */
+       rtl8723au_write32(adapter, rFPGA0_XA_RFInterfaceOE, val32);
+       rtl8723au_write32(adapter, rFPGA0_AnalogParameter4, Reg88c);
+       rtl8723au_write32(adapter, rOFDM0_TRMuxPar, Regc08);
+       rtl8723au_write32(adapter, rFPGA0_XCD_RFInterfaceSW, Reg874);
+       val32 = rtl8723au_read32(adapter, rOFDM0_XAAGCCore1);
+       val32 &= ~0x7f;
+       val32 |= 0x40;
+       rtl8723au_write32(adapter, rOFDM0_XAAGCCore1, val32);
+
+       rtl8723au_write32(adapter, rOFDM0_XAAGCCore1, Regc50);
+       ODM_SetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask,
+                    CurrentChannel);
        ODM_SetRFReg(pDM_Odm, RF_PATH_A, 0x00, bRFRegOffsetMask, RfLoopReg);
 
        /* Reload AFE Registers */
        odm_PHY_ReloadAFERegisters(pDM_Odm, AFE_REG_8723A, AFE_Backup, 16);
 
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_A[%d]= %d \n", 2416, AntA_report));
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_B[%d]= %d \n", 2416, AntB_report));
-       ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_O[%d]= %d \n", 2416, AntO_report));
+       ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
+                    ("psd_report_A[%d]= %d \n", 2416, AntA_report));
+       ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
+                    ("psd_report_B[%d]= %d \n", 2416, AntB_report));
+       ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
+                    ("psd_report_O[%d]= %d \n", 2416, AntO_report));
 
        /* 2 Test Ant B based on Ant A is ON */
        if (mode == ANTTESTB) {
@@ -1710,30 +1706,33 @@ bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode)
                if ((AntO_report >= 100) & (AntO_report < 118)) {
                        if (AntA_report > (AntO_report+1)) {
                                pDM_SWAT_Table->ANTA_ON = false;
-                               ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Ant A is OFF"));
+                               ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV,
+                                            ODM_DBG_LOUD, ("Ant A is OFF"));
                        } else {
                                pDM_SWAT_Table->ANTA_ON = true;
-                               ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Ant A is ON"));
+                               ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV,
+                                            ODM_DBG_LOUD, ("Ant A is ON"));
                        }
 
                        if (AntB_report > (AntO_report+2)) {
                                pDM_SWAT_Table->ANTB_ON = false;
-                               ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Ant B is OFF"));
+                               ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV,
+                                            ODM_DBG_LOUD, ("Ant B is OFF"));
                        } else {
                                pDM_SWAT_Table->ANTB_ON = true;
-                               ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Ant B is ON"));
+                               ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV,
+                                            ODM_DBG_LOUD, ("Ant B is ON"));
                        }
                }
        } else {
-               ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Need to check again\n"));
-               pDM_SWAT_Table->ANTA_ON = true; /*  Set Antenna A on as default */
-               pDM_SWAT_Table->ANTB_ON = false; /*  Set Antenna B off as default */
+               ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
+               ("ODM_SingleDualAntennaDetection(): Need to check again\n"));
+               /*  Set Antenna A on as default */
+               pDM_SWAT_Table->ANTA_ON = true;
+               /*  Set Antenna B off as default */
+               pDM_SWAT_Table->ANTB_ON = false;
                bResult = false;
        }
-       return bResult;
-}
 
-/* Justin: According to the current RRSI to adjust Response Frame TX power, 2012/11/05 */
-void odm_dtc(struct dm_odm_t *pDM_Odm)
-{
+       return bResult;
 }
index 33aafa01f900bfc7ab6ab9f24ab8ea8b8adc872a..7b9799e3dbdae06f501636b705736009c8e9a67d 100644 (file)
@@ -33,24 +33,23 @@ static s32 odm_SignalScaleMapping_92CSeries(struct dm_odm_t *pDM_Odm, s32 CurrSi
 {
        s32 RetSig = 0;
 
-       if ((pDM_Odm->SupportInterface  == ODM_ITRF_USB) || (pDM_Odm->SupportInterface  == ODM_ITRF_SDIO)) {
-               if (CurrSig >= 51 && CurrSig <= 100)
-                       RetSig = 100;
-               else if (CurrSig >= 41 && CurrSig <= 50)
-                       RetSig = 80 + ((CurrSig - 40)*2);
-               else if (CurrSig >= 31 && CurrSig <= 40)
-                       RetSig = 66 + (CurrSig - 30);
-               else if (CurrSig >= 21 && CurrSig <= 30)
-                       RetSig = 54 + (CurrSig - 20);
-               else if (CurrSig >= 10 && CurrSig <= 20)
-                       RetSig = 42 + (((CurrSig - 10) * 2) / 3);
-               else if (CurrSig >= 5 && CurrSig <= 9)
-                       RetSig = 22 + (((CurrSig - 5) * 3) / 2);
-               else if (CurrSig >= 1 && CurrSig <= 4)
-                       RetSig = 6 + (((CurrSig - 1) * 3) / 2);
-               else
-                       RetSig = CurrSig;
-       }
+       if (CurrSig >= 51 && CurrSig <= 100)
+               RetSig = 100;
+       else if (CurrSig >= 41 && CurrSig <= 50)
+               RetSig = 80 + ((CurrSig - 40)*2);
+       else if (CurrSig >= 31 && CurrSig <= 40)
+               RetSig = 66 + (CurrSig - 30);
+       else if (CurrSig >= 21 && CurrSig <= 30)
+               RetSig = 54 + (CurrSig - 20);
+       else if (CurrSig >= 10 && CurrSig <= 20)
+               RetSig = 42 + (((CurrSig - 10) * 2) / 3);
+       else if (CurrSig >= 5 && CurrSig <= 9)
+               RetSig = 22 + (((CurrSig - 5) * 3) / 2);
+       else if (CurrSig >= 1 && CurrSig <= 4)
+               RetSig = 6 + (((CurrSig - 1) * 3) / 2);
+       else
+               RetSig = CurrSig;
+
        return RetSig;
 }
 
index 88e0126e855aa6826d3e4a4fda4a2acbea7791fe..342dec3e939f325eae79d2b31766047c0802cdca 100644 (file)
@@ -14,6 +14,7 @@
  ******************************************************************************/
 
 #include "odm_precomp.h"
+#include "usb_ops_linux.h"
 
 void
 odm_ConfigRFReg_8723A(
@@ -43,62 +44,45 @@ odm_ConfigRFReg_8723A(
        }
 }
 
-void odm_ConfigMAC_8723A(struct dm_odm_t *pDM_Odm,
-       u32             Addr,
-       u8              Data
-       )
+void odm_ConfigMAC_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u8        data)
 {
-       ODM_Write1Byte(pDM_Odm, Addr, Data);
+       rtl8723au_write8(pDM_Odm->Adapter, addr, data);
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
-                    ("===> ODM_ConfigMACWithHeaderFile23a: [MAC_REG] %08X %08X\n",
-                    Addr, Data));
+                    ("===> %s: [MAC_REG] %08X %08X\n", __func__, addr, data));
 }
 
-void
-odm_ConfigBB_AGC_8723A(
-       struct dm_odm_t *pDM_Odm,
-       u32             Addr,
-       u32             Bitmask,
-       u32             Data
-  )
+void odm_ConfigBB_AGC_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u32 data)
 {
-       ODM_SetBBReg(pDM_Odm, Addr, Bitmask, Data);
+       rtl8723au_write32(pDM_Odm->Adapter, addr, data);
        /*  Add 1us delay between BB/RF register setting. */
        udelay(1);
 
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
-                    ("===> ODM_ConfigBBWithHeaderFile23a: [AGC_TAB] %08X %08X\n",
-                    Addr, Data));
+                    ("===> %s: [AGC_TAB] %08X %08X\n", __func__, addr, data));
 }
 
 void
-odm_ConfigBB_PHY_8723A(
-       struct dm_odm_t *pDM_Odm,
-       u32             Addr,
-       u32             Bitmask,
-       u32             Data
-  )
+odm_ConfigBB_PHY_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u32 data)
 {
-       if (Addr == 0xfe)
+       if (addr == 0xfe)
                msleep(50);
-       else if (Addr == 0xfd)
+       else if (addr == 0xfd)
                mdelay(5);
-       else if (Addr == 0xfc)
+       else if (addr == 0xfc)
                mdelay(1);
-       else if (Addr == 0xfb)
+       else if (addr == 0xfb)
                udelay(50);
-       else if (Addr == 0xfa)
+       else if (addr == 0xfa)
                udelay(5);
-       else if (Addr == 0xf9)
+       else if (addr == 0xf9)
                udelay(1);
-       else if (Addr == 0xa24)
-               pDM_Odm->RFCalibrateInfo.RegA24 = Data;
-       ODM_SetBBReg(pDM_Odm, Addr, Bitmask, Data);
+       else if (addr == 0xa24)
+               pDM_Odm->RFCalibrateInfo.RegA24 = data;
+       rtl8723au_write32(pDM_Odm->Adapter, addr, data);
 
        /*  Add 1us delay between BB/RF register setting. */
        udelay(1);
 
        ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
-                    ("===> ODM_ConfigBBWithHeaderFile23a: [PHY_REG] %08X %08X\n",
-                    Addr, Data));
+                    ("===> %s: [PHY_REG] %08X %08X\n", __func__, addr, data));
 }
index c912ab89bc3e9dd875590bd2533a758293d79cbb..cb2bdda6b0eba3478dc82a7c5851a51424b6cf42 100644 (file)
@@ -22,3 +22,18 @@ void ODM_InitDebugSetting23a(struct dm_odm_t *pDM_Odm)
 }
 
 u32 GlobalDebugLevel23A;
+
+void rt_trace(int comp, int level, const char *fmt, ...)
+{
+       struct va_format vaf;
+       va_list args;
+
+       va_start(args, fmt);
+
+       vaf.fmt = fmt;
+       vaf.va = &args;
+
+       pr_info(DRIVER_PREFIX " [0x%08x,%d] %pV", comp, level, &vaf);
+
+       va_end(args);
+}
index f03f6d4a38889240646356ec6687db0b55f771bb..d8f67902708e70955957f9a26da38c9c11de31dc 100644 (file)
 /*  */
 #include <usb_ops_linux.h>
 
-u8 ODM_Read1Byte(struct dm_odm_t *pDM_Odm,
-       u32                     RegAddr
-       )
-{
-       struct rtw_adapter *Adapter = pDM_Odm->Adapter;
-
-       return rtl8723au_read8(Adapter, RegAddr);
-}
-
-u16 ODM_Read2Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr)
-{
-       struct rtw_adapter *Adapter = pDM_Odm->Adapter;
-
-       return rtl8723au_read16(Adapter, RegAddr);
-}
-
-u32 ODM_Read4Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr)
-{
-       struct rtw_adapter *Adapter = pDM_Odm->Adapter;
-
-       return rtl8723au_read32(Adapter, RegAddr);
-}
-
-void ODM_Write1Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr, u8 Data)
-{
-       struct rtw_adapter *Adapter = pDM_Odm->Adapter;
-
-       rtl8723au_write8(Adapter, RegAddr, Data);
-}
-
-void ODM_Write2Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr, u16 Data)
-{
-       struct rtw_adapter *Adapter = pDM_Odm->Adapter;
-
-       rtl8723au_write16(Adapter, RegAddr, Data);
-}
-
-void ODM_Write4Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr, u32 Data)
-{
-       struct rtw_adapter *Adapter = pDM_Odm->Adapter;
-
-       rtl8723au_write32(Adapter, RegAddr, Data);
-}
-
-void ODM_SetMACReg(
-       struct dm_odm_t *pDM_Odm,
-       u32             RegAddr,
-       u32             BitMask,
-       u32             Data
-       )
-{
-       struct rtw_adapter *Adapter = pDM_Odm->Adapter;
-
-       PHY_SetBBReg(Adapter, RegAddr, BitMask, Data);
-}
-
-u32 ODM_GetMACReg(
-       struct dm_odm_t *pDM_Odm,
-       u32             RegAddr,
-       u32             BitMask
-       )
-{
-       struct rtw_adapter *Adapter = pDM_Odm->Adapter;
-
-       return PHY_QueryBBReg(Adapter, RegAddr, BitMask);
-}
-
-void ODM_SetBBReg(
-       struct dm_odm_t *pDM_Odm,
-       u32             RegAddr,
-       u32             BitMask,
-       u32             Data
-       )
-{
-       struct rtw_adapter *Adapter = pDM_Odm->Adapter;
-
-       PHY_SetBBReg(Adapter, RegAddr, BitMask, Data);
-}
-
-u32 ODM_GetBBReg(
-       struct dm_odm_t *pDM_Odm,
-       u32             RegAddr,
-       u32             BitMask
-       )
-{
-       struct rtw_adapter *Adapter = pDM_Odm->Adapter;
-
-       return PHY_QueryBBReg(Adapter, RegAddr, BitMask);
-}
-
 void ODM_SetRFReg(
        struct dm_odm_t *pDM_Odm,
        enum RF_RADIO_PATH      eRFPath,
index 73cfddd6df9aef6277db821b3c66d31a7425540a..cf15f80836badfd625e63e7a3d241686a6f0fb9a 100644 (file)
@@ -1554,7 +1554,8 @@ static void bthci_ResetBtSec(struct rtw_adapter *padapter, struct bt_security *p
                pBtSec->bUsedHwEncrypt = true;
        else
                pBtSec->bUsedHwEncrypt = false;
-       RT_TRACE(_module_rtl871x_security_c_, _drv_info_, ("%s: bUsedHwEncrypt =%d\n", __func__, pBtSec->bUsedHwEncrypt));
+       RT_TRACE(_module_rtl871x_security_c_, _drv_info_,
+                "%s: bUsedHwEncrypt =%d\n", __func__, pBtSec->bUsedHwEncrypt);
 
        pBtSec->RSNIE.Octet = pBtSec->RSNIEBuf;
 }
@@ -3208,7 +3209,7 @@ bthci_CmdDisconnectPhysicalLink(struct rtw_adapter *padapter,
        pBtDbg->dbgHciInfo.hciCmdCntDisconnectPhyLink++;
 
        PLH = *((u8 *)pHciCmd->Data);
-       PhysLinkDisconnectReason = (*((u8 *)pHciCmd->Data+1));
+       PhysLinkDisconnectReason = *((u8 *)pHciCmd->Data+1);
        RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_DISCONNECT_PHYSICAL_LINK  PhyHandle = 0x%x, Reason = 0x%x\n",
                PLH, PhysLinkDisconnectReason));
 
@@ -4518,8 +4519,8 @@ bthci_StateConnecting(struct rtw_adapter *padapter,
                RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_CONNECT_COMPLETE\n"));
 
                if (pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_JOINER) {
-                       RT_TRACE(_module_rtl871x_security_c_,
-                                _drv_info_, ("StateConnecting \n"));
+                       RT_TRACE(_module_rtl871x_security_c_, _drv_info_,
+                                "StateConnecting\n");
                }
                break;
        case STATE_CMD_DISCONNECT_PHY_LINK:
@@ -5796,7 +5797,7 @@ static void
 btdm_1AntUpdateHalRAMask(struct rtw_adapter *padapter, u32 mac_id, u32 filter)
 {
        u8 init_rate = 0;
-       u8 raid;
+       u8 raid, arg;
        u32 mask;
        u8 shortGIrate = false;
        int supportRateNum = 0;
@@ -5860,26 +5861,16 @@ btdm_1AntUpdateHalRAMask(struct rtw_adapter *padapter, u32 mac_id, u32 filter)
        mask &= ~filter;
        init_rate = get_highest_rate_idx23a(mask)&0x3f;
 
-       if (pHalData->fw_ractrl) {
-               u8 arg = 0;
+       arg = mac_id&0x1f;/* MACID */
+       arg |= BIT(7);
+       if (true == shortGIrate)
+               arg |= BIT(5);
 
-               arg = mac_id&0x1f;/* MACID */
-               arg |= BIT(7);
-               if (true == shortGIrate)
-                       arg |= BIT(5);
-
-               RTPRINT(FBT, BT_TRACE,
-                       ("[BTCoex], Update FW RAID entry, MASK = 0x%08x, "
-                        "arg = 0x%02x\n", mask, arg));
-
-               rtl8723a_set_raid_cmd(padapter, mask, arg);
-       } else {
-               if (shortGIrate)
-                       init_rate |= BIT(6);
+       RTPRINT(FBT, BT_TRACE,
+               ("[BTCoex], Update FW RAID entry, MASK = 0x%08x, "
+                "arg = 0x%02x\n", mask, arg));
 
-               rtl8723au_write8(padapter, REG_INIDATA_RATE_SEL + mac_id,
-                                init_rate);
-       }
+       rtl8723a_set_raid_cmd(padapter, mask, arg);
 
        psta->init_rate = init_rate;
        pdmpriv->INIDATA_RATE[mac_id] = init_rate;
@@ -11206,15 +11197,17 @@ void rtl8723a_BT_init_hal_vars(struct rtw_adapter *padapter)
        pHalData->bt_coexist.bt_radiosharedtype = pHalData->EEPROMBluetoothRadioShared;
 
        RT_TRACE(_module_hal_init_c_, _drv_info_,
-                ("BT Coexistance = 0x%x\n", rtl8723a_BT_coexist(padapter)));
+                "BT Coexistance = 0x%x\n", rtl8723a_BT_coexist(padapter));
 
        if (rtl8723a_BT_coexist(padapter)) {
                if (pHalData->bt_coexist.BT_Ant_Num == Ant_x2) {
                        BTDM_SetBtCoexCurrAntNum(padapter, 2);
-                       RT_TRACE(_module_hal_init_c_, _drv_info_, ("BlueTooth BT_Ant_Num = Antx2\n"));
+                       RT_TRACE(_module_hal_init_c_, _drv_info_,
+                                "BlueTooth BT_Ant_Num = Antx2\n");
                } else if (pHalData->bt_coexist.BT_Ant_Num == Ant_x1) {
                        BTDM_SetBtCoexCurrAntNum(padapter, 1);
-                       RT_TRACE(_module_hal_init_c_, _drv_info_, ("BlueTooth BT_Ant_Num = Antx1\n"));
+                       RT_TRACE(_module_hal_init_c_, _drv_info_,
+                                "BlueTooth BT_Ant_Num = Antx1\n");
                }
                pHalData->bt_coexist.bBTBusyTraffic = false;
                pHalData->bt_coexist.bBTTrafficModeSet = false;
@@ -11223,8 +11216,8 @@ void rtl8723a_BT_init_hal_vars(struct rtw_adapter *padapter)
                pHalData->bt_coexist.PreviousState = 0;
 
                RT_TRACE(_module_hal_init_c_, _drv_info_,
-                        ("bt_radiosharedType = 0x%x\n",
-                        pHalData->bt_coexist.bt_radiosharedtype));
+                        "bt_radiosharedType = 0x%x\n",
+                        pHalData->bt_coexist.bt_radiosharedtype);
        }
 }
 
index 7b56411cc3c8130c5cf70d816a57459ac4b8a5fc..11e1108d0c56f17a37de922b7b969df2ea842c9b 100644 (file)
@@ -142,32 +142,18 @@ int rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg)
 /* arg[5] = Short GI */
 void rtl8723a_add_rateatid(struct rtw_adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
 {
-       struct hal_data_8723a   *pHalData = GET_HAL_DATA(pAdapter);
-       u8 macid = arg&0x1f;
-       u8 raid = (bitmap>>28) & 0x0f;
+       struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
+       u8 macid = arg & 0x1f;
+       u32 raid = bitmap & 0xf0000000;
 
        bitmap &= 0x0fffffff;
        if (rssi_level != DM_RATR_STA_INIT)
                bitmap = ODM_Get_Rate_Bitmap23a(pHalData, macid, bitmap,
                                                rssi_level);
 
-       bitmap |= ((raid<<28)&0xf0000000);
+       bitmap |= raid;
 
-       if (pHalData->fw_ractrl == true) {
-               rtl8723a_set_raid_cmd(pAdapter, bitmap, arg);
-       } else {
-               u8 init_rate, shortGIrate = false;
-
-               init_rate = get_highest_rate_idx23a(bitmap&0x0fffffff)&0x3f;
-
-               shortGIrate = (arg&BIT(5)) ? true:false;
-
-               if (shortGIrate == true)
-                       init_rate |= BIT(6);
-
-               rtl8723au_write8(pAdapter, REG_INIDATA_RATE_SEL + macid,
-                                init_rate);
-       }
+       rtl8723a_set_raid_cmd(pAdapter, bitmap, arg);
 }
 
 void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode)
@@ -183,10 +169,8 @@ void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode)
            prevent conficting setting in Fw power */
        /*  saving sequence. 2010.06.07. Added by tynli.
            Suggested by SD3 yschang. */
-       if ((Mode != PS_MODE_ACTIVE) &&
-           (!IS_92C_SERIAL(pHalData->VersionID))) {
+       if (Mode != PS_MODE_ACTIVE && pHalData->rf_type != RF_2T2R)
                ODM_RF_Saving23a(&pHalData->odmpriv, true);
-       }
 
        H2CSetPwrMode.Mode = Mode;
        H2CSetPwrMode.SmartPS = pwrpriv->smart_ps;
index fa826b068d11ea8a91247a0b3b6a708e78d6efe5..1e831f2d1cafaf695dca988ee3444403f240dadc 100644 (file)
@@ -94,8 +94,6 @@ void rtl8723a_init_dm_priv(struct rtw_adapter *Adapter)
        memset(pDM_Odm, 0, sizeof(*pDM_Odm));
 
        pDM_Odm->Adapter = Adapter;
-       ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_PLATFORM, 0x04);
-       ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_INTERFACE, RTW_USB);/* RTL871X_HCI_TYPE */
 
        ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_IC_TYPE, ODM_RTL8723A);
 
@@ -119,15 +117,7 @@ void rtl8723a_init_dm_priv(struct rtw_adapter *Adapter)
                ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_EXT_LNA, true);
                ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_EXT_PA, true);
        }
-       ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_PATCH_ID, pHalData->CustomerID);
        ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_BWIFI_TEST, Adapter->registrypriv.wifi_spec);
-
-       if (pHalData->rf_type == RF_1T1R)
-               ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T1R);
-       else if (pHalData->rf_type == RF_2T2R)
-               ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_2T2R);
-       else if (pHalData->rf_type == RF_1T2R)
-               ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T2R);
 }
 
 static void Update_ODM_ComInfo_8723a(struct rtw_adapter *Adapter)
@@ -136,16 +126,7 @@ static void Update_ODM_ComInfo_8723a(struct rtw_adapter *Adapter)
        struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
        struct dm_priv  *pdmpriv = &pHalData->dmpriv;
        int i;
-       pdmpriv->InitODMFlag =  ODM_BB_DIG              |
-                               ODM_BB_RA_MASK          |
-                               ODM_BB_DYNAMIC_TXPWR    |
-                               ODM_BB_FA_CNT           |
-                               ODM_BB_RSSI_MONITOR     |
-                               ODM_BB_CCK_PD           |
-                               ODM_BB_PWR_SAVE         |
-                               ODM_MAC_EDCA_TURBO      |
-                               ODM_RF_TX_PWR_TRACK     |
-                               ODM_RF_CALIBRATION;
+       pdmpriv->InitODMFlag = 0;
        /*  Pointer reference */
        rtl8723a_odm_support_ability_set(Adapter, DYNAMIC_ALL_FUNC_ENABLE);
 
index a5eadd4e2580023553dcfede4b77928fcfbff008..04d01833dc304486dc5cb37b5b17acf1234026d2 100644 (file)
@@ -95,7 +95,7 @@ static int _WriteFW(struct rtw_adapter *padapter, void *buffer, u32 size)
                        goto exit;
        }
        RT_TRACE(_module_hal_init_c_, _drv_info_,
-                ("_WriteFW Done- for Normal chip.\n"));
+                "_WriteFW Done- for Normal chip.\n");
 
 exit:
        return ret;
@@ -115,13 +115,13 @@ static int _FWFreeToGo(struct rtw_adapter *padapter)
 
        if (counter >= POLLING_READY_TIMEOUT_COUNT) {
                RT_TRACE(_module_hal_init_c_, _drv_err_,
-                        ("%s: chksum report fail! REG_MCUFWDL:0x%08x\n",
-                         __func__, value32));
+                        "%s: chksum report fail! REG_MCUFWDL:0x%08x\n",
+                        __func__, value32);
                return _FAIL;
        }
        RT_TRACE(_module_hal_init_c_, _drv_info_,
-                ("%s: Checksum report OK! REG_MCUFWDL:0x%08x\n", __func__,
-                 value32));
+                "%s: Checksum report OK! REG_MCUFWDL:0x%08x\n", __func__,
+                value32);
 
        value32 = rtl8723au_read32(padapter, REG_MCUFWDL);
        value32 |= MCUFWDL_RDY;
@@ -134,17 +134,16 @@ static int _FWFreeToGo(struct rtw_adapter *padapter)
                value32 = rtl8723au_read32(padapter, REG_MCUFWDL);
                if (value32 & WINTINI_RDY) {
                        RT_TRACE(_module_hal_init_c_, _drv_info_,
-                                ("%s: Polling FW ready success!! "
-                                 "REG_MCUFWDL:0x%08x\n",
-                                 __func__, value32));
+                                "%s: Polling FW ready success!! REG_MCUFWDL:0x%08x\n",
+                                __func__, value32);
                        return _SUCCESS;
                }
                udelay(5);
        } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
 
        RT_TRACE(_module_hal_init_c_, _drv_err_,
-                ("%s: Polling FW ready fail!! REG_MCUFWDL:0x%08x\n",
-                 __func__, value32));
+                "%s: Polling FW ready fail!! REG_MCUFWDL:0x%08x\n",
+                __func__, value32);
        return _FAIL;
 }
 
@@ -173,8 +172,8 @@ void rtl8723a_FirmwareSelfReset(struct rtw_adapter *padapter)
                        u1bTmp = rtl8723au_read8(padapter, REG_SYS_FUNC_EN + 1);
                }
                RT_TRACE(_module_hal_init_c_, _drv_info_,
-                        ("-%s: 8051 reset success (%d)\n", __func__,
-                         Delay));
+                        "-%s: 8051 reset success (%d)\n", __func__,
+                        Delay);
 
                if ((Delay == 0)) {
                        /* force firmware reset */
@@ -206,13 +205,12 @@ int rtl8723a_FirmwareDownload(struct rtw_adapter *padapter)
        int fw_size;
        static int log_version;
 
-       RT_TRACE(_module_hal_init_c_, _drv_info_, ("+%s\n", __func__));
+       RT_TRACE(_module_hal_init_c_, _drv_info_, "+%s\n", __func__);
 
        if (IS_8723A_A_CUT(pHalData->VersionID)) {
                fw_name = "rtlwifi/rtl8723aufw_A.bin";
                RT_TRACE(_module_hal_init_c_, _drv_info_,
-                        ("rtl8723a_FirmwareDownload: R8723FwImageArray_UMC "
-                         "for RTL8723A A CUT\n"));
+                        "rtl8723a_FirmwareDownload: R8723FwImageArray_UMC for RTL8723A A CUT\n");
        } else if (IS_8723A_B_CUT(pHalData->VersionID)) {
                /*  WLAN Fw. */
                if (padapter->registrypriv.wifi_spec == 1) {
@@ -234,7 +232,7 @@ int rtl8723a_FirmwareDownload(struct rtw_adapter *padapter)
                /*  <Roger_TODO> We should download proper RAM Code here
                    to match the ROM code. */
                RT_TRACE(_module_hal_init_c_, _drv_err_,
-                        ("%s: unknow version!\n", __func__));
+                        "%s: unknown version!\n", __func__);
                rtStatus = _FAIL;
                goto Exit;
        }
@@ -319,11 +317,11 @@ int rtl8723a_FirmwareDownload(struct rtw_adapter *padapter)
        rtStatus = _FWFreeToGo(padapter);
        if (_SUCCESS != rtStatus) {
                RT_TRACE(_module_hal_init_c_, _drv_err_,
-                        ("DL Firmware failed!\n"));
+                        "DL Firmware failed!\n");
                goto Exit;
        }
        RT_TRACE(_module_hal_init_c_, _drv_info_,
-                ("Firmware is ready to run!\n"));
+                "Firmware is ready to run!\n");
 
 Exit:
        kfree(firmware_buf);
@@ -424,15 +422,14 @@ hal_ReadEFuse_WiFi(struct rtw_adapter *padapter,
                        offset = GET_HDR_OFFSET_2_0(efuseHeader);
 
                        ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseExtHdr);
-                       if (ALL_WORDS_DISABLED(efuseExtHdr)) {
+                       if (ALL_WORDS_DISABLED(efuseExtHdr))
                                continue;
-                       }
 
                        offset |= ((efuseExtHdr & 0xF0) >> 1);
-                       wden = (efuseExtHdr & 0x0F);
+                       wden = efuseExtHdr & 0x0F;
                } else {
-                       offset = ((efuseHeader >> 4) & 0x0f);
-                       wden = (efuseHeader & 0x0f);
+                       offset = (efuseHeader >> 4) & 0x0f;
+                       wden = efuseHeader & 0x0f;
                }
 
                if (offset < EFUSE_MAX_SECTION_8723A) {
@@ -524,15 +521,14 @@ hal_ReadEFuse_BT(struct rtw_adapter *padapter,
 
                                ReadEFuseByte23a(padapter, eFuse_Addr++,
                                              &efuseExtHdr);
-                               if (ALL_WORDS_DISABLED(efuseExtHdr)) {
+                               if (ALL_WORDS_DISABLED(efuseExtHdr))
                                        continue;
-                               }
 
                                offset |= ((efuseExtHdr & 0xF0) >> 1);
-                               wden = (efuseExtHdr & 0x0F);
+                               wden = efuseExtHdr & 0x0F;
                        } else {
-                               offset = ((efuseHeader >> 4) & 0x0f);
-                               wden = (efuseHeader & 0x0f);
+                               offset = (efuseHeader >> 4) & 0x0f;
+                               wden = efuseHeader & 0x0f;
                        }
 
                        if (offset < EFUSE_BT_MAX_SECTION) {
@@ -630,9 +626,8 @@ u16 rtl8723a_EfuseGetCurrentSize_WiFi(struct rtw_adapter *padapter)
                        hoffset = GET_HDR_OFFSET_2_0(efuse_data);
                        efuse_addr++;
                        efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data);
-                       if (ALL_WORDS_DISABLED(efuse_data)) {
+                       if (ALL_WORDS_DISABLED(efuse_data))
                                continue;
-                       }
 
                        hoffset |= ((efuse_data & 0xF0) >> 1);
                        hworden = efuse_data & 0x0F;
@@ -721,9 +716,8 @@ u16 rtl8723a_EfuseGetCurrentSize_BT(struct rtw_adapter *padapter)
                }
 
                /*  Check if we need to check next bank efuse */
-               if (efuse_addr < retU2) {
+               if (efuse_addr < retU2)
                        break;  /*  don't need to check next bank. */
-               }
        }
 
        retU2 = ((bank - 1) * EFUSE_BT_REAL_BANK_CONTENT_LEN) + efuse_addr;
@@ -744,7 +738,7 @@ void rtl8723a_read_chip_version(struct rtw_adapter *padapter)
        value32 = rtl8723au_read32(padapter, REG_SYS_CFG);
        ChipVersion.ICType = CHIP_8723A;
        ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
-       ChipVersion.RFType = RF_TYPE_1T1R;
+       pHalData->rf_type = RF_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) */
@@ -755,7 +749,7 @@ void rtl8723a_read_chip_version(struct rtw_adapter *padapter)
 
        value32 = rtl8723au_read32(padapter, REG_GPIO_OUTSTS);
        /*  ROM code version. */
-       ChipVersion.ROMVer = ((value32 & RF_RL_ID) >> 20);
+       ChipVersion.ROMVer = (value32 & RF_RL_ID) >> 20;
 
        /*  For multi-function consideration. Added by Roger, 2010.10.06. */
        pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
@@ -768,16 +762,8 @@ void rtl8723a_read_chip_version(struct rtw_adapter *padapter)
        pHalData->PolarityCtl =
                ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT :
                 RT_POLARITY_LOW_ACT);
-       dump_chip_info23a(ChipVersion);
        pHalData->VersionID = ChipVersion;
 
-       if (IS_1T2R(ChipVersion))
-               pHalData->rf_type = RF_1T2R;
-       else if (IS_2T2R(ChipVersion))
-               pHalData->rf_type = RF_2T2R;
-       else
-               pHalData->rf_type = RF_1T1R;
-
        MSG_8723A("RF_Type is %x!!\n", pHalData->rf_type);
 }
 
@@ -831,7 +817,7 @@ static void ResumeTxBeacon(struct rtw_adapter *padapter)
            we record the value */
        /*  which should be read from register to a global variable. */
 
-       RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+ResumeTxBeacon\n"));
+       RT_TRACE(_module_hci_hal_init_c_, _drv_info_, "+ResumeTxBeacon\n");
 
        pHalData->RegFwHwTxQCtrl |= BIT(6);
        rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
@@ -849,7 +835,7 @@ static void StopTxBeacon(struct rtw_adapter *padapter)
            we record the value */
        /*  which should be read from register to a global variable. */
 
-       RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+StopTxBeacon\n"));
+       RT_TRACE(_module_hci_hal_init_c_, _drv_info_, "+StopTxBeacon\n");
 
        pHalData->RegFwHwTxQCtrl &= ~BIT(6);
        rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
@@ -995,7 +981,7 @@ int c2h_handler_8723a(struct rtw_adapter *padapter, struct c2h_evt_hdr *c2h_evt)
        switch (c2h_evt->id) {
        case C2H_DBG:
                RT_TRACE(_module_hal_init_c_, _drv_info_,
-                        ("C2HCommandHandler: %s\n", c2h_evt->payload));
+                        "C2HCommandHandler: %s\n", c2h_evt->payload);
                break;
 
        case C2H_CCX_TX_RPT:
@@ -1005,22 +991,22 @@ int c2h_handler_8723a(struct rtw_adapter *padapter, struct c2h_evt_hdr *c2h_evt)
                break;
        case C2H_HW_INFO_EXCH:
                RT_TRACE(_module_hal_init_c_, _drv_info_,
-                        ("[BT], C2H_HW_INFO_EXCH\n"));
+                        "[BT], C2H_HW_INFO_EXCH\n");
                for (i = 0; i < c2h_evt->plen; i++) {
                        RT_TRACE(_module_hal_init_c_, _drv_info_,
-                                ("[BT], tmpBuf[%d]= 0x%x\n", i,
-                                 c2h_evt->payload[i]));
+                                "[BT], tmpBuf[%d]= 0x%x\n", i,
+                                c2h_evt->payload[i]);
                }
                break;
 
        case C2H_C2H_H2C_TEST:
                RT_TRACE(_module_hal_init_c_, _drv_info_,
-                        ("[BT], C2H_H2C_TEST\n"));
+                        "[BT], C2H_H2C_TEST\n");
                RT_TRACE(_module_hal_init_c_, _drv_info_,
-                        ("[BT], tmpBuf[0]/[1]/[2]/[3]/[4]= 0x%x/ 0x%x/ "
-                         "0x%x/ 0x%x/ 0x%x\n", c2h_evt->payload[0],
-                         c2h_evt->payload[1], c2h_evt->payload[2],
-                         c2h_evt->payload[3], c2h_evt->payload[4]));
+                        "[BT], tmpBuf[0]/[1]/[2]/[3]/[4]= 0x%x/ 0x%x/ 0x%x/ 0x%x/ 0x%x\n",
+                        c2h_evt->payload[0],
+                        c2h_evt->payload[1], c2h_evt->payload[2],
+                        c2h_evt->payload[3], c2h_evt->payload[4]);
                break;
 
        case C2H_BT_INFO:
@@ -1095,7 +1081,6 @@ void rtl8723a_init_default_value(struct rtw_adapter *padapter)
        pdmpriv = &pHalData->dmpriv;
 
        /*  init default value */
-       pHalData->fw_ractrl = false;
        pHalData->bIQKInitialized = false;
        if (!padapter->pwrctrlpriv.bkeepfwalive)
                pHalData->LastHMEBoxNum = 0;
@@ -1149,14 +1134,13 @@ static int _LLTWrite(struct rtw_adapter *padapter, u32 address, u32 data)
        /* polling */
        do {
                value = rtl8723au_read32(padapter, LLTReg);
-               if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) {
+               if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
                        break;
-               }
 
                if (count > POLLING_LLT_THRESHOLD) {
                        RT_TRACE(_module_hal_init_c_, _drv_err_,
-                                ("Failed to polling write LLT done at "
-                                 "address %d!\n", address));
+                                "Failed to polling write LLT done at address %d!\n",
+                                address);
                        status = _FAIL;
                        break;
                }
@@ -1174,16 +1158,14 @@ int InitLLTTable23a(struct rtw_adapter *padapter, u32 boundary)
 
        for (i = 0; i < (txpktbuf_bndy - 1); i++) {
                status = _LLTWrite(padapter, i, i + 1);
-               if (status != _SUCCESS) {
+               if (status != _SUCCESS)
                        return status;
-               }
        }
 
        /*  end of list */
        status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF);
-       if (status != _SUCCESS) {
+       if (status != _SUCCESS)
                return status;
-       }
 
        /*  Make the other pages as ring buffer */
        /*  This ring buffer is used as beacon buffer if we config this
@@ -1191,16 +1173,14 @@ int InitLLTTable23a(struct rtw_adapter *padapter, u32 boundary)
        /*  Otherwise used as local loopback buffer. */
        for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) {
                status = _LLTWrite(padapter, i, (i + 1));
-               if (_SUCCESS != status) {
+               if (_SUCCESS != status)
                        return status;
-               }
        }
 
        /*  Let last entry point to the start entry of ring buffer */
        status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy);
-       if (status != _SUCCESS) {
+       if (status != _SUCCESS)
                return status;
-       }
 
        return status;
 }
@@ -1272,8 +1252,6 @@ e.        SYS_FUNC_EN 0x02[7:0] = 0x14            reset BB state machine
 
        /*  2010/08/12 MH We need to set BB/GLBAL reset to save power
            for SS mode. */
-
-/*     RT_TRACE(COMP_INIT, DBG_LOUD, ("======> RF off and reset BB.\n")); */
 }
 
 static void _ResetDigitalProcedure1_92C(struct rtw_adapter *padapter,
@@ -1402,8 +1380,6 @@ static void _DisableAnalog(struct rtw_adapter *padapter, bool bWithoutHWSM)
                value8 = rtl8723au_read8(padapter, REG_LDOV12D_CTRL);
                value8 &= ~LDV12_EN;
                rtl8723au_write8(padapter, REG_LDOV12D_CTRL, value8);
-/*             RT_TRACE(COMP_INIT, DBG_LOUD,
-               (" REG_LDOV12D_CTRL Reg0x21:0x%02x.\n", value8)); */
        }
 
        /*****************************
@@ -1435,9 +1411,9 @@ static void _DisableAnalog(struct rtw_adapter *padapter, bool bWithoutHWSM)
 /*  HW Auto state machine */
 int CardDisableHWSM(struct rtw_adapter *padapter, u8 resetMCU)
 {
-       if (padapter->bSurpriseRemoved) {
+       if (padapter->bSurpriseRemoved)
                return _SUCCESS;
-       }
+
        /*  RF Off Sequence ==== */
        _DisableRFAFEAndResetBB8192C(padapter);
 
@@ -1451,7 +1427,7 @@ int CardDisableHWSM(struct rtw_adapter *padapter, u8 resetMCU)
        _DisableAnalog(padapter, false);
 
        RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                ("======> Card disable finished.\n"));
+                "======> Card disable finished.\n");
 
        return _SUCCESS;
 }
@@ -1459,9 +1435,8 @@ int CardDisableHWSM(struct rtw_adapter *padapter, u8 resetMCU)
 /*  without HW Auto state machine */
 int CardDisableWithoutHWSM(struct rtw_adapter *padapter)
 {
-       if (padapter->bSurpriseRemoved) {
+       if (padapter->bSurpriseRemoved)
                return _SUCCESS;
-       }
 
        /*  RF Off Sequence ==== */
        _DisableRFAFEAndResetBB8192C(padapter);
@@ -1478,8 +1453,6 @@ int CardDisableWithoutHWSM(struct rtw_adapter *padapter)
        /*   ==== Disable analog sequence === */
        _DisableAnalog(padapter, true);
 
-       /* RT_TRACE(COMP_INIT, DBG_LOUD,
-          ("<====== Card Disable Without HWSM .\n")); */
        return _SUCCESS;
 }
 
@@ -1496,7 +1469,7 @@ void Hal_InitPGData(struct rtw_adapter *padapter, u8 *PROMContent)
                }
        } else {
                RT_TRACE(_module_hci_hal_init_c_, _drv_notice_,
-                        ("AutoLoad Fail reported from CR9346!!\n"));
+                        "AutoLoad Fail reported from CR9346!!\n");
                /* update to default value 0xFF */
                if (!pEEPROM->EepromOrEfuse)
                        EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI);
@@ -1521,7 +1494,7 @@ void Hal_EfuseParseIDCode(struct rtw_adapter *padapter, u8 *hwinfo)
        }
 
        RT_TRACE(_module_hal_init_c_, _drv_info_,
-                ("EEPROM ID = 0x%04x\n", EEPROMId));
+                "EEPROM ID = 0x%04x\n", EEPROMId);
 }
 
 static void Hal_EEValueCheck(u8 EEType, void *pInValue, void *pOutValue)
@@ -1536,9 +1509,8 @@ static void Hal_EEValueCheck(u8 EEType, void *pInValue, void *pOutValue)
                        *pOut = *pIn;
                else {
                        RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
-                                ("EETYPE_TX_PWR, value =%d is invalid, set "
-                                 "to default = 0x%x\n",
-                                 *pIn, EEPROM_Default_TxPowerLevel));
+                                "EETYPE_TX_PWR, value =%d is invalid, set to default = 0x%x\n",
+                                *pIn, EEPROM_Default_TxPowerLevel);
                        *pOut = EEPROM_Default_TxPowerLevel;
                }
        }
@@ -1676,35 +1648,34 @@ Hal_EfuseParsetxpowerinfo_8723A(struct rtw_adapter *padapter,
        for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) {
                for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
                        RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                                ("RF(%u)-Ch(%u) [CCK / HT40_1S / HT40_2S] = "
-                                 "[0x%x / 0x%x / 0x%x]\n",
-                                 rfPath, ch,
-                                 pHalData->TxPwrLevelCck[rfPath][ch],
-                                 pHalData->TxPwrLevelHT40_1S[rfPath][ch],
-                                 pHalData->TxPwrLevelHT40_2S[rfPath][ch]));
+                                "RF(%u)-Ch(%u) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n",
+                                rfPath, ch,
+                                pHalData->TxPwrLevelCck[rfPath][ch],
+                                pHalData->TxPwrLevelHT40_1S[rfPath][ch],
+                                pHalData->TxPwrLevelHT40_2S[rfPath][ch]);
 
                }
        }
        for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
                RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                        ("RF-A Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
-                         pHalData->TxPwrHt20Diff[RF_PATH_A][ch],
-                         pHalData->TxPwrHt20Diff[RF_PATH_A][ch]));
+                        "RF-A Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
+                        pHalData->TxPwrHt20Diff[RF_PATH_A][ch],
+                        pHalData->TxPwrHt20Diff[RF_PATH_A][ch]);
        }
        for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++)
                RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                        ("RF-A Legacy to Ht40 Diff[%u] = 0x%x\n", ch,
-                         pHalData->TxPwrLegacyHtDiff[RF_PATH_A][ch]));
+                        "RF-A Legacy to Ht40 Diff[%u] = 0x%x\n", ch,
+                        pHalData->TxPwrLegacyHtDiff[RF_PATH_A][ch]);
        for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
                RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                        ("RF-B Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
-                         pHalData->TxPwrHt20Diff[RF_PATH_B][ch],
-                         pHalData->TxPwrHt20Diff[RF_PATH_B][ch]));
+                        "RF-B Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
+                        pHalData->TxPwrHt20Diff[RF_PATH_B][ch],
+                        pHalData->TxPwrHt20Diff[RF_PATH_B][ch]);
        }
        for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++)
                RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                        ("RF-B Legacy to HT40 Diff[%u] = 0x%x\n", ch,
-                         pHalData->TxPwrLegacyHtDiff[RF_PATH_B][ch]));
+                        "RF-B Legacy to HT40 Diff[%u] = 0x%x\n", ch,
+                        pHalData->TxPwrLegacyHtDiff[RF_PATH_B][ch]);
        if (!AutoLoadFail) {
                struct registry_priv *registry_par = &padapter->registrypriv;
                if (registry_par->regulatory_tid == 0xff) {
@@ -1721,7 +1692,7 @@ Hal_EfuseParsetxpowerinfo_8723A(struct rtw_adapter *padapter,
                pHalData->EEPROMRegulatory = 0;
        }
        RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                ("EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory));
+                "EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory);
 
        if (!AutoLoadFail)
                pHalData->bTXPowerDataReadFromEEPORM = true;
@@ -1747,8 +1718,8 @@ Hal_EfuseParseBTCoexistInfo_8723A(struct rtw_adapter *padapter,
                /*  eeprom spec */
                tempval = hwinfo[RF_OPTION4_8723A];
                pHalData->EEPROMBluetoothAntNum = (tempval & 0x1);
-               pHalData->EEPROMBluetoothAntIsolation = ((tempval & 0x10) >> 4);
-               pHalData->EEPROMBluetoothRadioShared = ((tempval & 0x20) >> 5);
+               pHalData->EEPROMBluetoothAntIsolation = (tempval & 0x10) >> 4;
+               pHalData->EEPROMBluetoothRadioShared = (tempval & 0x20) >> 5;
        } else {
                pHalData->EEPROMBluetoothCoexist = 0;
                pHalData->EEPROMBluetoothType = BT_RTL8723A;
@@ -1771,8 +1742,8 @@ Hal_EfuseParseEEPROMVer(struct rtw_adapter *padapter,
        else
                pHalData->EEPROMVersion = 1;
        RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                ("Hal_EfuseParseEEPROMVer(), EEVer = %d\n",
-                 pHalData->EEPROMVersion));
+                "Hal_EfuseParseEEPROMVer(), EEVer = %d\n",
+                pHalData->EEPROMVersion);
 }
 
 void
@@ -1805,10 +1776,10 @@ Hal_EfuseParseCustomerID(struct rtw_adapter *padapter,
                pHalData->EEPROMSubCustomerID = 0;
        }
        RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                ("EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID));
+                "EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID);
        RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                ("EEPROM SubCustomer ID: 0x%02x\n",
-                 pHalData->EEPROMSubCustomerID));
+                "EEPROM SubCustomer ID: 0x%02x\n",
+                pHalData->EEPROMSubCustomerID);
 }
 
 void
@@ -1837,8 +1808,8 @@ Hal_EfuseParseXtal_8723A(struct rtw_adapter *pAdapter,
                pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A;
        }
        RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                ("%s: CrystalCap = 0x%2x\n", __func__,
-                 pHalData->CrystalCap));
+                "%s: CrystalCap = 0x%2x\n", __func__,
+                pHalData->CrystalCap);
 }
 
 void
@@ -1875,9 +1846,8 @@ static void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc)
        /*  Clear first */
        ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
 
-       for (index = 0; index < count; index++) {
+       for (index = 0; index < count; index++)
                checksum ^= le16_to_cpu(*(usPtr + index));
-       }
 
        ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff);
 }
@@ -1925,9 +1895,8 @@ void rtl8723a_fill_fake_txdesc(struct rtw_adapter *padapter, u8 *pDesc,
                ptxdesc->txdw3 |= cpu_to_le32((8 << 28));
        }
 
-       if (true == IsBTQosNull) {
+       if (true == IsBTQosNull)
                ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); /*  BT NULL */
-       }
 
        /* offset 16 */
        ptxdesc->txdw4 |= cpu_to_le32(BIT(8));  /* driver uses rate */
index 19dc5e3b2e2ec94f41b0fc83f116e615613fc8d5..46a30659c96f5fab7f3814e91cd6e3e3c257966b 100644 (file)
@@ -121,18 +121,15 @@ PHY_SetBBReg(struct rtw_adapter *Adapter, u32 RegAddr, u32 BitMask, u32   Data)
 {
        u32 OriginalValue, BitShift;
 
-       /* RT_TRACE(COMP_RF, DBG_TRACE, ("--->PHY_SetBBReg(): RegAddr(%#lx), BitMask(%#lx), Data(%#lx)\n", RegAddr, BitMask, Data)); */
-
        if (BitMask != bMaskDWord) {/* if not "double word" write */
                OriginalValue = rtl8723au_read32(Adapter, RegAddr);
                BitShift = phy_CalculateBitShift(BitMask);
-               Data = ((OriginalValue & (~BitMask)) | (Data << BitShift));
+               Data = (OriginalValue & (~BitMask)) | (Data << BitShift);
        }
 
        rtl8723au_write32(Adapter, RegAddr, Data);
 
        /* RTPRINT(FPHY, PHY_BBW, ("BBW MASK = 0x%lx Addr[0x%lx]= 0x%lx\n", BitMask, RegAddr, Data)); */
-       /* RT_TRACE(COMP_RF, DBG_TRACE, ("<---PHY_SetBBReg(): RegAddr(%#lx), BitMask(%#lx), Data(%#lx)\n", RegAddr, BitMask, Data)); */
 }
 
 /*  */
@@ -190,25 +187,24 @@ phy_RFSerialRead(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath,
        /*  For 92S LSSI Read RFLSSIRead */
        /*  For RF A/B write 0x824/82c(does not work in the future) */
        /*  We must use 0x824 for RF A and B to execute read trigger */
-       tmplong = PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter2, bMaskDWord);
+       tmplong = rtl8723au_read32(Adapter, rFPGA0_XA_HSSIParameter2);
        if (eRFPath == RF_PATH_A)
                tmplong2 = tmplong;
        else
-               tmplong2 = PHY_QueryBBReg(Adapter, pPhyReg->rfHSSIPara2,
-                                         bMaskDWord);
+               tmplong2 = rtl8723au_read32(Adapter, pPhyReg->rfHSSIPara2);
 
        tmplong2 = (tmplong2 & ~bLSSIReadAddress) |
                (NewOffset << 23) | bLSSIReadEdge;      /* T65 RF */
 
-       PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2,
-                    bMaskDWord, tmplong & (~bLSSIReadEdge));
+       rtl8723au_write32(Adapter, rFPGA0_XA_HSSIParameter2,
+                         tmplong & (~bLSSIReadEdge));
        udelay(10);/*  PlatformStallExecution(10); */
 
-       PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, bMaskDWord, tmplong2);
+       rtl8723au_write32(Adapter, pPhyReg->rfHSSIPara2, tmplong2);
        udelay(100);/* PlatformStallExecution(100); */
 
-       PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2, bMaskDWord,
-                    tmplong | bLSSIReadEdge);
+       rtl8723au_write32(Adapter, rFPGA0_XA_HSSIParameter2,
+                         tmplong | bLSSIReadEdge);
        udelay(10);/* PlatformStallExecution(10); */
 
        if (eRFPath == RF_PATH_A)
@@ -319,9 +315,7 @@ phy_RFSerialWrite(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath,
        /*  */
        /*  Write Operation */
        /*  */
-       PHY_SetBBReg(Adapter, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
-       /* RTPRINT(FPHY, PHY_RFW, ("RFW-%d Addr[0x%lx]= 0x%lx\n", eRFPath, pPhyReg->rf3wireOffset, DataAndAddr)); */
-
+       rtl8723au_write32(Adapter, pPhyReg->rf3wireOffset, DataAndAddr);
 }
 
 /**
@@ -392,7 +386,7 @@ PHY_SetRFReg(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath,
        if (BitMask != bRFRegOffsetMask) {
                Original_Value = phy_RFSerialRead(Adapter, eRFPath, RegAddr);
                BitShift =  phy_CalculateBitShift(BitMask);
-               Data = ((Original_Value & (~BitMask)) | (Data << BitShift));
+               Data = (Original_Value & (~BitMask)) | (Data << BitShift);
        }
 
        phy_RFSerialWrite(Adapter, eRFPath, RegAddr, Data);
@@ -419,7 +413,6 @@ PHY_SetRFReg(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath,
 int PHY_MACConfig8723A(struct rtw_adapter *Adapter)
 {
        struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
-       bool is92C = IS_92C_SERIAL(pHalData->VersionID);
 
        /*  */
        /*  Config MAC */
@@ -427,9 +420,9 @@ int PHY_MACConfig8723A(struct rtw_adapter *Adapter)
        ODM_ReadAndConfig_MAC_REG_8723A(&pHalData->odmpriv);
 
        /*  2010.07.13 AMPDU aggregation number 9 */
-       /* rtw_write16(Adapter, REG_MAX_AGGR_NUM, MAX_AGGR_NUM); */
        rtl8723au_write8(Adapter, REG_MAX_AGGR_NUM, 0x0A);
-       if (is92C && (BOARD_USB_DONGLE == pHalData->BoardType))
+       if (pHalData->rf_type == RF_2T2R &&
+           BOARD_USB_DONGLE == pHalData->BoardType)
                rtl8723au_write8(Adapter, 0x40, 0x04);
 
        return _SUCCESS;
@@ -552,131 +545,51 @@ storePwrIndexDiffRateOffset(struct rtw_adapter *Adapter, u32 RegAddr,
 
        if (RegAddr == rTxAGC_A_Rate18_06) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][0] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][0])); */
        }
        if (RegAddr == rTxAGC_A_Rate54_24) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][1] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][1])); */
        }
        if (RegAddr == rTxAGC_A_CCK1_Mcs32) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][6] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][6] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][6])); */
        }
        if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0xffffff00) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][7] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][7] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][7])); */
        }
        if (RegAddr == rTxAGC_A_Mcs03_Mcs00) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][2] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][2])); */
        }
        if (RegAddr == rTxAGC_A_Mcs07_Mcs04) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][3] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][3])); */
        }
        if (RegAddr == rTxAGC_A_Mcs11_Mcs08) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][4] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][4])); */
        }
        if (RegAddr == rTxAGC_A_Mcs15_Mcs12) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][5] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][5])); */
        }
        if (RegAddr == rTxAGC_B_Rate18_06) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][8] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][8] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][8])); */
        }
        if (RegAddr == rTxAGC_B_Rate54_24) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][9] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][9])); */
        }
        if (RegAddr == rTxAGC_B_CCK1_55_Mcs32) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][14] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][14])); */
        }
        if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0x000000ff) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][15] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][15])); */
        }
        if (RegAddr == rTxAGC_B_Mcs03_Mcs00) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][10] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][10])); */
        }
        if (RegAddr == rTxAGC_B_Mcs07_Mcs04) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][11] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][11])); */
        }
        if (RegAddr == rTxAGC_B_Mcs11_Mcs08) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][12] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][12])); */
        }
        if (RegAddr == rTxAGC_B_Mcs15_Mcs12) {
                pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][13] = Data;
-               /* RT_TRACE(COMP_INIT, DBG_TRACE,
-                  ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%lx\n",
-                  pHalData->pwrGroupCnt, */
-               /*      pHalData->MCSTxPowerLevelOriginalOffset[
-                       pHalData->pwrGroupCnt][13])); */
                pHalData->pwrGroupCnt++;
        }
 }
@@ -831,7 +744,7 @@ PHY_BBConfig8723A(struct rtw_adapter *Adapter)
                             (CrystalCap | (CrystalCap << 6)));
        }
 
-       PHY_SetBBReg(Adapter, REG_LDOA15_CTRL, bMaskDWord, 0x01572505);
+       rtl8723au_write32(Adapter, REG_LDOA15_CTRL, 0x01572505);
        return rtStatus;
 }
 
@@ -920,10 +833,6 @@ _PHY_SetBWMode23a92C(struct rtw_adapter *Adapter)
        u8 regBwOpMode;
        u8 regRRSR_RSC;
 
-       /*  There is no 40MHz mode in RF_8225. */
-       if (pHalData->rf_chip == RF_8225)
-               return;
-
        if (Adapter->bDriverStopped)
                return;
 
@@ -982,10 +891,7 @@ _PHY_SetBWMode23a92C(struct rtw_adapter *Adapter)
                break;
 
        default:
-               /*RT_TRACE(COMP_DBG, DBG_LOUD,
-                 ("PHY_SetBWMode23aCallback8192C(): unknown Bandwidth: %#X\n" \
-                 , pHalData->CurrentChannelBW));*/
-                       break;
+               break;
        }
        /* Skip over setting of J-mode in BB register here. Default value
           is "None J mode". Emily 20070315 */
@@ -994,41 +900,8 @@ _PHY_SetBWMode23a92C(struct rtw_adapter *Adapter)
        /* NowL = PlatformEFIORead4Byte(Adapter, TSFR); */
        /* NowH = PlatformEFIORead4Byte(Adapter, TSFR+4); */
        /* EndTime = ((u64)NowH << 32) + NowL; */
-       /* RT_TRACE(COMP_SCAN, DBG_LOUD, ("SetBWMode23aCallback8190Pci: time
-          of SetBWMode23a = %I64d us!\n", (EndTime - BeginTime))); */
-
-       /* 3<3>Set RF related register */
-       switch (pHalData->rf_chip) {
-       case RF_8225:
-               /* PHY_SetRF8225Bandwidth(Adapter,
-                  pHalData->CurrentChannelBW); */
-               break;
-
-       case RF_8256:
-               /*  Please implement this function in Hal8190PciPhy8256.c */
-               /* PHY_SetRF8256Bandwidth(Adapter,
-                  pHalData->CurrentChannelBW); */
-               break;
-
-       case RF_8258:
-               /*  Please implement this function in Hal8190PciPhy8258.c */
-               /*  PHY_SetRF8258Bandwidth(); */
-               break;
-
-       case RF_6052:
-               rtl8723a_phy_rf6052set_bw(Adapter, pHalData->CurrentChannelBW);
-               break;
-
-       default:
-               /* RT_ASSERT(false, ("Unknown RFChipID: %d\n",
-                  pHalData->RFChipID)); */
-               break;
-       }
-
-       /* pHalData->SetBWMode23aInProgress = false; */
 
-       /* RT_TRACE(COMP_SCAN, DBG_LOUD,
-          ("<== PHY_SetBWMode23aCallback8192C() \n")); */
+       rtl8723a_phy_rf6052set_bw(Adapter, pHalData->CurrentChannelBW);
 }
 
  /*-----------------------------------------------------------------------------
index 1aad4384471cfdc5befb5a1d70183a65e1e14dc3..3e3f18634ffef53cb6e971b0b03f2b4b5b76f92f 100644 (file)
@@ -267,8 +267,8 @@ getTxPowerWriteValByRegulatory(struct rtw_adapter *Adapter, u8 Channel,
                        break;
                case 2: /*  Better regulatory */
                        /*  don't increase any power diff */
-                       writeVal = ((index < 2) ? powerBase0[rf] :
-                                   powerBase1[rf]);
+                       writeVal = (index < 2) ? powerBase0[rf] :
+                                   powerBase1[rf];
                        break;
                case 3: /*  Customer defined power diff. */
                        chnlGroup = 0;
@@ -353,7 +353,7 @@ static void writeOFDMPowerReg(struct rtw_adapter *Adapter, u8 index,
                else
                        RegOffset = RegOffset_B[index];
 
-               PHY_SetBBReg(Adapter, RegOffset, bMaskDWord, writeVal);
+               rtl8723au_write32(Adapter, RegOffset, writeVal);
 
                /*  201005115 Joseph: Set Tx Power diff for Tx power
                    training mechanism. */
index 6075b6dc1beead980e4737aa51bfcfcaca2dad3e..0fec84bcb5d98a33445041d15a98055a111d52e7 100644 (file)
@@ -48,7 +48,7 @@ int rtl8723au_init_recv_priv(struct rtw_adapter *padapter)
        if (!precvpriv->precv_buf) {
                res = _FAIL;
                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                        ("alloc recv_buf fail!\n"));
+                        "alloc recv_buf fail!\n");
                goto exit;
        }
 
@@ -194,8 +194,8 @@ void update_recvframe_phyinfo(struct recv_frame *precvframe,
        bool matchbssid = false;
        u8 *bssid;
 
-       matchbssid = (!ieee80211_is_ctl(hdr->frame_control) &&
-                     !pattrib->icv_err && !pattrib->crc_err);
+       matchbssid = !ieee80211_is_ctl(hdr->frame_control) &&
+                     !pattrib->icv_err && !pattrib->crc_err;
 
        if (matchbssid) {
                switch (hdr->frame_control &
index 1759487329ab70905561d2aee96d37319b916431..6bf87fe866445accd98d12ac6030a71a2b6c35dc 100644 (file)
@@ -42,7 +42,7 @@ static int urb_zero_packet_chk(struct rtw_adapter *padapter, int sz)
 
 static void rtl8192cu_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;
@@ -130,7 +130,7 @@ static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw)
        }
 }
 
-static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bagg_pkt)
+static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz)
 {
        int     pull = 0;
        uint    qsel;
@@ -143,7 +143,7 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag
        struct mlme_ext_info    *pmlmeinfo = &pmlmeext->mlmext_info;
        int     bmcst = is_multicast_ether_addr(pattrib->ra);
 
-       if ((!bagg_pkt) && (urb_zero_packet_chk(padapter, sz) == 0)) {
+       if (urb_zero_packet_chk(padapter, sz) == 0) {
                ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ);
                pull = 1;
                pxmitframe->pkt_offset--;
@@ -272,7 +272,8 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag
        if (bmcst)
                ptxdesc->txdw0 |= cpu_to_le32(BIT(24));
 
-       RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("offset0-txdesc = 0x%x\n", ptxdesc->txdw0));
+       RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+                "offset0-txdesc = 0x%x\n", ptxdesc->txdw0);
 
        /* offset 4 */
        /*  pkt_offset, unit:8 bytes padding */
@@ -303,7 +304,7 @@ static int rtw_dump_xframe(struct rtw_adapter *padapter,
 
        mem_addr = pxmitframe->buf_addr;
 
-       RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_dump_xframe()\n"));
+       RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, "rtw_dump_xframe()\n");
 
        for (t = 0; t < pattrib->nr_frags; t++) {
                if (inner_ret != _SUCCESS && ret == _SUCCESS)
@@ -311,7 +312,7 @@ static int rtw_dump_xframe(struct rtw_adapter *padapter,
 
                if (t != (pattrib->nr_frags - 1)) {
                        RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-                                ("pattrib->nr_frags =%d\n", pattrib->nr_frags));
+                                "pattrib->nr_frags =%d\n", pattrib->nr_frags);
 
                        sz = pxmitpriv->frag_len;
                        sz = sz - 4 - pattrib->icv_len;
@@ -320,7 +321,7 @@ static int rtw_dump_xframe(struct rtw_adapter *padapter,
                        sz = pattrib->last_txcmdsz;
                }
 
-               pull = update_txdesc(pxmitframe, mem_addr, sz, false);
+               pull = update_txdesc(pxmitframe, mem_addr, sz);
 
                if (pull) {
                        mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */
@@ -338,7 +339,7 @@ static int rtw_dump_xframe(struct rtw_adapter *padapter,
                rtw_count_tx_stats23a(padapter, pxmitframe, sz);
 
                RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
-                        ("rtw_write_port, w_sz =%d\n", w_sz));
+                        "rtw_write_port, w_sz =%d\n", w_sz);
 
                mem_addr += w_sz;
 
@@ -365,7 +366,7 @@ bool rtl8723au_xmitframe_complete(struct rtw_adapter *padapter,
        phwxmits = pxmitpriv->hwxmits;
        hwentry = pxmitpriv->hwxmit_entry;
 
-       RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("xmitframe_complete()\n"));
+       RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, "xmitframe_complete()\n");
 
        if (pxmitbuf == NULL) {
                pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv);
@@ -388,7 +389,8 @@ bool rtl8723au_xmitframe_complete(struct rtw_adapter *padapter,
                        rtw_os_xmit_complete23a(padapter, pxmitframe);/* always return ndis_packet after rtw_xmitframe_coalesce23a */
                }
 
-               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("xmitframe_complete(): rtw_dump_xframe\n"));
+               RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+                        "xmitframe_complete(): rtw_dump_xframe\n");
 
                if (res == _SUCCESS) {
                        rtw_dump_xframe(padapter, pxmitframe);
@@ -481,7 +483,7 @@ enqueue:
 
        if (res != _SUCCESS) {
                RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
-                        ("pre_xmitframe: enqueue xmitframe fail\n"));
+                        "pre_xmitframe: enqueue xmitframe fail\n");
                rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
 
                /*  Trick, make the statistics correct */
index adbf1c2dd383ac9fd921e422b143bc40cb84e99c..42ae29d26302d4e1f2649754debdcd981d80c82b 100644 (file)
@@ -447,22 +447,8 @@ static void _InitRetryFunction(struct rtw_adapter *Adapter)
 static void _InitRFType(struct rtw_adapter *Adapter)
 {
        struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
-       bool is92CU = IS_92C_SERIAL(pHalData->VersionID);
 
-       pHalData->rf_chip = RF_6052;
-
-       if (!is92CU) {
-               pHalData->rf_type = RF_1T1R;
-               DBG_8723A("Set RF Chip ID to RF_6052 and RF type to 1T1R.\n");
-               return;
-       }
-
-       /*  TODO: Consider that EEPROM set 92CU to 1T1R later. */
-       /*  Force to overwrite setting according to chip version. Ignore
-           EEPROM setting. */
-       /* pHalData->RF_Type = is92CU ? RF_2T2R : RF_1T1R; */
-       MSG_8723A("Set RF Chip ID to RF_6052 and RF type to %d.\n",
-                 pHalData->rf_type);
+       pHalData->rf_type = RF_1T1R;
 }
 
 /*  Set CCK and OFDM Block "ON" */
@@ -530,7 +516,7 @@ int rtl8723au_hal_init(struct rtw_adapter *Adapter)
        /*  Check if MAC has already power on. by tynli. 2011.05.27. */
        val8 = rtl8723au_read8(Adapter, REG_CR);
        RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                ("%s: REG_CR 0x100 = 0x%02x\n", __func__, val8));
+                "%s: REG_CR 0x100 = 0x%02x\n", __func__, val8);
        /* Fix 92DU-VC S3 hang with the reason is that secondary mac is not
           initialized. */
        /* 0x100 value of first mac is 0xEA while 0x100 value of secondary
@@ -540,13 +526,13 @@ int rtl8723au_hal_init(struct rtw_adapter *Adapter)
        } else {
                mac_on = true;
                RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                        ("%s: MAC has already power on\n", __func__));
+                        "%s: MAC has already power on\n", __func__);
        }
 
        status = _InitPowerOn(Adapter);
        if (status == _FAIL) {
                RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
-                        ("Failed to init power on!\n"));
+                        "Failed to init power on!\n");
                goto exit;
        }
 
@@ -561,7 +547,7 @@ int rtl8723au_hal_init(struct rtw_adapter *Adapter)
                status =  InitLLTTable23a(Adapter, boundary);
                if (status == _FAIL) {
                        RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
-                                ("Failed to init LLT table\n"));
+                                "Failed to init LLT table\n");
                        goto exit;
                }
        }
@@ -572,12 +558,10 @@ int rtl8723au_hal_init(struct rtw_adapter *Adapter)
        status = rtl8723a_FirmwareDownload(Adapter);
        if (status != _SUCCESS) {
                Adapter->bFWReady = false;
-               pHalData->fw_ractrl = false;
                DBG_8723A("fw download fail!\n");
                goto exit;
        } else {
                Adapter->bFWReady = true;
-               pHalData->fw_ractrl = true;
                DBG_8723A("fw download ok!\n");
        }
 
@@ -625,17 +609,22 @@ int rtl8723au_hal_init(struct rtw_adapter *Adapter)
        }
 
        /* reducing 80M spur */
-       PHY_SetBBReg(Adapter, REG_AFE_XTAL_CTRL, bMaskDWord, 0x0381808d);
-       PHY_SetBBReg(Adapter, REG_AFE_PLL_CTRL, bMaskDWord, 0xf0ffff83);
-       PHY_SetBBReg(Adapter, REG_AFE_PLL_CTRL, bMaskDWord, 0xf0ffff82);
-       PHY_SetBBReg(Adapter, REG_AFE_PLL_CTRL, bMaskDWord, 0xf0ffff83);
+       rtl8723au_write32(Adapter, REG_AFE_XTAL_CTRL, 0x0381808d);
+       rtl8723au_write32(Adapter, REG_AFE_PLL_CTRL, 0xf0ffff83);
+       rtl8723au_write32(Adapter, REG_AFE_PLL_CTRL, 0xf0ffff82);
+       rtl8723au_write32(Adapter, REG_AFE_PLL_CTRL, 0xf0ffff83);
 
        /* RFSW Control */
-       PHY_SetBBReg(Adapter, rFPGA0_TxInfo, bMaskDWord, 0x00000003);   /* 0x804[14]= 0 */
-       PHY_SetBBReg(Adapter, rFPGA0_XAB_RFInterfaceSW, bMaskDWord, 0x07000760);        /* 0x870[6:5]= b'11 */
-       PHY_SetBBReg(Adapter, rFPGA0_XA_RFInterfaceOE, bMaskDWord, 0x66F60210); /* 0x860[6:5]= b'00 */
+       /* 0x804[14]= 0 */
+       rtl8723au_write32(Adapter, rFPGA0_TxInfo, 0x00000003);
+       /* 0x870[6:5]= b'11 */
+       rtl8723au_write32(Adapter, rFPGA0_XAB_RFInterfaceSW, 0x07000760);
+       /* 0x860[6:5]= b'00 */
+       rtl8723au_write32(Adapter, rFPGA0_XA_RFInterfaceOE, 0x66F60210);
 
-       RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("%s: 0x870 = value 0x%x\n", __func__, PHY_QueryBBReg(Adapter, 0x870, bMaskDWord)));
+       RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
+                "%s: 0x870 = value 0x%x\n", __func__,
+                rtl8723au_read32(Adapter, 0x870));
 
        /*  */
        /*  Joseph Note: Keep RfRegChnlVal for later use. */
@@ -747,15 +736,16 @@ int rtl8723au_hal_init(struct rtw_adapter *Adapter)
 
        rtl8723a_InitHalDm(Adapter);
 
-       val8 = ((WiFiNavUpperUs + HAL_8723A_NAV_UPPER_UNIT - 1) /
-               HAL_8723A_NAV_UPPER_UNIT);
+       val8 = (WiFiNavUpperUs + HAL_8723A_NAV_UPPER_UNIT - 1) /
+               HAL_8723A_NAV_UPPER_UNIT;
        rtl8723au_write8(Adapter, REG_NAV_UPPER, val8);
 
        /*  2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test, but we need to fin root cause. */
        if (((rtl8723au_read32(Adapter, rFPGA0_RFMOD) & 0xFF000000) !=
             0x83000000)) {
                PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT(24), 1);
-               RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("%s: IQK fail recorver\n", __func__));
+               RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
+                        "%s: IQK fail recover\n", __func__);
        }
 
        /* ack for xmit mgmt frames. */
@@ -806,19 +796,18 @@ static void phy_SsPwrSwitch92CU(struct rtw_adapter *Adapter,
 
                /* AFE */
                if (pHalData->rf_type ==  RF_2T2R)
-                       PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
-                                    0x63DB25A0);
+                       rtl8723au_write32(Adapter, rRx_Wait_CCA, 0x63DB25A0);
                else if (pHalData->rf_type ==  RF_1T1R)
-                       PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
-                                    0x631B25A0);
+                       rtl8723au_write32(Adapter, rRx_Wait_CCA, 0x631B25A0);
 
                /*  4. issue 3-wire command that RF set to Rx idle
                    mode. This is used to re-write the RX idle mode. */
                /*  We can only prvide a usual value instead and then
                    HW will modify the value by itself. */
-               PHY_SetRFReg(Adapter, RF_PATH_A, 0, bRFRegOffsetMask, 0x32D95);
+               PHY_SetRFReg(Adapter, RF_PATH_A, RF_AC,
+                            bRFRegOffsetMask, 0x32D95);
                if (pHalData->rf_type ==  RF_2T2R) {
-                       PHY_SetRFReg(Adapter, RF_PATH_B, 0,
+                       PHY_SetRFReg(Adapter, RF_PATH_B, RF_AC,
                                     bRFRegOffsetMask, 0x32D95);
                }
                break;
@@ -829,7 +818,7 @@ static void phy_SsPwrSwitch92CU(struct rtw_adapter *Adapter,
                else
                        sps0 &= ~(BIT(0) | BIT(3));
 
-               RT_TRACE(_module_hal_init_c_, _drv_err_, ("SS LVL1\n"));
+               RT_TRACE(_module_hal_init_c_, _drv_err_, "SS LVL1\n");
                /*  Disable RF and BB only for SelectSuspend. */
 
                /*  1. Set BB/RF to shutdown. */
@@ -840,13 +829,11 @@ static void phy_SsPwrSwitch92CU(struct rtw_adapter *Adapter,
                                                for packet detection */
                /*      (4) Reg800[1] = 1       enable preamble power saving */
                Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF0] =
-                       PHY_QueryBBReg(Adapter, rFPGA0_XAB_RFParameter,
-                                      bMaskDWord);
+                       rtl8723au_read32(Adapter, rFPGA0_XAB_RFParameter);
                Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF1] =
-                       PHY_QueryBBReg(Adapter, rOFDM0_TRxPathEnable,
-                                      bMaskDWord);
+                       rtl8723au_read32(Adapter, rOFDM0_TRxPathEnable);
                Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF2] =
-                       PHY_QueryBBReg(Adapter, rFPGA0_RFMOD, bMaskDWord);
+                       rtl8723au_read32(Adapter, rFPGA0_RFMOD);
                if (pHalData->rf_type ==  RF_2T2R) {
                        PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
                                     0x380038, 0);
@@ -858,18 +845,16 @@ static void phy_SsPwrSwitch92CU(struct rtw_adapter *Adapter,
 
                /*  2 .AFE control register to power down. bit[30:22] */
                Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_AFE0] =
-                       PHY_QueryBBReg(Adapter, rRx_Wait_CCA, bMaskDWord);
+                       rtl8723au_read32(Adapter, rRx_Wait_CCA);
                if (pHalData->rf_type ==  RF_2T2R)
-                       PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
-                                    0x00DB25A0);
+                       rtl8723au_write32(Adapter, rRx_Wait_CCA, 0x00DB25A0);
                else if (pHalData->rf_type ==  RF_1T1R)
-                       PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
-                                    0x001B25A0);
+                       rtl8723au_write32(Adapter, rRx_Wait_CCA, 0x001B25A0);
 
                /*  3. issue 3-wire command that RF set to power down.*/
-               PHY_SetRFReg(Adapter, RF_PATH_A, 0, bRFRegOffsetMask, 0);
+               PHY_SetRFReg(Adapter, RF_PATH_A, RF_AC, bRFRegOffsetMask, 0);
                if (pHalData->rf_type ==  RF_2T2R)
-                       PHY_SetRFReg(Adapter, RF_PATH_B, 0,
+                       PHY_SetRFReg(Adapter, RF_PATH_B, RF_AC,
                                     bRFRegOffsetMask, 0);
 
                /*  4. Force PFM , disable SPS18_LDO_Marco_Block */
@@ -949,14 +934,14 @@ int rtl8723au_inirp_init(struct rtw_adapter *Adapter)
 
        status = _SUCCESS;
 
-       RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("===> usb_inirp_init\n"));
+       RT_TRACE(_module_hci_hal_init_c_, _drv_info_, "===> usb_inirp_init\n");
 
        /* issue Rx irp to receive data */
        precvbuf = (struct recv_buf *)precvpriv->precv_buf;
        for (i = 0; i < NR_RECVBUFF; i++) {
                if (rtl8723au_read_port(Adapter, 0, precvbuf) == _FAIL) {
                        RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
-                                ("usb_rx_init: usb_read_port error\n"));
+                                "usb_rx_init: usb_read_port error\n");
                        status = _FAIL;
                        goto exit;
                }
@@ -964,7 +949,7 @@ int rtl8723au_inirp_init(struct rtw_adapter *Adapter)
        }
        if (rtl8723au_read_interrupt(Adapter) == _FAIL) {
                RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
-                        ("%s: usb_read_interrupt error\n", __func__));
+                        "%s: usb_read_interrupt error\n", __func__);
                status = _FAIL;
        }
        pHalData->IntrMask[0] = rtl8723au_read32(Adapter, REG_USB_HIMR);
@@ -973,7 +958,7 @@ int rtl8723au_inirp_init(struct rtw_adapter *Adapter)
        rtl8723au_write32(Adapter, REG_USB_HIMR, pHalData->IntrMask[0]);
 exit:
        RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                ("<=== usb_inirp_init\n"));
+                "<=== usb_inirp_init\n");
        return status;
 }
 
@@ -982,7 +967,7 @@ int rtl8723au_inirp_deinit(struct rtw_adapter *Adapter)
        struct hal_data_8723a   *pHalData = GET_HAL_DATA(Adapter);
 
        RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                ("\n ===> usb_rx_deinit\n"));
+                "===> usb_rx_deinit\n");
        rtl8723au_read_port_cancel(Adapter);
        pHalData->IntrMask[0] = rtl8723au_read32(Adapter, REG_USB_HIMR);
        MSG_8723A("%s pHalData->IntrMask = 0x%04x\n", __func__,
@@ -990,7 +975,7 @@ int rtl8723au_inirp_deinit(struct rtw_adapter *Adapter)
        pHalData->IntrMask[0] = 0x0;
        rtl8723au_write32(Adapter, REG_USB_HIMR, pHalData->IntrMask[0]);
        RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
-                ("\n <=== usb_rx_deinit\n"));
+                "<=== usb_rx_deinit\n");
        return _SUCCESS;
 }
 
@@ -1037,11 +1022,10 @@ static void Hal_EfuseParseMACAddr_8723AU(struct rtw_adapter *padapter,
        }
 
        RT_TRACE(_module_hci_hal_init_c_, _drv_notice_,
-                ("Hal_EfuseParseMACAddr_8723AU: Permanent Address =%02x:%02x:"
-                 "%02x:%02x:%02x:%02x\n",
-                 pEEPROM->mac_addr[0], pEEPROM->mac_addr[1],
-                 pEEPROM->mac_addr[2], pEEPROM->mac_addr[3],
-                 pEEPROM->mac_addr[4], pEEPROM->mac_addr[5]));
+                "Hal_EfuseParseMACAddr_8723AU: Permanent Address =%02x:%02x:%02x:%02x:%02x:%02x\n",
+                pEEPROM->mac_addr[0], pEEPROM->mac_addr[1],
+                pEEPROM->mac_addr[2], pEEPROM->mac_addr[3],
+                pEEPROM->mac_addr[4], pEEPROM->mac_addr[5]);
 }
 
 static void readAdapterInfo(struct rtw_adapter *padapter)
@@ -1102,13 +1086,6 @@ static void _ReadPROMContent(struct rtw_adapter *Adapter)
        readAdapterInfo(Adapter);
 }
 
-static void _ReadRFType(struct rtw_adapter *Adapter)
-{
-       struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
-
-       pHalData->rf_chip = RF_6052;
-}
-
 /*  */
 /*     Description: */
 /*             We should set Efuse cell selection to WiFi cell in default. */
@@ -1138,12 +1115,8 @@ void rtl8723a_read_adapter_info(struct rtw_adapter *Adapter)
 
        hal_EfuseCellSel(Adapter);
 
-       _ReadRFType(Adapter);/* rf_chip -> _InitRFType() */
        _ReadPROMContent(Adapter);
 
-       /* MSG_8723A("%s()(done), rf_chip = 0x%x, rf_type = 0x%x\n",
-          __func__, pHalData->rf_chip, pHalData->rf_type); */
-
        MSG_8723A("<==== _ReadAdapterInfo8723AU in %d ms\n",
                  jiffies_to_msecs(jiffies - start));
 }
@@ -1192,8 +1165,6 @@ int GetHalDefVar8192CUsb(struct rtw_adapter *Adapter,
        }
                break;
        default:
-               /* RT_TRACE(COMP_INIT, DBG_WARNING, ("GetHalDefVar8192CUsb(): "
-                  "Unkown variable: %d!\n", eVariable)); */
                bResult = _FAIL;
                break;
        }
@@ -1211,7 +1182,7 @@ void rtl8723a_update_ramask(struct rtw_adapter *padapter,
        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
        struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
-       u8 init_rate, networkType, raid;
+       u8 init_rate, networkType, raid, arg;
        u32 mask, rate_bitmap;
        u8 shortGIrate = false;
        int supportRateNum;
@@ -1283,27 +1254,15 @@ void rtl8723a_update_ramask(struct rtw_adapter *padapter,
 
        init_rate = get_highest_rate_idx23a(mask) & 0x3f;
 
-       if (pHalData->fw_ractrl == true) {
-               u8 arg = 0;
-
-               arg = mac_id & 0x1f;/* MACID */
+       arg = mac_id & 0x1f;/* MACID */
+       arg |= BIT(7);
 
-               arg |= BIT(7);
+       if (shortGIrate == true)
+               arg |= BIT(5);
 
-               if (shortGIrate == true)
-                       arg |= BIT(5);
+       DBG_8723A("update raid entry, mask = 0x%x, arg = 0x%x\n", mask, arg);
 
-               DBG_8723A("update raid entry, mask = 0x%x, arg = 0x%x\n",
-                         mask, arg);
-
-               rtl8723a_set_raid_cmd(padapter, mask, arg);
-       } else {
-               if (shortGIrate == true)
-                       init_rate |= BIT(6);
-
-               rtl8723au_write8(padapter, (REG_INIDATA_RATE_SEL + mac_id),
-                                init_rate);
-       }
+       rtl8723a_set_raid_cmd(padapter, mask, arg);
 
        /* set ra_id */
        psta->raid = raid;
index a6d16adce107fa788776552a23f61ff140a4487c..371e6b373420c18a950828c9e14b4fa87b59d467 100644 (file)
@@ -297,14 +297,12 @@ urb_submit:
                case -ENODEV:
                case -ESHUTDOWN:
                        RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                                ("usb_read_port_complete:bSurpriseRemoved ="
-                                 "true\n"));
+                                "usb_read_port_complete:bSurpriseRemoved =true\n");
                        /* Fall Through here */
                case -ENOENT:
                        padapter->bDriverStopped = true;
                        RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                                ("usb_read_port_complete:bDriverStopped ="
-                                 "true\n"));
+                                "usb_read_port_complete:bDriverStopped =true\n");
                        break;
                case -EPROTO:
                        break;
@@ -367,16 +365,16 @@ static int recvbuf2recvframe(struct rtw_adapter *padapter, struct sk_buff *pskb)
 
        do {
                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                        ("recvbuf2recvframe: rxdesc = offsset 0:0x%08x, "
-                         "4:0x%08x, 8:0x%08x, C:0x%08x\n", prxstat->rxdw0,
-                         prxstat->rxdw1, prxstat->rxdw2, prxstat->rxdw4));
+                        "recvbuf2recvframe: rxdesc = offsset 0:0x%08x, 4:0x%08x, 8:0x%08x, C:0x%08x\n",
+                        prxstat->rxdw0, prxstat->rxdw1,
+                        prxstat->rxdw2, prxstat->rxdw4);
 
                prxstat = (struct recv_stat *)pbuf;
 
                precvframe = rtw_alloc_recvframe23a(pfree_recv_queue);
                if (!precvframe) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                ("recvbuf2recvframe: precvframe == NULL\n"));
+                                "recvbuf2recvframe: precvframe == NULL\n");
                        DBG_8723A("%s()-%d: rtw_alloc_recvframe23a() failed! RX "
                                  "Drop!\n", __func__, __LINE__);
                        goto _exit_recvbuf2recvframe;
@@ -400,7 +398,7 @@ static int recvbuf2recvframe(struct rtw_adapter *padapter, struct sk_buff *pskb)
 
                if (pattrib->pkt_len <= 0 || pkt_offset > transfer_len) {
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-                                ("recvbuf2recvframe: pkt_len<= 0\n"));
+                                "recvbuf2recvframe: pkt_len<= 0\n");
                        DBG_8723A("%s()-%d: RX Warning!\n",
                                  __func__, __LINE__);
                        rtw_free_recvframe23a(precvframe);
@@ -471,8 +469,7 @@ static int recvbuf2recvframe(struct rtw_adapter *padapter, struct sk_buff *pskb)
 
                if (rtw_recv_entry23a(precvframe) != _SUCCESS)
                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
-                                ("recvbuf2recvframe: rtw_recv_entry23a"
-                                 "(precvframe) != _SUCCESS\n"));
+                                "recvbuf2recvframe: rtw_recv_entry23a(precvframe) != _SUCCESS\n");
 
                pkt_cnt--;
                transfer_len -= pkt_offset;
@@ -520,16 +517,15 @@ static void usb_read_port_complete(struct urb *purb)
        struct recv_priv *precvpriv = &padapter->recvpriv;
 
        RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                ("usb_read_port_complete!!!\n"));
+                "usb_read_port_complete!!!\n");
 
        precvpriv->rx_pending_cnt--;
 
        if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
            padapter->bReadPortCancel) {
                RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                        ("usb_read_port_complete:bDriverStopped(%d) OR "
-                         "bSurpriseRemoved(%d)\n", padapter->bDriverStopped,
-                         padapter->bSurpriseRemoved));
+                        "usb_read_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n",
+                        padapter->bDriverStopped, padapter->bSurpriseRemoved);
 
                DBG_8723A("%s()-%d: RX Warning! bDriverStopped(%d) OR "
                          "bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
@@ -542,9 +538,7 @@ static void usb_read_port_complete(struct urb *purb)
                if (purb->actual_length > MAX_RECVBUF_SZ ||
                    purb->actual_length < RXDESC_SIZE) {
                        RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                                ("usb_read_port_complete: (purb->actual_"
-                                 "length > MAX_RECVBUF_SZ) || (purb->actual_"
-                                 "length < RXDESC_SIZE)\n"));
+                                "usb_read_port_complete: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)\n");
                        rtl8723au_read_port(padapter, 0, precvbuf);
                        DBG_8723A("%s()-%d: RX Warning!\n",
                                  __func__, __LINE__);
@@ -564,8 +558,8 @@ static void usb_read_port_complete(struct urb *purb)
                }
        } else {
                RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                        ("usb_read_port_complete : purb->status(%d) != 0 \n",
-                         purb->status));
+                        "usb_read_port_complete : purb->status(%d) != 0\n",
+                        purb->status);
                skb_put(precvbuf->pskb, purb->actual_length);
                precvbuf->pskb = NULL;
 
@@ -583,14 +577,12 @@ static void usb_read_port_complete(struct urb *purb)
                case -ENODEV:
                case -ESHUTDOWN:
                        RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                                ("usb_read_port_complete:bSurprise"
-                                 "Removed = true\n"));
+                                "usb_read_port_complete:bSurpriseRemoved = true\n");
                        /* Intentional fall through here */
                case -ENOENT:
                        padapter->bDriverStopped = true;
                        RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                                ("usb_read_port_complete:"
-                                 "bDriverStopped = true\n"));
+                                "usb_read_port_complete:bDriverStopped = true\n");
                        break;
                case -EPROTO:
                case -EOVERFLOW:
@@ -620,14 +612,13 @@ int rtl8723au_read_port(struct rtw_adapter *adapter, u32 cnt,
 
        if (adapter->bDriverStopped || adapter->bSurpriseRemoved) {
                RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                        ("usb_read_port:(padapter->bDriverStopped ||"
-                         "padapter->bSurpriseRemoved)!!!\n"));
+                        "usb_read_port:(padapter->bDriverStopped ||padapter->bSurpriseRemoved)!!!\n");
                return _FAIL;
        }
 
        if (!precvbuf) {
                RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                        ("usb_read_port:precvbuf == NULL\n"));
+                        "usb_read_port:precvbuf == NULL\n");
                return _FAIL;
        }
 
@@ -638,7 +629,8 @@ int rtl8723au_read_port(struct rtw_adapter *adapter, u32 cnt,
        if (!precvbuf->pskb) {
                precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
                if (precvbuf->pskb == NULL) {
-                       RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n"));
+                       RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+                                "init_recvbuf(): alloc_skb fail!\n");
                        return _FAIL;
                }
 
@@ -661,8 +653,8 @@ int rtl8723au_read_port(struct rtw_adapter *adapter, u32 cnt,
        err = usb_submit_urb(purb, GFP_ATOMIC);
        if ((err) && (err != -EPERM)) {
                RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                        ("cannot submit rx in-token(err = 0x%.8x), URB_STATUS "
-                         "= 0x%.8x", err, purb->status));
+                        "cannot submit rx in-token(err = 0x%.8x), URB_STATUS = 0x%.8x\n",
+                        err, purb->status);
                DBG_8723A("cannot submit rx in-token(err = 0x%08x), urb_status "
                          "= %d\n", err, purb->status);
                ret = _FAIL;
index 2247d98747194c23ef76f09eaaccf1a8455d8347..bcf36579f43aea293b36d54068c4aff0a48ff8b5 100644 (file)
@@ -16,9 +16,6 @@
 #ifndef __INC_HAL8723PHYCFG_H__
 #define __INC_HAL8723PHYCFG_H__
 
-/*--------------------------Define Parameters-------------------------------*/
-#define MAX_AGGR_NUM   0x0909
-
 /*------------------------------Define structure----------------------------*/
 enum RF_RADIO_PATH {
        RF_PATH_A = 0,                  /* Radio Path A */
@@ -39,15 +36,6 @@ enum WIRELESS_MODE {
        WIRELESS_MODE_AC        = BIT(6)
 };
 
-/* BB/RF related */
-enum rf_type_8190p {
-       RF_TYPE_MIN,            /*  0 */
-       RF_8225 = 1,            /*  1 11b/g RF for verification only */
-       RF_8256 = 2,            /*  2 11b/g/n */
-       RF_8258 = 3,            /*  3 11a/b/g/n RF */
-       RF_6052 = 4,            /*  4 11b/g/n RF */
-};
-
 struct bb_reg_define {
        u32 rfintfs;            /*  set software control: */
                                /*              0x870~0x877[8 bytes] */
index 607b71f6e1e4ca754c59afdffbc19cdae8d0cfef..2a0e4ea7afadc66b30874eb3fb7d426e932f7cf0 100644 (file)
@@ -51,30 +51,17 @@ 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)
@@ -108,17 +95,8 @@ struct hal_version {
 #define IS_CHIP_VENDOR_UMC(version)            \
        ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_UMC) ? true : false)
 
-#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_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)
index 7c31865e9865a08c96c8fb7f95c935fd5e5a113d..9c50320b2100008299b69c3501dd87d54a33df2d 100644 (file)
 #define RATE_36M                               BIT(9)
 #define RATE_48M                               BIT(10)
 #define RATE_54M                               BIT(11)
-/* MCS 1 Spatial Stream */
-#define RATE_MCS0                              BIT(12)
-#define RATE_MCS1                              BIT(13)
-#define RATE_MCS2                              BIT(14)
-#define RATE_MCS3                              BIT(15)
-#define RATE_MCS4                              BIT(16)
-#define RATE_MCS5                              BIT(17)
-#define RATE_MCS6                              BIT(18)
-#define RATE_MCS7                              BIT(19)
-/* MCS 2 Spatial Stream */
-#define RATE_MCS8                              BIT(20)
-#define RATE_MCS9                              BIT(21)
-#define RATE_MCS10                             BIT(22)
-#define RATE_MCS11                             BIT(23)
-#define RATE_MCS12                             BIT(24)
-#define RATE_MCS13                             BIT(25)
-#define RATE_MCS14                             BIT(26)
-#define RATE_MCS15                             BIT(27)
-
-/*  ALL CCK Rate */
-#define        RATE_ALL_CCK    (RATR_1M | RATR_2M | RATR_55M | RATR_11M)
-#define        RATE_ALL_OFDM_AG                                \
-       (RATR_6M | RATR_9M | RATR_12M | RATR_18M | RATR_24M| \
-        RATR_36M|RATR_48M|RATR_54M)
-#define        RATE_ALL_OFDM_1SS                               \
-       (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | RATR_MCS3 |        \
-        RATR_MCS4 | RATR_MCS5 | RATR_MCS6 | RATR_MCS7)
-#define        RATE_ALL_OFDM_2SS                               \
-       (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | RATR_MCS11|       \
-        RATR_MCS12 | RATR_MCS13 | RATR_MCS14 | RATR_MCS15)
 
 /*------------------------------ Tx Desc definition Macro ------------------------*/
 /* pragma mark -- Tx Desc related definition. -- */
 #define REG_NOA_DESC_COUNT                     0x05EC
 
 #include "HalVerDef.h"
-void dump_chip_info23a(struct hal_version      ChipVersion);
 
 
 u8     /* return the final channel plan decision */
index 404acb52352daa0ef57eb23c19c47975845ad214..b924d47fcfbc570da848780f870c60c16bcfb44b 100644 (file)
 #include <osdep_service.h>
 #include <drv_types.h>
 
-enum RTL871X_HCI_TYPE {
-       RTW_PCIE        = BIT(0),
-       RTW_USB         = BIT(1),
-       RTW_SDIO        = BIT(2),
-       RTW_GSPI        = BIT(3),
-};
-
 enum _CHIP_TYPE {
        NULL_CHIP_TYPE,
        RTL8712_8188S_8191S_8192S,
index cb23cd0349b4ae9e13e23345193641535a19086e..3aa40a32555ed88904837710545c47c5e59217c8 100644 (file)
@@ -171,20 +171,6 @@ struct ieee80211_snap_hdr {
 #define WLAN_REASON_JOIN_WRONG_CHANNEL       65534
 #define WLAN_REASON_EXPIRATION_CHK 65535
 
-
-#define IEEE80211_STATMASK_SIGNAL (1<<0)
-#define IEEE80211_STATMASK_RSSI (1<<1)
-#define IEEE80211_STATMASK_NOISE (1<<2)
-#define IEEE80211_STATMASK_RATE (1<<3)
-#define IEEE80211_STATMASK_WEMASK 0x7
-
-
-#define IEEE80211_CCK_MODULATION    (1<<0)
-#define IEEE80211_OFDM_MODULATION   (1<<1)
-
-#define IEEE80211_24GHZ_BAND     (1<<0)
-#define IEEE80211_52GHZ_BAND     (1<<1)
-
 #define IEEE80211_CCK_RATE_LEN                 4
 #define IEEE80211_NUM_OFDM_RATESLEN    8
 
@@ -265,9 +251,6 @@ join_res:
 > 0: TID
 */
 
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
-
 #define MAXTID 16
 
 #define WME_OUI_TYPE 2
index 5a0561e092ac63bd4bf6ceab81ce360c537ad711..24f2f28c473f4bc832f90deb016252a3062e866f 100644 (file)
@@ -158,27 +158,6 @@ struct false_alarm_stats {
        u32     Cnt_BW_LSC;     /* Gary */
 };
 
-struct pri_cca {
-       u8              PriCCA_flag;
-       u8              intf_flag;
-       u8              intf_type;
-       u8              DupRTS_flag;
-       u8              Monitor_flag;
-};
-
-struct rx_hp {
-       u8              RXHP_flag;
-       u8              PSD_func_trigger;
-       u8              PSD_bitmap_RXHP[80];
-       u8              Pre_IGI;
-       u8              Cur_IGI;
-       u8              Pre_pw_th;
-       u8              Cur_pw_th;
-       bool            First_time_enter;
-       bool            RXHP_enable;
-       u8              TP_Mode;
-};
-
 #define ASSOCIATE_ENTRY_NUM                                    32 /*  Max size of AsocEntry[]. */
 #define        ODM_ASSOCIATE_ENTRY_NUM                         ASSOCIATE_ENTRY_NUM
 
@@ -227,7 +206,6 @@ struct sw_ant_sw {
 
 struct edca_turbo {
        bool bCurrentTurboEDCA;
-       bool bIsCurRDLState;
        u32     prv_traffic_idx; /*  edca turbo */
 };
 
@@ -298,18 +276,14 @@ enum odm_cmninfo {
        /*  Fixed value: */
        /*  */
 
-       ODM_CMNINFO_PLATFORM = 0,
-       ODM_CMNINFO_INTERFACE,                          /*  enum odm_interface_def */
-       ODM_CMNINFO_MP_TEST_CHIP,
-       ODM_CMNINFO_IC_TYPE,                                    /*  enum odm_ic_type_def */
-       ODM_CMNINFO_CUT_VER,                                    /*  enum odm_cut_version */
-       ODM_CMNINFO_FAB_VER,                                    /*  enum odm_fab_version */
-       ODM_CMNINFO_RF_TYPE,                                    /*  enum rf_path_def or enum odm_rf_type? */
-       ODM_CMNINFO_BOARD_TYPE,                         /*  enum odm_board_type */
-       ODM_CMNINFO_EXT_LNA,                                    /*  true */
+       ODM_CMNINFO_MP_TEST_CHIP = 2,
+       ODM_CMNINFO_IC_TYPE,                    /*  enum odm_ic_type_def */
+       ODM_CMNINFO_CUT_VER,                    /*  enum odm_cut_version */
+       ODM_CMNINFO_FAB_VER,                    /*  enum odm_fab_version */
+       ODM_CMNINFO_BOARD_TYPE,                 /*  enum odm_board_type */
+       ODM_CMNINFO_EXT_LNA,                    /*  true */
        ODM_CMNINFO_EXT_PA,
        ODM_CMNINFO_EXT_TRSW,
-       ODM_CMNINFO_PATCH_ID,                           /* CUSTOMER ID */
        ODM_CMNINFO_BINHCT_TEST,
        ODM_CMNINFO_BWIFI_TEST,
        ODM_CMNINFO_SMART_CONCURRENT,
@@ -348,29 +322,7 @@ enum odm_cmninfo {
 /*  Define ODM support ability.  ODM_CMNINFO_ABILITY */
 enum {
        /*  BB ODM section BIT 0-15 */
-       ODM_BB_DIG                              = BIT(0),
-       ODM_BB_RA_MASK                          = BIT(1),
-       ODM_BB_DYNAMIC_TXPWR                    = BIT(2),
-       ODM_BB_FA_CNT                           = BIT(3),
-       ODM_BB_RSSI_MONITOR                     = BIT(4),
-       ODM_BB_CCK_PD                           = BIT(5),
        ODM_BB_ANT_DIV                          = BIT(6),
-       ODM_BB_PWR_SAVE                         = BIT(7),
-       ODM_BB_PWR_TRAIN                        = BIT(8),
-       ODM_BB_RATE_ADAPTIVE                    = BIT(9),
-       ODM_BB_PATH_DIV                         = BIT(10),
-       ODM_BB_PSD                              = BIT(11),
-       ODM_BB_RXHP                             = BIT(12),
-
-       /*  MAC DM section BIT 16-23 */
-       ODM_MAC_EDCA_TURBO                      = BIT(16),
-       ODM_MAC_EARLY_MODE                      = BIT(17),
-
-       /*  RF ODM section BIT 24-31 */
-       ODM_RF_TX_PWR_TRACK                     = BIT(24),
-       ODM_RF_RX_GAIN_TRACK                    = BIT(25),
-       ODM_RF_CALIBRATION                      = BIT(26),
-
 };
 
 /*     ODM_CMNINFO_INTERFACE */
@@ -409,7 +361,6 @@ enum odm_fab_version {
        ODM_UMC         =       1,
 };
 
-/*  ODM_CMNINFO_RF_TYPE */
 /*  For example 1T2R (A+AB = BIT0|BIT4|BIT5) */
 enum rf_path_def {
        ODM_RF_TX_A     =       BIT(0),
@@ -422,18 +373,6 @@ enum rf_path_def {
        ODM_RF_RX_D     =       BIT(7),
 };
 
-
-enum odm_rf_type {
-       ODM_1T1R        =       0,
-       ODM_1T2R        =       1,
-       ODM_2T2R        =       2,
-       ODM_2T3R        =       3,
-       ODM_2T4R        =       4,
-       ODM_3T3R        =       5,
-       ODM_3T4R        =       6,
-       ODM_4T4R        =       7,
-};
-
 /*  ODM Dynamic common info value definition */
 
 enum odm_mac_phy_mode {
@@ -587,33 +526,6 @@ struct odm_rf_cal_t {
        u8      bDPPathBOK;
 };
 
-/*  ODM Dynamic common info value definition */
-struct odm_fat_t {
-       u8      Bssid[6];
-       u8      antsel_rx_keep_0;
-       u8      antsel_rx_keep_1;
-       u8      antsel_rx_keep_2;
-       u32     antSumRSSI[7];
-       u32     antRSSIcnt[7];
-       u32     antAveRSSI[7];
-       u8      FAT_State;
-       u32     TrainIdx;
-       u8      antsel_a[ODM_ASSOCIATE_ENTRY_NUM];
-       u8      antsel_b[ODM_ASSOCIATE_ENTRY_NUM];
-       u8      antsel_c[ODM_ASSOCIATE_ENTRY_NUM];
-       u32     MainAnt_Sum[ODM_ASSOCIATE_ENTRY_NUM];
-       u32     AuxAnt_Sum[ODM_ASSOCIATE_ENTRY_NUM];
-       u32     MainAnt_Cnt[ODM_ASSOCIATE_ENTRY_NUM];
-       u32     AuxAnt_Cnt[ODM_ASSOCIATE_ENTRY_NUM];
-       u8      RxIdleAnt;
-       bool    bBecomeLinked;
-};
-
-enum fat_state {
-       FAT_NORMAL_STATE                = 0,
-       FAT_TRAINING_STATE              = 1,
-};
-
 enum ant_dif_type {
        NO_ANTDIV                       = 0xFF,
        CG_TRX_HW_ANTDIV                = 0x01,
@@ -636,7 +548,6 @@ struct dm_odm_t {
 /*  ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */
        bool                    bCckHighPower;
        u8                      RFPathRxEnable;         /*  ODM_CMNINFO_RFPATH_ENABLE */
-       u8                      ControlChannel;
 /*  ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */
 
 /* 1  COMMON INFORMATION */
@@ -645,16 +556,12 @@ struct dm_odm_t {
 /* HOOK BEFORE REG INIT----------- */
        /*  ODM Support Ability DIG/RATR/TX_PWR_TRACK/ Â¡K¡K = 1/2/3/¡K */
        u32                     SupportAbility;
-       /*  ODM PCIE/USB/SDIO/GSPI = 0/1/2/3 */
-       u8                      SupportInterface;
        /*  ODM composite or independent. Bit oriented/ 92C+92D+ .... or any other type = 1/2/3/... */
        u32                     SupportICType;
        /*  Cut Version TestChip/A-cut/B-cut... = 0/1/2/3/... */
        u8                      CutVersion;
        /*  Fab Version TSMC/UMC = 0/1 */
        u8                      FabVersion;
-       /*  RF Type 4T4R/3T3R/2T2R/1T2R/1T1R/... */
-       u8                      RFType;
        /*  Board Type Normal/HighPower/MiniCard/SLIM/Combo/... = 0/1/2/3/4/... */
        u8                      BoardType;
        /*  with external LNA  NO/Yes = 0/1 */
@@ -663,7 +570,6 @@ struct dm_odm_t {
        u8                      ExtPA;
        /*  with external TRSW  NO/Yes = 0/1 */
        u8                      ExtTRSW;
-       u8                      PatchID; /* Customer ID */
        bool                    bInHctTest;
        bool                    bWIFITest;
 
@@ -703,14 +609,6 @@ struct dm_odm_t {
        /*  2012/01/12 MH For MP, we need to reduce one array pointer for default port.?? */
        struct sta_info *               pODM_StaInfo[ODM_ASSOCIATE_ENTRY_NUM];
 
-       /*  */
-       /*  2012/02/14 MH Add to share 88E ra with other SW team. */
-       /*  We need to colelct all support abilit to a proper area. */
-       /*  */
-       bool                            RaSupport88E;
-
-       /*  Define ........... */
-
        /*  Latest packet phy info (ODM write) */
        struct odm_phy_dbg_info  PhyDbgInfo;
        /* PHY_INFO_88E         PhyInfo; */
@@ -728,11 +626,8 @@ struct dm_odm_t {
        /*  */
        /* ODM Structure */
        /*  */
-       struct odm_fat_t                DM_FatTable;
        struct dig_t    DM_DigTable;
        struct dynamic_pwr_sav          DM_PSTable;
-       struct pri_cca  DM_PriCCA;
-       struct rx_hp            DM_RXHP_Table;
        struct false_alarm_stats        FalseAlmCnt;
        struct false_alarm_stats        FlaseAlmCntBuddyAdapter;
        struct sw_ant_sw                DM_SWAT_Table;
@@ -745,32 +640,11 @@ struct dm_odm_t {
        /*  */
 
        /* PSD */
-       bool                    bUserAssignLevel;
-       u8                      RSSI_BT;                        /* come from BT */
-       bool                    bPSDinProcess;
-
-       /* for rate adaptive, in fact,  88c/92c fw will handle this */
-       u8                      bUseRAMask;
-
+       u8                      RSSI_BT;                /* come from BT */
        struct odm_rate_adapt   RateAdaptive;
 
 
        struct odm_rf_cal_t     RFCalibrateInfo;
-
-       /*  */
-       /*  TX power tracking */
-       /*  */
-       u8                      BbSwingIdxOfdm;
-       u8                      BbSwingIdxOfdmCurrent;
-       u8                      BbSwingIdxOfdmBase;
-       bool                    BbSwingFlagOfdm;
-       u8                      BbSwingIdxCck;
-       u8                      BbSwingIdxCckCurrent;
-       u8                      BbSwingIdxCckBase;
-       bool                    BbSwingFlagCck;
-       /*  */
-       /*  ODM system resource. */
-       /*  */
 };     /*  DM_Dynamic_Mechanism_Structure */
 
 enum odm_rf_content {
@@ -983,6 +857,4 @@ void ODM_SingleDualAntennaDefaultSetting(struct dm_odm_t *pDM_Odm);
 
 bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode);
 
-void odm_dtc(struct dm_odm_t *pDM_Odm);
-
 #endif
index a6cfb6df4cf7353670d28091272be01dcb581157..f2a54d829ed56925a488005591550a6aed5d3237 100644 (file)
@@ -20,9 +20,8 @@ void odm_ConfigRFReg_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data,
 
 void odm_ConfigMAC_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u8 Data);
 
-void odm_ConfigBB_AGC_8723A(struct dm_odm_t *pDM_Odm, u32 Addr,
-                           u32 Bitmask, u32 Data);
+void odm_ConfigBB_AGC_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u32 data);
 
-void odm_ConfigBB_PHY_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Bitmask, u32 Data);
+void odm_ConfigBB_PHY_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u32 data);
 
 #endif /*  end of SUPPORT */
index ea35070b744f97c1fe089d70c55e128caef1e498..1d3bf03b59ea7a40a4a100a8587702c4ebfebc3a 100644 (file)
@@ -54,17 +54,6 @@ typedef void (*RT_WORKITEM_CALL_BACK)(struct work_struct *pContext);
 /*  =========== EXtern Function Prototype */
 /*  */
 
-
-u8 ODM_Read1Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr);
-u16 ODM_Read2Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr);
-u32 ODM_Read4Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr);
-void ODM_Write1Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr, u8 Data);
-void ODM_Write2Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr, u16 Data);
-void ODM_Write4Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr, u32 Data);
-void ODM_SetMACReg(struct dm_odm_t *pDM_Odm, u32 RegAddr, u32 BitMask, u32 Data);
-u32 ODM_GetMACReg(struct dm_odm_t *pDM_Odm, u32 RegAddr, u32 BitMask);
-void ODM_SetBBReg(struct dm_odm_t *pDM_Odm, u32 RegAddr, u32 BitMask, u32 Data);
-u32 ODM_GetBBReg(struct dm_odm_t *pDM_Odm, u32 RegAddr, u32 BitMask);
 void ODM_SetRFReg(struct dm_odm_t *pDM_Odm, enum RF_RADIO_PATH eRFPath,
                  u32 RegAddr, u32 BitMask, u32 Data);
 u32 ODM_GetRFReg(struct dm_odm_t *pDM_Odm, enum RF_RADIO_PATH eRFPath,
index e14633678b52d1d63d32efad4036a52465ad12bd..ad3a442bc000cba7b2f6f8616973b1f953572ff4 100644 (file)
@@ -270,7 +270,6 @@ struct hal_data_8723a {
        u16     BasicRateSet;
 
        /* rf_ctrl */
-       u8      rf_chip;
        u8      rf_type;
        u8      NumTotalRFPath;
 
@@ -348,7 +347,6 @@ struct hal_data_8723a {
        /* for host message to fw */
        u8      LastHMEBoxNum;
 
-       u8      fw_ractrl;
        u8      RegTxPause;
        /*  Beacon function related global variable. */
        u8      RegFwHwTxQCtrl;
index b6b01732a7259f0a8af7108b2102a5921c6969ea..159183e9cab008d6c4a3d360e91e4be89dba8537 100644 (file)
 
 extern u32 GlobalDebugLevel23A;
 
+__printf(3, 4)
+void rt_trace(int comp, int level, const char *fmt, ...);
 
-#define RT_TRACE(_Comp, _Level, Fmt)                                   \
+#define RT_TRACE(_Comp, _Level, Fmt, ...)                              \
 do {                                                                   \
-       if (_Level <= GlobalDebugLevel23A) {                            \
-               pr_info("%s [0x%08x,%d]", DRIVER_PREFIX,                \
-                        (unsigned int)_Comp, _Level);                  \
-               pr_info Fmt;                                            \
-       }                                                               \
+       if (_Level <= GlobalDebugLevel23A)                              \
+               rt_trace(_Comp, _Level, Fmt, ##__VA_ARGS__);            \
 } while (0)
 
 #define RT_PRINT_DATA(_Comp, _Level, _TitleString, _HexData,           \
index 537bd8214efe1deaa0ada916c80e3c13b6603437..b139ed40cb2729555152af9e0df8be2d0ab40930 100644 (file)
@@ -729,7 +729,7 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, u8 key_index,
        if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 ||
            keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) {
                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
-                        ("wpa_set_encryption, crypt.alg = WEP\n"));
+                        "wpa_set_encryption, crypt.alg = WEP\n");
                DBG_8723A("wpa_set_encryption, crypt.alg = WEP\n");
 
                if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
@@ -1076,8 +1076,7 @@ static int cfg80211_rtw_get_station(struct wiphy *wiphy,
                ret = -ENOENT;
                goto exit;
        }
-       DBG_8723A("%s(%s): mac =" MAC_FMT "\n", __func__, ndev->name,
-                 MAC_ARG(mac));
+       DBG_8723A("%s(%s): mac=%pM\n", __func__, ndev->name, mac);
 
        /* for infra./P2PClient mode */
        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
@@ -1085,8 +1084,8 @@ static int cfg80211_rtw_get_station(struct wiphy *wiphy,
                struct wlan_network *cur_network = &pmlmepriv->cur_network;
 
                if (!ether_addr_equal(mac, cur_network->network.MacAddress)) {
-                       DBG_8723A("%s, mismatch bssid =" MAC_FMT "\n", __func__,
-                                 MAC_ARG(cur_network->network.MacAddress));
+                       DBG_8723A("%s, mismatch bssid=%pM\n",
+                                 __func__, cur_network->network.MacAddress);
                        ret = -ENOENT;
                        goto exit;
                }
@@ -1128,14 +1127,14 @@ static int cfg80211_infrastructure_mode(struct rtw_adapter *padapter,
        old_mode = cur_network->network.ifmode;
 
        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
-                ("+%s: old =%d new =%d fw_state = 0x%08x\n", __func__,
-                 old_mode, ifmode, get_fwstate(pmlmepriv)));
+                "+%s: old =%d new =%d fw_state = 0x%08x\n", __func__,
+                old_mode, ifmode, get_fwstate(pmlmepriv));
 
        if (old_mode != ifmode) {
                spin_lock_bh(&pmlmepriv->lock);
 
                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-                        (" change mode!"));
+                        "change mode!\n");
 
                if (old_mode == NL80211_IFTYPE_AP ||
                    old_mode == NL80211_IFTYPE_P2P_GO) {
@@ -1195,10 +1194,6 @@ static int cfg80211_infrastructure_mode(struct rtw_adapter *padapter,
 
                /* SecClearAllKeys(adapter); */
 
-               /* RT_TRACE(COMP_OID_SET, DBG_LOUD,
-                  ("set_infrastructure: fw_state:%x after changing mode\n", */
-               /* get_fwstate(pmlmepriv))); */
-
                spin_unlock_bh(&pmlmepriv->lock);
        }
 
@@ -1603,7 +1598,7 @@ static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
                          pie[i + 4], pie[i + 5], pie[i + 6], pie[i + 7]);
        if (ielen < RSN_HEADER_LEN) {
                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
-                        ("Ie len too short %d\n", (int)ielen));
+                        "Ie len too short %d\n", (int)ielen);
                ret = -1;
                goto exit;
        }
@@ -1726,11 +1721,10 @@ static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
                rtl8723a_off_rcr_am(padapter);
 
        RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
-                ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->"
-                 "securitypriv.ndisencryptstatus =%d padapter->"
-                 "securitypriv.ndisauthtype =%d\n", pairwise_cipher,
-                 padapter->securitypriv.ndisencryptstatus,
-                 padapter->securitypriv.ndisauthtype));
+                "rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n",
+                pairwise_cipher,
+                padapter->securitypriv.ndisencryptstatus,
+                padapter->securitypriv.ndisauthtype);
 
 exit:
        if (ret)
@@ -1746,7 +1740,7 @@ static int rtw_cfg80211_add_wep(struct rtw_adapter *padapter,
 
        if (keyid >= NUM_WEP_KEYS) {
                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-                        ("%s:keyid>4 =>fail\n", __func__));
+                        "%s:keyid>4 =>fail\n", __func__);
                res = _FAIL;
                goto exit;
        }
@@ -1755,45 +1749,45 @@ static int rtw_cfg80211_add_wep(struct rtw_adapter *padapter,
        case WLAN_KEY_LEN_WEP40:
                psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40;
                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-                        ("%s:wep->KeyLength = 5\n", __func__));
+                        "%s:wep->KeyLength = 5\n", __func__);
                break;
        case WLAN_KEY_LEN_WEP104:
                psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104;
                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-                        ("%s:wep->KeyLength = 13\n", __func__));
+                        "%s:wep->KeyLength = 13\n", __func__);
                break;
        default:
                psecuritypriv->dot11PrivacyAlgrthm = 0;
                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-                        ("%s:wep->KeyLength!= 5 or 13\n", __func__));
+                        "%s:wep->KeyLength!= 5 or 13\n", __func__);
                res = _FAIL;
                goto exit;
        }
 
        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-                ("%s:before memcpy, wep->KeyLength = 0x%x keyid =%x\n",
-                 __func__, wep->keylen, keyid));
+                "%s:before memcpy, wep->KeyLength = 0x%x keyid =%x\n",
+                __func__, wep->keylen, keyid);
 
        memcpy(&psecuritypriv->wep_key[keyid], wep, sizeof(struct rtw_wep_key));
 
        psecuritypriv->dot11PrivacyKeyIndex = keyid;
 
        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-                ("%s:security key material : "
-                 "%x %x %x %x %x %x %x %x %x %x %x %x %x\n", __func__,
-                 psecuritypriv->wep_key[keyid].key[0],
-                 psecuritypriv->wep_key[keyid].key[1],
-                 psecuritypriv->wep_key[keyid].key[2],
-                 psecuritypriv->wep_key[keyid].key[3],
-                 psecuritypriv->wep_key[keyid].key[4],
-                 psecuritypriv->wep_key[keyid].key[5],
-                 psecuritypriv->wep_key[keyid].key[6],
-                 psecuritypriv->wep_key[keyid].key[7],
-                 psecuritypriv->wep_key[keyid].key[8],
-                 psecuritypriv->wep_key[keyid].key[9],
-                 psecuritypriv->wep_key[keyid].key[10],
-                 psecuritypriv->wep_key[keyid].key[11],
-                 psecuritypriv->wep_key[keyid].key[12]));
+                "%s:security key material : %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
+                __func__,
+                psecuritypriv->wep_key[keyid].key[0],
+                psecuritypriv->wep_key[keyid].key[1],
+                psecuritypriv->wep_key[keyid].key[2],
+                psecuritypriv->wep_key[keyid].key[3],
+                psecuritypriv->wep_key[keyid].key[4],
+                psecuritypriv->wep_key[keyid].key[5],
+                psecuritypriv->wep_key[keyid].key[6],
+                psecuritypriv->wep_key[keyid].key[7],
+                psecuritypriv->wep_key[keyid].key[8],
+                psecuritypriv->wep_key[keyid].key[9],
+                psecuritypriv->wep_key[keyid].key[10],
+                psecuritypriv->wep_key[keyid].key[11],
+                psecuritypriv->wep_key[keyid].key[12]);
 
        res = rtw_set_key23a(padapter, psecuritypriv, keyid, 1);
 
@@ -1815,7 +1809,7 @@ static int rtw_set_ssid(struct rtw_adapter *padapter,
 
        if (padapter->hw_init_completed == false) {
                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-                        ("set_ssid: hw_init_completed == false =>exit!!!\n"));
+                        "set_ssid: hw_init_completed == false =>exit!!!\n");
                status = _FAIL;
                goto exit;
        }
@@ -1828,7 +1822,7 @@ static int rtw_set_ssid(struct rtw_adapter *padapter,
 
        if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
                RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-                        ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
+                        "set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n");
 
                if (pmlmepriv->assoc_ssid.ssid_len ==
                    newnetwork->network.Ssid.ssid_len &&
@@ -1837,9 +1831,9 @@ static int rtw_set_ssid(struct rtw_adapter *padapter,
                            newnetwork->network.Ssid.ssid_len)) {
                        if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
                                RT_TRACE(_module_rtl871x_ioctl_set_c_,
-                                        _drv_err_, ("New SSID is same SSID, "
-                                                    "fw_state = 0x%08x\n",
-                                                    get_fwstate(pmlmepriv)));
+                                        _drv_err_,
+                                        "New SSID is same SSID, fw_state = 0x%08x\n",
+                                        get_fwstate(pmlmepriv));
 
                                if (rtw_is_same_ibss23a(padapter, pnetwork)) {
                                        /*
@@ -1875,15 +1869,15 @@ static int rtw_set_ssid(struct rtw_adapter *padapter,
                        }
                } else {
                        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-                                ("Set SSID not the same ssid\n"));
+                                "Set SSID not the same ssid\n");
                        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-                                ("set_ssid =[%s] len = 0x%x\n",
-                                 newnetwork->network.Ssid.ssid,
-                                 newnetwork->network.Ssid.ssid_len));
+                                "set_ssid =[%s] len = 0x%x\n",
+                                newnetwork->network.Ssid.ssid,
+                                newnetwork->network.Ssid.ssid_len);
                        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-                                ("assoc_ssid =[%s] len = 0x%x\n",
-                                 pmlmepriv->assoc_ssid.ssid,
-                                 pmlmepriv->assoc_ssid.ssid_len));
+                                "assoc_ssid =[%s] len = 0x%x\n",
+                                pmlmepriv->assoc_ssid.ssid,
+                                pmlmepriv->assoc_ssid.ssid_len);
 
                        rtw_disassoc_cmd23a(padapter, 0, true);
 
@@ -1947,7 +1941,7 @@ release_mlme_lock:
 
 exit:
        RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-                ("-%s: status =%d\n", __func__, status));
+                "-%s: status =%d\n", __func__, status);
 
        return status;
 }
@@ -1989,7 +1983,7 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
        DBG_8723A("ssid =%s, len =%zu\n", sme->ssid, sme->ssid_len);
 
        if (sme->bssid)
-               DBG_8723A("bssid =" MAC_FMT "\n", MAC_ARG(sme->bssid));
+               DBG_8723A("bssid=%pM\n", sme->bssid);
 
        if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
                ret = -EBUSY;
@@ -2523,8 +2517,8 @@ static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb,
 
                mgmt = (struct ieee80211_mgmt *)dot11_hdr;
 
-               DBG_8723A("RTW_Tx:da =" MAC_FMT " via %s(%s)\n",
-                         MAC_ARG(mgmt->da), __func__, ndev->name);
+               DBG_8723A("RTW_Tx:da=%pM via %s(%s)\n",
+                         mgmt->da, __func__, ndev->name);
                category = mgmt->u.action.category;
                action = mgmt->u.action.u.wme_action.action_code;
                DBG_8723A("RTW_Tx:category(%u), action(%u)\n",
@@ -2877,7 +2871,7 @@ static int cfg80211_rtw_del_station(struct wiphy *wiphy,
                return ret;
        }
 
-       DBG_8723A("free sta macaddr =" MAC_FMT "\n", MAC_ARG(mac));
+       DBG_8723A("free sta macaddr=%pM\n", mac);
 
        if (is_broadcast_ether_addr(mac))
                return -EINVAL;
@@ -3053,8 +3047,7 @@ static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
        cfg80211_mgmt_tx_status(padapter->rtw_wdev, *cookie, buf, len, ack,
                                GFP_KERNEL);
 
-       DBG_8723A("RTW_Tx:tx_ch =%d, da =" MAC_FMT "\n", tx_ch,
-                 MAC_ARG(hdr->da));
+       DBG_8723A("RTW_Tx:tx_ch =%d, da =%pM\n", tx_ch, hdr->da);
        category = hdr->u.action.category;
        action = hdr->u.action.u.wme_action.action_code;
        DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category, action);
index 1b23eb13222b76baafb92d974a9308fabd836203..83696360c2932d7c66cd1671712a284a1b3f231d 100644 (file)
@@ -34,7 +34,7 @@ MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B.bin");
 MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B_NoBT.bin");
 
 /* module param defaults */
-static int rtw_chip_version = 0x00;
+static int rtw_chip_version;
 static int rtw_rfintfs = HWPI;
 static int rtw_debug = 1;
 
@@ -342,7 +342,7 @@ int rtw_init_netdev23a_name23a(struct net_device *pnetdev, const char *ifname)
 {
        if (dev_alloc_name(pnetdev, ifname) < 0) {
                RT_TRACE(_module_os_intfs_c_, _drv_err_,
-                        ("dev_alloc_name, fail!\n"));
+                        "dev_alloc_name, fail!\n");
        }
        netif_carrier_off(pnetdev);
        return 0;
@@ -357,7 +357,7 @@ struct net_device *rtw_init_netdev23a(struct rtw_adapter *old_padapter)
        struct rtw_adapter *padapter;
        struct net_device *pnetdev;
 
-       RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+init_net_dev\n"));
+       RT_TRACE(_module_os_intfs_c_, _drv_info_, "+init_net_dev\n");
 
        pnetdev = alloc_etherdev_mq(sizeof(struct rtw_adapter), 4);
        if (!pnetdev)
@@ -456,11 +456,11 @@ int rtw_init_drv_sw23a(struct rtw_adapter *padapter)
 {
        int ret8 = _SUCCESS;
 
-       RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_init_drv_sw23a\n"));
+       RT_TRACE(_module_os_intfs_c_, _drv_info_, "+rtw_init_drv_sw23a\n");
 
        if (rtw_init_cmd_priv23a(&padapter->cmdpriv) == _FAIL) {
                RT_TRACE(_module_os_intfs_c_, _drv_err_,
-                        ("\n Can't init cmd_priv\n"));
+                        "Can't init cmd_priv\n");
                ret8 = _FAIL;
                goto exit;
        }
@@ -469,14 +469,14 @@ int rtw_init_drv_sw23a(struct rtw_adapter *padapter)
 
        if (rtw_init_evt_priv23a(&padapter->evtpriv) == _FAIL) {
                RT_TRACE(_module_os_intfs_c_, _drv_err_,
-                        ("\n Can't init evt_priv\n"));
+                        "Can't init evt_priv\n");
                ret8 = _FAIL;
                goto exit;
        }
 
        if (rtw_init_mlme_priv23a(padapter) == _FAIL) {
                RT_TRACE(_module_os_intfs_c_, _drv_err_,
-                        ("\n Can't init mlme_priv\n"));
+                        "Can't init mlme_priv\n");
                ret8 = _FAIL;
                goto exit;
        }
@@ -484,7 +484,7 @@ int rtw_init_drv_sw23a(struct rtw_adapter *padapter)
 
        if (init_mlme_ext_priv23a(padapter) == _FAIL) {
                RT_TRACE(_module_os_intfs_c_, _drv_err_,
-                        ("\n Can't init mlme_ext_priv\n"));
+                        "Can't init mlme_ext_priv\n");
                ret8 = _FAIL;
                goto exit;
        }
@@ -521,40 +521,40 @@ int rtw_init_drv_sw23a(struct rtw_adapter *padapter)
 
 exit:
 
-       RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_init_drv_sw23a\n"));
+       RT_TRACE(_module_os_intfs_c_, _drv_info_, "-rtw_init_drv_sw23a\n");
        return ret8;
 }
 
 void rtw_cancel_all_timer23a(struct rtw_adapter *padapter)
 {
        RT_TRACE(_module_os_intfs_c_, _drv_info_,
-                ("+rtw_cancel_all_timer23a\n"));
+                "+rtw_cancel_all_timer23a\n");
 
        del_timer_sync(&padapter->mlmepriv.assoc_timer);
        RT_TRACE(_module_os_intfs_c_, _drv_info_,
-                ("%s:cancel association timer complete!\n", __func__));
+                "%s:cancel association timer complete!\n", __func__);
 
        del_timer_sync(&padapter->mlmepriv.scan_to_timer);
        RT_TRACE(_module_os_intfs_c_, _drv_info_,
-                ("%s:cancel scan_to_timer!\n", __func__));
+                "%s:cancel scan_to_timer!\n", __func__);
 
        del_timer_sync(&padapter->mlmepriv.dynamic_chk_timer);
        RT_TRACE(_module_os_intfs_c_, _drv_info_,
-                ("%s:cancel dynamic_chk_timer!\n", __func__));
+                "%s:cancel dynamic_chk_timer!\n", __func__);
 
        del_timer_sync(&padapter->pwrctrlpriv.pwr_state_check_timer);
 
        del_timer_sync(&padapter->mlmepriv.set_scan_deny_timer);
        rtw_clear_scan_deny(padapter);
        RT_TRACE(_module_os_intfs_c_, _drv_info_,
-                ("%s:cancel set_scan_deny_timer!\n", __func__));
+                "%s:cancel set_scan_deny_timer!\n", __func__);
 
        del_timer_sync(&padapter->recvpriv.signal_stat_timer);
 }
 
 int rtw_free_drv_sw23a(struct rtw_adapter *padapter)
 {
-       RT_TRACE(_module_os_intfs_c_, _drv_info_, ("==>rtw_free_drv_sw23a"));
+       RT_TRACE(_module_os_intfs_c_, _drv_info_, "==>rtw_free_drv_sw23a\n");
 
        free_mlme_ext_priv23a(&padapter->mlmeextpriv);
 
@@ -574,7 +574,7 @@ int rtw_free_drv_sw23a(struct rtw_adapter *padapter)
        kfree(padapter->HalData);
        padapter->HalData = NULL;
 
-       RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_free_drv_sw23a\n"));
+       RT_TRACE(_module_os_intfs_c_, _drv_info_, "-rtw_free_drv_sw23a\n");
        return _SUCCESS;
 }
 
@@ -594,8 +594,8 @@ static int _rtw_drv_register_netdev(struct rtw_adapter *padapter, char *name)
                ret = _FAIL;
                goto error_register_netdev;
        }
-       DBG_8723A("%s, MAC Address (if%d) = " MAC_FMT "\n", __func__,
-                 (padapter->iface_id + 1), MAC_ARG(pnetdev->dev_addr));
+       DBG_8723A("%s, MAC Address (if%d) = %pM\n",
+                 __func__, padapter->iface_id + 1, pnetdev->dev_addr);
        return ret;
 
 error_register_netdev:
@@ -647,7 +647,7 @@ int netdev_open23a(struct net_device *pnetdev)
        int ret = 0;
        int status;
 
-       RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+871x_drv - dev_open\n"));
+       RT_TRACE(_module_os_intfs_c_, _drv_info_, "+871x_drv - dev_open\n");
        DBG_8723A("+871x_drv - drv_open, bup =%d\n", padapter->bup);
 
        mutex_lock(&adapter_to_dvobj(padapter)->hw_init_mutex);
@@ -662,12 +662,11 @@ int netdev_open23a(struct net_device *pnetdev)
                status = rtl8723au_hal_init(padapter);
                if (status == _FAIL) {
                        RT_TRACE(_module_os_intfs_c_, _drv_err_,
-                                ("rtl871x_hal_init(): Can't init h/w!\n"));
+                                "rtl871x_hal_init(): Can't init h/w!\n");
                        goto netdev_open23a_error;
                }
 
-               DBG_8723A("MAC Address = "MAC_FMT"\n",
-                         MAC_ARG(pnetdev->dev_addr));
+               DBG_8723A("MAC Address = %pM\n", pnetdev->dev_addr);
 
                if (init_hw_mlme_ext23a(padapter) == _FAIL) {
                        DBG_8723A("can't init mlme_ext_priv\n");
@@ -695,7 +694,7 @@ int netdev_open23a(struct net_device *pnetdev)
        else
                netif_tx_wake_all_queues(pnetdev);
 
-       RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-871x_drv - dev_open\n"));
+       RT_TRACE(_module_os_intfs_c_, _drv_info_, "-871x_drv - dev_open\n");
        DBG_8723A("-871x_drv - drv_open, bup =%d\n", padapter->bup);
 exit:
        mutex_unlock(&adapter_to_dvobj(padapter)->hw_init_mutex);
@@ -708,7 +707,7 @@ netdev_open23a_error:
        netif_tx_stop_all_queues(pnetdev);
 
        RT_TRACE(_module_os_intfs_c_, _drv_err_,
-                ("-871x_drv - dev_open, fail!\n"));
+                "-871x_drv - dev_open, fail!\n");
        DBG_8723A("-871x_drv - drv_open fail, bup =%d\n", padapter->bup);
 
        ret = -1;
@@ -729,7 +728,7 @@ static int ips_netdrv_open(struct rtw_adapter *padapter)
        status = rtl8723au_hal_init(padapter);
        if (status == _FAIL) {
                RT_TRACE(_module_os_intfs_c_, _drv_err_,
-                        ("ips_netdrv_open(): Can't init h/w!\n"));
+                        "ips_netdrv_open(): Can't init h/w!\n");
                goto netdev_open23a_error;
        }
 
@@ -807,7 +806,7 @@ static int netdev_close(struct net_device *pnetdev)
 {
        struct rtw_adapter *padapter = netdev_priv(pnetdev);
 
-       RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+871x_drv - drv_close\n"));
+       RT_TRACE(_module_os_intfs_c_, _drv_info_, "+871x_drv - drv_close\n");
 
        padapter->net_closed = true;
 
@@ -835,7 +834,7 @@ static int netdev_close(struct net_device *pnetdev)
 
        rtw_scan_abort23a(padapter);
 
-       RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-871x_drv - drv_close\n"));
+       RT_TRACE(_module_os_intfs_c_, _drv_info_, "-871x_drv - drv_close\n");
        DBG_8723A("-871x_drv - drv_close, bup =%d\n", padapter->bup);
 
        return 0;
index bcd970baf4052deaa4e1d67d7a22f2fa3d61b10e..084b506ae16161bb6ecfa009fd8515395ae45e31 100644 (file)
@@ -81,19 +81,19 @@ int rtw_recv_indicatepkt23a(struct rtw_adapter *padapter,
        skb = precv_frame->pkt;
        if (!skb) {
                RT_TRACE(_module_recv_osdep_c_, _drv_err_,
-                        ("rtw_recv_indicatepkt23a():skb == NULL!!!!\n"));
+                        "rtw_recv_indicatepkt23a():skb == NULL!!!!\n");
                goto _recv_indicatepkt_drop;
        }
 
        RT_TRACE(_module_recv_osdep_c_, _drv_info_,
-                ("rtw_recv_indicatepkt23a():skb != NULL !!!\n"));
+                "rtw_recv_indicatepkt23a():skb != NULL !!!\n");
        RT_TRACE(_module_recv_osdep_c_, _drv_info_,
-                ("rtw_recv_indicatepkt23a():precv_frame->hdr.rx_data =%p\n",
-                 precv_frame->pkt->data));
+                "rtw_recv_indicatepkt23a():precv_frame->hdr.rx_data =%p\n",
+                precv_frame->pkt->data);
        RT_TRACE(_module_recv_osdep_c_, _drv_info_,
-                ("\n skb->head =%p skb->data =%p skb->tail =%p skb->end =%p skb->len =%d\n",
-                 skb->head, skb->data,
-                 skb_tail_pointer(skb), skb_end_pointer(skb), skb->len));
+                "skb->head =%p skb->data =%p skb->tail =%p skb->end =%p skb->len =%d\n",
+                skb->head, skb->data,
+                skb_tail_pointer(skb), skb_end_pointer(skb), skb->len);
 
        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
                struct sk_buff *pskb2 = NULL;
@@ -148,7 +148,7 @@ _recv_indicatepkt_end:
        rtw_free_recvframe23a(precv_frame);
 
        RT_TRACE(_module_recv_osdep_c_, _drv_info_,
-                ("\n rtw_recv_indicatepkt23a :after netif_rx!!!!\n"));
+                "rtw_recv_indicatepkt23a :after netif_rx!!!!\n");
        return _SUCCESS;
 
 _recv_indicatepkt_drop:
index 05755b870a5fbeaeda0de95d1a7dc1e7c9980e09..27b3a5b7d8d4022e241f8f3b751a53fd187725b3 100644 (file)
@@ -159,7 +159,7 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
 
        if (rtw_init_intf_priv(pdvobjpriv) == _FAIL) {
                RT_TRACE(_module_os_intfs_c_, _drv_err_,
-                        ("\n Can't INIT rtw_init_intf_priv\n"));
+                        "Can't INIT rtw_init_intf_priv\n");
                goto free_dvobj;
        }
        /* 3 misc */
@@ -213,7 +213,7 @@ static void usb_dvobj_deinit(struct usb_interface *usb_intf)
 
 void rtl8723a_usb_intf_stop(struct rtw_adapter *padapter)
 {
-       RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_stop\n"));
+       RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+usb_intf_stop\n");
 
        /* disable_hw_interrupt */
        if (!padapter->bSurpriseRemoved) {
@@ -221,7 +221,7 @@ void rtl8723a_usb_intf_stop(struct rtw_adapter *padapter)
                 * TODO:
                 */
                RT_TRACE(_module_hci_intfs_c_, _drv_err_,
-                        ("SurpriseRemoved == false\n"));
+                        "SurpriseRemoved == false\n");
        }
 
        /* cancel in irp */
@@ -231,13 +231,14 @@ void rtl8723a_usb_intf_stop(struct rtw_adapter *padapter)
        rtl8723au_write_port_cancel(padapter);
 
        /* todo:cancel other irps */
-       RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_stop\n"));
+       RT_TRACE(_module_hci_intfs_c_, _drv_err_, "-usb_intf_stop\n");
 }
 
 static void rtw_dev_unload(struct rtw_adapter *padapter)
 {
        struct submit_ctx *pack_tx_ops = &padapter->xmitpriv.ack_tx_ops;
-       RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_dev_unload\n"));
+
+       RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+rtw_dev_unload\n");
 
        if (padapter->bup) {
                DBG_8723A("===> rtw_dev_unload\n");
@@ -261,10 +262,10 @@ static void rtw_dev_unload(struct rtw_adapter *padapter)
                padapter->bup = false;
        } else {
                RT_TRACE(_module_hci_intfs_c_, _drv_err_,
-                        ("r871x_dev_unload():padapter->bup == false\n"));
+                        "r871x_dev_unload():padapter->bup == false\n");
        }
        DBG_8723A("<=== rtw_dev_unload\n");
-       RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n"));
+       RT_TRACE(_module_hci_intfs_c_, _drv_err_, "-rtw_dev_unload\n");
 }
 
 static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
@@ -435,7 +436,7 @@ static struct rtw_adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
        /* step 5. */
        if (rtw_init_drv_sw23a(padapter) == _FAIL) {
                RT_TRACE(_module_hci_intfs_c_, _drv_err_,
-                        ("Initialize driver software resource Failed!\n"));
+                        "Initialize driver software resource Failed!\n");
                goto free_hal_data;
        }
 
@@ -533,13 +534,13 @@ static int rtw_drv_init(struct usb_interface *pusb_intf,
        struct dvobj_priv *dvobj;
        int status = _FAIL;
 
-       RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_init\n"));
+       RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+rtw_drv_init\n");
 
        /* Initialize dvobj_priv */
        dvobj = usb_dvobj_init(pusb_intf);
        if (!dvobj) {
                RT_TRACE(_module_hci_intfs_c_, _drv_err_,
-                        ("initialize device object priv Failed!\n"));
+                        "initialize device object priv Failed!\n");
                goto exit;
        }
 
@@ -554,7 +555,7 @@ static int rtw_drv_init(struct usb_interface *pusb_intf,
        if (status != _SUCCESS)
                goto free_if1;
        RT_TRACE(_module_hci_intfs_c_, _drv_err_,
-                ("-871x_drv - drv_init, success!\n"));
+                "-871x_drv - drv_init, success!\n");
 
        status = _SUCCESS;
 
@@ -586,7 +587,7 @@ static void rtw_disconnect(struct usb_interface *pusb_intf)
 
        usb_set_intfdata(pusb_intf, NULL);
 
-       RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n"));
+       RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+dev_remove()\n");
 
        rtw_pm_set_ips23a(padapter, IPS_NONE);
        rtw_pm_set_lps23a(padapter, PS_MODE_ACTIVE);
@@ -597,21 +598,19 @@ static void rtw_disconnect(struct usb_interface *pusb_intf)
 
        usb_dvobj_deinit(pusb_intf);
 
-       RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-dev_remove()\n"));
+       RT_TRACE(_module_hci_intfs_c_, _drv_err_, "-dev_remove()\n");
        DBG_8723A("-r871xu_dev_remove, done\n");
-
-       return;
 }
 
 static int __init rtw_drv_entry(void)
 {
-       RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_entry\n"));
+       RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+rtw_drv_entry\n");
        return usb_register(usb_drv);
 }
 
 static void __exit rtw_drv_halt(void)
 {
-       RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_halt\n"));
+       RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+rtw_drv_halt\n");
        DBG_8723A("+rtw_drv_halt\n");
 
        usb_deregister(usb_drv);
index 3e19b3b2c1c21751fafe15162685f03c636279ea..0cdaef0a8c24b2bd89935686bb68035bf42e84cb 100644 (file)
@@ -58,9 +58,8 @@ static void usb_write_port23a_complete(struct urb *purb)
        if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
            padapter->bWritePortCancel) {
                RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                        ("usb_write_port23a_complete:bDriverStopped(%d) OR "
-                         "bSurpriseRemoved(%d)", padapter->bDriverStopped,
-                         padapter->bSurpriseRemoved));
+                        "usb_write_port23a_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n",
+                        padapter->bDriverStopped, padapter->bSurpriseRemoved);
                DBG_8723A("%s(): TX Warning! bDriverStopped(%d) OR "
                          "bSurpriseRemoved(%d) bWritePortCancel(%d) "
                          "pxmitbuf->ext_tag(%x)\n", __func__,
@@ -72,14 +71,14 @@ static void usb_write_port23a_complete(struct urb *purb)
 
        if (purb->status) {
                RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                        ("usb_write_port23a_complete : purb->status(%d) "
-                         "!= 0\n", purb->status));
+                        "usb_write_port23a_complete : purb->status(%d) != 0\n",
+                        purb->status);
                DBG_8723A("###=> urb_write_port_complete status(%d)\n",
                          purb->status);
                if (purb->status == -EPIPE || purb->status == -EPROTO) {
                } else if (purb->status == -EINPROGRESS) {
                        RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                                ("usb_write_port23a_complete: EINPROGESS\n"));
+                                "usb_write_port23a_complete: EINPROGESS\n");
                        goto check_completion;
                } else if (purb->status == -ENOENT) {
                        DBG_8723A("%s: -ENOENT\n", __func__);
@@ -89,18 +88,16 @@ static void usb_write_port23a_complete(struct urb *purb)
                        goto check_completion;
                } else if (purb->status == -ESHUTDOWN) {
                        RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                                ("usb_write_port23a_complete: ESHUTDOWN\n"));
+                                "usb_write_port23a_complete: ESHUTDOWN\n");
                        padapter->bDriverStopped = true;
                        RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                                ("usb_write_port23a_complete:bDriverStopped "
-                                 "= true\n"));
+                                "usb_write_port23a_complete:bDriverStopped = true\n");
                        goto check_completion;
                } else {
                        padapter->bSurpriseRemoved = true;
                        DBG_8723A("bSurpriseRemoved = true\n");
                        RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                                ("usb_write_port23a_complete:bSurpriseRemoved "
-                                 "= true\n"));
+                                "usb_write_port23a_complete:bSurpriseRemoved = true\n");
                        goto check_completion;
                }
        }
@@ -132,12 +129,12 @@ int rtl8723au_write_port(struct rtw_adapter *padapter, u32 addr, u32 cnt,
        int status;
        int ret = _FAIL;
 
-       RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("+usb_write_port23a\n"));
+       RT_TRACE(_module_hci_ops_os_c_, _drv_err_, "+usb_write_port23a\n");
 
        if (padapter->bDriverStopped || padapter->bSurpriseRemoved) {
                RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                        ("%s:(padapter->bDriverStopped || "
-                         "padapter->bSurpriseRemoved)!!!\n", __func__));
+                        "%s:(padapter->bDriverStopped || padapter->bSurpriseRemoved)!!!\n",
+                        __func__);
                rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
                goto exit;
        }
@@ -188,8 +185,8 @@ int rtl8723au_write_port(struct rtw_adapter *padapter, u32 addr, u32 cnt,
                                     RTW_SCTX_DONE_WRITE_PORT_ERR);
                DBG_8723A("usb_write_port23a, status =%d\n", status);
                RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-                        ("usb_write_port23a(): usb_submit_urb, status =%x\n",
-                        status));
+                        "usb_write_port23a(): usb_submit_urb, status =%x\n",
+                        status);
 
                switch (status) {
                case -ENODEV:
@@ -201,7 +198,7 @@ int rtl8723au_write_port(struct rtw_adapter *padapter, u32 addr, u32 cnt,
                goto exit;
        }
        ret = _SUCCESS;
-       RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("-usb_write_port23a\n"));
+       RT_TRACE(_module_hci_ops_os_c_, _drv_err_, "-usb_write_port23a\n");
 
 exit:
        if (ret != _SUCCESS)
index 69f88848715abc9d61f58ed9cbabcf91b18e8e43..9a14074ecec0551cd583b8cb3c295d7e5aa7dbf9 100644 (file)
@@ -123,11 +123,11 @@ int rtw_xmit23a_entry23a(struct sk_buff *skb, struct net_device *pnetdev)
        struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
        int res = 0;
 
-       RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("+xmit_enry\n"));
+       RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, "+xmit_enry\n");
 
        if (!rtw_if_up23a(padapter)) {
                RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
-                        ("rtw_xmit23a_entry23a: rtw_if_up23a fail\n"));
+                        "rtw_xmit23a_entry23a: rtw_if_up23a fail\n");
                goto drop_packet;
        }
 
@@ -139,16 +139,16 @@ int rtw_xmit23a_entry23a(struct sk_buff *skb, struct net_device *pnetdev)
 
        pxmitpriv->tx_pkts++;
        RT_TRACE(_module_xmit_osdep_c_, _drv_info_,
-                ("rtw_xmit23a_entry23a: tx_pkts=%d\n",
-                (u32)pxmitpriv->tx_pkts));
+                "rtw_xmit23a_entry23a: tx_pkts=%d\n",
+                (u32)pxmitpriv->tx_pkts);
        goto exit;
 
 drop_packet:
        pxmitpriv->tx_drop++;
        dev_kfree_skb_any(skb);
        RT_TRACE(_module_xmit_osdep_c_, _drv_notice_,
-                ("rtw_xmit23a_entry23a: drop, tx_drop=%d\n",
-                (u32)pxmitpriv->tx_drop));
+                "rtw_xmit23a_entry23a: drop, tx_drop=%d\n",
+                (u32)pxmitpriv->tx_drop);
 exit:
        return 0;
 }
index 17b4471c4d6d2241b1c6c670ee55f999afd36d50..f7fd03a94e5fa94c5228dd1e71f312f378af3d45 100644 (file)
@@ -3,4 +3,4 @@ obj-$(CONFIG_RTS5208) := rts5208.o
 ccflags-y := -Idrivers/scsi
 
 rts5208-y := rtsx.o rtsx_chip.o rtsx_transport.o rtsx_scsi.o \
-       rtsx_card.o general.o sd.o xd.o ms.o spi.o
+       rtsx_card.o general.o sd.o xd.o ms.o spi.o trace.o
index a47a19135d49ff27fd8d4edd164f389f1bd6bb80..ee818b0dc4011f7aab19db049e7fb6f82958f197 100644 (file)
@@ -26,9 +26,6 @@
 #include <linux/vmalloc.h>
 
 #include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
 #include "ms.h"
 
 static inline void ms_set_err_code(struct rtsx_chip *chip, u8 err_code)
@@ -47,7 +44,8 @@ static inline int ms_check_err_code(struct rtsx_chip *chip, u8 err_code)
 
 static int ms_parse_err_code(struct rtsx_chip *chip)
 {
-       TRACE_RET(chip, STATUS_FAIL);
+       rtsx_trace(chip);
+       return STATUS_FAIL;
 }
 
 static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode,
@@ -78,7 +76,8 @@ static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode,
        if (retval < 0) {
                rtsx_clear_ms_error(chip);
                ms_set_err_code(chip, MS_TO_ERROR);
-               TRACE_RET(chip, ms_parse_err_code(chip));
+               rtsx_trace(chip);
+               return ms_parse_err_code(chip);
        }
 
        ptr = rtsx_get_cmd_data(chip) + 1;
@@ -86,13 +85,15 @@ static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode,
        if (!(tpc & 0x08)) {            /* Read Packet */
                if (*ptr & MS_CRC16_ERR) {
                        ms_set_err_code(chip, MS_CRC16_ERROR);
-                       TRACE_RET(chip, ms_parse_err_code(chip));
+                       rtsx_trace(chip);
+                       return ms_parse_err_code(chip);
                }
        } else {                        /* Write Packet */
                if (CHK_MSPRO(ms_card) && !(*ptr & 0x80)) {
                        if (*ptr & (MS_INT_ERR | MS_INT_CMDNK)) {
                                ms_set_err_code(chip, MS_CMD_NK);
-                               TRACE_RET(chip, ms_parse_err_code(chip));
+                               rtsx_trace(chip);
+                               return ms_parse_err_code(chip);
                        }
                }
        }
@@ -100,22 +101,25 @@ static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode,
        if (*ptr & MS_RDY_TIMEOUT) {
                rtsx_clear_ms_error(chip);
                ms_set_err_code(chip, MS_TO_ERROR);
-               TRACE_RET(chip, ms_parse_err_code(chip));
+               rtsx_trace(chip);
+               return ms_parse_err_code(chip);
        }
 
        return STATUS_SUCCESS;
 }
 
 static int ms_transfer_data(struct rtsx_chip *chip, u8 trans_mode,
-                       u8 tpc, u16 sec_cnt, u8 cfg, int mode_2k,
+                       u8 tpc, u16 sec_cnt, u8 cfg, bool mode_2k,
                        int use_sg, void *buf, int buf_len)
 {
        int retval;
        u8 val, err_code = 0;
        enum dma_data_direction dir;
 
-       if (!buf || !buf_len)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (!buf || !buf_len) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (trans_mode == MS_TM_AUTO_READ) {
                dir = DMA_FROM_DEVICE;
@@ -124,7 +128,8 @@ static int ms_transfer_data(struct rtsx_chip *chip, u8 trans_mode,
                dir = DMA_TO_DEVICE;
                err_code = MS_FLASH_WRITE_ERROR;
        } else {
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        rtsx_init_cmd(chip);
@@ -160,12 +165,19 @@ static int ms_transfer_data(struct rtsx_chip *chip, u8 trans_mode,
                else
                        retval = STATUS_FAIL;
 
-               TRACE_RET(chip, retval);
+               rtsx_trace(chip);
+               return retval;
        }
 
-       RTSX_READ_REG(chip, MS_TRANS_CFG, &val);
-       if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT))
-               TRACE_RET(chip, STATUS_FAIL);
+       retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT)) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -176,8 +188,10 @@ static int ms_write_bytes(struct rtsx_chip *chip,
        struct ms_info *ms_card = &(chip->ms_card);
        int retval, i;
 
-       if (!data || (data_len < cnt))
-               TRACE_RET(chip, STATUS_ERROR);
+       if (!data || (data_len < cnt)) {
+               rtsx_trace(chip);
+               return STATUS_ERROR;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -211,25 +225,28 @@ static int ms_write_bytes(struct rtsx_chip *chip,
                if (!(tpc & 0x08)) {
                        if (val & MS_CRC16_ERR) {
                                ms_set_err_code(chip, MS_CRC16_ERROR);
-                               TRACE_RET(chip, ms_parse_err_code(chip));
+                               rtsx_trace(chip);
+                               return ms_parse_err_code(chip);
                        }
                } else {
                        if (CHK_MSPRO(ms_card) && !(val & 0x80)) {
                                if (val & (MS_INT_ERR | MS_INT_CMDNK)) {
                                        ms_set_err_code(chip, MS_CMD_NK);
-                                       TRACE_RET(chip,
-                                               ms_parse_err_code(chip));
+                                       rtsx_trace(chip);
+                                       return ms_parse_err_code(chip);
                                }
                        }
                }
 
                if (val & MS_RDY_TIMEOUT) {
                        ms_set_err_code(chip, MS_TO_ERROR);
-                       TRACE_RET(chip, ms_parse_err_code(chip));
+                       rtsx_trace(chip);
+                       return ms_parse_err_code(chip);
                }
 
                ms_set_err_code(chip, MS_TO_ERROR);
-               TRACE_RET(chip, ms_parse_err_code(chip));
+               rtsx_trace(chip);
+               return ms_parse_err_code(chip);
        }
 
        return STATUS_SUCCESS;
@@ -242,8 +259,10 @@ static int ms_read_bytes(struct rtsx_chip *chip,
        int retval, i;
        u8 *ptr;
 
-       if (!data)
-               TRACE_RET(chip, STATUS_ERROR);
+       if (!data) {
+               rtsx_trace(chip);
+               return STATUS_ERROR;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -277,25 +296,28 @@ static int ms_read_bytes(struct rtsx_chip *chip,
                if (!(tpc & 0x08)) {
                        if (val & MS_CRC16_ERR) {
                                ms_set_err_code(chip, MS_CRC16_ERROR);
-                               TRACE_RET(chip, ms_parse_err_code(chip));
+                               rtsx_trace(chip);
+                               return ms_parse_err_code(chip);
                        }
                } else {
                        if (CHK_MSPRO(ms_card) && !(val & 0x80)) {
                                if (val & (MS_INT_ERR | MS_INT_CMDNK)) {
                                        ms_set_err_code(chip, MS_CMD_NK);
-                                       TRACE_RET(chip,
-                                               ms_parse_err_code(chip));
+                                       rtsx_trace(chip);
+                                       return ms_parse_err_code(chip);
                                }
                        }
                }
 
                if (val & MS_RDY_TIMEOUT) {
                        ms_set_err_code(chip, MS_TO_ERROR);
-                       TRACE_RET(chip, ms_parse_err_code(chip));
+                       rtsx_trace(chip);
+                       return ms_parse_err_code(chip);
                }
 
                ms_set_err_code(chip, MS_TO_ERROR);
-               TRACE_RET(chip, ms_parse_err_code(chip));
+               rtsx_trace(chip);
+               return ms_parse_err_code(chip);
        }
 
        ptr = rtsx_get_cmd_data(chip) + 1;
@@ -331,7 +353,8 @@ static int ms_set_rw_reg_addr(struct rtsx_chip *chip,
                rtsx_clear_ms_error(chip);
        }
 
-       TRACE_RET(chip, STATUS_FAIL);
+       rtsx_trace(chip);
+       return STATUS_FAIL;
 }
 
 static int ms_send_cmd(struct rtsx_chip *chip, u8 cmd, u8 cfg)
@@ -369,12 +392,16 @@ static int ms_set_init_para(struct rtsx_chip *chip)
        }
 
        retval = switch_clock(chip, ms_card->ms_clock);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = select_card(chip, MS_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -385,37 +412,87 @@ static int ms_switch_clock(struct rtsx_chip *chip)
        int retval;
 
        retval = select_card(chip, MS_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = switch_clock(chip, ms_card->ms_clock);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
 
 static int ms_pull_ctl_disable(struct rtsx_chip *chip)
 {
+       int retval;
+
        if (CHECK_PID(chip, 0x5208)) {
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF,
-                       MS_D1_PD | MS_D2_PD | MS_CLK_PD | MS_D6_PD);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF,
-                       MS_D3_PD | MS_D0_PD | MS_BS_PD | XD_D4_PD);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF,
-                       MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF,
-                       XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF,
-                       MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF,
-                       MS_D5_PD | MS_D4_PD);
+               retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF,
+                                            MS_D1_PD | MS_D2_PD | MS_CLK_PD | MS_D6_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF,
+                                            MS_D3_PD | MS_D0_PD | MS_BS_PD | XD_D4_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF,
+                                            MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF,
+                                            XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF,
+                                            MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL6, 0xFF,
+                                            MS_D5_PD | MS_D4_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        } else if (CHECK_PID(chip, 0x5288)) {
                if (CHECK_BARO_PKG(chip, QFN)) {
-                       RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
-                       RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
-                       RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B);
-                       RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69);
+                       retval = rtsx_write_register(chip, CARD_PULL_CTL1,
+                                                    0xFF, 0x55);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+                       retval = rtsx_write_register(chip, CARD_PULL_CTL2,
+                                                    0xFF, 0x55);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+                       retval = rtsx_write_register(chip, CARD_PULL_CTL3,
+                                                    0xFF, 0x4B);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+                       retval = rtsx_write_register(chip, CARD_PULL_CTL4,
+                                                    0xFF, 0x69);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                }
        }
 
@@ -455,8 +532,10 @@ static int ms_pull_ctl_enable(struct rtsx_chip *chip)
        }
 
        retval = rtsx_send_cmd(chip, MS_CARD, 100);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -475,29 +554,41 @@ static int ms_prepare_reset(struct rtsx_chip *chip)
        ms_card->pro_under_formatting = 0;
 
        retval = ms_power_off_card3v3(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (!chip->ft2_fast_mode)
                wait_timeout(250);
 
        retval = enable_card_clock(chip, MS_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (chip->asic_code) {
                retval = ms_pull_ctl_enable(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        } else {
-               RTSX_WRITE_REG(chip, FPGA_PULL_CTL,
-                       FPGA_MS_PULL_CTL_BIT | 0x20, 0);
+               retval = rtsx_write_register(chip, FPGA_PULL_CTL,
+                                            FPGA_MS_PULL_CTL_BIT | 0x20, 0);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        }
 
        if (!chip->ft2_fast_mode) {
                retval = card_power_on(chip, MS_CARD);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                wait_timeout(150);
 
@@ -510,30 +601,52 @@ static int ms_prepare_reset(struct rtsx_chip *chip)
                if (chip->ocp_stat & oc_mask) {
                        dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
                                chip->ocp_stat);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 #endif
        }
 
-       RTSX_WRITE_REG(chip, CARD_OE, MS_OUTPUT_EN, MS_OUTPUT_EN);
+       retval = rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN,
+                                    MS_OUTPUT_EN);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        if (chip->asic_code) {
-               RTSX_WRITE_REG(chip, MS_CFG, 0xFF,
-                       SAMPLE_TIME_RISING | PUSH_TIME_DEFAULT |
-                       NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1);
+               retval = rtsx_write_register(chip, MS_CFG, 0xFF,
+                                            SAMPLE_TIME_RISING | PUSH_TIME_DEFAULT | NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        } else {
-               RTSX_WRITE_REG(chip, MS_CFG, 0xFF,
-                       SAMPLE_TIME_FALLING | PUSH_TIME_DEFAULT |
-                       NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1);
+               retval = rtsx_write_register(chip, MS_CFG, 0xFF,
+                                            SAMPLE_TIME_FALLING | PUSH_TIME_DEFAULT | NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+       }
+       retval = rtsx_write_register(chip, MS_TRANS_CFG, 0xFF,
+                                    NO_WAIT_INT | NO_AUTO_READ_INT_REG);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR,
+                                    MS_STOP | MS_CLR_ERR);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
        }
-       RTSX_WRITE_REG(chip, MS_TRANS_CFG,
-               0xFF, NO_WAIT_INT | NO_AUTO_READ_INT_REG);
-       RTSX_WRITE_REG(chip, CARD_STOP,
-               MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR);
 
        retval = ms_set_init_para(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -545,8 +658,10 @@ static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus)
        u8 val;
 
        retval = ms_set_rw_reg_addr(chip, Pro_StatusReg, 6, SystemParm, 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
                retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, READ_REG,
@@ -554,29 +669,49 @@ static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus)
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (i == MS_MAX_RETRY_COUNT)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (i == MS_MAX_RETRY_COUNT) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_READ_REG(chip, PPBUF_BASE2 + 2, &val);
+       retval = rtsx_read_register(chip, PPBUF_BASE2 + 2, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        dev_dbg(rtsx_dev(chip), "Type register: 0x%x\n", val);
        if (val != 0x01) {
                if (val != 0x02)
                        ms_card->check_ms_flow = 1;
 
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
-       RTSX_READ_REG(chip, PPBUF_BASE2 + 4, &val);
+       retval = rtsx_read_register(chip, PPBUF_BASE2 + 4, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        dev_dbg(rtsx_dev(chip), "Category register: 0x%x\n", val);
        if (val != 0) {
                ms_card->check_ms_flow = 1;
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
-       RTSX_READ_REG(chip, PPBUF_BASE2 + 5, &val);
+       retval = rtsx_read_register(chip, PPBUF_BASE2 + 5, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        dev_dbg(rtsx_dev(chip), "Class register: 0x%x\n", val);
        if (val == 0) {
-               RTSX_READ_REG(chip, PPBUF_BASE2, &val);
+               retval = rtsx_read_register(chip, PPBUF_BASE2, &val);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                if (val & WRT_PRTCT)
                        chip->card_wp |= MS_CARD;
                else
@@ -586,12 +721,17 @@ static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus)
                chip->card_wp |= MS_CARD;
        } else {
                ms_card->check_ms_flow = 1;
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        ms_card->ms_type |= TYPE_MSPRO;
 
-       RTSX_READ_REG(chip, PPBUF_BASE2 + 3, &val);
+       retval = rtsx_read_register(chip, PPBUF_BASE2 + 3, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        dev_dbg(rtsx_dev(chip), "IF Mode register: 0x%x\n", val);
        if (val == 0) {
                ms_card->ms_type &= 0x0F;
@@ -602,7 +742,8 @@ static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus)
                        ms_card->ms_type &= 0x0F;
 
        } else {
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -618,7 +759,8 @@ static int ms_confirm_cpu_startup(struct rtsx_chip *chip)
        do {
                if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
                        ms_set_err_code(chip, MS_NO_CARD);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
@@ -627,11 +769,15 @@ static int ms_confirm_cpu_startup(struct rtsx_chip *chip)
                        if (retval == STATUS_SUCCESS)
                                break;
                }
-               if (i == MS_MAX_RETRY_COUNT)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (i == MS_MAX_RETRY_COUNT) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
-               if (k > 100)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (k > 100) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                k++;
                wait_timeout(100);
@@ -642,14 +788,18 @@ static int ms_confirm_cpu_startup(struct rtsx_chip *chip)
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (i == MS_MAX_RETRY_COUNT)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (i == MS_MAX_RETRY_COUNT) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (val & INT_REG_ERR) {
                if (val & INT_REG_CMDNK)
                        chip->card_wp |= (MS_CARD);
-               else
-                       TRACE_RET(chip, STATUS_FAIL);
+               else {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
        /* --  end confirm CPU startup */
 
@@ -669,8 +819,10 @@ static int ms_switch_parallel_bus(struct rtsx_chip *chip)
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -689,21 +841,31 @@ static int ms_switch_8bit_bus(struct rtsx_chip *chip)
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_WRITE_REG(chip, MS_CFG, 0x98,
-               MS_BUS_WIDTH_8 | SAMPLE_TIME_FALLING);
+       retval = rtsx_write_register(chip, MS_CFG, 0x98,
+                                    MS_BUS_WIDTH_8 | SAMPLE_TIME_FALLING);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        ms_card->ms_type |= MS_8BIT;
        retval = ms_set_init_para(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
                retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT,
                                        1, NO_WAIT_INT);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -716,22 +878,29 @@ static int ms_pro_reset_flow(struct rtsx_chip *chip, int switch_8bit_bus)
 
        for (i = 0; i < 3; i++) {
                retval = ms_prepare_reset(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = ms_identify_media_type(chip, switch_8bit_bus);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = ms_confirm_cpu_startup(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = ms_switch_parallel_bus(chip);
                if (retval != STATUS_SUCCESS) {
                        if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
                                ms_set_err_code(chip, MS_NO_CARD);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        continue;
                } else {
@@ -739,23 +908,37 @@ static int ms_pro_reset_flow(struct rtsx_chip *chip, int switch_8bit_bus)
                }
        }
 
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        /* Switch MS-PRO into Parallel mode */
-       RTSX_WRITE_REG(chip, MS_CFG, 0x18, MS_BUS_WIDTH_4);
-       RTSX_WRITE_REG(chip, MS_CFG, PUSH_TIME_ODD, PUSH_TIME_ODD);
+       retval = rtsx_write_register(chip, MS_CFG, 0x18, MS_BUS_WIDTH_4);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, MS_CFG, PUSH_TIME_ODD,
+                                    PUSH_TIME_ODD);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        retval = ms_set_init_para(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        /* If MSPro HG Card, We shall try to switch to 8-bit bus */
        if (CHK_MSHG(ms_card) && chip->support_ms_8bit && switch_8bit_bus) {
                retval = ms_switch_8bit_bus(chip);
                if (retval != STATUS_SUCCESS) {
                        ms_card->switch_8bit_fail = 1;
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
@@ -771,8 +954,10 @@ static int msxc_change_power(struct rtsx_chip *chip, u8 mode)
        ms_cleanup_work(chip);
 
        retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        buf[0] = 0;
        buf[1] = mode;
@@ -782,16 +967,26 @@ static int msxc_change_power(struct rtsx_chip *chip, u8 mode)
        buf[5] = 0;
 
        retval = ms_write_bytes(chip, PRO_WRITE_REG, 6, NO_WAIT_INT, buf, 6);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = ms_send_cmd(chip, XC_CHG_POWER, WAIT_INT);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_READ_REG(chip, MS_TRANS_CFG, buf);
-       if (buf[0] & (MS_INT_CMDNK | MS_INT_ERR))
-               TRACE_RET(chip, STATUS_FAIL);
+       retval = rtsx_read_register(chip, MS_TRANS_CFG, buf);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       if (buf[0] & (MS_INT_CMDNK | MS_INT_ERR)) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -813,8 +1008,10 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
 #endif
 
        retval = ms_set_rw_reg_addr(chip, Pro_IntReg, 2, Pro_SystemParm, 7);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (CHK_MS8BIT(ms_card))
                data[0] = PARALLEL_8BIT_IF;
@@ -836,12 +1033,16 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        buf = kmalloc(64 * 512, GFP_KERNEL);
-       if (buf == NULL)
-               TRACE_RET(chip, STATUS_ERROR);
+       if (buf == NULL) {
+               rtsx_trace(chip);
+               return STATUS_ERROR;
+       }
 
        for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
                retval = ms_send_cmd(chip, PRO_READ_ATRB, WAIT_INT);
@@ -851,11 +1052,13 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
                retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
                if (retval != STATUS_SUCCESS) {
                        kfree(buf);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
                if (!(val & MS_INT_BREQ)) {
                        kfree(buf);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
                retval = ms_transfer_data(chip, MS_TM_AUTO_READ,
                                        PRO_READ_LONG_DATA, 0x40, WAIT_INT,
@@ -867,7 +1070,8 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
        }
        if (retval != STATUS_SUCCESS) {
                kfree(buf);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        i = 0;
@@ -875,7 +1079,8 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
                retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
                if (retval != STATUS_SUCCESS) {
                        kfree(buf);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                if ((val & MS_INT_CED) || !(val & MS_INT_BREQ))
@@ -885,7 +1090,8 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
                                        PRO_READ_LONG_DATA, 0, WAIT_INT);
                if (retval != STATUS_SUCCESS) {
                        kfree(buf);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                i++;
@@ -893,18 +1099,21 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
 
        if (retval != STATUS_SUCCESS) {
                kfree(buf);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if ((buf[0] != 0xa5) && (buf[1] != 0xc3)) {
                /* Signature code is wrong */
                kfree(buf);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if ((buf[4] < 1) || (buf[4] > 12)) {
                kfree(buf);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        for (i = 0; i < buf[4]; i++) {
@@ -929,15 +1138,18 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
                                sys_info_addr, sys_info_size);
                        if (sys_info_size != 96)  {
                                kfree(buf);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        if (sys_info_addr < 0x1A0) {
                                kfree(buf);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        if ((sys_info_size + sys_info_addr) > 0x8000) {
                                kfree(buf);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
 #ifdef SUPPORT_MSXC
@@ -964,15 +1176,18 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
                                model_name_addr, model_name_size);
                        if (model_name_size != 48)  {
                                kfree(buf);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        if (model_name_addr < 0x1A0) {
                                kfree(buf);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        if ((model_name_size + model_name_addr) > 0x8000) {
                                kfree(buf);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        found_model_name = 1;
@@ -985,7 +1200,8 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
 
        if (i == buf[4]) {
                kfree(buf);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        class_code =  buf[sys_info_addr + 0];
@@ -1030,15 +1246,21 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
 
 #ifdef SUPPORT_MSXC
        if (CHK_MSXC(ms_card)) {
-               if (class_code != 0x03)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (class_code != 0x03) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        } else {
-               if (class_code != 0x02)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (class_code != 0x02) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 #else
-       if (class_code != 0x02)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (class_code != 0x02) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 #endif
 
        if (device_type != 0x00) {
@@ -1046,12 +1268,15 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
                                (device_type == 0x03)) {
                        chip->card_wp |= MS_CARD;
                } else {
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
-       if (sub_class & 0xC0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (sub_class & 0xC0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        dev_dbg(rtsx_dev(chip), "class_code: 0x%x, device_type: 0x%x, sub_class: 0x%x\n",
                class_code, device_type, sub_class);
@@ -1099,16 +1324,21 @@ Retry:
        if (retval != STATUS_SUCCESS) {
                if (ms_card->switch_8bit_fail) {
                        retval = ms_pro_reset_flow(chip, 0);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                } else {
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
        retval = ms_read_attribute_info(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
 #ifdef XC_POWERCLASS
        if (CHK_HG8BIT(ms_card))
@@ -1148,8 +1378,10 @@ Retry:
 
 #ifdef SUPPORT_MAGIC_GATE
        retval = mg_set_tpc_para_sub(chip, 0, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 #endif
 
        if (CHK_HG8BIT(ms_card))
@@ -1166,16 +1398,21 @@ static int ms_read_status_reg(struct rtsx_chip *chip)
        u8 val[2];
 
        retval = ms_set_rw_reg_addr(chip, StatusReg0, 2, 0, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = ms_read_bytes(chip, READ_REG, 2, NO_WAIT_INT, val, 2);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (val[1] & (STS_UCDT | STS_UCEX | STS_UCFG)) {
                ms_set_err_code(chip, MS_FLASH_READ_ERROR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -1191,8 +1428,10 @@ static int ms_read_extra_data(struct rtsx_chip *chip,
 
        retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
                                SystemParm, 6);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (CHK_MS4BIT(ms_card)) {
                /* Parallel interface */
@@ -1213,8 +1452,10 @@ static int ms_read_extra_data(struct rtsx_chip *chip,
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (i == MS_MAX_RETRY_COUNT)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (i == MS_MAX_RETRY_COUNT) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ms_set_err_code(chip, MS_NO_ERROR);
 
@@ -1223,35 +1464,46 @@ static int ms_read_extra_data(struct rtsx_chip *chip,
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (i == MS_MAX_RETRY_COUNT)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (i == MS_MAX_RETRY_COUNT) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ms_set_err_code(chip, MS_NO_ERROR);
        retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (val & INT_REG_CMDNK) {
                ms_set_err_code(chip, MS_CMD_NK);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
        if (val & INT_REG_CED) {
                if (val & INT_REG_ERR) {
                        retval = ms_read_status_reg(chip);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        retval = ms_set_rw_reg_addr(chip, OverwriteFlag,
                                                MS_EXTRA_SIZE, SystemParm, 6);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                }
        }
 
        retval = ms_read_bytes(chip, READ_REG, MS_EXTRA_SIZE, NO_WAIT_INT,
                        data, MS_EXTRA_SIZE);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (buf && buf_len) {
                if (buf_len > MS_EXTRA_SIZE)
@@ -1269,13 +1521,17 @@ static int ms_write_extra_data(struct rtsx_chip *chip,
        int retval, i;
        u8 val, data[16];
 
-       if (!buf || (buf_len < MS_EXTRA_SIZE))
-               TRACE_RET(chip, STATUS_FAIL);
+       if (!buf || (buf_len < MS_EXTRA_SIZE)) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
                                SystemParm, 6 + MS_EXTRA_SIZE);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (CHK_MS4BIT(ms_card))
                data[0] = 0x88;
@@ -1293,26 +1549,34 @@ static int ms_write_extra_data(struct rtsx_chip *chip,
 
        retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE),
                                NO_WAIT_INT, data, 16);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ms_set_err_code(chip, MS_NO_ERROR);
        retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (val & INT_REG_CMDNK) {
                ms_set_err_code(chip, MS_CMD_NK);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
        if (val & INT_REG_CED) {
                if (val & INT_REG_ERR) {
                        ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
@@ -1328,8 +1592,10 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num)
 
        retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
                                SystemParm, 6);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (CHK_MS4BIT(ms_card))
                data[0] = 0x88;
@@ -1343,28 +1609,36 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num)
        data[5] = page_num;
 
        retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ms_set_err_code(chip, MS_NO_ERROR);
        retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (val & INT_REG_CMDNK) {
                ms_set_err_code(chip, MS_CMD_NK);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (val & INT_REG_CED) {
                if (val & INT_REG_ERR) {
                        if (!(val & INT_REG_BREQ)) {
                                ms_set_err_code(chip,  MS_FLASH_READ_ERROR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        retval = ms_read_status_reg(chip);
                        if (retval != STATUS_SUCCESS)
@@ -1373,18 +1647,23 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num)
                } else {
                        if (!(val & INT_REG_BREQ)) {
                                ms_set_err_code(chip, MS_BREQ_ERROR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
        }
 
        retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, READ_PAGE_DATA,
                                0, NO_WAIT_INT);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR))
-               TRACE_RET(chip, STATUS_FAIL);
+       if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -1397,13 +1676,17 @@ static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk)
        u8 val, data[8], extra[MS_EXTRA_SIZE];
 
        retval = ms_read_extra_data(chip, phy_blk, 0, extra, MS_EXTRA_SIZE);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
                                SystemParm, 7);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ms_set_err_code(chip, MS_NO_ERROR);
 
@@ -1421,27 +1704,35 @@ static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk)
        data[7] = 0xFF;
 
        retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, data, 7);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ms_set_err_code(chip, MS_NO_ERROR);
        retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (val & INT_REG_CMDNK) {
                ms_set_err_code(chip, MS_CMD_NK);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (val & INT_REG_CED) {
                if (val & INT_REG_ERR) {
                        ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
@@ -1457,8 +1748,10 @@ static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk)
 
        retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
                                SystemParm, 6);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ms_set_err_code(chip, MS_NO_ERROR);
 
@@ -1474,18 +1767,24 @@ static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk)
        data[5] = 0;
 
        retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
 ERASE_RTY:
        retval = ms_send_cmd(chip, BLOCK_ERASE, WAIT_INT);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ms_set_err_code(chip, MS_NO_ERROR);
        retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (val & INT_REG_CMDNK) {
                if (i < 3) {
@@ -1495,13 +1794,15 @@ ERASE_RTY:
 
                ms_set_err_code(chip, MS_CMD_NK);
                ms_set_bad_block(chip, phy_blk);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (val & INT_REG_CED) {
                if (val & INT_REG_ERR) {
                        ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
@@ -1544,13 +1845,16 @@ static int ms_init_page(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk,
        for (i = start_page; i < end_page; i++) {
                if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
                        ms_set_err_code(chip, MS_NO_CARD);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                retval = ms_write_extra_data(chip, phy_blk, i,
                                        extra, MS_EXTRA_SIZE);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -1560,7 +1864,8 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
                u16 log_blk, u8 start_page, u8 end_page)
 {
        struct ms_info *ms_card = &(chip->ms_card);
-       int retval, rty_cnt, uncorrect_flag = 0;
+       bool uncorrect_flag = false;
+       int retval, rty_cnt;
        u8 extra[MS_EXTRA_SIZE], val, i, j, data[16];
 
        dev_dbg(rtsx_dev(chip), "Copy page from 0x%x to 0x%x, logical block is 0x%x\n",
@@ -1569,42 +1874,58 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
                start_page, end_page);
 
        retval = ms_read_extra_data(chip, new_blk, 0, extra, MS_EXTRA_SIZE);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = ms_read_status_reg(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_READ_REG(chip, PPBUF_BASE2, &val);
+       retval = rtsx_read_register(chip, PPBUF_BASE2, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        if (val & BUF_FULL) {
                retval = ms_send_cmd(chip, CLEAR_BUF, WAIT_INT);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                if (!(val & INT_REG_CED)) {
                        ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
        for (i = start_page; i < end_page; i++) {
                if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
                        ms_set_err_code(chip, MS_NO_CARD);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                ms_read_extra_data(chip, old_blk, i, extra, MS_EXTRA_SIZE);
 
                retval = ms_set_rw_reg_addr(chip, OverwriteFlag,
                                        MS_EXTRA_SIZE, SystemParm, 6);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                ms_set_err_code(chip, MS_NO_ERROR);
 
@@ -1621,39 +1942,48 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
 
                retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT,
                                        data, 6);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                ms_set_err_code(chip, MS_NO_ERROR);
                retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                if (val & INT_REG_CMDNK) {
                        ms_set_err_code(chip, MS_CMD_NK);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                if (val & INT_REG_CED) {
                        if (val & INT_REG_ERR) {
                                retval = ms_read_status_reg(chip);
                                if (retval != STATUS_SUCCESS) {
-                                       uncorrect_flag = 1;
+                                       uncorrect_flag = true;
                                        dev_dbg(rtsx_dev(chip), "Uncorrectable error\n");
                                } else {
-                                       uncorrect_flag = 0;
+                                       uncorrect_flag = false;
                                }
 
                                retval = ms_transfer_tpc(chip,
                                                        MS_TM_NORMAL_READ,
                                                        READ_PAGE_DATA,
                                                        0, NO_WAIT_INT);
-                               if (retval != STATUS_SUCCESS)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if (retval != STATUS_SUCCESS) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
 
                                if (uncorrect_flag) {
                                        ms_set_page_status(log_blk, setPS_NG,
@@ -1684,13 +2014,16 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
                                        if (retval == STATUS_SUCCESS)
                                                break;
                                }
-                               if (rty_cnt == MS_MAX_RETRY_COUNT)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if (rty_cnt == MS_MAX_RETRY_COUNT) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
                        }
 
                        if (!(val & INT_REG_BREQ)) {
                                ms_set_err_code(chip, MS_BREQ_ERROR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
 
@@ -1724,35 +2057,45 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
 
                retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE),
                                        NO_WAIT_INT, data, 16);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                ms_set_err_code(chip, MS_NO_ERROR);
                retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                if (val & INT_REG_CMDNK) {
                        ms_set_err_code(chip, MS_CMD_NK);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                if (val & INT_REG_CED) {
                        if (val & INT_REG_ERR) {
                                ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
 
                if (i == 0) {
                        retval = ms_set_rw_reg_addr(chip, OverwriteFlag,
                                                MS_EXTRA_SIZE, SystemParm, 7);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        ms_set_err_code(chip, MS_NO_ERROR);
 
@@ -1771,29 +2114,37 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
 
                        retval = ms_write_bytes(chip, WRITE_REG, 7,
                                                NO_WAIT_INT, data, 8);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        ms_set_err_code(chip, MS_NO_ERROR);
                        retval = ms_read_bytes(chip, GET_INT, 1,
                                        NO_WAIT_INT, &val, 1);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        if (val & INT_REG_CMDNK) {
                                ms_set_err_code(chip, MS_CMD_NK);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        if (val & INT_REG_CED) {
                                if (val & INT_REG_ERR) {
                                        ms_set_err_code(chip,
                                                        MS_FLASH_WRITE_ERROR);
-                                       TRACE_RET(chip, STATUS_FAIL);
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
                                }
                        }
                }
@@ -1814,20 +2165,30 @@ static int reset_ms(struct rtsx_chip *chip)
 #endif
 
        retval = ms_prepare_reset(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ms_card->ms_type |= TYPE_MS;
 
        retval = ms_send_cmd(chip, MS_RESET, NO_WAIT_INT);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = ms_read_status_reg(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_READ_REG(chip, PPBUF_BASE2, &val);
+       retval = rtsx_read_register(chip, PPBUF_BASE2, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        if (val & WRT_PRTCT)
                chip->card_wp |= MS_CARD;
        else
@@ -1840,7 +2201,8 @@ RE_SEARCH:
        while (i < (MAX_DEFECTIVE_BLOCK + 2)) {
                if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
                        ms_set_err_code(chip, MS_NO_CARD);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                retval = ms_read_extra_data(chip, i, 0, extra, MS_EXTRA_SIZE);
@@ -1860,7 +2222,8 @@ RE_SEARCH:
 
        if (i == (MAX_DEFECTIVE_BLOCK + 2)) {
                dev_dbg(rtsx_dev(chip), "No boot block found!");
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        for (j = 0; j < 3; j++) {
@@ -1875,8 +2238,10 @@ RE_SEARCH:
        }
 
        retval = ms_read_page(chip, ms_card->boot_block, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        /* Read MS system information as sys_info */
        rtsx_init_cmd(chip);
@@ -1885,8 +2250,10 @@ RE_SEARCH:
                rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 0x1A0 + i, 0, 0);
 
        retval = rtsx_send_cmd(chip, MS_CARD, 100);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ptr = rtsx_get_cmd_data(chip);
        memcpy(ms_card->raw_sys_info, ptr, 96);
@@ -1908,8 +2275,10 @@ RE_SEARCH:
        rtsx_add_cmd(chip, READ_REG_CMD, MS_4bit_Support, 0, 0);
 
        retval = rtsx_send_cmd(chip, MS_CARD, 100);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ptr = rtsx_get_cmd_data(chip);
 
@@ -1982,19 +2351,36 @@ RE_SEARCH:
        /* Switch I/F Mode */
        if (ptr[15]) {
                retval = ms_set_rw_reg_addr(chip, 0, 0, SystemParm, 1);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
-               RTSX_WRITE_REG(chip, PPBUF_BASE2, 0xFF, 0x88);
-               RTSX_WRITE_REG(chip, PPBUF_BASE2 + 1, 0xFF, 0);
+               retval = rtsx_write_register(chip, PPBUF_BASE2, 0xFF, 0x88);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, PPBUF_BASE2 + 1, 0xFF, 0);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
 
                retval = ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG, 1,
                                        NO_WAIT_INT);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
-               RTSX_WRITE_REG(chip, MS_CFG, 0x58 | MS_NO_CHECK_INT,
-                       MS_BUS_WIDTH_4 | PUSH_TIME_ODD | MS_NO_CHECK_INT);
+               retval = rtsx_write_register(chip, MS_CFG,
+                                            0x58 | MS_NO_CHECK_INT,
+                                            MS_BUS_WIDTH_4 | PUSH_TIME_ODD | MS_NO_CHECK_INT);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
 
                ms_card->ms_type |= MS_4BIT;
        }
@@ -2020,29 +2406,41 @@ static int ms_init_l2p_tbl(struct rtsx_chip *chip)
 
        size = ms_card->segment_cnt * sizeof(struct zone_entry);
        ms_card->segment = vzalloc(size);
-       if (ms_card->segment == NULL)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (ms_card->segment == NULL) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = ms_read_page(chip, ms_card->boot_block, 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_GOTO(chip, INIT_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               goto INIT_FAIL;
+       }
 
        reg_addr = PPBUF_BASE2;
        for (i = 0; i < (((ms_card->total_block >> 9) * 10) + 1); i++) {
+               int block_no;
+
                retval = rtsx_read_register(chip, reg_addr++, &val1);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, INIT_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto INIT_FAIL;
+               }
 
                retval = rtsx_read_register(chip, reg_addr++, &val2);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, INIT_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto INIT_FAIL;
+               }
 
                defect_block = ((u16)val1 << 8) | val2;
                if (defect_block == 0xFFFF)
                        break;
 
                seg_no = defect_block / 512;
-               ms_card->segment[seg_no].defect_list[ms_card->segment[seg_no].disable_count++] = defect_block;
+
+               block_no = ms_card->segment[seg_no].disable_count++;
+               ms_card->segment[seg_no].defect_list[block_no] = defect_block;
        }
 
        for (i = 0; i < ms_card->segment_cnt; i++) {
@@ -2187,16 +2585,19 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no)
 {
        struct ms_info *ms_card = &(chip->ms_card);
        struct zone_entry *segment;
-       int retval, table_size, disable_cnt, defect_flag, i;
-       u16 start, end, phy_blk, log_blk, tmp_blk;
+       bool defect_flag;
+       int retval, table_size, disable_cnt, i;
+       u16 start, end, phy_blk, log_blk, tmp_blk, idx;
        u8 extra[MS_EXTRA_SIZE], us1, us2;
 
        dev_dbg(rtsx_dev(chip), "ms_build_l2p_tbl: %d\n", seg_no);
 
        if (ms_card->segment == NULL) {
                retval = ms_init_l2p_tbl(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, retval);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        }
 
        if (ms_card->segment[seg_no].build_flag) {
@@ -2214,15 +2615,19 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no)
 
        if (segment->l2p_table == NULL) {
                segment->l2p_table = vmalloc(table_size * 2);
-               if (segment->l2p_table == NULL)
-                       TRACE_GOTO(chip, BUILD_FAIL);
+               if (segment->l2p_table == NULL) {
+                       rtsx_trace(chip);
+                       goto BUILD_FAIL;
+               }
        }
        memset((u8 *)(segment->l2p_table), 0xff, table_size * 2);
 
        if (segment->free_table == NULL) {
                segment->free_table = vmalloc(MS_FREE_TABLE_CNT * 2);
-               if (segment->free_table == NULL)
-                       TRACE_GOTO(chip, BUILD_FAIL);
+               if (segment->free_table == NULL) {
+                       rtsx_trace(chip);
+                       goto BUILD_FAIL;
+               }
        }
        memset((u8 *)(segment->free_table), 0xff, MS_FREE_TABLE_CNT * 2);
 
@@ -2236,10 +2641,10 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no)
 
        for (phy_blk = start; phy_blk < end; phy_blk++) {
                if (disable_cnt) {
-                       defect_flag = 0;
+                       defect_flag = false;
                        for (i = 0; i < segment->disable_count; i++) {
                                if (phy_blk == segment->defect_list[i]) {
-                                       defect_flag = 1;
+                                       defect_flag = true;
                                        break;
                                }
                        }
@@ -2299,13 +2704,15 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no)
                        continue;
                }
 
-               if (segment->l2p_table[log_blk - ms_start_idx[seg_no]] == 0xFFFF) {
-                       segment->l2p_table[log_blk - ms_start_idx[seg_no]] = phy_blk;
+               idx = log_blk - ms_start_idx[seg_no];
+
+               if (segment->l2p_table[idx] == 0xFFFF) {
+                       segment->l2p_table[idx] = phy_blk;
                        continue;
                }
 
                us1 = extra[0] & 0x10;
-               tmp_blk = segment->l2p_table[log_blk - ms_start_idx[seg_no]];
+               tmp_blk = segment->l2p_table[idx];
                retval = ms_read_extra_data(chip, tmp_blk, 0,
                                        extra, MS_EXTRA_SIZE);
                if (retval != STATUS_SUCCESS)
@@ -2336,17 +2743,20 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no)
 
        for (log_blk = ms_start_idx[seg_no];
             log_blk < ms_start_idx[seg_no + 1]; log_blk++) {
-               if (segment->l2p_table[log_blk-ms_start_idx[seg_no]] == 0xFFFF) {
+               idx = log_blk - ms_start_idx[seg_no];
+               if (segment->l2p_table[idx] == 0xFFFF) {
                        phy_blk = ms_get_unused_block(chip, seg_no);
                        if (phy_blk == 0xFFFF) {
                                chip->card_wp |= MS_CARD;
                                return STATUS_SUCCESS;
                        }
                        retval = ms_init_page(chip, phy_blk, log_blk, 0, 1);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_GOTO(chip, BUILD_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               goto BUILD_FAIL;
+                       }
 
-                       segment->l2p_table[log_blk-ms_start_idx[seg_no]] = phy_blk;
+                       segment->l2p_table[idx] = phy_blk;
                        if (seg_no == ms_card->segment_cnt - 1) {
                                if (segment->unused_blk_cnt < 2) {
                                        chip->card_wp |= MS_CARD;
@@ -2374,14 +2784,18 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no)
                                phy_blk = ms_get_unused_block(chip, 0);
                                retval = ms_copy_page(chip, tmp_blk, phy_blk,
                                                log_blk, 0, ms_card->page_off + 1);
-                               if (retval != STATUS_SUCCESS)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if (retval != STATUS_SUCCESS) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
 
                                segment->l2p_table[log_blk] = phy_blk;
 
                                retval = ms_set_bad_block(chip, tmp_blk);
-                               if (retval != STATUS_SUCCESS)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if (retval != STATUS_SUCCESS) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
                        }
                }
        }
@@ -2411,12 +2825,16 @@ int reset_ms_card(struct rtsx_chip *chip)
        memset(ms_card, 0, sizeof(struct ms_info));
 
        retval = enable_card_clock(chip, MS_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = select_card(chip, MS_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ms_card->ms_type = 0;
 
@@ -2424,24 +2842,31 @@ int reset_ms_card(struct rtsx_chip *chip)
        if (retval != STATUS_SUCCESS) {
                if (ms_card->check_ms_flow) {
                        retval = reset_ms(chip);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                } else {
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
        retval = ms_set_init_para(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (!CHK_MSPRO(ms_card)) {
                /* Build table for the last segment,
                 * to check if L2P table block exists, erasing it
                 */
                retval = ms_build_l2p_tbl(chip, ms_card->total_block / 512 - 1);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        dev_dbg(rtsx_dev(chip), "ms_card->ms_type = 0x%x\n", ms_card->ms_type);
@@ -2470,8 +2895,10 @@ static int mspro_set_rw_cmd(struct rtsx_chip *chip,
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (i == MS_MAX_RETRY_COUNT)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (i == MS_MAX_RETRY_COUNT) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -2511,8 +2938,10 @@ static inline int ms_auto_tune_clock(struct rtsx_chip *chip)
        }
 
        retval = ms_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -2522,7 +2951,8 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb,
                                u16 sector_cnt)
 {
        struct ms_info *ms_card = &(chip->ms_card);
-       int retval, mode_2k = 0;
+       bool mode_2k = false;
+       int retval;
        u16 count;
        u8 val, trans_mode, rw_tpc, rw_cmd;
 
@@ -2547,7 +2977,7 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb,
                                rw_tpc = PRO_WRITE_QUAD_DATA;
                                rw_cmd = PRO_WRITE_2K_DATA;
                        }
-                       mode_2k = 1;
+                       mode_2k = true;
                }
        } else {
                if (srb->sc_data_direction == DMA_FROM_DEVICE) {
@@ -2560,15 +2990,21 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb,
        }
 
        retval = ms_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (srb->sc_data_direction == DMA_FROM_DEVICE)
                trans_mode = MS_TM_AUTO_READ;
        else
                trans_mode = MS_TM_AUTO_WRITE;
 
-       RTSX_READ_REG(chip, MS_TRANS_CFG, &val);
+       retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        if (ms_card->seq_mode) {
                if ((ms_card->pre_dir != srb->sc_data_direction)
@@ -2581,8 +3017,10 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb,
                        ms_card->total_sec_cnt = 0;
                        if (val & MS_INT_BREQ) {
                                retval = ms_send_cmd(chip, PRO_STOP, WAIT_INT);
-                               if (retval != STATUS_SUCCESS)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if (retval != STATUS_SUCCESS) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
 
                                rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
                        }
@@ -2609,7 +3047,8 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb,
                retval = mspro_set_rw_cmd(chip, start_sector, count, rw_cmd);
                if (retval != STATUS_SUCCESS) {
                        ms_card->seq_mode = 0;
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
@@ -2624,7 +3063,8 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb,
                if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
                        chip->rw_need_retry = 0;
                        dev_dbg(rtsx_dev(chip), "No card exist, exit mspro_rw_multi_sector\n");
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                if (val & MS_INT_BREQ)
@@ -2636,7 +3076,8 @@ static int mspro_rw_multi_sector(struct scsi_cmnd *srb,
                        ms_auto_tune_clock(chip);
                }
 
-               TRACE_RET(chip, retval);
+               rtsx_trace(chip);
+               return retval;
        }
 
        if (ms_card->seq_mode) {
@@ -2664,13 +3105,15 @@ static int mspro_read_format_progress(struct rtsx_chip *chip,
        retval = ms_switch_clock(chip);
        if (retval != STATUS_SUCCESS) {
                ms_card->format_status = FORMAT_FAIL;
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp);
        if (retval != STATUS_SUCCESS) {
                ms_card->format_status = FORMAT_FAIL;
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (!(tmp & MS_INT_BREQ)) {
@@ -2679,7 +3122,8 @@ static int mspro_read_format_progress(struct rtsx_chip *chip,
                        return STATUS_SUCCESS;
                }
                ms_card->format_status = FORMAT_FAIL;
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (short_data_len >= 256)
@@ -2691,14 +3135,16 @@ static int mspro_read_format_progress(struct rtsx_chip *chip,
                                MS_NO_CHECK_INT);
        if (retval != STATUS_SUCCESS) {
                ms_card->format_status = FORMAT_FAIL;
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, cnt, WAIT_INT,
                        data, 8);
        if (retval != STATUS_SUCCESS) {
                ms_card->format_status = FORMAT_FAIL;
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        total_progress = (data[0] << 24) | (data[1] << 16) |
@@ -2723,7 +3169,8 @@ static int mspro_read_format_progress(struct rtsx_chip *chip,
                retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp);
                if (retval != STATUS_SUCCESS) {
                        ms_card->format_status = FORMAT_FAIL;
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
                if (tmp & (MS_INT_CED | MS_INT_CMDNK |
                                MS_INT_BREQ | MS_INT_ERR))
@@ -2735,17 +3182,20 @@ static int mspro_read_format_progress(struct rtsx_chip *chip,
        retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT, 0);
        if (retval != STATUS_SUCCESS) {
                ms_card->format_status = FORMAT_FAIL;
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (i == 5000) {
                ms_card->format_status = FORMAT_FAIL;
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) {
                ms_card->format_status = FORMAT_FAIL;
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (tmp & MS_INT_CED) {
@@ -2756,7 +3206,8 @@ static int mspro_read_format_progress(struct rtsx_chip *chip,
        } else {
                ms_card->format_status = FORMAT_FAIL;
                ms_card->pro_under_formatting = 0;
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -2780,7 +3231,7 @@ void mspro_polling_format_status(struct rtsx_chip *chip)
 }
 
 int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip,
-               int short_data_len, int quick_format)
+               int short_data_len, bool quick_format)
 {
        struct ms_info *ms_card = &(chip->ms_card);
        int retval, i;
@@ -2788,12 +3239,16 @@ int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip,
        u16 para;
 
        retval = ms_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = ms_set_rw_reg_addr(chip, 0x00, 0x00, Pro_TPCParm, 0x01);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        memset(buf, 0, 2);
        switch (short_data_len) {
@@ -2818,8 +3273,10 @@ int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (i == MS_MAX_RETRY_COUNT)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (i == MS_MAX_RETRY_COUNT) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (quick_format)
                para = 0x0000;
@@ -2827,13 +3284,21 @@ int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                para = 0x0001;
 
        retval = mspro_set_rw_cmd(chip, 0, para, PRO_FORMAT);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_READ_REG(chip, MS_TRANS_CFG, &tmp);
+       retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
-       if (tmp & (MS_INT_CMDNK | MS_INT_ERR))
-               TRACE_RET(chip, STATUS_FAIL);
+       if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if ((tmp & (MS_INT_BREQ | MS_INT_CED)) == MS_INT_BREQ) {
                ms_card->pro_under_formatting = 1;
@@ -2850,7 +3315,8 @@ int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                return STATUS_SUCCESS;
        }
 
-       TRACE_RET(chip, STATUS_FAIL);
+       rtsx_trace(chip);
+       return STATUS_FAIL;
 }
 
 
@@ -2869,14 +3335,17 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk,
        if (retval == STATUS_SUCCESS) {
                if ((extra[1] & 0x30) != 0x30) {
                        ms_set_err_code(chip, MS_FLASH_READ_ERROR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
        retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
                                SystemParm, 6);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (CHK_MS4BIT(ms_card))
                data[0] = 0x88;
@@ -2895,14 +3364,18 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk,
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (i == MS_MAX_RETRY_COUNT)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (i == MS_MAX_RETRY_COUNT) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ms_set_err_code(chip, MS_NO_ERROR);
 
        retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ptr = buf;
 
@@ -2911,16 +3384,20 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk,
 
                if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
                        ms_set_err_code(chip, MS_NO_CARD);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                if (val & INT_REG_CMDNK) {
                        ms_set_err_code(chip, MS_CMD_NK);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
                if (val & INT_REG_ERR) {
                        if (val & INT_REG_BREQ) {
@@ -2933,34 +3410,42 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk,
                                                                page_addr, extra, MS_EXTRA_SIZE);
                                        }
                                        ms_set_err_code(chip, MS_FLASH_READ_ERROR);
-                                       TRACE_RET(chip, STATUS_FAIL);
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
                                }
                        } else {
                                ms_set_err_code(chip, MS_FLASH_READ_ERROR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                } else {
                        if (!(val & INT_REG_BREQ)) {
                                ms_set_err_code(chip, MS_BREQ_ERROR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
 
                if (page_addr == (end_page - 1)) {
                        if (!(val & INT_REG_CED)) {
                                retval = ms_send_cmd(chip, BLOCK_END, WAIT_INT);
-                               if (retval != STATUS_SUCCESS)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if (retval != STATUS_SUCCESS) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
                        }
 
                        retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT,
                                        &val, 1);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        if (!(val & INT_REG_CED)) {
                                ms_set_err_code(chip, MS_FLASH_READ_ERROR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        trans_cfg = NO_WAIT_INT;
@@ -2993,19 +3478,22 @@ static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk,
                        if (retval == -ETIMEDOUT) {
                                ms_set_err_code(chip, MS_TO_ERROR);
                                rtsx_clear_ms_error(chip);
-                               TRACE_RET(chip, STATUS_TIMEDOUT);
+                               rtsx_trace(chip);
+                               return STATUS_TIMEDOUT;
                        }
 
                        retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
                        if (retval != STATUS_SUCCESS) {
                                ms_set_err_code(chip, MS_TO_ERROR);
                                rtsx_clear_ms_error(chip);
-                               TRACE_RET(chip, STATUS_TIMEDOUT);
+                               rtsx_trace(chip);
+                               return STATUS_TIMEDOUT;
                        }
                        if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) {
                                ms_set_err_code(chip, MS_CRC16_ERROR);
                                rtsx_clear_ms_error(chip);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
 
@@ -3029,8 +3517,10 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk,
        if (!start_page) {
                retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
                                        SystemParm, 7);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                if (CHK_MS4BIT(ms_card))
                        data[0] = 0x88;
@@ -3047,24 +3537,32 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk,
 
                retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT,
                                        data, 8);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                ms_set_err_code(chip, MS_NO_ERROR);
                retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1,
                                        NO_WAIT_INT);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE,
                                SystemParm, (6 + MS_EXTRA_SIZE));
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ms_set_err_code(chip, MS_NO_ERROR);
 
@@ -3096,20 +3594,26 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk,
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (i == MS_MAX_RETRY_COUNT)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (i == MS_MAX_RETRY_COUNT) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
                retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (i == MS_MAX_RETRY_COUNT)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (i == MS_MAX_RETRY_COUNT) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ptr = buf;
        for (page_addr = start_page; page_addr < end_page; page_addr++) {
@@ -3117,20 +3621,24 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk,
 
                if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
                        ms_set_err_code(chip, MS_NO_CARD);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                if (val & INT_REG_CMDNK) {
                        ms_set_err_code(chip, MS_CMD_NK);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
                if (val & INT_REG_ERR) {
                        ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
                if (!(val & INT_REG_BREQ)) {
                        ms_set_err_code(chip, MS_BREQ_ERROR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                udelay(30);
@@ -3161,34 +3669,43 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk,
                        ms_set_err_code(chip, MS_TO_ERROR);
                        rtsx_clear_ms_error(chip);
 
-                       if (retval == -ETIMEDOUT)
-                               TRACE_RET(chip, STATUS_TIMEDOUT);
-                       else
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval == -ETIMEDOUT) {
+                               rtsx_trace(chip);
+                               return STATUS_TIMEDOUT;
+                       }
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                if ((end_page - start_page) == 1) {
                        if (!(val & INT_REG_CED)) {
                                ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                } else {
                        if (page_addr == (end_page - 1)) {
                                if (!(val & INT_REG_CED)) {
                                        retval = ms_send_cmd(chip, BLOCK_END,
                                                        WAIT_INT);
-                                       if (retval != STATUS_SUCCESS)
-                                               TRACE_RET(chip, STATUS_FAIL);
+                                       if (retval != STATUS_SUCCESS) {
+                                               rtsx_trace(chip);
+                                               return STATUS_FAIL;
+                                       }
                                }
 
                                retval = ms_read_bytes(chip, GET_INT, 1,
                                                NO_WAIT_INT, &val, 1);
-                               if (retval != STATUS_SUCCESS)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if (retval != STATUS_SUCCESS) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
                        }
 
                        if ((page_addr == (end_page - 1)) ||
@@ -3196,7 +3713,8 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk,
                                if (!(val & INT_REG_CED)) {
                                        ms_set_err_code(chip,
                                                        MS_FLASH_WRITE_ERROR);
-                                       TRACE_RET(chip, STATUS_FAIL);
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
                                }
                        }
                }
@@ -3217,8 +3735,10 @@ static int ms_finish_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
 
        retval = ms_copy_page(chip, old_blk, new_blk, log_blk,
                        page_off, ms_card->page_off + 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        seg_no = old_blk >> 9;
 
@@ -3244,8 +3764,10 @@ static int ms_prepare_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
        if (start_page) {
                retval = ms_copy_page(chip, old_blk, new_blk, log_blk,
                                0, start_page);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -3260,8 +3782,10 @@ int ms_delay_write(struct rtsx_chip *chip)
 
        if (delay_write->delay_write_flag) {
                retval = ms_set_init_para(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                delay_write->delay_write_flag = 0;
                retval = ms_finish_write(chip,
@@ -3269,8 +3793,10 @@ int ms_delay_write(struct rtsx_chip *chip)
                                        delay_write->new_phyblock,
                                        delay_write->logblock,
                                        delay_write->pageoff);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -3309,7 +3835,8 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
        retval = ms_switch_clock(chip);
        if (retval != STATUS_SUCCESS) {
                ms_rw_fail(srb, chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        log_blk = (u16)(start_sector >> ms_card->block_shift);
@@ -3325,7 +3852,8 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                if (retval != STATUS_SUCCESS) {
                        chip->card_fail |= MS_CARD;
                        set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
@@ -3342,7 +3870,8 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                        if (retval != STATUS_SUCCESS) {
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        old_blk = delay_write->old_phyblock;
                        new_blk = delay_write->new_phyblock;
@@ -3357,7 +3886,8 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                        if (retval != STATUS_SUCCESS) {
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 #endif
                        old_blk = ms_get_l2p_tbl(chip, seg_no,
@@ -3366,7 +3896,8 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                        if ((old_blk == 0xFFFF) || (new_blk == 0xFFFF)) {
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        retval = ms_prepare_write(chip, old_blk, new_blk,
@@ -3375,11 +3906,13 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                                if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
                                        set_sense_type(chip, lun,
                                                SENSE_TYPE_MEDIA_NOT_PRESENT);
-                                       TRACE_RET(chip, STATUS_FAIL);
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
                                }
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 #ifdef MS_DELAY_WRITE
                }
@@ -3391,11 +3924,13 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                        if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_NOT_PRESENT);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 #endif
                old_blk = ms_get_l2p_tbl(chip, seg_no,
@@ -3403,7 +3938,8 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                if (old_blk == 0xFFFF) {
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
@@ -3436,10 +3972,12 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                        if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_NOT_PRESENT);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        ms_rw_fail(srb, chip);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                if (srb->sc_data_direction == DMA_TO_DEVICE) {
@@ -3475,7 +4013,8 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                                chip->card_fail |= MS_CARD;
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_NOT_PRESENT);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
 
@@ -3483,14 +4022,16 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                                        log_blk - ms_start_idx[seg_no]);
                if (old_blk == 0xFFFF) {
                        ms_rw_fail(srb, chip);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                if (srb->sc_data_direction == DMA_TO_DEVICE) {
                        new_blk = ms_get_unused_block(chip, seg_no);
                        if (new_blk == 0xFFFF) {
                                ms_rw_fail(srb, chip);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
 
@@ -3515,11 +4056,13 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                                if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
                                        set_sense_type(chip, lun,
                                                SENSE_TYPE_MEDIA_NOT_PRESENT);
-                                       TRACE_RET(chip, STATUS_FAIL);
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
                                }
 
                                ms_rw_fail(srb, chip);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 #endif
                }
@@ -3581,12 +4124,16 @@ static int ms_poll_int(struct rtsx_chip *chip)
        rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANS_CFG, MS_INT_CED, MS_INT_CED);
 
        retval = rtsx_send_cmd(chip, MS_CARD, 5000);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        val = *rtsx_get_cmd_data(chip);
-       if (val & MS_INT_ERR)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (val & MS_INT_ERR) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -3649,12 +4196,15 @@ static int mg_send_ex_cmd(struct rtsx_chip *chip, u8 cmd, u8 entry_num)
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (i == MS_MAX_RETRY_COUNT)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (i == MS_MAX_RETRY_COUNT) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (check_ms_err(chip)) {
                rtsx_clear_ms_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -3671,8 +4221,10 @@ static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type,
        else
                retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6);
 
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        buf[0] = 0;
        buf[1] = 0;
@@ -3684,8 +4236,10 @@ static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type,
        }
        retval = ms_write_bytes(chip, PRO_WRITE_REG, (type == 0) ? 1 : 6,
                                NO_WAIT_INT, buf, 6);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -3699,19 +4253,23 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (scsi_bufflen(srb) < 12) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = mg_send_ex_cmd(chip, MG_SET_LID, 0);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        memset(buf1, 0, 32);
@@ -3723,12 +4281,14 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                buf1, 32);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
        if (check_ms_err(chip)) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
                rtsx_clear_ms_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -3744,12 +4304,16 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        buf = kmalloc(1540, GFP_KERNEL);
-       if (!buf)
-               TRACE_RET(chip, STATUS_ERROR);
+       if (!buf) {
+               rtsx_trace(chip);
+               return STATUS_ERROR;
+       }
 
        buf[0] = 0x04;
        buf[1] = 0x1A;
@@ -3759,7 +4323,8 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = mg_send_ex_cmd(chip, MG_GET_LEKB, 0);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-               TRACE_GOTO(chip, GetEKBFinish);
+               rtsx_trace(chip);
+               goto GetEKBFinish;
        }
 
        retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
@@ -3767,12 +4332,14 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                rtsx_clear_ms_error(chip);
-               TRACE_GOTO(chip, GetEKBFinish);
+               rtsx_trace(chip);
+               goto GetEKBFinish;
        }
        if (check_ms_err(chip)) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                rtsx_clear_ms_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        bufflen = min_t(int, 1052, scsi_bufflen(srb));
@@ -3795,25 +4362,30 @@ int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = mg_send_ex_cmd(chip, MG_GET_ID, 0);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT,
                        buf, 32);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
        if (check_ms_err(chip)) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
                rtsx_clear_ms_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        memcpy(ms_card->magic_gate_id, buf, 16);
@@ -3822,14 +4394,16 @@ int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = ms_poll_int(chip);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 #endif
 
        retval = mg_send_ex_cmd(chip, MG_SET_RD, 0);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        bufflen = min_t(int, 12, scsi_bufflen(srb));
@@ -3845,12 +4419,14 @@ int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                32, WAIT_INT, buf, 32);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
        if (check_ms_err(chip)) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
                rtsx_clear_ms_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        ms_card->mg_auth = 0;
@@ -3869,25 +4445,30 @@ int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = mg_send_ex_cmd(chip, MG_MAKE_RMS, 0);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT,
                        buf1, 32);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
        if (check_ms_err(chip)) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                rtsx_clear_ms_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        buf2[0] = 0x00;
@@ -3905,7 +4486,8 @@ int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = ms_poll_int(chip);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 #endif
 
@@ -3924,13 +4506,16 @@ int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = mg_send_ex_cmd(chip, MG_MAKE_KSE, 0);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        bufflen = min_t(int, 12, scsi_bufflen(srb));
@@ -3946,12 +4531,14 @@ int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                buf, 32);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
        if (check_ms_err(chip)) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
                rtsx_clear_ms_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        ms_card->mg_auth = 1;
@@ -3970,12 +4557,16 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        buf = kmalloc(1028, GFP_KERNEL);
-       if (!buf)
-               TRACE_RET(chip, STATUS_ERROR);
+       if (!buf) {
+               rtsx_trace(chip);
+               return STATUS_ERROR;
+       }
 
        buf[0] = 0x04;
        buf[1] = 0x02;
@@ -3985,7 +4576,8 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = mg_send_ex_cmd(chip, MG_GET_IBD, ms_card->mg_entry_num);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-               TRACE_GOTO(chip, GetICVFinish);
+               rtsx_trace(chip);
+               goto GetICVFinish;
        }
 
        retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
@@ -3993,12 +4585,14 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                rtsx_clear_ms_error(chip);
-               TRACE_GOTO(chip, GetICVFinish);
+               rtsx_trace(chip);
+               goto GetICVFinish;
        }
        if (check_ms_err(chip)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                rtsx_clear_ms_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        bufflen = min_t(int, 1028, scsi_bufflen(srb));
@@ -4023,12 +4617,16 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        ms_cleanup_work(chip);
 
        retval = ms_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        buf = kmalloc(1028, GFP_KERNEL);
-       if (!buf)
-               TRACE_RET(chip, STATUS_ERROR);
+       if (!buf) {
+               rtsx_trace(chip);
+               return STATUS_ERROR;
+       }
 
        bufflen = min_t(int, 1028, scsi_bufflen(srb));
        rtsx_stor_get_xfer_buf(buf, bufflen, srb);
@@ -4045,7 +4643,8 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                } else {
                        set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
                }
-               TRACE_GOTO(chip, SetICVFinish);
+               rtsx_trace(chip);
+               goto SetICVFinish;
        }
 
 #ifdef MG_SET_ICV_SLOW
@@ -4084,7 +4683,8 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                        SENSE_TYPE_MG_WRITE_ERR);
                        }
                        retval = STATUS_FAIL;
-                       TRACE_GOTO(chip, SetICVFinish);
+                       rtsx_trace(chip);
+                       goto SetICVFinish;
                }
        }
 #else
@@ -4102,7 +4702,8 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                } else {
                        set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
                }
-               TRACE_GOTO(chip, SetICVFinish);
+               rtsx_trace(chip);
+               goto SetICVFinish;
        }
 #endif
 
@@ -4142,22 +4743,37 @@ int ms_power_off_card3v3(struct rtsx_chip *chip)
        int retval;
 
        retval = disable_card_clock(chip, MS_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (chip->asic_code) {
                retval = ms_pull_ctl_disable(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        } else {
-               RTSX_WRITE_REG(chip, FPGA_PULL_CTL,
-                       FPGA_MS_PULL_CTL_BIT | 0x20, FPGA_MS_PULL_CTL_BIT);
+               retval = rtsx_write_register(chip, FPGA_PULL_CTL,
+                                            FPGA_MS_PULL_CTL_BIT | 0x20,
+                                            FPGA_MS_PULL_CTL_BIT);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+       }
+       retval = rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
        }
-       RTSX_WRITE_REG(chip, CARD_OE, MS_OUTPUT_EN, 0);
        if (!chip->ft2_fast_mode) {
                retval = card_power_off(chip, MS_CARD);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -4185,8 +4801,10 @@ int release_ms_card(struct rtsx_chip *chip)
 #endif
 
        retval = ms_power_off_card3v3(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
index 26c5b03d535e7805bc5d29f169226affc55fefed..d919170f2720ee485d6a6a9bf80a8f2b322e5950 100644 (file)
@@ -205,7 +205,7 @@ int reset_ms_card(struct rtsx_chip *chip);
 int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
        u32 start_sector, u16 sector_cnt);
 int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip,
-               int short_data_len, int quick_format);
+               int short_data_len, bool quick_format);
 void ms_free_l2p_tbl(struct rtsx_chip *chip);
 void ms_cleanup_work(struct rtsx_chip *chip);
 int ms_power_off_card3v3(struct rtsx_chip *chip);
index c74f1b8108f601aa44558e7abe1ee6e813d77092..d64b6ed9c0c967eb725a8911bc04138e6d25430d 100644 (file)
 #include <linux/workqueue.h>
 
 #include "rtsx.h"
-#include "rtsx_chip.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-#include "general.h"
-
 #include "ms.h"
 #include "sd.h"
 #include "xd.h"
@@ -137,8 +131,8 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
 
        /* check for state-transition errors */
        if (chip->srb != NULL) {
-               dev_err(&dev->pci->dev, "Error in %s: chip->srb = %p\n",
-                       __func__, chip->srb);
+               dev_err(&dev->pci->dev, "Error: chip->srb = %p\n",
+                       chip->srb);
                return SCSI_MLQUEUE_HOST_BUSY;
        }
 
@@ -1036,7 +1030,7 @@ static const struct pci_device_id rtsx_ids[] = {
 MODULE_DEVICE_TABLE(pci, rtsx_ids);
 
 /* pci_driver definition */
-static struct pci_driver driver = {
+static struct pci_driver rtsx_driver = {
        .name = CR_DRIVER_NAME,
        .id_table = rtsx_ids,
        .probe = rtsx_probe,
@@ -1048,21 +1042,4 @@ static struct pci_driver driver = {
        .shutdown = rtsx_shutdown,
 };
 
-static int __init rtsx_init(void)
-{
-       pr_info("Initializing Realtek PCIE storage driver...\n");
-
-       return pci_register_driver(&driver);
-}
-
-static void __exit rtsx_exit(void)
-{
-       pr_info("rtsx_exit() called\n");
-
-       pci_unregister_driver(&driver);
-
-       pr_info("%s module exit\n", CR_DRIVER_NAME);
-}
-
-module_init(rtsx_init)
-module_exit(rtsx_exit)
+module_pci_driver(rtsx_driver);
index 9e6ecb7457b502d45a76dee849e7570dc1b63421..262441bcfc41ab5f0b2a5c9bacbd11081ad88fd7 100644 (file)
@@ -46,9 +46,6 @@
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 
-#include "trace.h"
-#include "general.h"
-
 #define CR_DRIVER_NAME         "rts5208"
 
 #define pci_get_bus_and_slot(bus, devfn)       \
@@ -181,4 +178,14 @@ enum xfer_buf_dir  {TO_XFER_BUF, FROM_XFER_BUF};
 
 int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val);
 
+#define _MSG_TRACE
+
+#include "trace.h"
+#include "rtsx_chip.h"
+#include "rtsx_transport.h"
+#include "rtsx_scsi.h"
+#include "rtsx_card.h"
+#include "rtsx_sys.h"
+#include "general.h"
+
 #endif  /* __REALTEK_RTSX_H */
index b4595ab3f02b18c0d9e376fd68013b9a04069155..437436f5dbdd33f8d4b8b8b75094190954fe44d6 100644 (file)
 #include <linux/kernel.h>
 
 #include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-
-#include "rtsx_sys.h"
-#include "general.h"
-
 #include "sd.h"
 #include "xd.h"
 #include "ms.h"
@@ -657,8 +650,10 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk)
        dev_dbg(rtsx_dev(chip), "Switch SSC clock to %dMHz (cur_clk = %d)\n",
                clk, chip->cur_clk);
 
-       if ((clk <= 2) || (N > max_N))
-               TRACE_RET(chip, STATUS_FAIL);
+       if ((clk <= 2) || (N > max_N)) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        mcu_cnt = (u8)(125/clk + 3);
        if (mcu_cnt > 7)
@@ -697,11 +692,17 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk)
        }
 
        retval = rtsx_send_cmd(chip, 0, WAIT_TIME);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_ERROR);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_ERROR;
+       }
 
        udelay(10);
-       RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0);
+       retval = rtsx_write_register(chip, CLK_CTL, CLK_LOW_FREQ, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        chip->cur_clk = clk;
 
@@ -710,6 +711,7 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk)
 
 int switch_normal_clock(struct rtsx_chip *chip, int clk)
 {
+       int retval;
        u8 sel, div, mcu_cnt;
        int sd_vpclk_phase_reset = 0;
 
@@ -790,26 +792,62 @@ int switch_normal_clock(struct rtsx_chip *chip, int clk)
        default:
                dev_dbg(rtsx_dev(chip), "Try to switch to an illegal clock (%d)\n",
                        clk);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
-       RTSX_WRITE_REG(chip, CLK_CTL, 0xFF, CLK_LOW_FREQ);
+       retval = rtsx_write_register(chip, CLK_CTL, 0xFF, CLK_LOW_FREQ);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        if (sd_vpclk_phase_reset) {
-               RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
-               RTSX_WRITE_REG(chip, SD_VPCLK1_CTL, PHASE_NOT_RESET, 0);
+               retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
+                                            PHASE_NOT_RESET, 0);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, SD_VPCLK1_CTL,
+                                            PHASE_NOT_RESET, 0);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+       }
+       retval = rtsx_write_register(chip, CLK_DIV, 0xFF,
+                                    (div << 4) | mcu_cnt);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, CLK_SEL, 0xFF, sel);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
        }
-       RTSX_WRITE_REG(chip, CLK_DIV, 0xFF, (div << 4) | mcu_cnt);
-       RTSX_WRITE_REG(chip, CLK_SEL, 0xFF, sel);
 
        if (sd_vpclk_phase_reset) {
                udelay(200);
-               RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET,
-                               PHASE_NOT_RESET);
-               RTSX_WRITE_REG(chip, SD_VPCLK1_CTL, PHASE_NOT_RESET,
-                               PHASE_NOT_RESET);
+               retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
+                                            PHASE_NOT_RESET, PHASE_NOT_RESET);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, SD_VPCLK1_CTL,
+                                            PHASE_NOT_RESET, PHASE_NOT_RESET);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                udelay(200);
        }
-       RTSX_WRITE_REG(chip, CLK_CTL, 0xFF, 0);
+       retval = rtsx_write_register(chip, CLK_CTL, 0xFF, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        chip->cur_clk = clk;
 
@@ -844,6 +882,7 @@ void trans_dma_enable(enum dma_data_direction dir, struct rtsx_chip *chip,
 
 int enable_card_clock(struct rtsx_chip *chip, u8 card)
 {
+       int retval;
        u8 clk_en = 0;
 
        if (card & XD_CARD)
@@ -853,13 +892,18 @@ int enable_card_clock(struct rtsx_chip *chip, u8 card)
        if (card & MS_CARD)
                clk_en |= MS_CLK_EN;
 
-       RTSX_WRITE_REG(chip, CARD_CLK_EN, clk_en, clk_en);
+       retval = rtsx_write_register(chip, CARD_CLK_EN, clk_en, clk_en);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
 
 int disable_card_clock(struct rtsx_chip *chip, u8 card)
 {
+       int retval;
        u8 clk_en = 0;
 
        if (card & XD_CARD)
@@ -869,7 +913,11 @@ int disable_card_clock(struct rtsx_chip *chip, u8 card)
        if (card & MS_CARD)
                clk_en |= MS_CLK_EN;
 
-       RTSX_WRITE_REG(chip, CARD_CLK_EN, clk_en, 0);
+       retval = rtsx_write_register(chip, CARD_CLK_EN, clk_en, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -893,8 +941,10 @@ int card_power_on(struct rtsx_chip *chip, u8 card)
        rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val1);
 
        retval = rtsx_send_cmd(chip, 0, 100);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        udelay(chip->pmos_pwr_on_interval);
 
@@ -902,14 +952,17 @@ int card_power_on(struct rtsx_chip *chip, u8 card)
        rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val2);
 
        retval = rtsx_send_cmd(chip, 0, 100);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
 
 int card_power_off(struct rtsx_chip *chip, u8 card)
 {
+       int retval;
        u8 mask, val;
 
        if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && (card == MS_CARD)) {
@@ -920,7 +973,11 @@ int card_power_off(struct rtsx_chip *chip, u8 card)
                val = SD_POWER_OFF;
        }
 
-       RTSX_WRITE_REG(chip, CARD_PWR_CTL, mask, val);
+       retval = rtsx_write_register(chip, CARD_PWR_CTL, mask, val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -932,8 +989,10 @@ int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
        unsigned int lun = SCSI_LUN(srb);
        int i;
 
-       if (chip->rw_card[lun] == NULL)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (chip->rw_card[lun] == NULL) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        for (i = 0; i < 3; i++) {
                chip->rw_need_retry = 0;
@@ -942,11 +1001,14 @@ int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                if (retval != STATUS_SUCCESS) {
                        if (rtsx_check_chip_exist(chip) != STATUS_SUCCESS) {
                                rtsx_release_chip(chip);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        if (detect_card_cd(chip, chip->cur_card) !=
-                                                       STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                                                       STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        if (!chip->rw_need_retry) {
                                dev_dbg(rtsx_dev(chip), "RW fail, but no need to retry\n");
@@ -965,6 +1027,7 @@ int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
 
 int card_share_mode(struct rtsx_chip *chip, int card)
 {
+       int retval;
        u8 mask, value;
 
        if (CHECK_PID(chip, 0x5208)) {
@@ -975,8 +1038,10 @@ int card_share_mode(struct rtsx_chip *chip, int card)
                        value = CARD_SHARE_48_MS;
                else if (card == XD_CARD)
                        value = CARD_SHARE_48_XD;
-               else
-                       TRACE_RET(chip, STATUS_FAIL);
+               else {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
        } else if (CHECK_PID(chip, 0x5288)) {
                mask = 0x03;
@@ -986,14 +1051,21 @@ int card_share_mode(struct rtsx_chip *chip, int card)
                        value = CARD_SHARE_BAROSSA_MS;
                else if (card == XD_CARD)
                        value = CARD_SHARE_BAROSSA_XD;
-               else
-                       TRACE_RET(chip, STATUS_FAIL);
+               else {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
        } else {
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
-       RTSX_WRITE_REG(chip, CARD_SHARE_MODE, mask, value);
+       retval = rtsx_write_register(chip, CARD_SHARE_MODE, mask, value);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -1014,15 +1086,23 @@ int select_card(struct rtsx_chip *chip, int card)
                        mod = XD_MOD_SEL;
                else if (card == SPI_CARD)
                        mod = SPI_MOD_SEL;
-               else
-                       TRACE_RET(chip, STATUS_FAIL);
+               else {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
-               RTSX_WRITE_REG(chip, CARD_SELECT, 0x07, mod);
+               retval = rtsx_write_register(chip, CARD_SELECT, 0x07, mod);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                chip->cur_card = card;
 
                retval =  card_share_mode(chip, card);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -1067,12 +1147,15 @@ int detect_card_cd(struct rtsx_chip *chip, int card)
                card_cd = XD_EXIST;
        } else {
                dev_dbg(rtsx_dev(chip), "Wrong card type: 0x%x\n", card);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        status = rtsx_readl(chip, RTSX_BIPR);
-       if (!(status & card_cd))
-               TRACE_RET(chip, STATUS_FAIL);
+       if (!(status & card_cd)) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
index 75cf5889bda4ec42172038f2ef8c52f883233c12..8f2cf9a4ec69b52f878174e29d2ecf175a5dd55f 100644 (file)
@@ -1061,7 +1061,13 @@ int card_power_off(struct rtsx_chip *chip, u8 card);
 
 static inline int card_power_off_all(struct rtsx_chip *chip)
 {
-       RTSX_WRITE_REG(chip, CARD_PWR_CTL, 0x0F, 0x0F);
+       int retval;
+
+       retval = rtsx_write_register(chip, CARD_PWR_CTL, 0x0F, 0x0F);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
index 9593d8132938ee334ad3ec4dc5d9704c07ae4863..0c1716ebc827477ccd041389d2e64932a9c02642 100644 (file)
 #include <linux/vmalloc.h>
 
 #include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-#include "rtsx_chip.h"
-#include "rtsx_sys.h"
-#include "general.h"
-
 #include "sd.h"
 #include "xd.h"
 #include "ms.h"
@@ -123,22 +116,46 @@ void rtsx_disable_bus_int(struct rtsx_chip *chip)
 
 static int rtsx_pre_handle_sdio_old(struct rtsx_chip *chip)
 {
+       int retval;
+
        if (chip->ignore_sd && CHK_SDIO_EXIST(chip)) {
                if (chip->asic_code) {
-                       RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF,
-                                      MS_INS_PU | SD_WP_PU |
-                                      SD_CD_PU | SD_CMD_PU);
+                       retval = rtsx_write_register(chip, CARD_PULL_CTL5,
+                                                    0xFF,
+                                                    MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                } else {
-                       RTSX_WRITE_REG(chip, FPGA_PULL_CTL, 0xFF,
-                                      FPGA_SD_PULL_CTL_EN);
+                       retval = rtsx_write_register(chip, FPGA_PULL_CTL,
+                                                    0xFF,
+                                                    FPGA_SD_PULL_CTL_EN);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+               }
+               retval = rtsx_write_register(chip, CARD_SHARE_MODE, 0xFF,
+                                            CARD_SHARE_48_SD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
                }
-               RTSX_WRITE_REG(chip, CARD_SHARE_MODE, 0xFF, CARD_SHARE_48_SD);
 
                /* Enable SDIO internal clock */
-               RTSX_WRITE_REG(chip, 0xFF2C, 0x01, 0x01);
+               retval = rtsx_write_register(chip, 0xFF2C, 0x01, 0x01);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
 
-               RTSX_WRITE_REG(chip, SDIO_CTRL, 0xFF,
-                              SDIO_BUS_CTRL | SDIO_CD_CTRL);
+               retval = rtsx_write_register(chip, SDIO_CTRL, 0xFF,
+                                            SDIO_BUS_CTRL | SDIO_CD_CTRL);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
 
                chip->sd_int = 1;
                chip->sd_io = 1;
@@ -153,22 +170,30 @@ static int rtsx_pre_handle_sdio_old(struct rtsx_chip *chip)
 static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip)
 {
        u8 tmp;
-       int sw_bypass_sd = 0;
+       bool sw_bypass_sd = false;
        int retval;
 
        if (chip->driver_first_load) {
                if (CHECK_PID(chip, 0x5288)) {
-                       RTSX_READ_REG(chip, 0xFE5A, &tmp);
+                       retval = rtsx_read_register(chip, 0xFE5A, &tmp);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                        if (tmp & 0x08)
-                               sw_bypass_sd = 1;
+                               sw_bypass_sd = true;
                } else if (CHECK_PID(chip, 0x5208)) {
-                       RTSX_READ_REG(chip, 0xFE70, &tmp);
+                       retval = rtsx_read_register(chip, 0xFE70, &tmp);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                        if (tmp & 0x80)
-                               sw_bypass_sd = 1;
+                               sw_bypass_sd = true;
                }
        } else {
                if (chip->sdio_in_charge)
-                       sw_bypass_sd = 1;
+                       sw_bypass_sd = true;
        }
        dev_dbg(rtsx_dev(chip), "chip->sdio_in_charge = %d\n",
                chip->sdio_in_charge);
@@ -180,17 +205,37 @@ static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip)
        if (sw_bypass_sd) {
                u8 cd_toggle_mask = 0;
 
-               RTSX_READ_REG(chip, TLPTISTAT, &tmp);
+               retval = rtsx_read_register(chip, TLPTISTAT, &tmp);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                cd_toggle_mask = 0x08;
 
                if (tmp & cd_toggle_mask) {
                        /* Disable sdio_bus_auto_switch */
-                       if (CHECK_PID(chip, 0x5288))
-                               RTSX_WRITE_REG(chip, 0xFE5A, 0x08, 0x00);
-                       else if (CHECK_PID(chip, 0x5208))
-                               RTSX_WRITE_REG(chip, 0xFE70, 0x80, 0x00);
+                       if (CHECK_PID(chip, 0x5288)) {
+                               retval = rtsx_write_register(chip, 0xFE5A,
+                                                            0x08, 0x00);
+                               if (retval) {
+                                       rtsx_trace(chip);
+                                       return retval;
+                               }
+                       } else if (CHECK_PID(chip, 0x5208)) {
+                               retval = rtsx_write_register(chip, 0xFE70,
+                                                            0x80, 0x00);
+                               if (retval) {
+                                       rtsx_trace(chip);
+                                       return retval;
+                               }
+                       }
 
-                       RTSX_WRITE_REG(chip, TLPTISTAT, 0xFF, tmp);
+                       retval = rtsx_write_register(chip, TLPTISTAT, 0xFF,
+                                                    tmp);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
 
                        chip->need_reset |= SD_CARD;
                } else {
@@ -198,27 +243,52 @@ static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip)
 
                        if (chip->asic_code) {
                                retval = sd_pull_ctl_enable(chip);
-                               if (retval != STATUS_SUCCESS)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if (retval != STATUS_SUCCESS) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
                        } else {
-                               RTSX_WRITE_REG(chip, FPGA_PULL_CTL,
-                                              FPGA_SD_PULL_CTL_BIT | 0x20, 0);
+                               retval = rtsx_write_register(chip,
+                                                            FPGA_PULL_CTL,
+                                                            FPGA_SD_PULL_CTL_BIT | 0x20,
+                                                            0);
+                               if (retval) {
+                                       rtsx_trace(chip);
+                                       return retval;
+                               }
                        }
                        retval = card_share_mode(chip, SD_CARD);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        /* Enable sdio_bus_auto_switch */
-                       if (CHECK_PID(chip, 0x5288))
-                               RTSX_WRITE_REG(chip, 0xFE5A, 0x08, 0x08);
-                       else if (CHECK_PID(chip, 0x5208))
-                               RTSX_WRITE_REG(chip, 0xFE70, 0x80, 0x80);
+                       if (CHECK_PID(chip, 0x5288)) {
+                               retval = rtsx_write_register(chip, 0xFE5A,
+                                                            0x08, 0x08);
+                               if (retval) {
+                                       rtsx_trace(chip);
+                                       return retval;
+                               }
+                       } else if (CHECK_PID(chip, 0x5208)) {
+                               retval = rtsx_write_register(chip, 0xFE70,
+                                                            0x80, 0x80);
+                               if (retval) {
+                                       rtsx_trace(chip);
+                                       return retval;
+                               }
+                       }
 
                        chip->chip_insert_with_sdio = 1;
                        chip->sd_io = 1;
                }
        } else {
-               RTSX_WRITE_REG(chip, TLPTISTAT, 0x08, 0x08);
+               retval = rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
 
                chip->need_reset |= SD_CARD;
        }
@@ -237,25 +307,36 @@ static int rtsx_reset_aspm(struct rtsx_chip *chip)
 
                ret = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF,
                                        chip->aspm_l0s_l1_en);
-               if (ret != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (ret != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                return STATUS_SUCCESS;
        }
 
-       if (CHECK_PID(chip, 0x5208))
-               RTSX_WRITE_REG(chip, ASPM_FORCE_CTL, 0xFF, 0x3F);
+       if (CHECK_PID(chip, 0x5208)) {
+               ret = rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFF, 0x3F);
+               if (ret) {
+                       rtsx_trace(chip);
+                       return ret;
+               }
+       }
        ret = rtsx_write_config_byte(chip, LCTLR, chip->aspm_l0s_l1_en);
-       if (ret != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (ret != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        chip->aspm_level[0] = chip->aspm_l0s_l1_en;
        if (CHK_SDIO_EXIST(chip)) {
                chip->aspm_level[1] = chip->aspm_l0s_l1_en;
                ret = rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1,
                                        0xC0, 0xFF, chip->aspm_l0s_l1_en);
-               if (ret != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (ret != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        chip->aspm_enabled = 1;
@@ -273,7 +354,11 @@ static int rtsx_enable_pcie_intr(struct rtsx_chip *chip)
        }
 
        if (chip->phy_debug_mode) {
-               RTSX_WRITE_REG(chip, CDRESUMECTL, 0x77, 0);
+               ret = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0);
+               if (ret) {
+                       rtsx_trace(chip);
+                       return ret;
+               }
                rtsx_disable_bus_int(chip);
        } else {
                rtsx_enable_bus_int(chip);
@@ -283,23 +368,31 @@ static int rtsx_enable_pcie_intr(struct rtsx_chip *chip)
                u16 reg;
 
                ret = rtsx_read_phy_register(chip, 0x00, &reg);
-               if (ret != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (ret != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                reg &= 0xFE7F;
                reg |= 0x80;
                ret = rtsx_write_phy_register(chip, 0x00, reg);
-               if (ret != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (ret != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                ret = rtsx_read_phy_register(chip, 0x1C, &reg);
-               if (ret != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (ret != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                reg &= 0xFFF7;
                ret = rtsx_write_phy_register(chip, 0x1C, reg);
-               if (ret != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (ret != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        if (chip->driver_first_load && (chip->ic_version < IC_VER_C))
@@ -316,47 +409,116 @@ int rtsx_reset_chip(struct rtsx_chip *chip)
 
        rtsx_disable_aspm(chip);
 
-       RTSX_WRITE_REG(chip, HOST_SLEEP_STATE, 0x03, 0x00);
+       retval = rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 0x00);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        /* Disable card clock */
-       RTSX_WRITE_REG(chip, CARD_CLK_EN, 0x1E, 0);
+       retval = rtsx_write_register(chip, CARD_CLK_EN, 0x1E, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
 #ifdef SUPPORT_OCP
        /* SSC power on, OCD power on */
-       if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
-               RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, 0);
-       else
-               RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, MS_OC_POWER_DOWN);
+       if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+               retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN, 0);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+       } else {
+               retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN,
+                                            MS_OC_POWER_DOWN);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+       }
 
-       RTSX_WRITE_REG(chip, OCPPARA1, OCP_TIME_MASK, OCP_TIME_800);
-       RTSX_WRITE_REG(chip, OCPPARA2, OCP_THD_MASK, OCP_THD_244_946);
-       RTSX_WRITE_REG(chip, OCPCTL, 0xFF, CARD_OC_INT_EN | CARD_DETECT_EN);
+       retval = rtsx_write_register(chip, OCPPARA1, OCP_TIME_MASK,
+                                    OCP_TIME_800);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, OCPPARA2, OCP_THD_MASK,
+                                    OCP_THD_244_946);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, OCPCTL, 0xFF,
+                                    CARD_OC_INT_EN | CARD_DETECT_EN);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 #else
        /* OC power down */
-       RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, OC_POWER_DOWN);
+       retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN,
+                                    OC_POWER_DOWN);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 #endif
 
-       if (!CHECK_PID(chip, 0x5288))
-               RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0xFF, 0x03);
+       if (!CHECK_PID(chip, 0x5288)) {
+               retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0xFF, 0x03);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+       }
 
        /* Turn off LED */
-       RTSX_WRITE_REG(chip, CARD_GPIO, 0xFF, 0x03);
+       retval = rtsx_write_register(chip, CARD_GPIO, 0xFF, 0x03);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        /* Reset delink mode */
-       RTSX_WRITE_REG(chip, CHANGE_LINK_STATE, 0x0A, 0);
+       retval = rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        /* Card driving select */
-       RTSX_WRITE_REG(chip, CARD_DRIVE_SEL, 0xFF, chip->card_drive_sel);
+       retval = rtsx_write_register(chip, CARD_DRIVE_SEL, 0xFF,
+                                    chip->card_drive_sel);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
 #ifdef LED_AUTO_BLINK
-       RTSX_WRITE_REG(chip, CARD_AUTO_BLINK, 0xFF,
-                      LED_BLINK_SPEED | BLINK_EN | LED_GPIO0);
+       retval = rtsx_write_register(chip, CARD_AUTO_BLINK, 0xFF,
+                                    LED_BLINK_SPEED | BLINK_EN | LED_GPIO0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 #endif
 
        if (chip->asic_code) {
                /* Enable SSC Clock */
-               RTSX_WRITE_REG(chip, SSC_CTL1, 0xFF, SSC_8X_EN | SSC_SEL_4M);
-               RTSX_WRITE_REG(chip, SSC_CTL2, 0xFF, 0x12);
+               retval = rtsx_write_register(chip, SSC_CTL1, 0xFF,
+                                            SSC_8X_EN | SSC_SEL_4M);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, SSC_CTL2, 0xFF, 0x12);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        }
 
        /* Disable cd_pwr_save (u_force_rst_core_en=0, u_cd_rst_core_en=0)
@@ -366,55 +528,84 @@ int rtsx_reset_chip(struct rtsx_chip *chip)
              bit[5]    u_mac_phy_rst_n_dbg     rst_value = 1
              bit[4]    u_non_sticky_rst_n_dbg  rst_value = 0
        */
-       RTSX_WRITE_REG(chip, CHANGE_LINK_STATE, 0x16, 0x10);
+       retval = rtsx_write_register(chip, CHANGE_LINK_STATE, 0x16, 0x10);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        /* Enable ASPM */
        if (chip->aspm_l0s_l1_en) {
                retval = rtsx_reset_aspm(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        } else {
                if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
                        retval = rtsx_write_phy_register(chip, 0x07, 0x0129);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                }
                retval = rtsx_write_config_byte(chip, LCTLR,
                                                chip->aspm_l0s_l1_en);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        retval = rtsx_write_config_byte(chip, 0x81, 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (CHK_SDIO_EXIST(chip)) {
                retval = rtsx_write_cfg_dw(chip,
                                           CHECK_PID(chip, 0x5288) ? 2 : 1,
                                           0xC0, 0xFF00, 0x0100);
 
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        if (CHECK_PID(chip, 0x5288) && !CHK_SDIO_EXIST(chip)) {
                retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFFFF, 0x0103);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = rtsx_write_cfg_dw(chip, 2, 0x84, 0xFF, 0x03);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
-       RTSX_WRITE_REG(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT);
+       retval = rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT,
+                                    LINK_RDY_INT);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
-       RTSX_WRITE_REG(chip, PERST_GLITCH_WIDTH, 0xFF, 0x80);
+       retval = rtsx_write_register(chip, PERST_GLITCH_WIDTH, 0xFF, 0x80);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        retval = rtsx_enable_pcie_intr(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        chip->need_reset = 0;
 
@@ -436,13 +627,19 @@ int rtsx_reset_chip(struct rtsx_chip *chip)
 #else  /* HW_AUTO_SWITCH_SD_BUS */
                retval = rtsx_pre_handle_sdio_old(chip);
 #endif  /* HW_AUTO_SWITCH_SD_BUS */
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
        } else {
                chip->sd_io = 0;
-               RTSX_WRITE_REG(chip, SDIO_CTRL, SDIO_BUS_CTRL | SDIO_CD_CTRL,
-                              0);
+               retval = rtsx_write_register(chip, SDIO_CTRL,
+                                            SDIO_BUS_CTRL | SDIO_CD_CTRL, 0);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        }
 
 nextcard:
@@ -450,43 +647,91 @@ nextcard:
                chip->need_reset |= XD_CARD;
        if (chip->int_reg & MS_EXIST)
                chip->need_reset |= MS_CARD;
-       if (chip->int_reg & CARD_EXIST)
-               RTSX_WRITE_REG(chip, SSC_CTL1, SSC_RSTB, SSC_RSTB);
+       if (chip->int_reg & CARD_EXIST) {
+               retval = rtsx_write_register(chip, SSC_CTL1, SSC_RSTB,
+                                            SSC_RSTB);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+       }
 
        dev_dbg(rtsx_dev(chip), "In %s, chip->need_reset = 0x%x\n", __func__,
                (unsigned int)(chip->need_reset));
 
-       RTSX_WRITE_REG(chip, RCCTL, 0x01, 0x00);
+       retval = rtsx_write_register(chip, RCCTL, 0x01, 0x00);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) {
                /* Turn off main power when entering S3/S4 state */
-               RTSX_WRITE_REG(chip, MAIN_PWR_OFF_CTL, 0x03, 0x03);
+               retval = rtsx_write_register(chip, MAIN_PWR_OFF_CTL, 0x03,
+                                            0x03);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        }
 
        if (chip->remote_wakeup_en && !chip->auto_delink_en) {
-               RTSX_WRITE_REG(chip, WAKE_SEL_CTL, 0x07, 0x07);
-               if (chip->aux_pwr_exist)
-                       RTSX_WRITE_REG(chip, PME_FORCE_CTL, 0xFF, 0x33);
+               retval = rtsx_write_register(chip, WAKE_SEL_CTL, 0x07, 0x07);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               if (chip->aux_pwr_exist) {
+                       retval = rtsx_write_register(chip, PME_FORCE_CTL,
+                                                    0xFF, 0x33);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+               }
        } else {
-               RTSX_WRITE_REG(chip, WAKE_SEL_CTL, 0x07, 0x04);
-               RTSX_WRITE_REG(chip, PME_FORCE_CTL, 0xFF, 0x30);
+               retval = rtsx_write_register(chip, WAKE_SEL_CTL, 0x07, 0x04);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, PME_FORCE_CTL, 0xFF, 0x30);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        }
 
-       if (CHECK_PID(chip, 0x5208) && (chip->ic_version >= IC_VER_D))
-               RTSX_WRITE_REG(chip, PETXCFG, 0x1C, 0x14);
+       if (CHECK_PID(chip, 0x5208) && (chip->ic_version >= IC_VER_D)) {
+               retval = rtsx_write_register(chip, PETXCFG, 0x1C, 0x14);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+       }
 
        if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
                retval = rtsx_clr_phy_reg_bit(chip, 0x1C, 2);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        if (chip->ft2_fast_mode) {
-               RTSX_WRITE_REG(chip, CARD_PWR_CTL, 0xFF,
-                              MS_PARTIAL_POWER_ON | SD_PARTIAL_POWER_ON);
+               retval = rtsx_write_register(chip, CARD_PWR_CTL, 0xFF,
+                                            MS_PARTIAL_POWER_ON | SD_PARTIAL_POWER_ON);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                udelay(chip->pmos_pwr_on_interval);
-               RTSX_WRITE_REG(chip, CARD_PWR_CTL, 0xFF,
-                              MS_POWER_ON | SD_POWER_ON);
+               retval = rtsx_write_register(chip, CARD_PWR_CTL, 0xFF,
+                                            MS_POWER_ON | SD_POWER_ON);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
 
                wait_timeout(200);
        }
@@ -501,13 +746,14 @@ nextcard:
 
 static inline int check_sd_speed_prior(u32 sd_speed_prior)
 {
-       int i, fake_para = 0;
+       bool fake_para = false;
+       int i;
 
        for (i = 0; i < 4; i++) {
                u8 tmp = (u8)(sd_speed_prior >> (i*8));
 
                if ((tmp < 0x01) || (tmp > 0x04)) {
-                       fake_para = 1;
+                       fake_para = true;
                        break;
                }
        }
@@ -517,13 +763,14 @@ static inline int check_sd_speed_prior(u32 sd_speed_prior)
 
 static inline int check_sd_current_prior(u32 sd_current_prior)
 {
-       int i, fake_para = 0;
+       bool fake_para = false;
+       int i;
 
        for (i = 0; i < 4; i++) {
                u8 tmp = (u8)(sd_current_prior >> (i*8));
 
                if (tmp > 0x03) {
-                       fake_para = 1;
+                       fake_para = true;
                        break;
                }
        }
@@ -537,14 +784,24 @@ static int rts5208_init(struct rtsx_chip *chip)
        u16 reg = 0;
        u8 val = 0;
 
-       RTSX_WRITE_REG(chip, CLK_SEL, 0x03, 0x03);
-       RTSX_READ_REG(chip, CLK_SEL, &val);
+       retval = rtsx_write_register(chip, CLK_SEL, 0x03, 0x03);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_read_register(chip, CLK_SEL, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        chip->asic_code = val == 0 ? 1 : 0;
 
        if (chip->asic_code) {
                retval = rtsx_read_phy_register(chip, 0x1C, &reg);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                dev_dbg(rtsx_dev(chip), "Value of phy register 0x1C is 0x%x\n",
                        reg);
@@ -552,16 +809,28 @@ static int rts5208_init(struct rtsx_chip *chip)
                chip->phy_debug_mode = reg & PHY_DEBUG_MODE ? 1 : 0;
 
        } else {
-               RTSX_READ_REG(chip, 0xFE80, &val);
+               retval = rtsx_read_register(chip, 0xFE80, &val);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                chip->ic_version = val;
                chip->phy_debug_mode = 0;
        }
 
-       RTSX_READ_REG(chip, PDINFO, &val);
+       retval = rtsx_read_register(chip, PDINFO, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        dev_dbg(rtsx_dev(chip), "PDINFO: 0x%x\n", val);
        chip->aux_pwr_exist = val & AUX_PWR_DETECTED ? 1 : 0;
 
-       RTSX_READ_REG(chip, 0xFE50, &val);
+       retval = rtsx_read_register(chip, 0xFE50, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        chip->hw_bypass_sd = val & 0x01 ? 1 : 0;
 
        rtsx_read_config_byte(chip, 0x0E, &val);
@@ -571,7 +840,11 @@ static int rts5208_init(struct rtsx_chip *chip)
                CLR_SDIO_EXIST(chip);
 
        if (chip->use_hw_setting) {
-               RTSX_READ_REG(chip, CHANGE_LINK_STATE, &val);
+               retval = rtsx_read_register(chip, CHANGE_LINK_STATE, &val);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                chip->auto_delink_en = val & 0x80 ? 1 : 0;
        }
 
@@ -584,27 +857,49 @@ static int rts5288_init(struct rtsx_chip *chip)
        u8 val = 0, max_func;
        u32 lval = 0;
 
-       RTSX_WRITE_REG(chip, CLK_SEL, 0x03, 0x03);
-       RTSX_READ_REG(chip, CLK_SEL, &val);
+       retval = rtsx_write_register(chip, CLK_SEL, 0x03, 0x03);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_read_register(chip, CLK_SEL, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        chip->asic_code = val == 0 ? 1 : 0;
 
        chip->ic_version = 0;
        chip->phy_debug_mode = 0;
 
-       RTSX_READ_REG(chip, PDINFO, &val);
+       retval = rtsx_read_register(chip, PDINFO, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        dev_dbg(rtsx_dev(chip), "PDINFO: 0x%x\n", val);
        chip->aux_pwr_exist = val & AUX_PWR_DETECTED ? 1 : 0;
 
-       RTSX_READ_REG(chip, CARD_SHARE_MODE, &val);
+       retval = rtsx_read_register(chip, CARD_SHARE_MODE, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        dev_dbg(rtsx_dev(chip), "CARD_SHARE_MODE: 0x%x\n", val);
        chip->baro_pkg = val & 0x04 ? QFN : LQFP;
 
-       RTSX_READ_REG(chip, 0xFE5A, &val);
+       retval = rtsx_read_register(chip, 0xFE5A, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        chip->hw_bypass_sd = val & 0x10 ? 1 : 0;
 
        retval = rtsx_read_cfg_dw(chip, 0, 0x718, &lval);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        max_func = (u8)((lval >> 29) & 0x07);
        dev_dbg(rtsx_dev(chip), "Max function number: %d\n", max_func);
@@ -614,7 +909,11 @@ static int rts5288_init(struct rtsx_chip *chip)
                CLR_SDIO_EXIST(chip);
 
        if (chip->use_hw_setting) {
-               RTSX_READ_REG(chip, CHANGE_LINK_STATE, &val);
+               retval = rtsx_read_register(chip, CHANGE_LINK_STATE, &val);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                chip->auto_delink_en = val & 0x80 ? 1 : 0;
 
                if (CHECK_BARO_PKG(chip, LQFP))
@@ -693,21 +992,33 @@ int rtsx_init_chip(struct rtsx_chip *chip)
        if ((chip->mmc_ddr_tx_phase > 31) || (chip->mmc_ddr_tx_phase < 0))
                chip->mmc_ddr_tx_phase = 0;
 
-       RTSX_WRITE_REG(chip, FPDCTL, SSC_POWER_DOWN, 0);
+       retval = rtsx_write_register(chip, FPDCTL, SSC_POWER_DOWN, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        wait_timeout(200);
-       RTSX_WRITE_REG(chip, CLK_DIV, 0x07, 0x07);
+       retval = rtsx_write_register(chip, CLK_DIV, 0x07, 0x07);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        dev_dbg(rtsx_dev(chip), "chip->use_hw_setting = %d\n",
                chip->use_hw_setting);
 
        if (CHECK_PID(chip, 0x5208)) {
                retval = rts5208_init(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
        } else if (CHECK_PID(chip, 0x5288)) {
                retval = rts5288_init(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        if (chip->ss_en == 2)
@@ -754,8 +1065,10 @@ int rtsx_init_chip(struct rtsx_chip *chip)
        }
 
        retval = rtsx_reset_chip(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -784,31 +1097,31 @@ static inline void rtsx_blink_led(struct rtsx_chip *chip)
 
 static void rtsx_monitor_aspm_config(struct rtsx_chip *chip)
 {
-       int maybe_support_aspm, reg_changed;
+       bool reg_changed, maybe_support_aspm;
        u32 tmp = 0;
        u8 reg0 = 0, reg1 = 0;
 
-       maybe_support_aspm = 0;
-       reg_changed = 0;
+       maybe_support_aspm = false;
+       reg_changed = false;
        rtsx_read_config_byte(chip, LCTLR, &reg0);
        if (chip->aspm_level[0] != reg0) {
-               reg_changed = 1;
+               reg_changed = true;
                chip->aspm_level[0] = reg0;
        }
        if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
                rtsx_read_cfg_dw(chip, 1, 0xC0, &tmp);
                reg1 = (u8)tmp;
                if (chip->aspm_level[1] != reg1) {
-                       reg_changed = 1;
+                       reg_changed = true;
                        chip->aspm_level[1] = reg1;
                }
 
                if ((reg0 & 0x03) && (reg1 & 0x03))
-                       maybe_support_aspm = 1;
+                       maybe_support_aspm = true;
 
        } else {
                if (reg0 & 0x03)
-                       maybe_support_aspm = 1;
+                       maybe_support_aspm = true;
        }
 
        if (reg_changed) {
@@ -835,7 +1148,7 @@ void rtsx_polling_func(struct rtsx_chip *chip)
 #ifdef SUPPORT_SD_LOCK
        struct sd_info *sd_card = &chip->sd_card;
 #endif
-       int ss_allowed;
+       bool ss_allowed;
 
        if (rtsx_chk_stat(chip, RTSX_STAT_SUSPEND))
                return;
@@ -887,21 +1200,21 @@ void rtsx_polling_func(struct rtsx_chip *chip)
        rtsx_init_cards(chip);
 
        if (chip->ss_en) {
-               ss_allowed = 1;
+               ss_allowed = true;
 
                if (CHECK_PID(chip, 0x5288)) {
-                       ss_allowed = 0;
+                       ss_allowed = false;
                } else {
                        if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
                                u32 val;
 
                                rtsx_read_cfg_dw(chip, 1, 0x04, &val);
                                if (val & 0x07)
-                                       ss_allowed = 0;
+                                       ss_allowed = false;
                        }
                }
        } else {
-               ss_allowed = 0;
+               ss_allowed = false;
        }
 
        if (ss_allowed && !chip->sd_io) {
@@ -1153,14 +1466,17 @@ int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data)
        for (i = 0; i < MAX_RW_REG_CNT; i++) {
                val = rtsx_readl(chip, RTSX_HAIMR);
                if ((val & (1 << 31)) == 0) {
-                       if (data != (u8)val)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (data != (u8)val) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        return STATUS_SUCCESS;
                }
        }
 
-       TRACE_RET(chip, STATUS_TIMEDOUT);
+       rtsx_trace(chip);
+       return STATUS_TIMEDOUT;
 }
 
 int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data)
@@ -1181,8 +1497,10 @@ int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data)
                        break;
        }
 
-       if (i >= MAX_RW_REG_CNT)
-               TRACE_RET(chip, STATUS_TIMEDOUT);
+       if (i >= MAX_RW_REG_CNT) {
+               rtsx_trace(chip);
+               return STATUS_TIMEDOUT;
+       }
 
        if (data)
                *data = (u8)(val & 0xFF);
@@ -1193,13 +1511,19 @@ int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data)
 int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask,
                      u32 val)
 {
+       int retval;
        u8 mode = 0, tmp;
        int i;
 
        for (i = 0; i < 4; i++) {
                if (mask & 0xFF) {
-                       RTSX_WRITE_REG(chip, CFGDATA0 + i,
-                                      0xFF, (u8)(val & mask & 0xFF));
+                       retval = rtsx_write_register(chip, CFGDATA0 + i,
+                                                    0xFF,
+                                                    (u8)(val & mask & 0xFF));
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                        mode |= (1 << i);
                }
                mask >>= 8;
@@ -1207,14 +1531,31 @@ int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask,
        }
 
        if (mode) {
-               RTSX_WRITE_REG(chip, CFGADDR0, 0xFF, (u8)addr);
-               RTSX_WRITE_REG(chip, CFGADDR1, 0xFF, (u8)(addr >> 8));
+               retval = rtsx_write_register(chip, CFGADDR0, 0xFF, (u8)addr);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CFGADDR1, 0xFF,
+                                            (u8)(addr >> 8));
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
 
-               RTSX_WRITE_REG(chip, CFGRWCTL, 0xFF,
-                              0x80 | mode | ((func_no & 0x03) << 4));
+               retval = rtsx_write_register(chip, CFGRWCTL, 0xFF,
+                                            0x80 | mode | ((func_no & 0x03) << 4));
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
 
                for (i = 0; i < MAX_RW_REG_CNT; i++) {
-                       RTSX_READ_REG(chip, CFGRWCTL, &tmp);
+                       retval = rtsx_read_register(chip, CFGRWCTL, &tmp);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                        if ((tmp & 0x80) == 0)
                                break;
                }
@@ -1225,22 +1566,44 @@ int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask,
 
 int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val)
 {
+       int retval;
        int i;
        u8 tmp;
        u32 data = 0;
 
-       RTSX_WRITE_REG(chip, CFGADDR0, 0xFF, (u8)addr);
-       RTSX_WRITE_REG(chip, CFGADDR1, 0xFF, (u8)(addr >> 8));
-       RTSX_WRITE_REG(chip, CFGRWCTL, 0xFF, 0x80 | ((func_no & 0x03) << 4));
+       retval = rtsx_write_register(chip, CFGADDR0, 0xFF, (u8)addr);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, CFGADDR1, 0xFF, (u8)(addr >> 8));
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, CFGRWCTL, 0xFF,
+                                    0x80 | ((func_no & 0x03) << 4));
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        for (i = 0; i < MAX_RW_REG_CNT; i++) {
-               RTSX_READ_REG(chip, CFGRWCTL, &tmp);
+               retval = rtsx_read_register(chip, CFGRWCTL, &tmp);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                if ((tmp & 0x80) == 0)
                        break;
        }
 
        for (i = 0; i < 4; i++) {
-               RTSX_READ_REG(chip, CFGDATA0 + i, &tmp);
+               retval = rtsx_read_register(chip, CFGDATA0 + i, &tmp);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                data |= (u32)tmp << (i * 8);
        }
 
@@ -1259,8 +1622,10 @@ int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
        int dw_len, i, j;
        int retval;
 
-       if (!buf)
-               TRACE_RET(chip, STATUS_NOMEM);
+       if (!buf) {
+               rtsx_trace(chip);
+               return STATUS_NOMEM;
+       }
 
        if ((len + offset) % 4)
                dw_len = (len + offset) / 4 + 1;
@@ -1270,13 +1635,16 @@ int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
        dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len);
 
        data = vzalloc(dw_len * 4);
-       if (!data)
-               TRACE_RET(chip, STATUS_NOMEM);
+       if (!data) {
+               rtsx_trace(chip);
+               return STATUS_NOMEM;
+       }
 
        mask = vzalloc(dw_len * 4);
        if (!mask) {
                vfree(data);
-               TRACE_RET(chip, STATUS_NOMEM);
+               rtsx_trace(chip);
+               return STATUS_NOMEM;
        }
 
        j = 0;
@@ -1300,7 +1668,8 @@ int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
                if (retval != STATUS_SUCCESS) {
                        vfree(data);
                        vfree(mask);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
@@ -1327,15 +1696,18 @@ int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
        dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len);
 
        data = vmalloc(dw_len * 4);
-       if (!data)
-               TRACE_RET(chip, STATUS_NOMEM);
+       if (!data) {
+               rtsx_trace(chip);
+               return STATUS_NOMEM;
+       }
 
        for (i = 0; i < dw_len; i++) {
                retval = rtsx_read_cfg_dw(chip, func, aligned_addr + i * 4,
                                          data + i);
                if (retval != STATUS_SUCCESS) {
                        vfree(data);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
@@ -1358,51 +1730,99 @@ int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
 
 int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val)
 {
-       int i, finished = 0;
+       int retval;
+       bool finished = false;
+       int i;
        u8 tmp;
 
-       RTSX_WRITE_REG(chip, PHYDATA0, 0xFF, (u8)val);
-       RTSX_WRITE_REG(chip, PHYDATA1, 0xFF, (u8)(val >> 8));
-       RTSX_WRITE_REG(chip, PHYADDR, 0xFF, addr);
-       RTSX_WRITE_REG(chip, PHYRWCTL, 0xFF, 0x81);
+       retval = rtsx_write_register(chip, PHYDATA0, 0xFF, (u8)val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, PHYDATA1, 0xFF, (u8)(val >> 8));
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, PHYADDR, 0xFF, addr);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, PHYRWCTL, 0xFF, 0x81);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        for (i = 0; i < 100000; i++) {
-               RTSX_READ_REG(chip, PHYRWCTL, &tmp);
+               retval = rtsx_read_register(chip, PHYRWCTL, &tmp);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                if (!(tmp & 0x80)) {
-                       finished = 1;
+                       finished = true;
                        break;
                }
        }
 
-       if (!finished)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (!finished) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
 
 int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val)
 {
-       int i, finished = 0;
+       int retval;
+       bool finished = false;
+       int i;
        u16 data = 0;
        u8 tmp;
 
-       RTSX_WRITE_REG(chip, PHYADDR, 0xFF, addr);
-       RTSX_WRITE_REG(chip, PHYRWCTL, 0xFF, 0x80);
+       retval = rtsx_write_register(chip, PHYADDR, 0xFF, addr);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, PHYRWCTL, 0xFF, 0x80);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        for (i = 0; i < 100000; i++) {
-               RTSX_READ_REG(chip, PHYRWCTL, &tmp);
+               retval = rtsx_read_register(chip, PHYRWCTL, &tmp);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                if (!(tmp & 0x80)) {
-                       finished = 1;
+                       finished = true;
                        break;
                }
        }
 
-       if (!finished)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (!finished) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_READ_REG(chip, PHYDATA0, &tmp);
+       retval = rtsx_read_register(chip, PHYDATA0, &tmp);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        data = tmp;
-       RTSX_READ_REG(chip, PHYDATA1, &tmp);
+       retval = rtsx_read_register(chip, PHYDATA1, &tmp);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        data |= (u16)tmp << 8;
 
        if (val)
@@ -1413,22 +1833,37 @@ int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val)
 
 int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val)
 {
+       int retval;
        int i;
        u8 data = 0;
 
-       RTSX_WRITE_REG(chip, EFUSE_CTRL, 0xFF, 0x80|addr);
+       retval = rtsx_write_register(chip, EFUSE_CTRL, 0xFF, 0x80 | addr);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        for (i = 0; i < 100; i++) {
-               RTSX_READ_REG(chip, EFUSE_CTRL, &data);
+               retval = rtsx_read_register(chip, EFUSE_CTRL, &data);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                if (!(data & 0x80))
                        break;
                udelay(1);
        }
 
-       if (data & 0x80)
-               TRACE_RET(chip, STATUS_TIMEDOUT);
+       if (data & 0x80) {
+               rtsx_trace(chip);
+               return STATUS_TIMEDOUT;
+       }
 
-       RTSX_READ_REG(chip, EFUSE_DATA, &data);
+       retval = rtsx_read_register(chip, EFUSE_DATA, &data);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        if (val)
                *val = data;
 
@@ -1437,6 +1872,7 @@ int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val)
 
 int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val)
 {
+       int retval;
        int i, j;
        u8 data = 0, tmp = 0xFF;
 
@@ -1447,18 +1883,33 @@ int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val)
                tmp &= (~(u8)(1 << i));
                dev_dbg(rtsx_dev(chip), "Write 0x%x to 0x%x\n", tmp, addr);
 
-               RTSX_WRITE_REG(chip, EFUSE_DATA, 0xFF, tmp);
-               RTSX_WRITE_REG(chip, EFUSE_CTRL, 0xFF, 0xA0|addr);
+               retval = rtsx_write_register(chip, EFUSE_DATA, 0xFF, tmp);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, EFUSE_CTRL, 0xFF,
+                                            0xA0 | addr);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
 
                for (j = 0; j < 100; j++) {
-                       RTSX_READ_REG(chip, EFUSE_CTRL, &data);
+                       retval = rtsx_read_register(chip, EFUSE_CTRL, &data);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                        if (!(data & 0x80))
                                break;
                        wait_timeout(3);
                }
 
-               if (data & 0x80)
-                       TRACE_RET(chip, STATUS_TIMEDOUT);
+               if (data & 0x80) {
+                       rtsx_trace(chip);
+                       return STATUS_TIMEDOUT;
+               }
 
                wait_timeout(5);
        }
@@ -1472,14 +1923,18 @@ int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
        u16 value;
 
        retval = rtsx_read_phy_register(chip, reg, &value);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (value & (1 << bit)) {
                value &= ~(1 << bit);
                retval = rtsx_write_phy_register(chip, reg, value);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -1491,14 +1946,18 @@ int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
        u16 value;
 
        retval = rtsx_read_phy_register(chip, reg, &value);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if ((value & (1 << bit)) == 0) {
                value |= (1 << bit);
                retval = rtsx_write_phy_register(chip, reg, value);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -1506,9 +1965,14 @@ int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
 
 int rtsx_check_link_ready(struct rtsx_chip *chip)
 {
+       int retval;
        u8 val;
 
-       RTSX_READ_REG(chip, IRQSTAT0, &val);
+       retval = rtsx_read_register(chip, IRQSTAT0, &val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        dev_dbg(rtsx_dev(chip), "IRQSTAT0: 0x%x\n", val);
        if (val & LINK_RDY_INT) {
@@ -1615,7 +2079,7 @@ void rtsx_exit_ss(struct rtsx_chip *chip)
 int rtsx_pre_handle_interrupt(struct rtsx_chip *chip)
 {
        u32 status, int_enable;
-       int exit_ss = 0;
+       bool exit_ss = false;
 #ifdef SUPPORT_OCP
        u32 ocp_int = 0;
 
@@ -1625,7 +2089,7 @@ int rtsx_pre_handle_interrupt(struct rtsx_chip *chip)
        if (chip->ss_en) {
                chip->ss_counter = 0;
                if (rtsx_get_stat(chip) == RTSX_STAT_SS) {
-                       exit_ss = 1;
+                       exit_ss = true;
                        rtsx_exit_L1(chip);
                        rtsx_set_stat(chip, RTSX_STAT_RUN);
                }
@@ -1814,8 +2278,10 @@ int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
        u16 reg_addr;
        u8 *ptr;
 
-       if (!buf)
-               TRACE_RET(chip, STATUS_ERROR);
+       if (!buf) {
+               rtsx_trace(chip);
+               return STATUS_ERROR;
+       }
 
        ptr = buf;
        reg_addr = PPBUF_BASE2;
@@ -1826,8 +2292,10 @@ int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
                        rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
 
                retval = rtsx_send_cmd(chip, 0, 250);
-               if (retval < 0)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval < 0) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                memcpy(ptr, rtsx_get_cmd_data(chip), 256);
                ptr += 256;
@@ -1840,8 +2308,10 @@ int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
                        rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
 
                retval = rtsx_send_cmd(chip, 0, 250);
-               if (retval < 0)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval < 0) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        memcpy(ptr, rtsx_get_cmd_data(chip), buf_len%256);
@@ -1856,8 +2326,10 @@ int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
        u16 reg_addr;
        u8 *ptr;
 
-       if (!buf)
-               TRACE_RET(chip, STATUS_ERROR);
+       if (!buf) {
+               rtsx_trace(chip);
+               return STATUS_ERROR;
+       }
 
        ptr = buf;
        reg_addr = PPBUF_BASE2;
@@ -1871,8 +2343,10 @@ int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
                }
 
                retval = rtsx_send_cmd(chip, 0, 250);
-               if (retval < 0)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval < 0) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        if (buf_len%256) {
@@ -1885,8 +2359,10 @@ int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
                }
 
                retval = rtsx_send_cmd(chip, 0, 250);
-               if (retval < 0)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval < 0) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -1894,8 +2370,10 @@ int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
 
 int rtsx_check_chip_exist(struct rtsx_chip *chip)
 {
-       if (rtsx_readl(chip, 0) == 0xFFFFFFFF)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (rtsx_readl(chip, 0) == 0xFFFFFFFF) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -1918,8 +2396,10 @@ int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl)
 
        if (mask) {
                retval = rtsx_write_register(chip, FPDCTL, mask, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                if (CHECK_PID(chip, 0x5288))
                        wait_timeout(200);
@@ -1947,8 +2427,10 @@ int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl)
        if (mask) {
                val = mask;
                retval = rtsx_write_register(chip, FPDCTL, mask, val);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
index feac98661cec0ea2f064273641135e5f792af9e8..c295b1eedb44ec7e67896fe965ce7ee02f22a948 100644 (file)
@@ -988,20 +988,4 @@ int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len);
 int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len);
 int rtsx_check_chip_exist(struct rtsx_chip *chip);
 
-#define RTSX_WRITE_REG(chip, addr, mask, data)                         \
-       do {                                                            \
-               int retval = rtsx_write_register((chip), (addr), (mask), (data)); \
-               if (retval != STATUS_SUCCESS) {                         \
-                       TRACE_RET((chip), retval);                      \
-               }                                                       \
-       } while (0)
-
-#define RTSX_READ_REG(chip, addr, data)                                        \
-       do {                                                            \
-               int retval = rtsx_read_register((chip), (addr), (data)); \
-               if (retval != STATUS_SUCCESS) {                         \
-                       TRACE_RET((chip), retval);                      \
-               }                                                       \
-       } while (0)
-
 #endif  /* __REALTEK_RTSX_CHIP_H */
index 11610826acf19111934a5fc0252f8a371c5810d9..8a5d6a8e780f3a63658083f19f3adb494ec574aa 100644 (file)
 #include <linux/vmalloc.h>
 
 #include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_sys.h"
-#include "rtsx_card.h"
-#include "rtsx_chip.h"
-#include "rtsx_scsi.h"
 #include "sd.h"
 #include "ms.h"
 #include "spi.h"
@@ -39,7 +34,8 @@ void scsi_show_command(struct rtsx_chip *chip)
 {
        struct scsi_cmnd *srb = chip->srb;
        char *what = NULL;
-       int unknown_cmd = 0, len;
+       bool unknown_cmd = false;
+       int len;
 
        switch (srb->cmnd[0]) {
        case TEST_UNIT_READY:
@@ -310,7 +306,8 @@ void scsi_show_command(struct rtsx_chip *chip)
                what = "Realtek's vendor command";
                break;
        default:
-               what = "(unknown command)"; unknown_cmd = 1;
+               what = "(unknown command)";
+               unknown_cmd = true;
                break;
        }
 
@@ -485,7 +482,7 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        unsigned char sendbytes;
        unsigned char *buf;
        u8 card = get_lun_card(chip, lun);
-       int pro_formatter_flag = 0;
+       bool pro_formatter_flag = false;
        unsigned char inquiry_buf[] = {
                QULIFIRE|DRCT_ACCESS_DEV,
                RMB_DISC|0x0D,
@@ -510,8 +507,10 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        }
 
        buf = vmalloc(scsi_bufflen(srb));
-       if (buf == NULL)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (buf == NULL) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
 #ifdef SUPPORT_MAGIC_GATE
        if ((chip->mspro_formatter_enable) &&
@@ -519,10 +518,8 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 #else
        if (chip->mspro_formatter_enable)
 #endif
-       {
                if (!card || (card == MS_CARD))
-                       pro_formatter_flag = 1;
-       }
+                       pro_formatter_flag = true;
 
        if (pro_formatter_flag) {
                if (scsi_bufflen(srb) < 56)
@@ -587,12 +584,14 @@ static int start_stop_unit(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                if (check_card_ready(chip, lun))
                        return TRANSPORT_GOOD;
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
 
                break;
        }
 
-       TRACE_RET(chip, TRANSPORT_ERROR);
+       rtsx_trace(chip);
+       return TRANSPORT_ERROR;
 }
 
 
@@ -607,7 +606,8 @@ static int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (prevent) {
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        return TRANSPORT_GOOD;
@@ -644,8 +644,10 @@ static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        }
 
        buf = vmalloc(scsi_bufflen(srb));
-       if (buf == NULL)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (buf == NULL) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        tmp = (unsigned char *)sense;
        memcpy(buf, tmp, scsi_bufflen(srb));
@@ -665,7 +667,7 @@ static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd,
        struct ms_info *ms_card = &(chip->ms_card);
        int sys_info_offset;
        int data_size = buf_len;
-       int support_format = 0;
+       bool support_format = false;
        int i = 0;
 
        if (cmd == MODE_SENSE) {
@@ -686,10 +688,10 @@ static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd,
        /* Medium Type Code */
        if (check_card_ready(chip, lun)) {
                if (CHK_MSXC(ms_card)) {
-                       support_format = 1;
+                       support_format = true;
                        buf[i++] = 0x40;
                } else if (CHK_MSPRO(ms_card)) {
-                       support_format = 1;
+                       support_format = true;
                        buf[i++] = 0x20;
                } else {
                        buf[i++] = 0x10;
@@ -757,7 +759,7 @@ static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        unsigned int lun = SCSI_LUN(srb);
        unsigned int dataSize;
        int status;
-       int pro_formatter_flag;
+       bool pro_formatter_flag;
        unsigned char pageCode, *buf;
        u8 card = get_lun_card(chip, lun);
 
@@ -765,32 +767,35 @@ static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (!check_card_ready(chip, lun)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                scsi_set_resid(srb, scsi_bufflen(srb));
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 #endif
 
-       pro_formatter_flag = 0;
+       pro_formatter_flag = false;
        dataSize = 8;
 #ifdef SUPPORT_MAGIC_GATE
        if ((chip->lun2card[lun] & MS_CARD)) {
                if (!card || (card == MS_CARD)) {
                        dataSize = 108;
                        if (chip->mspro_formatter_enable)
-                               pro_formatter_flag = 1;
+                               pro_formatter_flag = true;
                }
        }
 #else
        if (card == MS_CARD) {
                if (chip->mspro_formatter_enable) {
-                       pro_formatter_flag = 1;
+                       pro_formatter_flag = true;
                        dataSize = 108;
                }
        }
 #endif
 
        buf = kmalloc(dataSize, GFP_KERNEL);
-       if (buf == NULL)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (buf == NULL) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        pageCode = srb->cmnd[2] & 0x3f;
 
@@ -869,7 +874,8 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (!check_card_ready(chip, lun) || (get_card_size(chip, lun) == 0)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (!(CHK_BIT(chip->lun_mc, lun))) {
@@ -885,7 +891,8 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                 */
                dev_dbg(rtsx_dev(chip), "SD card being erased!\n");
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (get_lun_card(chip, lun) == SD_CARD) {
@@ -893,7 +900,8 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        dev_dbg(rtsx_dev(chip), "SD card locked!\n");
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_READ_FORBIDDEN);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        }
 #endif
@@ -916,7 +924,8 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                sec_cnt = ((u16)(srb->cmnd[9]) << 8) | srb->cmnd[10];
        } else {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        /* In some test, we will receive a start_sec like 0xFFFFFFFF.
@@ -926,7 +935,8 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if ((start_sec > get_card_size(chip, lun)) ||
                        ((start_sec + sec_cnt) > get_card_size(chip, lun))) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (sec_cnt == 0) {
@@ -942,7 +952,8 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                else
                        set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
 
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (srb->sc_data_direction == DMA_TO_DEVICE) {
@@ -950,7 +961,8 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        dev_dbg(rtsx_dev(chip), "Write protected card!\n");
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_WRITE_PROTECT);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        }
 
@@ -969,7 +981,8 @@ static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
                }
                retval = TRANSPORT_FAILED;
-               TRACE_GOTO(chip, Exit);
+               rtsx_trace(chip);
+               goto Exit;
        } else {
                chip->rw_fail_cnt[lun] = 0;
                retval = TRANSPORT_GOOD;
@@ -994,15 +1007,18 @@ static int read_format_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (!check_card_ready(chip, lun)) {
                if (!chip->mspro_formatter_enable) {
                        set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        }
 
        buf_len = (scsi_bufflen(srb) > 12) ? 0x14 : 12;
 
        buf = kmalloc(buf_len, GFP_KERNEL);
-       if (buf == NULL)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (buf == NULL) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        buf[i++] = 0;
        buf[i++] = 0;
@@ -1067,7 +1083,8 @@ static int read_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (!check_card_ready(chip, lun)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (!(CHK_BIT(chip->lun_mc, lun))) {
@@ -1077,8 +1094,10 @@ static int read_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        }
 
        buf = kmalloc(8, GFP_KERNEL);
-       if (buf == NULL)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (buf == NULL) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        card_size = get_card_size(chip, lun);
        buf[0] = (unsigned char)((card_size - 1) >> 24);
@@ -1116,15 +1135,18 @@ static int read_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
 
        buf = vmalloc(len);
-       if (!buf)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (!buf) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        retval = rtsx_force_power_on(chip, SSC_PDCTL);
        if (retval != STATUS_SUCCESS) {
                vfree(buf);
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        for (i = 0; i < len; i++) {
@@ -1133,7 +1155,8 @@ static int read_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        vfree(buf);
                        set_sense_type(chip, SCSI_LUN(srb),
                                SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        }
 
@@ -1165,7 +1188,8 @@ static int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = rtsx_force_power_on(chip, SSC_PDCTL);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (len == 511) {
@@ -1173,14 +1197,17 @@ static int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                if (retval != STATUS_SUCCESS) {
                        set_sense_type(chip, SCSI_LUN(srb),
                                SENSE_TYPE_MEDIA_WRITE_ERR);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        } else {
                len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb),
                                        len);
                buf = vmalloc(len);
-               if (buf == NULL)
-                       TRACE_RET(chip, TRANSPORT_ERROR);
+               if (buf == NULL) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_ERROR;
+               }
 
                rtsx_stor_get_xfer_buf(buf, len, srb);
                scsi_set_resid(srb, scsi_bufflen(srb) - len);
@@ -1191,7 +1218,8 @@ static int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                vfree(buf);
                                set_sense_type(chip, SCSI_LUN(srb),
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
                        }
                }
 
@@ -1221,18 +1249,22 @@ static int read_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (addr < 0xFC00) {
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        buf = vmalloc(len);
-       if (!buf)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (!buf) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        retval = rtsx_force_power_on(chip, SSC_PDCTL);
        if (retval != STATUS_SUCCESS) {
                vfree(buf);
                set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        for (i = 0; i < len; i++) {
@@ -1241,7 +1273,8 @@ static int read_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        vfree(buf);
                        set_sense_type(chip, SCSI_LUN(srb),
                                SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        }
 
@@ -1274,13 +1307,16 @@ static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (addr < 0xFC00) {
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
        buf = vmalloc(len);
-       if (buf == NULL)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (buf == NULL) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        rtsx_stor_get_xfer_buf(buf, len, srb);
        scsi_set_resid(srb, scsi_bufflen(srb) - len);
@@ -1289,7 +1325,8 @@ static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (retval != STATUS_SUCCESS) {
                vfree(buf);
                set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        for (i = 0; i < len; i++) {
@@ -1298,7 +1335,8 @@ static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        vfree(buf);
                        set_sense_type(chip, SCSI_LUN(srb),
                                SENSE_TYPE_MEDIA_WRITE_ERR);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        }
 
@@ -1314,12 +1352,14 @@ static int get_sd_csd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (!check_card_ready(chip, lun)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (get_lun_card(chip, lun) != SD_CARD) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        scsi_set_resid(srb, 0);
@@ -1361,14 +1401,17 @@ static int trace_msg_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if ((scsi_bufflen(srb) < buf_len) || (scsi_sglist(srb) == NULL)) {
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        clear = srb->cmnd[2];
 
        buf = vmalloc(scsi_bufflen(srb));
-       if (buf == NULL)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (buf == NULL) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
        ptr = buf;
 
        if (chip->trace_msg[chip->msg_idx].valid)
@@ -1500,7 +1543,8 @@ static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                default:
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        } else if (srb->cmnd[3] == 2) {
                if (srb->cmnd[4]) {
@@ -1523,14 +1567,16 @@ static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        if (retval != STATUS_SUCCESS) {
                                set_sense_type(chip, SCSI_LUN(srb),
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
                        }
 
                        turn_off_led(chip, LED_GPIO);
                }
        } else {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        return TRANSPORT_GOOD;
@@ -1562,7 +1608,8 @@ static int get_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                default:
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
 
                rtsx_stor_set_xfer_buf(&tmp, 1, srb);
@@ -1572,7 +1619,8 @@ static int get_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                rtsx_stor_set_xfer_buf(&tmp, 1, srb);
        } else {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        return TRANSPORT_GOOD;
@@ -1610,7 +1658,8 @@ static int dma_access_ring_buffer(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_WRITE_ERR);
 
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
        scsi_set_resid(srb, 0);
 
@@ -1757,7 +1806,8 @@ static int set_chip_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (!CHECK_PID(chip, 0x5208)) {
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        phy_debug_mode = (int)(srb->cmnd[3]);
@@ -1765,35 +1815,47 @@ static int set_chip_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (phy_debug_mode) {
                chip->phy_debug_mode = 1;
                retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
+               }
 
                rtsx_disable_bus_int(chip);
 
                retval = rtsx_read_phy_register(chip, 0x1C, &reg);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
+               }
 
                reg |= 0x0001;
                retval = rtsx_write_phy_register(chip, 0x1C, reg);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
+               }
        } else {
                chip->phy_debug_mode = 0;
                retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0x77);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
+               }
 
                rtsx_enable_bus_int(chip);
 
                retval = rtsx_read_phy_register(chip, 0x1C, &reg);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
+               }
 
                reg &= 0xFFFE;
                retval = rtsx_write_phy_register(chip, 0x1C, reg);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
+               }
        }
 
        return TRANSPORT_GOOD;
@@ -1824,7 +1886,8 @@ static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                if (cmd_type > 2) {
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
                addr = (srb->cmnd[5] << 8) | srb->cmnd[6];
                mask = srb->cmnd[7];
@@ -1842,7 +1905,8 @@ static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                if (scsi_bufflen(srb) < 1) {
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
                rtsx_stor_set_xfer_buf(&value, 1, srb);
                scsi_set_resid(srb, 0);
@@ -1850,12 +1914,14 @@ static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        default:
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        return TRANSPORT_GOOD;
@@ -1902,15 +1968,18 @@ static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (len) {
                buf = vmalloc(len);
-               if (!buf)
-                       TRACE_RET(chip, TRANSPORT_ERROR);
+               if (!buf) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_ERROR;
+               }
 
                retval = rtsx_force_power_on(chip, SSC_PDCTL);
                if (retval != STATUS_SUCCESS) {
                        vfree(buf);
                        set_sense_type(chip, SCSI_LUN(srb),
                                SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
 
                for (i = 0; i < len / 2; i++) {
@@ -1919,7 +1988,8 @@ static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                vfree(buf);
                                set_sense_type(chip, SCSI_LUN(srb),
                                        SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
                        }
 
                        buf[2*i] = (u8)(val >> 8);
@@ -1963,8 +2033,10 @@ static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                        len);
 
                buf = vmalloc(len);
-               if (buf == NULL)
-                       TRACE_RET(chip, TRANSPORT_ERROR);
+               if (buf == NULL) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_ERROR;
+               }
 
                rtsx_stor_get_xfer_buf(buf, len, srb);
                scsi_set_resid(srb, scsi_bufflen(srb) - len);
@@ -1974,7 +2046,8 @@ static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        vfree(buf);
                        set_sense_type(chip, SCSI_LUN(srb),
                                SENSE_TYPE_MEDIA_WRITE_ERR);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
 
                for (i = 0; i < len / 2; i++) {
@@ -1984,7 +2057,8 @@ static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                vfree(buf);
                                set_sense_type(chip, SCSI_LUN(srb),
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
                        }
                }
 
@@ -2011,7 +2085,8 @@ static int erase_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = rtsx_force_power_on(chip, SSC_PDCTL);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        mode = srb->cmnd[3];
@@ -2022,19 +2097,22 @@ static int erase_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                if (retval != STATUS_SUCCESS) {
                        set_sense_type(chip, SCSI_LUN(srb),
                                SENSE_TYPE_MEDIA_WRITE_ERR);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        } else if (mode == 1) {
                retval = spi_erase_eeprom_byte(chip, addr);
                if (retval != STATUS_SUCCESS) {
                        set_sense_type(chip, SCSI_LUN(srb),
                                SENSE_TYPE_MEDIA_WRITE_ERR);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        } else {
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        return TRANSPORT_GOOD;
@@ -2058,15 +2136,18 @@ static int read_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
 
        buf = vmalloc(len);
-       if (!buf)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (!buf) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        retval = rtsx_force_power_on(chip, SSC_PDCTL);
        if (retval != STATUS_SUCCESS) {
                vfree(buf);
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        for (i = 0; i < len; i++) {
@@ -2075,7 +2156,8 @@ static int read_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        vfree(buf);
                        set_sense_type(chip, SCSI_LUN(srb),
                                SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        }
 
@@ -2107,8 +2189,10 @@ static int write_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
        buf = vmalloc(len);
-       if (buf == NULL)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (buf == NULL) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        rtsx_stor_get_xfer_buf(buf, len, srb);
        scsi_set_resid(srb, scsi_bufflen(srb) - len);
@@ -2117,7 +2201,8 @@ static int write_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (retval != STATUS_SUCCESS) {
                vfree(buf);
                set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        for (i = 0; i < len; i++) {
@@ -2126,7 +2211,8 @@ static int write_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        vfree(buf);
                        set_sense_type(chip, SCSI_LUN(srb),
                                SENSE_TYPE_MEDIA_WRITE_ERR);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        }
 
@@ -2153,15 +2239,18 @@ static int read_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        len = srb->cmnd[5];
 
        buf = vmalloc(len);
-       if (!buf)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (!buf) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        retval = rtsx_force_power_on(chip, SSC_PDCTL);
        if (retval != STATUS_SUCCESS) {
                vfree(buf);
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        for (i = 0; i < len; i++) {
@@ -2170,7 +2259,8 @@ static int read_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        vfree(buf);
                        set_sense_type(chip, SCSI_LUN(srb),
                                SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        }
 
@@ -2203,8 +2293,10 @@ static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        len = (u8)min_t(unsigned int, scsi_bufflen(srb), len);
        buf = vmalloc(len);
-       if (buf == NULL)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (buf == NULL) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        rtsx_stor_get_xfer_buf(buf, len, srb);
        scsi_set_resid(srb, scsi_bufflen(srb) - len);
@@ -2212,21 +2304,24 @@ static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = rtsx_force_power_on(chip, SSC_PDCTL);
        if (retval != STATUS_SUCCESS) {
                vfree(buf);
-               TRACE_RET(chip, TRANSPORT_ERROR);
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
        }
 
        if (chip->asic_code) {
                retval = rtsx_read_phy_register(chip, 0x08, &val);
                if (retval != STATUS_SUCCESS) {
                        vfree(buf);
-                       TRACE_RET(chip, TRANSPORT_ERROR);
+                       rtsx_trace(chip);
+                       return TRANSPORT_ERROR;
                }
 
                retval = rtsx_write_register(chip, PWR_GATE_CTRL,
                                        LDO3318_PWR_MASK, LDO_OFF);
                if (retval != STATUS_SUCCESS) {
                        vfree(buf);
-                       TRACE_RET(chip, TRANSPORT_ERROR);
+                       rtsx_trace(chip);
+                       return TRANSPORT_ERROR;
                }
 
                wait_timeout(600);
@@ -2235,14 +2330,16 @@ static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                                0x4C00 | chip->phy_voltage);
                if (retval != STATUS_SUCCESS) {
                        vfree(buf);
-                       TRACE_RET(chip, TRANSPORT_ERROR);
+                       rtsx_trace(chip);
+                       return TRANSPORT_ERROR;
                }
 
                retval = rtsx_write_register(chip, PWR_GATE_CTRL,
                                        LDO3318_PWR_MASK, LDO_ON);
                if (retval != STATUS_SUCCESS) {
                        vfree(buf);
-                       TRACE_RET(chip, TRANSPORT_ERROR);
+                       rtsx_trace(chip);
+                       return TRANSPORT_ERROR;
                }
 
                wait_timeout(600);
@@ -2251,7 +2348,8 @@ static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = card_power_on(chip, SPI_CARD);
        if (retval != STATUS_SUCCESS) {
                vfree(buf);
-               TRACE_RET(chip, TRANSPORT_ERROR);
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
        }
 
        wait_timeout(50);
@@ -2262,7 +2360,8 @@ static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        set_sense_type(chip, SCSI_LUN(srb),
                                SENSE_TYPE_MEDIA_WRITE_ERR);
                        result = TRANSPORT_FAILED;
-                       TRACE_GOTO(chip, Exit);
+                       rtsx_trace(chip);
+                       goto Exit;
                }
        }
 
@@ -2270,25 +2369,33 @@ Exit:
        vfree(buf);
 
        retval = card_power_off(chip, SPI_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        if (chip->asic_code) {
                retval = rtsx_write_register(chip, PWR_GATE_CTRL,
                                        LDO3318_PWR_MASK, LDO_OFF);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, TRANSPORT_ERROR);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_ERROR;
+               }
 
                wait_timeout(600);
 
                retval = rtsx_write_phy_register(chip, 0x08, val);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, TRANSPORT_ERROR);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_ERROR;
+               }
 
                retval = rtsx_write_register(chip, PWR_GATE_CTRL,
                                        LDO3318_PWR_MASK, LDO_ON);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, TRANSPORT_ERROR);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_ERROR;
+               }
        }
 
        return result;
@@ -2297,7 +2404,8 @@ Exit:
 static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 {
        int retval;
-       u8 func, func_max;
+       bool func_max;
+       u8 func;
        u16 addr, len;
        u8 *buf;
 
@@ -2317,26 +2425,30 @@ static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                __func__, func, addr, len);
 
        if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
-               func_max = 1;
+               func_max = true;
        else
-               func_max = 0;
+               func_max = false;
 
        if (func > func_max) {
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        buf = vmalloc(len);
-       if (!buf)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (!buf) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        retval = rtsx_read_cfg_seq(chip, func, addr, buf, len);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
                vfree(buf);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        len = (u16)min_t(unsigned int, scsi_bufflen(srb), len);
@@ -2351,7 +2463,8 @@ static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 static int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 {
        int retval;
-       u8 func, func_max;
+       bool func_max;
+       u8 func;
        u16 addr, len;
        u8 *buf;
 
@@ -2371,20 +2484,23 @@ static int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                __func__, func, addr);
 
        if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
-               func_max = 1;
+               func_max = true;
        else
-               func_max = 0;
+               func_max = false;
 
        if (func > func_max) {
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
        buf = vmalloc(len);
-       if (!buf)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (!buf) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        rtsx_stor_get_xfer_buf(buf, len, srb);
        scsi_set_resid(srb, scsi_bufflen(srb) - len);
@@ -2393,7 +2509,8 @@ static int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
                vfree(buf);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        vfree(buf);
@@ -2483,7 +2600,8 @@ static int app_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        default:
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        return result;
@@ -2626,7 +2744,8 @@ static int get_card_bus_width(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (!check_card_ready(chip, lun)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        card = get_lun_card(chip, lun);
@@ -2634,7 +2753,8 @@ static int get_card_bus_width(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                bus_width = chip->card_bus_width[lun];
        } else {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        scsi_set_resid(srb, 0);
@@ -2651,7 +2771,8 @@ static int spi_vendor_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        rtsx_disable_aspm(chip);
@@ -2700,13 +2821,16 @@ static int spi_vendor_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
 
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
 
-       if (result != STATUS_SUCCESS)
-               TRACE_RET(chip, TRANSPORT_FAILED);
+       if (result != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
+       }
 
        return TRANSPORT_GOOD;
 }
@@ -2765,7 +2889,8 @@ static int vendor_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        default:
                set_sense_type(chip, SCSI_LUN(srb),
                        SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        return result;
@@ -2797,18 +2922,21 @@ static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 {
        struct ms_info *ms_card = &(chip->ms_card);
        unsigned int lun = SCSI_LUN(srb);
-       int retval, quick_format;
+       bool quick_format;
+       int retval;
 
        if (get_lun_card(chip, lun) != MS_CARD) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if ((srb->cmnd[3] != 0x4D) || (srb->cmnd[4] != 0x47) ||
                (srb->cmnd[5] != 0x66) || (srb->cmnd[6] != 0x6D) ||
                (srb->cmnd[7] != 0x74)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        rtsx_disable_aspm(chip);
@@ -2820,35 +2948,40 @@ static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                if (!check_card_ready(chip, lun) ||
                                (get_card_size(chip, lun) == 0)) {
                        set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        }
        rtsx_set_stat(chip, RTSX_STAT_RUN);
 
        if (srb->cmnd[8] & 0x01)
-               quick_format = 0;
+               quick_format = false;
        else
-               quick_format = 1;
+               quick_format = true;
 
        if (!(chip->card_ready & MS_CARD)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (chip->card_wp & MS_CARD) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (!CHK_MSPRO(ms_card)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        retval = mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        scsi_set_resid(srb, 0);
@@ -2867,18 +3000,21 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (!check_card_ready(chip, lun)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
        if (get_lun_card(chip, lun) != MS_CARD) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if ((srb->cmnd[2] != 0xB0) || (srb->cmnd[4] != 0x4D) ||
                (srb->cmnd[5] != 0x53) || (srb->cmnd[6] != 0x49) ||
                (srb->cmnd[7] != 0x44)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        dev_info_id = srb->cmnd[3];
@@ -2886,7 +3022,8 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        (!CHK_MSXC(ms_card) && (dev_info_id == 0x13)) ||
                        !CHK_MSPRO(ms_card)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (dev_info_id == 0x15)
@@ -2895,8 +3032,10 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                buf_len = data_len = 0x6A;
 
        buf = kmalloc(buf_len, GFP_KERNEL);
-       if (!buf)
-               TRACE_RET(chip, TRANSPORT_ERROR);
+       if (!buf) {
+               rtsx_trace(chip);
+               return TRANSPORT_ERROR;
+       }
 
        i = 0;
        /*  GET Memory Stick Media Information Response Header */
@@ -2983,11 +3122,13 @@ static int sd_extention_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (!check_card_ready(chip, lun)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
        if (get_lun_card(chip, lun) != SD_CARD) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        switch (srb->cmnd[0]) {
@@ -3017,7 +3158,8 @@ static int sd_extention_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        default:
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        return result;
@@ -3044,21 +3186,25 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (!check_card_ready(chip, lun)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
        if (get_lun_card(chip, lun) != MS_CARD) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (srb->cmnd[7] != KC_MG_R_PRO) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (!CHK_MSPRO(ms_card)) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        key_format = srb->cmnd[10] & 0x3F;
@@ -3070,13 +3216,16 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        (srb->cmnd[8] == 0x04) &&
                        (srb->cmnd[9] == 0x1C)) {
                        retval = mg_get_local_EKB(srb, chip);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
+                       }
 
                } else {
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
                break;
 
@@ -3085,13 +3234,16 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        (srb->cmnd[8] == 0x00) &&
                        (srb->cmnd[9] == 0x24)) {
                        retval = mg_get_rsp_chg(srb, chip);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
+                       }
 
                } else {
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
                break;
 
@@ -3105,19 +3257,23 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        (srb->cmnd[4] == 0x00) &&
                        (srb->cmnd[5] < 32)) {
                        retval = mg_get_ICV(srb, chip);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
+                       }
 
                } else {
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
                break;
 
        default:
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        scsi_set_resid(srb, 0);
@@ -3143,25 +3299,30 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (!check_card_ready(chip, lun)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
        if (check_card_wp(chip, lun)) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
        if (get_lun_card(chip, lun) != MS_CARD) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (srb->cmnd[7] != KC_MG_R_PRO) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (!CHK_MSPRO(ms_card)) {
                set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        key_format = srb->cmnd[10] & 0x3F;
@@ -3173,13 +3334,16 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        (srb->cmnd[8] == 0x00) &&
                        (srb->cmnd[9] == 0x0C)) {
                        retval = mg_set_leaf_id(srb, chip);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
+                       }
 
                } else {
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
                break;
 
@@ -3188,13 +3352,16 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        (srb->cmnd[8] == 0x00) &&
                        (srb->cmnd[9] == 0x0C)) {
                        retval = mg_chg(srb, chip);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
+                       }
 
                } else {
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
                break;
 
@@ -3203,13 +3370,16 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        (srb->cmnd[8] == 0x00) &&
                        (srb->cmnd[9] == 0x0C)) {
                        retval = mg_rsp(srb, chip);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
+                       }
 
                } else {
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
                break;
 
@@ -3223,19 +3393,23 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        (srb->cmnd[4] == 0x00) &&
                        (srb->cmnd[5] < 32)) {
                        retval = mg_set_ICV(srb, chip);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
+                       }
 
                } else {
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
                break;
 
        default:
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        scsi_set_resid(srb, 0);
@@ -3264,7 +3438,8 @@ int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        /* Logical Unit Not Ready Format in Progress */
                        set_sense_data(chip, lun, CUR_ERR,
                                       0x02, 0, 0x04, 0x04, 0, 0);
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        }
 #endif
@@ -3276,7 +3451,8 @@ int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        /* Logical Unit Not Ready Format in Progress */
                        set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
                                        0, (u16)(ms_card->progress));
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
        }
 
index dab1995d1a6a5f9276edaaecf876fad2e166de77..f27491e802edeef46587208b6fc747d41c506270 100644 (file)
 #include <linux/sched.h>
 
 #include "rtsx.h"
-#include "rtsx_scsi.h"
-#include "rtsx_transport.h"
-#include "rtsx_chip.h"
-#include "rtsx_card.h"
 
 /***********************************************************************
  * Scatter-gather transfer buffer access routines
@@ -276,7 +272,8 @@ int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout)
                dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n",
                        chip->int_reg);
                err = -ETIMEDOUT;
-               TRACE_GOTO(chip, finish_send_cmd);
+               rtsx_trace(chip);
+               goto finish_send_cmd;
        }
 
        spin_lock_irq(&rtsx->reg_lock);
@@ -642,7 +639,7 @@ static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf,
        dma_addr_t addr;
        u8 dir;
        int err = 0;
-       u32 val = (1 << 31);
+       u32 val = 1 << 31;
        long timeleft;
 
        if ((buf == NULL) || (len <= 0))
index c28a92773f05de2e32985240238dbe4d25ed3ece..a8d657bb5c1bca8f99be1ea050a952ff9d337afa 100644 (file)
@@ -25,9 +25,6 @@
 #include <linux/sched.h>
 
 #include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
 #include "sd.h"
 
 #define SD_MAX_RETRY_COUNT     3
@@ -108,13 +105,19 @@ static void sd_init_reg_addr(struct rtsx_chip *chip)
 
 static int sd_check_data0_status(struct rtsx_chip *chip)
 {
+       int retval;
        u8 stat;
 
-       RTSX_READ_REG(chip, REG_SD_STAT1, &stat);
+       retval = rtsx_read_register(chip, REG_SD_STAT1, &stat);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        if (!(stat & SD_DAT0_STATUS)) {
                sd_set_err_code(chip, SD_BUSY);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -187,7 +190,8 @@ RTY_SEND_CMD:
                                retval = sd_check_data0_status(chip);
                                if (retval != STATUS_SUCCESS) {
                                        rtsx_clear_sd_error(chip);
-                                       TRACE_RET(chip, retval);
+                                       rtsx_trace(chip);
+                                       return retval;
                                }
                        } else {
                                sd_set_err_code(chip, SD_TO_ERR);
@@ -198,7 +202,8 @@ RTY_SEND_CMD:
                }
                rtsx_clear_sd_error(chip);
 
-               TRACE_RET(chip, retval);
+               rtsx_trace(chip);
+               return retval;
        }
 
        if (rsp_type == SD_RSP_TYPE_R0)
@@ -208,14 +213,16 @@ RTY_SEND_CMD:
 
        if ((ptr[0] & 0xC0) != 0) {
                sd_set_err_code(chip, SD_STS_ERR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (!(rsp_type & SD_NO_CHECK_CRC7)) {
                if (ptr[stat_idx] & SD_CRC7_ERR) {
                        if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
                                sd_set_err_code(chip, SD_CRC_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        if (rty_cnt < SD_MAX_RETRY_COUNT) {
                                wait_timeout(20);
@@ -223,7 +230,8 @@ RTY_SEND_CMD:
                                goto RTY_SEND_CMD;
                        } else {
                                sd_set_err_code(chip, SD_CRC_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
        }
@@ -232,8 +240,10 @@ RTY_SEND_CMD:
                if ((cmd_idx != SEND_RELATIVE_ADDR) &&
                        (cmd_idx != SEND_IF_COND)) {
                        if (cmd_idx != STOP_TRANSMISSION) {
-                               if (ptr[1] & 0x80)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if (ptr[1] & 0x80) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
                        }
 #ifdef SUPPORT_SD_LOCK
                        if (ptr[1] & 0x7D)
@@ -243,17 +253,20 @@ RTY_SEND_CMD:
                        {
                                dev_dbg(rtsx_dev(chip), "ptr[1]: 0x%02x\n",
                                        ptr[1]);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        if (ptr[2] & 0xFF) {
                                dev_dbg(rtsx_dev(chip), "ptr[2]: 0x%02x\n",
                                        ptr[2]);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        if (ptr[3] & 0x80) {
                                dev_dbg(rtsx_dev(chip), "ptr[3]: 0x%02x\n",
                                        ptr[3]);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        if (ptr[3] & 0x01)
                                sd_card->sd_data_buf_ready = 1;
@@ -282,8 +295,10 @@ static int sd_read_data(struct rtsx_chip *chip,
        if (!buf)
                buf_len = 0;
 
-       if (buf_len > 512)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (buf_len > 512) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -323,13 +338,16 @@ static int sd_read_data(struct rtsx_chip *chip,
                                            SD_RSP_TYPE_R1, NULL, 0);
                }
 
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (buf && buf_len) {
                retval = rtsx_read_ppbuf(chip, buf, buf_len);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -350,13 +368,16 @@ static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode,
 
        if (buf_len > 512) {
                /* This function can't write data more than one page */
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (buf && buf_len) {
                retval = rtsx_write_ppbuf(chip, buf, buf_len);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        rtsx_init_cmd(chip);
@@ -395,7 +416,8 @@ static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode,
                                sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
                }
 
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -412,7 +434,8 @@ static int sd_check_csd(struct rtsx_chip *chip, char check_wp)
        for (i = 0; i < 6; i++) {
                if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
                        sd_set_err_code(chip, SD_NO_CARD);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                retval = sd_send_cmd_get_rsp(chip, SEND_CSD, sd_card->sd_addr,
@@ -421,8 +444,10 @@ static int sd_check_csd(struct rtsx_chip *chip, char check_wp)
                        break;
        }
 
-       if (i == 6)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (i == 6) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        memcpy(sd_card->raw_csd, rsp + 1, 15);
 
@@ -464,10 +489,12 @@ static int sd_check_csd(struct rtsx_chip *chip, char check_wp)
                        else
                                sd_card->sd_clock = CLK_20;
                } else {
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        } else {
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (CHK_MMC_SECTOR_MODE(sd_card)) {
@@ -507,8 +534,8 @@ static int sd_check_csd(struct rtsx_chip *chip, char check_wp)
 
 static int sd_set_sample_push_timing(struct rtsx_chip *chip)
 {
+       int retval;
        struct sd_info *sd_card = &(chip->sd_card);
-
        u8 val = 0;
 
        if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY)
@@ -536,7 +563,11 @@ static int sd_set_sample_push_timing(struct rtsx_chip *chip)
                        val |= 0x08;
        }
 
-       RTSX_WRITE_REG(chip, REG_SD_CFG1, 0x1C, val);
+       retval = rtsx_write_register(chip, REG_SD_CFG1, 0x1C, val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -585,6 +616,7 @@ static void sd_choose_proper_clock(struct rtsx_chip *chip)
 
 static int sd_set_clock_divider(struct rtsx_chip *chip, u8 clk_div)
 {
+       int retval;
        u8 mask = 0, val = 0;
 
        mask = 0x60;
@@ -595,7 +627,11 @@ static int sd_set_clock_divider(struct rtsx_chip *chip, u8 clk_div)
        else if (clk_div == SD_CLK_DIVIDE_256)
                val = 0x20;
 
-       RTSX_WRITE_REG(chip, REG_SD_CFG1, mask, val);
+       retval = rtsx_write_register(chip, REG_SD_CFG1, mask, val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -606,14 +642,18 @@ static int sd_set_init_para(struct rtsx_chip *chip)
        int retval;
 
        retval = sd_set_sample_push_timing(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        sd_choose_proper_clock(chip);
 
        retval = switch_clock(chip, sd_card->sd_clock);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -636,8 +676,10 @@ int sd_select_card(struct rtsx_chip *chip, int select)
        }
 
        retval = sd_send_cmd_get_rsp(chip, cmd_idx, addr, cmd_type, NULL, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -651,8 +693,10 @@ static int sd_update_lock_status(struct rtsx_chip *chip)
 
        retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
                                SD_RSP_TYPE_R1, rsp, 5);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (rsp[1] & 0x02)
                sd_card->sd_lock_status |= SD_LOCKED;
@@ -662,8 +706,10 @@ static int sd_update_lock_status(struct rtsx_chip *chip)
        dev_dbg(rtsx_dev(chip), "sd_card->sd_lock_status = 0x%x\n",
                sd_card->sd_lock_status);
 
-       if (rsp[1] & 0x01)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (rsp[1] & 0x01) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -680,15 +726,18 @@ static int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state,
                retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
                                        sd_card->sd_addr, SD_RSP_TYPE_R1, rsp,
                                        5);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                if (((rsp[3] & 0x1E) == state) &&
                        ((rsp[3] & 0x01) == data_ready))
                        return STATUS_SUCCESS;
        }
 
-       TRACE_RET(chip, STATUS_FAIL);
+       rtsx_trace(chip);
+       return STATUS_FAIL;
 }
 
 static int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage)
@@ -700,24 +749,39 @@ static int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage)
                        retval = rtsx_write_phy_register(chip, 0x08,
                                                        0x4FC0 |
                                                        chip->phy_voltage);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                } else {
-                       RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8, 0);
+                       retval = rtsx_write_register(chip, SD_PAD_CTL,
+                                                    SD_IO_USING_1V8, 0);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                }
        } else if (voltage == SD_IO_1V8) {
                if (chip->asic_code) {
                        retval = rtsx_write_phy_register(chip, 0x08,
                                                        0x4C40 |
                                                        chip->phy_voltage);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                } else {
-                       RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8,
-                               SD_IO_USING_1V8);
+                       retval = rtsx_write_register(chip, SD_PAD_CTL,
+                                                    SD_IO_USING_1V8,
+                                                    SD_IO_USING_1V8);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                }
        } else {
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -728,33 +792,61 @@ static int sd_voltage_switch(struct rtsx_chip *chip)
        int retval;
        u8 stat;
 
-       RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP,
-               SD_CLK_TOGGLE_EN);
+       retval = rtsx_write_register(chip, SD_BUS_STAT,
+                                    SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP,
+                                    SD_CLK_TOGGLE_EN);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        retval = sd_send_cmd_get_rsp(chip, VOLTAGE_SWITCH, 0, SD_RSP_TYPE_R1,
                                NULL, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        udelay(chip->sd_voltage_switch_delay);
 
-       RTSX_READ_REG(chip, SD_BUS_STAT, &stat);
+       retval = rtsx_read_register(chip, SD_BUS_STAT, &stat);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
                                SD_DAT1_STATUS | SD_DAT0_STATUS)) {
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
-       RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_FORCE_STOP);
+       retval = rtsx_write_register(chip, SD_BUS_STAT, 0xFF,
+                                    SD_CLK_FORCE_STOP);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        retval = sd_change_bank_voltage(chip, SD_IO_1V8);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        wait_timeout(50);
 
-       RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN);
+       retval = rtsx_write_register(chip, SD_BUS_STAT, 0xFF,
+                                    SD_CLK_TOGGLE_EN);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        wait_timeout(10);
 
-       RTSX_READ_REG(chip, SD_BUS_STAT, &stat);
+       retval = rtsx_read_register(chip, SD_BUS_STAT, &stat);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        if ((stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
                                SD_DAT1_STATUS | SD_DAT0_STATUS)) !=
                        (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
@@ -763,23 +855,48 @@ static int sd_voltage_switch(struct rtsx_chip *chip)
                rtsx_write_register(chip, SD_BUS_STAT,
                                SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
                rtsx_write_register(chip, CARD_CLK_EN, 0xFF, 0);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
-       RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP,
-               0);
+       retval = rtsx_write_register(chip, SD_BUS_STAT,
+                                    SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
 
 static int sd_reset_dcm(struct rtsx_chip *chip, u8 tune_dir)
 {
+       int retval;
+
        if (tune_dir == TUNE_RX) {
-               RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RESET | DCM_RX);
-               RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RX);
+               retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF,
+                                            DCM_RESET | DCM_RX);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF, DCM_RX);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        } else {
-               RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RESET | DCM_TX);
-               RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_TX);
+               retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF,
+                                            DCM_RESET | DCM_TX);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF, DCM_TX);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -791,7 +908,7 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
        u16 SD_VP_CTL, SD_DCMPS_CTL;
        u8 val;
        int retval;
-       int ddr_rx = 0;
+       bool ddr_rx = false;
 
        dev_dbg(rtsx_dev(chip), "sd_change_phase (sample_point = %d, tune_dir = %d)\n",
                sample_point, tune_dir);
@@ -800,19 +917,42 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
                SD_VP_CTL = SD_VPRX_CTL;
                SD_DCMPS_CTL = SD_DCMPS_RX_CTL;
                if (CHK_SD_DDR50(sd_card))
-                       ddr_rx = 1;
+                       ddr_rx = true;
        } else {
                SD_VP_CTL = SD_VPTX_CTL;
                SD_DCMPS_CTL = SD_DCMPS_TX_CTL;
        }
 
        if (chip->asic_code) {
-               RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
-               RTSX_WRITE_REG(chip, SD_VP_CTL, 0x1F, sample_point);
-               RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
-               RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET,
-                       PHASE_NOT_RESET);
-               RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0);
+               retval = rtsx_write_register(chip, CLK_CTL, CHANGE_CLK,
+                                            CHANGE_CLK);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, SD_VP_CTL, 0x1F,
+                                            sample_point);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
+                                            PHASE_NOT_RESET, 0);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
+                                            PHASE_NOT_RESET, PHASE_NOT_RESET);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CLK_CTL, CHANGE_CLK, 0);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        } else {
                rtsx_read_register(chip, SD_VP_CTL, &val);
                dev_dbg(rtsx_dev(chip), "SD_VP_CTL: 0x%x\n", val);
@@ -820,16 +960,34 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
                dev_dbg(rtsx_dev(chip), "SD_DCMPS_CTL: 0x%x\n", val);
 
                if (ddr_rx) {
-                       RTSX_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE,
-                               PHASE_CHANGE);
+                       retval = rtsx_write_register(chip, SD_VP_CTL,
+                                                    PHASE_CHANGE,
+                                                    PHASE_CHANGE);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                        udelay(50);
-                       RTSX_WRITE_REG(chip, SD_VP_CTL, 0xFF,
-                               PHASE_CHANGE | PHASE_NOT_RESET | sample_point);
+                       retval = rtsx_write_register(chip, SD_VP_CTL, 0xFF,
+                                                    PHASE_CHANGE | PHASE_NOT_RESET | sample_point);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                } else {
-                       RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
+                       retval = rtsx_write_register(chip, CLK_CTL,
+                                                    CHANGE_CLK, CHANGE_CLK);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                        udelay(50);
-                       RTSX_WRITE_REG(chip, SD_VP_CTL, 0xFF,
-                                       PHASE_NOT_RESET | sample_point);
+                       retval = rtsx_write_register(chip, SD_VP_CTL, 0xFF,
+                                                    PHASE_NOT_RESET | sample_point);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                }
                udelay(100);
 
@@ -839,26 +997,52 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
                rtsx_add_cmd(chip, CHECK_REG_CMD, SD_DCMPS_CTL,
                        DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE);
                retval = rtsx_send_cmd(chip, SD_CARD, 100);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, Fail);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto Fail;
+               }
 
                val = *rtsx_get_cmd_data(chip);
-               if (val & DCMPS_ERROR)
-                       TRACE_GOTO(chip, Fail);
+               if (val & DCMPS_ERROR) {
+                       rtsx_trace(chip);
+                       goto Fail;
+               }
 
-               if ((val & DCMPS_CURRENT_PHASE) != sample_point)
-                       TRACE_GOTO(chip, Fail);
+               if ((val & DCMPS_CURRENT_PHASE) != sample_point) {
+                       rtsx_trace(chip);
+                       goto Fail;
+               }
 
-               RTSX_WRITE_REG(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0);
-               if (ddr_rx)
-                       RTSX_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE, 0);
-               else
-                       RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0);
+               retval = rtsx_write_register(chip, SD_DCMPS_CTL,
+                                            DCMPS_CHANGE, 0);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               if (ddr_rx) {
+                       retval = rtsx_write_register(chip, SD_VP_CTL,
+                                                    PHASE_CHANGE, 0);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+               } else {
+                       retval = rtsx_write_register(chip, CLK_CTL,
+                                                    CHANGE_CLK, 0);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+               }
 
                udelay(50);
        }
 
-       RTSX_WRITE_REG(chip, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
+       retval = rtsx_write_register(chip, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 
@@ -883,8 +1067,10 @@ static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width)
 
        retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
                                SD_RSP_TYPE_R1, NULL, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        cmd[0] = 0x40 | SEND_SCR;
        cmd[1] = 0;
@@ -896,13 +1082,16 @@ static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width)
                        buf, 8, 250);
        if (retval != STATUS_SUCCESS) {
                rtsx_clear_sd_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        memcpy(sd_card->raw_scr, buf, 8);
 
-       if ((buf[0] & 0x0F) == 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if ((buf[0] & 0x0F) == 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -944,7 +1133,8 @@ static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group,
                        break;
 
                default:
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        } else if (func_group == SD_FUNC_GROUP_3) {
                support_offset = FUNCTION_GROUP3_SUPPORT_OFFSET;
@@ -971,7 +1161,8 @@ static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group,
                        break;
 
                default:
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        } else if (func_group == SD_FUNC_GROUP_4) {
                support_offset = FUNCTION_GROUP4_SUPPORT_OFFSET;
@@ -998,23 +1189,27 @@ static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group,
                        break;
 
                default:
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        } else {
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (func_group == SD_FUNC_GROUP_1) {
                if (!(buf[support_offset] & support_mask) ||
                        ((buf[query_switch_offset] & 0x0F) != query_switch)) {
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
        /* Check 'Busy Status' */
        if ((buf[DATA_STRUCTURE_VER_OFFSET] == 0x01) &&
                    ((buf[check_busy_offset] & switch_busy) == switch_busy)) {
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -1056,7 +1251,8 @@ static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode,
                        buf, 64, 250);
        if (retval != STATUS_SUCCESS) {
                rtsx_clear_sd_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        dev_dbg(rtsx_dev(chip), "%*ph\n", 64, buf);
@@ -1083,19 +1279,33 @@ static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode,
 
                dev_dbg(rtsx_dev(chip), "Maximum current consumption: %dmA\n",
                        cc);
-               if ((cc == 0) || (cc > 800))
-                       TRACE_RET(chip, STATUS_FAIL);
+               if ((cc == 0) || (cc > 800)) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = sd_query_switch_result(chip, func_group,
                                                func_to_switch, buf, 64);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                if ((cc > 400) || (func_to_switch > CURRENT_LIMIT_400)) {
-                       RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK,
-                               chip->sd_800mA_ocp_thd);
-                       RTSX_WRITE_REG(chip, CARD_PWR_CTL, PMOS_STRG_MASK,
-                               PMOS_STRG_800mA);
+                       retval = rtsx_write_register(chip, OCPPARA2,
+                                                    SD_OCP_THD_MASK,
+                                                    chip->sd_800mA_ocp_thd);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+                       retval = rtsx_write_register(chip, CARD_PWR_CTL,
+                                                    PMOS_STRG_MASK,
+                                                    PMOS_STRG_800mA);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                }
        }
 
@@ -1121,12 +1331,13 @@ static int sd_check_switch(struct rtsx_chip *chip,
 {
        int retval;
        int i;
-       int switch_good = 0;
+       bool switch_good = false;
 
        for (i = 0; i < 3; i++) {
                if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
                        sd_set_err_code(chip, SD_NO_CARD);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                retval = sd_check_switch_mode(chip, SD_CHECK_MODE, func_group,
@@ -1137,14 +1348,19 @@ static int sd_check_switch(struct rtsx_chip *chip,
                        retval = sd_check_switch_mode(chip, SD_SWITCH_MODE,
                                        func_group, func_to_switch, bus_width);
                        if (retval == STATUS_SUCCESS) {
-                               switch_good = 1;
+                               switch_good = true;
                                break;
                        }
 
-                       RTSX_READ_REG(chip, SD_STAT1, &stat);
+                       retval = rtsx_read_register(chip, SD_STAT1, &stat);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                        if (stat & SD_CRC16_ERR) {
                                dev_dbg(rtsx_dev(chip), "SD CRC16 error when switching mode\n");
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
 
@@ -1154,8 +1370,10 @@ static int sd_check_switch(struct rtsx_chip *chip,
                wait_timeout(20);
        }
 
-       if (!switch_good)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (!switch_good) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -1170,8 +1388,10 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width)
        /* Get supported functions */
        retval = sd_check_switch_mode(chip, SD_CHECK_MODE,
                        NO_ARGUMENT, NO_ARGUMENT, bus_width);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        sd_card->func_group1_mask &= ~(sd_card->sd_switch_fail);
 
@@ -1239,7 +1459,8 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width)
                                sd_card->sd_switch_fail = SDR104_SUPPORT_MASK |
                                        DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK;
                        }
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                if (func_to_switch == SDR104_SUPPORT)
@@ -1253,10 +1474,17 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width)
        }
 
        if (CHK_SD_DDR50(sd_card)) {
-               RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0x04);
+               retval = rtsx_write_register(chip, SD_PUSH_POINT_CTL, 0x06,
+                                            0x04);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                retval = sd_set_sample_push_timing(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        if (!func_to_switch || (func_to_switch == HS_SUPPORT)) {
@@ -1310,15 +1538,22 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width)
                retval = sd_check_switch(chip, SD_FUNC_GROUP_4, func_to_switch,
                                        bus_width);
                if (retval != STATUS_SUCCESS) {
-                       if (sd_check_err_code(chip, SD_NO_CARD))
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (sd_check_err_code(chip, SD_NO_CARD)) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                }
                dev_dbg(rtsx_dev(chip), "Switch current limit finished! (%d)\n",
                        retval);
        }
 
-       if (CHK_SD_DDR50(sd_card))
-               RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0);
+       if (CHK_SD_DDR50(sd_card)) {
+               retval = rtsx_write_register(chip, SD_PUSH_POINT_CTL, 0x06, 0);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+       }
 
        return STATUS_SUCCESS;
 }
@@ -1330,7 +1565,11 @@ static int sd_wait_data_idle(struct rtsx_chip *chip)
        u8 val = 0;
 
        for (i = 0; i < 100; i++) {
-               RTSX_READ_REG(chip, SD_DATA_STATE, &val);
+               retval = rtsx_read_register(chip, SD_DATA_STATE, &val);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
                if (val & SD_DATA_IDLE) {
                        retval = STATUS_SUCCESS;
                        break;
@@ -1348,8 +1587,10 @@ static int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
        u8 cmd[5];
 
        retval = sd_change_phase(chip, sample_point, TUNE_RX);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        cmd[0] = 0x40 | SEND_TUNING_PATTERN;
        cmd[1] = 0;
@@ -1363,7 +1604,8 @@ static int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
                (void)sd_wait_data_idle(chip);
 
                rtsx_clear_sd_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -1376,15 +1618,19 @@ static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
        u8 cmd[5];
 
        retval = sd_change_phase(chip, sample_point, TUNE_RX);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        dev_dbg(rtsx_dev(chip), "sd ddr tuning rx\n");
 
        retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
                                SD_RSP_TYPE_R1, NULL, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        cmd[0] = 0x40 | SD_STATUS;
        cmd[1] = 0;
@@ -1398,7 +1644,8 @@ static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
                (void)sd_wait_data_idle(chip);
 
                rtsx_clear_sd_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -1418,8 +1665,10 @@ static int mmc_ddr_tunning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
                bus_width = SD_BUS_WIDTH_1;
 
        retval = sd_change_phase(chip, sample_point, TUNE_RX);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        dev_dbg(rtsx_dev(chip), "mmc ddr tuning rx\n");
 
@@ -1435,7 +1684,8 @@ static int mmc_ddr_tunning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
                (void)sd_wait_data_idle(chip);
 
                rtsx_clear_sd_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -1447,11 +1697,17 @@ static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
        int retval;
 
        retval = sd_change_phase(chip, sample_point, TUNE_TX);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
-               SD_RSP_80CLK_TIMEOUT_EN);
+       retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
+                                    SD_RSP_80CLK_TIMEOUT_EN);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
                SD_RSP_TYPE_R1, NULL, 0);
@@ -1459,11 +1715,17 @@ static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
                if (sd_check_err_code(chip, SD_RSP_TIMEOUT)) {
                        rtsx_write_register(chip, SD_CFG3,
                                        SD_RSP_80CLK_TIMEOUT_EN, 0);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
-       RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
+       retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
+                                    0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -1475,8 +1737,10 @@ static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
        u8 cmd[5], bus_width;
 
        retval = sd_change_phase(chip, sample_point, TUNE_TX);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (CHK_SD(sd_card)) {
                bus_width = SD_BUS_WIDTH_4;
@@ -1490,11 +1754,17 @@ static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
        }
 
        retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
-               SD_RSP_80CLK_TIMEOUT_EN);
+       retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
+                                    SD_RSP_80CLK_TIMEOUT_EN);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        cmd[0] = 0x40 | PROGRAM_CSD;
        cmd[1] = 0;
@@ -1507,10 +1777,16 @@ static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
        if (retval != STATUS_SUCCESS) {
                rtsx_clear_sd_error(chip);
                rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
-       RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
+       retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
+                                    0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1,
                        NULL, 0);
@@ -1524,7 +1800,8 @@ static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map,
        struct sd_info *sd_card = &(chip->sd_card);
        struct timing_phase_path path[MAX_PHASE + 1];
        int i, j, cont_path_cnt;
-       int new_block, max_len, final_path_idx;
+       bool new_block;
+       int max_len, final_path_idx;
        u8 final_phase = 0xFF;
 
        if (phase_map == 0xFFFFFFFF) {
@@ -1537,12 +1814,12 @@ static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map,
        }
 
        cont_path_cnt = 0;
-       new_block = 1;
+       new_block = true;
        j = 0;
        for (i = 0; i < MAX_PHASE + 1; i++) {
                if (phase_map & (1 << i)) {
                        if (new_block) {
-                               new_block = 0;
+                               new_block = false;
                                j = cont_path_cnt++;
                                path[j].start = i;
                                path[j].end = i;
@@ -1550,7 +1827,7 @@ static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map,
                                path[j].end = i;
                        }
                } else {
-                       new_block = 1;
+                       new_block = true;
                        if (cont_path_cnt) {
                                int idx = cont_path_cnt - 1;
 
@@ -1654,8 +1931,10 @@ static int sd_tuning_rx(struct rtsx_chip *chip)
        } else {
                if (CHK_MMC_DDR52(sd_card))
                        tuning_cmd = mmc_ddr_tunning_rx_cmd;
-               else
-                       TRACE_RET(chip, STATUS_FAIL);
+               else {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        for (i = 0; i < 3; i++) {
@@ -1663,7 +1942,8 @@ static int sd_tuning_rx(struct rtsx_chip *chip)
                for (j = MAX_PHASE; j >= 0; j--) {
                        if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
                                sd_set_err_code(chip, SD_NO_CARD);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        retval = tuning_cmd(chip, (u8)j);
@@ -1680,12 +1960,16 @@ static int sd_tuning_rx(struct rtsx_chip *chip)
        dev_dbg(rtsx_dev(chip), "RX phase_map = 0x%08x\n", phase_map);
 
        final_phase = sd_search_final_phase(chip, phase_map, TUNE_RX);
-       if (final_phase == 0xFF)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (final_phase == 0xFF) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = sd_change_phase(chip, final_phase, TUNE_RX);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -1698,8 +1982,12 @@ static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip)
        u32 phase_map;
        u8 final_phase;
 
-       RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
-               SD_RSP_80CLK_TIMEOUT_EN);
+       retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
+                                    SD_RSP_80CLK_TIMEOUT_EN);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        phase_map = 0;
        for (i = MAX_PHASE; i >= 0; i--) {
@@ -1707,7 +1995,8 @@ static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip)
                        sd_set_err_code(chip, SD_NO_CARD);
                        rtsx_write_register(chip, SD_CFG3,
                                                SD_RSP_80CLK_TIMEOUT_EN, 0);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                retval = sd_change_phase(chip, (u8)i, TUNE_TX);
@@ -1722,18 +2011,27 @@ static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip)
                        phase_map |= 1 << i;
        }
 
-       RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
+       retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
+                                    0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        dev_dbg(rtsx_dev(chip), "DDR TX pre tune phase_map = 0x%08x\n",
                phase_map);
 
        final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
-       if (final_phase == 0xFF)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (final_phase == 0xFF) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = sd_change_phase(chip, final_phase, TUNE_TX);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        dev_dbg(rtsx_dev(chip), "DDR TX pre tune phase: %d\n",
                (int)final_phase);
@@ -1759,8 +2057,10 @@ static int sd_tuning_tx(struct rtsx_chip *chip)
        } else {
                if (CHK_MMC_DDR52(sd_card))
                        tuning_cmd = sd_ddr_tuning_tx_cmd;
-               else
-                       TRACE_RET(chip, STATUS_FAIL);
+               else {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        for (i = 0; i < 3; i++) {
@@ -1770,7 +2070,8 @@ static int sd_tuning_tx(struct rtsx_chip *chip)
                                sd_set_err_code(chip, SD_NO_CARD);
                                rtsx_write_register(chip, SD_CFG3,
                                                    SD_RSP_80CLK_TIMEOUT_EN, 0);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        retval = tuning_cmd(chip, (u8)j);
@@ -1787,12 +2088,16 @@ static int sd_tuning_tx(struct rtsx_chip *chip)
        dev_dbg(rtsx_dev(chip), "TX phase_map = 0x%08x\n", phase_map);
 
        final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
-       if (final_phase == 0xFF)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (final_phase == 0xFF) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = sd_change_phase(chip, final_phase, TUNE_TX);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -1802,12 +2107,16 @@ static int sd_sdr_tuning(struct rtsx_chip *chip)
        int retval;
 
        retval = sd_tuning_tx(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = sd_tuning_rx(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -1818,23 +2127,31 @@ static int sd_ddr_tuning(struct rtsx_chip *chip)
 
        if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
                retval = sd_ddr_pre_tuning_tx(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        } else {
                retval = sd_change_phase(chip, (u8)chip->sd_ddr_tx_phase,
                                        TUNE_TX);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        retval = sd_tuning_rx(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
                retval = sd_tuning_tx(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -1846,23 +2163,31 @@ static int mmc_ddr_tuning(struct rtsx_chip *chip)
 
        if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
                retval = sd_ddr_pre_tuning_tx(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        } else {
                retval = sd_change_phase(chip, (u8)chip->mmc_ddr_tx_phase,
                                        TUNE_TX);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        retval = sd_tuning_rx(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
                retval = sd_tuning_tx(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -1875,12 +2200,16 @@ int sd_switch_clock(struct rtsx_chip *chip)
        int re_tuning = 0;
 
        retval = select_card(chip, SD_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = switch_clock(chip, sd_card->sd_clock);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (re_tuning) {
                if (CHK_SD(sd_card)) {
@@ -1893,8 +2222,10 @@ int sd_switch_clock(struct rtsx_chip *chip)
                                retval = mmc_ddr_tuning(chip);
                }
 
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -1924,41 +2255,100 @@ static int sd_prepare_reset(struct rtsx_chip *chip)
        chip->sd_io = 0;
 
        retval = sd_set_init_para(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, retval);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
-       RTSX_WRITE_REG(chip, REG_SD_CFG1, 0xFF, 0x40);
+       retval = rtsx_write_register(chip, REG_SD_CFG1, 0xFF, 0x40);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
-       RTSX_WRITE_REG(chip, CARD_STOP, SD_STOP | SD_CLR_ERR,
-               SD_STOP | SD_CLR_ERR);
+       retval = rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR,
+                                    SD_STOP | SD_CLR_ERR);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        retval = select_card(chip, SD_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
 
 static int sd_pull_ctl_disable(struct rtsx_chip *chip)
 {
+       int retval;
+
        if (CHECK_PID(chip, 0x5208)) {
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF,
-                       XD_D3_PD | SD_D7_PD | SD_CLK_PD | SD_D5_PD);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF,
-                       SD_D6_PD | SD_D0_PD | SD_D1_PD | XD_D5_PD);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF,
-                       SD_D4_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF,
-                       XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF,
-                       MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
+               retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF,
+                                            XD_D3_PD | SD_D7_PD | SD_CLK_PD | SD_D5_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF,
+                                            SD_D6_PD | SD_D0_PD | SD_D1_PD | XD_D5_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF,
+                                            SD_D4_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF,
+                                            XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF,
+                                            MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL6, 0xFF,
+                                            MS_D5_PD | MS_D4_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        } else if (CHECK_PID(chip, 0x5288)) {
                if (CHECK_BARO_PKG(chip, QFN)) {
-                       RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
-                       RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
-                       RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B);
-                       RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69);
+                       retval = rtsx_write_register(chip, CARD_PULL_CTL1,
+                                                    0xFF, 0x55);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+                       retval = rtsx_write_register(chip, CARD_PULL_CTL2,
+                                                    0xFF, 0x55);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+                       retval = rtsx_write_register(chip, CARD_PULL_CTL3,
+                                                    0xFF, 0x4B);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+                       retval = rtsx_write_register(chip, CARD_PULL_CTL4,
+                                                    0xFF, 0x69);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                }
        }
 
@@ -1998,8 +2388,10 @@ int sd_pull_ctl_enable(struct rtsx_chip *chip)
        }
 
        retval = rtsx_send_cmd(chip, SD_CARD, 100);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -2009,29 +2401,41 @@ static int sd_init_power(struct rtsx_chip *chip)
        int retval;
 
        retval = sd_power_off_card3v3(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (!chip->ft2_fast_mode)
                wait_timeout(250);
 
        retval = enable_card_clock(chip, SD_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (chip->asic_code) {
                retval = sd_pull_ctl_enable(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        } else {
-               RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_SD_PULL_CTL_BIT | 0x20,
-                       0);
+               retval = rtsx_write_register(chip, FPGA_PULL_CTL,
+                                            FPGA_SD_PULL_CTL_BIT | 0x20, 0);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        }
 
        if (!chip->ft2_fast_mode) {
                retval = card_power_on(chip, SD_CARD);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                wait_timeout(260);
 
@@ -2039,21 +2443,37 @@ static int sd_init_power(struct rtsx_chip *chip)
                if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
                        dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
                                chip->ocp_stat);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 #endif
        }
 
-       RTSX_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN);
+       retval = rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN,
+                                    SD_OUTPUT_EN);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
 
 static int sd_dummy_clock(struct rtsx_chip *chip)
 {
-       RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x01, 0x01);
+       int retval;
+
+       retval = rtsx_write_register(chip, REG_SD_CFG3, 0x01, 0x01);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        wait_timeout(5);
-       RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x01, 0);
+       retval = rtsx_write_register(chip, REG_SD_CFG3, 0x01, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -2085,7 +2505,8 @@ static int sd_read_lba0(struct rtsx_chip *chip)
                5, 512, 1, bus_width, NULL, 0, 100);
        if (retval != STATUS_SUCCESS) {
                rtsx_clear_sd_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -2101,8 +2522,10 @@ static int sd_check_wp_state(struct rtsx_chip *chip)
 
        retval = sd_send_cmd_get_rsp(chip, APP_CMD,
                        sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        cmd[0] = 0x40 | SD_STATUS;
        cmd[1] = 0;
@@ -2117,7 +2540,8 @@ static int sd_check_wp_state(struct rtsx_chip *chip)
 
                sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
                                SD_RSP_TYPE_R1, NULL, 0);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        dev_dbg(rtsx_dev(chip), "ACMD13:\n");
@@ -2141,14 +2565,15 @@ static int sd_check_wp_state(struct rtsx_chip *chip)
 static int reset_sd(struct rtsx_chip *chip)
 {
        struct sd_info *sd_card = &(chip->sd_card);
-       int retval, i = 0, j = 0, k = 0, hi_cap_flow = 0;
-       int sd_dont_switch = 0;
-       int support_1v8 = 0;
-       int try_sdio = 1;
+       bool hi_cap_flow = false;
+       int retval, i = 0, j = 0, k = 0;
+       bool sd_dont_switch = false;
+       bool support_1v8 = false;
+       bool try_sdio = true;
        u8 rsp[16];
        u8 switch_bus_width;
        u32 voltage = 0;
-       int sd20_mode = 0;
+       bool sd20_mode = false;
 
        SET_SD(sd_card);
 
@@ -2157,7 +2582,7 @@ Switch_Fail:
        i = 0;
        j = 0;
        k = 0;
-       hi_cap_flow = 0;
+       hi_cap_flow = false;
 
 #ifdef SUPPORT_SD_LOCK
        if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
@@ -2165,12 +2590,16 @@ Switch_Fail:
 #endif
 
        retval = sd_prepare_reset(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = sd_dummy_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) {
                int rty_cnt = 0;
@@ -2178,7 +2607,8 @@ Switch_Fail:
                for (; rty_cnt < chip->sdio_retry_cnt; rty_cnt++) {
                        if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
                                sd_set_err_code(chip, SD_NO_CARD);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0,
@@ -2190,7 +2620,8 @@ Switch_Fail:
                                        dev_dbg(rtsx_dev(chip), "SD_IO card (Function number: %d)!\n",
                                                func_num);
                                        chip->sd_io = 1;
-                                       TRACE_RET(chip, STATUS_FAIL);
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
                                }
 
                                break;
@@ -2208,8 +2639,10 @@ Switch_Fail:
 RTY_SD_RST:
        retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0,
                                NULL, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        wait_timeout(20);
 
@@ -2217,7 +2650,7 @@ RTY_SD_RST:
                                SD_RSP_TYPE_R7, rsp, 5);
        if (retval == STATUS_SUCCESS) {
                if ((rsp[4] == 0xAA) && ((rsp[3] & 0x0f) == 0x01)) {
-                       hi_cap_flow = 1;
+                       hi_cap_flow = true;
                        voltage = SUPPORT_VOLTAGE | 0x40000000;
                }
        }
@@ -2227,8 +2660,10 @@ RTY_SD_RST:
 
                retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0,
                                        SD_RSP_TYPE_R0, NULL, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                wait_timeout(20);
        }
@@ -2239,14 +2674,17 @@ RTY_SD_RST:
                if (retval != STATUS_SUCCESS) {
                        if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
                                sd_set_err_code(chip, SD_NO_CARD);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        j++;
                        if (j < 3)
                                goto RTY_SD_RST;
-                       else
-                               TRACE_RET(chip, STATUS_FAIL);
+                       else {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                }
 
                retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage,
@@ -2255,16 +2693,20 @@ RTY_SD_RST:
                        k++;
                        if (k < 3)
                                goto RTY_SD_RST;
-                       else
-                               TRACE_RET(chip, STATUS_FAIL);
+                       else {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                }
 
                i++;
                wait_timeout(20);
        } while (!(rsp[1] & 0x80) && (i < 255));
 
-       if (i == 255)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (i == 255) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (hi_cap_flow) {
                if (rsp[1] & 0x40)
@@ -2272,29 +2714,35 @@ RTY_SD_RST:
                else
                        CLR_SD_HCXC(sd_card);
 
-               support_1v8 = 0;
+               support_1v8 = false;
        } else {
                CLR_SD_HCXC(sd_card);
-               support_1v8 = 0;
+               support_1v8 = false;
        }
        dev_dbg(rtsx_dev(chip), "support_1v8 = %d\n", support_1v8);
 
        if (support_1v8) {
                retval = sd_voltage_switch(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2,
                                NULL, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        for (i = 0; i < 3; i++) {
                retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0,
                                        SD_RSP_TYPE_R6, rsp, 5);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                sd_card->sd_addr = (u32)rsp[1] << 24;
                sd_card->sd_addr += (u32)rsp[2] << 16;
@@ -2304,18 +2752,24 @@ RTY_SD_RST:
        }
 
        retval = sd_check_csd(chip, 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = sd_select_card(chip, 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
 #ifdef SUPPORT_SD_LOCK
 SD_UNLOCK_ENTRY:
        retval = sd_update_lock_status(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (sd_card->sd_lock_status & SD_LOCKED) {
                sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST);
@@ -2327,24 +2781,32 @@ SD_UNLOCK_ENTRY:
 
        retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
                                SD_RSP_TYPE_R1, NULL, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0,
                                SD_RSP_TYPE_R1, NULL, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (support_1v8) {
                retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
                                        SD_RSP_TYPE_R1, NULL, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2,
                                        SD_RSP_TYPE_R1, NULL, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                switch_bus_width = SD_BUS_WIDTH_4;
        } else {
@@ -2353,15 +2815,19 @@ SD_UNLOCK_ENTRY:
 
        retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1,
                                NULL, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (!(sd_card->raw_csd[4] & 0x40))
-               sd_dont_switch = 1;
+               sd_dont_switch = true;
 
        if (!sd_dont_switch) {
                if (sd20_mode) {
@@ -2378,16 +2844,16 @@ SD_UNLOCK_ENTRY:
                        retval = sd_switch_function(chip, switch_bus_width);
                        if (retval != STATUS_SUCCESS) {
                                sd_init_power(chip);
-                               sd_dont_switch = 1;
-                               try_sdio = 0;
+                               sd_dont_switch = true;
+                               try_sdio = false;
 
                                goto Switch_Fail;
                        }
                } else {
                        if (support_1v8) {
                                sd_init_power(chip);
-                               sd_dont_switch = 1;
-                               try_sdio = 0;
+                               sd_dont_switch = true;
+                               try_sdio = false;
 
                                goto Switch_Fail;
                        }
@@ -2397,13 +2863,17 @@ SD_UNLOCK_ENTRY:
        if (!support_1v8) {
                retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
                                        SD_RSP_TYPE_R1, NULL, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2,
                                        SD_RSP_TYPE_R1, NULL, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
 #ifdef SUPPORT_SD_LOCK
@@ -2413,12 +2883,18 @@ SD_UNLOCK_ENTRY:
        if (!sd20_mode && CHK_SD30_SPEED(sd_card)) {
                int read_lba0 = 1;
 
-               RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07,
-                       chip->sd30_drive_sel_1v8);
+               retval = rtsx_write_register(chip, SD30_DRIVE_SEL, 0x07,
+                                            chip->sd30_drive_sel_1v8);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
 
                retval = sd_set_init_para(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                if (CHK_SD_DDR50(sd_card))
                        retval = sd_ddr_tuning(chip);
@@ -2427,14 +2903,17 @@ SD_UNLOCK_ENTRY:
 
                if (retval != STATUS_SUCCESS) {
                        if (sd20_mode) {
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        } else {
                                retval = sd_init_power(chip);
-                               if (retval != STATUS_SUCCESS)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if (retval != STATUS_SUCCESS) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
 
-                               try_sdio = 0;
-                               sd20_mode = 1;
+                               try_sdio = false;
+                               sd20_mode = true;
                                goto Switch_Fail;
                        }
                }
@@ -2452,14 +2931,17 @@ SD_UNLOCK_ENTRY:
                        retval = sd_read_lba0(chip);
                        if (retval != STATUS_SUCCESS) {
                                if (sd20_mode) {
-                                       TRACE_RET(chip, STATUS_FAIL);
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
                                } else {
                                        retval = sd_init_power(chip);
-                                       if (retval != STATUS_SUCCESS)
-                                               TRACE_RET(chip, STATUS_FAIL);
+                                       if (retval != STATUS_SUCCESS) {
+                                               rtsx_trace(chip);
+                                               return STATUS_FAIL;
+                                       }
 
-                                       try_sdio = 0;
-                                       sd20_mode = 1;
+                                       try_sdio = false;
+                                       sd20_mode = true;
                                        goto Switch_Fail;
                                }
                        }
@@ -2467,15 +2949,27 @@ SD_UNLOCK_ENTRY:
        }
 
        retval = sd_check_wp_state(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
 
 #ifdef SUPPORT_SD_LOCK
        if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
-               RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_H, 0xFF, 0x02);
-               RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_L, 0xFF, 0x00);
+               retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_H, 0xFF,
+                                            0x02);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_L, 0xFF,
+                                            0x00);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        }
 #endif
 
@@ -2493,8 +2987,10 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
 
        retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL,
                                0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, SWITCH_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return SWITCH_FAIL;
+       }
 
        if (width == MMC_8BIT_BUS) {
                buf[0] = 0x55;
@@ -2510,20 +3006,25 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
        }
 
        retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0x02);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, SWITCH_ERR);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return SWITCH_ERR;
+       }
 
        retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3,
                        NULL, 0, byte_cnt, 1, bus_width, buf, len, 100);
        if (retval != STATUS_SUCCESS) {
                rtsx_clear_sd_error(chip);
                rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
-               TRACE_RET(chip, SWITCH_ERR);
+               rtsx_trace(chip);
+               return SWITCH_ERR;
        }
 
        retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, SWITCH_ERR);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return SWITCH_ERR;
+       }
 
        dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", BUSTEST_R);
 
@@ -2558,7 +3059,8 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
        retval = rtsx_send_cmd(chip, SD_CARD, 100);
        if (retval < 0) {
                rtsx_clear_sd_error(chip);
-               TRACE_RET(chip, SWITCH_ERR);
+               rtsx_trace(chip);
+               return SWITCH_ERR;
        }
 
        ptr = rtsx_get_cmd_data(chip) + 1;
@@ -2600,11 +3102,12 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
                }
        }
 
-       TRACE_RET(chip, SWITCH_FAIL);
+       rtsx_trace(chip);
+       return SWITCH_FAIL;
 }
 
 
-static int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr)
+static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        int retval;
@@ -2651,14 +3154,16 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr)
                        sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
                                        SD_RSP_TYPE_R1, NULL, 0);
                }
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        ptr = rtsx_get_cmd_data(chip);
        if (ptr[0] & SD_TRANSFER_ERR) {
                sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
                                SD_RSP_TYPE_R1, NULL, 0);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (CHK_MMC_SECTOR_MODE(sd_card)) {
@@ -2690,8 +3195,10 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr)
 
        sd_choose_proper_clock(chip);
        retval = switch_clock(chip, sd_card->sd_clock);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        /* Test Bus Procedure */
        retval = mmc_test_switch_bus(chip, MMC_8BIT_BUS);
@@ -2713,10 +3220,12 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr)
                        CLR_MMC_8BIT(sd_card);
                        CLR_MMC_4BIT(sd_card);
                } else {
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        } else {
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -2727,7 +3236,7 @@ static int reset_mmc(struct rtsx_chip *chip)
 {
        struct sd_info *sd_card = &(chip->sd_card);
        int retval, i = 0, j = 0, k = 0;
-       int switch_ddr = 1;
+       bool switch_ddr = true;
        u8 rsp[16];
        u8 spec_ver = 0;
        u32 temp;
@@ -2739,21 +3248,26 @@ static int reset_mmc(struct rtsx_chip *chip)
 
 Switch_Fail:
        retval = sd_prepare_reset(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, retval);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        SET_MMC(sd_card);
 
 RTY_MMC_RST:
        retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0,
                                NULL, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        do {
                if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
                        sd_set_err_code(chip, SD_NO_CARD);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                retval = sd_send_cmd_get_rsp(chip, SEND_OP_COND,
@@ -2767,7 +3281,8 @@ RTY_MMC_RST:
                                        sd_clr_err_code(chip);
                                        goto RTY_MMC_RST;
                                } else {
-                                       TRACE_RET(chip, STATUS_FAIL);
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
                                }
                        } else {
                                j++;
@@ -2775,7 +3290,8 @@ RTY_MMC_RST:
                                        sd_clr_err_code(chip);
                                        goto RTY_MMC_RST;
                                } else {
-                                       TRACE_RET(chip, STATUS_FAIL);
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
                                }
                        }
                }
@@ -2784,8 +3300,10 @@ RTY_MMC_RST:
                i++;
        } while (!(rsp[1] & 0x80) && (i < 255));
 
-       if (i == 255)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (i == 255) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if ((rsp[1] & 0x60) == 0x40)
                SET_MMC_SECTOR_MODE(sd_card);
@@ -2794,40 +3312,54 @@ RTY_MMC_RST:
 
        retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2,
                                NULL, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        sd_card->sd_addr = 0x00100000;
        retval = sd_send_cmd_get_rsp(chip, SET_RELATIVE_ADDR, sd_card->sd_addr,
                                SD_RSP_TYPE_R6, rsp, 5);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = sd_check_csd(chip, 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2;
 
        retval = sd_select_card(chip, 1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1,
                                NULL, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
 #ifdef SUPPORT_SD_LOCK
 MMC_UNLOCK_ENTRY:
        retval = sd_update_lock_status(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 #endif
 
        retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        chip->card_bus_width[chip->card2lun[SD_CARD]] = 1;
 
@@ -2837,29 +3369,39 @@ MMC_UNLOCK_ENTRY:
                        retval = mmc_switch_timing_bus(chip, switch_ddr);
                        if (retval != STATUS_SUCCESS) {
                                retval = sd_init_power(chip);
-                               if (retval != STATUS_SUCCESS)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if (retval != STATUS_SUCCESS) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
                                sd_card->mmc_dont_switch_bus = 1;
-                               TRACE_GOTO(chip, Switch_Fail);
+                               rtsx_trace(chip);
+                               goto Switch_Fail;
                        }
                }
 
-               if (CHK_MMC_SECTOR_MODE(sd_card) && (sd_card->capacity == 0))
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (CHK_MMC_SECTOR_MODE(sd_card) && (sd_card->capacity == 0)) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                if (switch_ddr && CHK_MMC_DDR52(sd_card)) {
                        retval = sd_set_init_para(chip);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        retval = mmc_ddr_tuning(chip);
                        if (retval != STATUS_SUCCESS) {
                                retval = sd_init_power(chip);
-                               if (retval != STATUS_SUCCESS)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if (retval != STATUS_SUCCESS) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
 
-                               switch_ddr = 0;
-                               TRACE_GOTO(chip, Switch_Fail);
+                               switch_ddr = false;
+                               rtsx_trace(chip);
+                               goto Switch_Fail;
                        }
 
                        retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
@@ -2867,11 +3409,14 @@ MMC_UNLOCK_ENTRY:
                                retval = sd_read_lba0(chip);
                                if (retval != STATUS_SUCCESS) {
                                        retval = sd_init_power(chip);
-                                       if (retval != STATUS_SUCCESS)
-                                               TRACE_RET(chip, STATUS_FAIL);
+                                       if (retval != STATUS_SUCCESS) {
+                                               rtsx_trace(chip);
+                                               return STATUS_FAIL;
+                                       }
 
-                                       switch_ddr = 0;
-                                       TRACE_GOTO(chip, Switch_Fail);
+                                       switch_ddr = false;
+                                       rtsx_trace(chip);
+                                       goto Switch_Fail;
                                }
                        }
                }
@@ -2879,8 +3424,18 @@ MMC_UNLOCK_ENTRY:
 
 #ifdef SUPPORT_SD_LOCK
        if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
-               RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_H, 0xFF, 0x02);
-               RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_L, 0xFF, 0x00);
+               retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_H, 0xFF,
+                                            0x02);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_L, 0xFF,
+                                            0x00);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        }
 #endif
 
@@ -2902,71 +3457,103 @@ int reset_sd_card(struct rtsx_chip *chip)
        chip->capacity[chip->card2lun[SD_CARD]] = 0;
 
        retval = enable_card_clock(chip, SD_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (chip->ignore_sd && CHK_SDIO_EXIST(chip) &&
                !CHK_SDIO_IGNORED(chip)) {
                if (chip->asic_code) {
                        retval = sd_pull_ctl_enable(chip);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                } else {
                        retval = rtsx_write_register(chip, FPGA_PULL_CTL,
                                                FPGA_SD_PULL_CTL_BIT | 0x20, 0);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                }
                retval = card_share_mode(chip, SD_CARD);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                chip->sd_io = 1;
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        retval = sd_init_power(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (chip->sd_ctl & RESET_MMC_FIRST) {
                retval = reset_mmc(chip);
                if (retval != STATUS_SUCCESS) {
-                       if (sd_check_err_code(chip, SD_NO_CARD))
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (sd_check_err_code(chip, SD_NO_CARD)) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        retval = reset_sd(chip);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                }
        } else {
                retval = reset_sd(chip);
                if (retval != STATUS_SUCCESS) {
-                       if (sd_check_err_code(chip, SD_NO_CARD))
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (sd_check_err_code(chip, SD_NO_CARD)) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        if (chip->sd_io) {
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        } else {
                                retval = reset_mmc(chip);
-                               if (retval != STATUS_SUCCESS)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if (retval != STATUS_SUCCESS) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
                        }
                }
        }
 
        retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
-       RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
+       retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
 
        retval = sd_set_init_para(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        dev_dbg(rtsx_dev(chip), "sd_card->sd_type = 0x%x\n", sd_card->sd_type);
 
@@ -2992,29 +3579,47 @@ static int reset_mmc_only(struct rtsx_chip *chip)
        chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity = 0;
 
        retval = enable_card_clock(chip, SD_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = sd_init_power(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = reset_mmc(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
-       RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
+       retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
 
        retval = sd_set_init_para(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        dev_dbg(rtsx_dev(chip), "In reset_mmc_only, sd_card->sd_type = 0x%x\n",
                sd_card->sd_type);
@@ -3032,15 +3637,18 @@ static int wait_data_buf_ready(struct rtsx_chip *chip)
        for (i = 0; i < WAIT_DATA_READY_RTY_CNT; i++) {
                if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
                        sd_set_err_code(chip, SD_NO_CARD);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                sd_card->sd_data_buf_ready = 0;
 
                retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
                                sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                if (sd_card->sd_data_buf_ready) {
                        return sd_send_cmd_get_rsp(chip, SEND_STATUS,
@@ -3050,7 +3658,8 @@ static int wait_data_buf_ready(struct rtsx_chip *chip)
 
        sd_set_err_code(chip, SD_TO_ERR);
 
-       TRACE_RET(chip, STATUS_FAIL);
+       rtsx_trace(chip);
+       return STATUS_FAIL;
 }
 
 void sd_stop_seq_mode(struct rtsx_chip *chip)
@@ -3118,8 +3727,10 @@ static inline int sd_auto_tune_clock(struct rtsx_chip *chip)
        }
 
        retval = sd_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -3156,7 +3767,8 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector,
                        chip->card_fail |= SD_CARD;
                        chip->capacity[chip->card2lun[SD_CARD]] = 0;
                        chip->rw_need_retry = 1;
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
@@ -3170,7 +3782,8 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector,
        retval = sd_switch_clock(chip);
        if (retval != STATUS_SUCCESS) {
                sd_set_err_code(chip, SD_IO_ERR);
-               TRACE_GOTO(chip, RW_FAIL);
+               rtsx_trace(chip);
+               goto RW_FAIL;
        }
 
        if (sd_card->seq_mode &&
@@ -3191,7 +3804,8 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector,
                if (retval != STATUS_SUCCESS) {
                        chip->rw_need_retry = 1;
                        sd_set_err_code(chip, SD_STS_ERR);
-                       TRACE_GOTO(chip, RW_FAIL);
+                       rtsx_trace(chip);
+                       goto RW_FAIL;
                }
 
                sd_card->seq_mode = 0;
@@ -3199,7 +3813,8 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector,
                retval = rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
                if (retval != STATUS_SUCCESS) {
                        sd_set_err_code(chip, SD_IO_ERR);
-                       TRACE_GOTO(chip, RW_FAIL);
+                       rtsx_trace(chip);
+                       goto RW_FAIL;
                }
 
                if ((sd_card->pre_sec_cnt < 0x80)
@@ -3290,21 +3905,24 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector,
 
                                chip->rw_need_retry = 1;
                                sd_set_err_code(chip, SD_TO_ERR);
-                               TRACE_GOTO(chip, RW_FAIL);
+                               rtsx_trace(chip);
+                               goto RW_FAIL;
                        }
 
                        retval = wait_data_buf_ready(chip);
                        if (retval != STATUS_SUCCESS) {
                                chip->rw_need_retry = 1;
                                sd_set_err_code(chip, SD_TO_ERR);
-                               TRACE_GOTO(chip, RW_FAIL);
+                               rtsx_trace(chip);
+                               goto RW_FAIL;
                        }
 
                        retval = sd_send_cmd_get_rsp(chip, WRITE_MULTIPLE_BLOCK,
                                        data_addr, SD_RSP_TYPE_R1, NULL, 0);
                        if (retval != STATUS_SUCCESS) {
                                chip->rw_need_retry = 1;
-                               TRACE_GOTO(chip, RW_FAIL);
+                               rtsx_trace(chip);
+                               goto RW_FAIL;
                        }
 
                        rtsx_init_cmd(chip);
@@ -3348,7 +3966,8 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector,
                if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
                        chip->rw_need_retry = 0;
                        dev_dbg(rtsx_dev(chip), "No card exist, exit sd_rw\n");
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                chip->rw_need_retry = 1;
@@ -3357,21 +3976,25 @@ int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector,
                                        SD_RSP_TYPE_R1b, NULL, 0);
                if (retval != STATUS_SUCCESS) {
                        sd_set_err_code(chip, SD_STS_ERR);
-                       TRACE_GOTO(chip, RW_FAIL);
+                       rtsx_trace(chip);
+                       goto RW_FAIL;
                }
 
                if (stat & (SD_CRC7_ERR | SD_CRC16_ERR | SD_CRC_WRITE_ERR)) {
                        dev_dbg(rtsx_dev(chip), "SD CRC error, tune clock!\n");
                        sd_set_err_code(chip, SD_CRC_ERR);
-                       TRACE_GOTO(chip, RW_FAIL);
+                       rtsx_trace(chip);
+                       goto RW_FAIL;
                }
 
                if (err == STATUS_TIMEDOUT) {
                        sd_set_err_code(chip, SD_TO_ERR);
-                       TRACE_GOTO(chip, RW_FAIL);
+                       rtsx_trace(chip);
+                       goto RW_FAIL;
                }
 
-               TRACE_RET(chip, err);
+               rtsx_trace(chip);
+               return err;
        }
 
        sd_card->pre_sec_addr = start_sector;
@@ -3386,7 +4009,8 @@ RW_FAIL:
        if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
                chip->rw_need_retry = 0;
                dev_dbg(rtsx_dev(chip), "No card exist, exit sd_rw\n");
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (sd_check_err_code(chip, SD_CRC_ERR)) {
@@ -3407,7 +4031,8 @@ RW_FAIL:
                }
        }
 
-       TRACE_RET(chip, STATUS_FAIL);
+       rtsx_trace(chip);
+       return STATUS_FAIL;
 }
 
 #ifdef SUPPORT_CPRM
@@ -3417,7 +4042,7 @@ int soft_reset_sd_card(struct rtsx_chip *chip)
 }
 
 int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
-               u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, int special_check)
+               u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, bool special_check)
 {
        int retval;
        int timeout = 100;
@@ -3473,13 +4098,16 @@ RTY_SEND_CMD:
 
                        if (rsp_type & SD_WAIT_BUSY_END) {
                                retval = sd_check_data0_status(chip);
-                               if (retval != STATUS_SUCCESS)
-                                       TRACE_RET(chip, retval);
+                               if (retval != STATUS_SUCCESS) {
+                                       rtsx_trace(chip);
+                                       return retval;
+                               }
                        } else {
                                sd_set_err_code(chip, SD_TO_ERR);
                        }
                }
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (rsp_type == SD_RSP_TYPE_R0)
@@ -3489,14 +4117,16 @@ RTY_SEND_CMD:
 
        if ((ptr[0] & 0xC0) != 0) {
                sd_set_err_code(chip, SD_STS_ERR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (!(rsp_type & SD_NO_CHECK_CRC7)) {
                if (ptr[stat_idx] & SD_CRC7_ERR) {
                        if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
                                sd_set_err_code(chip, SD_CRC_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        if (rty_cnt < SD_MAX_RETRY_COUNT) {
                                wait_timeout(20);
@@ -3504,16 +4134,19 @@ RTY_SEND_CMD:
                                goto RTY_SEND_CMD;
                        } else {
                                sd_set_err_code(chip, SD_CRC_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
        }
 
        if ((cmd_idx == SELECT_CARD) || (cmd_idx == APP_CMD) ||
                (cmd_idx == SEND_STATUS) || (cmd_idx == STOP_TRANSMISSION)) {
-               if ((cmd_idx != STOP_TRANSMISSION) && (special_check == 0)) {
-                       if (ptr[1] & 0x80)
-                               TRACE_RET(chip, STATUS_FAIL);
+               if ((cmd_idx != STOP_TRANSMISSION) && !special_check) {
+                       if (ptr[1] & 0x80) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                }
 #ifdef SUPPORT_SD_LOCK
                if (ptr[1] & 0x7D)
@@ -3521,19 +4154,26 @@ RTY_SEND_CMD:
                if (ptr[1] & 0x7F)
 #endif
                {
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
+               if (ptr[2] & 0xF8) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
-               if (ptr[2] & 0xF8)
-                       TRACE_RET(chip, STATUS_FAIL);
 
                if (cmd_idx == SELECT_CARD) {
                        if (rsp_type == SD_RSP_TYPE_R2) {
-                               if ((ptr[3] & 0x1E) != 0x04)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if ((ptr[3] & 0x1E) != 0x04) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
 
                        } else if (rsp_type == SD_RSP_TYPE_R0) {
-                               if ((ptr[3] & 0x1E) != 0x03)
-                                       TRACE_RET(chip, STATUS_FAIL);
+                               if ((ptr[3] & 0x1E) != 0x03) {
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
+                               }
                        }
                }
        }
@@ -3570,8 +4210,10 @@ int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type)
        rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0xFF, 0);
 
        retval = rtsx_send_cmd(chip, SD_CARD, 100);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (rsp) {
                int min_len = (rsp_len < len) ? rsp_len : len;
@@ -3617,7 +4259,8 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (!(CHK_BIT(chip->lun_mc, lun))) {
                SET_BIT(chip->lun_mc, lun);
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) ||
@@ -3625,7 +4268,8 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7]) ||
                (0x64 != srb->cmnd[8])) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        switch (srb->cmnd[1] & 0x0F) {
@@ -3639,7 +4283,8 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        default:
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        buf[5] = (1 == CHK_SD(sd_card)) ?  0x01 : 0x02;
@@ -3702,30 +4347,34 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        unsigned int lun = SCSI_LUN(srb);
        int retval, rsp_len;
        u8 cmd_idx, rsp_type;
-       u8 standby = 0, acmd = 0;
+       bool standby = false, acmd = false;
        u32 arg;
 
        if (!sd_card->sd_pass_thru_en) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        retval = sd_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, TRANSPORT_FAILED);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
+       }
 
        if (sd_card->pre_cmd_err) {
                sd_card->pre_cmd_err = 0;
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        cmd_idx = srb->cmnd[2] & 0x3F;
        if (srb->cmnd[1] & 0x02)
-               standby = 1;
+               standby = true;
 
        if (srb->cmnd[1] & 0x01)
-               acmd = 1;
+               acmd = true;
 
        arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) |
                ((u32)srb->cmnd[5] << 8) | srb->cmnd[6];
@@ -3733,64 +4382,83 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = get_rsp_type(srb, &rsp_type, &rsp_len);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
        sd_card->last_rsp_type = rsp_type;
 
        retval = sd_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, TRANSPORT_FAILED);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
+       }
 
 #ifdef SUPPORT_SD_LOCK
        if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
                if (CHK_MMC_8BIT(sd_card)) {
                        retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
                                                SD_BUS_WIDTH_8);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
+                       }
 
                } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
                        retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
                                                SD_BUS_WIDTH_4);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
+                       }
                }
        }
 #else
        retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, TRANSPORT_FAILED);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
+       }
 #endif
 
        if (standby) {
                retval = sd_select_card(chip, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Cmd_Failed;
+               }
        }
 
        if (acmd) {
                retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD,
                                                sd_card->sd_addr,
-                                               SD_RSP_TYPE_R1, NULL, 0, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
+                                               SD_RSP_TYPE_R1, NULL, 0, false);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Cmd_Failed;
+               }
        }
 
        retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
-                       sd_card->rsp, rsp_len, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
+                       sd_card->rsp, rsp_len, false);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               goto SD_Execute_Cmd_Failed;
+       }
 
        if (standby) {
                retval = sd_select_card(chip, 1);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Cmd_Failed;
+               }
        }
 
 #ifdef SUPPORT_SD_LOCK
        retval = sd_update_lock_status(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               goto SD_Execute_Cmd_Failed;
+       }
 #endif
 
        scsi_set_resid(srb, 0);
@@ -3804,7 +4472,8 @@ SD_Execute_Cmd_Failed:
        if (!(chip->card_ready & SD_CARD))
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 
-       TRACE_RET(chip, TRANSPORT_FAILED);
+       rtsx_trace(chip);
+       return TRANSPORT_FAILED;
 }
 
 int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
@@ -3812,35 +4481,39 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        struct sd_info *sd_card = &(chip->sd_card);
        unsigned int lun = SCSI_LUN(srb);
        int retval, rsp_len, i;
-       int cmd13_checkbit = 0, read_err = 0;
+       bool read_err = false, cmd13_checkbit = false;
        u8 cmd_idx, rsp_type, bus_width;
-       u8 send_cmd12 = 0, standby = 0, acmd = 0;
+       bool standby = false, send_cmd12 = false, acmd = false;
        u32 data_len;
 
        if (!sd_card->sd_pass_thru_en) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (sd_card->pre_cmd_err) {
                sd_card->pre_cmd_err = 0;
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        retval = sd_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, TRANSPORT_FAILED);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
+       }
 
        cmd_idx = srb->cmnd[2] & 0x3F;
        if (srb->cmnd[1] & 0x04)
-               send_cmd12 = 1;
+               send_cmd12 = true;
 
        if (srb->cmnd[1] & 0x02)
-               standby = 1;
+               standby = true;
 
        if (srb->cmnd[1] & 0x01)
-               acmd = 1;
+               acmd = true;
 
        data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8]
                                                << 8) | srb->cmnd[9];
@@ -3848,13 +4521,16 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = get_rsp_type(srb, &rsp_type, &rsp_len);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
        sd_card->last_rsp_type = rsp_type;
 
        retval = sd_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, TRANSPORT_FAILED);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
+       }
 
 #ifdef SUPPORT_SD_LOCK
        if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
@@ -3874,23 +4550,29 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (data_len < 512) {
                retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
-                               SD_RSP_TYPE_R1, NULL, 0, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+                               SD_RSP_TYPE_R1, NULL, 0, false);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Read_Cmd_Failed;
+               }
        }
 
        if (standby) {
                retval = sd_select_card(chip, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Read_Cmd_Failed;
+               }
        }
 
        if (acmd) {
                retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD,
                                                sd_card->sd_addr,
-                                               SD_RSP_TYPE_R1, NULL, 0, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+                                               SD_RSP_TYPE_R1, NULL, 0, false);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Read_Cmd_Failed;
+               }
        }
 
        if (data_len <= 512) {
@@ -3909,16 +4591,19 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                cmd[4] = srb->cmnd[6];
 
                buf = kmalloc(data_len, GFP_KERNEL);
-               if (buf == NULL)
-                       TRACE_RET(chip, TRANSPORT_ERROR);
+               if (buf == NULL) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_ERROR;
+               }
 
                retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt,
                                       blk_cnt, bus_width, buf, data_len, 2000);
                if (retval != STATUS_SUCCESS) {
-                       read_err = 1;
+                       read_err = true;
                        kfree(buf);
                        rtsx_clear_sd_error(chip);
-                       TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+                       rtsx_trace(chip);
+                       goto SD_Execute_Read_Cmd_Failed;
                }
 
                min_len = min(data_len, scsi_bufflen(srb));
@@ -3964,49 +4649,63 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                        scsi_bufflen(srb), scsi_sg_count(srb),
                                        DMA_FROM_DEVICE, 10000);
                if (retval < 0) {
-                       read_err = 1;
+                       read_err = true;
                        rtsx_clear_sd_error(chip);
-                       TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+                       rtsx_trace(chip);
+                       goto SD_Execute_Read_Cmd_Failed;
                }
 
        } else {
-               TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+               rtsx_trace(chip);
+               goto SD_Execute_Read_Cmd_Failed;
        }
 
        retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type);
-       if (retval != STATUS_SUCCESS)
-               TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               goto SD_Execute_Read_Cmd_Failed;
+       }
 
        if (standby) {
                retval = sd_select_card(chip, 1);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Read_Cmd_Failed;
+               }
        }
 
        if (send_cmd12) {
                retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
-                               0, SD_RSP_TYPE_R1b, NULL, 0, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+                               0, SD_RSP_TYPE_R1b, NULL, 0, false);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Read_Cmd_Failed;
+               }
        }
 
        if (data_len < 512) {
                retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
-                               SD_RSP_TYPE_R1, NULL, 0, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+                               SD_RSP_TYPE_R1, NULL, 0, false);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Read_Cmd_Failed;
+               }
 
                retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Read_Cmd_Failed;
+               }
 
                retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Read_Cmd_Failed;
+               }
        }
 
        if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04))
-               cmd13_checkbit = 1;
+               cmd13_checkbit = true;
 
        for (i = 0; i < 3; i++) {
                retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS,
@@ -4016,8 +4715,10 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (retval != STATUS_SUCCESS)
-               TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               goto SD_Execute_Read_Cmd_Failed;
+       }
 
        scsi_set_resid(srb, 0);
        return TRANSPORT_GOOD;
@@ -4033,7 +4734,8 @@ SD_Execute_Read_Cmd_Failed:
        if (!(chip->card_ready & SD_CARD))
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 
-       TRACE_RET(chip, TRANSPORT_FAILED);
+       rtsx_trace(chip);
+       return TRANSPORT_FAILED;
 }
 
 int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
@@ -4041,9 +4743,9 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        struct sd_info *sd_card = &(chip->sd_card);
        unsigned int lun = SCSI_LUN(srb);
        int retval, rsp_len, i;
-       int cmd13_checkbit = 0, write_err = 0;
+       bool write_err = false, cmd13_checkbit = false;
        u8 cmd_idx, rsp_type;
-       u8 send_cmd12 = 0, standby = 0, acmd = 0;
+       bool standby = false, send_cmd12 = false, acmd = false;
        u32 data_len, arg;
 #ifdef SUPPORT_SD_LOCK
        int lock_cmd_fail = 0;
@@ -4053,28 +4755,32 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (!sd_card->sd_pass_thru_en) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (sd_card->pre_cmd_err) {
                sd_card->pre_cmd_err = 0;
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        retval = sd_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, TRANSPORT_FAILED);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
+       }
 
        cmd_idx = srb->cmnd[2] & 0x3F;
        if (srb->cmnd[1] & 0x04)
-               send_cmd12 = 1;
+               send_cmd12 = true;
 
        if (srb->cmnd[1] & 0x02)
-               standby = 1;
+               standby = true;
 
        if (srb->cmnd[1] & 0x01)
-               acmd = 1;
+               acmd = true;
 
        data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8]
                                                << 8) | srb->cmnd[9];
@@ -4091,68 +4797,87 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = get_rsp_type(srb, &rsp_type, &rsp_len);
        if (retval != STATUS_SUCCESS) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
        sd_card->last_rsp_type = rsp_type;
 
        retval = sd_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, TRANSPORT_FAILED);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
+       }
 
 #ifdef SUPPORT_SD_LOCK
        if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
                if (CHK_MMC_8BIT(sd_card)) {
                        retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
                                                SD_BUS_WIDTH_8);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
+                       }
 
                } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
                        retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
                                                SD_BUS_WIDTH_4);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, TRANSPORT_FAILED);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return TRANSPORT_FAILED;
+                       }
                }
        }
 #else
        retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, TRANSPORT_FAILED);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
+       }
 #endif
 
        if (data_len < 512) {
                retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
-                               SD_RSP_TYPE_R1, NULL, 0, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+                               SD_RSP_TYPE_R1, NULL, 0, false);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Write_Cmd_Failed;
+               }
        }
 
        if (standby) {
                retval = sd_select_card(chip, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Write_Cmd_Failed;
+               }
        }
 
        if (acmd) {
                retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD,
                                                sd_card->sd_addr,
-                                               SD_RSP_TYPE_R1, NULL, 0, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+                                               SD_RSP_TYPE_R1, NULL, 0, false);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Write_Cmd_Failed;
+               }
        }
 
        retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
-                       sd_card->rsp, rsp_len, 0);
-       if (retval != STATUS_SUCCESS)
-               TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+                       sd_card->rsp, rsp_len, false);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               goto SD_Execute_Write_Cmd_Failed;
+       }
 
        if (data_len <= 512) {
                u16 i;
                u8 *buf;
 
                buf = kmalloc(data_len, GFP_KERNEL);
-               if (buf == NULL)
-                       TRACE_RET(chip, TRANSPORT_ERROR);
+               if (buf == NULL) {
+                       rtsx_trace(chip);
+                       return TRANSPORT_ERROR;
+               }
 
                rtsx_stor_get_xfer_buf(buf, data_len, srb);
 
@@ -4170,7 +4895,8 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        retval = rtsx_send_cmd(chip, 0, 250);
                        if (retval != STATUS_SUCCESS) {
                                kfree(buf);
-                               TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+                               rtsx_trace(chip);
+                               goto SD_Execute_Write_Cmd_Failed;
                        }
 
                        rtsx_init_cmd(chip);
@@ -4181,7 +4907,8 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        retval = rtsx_send_cmd(chip, 0, 250);
                        if (retval != STATUS_SUCCESS) {
                                kfree(buf);
-                               TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+                               rtsx_trace(chip);
+                               goto SD_Execute_Write_Cmd_Failed;
                        }
                } else {
                        rtsx_init_cmd(chip);
@@ -4192,7 +4919,8 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        retval = rtsx_send_cmd(chip, 0, 250);
                        if (retval != STATUS_SUCCESS) {
                                kfree(buf);
-                               TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+                               rtsx_trace(chip);
+                               goto SD_Execute_Write_Cmd_Failed;
                        }
                }
 
@@ -4243,13 +4971,15 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                        DMA_TO_DEVICE, 10000);
 
        } else {
-               TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+               rtsx_trace(chip);
+               goto SD_Execute_Write_Cmd_Failed;
        }
 
        if (retval < 0) {
-               write_err = 1;
+               write_err = true;
                rtsx_clear_sd_error(chip);
-               TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+               rtsx_trace(chip);
+               goto SD_Execute_Write_Cmd_Failed;
        }
 
 #ifdef SUPPORT_SD_LOCK
@@ -4275,34 +5005,44 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (standby) {
                retval = sd_select_card(chip, 1);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Write_Cmd_Failed;
+               }
        }
 
        if (send_cmd12) {
                retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
-                               0, SD_RSP_TYPE_R1b, NULL, 0, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+                               0, SD_RSP_TYPE_R1b, NULL, 0, false);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Write_Cmd_Failed;
+               }
        }
 
        if (data_len < 512) {
                retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
-                               SD_RSP_TYPE_R1, NULL, 0, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+                               SD_RSP_TYPE_R1, NULL, 0, false);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Write_Cmd_Failed;
+               }
 
                retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Write_Cmd_Failed;
+               }
 
                rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       goto SD_Execute_Write_Cmd_Failed;
+               }
        }
 
        if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04))
-               cmd13_checkbit = 1;
+               cmd13_checkbit = true;
 
        for (i = 0; i < 3; i++) {
                retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS,
@@ -4312,8 +5052,10 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                if (retval == STATUS_SUCCESS)
                        break;
        }
-       if (retval != STATUS_SUCCESS)
-               TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               goto SD_Execute_Write_Cmd_Failed;
+       }
 
 #ifdef SUPPORT_SD_LOCK
        if (cmd_idx == LOCK_UNLOCK) {
@@ -4339,7 +5081,8 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                                retval = reset_sd(chip);
                                                if (retval != STATUS_SUCCESS) {
                                                        sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
-                                                       TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+                                                       rtsx_trace(chip);
+                                                       goto SD_Execute_Write_Cmd_Failed;
                                                }
                                        }
 
@@ -4352,7 +5095,8 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (lock_cmd_fail) {
                scsi_set_resid(srb, 0);
                set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 #endif  /* SUPPORT_SD_LOCK */
 
@@ -4370,7 +5114,8 @@ SD_Execute_Write_Cmd_Failed:
        if (!(chip->card_ready & SD_CARD))
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 
-       TRACE_RET(chip, TRANSPORT_FAILED);
+       rtsx_trace(chip);
+       return TRANSPORT_FAILED;
 }
 
 int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
@@ -4382,20 +5127,23 @@ int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (!sd_card->sd_pass_thru_en) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (sd_card->pre_cmd_err) {
                sd_card->pre_cmd_err = 0;
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        data_len = ((u16)srb->cmnd[7] << 8) | srb->cmnd[8];
 
        if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        } else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) {
                count = (data_len < 17) ? data_len : 17;
        } else {
@@ -4420,13 +5168,15 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 
        if (!sd_card->sd_pass_thru_en) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if (sd_card->pre_cmd_err) {
                sd_card->pre_cmd_err = 0;
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) ||
@@ -4434,7 +5184,8 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7]) ||
                (0x64 != srb->cmnd[8])) {
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        switch (srb->cmnd[1] & 0x0F) {
@@ -4450,7 +5201,8 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip)
 #endif
                        set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                        sd_card->pre_cmd_err = 1;
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
 #ifdef SUPPORT_SD_LOCK
                sd_card->sd_lock_status &= ~SD_SDR_RST;
@@ -4462,13 +5214,15 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                if (retval != STATUS_SUCCESS) {
                        set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
                        sd_card->pre_cmd_err = 1;
-                       TRACE_RET(chip, TRANSPORT_FAILED);
+                       rtsx_trace(chip);
+                       return TRANSPORT_FAILED;
                }
                break;
 
        default:
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-               TRACE_RET(chip, TRANSPORT_FAILED);
+               rtsx_trace(chip);
+               return TRANSPORT_FAILED;
        }
 
        scsi_set_resid(srb, 0);
@@ -4492,26 +5246,41 @@ int sd_power_off_card3v3(struct rtsx_chip *chip)
        int retval;
 
        retval = disable_card_clock(chip, SD_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, 0);
+       retval = rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        if (!chip->ft2_fast_mode) {
                retval = card_power_off(chip, SD_CARD);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                wait_timeout(50);
        }
 
        if (chip->asic_code) {
                retval = sd_pull_ctl_disable(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        } else {
-               RTSX_WRITE_REG(chip, FPGA_PULL_CTL,
-                       FPGA_SD_PULL_CTL_BIT | 0x20, FPGA_SD_PULL_CTL_BIT);
+               retval = rtsx_write_register(chip, FPGA_PULL_CTL,
+                                            FPGA_SD_PULL_CTL_BIT | 0x20,
+                                            FPGA_SD_PULL_CTL_BIT);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -4538,8 +5307,10 @@ int release_sd_card(struct rtsx_chip *chip)
        memset(sd_card->raw_scr, 0, 8);
 
        retval = sd_power_off_card3v3(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
index 735b2d0f5a7897d99744ad30f0460023a0338174..60b79280fb5f909114e2477725cbd130219f3511 100644 (file)
@@ -287,7 +287,7 @@ int release_sd_card(struct rtsx_chip *chip);
 #ifdef SUPPORT_CPRM
 int soft_reset_sd_card(struct rtsx_chip *chip);
 int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
-               u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, int special_check);
+               u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, bool special_check);
 int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type);
 
 int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip);
index 29f4a80844fa61f8440975a7da2c6e9d7087f17f..e67e7ecc2cbd6fdb082d1c364b73f9fe8f9117cd 100644 (file)
@@ -25,9 +25,6 @@
 #include <linux/sched.h>
 
 #include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
 #include "spi.h"
 
 static inline void spi_set_err_code(struct rtsx_chip *chip, u8 err_code)
@@ -39,10 +36,20 @@ static inline void spi_set_err_code(struct rtsx_chip *chip, u8 err_code)
 
 static int spi_init(struct rtsx_chip *chip)
 {
-       RTSX_WRITE_REG(chip, SPI_CONTROL, 0xFF,
-               CS_POLARITY_LOW | DTO_MSB_FIRST | SPI_MASTER | SPI_MODE0 |
-               SPI_AUTO);
-       RTSX_WRITE_REG(chip, SPI_TCTL, EDO_TIMING_MASK, SAMPLE_DELAY_HALF);
+       int retval;
+
+       retval = rtsx_write_register(chip, SPI_CONTROL, 0xFF,
+                                    CS_POLARITY_LOW | DTO_MSB_FIRST | SPI_MASTER | SPI_MODE0 | SPI_AUTO);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, SPI_TCTL, EDO_TIMING_MASK,
+                                    SAMPLE_DELAY_HALF);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -52,25 +59,51 @@ static int spi_set_init_para(struct rtsx_chip *chip)
        struct spi_info *spi = &(chip->spi);
        int retval;
 
-       RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER1, 0xFF, (u8)(spi->clk_div >> 8));
-       RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER0, 0xFF, (u8)(spi->clk_div));
+       retval = rtsx_write_register(chip, SPI_CLK_DIVIDER1, 0xFF,
+                                    (u8)(spi->clk_div >> 8));
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, SPI_CLK_DIVIDER0, 0xFF,
+                                    (u8)(spi->clk_div));
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        retval = switch_clock(chip, spi->spi_clock);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = select_card(chip, SPI_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_WRITE_REG(chip, CARD_CLK_EN, SPI_CLK_EN, SPI_CLK_EN);
-       RTSX_WRITE_REG(chip, CARD_OE, SPI_OUTPUT_EN, SPI_OUTPUT_EN);
+       retval = rtsx_write_register(chip, CARD_CLK_EN, SPI_CLK_EN,
+                                    SPI_CLK_EN);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, CARD_OE, SPI_OUTPUT_EN,
+                                    SPI_OUTPUT_EN);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        wait_timeout(10);
 
        retval = spi_init(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -91,7 +124,8 @@ static int sf_polling_status(struct rtsx_chip *chip, int msec)
        if (retval < 0) {
                rtsx_clear_spi_error(chip);
                spi_set_err_code(chip, SPI_BUSY_ERR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -119,7 +153,8 @@ static int sf_enable_write(struct rtsx_chip *chip, u8 ins)
        if (retval < 0) {
                rtsx_clear_spi_error(chip);
                spi_set_err_code(chip, SPI_HW_ERR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -147,7 +182,8 @@ static int sf_disable_write(struct rtsx_chip *chip, u8 ins)
        if (retval < 0) {
                rtsx_clear_spi_error(chip);
                spi_set_err_code(chip, SPI_HW_ERR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -205,7 +241,8 @@ static int sf_erase(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr)
        if (retval < 0) {
                rtsx_clear_spi_error(chip);
                spi_set_err_code(chip, SPI_HW_ERR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -221,25 +258,56 @@ static int spi_init_eeprom(struct rtsx_chip *chip)
        else
                clk = CLK_30;
 
-       RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER1, 0xFF, 0x00);
-       RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER0, 0xFF, 0x27);
+       retval = rtsx_write_register(chip, SPI_CLK_DIVIDER1, 0xFF, 0x00);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, SPI_CLK_DIVIDER0, 0xFF, 0x27);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        retval = switch_clock(chip, clk);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = select_card(chip, SPI_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_WRITE_REG(chip, CARD_CLK_EN, SPI_CLK_EN, SPI_CLK_EN);
-       RTSX_WRITE_REG(chip, CARD_OE, SPI_OUTPUT_EN, SPI_OUTPUT_EN);
+       retval = rtsx_write_register(chip, CARD_CLK_EN, SPI_CLK_EN,
+                                    SPI_CLK_EN);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, CARD_OE, SPI_OUTPUT_EN,
+                                    SPI_OUTPUT_EN);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        wait_timeout(10);
 
-       RTSX_WRITE_REG(chip, SPI_CONTROL, 0xFF,
-               CS_POLARITY_HIGH | SPI_EEPROM_AUTO);
-       RTSX_WRITE_REG(chip, SPI_TCTL, EDO_TIMING_MASK, SAMPLE_DELAY_HALF);
+       retval = rtsx_write_register(chip, SPI_CONTROL, 0xFF,
+                                    CS_POLARITY_HIGH | SPI_EEPROM_AUTO);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
+       retval = rtsx_write_register(chip, SPI_TCTL, EDO_TIMING_MASK,
+                                    SAMPLE_DELAY_HALF);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -258,8 +326,10 @@ static int spi_eeprom_program_enable(struct rtsx_chip *chip)
                SPI_TRANSFER0_END);
 
        retval = rtsx_send_cmd(chip, 0, 100);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -269,12 +339,16 @@ int spi_erase_eeprom_chip(struct rtsx_chip *chip)
        int retval;
 
        retval = spi_init_eeprom(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = spi_eeprom_program_enable(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -288,10 +362,16 @@ int spi_erase_eeprom_chip(struct rtsx_chip *chip)
                SPI_TRANSFER0_END);
 
        retval = rtsx_send_cmd(chip, 0, 100);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
+       retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -301,12 +381,16 @@ int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr)
        int retval;
 
        retval = spi_init_eeprom(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = spi_eeprom_program_enable(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -322,10 +406,16 @@ int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr)
                SPI_TRANSFER0_END);
 
        retval = rtsx_send_cmd(chip, 0, 100);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
+       retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -337,8 +427,10 @@ int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val)
        u8 data;
 
        retval = spi_init_eeprom(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -355,16 +447,26 @@ int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val)
                SPI_TRANSFER0_END);
 
        retval = rtsx_send_cmd(chip, 0, 100);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        wait_timeout(5);
-       RTSX_READ_REG(chip, SPI_DATA, &data);
+       retval = rtsx_read_register(chip, SPI_DATA, &data);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        if (val)
                *val = data;
 
-       RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
+       retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -374,12 +476,16 @@ int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val)
        int retval;
 
        retval = spi_init_eeprom(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = spi_eeprom_program_enable(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -396,10 +502,16 @@ int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val)
                SPI_TRANSFER0_END);
 
        retval = rtsx_send_cmd(chip, 0, 100);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
+       retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -449,13 +561,15 @@ int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
        if (len > 512) {
                spi_set_err_code(chip, SPI_INVALID_COMMAND);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        retval = spi_set_init_para(chip);
        if (retval != STATUS_SUCCESS) {
                spi_set_err_code(chip, SPI_HW_ERR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        rtsx_init_cmd(chip);
@@ -497,19 +611,23 @@ int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (retval < 0) {
                rtsx_clear_spi_error(chip);
                spi_set_err_code(chip, SPI_HW_ERR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (len) {
                buf = kmalloc(len, GFP_KERNEL);
-               if (!buf)
-                       TRACE_RET(chip, STATUS_ERROR);
+               if (!buf) {
+                       rtsx_trace(chip);
+                       return STATUS_ERROR;
+               }
 
                retval = rtsx_read_ppbuf(chip, buf, len);
                if (retval != STATUS_SUCCESS) {
                        spi_set_err_code(chip, SPI_READ_ERR);
                        kfree(buf);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
@@ -541,12 +659,15 @@ int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = spi_set_init_para(chip);
        if (retval != STATUS_SUCCESS) {
                spi_set_err_code(chip, SPI_HW_ERR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL);
-       if (buf == NULL)
-               TRACE_RET(chip, STATUS_ERROR);
+       if (buf == NULL) {
+               rtsx_trace(chip);
+               return STATUS_ERROR;
+       }
 
        while (len) {
                u16 pagelen = SF_PAGE_LEN - (u8)addr;
@@ -598,7 +719,8 @@ int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        kfree(buf);
                        rtsx_clear_spi_error(chip);
                        spi_set_err_code(chip, SPI_HW_ERR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, &offset,
@@ -634,19 +756,23 @@ int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = spi_set_init_para(chip);
        if (retval != STATUS_SUCCESS) {
                spi_set_err_code(chip, SPI_HW_ERR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (program_mode == BYTE_PROGRAM) {
                buf = kmalloc(4, GFP_KERNEL);
-               if (!buf)
-                       TRACE_RET(chip, STATUS_ERROR);
+               if (!buf) {
+                       rtsx_trace(chip);
+                       return STATUS_ERROR;
+               }
 
                while (len) {
                        retval = sf_enable_write(chip, SPI_WREN);
                        if (retval != STATUS_SUCCESS) {
                                kfree(buf);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset,
@@ -665,13 +791,15 @@ int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                kfree(buf);
                                rtsx_clear_spi_error(chip);
                                spi_set_err_code(chip, SPI_HW_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        retval = sf_polling_status(chip, 100);
                        if (retval != STATUS_SUCCESS) {
                                kfree(buf);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        addr++;
@@ -684,12 +812,16 @@ int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                int first_byte = 1;
 
                retval = sf_enable_write(chip, SPI_WREN);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                buf = kmalloc(4, GFP_KERNEL);
-               if (!buf)
-                       TRACE_RET(chip, STATUS_ERROR);
+               if (!buf) {
+                       rtsx_trace(chip);
+                       return STATUS_ERROR;
+               }
 
                while (len) {
                        rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset,
@@ -713,13 +845,15 @@ int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                kfree(buf);
                                rtsx_clear_spi_error(chip);
                                spi_set_err_code(chip, SPI_HW_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        retval = sf_polling_status(chip, 100);
                        if (retval != STATUS_SUCCESS) {
                                kfree(buf);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        len--;
@@ -728,16 +862,22 @@ int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                kfree(buf);
 
                retval = sf_disable_write(chip, SPI_WRDI);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = sf_polling_status(chip, 100);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        } else if (program_mode == PAGE_PROGRAM) {
                buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL);
-               if (!buf)
-                       TRACE_RET(chip, STATUS_NOMEM);
+               if (!buf) {
+                       rtsx_trace(chip);
+                       return STATUS_NOMEM;
+               }
 
                while (len) {
                        u16 pagelen = SF_PAGE_LEN - (u8)addr;
@@ -748,7 +888,8 @@ int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                        retval = sf_enable_write(chip, SPI_WREN);
                        if (retval != STATUS_SUCCESS) {
                                kfree(buf);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        rtsx_init_cmd(chip);
@@ -767,13 +908,15 @@ int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                                kfree(buf);
                                rtsx_clear_spi_error(chip);
                                spi_set_err_code(chip, SPI_HW_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        retval = sf_polling_status(chip, 100);
                        if (retval != STATUS_SUCCESS) {
                                kfree(buf);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        addr += pagelen;
@@ -783,7 +926,8 @@ int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
                kfree(buf);
        } else {
                spi_set_err_code(chip, SPI_INVALID_COMMAND);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -805,28 +949,38 @@ int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = spi_set_init_para(chip);
        if (retval != STATUS_SUCCESS) {
                spi_set_err_code(chip, SPI_HW_ERR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        if (erase_mode == PAGE_ERASE) {
                retval = sf_enable_write(chip, SPI_WREN);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = sf_erase(chip, ins, 1, addr);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        } else if (erase_mode == CHIP_ERASE) {
                retval = sf_enable_write(chip, SPI_WREN);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = sf_erase(chip, ins, 0, 0);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        } else {
                spi_set_err_code(chip, SPI_INVALID_COMMAND);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -844,12 +998,15 @@ int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        retval = spi_set_init_para(chip);
        if (retval != STATUS_SUCCESS) {
                spi_set_err_code(chip, SPI_HW_ERR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        retval = sf_enable_write(chip, ewsr);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -871,7 +1028,8 @@ int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
        if (retval != STATUS_SUCCESS) {
                rtsx_clear_spi_error(chip);
                spi_set_err_code(chip, SPI_HW_ERR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
diff --git a/drivers/staging/rts5208/trace.c b/drivers/staging/rts5208/trace.c
new file mode 100644 (file)
index 0000000..1bddbdf
--- /dev/null
@@ -0,0 +1,26 @@
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include "rtsx.h"
+
+#ifdef _MSG_TRACE
+
+void _rtsx_trace(struct rtsx_chip *chip, const char *file, const char *func,
+                int line)
+{
+       struct trace_msg_t *msg = &chip->trace_msg[chip->msg_idx];
+
+       file = kbasename(file);
+       dev_dbg(rtsx_dev(chip), "[%s][%s]:[%d]\n", file, func, line);
+
+       strncpy(msg->file, file, MSG_FILE_LEN - 1);
+       strncpy(msg->func, func, MSG_FUNC_LEN - 1);
+       msg->line = (u16)line;
+       get_current_time(msg->timeval_buf, TIME_VAL_LEN);
+       msg->valid = 1;
+
+       chip->msg_idx++;
+       if (chip->msg_idx >= TRACE_ITEM_CNT)
+               chip->msg_idx = 0;
+}
+#endif
index a9ab4077b283eedc7e48b8a638fce0a3c915ec50..5b807874c1d7f01c9cd8808c4eda7bf41b278404 100644 (file)
 #ifndef __REALTEK_RTSX_TRACE_H
 #define __REALTEK_RTSX_TRACE_H
 
-#define _MSG_TRACE
+struct rtsx_chip;
 
 #ifdef _MSG_TRACE
-static inline char *filename(char *path)
+void _rtsx_trace(struct rtsx_chip *chip, const char *file, const char *func,
+                int line);
+#define rtsx_trace(chip)                                               \
+       _rtsx_trace(chip, __FILE__, __func__, __LINE__)
+#else
+static inline void rtsx_trace(struct rtsx_chip *chip)
 {
-       char *ptr;
-
-       if (path == NULL)
-               return NULL;
-
-       ptr = path;
-
-       while (*ptr != '\0') {
-               if ((*ptr == '\\') || (*ptr == '/'))
-                       path = ptr + 1;
-
-               ptr++;
-       }
-
-       return path;
 }
-
-#define TRACE_RET(chip, ret)                                           \
-       do {                                                            \
-               char *_file = filename(__FILE__);                       \
-               dev_dbg(rtsx_dev(chip), "[%s][%s]:[%d]\n", _file,       \
-                       __func__, __LINE__);                            \
-               (chip)->trace_msg[(chip)->msg_idx].line = (u16)(__LINE__); \
-               strncpy((chip)->trace_msg[(chip)->msg_idx].func, __func__, MSG_FUNC_LEN-1); \
-               strncpy((chip)->trace_msg[(chip)->msg_idx].file, _file, MSG_FILE_LEN-1); \
-               get_current_time((chip)->trace_msg[(chip)->msg_idx].timeval_buf, TIME_VAL_LEN); \
-               (chip)->trace_msg[(chip)->msg_idx].valid = 1;           \
-               (chip)->msg_idx++;                                      \
-               if ((chip)->msg_idx >= TRACE_ITEM_CNT) {                \
-                       (chip)->msg_idx = 0;                            \
-               }                                                       \
-               return ret;                                             \
-       } while (0)
-
-#define TRACE_GOTO(chip, label)                                                \
-       do {                                                            \
-               char *_file = filename(__FILE__);                       \
-               dev_dbg(rtsx_dev(chip), "[%s][%s]:[%d]\n", _file,       \
-                       __func__, __LINE__);                            \
-               (chip)->trace_msg[(chip)->msg_idx].line = (u16)(__LINE__); \
-               strncpy((chip)->trace_msg[(chip)->msg_idx].func, __func__, MSG_FUNC_LEN-1); \
-               strncpy((chip)->trace_msg[(chip)->msg_idx].file, _file, MSG_FILE_LEN-1); \
-               get_current_time((chip)->trace_msg[(chip)->msg_idx].timeval_buf, TIME_VAL_LEN); \
-               (chip)->trace_msg[(chip)->msg_idx].valid = 1;           \
-               (chip)->msg_idx++;                                      \
-               if ((chip)->msg_idx >= TRACE_ITEM_CNT) {                \
-                       (chip)->msg_idx = 0;                            \
-               }                                                       \
-               goto label;                                             \
-       } while (0)
-#else
-#define TRACE_RET(chip, ret)   return ret
-#define TRACE_GOTO(chip, label)        goto label
 #endif
 
 #endif  /* __REALTEK_RTSX_TRACE_H */
index 0d029fe92b40346028d1b05f5db2775d40ecd312..8fd108e50509137f9fa8a9993c141179172c60e4 100644 (file)
@@ -60,8 +60,10 @@ static int xd_set_init_para(struct rtsx_chip *chip)
                xd_card->xd_clock = CLK_50;
 
        retval = switch_clock(chip, xd_card->xd_clock);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -72,12 +74,16 @@ static int xd_switch_clock(struct rtsx_chip *chip)
        int retval;
 
        retval = select_card(chip, XD_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = switch_clock(chip, xd_card->xd_clock);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -99,8 +105,10 @@ static int xd_read_id(struct rtsx_chip *chip, u8 id_cmd, u8 *id_buf, u8 buf_len)
                rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_ADDRESS1 + i), 0, 0);
 
        retval = rtsx_send_cmd(chip, XD_CARD, 20);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ptr = rtsx_get_cmd_data(chip) + 1;
        if (id_buf && buf_len) {
@@ -167,8 +175,10 @@ static int xd_read_redundant(struct rtsx_chip *chip, u32 page_addr,
        rtsx_add_cmd(chip, READ_REG_CMD, XD_PARITY, 0, 0);
 
        retval = rtsx_send_cmd(chip, XD_CARD, 500);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (buf && buf_len) {
                u8 *ptr = rtsx_get_cmd_data(chip) + 1;
@@ -186,8 +196,10 @@ static int xd_read_data_from_ppb(struct rtsx_chip *chip, int offset,
 {
        int retval, i;
 
-       if (!buf || (buf_len < 0))
-               TRACE_RET(chip, STATUS_FAIL);
+       if (!buf || (buf_len < 0)) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -198,7 +210,8 @@ static int xd_read_data_from_ppb(struct rtsx_chip *chip, int offset,
        retval = rtsx_send_cmd(chip, 0, 250);
        if (retval < 0) {
                rtsx_clear_xd_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        memcpy(buf, rtsx_get_cmd_data(chip), buf_len);
@@ -212,8 +225,10 @@ static int xd_read_cis(struct rtsx_chip *chip, u32 page_addr, u8 *buf,
        int retval;
        u8 reg;
 
-       if (!buf || (buf_len < 10))
-               TRACE_RET(chip, STATUS_FAIL);
+       if (!buf || (buf_len < 10)) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -233,25 +248,47 @@ static int xd_read_cis(struct rtsx_chip *chip, u32 page_addr, u8 *buf,
        retval = rtsx_send_cmd(chip, XD_CARD, 250);
        if (retval == -ETIMEDOUT) {
                rtsx_clear_xd_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
-       RTSX_READ_REG(chip, XD_PAGE_STATUS, &reg);
+       retval = rtsx_read_register(chip, XD_PAGE_STATUS, &reg);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        if (reg != XD_GPG) {
                rtsx_clear_xd_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
-       RTSX_READ_REG(chip, XD_CTL, &reg);
+       retval = rtsx_read_register(chip, XD_CTL, &reg);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        if (!(reg & XD_ECC1_ERROR) || !(reg & XD_ECC1_UNCORRECTABLE)) {
                retval = xd_read_data_from_ppb(chip, 0, buf, buf_len);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
                if (reg & XD_ECC1_ERROR) {
                        u8 ecc_bit, ecc_byte;
 
-                       RTSX_READ_REG(chip, XD_ECC_BIT1, &ecc_bit);
-                       RTSX_READ_REG(chip, XD_ECC_BYTE1, &ecc_byte);
+                       retval = rtsx_read_register(chip, XD_ECC_BIT1,
+                                                   &ecc_bit);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+                       retval = rtsx_read_register(chip, XD_ECC_BYTE1,
+                                                   &ecc_byte);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
 
                        dev_dbg(rtsx_dev(chip), "ECC_BIT1 = 0x%x, ECC_BYTE1 = 0x%x\n",
                                ecc_bit, ecc_byte);
@@ -267,13 +304,25 @@ static int xd_read_cis(struct rtsx_chip *chip, u32 page_addr, u8 *buf,
                rtsx_clear_xd_error(chip);
 
                retval = xd_read_data_from_ppb(chip, 256, buf, buf_len);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
                if (reg & XD_ECC2_ERROR) {
                        u8 ecc_bit, ecc_byte;
 
-                       RTSX_READ_REG(chip, XD_ECC_BIT2, &ecc_bit);
-                       RTSX_READ_REG(chip, XD_ECC_BYTE2, &ecc_byte);
+                       retval = rtsx_read_register(chip, XD_ECC_BIT2,
+                                                   &ecc_bit);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+                       retval = rtsx_read_register(chip, XD_ECC_BYTE2,
+                                                   &ecc_byte);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
 
                        dev_dbg(rtsx_dev(chip), "ECC_BIT2 = 0x%x, ECC_BYTE2 = 0x%x\n",
                                ecc_bit, ecc_byte);
@@ -287,7 +336,8 @@ static int xd_read_cis(struct rtsx_chip *chip, u32 page_addr, u8 *buf,
                }
        } else {
                rtsx_clear_xd_error(chip);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -363,24 +413,71 @@ static void xd_fill_pull_ctl_enable(struct rtsx_chip *chip)
 
 static int xd_pull_ctl_disable(struct rtsx_chip *chip)
 {
+       int retval;
+
        if (CHECK_PID(chip, 0x5208)) {
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF,
-                       XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF,
-                       XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF,
-                       XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF,
-                       XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF,
-                       MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
-               RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
+               retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF,
+                                            XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF,
+                                            XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF,
+                                            XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF,
+                                            XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF,
+                                            MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
+               retval = rtsx_write_register(chip, CARD_PULL_CTL6, 0xFF,
+                                            MS_D5_PD | MS_D4_PD);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        } else if (CHECK_PID(chip, 0x5288)) {
                if (CHECK_BARO_PKG(chip, QFN)) {
-                       RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
-                       RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
-                       RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B);
-                       RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69);
+                       retval = rtsx_write_register(chip, CARD_PULL_CTL1,
+                                                    0xFF, 0x55);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+                       retval = rtsx_write_register(chip, CARD_PULL_CTL2,
+                                                    0xFF, 0x55);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+                       retval = rtsx_write_register(chip, CARD_PULL_CTL3,
+                                                    0xFF, 0x4B);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
+                       retval = rtsx_write_register(chip, CARD_PULL_CTL4,
+                                                    0xFF, 0x69);
+                       if (retval) {
+                               rtsx_trace(chip);
+                               return retval;
+                       }
                }
        }
 
@@ -394,8 +491,10 @@ static int reset_xd(struct rtsx_chip *chip)
        u8 *ptr, id_buf[4], redunt[11];
 
        retval = select_card(chip, XD_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -418,13 +517,17 @@ static int reset_xd(struct rtsx_chip *chip)
        rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0);
 
        retval = rtsx_send_cmd(chip, XD_CARD, 100);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (!chip->ft2_fast_mode) {
                retval = card_power_off(chip, XD_CARD);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                wait_timeout(250);
 
@@ -439,19 +542,24 @@ static int reset_xd(struct rtsx_chip *chip)
                }
 
                retval = rtsx_send_cmd(chip, XD_CARD, 100);
-               if (retval < 0)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval < 0) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                retval = card_power_on(chip, XD_CARD);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
 #ifdef SUPPORT_OCP
                wait_timeout(50);
                if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
                        dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
                                chip->ocp_stat);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 #endif
        }
@@ -472,15 +580,19 @@ static int reset_xd(struct rtsx_chip *chip)
        rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CTL, XD_CE_DISEN, XD_CE_DISEN);
 
        retval = rtsx_send_cmd(chip, XD_CARD, 100);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        if (!chip->ft2_fast_mode)
                wait_timeout(200);
 
        retval = xd_set_init_para(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        /* Read ID to check if the timing setting is right */
        for (i = 0; i < 4; i++) {
@@ -502,8 +614,10 @@ static int reset_xd(struct rtsx_chip *chip)
                rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0);
 
                retval = rtsx_send_cmd(chip, XD_CARD, 100);
-               if (retval < 0)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval < 0) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                ptr = rtsx_get_cmd_data(chip) + 1;
 
@@ -515,8 +629,10 @@ static int reset_xd(struct rtsx_chip *chip)
                        continue;
 
                retval = xd_read_id(chip, READ_ID, id_buf, 4);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                dev_dbg(rtsx_dev(chip), "READ_ID: 0x%x 0x%x 0x%x 0x%x\n",
                        id_buf[0], id_buf[1], id_buf[2], id_buf[3]);
@@ -596,8 +712,10 @@ static int reset_xd(struct rtsx_chip *chip)
                /* Confirm timing setting */
                for (j = 0; j < 10; j++) {
                        retval = xd_read_id(chip, READ_ID, id_buf, 4);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        if (id_buf[1] != xd_card->device_code)
                                break;
@@ -613,23 +731,30 @@ static int reset_xd(struct rtsx_chip *chip)
                xd_card->addr_cycle = 0;
                xd_card->capacity = 0;
 
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        retval = xd_read_id(chip, READ_xD_ID, id_buf, 4);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
        dev_dbg(rtsx_dev(chip), "READ_xD_ID: 0x%x 0x%x 0x%x 0x%x\n",
                id_buf[0], id_buf[1], id_buf[2], id_buf[3]);
-       if (id_buf[2] != XD_ID_CODE)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (id_buf[2] != XD_ID_CODE) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        /* Search CIS block */
        for (i = 0; i < 24; i++) {
                u32 page_addr;
 
-               if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                page_addr = (u32)i << xd_card->block_shift;
 
@@ -667,8 +792,10 @@ static int reset_xd(struct rtsx_chip *chip)
                        page_addr += j;
 
                        retval = xd_read_cis(chip, page_addr, buf, 10);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
 
                        if ((buf[0] == 0x01) && (buf[1] == 0x03) &&
                                (buf[2] == 0xD9)
@@ -684,8 +811,10 @@ static int reset_xd(struct rtsx_chip *chip)
        }
 
        dev_dbg(rtsx_dev(chip), "CIS block: 0x%x\n", xd_card->cis_block);
-       if (xd_card->cis_block == 0xFFFF)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (xd_card->cis_block == 0xFFFF) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        chip->capacity[chip->card2lun[XD_CARD]] = xd_card->capacity;
 
@@ -739,15 +868,19 @@ static int xd_init_l2p_tbl(struct rtsx_chip *chip)
        dev_dbg(rtsx_dev(chip), "xd_init_l2p_tbl: zone_cnt = %d\n",
                xd_card->zone_cnt);
 
-       if (xd_card->zone_cnt < 1)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (xd_card->zone_cnt < 1) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        size = xd_card->zone_cnt * sizeof(struct zone_entry);
        dev_dbg(rtsx_dev(chip), "Buffer size for l2p table is %d\n", size);
 
        xd_card->zone = vmalloc(size);
-       if (!xd_card->zone)
-               TRACE_RET(chip, STATUS_ERROR);
+       if (!xd_card->zone) {
+               rtsx_trace(chip);
+               return STATUS_ERROR;
+       }
 
        for (i = 0; i < xd_card->zone_cnt; i++) {
                xd_card->zone[i].build_flag = 0;
@@ -927,16 +1060,22 @@ int reset_xd_card(struct rtsx_chip *chip)
        xd_card->delay_write.delay_write_flag = 0;
 
        retval = enable_card_clock(chip, XD_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = reset_xd(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        retval = xd_init_l2p_tbl(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -950,8 +1089,10 @@ static int xd_mark_bad_block(struct rtsx_chip *chip, u32 phy_blk)
 
        dev_dbg(rtsx_dev(chip), "mark block 0x%x as bad block\n", phy_blk);
 
-       if (phy_blk == BLK_NOT_FOUND)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (phy_blk == BLK_NOT_FOUND) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -986,7 +1127,8 @@ static int xd_mark_bad_block(struct rtsx_chip *chip, u32 phy_blk)
                        xd_set_err_code(chip, XD_PRG_ERROR);
                else
                        xd_set_err_code(chip, XD_TO_ERROR);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -1002,10 +1144,14 @@ static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk,
 
        dev_dbg(rtsx_dev(chip), "Init block 0x%x\n", phy_blk);
 
-       if (start_page > end_page)
-               TRACE_RET(chip, STATUS_FAIL);
-       if (phy_blk == BLK_NOT_FOUND)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (start_page > end_page) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
+       if (phy_blk == BLK_NOT_FOUND) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -1040,7 +1186,8 @@ static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk,
                } else {
                        xd_set_err_code(chip, XD_TO_ERROR);
                }
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        return STATUS_SUCCESS;
@@ -1057,24 +1204,34 @@ static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk,
        dev_dbg(rtsx_dev(chip), "Copy page from block 0x%x to block 0x%x\n",
                old_blk, new_blk);
 
-       if (start_page > end_page)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (start_page > end_page) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND))
-               TRACE_RET(chip, STATUS_FAIL);
+       if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND)) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        old_page = (old_blk << xd_card->block_shift) + start_page;
        new_page = (new_blk << xd_card->block_shift) + start_page;
 
        XD_CLR_BAD_NEWBLK(xd_card);
 
-       RTSX_WRITE_REG(chip, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+       retval = rtsx_write_register(chip, CARD_DATA_SOURCE, 0x01,
+                                    PINGPONG_BUFFER);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        for (i = start_page; i < end_page; i++) {
                if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
                        rtsx_clear_xd_error(chip);
                        xd_set_err_code(chip, XD_NO_CARD);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                rtsx_init_cmd(chip);
@@ -1100,7 +1257,8 @@ static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk,
                                if (detect_card_cd(chip,
                                        XD_CARD) != STATUS_SUCCESS) {
                                        xd_set_err_code(chip, XD_NO_CARD);
-                                       TRACE_RET(chip, STATUS_FAIL);
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
                                }
 
                                if (((reg & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) ==
@@ -1119,7 +1277,8 @@ static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk,
                                }
                        } else {
                                xd_set_err_code(chip, XD_TO_ERROR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
 
@@ -1147,7 +1306,8 @@ static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk,
                        } else {
                                xd_set_err_code(chip, XD_TO_ERROR);
                        }
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                old_page++;
@@ -1172,14 +1332,17 @@ static int xd_reset_cmd(struct rtsx_chip *chip)
        rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0);
 
        retval = rtsx_send_cmd(chip, XD_CARD, 100);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        ptr = rtsx_get_cmd_data(chip) + 1;
        if (((ptr[0] & READY_FLAG) == READY_STATE) && (ptr[1] & XD_RDY))
                return STATUS_SUCCESS;
 
-       TRACE_RET(chip, STATUS_FAIL);
+       rtsx_trace(chip);
+       return STATUS_FAIL;
 }
 
 static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk)
@@ -1189,8 +1352,10 @@ static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk)
        u8 reg = 0, *ptr;
        int i, retval;
 
-       if (phy_blk == BLK_NOT_FOUND)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (phy_blk == BLK_NOT_FOUND) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        page_addr = phy_blk << xd_card->block_shift;
 
@@ -1212,13 +1377,16 @@ static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk)
                        if (reg & PROGRAM_ERROR) {
                                xd_mark_bad_block(chip, phy_blk);
                                xd_set_err_code(chip, XD_PRG_ERROR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        } else {
                                xd_set_err_code(chip, XD_ERASE_FAIL);
                        }
                        retval = xd_reset_cmd(chip);
-                       if (retval != STATUS_SUCCESS)
-                               TRACE_RET(chip, STATUS_FAIL);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
+                       }
                        continue;
                }
 
@@ -1226,7 +1394,8 @@ static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk)
                if (*ptr & PROGRAM_ERROR) {
                        xd_mark_bad_block(chip, phy_blk);
                        xd_set_err_code(chip, XD_PRG_ERROR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                return STATUS_SUCCESS;
@@ -1234,7 +1403,8 @@ static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk)
 
        xd_mark_bad_block(chip, phy_blk);
        xd_set_err_code(chip, XD_ERASE_FAIL);
-       TRACE_RET(chip, STATUS_FAIL);
+       rtsx_trace(chip);
+       return STATUS_FAIL;
 }
 
 
@@ -1266,15 +1436,19 @@ static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no)
 
        if (zone->l2p_table == NULL) {
                zone->l2p_table = vmalloc(2000);
-               if (zone->l2p_table == NULL)
-                       TRACE_GOTO(chip, Build_Fail);
+               if (zone->l2p_table == NULL) {
+                       rtsx_trace(chip);
+                       goto Build_Fail;
+               }
        }
        memset((u8 *)(zone->l2p_table), 0xff, 2000);
 
        if (zone->free_table == NULL) {
                zone->free_table = vmalloc(XD_FREE_TABLE_CNT * 2);
-               if (zone->free_table == NULL)
-                       TRACE_GOTO(chip, Build_Fail);
+               if (zone->free_table == NULL) {
+                       rtsx_trace(chip);
+                       goto Build_Fail;
+               }
        }
        memset((u8 *)(zone->free_table), 0xff, XD_FREE_TABLE_CNT * 2);
 
@@ -1440,8 +1614,10 @@ static int xd_send_cmd(struct rtsx_chip *chip, u8 cmd)
                XD_TRANSFER_END, XD_TRANSFER_END);
 
        retval = rtsx_send_cmd(chip, XD_CARD, 200);
-       if (retval < 0)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval < 0) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
@@ -1457,8 +1633,10 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk,
        u8 reg_val, page_cnt;
        int zone_no, retval, i;
 
-       if (start_page > end_page)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (start_page > end_page) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        page_cnt = end_page - start_page;
        zone_no = (int)(log_blk / 1000);
@@ -1474,7 +1652,8 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk,
 
                        if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
                                xd_set_err_code(chip, XD_NO_CARD);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
        }
@@ -1509,21 +1688,31 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk,
 
                if (retval == -ETIMEDOUT) {
                        xd_set_err_code(chip, XD_TO_ERROR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                } else {
-                       TRACE_GOTO(chip, Fail);
+                       rtsx_trace(chip);
+                       goto Fail;
                }
        }
 
        return STATUS_SUCCESS;
 
 Fail:
-       RTSX_READ_REG(chip, XD_PAGE_STATUS, &reg_val);
+       retval = rtsx_read_register(chip, XD_PAGE_STATUS, &reg_val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        if (reg_val !=  XD_GPG)
                xd_set_err_code(chip, XD_PRG_ERROR);
 
-       RTSX_READ_REG(chip, XD_CTL, &reg_val);
+       retval = rtsx_read_register(chip, XD_CTL, &reg_val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        if (((reg_val & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE))
                                == (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE))
@@ -1533,7 +1722,8 @@ Fail:
 
                if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
                        xd_set_err_code(chip, XD_NO_CARD);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                xd_set_err_code(chip, XD_ECC_ERROR);
@@ -1541,7 +1731,8 @@ Fail:
                new_blk = xd_get_unused_block(chip, zone_no);
                if (new_blk == NO_NEW_BLK) {
                        XD_CLR_BAD_OLDBLK(xd_card);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                retval = xd_copy_page(chip, phy_blk, new_blk, 0,
@@ -1555,7 +1746,8 @@ Fail:
                                XD_CLR_BAD_NEWBLK(xd_card);
                        }
                        XD_CLR_BAD_OLDBLK(xd_card);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
                xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF));
                xd_erase_block(chip, phy_blk);
@@ -1563,7 +1755,8 @@ Fail:
                XD_CLR_BAD_OLDBLK(xd_card);
        }
 
-       TRACE_RET(chip, STATUS_FAIL);
+       rtsx_trace(chip);
+       return STATUS_FAIL;
 }
 
 static int xd_finish_write(struct rtsx_chip *chip,
@@ -1576,8 +1769,10 @@ static int xd_finish_write(struct rtsx_chip *chip,
        dev_dbg(rtsx_dev(chip), "xd_finish_write, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x\n",
                old_blk, new_blk, log_blk);
 
-       if (page_off > xd_card->page_off)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (page_off > xd_card->page_off) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        zone_no = (int)(log_blk / 1000);
        log_off = (u16)(log_blk % 1000);
@@ -1589,7 +1784,8 @@ static int xd_finish_write(struct rtsx_chip *chip,
                        retval = xd_erase_block(chip, new_blk);
                        if (retval == STATUS_SUCCESS)
                                xd_set_unused_block(chip, new_blk);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        } else {
                retval = xd_copy_page(chip, old_blk, new_blk,
@@ -1601,7 +1797,8 @@ static int xd_finish_write(struct rtsx_chip *chip,
                                        xd_set_unused_block(chip, new_blk);
                        }
                        XD_CLR_BAD_NEWBLK(xd_card);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                retval = xd_erase_block(chip, old_blk);
@@ -1633,8 +1830,10 @@ static int xd_prepare_write(struct rtsx_chip *chip,
 
        if (page_off) {
                retval = xd_copy_page(chip, old_blk, new_blk, 0, page_off);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -1655,8 +1854,10 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk,
        dev_dbg(rtsx_dev(chip), "%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x\n",
                __func__, old_blk, new_blk, log_blk);
 
-       if (start_page > end_page)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (start_page > end_page) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        page_cnt = end_page - start_page;
        zone_no = (int)(log_blk / 1000);
@@ -1665,8 +1866,10 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk,
        page_addr = (new_blk << xd_card->block_shift) + start_page;
 
        retval = xd_send_cmd(chip, READ1_1);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        rtsx_init_cmd(chip);
 
@@ -1701,9 +1904,11 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk,
 
                if (retval == -ETIMEDOUT) {
                        xd_set_err_code(chip, XD_TO_ERROR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                } else {
-                       TRACE_GOTO(chip, Fail);
+                       rtsx_trace(chip);
+                       goto Fail;
                }
        }
 
@@ -1730,13 +1935,18 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk,
        return STATUS_SUCCESS;
 
 Fail:
-       RTSX_READ_REG(chip, XD_DAT, &reg_val);
+       retval = rtsx_read_register(chip, XD_DAT, &reg_val);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
        if (reg_val & PROGRAM_ERROR) {
                xd_set_err_code(chip, XD_PRG_ERROR);
                xd_mark_bad_block(chip, new_blk);
        }
 
-       TRACE_RET(chip, STATUS_FAIL);
+       rtsx_trace(chip);
+       return STATUS_FAIL;
 }
 
 #ifdef XD_DELAY_WRITE
@@ -1749,16 +1959,20 @@ int xd_delay_write(struct rtsx_chip *chip)
        if (delay_write->delay_write_flag) {
                dev_dbg(rtsx_dev(chip), "xd_delay_write\n");
                retval = xd_switch_clock(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                delay_write->delay_write_flag = 0;
                retval = xd_finish_write(chip,
                                delay_write->old_phyblock,
                                        delay_write->new_phyblock,
                                delay_write->logblock, delay_write->pageoff);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -1790,14 +2004,17 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
        ptr = (u8 *)scsi_sglist(srb);
 
        retval = xd_switch_clock(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
 
        if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
                chip->card_fail |= XD_CARD;
                set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-               TRACE_RET(chip, STATUS_FAIL);
+               rtsx_trace(chip);
+               return STATUS_FAIL;
        }
 
        log_blk = start_sector >> xd_card->block_shift;
@@ -1810,7 +2027,8 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                if (retval != STATUS_SUCCESS) {
                        chip->card_fail |= XD_CARD;
                        set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
@@ -1828,7 +2046,8 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                                if (retval != STATUS_SUCCESS) {
                                        set_sense_type(chip, lun,
                                                SENSE_TYPE_MEDIA_WRITE_ERR);
-                                       TRACE_RET(chip, STATUS_FAIL);
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
                                }
                        }
                        old_blk = delay_write->old_phyblock;
@@ -1844,7 +2063,8 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                        if (retval != STATUS_SUCCESS) {
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 #endif
                        old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
@@ -1853,7 +2073,8 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                                (new_blk == BLK_NOT_FOUND)) {
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 
                        retval = xd_prepare_write(chip, old_blk, new_blk,
@@ -1863,11 +2084,13 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                                        STATUS_SUCCESS) {
                                        set_sense_type(chip, lun,
                                                SENSE_TYPE_MEDIA_NOT_PRESENT);
-                                       TRACE_RET(chip, STATUS_FAIL);
+                                       rtsx_trace(chip);
+                                       return STATUS_FAIL;
                                }
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
 #ifdef XD_DELAY_WRITE
                }
@@ -1879,11 +2102,13 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                        if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_NOT_PRESENT);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 #endif
 
@@ -1891,7 +2116,8 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                if (old_blk == BLK_NOT_FOUND) {
                        set_sense_type(chip, lun,
                                SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
        }
 
@@ -1901,7 +2127,8 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
                        chip->card_fail |= XD_CARD;
                        set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                if ((start_page + total_sec_cnt) > (xd_card->page_off + 1))
@@ -1917,7 +2144,8 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                        if (retval != STATUS_SUCCESS) {
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                } else {
                        retval = xd_write_multiple_pages(chip, old_blk,
@@ -1927,7 +2155,8 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                        if (retval != STATUS_SUCCESS) {
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
 
@@ -1948,7 +2177,8 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                                chip->card_fail |= XD_CARD;
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_NOT_PRESENT);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
 
@@ -1961,7 +2191,8 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
 
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                if (srb->sc_data_direction == DMA_TO_DEVICE) {
@@ -1969,7 +2200,8 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                        if (new_blk == BLK_NOT_FOUND) {
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_WRITE_ERR);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
 
@@ -1988,7 +2220,8 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
                        chip->card_fail |= XD_CARD;
                        set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 
                retval = xd_finish_write(chip, old_blk, new_blk,
@@ -1997,10 +2230,12 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
                        if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
                                set_sense_type(chip, lun,
                                        SENSE_TYPE_MEDIA_NOT_PRESENT);
-                               TRACE_RET(chip, STATUS_FAIL);
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                        set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-                       TRACE_RET(chip, STATUS_FAIL);
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
                }
 #endif
        }
@@ -2049,25 +2284,39 @@ int xd_power_off_card3v3(struct rtsx_chip *chip)
        int retval;
 
        retval = disable_card_clock(chip, XD_CARD);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
-       RTSX_WRITE_REG(chip, CARD_OE, XD_OUTPUT_EN, 0);
+       retval = rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0);
+       if (retval) {
+               rtsx_trace(chip);
+               return retval;
+       }
 
        if (!chip->ft2_fast_mode) {
                retval = card_power_off(chip, XD_CARD);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
 
                wait_timeout(50);
        }
 
        if (chip->asic_code) {
                retval = xd_pull_ctl_disable(chip);
-               if (retval != STATUS_SUCCESS)
-                       TRACE_RET(chip, STATUS_FAIL);
+               if (retval != STATUS_SUCCESS) {
+                       rtsx_trace(chip);
+                       return STATUS_FAIL;
+               }
        } else {
-               RTSX_WRITE_REG(chip, FPGA_PULL_CTL, 0xFF, 0xDF);
+               retval = rtsx_write_register(chip, FPGA_PULL_CTL, 0xFF, 0xDF);
+               if (retval) {
+                       rtsx_trace(chip);
+                       return retval;
+               }
        }
 
        return STATUS_SUCCESS;
@@ -2087,8 +2336,10 @@ int release_xd_card(struct rtsx_chip *chip)
        xd_free_l2p_tbl(chip);
 
        retval = xd_power_off_card3v3(chip);
-       if (retval != STATUS_SUCCESS)
-               TRACE_RET(chip, STATUS_FAIL);
+       if (retval != STATUS_SUCCESS) {
+               rtsx_trace(chip);
+               return STATUS_FAIL;
+       }
 
        return STATUS_SUCCESS;
 }
index 9bd69ce3be0014b373c328aeb0ac6ca50c9c8eec..b0cd9357348fcc8a53e5ac8da5792867ab66f356 100644 (file)
@@ -68,9 +68,7 @@ do {                                         \
 
 #if SKEIN_UNROLL_256 == 0
 #define R256(p0, p1, p2, p3, ROT, r_num) /* fully unrolled */ \
-do {                                                          \
-       ROUND256(p0, p1, p2, p3, ROT, r_num);                 \
-} while (0)
+       ROUND256(p0, p1, p2, p3, ROT, r_num)
 
 #define I256(R)                                                           \
 do {                                                                      \
@@ -152,9 +150,7 @@ do {                                                         \
 
 #if SKEIN_UNROLL_512 == 0
 #define R512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num) /* unrolled */ \
-do {                                                                    \
-       ROUND512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num);           \
-} while (0)
+       ROUND512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num)
 
 #define I512(R)                                                           \
 do {                                                                      \
index 42d62ef56cb8661c9cce4e85e5ee4a5bcce99a52..c2bda1d38e41c1d21a500a69d2359f6dd43fe750 100644 (file)
@@ -84,7 +84,6 @@
 #include <linux/seq_file.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 
 #include <linux/firmware.h>
 #include <linux/types.h>
@@ -99,8 +98,7 @@
 #include "slic.h"
 
 static uint slic_first_init = 1;
-static char *slic_banner = "Alacritech SLIC Technology(tm) Server "
-               "and Storage Accelerator (Non-Accelerated)";
+static char *slic_banner = "Alacritech SLIC Technology(tm) Server and Storage Accelerator (Non-Accelerated)";
 
 static char *slic_proc_version = "2.0.351  2006/07/14 12:26:00";
 
@@ -166,7 +164,7 @@ static void slic_mcast_set_bit(struct adapter *adapter, char *address)
        /* Get the CRC polynomial for the mac address */
        /* we use bits 1-8 (lsb), bitwise reversed,
         * msb (= lsb bit 0 before bitrev) is automatically discarded */
-       crcpoly = (ether_crc(ETH_ALEN, address)>>23);
+       crcpoly = ether_crc(ETH_ALEN, address)>>23;
 
        /* We only have space on the SLIC for 64 entries.  Lop
         * off the top two bits. (2^6 = 64)
@@ -1852,7 +1850,7 @@ static void slic_xmit_build_request(struct adapter *adapter,
 
        ihcmd = &hcmd->cmd64;
 
-       ihcmd->flags = (adapter->port << IHFLG_IFSHFT);
+       ihcmd->flags = adapter->port << IHFLG_IFSHFT;
        ihcmd->command = IHCMD_XMT_REQ;
        ihcmd->u.slic_buffers.totlen = skb->len;
        phys_addr = pci_map_single(adapter->pcidev, skb->data, skb->len,
@@ -1864,8 +1862,8 @@ static void slic_xmit_build_request(struct adapter *adapter,
        hcmd->cmdsize = (u32) ((((u64)&ihcmd->u.slic_buffers.bufs[1] -
                                     (u64) hcmd) + 31) >> 5);
 #else
-       hcmd->cmdsize = ((((u32) &ihcmd->u.slic_buffers.bufs[1] -
-                          (u32) hcmd) + 31) >> 5);
+       hcmd->cmdsize = (((u32)&ihcmd->u.slic_buffers.bufs[1] -
+                                      (u32)hcmd) + 31) >> 5;
 #endif
 }
 
@@ -2315,9 +2313,8 @@ static int slic_if_init(struct adapter *adapter)
        }
        rc = slic_adapter_allocresources(adapter);
        if (rc) {
-               dev_err(&dev->dev,
-                       "%s: slic_adapter_allocresources FAILED %x\n",
-                       __func__, rc);
+               dev_err(&dev->dev, "slic_adapter_allocresources FAILED %x\n",
+                       rc);
                slic_adapter_freeresources(adapter);
                goto err;
        }
@@ -2362,22 +2359,19 @@ static int slic_if_init(struct adapter *adapter)
 
        adapter->state = ADAPT_UP;
        if (!card->loadtimerset) {
-               init_timer(&card->loadtimer);
+               setup_timer(&card->loadtimer, &slic_timer_load_check,
+                           (ulong)card);
                card->loadtimer.expires =
                    jiffies + (SLIC_LOADTIMER_PERIOD * HZ);
-               card->loadtimer.data = (ulong) card;
-               card->loadtimer.function = &slic_timer_load_check;
                add_timer(&card->loadtimer);
 
                card->loadtimerset = 1;
        }
 
        if (!adapter->pingtimerset) {
-               init_timer(&adapter->pingtimer);
+               setup_timer(&adapter->pingtimer, &slic_timer_ping, (ulong)dev);
                adapter->pingtimer.expires =
                    jiffies + (PING_TIMER_INTERVAL * HZ);
-               adapter->pingtimer.data = (ulong) dev;
-               adapter->pingtimer.function = &slic_timer_ping;
                add_timer(&adapter->pingtimer);
                adapter->pingtimerset = 1;
                adapter->card->pingstatus = ISR_PINGMASK;
@@ -2554,46 +2548,11 @@ static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                if (copy_from_user(data, rq->ifr_data, 28))
                        return -EFAULT;
                intagg = data[0];
-               dev_err(&dev->dev, "%s: set interrupt aggregation to %d\n",
-                       __func__, intagg);
+               dev_err(&dev->dev, "set interrupt aggregation to %d\n",
+                       intagg);
                slic_intagg_set(adapter, intagg);
                return 0;
 
-#ifdef SLIC_TRACE_DUMP_ENABLED
-       case SIOCSLICTRACEDUMP:
-               {
-                       u32 value;
-
-                       DBG_IOCTL("slic_ioctl  SIOCSLIC_TRACE_DUMP\n");
-
-                       if (copy_from_user(data, rq->ifr_data, 28)) {
-                               PRINT_ERROR
-                                   ("slic: copy_from_user FAILED getting initial simba param\n");
-                               return -EFAULT;
-                       }
-
-                       value = data[0];
-                       if (tracemon_request == SLIC_DUMP_DONE) {
-                               PRINT_ERROR
-                                   ("ATK Diagnostic Trace Dump Requested\n");
-                               tracemon_request = SLIC_DUMP_REQUESTED;
-                               tracemon_request_type = value;
-                               tracemon_timestamp = jiffies;
-                       } else if ((tracemon_request == SLIC_DUMP_REQUESTED) ||
-                                  (tracemon_request ==
-                                   SLIC_DUMP_IN_PROGRESS)) {
-                               PRINT_ERROR
-                                   ("ATK Diagnostic Trace Dump Requested but already in progress... ignore\n");
-                       } else {
-                               PRINT_ERROR
-                                   ("ATK Diagnostic Trace Dump Requested\n");
-                               tracemon_request = SLIC_DUMP_REQUESTED;
-                               tracemon_request_type = value;
-                               tracemon_timestamp = jiffies;
-                       }
-                       return 0;
-               }
-#endif
        case SIOCETHTOOL:
                if (copy_from_user(&ecmd, rq->ifr_data, sizeof(ecmd)))
                        return -EFAULT;
diff --git a/drivers/staging/sm750fb/Kconfig b/drivers/staging/sm750fb/Kconfig
new file mode 100644 (file)
index 0000000..c40d088
--- /dev/null
@@ -0,0 +1,10 @@
+config FB_SM750
+       tristate "Silicon Motion SM750 framebuffer support"
+       depends on FB && PCI
+       help
+         Frame buffer driver for the Silicon Motion SM750 chip
+         with 2D accelearion and dual head support.
+
+         This driver is also available as a module. The module will be
+         called sm750fb. If you want to compile it as a module, say M
+         here and read <file:Documentation/kbuild/modules.txt>.
diff --git a/drivers/staging/sm750fb/Makefile b/drivers/staging/sm750fb/Makefile
new file mode 100644 (file)
index 0000000..dcce3f4
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_FB_SM750) += sm750fb.o
+
+sm750fb-objs           := sm750.o sm750_hw.o sm750_accel.o sm750_cursor.o ddk750_chip.o ddk750_power.o ddk750_mode.o
+sm750fb-objs           += ddk750_display.o ddk750_help.o ddk750_swi2c.o ddk750_sii164.o ddk750_dvi.o ddk750_hwi2c.o
diff --git a/drivers/staging/sm750fb/TODO b/drivers/staging/sm750fb/TODO
new file mode 100644 (file)
index 0000000..bc16172
--- /dev/null
@@ -0,0 +1,15 @@
+TODO:
+- lots of clechpatch cleanup
+- use kernel coding style
+- refine the code and remove unused code
+- check on hardware effects of removal of USE_HW_I2C and USE_DVICHIP (these two
+       are supposed to be sample code which is given here if someone wants to
+       use those functionalities)
+- move it to drivers/video/fbdev
+- modify the code for drm framework
+
+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>
diff --git a/drivers/staging/sm750fb/ddk750.h b/drivers/staging/sm750fb/ddk750.h
new file mode 100644 (file)
index 0000000..2c10a08
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef DDK750_H__
+#define DDK750_H__
+/*******************************************************************
+*
+*         Copyright (c) 2007 by Silicon Motion, Inc. (SMI)
+*
+*  All rights are reserved. Reproduction or in part is prohibited
+*  without the written consent of the copyright owner.
+*
+*  RegSC.h --- SM718 SDK
+*  This file contains the definitions for the System Configuration registers.
+*
+*******************************************************************/
+#include "ddk750_reg.h"
+#include "ddk750_mode.h"
+#include "ddk750_chip.h"
+#include "ddk750_display.h"
+#include "ddk750_power.h"
+#include "ddk750_help.h"
+#ifdef USE_HW_I2C
+#include "ddk750_hwi2c.h"
+#endif
+#include "ddk750_swi2c.h"
+#endif
diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c
new file mode 100644 (file)
index 0000000..7b28328
--- /dev/null
@@ -0,0 +1,622 @@
+#include "ddk750_help.h"
+#include "ddk750_reg.h"
+#include "ddk750_chip.h"
+#include "ddk750_power.h"
+typedef struct _pllcalparam {
+       unsigned char power;/* d : 0~ 6*/
+       unsigned char pod;
+       unsigned char od;
+       unsigned char value;/* value of  2 power d (2^d) */
+}
+pllcalparam;
+
+
+logical_chip_type_t getChipType(void)
+{
+       unsigned short physicalID;
+       char physicalRev;
+       logical_chip_type_t chip;
+
+       physicalID = devId750;//either 0x718 or 0x750
+       physicalRev = revId750;
+
+       if (physicalID == 0x718)
+               chip = SM718;
+       else if (physicalID == 0x750) {
+               chip = SM750;
+               /* SM750 and SM750LE are different in their revision ID only. */
+               if (physicalRev == SM750LE_REVISION_ID)
+                       chip = SM750LE;
+       } else
+               chip = SM_UNKNOWN;
+
+       return chip;
+}
+
+
+inline unsigned int twoToPowerOfx(unsigned long x)
+{
+       unsigned long i;
+       unsigned long result = 1;
+
+       for (i = 1; i <= x; i++)
+               result *= 2;
+       return result;
+}
+
+inline unsigned int calcPLL(pll_value_t *pPLL)
+{
+       return (pPLL->inputFreq * pPLL->M / pPLL->N / twoToPowerOfx(pPLL->OD) / twoToPowerOfx(pPLL->POD));
+}
+
+unsigned int getPllValue(clock_type_t clockType, pll_value_t *pPLL)
+{
+       unsigned int ulPllReg = 0;
+
+       pPLL->inputFreq = DEFAULT_INPUT_CLOCK;
+       pPLL->clockType = clockType;
+
+       switch (clockType) {
+       case MXCLK_PLL:
+               ulPllReg = PEEK32(MXCLK_PLL_CTRL);
+               break;
+       case PRIMARY_PLL:
+               ulPllReg = PEEK32(PANEL_PLL_CTRL);
+               break;
+       case SECONDARY_PLL:
+               ulPllReg = PEEK32(CRT_PLL_CTRL);
+               break;
+       case VGA0_PLL:
+               ulPllReg = PEEK32(VGA_PLL0_CTRL);
+               break;
+       case VGA1_PLL:
+               ulPllReg = PEEK32(VGA_PLL1_CTRL);
+               break;
+       }
+
+       pPLL->M = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, M);
+       pPLL->N = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, N);
+       pPLL->OD = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, OD);
+       pPLL->POD = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, POD);
+
+       return calcPLL(pPLL);
+}
+
+
+unsigned int getChipClock(void)
+{
+       pll_value_t pll;
+#if 1
+       if (getChipType() == SM750LE)
+               return MHz(130);
+#endif
+
+       return getPllValue(MXCLK_PLL, &pll);
+}
+
+
+/*
+ * This function set up the main chip clock.
+ *
+ * Input: Frequency to be set.
+ */
+void setChipClock(unsigned int frequency)
+{
+       pll_value_t pll;
+       unsigned int ulActualMxClk;
+#if 1
+       /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
+       if (getChipType() == SM750LE)
+               return;
+#endif
+
+       if (frequency) {
+               /*
+               * Set up PLL, a structure to hold the value to be set in clocks.
+               */
+               pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
+               pll.clockType = MXCLK_PLL;
+
+               /*
+               * Call calcPllValue() to fill up the other fields for PLL structure.
+               * Sometime, the chip cannot set up the exact clock required by User.
+               * Return value from calcPllValue() gives the actual possible clock.
+               */
+               ulActualMxClk = calcPllValue(frequency, &pll);
+
+               /* Master Clock Control: MXCLK_PLL */
+               POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
+       }
+}
+
+
+
+void setMemoryClock(unsigned int frequency)
+{
+       unsigned int ulReg, divisor;
+ #if 1
+       /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
+       if (getChipType() == SM750LE)
+               return;
+#endif
+       if (frequency) {
+               /* Set the frequency to the maximum frequency that the DDR Memory can take
+               which is 336MHz. */
+               if (frequency > MHz(336))
+                       frequency = MHz(336);
+
+               /* Calculate the divisor */
+               divisor = (unsigned int) roundedDiv(getChipClock(), frequency);
+
+               /* Set the corresponding divisor in the register. */
+               ulReg = PEEK32(CURRENT_GATE);
+               switch (divisor) {
+               default:
+               case 1:
+                       ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_1);
+                       break;
+               case 2:
+                       ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_2);
+                       break;
+               case 3:
+                       ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_3);
+                       break;
+               case 4:
+                       ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_4);
+                       break;
+               }
+
+               setCurrentGate(ulReg);
+       }
+}
+
+
+/*
+ * This function set up the master clock (MCLK).
+ *
+ * Input: Frequency to be set.
+ *
+ * NOTE:
+ *      The maximum frequency the engine can run is 168MHz.
+ */
+void setMasterClock(unsigned int frequency)
+{
+       unsigned int ulReg, divisor;
+#if 1
+       /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
+       if (getChipType() == SM750LE)
+               return;
+#endif
+       if (frequency) {
+               /* Set the frequency to the maximum frequency that the SM750 engine can
+               run, which is about 190 MHz. */
+               if (frequency > MHz(190))
+                       frequency = MHz(190);
+
+               /* Calculate the divisor */
+               divisor = (unsigned int) roundedDiv(getChipClock(), frequency);
+
+               /* Set the corresponding divisor in the register. */
+               ulReg = PEEK32(CURRENT_GATE);
+               switch (divisor) {
+               default:
+               case 3:
+                       ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_3);
+                       break;
+               case 4:
+                       ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_4);
+                       break;
+               case 6:
+                       ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_6);
+                       break;
+               case 8:
+                       ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_8);
+                       break;
+               }
+
+               setCurrentGate(ulReg);
+               }
+}
+
+
+unsigned int ddk750_getVMSize(void)
+{
+       unsigned int reg;
+       unsigned int data;
+
+       /* sm750le only use 64 mb memory*/
+       if (getChipType() == SM750LE)
+               return MB(64);
+
+       /* for 750,always use power mode0*/
+       reg = PEEK32(MODE0_GATE);
+       reg = FIELD_SET(reg, MODE0_GATE, GPIO, ON);
+       POKE32(MODE0_GATE, reg);
+
+       /* get frame buffer size from GPIO */
+       reg = FIELD_GET(PEEK32(MISC_CTRL), MISC_CTRL, LOCALMEM_SIZE);
+       switch (reg) {
+       case MISC_CTRL_LOCALMEM_SIZE_8M:
+               data = MB(8);  break; /* 8  Mega byte */
+       case MISC_CTRL_LOCALMEM_SIZE_16M:
+               data = MB(16); break; /* 16 Mega byte */
+       case MISC_CTRL_LOCALMEM_SIZE_32M:
+               data = MB(32); break; /* 32 Mega byte */
+       case MISC_CTRL_LOCALMEM_SIZE_64M:
+               data = MB(64); break; /* 64 Mega byte */
+       default:
+               data = 0;
+               break;
+       }
+       return data;
+
+}
+
+int ddk750_initHw(initchip_param_t *pInitParam)
+{
+
+       unsigned int ulReg;
+#if 0
+       //move the code to map regiter function.
+       if (getChipType() == SM718) {
+               /* turn on big endian bit*/
+               ulReg = PEEK32(0x74);
+               /* now consider register definition in a big endian pattern*/
+               POKE32(0x74, ulReg|0x80000000);
+       }
+
+#endif
+
+
+       if (pInitParam->powerMode != 0 )
+               pInitParam->powerMode = 0;
+       setPowerMode(pInitParam->powerMode);
+
+       /* Enable display power gate & LOCALMEM power gate*/
+       ulReg = PEEK32(CURRENT_GATE);
+       ulReg = FIELD_SET(ulReg, CURRENT_GATE, DISPLAY, ON);
+       ulReg = FIELD_SET(ulReg, CURRENT_GATE, LOCALMEM, ON);
+       setCurrentGate(ulReg);
+
+       if (getChipType() != SM750LE) {
+               /*      set panel pll and graphic mode via mmio_88 */
+               ulReg = PEEK32(VGA_CONFIGURATION);
+               ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, PLL, PANEL);
+               ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, MODE, GRAPHIC);
+               POKE32(VGA_CONFIGURATION, ulReg);
+       } else {
+#if defined(__i386__) || defined( __x86_64__)
+               /* set graphic mode via IO method */
+               outb_p(0x88, 0x3d4);
+               outb_p(0x06, 0x3d5);
+#endif
+       }
+
+       /* Set the Main Chip Clock */
+       setChipClock(MHz((unsigned int)pInitParam->chipClock));
+
+       /* Set up memory clock. */
+       setMemoryClock(MHz(pInitParam->memClock));
+
+       /* Set up master clock */
+       setMasterClock(MHz(pInitParam->masterClock));
+
+
+       /* Reset the memory controller. If the memory controller is not reset in SM750,
+          the system might hang when sw accesses the memory.
+          The memory should be resetted after changing the MXCLK.
+        */
+       if (pInitParam->resetMemory == 1) {
+               ulReg = PEEK32(MISC_CTRL);
+               ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, RESET);
+               POKE32(MISC_CTRL, ulReg);
+
+               ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, NORMAL);
+               POKE32(MISC_CTRL, ulReg);
+       }
+
+       if (pInitParam->setAllEngOff == 1) {
+               enable2DEngine(0);
+
+               /* Disable Overlay, if a former application left it on */
+               ulReg = PEEK32(VIDEO_DISPLAY_CTRL);
+               ulReg = FIELD_SET(ulReg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE);
+               POKE32(VIDEO_DISPLAY_CTRL, ulReg);
+
+               /* Disable video alpha, if a former application left it on */
+               ulReg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
+               ulReg = FIELD_SET(ulReg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
+               POKE32(VIDEO_ALPHA_DISPLAY_CTRL, ulReg);
+
+               /* Disable alpha plane, if a former application left it on */
+               ulReg = PEEK32(ALPHA_DISPLAY_CTRL);
+               ulReg = FIELD_SET(ulReg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
+               POKE32(ALPHA_DISPLAY_CTRL, ulReg);
+
+#if 0
+               /* Disable LCD hardware cursor, if a former application left it on */
+               ulReg = PEEK32(PANEL_HWC_ADDRESS);
+               ulReg = FIELD_SET(ulReg, PANEL_HWC_ADDRESS, ENABLE, DISABLE);
+               POKE32(PANEL_HWC_ADDRESS, ulReg);
+
+               /* Disable CRT hardware cursor, if a former application left it on */
+               ulReg = PEEK32(CRT_HWC_ADDRESS);
+               ulReg = FIELD_SET(ulReg, CRT_HWC_ADDRESS, ENABLE, DISABLE);
+               POKE32(CRT_HWC_ADDRESS, ulReg);
+
+               /* Disable ZV Port 0, if a former application left it on */
+               ulReg = PEEK32(ZV0_CAPTURE_CTRL);
+               ulReg = FIELD_SET(ulReg, ZV0_CAPTURE_CTRL, CAP, DISABLE);
+               POKE32(ZV0_CAPTURE_CTRL, ulReg);
+
+               /* Disable ZV Port 1, if a former application left it on */
+               ulReg = PEEK32(ZV1_CAPTURE_CTRL);
+               ulReg = FIELD_SET(ulReg, ZV1_CAPTURE_CTRL, CAP, DISABLE);
+               POKE32(ZV1_CAPTURE_CTRL, ulReg);
+
+               /* Disable ZV Port Power, if a former application left it on */
+               enableZVPort(0);
+               /* Disable DMA Channel, if a former application left it on */
+               ulReg = PEEK32(DMA_ABORT_INTERRUPT);
+               ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT);
+               POKE32(DMA_ABORT_INTERRUPT, ulReg);
+
+               /* Disable i2c */
+               enableI2C(0);
+#endif
+               /* Disable DMA Channel, if a former application left it on */
+               ulReg = PEEK32(DMA_ABORT_INTERRUPT);
+               ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT);
+               POKE32(DMA_ABORT_INTERRUPT, ulReg);
+
+               /* Disable DMA Power, if a former application left it on */
+               enableDMA(0);
+       }
+
+       /* We can add more initialization as needed. */
+
+       return 0;
+}
+
+#if 0
+
+unsigned int absDiff(unsigned int a, unsigned int b)
+{
+       if ( a > b )
+               return(a - b);
+       else
+               return(b - a);
+}
+
+#endif
+/*
+       monk liu @ 4/6/2011:
+                  re-write the calculatePLL function of ddk750.
+                  the original version function does not use some mathematics tricks and shortcut
+                  when it doing the calculation of the best N,M,D combination
+                  I think this version gives a little upgrade in speed
+
+       750 pll clock formular:
+       Request Clock = (Input Clock * M )/(N * X)
+
+       Input Clock = 14318181 hz
+       X = 2 power D
+       D ={0,1,2,3,4,5,6}
+       M = {1,...,255}
+       N = {2,...,15}
+*/
+unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
+{
+       /* used for primary and secondary channel pixel clock pll */
+       static pllcalparam xparm_PIXEL[] = {
+               /* 2^0 = 1*/                    {0, 0, 0, 1},
+               /* 2^ 1 =2*/                    {1, 0, 1, 2},
+               /* 2^ 2  = 4*/          {2, 0, 2, 4},
+                                                       {3, 0, 3, 8},
+                                                       {4, 1, 3, 16},
+                                                       {5, 2, 3, 32},
+               /* 2^6 = 64  */         {6, 3, 3, 64},
+                                                       };
+
+       /* used for MXCLK (chip clock) */
+       static pllcalparam xparm_MXCLK[] = {
+               /* 2^0 = 1*/                    {0, 0, 0, 1},
+               /* 2^ 1 =2*/                    {1, 0, 1, 2},
+               /* 2^ 2  = 4*/          {2, 0, 2, 4},
+                                                       {3, 0, 3, 8},
+                                                       };
+
+       /* as sm750 register definition, N located in 2,15 and M located in 1,255       */
+       int N, M, X, d;
+       int xcnt;
+       int miniDiff;
+       unsigned int RN, quo, rem, fl_quo;
+       unsigned int input, request;
+       unsigned int tmpClock, ret;
+       pllcalparam * xparm;
+
+#if 1
+       if (getChipType() == SM750LE) {
+               /* SM750LE don't have prgrammable PLL and M/N values to work on.
+               Just return the requested clock. */
+               return request_orig;
+       }
+#endif
+
+       ret = 0;
+       miniDiff = ~0;
+       request = request_orig / 1000;
+       input = pll->inputFreq / 1000;
+
+       /* for MXCLK register , no POD provided, so need be treated differently */
+
+       if (pll->clockType != MXCLK_PLL) {
+               xparm = &xparm_PIXEL[0];
+               xcnt = sizeof(xparm_PIXEL)/sizeof(xparm_PIXEL[0]);
+       } else {
+               xparm = &xparm_MXCLK[0];
+               xcnt = sizeof(xparm_MXCLK)/sizeof(xparm_MXCLK[0]);
+       }
+
+
+       for (N = 15; N > 1; N--) {
+               /* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */
+               RN = N * request;
+               quo = RN / input;
+               rem = RN % input;/* rem always small than 14318181 */
+               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;
+                       if (M < 256 && M > 0) {
+                               unsigned int diff;
+                               tmpClock = pll->inputFreq *M / N / X;
+                               diff = absDiff(tmpClock, request_orig);
+                               if (diff < miniDiff) {
+                                       pll->M = M;
+                                       pll->N = N;
+                                       pll->OD = xparm[d].od;
+                                       pll->POD = xparm[d].pod;
+                                       miniDiff = diff;
+                                       ret = tmpClock;
+                               }
+                       }
+               }
+       }
+
+       //printk("Finally:  pll->n[%lu],m[%lu],od[%lu],pod[%lu]\n",pll->N,pll->M,pll->OD,pll->POD);
+       return ret;
+}
+
+unsigned int calcPllValue2(
+unsigned int ulRequestClk, /* Required pixel clock in Hz unit */
+pll_value_t *pPLL           /* Structure to hold the value to be set in PLL */
+)
+{
+       unsigned int M, N, OD, POD = 0, diff, pllClk, odPower, podPower;
+       unsigned int bestDiff = 0xffffffff; /* biggest 32 bit unsigned number */
+       unsigned int ret;
+    /* Init PLL structure to know states */
+       pPLL->M = 0;
+       pPLL->N = 0;
+       pPLL->OD = 0;
+       pPLL->POD = 0;
+
+    /* Sanity check: None at the moment */
+
+    /* Convert everything in Khz range in order to avoid calculation overflow */
+       pPLL->inputFreq /= 1000;
+       ulRequestClk /= 1000;
+
+#ifndef VALIDATION_CHIP
+    /* The maximum of post divider is 8. */
+       for (POD = 0; POD <= 3; POD++)
+#endif
+               {
+
+#ifndef VALIDATION_CHIP
+       /* MXCLK_PLL does not have post divider. */
+       if ((POD > 0) && (pPLL->clockType == MXCLK_PLL))
+               break;
+#endif
+
+       /* Work out 2 to the power of POD */
+       podPower = twoToPowerOfx(POD);
+
+       /* OD has only 2 bits [15:14] and its value must between 0 to 3 */
+       for (OD = 0; OD <= 3; OD++) {
+               /* Work out 2 to the power of OD */
+               odPower = twoToPowerOfx(OD);
+
+#ifdef VALIDATION_CHIP
+       if (odPower > 4)
+               podPower = 4;
+       else
+               podPower = odPower;
+#endif
+
+               /* N has 4 bits [11:8] and its value must between 2 and 15.
+               The N == 1 will behave differently --> Result is not correct. */
+       for (N = 2; N <= 15; N++) {
+               /* The formula for PLL is ulRequestClk = inputFreq * M / N / (2^OD)
+               In the following steps, we try to work out a best M value given the others are known.
+               To avoid decimal calculation, we use 1000 as multiplier for up to 3 decimal places of accuracy.
+               */
+               M = ulRequestClk * N * odPower * 1000 / pPLL->inputFreq;
+               M = roundedDiv(M, 1000);
+
+               /* M field has only 8 bits, reject value bigger than 8 bits */
+               if (M < 256) {
+                       /* Calculate the actual clock for a given M & N */
+                       pllClk = pPLL->inputFreq * M / N / odPower / podPower;
+
+                       /* How much are we different from the requirement */
+                       diff = absDiff(pllClk, ulRequestClk);
+
+                       if (diff < bestDiff) {
+                               bestDiff = diff;
+
+                               /* Store M and N values */
+                               pPLL->M  = M;
+                               pPLL->N  = N;
+                               pPLL->OD = OD;
+
+#ifdef VALIDATION_CHIP
+                       if (OD > 2)
+                               POD = 2;
+                       else
+                               POD = OD;
+#endif
+
+                       pPLL->POD = POD;
+                       }
+               }
+       }
+       }
+       }
+
+    /* Restore input frequency from Khz to hz unit */
+//    pPLL->inputFreq *= 1000;
+       ulRequestClk *= 1000;
+       pPLL->inputFreq = DEFAULT_INPUT_CLOCK; /* Default reference clock */
+
+    /* Output debug information */
+       //DDKDEBUGPRINT((DISPLAY_LEVEL, "calcPllValue: Requested Frequency = %d\n", ulRequestClk));
+       //DDKDEBUGPRINT((DISPLAY_LEVEL, "calcPllValue: Input CLK = %dHz, M=%d, N=%d, OD=%d, POD=%d\n", pPLL->inputFreq, pPLL->M, pPLL->N, pPLL->OD, pPLL->POD));
+
+    /* Return actual frequency that the PLL can set */
+       ret = calcPLL(pPLL);
+       return ret;
+}
+
+
+
+
+
+unsigned int formatPllReg(pll_value_t *pPLL)
+{
+       unsigned int ulPllReg = 0;
+
+    /* Note that all PLL's have the same format. Here, we just use Panel PLL parameter
+       to work out the bit fields in the register.
+       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)
+#ifndef VALIDATION_CHIP
+       | FIELD_VALUE(0, PANEL_PLL_CTRL, POD,    pPLL->POD)
+#endif
+       | FIELD_VALUE(0, PANEL_PLL_CTRL, OD,     pPLL->OD)
+       | FIELD_VALUE(0, PANEL_PLL_CTRL, N,      pPLL->N)
+       | FIELD_VALUE(0, PANEL_PLL_CTRL, M,      pPLL->M);
+
+    return ulPllReg;
+}
+
+
diff --git a/drivers/staging/sm750fb/ddk750_chip.h b/drivers/staging/sm750fb/ddk750_chip.h
new file mode 100644 (file)
index 0000000..04cb0d5
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef DDK750_CHIP_H__
+#define DDK750_CHIP_H__
+#define DEFAULT_INPUT_CLOCK 14318181 /* Default reference clock */
+#ifndef SM750LE_REVISION_ID
+#define SM750LE_REVISION_ID ((unsigned char)0xfe)
+#endif
+
+#include <linux/io.h>
+
+/* This is all the chips recognized by this library */
+typedef enum _logical_chip_type_t
+{
+    SM_UNKNOWN,
+    SM718,
+    SM750,
+    SM750LE,
+}
+logical_chip_type_t;
+
+
+typedef enum _clock_type_t
+{
+       MXCLK_PLL,
+       PRIMARY_PLL,
+       SECONDARY_PLL,
+       VGA0_PLL,
+       VGA1_PLL,
+}
+clock_type_t;
+
+typedef struct _pll_value_t
+{
+    clock_type_t clockType;
+    unsigned long inputFreq; /* Input clock frequency to the PLL */
+
+    /* Use this when clockType = PANEL_PLL */
+    unsigned long M;
+    unsigned long N;
+    unsigned long OD;
+    unsigned long POD;
+}
+pll_value_t;
+
+/* input struct to initChipParam() function */
+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
+                                    0 = keep the current clock setting
+                                    Others = the new main chip clock
+                                  */
+    unsigned short memClock;     /* Speed of memory clock in MHz unit
+                                    0 = keep the current clock setting
+                                    Others = the new memory clock
+                                  */
+    unsigned short masterClock;  /* Speed of master clock in MHz unit
+                                    0 = keep the current clock setting
+                                    Others = the new master clock
+                                  */
+    unsigned short setAllEngOff; /* 0 = leave all engine state untouched.
+                                    1 = make sure they are off: 2D, Overlay,
+                                    video alpha, alpha, hardware cursors
+                                 */
+    unsigned char resetMemory;   /* 0 = Do not reset the memory controller
+                                    1 = Reset the memory controller
+                                  */
+
+    /* More initialization parameter can be added if needed */
+}
+initchip_param_t;
+
+
+logical_chip_type_t getChipType(void);
+unsigned int calcPllValue(unsigned int request,pll_value_t *pll);
+unsigned int calcPllValue2(unsigned int,pll_value_t *);
+unsigned int formatPllReg(pll_value_t *pPLL);
+void ddk750_set_mmio(void __iomem *,unsigned short,char);
+unsigned int ddk750_getVMSize(void);
+int ddk750_initHw(initchip_param_t *);
+unsigned int getPllValue(clock_type_t clockType, pll_value_t *pPLL);
+unsigned int getChipClock(void);
+void setChipClock(unsigned int);
+void setMemoryClock(unsigned int frequency);
+void setMasterClock(unsigned int frequency);
+
+
+#endif
diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c
new file mode 100644 (file)
index 0000000..c84196a
--- /dev/null
@@ -0,0 +1,307 @@
+#include "ddk750_reg.h"
+#include "ddk750_help.h"
+#include "ddk750_display.h"
+#include "ddk750_power.h"
+#include "ddk750_dvi.h"
+
+#define primaryWaitVerticalSync(delay) waitNextVerticalSync(0,delay)
+
+static void setDisplayControl(int ctrl,int dispState)
+{
+       /* state != 0 means turn on both timing & plane en_bit */
+       unsigned long ulDisplayCtrlReg, ulReservedBits;
+       int cnt;
+
+       cnt = 0;
+
+       /* Set the primary display control */
+       if (!ctrl)
+       {
+               ulDisplayCtrlReg = PEEK32(PANEL_DISPLAY_CTRL);
+               /* Turn on/off the Panel display control */
+               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);
+
+                       ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
+                                                               PANEL_DISPLAY_CTRL, PLANE, ENABLE);
+
+                       /* Added some masks to mask out the reserved bits.
+                        * Sometimes, the reserved bits are set/reset randomly when
+                        * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register
+                        * reserved bits are needed to be masked out.
+                        */
+                       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);
+
+                       /* Somehow the register value on the plane is not set
+                        * until a few delay. Need to write
+                        * and read it a couple times
+                        */
+                       do
+                       {
+                               cnt++;
+                               POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
+                       } while((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) !=
+                                       (ulDisplayCtrlReg & ~ulReservedBits));
+                       printk("Set Panel Plane enbit:after tried %d times\n",cnt);
+               }
+               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.
+                        * Note: Modifying the plane bit will take effect on the
+                        * next vertical sync. Need to find out if it is necessary to
+                        * wait for 1 vsync before modifying the timing enable bit.
+                        * */
+                       ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
+                                                               PANEL_DISPLAY_CTRL, PLANE, DISABLE);
+                       POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
+
+                       ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
+                                                               PANEL_DISPLAY_CTRL, TIMING, DISABLE);
+                       POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
+               }
+
+       }
+       /* Set the secondary display control */
+       else
+       {
+               ulDisplayCtrlReg = PEEK32(CRT_DISPLAY_CTRL);
+
+               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,
+                                                               CRT_DISPLAY_CTRL, TIMING, ENABLE);
+                       POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
+
+                       ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
+                                                               CRT_DISPLAY_CTRL, PLANE, ENABLE);
+
+                       /* Added some masks to mask out the reserved bits.
+                        * Sometimes, the reserved bits are set/reset randomly when
+                        * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register
+                        * reserved bits are needed to be masked out.
+                        */
+
+                       ulReservedBits = FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
+                               FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
+                               FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) |
+                               FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_4_MASK, ENABLE);
+
+                       do
+                       {
+                               cnt++;
+                               POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
+                       } while((PEEK32(CRT_DISPLAY_CTRL) & ~ulReservedBits) !=
+                                       (ulDisplayCtrlReg & ~ulReservedBits));
+                               printk("Set Crt Plane enbit:after tried %d times\n",cnt);
+               }
+               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.
+                        * Note: Modifying the plane bit will take effect on the next
+                        * vertical sync. Need to find out if it is necessary to
+                        * wait for 1 vsync before modifying the timing enable bit.
+                        */
+                       ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
+                                                               CRT_DISPLAY_CTRL, PLANE, DISABLE);
+                       POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
+
+                       ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
+                                                               CRT_DISPLAY_CTRL, TIMING, DISABLE);
+                       POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
+               }
+       }
+}
+
+
+static void waitNextVerticalSync(int ctrl,int delay)
+{
+       unsigned int status;
+       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. */
+               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))
+               {
+                       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{
+
+               /* 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))
+               {
+                       return;
+               }
+
+               while (delay-- > 0)
+               {
+                       /* Wait for end of vsync. */
+                       do
+                       {
+                               status = FIELD_GET(PEEK32(SYSTEM_CTRL),
+                                                                  SYSTEM_CTRL,
+                                                                  CRT_VSYNC);
+                       }
+                       while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE);
+
+                       /* Wait for start of vsync. */
+                       do
+                       {
+                               status = FIELD_GET(PEEK32(SYSTEM_CTRL),
+                                                                  SYSTEM_CTRL,
+                                                                  CRT_VSYNC);
+                       }
+                       while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE);
+               }
+       }
+}
+
+static void swPanelPowerSequence(int disp,int delay)
+{
+       unsigned int reg;
+
+       /* disp should be 1 to open sequence */
+       reg = PEEK32(PANEL_DISPLAY_CTRL);
+       reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,FPEN,disp);
+       POKE32(PANEL_DISPLAY_CTRL,reg);
+       primaryWaitVerticalSync(delay);
+
+
+       reg = PEEK32(PANEL_DISPLAY_CTRL);
+       reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,DATA,disp);
+       POKE32(PANEL_DISPLAY_CTRL,reg);
+       primaryWaitVerticalSync(delay);
+
+       reg = PEEK32(PANEL_DISPLAY_CTRL);
+       reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,VBIASEN,disp);
+       POKE32(PANEL_DISPLAY_CTRL,reg);
+       primaryWaitVerticalSync(delay);
+
+
+       reg = PEEK32(PANEL_DISPLAY_CTRL);
+       reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,FPEN,disp);
+       POKE32(PANEL_DISPLAY_CTRL,reg);
+       primaryWaitVerticalSync(delay);
+
+}
+
+void ddk750_setLogicalDispOut(disp_output_t output)
+{
+       unsigned int reg;
+       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){
+               /* 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);
+               /*se blank off */
+               reg = FIELD_SET(reg,CRT_DISPLAY_CTRL,BLANK,OFF);
+               POKE32(CRT_DISPLAY_CTRL,reg);
+
+       }
+
+       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){
+               /* set secondary timing and plane en_bit*/
+               setDisplayControl(1,(output&SEC_TP_MASK)>>SEC_TP_OFFSET);
+       }
+
+       if(output & PNL_SEQ_USAGE){
+               /* set  panel sequence */
+               swPanelPowerSequence((output&PNL_SEQ_MASK)>>PNL_SEQ_OFFSET,4);
+       }
+
+       if(output & DAC_USAGE)
+               setDAC((output & DAC_MASK)>>DAC_OFFSET);
+
+       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;
+
+}
+
diff --git a/drivers/staging/sm750fb/ddk750_display.h b/drivers/staging/sm750fb/ddk750_display.h
new file mode 100644 (file)
index 0000000..ae0f84c
--- /dev/null
@@ -0,0 +1,160 @@
+#ifndef DDK750_DISPLAY_H__
+#define DDK750_DISPLAY_H__
+
+/* panel path select
+       80000[29:28]
+*/
+
+#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_SEC      ((2 << PNL_2_OFFSET)|PNL_2_USAGE)
+
+
+/* primary timing & plane enable bit
+       1: 80000[8] & 80000[2] on
+       0: both off
+*/
+#define PRI_TP_OFFSET 4
+#define PRI_TP_MASK (1 << PRI_TP_OFFSET)
+#define PRI_TP_USAGE (PRI_TP_MASK << 16)
+#define PRI_TP_ON ((0x1 << PRI_TP_OFFSET)|PRI_TP_USAGE)
+#define PRI_TP_OFF ((0x0 << PRI_TP_OFFSET)|PRI_TP_USAGE)
+
+
+/* panel sequency status
+       80000[27:24]
+*/
+#define PNL_SEQ_OFFSET 6
+#define PNL_SEQ_MASK (1 << PNL_SEQ_OFFSET)
+#define PNL_SEQ_USAGE (PNL_SEQ_MASK << 16)
+#define PNL_SEQ_ON ((1 << PNL_SEQ_OFFSET)|PNL_SEQ_USAGE)
+#define PNL_SEQ_OFF ((0 << PNL_SEQ_OFFSET)|PNL_SEQ_USAGE)
+
+/* dual digital output
+       80000[19]
+*/
+#define DUAL_TFT_OFFSET 8
+#define DUAL_TFT_MASK (1 << DUAL_TFT_OFFSET)
+#define DUAL_TFT_USAGE (DUAL_TFT_MASK << 16)
+#define DUAL_TFT_ON ((1 << DUAL_TFT_OFFSET)|DUAL_TFT_USAGE)
+#define DUAL_TFT_OFF ((0 << DUAL_TFT_OFFSET)|DUAL_TFT_USAGE)
+
+/* secondary timing & plane enable bit
+       1:80200[8] & 80200[2] on
+       0: both off
+*/
+#define SEC_TP_OFFSET 5
+#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)
+
+/* crt path select
+       80200[19:18]
+*/
+#define CRT_2_OFFSET 2
+#define CRT_2_MASK (3 << CRT_2_OFFSET)
+#define CRT_2_USAGE (CRT_2_MASK << 16)
+#define CRT_2_PRI ((0x0 << CRT_2_OFFSET)|CRT_2_USAGE)
+#define CRT_2_SEC ((0x2 << CRT_2_OFFSET)|CRT_2_USAGE)
+
+
+/* DAC affect both DVI and DSUB
+       4[20]
+*/
+#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_OFF ((0x1 << DAC_OFFSET)|DAC_USAGE)
+
+/* DPMS only affect D-SUB head
+       0[31:30]
+*/
+#define DPMS_OFFSET 9
+#define DPMS_MASK (3 << DPMS_OFFSET)
+#define DPMS_USAGE (DPMS_MASK << 16)
+#define DPMS_OFF ((3 << DPMS_OFFSET)|DPMS_USAGE)
+#define DPMS_ON ((0 << DPMS_OFFSET)|DPMS_USAGE)
+
+
+
+/*
+       LCD1 means panel path TFT1  & panel path DVI (so enable DAC)
+       CRT means crt path DSUB
+*/
+#if 0
+typedef enum _disp_output_t
+{
+       NO_DISPLAY = DPMS_OFF,
+
+       LCD1_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DPMS_OFF|DAC_ON,
+       LCD1_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DPMS_OFF|DAC_ON,
+
+       LCD2_PRI = CRT_2_PRI|PRI_TP_ON|DUAL_TFT_ON|DPMS_OFF,
+       LCD2_SEC = CRT_2_SEC|SEC_TP_ON|DUAL_TFT_ON|DPMS_OFF,
+
+       DSUB_PRI = CRT_2_PRI|PRI_TP_ON|DAC_ON,
+       DSUB_SEC = CRT_2_SEC|SEC_TP_ON|DAC_ON,
+
+       LCD1_DSUB_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|
+                                       CRT_2_PRI|SEC_TP_OFF|DAC_ON,
+
+       LCD1_DSUB_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|
+                                       CRT_2_SEC|PRI_TP_OFF|DAC_ON,
+
+       /* LCD1 show primary and DSUB show secondary */
+       LCD1_DSUB_DUAL = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|
+                                        CRT_2_SEC|SEC_TP_ON|DAC_ON,
+
+       /* LCD1 show secondary and DSUB show primary */
+       LCD1_DSUB_DUAL_SWAP = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|
+                                                       CRT_2_PRI|PRI_TP_ON|DAC_ON,
+
+       LCD1_LCD2_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|
+                                       CRT_2_PRI|SEC_TP_OFF|DPMS_OFF|DUAL_TFT_ON,
+
+       LCD1_LCD2_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|
+                                       CRT_2_SEC|PRI_TP_OFF|DPMS_OFF|DUAL_TFT_ON,
+
+       LCD1_LCD2_DSUB_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DAC_ON|
+                                               CRT_2_PRI|SEC_TP_OFF|DPMS_ON|DUAL_TFT_ON,
+
+       LCD1_LCD2_DSUB_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DAC_ON|
+                                               CRT_2_SEC|PRI_TP_OFF|DPMS_ON|DUAL_TFT_ON,
+
+
+}
+disp_output_t;
+#else
+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
+       do_LCD2_PRI = CRT_2_PRI|PRI_TP_ON,
+       do_LCD2_SEC = CRT_2_SEC|SEC_TP_ON,
+#else
+       do_LCD2_PRI = CRT_2_PRI|PRI_TP_ON|DUAL_TFT_ON,
+       do_LCD2_SEC = CRT_2_SEC|SEC_TP_ON|DUAL_TFT_ON,
+#endif
+       /*
+       do_DSUB_PRI = CRT_2_PRI|PRI_TP_ON|DPMS_ON|DAC_ON,
+       do_DSUB_SEC = CRT_2_SEC|SEC_TP_ON|DPMS_ON|DAC_ON,
+       */
+#if 0
+       do_CRT_PRI = CRT_2_PRI|PRI_TP_ON,
+       do_CRT_SEC = CRT_2_SEC|SEC_TP_ON,
+#else
+       do_CRT_PRI = CRT_2_PRI|PRI_TP_ON|DPMS_ON|DAC_ON,
+       do_CRT_SEC = CRT_2_SEC|SEC_TP_ON|DPMS_ON|DAC_ON,
+#endif
+}
+disp_output_t;
+#endif
+
+void ddk750_setLogicalDispOut(disp_output_t);
+int ddk750_initDVIDisp(void);
+
+#endif
diff --git a/drivers/staging/sm750fb/ddk750_dvi.c b/drivers/staging/sm750fb/ddk750_dvi.c
new file mode 100644 (file)
index 0000000..f5932bb
--- /dev/null
@@ -0,0 +1,99 @@
+#define USE_DVICHIP 
+#ifdef USE_DVICHIP
+#include "ddk750_help.h"
+#include "ddk750_reg.h"
+#include "ddk750_dvi.h"
+#include "ddk750_sii164.h"
+
+
+/* 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[] =
+{
+#ifdef DVI_CTRL_SII164
+    {
+        .pfnInit = sii164InitChip,
+        .pfnGetVendorId = sii164GetVendorID,
+        .pfnGetDeviceId = sii164GetDeviceID,
+#ifdef SII164_FULL_FUNCTIONS
+        .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
+                       )
+{
+       dvi_ctrl_device_t *pCurrentDviCtrl;
+       pCurrentDviCtrl = g_dcftSupportedDviController;
+       if(pCurrentDviCtrl->pfnInit != NULL)
+       {
+               return pCurrentDviCtrl->pfnInit(edgeSelect, busSelect, dualEdgeClkSelect, hsyncEnable,
+                              vsyncEnable, deskewEnable, deskewSetting, continuousSyncEnable,
+                              pllFilterEnable, pllFilterValue);
+       }
+       return -1;//error
+}
+
+
+/*
+ *  dviGetVendorID
+ *      This function gets the vendor ID of the DVI controller chip.
+ *
+ *  Output:
+ *      Vendor ID
+ */
+unsigned short dviGetVendorID(void)
+{
+    dvi_ctrl_device_t *pCurrentDviCtrl;
+
+    //pCurrentDviCtrl = getDviCtrl();
+    pCurrentDviCtrl = g_dcftSupportedDviController;
+    if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0)
+        return pCurrentDviCtrl->pfnGetVendorId();
+
+    return 0x0000;
+}
+
+
+/*
+ *  dviGetDeviceID
+ *      This function gets the device ID of the DVI controller chip.
+ *
+ *  Output:
+ *      Device ID
+ */
+unsigned short dviGetDeviceID(void)
+{
+    dvi_ctrl_device_t *pCurrentDviCtrl;
+
+//    pCurrentDviCtrl = getDviCtrl();
+       pCurrentDviCtrl = g_dcftSupportedDviController;
+    if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0)
+        return pCurrentDviCtrl->pfnGetDeviceId();
+
+    return 0x0000;
+}
+
+#endif
+
+
diff --git a/drivers/staging/sm750fb/ddk750_dvi.h b/drivers/staging/sm750fb/ddk750_dvi.h
new file mode 100644 (file)
index 0000000..50bcec2
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef DDK750_DVI_H__
+#define DDK750_DVI_H__
+
+/* dvi chip stuffs structros */
+
+typedef long (*PFN_DVICTRL_INIT)(
+    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);
+typedef void (*PFN_DVICTRL_RESETCHIP)(void);
+typedef char* (*PFN_DVICTRL_GETCHIPSTRING)(void);
+typedef unsigned short (*PFN_DVICTRL_GETVENDORID)(void);
+typedef unsigned short (*PFN_DVICTRL_GETDEVICEID)(void);
+typedef void (*PFN_DVICTRL_SETPOWER)(unsigned char powerUp);
+typedef void (*PFN_DVICTRL_HOTPLUGDETECTION)(unsigned char enableHotPlug);
+typedef unsigned char (*PFN_DVICTRL_ISCONNECTED)(void);
+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
+{
+    PFN_DVICTRL_INIT                pfnInit;
+    PFN_DVICTRL_RESETCHIP           pfnResetChip;
+    PFN_DVICTRL_GETCHIPSTRING       pfnGetChipString;
+    PFN_DVICTRL_GETVENDORID         pfnGetVendorId;
+    PFN_DVICTRL_GETDEVICEID         pfnGetDeviceId;
+    PFN_DVICTRL_SETPOWER            pfnSetPower;
+    PFN_DVICTRL_HOTPLUGDETECTION    pfnEnableHotPlugDetection;
+    PFN_DVICTRL_ISCONNECTED         pfnIsConnected;
+    PFN_DVICTRL_CHECKINTERRUPT      pfnCheckInterrupt;
+    PFN_DVICTRL_CLEARINTERRUPT      pfnClearInterrupt;
+} dvi_ctrl_device_t;
+#define DVI_CTRL_SII164
+
+
+
+/* dvi functions prototype */
+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 short dviGetVendorID(void);
+unsigned short dviGetDeviceID(void);
+
+
+
+#endif
+
diff --git a/drivers/staging/sm750fb/ddk750_help.c b/drivers/staging/sm750fb/ddk750_help.c
new file mode 100644 (file)
index 0000000..c68ff3b
--- /dev/null
@@ -0,0 +1,19 @@
+//#include "ddk750_reg.h"
+//#include "ddk750_chip.h"
+#include "ddk750_help.h"
+
+void __iomem * mmio750 = NULL;
+char revId750 = 0;
+unsigned short devId750 = 0;
+
+/* after driver mapped io registers, use this function first */
+void ddk750_set_mmio(void __iomem * addr,unsigned short devId,char revId)
+{
+       mmio750 = addr;
+       devId750 = devId;
+       revId750 = revId;
+       if(revId == 0xfe)
+               printk("found sm750le\n");
+}
+
+
diff --git a/drivers/staging/sm750fb/ddk750_help.h b/drivers/staging/sm750fb/ddk750_help.h
new file mode 100644 (file)
index 0000000..07c8264
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef DDK750_HELP_H__
+#define DDK750_HELP_H__
+#include "ddk750_chip.h"
+#ifndef USE_INTERNAL_REGISTER_ACCESS
+
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "sm750_help.h"
+
+
+#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)
+#else /* software control endianess */
+#define PEEK32(addr) readl(addr + mmio750)
+#define POKE32(addr,data) writel(data, addr + mmio750)
+#endif
+
+extern void __iomem * mmio750;
+extern char revId750;
+extern unsigned short devId750;
+#else
+/* implement if you want use it*/
+#endif
+
+#endif
diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c
new file mode 100644 (file)
index 0000000..7826376
--- /dev/null
@@ -0,0 +1,271 @@
+#define USE_HW_I2C
+#ifdef USE_HW_I2C
+#include "ddk750_help.h"
+#include "ddk750_reg.h"
+#include "ddk750_hwi2c.h"
+#include "ddk750_power.h"
+
+#define MAX_HWI2C_FIFO                  16
+#define HWI2C_WAIT_TIMEOUT              0xF0000
+
+
+int hwI2CInit(
+    unsigned char busSpeedMode
+)
+{
+    unsigned int value;
+
+    /* 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);
+       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;
+}
+
+
+void hwI2CClose(void)
+{
+    unsigned int 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);
+
+    /* 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;
+
+    /* 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--;
+
+       if (timeout == 0)
+           return (-1);
+
+    return 0;
+}
+
+
+
+/*
+ *  This function writes data to the i2c slave device registers.
+ *
+ *  Parameters:
+ *      deviceAddress   - i2c Slave device address
+ *      length          - Total number of bytes to be written to the device
+ *      pBuffer         - The buffer that contains the data to be written to the
+ *                     i2c device.
+ *
+ *  Return Value:
+ *      Total number of bytes those are actually written.
+ */
+static unsigned int hwI2CWriteData(
+    unsigned char deviceAddress,
+    unsigned int length,
+    unsigned char *pBuffer
+)
+{
+    unsigned char count, i;
+    unsigned int totalBytes = 0;
+
+    /* 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);
+
+        /* 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++);
+
+        /* 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;
+
+        /* Substract length */
+        length -= (count + 1);
+
+        /* Total byte written */
+        totalBytes += (count + 1);
+
+    } while (length > 0);
+
+    return totalBytes;
+}
+
+
+
+
+/*
+ *  This function reads data from the slave device and stores them
+ *  in the given buffer
+ *
+ *  Parameters:
+ *      deviceAddress   - i2c Slave device address
+ *      length          - Total number of bytes to be read
+ *      pBuffer         - Pointer to a buffer to be filled with the data read
+ *                     from the slave device. It has to be the same size as the
+ *                     length to make sure that it can keep all the data read.
+ *
+ *  Return Value:
+ *      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 count, i;
+    unsigned int totalBytes = 0;
+
+    /* 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);
+
+        /* 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));
+
+        /* 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);
+
+        /* Substract length by 16 */
+        length -= (count + 1);
+
+        /* Number of bytes read. */
+        totalBytes += (count + 1);
+
+    } while (length > 0);
+
+    return totalBytes;
+}
+
+
+
+
+/*
+ *  This function reads the slave device's register
+ *
+ *  Parameters:
+ *      deviceAddress   - i2c Slave device address which register
+ *                        to be read from
+ *      registerIndex   - Slave device's register to be read
+ *
+ *  Return Value:
+ *      Register value
+ */
+unsigned char hwI2CReadReg(
+    unsigned char deviceAddress,
+    unsigned char registerIndex
+)
+{
+    unsigned char value = (0xFF);
+
+    if (hwI2CWriteData(deviceAddress, 1, &registerIndex) == 1)
+        hwI2CReadData(deviceAddress, 1, &value);
+
+    return value;
+}
+
+
+
+
+
+/*
+ *  This function writes a value to the slave device's register
+ *
+ *  Parameters:
+ *      deviceAddress   - i2c Slave device address which register
+ *                        to be written
+ *      registerIndex   - Slave device's register to be written
+ *      data            - Data to be written to the register
+ *
+ *  Result:
+ *          0   - Success
+ *         -1   - Fail
+ */
+int hwI2CWriteReg(
+    unsigned char deviceAddress,
+    unsigned char registerIndex,
+    unsigned char data
+)
+{
+    unsigned char value[2];
+
+    value[0] = registerIndex;
+    value[1] = data;
+    if (hwI2CWriteData(deviceAddress, 2, value) == 2)
+        return 0;
+
+    return (-1);
+}
+
+
+#endif
diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.h b/drivers/staging/sm750fb/ddk750_hwi2c.h
new file mode 100644 (file)
index 0000000..ad31149
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef DDK750_HWI2C_H__
+#define DDK750_HWI2C_H__
+
+/* hwi2c functions */
+int hwI2CInit(unsigned char busSpeedMode);
+void hwI2CClose(void);
+
+unsigned char hwI2CReadReg(unsigned char deviceAddress,unsigned char registerIndex);
+int hwI2CWriteReg(unsigned char deviceAddress,unsigned char registerIndex,unsigned char data);
+#endif
diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c
new file mode 100644 (file)
index 0000000..2e418fb
--- /dev/null
@@ -0,0 +1,205 @@
+
+#include "ddk750_help.h"
+#include "ddk750_reg.h"
+#include "ddk750_mode.h"
+#include "ddk750_chip.h"
+
+/*
+       SM750LE only:
+    This function takes care extra registers and bit fields required to set
+    up a mode in SM750LE
+
+       Explanation about Display Control register:
+    HW only supports 7 predefined pixel clocks, and clock select is
+    in bit 29:27 of    Display Control register.
+*/
+static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, unsigned long dispControl)
+{
+       unsigned long x, y;
+
+       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.
+    */
+
+       /* Clear bit 29:27 of display control register */
+    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);
+       else if (x == 1024 && y == 768)
+       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL65);
+       else if (x == 1152 && y == 864)
+       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
+       else if (x == 1280 && y == 768)
+       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
+       else if (x == 1280 && y == 720)
+       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL74);
+       else if (x == 1280 && y == 960)
+       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
+       else if (x == 1280 && y == 1024)
+       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
+       else /* default to VGA clock */
+       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);
+
+    /* Set bit 14 of display controller */
+    dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLOCK_PHASE, ACTIVE_LOW);
+
+    POKE32(CRT_DISPLAY_CTRL, dispControl);
+
+       return dispControl;
+}
+
+
+
+/* only timing related registers will be  programed */
+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)
+       {
+               /* 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_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_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)|
+                                         FIELD_VALUE(0,CRT_DISPLAY_CTRL,HSYNC_PHASE,pModeParam->horizontal_sync_polarity)|
+                                         FIELD_SET(0,CRT_DISPLAY_CTRL,TIMING,ENABLE)|
+                                         FIELD_SET(0,CRT_DISPLAY_CTRL,PLANE,ENABLE);
+
+
+               if(getChipType() == SM750LE){
+                       displayControlAdjust_SM750LE(pModeParam,ulTmpValue);
+               }else{
+                       ulReg = PEEK32(CRT_DISPLAY_CTRL)
+                                       & FIELD_CLEAR(CRT_DISPLAY_CTRL,VSYNC_PHASE)
+                                       & FIELD_CLEAR(CRT_DISPLAY_CTRL,HSYNC_PHASE)
+                                       & FIELD_CLEAR(CRT_DISPLAY_CTRL,TIMING)
+                                       & FIELD_CLEAR(CRT_DISPLAY_CTRL,PLANE);
+
+                        POKE32(CRT_DISPLAY_CTRL,ulTmpValue|ulReg);
+               }
+
+       }
+       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_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_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);
+
+        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);
+
+
+               /* May a hardware bug or just my test chip (not confirmed).
+               * PANEL_DISPLAY_CTRL register seems requiring few writes
+               * before a value can be succesfully written in.
+               * Added some masks to mask out the reserved bits.
+               * Note: This problem happens by design. The hardware will wait for the
+               *       next vertical sync to turn on/off the plane.
+               */
+
+               POKE32(PANEL_DISPLAY_CTRL,ulTmpValue|ulReg);
+#if 1
+               while((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg))
+               {
+                       cnt++;
+                       if(cnt > 1000)
+                               break;
+                       POKE32(PANEL_DISPLAY_CTRL,ulTmpValue|ulReg);
+               }
+#endif
+       }
+       else{
+               ret = -1;
+       }
+       return ret;
+}
+
+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){
+               /* set graphic mode via IO method */
+               outb_p(0x88,0x3d4);
+               outb_p(0x06,0x3d5);
+       }
+       programModeRegisters(parm,&pll);
+       return 0;
+}
+
+
diff --git a/drivers/staging/sm750fb/ddk750_mode.h b/drivers/staging/sm750fb/ddk750_mode.h
new file mode 100644 (file)
index 0000000..6f8df96
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef DDK750_MODE_H__
+#define DDK750_MODE_H__
+
+#include "ddk750_chip.h"
+
+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;
+}
+mode_parameter_t;
+
+int ddk750_setModeTiming(mode_parameter_t *,clock_type_t);
+
+
+#endif
diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c
new file mode 100644 (file)
index 0000000..cbb9767
--- /dev/null
@@ -0,0 +1,239 @@
+#include "ddk750_help.h"
+#include "ddk750_reg.h"
+#include "ddk750_power.h"
+
+void ddk750_setDPMS(DPMS_t state)
+{
+       unsigned int value;
+       if(getChipType() == SM750LE){
+               value = PEEK32(CRT_DISPLAY_CTRL);
+               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);
+               POKE32(SYSTEM_CTRL, value);
+       }
+}
+
+unsigned int getPowerMode(void)
+{
+       if(getChipType() == SM750LE)
+               return 0;
+    return (FIELD_GET(PEEK32(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE));
+}
+
+
+/*
+ * SM50x can operate in one of three modes: 0, 1 or Sleep.
+ * On hardware reset, power mode 0 is default.
+ */
+void setPowerMode(unsigned int powerMode)
+{
+    unsigned int control_value = 0;
+
+    control_value = PEEK32(POWER_MODE_CTRL);
+
+       if(getChipType() == SM750LE)
+               return;
+
+    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_SLEEP:
+            control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, SLEEP);
+            break;
+
+        default:
+            break;
+    }
+
+    /* 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) |
+#endif
+            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) |
+#endif
+            FIELD_SET(  control_value, POWER_MODE_CTRL, OSC_INPUT,  ON);
+    }
+
+    /* 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);
+}
+
+
+
+/*
+ * This function enable/disable the 2D engine.
+ */
+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);
+}
+
+
+/*
+ * This function enable/disable the ZV Port.
+ */
+void enableZVPort(unsigned int enable)
+{
+    uint32_t gate;
+
+    /* 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);
+#else
+        /* 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);
+}
+
+
+void enableSSP(unsigned int enable)
+{
+    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);
+
+    setCurrentGate(gate);
+}
+
+void enableDMA(unsigned int enable)
+{
+    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);
+
+    setCurrentGate(gate);
+}
+
+/*
+ * This function enable/disable the GPIO Engine
+ */
+void enableGPIO(unsigned int enable)
+{
+    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);
+
+    setCurrentGate(gate);
+}
+
+/*
+ * This function enable/disable the PWM Engine
+ */
+void enablePWM(unsigned int enable)
+{
+    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);
+
+    setCurrentGate(gate);
+}
+
+/*
+ * This function enable/disable the I2C Engine
+ */
+void enableI2C(unsigned int enable)
+{
+    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);
+
+    setCurrentGate(gate);
+}
+
+
diff --git a/drivers/staging/sm750fb/ddk750_power.h b/drivers/staging/sm750fb/ddk750_power.h
new file mode 100644 (file)
index 0000000..71dc7f9
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef DDK750_POWER_H__
+#define DDK750_POWER_H__
+
+typedef enum _DPMS_t
+{
+    crtDPMS_ON = 0x0,
+    crtDPMS_STANDBY = 0x1,
+    crtDPMS_SUSPEND = 0x2,
+    crtDPMS_OFF = 0x3,
+}
+DPMS_t;
+
+#define setDAC(off) \
+               {       \
+               POKE32(MISC_CTRL,FIELD_VALUE(PEEK32(MISC_CTRL), \
+                                                                       MISC_CTRL,      \
+                                                                       DAC_POWER,      \
+                                                                       off));  \
+               }
+
+void ddk750_setDPMS(DPMS_t);
+
+unsigned int getPowerMode(void);
+
+/*
+ * This function sets the current power mode
+ */
+void setPowerMode(unsigned int powerMode);
+
+/*
+ * This function sets current gate
+ */
+void setCurrentGate(unsigned int gate);
+
+/*
+ * This function enable/disable the 2D engine.
+ */
+void enable2DEngine(unsigned int enable);
+
+/*
+ * This function enable/disable the ZV Port
+ */
+void enableZVPort(unsigned int enable);
+
+/*
+ * This function enable/disable the DMA Engine
+ */
+void enableDMA(unsigned int enable);
+
+/*
+ * This function enable/disable the GPIO Engine
+ */
+void enableGPIO(unsigned int enable);
+
+/*
+ * This function enable/disable the PWM Engine
+ */
+void enablePWM(unsigned int enable);
+
+/*
+ * This function enable/disable the I2C Engine
+ */
+void enableI2C(unsigned int enable);
+
+/*
+ * This function enable/disable the SSP.
+ */
+void enableSSP(unsigned int enable);
+
+
+#endif
diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h
new file mode 100644 (file)
index 0000000..2016f97
--- /dev/null
@@ -0,0 +1,2616 @@
+#ifndef DDK750_REG_H__
+#define DDK750_REG_H__
+
+/* New register for SM750LE */
+#define DE_STATE1                                        0x100054
+#define DE_STATE1_DE_ABORT                               0:0
+#define DE_STATE1_DE_ABORT_OFF                           0
+#define DE_STATE1_DE_ABORT_ON                            1
+
+#define DE_STATE2                                        0x100058
+#define DE_STATE2_DE_FIFO                                3:3
+#define DE_STATE2_DE_FIFO_NOTEMPTY                       0
+#define DE_STATE2_DE_FIFO_EMPTY                          1
+#define DE_STATE2_DE_STATUS                              2:2
+#define DE_STATE2_DE_STATUS_IDLE                         0
+#define DE_STATE2_DE_STATUS_BUSY                         1
+#define DE_STATE2_DE_MEM_FIFO                            1:1
+#define DE_STATE2_DE_MEM_FIFO_NOTEMPTY                   0
+#define DE_STATE2_DE_MEM_FIFO_EMPTY                      1
+#define DE_STATE2_DE_RESERVED                            0:0
+
+
+
+#define SYSTEM_CTRL                                   0x000000
+#define SYSTEM_CTRL_DPMS                              31:30
+#define SYSTEM_CTRL_DPMS_VPHP                         0
+#define SYSTEM_CTRL_DPMS_VPHN                         1
+#define SYSTEM_CTRL_DPMS_VNHP                         2
+#define SYSTEM_CTRL_DPMS_VNHN                         3
+#define SYSTEM_CTRL_PCI_BURST                         29:29
+#define SYSTEM_CTRL_PCI_BURST_OFF                     0
+#define SYSTEM_CTRL_PCI_BURST_ON                      1
+#define SYSTEM_CTRL_PCI_MASTER                        25:25
+#define SYSTEM_CTRL_PCI_MASTER_OFF                    0
+#define SYSTEM_CTRL_PCI_MASTER_ON                     1
+#define SYSTEM_CTRL_LATENCY_TIMER                     24:24
+#define SYSTEM_CTRL_LATENCY_TIMER_ON                  0
+#define SYSTEM_CTRL_LATENCY_TIMER_OFF                 1
+#define SYSTEM_CTRL_DE_FIFO                           23:23
+#define SYSTEM_CTRL_DE_FIFO_NOTEMPTY                  0
+#define SYSTEM_CTRL_DE_FIFO_EMPTY                     1
+#define SYSTEM_CTRL_DE_STATUS                         22:22
+#define SYSTEM_CTRL_DE_STATUS_IDLE                    0
+#define SYSTEM_CTRL_DE_STATUS_BUSY                    1
+#define SYSTEM_CTRL_DE_MEM_FIFO                       21:21
+#define SYSTEM_CTRL_DE_MEM_FIFO_NOTEMPTY              0
+#define SYSTEM_CTRL_DE_MEM_FIFO_EMPTY                 1
+#define SYSTEM_CTRL_CSC_STATUS                        20:20
+#define SYSTEM_CTRL_CSC_STATUS_IDLE                   0
+#define SYSTEM_CTRL_CSC_STATUS_BUSY                   1
+#define SYSTEM_CTRL_CRT_VSYNC                         19:19
+#define SYSTEM_CTRL_CRT_VSYNC_INACTIVE                0
+#define SYSTEM_CTRL_CRT_VSYNC_ACTIVE                  1
+#define SYSTEM_CTRL_PANEL_VSYNC                       18:18
+#define SYSTEM_CTRL_PANEL_VSYNC_INACTIVE              0
+#define SYSTEM_CTRL_PANEL_VSYNC_ACTIVE                1
+#define SYSTEM_CTRL_CURRENT_BUFFER                    17:17
+#define SYSTEM_CTRL_CURRENT_BUFFER_NORMAL             0
+#define SYSTEM_CTRL_CURRENT_BUFFER_FLIP_PENDING       1
+#define SYSTEM_CTRL_DMA_STATUS                        16:16
+#define SYSTEM_CTRL_DMA_STATUS_IDLE                   0
+#define SYSTEM_CTRL_DMA_STATUS_BUSY                   1
+#define SYSTEM_CTRL_PCI_BURST_READ                    15:15
+#define SYSTEM_CTRL_PCI_BURST_READ_OFF                0
+#define SYSTEM_CTRL_PCI_BURST_READ_ON                 1
+#define SYSTEM_CTRL_DE_ABORT                          13:13
+#define SYSTEM_CTRL_DE_ABORT_OFF                      0
+#define SYSTEM_CTRL_DE_ABORT_ON                       1
+#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK                11:11
+#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK_OFF            0
+#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK_ON             1
+#define SYSTEM_CTRL_PCI_RETRY                         7:7
+#define SYSTEM_CTRL_PCI_RETRY_ON                      0
+#define SYSTEM_CTRL_PCI_RETRY_OFF                     1
+#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE         5:4
+#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_1       0
+#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_2       1
+#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_4       2
+#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_8       3
+#define SYSTEM_CTRL_CRT_TRISTATE                      3:3
+#define SYSTEM_CTRL_CRT_TRISTATE_OFF                  0
+#define SYSTEM_CTRL_CRT_TRISTATE_ON                   1
+#define SYSTEM_CTRL_PCIMEM_TRISTATE                   2:2
+#define SYSTEM_CTRL_PCIMEM_TRISTATE_OFF               0
+#define SYSTEM_CTRL_PCIMEM_TRISTATE_ON                1
+#define SYSTEM_CTRL_LOCALMEM_TRISTATE                 1:1
+#define SYSTEM_CTRL_LOCALMEM_TRISTATE_OFF             0
+#define SYSTEM_CTRL_LOCALMEM_TRISTATE_ON              1
+#define SYSTEM_CTRL_PANEL_TRISTATE                    0:0
+#define SYSTEM_CTRL_PANEL_TRISTATE_OFF                0
+#define SYSTEM_CTRL_PANEL_TRISTATE_ON                 1
+
+#define MISC_CTRL                                     0x000004
+#define MISC_CTRL_DRAM_RERESH_COUNT                   27:27
+#define MISC_CTRL_DRAM_RERESH_COUNT_1ROW              0
+#define MISC_CTRL_DRAM_RERESH_COUNT_3ROW              1
+#define MISC_CTRL_DRAM_REFRESH_TIME                   26:25
+#define MISC_CTRL_DRAM_REFRESH_TIME_8                 0
+#define MISC_CTRL_DRAM_REFRESH_TIME_16                1
+#define MISC_CTRL_DRAM_REFRESH_TIME_32                2
+#define MISC_CTRL_DRAM_REFRESH_TIME_64                3
+#define MISC_CTRL_INT_OUTPUT                          24:24
+#define MISC_CTRL_INT_OUTPUT_NORMAL                   0
+#define MISC_CTRL_INT_OUTPUT_INVERT                   1
+#define MISC_CTRL_PLL_CLK_COUNT                       23:23
+#define MISC_CTRL_PLL_CLK_COUNT_OFF                   0
+#define MISC_CTRL_PLL_CLK_COUNT_ON                    1
+#define MISC_CTRL_DAC_POWER                           20:20
+#define MISC_CTRL_DAC_POWER_ON                        0
+#define MISC_CTRL_DAC_POWER_OFF                       1
+#define MISC_CTRL_CLK_SELECT                          16:16
+#define MISC_CTRL_CLK_SELECT_OSC                      0
+#define MISC_CTRL_CLK_SELECT_TESTCLK                  1
+#define MISC_CTRL_DRAM_COLUMN_SIZE                    15:14
+#define MISC_CTRL_DRAM_COLUMN_SIZE_256                0
+#define MISC_CTRL_DRAM_COLUMN_SIZE_512                1
+#define MISC_CTRL_DRAM_COLUMN_SIZE_1024               2
+#define MISC_CTRL_LOCALMEM_SIZE                       13:12
+#define MISC_CTRL_LOCALMEM_SIZE_8M                    3
+#define MISC_CTRL_LOCALMEM_SIZE_16M                   0
+#define MISC_CTRL_LOCALMEM_SIZE_32M                   1
+#define MISC_CTRL_LOCALMEM_SIZE_64M                   2
+#define MISC_CTRL_DRAM_TWTR                           11:11
+#define MISC_CTRL_DRAM_TWTR_2CLK                      0
+#define MISC_CTRL_DRAM_TWTR_1CLK                      1
+#define MISC_CTRL_DRAM_TWR                            10:10
+#define MISC_CTRL_DRAM_TWR_3CLK                       0
+#define MISC_CTRL_DRAM_TWR_2CLK                       1
+#define MISC_CTRL_DRAM_TRP                            9:9
+#define MISC_CTRL_DRAM_TRP_3CLK                       0
+#define MISC_CTRL_DRAM_TRP_4CLK                       1
+#define MISC_CTRL_DRAM_TRFC                           8:8
+#define MISC_CTRL_DRAM_TRFC_12CLK                     0
+#define MISC_CTRL_DRAM_TRFC_14CLK                     1
+#define MISC_CTRL_DRAM_TRAS                           7:7
+#define MISC_CTRL_DRAM_TRAS_7CLK                      0
+#define MISC_CTRL_DRAM_TRAS_8CLK                      1
+#define MISC_CTRL_LOCALMEM_RESET                      6:6
+#define MISC_CTRL_LOCALMEM_RESET_RESET                0
+#define MISC_CTRL_LOCALMEM_RESET_NORMAL               1
+#define MISC_CTRL_LOCALMEM_STATE                      5:5
+#define MISC_CTRL_LOCALMEM_STATE_ACTIVE               0
+#define MISC_CTRL_LOCALMEM_STATE_INACTIVE             1
+#define MISC_CTRL_CPU_CAS_LATENCY                     4:4
+#define MISC_CTRL_CPU_CAS_LATENCY_2CLK                0
+#define MISC_CTRL_CPU_CAS_LATENCY_3CLK                1
+#define MISC_CTRL_DLL                                 3:3
+#define MISC_CTRL_DLL_ON                              0
+#define MISC_CTRL_DLL_OFF                             1
+#define MISC_CTRL_DRAM_OUTPUT                         2:2
+#define MISC_CTRL_DRAM_OUTPUT_LOW                     0
+#define MISC_CTRL_DRAM_OUTPUT_HIGH                    1
+#define MISC_CTRL_LOCALMEM_BUS_SIZE                   1:1
+#define MISC_CTRL_LOCALMEM_BUS_SIZE_32                0
+#define MISC_CTRL_LOCALMEM_BUS_SIZE_64                1
+#define MISC_CTRL_EMBEDDED_LOCALMEM                   0:0
+#define MISC_CTRL_EMBEDDED_LOCALMEM_ON                0
+#define MISC_CTRL_EMBEDDED_LOCALMEM_OFF               1
+
+#define GPIO_MUX                                      0x000008
+#define GPIO_MUX_31                                   31:31
+#define GPIO_MUX_31_GPIO                              0
+#define GPIO_MUX_31_I2C                               1
+#define GPIO_MUX_30                                   30:30
+#define GPIO_MUX_30_GPIO                              0
+#define GPIO_MUX_30_I2C                               1
+#define GPIO_MUX_29                                   29:29
+#define GPIO_MUX_29_GPIO                              0
+#define GPIO_MUX_29_SSP1                              1
+#define GPIO_MUX_28                                   28:28
+#define GPIO_MUX_28_GPIO                              0
+#define GPIO_MUX_28_SSP1                              1
+#define GPIO_MUX_27                                   27:27
+#define GPIO_MUX_27_GPIO                              0
+#define GPIO_MUX_27_SSP1                              1
+#define GPIO_MUX_26                                   26:26
+#define GPIO_MUX_26_GPIO                              0
+#define GPIO_MUX_26_SSP1                              1
+#define GPIO_MUX_25                                   25:25
+#define GPIO_MUX_25_GPIO                              0
+#define GPIO_MUX_25_SSP1                              1
+#define GPIO_MUX_24                                   24:24
+#define GPIO_MUX_24_GPIO                              0
+#define GPIO_MUX_24_SSP0                              1
+#define GPIO_MUX_23                                   23:23
+#define GPIO_MUX_23_GPIO                              0
+#define GPIO_MUX_23_SSP0                              1
+#define GPIO_MUX_22                                   22:22
+#define GPIO_MUX_22_GPIO                              0
+#define GPIO_MUX_22_SSP0                              1
+#define GPIO_MUX_21                                   21:21
+#define GPIO_MUX_21_GPIO                              0
+#define GPIO_MUX_21_SSP0                              1
+#define GPIO_MUX_20                                   20:20
+#define GPIO_MUX_20_GPIO                              0
+#define GPIO_MUX_20_SSP0                              1
+#define GPIO_MUX_19                                   19:19
+#define GPIO_MUX_19_GPIO                              0
+#define GPIO_MUX_19_PWM                               1
+#define GPIO_MUX_18                                   18:18
+#define GPIO_MUX_18_GPIO                              0
+#define GPIO_MUX_18_PWM                               1
+#define GPIO_MUX_17                                   17:17
+#define GPIO_MUX_17_GPIO                              0
+#define GPIO_MUX_17_PWM                               1
+#define GPIO_MUX_16                                   16:16
+#define GPIO_MUX_16_GPIO_ZVPORT                       0
+#define GPIO_MUX_16_TEST_DATA                         1
+#define GPIO_MUX_15                                   15:15
+#define GPIO_MUX_15_GPIO_ZVPORT                       0
+#define GPIO_MUX_15_TEST_DATA                         1
+#define GPIO_MUX_14                                   14:14
+#define GPIO_MUX_14_GPIO_ZVPORT                       0
+#define GPIO_MUX_14_TEST_DATA                         1
+#define GPIO_MUX_13                                   13:13
+#define GPIO_MUX_13_GPIO_ZVPORT                       0
+#define GPIO_MUX_13_TEST_DATA                         1
+#define GPIO_MUX_12                                   12:12
+#define GPIO_MUX_12_GPIO_ZVPORT                       0
+#define GPIO_MUX_12_TEST_DATA                         1
+#define GPIO_MUX_11                                   11:11
+#define GPIO_MUX_11_GPIO_ZVPORT                       0
+#define GPIO_MUX_11_TEST_DATA                         1
+#define GPIO_MUX_10                                   10:10
+#define GPIO_MUX_10_GPIO_ZVPORT                       0
+#define GPIO_MUX_10_TEST_DATA                         1
+#define GPIO_MUX_9                                    9:9
+#define GPIO_MUX_9_GPIO_ZVPORT                        0
+#define GPIO_MUX_9_TEST_DATA                          1
+#define GPIO_MUX_8                                    8:8
+#define GPIO_MUX_8_GPIO_ZVPORT                        0
+#define GPIO_MUX_8_TEST_DATA                          1
+#define GPIO_MUX_7                                    7:7
+#define GPIO_MUX_7_GPIO_ZVPORT                        0
+#define GPIO_MUX_7_TEST_DATA                          1
+#define GPIO_MUX_6                                    6:6
+#define GPIO_MUX_6_GPIO_ZVPORT                        0
+#define GPIO_MUX_6_TEST_DATA                          1
+#define GPIO_MUX_5                                    5:5
+#define GPIO_MUX_5_GPIO_ZVPORT                        0
+#define GPIO_MUX_5_TEST_DATA                          1
+#define GPIO_MUX_4                                    4:4
+#define GPIO_MUX_4_GPIO_ZVPORT                        0
+#define GPIO_MUX_4_TEST_DATA                          1
+#define GPIO_MUX_3                                    3:3
+#define GPIO_MUX_3_GPIO_ZVPORT                        0
+#define GPIO_MUX_3_TEST_DATA                          1
+#define GPIO_MUX_2                                    2:2
+#define GPIO_MUX_2_GPIO_ZVPORT                        0
+#define GPIO_MUX_2_TEST_DATA                          1
+#define GPIO_MUX_1                                    1:1
+#define GPIO_MUX_1_GPIO_ZVPORT                        0
+#define GPIO_MUX_1_TEST_DATA                          1
+#define GPIO_MUX_0                                    0:0
+#define GPIO_MUX_0_GPIO_ZVPORT                        0
+#define GPIO_MUX_0_TEST_DATA                          1
+
+#define LOCALMEM_ARBITRATION                          0x00000C
+#define LOCALMEM_ARBITRATION_ROTATE                   28:28
+#define LOCALMEM_ARBITRATION_ROTATE_OFF               0
+#define LOCALMEM_ARBITRATION_ROTATE_ON                1
+#define LOCALMEM_ARBITRATION_VGA                      26:24
+#define LOCALMEM_ARBITRATION_VGA_OFF                  0
+#define LOCALMEM_ARBITRATION_VGA_PRIORITY_1           1
+#define LOCALMEM_ARBITRATION_VGA_PRIORITY_2           2
+#define LOCALMEM_ARBITRATION_VGA_PRIORITY_3           3
+#define LOCALMEM_ARBITRATION_VGA_PRIORITY_4           4
+#define LOCALMEM_ARBITRATION_VGA_PRIORITY_5           5
+#define LOCALMEM_ARBITRATION_VGA_PRIORITY_6           6
+#define LOCALMEM_ARBITRATION_VGA_PRIORITY_7           7
+#define LOCALMEM_ARBITRATION_DMA                      22:20
+#define LOCALMEM_ARBITRATION_DMA_OFF                  0
+#define LOCALMEM_ARBITRATION_DMA_PRIORITY_1           1
+#define LOCALMEM_ARBITRATION_DMA_PRIORITY_2           2
+#define LOCALMEM_ARBITRATION_DMA_PRIORITY_3           3
+#define LOCALMEM_ARBITRATION_DMA_PRIORITY_4           4
+#define LOCALMEM_ARBITRATION_DMA_PRIORITY_5           5
+#define LOCALMEM_ARBITRATION_DMA_PRIORITY_6           6
+#define LOCALMEM_ARBITRATION_DMA_PRIORITY_7           7
+#define LOCALMEM_ARBITRATION_ZVPORT1                  18:16
+#define LOCALMEM_ARBITRATION_ZVPORT1_OFF              0
+#define LOCALMEM_ARBITRATION_ZVPORT1_PRIORITY_1       1
+#define LOCALMEM_ARBITRATION_ZVPORT1_PRIORITY_2       2
+#define LOCALMEM_ARBITRATION_ZVPORT1_PRIORITY_3       3
+#define LOCALMEM_ARBITRATION_ZVPORT1_PRIORITY_4       4
+#define LOCALMEM_ARBITRATION_ZVPORT1_PRIORITY_5       5
+#define LOCALMEM_ARBITRATION_ZVPORT1_PRIORITY_6       6
+#define LOCALMEM_ARBITRATION_ZVPORT1_PRIORITY_7       7
+#define LOCALMEM_ARBITRATION_ZVPORT0                  14:12
+#define LOCALMEM_ARBITRATION_ZVPORT0_OFF              0
+#define LOCALMEM_ARBITRATION_ZVPORT0_PRIORITY_1       1
+#define LOCALMEM_ARBITRATION_ZVPORT0_PRIORITY_2       2
+#define LOCALMEM_ARBITRATION_ZVPORT0_PRIORITY_3       3
+#define LOCALMEM_ARBITRATION_ZVPORT0_PRIORITY_4       4
+#define LOCALMEM_ARBITRATION_ZVPORT0_PRIORITY_5       5
+#define LOCALMEM_ARBITRATION_ZVPORT0_PRIORITY_6       6
+#define LOCALMEM_ARBITRATION_ZVPORT0_PRIORITY_7       7
+#define LOCALMEM_ARBITRATION_VIDEO                    10:8
+#define LOCALMEM_ARBITRATION_VIDEO_OFF                0
+#define LOCALMEM_ARBITRATION_VIDEO_PRIORITY_1         1
+#define LOCALMEM_ARBITRATION_VIDEO_PRIORITY_2         2
+#define LOCALMEM_ARBITRATION_VIDEO_PRIORITY_3         3
+#define LOCALMEM_ARBITRATION_VIDEO_PRIORITY_4         4
+#define LOCALMEM_ARBITRATION_VIDEO_PRIORITY_5         5
+#define LOCALMEM_ARBITRATION_VIDEO_PRIORITY_6         6
+#define LOCALMEM_ARBITRATION_VIDEO_PRIORITY_7         7
+#define LOCALMEM_ARBITRATION_PANEL                    6:4
+#define LOCALMEM_ARBITRATION_PANEL_OFF                0
+#define LOCALMEM_ARBITRATION_PANEL_PRIORITY_1         1
+#define LOCALMEM_ARBITRATION_PANEL_PRIORITY_2         2
+#define LOCALMEM_ARBITRATION_PANEL_PRIORITY_3         3
+#define LOCALMEM_ARBITRATION_PANEL_PRIORITY_4         4
+#define LOCALMEM_ARBITRATION_PANEL_PRIORITY_5         5
+#define LOCALMEM_ARBITRATION_PANEL_PRIORITY_6         6
+#define LOCALMEM_ARBITRATION_PANEL_PRIORITY_7         7
+#define LOCALMEM_ARBITRATION_CRT                      2:0
+#define LOCALMEM_ARBITRATION_CRT_OFF                  0
+#define LOCALMEM_ARBITRATION_CRT_PRIORITY_1           1
+#define LOCALMEM_ARBITRATION_CRT_PRIORITY_2           2
+#define LOCALMEM_ARBITRATION_CRT_PRIORITY_3           3
+#define LOCALMEM_ARBITRATION_CRT_PRIORITY_4           4
+#define LOCALMEM_ARBITRATION_CRT_PRIORITY_5           5
+#define LOCALMEM_ARBITRATION_CRT_PRIORITY_6           6
+#define LOCALMEM_ARBITRATION_CRT_PRIORITY_7           7
+
+#define PCIMEM_ARBITRATION                            0x000010
+#define PCIMEM_ARBITRATION_ROTATE                     28:28
+#define PCIMEM_ARBITRATION_ROTATE_OFF                 0
+#define PCIMEM_ARBITRATION_ROTATE_ON                  1
+#define PCIMEM_ARBITRATION_VGA                        26:24
+#define PCIMEM_ARBITRATION_VGA_OFF                    0
+#define PCIMEM_ARBITRATION_VGA_PRIORITY_1             1
+#define PCIMEM_ARBITRATION_VGA_PRIORITY_2             2
+#define PCIMEM_ARBITRATION_VGA_PRIORITY_3             3
+#define PCIMEM_ARBITRATION_VGA_PRIORITY_4             4
+#define PCIMEM_ARBITRATION_VGA_PRIORITY_5             5
+#define PCIMEM_ARBITRATION_VGA_PRIORITY_6             6
+#define PCIMEM_ARBITRATION_VGA_PRIORITY_7             7
+#define PCIMEM_ARBITRATION_DMA                        22:20
+#define PCIMEM_ARBITRATION_DMA_OFF                    0
+#define PCIMEM_ARBITRATION_DMA_PRIORITY_1             1
+#define PCIMEM_ARBITRATION_DMA_PRIORITY_2             2
+#define PCIMEM_ARBITRATION_DMA_PRIORITY_3             3
+#define PCIMEM_ARBITRATION_DMA_PRIORITY_4             4
+#define PCIMEM_ARBITRATION_DMA_PRIORITY_5             5
+#define PCIMEM_ARBITRATION_DMA_PRIORITY_6             6
+#define PCIMEM_ARBITRATION_DMA_PRIORITY_7             7
+#define PCIMEM_ARBITRATION_ZVPORT1                    18:16
+#define PCIMEM_ARBITRATION_ZVPORT1_OFF                0
+#define PCIMEM_ARBITRATION_ZVPORT1_PRIORITY_1         1
+#define PCIMEM_ARBITRATION_ZVPORT1_PRIORITY_2         2
+#define PCIMEM_ARBITRATION_ZVPORT1_PRIORITY_3         3
+#define PCIMEM_ARBITRATION_ZVPORT1_PRIORITY_4         4
+#define PCIMEM_ARBITRATION_ZVPORT1_PRIORITY_5         5
+#define PCIMEM_ARBITRATION_ZVPORT1_PRIORITY_6         6
+#define PCIMEM_ARBITRATION_ZVPORT1_PRIORITY_7         7
+#define PCIMEM_ARBITRATION_ZVPORT0                    14:12
+#define PCIMEM_ARBITRATION_ZVPORT0_OFF                0
+#define PCIMEM_ARBITRATION_ZVPORT0_PRIORITY_1         1
+#define PCIMEM_ARBITRATION_ZVPORT0_PRIORITY_2         2
+#define PCIMEM_ARBITRATION_ZVPORT0_PRIORITY_3         3
+#define PCIMEM_ARBITRATION_ZVPORT0_PRIORITY_4         4
+#define PCIMEM_ARBITRATION_ZVPORT0_PRIORITY_5         5
+#define PCIMEM_ARBITRATION_ZVPORT0_PRIORITY_6         6
+#define PCIMEM_ARBITRATION_ZVPORT0_PRIORITY_7         7
+#define PCIMEM_ARBITRATION_VIDEO                      10:8
+#define PCIMEM_ARBITRATION_VIDEO_OFF                  0
+#define PCIMEM_ARBITRATION_VIDEO_PRIORITY_1           1
+#define PCIMEM_ARBITRATION_VIDEO_PRIORITY_2           2
+#define PCIMEM_ARBITRATION_VIDEO_PRIORITY_3           3
+#define PCIMEM_ARBITRATION_VIDEO_PRIORITY_4           4
+#define PCIMEM_ARBITRATION_VIDEO_PRIORITY_5           5
+#define PCIMEM_ARBITRATION_VIDEO_PRIORITY_6           6
+#define PCIMEM_ARBITRATION_VIDEO_PRIORITY_7           7
+#define PCIMEM_ARBITRATION_PANEL                      6:4
+#define PCIMEM_ARBITRATION_PANEL_OFF                  0
+#define PCIMEM_ARBITRATION_PANEL_PRIORITY_1           1
+#define PCIMEM_ARBITRATION_PANEL_PRIORITY_2           2
+#define PCIMEM_ARBITRATION_PANEL_PRIORITY_3           3
+#define PCIMEM_ARBITRATION_PANEL_PRIORITY_4           4
+#define PCIMEM_ARBITRATION_PANEL_PRIORITY_5           5
+#define PCIMEM_ARBITRATION_PANEL_PRIORITY_6           6
+#define PCIMEM_ARBITRATION_PANEL_PRIORITY_7           7
+#define PCIMEM_ARBITRATION_CRT                        2:0
+#define PCIMEM_ARBITRATION_CRT_OFF                    0
+#define PCIMEM_ARBITRATION_CRT_PRIORITY_1             1
+#define PCIMEM_ARBITRATION_CRT_PRIORITY_2             2
+#define PCIMEM_ARBITRATION_CRT_PRIORITY_3             3
+#define PCIMEM_ARBITRATION_CRT_PRIORITY_4             4
+#define PCIMEM_ARBITRATION_CRT_PRIORITY_5             5
+#define PCIMEM_ARBITRATION_CRT_PRIORITY_6             6
+#define PCIMEM_ARBITRATION_CRT_PRIORITY_7             7
+
+#define RAW_INT                                       0x000020
+#define RAW_INT_ZVPORT1_VSYNC                         4:4
+#define RAW_INT_ZVPORT1_VSYNC_INACTIVE                0
+#define RAW_INT_ZVPORT1_VSYNC_ACTIVE                  1
+#define RAW_INT_ZVPORT1_VSYNC_CLEAR                   1
+#define RAW_INT_ZVPORT0_VSYNC                         3:3
+#define RAW_INT_ZVPORT0_VSYNC_INACTIVE                0
+#define RAW_INT_ZVPORT0_VSYNC_ACTIVE                  1
+#define RAW_INT_ZVPORT0_VSYNC_CLEAR                   1
+#define RAW_INT_CRT_VSYNC                             2:2
+#define RAW_INT_CRT_VSYNC_INACTIVE                    0
+#define RAW_INT_CRT_VSYNC_ACTIVE                      1
+#define RAW_INT_CRT_VSYNC_CLEAR                       1
+#define RAW_INT_PANEL_VSYNC                           1:1
+#define RAW_INT_PANEL_VSYNC_INACTIVE                  0
+#define RAW_INT_PANEL_VSYNC_ACTIVE                    1
+#define RAW_INT_PANEL_VSYNC_CLEAR                     1
+#define RAW_INT_VGA_VSYNC                             0:0
+#define RAW_INT_VGA_VSYNC_INACTIVE                    0
+#define RAW_INT_VGA_VSYNC_ACTIVE                      1
+#define RAW_INT_VGA_VSYNC_CLEAR                       1
+
+#define INT_STATUS                                    0x000024
+#define INT_STATUS_GPIO31                             31:31
+#define INT_STATUS_GPIO31_INACTIVE                    0
+#define INT_STATUS_GPIO31_ACTIVE                      1
+#define INT_STATUS_GPIO30                             30:30
+#define INT_STATUS_GPIO30_INACTIVE                    0
+#define INT_STATUS_GPIO30_ACTIVE                      1
+#define INT_STATUS_GPIO29                             29:29
+#define INT_STATUS_GPIO29_INACTIVE                    0
+#define INT_STATUS_GPIO29_ACTIVE                      1
+#define INT_STATUS_GPIO28                             28:28
+#define INT_STATUS_GPIO28_INACTIVE                    0
+#define INT_STATUS_GPIO28_ACTIVE                      1
+#define INT_STATUS_GPIO27                             27:27
+#define INT_STATUS_GPIO27_INACTIVE                    0
+#define INT_STATUS_GPIO27_ACTIVE                      1
+#define INT_STATUS_GPIO26                             26:26
+#define INT_STATUS_GPIO26_INACTIVE                    0
+#define INT_STATUS_GPIO26_ACTIVE                      1
+#define INT_STATUS_GPIO25                             25:25
+#define INT_STATUS_GPIO25_INACTIVE                    0
+#define INT_STATUS_GPIO25_ACTIVE                      1
+#define INT_STATUS_I2C                                12:12
+#define INT_STATUS_I2C_INACTIVE                       0
+#define INT_STATUS_I2C_ACTIVE                         1
+#define INT_STATUS_PWM                                11:11
+#define INT_STATUS_PWM_INACTIVE                       0
+#define INT_STATUS_PWM_ACTIVE                         1
+#define INT_STATUS_DMA1                               10:10
+#define INT_STATUS_DMA1_INACTIVE                      0
+#define INT_STATUS_DMA1_ACTIVE                        1
+#define INT_STATUS_DMA0                               9:9
+#define INT_STATUS_DMA0_INACTIVE                      0
+#define INT_STATUS_DMA0_ACTIVE                        1
+#define INT_STATUS_PCI                                8:8
+#define INT_STATUS_PCI_INACTIVE                       0
+#define INT_STATUS_PCI_ACTIVE                         1
+#define INT_STATUS_SSP1                               7:7
+#define INT_STATUS_SSP1_INACTIVE                      0
+#define INT_STATUS_SSP1_ACTIVE                        1
+#define INT_STATUS_SSP0                               6:6
+#define INT_STATUS_SSP0_INACTIVE                      0
+#define INT_STATUS_SSP0_ACTIVE                        1
+#define INT_STATUS_DE                                 5:5
+#define INT_STATUS_DE_INACTIVE                        0
+#define INT_STATUS_DE_ACTIVE                          1
+#define INT_STATUS_ZVPORT1_VSYNC                      4:4
+#define INT_STATUS_ZVPORT1_VSYNC_INACTIVE             0
+#define INT_STATUS_ZVPORT1_VSYNC_ACTIVE               1
+#define INT_STATUS_ZVPORT0_VSYNC                      3:3
+#define INT_STATUS_ZVPORT0_VSYNC_INACTIVE             0
+#define INT_STATUS_ZVPORT0_VSYNC_ACTIVE               1
+#define INT_STATUS_CRT_VSYNC                          2:2
+#define INT_STATUS_CRT_VSYNC_INACTIVE                 0
+#define INT_STATUS_CRT_VSYNC_ACTIVE                   1
+#define INT_STATUS_PANEL_VSYNC                        1:1
+#define INT_STATUS_PANEL_VSYNC_INACTIVE               0
+#define INT_STATUS_PANEL_VSYNC_ACTIVE                 1
+#define INT_STATUS_VGA_VSYNC                          0:0
+#define INT_STATUS_VGA_VSYNC_INACTIVE                 0
+#define INT_STATUS_VGA_VSYNC_ACTIVE                   1
+
+#define INT_MASK                                      0x000028
+#define INT_MASK_GPIO31                               31:31
+#define INT_MASK_GPIO31_DISABLE                       0
+#define INT_MASK_GPIO31_ENABLE                        1
+#define INT_MASK_GPIO30                               30:30
+#define INT_MASK_GPIO30_DISABLE                       0
+#define INT_MASK_GPIO30_ENABLE                        1
+#define INT_MASK_GPIO29                               29:29
+#define INT_MASK_GPIO29_DISABLE                       0
+#define INT_MASK_GPIO29_ENABLE                        1
+#define INT_MASK_GPIO28                               28:28
+#define INT_MASK_GPIO28_DISABLE                       0
+#define INT_MASK_GPIO28_ENABLE                        1
+#define INT_MASK_GPIO27                               27:27
+#define INT_MASK_GPIO27_DISABLE                       0
+#define INT_MASK_GPIO27_ENABLE                        1
+#define INT_MASK_GPIO26                               26:26
+#define INT_MASK_GPIO26_DISABLE                       0
+#define INT_MASK_GPIO26_ENABLE                        1
+#define INT_MASK_GPIO25                               25:25
+#define INT_MASK_GPIO25_DISABLE                       0
+#define INT_MASK_GPIO25_ENABLE                        1
+#define INT_MASK_I2C                                  12:12
+#define INT_MASK_I2C_DISABLE                          0
+#define INT_MASK_I2C_ENABLE                           1
+#define INT_MASK_PWM                                  11:11
+#define INT_MASK_PWM_DISABLE                          0
+#define INT_MASK_PWM_ENABLE                           1
+#define INT_MASK_DMA1                                 10:10
+#define INT_MASK_DMA1_DISABLE                         0
+#define INT_MASK_DMA1_ENABLE                          1
+#define INT_MASK_DMA                                  9:9
+#define INT_MASK_DMA_DISABLE                          0
+#define INT_MASK_DMA_ENABLE                           1
+#define INT_MASK_PCI                                  8:8
+#define INT_MASK_PCI_DISABLE                          0
+#define INT_MASK_PCI_ENABLE                           1
+#define INT_MASK_SSP1                                 7:7
+#define INT_MASK_SSP1_DISABLE                         0
+#define INT_MASK_SSP1_ENABLE                          1
+#define INT_MASK_SSP0                                 6:6
+#define INT_MASK_SSP0_DISABLE                         0
+#define INT_MASK_SSP0_ENABLE                          1
+#define INT_MASK_DE                                   5:5
+#define INT_MASK_DE_DISABLE                           0
+#define INT_MASK_DE_ENABLE                            1
+#define INT_MASK_ZVPORT1_VSYNC                        4:4
+#define INT_MASK_ZVPORT1_VSYNC_DISABLE                0
+#define INT_MASK_ZVPORT1_VSYNC_ENABLE                 1
+#define INT_MASK_ZVPORT0_VSYNC                        3:3
+#define INT_MASK_ZVPORT0_VSYNC_DISABLE                0
+#define INT_MASK_ZVPORT0_VSYNC_ENABLE                 1
+#define INT_MASK_CRT_VSYNC                            2:2
+#define INT_MASK_CRT_VSYNC_DISABLE                    0
+#define INT_MASK_CRT_VSYNC_ENABLE                     1
+#define INT_MASK_PANEL_VSYNC                          1:1
+#define INT_MASK_PANEL_VSYNC_DISABLE                  0
+#define INT_MASK_PANEL_VSYNC_ENABLE                   1
+#define INT_MASK_VGA_VSYNC                            0:0
+#define INT_MASK_VGA_VSYNC_DISABLE                    0
+#define INT_MASK_VGA_VSYNC_ENABLE                     1
+
+#define CURRENT_GATE                                  0x000040
+#define CURRENT_GATE_MCLK                             15:14
+#ifdef VALIDATION_CHIP
+    #define CURRENT_GATE_MCLK_112MHZ                      0
+    #define CURRENT_GATE_MCLK_84MHZ                       1
+    #define CURRENT_GATE_MCLK_56MHZ                       2
+    #define CURRENT_GATE_MCLK_42MHZ                       3
+#else
+    #define CURRENT_GATE_MCLK_DIV_3                       0
+    #define CURRENT_GATE_MCLK_DIV_4                       1
+    #define CURRENT_GATE_MCLK_DIV_6                       2
+    #define CURRENT_GATE_MCLK_DIV_8                       3
+#endif
+#define CURRENT_GATE_M2XCLK                           13:12
+#ifdef VALIDATION_CHIP
+    #define CURRENT_GATE_M2XCLK_336MHZ                    0
+    #define CURRENT_GATE_M2XCLK_168MHZ                    1
+    #define CURRENT_GATE_M2XCLK_112MHZ                    2
+    #define CURRENT_GATE_M2XCLK_84MHZ                     3
+#else
+    #define CURRENT_GATE_M2XCLK_DIV_1                     0
+    #define CURRENT_GATE_M2XCLK_DIV_2                     1
+    #define CURRENT_GATE_M2XCLK_DIV_3                     2
+    #define CURRENT_GATE_M2XCLK_DIV_4                     3
+#endif
+#define CURRENT_GATE_VGA                              10:10
+#define CURRENT_GATE_VGA_OFF                          0
+#define CURRENT_GATE_VGA_ON                           1
+#define CURRENT_GATE_PWM                              9:9
+#define CURRENT_GATE_PWM_OFF                          0
+#define CURRENT_GATE_PWM_ON                           1
+#define CURRENT_GATE_I2C                              8:8
+#define CURRENT_GATE_I2C_OFF                          0
+#define CURRENT_GATE_I2C_ON                           1
+#define CURRENT_GATE_SSP                              7:7
+#define CURRENT_GATE_SSP_OFF                          0
+#define CURRENT_GATE_SSP_ON                           1
+#define CURRENT_GATE_GPIO                             6:6
+#define CURRENT_GATE_GPIO_OFF                         0
+#define CURRENT_GATE_GPIO_ON                          1
+#define CURRENT_GATE_ZVPORT                           5:5
+#define CURRENT_GATE_ZVPORT_OFF                       0
+#define CURRENT_GATE_ZVPORT_ON                        1
+#define CURRENT_GATE_CSC                              4:4
+#define CURRENT_GATE_CSC_OFF                          0
+#define CURRENT_GATE_CSC_ON                           1
+#define CURRENT_GATE_DE                               3:3
+#define CURRENT_GATE_DE_OFF                           0
+#define CURRENT_GATE_DE_ON                            1
+#define CURRENT_GATE_DISPLAY                          2:2
+#define CURRENT_GATE_DISPLAY_OFF                      0
+#define CURRENT_GATE_DISPLAY_ON                       1
+#define CURRENT_GATE_LOCALMEM                         1:1
+#define CURRENT_GATE_LOCALMEM_OFF                     0
+#define CURRENT_GATE_LOCALMEM_ON                      1
+#define CURRENT_GATE_DMA                              0:0
+#define CURRENT_GATE_DMA_OFF                          0
+#define CURRENT_GATE_DMA_ON                           1
+
+#define MODE0_GATE                                    0x000044
+#define MODE0_GATE_MCLK                               15:14
+#define MODE0_GATE_MCLK_112MHZ                        0
+#define MODE0_GATE_MCLK_84MHZ                         1
+#define MODE0_GATE_MCLK_56MHZ                         2
+#define MODE0_GATE_MCLK_42MHZ                         3
+#define MODE0_GATE_M2XCLK                             13:12
+#define MODE0_GATE_M2XCLK_336MHZ                      0
+#define MODE0_GATE_M2XCLK_168MHZ                      1
+#define MODE0_GATE_M2XCLK_112MHZ                      2
+#define MODE0_GATE_M2XCLK_84MHZ                       3
+#define MODE0_GATE_VGA                                10:10
+#define MODE0_GATE_VGA_OFF                            0
+#define MODE0_GATE_VGA_ON                             1
+#define MODE0_GATE_PWM                                9:9
+#define MODE0_GATE_PWM_OFF                            0
+#define MODE0_GATE_PWM_ON                             1
+#define MODE0_GATE_I2C                                8:8
+#define MODE0_GATE_I2C_OFF                            0
+#define MODE0_GATE_I2C_ON                             1
+#define MODE0_GATE_SSP                                7:7
+#define MODE0_GATE_SSP_OFF                            0
+#define MODE0_GATE_SSP_ON                             1
+#define MODE0_GATE_GPIO                               6:6
+#define MODE0_GATE_GPIO_OFF                           0
+#define MODE0_GATE_GPIO_ON                            1
+#define MODE0_GATE_ZVPORT                             5:5
+#define MODE0_GATE_ZVPORT_OFF                         0
+#define MODE0_GATE_ZVPORT_ON                          1
+#define MODE0_GATE_CSC                                4:4
+#define MODE0_GATE_CSC_OFF                            0
+#define MODE0_GATE_CSC_ON                             1
+#define MODE0_GATE_DE                                 3:3
+#define MODE0_GATE_DE_OFF                             0
+#define MODE0_GATE_DE_ON                              1
+#define MODE0_GATE_DISPLAY                            2:2
+#define MODE0_GATE_DISPLAY_OFF                        0
+#define MODE0_GATE_DISPLAY_ON                         1
+#define MODE0_GATE_LOCALMEM                           1:1
+#define MODE0_GATE_LOCALMEM_OFF                       0
+#define MODE0_GATE_LOCALMEM_ON                        1
+#define MODE0_GATE_DMA                                0:0
+#define MODE0_GATE_DMA_OFF                            0
+#define MODE0_GATE_DMA_ON                             1
+
+#define MODE1_GATE                                    0x000048
+#define MODE1_GATE_MCLK                               15:14
+#define MODE1_GATE_MCLK_112MHZ                        0
+#define MODE1_GATE_MCLK_84MHZ                         1
+#define MODE1_GATE_MCLK_56MHZ                         2
+#define MODE1_GATE_MCLK_42MHZ                         3
+#define MODE1_GATE_M2XCLK                             13:12
+#define MODE1_GATE_M2XCLK_336MHZ                      0
+#define MODE1_GATE_M2XCLK_168MHZ                      1
+#define MODE1_GATE_M2XCLK_112MHZ                      2
+#define MODE1_GATE_M2XCLK_84MHZ                       3
+#define MODE1_GATE_VGA                                10:10
+#define MODE1_GATE_VGA_OFF                            0
+#define MODE1_GATE_VGA_ON                             1
+#define MODE1_GATE_PWM                                9:9
+#define MODE1_GATE_PWM_OFF                            0
+#define MODE1_GATE_PWM_ON                             1
+#define MODE1_GATE_I2C                                8:8
+#define MODE1_GATE_I2C_OFF                            0
+#define MODE1_GATE_I2C_ON                             1
+#define MODE1_GATE_SSP                                7:7
+#define MODE1_GATE_SSP_OFF                            0
+#define MODE1_GATE_SSP_ON                             1
+#define MODE1_GATE_GPIO                               6:6
+#define MODE1_GATE_GPIO_OFF                           0
+#define MODE1_GATE_GPIO_ON                            1
+#define MODE1_GATE_ZVPORT                             5:5
+#define MODE1_GATE_ZVPORT_OFF                         0
+#define MODE1_GATE_ZVPORT_ON                          1
+#define MODE1_GATE_CSC                                4:4
+#define MODE1_GATE_CSC_OFF                            0
+#define MODE1_GATE_CSC_ON                             1
+#define MODE1_GATE_DE                                 3:3
+#define MODE1_GATE_DE_OFF                             0
+#define MODE1_GATE_DE_ON                              1
+#define MODE1_GATE_DISPLAY                            2:2
+#define MODE1_GATE_DISPLAY_OFF                        0
+#define MODE1_GATE_DISPLAY_ON                         1
+#define MODE1_GATE_LOCALMEM                           1:1
+#define MODE1_GATE_LOCALMEM_OFF                       0
+#define MODE1_GATE_LOCALMEM_ON                        1
+#define MODE1_GATE_DMA                                0:0
+#define MODE1_GATE_DMA_OFF                            0
+#define MODE1_GATE_DMA_ON                             1
+
+#define POWER_MODE_CTRL                               0x00004C
+#ifdef VALIDATION_CHIP
+    #define POWER_MODE_CTRL_336CLK                    4:4
+    #define POWER_MODE_CTRL_336CLK_OFF                0
+    #define POWER_MODE_CTRL_336CLK_ON                 1
+#endif
+#define POWER_MODE_CTRL_OSC_INPUT                     3:3
+#define POWER_MODE_CTRL_OSC_INPUT_OFF                 0
+#define POWER_MODE_CTRL_OSC_INPUT_ON                  1
+#define POWER_MODE_CTRL_ACPI                          2:2
+#define POWER_MODE_CTRL_ACPI_OFF                      0
+#define POWER_MODE_CTRL_ACPI_ON                       1
+#define POWER_MODE_CTRL_MODE                          1:0
+#define POWER_MODE_CTRL_MODE_MODE0                    0
+#define POWER_MODE_CTRL_MODE_MODE1                    1
+#define POWER_MODE_CTRL_MODE_SLEEP                    2
+
+#define PCI_MASTER_BASE                               0x000050
+#define PCI_MASTER_BASE_ADDRESS                       7:0
+
+#define DEVICE_ID                                     0x000054
+#define DEVICE_ID_DEVICE_ID                           31:16
+#define DEVICE_ID_REVISION_ID                         7:0
+
+#define PLL_CLK_COUNT                                 0x000058
+#define PLL_CLK_COUNT_COUNTER                         15:0
+
+#define PANEL_PLL_CTRL                                0x00005C
+#define PANEL_PLL_CTRL_BYPASS                         18:18
+#define PANEL_PLL_CTRL_BYPASS_OFF                     0
+#define PANEL_PLL_CTRL_BYPASS_ON                      1
+#define PANEL_PLL_CTRL_POWER                          17:17
+#define PANEL_PLL_CTRL_POWER_OFF                      0
+#define PANEL_PLL_CTRL_POWER_ON                       1
+#define PANEL_PLL_CTRL_INPUT                          16:16
+#define PANEL_PLL_CTRL_INPUT_OSC                      0
+#define PANEL_PLL_CTRL_INPUT_TESTCLK                  1
+#ifdef VALIDATION_CHIP
+    #define PANEL_PLL_CTRL_OD                         15:14
+#else
+    #define PANEL_PLL_CTRL_POD                        15:14
+    #define PANEL_PLL_CTRL_OD                         13:12
+#endif
+#define PANEL_PLL_CTRL_N                              11:8
+#define PANEL_PLL_CTRL_M                              7:0
+
+#define CRT_PLL_CTRL                                  0x000060
+#define CRT_PLL_CTRL_BYPASS                           18:18
+#define CRT_PLL_CTRL_BYPASS_OFF                       0
+#define CRT_PLL_CTRL_BYPASS_ON                        1
+#define CRT_PLL_CTRL_POWER                            17:17
+#define CRT_PLL_CTRL_POWER_OFF                        0
+#define CRT_PLL_CTRL_POWER_ON                         1
+#define CRT_PLL_CTRL_INPUT                            16:16
+#define CRT_PLL_CTRL_INPUT_OSC                        0
+#define CRT_PLL_CTRL_INPUT_TESTCLK                    1
+#ifdef VALIDATION_CHIP
+    #define CRT_PLL_CTRL_OD                           15:14
+#else
+    #define CRT_PLL_CTRL_POD                          15:14
+    #define CRT_PLL_CTRL_OD                           13:12
+#endif
+#define CRT_PLL_CTRL_N                                11:8
+#define CRT_PLL_CTRL_M                                7:0
+
+#define VGA_PLL0_CTRL                                 0x000064
+#define VGA_PLL0_CTRL_BYPASS                          18:18
+#define VGA_PLL0_CTRL_BYPASS_OFF                      0
+#define VGA_PLL0_CTRL_BYPASS_ON                       1
+#define VGA_PLL0_CTRL_POWER                           17:17
+#define VGA_PLL0_CTRL_POWER_OFF                       0
+#define VGA_PLL0_CTRL_POWER_ON                        1
+#define VGA_PLL0_CTRL_INPUT                           16:16
+#define VGA_PLL0_CTRL_INPUT_OSC                       0
+#define VGA_PLL0_CTRL_INPUT_TESTCLK                   1
+#ifdef VALIDATION_CHIP
+    #define VGA_PLL0_CTRL_OD                          15:14
+#else
+    #define VGA_PLL0_CTRL_POD                         15:14
+    #define VGA_PLL0_CTRL_OD                          13:12
+#endif
+#define VGA_PLL0_CTRL_N                               11:8
+#define VGA_PLL0_CTRL_M                               7:0
+
+#define VGA_PLL1_CTRL                                 0x000068
+#define VGA_PLL1_CTRL_BYPASS                          18:18
+#define VGA_PLL1_CTRL_BYPASS_OFF                      0
+#define VGA_PLL1_CTRL_BYPASS_ON                       1
+#define VGA_PLL1_CTRL_POWER                           17:17
+#define VGA_PLL1_CTRL_POWER_OFF                       0
+#define VGA_PLL1_CTRL_POWER_ON                        1
+#define VGA_PLL1_CTRL_INPUT                           16:16
+#define VGA_PLL1_CTRL_INPUT_OSC                       0
+#define VGA_PLL1_CTRL_INPUT_TESTCLK                   1
+#ifdef VALIDATION_CHIP
+    #define VGA_PLL1_CTRL_OD                          15:14
+#else
+    #define VGA_PLL1_CTRL_POD                         15:14
+    #define VGA_PLL1_CTRL_OD                          13:12
+#endif
+#define VGA_PLL1_CTRL_N                               11:8
+#define VGA_PLL1_CTRL_M                               7:0
+
+#define SCRATCH_DATA                                  0x00006c
+
+#ifndef VALIDATION_CHIP
+
+#define MXCLK_PLL_CTRL                                0x000070
+#define MXCLK_PLL_CTRL_BYPASS                         18:18
+#define MXCLK_PLL_CTRL_BYPASS_OFF                     0
+#define MXCLK_PLL_CTRL_BYPASS_ON                      1
+#define MXCLK_PLL_CTRL_POWER                          17:17
+#define MXCLK_PLL_CTRL_POWER_OFF                      0
+#define MXCLK_PLL_CTRL_POWER_ON                       1
+#define MXCLK_PLL_CTRL_INPUT                          16:16
+#define MXCLK_PLL_CTRL_INPUT_OSC                      0
+#define MXCLK_PLL_CTRL_INPUT_TESTCLK                  1
+#define MXCLK_PLL_CTRL_POD                            15:14
+#define MXCLK_PLL_CTRL_OD                             13:12
+#define MXCLK_PLL_CTRL_N                              11:8
+#define MXCLK_PLL_CTRL_M                              7:0
+
+#define VGA_CONFIGURATION                             0x000088
+#define VGA_CONFIGURATION_USER_DEFINE                 5:4
+#define VGA_CONFIGURATION_PLL                         2:2
+#define VGA_CONFIGURATION_PLL_VGA                     0
+#define VGA_CONFIGURATION_PLL_PANEL                   1
+#define VGA_CONFIGURATION_MODE                        1:1
+#define VGA_CONFIGURATION_MODE_TEXT                   0
+#define VGA_CONFIGURATION_MODE_GRAPHIC                1
+
+#endif
+
+#define GPIO_DATA                                       0x010000
+#define GPIO_DATA_31                                    31:31
+#define GPIO_DATA_30                                    30:30
+#define GPIO_DATA_29                                    29:29
+#define GPIO_DATA_28                                    28:28
+#define GPIO_DATA_27                                    27:27
+#define GPIO_DATA_26                                    26:26
+#define GPIO_DATA_25                                    25:25
+#define GPIO_DATA_24                                    24:24
+#define GPIO_DATA_23                                    23:23
+#define GPIO_DATA_22                                    22:22
+#define GPIO_DATA_21                                    21:21
+#define GPIO_DATA_20                                    20:20
+#define GPIO_DATA_19                                    19:19
+#define GPIO_DATA_18                                    18:18
+#define GPIO_DATA_17                                    17:17
+#define GPIO_DATA_16                                    16:16
+#define GPIO_DATA_15                                    15:15
+#define GPIO_DATA_14                                    14:14
+#define GPIO_DATA_13                                    13:13
+#define GPIO_DATA_12                                    12:12
+#define GPIO_DATA_11                                    11:11
+#define GPIO_DATA_10                                    10:10
+#define GPIO_DATA_9                                     9:9
+#define GPIO_DATA_8                                     8:8
+#define GPIO_DATA_7                                     7:7
+#define GPIO_DATA_6                                     6:6
+#define GPIO_DATA_5                                     5:5
+#define GPIO_DATA_4                                     4:4
+#define GPIO_DATA_3                                     3:3
+#define GPIO_DATA_2                                     2:2
+#define GPIO_DATA_1                                     1:1
+#define GPIO_DATA_0                                     0:0
+
+#define GPIO_DATA_DIRECTION                             0x010004
+#define GPIO_DATA_DIRECTION_31                          31:31
+#define GPIO_DATA_DIRECTION_31_INPUT                    0
+#define GPIO_DATA_DIRECTION_31_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_30                          30:30
+#define GPIO_DATA_DIRECTION_30_INPUT                    0
+#define GPIO_DATA_DIRECTION_30_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_29                          29:29
+#define GPIO_DATA_DIRECTION_29_INPUT                    0
+#define GPIO_DATA_DIRECTION_29_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_28                          28:28
+#define GPIO_DATA_DIRECTION_28_INPUT                    0
+#define GPIO_DATA_DIRECTION_28_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_27                          27:27
+#define GPIO_DATA_DIRECTION_27_INPUT                    0
+#define GPIO_DATA_DIRECTION_27_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_26                          26:26
+#define GPIO_DATA_DIRECTION_26_INPUT                    0
+#define GPIO_DATA_DIRECTION_26_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_25                          25:25
+#define GPIO_DATA_DIRECTION_25_INPUT                    0
+#define GPIO_DATA_DIRECTION_25_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_24                          24:24
+#define GPIO_DATA_DIRECTION_24_INPUT                    0
+#define GPIO_DATA_DIRECTION_24_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_23                          23:23
+#define GPIO_DATA_DIRECTION_23_INPUT                    0
+#define GPIO_DATA_DIRECTION_23_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_22                          22:22
+#define GPIO_DATA_DIRECTION_22_INPUT                    0
+#define GPIO_DATA_DIRECTION_22_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_21                          21:21
+#define GPIO_DATA_DIRECTION_21_INPUT                    0
+#define GPIO_DATA_DIRECTION_21_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_20                          20:20
+#define GPIO_DATA_DIRECTION_20_INPUT                    0
+#define GPIO_DATA_DIRECTION_20_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_19                          19:19
+#define GPIO_DATA_DIRECTION_19_INPUT                    0
+#define GPIO_DATA_DIRECTION_19_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_18                          18:18
+#define GPIO_DATA_DIRECTION_18_INPUT                    0
+#define GPIO_DATA_DIRECTION_18_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_17                          17:17
+#define GPIO_DATA_DIRECTION_17_INPUT                    0
+#define GPIO_DATA_DIRECTION_17_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_16                          16:16
+#define GPIO_DATA_DIRECTION_16_INPUT                    0
+#define GPIO_DATA_DIRECTION_16_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_15                          15:15
+#define GPIO_DATA_DIRECTION_15_INPUT                    0
+#define GPIO_DATA_DIRECTION_15_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_14                          14:14
+#define GPIO_DATA_DIRECTION_14_INPUT                    0
+#define GPIO_DATA_DIRECTION_14_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_13                          13:13
+#define GPIO_DATA_DIRECTION_13_INPUT                    0
+#define GPIO_DATA_DIRECTION_13_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_12                          12:12
+#define GPIO_DATA_DIRECTION_12_INPUT                    0
+#define GPIO_DATA_DIRECTION_12_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_11                          11:11
+#define GPIO_DATA_DIRECTION_11_INPUT                    0
+#define GPIO_DATA_DIRECTION_11_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_10                          10:10
+#define GPIO_DATA_DIRECTION_10_INPUT                    0
+#define GPIO_DATA_DIRECTION_10_OUTPUT                   1
+#define GPIO_DATA_DIRECTION_9                           9:9
+#define GPIO_DATA_DIRECTION_9_INPUT                     0
+#define GPIO_DATA_DIRECTION_9_OUTPUT                    1
+#define GPIO_DATA_DIRECTION_8                           8:8
+#define GPIO_DATA_DIRECTION_8_INPUT                     0
+#define GPIO_DATA_DIRECTION_8_OUTPUT                    1
+#define GPIO_DATA_DIRECTION_7                           7:7
+#define GPIO_DATA_DIRECTION_7_INPUT                     0
+#define GPIO_DATA_DIRECTION_7_OUTPUT                    1
+#define GPIO_DATA_DIRECTION_6                           6:6
+#define GPIO_DATA_DIRECTION_6_INPUT                     0
+#define GPIO_DATA_DIRECTION_6_OUTPUT                    1
+#define GPIO_DATA_DIRECTION_5                           5:5
+#define GPIO_DATA_DIRECTION_5_INPUT                     0
+#define GPIO_DATA_DIRECTION_5_OUTPUT                    1
+#define GPIO_DATA_DIRECTION_4                           4:4
+#define GPIO_DATA_DIRECTION_4_INPUT                     0
+#define GPIO_DATA_DIRECTION_4_OUTPUT                    1
+#define GPIO_DATA_DIRECTION_3                           3:3
+#define GPIO_DATA_DIRECTION_3_INPUT                     0
+#define GPIO_DATA_DIRECTION_3_OUTPUT                    1
+#define GPIO_DATA_DIRECTION_2                           2:2
+#define GPIO_DATA_DIRECTION_2_INPUT                     0
+#define GPIO_DATA_DIRECTION_2_OUTPUT                    1
+#define GPIO_DATA_DIRECTION_1                           131
+#define GPIO_DATA_DIRECTION_1_INPUT                     0
+#define GPIO_DATA_DIRECTION_1_OUTPUT                    1
+#define GPIO_DATA_DIRECTION_0                           0:0
+#define GPIO_DATA_DIRECTION_0_INPUT                     0
+#define GPIO_DATA_DIRECTION_0_OUTPUT                    1
+
+#define GPIO_INTERRUPT_SETUP                            0x010008
+#define GPIO_INTERRUPT_SETUP_TRIGGER_31                 22:22
+#define GPIO_INTERRUPT_SETUP_TRIGGER_31_EDGE            0
+#define GPIO_INTERRUPT_SETUP_TRIGGER_31_LEVEL           1
+#define GPIO_INTERRUPT_SETUP_TRIGGER_30                 21:21
+#define GPIO_INTERRUPT_SETUP_TRIGGER_30_EDGE            0
+#define GPIO_INTERRUPT_SETUP_TRIGGER_30_LEVEL           1
+#define GPIO_INTERRUPT_SETUP_TRIGGER_29                 20:20
+#define GPIO_INTERRUPT_SETUP_TRIGGER_29_EDGE            0
+#define GPIO_INTERRUPT_SETUP_TRIGGER_29_LEVEL           1
+#define GPIO_INTERRUPT_SETUP_TRIGGER_28                 19:19
+#define GPIO_INTERRUPT_SETUP_TRIGGER_28_EDGE            0
+#define GPIO_INTERRUPT_SETUP_TRIGGER_28_LEVEL           1
+#define GPIO_INTERRUPT_SETUP_TRIGGER_27                 18:18
+#define GPIO_INTERRUPT_SETUP_TRIGGER_27_EDGE            0
+#define GPIO_INTERRUPT_SETUP_TRIGGER_27_LEVEL           1
+#define GPIO_INTERRUPT_SETUP_TRIGGER_26                 17:17
+#define GPIO_INTERRUPT_SETUP_TRIGGER_26_EDGE            0
+#define GPIO_INTERRUPT_SETUP_TRIGGER_26_LEVEL           1
+#define GPIO_INTERRUPT_SETUP_TRIGGER_25                 16:16
+#define GPIO_INTERRUPT_SETUP_TRIGGER_25_EDGE            0
+#define GPIO_INTERRUPT_SETUP_TRIGGER_25_LEVEL           1
+#define GPIO_INTERRUPT_SETUP_ACTIVE_31                  14:14
+#define GPIO_INTERRUPT_SETUP_ACTIVE_31_LOW              0
+#define GPIO_INTERRUPT_SETUP_ACTIVE_31_HIGH             1
+#define GPIO_INTERRUPT_SETUP_ACTIVE_30                  13:13
+#define GPIO_INTERRUPT_SETUP_ACTIVE_30_LOW              0
+#define GPIO_INTERRUPT_SETUP_ACTIVE_30_HIGH             1
+#define GPIO_INTERRUPT_SETUP_ACTIVE_29                  12:12
+#define GPIO_INTERRUPT_SETUP_ACTIVE_29_LOW              0
+#define GPIO_INTERRUPT_SETUP_ACTIVE_29_HIGH             1
+#define GPIO_INTERRUPT_SETUP_ACTIVE_28                  11:11
+#define GPIO_INTERRUPT_SETUP_ACTIVE_28_LOW              0
+#define GPIO_INTERRUPT_SETUP_ACTIVE_28_HIGH             1
+#define GPIO_INTERRUPT_SETUP_ACTIVE_27                  10:10
+#define GPIO_INTERRUPT_SETUP_ACTIVE_27_LOW              0
+#define GPIO_INTERRUPT_SETUP_ACTIVE_27_HIGH             1
+#define GPIO_INTERRUPT_SETUP_ACTIVE_26                  9:9
+#define GPIO_INTERRUPT_SETUP_ACTIVE_26_LOW              0
+#define GPIO_INTERRUPT_SETUP_ACTIVE_26_HIGH             1
+#define GPIO_INTERRUPT_SETUP_ACTIVE_25                  8:8
+#define GPIO_INTERRUPT_SETUP_ACTIVE_25_LOW              0
+#define GPIO_INTERRUPT_SETUP_ACTIVE_25_HIGH             1
+#define GPIO_INTERRUPT_SETUP_ENABLE_31                  6:6
+#define GPIO_INTERRUPT_SETUP_ENABLE_31_GPIO             0
+#define GPIO_INTERRUPT_SETUP_ENABLE_31_INTERRUPT        1
+#define GPIO_INTERRUPT_SETUP_ENABLE_30                  5:5
+#define GPIO_INTERRUPT_SETUP_ENABLE_30_GPIO             0
+#define GPIO_INTERRUPT_SETUP_ENABLE_30_INTERRUPT        1
+#define GPIO_INTERRUPT_SETUP_ENABLE_29                  4:4
+#define GPIO_INTERRUPT_SETUP_ENABLE_29_GPIO             0
+#define GPIO_INTERRUPT_SETUP_ENABLE_29_INTERRUPT        1
+#define GPIO_INTERRUPT_SETUP_ENABLE_28                  3:3
+#define GPIO_INTERRUPT_SETUP_ENABLE_28_GPIO             0
+#define GPIO_INTERRUPT_SETUP_ENABLE_28_INTERRUPT        1
+#define GPIO_INTERRUPT_SETUP_ENABLE_27                  2:2
+#define GPIO_INTERRUPT_SETUP_ENABLE_27_GPIO             0
+#define GPIO_INTERRUPT_SETUP_ENABLE_27_INTERRUPT        1
+#define GPIO_INTERRUPT_SETUP_ENABLE_26                  1:1
+#define GPIO_INTERRUPT_SETUP_ENABLE_26_GPIO             0
+#define GPIO_INTERRUPT_SETUP_ENABLE_26_INTERRUPT        1
+#define GPIO_INTERRUPT_SETUP_ENABLE_25                  0:0
+#define GPIO_INTERRUPT_SETUP_ENABLE_25_GPIO             0
+#define GPIO_INTERRUPT_SETUP_ENABLE_25_INTERRUPT        1
+
+#define GPIO_INTERRUPT_STATUS                           0x01000C
+#define GPIO_INTERRUPT_STATUS_31                        22:22
+#define GPIO_INTERRUPT_STATUS_31_INACTIVE               0
+#define GPIO_INTERRUPT_STATUS_31_ACTIVE                 1
+#define GPIO_INTERRUPT_STATUS_31_RESET                  1
+#define GPIO_INTERRUPT_STATUS_30                        21:21
+#define GPIO_INTERRUPT_STATUS_30_INACTIVE               0
+#define GPIO_INTERRUPT_STATUS_30_ACTIVE                 1
+#define GPIO_INTERRUPT_STATUS_30_RESET                  1
+#define GPIO_INTERRUPT_STATUS_29                        20:20
+#define GPIO_INTERRUPT_STATUS_29_INACTIVE               0
+#define GPIO_INTERRUPT_STATUS_29_ACTIVE                 1
+#define GPIO_INTERRUPT_STATUS_29_RESET                  1
+#define GPIO_INTERRUPT_STATUS_28                        19:19
+#define GPIO_INTERRUPT_STATUS_28_INACTIVE               0
+#define GPIO_INTERRUPT_STATUS_28_ACTIVE                 1
+#define GPIO_INTERRUPT_STATUS_28_RESET                  1
+#define GPIO_INTERRUPT_STATUS_27                        18:18
+#define GPIO_INTERRUPT_STATUS_27_INACTIVE               0
+#define GPIO_INTERRUPT_STATUS_27_ACTIVE                 1
+#define GPIO_INTERRUPT_STATUS_27_RESET                  1
+#define GPIO_INTERRUPT_STATUS_26                        17:17
+#define GPIO_INTERRUPT_STATUS_26_INACTIVE               0
+#define GPIO_INTERRUPT_STATUS_26_ACTIVE                 1
+#define GPIO_INTERRUPT_STATUS_26_RESET                  1
+#define GPIO_INTERRUPT_STATUS_25                        16:16
+#define GPIO_INTERRUPT_STATUS_25_INACTIVE               0
+#define GPIO_INTERRUPT_STATUS_25_ACTIVE                 1
+#define GPIO_INTERRUPT_STATUS_25_RESET                  1
+
+
+#define PANEL_DISPLAY_CTRL                            0x080000
+#define PANEL_DISPLAY_CTRL_RESERVED_1_MASK            31:30
+#define PANEL_DISPLAY_CTRL_RESERVED_1_MASK_DISABLE    0
+#define PANEL_DISPLAY_CTRL_RESERVED_1_MASK_ENABLE     3
+#define PANEL_DISPLAY_CTRL_SELECT                     29:28
+#define PANEL_DISPLAY_CTRL_SELECT_PANEL               0
+#define PANEL_DISPLAY_CTRL_SELECT_VGA                 1
+#define PANEL_DISPLAY_CTRL_SELECT_CRT                 2
+#define PANEL_DISPLAY_CTRL_FPEN                       27:27
+#define PANEL_DISPLAY_CTRL_FPEN_LOW                   0
+#define PANEL_DISPLAY_CTRL_FPEN_HIGH                  1
+#define PANEL_DISPLAY_CTRL_VBIASEN                    26:26
+#define PANEL_DISPLAY_CTRL_VBIASEN_LOW                0
+#define PANEL_DISPLAY_CTRL_VBIASEN_HIGH               1
+#define PANEL_DISPLAY_CTRL_DATA                       25:25
+#define PANEL_DISPLAY_CTRL_DATA_DISABLE               0
+#define PANEL_DISPLAY_CTRL_DATA_ENABLE                1
+#define PANEL_DISPLAY_CTRL_FPVDDEN                    24:24
+#define PANEL_DISPLAY_CTRL_FPVDDEN_LOW                0
+#define PANEL_DISPLAY_CTRL_FPVDDEN_HIGH               1
+#define PANEL_DISPLAY_CTRL_RESERVED_2_MASK            23:20
+#define PANEL_DISPLAY_CTRL_RESERVED_2_MASK_DISABLE    0
+#define PANEL_DISPLAY_CTRL_RESERVED_2_MASK_ENABLE     15
+
+#define PANEL_DISPLAY_CTRL_TFT_DISP 19:18
+#define PANEL_DISPLAY_CTRL_TFT_DISP_24 0
+#define PANEL_DISPLAY_CTRL_TFT_DISP_36 1
+#define PANEL_DISPLAY_CTRL_TFT_DISP_18 2
+
+
+#define PANEL_DISPLAY_CTRL_DUAL_DISPLAY               19:19
+#define PANEL_DISPLAY_CTRL_DUAL_DISPLAY_DISABLE       0
+#define PANEL_DISPLAY_CTRL_DUAL_DISPLAY_ENABLE        1
+#define PANEL_DISPLAY_CTRL_DOUBLE_PIXEL               18:18
+#define PANEL_DISPLAY_CTRL_DOUBLE_PIXEL_DISABLE       0
+#define PANEL_DISPLAY_CTRL_DOUBLE_PIXEL_ENABLE        1
+#define PANEL_DISPLAY_CTRL_FIFO                       17:16
+#define PANEL_DISPLAY_CTRL_FIFO_1                     0
+#define PANEL_DISPLAY_CTRL_FIFO_3                     1
+#define PANEL_DISPLAY_CTRL_FIFO_7                     2
+#define PANEL_DISPLAY_CTRL_FIFO_11                    3
+#define PANEL_DISPLAY_CTRL_RESERVED_3_MASK            15:15
+#define PANEL_DISPLAY_CTRL_RESERVED_3_MASK_DISABLE    0
+#define PANEL_DISPLAY_CTRL_RESERVED_3_MASK_ENABLE     1
+#define PANEL_DISPLAY_CTRL_CLOCK_PHASE                14:14
+#define PANEL_DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_HIGH    0
+#define PANEL_DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_LOW     1
+#define PANEL_DISPLAY_CTRL_VSYNC_PHASE                13:13
+#define PANEL_DISPLAY_CTRL_VSYNC_PHASE_ACTIVE_HIGH    0
+#define PANEL_DISPLAY_CTRL_VSYNC_PHASE_ACTIVE_LOW     1
+#define PANEL_DISPLAY_CTRL_HSYNC_PHASE                12:12
+#define PANEL_DISPLAY_CTRL_HSYNC_PHASE_ACTIVE_HIGH    0
+#define PANEL_DISPLAY_CTRL_HSYNC_PHASE_ACTIVE_LOW     1
+#define PANEL_DISPLAY_CTRL_VSYNC                      11:11
+#define PANEL_DISPLAY_CTRL_VSYNC_ACTIVE_HIGH          0
+#define PANEL_DISPLAY_CTRL_VSYNC_ACTIVE_LOW           1
+#define PANEL_DISPLAY_CTRL_CAPTURE_TIMING             10:10
+#define PANEL_DISPLAY_CTRL_CAPTURE_TIMING_DISABLE     0
+#define PANEL_DISPLAY_CTRL_CAPTURE_TIMING_ENABLE      1
+#define PANEL_DISPLAY_CTRL_COLOR_KEY                  9:9
+#define PANEL_DISPLAY_CTRL_COLOR_KEY_DISABLE          0
+#define PANEL_DISPLAY_CTRL_COLOR_KEY_ENABLE           1
+#define PANEL_DISPLAY_CTRL_TIMING                     8:8
+#define PANEL_DISPLAY_CTRL_TIMING_DISABLE             0
+#define PANEL_DISPLAY_CTRL_TIMING_ENABLE              1
+#define PANEL_DISPLAY_CTRL_VERTICAL_PAN_DIR           7:7
+#define PANEL_DISPLAY_CTRL_VERTICAL_PAN_DIR_DOWN      0
+#define PANEL_DISPLAY_CTRL_VERTICAL_PAN_DIR_UP        1
+#define PANEL_DISPLAY_CTRL_VERTICAL_PAN               6:6
+#define PANEL_DISPLAY_CTRL_VERTICAL_PAN_DISABLE       0
+#define PANEL_DISPLAY_CTRL_VERTICAL_PAN_ENABLE        1
+#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN_DIR         5:5
+#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN_DIR_RIGHT   0
+#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN_DIR_LEFT    1
+#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN             4:4
+#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN_DISABLE     0
+#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN_ENABLE      1
+#define PANEL_DISPLAY_CTRL_GAMMA                      3:3
+#define PANEL_DISPLAY_CTRL_GAMMA_DISABLE              0
+#define PANEL_DISPLAY_CTRL_GAMMA_ENABLE               1
+#define PANEL_DISPLAY_CTRL_PLANE                      2:2
+#define PANEL_DISPLAY_CTRL_PLANE_DISABLE              0
+#define PANEL_DISPLAY_CTRL_PLANE_ENABLE               1
+#define PANEL_DISPLAY_CTRL_FORMAT                     1:0
+#define PANEL_DISPLAY_CTRL_FORMAT_8                   0
+#define PANEL_DISPLAY_CTRL_FORMAT_16                  1
+#define PANEL_DISPLAY_CTRL_FORMAT_32                  2
+
+#define PANEL_PAN_CTRL                                0x080004
+#define PANEL_PAN_CTRL_VERTICAL_PAN                   31:24
+#define PANEL_PAN_CTRL_VERTICAL_VSYNC                 21:16
+#define PANEL_PAN_CTRL_HORIZONTAL_PAN                 15:8
+#define PANEL_PAN_CTRL_HORIZONTAL_VSYNC               5:0
+
+#define PANEL_COLOR_KEY                               0x080008
+#define PANEL_COLOR_KEY_MASK                          31:16
+#define PANEL_COLOR_KEY_VALUE                         15:0
+
+#define PANEL_FB_ADDRESS                              0x08000C
+#define PANEL_FB_ADDRESS_STATUS                       31:31
+#define PANEL_FB_ADDRESS_STATUS_CURRENT               0
+#define PANEL_FB_ADDRESS_STATUS_PENDING               1
+#define PANEL_FB_ADDRESS_EXT                          27:27
+#define PANEL_FB_ADDRESS_EXT_LOCAL                    0
+#define PANEL_FB_ADDRESS_EXT_EXTERNAL                 1
+#define PANEL_FB_ADDRESS_ADDRESS                      25:0
+
+#define PANEL_FB_WIDTH                                0x080010
+#define PANEL_FB_WIDTH_WIDTH                          29:16
+#define PANEL_FB_WIDTH_OFFSET                         13:0
+
+#define PANEL_WINDOW_WIDTH                            0x080014
+#define PANEL_WINDOW_WIDTH_WIDTH                      27:16
+#define PANEL_WINDOW_WIDTH_X                          11:0
+
+#define PANEL_WINDOW_HEIGHT                           0x080018
+#define PANEL_WINDOW_HEIGHT_HEIGHT                    27:16
+#define PANEL_WINDOW_HEIGHT_Y                         11:0
+
+#define PANEL_PLANE_TL                                0x08001C
+#define PANEL_PLANE_TL_TOP                            26:16
+#define PANEL_PLANE_TL_LEFT                           10:0
+
+#define PANEL_PLANE_BR                                0x080020
+#define PANEL_PLANE_BR_BOTTOM                         26:16
+#define PANEL_PLANE_BR_RIGHT                          10:0
+
+#define PANEL_HORIZONTAL_TOTAL                        0x080024
+#define PANEL_HORIZONTAL_TOTAL_TOTAL                  27:16
+#define PANEL_HORIZONTAL_TOTAL_DISPLAY_END            11:0
+
+#define PANEL_HORIZONTAL_SYNC                         0x080028
+#define PANEL_HORIZONTAL_SYNC_WIDTH                   23:16
+#define PANEL_HORIZONTAL_SYNC_START                   11:0
+
+#define PANEL_VERTICAL_TOTAL                          0x08002C
+#define PANEL_VERTICAL_TOTAL_TOTAL                    26:16
+#define PANEL_VERTICAL_TOTAL_DISPLAY_END              10:0
+
+#define PANEL_VERTICAL_SYNC                           0x080030
+#define PANEL_VERTICAL_SYNC_HEIGHT                    21:16
+#define PANEL_VERTICAL_SYNC_START                     10:0
+
+#define PANEL_CURRENT_LINE                            0x080034
+#define PANEL_CURRENT_LINE_LINE                       10:0
+
+/* Video Control */
+
+#define VIDEO_DISPLAY_CTRL                              0x080040
+#define VIDEO_DISPLAY_CTRL_LINE_BUFFER                  18:18
+#define VIDEO_DISPLAY_CTRL_LINE_BUFFER_DISABLE          0
+#define VIDEO_DISPLAY_CTRL_LINE_BUFFER_ENABLE           1
+#define VIDEO_DISPLAY_CTRL_FIFO                         17:16
+#define VIDEO_DISPLAY_CTRL_FIFO_1                       0
+#define VIDEO_DISPLAY_CTRL_FIFO_3                       1
+#define VIDEO_DISPLAY_CTRL_FIFO_7                       2
+#define VIDEO_DISPLAY_CTRL_FIFO_11                      3
+#define VIDEO_DISPLAY_CTRL_BUFFER                       15:15
+#define VIDEO_DISPLAY_CTRL_BUFFER_0                     0
+#define VIDEO_DISPLAY_CTRL_BUFFER_1                     1
+#define VIDEO_DISPLAY_CTRL_CAPTURE                      14:14
+#define VIDEO_DISPLAY_CTRL_CAPTURE_DISABLE              0
+#define VIDEO_DISPLAY_CTRL_CAPTURE_ENABLE               1
+#define VIDEO_DISPLAY_CTRL_DOUBLE_BUFFER                13:13
+#define VIDEO_DISPLAY_CTRL_DOUBLE_BUFFER_DISABLE        0
+#define VIDEO_DISPLAY_CTRL_DOUBLE_BUFFER_ENABLE         1
+#define VIDEO_DISPLAY_CTRL_BYTE_SWAP                    12:12
+#define VIDEO_DISPLAY_CTRL_BYTE_SWAP_DISABLE            0
+#define VIDEO_DISPLAY_CTRL_BYTE_SWAP_ENABLE             1
+#define VIDEO_DISPLAY_CTRL_VERTICAL_SCALE               11:11
+#define VIDEO_DISPLAY_CTRL_VERTICAL_SCALE_NORMAL        0
+#define VIDEO_DISPLAY_CTRL_VERTICAL_SCALE_HALF          1
+#define VIDEO_DISPLAY_CTRL_HORIZONTAL_SCALE             10:10
+#define VIDEO_DISPLAY_CTRL_HORIZONTAL_SCALE_NORMAL      0
+#define VIDEO_DISPLAY_CTRL_HORIZONTAL_SCALE_HALF        1
+#define VIDEO_DISPLAY_CTRL_VERTICAL_MODE                9:9
+#define VIDEO_DISPLAY_CTRL_VERTICAL_MODE_REPLICATE      0
+#define VIDEO_DISPLAY_CTRL_VERTICAL_MODE_INTERPOLATE    1
+#define VIDEO_DISPLAY_CTRL_HORIZONTAL_MODE              8:8
+#define VIDEO_DISPLAY_CTRL_HORIZONTAL_MODE_REPLICATE    0
+#define VIDEO_DISPLAY_CTRL_HORIZONTAL_MODE_INTERPOLATE  1
+#define VIDEO_DISPLAY_CTRL_PIXEL                        7:4
+#define VIDEO_DISPLAY_CTRL_GAMMA                        3:3
+#define VIDEO_DISPLAY_CTRL_GAMMA_DISABLE                0
+#define VIDEO_DISPLAY_CTRL_GAMMA_ENABLE                 1
+#define VIDEO_DISPLAY_CTRL_PLANE                        2:2
+#define VIDEO_DISPLAY_CTRL_PLANE_DISABLE                0
+#define VIDEO_DISPLAY_CTRL_PLANE_ENABLE                 1
+#define VIDEO_DISPLAY_CTRL_FORMAT                       1:0
+#define VIDEO_DISPLAY_CTRL_FORMAT_8                     0
+#define VIDEO_DISPLAY_CTRL_FORMAT_16                    1
+#define VIDEO_DISPLAY_CTRL_FORMAT_32                    2
+#define VIDEO_DISPLAY_CTRL_FORMAT_YUV                   3
+
+#define VIDEO_FB_0_ADDRESS                            0x080044
+#define VIDEO_FB_0_ADDRESS_STATUS                     31:31
+#define VIDEO_FB_0_ADDRESS_STATUS_CURRENT             0
+#define VIDEO_FB_0_ADDRESS_STATUS_PENDING             1
+#define VIDEO_FB_0_ADDRESS_EXT                        27:27
+#define VIDEO_FB_0_ADDRESS_EXT_LOCAL                  0
+#define VIDEO_FB_0_ADDRESS_EXT_EXTERNAL               1
+#define VIDEO_FB_0_ADDRESS_ADDRESS                    25:0
+
+#define VIDEO_FB_WIDTH                                0x080048
+#define VIDEO_FB_WIDTH_WIDTH                          29:16
+#define VIDEO_FB_WIDTH_OFFSET                         13:0
+
+#define VIDEO_FB_0_LAST_ADDRESS                       0x08004C
+#define VIDEO_FB_0_LAST_ADDRESS_EXT                   27:27
+#define VIDEO_FB_0_LAST_ADDRESS_EXT_LOCAL             0
+#define VIDEO_FB_0_LAST_ADDRESS_EXT_EXTERNAL          1
+#define VIDEO_FB_0_LAST_ADDRESS_ADDRESS               25:0
+
+#define VIDEO_PLANE_TL                                0x080050
+#define VIDEO_PLANE_TL_TOP                            26:16
+#define VIDEO_PLANE_TL_LEFT                           10:0
+
+#define VIDEO_PLANE_BR                                0x080054
+#define VIDEO_PLANE_BR_BOTTOM                         26:16
+#define VIDEO_PLANE_BR_RIGHT                          10:0
+
+#define VIDEO_SCALE                                   0x080058
+#define VIDEO_SCALE_VERTICAL_MODE                     31:31
+#define VIDEO_SCALE_VERTICAL_MODE_EXPAND              0
+#define VIDEO_SCALE_VERTICAL_MODE_SHRINK              1
+#define VIDEO_SCALE_VERTICAL_SCALE                    27:16
+#define VIDEO_SCALE_HORIZONTAL_MODE                   15:15
+#define VIDEO_SCALE_HORIZONTAL_MODE_EXPAND            0
+#define VIDEO_SCALE_HORIZONTAL_MODE_SHRINK            1
+#define VIDEO_SCALE_HORIZONTAL_SCALE                  11:0
+
+#define VIDEO_INITIAL_SCALE                           0x08005C
+#define VIDEO_INITIAL_SCALE_FB_1                      27:16
+#define VIDEO_INITIAL_SCALE_FB_0                      11:0
+
+#define VIDEO_YUV_CONSTANTS                           0x080060
+#define VIDEO_YUV_CONSTANTS_Y                         31:24
+#define VIDEO_YUV_CONSTANTS_R                         23:16
+#define VIDEO_YUV_CONSTANTS_G                         15:8
+#define VIDEO_YUV_CONSTANTS_B                         7:0
+
+#define VIDEO_FB_1_ADDRESS                            0x080064
+#define VIDEO_FB_1_ADDRESS_STATUS                     31:31
+#define VIDEO_FB_1_ADDRESS_STATUS_CURRENT             0
+#define VIDEO_FB_1_ADDRESS_STATUS_PENDING             1
+#define VIDEO_FB_1_ADDRESS_EXT                        27:27
+#define VIDEO_FB_1_ADDRESS_EXT_LOCAL                  0
+#define VIDEO_FB_1_ADDRESS_EXT_EXTERNAL               1
+#define VIDEO_FB_1_ADDRESS_ADDRESS                    25:0
+
+#define VIDEO_FB_1_LAST_ADDRESS                       0x080068
+#define VIDEO_FB_1_LAST_ADDRESS_EXT                   27:27
+#define VIDEO_FB_1_LAST_ADDRESS_EXT_LOCAL             0
+#define VIDEO_FB_1_LAST_ADDRESS_EXT_EXTERNAL          1
+#define VIDEO_FB_1_LAST_ADDRESS_ADDRESS               25:0
+
+/* Video Alpha Control */
+
+#define VIDEO_ALPHA_DISPLAY_CTRL                        0x080080
+#define VIDEO_ALPHA_DISPLAY_CTRL_SELECT                 28:28
+#define VIDEO_ALPHA_DISPLAY_CTRL_SELECT_PER_PIXEL       0
+#define VIDEO_ALPHA_DISPLAY_CTRL_SELECT_ALPHA           1
+#define VIDEO_ALPHA_DISPLAY_CTRL_ALPHA                  27:24
+#define VIDEO_ALPHA_DISPLAY_CTRL_FIFO                   17:16
+#define VIDEO_ALPHA_DISPLAY_CTRL_FIFO_1                 0
+#define VIDEO_ALPHA_DISPLAY_CTRL_FIFO_3                 1
+#define VIDEO_ALPHA_DISPLAY_CTRL_FIFO_7                 2
+#define VIDEO_ALPHA_DISPLAY_CTRL_FIFO_11                3
+#define VIDEO_ALPHA_DISPLAY_CTRL_VERT_SCALE             11:11
+#define VIDEO_ALPHA_DISPLAY_CTRL_VERT_SCALE_NORMAL      0
+#define VIDEO_ALPHA_DISPLAY_CTRL_VERT_SCALE_HALF        1
+#define VIDEO_ALPHA_DISPLAY_CTRL_HORZ_SCALE             10:10
+#define VIDEO_ALPHA_DISPLAY_CTRL_HORZ_SCALE_NORMAL      0
+#define VIDEO_ALPHA_DISPLAY_CTRL_HORZ_SCALE_HALF        1
+#define VIDEO_ALPHA_DISPLAY_CTRL_VERT_MODE              9:9
+#define VIDEO_ALPHA_DISPLAY_CTRL_VERT_MODE_REPLICATE    0
+#define VIDEO_ALPHA_DISPLAY_CTRL_VERT_MODE_INTERPOLATE  1
+#define VIDEO_ALPHA_DISPLAY_CTRL_HORZ_MODE              8:8
+#define VIDEO_ALPHA_DISPLAY_CTRL_HORZ_MODE_REPLICATE    0
+#define VIDEO_ALPHA_DISPLAY_CTRL_HORZ_MODE_INTERPOLATE  1
+#define VIDEO_ALPHA_DISPLAY_CTRL_PIXEL                  7:4
+#define VIDEO_ALPHA_DISPLAY_CTRL_CHROMA_KEY             3:3
+#define VIDEO_ALPHA_DISPLAY_CTRL_CHROMA_KEY_DISABLE     0
+#define VIDEO_ALPHA_DISPLAY_CTRL_CHROMA_KEY_ENABLE      1
+#define VIDEO_ALPHA_DISPLAY_CTRL_PLANE                  2:2
+#define VIDEO_ALPHA_DISPLAY_CTRL_PLANE_DISABLE          0
+#define VIDEO_ALPHA_DISPLAY_CTRL_PLANE_ENABLE           1
+#define VIDEO_ALPHA_DISPLAY_CTRL_FORMAT                 1:0
+#define VIDEO_ALPHA_DISPLAY_CTRL_FORMAT_8               0
+#define VIDEO_ALPHA_DISPLAY_CTRL_FORMAT_16              1
+#define VIDEO_ALPHA_DISPLAY_CTRL_FORMAT_ALPHA_4_4       2
+#define VIDEO_ALPHA_DISPLAY_CTRL_FORMAT_ALPHA_4_4_4_4   3
+
+#define VIDEO_ALPHA_FB_ADDRESS                        0x080084
+#define VIDEO_ALPHA_FB_ADDRESS_STATUS                 31:31
+#define VIDEO_ALPHA_FB_ADDRESS_STATUS_CURRENT         0
+#define VIDEO_ALPHA_FB_ADDRESS_STATUS_PENDING         1
+#define VIDEO_ALPHA_FB_ADDRESS_EXT                    27:27
+#define VIDEO_ALPHA_FB_ADDRESS_EXT_LOCAL              0
+#define VIDEO_ALPHA_FB_ADDRESS_EXT_EXTERNAL           1
+#define VIDEO_ALPHA_FB_ADDRESS_ADDRESS                25:0
+
+#define VIDEO_ALPHA_FB_WIDTH                          0x080088
+#define VIDEO_ALPHA_FB_WIDTH_WIDTH                    29:16
+#define VIDEO_ALPHA_FB_WIDTH_OFFSET                   13:0
+
+#define VIDEO_ALPHA_FB_LAST_ADDRESS                   0x08008C
+#define VIDEO_ALPHA_FB_LAST_ADDRESS_EXT               27:27
+#define VIDEO_ALPHA_FB_LAST_ADDRESS_EXT_LOCAL         0
+#define VIDEO_ALPHA_FB_LAST_ADDRESS_EXT_EXTERNAL      1
+#define VIDEO_ALPHA_FB_LAST_ADDRESS_ADDRESS           25:0
+
+#define VIDEO_ALPHA_PLANE_TL                          0x080090
+#define VIDEO_ALPHA_PLANE_TL_TOP                      26:16
+#define VIDEO_ALPHA_PLANE_TL_LEFT                     10:0
+
+#define VIDEO_ALPHA_PLANE_BR                          0x080094
+#define VIDEO_ALPHA_PLANE_BR_BOTTOM                   26:16
+#define VIDEO_ALPHA_PLANE_BR_RIGHT                    10:0
+
+#define VIDEO_ALPHA_SCALE                             0x080098
+#define VIDEO_ALPHA_SCALE_VERTICAL_MODE               31:31
+#define VIDEO_ALPHA_SCALE_VERTICAL_MODE_EXPAND        0
+#define VIDEO_ALPHA_SCALE_VERTICAL_MODE_SHRINK        1
+#define VIDEO_ALPHA_SCALE_VERTICAL_SCALE              27:16
+#define VIDEO_ALPHA_SCALE_HORIZONTAL_MODE             15:15
+#define VIDEO_ALPHA_SCALE_HORIZONTAL_MODE_EXPAND      0
+#define VIDEO_ALPHA_SCALE_HORIZONTAL_MODE_SHRINK      1
+#define VIDEO_ALPHA_SCALE_HORIZONTAL_SCALE            11:0
+
+#define VIDEO_ALPHA_INITIAL_SCALE                     0x08009C
+#define VIDEO_ALPHA_INITIAL_SCALE_VERTICAL            27:16
+#define VIDEO_ALPHA_INITIAL_SCALE_HORIZONTAL          11:0
+
+#define VIDEO_ALPHA_CHROMA_KEY                        0x0800A0
+#define VIDEO_ALPHA_CHROMA_KEY_MASK                   31:16
+#define VIDEO_ALPHA_CHROMA_KEY_VALUE                  15:0
+
+#define VIDEO_ALPHA_COLOR_LOOKUP_01                   0x0800A4
+#define VIDEO_ALPHA_COLOR_LOOKUP_01_1                 31:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_01_1_RED             31:27
+#define VIDEO_ALPHA_COLOR_LOOKUP_01_1_GREEN           26:21
+#define VIDEO_ALPHA_COLOR_LOOKUP_01_1_BLUE            20:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_01_0                 15:0
+#define VIDEO_ALPHA_COLOR_LOOKUP_01_0_RED             15:11
+#define VIDEO_ALPHA_COLOR_LOOKUP_01_0_GREEN           10:5
+#define VIDEO_ALPHA_COLOR_LOOKUP_01_0_BLUE            4:0
+
+#define VIDEO_ALPHA_COLOR_LOOKUP_23                   0x0800A8
+#define VIDEO_ALPHA_COLOR_LOOKUP_23_3                 31:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_23_3_RED             31:27
+#define VIDEO_ALPHA_COLOR_LOOKUP_23_3_GREEN           26:21
+#define VIDEO_ALPHA_COLOR_LOOKUP_23_3_BLUE            20:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_23_2                 15:0
+#define VIDEO_ALPHA_COLOR_LOOKUP_23_2_RED             15:11
+#define VIDEO_ALPHA_COLOR_LOOKUP_23_2_GREEN           10:5
+#define VIDEO_ALPHA_COLOR_LOOKUP_23_2_BLUE            4:0
+
+#define VIDEO_ALPHA_COLOR_LOOKUP_45                   0x0800AC
+#define VIDEO_ALPHA_COLOR_LOOKUP_45_5                 31:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_45_5_RED             31:27
+#define VIDEO_ALPHA_COLOR_LOOKUP_45_5_GREEN           26:21
+#define VIDEO_ALPHA_COLOR_LOOKUP_45_5_BLUE            20:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_45_4                 15:0
+#define VIDEO_ALPHA_COLOR_LOOKUP_45_4_RED             15:11
+#define VIDEO_ALPHA_COLOR_LOOKUP_45_4_GREEN           10:5
+#define VIDEO_ALPHA_COLOR_LOOKUP_45_4_BLUE            4:0
+
+#define VIDEO_ALPHA_COLOR_LOOKUP_67                   0x0800B0
+#define VIDEO_ALPHA_COLOR_LOOKUP_67_7                 31:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_67_7_RED             31:27
+#define VIDEO_ALPHA_COLOR_LOOKUP_67_7_GREEN           26:21
+#define VIDEO_ALPHA_COLOR_LOOKUP_67_7_BLUE            20:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_67_6                 15:0
+#define VIDEO_ALPHA_COLOR_LOOKUP_67_6_RED             15:11
+#define VIDEO_ALPHA_COLOR_LOOKUP_67_6_GREEN           10:5
+#define VIDEO_ALPHA_COLOR_LOOKUP_67_6_BLUE            4:0
+
+#define VIDEO_ALPHA_COLOR_LOOKUP_89                   0x0800B4
+#define VIDEO_ALPHA_COLOR_LOOKUP_89_9                 31:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_89_9_RED             31:27
+#define VIDEO_ALPHA_COLOR_LOOKUP_89_9_GREEN           26:21
+#define VIDEO_ALPHA_COLOR_LOOKUP_89_9_BLUE            20:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_89_8                 15:0
+#define VIDEO_ALPHA_COLOR_LOOKUP_89_8_RED             15:11
+#define VIDEO_ALPHA_COLOR_LOOKUP_89_8_GREEN           10:5
+#define VIDEO_ALPHA_COLOR_LOOKUP_89_8_BLUE            4:0
+
+#define VIDEO_ALPHA_COLOR_LOOKUP_AB                   0x0800B8
+#define VIDEO_ALPHA_COLOR_LOOKUP_AB_B                 31:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_AB_B_RED             31:27
+#define VIDEO_ALPHA_COLOR_LOOKUP_AB_B_GREEN           26:21
+#define VIDEO_ALPHA_COLOR_LOOKUP_AB_B_BLUE            20:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_AB_A                 15:0
+#define VIDEO_ALPHA_COLOR_LOOKUP_AB_A_RED             15:11
+#define VIDEO_ALPHA_COLOR_LOOKUP_AB_A_GREEN           10:5
+#define VIDEO_ALPHA_COLOR_LOOKUP_AB_A_BLUE            4:0
+
+#define VIDEO_ALPHA_COLOR_LOOKUP_CD                   0x0800BC
+#define VIDEO_ALPHA_COLOR_LOOKUP_CD_D                 31:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_CD_D_RED             31:27
+#define VIDEO_ALPHA_COLOR_LOOKUP_CD_D_GREEN           26:21
+#define VIDEO_ALPHA_COLOR_LOOKUP_CD_D_BLUE            20:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_CD_C                 15:0
+#define VIDEO_ALPHA_COLOR_LOOKUP_CD_C_RED             15:11
+#define VIDEO_ALPHA_COLOR_LOOKUP_CD_C_GREEN           10:5
+#define VIDEO_ALPHA_COLOR_LOOKUP_CD_C_BLUE            4:0
+
+#define VIDEO_ALPHA_COLOR_LOOKUP_EF                   0x0800C0
+#define VIDEO_ALPHA_COLOR_LOOKUP_EF_F                 31:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_EF_F_RED             31:27
+#define VIDEO_ALPHA_COLOR_LOOKUP_EF_F_GREEN           26:21
+#define VIDEO_ALPHA_COLOR_LOOKUP_EF_F_BLUE            20:16
+#define VIDEO_ALPHA_COLOR_LOOKUP_EF_E                 15:0
+#define VIDEO_ALPHA_COLOR_LOOKUP_EF_E_RED             15:11
+#define VIDEO_ALPHA_COLOR_LOOKUP_EF_E_GREEN           10:5
+#define VIDEO_ALPHA_COLOR_LOOKUP_EF_E_BLUE            4:0
+
+/* Panel Cursor Control */
+
+#define PANEL_HWC_ADDRESS                             0x0800F0
+#define PANEL_HWC_ADDRESS_ENABLE                      31:31
+#define PANEL_HWC_ADDRESS_ENABLE_DISABLE              0
+#define PANEL_HWC_ADDRESS_ENABLE_ENABLE               1
+#define PANEL_HWC_ADDRESS_EXT                         27:27
+#define PANEL_HWC_ADDRESS_EXT_LOCAL                   0
+#define PANEL_HWC_ADDRESS_EXT_EXTERNAL                1
+#define PANEL_HWC_ADDRESS_ADDRESS                     25:0
+
+#define PANEL_HWC_LOCATION                            0x0800F4
+#define PANEL_HWC_LOCATION_TOP                        27:27
+#define PANEL_HWC_LOCATION_TOP_INSIDE                 0
+#define PANEL_HWC_LOCATION_TOP_OUTSIDE                1
+#define PANEL_HWC_LOCATION_Y                          26:16
+#define PANEL_HWC_LOCATION_LEFT                       11:11
+#define PANEL_HWC_LOCATION_LEFT_INSIDE                0
+#define PANEL_HWC_LOCATION_LEFT_OUTSIDE               1
+#define PANEL_HWC_LOCATION_X                          10:0
+
+#define PANEL_HWC_COLOR_12                            0x0800F8
+#define PANEL_HWC_COLOR_12_2_RGB565                   31:16
+#define PANEL_HWC_COLOR_12_1_RGB565                   15:0
+
+#define PANEL_HWC_COLOR_3                             0x0800FC
+#define PANEL_HWC_COLOR_3_RGB565                      15:0
+
+/* Old Definitions +++ */
+#define PANEL_HWC_COLOR_01                            0x0800F8
+#define PANEL_HWC_COLOR_01_1_RED                      31:27
+#define PANEL_HWC_COLOR_01_1_GREEN                    26:21
+#define PANEL_HWC_COLOR_01_1_BLUE                     20:16
+#define PANEL_HWC_COLOR_01_0_RED                      15:11
+#define PANEL_HWC_COLOR_01_0_GREEN                    10:5
+#define PANEL_HWC_COLOR_01_0_BLUE                     4:0
+
+#define PANEL_HWC_COLOR_2                             0x0800FC
+#define PANEL_HWC_COLOR_2_RED                         15:11
+#define PANEL_HWC_COLOR_2_GREEN                       10:5
+#define PANEL_HWC_COLOR_2_BLUE                        4:0
+/* Old Definitions --- */
+
+/* Alpha Control */
+
+#define ALPHA_DISPLAY_CTRL                            0x080100
+#define ALPHA_DISPLAY_CTRL_SELECT                     28:28
+#define ALPHA_DISPLAY_CTRL_SELECT_PER_PIXEL           0
+#define ALPHA_DISPLAY_CTRL_SELECT_ALPHA               1
+#define ALPHA_DISPLAY_CTRL_ALPHA                      27:24
+#define ALPHA_DISPLAY_CTRL_FIFO                       17:16
+#define ALPHA_DISPLAY_CTRL_FIFO_1                     0
+#define ALPHA_DISPLAY_CTRL_FIFO_3                     1
+#define ALPHA_DISPLAY_CTRL_FIFO_7                     2
+#define ALPHA_DISPLAY_CTRL_FIFO_11                    3
+#define ALPHA_DISPLAY_CTRL_PIXEL                      7:4
+#define ALPHA_DISPLAY_CTRL_CHROMA_KEY                 3:3
+#define ALPHA_DISPLAY_CTRL_CHROMA_KEY_DISABLE         0
+#define ALPHA_DISPLAY_CTRL_CHROMA_KEY_ENABLE          1
+#define ALPHA_DISPLAY_CTRL_PLANE                      2:2
+#define ALPHA_DISPLAY_CTRL_PLANE_DISABLE              0
+#define ALPHA_DISPLAY_CTRL_PLANE_ENABLE               1
+#define ALPHA_DISPLAY_CTRL_FORMAT                     1:0
+#define ALPHA_DISPLAY_CTRL_FORMAT_16                  1
+#define ALPHA_DISPLAY_CTRL_FORMAT_ALPHA_4_4           2
+#define ALPHA_DISPLAY_CTRL_FORMAT_ALPHA_4_4_4_4       3
+
+#define ALPHA_FB_ADDRESS                              0x080104
+#define ALPHA_FB_ADDRESS_STATUS                       31:31
+#define ALPHA_FB_ADDRESS_STATUS_CURRENT               0
+#define ALPHA_FB_ADDRESS_STATUS_PENDING               1
+#define ALPHA_FB_ADDRESS_EXT                          27:27
+#define ALPHA_FB_ADDRESS_EXT_LOCAL                    0
+#define ALPHA_FB_ADDRESS_EXT_EXTERNAL                 1
+#define ALPHA_FB_ADDRESS_ADDRESS                      25:0
+
+#define ALPHA_FB_WIDTH                                0x080108
+#define ALPHA_FB_WIDTH_WIDTH                          29:16
+#define ALPHA_FB_WIDTH_OFFSET                         13:0
+
+#define ALPHA_PLANE_TL                                0x08010C
+#define ALPHA_PLANE_TL_TOP                            26:16
+#define ALPHA_PLANE_TL_LEFT                           10:0
+
+#define ALPHA_PLANE_BR                                0x080110
+#define ALPHA_PLANE_BR_BOTTOM                         26:16
+#define ALPHA_PLANE_BR_RIGHT                          10:0
+
+#define ALPHA_CHROMA_KEY                              0x080114
+#define ALPHA_CHROMA_KEY_MASK                         31:16
+#define ALPHA_CHROMA_KEY_VALUE                        15:0
+
+#define ALPHA_COLOR_LOOKUP_01                         0x080118
+#define ALPHA_COLOR_LOOKUP_01_1                       31:16
+#define ALPHA_COLOR_LOOKUP_01_1_RED                   31:27
+#define ALPHA_COLOR_LOOKUP_01_1_GREEN                 26:21
+#define ALPHA_COLOR_LOOKUP_01_1_BLUE                  20:16
+#define ALPHA_COLOR_LOOKUP_01_0                       15:0
+#define ALPHA_COLOR_LOOKUP_01_0_RED                   15:11
+#define ALPHA_COLOR_LOOKUP_01_0_GREEN                 10:5
+#define ALPHA_COLOR_LOOKUP_01_0_BLUE                  4:0
+
+#define ALPHA_COLOR_LOOKUP_23                         0x08011C
+#define ALPHA_COLOR_LOOKUP_23_3                       31:16
+#define ALPHA_COLOR_LOOKUP_23_3_RED                   31:27
+#define ALPHA_COLOR_LOOKUP_23_3_GREEN                 26:21
+#define ALPHA_COLOR_LOOKUP_23_3_BLUE                  20:16
+#define ALPHA_COLOR_LOOKUP_23_2                       15:0
+#define ALPHA_COLOR_LOOKUP_23_2_RED                   15:11
+#define ALPHA_COLOR_LOOKUP_23_2_GREEN                 10:5
+#define ALPHA_COLOR_LOOKUP_23_2_BLUE                  4:0
+
+#define ALPHA_COLOR_LOOKUP_45                         0x080120
+#define ALPHA_COLOR_LOOKUP_45_5                       31:16
+#define ALPHA_COLOR_LOOKUP_45_5_RED                   31:27
+#define ALPHA_COLOR_LOOKUP_45_5_GREEN                 26:21
+#define ALPHA_COLOR_LOOKUP_45_5_BLUE                  20:16
+#define ALPHA_COLOR_LOOKUP_45_4                       15:0
+#define ALPHA_COLOR_LOOKUP_45_4_RED                   15:11
+#define ALPHA_COLOR_LOOKUP_45_4_GREEN                 10:5
+#define ALPHA_COLOR_LOOKUP_45_4_BLUE                  4:0
+
+#define ALPHA_COLOR_LOOKUP_67                         0x080124
+#define ALPHA_COLOR_LOOKUP_67_7                       31:16
+#define ALPHA_COLOR_LOOKUP_67_7_RED                   31:27
+#define ALPHA_COLOR_LOOKUP_67_7_GREEN                 26:21
+#define ALPHA_COLOR_LOOKUP_67_7_BLUE                  20:16
+#define ALPHA_COLOR_LOOKUP_67_6                       15:0
+#define ALPHA_COLOR_LOOKUP_67_6_RED                   15:11
+#define ALPHA_COLOR_LOOKUP_67_6_GREEN                 10:5
+#define ALPHA_COLOR_LOOKUP_67_6_BLUE                  4:0
+
+#define ALPHA_COLOR_LOOKUP_89                         0x080128
+#define ALPHA_COLOR_LOOKUP_89_9                       31:16
+#define ALPHA_COLOR_LOOKUP_89_9_RED                   31:27
+#define ALPHA_COLOR_LOOKUP_89_9_GREEN                 26:21
+#define ALPHA_COLOR_LOOKUP_89_9_BLUE                  20:16
+#define ALPHA_COLOR_LOOKUP_89_8                       15:0
+#define ALPHA_COLOR_LOOKUP_89_8_RED                   15:11
+#define ALPHA_COLOR_LOOKUP_89_8_GREEN                 10:5
+#define ALPHA_COLOR_LOOKUP_89_8_BLUE                  4:0
+
+#define ALPHA_COLOR_LOOKUP_AB                         0x08012C
+#define ALPHA_COLOR_LOOKUP_AB_B                       31:16
+#define ALPHA_COLOR_LOOKUP_AB_B_RED                   31:27
+#define ALPHA_COLOR_LOOKUP_AB_B_GREEN                 26:21
+#define ALPHA_COLOR_LOOKUP_AB_B_BLUE                  20:16
+#define ALPHA_COLOR_LOOKUP_AB_A                       15:0
+#define ALPHA_COLOR_LOOKUP_AB_A_RED                   15:11
+#define ALPHA_COLOR_LOOKUP_AB_A_GREEN                 10:5
+#define ALPHA_COLOR_LOOKUP_AB_A_BLUE                  4:0
+
+#define ALPHA_COLOR_LOOKUP_CD                         0x080130
+#define ALPHA_COLOR_LOOKUP_CD_D                       31:16
+#define ALPHA_COLOR_LOOKUP_CD_D_RED                   31:27
+#define ALPHA_COLOR_LOOKUP_CD_D_GREEN                 26:21
+#define ALPHA_COLOR_LOOKUP_CD_D_BLUE                  20:16
+#define ALPHA_COLOR_LOOKUP_CD_C                       15:0
+#define ALPHA_COLOR_LOOKUP_CD_C_RED                   15:11
+#define ALPHA_COLOR_LOOKUP_CD_C_GREEN                 10:5
+#define ALPHA_COLOR_LOOKUP_CD_C_BLUE                  4:0
+
+#define ALPHA_COLOR_LOOKUP_EF                         0x080134
+#define ALPHA_COLOR_LOOKUP_EF_F                       31:16
+#define ALPHA_COLOR_LOOKUP_EF_F_RED                   31:27
+#define ALPHA_COLOR_LOOKUP_EF_F_GREEN                 26:21
+#define ALPHA_COLOR_LOOKUP_EF_F_BLUE                  20:16
+#define ALPHA_COLOR_LOOKUP_EF_E                       15:0
+#define ALPHA_COLOR_LOOKUP_EF_E_RED                   15:11
+#define ALPHA_COLOR_LOOKUP_EF_E_GREEN                 10:5
+#define ALPHA_COLOR_LOOKUP_EF_E_BLUE                  4:0
+
+/* 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
+
+/* SM750LE definition */
+#define CRT_DISPLAY_CTRL_DPMS                         31:30
+#define CRT_DISPLAY_CTRL_DPMS_0                       0
+#define CRT_DISPLAY_CTRL_DPMS_1                       1
+#define CRT_DISPLAY_CTRL_DPMS_2                       2
+#define CRT_DISPLAY_CTRL_DPMS_3                       3
+#define CRT_DISPLAY_CTRL_CLK                          29:27
+#define CRT_DISPLAY_CTRL_CLK_PLL25                    0
+#define CRT_DISPLAY_CTRL_CLK_PLL41                    1
+#define CRT_DISPLAY_CTRL_CLK_PLL62                    2
+#define CRT_DISPLAY_CTRL_CLK_PLL65                    3
+#define CRT_DISPLAY_CTRL_CLK_PLL74                    4
+#define CRT_DISPLAY_CTRL_CLK_PLL80                    5
+#define CRT_DISPLAY_CTRL_CLK_PLL108                   6
+#define CRT_DISPLAY_CTRL_CLK_RESERVED                 7
+#define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC                26:26
+#define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC_DISABLE        1
+#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
+
+/* SM750LE definition */
+#define CRT_DISPLAY_CTRL_CRTSELECT                    25:25
+#define CRT_DISPLAY_CTRL_CRTSELECT_VGA                0
+#define CRT_DISPLAY_CTRL_CRTSELECT_CRT                1
+#define CRT_DISPLAY_CTRL_RGBBIT                       24:24
+#define CRT_DISPLAY_CTRL_RGBBIT_24BIT                 0
+#define CRT_DISPLAY_CTRL_RGBBIT_12BIT                 1
+
+
+#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_DISABLE      0
+#define CRT_DISPLAY_CTRL_RESERVED_4_MASK_ENABLE       1
+
+#ifndef VALIDATION_CHIP
+    #define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC            26:26
+    #define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC_DISABLE    1
+    #define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC_ENABLE     0
+    #define CRT_DISPLAY_CTRL_CENTERING                24:24
+    #define CRT_DISPLAY_CTRL_CENTERING_DISABLE        0
+    #define CRT_DISPLAY_CTRL_CENTERING_ENABLE         1
+#endif
+#define CRT_DISPLAY_CTRL_LOCK_TIMING                  23:23
+#define CRT_DISPLAY_CTRL_LOCK_TIMING_DISABLE          0
+#define CRT_DISPLAY_CTRL_LOCK_TIMING_ENABLE           1
+#define CRT_DISPLAY_CTRL_EXPANSION                    22:22
+#define CRT_DISPLAY_CTRL_EXPANSION_DISABLE            0
+#define CRT_DISPLAY_CTRL_EXPANSION_ENABLE             1
+#define CRT_DISPLAY_CTRL_VERTICAL_MODE                21:21
+#define CRT_DISPLAY_CTRL_VERTICAL_MODE_REPLICATE      0
+#define CRT_DISPLAY_CTRL_VERTICAL_MODE_INTERPOLATE    1
+#define CRT_DISPLAY_CTRL_HORIZONTAL_MODE              20:20
+#define CRT_DISPLAY_CTRL_HORIZONTAL_MODE_REPLICATE    0
+#define CRT_DISPLAY_CTRL_HORIZONTAL_MODE_INTERPOLATE  1
+#define CRT_DISPLAY_CTRL_SELECT                       19:18
+#define CRT_DISPLAY_CTRL_SELECT_PANEL                 0
+#define CRT_DISPLAY_CTRL_SELECT_VGA                   1
+#define CRT_DISPLAY_CTRL_SELECT_CRT                   2
+#define CRT_DISPLAY_CTRL_FIFO                         17:16
+#define CRT_DISPLAY_CTRL_FIFO_1                       0
+#define CRT_DISPLAY_CTRL_FIFO_3                       1
+#define CRT_DISPLAY_CTRL_FIFO_7                       2
+#define CRT_DISPLAY_CTRL_FIFO_11                      3
+#define CRT_DISPLAY_CTRL_CLOCK_PHASE                  14:14
+#define CRT_DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_HIGH      0
+#define CRT_DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_LOW       1
+#define CRT_DISPLAY_CTRL_VSYNC_PHASE                  13:13
+#define CRT_DISPLAY_CTRL_VSYNC_PHASE_ACTIVE_HIGH      0
+#define CRT_DISPLAY_CTRL_VSYNC_PHASE_ACTIVE_LOW       1
+#define CRT_DISPLAY_CTRL_HSYNC_PHASE                  12:12
+#define CRT_DISPLAY_CTRL_HSYNC_PHASE_ACTIVE_HIGH      0
+#define CRT_DISPLAY_CTRL_HSYNC_PHASE_ACTIVE_LOW       1
+#define CRT_DISPLAY_CTRL_BLANK                        10:10
+#define CRT_DISPLAY_CTRL_BLANK_OFF                    0
+#define CRT_DISPLAY_CTRL_BLANK_ON                     1
+#define CRT_DISPLAY_CTRL_TIMING                       8:8
+#define CRT_DISPLAY_CTRL_TIMING_DISABLE               0
+#define CRT_DISPLAY_CTRL_TIMING_ENABLE                1
+#define CRT_DISPLAY_CTRL_PIXEL                        7:4
+#define CRT_DISPLAY_CTRL_GAMMA                        3:3
+#define CRT_DISPLAY_CTRL_GAMMA_DISABLE                0
+#define CRT_DISPLAY_CTRL_GAMMA_ENABLE                 1
+#define CRT_DISPLAY_CTRL_PLANE                        2:2
+#define CRT_DISPLAY_CTRL_PLANE_DISABLE                0
+#define CRT_DISPLAY_CTRL_PLANE_ENABLE                 1
+#define CRT_DISPLAY_CTRL_FORMAT                       1:0
+#define CRT_DISPLAY_CTRL_FORMAT_8                     0
+#define CRT_DISPLAY_CTRL_FORMAT_16                    1
+#define CRT_DISPLAY_CTRL_FORMAT_32                    2
+#define CRT_DISPLAY_CTRL_RESERVED_BITS_MASK           0xFF000200
+
+#define CRT_FB_ADDRESS                                0x080204
+#define CRT_FB_ADDRESS_STATUS                         31:31
+#define CRT_FB_ADDRESS_STATUS_CURRENT                 0
+#define CRT_FB_ADDRESS_STATUS_PENDING                 1
+#define CRT_FB_ADDRESS_EXT                            27:27
+#define CRT_FB_ADDRESS_EXT_LOCAL                      0
+#define CRT_FB_ADDRESS_EXT_EXTERNAL                   1
+#define CRT_FB_ADDRESS_ADDRESS                        25:0
+
+#define CRT_FB_WIDTH                                  0x080208
+#define CRT_FB_WIDTH_WIDTH                            29:16
+#define CRT_FB_WIDTH_OFFSET                           13:0
+
+#define CRT_HORIZONTAL_TOTAL                          0x08020C
+#define CRT_HORIZONTAL_TOTAL_TOTAL                    27:16
+#define CRT_HORIZONTAL_TOTAL_DISPLAY_END              11:0
+
+#define CRT_HORIZONTAL_SYNC                           0x080210
+#define CRT_HORIZONTAL_SYNC_WIDTH                     23:16
+#define CRT_HORIZONTAL_SYNC_START                     11:0
+
+#define CRT_VERTICAL_TOTAL                            0x080214
+#define CRT_VERTICAL_TOTAL_TOTAL                      26:16
+#define CRT_VERTICAL_TOTAL_DISPLAY_END                10:0
+
+#define CRT_VERTICAL_SYNC                             0x080218
+#define CRT_VERTICAL_SYNC_HEIGHT                      21:16
+#define CRT_VERTICAL_SYNC_START                       10:0
+
+#define CRT_SIGNATURE_ANALYZER                        0x08021C
+#define CRT_SIGNATURE_ANALYZER_STATUS                 31:16
+#define CRT_SIGNATURE_ANALYZER_ENABLE                 3:3
+#define CRT_SIGNATURE_ANALYZER_ENABLE_DISABLE         0
+#define CRT_SIGNATURE_ANALYZER_ENABLE_ENABLE          1
+#define CRT_SIGNATURE_ANALYZER_RESET                  2:2
+#define CRT_SIGNATURE_ANALYZER_RESET_NORMAL           0
+#define CRT_SIGNATURE_ANALYZER_RESET_RESET            1
+#define CRT_SIGNATURE_ANALYZER_SOURCE                 1:0
+#define CRT_SIGNATURE_ANALYZER_SOURCE_RED             0
+#define CRT_SIGNATURE_ANALYZER_SOURCE_GREEN           1
+#define CRT_SIGNATURE_ANALYZER_SOURCE_BLUE            2
+
+#define CRT_CURRENT_LINE                              0x080220
+#define CRT_CURRENT_LINE_LINE                         10:0
+
+#define CRT_MONITOR_DETECT                            0x080224
+#define CRT_MONITOR_DETECT_VALUE                      25:25
+#define CRT_MONITOR_DETECT_VALUE_DISABLE              0
+#define CRT_MONITOR_DETECT_VALUE_ENABLE               1
+#define CRT_MONITOR_DETECT_ENABLE                     24:24
+#define CRT_MONITOR_DETECT_ENABLE_DISABLE             0
+#define CRT_MONITOR_DETECT_ENABLE_ENABLE              1
+#define CRT_MONITOR_DETECT_RED                        23:16
+#define CRT_MONITOR_DETECT_GREEN                      15:8
+#define CRT_MONITOR_DETECT_BLUE                       7:0
+
+#define CRT_SCALE                                     0x080228
+#define CRT_SCALE_VERTICAL_MODE                       31:31
+#define CRT_SCALE_VERTICAL_MODE_EXPAND                0
+#define CRT_SCALE_VERTICAL_MODE_SHRINK                1
+#define CRT_SCALE_VERTICAL_SCALE                      27:16
+#define CRT_SCALE_HORIZONTAL_MODE                     15:15
+#define CRT_SCALE_HORIZONTAL_MODE_EXPAND              0
+#define CRT_SCALE_HORIZONTAL_MODE_SHRINK              1
+#define CRT_SCALE_HORIZONTAL_SCALE                    11:0
+
+/* CRT Cursor Control */
+
+#define CRT_HWC_ADDRESS                               0x080230
+#define CRT_HWC_ADDRESS_ENABLE                        31:31
+#define CRT_HWC_ADDRESS_ENABLE_DISABLE                0
+#define CRT_HWC_ADDRESS_ENABLE_ENABLE                 1
+#define CRT_HWC_ADDRESS_EXT                           27:27
+#define CRT_HWC_ADDRESS_EXT_LOCAL                     0
+#define CRT_HWC_ADDRESS_EXT_EXTERNAL                  1
+#define CRT_HWC_ADDRESS_ADDRESS                       25:0
+
+#define CRT_HWC_LOCATION                              0x080234
+#define CRT_HWC_LOCATION_TOP                          27:27
+#define CRT_HWC_LOCATION_TOP_INSIDE                   0
+#define CRT_HWC_LOCATION_TOP_OUTSIDE                  1
+#define CRT_HWC_LOCATION_Y                            26:16
+#define CRT_HWC_LOCATION_LEFT                         11:11
+#define CRT_HWC_LOCATION_LEFT_INSIDE                  0
+#define CRT_HWC_LOCATION_LEFT_OUTSIDE                 1
+#define CRT_HWC_LOCATION_X                            10:0
+
+#define CRT_HWC_COLOR_12                              0x080238
+#define CRT_HWC_COLOR_12_2_RGB565                     31:16
+#define CRT_HWC_COLOR_12_1_RGB565                     15:0
+
+#define CRT_HWC_COLOR_3                               0x08023C
+#define CRT_HWC_COLOR_3_RGB565                        15:0
+
+/* Old Definitions +++. Need to be removed if no application use it. */
+#if 0
+    #define CRT_HWC_COLOR_01                          0x080238
+    #define CRT_HWC_COLOR_01_1_RED                    31:27
+    #define CRT_HWC_COLOR_01_1_GREEN                  26:21
+    #define CRT_HWC_COLOR_01_1_BLUE                   20:16
+    #define CRT_HWC_COLOR_01_0_RED                    15:11
+    #define CRT_HWC_COLOR_01_0_GREEN                  10:5
+    #define CRT_HWC_COLOR_01_0_BLUE                   4:0
+
+    #define CRT_HWC_COLOR_2                           0x08023C
+    #define CRT_HWC_COLOR_2_RED                       15:11
+    #define CRT_HWC_COLOR_2_GREEN                     10:5
+    #define CRT_HWC_COLOR_2_BLUE                      4:0
+#endif
+/* Old Definitions --- */
+
+/* This vertical expansion below start at 0x080240 ~ 0x080264 */
+#define CRT_VERTICAL_EXPANSION                        0x080240
+#ifndef VALIDATION_CHIP
+    #define CRT_VERTICAL_CENTERING_VALUE              31:24
+#endif
+#define CRT_VERTICAL_EXPANSION_COMPARE_VALUE          23:16
+#define CRT_VERTICAL_EXPANSION_LINE_BUFFER            15:12
+#define CRT_VERTICAL_EXPANSION_SCALE_FACTOR           11:0
+
+/* This horizontal expansion below start at 0x080268 ~ 0x08027C */
+#define CRT_HORIZONTAL_EXPANSION                      0x080268
+#ifndef VALIDATION_CHIP
+    #define CRT_HORIZONTAL_CENTERING_VALUE            31:24
+#endif
+#define CRT_HORIZONTAL_EXPANSION_COMPARE_VALUE        23:16
+#define CRT_HORIZONTAL_EXPANSION_SCALE_FACTOR         11:0
+
+#ifndef VALIDATION_CHIP
+    /* Auto Centering */
+    #define CRT_AUTO_CENTERING_TL                     0x080280
+    #define CRT_AUTO_CENTERING_TL_TOP                 26:16
+    #define CRT_AUTO_CENTERING_TL_LEFT                10:0
+
+    #define CRT_AUTO_CENTERING_BR                     0x080284
+    #define CRT_AUTO_CENTERING_BR_BOTTOM              26:16
+    #define CRT_AUTO_CENTERING_BR_RIGHT               10:0
+#endif
+
+/* sm750le new register to control panel output */
+#define DISPLAY_CONTROL_750LE  0x80288
+/* Palette RAM */
+
+/* Panel Pallete register starts at 0x080400 ~ 0x0807FC */
+#define PANEL_PALETTE_RAM                             0x080400
+
+/* Panel Pallete register starts at 0x080C00 ~ 0x080FFC */
+#define CRT_PALETTE_RAM                               0x080C00
+
+/* 2D registers
+ * move their defination into general lynx_accel.h file
+ * because all smi graphic chip share the same drawing engine
+ * register format */
+#if 0
+#define DE_SOURCE                                       0x100000
+#define DE_SOURCE_WRAP                                  31:31
+#define DE_SOURCE_WRAP_DISABLE                          0
+#define DE_SOURCE_WRAP_ENABLE                           1
+
+/*
+ * The following definitions are used in different setting
+ */
+
+/* Use these definitions in XY addressing mode or linear addressing mode. */
+#define DE_SOURCE_X_K1                                  27:16
+#define DE_SOURCE_Y_K2                                  11:0
+
+/* Use this definition in host write mode for mono. The Y_K2 is not used
+   in host write mode. */
+#define DE_SOURCE_X_K1_MONO                             20:16
+
+/* Use these definitions in Bresenham line drawing mode. */
+#define DE_SOURCE_X_K1_LINE                             29:16
+#define DE_SOURCE_Y_K2_LINE                             13:0
+
+#define DE_DESTINATION                                  0x100004
+#define DE_DESTINATION_WRAP                             31:31
+#define DE_DESTINATION_WRAP_DISABLE                     0
+#define DE_DESTINATION_WRAP_ENABLE                      1
+#if 1
+    #define DE_DESTINATION_X                            27:16
+    #define DE_DESTINATION_Y                            11:0
+#else
+    #define DE_DESTINATION_X                            28:16
+    #define DE_DESTINATION_Y                            15:0
+#endif
+
+#define DE_DIMENSION                                    0x100008
+#define DE_DIMENSION_X                                  28:16
+#define DE_DIMENSION_Y_ET                               15:0
+
+#define DE_CONTROL                                      0x10000C
+#define DE_CONTROL_STATUS                               31:31
+#define DE_CONTROL_STATUS_STOP                          0
+#define DE_CONTROL_STATUS_START                         1
+#define DE_CONTROL_PATTERN                              30:30
+#define DE_CONTROL_PATTERN_MONO                         0
+#define DE_CONTROL_PATTERN_COLOR                        1
+#define DE_CONTROL_UPDATE_DESTINATION_X                 29:29
+#define DE_CONTROL_UPDATE_DESTINATION_X_DISABLE         0
+#define DE_CONTROL_UPDATE_DESTINATION_X_ENABLE          1
+#define DE_CONTROL_QUICK_START                          28:28
+#define DE_CONTROL_QUICK_START_DISABLE                  0
+#define DE_CONTROL_QUICK_START_ENABLE                   1
+#define DE_CONTROL_DIRECTION                            27:27
+#define DE_CONTROL_DIRECTION_LEFT_TO_RIGHT              0
+#define DE_CONTROL_DIRECTION_RIGHT_TO_LEFT              1
+#define DE_CONTROL_MAJOR                                26:26
+#define DE_CONTROL_MAJOR_X                              0
+#define DE_CONTROL_MAJOR_Y                              1
+#define DE_CONTROL_STEP_X                               25:25
+#define DE_CONTROL_STEP_X_POSITIVE                      0
+#define DE_CONTROL_STEP_X_NEGATIVE                      1
+#define DE_CONTROL_STEP_Y                               24:24
+#define DE_CONTROL_STEP_Y_POSITIVE                      0
+#define DE_CONTROL_STEP_Y_NEGATIVE                      1
+#define DE_CONTROL_STRETCH                              23:23
+#define DE_CONTROL_STRETCH_DISABLE                      0
+#define DE_CONTROL_STRETCH_ENABLE                       1
+#define DE_CONTROL_HOST                                 22:22
+#define DE_CONTROL_HOST_COLOR                           0
+#define DE_CONTROL_HOST_MONO                            1
+#define DE_CONTROL_LAST_PIXEL                           21:21
+#define DE_CONTROL_LAST_PIXEL_OFF                       0
+#define DE_CONTROL_LAST_PIXEL_ON                        1
+#define DE_CONTROL_COMMAND                              20:16
+#define DE_CONTROL_COMMAND_BITBLT                       0
+#define DE_CONTROL_COMMAND_RECTANGLE_FILL               1
+#define DE_CONTROL_COMMAND_DE_TILE                      2
+#define DE_CONTROL_COMMAND_TRAPEZOID_FILL               3
+#define DE_CONTROL_COMMAND_ALPHA_BLEND                  4
+#define DE_CONTROL_COMMAND_RLE_STRIP                    5
+#define DE_CONTROL_COMMAND_SHORT_STROKE                 6
+#define DE_CONTROL_COMMAND_LINE_DRAW                    7
+#define DE_CONTROL_COMMAND_HOST_WRITE                   8
+#define DE_CONTROL_COMMAND_HOST_READ                    9
+#define DE_CONTROL_COMMAND_HOST_WRITE_BOTTOM_UP         10
+#define DE_CONTROL_COMMAND_ROTATE                       11
+#define DE_CONTROL_COMMAND_FONT                         12
+#define DE_CONTROL_COMMAND_TEXTURE_LOAD                 15
+#define DE_CONTROL_ROP_SELECT                           15:15
+#define DE_CONTROL_ROP_SELECT_ROP3                      0
+#define DE_CONTROL_ROP_SELECT_ROP2                      1
+#define DE_CONTROL_ROP2_SOURCE                          14:14
+#define DE_CONTROL_ROP2_SOURCE_BITMAP                   0
+#define DE_CONTROL_ROP2_SOURCE_PATTERN                  1
+#define DE_CONTROL_MONO_DATA                            13:12
+#define DE_CONTROL_MONO_DATA_NOT_PACKED                 0
+#define DE_CONTROL_MONO_DATA_8_PACKED                   1
+#define DE_CONTROL_MONO_DATA_16_PACKED                  2
+#define DE_CONTROL_MONO_DATA_32_PACKED                  3
+#define DE_CONTROL_REPEAT_ROTATE                        11:11
+#define DE_CONTROL_REPEAT_ROTATE_DISABLE                0
+#define DE_CONTROL_REPEAT_ROTATE_ENABLE                 1
+#define DE_CONTROL_TRANSPARENCY_MATCH                   10:10
+#define DE_CONTROL_TRANSPARENCY_MATCH_OPAQUE            0
+#define DE_CONTROL_TRANSPARENCY_MATCH_TRANSPARENT       1
+#define DE_CONTROL_TRANSPARENCY_SELECT                  9:9
+#define DE_CONTROL_TRANSPARENCY_SELECT_SOURCE           0
+#define DE_CONTROL_TRANSPARENCY_SELECT_DESTINATION      1
+#define DE_CONTROL_TRANSPARENCY                         8:8
+#define DE_CONTROL_TRANSPARENCY_DISABLE                 0
+#define DE_CONTROL_TRANSPARENCY_ENABLE                  1
+#define DE_CONTROL_ROP                                  7:0
+
+/* Pseudo fields. */
+
+#define DE_CONTROL_SHORT_STROKE_DIR                     27:24
+#define DE_CONTROL_SHORT_STROKE_DIR_225                 0
+#define DE_CONTROL_SHORT_STROKE_DIR_135                 1
+#define DE_CONTROL_SHORT_STROKE_DIR_315                 2
+#define DE_CONTROL_SHORT_STROKE_DIR_45                  3
+#define DE_CONTROL_SHORT_STROKE_DIR_270                 4
+#define DE_CONTROL_SHORT_STROKE_DIR_90                  5
+#define DE_CONTROL_SHORT_STROKE_DIR_180                 8
+#define DE_CONTROL_SHORT_STROKE_DIR_0                   10
+#define DE_CONTROL_ROTATION                             25:24
+#define DE_CONTROL_ROTATION_0                           0
+#define DE_CONTROL_ROTATION_270                         1
+#define DE_CONTROL_ROTATION_90                          2
+#define DE_CONTROL_ROTATION_180                         3
+
+#define DE_PITCH                                        0x100010
+#define DE_PITCH_DESTINATION                            28:16
+#define DE_PITCH_SOURCE                                 12:0
+
+#define DE_FOREGROUND                                   0x100014
+#define DE_FOREGROUND_COLOR                             31:0
+
+#define DE_BACKGROUND                                   0x100018
+#define DE_BACKGROUND_COLOR                             31:0
+
+#define DE_STRETCH_FORMAT                               0x10001C
+#define DE_STRETCH_FORMAT_PATTERN_XY                    30:30
+#define DE_STRETCH_FORMAT_PATTERN_XY_NORMAL             0
+#define DE_STRETCH_FORMAT_PATTERN_XY_OVERWRITE          1
+#define DE_STRETCH_FORMAT_PATTERN_Y                     29:27
+#define DE_STRETCH_FORMAT_PATTERN_X                     25:23
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT                  21:20
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT_8                0
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT_16               1
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT_32               2
+#define DE_STRETCH_FORMAT_ADDRESSING                    19:16
+#define DE_STRETCH_FORMAT_ADDRESSING_XY                 0
+#define DE_STRETCH_FORMAT_ADDRESSING_LINEAR             15
+#define DE_STRETCH_FORMAT_SOURCE_HEIGHT                 11:0
+
+#define DE_COLOR_COMPARE                                0x100020
+#define DE_COLOR_COMPARE_COLOR                          23:0
+
+#define DE_COLOR_COMPARE_MASK                           0x100024
+#define DE_COLOR_COMPARE_MASK_MASKS                     23:0
+
+#define DE_MASKS                                        0x100028
+#define DE_MASKS_BYTE_MASK                              31:16
+#define DE_MASKS_BIT_MASK                               15:0
+
+#define DE_CLIP_TL                                      0x10002C
+#define DE_CLIP_TL_TOP                                  31:16
+#define DE_CLIP_TL_STATUS                               13:13
+#define DE_CLIP_TL_STATUS_DISABLE                       0
+#define DE_CLIP_TL_STATUS_ENABLE                        1
+#define DE_CLIP_TL_INHIBIT                              12:12
+#define DE_CLIP_TL_INHIBIT_OUTSIDE                      0
+#define DE_CLIP_TL_INHIBIT_INSIDE                       1
+#define DE_CLIP_TL_LEFT                                 11:0
+
+#define DE_CLIP_BR                                      0x100030
+#define DE_CLIP_BR_BOTTOM                               31:16
+#define DE_CLIP_BR_RIGHT                                12:0
+
+#define DE_MONO_PATTERN_LOW                             0x100034
+#define DE_MONO_PATTERN_LOW_PATTERN                     31:0
+
+#define DE_MONO_PATTERN_HIGH                            0x100038
+#define DE_MONO_PATTERN_HIGH_PATTERN                    31:0
+
+#define DE_WINDOW_WIDTH                                 0x10003C
+#define DE_WINDOW_WIDTH_DESTINATION                     28:16
+#define DE_WINDOW_WIDTH_SOURCE                          12:0
+
+#define DE_WINDOW_SOURCE_BASE                           0x100040
+#define DE_WINDOW_SOURCE_BASE_EXT                       27:27
+#define DE_WINDOW_SOURCE_BASE_EXT_LOCAL                 0
+#define DE_WINDOW_SOURCE_BASE_EXT_EXTERNAL              1
+#define DE_WINDOW_SOURCE_BASE_CS                        26:26
+#define DE_WINDOW_SOURCE_BASE_CS_0                      0
+#define DE_WINDOW_SOURCE_BASE_CS_1                      1
+#define DE_WINDOW_SOURCE_BASE_ADDRESS                   25:0
+
+#define DE_WINDOW_DESTINATION_BASE                      0x100044
+#define DE_WINDOW_DESTINATION_BASE_EXT                  27:27
+#define DE_WINDOW_DESTINATION_BASE_EXT_LOCAL            0
+#define DE_WINDOW_DESTINATION_BASE_EXT_EXTERNAL         1
+#define DE_WINDOW_DESTINATION_BASE_CS                   26:26
+#define DE_WINDOW_DESTINATION_BASE_CS_0                 0
+#define DE_WINDOW_DESTINATION_BASE_CS_1                 1
+#define DE_WINDOW_DESTINATION_BASE_ADDRESS              25:0
+
+#define DE_ALPHA                                        0x100048
+#define DE_ALPHA_VALUE                                  7:0
+
+#define DE_WRAP                                         0x10004C
+#define DE_WRAP_X                                       31:16
+#define DE_WRAP_Y                                       15:0
+
+#define DE_STATUS                                       0x100050
+#define DE_STATUS_CSC                                   1:1
+#define DE_STATUS_CSC_CLEAR                             0
+#define DE_STATUS_CSC_NOT_ACTIVE                        0
+#define DE_STATUS_CSC_ACTIVE                            1
+#define DE_STATUS_2D                                    0:0
+#define DE_STATUS_2D_CLEAR                              0
+#define DE_STATUS_2D_NOT_ACTIVE                         0
+#define DE_STATUS_2D_ACTIVE                             1
+#endif
+/* Color Space Conversion registers. */
+
+#define CSC_Y_SOURCE_BASE                               0x1000C8
+#define CSC_Y_SOURCE_BASE_EXT                           27:27
+#define CSC_Y_SOURCE_BASE_EXT_LOCAL                     0
+#define CSC_Y_SOURCE_BASE_EXT_EXTERNAL                  1
+#define CSC_Y_SOURCE_BASE_CS                            26:26
+#define CSC_Y_SOURCE_BASE_CS_0                          0
+#define CSC_Y_SOURCE_BASE_CS_1                          1
+#define CSC_Y_SOURCE_BASE_ADDRESS                       25:0
+
+#define CSC_CONSTANTS                                   0x1000CC
+#define CSC_CONSTANTS_Y                                 31:24
+#define CSC_CONSTANTS_R                                 23:16
+#define CSC_CONSTANTS_G                                 15:8
+#define CSC_CONSTANTS_B                                 7:0
+
+#define CSC_Y_SOURCE_X                                  0x1000D0
+#define CSC_Y_SOURCE_X_INTEGER                          26:16
+#define CSC_Y_SOURCE_X_FRACTION                         15:3
+
+#define CSC_Y_SOURCE_Y                                  0x1000D4
+#define CSC_Y_SOURCE_Y_INTEGER                          27:16
+#define CSC_Y_SOURCE_Y_FRACTION                         15:3
+
+#define CSC_U_SOURCE_BASE                               0x1000D8
+#define CSC_U_SOURCE_BASE_EXT                           27:27
+#define CSC_U_SOURCE_BASE_EXT_LOCAL                     0
+#define CSC_U_SOURCE_BASE_EXT_EXTERNAL                  1
+#define CSC_U_SOURCE_BASE_CS                            26:26
+#define CSC_U_SOURCE_BASE_CS_0                          0
+#define CSC_U_SOURCE_BASE_CS_1                          1
+#define CSC_U_SOURCE_BASE_ADDRESS                       25:0
+
+#define CSC_V_SOURCE_BASE                               0x1000DC
+#define CSC_V_SOURCE_BASE_EXT                           27:27
+#define CSC_V_SOURCE_BASE_EXT_LOCAL                     0
+#define CSC_V_SOURCE_BASE_EXT_EXTERNAL                  1
+#define CSC_V_SOURCE_BASE_CS                            26:26
+#define CSC_V_SOURCE_BASE_CS_0                          0
+#define CSC_V_SOURCE_BASE_CS_1                          1
+#define CSC_V_SOURCE_BASE_ADDRESS                       25:0
+
+#define CSC_SOURCE_DIMENSION                            0x1000E0
+#define CSC_SOURCE_DIMENSION_X                          31:16
+#define CSC_SOURCE_DIMENSION_Y                          15:0
+
+#define CSC_SOURCE_PITCH                                0x1000E4
+#define CSC_SOURCE_PITCH_Y                              31:16
+#define CSC_SOURCE_PITCH_UV                             15:0
+
+#define CSC_DESTINATION                                 0x1000E8
+#define CSC_DESTINATION_WRAP                            31:31
+#define CSC_DESTINATION_WRAP_DISABLE                    0
+#define CSC_DESTINATION_WRAP_ENABLE                     1
+#define CSC_DESTINATION_X                               27:16
+#define CSC_DESTINATION_Y                               11:0
+
+#define CSC_DESTINATION_DIMENSION                       0x1000EC
+#define CSC_DESTINATION_DIMENSION_X                     31:16
+#define CSC_DESTINATION_DIMENSION_Y                     15:0
+
+#define CSC_DESTINATION_PITCH                           0x1000F0
+#define CSC_DESTINATION_PITCH_X                         31:16
+#define CSC_DESTINATION_PITCH_Y                         15:0
+
+#define CSC_SCALE_FACTOR                                0x1000F4
+#define CSC_SCALE_FACTOR_HORIZONTAL                     31:16
+#define CSC_SCALE_FACTOR_VERTICAL                       15:0
+
+#define CSC_DESTINATION_BASE                            0x1000F8
+#define CSC_DESTINATION_BASE_EXT                        27:27
+#define CSC_DESTINATION_BASE_EXT_LOCAL                  0
+#define CSC_DESTINATION_BASE_EXT_EXTERNAL               1
+#define CSC_DESTINATION_BASE_CS                         26:26
+#define CSC_DESTINATION_BASE_CS_0                       0
+#define CSC_DESTINATION_BASE_CS_1                       1
+#define CSC_DESTINATION_BASE_ADDRESS                    25:0
+
+#define CSC_CONTROL                                     0x1000FC
+#define CSC_CONTROL_STATUS                              31:31
+#define CSC_CONTROL_STATUS_STOP                         0
+#define CSC_CONTROL_STATUS_START                        1
+#define CSC_CONTROL_SOURCE_FORMAT                       30:28
+#define CSC_CONTROL_SOURCE_FORMAT_YUV422                0
+#define CSC_CONTROL_SOURCE_FORMAT_YUV420I               1
+#define CSC_CONTROL_SOURCE_FORMAT_YUV420                2
+#define CSC_CONTROL_SOURCE_FORMAT_YVU9                  3
+#define CSC_CONTROL_SOURCE_FORMAT_IYU1                  4
+#define CSC_CONTROL_SOURCE_FORMAT_IYU2                  5
+#define CSC_CONTROL_SOURCE_FORMAT_RGB565                6
+#define CSC_CONTROL_SOURCE_FORMAT_RGB8888               7
+#define CSC_CONTROL_DESTINATION_FORMAT                  27:26
+#define CSC_CONTROL_DESTINATION_FORMAT_RGB565           0
+#define CSC_CONTROL_DESTINATION_FORMAT_RGB8888          1
+#define CSC_CONTROL_HORIZONTAL_FILTER                   25:25
+#define CSC_CONTROL_HORIZONTAL_FILTER_DISABLE           0
+#define CSC_CONTROL_HORIZONTAL_FILTER_ENABLE            1
+#define CSC_CONTROL_VERTICAL_FILTER                     24:24
+#define CSC_CONTROL_VERTICAL_FILTER_DISABLE             0
+#define CSC_CONTROL_VERTICAL_FILTER_ENABLE              1
+#define CSC_CONTROL_BYTE_ORDER                          23:23
+#define CSC_CONTROL_BYTE_ORDER_YUYV                     0
+#define CSC_CONTROL_BYTE_ORDER_UYVY                     1
+
+#define DE_DATA_PORT                                    0x110000
+
+#define I2C_BYTE_COUNT                                  0x010040
+#define I2C_BYTE_COUNT_COUNT                            3:0
+
+#define I2C_CTRL                                        0x010041
+#define I2C_CTRL_INT                                    4:4
+#define I2C_CTRL_INT_DISABLE                            0
+#define I2C_CTRL_INT_ENABLE                             1
+#define I2C_CTRL_DIR                                    3:3
+#define I2C_CTRL_DIR_WR                                 0
+#define I2C_CTRL_DIR_RD                                 1
+#define I2C_CTRL_CTRL                                   2:2
+#define I2C_CTRL_CTRL_STOP                              0
+#define I2C_CTRL_CTRL_START                             1
+#define I2C_CTRL_MODE                                   1:1
+#define I2C_CTRL_MODE_STANDARD                          0
+#define I2C_CTRL_MODE_FAST                              1
+#define I2C_CTRL_EN                                     0:0
+#define I2C_CTRL_EN_DISABLE                             0
+#define I2C_CTRL_EN_ENABLE                              1
+
+#define I2C_STATUS                                      0x010042
+#define I2C_STATUS_TX                                   3:3
+#define I2C_STATUS_TX_PROGRESS                          0
+#define I2C_STATUS_TX_COMPLETED                         1
+#define I2C_TX_DONE                                     0x08
+#define I2C_STATUS_ERR                                  2:2
+#define I2C_STATUS_ERR_NORMAL                           0
+#define I2C_STATUS_ERR_ERROR                            1
+#define I2C_STATUS_ERR_CLEAR                            0
+#define I2C_STATUS_ACK                                  1:1
+#define I2C_STATUS_ACK_RECEIVED                         0
+#define I2C_STATUS_ACK_NOT                              1
+#define I2C_STATUS_BSY                                  0:0
+#define I2C_STATUS_BSY_IDLE                             0
+#define I2C_STATUS_BSY_BUSY                             1
+
+#define I2C_RESET                                       0x010042
+#define I2C_RESET_BUS_ERROR                             2:2
+#define I2C_RESET_BUS_ERROR_CLEAR                       0
+
+#define I2C_SLAVE_ADDRESS                               0x010043
+#define I2C_SLAVE_ADDRESS_ADDRESS                       7:1
+#define I2C_SLAVE_ADDRESS_RW                            0:0
+#define I2C_SLAVE_ADDRESS_RW_W                          0
+#define I2C_SLAVE_ADDRESS_RW_R                          1
+
+#define I2C_DATA0                                       0x010044
+#define I2C_DATA1                                       0x010045
+#define I2C_DATA2                                       0x010046
+#define I2C_DATA3                                       0x010047
+#define I2C_DATA4                                       0x010048
+#define I2C_DATA5                                       0x010049
+#define I2C_DATA6                                       0x01004A
+#define I2C_DATA7                                       0x01004B
+#define I2C_DATA8                                       0x01004C
+#define I2C_DATA9                                       0x01004D
+#define I2C_DATA10                                      0x01004E
+#define I2C_DATA11                                      0x01004F
+#define I2C_DATA12                                      0x010050
+#define I2C_DATA13                                      0x010051
+#define I2C_DATA14                                      0x010052
+#define I2C_DATA15                                      0x010053
+
+
+#define ZV0_CAPTURE_CTRL                                0x090000
+#define ZV0_CAPTURE_CTRL_FIELD_INPUT                    27:27
+#define ZV0_CAPTURE_CTRL_FIELD_INPUT_EVEN_FIELD         0
+#define ZV0_CAPTURE_CTRL_FIELD_INPUT_ODD_FIELD          1
+#define ZV0_CAPTURE_CTRL_SCAN                           26:26
+#define ZV0_CAPTURE_CTRL_SCAN_PROGRESSIVE               0
+#define ZV0_CAPTURE_CTRL_SCAN_INTERLACE                 1
+#define ZV0_CAPTURE_CTRL_CURRENT_BUFFER                 25:25
+#define ZV0_CAPTURE_CTRL_CURRENT_BUFFER_0               0
+#define ZV0_CAPTURE_CTRL_CURRENT_BUFFER_1               1
+#define ZV0_CAPTURE_CTRL_VERTICAL_SYNC                  24:24
+#define ZV0_CAPTURE_CTRL_VERTICAL_SYNC_INACTIVE         0
+#define ZV0_CAPTURE_CTRL_VERTICAL_SYNC_ACTIVE           1
+#define ZV0_CAPTURE_CTRL_ADJ                            19:19
+#define ZV0_CAPTURE_CTRL_ADJ_NORMAL                     0
+#define ZV0_CAPTURE_CTRL_ADJ_DELAY                      1
+#define ZV0_CAPTURE_CTRL_HA                             18:18
+#define ZV0_CAPTURE_CTRL_HA_DISABLE                     0
+#define ZV0_CAPTURE_CTRL_HA_ENABLE                      1
+#define ZV0_CAPTURE_CTRL_VSK                            17:17
+#define ZV0_CAPTURE_CTRL_VSK_DISABLE                    0
+#define ZV0_CAPTURE_CTRL_VSK_ENABLE                     1
+#define ZV0_CAPTURE_CTRL_HSK                            16:16
+#define ZV0_CAPTURE_CTRL_HSK_DISABLE                    0
+#define ZV0_CAPTURE_CTRL_HSK_ENABLE                     1
+#define ZV0_CAPTURE_CTRL_FD                             15:15
+#define ZV0_CAPTURE_CTRL_FD_RISING                      0
+#define ZV0_CAPTURE_CTRL_FD_FALLING                     1
+#define ZV0_CAPTURE_CTRL_VP                             14:14
+#define ZV0_CAPTURE_CTRL_VP_HIGH                        0
+#define ZV0_CAPTURE_CTRL_VP_LOW                         1
+#define ZV0_CAPTURE_CTRL_HP                             13:13
+#define ZV0_CAPTURE_CTRL_HP_HIGH                        0
+#define ZV0_CAPTURE_CTRL_HP_LOW                         1
+#define ZV0_CAPTURE_CTRL_CP                             12:12
+#define ZV0_CAPTURE_CTRL_CP_HIGH                        0
+#define ZV0_CAPTURE_CTRL_CP_LOW                         1
+#define ZV0_CAPTURE_CTRL_UVS                            11:11
+#define ZV0_CAPTURE_CTRL_UVS_DISABLE                    0
+#define ZV0_CAPTURE_CTRL_UVS_ENABLE                     1
+#define ZV0_CAPTURE_CTRL_BS                             10:10
+#define ZV0_CAPTURE_CTRL_BS_DISABLE                     0
+#define ZV0_CAPTURE_CTRL_BS_ENABLE                      1
+#define ZV0_CAPTURE_CTRL_CS                             9:9
+#define ZV0_CAPTURE_CTRL_CS_16                          0
+#define ZV0_CAPTURE_CTRL_CS_8                           1
+#define ZV0_CAPTURE_CTRL_CF                             8:8
+#define ZV0_CAPTURE_CTRL_CF_YUV                         0
+#define ZV0_CAPTURE_CTRL_CF_RGB                         1
+#define ZV0_CAPTURE_CTRL_FS                             7:7
+#define ZV0_CAPTURE_CTRL_FS_DISABLE                     0
+#define ZV0_CAPTURE_CTRL_FS_ENABLE                      1
+#define ZV0_CAPTURE_CTRL_WEAVE                          6:6
+#define ZV0_CAPTURE_CTRL_WEAVE_DISABLE                  0
+#define ZV0_CAPTURE_CTRL_WEAVE_ENABLE                   1
+#define ZV0_CAPTURE_CTRL_BOB                            5:5
+#define ZV0_CAPTURE_CTRL_BOB_DISABLE                    0
+#define ZV0_CAPTURE_CTRL_BOB_ENABLE                     1
+#define ZV0_CAPTURE_CTRL_DB                             4:4
+#define ZV0_CAPTURE_CTRL_DB_DISABLE                     0
+#define ZV0_CAPTURE_CTRL_DB_ENABLE                      1
+#define ZV0_CAPTURE_CTRL_CC                             3:3
+#define ZV0_CAPTURE_CTRL_CC_CONTINUE                    0
+#define ZV0_CAPTURE_CTRL_CC_CONDITION                   1
+#define ZV0_CAPTURE_CTRL_RGB                            2:2
+#define ZV0_CAPTURE_CTRL_RGB_DISABLE                    0
+#define ZV0_CAPTURE_CTRL_RGB_ENABLE                     1
+#define ZV0_CAPTURE_CTRL_656                            1:1
+#define ZV0_CAPTURE_CTRL_656_DISABLE                    0
+#define ZV0_CAPTURE_CTRL_656_ENABLE                     1
+#define ZV0_CAPTURE_CTRL_CAP                            0:0
+#define ZV0_CAPTURE_CTRL_CAP_DISABLE                    0
+#define ZV0_CAPTURE_CTRL_CAP_ENABLE                     1
+
+#define ZV0_CAPTURE_CLIP                                0x090004
+#define ZV0_CAPTURE_CLIP_YCLIP_EVEN_FIELD                25:16
+#define ZV0_CAPTURE_CLIP_YCLIP                          25:16
+#define ZV0_CAPTURE_CLIP_XCLIP                          9:0
+
+#define ZV0_CAPTURE_SIZE                                0x090008
+#define ZV0_CAPTURE_SIZE_HEIGHT                         26:16
+#define ZV0_CAPTURE_SIZE_WIDTH                          10:0
+
+#define ZV0_CAPTURE_BUF0_ADDRESS                        0x09000C
+#define ZV0_CAPTURE_BUF0_ADDRESS_STATUS                 31:31
+#define ZV0_CAPTURE_BUF0_ADDRESS_STATUS_CURRENT         0
+#define ZV0_CAPTURE_BUF0_ADDRESS_STATUS_PENDING         1
+#define ZV0_CAPTURE_BUF0_ADDRESS_EXT                    27:27
+#define ZV0_CAPTURE_BUF0_ADDRESS_EXT_LOCAL              0
+#define ZV0_CAPTURE_BUF0_ADDRESS_EXT_EXTERNAL           1
+#define ZV0_CAPTURE_BUF0_ADDRESS_CS                     26:26
+#define ZV0_CAPTURE_BUF0_ADDRESS_CS_0                   0
+#define ZV0_CAPTURE_BUF0_ADDRESS_CS_1                   1
+#define ZV0_CAPTURE_BUF0_ADDRESS_ADDRESS                25:0
+
+#define ZV0_CAPTURE_BUF1_ADDRESS                        0x090010
+#define ZV0_CAPTURE_BUF1_ADDRESS_STATUS                 31:31
+#define ZV0_CAPTURE_BUF1_ADDRESS_STATUS_CURRENT         0
+#define ZV0_CAPTURE_BUF1_ADDRESS_STATUS_PENDING         1
+#define ZV0_CAPTURE_BUF1_ADDRESS_EXT                    27:27
+#define ZV0_CAPTURE_BUF1_ADDRESS_EXT_LOCAL              0
+#define ZV0_CAPTURE_BUF1_ADDRESS_EXT_EXTERNAL           1
+#define ZV0_CAPTURE_BUF1_ADDRESS_CS                     26:26
+#define ZV0_CAPTURE_BUF1_ADDRESS_CS_0                   0
+#define ZV0_CAPTURE_BUF1_ADDRESS_CS_1                   1
+#define ZV0_CAPTURE_BUF1_ADDRESS_ADDRESS                25:0
+
+#define ZV0_CAPTURE_BUF_OFFSET                          0x090014
+#ifndef VALIDATION_CHIP
+    #define ZV0_CAPTURE_BUF_OFFSET_YCLIP_ODD_FIELD      25:16
+#endif
+#define ZV0_CAPTURE_BUF_OFFSET_OFFSET                   15:0
+
+#define ZV0_CAPTURE_FIFO_CTRL                           0x090018
+#define ZV0_CAPTURE_FIFO_CTRL_FIFO                      2:0
+#define ZV0_CAPTURE_FIFO_CTRL_FIFO_0                    0
+#define ZV0_CAPTURE_FIFO_CTRL_FIFO_1                    1
+#define ZV0_CAPTURE_FIFO_CTRL_FIFO_2                    2
+#define ZV0_CAPTURE_FIFO_CTRL_FIFO_3                    3
+#define ZV0_CAPTURE_FIFO_CTRL_FIFO_4                    4
+#define ZV0_CAPTURE_FIFO_CTRL_FIFO_5                    5
+#define ZV0_CAPTURE_FIFO_CTRL_FIFO_6                    6
+#define ZV0_CAPTURE_FIFO_CTRL_FIFO_7                    7
+
+#define ZV0_CAPTURE_YRGB_CONST                          0x09001C
+#define ZV0_CAPTURE_YRGB_CONST_Y                        31:24
+#define ZV0_CAPTURE_YRGB_CONST_R                        23:16
+#define ZV0_CAPTURE_YRGB_CONST_G                        15:8
+#define ZV0_CAPTURE_YRGB_CONST_B                        7:0
+
+#define ZV0_CAPTURE_LINE_COMP                           0x090020
+#define ZV0_CAPTURE_LINE_COMP_LC                        10:0
+
+/* ZV1 */
+
+#define ZV1_CAPTURE_CTRL                                0x098000
+#define ZV1_CAPTURE_CTRL_FIELD_INPUT                    27:27
+#define ZV1_CAPTURE_CTRL_FIELD_INPUT_EVEN_FIELD         0
+#define ZV1_CAPTURE_CTRL_FIELD_INPUT_ODD_FIELD          0
+#define ZV1_CAPTURE_CTRL_SCAN                           26:26
+#define ZV1_CAPTURE_CTRL_SCAN_PROGRESSIVE               0
+#define ZV1_CAPTURE_CTRL_SCAN_INTERLACE                 1
+#define ZV1_CAPTURE_CTRL_CURRENT_BUFFER                 25:25
+#define ZV1_CAPTURE_CTRL_CURRENT_BUFFER_0               0
+#define ZV1_CAPTURE_CTRL_CURRENT_BUFFER_1               1
+#define ZV1_CAPTURE_CTRL_VERTICAL_SYNC                  24:24
+#define ZV1_CAPTURE_CTRL_VERTICAL_SYNC_INACTIVE         0
+#define ZV1_CAPTURE_CTRL_VERTICAL_SYNC_ACTIVE           1
+#define ZV1_CAPTURE_CTRL_PANEL                          20:20
+#define ZV1_CAPTURE_CTRL_PANEL_DISABLE                  0
+#define ZV1_CAPTURE_CTRL_PANEL_ENABLE                   1
+#define ZV1_CAPTURE_CTRL_ADJ                            19:19
+#define ZV1_CAPTURE_CTRL_ADJ_NORMAL                     0
+#define ZV1_CAPTURE_CTRL_ADJ_DELAY                      1
+#define ZV1_CAPTURE_CTRL_HA                             18:18
+#define ZV1_CAPTURE_CTRL_HA_DISABLE                     0
+#define ZV1_CAPTURE_CTRL_HA_ENABLE                      1
+#define ZV1_CAPTURE_CTRL_VSK                            17:17
+#define ZV1_CAPTURE_CTRL_VSK_DISABLE                    0
+#define ZV1_CAPTURE_CTRL_VSK_ENABLE                     1
+#define ZV1_CAPTURE_CTRL_HSK                            16:16
+#define ZV1_CAPTURE_CTRL_HSK_DISABLE                    0
+#define ZV1_CAPTURE_CTRL_HSK_ENABLE                     1
+#define ZV1_CAPTURE_CTRL_FD                             15:15
+#define ZV1_CAPTURE_CTRL_FD_RISING                      0
+#define ZV1_CAPTURE_CTRL_FD_FALLING                     1
+#define ZV1_CAPTURE_CTRL_VP                             14:14
+#define ZV1_CAPTURE_CTRL_VP_HIGH                        0
+#define ZV1_CAPTURE_CTRL_VP_LOW                         1
+#define ZV1_CAPTURE_CTRL_HP                             13:13
+#define ZV1_CAPTURE_CTRL_HP_HIGH                        0
+#define ZV1_CAPTURE_CTRL_HP_LOW                         1
+#define ZV1_CAPTURE_CTRL_CP                             12:12
+#define ZV1_CAPTURE_CTRL_CP_HIGH                        0
+#define ZV1_CAPTURE_CTRL_CP_LOW                         1
+#define ZV1_CAPTURE_CTRL_UVS                            11:11
+#define ZV1_CAPTURE_CTRL_UVS_DISABLE                    0
+#define ZV1_CAPTURE_CTRL_UVS_ENABLE                     1
+#define ZV1_CAPTURE_CTRL_BS                             10:10
+#define ZV1_CAPTURE_CTRL_BS_DISABLE                     0
+#define ZV1_CAPTURE_CTRL_BS_ENABLE                      1
+#define ZV1_CAPTURE_CTRL_CS                             9:9
+#define ZV1_CAPTURE_CTRL_CS_16                          0
+#define ZV1_CAPTURE_CTRL_CS_8                           1
+#define ZV1_CAPTURE_CTRL_CF                             8:8
+#define ZV1_CAPTURE_CTRL_CF_YUV                         0
+#define ZV1_CAPTURE_CTRL_CF_RGB                         1
+#define ZV1_CAPTURE_CTRL_FS                             7:7
+#define ZV1_CAPTURE_CTRL_FS_DISABLE                     0
+#define ZV1_CAPTURE_CTRL_FS_ENABLE                      1
+#define ZV1_CAPTURE_CTRL_WEAVE                          6:6
+#define ZV1_CAPTURE_CTRL_WEAVE_DISABLE                  0
+#define ZV1_CAPTURE_CTRL_WEAVE_ENABLE                   1
+#define ZV1_CAPTURE_CTRL_BOB                            5:5
+#define ZV1_CAPTURE_CTRL_BOB_DISABLE                    0
+#define ZV1_CAPTURE_CTRL_BOB_ENABLE                     1
+#define ZV1_CAPTURE_CTRL_DB                             4:4
+#define ZV1_CAPTURE_CTRL_DB_DISABLE                     0
+#define ZV1_CAPTURE_CTRL_DB_ENABLE                      1
+#define ZV1_CAPTURE_CTRL_CC                             3:3
+#define ZV1_CAPTURE_CTRL_CC_CONTINUE                    0
+#define ZV1_CAPTURE_CTRL_CC_CONDITION                   1
+#define ZV1_CAPTURE_CTRL_RGB                            2:2
+#define ZV1_CAPTURE_CTRL_RGB_DISABLE                    0
+#define ZV1_CAPTURE_CTRL_RGB_ENABLE                     1
+#define ZV1_CAPTURE_CTRL_656                            1:1
+#define ZV1_CAPTURE_CTRL_656_DISABLE                    0
+#define ZV1_CAPTURE_CTRL_656_ENABLE                     1
+#define ZV1_CAPTURE_CTRL_CAP                            0:0
+#define ZV1_CAPTURE_CTRL_CAP_DISABLE                    0
+#define ZV1_CAPTURE_CTRL_CAP_ENABLE                     1
+
+#define ZV1_CAPTURE_CLIP                                0x098004
+#define ZV1_CAPTURE_CLIP_YCLIP                          25:16
+#define ZV1_CAPTURE_CLIP_XCLIP                          9:0
+
+#define ZV1_CAPTURE_SIZE                                0x098008
+#define ZV1_CAPTURE_SIZE_HEIGHT                         26:16
+#define ZV1_CAPTURE_SIZE_WIDTH                          10:0
+
+#define ZV1_CAPTURE_BUF0_ADDRESS                        0x09800C
+#define ZV1_CAPTURE_BUF0_ADDRESS_STATUS                 31:31
+#define ZV1_CAPTURE_BUF0_ADDRESS_STATUS_CURRENT         0
+#define ZV1_CAPTURE_BUF0_ADDRESS_STATUS_PENDING         1
+#define ZV1_CAPTURE_BUF0_ADDRESS_EXT                    27:27
+#define ZV1_CAPTURE_BUF0_ADDRESS_EXT_LOCAL              0
+#define ZV1_CAPTURE_BUF0_ADDRESS_EXT_EXTERNAL           1
+#define ZV1_CAPTURE_BUF0_ADDRESS_CS                     26:26
+#define ZV1_CAPTURE_BUF0_ADDRESS_CS_0                   0
+#define ZV1_CAPTURE_BUF0_ADDRESS_CS_1                   1
+#define ZV1_CAPTURE_BUF0_ADDRESS_ADDRESS                25:0
+
+#define ZV1_CAPTURE_BUF1_ADDRESS                        0x098010
+#define ZV1_CAPTURE_BUF1_ADDRESS_STATUS                 31:31
+#define ZV1_CAPTURE_BUF1_ADDRESS_STATUS_CURRENT         0
+#define ZV1_CAPTURE_BUF1_ADDRESS_STATUS_PENDING         1
+#define ZV1_CAPTURE_BUF1_ADDRESS_EXT                    27:27
+#define ZV1_CAPTURE_BUF1_ADDRESS_EXT_LOCAL              0
+#define ZV1_CAPTURE_BUF1_ADDRESS_EXT_EXTERNAL           1
+#define ZV1_CAPTURE_BUF1_ADDRESS_CS                     26:26
+#define ZV1_CAPTURE_BUF1_ADDRESS_CS_0                   0
+#define ZV1_CAPTURE_BUF1_ADDRESS_CS_1                   1
+#define ZV1_CAPTURE_BUF1_ADDRESS_ADDRESS                25:0
+
+#define ZV1_CAPTURE_BUF_OFFSET                          0x098014
+#define ZV1_CAPTURE_BUF_OFFSET_OFFSET                   15:0
+
+#define ZV1_CAPTURE_FIFO_CTRL                           0x098018
+#define ZV1_CAPTURE_FIFO_CTRL_FIFO                      2:0
+#define ZV1_CAPTURE_FIFO_CTRL_FIFO_0                    0
+#define ZV1_CAPTURE_FIFO_CTRL_FIFO_1                    1
+#define ZV1_CAPTURE_FIFO_CTRL_FIFO_2                    2
+#define ZV1_CAPTURE_FIFO_CTRL_FIFO_3                    3
+#define ZV1_CAPTURE_FIFO_CTRL_FIFO_4                    4
+#define ZV1_CAPTURE_FIFO_CTRL_FIFO_5                    5
+#define ZV1_CAPTURE_FIFO_CTRL_FIFO_6                    6
+#define ZV1_CAPTURE_FIFO_CTRL_FIFO_7                    7
+
+#define ZV1_CAPTURE_YRGB_CONST                          0x09801C
+#define ZV1_CAPTURE_YRGB_CONST_Y                        31:24
+#define ZV1_CAPTURE_YRGB_CONST_R                        23:16
+#define ZV1_CAPTURE_YRGB_CONST_G                        15:8
+#define ZV1_CAPTURE_YRGB_CONST_B                        7:0
+
+#define DMA_1_SOURCE                                    0x0D0010
+#define DMA_1_SOURCE_ADDRESS_EXT                        27:27
+#define DMA_1_SOURCE_ADDRESS_EXT_LOCAL                  0
+#define DMA_1_SOURCE_ADDRESS_EXT_EXTERNAL               1
+#define DMA_1_SOURCE_ADDRESS_CS                         26:26
+#define DMA_1_SOURCE_ADDRESS_CS_0                       0
+#define DMA_1_SOURCE_ADDRESS_CS_1                       1
+#define DMA_1_SOURCE_ADDRESS                            25:0
+
+#define DMA_1_DESTINATION                               0x0D0014
+#define DMA_1_DESTINATION_ADDRESS_EXT                   27:27
+#define DMA_1_DESTINATION_ADDRESS_EXT_LOCAL             0
+#define DMA_1_DESTINATION_ADDRESS_EXT_EXTERNAL          1
+#define DMA_1_DESTINATION_ADDRESS_CS                    26:26
+#define DMA_1_DESTINATION_ADDRESS_CS_0                  0
+#define DMA_1_DESTINATION_ADDRESS_CS_1                  1
+#define DMA_1_DESTINATION_ADDRESS                       25:0
+
+#define DMA_1_SIZE_CONTROL                              0x0D0018
+#define DMA_1_SIZE_CONTROL_STATUS                       31:31
+#define DMA_1_SIZE_CONTROL_STATUS_IDLE                  0
+#define DMA_1_SIZE_CONTROL_STATUS_ACTIVE                1
+#define DMA_1_SIZE_CONTROL_SIZE                         23:0
+
+#define DMA_ABORT_INTERRUPT                             0x0D0020
+#define DMA_ABORT_INTERRUPT_ABORT_1                     5:5
+#define DMA_ABORT_INTERRUPT_ABORT_1_ENABLE              0
+#define DMA_ABORT_INTERRUPT_ABORT_1_ABORT               1
+#define DMA_ABORT_INTERRUPT_ABORT_0                     4:4
+#define DMA_ABORT_INTERRUPT_ABORT_0_ENABLE              0
+#define DMA_ABORT_INTERRUPT_ABORT_0_ABORT               1
+#define DMA_ABORT_INTERRUPT_INT_1                       1:1
+#define DMA_ABORT_INTERRUPT_INT_1_CLEAR                 0
+#define DMA_ABORT_INTERRUPT_INT_1_FINISHED              1
+#define DMA_ABORT_INTERRUPT_INT_0                       0:0
+#define DMA_ABORT_INTERRUPT_INT_0_CLEAR                 0
+#define DMA_ABORT_INTERRUPT_INT_0_FINISHED              1
+
+
+
+
+
+/* Default i2c CLK and Data GPIO. These are the default i2c pins */
+#define DEFAULT_I2C_SCL                     30
+#define DEFAULT_I2C_SDA                     31
+
+
+#define GPIO_DATA_SM750LE                               0x020018
+#define GPIO_DATA_SM750LE_1                             1:1
+#define GPIO_DATA_SM750LE_0                             0:0
+
+#define GPIO_DATA_DIRECTION_SM750LE                     0x02001C
+#define GPIO_DATA_DIRECTION_SM750LE_1                   1:1
+#define GPIO_DATA_DIRECTION_SM750LE_1_INPUT             0
+#define GPIO_DATA_DIRECTION_SM750LE_1_OUTPUT            1
+#define GPIO_DATA_DIRECTION_SM750LE_0                   0:0
+#define GPIO_DATA_DIRECTION_SM750LE_0_INPUT             0
+#define GPIO_DATA_DIRECTION_SM750LE_0_OUTPUT            1
+
+
+#endif
diff --git a/drivers/staging/sm750fb/ddk750_sii164.c b/drivers/staging/sm750fb/ddk750_sii164.c
new file mode 100644 (file)
index 0000000..3d224d6
--- /dev/null
@@ -0,0 +1,425 @@
+#define USE_DVICHIP
+#ifdef USE_DVICHIP
+
+#include "ddk750_sii164.h"
+#include "ddk750_hwi2c.h"
+
+/* I2C Address of each SII164 chip */
+#define SII164_I2C_ADDRESS                  0x70
+
+/* Define this definition to use hardware i2c. */
+#define USE_HW_I2C
+
+#ifdef USE_HW_I2C
+    #define i2cWriteReg hwI2CWriteReg
+    #define i2cReadReg  hwI2CReadReg
+#else
+    #define i2cWriteReg swI2CWriteReg
+    #define i2cReadReg  swI2CReadReg
+#endif
+
+/* SII164 Vendor and Device ID */
+#define SII164_VENDOR_ID                    0x0001
+#define SII164_DEVICE_ID                    0x0006
+
+#ifdef SII164_FULL_FUNCTIONS
+/* Name of the DVI Controller chip */
+static char *gDviCtrlChipName = "Silicon Image SiI 164";
+#endif
+
+/*
+ *  sii164GetVendorID
+ *      This function gets the vendor ID of the DVI controller chip.
+ *
+ *  Output:
+ *      Vendor ID
+ */
+unsigned short sii164GetVendorID(void)
+{
+    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);
+
+    return vendorID;
+}
+
+/*
+ *  sii164GetDeviceID
+ *      This function gets the device ID of the DVI controller chip.
+ *
+ *  Output:
+ *      Device ID
+ */
+unsigned short sii164GetDeviceID(void)
+{
+    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);
+
+    return deviceID;
+}
+
+
+
+/* DVI.C will handle all SiI164 chip stuffs and try it best to make code minimal and useful */
+
+/*
+ *  sii164InitChip
+ *      This function initialize and detect the DVI controller chip.
+ *
+ *  Input:
+ *      edgeSelect          - Edge Select:
+ *                              0 = Input data is falling edge latched (falling edge
+ *                                  latched first in dual edge mode)
+ *                              1 = Input data is rising edge latched (rising edge
+ *                                  latched first in dual edge mode)
+ *      busSelect           - Input Bus Select:
+ *                              0 = Input data bus is 12-bits wide
+ *                              1 = Input data bus is 24-bits wide
+ *      dualEdgeClkSelect   - Dual Edge Clock Select
+ *                              0 = Input data is single edge latched
+ *                              1 = Input data is dual edge latched
+ *      hsyncEnable         - Horizontal Sync Enable:
+ *                              0 = HSYNC input is transmitted as fixed LOW
+ *                              1 = HSYNC input is transmitted as is
+ *      vsyncEnable         - Vertical Sync Enable:
+ *                              0 = VSYNC input is transmitted as fixed LOW
+ *                              1 = VSYNC input is transmitted as is
+ *      deskewEnable        - De-skewing Enable:
+ *                              0 = De-skew disabled
+ *                              1 = De-skew enabled
+ *      deskewSetting       - De-skewing Setting (increment of 260psec)
+ *                              0 = 1 step --> minimum setup / maximum hold
+ *                              1 = 2 step
+ *                              2 = 3 step
+ *                              3 = 4 step
+ *                              4 = 5 step
+ *                              5 = 6 step
+ *                              6 = 7 step
+ *                              7 = 8 step --> maximum setup / minimum hold
+ *      continuousSyncEnable- SYNC Continuous:
+ *                              0 = Disable
+ *                              1 = Enable
+ *      pllFilterEnable     - PLL Filter Enable
+ *                              0 = Disable PLL Filter
+ *                              1 = Enable PLL Filter
+ *      pllFilterValue      - PLL Filter characteristics:
+ *                              0~7 (recommended value is 4)
+ *
+ *  Output:
+ *      0   - Success
+ *     -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 ucRegIndex, ucRegValue;
+    //unsigned char ucDeviceAddress,
+       unsigned char config;
+    //unsigned long delayCount;
+
+    /* Initialize the i2c bus */
+#ifdef USE_HW_I2C
+    /* Use fast mode. */
+    hwI2CInit(1);
+#else
+    swI2CInit(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA);
+#endif
+
+    /* Check if SII164 Chip exists */
+    if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID))
+    {
+
+#ifdef DDKDEBUG
+        //sii164PrintRegisterValues();
+#endif
+        /*
+         *  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);
+
+#ifdef DDKDEBUG
+        //sii164PrintRegisterValues();
+#endif
+
+        return 0;
+    }
+
+    /* Return -1 if initialization fails. */
+    return (-1);
+}
+
+
+
+
+
+/* below sii164 function is not neccessary */
+
+#ifdef SII164_FULL_FUNCTIONS
+
+/*
+ *  sii164ResetChip
+ *      This function resets the DVI Controller Chip.
+ */
+void sii164ResetChip(void)
+{
+    /* Power down */
+    sii164SetPower(0);
+    sii164SetPower(1);
+}
+
+
+/*
+ * sii164GetChipString
+ *      This function returns a char string name of the current DVI Controller chip.
+ *      It's convenient for application need to display the chip name.
+ */
+char *sii164GetChipString(void)
+{
+    return gDviCtrlChipName;
+}
+
+
+/*
+ *  sii164SetPower
+ *      This function sets the power configuration of the DVI Controller Chip.
+ *
+ *  Input:
+ *      powerUp - Flag to set the power down or up
+ */
+void sii164SetPower(
+    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);
+    }
+}
+
+
+/*
+ *  sii164SelectHotPlugDetectionMode
+ *      This function selects the mode of the hot plug detection.
+ */
+static void sii164SelectHotPlugDetectionMode(
+    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);
+}
+
+/*
+ *  sii164EnableHotPlugDetection
+ *      This function enables the Hot Plug detection.
+ *
+ *  enableHotPlug   - Enable (=1) / disable (=0) Hot Plug detection
+ */
+void sii164EnableHotPlugDetection(
+    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);
+}
+
+/*
+ *  sii164IsConnected
+ *      Check if the DVI Monitor is connected.
+ *
+ *  Output:
+ *      0   - Not Connected
+ *      1   - Connected
+ */
+unsigned char sii164IsConnected(void)
+{
+    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;
+}
+
+/*
+ *  sii164CheckInterrupt
+ *      Checks if interrupt has occured.
+ *
+ *  Output:
+ *      0   - No interrupt
+ *      1   - Interrupt occurs
+ */
+unsigned char sii164CheckInterrupt(void)
+{
+    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;
+}
+
+/*
+ *  sii164ClearInterrupt
+ *      Clear the hot plug interrupt.
+ */
+void sii164ClearInterrupt(void)
+{
+    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);
+}
+
+#endif
+
+#endif
+
+
diff --git a/drivers/staging/sm750fb/ddk750_sii164.h b/drivers/staging/sm750fb/ddk750_sii164.h
new file mode 100644 (file)
index 0000000..2b4c7d3
--- /dev/null
@@ -0,0 +1,172 @@
+#ifndef DDK750_SII164_H__
+#define DDK750_SII164_H__
+
+#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. */
+} 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 short sii164GetVendorID(void);
+unsigned short sii164GetDeviceID(void);
+
+
+#ifdef SII164_FULL_FUNCTIONS
+void sii164ResetChip(void);
+char *sii164GetChipString(void);
+void sii164SetPower(unsigned char powerUp);
+void sii164EnableHotPlugDetection(unsigned char enableHotPlug);
+unsigned char sii164IsConnected(void);
+unsigned char sii164CheckInterrupt(void);
+void sii164ClearInterrupt(void);
+#endif
+/* below register definination is used for Silicon Image SiI164 DVI controller chip */
+/*
+ * Vendor ID registers
+ */
+#define SII164_VENDOR_ID_LOW                        0x00
+#define SII164_VENDOR_ID_HIGH                       0x01
+
+/*
+ * Device ID registers
+ */
+#define SII164_DEVICE_ID_LOW                        0x02
+#define SII164_DEVICE_ID_HIGH                       0x03
+
+/*
+ * Device Revision
+ */
+#define SII164_DEVICE_REVISION                      0x04
+
+/*
+ * Frequency Limitation registers
+ */
+#define SII164_FREQUENCY_LIMIT_LOW                  0x06
+#define SII164_FREQUENCY_LIMIT_HIGH                 0x07
+
+/*
+ * Power Down and Input Signal Configuration registers
+ */
+#define SII164_CONFIGURATION                        0x08
+
+/* Power down (PD) */
+#define SII164_CONFIGURATION_POWER_DOWN             0x00
+#define SII164_CONFIGURATION_POWER_NORMAL           0x01
+#define SII164_CONFIGURATION_POWER_MASK             0x01
+
+/* Input Edge Latch Select (EDGE) */
+#define SII164_CONFIGURATION_LATCH_FALLING          0x00
+#define SII164_CONFIGURATION_LATCH_RISING           0x02
+
+/* Bus Select (BSEL) */
+#define SII164_CONFIGURATION_BUS_12BITS             0x00
+#define SII164_CONFIGURATION_BUS_24BITS             0x04
+
+/* Dual Edge Clock Select (DSEL) */
+#define SII164_CONFIGURATION_CLOCK_SINGLE           0x00
+#define SII164_CONFIGURATION_CLOCK_DUAL             0x08
+
+/* Horizontal Sync Enable (HEN) */
+#define SII164_CONFIGURATION_HSYNC_FORCE_LOW        0x00
+#define SII164_CONFIGURATION_HSYNC_AS_IS            0x10
+
+/* Vertical Sync Enable (VEN) */
+#define SII164_CONFIGURATION_VSYNC_FORCE_LOW        0x00
+#define SII164_CONFIGURATION_VSYNC_AS_IS            0x20
+
+/*
+ * Detection registers
+ */
+#define SII164_DETECT                               0x09
+
+/* Monitor Detect Interrupt (MDI) */
+#define SII164_DETECT_MONITOR_STATE_CHANGE          0x00
+#define SII164_DETECT_MONITOR_STATE_NO_CHANGE       0x01
+#define SII164_DETECT_MONITOR_STATE_CLEAR           0x01
+#define SII164_DETECT_MONITOR_STATE_MASK            0x01
+
+/* Hot Plug detect Input (HTPLG) */
+#define SII164_DETECT_HOT_PLUG_STATUS_OFF           0x00
+#define SII164_DETECT_HOT_PLUG_STATUS_ON            0x02
+#define SII164_DETECT_HOT_PLUG_STATUS_MASK          0x02
+
+/* Receiver Sense (RSEN) */
+#define SII164_DETECT_RECEIVER_SENSE_NOT_DETECTED   0x00
+#define SII164_DETECT_RECEIVER_SENSE_DETECTED       0x04
+
+/* Interrupt Generation Method (TSEL) */
+#define SII164_DETECT_INTERRUPT_BY_RSEN_PIN         0x00
+#define SII164_DETECT_INTERRUPT_BY_HTPLG_PIN        0x08
+#define SII164_DETECT_INTERRUPT_MASK                0x08
+
+/* Monitor Sense Output (MSEN) */
+#define SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH     0x00
+#define SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI      0x10
+#define SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN     0x20
+#define SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG    0x30
+#define SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG     0x30
+
+/*
+ * Skewing registers
+ */
+#define SII164_DESKEW                               0x0A
+
+/* General Purpose Input (CTL[3:1]) */
+#define SII164_DESKEW_GENERAL_PURPOSE_INPUT_MASK    0x0E
+
+/* De-skewing Enable bit (DKEN) */
+#define SII164_DESKEW_DISABLE                       0x00
+#define SII164_DESKEW_ENABLE                        0x10
+
+/* De-skewing Setting (DK[3:1])*/
+#define SII164_DESKEW_1_STEP                        0x00
+#define SII164_DESKEW_2_STEP                        0x20
+#define SII164_DESKEW_3_STEP                        0x40
+#define SII164_DESKEW_4_STEP                        0x60
+#define SII164_DESKEW_5_STEP                        0x80
+#define SII164_DESKEW_6_STEP                        0xA0
+#define SII164_DESKEW_7_STEP                        0xC0
+#define SII164_DESKEW_8_STEP                        0xE0
+
+/*
+ * User Configuration Data registers (CFG 7:0)
+ */
+#define SII164_USER_CONFIGURATION                   0x0B
+
+/*
+ * PLL registers
+ */
+#define SII164_PLL                                  0x0C
+
+/* PLL Filter Value (PLLF) */
+#define SII164_PLL_FILTER_VALUE_MASK                0x0E
+
+/* PLL Filter Enable (PFEN) */
+#define SII164_PLL_FILTER_DISABLE                   0x00
+#define SII164_PLL_FILTER_ENABLE                    0x01
+
+/* Sync Continuous (SCNT) */
+#define SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE   0x00
+#define SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE    0x80
+
+#endif
diff --git a/drivers/staging/sm750fb/ddk750_swi2c.c b/drivers/staging/sm750fb/ddk750_swi2c.c
new file mode 100644 (file)
index 0000000..901b373
--- /dev/null
@@ -0,0 +1,522 @@
+/*******************************************************************
+*
+*         Copyright (c) 2007 by Silicon Motion, Inc. (SMI)
+*
+*  All rights are reserved. Reproduction or in part is prohibited
+*  without the written consent of the copyright owner.
+*
+*  swi2c.c --- SM750/SM718 DDK
+*  This file contains the source code for I2C using software
+*  implementation.
+*
+*******************************************************************/
+#include "ddk750_help.h"
+#include "ddk750_reg.h"
+#include "ddk750_swi2c.h"
+#include "ddk750_power.h"
+
+
+/*******************************************************************
+ * I2C Software Master Driver:
+ * ===========================
+ * Each i2c cycle is split into 4 sections. Each of these section marks
+ * a point in time where the SCL or SDA may be changed.
+ *
+ * 1 Cycle == |  Section I. |  Section 2. |  Section 3. |  Section 4. |
+ *            +-------------+-------------+-------------+-------------+
+ *            | SCL set LOW |SCL no change| SCL set HIGH|SCL no change|
+ *
+ *                                          ____________ _____________
+ * SCL == XXXX _____________ ____________ /
+ *
+ * I.e. the SCL may only be changed in section 1. and section 3. while
+ * the SDA may only be changed in section 2. and section 4. The table
+ * below gives the changes for these 2 lines in the varios sections.
+ *
+ * Section changes Table:
+ * ======================
+ * blank = no change, L = set bit LOW, H = set bit HIGH
+ *
+ *                                | 1.| 2.| 3.| 4.|
+ *                 ---------------+---+---+---+---+
+ *                 Tx Start   SDA |   | H |   | L |
+ *                            SCL | L |   | H |   |
+ *                 ---------------+---+---+---+---+
+ *                 Tx Stop    SDA |   | L |   | H |
+ *                            SCL | L |   | H |   |
+ *                 ---------------+---+---+---+---+
+ *                 Tx bit H   SDA |   | H |   |   |
+ *                            SCL | L |   | H |   |
+ *                 ---------------+---+---+---+---+
+ *                 Tx bit L   SDA |   | L |   |   |
+ *                            SCL | L |   | H |   |
+ *                 ---------------+---+---+---+---+
+ *
+ ******************************************************************/
+
+/* GPIO pins used for this I2C. It ranges from 0 to 63. */
+static unsigned char g_i2cClockGPIO = DEFAULT_I2C_SCL;
+static unsigned char g_i2cDataGPIO = DEFAULT_I2C_SDA;
+
+/*
+ *  Below is the variable declaration for the GPIO pin register usage
+ *  for the i2c Clock and i2c Data.
+ *
+ *  Note:
+ *      Notice that the GPIO usage for the i2c clock and i2c Data are
+ *      separated. This is to make this code flexible enough when
+ *      two separate GPIO pins for the clock and data are located
+ *      in two different GPIO register set (worst case).
+ */
+
+/* i2c Clock GPIO Register usage */
+static unsigned long g_i2cClkGPIOMuxReg = GPIO_MUX;
+static unsigned long g_i2cClkGPIODataReg = GPIO_DATA;
+static unsigned long g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION;
+
+/* i2c Data GPIO Register usage */
+static unsigned long g_i2cDataGPIOMuxReg = GPIO_MUX;
+static unsigned long g_i2cDataGPIODataReg = GPIO_DATA;
+static unsigned long g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION;
+
+/*
+ *  This function puts a delay between command
+ */
+static void swI2CWait(void)
+{
+       /* find a bug:
+        * peekIO method works well before suspend/resume
+        * but after suspend, peekIO(0x3ce,0x61) & 0x10
+        * always be non-zero,which makes the while loop
+        * never finish.
+        * use non-ultimate for loop below is safe
+        * */
+#if 0
+    /* Change wait algorithm to use PCI bus clock,
+       it's more reliable than counter loop ..
+       write 0x61 to 0x3ce and read from 0x3cf
+       */
+       while(peekIO(0x3ce,0x61) & 0x10);
+#else
+    int i, Temp;
+
+    for(i=0; i<600; i++)
+    {
+        Temp = i;
+        Temp += i;
+    }
+#endif
+}
+
+/*
+ *  This function set/reset the SCL GPIO pin
+ *
+ *  Parameters:
+ *      value    - Bit value to set to the SCL or SDA (0 = low, 1 = high)
+ *
+ *  Notes:
+ *      When setting SCL to high, just set the GPIO as input where the pull up
+ *      resistor will pull the signal up. Do not use software to pull up the
+ *      signal because the i2c will fail when other device try to drive the
+ *      signal due to SM50x will drive the signal to always high.
+ */
+void swI2CSCL(unsigned char value)
+{
+    unsigned long ulGPIOData;
+    unsigned long ulGPIODirection;
+
+    ulGPIODirection = PEEK32(g_i2cClkGPIODataDirReg);
+    if (value)      /* High */
+    {
+        /* Set direction as input. This will automatically pull the signal up. */
+        ulGPIODirection &= ~(1 << g_i2cClockGPIO);
+        POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection);
+    }
+    else            /* Low */
+    {
+        /* Set the signal down */
+        ulGPIOData = PEEK32(g_i2cClkGPIODataReg);
+        ulGPIOData &= ~(1 << g_i2cClockGPIO);
+        POKE32(g_i2cClkGPIODataReg, ulGPIOData);
+
+        /* Set direction as output */
+        ulGPIODirection |= (1 << g_i2cClockGPIO);
+        POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection);
+    }
+}
+
+/*
+ *  This function set/reset the SDA GPIO pin
+ *
+ *  Parameters:
+ *      value    - Bit value to set to the SCL or SDA (0 = low, 1 = high)
+ *
+ *  Notes:
+ *      When setting SCL to high, just set the GPIO as input where the pull up
+ *      resistor will pull the signal up. Do not use software to pull up the
+ *      signal because the i2c will fail when other device try to drive the
+ *      signal due to SM50x will drive the signal to always high.
+ */
+void swI2CSDA(unsigned char value)
+{
+    unsigned long ulGPIOData;
+    unsigned long ulGPIODirection;
+
+    ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg);
+    if (value)      /* High */
+    {
+        /* Set direction as input. This will automatically pull the signal up. */
+        ulGPIODirection &= ~(1 << g_i2cDataGPIO);
+        POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection);
+    }
+    else            /* Low */
+    {
+        /* Set the signal down */
+        ulGPIOData = PEEK32(g_i2cDataGPIODataReg);
+        ulGPIOData &= ~(1 << g_i2cDataGPIO);
+        POKE32(g_i2cDataGPIODataReg, ulGPIOData);
+
+        /* Set direction as output */
+        ulGPIODirection |= (1 << g_i2cDataGPIO);
+        POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection);
+    }
+}
+
+/*
+ *  This function read the data from the SDA GPIO pin
+ *
+ *  Return Value:
+ *      The SDA data bit sent by the Slave
+ */
+static unsigned char swI2CReadSDA(void)
+{
+    unsigned long ulGPIODirection;
+    unsigned long ulGPIOData;
+
+    /* Make sure that the direction is input (High) */
+    ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg);
+    if ((ulGPIODirection & (1 << g_i2cDataGPIO)) != (~(1 << g_i2cDataGPIO)))
+    {
+        ulGPIODirection &= ~(1 << g_i2cDataGPIO);
+        POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection);
+    }
+
+    /* Now read the SDA line */
+    ulGPIOData = PEEK32(g_i2cDataGPIODataReg);
+    if (ulGPIOData & (1 << g_i2cDataGPIO))
+        return 1;
+    else
+        return 0;
+}
+
+/*
+ *  This function sends ACK signal
+ */
+static void swI2CAck(void)
+{
+    return;  /* Single byte read is ok without it. */
+}
+
+/*
+ *  This function sends the start command to the slave device
+ */
+static void swI2CStart(void)
+{
+    /* Start I2C */
+    swI2CSDA(1);
+    swI2CSCL(1);
+    swI2CSDA(0);
+}
+
+/*
+ *  This function sends the stop command to the slave device
+ */
+static void swI2CStop(void)
+{
+    /* Stop the I2C */
+    swI2CSCL(1);
+    swI2CSDA(0);
+    swI2CSDA(1);
+}
+
+/*
+ *  This function writes one byte to the slave device
+ *
+ *  Parameters:
+ *      data    - Data to be write to the slave device
+ *
+ *  Return Value:
+ *       0   - Success
+ *      -1   - Fail to write byte
+ */
+static long swI2CWriteByte(unsigned char data)
+{
+    unsigned char value = data;
+    int i;
+
+    /* Sending the data bit by bit */
+    for (i=0; i<8; i++)
+    {
+        /* Set SCL to low */
+        swI2CSCL(0);
+
+        /* Send data bit */
+        if ((value & 0x80) != 0)
+            swI2CSDA(1);
+        else
+            swI2CSDA(0);
+
+        swI2CWait();
+
+        /* Toggle clk line to one */
+        swI2CSCL(1);
+        swI2CWait();
+
+        /* Shift byte to be sent */
+        value = value << 1;
+    }
+
+    /* Set the SCL Low and SDA High (prepare to get input) */
+    swI2CSCL(0);
+    swI2CSDA(1);
+
+    /* Set the SCL High for ack */
+    swI2CWait();
+    swI2CSCL(1);
+    swI2CWait();
+
+    /* Read SDA, until SDA==0 */
+    for(i=0; i<0xff; i++)
+    {
+        if (!swI2CReadSDA())
+            break;
+
+        swI2CSCL(0);
+        swI2CWait();
+        swI2CSCL(1);
+        swI2CWait();
+    }
+
+    /* Set the SCL Low and SDA High */
+    swI2CSCL(0);
+    swI2CSDA(1);
+
+    if (i<0xff)
+        return 0;
+    else
+        return -1;
+}
+
+/*
+ *  This function reads one byte from the slave device
+ *
+ *  Parameters:
+ *      ack    - Flag to indicate either to send the acknowledge
+ *            message to the slave device or not
+ *
+ *  Return Value:
+ *      One byte data read from the Slave device
+ */
+static unsigned char swI2CReadByte(unsigned char ack)
+{
+    int i;
+    unsigned char data = 0;
+
+    for(i=7; i>=0; i--)
+    {
+        /* Set the SCL to Low and SDA to High (Input) */
+        swI2CSCL(0);
+        swI2CSDA(1);
+        swI2CWait();
+
+        /* Set the SCL High */
+        swI2CSCL(1);
+        swI2CWait();
+
+        /* Read data bits from SDA */
+        data |= (swI2CReadSDA() << i);
+    }
+
+    if (ack)
+        swI2CAck();
+
+    /* Set the SCL Low and SDA High */
+    swI2CSCL(0);
+    swI2CSDA(1);
+
+    return data;
+}
+
+/*
+ * This function initializes GPIO port for SW I2C communication.
+ *
+ * Parameters:
+ *      i2cClkGPIO      - The GPIO pin to be used as i2c SCL
+ *      i2cDataGPIO     - The GPIO pin to be used as i2c SDA
+ *
+ * Return Value:
+ *      -1   - Fail to initialize the i2c
+ *       0   - Success
+ */
+static long swI2CInit_SM750LE(unsigned char i2cClkGPIO,
+                             unsigned char i2cDataGPIO)
+{
+    int i;
+
+    /* Initialize the GPIO pin for the i2c Clock Register */
+    g_i2cClkGPIODataReg = GPIO_DATA_SM750LE;
+    g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE;
+
+    /* Initialize the Clock GPIO Offset */
+    g_i2cClockGPIO = i2cClkGPIO;
+
+    /* Initialize the GPIO pin for the i2c Data Register */
+    g_i2cDataGPIODataReg = GPIO_DATA_SM750LE;
+    g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE;
+
+    /* Initialize the Data GPIO Offset */
+    g_i2cDataGPIO = i2cDataGPIO;
+
+    /* Note that SM750LE don't have GPIO MUX and power is always on */
+
+    /* Clear the i2c lines. */
+    for(i=0; i<9; i++)
+        swI2CStop();
+
+    return 0;
+}
+
+/*
+ * This function initializes the i2c attributes and bus
+ *
+ * Parameters:
+ *      i2cClkGPIO      - The GPIO pin to be used as i2c SCL
+ *      i2cDataGPIO     - The GPIO pin to be used as i2c SDA
+ *
+ * Return Value:
+ *      -1   - Fail to initialize the i2c
+ *       0   - Success
+ */
+long swI2CInit(
+    unsigned char i2cClkGPIO,
+    unsigned char i2cDataGPIO
+)
+{
+    int i;
+
+    /* Return 0 if the GPIO pins to be used is out of range. The range is only from [0..63] */
+    if ((i2cClkGPIO > 31) || (i2cDataGPIO > 31))
+        return -1;
+
+    if (getChipType() == SM750LE)
+        return swI2CInit_SM750LE(i2cClkGPIO, i2cDataGPIO);
+
+    /* Initialize the GPIO pin for the i2c Clock Register */
+    g_i2cClkGPIOMuxReg = GPIO_MUX;
+    g_i2cClkGPIODataReg = GPIO_DATA;
+    g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION;
+
+    /* Initialize the Clock GPIO Offset */
+    g_i2cClockGPIO = i2cClkGPIO;
+
+    /* Initialize the GPIO pin for the i2c Data Register */
+    g_i2cDataGPIOMuxReg = GPIO_MUX;
+    g_i2cDataGPIODataReg = GPIO_DATA;
+    g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION;
+
+    /* Initialize the Data GPIO Offset */
+    g_i2cDataGPIO = i2cDataGPIO;
+
+    /* Enable the GPIO pins for the i2c Clock and Data (GPIO MUX) */
+    POKE32(g_i2cClkGPIOMuxReg,
+                      PEEK32(g_i2cClkGPIOMuxReg) & ~(1 << g_i2cClockGPIO));
+    POKE32(g_i2cDataGPIOMuxReg,
+                      PEEK32(g_i2cDataGPIOMuxReg) & ~(1 << g_i2cDataGPIO));
+
+    /* Enable GPIO power */
+    enableGPIO(1);
+
+    /* Clear the i2c lines. */
+    for(i=0; i<9; i++)
+        swI2CStop();
+
+    return 0;
+}
+
+/*
+ *  This function reads the slave device's register
+ *
+ *  Parameters:
+ *      deviceAddress   - i2c Slave device address which register
+ *                        to be read from
+ *      registerIndex   - Slave device's register to be read
+ *
+ *  Return Value:
+ *      Register value
+ */
+unsigned char swI2CReadReg(
+    unsigned char deviceAddress,
+    unsigned char registerIndex
+)
+{
+    unsigned char data;
+
+    /* Send the Start signal */
+    swI2CStart();
+
+    /* Send the device address */
+    swI2CWriteByte(deviceAddress);
+
+    /* Send the register index */
+    swI2CWriteByte(registerIndex);
+
+    /* Get the bus again and get the data from the device read address */
+    swI2CStart();
+    swI2CWriteByte(deviceAddress + 1);
+    data = swI2CReadByte(1);
+
+    /* Stop swI2C and release the bus */
+    swI2CStop();
+
+    return data;
+}
+
+/*
+ *  This function writes a value to the slave device's register
+ *
+ *  Parameters:
+ *      deviceAddress   - i2c Slave device address which register
+ *                        to be written
+ *      registerIndex   - Slave device's register to be written
+ *      data            - Data to be written to the register
+ *
+ *  Result:
+ *          0   - Success
+ *         -1   - Fail
+ */
+long swI2CWriteReg(
+    unsigned char deviceAddress,
+    unsigned char registerIndex,
+    unsigned char data
+)
+{
+    long returnValue = 0;
+
+    /* Send the Start signal */
+    swI2CStart();
+
+    /* Send the device address and read the data. All should return success
+       in order for the writing processed to be successful
+     */
+    if ((swI2CWriteByte(deviceAddress) != 0) ||
+        (swI2CWriteByte(registerIndex) != 0) ||
+        (swI2CWriteByte(data) != 0))
+    {
+        returnValue = -1;
+    }
+
+    /* Stop i2c and release the bus */
+    swI2CStop();
+
+    return returnValue;
+}
diff --git a/drivers/staging/sm750fb/ddk750_swi2c.h b/drivers/staging/sm750fb/ddk750_swi2c.h
new file mode 100644 (file)
index 0000000..ec5463b
--- /dev/null
@@ -0,0 +1,92 @@
+/*******************************************************************
+*
+*         Copyright (c) 2007 by Silicon Motion, Inc. (SMI)
+*
+*  All rights are reserved. Reproduction or in part is prohibited
+*  without the written consent of the copyright owner.
+*
+*  swi2c.h --- SM750/SM718 DDK
+*  This file contains the definitions for i2c using software
+*  implementation.
+*
+*******************************************************************/
+#ifndef _SWI2C_H_
+#define _SWI2C_H_
+
+/* Default i2c CLK and Data GPIO. These are the default i2c pins */
+#define DEFAULT_I2C_SCL                     30
+#define DEFAULT_I2C_SDA                     31
+
+/*
+ * This function initializes the i2c attributes and bus
+ *
+ * Parameters:
+ *      i2cClkGPIO  - The GPIO pin to be used as i2c SCL
+ *      i2cDataGPIO - The GPIO pin to be used as i2c SDA
+ *
+ * Return Value:
+ *      -1   - Fail to initialize the i2c
+ *       0   - Success
+ */
+long swI2CInit(
+    unsigned char i2cClkGPIO,
+    unsigned char i2cDataGPIO
+);
+
+/*
+ *  This function reads the slave device's register
+ *
+ *  Parameters:
+ *      deviceAddress   - i2c Slave device address which register
+ *                        to be read from
+ *      registerIndex   - Slave device's register to be read
+ *
+ *  Return Value:
+ *      Register value
+ */
+unsigned char swI2CReadReg(
+    unsigned char deviceAddress,
+    unsigned char registerIndex
+);
+
+/*
+ *  This function writes a value to the slave device's register
+ *
+ *  Parameters:
+ *      deviceAddress   - i2c Slave device address which register
+ *                        to be written
+ *      registerIndex   - Slave device's register to be written
+ *      data            - Data to be written to the register
+ *
+ *  Result:
+ *          0   - Success
+ *         -1   - Fail
+ */
+long swI2CWriteReg(
+    unsigned char deviceAddress,
+    unsigned char registerIndex,
+    unsigned char data
+);
+
+/*
+ *  These two functions are used to toggle the data on the SCL and SDA I2C lines.
+ *  The used of these two functions are not recommended unless it is necessary.
+ */
+
+/*
+ *  This function set/reset the SCL GPIO pin
+ *
+ *  Parameters:
+ *      value  - Bit value to set to the SCL or SDA (0 = low, 1 = high)
+ */
+void swI2CSCL(unsigned char value);
+
+/*
+ *  This function set/reset the SDA GPIO pin
+ *
+ *  Parameters:
+ *      value  - Bit value to set to the SCL or SDA (0 = low, 1 = high)
+ */
+void swI2CSDA(unsigned char value);
+
+#endif  /* _SWI2C_H_ */
diff --git a/drivers/staging/sm750fb/modedb.h b/drivers/staging/sm750fb/modedb.h
new file mode 100644 (file)
index 0000000..c5275c6
--- /dev/null
@@ -0,0 +1,221 @@
+
+static const struct fb_videomode modedb2[] = {
+    {
+       /* 640x400 @ 70 Hz, 31.5 kHz hsync */
+       NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 640x480 @ 60 Hz, 31.5 kHz hsync */
+       NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 800x600 @ 56 Hz, 35.15 kHz hsync */
+       NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */
+       NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8,
+       0, FB_VMODE_INTERLACED
+    }, {
+       /* 640x400 @ 85 Hz, 37.86 kHz hsync */
+       NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3,
+       FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+       /* 640x480 @ 72 Hz, 36.5 kHz hsync */
+       NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 640x480 @ 75 Hz, 37.50 kHz hsync */
+       NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 800x600 @ 60 Hz, 37.8 kHz hsync */
+       NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
+       FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+       /* 640x480 @ 85 Hz, 43.27 kHz hsync */
+       NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */
+       NULL, 69, 1152, 864, 15384, 96, 16, 110, 1, 216, 10,
+       0, FB_VMODE_INTERLACED
+    }, {
+       /* 800x600 @ 72 Hz, 48.0 kHz hsync */
+       NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
+       FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1024x768 @ 60 Hz, 48.4 kHz hsync */
+       NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 640x480 @ 100 Hz, 53.01 kHz hsync */
+       NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1152x864 @ 60 Hz, 53.5 kHz hsync */
+       NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 800x600 @ 85 Hz, 55.84 kHz hsync */
+       NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1024x768 @ 70 Hz, 56.5 kHz hsync */
+       NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+        /*  1280x960-60 VESA */
+        NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+        FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA
+    }, {
+        /*  1280x1024-60 VESA */
+        NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+        FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA
+    }, {
+       /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */
+       NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12,
+       0, FB_VMODE_INTERLACED
+    }, {
+       /* 800x600 @ 100 Hz, 64.02 kHz hsync */
+       NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1024x768 @ 76 Hz, 62.5 kHz hsync */
+       NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1152x864 @ 70 Hz, 62.4 kHz hsync */
+       NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1280x1024 @ 61 Hz, 64.2 kHz hsync */
+       NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1400x1050 @ 60Hz, 63.9 kHz hsync */
+       NULL, 68, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/
+       NULL, 75, 1400, 1050, 9271, 120, 56, 13, 0, 112, 3,
+       FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/
+        NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3,
+       FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1024x768 @ 85 Hz, 70.24 kHz hsync */
+       NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1152x864 @ 78 Hz, 70.8 kHz hsync */
+       NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1280x1024 @ 70 Hz, 74.59 kHz hsync */
+       NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1600x1200 @ 60Hz, 75.00 kHz hsync */
+       NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
+       FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1152x864 @ 84 Hz, 76.0 kHz hsync */
+       NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1280x1024 @ 74 Hz, 78.85 kHz hsync */
+       NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1024x768 @ 100Hz, 80.21 kHz hsync */
+       NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1280x1024 @ 76 Hz, 81.13 kHz hsync */
+       NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1600x1200 @ 70 Hz, 87.50 kHz hsync */
+       NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1152x864 @ 100 Hz, 89.62 kHz hsync */
+       NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1280x1024 @ 85 Hz, 91.15 kHz hsync */
+       NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+       FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1600x1200 @ 75 Hz, 93.75 kHz hsync */
+       NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
+       FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */
+       NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
+       FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1280x1024 @ 100 Hz, 107.16 kHz hsync */
+       NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1800x1440 @ 64Hz, 96.15 kHz hsync  */
+       NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3,
+       FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1800x1440 @ 70Hz, 104.52 kHz hsync  */
+       NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3,
+       FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+       /* 512x384 @ 78 Hz, 31.50 kHz hsync */
+       NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 512x384 @ 85 Hz, 34.38 kHz hsync */
+       NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */
+       NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1,
+       0, FB_VMODE_DOUBLE
+    }, {
+       /* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */
+       NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1,
+       0, FB_VMODE_DOUBLE
+    }, {
+       /* 320x240 @ 72 Hz, 36.5 kHz hsync */
+       NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2,
+       0, FB_VMODE_DOUBLE
+    }, {
+       /* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */
+       NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1,
+       0, FB_VMODE_DOUBLE
+    }, {
+       /* 400x300 @ 60 Hz, 37.8 kHz hsync */
+       NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2,
+       0, FB_VMODE_DOUBLE
+    }, {
+       /* 400x300 @ 72 Hz, 48.0 kHz hsync */
+       NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3,
+       0, FB_VMODE_DOUBLE
+    }, {
+       /* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */
+       NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1,
+       0, FB_VMODE_DOUBLE
+    }, {
+       /* 480x300 @ 60 Hz, 37.8 kHz hsync */
+       NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2,
+       0, FB_VMODE_DOUBLE
+    }, {
+       /* 480x300 @ 63 Hz, 39.6 kHz hsync */
+       NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2,
+       0, FB_VMODE_DOUBLE
+    }, {
+       /* 480x300 @ 72 Hz, 48.0 kHz hsync */
+       NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3,
+       0, FB_VMODE_DOUBLE
+    },
+};
+static const int nmodedb2 = sizeof(modedb2);
diff --git a/drivers/staging/sm750fb/readme b/drivers/staging/sm750fb/readme
new file mode 100644 (file)
index 0000000..ab9af79
--- /dev/null
@@ -0,0 +1,38 @@
+Introduction:
+       SM750 of Silicon MOtion is pci express display controller device.
+       The SM750 embedded graphics features include:
+       - dual display
+       - 2D acceleration
+       - 16MB integrated video memory
+
+About the kernel module paramter of driver:
+
+       Use 1280,8bpp index color and 60 hz mode:
+       insmod ./sm750fb.ko g_option="1280x1024-8@60"
+
+       Disable MTRR,Disable 2d acceleration,Disable hardware cursor,
+       and use a 800x600 mode :
+       insmod ./sm750fb.ko g_option="noaccel:nomtrr:nohwc:800x600"
+
+       dual frame buffer for driver with "dual" parameter
+       insmod ./sm750fb.ko g_option="dual,800x600:1024x768"
+       it will create fb0 and fb1 (or fb1,fb2 if fb0 already exist) under /dev
+       and user can use con2fb to link fbX and ttyX
+
+       Notes:
+       1) if you build the driver with built-in method, the paramter
+               you edited in the grub config file will be also the
+               same format as above modular method,but additionaly add
+               "video=sm750fb:"
+               ahead of parameters,so,it looks like:
+               video=sm750fb:noaccel,1280x1024@60,otherparam,etc...
+               it equal to modular method with below command:
+               insmod ./sm750fb.ko g_option="noaccel:1280x1024@60:otherparm:etc..."
+
+       2) if you put 800x600 into the paramter without bpp and
+               refresh rate, kernel driver will defaulty use 16bpp and 60hz
+
+Important:
+       if you have vesafb enabled in your config then /dev/fb0 will be created by vesafb
+       and this driver will use fb1, fb2. In that case, you need to configure your X-server
+       to use fb1. Another simple althernative is to disable vesafb from your config.
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
new file mode 100644 (file)
index 0000000..3c7ea95
--- /dev/null
@@ -0,0 +1,1403 @@
+#include<linux/kernel.h>
+#include<linux/module.h>
+#include<linux/errno.h>
+#include<linux/string.h>
+#include<linux/mm.h>
+#include<linux/slab.h>
+#include<linux/delay.h>
+#include<linux/fb.h>
+#include<linux/ioport.h>
+#include<linux/init.h>
+#include<linux/pci.h>
+#include<linux/mm_types.h>
+#include<linux/vmalloc.h>
+#include<linux/pagemap.h>
+#include<linux/screen_info.h>
+#include<linux/vmalloc.h>
+#include<linux/pagemap.h>
+#include <linux/console.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+#include <asm/fb.h>
+#include "sm750.h"
+#include "sm750_hw.h"
+#include "sm750_accel.h"
+#include "sm750_cursor.h"
+
+#include "modedb.h"
+
+int smi_indent = 0;
+
+
+/*
+ * #ifdef __BIG_ENDIAN
+ * ssize_t lynxfb_ops_write(struct fb_info *info, const char __user *buf,
+ * size_t count, loff_t *ppos);
+ * ssize_t lynxfb_ops_read(struct fb_info *info, char __user *buf,
+ * size_t count, loff_t *ppos);
+ * #endif
+ */
+
+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;
+#ifdef CONFIG_MTRR
+static int g_nomtrr;
+#endif
+static const char *g_fbmode[] = {NULL, NULL};
+static const char *g_def_fbmode = "800x600-16@60";
+static char *g_settings = NULL;
+static int g_dualview;
+static char *g_option = NULL;
+
+
+static const struct fb_videomode lynx750_ext[] = {
+       /*      1024x600-60 VESA        [1.71:1] */
+       {NULL,  60, 1024, 600, 20423, 144,  40, 18, 1, 104, 3,
+        FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+        FB_VMODE_NONINTERLACED},
+
+       /*      1024x600-70 VESA */
+       {NULL,  70, 1024, 600, 17211, 152,  48, 21, 1, 104, 3,
+        FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+        FB_VMODE_NONINTERLACED},
+
+       /*      1024x600-75 VESA */
+       {NULL,  75, 1024, 600, 15822, 160,  56, 23, 1, 104, 3,
+        FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+        FB_VMODE_NONINTERLACED},
+
+       /*      1024x600-85 VESA */
+       {NULL,  85, 1024, 600, 13730, 168,  56, 26, 1, 112, 3,
+        FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+        FB_VMODE_NONINTERLACED},
+
+       /*      720x480 */
+       {NULL, 60,  720,  480,  37427, 88,   16, 13, 1,   72,  3,
+        FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+        FB_VMODE_NONINTERLACED},
+
+       /*      1280x720                [1.78:1]        */
+       {NULL, 60,  1280,  720,  13426, 162, 86, 22, 1,  136, 3,
+        FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+        FB_VMODE_NONINTERLACED},
+
+       /*      1280x768@60 */
+       {NULL, 60, 1280, 768, 12579, 192, 64, 20, 3, 128, 7,
+        FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+        FB_VMODE_NONINTERLACED},
+
+       {NULL, 60, 1360, 768, 11804, 208, 64, 23, 1, 144, 3,
+        FB_SYNC_HOR_HIGH_ACT|FB_VMODE_NONINTERLACED},
+
+       /*      1360 x 768      [1.77083:1]     */
+       {NULL,  60, 1360, 768, 11804, 208,  64, 23, 1, 144, 3,
+        FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+        FB_VMODE_NONINTERLACED},
+
+       /*      1368 x 768      [1.78:1]        */
+       {NULL, 60,  1368,  768,  11647, 216, 72, 23, 1,  144, 3,
+        FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+        FB_VMODE_NONINTERLACED},
+
+       /*      1440 x 900              [16:10] */
+       {NULL, 60, 1440, 900, 9392, 232, 80, 28, 1, 152, 3,
+        FB_SYNC_VERT_HIGH_ACT,
+        FB_VMODE_NONINTERLACED},
+
+       /*      1440x960                [15:10] */
+       {NULL, 60, 1440, 960, 8733, 240, 88, 30, 1, 152, 3,
+        FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+        FB_VMODE_NONINTERLACED},
+
+       /*      1920x1080       [16:9]  */
+       {NULL, 60, 1920, 1080, 6734, 148, 88, 41, 1, 44, 3,
+        FB_SYNC_VERT_HIGH_ACT,
+        FB_VMODE_NONINTERLACED},
+};
+
+
+
+
+/* no hardware cursor supported under version 2.6.10, kernel bug */
+static int lynxfb_ops_cursor(struct fb_info *info, struct fb_cursor *fbcursor)
+{
+       struct lynxfb_par *par;
+       struct lynxfb_crtc *crtc;
+       struct lynx_cursor *cursor;
+
+       par = info->par;
+       crtc = &par->crtc;
+       cursor = &crtc->cursor;
+
+       if (fbcursor->image.width > cursor->maxW ||
+          fbcursor->image.height > cursor->maxH ||
+          fbcursor->image.depth > 1) {
+               return -ENXIO;
+       }
+
+       cursor->disable(cursor);
+       if (fbcursor->set & FB_CUR_SETSIZE)
+               cursor->setSize(cursor,
+                               fbcursor->image.width,
+                               fbcursor->image.height);
+
+       if (fbcursor->set & FB_CUR_SETPOS)
+               cursor->setPos(cursor,
+                              fbcursor->image.dx - info->var.xoffset,
+                              fbcursor->image.dy - info->var.yoffset);
+
+       if (fbcursor->set & FB_CUR_SETCMAP) {
+               /* 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)|
+                     ((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)|
+                     ((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,
+                               fbcursor->image.data,
+                               fbcursor->mask);
+       }
+
+       if (fbcursor->enable)
+               cursor->enable(cursor);
+
+       return 0;
+}
+
+static void lynxfb_ops_fillrect(struct fb_info *info,
+                               const struct fb_fillrect *region)
+{
+       struct lynxfb_par *par;
+       struct lynx_share *share;
+       unsigned int base, pitch, Bpp, rop;
+       u32 color;
+
+       if (info->state != FBINFO_STATE_RUNNING)
+               return;
+
+       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  */
+       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;
+
+       /*
+        * If not use spin_lock,system will die if user load driver
+        * and immediatly unload driver frequently (dual)
+        */
+       if (share->dual)
+               spin_lock(&share->slock);
+
+       share->accel.de_fillrect(&share->accel,
+                                base, pitch, Bpp,
+                                region->dx, region->dy,
+                                region->width, region->height,
+                                color, rop);
+       if (share->dual)
+               spin_unlock(&share->slock);
+}
+
+static void lynxfb_ops_copyarea(struct fb_info *info,
+                               const struct fb_copyarea *region)
+{
+       struct lynxfb_par *par;
+       struct lynx_share *share;
+       unsigned int base, pitch, Bpp;
+
+       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  */
+       base = par->crtc.oScreen;
+       pitch = info->fix.line_length;
+       Bpp = info->var.bits_per_pixel >> 3;
+
+       /*
+        * If not use spin_lock, system will die if user load driver
+        * and immediatly unload driver frequently (dual)
+        */
+       if (share->dual)
+               spin_lock(&share->slock);
+
+       share->accel.de_copyarea(&share->accel,
+                                base, pitch, region->sx, region->sy,
+                                base, pitch, Bpp, region->dx, region->dy,
+                                region->width, region->height, HW_ROP2_COPY);
+       if (share->dual)
+               spin_unlock(&share->slock);
+}
+
+static void lynxfb_ops_imageblit(struct fb_info *info,
+                                const struct fb_image *image)
+{
+       unsigned int base, pitch, Bpp;
+       unsigned int fgcol, bgcol;
+       struct lynxfb_par *par;
+       struct lynx_share *share;
+
+       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  */
+       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;
+       }
+       return;
+_do_work:
+       /*
+        * If not use spin_lock, system will die if user load driver
+        * and immediatly unload driver frequently (dual)
+        */
+       if (share->dual)
+               spin_lock(&share->slock);
+
+       share->accel.de_imageblit(&share->accel,
+                                 image->data, image->width>>3, 0,
+                                 base, pitch, Bpp,
+                                 image->dx, image->dy,
+                                 image->width, image->height,
+                                 fgcol, bgcol, HW_ROP2_COPY);
+       if (share->dual)
+               spin_unlock(&share->slock);
+}
+
+static int lynxfb_ops_pan_display(struct fb_var_screeninfo *var,
+                                 struct fb_info *info)
+{
+       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;
+}
+
+static int lynxfb_ops_set_par(struct fb_info *info)
+{
+       struct lynxfb_par *par;
+       struct lynx_share *share;
+       struct lynxfb_crtc *crtc;
+       struct lynxfb_output *output;
+       struct fb_var_screeninfo *var;
+       struct fb_fix_screeninfo *fix;
+       int ret;
+       unsigned int line_length;
+
+       if (!info)
+               return -EINVAL;
+
+       ret = 0;
+       par = info->par;
+       share = par->share;
+       crtc = &par->crtc;
+       output = &par->output;
+       var = &info->var;
+       fix = &info->fix;
+
+       /* fix structur is not so FIX ... */
+       line_length = var->xres_virtual * var->bits_per_pixel / 8;
+       line_length = PADDING(crtc->line_pad, line_length);
+       fix->line_length = line_length;
+       pr_err("fix->line_length = %d\n", fix->line_length);
+
+       /* 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:
+               fix->visual = FB_VISUAL_PSEUDOCOLOR;
+               var->red.offset = 0;
+               var->red.length = 8;
+               var->green.offset = 0;
+               var->green.length = 8;
+               var->blue.offset = 0;
+               var->blue.length = 8;
+               var->transp.length = 0;
+               var->transp.offset = 0;
+               break;
+       case 16:
+               var->red.offset = 11;
+               var->red.length = 5;
+               var->green.offset = 5;
+               var->green.length = 6;
+               var->blue.offset = 0;
+               var->blue.length = 5;
+               var->transp.length = 0;
+               var->transp.offset = 0;
+               fix->visual = FB_VISUAL_TRUECOLOR;
+               break;
+       case 24:
+       case 32:
+               var->red.offset = 16;
+               var->red.length = 8;
+               var->green.offset = 8;
+               var->green.length = 8;
+               var->blue.offset = 0;
+               var->blue.length = 8;
+               fix->visual = FB_VISUAL_TRUECOLOR;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       var->height = var->width = -1;
+       var->accel_flags = 0;/*FB_ACCELF_TEXT;*/
+
+       if (ret) {
+               pr_err("pixel bpp format not satisfied\n.");
+               return ret;
+       }
+       ret = crtc->proc_setMode(crtc, var, fix);
+       if (!ret)
+               ret = output->proc_setMode(output, var, fix);
+       return ret;
+}
+
+static inline unsigned int chan_to_field(unsigned int chan,
+                                        struct fb_bitfield *bf)
+{
+       chan &= 0xffff;
+       chan >>= 16 - bf->length;
+       return chan << bf->offset;
+}
+
+#ifdef CONFIG_PM
+static int lynxfb_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+       struct fb_info *info;
+       struct lynx_share *share;
+       int ret;
+
+       if (mesg.event == pdev->dev.power.power_state.event)
+               return 0;
+
+       ret = 0;
+       share = pci_get_drvdata(pdev);
+       switch (mesg.event) {
+       case PM_EVENT_FREEZE:
+       case PM_EVENT_PRETHAW:
+               pdev->dev.power.power_state = mesg;
+               return 0;
+       }
+
+       console_lock();
+       if (mesg.event & PM_EVENT_SLEEP) {
+               info = share->fbinfo[0];
+               if (info)
+                       /* 1 means do suspend */
+                       fb_set_suspend(info, 1);
+               info = share->fbinfo[1];
+               if (info)
+                       /* 1 means do suspend */
+                       fb_set_suspend(info, 1);
+
+               ret = pci_save_state(pdev);
+               if (ret) {
+                       pr_err("error:%d occurred in pci_save_state\n", ret);
+                       return ret;
+               }
+
+               /* set chip to sleep mode */
+               if (share->suspend)
+                       (*share->suspend)(share);
+
+               pci_disable_device(pdev);
+               ret = pci_set_power_state(pdev, pci_choose_state(pdev, mesg));
+               if (ret) {
+                       pr_err("error:%d occurred in pci_set_power_state\n", ret);
+                       return ret;
+               }
+       }
+
+       pdev->dev.power.power_state = mesg;
+       console_unlock();
+       return ret;
+}
+
+static int lynxfb_resume(struct pci_dev *pdev)
+{
+       struct fb_info *info;
+       struct lynx_share *share;
+
+       struct lynxfb_par *par;
+       struct lynxfb_crtc *crtc;
+       struct lynx_cursor *cursor;
+
+       int ret;
+
+
+       ret = 0;
+       share = pci_get_drvdata(pdev);
+
+       console_lock();
+
+       ret = pci_set_power_state(pdev, PCI_D0);
+       if (ret) {
+               pr_err("error:%d occured in pci_set_power_state\n", ret);
+               return ret;
+       }
+
+
+       if (pdev->dev.power.power_state.event != PM_EVENT_FREEZE) {
+               pci_restore_state(pdev);
+               ret = pci_enable_device(pdev);
+               if (ret) {
+                       pr_err("error:%d occured in pci_enable_device\n", ret);
+                       return ret;
+               }
+               pci_set_master(pdev);
+       }
+       if (share->resume)
+               (*share->resume)(share);
+
+       hw_sm750_inithw(share, pdev);
+
+
+       info = share->fbinfo[0];
+
+       if (info) {
+               par = info->par;
+               crtc = &par->crtc;
+               cursor = &crtc->cursor;
+               memset_io(cursor->vstart, 0x0, cursor->size);
+               memset_io(crtc->vScreen, 0x0, crtc->vidmem_size);
+               lynxfb_ops_set_par(info);
+               fb_set_suspend(info, 0);
+       }
+
+       info = share->fbinfo[1];
+
+       if (info) {
+               par = info->par;
+               crtc = &par->crtc;
+               cursor = &crtc->cursor;
+               memset_io(cursor->vstart, 0x0, cursor->size);
+               memset_io(crtc->vScreen, 0x0, crtc->vidmem_size);
+               lynxfb_ops_set_par(info);
+               fb_set_suspend(info, 0);
+       }
+
+
+       console_unlock();
+       return ret;
+}
+#endif
+
+static int lynxfb_ops_check_var(struct fb_var_screeninfo *var,
+                               struct fb_info *info)
+{
+       struct lynxfb_par *par;
+       struct lynxfb_crtc *crtc;
+       struct lynxfb_output *output;
+       struct lynx_share *share;
+       int ret;
+       resource_size_t request;
+
+
+       par = info->par;
+       crtc = &par->crtc;
+       output = &par->output;
+       share = par->share;
+       ret = 0;
+
+       pr_debug("check var:%dx%d-%d\n",
+                var->xres,
+                var->yres,
+                var->bits_per_pixel);
+
+
+       switch (var->bits_per_pixel) {
+       case 8:
+       case 16:
+       case 24: /* support 24 bpp for only lynx712/722/720 */
+       case 32:
+               break;
+       default:
+               pr_err("bpp %d not supported\n", var->bits_per_pixel);
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       switch (var->bits_per_pixel) {
+       case 8:
+               info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+               var->red.offset = 0;
+               var->red.length = 8;
+               var->green.offset = 0;
+               var->green.length = 8;
+               var->blue.offset = 0;
+               var->blue.length = 8;
+               var->transp.length = 0;
+               var->transp.offset = 0;
+               break;
+       case 16:
+               var->red.offset = 11;
+               var->red.length = 5;
+               var->green.offset = 5;
+               var->green.length = 6;
+               var->blue.offset = 0;
+               var->blue.length = 5;
+               var->transp.length = 0;
+               var->transp.offset = 0;
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+               break;
+       case 24:
+       case 32:
+               var->red.offset = 16;
+               var->red.length = 8;
+               var->green.offset = 8;
+               var->green.length = 8;
+               var->blue.offset = 0;
+               var->blue.length = 8;
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       var->height = var->width = -1;
+       var->accel_flags = 0;/* FB_ACCELF_TEXT; */
+
+       /* check if current fb's video memory big enought to hold the onscreen*/
+       request = var->xres_virtual * (var->bits_per_pixel >> 3);
+       /* defaulty crtc->channel go with par->index */
+
+       request = PADDING(crtc->line_pad, request);
+       request = request * var->yres_virtual;
+       if (crtc->vidmem_size < request) {
+               pr_err("not enough video memory for mode\n");
+               return -ENOMEM;
+       }
+
+       ret = output->proc_checkMode(output, var);
+       if (!ret)
+               ret = crtc->proc_checkMode(crtc, var);
+exit:
+       return ret;
+}
+
+
+static int lynxfb_ops_setcolreg(unsigned regno,
+                               unsigned red,
+                               unsigned green,
+                               unsigned blue,
+                               unsigned transp,
+                               struct fb_info *info)
+{
+       struct lynxfb_par *par;
+       struct lynxfb_crtc *crtc;
+       struct fb_var_screeninfo *var;
+       int ret;
+
+       par = info->par;
+       crtc = &par->crtc;
+       var = &info->var;
+       ret = 0;
+
+       if (regno > 256) {
+               pr_err("regno = %d\n", regno);
+               return -EINVAL;
+       }
+
+       if (info->var.grayscale)
+               red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+
+       if (var->bits_per_pixel == 8 &&
+           info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
+               red >>= 8;
+               green >>= 8;
+               blue >>= 8;
+               ret = crtc->proc_setColReg(crtc, regno, red, green, blue);
+               goto exit;
+       }
+
+
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 256) {
+               u32 val;
+
+               if (var->bits_per_pixel == 16 ||
+                   var->bits_per_pixel == 32 ||
+                   var->bits_per_pixel == 24) {
+                       val = chan_to_field(red, &var->red);
+                       val |= chan_to_field(green, &var->green);
+                       val |= chan_to_field(blue, &var->blue);
+                       par->pseudo_palette[regno] = val;
+                       goto exit;
+               }
+       }
+
+       ret = -EINVAL;
+
+exit:
+       return ret;
+}
+
+static int lynxfb_ops_blank(int blank, struct fb_info *info)
+{
+       struct lynxfb_par *par;
+       struct lynxfb_output *output;
+
+       pr_debug("blank = %d.\n", blank);
+       par = info->par;
+       output = &par->output;
+       return output->proc_setBLANK(output, blank);
+}
+
+static int sm750fb_set_drv(struct lynxfb_par *par)
+{
+       int ret;
+       struct lynx_share *share;
+       struct sm750_share *spec_share;
+       struct lynxfb_output *output;
+       struct lynxfb_crtc *crtc;
+
+       ret = 0;
+
+       share = par->share;
+       spec_share = container_of(share, struct sm750_share, share);
+       output = &par->output;
+       crtc = &par->crtc;
+
+       crtc->vidmem_size = (share->dual)?share->vidmem_size>>1:share->vidmem_size;
+       /* setup crtc and output member */
+       spec_share->hwCursor = g_hwcursor;
+
+       crtc->proc_setMode = hw_sm750_crtc_setMode;
+       crtc->proc_checkMode = hw_sm750_crtc_checkMode;
+       crtc->proc_setColReg = hw_sm750_setColReg;
+       crtc->proc_panDisplay = hw_sm750_pan_display;
+       crtc->clear = hw_sm750_crtc_clear;
+       crtc->line_pad = 16;
+       crtc->xpanstep = 8;
+       crtc->ypanstep = 1;
+       crtc->ywrapstep = 0;
+
+       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->clear = hw_sm750_output_clear;
+       /* chip specific phase */
+       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;
+               crtc->channel = sm750_primary;
+               crtc->oScreen = 0;
+               crtc->vScreen = share->pvMem;
+               pr_info("use simul primary mode\n");
+               break;
+       case sm750_simul_sec:
+               output->paths = sm750_pnc;
+               crtc->channel = sm750_secondary;
+               crtc->oScreen = 0;
+               crtc->vScreen = share->pvMem;
+               break;
+       case sm750_dual_normal:
+               if (par->index == 0) {
+                       output->paths = sm750_panel;
+                       crtc->channel = sm750_primary;
+                       crtc->oScreen = 0;
+                       crtc->vScreen = share->pvMem;
+               } else {
+                       output->paths = sm750_crt;
+                       crtc->channel = sm750_secondary;
+                       /* not consider of padding stuffs for oScreen,need fix */
+                       crtc->oScreen = (share->vidmem_size >> 1);
+                       crtc->vScreen = share->pvMem + crtc->oScreen;
+               }
+               break;
+       case sm750_dual_swap:
+               if (par->index == 0) {
+                       output->paths = sm750_panel;
+                       crtc->channel = sm750_secondary;
+                       crtc->oScreen = 0;
+                       crtc->vScreen = share->pvMem;
+               } else {
+                       output->paths = sm750_crt;
+                       crtc->channel = sm750_primary;
+                       /* not consider of padding stuffs for oScreen,need fix */
+                       crtc->oScreen = (share->vidmem_size >> 1);
+                       crtc->vScreen = share->pvMem + crtc->oScreen;
+               }
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static struct fb_ops lynxfb_ops = {
+       .owner = THIS_MODULE,
+       .fb_check_var =  lynxfb_ops_check_var,
+       .fb_set_par = lynxfb_ops_set_par,
+       .fb_setcolreg = lynxfb_ops_setcolreg,
+       .fb_blank = lynxfb_ops_blank,
+       .fb_fillrect = cfb_fillrect,
+       .fb_imageblit = cfb_imageblit,
+       .fb_copyarea = cfb_copyarea,
+       /* cursor */
+       .fb_cursor = lynxfb_ops_cursor,
+};
+
+
+static int lynxfb_set_fbinfo(struct fb_info *info, int index)
+{
+       int i;
+       struct lynxfb_par *par;
+       struct lynx_share *share;
+       struct lynxfb_crtc *crtc;
+       struct lynxfb_output *output;
+       struct fb_var_screeninfo *var;
+       struct fb_fix_screeninfo *fix;
+
+       const struct fb_videomode *pdb[] = {
+               lynx750_ext, NULL, vesa_modes,
+       };
+       int cdb[] = {ARRAY_SIZE(lynx750_ext), 0, VESA_MODEDB_SIZE};
+       static const char *mdb_desc[] = {
+               "driver prepared modes",
+               "kernel prepared default modedb",
+               "kernel HELPERS prepared vesa_modes",
+       };
+
+
+       static const char *fixId[2] = {
+               "sm750_fb1", "sm750_fb2",
+       };
+
+       int ret, line_length;
+
+       ret = 0;
+       par = (struct lynxfb_par *)info->par;
+       share = par->share;
+       crtc = &par->crtc;
+       output = &par->output;
+       var = &info->var;
+       fix = &info->fix;
+
+       /* set index */
+       par->index = index;
+       output->channel = &crtc->channel;
+       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 */
+       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.disable = hw_cursor_disable;
+       crtc->cursor.enable = hw_cursor_enable;
+       crtc->cursor.setColor = hw_cursor_setColor;
+       crtc->cursor.setPos = hw_cursor_setPos;
+       crtc->cursor.setSize = hw_cursor_setSize;
+       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) {
+               lynxfb_ops.fb_cursor = NULL;
+               crtc->cursor.disable(&crtc->cursor);
+       }
+
+
+       /* set info->fbops, must be set before fb_find_mode */
+       if (!share->accel_off) {
+               /* use 2d acceleration */
+               lynxfb_ops.fb_fillrect = lynxfb_ops_fillrect;
+               lynxfb_ops.fb_copyarea = lynxfb_ops_copyarea;
+               lynxfb_ops.fb_imageblit = lynxfb_ops_imageblit;
+       }
+       info->fbops = &lynxfb_ops;
+
+       if (!g_fbmode[index]) {
+               g_fbmode[index] = g_def_fbmode;
+               if (index)
+                       g_fbmode[index] = g_fbmode[0];
+       }
+
+
+       for (i = 0; i < 3; i++) {
+
+               ret = fb_find_mode(var, info, g_fbmode[index],
+                                  pdb[i], cdb[i], NULL, 8);
+
+               if (ret == 1) {
+                       pr_info("success! use specified mode:%s in %s\n",
+                               g_fbmode[index],
+                               mdb_desc[i]);
+                       break;
+               } else if (ret == 2) {
+                       pr_warn("use specified mode:%s in %s,with an ignored refresh rate\n",
+                               g_fbmode[index],
+                               mdb_desc[i]);
+                       break;
+               } else if (ret == 3) {
+                       pr_warn("wanna use default mode\n");
+                       /*break;*/
+               } else if (ret == 4) {
+                       pr_warn("fall back to any valid mode\n");
+               } else {
+                       pr_warn("ret = %d,fb_find_mode failed,with %s\n",
+                               ret,
+                               mdb_desc[i]);
+               }
+       }
+
+       /* some member of info->var had been set by fb_find_mode */
+
+       pr_info("Member of info->var is :\n\
+               xres=%d\n\
+               yres=%d\n\
+               xres_virtual=%d\n\
+               yres_virtual=%d\n\
+               xoffset=%d\n\
+               yoffset=%d\n\
+               bits_per_pixel=%d\n \
+               ...\n",
+               var->xres,
+               var->yres,
+               var->xres_virtual,
+               var->yres_virtual,
+               var->xoffset,
+               var->yoffset,
+               var->bits_per_pixel);
+
+       /* set par */
+       par->info = info;
+
+       /* set info */
+       line_length = PADDING(crtc->line_pad,
+                             (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;
+
+       /* set info->fix */
+       fix->type = FB_TYPE_PACKED_PIXELS;
+       fix->type_aux = 0;
+       fix->xpanstep = crtc->xpanstep;
+       fix->ypanstep = crtc->ypanstep;
+       fix->ywrapstep = crtc->ywrapstep;
+       fix->accel = FB_ACCEL_SMI;
+
+       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,
+        * 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;
+       fix->line_length = line_length;
+       fix->mmio_start = share->vidreg_start;
+       pr_info("fix->mmio_start = %lx\n", fix->mmio_start);
+       fix->mmio_len = share->vidreg_size;
+       pr_info("fix->mmio_len = %x\n", fix->mmio_len);
+       switch (var->bits_per_pixel) {
+       case 8:
+               fix->visual = FB_VISUAL_PSEUDOCOLOR;
+               break;
+       case 16:
+       case 32:
+               fix->visual = FB_VISUAL_TRUECOLOR;
+               break;
+       }
+
+       /* set var */
+       var->activate = FB_ACTIVATE_NOW;
+       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",
+                info->cmap.start, info->cmap.len,
+                info->cmap.red, info->cmap.green, info->cmap.blue,
+                info->cmap.transp);
+
+       ret = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (ret < 0) {
+               pr_err("Could not allcate memory for cmap.\n");
+               goto exit;
+       }
+
+       pr_debug("#2 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);
+
+exit:
+       lynxfb_ops_check_var(var, info);
+       return ret;
+}
+
+/*     chip specific g_option configuration routine */
+static void sm750fb_setup(struct lynx_share *share, char *src)
+{
+       struct sm750_share *spec_share;
+       char *opt;
+#ifdef CAP_EXPENSION
+       char *exp_res;
+#endif
+       int swap;
+
+
+       spec_share = container_of(share, struct sm750_share, share);
+#ifdef CAP_EXPENSIION
+       exp_res = NULL;
+#endif
+       swap = 0;
+
+       spec_share->state.initParm.chip_clk = 0;
+       spec_share->state.initParm.mem_clk = 0;
+       spec_share->state.initParm.master_clk = 0;
+       spec_share->state.initParm.powerMode = 0;
+       spec_share->state.initParm.setAllEngOff = 0;
+       spec_share->state.initParm.resetMemory = 1;
+
+       /* defaultly turn g_hwcursor on for both view */
+       g_hwcursor = 3;
+
+       if (!src || !*src) {
+               pr_warn("no specific g_option.\n");
+               goto NO_PARAM;
+       }
+
+       while ((opt = strsep(&src, ":")) != NULL && *opt != 0) {
+               pr_err("opt=%s\n", opt);
+               pr_err("src=%s\n", src);
+
+               if (!strncmp(opt, "swap", strlen("swap")))
+                       swap = 1;
+               else if (!strncmp(opt, "nocrt", strlen("nocrt")))
+                       spec_share->state.nocrt = 1;
+               else if (!strncmp(opt, "36bit", strlen("36bit")))
+                       spec_share->state.pnltype = sm750_doubleTFT;
+               else if (!strncmp(opt, "18bit", strlen("18bit")))
+                       spec_share->state.pnltype = sm750_dualTFT;
+               else if (!strncmp(opt, "24bit", strlen("24bit")))
+                       spec_share->state.pnltype = sm750_24TFT;
+#ifdef CAP_EXPANSION
+               else if (!strncmp(opt, "exp:", strlen("exp:")))
+                       exp_res = opt + strlen("exp:");
+#endif
+               else if (!strncmp(opt, "nohwc0", strlen("nohwc0")))
+                       g_hwcursor &= ~0x1;
+               else if (!strncmp(opt, "nohwc1", strlen("nohwc1")))
+                       g_hwcursor &= ~0x2;
+               else if (!strncmp(opt, "nohwc", strlen("nohwc")))
+                       g_hwcursor = 0;
+               else {
+                       if (!g_fbmode[0]) {
+                               g_fbmode[0] = opt;
+                               pr_info("find fbmode0 : %s\n", g_fbmode[0]);
+                       } else if (!g_fbmode[1]) {
+                               g_fbmode[1] = opt;
+                               pr_info("find fbmode1 : %s\n", g_fbmode[1]);
+                       } else {
+                               pr_warn("How many view you wann set?\n");
+                       }
+               }
+       }
+#ifdef CAP_EXPANSION
+       if (getExpRes(exp_res,
+                     &spec_share->state.xLCD,
+                     &spec_share->state.yLCD)) {
+               /* seems exp_res is not valid */
+               spec_share->state.xLCD = spec_share->state.yLCD = 0;
+       }
+#endif
+
+NO_PARAM:
+       if (share->revid != SM750LE_REVISION_ID) {
+               if (share->dual) {
+                       if (swap)
+                               spec_share->state.dataflow = sm750_dual_swap;
+                       else
+                               spec_share->state.dataflow = sm750_dual_normal;
+               } else {
+                       if (swap)
+                               spec_share->state.dataflow = sm750_simul_sec;
+                       else
+                               spec_share->state.dataflow = sm750_simul_pri;
+               }
+       } else {
+               /* SM750LE only have one crt channel */
+               spec_share->state.dataflow = sm750_simul_sec;
+               /* sm750le do not have complex attributes */
+               spec_share->state.nocrt = 0;
+       }
+}
+
+static int lynxfb_pci_probe(struct pci_dev *pdev,
+                           const struct pci_device_id * ent)
+{
+       struct fb_info *info[] = {NULL, NULL};
+       struct lynx_share *share = NULL;
+
+       struct sm750_share *spec_share = NULL;
+       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 */
+       spec_offset = offsetof(struct sm750_share, share);
+
+       spec_share = kzalloc(sizeof(*spec_share), GFP_KERNEL);
+       if (!spec_share) {
+               pr_err("Could not allocate memory for share.\n");
+               goto err_share;
+       }
+
+       /* setting share structure */
+       share = (struct lynx_share *)(&(spec_share->share));
+       share->fbinfo[0] = share->fbinfo[1] = NULL;
+       share->devid = pdev->device;
+       share->revid = pdev->revision;
+
+       pr_info("share->revid = %02x\n", share->revid);
+       share->pdev = pdev;
+#ifdef CONFIG_MTRR
+       share->mtrr_off = g_nomtrr;
+       share->mtrr.vram = 0;
+       share->mtrr.vram_added = 0;
+#endif
+       share->accel_off = g_noaccel;
+       share->dual = g_dualview;
+       spin_lock_init(&share->slock);
+
+       if (!share->accel_off) {
+               /* 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 */
+               share->accel.de_init = hw_de_init;
+               share->accel.de_fillrect = hw_fillrect;
+               share->accel.de_copyarea = hw_copyarea;
+               share->accel.de_imageblit = hw_imageblit;
+               pr_info("enable 2d acceleration\n");
+       } else {
+               pr_info("disable 2d acceleration\n");
+       }
+
+       /* call chip specific setup routine  */
+       sm750fb_setup(share, g_settings);
+
+       /* call chip specific mmap routine */
+       if (hw_sm750_map(share, pdev)) {
+               pr_err("Memory map failed\n");
+               goto err_map;
+       }
+
+#ifdef CONFIG_MTRR
+       if (!share->mtrr_off) {
+               pr_info("enable mtrr\n");
+               share->mtrr.vram = mtrr_add(share->vidmem_start,
+                                           share->vidmem_size,
+                                           MTRR_TYPE_WRCOMB, 1);
+
+               if (share->mtrr.vram < 0) {
+                       /* don't block driver with the failure of MTRR */
+                       pr_err("Unable to setup MTRR.\n");
+               } else {
+                       share->mtrr.vram_added = 1;
+                       pr_info("MTRR added succesfully\n");
+               }
+       }
+#endif
+
+       memset_io(share->pvMem, 0, share->vidmem_size);
+
+       pr_info("sm%3x mmio address = %p\n", share->devid, share->pvReg);
+
+       pci_set_drvdata(pdev, share);
+
+       /* call chipInit routine */
+       hw_sm750_inithw(share, pdev);
+
+       /* allocate frame buffer info structor according to g_dualview */
+       fbidx = 0;
+ALLOC_FB:
+       info[fbidx] = framebuffer_alloc(sizeof(struct lynxfb_par), &pdev->dev);
+       if (!info[fbidx]) {
+               pr_err("Could not allocate framebuffer #%d.\n", fbidx);
+               if (fbidx == 0)
+                       goto err_info0_alloc;
+               else
+                       goto err_info1_alloc;
+       } else {
+               struct lynxfb_par *par;
+               int errno;
+
+               pr_info("framebuffer #%d alloc okay\n", fbidx);
+               share->fbinfo[fbidx] = info[fbidx];
+               par = info[fbidx]->par;
+               par->share = share;
+
+               /* set fb_info structure */
+               if (lynxfb_set_fbinfo(info[fbidx], fbidx)) {
+                       pr_err("Failed to initial fb_info #%d.\n", fbidx);
+                       if (fbidx == 0)
+                               goto err_info0_set;
+                       else
+                               goto err_info1_set;
+               }
+
+               /* register frame buffer */
+               pr_info("Ready to register framebuffer #%d.\n", fbidx);
+               errno = register_framebuffer(info[fbidx]);
+               if (errno < 0) {
+                       pr_err("Failed to register fb_info #%d. err %d\n",
+                              fbidx,
+                              errno);
+                       if (fbidx == 0)
+                               goto err_register0;
+                       else
+                               goto err_register1;
+               }
+               pr_info("Accomplished register framebuffer #%d.\n", fbidx);
+       }
+
+       /* no dual view by far */
+       fbidx++;
+       if (share->dual && fbidx < 2)
+               goto ALLOC_FB;
+
+       return 0;
+
+err_register1:
+err_info1_set:
+       framebuffer_release(info[1]);
+err_info1_alloc:
+       unregister_framebuffer(info[0]);
+err_register0:
+err_info0_set:
+       framebuffer_release(info[0]);
+err_info0_alloc:
+err_map:
+       kfree(spec_share);
+err_share:
+err_enable:
+       return -ENODEV;
+}
+
+static void __exit lynxfb_pci_remove(struct pci_dev *pdev)
+{
+       struct fb_info *info;
+       struct lynx_share *share;
+       void *spec_share;
+       struct lynxfb_par *par;
+       int cnt;
+
+       cnt = 2;
+       share = pci_get_drvdata(pdev);
+
+       while (cnt-- > 0) {
+               info = share->fbinfo[cnt];
+               if (!info)
+                       continue;
+               par = info->par;
+
+               unregister_framebuffer(info);
+               /* clean crtc & output allocations */
+               par->crtc.clear(&par->crtc);
+               par->output.clear(&par->output);
+               /* release frame buffer */
+               framebuffer_release(info);
+       }
+#ifdef CONFIG_MTRR
+       if (share->mtrr.vram_added)
+               mtrr_del(share->mtrr.vram,
+                        share->vidmem_start,
+                        share->vidmem_size);
+#endif
+
+       iounmap(share->pvReg);
+       iounmap(share->pvMem);
+       spec_share = container_of(share, struct sm750_share, share);
+       kfree(g_settings);
+       kfree(spec_share);
+       pci_set_drvdata(pdev, NULL);
+}
+
+static int __init lynxfb_setup(char *options)
+{
+       int len;
+       char *opt, *tmp;
+
+
+       if (!options || !*options) {
+               pr_warn("no options.\n");
+               return 0;
+       }
+
+       pr_info("options:%s\n", options);
+
+       len = strlen(options) + 1;
+       g_settings = kzalloc(len, GFP_KERNEL);
+       if (!g_settings)
+               return -ENOMEM;
+
+       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.
+               */
+       while ((opt = strsep(&options, ":")) != NULL) {
+               /* options that mean for any lynx chips are configured here */
+               if (!strncmp(opt, "noaccel", strlen("noaccel")))
+                       g_noaccel = 1;
+#ifdef CONFIG_MTRR
+               else if (!strncmp(opt, "nomtrr", strlen("nomtrr")))
+                       g_nomtrr = 1;
+#endif
+               else if (!strncmp(opt, "dual", strlen("dual")))
+                       g_dualview = 1;
+               else {
+                       strcat(tmp, opt);
+                       tmp += strlen(opt);
+                       if (options != NULL)
+                               *tmp++ = ':';
+                       else
+                               *tmp++ = 0;
+               }
+       }
+
+       /* misc g_settings are transport to chip specific routines */
+       pr_info("parameter left for chip specific analysis:%s\n", g_settings);
+       return 0;
+}
+
+static struct pci_device_id smi_pci_table[] = {
+       { PCI_DEVICE(0x126f, 0x0750), },
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, smi_pci_table);
+
+static struct pci_driver lynxfb_driver = {
+       .name =         "sm750fb",
+       .id_table =     smi_pci_table,
+       .probe =        lynxfb_pci_probe,
+       .remove =       lynxfb_pci_remove,
+#ifdef CONFIG_PM
+       .suspend = lynxfb_suspend,
+       .resume = lynxfb_resume,
+#endif
+};
+
+
+static int __init lynxfb_init(void)
+{
+       char *option;
+       int ret;
+
+#ifdef MODULE
+       option = g_option;
+#else
+       if (fb_get_options("sm750fb", &option))
+               return -ENODEV;
+#endif
+
+       lynxfb_setup(option);
+       ret = pci_register_driver(&lynxfb_driver);
+       return ret;
+}
+module_init(lynxfb_init);
+
+static void __exit lynxfb_exit(void)
+{
+       pci_unregister_driver(&lynxfb_driver);
+}
+module_exit(lynxfb_exit);
+
+module_param(g_option, charp, S_IRUGO);
+
+MODULE_PARM_DESC(g_option,
+                "\n\t\tCommon options:\n"
+                "\t\tnoaccel:disable 2d capabilities\n"
+                "\t\tnomtrr:disable MTRR attribute for video memory\n"
+                "\t\tdualview:dual frame buffer feature enabled\n"
+                "\t\tnohwc:disable hardware cursor\n"
+                "\t\tUsual example:\n"
+                "\t\tinsmod ./sm750fb.ko g_option=\"noaccel,nohwc,1280x1024-8@60\"\n"
+                );
+
+MODULE_AUTHOR("monk liu <monk.liu@siliconmotion.com>");
+MODULE_AUTHOR("Sudip Mukherjee <sudip@vectorindia.org>");
+MODULE_DESCRIPTION("Frame buffer driver for SM750 chipset");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h
new file mode 100644 (file)
index 0000000..0847d2b
--- /dev/null
@@ -0,0 +1,186 @@
+#ifndef LYNXDRV_H_
+#define LYNXDRV_H_
+
+
+
+#define FB_ACCEL_SMI 0xab
+/* please use revision id to distinguish sm750le and sm750*/
+#define SPC_SM750      0
+
+//#define SPC_SM750LE 8
+
+#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)))
+extern int smi_indent;
+
+
+struct lynx_accel{
+       /* base virtual address of DPR registers */
+       volatile unsigned char __iomem * dprBase;
+       /* base virtual address of de data port */
+       volatile unsigned char __iomem * dpPortBase;
+
+       /* function fointers */
+       void (*de_init)(struct lynx_accel *);
+
+       int (*de_wait)(void);/* see if hardware ready to work */
+
+       int (*de_fillrect)(struct lynx_accel *,u32,u32,u32,
+                                                       u32,u32,u32,u32,u32,u32);
+
+       int (*de_copyarea)(struct lynx_accel *,u32,u32,u32,u32,
+                                               u32,u32,u32,u32,
+                                               u32,u32,u32,u32);
+
+       int (*de_imageblit)(struct lynx_accel *,const char *,u32,u32,u32,
+                                               u32,u32,u32,u32,u32,u32,u32,u32,u32);
+
+};
+
+/*     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{
+       /* common members */
+       u16 devid;
+       u8 revid;
+       struct pci_dev * pdev;
+       struct fb_info * fbinfo[2];
+       struct lynx_accel accel;
+       int accel_off;
+       int dual;
+#ifdef CONFIG_MTRR
+               int mtrr_off;
+               struct{
+                       int vram;
+                       int vram_added;
+               }mtrr;
+#endif
+       /* all smi graphic adaptor got below attributes */
+       unsigned long vidmem_start;
+       unsigned long vidreg_start;
+       __u32 vidmem_size;
+       __u32 vidreg_size;
+       void __iomem * pvReg;
+       unsigned char __iomem * pvMem;
+       /* locks*/
+       spinlock_t slock;
+       /* function pointers */
+       void (*suspend)(struct lynx_share*);
+       void (*resume)(struct lynx_share*);
+};
+
+struct lynx_cursor{
+       /* cursor width ,height and size */
+       int w;
+       int h;
+       int size;
+       /* hardware limitation */
+       int maxW;
+       int maxH;
+       /* base virtual address and offset  of cursor image */
+       char __iomem * vstart;
+       int offset;
+       /* mmio addr of hw cursor */
+       volatile char __iomem * mmio;
+       /* the lynx_share of this adaptor */
+       struct lynx_share * share;
+       /* proc_routines */
+       void (*enable)(struct lynx_cursor *);
+       void (*disable)(struct lynx_cursor *);
+       void (*setSize)(struct lynx_cursor *,int,int);
+       void (*setPos)(struct lynx_cursor *,int,int);
+       void (*setColor)(struct lynx_cursor *,u32,u32);
+       void (*setData)(struct lynx_cursor *,u16,const u8*,const u8*);
+};
+
+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
+       int oScreen;//onscreen address offset in vidmem
+       int channel;/* which channel this crtc stands for*/
+       resource_size_t vidmem_size;/* this view's video memory max size */
+
+       /* below attributes belong to info->fix, their value depends on specific adaptor*/
+       u16 line_pad;/* padding information:0,1,2,4,8,16,... */
+       u16 xpanstep;
+       u16 ypanstep;
+       u16 ywrapstep;
+
+       void * priv;
+
+       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_panDisplay)(struct lynxfb_crtc *,
+                              const struct fb_var_screeninfo *,
+                              const struct fb_info *);
+       /* cursor information */
+       struct lynx_cursor cursor;
+};
+
+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
+       */
+
+       int * 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*,
+                                               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*);
+};
+
+struct lynxfb_par{
+       /* either 0 or 1 for dual head adaptor,0 is the older one registered */
+       int index;
+       unsigned int pseudo_palette[256];
+       struct lynxfb_crtc crtc;
+       struct lynxfb_output output;
+       struct fb_info * info;
+       struct lynx_share * share;
+};
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+
+#define PS_TO_HZ(ps)   \
+                       ({      \
+                       unsigned long long hz = 1000*1000*1000*1000ULL; \
+                       do_div(hz,ps);  \
+                       (unsigned long)hz;})
+
+static inline unsigned long ps_to_hz(unsigned int psvalue)
+{
+       unsigned long long numerator=1000*1000*1000*1000ULL;
+       /* 10^12 / picosecond period gives frequency in Hz */
+       do_div(numerator, psvalue);
+       return (unsigned long)numerator;
+}
+
+
+#endif
diff --git a/drivers/staging/sm750fb/sm750_accel.c b/drivers/staging/sm750fb/sm750_accel.c
new file mode 100644 (file)
index 0000000..c5a3726
--- /dev/null
@@ -0,0 +1,437 @@
+#include<linux/module.h>
+#include<linux/kernel.h>
+#include<linux/errno.h>
+#include<linux/string.h>
+#include<linux/mm.h>
+#include<linux/slab.h>
+#include<linux/delay.h>
+#include<linux/fb.h>
+#include<linux/ioport.h>
+#include<linux/init.h>
+#include<linux/pci.h>
+#include<linux/vmalloc.h>
+#include<linux/pagemap.h>
+#include <linux/console.h>
+#include<linux/platform_device.h>
+#include<linux/screen_info.h>
+
+#include "sm750.h"
+#include "sm750_accel.h"
+#include "sm750_help.h"
+static inline void write_dpr(struct lynx_accel * accel,int offset,u32 regValue)
+{
+       writel(regValue,accel->dprBase + offset);
+}
+
+static inline u32 read_dpr(struct lynx_accel * accel,int offset)
+{
+       return readl(accel->dprBase + offset);
+}
+
+static inline void write_dpPort(struct lynx_accel * accel,u32 data)
+{
+       writel(data,accel->dpPortBase);
+}
+
+void hw_de_init(struct lynx_accel * accel)
+{
+       /* setup 2d engine registers */
+       u32 reg,clr;
+       
+       write_dpr(accel,DE_MASKS,0xFFFFFFFF);
+
+       /* dpr1c */
+       reg = FIELD_SET(0,DE_STRETCH_FORMAT,PATTERN_XY,NORMAL)|
+               FIELD_VALUE(0,DE_STRETCH_FORMAT,PATTERN_Y,0)|
+               FIELD_VALUE(0,DE_STRETCH_FORMAT,PATTERN_X,0)|
+               FIELD_SET(0,DE_STRETCH_FORMAT,ADDRESSING,XY)|
+               FIELD_VALUE(0,DE_STRETCH_FORMAT,SOURCE_HEIGHT,3);
+
+       clr = FIELD_CLEAR(DE_STRETCH_FORMAT,PATTERN_XY)&
+               FIELD_CLEAR(DE_STRETCH_FORMAT,PATTERN_Y)&
+               FIELD_CLEAR(DE_STRETCH_FORMAT,PATTERN_X)&
+               FIELD_CLEAR(DE_STRETCH_FORMAT,ADDRESSING)&
+               FIELD_CLEAR(DE_STRETCH_FORMAT,SOURCE_HEIGHT);
+
+       /* DE_STRETCH bpp format need be initilized in setMode routine */
+       write_dpr(accel,DE_STRETCH_FORMAT,(read_dpr(accel,DE_STRETCH_FORMAT) & clr) | reg);
+
+       /* disable clipping and transparent */
+       write_dpr(accel,DE_CLIP_TL,0);//dpr2c
+       write_dpr(accel,DE_CLIP_BR,0);//dpr30
+
+       write_dpr(accel,DE_COLOR_COMPARE_MASK,0);//dpr24
+       write_dpr(accel,DE_COLOR_COMPARE,0);
+
+       reg = FIELD_SET(0,DE_CONTROL,TRANSPARENCY,DISABLE)|
+               FIELD_SET(0,DE_CONTROL,TRANSPARENCY_MATCH,OPAQUE)|
+               FIELD_SET(0,DE_CONTROL,TRANSPARENCY_SELECT,SOURCE);
+
+       clr = FIELD_CLEAR(DE_CONTROL,TRANSPARENCY)&
+               FIELD_CLEAR(DE_CONTROL,TRANSPARENCY_MATCH)&
+               FIELD_CLEAR(DE_CONTROL,TRANSPARENCY_SELECT);
+
+       /* dpr0c */
+       write_dpr(accel,DE_CONTROL,(read_dpr(accel,DE_CONTROL)&clr)|reg);
+}
+
+/* set2dformat only be called from setmode functions
+ * but if you need dual framebuffer driver,need call set2dformat
+ * every time you use 2d function */
+
+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);
+       write_dpr(accel,DE_STRETCH_FORMAT,reg);
+}
+
+int hw_fillrect(struct lynx_accel * accel,
+                               u32 base,u32 pitch,u32 Bpp,
+                               u32 x,u32 y,u32 width,u32 height,
+                               u32 color,u32 rop)
+{
+       u32 deCtrl;
+
+       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__);
+               return -1;
+       }
+
+       write_dpr(accel,DE_WINDOW_DESTINATION_BASE,base);//dpr40
+       write_dpr(accel,DE_PITCH,
+                       FIELD_VALUE(0,DE_PITCH,DESTINATION,pitch/Bpp)|
+                       FIELD_VALUE(0,DE_PITCH,SOURCE,pitch/Bpp));//dpr10
+
+       write_dpr(accel,DE_WINDOW_WIDTH,
+                       FIELD_VALUE(0,DE_WINDOW_WIDTH,DESTINATION,pitch/Bpp)|
+                       FIELD_VALUE(0,DE_WINDOW_WIDTH,SOURCE,pitch/Bpp));//dpr44
+
+       write_dpr(accel,DE_FOREGROUND,color);//DPR14
+
+       write_dpr(accel,DE_DESTINATION,
+                       FIELD_SET(0,DE_DESTINATION,WRAP,DISABLE)|
+                       FIELD_VALUE(0,DE_DESTINATION,X,x)|
+                       FIELD_VALUE(0,DE_DESTINATION,Y,y));//dpr4
+
+       write_dpr(accel,DE_DIMENSION,
+                       FIELD_VALUE(0,DE_DIMENSION,X,width)|
+                       FIELD_VALUE(0,DE_DIMENSION,Y_ET,height));//dpr8
+
+       deCtrl =
+               FIELD_SET(0,DE_CONTROL,STATUS,START)|
+               FIELD_SET(0,DE_CONTROL,DIRECTION,LEFT_TO_RIGHT)|
+               FIELD_SET(0,DE_CONTROL,LAST_PIXEL,ON)|
+               FIELD_SET(0,DE_CONTROL,COMMAND,RECTANGLE_FILL)|
+               FIELD_SET(0,DE_CONTROL,ROP_SELECT,ROP2)|
+               FIELD_VALUE(0,DE_CONTROL,ROP,rop);//dpr0xc
+
+       write_dpr(accel,DE_CONTROL,deCtrl);
+       return 0;
+}
+
+int hw_copyarea(
+struct lynx_accel * accel,
+unsigned int sBase,  /* Address of source: offset in frame buffer */
+unsigned int sPitch, /* Pitch value of source surface in BYTE */
+unsigned int sx,
+unsigned int sy,     /* Starting coordinate of source surface */
+unsigned int dBase,  /* Address of destination: offset in frame buffer */
+unsigned int dPitch, /* Pitch value of destination surface in BYTE */
+unsigned int Bpp,    /* Color depth of destination surface */
+unsigned int dx,
+unsigned int dy,     /* Starting coordinate of destination surface */
+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;
+       /* 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().
+    */
+
+    /* 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 convertion.
+    */
+       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
+#endif
+       {
+               write_dpr(accel,DE_PITCH,
+                               FIELD_VALUE(0, DE_PITCH, DESTINATION, (dPitch/Bpp)) |
+                               FIELD_VALUE(0, DE_PITCH, SOURCE,      (sPitch/Bpp)));//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/Bpp)) |
+        FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE,      (sPitch/Bpp)));//dpr3c
+
+       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
+    }
+
+    return 0;
+}
+
+static unsigned int deGetTransparency(struct lynx_accel * accel)
+{
+    unsigned int de_ctrl;
+
+    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);
+
+    return de_ctrl;
+}
+
+int hw_imageblit(struct lynx_accel *accel,
+                const char *pSrcbuf, /* pointer to start of source buffer in system memory */
+                u32 srcDelta,          /* Pitch value (in bytes) of the source buffer, +ive means top down and -ive mean button up */
+                u32 startBit, /* Mono data can start at any bit in a byte, this value should be 0 to 7 */
+                u32 dBase,    /* Address of destination: offset in frame buffer */
+                u32 dPitch,   /* Pitch value of destination surface in BYTE */
+                u32 bytePerPixel,      /* Color depth of destination surface */
+                u32 dx,
+                u32 dy,       /* Starting coordinate of destination surface */
+                u32 width,
+                u32 height,   /* width and height of rectange in pixel value */
+                u32 fColor,   /* Foreground color (corresponding to a 1 in the monochrome data */
+                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)
+    {
+//             inf_msg("*** ImageBlit return -1 ***\n");
+        return -1;
+    }
+
+    /* 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 convertion.
+    */
+       if(bytePerPixel == 3 ){
+               dx *= 3;
+               width *= 3;
+               startBit *= 3;
+               write_dpr(accel,DE_PITCH,
+                               FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
+                               FIELD_VALUE(0, DE_PITCH, SOURCE,      dPitch));//dpr10
+
+       }
+       else
+#endif
+       {
+               write_dpr(accel,DE_PITCH,
+                               FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch/bytePerPixel) |
+                               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)));
+
+    /* 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_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);
+
+       de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2)         |
+               FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2)    |
+               FIELD_SET(0, DE_CONTROL, COMMAND, HOST_WRITE) |
+               FIELD_SET(0, DE_CONTROL, HOST, MONO)          |
+               FIELD_SET(0, DE_CONTROL, STATUS, START);
+
+       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;
+}
+
diff --git a/drivers/staging/sm750fb/sm750_accel.h b/drivers/staging/sm750fb/sm750_accel.h
new file mode 100644 (file)
index 0000000..3ee0bd8
--- /dev/null
@@ -0,0 +1,275 @@
+#ifndef ACCEL_H__
+#define ACCEL_H__
+
+#define HW_ROP2_COPY 0xc
+#define HW_ROP2_XOR 0x6
+
+/* 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
+/* for sm712,de_base is at mmreg_32kb */
+#define DE_BASE_ADDR_TYPE2  0x8000
+/* for sm722,de_base is at mmreg_0 */
+#define DE_BASE_ADDR_TYPE3 0
+
+/* type1 data port address is at mmreg_0x110000*/
+#define DE_PORT_ADDR_TYPE1 0x110000
+/* for sm712,data port address is at mmreg_0 */
+#define DE_PORT_ADDR_TYPE2 0x100000
+/* for sm722,data port address is at mmreg_1mb */
+#define DE_PORT_ADDR_TYPE3 0x100000
+
+#define DE_SOURCE                                       0x0
+#define DE_SOURCE_WRAP                                  31:31
+#define DE_SOURCE_WRAP_DISABLE                          0
+#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_DESTINATION                                  0x4
+#define DE_DESTINATION_WRAP                             31:31
+#define DE_DESTINATION_WRAP_DISABLE                     0
+#define DE_DESTINATION_WRAP_ENABLE                      1
+#define DE_DESTINATION_X                                28:16
+#define DE_DESTINATION_Y                                15:0
+
+#define DE_DIMENSION                                    0x8
+#define DE_DIMENSION_X                                  28:16
+#define DE_DIMENSION_Y_ET                               15:0
+
+#define DE_CONTROL                                      0xC
+#define DE_CONTROL_STATUS                               31:31
+#define DE_CONTROL_STATUS_STOP                          0
+#define DE_CONTROL_STATUS_START                         1
+#define DE_CONTROL_PATTERN                              30:30
+#define DE_CONTROL_PATTERN_MONO                         0
+#define DE_CONTROL_PATTERN_COLOR                        1
+#define DE_CONTROL_UPDATE_DESTINATION_X                 29:29
+#define DE_CONTROL_UPDATE_DESTINATION_X_DISABLE         0
+#define DE_CONTROL_UPDATE_DESTINATION_X_ENABLE          1
+#define DE_CONTROL_QUICK_START                          28:28
+#define DE_CONTROL_QUICK_START_DISABLE                  0
+#define DE_CONTROL_QUICK_START_ENABLE                   1
+#define DE_CONTROL_DIRECTION                            27:27
+#define DE_CONTROL_DIRECTION_LEFT_TO_RIGHT              0
+#define DE_CONTROL_DIRECTION_RIGHT_TO_LEFT              1
+#define DE_CONTROL_MAJOR                                26:26
+#define DE_CONTROL_MAJOR_X                              0
+#define DE_CONTROL_MAJOR_Y                              1
+#define DE_CONTROL_STEP_X                               25:25
+#define DE_CONTROL_STEP_X_POSITIVE                      1
+#define DE_CONTROL_STEP_X_NEGATIVE                      0
+#define DE_CONTROL_STEP_Y                               24:24
+#define DE_CONTROL_STEP_Y_POSITIVE                      1
+#define DE_CONTROL_STEP_Y_NEGATIVE                      0
+#define DE_CONTROL_STRETCH                              23:23
+#define DE_CONTROL_STRETCH_DISABLE                      0
+#define DE_CONTROL_STRETCH_ENABLE                       1
+#define DE_CONTROL_HOST                                 22:22
+#define DE_CONTROL_HOST_COLOR                           0
+#define DE_CONTROL_HOST_MONO                            1
+#define DE_CONTROL_LAST_PIXEL                           21:21
+#define DE_CONTROL_LAST_PIXEL_OFF                       0
+#define DE_CONTROL_LAST_PIXEL_ON                        1
+#define DE_CONTROL_COMMAND                              20:16
+#define DE_CONTROL_COMMAND_BITBLT                       0
+#define DE_CONTROL_COMMAND_RECTANGLE_FILL               1
+#define DE_CONTROL_COMMAND_DE_TILE                      2
+#define DE_CONTROL_COMMAND_TRAPEZOID_FILL               3
+#define DE_CONTROL_COMMAND_ALPHA_BLEND                  4
+#define DE_CONTROL_COMMAND_RLE_STRIP                    5
+#define DE_CONTROL_COMMAND_SHORT_STROKE                 6
+#define DE_CONTROL_COMMAND_LINE_DRAW                    7
+#define DE_CONTROL_COMMAND_HOST_WRITE                   8
+#define DE_CONTROL_COMMAND_HOST_READ                    9
+#define DE_CONTROL_COMMAND_HOST_WRITE_BOTTOM_UP         10
+#define DE_CONTROL_COMMAND_ROTATE                       11
+#define DE_CONTROL_COMMAND_FONT                         12
+#define DE_CONTROL_COMMAND_TEXTURE_LOAD                 15
+#define DE_CONTROL_ROP_SELECT                           15:15
+#define DE_CONTROL_ROP_SELECT_ROP3                      0
+#define DE_CONTROL_ROP_SELECT_ROP2                      1
+#define DE_CONTROL_ROP2_SOURCE                          14:14
+#define DE_CONTROL_ROP2_SOURCE_BITMAP                   0
+#define DE_CONTROL_ROP2_SOURCE_PATTERN                  1
+#define DE_CONTROL_MONO_DATA                            13:12
+#define DE_CONTROL_MONO_DATA_NOT_PACKED                 0
+#define DE_CONTROL_MONO_DATA_8_PACKED                   1
+#define DE_CONTROL_MONO_DATA_16_PACKED                  2
+#define DE_CONTROL_MONO_DATA_32_PACKED                  3
+#define DE_CONTROL_REPEAT_ROTATE                        11:11
+#define DE_CONTROL_REPEAT_ROTATE_DISABLE                0
+#define DE_CONTROL_REPEAT_ROTATE_ENABLE                 1
+#define DE_CONTROL_TRANSPARENCY_MATCH                   10:10
+#define DE_CONTROL_TRANSPARENCY_MATCH_OPAQUE            0
+#define DE_CONTROL_TRANSPARENCY_MATCH_TRANSPARENT       1
+#define DE_CONTROL_TRANSPARENCY_SELECT                  9:9
+#define DE_CONTROL_TRANSPARENCY_SELECT_SOURCE           0
+#define DE_CONTROL_TRANSPARENCY_SELECT_DESTINATION      1
+#define DE_CONTROL_TRANSPARENCY                         8:8
+#define DE_CONTROL_TRANSPARENCY_DISABLE                 0
+#define DE_CONTROL_TRANSPARENCY_ENABLE                  1
+#define DE_CONTROL_ROP                                  7:0
+
+// Pseudo fields.
+
+#define DE_CONTROL_SHORT_STROKE_DIR                     27:24
+#define DE_CONTROL_SHORT_STROKE_DIR_225                 0
+#define DE_CONTROL_SHORT_STROKE_DIR_135                 1
+#define DE_CONTROL_SHORT_STROKE_DIR_315                 2
+#define DE_CONTROL_SHORT_STROKE_DIR_45                  3
+#define DE_CONTROL_SHORT_STROKE_DIR_270                 4
+#define DE_CONTROL_SHORT_STROKE_DIR_90                  5
+#define DE_CONTROL_SHORT_STROKE_DIR_180                 8
+#define DE_CONTROL_SHORT_STROKE_DIR_0                   10
+#define DE_CONTROL_ROTATION                             25:24
+#define DE_CONTROL_ROTATION_0                           0
+#define DE_CONTROL_ROTATION_270                         1
+#define DE_CONTROL_ROTATION_90                          2
+#define DE_CONTROL_ROTATION_180                         3
+
+#define DE_PITCH                                        0x000010
+#define DE_PITCH_DESTINATION                            28:16
+#define DE_PITCH_SOURCE                                 12:0
+
+#define DE_FOREGROUND                                   0x000014
+#define DE_FOREGROUND_COLOR                             31:0
+
+#define DE_BACKGROUND                                   0x000018
+#define DE_BACKGROUND_COLOR                             31:0
+
+#define DE_STRETCH_FORMAT                               0x00001C
+#define DE_STRETCH_FORMAT_PATTERN_XY                    30:30
+#define DE_STRETCH_FORMAT_PATTERN_XY_NORMAL             0
+#define DE_STRETCH_FORMAT_PATTERN_XY_OVERWRITE          1
+#define DE_STRETCH_FORMAT_PATTERN_Y                     29:27
+#define DE_STRETCH_FORMAT_PATTERN_X                     25:23
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT                  21:20
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT_8                0
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT_16               1
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT_32               2
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT_24               3
+
+#define DE_STRETCH_FORMAT_ADDRESSING                    19:16
+#define DE_STRETCH_FORMAT_ADDRESSING_XY                 0
+#define DE_STRETCH_FORMAT_ADDRESSING_LINEAR             15
+#define DE_STRETCH_FORMAT_SOURCE_HEIGHT                 11:0
+
+#define DE_COLOR_COMPARE                                0x000020
+#define DE_COLOR_COMPARE_COLOR                          23:0
+
+#define DE_COLOR_COMPARE_MASK                           0x000024
+#define DE_COLOR_COMPARE_MASK_MASKS                     23:0
+
+#define DE_MASKS                                        0x000028
+#define DE_MASKS_BYTE_MASK                              31:16
+#define DE_MASKS_BIT_MASK                               15:0
+
+#define DE_CLIP_TL                                      0x00002C
+#define DE_CLIP_TL_TOP                                  31:16
+#define DE_CLIP_TL_STATUS                               13:13
+#define DE_CLIP_TL_STATUS_DISABLE                       0
+#define DE_CLIP_TL_STATUS_ENABLE                        1
+#define DE_CLIP_TL_INHIBIT                              12:12
+#define DE_CLIP_TL_INHIBIT_OUTSIDE                      0
+#define DE_CLIP_TL_INHIBIT_INSIDE                       1
+#define DE_CLIP_TL_LEFT                                 11:0
+
+#define DE_CLIP_BR                                      0x000030
+#define DE_CLIP_BR_BOTTOM                               31:16
+#define DE_CLIP_BR_RIGHT                                12:0
+
+#define DE_MONO_PATTERN_LOW                             0x000034
+#define DE_MONO_PATTERN_LOW_PATTERN                     31:0
+
+#define DE_MONO_PATTERN_HIGH                            0x000038
+#define DE_MONO_PATTERN_HIGH_PATTERN                    31:0
+
+#define DE_WINDOW_WIDTH                                 0x00003C
+#define DE_WINDOW_WIDTH_DESTINATION                     28:16
+#define DE_WINDOW_WIDTH_SOURCE                          12:0
+
+#define DE_WINDOW_SOURCE_BASE                           0x000040
+#define DE_WINDOW_SOURCE_BASE_EXT                       27:27
+#define DE_WINDOW_SOURCE_BASE_EXT_LOCAL                 0
+#define DE_WINDOW_SOURCE_BASE_EXT_EXTERNAL              1
+#define DE_WINDOW_SOURCE_BASE_CS                        26:26
+#define DE_WINDOW_SOURCE_BASE_CS_0                      0
+#define DE_WINDOW_SOURCE_BASE_CS_1                      1
+#define DE_WINDOW_SOURCE_BASE_ADDRESS                   25:0
+
+#define DE_WINDOW_DESTINATION_BASE                      0x000044
+#define DE_WINDOW_DESTINATION_BASE_EXT                  27:27
+#define DE_WINDOW_DESTINATION_BASE_EXT_LOCAL            0
+#define DE_WINDOW_DESTINATION_BASE_EXT_EXTERNAL         1
+#define DE_WINDOW_DESTINATION_BASE_CS                   26:26
+#define DE_WINDOW_DESTINATION_BASE_CS_0                 0
+#define DE_WINDOW_DESTINATION_BASE_CS_1                 1
+#define DE_WINDOW_DESTINATION_BASE_ADDRESS              25:0
+
+#define DE_ALPHA                                        0x000048
+#define DE_ALPHA_VALUE                                  7:0
+
+#define DE_WRAP                                         0x00004C
+#define DE_WRAP_X                                       31:16
+#define DE_WRAP_Y                                       15:0
+
+#define DE_STATUS                                       0x000050
+#define DE_STATUS_CSC                                   1:1
+#define DE_STATUS_CSC_CLEAR                             0
+#define DE_STATUS_CSC_NOT_ACTIVE                        0
+#define DE_STATUS_CSC_ACTIVE                            1
+#define DE_STATUS_2D                                    0:0
+#define DE_STATUS_2D_CLEAR                              0
+#define DE_STATUS_2D_NOT_ACTIVE                         0
+#define DE_STATUS_2D_ACTIVE                             1
+
+
+
+/* blt direction */
+#define TOP_TO_BOTTOM 0
+#define LEFT_TO_RIGHT 0
+#define BOTTOM_TO_TOP 1
+#define RIGHT_TO_LEFT 1
+
+void hw_set2dformat(struct lynx_accel * accel,int fmt);
+
+void hw_de_init(struct lynx_accel * accel);
+
+int hw_fillrect(struct lynx_accel * accel,
+                               u32 base,u32 pitch,u32 Bpp,
+                               u32 x,u32 y,u32 width,u32 height,
+                               u32 color,u32 rop);
+
+int hw_copyarea(
+struct lynx_accel * accel,
+unsigned int sBase,  /* Address of source: offset in frame buffer */
+unsigned int sPitch, /* Pitch value of source surface in BYTE */
+unsigned int sx,
+unsigned int sy,     /* Starting coordinate of source surface */
+unsigned int dBase,  /* Address of destination: offset in frame buffer */
+unsigned int dPitch, /* Pitch value of destination surface in BYTE */
+unsigned int bpp,    /* Color depth of destination surface */
+unsigned int dx,
+unsigned int dy,     /* Starting coordinate of destination surface */
+unsigned int width,
+unsigned int height, /* width and height of rectangle in pixel value */
+unsigned int rop2);
+
+int hw_imageblit(struct lynx_accel *accel,
+                const char *pSrcbuf, /* pointer to start of source buffer in system memory */
+                u32 srcDelta,          /* Pitch value (in bytes) of the source buffer, +ive means top down and -ive mean button up */
+                u32 startBit, /* Mono data can start at any bit in a byte, this value should be 0 to 7 */
+                u32 dBase,    /* Address of destination: offset in frame buffer */
+                u32 dPitch,   /* Pitch value of destination surface in BYTE */
+                u32 bytePerPixel,      /* Color depth of destination surface */
+                u32 dx,
+                u32 dy,       /* Starting coordinate of destination surface */
+                u32 width,
+                u32 height,   /* width and height of rectange in pixel value */
+                u32 fColor,   /* Foreground color (corresponding to a 1 in the monochrome data */
+                u32 bColor,   /* Background color (corresponding to a 0 in the monochrome data */
+                u32 rop2);
+#endif
diff --git a/drivers/staging/sm750fb/sm750_cursor.c b/drivers/staging/sm750fb/sm750_cursor.c
new file mode 100644 (file)
index 0000000..68d5cbc
--- /dev/null
@@ -0,0 +1,251 @@
+#include<linux/module.h>
+#include<linux/kernel.h>
+#include<linux/errno.h>
+#include<linux/string.h>
+#include<linux/mm.h>
+#include<linux/slab.h>
+#include<linux/delay.h>
+#include<linux/fb.h>
+#include<linux/ioport.h>
+#include<linux/init.h>
+#include<linux/pci.h>
+#include<linux/vmalloc.h>
+#include<linux/pagemap.h>
+#include <linux/console.h>
+#include<linux/platform_device.h>
+#include<linux/screen_info.h>
+
+#include "sm750.h"
+#include "sm750_help.h"
+#include "sm750_cursor.h"
+
+
+#define PEEK32(addr) \
+readl(cursor->mmio + (addr))
+
+#define POKE32(addr,data) \
+writel((data),cursor->mmio + (addr))
+
+/* cursor control for voyager and 718/750*/
+#define HWC_ADDRESS                         0x0
+#define HWC_ADDRESS_ENABLE                  31:31
+#define HWC_ADDRESS_ENABLE_DISABLE          0
+#define HWC_ADDRESS_ENABLE_ENABLE           1
+#define HWC_ADDRESS_EXT                     27:27
+#define HWC_ADDRESS_EXT_LOCAL               0
+#define HWC_ADDRESS_EXT_EXTERNAL            1
+#define HWC_ADDRESS_CS                      26:26
+#define HWC_ADDRESS_CS_0                    0
+#define HWC_ADDRESS_CS_1                    1
+#define HWC_ADDRESS_ADDRESS                 25:0
+
+#define HWC_LOCATION                        0x4
+#define HWC_LOCATION_TOP                    27:27
+#define HWC_LOCATION_TOP_INSIDE             0
+#define HWC_LOCATION_TOP_OUTSIDE            1
+#define HWC_LOCATION_Y                      26:16
+#define HWC_LOCATION_LEFT                   11:11
+#define HWC_LOCATION_LEFT_INSIDE            0
+#define HWC_LOCATION_LEFT_OUTSIDE           1
+#define HWC_LOCATION_X                      10:0
+
+#define HWC_COLOR_12                        0x8
+#define HWC_COLOR_12_2_RGB565               31:16
+#define HWC_COLOR_12_1_RGB565               15:0
+
+#define HWC_COLOR_3                         0xC
+#define HWC_COLOR_3_RGB565                  15:0
+
+
+/* hw_cursor_xxx works for voyager,718 and 750 */
+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);
+       POKE32(HWC_ADDRESS,reg);
+}
+void hw_cursor_disable(struct lynx_cursor * cursor)
+{
+       POKE32(HWC_ADDRESS,0);
+}
+
+void hw_cursor_setSize(struct lynx_cursor * cursor,
+                                               int w,int h)
+{
+       cursor->w = w;
+       cursor->h = h;
+}
+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);
+}
+void hw_cursor_setColor(struct lynx_cursor * cursor,
+                                               u32 fg,u32 bg)
+{
+       POKE32(HWC_COLOR_12,(fg<<16)|(bg&0xffff));
+       POKE32(HWC_COLOR_3,0xffe0);
+}
+
+void hw_cursor_setData(struct lynx_cursor * cursor,
+                       u16 rop,const u8* pcol,const u8* pmsk)
+{
+       int i,j,count,pitch,offset;
+       u8 color,mask,opr;
+       u16 data;
+       void __iomem *pbuffer, *pstart;
+
+       /*  in byte*/
+       pitch = cursor->w >> 3;
+
+       /* in byte      */
+       count = pitch * cursor->h;
+
+       /* in byte */
+       offset = cursor->maxW * 2 / 8;
+
+       data = 0;
+       pstart = cursor->vstart;
+       pbuffer = pstart;
+
+/*
+       if(odd &1){
+               hw_cursor_setData2(cursor,rop,pcol,pmsk);
+       }
+       odd++;
+       if(odd > 0xfffffff0)
+               odd=0;
+*/
+
+       for(i=0;i<count;i++)
+       {
+               color = *pcol++;
+               mask = *pmsk++;
+               data = 0;
+
+               /* either method below works well,
+                * but method 2 shows no lag
+                * and method 1 seems a bit wrong*/
+#if 0
+               if(rop == ROP_XOR)
+                       opr = mask ^ color;
+               else
+                       opr = mask & color;
+
+               for(j=0;j<8;j++)
+               {
+
+                       if(opr & (0x80 >> j))
+                       {       //use fg color,id = 2
+                               data |= 2 << (j*2);
+                       }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)
+                                       opr = mask ^ color;
+                               else
+                                       opr = mask & color;
+
+                               /* 2 stands for forecolor and 1 for backcolor */
+                               data |= ((opr & (0x80>>j))?2:1)<<(j*2);
+                       }
+               }
+#endif
+               iowrite16(data, pbuffer);
+
+               /* assume pitch is 1,2,4,8,...*/
+#if 0
+               if(!((i+1)&(pitch-1)))   /* below line equal to is line */
+#else
+               if((i+1) % pitch == 0)
+#endif
+               {
+                       /* need a return */
+                       pstart += offset;
+                       pbuffer = pstart;
+               }else{
+                       pbuffer += sizeof(u16);
+               }
+
+       }
+
+
+}
+
+
+void hw_cursor_setData2(struct lynx_cursor * cursor,
+                       u16 rop,const u8* pcol,const u8* pmsk)
+{
+       int i,j,count,pitch,offset;
+       u8 color, mask;
+       u16 data;
+       void __iomem *pbuffer, *pstart;
+
+       /*  in byte*/
+       pitch = cursor->w >> 3;
+
+       /* in byte      */
+       count = pitch * cursor->h;
+
+       /* in byte */
+       offset = cursor->maxW * 2 / 8;
+
+       data = 0;
+       pstart = cursor->vstart;
+       pbuffer = pstart;
+
+       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)
+                       opr = mask ^ color;
+               else
+                       opr = mask & color;
+
+               for(j=0;j<8;j++)
+               {
+
+                       if(opr & (0x80 >> j))
+                       {       //use fg color,id = 2
+                               data |= 2 << (j*2);
+                       }else{
+                               //use bg color,id = 1
+                               data |= 1 << (j*2);
+                       }
+               }
+#else
+               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+1) % pitch == 0)
+               {
+                       /* need a return */
+                       pstart += offset;
+                       pbuffer = pstart;
+               }else{
+                       pbuffer += sizeof(u16);
+               }
+
+       }
+}
diff --git a/drivers/staging/sm750fb/sm750_cursor.h b/drivers/staging/sm750fb/sm750_cursor.h
new file mode 100644 (file)
index 0000000..8cede07
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef LYNX_CURSOR_H__
+#define LYNX_CURSOR_H__
+
+/* hw_cursor_xxx works for voyager,718 and 750 */
+void hw_cursor_enable(struct lynx_cursor * cursor);
+void hw_cursor_disable(struct lynx_cursor * cursor);
+void hw_cursor_setSize(struct lynx_cursor * cursor,
+                                               int w,int h);
+void hw_cursor_setPos(struct lynx_cursor * cursor,
+                                               int x,int y);
+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);
+void hw_cursor_setData2(struct lynx_cursor * cursor,
+                       u16 rop,const u8* data,const u8* mask);
+#endif
diff --git a/drivers/staging/sm750fb/sm750_help.h b/drivers/staging/sm750fb/sm750_help.h
new file mode 100644 (file)
index 0000000..e0128d2
--- /dev/null
@@ -0,0 +1,111 @@
+#ifndef LYNX_HELP_H__
+#define LYNX_HELP_H__
+/*****************************************************************************\
+ *                                FIELD MACROS                               *
+\*****************************************************************************/
+
+#define _LSB(f)             (0 ? f)
+#define _MSB(f)             (1 ? f)
+#define _COUNT(f)           (_MSB(f) - _LSB(f) + 1)
+
+#define RAW_MASK(f)         (0xFFFFFFFF >> (32 - _COUNT(f)))
+#define GET_MASK(f)         (RAW_MASK(f) << _LSB(f))
+#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)))
+#define SET_FIELDV(d,f,v)   (((d) & ~GET_MASK(f)) | \
+                            (((v) & RAW_MASK(f)) << _LSB(f)))
+
+
+////////////////////////////////////////////////////////////////////////////////
+//                                                                            //
+// Internal macros                                                            //
+//                                                                            //
+////////////////////////////////////////////////////////////////////////////////
+
+#define _F_START(f)             (0 ? f)
+#define _F_END(f)               (1 ? f)
+#define _F_SIZE(f)              (1 + _F_END(f) - _F_START(f))
+#define _F_MASK(f)              (((1 << _F_SIZE(f)) - 1) << _F_START(f))
+#define _F_NORMALIZE(v, f)      (((v) & _F_MASK(f)) >> _F_START(f))
+#define _F_DENORMALIZE(v, f)    (((v) << _F_START(f)) & _F_MASK(f))
+
+
+////////////////////////////////////////////////////////////////////////////////
+//                                                                            //
+// Global macros                                                              //
+//                                                                            //
+////////////////////////////////////////////////////////////////////////////////
+
+#define FIELD_GET(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) \
+)
+
+#define FIELD_VALUE(x, reg, field, value) \
+( \
+    (x & ~_F_MASK(reg ## _ ## field)) \
+    | _F_DENORMALIZE(value, reg ## _ ## field) \
+)
+
+#define FIELD_CLEAR(reg, field) \
+( \
+    ~ _F_MASK(reg ## _ ## field) \
+)
+
+
+////////////////////////////////////////////////////////////////////////////////
+//                                                                            //
+// Field Macros                                                               //
+//                                                                            //
+////////////////////////////////////////////////////////////////////////////////
+
+#define FIELD_START(field)              (0 ? field)
+#define FIELD_END(field)                (1 ? field)
+#define FIELD_SIZE(field)               (1 + FIELD_END(field) - FIELD_START(field))
+#define FIELD_MASK(field)               (((1 << (FIELD_SIZE(field)-1)) | ((1 << (FIELD_SIZE(field)-1)) - 1)) << FIELD_START(field))
+#define FIELD_NORMALIZE(reg, field)     (((reg) & FIELD_MASK(field)) >> FIELD_START(field))
+#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)
+#define FIELD_INIT_VAL(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)
+
+#define RGB(r, g, b) \
+( \
+    (unsigned long) (((r) << 16) | ((g) << 8) | (b)) \
+)
+
+#define RGB16(r, g, b) \
+( \
+    (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)
+               return b-a;
+       else
+               return a-b;
+}
+
+/* n / d + 1 / 2 = (2n + d) / 2d */
+#define roundedDiv(num,denom)  ((2 * (num) + (denom)) / (2 * (denom)))
+#define MB(x) ((x)<<20)
+#define KB(x) ((x)<<10)
+#define MHz(x) ((x) * 1000000)
+
+
+
+
+#endif
diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c
new file mode 100644 (file)
index 0000000..9f0d06d
--- /dev/null
@@ -0,0 +1,642 @@
+#include <linux/version.h>
+#include<linux/module.h>
+#include<linux/kernel.h>
+#include<linux/errno.h>
+#include<linux/string.h>
+#include<linux/mm.h>
+#include<linux/slab.h>
+#include<linux/delay.h>
+#include<linux/fb.h>
+#include<linux/ioport.h>
+#include<linux/init.h>
+#include<linux/pci.h>
+#include<linux/vmalloc.h>
+#include<linux/pagemap.h>
+#include <linux/console.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+#include<linux/platform_device.h>
+#include<linux/screen_info.h>
+
+#include "sm750.h"
+#include "sm750_hw.h"
+#include "ddk750.h"
+#include "sm750_accel.h"
+
+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;
+
+       share->vidreg_start  = pci_resource_start(pdev, 1);
+       share->vidreg_size = MB(2);
+
+       pr_info("mmio phyAddr = %lx\n", share->vidreg_start);
+
+       /* reserve the vidreg space of smi adaptor
+        * if you do this, u need to add release region code
+        * in lynxfb_remove, or memory will not be mapped again
+        * successfully
+        * */
+
+       if((ret = pci_request_region(pdev, 1, "sm750fb")))
+       {
+               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){
+               pr_err("mmio failed\n");
+               ret = -EFAULT;
+               goto exit;
+       }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;
+
+       ddk750_set_mmio(share->pvReg,share->devid, share->revid);
+
+       share->vidmem_start = pci_resource_start(pdev, 0);
+       /* don't use pdev_resource[x].end - resource[x].start to
+        * calculate the resource size,its only the maximum available
+        * size but not the actual size,use
+        * @hw_sm750_getVMSize function can be safe.
+        * */
+       share->vidmem_size = hw_sm750_getVMSize(share);
+       pr_info("video memory phyAddr = %lx, size = %u bytes\n",
+       share->vidmem_start, share->vidmem_size);
+
+       /* reserve the vidmem space of smi adaptor */
+#if 0
+       if((ret = pci_request_region(pdev,0,_moduleName_)))
+       {
+               pr_err("Can not request PCI regions.\n");
+               goto exit;
+       }
+#endif
+
+       share->pvMem = ioremap(share->vidmem_start,
+                                                       share->vidmem_size);
+
+       if(!share->pvMem){
+               pr_err("Map video memory failed\n");
+               ret = -EFAULT;
+               goto exit;
+       }else{
+               pr_info("video memory vaddr = %p\n", share->pvMem);
+       }
+exit:
+       return ret;
+}
+
+
+
+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)?
+                                               DEFAULT_SM750LE_CHIP_CLOCK :
+                                               DEFAULT_SM750_CHIP_CLOCK;
+
+       if(parm->mem_clk == 0)
+               parm->mem_clk = parm->chip_clk;
+       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){
+               POKE32(SYSTEM_CTRL,
+                               FIELD_SET(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, PCI_BURST, ON));
+       }
+
+       /* sm750 use sii164, it can be setup with default value
+        * by on power, so initDVIDisp can be skipped */
+#if 0
+       ddk750_initDVIDisp();
+#endif
+
+       if(getChipType() != SM750LE)
+       {
+               /* does user need CRT ?*/
+               if(spec_share->state.nocrt){
+                       POKE32(MISC_CTRL,
+                                       FIELD_SET(PEEK32(MISC_CTRL),
+                                       MISC_CTRL,
+                                       DAC_POWER, OFF));
+                       /* shut off dpms */
+                       POKE32(SYSTEM_CTRL,
+                                       FIELD_SET(PEEK32(SYSTEM_CTRL),
+                                       SYSTEM_CTRL,
+                                       DPMS, VNHN));
+               }else{
+                       POKE32(MISC_CTRL,
+                                       FIELD_SET(PEEK32(MISC_CTRL),
+                                       MISC_CTRL,
+                                       DAC_POWER, ON));
+                       /* turn on dpms */
+                       POKE32(SYSTEM_CTRL,
+                                       FIELD_SET(PEEK32(SYSTEM_CTRL),
+                                       SYSTEM_CTRL,
+                                       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;
+               }
+       }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);
+
+
+        /* 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);
+                       pr_info("okay,CH7301 DVI chip setup done\n");
+        }
+       }
+
+       /* init 2d engine */
+       if(!share->accel_off){
+               hw_sm750_initAccel(share);
+//             share->accel.de_wait = hw_sm750_deWait;
+       }
+
+       return 0;
+}
+
+
+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)
+{
+       
+       return 0;
+}
+
+
+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){
+                       pr_info("primary channel\n");
+                       if(output->paths & sm750_panel)
+                               dispSet |= do_LCD1_PRI;
+                       if(output->paths & sm750_crt)
+                               dispSet |= do_CRT_PRI;
+
+               }else{
+                       pr_info("secondary channel\n");
+                       if(output->paths & sm750_panel)
+                               dispSet |= do_LCD1_SEC;
+                       if(output->paths & sm750_crt)
+                               dispSet |= do_CRT_SEC;
+
+               }
+               ddk750_setLogicalDispOut(dispSet);
+       }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");
+       return ret;
+}
+
+void hw_sm750_output_clear(struct lynxfb_output* output)
+{
+       
+       return;
+}
+
+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:
+                       return -EINVAL;
+
+       }
+
+       return 0;
+}
+
+
+/*
+       set the controller's mode for @crtc charged with @var and @fix parameters
+*/
+int hw_sm750_crtc_setMode(struct lynxfb_crtc* crtc,
+                                                               struct fb_var_screeninfo* var,
+                                                               struct fb_fix_screeninfo* fix)
+{
+       int ret,fmt;
+       u32 reg;
+       mode_parameter_t modparm;
+       clock_type_t clock;
+       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){
+               /* 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;
+               }
+               hw_set2dformat(&share->accel, fmt);
+       }
+#endif
+
+       /* set timing */
+//     modparm.pixel_clock = PS_TO_HZ(var->pixclock);
+       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.horizontal_display_end = var->xres;
+       modparm.horizontal_sync_width = var->hsync_len;
+       modparm.horizontal_sync_start = var->xres + var->right_margin;
+       modparm.horizontal_total = var->xres + var->left_margin + var->right_margin + var->hsync_len;
+       modparm.vertical_display_end = var->yres;
+       modparm.vertical_sync_height = var->vsync_len;
+       modparm.vertical_sync_start = var->yres + var->lower_margin;
+       modparm.vertical_total = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
+
+       /* choose pll */
+       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){
+               pr_err("Set mode timing failed\n");
+               goto exit;
+       }
+
+       if(crtc->channel != sm750_secondary){
+               /* set pitch, offset ,width,start address ,etc... */
+               POKE32(PANEL_FB_ADDRESS,
+                       FIELD_SET(0, PANEL_FB_ADDRESS, STATUS, CURRENT)|
+                       FIELD_SET(0, PANEL_FB_ADDRESS, EXT, LOCAL)|
+                       FIELD_VALUE(0, PANEL_FB_ADDRESS, ADDRESS, crtc->oScreen));
+
+               reg = var->xres * (var->bits_per_pixel >> 3);
+               /* crtc->channel is not equal to par->index on numeric,be aware of that */
+               reg = PADDING(crtc->line_pad,reg);
+
+               POKE32(PANEL_FB_WIDTH,
+                       FIELD_VALUE(0, PANEL_FB_WIDTH, WIDTH, reg)|
+                       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, X, var->xoffset));
+
+               POKE32(PANEL_WINDOW_HEIGHT,
+                       FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, HEIGHT, var->yres_virtual - 1)|
+                       FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, Y, var->yoffset));
+
+               POKE32(PANEL_PLANE_TL, 0);
+
+               POKE32(PANEL_PLANE_BR,
+                       FIELD_VALUE(0, PANEL_PLANE_BR, BOTTOM, var->yres - 1)|
+                       FIELD_VALUE(0, PANEL_PLANE_BR,RIGHT, var->xres - 1));
+
+               /* set pixel format */
+               reg = PEEK32(PANEL_DISPLAY_CTRL);
+               POKE32(PANEL_DISPLAY_CTRL,
+                       FIELD_VALUE(reg,
+                       PANEL_DISPLAY_CTRL, FORMAT,
+                       (var->bits_per_pixel >> 4)
+                       ));
+       }else{
+               /* not implemented now */
+               POKE32(CRT_FB_ADDRESS, crtc->oScreen);
+               reg = var->xres * (var->bits_per_pixel >> 3);
+               /* crtc->channel is not equal to par->index on numeric,be aware of that */
+               reg = PADDING(crtc->line_pad, reg);
+
+               POKE32(CRT_FB_WIDTH,
+                       FIELD_VALUE(0, CRT_FB_WIDTH, WIDTH, reg)|
+                       FIELD_VALUE(0, CRT_FB_WIDTH, OFFSET, fix->line_length));
+
+               /* SET PIXEL FORMAT */
+               reg = PEEK32(CRT_DISPLAY_CTRL);
+               reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, FORMAT, var->bits_per_pixel >> 4);
+               POKE32(CRT_DISPLAY_CTRL, reg);
+
+       }
+
+
+exit:
+       return ret;
+}
+
+void hw_sm750_crtc_clear(struct lynxfb_crtc* crtc)
+{
+       
+       return;
+}
+
+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};
+       POKE32(add[crtc->channel] + index*4, (red<<16)|(green<<8)|blue);
+       return 0;
+}
+
+int hw_sm750le_setBLANK(struct lynxfb_output * output, int blank){
+       int dpms,crtdb;
+       
+       switch(blank)
+       {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
+               case FB_BLANK_UNBLANK:
+#else
+               case VESA_NO_BLANKING:
+#endif
+                       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;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
+               case FB_BLANK_VSYNC_SUSPEND:
+#else
+               case VESA_VSYNC_SUSPEND:
+#endif
+                       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:
+#else
+               case VESA_HSYNC_SUSPEND:
+#endif
+                       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:
+#else
+               case VESA_POWERDOWN:
+#endif
+                       dpms = CRT_DISPLAY_CTRL_DPMS_3;
+                       crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+                       break;
+               default:
+                       return -EINVAL;
+       }
+
+       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_output* output,int blank)
+{
+       unsigned int dpms, pps, crtdb;
+       
+       dpms = pps = crtdb = 0;
+
+       switch (blank)
+       {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
+               case FB_BLANK_UNBLANK:
+#else
+               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;
+#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;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
+               case FB_BLANK_VSYNC_SUSPEND:
+#else
+               case VESA_VSYNC_SUSPEND:
+#endif
+                       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:
+#else
+               case VESA_HSYNC_SUSPEND:
+#endif
+                       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:
+#else
+               case VESA_POWERDOWN:
+#endif
+                       dpms = SYSTEM_CTRL_DPMS_VNHN;
+                       pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
+                       crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+                       break;
+       }
+
+       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){
+               POKE32(PANEL_DISPLAY_CTRL, FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, DATA, pps));
+       }
+
+       return 0;
+}
+
+
+void hw_sm750_initAccel(struct lynx_share * share)
+{
+       u32 reg;
+       enable2DEngine(1);
+
+       if(getChipType() == SM750LE){
+               reg = PEEK32(DE_STATE1);
+               reg = FIELD_SET(reg, DE_STATE1, DE_ABORT,ON);
+               POKE32(DE_STATE1,reg);
+
+               reg = PEEK32(DE_STATE1);
+               reg = FIELD_SET(reg, DE_STATE1, DE_ABORT,OFF);
+               POKE32(DE_STATE1, reg);
+
+       }else{
+               /* engine reset */
+               reg = PEEK32(SYSTEM_CTRL);
+           reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT,ON);
+               POKE32(SYSTEM_CTRL, reg);
+
+               reg = PEEK32(SYSTEM_CTRL);
+               reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT,OFF);
+               POKE32(SYSTEM_CTRL, reg);
+       }
+
+       /* call 2d init */
+       share->accel.de_init(&share->accel);
+}
+
+int hw_sm750le_deWait(void)
+{
+       int i=0x10000000;
+       while(i--){
+               unsigned int dwVal = PEEK32(DE_STATE2);
+               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))
+               {
+                       return 0;
+               }
+       }
+       /* timeout error */
+       return -1;
+}
+
+
+int hw_sm750_deWait(void)
+{
+       int i=0x10000000;
+       while(i--){
+               unsigned int dwVal = PEEK32(SYSTEM_CTRL);
+               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))
+               {
+                       return 0;
+               }
+       }
+       /* timeout error */
+       return -1;
+}
+
+int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
+        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;
+}
+
diff --git a/drivers/staging/sm750fb/sm750_hw.h b/drivers/staging/sm750fb/sm750_hw.h
new file mode 100644 (file)
index 0000000..b05be5e
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef LYNX_HW750_H__
+#define LYNX_HW750_H__
+
+
+#define DEFAULT_SM750_CHIP_CLOCK               290
+#define DEFAULT_SM750LE_CHIP_CLOCK     333
+#ifndef SM750LE_REVISION_ID
+#define SM750LE_REVISION_ID (unsigned char)0xfe
+#endif
+
+//#define DEFAULT_MEM_CLOCK    (DEFAULT_SM750_CHIP_CLOCK/1)
+//#define DEFAULT_MASTER_CLOCK (DEFAULT_SM750_CHIP_CLOCK/3)
+
+
+enum sm750_pnltype{
+
+       sm750_24TFT = 0,/* 24bit tft */
+
+       sm750_dualTFT = 2,/* dual 18 bit tft */
+
+       sm750_doubleTFT = 1,/* 36 bit double pixel tft */
+};
+
+/* vga channel is not concerned  */
+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_swap,/*      primary => crt head and secondary => panel */
+};
+
+
+enum sm750_channel{
+       sm750_primary = 0,
+       /* enum value equal to the register filed data */
+       sm750_secondary = 1,
+};
+
+enum sm750_path{
+       sm750_panel = 1,
+       sm750_crt = 2,
+       sm750_pnc = 3,/* panel and crt */
+};
+
+struct init_status{
+       ushort powerMode;
+       /* below three clocks are in unit of MHZ*/
+       ushort chip_clk;
+       ushort mem_clk;
+       ushort master_clk;
+       ushort setAllEngOff;
+       ushort resetMemory;
+};
+
+struct sm750_state{
+       struct init_status initParm;
+       enum sm750_pnltype pnltype;
+       enum sm750_dataflow dataflow;
+       int nocrt;
+       int xLCD;
+       int yLCD;
+};
+
+/*     sm750_share stands for a presentation of two frame buffer
+       that use one sm750 adaptor, it is similiar to the super class of lynx_share
+       in C++
+*/
+
+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
+       */
+};
+
+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);
+int hw_sm750le_deWait(void);
+
+resource_size_t hw_sm750_getVMSize(struct lynx_share *);
+int hw_sm750_output_checkMode(struct lynxfb_output*,struct fb_var_screeninfo*);
+int hw_sm750_output_setMode(struct lynxfb_output*,struct fb_var_screeninfo*,struct fb_fix_screeninfo*);
+int hw_sm750_crtc_checkMode(struct lynxfb_crtc*,struct fb_var_screeninfo*);
+int hw_sm750_crtc_setMode(struct lynxfb_crtc*,struct fb_var_screeninfo*,struct fb_fix_screeninfo*);
+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*);
+int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
+        const struct fb_var_screeninfo *var,
+        const struct fb_info *info);
+
+#endif
index 7cc1896938b60b13992d6e5982f680a71822eea7..c5d62534e4a4cebb54f85dc400952e56c122bdec 100644 (file)
@@ -119,7 +119,7 @@ struct ModeInit {
 /**********************************************************************
                         SM712 Mode table.
  **********************************************************************/
-struct ModeInit vgamode[] = {
+static struct ModeInit vgamode[] = {
        {
         /*  mode#0: 640 x 480  16Bpp  60Hz */
         640, 480, 16, 60,
index ebd95365ffae83e1afd456a5d451d7217397cb87..77f51a07500470215cf024681444b72c425bb401 100644 (file)
@@ -113,13 +113,15 @@ static struct vesa_mode vesa_mode_table[] = {
 
 static struct screen_info smtc_scr_info;
 
+static char *mode_option;
+
 /* process command line options, get vga parameter */
-static int __init sm7xx_vga_setup(char *options)
+static void __init sm7xx_vga_setup(char *options)
 {
        int i;
 
        if (!options || !*options)
-               return -EINVAL;
+               return;
 
        smtc_scr_info.lfb_width = 0;
        smtc_scr_info.lfb_height = 0;
@@ -133,13 +135,10 @@ static int __init sm7xx_vga_setup(char *options)
                        smtc_scr_info.lfb_height =
                                                vesa_mode_table[i].lfb_height;
                        smtc_scr_info.lfb_depth  = vesa_mode_table[i].lfb_depth;
-                       return 0;
+                       return;
                }
        }
-
-       return -1;
 }
-__setup("vga=", sm7xx_vga_setup);
 
 static void sm712_setpalette(int regno, unsigned red, unsigned green,
                             unsigned blue, struct fb_info *info)
@@ -777,6 +776,12 @@ static int smtcfb_pci_probe(struct pci_dev *pdev,
        if (err)
                return err;
 
+       err = pci_request_region(pdev, 0, "sm7xxfb");
+       if (err < 0) {
+               dev_err(&pdev->dev, "cannot reserve framebuffer region\n");
+               goto failed_regions;
+       }
+
        sprintf(smtcfb_fix.id, "sm%Xfb", ent->device);
 
        sfb = smtc_alloc_fb_info(pdev);
@@ -906,6 +911,9 @@ failed_fb:
        smtc_free_fb_info(sfb);
 
 failed_free:
+       pci_release_region(pdev, 0);
+
+failed_regions:
        pci_disable_device(pdev);
 
        return err;
@@ -923,6 +931,8 @@ static const struct pci_device_id smtcfb_pci_table[] = {
        {0,}
 };
 
+MODULE_DEVICE_TABLE(pci, smtcfb_pci_table);
+
 static void smtcfb_pci_remove(struct pci_dev *pdev)
 {
        struct smtcfb_info *sfb;
@@ -932,6 +942,8 @@ static void smtcfb_pci_remove(struct pci_dev *pdev)
        smtc_unmap_mmio(sfb);
        unregister_framebuffer(&sfb->fb);
        smtc_free_fb_info(sfb);
+       pci_release_region(pdev, 0);
+       pci_disable_device(pdev);
 }
 
 #ifdef CONFIG_PM
@@ -1017,7 +1029,29 @@ static struct pci_driver smtcfb_driver = {
        .driver.pm  = SM7XX_PM_OPS,
 };
 
-module_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);
+}
+
+module_init(sm712fb_init);
+
+static void __exit sm712fb_exit(void)
+{
+       pci_unregister_driver(&smtcfb_driver);
+}
+
+module_exit(sm712fb_exit);
 
 MODULE_AUTHOR("Siliconmotion ");
 MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
index 3708bc13ae86eed59570bdfad3fa1953ee04293e..0211df60004a6e267698b2171dd449a797258f2c 100644 (file)
@@ -840,12 +840,10 @@ static ssize_t message_show(struct kobject *kobj,
 static ssize_t message_store(struct kobject *kobj, struct kobj_attribute *attr,
        const char *buf, size_t count)
 {
-       ssize_t retval = 0;
        struct msg_group_t *group = spk_find_msg_group(attr->attr.name);
 
        BUG_ON(!group);
-       retval = message_store_helper(buf, count, group);
-       return retval;
+       return message_store_helper(buf, count, group);
 }
 
 /*
index e9f0c150d2467632a3581eb98459431ca2aa7973..c955976414ee8d7f46d2eadb4e6e6e33063192fa 100644 (file)
@@ -423,7 +423,8 @@ static void announce_edge(struct vc_data *vc, int msg_id)
        if (spk_bleeps & 1)
                bleep(spk_y);
        if ((spk_bleeps & 2) && (msg_id < edge_quiet))
-               synth_printf("%s\n", spk_msg_get(MSG_EDGE_MSGS_START + msg_id - 1));
+               synth_printf("%s\n",
+                       spk_msg_get(MSG_EDGE_MSGS_START + msg_id - 1));
 }
 
 static void speak_char(u_char ch)
@@ -1131,7 +1132,8 @@ static void spkup_write(const char *in_buf, int count)
        if (in_count > 2 && rep_count > 2) {
                if (last_type & CH_RPT) {
                        synth_printf(" ");
-                       synth_printf(spk_msg_get(MSG_REPEAT_DESC2), ++rep_count);
+                       synth_printf(spk_msg_get(MSG_REPEAT_DESC2),
+                                       ++rep_count);
                        synth_printf(" ");
                }
                rep_count = 0;
@@ -1527,7 +1529,7 @@ static void update_color_buffer(struct vc_data *vc, const char *ic, int len)
        int i, bi, hi;
        int vc_num = vc->vc_num;
 
-       bi = ((vc->vc_attr & 0x70) >> 4);
+       bi = (vc->vc_attr & 0x70) >> 4;
        hi = speakup_console[vc_num]->ht.highsize[bi];
 
        i = 0;
@@ -1847,7 +1849,8 @@ static void speakup_win_set(struct vc_data *vc)
                        win_right = spk_x;
                }
                snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_BOUNDARY),
-                        (win_start) ? spk_msg_get(MSG_END) : spk_msg_get(MSG_START),
+                        (win_start) ?
+                               spk_msg_get(MSG_END) : spk_msg_get(MSG_START),
                         (int)spk_y + 1, (int)spk_x + 1);
        }
        synth_printf("%s\n", info);
index 317bb8432a04251777cb5beee839b4607e739fa3..1b399214ecf7361ef5cf1ad83c650d0fb1bbc296 100644 (file)
@@ -34,6 +34,7 @@ struct old_serial_port {
 #define SPK_TIMEOUT 100
 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
 
-#define spk_serial_tx_busy() ((inb(speakup_info.port_tts + UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY)
+#define spk_serial_tx_busy() \
+       ((inb(speakup_info.port_tts + UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY)
 
 #endif
index 898dce5e1243e754a7dafd652d12ff53069b59f8..a7f4962427f36b98d54e98518e8259ff11f044c8 100644 (file)
@@ -61,10 +61,12 @@ 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_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);
 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 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);
 
index f0bfd9e991913903e51d57926030ef0e20e6772c..f418893928ece6c019f5870ff4d1aed56152c6b4 100644 (file)
@@ -318,18 +318,8 @@ module_param_named(start, synth_acntpc.startup, short, S_IRUGO);
 MODULE_PARM_DESC(port, "Set the port for the synthesizer (override probing).");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init acntpc_init(void)
-{
-       return synth_add(&synth_acntpc);
-}
-
-static void __exit acntpc_exit(void)
-{
-       synth_remove(&synth_acntpc);
-}
+module_spk_synth(synth_acntpc);
 
-module_init(acntpc_init);
-module_exit(acntpc_exit);
 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for Accent PC synthesizer");
index 3f2b5698a3d86606c5920c3ad5c93cc88311cfdf..af2690f38950c737345542035ac6c6be0f46b42a 100644 (file)
@@ -143,18 +143,8 @@ module_param_named(start, synth_acntsa.startup, short, S_IRUGO);
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init acntsa_init(void)
-{
-       return synth_add(&synth_acntsa);
-}
-
-static void __exit acntsa_exit(void)
-{
-       synth_remove(&synth_acntsa);
-}
+module_spk_synth(synth_acntsa);
 
-module_init(acntsa_init);
-module_exit(acntsa_exit);
 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for Accent SA synthesizer");
index 678b263e551c4cee34e8ef73e87af7c92d6c8f03..51788f7d4480cb740a6773352dbca9f978d9940a 100644 (file)
@@ -207,18 +207,8 @@ module_param_named(start, synth_apollo.startup, short, S_IRUGO);
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init apollo_init(void)
-{
-       return synth_add(&synth_apollo);
-}
-
-static void __exit apollo_exit(void)
-{
-       synth_remove(&synth_apollo);
-}
+module_spk_synth(synth_apollo);
 
-module_init(apollo_init);
-module_exit(apollo_exit);
 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for Apollo II synthesizer");
index 5cbaec8335fe373a4d52a5b3aa1d52bdfe541500..ea89e36ecd0d3eb544d1858ef5b1492116c3f706 100644 (file)
@@ -177,18 +177,8 @@ module_param_named(start, synth_audptr.startup, short, S_IRUGO);
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init audptr_init(void)
-{
-       return synth_add(&synth_audptr);
-}
-
-static void __exit audptr_exit(void)
-{
-       synth_remove(&synth_audptr);
-}
+module_spk_synth(synth_audptr);
 
-module_init(audptr_init);
-module_exit(audptr_exit);
 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for Audapter synthesizer");
index 2f070282a85de6f87f4f4b7000745d06bb92610f..80f8358d4199ca0e49920092fb730e114402b386 100644 (file)
@@ -127,18 +127,8 @@ module_param_named(start, synth_bns.startup, short, S_IRUGO);
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init bns_init(void)
-{
-       return synth_add(&synth_bns);
-}
+module_spk_synth(synth_bns);
 
-static void __exit bns_exit(void)
-{
-       synth_remove(&synth_bns);
-}
-
-module_init(bns_init);
-module_exit(bns_exit);
 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for Braille 'n Speak synthesizers");
index 555029036dc2bb3dc32895ffdb5f51a8b34e0318..e0b5db9bb46e6eb24af420a8370a6b264ced3c16 100644 (file)
@@ -207,10 +207,12 @@ static void do_catch_up(struct spk_synth *synth)
                        if (time_after_eq(jiffies, jiff_max)) {
                                if (!in_escape)
                                        spk_serial_out(PROCSPEECH);
-                               spin_lock_irqsave(&speakup_info.spinlock, flags);
+                               spin_lock_irqsave(&speakup_info.spinlock,
+                                                       flags);
                                jiffy_delta_val = jiffy_delta->u.n.value;
                                delay_time_val = delay_time->u.n.value;
-                               spin_unlock_irqrestore(&speakup_info.spinlock, flags);
+                               spin_unlock_irqrestore(&speakup_info.spinlock,
+                                                       flags);
                                schedule_timeout(msecs_to_jiffies
                                                 (delay_time_val));
                                jiff_max = jiffies + jiffy_delta_val;
@@ -234,18 +236,8 @@ module_param_named(start, synth_decext.startup, short, S_IRUGO);
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init decext_init(void)
-{
-       return synth_add(&synth_decext);
-}
-
-static void __exit decext_exit(void)
-{
-       synth_remove(&synth_decext);
-}
+module_spk_synth(synth_decext);
 
-module_init(decext_init);
-module_exit(decext_exit);
 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for DECtalk External synthesizers");
index 7c9c432e48d99fd11d71b6c2722eb36bd8fdef48..437e13a85943dc00a0bbb7eb569eafe62589afb2 100644 (file)
@@ -423,10 +423,12 @@ static void do_catch_up(struct spk_synth *synth)
                        if (time_after_eq(jiffies, jiff_max)) {
                                if (!in_escape)
                                        dt_sendchar(PROCSPEECH);
-                               spin_lock_irqsave(&speakup_info.spinlock, flags);
+                               spin_lock_irqsave(&speakup_info.spinlock,
+                                                       flags);
                                jiffy_delta_val = jiffy_delta->u.n.value;
                                delay_time_val = delay_time->u.n.value;
-                               spin_unlock_irqrestore(&speakup_info.spinlock, flags);
+                               spin_unlock_irqrestore(&speakup_info.spinlock,
+                                                       flags);
                                schedule_timeout(msecs_to_jiffies
                                                 (delay_time_val));
                                jiff_max = jiffies + jiffy_delta_val;
@@ -491,18 +493,8 @@ module_param_named(start, synth_dec_pc.startup, short, S_IRUGO);
 
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init decpc_init(void)
-{
-       return synth_add(&synth_dec_pc);
-}
-
-static void __exit decpc_exit(void)
-{
-       synth_remove(&synth_dec_pc);
-}
+module_spk_synth(synth_dec_pc);
 
-module_init(decpc_init);
-module_exit(decpc_exit);
 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for DECtalk PC synthesizers");
index 69e7c2b41b9493d791987e5cf9103dd50bdd2e37..b5a23d42f4d5dc49fa2ad17fbea65685e9e95f3b 100644 (file)
@@ -306,18 +306,8 @@ module_param_named(start, synth_dectlk.startup, short, S_IRUGO);
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init dectlk_init(void)
-{
-       return synth_add(&synth_dectlk);
-}
-
-static void __exit dectlk_exit(void)
-{
-       synth_remove(&synth_dectlk);
-}
+module_spk_synth(synth_dectlk);
 
-module_init(dectlk_init);
-module_exit(dectlk_exit);
 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for DECtalk Express synthesizers");
index 89592c0b915147e878fa83b29b07a6fec7c0bd66..345efd3344b06b11a66363add33fb2a7b62c6f67 100644 (file)
@@ -388,18 +388,8 @@ module_param_named(start, synth_dtlk.startup, short, S_IRUGO);
 MODULE_PARM_DESC(port, "Set the port for the synthesizer (override probing).");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init dtlk_init(void)
-{
-       return synth_add(&synth_dtlk);
-}
-
-static void __exit dtlk_exit(void)
-{
-       synth_remove(&synth_dtlk);
-}
+module_spk_synth(synth_dtlk);
 
-module_init(dtlk_init);
-module_exit(dtlk_exit);
 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for DoubleTalk PC synthesizers");
index 362342a194afb2975b8fcd2328282c11d48781ed..f66811269475a6864a64062ce93bf6191ef103ae 100644 (file)
@@ -129,18 +129,8 @@ module_param_named(start, synth_dummy.startup, short, S_IRUGO);
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init dummy_init(void)
-{
-       return synth_add(&synth_dummy);
-}
+module_spk_synth(synth_dummy);
 
-static void __exit dummy_exit(void)
-{
-       synth_remove(&synth_dummy);
-}
-
-module_init(dummy_init);
-module_exit(dummy_exit);
 MODULE_AUTHOR("Samuel Thibault <samuel.thibault@ens-lyon.org>");
 MODULE_DESCRIPTION("Speakup support for text console");
 MODULE_LICENSE("GPL");
index cef20fdda64684038293b8e09778e23d28df4501..6ea02736566443a6db010865428fe029a6cc633d 100644 (file)
@@ -319,18 +319,8 @@ module_param_named(start, synth_keypc.startup, short, S_IRUGO);
 MODULE_PARM_DESC(port, "Set the port for the synthesizer (override probing).");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init keypc_init(void)
-{
-       return synth_add(&synth_keypc);
-}
-
-static void __exit keypc_exit(void)
-{
-       synth_remove(&synth_keypc);
-}
+module_spk_synth(synth_keypc);
 
-module_init(keypc_init);
-module_exit(keypc_exit);
 MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for Keynote Gold PC synthesizers");
 MODULE_LICENSE("GPL");
index 377a6e2b8b9390038b1607c06c06cac73a6c8278..cc4806be806b2a6c782adc5c6bd6b8fb0935e948 100644 (file)
@@ -175,18 +175,8 @@ module_param_named(start, synth_ltlk.startup, short, S_IRUGO);
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init ltlk_init(void)
-{
-       return synth_add(&synth_ltlk);
-}
-
-static void __exit ltlk_exit(void)
-{
-       synth_remove(&synth_ltlk);
-}
+module_spk_synth(synth_ltlk);
 
-module_init(ltlk_init);
-module_exit(ltlk_exit);
 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for DoubleTalk LT/LiteTalk synthesizers");
index e6e93fbd183a090bcb7636f9745abe8438cada07..fb31bb95d83a1b591b47f34e571979cd2660228f 100644 (file)
@@ -350,19 +350,8 @@ module_param_named(start, synth_soft.startup, short, S_IRUGO);
 
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
+module_spk_synth(synth_soft);
 
-static int __init soft_init(void)
-{
-       return synth_add(&synth_soft);
-}
-
-static void __exit soft_exit(void)
-{
-       synth_remove(&synth_soft);
-}
-
-module_init(soft_init);
-module_exit(soft_exit);
 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_DESCRIPTION("Speakup userspace software synthesizer support");
 MODULE_LICENSE("GPL");
index bccddf8b89fd23baf7b2043f690bd312d29d4870..1007a6168c3cc3e28d7d58fa9b499acb7eec6719 100644 (file)
@@ -146,18 +146,8 @@ module_param_named(start, synth_spkout.startup, short, S_IRUGO);
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init spkout_init(void)
-{
-       return synth_add(&synth_spkout);
-}
-
-static void __exit spkout_exit(void)
-{
-       synth_remove(&synth_spkout);
-}
+module_spk_synth(synth_spkout);
 
-module_init(spkout_init);
-module_exit(spkout_exit);
 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for Speak Out synthesizers");
index dbe84b13772c08cc8e124e13dab8121cdef860da..6c21e7112210afc3dee54ca95984fd42a852f092 100644 (file)
@@ -127,18 +127,8 @@ module_param_named(start, synth_txprt.startup, short, S_IRUGO);
 MODULE_PARM_DESC(ser, "Set the serial port for the synthesizer (0-based).");
 MODULE_PARM_DESC(start, "Start the synthesizer once it is loaded.");
 
-static int __init txprt_init(void)
-{
-       return synth_add(&synth_txprt);
-}
+module_spk_synth(synth_txprt);
 
-static void __exit txprt_exit(void)
-{
-       synth_remove(&synth_txprt);
-}
-
-module_init(txprt_init);
-module_exit(txprt_exit);
 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for Transport synthesizers");
index 637ba6760ec060fb75a32fe661fe0a8880511970..1ef3795b865d32ae3dbbbcf807034affa1676da1 100644 (file)
 
 #define KT_SPKUP 15
 
-extern const struct old_serial_port *spk_serial_init(int index);
-extern void spk_stop_serial_interrupt(void);
-extern int spk_wait_for_xmitr(void);
-extern unsigned char spk_serial_in(void);
-extern unsigned char spk_serial_in_nowait(void);
-extern int spk_serial_out(const char ch);
-extern void spk_serial_release(void);
+const struct old_serial_port *spk_serial_init(int index);
+void spk_stop_serial_interrupt(void);
+int spk_wait_for_xmitr(void);
+unsigned char spk_serial_in(void);
+unsigned char spk_serial_in_nowait(void);
+int spk_serial_out(const char ch);
+void spk_serial_release(void);
 
-extern char synth_buffer_getc(void);
-extern char synth_buffer_peek(void);
-extern int synth_buffer_empty(void);
-extern struct var_t *spk_get_var(enum var_id_t var_id);
-extern ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr,
-       char *buf);
-extern ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr,
-       const char *buf, size_t count);
+char synth_buffer_getc(void);
+char synth_buffer_peek(void);
+int synth_buffer_empty(void);
+struct var_t *spk_get_var(enum var_id_t var_id);
+ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr,
+                    char *buf);
+ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr,
+                     const char *buf, size_t count);
 
-extern int spk_serial_synth_probe(struct spk_synth *synth);
-extern const char *spk_synth_immediate(struct spk_synth *synth, const char *buff);
-extern void spk_do_catch_up(struct spk_synth *synth);
-extern void spk_synth_flush(struct spk_synth *synth);
-extern int spk_synth_is_alive_nop(struct spk_synth *synth);
-extern int spk_synth_is_alive_restart(struct spk_synth *synth);
-extern void synth_printf(const char *buf, ...);
-extern int synth_request_region(u_long, u_long);
-extern int synth_release_region(u_long, u_long);
-extern int synth_add(struct spk_synth *in_synth);
-extern void synth_remove(struct spk_synth *in_synth);
+int spk_serial_synth_probe(struct spk_synth *synth);
+const char *spk_synth_immediate(struct spk_synth *synth, const char *buff);
+void spk_do_catch_up(struct spk_synth *synth);
+void spk_synth_flush(struct spk_synth *synth);
+int spk_synth_is_alive_nop(struct spk_synth *synth);
+int spk_synth_is_alive_restart(struct spk_synth *synth);
+void synth_printf(const char *buf, ...);
+int synth_request_region(u_long, u_long);
+int synth_release_region(u_long, u_long);
+int synth_add(struct spk_synth *in_synth);
+void synth_remove(struct spk_synth *in_synth);
 
 extern struct speakup_info_t speakup_info;
 
index 8c565c94b8b25445242c34c4e1308925e1416194..e8ff5d7d6419b3f8f53ccc5896c559eccfc83e45 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
 #include <linux/io.h>          /* for inb_p, outb_p, inb, outb, etc... */
+#include <linux/device.h>
 
 enum var_type_t {
        VAR_NUM = 0,
@@ -167,7 +168,8 @@ struct spk_synth {
        int *default_vol;
        int (*probe)(struct spk_synth *synth);
        void (*release)(void);
-       const char *(*synth_immediate)(struct spk_synth *synth, const char *buff);
+       const char *(*synth_immediate)(struct spk_synth *synth,
+                                       const char *buff);
        void (*catch_up)(struct spk_synth *synth);
        void (*flush)(struct spk_synth *synth);
        int (*is_alive)(struct spk_synth *synth);
@@ -179,6 +181,16 @@ struct spk_synth {
        struct attribute_group attributes;
 };
 
+/**
+ * module_spk_synth() - Helper macro for registering a speakup driver
+ * @__spk_synth: spk_synth struct
+ * Helper macro for speakup drivers which do not do anything special in module
+ * init/exit. This eliminates a lot of boilerplate. Each module may only
+ * use this macro once, and calling it replaces module_init() and module_exit()
+ */
+#define module_spk_synth(__spk_synth) \
+       module_driver(__spk_synth, synth_add, synth_remove)
+
 struct speakup_info_t {
        spinlock_t spinlock;
        int port_tts;
index f92ae1d24f9f9a5ba417777294e8c2eb2ce428ea..0f524bb7b41d5bfaba0e038e20846c63d24b7785 100644 (file)
@@ -209,7 +209,7 @@ static int synaptics_rmi4_set_page(struct synaptics_rmi4_data *pdata,
                txbuf[1]        = page;
                retval  = i2c_master_send(i2c, txbuf, PAGE_LEN);
                if (retval != PAGE_LEN)
-                       dev_err(&i2c->dev, "%s:failed:%d\n", __func__, retval);
+                       dev_err(&i2c->dev, "failed:%d\n", retval);
                else
                        pdata->current_page = page;
        } else
@@ -283,7 +283,7 @@ static int synaptics_rmi4_i2c_byte_write(struct synaptics_rmi4_data *pdata,
        retval          = i2c_master_send(pdata->i2c_client, txbuf, 2);
        /* Add in retry on writes only in certain error return values */
        if (retval != 2) {
-               dev_err(&i2c->dev, "%s:failed:%d\n", __func__, retval);
+               dev_err(&i2c->dev, "failed:%d\n", retval);
                retval = -EIO;
        } else
                retval = 1;
@@ -830,8 +830,8 @@ static int synaptics_rmi4_i2c_query_device(struct synaptics_rmi4_data *pdata)
 
        /* Check if this is a Synaptics device - report if not. */
        if (pdata->rmi4_mod_info.manufacturer_id != 1)
-               dev_err(&client->dev, "%s: non-Synaptics mfg id:%d\n",
-                       __func__, pdata->rmi4_mod_info.manufacturer_id);
+               dev_err(&client->dev, "non-Synaptics mfg id:%d\n",
+                       pdata->rmi4_mod_info.manufacturer_id);
 
        list_for_each_entry(rfi, &pdata->rmi4_mod_info.support_fn_list, link)
                data_sources += rfi->num_of_data_sources;
@@ -990,8 +990,8 @@ static int synaptics_rmi4_probe
                                        platformdata->irq_type,
                                        DRIVER_NAME, rmi4_data);
        if (retval) {
-               dev_err(&client->dev, "%s:Unable to get attn irq %d\n",
-                               __func__, client->irq);
+               dev_err(&client->dev, "Unable to get attn irq %d\n",
+                       client->irq);
                goto err_query_dev;
        }
 
@@ -1112,12 +1112,11 @@ static int synaptics_rmi4_resume(struct device *dev)
        return 0;
 }
 
-static const struct dev_pm_ops synaptics_rmi4_dev_pm_ops = {
-       .suspend = synaptics_rmi4_suspend,
-       .resume  = synaptics_rmi4_resume,
-};
 #endif
 
+static SIMPLE_DEV_PM_OPS(synaptics_rmi4_dev_pm_ops, synaptics_rmi4_suspend,
+                        synaptics_rmi4_resume);
+
 static const struct i2c_device_id synaptics_rmi4_id_table[] = {
        { DRIVER_NAME, 0 },
        { },
@@ -1128,9 +1127,7 @@ static struct i2c_driver synaptics_rmi4_driver = {
        .driver = {
                .name   =       DRIVER_NAME,
                .owner  =       THIS_MODULE,
-#ifdef CONFIG_PM
                .pm     =       &synaptics_rmi4_dev_pm_ops,
-#endif
        },
        .probe          =       synaptics_rmi4_probe,
        .remove         =       synaptics_rmi4_remove,
index eb7efe484f6f905c8c43a47c46fe4459583aca09..3bd7579e1daf85800249f804e246a72f9e6a0491 100644 (file)
@@ -337,7 +337,7 @@ struct uiscmdrsp_scsi {
     /* peripheral type of 3 - processor */
     /* specifies device capable, but not present */
 
-#define DEV_HISUPPORT 0x10;    /* HiSup = 1; shows support for report luns */
+#define DEV_HISUPPORT 0x10     /* HiSup = 1; shows support for report luns */
     /* must be returned for lun 0. */
 
 /* NOTE: Linux code assumes inquiry contains 36 bytes. Without checking length
index 78333719c4967164a95e93efd88347d81f1ce344..59a7459eb96243708d21cadc99bcff4eba51802b 100644 (file)
@@ -79,18 +79,15 @@ enum vmcall_monitor_interface_method_tuple { /* VMCALL identification tuples  */
 #define ISSUE_IO_VMCALL(method, param, result) \
        (result = unisys_vmcall(method, (param) & 0xFFFFFFFF,   \
                                (param) >> 32))
-#define ISSUE_IO_EXTENDED_VMCALL(method, param1, param2,       \
-                                param3, result)                        \
-       (result = unisys_extended_vmcall(method, param1,        \
-                                        param2, param3))
+#define ISSUE_IO_EXTENDED_VMCALL(method, param1, param2, param3) \
+       unisys_extended_vmcall(method, param1, param2, param3)
 
     /* The following uses VMCALL_POST_CODE_LOGEVENT interface but is currently
      * not used much */
 #define ISSUE_IO_VMCALL_POSTCODE_SEVERITY(postcode, severity)          \
 do {                                                                   \
-       u32 _tempresult = VMCALL_SUCCESS;                               \
        ISSUE_IO_EXTENDED_VMCALL(VMCALL_POST_CODE_LOGEVENT, severity,   \
-                                MDS_APPOS, postcode, _tempresult);     \
+                                MDS_APPOS, postcode);                  \
 } while (0)
 #endif
 
index 1174056ec3d960e4a347a921cc581b2428daea7c..809c6794290ea00313f20dc5794acf6e6fd23a59 100644 (file)
@@ -26,7 +26,6 @@
 #ifndef __PROCOBJECTTREE_H__
 #define __PROCOBJECTTREE_H__
 
-#include "uniklog.h"
 #include "timskmod.h"
 
 /* These are opaque structures to users.
index 4019a0d63645fe53380caec301679a68f9979e87..cde2494ad896df36a5ff57b9b972469edf4fd744 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/fcntl.h>
-#include <linux/aio.h>
 #include <linux/workqueue.h>
 #include <linux/kthread.h>
 #include <linux/seq_file.h>
 #define HOSTADDRESS unsigned long long
 #endif
 
-/** Try to evaulate the provided expression, and do a RETINT(x) iff
- *  the expression evaluates to < 0.
- */
-#define ASSERT(cond)                                           \
-       do { if (!(cond))                                      \
-                       HUHDRV("ASSERT failed - %s",           \
-                              __stringify(cond));             \
-       } while (0)
-
 #define sizeofmember(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER))
 /** "Covered quotient" function */
 #define COVQ(v, d)  (((v) + (d) - 1) / (d))
                (void *)(p2) = SWAPPOINTERS_TEMP;       \
        } while (0)
 
-#define PRINTKDRV(fmt, args...) LOGINF(fmt, ## args)
-#define TBDDRV(fmt, args...)    LOGERR(fmt, ## args)
-#define HUHDRV(fmt, args...)    LOGERR(fmt, ## args)
-#define ERRDRV(fmt, args...)    LOGERR(fmt, ## args)
 #define WARNDRV(fmt, args...)   LOGWRN(fmt, ## args)
 #define SECUREDRV(fmt, args...) LOGWRN(fmt, ## args)
-#define INFODRV(fmt, args...)   LOGINF(fmt, ## args)
-#define DEBUGDRV(fmt, args...)  DBGINF(fmt, ## args)
 
 #define PRINTKDEV(devname, fmt, args...)  LOGINFDEV(devname, fmt, ## args)
 #define TBDDEV(devname, fmt, args...)     LOGERRDEV(devname, fmt, ## args)
 #define SECUREDEV(devname, fmt, args...)  LOGWRNDEV(devname, fmt, ## args)
 #define INFODEV(devname, fmt, args...)    LOGINFDEV(devname, fmt, ## args)
 #define INFODEVX(devno, fmt, args...)     LOGINFDEVX(devno, fmt, ## args)
-#define DEBUGDEV(devname, fmt, args...)   DBGINFDEV(devname, fmt, ## args)
 
 /** Verifies the consistency of your PRIVATEDEVICEDATA structure using
  *  conventional "signature" fields:
index 25b6181d78af99c3beafebfe5d1e25dac3ee42a3..08ba16ea840ee5087a633840fd5fba15d26daf90 100644 (file)
@@ -25,7 +25,6 @@
 
 #include "linux/version.h"
 #include "iochannel.h"
-#include "uniklog.h"
 #include <linux/atomic.h>
 #include <linux/semaphore.h>
 #include <linux/uuid.h>
index aa86ade7cb13a9c00559e48249fb0e8f87e7bb36..52c3eb4ded2c5c3deb465b32bb012026d922ae36 100644 (file)
@@ -27,7 +27,6 @@
 struct uisthread_info {
        struct task_struct *task;
        int id;
-       int should_stop;
        struct completion has_stopped;
 };
 
index 7414220676d3d9c3aeb5e3ebb05916d53d1762c1..c7d0ba8aafd8aa77f9b4adab81b03f6933d73766 100644 (file)
@@ -65,17 +65,7 @@ struct req_handler_info {
        struct list_head list_link;     /* links into ReqHandlerInfo_list */
 };
 
-struct req_handler_info *req_handler_add(uuid_le switch_uuid,
-                               const char *switch_type_name,
-                               int (*controlfunc)(struct io_msgs *),
-                               unsigned long min_channel_bytes,
-                               int (*svr_channel_ok)(unsigned long
-                                                        channel_bytes),
-                               int (*svr_channel_init)(void *x,
-                                               unsigned char *client_str,
-                                               u32 client_str_len, u64 bytes));
 struct req_handler_info *req_handler_find(uuid_le switch_uuid);
-int req_handler_del(uuid_le switch_uuid);
 
 #define uislib_ioremap_cache(addr, size) \
        dbg_ioremap_cache(addr, size, __FILE__, __LINE__)
@@ -115,19 +105,7 @@ int uisutil_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining,
 
 int uisctrl_register_req_handler(int type, void *fptr,
                        struct ultra_vbus_deviceinfo *chipset_driver_info);
-int uisctrl_register_req_handler_ex(uuid_le switch_guid,
-                       const char *switch_type_name,
-                       int (*fptr)(struct io_msgs *),
-                       unsigned long min_channel_bytes,
-                       int (*svr_channel_ok)(unsigned long
-                                             channel_bytes),
-                       int (*svr_channel_init)(void *x,
-                                               unsigned char *client_str,
-                                               u32 client_str_len,
-                                               u64 bytes),
-                       struct ultra_vbus_deviceinfo *chipset_driver_info);
 
-int uisctrl_unregister_req_handler_ex(uuid_le switch_uuid);
 unsigned char *util_map_virt(struct phys_info *sg);
 void util_unmap_virt(struct phys_info *sg);
 unsigned char *util_map_virt_atomic(struct phys_info *sg);
@@ -206,21 +184,10 @@ wait_for_valid_guid(uuid_le __iomem *guid)
                              (void __iomem *)guid, sizeof(uuid_le));
                if (uuid_le_cmp(tmpguid, NULL_UUID_LE) != 0)
                        break;
-               LOGERR("Waiting for non-0 GUID (why???)...\n");
                UIS_THREAD_WAIT_SEC(5);
        }
-       LOGERR("OK... GUID is non-0 now\n");
 }
 
-/* CopyFragsInfoFromSkb returns the number of entries added to frags array
- * Returns -1 on failure.
- */
-unsigned int uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx,
-                                            void *skb_in,
-                                            unsigned int firstfraglen,
-                                            unsigned int frags_max,
-                                            struct phys_info frags[]);
-
 static inline unsigned int
 issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes)
 {
diff --git a/drivers/staging/unisys/include/uniklog.h b/drivers/staging/unisys/include/uniklog.h
deleted file mode 100644 (file)
index ecd1bdb..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/* uniklog.h
- *
- * Copyright (C) 2010 - 2013 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 distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-/* This module contains macros to aid developers in logging messages.
- *
- * This module is affected by the DEBUG compiletime option.
- *
- */
-#ifndef __UNIKLOG_H__
-#define __UNIKLOG_H__
-
-#include <linux/printk.h>
-
-/*
- * # DBGINF
- *
- * \brief Log debug informational message - log a LOG_INFO message only
- *        if DEBUG compiletime option enabled
- *
- * \param devname the device name of the device reporting this message, or
- *                NULL if this message is NOT device-related.
- * \param fmt printf()-style format string containing the message to log.
- * \param args Optional arguments to be formatted and inserted into the
- *             format string.
- * \return nothing
- *
- * Log a message at the LOG_INFO level, but only if DEBUG is enabled.  If
- * DEBUG is disabled, this expands to a no-op.
- */
-
-/*
- * # DBGVER
- *
- * \brief Log debug verbose message - log a LOG_DEBUG message only if
- *        DEBUG compiletime option enabled
- *
- * \param devname the device name of the device reporting this message, or
- *                NULL if this message is NOT device-related.
- * \param fmt printf()-style format string containing the message to log.
- * \param args Optional arguments to be formatted and inserted into the
- *             format string.
- * \return nothing
- *
- * Log a message at the LOG_DEBUG level, but only if DEBUG is enabled.  If
- * DEBUG is disabled, this expands to a no-op.  Note also that LOG_DEBUG
- * messages can be enabled/disabled at runtime as well.
- */
-#define DBGINFDEV(devname, fmt, args...)        do { } while (0)
-#define DBGVERDEV(devname, fmt, args...)        do { } while (0)
-#define DBGINF(fmt, args...)                    do { } while (0)
-#define DBGVER(fmt, args...)                    do { } while (0)
-
-/*
- * # LOGINF
- *
- * \brief Log informational message - logs a message at the LOG_INFO level
- *
- * \param devname the device name of the device reporting this message, or
- *                NULL if this message is NOT device-related.
- * \param fmt printf()-style format string containing the message to log.
- * \param args Optional arguments to be formatted and inserted into the
- *             format string.
- * \return nothing
- *
- * Logs the specified message at the LOG_INFO level.
- */
-
-#define LOGINF(fmt, args...) pr_info(fmt, ## args)
-#define LOGINFDEV(devname, fmt, args...) \
-       pr_info("%s " fmt, devname, ## args)
-#define LOGINFDEVX(devno, fmt, args...) \
-       pr_info("dev%d " fmt, devno, ## args)
-#define LOGINFNAME(vnic, fmt, args...)                         \
-       do {                                                            \
-               if (vnic != NULL) {                                     \
-                       pr_info("%s " fmt, vnic->name, ## args);        \
-               } else {                                                \
-                       pr_info(fmt, ## args);                          \
-               }                                                       \
-       } while (0)
-
-/*
- * # LOGVER
- *
- * \brief Log verbose message - logs a message at the LOG_DEBUG level,
- *        which can be disabled at runtime
- *
- * \param devname the device name of the device reporting this message, or
- *                NULL if this message is NOT device-related.
- * \param fmt printf()-style format string containing the message to log.
- * \param args Optional arguments to be formatted and inserted into the format
- * \param string.
- * \return nothing
- *
- * Logs the specified message at the LOG_DEBUG level.  Note also that
- * LOG_DEBUG messages can be enabled/disabled at runtime as well.
- */
-#define LOGVER(fmt, args...) pr_debug(fmt, ## args)
-#define LOGVERDEV(devname, fmt, args...) \
-       pr_debug("%s " fmt, devname, ## args)
-#define LOGVERNAME(vnic, fmt, args...)                                 \
-       do {                                                            \
-               if (vnic != NULL) {                                     \
-                       pr_debug("%s " fmt, vnic->name, ## args);       \
-               } else {                                                \
-                       pr_debug(fmt, ## args);                         \
-               }                                                       \
-       } while (0)
-
-/*
- * # LOGERR
- *
- * \brief Log error message - logs a message at the LOG_ERR level,
- *        including source line number information
- *
- * \param devname the device name of the device reporting this message, or
- *                NULL if this message is NOT device-related.
- * \param fmt printf()-style format string containing the message to log.
- * \param args Optional arguments to be formatted and inserted into the format
- * \param string.
- * \return nothing
- *
- * Logs the specified error message at the LOG_ERR level.  It will also
- * include the file, line number, and function name of where the error
- * originated in the log message.
- */
-#define LOGERR(fmt, args...) pr_err(fmt, ## args)
-#define LOGERRDEV(devname, fmt, args...) \
-       pr_err("%s " fmt, devname, ## args)
-#define LOGERRDEVX(devno, fmt, args...) \
-       pr_err("dev%d " fmt, devno, ## args)
-#define LOGERRNAME(vnic, fmt, args...)                         \
-       do {                                                            \
-               if (vnic != NULL) {                                     \
-                       pr_err("%s " fmt, vnic->name, ## args); \
-               } else {                                                \
-                       pr_err(fmt, ## args);                           \
-               }                                                       \
-       } while (0)
-#define LOGORDUMPERR(seqfile, fmt, args...) do {               \
-               if (seqfile) {                                  \
-                       seq_printf(seqfile, fmt, ## args);      \
-               } else {                                        \
-                       LOGERR(fmt, ## args);                   \
-               }                                               \
-       } while (0)
-
-/*
- * # LOGWRN
- *
- * \brief Log warning message - Logs a message at the LOG_WARNING level,
- *        including source line number information
- *
- * \param devname the device name of the device reporting this message, or
- *                NULL if this message is NOT device-related.
- * \param fmt printf()-style format string containing the message to log.
- * \param args Optional arguments to be formatted and inserted into the format
- * \param string.
- * \return nothing
- *
- * Logs the specified error message at the LOG_WARNING level.  It will also
- * include the file, line number, and function name of where the error
- * originated in the log message.
- */
-#define LOGWRN(fmt, args...) pr_warn(fmt, ## args)
-#define LOGWRNDEV(devname, fmt, args...) \
-       pr_warn("%s " fmt, devname, ## args)
-#define LOGWRNNAME(vnic, fmt, args...) \
-       do {                                                            \
-               if (vnic != NULL) {                                     \
-                       pr_warn("%s " fmt, vnic->name, ## args);        \
-               } else {                                                \
-                       pr_warn(fmt, ## args);                          \
-               }                                                       \
-       } while (0)
-
-#endif /* __UNIKLOG_H__ */
index a712eb82224a4f68ae34e812f09140d4bffdf2b2..c39a0a21ae5fa7699c10099da1072c8d8dff6038 100644 (file)
@@ -4,7 +4,7 @@
 
 config UNISYS_UISLIB
        tristate "Unisys uislib driver"
-       depends on UNISYSSPAR && UNISYS_VISORCHIPSET && HAS_IOMEM
+       select UNISYS_VISORCHIPSET
        ---help---
        If you say Y here, you will enable the Unisys uislib driver.
 
index 08e620d1749792feff77f39616f5b4872793b965..860f494f132faff2c784f01651468168ecdfa873 100644 (file)
@@ -7,8 +7,6 @@ obj-$(CONFIG_UNISYS_UISLIB)     += visoruislib.o
 visoruislib-y := uislib.o uisqueue.o  uisthread.o  uisutils.o
 
 ccflags-y += -Idrivers/staging/unisys/include
-ccflags-y += -Idrivers/staging/unisys/channels
 ccflags-y += -Idrivers/staging/unisys/visorchipset
-ccflags-y += -Idrivers/staging/unisys/sparstopdriver
 ccflags-y += -Idrivers/staging/unisys/common-spar/include
 ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
index a9eeddeba7354cf8466e7ad0709070ab569fb06a..f93d0bb11b12d67f8d3b170e693b83e916c88f92 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/uuid.h>
 
 #include <linux/version.h>
-#include "uniklog.h"
 #include "diagnostics/appos_subsystems.h"
 #include "uisutils.h"
 #include "vbuschannel.h"
@@ -132,14 +131,10 @@ static __iomem void *init_vbus_channel(u64 ch_addr, u32 ch_bytes)
 {
        void __iomem *ch = uislib_ioremap_cache(ch_addr, ch_bytes);
 
-       if (!ch) {
-               LOGERR("CONTROLVM_BUS_CREATE error: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
-                      (unsigned long long)ch_addr,
-                      (unsigned long long)ch_bytes);
+       if (!ch)
                return NULL;
-       }
+
        if (!SPAR_VBUS_CHANNEL_OK_CLIENT(ch)) {
-               ERRDRV("%s channel cannot be used", __func__);
                uislib_iounmap(ch);
                return NULL;
        }
@@ -154,8 +149,6 @@ create_bus(struct controlvm_message *msg, char *buf)
        size_t size;
 
        if (max_bus_count == bus_list_count) {
-               LOGERR("CONTROLVM_BUS_CREATE Failed: max buses:%d already created\n",
-                      max_bus_count);
                POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, max_bus_count,
                                 POSTCODE_SEVERITY_ERR);
                return CONTROLVM_RESP_ERROR_MAX_BUSES;
@@ -172,7 +165,6 @@ create_bus(struct controlvm_message *msg, char *buf)
            (dev_count * sizeof(struct device_info *));
        bus = kzalloc(size, GFP_ATOMIC);
        if (!bus) {
-               LOGERR("CONTROLVM_BUS_CREATE Failed: kmalloc for bus failed.\n");
                POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                return CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
@@ -209,8 +201,6 @@ create_bus(struct controlvm_message *msg, char *buf)
                /* found a bus already in the list with same bus_no -
                 * reject add
                 */
-               LOGERR("CONTROLVM_BUS_CREATE Failed: bus %d already exists.\n",
-                      bus->bus_no);
                POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->bus_no,
                                 POSTCODE_SEVERITY_ERR);
                kfree(bus);
@@ -234,14 +224,12 @@ create_bus(struct controlvm_message *msg, char *buf)
                cmd.add_vbus.bus_uuid = msg->cmd.create_bus.bus_data_type_uuid;
                cmd.add_vbus.instance_uuid = msg->cmd.create_bus.bus_inst_uuid;
                if (!virt_control_chan_func) {
-                       LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci callback not registered.");
                        POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->bus_no,
                                         POSTCODE_SEVERITY_ERR);
                        kfree(bus);
                        return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
                }
                if (!virt_control_chan_func(&cmd)) {
-                       LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci GUEST_ADD_VBUS returned error.");
                        POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->bus_no,
                                         POSTCODE_SEVERITY_ERR);
                        kfree(bus);
@@ -287,17 +275,13 @@ destroy_bus(struct controlvm_message *msg, char *buf)
        }
 
        if (!bus) {
-               LOGERR("CONTROLVM_BUS_DESTROY Failed: failed to find bus %d.\n",
-                      bus_no);
                read_unlock(&bus_list_lock);
                return CONTROLVM_RESP_ERROR_ALREADY_DONE;
        }
 
        /* verify that this bus has no devices. */
        for (i = 0; i < bus->device_count; i++) {
-               if (bus->device[i] != NULL) {
-                       LOGERR("CONTROLVM_BUS_DESTROY Failed: device %i attached to bus %d.",
-                              i, bus_no);
+               if (bus->device[i]) {
                        read_unlock(&bus_list_lock);
                        return CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED;
                }
@@ -311,14 +295,11 @@ destroy_bus(struct controlvm_message *msg, char *buf)
           with this bus. */
        cmd.msgtype = GUEST_DEL_VBUS;
        cmd.del_vbus.bus_no = bus_no;
-       if (!virt_control_chan_func) {
-               LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci callback not registered.");
+       if (!virt_control_chan_func)
                return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
-       }
-       if (!virt_control_chan_func(&cmd)) {
-               LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci GUEST_DEL_VBUS returned error.");
+
+       if (!virt_control_chan_func(&cmd))
                return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
-       }
 
        /* finally, remove the bus from the list */
 remove:
@@ -357,7 +338,6 @@ static int create_device(struct controlvm_message *msg, char *buf)
 
        dev = kzalloc(sizeof(*dev), GFP_ATOMIC);
        if (!dev) {
-               LOGERR("CONTROLVM_DEVICE_CREATE Failed: kmalloc for dev failed.\n");
                POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                return CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
@@ -381,9 +361,6 @@ static int create_device(struct controlvm_message *msg, char *buf)
                         */
                        min_size = req_handler->min_channel_bytes;
                if (min_size > msg->cmd.create_device.channel_bytes) {
-                       LOGERR("CONTROLVM_DEVICE_CREATE Failed: channel size is too small, channel size:0x%lx, required size:0x%lx",
-                              (ulong)msg->cmd.create_device.channel_bytes,
-                              (ulong)min_size);
                        POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no,
                                         bus_no, POSTCODE_SEVERITY_ERR);
                        result = CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL;
@@ -393,9 +370,6 @@ static int create_device(struct controlvm_message *msg, char *buf)
                    uislib_ioremap_cache(dev->channel_addr,
                                         msg->cmd.create_device.channel_bytes);
                if (!dev->chanptr) {
-                       LOGERR("CONTROLVM_DEVICE_CREATE Failed: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
-                              dev->channel_addr,
-                              msg->cmd.create_device.channel_bytes);
                        result = CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
                        POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no,
                                         bus_no, POSTCODE_SEVERITY_ERR);
@@ -411,8 +385,6 @@ static int create_device(struct controlvm_message *msg, char *buf)
                        continue;
                /* make sure the device number is valid */
                if (dev_no >= bus->device_count) {
-                       LOGERR("CONTROLVM_DEVICE_CREATE Failed: device (%d) >= deviceCount (%d).",
-                              dev_no, bus->device_count);
                        result = CONTROLVM_RESP_ERROR_MAX_DEVICES;
                        POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no,
                                         bus_no, POSTCODE_SEVERITY_ERR);
@@ -421,8 +393,6 @@ static int create_device(struct controlvm_message *msg, char *buf)
                }
                /* make sure this device is not already set */
                if (bus->device[dev_no]) {
-                       LOGERR("CONTROLVM_DEVICE_CREATE Failed: device %d is already exists.",
-                              dev_no);
                        POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC,
                                         dev_no, bus_no,
                                         POSTCODE_SEVERITY_ERR);
@@ -445,8 +415,6 @@ static int create_device(struct controlvm_message *msg, char *buf)
                        wait_for_valid_guid(&((struct channel_header __iomem *)
                                            (dev->chanptr))->chtype);
                        if (!SPAR_VHBA_CHANNEL_OK_CLIENT(dev->chanptr)) {
-                               LOGERR("CONTROLVM_DEVICE_CREATE Failed:[CLIENT]VHBA dev %d chan invalid.",
-                                      dev_no);
                                POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC,
                                                 dev_no, bus_no,
                                                 POSTCODE_SEVERITY_ERR);
@@ -464,8 +432,6 @@ static int create_device(struct controlvm_message *msg, char *buf)
                        wait_for_valid_guid(&((struct channel_header __iomem *)
                                            (dev->chanptr))->chtype);
                        if (!SPAR_VNIC_CHANNEL_OK_CLIENT(dev->chanptr)) {
-                               LOGERR("CONTROLVM_DEVICE_CREATE Failed: VNIC[CLIENT] dev %d chan invalid.",
-                                      dev_no);
                                POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC,
                                                 dev_no, bus_no,
                                                 POSTCODE_SEVERITY_ERR);
@@ -479,7 +445,6 @@ static int create_device(struct controlvm_message *msg, char *buf)
                        cmd.add_vnic.instance_uuid = dev->instance_uuid;
                        cmd.add_vhba.intr = dev->intr;
                } else {
-                       LOGERR("CONTROLVM_DEVICE_CREATE Failed: unknown channelTypeGuid.\n");
                        POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no,
                                         bus_no, POSTCODE_SEVERITY_ERR);
                        result = CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
@@ -487,7 +452,6 @@ static int create_device(struct controlvm_message *msg, char *buf)
                }
 
                if (!virt_control_chan_func) {
-                       LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci callback not registered.");
                        POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no,
                                         bus_no, POSTCODE_SEVERITY_ERR);
                        result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
@@ -495,7 +459,6 @@ static int create_device(struct controlvm_message *msg, char *buf)
                }
 
                if (!virt_control_chan_func(&cmd)) {
-                       LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci GUEST_ADD_[VHBA||VNIC] returned error.");
                        POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no,
                                         bus_no, POSTCODE_SEVERITY_ERR);
                        result =
@@ -510,8 +473,6 @@ static int create_device(struct controlvm_message *msg, char *buf)
        }
        read_unlock(&bus_list_lock);
 
-       LOGERR("CONTROLVM_DEVICE_CREATE Failed: failed to find bus %d.",
-              bus_no);
        POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
                         POSTCODE_SEVERITY_ERR);
        result = CONTROLVM_RESP_ERROR_BUS_INVALID;
@@ -542,15 +503,11 @@ static int pause_device(struct controlvm_message *msg)
                if (bus->bus_no == bus_no) {
                        /* make sure the device number is valid */
                        if (dev_no >= bus->device_count) {
-                               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device(%d) >= deviceCount(%d).",
-                                      dev_no, bus->device_count);
                                retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID;
                        } else {
                                /* make sure this device exists */
                                dev = bus->device[dev_no];
                                if (!dev) {
-                                       LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device %d does not exist.",
-                                              dev_no);
                                        retval =
                                          CONTROLVM_RESP_ERROR_ALREADY_DONE;
                                }
@@ -558,11 +515,9 @@ static int pause_device(struct controlvm_message *msg)
                        break;
                }
        }
-       if (!bus) {
-               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: bus %d does not exist",
-                      bus_no);
+       if (!bus)
                retval = CONTROLVM_RESP_ERROR_BUS_INVALID;
-       }
+
        read_unlock(&bus_list_lock);
        if (retval == CONTROLVM_RESP_SUCCESS) {
                /* the msg is bound for virtpci; send
@@ -577,15 +532,11 @@ static int pause_device(struct controlvm_message *msg)
                        cmd.msgtype = GUEST_PAUSE_VNIC;
                        cmd.pause_vnic.chanptr = dev->chanptr;
                } else {
-                       LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: unknown channelTypeGuid.\n");
                        return CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
                }
-               if (!virt_control_chan_func) {
-                       LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
+               if (!virt_control_chan_func)
                        return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
-               }
                if (!virt_control_chan_func(&cmd)) {
-                       LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: virtpci GUEST_PAUSE_[VHBA||VNIC] returned error.");
                        return
                          CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
                }
@@ -609,15 +560,11 @@ static int resume_device(struct controlvm_message *msg)
                if (bus->bus_no == bus_no) {
                        /* make sure the device number is valid */
                        if (dev_no >= bus->device_count) {
-                               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device(%d) >= deviceCount(%d).",
-                                      dev_no, bus->device_count);
                                retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID;
                        } else {
                                /* make sure this device exists */
                                dev = bus->device[dev_no];
                                if (!dev) {
-                                       LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device %d does not exist.",
-                                              dev_no);
                                        retval =
                                          CONTROLVM_RESP_ERROR_ALREADY_DONE;
                                }
@@ -626,11 +573,9 @@ static int resume_device(struct controlvm_message *msg)
                }
        }
 
-       if (!bus) {
-               LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: bus %d does not exist",
-                      bus_no);
+       if (!bus)
                retval = CONTROLVM_RESP_ERROR_BUS_INVALID;
-       }
+
        read_unlock(&bus_list_lock);
        /* the msg is bound for virtpci; send
         * guest_msgs struct to callback
@@ -645,15 +590,11 @@ static int resume_device(struct controlvm_message *msg)
                        cmd.msgtype = GUEST_RESUME_VNIC;
                        cmd.resume_vnic.chanptr = dev->chanptr;
                } else {
-                       LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: unknown channelTypeGuid.\n");
                        return CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
                }
-               if (!virt_control_chan_func) {
-                       LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
+               if (!virt_control_chan_func)
                        return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
-               }
                if (!virt_control_chan_func(&cmd)) {
-                       LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: virtpci GUEST_RESUME_[VHBA||VNIC] returned error.");
                        return
                          CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
                }
@@ -673,21 +614,15 @@ static int destroy_device(struct controlvm_message *msg, char *buf)
        dev_no = msg->cmd.destroy_device.bus_no;
 
        read_lock(&bus_list_lock);
-       LOGINF("destroy_device called for bus_no=%u, dev_no=%u", bus_no,
-              dev_no);
        for (bus = bus_list; bus; bus = bus->next) {
                if (bus->bus_no == bus_no) {
                        /* make sure the device number is valid */
                        if (dev_no >= bus->device_count) {
-                               LOGERR("CONTROLVM_DEVICE_DESTROY Failed: device(%d) >= device_count(%d).",
-                                      dev_no, bus->device_count);
                                retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID;
                        } else {
                                /* make sure this device exists */
                                dev = bus->device[dev_no];
                                if (!dev) {
-                                       LOGERR("CONTROLVM_DEVICE_DESTROY Failed: device %d does not exist.",
-                                              dev_no);
                                        retval =
                                             CONTROLVM_RESP_ERROR_ALREADY_DONE;
                                }
@@ -696,11 +631,8 @@ static int destroy_device(struct controlvm_message *msg, char *buf)
                }
        }
 
-       if (!bus) {
-               LOGERR("CONTROLVM_DEVICE_DESTROY Failed: bus %d does not exist",
-                      bus_no);
+       if (!bus)
                retval = CONTROLVM_RESP_ERROR_BUS_INVALID;
-       }
        read_unlock(&bus_list_lock);
        if (retval == CONTROLVM_RESP_SUCCESS) {
                /* the msg is bound for virtpci; send
@@ -715,17 +647,14 @@ static int destroy_device(struct controlvm_message *msg, char *buf)
                        cmd.msgtype = GUEST_DEL_VNIC;
                        cmd.del_vnic.chanptr = dev->chanptr;
                } else {
-                       LOGERR("CONTROLVM_DEVICE_DESTROY Failed: unknown channelTypeGuid.\n");
                        return
                            CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
                }
                if (!virt_control_chan_func) {
-                       LOGERR("CONTROLVM_DEVICE_DESTROY Failed: virtpci callback not registered.");
                        return
                            CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
                }
                if (!virt_control_chan_func(&cmd)) {
-                       LOGERR("CONTROLVM_DEVICE_DESTROY Failed: virtpci GUEST_DEL_[VHBA||VNIC] returned error.");
                        return
                            CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
                }
@@ -734,15 +663,11 @@ static int destroy_device(struct controlvm_message *msg, char *buf)
  * on which accesses the channel and you will get a "unable to handle
  * kernel paging request"
  */
-               if (dev->polling) {
-                       LOGINF("calling uislib_disable_channel_interrupts");
+               if (dev->polling)
                        uislib_disable_channel_interrupts(bus_no, dev_no);
-               }
                /* unmap the channel memory for the device. */
-               if (!msg->hdr.flags.test_message) {
-                       LOGINF("destroy_device, doing iounmap");
+               if (!msg->hdr.flags.test_message)
                        uislib_iounmap(dev->chanptr);
-               }
                kfree(dev);
                bus->device[dev_no] = NULL;
        }
@@ -780,10 +705,8 @@ static int delete_bus_glue(u32 bus_no)
 
        init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
        msg.cmd.destroy_bus.bus_no = bus_no;
-       if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
-               LOGERR("destroy_bus failed. bus_no=0x%x\n", bus_no);
+       if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS)
                return 0;
-       }
        return 1;
 }
 
@@ -794,11 +717,8 @@ static int delete_device_glue(u32 bus_no, u32 dev_no)
        init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0);
        msg.cmd.destroy_device.bus_no = bus_no;
        msg.cmd.destroy_device.dev_no = dev_no;
-       if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
-               LOGERR("destroy_device failed. bus_no=0x%x dev_no=0x%x\n",
-                      bus_no, dev_no);
+       if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS)
                return 0;
-       }
        return 1;
 }
 
@@ -808,7 +728,6 @@ uislib_client_inject_add_bus(u32 bus_no, uuid_le inst_uuid,
 {
        struct controlvm_message msg;
 
-       LOGINF("enter busNo=0x%x\n", bus_no);
        /* step 0: init the chipset */
        POSTCODE_LINUX_3(CHIPSET_INIT_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO);
 
@@ -824,11 +743,8 @@ uislib_client_inject_add_bus(u32 bus_no, uuid_le inst_uuid,
                */
                msg.cmd.init_chipset.bus_count = 23;
                msg.cmd.init_chipset.switch_count = 0;
-               if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
-                       LOGERR("init_chipset failed.\n");
+               if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS)
                        return 0;
-               }
-               LOGINF("chipset initialized\n");
                POSTCODE_LINUX_3(CHIPSET_INIT_EXIT_PC, bus_no,
                                 POSTCODE_SEVERITY_INFO);
        }
@@ -842,7 +758,6 @@ uislib_client_inject_add_bus(u32 bus_no, uuid_le inst_uuid,
        msg.cmd.create_bus.channel_addr = channel_addr;
        msg.cmd.create_bus.channel_bytes = n_channel_bytes;
        if (create_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
-               LOGERR("create_bus failed.\n");
                POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                return 0;
@@ -871,11 +786,8 @@ uislib_client_inject_pause_vhba(u32 bus_no, u32 dev_no)
        msg.cmd.device_change_state.dev_no = dev_no;
        msg.cmd.device_change_state.state = segment_state_standby;
        rc = pause_device(&msg);
-       if (rc != CONTROLVM_RESP_SUCCESS) {
-               LOGERR("VHBA pause_device failed. busNo=0x%x devNo=0x%x\n",
-                      bus_no, dev_no);
+       if (rc != CONTROLVM_RESP_SUCCESS)
                return rc;
-       }
        return 0;
 }
 EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vhba);
@@ -891,11 +803,8 @@ uislib_client_inject_resume_vhba(u32 bus_no, u32 dev_no)
        msg.cmd.device_change_state.dev_no = dev_no;
        msg.cmd.device_change_state.state = segment_state_running;
        rc = resume_device(&msg);
-       if (rc != CONTROLVM_RESP_SUCCESS) {
-               LOGERR("VHBA resume_device failed. busNo=0x%x devNo=0x%x\n",
-                      bus_no, dev_no);
+       if (rc != CONTROLVM_RESP_SUCCESS)
                return rc;
-       }
        return 0;
 }
 EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vhba);
@@ -908,7 +817,6 @@ uislib_client_inject_add_vhba(u32 bus_no, u32 dev_no,
 {
        struct controlvm_message msg;
 
-       LOGINF(" enter busNo=0x%x devNo=0x%x\n", bus_no, dev_no);
        /* chipset init'ed with bus bus has been previously created -
        * Verify it still exists step 2: create the VHBA device on the
        * bus
@@ -932,8 +840,6 @@ uislib_client_inject_add_vhba(u32 bus_no, u32 dev_no,
                       sizeof(struct irq_info));
        msg.cmd.create_device.channel_addr = phys_chan_addr;
        if (chan_bytes < MIN_IO_CHANNEL_SIZE) {
-               LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n",
-                      chan_bytes, (unsigned int)MIN_IO_CHANNEL_SIZE);
                POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, chan_bytes,
                                 MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR);
                return 0;
@@ -941,7 +847,6 @@ uislib_client_inject_add_vhba(u32 bus_no, u32 dev_no,
        msg.cmd.create_device.channel_bytes = chan_bytes;
        msg.cmd.create_device.data_type_uuid = spar_vhba_channel_protocol_uuid;
        if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
-               LOGERR("VHBA create_device failed.\n");
                POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, dev_no, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                return 0;
@@ -967,7 +872,6 @@ uislib_client_inject_add_vnic(u32 bus_no, u32 dev_no,
 {
        struct controlvm_message msg;
 
-       LOGINF(" enter busNo=0x%x devNo=0x%x\n", bus_no, dev_no);
        /* chipset init'ed with bus bus has been previously created -
        * Verify it still exists step 2: create the VNIC device on the
        * bus
@@ -991,8 +895,6 @@ uislib_client_inject_add_vnic(u32 bus_no, u32 dev_no,
                       sizeof(struct irq_info));
        msg.cmd.create_device.channel_addr = phys_chan_addr;
        if (chan_bytes < MIN_IO_CHANNEL_SIZE) {
-               LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n",
-                      chan_bytes, (unsigned int)MIN_IO_CHANNEL_SIZE);
                POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, chan_bytes,
                                 MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR);
                return 0;
@@ -1000,7 +902,6 @@ uislib_client_inject_add_vnic(u32 bus_no, u32 dev_no,
        msg.cmd.create_device.channel_bytes = chan_bytes;
        msg.cmd.create_device.data_type_uuid = spar_vnic_channel_protocol_uuid;
        if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
-               LOGERR("VNIC create_device failed.\n");
                POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, dev_no, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                return 0;
@@ -1023,11 +924,8 @@ uislib_client_inject_pause_vnic(u32 bus_no, u32 dev_no)
        msg.cmd.device_change_state.dev_no = dev_no;
        msg.cmd.device_change_state.state = segment_state_standby;
        rc = pause_device(&msg);
-       if (rc != CONTROLVM_RESP_SUCCESS) {
-               LOGERR("VNIC pause_device failed. busNo=0x%x devNo=0x%x\n",
-                      bus_no, dev_no);
+       if (rc != CONTROLVM_RESP_SUCCESS)
                return -1;
-       }
        return 0;
 }
 EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vnic);
@@ -1043,11 +941,8 @@ uislib_client_inject_resume_vnic(u32 bus_no, u32 dev_no)
        msg.cmd.device_change_state.dev_no = dev_no;
        msg.cmd.device_change_state.state = segment_state_running;
        rc = resume_device(&msg);
-       if (rc != CONTROLVM_RESP_SUCCESS) {
-               LOGERR("VNIC resume_device failed. busNo=0x%x devNo=0x%x\n",
-                      bus_no, dev_no);
+       if (rc != CONTROLVM_RESP_SUCCESS)
                return -1;
-       }
        return 0;
 }
 EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vnic);
@@ -1069,11 +964,8 @@ uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln)
        */
        void *p = kmem_cache_alloc(cur_pool, GFP_ATOMIC | __GFP_NORETRY);
 
-       if (p == NULL) {
-               LOGERR("uislib_malloc failed to alloc uiscmdrsp @%s:%d",
-                      fn, ln);
+       if (!p)
                return NULL;
-       }
        return p;
 }
 EXPORT_SYMBOL_GPL(uislib_cache_alloc);
@@ -1081,10 +973,8 @@ EXPORT_SYMBOL_GPL(uislib_cache_alloc);
 void
 uislib_cache_free(struct kmem_cache *cur_pool, void *p, char *fn, int ln)
 {
-       if (p == NULL) {
-               LOGERR("uislib_free NULL pointer @%s:%d", fn, ln);
+       if (!p)
                return;
-       }
        kmem_cache_free(cur_pool, p);
 }
 EXPORT_SYMBOL_GPL(uislib_cache_free);
@@ -1162,20 +1052,16 @@ static ssize_t info_debugfs_read(struct file *file, char __user *buf,
        int remaining_bytes = PROC_READ_BUFFER_SIZE;
 
 /* *start = buf; */
-       if (debug_buf == NULL) {
-               DBGINF("debug_buf == NULL; allocating buffer.\n.");
+       if (!debug_buf) {
                debug_buf = vmalloc(PROC_READ_BUFFER_SIZE);
 
-               if (debug_buf == NULL) {
-                       LOGERR("failed to allocate buffer to provide proc data.\n");
+               if (!debug_buf)
                        return -ENOMEM;
-               }
        }
 
        temp = debug_buf;
 
        if ((*offset == 0) || (!debug_buf_valid)) {
-               DBGINF("calling info_debugfs_read_helper.\n");
                /* if the read fails, then -1 will be returned */
                total_bytes = info_debugfs_read_helper(&temp, &remaining_bytes);
                debug_buf_valid = 1;
@@ -1196,17 +1082,9 @@ static struct device_info *find_dev(u32 bus_no, u32 dev_no)
        for (bus = bus_list; bus; bus = bus->next) {
                if (bus->bus_no == bus_no) {
                        /* make sure the device number is valid */
-                       if (dev_no >= bus->device_count) {
-                               LOGERR("%s bad bus_no, dev_no=%d,%d",
-                                      __func__,
-                                      (int)bus_no, (int)dev_no);
+                       if (dev_no >= bus->device_count)
                                break;
-                       }
                        dev = bus->device[dev_no];
-                       if (!dev)
-                               LOGERR("%s bad bus_no, dev_no=%d,%d",
-                                      __func__,
-                                      (int)bus_no, (int)dev_no);
                        break;
                }
        }
@@ -1253,7 +1131,6 @@ static int process_incoming(void *v)
                                wait_cycles = (cur_cycles - old_cycles);
                }
        }
-       LOGINF("wait_cycles=%llu", wait_cycles);
        cycles_before_wait = wait_cycles;
        idle_cycles = 0;
        poll_dev_start = 0;
@@ -1281,7 +1158,7 @@ static int process_incoming(void *v)
                                * Reschedule work to occur as soon as
                                * possible. */
                                idle_cycles = 0;
-                               if (new_tail == NULL) {
+                               if (!new_tail) {
                                        dev->first_busy_cnt++;
                                        if (!
                                            (list_is_last
@@ -1294,10 +1171,10 @@ static int process_incoming(void *v)
                                        }
                                }
                        }
-                       if (incoming_ti.should_stop)
+                       if (kthread_should_stop())
                                break;
                }
-               if (new_tail != NULL) {
+               if (new_tail) {
                        tot_moved_to_tail_cnt++;
                        list_move_tail(new_tail, &poll_dev_chan);
                }
@@ -1311,12 +1188,10 @@ static int process_incoming(void *v)
                * - there is no input waiting on any of the channels
                * - we have received a signal to stop this thread
                */
-               if (incoming_ti.should_stop)
+               if (kthread_should_stop())
                        break;
-               if (en_smart_wakeup == 0xFF) {
-                       LOGINF("en_smart_wakeup set to 0xff, to force exiting process_incoming");
+               if (en_smart_wakeup == 0xFF)
                        break;
-               }
                /* wait for POLLJIFFIES_NORMAL jiffies, or until
                * someone wakes up poll_dev_wake_q,
                * whichever comes first only do a wait when we have
@@ -1335,7 +1210,6 @@ static int process_incoming(void *v)
                        idle_cycles = idle_cycles + delta_cycles;
                }
        }
-       DBGINF("exiting.\n");
        complete_and_exit(&incoming_ti.has_stopped, 0);
 }
 
@@ -1346,7 +1220,6 @@ initialize_incoming_thread(void)
                return TRUE;
        if (!uisthread_start(&incoming_ti,
                             &process_incoming, NULL, "dev_incoming")) {
-               LOGERR("uisthread_start initialize_incoming_thread ****FAILED");
                return FALSE;
        }
        incoming_started = TRUE;
@@ -1367,11 +1240,9 @@ uislib_enable_channel_interrupts(u32 bus_no, u32 dev_no,
        struct device_info *dev;
 
        dev = find_dev(bus_no, dev_no);
-       if (!dev) {
-               LOGERR("%s busNo=%d, devNo=%d", __func__, (int)(bus_no),
-                      (int)(dev_no));
+       if (!dev)
                return;
-       }
+
        down(&poll_dev_lock);
        initialize_incoming_thread();
        dev->interrupt = interrupt;
@@ -1392,11 +1263,8 @@ uislib_disable_channel_interrupts(u32 bus_no, u32 dev_no)
        struct device_info *dev;
 
        dev = find_dev(bus_no, dev_no);
-       if (!dev) {
-               LOGERR("%s busNo=%d, devNo=%d", __func__, (int)(bus_no),
-                      (int)(dev_no));
+       if (!dev)
                return;
-       }
        down(&poll_dev_lock);
        list_del(&dev->list_polling_device_channels);
        dev->polling = FALSE;
@@ -1446,27 +1314,6 @@ uislib_mod_init(void)
        if (!unisys_spar_platform)
                return -ENODEV;
 
-       LOGINF("MONITORAPIS");
-
-       LOGINF("sizeof(struct uiscmdrsp):%lu bytes\n",
-              (ulong)sizeof(struct uiscmdrsp));
-       LOGINF("sizeof(struct phys_info):%lu\n",
-              (ulong)sizeof(struct phys_info));
-       LOGINF("sizeof(uiscmdrsp_scsi):%lu\n",
-              (ulong)sizeof(struct uiscmdrsp_scsi));
-       LOGINF("sizeof(uiscmdrsp_net):%lu\n",
-              (ulong)sizeof(struct uiscmdrsp_net));
-       LOGINF("sizeof(CONTROLVM_MESSAGE):%lu bytes\n",
-              (ulong)sizeof(struct controlvm_message));
-       LOGINF("sizeof(struct spar_controlvm_channel_protocol):%lu bytes\n",
-              (ulong)sizeof(struct spar_controlvm_channel_protocol));
-       LOGINF("sizeof(CHANNEL_HEADER):%lu bytes\n",
-              (ulong)sizeof(struct channel_header));
-       LOGINF("sizeof(struct spar_io_channel_protocol):%lu bytes\n",
-              (ulong)sizeof(struct spar_io_channel_protocol));
-       LOGINF("SIZEOF_CMDRSP:%lu bytes\n", SIZEOF_CMDRSP);
-       LOGINF("SIZEOF_PROTOCOL:%lu bytes\n", SIZEOF_PROTOCOL);
-
        /* initialize global pointers to NULL */
        bus_list = NULL;
        bus_list_count = 0;
@@ -1514,8 +1361,6 @@ uislib_mod_exit(void)
        debugfs_remove(cycles_before_wait_debugfs_read);
        debugfs_remove(platformnumber_debugfs_read);
        debugfs_remove(dir_debugfs);
-
-       DBGINF("goodbye.\n");
 }
 
 module_init(uislib_mod_init);
index 71bb7b608e9a4615b02aee7dccacac1f1c2d2bad..d46dd7428a30ab7462039108607ef63f0b56895a 100644 (file)
@@ -295,12 +295,10 @@ uisqueue_put_cmdrsp_with_lock_client(struct uisqueue_info *queueinfo,
        while (!do_locked_client_insert(queueinfo, whichqueue, cmdrsp,
                                        (spinlock_t *)insertlock,
                                        channel_id)) {
-               if (oktowait != OK_TO_WAIT) {
-                       LOGERR("****FAILED visor_signal_insert failed; cannot wait; insert aborted\n");
+               if (oktowait != OK_TO_WAIT)
                        return 0;       /* failed to queue */
-               }
+
                /* try again */
-               LOGERR("****FAILED visor_signal_insert failed; waiting to try again\n");
                set_current_state(TASK_INTERRUPTIBLE);
                schedule_timeout(msecs_to_jiffies(10));
        }
index 25adf1a7307c9d1112908f790e60c5ec1331a37b..d3c973b617ee7fe1de8da632779e6ad7d97294bf 100644 (file)
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/kthread.h>
-#include "uniklog.h"
 #include "uisutils.h"
 #include "uisthread.h"
 
-#define KILL(a, b, c) kill_pid(find_vpid(a), b, c)
-
 /* this is shorter than using __FILE__ (full path name) in
  * debug/info/error messages
  */
@@ -41,17 +38,14 @@ int
 uisthread_start(struct uisthread_info *thrinfo,
                int (*threadfn)(void *), void *thrcontext, char *name)
 {
-       thrinfo->should_stop = 0;
        /* used to stop the thread */
        init_completion(&thrinfo->has_stopped);
-       thrinfo->task = kthread_create(threadfn, thrcontext, name, NULL);
+       thrinfo->task = kthread_run(threadfn, thrcontext, name);
        if (IS_ERR(thrinfo->task)) {
                thrinfo->id = 0;
                return 0;       /* failure */
        }
        thrinfo->id = thrinfo->task->pid;
-       wake_up_process(thrinfo->task);
-       LOGINF("started thread pid:%d\n", thrinfo->id);
        return 1;
 }
 EXPORT_SYMBOL_GPL(uisthread_start);
@@ -59,27 +53,17 @@ EXPORT_SYMBOL_GPL(uisthread_start);
 void
 uisthread_stop(struct uisthread_info *thrinfo)
 {
-       int ret;
        int stopped = 0;
 
        if (thrinfo->id == 0)
                return;         /* thread not running */
 
-       LOGINF("uisthread_stop stopping id:%d\n", thrinfo->id);
-       thrinfo->should_stop = 1;
-       ret = KILL(thrinfo->id, SIGHUP, 1);
-       if (ret) {
-               LOGERR("unable to signal thread %d\n", ret);
-       } else {
-               /* give up if the thread has NOT died in 1 minute */
-               if (wait_for_completion_timeout(&thrinfo->has_stopped, 60 * HZ))
-                       stopped = 1;
-               else
-                       LOGERR("timed out trying to signal thread\n");
-       }
-       if (stopped) {
-               LOGINF("uisthread_stop stopped id:%d\n", thrinfo->id);
+       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))
+               stopped = 1;
+
+       if (stopped)
                thrinfo->id = 0;
-       }
 }
 EXPORT_SYMBOL_GPL(uisthread_stop);
index 31318d246252981189ebeea753889313bcc16419..26ab76526813712cf27863e03c09ac46289c1181 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/uuid.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
-#include "uniklog.h"
 #include "uisutils.h"
 #include "version.h"
 #include "vbushelper.h"
@@ -53,7 +52,6 @@ uisutil_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining,
        va_list args;
        int len;
 
-       DBGINF("buffer = 0x%p : *buffer = 0x%p.\n", buffer, *buffer);
        va_start(args, format);
        len = vsnprintf(*buffer, *buffer_remaining, format, args);
        va_end(args);
@@ -61,7 +59,6 @@ uisutil_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining,
                *buffer += *buffer_remaining;
                *total += *buffer_remaining;
                *buffer_remaining = 0;
-               LOGERR("bytes remaining is too small!\n");
                return -1;
        }
        *buffer_remaining -= len;
@@ -75,8 +72,6 @@ int
 uisctrl_register_req_handler(int type, void *fptr,
                             struct ultra_vbus_deviceinfo *chipset_driver_info)
 {
-       LOGINF("type = %d, fptr = 0x%p.\n", type, fptr);
-
        switch (type) {
        case 2:
                if (fptr) {
@@ -91,7 +86,6 @@ uisctrl_register_req_handler(int type, void *fptr,
                break;
 
        default:
-               LOGERR("invalid type %d.\n", type);
                return 0;
        }
        if (chipset_driver_info)
@@ -102,71 +96,6 @@ uisctrl_register_req_handler(int type, void *fptr,
 }
 EXPORT_SYMBOL_GPL(uisctrl_register_req_handler);
 
-int
-uisctrl_register_req_handler_ex(uuid_le switch_uuid,
-                       const char *switch_type_name,
-                       int (*controlfunc)(struct io_msgs *),
-                       unsigned long min_channel_bytes,
-                       int (*server_channel_ok)(unsigned long channel_bytes),
-                       int (*server_channel_init)(void *x,
-                                               unsigned char *client_str,
-                                               u32 client_str_len, u64 bytes),
-                       struct ultra_vbus_deviceinfo *chipset_driver_info)
-{
-       struct req_handler_info *req_handler;
-
-       LOGINF("type=%pUL, controlfunc=0x%p.\n",
-              &switch_uuid, controlfunc);
-       if (!controlfunc) {
-               LOGERR("%pUL: controlfunc must be supplied\n", &switch_uuid);
-               return 0;
-       }
-       if (!server_channel_ok) {
-               LOGERR("%pUL: Server_Channel_Ok must be supplied\n",
-                               &switch_uuid);
-               return 0;
-       }
-       if (!server_channel_init) {
-               LOGERR("%pUL: Server_Channel_Init must be supplied\n",
-                               &switch_uuid);
-               return 0;
-       }
-       req_handler = req_handler_add(switch_uuid,
-                                     switch_type_name,
-                                     controlfunc,
-                                     min_channel_bytes,
-                                     server_channel_ok, server_channel_init);
-       if (!req_handler) {
-               LOGERR("failed to add %pUL to server list\n", &switch_uuid);
-               return 0;
-       }
-
-       atomic_inc(&uisutils_registered_services);
-       if (chipset_driver_info) {
-               bus_device_info_init(chipset_driver_info, "chipset",
-                                    "uislib", VERSION, NULL);
-               return 1;
-       }
-
-       LOGERR("failed to register type %pUL.\n", &switch_uuid);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(uisctrl_register_req_handler_ex);
-
-int
-uisctrl_unregister_req_handler_ex(uuid_le switch_uuid)
-{
-       LOGINF("type=%pUL.\n", &switch_uuid);
-       if (req_handler_del(switch_uuid) < 0) {
-               LOGERR("failed to remove %pUL from server list\n",
-                      &switch_uuid);
-               return 0;
-       }
-       atomic_dec(&uisutils_registered_services);
-       return 1;
-}
-EXPORT_SYMBOL_GPL(uisctrl_unregister_req_handler_ex);
-
 /*
  * unsigned int uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx,
  *                                          void *skb_in,
@@ -185,116 +114,10 @@ EXPORT_SYMBOL_GPL(uisctrl_unregister_req_handler_ex);
  *                                         return value indicates number of
  *                                         entries filled in frags
  */
-unsigned int
-uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx, void *skb_in,
-                               unsigned int firstfraglen,
-                               unsigned int frags_max,
-                               struct phys_info frags[])
-{
-       unsigned int count = 0, ii, size, offset = 0, numfrags;
-       struct sk_buff *skb = skb_in;
-
-       numfrags = skb_shinfo(skb)->nr_frags;
-
-       while (firstfraglen) {
-               if (count == frags_max) {
-                       LOGERR("%s frags array too small: max:%d count:%d\n",
-                              calling_ctx, frags_max, count);
-                       return -1;      /* failure */
-               }
-               frags[count].pi_pfn =
-                   page_to_pfn(virt_to_page(skb->data + offset));
-               frags[count].pi_off =
-                   (unsigned long)(skb->data + offset) & PI_PAGE_MASK;
-               size =
-                   min(firstfraglen,
-                       (unsigned int)(PI_PAGE_SIZE - frags[count].pi_off));
-               /* can take smallest of firstfraglen(what's left) OR
-               * bytes left in the page
-               */
-               frags[count].pi_len = size;
-               firstfraglen -= size;
-               offset += size;
-               count++;
-       }
-       if (!numfrags)
-               goto dolist;
-
-       if ((count + numfrags) > frags_max) {
-               LOGERR("**** FAILED %s frags array too small: max:%d count+nr_frags:%d\n",
-                      calling_ctx, frags_max, count + numfrags);
-               return -1;      /* failure */
-       }
-
-       for (ii = 0; ii < numfrags; ii++) {
-               count = add_physinfo_entries(page_to_pfn(
-                               skb_frag_page(&skb_shinfo(skb)->frags[ii])),
-                                       skb_shinfo(skb)->frags[ii].
-                                       page_offset,
-                                       skb_shinfo(skb)->frags[ii].
-                                       size, count, frags_max,
-                                       frags);
-               if (count == 0) {
-                       LOGERR("**** FAILED to add physinfo entries\n");
-                       return -1;      /* failure */
-               }
-       }
-
-dolist: if (skb_shinfo(skb)->frag_list) {
-               struct sk_buff *skbinlist;
-               int c;
-
-               for (skbinlist = skb_shinfo(skb)->frag_list; skbinlist;
-                    skbinlist = skbinlist->next) {
-                       c = uisutil_copy_fragsinfo_from_skb("recursive",
-                               skbinlist,
-                               skbinlist->len - skbinlist->data_len,
-                               frags_max - count,
-                               &frags[count]);
-                       if (c == -1) {
-                               LOGERR("**** FAILED recursive call failed\n");
-                               return -1;
-                       }
-                       count += c;
-               }
-       }
-       return count;
-}
-EXPORT_SYMBOL_GPL(uisutil_copy_fragsinfo_from_skb);
 
 static LIST_HEAD(req_handler_info_list); /* list of struct req_handler_info */
 static DEFINE_SPINLOCK(req_handler_info_list_lock);
 
-struct req_handler_info *
-req_handler_add(uuid_le switch_uuid,
-             const char *switch_type_name,
-             int (*controlfunc)(struct io_msgs *),
-             unsigned long min_channel_bytes,
-             int (*server_channel_ok)(unsigned long channel_bytes),
-             int (*server_channel_init)
-              (void *x, unsigned char *clientstr, u32 clientstr_len,
-               u64 bytes))
-{
-       struct req_handler_info *rc = NULL;
-
-       rc = kzalloc(sizeof(*rc), GFP_ATOMIC);
-       if (!rc)
-               return NULL;
-       rc->switch_uuid = switch_uuid;
-       rc->controlfunc = controlfunc;
-       rc->min_channel_bytes = min_channel_bytes;
-       rc->server_channel_ok = server_channel_ok;
-       rc->server_channel_init = server_channel_init;
-       if (switch_type_name)
-               strncpy(rc->switch_type_name, switch_type_name,
-                       sizeof(rc->switch_type_name) - 1);
-       spin_lock(&req_handler_info_list_lock);
-       list_add_tail(&rc->list_link, &req_handler_info_list);
-       spin_unlock(&req_handler_info_list_lock);
-
-       return rc;
-}
-
 struct req_handler_info *
 req_handler_find(uuid_le switch_uuid)
 {
@@ -312,23 +135,3 @@ req_handler_find(uuid_le switch_uuid)
        spin_unlock(&req_handler_info_list_lock);
        return NULL;
 }
-
-int
-req_handler_del(uuid_le switch_uuid)
-{
-       struct list_head *lelt, *tmp;
-       struct req_handler_info *entry = NULL;
-       int rc = -1;
-
-       spin_lock(&req_handler_info_list_lock);
-       list_for_each_safe(lelt, tmp, &req_handler_info_list) {
-               entry = list_entry(lelt, struct req_handler_info, list_link);
-               if (uuid_le_cmp(entry->switch_uuid, switch_uuid) == 0) {
-                       list_del(lelt);
-                       kfree(entry);
-                       rc++;
-               }
-       }
-       spin_unlock(&req_handler_info_list_lock);
-       return rc;
-}
index 9af98fc7acbc389b7b296bf62d044006b69c7ced..dfadfc49114aba7fb13b684d500efda75ace498c 100644 (file)
@@ -4,7 +4,10 @@
 
 config UNISYS_VIRTHBA
        tristate "Unisys virthba driver"
-       depends on UNISYSSPAR && UNISYS_VISORCHIPSET && UNISYS_UISLIB && UNISYS_VIRTPCI && SCSI
+       depends on SCSI
+       select UNISYS_VISORCHIPSET
+       select UNISYS_UISLIB
+       select UNISYS_VIRTPCI
        ---help---
        If you say Y here, you will enable the Unisys virthba driver.
 
index ba55ae12488e021d6a5ff5734c9f9a1afa8a88e0..a4e4037391832760423e53dc1159b257245893fa 100644 (file)
@@ -6,7 +6,6 @@ obj-$(CONFIG_UNISYS_VIRTHBA)    += virthba.o
 
 ccflags-y += -Idrivers/staging/unisys/include
 ccflags-y += -Idrivers/staging/unisys/uislib
-ccflags-y += -Idrivers/staging/unisys/timskmod
 ccflags-y += -Idrivers/staging/unisys/visorchipset
 ccflags-y += -Idrivers/staging/unisys/virtpci
 ccflags-y += -Idrivers/staging/unisys/common-spar/include
index e6ecea560495fabab567ca94983b99be1a423d56..d9001cca0f73575fd47ae94073af268dde4770f3 100644 (file)
  * which start with an 8 digit sequence number, a colon, and then
  * letters after that */
 
-#undef DBGINF
-
 #include <linux/kernel.h>
 #ifdef CONFIG_MODVERSIONS
 #include <config/modversions.h>
 #endif
 
-#include "uniklog.h"
 #include "diagnostics/appos_subsystems.h"
 #include "uisutils.h"
 #include "uisqueue.h"
@@ -261,11 +258,9 @@ add_scsipending_entry(struct virthba_info *vhbainfo, char cmdtype, void *new)
 
        spin_lock_irqsave(&vhbainfo->privlock, flags);
        insert_location = vhbainfo->nextinsert;
-       while (vhbainfo->pending[insert_location].sent != NULL) {
+       while (vhbainfo->pending[insert_location].sent) {
                insert_location = (insert_location + 1) % MAX_PENDING_REQUESTS;
                if (insert_location == (int)vhbainfo->nextinsert) {
-                       LOGERR("Queue should be full. insert_location<<%d>>  Unable to find open slot for pending commands.\n",
-                            insert_location);
                        spin_unlock_irqrestore(&vhbainfo->privlock, flags);
                        return -1;
                }
@@ -286,7 +281,6 @@ add_scsipending_entry_with_wait(struct virthba_info *vhbainfo, char cmdtype,
        int insert_location = add_scsipending_entry(vhbainfo, cmdtype, new);
 
        while (insert_location == -1) {
-               LOGERR("Failed to find empty queue slot.  Waiting to try again\n");
                set_current_state(TASK_INTERRUPTIBLE);
                schedule_timeout(msecs_to_jiffies(10));
                insert_location = add_scsipending_entry(vhbainfo, cmdtype, new);
@@ -301,16 +295,8 @@ del_scsipending_entry(struct virthba_info *vhbainfo, uintptr_t del)
        unsigned long flags;
        void *sent = NULL;
 
-       if (del >= MAX_PENDING_REQUESTS) {
-               LOGERR("Invalid queue position <<%lu>> given to delete. MAX_PENDING_REQUESTS <<%d>>\n",
-                    (unsigned long)del, MAX_PENDING_REQUESTS);
-       } else {
+       if (del < MAX_PENDING_REQUESTS) {
                spin_lock_irqsave(&vhbainfo->privlock, flags);
-
-               if (vhbainfo->pending[del].sent == NULL)
-                       LOGERR("Deleting already cleared queue entry at <<%lu>>.\n",
-                            (unsigned long)del);
-
                sent = vhbainfo->pending[del].sent;
 
                vhbainfo->pending[del].cmdtype = 0;
@@ -357,13 +343,7 @@ send_disk_add_remove(struct diskaddremove *dar)
                error =
                    scsi_add_device(dar->shost, dar->channel, dar->id,
                                    dar->lun);
-               if (error)
-                       LOGERR("Failed scsi_add_device: host_no=%d[chan=%d:id=%d:lun=%d]\n",
-                            dar->shost->host_no, dar->channel, dar->id,
-                            dar->lun);
-       } else
-               LOGERR("Failed scsi_device_lookup:[chan=%d:id=%d:lun=%d]\n",
-                      dar->channel, dar->id, dar->lun);
+       }
        kfree(dar);
 }
 
@@ -408,10 +388,6 @@ process_disk_notify(struct Scsi_Host *shost, struct uiscmdrsp *cmdrsp)
                dar->id = cmdrsp->disknotify.id;
                dar->lun = cmdrsp->disknotify.lun;
                QUEUE_DISKADDREMOVE(dar);
-       } else {
-               LOGERR("kmalloc failed for dar. host_no=%d[chan=%d:id=%d:lun=%d]\n",
-                    shost->host_no, cmdrsp->disknotify.channel,
-                    cmdrsp->disknotify.id, cmdrsp->disknotify.lun);
        }
 }
 
@@ -427,7 +403,7 @@ virthba_isr(int irq, void *dev_id)
        u64 mask;
        unsigned long long rc1;
 
-       if (virthbainfo == NULL)
+       if (!virthbainfo)
                return IRQ_NONE;
        virthbainfo->interrupts_rcvd++;
        channel_header = virthbainfo->chinfo.queueinfo->chan;
@@ -467,13 +443,6 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id)
        struct signal_queue_header __iomem *pqhdr;
        u64 mask;
 
-       LOGVER("entering virthba_probe...\n");
-       LOGVER("virtpcidev bus_no<<%d>>devNo<<%d>>", virtpcidev->bus_no,
-              virtpcidev->device_no);
-
-       LOGINF("entering virthba_probe...\n");
-       LOGINF("virtpcidev bus_no<<%d>>devNo<<%d>>", virtpcidev->bus_no,
-              virtpcidev->device_no);
        POSTCODE_LINUX_2(VHBA_PROBE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
        /* call scsi_host_alloc to register a scsi host adapter
         * instance - this virthba that has just been created is an
@@ -482,7 +451,6 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id)
         * initialization.  The host is not published to the scsi
         * midlayer until scsi_add_host is called.
         */
-       DBGINF("calling scsi_host_alloc.\n");
 
        /* arg 2 passed in length of extra space we want allocated
         * with scsi_host struct for our own use scsi_host_alloc
@@ -490,12 +458,9 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id)
         */
        scsihost = scsi_host_alloc(&virthba_driver_template,
                                   sizeof(struct virthba_info));
-       if (scsihost == NULL)
+       if (!scsihost)
                return -ENODEV;
 
-       DBGINF("scsihost: 0x%p, scsihost->this_id: %d, host_no: %d.\n",
-              scsihost, scsihost->this_id, scsihost->host_no);
-
        scsihost->this_id = UIS_MAGIC_VHBA;
        /* linux treats max-channel differently than max-id & max-lun.
         * In the latter cases, those two values result in 0 to max-1
@@ -503,12 +468,6 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id)
         * scan is 0 to max (inclusive); so we will subtract one from
         * the max-channel value.
         */
-       LOGINF("virtpcidev->scsi.max.max_channel=%u, max_id=%u, max_lun=%u, cmd_per_lun=%u, max_io_size=%u\n",
-            (unsigned)virtpcidev->scsi.max.max_channel - 1,
-            (unsigned)virtpcidev->scsi.max.max_id,
-            (unsigned)virtpcidev->scsi.max.max_lun,
-            (unsigned)virtpcidev->scsi.max.cmd_per_lun,
-            (unsigned)virtpcidev->scsi.max.max_io_size);
        scsihost->max_channel = (unsigned)virtpcidev->scsi.max.max_channel;
        scsihost->max_id = (unsigned)virtpcidev->scsi.max.max_id;
        scsihost->max_lun = (unsigned)virtpcidev->scsi.max.max_lun;
@@ -519,15 +478,6 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id)
            (unsigned short)(virtpcidev->scsi.max.max_io_size / PAGE_SIZE);
        if (scsihost->sg_tablesize > MAX_PHYS_INFO)
                scsihost->sg_tablesize = MAX_PHYS_INFO;
-       LOGINF("scsihost->max_channel=%u, max_id=%u, max_lun=%llu, cmd_per_lun=%u, max_sectors=%hu, sg_tablesize=%hu\n",
-            scsihost->max_channel, scsihost->max_id, scsihost->max_lun,
-            scsihost->cmd_per_lun, scsihost->max_sectors,
-            scsihost->sg_tablesize);
-       LOGINF("scsihost->can_queue=%u, scsihost->cmd_per_lun=%u, max_sectors=%hu, sg_tablesize=%hu\n",
-            scsihost->can_queue, scsihost->cmd_per_lun, scsihost->max_sectors,
-            scsihost->sg_tablesize);
-
-       DBGINF("calling scsi_add_host\n");
 
        /* this creates "host%d" in sysfs.  If 2nd argument is NULL,
         * then this generic /sys/devices/platform/host?  device is
@@ -538,7 +488,6 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id)
         */
        error = scsi_add_host(scsihost, &virtpcidev->generic_dev);
        if (error) {
-               LOGERR("scsi_add_host ****FAILED 0x%x  TBD - RECOVER\n", error);
                POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
                /* decr refcount on scsihost which was incremented by
                 * scsi_add_host so the scsi_host gets deleted
@@ -550,7 +499,7 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id)
        virthbainfo = (struct virthba_info *)scsihost->hostdata;
        memset(virthbainfo, 0, sizeof(struct virthba_info));
        for (i = 0; i < VIRTHBASOPENMAX; i++) {
-               if (virthbas_open[i].virthbainfo == NULL) {
+               if (!virthbas_open[i].virthbainfo) {
                        virthbas_open[i].virthbainfo = virthbainfo;
                        break;
                }
@@ -560,9 +509,6 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id)
        virthbainfo->virtpcidev = virtpcidev;
        spin_lock_init(&virthbainfo->chinfo.insertlock);
 
-       DBGINF("generic_dev: 0x%p, queueinfo: 0x%p.\n",
-              &virtpcidev->generic_dev, &virtpcidev->queueinfo);
-
        init_waitqueue_head(&virthbainfo->rsp_queue);
        spin_lock_init(&virthbainfo->privlock);
        memset(&virthbainfo->pending, 0, sizeof(virthbainfo->pending));
@@ -584,8 +530,6 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id)
               ULTRA_IO_CHANNEL_IS_POLLING,
               &virthbainfo->chinfo.queueinfo->chan->features);
        /* start thread that will receive scsicmnd responses */
-       DBGINF("starting rsp thread -- queueinfo: 0x%p, threadinfo: 0x%p.\n",
-              virthbainfo->chinfo.queueinfo, &virthbainfo->chinfo.threadinfo);
 
        channel_header = virthbainfo->chinfo.queueinfo->chan;
        pqhdr = (struct signal_queue_header __iomem *)
@@ -596,7 +540,6 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id)
        if (!uisthread_start(&virthbainfo->chinfo.threadinfo,
                             process_incoming_rsps,
                             virthbainfo, "vhba_incoming")) {
-               LOGERR("uisthread_start rsp ****FAILED\n");
                /* decr refcount on scsihost which was incremented by
                 * scsi_add_host so the scsi_host gets deleted
                 */
@@ -604,42 +547,26 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id)
                scsi_host_put(scsihost);
                return -ENODEV;
        }
-       LOGINF("sendInterruptHandle=0x%16llX",
-              virthbainfo->intr.send_irq_handle);
-       LOGINF("recvInterruptHandle=0x%16llX",
-              virthbainfo->intr.recv_irq_handle);
-       LOGINF("recvInterruptVector=0x%8X",
-              virthbainfo->intr.recv_irq_vector);
-       LOGINF("recvInterruptShared=0x%2X",
-              virthbainfo->intr.recv_irq_shared);
-       LOGINF("scsihost.hostt->name=%s", scsihost->hostt->name);
        virthbainfo->interrupt_vector =
            virthbainfo->intr.recv_irq_handle & INTERRUPT_VECTOR_MASK;
        rsp = request_irq(virthbainfo->interrupt_vector, handler, IRQF_SHARED,
                          scsihost->hostt->name, virthbainfo);
        if (rsp != 0) {
-               LOGERR("request_irq(%d) uislib_virthba_ISR request failed with rsp=%d\n",
-                      virthbainfo->interrupt_vector, rsp);
                virthbainfo->interrupt_vector = -1;
                POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
        } else {
-               u64 __iomem *Features_addr =
+               u64 __iomem *features_addr =
                    &virthbainfo->chinfo.queueinfo->chan->features;
-               LOGERR("request_irq(%d) uislib_virthba_ISR request succeeded\n",
-                      virthbainfo->interrupt_vector);
                mask = ~(ULTRA_IO_CHANNEL_IS_POLLING |
                         ULTRA_IO_DRIVER_DISABLES_INTS);
-               uisqueue_interlocked_and(Features_addr, mask);
+               uisqueue_interlocked_and(features_addr, mask);
                mask = ULTRA_IO_DRIVER_ENABLES_INTS;
-               uisqueue_interlocked_or(Features_addr, mask);
+               uisqueue_interlocked_or(features_addr, mask);
                rsltq_wait_usecs = 4000000;
        }
 
-       DBGINF("calling scsi_scan_host.\n");
        scsi_scan_host(scsihost);
-       DBGINF("return from scsi_scan_host.\n");
 
-       LOGINF("virthba added scsihost:0x%p\n", scsihost);
        POSTCODE_LINUX_2(VHBA_PROBE_EXIT_PC, POSTCODE_SEVERITY_INFO);
        return 0;
 }
@@ -651,28 +578,18 @@ virthba_remove(struct virtpci_dev *virtpcidev)
        struct Scsi_Host *scsihost =
            (struct Scsi_Host *)virtpcidev->scsi.scsihost;
 
-       LOGINF("virtpcidev bus_no<<%d>>devNo<<%d>>", virtpcidev->bus_no,
-              virtpcidev->device_no);
        virthbainfo = (struct virthba_info *)scsihost->hostdata;
        if (virthbainfo->interrupt_vector != -1)
                free_irq(virthbainfo->interrupt_vector, virthbainfo);
-       LOGINF("Removing virtpcidev: 0x%p, virthbainfo: 0x%p\n", virtpcidev,
-              virthbainfo);
 
-       DBGINF("removing scsihost: 0x%p, scsihost->this_id: %d\n", scsihost,
-              scsihost->this_id);
        scsi_remove_host(scsihost);
 
-       DBGINF("stopping thread.\n");
        uisthread_stop(&virthbainfo->chinfo.threadinfo);
 
-       DBGINF("calling scsi_host_put\n");
-
        /* decr refcount on scsihost which was incremented by
         * scsi_add_host so the scsi_host gets deleted
         */
        scsi_host_put(scsihost);
-       LOGINF("virthba removed scsi_host.\n");
 }
 
 static int
@@ -686,19 +603,12 @@ forward_vdiskmgmt_command(enum vdisk_mgmt_types vdiskcmdtype,
        int notifyresult = 0xffff;
        wait_queue_head_t notifyevent;
 
-       LOGINF("vDiskMgmt:%d %d:%d:%d\n", vdiskcmdtype,
-              vdest->channel, vdest->id, vdest->lun);
-
-       if (virthbainfo->serverdown || virthbainfo->serverchangingstate) {
-               DBGINF("Server is down/changing state. Returning Failure.\n");
+       if (virthbainfo->serverdown || virthbainfo->serverchangingstate)
                return FAILED;
-       }
 
        cmdrsp = kzalloc(SIZEOF_CMDRSP, GFP_ATOMIC);
-       if (cmdrsp == NULL) {
-               LOGERR("kmalloc of cmdrsp failed.\n");
-               return FAILED;  /* reject */
-       }
+       if (!cmdrsp)
+               return FAILED;  /* reject */
 
        init_waitqueue_head(&notifyevent);
 
@@ -727,10 +637,7 @@ forward_vdiskmgmt_command(enum vdisk_mgmt_types vdiskcmdtype,
                                             &virthbainfo->chinfo.insertlock,
                                             DONT_ISSUE_INTERRUPT, (u64)NULL,
                                             OK_TO_WAIT, "vhba");
-       LOGINF("VdiskMgmt waiting on event notifyevent=0x%p\n",
-              cmdrsp->scsitaskmgmt.notify);
        wait_event(notifyevent, notifyresult != 0xffff);
-       LOGINF("VdiskMgmt complete; result:%d\n", cmdrsp->vdiskmgmt.result);
        kfree(cmdrsp);
        return SUCCESS;
 }
@@ -749,19 +656,12 @@ forward_taskmgmt_command(enum task_mgmt_types tasktype,
        int notifyresult = 0xffff;
        wait_queue_head_t notifyevent;
 
-       LOGINF("TaskMgmt:%d %d:%d:%llu\n", tasktype,
-              scsidev->channel, scsidev->id, scsidev->lun);
-
-       if (virthbainfo->serverdown || virthbainfo->serverchangingstate) {
-               DBGINF("Server is down/changing state. Returning Failure.\n");
+       if (virthbainfo->serverdown || virthbainfo->serverchangingstate)
                return FAILED;
-       }
 
        cmdrsp = kzalloc(SIZEOF_CMDRSP, GFP_ATOMIC);
-       if (cmdrsp == NULL) {
-               LOGERR("kmalloc of cmdrsp failed.\n");
+       if (!cmdrsp)
                return FAILED;  /* reject */
-       }
 
        init_waitqueue_head(&notifyevent);
 
@@ -789,10 +689,7 @@ forward_taskmgmt_command(enum task_mgmt_types tasktype,
                                             &virthbainfo->chinfo.insertlock,
                                             DONT_ISSUE_INTERRUPT, (u64)NULL,
                                             OK_TO_WAIT, "vhba");
-       LOGINF("TaskMgmt waiting on event notifyevent=0x%p\n",
-              cmdrsp->scsitaskmgmt.notify);
        wait_event(notifyevent, notifyresult != 0xffff);
-       LOGINF("TaskMgmt complete; result:%d\n", cmdrsp->scsitaskmgmt.result);
        kfree(cmdrsp);
        return SUCCESS;
 }
@@ -882,7 +779,6 @@ static int
 virthba_host_reset_handler(struct scsi_cmnd *scsicmd)
 {
        /* issue TASK_MGMT_TARGET_RESET for each target on each bus for host */
-       LOGERR("virthba_host_reset_handler Not yet implemented\n");
        return SUCCESS;
 }
 
@@ -899,7 +795,6 @@ virthba_get_info(struct Scsi_Host *shp)
 static int
 virthba_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
 {
-       DBGINF("In virthba_ioctl: ioctl: cmd=0x%x\n", cmd);
        return -EINVAL;
 }
 
@@ -923,16 +818,11 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd,
        struct scatterlist *sgl = NULL;
        int sg_failed = 0;
 
-       if (virthbainfo->serverdown || virthbainfo->serverchangingstate) {
-               DBGINF("Server is down/changing state. Returning SCSI_MLQUEUE_DEVICE_BUSY.\n");
+       if (virthbainfo->serverdown || virthbainfo->serverchangingstate)
                return SCSI_MLQUEUE_DEVICE_BUSY;
-       }
-
        cmdrsp = kzalloc(SIZEOF_CMDRSP, GFP_ATOMIC);
-       if (cmdrsp == NULL) {
-               LOGERR("kmalloc of cmdrsp failed.\n");
+       if (!cmdrsp)
                return 1;       /* reject the command */
-       }
 
        /* now saving everything we need from scsi_cmd into cmdrsp
         * before we queue cmdrsp set type to command - as opposed to
@@ -947,7 +837,6 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd,
        if (insert_location != -1) {
                cmdrsp->scsi.scsicmd = (void *)(uintptr_t)insert_location;
        } else {
-               LOGERR("Queue is full. Returning busy.\n");
                kfree(cmdrsp);
                return SCSI_MLQUEUE_DEVICE_BUSY;
        }
@@ -968,8 +857,6 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd,
                max_buff_len = cmdrsp->scsi.bufflen;
 
        if (scsi_sg_count(scsicmd) > MAX_PHYS_INFO) {
-               LOGERR("scsicmd use_sg:%d greater than MAX:%d\n",
-                      scsi_sg_count(scsicmd), MAX_PHYS_INFO);
                del_scsipending_entry(virthbainfo, (uintptr_t)insert_location);
                kfree(cmdrsp);
                return 1;       /* reject the command */
@@ -982,11 +869,8 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd,
        /* convert buffer to phys information */
        if (scsi_sg_count(scsicmd) == 0) {
                if (scsi_bufflen(scsicmd) > 0) {
-                       LOGERR("**** FAILED No scatter list for bufflen > 0\n");
                        BUG_ON(scsi_sg_count(scsicmd) == 0);
                }
-               DBGINF("No sg; buffer:0x%p bufflen:%d\n",
-                      scsi_sglist(scsicmd), scsi_bufflen(scsicmd));
        } else {
                /* buffer is scatterlist - copy it out */
                sgl = scsi_sglist(scsicmd);
@@ -994,21 +878,9 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd,
                for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) {
                        cmdrsp->scsi.gpi_list[i].address = sg_phys(sg);
                        cmdrsp->scsi.gpi_list[i].length = sg->length;
-                       if ((i != 0) && (sg->offset != 0))
-                               LOGINF("Offset on a sg_entry other than zero =<<%d>>.\n",
-                                      sg->offset);
                }
 
                if (sg_failed) {
-                       LOGERR("Start sg_list dump (entries %d, bufflen %d)...\n",
-                              scsi_sg_count(scsicmd), cmdrsp->scsi.bufflen);
-                       for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) {
-                               LOGERR("   Entry(%d): page->[0x%p], phys->[0x%Lx], off(%d), len(%d)\n",
-                                      i, sg_page(sg),
-                                      (unsigned long long)sg_phys(sg),
-                                      sg->offset, sg->length);
-                       }
-                       LOGERR("Done sg_list dump.\n");
                        /* BUG(); ***** For now, let it fail in uissd
                         * if it is a problem, as it might just
                         * work
@@ -1027,7 +899,6 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd,
                                                 (u64)NULL, DONT_WAIT, "vhba");
        if (i == 0) {
                /* queue must be full - and we said don't wait - return busy */
-               LOGERR("uisqueue_put_cmdrsp_with_lock ****FAILED\n");
                kfree(cmdrsp);
                del_scsipending_entry(virthbainfo, (uintptr_t)insert_location);
                return SCSI_MLQUEUE_DEVICE_BUSY;
@@ -1052,10 +923,9 @@ virthba_slave_alloc(struct scsi_device *scsidev)
        struct Scsi_Host *scsihost = (struct Scsi_Host *)scsidev->host;
 
        virthbainfo = (struct virthba_info *)scsihost->hostdata;
-       if (!virthbainfo) {
-               LOGERR("Could not find virthba_info for scsihost\n");
+       if (!virthbainfo)
                return 0;       /* even though we errored, treat as success */
-       }
+
        for (vdisk = &virthbainfo->head; vdisk->next; vdisk = vdisk->next) {
                if (vdisk->next->valid &&
                    (vdisk->next->channel == scsidev->channel) &&
@@ -1064,10 +934,8 @@ virthba_slave_alloc(struct scsi_device *scsidev)
                        return 0;
        }
        tmpvdisk = kzalloc(sizeof(*tmpvdisk), GFP_ATOMIC);
-       if (!tmpvdisk) {        /* error allocating */
-               LOGERR("Could not allocate memory for disk\n");
+       if (!tmpvdisk)
                return 0;
-       }
 
        tmpvdisk->channel = scsidev->channel;
        tmpvdisk->id = scsidev->id;
@@ -1094,8 +962,6 @@ virthba_slave_destroy(struct scsi_device *scsidev)
        struct Scsi_Host *scsihost = (struct Scsi_Host *)scsidev->host;
 
        virthbainfo = (struct virthba_info *)scsihost->hostdata;
-       if (!virthbainfo)
-               LOGERR("Could not find virthba_info for scsihost\n");
        for (vdisk = &virthbainfo->head; vdisk->next; vdisk = vdisk->next) {
                if (vdisk->next->valid &&
                    (vdisk->next->channel == scsidev->channel) &&
@@ -1140,19 +1006,6 @@ do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
 
                if (atomic_read(&vdisk->error_count) < VIRTHBA_ERROR_COUNT) {
                        atomic_inc(&vdisk->error_count);
-                       LOGERR("SCSICMD ****FAILED scsicmd:0x%p op:0x%x <%d:%d:%d:%llu> 0x%x-0x%x-0x%x-0x%x-0x%x.\n",
-                              scsicmd, cmdrsp->scsi.cmnd[0],
-                              scsidev->host->host_no, scsidev->id,
-                              scsidev->channel, scsidev->lun,
-                              cmdrsp->scsi.linuxstat, sd->valid, sd->sense_key,
-                              sd->additional_sense_code,
-                              sd->additional_sense_code_qualifier);
-                       if (atomic_read(&vdisk->error_count) ==
-                           VIRTHBA_ERROR_COUNT) {
-                               LOGERR("Throtling SCSICMD errors disk <%d:%d:%d:%llu>\n",
-                                      scsidev->host->host_no, scsidev->id,
-                                      scsidev->channel, scsidev->lun);
-                       }
                        atomic_set(&vdisk->ios_threshold, IOS_ERROR_THRESHOLD);
                }
        }
@@ -1188,7 +1041,6 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
 
                if (scsi_sg_count(scsicmd) == 0) {
                        if (scsi_bufflen(scsicmd) > 0) {
-                               LOGERR("**** FAILED No scatter list for bufflen > 0\n");
                                BUG_ON(scsi_sg_count(scsicmd) ==
                                       0);
                        }
@@ -1199,8 +1051,6 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
 
                sg = scsi_sglist(scsicmd);
                for (i = 0; i < scsi_sg_count(scsicmd); i++) {
-                       DBGVER("copying OUT OF buf into 0x%p %d\n",
-                              sg_page(sg + i), sg[i].length);
                        thispage_orig = kmap_atomic(sg_page(sg + i));
                        thispage = (void *)((unsigned long)thispage_orig |
                                             sg[i].offset);
@@ -1219,7 +1069,6 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
                        if (atomic_read(&vdisk->ios_threshold) > 0) {
                                atomic_dec(&vdisk->ios_threshold);
                                if (atomic_read(&vdisk->ios_threshold) == 0) {
-                                       LOGERR("Resetting error count for disk\n");
                                        atomic_set(&vdisk->error_count, 0);
                                }
                        }
@@ -1230,8 +1079,6 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
 static void
 complete_scsi_command(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
 {
-       DBGINF("cmdrsp: 0x%p, scsistat:0x%x.\n", cmdrsp, cmdrsp->scsi.scsistat);
-
        /* take what we need out of cmdrsp and complete the scsicmd */
        scsicmd->result = cmdrsp->scsi.linuxstat;
        if (cmdrsp->scsi.linuxstat)
@@ -1239,10 +1086,8 @@ complete_scsi_command(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
        else
                do_scsi_nolinuxstat(cmdrsp, scsicmd);
 
-       if (scsicmd->scsi_done) {
-               DBGVER("Scsi_DONE\n");
+       if (scsicmd->scsi_done)
                scsicmd->scsi_done(scsicmd);
-       }
 }
 
 static inline void
@@ -1252,7 +1097,6 @@ complete_vdiskmgmt_command(struct uiscmdrsp *cmdrsp)
        /* wake up the error handler that is waiting for this */
        *(int *)cmdrsp->vdiskmgmt.notifyresult = cmdrsp->vdiskmgmt.result;
        wake_up_all((wait_queue_head_t *)cmdrsp->vdiskmgmt.notify);
-       LOGINF("set notify result to %d\n", cmdrsp->vdiskmgmt.result);
 }
 
 static inline void
@@ -1263,7 +1107,6 @@ complete_taskmgmt_command(struct uiscmdrsp *cmdrsp)
        *(int *)cmdrsp->scsitaskmgmt.notifyresult =
            cmdrsp->scsitaskmgmt.result;
        wake_up_all((wait_queue_head_t *)cmdrsp->scsitaskmgmt.notify);
-       LOGINF("set notify result to %d\n", cmdrsp->scsitaskmgmt.result);
 }
 
 static void
@@ -1319,8 +1162,7 @@ drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc,
                                                    cmdrsp->vdiskmgmt.scsicmd))
                                break;
                        complete_vdiskmgmt_command(cmdrsp);
-               } else
-                       LOGERR("Invalid cmdtype %d\n", cmdrsp->cmdtype);
+               }
                /* cmdrsp is now available for reuse */
        }
 }
@@ -1341,13 +1183,14 @@ process_incoming_rsps(void *v)
        UIS_DAEMONIZE("vhba_incoming");
        /* alloc once and reuse */
        cmdrsp = kmalloc(SZ, GFP_ATOMIC);
-       if (cmdrsp == NULL) {
-               LOGERR("process_incoming_rsps ****FAILED to malloc - thread exiting\n");
+       if (!cmdrsp) {
                complete_and_exit(&dc->threadinfo.has_stopped, 0);
                return 0;
        }
        mask = ULTRA_CHANNEL_ENABLE_INTS;
        while (1) {
+               if (kthread_should_stop())
+                       break;
                wait_event_interruptible_timeout(virthbainfo->rsp_queue,
                         (atomic_read(&virthbainfo->interrupt_rcvd) == 1),
                                      usecs_to_jiffies(rsltq_wait_usecs));
@@ -1355,13 +1198,10 @@ process_incoming_rsps(void *v)
                /* drain queue */
                drain_queue(virthbainfo, dc, cmdrsp);
                rc1 = uisqueue_interlocked_or(virthbainfo->flags_addr, mask);
-               if (dc->threadinfo.should_stop)
-                       break;
        }
 
        kfree(cmdrsp);
 
-       DBGINF("exiting processing incoming rsps.\n");
        complete_and_exit(&dc->threadinfo.has_stopped, 0);
 }
 
@@ -1386,7 +1226,7 @@ static ssize_t info_debugfs_read(struct file *file,
                return -ENOMEM;
 
        for (i = 0; i < VIRTHBASOPENMAX; i++) {
-               if (virthbas_open[i].virthbainfo == NULL)
+               if (!virthbas_open[i].virthbainfo)
                        continue;
 
                virthbainfo = virthbas_open[i].virthbainfo;
@@ -1436,23 +1276,17 @@ static ssize_t enable_ints_write(struct file *file, const char __user *buffer,
                return -EINVAL;
 
        buf[count] = '\0';
-       if (copy_from_user(buf, buffer, count)) {
-               LOGERR("copy_from_user failed. buf<<%.*s>> count<<%lu>>\n",
-                      (int)count, buf, count);
+       if (copy_from_user(buf, buffer, count))
                return -EFAULT;
-       }
 
        i = kstrtoint(buf, 10, &new_value);
 
-       if (i != 0) {
-               LOGERR("Failed to scan value for enable_ints, buf<<%.*s>>",
-                      (int)count, buf);
+       if (i != 0)
                return -EFAULT;
-       }
 
        /* set all counts to new_value usually 0 */
        for (i = 0; i < VIRTHBASOPENMAX; i++) {
-               if (virthbas_open[i].virthbainfo != NULL) {
+               if (virthbas_open[i].virthbainfo) {
                        virthbainfo = virthbas_open[i].virthbainfo;
                        features_addr =
                                &virthbainfo->chinfo.queueinfo->chan->features;
@@ -1484,17 +1318,11 @@ virthba_serverup(struct virtpci_dev *virtpcidev)
            (struct virthba_info *)((struct Scsi_Host *)virtpcidev->scsi.
                                     scsihost)->hostdata;
 
-       DBGINF("virtpcidev bus_no<<%d>>devNo<<%d>>", virtpcidev->bus_no,
-              virtpcidev->device_no);
-
-       if (!virthbainfo->serverdown) {
-               DBGINF("Server up message received while server is already up.\n");
+       if (!virthbainfo->serverdown)
                return 1;
-       }
-       if (virthbainfo->serverchangingstate) {
-               LOGERR("Server already processing change state message\n");
+
+       if (virthbainfo->serverchangingstate)
                return 0;
-       }
 
        virthbainfo->serverchangingstate = true;
        /* Must transition channel to ATTACHED state BEFORE we
@@ -1508,7 +1336,6 @@ virthba_serverup(struct virtpci_dev *virtpcidev)
        if (!uisthread_start(&virthbainfo->chinfo.threadinfo,
                             process_incoming_rsps,
                             virthbainfo, "vhba_incoming")) {
-               LOGERR("uisthread_start rsp ****FAILED\n");
                return 0;
        }
        virthbainfo->serverdown = false;
@@ -1543,18 +1370,16 @@ virthba_serverdown_complete(struct work_struct *work)
                switch (pendingdel->cmdtype) {
                case CMD_SCSI_TYPE:
                        scsicmd = (struct scsi_cmnd *)pendingdel->sent;
-                       scsicmd->result = (DID_RESET << 16);
+                       scsicmd->result = DID_RESET << 16;
                        if (scsicmd->scsi_done)
                                scsicmd->scsi_done(scsicmd);
                        break;
                case CMD_SCSITASKMGMT_TYPE:
                        cmdrsp = (struct uiscmdrsp *)pendingdel->sent;
-                       DBGINF("cmdrsp=0x%x, notify=0x%x\n", cmdrsp,
-                              cmdrsp->scsitaskmgmt.notify);
-                       *(int *)cmdrsp->scsitaskmgmt.notifyresult =
-                           TASK_MGMT_FAILED;
                        wake_up_all((wait_queue_head_t *)
                                    cmdrsp->scsitaskmgmt.notify);
+                       *(int *)cmdrsp->scsitaskmgmt.notifyresult =
+                               TASK_MGMT_FAILED;
                        break;
                case CMD_VDISKMGMT_TYPE:
                        cmdrsp = (struct uiscmdrsp *)pendingdel->sent;
@@ -1564,9 +1389,7 @@ virthba_serverdown_complete(struct work_struct *work)
                                    cmdrsp->vdiskmgmt.notify);
                        break;
                default:
-                       if (pendingdel->sent != NULL)
-                               LOGERR("Unknown command type: 0x%x.  Only freeing list structure.\n",
-                                    pendingdel->cmdtype);
+                       break;
                }
                pendingdel->cmdtype = 0;
                pendingdel->sent = NULL;
@@ -1575,8 +1398,6 @@ virthba_serverdown_complete(struct work_struct *work)
 
        virtpcidev = virthbainfo->virtpcidev;
 
-       DBGINF("virtpcidev bus_no<<%d>>devNo<<%d>>", virtpcidev->bus_no,
-              virtpcidev->device_no);
        virthbainfo->serverdown = true;
        virthbainfo->serverchangingstate = false;
        /* Return the ServerDown response to Command */
@@ -1594,19 +1415,12 @@ virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state)
            (struct virthba_info *)((struct Scsi_Host *)virtpcidev->scsi.
                                     scsihost)->hostdata;
 
-       DBGINF("virthba_serverdown");
-       DBGINF("virtpcidev bus_no<<%d>>devNo<<%d>>", virtpcidev->bus_no,
-              virtpcidev->device_no);
-
        if (!virthbainfo->serverdown && !virthbainfo->serverchangingstate) {
                virthbainfo->serverchangingstate = true;
                queue_work(virthba_serverdown_workqueue,
                           &virthbainfo->serverdown_completion);
        } else if (virthbainfo->serverchangingstate) {
-               LOGERR("Server already processing change state message\n");
                stat = 0;
-       } else {
-               LOGERR("Server already down, but another server down message received.");
        }
 
        return stat;
@@ -1619,7 +1433,6 @@ virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state)
 static int __init
 virthba_parse_line(char *str)
 {
-       DBGINF("In virthba_parse_line %s\n", str);
        return 1;
 }
 
@@ -1629,14 +1442,13 @@ virthba_parse_options(char *line)
        char *next = line;
 
        POSTCODE_LINUX_2(VHBA_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
-       if (line == NULL || !*line)
+       if (!line || !*line)
                return;
-       while ((line = next) != NULL) {
+       while ((line = next)) {
                next = strchr(line, ' ');
-               if (next != NULL)
+               if (next)
                        *next++ = 0;
-               if (!virthba_parse_line(line))
-                       DBGINF("Unknown option '%s'\n", line);
+               virthba_parse_line(line);
        }
 
        POSTCODE_LINUX_2(VHBA_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
@@ -1651,14 +1463,11 @@ virthba_mod_init(void)
        if (!unisys_spar_platform)
                return -ENODEV;
 
-       LOGINF("Entering virthba_mod_init...\n");
-
        POSTCODE_LINUX_2(VHBA_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
        virthba_parse_options(virthba_options);
 
        error = virtpci_register_driver(&virthba_driver);
        if (error < 0) {
-               LOGERR("register ****FAILED 0x%x\n", error);
                POSTCODE_LINUX_3(VHBA_CREATE_FAILURE_PC, error,
                                 POSTCODE_SEVERITY_ERR);
        } else {
@@ -1681,8 +1490,7 @@ virthba_mod_init(void)
                /* Initialize the serverdown workqueue */
                virthba_serverdown_workqueue =
                    create_singlethread_workqueue("virthba_serverdown");
-               if (virthba_serverdown_workqueue == NULL) {
-                       LOGERR("**** FAILED virthba_serverdown_workqueue creation\n");
+               if (!virthba_serverdown_workqueue) {
                        POSTCODE_LINUX_2(VHBA_CREATE_FAILURE_PC,
                                         POSTCODE_SEVERITY_ERR);
                        error = -1;
@@ -1690,7 +1498,6 @@ virthba_mod_init(void)
        }
 
        POSTCODE_LINUX_2(VHBA_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
-       LOGINF("Leaving virthba_mod_init\n");
        return error;
 }
 
@@ -1740,8 +1547,6 @@ static DEVICE_ATTRIBUTE *virthba_shost_attrs[] = {
 static void __exit
 virthba_mod_exit(void)
 {
-       LOGINF("entering virthba_mod_exit...\n");
-
        virtpci_unregister_driver(&virthba_driver);
        /* unregister is going to call virthba_remove */
        /* destroy serverdown completion workqueue */
@@ -1751,7 +1556,6 @@ virthba_mod_exit(void)
        }
 
        debugfs_remove_recursive(virthba_debugfs_dir);
-       LOGINF("Leaving virthba_mod_exit\n");
 }
 
 /* specify function to be run at module insertion time */
index e59efcbc4d3b6b9b22d78d81b73198c216e36b36..6d19482ce11badcc7b2da0788869736ed16578b1 100644 (file)
@@ -4,7 +4,7 @@
 
 config UNISYS_VIRTPCI
        tristate "Unisys virtpci driver"
-       depends on UNISYSSPAR && UNISYS_UISLIB
+       select UNISYS_UISLIB
        ---help---
        If you say Y here, you will enable the Unisys virtpci driver.
 
index 8fdfd6f3605f0b1bcdfccc7fe8df607bec7a577f..d5ad01783c07214aff8f35b8f4745f78137f58f2 100644 (file)
@@ -21,7 +21,6 @@
 #ifdef CONFIG_MODVERSIONS
 #include <config/modversions.h>
 #endif
-#include "uniklog.h"
 #include "diagnostics/appos_subsystems.h"
 #include "uisutils.h"
 #include "vbuschannel.h"
@@ -187,13 +186,11 @@ static int write_vbus_chp_info(struct spar_vbus_channel_protocol *chan,
 {
        int off;
 
-       if (!chan) {
-               LOGERR("vbus channel not present");
+       if (!chan)
                return -1;
-       }
+
        off = sizeof(struct channel_header) + chan->hdr_info.chp_info_offset;
        if (chan->hdr_info.chp_info_offset == 0) {
-               LOGERR("vbus channel not used, because chp_info_offset == 0");
                return -1;
        }
        memcpy(((u8 *)(chan)) + off, info, sizeof(*info));
@@ -206,15 +203,12 @@ static int write_vbus_bus_info(struct spar_vbus_channel_protocol *chan,
 {
        int off;
 
-       if (!chan) {
-               LOGERR("vbus channel not present");
+       if (!chan)
                return -1;
-       }
+
        off = sizeof(struct channel_header) + chan->hdr_info.bus_info_offset;
-       if (chan->hdr_info.bus_info_offset == 0) {
-               LOGERR("vbus channel not used, because bus_info_offset == 0");
+       if (chan->hdr_info.bus_info_offset == 0)
                return -1;
-       }
        memcpy(((u8 *)(chan)) + off, info, sizeof(*info));
        return 0;
 }
@@ -228,18 +222,16 @@ write_vbus_dev_info(struct spar_vbus_channel_protocol *chan,
 {
        int off;
 
-       if (!chan) {
-               LOGERR("vbus channel not present");
+       if (!chan)
                return -1;
-       }
+
        off =
            (sizeof(struct channel_header) +
             chan->hdr_info.dev_info_offset) +
            (chan->hdr_info.device_info_struct_bytes * devix);
-       if (chan->hdr_info.dev_info_offset == 0) {
-               LOGERR("vbus channel not used, because dev_info_offset == 0");
+       if (chan->hdr_info.dev_info_offset == 0)
                return -1;
-       }
+
        memcpy(((u8 *)(chan)) + off, info, sizeof(*info));
        return 0;
 }
@@ -271,7 +263,6 @@ static int add_vbus(struct add_vbus_guestpart *addparams)
         */
        ret = device_register(vbus);
        if (ret) {
-               LOGERR("device_register FAILED:%d\n", ret);
                POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
                return 0;
        }
@@ -279,8 +270,6 @@ static int add_vbus(struct add_vbus_guestpart *addparams)
                            &chipset_driver_info);
        write_vbus_bus_info(vbus->platform_data /* chanptr */,
                            &bus_driver_info);
-       LOGINF("Added vbus %d; device %s created successfully\n",
-              addparams->bus_no, BUS_ID(vbus));
        POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
        return 1;
 }
@@ -312,7 +301,6 @@ static int add_vhba(struct add_virt_guestpart *addparams)
        POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
        if (!WAIT_FOR_IO_CHANNEL
            ((struct spar_io_channel_protocol __iomem *)addparams->chanptr)) {
-               LOGERR("Timed out.  Channel not ready\n");
                POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
                return 0;
        }
@@ -323,19 +311,11 @@ static int add_vhba(struct add_virt_guestpart *addparams)
        sprintf(busid, "vbus%d", addparams->bus_no);
        vbus = bus_find_device(&virtpci_bus_type, NULL,
                               (void *)busid, match_busid);
-       if (!vbus) {
-               LOGERR("**** FAILED to find vbus %s\n", busid);
+       if (!vbus)
                return 0;
-       }
 
-       LOGINF("Adding vhba wwnn:%x:%x config:%d-%d-%d-%d chanptr:%p\n",
-              scsi.wwnn.wwnn1, scsi.wwnn.wwnn2,
-              scsi.max.max_channel, scsi.max.max_id, scsi.max.max_lun,
-              scsi.max.cmd_per_lun, addparams->chanptr);
        i = virtpci_device_add(vbus, VIRTHBA_TYPE, addparams, &scsi, NULL);
        if (i) {
-               LOGINF("Added vhba wwnn:%x:%x chanptr:%p\n", scsi.wwnn.wwnn1,
-                      scsi.wwnn.wwnn2, addparams->chanptr);
                POSTCODE_LINUX_3(VPCI_CREATE_EXIT_PC, i,
                                 POSTCODE_SEVERITY_INFO);
        }
@@ -375,7 +355,6 @@ add_vnic(struct add_virt_guestpart *addparams)
        POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
        if (!WAIT_FOR_IO_CHANNEL
            ((struct spar_io_channel_protocol __iomem *)addparams->chanptr)) {
-               LOGERR("Timed out, channel not ready\n");
                POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
                return 0;
        }
@@ -386,20 +365,11 @@ add_vnic(struct add_virt_guestpart *addparams)
        sprintf(busid, "vbus%d", addparams->bus_no);
        vbus = bus_find_device(&virtpci_bus_type, NULL,
                               (void *)busid, match_busid);
-       if (!vbus) {
-               LOGERR("**** FAILED to find vbus %s\n", busid);
+       if (!vbus)
                return 0;
-       }
 
-       LOGINF("Adding vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x rcvbufs:%d mtu:%d chanptr:%p%pUL\n",
-              net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
-              net.mac_addr[3], net.mac_addr[4], net.mac_addr[5],
-              net.num_rcv_bufs, net.mtu, addparams->chanptr, &net.zone_uuid);
        i = virtpci_device_add(vbus, VIRTNIC_TYPE, addparams, NULL, &net);
        if (i) {
-               LOGINF("Added vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
-                      net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
-                      net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
                POSTCODE_LINUX_3(VPCI_CREATE_EXIT_PC, i,
                                 POSTCODE_SEVERITY_INFO);
                return 1;
@@ -420,34 +390,24 @@ delete_vbus(struct del_vbus_guestpart *delparams)
        sprintf(busid, "vbus%d", delparams->bus_no);
        vbus = bus_find_device(&virtpci_bus_type, NULL,
                               (void *)busid, match_busid);
-       if (!vbus) {
-               LOGERR("**** FAILED to find vbus %s\n", busid);
+       if (!vbus)
                return 0;
-       }
 
        /* ensure that bus has no devices? -- TBD */
-       LOGINF("Deleting %s\n", BUS_ID(vbus));
-       if (delete_vbus_device(vbus, NULL))
-               return 0;       /* failure */
-       LOGINF("Deleted vbus %d\n", delparams->bus_no);
        return 1;
 }
 
 static int
 delete_vbus_device(struct device *vbus, void *data)
 {
-       int checkforroot = (data != NULL);
        struct device *dev = &virtpci_rootbus_device;
 
-       if ((checkforroot) && match_busid(vbus, (void *)BUS_ID(dev))) {
+       if ((data) && match_busid(vbus, (void *)BUS_ID(dev))) {
                /* skip it - don't delete root bus */
-               LOGINF("skipping root bus\n");
                return 0;       /* pretend no error */
        }
-       LOGINF("Calling unregister for %s\n", BUS_ID(vbus));
        device_unregister(vbus);
        kfree(vbus);
-       LOGINF("VBus unregister and freed\n");
        return 0;               /* no error */
 }
 
@@ -461,12 +421,8 @@ static int pause_vhba(struct pause_virt_guestpart *pauseparams)
 
        GET_SCSIADAPINFO_FROM_CHANPTR(pauseparams->chanptr);
 
-       LOGINF("Pausing vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2);
        i = virtpci_device_serverdown(NULL /*no parent bus */, VIRTHBA_TYPE,
                                      &scsi.wwnn, NULL);
-       if (i)
-               LOGINF("Paused vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1,
-                      scsi.wwnn.wwnn2);
        return i;
 }
 
@@ -480,16 +436,8 @@ static int pause_vnic(struct pause_virt_guestpart *pauseparams)
 
        GET_NETADAPINFO_FROM_CHANPTR(pauseparams->chanptr);
 
-       LOGINF("Pausing vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
-              net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
-              net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
        i = virtpci_device_serverdown(NULL /*no parent bus */, VIRTNIC_TYPE,
                                      NULL, net.mac_addr);
-       if (i) {
-               LOGINF(" Paused vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
-                      net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
-                      net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
-       }
        return i;
 }
 
@@ -503,12 +451,8 @@ static int resume_vhba(struct resume_virt_guestpart *resumeparams)
 
        GET_SCSIADAPINFO_FROM_CHANPTR(resumeparams->chanptr);
 
-       LOGINF("Resuming vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2);
        i = virtpci_device_serverup(NULL /*no parent bus */, VIRTHBA_TYPE,
                                    &scsi.wwnn, NULL);
-       if (i)
-               LOGINF("Resumed vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1,
-                      scsi.wwnn.wwnn2);
        return i;
 }
 
@@ -523,16 +467,8 @@ resume_vnic(struct resume_virt_guestpart *resumeparams)
 
        GET_NETADAPINFO_FROM_CHANPTR(resumeparams->chanptr);
 
-       LOGINF("Resuming vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
-              net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
-              net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
        i = virtpci_device_serverup(NULL /*no parent bus */, VIRTNIC_TYPE,
                                    NULL, net.mac_addr);
-       if (i) {
-               LOGINF(" Resumed vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
-                      net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
-                      net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
-       }
        return i;
 }
 
@@ -546,12 +482,9 @@ static int delete_vhba(struct del_virt_guestpart *delparams)
 
        GET_SCSIADAPINFO_FROM_CHANPTR(delparams->chanptr);
 
-       LOGINF("Deleting vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2);
        i = virtpci_device_del(NULL /*no parent bus */, VIRTHBA_TYPE,
                               &scsi.wwnn, NULL);
        if (i) {
-               LOGINF("Deleted vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1,
-                      scsi.wwnn.wwnn2);
                return 1;
        }
        return 0;
@@ -567,23 +500,13 @@ static int delete_vnic(struct del_virt_guestpart *delparams)
 
        GET_NETADAPINFO_FROM_CHANPTR(delparams->chanptr);
 
-       LOGINF("Deleting vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
-              net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
-              net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
        i = virtpci_device_del(NULL /*no parent bus */, VIRTNIC_TYPE, NULL,
                               net.mac_addr);
-       if (i) {
-               LOGINF("Deleted vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
-                      net.mac_addr[0], net.mac_addr[1], net.mac_addr[2],
-                      net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]);
-       }
        return i;
 }
 
 #define DELETE_ONE_VPCIDEV(vpcidev) { \
-       LOGINF("calling device_unregister:%p\n", &vpcidev->generic_dev); \
        device_unregister(&vpcidev->generic_dev); \
-       LOGINF("Deleted %p\n", vpcidev); \
        kfree(vpcidev); \
 }
 
@@ -610,12 +533,10 @@ static void delete_all(void)
                tmpvpcidev = nextvpcidev;
                count++;
        }
-       LOGINF("Deleted %d vhbas/vnics.\n", count);
 
        /* now delete each vbus */
-       if (bus_for_each_dev
-           (&virtpci_bus_type, NULL, (void *)1, delete_vbus_device))
-               LOGERR("delete of all vbus failed\n");
+       bus_for_each_dev(&virtpci_bus_type, NULL, (void *)1,
+                        delete_vbus_device);
 }
 
 /* deletes all vnics or vhbas
@@ -632,24 +553,14 @@ static int delete_all_virt(enum virtpci_dev_type devtype,
        sprintf(busid, "vbus%d", delparams->bus_no);
        vbus = bus_find_device(&virtpci_bus_type, NULL,
                               (void *)busid, match_busid);
-       if (!vbus) {
-               LOGERR("**** FAILED to find vbus %s\n", busid);
+       if (!vbus)
                return 0;
-       }
 
-       if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
-               LOGERR("**** FAILED to delete all devices; devtype:%d not vhba:%d or vnic:%d\n",
-                      devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+       if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE))
                return 0;
-       }
 
-       LOGINF("Deleting all %s in vbus %s\n",
-              devtype == VIRTHBA_TYPE ? "vhbas" : "vnics", busid);
        /* delete all vhbas/vnics */
        i = virtpci_device_del(vbus, devtype, NULL, NULL);
-       if (i > 0)
-               LOGINF("Deleted %d %s\n", i,
-                      devtype == VIRTHBA_TYPE ? "vhbas" : "vnics");
        return 1;
 }
 
@@ -684,7 +595,6 @@ static int virtpci_ctrlchan_func(struct guest_msgs *msg)
        case GUEST_RESUME_VNIC:
                return resume_vnic(&msg->resume_vnic);
        default:
-               LOGERR("invalid message type %d.\n", msg->msgtype);
                return 0;
        }
 }
@@ -708,9 +618,6 @@ virtpci_match_device(const struct pci_device_id *ids,
                     const struct virtpci_dev *dev)
 {
        while (ids->vendor || ids->subvendor || ids->class_mask) {
-               DBGINF("ids->vendor:%x dev->vendor:%x ids->device:%x dev->device:%x\n",
-                      ids->vendor, dev->vendor, ids->device, dev->device);
-
                if ((ids->vendor == dev->vendor) &&
                    (ids->device == dev->device))
                        return ids;
@@ -731,20 +638,15 @@ static int virtpci_bus_match(struct device *dev, struct device_driver *drv)
        struct virtpci_driver *virtpcidrv = driver_to_virtpci_driver(drv);
        int match = 0;
 
-       DBGINF("In virtpci_bus_match dev->bus_id:%s drv->name:%s\n",
-              dev->bus_id, drv->name);
-
        /* check ids list for a match */
        if (virtpci_match_device(virtpcidrv->id_table, virtpcidev))
                match = 1;
 
-       DBGINF("returning match:%d\n", match);
        return match;           /* 0 - no match; 1 - yes it matches */
 }
 
 static int virtpci_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
-       DBGINF("In virtpci_hotplug\n");
        /* add variables to the environment prior to the generation of
         * hotplug events to user space
         */
@@ -766,24 +668,19 @@ static void fix_vbus_dev_info(struct device *dev, int dev_no, int dev_type,
        struct ultra_vbus_deviceinfo dev_info;
        const char *stype;
 
-       if (!dev) {
-               LOGERR("%s dev is NULL", __func__);
+       if (!dev)
                return;
-       }
-       if (!virtpcidrv) {
-               LOGERR("%s driver is NULL", __func__);
+       if (!virtpcidrv)
                return;
-       }
+
        vbus = dev->parent;
-       if (!vbus) {
-               LOGERR("%s dev has no parent bus", __func__);
+       if (!vbus)
                return;
-       }
+
        chan = vbus->platform_data;
-       if (!chan) {
-               LOGERR("%s dev bus has no channel", __func__);
+       if (!chan)
                return;
-       }
+
        switch (dev_type) {
        case PCI_DEVICE_ID_VIRTHBA:
                stype = "vHBA";
@@ -820,8 +717,6 @@ static int virtpci_device_probe(struct device *dev)
        const struct pci_device_id *id;
        int error = 0;
 
-       LOGINF("In virtpci_device_probe dev:%p virtpcidev:%p virtpcidrv:%p\n",
-              dev, virtpcidev, virtpcidrv);    /* VERBOSE/DEBUG ? */
        POSTCODE_LINUX_2(VPCI_PROBE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
        /* static match and static probe vs dynamic match & dynamic
         * probe - do we care?.
@@ -866,9 +761,6 @@ static int virtpci_device_remove(struct device *dev_)
        struct virtpci_dev *virtpcidev = device_to_virtpci_dev(dev_);
        struct virtpci_driver *virtpcidrv = virtpcidev->mydriver;
 
-       LOGINF("In virtpci_device_remove bus_id:%s dev_:%p virtpcidev:%p dev->driver:%p drivername:%s\n",
-              BUS_ID(dev_), dev_, virtpcidev, dev_->driver,
-              dev_->driver->name);     /* VERBOSE/DEBUG */
        if (virtpcidrv) {
                /* TEMP: assuming we have only one such driver for now */
                if (virtpcidrv->remove)
@@ -876,10 +768,7 @@ static int virtpci_device_remove(struct device *dev_)
                virtpcidev->mydriver = NULL;
        }
 
-       DBGINF("calling putdevice\n");
        put_device(dev_);
-
-       DBGINF("Leaving\n");
        return 0;
 }
 
@@ -889,11 +778,6 @@ static int virtpci_device_remove(struct device *dev_)
 
 static void virtpci_bus_release(struct device *dev)
 {
-       /* this function is called when the last reference to the
-        * device is removed
-        */
-       DBGINF("In virtpci_bus_release\n");
-       /* what else is supposed to happen here? */
 }
 
 /*****************************************************/
@@ -915,14 +799,9 @@ static int virtpci_device_add(struct device *parentbus, int devtype,
        struct spar_io_channel_protocol __iomem *io_chan = NULL;
        struct device *dev;
 
-       LOGINF("virtpci_device_add parentbus:%p chanptr:%p\n", parentbus,
-              addparams->chanptr);
-
        POSTCODE_LINUX_2(VPCI_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO);
 
        if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
-               LOGERR("**** FAILED to add device; devtype:%d not vhba:%d or vnic:%d\n",
-                      devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
                POSTCODE_LINUX_3(VPCI_CREATE_FAILURE_PC, devtype,
                                 POSTCODE_SEVERITY_ERR);
                return 0;
@@ -930,8 +809,7 @@ static int virtpci_device_add(struct device *parentbus, int devtype,
 
        /* add a Virtual Device */
        virtpcidev = kzalloc(sizeof(*virtpcidev), GFP_ATOMIC);
-       if (virtpcidev == NULL) {
-               LOGERR("can't add device - malloc FALLED\n");
+       if (!virtpcidev) {
                POSTCODE_LINUX_2(MALLOC_FAILURE_PC, POSTCODE_SEVERITY_ERR);
                return 0;
        }
@@ -993,7 +871,6 @@ static int virtpci_device_add(struct device *parentbus, int devtype,
                 */
                write_unlock_irqrestore(&vpcidev_list_lock, flags);
                kfree(virtpcidev);
-               LOGERR("**** FAILED vhba/vnic already exists in the list\n");
                POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
                return 0;
        }
@@ -1024,8 +901,6 @@ static int virtpci_device_add(struct device *parentbus, int devtype,
        * list. Otherwise, a device_unregister from this function can
        * cause a "scheduling while atomic".
        */
-       DBGINF("registering device:%p with bus_id:%s\n",
-              &virtpcidev->generic_dev, virtpcidev->generic_dev.bus_id);
        ret = device_register(&virtpcidev->generic_dev);
        /* NOTE: THIS IS CALLING HOTPLUG virtpci_hotplug!!!
         * This call to device_register results in virtpci_bus_match
@@ -1037,7 +912,6 @@ static int virtpci_device_add(struct device *parentbus, int devtype,
         * virtpci_device_probe is successful
         */
        if (ret) {
-               LOGERR("device_register returned %d\n", ret);
                dev = &virtpcidev->generic_dev;
                SPAR_CHANNEL_CLIENT_TRANSITION(addparams->chanptr,
                                               BUS_ID(dev),
@@ -1060,10 +934,6 @@ static int virtpci_device_add(struct device *parentbus, int devtype,
                return 0;
        }
 
-       LOGINF("Added %s:%d:%d &virtpcidev->generic_dev:%p\n",
-              (devtype == VIRTHBA_TYPE) ? "virthba" : "virtnic",
-              addparams->bus_no, addparams->device_no,
-              &virtpcidev->generic_dev);
        POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
        return 1;
 }
@@ -1080,11 +950,8 @@ static int virtpci_device_serverdown(struct device *parentbus,
        unsigned long flags;
        int rc = 0;
 
-       if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
-               LOGERR("**** FAILED to pause device; devtype:%d not vhba:%d or vnic:%d\n",
-                      devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+       if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE))
                return 0;
-       }
 
        /* find the vhba or vnic in virtpci device list */
        write_lock_irqsave(&vpcidev_list_lock, flags);
@@ -1119,10 +986,8 @@ static int virtpci_device_serverdown(struct device *parentbus,
        }
        write_unlock_irqrestore(&vpcidev_list_lock, flags);
 
-       if (!found) {
-               LOGERR("**** FAILED to find vhba/vnic in the list\n");
+       if (!found)
                return 0;
-       }
 
        return rc;
 }
@@ -1139,11 +1004,9 @@ static int virtpci_device_serverup(struct device *parentbus,
        unsigned long flags;
        int rc = 0;
 
-       if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
-               LOGERR("**** FAILED to resume device; devtype:%d not vhba:%d or vnic:%d\n",
-                      devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+       if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE))
                return 0;
-       }
+
 
        /* find the vhba or vnic in virtpci device list */
        write_lock_irqsave(&vpcidev_list_lock, flags);
@@ -1187,10 +1050,8 @@ static int virtpci_device_serverup(struct device *parentbus,
 
        write_unlock_irqrestore(&vpcidev_list_lock, flags);
 
-       if (!found) {
-               LOGERR("**** FAILED to find vhba/vnic in the list\n");
+       if (!found)
                return 0;
-       }
 
        return rc;
 }
@@ -1209,17 +1070,14 @@ static int virtpci_device_del(struct device *parentbus,
        continue; \
 }
 
-       if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE)) {
-               LOGERR("**** FAILED to delete device; devtype:%d not vhba:%d or vnic:%d\n",
-                      devtype, VIRTHBA_TYPE, VIRTNIC_TYPE);
+       if ((devtype != VIRTHBA_TYPE) && (devtype != VIRTNIC_TYPE))
                return 0;
-       }
 
        /* see if we are to delete all - NOTE: all implies we have a
         * valid parentbus
         */
-       all = ((devtype == VIRTHBA_TYPE) && (wwnn == NULL)) ||
-           ((devtype == VIRTNIC_TYPE) && (macaddr == NULL));
+       all = ((devtype == VIRTHBA_TYPE) && (!wwnn)) ||
+           ((devtype == VIRTNIC_TYPE) && (!macaddr));
 
        /* find all the vhba or vnic or both in virtpci device list
        * keep list of ones we are deleting so we can call
@@ -1280,10 +1138,8 @@ static int virtpci_device_del(struct device *parentbus,
        }
        write_unlock_irqrestore(&vpcidev_list_lock, flags);
 
-       if (!all && (count == 0)) {
-               LOGERR("**** FAILED to find vhba/vnic in the list\n");
+       if (!all && (count == 0))
                return 0;
-       }
 
        /* now delete each one from delete list */
        while (dellist) {
@@ -1303,7 +1159,6 @@ static void virtpci_device_release(struct device *dev_)
        /* this function is called when the last reference to the
         * device is removed
         */
-       LOGINF("In virtpci_device_release:%p - NOT YET IMPLEMENTED\n", dev_);
 }
 
 /*****************************************************/
@@ -1324,8 +1179,6 @@ static ssize_t virtpci_driver_attr_show(struct kobject *kobj,
        struct driver_private *dprivate = to_driver(kobj);
        struct device_driver *driver = dprivate->driver;
 
-       DBGINF("In virtpci_driver_attr_show driver->name:%s\n", driver->name);
-
        if (dattr->show)
                ret = dattr->show(driver, buf);
 
@@ -1342,8 +1195,6 @@ static ssize_t virtpci_driver_attr_store(struct kobject *kobj,
        struct driver_private *dprivate = to_driver(kobj);
        struct device_driver *driver = dprivate->driver;
 
-       DBGINF("In virtpci_driver_attr_store driver->name:%s\n", driver->name);
-
        if (dattr->store)
                ret = dattr->store(driver, buf, count);
 
@@ -1355,12 +1206,8 @@ int virtpci_register_driver(struct virtpci_driver *drv)
 {
        int result = 0;
 
-       DBGINF("In virtpci_register_driver\n");
-
-       if (drv->id_table == NULL) {
-               LOGERR("id_table missing\n");
+       if (!drv->id_table)
                return 1;
-       }
        /* initialize core driver fields needed to call driver_register */
        drv->core_driver.name = drv->name;      /* name of driver in sysfs */
        drv->core_driver.bus = &virtpci_bus_type;       /* type of bus this
@@ -1389,7 +1236,6 @@ EXPORT_SYMBOL_GPL(virtpci_register_driver);
 
 void virtpci_unregister_driver(struct virtpci_driver *drv)
 {
-       DBGINF("In virtpci_unregister_driver drv:%p\n", drv);
        driver_unregister(&drv->core_driver);
        /* driver_unregister calls bus_remove_driver
         * bus_remove_driver calls device_detach
@@ -1399,7 +1245,6 @@ void virtpci_unregister_driver(struct virtpci_driver *drv)
         * virtpci_device_remove
         * virtpci_device_remove calls virthba_remove
         */
-       DBGINF("Leaving\n");
 }
 EXPORT_SYMBOL_GPL(virtpci_unregister_driver);
 
@@ -1442,9 +1287,8 @@ static ssize_t info_debugfs_read(struct file *file, char __user *buf,
        printparam.str_pos = &str_pos;
        printparam.buf = vbuf;
        printparam.len = &len;
-       if (bus_for_each_dev(&virtpci_bus_type, NULL,
-                            (void *)&printparam, print_vbus))
-               LOGERR("Failed to find bus\n");
+       bus_for_each_dev(&virtpci_bus_type, NULL, (void *)&printparam,
+                        print_vbus);
 
        str_pos += scnprintf(vbuf + str_pos, len - str_pos,
                        "\n Virtual PCI devices\n");
@@ -1464,15 +1308,10 @@ static ssize_t info_debugfs_read(struct file *file, char __user *buf,
                                        tmpvpcidev->scsi.max.cmd_per_lun);
                } else {
                        str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                       "[%d:%d] VNic:%02x:%02x:%02x:%02x:%02x:%02x num_rcv_bufs:%d mtu:%d",
+                                       "[%d:%d] VNic:%pM num_rcv_bufs:%d mtu:%d",
                                        tmpvpcidev->bus_no,
                                        tmpvpcidev->device_no,
-                                       tmpvpcidev->net.mac_addr[0],
-                                       tmpvpcidev->net.mac_addr[1],
-                                       tmpvpcidev->net.mac_addr[2],
-                                       tmpvpcidev->net.mac_addr[3],
-                                       tmpvpcidev->net.mac_addr[4],
-                                       tmpvpcidev->net.mac_addr[5],
+                                       tmpvpcidev->net.mac_addr,
                                        tmpvpcidev->net.num_rcv_bufs,
                                        tmpvpcidev->net.mtu);
                }
@@ -1507,58 +1346,44 @@ static int __init virtpci_mod_init(void)
         * drivers directory
         */
        if (ret) {
-               LOGERR("bus_register ****FAILED:%d\n", ret);
                POSTCODE_LINUX_3(VPCI_CREATE_FAILURE_PC, ret,
                                 POSTCODE_SEVERITY_ERR);
                return ret;
        }
-       DBGINF("bus_register successful\n");
        bus_device_info_init(&bus_driver_info, "clientbus", "virtpci",
                             VERSION, NULL);
 
        /* create a root bus used to parent all the virtpci buses. */
        ret = device_register(&virtpci_rootbus_device);
        if (ret) {
-               LOGERR("device_register FAILED:%d\n", ret);
                bus_unregister(&virtpci_bus_type);
                POSTCODE_LINUX_3(VPCI_CREATE_FAILURE_PC, ret,
                                 POSTCODE_SEVERITY_ERR);
                return ret;
        }
-       DBGINF("device_register successful ret:%x\n", ret);
 
        if (!uisctrl_register_req_handler(2, (void *)&virtpci_ctrlchan_func,
                                          &chipset_driver_info)) {
-               LOGERR("uisctrl_register_req_handler ****FAILED.\n");
                POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR);
                device_unregister(&virtpci_rootbus_device);
                bus_unregister(&virtpci_bus_type);
                return -1;
        }
 
-       LOGINF("successfully registered virtpci_ctrlchan_func (0x%p) as callback.\n",
-              (void *)&virtpci_ctrlchan_func);
        /* create debugfs directory and info file inside. */
        virtpci_debugfs_dir = debugfs_create_dir("virtpci", NULL);
        debugfs_create_file("info", S_IRUSR, virtpci_debugfs_dir,
                            NULL, &debugfs_info_fops);
-       LOGINF("Leaving\n");
        POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
        return 0;
 }
 
 static void __exit virtpci_mod_exit(void)
 {
-       LOGINF("virtpci_mod_exit...\n");
-
        /* unregister the callback function */
-       if (!uisctrl_register_req_handler(2, NULL, NULL))
-               LOGERR("uisctrl_register_req_handler ****FAILED.\n");
-
        device_unregister(&virtpci_rootbus_device);
        bus_unregister(&virtpci_bus_type);
        debugfs_remove_recursive(virtpci_debugfs_dir);
-       LOGINF("Leaving\n");
 }
 
 module_init(virtpci_mod_init);
index 41c3b4b997eb8039e54fa2f449434cb312ed0101..8d31bebf039abfbdda261e5e464d114867e0b3e4 100644 (file)
@@ -4,7 +4,7 @@
 
 config UNISYS_VISORCHANNEL
        tristate "Unisys visorchannel driver"
-       depends on UNISYSSPAR && UNISYS_VISORUTIL
+       select UNISYS_VISORUTIL
        ---help---
        If you say Y here, you will enable the Unisys visorchannel driver.
 
index 581ed83fe6d07afe25b49cf2e4ab827eac5e3bda..0ed8e1d8033a8d8ca6ae4a92fc3befa706183c2e 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef __VISORCHANNEL_GLOBALS_H__
 #define __VISORCHANNEL_GLOBALS_H__
 
-#include "uniklog.h"
 #include "timskmod.h"
 #include "memregion.h"
 #include "version.h"
index 0188ef866fdd8a9630cf767a8f78e834e4bc84c8..7a9a7242f75d928d982585c6f1b340ecfa7e51d4 100644 (file)
@@ -58,8 +58,7 @@ visorchannel_create_guts(HOSTADDRESS physaddr, ulong channel_bytes,
        void *rc = NULL;
 
        p = kmalloc(sizeof(*p), GFP_KERNEL|__GFP_NORETRY);
-       if (p == NULL) {
-               ERRDRV("allocation failed: (status=0)\n");
+       if (!p) {
                rc = NULL;
                goto cleanup;
        }
@@ -69,7 +68,7 @@ visorchannel_create_guts(HOSTADDRESS physaddr, ulong channel_bytes,
        spin_lock_init(&p->remove_lock);
 
        /* prepare chan_hdr (abstraction to read/write channel memory) */
-       if (parent == NULL)
+       if (!parent)
                p->memregion =
                    visor_memregion_create(physaddr,
                                           sizeof(struct channel_header));
@@ -77,14 +76,12 @@ visorchannel_create_guts(HOSTADDRESS physaddr, ulong channel_bytes,
                p->memregion =
                    visor_memregion_create_overlapped(parent->memregion,
                                off, sizeof(struct channel_header));
-       if (p->memregion == NULL) {
-               ERRDRV("visor_memregion_create failed failed: (status=0)\n");
+       if (!p->memregion) {
                rc = NULL;
                goto cleanup;
        }
        if (visor_memregion_read(p->memregion, 0, &p->chan_hdr,
                                 sizeof(struct channel_header)) < 0) {
-               ERRDRV("visor_memregion_read failed: (status=0)\n");
                rc = NULL;
                goto cleanup;
        }
@@ -95,7 +92,6 @@ visorchannel_create_guts(HOSTADDRESS physaddr, ulong channel_bytes,
                /* we had better be a CLIENT of this channel */
                guid = p->chan_hdr.chtype;
        if (visor_memregion_resize(p->memregion, channel_bytes) < 0) {
-               ERRDRV("visor_memregion_resize failed: (status=0)\n");
                rc = NULL;
                goto cleanup;
        }
@@ -105,8 +101,8 @@ visorchannel_create_guts(HOSTADDRESS physaddr, ulong channel_bytes,
        rc = p;
 cleanup:
 
-       if (rc == NULL) {
-               if (p != NULL) {
+       if (!rc) {
+               if (!p) {
                        visorchannel_destroy(p);
                        p = NULL;
                }
@@ -154,9 +150,9 @@ EXPORT_SYMBOL_GPL(visorchannel_create_overlapped_with_lock);
 void
 visorchannel_destroy(struct visorchannel *channel)
 {
-       if (channel == NULL)
+       if (!channel)
                return;
-       if (channel->memregion != NULL) {
+       if (channel->memregion) {
                visor_memregion_destroy(channel->memregion);
                channel->memregion = NULL;
        }
@@ -256,10 +252,9 @@ visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch,
        int written = 0;
        u8 *buf = vmalloc(bufsize);
 
-       if (buf == NULL) {
-               ERRDRV("%s failed memory allocation", __func__);
+       if (!buf)
                goto cleanup;
-       }
+
        memset(buf, ch, bufsize);
        while (nbytes > 0) {
                ulong thisbytes = bufsize;
@@ -279,7 +274,7 @@ visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch,
        rc = 0;
 
 cleanup:
-       if (buf != NULL) {
+       if (buf) {
                vfree(buf);
                buf = NULL;
        }
@@ -324,10 +319,8 @@ sig_read_header(struct visorchannel *channel, u32 queue,
 {
        BOOL rc = FALSE;
 
-       if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header)) {
-               ERRDRV("oChannelSpace too small: (status=%d)\n", rc);
+       if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
                goto cleanup;
-       }
 
        /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
 
@@ -335,10 +328,6 @@ sig_read_header(struct visorchannel *channel, u32 queue,
                                 SIG_QUEUE_OFFSET(&channel->chan_hdr, queue),
                                 sig_hdr,
                                 sizeof(struct signal_queue_header)) < 0) {
-               ERRDRV("queue=%d SIG_QUEUE_OFFSET=%d",
-                      queue, (int)SIG_QUEUE_OFFSET(&channel->chan_hdr, queue));
-               ERRDRV("visor_memregion_read of signal queue failed: (status=%d)\n",
-                      rc);
                goto cleanup;
        }
        rc = TRUE;
@@ -358,15 +347,11 @@ sig_do_data(struct visorchannel *channel, u32 queue,
                if (visor_memregion_write(channel->memregion,
                                          signal_data_offset,
                                          data, sig_hdr->signal_size) < 0) {
-                       ERRDRV("visor_memregion_write of signal data failed: (status=%d)\n",
-                              rc);
                        goto cleanup;
                }
        } else {
                if (visor_memregion_read(channel->memregion, signal_data_offset,
                                         data, sig_hdr->signal_size) < 0) {
-                       ERRDRV("visor_memregion_read of signal data failed: (status=%d)\n",
-                              rc);
                        goto cleanup;
                }
        }
@@ -404,8 +389,6 @@ safe_sig_queue_validate(struct signal_queue_header *psafe_sqh,
                punsafe_sqh->head = *phead;
                punsafe_sqh->tail = *ptail;
 
-               ERRDRV("safe_sig_queue_validate: head = 0x%x, tail = 0x%x, MaxSlots = 0x%x",
-                      *phead, *ptail, psafe_sqh->max_slots);
                return 0;
        }
        return 1;
@@ -416,15 +399,13 @@ signalremove_inner(struct visorchannel *channel, u32 queue, void *msg)
 {
        struct signal_queue_header sig_hdr;
 
-       if (!sig_read_header(channel, queue, &sig_hdr)) {
+       if (!sig_read_header(channel, queue, &sig_hdr))
                return FALSE;
-       }
        if (sig_hdr.head == sig_hdr.tail)
                return FALSE;   /* no signals to remove */
 
        sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
        if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg)) {
-               ERRDRV("sig_read_data failed\n");
                return FALSE;
        }
        sig_hdr.num_received++;
@@ -433,14 +414,10 @@ signalremove_inner(struct visorchannel *channel, u32 queue, void *msg)
         * update host memory.
         */
        mb(); /* required for channel synch */
-       if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail)) {
-               ERRDRV("visor_memregion_write of Tail failed\n");
+       if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail))
                return FALSE;
-       }
-       if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received)) {
-               ERRDRV("visor_memregion_write of NumSignalsReceived failed\n");
+       if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received))
                return FALSE;
-       }
        return TRUE;
 }
 
@@ -466,35 +443,34 @@ signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
 {
        struct signal_queue_header sig_hdr;
 
-       if (!sig_read_header(channel, queue, &sig_hdr)) {
+       if (!sig_read_header(channel, queue, &sig_hdr))
                return FALSE;
-       }
 
        sig_hdr.head = ((sig_hdr.head + 1) % sig_hdr.max_slots);
        if (sig_hdr.head == sig_hdr.tail) {
                sig_hdr.num_overflows++;
-               if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_overflows))
-                       ERRDRV("visor_memregion_write of NumOverflows failed\n");
-
+               visor_memregion_write(channel->memregion,
+                                     SIG_QUEUE_OFFSET(&channel->chan_hdr,
+                                                      queue) +
+                                     offsetof(struct signal_queue_header,
+                                              num_overflows),
+                                     &(sig_hdr.num_overflows),
+                                     sizeof(sig_hdr.num_overflows));
                return FALSE;
        }
 
-       if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg)) {
-               ERRDRV("sig_write_data failed\n");
+       if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg))
                return FALSE;
-       }
+
        sig_hdr.num_sent++;
 
        /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
         * update host memory.
         */
        mb(); /* required for channel synch */
-       if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head)) {
-               ERRDRV("visor_memregion_write of Head failed\n");
+       if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head))
                return FALSE;
-       }
        if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent)) {
-               ERRDRV("visor_memregion_write of NumSignalsSent failed\n");
                return FALSE;
        }
 
@@ -584,15 +560,12 @@ visorchannel_debug(struct visorchannel *channel, int num_queues,
        int i = 0;
        int errcode = 0;
 
-       if (channel == NULL) {
-               ERRDRV("%s no channel", __func__);
+       if (!channel)
                return;
-       }
        memregion = channel->memregion;
-       if (memregion == NULL) {
-               ERRDRV("%s no memregion", __func__);
+       if (!memregion)
                return;
-       }
+
        addr = visor_memregion_get_physaddr(memregion);
        nbytes_region = visor_memregion_get_nbytes(memregion);
        errcode = visorchannel_read(channel, off,
@@ -672,11 +645,8 @@ visorchannel_dump_section(struct visorchannel *chan, char *s,
                goto fmt_failed;
 
        errcode = visorchannel_read(chan, off, buf, len);
-       if (errcode < 0) {
-               ERRDRV("%s failed to read %s from channel errcode=%d",
-                      s, __func__, errcode);
+       if (errcode < 0)
                goto read_failed;
-       }
        seq_printf(seq, "channel %s:\n", s);
        tbuf = buf;
        while (len > 0) {
index f4be2e62c97dbb0d2387042c7ff5de8151847a38..787d4774b1990fac44bbc1362f68a23b775ab00c 100644 (file)
@@ -32,14 +32,12 @@ visorchannel_init(void)
        if (!unisys_spar_platform)
                return -ENODEV;
 
-       INFODRV("driver version %s loaded", VERSION);
        return 0;
 }
 
 static void
 visorchannel_exit(void)
 {
-       INFODRV("driver unloaded");
 }
 
 module_init(visorchannel_init);
index e86836f84243c7265cca27c2ff191ce7f5a43ce0..b03bfc5c3043f1cf15fd8b5094b1150e1fca769e 100644 (file)
@@ -4,7 +4,8 @@
 
 config UNISYS_VISORCHIPSET
        tristate "Unisys visorchipset driver"
-       depends on UNISYSSPAR && UNISYS_VISORUTIL && UNISYS_VISORCHANNEL && HAS_IOMEM
+       select UNISYS_VISORUTIL
+       select UNISYS_VISORCHANNEL
        ---help---
        If you say Y here, you will enable the Unisys visorchipset driver.
 
index e51fd4e3fa2ddfb89364fe9a6ffafa078205a57e..203de0b5f6071fd9ff5d1ff86113bd869a44f1b0 100644 (file)
 
 static struct cdev file_cdev;
 static struct visorchannel **file_controlvm_channel;
-static dev_t majordev = -1; /**< indicates major num for device */
-static BOOL registered = FALSE;
-
-static int visorchipset_open(struct inode *inode, struct file *file);
-static int visorchipset_release(struct inode *inode, struct file *file);
-static int visorchipset_mmap(struct file *file, struct vm_area_struct *vma);
-long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-
-static const struct file_operations visorchipset_fops = {
-       .owner = THIS_MODULE,
-       .open = visorchipset_open,
-       .read = NULL,
-       .write = NULL,
-       .unlocked_ioctl = visorchipset_ioctl,
-       .release = visorchipset_release,
-       .mmap = visorchipset_mmap,
-};
-
-int
-visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel)
-{
-       int rc = 0;
-
-       file_controlvm_channel = controlvm_channel;
-       majordev = major_dev;
-       cdev_init(&file_cdev, &visorchipset_fops);
-       file_cdev.owner = THIS_MODULE;
-       if (MAJOR(majordev) == 0) {
-               /* dynamic major device number registration required */
-               if (alloc_chrdev_region(&majordev, 0, 1, MYDRVNAME) < 0) {
-                       ERRDRV("Unable to allocate+register char device %s",
-                              MYDRVNAME);
-                       return -1;
-               }
-               registered = TRUE;
-               INFODRV("New major number %d registered\n", MAJOR(majordev));
-       } else {
-               /* static major device number registration required */
-               if (register_chrdev_region(majordev, 1, MYDRVNAME) < 0) {
-                       ERRDRV("Unable to register char device %s", MYDRVNAME);
-                       return -1;
-               }
-               registered = TRUE;
-               INFODRV("Static major number %d registered\n", MAJOR(majordev));
-       }
-       rc = cdev_add(&file_cdev, MKDEV(MAJOR(majordev), 0), 1);
-       if (rc  < 0) {
-               ERRDRV("failed to create char device: (status=%d)\n", rc);
-               return -1;
-       }
-       INFODRV("Registered char device for %s (major=%d)",
-               MYDRVNAME, MAJOR(majordev));
-       return 0;
-}
 
 void
-visorchipset_file_cleanup(void)
+visorchipset_file_cleanup(dev_t major_dev)
 {
        if (file_cdev.ops != NULL)
                cdev_del(&file_cdev);
        file_cdev.ops = NULL;
-       if (registered) {
-               if (MAJOR(majordev) >= 0) {
-                       unregister_chrdev_region(majordev, 1);
-                       majordev = MKDEV(0, 0);
-               }
-               registered = FALSE;
-       }
+       unregister_chrdev_region(major_dev, 1);
 }
 
 static int
@@ -105,7 +45,6 @@ visorchipset_open(struct inode *inode, struct file *file)
 {
        unsigned minor_number = iminor(inode);
 
-       DEBUGDRV("%s", __func__);
        if (minor_number != 0)
                return -ENODEV;
        file->private_data = NULL;
@@ -115,7 +54,6 @@ visorchipset_open(struct inode *inode, struct file *file)
 static int
 visorchipset_release(struct inode *inode, struct file *file)
 {
-       DEBUGDRV("%s", __func__);
        return 0;
 }
 
@@ -127,16 +65,13 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma)
        GUEST_PHYSICAL_ADDRESS addr = 0;
 
        /* sv_enable_dfp(); */
-       DEBUGDRV("%s", __func__);
-       if (offset & (PAGE_SIZE - 1)) {
-               ERRDRV("%s virtual address NOT page-aligned!", __func__);
+       if (offset & (PAGE_SIZE - 1))
                return -ENXIO;  /* need aligned offsets */
-       }
+
        switch (offset) {
        case VISORCHIPSET_MMAP_CONTROLCHANOFFSET:
                vma->vm_flags |= VM_IO;
                if (*file_controlvm_channel == NULL) {
-                       ERRDRV("%s no controlvm channel yet", __func__);
                        return -ENXIO;
                }
                visorchannel_read(*file_controlvm_channel,
@@ -144,33 +79,29 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma)
                                 gp_control_channel),
                        &addr, sizeof(addr));
                if (addr == 0) {
-                       ERRDRV("%s control channel address is 0", __func__);
                        return -ENXIO;
                }
                physaddr = (ulong)addr;
-               DEBUGDRV("mapping physical address = 0x%lx", physaddr);
                if (remap_pfn_range(vma, vma->vm_start,
                                    physaddr >> PAGE_SHIFT,
                                    vma->vm_end - vma->vm_start,
                                    /*pgprot_noncached */
                                    (vma->vm_page_prot))) {
-                       ERRDRV("%s remap_pfn_range failed", __func__);
                        return -EAGAIN;
                }
                break;
        default:
                return -ENOSYS;
        }
-       DEBUGDRV("%s success!", __func__);
        return 0;
 }
 
-long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long visorchipset_ioctl(struct file *file, unsigned int cmd,
+                               unsigned long arg)
 {
        s64 adjustment;
        s64 vrtc_offset;
 
-       DBGINF("entered visorchipset_ioctl, cmd=%d", cmd);
        switch (cmd) {
        case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET:
                /* get the physical rtc offset */
@@ -179,19 +110,51 @@ long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                    ((void __user *)arg, &vrtc_offset, sizeof(vrtc_offset))) {
                        return -EFAULT;
                }
-               DBGINF("insde visorchipset_ioctl, cmd=%d, vrtc_offset=%lld",
-                      cmd, vrtc_offset);
                return SUCCESS;
        case VMCALL_UPDATE_PHYSICAL_TIME:
                if (copy_from_user
                    (&adjustment, (void __user *)arg, sizeof(adjustment))) {
                        return -EFAULT;
                }
-               DBGINF("insde visorchipset_ioctl, cmd=%d, adjustment=%lld", cmd,
-                      adjustment);
                return issue_vmcall_update_physical_time(adjustment);
        default:
-               LOGERR("visorchipset_ioctl received invalid command");
                return -EFAULT;
        }
 }
+
+static const struct file_operations visorchipset_fops = {
+       .owner = THIS_MODULE,
+       .open = visorchipset_open,
+       .read = NULL,
+       .write = NULL,
+       .unlocked_ioctl = visorchipset_ioctl,
+       .release = visorchipset_release,
+       .mmap = visorchipset_mmap,
+};
+
+int
+visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel)
+{
+       int rc = 0;
+
+       file_controlvm_channel = controlvm_channel;
+       cdev_init(&file_cdev, &visorchipset_fops);
+       file_cdev.owner = THIS_MODULE;
+       if (MAJOR(major_dev) == 0) {
+               rc = alloc_chrdev_region(&major_dev, 0, 1, MYDRVNAME);
+               /* dynamic major device number registration required */
+               if (rc < 0)
+                       return rc;
+       } else {
+               /* static major device number registration required */
+               rc = register_chrdev_region(major_dev, 1, MYDRVNAME);
+               if (rc < 0)
+                       return rc;
+       }
+       rc = cdev_add(&file_cdev, MKDEV(MAJOR(major_dev), 0), 1);
+       if (rc < 0) {
+               unregister_chrdev_region(major_dev, 1);
+               return rc;
+       }
+       return 0;
+}
index dc7a19556b3f127af30079dba3bf66b08d76b602..51f7699b744bd3df40bf72dd0c8f0189d36e9a17 100644 (file)
@@ -22,6 +22,6 @@
 
 int visorchipset_file_init(dev_t majorDev,
                           struct visorchannel **pControlVm_channel);
-void visorchipset_file_cleanup(void);
+void visorchipset_file_cleanup(dev_t major_dev);
 
 #endif
index a1d35d4bef2e45ae7ae4270cc6b3bce54c4e4e41..f76e498a36b5f00a871acca8d7df38cc372075be 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef __VISORCHIPSET_GLOBALS_H__
 #define __VISORCHIPSET_GLOBALS_H__
 
-#include "uniklog.h"
 #include "diagnostics/appos_subsystems.h"
 #include "timskmod.h"
 #include "visorchipset.h"
index 9edbd3bbd186d056d3a0a64eda166df60bd25707..d8a2d6f5a75d7ac953f6747056c956172c6103d5 100644 (file)
@@ -29,9 +29,9 @@
  * incoming payloads.  This serves as a throttling mechanism.
  */
 #define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128)
-static ulong Controlvm_Payload_Bytes_Buffered;
+static ulong controlvm_payload_bytes_buffered;
 
-struct PARSER_CONTEXT_Tag {
+struct parser_context {
        ulong allocbytes;
        ulong param_bytes;
        u8 *curr;
@@ -40,41 +40,36 @@ struct PARSER_CONTEXT_Tag {
        char data[0];
 };
 
-static PARSER_CONTEXT *
-parser_init_guts(u64 addr, u32 bytes, BOOL isLocal,
-                BOOL hasStandardPayloadHeader, BOOL *tryAgain)
+static struct parser_context *
+parser_init_guts(u64 addr, u32 bytes, BOOL local,
+                BOOL standard_payload_header, BOOL *retry)
 {
-       int allocbytes = sizeof(PARSER_CONTEXT) + bytes;
-       PARSER_CONTEXT *rc = NULL;
-       PARSER_CONTEXT *ctx = NULL;
+       int allocbytes = sizeof(struct parser_context) + bytes;
+       struct parser_context *rc = NULL;
+       struct parser_context *ctx = NULL;
        struct memregion *rgn = NULL;
        struct spar_controlvm_parameters_header *phdr = NULL;
 
-       if (tryAgain)
-               *tryAgain = FALSE;
-       if (!hasStandardPayloadHeader)
+       if (retry)
+               *retry = FALSE;
+       if (!standard_payload_header)
                /* alloc and 0 extra byte to ensure payload is
                 * '\0'-terminated
                 */
                allocbytes++;
-       if ((Controlvm_Payload_Bytes_Buffered + bytes)
+       if ((controlvm_payload_bytes_buffered + bytes)
            > MAX_CONTROLVM_PAYLOAD_BYTES) {
-               ERRDRV("%s (%s:%d) - prevented allocation of %d bytes to prevent exceeding throttling max (%d)",
-                      __func__, __FILE__, __LINE__, allocbytes,
-                      MAX_CONTROLVM_PAYLOAD_BYTES);
-               if (tryAgain)
-                       *tryAgain = TRUE;
+               if (retry)
+                       *retry = TRUE;
                rc = NULL;
-               goto Away;
+               goto cleanup;
        }
        ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY);
-       if (ctx == NULL) {
-               ERRDRV("%s (%s:%d) - failed to allocate %d bytes",
-                      __func__, __FILE__, __LINE__, allocbytes);
-               if (tryAgain)
-                       *tryAgain = TRUE;
+       if (!ctx) {
+               if (retry)
+                       *retry = TRUE;
                rc = NULL;
-               goto Away;
+               goto cleanup;
        }
 
        ctx->allocbytes = allocbytes;
@@ -82,15 +77,12 @@ parser_init_guts(u64 addr, u32 bytes, BOOL isLocal,
        ctx->curr = NULL;
        ctx->bytes_remaining = 0;
        ctx->byte_stream = FALSE;
-       if (isLocal) {
+       if (local) {
                void *p;
 
                if (addr > virt_to_phys(high_memory - 1)) {
-                       ERRDRV("%s - bad local address (0x%-16.16Lx for %lu)",
-                              __func__,
-                              (unsigned long long) addr, (ulong) bytes);
                        rc = NULL;
-                       goto Away;
+                       goto cleanup;
                }
                p = __va((ulong) (addr));
                memcpy(ctx->data, p, bytes);
@@ -98,54 +90,42 @@ parser_init_guts(u64 addr, u32 bytes, BOOL isLocal,
                rgn = visor_memregion_create(addr, bytes);
                if (!rgn) {
                        rc = NULL;
-                       goto Away;
+                       goto cleanup;
                }
                if (visor_memregion_read(rgn, 0, ctx->data, bytes) < 0) {
                        rc = NULL;
-                       goto Away;
+                       goto cleanup;
                }
        }
-       if (!hasStandardPayloadHeader) {
+       if (!standard_payload_header) {
                ctx->byte_stream = TRUE;
                rc = ctx;
-               goto Away;
+               goto cleanup;
        }
        phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
        if (phdr->total_length != bytes) {
-               ERRDRV("%s - bad total length %lu (should be %lu)",
-                      __func__,
-                      (ulong) (phdr->total_length), (ulong) (bytes));
                rc = NULL;
-               goto Away;
+               goto cleanup;
        }
        if (phdr->total_length < phdr->header_length) {
-               ERRDRV("%s - total length < header length (%lu < %lu)",
-                      __func__,
-                      (ulong) (phdr->total_length),
-                      (ulong) (phdr->header_length));
                rc = NULL;
-               goto Away;
+               goto cleanup;
        }
        if (phdr->header_length <
            sizeof(struct spar_controlvm_parameters_header)) {
-               ERRDRV("%s - header is too small (%lu < %lu)",
-                      __func__,
-                      (ulong) (phdr->header_length),
-                      (ulong)(sizeof(
-                               struct spar_controlvm_parameters_header)));
                rc = NULL;
-               goto Away;
+               goto cleanup;
        }
 
        rc = ctx;
-Away:
+cleanup:
        if (rgn) {
                visor_memregion_destroy(rgn);
                rgn = NULL;
        }
-       if (rc)
-               Controlvm_Payload_Bytes_Buffered += ctx->param_bytes;
-       else {
+       if (rc) {
+               controlvm_payload_bytes_buffered += ctx->param_bytes;
+       else {
                if (ctx) {
                        parser_done(ctx);
                        ctx = NULL;
@@ -154,10 +134,10 @@ Away:
        return rc;
 }
 
-PARSER_CONTEXT *
-parser_init(u64 addr, u32 bytes, BOOL isLocal, BOOL *tryAgain)
+struct parser_context *
+parser_init(u64 addr, u32 bytes, BOOL local, BOOL *retry)
 {
-       return parser_init_guts(addr, bytes, isLocal, TRUE, tryAgain);
+       return parser_init_guts(addr, bytes, local, TRUE, retry);
 }
 
 /* Call this instead of parser_init() if the payload area consists of just
@@ -165,16 +145,16 @@ parser_init(u64 addr, u32 bytes, BOOL isLocal, BOOL *tryAgain)
  * structures.  Afterwards, you can call parser_simpleString_get() or
  * parser_byteStream_get() to obtain the data.
  */
-PARSER_CONTEXT *
-parser_init_byteStream(u64 addr, u32 bytes, BOOL isLocal, BOOL *tryAgain)
+struct parser_context *
+parser_init_byte_stream(u64 addr, u32 bytes, BOOL local, BOOL *retry)
 {
-       return parser_init_guts(addr, bytes, isLocal, FALSE, tryAgain);
+       return parser_init_guts(addr, bytes, local, FALSE, retry);
 }
 
 /* Obtain '\0'-terminated copy of string in payload area.
  */
 char *
-parser_simpleString_get(PARSER_CONTEXT *ctx)
+parser_simpleString_get(struct parser_context *ctx)
 {
        if (!ctx->byte_stream)
                return NULL;
@@ -185,40 +165,33 @@ parser_simpleString_get(PARSER_CONTEXT *ctx)
 
 /* Obtain a copy of the buffer in the payload area.
  */
-void *
-parser_byteStream_get(PARSER_CONTEXT *ctx, ulong *nbytes)
+void *parser_byte_stream_get(struct parser_context *ctx, ulong *nbytes)
 {
        if (!ctx->byte_stream)
                return NULL;
        if (nbytes)
                *nbytes = ctx->param_bytes;
-       return (void *) ctx->data;
+       return (void *)ctx->data;
 }
 
 uuid_le
-parser_id_get(PARSER_CONTEXT *ctx)
+parser_id_get(struct parser_context *ctx)
 {
        struct spar_controlvm_parameters_header *phdr = NULL;
 
-       if (ctx == NULL) {
-               ERRDRV("%s (%s:%d) - no context",
-                      __func__, __FILE__, __LINE__);
+       if (ctx == NULL)
                return NULL_UUID_LE;
-       }
        phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
        return phdr->id;
 }
 
 void
-parser_param_start(PARSER_CONTEXT *ctx, PARSER_WHICH_STRING which_string)
+parser_param_start(struct parser_context *ctx, PARSER_WHICH_STRING which_string)
 {
        struct spar_controlvm_parameters_header *phdr = NULL;
 
-       if (ctx == NULL) {
-               ERRDRV("%s (%s:%d) - no context",
-                      __func__, __FILE__, __LINE__);
+       if (ctx == NULL)
                goto Away;
-       }
        phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
        switch (which_string) {
        case PARSERSTRING_INITIATOR:
@@ -238,7 +211,6 @@ parser_param_start(PARSER_CONTEXT *ctx, PARSER_WHICH_STRING which_string)
                ctx->bytes_remaining = phdr->name_length;
                break;
        default:
-               ERRDRV("%s - bad which_string %d", __func__, which_string);
                break;
        }
 
@@ -247,11 +219,11 @@ Away:
 }
 
 void
-parser_done(PARSER_CONTEXT *ctx)
+parser_done(struct parser_context *ctx)
 {
        if (!ctx)
                return;
-       Controlvm_Payload_Bytes_Buffered -= ctx->param_bytes;
+       controlvm_payload_bytes_buffered -= ctx->param_bytes;
        kfree(ctx);
 }
 
@@ -290,7 +262,7 @@ string_length_no_trail(char *s, int len)
  *    parameter
  */
 void *
-parser_param_get(PARSER_CONTEXT *ctx, char *nam, int namesize)
+parser_param_get(struct parser_context *ctx, char *nam, int namesize)
 {
        u8 *pscan, *pnam = nam;
        ulong nscan;
@@ -321,25 +293,18 @@ parser_param_get(PARSER_CONTEXT *ctx, char *nam, int namesize)
        }
 
        while (*pscan != ':') {
-               if (namesize <= 0) {
-                       ERRDRV("%s - name too big", __func__);
+               if (namesize <= 0)
                        return NULL;
-               }
                *pnam = toupper(*pscan);
                pnam++;
                namesize--;
                pscan++;
                nscan--;
-               if (nscan == 0) {
-                       ERRDRV("%s - unexpected end of input parsing name",
-                              __func__);
+               if (nscan == 0)
                        return NULL;
-               }
        }
-       if (namesize <= 0) {
-               ERRDRV("%s - name too big", __func__);
+       if (namesize <= 0)
                return NULL;
-       }
        *pnam = '\0';
        nam[string_length_no_trail(nam, strlen(nam))] = '\0';
 
@@ -350,26 +315,17 @@ parser_param_get(PARSER_CONTEXT *ctx, char *nam, int namesize)
        while (isspace(*pscan)) {
                pscan++;
                nscan--;
-               if (nscan == 0) {
-                       ERRDRV("%s - unexpected end of input looking for value",
-                              __func__);
+               if (nscan == 0)
                        return NULL;
-               }
        }
-       if (nscan == 0) {
-               ERRDRV("%s - unexpected end of input looking for value",
-                      __func__);
+       if (nscan == 0)
                return NULL;
-       }
        if (*pscan == '\'' || *pscan == '"') {
                closing_quote = *pscan;
                pscan++;
                nscan--;
-               if (nscan == 0) {
-                       ERRDRV("%s - unexpected end of input after %c",
-                              __func__, closing_quote);
+               if (nscan == 0)
                        return NULL;
-               }
        }
 
        /* look for a separator character, terminator character, or
@@ -377,10 +333,8 @@ parser_param_get(PARSER_CONTEXT *ctx, char *nam, int namesize)
         */
        for (i = 0, value_length = -1; i < nscan; i++) {
                if (closing_quote) {
-                       if (pscan[i] == '\0') {
-                               ERRDRV("%s - unexpected end of input parsing quoted value", __func__);
+                       if (pscan[i] == '\0')
                                return NULL;
-                       }
                        if (pscan[i] == closing_quote) {
                                value_length = i;
                                break;
@@ -393,10 +347,8 @@ parser_param_get(PARSER_CONTEXT *ctx, char *nam, int namesize)
                }
        }
        if (value_length < 0) {
-               if (closing_quote) {
-                       ERRDRV("%s - unexpected end of input parsing quoted value", __func__);
+               if (closing_quote)
                        return NULL;
-               }
                value_length = nscan;
        }
        orig_value_length = value_length;
@@ -433,7 +385,6 @@ parser_param_get(PARSER_CONTEXT *ctx, char *nam, int namesize)
                                pscan++;
                                nscan--;
                        } else if (*pscan != '\0') {
-                               ERRDRV("%s - missing separator after quoted string", __func__);
                                kfree(value);
                                value = NULL;
                                return NULL;
@@ -446,7 +397,7 @@ parser_param_get(PARSER_CONTEXT *ctx, char *nam, int namesize)
 }
 
 void *
-parser_string_get(PARSER_CONTEXT *ctx)
+parser_string_get(struct parser_context *ctx)
 {
        u8 *pscan;
        ulong nscan;
index 9fbe3b5b7cc374690c1c1d52bd419da16bce38eb..2b903f1beff2e309d390cc1041780fa77a34a51c 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <linux/uuid.h>
 
-#include "uniklog.h"
 #include "timskmod.h"
 #include "channel.h"
 
@@ -31,17 +30,17 @@ typedef enum {
        PARSERSTRING_NAME,
 } PARSER_WHICH_STRING;
 
-typedef struct PARSER_CONTEXT_Tag PARSER_CONTEXT;
-
-PARSER_CONTEXT *parser_init(u64 addr, u32 bytes, BOOL isLocal, BOOL *tryAgain);
-PARSER_CONTEXT *parser_init_byteStream(u64 addr, u32 bytes, BOOL isLocal,
-                                      BOOL *tryAgain);
-void parser_param_start(PARSER_CONTEXT *ctx, PARSER_WHICH_STRING which_string);
-void *parser_param_get(PARSER_CONTEXT *ctx, char *nam, int namesize);
-void *parser_string_get(PARSER_CONTEXT *ctx);
-uuid_le parser_id_get(PARSER_CONTEXT *ctx);
-char *parser_simpleString_get(PARSER_CONTEXT *ctx);
-void *parser_byteStream_get(PARSER_CONTEXT *ctx, ulong *nbytes);
-void parser_done(PARSER_CONTEXT *ctx);
+struct parser_context *parser_init(u64 addr, u32 bytes, BOOL isLocal,
+                                  BOOL *tryAgain);
+struct parser_context *parser_init_byte_stream(u64 addr, u32 bytes, BOOL local,
+                                      BOOL *retry);
+void parser_param_start(struct parser_context *ctx,
+                       PARSER_WHICH_STRING which_string);
+void *parser_param_get(struct parser_context *ctx, char *nam, int namesize);
+void *parser_string_get(struct parser_context *ctx);
+uuid_le parser_id_get(struct parser_context *ctx);
+char *parser_simpleString_get(struct parser_context *ctx);
+void *parser_byte_stream_get(struct parser_context *ctx, ulong *nbytes);
+void parser_done(struct parser_context *ctx);
 
 #endif
index 98f3ba4c13acefb42ab78b94ed4430af1a464ead..bd46df9ef45a36095aa637d9ad911ec8b2cf247f 100644 (file)
@@ -133,7 +133,6 @@ struct visorchipset_bus_info {
        u8 *description;        /* UTF8 */
        u64 reserved1;
        u32 reserved2;
-       MYPROCOBJECT *proc_object;
        struct {
                u32 server:1;
                /* Add new fields above. */
index f606ee9e0de908fb1107ce6f66fbe07785f3f6c9..f2663d2c753003cdb62171e176baa61b2051cee3 100644 (file)
@@ -22,7 +22,6 @@
 #include "periodic_work.h"
 #include "file.h"
 #include "parser.h"
-#include "uniklog.h"
 #include "uisutils.h"
 #include "controlvmcompletionstatus.h"
 #include "guestlinuxdebug.h"
@@ -49,8 +48,8 @@
 * message, we switch back to fast polling mode.
 */
 #define MIN_IDLE_SECONDS 10
-static ulong Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
-static ulong Most_recent_message_jiffies;      /* when we got our last
+static ulong poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
+static ulong most_recent_message_jiffies;      /* when we got our last
                                                 * controlvm message */
 static inline char *
 NONULLSTR(char *s)
@@ -66,83 +65,74 @@ static int clientregistered;
 #define MAX_CHIPSET_EVENTS 2
 static u8 chipset_events[MAX_CHIPSET_EVENTS] = { 0, 0 };
 
-static struct delayed_work Periodic_controlvm_work;
-static struct workqueue_struct *Periodic_controlvm_workqueue;
-static DEFINE_SEMAPHORE(NotifierLock);
+static struct delayed_work periodic_controlvm_work;
+static struct workqueue_struct *periodic_controlvm_workqueue;
+static DEFINE_SEMAPHORE(notifier_lock);
 
-typedef struct {
-       struct controlvm_message message;
-       unsigned int crc;
-} MESSAGE_ENVELOPE;
-
-static struct controlvm_message_header g_DiagMsgHdr;
-static struct controlvm_message_header g_ChipSetMsgHdr;
-static struct controlvm_message_header g_DelDumpMsgHdr;
-static const uuid_le UltraDiagPoolChannelProtocolGuid =
+static struct controlvm_message_header g_diag_msg_hdr;
+static struct controlvm_message_header g_chipset_msg_hdr;
+static struct controlvm_message_header g_del_dump_msg_hdr;
+static const uuid_le spar_diag_pool_channel_protocol_uuid =
        SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID;
 /* 0xffffff is an invalid Bus/Device number */
-static ulong g_diagpoolBusNo = 0xffffff;
-static ulong g_diagpoolDevNo = 0xffffff;
-static struct controlvm_message_packet g_DeviceChangeStatePacket;
+static ulong g_diagpool_bus_no = 0xffffff;
+static ulong g_diagpool_dev_no = 0xffffff;
+static struct controlvm_message_packet g_devicechangestate_packet;
 
 /* Only VNIC and VHBA channels are sent to visorclientbus (aka
  * "visorhackbus")
  */
 #define FOR_VISORHACKBUS(channel_type_guid) \
        (((uuid_le_cmp(channel_type_guid,\
-                      spar_vnic_channel_protocol_uuid) == 0)\
-       || (uuid_le_cmp(channel_type_guid,\
+                      spar_vnic_channel_protocol_uuid) == 0) ||\
+       (uuid_le_cmp(channel_type_guid,\
                        spar_vhba_channel_protocol_uuid) == 0)))
 #define FOR_VISORBUS(channel_type_guid) (!(FOR_VISORHACKBUS(channel_type_guid)))
 
 #define is_diagpool_channel(channel_type_guid) \
-        (uuid_le_cmp(channel_type_guid, UltraDiagPoolChannelProtocolGuid) == 0)
+       (uuid_le_cmp(channel_type_guid,\
+                    spar_diag_pool_channel_protocol_uuid) == 0)
 
-static LIST_HEAD(BusInfoList);
-static LIST_HEAD(DevInfoList);
+static LIST_HEAD(bus_info_list);
+static LIST_HEAD(dev_info_list);
 
-static struct visorchannel *ControlVm_channel;
+static struct visorchannel *controlvm_channel;
 
-typedef struct {
+/* Manages the request payload in the controlvm channel */
+static struct controlvm_payload_info {
        u8 __iomem *ptr;        /* pointer to base address of payload pool */
        u64 offset;             /* offset from beginning of controlvm
                                 * channel to beginning of payload * pool */
        u32 bytes;              /* number of bytes in payload pool */
-} CONTROLVM_PAYLOAD_INFO;
-
-/* Manages the request payload in the controlvm channel */
-static CONTROLVM_PAYLOAD_INFO ControlVm_payload_info;
+} controlvm_payload_info;
 
-static struct channel_header *Test_Vnic_channel;
-
-typedef struct {
-       struct controlvm_message_header Dumpcapture_header;
-       struct controlvm_message_header Gettextdump_header;
-       struct controlvm_message_header Dumpcomplete_header;
-       BOOL Gettextdump_outstanding;
+/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE /
+ * CONTROLVM_DUMP_GETTEXTDUMP / CONTROLVM_DUMP_COMPLETE conversation.
+ */
+static struct livedump_info {
+       struct controlvm_message_header dumpcapture_header;
+       struct controlvm_message_header gettextdump_header;
+       struct controlvm_message_header dumpcomplete_header;
+       BOOL gettextdump_outstanding;
        u32 crc32;
        ulong length;
        atomic_t buffers_in_use;
        ulong destination;
-} LIVEDUMP_INFO;
-/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE /
- * CONTROLVM_DUMP_GETTEXTDUMP / CONTROLVM_DUMP_COMPLETE conversation.
- */
-static LIVEDUMP_INFO LiveDump_info;
+} livedump_info;
 
 /* The following globals are used to handle the scenario where we are unable to
  * offload the payload from a controlvm message due to memory requirements.  In
  * this scenario, we simply stash the controlvm message, then attempt to
  * process it again the next time controlvm_periodic_work() runs.
  */
-static struct controlvm_message ControlVm_Pending_Msg;
-static BOOL ControlVm_Pending_Msg_Valid = FALSE;
+static struct controlvm_message controlvm_pending_msg;
+static BOOL controlvm_pending_msg_valid = FALSE;
 
 /* Pool of struct putfile_buffer_entry, for keeping track of pending (incoming)
  * TRANSMIT_FILE PutFile payloads.
  */
-static struct kmem_cache *Putfile_buffer_list_pool;
-static const char Putfile_buffer_list_pool_name[] =
+static struct kmem_cache *putfile_buffer_list_pool;
+static const char putfile_buffer_list_pool_name[] =
        "controlvm_putfile_buffer_list_pool";
 
 /* This identifies a data buffer that has been received via a controlvm messages
@@ -150,14 +140,14 @@ static const char Putfile_buffer_list_pool_name[] =
  */
 struct putfile_buffer_entry {
        struct list_head next;  /* putfile_buffer_entry list */
-       PARSER_CONTEXT *parser_ctx; /* points to buffer containing input data */
+       struct parser_context *parser_ctx; /* points to input data buffer */
 };
 
 /* List of struct putfile_request *, via next_putfile_request member.
  * Each entry in this list identifies an outstanding TRANSMIT_FILE
  * conversation.
  */
-static LIST_HEAD(Putfile_request_list);
+static LIST_HEAD(putfile_request_list);
 
 /* This describes a buffer and its current state of transfer (e.g., how many
  * bytes have already been supplied as putfile data, and how many bytes are
@@ -165,7 +155,7 @@ static LIST_HEAD(Putfile_request_list);
  */
 struct putfile_active_buffer {
        /* a payload from a controlvm message, containing a file data buffer */
-       PARSER_CONTEXT *parser_ctx;
+       struct parser_context *parser_ctx;
        /* points within data area of parser_ctx to next byte of data */
        u8 *pnext;
        /* # bytes left from <pnext> to the end of this data buffer */
@@ -213,7 +203,7 @@ struct putfile_request {
        int completion_status;
 };
 
-static atomic_t Visorchipset_cache_buffers_in_use = ATOMIC_INIT(0);
+static atomic_t visorchipset_cache_buffers_in_use = ATOMIC_INIT(0);
 
 struct parahotplug_request {
        struct list_head list;
@@ -222,23 +212,23 @@ struct parahotplug_request {
        struct controlvm_message msg;
 };
 
-static LIST_HEAD(Parahotplug_request_list);
-static DEFINE_SPINLOCK(Parahotplug_request_list_lock); /* lock for above */
+static LIST_HEAD(parahotplug_request_list);
+static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */
 static void parahotplug_process_list(void);
 
 /* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE /
  * CONTROLVM_REPORTEVENT.
  */
-static struct visorchipset_busdev_notifiers BusDev_Server_Notifiers;
-static struct visorchipset_busdev_notifiers BusDev_Client_Notifiers;
+static struct visorchipset_busdev_notifiers busdev_server_notifiers;
+static struct visorchipset_busdev_notifiers busdev_client_notifiers;
 
-static void bus_create_response(ulong busNo, int response);
-static void bus_destroy_response(ulong busNo, int response);
-static void device_create_response(ulong busNo, ulong devNo, int response);
-static void device_destroy_response(ulong busNo, ulong devNo, int response);
-static void device_resume_response(ulong busNo, ulong devNo, int response);
+static void bus_create_response(ulong bus_no, int response);
+static void bus_destroy_response(ulong bus_no, int response);
+static void device_create_response(ulong bus_no, ulong dev_no, int response);
+static void device_destroy_response(ulong bus_no, ulong dev_no, int response);
+static void device_resume_response(ulong bus_no, ulong dev_no, int response);
 
-static struct visorchipset_busdev_responders BusDev_Responders = {
+static struct visorchipset_busdev_responders busdev_responders = {
        .bus_create = bus_create_response,
        .bus_destroy = bus_destroy_response,
        .device_create = device_create_response,
@@ -248,49 +238,55 @@ static struct visorchipset_busdev_responders BusDev_Responders = {
 };
 
 /* info for /dev/visorchipset */
-static dev_t MajorDev = -1; /**< indicates major num for device */
+static dev_t major_dev = -1; /**< indicates major num for device */
 
 /* prototypes for attributes */
 static ssize_t toolaction_show(struct device *dev,
-       struct device_attribute *attr, char *buf);
+                              struct device_attribute *attr, char *buf);
 static ssize_t toolaction_store(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count);
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
 static DEVICE_ATTR_RW(toolaction);
 
 static ssize_t boottotool_show(struct device *dev,
-       struct device_attribute *attr, char *buf);
+                              struct device_attribute *attr, char *buf);
 static ssize_t boottotool_store(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count);
+                               struct device_attribute *attr, const char *buf,
+                               size_t count);
 static DEVICE_ATTR_RW(boottotool);
 
 static ssize_t error_show(struct device *dev, struct device_attribute *attr,
-       char *buf);
+                         char *buf);
 static ssize_t error_store(struct device *dev, struct device_attribute *attr,
-       const char *buf, size_t count);
+                          const char *buf, size_t count);
 static DEVICE_ATTR_RW(error);
 
 static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
-       char *buf);
+                          char *buf);
 static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
-       const char *buf, size_t count);
+                           const char *buf, size_t count);
 static DEVICE_ATTR_RW(textid);
 
 static ssize_t remaining_steps_show(struct device *dev,
-       struct device_attribute *attr, char *buf);
+                                   struct device_attribute *attr, char *buf);
 static ssize_t remaining_steps_store(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count);
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count);
 static DEVICE_ATTR_RW(remaining_steps);
 
 static ssize_t chipsetready_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count);
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count);
 static DEVICE_ATTR_WO(chipsetready);
 
 static ssize_t devicedisabled_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count);
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count);
 static DEVICE_ATTR_WO(devicedisabled);
 
 static ssize_t deviceenabled_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count);
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count);
 static DEVICE_ATTR_WO(deviceenabled);
 
 static struct attribute *visorchipset_install_attrs[] = {
@@ -336,47 +332,48 @@ static const struct attribute_group *visorchipset_dev_groups[] = {
 };
 
 /* /sys/devices/platform/visorchipset */
-static struct platform_device Visorchipset_platform_device = {
+static struct platform_device visorchipset_platform_device = {
        .name = "visorchipset",
        .id = -1,
        .dev.groups = visorchipset_dev_groups,
 };
 
 /* Function prototypes */
-static void controlvm_respond(struct controlvm_message_header *msgHdr,
+static void controlvm_respond(struct controlvm_message_header *msg_hdr,
                              int response);
 static void controlvm_respond_chipset_init(
-               struct controlvm_message_header *msgHdr, int response,
+               struct controlvm_message_header *msg_hdr, int response,
                enum ultra_chipset_feature features);
 static void controlvm_respond_physdev_changestate(
-               struct controlvm_message_header *msgHdr, int response,
+               struct controlvm_message_header *msg_hdr, int response,
                struct spar_segment_state state);
 
 static ssize_t toolaction_show(struct device *dev,
                               struct device_attribute *attr,
                               char *buf)
 {
-       u8 toolAction;
+       u8 tool_action;
 
-       visorchannel_read(ControlVm_channel,
+       visorchannel_read(controlvm_channel,
                offsetof(struct spar_controlvm_channel_protocol,
-                          tool_action), &toolAction, sizeof(u8));
-       return scnprintf(buf, PAGE_SIZE, "%u\n", toolAction);
+                        tool_action), &tool_action, sizeof(u8));
+       return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action);
 }
 
 static ssize_t toolaction_store(struct device *dev,
                                struct device_attribute *attr,
                                const char *buf, size_t count)
 {
-       u8 toolAction;
+       u8 tool_action;
        int ret;
 
-       if (kstrtou8(buf, 10, &toolAction) != 0)
+       if (kstrtou8(buf, 10, &tool_action) != 0)
                return -EINVAL;
 
-       ret = visorchannel_write(ControlVm_channel,
-               offsetof(struct spar_controlvm_channel_protocol, tool_action),
-               &toolAction, sizeof(u8));
+       ret = visorchannel_write(controlvm_channel,
+               offsetof(struct spar_controlvm_channel_protocol,
+                        tool_action),
+               &tool_action, sizeof(u8));
 
        if (ret)
                return ret;
@@ -387,14 +384,14 @@ static ssize_t boottotool_show(struct device *dev,
                               struct device_attribute *attr,
                               char *buf)
 {
-       struct efi_spar_indication efiSparIndication;
+       struct efi_spar_indication efi_spar_indication;
 
-       visorchannel_read(ControlVm_channel,
-               offsetof(struct spar_controlvm_channel_protocol,
-                       efi_spar_ind), &efiSparIndication,
-               sizeof(struct efi_spar_indication));
+       visorchannel_read(controlvm_channel,
+                         offsetof(struct spar_controlvm_channel_protocol,
+                                  efi_spar_ind), &efi_spar_indication,
+                         sizeof(struct efi_spar_indication));
        return scnprintf(buf, PAGE_SIZE, "%u\n",
-                       efiSparIndication.boot_to_tool);
+                        efi_spar_indication.boot_to_tool);
 }
 
 static ssize_t boottotool_store(struct device *dev,
@@ -402,17 +399,16 @@ static ssize_t boottotool_store(struct device *dev,
                                const char *buf, size_t count)
 {
        int val, ret;
-       struct efi_spar_indication efiSparIndication;
+       struct efi_spar_indication efi_spar_indication;
 
        if (kstrtoint(buf, 10, &val) != 0)
                return -EINVAL;
 
-       efiSparIndication.boot_to_tool = val;
-       ret = visorchannel_write(ControlVm_channel,
+       efi_spar_indication.boot_to_tool = val;
+       ret = visorchannel_write(controlvm_channel,
                        offsetof(struct spar_controlvm_channel_protocol,
-                               efi_spar_ind),
-                       &(efiSparIndication),
-               sizeof(struct efi_spar_indication));
+                                efi_spar_ind), &(efi_spar_indication),
+                                sizeof(struct efi_spar_indication));
 
        if (ret)
                return ret;
@@ -420,18 +416,19 @@ static ssize_t boottotool_store(struct device *dev,
 }
 
 static ssize_t error_show(struct device *dev, struct device_attribute *attr,
-               char *buf)
+                         char *buf)
 {
        u32 error;
 
-       visorchannel_read(ControlVm_channel, offsetof(
-               struct spar_controlvm_channel_protocol, installation_error),
-               &error, sizeof(u32));
+       visorchannel_read(controlvm_channel,
+                         offsetof(struct spar_controlvm_channel_protocol,
+                                  installation_error),
+                         &error, sizeof(u32));
        return scnprintf(buf, PAGE_SIZE, "%i\n", error);
 }
 
 static ssize_t error_store(struct device *dev, struct device_attribute *attr,
-               const char *buf, size_t count)
+                          const char *buf, size_t count)
 {
        u32 error;
        int ret;
@@ -439,114 +436,81 @@ static ssize_t error_store(struct device *dev, struct device_attribute *attr,
        if (kstrtou32(buf, 10, &error) != 0)
                return -EINVAL;
 
-       ret = visorchannel_write(ControlVm_channel,
-                       offsetof(struct spar_controlvm_channel_protocol,
-                               installation_error),
-                       &error, sizeof(u32));
+       ret = visorchannel_write(controlvm_channel,
+               offsetof(struct spar_controlvm_channel_protocol,
+                        installation_error),
+               &error, sizeof(u32));
        if (ret)
                return ret;
        return count;
 }
 
 static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
-               char *buf)
+                          char *buf)
 {
-       u32 textId;
+       u32 text_id;
 
-       visorchannel_read(ControlVm_channel, offsetof(
-               struct spar_controlvm_channel_protocol, installation_text_id),
-               &textId, sizeof(u32));
-       return scnprintf(buf, PAGE_SIZE, "%i\n", textId);
+       visorchannel_read(controlvm_channel,
+                         offsetof(struct spar_controlvm_channel_protocol,
+                                  installation_text_id),
+                         &text_id, sizeof(u32));
+       return scnprintf(buf, PAGE_SIZE, "%i\n", text_id);
 }
 
 static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
-               const char *buf, size_t count)
+                           const char *buf, size_t count)
 {
-       u32 textId;
+       u32 text_id;
        int ret;
 
-       if (kstrtou32(buf, 10, &textId) != 0)
+       if (kstrtou32(buf, 10, &text_id) != 0)
                return -EINVAL;
 
-       ret = visorchannel_write(ControlVm_channel,
-                       offsetof(struct spar_controlvm_channel_protocol,
-                               installation_text_id),
-                       &textId, sizeof(u32));
+       ret = visorchannel_write(controlvm_channel,
+               offsetof(struct spar_controlvm_channel_protocol,
+                        installation_text_id),
+               &text_id, sizeof(u32));
        if (ret)
                return ret;
        return count;
 }
 
-
 static ssize_t remaining_steps_show(struct device *dev,
-       struct device_attribute *attr, char *buf)
+                                   struct device_attribute *attr, char *buf)
 {
-       u16 remainingSteps;
+       u16 remaining_steps;
 
-       visorchannel_read(ControlVm_channel,
-               offsetof(struct spar_controlvm_channel_protocol,
-                       installation_remaining_steps),
-               &remainingSteps,
-               sizeof(u16));
-       return scnprintf(buf, PAGE_SIZE, "%hu\n", remainingSteps);
+       visorchannel_read(controlvm_channel,
+                         offsetof(struct spar_controlvm_channel_protocol,
+                                  installation_remaining_steps),
+                         &remaining_steps, sizeof(u16));
+       return scnprintf(buf, PAGE_SIZE, "%hu\n", remaining_steps);
 }
 
 static ssize_t remaining_steps_store(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count)
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
 {
-       u16 remainingSteps;
+       u16 remaining_steps;
        int ret;
 
-       if (kstrtou16(buf, 10, &remainingSteps) != 0)
+       if (kstrtou16(buf, 10, &remaining_steps) != 0)
                return -EINVAL;
 
-       ret = visorchannel_write(ControlVm_channel,
-                       offsetof(struct spar_controlvm_channel_protocol,
-                               installation_remaining_steps),
-                       &remainingSteps, sizeof(u16));
+       ret = visorchannel_write(controlvm_channel,
+               offsetof(struct spar_controlvm_channel_protocol,
+                        installation_remaining_steps),
+               &remaining_steps, sizeof(u16));
        if (ret)
                return ret;
        return count;
 }
 
-#if 0
-static void
-testUnicode(void)
-{
-       wchar_t unicodeString[] = { 'a', 'b', 'c', 0 };
-       char s[sizeof(unicodeString) * NLS_MAX_CHARSET_SIZE];
-       wchar_t unicode2[99];
-
-       /* NOTE: Either due to a bug, or feature I don't understand, the
-        *       kernel utf8_mbstowcs() and utf_wcstombs() do NOT copy the
-        *       trailed NUL byte!!   REALLY!!!!!    Arrrrgggghhhhh
-        */
-
-       LOGINF("sizeof(wchar_t) = %d", sizeof(wchar_t));
-       LOGINF("utf8_wcstombs=%d",
-              chrs = utf8_wcstombs(s, unicodeString, sizeof(s)));
-       if (chrs >= 0)
-               s[chrs] = '\0'; /* GRRRRRRRR */
-       LOGINF("s='%s'", s);
-       LOGINF("utf8_mbstowcs=%d", chrs = utf8_mbstowcs(unicode2, s, 100));
-       if (chrs >= 0)
-               unicode2[chrs] = 0;     /* GRRRRRRRR */
-       if (memcmp(unicodeString, unicode2, sizeof(unicodeString)) == 0)
-               LOGINF("strings match... good");
-       else
-               LOGINF("strings did not match!!");
-}
-#endif
-
 static void
-busInfo_clear(void *v)
+bus_info_clear(void *v)
 {
        struct visorchipset_bus_info *p = (struct visorchipset_bus_info *) (v);
 
-       if (p->proc_object) {
-               visor_proc_DestroyObject(p->proc_object);
-               p->proc_object = NULL;
-       }
        kfree(p->name);
        p->name = NULL;
 
@@ -558,7 +522,7 @@ busInfo_clear(void *v)
 }
 
 static void
-devInfo_clear(void *v)
+dev_info_clear(void *v)
 {
        struct visorchipset_device_info *p =
                        (struct visorchipset_device_info *)(v);
@@ -593,22 +557,22 @@ visorchipset_register_busdev_server(
                        struct visorchipset_busdev_responders *responders,
                        struct ultra_vbus_deviceinfo *driver_info)
 {
-       down(&NotifierLock);
-       if (notifiers == NULL) {
-               memset(&BusDev_Server_Notifiers, 0,
-                      sizeof(BusDev_Server_Notifiers));
+       down(&notifier_lock);
+       if (!notifiers) {
+               memset(&busdev_server_notifiers, 0,
+                      sizeof(busdev_server_notifiers));
                serverregistered = 0;   /* clear flag */
        } else {
-               BusDev_Server_Notifiers = *notifiers;
+               busdev_server_notifiers = *notifiers;
                serverregistered = 1;   /* set flag */
        }
        if (responders)
-               *responders = BusDev_Responders;
+               *responders = busdev_responders;
        if (driver_info)
                bus_device_info_init(driver_info, "chipset", "visorchipset",
-                                  VERSION, NULL);
+                                    VERSION, NULL);
 
-       up(&NotifierLock);
+       up(&notifier_lock);
 }
 EXPORT_SYMBOL_GPL(visorchipset_register_busdev_server);
 
@@ -618,21 +582,21 @@ visorchipset_register_busdev_client(
                        struct visorchipset_busdev_responders *responders,
                        struct ultra_vbus_deviceinfo *driver_info)
 {
-       down(&NotifierLock);
-       if (notifiers == NULL) {
-               memset(&BusDev_Client_Notifiers, 0,
-                      sizeof(BusDev_Client_Notifiers));
+       down(&notifier_lock);
+       if (!notifiers) {
+               memset(&busdev_client_notifiers, 0,
+                      sizeof(busdev_client_notifiers));
                clientregistered = 0;   /* clear flag */
        } else {
-               BusDev_Client_Notifiers = *notifiers;
+               busdev_client_notifiers = *notifiers;
                clientregistered = 1;   /* set flag */
        }
        if (responders)
-               *responders = BusDev_Responders;
+               *responders = busdev_responders;
        if (driver_info)
                bus_device_info_init(driver_info, "chipset(bolts)",
                                     "visorchipset", VERSION, NULL);
-       up(&NotifierLock);
+       up(&notifier_lock);
 }
 EXPORT_SYMBOL_GPL(visorchipset_register_busdev_client);
 
@@ -642,14 +606,14 @@ cleanup_controlvm_structures(void)
        struct visorchipset_bus_info *bi, *tmp_bi;
        struct visorchipset_device_info *di, *tmp_di;
 
-       list_for_each_entry_safe(bi, tmp_bi, &BusInfoList, entry) {
-               busInfo_clear(bi);
+       list_for_each_entry_safe(bi, tmp_bi, &bus_info_list, entry) {
+               bus_info_clear(bi);
                list_del(&bi->entry);
                kfree(bi);
        }
 
-       list_for_each_entry_safe(di, tmp_di, &DevInfoList, entry) {
-               devInfo_clear(di);
+       list_for_each_entry_safe(di, tmp_di, &dev_info_list, entry) {
+               dev_info_clear(di);
                list_del(&di->entry);
                kfree(di);
        }
@@ -664,9 +628,8 @@ chipset_init(struct controlvm_message *inmsg)
 
        POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
        if (chipset_inited) {
-               LOGERR("CONTROLVM_CHIPSET_INIT Failed: Already Done.");
                rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
-               goto Away;
+               goto cleanup;
        }
        chipset_inited = 1;
        POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO);
@@ -681,7 +644,7 @@ chipset_init(struct controlvm_message *inmsg)
         * features-aware driver. */
        features |= ULTRA_CHIPSET_FEATURE_REPLY;
 
-Away:
+cleanup:
        if (rc < 0)
                cleanup_controlvm_structures();
        if (inmsg->hdr.flags.response_expected)
@@ -690,10 +653,10 @@ Away:
 
 static void
 controlvm_init_response(struct controlvm_message *msg,
-                       struct controlvm_message_header *msgHdr, int response)
+                       struct controlvm_message_header *msg_hdr, int response)
 {
        memset(msg, 0, sizeof(struct controlvm_message));
-       memcpy(&msg->hdr, msgHdr, sizeof(struct controlvm_message_header));
+       memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header));
        msg->hdr.payload_bytes = 0;
        msg->hdr.payload_vm_offset = 0;
        msg->hdr.payload_max_bytes = 0;
@@ -704,59 +667,54 @@ controlvm_init_response(struct controlvm_message *msg,
 }
 
 static void
-controlvm_respond(struct controlvm_message_header *msgHdr, int response)
+controlvm_respond(struct controlvm_message_header *msg_hdr, int response)
 {
        struct controlvm_message outmsg;
 
-       controlvm_init_response(&outmsg, msgHdr, response);
+       controlvm_init_response(&outmsg, msg_hdr, response);
        /* For DiagPool channel DEVICE_CHANGESTATE, we need to send
        * back the deviceChangeState structure in the packet. */
-       if (msgHdr->id == CONTROLVM_DEVICE_CHANGESTATE
-           && g_DeviceChangeStatePacket.device_change_state.bus_no ==
-           g_diagpoolBusNo
-           && g_DeviceChangeStatePacket.device_change_state.dev_no ==
-           g_diagpoolDevNo)
-               outmsg.cmd = g_DeviceChangeStatePacket;
-       if (outmsg.hdr.flags.test_message == 1) {
-               LOGINF("%s controlvm_msg=0x%x response=%d for test message",
-                      __func__, outmsg.hdr.id, response);
+       if (msg_hdr->id == CONTROLVM_DEVICE_CHANGESTATE &&
+           g_devicechangestate_packet.device_change_state.bus_no ==
+           g_diagpool_bus_no &&
+           g_devicechangestate_packet.device_change_state.dev_no ==
+           g_diagpool_dev_no)
+               outmsg.cmd = g_devicechangestate_packet;
+       if (outmsg.hdr.flags.test_message == 1)
                return;
-       }
-       if (!visorchannel_signalinsert(ControlVm_channel,
+
+       if (!visorchannel_signalinsert(controlvm_channel,
                                       CONTROLVM_QUEUE_REQUEST, &outmsg)) {
-               LOGERR("signalinsert failed!");
                return;
        }
 }
 
 static void
-controlvm_respond_chipset_init(struct controlvm_message_header *msgHdr,
+controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr,
                               int response,
                               enum ultra_chipset_feature features)
 {
        struct controlvm_message outmsg;
 
-       controlvm_init_response(&outmsg, msgHdr, response);
+       controlvm_init_response(&outmsg, msg_hdr, response);
        outmsg.cmd.init_chipset.features = features;
-       if (!visorchannel_signalinsert(ControlVm_channel,
+       if (!visorchannel_signalinsert(controlvm_channel,
                                       CONTROLVM_QUEUE_REQUEST, &outmsg)) {
-               LOGERR("signalinsert failed!");
                return;
        }
 }
 
 static void controlvm_respond_physdev_changestate(
-               struct controlvm_message_header *msgHdr, int response,
+               struct controlvm_message_header *msg_hdr, int response,
                struct spar_segment_state state)
 {
        struct controlvm_message outmsg;
 
-       controlvm_init_response(&outmsg, msgHdr, response);
+       controlvm_init_response(&outmsg, msg_hdr, response);
        outmsg.cmd.device_change_state.state = state;
        outmsg.cmd.device_change_state.flags.phys_device = 1;
-       if (!visorchannel_signalinsert(ControlVm_channel,
+       if (!visorchannel_signalinsert(controlvm_channel,
                                       CONTROLVM_QUEUE_REQUEST, &outmsg)) {
-               LOGERR("signalinsert failed!");
                return;
        }
 }
@@ -765,56 +723,50 @@ void
 visorchipset_save_message(struct controlvm_message *msg,
                          enum crash_obj_type type)
 {
-       u32 localSavedCrashMsgOffset;
-       u16 localSavedCrashMsgCount;
+       u32 crash_msg_offset;
+       u16 crash_msg_count;
 
        /* get saved message count */
-       if (visorchannel_read(ControlVm_channel,
+       if (visorchannel_read(controlvm_channel,
                              offsetof(struct spar_controlvm_channel_protocol,
                                       saved_crash_message_count),
-                             &localSavedCrashMsgCount, sizeof(u16)) < 0) {
-               LOGERR("failed to get Saved Message Count");
+                             &crash_msg_count, sizeof(u16)) < 0) {
                POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
                                 POSTCODE_SEVERITY_ERR);
                return;
        }
 
-       if (localSavedCrashMsgCount != CONTROLVM_CRASHMSG_MAX) {
-               LOGERR("Saved Message Count incorrect %d",
-                      localSavedCrashMsgCount);
+       if (crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
                POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
-                                localSavedCrashMsgCount,
+                                crash_msg_count,
                                 POSTCODE_SEVERITY_ERR);
                return;
        }
 
        /* get saved crash message offset */
-       if (visorchannel_read(ControlVm_channel,
+       if (visorchannel_read(controlvm_channel,
                              offsetof(struct spar_controlvm_channel_protocol,
                                       saved_crash_message_offset),
-                             &localSavedCrashMsgOffset, sizeof(u32)) < 0) {
-               LOGERR("failed to get Saved Message Offset");
+                             &crash_msg_offset, sizeof(u32)) < 0) {
                POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
                                 POSTCODE_SEVERITY_ERR);
                return;
        }
 
        if (type == CRASH_BUS) {
-               if (visorchannel_write(ControlVm_channel,
-                                      localSavedCrashMsgOffset,
+               if (visorchannel_write(controlvm_channel,
+                                      crash_msg_offset,
                                       msg,
                                       sizeof(struct controlvm_message)) < 0) {
-                       LOGERR("SAVE_MSG_BUS_FAILURE: Failed to write CrashCreateBusMsg!");
                        POSTCODE_LINUX_2(SAVE_MSG_BUS_FAILURE_PC,
                                         POSTCODE_SEVERITY_ERR);
                        return;
                }
        } else {
-               if (visorchannel_write(ControlVm_channel,
-                                      localSavedCrashMsgOffset +
+               if (visorchannel_write(controlvm_channel,
+                                      crash_msg_offset +
                                       sizeof(struct controlvm_message), msg,
                                       sizeof(struct controlvm_message)) < 0) {
-                       LOGERR("SAVE_MSG_DEV_FAILURE: Failed to write CrashCreateDevMsg!");
                        POSTCODE_LINUX_2(SAVE_MSG_DEV_FAILURE_PC,
                                         POSTCODE_SEVERITY_ERR);
                        return;
@@ -824,134 +776,118 @@ visorchipset_save_message(struct controlvm_message *msg,
 EXPORT_SYMBOL_GPL(visorchipset_save_message);
 
 static void
-bus_responder(enum controlvm_id cmdId, ulong busNo, int response)
+bus_responder(enum controlvm_id cmd_id, ulong bus_no, int response)
 {
        struct visorchipset_bus_info *p = NULL;
        BOOL need_clear = FALSE;
 
-       p = findbus(&BusInfoList, busNo);
-       if (!p) {
-               LOGERR("internal error busNo=%lu", busNo);
+       p = findbus(&bus_info_list, bus_no);
+       if (!p)
                return;
-       }
+
        if (response < 0) {
-               if ((cmdId == CONTROLVM_BUS_CREATE) &&
+               if ((cmd_id == CONTROLVM_BUS_CREATE) &&
                    (response != (-CONTROLVM_RESP_ERROR_ALREADY_DONE)))
                        /* undo the row we just created... */
-                       delbusdevices(&DevInfoList, busNo);
+                       delbusdevices(&dev_info_list, bus_no);
        } else {
-               if (cmdId == CONTROLVM_BUS_CREATE)
+               if (cmd_id == CONTROLVM_BUS_CREATE)
                        p->state.created = 1;
-               if (cmdId == CONTROLVM_BUS_DESTROY)
+               if (cmd_id == CONTROLVM_BUS_DESTROY)
                        need_clear = TRUE;
        }
 
-       if (p->pending_msg_hdr.id == CONTROLVM_INVALID) {
-               LOGERR("bus_responder no pending msg");
+       if (p->pending_msg_hdr.id == CONTROLVM_INVALID)
                return;         /* no controlvm response needed */
-       }
-       if (p->pending_msg_hdr.id != (u32) cmdId) {
-               LOGERR("expected=%d, found=%d", cmdId, p->pending_msg_hdr.id);
+       if (p->pending_msg_hdr.id != (u32)cmd_id)
                return;
-       }
        controlvm_respond(&p->pending_msg_hdr, response);
        p->pending_msg_hdr.id = CONTROLVM_INVALID;
        if (need_clear) {
-               busInfo_clear(p);
-               delbusdevices(&DevInfoList, busNo);
+               bus_info_clear(p);
+               delbusdevices(&dev_info_list, bus_no);
        }
 }
 
 static void
-device_changestate_responder(enum controlvm_id cmdId,
-                            ulong busNo, ulong devNo, int response,
-                            struct spar_segment_state responseState)
+device_changestate_responder(enum controlvm_id cmd_id,
+                            ulong bus_no, ulong dev_no, int response,
+                            struct spar_segment_state response_state)
 {
        struct visorchipset_device_info *p = NULL;
        struct controlvm_message outmsg;
 
-       p = finddevice(&DevInfoList, busNo, devNo);
-       if (!p) {
-               LOGERR("internal error; busNo=%lu, devNo=%lu", busNo, devNo);
+       p = finddevice(&dev_info_list, bus_no, dev_no);
+       if (!p)
                return;
-       }
-       if (p->pending_msg_hdr.id == CONTROLVM_INVALID) {
-               LOGERR("device_responder no pending msg");
+       if (p->pending_msg_hdr.id == CONTROLVM_INVALID)
                return;         /* no controlvm response needed */
-       }
-       if (p->pending_msg_hdr.id != cmdId) {
-               LOGERR("expected=%d, found=%d", cmdId, p->pending_msg_hdr.id);
+       if (p->pending_msg_hdr.id != cmd_id)
                return;
-       }
 
        controlvm_init_response(&outmsg, &p->pending_msg_hdr, response);
 
-       outmsg.cmd.device_change_state.bus_no = busNo;
-       outmsg.cmd.device_change_state.dev_no = devNo;
-       outmsg.cmd.device_change_state.state = responseState;
+       outmsg.cmd.device_change_state.bus_no = bus_no;
+       outmsg.cmd.device_change_state.dev_no = dev_no;
+       outmsg.cmd.device_change_state.state = response_state;
 
-       if (!visorchannel_signalinsert(ControlVm_channel,
-                                      CONTROLVM_QUEUE_REQUEST, &outmsg)) {
-               LOGERR("signalinsert failed!");
+       if (!visorchannel_signalinsert(controlvm_channel,
+                                      CONTROLVM_QUEUE_REQUEST, &outmsg))
                return;
-       }
 
        p->pending_msg_hdr.id = CONTROLVM_INVALID;
 }
 
 static void
-device_responder(enum controlvm_id cmdId, ulong busNo, ulong devNo,
+device_responder(enum controlvm_id cmd_id, ulong bus_no, ulong dev_no,
                 int response)
 {
        struct visorchipset_device_info *p = NULL;
        BOOL need_clear = FALSE;
 
-       p = finddevice(&DevInfoList, busNo, devNo);
-       if (!p) {
-               LOGERR("internal error; busNo=%lu, devNo=%lu", busNo, devNo);
+       p = finddevice(&dev_info_list, bus_no, dev_no);
+       if (!p)
                return;
-       }
        if (response >= 0) {
-               if (cmdId == CONTROLVM_DEVICE_CREATE)
+               if (cmd_id == CONTROLVM_DEVICE_CREATE)
                        p->state.created = 1;
-               if (cmdId == CONTROLVM_DEVICE_DESTROY)
+               if (cmd_id == CONTROLVM_DEVICE_DESTROY)
                        need_clear = TRUE;
        }
 
-       if (p->pending_msg_hdr.id == CONTROLVM_INVALID) {
-               LOGERR("device_responder no pending msg");
+       if (p->pending_msg_hdr.id == CONTROLVM_INVALID)
                return;         /* no controlvm response needed */
-       }
-       if (p->pending_msg_hdr.id != (u32) cmdId) {
-               LOGERR("expected=%d, found=%d", cmdId, p->pending_msg_hdr.id);
+
+       if (p->pending_msg_hdr.id != (u32)cmd_id)
                return;
-       }
+
        controlvm_respond(&p->pending_msg_hdr, response);
        p->pending_msg_hdr.id = CONTROLVM_INVALID;
        if (need_clear)
-               devInfo_clear(p);
+               dev_info_clear(p);
 }
 
 static void
-bus_epilog(u32 busNo,
-          u32 cmd, struct controlvm_message_header *msgHdr,
-          int response, BOOL needResponse)
+bus_epilog(u32 bus_no,
+          u32 cmd, struct controlvm_message_header *msg_hdr,
+          int response, BOOL need_response)
 {
        BOOL notified = FALSE;
 
-       struct visorchipset_bus_info *pBusInfo = findbus(&BusInfoList, busNo);
+       struct visorchipset_bus_info *bus_info = findbus(&bus_info_list,
+                                                        bus_no);
 
-       if (!pBusInfo) {
-               LOGERR("HUH? bad busNo=%d", busNo);
+       if (!bus_info)
                return;
-       }
-       if (needResponse) {
-               memcpy(&pBusInfo->pending_msg_hdr, msgHdr,
+
+       if (need_response) {
+               memcpy(&bus_info->pending_msg_hdr, msg_hdr,
                       sizeof(struct controlvm_message_header));
-       } else
-               pBusInfo->pending_msg_hdr.id = CONTROLVM_INVALID;
+       } else {
+               bus_info->pending_msg_hdr.id = CONTROLVM_INVALID;
+       }
 
-       down(&NotifierLock);
+       down(&notifier_lock);
        if (response == CONTROLVM_RESP_SUCCESS) {
                switch (cmd) {
                case CONTROLVM_BUS_CREATE:
@@ -965,24 +901,24 @@ bus_epilog(u32 busNo,
                        * either server or client devices
                        * - BusDev_Client can handle ONLY client
                        * devices */
-                       if (BusDev_Server_Notifiers.bus_create) {
-                               (*BusDev_Server_Notifiers.bus_create) (busNo);
+                       if (busdev_server_notifiers.bus_create) {
+                               (*busdev_server_notifiers.bus_create) (bus_no);
                                notified = TRUE;
                        }
-                       if ((!pBusInfo->flags.server) /*client */ &&
-                           BusDev_Client_Notifiers.bus_create) {
-                               (*BusDev_Client_Notifiers.bus_create) (busNo);
+                       if ((!bus_info->flags.server) /*client */ &&
+                           busdev_client_notifiers.bus_create) {
+                               (*busdev_client_notifiers.bus_create) (bus_no);
                                notified = TRUE;
                        }
                        break;
                case CONTROLVM_BUS_DESTROY:
-                       if (BusDev_Server_Notifiers.bus_destroy) {
-                               (*BusDev_Server_Notifiers.bus_destroy) (busNo);
+                       if (busdev_server_notifiers.bus_destroy) {
+                               (*busdev_server_notifiers.bus_destroy) (bus_no);
                                notified = TRUE;
                        }
-                       if ((!pBusInfo->flags.server) /*client */ &&
-                           BusDev_Client_Notifiers.bus_destroy) {
-                               (*BusDev_Client_Notifiers.bus_destroy) (busNo);
+                       if ((!bus_info->flags.server) /*client */ &&
+                           busdev_client_notifiers.bus_destroy) {
+                               (*busdev_client_notifiers.bus_destroy) (bus_no);
                                notified = TRUE;
                        }
                        break;
@@ -995,45 +931,45 @@ bus_epilog(u32 busNo,
                 */
                ;
        else
-               bus_responder(cmd, busNo, response);
-       up(&NotifierLock);
+               bus_responder(cmd, bus_no, response);
+       up(&notifier_lock);
 }
 
 static void
-device_epilog(u32 busNo, u32 devNo, struct spar_segment_state state, u32 cmd,
-             struct controlvm_message_header *msgHdr, int response,
-             BOOL needResponse, BOOL for_visorbus)
+device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd,
+             struct controlvm_message_header *msg_hdr, int response,
+             BOOL need_response, BOOL for_visorbus)
 {
        struct visorchipset_busdev_notifiers *notifiers = NULL;
        BOOL notified = FALSE;
 
-       struct visorchipset_device_info *pDevInfo =
-               finddevice(&DevInfoList, busNo, devNo);
+       struct visorchipset_device_info *dev_info =
+               finddevice(&dev_info_list, bus_no, dev_no);
        char *envp[] = {
                "SPARSP_DIAGPOOL_PAUSED_STATE = 1",
                NULL
        };
 
-       if (!pDevInfo) {
-               LOGERR("HUH? bad busNo=%d, devNo=%d", busNo, devNo);
+       if (!dev_info)
                return;
-       }
+
        if (for_visorbus)
-               notifiers = &BusDev_Server_Notifiers;
+               notifiers = &busdev_server_notifiers;
        else
-               notifiers = &BusDev_Client_Notifiers;
-       if (needResponse) {
-               memcpy(&pDevInfo->pending_msg_hdr, msgHdr,
+               notifiers = &busdev_client_notifiers;
+       if (need_response) {
+               memcpy(&dev_info->pending_msg_hdr, msg_hdr,
                       sizeof(struct controlvm_message_header));
-       } else
-               pDevInfo->pending_msg_hdr.id = CONTROLVM_INVALID;
+       } else {
+               dev_info->pending_msg_hdr.id = CONTROLVM_INVALID;
+       }
 
-       down(&NotifierLock);
+       down(&notifier_lock);
        if (response >= 0) {
                switch (cmd) {
                case CONTROLVM_DEVICE_CREATE:
                        if (notifiers->device_create) {
-                               (*notifiers->device_create) (busNo, devNo);
+                               (*notifiers->device_create) (bus_no, dev_no);
                                notified = TRUE;
                        }
                        break;
@@ -1043,8 +979,8 @@ device_epilog(u32 busNo, u32 devNo, struct spar_segment_state state, u32 cmd,
                            state.operating ==
                                segment_state_running.operating) {
                                if (notifiers->device_resume) {
-                                       (*notifiers->device_resume) (busNo,
-                                                                    devNo);
+                                       (*notifiers->device_resume) (bus_no,
+                                                                    dev_no);
                                        notified = TRUE;
                                }
                        }
@@ -1056,8 +992,8 @@ device_epilog(u32 busNo, u32 devNo, struct spar_segment_state state, u32 cmd,
                                 * where server is lost
                                 */
                                if (notifiers->device_pause) {
-                                       (*notifiers->device_pause) (busNo,
-                                                                   devNo);
+                                       (*notifiers->device_pause) (bus_no,
+                                                                   dev_no);
                                        notified = TRUE;
                                }
                        } else if (state.alive == segment_state_paused.alive &&
@@ -1066,22 +1002,20 @@ device_epilog(u32 busNo, u32 devNo, struct spar_segment_state state, u32 cmd,
                                /* this is lite pause where channel is
                                 * still valid just 'pause' of it
                                 */
-                               if (busNo == g_diagpoolBusNo
-                                   && devNo == g_diagpoolDevNo) {
-                                       LOGINF("DEVICE_CHANGESTATE(DiagpoolChannel busNo=%d devNo=%d is pausing...)",
-                                            busNo, devNo);
+                               if (bus_no == g_diagpool_bus_no &&
+                                   dev_no == g_diagpool_dev_no) {
                                        /* this will trigger the
                                         * diag_shutdown.sh script in
                                         * the visorchipset hotplug */
                                        kobject_uevent_env
-                                           (&Visorchipset_platform_device.dev.
+                                           (&visorchipset_platform_device.dev.
                                             kobj, KOBJ_ONLINE, envp);
                                }
                        }
                        break;
                case CONTROLVM_DEVICE_DESTROY:
                        if (notifiers->device_destroy) {
-                               (*notifiers->device_destroy) (busNo, devNo);
+                               (*notifiers->device_destroy) (bus_no, dev_no);
                                notified = TRUE;
                        }
                        break;
@@ -1094,62 +1028,57 @@ device_epilog(u32 busNo, u32 devNo, struct spar_segment_state state, u32 cmd,
                 */
                ;
        else
-               device_responder(cmd, busNo, devNo, response);
-       up(&NotifierLock);
+               device_responder(cmd, bus_no, dev_no, response);
+       up(&notifier_lock);
 }
 
 static void
 bus_create(struct controlvm_message *inmsg)
 {
        struct controlvm_message_packet *cmd = &inmsg->cmd;
-       ulong busNo = cmd->create_bus.bus_no;
+       ulong bus_no = cmd->create_bus.bus_no;
        int rc = CONTROLVM_RESP_SUCCESS;
-       struct visorchipset_bus_info *pBusInfo = NULL;
-
+       struct visorchipset_bus_info *bus_info = NULL;
 
-       pBusInfo = findbus(&BusInfoList, busNo);
-       if (pBusInfo && (pBusInfo->state.created == 1)) {
-               LOGERR("CONTROLVM_BUS_CREATE Failed: bus %lu already exists",
-                      busNo);
-               POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
+       bus_info = findbus(&bus_info_list, bus_no);
+       if (bus_info && (bus_info->state.created == 1)) {
+               POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
-               goto Away;
+               goto cleanup;
        }
-       pBusInfo = kzalloc(sizeof(struct visorchipset_bus_info), GFP_KERNEL);
-       if (pBusInfo == NULL) {
-               LOGERR("CONTROLVM_BUS_CREATE Failed: bus %lu kzalloc failed",
-                      busNo);
-               POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
+       bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL);
+       if (!bus_info) {
+               POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
-               goto Away;
+               goto cleanup;
        }
 
-       INIT_LIST_HEAD(&pBusInfo->entry);
-       pBusInfo->bus_no = busNo;
-       pBusInfo->dev_no = cmd->create_bus.dev_count;
+       INIT_LIST_HEAD(&bus_info->entry);
+       bus_info->bus_no = bus_no;
+       bus_info->dev_no = cmd->create_bus.dev_count;
 
-       POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, busNo, POSTCODE_SEVERITY_INFO);
+       POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO);
 
        if (inmsg->hdr.flags.test_message == 1)
-               pBusInfo->chan_info.addr_type = ADDRTYPE_LOCALTEST;
+               bus_info->chan_info.addr_type = ADDRTYPE_LOCALTEST;
        else
-               pBusInfo->chan_info.addr_type = ADDRTYPE_LOCALPHYSICAL;
+               bus_info->chan_info.addr_type = ADDRTYPE_LOCALPHYSICAL;
 
-       pBusInfo->flags.server = inmsg->hdr.flags.server;
-       pBusInfo->chan_info.channel_addr = cmd->create_bus.channel_addr;
-       pBusInfo->chan_info.n_channel_bytes = cmd->create_bus.channel_bytes;
-       pBusInfo->chan_info.channel_type_uuid =
+       bus_info->flags.server = inmsg->hdr.flags.server;
+       bus_info->chan_info.channel_addr = cmd->create_bus.channel_addr;
+       bus_info->chan_info.n_channel_bytes = cmd->create_bus.channel_bytes;
+       bus_info->chan_info.channel_type_uuid =
                        cmd->create_bus.bus_data_type_uuid;
-       pBusInfo->chan_info.channel_inst_uuid = cmd->create_bus.bus_inst_uuid;
+       bus_info->chan_info.channel_inst_uuid = cmd->create_bus.bus_inst_uuid;
 
-       list_add(&pBusInfo->entry, &BusInfoList);
+       list_add(&bus_info->entry, &bus_info_list);
 
-       POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, busNo, POSTCODE_SEVERITY_INFO);
+       POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO);
 
-Away:
-       bus_epilog(busNo, CONTROLVM_BUS_CREATE, &inmsg->hdr,
+cleanup:
+       bus_epilog(bus_no, CONTROLVM_BUS_CREATE, &inmsg->hdr,
                   rc, inmsg->hdr.flags.response_expected == 1);
 }
 
@@ -1157,76 +1086,58 @@ static void
 bus_destroy(struct controlvm_message *inmsg)
 {
        struct controlvm_message_packet *cmd = &inmsg->cmd;
-       ulong busNo = cmd->destroy_bus.bus_no;
-       struct visorchipset_bus_info *pBusInfo;
+       ulong bus_no = cmd->destroy_bus.bus_no;
+       struct visorchipset_bus_info *bus_info;
        int rc = CONTROLVM_RESP_SUCCESS;
 
-       pBusInfo = findbus(&BusInfoList, busNo);
-       if (!pBusInfo) {
-               LOGERR("CONTROLVM_BUS_DESTROY Failed: bus %lu invalid", busNo);
+       bus_info = findbus(&bus_info_list, bus_no);
+       if (!bus_info)
                rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
-               goto Away;
-       }
-       if (pBusInfo->state.created == 0) {
-               LOGERR("CONTROLVM_BUS_DESTROY Failed: bus %lu already destroyed",
-                    busNo);
+       else if (bus_info->state.created == 0)
                rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
-               goto Away;
-       }
 
-Away:
-       bus_epilog(busNo, CONTROLVM_BUS_DESTROY, &inmsg->hdr,
+       bus_epilog(bus_no, CONTROLVM_BUS_DESTROY, &inmsg->hdr,
                   rc, inmsg->hdr.flags.response_expected == 1);
 }
 
 static void
-bus_configure(struct controlvm_message *inmsg, PARSER_CONTEXT *parser_ctx)
+bus_configure(struct controlvm_message *inmsg,
+             struct parser_context *parser_ctx)
 {
        struct controlvm_message_packet *cmd = &inmsg->cmd;
-       ulong busNo = cmd->configure_bus.bus_no;
-       struct visorchipset_bus_info *pBusInfo = NULL;
+       ulong bus_no = cmd->configure_bus.bus_no;
+       struct visorchipset_bus_info *bus_info = NULL;
        int rc = CONTROLVM_RESP_SUCCESS;
        char s[99];
 
-       busNo = cmd->configure_bus.bus_no;
-       POSTCODE_LINUX_3(BUS_CONFIGURE_ENTRY_PC, busNo, POSTCODE_SEVERITY_INFO);
+       bus_no = cmd->configure_bus.bus_no;
+       POSTCODE_LINUX_3(BUS_CONFIGURE_ENTRY_PC, bus_no,
+                        POSTCODE_SEVERITY_INFO);
 
-       pBusInfo = findbus(&BusInfoList, busNo);
-       if (!pBusInfo) {
-               LOGERR("CONTROLVM_BUS_CONFIGURE Failed: bus %lu invalid",
-                      busNo);
-               POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, busNo,
+       bus_info = findbus(&bus_info_list, bus_no);
+       if (!bus_info) {
+               POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
-               goto Away;
-       }
-       if (pBusInfo->state.created == 0) {
-               LOGERR("CONTROLVM_BUS_CONFIGURE Failed: Invalid bus %lu - not created yet",
-                    busNo);
-               POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, busNo,
+       } else if (bus_info->state.created == 0) {
+               POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
-               goto Away;
-       }
-       /* TBD - add this check to other commands also... */
-       if (pBusInfo->pending_msg_hdr.id != CONTROLVM_INVALID) {
-               LOGERR("CONTROLVM_BUS_CONFIGURE Failed: bus %lu MsgId=%u outstanding",
-                    busNo, (uint) pBusInfo->pending_msg_hdr.id);
-               POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, busNo,
+       } else if (bus_info->pending_msg_hdr.id != CONTROLVM_INVALID) {
+               POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                rc = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
-               goto Away;
-       }
-
-       pBusInfo->partition_handle = cmd->configure_bus.guest_handle;
-       pBusInfo->partition_uuid = parser_id_get(parser_ctx);
-       parser_param_start(parser_ctx, PARSERSTRING_NAME);
-       pBusInfo->name = parser_string_get(parser_ctx);
+       } else {
+               bus_info->partition_handle = cmd->configure_bus.guest_handle;
+               bus_info->partition_uuid = parser_id_get(parser_ctx);
+               parser_param_start(parser_ctx, PARSERSTRING_NAME);
+               bus_info->name = parser_string_get(parser_ctx);
 
-       visorchannel_uuid_id(&pBusInfo->partition_uuid, s);
-       POSTCODE_LINUX_3(BUS_CONFIGURE_EXIT_PC, busNo, POSTCODE_SEVERITY_INFO);
-Away:
-       bus_epilog(busNo, CONTROLVM_BUS_CONFIGURE, &inmsg->hdr,
+               visorchannel_uuid_id(&bus_info->partition_uuid, s);
+               POSTCODE_LINUX_3(BUS_CONFIGURE_EXIT_PC, bus_no,
+                                POSTCODE_SEVERITY_INFO);
+       }
+       bus_epilog(bus_no, CONTROLVM_BUS_CONFIGURE, &inmsg->hdr,
                   rc, inmsg->hdr.flags.response_expected == 1);
 }
 
@@ -1234,191 +1145,158 @@ static void
 my_device_create(struct controlvm_message *inmsg)
 {
        struct controlvm_message_packet *cmd = &inmsg->cmd;
-       ulong busNo = cmd->create_device.bus_no;
-       ulong devNo = cmd->create_device.dev_no;
-       struct visorchipset_device_info *pDevInfo = NULL;
-       struct visorchipset_bus_info *pBusInfo = NULL;
+       ulong bus_no = cmd->create_device.bus_no;
+       ulong dev_no = cmd->create_device.dev_no;
+       struct visorchipset_device_info *dev_info = NULL;
+       struct visorchipset_bus_info *bus_info = NULL;
        int rc = CONTROLVM_RESP_SUCCESS;
 
-       pDevInfo = finddevice(&DevInfoList, busNo, devNo);
-       if (pDevInfo && (pDevInfo->state.created == 1)) {
-               LOGERR("CONTROLVM_DEVICE_CREATE Failed: busNo=%lu, devNo=%lu already exists",
-                    busNo, devNo);
-               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+       dev_info = finddevice(&dev_info_list, bus_no, dev_no);
+       if (dev_info && (dev_info->state.created == 1)) {
+               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
-               goto Away;
+               goto cleanup;
        }
-       pBusInfo = findbus(&BusInfoList, busNo);
-       if (!pBusInfo) {
-               LOGERR("CONTROLVM_DEVICE_CREATE Failed: Invalid bus %lu - out of range",
-                    busNo);
-               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+       bus_info = findbus(&bus_info_list, bus_no);
+       if (!bus_info) {
+               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
-               goto Away;
+               goto cleanup;
        }
-       if (pBusInfo->state.created == 0) {
-               LOGERR("CONTROLVM_DEVICE_CREATE Failed: Invalid bus %lu - not created yet",
-                    busNo);
-               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+       if (bus_info->state.created == 0) {
+               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
-               goto Away;
+               goto cleanup;
        }
-       pDevInfo = kzalloc(sizeof(struct visorchipset_device_info), GFP_KERNEL);
-       if (pDevInfo == NULL) {
-               LOGERR("CONTROLVM_DEVICE_CREATE Failed: busNo=%lu, devNo=%lu kmaloc failed",
-                    busNo, devNo);
-               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
+       dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
+       if (!dev_info) {
+               POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
-               goto Away;
+               goto cleanup;
        }
 
-       INIT_LIST_HEAD(&pDevInfo->entry);
-       pDevInfo->bus_no = busNo;
-       pDevInfo->dev_no = devNo;
-       pDevInfo->dev_inst_uuid = cmd->create_device.dev_inst_uuid;
-       POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, devNo, busNo,
+       INIT_LIST_HEAD(&dev_info->entry);
+       dev_info->bus_no = bus_no;
+       dev_info->dev_no = dev_no;
+       dev_info->dev_inst_uuid = cmd->create_device.dev_inst_uuid;
+       POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no,
                         POSTCODE_SEVERITY_INFO);
 
        if (inmsg->hdr.flags.test_message == 1)
-               pDevInfo->chan_info.addr_type = ADDRTYPE_LOCALTEST;
+               dev_info->chan_info.addr_type = ADDRTYPE_LOCALTEST;
        else
-               pDevInfo->chan_info.addr_type = ADDRTYPE_LOCALPHYSICAL;
-       pDevInfo->chan_info.channel_addr = cmd->create_device.channel_addr;
-       pDevInfo->chan_info.n_channel_bytes = cmd->create_device.channel_bytes;
-       pDevInfo->chan_info.channel_type_uuid =
+               dev_info->chan_info.addr_type = ADDRTYPE_LOCALPHYSICAL;
+       dev_info->chan_info.channel_addr = cmd->create_device.channel_addr;
+       dev_info->chan_info.n_channel_bytes = cmd->create_device.channel_bytes;
+       dev_info->chan_info.channel_type_uuid =
                        cmd->create_device.data_type_uuid;
-       pDevInfo->chan_info.intr = cmd->create_device.intr;
-       list_add(&pDevInfo->entry, &DevInfoList);
-       POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, devNo, busNo,
+       dev_info->chan_info.intr = cmd->create_device.intr;
+       list_add(&dev_info->entry, &dev_info_list);
+       POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, dev_no, bus_no,
                         POSTCODE_SEVERITY_INFO);
-Away:
+cleanup:
        /* get the bus and devNo for DiagPool channel */
-       if (pDevInfo &&
-           is_diagpool_channel(pDevInfo->chan_info.channel_type_uuid)) {
-               g_diagpoolBusNo = busNo;
-               g_diagpoolDevNo = devNo;
-               LOGINF("CONTROLVM_DEVICE_CREATE for DiagPool channel: busNo=%lu, devNo=%lu",
-                    g_diagpoolBusNo, g_diagpoolDevNo);
-       }
-       device_epilog(busNo, devNo, segment_state_running,
+       if (dev_info &&
+           is_diagpool_channel(dev_info->chan_info.channel_type_uuid)) {
+               g_diagpool_bus_no = bus_no;
+               g_diagpool_dev_no = dev_no;
+       }
+       device_epilog(bus_no, dev_no, segment_state_running,
                      CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc,
                      inmsg->hdr.flags.response_expected == 1,
-                     FOR_VISORBUS(pDevInfo->chan_info.channel_type_uuid));
+                     FOR_VISORBUS(dev_info->chan_info.channel_type_uuid));
 }
 
 static void
 my_device_changestate(struct controlvm_message *inmsg)
 {
        struct controlvm_message_packet *cmd = &inmsg->cmd;
-       ulong busNo = cmd->device_change_state.bus_no;
-       ulong devNo = cmd->device_change_state.dev_no;
+       ulong bus_no = cmd->device_change_state.bus_no;
+       ulong dev_no = cmd->device_change_state.dev_no;
        struct spar_segment_state state = cmd->device_change_state.state;
-       struct visorchipset_device_info *pDevInfo = NULL;
+       struct visorchipset_device_info *dev_info = NULL;
        int rc = CONTROLVM_RESP_SUCCESS;
 
-       pDevInfo = finddevice(&DevInfoList, busNo, devNo);
-       if (!pDevInfo) {
-               LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: busNo=%lu, devNo=%lu invalid (doesn't exist)",
-                    busNo, devNo);
-               POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, devNo, busNo,
+       dev_info = finddevice(&dev_info_list, bus_no, dev_no);
+       if (!dev_info) {
+               POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
-               goto Away;
-       }
-       if (pDevInfo->state.created == 0) {
-               LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: busNo=%lu, devNo=%lu invalid (not created)",
-                    busNo, devNo);
-               POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, devNo, busNo,
+       } else if (dev_info->state.created == 0) {
+               POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
                                 POSTCODE_SEVERITY_ERR);
                rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
        }
-Away:
-       if ((rc >= CONTROLVM_RESP_SUCCESS) && pDevInfo)
-               device_epilog(busNo, devNo, state, CONTROLVM_DEVICE_CHANGESTATE,
-                             &inmsg->hdr, rc,
+       if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
+               device_epilog(bus_no, dev_no, state,
+                             CONTROLVM_DEVICE_CHANGESTATE, &inmsg->hdr, rc,
                              inmsg->hdr.flags.response_expected == 1,
                              FOR_VISORBUS(
-                                       pDevInfo->chan_info.channel_type_uuid));
+                                       dev_info->chan_info.channel_type_uuid));
 }
 
 static void
 my_device_destroy(struct controlvm_message *inmsg)
 {
        struct controlvm_message_packet *cmd = &inmsg->cmd;
-       ulong busNo = cmd->destroy_device.bus_no;
-       ulong devNo = cmd->destroy_device.dev_no;
-       struct visorchipset_device_info *pDevInfo = NULL;
+       ulong bus_no = cmd->destroy_device.bus_no;
+       ulong dev_no = cmd->destroy_device.dev_no;
+       struct visorchipset_device_info *dev_info = NULL;
        int rc = CONTROLVM_RESP_SUCCESS;
 
-       pDevInfo = finddevice(&DevInfoList, busNo, devNo);
-       if (!pDevInfo) {
-               LOGERR("CONTROLVM_DEVICE_DESTROY Failed: busNo=%lu, devNo=%lu invalid",
-                    busNo, devNo);
+       dev_info = finddevice(&dev_info_list, bus_no, dev_no);
+       if (!dev_info)
                rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
-               goto Away;
-       }
-       if (pDevInfo->state.created == 0) {
-               LOGERR("CONTROLVM_DEVICE_DESTROY Failed: busNo=%lu, devNo=%lu already destroyed",
-                    busNo, devNo);
+       else if (dev_info->state.created == 0)
                rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
-       }
 
-Away:
-       if ((rc >= CONTROLVM_RESP_SUCCESS) && pDevInfo)
-               device_epilog(busNo, devNo, segment_state_running,
+       if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
+               device_epilog(bus_no, dev_no, segment_state_running,
                              CONTROLVM_DEVICE_DESTROY, &inmsg->hdr, rc,
                              inmsg->hdr.flags.response_expected == 1,
                              FOR_VISORBUS(
-                                       pDevInfo->chan_info.channel_type_uuid));
+                                       dev_info->chan_info.channel_type_uuid));
 }
 
 /* When provided with the physical address of the controlvm channel
  * (phys_addr), the offset to the payload area we need to manage
  * (offset), and the size of this payload area (bytes), fills in the
- * CONTROLVM_PAYLOAD_INFO struct.  Returns TRUE for success or FALSE
+ * controlvm_payload_info struct.  Returns TRUE for success or FALSE
  * for failure.
  */
 static int
 initialize_controlvm_payload_info(HOSTADDRESS phys_addr, u64 offset, u32 bytes,
-                                 CONTROLVM_PAYLOAD_INFO *info)
+                                 struct controlvm_payload_info *info)
 {
        u8 __iomem *payload = NULL;
        int rc = CONTROLVM_RESP_SUCCESS;
 
-       if (info == NULL) {
-               LOGERR("HUH ? CONTROLVM_PAYLOAD_INIT Failed : Programmer check at %s:%d",
-                    __FILE__, __LINE__);
+       if (!info) {
                rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
-               goto Away;
+               goto cleanup;
        }
-       memset(info, 0, sizeof(CONTROLVM_PAYLOAD_INFO));
+       memset(info, 0, sizeof(struct controlvm_payload_info));
        if ((offset == 0) || (bytes == 0)) {
-               LOGERR("CONTROLVM_PAYLOAD_INIT Failed: request_payload_offset=%llu request_payload_bytes=%llu!",
-                    (u64) offset, (u64) bytes);
                rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
-               goto Away;
+               goto cleanup;
        }
        payload = ioremap_cache(phys_addr + offset, bytes);
-       if (payload == NULL) {
-               LOGERR("CONTROLVM_PAYLOAD_INIT Failed: ioremap_cache %llu for %llu bytes failed",
-                    (u64) offset, (u64) bytes);
+       if (!payload) {
                rc = -CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
-               goto Away;
+               goto cleanup;
        }
 
        info->offset = offset;
        info->bytes = bytes;
        info->ptr = payload;
-       LOGINF("offset=%llu, bytes=%lu, ptr=%p",
-              (u64) (info->offset), (ulong) (info->bytes), info->ptr);
 
-Away:
+cleanup:
        if (rc < 0) {
-               if (payload != NULL) {
+               if (payload) {
                        iounmap(payload);
                        payload = NULL;
                }
@@ -1427,43 +1305,41 @@ Away:
 }
 
 static void
-destroy_controlvm_payload_info(CONTROLVM_PAYLOAD_INFO *info)
+destroy_controlvm_payload_info(struct controlvm_payload_info *info)
 {
-       if (info->ptr != NULL) {
+       if (info->ptr) {
                iounmap(info->ptr);
                info->ptr = NULL;
        }
-       memset(info, 0, sizeof(CONTROLVM_PAYLOAD_INFO));
+       memset(info, 0, sizeof(struct controlvm_payload_info));
 }
 
 static void
 initialize_controlvm_payload(void)
 {
-       HOSTADDRESS phys_addr = visorchannel_get_physaddr(ControlVm_channel);
-       u64 payloadOffset = 0;
-       u32 payloadBytes = 0;
+       HOSTADDRESS phys_addr = visorchannel_get_physaddr(controlvm_channel);
+       u64 payload_offset = 0;
+       u32 payload_bytes = 0;
 
-       if (visorchannel_read(ControlVm_channel,
+       if (visorchannel_read(controlvm_channel,
                              offsetof(struct spar_controlvm_channel_protocol,
                                       request_payload_offset),
-                             &payloadOffset, sizeof(payloadOffset)) < 0) {
-               LOGERR("CONTROLVM_PAYLOAD_INIT Failed to read controlvm channel!");
+                             &payload_offset, sizeof(payload_offset)) < 0) {
                POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
                                 POSTCODE_SEVERITY_ERR);
                return;
        }
-       if (visorchannel_read(ControlVm_channel,
+       if (visorchannel_read(controlvm_channel,
                              offsetof(struct spar_controlvm_channel_protocol,
                                       request_payload_bytes),
-                             &payloadBytes, sizeof(payloadBytes)) < 0) {
-               LOGERR("CONTROLVM_PAYLOAD_INIT Failed to read controlvm channel!");
+                             &payload_bytes, sizeof(payload_bytes)) < 0) {
                POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
                                 POSTCODE_SEVERITY_ERR);
                return;
        }
        initialize_controlvm_payload_info(phys_addr,
-                                         payloadOffset, payloadBytes,
-                                         &ControlVm_payload_info);
+                                         payload_offset, payload_bytes,
+                                         &controlvm_payload_info);
 }
 
 /*  Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
@@ -1472,7 +1348,7 @@ initialize_controlvm_payload(void)
 int
 visorchipset_chipset_ready(void)
 {
-       kobject_uevent(&Visorchipset_platform_device.dev.kobj, KOBJ_ONLINE);
+       kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_ONLINE);
        return CONTROLVM_RESP_SUCCESS;
 }
 EXPORT_SYMBOL_GPL(visorchipset_chipset_ready);
@@ -1484,7 +1360,7 @@ visorchipset_chipset_selftest(void)
        char *envp[] = { env_selftest, NULL };
 
        sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1);
-       kobject_uevent_env(&Visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
+       kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
                           envp);
        return CONTROLVM_RESP_SUCCESS;
 }
@@ -1496,49 +1372,48 @@ EXPORT_SYMBOL_GPL(visorchipset_chipset_selftest);
 int
 visorchipset_chipset_notready(void)
 {
-       kobject_uevent(&Visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE);
+       kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE);
        return CONTROLVM_RESP_SUCCESS;
 }
 EXPORT_SYMBOL_GPL(visorchipset_chipset_notready);
 
 static void
-chipset_ready(struct controlvm_message_header *msgHdr)
+chipset_ready(struct controlvm_message_header *msg_hdr)
 {
        int rc = visorchipset_chipset_ready();
 
        if (rc != CONTROLVM_RESP_SUCCESS)
                rc = -rc;
-       if (msgHdr->flags.response_expected && !visorchipset_holdchipsetready)
-               controlvm_respond(msgHdr, rc);
-       if (msgHdr->flags.response_expected && visorchipset_holdchipsetready) {
+       if (msg_hdr->flags.response_expected && !visorchipset_holdchipsetready)
+               controlvm_respond(msg_hdr, rc);
+       if (msg_hdr->flags.response_expected && visorchipset_holdchipsetready) {
                /* Send CHIPSET_READY response when all modules have been loaded
                 * and disks mounted for the partition
                 */
-               g_ChipSetMsgHdr = *msgHdr;
-               LOGINF("Holding CHIPSET_READY response");
+               g_chipset_msg_hdr = *msg_hdr;
        }
 }
 
 static void
-chipset_selftest(struct controlvm_message_header *msgHdr)
+chipset_selftest(struct controlvm_message_header *msg_hdr)
 {
        int rc = visorchipset_chipset_selftest();
 
        if (rc != CONTROLVM_RESP_SUCCESS)
                rc = -rc;
-       if (msgHdr->flags.response_expected)
-               controlvm_respond(msgHdr, rc);
+       if (msg_hdr->flags.response_expected)
+               controlvm_respond(msg_hdr, rc);
 }
 
 static void
-chipset_notready(struct controlvm_message_header *msgHdr)
+chipset_notready(struct controlvm_message_header *msg_hdr)
 {
        int rc = visorchipset_chipset_notready();
 
        if (rc != CONTROLVM_RESP_SUCCESS)
                rc = -rc;
-       if (msgHdr->flags.response_expected)
-               controlvm_respond(msgHdr, rc);
+       if (msg_hdr->flags.response_expected)
+               controlvm_respond(msg_hdr, rc);
 }
 
 /* This is your "one-stop" shop for grabbing the next message from the
@@ -1547,14 +1422,11 @@ chipset_notready(struct controlvm_message_header *msgHdr)
 static BOOL
 read_controlvm_event(struct controlvm_message *msg)
 {
-       if (visorchannel_signalremove(ControlVm_channel,
+       if (visorchannel_signalremove(controlvm_channel,
                                      CONTROLVM_QUEUE_EVENT, msg)) {
                /* got a message */
-               if (msg->hdr.flags.test_message == 1) {
-                       LOGERR("ignoring bad CONTROLVM_QUEUE_EVENT msg with controlvm_msg_id=0x%x because Flags.testMessage is nonsensical (=1)",
-                              msg->hdr.id);
+               if (msg->hdr.flags.test_message == 1)
                        return FALSE;
-               }
                return TRUE;
        }
        return FALSE;
@@ -1604,10 +1476,10 @@ parahotplug_next_expiration(void)
 static struct parahotplug_request *
 parahotplug_request_create(struct controlvm_message *msg)
 {
-       struct parahotplug_request *req =
-           kmalloc(sizeof(struct parahotplug_request),
-                   GFP_KERNEL|__GFP_NORETRY);
-       if (req == NULL)
+       struct parahotplug_request *req;
+
+       req = kmalloc(sizeof(*req), GFP_KERNEL | __GFP_NORETRY);
+       if (!req)
                return NULL;
 
        req->id = parahotplug_next_id();
@@ -1652,13 +1524,7 @@ parahotplug_request_kickoff(struct parahotplug_request *req)
        sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d",
                cmd->device_change_state.dev_no & 0x7);
 
-       LOGINF("parahotplug_request_kickoff: state=%d, bdf=%d/%d/%d, id=%u\n",
-              cmd->device_change_state.state.active,
-              cmd->device_change_state.bus_no,
-              cmd->device_change_state.dev_no >> 3,
-              cmd->device_change_state.dev_no & 7, req->id);
-
-       kobject_uevent_env(&Visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
+       kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
                           envp);
 }
 
@@ -1672,23 +1538,25 @@ parahotplug_process_list(void)
        struct list_head *pos = NULL;
        struct list_head *tmp = NULL;
 
-       spin_lock(&Parahotplug_request_list_lock);
+       spin_lock(&parahotplug_request_list_lock);
 
-       list_for_each_safe(pos, tmp, &Parahotplug_request_list) {
+       list_for_each_safe(pos, tmp, &parahotplug_request_list) {
                struct parahotplug_request *req =
                    list_entry(pos, struct parahotplug_request, list);
-               if (time_after_eq(jiffies, req->expiration)) {
-                       list_del(pos);
-                       if (req->msg.hdr.flags.response_expected)
-                               controlvm_respond_physdev_changestate(
-                                       &req->msg.hdr,
-                                       CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT,
-                                       req->msg.cmd.device_change_state.state);
-                       parahotplug_request_destroy(req);
-               }
+
+               if (!time_after_eq(jiffies, req->expiration))
+                       continue;
+
+               list_del(pos);
+               if (req->msg.hdr.flags.response_expected)
+                       controlvm_respond_physdev_changestate(
+                               &req->msg.hdr,
+                               CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT,
+                               req->msg.cmd.device_change_state.state);
+               parahotplug_request_destroy(req);
        }
 
-       spin_unlock(&Parahotplug_request_list_lock);
+       spin_unlock(&parahotplug_request_list_lock);
 }
 
 /*
@@ -1702,10 +1570,10 @@ parahotplug_request_complete(int id, u16 active)
        struct list_head *pos = NULL;
        struct list_head *tmp = NULL;
 
-       spin_lock(&Parahotplug_request_list_lock);
+       spin_lock(&parahotplug_request_list_lock);
 
        /* Look for a request matching "id". */
-       list_for_each_safe(pos, tmp, &Parahotplug_request_list) {
+       list_for_each_safe(pos, tmp, &parahotplug_request_list) {
                struct parahotplug_request *req =
                    list_entry(pos, struct parahotplug_request, list);
                if (req->id == id) {
@@ -1713,7 +1581,7 @@ parahotplug_request_complete(int id, u16 active)
                         * respond.
                         */
                        list_del(pos);
-                       spin_unlock(&Parahotplug_request_list_lock);
+                       spin_unlock(&parahotplug_request_list_lock);
                        req->msg.cmd.device_change_state.state.active = active;
                        if (req->msg.hdr.flags.response_expected)
                                controlvm_respond_physdev_changestate(
@@ -1724,7 +1592,7 @@ parahotplug_request_complete(int id, u16 active)
                }
        }
 
-       spin_unlock(&Parahotplug_request_list_lock);
+       spin_unlock(&parahotplug_request_list_lock);
        return -1;
 }
 
@@ -1738,10 +1606,8 @@ parahotplug_process_message(struct controlvm_message *inmsg)
 
        req = parahotplug_request_create(inmsg);
 
-       if (req == NULL) {
-               LOGERR("parahotplug_process_message: couldn't allocate request");
+       if (!req)
                return;
-       }
 
        if (inmsg->cmd.device_change_state.state.active) {
                /* For enable messages, just respond with success
@@ -1755,8 +1621,8 @@ parahotplug_process_message(struct controlvm_message *inmsg)
                */
                parahotplug_request_kickoff(req);
                controlvm_respond_physdev_changestate(&inmsg->hdr,
-                               CONTROLVM_RESP_SUCCESS, inmsg->cmd.
-                               device_change_state.state);
+                       CONTROLVM_RESP_SUCCESS,
+                       inmsg->cmd.device_change_state.state);
                parahotplug_request_destroy(req);
        } else {
                /* For disable messages, add the request to the
@@ -1764,9 +1630,9 @@ parahotplug_process_message(struct controlvm_message *inmsg)
                * won't get responded to until the script has
                * indicated it's done.
                */
-               spin_lock(&Parahotplug_request_list_lock);
-               list_add_tail(&(req->list), &Parahotplug_request_list);
-               spin_unlock(&Parahotplug_request_list_lock);
+               spin_lock(&parahotplug_request_list_lock);
+               list_add_tail(&req->list, &parahotplug_request_list);
+               spin_unlock(&parahotplug_request_list_lock);
 
                parahotplug_request_kickoff(req);
        }
@@ -1787,135 +1653,94 @@ static BOOL
 handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr)
 {
        struct controlvm_message_packet *cmd = &inmsg.cmd;
-       u64 parametersAddr = 0;
-       u32 parametersBytes = 0;
-       PARSER_CONTEXT *parser_ctx = NULL;
-       BOOL isLocalAddr = FALSE;
+       u64 parm_addr = 0;
+       u32 parm_bytes = 0;
+       struct parser_context *parser_ctx = NULL;
+       bool local_addr = false;
        struct controlvm_message ackmsg;
 
        /* create parsing context if necessary */
-       isLocalAddr = (inmsg.hdr.flags.test_message == 1);
-       if (channel_addr == 0) {
-               LOGERR("HUH? channel_addr is 0!");
+       local_addr = (inmsg.hdr.flags.test_message == 1);
+       if (channel_addr == 0)
                return TRUE;
-       }
-       parametersAddr = channel_addr + inmsg.hdr.payload_vm_offset;
-       parametersBytes = inmsg.hdr.payload_bytes;
+       parm_addr = channel_addr + inmsg.hdr.payload_vm_offset;
+       parm_bytes = inmsg.hdr.payload_bytes;
 
        /* Parameter and channel addresses within test messages actually lie
         * within our OS-controlled memory.  We need to know that, because it
         * makes a difference in how we compute the virtual address.
         */
-       if (parametersAddr != 0 && parametersBytes != 0) {
+       if (parm_addr != 0 && parm_bytes != 0) {
                BOOL retry = FALSE;
 
                parser_ctx =
-                   parser_init_byteStream(parametersAddr, parametersBytes,
-                                          isLocalAddr, &retry);
-               if (!parser_ctx) {
-                       if (retry) {
-                               LOGWRN("throttling to copy payload");
-                               return FALSE;
-                       }
-                       LOGWRN("parsing failed");
-                       LOGWRN("inmsg.hdr.Id=0x%lx", (ulong) inmsg.hdr.id);
-                       LOGWRN("parametersAddr=0x%llx", (u64) parametersAddr);
-                       LOGWRN("parametersBytes=%lu", (ulong) parametersBytes);
-                       LOGWRN("isLocalAddr=%d", isLocalAddr);
-               }
+                   parser_init_byte_stream(parm_addr, parm_bytes,
+                                           local_addr, &retry);
+               if (!parser_ctx && retry)
+                       return FALSE;
        }
 
-       if (!isLocalAddr) {
+       if (!local_addr) {
                controlvm_init_response(&ackmsg, &inmsg.hdr,
                                        CONTROLVM_RESP_SUCCESS);
-               if ((ControlVm_channel)
-                   &&
-                   (!visorchannel_signalinsert
-                    (ControlVm_channel, CONTROLVM_QUEUE_ACK, &ackmsg)))
-                       LOGWRN("failed to send ACK failed");
+               if (controlvm_channel)
+                       visorchannel_signalinsert(controlvm_channel,
+                                                 CONTROLVM_QUEUE_ACK,
+                                                 &ackmsg);
        }
        switch (inmsg.hdr.id) {
        case CONTROLVM_CHIPSET_INIT:
-               LOGINF("CHIPSET_INIT(#busses=%lu,#switches=%lu)",
-                      (ulong) inmsg.cmd.init_chipset.bus_count,
-                      (ulong) inmsg.cmd.init_chipset.switch_count);
                chipset_init(&inmsg);
                break;
        case CONTROLVM_BUS_CREATE:
-               LOGINF("BUS_CREATE(%lu,#devs=%lu)",
-                      (ulong) cmd->create_bus.bus_no,
-                      (ulong) cmd->create_bus.dev_count);
                bus_create(&inmsg);
                break;
        case CONTROLVM_BUS_DESTROY:
-               LOGINF("BUS_DESTROY(%lu)", (ulong) cmd->destroy_bus.bus_no);
                bus_destroy(&inmsg);
                break;
        case CONTROLVM_BUS_CONFIGURE:
-               LOGINF("BUS_CONFIGURE(%lu)", (ulong) cmd->configure_bus.bus_no);
                bus_configure(&inmsg, parser_ctx);
                break;
        case CONTROLVM_DEVICE_CREATE:
-               LOGINF("DEVICE_CREATE(%lu,%lu)",
-                      (ulong) cmd->create_device.bus_no,
-                      (ulong) cmd->create_device.dev_no);
                my_device_create(&inmsg);
                break;
        case CONTROLVM_DEVICE_CHANGESTATE:
                if (cmd->device_change_state.flags.phys_device) {
-                       LOGINF("DEVICE_CHANGESTATE for physical device (%lu,%lu, active=%lu)",
-                            (ulong) cmd->device_change_state.bus_no,
-                            (ulong) cmd->device_change_state.dev_no,
-                            (ulong) cmd->device_change_state.state.active);
                        parahotplug_process_message(&inmsg);
                } else {
-                       LOGINF("DEVICE_CHANGESTATE for virtual device (%lu,%lu, state.Alive=0x%lx)",
-                            (ulong) cmd->device_change_state.bus_no,
-                            (ulong) cmd->device_change_state.dev_no,
-                            (ulong) cmd->device_change_state.state.alive);
                        /* save the hdr and cmd structures for later use */
                        /* when sending back the response to Command */
                        my_device_changestate(&inmsg);
-                       g_DiagMsgHdr = inmsg.hdr;
-                       g_DeviceChangeStatePacket = inmsg.cmd;
+                       g_diag_msg_hdr = inmsg.hdr;
+                       g_devicechangestate_packet = inmsg.cmd;
                        break;
                }
                break;
        case CONTROLVM_DEVICE_DESTROY:
-               LOGINF("DEVICE_DESTROY(%lu,%lu)",
-                      (ulong) cmd->destroy_device.bus_no,
-                      (ulong) cmd->destroy_device.dev_no);
                my_device_destroy(&inmsg);
                break;
        case CONTROLVM_DEVICE_CONFIGURE:
-               LOGINF("DEVICE_CONFIGURE(%lu,%lu)",
-                      (ulong) cmd->configure_device.bus_no,
-                      (ulong) cmd->configure_device.dev_no);
                /* no op for now, just send a respond that we passed */
                if (inmsg.hdr.flags.response_expected)
                        controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS);
                break;
        case CONTROLVM_CHIPSET_READY:
-               LOGINF("CHIPSET_READY");
                chipset_ready(&inmsg.hdr);
                break;
        case CONTROLVM_CHIPSET_SELFTEST:
-               LOGINF("CHIPSET_SELFTEST");
                chipset_selftest(&inmsg.hdr);
                break;
        case CONTROLVM_CHIPSET_STOP:
-               LOGINF("CHIPSET_STOP");
                chipset_notready(&inmsg.hdr);
                break;
        default:
-               LOGERR("unrecognized controlvm cmd=%d", (int) inmsg.hdr.id);
                if (inmsg.hdr.flags.response_expected)
                        controlvm_respond(&inmsg.hdr,
-                                         -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN);
+                               -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN);
                break;
        }
 
-       if (parser_ctx != NULL) {
+       if (parser_ctx) {
                parser_done(parser_ctx);
                parser_ctx = NULL;
        }
@@ -1927,12 +1752,9 @@ static HOSTADDRESS controlvm_get_channel_address(void)
        u64 addr = 0;
        u32 size = 0;
 
-       if (!VMCALL_SUCCESSFUL(issue_vmcall_io_controlvm_addr(&addr, &size))) {
-               ERRDRV("%s - vmcall to determine controlvm channel addr failed",
-                      __func__);
+       if (!VMCALL_SUCCESSFUL(issue_vmcall_io_controlvm_addr(&addr, &size)))
                return 0;
-       }
-       INFODRV("controlvm addr=%Lx", addr);
+
        return addr;
 }
 
@@ -1940,69 +1762,63 @@ static void
 controlvm_periodic_work(struct work_struct *work)
 {
        struct controlvm_message inmsg;
-       BOOL gotACommand = FALSE;
+       BOOL got_command = FALSE;
        BOOL handle_command_failed = FALSE;
-       static u64 Poll_Count;
+       static u64 poll_count;
 
        /* make sure visorbus server is registered for controlvm callbacks */
        if (visorchipset_serverregwait && !serverregistered)
-               goto Away;
+               goto cleanup;
        /* make sure visorclientbus server is regsitered for controlvm
         * callbacks
         */
        if (visorchipset_clientregwait && !clientregistered)
-               goto Away;
+               goto cleanup;
 
-       Poll_Count++;
-       if (Poll_Count >= 250)
+       poll_count++;
+       if (poll_count >= 250)
                ;       /* keep going */
        else
-               goto Away;
+               goto cleanup;
 
        /* Check events to determine if response to CHIPSET_READY
         * should be sent
         */
-       if (visorchipset_holdchipsetready
-           && (g_ChipSetMsgHdr.id != CONTROLVM_INVALID)) {
+       if (visorchipset_holdchipsetready &&
+           (g_chipset_msg_hdr.id != CONTROLVM_INVALID)) {
                if (check_chipset_events() == 1) {
-                       LOGINF("Sending CHIPSET_READY response");
-                       controlvm_respond(&g_ChipSetMsgHdr, 0);
+                       controlvm_respond(&g_chipset_msg_hdr, 0);
                        clear_chipset_events();
-                       memset(&g_ChipSetMsgHdr, 0,
+                       memset(&g_chipset_msg_hdr, 0,
                               sizeof(struct controlvm_message_header));
                }
        }
 
-       while (visorchannel_signalremove(ControlVm_channel,
+       while (visorchannel_signalremove(controlvm_channel,
                                         CONTROLVM_QUEUE_RESPONSE,
-                                        &inmsg)) {
-               if (inmsg.hdr.payload_max_bytes != 0) {
-                       LOGERR("Payload of size %lu returned @%lu with unexpected message id %d.",
-                            (ulong) inmsg.hdr.payload_max_bytes,
-                            (ulong) inmsg.hdr.payload_vm_offset,
-                            inmsg.hdr.id);
-               }
-       }
-       if (!gotACommand) {
-               if (ControlVm_Pending_Msg_Valid) {
+                                        &inmsg))
+               ;
+       if (!got_command) {
+               if (controlvm_pending_msg_valid) {
                        /* we throttled processing of a prior
                        * msg, so try to process it again
                        * rather than reading a new one
                        */
-                       inmsg = ControlVm_Pending_Msg;
-                       ControlVm_Pending_Msg_Valid = FALSE;
-                       gotACommand = TRUE;
-               } else
-                       gotACommand = read_controlvm_event(&inmsg);
+                       inmsg = controlvm_pending_msg;
+                       controlvm_pending_msg_valid = FALSE;
+                       got_command = true;
+               } else {
+                       got_command = read_controlvm_event(&inmsg);
+               }
        }
 
        handle_command_failed = FALSE;
-       while (gotACommand && (!handle_command_failed)) {
-               Most_recent_message_jiffies = jiffies;
+       while (got_command && (!handle_command_failed)) {
+               most_recent_message_jiffies = jiffies;
                if (handle_command(inmsg,
                                   visorchannel_get_physaddr
-                                  (ControlVm_channel)))
-                       gotACommand = read_controlvm_event(&inmsg);
+                                  (controlvm_channel)))
+                       got_command = read_controlvm_event(&inmsg);
                else {
                        /* this is a scenario where throttling
                        * is required, but probably NOT an
@@ -2011,56 +1827,51 @@ controlvm_periodic_work(struct work_struct *work)
                        * reprocess it on our next loop
                        */
                        handle_command_failed = TRUE;
-                       ControlVm_Pending_Msg = inmsg;
-                       ControlVm_Pending_Msg_Valid = TRUE;
+                       controlvm_pending_msg = inmsg;
+                       controlvm_pending_msg_valid = TRUE;
                }
        }
 
        /* parahotplug_worker */
        parahotplug_process_list();
 
-Away:
+cleanup:
 
        if (time_after(jiffies,
-                      Most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) {
+                      most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) {
                /* it's been longer than MIN_IDLE_SECONDS since we
                * processed our last controlvm message; slow down the
                * polling
                */
-               if (Poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW) {
-                       LOGINF("switched to slow controlvm polling");
-                       Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
-               }
+               if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW)
+                       poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
        } else {
-               if (Poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST) {
-                       Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
-                       LOGINF("switched to fast controlvm polling");
-               }
+               if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST)
+                       poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
        }
 
-       queue_delayed_work(Periodic_controlvm_workqueue,
-                          &Periodic_controlvm_work, Poll_jiffies);
+       queue_delayed_work(periodic_controlvm_workqueue,
+                          &periodic_controlvm_work, poll_jiffies);
 }
 
 static void
 setup_crash_devices_work_queue(struct work_struct *work)
 {
-
-       struct controlvm_message localCrashCreateBusMsg;
-       struct controlvm_message localCrashCreateDevMsg;
+       struct controlvm_message local_crash_bus_msg;
+       struct controlvm_message local_crash_dev_msg;
        struct controlvm_message msg;
-       u32 localSavedCrashMsgOffset;
-       u16 localSavedCrashMsgCount;
+       u32 local_crash_msg_offset;
+       u16 local_crash_msg_count;
 
        /* make sure visorbus server is registered for controlvm callbacks */
        if (visorchipset_serverregwait && !serverregistered)
-               goto Away;
+               goto cleanup;
 
        /* make sure visorclientbus server is regsitered for controlvm
         * callbacks
         */
        if (visorchipset_clientregwait && !clientregistered)
-               goto Away;
+               goto cleanup;
 
        POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO);
 
@@ -2072,118 +1883,108 @@ setup_crash_devices_work_queue(struct work_struct *work)
        chipset_init(&msg);
 
        /* get saved message count */
-       if (visorchannel_read(ControlVm_channel,
+       if (visorchannel_read(controlvm_channel,
                              offsetof(struct spar_controlvm_channel_protocol,
                                       saved_crash_message_count),
-                             &localSavedCrashMsgCount, sizeof(u16)) < 0) {
-               LOGERR("failed to get Saved Message Count");
+                             &local_crash_msg_count, sizeof(u16)) < 0) {
                POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
                                 POSTCODE_SEVERITY_ERR);
                return;
        }
 
-       if (localSavedCrashMsgCount != CONTROLVM_CRASHMSG_MAX) {
-               LOGERR("Saved Message Count incorrect %d",
-                      localSavedCrashMsgCount);
+       if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
                POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
-                                localSavedCrashMsgCount,
+                                local_crash_msg_count,
                                 POSTCODE_SEVERITY_ERR);
                return;
        }
 
        /* get saved crash message offset */
-       if (visorchannel_read(ControlVm_channel,
+       if (visorchannel_read(controlvm_channel,
                              offsetof(struct spar_controlvm_channel_protocol,
                                       saved_crash_message_offset),
-                             &localSavedCrashMsgOffset, sizeof(u32)) < 0) {
-               LOGERR("failed to get Saved Message Offset");
+                             &local_crash_msg_offset, sizeof(u32)) < 0) {
                POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
                                 POSTCODE_SEVERITY_ERR);
                return;
        }
 
        /* read create device message for storage bus offset */
-       if (visorchannel_read(ControlVm_channel,
-                             localSavedCrashMsgOffset,
-                             &localCrashCreateBusMsg,
+       if (visorchannel_read(controlvm_channel,
+                             local_crash_msg_offset,
+                             &local_crash_bus_msg,
                              sizeof(struct controlvm_message)) < 0) {
-               LOGERR("CRASH_DEV_RD_BUS_FAIULRE: Failed to read CrashCreateBusMsg!");
                POSTCODE_LINUX_2(CRASH_DEV_RD_BUS_FAIULRE_PC,
                                 POSTCODE_SEVERITY_ERR);
                return;
        }
 
        /* read create device message for storage device */
-       if (visorchannel_read(ControlVm_channel,
-                             localSavedCrashMsgOffset +
+       if (visorchannel_read(controlvm_channel,
+                             local_crash_msg_offset +
                              sizeof(struct controlvm_message),
-                             &localCrashCreateDevMsg,
+                             &local_crash_dev_msg,
                              sizeof(struct controlvm_message)) < 0) {
-               LOGERR("CRASH_DEV_RD_DEV_FAIULRE: Failed to read CrashCreateDevMsg!");
                POSTCODE_LINUX_2(CRASH_DEV_RD_DEV_FAIULRE_PC,
                                 POSTCODE_SEVERITY_ERR);
                return;
        }
 
        /* reuse IOVM create bus message */
-       if (localCrashCreateBusMsg.cmd.create_bus.channel_addr != 0)
-               bus_create(&localCrashCreateBusMsg);
-       else {
-               LOGERR("CrashCreateBusMsg is null, no dump will be taken");
+       if (local_crash_bus_msg.cmd.create_bus.channel_addr != 0) {
+               bus_create(&local_crash_bus_msg);
+       } else {
                POSTCODE_LINUX_2(CRASH_DEV_BUS_NULL_FAILURE_PC,
                                 POSTCODE_SEVERITY_ERR);
                return;
        }
 
        /* reuse create device message for storage device */
-       if (localCrashCreateDevMsg.cmd.create_device.channel_addr != 0)
-               my_device_create(&localCrashCreateDevMsg);
-       else {
-               LOGERR("CrashCreateDevMsg is null, no dump will be taken");
+       if (local_crash_dev_msg.cmd.create_device.channel_addr != 0) {
+               my_device_create(&local_crash_dev_msg);
+       } else {
                POSTCODE_LINUX_2(CRASH_DEV_DEV_NULL_FAILURE_PC,
                                 POSTCODE_SEVERITY_ERR);
                return;
        }
-       LOGINF("Bus and device ready for dumping");
        POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO);
        return;
 
-Away:
+cleanup:
 
-       Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
+       poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
 
-       queue_delayed_work(Periodic_controlvm_workqueue,
-                          &Periodic_controlvm_work, Poll_jiffies);
+       queue_delayed_work(periodic_controlvm_workqueue,
+                          &periodic_controlvm_work, poll_jiffies);
 }
 
 static void
-bus_create_response(ulong busNo, int response)
+bus_create_response(ulong bus_no, int response)
 {
-       bus_responder(CONTROLVM_BUS_CREATE, busNo, response);
+       bus_responder(CONTROLVM_BUS_CREATE, bus_no, response);
 }
 
 static void
-bus_destroy_response(ulong busNo, int response)
+bus_destroy_response(ulong bus_no, int response)
 {
-       bus_responder(CONTROLVM_BUS_DESTROY, busNo, response);
+       bus_responder(CONTROLVM_BUS_DESTROY, bus_no, response);
 }
 
 static void
-device_create_response(ulong busNo, ulong devNo, int response)
+device_create_response(ulong bus_no, ulong dev_no, int response)
 {
-       device_responder(CONTROLVM_DEVICE_CREATE, busNo, devNo, response);
+       device_responder(CONTROLVM_DEVICE_CREATE, bus_no, dev_no, response);
 }
 
 static void
-device_destroy_response(ulong busNo, ulong devNo, int response)
+device_destroy_response(ulong bus_no, ulong dev_no, int response)
 {
-       device_responder(CONTROLVM_DEVICE_DESTROY, busNo, devNo, response);
+       device_responder(CONTROLVM_DEVICE_DESTROY, bus_no, dev_no, response);
 }
 
 void
 visorchipset_device_pause_response(ulong bus_no, ulong dev_no, int response)
 {
-
        device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
                                     bus_no, dev_no, response,
                                     segment_state_standby);
@@ -2191,22 +1992,20 @@ visorchipset_device_pause_response(ulong bus_no, ulong dev_no, int response)
 EXPORT_SYMBOL_GPL(visorchipset_device_pause_response);
 
 static void
-device_resume_response(ulong busNo, ulong devNo, int response)
+device_resume_response(ulong bus_no, ulong dev_no, int response)
 {
        device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
-                                    busNo, devNo, response,
+                                    bus_no, dev_no, response,
                                     segment_state_running);
 }
 
 BOOL
 visorchipset_get_bus_info(ulong bus_no, struct visorchipset_bus_info *bus_info)
 {
-       void *p = findbus(&BusInfoList, bus_no);
+       void *p = findbus(&bus_info_list, bus_no);
 
-       if (!p) {
-               LOGERR("(%lu) failed", bus_no);
+       if (!p)
                return FALSE;
-       }
        memcpy(bus_info, p, sizeof(struct visorchipset_bus_info));
        return TRUE;
 }
@@ -2215,12 +2014,10 @@ EXPORT_SYMBOL_GPL(visorchipset_get_bus_info);
 BOOL
 visorchipset_set_bus_context(ulong bus_no, void *context)
 {
-       struct visorchipset_bus_info *p = findbus(&BusInfoList, bus_no);
+       struct visorchipset_bus_info *p = findbus(&bus_info_list, bus_no);
 
-       if (!p) {
-               LOGERR("(%lu) failed", bus_no);
+       if (!p)
                return FALSE;
-       }
        p->bus_driver_context = context;
        return TRUE;
 }
@@ -2230,12 +2027,10 @@ BOOL
 visorchipset_get_device_info(ulong bus_no, ulong dev_no,
                             struct visorchipset_device_info *dev_info)
 {
-       void *p = finddevice(&DevInfoList, bus_no, dev_no);
+       void *p = finddevice(&dev_info_list, bus_no, dev_no);
 
-       if (!p) {
-               LOGERR("(%lu,%lu) failed", bus_no, dev_no);
+       if (!p)
                return FALSE;
-       }
        memcpy(dev_info, p, sizeof(struct visorchipset_device_info));
        return TRUE;
 }
@@ -2245,12 +2040,10 @@ BOOL
 visorchipset_set_device_context(ulong bus_no, ulong dev_no, void *context)
 {
        struct visorchipset_device_info *p =
-                       finddevice(&DevInfoList, bus_no, dev_no);
+                       finddevice(&dev_info_list, bus_no, dev_no);
 
-       if (!p) {
-               LOGERR("(%lu,%lu) failed", bus_no, dev_no);
+       if (!p)
                return FALSE;
-       }
        p->bus_driver_context = context;
        return TRUE;
 }
@@ -2278,11 +2071,10 @@ visorchipset_cache_alloc(struct kmem_cache *pool, BOOL ok_to_block,
         */
        gfp |= __GFP_NORETRY;
        p = kmem_cache_alloc(pool, gfp);
-       if (!p) {
-               LOGERR("kmem_cache_alloc failed early @%s:%d\n", fn, ln);
+       if (!p)
                return NULL;
-       }
-       atomic_inc(&Visorchipset_cache_buffers_in_use);
+
+       atomic_inc(&visorchipset_cache_buffers_in_use);
        return p;
 }
 
@@ -2291,16 +2083,16 @@ visorchipset_cache_alloc(struct kmem_cache *pool, BOOL ok_to_block,
 void
 visorchipset_cache_free(struct kmem_cache *pool, void *p, char *fn, int ln)
 {
-       if (!p) {
-               LOGERR("NULL pointer @%s:%d\n", fn, ln);
+       if (!p)
                return;
-       }
-       atomic_dec(&Visorchipset_cache_buffers_in_use);
+
+       atomic_dec(&visorchipset_cache_buffers_in_use);
        kmem_cache_free(pool, p);
 }
 
 static ssize_t chipsetready_store(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count)
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count)
 {
        char msgtype[64];
 
@@ -2322,7 +2114,8 @@ static ssize_t chipsetready_store(struct device *dev,
  * and then passed back when the device has been removed.
  */
 static ssize_t devicedisabled_store(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count)
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count)
 {
        uint id;
 
@@ -2338,7 +2131,8 @@ static ssize_t devicedisabled_store(struct device *dev,
  * and then passed back when the device has been brought back up.
  */
 static ssize_t deviceenabled_store(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count)
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
 {
        uint id;
 
@@ -2353,133 +2147,102 @@ static int __init
 visorchipset_init(void)
 {
        int rc = 0, x = 0;
-       char s[64];
        HOSTADDRESS addr;
 
        if (!unisys_spar_platform)
                return -ENODEV;
 
-       LOGINF("chipset driver version %s loaded", VERSION);
-       /* process module options */
-       POSTCODE_LINUX_2(DRIVER_ENTRY_PC, POSTCODE_SEVERITY_INFO);
-
-       LOGINF("option - testvnic=%d", visorchipset_testvnic);
-       LOGINF("option - testvnicclient=%d", visorchipset_testvnicclient);
-       LOGINF("option - testmsg=%d", visorchipset_testmsg);
-       LOGINF("option - testteardown=%d", visorchipset_testteardown);
-       LOGINF("option - major=%d", visorchipset_major);
-       LOGINF("option - serverregwait=%d", visorchipset_serverregwait);
-       LOGINF("option - clientregwait=%d", visorchipset_clientregwait);
-       LOGINF("option - holdchipsetready=%d", visorchipset_holdchipsetready);
-
-       memset(&BusDev_Server_Notifiers, 0, sizeof(BusDev_Server_Notifiers));
-       memset(&BusDev_Client_Notifiers, 0, sizeof(BusDev_Client_Notifiers));
-       memset(&ControlVm_payload_info, 0, sizeof(ControlVm_payload_info));
-       memset(&LiveDump_info, 0, sizeof(LiveDump_info));
-       atomic_set(&LiveDump_info.buffers_in_use, 0);
+       memset(&busdev_server_notifiers, 0, sizeof(busdev_server_notifiers));
+       memset(&busdev_client_notifiers, 0, sizeof(busdev_client_notifiers));
+       memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info));
+       memset(&livedump_info, 0, sizeof(livedump_info));
+       atomic_set(&livedump_info.buffers_in_use, 0);
 
        if (visorchipset_testvnic) {
-               ERRDRV("testvnic option no longer supported: (status = %d)\n",
-                      x);
                POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, x, DIAG_SEVERITY_ERR);
                rc = x;
-               goto Away;
+               goto cleanup;
        }
 
        addr = controlvm_get_channel_address();
        if (addr != 0) {
-               ControlVm_channel =
+               controlvm_channel =
                    visorchannel_create_with_lock
                    (addr,
                     sizeof(struct spar_controlvm_channel_protocol),
                     spar_controlvm_channel_protocol_uuid);
                if (SPAR_CONTROLVM_CHANNEL_OK_CLIENT(
-                               visorchannel_get_header(ControlVm_channel))) {
-                       LOGINF("Channel %s (ControlVm) discovered",
-                              visorchannel_id(ControlVm_channel, s));
+                               visorchannel_get_header(controlvm_channel))) {
                        initialize_controlvm_payload();
                } else {
-                       LOGERR("controlvm channel is invalid");
-                       visorchannel_destroy(ControlVm_channel);
-                       ControlVm_channel = NULL;
+                       visorchannel_destroy(controlvm_channel);
+                       controlvm_channel = NULL;
                        return -ENODEV;
                }
        } else {
-               LOGERR("no controlvm channel discovered");
                return -ENODEV;
        }
 
-       MajorDev = MKDEV(visorchipset_major, 0);
-       rc = visorchipset_file_init(MajorDev, &ControlVm_channel);
+       major_dev = MKDEV(visorchipset_major, 0);
+       rc = visorchipset_file_init(major_dev, &controlvm_channel);
        if (rc < 0) {
-               ERRDRV("visorchipset_file_init(MajorDev, &ControlVm_channel): error (status=%d)\n", rc);
                POSTCODE_LINUX_2(CHIPSET_INIT_FAILURE_PC, DIAG_SEVERITY_ERR);
-               goto Away;
+               goto cleanup;
        }
 
-       memset(&g_DiagMsgHdr, 0, sizeof(struct controlvm_message_header));
+       memset(&g_diag_msg_hdr, 0, sizeof(struct controlvm_message_header));
 
-       memset(&g_ChipSetMsgHdr, 0, sizeof(struct controlvm_message_header));
+       memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header));
 
-       memset(&g_DelDumpMsgHdr, 0, sizeof(struct controlvm_message_header));
+       memset(&g_del_dump_msg_hdr, 0, sizeof(struct controlvm_message_header));
 
-       Putfile_buffer_list_pool =
-           kmem_cache_create(Putfile_buffer_list_pool_name,
+       putfile_buffer_list_pool =
+           kmem_cache_create(putfile_buffer_list_pool_name,
                              sizeof(struct putfile_buffer_entry),
                              0, SLAB_HWCACHE_ALIGN, NULL);
-       if (!Putfile_buffer_list_pool) {
-               ERRDRV("failed to alloc Putfile_buffer_list_pool: (status=-1)\n");
+       if (!putfile_buffer_list_pool) {
                POSTCODE_LINUX_2(CHIPSET_INIT_FAILURE_PC, DIAG_SEVERITY_ERR);
                rc = -1;
-               goto Away;
+               goto cleanup;
        }
-       if (visorchipset_disable_controlvm) {
-               LOGINF("visorchipset_init:controlvm disabled");
-       } else {
+       if (!visorchipset_disable_controlvm) {
                /* if booting in a crash kernel */
                if (visorchipset_crash_kernel)
-                       INIT_DELAYED_WORK(&Periodic_controlvm_work,
+                       INIT_DELAYED_WORK(&periodic_controlvm_work,
                                          setup_crash_devices_work_queue);
                else
-                       INIT_DELAYED_WORK(&Periodic_controlvm_work,
+                       INIT_DELAYED_WORK(&periodic_controlvm_work,
                                          controlvm_periodic_work);
-               Periodic_controlvm_workqueue =
+               periodic_controlvm_workqueue =
                    create_singlethread_workqueue("visorchipset_controlvm");
 
-               if (Periodic_controlvm_workqueue == NULL) {
-                       ERRDRV("cannot create controlvm workqueue: (status=%d)\n",
-                              -ENOMEM);
+               if (!periodic_controlvm_workqueue) {
                        POSTCODE_LINUX_2(CREATE_WORKQUEUE_FAILED_PC,
                                         DIAG_SEVERITY_ERR);
                        rc = -ENOMEM;
-                       goto Away;
+                       goto cleanup;
                }
-               Most_recent_message_jiffies = jiffies;
-               Poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
-               rc = queue_delayed_work(Periodic_controlvm_workqueue,
-                                       &Periodic_controlvm_work, Poll_jiffies);
+               most_recent_message_jiffies = jiffies;
+               poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
+               rc = queue_delayed_work(periodic_controlvm_workqueue,
+                                       &periodic_controlvm_work, poll_jiffies);
                if (rc < 0) {
-                       ERRDRV("queue_delayed_work(Periodic_controlvm_workqueue, &Periodic_controlvm_work, Poll_jiffies): error (status=%d)\n", rc);
                        POSTCODE_LINUX_2(QUEUE_DELAYED_WORK_PC,
                                         DIAG_SEVERITY_ERR);
-                       goto Away;
+                       goto cleanup;
                }
-
        }
 
-       Visorchipset_platform_device.dev.devt = MajorDev;
-       if (platform_device_register(&Visorchipset_platform_device) < 0) {
-               ERRDRV("platform_device_register(visorchipset) failed: (status=-1)\n");
+       visorchipset_platform_device.dev.devt = major_dev;
+       if (platform_device_register(&visorchipset_platform_device) < 0) {
                POSTCODE_LINUX_2(DEVICE_REGISTER_FAILURE_PC, DIAG_SEVERITY_ERR);
                rc = -1;
-               goto Away;
+               goto cleanup;
        }
-       LOGINF("visorchipset device created");
        POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO);
        rc = 0;
-Away:
+cleanup:
        if (rc) {
-               LOGERR("visorchipset_init failed");
                POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc,
                                 POSTCODE_SEVERITY_ERR);
        }
@@ -2489,40 +2252,34 @@ Away:
 static void
 visorchipset_exit(void)
 {
-       char s[99];
-
        POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
 
        if (visorchipset_disable_controlvm) {
                ;
        } else {
-               cancel_delayed_work(&Periodic_controlvm_work);
-               flush_workqueue(Periodic_controlvm_workqueue);
-               destroy_workqueue(Periodic_controlvm_workqueue);
-               Periodic_controlvm_workqueue = NULL;
-               destroy_controlvm_payload_info(&ControlVm_payload_info);
+               cancel_delayed_work(&periodic_controlvm_work);
+               flush_workqueue(periodic_controlvm_workqueue);
+               destroy_workqueue(periodic_controlvm_workqueue);
+               periodic_controlvm_workqueue = NULL;
+               destroy_controlvm_payload_info(&controlvm_payload_info);
        }
-       Test_Vnic_channel = NULL;
-       if (Putfile_buffer_list_pool) {
-               kmem_cache_destroy(Putfile_buffer_list_pool);
-               Putfile_buffer_list_pool = NULL;
+       if (putfile_buffer_list_pool) {
+               kmem_cache_destroy(putfile_buffer_list_pool);
+               putfile_buffer_list_pool = NULL;
        }
 
        cleanup_controlvm_structures();
 
-       memset(&g_DiagMsgHdr, 0, sizeof(struct controlvm_message_header));
+       memset(&g_diag_msg_hdr, 0, sizeof(struct controlvm_message_header));
 
-       memset(&g_ChipSetMsgHdr, 0, sizeof(struct controlvm_message_header));
+       memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header));
 
-       memset(&g_DelDumpMsgHdr, 0, sizeof(struct controlvm_message_header));
+       memset(&g_del_dump_msg_hdr, 0, sizeof(struct controlvm_message_header));
 
-       LOGINF("Channel %s (ControlVm) disconnected",
-              visorchannel_id(ControlVm_channel, s));
-       visorchannel_destroy(ControlVm_channel);
+       visorchannel_destroy(controlvm_channel);
 
-       visorchipset_file_cleanup();
+       visorchipset_file_cleanup(visorchipset_platform_device.dev.devt);
        POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
-       LOGINF("chipset driver unloaded");
 }
 
 module_param_named(testvnic, visorchipset_testvnic, int, S_IRUGO);
index 74b474eac25265d530bb0bca3b16ca90137481a1..be9c2cf890ccd72678abb357e16acc2fc128a6cd 100644 (file)
@@ -4,7 +4,6 @@
 
 config UNISYS_VISORUTIL
        tristate "Unisys visorutil driver"
-       depends on UNISYSSPAR && HAS_IOMEM
        ---help---
        If you say Y here, you will enable the Unisys visorutil driver.
 
index d871bbb78cef420118a7ca5fece80e43bb00f008..d9ab5a36e3bf0b026274540d2f23f6617e0b471c 100644 (file)
@@ -4,7 +4,6 @@
 
 obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil.o
 
-visorutil-y := charqueue.o  easyproc.o  periodic_work.o  procobjecttree.o  \
-               memregion_direct.o visorkmodutils.o
+visorutil-y := charqueue.o  periodic_work.o  memregion_direct.o visorkmodutils.o
 
 ccflags-y += -Idrivers/staging/unisys/include
index ac7acb7c5b7955eb63c1c7403eebb314f2fc5cb9..c91752a2d06b6f385f137a08a44cd82622c321c1 100644 (file)
@@ -36,13 +36,11 @@ struct charqueue {
 struct charqueue *visor_charqueue_create(ulong nslots)
 {
        int alloc_size = sizeof(struct charqueue) + nslots + 1;
-       struct charqueue *cq = kmalloc(alloc_size, GFP_KERNEL|__GFP_NORETRY);
+       struct charqueue *cq;
 
-       if (cq == NULL) {
-               ERRDRV("visor_charqueue_create allocation failed (alloc_size=%d)",
-                      alloc_size);
+       cq = kmalloc(alloc_size, GFP_KERNEL|__GFP_NORETRY);
+       if (cq == NULL)
                return NULL;
-       }
        cq->alloc_size = alloc_size;
        cq->nslots = nslots;
        cq->head = 0;
index 56c1f79a54b0487ebd83297a1a8d77f96ea6ea06..f46a776b935bd4809fb9469eee247c479989d4a1 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef __CHARQUEUE_H__
 #define __CHARQUEUE_H__
 
-#include "uniklog.h"
 #include "timskmod.h"
 
 /* struct charqueue is an opaque structure to users.
diff --git a/drivers/staging/unisys/visorutil/easyproc.c b/drivers/staging/unisys/visorutil/easyproc.c
deleted file mode 100644 (file)
index 40f1ae9..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-/* Copyright (C) 2010 - 2013 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 distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-/** @file *********************************************************************
- *
- *  Handle procfs-specific tasks.
- *  Note that this file does not know about any module-specific things, nor
- *  does it know anything about what information to reveal as part of the proc
- *  entries.  The 2 functions that take care of displaying device and
- *  driver specific information are passed as parameters to
- *  visor_easyproc_InitDriver().
- *
- *      void show_device_info(struct seq_file *seq, void *p);
- *      void show_driver_info(struct seq_file *seq);
- *
- *  The second parameter to show_device_info is actually a pointer to the
- *  device-specific info to show.  It is the context that was originally
- *  passed to visor_easyproc_InitDevice().
- *
- ******************************************************************************
- */
-
-#include <linux/proc_fs.h>
-
-#include "uniklog.h"
-#include "timskmod.h"
-#include "easyproc.h"
-
-#define MYDRVNAME "easyproc"
-
-
-
-/*
- *   /proc/<ProcId>                              ProcDir
- *   /proc/<ProcId>/driver                       ProcDriverDir
- *   /proc/<ProcId>/driver/diag                  ProcDriverDiagFile
- *   /proc/<ProcId>/device                       ProcDeviceDir
- *   /proc/<ProcId>/device/0                     procDevicexDir
- *   /proc/<ProcId>/device/0/diag                procDevicexDiagFile
- */
-
-
-static ssize_t proc_write_device(struct file *file, const char __user *buffer,
-                                size_t count, loff_t *ppos);
-static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
-                                size_t count, loff_t *ppos);
-
-static struct proc_dir_entry *
-       createProcDir(char *name, struct proc_dir_entry *parent)
-{
-       struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent);
-
-       if (p == NULL)
-               ERRDRV("failed to create /proc directory %s", name);
-       return p;
-}
-
-static int seq_show_driver(struct seq_file *seq, void *offset);
-static int proc_open_driver(struct inode *inode, struct file *file)
-{
-       return single_open(file, seq_show_driver, PDE_DATA(inode));
-}
-static const struct file_operations proc_fops_driver = {
-       .open = proc_open_driver,
-       .read = seq_read,
-       .write = proc_write_driver,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static int seq_show_device(struct seq_file *seq, void *offset);
-static int seq_show_device_property(struct seq_file *seq, void *offset);
-static int proc_open_device(struct inode *inode, struct file *file)
-{
-       return single_open(file, seq_show_device, PDE_DATA(inode));
-}
-static const struct file_operations proc_fops_device = {
-       .open = proc_open_device,
-       .read = seq_read,
-       .write = proc_write_device,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-static int proc_open_device_property(struct inode *inode, struct file *file)
-{
-       return single_open(file, seq_show_device_property, PDE_DATA(inode));
-}
-static const struct file_operations proc_fops_device_property = {
-       .open = proc_open_device_property,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-
-
-void visor_easyproc_InitDriver(struct easyproc_driver_info *pdriver,
-                              char *procId,
-                              void (*show_driver_info)(struct seq_file *),
-                              void (*show_device_info)(struct seq_file *,
-                                                       void *))
-{
-       memset(pdriver, 0, sizeof(struct easyproc_driver_info));
-       pdriver->ProcId = procId;
-       if (pdriver->ProcId == NULL)
-               ERRDRV("ProcId cannot be NULL (trouble ahead)!");
-       pdriver->Show_driver_info = show_driver_info;
-       pdriver->Show_device_info = show_device_info;
-       if (pdriver->ProcDir == NULL)
-               pdriver->ProcDir = createProcDir(pdriver->ProcId, NULL);
-       if ((pdriver->ProcDir != NULL) && (pdriver->ProcDriverDir == NULL))
-               pdriver->ProcDriverDir = createProcDir("driver",
-                                                      pdriver->ProcDir);
-       if ((pdriver->ProcDir != NULL) && (pdriver->ProcDeviceDir == NULL))
-               pdriver->ProcDeviceDir = createProcDir("device",
-                                                      pdriver->ProcDir);
-       if ((pdriver->ProcDriverDir != NULL) &&
-           (pdriver->ProcDriverDiagFile == NULL)) {
-               pdriver->ProcDriverDiagFile =
-                       proc_create_data("diag", 0,
-                                        pdriver->ProcDriverDir,
-                                        &proc_fops_driver, pdriver);
-               if (pdriver->ProcDriverDiagFile == NULL)
-                       ERRDRV("failed to register /proc/%s/driver/diag entry",
-                              pdriver->ProcId);
-       }
-}
-EXPORT_SYMBOL_GPL(visor_easyproc_InitDriver);
-
-
-
-void visor_easyproc_InitDriverEx(struct easyproc_driver_info *pdriver,
-                                char *procId,
-                                void (*show_driver_info)(struct seq_file *),
-                                void (*show_device_info)(struct seq_file *,
-                                                         void *),
-                                void (*write_driver_info)(char *buf,
-                                                          size_t count,
-                                                          loff_t *ppos),
-                                void (*write_device_info)(char *buf,
-                                                          size_t count,
-                                                          loff_t *ppos,
-                                                          void *p))
-{
-       visor_easyproc_InitDriver(pdriver, procId,
-                                 show_driver_info, show_device_info);
-       pdriver->Write_driver_info = write_driver_info;
-       pdriver->Write_device_info = write_device_info;
-}
-EXPORT_SYMBOL_GPL(visor_easyproc_InitDriverEx);
-
-
-
-void visor_easyproc_DeInitDriver(struct easyproc_driver_info *pdriver)
-{
-       if (pdriver->ProcDriverDiagFile != NULL) {
-               remove_proc_entry("diag", pdriver->ProcDriverDir);
-               pdriver->ProcDriverDiagFile = NULL;
-       }
-       if (pdriver->ProcDriverDir != NULL) {
-               remove_proc_entry("driver", pdriver->ProcDir);
-               pdriver->ProcDriverDir = NULL;
-       }
-       if (pdriver->ProcDeviceDir != NULL) {
-               remove_proc_entry("device", pdriver->ProcDir);
-               pdriver->ProcDeviceDir = NULL;
-       }
-       if (pdriver->ProcDir != NULL) {
-               remove_proc_entry(pdriver->ProcId, NULL);
-               pdriver->ProcDir = NULL;
-       }
-       pdriver->ProcId = NULL;
-       pdriver->Show_driver_info = NULL;
-       pdriver->Show_device_info = NULL;
-       pdriver->Write_driver_info = NULL;
-       pdriver->Write_device_info = NULL;
-}
-EXPORT_SYMBOL_GPL(visor_easyproc_DeInitDriver);
-
-
-
-void visor_easyproc_InitDevice(struct easyproc_driver_info *pdriver,
-                              struct easyproc_device_info *p, int devno,
-                              void *devdata)
-{
-       if ((pdriver->ProcDeviceDir != NULL) && (p->procDevicexDir == NULL)) {
-               char s[29];
-
-               sprintf(s, "%d", devno);
-               p->procDevicexDir = createProcDir(s, pdriver->ProcDeviceDir);
-               p->devno = devno;
-       }
-       p->devdata = devdata;
-       p->pdriver = pdriver;
-       p->devno = devno;
-       if ((p->procDevicexDir != NULL) && (p->procDevicexDiagFile == NULL)) {
-               p->procDevicexDiagFile =
-                       proc_create_data("diag", 0, p->procDevicexDir,
-                                        &proc_fops_device, p);
-               if (p->procDevicexDiagFile == NULL)
-                       ERRDEVX(devno, "failed to register /proc/%s/device/%d/diag entry",
-                               pdriver->ProcId, devno
-                              );
-       }
-       memset(&(p->device_property_info[0]), 0,
-              sizeof(p->device_property_info));
-}
-EXPORT_SYMBOL_GPL(visor_easyproc_InitDevice);
-
-
-
-void visor_easyproc_CreateDeviceProperty(struct easyproc_device_info *p,
-                                        void (*show_property_info)
-                                        (struct seq_file *, void *),
-                                        char *property_name)
-{
-       size_t i;
-       struct easyproc_device_property_info *px = NULL;
-
-       if (p->procDevicexDir == NULL) {
-               ERRDRV("state error");
-               return;
-       }
-       for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
-               if (p->device_property_info[i].procEntry == NULL) {
-                       px = &(p->device_property_info[i]);
-                       break;
-               }
-       }
-       if (!px) {
-               ERRDEVX(p->devno, "too many device properties");
-               return;
-       }
-       px->devdata = p->devdata;
-       px->pdriver = p->pdriver;
-       px->procEntry = proc_create_data(property_name, 0, p->procDevicexDir,
-                                        &proc_fops_device_property, px);
-       if (strlen(property_name)+1 > sizeof(px->property_name)) {
-               ERRDEVX(p->devno, "device property name %s too long",
-                       property_name);
-               return;
-       }
-       strcpy(px->property_name, property_name);
-       if (px->procEntry == NULL) {
-               ERRDEVX(p->devno,
-                       "failed to register /proc/%s/device/%d/%s entry",
-                       p->pdriver->ProcId, p->devno, property_name);
-               return;
-       }
-       px->show_device_property_info = show_property_info;
-}
-EXPORT_SYMBOL_GPL(visor_easyproc_CreateDeviceProperty);
-
-
-
-void visor_easyproc_DeInitDevice(struct easyproc_driver_info *pdriver,
-                                struct easyproc_device_info *p, int devno)
-{
-       size_t i;
-
-       for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
-               if (p->device_property_info[i].procEntry != NULL) {
-                       struct easyproc_device_property_info *px =
-                               &(p->device_property_info[i]);
-                       remove_proc_entry(px->property_name, p->procDevicexDir);
-                       px->procEntry = NULL;
-               }
-       }
-       if (p->procDevicexDiagFile != NULL) {
-               remove_proc_entry("diag", p->procDevicexDir);
-               p->procDevicexDiagFile = NULL;
-       }
-       if (p->procDevicexDir != NULL) {
-               char s[29];
-
-               sprintf(s, "%d", devno);
-               remove_proc_entry(s, pdriver->ProcDeviceDir);
-               p->procDevicexDir = NULL;
-       }
-       p->devdata = NULL;
-       p->pdriver = NULL;
-}
-EXPORT_SYMBOL_GPL(visor_easyproc_DeInitDevice);
-
-
-
-static int seq_show_driver(struct seq_file *seq, void *offset)
-{
-       struct easyproc_driver_info *p =
-               (struct easyproc_driver_info *)(seq->private);
-       if (!p)
-               return 0;
-       (*(p->Show_driver_info))(seq);
-       return 0;
-}
-
-
-
-static int seq_show_device(struct seq_file *seq, void *offset)
-{
-       struct easyproc_device_info *p =
-               (struct easyproc_device_info *)(seq->private);
-       if ((!p) || (!(p->pdriver)))
-               return 0;
-       (*(p->pdriver->Show_device_info))(seq, p->devdata);
-       return 0;
-}
-
-
-
-static int seq_show_device_property(struct seq_file *seq, void *offset)
-{
-       struct easyproc_device_property_info *p =
-               (struct easyproc_device_property_info *)(seq->private);
-       if ((!p) || (!(p->show_device_property_info)))
-               return 0;
-       (*(p->show_device_property_info))(seq, p->devdata);
-       return 0;
-}
-
-
-
-static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
-                                size_t count, loff_t *ppos)
-{
-       struct seq_file *seq = (struct seq_file *)file->private_data;
-       struct easyproc_driver_info *p = NULL;
-       char local_buf[256];
-
-       if (seq == NULL)
-               return 0;
-       p = (struct easyproc_driver_info *)(seq->private);
-       if ((!p) || (!(p->Write_driver_info)))
-               return 0;
-       if (count >= sizeof(local_buf))
-               return -ENOMEM;
-       if (copy_from_user(local_buf, buffer, count))
-               return -EFAULT;
-       local_buf[count] = '\0';  /* be friendly */
-       (*(p->Write_driver_info))(local_buf, count, ppos);
-       return count;
-}
-
-
-
-static ssize_t proc_write_device(struct file *file, const char __user *buffer,
-                                size_t count, loff_t *ppos)
-{
-       struct seq_file *seq = (struct seq_file *)file->private_data;
-       struct easyproc_device_info *p = NULL;
-       char local_buf[256];
-
-       if (seq == NULL)
-               return 0;
-       p = (struct easyproc_device_info *)(seq->private);
-       if ((!p) || (!(p->pdriver)) || (!(p->pdriver->Write_device_info)))
-               return 0;
-       if (count >= sizeof(local_buf))
-               return -ENOMEM;
-       if (copy_from_user(local_buf, buffer, count))
-               return -EFAULT;
-       local_buf[count] = '\0';  /* be friendly */
-       (*(p->pdriver->Write_device_info))(local_buf, count, ppos, p->devdata);
-       return count;
-}
diff --git a/drivers/staging/unisys/visorutil/easyproc.h b/drivers/staging/unisys/visorutil/easyproc.h
deleted file mode 100644 (file)
index 6ce7d5e..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/* easyproc.h
- *
- * Copyright (C) 2010 - 2013 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 distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-/** @file *********************************************************************
- *
- *  This describes the interfaces necessary for a simple /proc file
- *  implementation for a driver.
- *
- ******************************************************************************
- */
-
-#ifndef __EASYPROC_H__
-#define __EASYPROC_H__
-
-#include "timskmod.h"
-
-
-struct easyproc_driver_info {
-       struct proc_dir_entry *ProcDir;
-       struct proc_dir_entry *ProcDriverDir;
-       struct proc_dir_entry *ProcDriverDiagFile;
-       struct proc_dir_entry *ProcDeviceDir;
-       char *ProcId;
-       void (*Show_device_info)(struct seq_file *seq, void *p);
-       void (*Show_driver_info)(struct seq_file *seq);
-       void (*Write_device_info)(char *buf, size_t count,
-                                 loff_t *ppos, void *p);
-       void (*Write_driver_info)(char *buf, size_t count, loff_t *ppos);
-};
-
-/* property is a file under /proc/<x>/device/<x>/<property_name> */
-struct easyproc_device_property_info {
-       char property_name[25];
-       struct proc_dir_entry *procEntry;
-       struct easyproc_driver_info *pdriver;
-       void *devdata;
-       void (*show_device_property_info)(struct seq_file *seq, void *p);
-};
-
-struct easyproc_device_info {
-       struct proc_dir_entry *procDevicexDir;
-       struct proc_dir_entry *procDevicexDiagFile;
-       struct easyproc_driver_info *pdriver;
-       void *devdata;
-       int devno;
-       /*  allow for a number of custom properties for each device: */
-       struct easyproc_device_property_info device_property_info[10];
-};
-
-void visor_easyproc_InitDevice(struct easyproc_driver_info *pdriver,
-                              struct easyproc_device_info *p, int devno,
-                              void *devdata);
-void visor_easyproc_DeInitDevice(struct easyproc_driver_info *pdriver,
-                                struct easyproc_device_info *p, int devno);
-void visor_easyproc_InitDriver(struct easyproc_driver_info *pdriver,
-                              char *procId,
-                              void (*show_driver_info)(struct seq_file *),
-                              void (*show_device_info)(struct seq_file *,
-                                                       void *));
-void visor_easyproc_InitDriverEx(struct easyproc_driver_info *pdriver,
-                                char *procId,
-                                void (*show_driver_info)(struct seq_file *),
-                                void (*show_device_info)(struct seq_file *,
-                                                         void *),
-                                void (*Write_driver_info)(char *buf,
-                                                          size_t count,
-                                                          loff_t *ppos),
-                                void (*Write_device_info)(char *buf,
-                                                          size_t count,
-                                                          loff_t *ppos,
-                                                          void *p));
-void visor_easyproc_DeInitDriver(struct easyproc_driver_info *pdriver);
-void visor_easyproc_CreateDeviceProperty(struct easyproc_device_info *p,
-                                        void (*show_property_info)
-                                        (struct seq_file *, void *),
-                                        char *property_name);
-
-#endif
index 33522cc8c22c9687d9c9fee70c764a7cfea5dcd1..eb7422fbe20f4f08db705e8ce6f982450975d750 100644 (file)
@@ -20,7 +20,6 @@
  *  channel memory (in main memory of the host system) from code running in
  *  a virtual partition.
  */
-#include "uniklog.h"
 #include "timskmod.h"
 #include "memregion.h"
 
@@ -41,12 +40,12 @@ struct memregion *
 visor_memregion_create(HOSTADDRESS physaddr, ulong nbytes)
 {
        struct memregion *rc = NULL;
-       struct memregion *memregion = kzalloc(sizeof(*memregion),
-                                             GFP_KERNEL | __GFP_NORETRY);
-       if (memregion == NULL) {
-               ERRDRV("visor_memregion_create allocation failed");
+       struct memregion *memregion;
+
+       memregion = kzalloc(sizeof(*memregion), GFP_KERNEL | __GFP_NORETRY);
+       if (memregion == NULL)
                return NULL;
-       }
+
        memregion->physaddr = physaddr;
        memregion->nbytes = nbytes;
        memregion->overlapped = FALSE;
@@ -70,25 +69,19 @@ visor_memregion_create_overlapped(struct memregion *parent, ulong offset,
 {
        struct memregion *memregion = NULL;
 
-       if (parent == NULL) {
-               ERRDRV("%s parent is NULL", __func__);
+       if (parent == NULL)
                return NULL;
-       }
-       if (parent->mapped == NULL) {
-               ERRDRV("%s parent is not mapped!", __func__);
+
+       if (parent->mapped == NULL)
                return NULL;
-       }
+
        if ((offset >= parent->nbytes) ||
-           ((offset + nbytes) >= parent->nbytes)) {
-               ERRDRV("%s range (%lu,%lu) out of parent range",
-                      __func__, offset, nbytes);
+           ((offset + nbytes) >= parent->nbytes))
                return NULL;
-       }
+
        memregion = kzalloc(sizeof(*memregion), GFP_KERNEL|__GFP_NORETRY);
-       if (memregion == NULL) {
-               ERRDRV("%s allocation failed", __func__);
+       if (memregion == NULL)
                return NULL;
-       }
 
        memregion->physaddr = parent->physaddr + offset;
        memregion->nbytes = nbytes;
@@ -106,17 +99,11 @@ mapit(struct memregion *memregion)
        ulong nbytes = memregion->nbytes;
 
        memregion->requested = FALSE;
-       if (!request_mem_region(physaddr, nbytes, MYDRVNAME))
-               ERRDRV("cannot reserve channel memory @0x%lx for 0x%lx-- no big deal",
-                      physaddr, nbytes);
-       else
+       if (request_mem_region(physaddr, nbytes, MYDRVNAME))
                memregion->requested = TRUE;
        memregion->mapped = ioremap_cache(physaddr, nbytes);
-       if (memregion->mapped == NULL) {
-               ERRDRV("cannot ioremap_cache channel memory @0x%lx for 0x%lx",
-                      physaddr, nbytes);
+       if (!memregion->mapped)
                return FALSE;
-       }
        return TRUE;
 }
 
@@ -180,10 +167,9 @@ memregion_readwrite(BOOL is_write,
                    struct memregion *memregion, ulong offset,
                    void *local, ulong nbytes)
 {
-       if (offset + nbytes > memregion->nbytes) {
-               ERRDRV("memregion_readwrite offset out of range!!");
+       if (offset + nbytes > memregion->nbytes)
                return -EIO;
-       }
+
        if (is_write)
                memcpy_toio(memregion->mapped + offset, local, nbytes);
        else
index 0908bf929401be23dd35e2845487b1e007889709..abbfb48894f309e5405f9d7ae2ab3751786bc956 100644 (file)
@@ -19,7 +19,6 @@
  *  Helper functions to schedule periodic work in Linux kernel mode.
  */
 
-#include "uniklog.h"
 #include "timskmod.h"
 #include "periodic_work.h"
 
@@ -90,7 +89,6 @@ BOOL visor_periodic_work_nextperiod(struct periodic_work *pw)
                goto unlock;
        } else if (queue_delayed_work(pw->workqueue, &pw->work,
                                      pw->jiffy_interval) < 0) {
-               ERRDEV(pw->devnam, "queue_delayed_work failed!");
                pw->is_scheduled = FALSE;
                rc = FALSE;
                goto unlock;
@@ -116,15 +114,12 @@ BOOL visor_periodic_work_start(struct periodic_work *pw)
                goto unlock;
        }
        if (pw->want_to_stop) {
-               ERRDEV(pw->devnam,
-                      "dev_start_periodic_work failed!");
                rc = FALSE;
                goto unlock;
        }
        INIT_DELAYED_WORK(&pw->work, &periodic_work_func);
        if (queue_delayed_work(pw->workqueue, &pw->work,
                               pw->jiffy_interval) < 0) {
-               ERRDEV(pw->devnam, "%s queue_delayed_work failed!", __func__);
                rc = FALSE;
                goto unlock;
        }
@@ -182,7 +177,7 @@ BOOL visor_periodic_work_stop(struct periodic_work *pw)
                        /* We get here if the delayed work was pending as
                         * delayed work, but was NOT run.
                         */
-                       ASSERT(pw->is_scheduled);
+                       WARN_ON(!pw->is_scheduled);
                        pw->is_scheduled = FALSE;
                } else {
                        /* If we get here, either the delayed work:
@@ -197,14 +192,6 @@ BOOL visor_periodic_work_stop(struct periodic_work *pw)
                }
                if (pw->is_scheduled) {
                        write_unlock(&pw->lock);
-                       WARNDEV(pw->devnam,
-                               "waiting for delayed work...");
-                       /* We rely on the delayed work function running here,
-                        * and eventually calling
-                        * visor_periodic_work_nextperiod(),
-                        * which will see that want_to_stop is set, and
-                        * subsequently clear is_scheduled.
-                        */
                        SLEEPJIFFIES(10);
                        write_lock(&pw->lock);
                } else {
diff --git a/drivers/staging/unisys/visorutil/procobjecttree.c b/drivers/staging/unisys/visorutil/procobjecttree.c
deleted file mode 100644 (file)
index 82279ca..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-/* procobjecttree.c
- *
- * Copyright (C) 2010 - 2013 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 distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- */
-
-#include "procobjecttree.h"
-
-#define MYDRVNAME "procobjecttree"
-
-
-
-/** This is context info that we stash in each /proc file entry, which we
- *  need in order to call the callback function that supplies the /proc read
- *  info for that file.
- */
-struct proc_dir_entry_context {
-       void (*show_property)(struct seq_file *, void *, int);
-       MYPROCOBJECT *procObject;
-       int propertyIndex;
-
-};
-
-/** This describes the attributes of a tree rooted at
- *  <procDirRoot>/<name[0]>/<name[1]>/...
- *  Properties for each object of this type will be located under
- *  <procDirRoot>/<name[0]>/<name[1]>/.../<objectName>/<propertyName>.
- */
-struct MYPROCTYPE_Tag {
-       const char **name;  /**< node names for this type, ending with NULL */
-       int nNames;         /**< num of node names in <name> */
-
-       /** root dir for this type tree in /proc */
-       struct proc_dir_entry *procDirRoot;
-
-       struct proc_dir_entry **procDirs;  /**< for each node in <name> */
-
-       /** bottom dir where objects will be rooted; i.e., this is
-        *  <procDirRoot>/<name[0]>/<name[1]>/.../, which is the same as the
-        *  last entry in the <procDirs> array. */
-       struct proc_dir_entry *procDir;
-
-       /** name for each property that objects of this type can have */
-       const char **propertyNames;
-
-       int nProperties;       /**< num of names in <propertyNames> */
-
-       /** Call this, passing MYPROCOBJECT.context and the property index
-        *  whenever someone reads the proc entry */
-       void (*show_property)(struct seq_file *, void *, int);
-};
-
-
-
-struct MYPROCOBJECT_Tag {
-       MYPROCTYPE *type;
-
-       /** This is the name of the dir node in /proc under which the
-        *  properties of this object will appear as files. */
-       char *name;
-
-       int namesize;   /**< number of bytes allocated for name */
-       void *context;  /**< passed to MYPROCTYPE.show_property */
-
-       /** <type.procDirRoot>/<type.name[0]>/<type.name[1]>/.../<name> */
-       struct proc_dir_entry *procDir;
-
-       /** a proc dir entry for each of the properties of the object;
-        *  properties are identified in MYPROCTYPE.propertyNames, so each of
-        *  the <procDirProperties> describes a single file like
-        *  <type.procDirRoot>/<type.name[0]>/<type.name[1]>/...
-        *           /<name>/<propertyName>
-        */
-       struct proc_dir_entry **procDirProperties;
-
-       /** this is a holding area for the context information that is needed
-        *  to run the /proc callback function */
-       struct proc_dir_entry_context *procDirPropertyContexts;
-};
-
-
-
-static struct proc_dir_entry *
-createProcDir(const char *name, struct proc_dir_entry *parent)
-{
-       struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent);
-
-       if (p == NULL)
-               ERRDRV("failed to create /proc directory %s", name);
-       return p;
-}
-
-static struct proc_dir_entry *
-createProcFile(const char *name, struct proc_dir_entry *parent,
-              const struct file_operations *fops, void *data)
-{
-       struct proc_dir_entry *p = proc_create_data(name, 0, parent,
-                                                   fops, data);
-       if (p == NULL)
-               ERRDRV("failed to create /proc file %s", name);
-       return p;
-}
-
-static int seq_show(struct seq_file *seq, void *offset);
-static int proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, seq_show, PDE_DATA(inode));
-}
-
-static const struct file_operations proc_fops = {
-       .open = proc_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-
-
-MYPROCTYPE *visor_proc_CreateType(struct proc_dir_entry *procDirRoot,
-                                 const char **name,
-                                 const char **propertyNames,
-                                 void (*show_property)(struct seq_file *,
-                                                       void *, int))
-{
-       int i = 0;
-       MYPROCTYPE *rc = NULL, *type = NULL;
-       struct proc_dir_entry *parent = NULL;
-
-       if (procDirRoot == NULL) {
-               ERRDRV("procDirRoot cannot be NULL!\n");
-               goto Away;
-       }
-       if (name == NULL || name[0] == NULL) {
-               ERRDRV("name must contain at least 1 node name!\n");
-               goto Away;
-       }
-       type = kzalloc(sizeof(MYPROCTYPE), GFP_KERNEL | __GFP_NORETRY);
-       if (type == NULL) {
-               ERRDRV("out of memory\n");
-               goto Away;
-       }
-       type->name = name;
-       type->propertyNames = propertyNames;
-       type->nProperties = 0;
-       type->nNames = 0;
-       type->show_property = show_property;
-       type->procDirRoot = procDirRoot;
-       if (type->propertyNames != NULL)
-               while (type->propertyNames[type->nProperties] != NULL)
-                       type->nProperties++;
-       while (type->name[type->nNames] != NULL)
-               type->nNames++;
-       type->procDirs = kzalloc((type->nNames + 1) *
-                                sizeof(struct proc_dir_entry *),
-                                GFP_KERNEL | __GFP_NORETRY);
-       if (type->procDirs == NULL) {
-               ERRDRV("out of memory\n");
-               goto Away;
-       }
-       parent = procDirRoot;
-       for (i = 0; i < type->nNames; i++) {
-               type->procDirs[i] = createProcDir(type->name[i], parent);
-               if (type->procDirs[i] == NULL) {
-                       rc = NULL;
-                       goto Away;
-               }
-               parent = type->procDirs[i];
-       }
-       type->procDir = type->procDirs[type->nNames-1];
-       rc = type;
-Away:
-       if (rc == NULL) {
-               if (type != NULL) {
-                       visor_proc_DestroyType(type);
-                       type = NULL;
-               }
-       }
-       return rc;
-}
-EXPORT_SYMBOL_GPL(visor_proc_CreateType);
-
-
-
-void visor_proc_DestroyType(MYPROCTYPE *type)
-{
-       if (type == NULL)
-               return;
-       if (type->procDirs != NULL) {
-               int i = type->nNames-1;
-
-               while (i >= 0) {
-                       if (type->procDirs[i] != NULL) {
-                               struct proc_dir_entry *parent = NULL;
-
-                               if (i == 0)
-                                       parent = type->procDirRoot;
-                               else
-                                       parent = type->procDirs[i-1];
-                               remove_proc_entry(type->name[i], parent);
-                       }
-                       i--;
-               }
-               kfree(type->procDirs);
-               type->procDirs = NULL;
-       }
-       kfree(type);
-}
-EXPORT_SYMBOL_GPL(visor_proc_DestroyType);
-
-
-
-MYPROCOBJECT *visor_proc_CreateObject(MYPROCTYPE *type,
-                                     const char *name, void *context)
-{
-       MYPROCOBJECT *obj = NULL, *rc = NULL;
-       int i = 0;
-
-       if (type == NULL) {
-               ERRDRV("type cannot be NULL\n");
-               goto Away;
-       }
-       obj = kzalloc(sizeof(MYPROCOBJECT), GFP_KERNEL | __GFP_NORETRY);
-       if (obj == NULL) {
-               ERRDRV("out of memory\n");
-               goto Away;
-       }
-       obj->type = type;
-       obj->context = context;
-       if (name == NULL) {
-               obj->name = NULL;
-               obj->procDir = type->procDir;
-       } else {
-               obj->namesize = strlen(name)+1;
-               obj->name = kmalloc(obj->namesize, GFP_KERNEL | __GFP_NORETRY);
-               if (obj->name == NULL) {
-                       obj->namesize = 0;
-                       ERRDRV("out of memory\n");
-                       goto Away;
-               }
-               strcpy(obj->name, name);
-               obj->procDir = createProcDir(obj->name, type->procDir);
-               if (obj->procDir == NULL)
-                       goto Away;
-       }
-       obj->procDirPropertyContexts =
-               kzalloc((type->nProperties + 1) *
-                       sizeof(struct proc_dir_entry_context),
-                       GFP_KERNEL | __GFP_NORETRY);
-       if (obj->procDirPropertyContexts == NULL) {
-               ERRDRV("out of memory\n");
-               goto Away;
-       }
-       obj->procDirProperties = kzalloc((type->nProperties + 1) *
-                                        sizeof(struct proc_dir_entry *),
-                                        GFP_KERNEL | __GFP_NORETRY);
-       if (obj->procDirProperties == NULL) {
-               ERRDRV("out of memory\n");
-               goto Away;
-       }
-       for (i = 0; i < type->nProperties; i++) {
-               obj->procDirPropertyContexts[i].procObject = obj;
-               obj->procDirPropertyContexts[i].propertyIndex = i;
-               obj->procDirPropertyContexts[i].show_property =
-                       type->show_property;
-               if (type->propertyNames[i][0] != '\0') {
-                       /* only create properties that have names */
-                       obj->procDirProperties[i] =
-                               createProcFile(type->propertyNames[i],
-                                       obj->procDir, &proc_fops,
-                                       &obj->procDirPropertyContexts[i]);
-                       if (obj->procDirProperties[i] == NULL) {
-                               rc = NULL;
-                               goto Away;
-                       }
-               }
-       }
-       rc = obj;
-Away:
-       if (rc == NULL) {
-               if (obj != NULL) {
-                       visor_proc_DestroyObject(obj);
-                       obj = NULL;
-               }
-       }
-       return rc;
-}
-EXPORT_SYMBOL_GPL(visor_proc_CreateObject);
-
-
-
-void visor_proc_DestroyObject(MYPROCOBJECT *obj)
-{
-       MYPROCTYPE *type = NULL;
-
-       if (obj == NULL)
-               return;
-       type = obj->type;
-       if (type == NULL)
-               return;
-       if (obj->procDirProperties != NULL) {
-               int i = 0;
-
-               for (i = 0; i < type->nProperties; i++) {
-                       if (obj->procDirProperties[i] != NULL) {
-                               remove_proc_entry(type->propertyNames[i],
-                                                 obj->procDir);
-                               obj->procDirProperties[i] = NULL;
-                       }
-               }
-               kfree(obj->procDirProperties);
-               obj->procDirProperties = NULL;
-       }
-
-       kfree(obj->procDirPropertyContexts);
-       obj->procDirPropertyContexts = NULL;
-
-       if (obj->procDir != NULL) {
-               if (obj->name != NULL)
-                       remove_proc_entry(obj->name, type->procDir);
-               obj->procDir = NULL;
-       }
-
-       kfree(obj->name);
-       obj->name = NULL;
-       kfree(obj);
-}
-EXPORT_SYMBOL_GPL(visor_proc_DestroyObject);
-
-
-
-static int seq_show(struct seq_file *seq, void *offset)
-{
-       struct proc_dir_entry_context *ctx = seq->private;
-
-       if (ctx == NULL) {
-               ERRDRV("I don't have a freakin' clue...");
-               return 0;
-       }
-       (*ctx->show_property)(seq, ctx->procObject->context,
-                             ctx->propertyIndex);
-       return 0;
-}
index 556e2642d2d976f1ff829792d1583491f2fa479b..62f0f7046e1734d4c697642c5563dd320da63335 100644 (file)
@@ -15,7 +15,6 @@
  * details.
  */
 
-#include "uniklog.h"
 #include "timskmod.h"
 
 #define MYDRVNAME "timskmodutils"
index 84c5a07e8f6a70b215664b2541c99bf66c0066c7..eabbcc710a2024d68d9e2c69c9bb88b9d3b5b179 100644 (file)
@@ -13,7 +13,6 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
index da34d5529f5154d35f259ec81eca147e868cf3e1..77901b345a716f7c3c0d7dc0347d910fba810ae0 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
index 8b1f533314331e5d9882316259954ef42254d355..19ba749bb122c92e5ad22a8b8b360c9489adefe7 100644 (file)
@@ -17,6 +17,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/atomic.h>
 #include <linux/cdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
@@ -41,7 +42,6 @@
 
 #include "vme_user.h"
 
-static DEFINE_MUTEX(vme_user_mutex);
 static const char driver_name[] = "vme_user";
 
 static int bus[VME_USER_BUS_MAX];
@@ -100,6 +100,7 @@ struct image_desc {
        struct device *device;  /* Sysfs device */
        struct vme_resource *resource;  /* VME resource */
        int users;              /* Number of current users */
+       int mmap_count;         /* Number of current mmap's */
 };
 static struct image_desc image[VME_DEVS];
 
@@ -135,6 +136,10 @@ static ssize_t vme_user_write(struct file *, const char __user *, size_t,
        loff_t *);
 static loff_t vme_user_llseek(struct file *, loff_t, int);
 static long vme_user_unlocked_ioctl(struct file *, unsigned int, unsigned long);
+static int vme_user_mmap(struct file *file, struct vm_area_struct *vma);
+
+static void vme_user_vm_open(struct vm_area_struct *vma);
+static void vme_user_vm_close(struct vm_area_struct *vma);
 
 static int vme_user_match(struct vme_dev *);
 static int vme_user_probe(struct vme_dev *);
@@ -148,6 +153,17 @@ static const struct file_operations vme_user_fops = {
        .llseek = vme_user_llseek,
        .unlocked_ioctl = vme_user_unlocked_ioctl,
        .compat_ioctl = vme_user_unlocked_ioctl,
+       .mmap = vme_user_mmap,
+};
+
+struct vme_user_vma_priv {
+       unsigned int minor;
+       atomic_t refcnt;
+};
+
+static const struct vm_operations_struct vme_user_vm_ops = {
+       .open = vme_user_vm_open,
+       .close = vme_user_vm_close,
 };
 
 
@@ -489,6 +505,11 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
 
                case VME_SET_MASTER:
 
+                       if (image[minor].mmap_count != 0) {
+                               pr_warn("Can't adjust mapped window\n");
+                               return -EPERM;
+                       }
+
                        copied = copy_from_user(&master, argp, sizeof(master));
                        if (copied != 0) {
                                pr_warn("Partial copy from userspace\n");
@@ -555,14 +576,79 @@ static long
 vme_user_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        int ret;
+       struct inode *inode = file_inode(file);
+       unsigned int minor = MINOR(inode->i_rdev);
 
-       mutex_lock(&vme_user_mutex);
-       ret = vme_user_ioctl(file_inode(file), file, cmd, arg);
-       mutex_unlock(&vme_user_mutex);
+       mutex_lock(&image[minor].mutex);
+       ret = vme_user_ioctl(inode, file, cmd, arg);
+       mutex_unlock(&image[minor].mutex);
 
        return ret;
 }
 
+static void vme_user_vm_open(struct vm_area_struct *vma)
+{
+       struct vme_user_vma_priv *vma_priv = vma->vm_private_data;
+
+       atomic_inc(&vma_priv->refcnt);
+}
+
+static void vme_user_vm_close(struct vm_area_struct *vma)
+{
+       struct vme_user_vma_priv *vma_priv = vma->vm_private_data;
+       unsigned int minor = vma_priv->minor;
+
+       if (!atomic_dec_and_test(&vma_priv->refcnt))
+               return;
+
+       mutex_lock(&image[minor].mutex);
+       image[minor].mmap_count--;
+       mutex_unlock(&image[minor].mutex);
+
+       kfree(vma_priv);
+}
+
+static int vme_user_master_mmap(unsigned int minor, struct vm_area_struct *vma)
+{
+       int err;
+       struct vme_user_vma_priv *vma_priv;
+
+       mutex_lock(&image[minor].mutex);
+
+       err = vme_master_mmap(image[minor].resource, vma);
+       if (err) {
+               mutex_unlock(&image[minor].mutex);
+               return err;
+       }
+
+       vma_priv = kmalloc(sizeof(struct vme_user_vma_priv), GFP_KERNEL);
+       if (vma_priv == NULL) {
+               mutex_unlock(&image[minor].mutex);
+               return -ENOMEM;
+       }
+
+       vma_priv->minor = minor;
+       atomic_set(&vma_priv->refcnt, 1);
+       vma->vm_ops = &vme_user_vm_ops;
+       vma->vm_private_data = vma_priv;
+
+       image[minor].mmap_count++;
+
+       mutex_unlock(&image[minor].mutex);
+
+       return 0;
+}
+
+static int vme_user_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       unsigned int minor = MINOR(file_inode(file)->i_rdev);
+
+       if (type[minor] == MASTER_MINOR)
+               return vme_user_master_mmap(minor, vma);
+
+       return -ENODEV;
+}
+
 
 /*
  * Unallocate a previously allocated buffer
index 565ba189afb2abda8ad3b713f0dff17f971ec493..b0ea38f1911c1bdca61a95b25208126d141645d7 100644 (file)
@@ -2021,14 +2021,20 @@ bool BBbVT3253Init(struct vnt_private *priv)
        if (byRFType == RF_RFMD2959) {
                if (byLocalID <= REV_ID_VT3253_A1) {
                        for (ii = 0; ii < CB_VT3253_INIT_FOR_RFMD; ii++)
-                               bResult &= BBbWriteEmbedded(priv, byVT3253InitTab_RFMD[ii][0], byVT3253InitTab_RFMD[ii][1]);
+                               bResult &= BBbWriteEmbedded(priv,
+                                       byVT3253InitTab_RFMD[ii][0],
+                                       byVT3253InitTab_RFMD[ii][1]);
 
                } else {
                        for (ii = 0; ii < CB_VT3253B0_INIT_FOR_RFMD; ii++)
-                               bResult &= BBbWriteEmbedded(priv, byVT3253B0_RFMD[ii][0], byVT3253B0_RFMD[ii][1]);
+                               bResult &= BBbWriteEmbedded(priv,
+                                       byVT3253B0_RFMD[ii][0],
+                                       byVT3253B0_RFMD[ii][1]);
 
                        for (ii = 0; ii < CB_VT3253B0_AGC_FOR_RFMD2959; ii++)
-                               bResult &= BBbWriteEmbedded(priv, byVT3253B0_AGC4_RFMD2959[ii][0], byVT3253B0_AGC4_RFMD2959[ii][1]);
+                               bResult &= BBbWriteEmbedded(priv,
+                                       byVT3253B0_AGC4_RFMD2959[ii][0],
+                                       byVT3253B0_AGC4_RFMD2959[ii][1]);
 
                        VNSvOutPortD(dwIoBase + MAC_REG_ITRTMSET, 0x23);
                        MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT(0));
@@ -2043,10 +2049,13 @@ bool BBbVT3253Init(struct vnt_private *priv)
                priv->ldBmThreshold[3] = 0;
        } else if ((byRFType == RF_AIROHA) || (byRFType == RF_AL2230S)) {
                for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++)
-                       bResult &= BBbWriteEmbedded(priv, byVT3253B0_AIROHA2230[ii][0], byVT3253B0_AIROHA2230[ii][1]);
+                       bResult &= BBbWriteEmbedded(priv,
+                               byVT3253B0_AIROHA2230[ii][0],
+                               byVT3253B0_AIROHA2230[ii][1]);
 
                for (ii = 0; ii < CB_VT3253B0_AGC; ii++)
-                       bResult &= BBbWriteEmbedded(priv, byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
+                       bResult &= BBbWriteEmbedded(priv,
+                               byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
 
                priv->abyBBVGA[0] = 0x1C;
                priv->abyBBVGA[1] = 0x10;
@@ -2058,10 +2067,14 @@ bool BBbVT3253Init(struct vnt_private *priv)
                priv->ldBmThreshold[3] = 0;
        } else if (byRFType == RF_UW2451) {
                for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++)
-                       bResult &= BBbWriteEmbedded(priv, byVT3253B0_UW2451[ii][0], byVT3253B0_UW2451[ii][1]);
+                       bResult &= BBbWriteEmbedded(priv,
+                               byVT3253B0_UW2451[ii][0],
+                               byVT3253B0_UW2451[ii][1]);
 
                for (ii = 0; ii < CB_VT3253B0_AGC; ii++)
-                       bResult &= BBbWriteEmbedded(priv, byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
+                       bResult &= BBbWriteEmbedded(priv,
+                               byVT3253B0_AGC[ii][0],
+                               byVT3253B0_AGC[ii][1]);
 
                VNSvOutPortB(dwIoBase + MAC_REG_ITRTMSET, 0x23);
                MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT(0));
@@ -2076,7 +2089,9 @@ bool BBbVT3253Init(struct vnt_private *priv)
                priv->ldBmThreshold[3] = 0;
        } else if (byRFType == RF_UW2452) {
                for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++)
-                       bResult &= BBbWriteEmbedded(priv, byVT3253B0_UW2451[ii][0], byVT3253B0_UW2451[ii][1]);
+                       bResult &= BBbWriteEmbedded(priv,
+                               byVT3253B0_UW2451[ii][0],
+                               byVT3253B0_UW2451[ii][1]);
 
                /* Init ANT B select,TX Config CR09 = 0x61->0x45, 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted) */
                /*bResult &= BBbWriteEmbedded(dwIoBase,0x09,0x41);*/
@@ -2097,7 +2112,8 @@ bool BBbVT3253Init(struct vnt_private *priv)
                bResult &= BBbWriteEmbedded(priv, 0xb0, 0x58);
 
                for (ii = 0; ii < CB_VT3253B0_AGC; ii++)
-                       bResult &= BBbWriteEmbedded(priv, byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
+                       bResult &= BBbWriteEmbedded(priv,
+                               byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
 
                priv->abyBBVGA[0] = 0x14;
                priv->abyBBVGA[1] = 0x0A;
@@ -2111,10 +2127,13 @@ bool BBbVT3253Init(struct vnt_private *priv)
 
        } else if (byRFType == RF_VT3226) {
                for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++)
-                       bResult &= BBbWriteEmbedded(priv, byVT3253B0_AIROHA2230[ii][0], byVT3253B0_AIROHA2230[ii][1]);
+                       bResult &= BBbWriteEmbedded(priv,
+                               byVT3253B0_AIROHA2230[ii][0],
+                               byVT3253B0_AIROHA2230[ii][1]);
 
                for (ii = 0; ii < CB_VT3253B0_AGC; ii++)
-                       bResult &= BBbWriteEmbedded(priv, byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
+                       bResult &= BBbWriteEmbedded(priv,
+                               byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
 
                priv->abyBBVGA[0] = 0x1C;
                priv->abyBBVGA[1] = 0x10;
@@ -2129,7 +2148,9 @@ bool BBbVT3253Init(struct vnt_private *priv)
                /* {{ RobertYu: 20050104 */
        } else if (byRFType == RF_AIROHA7230) {
                for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++)
-                       bResult &= BBbWriteEmbedded(priv, byVT3253B0_AIROHA2230[ii][0], byVT3253B0_AIROHA2230[ii][1]);
+                       bResult &= BBbWriteEmbedded(priv,
+                               byVT3253B0_AIROHA2230[ii][0],
+                               byVT3253B0_AIROHA2230[ii][1]);
 
 
                /* {{ RobertYu:20050223, request by JerryChung */
@@ -2142,7 +2163,8 @@ bool BBbVT3253Init(struct vnt_private *priv)
                /* }} */
 
                for (ii = 0; ii < CB_VT3253B0_AGC; ii++)
-                       bResult &= BBbWriteEmbedded(priv, byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
+                       bResult &= BBbWriteEmbedded(priv,
+                               byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]);
 
                priv->abyBBVGA[0] = 0x1C;
                priv->abyBBVGA[1] = 0x10;
index 3c17725d5910d1c2ccae323b3a56fc48b93bfbc9..7a717828fa09d37e11151d659c7514af430eb596 100644 (file)
@@ -193,7 +193,8 @@ bool set_channel(void *pDeviceHandler, struct ieee80211_channel *ch)
        /* clear NAV */
        MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MACCR, MACCR_CLRNAV);
 
-       /* TX_PE will reserve 3 us for MAX2829 A mode only, it is for better TX throughput */
+       /* TX_PE will reserve 3 us for MAX2829 A mode only,
+          it is for better TX throughput */
 
        if (pDevice->byRFType == RF_AIROHA7230)
                RFbAL7230SelectChannelPostProcess(pDevice, pDevice->byCurrentCh,
@@ -217,9 +218,11 @@ bool set_channel(void *pDeviceHandler, struct ieee80211_channel *ch)
                /* set HW default power register */
                MACvSelectPage1(pDevice->PortOffset);
                RFbSetPower(pDevice, RATE_1M, pDevice->byCurrentCh);
-               VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWRCCK, pDevice->byCurPwr);
+               VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWRCCK,
+                            pDevice->byCurPwr);
                RFbSetPower(pDevice, RATE_6M, pDevice->byCurrentCh);
-               VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWROFDM, pDevice->byCurPwr);
+               VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWROFDM,
+                            pDevice->byCurPwr);
                MACvSelectPage0(pDevice->PortOffset);
 
                spin_unlock_irqrestore(&pDevice->lock, flags);
index 03b2a90b9ac0b6f73109686b66623c61f0cd5ccb..4bb4f8ee41321a23134bcaf750ff3d2896350e82 100644 (file)
@@ -64,9 +64,9 @@
 #include <linux/slab.h>
 
 /*---------------------  Static Definitions -------------------------*/
-//
-// Define module options
-//
+/*
+ * Define module options
+ */
 MODULE_AUTHOR("VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver");
@@ -126,9 +126,9 @@ DEVICE_PARAM(LongRetryLimit, "long frame retry limits");
 
 DEVICE_PARAM(BasebandType, "baseband type");
 
-//
-// Static vars definitions
-//
+/*
+ * Static vars definitions
+ */
 static CHIP_INFO chip_info_table[] = {
        { VT3253,       "VIA Networking Solomon-A/B/G Wireless LAN Adapter ",
          256, 1,     DEVICE_FLAGS_IP_ALIGN|DEVICE_FLAGS_TX_ALIGN },
@@ -231,9 +231,9 @@ device_set_options(struct vnt_private *pDevice)
        pr_debug(" byBBType= %d\n", (int)pDevice->byBBType);
 }
 
-//
-// Initialisation of MAC & BBP registers
-//
+/*
+ * Initialisation of MAC & BBP registers
+ */
 
 static void device_init_registers(struct vnt_private *pDevice)
 {
@@ -530,12 +530,12 @@ static bool device_init_rings(struct vnt_private *pDevice)
        void *vir_pool;
 
        /*allocate all RD/TD rings a single pool*/
-       vir_pool = pci_zalloc_consistent(pDevice->pcid,
+       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->pool_dma);
+                                        &pDevice->pool_dma, GFP_ATOMIC);
        if (vir_pool == NULL) {
                dev_err(&pDevice->pcid->dev, "allocate desc dma memory failed\n");
                return false;
@@ -549,16 +549,17 @@ static bool device_init_rings(struct vnt_private *pDevice)
        pDevice->rd1_pool_dma = pDevice->rd0_pool_dma +
                pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc);
 
-       pDevice->tx0_bufs = pci_zalloc_consistent(pDevice->pcid,
+       pDevice->tx0_bufs = dma_zalloc_coherent(&pDevice->pcid->dev,
                                                  pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
                                                  pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
                                                  CB_BEACON_BUF_SIZE +
                                                  CB_MAX_BUF_SIZE,
-                                                 &pDevice->tx_bufs_dma0);
+                                                 &pDevice->tx_bufs_dma0,
+                                                 GFP_ATOMIC);
        if (pDevice->tx0_bufs == NULL) {
                dev_err(&pDevice->pcid->dev, "allocate buf dma memory failed\n");
 
-               pci_free_consistent(pDevice->pcid,
+               dma_free_coherent(&pDevice->pcid->dev,
                                    pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
                                    pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
                                    pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
@@ -574,7 +575,7 @@ static bool device_init_rings(struct vnt_private *pDevice)
        pDevice->td1_pool_dma = pDevice->td0_pool_dma +
                pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
 
-       // vir_pool: pvoid type
+       /* vir_pool: pvoid type */
        pDevice->apTD0Rings = vir_pool
                + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc)
                + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc);
@@ -604,7 +605,7 @@ static bool device_init_rings(struct vnt_private *pDevice)
 
 static void device_free_rings(struct vnt_private *pDevice)
 {
-       pci_free_consistent(pDevice->pcid,
+       dma_free_coherent(&pDevice->pcid->dev,
                            pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
                            pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
                            pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
@@ -614,7 +615,7 @@ static void device_free_rings(struct vnt_private *pDevice)
                );
 
        if (pDevice->tx0_bufs)
-               pci_free_consistent(pDevice->pcid,
+               dma_free_coherent(&pDevice->pcid->dev,
                                    pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ +
                                    pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ +
                                    CB_BEACON_BUF_SIZE +
@@ -679,8 +680,8 @@ static void device_free_rd0_ring(struct vnt_private *pDevice)
                PSRxDesc        pDesc = &(pDevice->aRD0Ring[i]);
                PDEVICE_RD_INFO  pRDInfo = pDesc->pRDInfo;
 
-               pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma,
-                                pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
+               dma_unmap_single(&pDevice->pcid->dev, pRDInfo->skb_dma,
+                                pDevice->rx_buf_sz, DMA_FROM_DEVICE);
 
                dev_kfree_skb(pRDInfo->skb);
 
@@ -696,8 +697,8 @@ static void device_free_rd1_ring(struct vnt_private *pDevice)
                PSRxDesc        pDesc = &(pDevice->aRD1Ring[i]);
                PDEVICE_RD_INFO  pRDInfo = pDesc->pRDInfo;
 
-               pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma,
-                                pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
+               dma_unmap_single(&pDevice->pcid->dev, pRDInfo->skb_dma,
+                                pDevice->rx_buf_sz, DMA_FROM_DEVICE);
 
                dev_kfree_skb(pRDInfo->skb);
 
@@ -765,8 +766,8 @@ static void device_free_td0_ring(struct vnt_private *pDevice)
                PDEVICE_TD_INFO  pTDInfo = pDesc->pTDInfo;
 
                if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
-                       pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma,
-                                        pTDInfo->skb->len, PCI_DMA_TODEVICE);
+                       dma_unmap_single(&pDevice->pcid->dev, pTDInfo->skb_dma,
+                                        pTDInfo->skb->len, DMA_TO_DEVICE);
 
                if (pTDInfo->skb)
                        dev_kfree_skb(pTDInfo->skb);
@@ -784,8 +785,8 @@ static void device_free_td1_ring(struct vnt_private *pDevice)
                PDEVICE_TD_INFO  pTDInfo = pDesc->pTDInfo;
 
                if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
-                       pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma,
-                                        pTDInfo->skb->len, PCI_DMA_TODEVICE);
+                       dma_unmap_single(&pDevice->pcid->dev, pTDInfo->skb_dma,
+                                        pTDInfo->skb->len, DMA_TO_DEVICE);
 
                if (pTDInfo->skb)
                        dev_kfree_skb(pTDInfo->skb);
@@ -831,9 +832,9 @@ static bool device_alloc_rx_buf(struct vnt_private *pDevice, PSRxDesc pRD)
        ASSERT(pRDInfo->skb);
 
        pRDInfo->skb_dma =
-               pci_map_single(pDevice->pcid,
+               dma_map_single(&pDevice->pcid->dev,
                               skb_put(pRDInfo->skb, skb_tailroom(pRDInfo->skb)),
-                              pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
+                              pDevice->rx_buf_sz, DMA_FROM_DEVICE);
 
        *((unsigned int *)&(pRD->m_rd0RD0)) = 0; /* FIX cast */
 
@@ -933,7 +934,7 @@ static int device_tx_srv(struct vnt_private *pDevice, unsigned int uIdx)
                byTsr0 = pTD->m_td0TD0.byTSR0;
                byTsr1 = pTD->m_td0TD0.byTSR1;
 
-               //Only the status of first TD in the chain is correct
+               /* 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) {
 
@@ -982,10 +983,10 @@ static void device_free_tx_buf(struct vnt_private *pDevice, PSTxDesc pDesc)
        PDEVICE_TD_INFO  pTDInfo = pDesc->pTDInfo;
        struct sk_buff *skb = pTDInfo->skb;
 
-       // pre-allocated buf_dma can't be unmapped.
+       /* pre-allocated buf_dma can't be unmapped. */
        if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) {
-               pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma, skb->len,
-                                PCI_DMA_TODEVICE);
+               dma_unmap_single(&pDevice->pcid->dev, pTDInfo->skb_dma,
+                                skb->len, DMA_TO_DEVICE);
        }
 
        if (pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)
@@ -1074,7 +1075,7 @@ static  irqreturn_t  device_intr(int irq,  void *dev_instance)
 
        spin_lock_irqsave(&pDevice->lock, flags);
 
-       //Make sure current page is 0
+       /* Make sure current page is 0 */
        VNSvInPortB(pDevice->PortOffset + MAC_REG_PAGE1SEL, &byOrgPageSel);
        if (byOrgPageSel == 1)
                MACvSelectPage0(pDevice->PortOffset);
@@ -1082,10 +1083,12 @@ static  irqreturn_t  device_intr(int irq,  void *dev_instance)
                byOrgPageSel = 0;
 
        MACvReadMIBCounter(pDevice->PortOffset, &dwMIBCounter);
-       // TBD....
-       // Must do this after doing rx/tx, cause ISR bit is slow
-       // than RD/TD write back
-       // update ISR counter
+       /*
+        * TBD....
+        * Must do this after doing rx/tx, cause ISR bit is slow
+        * than RD/TD write back
+        * update ISR counter
+        */
        STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic, dwMIBCounter);
        while (pDevice->dwIsr != 0) {
                STAvUpdateIsrStatCounter(&pDevice->scStatistic, pDevice->dwIsr);
index 3c5b87ffdcaccbfb50ddfb3a602bda84f774ad66..b25ee962558d786776df34cedcbefe5ee9999b7a 100644 (file)
@@ -140,8 +140,8 @@ bool vnt_receive_frame(struct vnt_private *priv, PSRxDesc curr_rd)
 
        skb = rd_info->skb;
 
-       pci_unmap_single(priv->pcid, rd_info->skb_dma,
-                        priv->rx_buf_sz, PCI_DMA_FROMDEVICE);
+       dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma,
+                        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);
index c01d4afb6ab8c5d6ddcd4e306d3ca0a516e92cc8..261f8181d4105ac6f1793d4c5118fa276e02cc84 100644 (file)
@@ -66,4 +66,4 @@ int vnt_key_init_table(struct vnt_private *);
 int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
                 struct ieee80211_vif *vif, struct ieee80211_key_conf *key);
 
-#endif // __KEY_H__
+#endif /* __KEY_H__ */
index 3653a2bd1e36014d39e2454d74cd8258785ed6c9..8048b3263360828b3f5c819df7505e030998fa85 100644 (file)
@@ -141,7 +141,7 @@ bool MACbIsIntDisable(void __iomem *dwIoBase)
  */
 void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit)
 {
-       // set SRT
+       /* set SRT */
        VNSvOutPortB(dwIoBase + MAC_REG_SRT, byRetryLimit);
 }
 
@@ -162,7 +162,7 @@ void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit)
  */
 void MACvSetLongRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit)
 {
-       // set LRT
+       /* set LRT */
        VNSvOutPortB(dwIoBase + MAC_REG_LRT, byRetryLimit);
 }
 
@@ -186,7 +186,7 @@ void MACvSetLoopbackMode(void __iomem *dwIoBase, unsigned char byLoopbackMode)
 
        ASSERT(byLoopbackMode < 3);
        byLoopbackMode <<= 6;
-       // set TCR
+       /* set TCR */
        VNSvInPortB(dwIoBase + MAC_REG_TEST, &byOrgValue);
        byOrgValue = byOrgValue & 0x3F;
        byOrgValue = byOrgValue | byLoopbackMode;
@@ -210,13 +210,13 @@ void MACvSaveContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf)
 {
        int         ii;
 
-       // read page0 register
+       /* read page0 register */
        for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE0; ii++)
                VNSvInPortB((dwIoBase + ii), (pbyCxtBuf + ii));
 
        MACvSelectPage1(dwIoBase);
 
-       // read page1 register
+       /* read page1 register */
        for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE1; ii++)
                VNSvInPortB((dwIoBase + ii), (pbyCxtBuf + MAC_MAX_CONTEXT_SIZE_PAGE0 + ii));
 
@@ -242,27 +242,27 @@ void MACvRestoreContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf)
        int         ii;
 
        MACvSelectPage1(dwIoBase);
-       // restore page1
+       /* restore page1 */
        for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE1; ii++)
                VNSvOutPortB((dwIoBase + ii), *(pbyCxtBuf + MAC_MAX_CONTEXT_SIZE_PAGE0 + ii));
 
        MACvSelectPage0(dwIoBase);
 
-       // restore RCR,TCR,IMR...
+       /* restore RCR,TCR,IMR... */
        for (ii = MAC_REG_RCR; ii < MAC_REG_ISR; ii++)
                VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii));
 
-       // restore MAC Config.
+       /* restore MAC Config. */
        for (ii = MAC_REG_LRT; ii < MAC_REG_PAGE1SEL; ii++)
                VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii));
 
        VNSvOutPortB(dwIoBase + MAC_REG_CFG, *(pbyCxtBuf + MAC_REG_CFG));
 
-       // restore PS Config.
+       /* restore PS Config. */
        for (ii = MAC_REG_PSCFG; ii < MAC_REG_BBREGCTL; ii++)
                VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii));
 
-       // restore CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR
+       /* restore CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR */
        VNSvOutPortD(dwIoBase + MAC_REG_TXDMAPTR0, *(unsigned long *)(pbyCxtBuf + MAC_REG_TXDMAPTR0));
        VNSvOutPortD(dwIoBase + MAC_REG_AC0DMAPTR, *(unsigned long *)(pbyCxtBuf + MAC_REG_AC0DMAPTR));
        VNSvOutPortD(dwIoBase + MAC_REG_BCNDMAPTR, *(unsigned long *)(pbyCxtBuf + MAC_REG_BCNDMAPTR));
@@ -290,7 +290,7 @@ bool MACbSoftwareReset(void __iomem *dwIoBase)
        unsigned char byData;
        unsigned short ww;
 
-       // turn on HOSTCR_SOFTRST, just write 0x01 to reset
+       /* turn on HOSTCR_SOFTRST, just write 0x01 to reset */
        VNSvOutPortB(dwIoBase + MAC_REG_HOSTCR, 0x01);
 
        for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
@@ -321,15 +321,15 @@ bool MACbSafeSoftwareReset(void __iomem *dwIoBase)
        unsigned char abyTmpRegData[MAC_MAX_CONTEXT_SIZE_PAGE0+MAC_MAX_CONTEXT_SIZE_PAGE1];
        bool bRetVal;
 
-       // PATCH....
-       // save some important register's value, then do
-       // reset, then restore register's value
-
-       // save MAC context
+       /* PATCH....
+        * save some important register's value, then do
+        * reset, then restore register's value
+        */
+       /* save MAC context */
        MACvSaveContext(dwIoBase, abyTmpRegData);
-       // do reset
+       /* do reset */
        bRetVal = MACbSoftwareReset(dwIoBase);
-       // restore MAC context, except CR0
+       /* restore MAC context, except CR0 */
        MACvRestoreContext(dwIoBase, abyTmpRegData);
 
        return bRetVal;
@@ -354,9 +354,9 @@ bool MACbSafeRxOff(void __iomem *dwIoBase)
        unsigned long dwData;
        unsigned char byData;
 
-       // turn off wow temp for turn off Rx safely
+       /* turn off wow temp for turn off Rx safely */
 
-       // Clear RX DMA0,1
+       /* Clear RX DMA0,1 */
        VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_CLRRUN);
        VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_CLRRUN);
        for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
@@ -380,9 +380,9 @@ bool MACbSafeRxOff(void __iomem *dwIoBase)
                return false;
        }
 
-       // try to safe shutdown RX
+       /* try to safe shutdown RX */
        MACvRegBitsOff(dwIoBase, MAC_REG_HOSTCR, HOSTCR_RXON);
-       // W_MAX_TIMEOUT is the timeout period
+       /* W_MAX_TIMEOUT is the timeout period */
        for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
                VNSvInPortB(dwIoBase + MAC_REG_HOSTCR, &byData);
                if (!(byData & HOSTCR_RXONST))
@@ -415,10 +415,10 @@ bool MACbSafeTxOff(void __iomem *dwIoBase)
        unsigned long dwData;
        unsigned char byData;
 
-       // Clear TX DMA
-       //Tx0
+       /* Clear TX DMA */
+       /* Tx0 */
        VNSvOutPortD(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_CLRRUN);
-       //AC0
+       /* AC0 */
        VNSvOutPortD(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_CLRRUN);
 
        for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
@@ -442,10 +442,10 @@ bool MACbSafeTxOff(void __iomem *dwIoBase)
                return false;
        }
 
-       // try to safe shutdown TX
+       /* try to safe shutdown TX */
        MACvRegBitsOff(dwIoBase, MAC_REG_HOSTCR, HOSTCR_TXON);
 
-       // W_MAX_TIMEOUT is the timeout period
+       /* W_MAX_TIMEOUT is the timeout period */
        for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
                VNSvInPortB(dwIoBase + MAC_REG_HOSTCR, &byData);
                if (!(byData & HOSTCR_TXONST))
@@ -509,10 +509,10 @@ bool MACbSafeStop(void __iomem *dwIoBase)
  */
 bool MACbShutdown(void __iomem *dwIoBase)
 {
-       // disable MAC IMR
+       /* disable MAC IMR */
        MACvIntDisable(dwIoBase);
        MACvSetLoopbackMode(dwIoBase, MAC_LB_INTERNAL);
-       // stop the adapter
+       /* stop the adapter */
        if (!MACbSafeStop(dwIoBase)) {
                MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE);
                return false;
@@ -536,18 +536,18 @@ bool MACbShutdown(void __iomem *dwIoBase)
  */
 void MACvInitialize(void __iomem *dwIoBase)
 {
-       // clear sticky bits
+       /* clear sticky bits */
        MACvClearStckDS(dwIoBase);
-       // disable force PME-enable
+       /* disable force PME-enable */
        VNSvOutPortB(dwIoBase + MAC_REG_PMC1, PME_OVR);
-       // only 3253 A
+       /* only 3253 A */
 
-       // do reset
+       /* do reset */
        MACbSoftwareReset(dwIoBase);
 
-       // reset TSF counter
+       /* reset TSF counter */
        VNSvOutPortB(dwIoBase + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
-       // enable TSF counter
+       /* enable TSF counter */
        VNSvOutPortB(dwIoBase + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
 }
 
@@ -678,7 +678,7 @@ void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase, unsigned long dwCurrDescAd
  * Return Value: none
  *
  */
-//TxDMA1 = AC0DMA
+/* TxDMA1 = AC0DMA */
 void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase, unsigned long dwCurrDescAddr)
 {
        unsigned short ww;
@@ -733,7 +733,7 @@ void MACvTimer0MicroSDelay(void __iomem *dwIoBase, unsigned int uDelay)
        VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0);
        VNSvOutPortD(dwIoBase + MAC_REG_TMDATA0, uDelay);
        VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, (TMCTL_TMD | TMCTL_TE));
-       for (ii = 0; ii < 66; ii++) {  // assume max PCI clock is 66Mhz
+       for (ii = 0; ii < 66; ii++) {  /* assume max PCI clock is 66Mhz */
                for (uu = 0; uu < uDelay; uu++) {
                        VNSvInPortB(dwIoBase + MAC_REG_TMCTL0, &byValue);
                        if ((byValue == 0) ||
@@ -780,14 +780,14 @@ bool MACbPSWakeup(void __iomem *dwIoBase)
 {
        unsigned char byOrgValue;
        unsigned int ww;
-       // Read PSCTL
+       /* Read PSCTL */
        if (MACbIsRegBitsOff(dwIoBase, MAC_REG_PSCTL, PSCTL_PS))
                return true;
 
-       // Disable PS
+       /* Disable PS */
        MACvRegBitsOff(dwIoBase, MAC_REG_PSCTL, PSCTL_PSEN);
 
-       // Check if SyncFlushOK
+       /* Check if SyncFlushOK */
        for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
                VNSvInPortB(dwIoBase + MAC_REG_PSCTL, &byOrgValue);
                if (byOrgValue & PSCTL_WAKEDONE)
@@ -859,7 +859,7 @@ void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl, unsigned in
 
        wOffset += (uKeyIdx * 4);
        for (ii = 0; ii < 4; ii++) {
-               // always push 128 bits
+               /* always push 128 bits */
                pr_debug("3.(%d) wOffset: %d, Data: %X\n",
                         ii, wOffset+ii, *pdwKey);
                VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii);
index d2f351d19ff8a84df5d197f5175b0c4e735cd04c..d55c762027ed4f44e9592b1a037ed88aa6480ced 100644 (file)
@@ -63,51 +63,51 @@ void STAvUpdateIsrStatCounter(PSStatCounter pStatistic, unsigned long dwIsr)
        /**********************/
        /* ABNORMAL interrupt */
        /**********************/
-       // not any IMR bit invoke irq
+       /* not any IMR bit invoke irq */
 
        if (dwIsr == 0) {
                pStatistic->ISRStat.dwIsrUnknown++;
                return;
        }
 
-//Added by Kyle
-       if (dwIsr & ISR_TXDMA0)               // ISR, bit0
-               pStatistic->ISRStat.dwIsrTx0OK++;             // TXDMA0 successful
+/* Added by Kyle */
+       if (dwIsr & ISR_TXDMA0)               /* ISR, bit0 */
+               pStatistic->ISRStat.dwIsrTx0OK++;             /* TXDMA0 successful */
 
-       if (dwIsr & ISR_AC0DMA)               // ISR, bit1
-               pStatistic->ISRStat.dwIsrAC0TxOK++;           // AC0DMA successful
+       if (dwIsr & ISR_AC0DMA)               /* ISR, bit1 */
+               pStatistic->ISRStat.dwIsrAC0TxOK++;           /* AC0DMA successful */
 
-       if (dwIsr & ISR_BNTX)                 // ISR, bit2
-               pStatistic->ISRStat.dwIsrBeaconTxOK++;        // BeaconTx successful
+       if (dwIsr & ISR_BNTX)                 /* ISR, bit2 */
+               pStatistic->ISRStat.dwIsrBeaconTxOK++;        /* BeaconTx successful */
 
-       if (dwIsr & ISR_RXDMA0)               // ISR, bit3
-               pStatistic->ISRStat.dwIsrRx0OK++;             // Rx0 successful
+       if (dwIsr & ISR_RXDMA0)               /* ISR, bit3 */
+               pStatistic->ISRStat.dwIsrRx0OK++;             /* Rx0 successful */
 
-       if (dwIsr & ISR_TBTT)                 // ISR, bit4
-               pStatistic->ISRStat.dwIsrTBTTInt++;           // TBTT successful
+       if (dwIsr & ISR_TBTT)                 /* ISR, bit4 */
+               pStatistic->ISRStat.dwIsrTBTTInt++;           /* TBTT successful */
 
-       if (dwIsr & ISR_SOFTTIMER)            // ISR, bit6
+       if (dwIsr & ISR_SOFTTIMER)            /* ISR, bit6 */
                pStatistic->ISRStat.dwIsrSTIMERInt++;
 
-       if (dwIsr & ISR_WATCHDOG)             // ISR, bit7
+       if (dwIsr & ISR_WATCHDOG)             /* ISR, bit7 */
                pStatistic->ISRStat.dwIsrWatchDog++;
 
-       if (dwIsr & ISR_FETALERR)             // ISR, bit8
+       if (dwIsr & ISR_FETALERR)             /* ISR, bit8 */
                pStatistic->ISRStat.dwIsrUnrecoverableError++;
 
-       if (dwIsr & ISR_SOFTINT)              // ISR, bit9
-               pStatistic->ISRStat.dwIsrSoftInterrupt++;     // software interrupt
+       if (dwIsr & ISR_SOFTINT)              /* ISR, bit9 */
+               pStatistic->ISRStat.dwIsrSoftInterrupt++;     /* software interrupt */
 
-       if (dwIsr & ISR_MIBNEARFULL)          // ISR, bit10
+       if (dwIsr & ISR_MIBNEARFULL)          /* ISR, bit10 */
                pStatistic->ISRStat.dwIsrMIBNearfull++;
 
-       if (dwIsr & ISR_RXNOBUF)              // ISR, bit11
-               pStatistic->ISRStat.dwIsrRxNoBuf++;           // Rx No Buff
+       if (dwIsr & ISR_RXNOBUF)              /* ISR, bit11 */
+               pStatistic->ISRStat.dwIsrRxNoBuf++;           /* Rx No Buff */
 
-       if (dwIsr & ISR_RXDMA1)               // ISR, bit12
-               pStatistic->ISRStat.dwIsrRx1OK++;             // Rx1 successful
+       if (dwIsr & ISR_RXDMA1)               /* ISR, bit12 */
+               pStatistic->ISRStat.dwIsrRx1OK++;             /* Rx1 successful */
 
-       if (dwIsr & ISR_SOFTTIMER1)           // ISR, bit21
+       if (dwIsr & ISR_SOFTTIMER1)           /* ISR, bit21 */
                pStatistic->ISRStat.dwIsrSTIMER1Int++;
 }
 
index 07ce3fd88e70dd69595816fe7af72fb2db21baf1..74687761bd2ee0e6af91c89492875e07cebebc9c 100644 (file)
 /*---------------------  Static Functions  --------------------------*/
 
 /*---------------------  Static Definitions -------------------------*/
-#define CRITICAL_PACKET_LEN      256    // if packet size < 256 -> in-direct send
-                                        //    packet size >= 256 -> direct send
+#define CRITICAL_PACKET_LEN      256    /* if packet size < 256 -> in-direct send
+                                            packet size >= 256 -> direct send */
 
 static const unsigned short wTimeStampOff[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
+       {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 */
 };
 
 static const unsigned short wFB_Opt0[2][5] = {
-       {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, // fallback_rate0
-       {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, // fallback_rate1
+       {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, /* fallback_rate0 */
+       {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, /* fallback_rate1 */
 };
 static const unsigned short wFB_Opt1[2][5] = {
-       {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, // fallback_rate0
-       {RATE_6M , RATE_6M,  RATE_12M, RATE_12M, RATE_18M}, // fallback_rate1
+       {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, /* fallback_rate0 */
+       {RATE_6M , RATE_6M,  RATE_12M, RATE_12M, RATE_18M}, /* fallback_rate1 */
 };
 
 #define RTSDUR_BB       0
@@ -116,7 +116,7 @@ void
 s_vGenerateTxParameter(
        struct vnt_private *pDevice,
        unsigned char byPktType,
-       void *pTxBufHead,
+       struct vnt_tx_fifo_head *,
        void *pvRrvTime,
        void *pvRTS,
        void *pvCTS,
@@ -176,9 +176,9 @@ s_uGetTxRsvTime(
        unsigned int uDataTime, uAckTime;
 
        uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wRate);
-       if (byPktType == PK_TYPE_11B) //llb,CCK mode
+       if (byPktType == PK_TYPE_11B) /* llb,CCK mode */
                uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (unsigned short)pDevice->byTopCCKBasicRate);
-       else //11g 2.4G OFDM mode & 11a 5G OFDM mode
+       else /* 11g 2.4G OFDM mode & 11a 5G OFDM mode */
                uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (unsigned short)pDevice->byTopOFDMBasicRate);
 
        if (bNeedAck)
@@ -194,7 +194,7 @@ static __le16 vnt_rxtx_rsvtime_le16(struct vnt_private *priv, u8 pkt_type,
                                                frame_length, rate, need_ack));
 }
 
-//byFreqType: 0=>5GHZ 1=>2.4GHZ
+/* byFreqType: 0=>5GHZ 1=>2.4GHZ */
 static
 __le16
 s_uGetRTSCTSRsvTime(
@@ -210,29 +210,29 @@ s_uGetRTSCTSRsvTime(
        uRrvTime = uRTSTime = uCTSTime = uAckTime = uDataTime = 0;
 
        uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wCurrentRate);
-       if (byRTSRsvType == 0) { //RTSTxRrvTime_bb
+       if (byRTSRsvType == 0) { /* RTSTxRrvTime_bb */
                uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate);
                uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-       } else if (byRTSRsvType == 1) { //RTSTxRrvTime_ba, only in 2.4GHZ
+       } else if (byRTSRsvType == 1) { /* RTSTxRrvTime_ba, only in 2.4GHZ */
                uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate);
                uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
                uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-       } else if (byRTSRsvType == 2) { //RTSTxRrvTime_aa
+       } else if (byRTSRsvType == 2) { /* RTSTxRrvTime_aa */
                uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopOFDMBasicRate);
                uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-       } else if (byRTSRsvType == 3) { //CTSTxRrvTime_ba, only in 2.4GHZ
+       } else if (byRTSRsvType == 3) { /* CTSTxRrvTime_ba, only in 2.4GHZ */
                uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
                uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
                uRrvTime = uCTSTime + uAckTime + uDataTime + 2*pDevice->uSIFS;
                return cpu_to_le16((u16)uRrvTime);
        }
 
-       //RTSRrvTime
+       /* RTSRrvTime */
        uRrvTime = uRTSTime + uCTSTime + uAckTime + uDataTime + 3*pDevice->uSIFS;
        return cpu_to_le16((u16)uRrvTime);
 }
 
-//byFreqType 0: 5GHz, 1:2.4Ghz
+/* byFreqType 0: 5GHz, 1:2.4Ghz */
 static
 unsigned int
 s_uGetDataDuration(
@@ -248,22 +248,22 @@ s_uGetDataDuration(
        unsigned char byFBOption
 )
 {
-       bool bLastFrag = 0;
+       bool bLastFrag = false;
        unsigned int uAckTime = 0, uNextPktTime = 0;
 
        if (uFragIdx == (uMACfragNum-1))
-               bLastFrag = 1;
+               bLastFrag = true;
 
        switch (byDurType) {
-       case DATADUR_B:    //DATADUR_B
-               if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag
+       case DATADUR_B:    /* DATADUR_B */
+               if (((uMACfragNum == 1)) || bLastFrag) {/* Non Frag or Last Frag */
                        if (bNeedAck) {
                                uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
                                return pDevice->uSIFS + uAckTime;
                        } else {
                                return 0;
                        }
-               } else {//First Frag or Mid Frag
+               } else {/* First Frag or Mid Frag */
                        if (uFragIdx == (uMACfragNum-2))
                                uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck);
                        else
@@ -278,15 +278,15 @@ s_uGetDataDuration(
                }
                break;
 
-       case DATADUR_A:    //DATADUR_A
-               if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag
+       case DATADUR_A:    /* DATADUR_A */
+               if (((uMACfragNum == 1)) || bLastFrag) {/* Non Frag or Last Frag */
                        if (bNeedAck) {
                                uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
                                return pDevice->uSIFS + uAckTime;
                        } else {
                                return 0;
                        }
-               } else {//First Frag or Mid Frag
+               } else {/* First Frag or Mid Frag */
                        if (uFragIdx == (uMACfragNum-2))
                                uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck);
                        else
@@ -301,15 +301,15 @@ s_uGetDataDuration(
                }
                break;
 
-       case DATADUR_A_F0:    //DATADUR_A_F0
-               if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag
+       case DATADUR_A_F0:    /* DATADUR_A_F0 */
+               if (((uMACfragNum == 1)) || bLastFrag) {/* Non Frag or Last Frag */
                        if (bNeedAck) {
                                uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
                                return pDevice->uSIFS + uAckTime;
                        } else {
                                return 0;
                        }
-               } else { //First Frag or Mid Frag
+               } else { /* First Frag or Mid Frag */
                        if (byFBOption == AUTO_FB_0) {
                                if (wRate < RATE_18M)
                                        wRate = RATE_18M;
@@ -321,7 +321,7 @@ s_uGetDataDuration(
                                else
                                        uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
 
-                       } else { // (byFBOption == AUTO_FB_1)
+                       } else { /* (byFBOption == AUTO_FB_1) */
                                if (wRate < RATE_18M)
                                        wRate = RATE_18M;
                                else if (wRate > RATE_54M)
@@ -343,15 +343,15 @@ s_uGetDataDuration(
                }
                break;
 
-       case DATADUR_A_F1:    //DATADUR_A_F1
-               if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag
+       case DATADUR_A_F1:    /* DATADUR_A_F1 */
+               if (((uMACfragNum == 1)) || bLastFrag) { /* Non Frag or Last Frag */
                        if (bNeedAck) {
                                uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
                                return pDevice->uSIFS + uAckTime;
                        } else {
                                return 0;
                        }
-               } else { //First Frag or Mid Frag
+               } else { /* First Frag or Mid Frag */
                        if (byFBOption == AUTO_FB_0) {
                                if (wRate < RATE_18M)
                                        wRate = RATE_18M;
@@ -363,7 +363,7 @@ s_uGetDataDuration(
                                else
                                        uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
 
-                       } else { // (byFBOption == AUTO_FB_1)
+                       } else { /* (byFBOption == AUTO_FB_1) */
                                if (wRate < RATE_18M)
                                        wRate = RATE_18M;
                                else if (wRate > RATE_54M)
@@ -391,7 +391,7 @@ s_uGetDataDuration(
        return 0;
 }
 
-//byFreqType: 0=>5GHZ 1=>2.4GHZ
+/* byFreqType: 0=>5GHZ 1=>2.4GHZ */
 static
 __le16
 s_uGetRTSCTSDuration(
@@ -407,26 +407,26 @@ s_uGetRTSCTSDuration(
        unsigned int uCTSTime = 0, uDurTime = 0;
 
        switch (byDurType) {
-       case RTSDUR_BB:    //RTSDuration_bb
+       case RTSDUR_BB:    /* RTSDuration_bb */
                uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
                uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
                break;
 
-       case RTSDUR_BA:    //RTSDuration_ba
+       case RTSDUR_BA:    /* RTSDuration_ba */
                uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
                uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
                break;
 
-       case RTSDUR_AA:    //RTSDuration_aa
+       case RTSDUR_AA:    /* RTSDuration_aa */
                uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
                uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
                break;
 
-       case CTSDUR_BA:    //CTSDuration_ba
+       case CTSDUR_BA:    /* CTSDuration_ba */
                uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
                break;
 
-       case RTSDUR_BA_F0: //RTSDuration_ba_f0
+       case RTSDUR_BA_F0: /* RTSDuration_ba_f0 */
                uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
                if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
                        uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
@@ -435,7 +435,7 @@ s_uGetRTSCTSDuration(
 
                break;
 
-       case RTSDUR_AA_F0: //RTSDuration_aa_f0
+       case RTSDUR_AA_F0: /* RTSDuration_aa_f0 */
                uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
                if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
                        uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
@@ -444,7 +444,7 @@ s_uGetRTSCTSDuration(
 
                break;
 
-       case RTSDUR_BA_F1: //RTSDuration_ba_f1
+       case RTSDUR_BA_F1: /* RTSDuration_ba_f1 */
                uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
                if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
                        uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
@@ -453,7 +453,7 @@ s_uGetRTSCTSDuration(
 
                break;
 
-       case RTSDUR_AA_F1: //RTSDuration_aa_f1
+       case RTSDUR_AA_F1: /* RTSDuration_aa_f1 */
                uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
                if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
                        uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
@@ -462,7 +462,7 @@ s_uGetRTSCTSDuration(
 
                break;
 
-       case CTSDUR_BA_F0: //CTSDuration_ba_f0
+       case CTSDUR_BA_F0: /* CTSDuration_ba_f0 */
                if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
                        uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
                else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
@@ -470,7 +470,7 @@ s_uGetRTSCTSDuration(
 
                break;
 
-       case CTSDUR_BA_F1: //CTSDuration_ba_f1
+       case CTSDUR_BA_F1: /* CTSDuration_ba_f1 */
                if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
                        uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
                else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
@@ -565,7 +565,7 @@ s_uFillDataHead(
                        buf->time_stamp_off_b = vnt_time_stamp_off(pDevice, pDevice->byTopCCKBasicRate);
 
                        return buf->duration_a;
-               } //if (byFBOption == AUTO_FB_NONE)
+               } /* if (byFBOption == AUTO_FB_NONE) */
        } else if (byPktType == PK_TYPE_11A) {
                if ((byFBOption != AUTO_FB_NONE)) {
                        /* Auto Fallback */
@@ -651,13 +651,13 @@ s_vFillRTSHead(
                return;
 
        if (bDisCRC) {
-               // When CRCDIS bit is on, H/W forgot to generate FCS for RTS frame,
-               // in this case we need to decrease its length by 4.
+               /* When CRCDIS bit is on, H/W forgot to generate FCS for RTS frame,
+                in this case we need to decrease its length by 4. */
                uRTSFrameLen -= 4;
        }
 
-       // Note: So far RTSHead dosen't appear in ATIM & Beacom DMA, so we don't need to take them into account.
-       //       Otherwise, we need to modify codes for them.
+       /* Note: So far RTSHead dosen't appear in ATIM & Beacom DMA, so we don't need to take them into account.
+              Otherwise, we need to modify codes for them. */
        if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
                if (byFBOption == AUTO_FB_NONE) {
                        struct vnt_rts_g *buf = pvRTS;
@@ -748,7 +748,7 @@ s_vFillRTSHead(
 
                        ether_addr_copy(buf->data.ra, hdr->addr1);
                        ether_addr_copy(buf->data.ta, hdr->addr2);
-               } // if (byFBOption == AUTO_FB_NONE)
+               } /* if (byFBOption == AUTO_FB_NONE) */
        } else if (byPktType == PK_TYPE_11A) {
                if (byFBOption == AUTO_FB_NONE) {
                        struct vnt_rts_ab *buf = pvRTS;
@@ -843,14 +843,14 @@ s_vFillCTSHead(
                return;
 
        if (bDisCRC) {
-               // When CRCDIS bit is on, H/W forgot to generate FCS for CTS frame,
-               // in this case we need to decrease its length by 4.
+               /* When CRCDIS bit is on, H/W forgot to generate FCS for CTS frame,
+                in this case we need to decrease its length by 4. */
                uCTSFrameLen -= 4;
        }
 
        if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
                if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) {
-                       // Auto Fall back
+                       /* Auto Fall back */
                        struct vnt_cts_fb *buf = pvCTS;
                        /* Get SignalField, ServiceField & Length */
                        vnt_get_phy_field(pDevice, uCTSFrameLen,
@@ -888,7 +888,7 @@ s_vFillCTSHead(
 
                        ether_addr_copy(buf->data.ra,
                                        pDevice->abyCurrentNetAddr);
-               } else { //if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA)
+               } else { /* if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) */
                        struct vnt_cts *buf = pvCTS;
                        /* Get SignalField, ServiceField & Length */
                        vnt_get_phy_field(pDevice, uCTSFrameLen,
@@ -937,14 +937,14 @@ s_vFillCTSHead(
  *
  * Return Value: none
  *
- -*/
-// unsigned int cbFrameSize,//Hdr+Payload+FCS
+ -
+ * unsigned int cbFrameSize, Hdr+Payload+FCS */
 static
 void
 s_vGenerateTxParameter(
        struct vnt_private *pDevice,
        unsigned char byPktType,
-       void *pTxBufHead,
+       struct vnt_tx_fifo_head *tx_buffer_head,
        void *pvRrvTime,
        void *pvRTS,
        void *pvCTS,
@@ -955,29 +955,26 @@ s_vGenerateTxParameter(
        unsigned short wCurrentRate
 )
 {
-       unsigned short wFifoCtl;
+       u16 fifo_ctl = le16_to_cpu(tx_buffer_head->fifo_ctl);
        bool bDisCRC = false;
        unsigned char byFBOption = AUTO_FB_NONE;
 
-       PSTxBufHead pFifoHead = (PSTxBufHead)pTxBufHead;
-
-       pFifoHead->wReserved = wCurrentRate;
-       wFifoCtl = pFifoHead->wFIFOCtl;
+       tx_buffer_head->current_rate = cpu_to_le16(wCurrentRate);
 
-       if (wFifoCtl & FIFOCTL_CRCDIS)
+       if (fifo_ctl & FIFOCTL_CRCDIS)
                bDisCRC = true;
 
-       if (wFifoCtl & FIFOCTL_AUTO_FB_0)
+       if (fifo_ctl & FIFOCTL_AUTO_FB_0)
                byFBOption = AUTO_FB_0;
-       else if (wFifoCtl & FIFOCTL_AUTO_FB_1)
+       else if (fifo_ctl & FIFOCTL_AUTO_FB_1)
                byFBOption = AUTO_FB_1;
 
        if (!pvRrvTime)
                return;
 
        if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
-               if (pvRTS != NULL) { //RTS_need
-                       /* Fill RsvTime */
+               if (pvRTS != NULL) { /RTS_need
+                        Fill RsvTime */
                        struct vnt_rrv_time_rts *buf = pvRrvTime;
 
                        buf->rts_rrv_time_aa = s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate);
@@ -987,40 +984,40 @@ s_vGenerateTxParameter(
                        buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK);
 
                        s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
-               } else {//RTS_needless, PCF mode
+               } else {/* RTS_needless, PCF mode */
                        struct vnt_rrv_time_cts *buf = pvRrvTime;
 
                        buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);
                        buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK);
                        buf->cts_rrv_time_ba = s_uGetRTSCTSRsvTime(pDevice, 3, byPktType, cbFrameSize, wCurrentRate);
 
-                       //Fill CTS
+                       /* Fill CTS */
                        s_vFillCTSHead(pDevice, uDMAIdx, byPktType, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption);
                }
        } else if (byPktType == PK_TYPE_11A) {
-               if (pvRTS != NULL) {//RTS_need, non PCF mode
+               if (pvRTS != NULL) {/* RTS_need, non PCF mode */
                        struct vnt_rrv_time_ab *buf = pvRrvTime;
 
                        buf->rts_rrv_time = s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate);
                        buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);
 
-                       //Fill RTS
+                       /* Fill RTS */
                        s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
-               } else if (pvRTS == NULL) {//RTS_needless, non PCF mode
+               } else if (pvRTS == NULL) {/* RTS_needless, non PCF mode */
                        struct vnt_rrv_time_ab *buf = pvRrvTime;
 
                        buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK);
                }
        } else if (byPktType == PK_TYPE_11B) {
-               if ((pvRTS != NULL)) {//RTS_need, non PCF mode
+               if ((pvRTS != NULL)) {/* RTS_need, non PCF mode */
                        struct vnt_rrv_time_ab *buf = pvRrvTime;
 
                        buf->rts_rrv_time = s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate);
                        buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK);
 
-                       //Fill RTS
+                       /* Fill RTS */
                        s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
-               } else { //RTS_needless, non PCF mode
+               } else { /* RTS_needless, non PCF mode */
                        struct vnt_rrv_time_ab *buf = pvRrvTime;
 
                        buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK);
@@ -1058,7 +1055,7 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
        void *pvRTS;
        void *pvCTS;
        void *pvTxDataHd;
-       unsigned short wTxBufSize;   // FFinfo size
+       unsigned short wTxBufSize;   /* FFinfo size */
        unsigned char byFBOption = AUTO_FB_NONE;
 
        pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL;
@@ -1076,27 +1073,27 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
                cbFrameSize += info->control.hw_key->icv_len;
 
                if (pDevice->byLocalID > REV_ID_VT3253_A1) {
-                       //MAC Header should be padding 0 to DW alignment.
+                       /* MAC Header should be padding 0 to DW alignment. */
                        uPadding = 4 - (ieee80211_get_hdrlen_from_skb(skb) % 4);
                        uPadding %= 4;
                }
        }
 
-       //
-       // Use for AUTO FALL BACK
-       //
+       /*
+       * Use for AUTO FALL BACK
+       */
        if (fifo_ctl & FIFOCTL_AUTO_FB_0)
                byFBOption = AUTO_FB_0;
        else if (fifo_ctl & FIFOCTL_AUTO_FB_1)
                byFBOption = AUTO_FB_1;
 
-       //////////////////////////////////////////////////////
-       //Set RrvTime/RTS/CTS Buffer
+
+       /* Set RrvTime/RTS/CTS Buffer */
        wTxBufSize = sizeof(STxBufHead);
-       if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
+       if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {/* 802.11g packet */
 
                if (byFBOption == AUTO_FB_NONE) {
-                       if (bRTS == true) {//RTS_need
+                       if (bRTS == true) {/* RTS_need */
                                pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
                                pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts));
                                pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
@@ -1106,7 +1103,7 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
                                cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
                                                        cbMICHDR + sizeof(struct vnt_rts_g) +
                                                        sizeof(struct vnt_tx_datahead_g);
-                       } else { //RTS_needless
+                       } else { /* RTS_needless */
                                pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
                                pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts));
                                pvRTS = NULL;
@@ -1117,8 +1114,8 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
                                                        cbMICHDR + sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);
                        }
                } else {
-                       // Auto Fall Back
-                       if (bRTS == true) {//RTS_need
+                       /* Auto Fall Back */
+                       if (bRTS == true) {/* RTS_need */
                                pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
                                pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts));
                                pvRTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
@@ -1127,7 +1124,7 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
                                        cbMICHDR + sizeof(struct vnt_rts_g_fb));
                                cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
                                        cbMICHDR + sizeof(struct vnt_rts_g_fb) + sizeof(struct vnt_tx_datahead_g_fb);
-                       } else { //RTS_needless
+                       } else { /* RTS_needless */
                                pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
                                pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts));
                                pvRTS = NULL;
@@ -1137,8 +1134,8 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
                                cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
                                        cbMICHDR + sizeof(struct vnt_cts_fb) + sizeof(struct vnt_tx_datahead_g_fb);
                        }
-               } // Auto Fall Back
-       } else {//802.11a/b packet
+               } /* Auto Fall Back */
+       } else {/* 802.11a/b packet */
 
                if (byFBOption == AUTO_FB_NONE) {
                        if (bRTS == true) {
@@ -1150,7 +1147,7 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
                                        sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_ab));
                                cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
                                        cbMICHDR + sizeof(struct vnt_rts_ab) + sizeof(struct vnt_tx_datahead_ab);
-                       } else { //RTS_needless, need MICHDR
+                       } else { /* RTS_needless, need MICHDR */
                                pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
                                pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
                                pvRTS = NULL;
@@ -1160,8 +1157,8 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
                                        cbMICHDR + sizeof(struct vnt_tx_datahead_ab);
                        }
                } else {
-                       // Auto Fall Back
-                       if (bRTS == true) {//RTS_need
+                       /* Auto Fall Back */
+                       if (bRTS == true) { /* RTS_need */
                                pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
                                pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
                                pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
@@ -1170,7 +1167,7 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
                                        sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_a_fb));
                                cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
                                        cbMICHDR + sizeof(struct vnt_rts_a_fb) + sizeof(struct vnt_tx_datahead_a_fb);
-                       } else { //RTS_needless
+                       } else { /* RTS_needless */
                                pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
                                pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
                                pvRTS = NULL;
@@ -1179,7 +1176,7 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
                                cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
                                        cbMICHDR + sizeof(struct vnt_tx_datahead_a_fb);
                        }
-               } // Auto Fall Back
+               } /* Auto Fall Back */
        }
 
        td_info->mic_hdr = pMICHDR;
@@ -1308,10 +1305,18 @@ int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx,
                            priv->hw->conf.chandef.chan->hw_value);
        }
 
-       if (current_rate > RATE_11M)
-               pkt_type = (u8)priv->byPacketType;
-       else
+       if (current_rate > RATE_11M) {
+               if (info->band == IEEE80211_BAND_5GHZ) {
+                       pkt_type = PK_TYPE_11A;
+               } else {
+                       if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+                               pkt_type = PK_TYPE_11GB;
+                       else
+                               pkt_type = PK_TYPE_11GA;
+               }
+       } else {
                pkt_type = PK_TYPE_11B;
+       }
 
        /*Set fifo controls */
        if (pkt_type == PK_TYPE_11A)
@@ -1505,8 +1510,6 @@ int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif)
 int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
                      struct ieee80211_bss_conf *conf)
 {
-       int ret;
-
        VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
 
        VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
@@ -1515,7 +1518,5 @@ int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
 
        CARDbSetBeaconPeriod(priv, conf->beacon_int);
 
-       ret = vnt_beacon_make(priv, vif);
-
-       return ret;
+       return vnt_beacon_make(priv, vif);
 }
index 7d3e3ef9f17fffc4299bda8a3b1f5451c493a832..531bf0069373fa0c8a9a934de045b465e1ba0e09 100644 (file)
@@ -24,7 +24,6 @@
  * Author: Jerry Chen
  *
  * Date: Jan 29, 2003
- *
  */
 
 #ifndef __SROM_H__
 
 #define EEP_MAX_CONTEXT_SIZE    256
 
-#define CB_EEPROM_READBYTE_WAIT 900     //us
+#define CB_EEPROM_READBYTE_WAIT 900     /* us */
 
 #define W_MAX_I2CRETRY          0x0fff
 
-//
-// Contents in the EEPROM
-//
-#define EEP_OFS_PAR         0x00        // physical address
+/* Contents in the EEPROM */
+#define EEP_OFS_PAR         0x00        /* physical address */
 #define EEP_OFS_ANTENNA     0x16
 #define EEP_OFS_RADIOCTL    0x17
-#define EEP_OFS_RFTYPE      0x1B        // for select RF
-#define EEP_OFS_MINCHANNEL  0x1C        // Min Channel #
-#define EEP_OFS_MAXCHANNEL  0x1D        // Max Channel #
-#define EEP_OFS_SIGNATURE   0x1E        //
-#define EEP_OFS_ZONETYPE    0x1F        //
-#define EEP_OFS_RFTABLE     0x20        // RF POWER TABLE
+#define EEP_OFS_RFTYPE      0x1B        /* for select RF */
+#define EEP_OFS_MINCHANNEL  0x1C        /* Min Channel # */
+#define EEP_OFS_MAXCHANNEL  0x1D        /* Max Channel # */
+#define EEP_OFS_SIGNATURE   0x1E
+#define EEP_OFS_ZONETYPE    0x1F
+#define EEP_OFS_RFTABLE     0x20        /* RF POWER TABLE */
 #define EEP_OFS_PWR_CCK     0x20
 #define EEP_OFS_SETPT_CCK   0x21
 #define EEP_OFS_PWR_OFDMG   0x23
 #define EEP_OFS_SETPT_OFDMG 0x24
-#define EEP_OFS_PWR_FORMULA_OST  0x26   //
+#define EEP_OFS_PWR_FORMULA_OST  0x26
 #define EEP_OFS_MAJOR_VER 0x2E
 #define EEP_OFS_MINOR_VER 0x2F
 #define EEP_OFS_CCK_PWR_TBL     0x30
 #define EEP_OFS_CCK_PWR_dBm     0x3F
 #define EEP_OFS_OFDM_PWR_TBL    0x40
 #define EEP_OFS_OFDM_PWR_dBm    0x4F
-//{{ RobertYu: 20041124
+/*{{ RobertYu: 20041124 */
 #define EEP_OFS_SETPT_OFDMA         0x4E
 #define EEP_OFS_OFDMA_PWR_TBL       0x50
-//}}
+/*}}*/
 #define EEP_OFS_OFDMA_PWR_dBm       0xD2
 
-//----------need to remove --------------------
-#define EEP_OFS_BBTAB_LEN   0x70        // BB Table Length
-#define EEP_OFS_BBTAB_ADR   0x71        // BB Table Offset
-#define EEP_OFS_CHECKSUM    0xFF        // reserved area for baseband 28h ~ 78h
+/*----------need to remove --------------------*/
+#define EEP_OFS_BBTAB_LEN   0x70        /* BB Table Length */
+#define EEP_OFS_BBTAB_ADR   0x71        /* BB Table Offset */
+#define EEP_OFS_CHECKSUM    0xFF        /* reserved area for baseband 28h~78h */
 
-#define EEP_I2C_DEV_ID      0x50        // EEPROM device address on the I2C bus
+#define EEP_I2C_DEV_ID      0x50        /* EEPROM device address on I2C bus */
 
-//
-// Bits in EEP_OFS_ANTENNA
-//
+/* Bits in EEP_OFS_ANTENNA */
 #define EEP_ANTENNA_MAIN    0x01
 #define EEP_ANTENNA_AUX     0x02
 #define EEP_ANTINV          0x04
 
-//
-// Bits in EEP_OFS_RADIOCTL
-//
+/* Bits in EEP_OFS_RADIOCTL */
 #define EEP_RADIOCTL_ENABLE 0x80
 #define EEP_RADIOCTL_INV    0x01
 
 
 /*---------------------  Export Functions  --------------------------*/
 
-unsigned char SROMbyReadEmbedded(void __iomem *dwIoBase, unsigned char byContntOffset);
+unsigned char SROMbyReadEmbedded(void __iomem *dwIoBase,
+                                unsigned char byContntOffset);
 
 void SROMvReadAllContents(void __iomem *dwIoBase, unsigned char *pbyEepromRegs);
 
-void SROMvReadEtherAddress(void __iomem *dwIoBase, unsigned char *pbyEtherAddress);
+void SROMvReadEtherAddress(void __iomem *dwIoBase,
+                          unsigned char *pbyEtherAddress);
 
-#endif // __EEPROM_H__
+#endif /* __EEPROM_H__*/
index 607b78f7a6a03aa45ba5d08628822a0584677469..597efefc017f9b8f9f0d4ab7a3975a7e78aff487 100644 (file)
@@ -55,4 +55,4 @@
 #define MAKEDWORD(lw, hw)   ((unsigned long)(((unsigned short)(lw)) | (((unsigned long)((unsigned short)(hw))) << 16)))
 #endif
 
-#endif // __TMACRO_H__
+#endif /* __TMACRO_H__ */
index a177645af83e6e8d5b37491b0b6096f74fdf55b9..d440f284bf1891c8bec4c1afc95996a8241debea 100644 (file)
@@ -61,7 +61,7 @@ int vnt_download_firmware(struct vnt_private *priv)
 
        buffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
        if (!buffer)
-               goto out;
+               goto free_fw;
 
        for (ii = 0; ii < fw->size; ii += FIRMWARE_CHUNK_SIZE) {
                length = min_t(int, fw->size - ii, FIRMWARE_CHUNK_SIZE);
index bb37e33b9ffa00001fc64597649adee59848420f..5dfac05b9cf17002d1cb0f049ed9d92d6bb91488 100644 (file)
@@ -30,6 +30,8 @@
  * Revision History:
  */
 
+#include <linux/etherdevice.h>
+
 #include "desc.h"
 #include "mac.h"
 #include "usbpipe.h"
@@ -126,7 +128,7 @@ void vnt_mac_set_keyentry(struct vnt_private *priv, u16 key_ctl, u32 entry_idx,
        offset += (entry_idx * MISCFIFO_KEYENTRYSIZE);
 
        set_key.u.write.key_ctl = cpu_to_le16(key_ctl);
-       memcpy(set_key.u.write.addr, addr, ETH_ALEN);
+       ether_addr_copy(set_key.u.write.addr, addr);
 
        /* swap over swap[0] and swap[1] to get correct write order */
        swap(set_key.u.swap[0], set_key.u.swap[1]);
index 71adc1f61838654c0abb10bd377057de19a18a43..ab3ab84cb0a717179472971d2817724441cbb350 100644 (file)
@@ -963,6 +963,7 @@ vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id)
        hw = ieee80211_alloc_hw(sizeof(struct vnt_private), &vnt_mac_ops);
        if (!hw) {
                dev_err(&udev->dev, "could not register ieee80211_hw\n");
+               rc = -ENOMEM;
                goto err_nomem;
        }
 
index 33baf26de4b581b1a354f872baa536466f920c09..f6c2cf8590c4811471a88c9e82be1d4151a11618 100644 (file)
@@ -755,9 +755,9 @@ static void vnt_fill_txkey(struct vnt_usb_send_context *tx_context,
                else
                        mic_hdr->hlen = cpu_to_be16(22);
 
-               memcpy(mic_hdr->addr1, hdr->addr1, ETH_ALEN);
-               memcpy(mic_hdr->addr2, hdr->addr2, ETH_ALEN);
-               memcpy(mic_hdr->addr3, hdr->addr3, ETH_ALEN);
+               ether_addr_copy(mic_hdr->addr1, hdr->addr1);
+               ether_addr_copy(mic_hdr->addr2, hdr->addr2);
+               ether_addr_copy(mic_hdr->addr3, hdr->addr3);
 
                mic_hdr->frame_control = cpu_to_le16(
                        le16_to_cpu(hdr->frame_control) & 0xc78f);
@@ -765,7 +765,7 @@ static void vnt_fill_txkey(struct vnt_usb_send_context *tx_context,
                                le16_to_cpu(hdr->seq_ctrl) & 0xf);
 
                if (ieee80211_has_a4(hdr->frame_control))
-                       memcpy(mic_hdr->addr4, hdr->addr4, ETH_ALEN);
+                       ether_addr_copy(mic_hdr->addr4, hdr->addr4);
 
 
                memcpy(key_buffer, tx_key->key, WLAN_KEY_LEN_CCMP);
index 8f2091070491fce457c0e29ffb7ddcf8af61a9f5..8dfe4381ddf76fa3a3aa9ddfb6d0cf8a878681cb 100644 (file)
@@ -1204,19 +1204,19 @@ typedef struct hfa484x_metacmd {
 #define WLAN_ACCESS_DENY       3   /* Do not authenticate "denied" stations. */
 
 /* XXX These are going away ASAP */
-typedef struct prism2sta_authlist {
+struct prism2sta_authlist {
        unsigned int cnt;
        u8 addr[WLAN_AUTH_MAX][ETH_ALEN];
        u8 assoc[WLAN_AUTH_MAX];
-} prism2sta_authlist_t;
+};
 
-typedef struct prism2sta_accesslist {
+struct prism2sta_accesslist {
        unsigned int modify;
        unsigned int cnt;
        u8 addr[WLAN_ACCESS_MAX][ETH_ALEN];
        unsigned int cnt1;
        u8 addr1[WLAN_ACCESS_MAX][ETH_ALEN];
-} prism2sta_accesslist_t;
+};
 
 typedef struct hfa384x {
        /* USB support data */
@@ -1348,10 +1348,10 @@ typedef struct hfa384x {
 
        hfa384x_InfFrame_t *scanresults;
 
-       prism2sta_authlist_t authlist;  /* Authenticated station list. */
-       unsigned int accessmode;        /* Access mode. */
-       prism2sta_accesslist_t allow;   /* Allowed station list. */
-       prism2sta_accesslist_t deny;    /* Denied station list. */
+       struct prism2sta_authlist authlist;     /* Authenticated station list. */
+       unsigned int accessmode;                /* Access mode. */
+       struct prism2sta_accesslist allow;      /* Allowed station list. */
+       struct prism2sta_accesslist deny;       /* Denied station list. */
 
 } hfa384x_t;
 
@@ -1413,7 +1413,8 @@ int hfa384x_drvr_start(hfa384x_t *hw);
 int hfa384x_drvr_stop(hfa384x_t *hw);
 int
 hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb,
-                    union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep);
+                    union p80211_hdr *p80211_hdr,
+                    struct p80211_metawep *p80211_wep);
 void hfa384x_tx_timeout(wlandevice_t *wlandev);
 
 int hfa384x_cmd_initialize(hfa384x_t *hw);
index 28cd1c4c02c8501a07a9791b9126b0a3c83f1b94..e109a7fd422ffe387f0457c695eb39518472d956 100644 (file)
@@ -557,17 +557,13 @@ void hfa384x_create(hfa384x_t *hw, struct usb_device *usb)
        INIT_WORK(&hw->link_bh, prism2sta_processing_defer);
        INIT_WORK(&hw->usb_work, hfa384x_usb_defer);
 
-       init_timer(&hw->throttle);
-       hw->throttle.function = hfa384x_usb_throttlefn;
-       hw->throttle.data = (unsigned long)hw;
+       setup_timer(&hw->throttle, hfa384x_usb_throttlefn, (unsigned long)hw);
 
-       init_timer(&hw->resptimer);
-       hw->resptimer.function = hfa384x_usbctlx_resptimerfn;
-       hw->resptimer.data = (unsigned long)hw;
+       setup_timer(&hw->resptimer, hfa384x_usbctlx_resptimerfn,
+                   (unsigned long)hw);
 
-       init_timer(&hw->reqtimer);
-       hw->reqtimer.function = hfa384x_usbctlx_reqtimerfn;
-       hw->reqtimer.data = (unsigned long)hw;
+       setup_timer(&hw->reqtimer, hfa384x_usbctlx_reqtimerfn,
+                   (unsigned long)hw);
 
        usb_init_urb(&hw->rx_urb);
        usb_init_urb(&hw->tx_urb);
@@ -577,9 +573,8 @@ void hfa384x_create(hfa384x_t *hw, struct usb_device *usb)
        hw->state = HFA384x_STATE_INIT;
 
        INIT_WORK(&hw->commsqual_bh, prism2sta_commsqual_defer);
-       init_timer(&hw->commsqual_timer);
-       hw->commsqual_timer.data = (unsigned long)hw;
-       hw->commsqual_timer.function = prism2sta_commsqual_timer;
+       setup_timer(&hw->commsqual_timer, prism2sta_commsqual_timer,
+                   (unsigned long)hw);
 }
 
 /*----------------------------------------------------------------
@@ -624,11 +619,10 @@ static hfa384x_usbctlx_t *usbctlx_alloc(void)
 {
        hfa384x_usbctlx_t *ctlx;
 
-       ctlx = kmalloc(sizeof(*ctlx), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
-       if (ctlx != NULL) {
-               memset(ctlx, 0, sizeof(*ctlx));
+       ctlx = kzalloc(sizeof(*ctlx),
+                      in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+       if (ctlx != NULL)
                init_completion(&ctlx->done);
-       }
 
        return ctlx;
 }
index 0163e062b650810b9310bf5faefde96be2972ee8..b4a15ef3a405ce78bb0044aeff03a86f566da5a8 100644 (file)
@@ -582,8 +582,6 @@ static int prism2mib_privacyinvoked(struct mibrec *mib,
                                    struct p80211msg_dot11req_mibset *msg,
                                    void *data)
 {
-       int result;
-
        if (wlandev->hostwep & HOSTWEP_DECRYPT) {
                if (wlandev->hostwep & HOSTWEP_DECRYPT)
                        mib->parm2 |= HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
@@ -591,9 +589,7 @@ static int prism2mib_privacyinvoked(struct mibrec *mib,
                        mib->parm2 |= HFA384x_WEPFLAGS_DISABLE_TXCRYPT;
        }
 
-       result = prism2mib_flag(mib, isget, wlandev, hw, msg, data);
-
-       return result;
+       return prism2mib_flag(mib, isget, wlandev, hw, msg, data);
 }
 
 /*----------------------------------------------------------------
@@ -628,11 +624,8 @@ static int prism2mib_excludeunencrypted(struct mibrec *mib,
                                        struct p80211msg_dot11req_mibset *msg,
                                        void *data)
 {
-       int result;
-
-       result = prism2mib_flag(mib, isget, wlandev, hw, msg, data);
 
-       return result;
+       return prism2mib_flag(mib, isget, wlandev, hw, msg, data);
 }
 
 /*----------------------------------------------------------------
index 10ad24a89ddd24c30913e14be13f6cd15ca0bee0..ddb294e7044ff1a9e0cd614eb965551f27aab35f 100644 (file)
@@ -51,7 +51,6 @@
 */
 
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -60,6 +59,7 @@
 #include <linux/netdevice.h>
 #include <linux/workqueue.h>
 #include <linux/byteorder/generic.h>
+#include <linux/etherdevice.h>
 
 #include <linux/io.h>
 #include <linux/delay.h>
@@ -243,7 +243,6 @@ static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb,
                             struct p80211_metawep *p80211_wep)
 {
        hfa384x_t *hw = (hfa384x_t *) wlandev->priv;
-       int result;
 
        /* If necessary, set the 802.11 WEP bit */
        if ((wlandev->hostwep & (HOSTWEP_PRIVACYINVOKED | HOSTWEP_ENCRYPT)) ==
@@ -251,9 +250,7 @@ static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb,
                p80211_hdr->a3.fc |= cpu_to_le16(WLAN_SET_FC_ISWEP(1));
        }
 
-       result = hfa384x_drvr_txframe(hw, skb, p80211_hdr, p80211_wep);
-
-       return result;
+       return hfa384x_drvr_txframe(hw, skb, p80211_hdr, p80211_wep);
 }
 
 /*----------------------------------------------------------------
@@ -1548,7 +1545,7 @@ static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev,
         ** authentication.
         */
 
-       memcpy(rec.address, inf->info.authreq.sta_addr, ETH_ALEN);
+       ether_addr_copy(rec.address, inf->info.authreq.sta_addr);
        rec.status = P80211ENUM_status_unspec_failure;
 
        /*
@@ -1661,8 +1658,8 @@ static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev,
                        if (hw->authlist.cnt >= WLAN_AUTH_MAX) {
                                rec.status = P80211ENUM_status_ap_full;
                        } else {
-                               memcpy(hw->authlist.addr[hw->authlist.cnt],
-                                      rec.address, ETH_ALEN);
+                               ether_addr_copy(hw->authlist.addr[hw->authlist.cnt],
+                                               rec.address);
                                hw->authlist.cnt++;
                                added = 1;
                        }
index 935c714f592a4768d9d3f41ec56b9131f05243f5..74e88200726ccd7da5f92f966517eb2e1dfe2d5c 100644 (file)
@@ -106,7 +106,7 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
 
        sr_data = XGI_CRT1Table[index].CR[5];
 
-       HDE = (XGI330_RefIndex[RefreshRateTableIndex].XRes >> 3);
+       HDE = XGI330_RefIndex[RefreshRateTableIndex].XRes >> 3;
 
        cr_data = XGI_CRT1Table[index].CR[3];
 
@@ -1011,8 +1011,8 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
                               XGIbios_mode[xgifb_info->mode_idx].mode_no);
                        return -EINVAL;
                }
-               info->fix.line_length = ((info->var.xres_virtual
-                               * info->var.bits_per_pixel) >> 6);
+               info->fix.line_length = (info->var.xres_virtual
+                               * info->var.bits_per_pixel) >> 6;
 
                xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
index 1f6f699e238c35eb818611d6d048a7ebebefa6e6..a47395e92d20aecaa90eb4de981e4fba3a78ceaf 100644 (file)
@@ -308,11 +308,11 @@ static void XGI_SetCRT1Timing_H(struct vb_device_info *pVBInfo,
                data |= data1;
                xgifb_reg_set(pVBInfo->P3d4, 0x05, data);
                data = xgifb_reg_get(pVBInfo->P3c4, 0x0e);
-               data = data >> 5;
+               data >>= 5;
                data = data + 3;
                if (data > 7)
                        data = data - 7;
-               data = data << 5;
+               data <<= 5;
                xgifb_reg_and_or(pVBInfo->P3c4, 0x0e, ~0xE0, data);
        }
 }
@@ -347,7 +347,7 @@ static void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
 
        data = pVBInfo->TimingV.data[6];
        data &= 0x80;
-       data = data >> 2;
+       data >>= 2;
 
        i = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
        i &= DoubleScanMode;
@@ -693,18 +693,18 @@ static void XGI_SetCRT1DE(unsigned short ModeIdIndex,
        tempbx = XGI330_ModeResInfo[resindex].VTotal;
 
        if (modeflag & HalfDCLK)
-               tempax = tempax >> 1;
+               tempax >>= 1;
 
        if (modeflag & HalfDCLK)
-               tempax = tempax << 1;
+               tempax <<= 1;
 
        temp = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
 
        if (temp & InterlaceMode)
-               tempbx = tempbx >> 1;
+               tempbx >>= 1;
 
        if (modeflag & DoubleScanMode)
-               tempbx = tempbx << 1;
+               tempbx <<= 1;
 
        tempcx = 8;
 
@@ -721,7 +721,7 @@ static void XGI_SetCRT1DE(unsigned short ModeIdIndex,
                        (unsigned short) ((tempcx & 0x0ff00) >> 10));
        xgifb_reg_set(pVBInfo->P3d4, 0x12, (unsigned short) (tempbx & 0xff));
        tempax = 0;
-       tempbx = tempbx >> 8;
+       tempbx >>= 8;
 
        if (tempbx & 0x01)
                tempax |= 0x02;
@@ -750,14 +750,14 @@ static void XGI_SetCRT1Offset(unsigned short ModeNo,
 
        /* GetOffset */
        temp = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeInfo;
-       temp = temp >> 8;
+       temp >>= 8;
        temp = XGI330_ScreenOffset[temp];
 
        temp2 = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
        temp2 &= InterlaceMode;
 
        if (temp2)
-               temp = temp << 1;
+               temp <<= 1;
 
        temp2 = pVBInfo->ModeType - ModeEGA;
 
@@ -792,7 +792,7 @@ static void XGI_SetCRT1Offset(unsigned short ModeNo,
        /* SetOffset */
        DisplayUnit = temp;
        temp2 = temp;
-       temp = temp >> 8; /* ah */
+       temp >>= 8; /* ah */
        temp &= 0x0F;
        i = xgifb_reg_get(pVBInfo->P3c4, 0x0E);
        i &= 0xF0;
@@ -809,7 +809,7 @@ static void XGI_SetCRT1Offset(unsigned short ModeNo,
        if (temp2)
                DisplayUnit >>= 1;
 
-       DisplayUnit = DisplayUnit << 5;
+       DisplayUnit <<= 5;
        ah = (DisplayUnit & 0xff00) >> 8;
        al = DisplayUnit & 0x00ff;
        if (al == 0)
@@ -912,7 +912,7 @@ static void XGI_SetCRT1VCLK(unsigned short ModeIdIndex,
                        index = data;
                        index &= 0xE0;
                        data &= 0x1F;
-                       data = data << 1;
+                       data <<= 1;
                        data += 1;
                        data |= index;
                        xgifb_reg_set(pVBInfo->P3c4, 0x2C, data);
@@ -1011,7 +1011,7 @@ static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
        data2 = 0;
        data2 |= 0x02;
        data3 = pVBInfo->ModeType - ModeVGA;
-       data3 = data3 << 2;
+       data3 <<= 2;
        data2 |= data3;
        data &= InterlaceMode;
 
@@ -1126,7 +1126,7 @@ static void XGI_LoadDAC(struct vb_device_info *pVBInfo)
                                data2 += 0x15;
 
                        outb(data2, pVBInfo->P3c9);
-                       data = data >> 2;
+                       data >>= 2;
                }
        }
 
@@ -1185,10 +1185,10 @@ static void XGI_GetLVDSResInfo(unsigned short ModeIdIndex,
        yres = XGI330_ModeResInfo[resindex].VTotal;
 
        if (modeflag & HalfDCLK)
-               xres = xres << 1;
+               xres <<= 1;
 
        if (modeflag & DoubleScanMode)
-               yres = yres << 1;
+               yres <<= 1;
 
        if (xres == 720)
                xres = 640;
@@ -1450,8 +1450,8 @@ static void XGI_SetLVDSRegs(unsigned short ModeIdIndex,
 
        xgifb_reg_set(pVBInfo->Part1Port, 0x1A, tempbx & 0x07);
 
-       tempcx = tempcx >> 3;
-       tempbx = tempbx >> 3;
+       tempcx >>= 3;
+       tempbx >>= 3;
 
        xgifb_reg_set(pVBInfo->Part1Port, 0x16,
                        (unsigned short) (tempbx & 0xff));
@@ -1473,9 +1473,9 @@ static void XGI_SetLVDSRegs(unsigned short ModeIdIndex,
                tempcx -= tempax;
 
        tempax = tempbx & 0x07;
-       tempax = tempax >> 5;
-       tempcx = tempcx >> 3;
-       tempbx = tempbx >> 3;
+       tempax >>= 5;
+       tempcx >>= 3;
+       tempbx >>= 3;
 
        tempcx &= 0x1f;
        tempax |= tempcx;
@@ -1600,7 +1600,7 @@ static void XGI_SetLVDSRegs(unsigned short ModeIdIndex,
        temp1 = pVBInfo->VGAHDE << 16;
 
        temp1 /= temp3;
-       temp3 = temp3 << 16;
+       temp3 <<= 16;
        temp1 -= 1;
 
        temp3 = (temp3 & 0xffff0000) + (temp1 & 0xffff);
@@ -1622,10 +1622,10 @@ static void XGI_SetLVDSRegs(unsigned short ModeIdIndex,
        xgifb_reg_set(pVBInfo->Part1Port, 0x21,
                        (unsigned short) (tempbx & 0xff));
 
-       temp3 = temp3 >> 16;
+       temp3 >>= 16;
 
        if (modeflag & HalfDCLK)
-               temp3 = temp3 >> 1;
+               temp3 >>= 1;
 
        xgifb_reg_set(pVBInfo->Part1Port, 0x22,
                        (unsigned short) ((temp3 >> 8) & 0xff));
@@ -1909,7 +1909,7 @@ static void XGI_GetVBInfo(unsigned short ModeIdIndex,
        tempbx = tempbx | temp;
        temp = xgifb_reg_get(pVBInfo->P3d4, 0x31);
        push = temp;
-       push = push << 8;
+       push <<= 8;
        tempax = temp << 8;
        tempbx = tempbx | tempax;
        temp = (SetCRT2ToDualEdge | SetCRT2ToYPbPr525750 | XGI_SetCRT2ToLCDA
@@ -2107,7 +2107,7 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeIdIndex,
                        if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
                                tempax &= 0x0F;
                        else
-                               tempax = tempax >> 4;
+                               tempax >>= 4;
 
                        if ((resinfo == 6) || (resinfo == 9)) {
                                if (tempax >= 3)
@@ -2182,7 +2182,7 @@ static unsigned char XG21GPIODataTransfer(unsigned char ujDate)
        unsigned char i = 0;
 
        for (i = 0; i < 8; i++) {
-               ujRet = ujRet << 1;
+               ujRet <<= 1;
                ujRet |= (ujDate >> i) & 1;
        }
 
@@ -2494,7 +2494,7 @@ static void XGI_GetRAMDAC2DATA(unsigned short ModeIdIndex,
        tempcx = (unsigned short)
                        XGI_CRT1Table[CRT1Index].CR[14] << 8;
        tempcx &= 0x0100;
-       tempcx = tempcx << 2;
+       tempcx <<= 2;
        tempbx |= tempcx;
        temp1 = (unsigned short) XGI_CRT1Table[CRT1Index].CR[9];
 
@@ -2745,7 +2745,7 @@ static unsigned short XGI_GetOffset(unsigned short ModeNo,
        temp = XGI330_ScreenOffset[index];
 
        if (infoflag & InterlaceMode)
-               temp = temp << 1;
+               temp <<= 1;
 
        colordepth = XGI_GetColorDepth(ModeIdIndex);
 
@@ -2754,7 +2754,7 @@ static unsigned short XGI_GetOffset(unsigned short ModeNo,
                colordepth = ColorDepth[temp];
                temp = 0x6B;
                if (infoflag & InterlaceMode)
-                       temp = temp << 1;
+                       temp <<= 1;
        }
        return temp * colordepth;
 }
@@ -2826,7 +2826,7 @@ static void XGI_SetGroup1(unsigned short ModeIdIndex,
                xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp);
                tempcx = ((pVBInfo->VGAHT - pVBInfo->VGAHDE) / 2) >> 2;
                pushbx = pVBInfo->VGAHDE / 2 + 16;
-               tempcx = tempcx >> 1;
+               tempcx >>= 1;
                tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
                tempcx += tempbx;
 
@@ -2861,7 +2861,7 @@ static void XGI_SetGroup1(unsigned short ModeIdIndex,
                xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp);
                tempcx = (pVBInfo->VGAHT - pVBInfo->VGAHDE) >> 2; /* cx */
                pushbx = pVBInfo->VGAHDE + 16;
-               tempcx = tempcx >> 1;
+               tempcx >>= 1;
                tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
                tempcx += tempbx;
 
@@ -2980,7 +2980,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
        tempax = pVBInfo->VGAHDE; /* 0x04 Horizontal Display End */
 
        if (modeflag & HalfDCLK)
-               tempax = tempax >> 1;
+               tempax >>= 1;
 
        tempax = (tempax / tempcx) - 1;
        tempbx |= ((tempax & 0x00FF) << 8);
@@ -3015,7 +3015,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
                tempax = pVBInfo->VGAHT;
 
        if (modeflag & HalfDCLK)
-               tempax = tempax >> 1;
+               tempax >>= 1;
 
        tempax = (tempax / tempcx) - 5;
        tempcx = tempax; /* 20030401 0x07 horizontal Retrace Start */
@@ -3142,11 +3142,11 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
 
        tempax = push1;
        tempax -= tempbx; /* 0x0C Vertical Retrace Start */
-       tempax = tempax >> 2;
+       tempax >>= 2;
        push1 = tempax; /* push ax */
 
        if (resinfo != 0x09) {
-               tempax = tempax << 1;
+               tempax <<= 1;
                tempbx += tempax;
        }
 
@@ -3179,7 +3179,7 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
                }
        }
        tempax = push1;
-       tempax = tempax >> 2;
+       tempax >>= 2;
        tempax++;
        tempax += tempbx;
        push1 = tempax; /* push ax */
@@ -3332,7 +3332,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
 
        if (pVBInfo->VDE <= tempax) {
                tempax -= pVBInfo->VDE;
-               tempax = tempax >> 2;
+               tempax >>= 2;
                tempax = (tempax & 0x00FF) | ((tempax & 0x00FF) << 8);
                push1 = tempax;
                temp = (tempax & 0xFF00) >> 8;
@@ -3377,7 +3377,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
        tempcx = pVBInfo->HT;
 
        if (XGI_IsLCDDualLink(pVBInfo))
-               tempcx = tempcx >> 1;
+               tempcx >>= 1;
 
        tempcx -= 2;
        temp = tempcx & 0x00FF;
@@ -3394,7 +3394,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
                tempcx -= 4;
 
        temp = tempcx & 0x00FF;
-       temp = temp << 4;
+       temp <<= 4;
        xgifb_reg_and_or(pVBInfo->Part2Port, 0x22, 0x0F, temp);
 
        tempbx = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);
@@ -3403,7 +3403,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
        temp = tempbx & 0x00FF;
        xgifb_reg_set(pVBInfo->Part2Port, 0x24, temp);
        temp = (tempbx & 0xFF00) >> 8;
-       temp = temp << 4;
+       temp <<= 4;
        xgifb_reg_and_or(pVBInfo->Part2Port, 0x25, 0x0F, temp);
 
        tempbx = push2;
@@ -3428,7 +3428,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
                tempcx -= 4;
 
        temp = tempcx & 0xFF;
-       temp = temp << 4;
+       temp <<= 4;
        xgifb_reg_and_or(pVBInfo->Part2Port, 0x2A, 0x0F, temp);
 
        tempcx = push1; /* pop cx */
@@ -3436,7 +3436,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
        temp = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);
        tempcx -= temp;
        temp = tempcx & 0x00FF;
-       temp = temp << 4;
+       temp <<= 4;
        xgifb_reg_and_or(pVBInfo->Part2Port, 0x2D, 0x0F, temp);
 
        tempcx -= 11;
@@ -3462,9 +3462,9 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
                    (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) {
                        if (!(pVBInfo->TVInfo &
                            (TVSetYPbPr525p | TVSetYPbPr750p)))
-                               tempbx = tempbx >> 1;
+                               tempbx >>= 1;
                } else
-                       tempbx = tempbx >> 1;
+                       tempbx >>= 1;
        }
 
        tempbx -= 2;
@@ -3514,7 +3514,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
                if (pVBInfo->VBInfo & SetCRT2ToTV) {
                        if (!(pVBInfo->TVInfo & (TVSetYPbPr525p
                                        | TVSetYPbPr750p)))
-                               tempbx = tempbx >> 1;
+                               tempbx >>= 1;
                }
 
                if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
@@ -3627,7 +3627,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
        xgifb_reg_set(pVBInfo->Part2Port, 0x4c, temp);
 
        temp = ((tempcx & 0xFF00) >> 8) & 0x03;
-       temp = temp << 2;
+       temp <<= 2;
        temp |= ((tempbx & 0xFF00) >> 8) & 0x03;
 
        if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
@@ -3691,13 +3691,13 @@ static void XGI_SetLCDRegs(unsigned short ModeIdIndex,
        tempbx = pVBInfo->HDE; /* RHACTE=HDE-1 */
 
        if (XGI_IsLCDDualLink(pVBInfo))
-               tempbx = tempbx >> 1;
+               tempbx >>= 1;
 
        tempbx -= 1;
        temp = tempbx & 0x00FF;
        xgifb_reg_set(pVBInfo->Part2Port, 0x2C, temp);
        temp = (tempbx & 0xFF00) >> 8;
-       temp = temp << 4;
+       temp <<= 4;
        xgifb_reg_and_or(pVBInfo->Part2Port, 0x2B, 0x0F, temp);
        temp = 0x01;
 
@@ -3713,7 +3713,7 @@ static void XGI_SetLCDRegs(unsigned short ModeIdIndex,
        temp = tempcx & 0x00FF; /* RVTVT=VT-1 */
        xgifb_reg_set(pVBInfo->Part2Port, 0x19, temp);
        temp = (tempcx & 0xFF00) >> 8;
-       temp = temp << 5;
+       temp <<= 5;
        xgifb_reg_set(pVBInfo->Part2Port, 0x1A, temp);
        xgifb_reg_and_or(pVBInfo->Part2Port, 0x09, 0xF0, 0x00);
        xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0xF0, 0x00);
@@ -3770,7 +3770,7 @@ static void XGI_SetLCDRegs(unsigned short ModeIdIndex,
        tempch = ((tempcx & 0xFF00) >> 8) & 0x07;
        tempbh = ((tempbx & 0xFF00) >> 8) & 0x07;
        tempah = tempch;
-       tempah = tempah << 3;
+       tempah <<= 3;
        tempah |= tempbh;
        xgifb_reg_set(pVBInfo->Part2Port, 0x02, tempah);
 
@@ -3787,7 +3787,7 @@ static void XGI_SetLCDRegs(unsigned short ModeIdIndex,
        temp = tempbx & 0x00FF; /* RTVACTEE=lcdvrs */
        xgifb_reg_set(pVBInfo->Part2Port, 0x04, temp);
        temp = (tempbx & 0xFF00) >> 8;
-       temp = temp << 4;
+       temp <<= 4;
        temp |= (tempcx & 0x000F);
        xgifb_reg_set(pVBInfo->Part2Port, 0x01, temp);
        tempcx = pushbx;
@@ -3796,9 +3796,9 @@ static void XGI_SetLCDRegs(unsigned short ModeIdIndex,
        tempbx &= 0x0FFF;
 
        if (XGI_IsLCDDualLink(pVBInfo)) {
-               tempax = tempax >> 1;
-               tempbx = tempbx >> 1;
-               tempcx = tempcx >> 1;
+               tempax >>= 1;
+               tempbx >>= 1;
+               tempcx >>= 1;
        }
 
        if (pVBInfo->VBType & VB_SIS302LV)
@@ -3826,9 +3826,9 @@ static void XGI_SetLCDRegs(unsigned short ModeIdIndex,
        tempax = pVBInfo->HT;
        tempbx = pVBInfo->LCDHRS;
        if (XGI_IsLCDDualLink(pVBInfo)) {
-               tempax = tempax >> 1;
-               tempbx = tempbx >> 1;
-               tempcx = tempcx >> 1;
+               tempax >>= 1;
+               tempbx >>= 1;
+               tempcx >>= 1;
        }
 
        if (pVBInfo->VBType & VB_SIS302LV)
@@ -3843,7 +3843,7 @@ static void XGI_SetLCDRegs(unsigned short ModeIdIndex,
        xgifb_reg_set(pVBInfo->Part2Port, 0x1C, temp);
 
        temp = (tempbx & 0xFF00) >> 8;
-       temp = temp << 4;
+       temp <<= 4;
        xgifb_reg_and_or(pVBInfo->Part2Port, 0x1D, ~0x0F0, temp);
        temp = tempcx & 0x00FF; /* RHSYEXP2S=lcdhre */
        xgifb_reg_set(pVBInfo->Part2Port, 0x21, temp);
@@ -4044,10 +4044,10 @@ static void XGI_SetGroup4(unsigned short ModeIdIndex,
        tempbx = pVBInfo->VGAHDE;
 
        if (modeflag & HalfDCLK)
-               tempbx = tempbx >> 1;
+               tempbx >>= 1;
 
        if (XGI_IsLCDDualLink(pVBInfo))
-               tempbx = tempbx >> 1;
+               tempbx >>= 1;
 
        if (tempcx & SetCRT2ToHiVision) {
                temp = 0;
@@ -4107,7 +4107,7 @@ static void XGI_SetGroup4(unsigned short ModeIdIndex,
        xgifb_reg_set(pVBInfo->Part4Port, 0x1A, temp);
        tempbx = (unsigned short) (tempebx >> 16);
        temp = tempbx & 0x00FF;
-       temp = temp << 4;
+       temp <<= 4;
        temp |= ((tempcx & 0xFF00) >> 8);
        xgifb_reg_set(pVBInfo->Part4Port, 0x19, temp);
 
@@ -4118,10 +4118,10 @@ static void XGI_SetGroup4(unsigned short ModeIdIndex,
                xgifb_reg_set(pVBInfo->Part4Port, 0x1C, temp);
                tempax = pVBInfo->VGAHDE;
                if (modeflag & HalfDCLK)
-                       tempax = tempax >> 1;
+                       tempax >>= 1;
 
                if (XGI_IsLCDDualLink(pVBInfo))
-                       tempax = tempax >> 1;
+                       tempax >>= 1;
 
                if (pVBInfo->VBInfo & SetCRT2ToLCD) {
                        if (tempax > 800)
@@ -4162,7 +4162,7 @@ static void XGI_SetGroup4(unsigned short ModeIdIndex,
                xgifb_reg_and_or(pVBInfo->Part4Port, 0x1F, 0x00C0, temp);
                tempbx = pVBInfo->HT;
                if (XGI_IsLCDDualLink(pVBInfo))
-                       tempbx = tempbx >> 1;
+                       tempbx >>= 1;
                tempbx = (tempbx >> 1) - 2;
                temp = ((tempbx & 0x0700) >> 8) << 3;
                xgifb_reg_and_or(pVBInfo->Part4Port, 0x21, 0x00C0, temp);
@@ -4622,7 +4622,7 @@ static void XGI_SetDelayComp(struct vb_device_info *pVBInfo)
                        tempbl = XGI301TVDelay;
 
                        if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
-                               tempbl = tempbl >> 4;
+                               tempbl >>= 4;
                        if (pVBInfo->VBInfo &
                            (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
                                tempbh = XGI301LCDDelay;
@@ -4785,7 +4785,7 @@ static void XGI_SetAntiFlicker(struct vb_device_info *pVBInfo)
        tempbx = XGI_GetTVPtrIndex(pVBInfo);
        tempbx &= 0xFE;
        tempah = TVAntiFlickList[tempbx];
-       tempah = tempah << 4;
+       tempah <<= 4;
 
        xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0x8F, tempah);
 }
@@ -4799,7 +4799,7 @@ static void XGI_SetEdgeEnhance(struct vb_device_info *pVBInfo)
        tempbx = XGI_GetTVPtrIndex(pVBInfo);
        tempbx &= 0xFE;
        tempah = TVEdgeList[tempbx];
-       tempah = tempah << 5;
+       tempah <<= 5;
 
        xgifb_reg_and_or(pVBInfo->Part2Port, 0x3A, 0x1F, tempah);
 }
@@ -5101,7 +5101,7 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
        unsigned short RefreshRateTableIndex, i, index, temp;
 
        index = xgifb_reg_get(pVBInfo->P3d4, 0x33);
-       index = index >> pVBInfo->SelectCRT2Rate;
+       index >>= pVBInfo->SelectCRT2Rate;
        index &= 0x0F;
 
        if (pVBInfo->LCDInfo & LCDNonExpanding)
index 2accb6e47beb35c1eff10256f7a85d749fe6d590..77d64251af40451f8e897eac1813599e3ba499d0 100644 (file)
@@ -1181,7 +1181,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
         * traditional iSCSI block I/O.
         */
        if (iscsit_allocate_iovecs(cmd) < 0) {
-               return iscsit_add_reject_cmd(cmd,
+               return iscsit_reject_cmd(cmd,
                                ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
        }
        immed_data = cmd->immediate_data;
@@ -3468,6 +3468,7 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
                                                tpg_np_list) {
                                struct iscsi_np *np = tpg_np->tpg_np;
                                bool inaddr_any = iscsit_check_inaddr_any(np);
+                               char *fmt_str;
 
                                if (np->np_network_transport != network_transport)
                                        continue;
@@ -3495,8 +3496,12 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
                                        }
                                }
 
-                               len = sprintf(buf, "TargetAddress="
-                                       "%s:%hu,%hu",
+                               if (np->np_sockaddr.ss_family == AF_INET6)
+                                       fmt_str = "TargetAddress=[%s]:%hu,%hu";
+                               else
+                                       fmt_str = "TargetAddress=%s:%hu,%hu";
+
+                               len = sprintf(buf, fmt_str,
                                        inaddr_any ? conn->local_ip : np->np_ip,
                                        np->np_port,
                                        tpg->tpgt);
index 79b4ec3ca2db12416a692fba785a09b462e3169f..7faa6aef9a4d5429cbf1d3810ebb181f7a911beb 100644 (file)
@@ -781,8 +781,8 @@ int se_dev_set_emulate_fua_write(struct se_device *dev, int flag)
        }
        if (flag &&
            dev->transport->get_write_cache) {
-               pr_err("emulate_fua_write not supported for this device\n");
-               return -EINVAL;
+               pr_warn("emulate_fua_write not supported for this device, ignoring\n");
+               return 0;
        }
        if (dev->export_count) {
                pr_err("emulate_fua_write cannot be changed with active"
index d1ec5804c0bb94cebeb22d5038b4861393047ba0..76c515dd802b489116dd73f342520dff8326a67e 100644 (file)
@@ -25,7 +25,7 @@
  * Function to allocate regfields which are common
  * between syscfg and memory mapped based sensors
  */
-int st_thermal_alloc_regfields(struct st_thermal_sensor *sensor)
+static int st_thermal_alloc_regfields(struct st_thermal_sensor *sensor)
 {
        struct device *dev = sensor->dev;
        struct regmap *regmap = sensor->regmap;
index 067bfcdb91d678aefb4fb5ca461024dd0792b699..fc0c9e198710327bbd10983b895eac4d740bb258 100644 (file)
@@ -157,7 +157,7 @@ static const struct st_thermal_sensor_ops st_mmap_sensor_ops = {
 };
 
 /* Compatible device data stih416 mpe thermal sensor */
-const struct st_thermal_compat_data st_416mpe_cdata = {
+static const struct st_thermal_compat_data st_416mpe_cdata = {
        .reg_fields             = st_mmap_thermal_regfields,
        .ops                    = &st_mmap_sensor_ops,
        .calibration_val        = 14,
@@ -166,7 +166,7 @@ const struct st_thermal_compat_data st_416mpe_cdata = {
 };
 
 /* Compatible device data stih407 thermal sensor */
-const struct st_thermal_compat_data st_407_cdata = {
+static const struct st_thermal_compat_data st_407_cdata = {
        .reg_fields             = st_mmap_thermal_regfields,
        .ops                    = &st_mmap_sensor_ops,
        .calibration_val        = 16,
@@ -174,19 +174,19 @@ const struct st_thermal_compat_data st_407_cdata = {
        .crit_temp              = 120,
 };
 
-static struct of_device_id st_mmap_thermal_of_match[] = {
+static const struct of_device_id st_mmap_thermal_of_match[] = {
        { .compatible = "st,stih416-mpe-thermal", .data = &st_416mpe_cdata },
        { .compatible = "st,stih407-thermal",     .data = &st_407_cdata },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, st_mmap_thermal_of_match);
 
-int st_mmap_probe(struct platform_device *pdev)
+static int st_mmap_probe(struct platform_device *pdev)
 {
        return st_thermal_register(pdev,  st_mmap_thermal_of_match);
 }
 
-int st_mmap_remove(struct platform_device *pdev)
+static int st_mmap_remove(struct platform_device *pdev)
 {
        return st_thermal_unregister(pdev);
 }
index 26d36a242bb89d63dec3b110e1eaa96b4c4fad65..3df5b789070325db13361d14b33eb4817bfc0d8d 100644 (file)
@@ -104,7 +104,7 @@ static const struct st_thermal_sensor_ops st_syscfg_sensor_ops = {
 };
 
 /* Compatible device data for stih415 sas thermal sensor */
-const struct st_thermal_compat_data st_415sas_cdata = {
+static const struct st_thermal_compat_data st_415sas_cdata = {
        .sys_compat             = "st,stih415-front-syscfg",
        .reg_fields             = st_415sas_regfields,
        .ops                    = &st_syscfg_sensor_ops,
@@ -114,7 +114,7 @@ const struct st_thermal_compat_data st_415sas_cdata = {
 };
 
 /* Compatible device data for stih415 mpe thermal sensor */
-const struct st_thermal_compat_data st_415mpe_cdata = {
+static const struct st_thermal_compat_data st_415mpe_cdata = {
        .sys_compat             = "st,stih415-system-syscfg",
        .reg_fields             = st_415mpe_regfields,
        .ops                    = &st_syscfg_sensor_ops,
@@ -124,7 +124,7 @@ const struct st_thermal_compat_data st_415mpe_cdata = {
 };
 
 /* Compatible device data for stih416 sas thermal sensor */
-const struct st_thermal_compat_data st_416sas_cdata = {
+static const struct st_thermal_compat_data st_416sas_cdata = {
        .sys_compat             = "st,stih416-front-syscfg",
        .reg_fields             = st_416sas_regfields,
        .ops                    = &st_syscfg_sensor_ops,
@@ -134,7 +134,7 @@ const struct st_thermal_compat_data st_416sas_cdata = {
 };
 
 /* Compatible device data for stid127 thermal sensor */
-const struct st_thermal_compat_data st_127_cdata = {
+static const struct st_thermal_compat_data st_127_cdata = {
        .sys_compat             = "st,stid127-cpu-syscfg",
        .reg_fields             = st_127_regfields,
        .ops                    = &st_syscfg_sensor_ops,
@@ -143,7 +143,7 @@ const struct st_thermal_compat_data st_127_cdata = {
        .crit_temp              = 120,
 };
 
-static struct of_device_id st_syscfg_thermal_of_match[] = {
+static const struct of_device_id st_syscfg_thermal_of_match[] = {
        { .compatible = "st,stih415-sas-thermal", .data = &st_415sas_cdata },
        { .compatible = "st,stih415-mpe-thermal", .data = &st_415mpe_cdata },
        { .compatible = "st,stih416-sas-thermal", .data = &st_416sas_cdata },
@@ -152,12 +152,12 @@ static struct of_device_id st_syscfg_thermal_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, st_syscfg_thermal_of_match);
 
-int st_syscfg_probe(struct platform_device *pdev)
+static int st_syscfg_probe(struct platform_device *pdev)
 {
        return st_thermal_register(pdev, st_syscfg_thermal_of_match);
 }
 
-int st_syscfg_remove(struct platform_device *pdev)
+static int st_syscfg_remove(struct platform_device *pdev)
 {
        return st_thermal_unregister(pdev);
 }
index 174d3bcf8bd7a16a161cdf94c53e8d14efaa55a6..4108db7e10c1094622d4abca08017db3125cf80e 100644 (file)
@@ -458,8 +458,10 @@ static void update_temperature(struct thermal_zone_device *tz)
 
        ret = thermal_zone_get_temp(tz, &temp);
        if (ret) {
-               dev_warn(&tz->device, "failed to read out thermal zone %d\n",
-                        tz->id);
+               if (ret != -EAGAIN)
+                       dev_warn(&tz->device,
+                                "failed to read out thermal zone (%d)\n",
+                                ret);
                return;
        }
 
index 967b2c2b7cf1063e6d638dcb2e7b3b3b9bde37f0..0655fecf8240593cd53a312c535e5f7296f5c280 100644 (file)
@@ -229,7 +229,6 @@ static int goldfish_tty_probe(struct platform_device *pdev)
 {
        struct goldfish_tty *qtty;
        int ret = -EINVAL;
-       int i;
        struct resource *r;
        struct device *ttydev;
        void __iomem *base;
@@ -293,7 +292,6 @@ static int goldfish_tty_probe(struct platform_device *pdev)
        mutex_unlock(&goldfish_tty_lock);
        return 0;
 
-       tty_unregister_device(goldfish_tty_driver, i);
 err_tty_register_device_failed:
        free_irq(irq, pdev);
 err_request_irq_failed:
index 5c77e1eac4eea77b80100d86abb7508df2be3331..ad7031a4f3c4dd5071c39456d9f38982056592f2 100644 (file)
@@ -1455,7 +1455,7 @@ static void __handle_setup_get_version_rsp(struct ipw_hardware *hw)
                        return;
                }
 
-               set_RTS(hw, PRIO_SETUP, channel_idx,
+               ret = set_RTS(hw, PRIO_SETUP, channel_idx,
                        (hw->control_lines [channel_idx] &
                         IPW_CONTROL_LINE_RTS) != 0);
                if (ret) {
index 259a4d5a4e8f4ca4ce305a69ca8ed469106c1d16..843f2cdc280b9d178d09469eb0363658d6a69805 100644 (file)
@@ -275,6 +275,7 @@ static struct sysrq_key_op sysrq_showregs_op = {
 static void sysrq_handle_showstate(int key)
 {
        show_state();
+       show_workqueue_state();
 }
 static struct sysrq_key_op sysrq_showstate_op = {
        .handler        = sysrq_handle_showstate,
index 2f1e2aa42b446ef608b8b07f9dcf4e2a80711ded..d8926c6cd2a8ea4a374aef845522f40fdcba1cb7 100644 (file)
@@ -5,6 +5,7 @@
 # Object files in subdirectories
 
 obj-$(CONFIG_USB)              += core/
+obj-$(CONFIG_USB_SUPPORT)      += phy/
 
 obj-$(CONFIG_USB_DWC3)         += dwc3/
 obj-$(CONFIG_USB_DWC2)         += dwc2/
@@ -48,7 +49,6 @@ obj-$(CONFIG_USB_MICROTEK)    += image/
 obj-$(CONFIG_USB_SERIAL)       += serial/
 
 obj-$(CONFIG_USB)              += misc/
-obj-$(CONFIG_USB_SUPPORT)      += phy/
 obj-$(CONFIG_EARLY_PRINTK_DBGP)        += early/
 
 obj-$(CONFIG_USB_ATM)          += atm/
index 5a459377574bcdc3436314ea17284fa1ad7ea3e9..888998a7fe314c4ee3f25298f2c81f0d429365c4 100644 (file)
@@ -952,7 +952,7 @@ static void uea_load_page_e1(struct work_struct *work)
        int i;
 
        /* reload firmware when reboot start and it's loaded already */
-       if (ovl == 0 && pageno == 0 && sc->dsp_firm) {
+       if (ovl == 0 && pageno == 0) {
                release_firmware(sc->dsp_firm);
                sc->dsp_firm = NULL;
        }
@@ -1074,7 +1074,7 @@ static void uea_load_page_e4(struct work_struct *work)
        uea_dbg(INS_TO_USBDEV(sc), "sending DSP page %u\n", pageno);
 
        /* reload firmware when reboot start and it's loaded already */
-       if (pageno == 0 && sc->dsp_firm) {
+       if (pageno == 0) {
                release_firmware(sc->dsp_firm);
                sc->dsp_firm = NULL;
        }
index 20ec4eee1ac8af88d780970e5a7488b2f117c4c8..c2d13968da821f60277b29f612b4a15b42daf8b7 100644 (file)
@@ -34,7 +34,7 @@
 
 static __u8 c67x00_hub_des[] = {
        0x09,                   /*  __u8  bLength; */
-       0x29,                   /*  __u8  bDescriptorType; Hub-descriptor */
+       USB_DT_HUB,             /*  __u8  bDescriptorType; Hub-descriptor */
        0x02,                   /*  __u8  bNbrPorts; */
        0x00,                   /* __u16  wHubCharacteristics; */
        0x00,                   /*   (per-port OC, no power switching) */
index 77b47d82c9a69d05d7985068fb956f961b6481f1..5ce3f1d6a6ed340d8cf4db1a01c7fca3e6a6139a 100644 (file)
@@ -10,6 +10,17 @@ config USB_CHIPIDEA
 
 if USB_CHIPIDEA
 
+config USB_CHIPIDEA_OF
+       tristate
+       depends on OF
+       default USB_CHIPIDEA
+
+config USB_CHIPIDEA_PCI
+       tristate
+       depends on PCI
+       depends on NOP_USB_XCEIV
+       default USB_CHIPIDEA
+
 config USB_CHIPIDEA_UDC
        bool "ChipIdea device controller"
        depends on USB_GADGET
index 1fc86a2ca22d54c551eb9c09689d0b1318feaa5f..4decb12f25786221690c5adca6bb4448512039b1 100644 (file)
@@ -14,11 +14,6 @@ obj-$(CONFIG_USB_CHIPIDEA)   += ci_hdrc_usb2.o
 obj-$(CONFIG_USB_CHIPIDEA)     += ci_hdrc_msm.o
 obj-$(CONFIG_USB_CHIPIDEA)     += ci_hdrc_zevio.o
 
-# PCI doesn't provide stubs, need to check
-ifneq ($(CONFIG_PCI),)
-       obj-$(CONFIG_USB_CHIPIDEA)      += ci_hdrc_pci.o
-endif
+obj-$(CONFIG_USB_CHIPIDEA_PCI) += ci_hdrc_pci.o
 
-ifneq ($(CONFIG_OF),)
-       obj-$(CONFIG_USB_CHIPIDEA)      += usbmisc_imx.o ci_hdrc_imx.o
-endif
+obj-$(CONFIG_USB_CHIPIDEA_OF)  += usbmisc_imx.o ci_hdrc_imx.o
index ca57e3dcd3d57b10412e4aa1dcafad9a772ad3cc..3cb9bda51ddfde76f991581736af7fb6e111a4e3 100644 (file)
 
 #include <linux/usb/ehci_def.h>
 
+/*
+ * ID
+ * For 1.x revision, bit24 - bit31 are reserved
+ * For 2.x revision, bit25 - bit28 are 0x2
+ */
+#define TAG                  (0x1F << 16)
+#define REVISION             (0xF << 21)
+#define VERSION                      (0xF << 25)
+#define CIVERSION            (0x7 << 29)
+
 /* HCCPARAMS */
 #define HCCPARAMS_LEN         BIT(17)
 
@@ -53,6 +63,7 @@
 #define PORTSC_HSP            BIT(9)
 #define PORTSC_PP             BIT(12)
 #define PORTSC_PTC            (0x0FUL << 16)
+#define PORTSC_WKCN           BIT(20)
 #define PORTSC_PHCD(d)       ((d) ? BIT(22) : BIT(23))
 /* PTS and PTW for non lpm version only */
 #define PORTSC_PFSC           BIT(24)
index 65913d48f0c80538cb4153aeac05ee6142750191..6d6200e37b71e02b0e0d4a67cdd35f160f61de3b 100644 (file)
 /******************************************************************************
  * REGISTERS
  *****************************************************************************/
+/* Identification Registers */
+#define ID_ID                          0x0
+#define ID_HWGENERAL                   0x4
+#define ID_HWHOST                      0x8
+#define ID_HWDEVICE                    0xc
+#define ID_HWTXBUF                     0x10
+#define ID_HWRXBUF                     0x14
+#define ID_SBUSCFG                     0x90
+
 /* register indices */
 enum ci_hw_regs {
        CAP_CAPLENGTH,
@@ -97,6 +106,18 @@ enum ci_role {
        CI_ROLE_END,
 };
 
+enum ci_revision {
+       CI_REVISION_1X = 10,    /* Revision 1.x */
+       CI_REVISION_20 = 20, /* Revision 2.0 */
+       CI_REVISION_21, /* Revision 2.1 */
+       CI_REVISION_22, /* Revision 2.2 */
+       CI_REVISION_23, /* Revision 2.3 */
+       CI_REVISION_24, /* Revision 2.4 */
+       CI_REVISION_25, /* Revision 2.5 */
+       CI_REVISION_25_PLUS, /* Revision above than 2.5 */
+       CI_REVISION_UNKNOWN = 99, /* Unknown Revision */
+};
+
 /**
  * struct ci_role_driver - host/gadget role driver
  * @start: start this role
@@ -141,7 +162,10 @@ struct hw_bank {
  * @role: current role
  * @is_otg: if the device is otg-capable
  * @fsm: otg finite state machine
- * @fsm_timer: pointer to timer list of otg fsm
+ * @otg_fsm_hrtimer: hrtimer for otg fsm timers
+ * @hr_timeouts: time out list for active otg fsm timers
+ * @enabled_otg_timer_bits: bits of enabled otg timers
+ * @next_otg_timer: next nearest enabled timer to be expired
  * @work: work for role changing
  * @wq: workqueue thread
  * @qh_pool: allocation pool for queue heads
@@ -169,6 +193,10 @@ struct hw_bank {
  * @b_sess_valid_event: indicates there is a vbus event, and handled
  * at ci_otg_work
  * @imx28_write_fix: Freescale imx28 needs swp instruction for writing
+ * @supports_runtime_pm: if runtime pm is supported
+ * @in_lpm: if the core in low power mode
+ * @wakeup_int: if wakeup interrupt occur
+ * @rev: The revision number for controller
  */
 struct ci_hdrc {
        struct device                   *dev;
@@ -180,7 +208,10 @@ struct ci_hdrc {
        bool                            is_otg;
        struct usb_otg                  otg;
        struct otg_fsm                  fsm;
-       struct ci_otg_fsm_timer_list    *fsm_timer;
+       struct hrtimer                  otg_fsm_hrtimer;
+       ktime_t                         hr_timeouts[NUM_OTG_FSM_TIMERS];
+       unsigned                        enabled_otg_timer_bits;
+       enum otg_fsm_timer              next_otg_timer;
        struct work_struct              work;
        struct workqueue_struct         *wq;
 
@@ -211,6 +242,10 @@ struct ci_hdrc {
        bool                            id_event;
        bool                            b_sess_valid_event;
        bool                            imx28_write_fix;
+       bool                            supports_runtime_pm;
+       bool                            in_lpm;
+       bool                            wakeup_int;
+       enum ci_revision                rev;
 };
 
 static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
@@ -247,6 +282,36 @@ static inline void ci_role_stop(struct ci_hdrc *ci)
        ci->roles[role]->stop(ci);
 }
 
+/**
+ * hw_read_id_reg: reads from a identification register
+ * @ci: the controller
+ * @offset: offset from the beginning of identification registers region
+ * @mask: bitfield mask
+ *
+ * This function returns register contents
+ */
+static inline u32 hw_read_id_reg(struct ci_hdrc *ci, u32 offset, u32 mask)
+{
+       return ioread32(ci->hw_bank.abs + offset) & mask;
+}
+
+/**
+ * hw_write_id_reg: writes to a identification register
+ * @ci: the controller
+ * @offset: offset from the beginning of identification registers region
+ * @mask: bitfield mask
+ * @data: new value
+ */
+static inline void hw_write_id_reg(struct ci_hdrc *ci, u32 offset,
+                           u32 mask, u32 data)
+{
+       if (~mask)
+               data = (ioread32(ci->hw_bank.abs + offset) & ~mask)
+                       | (data & mask);
+
+       iowrite32(data, ci->hw_bank.abs + offset);
+}
+
 /**
  * hw_read: reads from a hw register
  * @ci: the controller
index 0f05de7c6b6c790e766ed035143840a84d4aef5c..389f0e0342596410c89b6c61b52b8907d90f9c0d 100644 (file)
 #include "ci.h"
 #include "ci_hdrc_imx.h"
 
-#define CI_HDRC_IMX_IMX28_WRITE_FIX BIT(0)
-
 struct ci_hdrc_imx_platform_flag {
        unsigned int flags;
+       bool runtime_pm;
 };
 
 static const struct ci_hdrc_imx_platform_flag imx27_usb_data = {
 };
 
 static const struct ci_hdrc_imx_platform_flag imx28_usb_data = {
-       .flags = CI_HDRC_IMX_IMX28_WRITE_FIX,
+       .flags = CI_HDRC_IMX28_WRITE_FIX |
+               CI_HDRC_TURN_VBUS_EARLY_ON,
+};
+
+static const struct ci_hdrc_imx_platform_flag imx6q_usb_data = {
+       .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
+               CI_HDRC_TURN_VBUS_EARLY_ON,
+};
+
+static const struct ci_hdrc_imx_platform_flag imx6sl_usb_data = {
+       .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
+               CI_HDRC_TURN_VBUS_EARLY_ON,
+};
+
+static const struct ci_hdrc_imx_platform_flag imx6sx_usb_data = {
+       .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
+               CI_HDRC_TURN_VBUS_EARLY_ON,
 };
 
 static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
        { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
        { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data},
+       { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data},
+       { .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data},
+       { .compatible = "fsl,imx6sx-usb", .data = &imx6sl_usb_data},
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
@@ -48,6 +66,8 @@ struct ci_hdrc_imx_data {
        struct platform_device *ci_pdev;
        struct clk *clk;
        struct imx_usbmisc_data *usbmisc_data;
+       bool supports_runtime_pm;
+       bool in_lpm;
 };
 
 /* Common functions shared by usbmisc drivers */
@@ -145,21 +165,18 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
        }
 
        pdata.usb_phy = data->phy;
-
-       if (imx_platform_flag->flags & CI_HDRC_IMX_IMX28_WRITE_FIX)
-               pdata.flags |= CI_HDRC_IMX28_WRITE_FIX;
+       pdata.flags |= imx_platform_flag->flags;
+       if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM)
+               data->supports_runtime_pm = true;
 
        ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
        if (ret)
                goto err_clk;
 
-       if (data->usbmisc_data) {
-               ret = imx_usbmisc_init(data->usbmisc_data);
-               if (ret) {
-                       dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n",
-                                       ret);
-                       goto err_clk;
-               }
+       ret = imx_usbmisc_init(data->usbmisc_data);
+       if (ret) {
+               dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n", ret);
+               goto err_clk;
        }
 
        data->ci_pdev = ci_hdrc_add_device(&pdev->dev,
@@ -173,19 +190,20 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
                goto err_clk;
        }
 
-       if (data->usbmisc_data) {
-               ret = imx_usbmisc_init_post(data->usbmisc_data);
-               if (ret) {
-                       dev_err(&pdev->dev, "usbmisc post failed, ret=%d\n",
-                                       ret);
-                       goto disable_device;
-               }
+       ret = imx_usbmisc_init_post(data->usbmisc_data);
+       if (ret) {
+               dev_err(&pdev->dev, "usbmisc post failed, ret=%d\n", ret);
+               goto disable_device;
        }
 
        platform_set_drvdata(pdev, data);
 
-       pm_runtime_no_callbacks(&pdev->dev);
-       pm_runtime_enable(&pdev->dev);
+       if (data->supports_runtime_pm) {
+               pm_runtime_set_active(&pdev->dev);
+               pm_runtime_enable(&pdev->dev);
+       }
+
+       device_set_wakeup_capable(&pdev->dev, true);
 
        return 0;
 
@@ -200,14 +218,18 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
 {
        struct ci_hdrc_imx_data *data = platform_get_drvdata(pdev);
 
-       pm_runtime_disable(&pdev->dev);
+       if (data->supports_runtime_pm) {
+               pm_runtime_get_sync(&pdev->dev);
+               pm_runtime_disable(&pdev->dev);
+               pm_runtime_put_noidle(&pdev->dev);
+       }
        ci_hdrc_remove_device(data->ci_pdev);
        clk_disable_unprepare(data->clk);
 
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 static int imx_controller_suspend(struct device *dev)
 {
        struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
@@ -215,6 +237,7 @@ static int imx_controller_suspend(struct device *dev)
        dev_dbg(dev, "at %s\n", __func__);
 
        clk_disable_unprepare(data->clk);
+       data->in_lpm = true;
 
        return 0;
 }
@@ -222,25 +245,103 @@ static int imx_controller_suspend(struct device *dev)
 static int imx_controller_resume(struct device *dev)
 {
        struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+       int ret = 0;
 
        dev_dbg(dev, "at %s\n", __func__);
 
-       return clk_prepare_enable(data->clk);
+       if (!data->in_lpm) {
+               WARN_ON(1);
+               return 0;
+       }
+
+       ret = clk_prepare_enable(data->clk);
+       if (ret)
+               return ret;
+
+       data->in_lpm = false;
+
+       ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false);
+       if (ret) {
+               dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret);
+               goto clk_disable;
+       }
+
+       return 0;
+
+clk_disable:
+       clk_disable_unprepare(data->clk);
+       return ret;
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int ci_hdrc_imx_suspend(struct device *dev)
 {
+       int ret;
+
+       struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+
+       if (data->in_lpm)
+               /* The core's suspend doesn't run */
+               return 0;
+
+       if (device_may_wakeup(dev)) {
+               ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true);
+               if (ret) {
+                       dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n",
+                                       ret);
+                       return ret;
+               }
+       }
+
        return imx_controller_suspend(dev);
 }
 
 static int ci_hdrc_imx_resume(struct device *dev)
 {
-       return imx_controller_resume(dev);
+       struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+       int ret;
+
+       ret = imx_controller_resume(dev);
+       if (!ret && data->supports_runtime_pm) {
+               pm_runtime_disable(dev);
+               pm_runtime_set_active(dev);
+               pm_runtime_enable(dev);
+       }
+
+       return ret;
 }
 #endif /* CONFIG_PM_SLEEP */
 
+static int ci_hdrc_imx_runtime_suspend(struct device *dev)
+{
+       struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+       int ret;
+
+       if (data->in_lpm) {
+               WARN_ON(1);
+               return 0;
+       }
+
+       ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true);
+       if (ret) {
+               dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret);
+               return ret;
+       }
+
+       return imx_controller_suspend(dev);
+}
+
+static int ci_hdrc_imx_runtime_resume(struct device *dev)
+{
+       return imx_controller_resume(dev);
+}
+
+#endif /* CONFIG_PM */
+
 static const struct dev_pm_ops ci_hdrc_imx_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(ci_hdrc_imx_suspend, ci_hdrc_imx_resume)
+       SET_RUNTIME_PM_OPS(ci_hdrc_imx_runtime_suspend,
+                       ci_hdrc_imx_runtime_resume, NULL)
 };
 static struct platform_driver ci_hdrc_imx_driver = {
        .probe = ci_hdrc_imx_probe,
index 4ed828f75a1e6ed56db69adfb946a1f9d8ff9b88..635717e9354aa0f7a30c1797c0718f058adb045b 100644 (file)
@@ -22,5 +22,6 @@ struct imx_usbmisc_data {
 
 int imx_usbmisc_init(struct imx_usbmisc_data *);
 int imx_usbmisc_init_post(struct imx_usbmisc_data *);
+int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *, bool);
 
 #endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */
index 4df6694372117cb4c0bfbdebced3238e2914a11b..773d150512fa4da6af83e5df10b069cc0276914c 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/chipidea.h>
+#include <linux/usb/usb_phy_generic.h>
 
 /* driver name */
 #define UDC_DRIVER_NAME   "ci_hdrc_pci"
 
+struct ci_hdrc_pci {
+       struct platform_device  *ci;
+       struct platform_device  *phy;
+};
+
 /******************************************************************************
  * PCI block
  *****************************************************************************/
@@ -52,7 +58,7 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,
                                       const struct pci_device_id *id)
 {
        struct ci_hdrc_platform_data *platdata = (void *)id->driver_data;
-       struct platform_device *plat_ci;
+       struct ci_hdrc_pci *ci;
        struct resource res[3];
        int retval = 0, nres = 2;
 
@@ -61,6 +67,10 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,
                return -ENODEV;
        }
 
+       ci = devm_kzalloc(&pdev->dev, sizeof(*ci), GFP_KERNEL);
+       if (!ci)
+               return -ENOMEM;
+
        retval = pcim_enable_device(pdev);
        if (retval)
                return retval;
@@ -73,6 +83,11 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,
        pci_set_master(pdev);
        pci_try_set_mwi(pdev);
 
+       /* register a nop PHY */
+       ci->phy = usb_phy_generic_register();
+       if (!ci->phy)
+               return -ENOMEM;
+
        memset(res, 0, sizeof(res));
        res[0].start    = pci_resource_start(pdev, 0);
        res[0].end      = pci_resource_end(pdev, 0);
@@ -80,13 +95,14 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,
        res[1].start    = pdev->irq;
        res[1].flags    = IORESOURCE_IRQ;
 
-       plat_ci = ci_hdrc_add_device(&pdev->dev, res, nres, platdata);
-       if (IS_ERR(plat_ci)) {
+       ci->ci = ci_hdrc_add_device(&pdev->dev, res, nres, platdata);
+       if (IS_ERR(ci->ci)) {
                dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
-               return PTR_ERR(plat_ci);
+               usb_phy_generic_unregister(ci->phy);
+               return PTR_ERR(ci->ci);
        }
 
-       pci_set_drvdata(pdev, plat_ci);
+       pci_set_drvdata(pdev, ci);
 
        return 0;
 }
@@ -101,9 +117,10 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,
  */
 static void ci_hdrc_pci_remove(struct pci_dev *pdev)
 {
-       struct platform_device *plat_ci = pci_get_drvdata(pdev);
+       struct ci_hdrc_pci *ci = pci_get_drvdata(pdev);
 
-       ci_hdrc_remove_device(plat_ci);
+       ci_hdrc_remove_device(ci->ci);
+       usb_phy_generic_unregister(ci->phy);
 }
 
 /**
index d976fc1db73ab99fbde57bcbbeaefb571b0d8b69..1264de50552728967c5cb9a63854cd0f0e1a006c 100644 (file)
@@ -18,7 +18,7 @@
 
 static struct ci_hdrc_platform_data ci_hdrc_zevio_platdata = {
        .name                   = "ci_hdrc_zevio",
-       .flags                  = CI_HDRC_REGS_SHARED,
+       .flags                  = CI_HDRC_REGS_SHARED | CI_HDRC_FORCE_FULLSPEED,
        .capoffset              = DEF_CAPOFFSET,
 };
 
index a57dc8866fc5ff938641686f7945916074723fe8..74fea4fa41b156248ce6d7116db02b54990066a9 100644 (file)
@@ -137,6 +137,22 @@ static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
        return 0;
 }
 
+static enum ci_revision ci_get_revision(struct ci_hdrc *ci)
+{
+       int ver = hw_read_id_reg(ci, ID_ID, VERSION) >> __ffs(VERSION);
+       enum ci_revision rev = CI_REVISION_UNKNOWN;
+
+       if (ver == 0x2) {
+               rev = hw_read_id_reg(ci, ID_ID, REVISION)
+                       >> __ffs(REVISION);
+               rev += CI_REVISION_20;
+       } else if (ver == 0x0) {
+               rev = CI_REVISION_1X;
+       }
+
+       return rev;
+}
+
 /**
  * hw_read_intr_enable: returns interrupt enable register
  *
@@ -251,8 +267,11 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base)
        /* Clear all interrupts status bits*/
        hw_write(ci, OP_USBSTS, 0xffffffff, 0xffffffff);
 
-       dev_dbg(ci->dev, "ChipIdea HDRC found, lpm: %d; cap: %p op: %p\n",
-               ci->hw_bank.lpm, ci->hw_bank.cap, ci->hw_bank.op);
+       ci->rev = ci_get_revision(ci);
+
+       dev_dbg(ci->dev,
+               "ChipIdea HDRC found, revision: %d, lpm: %d; cap: %p op: %p\n",
+               ci->rev, ci->hw_bank.lpm, ci->hw_bank.cap, ci->hw_bank.op);
 
        /* setup lock mode ? */
 
@@ -491,6 +510,13 @@ static irqreturn_t ci_irq(int irq, void *data)
        irqreturn_t ret = IRQ_NONE;
        u32 otgsc = 0;
 
+       if (ci->in_lpm) {
+               disable_irq_nosync(irq);
+               ci->wakeup_int = true;
+               pm_runtime_get(ci->dev);
+               return IRQ_HANDLED;
+       }
+
        if (ci->is_otg) {
                otgsc = hw_read_otgsc(ci, ~0);
                if (ci_otg_is_fsm_mode(ci)) {
@@ -642,8 +668,12 @@ static void ci_get_otg_capable(struct ci_hdrc *ci)
                ci->is_otg = (hw_read(ci, CAP_DCCPARAMS,
                                DCCPARAMS_DC | DCCPARAMS_HC)
                                        == (DCCPARAMS_DC | DCCPARAMS_HC));
-       if (ci->is_otg)
+       if (ci->is_otg) {
                dev_dbg(ci->dev, "It is OTG capable controller\n");
+               /* Disable and clear all OTG irq */
+               hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS,
+                                                       OTGSC_INT_STATUS_BITS);
+       }
 }
 
 static int ci_hdrc_probe(struct platform_device *pdev)
@@ -673,6 +703,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
        ci->platdata = dev_get_platdata(dev);
        ci->imx28_write_fix = !!(ci->platdata->flags &
                CI_HDRC_IMX28_WRITE_FIX);
+       ci->supports_runtime_pm = !!(ci->platdata->flags &
+               CI_HDRC_SUPPORTS_RUNTIME_PM);
 
        ret = hw_device_init(ci, base);
        if (ret < 0) {
@@ -740,9 +772,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
        }
 
        if (ci->is_otg && ci->roles[CI_ROLE_GADGET]) {
-               /* Disable and clear all OTG irq */
-               hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS,
-                                                       OTGSC_INT_STATUS_BITS);
                ret = ci_hdrc_otg_init(ci);
                if (ret) {
                        dev_err(dev, "init otg fails, ret = %d\n", ret);
@@ -769,11 +798,11 @@ static int ci_hdrc_probe(struct platform_device *pdev)
                        : CI_ROLE_GADGET;
        }
 
-       /* only update vbus status for peripheral */
-       if (ci->role == CI_ROLE_GADGET)
-               ci_handle_vbus_change(ci);
-
        if (!ci_otg_is_fsm_mode(ci)) {
+               /* only update vbus status for peripheral */
+               if (ci->role == CI_ROLE_GADGET)
+                       ci_handle_vbus_change(ci);
+
                ret = ci_role_start(ci, ci->role);
                if (ret) {
                        dev_err(dev, "can't start %s role\n",
@@ -788,9 +817,19 @@ static int ci_hdrc_probe(struct platform_device *pdev)
        if (ret)
                goto stop;
 
+       if (ci->supports_runtime_pm) {
+               pm_runtime_set_active(&pdev->dev);
+               pm_runtime_enable(&pdev->dev);
+               pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
+               pm_runtime_mark_last_busy(ci->dev);
+               pm_runtime_use_autosuspend(&pdev->dev);
+       }
+
        if (ci_otg_is_fsm_mode(ci))
                ci_hdrc_otg_fsm_start(ci);
 
+       device_set_wakeup_capable(&pdev->dev, true);
+
        ret = dbg_create_files(ci);
        if (!ret)
                return 0;
@@ -807,6 +846,12 @@ static int ci_hdrc_remove(struct platform_device *pdev)
 {
        struct ci_hdrc *ci = platform_get_drvdata(pdev);
 
+       if (ci->supports_runtime_pm) {
+               pm_runtime_get_sync(&pdev->dev);
+               pm_runtime_disable(&pdev->dev);
+               pm_runtime_put_noidle(&pdev->dev);
+       }
+
        dbg_remove_files(ci);
        ci_role_destroy(ci);
        ci_hdrc_enter_lpm(ci, true);
@@ -815,13 +860,41 @@ static int ci_hdrc_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
+/* Prepare wakeup by SRP before suspend */
+static void ci_otg_fsm_suspend_for_srp(struct ci_hdrc *ci)
+{
+       if ((ci->fsm.otg->state == OTG_STATE_A_IDLE) &&
+                               !hw_read_otgsc(ci, OTGSC_ID)) {
+               hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_PP,
+                                                               PORTSC_PP);
+               hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_WKCN,
+                                                               PORTSC_WKCN);
+       }
+}
+
+/* Handle SRP when wakeup by data pulse */
+static void ci_otg_fsm_wakeup_by_srp(struct ci_hdrc *ci)
+{
+       if ((ci->fsm.otg->state == OTG_STATE_A_IDLE) &&
+               (ci->fsm.a_bus_drop == 1) && (ci->fsm.a_bus_req == 0)) {
+               if (!hw_read_otgsc(ci, OTGSC_ID)) {
+                       ci->fsm.a_srp_det = 1;
+                       ci->fsm.a_bus_drop = 0;
+               } else {
+                       ci->fsm.id = 1;
+               }
+               ci_otg_queue_work(ci);
+       }
+}
+
 static void ci_controller_suspend(struct ci_hdrc *ci)
 {
+       disable_irq(ci->irq);
        ci_hdrc_enter_lpm(ci, true);
-
-       if (ci->usb_phy)
-               usb_phy_set_suspend(ci->usb_phy, 1);
+       usb_phy_set_suspend(ci->usb_phy, 1);
+       ci->in_lpm = true;
+       enable_irq(ci->irq);
 }
 
 static int ci_controller_resume(struct device *dev)
@@ -830,23 +903,59 @@ static int ci_controller_resume(struct device *dev)
 
        dev_dbg(dev, "at %s\n", __func__);
 
-       ci_hdrc_enter_lpm(ci, false);
+       if (!ci->in_lpm) {
+               WARN_ON(1);
+               return 0;
+       }
 
+       ci_hdrc_enter_lpm(ci, false);
        if (ci->usb_phy) {
                usb_phy_set_suspend(ci->usb_phy, 0);
                usb_phy_set_wakeup(ci->usb_phy, false);
                hw_wait_phy_stable();
        }
 
+       ci->in_lpm = false;
+       if (ci->wakeup_int) {
+               ci->wakeup_int = false;
+               pm_runtime_mark_last_busy(ci->dev);
+               pm_runtime_put_autosuspend(ci->dev);
+               enable_irq(ci->irq);
+               if (ci_otg_is_fsm_mode(ci))
+                       ci_otg_fsm_wakeup_by_srp(ci);
+       }
+
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int ci_suspend(struct device *dev)
 {
        struct ci_hdrc *ci = dev_get_drvdata(dev);
 
        if (ci->wq)
                flush_workqueue(ci->wq);
+       /*
+        * Controller needs to be active during suspend, otherwise the core
+        * may run resume when the parent is at suspend if other driver's
+        * suspend fails, it occurs before parent's suspend has not started,
+        * but the core suspend has finished.
+        */
+       if (ci->in_lpm)
+               pm_runtime_resume(dev);
+
+       if (ci->in_lpm) {
+               WARN_ON(1);
+               return 0;
+       }
+
+       if (device_may_wakeup(dev)) {
+               if (ci_otg_is_fsm_mode(ci))
+                       ci_otg_fsm_suspend_for_srp(ci);
+
+               usb_phy_set_wakeup(ci->usb_phy, true);
+               enable_irq_wake(ci->irq);
+       }
 
        ci_controller_suspend(ci);
 
@@ -855,13 +964,57 @@ static int ci_suspend(struct device *dev)
 
 static int ci_resume(struct device *dev)
 {
-       return ci_controller_resume(dev);
+       struct ci_hdrc *ci = dev_get_drvdata(dev);
+       int ret;
+
+       if (device_may_wakeup(dev))
+               disable_irq_wake(ci->irq);
+
+       ret = ci_controller_resume(dev);
+       if (ret)
+               return ret;
+
+       if (ci->supports_runtime_pm) {
+               pm_runtime_disable(dev);
+               pm_runtime_set_active(dev);
+               pm_runtime_enable(dev);
+       }
+
+       return ret;
 }
 #endif /* CONFIG_PM_SLEEP */
 
+static int ci_runtime_suspend(struct device *dev)
+{
+       struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+       dev_dbg(dev, "at %s\n", __func__);
+
+       if (ci->in_lpm) {
+               WARN_ON(1);
+               return 0;
+       }
+
+       if (ci_otg_is_fsm_mode(ci))
+               ci_otg_fsm_suspend_for_srp(ci);
+
+       usb_phy_set_wakeup(ci->usb_phy, true);
+       ci_controller_suspend(ci);
+
+       return 0;
+}
+
+static int ci_runtime_resume(struct device *dev)
+{
+       return ci_controller_resume(dev);
+}
+
+#endif /* CONFIG_PM */
 static const struct dev_pm_ops ci_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(ci_suspend, ci_resume)
+       SET_RUNTIME_PM_OPS(ci_runtime_suspend, ci_runtime_resume, NULL)
 };
+
 static struct platform_driver ci_hdrc_driver = {
        .probe  = ci_hdrc_probe,
        .remove = ci_hdrc_remove,
index 268e4236e84cfd51ecd9748af71fc772f196666b..dfb05edcdb96dbbb3b794d6faf5c799b3c031f06 100644 (file)
@@ -336,8 +336,8 @@ static int ci_registers_show(struct seq_file *s, void *unused)
        struct ci_hdrc *ci = s->private;
        u32 tmp_reg;
 
-       if (!ci)
-               return 0;
+       if (!ci || ci->in_lpm)
+               return -EPERM;
 
        /* ------ Registers ----- */
        tmp_reg = hw_read_intr_enable(ci);
index 48731d0bab357a75232fdbd7b4063fe29af3ad4e..21fe1a31431356d5056d4c443eb982a15ff25534 100644 (file)
@@ -33,6 +33,7 @@
 #include "host.h"
 
 static struct hc_driver __read_mostly ci_ehci_hc_driver;
+static int (*orig_bus_suspend)(struct usb_hcd *hcd);
 
 struct ehci_ci_priv {
        struct regulator *reg_vbus;
@@ -43,11 +44,10 @@ 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 device *dev = hcd->self.controller;
-       struct ci_hdrc *ci = dev_get_drvdata(dev);
        int ret = 0;
        int port = HCS_N_PORTS(ehci->hcs_params);
 
-       if (priv->reg_vbus && !ci_otg_is_fsm_mode(ci)) {
+       if (priv->reg_vbus) {
                if (port > 1) {
                        dev_warn(dev,
                                "Not support multi-port regulator control\n");
@@ -113,12 +113,23 @@ static int host_start(struct ci_hdrc *ci)
        priv = (struct ehci_ci_priv *)ehci->priv;
        priv->reg_vbus = NULL;
 
-       if (ci->platdata->reg_vbus)
-               priv->reg_vbus = ci->platdata->reg_vbus;
+       if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci)) {
+               if (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON) {
+                       ret = regulator_enable(ci->platdata->reg_vbus);
+                       if (ret) {
+                               dev_err(ci->dev,
+                               "Failed to enable vbus regulator, ret=%d\n",
+                                                                       ret);
+                               goto put_hcd;
+                       }
+               } else {
+                       priv->reg_vbus = ci->platdata->reg_vbus;
+               }
+       }
 
        ret = usb_add_hcd(hcd, 0, 0);
        if (ret) {
-               goto put_hcd;
+               goto disable_reg;
        } else {
                struct usb_otg *otg = &ci->otg;
 
@@ -133,8 +144,15 @@ 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:
+       if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) &&
+                       (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
+               regulator_disable(ci->platdata->reg_vbus);
 put_hcd:
        usb_put_hcd(hcd);
 
@@ -148,6 +166,9 @@ static void host_stop(struct ci_hdrc *ci)
        if (hcd) {
                usb_remove_hcd(hcd);
                usb_put_hcd(hcd);
+               if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) &&
+                       (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
+                               regulator_disable(ci->platdata->reg_vbus);
        }
 }
 
@@ -158,6 +179,47 @@ void ci_hdrc_host_destroy(struct ci_hdrc *ci)
                host_stop(ci);
 }
 
+static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
+{
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+       int port;
+       u32 tmp;
+
+       int ret = orig_bus_suspend(hcd);
+
+       if (ret)
+               return ret;
+
+       port = HCS_N_PORTS(ehci->hcs_params);
+       while (port--) {
+               u32 __iomem *reg = &ehci->regs->port_status[port];
+               u32 portsc = ehci_readl(ehci, reg);
+
+               if (portsc & PORT_CONNECT) {
+                       /*
+                        * For chipidea, the resume signal will be ended
+                        * automatically, so for remote wakeup case, the
+                        * usbcmd.rs may not be set before the resume has
+                        * ended if other resume paths consumes too much
+                        * time (~24ms), in that case, the SOF will not
+                        * send out within 3ms after resume ends, then the
+                        * high speed device will enter full speed mode.
+                        */
+
+                       tmp = ehci_readl(ehci, &ehci->regs->command);
+                       tmp |= CMD_RUN;
+                       ehci_writel(ehci, tmp, &ehci->regs->command);
+                       /*
+                        * It needs a short delay between set RS bit and PHCD.
+                        */
+                       usleep_range(150, 200);
+                       break;
+               }
+       }
+
+       return 0;
+}
+
 int ci_hdrc_host_init(struct ci_hdrc *ci)
 {
        struct ci_role_driver *rdrv;
@@ -176,6 +238,8 @@ int ci_hdrc_host_init(struct ci_hdrc *ci)
        ci->roles[CI_ROLE_HOST] = rdrv;
 
        ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides);
+       orig_bus_suspend = ci_ehci_hc_driver.bus_suspend;
+       ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend;
 
        return 0;
 }
index a048b08b9d4dbb1fff35dbc73da7366c8a78f48d..ad6c87a4653c2e4331eeb3b48787f525687e0c8a 100644 (file)
@@ -96,6 +96,7 @@ static void ci_otg_work(struct work_struct *work)
                return;
        }
 
+       pm_runtime_get_sync(ci->dev);
        if (ci->id_event) {
                ci->id_event = false;
                ci_handle_id_switch(ci);
@@ -104,6 +105,7 @@ static void ci_otg_work(struct work_struct *work)
                ci_handle_vbus_change(ci);
        } else
                dev_err(ci->dev, "unexpected event occurs at %s\n", __func__);
+       pm_runtime_put_sync(ci->dev);
 
        enable_irq(ci->irq);
 }
index 562e581f67656fbf13eb72bd175f8766be59599f..083acf45ad5aba6cc9e0fe6c9c7d94b3e0fcd85c 100644 (file)
 #include "otg.h"
 #include "otg_fsm.h"
 
-static struct ci_otg_fsm_timer *otg_timer_initializer
-(struct ci_hdrc *ci, void (*function)(void *, unsigned long),
-                       unsigned long expires, unsigned long data)
-{
-       struct ci_otg_fsm_timer *timer;
-
-       timer = devm_kzalloc(ci->dev, sizeof(struct ci_otg_fsm_timer),
-                                                               GFP_KERNEL);
-       if (!timer)
-               return NULL;
-       timer->function = function;
-       timer->expires = expires;
-       timer->data = data;
-       return timer;
-}
-
 /* Add for otg: interact with user space app */
 static ssize_t
 get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
@@ -203,230 +187,228 @@ static struct attribute_group inputs_attr_group = {
        .attrs = inputs_attrs,
 };
 
+/*
+ * Keep this list in the same order as timers indexed
+ * by enum otg_fsm_timer in include/linux/usb/otg-fsm.h
+ */
+static unsigned otg_timer_ms[] = {
+       TA_WAIT_VRISE,
+       TA_WAIT_VFALL,
+       TA_WAIT_BCON,
+       TA_AIDL_BDIS,
+       TB_ASE0_BRST,
+       TA_BIDL_ADIS,
+       TB_SE0_SRP,
+       TB_SRP_FAIL,
+       0,
+       TB_DATA_PLS,
+       TB_SSEND_SRP,
+};
+
 /*
  * Add timer to active timer list
  */
-static void ci_otg_add_timer(struct ci_hdrc *ci, enum ci_otg_fsm_timer_index t)
+static void ci_otg_add_timer(struct ci_hdrc *ci, enum otg_fsm_timer t)
 {
-       struct ci_otg_fsm_timer *tmp_timer;
-       struct ci_otg_fsm_timer *timer = ci->fsm_timer->timer_list[t];
-       struct list_head *active_timers = &ci->fsm_timer->active_timers;
+       unsigned long flags, timer_sec, timer_nsec;
 
-       if (t >= NUM_CI_OTG_FSM_TIMERS)
+       if (t >= NUM_OTG_FSM_TIMERS)
                return;
 
-       /*
-        * Check if the timer is already in the active list,
-        * if so update timer count
-        */
-       list_for_each_entry(tmp_timer, active_timers, list)
-               if (tmp_timer == timer) {
-                       timer->count = timer->expires;
-                       return;
-               }
-
-       timer->count = timer->expires;
-       list_add_tail(&timer->list, active_timers);
-
-       /* Enable 1ms irq */
-       if (!(hw_read_otgsc(ci, OTGSC_1MSIE)))
-               hw_write_otgsc(ci, OTGSC_1MSIE, OTGSC_1MSIE);
+       spin_lock_irqsave(&ci->lock, flags);
+       timer_sec = otg_timer_ms[t] / MSEC_PER_SEC;
+       timer_nsec = (otg_timer_ms[t] % MSEC_PER_SEC) * NSEC_PER_MSEC;
+       ci->hr_timeouts[t] = ktime_add(ktime_get(),
+                               ktime_set(timer_sec, timer_nsec));
+       ci->enabled_otg_timer_bits |= (1 << t);
+       if ((ci->next_otg_timer == NUM_OTG_FSM_TIMERS) ||
+                       (ci->hr_timeouts[ci->next_otg_timer].tv64 >
+                                               ci->hr_timeouts[t].tv64)) {
+                       ci->next_otg_timer = t;
+                       hrtimer_start_range_ns(&ci->otg_fsm_hrtimer,
+                                       ci->hr_timeouts[t], NSEC_PER_MSEC,
+                                                       HRTIMER_MODE_ABS);
+       }
+       spin_unlock_irqrestore(&ci->lock, flags);
 }
 
 /*
  * Remove timer from active timer list
  */
-static void ci_otg_del_timer(struct ci_hdrc *ci, enum ci_otg_fsm_timer_index t)
+static void ci_otg_del_timer(struct ci_hdrc *ci, enum otg_fsm_timer t)
 {
-       struct ci_otg_fsm_timer *tmp_timer, *del_tmp;
-       struct ci_otg_fsm_timer *timer = ci->fsm_timer->timer_list[t];
-       struct list_head *active_timers = &ci->fsm_timer->active_timers;
+       unsigned long flags, enabled_timer_bits;
+       enum otg_fsm_timer cur_timer, next_timer = NUM_OTG_FSM_TIMERS;
 
-       if (t >= NUM_CI_OTG_FSM_TIMERS)
+       if ((t >= NUM_OTG_FSM_TIMERS) ||
+                       !(ci->enabled_otg_timer_bits & (1 << t)))
                return;
 
-       list_for_each_entry_safe(tmp_timer, del_tmp, active_timers, list)
-               if (tmp_timer == timer)
-                       list_del(&timer->list);
-
-       /* Disable 1ms irq if there is no any active timer */
-       if (list_empty(active_timers))
-               hw_write_otgsc(ci, OTGSC_1MSIE, 0);
-}
-
-/*
- * Reduce timer count by 1, and find timeout conditions.
- * Called by otg 1ms timer interrupt
- */
-static inline int ci_otg_tick_timer(struct ci_hdrc *ci)
-{
-       struct ci_otg_fsm_timer *tmp_timer, *del_tmp;
-       struct list_head *active_timers = &ci->fsm_timer->active_timers;
-       int expired = 0;
-
-       list_for_each_entry_safe(tmp_timer, del_tmp, active_timers, list) {
-               tmp_timer->count--;
-               /* check if timer expires */
-               if (!tmp_timer->count) {
-                       list_del(&tmp_timer->list);
-                       tmp_timer->function(ci, tmp_timer->data);
-                       expired = 1;
+       spin_lock_irqsave(&ci->lock, flags);
+       ci->enabled_otg_timer_bits &= ~(1 << t);
+       if (ci->next_otg_timer == t) {
+               if (ci->enabled_otg_timer_bits == 0) {
+                       /* No enabled timers after delete it */
+                       hrtimer_cancel(&ci->otg_fsm_hrtimer);
+                       ci->next_otg_timer = NUM_OTG_FSM_TIMERS;
+               } else {
+                       /* Find the next timer */
+                       enabled_timer_bits = ci->enabled_otg_timer_bits;
+                       for_each_set_bit(cur_timer, &enabled_timer_bits,
+                                                       NUM_OTG_FSM_TIMERS) {
+                               if ((next_timer == NUM_OTG_FSM_TIMERS) ||
+                                       (ci->hr_timeouts[next_timer].tv64 <
+                                       ci->hr_timeouts[cur_timer].tv64))
+                                       next_timer = cur_timer;
+                       }
                }
        }
-
-       /* disable 1ms irq if there is no any timer active */
-       if ((expired == 1) && list_empty(active_timers))
-               hw_write_otgsc(ci, OTGSC_1MSIE, 0);
-
-       return expired;
+       if (next_timer != NUM_OTG_FSM_TIMERS) {
+               ci->next_otg_timer = next_timer;
+               hrtimer_start_range_ns(&ci->otg_fsm_hrtimer,
+                       ci->hr_timeouts[next_timer], NSEC_PER_MSEC,
+                                                       HRTIMER_MODE_ABS);
+       }
+       spin_unlock_irqrestore(&ci->lock, flags);
 }
 
-/* The timeout callback function to set time out bit */
-static void set_tmout(void *ptr, unsigned long indicator)
+/* OTG FSM timer handlers */
+static int a_wait_vrise_tmout(struct ci_hdrc *ci)
 {
-       *(int *)indicator = 1;
+       ci->fsm.a_wait_vrise_tmout = 1;
+       return 0;
 }
 
-static void set_tmout_and_fsm(void *ptr, unsigned long indicator)
+static int a_wait_vfall_tmout(struct ci_hdrc *ci)
 {
-       struct ci_hdrc *ci = (struct ci_hdrc *)ptr;
-
-       set_tmout(ci, indicator);
-
-       ci_otg_queue_work(ci);
+       ci->fsm.a_wait_vfall_tmout = 1;
+       return 0;
 }
 
-static void a_wait_vfall_tmout_func(void *ptr, unsigned long indicator)
+static int a_wait_bcon_tmout(struct ci_hdrc *ci)
 {
-       struct ci_hdrc *ci = (struct ci_hdrc *)ptr;
-
-       set_tmout(ci, indicator);
-       /* Disable port power */
-       hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_PP, 0);
-       /* Clear existing DP irq */
-       hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS);
-       /* Enable data pulse irq */
-       hw_write_otgsc(ci, OTGSC_DPIE, OTGSC_DPIE);
-       ci_otg_queue_work(ci);
+       ci->fsm.a_wait_bcon_tmout = 1;
+       return 0;
 }
 
-static void b_ase0_brst_tmout_func(void *ptr, unsigned long indicator)
+static int a_aidl_bdis_tmout(struct ci_hdrc *ci)
 {
-       struct ci_hdrc *ci = (struct ci_hdrc *)ptr;
-
-       set_tmout(ci, indicator);
-       if (!hw_read_otgsc(ci, OTGSC_BSV))
-               ci->fsm.b_sess_vld = 0;
-
-       ci_otg_queue_work(ci);
+       ci->fsm.a_aidl_bdis_tmout = 1;
+       return 0;
 }
 
-static void b_ssend_srp_tmout_func(void *ptr, unsigned long indicator)
+static int b_ase0_brst_tmout(struct ci_hdrc *ci)
 {
-       struct ci_hdrc *ci = (struct ci_hdrc *)ptr;
-
-       set_tmout(ci, indicator);
-
-       /* only vbus fall below B_sess_vld in b_idle state */
-       if (ci->fsm.otg->state == OTG_STATE_B_IDLE)
-               ci_otg_queue_work(ci);
+       ci->fsm.b_ase0_brst_tmout = 1;
+       return 0;
 }
 
-static void b_sess_vld_tmout_func(void *ptr, unsigned long indicator)
+static int a_bidl_adis_tmout(struct ci_hdrc *ci)
 {
-       struct ci_hdrc *ci = (struct ci_hdrc *)ptr;
+       ci->fsm.a_bidl_adis_tmout = 1;
+       return 0;
+}
 
-       /* Check if A detached */
-       if (!(hw_read_otgsc(ci, OTGSC_BSV))) {
-               ci->fsm.b_sess_vld = 0;
-               ci_otg_add_timer(ci, B_SSEND_SRP);
-               ci_otg_queue_work(ci);
-       }
+static int b_se0_srp_tmout(struct ci_hdrc *ci)
+{
+       ci->fsm.b_se0_srp = 1;
+       return 0;
 }
 
-static void b_data_pulse_end(void *ptr, unsigned long indicator)
+static int b_srp_fail_tmout(struct ci_hdrc *ci)
 {
-       struct ci_hdrc *ci = (struct ci_hdrc *)ptr;
+       ci->fsm.b_srp_done = 1;
+       return 1;
+}
 
+static int b_data_pls_tmout(struct ci_hdrc *ci)
+{
        ci->fsm.b_srp_done = 1;
        ci->fsm.b_bus_req = 0;
        if (ci->fsm.power_up)
                ci->fsm.power_up = 0;
-
        hw_write_otgsc(ci, OTGSC_HABA, 0);
+       pm_runtime_put(ci->dev);
+       return 0;
+}
 
-       ci_otg_queue_work(ci);
+static int b_ssend_srp_tmout(struct ci_hdrc *ci)
+{
+       ci->fsm.b_ssend_srp = 1;
+       /* only vbus fall below B_sess_vld in b_idle state */
+       if (ci->fsm.otg->state == OTG_STATE_B_IDLE)
+               return 0;
+       else
+               return 1;
+}
+
+/*
+ * Keep this list in the same order as timers indexed
+ * by enum otg_fsm_timer in include/linux/usb/otg-fsm.h
+ */
+static int (*otg_timer_handlers[])(struct ci_hdrc *) = {
+       a_wait_vrise_tmout,     /* A_WAIT_VRISE */
+       a_wait_vfall_tmout,     /* A_WAIT_VFALL */
+       a_wait_bcon_tmout,      /* A_WAIT_BCON */
+       a_aidl_bdis_tmout,      /* A_AIDL_BDIS */
+       b_ase0_brst_tmout,      /* B_ASE0_BRST */
+       a_bidl_adis_tmout,      /* A_BIDL_ADIS */
+       b_se0_srp_tmout,        /* B_SE0_SRP */
+       b_srp_fail_tmout,       /* B_SRP_FAIL */
+       NULL,                   /* A_WAIT_ENUM */
+       b_data_pls_tmout,       /* B_DATA_PLS */
+       b_ssend_srp_tmout,      /* B_SSEND_SRP */
+};
+
+/*
+ * Enable the next nearest enabled timer if have
+ */
+static enum hrtimer_restart ci_otg_hrtimer_func(struct hrtimer *t)
+{
+       struct ci_hdrc *ci = container_of(t, struct ci_hdrc, otg_fsm_hrtimer);
+       ktime_t now, *timeout;
+       unsigned long   enabled_timer_bits;
+       unsigned long   flags;
+       enum otg_fsm_timer cur_timer, next_timer = NUM_OTG_FSM_TIMERS;
+       int ret = -EINVAL;
+
+       spin_lock_irqsave(&ci->lock, flags);
+       enabled_timer_bits = ci->enabled_otg_timer_bits;
+       ci->next_otg_timer = NUM_OTG_FSM_TIMERS;
+
+       now = ktime_get();
+       for_each_set_bit(cur_timer, &enabled_timer_bits, NUM_OTG_FSM_TIMERS) {
+               if (now.tv64 >= ci->hr_timeouts[cur_timer].tv64) {
+                       ci->enabled_otg_timer_bits &= ~(1 << cur_timer);
+                       if (otg_timer_handlers[cur_timer])
+                               ret = otg_timer_handlers[cur_timer](ci);
+               } else {
+                       if ((next_timer == NUM_OTG_FSM_TIMERS) ||
+                               (ci->hr_timeouts[cur_timer].tv64 <
+                                       ci->hr_timeouts[next_timer].tv64))
+                               next_timer = cur_timer;
+               }
+       }
+       /* Enable the next nearest timer */
+       if (next_timer < NUM_OTG_FSM_TIMERS) {
+               timeout = &ci->hr_timeouts[next_timer];
+               hrtimer_start_range_ns(&ci->otg_fsm_hrtimer, *timeout,
+                                       NSEC_PER_MSEC, HRTIMER_MODE_ABS);
+               ci->next_otg_timer = next_timer;
+       }
+       spin_unlock_irqrestore(&ci->lock, flags);
+
+       if (!ret)
+               ci_otg_queue_work(ci);
+
+       return HRTIMER_NORESTART;
 }
 
 /* Initialize timers */
 static int ci_otg_init_timers(struct ci_hdrc *ci)
 {
-       struct otg_fsm *fsm = &ci->fsm;
-
-       /* FSM used timers */
-       ci->fsm_timer->timer_list[A_WAIT_VRISE] =
-               otg_timer_initializer(ci, &set_tmout_and_fsm, TA_WAIT_VRISE,
-                       (unsigned long)&fsm->a_wait_vrise_tmout);
-       if (ci->fsm_timer->timer_list[A_WAIT_VRISE] == NULL)
-               return -ENOMEM;
-
-       ci->fsm_timer->timer_list[A_WAIT_VFALL] =
-               otg_timer_initializer(ci, &a_wait_vfall_tmout_func,
-               TA_WAIT_VFALL, (unsigned long)&fsm->a_wait_vfall_tmout);
-       if (ci->fsm_timer->timer_list[A_WAIT_VFALL] == NULL)
-               return -ENOMEM;
-
-       ci->fsm_timer->timer_list[A_WAIT_BCON] =
-               otg_timer_initializer(ci, &set_tmout_and_fsm, TA_WAIT_BCON,
-                               (unsigned long)&fsm->a_wait_bcon_tmout);
-       if (ci->fsm_timer->timer_list[A_WAIT_BCON] == NULL)
-               return -ENOMEM;
-
-       ci->fsm_timer->timer_list[A_AIDL_BDIS] =
-               otg_timer_initializer(ci, &set_tmout_and_fsm, TA_AIDL_BDIS,
-                               (unsigned long)&fsm->a_aidl_bdis_tmout);
-       if (ci->fsm_timer->timer_list[A_AIDL_BDIS] == NULL)
-               return -ENOMEM;
-
-       ci->fsm_timer->timer_list[A_BIDL_ADIS] =
-               otg_timer_initializer(ci, &set_tmout_and_fsm, TA_BIDL_ADIS,
-                               (unsigned long)&fsm->a_bidl_adis_tmout);
-       if (ci->fsm_timer->timer_list[A_BIDL_ADIS] == NULL)
-               return -ENOMEM;
-
-       ci->fsm_timer->timer_list[B_ASE0_BRST] =
-               otg_timer_initializer(ci, &b_ase0_brst_tmout_func, TB_ASE0_BRST,
-                                       (unsigned long)&fsm->b_ase0_brst_tmout);
-       if (ci->fsm_timer->timer_list[B_ASE0_BRST] == NULL)
-               return -ENOMEM;
-
-       ci->fsm_timer->timer_list[B_SE0_SRP] =
-               otg_timer_initializer(ci, &set_tmout_and_fsm, TB_SE0_SRP,
-                                       (unsigned long)&fsm->b_se0_srp);
-       if (ci->fsm_timer->timer_list[B_SE0_SRP] == NULL)
-               return -ENOMEM;
-
-       ci->fsm_timer->timer_list[B_SSEND_SRP] =
-               otg_timer_initializer(ci, &b_ssend_srp_tmout_func, TB_SSEND_SRP,
-                                       (unsigned long)&fsm->b_ssend_srp);
-       if (ci->fsm_timer->timer_list[B_SSEND_SRP] == NULL)
-               return -ENOMEM;
-
-       ci->fsm_timer->timer_list[B_SRP_FAIL] =
-               otg_timer_initializer(ci, &set_tmout, TB_SRP_FAIL,
-                               (unsigned long)&fsm->b_srp_done);
-       if (ci->fsm_timer->timer_list[B_SRP_FAIL] == NULL)
-               return -ENOMEM;
-
-       ci->fsm_timer->timer_list[B_DATA_PLS] =
-               otg_timer_initializer(ci, &b_data_pulse_end, TB_DATA_PLS, 0);
-       if (ci->fsm_timer->timer_list[B_DATA_PLS] == NULL)
-               return -ENOMEM;
-
-       ci->fsm_timer->timer_list[B_SESS_VLD] = otg_timer_initializer(ci,
-                                       &b_sess_vld_tmout_func, TB_SESS_VLD, 0);
-       if (ci->fsm_timer->timer_list[B_SESS_VLD] == NULL)
-               return -ENOMEM;
+       hrtimer_init(&ci->otg_fsm_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+       ci->otg_fsm_hrtimer.function = ci_otg_hrtimer_func;
 
        return 0;
 }
@@ -530,6 +512,7 @@ static void ci_otg_start_pulse(struct otg_fsm *fsm)
        /* Hardware Assistant Data pulse */
        hw_write_otgsc(ci, OTGSC_HADP, OTGSC_HADP);
 
+       pm_runtime_get(ci->dev);
        ci_otg_add_timer(ci, B_DATA_PLS);
 }
 
@@ -585,6 +568,7 @@ int ci_otg_fsm_work(struct ci_hdrc *ci)
                ci->fsm.otg->state < OTG_STATE_A_IDLE)
                return 0;
 
+       pm_runtime_get_sync(ci->dev);
        if (otg_statemachine(&ci->fsm)) {
                if (ci->fsm.otg->state == OTG_STATE_A_IDLE) {
                        /*
@@ -596,8 +580,15 @@ int ci_otg_fsm_work(struct ci_hdrc *ci)
                         * a_idle to a_wait_vrise when power up
                         */
                        if ((ci->fsm.id) || (ci->id_event) ||
-                                               (ci->fsm.power_up))
+                                               (ci->fsm.power_up)) {
                                ci_otg_queue_work(ci);
+                       } else {
+                               /* Enable data pulse irq */
+                               hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS |
+                                                               PORTSC_PP, 0);
+                               hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS);
+                               hw_write_otgsc(ci, OTGSC_DPIE, OTGSC_DPIE);
+                       }
                        if (ci->id_event)
                                ci->id_event = false;
                } else if (ci->fsm.otg->state == OTG_STATE_B_IDLE) {
@@ -609,8 +600,13 @@ int ci_otg_fsm_work(struct ci_hdrc *ci)
                                 */
                                ci_otg_queue_work(ci);
                        }
+               } else if (ci->fsm.otg->state == OTG_STATE_A_HOST) {
+                       pm_runtime_mark_last_busy(ci->dev);
+                       pm_runtime_put_autosuspend(ci->dev);
+                       return 0;
                }
        }
+       pm_runtime_put_sync(ci->dev);
        return 0;
 }
 
@@ -655,7 +651,6 @@ static void ci_otg_fsm_event(struct ci_hdrc *ci)
                        fsm->a_conn = 0;
                        fsm->b_bus_req = 0;
                        ci_otg_queue_work(ci);
-                       ci_otg_add_timer(ci, B_SESS_VLD);
                }
                break;
        case OTG_STATE_A_PERIPHERAL:
@@ -725,11 +720,7 @@ irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci)
        fsm->id = (otgsc & OTGSC_ID) ? 1 : 0;
 
        if (otg_int_src) {
-               if (otg_int_src & OTGSC_1MSIS) {
-                       hw_write_otgsc(ci, OTGSC_1MSIS, OTGSC_1MSIS);
-                       retval = ci_otg_tick_timer(ci);
-                       return IRQ_HANDLED;
-               } else if (otg_int_src & OTGSC_DPIS) {
+               if (otg_int_src & OTGSC_DPIS) {
                        hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS);
                        fsm->a_srp_det = 1;
                        fsm->a_bus_drop = 0;
@@ -793,17 +784,13 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
 
        mutex_init(&ci->fsm.lock);
 
-       ci->fsm_timer = devm_kzalloc(ci->dev,
-                       sizeof(struct ci_otg_fsm_timer_list), GFP_KERNEL);
-       if (!ci->fsm_timer)
-               return -ENOMEM;
-
-       INIT_LIST_HEAD(&ci->fsm_timer->active_timers);
        retval = ci_otg_init_timers(ci);
        if (retval) {
                dev_err(ci->dev, "Couldn't init OTG timers\n");
                return retval;
        }
+       ci->enabled_otg_timer_bits = 0;
+       ci->next_otg_timer = NUM_OTG_FSM_TIMERS;
 
        retval = sysfs_create_group(&ci->dev->kobj, &inputs_attr_group);
        if (retval < 0) {
index 94c085f456a9cdc999697df7266b9261fac665a7..2689375ae5da33cf5c339222a6c2d211843b2a11 100644 (file)
 /* SSEND time before SRP */
 #define TB_SSEND_SRP         (1500)    /* minimum 1.5 sec, section:5.1.2 */
 
-#define TB_SESS_VLD          (1000)
-
-enum ci_otg_fsm_timer_index {
-       /*
-        * CI specific timers, start from the end
-        * of standard and auxiliary OTG timers
-        */
-       B_DATA_PLS = NUM_OTG_FSM_TIMERS,
-       B_SSEND_SRP,
-       B_SESS_VLD,
-
-       NUM_CI_OTG_FSM_TIMERS,
-};
-
-struct ci_otg_fsm_timer {
-       unsigned long expires;  /* Number of count increase to timeout */
-       unsigned long count;    /* Tick counter */
-       void (*function)(void *, unsigned long);        /* Timeout function */
-       unsigned long data;     /* Data passed to function */
-       struct list_head list;
-};
-
-struct ci_otg_fsm_timer_list {
-       struct ci_otg_fsm_timer *timer_list[NUM_CI_OTG_FSM_TIMERS];
-       struct list_head active_timers;
-};
-
 #ifdef CONFIG_USB_OTG_FSM
 
 int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci);
index 4bfb7ac0239f9b4bac46ec3246ff99f29e4dcc2a..764f668d45a9bb6ad4cde8ea0f4a8b0661dead86 100644 (file)
@@ -86,10 +86,8 @@ static int hw_device_state(struct ci_hdrc *ci, u32 dma)
                /* interrupt, error, port change, reset, sleep/suspend */
                hw_write(ci, OP_USBINTR, ~0,
                             USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
-               hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
        } else {
                hw_write(ci, OP_USBINTR, ~0, 0);
-               hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
        }
        return 0;
 }
@@ -522,6 +520,20 @@ static void free_pending_td(struct ci_hw_ep *hwep)
        kfree(pending);
 }
 
+static int reprime_dtd(struct ci_hdrc *ci, struct ci_hw_ep *hwep,
+                                          struct td_node *node)
+{
+       hwep->qh.ptr->td.next = node->dma;
+       hwep->qh.ptr->td.token &=
+               cpu_to_le32(~(TD_STATUS_HALTED | TD_STATUS_ACTIVE));
+
+       /* Synchronize before ep prime */
+       wmb();
+
+       return hw_ep_prime(ci, hwep->num, hwep->dir,
+                               hwep->type == USB_ENDPOINT_XFER_CONTROL);
+}
+
 /**
  * _hardware_dequeue: handles a request at hardware level
  * @gadget: gadget
@@ -535,6 +547,7 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
        struct td_node *node, *tmpnode;
        unsigned remaining_length;
        unsigned actual = hwreq->req.length;
+       struct ci_hdrc *ci = hwep->ci;
 
        if (hwreq->req.status != -EALREADY)
                return -EINVAL;
@@ -544,6 +557,11 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
        list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) {
                tmptoken = le32_to_cpu(node->ptr->token);
                if ((TD_STATUS_ACTIVE & tmptoken) != 0) {
+                       int n = hw_ep_bit(hwep->num, hwep->dir);
+
+                       if (ci->rev == CI_REVISION_24)
+                               if (!hw_read(ci, OP_ENDPTSTAT, BIT(n)))
+                                       reprime_dtd(ci, hwep, node);
                        hwreq->req.status = -EALREADY;
                        return -EBUSY;
                }
@@ -1162,10 +1180,13 @@ static int ep_enable(struct usb_ep *ep,
 
        /* only internal SW should enable ctrl endpts */
 
-       hwep->ep.desc = desc;
-
-       if (!list_empty(&hwep->qh.queue))
+       if (!list_empty(&hwep->qh.queue)) {
                dev_warn(hwep->ci->dev, "enabling a non-empty endpoint!\n");
+               spin_unlock_irqrestore(hwep->lock, flags);
+               return -EBUSY;
+       }
+
+       hwep->ep.desc = desc;
 
        hwep->dir  = usb_endpoint_dir_in(desc) ? TX : RX;
        hwep->num  = usb_endpoint_num(desc);
@@ -1485,7 +1506,9 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
                        hw_device_reset(ci);
                        hw_device_state(ci, ci->ep0out->qh.dma);
                        usb_gadget_set_state(_gadget, USB_STATE_POWERED);
+                       usb_udc_vbus_handler(_gadget, true);
                } else {
+                       usb_udc_vbus_handler(_gadget, false);
                        if (ci->driver)
                                ci->driver->disconnect(&ci->gadget);
                        hw_device_state(ci, 0);
@@ -1551,13 +1574,16 @@ static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on)
 {
        struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget);
 
-       if (!ci->vbus_active)
-               return -EOPNOTSUPP;
+       /* Data+ pullup controlled by OTG state machine in OTG fsm mode */
+       if (ci_otg_is_fsm_mode(ci))
+               return 0;
 
+       pm_runtime_get_sync(&ci->gadget.dev);
        if (is_on)
                hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
        else
                hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
+       pm_runtime_put_sync(&ci->gadget.dev);
 
        return 0;
 }
@@ -1687,6 +1713,7 @@ static int ci_udc_start(struct usb_gadget *gadget,
                spin_lock_irqsave(&ci->lock, flags);
                hw_device_reset(ci);
        } else {
+               usb_udc_vbus_handler(&ci->gadget, false);
                pm_runtime_put_sync(&ci->gadget.dev);
                return retval;
        }
index c3c6225b8acfc3dd792a238c3c5f7459488d77d3..140945cb124f51056673dd3b52085fc73689e2ca 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/module.h>
 #include <linux/of_platform.h>
-#include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/delay.h>
 #define MX53_USB_PLL_DIV_24_MHZ                0x01
 
 #define MX6_BM_OVER_CUR_DIS            BIT(7)
+#define MX6_BM_WAKEUP_ENABLE           BIT(10)
+#define MX6_BM_ID_WAKEUP               BIT(16)
+#define MX6_BM_VBUS_WAKEUP             BIT(17)
+#define MX6SX_BM_DPDM_WAKEUP_EN                BIT(29)
+#define MX6_BM_WAKEUP_INTR             BIT(31)
+#define MX6_USB_OTG1_PHY_CTRL          0x18
+/* For imx6dql, it is host-only controller, for later imx6, it is otg's */
+#define MX6_USB_OTG2_PHY_CTRL          0x1c
+#define MX6SX_USB_VBUS_WAKEUP_SOURCE(v)        (v << 8)
+#define MX6SX_USB_VBUS_WAKEUP_SOURCE_VBUS      MX6SX_USB_VBUS_WAKEUP_SOURCE(0)
+#define MX6SX_USB_VBUS_WAKEUP_SOURCE_AVALID    MX6SX_USB_VBUS_WAKEUP_SOURCE(1)
+#define MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID    MX6SX_USB_VBUS_WAKEUP_SOURCE(2)
+#define MX6SX_USB_VBUS_WAKEUP_SOURCE_SESS_END  MX6SX_USB_VBUS_WAKEUP_SOURCE(3)
 
 #define VF610_OVER_CUR_DIS             BIT(7)
 
@@ -64,12 +76,13 @@ struct usbmisc_ops {
        int (*init)(struct imx_usbmisc_data *data);
        /* It's called once after adding a usb device */
        int (*post)(struct imx_usbmisc_data *data);
+       /* It's called when we need to enable/disable usb wakeup */
+       int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
 };
 
 struct imx_usbmisc {
        void __iomem *base;
        spinlock_t lock;
-       struct clk *clk;
        const struct usbmisc_ops *ops;
 };
 
@@ -204,6 +217,35 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
        return 0;
 }
 
+static int usbmisc_imx6q_set_wakeup
+       (struct imx_usbmisc_data *data, bool enabled)
+{
+       struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+       unsigned long flags;
+       u32 val;
+       u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
+               MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
+       int ret = 0;
+
+       if (data->index > 3)
+               return -EINVAL;
+
+       spin_lock_irqsave(&usbmisc->lock, flags);
+       val = readl(usbmisc->base + data->index * 4);
+       if (enabled) {
+               val |= wakeup_setting;
+               writel(val, usbmisc->base + data->index * 4);
+       } else {
+               if (val & MX6_BM_WAKEUP_INTR)
+                       pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
+               val &= ~wakeup_setting;
+               writel(val, usbmisc->base + data->index * 4);
+       }
+       spin_unlock_irqrestore(&usbmisc->lock, flags);
+
+       return ret;
+}
+
 static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
 {
        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
@@ -221,6 +263,36 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
                spin_unlock_irqrestore(&usbmisc->lock, flags);
        }
 
+       usbmisc_imx6q_set_wakeup(data, false);
+
+       return 0;
+}
+
+static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
+{
+       void __iomem *reg = NULL;
+       unsigned long flags;
+       struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+       u32 val;
+
+       usbmisc_imx6q_init(data);
+
+       if (data->index == 0 || data->index == 1) {
+               reg = usbmisc->base + MX6_USB_OTG1_PHY_CTRL + data->index * 4;
+               spin_lock_irqsave(&usbmisc->lock, flags);
+               /* Set vbus wakeup source as bvalid */
+               val = readl(reg);
+               writel(val | MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID, reg);
+               /*
+                * Disable dp/dm wakeup in device mode when vbus is
+                * not there.
+                */
+               val = readl(usbmisc->base + data->index * 4);
+               writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN,
+                       usbmisc->base + data->index * 4);
+               spin_unlock_irqrestore(&usbmisc->lock, flags);
+       }
+
        return 0;
 }
 
@@ -258,6 +330,7 @@ static const struct usbmisc_ops imx53_usbmisc_ops = {
 };
 
 static const struct usbmisc_ops imx6q_usbmisc_ops = {
+       .set_wakeup = usbmisc_imx6q_set_wakeup,
        .init = usbmisc_imx6q_init,
 };
 
@@ -265,10 +338,19 @@ static const struct usbmisc_ops vf610_usbmisc_ops = {
        .init = usbmisc_vf610_init,
 };
 
+static const struct usbmisc_ops imx6sx_usbmisc_ops = {
+       .set_wakeup = usbmisc_imx6q_set_wakeup,
+       .init = usbmisc_imx6sx_init,
+};
+
 int imx_usbmisc_init(struct imx_usbmisc_data *data)
 {
-       struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+       struct imx_usbmisc *usbmisc;
+
+       if (!data)
+               return 0;
 
+       usbmisc = dev_get_drvdata(data->dev);
        if (!usbmisc->ops->init)
                return 0;
        return usbmisc->ops->init(data);
@@ -277,14 +359,32 @@ EXPORT_SYMBOL_GPL(imx_usbmisc_init);
 
 int imx_usbmisc_init_post(struct imx_usbmisc_data *data)
 {
-       struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+       struct imx_usbmisc *usbmisc;
 
+       if (!data)
+               return 0;
+
+       usbmisc = dev_get_drvdata(data->dev);
        if (!usbmisc->ops->post)
                return 0;
        return usbmisc->ops->post(data);
 }
 EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
 
+int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
+{
+       struct imx_usbmisc *usbmisc;
+
+       if (!data)
+               return 0;
+
+       usbmisc = dev_get_drvdata(data->dev);
+       if (!usbmisc->ops->set_wakeup)
+               return 0;
+       return usbmisc->ops->set_wakeup(data, enabled);
+}
+EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
+
 static const struct of_device_id usbmisc_imx_dt_ids[] = {
        {
                .compatible = "fsl,imx25-usbmisc",
@@ -314,6 +414,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
                .compatible = "fsl,vf610-usbmisc",
                .data = &vf610_usbmisc_ops,
        },
+       {
+               .compatible = "fsl,imx6sx-usbmisc",
+               .data = &imx6sx_usbmisc_ops,
+       },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
@@ -322,7 +426,6 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct imx_usbmisc *data;
-       int ret;
        struct of_device_id *tmp_dev;
 
        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
@@ -336,20 +439,6 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
        if (IS_ERR(data->base))
                return PTR_ERR(data->base);
 
-       data->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(data->clk)) {
-               dev_err(&pdev->dev,
-                       "failed to get clock, err=%ld\n", PTR_ERR(data->clk));
-               return PTR_ERR(data->clk);
-       }
-
-       ret = clk_prepare_enable(data->clk);
-       if (ret) {
-               dev_err(&pdev->dev,
-                       "clk_prepare_enable failed, err=%d\n", ret);
-               return ret;
-       }
-
        tmp_dev = (struct of_device_id *)
                of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
        data->ops = (const struct usbmisc_ops *)tmp_dev->data;
@@ -360,8 +449,6 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
 
 static int usbmisc_imx_remove(struct platform_device *pdev)
 {
-       struct imx_usbmisc *usbmisc = dev_get_drvdata(&pdev->dev);
-       clk_disable_unprepare(usbmisc->clk);
        return 0;
 }
 
index 683617714e7cf852fdf3fc2d4ec8590ab6d1a114..3e15add665e236f2ef15bd1a9858dd9eabcb0c96 100644 (file)
@@ -360,7 +360,7 @@ static void acm_ctrl_irq(struct urb *urb)
        }
 exit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
-       if (retval)
+       if (retval && retval != -EPERM)
                dev_err(&acm->control->dev, "%s - usb_submit_urb failed: %d\n",
                                                        __func__, retval);
 }
@@ -417,25 +417,33 @@ static void acm_read_bulk_callback(struct urb *urb)
        struct acm_rb *rb = urb->context;
        struct acm *acm = rb->instance;
        unsigned long flags;
+       int status = urb->status;
 
        dev_vdbg(&acm->data->dev, "%s - urb %d, len %d\n", __func__,
                                        rb->index, urb->actual_length);
-       set_bit(rb->index, &acm->read_urbs_free);
 
        if (!acm->dev) {
+               set_bit(rb->index, &acm->read_urbs_free);
                dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__);
                return;
        }
 
-       if (urb->status) {
+       if (status) {
+               set_bit(rb->index, &acm->read_urbs_free);
                dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n",
-                                                       __func__, urb->status);
+                                                       __func__, status);
                return;
        }
 
        usb_mark_last_busy(acm->dev);
 
        acm_process_read_urb(acm, urb);
+       /*
+        * Unthrottle may run on another CPU which needs to see events
+        * in the same order. Submission has an implict barrier
+        */
+       smp_mb__before_atomic();
+       set_bit(rb->index, &acm->read_urbs_free);
 
        /* throttle device if requested by tty */
        spin_lock_irqsave(&acm->read_lock, flags);
@@ -454,13 +462,14 @@ static void acm_write_bulk(struct urb *urb)
        struct acm_wb *wb = urb->context;
        struct acm *acm = wb->instance;
        unsigned long flags;
+       int status = urb->status;
 
-       if (urb->status || (urb->actual_length != urb->transfer_buffer_length))
+       if (status || (urb->actual_length != urb->transfer_buffer_length))
                dev_vdbg(&acm->data->dev, "%s - len %d/%d, status %d\n",
                        __func__,
                        urb->actual_length,
                        urb->transfer_buffer_length,
-                       urb->status);
+                       status);
 
        spin_lock_irqsave(&acm->write_lock, flags);
        acm_write_done(acm, wb);
index a051a7a2b1bd534a93fd459da7c553e0a5af4dfa..61ea87917433096a73cb2bc3ef7f3f3a857e5caa 100644 (file)
@@ -245,7 +245,7 @@ static void wdm_int_callback(struct urb *urb)
        case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
                dev_dbg(&desc->intf->dev,
                        "NOTIFY_RESPONSE_AVAILABLE received: index %d len %d",
-                       dr->wIndex, dr->wLength);
+                       le16_to_cpu(dr->wIndex), le16_to_cpu(dr->wLength));
                break;
 
        case USB_CDC_NOTIFY_NETWORK_CONNECTION:
@@ -262,7 +262,9 @@ static void wdm_int_callback(struct urb *urb)
                clear_bit(WDM_POLL_RUNNING, &desc->flags);
                dev_err(&desc->intf->dev,
                        "unknown notification %d received: index %d len %d\n",
-                       dr->bNotificationType, dr->wIndex, dr->wLength);
+                       dr->bNotificationType,
+                       le16_to_cpu(dr->wIndex),
+                       le16_to_cpu(dr->wLength));
                goto exit;
        }
 
@@ -339,7 +341,7 @@ static ssize_t wdm_write
        desc->werr = 0;
        spin_unlock_irq(&desc->iuspin);
        if (we < 0)
-               return -EIO;
+               return usb_translate_errors(we);
 
        buf = kmalloc(count, GFP_KERNEL);
        if (!buf) {
@@ -349,30 +351,25 @@ static ssize_t wdm_write
 
        r = copy_from_user(buf, buffer, count);
        if (r > 0) {
-               kfree(buf);
                rv = -EFAULT;
-               goto outnl;
+               goto out_free_mem;
        }
 
        /* concurrent writes and disconnect */
        r = mutex_lock_interruptible(&desc->wlock);
        rv = -ERESTARTSYS;
-       if (r) {
-               kfree(buf);
-               goto outnl;
-       }
+       if (r)
+               goto out_free_mem;
 
        if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
-               kfree(buf);
                rv = -ENODEV;
-               goto outnp;
+               goto out_free_mem_lock;
        }
 
        r = usb_autopm_get_interface(desc->intf);
        if (r < 0) {
-               kfree(buf);
                rv = usb_translate_errors(r);
-               goto outnp;
+               goto out_free_mem_lock;
        }
 
        if (!(file->f_flags & O_NONBLOCK))
@@ -386,9 +383,8 @@ static ssize_t wdm_write
                r = -EIO;
 
        if (r < 0) {
-               kfree(buf);
                rv = r;
-               goto out;
+               goto out_free_mem_pm;
        }
 
        req = desc->orq;
@@ -408,28 +404,35 @@ static ssize_t wdm_write
                             USB_RECIP_INTERFACE);
        req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
        req->wValue = 0;
-       req->wIndex = desc->inum;
+       req->wIndex = desc->inum; /* already converted */
        req->wLength = cpu_to_le16(count);
        set_bit(WDM_IN_USE, &desc->flags);
        desc->outbuf = buf;
 
        rv = usb_submit_urb(desc->command, GFP_KERNEL);
        if (rv < 0) {
-               kfree(buf);
                desc->outbuf = NULL;
                clear_bit(WDM_IN_USE, &desc->flags);
                dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv);
                rv = usb_translate_errors(rv);
+               goto out_free_mem_pm;
        } else {
                dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d",
-                       req->wIndex);
+                       le16_to_cpu(req->wIndex));
        }
-out:
+
        usb_autopm_put_interface(desc->intf);
-outnp:
        mutex_unlock(&desc->wlock);
 outnl:
        return rv < 0 ? rv : count;
+
+out_free_mem_pm:
+       usb_autopm_put_interface(desc->intf);
+out_free_mem_lock:
+       mutex_unlock(&desc->wlock);
+out_free_mem:
+       kfree(buf);
+       return rv;
 }
 
 /*
@@ -519,9 +522,9 @@ retry:
                spin_lock_irq(&desc->iuspin);
 
                if (desc->rerr) { /* read completed, error happened */
+                       rv = usb_translate_errors(desc->rerr);
                        desc->rerr = 0;
                        spin_unlock_irq(&desc->iuspin);
-                       rv = -EIO;
                        goto err;
                }
                /*
@@ -820,7 +823,7 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor
        desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
        desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
        desc->irq->wValue = 0;
-       desc->irq->wIndex = desc->inum;
+       desc->irq->wIndex = desc->inum; /* already converted */
        desc->irq->wLength = cpu_to_le16(desc->wMaxCommand);
 
        usb_fill_control_urb(
index 11635537c052cdc5d4e4c78d615a09aafc4c5e83..4b0448c26810c31b1fafdcdaceb15534711e6221 100644 (file)
@@ -2408,7 +2408,7 @@ static int usbdev_notify(struct notifier_block *self,
 }
 
 static struct notifier_block usbdev_nb = {
-       .notifier_call =        usbdev_notify,
+       .notifier_call =        usbdev_notify,
 };
 
 static struct cdev usb_device_cdev;
index d7c3d5a35946a63a905dc2501ec72beae0c5fe42..3b7151687776817bf34981c878833a25fbda119f 100644 (file)
@@ -3406,10 +3406,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
        if (status) {
                dev_dbg(&port_dev->dev, "can't resume, status %d\n", status);
        } else {
-               /* drive resume for at least 20 msec */
+               /* drive resume for USB_RESUME_TIMEOUT msec */
                dev_dbg(&udev->dev, "usb %sresume\n",
                                (PMSG_IS_AUTO(msg) ? "auto-" : ""));
-               msleep(25);
+               msleep(USB_RESUME_TIMEOUT);
 
                /* Virtual root hubs can trigger on GET_PORT_STATUS to
                 * stop resume signaling.  Then finish the resume
index b1fb9aef0f5b09b10b412c315345637eb3f50a72..8d5b2f4113cd563004acbabb459f4e4212361138 100644 (file)
@@ -49,6 +49,22 @@ const char *usbcore_name = "usbcore";
 
 static bool nousb;     /* Disable USB when built into kernel image */
 
+/* To disable USB, kernel command line is 'nousb' not 'usbcore.nousb' */
+#ifdef MODULE
+module_param(nousb, bool, 0444);
+#else
+core_param(nousb, nousb, bool, 0444);
+#endif
+
+/*
+ * for external read access to <nousb>
+ */
+int usb_disabled(void)
+{
+       return nousb;
+}
+EXPORT_SYMBOL_GPL(usb_disabled);
+
 #ifdef CONFIG_PM
 static int usb_autosuspend_delay = 2;          /* Default delay value,
                                                 * in seconds */
@@ -964,22 +980,6 @@ void usb_buffer_unmap_sg(const struct usb_device *dev, int is_in,
 EXPORT_SYMBOL_GPL(usb_buffer_unmap_sg);
 #endif
 
-/* To disable USB, kernel command line is 'nousb' not 'usbcore.nousb' */
-#ifdef MODULE
-module_param(nousb, bool, 0444);
-#else
-core_param(nousb, nousb, bool, 0444);
-#endif
-
-/*
- * for external read access to <nousb>
- */
-int usb_disabled(void)
-{
-       return nousb;
-}
-EXPORT_SYMBOL_GPL(usb_disabled);
-
 /*
  * Notifications of device and interface registration
  */
@@ -1045,7 +1045,7 @@ static void usb_debugfs_cleanup(void)
 static int __init usb_init(void)
 {
        int retval;
-       if (nousb) {
+       if (usb_disabled()) {
                pr_info("%s: USB support disabled\n", usbcore_name);
                return 0;
        }
@@ -1102,7 +1102,7 @@ out:
 static void __exit usb_exit(void)
 {
        /* This will matter if shutdown/reboot does exitcalls. */
-       if (nousb)
+       if (usb_disabled())
                return;
 
        usb_deregister_device_driver(&usb_generic_driver);
index 76b9ba4dc9258ff0d523c2a9898f701568b31d06..1bcb36ae6505afc9cff52f218d396271f763d542 100644 (file)
@@ -59,11 +59,13 @@ config USB_DWC2_PLATFORM
 
 config USB_DWC2_PCI
        tristate "DWC2 PCI"
-       depends on USB_DWC2_HOST && PCI
-       default USB_DWC2_HOST
+       depends on PCI
+       default n
+       select USB_DWC2_PLATFORM
+       select NOP_USB_XCEIV
        help
          The Designware USB2.0 PCI interface module for controllers
-         connected to a PCI bus. This is only used for host mode.
+         connected to a PCI bus.
 
 config USB_DWC2_DEBUG
        bool "Enable Debugging Messages"
index 8f752679752aaacdcdcf215a66cfba0fedfde16e..f07b425eaff382b0f8403beaec15117ae42335a6 100644 (file)
@@ -19,10 +19,8 @@ endif
 # mode. The PCI bus interface module will called dwc2_pci.ko and the platform
 # interface module will be called dwc2_platform.ko.
 
-ifneq ($(CONFIG_USB_DWC2_PCI),)
-       obj-$(CONFIG_USB_DWC2)          += dwc2_pci.o
-       dwc2_pci-y                      := pci.o
-endif
+obj-$(CONFIG_USB_DWC2_PCI)             += dwc2_pci.o
+dwc2_pci-y                             := pci.o
 
 obj-$(CONFIG_USB_DWC2_PLATFORM)                += dwc2_platform.o
 dwc2_platform-y                                := platform.o
index f74304b12652062d43335e266812fe4cb645a822..836c012c770788d2d7e23109660d621939dff86b 100644 (file)
@@ -593,6 +593,8 @@ struct dwc2_hsotg {
        struct dwc2_core_params *core_params;
        enum usb_otg_state op_state;
        enum usb_dr_mode dr_mode;
+       unsigned int hcd_enabled:1;
+       unsigned int gadget_enabled:1;
 
        struct phy *phy;
        struct usb_phy *uphy;
index c78c8740db1d7855967d441a21ae1ffafe3d26fc..fbbbac2150a53fbcf7536088c563a46167eada3d 100644 (file)
@@ -257,6 +257,14 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg)
                 */
                channel->qh = NULL;
        }
+       /* All channels have been freed, mark them available */
+       if (hsotg->core_params->uframe_sched > 0) {
+               hsotg->available_host_channels =
+                       hsotg->core_params->host_channels;
+       } else {
+               hsotg->non_periodic_channels = 0;
+               hsotg->periodic_channels = 0;
+       }
 }
 
 /**
@@ -1527,7 +1535,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                        hprt0 |= HPRT0_RES;
                        writel(hprt0, hsotg->regs + HPRT0);
                        hprt0 &= ~HPRT0_SUSP;
-                       usleep_range(100000, 150000);
+                       msleep(USB_RESUME_TIMEOUT);
 
                        hprt0 &= ~HPRT0_RES;
                        writel(hprt0, hsotg->regs + HPRT0);
@@ -1608,7 +1616,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                dev_dbg(hsotg->dev, "GetHubDescriptor\n");
                hub_desc = (struct usb_hub_descriptor *)buf;
                hub_desc->bDescLength = 9;
-               hub_desc->bDescriptorType = 0x29;
+               hub_desc->bDescriptorType = USB_DT_HUB;
                hub_desc->bNbrPorts = 1;
                hub_desc->wHubCharacteristics =
                        cpu_to_le16(HUB_CHAR_COMMON_LPSM |
index a4e724b0a62e9aa89cdecce45eea9991e857a051..ae419615a176a5e1da5ad13f8167c3bcddf0cdfe 100644 (file)
 
 #include <linux/usb/hcd.h>
 #include <linux/usb/ch11.h>
+#include <linux/platform_device.h>
+#include <linux/usb/usb_phy_generic.h>
 
-#include "core.h"
-#include "hcd.h"
-
-#define PCI_VENDOR_ID_SYNOPSYS         0x16c3
 #define PCI_PRODUCT_ID_HAPS_HSOTG      0xabc0
 
-static const char dwc2_driver_name[] = "dwc2";
-
-static const struct dwc2_core_params dwc2_module_params = {
-       .otg_cap                        = -1,
-       .otg_ver                        = -1,
-       .dma_enable                     = -1,
-       .dma_desc_enable                = 0,
-       .speed                          = -1,
-       .enable_dynamic_fifo            = -1,
-       .en_multiple_tx_fifo            = -1,
-       .host_rx_fifo_size              = 1024,
-       .host_nperio_tx_fifo_size       = 256,
-       .host_perio_tx_fifo_size        = 1024,
-       .max_transfer_size              = 65535,
-       .max_packet_count               = 511,
-       .host_channels                  = -1,
-       .phy_type                       = -1,
-       .phy_utmi_width                 = -1,
-       .phy_ulpi_ddr                   = -1,
-       .phy_ulpi_ext_vbus              = -1,
-       .i2c_enable                     = -1,
-       .ulpi_fs_ls                     = -1,
-       .host_support_fs_ls_low_power   = -1,
-       .host_ls_low_power_phy_clk      = -1,
-       .ts_dline                       = -1,
-       .reload_ctl                     = -1,
-       .ahbcfg                         = -1,
-       .uframe_sched                   = -1,
+static const char dwc2_driver_name[] = "dwc2-pci";
+
+struct dwc2_pci_glue {
+       struct platform_device *dwc2;
+       struct platform_device *phy;
 };
 
-/**
- * dwc2_driver_remove() - Called when the DWC_otg core is unregistered with the
- * DWC_otg driver
- *
- * @dev: Bus device
- *
- * This routine is called, for example, when the rmmod command is executed. The
- * device may or may not be electrically present. If it is present, the driver
- * stops device processing. Any resources used on behalf of this device are
- * freed.
- */
-static void dwc2_driver_remove(struct pci_dev *dev)
+static void dwc2_pci_remove(struct pci_dev *pci)
 {
-       struct dwc2_hsotg *hsotg = pci_get_drvdata(dev);
+       struct dwc2_pci_glue *glue = pci_get_drvdata(pci);
 
-       dwc2_hcd_remove(hsotg);
-       pci_disable_device(dev);
+       platform_device_unregister(glue->dwc2);
+       usb_phy_generic_unregister(glue->phy);
+       kfree(glue);
+       pci_set_drvdata(pci, NULL);
 }
 
-/**
- * dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg
- * driver
- *
- * @dev: Bus device
- *
- * This routine creates the driver components required to control the device
- * (core, HCD, and PCD) and initializes the device. The driver components are
- * stored in a dwc2_hsotg structure. A reference to the dwc2_hsotg is saved
- * in the device private data. This allows the driver to access the dwc2_hsotg
- * structure on subsequent calls to driver methods for this device.
- */
-static int dwc2_driver_probe(struct pci_dev *dev,
-                            const struct pci_device_id *id)
+static int dwc2_pci_probe(struct pci_dev *pci,
+               const struct pci_device_id *id)
 {
-       struct dwc2_hsotg *hsotg;
-       int retval;
+       struct resource         res[2];
+       struct platform_device  *dwc2;
+       struct platform_device  *phy;
+       int                     ret;
+       struct device           *dev = &pci->dev;
+       struct dwc2_pci_glue    *glue;
+
+       ret = pcim_enable_device(pci);
+       if (ret) {
+               dev_err(dev, "failed to enable pci device\n");
+               return -ENODEV;
+       }
+
+       pci_set_master(pci);
 
-       hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL);
-       if (!hsotg)
+       dwc2 = platform_device_alloc("dwc2", PLATFORM_DEVID_AUTO);
+       if (!dwc2) {
+               dev_err(dev, "couldn't allocate dwc2 device\n");
                return -ENOMEM;
+       }
 
-       hsotg->dev = &dev->dev;
-       hsotg->regs = devm_ioremap_resource(&dev->dev, &dev->resource[0]);
-       if (IS_ERR(hsotg->regs))
-               return PTR_ERR(hsotg->regs);
+       memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
 
-       dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n",
-               (unsigned long)pci_resource_start(dev, 0), hsotg->regs);
+       res[0].start    = pci_resource_start(pci, 0);
+       res[0].end      = pci_resource_end(pci, 0);
+       res[0].name     = "dwc2";
+       res[0].flags    = IORESOURCE_MEM;
 
-       if (pci_enable_device(dev) < 0)
-               return -ENODEV;
+       res[1].start    = pci->irq;
+       res[1].name     = "dwc2";
+       res[1].flags    = IORESOURCE_IRQ;
 
-       pci_set_master(dev);
+       ret = platform_device_add_resources(dwc2, res, ARRAY_SIZE(res));
+       if (ret) {
+               dev_err(dev, "couldn't add resources to dwc2 device\n");
+               return ret;
+       }
 
-       retval = devm_request_irq(hsotg->dev, dev->irq,
-                                 dwc2_handle_common_intr, IRQF_SHARED,
-                                 dev_name(hsotg->dev), hsotg);
-       if (retval)
-               return retval;
+       dwc2->dev.parent = dev;
 
-       spin_lock_init(&hsotg->lock);
-       retval = dwc2_hcd_init(hsotg, dev->irq, &dwc2_module_params);
-       if (retval) {
-               pci_disable_device(dev);
-               return retval;
+       phy = usb_phy_generic_register();
+       if (IS_ERR(phy)) {
+               dev_err(dev, "error registering generic PHY (%ld)\n",
+                       PTR_ERR(phy));
+               return PTR_ERR(phy);
        }
 
-       pci_set_drvdata(dev, hsotg);
+       ret = platform_device_add(dwc2);
+       if (ret) {
+               dev_err(dev, "failed to register dwc2 device\n");
+               goto err;
+       }
+
+       glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+       if (!glue)
+               return -ENOMEM;
+
+       glue->phy = phy;
+       glue->dwc2 = dwc2;
+       pci_set_drvdata(pci, glue);
 
-       return retval;
+       return 0;
+err:
+       usb_phy_generic_unregister(phy);
+       platform_device_put(dwc2);
+       return ret;
 }
 
 static const struct pci_device_id dwc2_pci_ids[] = {
@@ -174,8 +158,8 @@ MODULE_DEVICE_TABLE(pci, dwc2_pci_ids);
 static struct pci_driver dwc2_pci_driver = {
        .name = dwc2_driver_name,
        .id_table = dwc2_pci_ids,
-       .probe = dwc2_driver_probe,
-       .remove = dwc2_driver_remove,
+       .probe = dwc2_pci_probe,
+       .remove = dwc2_pci_remove,
 };
 
 module_pci_driver(dwc2_pci_driver);
index ae095f009b4f792b508ee2e713f3268359a27b42..185663e0b5f439af16065989a27ae74cc31a59b6 100644 (file)
@@ -121,8 +121,10 @@ static int dwc2_driver_remove(struct platform_device *dev)
 {
        struct dwc2_hsotg *hsotg = platform_get_drvdata(dev);
 
-       dwc2_hcd_remove(hsotg);
-       s3c_hsotg_remove(hsotg);
+       if (hsotg->hcd_enabled)
+               dwc2_hcd_remove(hsotg);
+       if (hsotg->gadget_enabled)
+               s3c_hsotg_remove(hsotg);
 
        return 0;
 }
@@ -234,12 +236,23 @@ static int dwc2_driver_probe(struct platform_device *dev)
 
        spin_lock_init(&hsotg->lock);
        mutex_init(&hsotg->init_mutex);
-       retval = dwc2_gadget_init(hsotg, irq);
-       if (retval)
-               return retval;
-       retval = dwc2_hcd_init(hsotg, irq, params);
-       if (retval)
-               return retval;
+
+       if (hsotg->dr_mode != USB_DR_MODE_HOST) {
+               retval = dwc2_gadget_init(hsotg, irq);
+               if (retval)
+                       return retval;
+               hsotg->gadget_enabled = 1;
+       }
+
+       if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) {
+               retval = dwc2_hcd_init(hsotg, irq, params);
+               if (retval) {
+                       if (hsotg->gadget_enabled)
+                               s3c_hsotg_remove(hsotg);
+                       return retval;
+               }
+               hsotg->hcd_enabled = 1;
+       }
 
        platform_set_drvdata(dev, hsotg);
 
index edbf9c85af7eddebc20c0cc76c2aea508d95d07b..827c4f80379f38d7ecfadfd60bb1f16e72c34fa4 100644 (file)
@@ -104,11 +104,4 @@ config USB_DWC3_DEBUG
        help
          Say Y here to enable debugging messages on DWC3 Driver.
 
-config DWC3_HOST_USB3_LPM_ENABLE
-       bool "Enable USB3 LPM Capability"
-       depends on USB_DWC3_HOST=y || USB_DWC3_DUAL_ROLE=y
-       default n
-       help
-         Select this when you want to enable USB3 LPM with dwc3 xhci host.
-
 endif
index 9f0e209b8f6cee759d873eca5e6f813f6809a524..2bbab3d86fffe7437100f4757d42d174e51f5928 100644 (file)
@@ -774,17 +774,13 @@ static int dwc3_probe(struct platform_device *pdev)
         * since it will be requested by the xhci-plat driver.
         */
        regs = devm_ioremap_resource(dev, res);
-       if (IS_ERR(regs))
-               return PTR_ERR(regs);
+       if (IS_ERR(regs)) {
+               ret = PTR_ERR(regs);
+               goto err0;
+       }
 
        dwc->regs       = regs;
        dwc->regs_size  = resource_size(res);
-       /*
-        * restore res->start back to its original value so that,
-        * in case the probe is deferred, we don't end up getting error in
-        * request the memory region the next time probe is called.
-        */
-       res->start -= DWC3_GLOBALS_REGS_START;
 
        /* default to highest possible threshold */
        lpm_nyet_threshold = 0xff;
@@ -808,6 +804,8 @@ static int dwc3_probe(struct platform_device *pdev)
                                "snps,is-utmi-l1-suspend");
                of_property_read_u8(node, "snps,hird-threshold",
                                &hird_threshold);
+               dwc->usb3_lpm_capable = of_property_read_bool(node,
+                               "snps,usb3_lpm_capable");
 
                dwc->needs_fifo_resize = of_property_read_bool(node,
                                "tx-fifo-resize");
@@ -848,6 +846,7 @@ static int dwc3_probe(struct platform_device *pdev)
                        hird_threshold = pdata->hird_threshold;
 
                dwc->needs_fifo_resize = pdata->tx_fifo_resize;
+               dwc->usb3_lpm_capable = pdata->usb3_lpm_capable;
                dwc->dr_mode = pdata->dr_mode;
 
                dwc->disable_scramble_quirk = pdata->disable_scramble_quirk;
@@ -878,7 +877,7 @@ static int dwc3_probe(struct platform_device *pdev)
 
        ret = dwc3_core_get_phy(dwc);
        if (ret)
-               return ret;
+               goto err0;
 
        spin_lock_init(&dwc->lock);
        platform_set_drvdata(pdev, dwc);
@@ -899,7 +898,7 @@ static int dwc3_probe(struct platform_device *pdev)
        if (ret) {
                dev_err(dwc->dev, "failed to allocate event buffers\n");
                ret = -ENOMEM;
-               goto err0;
+               goto err1;
        }
 
        if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
@@ -913,65 +912,81 @@ static int dwc3_probe(struct platform_device *pdev)
        ret = dwc3_core_init(dwc);
        if (ret) {
                dev_err(dev, "failed to initialize core\n");
-               goto err0;
+               goto err1;
        }
 
        usb_phy_set_suspend(dwc->usb2_phy, 0);
        usb_phy_set_suspend(dwc->usb3_phy, 0);
        ret = phy_power_on(dwc->usb2_generic_phy);
        if (ret < 0)
-               goto err1;
+               goto err2;
 
        ret = phy_power_on(dwc->usb3_generic_phy);
        if (ret < 0)
-               goto err_usb2phy_power;
+               goto err3;
 
        ret = dwc3_event_buffers_setup(dwc);
        if (ret) {
                dev_err(dwc->dev, "failed to setup event buffers\n");
-               goto err_usb3phy_power;
+               goto err4;
        }
 
        ret = dwc3_core_init_mode(dwc);
        if (ret)
-               goto err2;
+               goto err5;
 
        ret = dwc3_debugfs_init(dwc);
        if (ret) {
                dev_err(dev, "failed to initialize debugfs\n");
-               goto err3;
+               goto err6;
        }
 
        pm_runtime_allow(dev);
 
        return 0;
 
-err3:
+err6:
        dwc3_core_exit_mode(dwc);
 
-err2:
+err5:
        dwc3_event_buffers_cleanup(dwc);
 
-err_usb3phy_power:
+err4:
        phy_power_off(dwc->usb3_generic_phy);
 
-err_usb2phy_power:
+err3:
        phy_power_off(dwc->usb2_generic_phy);
 
-err1:
+err2:
        usb_phy_set_suspend(dwc->usb2_phy, 1);
        usb_phy_set_suspend(dwc->usb3_phy, 1);
        dwc3_core_exit(dwc);
 
-err0:
+err1:
        dwc3_free_event_buffers(dwc);
 
+err0:
+       /*
+        * restore res->start back to its original value so that, in case the
+        * probe is deferred, we don't end up getting error in request the
+        * memory region the next time probe is called.
+        */
+       res->start -= DWC3_GLOBALS_REGS_START;
+
        return ret;
 }
 
 static int dwc3_remove(struct platform_device *pdev)
 {
        struct dwc3     *dwc = platform_get_drvdata(pdev);
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       /*
+        * restore res->start back to its original value so that, in case the
+        * probe is deferred, we don't end up getting error in request the
+        * memory region the next time probe is called.
+        */
+       res->start -= DWC3_GLOBALS_REGS_START;
 
        dwc3_debugfs_exit(dwc);
        dwc3_core_exit_mode(dwc);
index d201910b892f9f9d068cdb1dab74551c3904b11c..fdab715a063119d6e696a8f66ea26d4a1613e983 100644 (file)
@@ -689,6 +689,7 @@ struct dwc3_scratchpad_array {
  * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
  * @start_config_issued: true when StartConfig command has been issued
  * @three_stage_setup: set if we perform a three phase setup
+ * @usb3_lpm_capable: set if hadrware supports Link Power Management
  * @disable_scramble_quirk: set if we enable the disable scramble quirk
  * @u2exit_lfps_quirk: set if we enable u2exit lfps quirk
  * @u2ss_inp3_quirk: set if we enable P3 OK for U2/SS Inactive quirk
@@ -812,6 +813,7 @@ struct dwc3 {
        unsigned                setup_packet_pending:1;
        unsigned                start_config_issued:1;
        unsigned                three_stage_setup:1;
+       unsigned                usb3_lpm_capable:1;
 
        unsigned                disable_scramble_quirk:1;
        unsigned                u2exit_lfps_quirk:1;
index 52e0c4e5e48efa8cc1ccecf0ee30364ff1419634..edba5348be186bf33857bd7c1d47233df6d12422 100644 (file)
@@ -325,15 +325,6 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
        return IRQ_HANDLED;
 }
 
-static int dwc3_omap_remove_core(struct device *dev, void *c)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-
-       of_device_unregister(pdev);
-
-       return 0;
-}
-
 static void dwc3_omap_enable_irqs(struct dwc3_omap *omap)
 {
        u32                     reg;
@@ -600,7 +591,7 @@ static int dwc3_omap_remove(struct platform_device *pdev)
        if (omap->extcon_id_dev.edev)
                extcon_unregister_interest(&omap->extcon_id_dev);
        dwc3_omap_disable_irqs(omap);
-       device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
+       of_platform_depopulate(omap->dev);
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
 
index 8d950569d557bdacf2711fa8eb449a5dc63f4f1a..b773fb53d6a7cd09be0daee5f119279ada098e78 100644 (file)
@@ -24,8 +24,6 @@
 
 #include "platform_data.h"
 
-/* FIXME define these in <linux/pci_ids.h> */
-#define PCI_VENDOR_ID_SYNOPSYS         0x16c3
 #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3        0xabcd
 #define PCI_DEVICE_ID_INTEL_BYT                0x0f37
 #define PCI_DEVICE_ID_INTEL_MRFLD      0x119e
index a03a485205c787c74812f14337096b2831223cbc..8946c32047e996308e3a752c8dd0ce7f501c3909 100644 (file)
@@ -1855,32 +1855,27 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
        unsigned int            i;
        int                     ret;
 
+       req = next_request(&dep->req_queued);
+       if (!req) {
+               WARN_ON_ONCE(1);
+               return 1;
+       }
+       i = 0;
        do {
-               req = next_request(&dep->req_queued);
-               if (!req) {
-                       WARN_ON_ONCE(1);
-                       return 1;
-               }
-               i = 0;
-               do {
-                       slot = req->start_slot + i;
-                       if ((slot == DWC3_TRB_NUM - 1) &&
+               slot = req->start_slot + i;
+               if ((slot == DWC3_TRB_NUM - 1) &&
                                usb_endpoint_xfer_isoc(dep->endpoint.desc))
-                               slot++;
-                       slot %= DWC3_TRB_NUM;
-                       trb = &dep->trb_pool[slot];
-
-                       ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
-                                       event, status);
-                       if (ret)
-                               break;
-               }while (++i < req->request.num_mapped_sgs);
-
-               dwc3_gadget_giveback(dep, req, status);
+                       slot++;
+               slot %= DWC3_TRB_NUM;
+               trb = &dep->trb_pool[slot];
 
+               ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
+                               event, status);
                if (ret)
                        break;
-       } while (1);
+       } while (++i < req->request.num_mapped_sgs);
+
+       dwc3_gadget_giveback(dep, req, status);
 
        if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
                        list_empty(&dep->req_queued)) {
index 12bfd3c5405e48c6225cfc7489fb747e1698d663..c679f63783aec8c1a0fe4e43bef80546a55abf44 100644 (file)
@@ -49,9 +49,7 @@ int dwc3_host_init(struct dwc3 *dwc)
 
        memset(&pdata, 0, sizeof(pdata));
 
-#ifdef CONFIG_DWC3_HOST_USB3_LPM_ENABLE
-       pdata.usb3_lpm_capable = 1;
-#endif
+       pdata.usb3_lpm_capable = dwc->usb3_lpm_capable;
 
        ret = platform_device_add_data(xhci, &pdata, sizeof(pdata));
        if (ret) {
index a3a3b6d5668cf47d9555e470500ca3cb0d25bbe7..a2bd464be828785975383a2f66a3b2cba39bf0ab 100644 (file)
@@ -24,6 +24,7 @@ struct dwc3_platform_data {
        enum usb_device_speed maximum_speed;
        enum usb_dr_mode dr_mode;
        bool tx_fifo_resize;
+       bool usb3_lpm_capable;
 
        unsigned is_utmi_l1_suspend:1;
        u8 hird_threshold;
index b454d05be5838e08ecdda4fd60514ad0f444edc9..bcf83c0a6e62b340899ea661955de89bbfc9df11 100644 (file)
@@ -196,6 +196,9 @@ config USB_F_MIDI
 config USB_F_HID
        tristate
 
+config USB_F_PRINTER
+       tristate
+
 choice
        tristate "USB Gadget Drivers"
        default USB_ETH
@@ -434,6 +437,20 @@ config USB_CONFIGFS_F_UVC
          device. It provides a userspace API to process UVC control requests
          and stream video data to the host.
 
+config USB_CONFIGFS_F_PRINTER
+       bool "Printer function"
+       select USB_F_PRINTER
+       depends on USB_CONFIGFS
+       help
+         The Printer function channels data between the USB host and a
+         userspace program driving the print engine. The user space
+         program reads and writes the device file /dev/g_printer<X> to
+         receive or send printer data. It can use ioctl calls to
+         the device file to get or set printer status.
+
+         For more information, see Documentation/usb/gadget_printer.txt
+         which includes sample code for accessing the device file.
+
 source "drivers/usb/gadget/legacy/Kconfig"
 
 endchoice
index 13adfd1a3f54947f860f10161156a057dde274bc..4e3447bbd0976e42eda4ec2a5d71f6cb4e9f75c9 100644 (file)
@@ -1161,11 +1161,11 @@ static struct usb_gadget_string_container *copy_gadget_strings(
  * This function will create a deep copy of usb_gadget_strings and usb_string
  * and attach it to the cdev. The actual string (usb_string.s) will not be
  * copied but only a referenced will be made. The struct usb_gadget_strings
- * array may contain multiple languges and should be NULL terminated.
+ * array may contain multiple languages and should be NULL terminated.
  * The ->language pointer of each struct usb_gadget_strings has to contain the
  * same amount of entries.
  * For instance: sp[0] is en-US, sp[1] is es-ES. It is expected that the first
- * usb_string entry of es-ES containts the translation of the first usb_string
+ * usb_string entry of es-ES contains the translation of the first usb_string
  * entry of en-US. Therefore both entries become the same id assign.
  */
 struct usb_string *usb_gstrings_attach(struct usb_composite_dev *cdev,
@@ -1472,6 +1472,13 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
        req->length = 0;
        gadget->ep0->driver_data = cdev;
 
+       /*
+        * Don't let non-standard requests match any of the cases below
+        * by accident.
+        */
+       if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD)
+               goto unknown;
+
        switch (ctrl->bRequest) {
 
        /* we handle all standard USB descriptors */
@@ -1751,6 +1758,10 @@ unknown:
                 * take such requests too, if that's ever needed:  to work
                 * in config 0, etc.
                 */
+               list_for_each_entry(f, &cdev->config->functions, list)
+                       if (f->req_match && f->req_match(f, ctrl))
+                               goto try_fun_setup;
+               f = NULL;
                switch (ctrl->bRequestType & USB_RECIP_MASK) {
                case USB_RECIP_INTERFACE:
                        if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
@@ -1768,7 +1779,7 @@ unknown:
                                f = NULL;
                        break;
                }
-
+try_fun_setup:
                if (f && f->setup)
                        value = f->setup(f, ctrl);
                else {
index f71b1aaa0edfcaf78fe464170f508009140cc375..bd7def576955d825bf1651508fd715c964bd33c2 100644 (file)
@@ -42,3 +42,5 @@ usb_f_midi-y                  := f_midi.o
 obj-$(CONFIG_USB_F_MIDI)       += usb_f_midi.o
 usb_f_hid-y                    := f_hid.o
 obj-$(CONFIG_USB_F_HID)                += usb_f_hid.o
+usb_f_printer-y                        := f_printer.o
+obj-$(CONFIG_USB_F_PRINTER)    += usb_f_printer.o
index 175c9956cbe3a36949526029103d38b4c97225c3..a12315a78248d4a40349586062e043b8574d1308 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/export.h>
 #include <linux/hid.h>
 #include <linux/module.h>
+#include <linux/uio.h>
 #include <asm/unaligned.h>
 
 #include <linux/usb/composite.h>
@@ -655,9 +656,10 @@ static void ffs_user_copy_worker(struct work_struct *work)
                unuse_mm(io_data->mm);
        }
 
-       aio_complete(io_data->kiocb, ret, ret);
+       io_data->kiocb->ki_complete(io_data->kiocb, ret, ret);
 
-       if (io_data->ffs->ffs_eventfd && !io_data->kiocb->ki_eventfd)
+       if (io_data->ffs->ffs_eventfd &&
+           !(io_data->kiocb->ki_flags & IOCB_EVENTFD))
                eventfd_signal(io_data->ffs->ffs_eventfd, 1);
 
        usb_ep_free_request(io_data->ep, io_data->req);
index a2612fb79eff261ee336b73940f88e7514f9c5e0..13dfc9915b1dee679b89f83a19ab3ef56641ae34 100644 (file)
@@ -908,7 +908,6 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
 
        /* disable/free request and end point */
        usb_ep_disable(hidg->in_ep);
-       usb_ep_dequeue(hidg->in_ep, hidg->req);
        kfree(hidg->req->buf);
        usb_ep_free_request(hidg->in_ep, hidg->req);
 
index 811929cd4c9e21b7c59061375e4ad9de335e0c03..3cc109f3c9c803638b8a47ffc1aa4aabb8397a6b 100644 (file)
@@ -1085,7 +1085,7 @@ static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh)
        if (!curlun) {          /* Unsupported LUNs are okay */
                common->bad_lun_okay = 1;
                memset(buf, 0, 36);
-               buf[0] = 0x7f;          /* Unsupported, no device-type */
+               buf[0] = TYPE_NO_LUN;   /* Unsupported, no device-type */
                buf[4] = 31;            /* Additional length */
                return 36;
        }
@@ -2624,13 +2624,10 @@ static ssize_t file_store(struct device *dev, struct device_attribute *attr,
        return fsg_store_file(curlun, filesem, buf, count);
 }
 
-static DEVICE_ATTR_RW(ro);
 static DEVICE_ATTR_RW(nofua);
-static DEVICE_ATTR_RW(file);
-
-static struct device_attribute dev_attr_ro_cdrom = __ATTR_RO(ro);
-static struct device_attribute dev_attr_file_nonremovable = __ATTR_RO(file);
-
+/* mode wil be set in fsg_lun_attr_is_visible() */
+static DEVICE_ATTR(ro, 0, ro_show, ro_store);
+static DEVICE_ATTR(file, 0, file_show, file_store);
 
 /****************************** FSG COMMON ******************************/
 
@@ -2745,40 +2742,10 @@ error_release:
 }
 EXPORT_SYMBOL_GPL(fsg_common_set_num_buffers);
 
-static inline void fsg_common_remove_sysfs(struct fsg_lun *lun)
-{
-       device_remove_file(&lun->dev, &dev_attr_nofua);
-       /*
-        * device_remove_file() =>
-        *
-        * here the attr (e.g. dev_attr_ro) is only used to be passed to:
-        *
-        *      sysfs_remove_file() =>
-        *
-        *      here e.g. both dev_attr_ro_cdrom and dev_attr_ro are in
-        *      the same namespace and
-        *      from here only attr->name is passed to:
-        *
-        *              sysfs_hash_and_remove()
-        *
-        *              attr->name is the same for dev_attr_ro_cdrom and
-        *              dev_attr_ro
-        *              attr->name is the same for dev_attr_file and
-        *              dev_attr_file_nonremovable
-        *
-        * so we don't differentiate between removing e.g. dev_attr_ro_cdrom
-        * and dev_attr_ro
-        */
-       device_remove_file(&lun->dev, &dev_attr_ro);
-       device_remove_file(&lun->dev, &dev_attr_file);
-}
-
 void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs)
 {
-       if (sysfs) {
-               fsg_common_remove_sysfs(lun);
+       if (sysfs)
                device_unregister(&lun->dev);
-       }
        fsg_lun_close(lun);
        kfree(lun);
 }
@@ -2877,41 +2844,35 @@ int fsg_common_set_cdev(struct fsg_common *common,
 }
 EXPORT_SYMBOL_GPL(fsg_common_set_cdev);
 
-static inline int fsg_common_add_sysfs(struct fsg_common *common,
-                                      struct fsg_lun *lun)
-{
-       int rc;
+static struct attribute *fsg_lun_dev_attrs[] = {
+       &dev_attr_ro.attr,
+       &dev_attr_file.attr,
+       &dev_attr_nofua.attr,
+       NULL
+};
 
-       rc = device_register(&lun->dev);
-       if (rc) {
-               put_device(&lun->dev);
-               return rc;
-       }
+static umode_t fsg_lun_dev_is_visible(struct kobject *kobj,
+                                     struct attribute *attr, int idx)
+{
+       struct device *dev = kobj_to_dev(kobj);
+       struct fsg_lun *lun = fsg_lun_from_dev(dev);
 
-       rc = device_create_file(&lun->dev,
-                               lun->cdrom
-                             ? &dev_attr_ro_cdrom
-                             : &dev_attr_ro);
-       if (rc)
-               goto error;
-       rc = device_create_file(&lun->dev,
-                               lun->removable
-                             ? &dev_attr_file
-                             : &dev_attr_file_nonremovable);
-       if (rc)
-               goto error;
-       rc = device_create_file(&lun->dev, &dev_attr_nofua);
-       if (rc)
-               goto error;
+       if (attr == &dev_attr_ro.attr)
+               return lun->cdrom ? S_IRUGO : (S_IWUSR | S_IRUGO);
+       if (attr == &dev_attr_file.attr)
+               return lun->removable ? (S_IWUSR | S_IRUGO) : S_IRUGO;
+       return attr->mode;
+}
 
-       return 0;
+static const struct attribute_group fsg_lun_dev_group = {
+       .attrs = fsg_lun_dev_attrs,
+       .is_visible = fsg_lun_dev_is_visible,
+};
 
-error:
-       /* removing nonexistent files is a no-op */
-       fsg_common_remove_sysfs(lun);
-       device_unregister(&lun->dev);
-       return rc;
-}
+static const struct attribute_group *fsg_lun_dev_groups[] = {
+       &fsg_lun_dev_group,
+       NULL
+};
 
 int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
                          unsigned int id, const char *name,
@@ -2949,13 +2910,15 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
        } else {
                lun->dev.release = fsg_lun_release;
                lun->dev.parent = &common->gadget->dev;
+               lun->dev.groups = fsg_lun_dev_groups;
                dev_set_drvdata(&lun->dev, &common->filesem);
                dev_set_name(&lun->dev, "%s", name);
                lun->name = dev_name(&lun->dev);
 
-               rc = fsg_common_add_sysfs(common, lun);
+               rc = device_register(&lun->dev);
                if (rc) {
                        pr_info("failed to register LUN%d: %d\n", id, rc);
+                       put_device(&lun->dev);
                        goto error_sysfs;
                }
        }
@@ -2988,10 +2951,8 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
        return 0;
 
 error_lun:
-       if (common->sysfs) {
-               fsg_common_remove_sysfs(lun);
+       if (common->sysfs)
                device_unregister(&lun->dev);
-       }
        fsg_lun_close(lun);
        common->luns[id] = NULL;
 error_sysfs:
@@ -3077,8 +3038,6 @@ static void fsg_common_release(struct kref *ref)
                        struct fsg_lun *lun = *lun_it;
                        if (!lun)
                                continue;
-                       if (common->sysfs)
-                               fsg_common_remove_sysfs(lun);
                        fsg_lun_close(lun);
                        if (common->sysfs)
                                device_unregister(&lun->dev);
diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c
new file mode 100644 (file)
index 0000000..44173df
--- /dev/null
@@ -0,0 +1,1471 @@
+/*
+ * f_printer.c - USB printer function driver
+ *
+ * Copied from drivers/usb/gadget/legacy/printer.c,
+ * which was:
+ *
+ * printer.c -- Printer gadget driver
+ *
+ * Copyright (C) 2003-2005 David Brownell
+ * Copyright (C) 2006 Craig W. Nadler
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/idr.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/moduleparam.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/cdev.h>
+
+#include <asm/byteorder.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/uaccess.h>
+#include <asm/unaligned.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/composite.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/g_printer.h>
+
+#include "u_printer.h"
+
+#define PNP_STRING_LEN         1024
+#define PRINTER_MINORS         4
+#define GET_DEVICE_ID          0
+#define GET_PORT_STATUS                1
+#define SOFT_RESET             2
+
+static int major, minors;
+static struct class *usb_gadget_class;
+static DEFINE_IDA(printer_ida);
+static DEFINE_MUTEX(printer_ida_lock); /* protects access do printer_ida */
+
+/*-------------------------------------------------------------------------*/
+
+struct printer_dev {
+       spinlock_t              lock;           /* lock this structure */
+       /* lock buffer lists during read/write calls */
+       struct mutex            lock_printer_io;
+       struct usb_gadget       *gadget;
+       s8                      interface;
+       struct usb_ep           *in_ep, *out_ep;
+
+       struct list_head        rx_reqs;        /* List of free RX structs */
+       struct list_head        rx_reqs_active; /* List of Active RX xfers */
+       struct list_head        rx_buffers;     /* List of completed xfers */
+       /* wait until there is data to be read. */
+       wait_queue_head_t       rx_wait;
+       struct list_head        tx_reqs;        /* List of free TX structs */
+       struct list_head        tx_reqs_active; /* List of Active TX xfers */
+       /* Wait until there are write buffers available to use. */
+       wait_queue_head_t       tx_wait;
+       /* Wait until all write buffers have been sent. */
+       wait_queue_head_t       tx_flush_wait;
+       struct usb_request      *current_rx_req;
+       size_t                  current_rx_bytes;
+       u8                      *current_rx_buf;
+       u8                      printer_status;
+       u8                      reset_printer;
+       int                     minor;
+       struct cdev             printer_cdev;
+       u8                      printer_cdev_open;
+       wait_queue_head_t       wait;
+       unsigned                q_len;
+       char                    *pnp_string;    /* We don't own memory! */
+       struct usb_function     function;
+};
+
+static inline struct printer_dev *func_to_printer(struct usb_function *f)
+{
+       return container_of(f, struct printer_dev, function);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * DESCRIPTORS ... most are static, but strings and (full) configuration
+ * descriptors are built on demand.
+ */
+
+/* holds our biggest descriptor */
+#define USB_DESC_BUFSIZE               256
+#define USB_BUFSIZE                    8192
+
+static struct usb_interface_descriptor intf_desc = {
+       .bLength =              sizeof(intf_desc),
+       .bDescriptorType =      USB_DT_INTERFACE,
+       .bNumEndpoints =        2,
+       .bInterfaceClass =      USB_CLASS_PRINTER,
+       .bInterfaceSubClass =   1,      /* Printer Sub-Class */
+       .bInterfaceProtocol =   2,      /* Bi-Directional */
+       .iInterface =           0
+};
+
+static struct usb_endpoint_descriptor fs_ep_in_desc = {
+       .bLength =              USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bEndpointAddress =     USB_DIR_IN,
+       .bmAttributes =         USB_ENDPOINT_XFER_BULK
+};
+
+static struct usb_endpoint_descriptor fs_ep_out_desc = {
+       .bLength =              USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bEndpointAddress =     USB_DIR_OUT,
+       .bmAttributes =         USB_ENDPOINT_XFER_BULK
+};
+
+static struct usb_descriptor_header *fs_printer_function[] = {
+       (struct usb_descriptor_header *) &intf_desc,
+       (struct usb_descriptor_header *) &fs_ep_in_desc,
+       (struct usb_descriptor_header *) &fs_ep_out_desc,
+       NULL
+};
+
+/*
+ * usb 2.0 devices need to expose both high speed and full speed
+ * descriptors, unless they only run at full speed.
+ */
+
+static struct usb_endpoint_descriptor hs_ep_in_desc = {
+       .bLength =              USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize =       cpu_to_le16(512)
+};
+
+static struct usb_endpoint_descriptor hs_ep_out_desc = {
+       .bLength =              USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize =       cpu_to_le16(512)
+};
+
+static struct usb_qualifier_descriptor dev_qualifier = {
+       .bLength =              sizeof(dev_qualifier),
+       .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
+       .bcdUSB =               cpu_to_le16(0x0200),
+       .bDeviceClass =         USB_CLASS_PRINTER,
+       .bNumConfigurations =   1
+};
+
+static struct usb_descriptor_header *hs_printer_function[] = {
+       (struct usb_descriptor_header *) &intf_desc,
+       (struct usb_descriptor_header *) &hs_ep_in_desc,
+       (struct usb_descriptor_header *) &hs_ep_out_desc,
+       NULL
+};
+
+/*
+ * Added endpoint descriptors for 3.0 devices
+ */
+
+static struct usb_endpoint_descriptor ss_ep_in_desc = {
+       .bLength =              USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize =       cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor ss_ep_in_comp_desc = {
+       .bLength =              sizeof(ss_ep_in_comp_desc),
+       .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
+};
+
+static struct usb_endpoint_descriptor ss_ep_out_desc = {
+       .bLength =              USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize =       cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor ss_ep_out_comp_desc = {
+       .bLength =              sizeof(ss_ep_out_comp_desc),
+       .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
+};
+
+static struct usb_descriptor_header *ss_printer_function[] = {
+       (struct usb_descriptor_header *) &intf_desc,
+       (struct usb_descriptor_header *) &ss_ep_in_desc,
+       (struct usb_descriptor_header *) &ss_ep_in_comp_desc,
+       (struct usb_descriptor_header *) &ss_ep_out_desc,
+       (struct usb_descriptor_header *) &ss_ep_out_comp_desc,
+       NULL
+};
+
+/* maxpacket and other transfer characteristics vary by speed. */
+static inline struct usb_endpoint_descriptor *ep_desc(struct usb_gadget *gadget,
+                                       struct usb_endpoint_descriptor *fs,
+                                       struct usb_endpoint_descriptor *hs,
+                                       struct usb_endpoint_descriptor *ss)
+{
+       switch (gadget->speed) {
+       case USB_SPEED_SUPER:
+               return ss;
+       case USB_SPEED_HIGH:
+               return hs;
+       default:
+               return fs;
+       }
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_request *
+printer_req_alloc(struct usb_ep *ep, unsigned len, gfp_t gfp_flags)
+{
+       struct usb_request      *req;
+
+       req = usb_ep_alloc_request(ep, gfp_flags);
+
+       if (req != NULL) {
+               req->length = len;
+               req->buf = kmalloc(len, gfp_flags);
+               if (req->buf == NULL) {
+                       usb_ep_free_request(ep, req);
+                       return NULL;
+               }
+       }
+
+       return req;
+}
+
+static void
+printer_req_free(struct usb_ep *ep, struct usb_request *req)
+{
+       if (ep != NULL && req != NULL) {
+               kfree(req->buf);
+               usb_ep_free_request(ep, req);
+       }
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void rx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+       struct printer_dev      *dev = ep->driver_data;
+       int                     status = req->status;
+       unsigned long           flags;
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       list_del_init(&req->list);      /* Remode from Active List */
+
+       switch (status) {
+
+       /* normal completion */
+       case 0:
+               if (req->actual > 0) {
+                       list_add_tail(&req->list, &dev->rx_buffers);
+                       DBG(dev, "G_Printer : rx length %d\n", req->actual);
+               } else {
+                       list_add(&req->list, &dev->rx_reqs);
+               }
+               break;
+
+       /* software-driven interface shutdown */
+       case -ECONNRESET:               /* unlink */
+       case -ESHUTDOWN:                /* disconnect etc */
+               VDBG(dev, "rx shutdown, code %d\n", status);
+               list_add(&req->list, &dev->rx_reqs);
+               break;
+
+       /* for hardware automagic (such as pxa) */
+       case -ECONNABORTED:             /* endpoint reset */
+               DBG(dev, "rx %s reset\n", ep->name);
+               list_add(&req->list, &dev->rx_reqs);
+               break;
+
+       /* data overrun */
+       case -EOVERFLOW:
+               /* FALLTHROUGH */
+
+       default:
+               DBG(dev, "rx status %d\n", status);
+               list_add(&req->list, &dev->rx_reqs);
+               break;
+       }
+
+       wake_up_interruptible(&dev->rx_wait);
+       spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+static void tx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+       struct printer_dev      *dev = ep->driver_data;
+
+       switch (req->status) {
+       default:
+               VDBG(dev, "tx err %d\n", req->status);
+               /* FALLTHROUGH */
+       case -ECONNRESET:               /* unlink */
+       case -ESHUTDOWN:                /* disconnect etc */
+               break;
+       case 0:
+               break;
+       }
+
+       spin_lock(&dev->lock);
+       /* Take the request struct off the active list and put it on the
+        * free list.
+        */
+       list_del_init(&req->list);
+       list_add(&req->list, &dev->tx_reqs);
+       wake_up_interruptible(&dev->tx_wait);
+       if (likely(list_empty(&dev->tx_reqs_active)))
+               wake_up_interruptible(&dev->tx_flush_wait);
+
+       spin_unlock(&dev->lock);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+printer_open(struct inode *inode, struct file *fd)
+{
+       struct printer_dev      *dev;
+       unsigned long           flags;
+       int                     ret = -EBUSY;
+
+       dev = container_of(inode->i_cdev, struct printer_dev, printer_cdev);
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       if (!dev->printer_cdev_open) {
+               dev->printer_cdev_open = 1;
+               fd->private_data = dev;
+               ret = 0;
+               /* Change the printer status to show that it's on-line. */
+               dev->printer_status |= PRINTER_SELECTED;
+       }
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       DBG(dev, "printer_open returned %x\n", ret);
+       return ret;
+}
+
+static int
+printer_close(struct inode *inode, struct file *fd)
+{
+       struct printer_dev      *dev = fd->private_data;
+       unsigned long           flags;
+
+       spin_lock_irqsave(&dev->lock, flags);
+       dev->printer_cdev_open = 0;
+       fd->private_data = NULL;
+       /* Change printer status to show that the printer is off-line. */
+       dev->printer_status &= ~PRINTER_SELECTED;
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       DBG(dev, "printer_close\n");
+
+       return 0;
+}
+
+/* This function must be called with interrupts turned off. */
+static void
+setup_rx_reqs(struct printer_dev *dev)
+{
+       struct usb_request              *req;
+
+       while (likely(!list_empty(&dev->rx_reqs))) {
+               int error;
+
+               req = container_of(dev->rx_reqs.next,
+                               struct usb_request, list);
+               list_del_init(&req->list);
+
+               /* The USB Host sends us whatever amount of data it wants to
+                * so we always set the length field to the full USB_BUFSIZE.
+                * If the amount of data is more than the read() caller asked
+                * for it will be stored in the request buffer until it is
+                * asked for by read().
+                */
+               req->length = USB_BUFSIZE;
+               req->complete = rx_complete;
+
+               /* here, we unlock, and only unlock, to avoid deadlock. */
+               spin_unlock(&dev->lock);
+               error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
+               spin_lock(&dev->lock);
+               if (error) {
+                       DBG(dev, "rx submit --> %d\n", error);
+                       list_add(&req->list, &dev->rx_reqs);
+                       break;
+               }
+               /* if the req is empty, then add it into dev->rx_reqs_active. */
+               else if (list_empty(&req->list))
+                       list_add(&req->list, &dev->rx_reqs_active);
+       }
+}
+
+static ssize_t
+printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+{
+       struct printer_dev              *dev = fd->private_data;
+       unsigned long                   flags;
+       size_t                          size;
+       size_t                          bytes_copied;
+       struct usb_request              *req;
+       /* This is a pointer to the current USB rx request. */
+       struct usb_request              *current_rx_req;
+       /* This is the number of bytes in the current rx buffer. */
+       size_t                          current_rx_bytes;
+       /* This is a pointer to the current rx buffer. */
+       u8                              *current_rx_buf;
+
+       if (len == 0)
+               return -EINVAL;
+
+       DBG(dev, "printer_read trying to read %d bytes\n", (int)len);
+
+       mutex_lock(&dev->lock_printer_io);
+       spin_lock_irqsave(&dev->lock, flags);
+
+       /* We will use this flag later to check if a printer reset happened
+        * after we turn interrupts back on.
+        */
+       dev->reset_printer = 0;
+
+       setup_rx_reqs(dev);
+
+       bytes_copied = 0;
+       current_rx_req = dev->current_rx_req;
+       current_rx_bytes = dev->current_rx_bytes;
+       current_rx_buf = dev->current_rx_buf;
+       dev->current_rx_req = NULL;
+       dev->current_rx_bytes = 0;
+       dev->current_rx_buf = NULL;
+
+       /* Check if there is any data in the read buffers. Please note that
+        * current_rx_bytes is the number of bytes in the current rx buffer.
+        * If it is zero then check if there are any other rx_buffers that
+        * are on the completed list. We are only out of data if all rx
+        * buffers are empty.
+        */
+       if ((current_rx_bytes == 0) &&
+                       (likely(list_empty(&dev->rx_buffers)))) {
+               /* Turn interrupts back on before sleeping. */
+               spin_unlock_irqrestore(&dev->lock, flags);
+
+               /*
+                * If no data is available check if this is a NON-Blocking
+                * call or not.
+                */
+               if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
+                       mutex_unlock(&dev->lock_printer_io);
+                       return -EAGAIN;
+               }
+
+               /* Sleep until data is available */
+               wait_event_interruptible(dev->rx_wait,
+                               (likely(!list_empty(&dev->rx_buffers))));
+               spin_lock_irqsave(&dev->lock, flags);
+       }
+
+       /* We have data to return then copy it to the caller's buffer.*/
+       while ((current_rx_bytes || likely(!list_empty(&dev->rx_buffers)))
+                       && len) {
+               if (current_rx_bytes == 0) {
+                       req = container_of(dev->rx_buffers.next,
+                                       struct usb_request, list);
+                       list_del_init(&req->list);
+
+                       if (req->actual && req->buf) {
+                               current_rx_req = req;
+                               current_rx_bytes = req->actual;
+                               current_rx_buf = req->buf;
+                       } else {
+                               list_add(&req->list, &dev->rx_reqs);
+                               continue;
+                       }
+               }
+
+               /* Don't leave irqs off while doing memory copies */
+               spin_unlock_irqrestore(&dev->lock, flags);
+
+               if (len > current_rx_bytes)
+                       size = current_rx_bytes;
+               else
+                       size = len;
+
+               size -= copy_to_user(buf, current_rx_buf, size);
+               bytes_copied += size;
+               len -= size;
+               buf += size;
+
+               spin_lock_irqsave(&dev->lock, flags);
+
+               /* We've disconnected or reset so return. */
+               if (dev->reset_printer) {
+                       list_add(&current_rx_req->list, &dev->rx_reqs);
+                       spin_unlock_irqrestore(&dev->lock, flags);
+                       mutex_unlock(&dev->lock_printer_io);
+                       return -EAGAIN;
+               }
+
+               /* If we not returning all the data left in this RX request
+                * buffer then adjust the amount of data left in the buffer.
+                * Othewise if we are done with this RX request buffer then
+                * requeue it to get any incoming data from the USB host.
+                */
+               if (size < current_rx_bytes) {
+                       current_rx_bytes -= size;
+                       current_rx_buf += size;
+               } else {
+                       list_add(&current_rx_req->list, &dev->rx_reqs);
+                       current_rx_bytes = 0;
+                       current_rx_buf = NULL;
+                       current_rx_req = NULL;
+               }
+       }
+
+       dev->current_rx_req = current_rx_req;
+       dev->current_rx_bytes = current_rx_bytes;
+       dev->current_rx_buf = current_rx_buf;
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+       mutex_unlock(&dev->lock_printer_io);
+
+       DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied);
+
+       if (bytes_copied)
+               return bytes_copied;
+       else
+               return -EAGAIN;
+}
+
+static ssize_t
+printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+{
+       struct printer_dev      *dev = fd->private_data;
+       unsigned long           flags;
+       size_t                  size;   /* Amount of data in a TX request. */
+       size_t                  bytes_copied = 0;
+       struct usb_request      *req;
+
+       DBG(dev, "printer_write trying to send %d bytes\n", (int)len);
+
+       if (len == 0)
+               return -EINVAL;
+
+       mutex_lock(&dev->lock_printer_io);
+       spin_lock_irqsave(&dev->lock, flags);
+
+       /* Check if a printer reset happens while we have interrupts on */
+       dev->reset_printer = 0;
+
+       /* Check if there is any available write buffers */
+       if (likely(list_empty(&dev->tx_reqs))) {
+               /* Turn interrupts back on before sleeping. */
+               spin_unlock_irqrestore(&dev->lock, flags);
+
+               /*
+                * If write buffers are available check if this is
+                * a NON-Blocking call or not.
+                */
+               if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
+                       mutex_unlock(&dev->lock_printer_io);
+                       return -EAGAIN;
+               }
+
+               /* Sleep until a write buffer is available */
+               wait_event_interruptible(dev->tx_wait,
+                               (likely(!list_empty(&dev->tx_reqs))));
+               spin_lock_irqsave(&dev->lock, flags);
+       }
+
+       while (likely(!list_empty(&dev->tx_reqs)) && len) {
+
+               if (len > USB_BUFSIZE)
+                       size = USB_BUFSIZE;
+               else
+                       size = len;
+
+               req = container_of(dev->tx_reqs.next, struct usb_request,
+                               list);
+               list_del_init(&req->list);
+
+               req->complete = tx_complete;
+               req->length = size;
+
+               /* Check if we need to send a zero length packet. */
+               if (len > size)
+                       /* They will be more TX requests so no yet. */
+                       req->zero = 0;
+               else
+                       /* If the data amount is not a multiple of the
+                        * maxpacket size then send a zero length packet.
+                        */
+                       req->zero = ((len % dev->in_ep->maxpacket) == 0);
+
+               /* Don't leave irqs off while doing memory copies */
+               spin_unlock_irqrestore(&dev->lock, flags);
+
+               if (copy_from_user(req->buf, buf, size)) {
+                       list_add(&req->list, &dev->tx_reqs);
+                       mutex_unlock(&dev->lock_printer_io);
+                       return bytes_copied;
+               }
+
+               bytes_copied += size;
+               len -= size;
+               buf += size;
+
+               spin_lock_irqsave(&dev->lock, flags);
+
+               /* We've disconnected or reset so free the req and buffer */
+               if (dev->reset_printer) {
+                       list_add(&req->list, &dev->tx_reqs);
+                       spin_unlock_irqrestore(&dev->lock, flags);
+                       mutex_unlock(&dev->lock_printer_io);
+                       return -EAGAIN;
+               }
+
+               if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
+                       list_add(&req->list, &dev->tx_reqs);
+                       spin_unlock_irqrestore(&dev->lock, flags);
+                       mutex_unlock(&dev->lock_printer_io);
+                       return -EAGAIN;
+               }
+
+               list_add(&req->list, &dev->tx_reqs_active);
+
+       }
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+       mutex_unlock(&dev->lock_printer_io);
+
+       DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);
+
+       if (bytes_copied)
+               return bytes_copied;
+       else
+               return -EAGAIN;
+}
+
+static int
+printer_fsync(struct file *fd, loff_t start, loff_t end, int datasync)
+{
+       struct printer_dev      *dev = fd->private_data;
+       struct inode *inode = file_inode(fd);
+       unsigned long           flags;
+       int                     tx_list_empty;
+
+       mutex_lock(&inode->i_mutex);
+       spin_lock_irqsave(&dev->lock, flags);
+       tx_list_empty = (likely(list_empty(&dev->tx_reqs)));
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       if (!tx_list_empty) {
+               /* Sleep until all data has been sent */
+               wait_event_interruptible(dev->tx_flush_wait,
+                               (likely(list_empty(&dev->tx_reqs_active))));
+       }
+       mutex_unlock(&inode->i_mutex);
+
+       return 0;
+}
+
+static unsigned int
+printer_poll(struct file *fd, poll_table *wait)
+{
+       struct printer_dev      *dev = fd->private_data;
+       unsigned long           flags;
+       int                     status = 0;
+
+       mutex_lock(&dev->lock_printer_io);
+       spin_lock_irqsave(&dev->lock, flags);
+       setup_rx_reqs(dev);
+       spin_unlock_irqrestore(&dev->lock, flags);
+       mutex_unlock(&dev->lock_printer_io);
+
+       poll_wait(fd, &dev->rx_wait, wait);
+       poll_wait(fd, &dev->tx_wait, wait);
+
+       spin_lock_irqsave(&dev->lock, flags);
+       if (likely(!list_empty(&dev->tx_reqs)))
+               status |= POLLOUT | POLLWRNORM;
+
+       if (likely(dev->current_rx_bytes) ||
+                       likely(!list_empty(&dev->rx_buffers)))
+               status |= POLLIN | POLLRDNORM;
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return status;
+}
+
+static long
+printer_ioctl(struct file *fd, unsigned int code, unsigned long arg)
+{
+       struct printer_dev      *dev = fd->private_data;
+       unsigned long           flags;
+       int                     status = 0;
+
+       DBG(dev, "printer_ioctl: cmd=0x%4.4x, arg=%lu\n", code, arg);
+
+       /* handle ioctls */
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       switch (code) {
+       case GADGET_GET_PRINTER_STATUS:
+               status = (int)dev->printer_status;
+               break;
+       case GADGET_SET_PRINTER_STATUS:
+               dev->printer_status = (u8)arg;
+               break;
+       default:
+               /* could not handle ioctl */
+               DBG(dev, "printer_ioctl: ERROR cmd=0x%4.4xis not supported\n",
+                               code);
+               status = -ENOTTY;
+       }
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return status;
+}
+
+/* used after endpoint configuration */
+static const struct file_operations printer_io_operations = {
+       .owner =        THIS_MODULE,
+       .open =         printer_open,
+       .read =         printer_read,
+       .write =        printer_write,
+       .fsync =        printer_fsync,
+       .poll =         printer_poll,
+       .unlocked_ioctl = printer_ioctl,
+       .release =      printer_close,
+       .llseek =       noop_llseek,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int
+set_printer_interface(struct printer_dev *dev)
+{
+       int                     result = 0;
+
+       dev->in_ep->desc = ep_desc(dev->gadget, &fs_ep_in_desc, &hs_ep_in_desc,
+                               &ss_ep_in_desc);
+       dev->in_ep->driver_data = dev;
+
+       dev->out_ep->desc = ep_desc(dev->gadget, &fs_ep_out_desc,
+                                   &hs_ep_out_desc, &ss_ep_out_desc);
+       dev->out_ep->driver_data = dev;
+
+       result = usb_ep_enable(dev->in_ep);
+       if (result != 0) {
+               DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result);
+               goto done;
+       }
+
+       result = usb_ep_enable(dev->out_ep);
+       if (result != 0) {
+               DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result);
+               goto done;
+       }
+
+done:
+       /* on error, disable any endpoints  */
+       if (result != 0) {
+               (void) usb_ep_disable(dev->in_ep);
+               (void) usb_ep_disable(dev->out_ep);
+               dev->in_ep->desc = NULL;
+               dev->out_ep->desc = NULL;
+       }
+
+       /* caller is responsible for cleanup on error */
+       return result;
+}
+
+static void printer_reset_interface(struct printer_dev *dev)
+{
+       if (dev->interface < 0)
+               return;
+
+       DBG(dev, "%s\n", __func__);
+
+       if (dev->in_ep->desc)
+               usb_ep_disable(dev->in_ep);
+
+       if (dev->out_ep->desc)
+               usb_ep_disable(dev->out_ep);
+
+       dev->in_ep->desc = NULL;
+       dev->out_ep->desc = NULL;
+       dev->interface = -1;
+}
+
+/* Change our operational Interface. */
+static int set_interface(struct printer_dev *dev, unsigned number)
+{
+       int                     result = 0;
+
+       /* Free the current interface */
+       printer_reset_interface(dev);
+
+       result = set_printer_interface(dev);
+       if (result)
+               printer_reset_interface(dev);
+       else
+               dev->interface = number;
+
+       if (!result)
+               INFO(dev, "Using interface %x\n", number);
+
+       return result;
+}
+
+static void printer_soft_reset(struct printer_dev *dev)
+{
+       struct usb_request      *req;
+
+       INFO(dev, "Received Printer Reset Request\n");
+
+       if (usb_ep_disable(dev->in_ep))
+               DBG(dev, "Failed to disable USB in_ep\n");
+       if (usb_ep_disable(dev->out_ep))
+               DBG(dev, "Failed to disable USB out_ep\n");
+
+       if (dev->current_rx_req != NULL) {
+               list_add(&dev->current_rx_req->list, &dev->rx_reqs);
+               dev->current_rx_req = NULL;
+       }
+       dev->current_rx_bytes = 0;
+       dev->current_rx_buf = NULL;
+       dev->reset_printer = 1;
+
+       while (likely(!(list_empty(&dev->rx_buffers)))) {
+               req = container_of(dev->rx_buffers.next, struct usb_request,
+                               list);
+               list_del_init(&req->list);
+               list_add(&req->list, &dev->rx_reqs);
+       }
+
+       while (likely(!(list_empty(&dev->rx_reqs_active)))) {
+               req = container_of(dev->rx_buffers.next, struct usb_request,
+                               list);
+               list_del_init(&req->list);
+               list_add(&req->list, &dev->rx_reqs);
+       }
+
+       while (likely(!(list_empty(&dev->tx_reqs_active)))) {
+               req = container_of(dev->tx_reqs_active.next,
+                               struct usb_request, list);
+               list_del_init(&req->list);
+               list_add(&req->list, &dev->tx_reqs);
+       }
+
+       if (usb_ep_enable(dev->in_ep))
+               DBG(dev, "Failed to enable USB in_ep\n");
+       if (usb_ep_enable(dev->out_ep))
+               DBG(dev, "Failed to enable USB out_ep\n");
+
+       wake_up_interruptible(&dev->rx_wait);
+       wake_up_interruptible(&dev->tx_wait);
+       wake_up_interruptible(&dev->tx_flush_wait);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static bool gprinter_req_match(struct usb_function *f,
+                              const struct usb_ctrlrequest *ctrl)
+{
+       struct printer_dev      *dev = func_to_printer(f);
+       u16                     w_index = le16_to_cpu(ctrl->wIndex);
+       u16                     w_value = le16_to_cpu(ctrl->wValue);
+       u16                     w_length = le16_to_cpu(ctrl->wLength);
+
+       if ((ctrl->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE ||
+           (ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS)
+               return false;
+
+       switch (ctrl->bRequest) {
+       case GET_DEVICE_ID:
+               w_index >>= 8;
+               if (w_length <= PNP_STRING_LEN &&
+                   (USB_DIR_IN & ctrl->bRequestType))
+                       break;
+               return false;
+       case GET_PORT_STATUS:
+               if (!w_value && w_length == 1 &&
+                   (USB_DIR_IN & ctrl->bRequestType))
+                       break;
+               return false;
+       case SOFT_RESET:
+               if (!w_value && !w_length &&
+                  !(USB_DIR_IN & ctrl->bRequestType))
+                       break;
+               /* fall through */
+       default:
+               return false;
+       }
+       return w_index == dev->interface;
+}
+
+/*
+ * The setup() callback implements all the ep0 functionality that's not
+ * handled lower down.
+ */
+static int printer_func_setup(struct usb_function *f,
+               const struct usb_ctrlrequest *ctrl)
+{
+       struct printer_dev *dev = func_to_printer(f);
+       struct usb_composite_dev *cdev = f->config->cdev;
+       struct usb_request      *req = cdev->req;
+       int                     value = -EOPNOTSUPP;
+       u16                     wIndex = le16_to_cpu(ctrl->wIndex);
+       u16                     wValue = le16_to_cpu(ctrl->wValue);
+       u16                     wLength = le16_to_cpu(ctrl->wLength);
+
+       DBG(dev, "ctrl req%02x.%02x v%04x i%04x l%d\n",
+               ctrl->bRequestType, ctrl->bRequest, wValue, wIndex, wLength);
+
+       switch (ctrl->bRequestType&USB_TYPE_MASK) {
+       case USB_TYPE_CLASS:
+               switch (ctrl->bRequest) {
+               case GET_DEVICE_ID: /* Get the IEEE-1284 PNP String */
+                       /* Only one printer interface is supported. */
+                       if ((wIndex>>8) != dev->interface)
+                               break;
+
+                       value = (dev->pnp_string[0] << 8) | dev->pnp_string[1];
+                       memcpy(req->buf, dev->pnp_string, value);
+                       DBG(dev, "1284 PNP String: %x %s\n", value,
+                                       &dev->pnp_string[2]);
+                       break;
+
+               case GET_PORT_STATUS: /* Get Port Status */
+                       /* Only one printer interface is supported. */
+                       if (wIndex != dev->interface)
+                               break;
+
+                       *(u8 *)req->buf = dev->printer_status;
+                       value = min_t(u16, wLength, 1);
+                       break;
+
+               case SOFT_RESET: /* Soft Reset */
+                       /* Only one printer interface is supported. */
+                       if (wIndex != dev->interface)
+                               break;
+
+                       printer_soft_reset(dev);
+
+                       value = 0;
+                       break;
+
+               default:
+                       goto unknown;
+               }
+               break;
+
+       default:
+unknown:
+               VDBG(dev,
+                       "unknown ctrl req%02x.%02x v%04x i%04x l%d\n",
+                       ctrl->bRequestType, ctrl->bRequest,
+                       wValue, wIndex, wLength);
+               break;
+       }
+       /* host either stalls (value < 0) or reports success */
+       if (value >= 0) {
+               req->length = value;
+               req->zero = value < wLength;
+               value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+               if (value < 0) {
+                       ERROR(dev, "%s:%d Error!\n", __func__, __LINE__);
+                       req->status = 0;
+               }
+       }
+       return value;
+}
+
+static int printer_func_bind(struct usb_configuration *c,
+               struct usb_function *f)
+{
+       struct usb_gadget *gadget = c->cdev->gadget;
+       struct printer_dev *dev = func_to_printer(f);
+       struct device *pdev;
+       struct usb_composite_dev *cdev = c->cdev;
+       struct usb_ep *in_ep;
+       struct usb_ep *out_ep = NULL;
+       struct usb_request *req;
+       dev_t devt;
+       int id;
+       int ret;
+       u32 i;
+
+       id = usb_interface_id(c, f);
+       if (id < 0)
+               return id;
+       intf_desc.bInterfaceNumber = id;
+
+       /* finish hookup to lower layer ... */
+       dev->gadget = gadget;
+
+       /* all we really need is bulk IN/OUT */
+       in_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_in_desc);
+       if (!in_ep) {
+autoconf_fail:
+               dev_err(&cdev->gadget->dev, "can't autoconfigure on %s\n",
+                       cdev->gadget->name);
+               return -ENODEV;
+       }
+       in_ep->driver_data = in_ep;     /* claim */
+
+       out_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_out_desc);
+       if (!out_ep)
+               goto autoconf_fail;
+       out_ep->driver_data = out_ep;   /* claim */
+
+       /* assumes that all endpoints are dual-speed */
+       hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
+       hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
+       ss_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
+       ss_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
+
+       ret = usb_assign_descriptors(f, fs_printer_function,
+                       hs_printer_function, ss_printer_function);
+       if (ret)
+               return ret;
+
+       dev->in_ep = in_ep;
+       dev->out_ep = out_ep;
+
+       ret = -ENOMEM;
+       for (i = 0; i < dev->q_len; i++) {
+               req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL);
+               if (!req)
+                       goto fail_tx_reqs;
+               list_add(&req->list, &dev->tx_reqs);
+       }
+
+       for (i = 0; i < dev->q_len; i++) {
+               req = printer_req_alloc(dev->out_ep, USB_BUFSIZE, GFP_KERNEL);
+               if (!req)
+                       goto fail_rx_reqs;
+               list_add(&req->list, &dev->rx_reqs);
+       }
+
+       /* Setup the sysfs files for the printer gadget. */
+       devt = MKDEV(major, dev->minor);
+       pdev = device_create(usb_gadget_class, NULL, devt,
+                                 NULL, "g_printer%d", dev->minor);
+       if (IS_ERR(pdev)) {
+               ERROR(dev, "Failed to create device: g_printer\n");
+               ret = PTR_ERR(pdev);
+               goto fail_rx_reqs;
+       }
+
+       /*
+        * Register a character device as an interface to a user mode
+        * program that handles the printer specific functionality.
+        */
+       cdev_init(&dev->printer_cdev, &printer_io_operations);
+       dev->printer_cdev.owner = THIS_MODULE;
+       ret = cdev_add(&dev->printer_cdev, devt, 1);
+       if (ret) {
+               ERROR(dev, "Failed to open char device\n");
+               goto fail_cdev_add;
+       }
+
+       return 0;
+
+fail_cdev_add:
+       device_destroy(usb_gadget_class, devt);
+
+fail_rx_reqs:
+       while (!list_empty(&dev->rx_reqs)) {
+               req = container_of(dev->rx_reqs.next, struct usb_request, list);
+               list_del(&req->list);
+               printer_req_free(dev->out_ep, req);
+       }
+
+fail_tx_reqs:
+       while (!list_empty(&dev->tx_reqs)) {
+               req = container_of(dev->tx_reqs.next, struct usb_request, list);
+               list_del(&req->list);
+               printer_req_free(dev->in_ep, req);
+       }
+
+       return ret;
+
+}
+
+static int printer_func_set_alt(struct usb_function *f,
+               unsigned intf, unsigned alt)
+{
+       struct printer_dev *dev = func_to_printer(f);
+       int ret = -ENOTSUPP;
+
+       if (!alt)
+               ret = set_interface(dev, intf);
+
+       return ret;
+}
+
+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
+*to_f_printer_opts(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct f_printer_opts,
+                           func_inst.group);
+}
+
+CONFIGFS_ATTR_STRUCT(f_printer_opts);
+CONFIGFS_ATTR_OPS(f_printer_opts);
+
+static void printer_attr_release(struct config_item *item)
+{
+       struct f_printer_opts *opts = to_f_printer_opts(item);
+
+       usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations printer_item_ops = {
+       .release        = printer_attr_release,
+       .show_attribute = f_printer_opts_attr_show,
+       .store_attribute = f_printer_opts_attr_store,
+};
+
+static ssize_t f_printer_opts_pnp_string_show(struct f_printer_opts *opts,
+                                             char *page)
+{
+       int result;
+
+       mutex_lock(&opts->lock);
+       result = strlcpy(page, opts->pnp_string + 2, PNP_STRING_LEN - 2);
+       mutex_unlock(&opts->lock);
+
+       return result;
+}
+
+static ssize_t f_printer_opts_pnp_string_store(struct f_printer_opts *opts,
+                                              const char *page, size_t len)
+{
+       int result, l;
+
+       mutex_lock(&opts->lock);
+       result = strlcpy(opts->pnp_string + 2, page, PNP_STRING_LEN - 2);
+       l = strlen(opts->pnp_string + 2) + 2;
+       opts->pnp_string[0] = (l >> 8) & 0xFF;
+       opts->pnp_string[1] = l & 0xFF;
+       mutex_unlock(&opts->lock);
+
+       return result;
+}
+
+static struct f_printer_opts_attribute f_printer_opts_pnp_string =
+       __CONFIGFS_ATTR(pnp_string, S_IRUGO | S_IWUSR,
+                       f_printer_opts_pnp_string_show,
+                       f_printer_opts_pnp_string_store);
+
+static ssize_t f_printer_opts_q_len_show(struct f_printer_opts *opts,
+                                        char *page)
+{
+       int result;
+
+       mutex_lock(&opts->lock);
+       result = sprintf(page, "%d\n", opts->q_len);
+       mutex_unlock(&opts->lock);
+
+       return result;
+}
+
+static ssize_t f_printer_opts_q_len_store(struct f_printer_opts *opts,
+                                         const char *page, size_t len)
+{
+       int ret;
+       u16 num;
+
+       mutex_lock(&opts->lock);
+       if (opts->refcnt) {
+               ret = -EBUSY;
+               goto end;
+       }
+
+       ret = kstrtou16(page, 0, &num);
+       if (ret)
+               goto end;
+
+       opts->q_len = (unsigned)num;
+       ret = len;
+end:
+       mutex_unlock(&opts->lock);
+       return ret;
+}
+
+static struct f_printer_opts_attribute f_printer_opts_q_len =
+       __CONFIGFS_ATTR(q_len, S_IRUGO | S_IWUSR, f_printer_opts_q_len_show,
+                       f_printer_opts_q_len_store);
+
+static struct configfs_attribute *printer_attrs[] = {
+       &f_printer_opts_pnp_string.attr,
+       &f_printer_opts_q_len.attr,
+       NULL,
+};
+
+static struct config_item_type printer_func_type = {
+       .ct_item_ops    = &printer_item_ops,
+       .ct_attrs       = printer_attrs,
+       .ct_owner       = THIS_MODULE,
+};
+
+static inline int gprinter_get_minor(void)
+{
+       return ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL);
+}
+
+static inline void gprinter_put_minor(int minor)
+{
+       ida_simple_remove(&printer_ida, minor);
+}
+
+static int gprinter_setup(int);
+static void gprinter_cleanup(void);
+
+static void gprinter_free_inst(struct usb_function_instance *f)
+{
+       struct f_printer_opts *opts;
+
+       opts = container_of(f, struct f_printer_opts, func_inst);
+
+       mutex_lock(&printer_ida_lock);
+
+       gprinter_put_minor(opts->minor);
+       if (idr_is_empty(&printer_ida.idr))
+               gprinter_cleanup();
+
+       mutex_unlock(&printer_ida_lock);
+
+       kfree(opts);
+}
+
+static struct usb_function_instance *gprinter_alloc_inst(void)
+{
+       struct f_printer_opts *opts;
+       struct usb_function_instance *ret;
+       int status = 0;
+
+       opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+       if (!opts)
+               return ERR_PTR(-ENOMEM);
+
+       mutex_init(&opts->lock);
+       opts->func_inst.free_func_inst = gprinter_free_inst;
+       ret = &opts->func_inst;
+
+       mutex_lock(&printer_ida_lock);
+
+       if (idr_is_empty(&printer_ida.idr)) {
+               status = gprinter_setup(PRINTER_MINORS);
+               if (status) {
+                       ret = ERR_PTR(status);
+                       kfree(opts);
+                       goto unlock;
+               }
+       }
+
+       opts->minor = gprinter_get_minor();
+       if (opts->minor < 0) {
+               ret = ERR_PTR(opts->minor);
+               kfree(opts);
+               if (idr_is_empty(&printer_ida.idr))
+                       gprinter_cleanup();
+               goto unlock;
+       }
+       config_group_init_type_name(&opts->func_inst.group, "",
+                                   &printer_func_type);
+
+unlock:
+       mutex_unlock(&printer_ida_lock);
+       return ret;
+}
+
+static void gprinter_free(struct usb_function *f)
+{
+       struct printer_dev *dev = func_to_printer(f);
+       struct f_printer_opts *opts;
+
+       opts = container_of(f->fi, struct f_printer_opts, func_inst);
+       kfree(dev);
+       mutex_lock(&opts->lock);
+       --opts->refcnt;
+       mutex_unlock(&opts->lock);
+}
+
+static void printer_func_unbind(struct usb_configuration *c,
+               struct usb_function *f)
+{
+       struct printer_dev      *dev;
+       struct usb_request      *req;
+
+       dev = func_to_printer(f);
+
+       device_destroy(usb_gadget_class, MKDEV(major, dev->minor));
+
+       /* Remove Character Device */
+       cdev_del(&dev->printer_cdev);
+
+       /* we must already have been disconnected ... no i/o may be active */
+       WARN_ON(!list_empty(&dev->tx_reqs_active));
+       WARN_ON(!list_empty(&dev->rx_reqs_active));
+
+       /* Free all memory for this driver. */
+       while (!list_empty(&dev->tx_reqs)) {
+               req = container_of(dev->tx_reqs.next, struct usb_request,
+                               list);
+               list_del(&req->list);
+               printer_req_free(dev->in_ep, req);
+       }
+
+       if (dev->current_rx_req != NULL)
+               printer_req_free(dev->out_ep, dev->current_rx_req);
+
+       while (!list_empty(&dev->rx_reqs)) {
+               req = container_of(dev->rx_reqs.next,
+                               struct usb_request, list);
+               list_del(&req->list);
+               printer_req_free(dev->out_ep, req);
+       }
+
+       while (!list_empty(&dev->rx_buffers)) {
+               req = container_of(dev->rx_buffers.next,
+                               struct usb_request, list);
+               list_del(&req->list);
+               printer_req_free(dev->out_ep, req);
+       }
+       usb_free_all_descriptors(f);
+}
+
+static struct usb_function *gprinter_alloc(struct usb_function_instance *fi)
+{
+       struct printer_dev      *dev;
+       struct f_printer_opts   *opts;
+
+       opts = container_of(fi, struct f_printer_opts, func_inst);
+
+       mutex_lock(&opts->lock);
+       if (opts->minor >= minors) {
+               mutex_unlock(&opts->lock);
+               return ERR_PTR(-ENOENT);
+       }
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev) {
+               mutex_unlock(&opts->lock);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       ++opts->refcnt;
+       dev->minor = opts->minor;
+       dev->pnp_string = opts->pnp_string;
+       dev->q_len = opts->q_len;
+       mutex_unlock(&opts->lock);
+
+       dev->function.name = "printer";
+       dev->function.bind = printer_func_bind;
+       dev->function.setup = printer_func_setup;
+       dev->function.unbind = printer_func_unbind;
+       dev->function.set_alt = printer_func_set_alt;
+       dev->function.disable = printer_func_disable;
+       dev->function.req_match = gprinter_req_match;
+       dev->function.free_func = gprinter_free;
+
+       INIT_LIST_HEAD(&dev->tx_reqs);
+       INIT_LIST_HEAD(&dev->rx_reqs);
+       INIT_LIST_HEAD(&dev->rx_buffers);
+       INIT_LIST_HEAD(&dev->tx_reqs_active);
+       INIT_LIST_HEAD(&dev->rx_reqs_active);
+
+       spin_lock_init(&dev->lock);
+       mutex_init(&dev->lock_printer_io);
+       init_waitqueue_head(&dev->rx_wait);
+       init_waitqueue_head(&dev->tx_wait);
+       init_waitqueue_head(&dev->tx_flush_wait);
+
+       dev->interface = -1;
+       dev->printer_cdev_open = 0;
+       dev->printer_status = PRINTER_NOT_ERROR;
+       dev->current_rx_req = NULL;
+       dev->current_rx_bytes = 0;
+       dev->current_rx_buf = NULL;
+
+       return &dev->function;
+}
+
+DECLARE_USB_FUNCTION_INIT(printer, gprinter_alloc_inst, gprinter_alloc);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Craig Nadler");
+
+static int gprinter_setup(int count)
+{
+       int status;
+       dev_t devt;
+
+       usb_gadget_class = class_create(THIS_MODULE, "usb_printer_gadget");
+       if (IS_ERR(usb_gadget_class)) {
+               status = PTR_ERR(usb_gadget_class);
+               usb_gadget_class = NULL;
+               pr_err("unable to create usb_gadget class %d\n", status);
+               return status;
+       }
+
+       status = alloc_chrdev_region(&devt, 0, count, "USB printer gadget");
+       if (status) {
+               pr_err("alloc_chrdev_region %d\n", status);
+               class_destroy(usb_gadget_class);
+               usb_gadget_class = NULL;
+               return status;
+       }
+
+       major = MAJOR(devt);
+       minors = count;
+
+       return status;
+}
+
+static void gprinter_cleanup(void)
+{
+       if (major) {
+               unregister_chrdev_region(MKDEV(major, 0), minors);
+               major = minors = 0;
+       }
+       class_destroy(usb_gadget_class);
+       usb_gadget_class = NULL;
+}
diff --git a/drivers/usb/gadget/function/u_printer.h b/drivers/usb/gadget/function/u_printer.h
new file mode 100644 (file)
index 0000000..0e2c49d
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * u_printer.h
+ *
+ * Utility definitions for the printer function
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef U_PRINTER_H
+#define U_PRINTER_H
+
+#include <linux/usb/composite.h>
+
+#define PNP_STRING_LEN                 1024
+
+struct f_printer_opts {
+       struct usb_function_instance    func_inst;
+       int                             minor;
+       char                            pnp_string[PNP_STRING_LEN];
+       unsigned                        q_len;
+
+       /*
+        * Protect the data from concurrent access by read/write
+        * and create symlink/remove symlink
+        */
+       struct mutex                    lock;
+       int                             refcnt;
+};
+
+#endif /* U_PRINTER_H */
index 491082aaf1039fa7cdef927a371a5b3514974e16..89179ab20c109277a3d49c48b7d91d85eb821f4c 100644 (file)
@@ -912,7 +912,7 @@ static int gs_put_char(struct tty_struct *tty, unsigned char ch)
        unsigned long   flags;
        int             status;
 
-       pr_vdebug("gs_put_char: (%d,%p) char=0x%x, called from %pf\n",
+       pr_vdebug("gs_put_char: (%d,%p) char=0x%x, called from %ps\n",
                port->port_num, tty, ch, __builtin_return_address(0));
 
        spin_lock_irqsave(&port->port_lock, flags);
index 113c87e22117d432708001bec07957678267ea46..d5a7102de696611ea45124796610a20f9fb033cd 100644 (file)
@@ -301,6 +301,7 @@ config USB_MIDI_GADGET
 config USB_G_PRINTER
        tristate "Printer Gadget"
        select USB_LIBCOMPOSITE
+       select USB_F_PRINTER
        help
          The Printer Gadget channels data between the USB host and a
          userspace program driving the print engine. The user space
index 200f9a584064fd9199ba99ff75a2e26a33c788f7..662ef2c1c62b67d0340cbf8593d515f14f2568dc 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/poll.h>
 #include <linux/mmu_context.h>
 #include <linux/aio.h>
+#include <linux/uio.h>
 
 #include <linux/device.h>
 #include <linux/moduleparam.h>
@@ -469,7 +470,7 @@ static void ep_user_copy_worker(struct work_struct *work)
                ret = -EFAULT;
 
        /* completing the iocb can drop the ctx and mm, don't touch mm after */
-       aio_complete(iocb, ret, ret);
+       iocb->ki_complete(iocb, ret, ret);
 
        kfree(priv->buf);
        kfree(priv->to_free);
@@ -497,7 +498,8 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
                kfree(priv);
                iocb->private = NULL;
                /* aio_complete() reports bytes-transferred _and_ faults */
-               aio_complete(iocb, req->actual ? req->actual : req->status,
+
+               iocb->ki_complete(iocb, req->actual ? req->actual : req->status,
                                req->status);
        } else {
                /* ep_copy_to_user() won't report both; we hide some faults */
index 90545980542f2c7c14e5f669444d012de5e73e26..d5b6ee725a2ac04030ac52fc4b4e9c93477a90b6 100644 (file)
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/moduleparam.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/types.h>
-#include <linux/ctype.h>
-#include <linux/cdev.h>
-
 #include <asm/byteorder.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/uaccess.h>
-#include <asm/unaligned.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/composite.h>
 USB_GADGET_COMPOSITE_OPTIONS();
 
 #define DRIVER_DESC            "Printer Gadget"
-#define DRIVER_VERSION         "2007 OCT 06"
+#define DRIVER_VERSION         "2015 FEB 17"
 
-static DEFINE_MUTEX(printer_mutex);
 static const char shortname [] = "printer";
 static const char driver_desc [] = DRIVER_DESC;
 
-static dev_t g_printer_devno;
-
-static struct class *usb_gadget_class;
-
-/*-------------------------------------------------------------------------*/
-
-struct printer_dev {
-       spinlock_t              lock;           /* lock this structure */
-       /* lock buffer lists during read/write calls */
-       struct mutex            lock_printer_io;
-       struct usb_gadget       *gadget;
-       s8                      interface;
-       struct usb_ep           *in_ep, *out_ep;
-
-       struct list_head        rx_reqs;        /* List of free RX structs */
-       struct list_head        rx_reqs_active; /* List of Active RX xfers */
-       struct list_head        rx_buffers;     /* List of completed xfers */
-       /* wait until there is data to be read. */
-       wait_queue_head_t       rx_wait;
-       struct list_head        tx_reqs;        /* List of free TX structs */
-       struct list_head        tx_reqs_active; /* List of Active TX xfers */
-       /* Wait until there are write buffers available to use. */
-       wait_queue_head_t       tx_wait;
-       /* Wait until all write buffers have been sent. */
-       wait_queue_head_t       tx_flush_wait;
-       struct usb_request      *current_rx_req;
-       size_t                  current_rx_bytes;
-       u8                      *current_rx_buf;
-       u8                      printer_status;
-       u8                      reset_printer;
-       struct cdev             printer_cdev;
-       struct device           *pdev;
-       u8                      printer_cdev_open;
-       wait_queue_head_t       wait;
-       struct usb_function     function;
-};
-
-static struct printer_dev usb_printer_gadget;
+#include "u_printer.h"
 
 /*-------------------------------------------------------------------------*/
 
@@ -120,6 +60,9 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR);
 
 #define QLEN   qlen
 
+static struct usb_function_instance *fi_printer;
+static struct usb_function *f_printer;
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -127,10 +70,6 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR);
  * descriptors are built on demand.
  */
 
-/* holds our biggest descriptor */
-#define USB_DESC_BUFSIZE               256
-#define USB_BUFSIZE                    8192
-
 static struct usb_device_descriptor device_desc = {
        .bLength =              sizeof device_desc,
        .bDescriptorType =      USB_DT_DEVICE,
@@ -143,108 +82,6 @@ static struct usb_device_descriptor device_desc = {
        .bNumConfigurations =   1
 };
 
-static struct usb_interface_descriptor intf_desc = {
-       .bLength =              sizeof intf_desc,
-       .bDescriptorType =      USB_DT_INTERFACE,
-       .bNumEndpoints =        2,
-       .bInterfaceClass =      USB_CLASS_PRINTER,
-       .bInterfaceSubClass =   1,      /* Printer Sub-Class */
-       .bInterfaceProtocol =   2,      /* Bi-Directional */
-       .iInterface =           0
-};
-
-static struct usb_endpoint_descriptor fs_ep_in_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-       .bEndpointAddress =     USB_DIR_IN,
-       .bmAttributes =         USB_ENDPOINT_XFER_BULK
-};
-
-static struct usb_endpoint_descriptor fs_ep_out_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-       .bEndpointAddress =     USB_DIR_OUT,
-       .bmAttributes =         USB_ENDPOINT_XFER_BULK
-};
-
-static struct usb_descriptor_header *fs_printer_function[] = {
-       (struct usb_descriptor_header *) &intf_desc,
-       (struct usb_descriptor_header *) &fs_ep_in_desc,
-       (struct usb_descriptor_header *) &fs_ep_out_desc,
-       NULL
-};
-
-/*
- * usb 2.0 devices need to expose both high speed and full speed
- * descriptors, unless they only run at full speed.
- */
-
-static struct usb_endpoint_descriptor hs_ep_in_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
-       .wMaxPacketSize =       cpu_to_le16(512)
-};
-
-static struct usb_endpoint_descriptor hs_ep_out_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
-       .wMaxPacketSize =       cpu_to_le16(512)
-};
-
-static struct usb_qualifier_descriptor dev_qualifier = {
-       .bLength =              sizeof dev_qualifier,
-       .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
-       .bcdUSB =               cpu_to_le16(0x0200),
-       .bDeviceClass =         USB_CLASS_PRINTER,
-       .bNumConfigurations =   1
-};
-
-static struct usb_descriptor_header *hs_printer_function[] = {
-       (struct usb_descriptor_header *) &intf_desc,
-       (struct usb_descriptor_header *) &hs_ep_in_desc,
-       (struct usb_descriptor_header *) &hs_ep_out_desc,
-       NULL
-};
-
-/*
- * Added endpoint descriptors for 3.0 devices
- */
-
-static struct usb_endpoint_descriptor ss_ep_in_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
-       .wMaxPacketSize =       cpu_to_le16(1024),
-};
-
-static struct usb_ss_ep_comp_descriptor ss_ep_in_comp_desc = {
-       .bLength =              sizeof(ss_ep_in_comp_desc),
-       .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
-};
-
-static struct usb_endpoint_descriptor ss_ep_out_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
-       .wMaxPacketSize =       cpu_to_le16(1024),
-};
-
-static struct usb_ss_ep_comp_descriptor ss_ep_out_comp_desc = {
-       .bLength =              sizeof(ss_ep_out_comp_desc),
-       .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
-};
-
-static struct usb_descriptor_header *ss_printer_function[] = {
-       (struct usb_descriptor_header *) &intf_desc,
-       (struct usb_descriptor_header *) &ss_ep_in_desc,
-       (struct usb_descriptor_header *) &ss_ep_in_comp_desc,
-       (struct usb_descriptor_header *) &ss_ep_out_desc,
-       (struct usb_descriptor_header *) &ss_ep_out_comp_desc,
-       NULL
-};
-
 static struct usb_otg_descriptor otg_descriptor = {
        .bLength =              sizeof otg_descriptor,
        .bDescriptorType =      USB_DT_OTG,
@@ -256,29 +93,13 @@ static const struct usb_descriptor_header *otg_desc[] = {
        NULL,
 };
 
-/* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *ep_desc(struct usb_gadget *gadget,
-                                       struct usb_endpoint_descriptor *fs,
-                                       struct usb_endpoint_descriptor *hs,
-                                       struct usb_endpoint_descriptor *ss)
-{
-       switch (gadget->speed) {
-       case USB_SPEED_SUPER:
-               return ss;
-       case USB_SPEED_HIGH:
-               return hs;
-       default:
-               return fs;
-       }
-}
-
 /*-------------------------------------------------------------------------*/
 
 /* descriptors that are built on-demand */
 
 static char                            product_desc [40] = DRIVER_DESC;
 static char                            serial_num [40] = "1";
-static char                            pnp_string [1024] =
+static char                            pnp_string[PNP_STRING_LEN] =
        "XXMFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;";
 
 /* static strings, in UTF-8 */
@@ -299,921 +120,19 @@ static struct usb_gadget_strings *dev_strings[] = {
        NULL,
 };
 
-/*-------------------------------------------------------------------------*/
-
-static struct usb_request *
-printer_req_alloc(struct usb_ep *ep, unsigned len, gfp_t gfp_flags)
-{
-       struct usb_request      *req;
-
-       req = usb_ep_alloc_request(ep, gfp_flags);
-
-       if (req != NULL) {
-               req->length = len;
-               req->buf = kmalloc(len, gfp_flags);
-               if (req->buf == NULL) {
-                       usb_ep_free_request(ep, req);
-                       return NULL;
-               }
-       }
-
-       return req;
-}
-
-static void
-printer_req_free(struct usb_ep *ep, struct usb_request *req)
-{
-       if (ep != NULL && req != NULL) {
-               kfree(req->buf);
-               usb_ep_free_request(ep, req);
-       }
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void rx_complete(struct usb_ep *ep, struct usb_request *req)
-{
-       struct printer_dev      *dev = ep->driver_data;
-       int                     status = req->status;
-       unsigned long           flags;
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       list_del_init(&req->list);      /* Remode from Active List */
-
-       switch (status) {
-
-       /* normal completion */
-       case 0:
-               if (req->actual > 0) {
-                       list_add_tail(&req->list, &dev->rx_buffers);
-                       DBG(dev, "G_Printer : rx length %d\n", req->actual);
-               } else {
-                       list_add(&req->list, &dev->rx_reqs);
-               }
-               break;
-
-       /* software-driven interface shutdown */
-       case -ECONNRESET:               /* unlink */
-       case -ESHUTDOWN:                /* disconnect etc */
-               VDBG(dev, "rx shutdown, code %d\n", status);
-               list_add(&req->list, &dev->rx_reqs);
-               break;
-
-       /* for hardware automagic (such as pxa) */
-       case -ECONNABORTED:             /* endpoint reset */
-               DBG(dev, "rx %s reset\n", ep->name);
-               list_add(&req->list, &dev->rx_reqs);
-               break;
-
-       /* data overrun */
-       case -EOVERFLOW:
-               /* FALLTHROUGH */
-
-       default:
-               DBG(dev, "rx status %d\n", status);
-               list_add(&req->list, &dev->rx_reqs);
-               break;
-       }
-
-       wake_up_interruptible(&dev->rx_wait);
-       spin_unlock_irqrestore(&dev->lock, flags);
-}
-
-static void tx_complete(struct usb_ep *ep, struct usb_request *req)
-{
-       struct printer_dev      *dev = ep->driver_data;
-
-       switch (req->status) {
-       default:
-               VDBG(dev, "tx err %d\n", req->status);
-               /* FALLTHROUGH */
-       case -ECONNRESET:               /* unlink */
-       case -ESHUTDOWN:                /* disconnect etc */
-               break;
-       case 0:
-               break;
-       }
-
-       spin_lock(&dev->lock);
-       /* Take the request struct off the active list and put it on the
-        * free list.
-        */
-       list_del_init(&req->list);
-       list_add(&req->list, &dev->tx_reqs);
-       wake_up_interruptible(&dev->tx_wait);
-       if (likely(list_empty(&dev->tx_reqs_active)))
-               wake_up_interruptible(&dev->tx_flush_wait);
-
-       spin_unlock(&dev->lock);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-printer_open(struct inode *inode, struct file *fd)
-{
-       struct printer_dev      *dev;
-       unsigned long           flags;
-       int                     ret = -EBUSY;
-
-       mutex_lock(&printer_mutex);
-       dev = container_of(inode->i_cdev, struct printer_dev, printer_cdev);
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       if (!dev->printer_cdev_open) {
-               dev->printer_cdev_open = 1;
-               fd->private_data = dev;
-               ret = 0;
-               /* Change the printer status to show that it's on-line. */
-               dev->printer_status |= PRINTER_SELECTED;
-       }
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       DBG(dev, "printer_open returned %x\n", ret);
-       mutex_unlock(&printer_mutex);
-       return ret;
-}
-
-static int
-printer_close(struct inode *inode, struct file *fd)
-{
-       struct printer_dev      *dev = fd->private_data;
-       unsigned long           flags;
-
-       spin_lock_irqsave(&dev->lock, flags);
-       dev->printer_cdev_open = 0;
-       fd->private_data = NULL;
-       /* Change printer status to show that the printer is off-line. */
-       dev->printer_status &= ~PRINTER_SELECTED;
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       DBG(dev, "printer_close\n");
-
-       return 0;
-}
-
-/* This function must be called with interrupts turned off. */
-static void
-setup_rx_reqs(struct printer_dev *dev)
-{
-       struct usb_request              *req;
-
-       while (likely(!list_empty(&dev->rx_reqs))) {
-               int error;
-
-               req = container_of(dev->rx_reqs.next,
-                               struct usb_request, list);
-               list_del_init(&req->list);
-
-               /* The USB Host sends us whatever amount of data it wants to
-                * so we always set the length field to the full USB_BUFSIZE.
-                * If the amount of data is more than the read() caller asked
-                * for it will be stored in the request buffer until it is
-                * asked for by read().
-                */
-               req->length = USB_BUFSIZE;
-               req->complete = rx_complete;
-
-               /* here, we unlock, and only unlock, to avoid deadlock. */
-               spin_unlock(&dev->lock);
-               error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
-               spin_lock(&dev->lock);
-               if (error) {
-                       DBG(dev, "rx submit --> %d\n", error);
-                       list_add(&req->list, &dev->rx_reqs);
-                       break;
-               }
-               /* if the req is empty, then add it into dev->rx_reqs_active. */
-               else if (list_empty(&req->list)) {
-                       list_add(&req->list, &dev->rx_reqs_active);
-               }
-       }
-}
-
-static ssize_t
-printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
-{
-       struct printer_dev              *dev = fd->private_data;
-       unsigned long                   flags;
-       size_t                          size;
-       size_t                          bytes_copied;
-       struct usb_request              *req;
-       /* This is a pointer to the current USB rx request. */
-       struct usb_request              *current_rx_req;
-       /* This is the number of bytes in the current rx buffer. */
-       size_t                          current_rx_bytes;
-       /* This is a pointer to the current rx buffer. */
-       u8                              *current_rx_buf;
-
-       if (len == 0)
-               return -EINVAL;
-
-       DBG(dev, "printer_read trying to read %d bytes\n", (int)len);
-
-       mutex_lock(&dev->lock_printer_io);
-       spin_lock_irqsave(&dev->lock, flags);
-
-       /* We will use this flag later to check if a printer reset happened
-        * after we turn interrupts back on.
-        */
-       dev->reset_printer = 0;
-
-       setup_rx_reqs(dev);
-
-       bytes_copied = 0;
-       current_rx_req = dev->current_rx_req;
-       current_rx_bytes = dev->current_rx_bytes;
-       current_rx_buf = dev->current_rx_buf;
-       dev->current_rx_req = NULL;
-       dev->current_rx_bytes = 0;
-       dev->current_rx_buf = NULL;
-
-       /* Check if there is any data in the read buffers. Please note that
-        * current_rx_bytes is the number of bytes in the current rx buffer.
-        * If it is zero then check if there are any other rx_buffers that
-        * are on the completed list. We are only out of data if all rx
-        * buffers are empty.
-        */
-       if ((current_rx_bytes == 0) &&
-                       (likely(list_empty(&dev->rx_buffers)))) {
-               /* Turn interrupts back on before sleeping. */
-               spin_unlock_irqrestore(&dev->lock, flags);
-
-               /*
-                * If no data is available check if this is a NON-Blocking
-                * call or not.
-                */
-               if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
-                       mutex_unlock(&dev->lock_printer_io);
-                       return -EAGAIN;
-               }
-
-               /* Sleep until data is available */
-               wait_event_interruptible(dev->rx_wait,
-                               (likely(!list_empty(&dev->rx_buffers))));
-               spin_lock_irqsave(&dev->lock, flags);
-       }
-
-       /* We have data to return then copy it to the caller's buffer.*/
-       while ((current_rx_bytes || likely(!list_empty(&dev->rx_buffers)))
-                       && len) {
-               if (current_rx_bytes == 0) {
-                       req = container_of(dev->rx_buffers.next,
-                                       struct usb_request, list);
-                       list_del_init(&req->list);
-
-                       if (req->actual && req->buf) {
-                               current_rx_req = req;
-                               current_rx_bytes = req->actual;
-                               current_rx_buf = req->buf;
-                       } else {
-                               list_add(&req->list, &dev->rx_reqs);
-                               continue;
-                       }
-               }
-
-               /* Don't leave irqs off while doing memory copies */
-               spin_unlock_irqrestore(&dev->lock, flags);
-
-               if (len > current_rx_bytes)
-                       size = current_rx_bytes;
-               else
-                       size = len;
-
-               size -= copy_to_user(buf, current_rx_buf, size);
-               bytes_copied += size;
-               len -= size;
-               buf += size;
-
-               spin_lock_irqsave(&dev->lock, flags);
-
-               /* We've disconnected or reset so return. */
-               if (dev->reset_printer) {
-                       list_add(&current_rx_req->list, &dev->rx_reqs);
-                       spin_unlock_irqrestore(&dev->lock, flags);
-                       mutex_unlock(&dev->lock_printer_io);
-                       return -EAGAIN;
-               }
-
-               /* If we not returning all the data left in this RX request
-                * buffer then adjust the amount of data left in the buffer.
-                * Othewise if we are done with this RX request buffer then
-                * requeue it to get any incoming data from the USB host.
-                */
-               if (size < current_rx_bytes) {
-                       current_rx_bytes -= size;
-                       current_rx_buf += size;
-               } else {
-                       list_add(&current_rx_req->list, &dev->rx_reqs);
-                       current_rx_bytes = 0;
-                       current_rx_buf = NULL;
-                       current_rx_req = NULL;
-               }
-       }
-
-       dev->current_rx_req = current_rx_req;
-       dev->current_rx_bytes = current_rx_bytes;
-       dev->current_rx_buf = current_rx_buf;
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-       mutex_unlock(&dev->lock_printer_io);
-
-       DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied);
-
-       if (bytes_copied)
-               return bytes_copied;
-       else
-               return -EAGAIN;
-}
-
-static ssize_t
-printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
-{
-       struct printer_dev      *dev = fd->private_data;
-       unsigned long           flags;
-       size_t                  size;   /* Amount of data in a TX request. */
-       size_t                  bytes_copied = 0;
-       struct usb_request      *req;
-
-       DBG(dev, "printer_write trying to send %d bytes\n", (int)len);
-
-       if (len == 0)
-               return -EINVAL;
-
-       mutex_lock(&dev->lock_printer_io);
-       spin_lock_irqsave(&dev->lock, flags);
-
-       /* Check if a printer reset happens while we have interrupts on */
-       dev->reset_printer = 0;
-
-       /* Check if there is any available write buffers */
-       if (likely(list_empty(&dev->tx_reqs))) {
-               /* Turn interrupts back on before sleeping. */
-               spin_unlock_irqrestore(&dev->lock, flags);
-
-               /*
-                * If write buffers are available check if this is
-                * a NON-Blocking call or not.
-                */
-               if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
-                       mutex_unlock(&dev->lock_printer_io);
-                       return -EAGAIN;
-               }
-
-               /* Sleep until a write buffer is available */
-               wait_event_interruptible(dev->tx_wait,
-                               (likely(!list_empty(&dev->tx_reqs))));
-               spin_lock_irqsave(&dev->lock, flags);
-       }
-
-       while (likely(!list_empty(&dev->tx_reqs)) && len) {
-
-               if (len > USB_BUFSIZE)
-                       size = USB_BUFSIZE;
-               else
-                       size = len;
-
-               req = container_of(dev->tx_reqs.next, struct usb_request,
-                               list);
-               list_del_init(&req->list);
-
-               req->complete = tx_complete;
-               req->length = size;
-
-               /* Check if we need to send a zero length packet. */
-               if (len > size)
-                       /* They will be more TX requests so no yet. */
-                       req->zero = 0;
-               else
-                       /* If the data amount is not a multple of the
-                        * maxpacket size then send a zero length packet.
-                        */
-                       req->zero = ((len % dev->in_ep->maxpacket) == 0);
-
-               /* Don't leave irqs off while doing memory copies */
-               spin_unlock_irqrestore(&dev->lock, flags);
-
-               if (copy_from_user(req->buf, buf, size)) {
-                       list_add(&req->list, &dev->tx_reqs);
-                       mutex_unlock(&dev->lock_printer_io);
-                       return bytes_copied;
-               }
-
-               bytes_copied += size;
-               len -= size;
-               buf += size;
-
-               spin_lock_irqsave(&dev->lock, flags);
-
-               /* We've disconnected or reset so free the req and buffer */
-               if (dev->reset_printer) {
-                       list_add(&req->list, &dev->tx_reqs);
-                       spin_unlock_irqrestore(&dev->lock, flags);
-                       mutex_unlock(&dev->lock_printer_io);
-                       return -EAGAIN;
-               }
-
-               if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
-                       list_add(&req->list, &dev->tx_reqs);
-                       spin_unlock_irqrestore(&dev->lock, flags);
-                       mutex_unlock(&dev->lock_printer_io);
-                       return -EAGAIN;
-               }
-
-               list_add(&req->list, &dev->tx_reqs_active);
-
-       }
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-       mutex_unlock(&dev->lock_printer_io);
-
-       DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);
-
-       if (bytes_copied) {
-               return bytes_copied;
-       } else {
-               return -EAGAIN;
-       }
-}
-
-static int
-printer_fsync(struct file *fd, loff_t start, loff_t end, int datasync)
-{
-       struct printer_dev      *dev = fd->private_data;
-       struct inode *inode = file_inode(fd);
-       unsigned long           flags;
-       int                     tx_list_empty;
-
-       mutex_lock(&inode->i_mutex);
-       spin_lock_irqsave(&dev->lock, flags);
-       tx_list_empty = (likely(list_empty(&dev->tx_reqs)));
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       if (!tx_list_empty) {
-               /* Sleep until all data has been sent */
-               wait_event_interruptible(dev->tx_flush_wait,
-                               (likely(list_empty(&dev->tx_reqs_active))));
-       }
-       mutex_unlock(&inode->i_mutex);
-
-       return 0;
-}
-
-static unsigned int
-printer_poll(struct file *fd, poll_table *wait)
-{
-       struct printer_dev      *dev = fd->private_data;
-       unsigned long           flags;
-       int                     status = 0;
-
-       mutex_lock(&dev->lock_printer_io);
-       spin_lock_irqsave(&dev->lock, flags);
-       setup_rx_reqs(dev);
-       spin_unlock_irqrestore(&dev->lock, flags);
-       mutex_unlock(&dev->lock_printer_io);
-
-       poll_wait(fd, &dev->rx_wait, wait);
-       poll_wait(fd, &dev->tx_wait, wait);
-
-       spin_lock_irqsave(&dev->lock, flags);
-       if (likely(!list_empty(&dev->tx_reqs)))
-               status |= POLLOUT | POLLWRNORM;
-
-       if (likely(dev->current_rx_bytes) ||
-                       likely(!list_empty(&dev->rx_buffers)))
-               status |= POLLIN | POLLRDNORM;
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return status;
-}
-
-static long
-printer_ioctl(struct file *fd, unsigned int code, unsigned long arg)
-{
-       struct printer_dev      *dev = fd->private_data;
-       unsigned long           flags;
-       int                     status = 0;
-
-       DBG(dev, "printer_ioctl: cmd=0x%4.4x, arg=%lu\n", code, arg);
-
-       /* handle ioctls */
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       switch (code) {
-       case GADGET_GET_PRINTER_STATUS:
-               status = (int)dev->printer_status;
-               break;
-       case GADGET_SET_PRINTER_STATUS:
-               dev->printer_status = (u8)arg;
-               break;
-       default:
-               /* could not handle ioctl */
-               DBG(dev, "printer_ioctl: ERROR cmd=0x%4.4xis not supported\n",
-                               code);
-               status = -ENOTTY;
-       }
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-
-       return status;
-}
-
-/* used after endpoint configuration */
-static const struct file_operations printer_io_operations = {
-       .owner =        THIS_MODULE,
-       .open =         printer_open,
-       .read =         printer_read,
-       .write =        printer_write,
-       .fsync =        printer_fsync,
-       .poll =         printer_poll,
-       .unlocked_ioctl = printer_ioctl,
-       .release =      printer_close,
-       .llseek =       noop_llseek,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int
-set_printer_interface(struct printer_dev *dev)
-{
-       int                     result = 0;
-
-       dev->in_ep->desc = ep_desc(dev->gadget, &fs_ep_in_desc, &hs_ep_in_desc,
-                               &ss_ep_in_desc);
-       dev->in_ep->driver_data = dev;
-
-       dev->out_ep->desc = ep_desc(dev->gadget, &fs_ep_out_desc,
-                                   &hs_ep_out_desc, &ss_ep_out_desc);
-       dev->out_ep->driver_data = dev;
-
-       result = usb_ep_enable(dev->in_ep);
-       if (result != 0) {
-               DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result);
-               goto done;
-       }
-
-       result = usb_ep_enable(dev->out_ep);
-       if (result != 0) {
-               DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result);
-               goto done;
-       }
-
-done:
-       /* on error, disable any endpoints  */
-       if (result != 0) {
-               (void) usb_ep_disable(dev->in_ep);
-               (void) usb_ep_disable(dev->out_ep);
-               dev->in_ep->desc = NULL;
-               dev->out_ep->desc = NULL;
-       }
-
-       /* caller is responsible for cleanup on error */
-       return result;
-}
-
-static void printer_reset_interface(struct printer_dev *dev)
-{
-       if (dev->interface < 0)
-               return;
-
-       DBG(dev, "%s\n", __func__);
-
-       if (dev->in_ep->desc)
-               usb_ep_disable(dev->in_ep);
-
-       if (dev->out_ep->desc)
-               usb_ep_disable(dev->out_ep);
-
-       dev->in_ep->desc = NULL;
-       dev->out_ep->desc = NULL;
-       dev->interface = -1;
-}
-
-/* Change our operational Interface. */
-static int set_interface(struct printer_dev *dev, unsigned number)
-{
-       int                     result = 0;
-
-       /* Free the current interface */
-       printer_reset_interface(dev);
-
-       result = set_printer_interface(dev);
-       if (result)
-               printer_reset_interface(dev);
-       else
-               dev->interface = number;
-
-       if (!result)
-               INFO(dev, "Using interface %x\n", number);
-
-       return result;
-}
-
-static void printer_soft_reset(struct printer_dev *dev)
-{
-       struct usb_request      *req;
-
-       INFO(dev, "Received Printer Reset Request\n");
-
-       if (usb_ep_disable(dev->in_ep))
-               DBG(dev, "Failed to disable USB in_ep\n");
-       if (usb_ep_disable(dev->out_ep))
-               DBG(dev, "Failed to disable USB out_ep\n");
-
-       if (dev->current_rx_req != NULL) {
-               list_add(&dev->current_rx_req->list, &dev->rx_reqs);
-               dev->current_rx_req = NULL;
-       }
-       dev->current_rx_bytes = 0;
-       dev->current_rx_buf = NULL;
-       dev->reset_printer = 1;
-
-       while (likely(!(list_empty(&dev->rx_buffers)))) {
-               req = container_of(dev->rx_buffers.next, struct usb_request,
-                               list);
-               list_del_init(&req->list);
-               list_add(&req->list, &dev->rx_reqs);
-       }
-
-       while (likely(!(list_empty(&dev->rx_reqs_active)))) {
-               req = container_of(dev->rx_buffers.next, struct usb_request,
-                               list);
-               list_del_init(&req->list);
-               list_add(&req->list, &dev->rx_reqs);
-       }
-
-       while (likely(!(list_empty(&dev->tx_reqs_active)))) {
-               req = container_of(dev->tx_reqs_active.next,
-                               struct usb_request, list);
-               list_del_init(&req->list);
-               list_add(&req->list, &dev->tx_reqs);
-       }
-
-       if (usb_ep_enable(dev->in_ep))
-               DBG(dev, "Failed to enable USB in_ep\n");
-       if (usb_ep_enable(dev->out_ep))
-               DBG(dev, "Failed to enable USB out_ep\n");
-
-       wake_up_interruptible(&dev->rx_wait);
-       wake_up_interruptible(&dev->tx_wait);
-       wake_up_interruptible(&dev->tx_flush_wait);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * The setup() callback implements all the ep0 functionality that's not
- * handled lower down.
- */
-static int printer_func_setup(struct usb_function *f,
-               const struct usb_ctrlrequest *ctrl)
-{
-       struct printer_dev *dev = container_of(f, struct printer_dev, function);
-       struct usb_composite_dev *cdev = f->config->cdev;
-       struct usb_request      *req = cdev->req;
-       int                     value = -EOPNOTSUPP;
-       u16                     wIndex = le16_to_cpu(ctrl->wIndex);
-       u16                     wValue = le16_to_cpu(ctrl->wValue);
-       u16                     wLength = le16_to_cpu(ctrl->wLength);
-
-       DBG(dev, "ctrl req%02x.%02x v%04x i%04x l%d\n",
-               ctrl->bRequestType, ctrl->bRequest, wValue, wIndex, wLength);
-
-       switch (ctrl->bRequestType&USB_TYPE_MASK) {
-       case USB_TYPE_CLASS:
-               switch (ctrl->bRequest) {
-               case 0: /* Get the IEEE-1284 PNP String */
-                       /* Only one printer interface is supported. */
-                       if ((wIndex>>8) != dev->interface)
-                               break;
-
-                       value = (pnp_string[0]<<8)|pnp_string[1];
-                       memcpy(req->buf, pnp_string, value);
-                       DBG(dev, "1284 PNP String: %x %s\n", value,
-                                       &pnp_string[2]);
-                       break;
-
-               case 1: /* Get Port Status */
-                       /* Only one printer interface is supported. */
-                       if (wIndex != dev->interface)
-                               break;
-
-                       *(u8 *)req->buf = dev->printer_status;
-                       value = min(wLength, (u16) 1);
-                       break;
-
-               case 2: /* Soft Reset */
-                       /* Only one printer interface is supported. */
-                       if (wIndex != dev->interface)
-                               break;
-
-                       printer_soft_reset(dev);
-
-                       value = 0;
-                       break;
-
-               default:
-                       goto unknown;
-               }
-               break;
-
-       default:
-unknown:
-               VDBG(dev,
-                       "unknown ctrl req%02x.%02x v%04x i%04x l%d\n",
-                       ctrl->bRequestType, ctrl->bRequest,
-                       wValue, wIndex, wLength);
-               break;
-       }
-       /* host either stalls (value < 0) or reports success */
-       return value;
-}
-
-static int __init printer_func_bind(struct usb_configuration *c,
-               struct usb_function *f)
-{
-       struct printer_dev *dev = container_of(f, struct printer_dev, function);
-       struct usb_composite_dev *cdev = c->cdev;
-       struct usb_ep *in_ep;
-       struct usb_ep *out_ep = NULL;
-       int id;
-       int ret;
-
-       id = usb_interface_id(c, f);
-       if (id < 0)
-               return id;
-       intf_desc.bInterfaceNumber = id;
-
-       /* all we really need is bulk IN/OUT */
-       in_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_in_desc);
-       if (!in_ep) {
-autoconf_fail:
-               dev_err(&cdev->gadget->dev, "can't autoconfigure on %s\n",
-                       cdev->gadget->name);
-               return -ENODEV;
-       }
-       in_ep->driver_data = in_ep;     /* claim */
-
-       out_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_out_desc);
-       if (!out_ep)
-               goto autoconf_fail;
-       out_ep->driver_data = out_ep;   /* claim */
-
-       /* assumes that all endpoints are dual-speed */
-       hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
-       hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
-       ss_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
-       ss_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
-
-       ret = usb_assign_descriptors(f, fs_printer_function,
-                       hs_printer_function, ss_printer_function);
-       if (ret)
-               return ret;
-
-       dev->in_ep = in_ep;
-       dev->out_ep = out_ep;
-       return 0;
-}
-
-static void printer_func_unbind(struct usb_configuration *c,
-               struct usb_function *f)
-{
-       usb_free_all_descriptors(f);
-}
-
-static int printer_func_set_alt(struct usb_function *f,
-               unsigned intf, unsigned alt)
-{
-       struct printer_dev *dev = container_of(f, struct printer_dev, function);
-       int ret = -ENOTSUPP;
-
-       if (!alt)
-               ret = set_interface(dev, intf);
-
-       return ret;
-}
-
-static void printer_func_disable(struct usb_function *f)
-{
-       struct printer_dev *dev = container_of(f, struct printer_dev, function);
-       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 void printer_cfg_unbind(struct usb_configuration *c)
-{
-       struct printer_dev      *dev;
-       struct usb_request      *req;
-
-       dev = &usb_printer_gadget;
-
-       DBG(dev, "%s\n", __func__);
-
-       /* Remove sysfs files */
-       device_destroy(usb_gadget_class, g_printer_devno);
-
-       /* Remove Character Device */
-       cdev_del(&dev->printer_cdev);
-
-       /* we must already have been disconnected ... no i/o may be active */
-       WARN_ON(!list_empty(&dev->tx_reqs_active));
-       WARN_ON(!list_empty(&dev->rx_reqs_active));
-
-       /* Free all memory for this driver. */
-       while (!list_empty(&dev->tx_reqs)) {
-               req = container_of(dev->tx_reqs.next, struct usb_request,
-                               list);
-               list_del(&req->list);
-               printer_req_free(dev->in_ep, req);
-       }
-
-       if (dev->current_rx_req != NULL)
-               printer_req_free(dev->out_ep, dev->current_rx_req);
-
-       while (!list_empty(&dev->rx_reqs)) {
-               req = container_of(dev->rx_reqs.next,
-                               struct usb_request, list);
-               list_del(&req->list);
-               printer_req_free(dev->out_ep, req);
-       }
-
-       while (!list_empty(&dev->rx_buffers)) {
-               req = container_of(dev->rx_buffers.next,
-                               struct usb_request, list);
-               list_del(&req->list);
-               printer_req_free(dev->out_ep, req);
-       }
-}
-
 static struct usb_configuration printer_cfg_driver = {
        .label                  = "printer",
-       .unbind                 = printer_cfg_unbind,
        .bConfigurationValue    = 1,
        .bmAttributes           = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
 };
 
-static int __init printer_bind_config(struct usb_configuration *c)
+static int __init printer_do_config(struct usb_configuration *c)
 {
        struct usb_gadget       *gadget = c->cdev->gadget;
-       struct printer_dev      *dev;
-       int                     status = -ENOMEM;
-       size_t                  len;
-       u32                     i;
-       struct usb_request      *req;
+       int                     status = 0;
 
        usb_ep_autoconfig_reset(gadget);
 
-       dev = &usb_printer_gadget;
-
-       dev->function.name = shortname;
-       dev->function.bind = printer_func_bind;
-       dev->function.setup = printer_func_setup;
-       dev->function.unbind = printer_func_unbind;
-       dev->function.set_alt = printer_func_set_alt;
-       dev->function.disable = printer_func_disable;
-
-       status = usb_add_function(c, &dev->function);
-       if (status)
-               return status;
-
-       /* Setup the sysfs files for the printer gadget. */
-       dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
-                                 NULL, "g_printer");
-       if (IS_ERR(dev->pdev)) {
-               ERROR(dev, "Failed to create device: g_printer\n");
-               status = PTR_ERR(dev->pdev);
-               goto fail;
-       }
-
-       /*
-        * Register a character device as an interface to a user mode
-        * program that handles the printer specific functionality.
-        */
-       cdev_init(&dev->printer_cdev, &printer_io_operations);
-       dev->printer_cdev.owner = THIS_MODULE;
-       status = cdev_add(&dev->printer_cdev, g_printer_devno, 1);
-       if (status) {
-               ERROR(dev, "Failed to open char device\n");
-               goto fail;
-       }
-
-       if (iPNPstring)
-               strlcpy(&pnp_string[2], iPNPstring, (sizeof pnp_string)-2);
-
-       len = strlen(pnp_string);
-       pnp_string[0] = (len >> 8) & 0xFF;
-       pnp_string[1] = len & 0xFF;
-
        usb_gadget_set_selfpowered(gadget);
 
        if (gadget_is_otg(gadget)) {
@@ -1222,86 +141,64 @@ static int __init printer_bind_config(struct usb_configuration *c)
                printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
        }
 
-       spin_lock_init(&dev->lock);
-       mutex_init(&dev->lock_printer_io);
-       INIT_LIST_HEAD(&dev->tx_reqs);
-       INIT_LIST_HEAD(&dev->tx_reqs_active);
-       INIT_LIST_HEAD(&dev->rx_reqs);
-       INIT_LIST_HEAD(&dev->rx_reqs_active);
-       INIT_LIST_HEAD(&dev->rx_buffers);
-       init_waitqueue_head(&dev->rx_wait);
-       init_waitqueue_head(&dev->tx_wait);
-       init_waitqueue_head(&dev->tx_flush_wait);
-
-       dev->interface = -1;
-       dev->printer_cdev_open = 0;
-       dev->printer_status = PRINTER_NOT_ERROR;
-       dev->current_rx_req = NULL;
-       dev->current_rx_bytes = 0;
-       dev->current_rx_buf = NULL;
-
-       for (i = 0; i < QLEN; i++) {
-               req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL);
-               if (!req) {
-                       while (!list_empty(&dev->tx_reqs)) {
-                               req = container_of(dev->tx_reqs.next,
-                                               struct usb_request, list);
-                               list_del(&req->list);
-                               printer_req_free(dev->in_ep, req);
-                       }
-                       return -ENOMEM;
-               }
-               list_add(&req->list, &dev->tx_reqs);
-       }
-
-       for (i = 0; i < QLEN; i++) {
-               req = printer_req_alloc(dev->out_ep, USB_BUFSIZE, GFP_KERNEL);
-               if (!req) {
-                       while (!list_empty(&dev->rx_reqs)) {
-                               req = container_of(dev->rx_reqs.next,
-                                               struct usb_request, list);
-                               list_del(&req->list);
-                               printer_req_free(dev->out_ep, req);
-                       }
-                       return -ENOMEM;
-               }
-               list_add(&req->list, &dev->rx_reqs);
-       }
-
-       /* finish hookup to lower layer ... */
-       dev->gadget = gadget;
+       f_printer = usb_get_function(fi_printer);
+       if (IS_ERR(f_printer))
+               return PTR_ERR(f_printer);
 
-       INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
-       return 0;
+       status = usb_add_function(c, f_printer);
+       if (status < 0)
+               usb_put_function(f_printer);
 
-fail:
-       printer_cfg_unbind(c);
        return status;
 }
 
-static int printer_unbind(struct usb_composite_dev *cdev)
-{
-       return 0;
-}
-
 static int __init printer_bind(struct usb_composite_dev *cdev)
 {
-       int ret;
+       struct f_printer_opts *opts;
+       int ret, len;
+
+       fi_printer = usb_get_function_instance("printer");
+       if (IS_ERR(fi_printer))
+               return PTR_ERR(fi_printer);
+
+       if (iPNPstring)
+               strlcpy(&pnp_string[2], iPNPstring, PNP_STRING_LEN - 2);
+
+       len = strlen(pnp_string);
+       pnp_string[0] = (len >> 8) & 0xFF;
+       pnp_string[1] = len & 0xFF;
+
+       opts = container_of(fi_printer, struct f_printer_opts, func_inst);
+       opts->minor = 0;
+       memcpy(opts->pnp_string, pnp_string, PNP_STRING_LEN);
+       opts->q_len = QLEN;
 
        ret = usb_string_ids_tab(cdev, strings);
-       if (ret < 0)
+       if (ret < 0) {
+               usb_put_function_instance(fi_printer);
                return ret;
+       }
        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_bind_config);
-       if (ret)
+       ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config);
+       if (ret) {
+               usb_put_function_instance(fi_printer);
                return ret;
+       }
        usb_composite_overwrite_options(cdev, &coverwrite);
        return ret;
 }
 
+static int __exit printer_unbind(struct usb_composite_dev *cdev)
+{
+       usb_put_function(f_printer);
+       usb_put_function_instance(fi_printer);
+
+       return 0;
+}
+
 static __refdata struct usb_composite_driver printer_driver = {
        .name           = shortname,
        .dev            = &device_desc,
@@ -1311,47 +208,7 @@ static __refdata struct usb_composite_driver printer_driver = {
        .unbind         = printer_unbind,
 };
 
-static int __init
-init(void)
-{
-       int status;
-
-       usb_gadget_class = class_create(THIS_MODULE, "usb_printer_gadget");
-       if (IS_ERR(usb_gadget_class)) {
-               status = PTR_ERR(usb_gadget_class);
-               pr_err("unable to create usb_gadget class %d\n", status);
-               return status;
-       }
-
-       status = alloc_chrdev_region(&g_printer_devno, 0, 1,
-                       "USB printer gadget");
-       if (status) {
-               pr_err("alloc_chrdev_region %d\n", status);
-               class_destroy(usb_gadget_class);
-               return status;
-       }
-
-       status = usb_composite_probe(&printer_driver);
-       if (status) {
-               class_destroy(usb_gadget_class);
-               unregister_chrdev_region(g_printer_devno, 1);
-               pr_err("usb_gadget_probe_driver %x\n", status);
-       }
-
-       return status;
-}
-module_init(init);
-
-static void __exit
-cleanup(void)
-{
-       mutex_lock(&usb_printer_gadget.lock_printer_io);
-       usb_composite_unregister(&printer_driver);
-       unregister_chrdev_region(g_printer_devno, 1);
-       class_destroy(usb_gadget_class);
-       mutex_unlock(&usb_printer_gadget.lock_printer_io);
-}
-module_exit(cleanup);
+module_usb_composite_driver(printer_driver);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Craig Nadler");
index d79cb35dbf8a2099dab062473ed9e70a21feca2d..4c01953a0869cf67693ec2842d48b508770927a2 100644 (file)
@@ -152,7 +152,7 @@ static int regs_dbg_open(struct inode *inode, struct file *file)
 
        spin_lock_irq(&udc->lock);
        for (i = 0; i < inode->i_size / 4; i++)
-               data[i] = __raw_readl(udc->regs + i * 4);
+               data[i] = usba_io_readl(udc->regs + i * 4);
        spin_unlock_irq(&udc->lock);
 
        file->private_data = data;
@@ -1249,7 +1249,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
                if (crq->wLength != cpu_to_le16(sizeof(status)))
                        goto stall;
                ep->state = DATA_STAGE_IN;
-               __raw_writew(status, ep->fifo);
+               usba_io_writew(status, ep->fifo);
                usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
                break;
        }
@@ -1739,7 +1739,72 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
        return IRQ_HANDLED;
 }
 
-static irqreturn_t usba_vbus_irq(int irq, void *devid)
+static int start_clock(struct usba_udc *udc)
+{
+       int ret;
+
+       if (udc->clocked)
+               return 0;
+
+       ret = clk_prepare_enable(udc->pclk);
+       if (ret)
+               return ret;
+       ret = clk_prepare_enable(udc->hclk);
+       if (ret) {
+               clk_disable_unprepare(udc->pclk);
+               return ret;
+       }
+
+       udc->clocked = true;
+       return 0;
+}
+
+static void stop_clock(struct usba_udc *udc)
+{
+       if (!udc->clocked)
+               return;
+
+       clk_disable_unprepare(udc->hclk);
+       clk_disable_unprepare(udc->pclk);
+
+       udc->clocked = false;
+}
+
+static int usba_start(struct usba_udc *udc)
+{
+       unsigned long flags;
+       int ret;
+
+       ret = start_clock(udc);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       toggle_bias(udc, 1);
+       usba_writel(udc, CTRL, USBA_ENABLE_MASK);
+       usba_int_enb_set(udc, USBA_END_OF_RESET);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static void usba_stop(struct usba_udc *udc)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       reset_all_endpoints(udc);
+
+       /* This will also disable the DP pullup */
+       toggle_bias(udc, 0);
+       usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       stop_clock(udc);
+}
+
+static irqreturn_t usba_vbus_irq_thread(int irq, void *devid)
 {
        struct usba_udc *udc = devid;
        int vbus;
@@ -1747,35 +1812,22 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid)
        /* debounce */
        udelay(10);
 
-       spin_lock(&udc->lock);
-
-       /* May happen if Vbus pin toggles during probe() */
-       if (!udc->driver)
-               goto out;
+       mutex_lock(&udc->vbus_mutex);
 
        vbus = vbus_is_present(udc);
        if (vbus != udc->vbus_prev) {
                if (vbus) {
-                       toggle_bias(udc, 1);
-                       usba_writel(udc, CTRL, USBA_ENABLE_MASK);
-                       usba_int_enb_set(udc, USBA_END_OF_RESET);
+                       usba_start(udc);
                } else {
-                       udc->gadget.speed = USB_SPEED_UNKNOWN;
-                       reset_all_endpoints(udc);
-                       toggle_bias(udc, 0);
-                       usba_writel(udc, CTRL, USBA_DISABLE_MASK);
-                       if (udc->driver->disconnect) {
-                               spin_unlock(&udc->lock);
+                       usba_stop(udc);
+
+                       if (udc->driver->disconnect)
                                udc->driver->disconnect(&udc->gadget);
-                               spin_lock(&udc->lock);
-                       }
                }
                udc->vbus_prev = vbus;
        }
 
-out:
-       spin_unlock(&udc->lock);
-
+       mutex_unlock(&udc->vbus_mutex);
        return IRQ_HANDLED;
 }
 
@@ -1787,55 +1839,47 @@ static int atmel_usba_start(struct usb_gadget *gadget,
        unsigned long flags;
 
        spin_lock_irqsave(&udc->lock, flags);
-
        udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
        udc->driver = driver;
        spin_unlock_irqrestore(&udc->lock, flags);
 
-       ret = clk_prepare_enable(udc->pclk);
-       if (ret)
-               return ret;
-       ret = clk_prepare_enable(udc->hclk);
-       if (ret) {
-               clk_disable_unprepare(udc->pclk);
-               return ret;
-       }
+       mutex_lock(&udc->vbus_mutex);
 
-       udc->vbus_prev = 0;
        if (gpio_is_valid(udc->vbus_pin))
                enable_irq(gpio_to_irq(udc->vbus_pin));
 
        /* If Vbus is present, enable the controller and wait for reset */
-       spin_lock_irqsave(&udc->lock, flags);
-       if (vbus_is_present(udc) && udc->vbus_prev == 0) {
-               toggle_bias(udc, 1);
-               usba_writel(udc, CTRL, USBA_ENABLE_MASK);
-               usba_int_enb_set(udc, USBA_END_OF_RESET);
+       udc->vbus_prev = vbus_is_present(udc);
+       if (udc->vbus_prev) {
+               ret = usba_start(udc);
+               if (ret)
+                       goto err;
        }
-       spin_unlock_irqrestore(&udc->lock, flags);
 
+       mutex_unlock(&udc->vbus_mutex);
        return 0;
+
+err:
+       if (gpio_is_valid(udc->vbus_pin))
+               disable_irq(gpio_to_irq(udc->vbus_pin));
+
+       mutex_unlock(&udc->vbus_mutex);
+
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
+       udc->driver = NULL;
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return ret;
 }
 
 static int atmel_usba_stop(struct usb_gadget *gadget)
 {
        struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
-       unsigned long flags;
 
        if (gpio_is_valid(udc->vbus_pin))
                disable_irq(gpio_to_irq(udc->vbus_pin));
 
-       spin_lock_irqsave(&udc->lock, flags);
-       udc->gadget.speed = USB_SPEED_UNKNOWN;
-       reset_all_endpoints(udc);
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       /* This will also disable the DP pullup */
-       toggle_bias(udc, 0);
-       usba_writel(udc, CTRL, USBA_DISABLE_MASK);
-
-       clk_disable_unprepare(udc->hclk);
-       clk_disable_unprepare(udc->pclk);
+       usba_stop(udc);
 
        udc->driver = NULL;
 
@@ -2057,6 +2101,7 @@ static int usba_udc_probe(struct platform_device *pdev)
                return PTR_ERR(hclk);
 
        spin_lock_init(&udc->lock);
+       mutex_init(&udc->vbus_mutex);
        udc->pdev = pdev;
        udc->pclk = pclk;
        udc->hclk = hclk;
@@ -2111,17 +2156,17 @@ static int usba_udc_probe(struct platform_device *pdev)
 
        if (gpio_is_valid(udc->vbus_pin)) {
                if (!devm_gpio_request(&pdev->dev, udc->vbus_pin, "atmel_usba_udc")) {
-                       ret = devm_request_irq(&pdev->dev,
-                                       gpio_to_irq(udc->vbus_pin),
-                                       usba_vbus_irq, 0,
+                       irq_set_status_flags(gpio_to_irq(udc->vbus_pin),
+                                       IRQ_NOAUTOEN);
+                       ret = devm_request_threaded_irq(&pdev->dev,
+                                       gpio_to_irq(udc->vbus_pin), NULL,
+                                       usba_vbus_irq_thread, IRQF_ONESHOT,
                                        "atmel_usba_udc", udc);
                        if (ret) {
                                udc->vbus_pin = -ENODEV;
                                dev_warn(&udc->pdev->dev,
                                         "failed to request vbus irq; "
                                         "assuming always on\n");
-                       } else {
-                               disable_irq(gpio_to_irq(udc->vbus_pin));
                        }
                } else {
                        /* gpio_request fail so use -EINVAL for gpio_is_valid */
@@ -2132,6 +2177,7 @@ static int usba_udc_probe(struct platform_device *pdev)
        ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
        if (ret)
                return ret;
+       device_init_wakeup(&pdev->dev, 1);
 
        usba_init_debugfs(udc);
        for (i = 1; i < udc->num_ep; i++)
@@ -2147,6 +2193,7 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
 
        udc = platform_get_drvdata(pdev);
 
+       device_init_wakeup(&pdev->dev, 0);
        usb_del_gadget_udc(&udc->gadget);
 
        for (i = 1; i < udc->num_ep; i++)
@@ -2156,10 +2203,65 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int usba_udc_suspend(struct device *dev)
+{
+       struct usba_udc *udc = dev_get_drvdata(dev);
+
+       /* Not started */
+       if (!udc->driver)
+               return 0;
+
+       mutex_lock(&udc->vbus_mutex);
+
+       if (!device_may_wakeup(dev)) {
+               usba_stop(udc);
+               goto out;
+       }
+
+       /*
+        * Device may wake up. We stay clocked if we failed
+        * to request vbus irq, assuming always on.
+        */
+       if (gpio_is_valid(udc->vbus_pin)) {
+               usba_stop(udc);
+               enable_irq_wake(gpio_to_irq(udc->vbus_pin));
+       }
+
+out:
+       mutex_unlock(&udc->vbus_mutex);
+       return 0;
+}
+
+static int usba_udc_resume(struct device *dev)
+{
+       struct usba_udc *udc = dev_get_drvdata(dev);
+
+       /* Not started */
+       if (!udc->driver)
+               return 0;
+
+       if (device_may_wakeup(dev) && gpio_is_valid(udc->vbus_pin))
+               disable_irq_wake(gpio_to_irq(udc->vbus_pin));
+
+       /* If Vbus is present, enable the controller and wait for reset */
+       mutex_lock(&udc->vbus_mutex);
+       udc->vbus_prev = vbus_is_present(udc);
+       if (udc->vbus_prev)
+               usba_start(udc);
+       mutex_unlock(&udc->vbus_mutex);
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(usba_udc_pm_ops, usba_udc_suspend, usba_udc_resume);
+
 static struct platform_driver udc_driver = {
        .remove         = __exit_p(usba_udc_remove),
        .driver         = {
                .name           = "atmel_usba_udc",
+               .pm             = &usba_udc_pm_ops,
                .of_match_table = of_match_ptr(atmel_udc_dt_ids),
        },
 };
index 497cd18836f381c46b710e8751806adbc07eeb27..ea448a3447670f5e9017841cf76efcdb9909b724 100644 (file)
         | USBA_BF(name, value))
 
 /* Register access macros */
+#ifdef CONFIG_AVR32
+#define usba_io_readl  __raw_readl
+#define usba_io_writel __raw_writel
+#define usba_io_writew __raw_writew
+#else
+#define usba_io_readl  readl_relaxed
+#define usba_io_writel writel_relaxed
+#define usba_io_writew writew_relaxed
+#endif
+
 #define usba_readl(udc, reg)                                   \
-       __raw_readl((udc)->regs + USBA_##reg)
+       usba_io_readl((udc)->regs + USBA_##reg)
 #define usba_writel(udc, reg, value)                           \
-       __raw_writel((value), (udc)->regs + USBA_##reg)
+       usba_io_writel((value), (udc)->regs + USBA_##reg)
 #define usba_ep_readl(ep, reg)                                 \
-       __raw_readl((ep)->ep_regs + USBA_EPT_##reg)
+       usba_io_readl((ep)->ep_regs + USBA_EPT_##reg)
 #define usba_ep_writel(ep, reg, value)                         \
-       __raw_writel((value), (ep)->ep_regs + USBA_EPT_##reg)
+       usba_io_writel((value), (ep)->ep_regs + USBA_EPT_##reg)
 #define usba_dma_readl(ep, reg)                                        \
-       __raw_readl((ep)->dma_regs + USBA_DMA_##reg)
+       usba_io_readl((ep)->dma_regs + USBA_DMA_##reg)
 #define usba_dma_writel(ep, reg, value)                                \
-       __raw_writel((value), (ep)->dma_regs + USBA_DMA_##reg)
+       usba_io_writel((value), (ep)->dma_regs + USBA_DMA_##reg)
 
 /* Calculate base address for a given endpoint or DMA controller */
 #define USBA_EPT_BASE(x)       (0x100 + (x) * 0x20)
@@ -313,6 +323,9 @@ struct usba_udc {
        /* Protect hw registers from concurrent modifications */
        spinlock_t lock;
 
+       /* Mutex to prevent concurrent start or stop */
+       struct mutex vbus_mutex;
+
        void __iomem *regs;
        void __iomem *fifo;
 
@@ -328,6 +341,7 @@ struct usba_udc {
        struct clk *hclk;
        struct usba_ep *usba_ep;
        bool bias_pulse_needed;
+       bool clocked;
 
        u16 devstatus;
 
index 8dda48445f6ff5a4a066d870f61bd539c603c214..181112c88f430d39985c199312b2043337c02cf6 100644 (file)
@@ -1923,7 +1923,7 @@ static inline void
 ss_hub_descriptor(struct usb_hub_descriptor *desc)
 {
        memset(desc, 0, sizeof *desc);
-       desc->bDescriptorType = 0x2a;
+       desc->bDescriptorType = USB_DT_SS_HUB;
        desc->bDescLength = 12;
        desc->wHubCharacteristics = cpu_to_le16(
                        HUB_CHAR_INDV_PORT_LPSM |
@@ -1936,7 +1936,7 @@ ss_hub_descriptor(struct usb_hub_descriptor *desc)
 static inline void hub_descriptor(struct usb_hub_descriptor *desc)
 {
        memset(desc, 0, sizeof *desc);
-       desc->bDescriptorType = 0x29;
+       desc->bDescriptorType = USB_DT_HUB;
        desc->bDescLength = 9;
        desc->wHubCharacteristics = cpu_to_le16(
                        HUB_CHAR_INDV_PORT_LPSM |
@@ -2631,7 +2631,7 @@ static int __init init(void)
                return -EINVAL;
 
        if (mod_data.num < 1 || mod_data.num > MAX_NUM_UDC) {
-               pr_err("Number of emulated UDC must be in range of 1…%d\n",
+               pr_err("Number of emulated UDC must be in range of 1...%d\n",
                                MAX_NUM_UDC);
                return -EINVAL;
        }
index 5b9176e7202a8fb30c4a07ff7bf8e55e56b740ab..9e8d842e8c08546ed1fe109a3586da6b3c4ee102 100644 (file)
@@ -1024,35 +1024,79 @@ static const char proc_node_name [] = "driver/udc";
 static void dump_intmask(struct seq_file *m, const char *label, u32 mask)
 {
        /* int_status is the same format ... */
-       seq_printf(m,
-               "%s %05X =" FOURBITS EIGHTBITS EIGHTBITS "\n",
-               label, mask,
-               (mask & INT_PWRDETECT) ? " power" : "",
-               (mask & INT_SYSERROR) ? " sys" : "",
-               (mask & INT_MSTRDEND) ? " in-dma" : "",
-               (mask & INT_MSTWRTMOUT) ? " wrtmo" : "",
-
-               (mask & INT_MSTWREND) ? " out-dma" : "",
-               (mask & INT_MSTWRSET) ? " wrset" : "",
-               (mask & INT_ERR) ? " err" : "",
-               (mask & INT_SOF) ? " sof" : "",
-
-               (mask & INT_EP3NAK) ? " ep3nak" : "",
-               (mask & INT_EP2NAK) ? " ep2nak" : "",
-               (mask & INT_EP1NAK) ? " ep1nak" : "",
-               (mask & INT_EP3DATASET) ? " ep3" : "",
-
-               (mask & INT_EP2DATASET) ? " ep2" : "",
-               (mask & INT_EP1DATASET) ? " ep1" : "",
-               (mask & INT_STATUSNAK) ? " ep0snak" : "",
-               (mask & INT_STATUS) ? " ep0status" : "",
-
-               (mask & INT_SETUP) ? " setup" : "",
-               (mask & INT_ENDPOINT0) ? " ep0" : "",
-               (mask & INT_USBRESET) ? " reset" : "",
-               (mask & INT_SUSPEND) ? " suspend" : "");
+       seq_printf(m, "%s %05X =" FOURBITS EIGHTBITS EIGHTBITS "\n",
+                  label, mask,
+                  (mask & INT_PWRDETECT) ? " power" : "",
+                  (mask & INT_SYSERROR) ? " sys" : "",
+                  (mask & INT_MSTRDEND) ? " in-dma" : "",
+                  (mask & INT_MSTWRTMOUT) ? " wrtmo" : "",
+
+                  (mask & INT_MSTWREND) ? " out-dma" : "",
+                  (mask & INT_MSTWRSET) ? " wrset" : "",
+                  (mask & INT_ERR) ? " err" : "",
+                  (mask & INT_SOF) ? " sof" : "",
+
+                  (mask & INT_EP3NAK) ? " ep3nak" : "",
+                  (mask & INT_EP2NAK) ? " ep2nak" : "",
+                  (mask & INT_EP1NAK) ? " ep1nak" : "",
+                  (mask & INT_EP3DATASET) ? " ep3" : "",
+
+                  (mask & INT_EP2DATASET) ? " ep2" : "",
+                  (mask & INT_EP1DATASET) ? " ep1" : "",
+                  (mask & INT_STATUSNAK) ? " ep0snak" : "",
+                  (mask & INT_STATUS) ? " ep0status" : "",
+
+                  (mask & INT_SETUP) ? " setup" : "",
+                  (mask & INT_ENDPOINT0) ? " ep0" : "",
+                  (mask & INT_USBRESET) ? " reset" : "",
+                  (mask & INT_SUSPEND) ? " suspend" : "");
+}
+
+static const char *udc_ep_state(enum ep0state state)
+{
+       switch (state) {
+       case EP0_DISCONNECT:
+               return "ep0_disconnect";
+       case EP0_IDLE:
+               return "ep0_idle";
+       case EP0_IN:
+               return "ep0_in";
+       case EP0_OUT:
+               return "ep0_out";
+       case EP0_STATUS:
+               return "ep0_status";
+       case EP0_STALL:
+               return "ep0_stall";
+       case EP0_SUSPEND:
+               return "ep0_suspend";
+       }
+
+       return "ep0_?";
 }
 
+static const char *udc_ep_status(u32 status)
+{
+       switch (status & EPxSTATUS_EP_MASK) {
+       case EPxSTATUS_EP_READY:
+               return "ready";
+       case EPxSTATUS_EP_DATAIN:
+               return "packet";
+       case EPxSTATUS_EP_FULL:
+               return "full";
+       case EPxSTATUS_EP_TX_ERR:       /* host will retry */
+               return "tx_err";
+       case EPxSTATUS_EP_RX_ERR:
+               return "rx_err";
+       case EPxSTATUS_EP_BUSY:         /* ep0 only */
+               return "busy";
+       case EPxSTATUS_EP_STALL:
+               return "stall";
+       case EPxSTATUS_EP_INVALID:      /* these "can't happen" */
+               return "invalid";
+       }
+
+       return "?";
+}
 
 static int udc_proc_read(struct seq_file *m, void *v)
 {
@@ -1068,29 +1112,18 @@ static int udc_proc_read(struct seq_file *m, void *v)
        tmp = readl(&regs->power_detect);
        is_usb_connected = tmp & PW_DETECT;
        seq_printf(m,
-               "%s - %s\n"
-               "%s version: %s %s\n"
-               "Gadget driver: %s\n"
-               "Host %s, %s\n"
-               "\n",
-               pci_name(dev->pdev), driver_desc,
-               driver_name, DRIVER_VERSION, dmastr(),
-               dev->driver ? dev->driver->driver.name : "(none)",
-               is_usb_connected
-                       ? ((tmp & PW_PULLUP) ? "full speed" : "powered")
-                       : "disconnected",
-               ({const char *state;
-               switch(dev->ep0state){
-               case EP0_DISCONNECT:    state = "ep0_disconnect"; break;
-               case EP0_IDLE:          state = "ep0_idle"; break;
-               case EP0_IN:            state = "ep0_in"; break;
-               case EP0_OUT:           state = "ep0_out"; break;
-               case EP0_STATUS:        state = "ep0_status"; break;
-               case EP0_STALL:         state = "ep0_stall"; break;
-               case EP0_SUSPEND:       state = "ep0_suspend"; break;
-               default:                state = "ep0_?"; break;
-               } state; })
-               );
+                  "%s - %s\n"
+                  "%s version: %s %s\n"
+                  "Gadget driver: %s\n"
+                  "Host %s, %s\n"
+                  "\n",
+                  pci_name(dev->pdev), driver_desc,
+                  driver_name, DRIVER_VERSION, dmastr(),
+                  dev->driver ? dev->driver->driver.name : "(none)",
+                  is_usb_connected
+                          ? ((tmp & PW_PULLUP) ? "full speed" : "powered")
+                          : "disconnected",
+                  udc_ep_state(dev->ep0state));
 
        dump_intmask(m, "int_status", readl(&regs->int_status));
        dump_intmask(m, "int_enable", readl(&regs->int_enable));
@@ -1099,31 +1132,30 @@ static int udc_proc_read(struct seq_file *m, void *v)
                goto done;
 
        /* registers for (active) device and ep0 */
-       if (seq_printf(m, "\nirqs %lu\ndataset %02x "
-                       "single.bcs %02x.%02x state %x addr %u\n",
-                       dev->irqs, readl(&regs->DataSet),
-                       readl(&regs->EPxSingle), readl(&regs->EPxBCS),
-                       readl(&regs->UsbState),
-                       readl(&regs->address)) < 0)
+       seq_printf(m, "\nirqs %lu\ndataset %02x single.bcs %02x.%02x state %x addr %u\n",
+                  dev->irqs, readl(&regs->DataSet),
+                  readl(&regs->EPxSingle), readl(&regs->EPxBCS),
+                  readl(&regs->UsbState),
+                  readl(&regs->address));
+       if (seq_has_overflowed(m))
                goto done;
 
        tmp = readl(&regs->dma_master);
-       if (seq_printf(m,
-               "dma %03X =" EIGHTBITS "%s %s\n", tmp,
-               (tmp & MST_EOPB_DIS) ? " eopb-" : "",
-               (tmp & MST_EOPB_ENA) ? " eopb+" : "",
-               (tmp & MST_TIMEOUT_DIS) ? " tmo-" : "",
-               (tmp & MST_TIMEOUT_ENA) ? " tmo+" : "",
-
-               (tmp & MST_RD_EOPB) ? " eopb" : "",
-               (tmp & MST_RD_RESET) ? " in_reset" : "",
-               (tmp & MST_WR_RESET) ? " out_reset" : "",
-               (tmp & MST_RD_ENA) ? " IN" : "",
-
-               (tmp & MST_WR_ENA) ? " OUT" : "",
-               (tmp & MST_CONNECTION)
-                       ? "ep1in/ep2out"
-                       : "ep1out/ep2in") < 0)
+       seq_printf(m, "dma %03X =" EIGHTBITS "%s %s\n",
+                  tmp,
+                  (tmp & MST_EOPB_DIS) ? " eopb-" : "",
+                  (tmp & MST_EOPB_ENA) ? " eopb+" : "",
+                  (tmp & MST_TIMEOUT_DIS) ? " tmo-" : "",
+                  (tmp & MST_TIMEOUT_ENA) ? " tmo+" : "",
+
+                  (tmp & MST_RD_EOPB) ? " eopb" : "",
+                  (tmp & MST_RD_RESET) ? " in_reset" : "",
+                  (tmp & MST_WR_RESET) ? " out_reset" : "",
+                  (tmp & MST_RD_ENA) ? " IN" : "",
+
+                  (tmp & MST_WR_ENA) ? " OUT" : "",
+                  (tmp & MST_CONNECTION) ? "ep1in/ep2out" : "ep1out/ep2in");
+       if (seq_has_overflowed(m))
                goto done;
 
        /* dump endpoint queues */
@@ -1135,44 +1167,23 @@ static int udc_proc_read(struct seq_file *m, void *v)
                        continue;
 
                tmp = readl(ep->reg_status);
-               if (seq_printf(m,
-                       "%s %s max %u %s, irqs %lu, "
-                       "status %02x (%s) " FOURBITS "\n",
-                       ep->ep.name,
-                       ep->is_in ? "in" : "out",
-                       ep->ep.maxpacket,
-                       ep->dma ? "dma" : "pio",
-                       ep->irqs,
-                       tmp, ({ char *s;
-                       switch (tmp & EPxSTATUS_EP_MASK) {
-                       case EPxSTATUS_EP_READY:
-                               s = "ready"; break;
-                       case EPxSTATUS_EP_DATAIN:
-                               s = "packet"; break;
-                       case EPxSTATUS_EP_FULL:
-                               s = "full"; break;
-                       case EPxSTATUS_EP_TX_ERR:       // host will retry
-                               s = "tx_err"; break;
-                       case EPxSTATUS_EP_RX_ERR:
-                               s = "rx_err"; break;
-                       case EPxSTATUS_EP_BUSY:         /* ep0 only */
-                               s = "busy"; break;
-                       case EPxSTATUS_EP_STALL:
-                               s = "stall"; break;
-                       case EPxSTATUS_EP_INVALID:      // these "can't happen"
-                               s = "invalid"; break;
-                       default:
-                               s = "?"; break;
-                       } s; }),
-                       (tmp & EPxSTATUS_TOGGLE) ? "data1" : "data0",
-                       (tmp & EPxSTATUS_SUSPEND) ? " suspend" : "",
-                       (tmp & EPxSTATUS_FIFO_DISABLE) ? " disable" : "",
-                       (tmp & EPxSTATUS_STAGE_ERROR) ? " ep0stat" : ""
-                       ) < 0)
+               seq_printf(m, "%s %s max %u %s, irqs %lu, status %02x (%s) " FOURBITS "\n",
+                          ep->ep.name,
+                          ep->is_in ? "in" : "out",
+                          ep->ep.maxpacket,
+                          ep->dma ? "dma" : "pio",
+                          ep->irqs,
+                          tmp, udc_ep_status(tmp),
+                          (tmp & EPxSTATUS_TOGGLE) ? "data1" : "data0",
+                          (tmp & EPxSTATUS_SUSPEND) ? " suspend" : "",
+                          (tmp & EPxSTATUS_FIFO_DISABLE) ? " disable" : "",
+                          (tmp & EPxSTATUS_STAGE_ERROR) ? " ep0stat" : "");
+               if (seq_has_overflowed(m))
                        goto done;
 
                if (list_empty(&ep->queue)) {
-                       if (seq_puts(m, "\t(nothing queued)\n") < 0)
+                       seq_puts(m, "\t(nothing queued)\n");
+                       if (seq_has_overflowed(m))
                                goto done;
                        continue;
                }
@@ -1187,10 +1198,10 @@ static int udc_proc_read(struct seq_file *m, void *v)
                        } else
                                tmp = req->req.actual;
 
-                       if (seq_printf(m,
-                               "\treq %p len %u/%u buf %p\n",
-                               &req->req, tmp, req->req.length,
-                               req->req.buf) < 0)
+                       seq_printf(m, "\treq %p len %u/%u buf %p\n",
+                                  &req->req, tmp, req->req.length,
+                                  req->req.buf);
+                       if (seq_has_overflowed(m))
                                goto done;
                }
        }
index 27fd41333f71ffcb31c24ffe05f71a48d988c20f..3b6a7852822d4aca3832876dabae212241268efd 100644 (file)
@@ -1803,23 +1803,14 @@ static int lpc32xx_ep_queue(struct usb_ep *_ep,
        req = container_of(_req, struct lpc32xx_request, req);
        ep = container_of(_ep, struct lpc32xx_ep, ep);
 
-       if (!_req || !_req->complete || !_req->buf ||
+       if (!_ep || !_req || !_req->complete || !_req->buf ||
            !list_empty(&req->queue))
                return -EINVAL;
 
        udc = ep->udc;
 
-       if (!_ep) {
-               dev_dbg(udc->dev, "invalid ep\n");
-               return -EINVAL;
-       }
-
-
-       if ((!udc) || (!udc->driver) ||
-           (udc->gadget.speed == USB_SPEED_UNKNOWN)) {
-               dev_dbg(udc->dev, "invalid device\n");
-               return -EINVAL;
-       }
+       if (udc->gadget.speed == USB_SPEED_UNKNOWN)
+               return -EPIPE;
 
        if (ep->lep) {
                struct lpc32xx_usbd_dd_gad *dd;
index d2c0bf65e345fb55b288cbc1274fa3c8a2b92aed..9871b90195ad8eea42f3746946d740a248ef9f2c 100644 (file)
@@ -80,6 +80,13 @@ static const char *const ep_name[] = {
        "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",
+};
+
 /* 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
@@ -138,31 +145,44 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
        u32                     max, tmp;
        unsigned long           flags;
        static const u32 ep_key[9] = { 1, 0, 1, 0, 1, 1, 0, 1, 0 };
+       int ret = 0;
 
        ep = container_of(_ep, struct net2280_ep, ep);
        if (!_ep || !desc || ep->desc || _ep->name == ep0name ||
-                       desc->bDescriptorType != USB_DT_ENDPOINT)
+                       desc->bDescriptorType != USB_DT_ENDPOINT) {
+               pr_err("%s: failed at line=%d\n", __func__, __LINE__);
                return -EINVAL;
+       }
        dev = ep->dev;
-       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+               ret = -ESHUTDOWN;
+               goto print_err;
+       }
 
        /* erratum 0119 workaround ties up an endpoint number */
-       if ((desc->bEndpointAddress & 0x0f) == EP_DONTUSE)
-               return -EDOM;
+       if ((desc->bEndpointAddress & 0x0f) == EP_DONTUSE) {
+               ret = -EDOM;
+               goto print_err;
+       }
 
        if (dev->quirks & PLX_SUPERSPEED) {
-               if ((desc->bEndpointAddress & 0x0f) >= 0x0c)
-                       return -EDOM;
+               if ((desc->bEndpointAddress & 0x0f) >= 0x0c) {
+                       ret = -EDOM;
+                       goto print_err;
+               }
                ep->is_in = !!usb_endpoint_dir_in(desc);
-               if (dev->enhanced_mode && ep->is_in && ep_key[ep->num])
-                       return -EINVAL;
+               if (dev->enhanced_mode && ep->is_in && ep_key[ep->num]) {
+                       ret = -EINVAL;
+                       goto print_err;
+               }
        }
 
        /* sanity check ep-e/ep-f since their fifos are small */
        max = usb_endpoint_maxp(desc) & 0x1fff;
-       if (ep->num > 4 && max > 64 && (dev->quirks & PLX_LEGACY))
-               return -ERANGE;
+       if (ep->num > 4 && max > 64 && (dev->quirks & PLX_LEGACY)) {
+               ret = -ERANGE;
+               goto print_err;
+       }
 
        spin_lock_irqsave(&dev->lock, flags);
        _ep->maxpacket = max & 0x7ff;
@@ -192,7 +212,8 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
                    (dev->gadget.speed == USB_SPEED_HIGH && max != 512) ||
                    (dev->gadget.speed == USB_SPEED_FULL && max > 64)) {
                        spin_unlock_irqrestore(&dev->lock, flags);
-                       return -ERANGE;
+                       ret = -ERANGE;
+                       goto print_err;
                }
        }
        ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC);
@@ -271,7 +292,11 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 
        /* pci writes may still be posted */
        spin_unlock_irqrestore(&dev->lock, flags);
-       return 0;
+       return ret;
+
+print_err:
+       dev_err(&ep->dev->pdev->dev, "%s: error=%d\n", __func__, ret);
+       return ret;
 }
 
 static int handshake(u32 __iomem *ptr, u32 mask, u32 done, int usec)
@@ -426,9 +451,10 @@ static int net2280_disable(struct usb_ep *_ep)
        unsigned long           flags;
 
        ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || !ep->desc || _ep->name == ep0name)
+       if (!_ep || !ep->desc || _ep->name == ep0name) {
+               pr_err("%s: Invalid ep=%p or ep->desc\n", __func__, _ep);
                return -EINVAL;
-
+       }
        spin_lock_irqsave(&ep->dev->lock, flags);
        nuke(ep);
 
@@ -458,8 +484,10 @@ static struct usb_request
        struct net2280_ep       *ep;
        struct net2280_request  *req;
 
-       if (!_ep)
+       if (!_ep) {
+               pr_err("%s: Invalid ep\n", __func__);
                return NULL;
+       }
        ep = container_of(_ep, struct net2280_ep, ep);
 
        req = kzalloc(sizeof(*req), gfp_flags);
@@ -491,8 +519,11 @@ static void net2280_free_request(struct usb_ep *_ep, struct usb_request *_req)
        struct net2280_request  *req;
 
        ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || !_req)
+       if (!_ep || !_req) {
+               dev_err(&ep->dev->pdev->dev, "%s: Inavlid ep=%p or req=%p\n",
+                                                       __func__, _ep, _req);
                return;
+       }
 
        req = container_of(_req, struct net2280_request, req);
        WARN_ON(!list_empty(&req->queue));
@@ -896,35 +927,44 @@ net2280_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
        struct net2280_ep       *ep;
        struct net2280          *dev;
        unsigned long           flags;
+       int ret = 0;
 
        /* we always require a cpu-view buffer, so that we can
         * always use pio (as fallback or whatever).
         */
-       req = container_of(_req, struct net2280_request, req);
-       if (!_req || !_req->complete || !_req->buf ||
-                               !list_empty(&req->queue))
-               return -EINVAL;
-       if (_req->length > (~0 & DMA_BYTE_COUNT_MASK))
-               return -EDOM;
        ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0))
+       if (!_ep || (!ep->desc && ep->num != 0)) {
+               pr_err("%s: Invalid ep=%p or ep->desc\n", __func__, _ep);
                return -EINVAL;
+       }
+       req = container_of(_req, struct net2280_request, req);
+       if (!_req || !_req->complete || !_req->buf ||
+                               !list_empty(&req->queue)) {
+               ret = -EINVAL;
+               goto print_err;
+       }
+       if (_req->length > (~0 & DMA_BYTE_COUNT_MASK)) {
+               ret = -EDOM;
+               goto print_err;
+       }
        dev = ep->dev;
-       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+               ret = -ESHUTDOWN;
+               goto print_err;
+       }
 
        /* FIXME implement PIO fallback for ZLPs with DMA */
-       if (ep->dma && _req->length == 0)
-               return -EOPNOTSUPP;
+       if (ep->dma && _req->length == 0) {
+               ret = -EOPNOTSUPP;
+               goto print_err;
+       }
 
        /* set up dma mapping in case the caller didn't */
        if (ep->dma) {
-               int ret;
-
                ret = usb_gadget_map_request(&dev->gadget, _req,
                                ep->is_in);
                if (ret)
-                       return ret;
+                       goto print_err;
        }
 
        ep_vdbg(dev, "%s queue req %p, len %d buf %p\n",
@@ -1013,7 +1053,11 @@ done:
        spin_unlock_irqrestore(&dev->lock, flags);
 
        /* pci writes may still be posted */
-       return 0;
+       return ret;
+
+print_err:
+       dev_err(&ep->dev->pdev->dev, "%s: error=%d\n", __func__, ret);
+       return ret;
 }
 
 static inline void
@@ -1134,8 +1178,11 @@ static int net2280_dequeue(struct usb_ep *_ep, struct usb_request *_req)
        int                     stopped;
 
        ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0) || !_req)
+       if (!_ep || (!ep->desc && ep->num != 0) || !_req) {
+               pr_err("%s: Invalid ep=%p or ep->desc or req=%p\n",
+                                               __func__, _ep, _req);
                return -EINVAL;
+       }
 
        spin_lock_irqsave(&ep->dev->lock, flags);
        stopped = ep->stopped;
@@ -1157,6 +1204,8 @@ static int net2280_dequeue(struct usb_ep *_ep, struct usb_request *_req)
        }
        if (&req->req != _req) {
                spin_unlock_irqrestore(&ep->dev->lock, flags);
+               dev_err(&ep->dev->pdev->dev, "%s: Request mismatch\n",
+                                                               __func__);
                return -EINVAL;
        }
 
@@ -1214,20 +1263,28 @@ net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
        int                     retval = 0;
 
        ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0))
+       if (!_ep || (!ep->desc && ep->num != 0)) {
+               pr_err("%s: Invalid ep=%p or ep->desc\n", __func__, _ep);
                return -EINVAL;
-       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-               return -ESHUTDOWN;
+       }
+       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN) {
+               retval = -ESHUTDOWN;
+               goto print_err;
+       }
        if (ep->desc /* not ep0 */ && (ep->desc->bmAttributes & 0x03)
-                                               == USB_ENDPOINT_XFER_ISOC)
-               return -EINVAL;
+                                               == USB_ENDPOINT_XFER_ISOC) {
+               retval = -EINVAL;
+               goto print_err;
+       }
 
        spin_lock_irqsave(&ep->dev->lock, flags);
-       if (!list_empty(&ep->queue))
+       if (!list_empty(&ep->queue)) {
                retval = -EAGAIN;
-       else if (ep->is_in && value && net2280_fifo_status(_ep) != 0)
+               goto print_unlock;
+       } else if (ep->is_in && value && net2280_fifo_status(_ep) != 0) {
                retval = -EAGAIN;
-       else {
+               goto print_unlock;
+       } else {
                ep_vdbg(ep->dev, "%s %s %s\n", _ep->name,
                                value ? "set" : "clear",
                                wedged ? "wedge" : "halt");
@@ -1251,6 +1308,12 @@ net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
        spin_unlock_irqrestore(&ep->dev->lock, flags);
 
        return retval;
+
+print_unlock:
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+print_err:
+       dev_err(&ep->dev->pdev->dev, "%s: error=%d\n", __func__, retval);
+       return retval;
 }
 
 static int net2280_set_halt(struct usb_ep *_ep, int value)
@@ -1260,8 +1323,10 @@ static int net2280_set_halt(struct usb_ep *_ep, int value)
 
 static int net2280_set_wedge(struct usb_ep *_ep)
 {
-       if (!_ep || _ep->name == ep0name)
+       if (!_ep || _ep->name == ep0name) {
+               pr_err("%s: Invalid ep=%p or ep0\n", __func__, _ep);
                return -EINVAL;
+       }
        return net2280_set_halt_and_wedge(_ep, 1, 1);
 }
 
@@ -1271,14 +1336,22 @@ static int net2280_fifo_status(struct usb_ep *_ep)
        u32                     avail;
 
        ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0))
+       if (!_ep || (!ep->desc && ep->num != 0)) {
+               pr_err("%s: Invalid ep=%p or ep->desc\n", __func__, _ep);
                return -ENODEV;
-       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+       }
+       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN) {
+               dev_err(&ep->dev->pdev->dev,
+                       "%s: Invalid driver=%p or speed=%d\n",
+                       __func__, ep->dev->driver, ep->dev->gadget.speed);
                return -ESHUTDOWN;
+       }
 
        avail = readl(&ep->regs->ep_avail) & (BIT(12) - 1);
-       if (avail > ep->fifo_size)
+       if (avail > ep->fifo_size) {
+               dev_err(&ep->dev->pdev->dev, "%s: Fifo overflow\n", __func__);
                return -EOVERFLOW;
+       }
        if (ep->is_in)
                avail = ep->fifo_size - avail;
        return avail;
@@ -1289,10 +1362,16 @@ static void net2280_fifo_flush(struct usb_ep *_ep)
        struct net2280_ep       *ep;
 
        ep = container_of(_ep, struct net2280_ep, ep);
-       if (!_ep || (!ep->desc && ep->num != 0))
+       if (!_ep || (!ep->desc && ep->num != 0)) {
+               pr_err("%s: Invalid ep=%p or ep->desc\n", __func__, _ep);
                return;
-       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+       }
+       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN) {
+               dev_err(&ep->dev->pdev->dev,
+                       "%s: Invalid driver=%p or speed=%d\n",
+                       __func__, ep->dev->driver, ep->dev->gadget.speed);
                return;
+       }
 
        writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat);
        (void) readl(&ep->regs->ep_rsp);
@@ -1977,7 +2056,7 @@ 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 = ep_name[i];
+               ep->ep.name = dev->enhanced_mode ? ep_name_adv[i] : ep_name[i];
                ep->dev = dev;
                ep->num = i;
 
@@ -1989,11 +2068,9 @@ static void usb_reinit_338x(struct net2280 *dev)
                        ep->regs = (struct net2280_ep_regs __iomem *)
                                (((void __iomem *)&dev->epregs[ne[i]]) +
                                ep_reg_addr[i]);
-                       ep->fiforegs = &dev->fiforegs[i];
                } else {
                        ep->cfg = &dev->epregs[i];
                        ep->regs = &dev->epregs[i];
-                       ep->fiforegs = &dev->fiforegs[i];
                }
 
                ep->fifo_size = (i != 0) ? 2048 : 512;
@@ -2186,7 +2263,6 @@ static int net2280_start(struct usb_gadget *_gadget,
                dev->ep[i].irqs = 0;
 
        /* hook up the driver ... */
-       dev->softconnect = 1;
        driver->driver.bus = NULL;
        dev->driver = driver;
 
@@ -3052,6 +3128,8 @@ next_endpoints:
                BIT(PCI_RETRY_ABORT_INTERRUPT))
 
 static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
+__releases(dev->lock)
+__acquires(dev->lock)
 {
        struct net2280_ep       *ep;
        u32                     tmp, num, mask, scratch;
@@ -3373,8 +3451,6 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                u32 usbstat;
                dev->usb_ext = (struct usb338x_usb_ext_regs __iomem *)
                                                        (base + 0x00b4);
-               dev->fiforegs = (struct usb338x_fifo_regs __iomem *)
-                                                       (base + 0x0500);
                dev->llregs = (struct usb338x_ll_regs __iomem *)
                                                        (base + 0x0700);
                dev->ll_lfps_regs = (struct usb338x_ll_lfps_regs __iomem *)
index ac8d5a20a378a9de074901b8667bb721f8e86cdc..4dff60d34f732097752e59360e0edcf7e5eb90b4 100644 (file)
@@ -96,7 +96,6 @@ struct net2280_ep {
        struct net2280_ep_regs                  __iomem *regs;
        struct net2280_dma_regs                 __iomem *dma;
        struct net2280_dma                      *dummy;
-       struct usb338x_fifo_regs __iomem *fiforegs;
        dma_addr_t                              td_dma; /* of dummy */
        struct net2280                          *dev;
        unsigned long                           irqs;
@@ -181,7 +180,6 @@ struct net2280 {
        struct net2280_dma_regs         __iomem *dma;
        struct net2280_dep_regs         __iomem *dep;
        struct net2280_ep_regs          __iomem *epregs;
-       struct usb338x_fifo_regs        __iomem *fiforegs;
        struct usb338x_ll_regs          __iomem *llregs;
        struct usb338x_ll_lfps_regs     __iomem *ll_lfps_regs;
        struct usb338x_ll_tsn_regs      __iomem *ll_tsn_regs;
index 6a855fc9bd84cf7716785e7ba62a60b7cb556882..b51226abade625d2ac0f34de68a72842d9c6742b 100644 (file)
@@ -93,50 +93,46 @@ static void handle_ep(struct pxa_ep *ep);
 static int state_dbg_show(struct seq_file *s, void *p)
 {
        struct pxa_udc *udc = s->private;
-       int pos = 0, ret;
        u32 tmp;
 
-       ret = -ENODEV;
        if (!udc->driver)
-               goto out;
+               return -ENODEV;
 
        /* basic device status */
-       pos += seq_printf(s, DRIVER_DESC "\n"
-                        "%s version: %s\nGadget driver: %s\n",
-                        driver_name, DRIVER_VERSION,
-                        udc->driver ? udc->driver->driver.name : "(none)");
+       seq_printf(s, DRIVER_DESC "\n"
+                  "%s version: %s\n"
+                  "Gadget driver: %s\n",
+                  driver_name, DRIVER_VERSION,
+                  udc->driver ? udc->driver->driver.name : "(none)");
 
        tmp = udc_readl(udc, UDCCR);
-       pos += seq_printf(s,
-                        "udccr=0x%0x(%s%s%s%s%s%s%s%s%s%s), "
-                        "con=%d,inter=%d,altinter=%d\n", tmp,
-                        (tmp & UDCCR_OEN) ? " oen":"",
-                        (tmp & UDCCR_AALTHNP) ? " aalthnp":"",
-                        (tmp & UDCCR_AHNP) ? " rem" : "",
-                        (tmp & UDCCR_BHNP) ? " rstir" : "",
-                        (tmp & UDCCR_DWRE) ? " dwre" : "",
-                        (tmp & UDCCR_SMAC) ? " smac" : "",
-                        (tmp & UDCCR_EMCE) ? " emce" : "",
-                        (tmp & UDCCR_UDR) ? " udr" : "",
-                        (tmp & UDCCR_UDA) ? " uda" : "",
-                        (tmp & UDCCR_UDE) ? " ude" : "",
-                        (tmp & UDCCR_ACN) >> UDCCR_ACN_S,
-                        (tmp & UDCCR_AIN) >> UDCCR_AIN_S,
-                        (tmp & UDCCR_AAISN) >> UDCCR_AAISN_S);
+       seq_printf(s,
+                  "udccr=0x%0x(%s%s%s%s%s%s%s%s%s%s), con=%d,inter=%d,altinter=%d\n",
+                  tmp,
+                  (tmp & UDCCR_OEN) ? " oen":"",
+                  (tmp & UDCCR_AALTHNP) ? " aalthnp":"",
+                  (tmp & UDCCR_AHNP) ? " rem" : "",
+                  (tmp & UDCCR_BHNP) ? " rstir" : "",
+                  (tmp & UDCCR_DWRE) ? " dwre" : "",
+                  (tmp & UDCCR_SMAC) ? " smac" : "",
+                  (tmp & UDCCR_EMCE) ? " emce" : "",
+                  (tmp & UDCCR_UDR) ? " udr" : "",
+                  (tmp & UDCCR_UDA) ? " uda" : "",
+                  (tmp & UDCCR_UDE) ? " ude" : "",
+                  (tmp & UDCCR_ACN) >> UDCCR_ACN_S,
+                  (tmp & UDCCR_AIN) >> UDCCR_AIN_S,
+                  (tmp & UDCCR_AAISN) >> UDCCR_AAISN_S);
        /* registers for device and ep0 */
-       pos += seq_printf(s, "udcicr0=0x%08x udcicr1=0x%08x\n",
-                       udc_readl(udc, UDCICR0), udc_readl(udc, UDCICR1));
-       pos += seq_printf(s, "udcisr0=0x%08x udcisr1=0x%08x\n",
-                       udc_readl(udc, UDCISR0), udc_readl(udc, UDCISR1));
-       pos += seq_printf(s, "udcfnr=%d\n", udc_readl(udc, UDCFNR));
-       pos += seq_printf(s, "irqs: reset=%lu, suspend=%lu, resume=%lu, "
-                       "reconfig=%lu\n",
-                       udc->stats.irqs_reset, udc->stats.irqs_suspend,
-                       udc->stats.irqs_resume, udc->stats.irqs_reconfig);
-
-       ret = 0;
-out:
-       return ret;
+       seq_printf(s, "udcicr0=0x%08x udcicr1=0x%08x\n",
+                  udc_readl(udc, UDCICR0), udc_readl(udc, UDCICR1));
+       seq_printf(s, "udcisr0=0x%08x udcisr1=0x%08x\n",
+                  udc_readl(udc, UDCISR0), udc_readl(udc, UDCISR1));
+       seq_printf(s, "udcfnr=%d\n", udc_readl(udc, UDCFNR));
+       seq_printf(s, "irqs: reset=%lu, suspend=%lu, resume=%lu, reconfig=%lu\n",
+                  udc->stats.irqs_reset, udc->stats.irqs_suspend,
+                  udc->stats.irqs_resume, udc->stats.irqs_reconfig);
+
+       return 0;
 }
 
 static int queues_dbg_show(struct seq_file *s, void *p)
@@ -144,75 +140,67 @@ static int queues_dbg_show(struct seq_file *s, void *p)
        struct pxa_udc *udc = s->private;
        struct pxa_ep *ep;
        struct pxa27x_request *req;
-       int pos = 0, i, maxpkt, ret;
+       int i, maxpkt;
 
-       ret = -ENODEV;
        if (!udc->driver)
-               goto out;
+               return -ENODEV;
 
        /* dump endpoint queues */
        for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
                ep = &udc->pxa_ep[i];
                maxpkt = ep->fifo_size;
-               pos += seq_printf(s,  "%-12s max_pkt=%d %s\n",
-                               EPNAME(ep), maxpkt, "pio");
+               seq_printf(s,  "%-12s max_pkt=%d %s\n",
+                          EPNAME(ep), maxpkt, "pio");
 
                if (list_empty(&ep->queue)) {
-                       pos += seq_printf(s, "\t(nothing queued)\n");
+                       seq_puts(s, "\t(nothing queued)\n");
                        continue;
                }
 
                list_for_each_entry(req, &ep->queue, queue) {
-                       pos += seq_printf(s,  "\treq %p len %d/%d buf %p\n",
-                                       &req->req, req->req.actual,
-                                       req->req.length, req->req.buf);
+                       seq_printf(s,  "\treq %p len %d/%d buf %p\n",
+                                  &req->req, req->req.actual,
+                                  req->req.length, req->req.buf);
                }
        }
 
-       ret = 0;
-out:
-       return ret;
+       return 0;
 }
 
 static int eps_dbg_show(struct seq_file *s, void *p)
 {
        struct pxa_udc *udc = s->private;
        struct pxa_ep *ep;
-       int pos = 0, i, ret;
+       int i;
        u32 tmp;
 
-       ret = -ENODEV;
        if (!udc->driver)
-               goto out;
+               return -ENODEV;
 
        ep = &udc->pxa_ep[0];
        tmp = udc_ep_readl(ep, UDCCSR);
-       pos += seq_printf(s, "udccsr0=0x%03x(%s%s%s%s%s%s%s)\n", tmp,
-                        (tmp & UDCCSR0_SA) ? " sa" : "",
-                        (tmp & UDCCSR0_RNE) ? " rne" : "",
-                        (tmp & UDCCSR0_FST) ? " fst" : "",
-                        (tmp & UDCCSR0_SST) ? " sst" : "",
-                        (tmp & UDCCSR0_DME) ? " dme" : "",
-                        (tmp & UDCCSR0_IPR) ? " ipr" : "",
-                        (tmp & UDCCSR0_OPC) ? " opc" : "");
+       seq_printf(s, "udccsr0=0x%03x(%s%s%s%s%s%s%s)\n",
+                  tmp,
+                  (tmp & UDCCSR0_SA) ? " sa" : "",
+                  (tmp & UDCCSR0_RNE) ? " rne" : "",
+                  (tmp & UDCCSR0_FST) ? " fst" : "",
+                  (tmp & UDCCSR0_SST) ? " sst" : "",
+                  (tmp & UDCCSR0_DME) ? " dme" : "",
+                  (tmp & UDCCSR0_IPR) ? " ipr" : "",
+                  (tmp & UDCCSR0_OPC) ? " opc" : "");
        for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
                ep = &udc->pxa_ep[i];
                tmp = i? udc_ep_readl(ep, UDCCR) : udc_readl(udc, UDCCR);
-               pos += seq_printf(s, "%-12s: "
-                               "IN %lu(%lu reqs), OUT %lu(%lu reqs), "
-                               "irqs=%lu, udccr=0x%08x, udccsr=0x%03x, "
-                               "udcbcr=%d\n",
-                               EPNAME(ep),
-                               ep->stats.in_bytes, ep->stats.in_ops,
-                               ep->stats.out_bytes, ep->stats.out_ops,
-                               ep->stats.irqs,
-                               tmp, udc_ep_readl(ep, UDCCSR),
-                               udc_ep_readl(ep, UDCBCR));
+               seq_printf(s, "%-12s: IN %lu(%lu reqs), OUT %lu(%lu reqs), irqs=%lu, udccr=0x%08x, udccsr=0x%03x, udcbcr=%d\n",
+                          EPNAME(ep),
+                          ep->stats.in_bytes, ep->stats.in_ops,
+                          ep->stats.out_bytes, ep->stats.out_ops,
+                          ep->stats.irqs,
+                          tmp, udc_ep_readl(ep, UDCCSR),
+                          udc_ep_readl(ep, UDCBCR));
        }
 
-       ret = 0;
-out:
-       return ret;
+       return 0;
 }
 
 static int eps_dbg_open(struct inode *inode, struct file *file)
@@ -2399,7 +2387,7 @@ static struct pxa_udc memory = {
 };
 
 #if defined(CONFIG_OF)
-static struct of_device_id udc_pxa_dt_ids[] = {
+static const struct of_device_id udc_pxa_dt_ids[] = {
        { .compatible = "marvell,pxa270-udc" },
        {}
 };
index 5a81cb086b99353ef7d8d3e12f8cfdbff1eb5a45..d69c35558f6852beecd1bfc85acee35c26781ec8 100644 (file)
@@ -35,6 +35,8 @@
  * @dev - the child device to the actual controller
  * @gadget - the gadget. For use by the class code
  * @list - for use by the udc class driver
+ * @vbus - for udcs who care about vbus status, this value is real vbus status;
+ * for udcs who do not care about vbus status, this value is always true
  *
  * This represents the internal data structure which is used by the UDC-class
  * to hold information about udc driver and gadget together.
@@ -44,6 +46,7 @@ struct usb_udc {
        struct usb_gadget               *gadget;
        struct device                   dev;
        struct list_head                list;
+       bool                            vbus;
 };
 
 static struct class *udc_class;
@@ -128,21 +131,11 @@ EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
 
 static void usb_gadget_state_work(struct work_struct *work)
 {
-       struct usb_gadget       *gadget = work_to_gadget(work);
-       struct usb_udc          *udc = NULL;
-
-       mutex_lock(&udc_lock);
-       list_for_each_entry(udc, &udc_list, list)
-               if (udc->gadget == gadget)
-                       goto found;
-       mutex_unlock(&udc_lock);
-
-       return;
-
-found:
-       mutex_unlock(&udc_lock);
+       struct usb_gadget *gadget = work_to_gadget(work);
+       struct usb_udc *udc = gadget->udc;
 
-       sysfs_notify(&udc->dev.kobj, NULL, "state");
+       if (udc)
+               sysfs_notify(&udc->dev.kobj, NULL, "state");
 }
 
 void usb_gadget_set_state(struct usb_gadget *gadget,
@@ -155,6 +148,34 @@ EXPORT_SYMBOL_GPL(usb_gadget_set_state);
 
 /* ------------------------------------------------------------------------- */
 
+static void usb_udc_connect_control(struct usb_udc *udc)
+{
+       if (udc->vbus)
+               usb_gadget_connect(udc->gadget);
+       else
+               usb_gadget_disconnect(udc->gadget);
+}
+
+/**
+ * usb_udc_vbus_handler - updates the udc core vbus status, and try to
+ * connect or disconnect gadget
+ * @gadget: The gadget which vbus change occurs
+ * @status: The vbus status
+ *
+ * The udc driver calls it when it wants to connect or disconnect gadget
+ * according to vbus status.
+ */
+void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status)
+{
+       struct usb_udc *udc = gadget->udc;
+
+       if (udc) {
+               udc->vbus = status;
+               usb_udc_connect_control(udc);
+       }
+}
+EXPORT_SYMBOL_GPL(usb_udc_vbus_handler);
+
 /**
  * usb_gadget_udc_reset - notifies the udc core that bus reset occurs
  * @gadget: The gadget which bus reset occurs
@@ -278,6 +299,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
                goto err3;
 
        udc->gadget = gadget;
+       gadget->udc = udc;
 
        mutex_lock(&udc_lock);
        list_add_tail(&udc->list, &udc_list);
@@ -287,6 +309,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
                goto err4;
 
        usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
+       udc->vbus = true;
 
        mutex_unlock(&udc_lock);
 
@@ -348,21 +371,14 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
  */
 void usb_del_gadget_udc(struct usb_gadget *gadget)
 {
-       struct usb_udc          *udc = NULL;
+       struct usb_udc *udc = gadget->udc;
 
-       mutex_lock(&udc_lock);
-       list_for_each_entry(udc, &udc_list, list)
-               if (udc->gadget == gadget)
-                       goto found;
-
-       dev_err(gadget->dev.parent, "gadget not registered.\n");
-       mutex_unlock(&udc_lock);
-
-       return;
+       if (!udc)
+               return;
 
-found:
        dev_vdbg(gadget->dev.parent, "unregistering gadget\n");
 
+       mutex_lock(&udc_lock);
        list_del(&udc->list);
        mutex_unlock(&udc_lock);
 
@@ -397,7 +413,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
                driver->unbind(udc->gadget);
                goto err1;
        }
-       usb_gadget_connect(udc->gadget);
+       usb_udc_connect_control(udc);
 
        kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
        return 0;
index 5ad60e46dc2b204926222fd2b4a6de401b41baec..197a6a3e613b29dc8c736ea42f9c6c191da327b1 100644 (file)
@@ -198,7 +198,7 @@ config USB_EHCI_HCD_AT91
 
 config USB_EHCI_MSM
        tristate "Support for Qualcomm QSD/MSM on-chip EHCI USB controller"
-       depends on ARCH_MSM || ARCH_QCOM
+       depends on ARCH_QCOM
        select USB_EHCI_ROOT_HUB_TT
        ---help---
          Enables support for the USB Host controller present on the
index 85e56d1abd2307a8620c6fcfa1211a4136f74faf..f4d88dfb26a7e5ca0200620e39210b1080a3f263 100644 (file)
@@ -792,12 +792,12 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                                        ehci->reset_done[i] == 0))
                                continue;
 
-                       /* start 20 msec resume signaling from this port,
-                        * and make hub_wq collect PORT_STAT_C_SUSPEND to
-                        * stop that signaling.  Use 5 ms extra for safety,
-                        * like usb_port_resume() does.
+                       /* start USB_RESUME_TIMEOUT msec resume signaling from
+                        * this port, and make hub_wq collect
+                        * PORT_STAT_C_SUSPEND to stop that signaling.
                         */
-                       ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
+                       ehci->reset_done[i] = jiffies +
+                               msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        set_bit(i, &ehci->resuming_ports);
                        ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
                        usb_hcd_start_port_resume(&hcd->self, i);
index 87cf86f38b363ff0f81dd66367769ff594d266bc..69208447d213e4bc613a25c7f82563b45b1d21d1 100644 (file)
@@ -471,10 +471,13 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
                ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
        }
 
-       /* msleep for 20ms only if code is trying to resume port */
+       /*
+        * msleep for USB_RESUME_TIMEOUT ms only if code is trying to resume
+        * port
+        */
        if (resume_needed) {
                spin_unlock_irq(&ehci->lock);
-               msleep(20);
+               msleep(USB_RESUME_TIMEOUT);
                spin_lock_irq(&ehci->lock);
                if (ehci->shutdown)
                        goto shutdown;
@@ -688,7 +691,7 @@ ehci_hub_descriptor (
        int             ports = HCS_N_PORTS (ehci->hcs_params);
        u16             temp;
 
-       desc->bDescriptorType = 0x29;
+       desc->bDescriptorType = USB_DT_HUB;
        desc->bPwrOn2PwrGood = 10;      /* ehci 1.0, 2.3.9 says 20ms max */
        desc->bHubContrCurrent = 0;
 
@@ -942,7 +945,7 @@ int ehci_hub_control(
                        temp &= ~PORT_WAKE_BITS;
                        ehci_writel(ehci, temp | PORT_RESUME, status_reg);
                        ehci->reset_done[wIndex] = jiffies
-                                       + msecs_to_jiffies(20);
+                                       + msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        set_bit(wIndex, &ehci->resuming_ports);
                        usb_hcd_start_port_resume(&hcd->self, wIndex);
                        break;
index f6eafecab15c508eed0fef4e332b437448516480..bfcbb9aa8816bb5a4c84bef1d525ca8d086c8c66 100644 (file)
 #define wrl(off, val)  writel_relaxed((val), hcd->regs + (off))
 
 #define USB_CMD                        0x140
+#define   USB_CMD_RUN          BIT(0)
+#define   USB_CMD_RESET                BIT(1)
 #define USB_MODE               0x1a8
+#define   USB_MODE_MASK                GENMASK(1, 0)
+#define   USB_MODE_DEVICE      0x2
+#define   USB_MODE_HOST                0x3
+#define   USB_MODE_SDIS                BIT(4)
 #define USB_CAUSE              0x310
 #define USB_MASK               0x314
 #define USB_WINDOW_CTRL(i)     (0x320 + ((i) << 4))
@@ -69,8 +75,8 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd)
        /*
         * Reset controller
         */
-       wrl(USB_CMD, rdl(USB_CMD) | 0x2);
-       while (rdl(USB_CMD) & 0x2);
+       wrl(USB_CMD, rdl(USB_CMD) | USB_CMD_RESET);
+       while (rdl(USB_CMD) & USB_CMD_RESET);
 
        /*
         * GL# USB-10: Set IPG for non start of frame packets
@@ -112,16 +118,16 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd)
        /*
         * Stop and reset controller
         */
-       wrl(USB_CMD, rdl(USB_CMD) & ~0x1);
-       wrl(USB_CMD, rdl(USB_CMD) | 0x2);
-       while (rdl(USB_CMD) & 0x2);
+       wrl(USB_CMD, rdl(USB_CMD) & ~USB_CMD_RUN);
+       wrl(USB_CMD, rdl(USB_CMD) | USB_CMD_RESET);
+       while (rdl(USB_CMD) & USB_CMD_RESET);
 
        /*
         * GL# USB-5 Streaming disable REG_USB_MODE[4]=1
         * TBD: This need to be done after each reset!
         * GL# USB-4 Setup USB Host mode
         */
-       wrl(USB_MODE, 0x13);
+       wrl(USB_MODE, USB_MODE_SDIS | USB_MODE_HOST);
 }
 
 static void
index 70116a65262cc70c829e7d0cd7d2e03e35da59fc..3bacdd7befe9b0c55dafa1e1d799ecb1f8df6535 100644 (file)
@@ -30,7 +30,7 @@
 /* virtual root hub specific descriptor */
 static u8 root_hub_des[] = {
        0x09, /* blength */
-       0x29, /* bDescriptorType;hub-descriptor */
+       USB_DT_HUB, /* bDescriptorType;hub-descriptor */
        0x01, /* bNbrPorts */
        HUB_CHAR_INDV_PORT_LPSM | HUB_CHAR_NO_OCPM, /* wHubCharacteristics */
        0x00, /* per-port power, no overcurrent */
index 475b21fd373baa6102be4b102b856098857dfdb8..000ed80ab592a0ce731023386a3636d3bd920976 100644 (file)
@@ -1509,7 +1509,7 @@ fotg210_hub_descriptor(
        int             ports = HCS_N_PORTS(fotg210->hcs_params);
        u16             temp;
 
-       desc->bDescriptorType = 0x29;
+       desc->bDescriptorType = USB_DT_HUB;
        desc->bPwrOn2PwrGood = 10;      /* fotg210 1.0, 2.3.9 says 20ms max */
        desc->bHubContrCurrent = 0;
 
@@ -1595,7 +1595,7 @@ static int fotg210_hub_control(
                        /* resume signaling for 20 msec */
                        fotg210_writel(fotg210, temp | PORT_RESUME, status_reg);
                        fotg210->reset_done[wIndex] = jiffies
-                                       + msecs_to_jiffies(20);
+                                       + msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        break;
                case USB_PORT_FEAT_C_SUSPEND:
                        clear_bit(wIndex, &fotg210->port_c_suspend);
index a83eefefffdad1cfe032b819938d4138d4bf6bab..00e492eaba6ad4f356709f8737b1b6b868d9f098 100644 (file)
@@ -1467,7 +1467,7 @@ fusbh200_hub_descriptor (
        int             ports = HCS_N_PORTS (fusbh200->hcs_params);
        u16             temp;
 
-       desc->bDescriptorType = 0x29;
+       desc->bDescriptorType = USB_DT_HUB;
        desc->bPwrOn2PwrGood = 10;      /* fusbh200 1.0, 2.3.9 says 20ms max */
        desc->bHubContrCurrent = 0;
 
@@ -1550,10 +1550,9 @@ static int fusbh200_hub_control (
                        if ((temp & PORT_PE) == 0)
                                goto error;
 
-                       /* resume signaling for 20 msec */
                        fusbh200_writel(fusbh200, temp | PORT_RESUME, status_reg);
                        fusbh200->reset_done[wIndex] = jiffies
-                                       + msecs_to_jiffies(20);
+                                       + msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        break;
                case USB_PORT_FEAT_C_SUSPEND:
                        clear_bit(wIndex, &fusbh200->port_c_suspend);
index 6a2ad550b1205f84e44477de15b1eb47ccf78086..f542045dc2a624fb8e0f3b82c55dc7a177fd3e75 100644 (file)
@@ -1474,7 +1474,7 @@ static int get_hub_descriptor(struct usb_hcd *hcd,
                              struct usb_hub_descriptor *desc)
 {
        struct imx21 *imx21 = hcd_to_imx21(hcd);
-       desc->bDescriptorType = 0x29;   /* HUB descriptor */
+       desc->bDescriptorType = USB_DT_HUB; /* HUB descriptor */
        desc->bHubContrCurrent = 0;
 
        desc->bNbrPorts = readl(imx21->regs + USBH_ROOTHUBA)
index 113d0cc6cc43d00707b985b227f232fd043f13e7..13181dcd98204b868aeafe9a00f72f3924b69abb 100644 (file)
@@ -943,7 +943,7 @@ static void isp116x_hub_descriptor(struct isp116x *isp116x,
 {
        u32 reg = isp116x->rhdesca;
 
-       desc->bDescriptorType = 0x29;
+       desc->bDescriptorType = USB_DT_HUB;
        desc->bDescLength = 9;
        desc->bHubContrCurrent = 0;
        desc->bNbrPorts = (u8) (reg & 0x3);
@@ -1490,7 +1490,7 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
        spin_unlock_irq(&isp116x->lock);
 
        hcd->state = HC_STATE_RESUMING;
-       msleep(20);
+       msleep(USB_RESUME_TIMEOUT);
 
        /* Go operational */
        spin_lock_irq(&isp116x->lock);
index b32ab60cad1ecd34946033afc1327972c8bbee84..6cf82ee460a68aec25e47b6e0086e1b3552c433f 100644 (file)
@@ -1538,7 +1538,7 @@ static void isp1362_hub_descriptor(struct isp1362_hcd *isp1362_hcd,
 
        DBG(3, "%s: enter\n", __func__);
 
-       desc->bDescriptorType = 0x29;
+       desc->bDescriptorType = USB_DT_HUB;
        desc->bDescLength = 9;
        desc->bHubContrCurrent = 0;
        desc->bNbrPorts = reg & 0x3;
index a98833cbfcf311193d420230de40f4a816b41b6b..fc1fd403973a8aa992ad7b61a88efe5dd301143d 100644 (file)
@@ -1659,7 +1659,7 @@ hub_descriptor(struct usb_hub_descriptor *desc)
        /*
         * See Table 11-13: Hub Descriptor in USB 2.0 spec.
         */
-       desc->bDescriptorType = 0x29;   /* hub descriptor */
+       desc->bDescriptorType = USB_DT_HUB; /* hub descriptor */
        desc->bDescLength = 9;
        desc->wHubCharacteristics = cpu_to_le16(HUB_CHAR_INDV_PORT_LPSM |
                                                HUB_CHAR_COMMON_OCPM);
index 7cce85a1f7dc170299e5aded49fed41b306b987f..15df00cceed91efe1cffe340e60eefa87d092828 100644 (file)
@@ -39,7 +39,6 @@
 struct ohci_at91_priv {
        struct clk *iclk;
        struct clk *fclk;
-       struct clk *uclk;
        struct clk *hclk;
        bool clocked;
        bool wakeup;            /* Saved wake-up state for resume */
@@ -64,10 +63,8 @@ static void at91_start_clock(struct ohci_at91_priv *ohci_at91)
 {
        if (ohci_at91->clocked)
                return;
-       if (IS_ENABLED(CONFIG_COMMON_CLK)) {
-               clk_set_rate(ohci_at91->uclk, 48000000);
-               clk_prepare_enable(ohci_at91->uclk);
-       }
+
+       clk_set_rate(ohci_at91->fclk, 48000000);
        clk_prepare_enable(ohci_at91->hclk);
        clk_prepare_enable(ohci_at91->iclk);
        clk_prepare_enable(ohci_at91->fclk);
@@ -78,11 +75,10 @@ static void at91_stop_clock(struct ohci_at91_priv *ohci_at91)
 {
        if (!ohci_at91->clocked)
                return;
+
        clk_disable_unprepare(ohci_at91->fclk);
        clk_disable_unprepare(ohci_at91->iclk);
        clk_disable_unprepare(ohci_at91->hclk);
-       if (IS_ENABLED(CONFIG_COMMON_CLK))
-               clk_disable_unprepare(ohci_at91->uclk);
        ohci_at91->clocked = false;
 }
 
@@ -191,14 +187,6 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
                retval = PTR_ERR(ohci_at91->hclk);
                goto err;
        }
-       if (IS_ENABLED(CONFIG_COMMON_CLK)) {
-               ohci_at91->uclk = devm_clk_get(dev, "usb_clk");
-               if (IS_ERR(ohci_at91->uclk)) {
-                       dev_err(dev, "failed to get uclk\n");
-                       retval = PTR_ERR(ohci_at91->uclk);
-                       goto err;
-               }
-       }
 
        board = hcd->self.controller->platform_data;
        ohci = hcd_to_ohci(hcd);
index fe2aedd8a54db23c6cb692fba8d250b3c01a4320..ed678c17c4eaadd4f4ceee99a6161da3e00b3d76 100644 (file)
@@ -536,7 +536,7 @@ ohci_hub_descriptor (
        u32             rh = roothub_a (ohci);
        u16             temp;
 
-       desc->bDescriptorType = 0x29;
+       desc->bDescriptorType = USB_DT_HUB;
        desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
        desc->bHubContrCurrent = 0;
 
index ef7efb278b15e34689f99f95f7bb96577089da79..6352f54e65a1d9359f999a26aa6f12cea08f877d 100644 (file)
@@ -445,7 +445,7 @@ static void ehci_hub_descriptor(struct oxu_hcd *oxu,
        int ports = HCS_N_PORTS(oxu->hcs_params);
        u16 temp;
 
-       desc->bDescriptorType = 0x29;
+       desc->bDescriptorType = USB_DT_HUB;
        desc->bPwrOn2PwrGood = 10;      /* oxu 1.0, 2.3.9 says 20ms max */
        desc->bHubContrCurrent = 0;
 
@@ -2500,11 +2500,12 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd)
                                        || oxu->reset_done[i] != 0)
                                continue;
 
-                       /* start 20 msec resume signaling from this port,
-                        * and make hub_wq collect PORT_STAT_C_SUSPEND to
+                       /* start USB_RESUME_TIMEOUT resume signaling from this
+                        * port, and make hub_wq collect PORT_STAT_C_SUSPEND to
                         * stop that signaling.
                         */
-                       oxu->reset_done[i] = jiffies + msecs_to_jiffies(20);
+                       oxu->reset_done[i] = jiffies +
+                               msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        oxu_dbg(oxu, "port %d remote wakeup\n", i + 1);
                        mod_timer(&hcd->rh_timer, oxu->reset_done[i]);
                }
index bdc82fea0a1f2a8dc40a2e554aeb6ad5fb1f5d50..4cbd0633c5c2dbbc1779cc2ae3aa0a4c818bf72e 100644 (file)
@@ -2136,7 +2136,7 @@ static int r8a66597_hub_status_data(struct usb_hcd *hcd, char *buf)
 static void r8a66597_hub_descriptor(struct r8a66597 *r8a66597,
                                    struct usb_hub_descriptor *desc)
 {
-       desc->bDescriptorType = 0x29;
+       desc->bDescriptorType = USB_DT_HUB;
        desc->bHubContrCurrent = 0;
        desc->bNbrPorts = r8a66597->max_root_hub;
        desc->bDescLength = 9;
@@ -2301,7 +2301,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
                rh->port &= ~USB_PORT_STAT_SUSPEND;
                rh->port |= USB_PORT_STAT_C_SUSPEND << 16;
                r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
-               msleep(50);
+               msleep(USB_RESUME_TIMEOUT);
                r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg);
        }
 
index 4f4ba1ea9e9be5298a145ffd506c37370f266655..fd2a11473be79921416597ae87489d4606d26f55 100644 (file)
@@ -1091,7 +1091,7 @@ sl811h_hub_descriptor (
 ) {
        u16             temp = 0;
 
-       desc->bDescriptorType = 0x29;
+       desc->bDescriptorType = USB_DT_HUB;
        desc->bHubContrCurrent = 0;
 
        desc->bNbrPorts = 1;
@@ -1259,7 +1259,7 @@ sl811h_hub_control(
                        sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
 
                        mod_timer(&sl811->timer, jiffies
-                                       + msecs_to_jiffies(20));
+                                       + msecs_to_jiffies(USB_RESUME_TIMEOUT));
                        break;
                case USB_PORT_FEAT_POWER:
                        port_power(sl811, 0);
@@ -1809,7 +1809,6 @@ struct platform_driver sl811h_driver = {
        .resume =       sl811h_resume,
        .driver = {
                .name = (char *) hcd_name,
-               .owner = THIS_MODULE,
        },
 };
 EXPORT_SYMBOL(sl811h_driver);
index ad97e8a1ad1cb733fea7145921bbdfe45d9b5925..d51687780b61a5428c8cb2238931d63ac9690bdd 100644 (file)
@@ -2584,7 +2584,7 @@ static int u132_roothub_descriptor(struct u132 *u132,
        retval = u132_read_pcimem(u132, roothub.a, &rh_a);
        if (retval)
                return retval;
-       desc->bDescriptorType = 0x29;
+       desc->bDescriptorType = USB_DT_HUB;
        desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24;
        desc->bHubContrCurrent = 0;
        desc->bNbrPorts = u132->num_ports;
index 19ba5eafb31e8458ec00fea95f0e0946cd45153e..ece9e37e89fe2888379d57a63814ed21d00b28be 100644 (file)
@@ -15,7 +15,7 @@
 static const __u8 root_hub_hub_des[] =
 {
        0x09,                   /*  __u8  bLength; */
-       0x29,                   /*  __u8  bDescriptorType; Hub-descriptor */
+       USB_DT_HUB,             /*  __u8  bDescriptorType; Hub-descriptor */
        0x02,                   /*  __u8  bNbrPorts; */
        HUB_CHAR_NO_LPSM |      /* __u16  wHubCharacteristics; */
                HUB_CHAR_INDV_PORT_OCPM, /* (per-port OC, no power switching) */
@@ -166,7 +166,7 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
                                /* Port received a wakeup request */
                                set_bit(port, &uhci->resuming_ports);
                                uhci->ports_timeout = jiffies +
-                                               msecs_to_jiffies(25);
+                                       msecs_to_jiffies(USB_RESUME_TIMEOUT);
                                usb_hcd_start_port_resume(
                                                &uhci_to_hcd(uhci)->self, port);
 
@@ -338,7 +338,8 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        uhci_finish_suspend(uhci, port, port_addr);
 
                        /* USB v2.0 7.1.7.5 */
-                       uhci->ports_timeout = jiffies + msecs_to_jiffies(50);
+                       uhci->ports_timeout = jiffies +
+                               msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        break;
                case USB_PORT_FEAT_POWER:
                        /* UHCI has no power switching */
index d7b363a418dee67917e9320fda6b5367a6b10ee1..43626c44683b81c86ae90b052f0a3f198c8201c8 100644 (file)
@@ -313,8 +313,7 @@ error_wusbhc_create:
        uwb_rc_put(wusbhc->uwb_rc);
 error:
        whc_clean_up(whc);
-       if (usb_hcd)
-               usb_put_hcd(usb_hcd);
+       usb_put_hcd(usb_hcd);
        return ret;
 }
 
index 0e11d61408ff3f95a3110636e858119f4037cf0c..783e819139a78adf233343e2ac95fed9bf19c731 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/usb/phy.h>
 #include <linux/slab.h>
 #include <linux/usb/xhci_pdriver.h>
 
@@ -155,12 +156,27 @@ static int xhci_plat_probe(struct platform_device *pdev)
        if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
                xhci->shared_hcd->can_do_streams = 1;
 
+       hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
+       if (IS_ERR(hcd->usb_phy)) {
+               ret = PTR_ERR(hcd->usb_phy);
+               if (ret == -EPROBE_DEFER)
+                       goto put_usb3_hcd;
+               hcd->usb_phy = NULL;
+       } else {
+               ret = usb_phy_init(hcd->usb_phy);
+               if (ret)
+                       goto put_usb3_hcd;
+       }
+
        ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
        if (ret)
-               goto put_usb3_hcd;
+               goto disable_usb_phy;
 
        return 0;
 
+disable_usb_phy:
+       usb_phy_shutdown(hcd->usb_phy);
+
 put_usb3_hcd:
        usb_put_hcd(xhci->shared_hcd);
 
@@ -184,6 +200,7 @@ static int xhci_plat_remove(struct platform_device *dev)
        struct clk *clk = xhci->clk;
 
        usb_remove_hcd(xhci->shared_hcd);
+       usb_phy_shutdown(hcd->usb_phy);
        usb_put_hcd(xhci->shared_hcd);
 
        usb_remove_hcd(hcd);
index 73485fa4372ff7d89298d4d8968fd28d5ec43265..f5397a517c54ce5a7df00b60e4b2482a2fd8b16c 100644 (file)
@@ -238,7 +238,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
 
                        /* Toggle the cycle bit after the last ring segment. */
                        if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
-                               ring->cycle_state = (ring->cycle_state ? 0 : 1);
+                               ring->cycle_state ^= 1;
                        }
                }
                ring->enq_seg = ring->enq_seg->next;
@@ -1574,7 +1574,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
                } else {
                        xhci_dbg(xhci, "resume HS port %d\n", port_id);
                        bus_state->resume_done[faked_port_index] = jiffies +
-                               msecs_to_jiffies(20);
+                               msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        set_bit(faked_port_index, &bus_state->resuming_ports);
                        mod_timer(&hcd->rh_timer,
                                  bus_state->resume_done[faked_port_index]);
@@ -2809,7 +2809,7 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
 
                        /* Toggle the cycle bit after the last ring segment. */
                        if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
-                               ring->cycle_state = (ring->cycle_state ? 0 : 1);
+                               ring->cycle_state ^= 1;
                        }
                        ring->enq_seg = ring->enq_seg->next;
                        ring->enqueue = ring->enq_seg->trbs;
index dde3959b7a33a1924a21ee915c0135d23dc64ca7..59c05653b2ea21517b380ec8dfae9d01baadea14 100644 (file)
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM xhci-hcd
 
+/*
+ * The TRACE_SYSTEM_VAR defaults to TRACE_SYSTEM, but must be a
+ * legitimate C variable. It is not exported to user space.
+ */
+#undef TRACE_SYSTEM_VAR
+#define TRACE_SYSTEM_VAR xhci_hcd
+
 #if !defined(__XHCI_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
 #define __XHCI_TRACE_H
 
index a62865af53ccca76e9c123a2075d40d8c7961ce9..5cf2633cdb0471678da917bcccf91272c1300e42 100644 (file)
@@ -347,7 +347,8 @@ static int mdc800_usb_waitForIRQ (int mode, int msec)
 {
        mdc800->camera_request_ready=1+mode;
 
-       wait_event_timeout(mdc800->irq_wait, mdc800->irq_woken, msec*HZ/1000);
+       wait_event_timeout(mdc800->irq_wait, mdc800->irq_woken,
+                          msecs_to_jiffies(msec));
        mdc800->irq_woken = 0;
 
        if (mdc800->camera_request_ready>0)
@@ -743,8 +744,9 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l
                                        mutex_unlock(&mdc800->io_lock);
                                        return len-left;
                                }
-                               wait_event_timeout(mdc800->download_wait, mdc800->downloaded,
-                                                                               TO_DOWNLOAD_GET_READY*HZ/1000);
+                               wait_event_timeout(mdc800->download_wait,
+                                    mdc800->downloaded,
+                                    msecs_to_jiffies(TO_DOWNLOAD_GET_READY));
                                mdc800->downloaded = 0;
                                if (mdc800->download_urb->status != 0)
                                {
@@ -867,7 +869,8 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s
                                mutex_unlock(&mdc800->io_lock);
                                return -EIO;
                        }
-                       wait_event_timeout(mdc800->write_wait, mdc800->written, TO_WRITE_GET_READY*HZ/1000);
+                       wait_event_timeout(mdc800->write_wait, mdc800->written,
+                                       msecs_to_jiffies(TO_WRITE_GET_READY));
                        mdc800->written = 0;
                        if (mdc800->state == WORKING)
                        {
index 3cb98b1d5d2960171bea26d4fff70e2217d9e7f0..ac31d19cc54bcee01cbde7e850d5744e53542777 100644 (file)
@@ -1758,7 +1758,7 @@ static void isp1760_hub_descriptor(struct isp1760_hcd *priv,
        int ports = HCS_N_PORTS(priv->hcs_params);
        u16 temp;
 
-       desc->bDescriptorType = 0x29;
+       desc->bDescriptorType = USB_DT_HUB;
        /* priv 1.0, 2.3.9 says 20ms max */
        desc->bPwrOn2PwrGood = 10;
        desc->bHubContrCurrent = 0;
@@ -1869,7 +1869,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
                                reg_write32(hcd->regs, HC_PORTSC1,
                                                        temp | PORT_RESUME);
                                priv->reset_done = jiffies +
-                                       msecs_to_jiffies(20);
+                                       msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        }
                        break;
                case USB_PORT_FEAT_C_SUSPEND:
index 76d77206e011c19a13e9969f5573d0356f1da0bd..f7a7fc21be8a7b75795077e9493f217059b04f29 100644 (file)
@@ -255,3 +255,16 @@ config USB_LINK_LAYER_TEST
          This driver is for generating specific traffic for Super Speed Link
          Layer Test Device. Say Y only when you want to conduct USB Super Speed
          Link Layer Test for host controllers.
+
+config USB_CHAOSKEY
+       tristate "ChaosKey random number generator driver support"
+       depends on HW_RANDOM
+       help
+         Say Y here if you want to connect an AltusMetrum ChaosKey to
+         your computer's USB port. The ChaosKey is a hardware random
+         number generator which hooks into the kernel entropy pool to
+         ensure a large supply of entropy for /dev/random and
+         /dev/urandom and also provides direct access via /dev/chaoskeyX
+
+         To compile this driver as a module, choose M here: the
+         module will be called chaoskey.
index 65b0402c1ca1f97bcb4c4aa4c85a6424de253d4f..45fd4ac39d3e4878716a6466f2d3bc1c38b36ede 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_USB_USS720)              += uss720.o
 obj-$(CONFIG_USB_SEVSEG)               += usbsevseg.o
 obj-$(CONFIG_USB_YUREX)                        += yurex.o
 obj-$(CONFIG_USB_HSIC_USB3503)         += usb3503.o
+obj-$(CONFIG_USB_CHAOSKEY)             += chaoskey.o
 
 obj-$(CONFIG_USB_SISUSBVGA)            += sisusbvga/
 obj-$(CONFIG_USB_LINK_LAYER_TEST)      += lvstest.o
index b3d245ef46efa7e72a4a4e7fd22ad80029f2a821..a0a3827b4aff75a774a01f2a6edc147989702697 100644 (file)
@@ -329,7 +329,7 @@ error:
                                        pdata->urbdata, pdata->urb->transfer_dma);
                        usb_free_urb(pdata->urb);
                }
-               if (pdata->bd && !IS_ERR(pdata->bd))
+               if (!IS_ERR(pdata->bd))
                        backlight_device_unregister(pdata->bd);
                kfree(pdata->msgdata);
        }
diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c
new file mode 100644 (file)
index 0000000..3ad5d19
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ * chaoskey - driver for ChaosKey device from Altus Metrum.
+ *
+ * This device provides true random numbers using a noise source based
+ * on a reverse-biased p-n junction in avalanche breakdown. More
+ * details can be found at http://chaoskey.org
+ *
+ * The driver connects to the kernel hardware RNG interface to provide
+ * entropy for /dev/random and other kernel activities. It also offers
+ * a separate /dev/ entry to allow for direct access to the random
+ * bit stream.
+ *
+ * Copyright Â© 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/wait.h>
+#include <linux/hw_random.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+
+static struct usb_driver chaoskey_driver;
+static struct usb_class_driver chaoskey_class;
+static int chaoskey_rng_read(struct hwrng *rng, void *data,
+                            size_t max, bool wait);
+
+#define usb_dbg(usb_if, format, arg...) \
+       dev_dbg(&(usb_if)->dev, format, ## arg)
+
+#define usb_err(usb_if, format, arg...) \
+       dev_err(&(usb_if)->dev, format, ## arg)
+
+/* Version Information */
+#define DRIVER_VERSION "v0.1"
+#define DRIVER_AUTHOR  "Keith Packard, keithp@keithp.com"
+#define DRIVER_DESC    "Altus Metrum ChaosKey driver"
+#define DRIVER_SHORT   "chaoskey"
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+#define CHAOSKEY_VENDOR_ID     0x1d50  /* OpenMoko */
+#define CHAOSKEY_PRODUCT_ID    0x60c6  /* ChaosKey */
+
+#define CHAOSKEY_BUF_LEN       64      /* max size of USB full speed packet */
+
+#define NAK_TIMEOUT (HZ)               /* stall/wait timeout for device */
+
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define USB_CHAOSKEY_MINOR_BASE 0
+#else
+
+/* IOWARRIOR_MINOR_BASE + 16, not official yet */
+#define USB_CHAOSKEY_MINOR_BASE 224
+#endif
+
+static const struct usb_device_id chaoskey_table[] = {
+       { USB_DEVICE(CHAOSKEY_VENDOR_ID, CHAOSKEY_PRODUCT_ID) },
+       { },
+};
+MODULE_DEVICE_TABLE(usb, chaoskey_table);
+
+/* Driver-local specific stuff */
+struct chaoskey {
+       struct usb_interface *interface;
+       char in_ep;
+       struct mutex lock;
+       struct mutex rng_lock;
+       int open;                       /* open count */
+       int present;                    /* device not disconnected */
+       int size;                       /* size of buf */
+       int valid;                      /* bytes of buf read */
+       int used;                       /* bytes of buf consumed */
+       char *name;                     /* product + serial */
+       struct hwrng hwrng;             /* Embedded struct for hwrng */
+       int hwrng_registered;           /* registered with hwrng API */
+       wait_queue_head_t wait_q;       /* for timeouts */
+       char *buf;
+};
+
+static void chaoskey_free(struct chaoskey *dev)
+{
+       usb_dbg(dev->interface, "free");
+       kfree(dev->name);
+       kfree(dev->buf);
+       kfree(dev);
+}
+
+static int chaoskey_probe(struct usb_interface *interface,
+                         const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(interface);
+       struct usb_host_interface *altsetting = interface->cur_altsetting;
+       int i;
+       int in_ep = -1;
+       struct chaoskey *dev;
+       int result;
+       int size;
+
+       usb_dbg(interface, "probe %s-%s", udev->product, udev->serial);
+
+       /* Find the first bulk IN endpoint and its packet size */
+       for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
+               if (usb_endpoint_is_bulk_in(&altsetting->endpoint[i].desc)) {
+                       in_ep = usb_endpoint_num(&altsetting->endpoint[i].desc);
+                       size = usb_endpoint_maxp(&altsetting->endpoint[i].desc);
+                       break;
+               }
+       }
+
+       /* Validate endpoint and size */
+       if (in_ep == -1) {
+               usb_dbg(interface, "no IN endpoint found");
+               return -ENODEV;
+       }
+       if (size <= 0) {
+               usb_dbg(interface, "invalid size (%d)", size);
+               return -ENODEV;
+       }
+
+       if (size > CHAOSKEY_BUF_LEN) {
+               usb_dbg(interface, "size reduced from %d to %d\n",
+                       size, CHAOSKEY_BUF_LEN);
+               size = CHAOSKEY_BUF_LEN;
+       }
+
+       /* Looks good, allocate and initialize */
+
+       dev = kzalloc(sizeof(struct chaoskey), GFP_KERNEL);
+
+       if (dev == NULL)
+               return -ENOMEM;
+
+       dev->buf = kmalloc(size, GFP_KERNEL);
+
+       if (dev->buf == NULL) {
+               kfree(dev);
+               return -ENOMEM;
+       }
+
+       /* Construct a name using the product and serial values. Each
+        * device needs a unique name for the hwrng code
+        */
+
+       if (udev->product && udev->serial) {
+               dev->name = kmalloc(strlen(udev->product) + 1 +
+                                   strlen(udev->serial) + 1, GFP_KERNEL);
+               if (dev->name == NULL) {
+                       kfree(dev->buf);
+                       kfree(dev);
+                       return -ENOMEM;
+               }
+
+               strcpy(dev->name, udev->product);
+               strcat(dev->name, "-");
+               strcat(dev->name, udev->serial);
+       }
+
+       dev->interface = interface;
+
+       dev->in_ep = in_ep;
+
+       dev->size = size;
+       dev->present = 1;
+
+       init_waitqueue_head(&dev->wait_q);
+
+       mutex_init(&dev->lock);
+       mutex_init(&dev->rng_lock);
+
+       usb_set_intfdata(interface, dev);
+
+       result = usb_register_dev(interface, &chaoskey_class);
+       if (result) {
+               usb_err(interface, "Unable to allocate minor number.");
+               usb_set_intfdata(interface, NULL);
+               chaoskey_free(dev);
+               return result;
+       }
+
+       dev->hwrng.name = dev->name ? dev->name : chaoskey_driver.name;
+       dev->hwrng.read = chaoskey_rng_read;
+
+       /* Set the 'quality' metric.  Quality is measured in units of
+        * 1/1024's of a bit ("mills"). This should be set to 1024,
+        * but there is a bug in the hwrng core which masks it with
+        * 1023.
+        *
+        * The patch that has been merged to the crypto development
+        * tree for that bug limits the value to 1024 at most, so by
+        * setting this to 1024 + 1023, we get 1023 before the fix is
+        * merged and 1024 afterwards. We'll patch this driver once
+        * both bits of code are in the same tree.
+        */
+       dev->hwrng.quality = 1024 + 1023;
+
+       dev->hwrng_registered = (hwrng_register(&dev->hwrng) == 0);
+       if (!dev->hwrng_registered)
+               usb_err(interface, "Unable to register with hwrng");
+
+       usb_enable_autosuspend(udev);
+
+       usb_dbg(interface, "chaoskey probe success, size %d", dev->size);
+       return 0;
+}
+
+static void chaoskey_disconnect(struct usb_interface *interface)
+{
+       struct chaoskey *dev;
+
+       usb_dbg(interface, "disconnect");
+       dev = usb_get_intfdata(interface);
+       if (!dev) {
+               usb_dbg(interface, "disconnect failed - no dev");
+               return;
+       }
+
+       if (dev->hwrng_registered)
+               hwrng_unregister(&dev->hwrng);
+
+       usb_deregister_dev(interface, &chaoskey_class);
+
+       usb_set_intfdata(interface, NULL);
+       mutex_lock(&dev->lock);
+
+       dev->present = 0;
+
+       if (!dev->open) {
+               mutex_unlock(&dev->lock);
+               chaoskey_free(dev);
+       } else
+               mutex_unlock(&dev->lock);
+
+       usb_dbg(interface, "disconnect done");
+}
+
+static int chaoskey_open(struct inode *inode, struct file *file)
+{
+       struct chaoskey *dev;
+       struct usb_interface *interface;
+
+       /* get the interface from minor number and driver information */
+       interface = usb_find_interface(&chaoskey_driver, iminor(inode));
+       if (!interface)
+               return -ENODEV;
+
+       usb_dbg(interface, "open");
+
+       dev = usb_get_intfdata(interface);
+       if (!dev) {
+               usb_dbg(interface, "open (dev)");
+               return -ENODEV;
+       }
+
+       file->private_data = dev;
+       mutex_lock(&dev->lock);
+       ++dev->open;
+       mutex_unlock(&dev->lock);
+
+       usb_dbg(interface, "open success");
+       return 0;
+}
+
+static int chaoskey_release(struct inode *inode, struct file *file)
+{
+       struct chaoskey *dev = file->private_data;
+       struct usb_interface *interface;
+
+       if (dev == NULL)
+               return -ENODEV;
+
+       interface = dev->interface;
+
+       usb_dbg(interface, "release");
+
+       mutex_lock(&dev->lock);
+
+       usb_dbg(interface, "open count at release is %d", dev->open);
+
+       if (dev->open <= 0) {
+               usb_dbg(interface, "invalid open count (%d)", dev->open);
+               mutex_unlock(&dev->lock);
+               return -ENODEV;
+       }
+
+       --dev->open;
+
+       if (!dev->present) {
+               if (dev->open == 0) {
+                       mutex_unlock(&dev->lock);
+                       chaoskey_free(dev);
+               } else
+                       mutex_unlock(&dev->lock);
+       } else
+               mutex_unlock(&dev->lock);
+
+       usb_dbg(interface, "release success");
+       return 0;
+}
+
+/* Fill the buffer. Called with dev->lock held
+ */
+static int _chaoskey_fill(struct chaoskey *dev)
+{
+       DEFINE_WAIT(wait);
+       int result;
+       int this_read;
+       struct usb_device *udev = interface_to_usbdev(dev->interface);
+
+       usb_dbg(dev->interface, "fill");
+
+       /* Return immediately if someone called before the buffer was
+        * empty */
+       if (dev->valid != dev->used) {
+               usb_dbg(dev->interface, "not empty yet (valid %d used %d)",
+                       dev->valid, dev->used);
+               return 0;
+       }
+
+       /* Bail if the device has been removed */
+       if (!dev->present) {
+               usb_dbg(dev->interface, "device not present");
+               return -ENODEV;
+       }
+
+       /* Make sure the device is awake */
+       result = usb_autopm_get_interface(dev->interface);
+       if (result) {
+               usb_dbg(dev->interface, "wakeup failed (result %d)", result);
+               return result;
+       }
+
+       result = usb_bulk_msg(udev,
+                             usb_rcvbulkpipe(udev, dev->in_ep),
+                             dev->buf, dev->size, &this_read,
+                             NAK_TIMEOUT);
+
+       /* Let the device go back to sleep eventually */
+       usb_autopm_put_interface(dev->interface);
+
+       if (result == 0) {
+               dev->valid = this_read;
+               dev->used = 0;
+       }
+
+       usb_dbg(dev->interface, "bulk_msg result %d this_read %d",
+               result, this_read);
+
+       return result;
+}
+
+static ssize_t chaoskey_read(struct file *file,
+                            char __user *buffer,
+                            size_t count,
+                            loff_t *ppos)
+{
+       struct chaoskey *dev;
+       ssize_t read_count = 0;
+       int this_time;
+       int result = 0;
+       unsigned long remain;
+
+       dev = file->private_data;
+
+       if (dev == NULL || !dev->present)
+               return -ENODEV;
+
+       usb_dbg(dev->interface, "read %zu", count);
+
+       while (count > 0) {
+
+               /* Grab the rng_lock briefly to ensure that the hwrng interface
+                * gets priority over other user access
+                */
+               result = mutex_lock_interruptible(&dev->rng_lock);
+               if (result)
+                       goto bail;
+               mutex_unlock(&dev->rng_lock);
+
+               result = mutex_lock_interruptible(&dev->lock);
+               if (result)
+                       goto bail;
+               if (dev->valid == dev->used) {
+                       result = _chaoskey_fill(dev);
+                       if (result) {
+                               mutex_unlock(&dev->lock);
+                               goto bail;
+                       }
+
+                       /* Read returned zero bytes */
+                       if (dev->used == dev->valid) {
+                               mutex_unlock(&dev->lock);
+                               goto bail;
+                       }
+               }
+
+               this_time = dev->valid - dev->used;
+               if (this_time > count)
+                       this_time = count;
+
+               remain = copy_to_user(buffer, dev->buf + dev->used, this_time);
+               if (remain) {
+                       result = -EFAULT;
+
+                       /* Consume the bytes that were copied so we don't leak
+                        * data to user space
+                        */
+                       dev->used += this_time - remain;
+                       mutex_unlock(&dev->lock);
+                       goto bail;
+               }
+
+               count -= this_time;
+               read_count += this_time;
+               buffer += this_time;
+               dev->used += this_time;
+               mutex_unlock(&dev->lock);
+       }
+bail:
+       if (read_count) {
+               usb_dbg(dev->interface, "read %zu bytes", read_count);
+               return read_count;
+       }
+       usb_dbg(dev->interface, "empty read, result %d", result);
+       return result;
+}
+
+static int chaoskey_rng_read(struct hwrng *rng, void *data,
+                            size_t max, bool wait)
+{
+       struct chaoskey *dev = container_of(rng, struct chaoskey, hwrng);
+       int this_time;
+
+       usb_dbg(dev->interface, "rng_read max %zu wait %d", max, wait);
+
+       if (!dev->present) {
+               usb_dbg(dev->interface, "device not present");
+               return 0;
+       }
+
+       /* Hold the rng_lock until we acquire the device lock so that
+        * this operation gets priority over other user access to the
+        * device
+        */
+       mutex_lock(&dev->rng_lock);
+
+       mutex_lock(&dev->lock);
+
+       mutex_unlock(&dev->rng_lock);
+
+       /* Try to fill the buffer if empty. It doesn't actually matter
+        * if _chaoskey_fill works; we'll just return zero bytes as
+        * the buffer will still be empty
+        */
+       if (dev->valid == dev->used)
+               (void) _chaoskey_fill(dev);
+
+       this_time = dev->valid - dev->used;
+       if (this_time > max)
+               this_time = max;
+
+       memcpy(data, dev->buf, this_time);
+
+       dev->used += this_time;
+
+       mutex_unlock(&dev->lock);
+
+       usb_dbg(dev->interface, "rng_read this_time %d\n", this_time);
+       return this_time;
+}
+
+#ifdef CONFIG_PM
+static int chaoskey_suspend(struct usb_interface *interface,
+                           pm_message_t message)
+{
+       usb_dbg(interface, "suspend");
+       return 0;
+}
+
+static int chaoskey_resume(struct usb_interface *interface)
+{
+       usb_dbg(interface, "resume");
+       return 0;
+}
+#else
+#define chaoskey_suspend NULL
+#define chaoskey_resume NULL
+#endif
+
+/* file operation pointers */
+static const struct file_operations chaoskey_fops = {
+       .owner = THIS_MODULE,
+       .read = chaoskey_read,
+       .open = chaoskey_open,
+       .release = chaoskey_release,
+       .llseek = default_llseek,
+};
+
+/* class driver information */
+static struct usb_class_driver chaoskey_class = {
+       .name = "chaoskey%d",
+       .fops = &chaoskey_fops,
+       .minor_base = USB_CHAOSKEY_MINOR_BASE,
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver chaoskey_driver = {
+       .name = DRIVER_SHORT,
+       .probe = chaoskey_probe,
+       .disconnect = chaoskey_disconnect,
+       .suspend = chaoskey_suspend,
+       .resume = chaoskey_resume,
+       .reset_resume = chaoskey_resume,
+       .id_table = chaoskey_table,
+       .supports_autosuspend = 1,
+};
+
+module_usb_driver(chaoskey_driver);
+
index 97cd9e24bd25b30dbfb9e7cbfd9f35a86728b243..7771be3ac178ea0e95ca7da1f85ff55543ff4a00 100644 (file)
@@ -574,7 +574,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
        }
 
        if (read_timeout) {
-               timeout = jiffies + read_timeout * HZ / 1000;
+               timeout = jiffies + msecs_to_jiffies(read_timeout);
        }
 
        /* wait for data */
@@ -592,7 +592,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
                /* reset read timeout during read or write activity */
                if (read_timeout
                    && (dev->read_buffer_length || dev->interrupt_out_busy)) {
-                       timeout = jiffies + read_timeout * HZ / 1000;
+                       timeout = jiffies + msecs_to_jiffies(read_timeout);
                }
                /* check for read timeout */
                if (read_timeout && time_after (jiffies, timeout)) {
@@ -831,7 +831,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
        dev->read_buffer_length = 0;
        dev->read_packet_length = 0;
        spin_lock_init (&dev->read_buffer_lock);
-       dev->packet_timeout_jiffies = packet_timeout * HZ / 1000;
+       dev->packet_timeout_jiffies = msecs_to_jiffies(packet_timeout);
        dev->read_last_arrival = jiffies;
 
        init_waitqueue_head (&dev->read_wait);
index 258d2f546e430e0a3e866537156f2ce64a0cc106..64ff5b91752d2187c0c949927dfa311b49531460 100644 (file)
@@ -186,8 +186,31 @@ static int usb3503_probe(struct usb3503 *hub)
                hub->mode               = pdata->initial_mode;
        } else if (np) {
                struct clk *clk;
+               u32 rate = 0;
                hub->port_off_mask = 0;
 
+               if (!of_property_read_u32(np, "refclk-frequency", &rate)) {
+                       switch (rate) {
+                       case 38400000:
+                       case 26000000:
+                       case 19200000:
+                       case 12000000:
+                               hub->secondary_ref_clk = 0;
+                               break;
+                       case 24000000:
+                       case 27000000:
+                       case 25000000:
+                       case 50000000:
+                               hub->secondary_ref_clk = 1;
+                               break;
+                       default:
+                               dev_err(dev,
+                                       "unsupported reference clock rate (%d)\n",
+                                       (int) rate);
+                               return -EINVAL;
+                       }
+               }
+
                clk = devm_clk_get(dev, "refclk");
                if (IS_ERR(clk) && PTR_ERR(clk) != -ENOENT) {
                        dev_err(dev, "unable to request refclk (%ld)\n",
@@ -196,31 +219,9 @@ static int usb3503_probe(struct usb3503 *hub)
                }
 
                if (!IS_ERR(clk)) {
-                       u32 rate = 0;
                        hub->clk = clk;
 
-                       if (!of_property_read_u32(np, "refclk-frequency",
-                                                &rate)) {
-
-                               switch (rate) {
-                               case 38400000:
-                               case 26000000:
-                               case 19200000:
-                               case 12000000:
-                                       hub->secondary_ref_clk = 0;
-                                       break;
-                               case 24000000:
-                               case 27000000:
-                               case 25000000:
-                               case 50000000:
-                                       hub->secondary_ref_clk = 1;
-                                       break;
-                               default:
-                                       dev_err(dev,
-                                               "unsupported reference clock rate (%d)\n",
-                                               (int) rate);
-                                       return -EINVAL;
-                               }
+                       if (rate != 0) {
                                err = clk_set_rate(hub->clk, rate);
                                if (err) {
                                        dev_err(dev,
index 067920f2d570fb77be332cf16e885bf63e0a352c..3789b08ef67b037781e278c41c0d4b2f2d33e5d9 100644 (file)
@@ -99,6 +99,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
+#include <linux/usb.h>
 
 #include "musb_core.h"
 
@@ -507,7 +508,8 @@ void musb_hnp_stop(struct musb *musb)
        musb->port1_status &= ~(USB_PORT_STAT_C_CONNECTION << 16);
 }
 
-static void musb_generic_disable(struct musb *musb);
+static void musb_recover_from_babble(struct musb *musb);
+
 /*
  * Interrupt Service Routine to record USB "global" interrupts.
  * Since these do not happen often and signify things of
@@ -534,35 +536,21 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
         */
        if (int_usb & MUSB_INTR_RESUME) {
                handled = IRQ_HANDLED;
-               dev_dbg(musb->controller, "RESUME (%s)\n", usb_otg_state_string(musb->xceiv->otg->state));
+               dev_dbg(musb->controller, "RESUME (%s)\n",
+                               usb_otg_state_string(musb->xceiv->otg->state));
 
                if (devctl & MUSB_DEVCTL_HM) {
-                       void __iomem *mbase = musb->mregs;
-                       u8 power;
-
                        switch (musb->xceiv->otg->state) {
                        case OTG_STATE_A_SUSPEND:
                                /* remote wakeup?  later, GetPortStatus
                                 * will stop RESUME signaling
                                 */
 
-                               power = musb_readb(musb->mregs, MUSB_POWER);
-                               if (power & MUSB_POWER_SUSPENDM) {
-                                       /* spurious */
-                                       musb->int_usb &= ~MUSB_INTR_SUSPEND;
-                                       dev_dbg(musb->controller, "Spurious SUSPENDM\n");
-                                       break;
-                               }
-
-                               power &= ~MUSB_POWER_SUSPENDM;
-                               musb_writeb(mbase, MUSB_POWER,
-                                               power | MUSB_POWER_RESUME);
-
                                musb->port1_status |=
                                                (USB_PORT_STAT_C_SUSPEND << 16)
                                                | MUSB_PORT_STAT_RESUME;
                                musb->rh_timer = jiffies
-                                                + msecs_to_jiffies(20);
+                                       + msecs_to_jiffies(USB_RESUME_TIMEOUT);
                                musb->need_finish_resume = 1;
 
                                musb->xceiv->otg->state = OTG_STATE_A_HOST;
@@ -775,10 +763,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 
                musb->ep0_stage = MUSB_EP0_START;
 
-               /* flush endpoints when transitioning from Device Mode */
-               if (is_peripheral_active(musb)) {
-                       /* REVISIT HNP; just force disconnect */
-               }
                musb->intrtxe = musb->epmask;
                musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe);
                musb->intrrxe = musb->epmask & 0xfffe;
@@ -879,20 +863,19 @@ b_host:
         */
        if (int_usb & MUSB_INTR_RESET) {
                handled = IRQ_HANDLED;
-               if ((devctl & MUSB_DEVCTL_HM) != 0) {
+               if (devctl & MUSB_DEVCTL_HM) {
                        /*
-                        * Looks like non-HS BABBLE can be ignored, but
-                        * HS BABBLE is an error condition. For HS the solution
-                        * is to avoid babble in the first place and fix what
-                        * caused BABBLE. When HS BABBLE happens we can only
-                        * stop the session.
+                        * When BABBLE happens what we can depends on which
+                        * platform MUSB is running, because some platforms
+                        * implemented proprietary means for 'recovering' from
+                        * Babble conditions. One such platform is AM335x. In
+                        * most cases, however, the only thing we can do is
+                        * drop the session.
                         */
-                       if (devctl & (MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV))
-                               dev_dbg(musb->controller, "BABBLE devctl: %02x\n", devctl);
-                       else {
-                               ERR("Stopping host session -- babble\n");
-                               musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
-                       }
+                       dev_err(musb->controller, "Babble\n");
+
+                       if (is_host_active(musb))
+                               musb_recover_from_babble(musb);
                } else {
                        dev_dbg(musb->controller, "BUS RESET as %s\n",
                                usb_otg_state_string(musb->xceiv->otg->state));
@@ -931,13 +914,6 @@ b_host:
                }
        }
 
-       /* handle babble condition */
-       if (int_usb & MUSB_INTR_BABBLE && is_host_active(musb)) {
-               musb_generic_disable(musb);
-               schedule_delayed_work(&musb->recover_work,
-                                     msecs_to_jiffies(100));
-       }
-
 #if 0
 /* REVISIT ... this would be for multiplexing periodic endpoints, or
  * supporting transfer phasing to prevent exceeding ISO bandwidth
@@ -990,7 +966,7 @@ b_host:
 
 /*-------------------------------------------------------------------------*/
 
-static void musb_generic_disable(struct musb *musb)
+static void musb_disable_interrupts(struct musb *musb)
 {
        void __iomem    *mbase = musb->mregs;
        u16     temp;
@@ -1002,14 +978,33 @@ static void musb_generic_disable(struct musb *musb)
        musb->intrrxe = 0;
        musb_writew(mbase, MUSB_INTRRXE, 0);
 
-       /* off */
-       musb_writeb(mbase, MUSB_DEVCTL, 0);
-
        /*  flush pending interrupts */
        temp = musb_readb(mbase, MUSB_INTRUSB);
        temp = musb_readw(mbase, MUSB_INTRTX);
        temp = musb_readw(mbase, MUSB_INTRRX);
+}
+
+static void musb_enable_interrupts(struct musb *musb)
+{
+       void __iomem    *regs = musb->mregs;
+
+       /*  Set INT enable registers, enable interrupts */
+       musb->intrtxe = musb->epmask;
+       musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
+       musb->intrrxe = musb->epmask & 0xfffe;
+       musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
+       musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
+
+}
+
+static void musb_generic_disable(struct musb *musb)
+{
+       void __iomem    *mbase = musb->mregs;
 
+       musb_disable_interrupts(musb);
+
+       /* off */
+       musb_writeb(mbase, MUSB_DEVCTL, 0);
 }
 
 /*
@@ -1022,13 +1017,7 @@ void musb_start(struct musb *musb)
 
        dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
 
-       /*  Set INT enable registers, enable interrupts */
-       musb->intrtxe = musb->epmask;
-       musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
-       musb->intrrxe = musb->epmask & 0xfffe;
-       musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
-       musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
-
+       musb_enable_interrupts(musb);
        musb_writeb(regs, MUSB_TESTMODE, 0);
 
        /* put into basic highspeed mode and start session */
@@ -1587,9 +1576,12 @@ static int musb_core_init(u16 musb_type, struct musb *musb)
 irqreturn_t musb_interrupt(struct musb *musb)
 {
        irqreturn_t     retval = IRQ_NONE;
+       unsigned long   status;
+       unsigned long   epnum;
        u8              devctl;
-       int             ep_num;
-       u32             reg;
+
+       if (!musb->int_usb && !musb->int_tx && !musb->int_rx)
+               return IRQ_NONE;
 
        devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
@@ -1597,56 +1589,57 @@ irqreturn_t musb_interrupt(struct musb *musb)
                is_host_active(musb) ? "host" : "peripheral",
                musb->int_usb, musb->int_tx, musb->int_rx);
 
-       /* the core can interrupt us for multiple reasons; docs have
-        * a generic interrupt flowchart to follow
+       /**
+        * According to Mentor Graphics' documentation, flowchart on page 98,
+        * IRQ should be handled as follows:
+        *
+        * . Resume IRQ
+        * . Session Request IRQ
+        * . VBUS Error IRQ
+        * . Suspend IRQ
+        * . Connect IRQ
+        * . Disconnect IRQ
+        * . Reset/Babble IRQ
+        * . SOF IRQ (we're not using this one)
+        * . Endpoint 0 IRQ
+        * . TX Endpoints
+        * . RX Endpoints
+        *
+        * We will be following that flowchart in order to avoid any problems
+        * that might arise with internal Finite State Machine.
         */
-       if (musb->int_usb)
-               retval |= musb_stage0_irq(musb, musb->int_usb,
-                               devctl);
 
-       /* "stage 1" is handling endpoint irqs */
+       if (musb->int_usb)
+               retval |= musb_stage0_irq(musb, musb->int_usb, devctl);
 
-       /* handle endpoint 0 first */
        if (musb->int_tx & 1) {
                if (is_host_active(musb))
                        retval |= musb_h_ep0_irq(musb);
                else
                        retval |= musb_g_ep0_irq(musb);
+
+               /* we have just handled endpoint 0 IRQ, clear it */
+               musb->int_tx &= ~BIT(0);
        }
 
-       /* RX on endpoints 1-15 */
-       reg = musb->int_rx >> 1;
-       ep_num = 1;
-       while (reg) {
-               if (reg & 1) {
-                       /* musb_ep_select(musb->mregs, ep_num); */
-                       /* REVISIT just retval = ep->rx_irq(...) */
-                       retval = IRQ_HANDLED;
-                       if (is_host_active(musb))
-                               musb_host_rx(musb, ep_num);
-                       else
-                               musb_g_rx(musb, ep_num);
-               }
+       status = musb->int_tx;
 
-               reg >>= 1;
-               ep_num++;
+       for_each_set_bit(epnum, &status, 16) {
+               retval = IRQ_HANDLED;
+               if (is_host_active(musb))
+                       musb_host_tx(musb, epnum);
+               else
+                       musb_g_tx(musb, epnum);
        }
 
-       /* TX on endpoints 1-15 */
-       reg = musb->int_tx >> 1;
-       ep_num = 1;
-       while (reg) {
-               if (reg & 1) {
-                       /* musb_ep_select(musb->mregs, ep_num); */
-                       /* REVISIT just retval |= ep->tx_irq(...) */
-                       retval = IRQ_HANDLED;
-                       if (is_host_active(musb))
-                               musb_host_tx(musb, ep_num);
-                       else
-                               musb_g_tx(musb, ep_num);
-               }
-               reg >>= 1;
-               ep_num++;
+       status = musb->int_rx;
+
+       for_each_set_bit(epnum, &status, 16) {
+               retval = IRQ_HANDLED;
+               if (is_host_active(musb))
+                       musb_host_rx(musb, epnum);
+               else
+                       musb_g_rx(musb, epnum);
        }
 
        return retval;
@@ -1825,33 +1818,44 @@ static void musb_irq_work(struct work_struct *data)
        }
 }
 
-/* Recover from babble interrupt conditions */
-static void musb_recover_work(struct work_struct *data)
+static void musb_recover_from_babble(struct musb *musb)
 {
-       struct musb *musb = container_of(data, struct musb, recover_work.work);
-       int status, ret;
+       int ret;
+       u8 devctl;
 
-       ret  = musb_platform_reset(musb);
-       if (ret)
+       musb_disable_interrupts(musb);
+
+       /*
+        * wait at least 320 cycles of 60MHz clock. That's 5.3us, we will give
+        * it some slack and wait for 10us.
+        */
+       udelay(10);
+
+       ret  = musb_platform_recover(musb);
+       if (ret) {
+               musb_enable_interrupts(musb);
                return;
+       }
 
-       usb_phy_vbus_off(musb->xceiv);
-       usleep_range(100, 200);
+       /* drop session bit */
+       devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+       devctl &= ~MUSB_DEVCTL_SESSION;
+       musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 
-       usb_phy_vbus_on(musb->xceiv);
-       usleep_range(100, 200);
+       /* tell usbcore about it */
+       musb_root_disconnect(musb);
 
        /*
         * When a babble condition occurs, the musb controller
         * removes the session bit and the endpoint config is lost.
         */
        if (musb->dyn_fifo)
-               status = ep_config_from_table(musb);
+               ret = ep_config_from_table(musb);
        else
-               status = ep_config_from_hw(musb);
+               ret = ep_config_from_hw(musb);
 
-       /* start the session again */
-       if (status == 0)
+       /* restart session */
+       if (ret == 0)
                musb_start(musb);
 }
 
@@ -2087,7 +2091,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 
        /* Init IRQ workqueue before request_irq */
        INIT_WORK(&musb->irq_work, musb_irq_work);
-       INIT_DELAYED_WORK(&musb->recover_work, musb_recover_work);
        INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset);
        INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume);
 
@@ -2183,7 +2186,6 @@ fail4:
 
 fail3:
        cancel_work_sync(&musb->irq_work);
-       cancel_delayed_work_sync(&musb->recover_work);
        cancel_delayed_work_sync(&musb->finish_resume_work);
        cancel_delayed_work_sync(&musb->deassert_reset_work);
        if (musb->dma_controller)
@@ -2249,7 +2251,6 @@ static int musb_remove(struct platform_device *pdev)
                dma_controller_destroy(musb->dma_controller);
 
        cancel_work_sync(&musb->irq_work);
-       cancel_delayed_work_sync(&musb->recover_work);
        cancel_delayed_work_sync(&musb->finish_resume_work);
        cancel_delayed_work_sync(&musb->deassert_reset_work);
        musb_free(musb);
@@ -2463,7 +2464,7 @@ static int musb_resume(struct device *dev)
        if (musb->need_finish_resume) {
                musb->need_finish_resume = 0;
                schedule_delayed_work(&musb->finish_resume_work,
-                                     msecs_to_jiffies(20));
+                                     msecs_to_jiffies(USB_RESUME_TIMEOUT));
        }
 
        /*
@@ -2506,7 +2507,7 @@ static int musb_runtime_resume(struct device *dev)
        if (musb->need_finish_resume) {
                musb->need_finish_resume = 0;
                schedule_delayed_work(&musb->finish_resume_work,
-                               msecs_to_jiffies(20));
+                               msecs_to_jiffies(USB_RESUME_TIMEOUT));
        }
 
        return 0;
index 5e65958f79151ea7107df5028a954804cb91b879..3877249a8b2d39c009da0a93874b79c3155a26b4 100644 (file)
@@ -160,7 +160,8 @@ struct musb_io;
  * @init:      turns on clocks, sets up platform-specific registers, etc
  * @exit:      undoes @init
  * @set_mode:  forcefully changes operating mode
- * @try_ilde:  tries to idle the IP
+ * @try_idle:  tries to idle the IP
+ * @recover:   platform-specific babble recovery
  * @vbus_status: returns vbus status if possible
  * @set_vbus:  forces vbus status
  * @adjust_channel_params: pre check for standard dma channel_program func
@@ -196,7 +197,7 @@ struct musb_platform_ops {
        void    (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf);
        int     (*set_mode)(struct musb *musb, u8 mode);
        void    (*try_idle)(struct musb *musb, unsigned long timeout);
-       int     (*reset)(struct musb *musb);
+       int     (*recover)(struct musb *musb);
 
        int     (*vbus_status)(struct musb *musb);
        void    (*set_vbus)(struct musb *musb, int on);
@@ -300,7 +301,6 @@ struct musb {
 
        irqreturn_t             (*isr)(int, void *);
        struct work_struct      irq_work;
-       struct delayed_work     recover_work;
        struct delayed_work     deassert_reset_work;
        struct delayed_work     finish_resume_work;
        u16                     hwvers;
@@ -558,12 +558,12 @@ static inline void musb_platform_try_idle(struct musb *musb,
                musb->ops->try_idle(musb, timeout);
 }
 
-static inline int  musb_platform_reset(struct musb *musb)
+static inline int  musb_platform_recover(struct musb *musb)
 {
-       if (!musb->ops->reset)
-               return -EINVAL;
+       if (!musb->ops->recover)
+               return 0;
 
-       return musb->ops->reset(musb);
+       return musb->ops->recover(musb);
 }
 
 static inline int musb_platform_get_vbus_status(struct musb *musb)
index be84562d021b8c401f981c7f7a5a7c4551cd16bc..8bd8c5e26921caea09e9a7cd973b462df8622249 100644 (file)
@@ -225,10 +225,12 @@ static void cppi41_dma_callback(void *private_data)
        struct dma_channel *channel = private_data;
        struct cppi41_dma_channel *cppi41_channel = channel->private_data;
        struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+       struct cppi41_dma_controller *controller;
        struct musb *musb = hw_ep->musb;
        unsigned long flags;
        struct dma_tx_state txstate;
        u32 transferred;
+       int is_hs = 0;
        bool empty;
 
        spin_lock_irqsave(&musb->lock, flags);
@@ -248,61 +250,59 @@ static void cppi41_dma_callback(void *private_data)
                        transferred < cppi41_channel->packet_sz)
                cppi41_channel->prog_len = 0;
 
-       empty = musb_is_tx_fifo_empty(hw_ep);
-       if (empty) {
+       if (cppi41_channel->is_tx)
+               empty = musb_is_tx_fifo_empty(hw_ep);
+
+       if (!cppi41_channel->is_tx || empty) {
                cppi41_trans_done(cppi41_channel);
-       } else {
-               struct cppi41_dma_controller *controller;
-               int is_hs = 0;
-               /*
-                * On AM335x it has been observed that the TX interrupt fires
-                * too early that means the TXFIFO is not yet empty but the DMA
-                * engine says that it is done with the transfer. We don't
-                * receive a FIFO empty interrupt so the only thing we can do is
-                * to poll for the bit. On HS it usually takes 2us, on FS around
-                * 110us - 150us depending on the transfer size.
-                * We spin on HS (no longer than than 25us and setup a timer on
-                * FS to check for the bit and complete the transfer.
-                */
-               controller = cppi41_channel->controller;
+               goto out;
+       }
 
-               if (is_host_active(musb)) {
-                       if (musb->port1_status & USB_PORT_STAT_HIGH_SPEED)
-                               is_hs = 1;
-               } else {
-                       if (musb->g.speed == USB_SPEED_HIGH)
-                               is_hs = 1;
-               }
-               if (is_hs) {
-                       unsigned wait = 25;
-
-                       do {
-                               empty = musb_is_tx_fifo_empty(hw_ep);
-                               if (empty)
-                                       break;
-                               wait--;
-                               if (!wait)
-                                       break;
-                               udelay(1);
-                       } while (1);
+       /*
+        * On AM335x it has been observed that the TX interrupt fires
+        * too early that means the TXFIFO is not yet empty but the DMA
+        * engine says that it is done with the transfer. We don't
+        * receive a FIFO empty interrupt so the only thing we can do is
+        * to poll for the bit. On HS it usually takes 2us, on FS around
+        * 110us - 150us depending on the transfer size.
+        * We spin on HS (no longer than than 25us and setup a timer on
+        * FS to check for the bit and complete the transfer.
+        */
+       controller = cppi41_channel->controller;
+
+       if (is_host_active(musb)) {
+               if (musb->port1_status & USB_PORT_STAT_HIGH_SPEED)
+                       is_hs = 1;
+       } else {
+               if (musb->g.speed == USB_SPEED_HIGH)
+                       is_hs = 1;
+       }
+       if (is_hs) {
+               unsigned wait = 25;
 
+               do {
                        empty = musb_is_tx_fifo_empty(hw_ep);
                        if (empty) {
                                cppi41_trans_done(cppi41_channel);
                                goto out;
                        }
-               }
-               list_add_tail(&cppi41_channel->tx_check,
-                               &controller->early_tx_list);
-               if (!hrtimer_is_queued(&controller->early_tx)) {
-                       unsigned long usecs = cppi41_channel->total_len / 10;
+                       wait--;
+                       if (!wait)
+                               break;
+                       cpu_relax();
+               } while (1);
+       }
+       list_add_tail(&cppi41_channel->tx_check,
+                       &controller->early_tx_list);
+       if (!hrtimer_is_queued(&controller->early_tx)) {
+               unsigned long usecs = cppi41_channel->total_len / 10;
 
-                       hrtimer_start_range_ns(&controller->early_tx,
+               hrtimer_start_range_ns(&controller->early_tx,
                                ktime_set(0, usecs * NSEC_PER_USEC),
                                20 * NSEC_PER_USEC,
                                HRTIMER_MODE_REL);
-               }
        }
+
 out:
        spin_unlock_irqrestore(&musb->lock, flags);
 }
index a900c9877195ad6ef2048ddb8c2813c8e196feed..65d931a28a14c7e5c66860af7b4e54e12adbb6b5 100644 (file)
@@ -119,7 +119,7 @@ struct dsps_musb_wrapper {
        unsigned        iddig:5;
        unsigned        iddig_mux:5;
        /* miscellaneous stuff */
-       u8              poll_seconds;
+       unsigned        poll_timeout;
 };
 
 /*
@@ -225,9 +225,8 @@ static void dsps_musb_enable(struct musb *musb)
 
        dsps_writel(reg_base, wrp->epintr_set, epmask);
        dsps_writel(reg_base, wrp->coreintr_set, coremask);
-       /* Force the DRVVBUS IRQ so we can start polling for ID change. */
-       dsps_writel(reg_base, wrp->coreintr_set,
-                   (1 << wrp->drvvbus) << wrp->usb_shift);
+       /* start polling for ID change. */
+       mod_timer(&glue->timer, jiffies + msecs_to_jiffies(wrp->poll_timeout));
        dsps_musb_try_idle(musb, 0);
 }
 
@@ -285,7 +284,8 @@ static void otg_timer(unsigned long _musb)
                }
                if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session)
                        dsps_writeb(mregs, MUSB_DEVCTL, MUSB_DEVCTL_SESSION);
-               mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
+               mod_timer(&glue->timer, jiffies +
+                               msecs_to_jiffies(wrp->poll_timeout));
                break;
        case OTG_STATE_A_WAIT_VFALL:
                musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
@@ -330,28 +330,6 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 
        dev_dbg(musb->controller, "usbintr (%x) epintr(%x)\n",
                        usbintr, epintr);
-       /*
-        * DRVVBUS IRQs are the only proxy we have (a very poor one!) for
-        * DSPS IP's missing ID change IRQ.  We need an ID change IRQ to
-        * switch appropriately between halves of the OTG state machine.
-        * Managing DEVCTL.SESSION per Mentor docs requires that we know its
-        * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
-        * Also, DRVVBUS pulses for SRP (but not at 5V) ...
-        */
-       if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE) {
-               pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
-
-               /*
-                * When a babble condition occurs, the musb controller removes
-                * the session and is no longer in host mode. Hence, all
-                * devices connected to its root hub get disconnected.
-                *
-                * Hand this error down to the musb core isr, so it can
-                * recover.
-                */
-               musb->int_usb = MUSB_INTR_BABBLE | MUSB_INTR_DISCONNECT;
-               musb->int_tx = musb->int_rx = 0;
-       }
 
        if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
                int drvvbus = dsps_readl(reg_base, wrp->status);
@@ -374,8 +352,8 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
                         */
                        musb->int_usb &= ~MUSB_INTR_VBUSERROR;
                        musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL;
-                       mod_timer(&glue->timer,
-                                       jiffies + wrp->poll_seconds * HZ);
+                       mod_timer(&glue->timer, jiffies +
+                                       msecs_to_jiffies(wrp->poll_timeout));
                        WARNING("VBUS error workaround (delay coming)\n");
                } else if (drvvbus) {
                        MUSB_HST_MODE(musb);
@@ -404,7 +382,8 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
        /* Poll for ID change in OTG port mode */
        if (musb->xceiv->otg->state == OTG_STATE_B_IDLE &&
                        musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
-               mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
+               mod_timer(&glue->timer, jiffies +
+                               msecs_to_jiffies(wrp->poll_timeout));
 out:
        spin_unlock_irqrestore(&musb->lock, flags);
 
@@ -453,7 +432,7 @@ static int dsps_musb_init(struct musb *musb)
        musb->ctrl_base = reg_base;
 
        /* NOP driver needs change if supporting dual instance */
-       musb->xceiv = devm_usb_get_phy_by_phandle(dev, "phys", 0);
+       musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "phys", 0);
        if (IS_ERR(musb->xceiv))
                return PTR_ERR(musb->xceiv);
 
@@ -497,7 +476,7 @@ static int dsps_musb_init(struct musb *musb)
         * logic enabled.
         */
        val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL);
-       if (val == MUSB_BABBLE_RCV_DISABLE) {
+       if (val & MUSB_BABBLE_RCV_DISABLE) {
                glue->sw_babble_enabled = true;
                val |= MUSB_BABBLE_SW_SESSION_CTRL;
                dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val);
@@ -571,7 +550,7 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode)
        return 0;
 }
 
-static bool  sw_babble_control(struct musb *musb)
+static bool dsps_sw_babble_control(struct musb *musb)
 {
        u8 babble_ctl;
        bool session_restart =  false;
@@ -622,37 +601,36 @@ static bool  sw_babble_control(struct musb *musb)
        return session_restart;
 }
 
-static int dsps_musb_reset(struct musb *musb)
+static int dsps_musb_recover(struct musb *musb)
 {
        struct device *dev = musb->controller;
        struct dsps_glue *glue = dev_get_drvdata(dev->parent);
-       const struct dsps_musb_wrapper *wrp = glue->wrp;
-       int session_restart = 0, error;
+       int session_restart = 0;
 
        if (glue->sw_babble_enabled)
-               session_restart = sw_babble_control(musb);
-       /*
-        * In case of new silicon version babble condition can be recovered
-        * without resetting the MUSB. But for older silicon versions, MUSB
-        * reset is needed
-        */
-       if (session_restart || !glue->sw_babble_enabled) {
-               dev_info(musb->controller, "Restarting MUSB to recover from Babble\n");
-               dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset));
-               usleep_range(100, 200);
-               usb_phy_shutdown(musb->xceiv);
-               error = phy_power_off(musb->phy);
-               if (error)
-                       dev_err(dev, "phy shutdown failed: %i\n", error);
-               usleep_range(100, 200);
-               usb_phy_init(musb->xceiv);
-               error = phy_power_on(musb->phy);
-               if (error)
-                       dev_err(dev, "phy powerup failed: %i\n", error);
+               session_restart = dsps_sw_babble_control(musb);
+       else
                session_restart = 1;
+
+       return session_restart ? 0 : -EPIPE;
+}
+
+/* Similar to am35x, dm81xx support only 32-bit read operation */
+static void dsps_read_fifo32(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
+{
+       void __iomem *fifo = hw_ep->fifo;
+
+       if (len >= 4) {
+               ioread32_rep(fifo, dst, len >> 2);
+               dst += len & ~0x03;
+               len &= 0x03;
        }
 
-       return !session_restart;
+       /* Read any remaining 1 to 3 bytes */
+       if (len > 0) {
+               u32 val = musb_readl(fifo, 0);
+               memcpy(dst, &val, len);
+       }
 }
 
 static struct musb_platform_ops dsps_ops = {
@@ -665,7 +643,7 @@ static struct musb_platform_ops dsps_ops = {
 
        .try_idle       = dsps_musb_try_idle,
        .set_mode       = dsps_musb_set_mode,
-       .reset          = dsps_musb_reset,
+       .recover        = dsps_musb_recover,
 };
 
 static u64 musb_dmamask = DMA_BIT_MASK(32);
@@ -737,7 +715,6 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue,
        musb->dev.parent                = dev;
        musb->dev.dma_mask              = &musb_dmamask;
        musb->dev.coherent_dma_mask     = musb_dmamask;
-       musb->dev.of_node               = of_node_get(dn);
 
        glue->musb = musb;
 
@@ -802,6 +779,9 @@ static int dsps_probe(struct platform_device *pdev)
        }
        wrp = match->data;
 
+       if (of_device_is_compatible(pdev->dev.of_node, "ti,musb-dm816"))
+               dsps_ops.read_fifo = dsps_read_fifo32;
+
        /* allocate glue */
        glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
        if (!glue)
@@ -873,12 +853,14 @@ static const struct dsps_musb_wrapper am33xx_driver_data = {
        .rxep_shift             = 16,
        .rxep_mask              = 0xfffe,
        .rxep_bitmap            = (0xfffe << 16),
-       .poll_seconds           = 2,
+       .poll_timeout           = 2000, /* ms */
 };
 
 static const struct of_device_id musb_dsps_of_match[] = {
        { .compatible = "ti,musb-am33xx",
-               .data = (void *) &am33xx_driver_data, },
+               .data = &am33xx_driver_data, },
+       { .compatible = "ti,musb-dm816",
+               .data = &am33xx_driver_data, },
        {  },
 };
 MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
@@ -929,7 +911,8 @@ static int dsps_resume(struct device *dev)
        dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode);
        if (musb->xceiv->otg->state == OTG_STATE_B_IDLE &&
            musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
-               mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
+               mod_timer(&glue->timer, jiffies +
+                               msecs_to_jiffies(wrp->poll_timeout));
 
        return 0;
 }
index b2d9040c7685ba6a63ebcfa4ec59676e931369b1..4c481cd66c77a9724dc5725d8e950dbc51bf23a5 100644 (file)
@@ -1876,44 +1876,6 @@ err:
        return retval;
 }
 
-static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
-{
-       int                     i;
-       struct musb_hw_ep       *hw_ep;
-
-       /* don't disconnect if it's not connected */
-       if (musb->g.speed == USB_SPEED_UNKNOWN)
-               driver = NULL;
-       else
-               musb->g.speed = USB_SPEED_UNKNOWN;
-
-       /* deactivate the hardware */
-       if (musb->softconnect) {
-               musb->softconnect = 0;
-               musb_pullup(musb, 0);
-       }
-       musb_stop(musb);
-
-       /* killing any outstanding requests will quiesce the driver;
-        * then report disconnect
-        */
-       if (driver) {
-               for (i = 0, hw_ep = musb->endpoints;
-                               i < musb->nr_endpoints;
-                               i++, hw_ep++) {
-                       musb_ep_select(musb->mregs, i);
-                       if (hw_ep->is_shared_fifo /* || !epnum */) {
-                               nuke(&hw_ep->ep_in, -ESHUTDOWN);
-                       } else {
-                               if (hw_ep->max_packet_sz_tx)
-                                       nuke(&hw_ep->ep_in, -ESHUTDOWN);
-                               if (hw_ep->max_packet_sz_rx)
-                                       nuke(&hw_ep->ep_out, -ESHUTDOWN);
-                       }
-               }
-       }
-}
-
 /*
  * Unregister the gadget driver. Used by gadget drivers when
  * unregistering themselves from the controller.
@@ -1940,7 +1902,7 @@ static int musb_gadget_stop(struct usb_gadget *g)
        (void) musb_gadget_vbus_draw(&musb->g, 0);
 
        musb->xceiv->otg->state = OTG_STATE_UNDEFINED;
-       stop_activity(musb, NULL);
+       musb_stop(musb);
        otg_set_peripheral(musb->xceiv->otg, NULL);
 
        musb->is_active = 0;
index 294e159f4afe82a9f96a3d449976b7a2f48d6a13..86c4b533e90b3f9d33c4ff06c8e58d59928754f3 100644 (file)
@@ -136,7 +136,7 @@ void musb_port_suspend(struct musb *musb, bool do_suspend)
                /* later, GetPortStatus will stop RESUME signaling */
                musb->port1_status |= MUSB_PORT_STAT_RESUME;
                schedule_delayed_work(&musb->finish_resume_work,
-                                     msecs_to_jiffies(20));
+                                     msecs_to_jiffies(USB_RESUME_TIMEOUT));
        }
 }
 
@@ -345,7 +345,7 @@ int musb_hub_control(
                struct usb_hub_descriptor *desc = (void *)buf;
 
                desc->bDescLength = 9;
-               desc->bDescriptorType = 0x29;
+               desc->bDescriptorType = USB_DT_HUB;
                desc->bNbrPorts = 1;
                desc->wHubCharacteristics = cpu_to_le16(
                        HUB_CHAR_INDV_PORT_LPSM /* per-port power switching */
index 52d3d58252e1fd4a3702705a8d12f57d81942ca2..2175678e674ebf4408635f5582eee50d4bb17400 100644 (file)
@@ -139,7 +139,7 @@ config USB_ISP1301
 
 config USB_MSM_OTG
        tristate "Qualcomm on-chip USB OTG controller support"
-       depends on (USB || USB_GADGET) && (ARCH_MSM || ARCH_QCOM || COMPILE_TEST)
+       depends on (USB || USB_GADGET) && (ARCH_QCOM || COMPILE_TEST)
        depends on RESET_CONTROLLER
        select USB_PHY
        help
@@ -202,13 +202,13 @@ config USB_RCAR_GEN2_PHY
 config USB_ULPI
        bool "Generic ULPI Transceiver Driver"
        depends on ARM || ARM64
+       select USB_ULPI_VIEWPORT
        help
          Enable this to support ULPI connected USB OTG transceivers which
          are likely found on embedded boards.
 
 config USB_ULPI_VIEWPORT
        bool
-       depends on USB_ULPI
        help
          Provides read/write operations to the ULPI phy register set for
          controllers with a viewport register (e.g. Chipidea/ARC controllers).
index 7ea0154da9d55cfbdc2577be053f4478ad0031d2..66ffa82457a8a5c79038f09d4780f4f5a70c85ee 100644 (file)
@@ -27,7 +27,7 @@ static const char *const usbphy_modes[] = {
  * @np:        Pointer to the given device_node
  *
  * The function gets phy interface string from property 'phy_type',
- * and returns the correspondig enum usb_phy_interface
+ * and returns the corresponding enum usb_phy_interface
  */
 enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np)
 {
index 0b1bd2369293d98468641541cee2e1ccc22493d4..7225d526df0446ff26fd69ef65268265737d8c66 100644 (file)
@@ -277,7 +277,7 @@ static void ab8500_usb_regulator_enable(struct ab8500_usb *ab)
                        dev_err(ab->dev, "Failed to set the Vintcore to 1.3V, ret=%d\n",
                                        ret);
 
-               ret = regulator_set_optimum_mode(ab->v_ulpi, 28000);
+               ret = regulator_set_load(ab->v_ulpi, 28000);
                if (ret < 0)
                        dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
                                        ret);
@@ -317,7 +317,7 @@ static void ab8500_usb_regulator_disable(struct ab8500_usb *ab)
                                                ab->saved_v_ulpi, ret);
                }
 
-               ret = regulator_set_optimum_mode(ab->v_ulpi, 0);
+               ret = regulator_set_load(ab->v_ulpi, 0);
                if (ret < 0)
                        dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
                                        ret);
@@ -893,7 +893,7 @@ static int abx500_usb_link_status_update(struct ab8500_usb *ab)
 
 /*
  * Disconnection Sequence:
- *   1. Disconect Interrupt
+ *   1. Disconnect Interrupt
  *   2. Disable regulators
  *   3. Disable AB clock
  *   4. Disable the Phy
index 70be50b734b28972a89c426028c7166744d7581a..deee68eafb72a70c8c504d659e8fc573cc270d09 100644 (file)
@@ -62,14 +62,14 @@ static int nop_set_suspend(struct usb_phy *x, int suspend)
        return 0;
 }
 
-static void nop_reset_set(struct usb_phy_generic *nop, int asserted)
+static void nop_reset(struct usb_phy_generic *nop)
 {
        if (!nop->gpiod_reset)
                return;
 
-       gpiod_direction_output(nop->gpiod_reset, !asserted);
+       gpiod_set_value(nop->gpiod_reset, 1);
        usleep_range(10000, 20000);
-       gpiod_set_value(nop->gpiod_reset, asserted);
+       gpiod_set_value(nop->gpiod_reset, 0);
 }
 
 /* interface to regulator framework */
@@ -151,8 +151,7 @@ int usb_gen_phy_init(struct usb_phy *phy)
        if (!IS_ERR(nop->clk))
                clk_prepare_enable(nop->clk);
 
-       /* De-assert RESET */
-       nop_reset_set(nop, 0);
+       nop_reset(nop);
 
        return 0;
 }
@@ -162,8 +161,7 @@ void usb_gen_phy_shutdown(struct usb_phy *phy)
 {
        struct usb_phy_generic *nop = dev_get_drvdata(phy->dev);
 
-       /* Assert RESET */
-       nop_reset_set(nop, 1);
+       gpiod_set_value(nop->gpiod_reset, 1);
 
        if (!IS_ERR(nop->clk))
                clk_disable_unprepare(nop->clk);
index 000fd892455f7de0f31c94f44aad116d1c244f61..c9156beeadef66718e82e002bb53569c64ffdd13 100644 (file)
@@ -142,27 +142,22 @@ static int msm_hsusb_ldo_set_mode(struct msm_otg *motg, int on)
        int ret = 0;
 
        if (on) {
-               ret = regulator_set_optimum_mode(motg->v1p8,
-                               USB_PHY_1P8_HPM_LOAD);
+               ret = regulator_set_load(motg->v1p8, USB_PHY_1P8_HPM_LOAD);
                if (ret < 0) {
                        pr_err("Could not set HPM for v1p8\n");
                        return ret;
                }
-               ret = regulator_set_optimum_mode(motg->v3p3,
-                               USB_PHY_3P3_HPM_LOAD);
+               ret = regulator_set_load(motg->v3p3, USB_PHY_3P3_HPM_LOAD);
                if (ret < 0) {
                        pr_err("Could not set HPM for v3p3\n");
-                       regulator_set_optimum_mode(motg->v1p8,
-                               USB_PHY_1P8_LPM_LOAD);
+                       regulator_set_load(motg->v1p8, USB_PHY_1P8_LPM_LOAD);
                        return ret;
                }
        } else {
-               ret = regulator_set_optimum_mode(motg->v1p8,
-                               USB_PHY_1P8_LPM_LOAD);
+               ret = regulator_set_load(motg->v1p8, USB_PHY_1P8_LPM_LOAD);
                if (ret < 0)
                        pr_err("Could not set LPM for v1p8\n");
-               ret = regulator_set_optimum_mode(motg->v3p3,
-                               USB_PHY_3P3_LPM_LOAD);
+               ret = regulator_set_load(motg->v3p3, USB_PHY_3P3_LPM_LOAD);
                if (ret < 0)
                        pr_err("Could not set LPM for v3p3\n");
        }
@@ -263,9 +258,7 @@ static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
 {
        int ret;
 
-       if (motg->pdata->link_clk_reset)
-               ret = motg->pdata->link_clk_reset(motg->clk, assert);
-       else if (assert)
+       if (assert)
                ret = reset_control_assert(motg->link_rst);
        else
                ret = reset_control_deassert(motg->link_rst);
@@ -281,9 +274,7 @@ static int msm_otg_phy_clk_reset(struct msm_otg *motg)
 {
        int ret = 0;
 
-       if (motg->pdata->phy_clk_reset)
-               ret = motg->pdata->phy_clk_reset(motg->phy_reset_clk);
-       else if (motg->phy_rst)
+       if (motg->phy_rst)
                ret = reset_control_reset(motg->phy_rst);
 
        if (ret)
@@ -1551,16 +1542,6 @@ static int msm_otg_probe(struct platform_device *pdev)
        phy = &motg->phy;
        phy->dev = &pdev->dev;
 
-       if (motg->pdata->phy_clk_reset) {
-               motg->phy_reset_clk = devm_clk_get(&pdev->dev,
-                                          np ? "phy" : "usb_phy_clk");
-
-               if (IS_ERR(motg->phy_reset_clk)) {
-                       dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
-                       return PTR_ERR(motg->phy_reset_clk);
-               }
-       }
-
        motg->clk = devm_clk_get(&pdev->dev, np ? "core" : "usb_hs_clk");
        if (IS_ERR(motg->clk)) {
                dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
index f83808413ba2296ccda2587bf719cf6ce0219dd5..f81800b6562a46a866407897a2b8b4753e56e133 100644 (file)
@@ -47,7 +47,7 @@ struct rcar_gen2_usb_phy_priv {
 
 /* USB General status register */
 #define USBHS_UGSTS_REG                        0x88
-#define USBHS_UGSTS_LOCK               (3 << 8)
+#define USBHS_UGSTS_LOCK               (1 << 8)
 
 /* Enable USBHS internal phy */
 static int __rcar_gen2_usbhs_phy_enable(void __iomem *base)
index 2f9735b3533891c85dc907d8b1cc95a1e50d2559..d1cd6b50f5204898f0ed11785eecc73d1d6f5ebd 100644 (file)
@@ -81,7 +81,9 @@ static void devm_usb_phy_release(struct device *dev, void *res)
 
 static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
 {
-       return res == match_data;
+       struct usb_phy **phy = res;
+
+       return *phy == match_data;
 }
 
 /**
index 4cf77d3c3bd23cb5db6d5dde887eb9255c2d949b..0f7e850fd4aaff625f8c22e306d0496f358977be 100644 (file)
@@ -275,6 +275,16 @@ int usbhs_set_device_config(struct usbhs_priv *priv, int devnum,
        return 0;
 }
 
+/*
+ *             interrupt functions
+ */
+void usbhs_xxxsts_clear(struct usbhs_priv *priv, u16 sts_reg, u16 bit)
+{
+       u16 pipe_mask = (u16)GENMASK(usbhs_get_dparam(priv, pipe_size), 0);
+
+       usbhs_write(priv, sts_reg, ~(1 << bit) & pipe_mask);
+}
+
 /*
  *             local functions
  */
@@ -487,6 +497,15 @@ static struct renesas_usbhs_platform_info *usbhs_parse_dt(struct device *dev)
        if (gpio > 0)
                dparam->enable_gpio = gpio;
 
+       switch (dparam->type) {
+       case USBHS_TYPE_R8A7790:
+       case USBHS_TYPE_R8A7791:
+               dparam->has_usb_dmac = 1;
+               break;
+       default:
+               break;
+       }
+
        return info;
 }
 
index fc96e924edc4684a200190319c39eebe022f0572..8c5fc12ad7781f7a83ef9ec142107fd542b1e0f8 100644 (file)
@@ -193,6 +193,7 @@ struct usbhs_priv;
 #define TYPE_BULK      (1 << 14)
 #define TYPE_INT       (2 << 14)
 #define TYPE_ISO       (3 << 14)
+#define BFRE           (1 << 10)       /* BRDY Interrupt Operation Spec. */
 #define DBLB           (1 << 9)        /* Double Buffer Mode */
 #define SHTNAK         (1 << 7)        /* Pipe Disable in Transfer End */
 #define DIR_OUT                (1 << 4)        /* Transfer Direction */
@@ -216,6 +217,7 @@ struct usbhs_priv;
 #define        ACLRM           (1 << 9)        /* Buffer Auto-Clear Mode */
 #define SQCLR          (1 << 8)        /* Toggle Bit Clear */
 #define SQSET          (1 << 7)        /* Toggle Bit Set */
+#define SQMON          (1 << 6)        /* Toggle Bit Check */
 #define PBUSY          (1 << 5)        /* Pipe Busy */
 #define PID_MASK       (0x3)           /* Response PID */
 #define  PID_NAK       0
@@ -323,6 +325,11 @@ int usbhs_frame_get_num(struct usbhs_priv *priv);
 int usbhs_set_device_config(struct usbhs_priv *priv, int devnum, u16 upphub,
                           u16 hubport, u16 speed);
 
+/*
+ * interrupt functions
+ */
+void usbhs_xxxsts_clear(struct usbhs_priv *priv, u16 sts_reg, u16 bit);
+
 /*
  * data
  */
index d891bff39d66cc538f50c71f4547e763581f197b..8597cf9cfceb7715883738ac8cf1c0380e9a00b1 100644 (file)
@@ -813,7 +813,8 @@ static void xfer_work(struct work_struct *work)
        desc->callback          = usbhsf_dma_complete;
        desc->callback_param    = pipe;
 
-       if (dmaengine_submit(desc) < 0) {
+       pkt->cookie = dmaengine_submit(desc);
+       if (pkt->cookie < 0) {
                dev_err(dev, "Failed to submit dma descriptor\n");
                return;
        }
@@ -822,10 +823,10 @@ static void xfer_work(struct work_struct *work)
                fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
 
        usbhs_pipe_running(pipe, 1);
-       usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
-       usbhs_pipe_enable(pipe);
        usbhsf_dma_start(pipe, fifo);
+       usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
        dma_async_issue_pending(chan);
+       usbhs_pipe_enable(pipe);
 }
 
 /*
@@ -838,6 +839,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
        struct usbhs_fifo *fifo;
        int len = pkt->length - pkt->actual;
        int ret;
+       uintptr_t align_mask;
 
        if (usbhs_pipe_is_busy(pipe))
                return 0;
@@ -847,10 +849,14 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
            usbhs_pipe_is_dcp(pipe))
                goto usbhsf_pio_prepare_push;
 
-       if (len & 0x7) /* 8byte alignment */
+       /* check data length if this driver don't use USB-DMAC */
+       if (!usbhs_get_dparam(priv, has_usb_dmac) && len & 0x7)
                goto usbhsf_pio_prepare_push;
 
-       if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
+       /* check buffer alignment */
+       align_mask = usbhs_get_dparam(priv, has_usb_dmac) ?
+                                       USBHS_USB_DMAC_XFER_SIZE - 1 : 0x7;
+       if ((uintptr_t)(pkt->buf + pkt->actual) & align_mask)
                goto usbhsf_pio_prepare_push;
 
        /* return at this time if the pipe is running */
@@ -924,7 +930,85 @@ struct usbhs_pkt_handle usbhs_fifo_dma_push_handler = {
 /*
  *             DMA pop handler
  */
-static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)
+
+static int usbhsf_dma_prepare_pop_with_rx_irq(struct usbhs_pkt *pkt,
+                                             int *is_done)
+{
+       return usbhsf_prepare_pop(pkt, is_done);
+}
+
+static int usbhsf_dma_prepare_pop_with_usb_dmac(struct usbhs_pkt *pkt,
+                                               int *is_done)
+{
+       struct usbhs_pipe *pipe = pkt->pipe;
+       struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+       struct usbhs_fifo *fifo;
+       int ret;
+
+       if (usbhs_pipe_is_busy(pipe))
+               return 0;
+
+       /* use PIO if packet is less than pio_dma_border or pipe is DCP */
+       if ((pkt->length < usbhs_get_dparam(priv, pio_dma_border)) ||
+           usbhs_pipe_is_dcp(pipe))
+               goto usbhsf_pio_prepare_pop;
+
+       fifo = usbhsf_get_dma_fifo(priv, pkt);
+       if (!fifo)
+               goto usbhsf_pio_prepare_pop;
+
+       if ((uintptr_t)pkt->buf & (USBHS_USB_DMAC_XFER_SIZE - 1))
+               goto usbhsf_pio_prepare_pop;
+
+       usbhs_pipe_config_change_bfre(pipe, 1);
+
+       ret = usbhsf_fifo_select(pipe, fifo, 0);
+       if (ret < 0)
+               goto usbhsf_pio_prepare_pop;
+
+       if (usbhsf_dma_map(pkt) < 0)
+               goto usbhsf_pio_prepare_pop_unselect;
+
+       /* DMA */
+
+       /*
+        * usbhs_fifo_dma_pop_handler :: prepare
+        * enabled irq to come here.
+        * but it is no longer needed for DMA. disable it.
+        */
+       usbhsf_rx_irq_ctrl(pipe, 0);
+
+       pkt->trans = pkt->length;
+
+       INIT_WORK(&pkt->work, xfer_work);
+       schedule_work(&pkt->work);
+
+       return 0;
+
+usbhsf_pio_prepare_pop_unselect:
+       usbhsf_fifo_unselect(pipe, fifo);
+usbhsf_pio_prepare_pop:
+
+       /*
+        * change handler to PIO
+        */
+       pkt->handler = &usbhs_fifo_pio_pop_handler;
+       usbhs_pipe_config_change_bfre(pipe, 0);
+
+       return pkt->handler->prepare(pkt, is_done);
+}
+
+static int usbhsf_dma_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
+{
+       struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe);
+
+       if (usbhs_get_dparam(priv, has_usb_dmac))
+               return usbhsf_dma_prepare_pop_with_usb_dmac(pkt, is_done);
+       else
+               return usbhsf_dma_prepare_pop_with_rx_irq(pkt, is_done);
+}
+
+static int usbhsf_dma_try_pop_with_rx_irq(struct usbhs_pkt *pkt, int *is_done)
 {
        struct usbhs_pipe *pipe = pkt->pipe;
        struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
@@ -993,7 +1077,16 @@ usbhsf_pio_prepare_pop:
        return pkt->handler->try_run(pkt, is_done);
 }
 
-static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done)
+static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)
+{
+       struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe);
+
+       BUG_ON(usbhs_get_dparam(priv, has_usb_dmac));
+
+       return usbhsf_dma_try_pop_with_rx_irq(pkt, is_done);
+}
+
+static int usbhsf_dma_pop_done_with_rx_irq(struct usbhs_pkt *pkt, int *is_done)
 {
        struct usbhs_pipe *pipe = pkt->pipe;
        int maxp = usbhs_pipe_get_maxpacket(pipe);
@@ -1017,8 +1110,68 @@ static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done)
        return 0;
 }
 
+static size_t usbhs_dma_calc_received_size(struct usbhs_pkt *pkt,
+                                          struct dma_chan *chan, int dtln)
+{
+       struct usbhs_pipe *pipe = pkt->pipe;
+       struct dma_tx_state state;
+       size_t received_size;
+       int maxp = usbhs_pipe_get_maxpacket(pipe);
+
+       dmaengine_tx_status(chan, pkt->cookie, &state);
+       received_size = pkt->length - state.residue;
+
+       if (dtln) {
+               received_size -= USBHS_USB_DMAC_XFER_SIZE;
+               received_size &= ~(maxp - 1);
+               received_size += dtln;
+       }
+
+       return received_size;
+}
+
+static int usbhsf_dma_pop_done_with_usb_dmac(struct usbhs_pkt *pkt,
+                                            int *is_done)
+{
+       struct usbhs_pipe *pipe = pkt->pipe;
+       struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+       struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe);
+       struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt);
+       int rcv_len;
+
+       /*
+        * Since the driver disables rx_irq in DMA mode, the interrupt handler
+        * cannot the BRDYSTS. So, the function clears it here because the
+        * driver may use PIO mode next time.
+        */
+       usbhs_xxxsts_clear(priv, BRDYSTS, usbhs_pipe_number(pipe));
+
+       rcv_len = usbhsf_fifo_rcv_len(priv, fifo);
+       usbhsf_fifo_clear(pipe, fifo);
+       pkt->actual = usbhs_dma_calc_received_size(pkt, chan, rcv_len);
+
+       usbhsf_dma_stop(pipe, fifo);
+       usbhsf_dma_unmap(pkt);
+       usbhsf_fifo_unselect(pipe, pipe->fifo);
+
+       /* The driver can assume the rx transaction is always "done" */
+       *is_done = 1;
+
+       return 0;
+}
+
+static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done)
+{
+       struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe);
+
+       if (usbhs_get_dparam(priv, has_usb_dmac))
+               return usbhsf_dma_pop_done_with_usb_dmac(pkt, is_done);
+       else
+               return usbhsf_dma_pop_done_with_rx_irq(pkt, is_done);
+}
+
 struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler = {
-       .prepare        = usbhsf_prepare_pop,
+       .prepare        = usbhsf_dma_prepare_pop,
        .try_run        = usbhsf_dma_try_pop,
        .dma_done       = usbhsf_dma_pop_done
 };
@@ -1069,23 +1222,29 @@ static void usbhsf_dma_init_pdev(struct usbhs_fifo *fifo)
                                            &fifo->rx_slave);
 }
 
-static void usbhsf_dma_init_dt(struct device *dev, struct usbhs_fifo *fifo)
+static void usbhsf_dma_init_dt(struct device *dev, struct usbhs_fifo *fifo,
+                              int channel)
 {
-       fifo->tx_chan = dma_request_slave_channel_reason(dev, "tx");
+       char name[16];
+
+       snprintf(name, sizeof(name), "tx%d", channel);
+       fifo->tx_chan = dma_request_slave_channel_reason(dev, name);
        if (IS_ERR(fifo->tx_chan))
                fifo->tx_chan = NULL;
-       fifo->rx_chan = dma_request_slave_channel_reason(dev, "rx");
+
+       snprintf(name, sizeof(name), "rx%d", channel);
+       fifo->rx_chan = dma_request_slave_channel_reason(dev, name);
        if (IS_ERR(fifo->rx_chan))
                fifo->rx_chan = NULL;
 }
 
-static void usbhsf_dma_init(struct usbhs_priv *priv,
-                           struct usbhs_fifo *fifo)
+static void usbhsf_dma_init(struct usbhs_priv *priv, struct usbhs_fifo *fifo,
+                           int channel)
 {
        struct device *dev = usbhs_priv_to_dev(priv);
 
        if (dev->of_node)
-               usbhsf_dma_init_dt(dev, fifo);
+               usbhsf_dma_init_dt(dev, fifo, channel);
        else
                usbhsf_dma_init_pdev(fifo);
 
@@ -1231,7 +1390,7 @@ do {                                                                      \
                        usbhs_get_dparam(priv, d##channel##_tx_id);     \
        fifo->rx_slave.shdma_slave.slave_id =                           \
                        usbhs_get_dparam(priv, d##channel##_rx_id);     \
-       usbhsf_dma_init(priv, fifo);                                    \
+       usbhsf_dma_init(priv, fifo, channel);                           \
 } while (0)
 
 #define USBHS_DFIFO_INIT(priv, fifo, channel)                          \
index f07037c1185fd91683da6f8d83b7928324e50881..04d3f8abad9e5fcb59b71219496ee7a2122a7509 100644 (file)
@@ -58,6 +58,7 @@ struct usbhs_pkt {
                     struct usbhs_pkt *pkt);
        struct work_struct work;
        dma_addr_t dma;
+       dma_cookie_t cookie;
        void *buf;
        int length;
        int trans;
index e0384af77e567c8a278f80b1368d8fe2ce9b59e3..dc2aa326120252bcb1ed3eb45c3f31459d4f6497 100644 (file)
@@ -119,18 +119,34 @@ struct usbhsg_recip_handle {
 /*
  *             queue push/pop
  */
-static void usbhsg_queue_pop(struct usbhsg_uep *uep,
-                            struct usbhsg_request *ureq,
-                            int status)
+static void __usbhsg_queue_pop(struct usbhsg_uep *uep,
+                              struct usbhsg_request *ureq,
+                              int status)
 {
        struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
        struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
        struct device *dev = usbhsg_gpriv_to_dev(gpriv);
+       struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
 
        dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe));
 
        ureq->req.status = status;
+       spin_unlock(usbhs_priv_to_lock(priv));
        usb_gadget_giveback_request(&uep->ep, &ureq->req);
+       spin_lock(usbhs_priv_to_lock(priv));
+}
+
+static void usbhsg_queue_pop(struct usbhsg_uep *uep,
+                            struct usbhsg_request *ureq,
+                            int status)
+{
+       struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
+       struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
+       unsigned long flags;
+
+       usbhs_lock(priv, flags);
+       __usbhsg_queue_pop(uep, ureq, status);
+       usbhs_unlock(priv, flags);
 }
 
 static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt)
index 96eead6192821f183c47331ae53c8d5a248d75c6..bd050359926c50d6dd99bdb95c32f241817b0954 100644 (file)
@@ -1229,7 +1229,7 @@ static int __usbhsh_hub_get_status(struct usbhsh_hpriv *hpriv,
                break;
 
        case GetHubDescriptor:
-               desc->bDescriptorType           = 0x29;
+               desc->bDescriptorType           = USB_DT_HUB;
                desc->bHubContrCurrent          = 0;
                desc->bNbrPorts                 = roothub_id;
                desc->bDescLength               = 9;
index 007f45abe96cf962ce32298b334ef1ece701aac5..4f9c3356127adb76bb6c057affc1b8b0bd99d291 100644 (file)
@@ -84,6 +84,17 @@ static void __usbhsp_pipe_xxx_set(struct usbhs_pipe *pipe,
                usbhs_bset(priv, pipe_reg, mask, val);
 }
 
+static u16 __usbhsp_pipe_xxx_get(struct usbhs_pipe *pipe,
+                                u16 dcp_reg, u16 pipe_reg)
+{
+       struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+
+       if (usbhs_pipe_is_dcp(pipe))
+               return usbhs_read(priv, dcp_reg);
+       else
+               return usbhs_read(priv, pipe_reg);
+}
+
 /*
  *             DCPCFG/PIPECFG functions
  */
@@ -92,6 +103,11 @@ static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
        __usbhsp_pipe_xxx_set(pipe, DCPCFG, PIPECFG, mask, val);
 }
 
+static u16 usbhsp_pipe_cfg_get(struct usbhs_pipe *pipe)
+{
+       return __usbhsp_pipe_xxx_get(pipe, DCPCFG, PIPECFG);
+}
+
 /*
  *             PIPEnTRN/PIPEnTRE functions
  */
@@ -616,6 +632,11 @@ void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int sequence)
        usbhsp_pipectrl_set(pipe, mask, val);
 }
 
+static int usbhs_pipe_get_data_sequence(struct usbhs_pipe *pipe)
+{
+       return !!(usbhsp_pipectrl_get(pipe) & SQMON);
+}
+
 void usbhs_pipe_clear(struct usbhs_pipe *pipe)
 {
        if (usbhs_pipe_is_dcp(pipe)) {
@@ -626,6 +647,24 @@ void usbhs_pipe_clear(struct usbhs_pipe *pipe)
        }
 }
 
+void usbhs_pipe_config_change_bfre(struct usbhs_pipe *pipe, int enable)
+{
+       int sequence;
+
+       if (usbhs_pipe_is_dcp(pipe))
+               return;
+
+       usbhsp_pipe_select(pipe);
+       /* check if the driver needs to change the BFRE value */
+       if (!(enable ^ !!(usbhsp_pipe_cfg_get(pipe) & BFRE)))
+               return;
+
+       sequence = usbhs_pipe_get_data_sequence(pipe);
+       usbhsp_pipe_cfg_set(pipe, BFRE, enable ? BFRE : 0);
+       usbhs_pipe_clear(pipe);
+       usbhs_pipe_data_sequence(pipe, sequence);
+}
+
 static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type)
 {
        struct usbhs_pipe *pos, *pipe;
index d24a059723704cbae9c09c501f580c3ff0a450b7..b0bc7b603016728fdd26a5d123b612a5882de69f 100644 (file)
@@ -97,6 +97,7 @@ void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len);
 void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo);
 void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel,
                              u16 epnum, u16 maxp);
+void usbhs_pipe_config_change_bfre(struct usbhs_pipe *pipe, int enable);
 
 #define usbhs_pipe_sequence_data0(pipe)        usbhs_pipe_data_sequence(pipe, 0)
 #define usbhs_pipe_sequence_data1(pipe)        usbhs_pipe_data_sequence(pipe, 1)
index ede4f5fcfadda11dcdb7ab954769f827bd3c312a..c73808f095bba2b3f71ff2885778e7dd6f0ddd8d 100644 (file)
@@ -325,7 +325,6 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
        if (r) {
                dev_err(&port->dev, "%s - failed to submit interrupt urb: %d\n",
                        __func__, r);
-               ch341_close(port);
                goto out;
        }
 
index c5dc233db2d94bcbdfb9bde55770f6daf625979e..972f5a5fe577ed31686bda9cedfc75313e5ce1f1 100644 (file)
 #include <linux/serial.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
+#include <linux/serial_reg.h>
 
 static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x1934, 0x0706) },
@@ -30,37 +31,218 @@ static const struct usb_device_id id_table[] = {
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
-#define CONTROL_DTR                    0x01
-#define CONTROL_RTS                    0x02
+/* Maximum baudrate for F81232 */
+#define F81232_MAX_BAUDRATE            115200
 
-#define UART_STATE                     0x08
-#define UART_STATE_TRANSIENT_MASK      0x74
-#define UART_DCD                       0x01
-#define UART_DSR                       0x02
-#define UART_BREAK_ERROR               0x04
-#define UART_RING                      0x08
-#define UART_FRAME_ERROR               0x10
-#define UART_PARITY_ERROR              0x20
-#define UART_OVERRUN_ERROR             0x40
-#define UART_CTS                       0x80
+/* USB Control EP parameter */
+#define F81232_REGISTER_REQUEST                0xa0
+#define F81232_GET_REGISTER            0xc0
+#define F81232_SET_REGISTER            0x40
+
+#define SERIAL_BASE_ADDRESS            0x0120
+#define RECEIVE_BUFFER_REGISTER                (0x00 + SERIAL_BASE_ADDRESS)
+#define INTERRUPT_ENABLE_REGISTER      (0x01 + SERIAL_BASE_ADDRESS)
+#define FIFO_CONTROL_REGISTER          (0x02 + SERIAL_BASE_ADDRESS)
+#define LINE_CONTROL_REGISTER          (0x03 + SERIAL_BASE_ADDRESS)
+#define MODEM_CONTROL_REGISTER         (0x04 + SERIAL_BASE_ADDRESS)
+#define MODEM_STATUS_REGISTER          (0x06 + SERIAL_BASE_ADDRESS)
 
 struct f81232_private {
-       spinlock_t lock;
-       u8 line_control;
-       u8 line_status;
+       struct mutex lock;
+       u8 modem_control;
+       u8 modem_status;
+       struct work_struct interrupt_work;
+       struct usb_serial_port *port;
 };
 
+static int calc_baud_divisor(speed_t baudrate)
+{
+       return DIV_ROUND_CLOSEST(F81232_MAX_BAUDRATE, baudrate);
+}
+
+static int f81232_get_register(struct usb_serial_port *port, u16 reg, u8 *val)
+{
+       int status;
+       u8 *tmp;
+       struct usb_device *dev = port->serial->dev;
+
+       tmp = kmalloc(sizeof(*val), GFP_KERNEL);
+       if (!tmp)
+               return -ENOMEM;
+
+       status = usb_control_msg(dev,
+                               usb_rcvctrlpipe(dev, 0),
+                               F81232_REGISTER_REQUEST,
+                               F81232_GET_REGISTER,
+                               reg,
+                               0,
+                               tmp,
+                               sizeof(*val),
+                               USB_CTRL_GET_TIMEOUT);
+       if (status != sizeof(*val)) {
+               dev_err(&port->dev, "%s failed status: %d\n", __func__, status);
+
+               if (status < 0)
+                       status = usb_translate_errors(status);
+               else
+                       status = -EIO;
+       } else {
+               status = 0;
+               *val = *tmp;
+       }
+
+       kfree(tmp);
+       return status;
+}
+
+static int f81232_set_register(struct usb_serial_port *port, u16 reg, u8 val)
+{
+       int status;
+       u8 *tmp;
+       struct usb_device *dev = port->serial->dev;
+
+       tmp = kmalloc(sizeof(val), GFP_KERNEL);
+       if (!tmp)
+               return -ENOMEM;
+
+       *tmp = val;
+
+       status = usb_control_msg(dev,
+                               usb_sndctrlpipe(dev, 0),
+                               F81232_REGISTER_REQUEST,
+                               F81232_SET_REGISTER,
+                               reg,
+                               0,
+                               tmp,
+                               sizeof(val),
+                               USB_CTRL_SET_TIMEOUT);
+       if (status != sizeof(val)) {
+               dev_err(&port->dev, "%s failed status: %d\n", __func__, status);
+
+               if (status < 0)
+                       status = usb_translate_errors(status);
+               else
+                       status = -EIO;
+       } else {
+               status = 0;
+       }
+
+       kfree(tmp);
+       return status;
+}
+
+static void f81232_read_msr(struct usb_serial_port *port)
+{
+       int status;
+       u8 current_msr;
+       struct tty_struct *tty;
+       struct f81232_private *priv = usb_get_serial_port_data(port);
+
+       mutex_lock(&priv->lock);
+       status = f81232_get_register(port, MODEM_STATUS_REGISTER,
+                       &current_msr);
+       if (status) {
+               dev_err(&port->dev, "%s fail, status: %d\n", __func__, status);
+               mutex_unlock(&priv->lock);
+               return;
+       }
+
+       if (!(current_msr & UART_MSR_ANY_DELTA)) {
+               mutex_unlock(&priv->lock);
+               return;
+       }
+
+       priv->modem_status = current_msr;
+
+       if (current_msr & UART_MSR_DCTS)
+               port->icount.cts++;
+       if (current_msr & UART_MSR_DDSR)
+               port->icount.dsr++;
+       if (current_msr & UART_MSR_TERI)
+               port->icount.rng++;
+       if (current_msr & UART_MSR_DDCD) {
+               port->icount.dcd++;
+               tty = tty_port_tty_get(&port->port);
+               if (tty) {
+                       usb_serial_handle_dcd_change(port, tty,
+                                       current_msr & UART_MSR_DCD);
+
+                       tty_kref_put(tty);
+               }
+       }
+
+       wake_up_interruptible(&port->port.delta_msr_wait);
+       mutex_unlock(&priv->lock);
+}
+
+static int f81232_set_mctrl(struct usb_serial_port *port,
+                                          unsigned int set, unsigned int clear)
+{
+       u8 val;
+       int status;
+       struct f81232_private *priv = usb_get_serial_port_data(port);
+
+       if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0)
+               return 0;       /* no change */
+
+       /* 'set' takes precedence over 'clear' */
+       clear &= ~set;
+
+       /* force enable interrupt with OUT2 */
+       mutex_lock(&priv->lock);
+       val = UART_MCR_OUT2 | priv->modem_control;
+
+       if (clear & TIOCM_DTR)
+               val &= ~UART_MCR_DTR;
+
+       if (clear & TIOCM_RTS)
+               val &= ~UART_MCR_RTS;
+
+       if (set & TIOCM_DTR)
+               val |= UART_MCR_DTR;
+
+       if (set & TIOCM_RTS)
+               val |= UART_MCR_RTS;
+
+       dev_dbg(&port->dev, "%s new:%02x old:%02x\n", __func__,
+                       val, priv->modem_control);
+
+       status = f81232_set_register(port, MODEM_CONTROL_REGISTER, val);
+       if (status) {
+               dev_err(&port->dev, "%s set MCR status < 0\n", __func__);
+               mutex_unlock(&priv->lock);
+               return status;
+       }
+
+       priv->modem_control = val;
+       mutex_unlock(&priv->lock);
+
+       return 0;
+}
+
 static void f81232_update_line_status(struct usb_serial_port *port,
                                      unsigned char *data,
-                                     unsigned int actual_length)
+                                     size_t actual_length)
 {
-       /*
-        * FIXME: Update port->icount, and call
-        *
-        *              wake_up_interruptible(&port->port.delta_msr_wait);
-        *
-        *        on MSR changes.
-        */
+       struct f81232_private *priv = usb_get_serial_port_data(port);
+
+       if (!actual_length)
+               return;
+
+       switch (data[0] & 0x07) {
+       case 0x00: /* msr change */
+               dev_dbg(&port->dev, "IIR: MSR Change: %02x\n", data[0]);
+               schedule_work(&priv->interrupt_work);
+               break;
+       case 0x02: /* tx-empty */
+               break;
+       case 0x04: /* rx data available */
+               break;
+       case 0x06: /* lsr change */
+               /* we can forget it. the LSR will read from bulk-in */
+               dev_dbg(&port->dev, "IIR: LSR Change: %02x\n", data[0]);
+               break;
+       }
 }
 
 static void f81232_read_int_callback(struct urb *urb)
@@ -104,55 +286,55 @@ exit:
 static void f81232_process_read_urb(struct urb *urb)
 {
        struct usb_serial_port *port = urb->context;
-       struct f81232_private *priv = usb_get_serial_port_data(port);
        unsigned char *data = urb->transfer_buffer;
-       char tty_flag = TTY_NORMAL;
-       unsigned long flags;
-       u8 line_status;
-       int i;
-
-       /* update line status */
-       spin_lock_irqsave(&priv->lock, flags);
-       line_status = priv->line_status;
-       priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       if (!urb->actual_length)
+       char tty_flag;
+       unsigned int i;
+       u8 lsr;
+
+       /*
+        * When opening the port we get a 1-byte packet with the current LSR,
+        * which we discard.
+        */
+       if ((urb->actual_length < 2) || (urb->actual_length % 2))
                return;
 
-       /* break takes precedence over parity, */
-       /* which takes precedence over framing errors */
-       if (line_status & UART_BREAK_ERROR)
-               tty_flag = TTY_BREAK;
-       else if (line_status & UART_PARITY_ERROR)
-               tty_flag = TTY_PARITY;
-       else if (line_status & UART_FRAME_ERROR)
-               tty_flag = TTY_FRAME;
-       dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__, tty_flag);
-
-       /* overrun is special, not associated with a char */
-       if (line_status & UART_OVERRUN_ERROR)
-               tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
-
-       if (port->port.console && port->sysrq) {
-               for (i = 0; i < urb->actual_length; ++i)
-                       if (!usb_serial_handle_sysrq_char(port, data[i]))
-                               tty_insert_flip_char(&port->port, data[i],
-                                               tty_flag);
-       } else {
-               tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag,
-                                                       urb->actual_length);
+       /* bulk-in data: [LSR(1Byte)+DATA(1Byte)][LSR(1Byte)+DATA(1Byte)]... */
+
+       for (i = 0; i < urb->actual_length; i += 2) {
+               tty_flag = TTY_NORMAL;
+               lsr = data[i];
+
+               if (lsr & UART_LSR_BRK_ERROR_BITS) {
+                       if (lsr & UART_LSR_BI) {
+                               tty_flag = TTY_BREAK;
+                               port->icount.brk++;
+                               usb_serial_handle_break(port);
+                       } else if (lsr & UART_LSR_PE) {
+                               tty_flag = TTY_PARITY;
+                               port->icount.parity++;
+                       } else if (lsr & UART_LSR_FE) {
+                               tty_flag = TTY_FRAME;
+                               port->icount.frame++;
+                       }
+
+                       if (lsr & UART_LSR_OE) {
+                               port->icount.overrun++;
+                               tty_insert_flip_char(&port->port, 0,
+                                               TTY_OVERRUN);
+                       }
+               }
+
+               if (port->port.console && port->sysrq) {
+                       if (usb_serial_handle_sysrq_char(port, data[i + 1]))
+                               continue;
+               }
+
+               tty_insert_flip_char(&port->port, data[i + 1], tty_flag);
        }
 
        tty_flip_buffer_push(&port->port);
 }
 
-static int set_control_lines(struct usb_device *dev, u8 value)
-{
-       /* FIXME - Stubbed out for now */
-       return 0;
-}
-
 static void f81232_break_ctl(struct tty_struct *tty, int break_state)
 {
        /* FIXME - Stubbed out for now */
@@ -164,37 +346,198 @@ static void f81232_break_ctl(struct tty_struct *tty, int break_state)
         */
 }
 
+static void f81232_set_baudrate(struct usb_serial_port *port, speed_t baudrate)
+{
+       u8 lcr;
+       int divisor;
+       int status = 0;
+
+       divisor = calc_baud_divisor(baudrate);
+
+       status = f81232_get_register(port, LINE_CONTROL_REGISTER,
+                        &lcr); /* get LCR */
+       if (status) {
+               dev_err(&port->dev, "%s failed to get LCR: %d\n",
+                       __func__, status);
+               return;
+       }
+
+       status = f81232_set_register(port, LINE_CONTROL_REGISTER,
+                        lcr | UART_LCR_DLAB); /* Enable DLAB */
+       if (status) {
+               dev_err(&port->dev, "%s failed to set DLAB: %d\n",
+                       __func__, status);
+               return;
+       }
+
+       status = f81232_set_register(port, RECEIVE_BUFFER_REGISTER,
+                        divisor & 0x00ff); /* low */
+       if (status) {
+               dev_err(&port->dev, "%s failed to set baudrate MSB: %d\n",
+                       __func__, status);
+               goto reapply_lcr;
+       }
+
+       status = f81232_set_register(port, INTERRUPT_ENABLE_REGISTER,
+                        (divisor & 0xff00) >> 8); /* high */
+       if (status) {
+               dev_err(&port->dev, "%s failed to set baudrate LSB: %d\n",
+                       __func__, status);
+       }
+
+reapply_lcr:
+       status = f81232_set_register(port, LINE_CONTROL_REGISTER,
+                       lcr & ~UART_LCR_DLAB);
+       if (status) {
+               dev_err(&port->dev, "%s failed to set DLAB: %d\n",
+                       __func__, status);
+       }
+}
+
+static int f81232_port_enable(struct usb_serial_port *port)
+{
+       u8 val;
+       int status;
+
+       /* fifo on, trigger8, clear TX/RX*/
+       val = UART_FCR_TRIGGER_8 | UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
+                       UART_FCR_CLEAR_XMIT;
+
+       status = f81232_set_register(port, FIFO_CONTROL_REGISTER, val);
+       if (status) {
+               dev_err(&port->dev, "%s failed to set FCR: %d\n",
+                       __func__, status);
+               return status;
+       }
+
+       /* MSR Interrupt only, LSR will read from Bulk-in odd byte */
+       status = f81232_set_register(port, INTERRUPT_ENABLE_REGISTER,
+                       UART_IER_MSI);
+       if (status) {
+               dev_err(&port->dev, "%s failed to set IER: %d\n",
+                       __func__, status);
+               return status;
+       }
+
+       return 0;
+}
+
+static int f81232_port_disable(struct usb_serial_port *port)
+{
+       int status;
+
+       status = f81232_set_register(port, INTERRUPT_ENABLE_REGISTER, 0);
+       if (status) {
+               dev_err(&port->dev, "%s failed to set IER: %d\n",
+                       __func__, status);
+               return status;
+       }
+
+       return 0;
+}
+
 static void f81232_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios)
 {
-       /* FIXME - Stubbed out for now */
+       u8 new_lcr = 0;
+       int status = 0;
+       speed_t baudrate;
 
        /* Don't change anything if nothing has changed */
        if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios))
                return;
 
-       /* Do the real work here... */
-       if (old_termios)
-               tty_termios_copy_hw(&tty->termios, old_termios);
+       if (C_BAUD(tty) == B0)
+               f81232_set_mctrl(port, 0, TIOCM_DTR | TIOCM_RTS);
+       else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
+               f81232_set_mctrl(port, TIOCM_DTR | TIOCM_RTS, 0);
+
+       baudrate = tty_get_baud_rate(tty);
+       if (baudrate > 0) {
+               if (baudrate > F81232_MAX_BAUDRATE) {
+                       baudrate = F81232_MAX_BAUDRATE;
+                       tty_encode_baud_rate(tty, baudrate, baudrate);
+               }
+               f81232_set_baudrate(port, baudrate);
+       }
+
+       if (C_PARENB(tty)) {
+               new_lcr |= UART_LCR_PARITY;
+
+               if (!C_PARODD(tty))
+                       new_lcr |= UART_LCR_EPAR;
+
+               if (C_CMSPAR(tty))
+                       new_lcr |= UART_LCR_SPAR;
+       }
+
+       if (C_CSTOPB(tty))
+               new_lcr |= UART_LCR_STOP;
+
+       switch (C_CSIZE(tty)) {
+       case CS5:
+               new_lcr |= UART_LCR_WLEN5;
+               break;
+       case CS6:
+               new_lcr |= UART_LCR_WLEN6;
+               break;
+       case CS7:
+               new_lcr |= UART_LCR_WLEN7;
+               break;
+       default:
+       case CS8:
+               new_lcr |= UART_LCR_WLEN8;
+               break;
+       }
+
+       status = f81232_set_register(port, LINE_CONTROL_REGISTER, new_lcr);
+       if (status) {
+               dev_err(&port->dev, "%s failed to set LCR: %d\n",
+                       __func__, status);
+       }
 }
 
 static int f81232_tiocmget(struct tty_struct *tty)
 {
-       /* FIXME - Stubbed out for now */
-       return 0;
+       int r;
+       struct usb_serial_port *port = tty->driver_data;
+       struct f81232_private *port_priv = usb_get_serial_port_data(port);
+       u8 mcr, msr;
+
+       /* force get current MSR changed state */
+       f81232_read_msr(port);
+
+       mutex_lock(&port_priv->lock);
+       mcr = port_priv->modem_control;
+       msr = port_priv->modem_status;
+       mutex_unlock(&port_priv->lock);
+
+       r = (mcr & UART_MCR_DTR ? TIOCM_DTR : 0) |
+               (mcr & UART_MCR_RTS ? TIOCM_RTS : 0) |
+               (msr & UART_MSR_CTS ? TIOCM_CTS : 0) |
+               (msr & UART_MSR_DCD ? TIOCM_CAR : 0) |
+               (msr & UART_MSR_RI ? TIOCM_RI : 0) |
+               (msr & UART_MSR_DSR ? TIOCM_DSR : 0);
+
+       return r;
 }
 
 static int f81232_tiocmset(struct tty_struct *tty,
                        unsigned int set, unsigned int clear)
 {
-       /* FIXME - Stubbed out for now */
-       return 0;
+       struct usb_serial_port *port = tty->driver_data;
+
+       return f81232_set_mctrl(port, set, clear);
 }
 
 static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
        int result;
 
+       result = f81232_port_enable(port);
+       if (result)
+               return result;
+
        /* Setup termios */
        if (tty)
                f81232_set_termios(tty, port, NULL);
@@ -217,59 +560,73 @@ static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port)
 
 static void f81232_close(struct usb_serial_port *port)
 {
+       f81232_port_disable(port);
        usb_serial_generic_close(port);
        usb_kill_urb(port->interrupt_in_urb);
 }
 
 static void f81232_dtr_rts(struct usb_serial_port *port, int on)
 {
-       struct f81232_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
-       u8 control;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       /* Change DTR and RTS */
        if (on)
-               priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+               f81232_set_mctrl(port, TIOCM_DTR | TIOCM_RTS, 0);
        else
-               priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
-       control = priv->line_control;
-       spin_unlock_irqrestore(&priv->lock, flags);
-       set_control_lines(port->serial->dev, control);
+               f81232_set_mctrl(port, 0, TIOCM_DTR | TIOCM_RTS);
 }
 
 static int f81232_carrier_raised(struct usb_serial_port *port)
 {
+       u8 msr;
        struct f81232_private *priv = usb_get_serial_port_data(port);
-       if (priv->line_status & UART_DCD)
+
+       mutex_lock(&priv->lock);
+       msr = priv->modem_status;
+       mutex_unlock(&priv->lock);
+
+       if (msr & UART_MSR_DCD)
                return 1;
        return 0;
 }
 
+static int f81232_get_serial_info(struct usb_serial_port *port,
+               unsigned long arg)
+{
+       struct serial_struct ser;
+
+       memset(&ser, 0, sizeof(ser));
+
+       ser.type = PORT_16550A;
+       ser.line = port->minor;
+       ser.port = port->port_number;
+       ser.baud_base = F81232_MAX_BAUDRATE;
+
+       if (copy_to_user((void __user *)arg, &ser, sizeof(ser)))
+               return -EFAULT;
+
+       return 0;
+}
+
 static int f81232_ioctl(struct tty_struct *tty,
                        unsigned int cmd, unsigned long arg)
 {
-       struct serial_struct ser;
        struct usb_serial_port *port = tty->driver_data;
 
        switch (cmd) {
        case TIOCGSERIAL:
-               memset(&ser, 0, sizeof ser);
-               ser.type = PORT_16654;
-               ser.line = port->minor;
-               ser.port = port->port_number;
-               ser.baud_base = 460800;
-
-               if (copy_to_user((void __user *)arg, &ser, sizeof ser))
-                       return -EFAULT;
-
-               return 0;
+               return f81232_get_serial_info(port, arg);
        default:
                break;
        }
        return -ENOIOCTLCMD;
 }
 
+static void  f81232_interrupt_work(struct work_struct *work)
+{
+       struct f81232_private *priv =
+               container_of(work, struct f81232_private, interrupt_work);
+
+       f81232_read_msr(priv->port);
+}
+
 static int f81232_port_probe(struct usb_serial_port *port)
 {
        struct f81232_private *priv;
@@ -278,11 +635,13 @@ static int f81232_port_probe(struct usb_serial_port *port)
        if (!priv)
                return -ENOMEM;
 
-       spin_lock_init(&priv->lock);
+       mutex_init(&priv->lock);
+       INIT_WORK(&priv->interrupt_work,  f81232_interrupt_work);
 
        usb_set_serial_port_data(port, priv);
 
        port->port.drain_delay = 256;
+       priv->port = port;
 
        return 0;
 }
@@ -308,7 +667,7 @@ static struct usb_serial_driver f81232_device = {
        .bulk_out_size =        256,
        .open =                 f81232_open,
        .close =                f81232_close,
-       .dtr_rts =              f81232_dtr_rts,
+       .dtr_rts =              f81232_dtr_rts,
        .carrier_raised =       f81232_carrier_raised,
        .ioctl =                f81232_ioctl,
        .break_ctl =            f81232_break_ctl,
@@ -330,5 +689,6 @@ static struct usb_serial_driver * const serial_drivers[] = {
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_DESCRIPTION("Fintek F81232 USB to serial adaptor driver");
-MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org");
+MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org>");
+MODULE_AUTHOR("Peter Hong <peter_hong@fintek.com.tw>");
 MODULE_LICENSE("GPL v2");
index 62c2d9daa7d6b0a949de72ae0dbbbc56ac1e148c..4b55ab66a5347c44d846ce4ecff5211ac14fb6f5 100644 (file)
@@ -207,7 +207,8 @@ static struct alauda_card_info alauda_card_ids[] = {
        { 0,}
 };
 
-static struct alauda_card_info *alauda_card_find_id(unsigned char id) {
+static struct alauda_card_info *alauda_card_find_id(unsigned char id)
+{
        int i;
 
        for (i = 0; alauda_card_ids[i].id != 0; i++)
@@ -223,7 +224,8 @@ static struct alauda_card_info *alauda_card_find_id(unsigned char id) {
 static unsigned char parity[256];
 static unsigned char ecc2[256];
 
-static void nand_init_ecc(void) {
+static void nand_init_ecc(void)
+{
        int i, j, a;
 
        parity[0] = 0;
@@ -247,7 +249,8 @@ static void nand_init_ecc(void) {
 }
 
 /* compute 3-byte ecc on 256 bytes */
-static void nand_compute_ecc(unsigned char *data, unsigned char *ecc) {
+static void nand_compute_ecc(unsigned char *data, unsigned char *ecc)
+{
        int i, j, a;
        unsigned char par = 0, bit, bits[8] = {0};
 
@@ -270,11 +273,13 @@ static void nand_compute_ecc(unsigned char *data, unsigned char *ecc) {
        ecc[2] = ecc2[par];
 }
 
-static int nand_compare_ecc(unsigned char *data, unsigned char *ecc) {
+static int nand_compare_ecc(unsigned char *data, unsigned char *ecc)
+{
        return (data[0] == ecc[0] && data[1] == ecc[1] && data[2] == ecc[2]);
 }
 
-static void nand_store_ecc(unsigned char *data, unsigned char *ecc) {
+static void nand_store_ecc(unsigned char *data, unsigned char *ecc)
+{
        memcpy(data, ecc, 3);
 }
 
index 8514a2d82b72a2404420cd813f6aebff08e19f57..b3466d1395f20f7eae934d3bebb1f38b8800c230 100644 (file)
@@ -96,13 +96,13 @@ static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
        if (save_cmnd[1] >> 5) /* MULTIPLE_COUNT */
                goto invalid_fld;
        /* check protocol */
-       switch((save_cmnd[1] >> 1) & 0xf) {
-               case 3: /*no DATA */
-               case 4: /* PIO in */
-               case 5: /* PIO out */
-                       break;
-               default:
-                       goto invalid_fld;
+       switch ((save_cmnd[1] >> 1) & 0xf) {
+       case 3: /*no DATA */
+       case 4: /* PIO in */
+       case 5: /* PIO out */
+               break;
+       default:
+               goto invalid_fld;
        }
 
        /* first build the ATACB command */
@@ -132,8 +132,7 @@ static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
                                        || save_cmnd[11])
                                goto invalid_fld;
                }
-       }
-       else { /* ATA12 */
+       } else { /* ATA12 */
                srb->cmnd[ 6] = save_cmnd[3]; /* features */
                srb->cmnd[ 7] = save_cmnd[4]; /* sector count */
                srb->cmnd[ 8] = save_cmnd[5]; /* lba low */
index 599d8bff26c3f19164f5a79c428a11f3da4e3322..076178645ba43fed2e9245c9014a231207524007 100644 (file)
@@ -737,7 +737,7 @@ static void isd200_log_config(struct us_data *us, struct isd200_info *info)
                     info->ConfigData.ATAExtraConfig & ATACFGE_CONF_DESC2);
        usb_stor_dbg(us, "      Skip Device Boot: 0x%x\n",
                     info->ConfigData.ATAExtraConfig & ATACFGE_SKIP_BOOT);
-       usb_stor_dbg(us, "      ATA 3 State Supsend: 0x%x\n",
+       usb_stor_dbg(us, "      ATA 3 State Suspend: 0x%x\n",
                     info->ConfigData.ATAExtraConfig & ATACFGE_STATE_SUSPEND);
        usb_stor_dbg(us, "      Descriptor Override: 0x%x\n",
                     info->ConfigData.ATAExtraConfig & ATACFGE_DESC_OVERRIDE);
index 11f6f61c2381b287c74d2cb424cadb3086d58fd2..e9ef1eccdace88f1c4f9adb93d8ab566eb759de6 100644 (file)
@@ -216,7 +216,7 @@ done:
 static inline void hub_descriptor(struct usb_hub_descriptor *desc)
 {
        memset(desc, 0, sizeof(*desc));
-       desc->bDescriptorType = 0x29;
+       desc->bDescriptorType = USB_DT_HUB;
        desc->bDescLength = 9;
        desc->wHubCharacteristics = __constant_cpu_to_le16(
                HUB_CHAR_INDV_PORT_LPSM | HUB_CHAR_COMMON_OCPM);
index aa5af817f31c9b96de3e07f6fd1baff06035fab8..a082fe62b1f0c2cd0a2be1acc1226da8a04b530a 100644 (file)
@@ -182,7 +182,7 @@ static int wusbhc_rh_get_hub_descr(struct wusbhc *wusbhc, u16 wValue,
        if (wLength < length)
                return -ENOSPC;
        descr->bDescLength = 7 + 2 * temp;
-       descr->bDescriptorType = 0x29;  /* HUB type */
+       descr->bDescriptorType = USB_DT_HUB; /* HUB type */
        descr->bNbrPorts = wusbhc->ports_max;
        descr->wHubCharacteristics = cpu_to_le16(
                HUB_CHAR_COMMON_LPSM    /* All ports power at once */
index 88a290f57ea0dd7630f94bdf69f7923a4640e18c..c8571405146d394bfd8df9c20146df39ba1da74c 100644 (file)
@@ -163,38 +163,6 @@ static int umc_device_remove(struct device *dev)
        return 0;
 }
 
-static int umc_device_suspend(struct device *dev, pm_message_t state)
-{
-       struct umc_dev *umc;
-       struct umc_driver *umc_driver;
-       int err = 0;
-
-       umc = to_umc_dev(dev);
-
-       if (dev->driver) {
-               umc_driver = to_umc_driver(dev->driver);
-               if (umc_driver->suspend)
-                       err = umc_driver->suspend(umc, state);
-       }
-       return err;
-}
-
-static int umc_device_resume(struct device *dev)
-{
-       struct umc_dev *umc;
-       struct umc_driver *umc_driver;
-       int err = 0;
-
-       umc = to_umc_dev(dev);
-
-       if (dev->driver) {
-               umc_driver = to_umc_driver(dev->driver);
-               if (umc_driver->resume)
-                       err = umc_driver->resume(umc);
-       }
-       return err;
-}
-
 static ssize_t capability_id_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct umc_dev *umc = to_umc_dev(dev);
@@ -223,8 +191,6 @@ struct bus_type umc_bus_type = {
        .match          = umc_bus_match,
        .probe          = umc_device_probe,
        .remove         = umc_device_remove,
-       .suspend        = umc_device_suspend,
-       .resume         = umc_device_resume,
        .dev_groups     = umc_dev_groups,
 };
 EXPORT_SYMBOL_GPL(umc_bus_type);
index 46b7cfcdfbca98021f70bd34d4851a1c5ef6dc4d..c3ee39a04ea8df92e574bc3e4f061bb686ecb8e2 100644 (file)
@@ -133,8 +133,7 @@ static void whci_del_cap(struct whci_card *card, int n)
 {
        struct umc_dev *umc = card->devs[n];
 
-       if (umc != NULL)
-               umc_device_unregister(umc);
+       umc_device_unregister(umc);
 }
 
 static int whci_n_caps(struct pci_dev *pci)
index 14e27ab3245686610efb7e82dccaa84edc1377c7..7d092ddc81195814ca0409fdcc19770832f35086 100644 (file)
@@ -13,6 +13,11 @@ config VFIO_SPAPR_EEH
        depends on EEH && VFIO_IOMMU_SPAPR_TCE
        default n
 
+config VFIO_VIRQFD
+       tristate
+       depends on VFIO && EVENTFD
+       default n
+
 menuconfig VFIO
        tristate "VFIO Non-Privileged userspace driver framework"
        depends on IOMMU_API
@@ -27,3 +32,4 @@ menuconfig VFIO
          If you don't know what to do here, say N.
 
 source "drivers/vfio/pci/Kconfig"
+source "drivers/vfio/platform/Kconfig"
index 0b035b12600a7ba6aeaa8d16367fdfbe4f78c9da..7b8a31f63fea81487fed01224d978c0804f02faf 100644 (file)
@@ -1,5 +1,9 @@
+vfio_virqfd-y := virqfd.o
+
 obj-$(CONFIG_VFIO) += vfio.o
+obj-$(CONFIG_VFIO_VIRQFD) += vfio_virqfd.o
 obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
 obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
 obj-$(CONFIG_VFIO_SPAPR_EEH) += vfio_spapr_eeh.o
 obj-$(CONFIG_VFIO_PCI) += pci/
+obj-$(CONFIG_VFIO_PLATFORM) += platform/
index c6bb5da2d2a7183307b62e5a50e18e759ea2ee94..579d83bf53583f53966a01bd299e4f31a08c2bd7 100644 (file)
@@ -1,6 +1,7 @@
 config VFIO_PCI
        tristate "VFIO support for PCI devices"
        depends on VFIO && PCI && EVENTFD
+       select VFIO_VIRQFD
        help
          Support for the PCI VFIO bus driver.  This is required to make
          use of PCI drivers using the VFIO framework.
index f8a186381ae8726887657c6c868a8b2ceeef2e54..69fab0fd15aec4a5cb05c870984dc7e4bc9dcad4 100644 (file)
@@ -11,6 +11,8 @@
  * Author: Tom Lyon, pugs@cisco.com
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/device.h>
 #include <linux/eventfd.h>
 #include <linux/file.h>
@@ -25,6 +27,7 @@
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <linux/vfio.h>
+#include <linux/vgaarb.h>
 
 #include "vfio_pci_private.h"
 
 #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson@redhat.com>"
 #define DRIVER_DESC     "VFIO PCI - User Level meta-driver"
 
+static char ids[1024] __initdata;
+module_param_string(ids, ids, sizeof(ids), 0);
+MODULE_PARM_DESC(ids, "Initial PCI IDs to add to the vfio driver, format is \"vendor:device[:subvendor[:subdevice[:class[:class_mask]]]]\" and multiple comma separated entries can be specified");
+
 static bool nointxmask;
 module_param_named(nointxmask, nointxmask, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(nointxmask,
                  "Disable support for PCI 2.3 style INTx masking.  If this resolves problems for specific devices, report lspci -vvvxxx to linux-pci@vger.kernel.org so the device can be fixed automatically via the broken_intx_masking flag.");
 
+#ifdef CONFIG_VFIO_PCI_VGA
+static bool disable_vga;
+module_param(disable_vga, bool, S_IRUGO);
+MODULE_PARM_DESC(disable_vga, "Disable VGA resource access through vfio-pci");
+#endif
+
+static bool disable_idle_d3;
+module_param(disable_idle_d3, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(disable_idle_d3,
+                "Disable using the PCI D3 low power state for idle, unused devices");
+
 static DEFINE_MUTEX(driver_lock);
 
+static inline bool vfio_vga_disabled(void)
+{
+#ifdef CONFIG_VFIO_PCI_VGA
+       return disable_vga;
+#else
+       return true;
+#endif
+}
+
+/*
+ * Our VGA arbiter participation is limited since we don't know anything
+ * about the device itself.  However, if the device is the only VGA device
+ * downstream of a bridge and VFIO VGA support is disabled, then we can
+ * safely return legacy VGA IO and memory as not decoded since the user
+ * has no way to get to it and routing can be disabled externally at the
+ * bridge.
+ */
+static unsigned int vfio_pci_set_vga_decode(void *opaque, bool single_vga)
+{
+       struct vfio_pci_device *vdev = opaque;
+       struct pci_dev *tmp = NULL, *pdev = vdev->pdev;
+       unsigned char max_busnr;
+       unsigned int decodes;
+
+       if (single_vga || !vfio_vga_disabled() || pci_is_root_bus(pdev->bus))
+               return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM |
+                      VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
+
+       max_busnr = pci_bus_max_busnr(pdev->bus);
+       decodes = VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
+
+       while ((tmp = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, tmp)) != NULL) {
+               if (tmp == pdev ||
+                   pci_domain_nr(tmp->bus) != pci_domain_nr(pdev->bus) ||
+                   pci_is_root_bus(tmp->bus))
+                       continue;
+
+               if (tmp->bus->number >= pdev->bus->number &&
+                   tmp->bus->number <= max_busnr) {
+                       pci_dev_put(tmp);
+                       decodes |= VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
+                       break;
+               }
+       }
+
+       return decodes;
+}
+
+static inline bool vfio_pci_is_vga(struct pci_dev *pdev)
+{
+       return (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
+}
+
 static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev);
 
 static int vfio_pci_enable(struct vfio_pci_device *vdev)
@@ -48,6 +119,8 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
        u16 cmd;
        u8 msix_pos;
 
+       pci_set_power_state(pdev, PCI_D0);
+
        /* Don't allow our initial saved state to include busmaster */
        pci_clear_master(pdev);
 
@@ -93,10 +166,8 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
        } else
                vdev->msix_bar = 0xFF;
 
-#ifdef CONFIG_VFIO_PCI_VGA
-       if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
+       if (!vfio_vga_disabled() && vfio_pci_is_vga(pdev))
                vdev->has_vga = true;
-#endif
 
        return 0;
 }
@@ -153,20 +224,17 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
         * Try to reset the device.  The success of this is dependent on
         * being able to lock the device, which is not always possible.
         */
-       if (vdev->reset_works) {
-               int ret = pci_try_reset_function(pdev);
-               if (ret)
-                       pr_warn("%s: Failed to reset device %s (%d)\n",
-                               __func__, dev_name(&pdev->dev), ret);
-               else
-                       vdev->needs_reset = false;
-       }
+       if (vdev->reset_works && !pci_try_reset_function(pdev))
+               vdev->needs_reset = false;
 
        pci_restore_state(pdev);
 out:
        pci_disable_device(pdev);
 
        vfio_pci_try_bus_reset(vdev);
+
+       if (!disable_idle_d3)
+               pci_set_power_state(pdev, PCI_D3hot);
 }
 
 static void vfio_pci_release(void *device_data)
@@ -885,6 +953,27 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (ret) {
                iommu_group_put(group);
                kfree(vdev);
+               return ret;
+       }
+
+       if (vfio_pci_is_vga(pdev)) {
+               vga_client_register(pdev, vdev, NULL, vfio_pci_set_vga_decode);
+               vga_set_legacy_decoding(pdev,
+                                       vfio_pci_set_vga_decode(vdev, false));
+       }
+
+       if (!disable_idle_d3) {
+               /*
+                * pci-core sets the device power state to an unknown value at
+                * bootup and after being removed from a driver.  The only
+                * transition it allows from this unknown state is to D0, which
+                * typically happens when a driver calls pci_enable_device().
+                * We're not ready to enable the device yet, but we do want to
+                * be able to get to D3.  Therefore first do a D0 transition
+                * before going to D3.
+                */
+               pci_set_power_state(pdev, PCI_D0);
+               pci_set_power_state(pdev, PCI_D3hot);
        }
 
        return ret;
@@ -895,10 +984,21 @@ static void vfio_pci_remove(struct pci_dev *pdev)
        struct vfio_pci_device *vdev;
 
        vdev = vfio_del_group_dev(&pdev->dev);
-       if (vdev) {
-               iommu_group_put(pdev->dev.iommu_group);
-               kfree(vdev);
+       if (!vdev)
+               return;
+
+       iommu_group_put(pdev->dev.iommu_group);
+       kfree(vdev);
+
+       if (vfio_pci_is_vga(pdev)) {
+               vga_client_register(pdev, NULL, NULL, NULL);
+               vga_set_legacy_decoding(pdev,
+                               VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM |
+                               VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM);
        }
+
+       if (!disable_idle_d3)
+               pci_set_power_state(pdev, PCI_D0);
 }
 
 static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
@@ -1017,10 +1117,13 @@ static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev)
 
 put_devs:
        for (i = 0; i < devs.cur_index; i++) {
-               if (!ret) {
-                       tmp = vfio_device_data(devs.devices[i]);
+               tmp = vfio_device_data(devs.devices[i]);
+               if (!ret)
                        tmp->needs_reset = false;
-               }
+
+               if (!tmp->refcnt && !disable_idle_d3)
+                       pci_set_power_state(tmp->pdev, PCI_D3hot);
+
                vfio_device_put(devs.devices[i]);
        }
 
@@ -1030,10 +1133,50 @@ put_devs:
 static void __exit vfio_pci_cleanup(void)
 {
        pci_unregister_driver(&vfio_pci_driver);
-       vfio_pci_virqfd_exit();
        vfio_pci_uninit_perm_bits();
 }
 
+static void __init vfio_pci_fill_ids(void)
+{
+       char *p, *id;
+       int rc;
+
+       /* no ids passed actually */
+       if (ids[0] == '\0')
+               return;
+
+       /* add ids specified in the module parameter */
+       p = ids;
+       while ((id = strsep(&p, ","))) {
+               unsigned int vendor, device, subvendor = PCI_ANY_ID,
+                       subdevice = PCI_ANY_ID, class = 0, class_mask = 0;
+               int fields;
+
+               if (!strlen(id))
+                       continue;
+
+               fields = sscanf(id, "%x:%x:%x:%x:%x:%x",
+                               &vendor, &device, &subvendor, &subdevice,
+                               &class, &class_mask);
+
+               if (fields < 2) {
+                       pr_warn("invalid id string \"%s\"\n", id);
+                       continue;
+               }
+
+               rc = pci_add_dynid(&vfio_pci_driver, vendor, device,
+                                  subvendor, subdevice, class, class_mask, 0);
+               if (rc)
+                       pr_warn("failed to add dynamic id [%04hx:%04hx[%04hx:%04hx]] class %#08x/%08x (%d)\n",
+                               vendor, device, subvendor, subdevice,
+                               class, class_mask, rc);
+               else
+                       pr_info("add [%04hx:%04hx[%04hx:%04hx]] class %#08x/%08x\n",
+                               vendor, device, subvendor, subdevice,
+                               class, class_mask);
+       }
+}
+
 static int __init vfio_pci_init(void)
 {
        int ret;
@@ -1043,21 +1186,16 @@ static int __init vfio_pci_init(void)
        if (ret)
                return ret;
 
-       /* Start the virqfd cleanup handler */
-       ret = vfio_pci_virqfd_init();
-       if (ret)
-               goto out_virqfd;
-
        /* Register and scan for devices */
        ret = pci_register_driver(&vfio_pci_driver);
        if (ret)
                goto out_driver;
 
+       vfio_pci_fill_ids();
+
        return 0;
 
 out_driver:
-       vfio_pci_virqfd_exit();
-out_virqfd:
        vfio_pci_uninit_perm_bits();
        return ret;
 }
index 2027a27546ef4f7a816c08f7598e9c796e6c5ad7..1f577b4ac126029d2b7664b3380f25a9a1e4b267 100644 (file)
 #include <linux/msi.h>
 #include <linux/pci.h>
 #include <linux/file.h>
-#include <linux/poll.h>
 #include <linux/vfio.h>
 #include <linux/wait.h>
-#include <linux/workqueue.h>
 #include <linux/slab.h>
 
 #include "vfio_pci_private.h"
 
-/*
- * IRQfd - generic
- */
-struct virqfd {
-       struct vfio_pci_device  *vdev;
-       struct eventfd_ctx      *eventfd;
-       int                     (*handler)(struct vfio_pci_device *, void *);
-       void                    (*thread)(struct vfio_pci_device *, void *);
-       void                    *data;
-       struct work_struct      inject;
-       wait_queue_t            wait;
-       poll_table              pt;
-       struct work_struct      shutdown;
-       struct virqfd           **pvirqfd;
-};
-
-static struct workqueue_struct *vfio_irqfd_cleanup_wq;
-
-int __init vfio_pci_virqfd_init(void)
-{
-       vfio_irqfd_cleanup_wq =
-               create_singlethread_workqueue("vfio-irqfd-cleanup");
-       if (!vfio_irqfd_cleanup_wq)
-               return -ENOMEM;
-
-       return 0;
-}
-
-void vfio_pci_virqfd_exit(void)
-{
-       destroy_workqueue(vfio_irqfd_cleanup_wq);
-}
-
-static void virqfd_deactivate(struct virqfd *virqfd)
-{
-       queue_work(vfio_irqfd_cleanup_wq, &virqfd->shutdown);
-}
-
-static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
-{
-       struct virqfd *virqfd = container_of(wait, struct virqfd, wait);
-       unsigned long flags = (unsigned long)key;
-
-       if (flags & POLLIN) {
-               /* An event has been signaled, call function */
-               if ((!virqfd->handler ||
-                    virqfd->handler(virqfd->vdev, virqfd->data)) &&
-                   virqfd->thread)
-                       schedule_work(&virqfd->inject);
-       }
-
-       if (flags & POLLHUP) {
-               unsigned long flags;
-               spin_lock_irqsave(&virqfd->vdev->irqlock, flags);
-
-               /*
-                * The eventfd is closing, if the virqfd has not yet been
-                * queued for release, as determined by testing whether the
-                * vdev pointer to it is still valid, queue it now.  As
-                * with kvm irqfds, we know we won't race against the virqfd
-                * going away because we hold wqh->lock to get here.
-                */
-               if (*(virqfd->pvirqfd) == virqfd) {
-                       *(virqfd->pvirqfd) = NULL;
-                       virqfd_deactivate(virqfd);
-               }
-
-               spin_unlock_irqrestore(&virqfd->vdev->irqlock, flags);
-       }
-
-       return 0;
-}
-
-static void virqfd_ptable_queue_proc(struct file *file,
-                                    wait_queue_head_t *wqh, poll_table *pt)
-{
-       struct virqfd *virqfd = container_of(pt, struct virqfd, pt);
-       add_wait_queue(wqh, &virqfd->wait);
-}
-
-static void virqfd_shutdown(struct work_struct *work)
-{
-       struct virqfd *virqfd = container_of(work, struct virqfd, shutdown);
-       u64 cnt;
-
-       eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt);
-       flush_work(&virqfd->inject);
-       eventfd_ctx_put(virqfd->eventfd);
-
-       kfree(virqfd);
-}
-
-static void virqfd_inject(struct work_struct *work)
-{
-       struct virqfd *virqfd = container_of(work, struct virqfd, inject);
-       if (virqfd->thread)
-               virqfd->thread(virqfd->vdev, virqfd->data);
-}
-
-static int virqfd_enable(struct vfio_pci_device *vdev,
-                        int (*handler)(struct vfio_pci_device *, void *),
-                        void (*thread)(struct vfio_pci_device *, void *),
-                        void *data, struct virqfd **pvirqfd, int fd)
-{
-       struct fd irqfd;
-       struct eventfd_ctx *ctx;
-       struct virqfd *virqfd;
-       int ret = 0;
-       unsigned int events;
-
-       virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL);
-       if (!virqfd)
-               return -ENOMEM;
-
-       virqfd->pvirqfd = pvirqfd;
-       virqfd->vdev = vdev;
-       virqfd->handler = handler;
-       virqfd->thread = thread;
-       virqfd->data = data;
-
-       INIT_WORK(&virqfd->shutdown, virqfd_shutdown);
-       INIT_WORK(&virqfd->inject, virqfd_inject);
-
-       irqfd = fdget(fd);
-       if (!irqfd.file) {
-               ret = -EBADF;
-               goto err_fd;
-       }
-
-       ctx = eventfd_ctx_fileget(irqfd.file);
-       if (IS_ERR(ctx)) {
-               ret = PTR_ERR(ctx);
-               goto err_ctx;
-       }
-
-       virqfd->eventfd = ctx;
-
-       /*
-        * virqfds can be released by closing the eventfd or directly
-        * through ioctl.  These are both done through a workqueue, so
-        * we update the pointer to the virqfd under lock to avoid
-        * pushing multiple jobs to release the same virqfd.
-        */
-       spin_lock_irq(&vdev->irqlock);
-
-       if (*pvirqfd) {
-               spin_unlock_irq(&vdev->irqlock);
-               ret = -EBUSY;
-               goto err_busy;
-       }
-       *pvirqfd = virqfd;
-
-       spin_unlock_irq(&vdev->irqlock);
-
-       /*
-        * Install our own custom wake-up handling so we are notified via
-        * a callback whenever someone signals the underlying eventfd.
-        */
-       init_waitqueue_func_entry(&virqfd->wait, virqfd_wakeup);
-       init_poll_funcptr(&virqfd->pt, virqfd_ptable_queue_proc);
-
-       events = irqfd.file->f_op->poll(irqfd.file, &virqfd->pt);
-
-       /*
-        * Check if there was an event already pending on the eventfd
-        * before we registered and trigger it as if we didn't miss it.
-        */
-       if (events & POLLIN) {
-               if ((!handler || handler(vdev, data)) && thread)
-                       schedule_work(&virqfd->inject);
-       }
-
-       /*
-        * Do not drop the file until the irqfd is fully initialized,
-        * otherwise we might race against the POLLHUP.
-        */
-       fdput(irqfd);
-
-       return 0;
-err_busy:
-       eventfd_ctx_put(ctx);
-err_ctx:
-       fdput(irqfd);
-err_fd:
-       kfree(virqfd);
-
-       return ret;
-}
-
-static void virqfd_disable(struct vfio_pci_device *vdev,
-                          struct virqfd **pvirqfd)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&vdev->irqlock, flags);
-
-       if (*pvirqfd) {
-               virqfd_deactivate(*pvirqfd);
-               *pvirqfd = NULL;
-       }
-
-       spin_unlock_irqrestore(&vdev->irqlock, flags);
-
-       /*
-        * Block until we know all outstanding shutdown jobs have completed.
-        * Even if we don't queue the job, flush the wq to be sure it's
-        * been released.
-        */
-       flush_workqueue(vfio_irqfd_cleanup_wq);
-}
-
 /*
  * INTx
  */
-static void vfio_send_intx_eventfd(struct vfio_pci_device *vdev, void *unused)
+static void vfio_send_intx_eventfd(void *opaque, void *unused)
 {
+       struct vfio_pci_device *vdev = opaque;
+
        if (likely(is_intx(vdev) && !vdev->virq_disabled))
                eventfd_signal(vdev->ctx[0].trigger, 1);
 }
@@ -285,9 +74,9 @@ void vfio_pci_intx_mask(struct vfio_pci_device *vdev)
  * a signal is necessary, which can then be handled via a work queue
  * or directly depending on the caller.
  */
-static int vfio_pci_intx_unmask_handler(struct vfio_pci_device *vdev,
-                                       void *unused)
+static int vfio_pci_intx_unmask_handler(void *opaque, void *unused)
 {
+       struct vfio_pci_device *vdev = opaque;
        struct pci_dev *pdev = vdev->pdev;
        unsigned long flags;
        int ret = 0;
@@ -440,8 +229,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)
 static void vfio_intx_disable(struct vfio_pci_device *vdev)
 {
        vfio_intx_set_signal(vdev, -1);
-       virqfd_disable(vdev, &vdev->ctx[0].unmask);
-       virqfd_disable(vdev, &vdev->ctx[0].mask);
+       vfio_virqfd_disable(&vdev->ctx[0].unmask);
+       vfio_virqfd_disable(&vdev->ctx[0].mask);
        vdev->irq_type = VFIO_PCI_NUM_IRQS;
        vdev->num_ctx = 0;
        kfree(vdev->ctx);
@@ -605,8 +394,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
        vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
 
        for (i = 0; i < vdev->num_ctx; i++) {
-               virqfd_disable(vdev, &vdev->ctx[i].unmask);
-               virqfd_disable(vdev, &vdev->ctx[i].mask);
+               vfio_virqfd_disable(&vdev->ctx[i].unmask);
+               vfio_virqfd_disable(&vdev->ctx[i].mask);
        }
 
        if (msix) {
@@ -639,11 +428,12 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev,
        } else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
                int32_t fd = *(int32_t *)data;
                if (fd >= 0)
-                       return virqfd_enable(vdev, vfio_pci_intx_unmask_handler,
-                                            vfio_send_intx_eventfd, NULL,
-                                            &vdev->ctx[0].unmask, fd);
+                       return vfio_virqfd_enable((void *) vdev,
+                                                 vfio_pci_intx_unmask_handler,
+                                                 vfio_send_intx_eventfd, NULL,
+                                                 &vdev->ctx[0].unmask, fd);
 
-               virqfd_disable(vdev, &vdev->ctx[0].unmask);
+               vfio_virqfd_disable(&vdev->ctx[0].unmask);
        }
 
        return 0;
index c9f9b323f152733685f9dafc67793472921658ec..ae0e1b4c17114ab7cdea64b49330789409feb707 100644 (file)
@@ -87,9 +87,6 @@ extern ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf,
 extern int vfio_pci_init_perm_bits(void);
 extern void vfio_pci_uninit_perm_bits(void);
 
-extern int vfio_pci_virqfd_init(void);
-extern void vfio_pci_virqfd_exit(void);
-
 extern int vfio_config_init(struct vfio_pci_device *vdev);
 extern void vfio_config_free(struct vfio_pci_device *vdev);
 #endif /* VFIO_PCI_PRIVATE_H */
diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig
new file mode 100644 (file)
index 0000000..9a4403e
--- /dev/null
@@ -0,0 +1,20 @@
+config VFIO_PLATFORM
+       tristate "VFIO support for platform devices"
+       depends on VFIO && EVENTFD && ARM
+       select VFIO_VIRQFD
+       help
+         Support for platform devices with VFIO. This is required to make
+         use of platform devices present on the system using the VFIO
+         framework.
+
+         If you don't know what to do here, say N.
+
+config VFIO_AMBA
+       tristate "VFIO support for AMBA devices"
+       depends on VFIO_PLATFORM && ARM_AMBA
+       help
+         Support for ARM AMBA devices with VFIO. This is required to make
+         use of ARM AMBA devices present on the system using the VFIO
+         framework.
+
+         If you don't know what to do here, say N.
diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
new file mode 100644 (file)
index 0000000..81de144
--- /dev/null
@@ -0,0 +1,8 @@
+
+vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o
+
+obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
+
+vfio-amba-y := vfio_amba.o
+
+obj-$(CONFIG_VFIO_AMBA) += vfio-amba.o
diff --git a/drivers/vfio/platform/vfio_amba.c b/drivers/vfio/platform/vfio_amba.c
new file mode 100644 (file)
index 0000000..ff0331f
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis@virtualopensystems.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/module.h>
+#include <linux/slab.h>
+#include <linux/vfio.h>
+#include <linux/amba/bus.h>
+
+#include "vfio_platform_private.h"
+
+#define DRIVER_VERSION  "0.10"
+#define DRIVER_AUTHOR   "Antonios Motakis <a.motakis@virtualopensystems.com>"
+#define DRIVER_DESC     "VFIO for AMBA devices - User Level meta-driver"
+
+/* probing devices from the AMBA bus */
+
+static struct resource *get_amba_resource(struct vfio_platform_device *vdev,
+                                         int i)
+{
+       struct amba_device *adev = (struct amba_device *) vdev->opaque;
+
+       if (i == 0)
+               return &adev->res;
+
+       return NULL;
+}
+
+static int get_amba_irq(struct vfio_platform_device *vdev, int i)
+{
+       struct amba_device *adev = (struct amba_device *) vdev->opaque;
+       int ret = 0;
+
+       if (i < AMBA_NR_IRQS)
+               ret = adev->irq[i];
+
+       /* zero is an unset IRQ for AMBA devices */
+       return ret ? ret : -ENXIO;
+}
+
+static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
+{
+       struct vfio_platform_device *vdev;
+       int ret;
+
+       vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+       if (!vdev)
+               return -ENOMEM;
+
+       vdev->name = kasprintf(GFP_KERNEL, "vfio-amba-%08x", adev->periphid);
+       if (!vdev->name) {
+               kfree(vdev);
+               return -ENOMEM;
+       }
+
+       vdev->opaque = (void *) adev;
+       vdev->flags = VFIO_DEVICE_FLAGS_AMBA;
+       vdev->get_resource = get_amba_resource;
+       vdev->get_irq = get_amba_irq;
+
+       ret = vfio_platform_probe_common(vdev, &adev->dev);
+       if (ret) {
+               kfree(vdev->name);
+               kfree(vdev);
+       }
+
+       return ret;
+}
+
+static int vfio_amba_remove(struct amba_device *adev)
+{
+       struct vfio_platform_device *vdev;
+
+       vdev = vfio_platform_remove_common(&adev->dev);
+       if (vdev) {
+               kfree(vdev->name);
+               kfree(vdev);
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static struct amba_id pl330_ids[] = {
+       { 0, 0 },
+};
+
+MODULE_DEVICE_TABLE(amba, pl330_ids);
+
+static struct amba_driver vfio_amba_driver = {
+       .probe = vfio_amba_probe,
+       .remove = vfio_amba_remove,
+       .id_table = pl330_ids,
+       .drv = {
+               .name = "vfio-amba",
+               .owner = THIS_MODULE,
+       },
+};
+
+module_amba_driver(vfio_amba_driver);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c
new file mode 100644 (file)
index 0000000..cef645c
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis@virtualopensystems.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/module.h>
+#include <linux/slab.h>
+#include <linux/vfio.h>
+#include <linux/platform_device.h>
+
+#include "vfio_platform_private.h"
+
+#define DRIVER_VERSION  "0.10"
+#define DRIVER_AUTHOR   "Antonios Motakis <a.motakis@virtualopensystems.com>"
+#define DRIVER_DESC     "VFIO for platform devices - User Level meta-driver"
+
+/* probing devices from the linux platform bus */
+
+static struct resource *get_platform_resource(struct vfio_platform_device *vdev,
+                                             int num)
+{
+       struct platform_device *dev = (struct platform_device *) vdev->opaque;
+       int i;
+
+       for (i = 0; i < dev->num_resources; i++) {
+               struct resource *r = &dev->resource[i];
+
+               if (resource_type(r) & (IORESOURCE_MEM|IORESOURCE_IO)) {
+                       if (!num)
+                               return r;
+
+                       num--;
+               }
+       }
+       return NULL;
+}
+
+static int get_platform_irq(struct vfio_platform_device *vdev, int i)
+{
+       struct platform_device *pdev = (struct platform_device *) vdev->opaque;
+
+       return platform_get_irq(pdev, i);
+}
+
+static int vfio_platform_probe(struct platform_device *pdev)
+{
+       struct vfio_platform_device *vdev;
+       int ret;
+
+       vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+       if (!vdev)
+               return -ENOMEM;
+
+       vdev->opaque = (void *) pdev;
+       vdev->name = pdev->name;
+       vdev->flags = VFIO_DEVICE_FLAGS_PLATFORM;
+       vdev->get_resource = get_platform_resource;
+       vdev->get_irq = get_platform_irq;
+
+       ret = vfio_platform_probe_common(vdev, &pdev->dev);
+       if (ret)
+               kfree(vdev);
+
+       return ret;
+}
+
+static int vfio_platform_remove(struct platform_device *pdev)
+{
+       struct vfio_platform_device *vdev;
+
+       vdev = vfio_platform_remove_common(&pdev->dev);
+       if (vdev) {
+               kfree(vdev);
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static struct platform_driver vfio_platform_driver = {
+       .probe          = vfio_platform_probe,
+       .remove         = vfio_platform_remove,
+       .driver = {
+               .name   = "vfio-platform",
+               .owner  = THIS_MODULE,
+       },
+};
+
+module_platform_driver(vfio_platform_driver);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
new file mode 100644 (file)
index 0000000..abcff7a
--- /dev/null
@@ -0,0 +1,521 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis@virtualopensystems.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/device.h>
+#include <linux/iommu.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/vfio.h>
+
+#include "vfio_platform_private.h"
+
+static DEFINE_MUTEX(driver_lock);
+
+static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
+{
+       int cnt = 0, i;
+
+       while (vdev->get_resource(vdev, cnt))
+               cnt++;
+
+       vdev->regions = kcalloc(cnt, sizeof(struct vfio_platform_region),
+                               GFP_KERNEL);
+       if (!vdev->regions)
+               return -ENOMEM;
+
+       for (i = 0; i < cnt;  i++) {
+               struct resource *res =
+                       vdev->get_resource(vdev, i);
+
+               if (!res)
+                       goto err;
+
+               vdev->regions[i].addr = res->start;
+               vdev->regions[i].size = resource_size(res);
+               vdev->regions[i].flags = 0;
+
+               switch (resource_type(res)) {
+               case IORESOURCE_MEM:
+                       vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_MMIO;
+                       vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ;
+                       if (!(res->flags & IORESOURCE_READONLY))
+                               vdev->regions[i].flags |=
+                                       VFIO_REGION_INFO_FLAG_WRITE;
+
+                       /*
+                        * Only regions addressed with PAGE granularity may be
+                        * MMAPed securely.
+                        */
+                       if (!(vdev->regions[i].addr & ~PAGE_MASK) &&
+                                       !(vdev->regions[i].size & ~PAGE_MASK))
+                               vdev->regions[i].flags |=
+                                       VFIO_REGION_INFO_FLAG_MMAP;
+
+                       break;
+               case IORESOURCE_IO:
+                       vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
+                       break;
+               default:
+                       goto err;
+               }
+       }
+
+       vdev->num_regions = cnt;
+
+       return 0;
+err:
+       kfree(vdev->regions);
+       return -EINVAL;
+}
+
+static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
+{
+       int i;
+
+       for (i = 0; i < vdev->num_regions; i++)
+               iounmap(vdev->regions[i].ioaddr);
+
+       vdev->num_regions = 0;
+       kfree(vdev->regions);
+}
+
+static void vfio_platform_release(void *device_data)
+{
+       struct vfio_platform_device *vdev = device_data;
+
+       mutex_lock(&driver_lock);
+
+       if (!(--vdev->refcnt)) {
+               vfio_platform_regions_cleanup(vdev);
+               vfio_platform_irq_cleanup(vdev);
+       }
+
+       mutex_unlock(&driver_lock);
+
+       module_put(THIS_MODULE);
+}
+
+static int vfio_platform_open(void *device_data)
+{
+       struct vfio_platform_device *vdev = device_data;
+       int ret;
+
+       if (!try_module_get(THIS_MODULE))
+               return -ENODEV;
+
+       mutex_lock(&driver_lock);
+
+       if (!vdev->refcnt) {
+               ret = vfio_platform_regions_init(vdev);
+               if (ret)
+                       goto err_reg;
+
+               ret = vfio_platform_irq_init(vdev);
+               if (ret)
+                       goto err_irq;
+       }
+
+       vdev->refcnt++;
+
+       mutex_unlock(&driver_lock);
+       return 0;
+
+err_irq:
+       vfio_platform_regions_cleanup(vdev);
+err_reg:
+       mutex_unlock(&driver_lock);
+       module_put(THIS_MODULE);
+       return ret;
+}
+
+static long vfio_platform_ioctl(void *device_data,
+                               unsigned int cmd, unsigned long arg)
+{
+       struct vfio_platform_device *vdev = device_data;
+       unsigned long minsz;
+
+       if (cmd == VFIO_DEVICE_GET_INFO) {
+               struct vfio_device_info info;
+
+               minsz = offsetofend(struct vfio_device_info, num_irqs);
+
+               if (copy_from_user(&info, (void __user *)arg, minsz))
+                       return -EFAULT;
+
+               if (info.argsz < minsz)
+                       return -EINVAL;
+
+               info.flags = vdev->flags;
+               info.num_regions = vdev->num_regions;
+               info.num_irqs = vdev->num_irqs;
+
+               return copy_to_user((void __user *)arg, &info, minsz);
+
+       } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
+               struct vfio_region_info info;
+
+               minsz = offsetofend(struct vfio_region_info, offset);
+
+               if (copy_from_user(&info, (void __user *)arg, minsz))
+                       return -EFAULT;
+
+               if (info.argsz < minsz)
+                       return -EINVAL;
+
+               if (info.index >= vdev->num_regions)
+                       return -EINVAL;
+
+               /* map offset to the physical address  */
+               info.offset = VFIO_PLATFORM_INDEX_TO_OFFSET(info.index);
+               info.size = vdev->regions[info.index].size;
+               info.flags = vdev->regions[info.index].flags;
+
+               return copy_to_user((void __user *)arg, &info, minsz);
+
+       } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
+               struct vfio_irq_info info;
+
+               minsz = offsetofend(struct vfio_irq_info, count);
+
+               if (copy_from_user(&info, (void __user *)arg, minsz))
+                       return -EFAULT;
+
+               if (info.argsz < minsz)
+                       return -EINVAL;
+
+               if (info.index >= vdev->num_irqs)
+                       return -EINVAL;
+
+               info.flags = vdev->irqs[info.index].flags;
+               info.count = vdev->irqs[info.index].count;
+
+               return copy_to_user((void __user *)arg, &info, minsz);
+
+       } else if (cmd == VFIO_DEVICE_SET_IRQS) {
+               struct vfio_irq_set hdr;
+               u8 *data = NULL;
+               int ret = 0;
+
+               minsz = offsetofend(struct vfio_irq_set, count);
+
+               if (copy_from_user(&hdr, (void __user *)arg, minsz))
+                       return -EFAULT;
+
+               if (hdr.argsz < minsz)
+                       return -EINVAL;
+
+               if (hdr.index >= vdev->num_irqs)
+                       return -EINVAL;
+
+               if (hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK |
+                                 VFIO_IRQ_SET_ACTION_TYPE_MASK))
+                       return -EINVAL;
+
+               if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
+                       size_t size;
+
+                       if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL)
+                               size = sizeof(uint8_t);
+                       else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD)
+                               size = sizeof(int32_t);
+                       else
+                               return -EINVAL;
+
+                       if (hdr.argsz - minsz < size)
+                               return -EINVAL;
+
+                       data = memdup_user((void __user *)(arg + minsz), size);
+                       if (IS_ERR(data))
+                               return PTR_ERR(data);
+               }
+
+               mutex_lock(&vdev->igate);
+
+               ret = vfio_platform_set_irqs_ioctl(vdev, hdr.flags, hdr.index,
+                                                  hdr.start, hdr.count, data);
+               mutex_unlock(&vdev->igate);
+               kfree(data);
+
+               return ret;
+
+       } else if (cmd == VFIO_DEVICE_RESET)
+               return -EINVAL;
+
+       return -ENOTTY;
+}
+
+static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
+                                      char __user *buf, size_t count,
+                                      loff_t off)
+{
+       unsigned int done = 0;
+
+       if (!reg.ioaddr) {
+               reg.ioaddr =
+                       ioremap_nocache(reg.addr, reg.size);
+
+               if (!reg.ioaddr)
+                       return -ENOMEM;
+       }
+
+       while (count) {
+               size_t filled;
+
+               if (count >= 4 && !(off % 4)) {
+                       u32 val;
+
+                       val = ioread32(reg.ioaddr + off);
+                       if (copy_to_user(buf, &val, 4))
+                               goto err;
+
+                       filled = 4;
+               } else if (count >= 2 && !(off % 2)) {
+                       u16 val;
+
+                       val = ioread16(reg.ioaddr + off);
+                       if (copy_to_user(buf, &val, 2))
+                               goto err;
+
+                       filled = 2;
+               } else {
+                       u8 val;
+
+                       val = ioread8(reg.ioaddr + off);
+                       if (copy_to_user(buf, &val, 1))
+                               goto err;
+
+                       filled = 1;
+               }
+
+
+               count -= filled;
+               done += filled;
+               off += filled;
+               buf += filled;
+       }
+
+       return done;
+err:
+       return -EFAULT;
+}
+
+static ssize_t vfio_platform_read(void *device_data, char __user *buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct vfio_platform_device *vdev = device_data;
+       unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
+       loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
+
+       if (index >= vdev->num_regions)
+               return -EINVAL;
+
+       if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ))
+               return -EINVAL;
+
+       if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
+               return vfio_platform_read_mmio(vdev->regions[index],
+                                                       buf, count, off);
+       else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
+               return -EINVAL; /* not implemented */
+
+       return -EINVAL;
+}
+
+static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
+                                       const char __user *buf, size_t count,
+                                       loff_t off)
+{
+       unsigned int done = 0;
+
+       if (!reg.ioaddr) {
+               reg.ioaddr =
+                       ioremap_nocache(reg.addr, reg.size);
+
+               if (!reg.ioaddr)
+                       return -ENOMEM;
+       }
+
+       while (count) {
+               size_t filled;
+
+               if (count >= 4 && !(off % 4)) {
+                       u32 val;
+
+                       if (copy_from_user(&val, buf, 4))
+                               goto err;
+                       iowrite32(val, reg.ioaddr + off);
+
+                       filled = 4;
+               } else if (count >= 2 && !(off % 2)) {
+                       u16 val;
+
+                       if (copy_from_user(&val, buf, 2))
+                               goto err;
+                       iowrite16(val, reg.ioaddr + off);
+
+                       filled = 2;
+               } else {
+                       u8 val;
+
+                       if (copy_from_user(&val, buf, 1))
+                               goto err;
+                       iowrite8(val, reg.ioaddr + off);
+
+                       filled = 1;
+               }
+
+               count -= filled;
+               done += filled;
+               off += filled;
+               buf += filled;
+       }
+
+       return done;
+err:
+       return -EFAULT;
+}
+
+static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
+                                  size_t count, loff_t *ppos)
+{
+       struct vfio_platform_device *vdev = device_data;
+       unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
+       loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
+
+       if (index >= vdev->num_regions)
+               return -EINVAL;
+
+       if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE))
+               return -EINVAL;
+
+       if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
+               return vfio_platform_write_mmio(vdev->regions[index],
+                                                       buf, count, off);
+       else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
+               return -EINVAL; /* not implemented */
+
+       return -EINVAL;
+}
+
+static int vfio_platform_mmap_mmio(struct vfio_platform_region region,
+                                  struct vm_area_struct *vma)
+{
+       u64 req_len, pgoff, req_start;
+
+       req_len = vma->vm_end - vma->vm_start;
+       pgoff = vma->vm_pgoff &
+               ((1U << (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
+       req_start = pgoff << PAGE_SHIFT;
+
+       if (region.size < PAGE_SIZE || req_start + req_len > region.size)
+               return -EINVAL;
+
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff;
+
+       return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+                              req_len, vma->vm_page_prot);
+}
+
+static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma)
+{
+       struct vfio_platform_device *vdev = device_data;
+       unsigned int index;
+
+       index = vma->vm_pgoff >> (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT);
+
+       if (vma->vm_end < vma->vm_start)
+               return -EINVAL;
+       if (!(vma->vm_flags & VM_SHARED))
+               return -EINVAL;
+       if (index >= vdev->num_regions)
+               return -EINVAL;
+       if (vma->vm_start & ~PAGE_MASK)
+               return -EINVAL;
+       if (vma->vm_end & ~PAGE_MASK)
+               return -EINVAL;
+
+       if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP))
+               return -EINVAL;
+
+       if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ)
+                       && (vma->vm_flags & VM_READ))
+               return -EINVAL;
+
+       if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE)
+                       && (vma->vm_flags & VM_WRITE))
+               return -EINVAL;
+
+       vma->vm_private_data = vdev;
+
+       if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
+               return vfio_platform_mmap_mmio(vdev->regions[index], vma);
+
+       else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
+               return -EINVAL; /* not implemented */
+
+       return -EINVAL;
+}
+
+static const struct vfio_device_ops vfio_platform_ops = {
+       .name           = "vfio-platform",
+       .open           = vfio_platform_open,
+       .release        = vfio_platform_release,
+       .ioctl          = vfio_platform_ioctl,
+       .read           = vfio_platform_read,
+       .write          = vfio_platform_write,
+       .mmap           = vfio_platform_mmap,
+};
+
+int vfio_platform_probe_common(struct vfio_platform_device *vdev,
+                              struct device *dev)
+{
+       struct iommu_group *group;
+       int ret;
+
+       if (!vdev)
+               return -EINVAL;
+
+       group = iommu_group_get(dev);
+       if (!group) {
+               pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
+               return -EINVAL;
+       }
+
+       ret = vfio_add_group_dev(dev, &vfio_platform_ops, vdev);
+       if (ret) {
+               iommu_group_put(group);
+               return ret;
+       }
+
+       mutex_init(&vdev->igate);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(vfio_platform_probe_common);
+
+struct vfio_platform_device *vfio_platform_remove_common(struct device *dev)
+{
+       struct vfio_platform_device *vdev;
+
+       vdev = vfio_del_group_dev(dev);
+       if (vdev)
+               iommu_group_put(dev->iommu_group);
+
+       return vdev;
+}
+EXPORT_SYMBOL_GPL(vfio_platform_remove_common);
diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c
new file mode 100644 (file)
index 0000000..88bba57
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * VFIO platform devices interrupt handling
+ *
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis@virtualopensystems.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/eventfd.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/vfio.h>
+#include <linux/irq.h>
+
+#include "vfio_platform_private.h"
+
+static void vfio_platform_mask(struct vfio_platform_irq *irq_ctx)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&irq_ctx->lock, flags);
+
+       if (!irq_ctx->masked) {
+               disable_irq_nosync(irq_ctx->hwirq);
+               irq_ctx->masked = true;
+       }
+
+       spin_unlock_irqrestore(&irq_ctx->lock, flags);
+}
+
+static int vfio_platform_mask_handler(void *opaque, void *unused)
+{
+       struct vfio_platform_irq *irq_ctx = opaque;
+
+       vfio_platform_mask(irq_ctx);
+
+       return 0;
+}
+
+static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
+                                     unsigned index, unsigned start,
+                                     unsigned count, uint32_t flags,
+                                     void *data)
+{
+       if (start != 0 || count != 1)
+               return -EINVAL;
+
+       if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
+               return -EINVAL;
+
+       if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+               int32_t fd = *(int32_t *)data;
+
+               if (fd >= 0)
+                       return vfio_virqfd_enable((void *) &vdev->irqs[index],
+                                                 vfio_platform_mask_handler,
+                                                 NULL, NULL,
+                                                 &vdev->irqs[index].mask, fd);
+
+               vfio_virqfd_disable(&vdev->irqs[index].mask);
+               return 0;
+       }
+
+       if (flags & VFIO_IRQ_SET_DATA_NONE) {
+               vfio_platform_mask(&vdev->irqs[index]);
+
+       } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+               uint8_t mask = *(uint8_t *)data;
+
+               if (mask)
+                       vfio_platform_mask(&vdev->irqs[index]);
+       }
+
+       return 0;
+}
+
+static void vfio_platform_unmask(struct vfio_platform_irq *irq_ctx)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&irq_ctx->lock, flags);
+
+       if (irq_ctx->masked) {
+               enable_irq(irq_ctx->hwirq);
+               irq_ctx->masked = false;
+       }
+
+       spin_unlock_irqrestore(&irq_ctx->lock, flags);
+}
+
+static int vfio_platform_unmask_handler(void *opaque, void *unused)
+{
+       struct vfio_platform_irq *irq_ctx = opaque;
+
+       vfio_platform_unmask(irq_ctx);
+
+       return 0;
+}
+
+static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
+                                       unsigned index, unsigned start,
+                                       unsigned count, uint32_t flags,
+                                       void *data)
+{
+       if (start != 0 || count != 1)
+               return -EINVAL;
+
+       if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
+               return -EINVAL;
+
+       if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+               int32_t fd = *(int32_t *)data;
+
+               if (fd >= 0)
+                       return vfio_virqfd_enable((void *) &vdev->irqs[index],
+                                                 vfio_platform_unmask_handler,
+                                                 NULL, NULL,
+                                                 &vdev->irqs[index].unmask,
+                                                 fd);
+
+               vfio_virqfd_disable(&vdev->irqs[index].unmask);
+               return 0;
+       }
+
+       if (flags & VFIO_IRQ_SET_DATA_NONE) {
+               vfio_platform_unmask(&vdev->irqs[index]);
+
+       } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+               uint8_t unmask = *(uint8_t *)data;
+
+               if (unmask)
+                       vfio_platform_unmask(&vdev->irqs[index]);
+       }
+
+       return 0;
+}
+
+static irqreturn_t vfio_automasked_irq_handler(int irq, void *dev_id)
+{
+       struct vfio_platform_irq *irq_ctx = dev_id;
+       unsigned long flags;
+       int ret = IRQ_NONE;
+
+       spin_lock_irqsave(&irq_ctx->lock, flags);
+
+       if (!irq_ctx->masked) {
+               ret = IRQ_HANDLED;
+
+               /* automask maskable interrupts */
+               disable_irq_nosync(irq_ctx->hwirq);
+               irq_ctx->masked = true;
+       }
+
+       spin_unlock_irqrestore(&irq_ctx->lock, flags);
+
+       if (ret == IRQ_HANDLED)
+               eventfd_signal(irq_ctx->trigger, 1);
+
+       return ret;
+}
+
+static irqreturn_t vfio_irq_handler(int irq, void *dev_id)
+{
+       struct vfio_platform_irq *irq_ctx = dev_id;
+
+       eventfd_signal(irq_ctx->trigger, 1);
+
+       return IRQ_HANDLED;
+}
+
+static int vfio_set_trigger(struct vfio_platform_device *vdev, int index,
+                           int fd, irq_handler_t handler)
+{
+       struct vfio_platform_irq *irq = &vdev->irqs[index];
+       struct eventfd_ctx *trigger;
+       int ret;
+
+       if (irq->trigger) {
+               free_irq(irq->hwirq, irq);
+               kfree(irq->name);
+               eventfd_ctx_put(irq->trigger);
+               irq->trigger = NULL;
+       }
+
+       if (fd < 0) /* Disable only */
+               return 0;
+
+       irq->name = kasprintf(GFP_KERNEL, "vfio-irq[%d](%s)",
+                                               irq->hwirq, vdev->name);
+       if (!irq->name)
+               return -ENOMEM;
+
+       trigger = eventfd_ctx_fdget(fd);
+       if (IS_ERR(trigger)) {
+               kfree(irq->name);
+               return PTR_ERR(trigger);
+       }
+
+       irq->trigger = trigger;
+
+       irq_set_status_flags(irq->hwirq, IRQ_NOAUTOEN);
+       ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
+       if (ret) {
+               kfree(irq->name);
+               eventfd_ctx_put(trigger);
+               irq->trigger = NULL;
+               return ret;
+       }
+
+       if (!irq->masked)
+               enable_irq(irq->hwirq);
+
+       return 0;
+}
+
+static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev,
+                                        unsigned index, unsigned start,
+                                        unsigned count, uint32_t flags,
+                                        void *data)
+{
+       struct vfio_platform_irq *irq = &vdev->irqs[index];
+       irq_handler_t handler;
+
+       if (vdev->irqs[index].flags & VFIO_IRQ_INFO_AUTOMASKED)
+               handler = vfio_automasked_irq_handler;
+       else
+               handler = vfio_irq_handler;
+
+       if (!count && (flags & VFIO_IRQ_SET_DATA_NONE))
+               return vfio_set_trigger(vdev, index, -1, handler);
+
+       if (start != 0 || count != 1)
+               return -EINVAL;
+
+       if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+               int32_t fd = *(int32_t *)data;
+
+               return vfio_set_trigger(vdev, index, fd, handler);
+       }
+
+       if (flags & VFIO_IRQ_SET_DATA_NONE) {
+               handler(irq->hwirq, irq);
+
+       } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+               uint8_t trigger = *(uint8_t *)data;
+
+               if (trigger)
+                       handler(irq->hwirq, irq);
+       }
+
+       return 0;
+}
+
+int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
+                                uint32_t flags, unsigned index, unsigned start,
+                                unsigned count, void *data)
+{
+       int (*func)(struct vfio_platform_device *vdev, unsigned index,
+                   unsigned start, unsigned count, uint32_t flags,
+                   void *data) = NULL;
+
+       switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
+       case VFIO_IRQ_SET_ACTION_MASK:
+               func = vfio_platform_set_irq_mask;
+               break;
+       case VFIO_IRQ_SET_ACTION_UNMASK:
+               func = vfio_platform_set_irq_unmask;
+               break;
+       case VFIO_IRQ_SET_ACTION_TRIGGER:
+               func = vfio_platform_set_irq_trigger;
+               break;
+       }
+
+       if (!func)
+               return -ENOTTY;
+
+       return func(vdev, index, start, count, flags, data);
+}
+
+int vfio_platform_irq_init(struct vfio_platform_device *vdev)
+{
+       int cnt = 0, i;
+
+       while (vdev->get_irq(vdev, cnt) >= 0)
+               cnt++;
+
+       vdev->irqs = kcalloc(cnt, sizeof(struct vfio_platform_irq), GFP_KERNEL);
+       if (!vdev->irqs)
+               return -ENOMEM;
+
+       for (i = 0; i < cnt; i++) {
+               int hwirq = vdev->get_irq(vdev, i);
+
+               if (hwirq < 0)
+                       goto err;
+
+               spin_lock_init(&vdev->irqs[i].lock);
+
+               vdev->irqs[i].flags = VFIO_IRQ_INFO_EVENTFD;
+
+               if (irq_get_trigger_type(hwirq) & IRQ_TYPE_LEVEL_MASK)
+                       vdev->irqs[i].flags |= VFIO_IRQ_INFO_MASKABLE
+                                               | VFIO_IRQ_INFO_AUTOMASKED;
+
+               vdev->irqs[i].count = 1;
+               vdev->irqs[i].hwirq = hwirq;
+               vdev->irqs[i].masked = false;
+       }
+
+       vdev->num_irqs = cnt;
+
+       return 0;
+err:
+       kfree(vdev->irqs);
+       return -EINVAL;
+}
+
+void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev)
+{
+       int i;
+
+       for (i = 0; i < vdev->num_irqs; i++)
+               vfio_set_trigger(vdev, i, -1, NULL);
+
+       vdev->num_irqs = 0;
+       kfree(vdev->irqs);
+}
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
new file mode 100644 (file)
index 0000000..5d31e04
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis <a.motakis@virtualopensystems.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 VFIO_PLATFORM_PRIVATE_H
+#define VFIO_PLATFORM_PRIVATE_H
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+
+#define VFIO_PLATFORM_OFFSET_SHIFT   40
+#define VFIO_PLATFORM_OFFSET_MASK (((u64)(1) << VFIO_PLATFORM_OFFSET_SHIFT) - 1)
+
+#define VFIO_PLATFORM_OFFSET_TO_INDEX(off)     \
+       (off >> VFIO_PLATFORM_OFFSET_SHIFT)
+
+#define VFIO_PLATFORM_INDEX_TO_OFFSET(index)   \
+       ((u64)(index) << VFIO_PLATFORM_OFFSET_SHIFT)
+
+struct vfio_platform_irq {
+       u32                     flags;
+       u32                     count;
+       int                     hwirq;
+       char                    *name;
+       struct eventfd_ctx      *trigger;
+       bool                    masked;
+       spinlock_t              lock;
+       struct virqfd           *unmask;
+       struct virqfd           *mask;
+};
+
+struct vfio_platform_region {
+       u64                     addr;
+       resource_size_t         size;
+       u32                     flags;
+       u32                     type;
+#define VFIO_PLATFORM_REGION_TYPE_MMIO 1
+#define VFIO_PLATFORM_REGION_TYPE_PIO  2
+       void __iomem            *ioaddr;
+};
+
+struct vfio_platform_device {
+       struct vfio_platform_region     *regions;
+       u32                             num_regions;
+       struct vfio_platform_irq        *irqs;
+       u32                             num_irqs;
+       int                             refcnt;
+       struct mutex                    igate;
+
+       /*
+        * These fields should be filled by the bus specific binder
+        */
+       void            *opaque;
+       const char      *name;
+       uint32_t        flags;
+       /* callbacks to discover device resources */
+       struct resource*
+               (*get_resource)(struct vfio_platform_device *vdev, int i);
+       int     (*get_irq)(struct vfio_platform_device *vdev, int i);
+};
+
+extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
+                                     struct device *dev);
+extern struct vfio_platform_device *vfio_platform_remove_common
+                                    (struct device *dev);
+
+extern int vfio_platform_irq_init(struct vfio_platform_device *vdev);
+extern void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev);
+
+extern int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
+                                       uint32_t flags, unsigned index,
+                                       unsigned start, unsigned count,
+                                       void *data);
+
+#endif /* VFIO_PLATFORM_PRIVATE_H */
index 4cde8550144406c02715448b8fbc4a88b538189b..0d336625ac7113b0e0cc10d4a9d00283cc673766 100644 (file)
@@ -234,22 +234,21 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
 
        mutex_lock(&vfio.group_lock);
 
-       minor = vfio_alloc_group_minor(group);
-       if (minor < 0) {
-               vfio_group_unlock_and_free(group);
-               return ERR_PTR(minor);
-       }
-
        /* Did we race creating this group? */
        list_for_each_entry(tmp, &vfio.group_list, vfio_next) {
                if (tmp->iommu_group == iommu_group) {
                        vfio_group_get(tmp);
-                       vfio_free_group_minor(minor);
                        vfio_group_unlock_and_free(group);
                        return tmp;
                }
        }
 
+       minor = vfio_alloc_group_minor(group);
+       if (minor < 0) {
+               vfio_group_unlock_and_free(group);
+               return ERR_PTR(minor);
+       }
+
        dev = device_create(vfio.class, NULL,
                            MKDEV(MAJOR(vfio.group_devt), minor),
                            group, "%d", iommu_group_id(iommu_group));
diff --git a/drivers/vfio/virqfd.c b/drivers/vfio/virqfd.c
new file mode 100644 (file)
index 0000000..27c89cd
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * VFIO generic eventfd code for IRQFD support.
+ * Derived from drivers/vfio/pci/vfio_pci_intrs.c
+ *
+ * Copyright (C) 2012 Red Hat, Inc.  All rights reserved.
+ *     Author: Alex Williamson <alex.williamson@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/vfio.h>
+#include <linux/eventfd.h>
+#include <linux/file.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#define DRIVER_VERSION  "0.1"
+#define DRIVER_AUTHOR   "Alex Williamson <alex.williamson@redhat.com>"
+#define DRIVER_DESC     "IRQFD support for VFIO bus drivers"
+
+static struct workqueue_struct *vfio_irqfd_cleanup_wq;
+static DEFINE_SPINLOCK(virqfd_lock);
+
+static int __init vfio_virqfd_init(void)
+{
+       vfio_irqfd_cleanup_wq =
+               create_singlethread_workqueue("vfio-irqfd-cleanup");
+       if (!vfio_irqfd_cleanup_wq)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void __exit vfio_virqfd_exit(void)
+{
+       destroy_workqueue(vfio_irqfd_cleanup_wq);
+}
+
+static void virqfd_deactivate(struct virqfd *virqfd)
+{
+       queue_work(vfio_irqfd_cleanup_wq, &virqfd->shutdown);
+}
+
+static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+       struct virqfd *virqfd = container_of(wait, struct virqfd, wait);
+       unsigned long flags = (unsigned long)key;
+
+       if (flags & POLLIN) {
+               /* An event has been signaled, call function */
+               if ((!virqfd->handler ||
+                    virqfd->handler(virqfd->opaque, virqfd->data)) &&
+                   virqfd->thread)
+                       schedule_work(&virqfd->inject);
+       }
+
+       if (flags & POLLHUP) {
+               unsigned long flags;
+               spin_lock_irqsave(&virqfd_lock, flags);
+
+               /*
+                * The eventfd is closing, if the virqfd has not yet been
+                * queued for release, as determined by testing whether the
+                * virqfd pointer to it is still valid, queue it now.  As
+                * with kvm irqfds, we know we won't race against the virqfd
+                * going away because we hold the lock to get here.
+                */
+               if (*(virqfd->pvirqfd) == virqfd) {
+                       *(virqfd->pvirqfd) = NULL;
+                       virqfd_deactivate(virqfd);
+               }
+
+               spin_unlock_irqrestore(&virqfd_lock, flags);
+       }
+
+       return 0;
+}
+
+static void virqfd_ptable_queue_proc(struct file *file,
+                                    wait_queue_head_t *wqh, poll_table *pt)
+{
+       struct virqfd *virqfd = container_of(pt, struct virqfd, pt);
+       add_wait_queue(wqh, &virqfd->wait);
+}
+
+static void virqfd_shutdown(struct work_struct *work)
+{
+       struct virqfd *virqfd = container_of(work, struct virqfd, shutdown);
+       u64 cnt;
+
+       eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt);
+       flush_work(&virqfd->inject);
+       eventfd_ctx_put(virqfd->eventfd);
+
+       kfree(virqfd);
+}
+
+static void virqfd_inject(struct work_struct *work)
+{
+       struct virqfd *virqfd = container_of(work, struct virqfd, inject);
+       if (virqfd->thread)
+               virqfd->thread(virqfd->opaque, virqfd->data);
+}
+
+int vfio_virqfd_enable(void *opaque,
+                      int (*handler)(void *, void *),
+                      void (*thread)(void *, void *),
+                      void *data, struct virqfd **pvirqfd, int fd)
+{
+       struct fd irqfd;
+       struct eventfd_ctx *ctx;
+       struct virqfd *virqfd;
+       int ret = 0;
+       unsigned int events;
+
+       virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL);
+       if (!virqfd)
+               return -ENOMEM;
+
+       virqfd->pvirqfd = pvirqfd;
+       virqfd->opaque = opaque;
+       virqfd->handler = handler;
+       virqfd->thread = thread;
+       virqfd->data = data;
+
+       INIT_WORK(&virqfd->shutdown, virqfd_shutdown);
+       INIT_WORK(&virqfd->inject, virqfd_inject);
+
+       irqfd = fdget(fd);
+       if (!irqfd.file) {
+               ret = -EBADF;
+               goto err_fd;
+       }
+
+       ctx = eventfd_ctx_fileget(irqfd.file);
+       if (IS_ERR(ctx)) {
+               ret = PTR_ERR(ctx);
+               goto err_ctx;
+       }
+
+       virqfd->eventfd = ctx;
+
+       /*
+        * virqfds can be released by closing the eventfd or directly
+        * through ioctl.  These are both done through a workqueue, so
+        * we update the pointer to the virqfd under lock to avoid
+        * pushing multiple jobs to release the same virqfd.
+        */
+       spin_lock_irq(&virqfd_lock);
+
+       if (*pvirqfd) {
+               spin_unlock_irq(&virqfd_lock);
+               ret = -EBUSY;
+               goto err_busy;
+       }
+       *pvirqfd = virqfd;
+
+       spin_unlock_irq(&virqfd_lock);
+
+       /*
+        * Install our own custom wake-up handling so we are notified via
+        * a callback whenever someone signals the underlying eventfd.
+        */
+       init_waitqueue_func_entry(&virqfd->wait, virqfd_wakeup);
+       init_poll_funcptr(&virqfd->pt, virqfd_ptable_queue_proc);
+
+       events = irqfd.file->f_op->poll(irqfd.file, &virqfd->pt);
+
+       /*
+        * Check if there was an event already pending on the eventfd
+        * before we registered and trigger it as if we didn't miss it.
+        */
+       if (events & POLLIN) {
+               if ((!handler || handler(opaque, data)) && thread)
+                       schedule_work(&virqfd->inject);
+       }
+
+       /*
+        * Do not drop the file until the irqfd is fully initialized,
+        * otherwise we might race against the POLLHUP.
+        */
+       fdput(irqfd);
+
+       return 0;
+err_busy:
+       eventfd_ctx_put(ctx);
+err_ctx:
+       fdput(irqfd);
+err_fd:
+       kfree(virqfd);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(vfio_virqfd_enable);
+
+void vfio_virqfd_disable(struct virqfd **pvirqfd)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&virqfd_lock, flags);
+
+       if (*pvirqfd) {
+               virqfd_deactivate(*pvirqfd);
+               *pvirqfd = NULL;
+       }
+
+       spin_unlock_irqrestore(&virqfd_lock, flags);
+
+       /*
+        * Block until we know all outstanding shutdown jobs have completed.
+        * Even if we don't queue the job, flush the wq to be sure it's
+        * been released.
+        */
+       flush_workqueue(vfio_irqfd_cleanup_wq);
+}
+EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
+
+module_init(vfio_virqfd_init);
+module_exit(vfio_virqfd_exit);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
index 9a23698b6fe8398c1025ea3a234db11a4779ba09..2da5862876d1fe78fb53371bce64dde5269ad71b 100644 (file)
@@ -168,10 +168,7 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev,
        struct device_node *nproot, *np;
        int iset = 0;
 
-       nproot = of_node_get(pdev->dev.parent->of_node);
-       if (!nproot)
-               return -ENODEV;
-       nproot = of_find_node_by_name(nproot, "backlights");
+       nproot = of_get_child_by_name(pdev->dev.parent->of_node, "backlights");
        if (!nproot) {
                dev_err(&pdev->dev, "failed to find backlights node\n");
                return -ENODEV;
index efb09046a8cf7b3d8e56a4cf267fdff98f2ff194..2d9923a60076e3809d83a8435779ef5795d2590e 100644 (file)
@@ -408,6 +408,16 @@ config BACKLIGHT_PANDORA
          If you have a Pandora console, say Y to enable the
          backlight driver.
 
+config BACKLIGHT_SKY81452
+       tristate "Backlight driver for SKY81452"
+       depends on BACKLIGHT_CLASS_DEVICE && MFD_SKY81452
+       help
+         If you have a Skyworks SKY81452, say Y to enable the
+         backlight driver.
+
+         To compile this driver as a module, choose M here: the module will
+         be called sky81452-backlight
+
 config BACKLIGHT_TPS65217
        tristate "TPS65217 Backlight"
        depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217
index fcd50b73216516e2cca50e186eeb5e61999c97f8..d67073f9d421f91a6689c1d971235b2c18c4789f 100644 (file)
@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA)               += pandora_bl.o
 obj-$(CONFIG_BACKLIGHT_PCF50633)       += pcf50633-backlight.o
 obj-$(CONFIG_BACKLIGHT_PWM)            += pwm_bl.o
 obj-$(CONFIG_BACKLIGHT_SAHARA)         += kb3886_bl.o
+obj-$(CONFIG_BACKLIGHT_SKY81452)       += sky81452-backlight.o
 obj-$(CONFIG_BACKLIGHT_TOSA)           += tosa_bl.o
 obj-$(CONFIG_BACKLIGHT_TPS65217)       += tps65217_bl.o
 obj-$(CONFIG_BACKLIGHT_WM831X)         += wm831x_bl.o
index d4bd74bd5070709215c6ec4db409af67c841c4e8..b1943e7735a12881130dc3d94b4266a992fc4230 100644 (file)
@@ -165,6 +165,7 @@ static struct platform_device_id da9052_wled_ids[] = {
                .name           = "da9052-wled3",
                .driver_data    = DA9052_TYPE_WLED3,
        },
+       { },
 };
 
 static struct platform_driver da9052_wled_driver = {
diff --git a/drivers/video/backlight/sky81452-backlight.c b/drivers/video/backlight/sky81452-backlight.c
new file mode 100644 (file)
index 0000000..052fa1b
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * sky81452-backlight.c        SKY81452 backlight driver
+ *
+ * Copyright 2014 Skyworks Solutions Inc.
+ * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/platform_data/sky81452-backlight.h>
+#include <linux/slab.h>
+
+/* registers */
+#define SKY81452_REG0  0x00
+#define SKY81452_REG1  0x01
+#define SKY81452_REG2  0x02
+#define SKY81452_REG4  0x04
+#define SKY81452_REG5  0x05
+
+/* bit mask */
+#define SKY81452_CS    0xFF
+#define SKY81452_EN    0x3F
+#define SKY81452_IGPW  0x20
+#define SKY81452_PWMMD 0x10
+#define SKY81452_PHASE 0x08
+#define SKY81452_ILIM  0x04
+#define SKY81452_VSHRT 0x03
+#define SKY81452_OCP   0x80
+#define SKY81452_OTMP  0x40
+#define SKY81452_SHRT  0x3F
+#define SKY81452_OPN   0x3F
+
+#define SKY81452_DEFAULT_NAME "lcd-backlight"
+#define SKY81452_MAX_BRIGHTNESS        (SKY81452_CS + 1)
+
+#define CTZ(b) __builtin_ctz(b)
+
+static int sky81452_bl_update_status(struct backlight_device *bd)
+{
+       const struct sky81452_bl_platform_data *pdata =
+                       dev_get_platdata(bd->dev.parent);
+       const unsigned int brightness = (unsigned int)bd->props.brightness;
+       struct regmap *regmap = bl_get_data(bd);
+       int ret;
+
+       if (brightness > 0) {
+               ret = regmap_write(regmap, SKY81452_REG0, brightness - 1);
+               if (IS_ERR_VALUE(ret))
+                       return ret;
+
+               return regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
+                                       pdata->enable << CTZ(SKY81452_EN));
+       }
+
+       return regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN, 0);
+}
+
+static const struct backlight_ops sky81452_bl_ops = {
+       .update_status = sky81452_bl_update_status,
+};
+
+static ssize_t sky81452_bl_store_enable(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct regmap *regmap = bl_get_data(to_backlight_device(dev));
+       unsigned long value;
+       int ret;
+
+       ret = kstrtoul(buf, 16, &value);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+
+       ret = regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
+                                       value << CTZ(SKY81452_EN));
+       if (IS_ERR_VALUE(ret))
+               return ret;
+
+       return count;
+}
+
+static ssize_t sky81452_bl_show_open_short(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct regmap *regmap = bl_get_data(to_backlight_device(dev));
+       unsigned int reg, value = 0;
+       char tmp[3];
+       int i, ret;
+
+       reg = !strcmp(attr->attr.name, "open") ? SKY81452_REG5 : SKY81452_REG4;
+       ret = regmap_read(regmap, reg, &value);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+
+       if (value & SKY81452_SHRT) {
+               *buf = 0;
+               for (i = 0; i < 6; i++) {
+                       if (value & 0x01) {
+                               sprintf(tmp, "%d ", i + 1);
+                               strcat(buf, tmp);
+                       }
+                       value >>= 1;
+               }
+               strcat(buf, "\n");
+       } else {
+               strcpy(buf, "none\n");
+       }
+
+       return strlen(buf);
+}
+
+static ssize_t sky81452_bl_show_fault(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct regmap *regmap = bl_get_data(to_backlight_device(dev));
+       unsigned int value = 0;
+       int ret;
+
+       ret = regmap_read(regmap, SKY81452_REG4, &value);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+
+       *buf = 0;
+
+       if (value & SKY81452_OCP)
+               strcat(buf, "over-current ");
+
+       if (value & SKY81452_OTMP)
+               strcat(buf, "over-temperature");
+
+       strcat(buf, "\n");
+       return strlen(buf);
+}
+
+static DEVICE_ATTR(enable, S_IWGRP | S_IWUSR, NULL, sky81452_bl_store_enable);
+static DEVICE_ATTR(open, S_IRUGO, sky81452_bl_show_open_short, NULL);
+static DEVICE_ATTR(short, S_IRUGO, sky81452_bl_show_open_short, NULL);
+static DEVICE_ATTR(fault, S_IRUGO, sky81452_bl_show_fault, NULL);
+
+static struct attribute *sky81452_bl_attribute[] = {
+       &dev_attr_enable.attr,
+       &dev_attr_open.attr,
+       &dev_attr_short.attr,
+       &dev_attr_fault.attr,
+       NULL
+};
+
+static const struct attribute_group sky81452_bl_attr_group = {
+       .attrs = sky81452_bl_attribute,
+};
+
+#ifdef CONFIG_OF
+static struct sky81452_bl_platform_data *sky81452_bl_parse_dt(
+                                                       struct device *dev)
+{
+       struct device_node *np = of_node_get(dev->of_node);
+       struct sky81452_bl_platform_data *pdata;
+       int num_entry;
+       unsigned int sources[6];
+       int ret;
+
+       if (!np) {
+               dev_err(dev, "backlight node not found.\n");
+               return ERR_PTR(-ENODATA);
+       }
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               of_node_put(np);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       of_property_read_string(np, "name", &pdata->name);
+       pdata->ignore_pwm = of_property_read_bool(np, "skyworks,ignore-pwm");
+       pdata->dpwm_mode = of_property_read_bool(np, "skyworks,dpwm-mode");
+       pdata->phase_shift = of_property_read_bool(np, "skyworks,phase-shift");
+       pdata->gpio_enable = of_get_gpio(np, 0);
+
+       ret = of_property_count_u32_elems(np, "led-sources");
+       if (IS_ERR_VALUE(ret)) {
+               pdata->enable = SKY81452_EN >> CTZ(SKY81452_EN);
+       } else {
+               num_entry = ret;
+               if (num_entry > 6)
+                       num_entry = 6;
+
+               ret = of_property_read_u32_array(np, "led-sources", sources,
+                                       num_entry);
+               if (IS_ERR_VALUE(ret)) {
+                       dev_err(dev, "led-sources node is invalid.\n");
+                       return ERR_PTR(-EINVAL);
+               }
+
+               pdata->enable = 0;
+               while (--num_entry)
+                       pdata->enable |= (1 << sources[num_entry]);
+       }
+
+       ret = of_property_read_u32(np,
+                       "skyworks,short-detection-threshold-volt",
+                       &pdata->short_detection_threshold);
+       if (IS_ERR_VALUE(ret))
+               pdata->short_detection_threshold = 7;
+
+       ret = of_property_read_u32(np, "skyworks,current-limit-mA",
+                       &pdata->boost_current_limit);
+       if (IS_ERR_VALUE(ret))
+               pdata->boost_current_limit = 2750;
+
+       of_node_put(np);
+       return pdata;
+}
+#else
+static struct sky81452_bl_platform_data *sky81452_bl_parse_dt(
+                                                       struct device *dev)
+{
+       return ERR_PTR(-EINVAL);
+}
+#endif
+
+static int sky81452_bl_init_device(struct regmap *regmap,
+               struct sky81452_bl_platform_data *pdata)
+{
+       unsigned int value;
+
+       value = pdata->ignore_pwm ? SKY81452_IGPW : 0;
+       value |= pdata->dpwm_mode ? SKY81452_PWMMD : 0;
+       value |= pdata->phase_shift ? 0 : SKY81452_PHASE;
+
+       if (pdata->boost_current_limit == 2300)
+               value |= SKY81452_ILIM;
+       else if (pdata->boost_current_limit != 2750)
+               return -EINVAL;
+
+       if (pdata->short_detection_threshold < 4 ||
+                               pdata->short_detection_threshold > 7)
+               return -EINVAL;
+       value |= (7 - pdata->short_detection_threshold) << CTZ(SKY81452_VSHRT);
+
+       return regmap_write(regmap, SKY81452_REG2, value);
+}
+
+static int sky81452_bl_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct regmap *regmap = dev_get_drvdata(dev->parent);
+       struct sky81452_bl_platform_data *pdata = dev_get_platdata(dev);
+       struct backlight_device *bd;
+       struct backlight_properties props;
+       const char *name;
+       int ret;
+
+       if (!pdata) {
+               pdata = sky81452_bl_parse_dt(dev);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
+       }
+
+       if (gpio_is_valid(pdata->gpio_enable)) {
+               ret = devm_gpio_request_one(dev, pdata->gpio_enable,
+                                       GPIOF_OUT_INIT_HIGH, "sky81452-en");
+               if (IS_ERR_VALUE(ret)) {
+                       dev_err(dev, "failed to request GPIO. err=%d\n", ret);
+                       return ret;
+               }
+       }
+
+       ret = sky81452_bl_init_device(regmap, pdata);
+       if (IS_ERR_VALUE(ret)) {
+               dev_err(dev, "failed to initialize. err=%d\n", ret);
+               return ret;
+       }
+
+       memset(&props, 0, sizeof(props));
+       props.max_brightness = SKY81452_MAX_BRIGHTNESS,
+       name = pdata->name ? pdata->name : SKY81452_DEFAULT_NAME;
+       bd = devm_backlight_device_register(dev, name, dev, regmap,
+                                               &sky81452_bl_ops, &props);
+       if (IS_ERR(bd)) {
+               dev_err(dev, "failed to register. err=%ld\n", PTR_ERR(bd));
+               return PTR_ERR(bd);
+       }
+
+       platform_set_drvdata(pdev, bd);
+
+       ret  = sysfs_create_group(&bd->dev.kobj, &sky81452_bl_attr_group);
+       if (IS_ERR_VALUE(ret)) {
+               dev_err(dev, "failed to create attribute. err=%d\n", ret);
+               return ret;
+       }
+
+       return ret;
+}
+
+static int sky81452_bl_remove(struct platform_device *pdev)
+{
+       const struct sky81452_bl_platform_data *pdata =
+                                               dev_get_platdata(&pdev->dev);
+       struct backlight_device *bd = platform_get_drvdata(pdev);
+
+       sysfs_remove_group(&bd->dev.kobj, &sky81452_bl_attr_group);
+
+       bd->props.power = FB_BLANK_UNBLANK;
+       bd->props.brightness = 0;
+       backlight_update_status(bd);
+
+       if (gpio_is_valid(pdata->gpio_enable))
+               gpio_set_value_cansleep(pdata->gpio_enable, 0);
+
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id sky81452_bl_of_match[] = {
+       { .compatible = "skyworks,sky81452-backlight", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, sky81452_bl_of_match);
+#endif
+
+static struct platform_driver sky81452_bl_driver = {
+       .driver = {
+               .name = "sky81452-backlight",
+               .of_match_table = of_match_ptr(sky81452_bl_of_match),
+       },
+       .probe = sky81452_bl_probe,
+       .remove = sky81452_bl_remove,
+};
+
+module_platform_driver(sky81452_bl_driver);
+
+MODULE_DESCRIPTION("Skyworks SKY81452 backlight driver");
+MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>");
+MODULE_LICENSE("GPL v2");
index e07cfa8001bbf0ab2a253eae50b6290c3a60a984..895c2a31918df1d7bbabe1977faefe0f7543f0b2 100644 (file)
@@ -587,11 +587,6 @@ static int tsi148_slave_set(struct vme_slave_resource *image, int enabled,
                granularity = 0x10000;
                addr |= TSI148_LCSR_ITAT_AS_A64;
                break;
-       case VME_CRCSR:
-       case VME_USER1:
-       case VME_USER2:
-       case VME_USER3:
-       case VME_USER4:
        default:
                dev_err(tsi148_bridge->parent, "Invalid address space\n");
                return -EINVAL;
@@ -2471,7 +2466,8 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                master_image->locked = 0;
                master_image->number = i;
                master_image->address_attr = VME_A16 | VME_A24 | VME_A32 |
-                       VME_A64;
+                       VME_A64 | VME_CRCSR | VME_USER1 | VME_USER2 |
+                       VME_USER3 | VME_USER4;
                master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
                        VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 |
                        VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
@@ -2500,8 +2496,7 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                slave_image->locked = 0;
                slave_image->number = i;
                slave_image->address_attr = VME_A16 | VME_A24 | VME_A32 |
-                       VME_A64 | VME_CRCSR | VME_USER1 | VME_USER2 |
-                       VME_USER3 | VME_USER4;
+                       VME_A64;
                slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
                        VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 |
                        VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
index d95fb848dd03368c26c4d0b59020e5ac02a0b893..6bab2c4ed77c9f8b0ba4335932203680aceb6af7 100644 (file)
@@ -609,6 +609,32 @@ unsigned int vme_master_rmw(struct vme_resource *resource, unsigned int mask,
 }
 EXPORT_SYMBOL(vme_master_rmw);
 
+int vme_master_mmap(struct vme_resource *resource, struct vm_area_struct *vma)
+{
+       struct vme_master_resource *image;
+       phys_addr_t phys_addr;
+       unsigned long vma_size;
+
+       if (resource->type != VME_MASTER) {
+               pr_err("Not a master resource\n");
+               return -EINVAL;
+       }
+
+       image = list_entry(resource->entry, struct vme_master_resource, list);
+       phys_addr = image->bus_resource.start + (vma->vm_pgoff << PAGE_SHIFT);
+       vma_size = vma->vm_end - vma->vm_start;
+
+       if (phys_addr + vma_size > image->bus_resource.end + 1) {
+               pr_err("Map size cannot exceed the window size\n");
+               return -EFAULT;
+       }
+
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+       return vm_iomap_memory(vma, phys_addr, vma->vm_end - vma->vm_start);
+}
+EXPORT_SYMBOL(vme_master_mmap);
+
 void vme_master_free(struct vme_resource *resource)
 {
        struct vme_master_resource *master_image;
index 8a65423bc696b4eac607012437b3af8e1161458e..c4211a31612d447d3f40ad61f11c10e4cb4d0e5d 100644 (file)
@@ -397,13 +397,15 @@ static int __init xen_tmem_init(void)
 #ifdef CONFIG_CLEANCACHE
        BUG_ON(sizeof(struct cleancache_filekey) != sizeof(struct tmem_oid));
        if (tmem_enabled && cleancache) {
-               char *s = "";
-               struct cleancache_ops *old_ops =
-                       cleancache_register_ops(&tmem_cleancache_ops);
-               if (old_ops)
-                       s = " (WARNING: cleancache_ops overridden)";
-               pr_info("cleancache enabled, RAM provided by Xen Transcendent Memory%s\n",
-                       s);
+               int err;
+
+               err = cleancache_register_ops(&tmem_cleancache_ops);
+               if (err)
+                       pr_warn("xen-tmem: failed to enable cleancache: %d\n",
+                               err);
+               else
+                       pr_info("cleancache enabled, RAM provided by "
+                               "Xen Transcendent Memory\n");
        }
 #endif
 #ifdef CONFIG_XEN_SELFBALLOONING
index eb14e055ea83e8509e7ea6ae569e3c1966d3b896..ff1a5bac420098d528a46c6cccecfa1caa73c421 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/pagemap.h>
 #include <linux/idr.h>
 #include <linux/sched.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include <net/9p/9p.h>
 #include <net/9p/client.h>
 
index 270c48148f7947b445cc76765481556c25b8010e..2d0cbbd14cfc8addc59773e6934aadd22b04e5e1 100644 (file)
@@ -27,9 +27,6 @@ config COMPAT_BINFMT_ELF
        bool
        depends on COMPAT && BINFMT_ELF
 
-config ARCH_BINFMT_ELF_RANDOMIZE_PIE
-       bool
-
 config ARCH_BINFMT_ELF_STATE
        bool
 
index a88ac4838c9e2b89cffae17a72aa36d195356518..cb92fd4c31729cc5cf799a3278c57ad3c1af6314 100644 (file)
@@ -118,6 +118,7 @@ obj-$(CONFIG_HOSTFS)                += hostfs/
 obj-$(CONFIG_HPPFS)            += hppfs/
 obj-$(CONFIG_CACHEFILES)       += cachefiles/
 obj-$(CONFIG_DEBUG_FS)         += debugfs/
+obj-$(CONFIG_TRACING)          += tracefs/
 obj-$(CONFIG_OCFS2_FS)         += ocfs2/
 obj-$(CONFIG_BTRFS_FS)         += btrfs/
 obj-$(CONFIG_GFS2_FS)           += gfs2/
index a91795e01a7ff0c0e85abf1bdf69f3d1d828b231..3aa7eb66547ea31b7556c1502d3900dce0aa80dd 100644 (file)
@@ -12,7 +12,7 @@
  *  affs regular file handling primitives
  */
 
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include "affs.h"
 
 static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext);
index c13cb08964eda91afe26754733054147e220ecb7..0714abcd7f32321754287e46aec129196832e2ef 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/pagemap.h>
 #include <linux/writeback.h>
 #include <linux/pagevec.h>
-#include <linux/aio.h>
 #include "internal.h"
 
 static int afs_write_back_from_locked_page(struct afs_writeback *wb,
index f8e52a1854c1ab383e32383ac65a0f167e385793..1ab60010cf6c75b52945bdf884aa5088a536434f 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -151,6 +151,38 @@ struct kioctx {
        unsigned                id;
 };
 
+/*
+ * We use ki_cancel == KIOCB_CANCELLED to indicate that a kiocb has been either
+ * cancelled or completed (this makes a certain amount of sense because
+ * successful cancellation - io_cancel() - does deliver the completion to
+ * userspace).
+ *
+ * And since most things don't implement kiocb cancellation and we'd really like
+ * kiocb completion to be lockless when possible, we use ki_cancel to
+ * synchronize cancellation and completion - we only set it to KIOCB_CANCELLED
+ * with xchg() or cmpxchg(), see batch_complete_aio() and kiocb_cancel().
+ */
+#define KIOCB_CANCELLED                ((void *) (~0ULL))
+
+struct aio_kiocb {
+       struct kiocb            common;
+
+       struct kioctx           *ki_ctx;
+       kiocb_cancel_fn         *ki_cancel;
+
+       struct iocb __user      *ki_user_iocb;  /* user's aiocb */
+       __u64                   ki_user_data;   /* user's data for completion */
+
+       struct list_head        ki_list;        /* the aio core uses this
+                                                * for cancellation */
+
+       /*
+        * If the aio_resfd field of the userspace iocb is not zero,
+        * this is the underlying eventfd context to deliver events to.
+        */
+       struct eventfd_ctx      *ki_eventfd;
+};
+
 /*------ sysctl variables----*/
 static DEFINE_SPINLOCK(aio_nr_lock);
 unsigned long aio_nr;          /* current system wide number of aio requests */
@@ -220,7 +252,7 @@ static int __init aio_setup(void)
        if (IS_ERR(aio_mnt))
                panic("Failed to create aio fs mount.");
 
-       kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
+       kiocb_cachep = KMEM_CACHE(aio_kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
        kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 
        pr_debug("sizeof(struct page) = %zu\n", sizeof(struct page));
@@ -278,11 +310,11 @@ static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
-static void aio_ring_remap(struct file *file, struct vm_area_struct *vma)
+static int aio_ring_remap(struct file *file, struct vm_area_struct *vma)
 {
        struct mm_struct *mm = vma->vm_mm;
        struct kioctx_table *table;
-       int i;
+       int i, res = -EINVAL;
 
        spin_lock(&mm->ioctx_lock);
        rcu_read_lock();
@@ -292,13 +324,17 @@ static void aio_ring_remap(struct file *file, struct vm_area_struct *vma)
 
                ctx = table->table[i];
                if (ctx && ctx->aio_ring_file == file) {
-                       ctx->user_id = ctx->mmap_base = vma->vm_start;
+                       if (!atomic_read(&ctx->dead)) {
+                               ctx->user_id = ctx->mmap_base = vma->vm_start;
+                               res = 0;
+                       }
                        break;
                }
        }
 
        rcu_read_unlock();
        spin_unlock(&mm->ioctx_lock);
+       return res;
 }
 
 static const struct file_operations aio_ring_fops = {
@@ -480,8 +516,9 @@ static int aio_setup_ring(struct kioctx *ctx)
 #define AIO_EVENTS_FIRST_PAGE  ((PAGE_SIZE - sizeof(struct aio_ring)) / sizeof(struct io_event))
 #define AIO_EVENTS_OFFSET      (AIO_EVENTS_PER_PAGE - AIO_EVENTS_FIRST_PAGE)
 
-void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel)
+void kiocb_set_cancel_fn(struct kiocb *iocb, kiocb_cancel_fn *cancel)
 {
+       struct aio_kiocb *req = container_of(iocb, struct aio_kiocb, common);
        struct kioctx *ctx = req->ki_ctx;
        unsigned long flags;
 
@@ -496,7 +533,7 @@ void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel)
 }
 EXPORT_SYMBOL(kiocb_set_cancel_fn);
 
-static int kiocb_cancel(struct kiocb *kiocb)
+static int kiocb_cancel(struct aio_kiocb *kiocb)
 {
        kiocb_cancel_fn *old, *cancel;
 
@@ -514,7 +551,7 @@ static int kiocb_cancel(struct kiocb *kiocb)
                cancel = cmpxchg(&kiocb->ki_cancel, old, KIOCB_CANCELLED);
        } while (cancel != old);
 
-       return cancel(kiocb);
+       return cancel(&kiocb->common);
 }
 
 static void free_ioctx(struct work_struct *work)
@@ -550,13 +587,13 @@ static void free_ioctx_reqs(struct percpu_ref *ref)
 static void free_ioctx_users(struct percpu_ref *ref)
 {
        struct kioctx *ctx = container_of(ref, struct kioctx, users);
-       struct kiocb *req;
+       struct aio_kiocb *req;
 
        spin_lock_irq(&ctx->ctx_lock);
 
        while (!list_empty(&ctx->active_reqs)) {
                req = list_first_entry(&ctx->active_reqs,
-                                      struct kiocb, ki_list);
+                                      struct aio_kiocb, ki_list);
 
                list_del_init(&req->ki_list);
                kiocb_cancel(req);
@@ -727,6 +764,9 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 err_cleanup:
        aio_nr_sub(ctx->max_reqs);
 err_ctx:
+       atomic_set(&ctx->dead, 1);
+       if (ctx->mmap_size)
+               vm_munmap(ctx->mmap_base, ctx->mmap_size);
        aio_free_ring(ctx);
 err:
        mutex_unlock(&ctx->ring_lock);
@@ -748,11 +788,12 @@ static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx,
 {
        struct kioctx_table *table;
 
-       if (atomic_xchg(&ctx->dead, 1))
+       spin_lock(&mm->ioctx_lock);
+       if (atomic_xchg(&ctx->dead, 1)) {
+               spin_unlock(&mm->ioctx_lock);
                return -EINVAL;
+       }
 
-
-       spin_lock(&mm->ioctx_lock);
        table = rcu_dereference_raw(mm->ioctx_table);
        WARN_ON(ctx != table->table[ctx->id]);
        table->table[ctx->id] = NULL;
@@ -778,22 +819,6 @@ static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx,
        return 0;
 }
 
-/* wait_on_sync_kiocb:
- *     Waits on the given sync kiocb to complete.
- */
-ssize_t wait_on_sync_kiocb(struct kiocb *req)
-{
-       while (!req->ki_ctx) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               if (req->ki_ctx)
-                       break;
-               io_schedule();
-       }
-       __set_current_state(TASK_RUNNING);
-       return req->ki_user_data;
-}
-EXPORT_SYMBOL(wait_on_sync_kiocb);
-
 /*
  * exit_aio: called when the last user of mm goes away.  At this point, there is
  * no way for any new requests to be submited or any of the io_* syscalls to be
@@ -948,9 +973,9 @@ static void user_refill_reqs_available(struct kioctx *ctx)
  *     Allocate a slot for an aio request.
  * Returns NULL if no requests are free.
  */
-static inline struct kiocb *aio_get_req(struct kioctx *ctx)
+static inline struct aio_kiocb *aio_get_req(struct kioctx *ctx)
 {
-       struct kiocb *req;
+       struct aio_kiocb *req;
 
        if (!get_reqs_available(ctx)) {
                user_refill_reqs_available(ctx);
@@ -971,10 +996,10 @@ out_put:
        return NULL;
 }
 
-static void kiocb_free(struct kiocb *req)
+static void kiocb_free(struct aio_kiocb *req)
 {
-       if (req->ki_filp)
-               fput(req->ki_filp);
+       if (req->common.ki_filp)
+               fput(req->common.ki_filp);
        if (req->ki_eventfd != NULL)
                eventfd_ctx_put(req->ki_eventfd);
        kmem_cache_free(kiocb_cachep, req);
@@ -1010,8 +1035,9 @@ out:
 /* aio_complete
  *     Called when the io request on the given iocb is complete.
  */
-void aio_complete(struct kiocb *iocb, long res, long res2)
+static void aio_complete(struct kiocb *kiocb, long res, long res2)
 {
+       struct aio_kiocb *iocb = container_of(kiocb, struct aio_kiocb, common);
        struct kioctx   *ctx = iocb->ki_ctx;
        struct aio_ring *ring;
        struct io_event *ev_page, *event;
@@ -1025,13 +1051,7 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
         *    ref, no other paths have a way to get another ref
         *  - the sync task helpfully left a reference to itself in the iocb
         */
-       if (is_sync_kiocb(iocb)) {
-               iocb->ki_user_data = res;
-               smp_wmb();
-               iocb->ki_ctx = ERR_PTR(-EXDEV);
-               wake_up_process(iocb->ki_obj.tsk);
-               return;
-       }
+       BUG_ON(is_sync_kiocb(kiocb));
 
        if (iocb->ki_list.next) {
                unsigned long flags;
@@ -1057,7 +1077,7 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
        ev_page = kmap_atomic(ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE]);
        event = ev_page + pos % AIO_EVENTS_PER_PAGE;
 
-       event->obj = (u64)(unsigned long)iocb->ki_obj.user;
+       event->obj = (u64)(unsigned long)iocb->ki_user_iocb;
        event->data = iocb->ki_user_data;
        event->res = res;
        event->res2 = res2;
@@ -1066,7 +1086,7 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
        flush_dcache_page(ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE]);
 
        pr_debug("%p[%u]: %p: %p %Lx %lx %lx\n",
-                ctx, tail, iocb, iocb->ki_obj.user, iocb->ki_user_data,
+                ctx, tail, iocb, iocb->ki_user_iocb, iocb->ki_user_data,
                 res, res2);
 
        /* after flagging the request as done, we
@@ -1113,7 +1133,6 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
 
        percpu_ref_put(&ctx->reqs);
 }
-EXPORT_SYMBOL(aio_complete);
 
 /* aio_read_events_ring
  *     Pull an event off of the ioctx's event ring.  Returns the number of
@@ -1341,46 +1360,19 @@ typedef ssize_t (aio_rw_op)(struct kiocb *, const struct iovec *,
                            unsigned long, loff_t);
 typedef ssize_t (rw_iter_op)(struct kiocb *, struct iov_iter *);
 
-static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
-                                    int rw, char __user *buf,
-                                    unsigned long *nr_segs,
-                                    struct iovec **iovec,
-                                    bool compat)
+static int aio_setup_vectored_rw(int rw, char __user *buf, size_t len,
+                                struct iovec **iovec,
+                                bool compat,
+                                struct iov_iter *iter)
 {
-       ssize_t ret;
-
-       *nr_segs = kiocb->ki_nbytes;
-
 #ifdef CONFIG_COMPAT
        if (compat)
-               ret = compat_rw_copy_check_uvector(rw,
+               return compat_import_iovec(rw,
                                (struct compat_iovec __user *)buf,
-                               *nr_segs, UIO_FASTIOV, *iovec, iovec);
-       else
+                               len, UIO_FASTIOV, iovec, iter);
 #endif
-               ret = rw_copy_check_uvector(rw,
-                               (struct iovec __user *)buf,
-                               *nr_segs, UIO_FASTIOV, *iovec, iovec);
-       if (ret < 0)
-               return ret;
-
-       /* ki_nbytes now reflect bytes instead of segs */
-       kiocb->ki_nbytes = ret;
-       return 0;
-}
-
-static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
-                                      int rw, char __user *buf,
-                                      unsigned long *nr_segs,
-                                      struct iovec *iovec)
-{
-       if (unlikely(!access_ok(!rw, buf, kiocb->ki_nbytes)))
-               return -EFAULT;
-
-       iovec->iov_base = buf;
-       iovec->iov_len = kiocb->ki_nbytes;
-       *nr_segs = 1;
-       return 0;
+       return import_iovec(rw, (struct iovec __user *)buf,
+                               len, UIO_FASTIOV, iovec, iter);
 }
 
 /*
@@ -1388,11 +1380,10 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
  *     Performs the initial checks and io submission.
  */
 static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
-                           char __user *buf, bool compat)
+                           char __user *buf, size_t len, bool compat)
 {
        struct file *file = req->ki_filp;
        ssize_t ret;
-       unsigned long nr_segs;
        int rw;
        fmode_t mode;
        aio_rw_op *rw_op;
@@ -1423,21 +1414,22 @@ rw_common:
                if (!rw_op && !iter_op)
                        return -EINVAL;
 
-               ret = (opcode == IOCB_CMD_PREADV ||
-                      opcode == IOCB_CMD_PWRITEV)
-                       ? aio_setup_vectored_rw(req, rw, buf, &nr_segs,
-                                               &iovec, compat)
-                       : aio_setup_single_vector(req, rw, buf, &nr_segs,
-                                                 iovec);
+               if (opcode == IOCB_CMD_PREADV || opcode == IOCB_CMD_PWRITEV)
+                       ret = aio_setup_vectored_rw(rw, buf, len,
+                                               &iovec, compat, &iter);
+               else {
+                       ret = import_single_range(rw, buf, len, iovec, &iter);
+                       iovec = NULL;
+               }
                if (!ret)
-                       ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes);
+                       ret = rw_verify_area(rw, file, &req->ki_pos,
+                                            iov_iter_count(&iter));
                if (ret < 0) {
-                       if (iovec != inline_vecs)
-                               kfree(iovec);
+                       kfree(iovec);
                        return ret;
                }
 
-               req->ki_nbytes = ret;
+               len = ret;
 
                /* XXX: move/kill - rw_verify_area()? */
                /* This matches the pread()/pwrite() logic */
@@ -1450,14 +1442,14 @@ rw_common:
                        file_start_write(file);
 
                if (iter_op) {
-                       iov_iter_init(&iter, rw, iovec, nr_segs, req->ki_nbytes);
                        ret = iter_op(req, &iter);
                } else {
-                       ret = rw_op(req, iovec, nr_segs, req->ki_pos);
+                       ret = rw_op(req, iter.iov, iter.nr_segs, req->ki_pos);
                }
 
                if (rw == WRITE)
                        file_end_write(file);
+               kfree(iovec);
                break;
 
        case IOCB_CMD_FDSYNC:
@@ -1479,9 +1471,6 @@ rw_common:
                return -EINVAL;
        }
 
-       if (iovec != inline_vecs)
-               kfree(iovec);
-
        if (ret != -EIOCBQUEUED) {
                /*
                 * There's no easy way to restart the syscall since other AIO's
@@ -1500,7 +1489,7 @@ rw_common:
 static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                         struct iocb *iocb, bool compat)
 {
-       struct kiocb *req;
+       struct aio_kiocb *req;
        ssize_t ret;
 
        /* enforce forwards compatibility on users */
@@ -1523,11 +1512,14 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
        if (unlikely(!req))
                return -EAGAIN;
 
-       req->ki_filp = fget(iocb->aio_fildes);
-       if (unlikely(!req->ki_filp)) {
+       req->common.ki_filp = fget(iocb->aio_fildes);
+       if (unlikely(!req->common.ki_filp)) {
                ret = -EBADF;
                goto out_put_req;
        }
+       req->common.ki_pos = iocb->aio_offset;
+       req->common.ki_complete = aio_complete;
+       req->common.ki_flags = 0;
 
        if (iocb->aio_flags & IOCB_FLAG_RESFD) {
                /*
@@ -1542,6 +1534,8 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                        req->ki_eventfd = NULL;
                        goto out_put_req;
                }
+
+               req->common.ki_flags |= IOCB_EVENTFD;
        }
 
        ret = put_user(KIOCB_KEY, &user_iocb->aio_key);
@@ -1550,13 +1544,12 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                goto out_put_req;
        }
 
-       req->ki_obj.user = user_iocb;
+       req->ki_user_iocb = user_iocb;
        req->ki_user_data = iocb->aio_data;
-       req->ki_pos = iocb->aio_offset;
-       req->ki_nbytes = iocb->aio_nbytes;
 
-       ret = aio_run_iocb(req, iocb->aio_lio_opcode,
+       ret = aio_run_iocb(&req->common, iocb->aio_lio_opcode,
                           (char __user *)(unsigned long)iocb->aio_buf,
+                          iocb->aio_nbytes,
                           compat);
        if (ret)
                goto out_put_req;
@@ -1643,10 +1636,10 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
 /* lookup_kiocb
  *     Finds a given iocb for cancellation.
  */
-static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb,
-                                 u32 key)
+static struct aio_kiocb *
+lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb, u32 key)
 {
-       struct list_head *pos;
+       struct aio_kiocb *kiocb;
 
        assert_spin_locked(&ctx->ctx_lock);
 
@@ -1654,9 +1647,8 @@ static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb,
                return NULL;
 
        /* TODO: use a hash or array, this sucks. */
-       list_for_each(pos, &ctx->active_reqs) {
-               struct kiocb *kiocb = list_kiocb(pos);
-               if (kiocb->ki_obj.user == iocb)
+       list_for_each_entry(kiocb, &ctx->active_reqs, ki_list) {
+               if (kiocb->ki_user_iocb == iocb)
                        return kiocb;
        }
        return NULL;
@@ -1676,7 +1668,7 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
                struct io_event __user *, result)
 {
        struct kioctx *ctx;
-       struct kiocb *kiocb;
+       struct aio_kiocb *kiocb;
        u32 key;
        int ret;
 
index 90bc079d9982928b7a9b5bcb6ad3efd6ebf1375f..fdcb4d69f430db6370e1eed7c1c04c9a3f333746 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 #include <linux/writeback.h>
+#include <linux/uio.h>
 #include <asm/uaccess.h>
 #include "bfs.h"
 
index 995986b8e36b8f3fd8529582c50e545d9b26322e..241ef68d28930a7faed26f18b67b296138e61d9e 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/security.h>
 #include <linux/random.h>
 #include <linux/elf.h>
+#include <linux/elf-randomize.h>
 #include <linux/utsname.h>
 #include <linux/coredump.h>
 #include <linux/sched.h>
@@ -862,6 +863,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
            i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
                int elf_prot = 0, elf_flags;
                unsigned long k, vaddr;
+               unsigned long total_size = 0;
 
                if (elf_ppnt->p_type != PT_LOAD)
                        continue;
@@ -909,25 +911,20 @@ static int load_elf_binary(struct linux_binprm *bprm)
                         * default mmap base, as well as whatever program they
                         * might try to exec.  This is because the brk will
                         * follow the loader, and is not movable.  */
-#ifdef CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE
-                       /* Memory randomization might have been switched off
-                        * in runtime via sysctl or explicit setting of
-                        * personality flags.
-                        * If that is the case, retain the original non-zero
-                        * load_bias value in order to establish proper
-                        * non-randomized mappings.
-                        */
+                       load_bias = ELF_ET_DYN_BASE - vaddr;
                        if (current->flags & PF_RANDOMIZE)
-                               load_bias = 0;
-                       else
-                               load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
-#else
-                       load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
-#endif
+                               load_bias += arch_mmap_rnd();
+                       load_bias = ELF_PAGESTART(load_bias);
+                       total_size = total_mapping_size(elf_phdata,
+                                                       loc->elf_ex.e_phnum);
+                       if (!total_size) {
+                               error = -EINVAL;
+                               goto out_free_dentry;
+                       }
                }
 
                error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
-                               elf_prot, elf_flags, 0);
+                               elf_prot, elf_flags, total_size);
                if (BAD_ADDR(error)) {
                        retval = IS_ERR((void *)error) ?
                                PTR_ERR((void*)error) : -EINVAL;
@@ -1053,15 +1050,13 @@ static int load_elf_binary(struct linux_binprm *bprm)
        current->mm->end_data = end_data;
        current->mm->start_stack = bprm->p;
 
-#ifdef arch_randomize_brk
        if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) {
                current->mm->brk = current->mm->start_brk =
                        arch_randomize_brk(current->mm);
-#ifdef CONFIG_COMPAT_BRK
+#ifdef compat_brk_randomized
                current->brk_randomized = 1;
 #endif
        }
-#endif
 
        if (current->personality & MMAP_PAGE_ZERO) {
                /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
index 975266be67d319aa019a48e94cfda0a3ca8ce1e0..2e522aed6584d3a7837155897b2a47085b5ed303 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/namei.h>
 #include <linux/log2.h>
 #include <linux/cleancache.h>
-#include <linux/aio.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
index 30982bbd31c30c2b154836b0f51b94c37e22923c..aee18f84e3159c1e369a0c14eff0baad8ddbb59a 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/string.h>
 #include <linux/backing-dev.h>
 #include <linux/mpage.h>
-#include <linux/aio.h>
 #include <linux/falloc.h>
 #include <linux/swap.h>
 #include <linux/writeback.h>
@@ -32,6 +31,7 @@
 #include <linux/compat.h>
 #include <linux/slab.h>
 #include <linux/btrfs.h>
+#include <linux/uio.h>
 #include "ctree.h"
 #include "disk-io.h"
 #include "transaction.h"
index d2e732d7af524640bc2c197da3e7123182b4537e..686331f22b15ce0fcc8233c2529a50c2eb6190c7 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/writeback.h>
 #include <linux/statfs.h>
 #include <linux/compat.h>
-#include <linux/aio.h>
 #include <linux/bit_spinlock.h>
 #include <linux/xattr.h>
 #include <linux/posix_acl.h>
@@ -43,6 +42,7 @@
 #include <linux/btrfs.h>
 #include <linux/blkdev.h>
 #include <linux/posix_acl_xattr.h>
+#include <linux/uio.h>
 #include "ctree.h"
 #include "disk-io.h"
 #include "transaction.h"
index 20805db2c98774a8cbe3242d37c63f370149f1a9..c7a5602d01eed200912d3a90ca4ac6780209cb6f 100644 (file)
@@ -3243,8 +3243,8 @@ int try_to_free_buffers(struct page *page)
         * to synchronise against __set_page_dirty_buffers and prevent the
         * dirty bit from being lost.
         */
-       if (ret)
-               cancel_dirty_page(page, PAGE_CACHE_SIZE);
+       if (ret && TestClearPageDirty(page))
+               account_page_cleaned(page, mapping);
        spin_unlock(&mapping->private_lock);
 out:
        if (buffers_to_free) {
index d533075a823d5eb92e709547b8fe790c59cba981..139f2fea91a0fe8472cf138e900bfe580db43f50 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/writeback.h>
-#include <linux/aio.h>
 #include <linux/falloc.h>
 
 #include "super.h"
@@ -808,7 +807,7 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)
 {
        struct file *filp = iocb->ki_filp;
        struct ceph_file_info *fi = filp->private_data;
-       size_t len = iocb->ki_nbytes;
+       size_t len = iov_iter_count(to);
        struct inode *inode = file_inode(filp);
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct page *pinned_page = NULL;
index 480cf9c81d505b8351dd76eee0f012110c3f2b9c..f3bfe08e177b6c86a4f1a99a8905f1b417f82af5 100644 (file)
@@ -773,8 +773,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
 
        length = atomic_dec_return(&tcpSesAllocCount);
        if (length > 0)
-               mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
-                               GFP_KERNEL);
+               mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
 }
 
 static int
@@ -848,8 +847,7 @@ cifs_demultiplex_thread(void *p)
 
        length = atomic_inc_return(&tcpSesAllocCount);
        if (length > 1)
-               mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
-                               GFP_KERNEL);
+               mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
 
        set_freezable();
        while (server->tcpStatus != CifsExiting) {
index c71e3732e53bcebbffca749e65b7095fd4ff6e7e..d99736a63e3cf6d5da6850e4eee02ecd7ae672e4 100644 (file)
@@ -2690,7 +2690,7 @@ static int __d_unalias(struct inode *inode,
                struct dentry *dentry, struct dentry *alias)
 {
        struct mutex *m1 = NULL, *m2 = NULL;
-       int ret = -EBUSY;
+       int ret = -ESTALE;
 
        /* If alias and dentry share a parent, then no extra locks required */
        if (alias->d_parent == dentry->d_parent)
index 96400ab42d135e7d572d29de9d4f3637fedd7817..61e72d44cf94142c1946f9dbc74904b8f31ec98e 100644 (file)
@@ -254,6 +254,9 @@ static struct dentry *start_creating(const char *name, struct dentry *parent)
 
        pr_debug("debugfs: creating file '%s'\n",name);
 
+       if (IS_ERR(parent))
+               return parent;
+
        error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
                              &debugfs_mount_count);
        if (error)
index e181b6b2e297fb5d3bd03a07efe382f0dd204972..6fb00e3f1059791d21b4ffc80671f3d051ecbc8e 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/uio.h>
 #include <linux/atomic.h>
 #include <linux/prefetch.h>
-#include <linux/aio.h>
 
 /*
  * How many user pages to map in one call to get_user_pages().  This determines
@@ -265,7 +264,7 @@ static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret,
                                ret = err;
                }
 
-               aio_complete(dio->iocb, ret, 0);
+               dio->iocb->ki_complete(dio->iocb, ret, 0);
        }
 
        kmem_cache_free(dio_cache, dio);
@@ -1056,7 +1055,7 @@ static inline int drop_refcount(struct dio *dio)
         * operation.  AIO can if it was a broken operation described above or
         * in fact if all the bios race to complete before we get here.  In
         * that case dio_complete() translates the EIOCBQUEUED into the proper
-        * return code that the caller will hand to aio_complete().
+        * return code that the caller will hand to ->complete().
         *
         * This is managed by the bio_lock instead of being an atomic_t so that
         * completion paths can drop their ref and use the remaining count to
index fd39bad6f1bdf8bbcb4321a8fc8ff1934d67167c..79675089443df98c23de1602d3ca59a887cbb4d4 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/security.h>
 #include <linux/compat.h>
 #include <linux/fs_stack.h>
-#include <linux/aio.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -52,12 +51,6 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
        struct file *file = iocb->ki_filp;
 
        rc = generic_file_read_iter(iocb, to);
-       /*
-        * Even though this is a async interface, we need to wait
-        * for IO to finish to update atime
-        */
-       if (-EIOCBQUEUED == rc)
-               rc = wait_on_sync_kiocb(iocb);
        if (rc >= 0) {
                path = ecryptfs_dentry_to_lower_path(file->f_path.dentry);
                touch_atime(path);
index 6434bc00012517a30ace1cb97f2160b0c48eea3a..df9d6afbc5d5eb745e00a9a2575b28890e94d7b7 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/mpage.h>
 #include <linux/fiemap.h>
 #include <linux/namei.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include "ext2.h"
 #include "acl.h"
 #include "xattr.h"
index 2c6ccc49ba279cacf77fe6609fe44a50b970898c..db07ffbe7c85cdabbe89d49b3b2294dd8a1d84cf 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/writeback.h>
 #include <linux/mpage.h>
 #include <linux/namei.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include "ext3.h"
 #include "xattr.h"
 #include "acl.h"
index 33a09da16c9ce1e8049fdcacdf3e8833410fd78f..598abbbe678619c347dbe53d8dfe2c8cd6c86c65 100644 (file)
@@ -23,9 +23,9 @@
 #include <linux/jbd2.h>
 #include <linux/mount.h>
 #include <linux/path.h>
-#include <linux/aio.h>
 #include <linux/quotaops.h>
 #include <linux/pagevec.h>
+#include <linux/uio.h>
 #include "ext4.h"
 #include "ext4_jbd2.h"
 #include "xattr.h"
index 45fe924f82bce2ff76e3e74b45ec1833729433ea..740c7871c11770a683395989df5548d3d3357c22 100644 (file)
@@ -20,9 +20,9 @@
  *     (sct@redhat.com), 1993, 1998
  */
 
-#include <linux/aio.h>
 #include "ext4_jbd2.h"
 #include "truncate.h"
+#include <linux/uio.h>
 
 #include <trace/events/ext4.h>
 
index 5cb9a212b86f3efd69ca604df07dc20b901dabb1..a3f451370bef4b49a23343daf63af2459de0741c 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/printk.h>
 #include <linux/slab.h>
 #include <linux/ratelimit.h>
-#include <linux/aio.h>
 #include <linux/bitops.h>
 
 #include "ext4_jbd2.h"
index b24a2541a9baaa0d4c22e80a75050af2517a417d..464984261e698af8317621c45b8d2089551bc790 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/pagevec.h>
 #include <linux/mpage.h>
 #include <linux/namei.h>
-#include <linux/aio.h>
 #include <linux/uio.h>
 #include <linux/bio.h>
 #include <linux/workqueue.h>
index 985ed023a750170b924455ea23e2684c50baeba4..497f8515d2056283d040b912dd638e65a4576fe7 100644 (file)
 #include <linux/f2fs_fs.h>
 #include <linux/buffer_head.h>
 #include <linux/mpage.h>
-#include <linux/aio.h>
 #include <linux/writeback.h>
 #include <linux/backing-dev.h>
 #include <linux/blkdev.h>
 #include <linux/bio.h>
 #include <linux/prefetch.h>
+#include <linux/uio.h>
 
 #include "f2fs.h"
 #include "node.h"
index 497c7c5263c7ca3962c385605fbbb558d351f759..8521207de22935464f074b70448cae781ed403e1 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/mpage.h>
 #include <linux/buffer_head.h>
 #include <linux/mount.h>
-#include <linux/aio.h>
 #include <linux/vfs.h>
 #include <linux/parser.h>
 #include <linux/uio.h>
index 28d0c7abba1c2fa7748d3b1c2874b855427b3897..b3fa0503223411ff97b3ab5c2f775310b1f3cccb 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/device.h>
 #include <linux/file.h>
 #include <linux/fs.h>
-#include <linux/aio.h>
 #include <linux/kdev_t.h>
 #include <linux/kthread.h>
 #include <linux/list.h>
@@ -48,6 +47,7 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/module.h>
+#include <linux/uio.h>
 
 #include "fuse_i.h"
 
index 39706c57ad3cb157d81594065a15f154f61d7bd8..95a2797eef66d8db6edb1c7c4310be292744a427 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/swap.h>
 #include <linux/splice.h>
-#include <linux/aio.h>
 
 MODULE_ALIAS_MISCDEV(FUSE_MINOR);
 MODULE_ALIAS("devname:fuse");
index c01ec3bdcfd81090fae2cb26ae166f351d4505eb..ff102cbf16eab45bdd74eb7cffeafc99a4d7b064 100644 (file)
@@ -15,8 +15,8 @@
 #include <linux/module.h>
 #include <linux/compat.h>
 #include <linux/swap.h>
-#include <linux/aio.h>
 #include <linux/falloc.h>
+#include <linux/uio.h>
 
 static const struct file_operations fuse_direct_io_file_operations;
 
@@ -528,6 +528,17 @@ static void fuse_release_user_pages(struct fuse_req *req, int write)
        }
 }
 
+static ssize_t fuse_get_res_by_io(struct fuse_io_priv *io)
+{
+       if (io->err)
+               return io->err;
+
+       if (io->bytes >= 0 && io->write)
+               return -EIO;
+
+       return io->bytes < 0 ? io->size : io->bytes;
+}
+
 /**
  * In case of short read, the caller sets 'pos' to the position of
  * actual end of fuse request in IO request. Otherwise, if bytes_requested
@@ -546,6 +557,7 @@ static void fuse_release_user_pages(struct fuse_req *req, int write)
  */
 static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos)
 {
+       bool is_sync = is_sync_kiocb(io->iocb);
        int left;
 
        spin_lock(&io->lock);
@@ -555,30 +567,24 @@ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos)
                io->bytes = pos;
 
        left = --io->reqs;
+       if (!left && is_sync)
+               complete(io->done);
        spin_unlock(&io->lock);
 
-       if (!left) {
-               long res;
+       if (!left && !is_sync) {
+               ssize_t res = fuse_get_res_by_io(io);
 
-               if (io->err)
-                       res = io->err;
-               else if (io->bytes >= 0 && io->write)
-                       res = -EIO;
-               else {
-                       res = io->bytes < 0 ? io->size : io->bytes;
+               if (res >= 0) {
+                       struct inode *inode = file_inode(io->iocb->ki_filp);
+                       struct fuse_conn *fc = get_fuse_conn(inode);
+                       struct fuse_inode *fi = get_fuse_inode(inode);
 
-                       if (!is_sync_kiocb(io->iocb)) {
-                               struct inode *inode = file_inode(io->iocb->ki_filp);
-                               struct fuse_conn *fc = get_fuse_conn(inode);
-                               struct fuse_inode *fi = get_fuse_inode(inode);
-
-                               spin_lock(&fc->lock);
-                               fi->attr_version = ++fc->attr_version;
-                               spin_unlock(&fc->lock);
-                       }
+                       spin_lock(&fc->lock);
+                       fi->attr_version = ++fc->attr_version;
+                       spin_unlock(&fc->lock);
                }
 
-               aio_complete(io->iocb, res, 0);
+               io->iocb->ki_complete(io->iocb, res, 0);
                kfree(io);
        }
 }
@@ -2801,6 +2807,7 @@ static ssize_t
 fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
                        loff_t offset)
 {
+       DECLARE_COMPLETION_ONSTACK(wait);
        ssize_t ret = 0;
        struct file *file = iocb->ki_filp;
        struct fuse_file *ff = file->private_data;
@@ -2852,6 +2859,9 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
        if (!is_sync_kiocb(iocb) && (offset + count > i_size) && rw == WRITE)
                io->async = false;
 
+       if (io->async && is_sync_kiocb(iocb))
+               io->done = &wait;
+
        if (rw == WRITE)
                ret = __fuse_direct_write(io, iter, &pos);
        else
@@ -2864,11 +2874,12 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
                if (!is_sync_kiocb(iocb))
                        return -EIOCBQUEUED;
 
-               ret = wait_on_sync_kiocb(iocb);
-       } else {
-               kfree(io);
+               wait_for_completion(&wait);
+               ret = fuse_get_res_by_io(io);
        }
 
+       kfree(io);
+
        if (rw == WRITE) {
                if (ret > 0)
                        fuse_write_update_size(inode, pos);
index 1cdfb07c1376b4f4b5633e86fdbdfc4320953de2..7354dc142a50845a62e9a413d82d185afc1f5b0d 100644 (file)
@@ -263,6 +263,7 @@ struct fuse_io_priv {
        int err;
        struct kiocb *iocb;
        struct file *file;
+       struct completion *done;
 };
 
 /**
index 7b3143064af1130d22c14f66c8236785093c545a..1be3b061c05c921f60ddfebcce809875fe8de662 100644 (file)
@@ -110,11 +110,7 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
        error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
        if (error)
                goto out;
-
-       if (acl)
-               set_cached_acl(inode, type, acl);
-       else
-               forget_cached_acl(inode, type);
+       set_cached_acl(inode, type, acl);
 out:
        kfree(data);
        return error;
index 4ad4f94edebe25cc8afa3fa7c4ec35913cb00642..a6e6990aea395e63c158f6105034d6b7c6b53a62 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/swap.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/backing-dev.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include <trace/events/writeback.h>
 
 #include "gfs2.h"
@@ -671,12 +671,12 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
 
        if (alloc_required) {
                struct gfs2_alloc_parms ap = { .aflags = 0, };
-               error = gfs2_quota_lock_check(ip);
+               requested = data_blocks + ind_blocks;
+               ap.target = requested;
+               error = gfs2_quota_lock_check(ip, &ap);
                if (error)
                        goto out_unlock;
 
-               requested = data_blocks + ind_blocks;
-               ap.target = requested;
                error = gfs2_inplace_reserve(ip, &ap);
                if (error)
                        goto out_qunlock;
index f0b945ab853e488a852a1a8459e9aa873def54b9..61296ecbd0e20a59a8d5067169e871b1628d93a4 100644 (file)
@@ -1224,7 +1224,7 @@ static int do_grow(struct inode *inode, u64 size)
 
        if (gfs2_is_stuffed(ip) &&
            (size > (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)))) {
-               error = gfs2_quota_lock_check(ip);
+               error = gfs2_quota_lock_check(ip, &ap);
                if (error)
                        return error;
 
index 3e32bb8e2d7e573df59dc360a1ac38fe4ec759bd..8ec43ab5babf4785470ca246cfff9077c683e5c1 100644 (file)
@@ -25,7 +25,6 @@
 #include <asm/uaccess.h>
 #include <linux/dlm.h>
 #include <linux/dlm_plock.h>
-#include <linux/aio.h>
 #include <linux/delay.h>
 
 #include "gfs2.h"
@@ -429,11 +428,11 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        if (ret)
                goto out_unlock;
 
-       ret = gfs2_quota_lock_check(ip);
-       if (ret)
-               goto out_unlock;
        gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks);
        ap.target = data_blocks + ind_blocks;
+       ret = gfs2_quota_lock_check(ip, &ap);
+       if (ret)
+               goto out_unlock;
        ret = gfs2_inplace_reserve(ip, &ap);
        if (ret)
                goto out_quota_unlock;
@@ -765,22 +764,30 @@ out:
        brelse(dibh);
        return error;
 }
-
-static void calc_max_reserv(struct gfs2_inode *ip, loff_t max, loff_t *len,
-                           unsigned int *data_blocks, unsigned int *ind_blocks)
+/**
+ * calc_max_reserv() - Reverse of write_calc_reserv. Given a number of
+ *                     blocks, determine how many bytes can be written.
+ * @ip:          The inode in question.
+ * @len:         Max cap of bytes. What we return in *len must be <= this.
+ * @data_blocks: Compute and return the number of data blocks needed
+ * @ind_blocks:  Compute and return the number of indirect blocks needed
+ * @max_blocks:  The total blocks available to work with.
+ *
+ * Returns: void, but @len, @data_blocks and @ind_blocks are filled in.
+ */
+static void calc_max_reserv(struct gfs2_inode *ip, loff_t *len,
+                           unsigned int *data_blocks, unsigned int *ind_blocks,
+                           unsigned int max_blocks)
 {
+       loff_t max = *len;
        const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-       unsigned int max_blocks = ip->i_rgd->rd_free_clone;
        unsigned int tmp, max_data = max_blocks - 3 * (sdp->sd_max_height - 1);
 
        for (tmp = max_data; tmp > sdp->sd_diptrs;) {
                tmp = DIV_ROUND_UP(tmp, sdp->sd_inptrs);
                max_data -= tmp;
        }
-       /* This calculation isn't the exact reverse of gfs2_write_calc_reserve,
-          so it might end up with fewer data blocks */
-       if (max_data <= *data_blocks)
-               return;
+
        *data_blocks = max_data;
        *ind_blocks = max_blocks - max_data;
        *len = ((loff_t)max_data - 3) << sdp->sd_sb.sb_bsize_shift;
@@ -797,7 +804,7 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_alloc_parms ap = { .aflags = 0, };
        unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
-       loff_t bytes, max_bytes;
+       loff_t bytes, max_bytes, max_blks = UINT_MAX;
        int error;
        const loff_t pos = offset;
        const loff_t count = len;
@@ -819,6 +826,9 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
 
        gfs2_size_hint(file, offset, len);
 
+       gfs2_write_calc_reserv(ip, PAGE_SIZE, &data_blocks, &ind_blocks);
+       ap.min_target = data_blocks + ind_blocks;
+
        while (len > 0) {
                if (len < bytes)
                        bytes = len;
@@ -827,27 +837,41 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
                        offset += bytes;
                        continue;
                }
-               error = gfs2_quota_lock_check(ip);
+
+               /* We need to determine how many bytes we can actually
+                * fallocate without exceeding quota or going over the
+                * end of the fs. We start off optimistically by assuming
+                * we can write max_bytes */
+               max_bytes = (len > max_chunk_size) ? max_chunk_size : len;
+
+               /* Since max_bytes is most likely a theoretical max, we
+                * calculate a more realistic 'bytes' to serve as a good
+                * starting point for the number of bytes we may be able
+                * to write */
+               gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);
+               ap.target = data_blocks + ind_blocks;
+
+               error = gfs2_quota_lock_check(ip, &ap);
                if (error)
                        return error;
-retry:
-               gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);
+               /* ap.allowed tells us how many blocks quota will allow
+                * us to write. Check if this reduces max_blks */
+               if (ap.allowed && ap.allowed < max_blks)
+                       max_blks = ap.allowed;
 
-               ap.target = data_blocks + ind_blocks;
                error = gfs2_inplace_reserve(ip, &ap);
-               if (error) {
-                       if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) {
-                               bytes >>= 1;
-                               bytes &= bsize_mask;
-                               if (bytes == 0)
-                                       bytes = sdp->sd_sb.sb_bsize;
-                               goto retry;
-                       }
+               if (error)
                        goto out_qunlock;
-               }
-               max_bytes = bytes;
-               calc_max_reserv(ip, (len > max_chunk_size)? max_chunk_size: len,
-                               &max_bytes, &data_blocks, &ind_blocks);
+
+               /* check if the selected rgrp limits our max_blks further */
+               if (ap.allowed && ap.allowed < max_blks)
+                       max_blks = ap.allowed;
+
+               /* Almost done. Calculate bytes that can be written using
+                * max_blks. We also recompute max_bytes, data_blocks and
+                * ind_blocks */
+               calc_max_reserv(ip, &max_bytes, &data_blocks,
+                               &ind_blocks, max_blks);
 
                rblocks = RES_DINODE + ind_blocks + RES_STATFS + RES_QUOTA +
                          RES_RG_HDR + gfs2_rg_blocks(ip, data_blocks + ind_blocks);
@@ -931,6 +955,22 @@ out_uninit:
        return ret;
 }
 
+static ssize_t gfs2_file_splice_write(struct pipe_inode_info *pipe,
+                                     struct file *out, loff_t *ppos,
+                                     size_t len, unsigned int flags)
+{
+       int error;
+       struct gfs2_inode *ip = GFS2_I(out->f_mapping->host);
+
+       error = gfs2_rs_alloc(ip);
+       if (error)
+               return (ssize_t)error;
+
+       gfs2_size_hint(out, *ppos, len);
+
+       return iter_file_splice_write(pipe, out, ppos, len, flags);
+}
+
 #ifdef CONFIG_GFS2_FS_LOCKING_DLM
 
 /**
@@ -1077,7 +1117,7 @@ const struct file_operations gfs2_file_fops = {
        .lock           = gfs2_lock,
        .flock          = gfs2_flock,
        .splice_read    = generic_file_splice_read,
-       .splice_write   = iter_file_splice_write,
+       .splice_write   = gfs2_file_splice_write,
        .setlease       = simple_nosetlease,
        .fallocate      = gfs2_fallocate,
 };
@@ -1107,7 +1147,7 @@ const struct file_operations gfs2_file_fops_nolock = {
        .release        = gfs2_release,
        .fsync          = gfs2_fsync,
        .splice_read    = generic_file_splice_read,
-       .splice_write   = iter_file_splice_write,
+       .splice_write   = gfs2_file_splice_write,
        .setlease       = generic_setlease,
        .fallocate      = gfs2_fallocate,
 };
index f42dffba056ab0e6908788084f1c449e1c2683e6..0fa8062f85a7ab20332301ffafd1733940352096 100644 (file)
@@ -2047,34 +2047,41 @@ static const struct file_operations gfs2_sbstats_fops = {
 
 int gfs2_create_debugfs_file(struct gfs2_sbd *sdp)
 {
-       sdp->debugfs_dir = debugfs_create_dir(sdp->sd_table_name, gfs2_root);
-       if (!sdp->debugfs_dir)
-               return -ENOMEM;
-       sdp->debugfs_dentry_glocks = debugfs_create_file("glocks",
-                                                        S_IFREG | S_IRUGO,
-                                                        sdp->debugfs_dir, sdp,
-                                                        &gfs2_glocks_fops);
-       if (!sdp->debugfs_dentry_glocks)
+       struct dentry *dent;
+
+       dent = debugfs_create_dir(sdp->sd_table_name, gfs2_root);
+       if (IS_ERR_OR_NULL(dent))
+               goto fail;
+       sdp->debugfs_dir = dent;
+
+       dent = debugfs_create_file("glocks",
+                                  S_IFREG | S_IRUGO,
+                                  sdp->debugfs_dir, sdp,
+                                  &gfs2_glocks_fops);
+       if (IS_ERR_OR_NULL(dent))
                goto fail;
+       sdp->debugfs_dentry_glocks = dent;
 
-       sdp->debugfs_dentry_glstats = debugfs_create_file("glstats",
-                                                       S_IFREG | S_IRUGO,
-                                                       sdp->debugfs_dir, sdp,
-                                                       &gfs2_glstats_fops);
-       if (!sdp->debugfs_dentry_glstats)
+       dent = debugfs_create_file("glstats",
+                                  S_IFREG | S_IRUGO,
+                                  sdp->debugfs_dir, sdp,
+                                  &gfs2_glstats_fops);
+       if (IS_ERR_OR_NULL(dent))
                goto fail;
+       sdp->debugfs_dentry_glstats = dent;
 
-       sdp->debugfs_dentry_sbstats = debugfs_create_file("sbstats",
-                                                       S_IFREG | S_IRUGO,
-                                                       sdp->debugfs_dir, sdp,
-                                                       &gfs2_sbstats_fops);
-       if (!sdp->debugfs_dentry_sbstats)
+       dent = debugfs_create_file("sbstats",
+                                  S_IFREG | S_IRUGO,
+                                  sdp->debugfs_dir, sdp,
+                                  &gfs2_sbstats_fops);
+       if (IS_ERR_OR_NULL(dent))
                goto fail;
+       sdp->debugfs_dentry_sbstats = dent;
 
        return 0;
 fail:
        gfs2_delete_debugfs_file(sdp);
-       return -ENOMEM;
+       return dent ? PTR_ERR(dent) : -ENOMEM;
 }
 
 void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp)
@@ -2100,6 +2107,8 @@ void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp)
 int gfs2_register_debugfs(void)
 {
        gfs2_root = debugfs_create_dir("gfs2", NULL);
+       if (IS_ERR(gfs2_root))
+               return PTR_ERR(gfs2_root);
        return gfs2_root ? 0 : -ENOMEM;
 }
 
index 7a2dbbc0d6348e39872491b3e6a070c5729f93f5..58b75abf6ab2f4e9e0c1b37752eba724a5b55b61 100644 (file)
@@ -301,8 +301,10 @@ struct gfs2_blkreserv {
  * to the allocation code.
  */
 struct gfs2_alloc_parms {
-       u32 target;
+       u64 target;
+       u32 min_target;
        u32 aflags;
+       u64 allowed;
 };
 
 enum {
index 73c72253faac07f2918c08e5e20438d148160f7e..08bc84d7e768e7fb46ab7bae03c8f18597cb59fc 100644 (file)
@@ -382,7 +382,7 @@ static int alloc_dinode(struct gfs2_inode *ip, u32 flags, unsigned *dblocks)
        struct gfs2_alloc_parms ap = { .target = *dblocks, .aflags = flags, };
        int error;
 
-       error = gfs2_quota_lock_check(ip);
+       error = gfs2_quota_lock_check(ip, &ap);
        if (error)
                goto out;
 
@@ -525,7 +525,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
        int error;
 
        if (da->nr_blocks) {
-               error = gfs2_quota_lock_check(dip);
+               error = gfs2_quota_lock_check(dip, &ap);
                if (error)
                        goto fail_quota_locks;
 
@@ -953,7 +953,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
 
        if (da.nr_blocks) {
                struct gfs2_alloc_parms ap = { .target = da.nr_blocks, };
-               error = gfs2_quota_lock_check(dip);
+               error = gfs2_quota_lock_check(dip, &ap);
                if (error)
                        goto out_gunlock;
 
@@ -1470,7 +1470,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
 
        if (da.nr_blocks) {
                struct gfs2_alloc_parms ap = { .target = da.nr_blocks, };
-               error = gfs2_quota_lock_check(ndip);
+               error = gfs2_quota_lock_check(ndip, &ap);
                if (error)
                        goto out_gunlock;
 
@@ -1669,6 +1669,7 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
        kuid_t ouid, nuid;
        kgid_t ogid, ngid;
        int error;
+       struct gfs2_alloc_parms ap;
 
        ouid = inode->i_uid;
        ogid = inode->i_gid;
@@ -1696,9 +1697,11 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
        if (error)
                goto out;
 
+       ap.target = gfs2_get_inode_blocks(&ip->i_inode);
+
        if (!uid_eq(ouid, NO_UID_QUOTA_CHANGE) ||
            !gid_eq(ogid, NO_GID_QUOTA_CHANGE)) {
-               error = gfs2_quota_check(ip, nuid, ngid);
+               error = gfs2_quota_check(ip, nuid, ngid, &ap);
                if (error)
                        goto out_gunlock_q;
        }
@@ -1713,9 +1716,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
 
        if (!uid_eq(ouid, NO_UID_QUOTA_CHANGE) ||
            !gid_eq(ogid, NO_GID_QUOTA_CHANGE)) {
-               u64 blocks = gfs2_get_inode_blocks(&ip->i_inode);
-               gfs2_quota_change(ip, -blocks, ouid, ogid);
-               gfs2_quota_change(ip, blocks, nuid, ngid);
+               gfs2_quota_change(ip, -ap.target, ouid, ogid);
+               gfs2_quota_change(ip, ap.target, nuid, ngid);
        }
 
 out_end_trans:
index 3aa17d4d1cfcbf341e6115a8029c0e82f3e1a2cd..5c27e48aa76f57e1e070cfc89c0c99647fbea456 100644 (file)
@@ -923,6 +923,9 @@ restart:
        if (error)
                return error;
 
+       if (test_and_clear_bit(QDF_REFRESH, &qd->qd_flags))
+               force_refresh = FORCE;
+
        qd->qd_qb = *(struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr;
 
        if (force_refresh || qd->qd_qb.qb_magic != cpu_to_be32(GFS2_MAGIC)) {
@@ -974,11 +977,8 @@ int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
             sizeof(struct gfs2_quota_data *), sort_qd, NULL);
 
        for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
-               int force = NO_FORCE;
                qd = ip->i_res->rs_qa_qd[x];
-               if (test_and_clear_bit(QDF_REFRESH, &qd->qd_flags))
-                       force = FORCE;
-               error = do_glock(qd, force, &ip->i_res->rs_qa_qd_ghs[x]);
+               error = do_glock(qd, NO_FORCE, &ip->i_res->rs_qa_qd_ghs[x]);
                if (error)
                        break;
        }
@@ -1094,14 +1094,33 @@ static int print_message(struct gfs2_quota_data *qd, char *type)
        return 0;
 }
 
-int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
+/**
+ * gfs2_quota_check - check if allocating new blocks will exceed quota
+ * @ip:  The inode for which this check is being performed
+ * @uid: The uid to check against
+ * @gid: The gid to check against
+ * @ap:  The allocation parameters. ap->target contains the requested
+ *       blocks. ap->min_target, if set, contains the minimum blks
+ *       requested.
+ *
+ * Returns: 0 on success.
+ *                  min_req = ap->min_target ? ap->min_target : ap->target;
+ *                  quota must allow atleast min_req blks for success and
+ *                  ap->allowed is set to the number of blocks allowed
+ *
+ *          -EDQUOT otherwise, quota violation. ap->allowed is set to number
+ *                  of blocks available.
+ */
+int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid,
+                    struct gfs2_alloc_parms *ap)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_quota_data *qd;
-       s64 value;
+       s64 value, warn, limit;
        unsigned int x;
        int error = 0;
 
+       ap->allowed = UINT_MAX; /* Assume we are permitted a whole lot */
        if (!test_bit(GIF_QD_LOCKED, &ip->i_flags))
                return 0;
 
@@ -1115,30 +1134,37 @@ int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
                      qid_eq(qd->qd_id, make_kqid_gid(gid))))
                        continue;
 
+               warn = (s64)be64_to_cpu(qd->qd_qb.qb_warn);
+               limit = (s64)be64_to_cpu(qd->qd_qb.qb_limit);
                value = (s64)be64_to_cpu(qd->qd_qb.qb_value);
                spin_lock(&qd_lock);
                value += qd->qd_change;
                spin_unlock(&qd_lock);
 
-               if (be64_to_cpu(qd->qd_qb.qb_limit) && (s64)be64_to_cpu(qd->qd_qb.qb_limit) < value) {
-                       print_message(qd, "exceeded");
-                       quota_send_warning(qd->qd_id,
-                                          sdp->sd_vfs->s_dev, QUOTA_NL_BHARDWARN);
-
-                       error = -EDQUOT;
-                       break;
-               } else if (be64_to_cpu(qd->qd_qb.qb_warn) &&
-                          (s64)be64_to_cpu(qd->qd_qb.qb_warn) < value &&
+               if (limit > 0 && (limit - value) < ap->allowed)
+                       ap->allowed = limit - value;
+               /* If we can't meet the target */
+               if (limit && limit < (value + (s64)ap->target)) {
+                       /* If no min_target specified or we don't meet
+                        * min_target, return -EDQUOT */
+                       if (!ap->min_target || ap->min_target > ap->allowed) {
+                               print_message(qd, "exceeded");
+                               quota_send_warning(qd->qd_id,
+                                                  sdp->sd_vfs->s_dev,
+                                                  QUOTA_NL_BHARDWARN);
+                               error = -EDQUOT;
+                               break;
+                       }
+               } else if (warn && warn < value &&
                           time_after_eq(jiffies, qd->qd_last_warn +
-                                        gfs2_tune_get(sdp,
-                                               gt_quota_warn_period) * HZ)) {
+                                        gfs2_tune_get(sdp, gt_quota_warn_period)
+                                        * HZ)) {
                        quota_send_warning(qd->qd_id,
                                           sdp->sd_vfs->s_dev, QUOTA_NL_BSOFTWARN);
                        error = print_message(qd, "warning");
                        qd->qd_last_warn = jiffies;
                }
        }
-
        return error;
 }
 
index 55d506eb3c4a31ab956ab23e85158d0ddc4947ea..ad04b3acae2b9d1449a8b2e1127dcc53e45bb74d 100644 (file)
@@ -24,7 +24,8 @@ extern void gfs2_quota_unhold(struct gfs2_inode *ip);
 extern int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid);
 extern void gfs2_quota_unlock(struct gfs2_inode *ip);
 
-extern int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid);
+extern int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid,
+                           struct gfs2_alloc_parms *ap);
 extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
                              kuid_t uid, kgid_t gid);
 
@@ -37,7 +38,8 @@ extern int gfs2_quotad(void *data);
 
 extern void gfs2_wake_up_statfs(struct gfs2_sbd *sdp);
 
-static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
+static inline int gfs2_quota_lock_check(struct gfs2_inode *ip,
+                                       struct gfs2_alloc_parms *ap)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        int ret;
@@ -48,7 +50,7 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
                return ret;
        if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
                return 0;
-       ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
+       ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid, ap);
        if (ret)
                gfs2_quota_unlock(ip);
        return ret;
index 9150207f365cdfe8207879415fb816526f8178b3..6af2396a317c3de22e9d8bd86e28246b28067523 100644 (file)
@@ -1946,10 +1946,18 @@ static inline int fast_to_acquire(struct gfs2_rgrpd *rgd)
  * @ip: the inode to reserve space for
  * @ap: the allocation parameters
  *
- * Returns: errno
+ * We try our best to find an rgrp that has at least ap->target blocks
+ * available. After a couple of passes (loops == 2), the prospects of finding
+ * such an rgrp diminish. At this stage, we return the first rgrp that has
+ * atleast ap->min_target blocks available. Either way, we set ap->allowed to
+ * the number of blocks available in the chosen rgrp.
+ *
+ * Returns: 0 on success,
+ *          -ENOMEM if a suitable rgrp can't be found
+ *          errno otherwise
  */
 
-int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *ap)
+int gfs2_inplace_reserve(struct gfs2_inode *ip, struct gfs2_alloc_parms *ap)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_rgrpd *begin = NULL;
@@ -2012,7 +2020,7 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *a
                /* Skip unuseable resource groups */
                if ((rs->rs_rbm.rgd->rd_flags & (GFS2_RGF_NOALLOC |
                                                 GFS2_RDF_ERROR)) ||
-                   (ap->target > rs->rs_rbm.rgd->rd_extfail_pt))
+                   (loops == 0 && ap->target > rs->rs_rbm.rgd->rd_extfail_pt))
                        goto skip_rgrp;
 
                if (sdp->sd_args.ar_rgrplvb)
@@ -2027,11 +2035,13 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *a
                        goto check_rgrp;
 
                /* If rgrp has enough free space, use it */
-               if (rs->rs_rbm.rgd->rd_free_clone >= ap->target) {
+               if (rs->rs_rbm.rgd->rd_free_clone >= ap->target ||
+                   (loops == 2 && ap->min_target &&
+                    rs->rs_rbm.rgd->rd_free_clone >= ap->min_target)) {
                        ip->i_rgd = rs->rs_rbm.rgd;
+                       ap->allowed = ip->i_rgd->rd_free_clone;
                        return 0;
                }
-
 check_rgrp:
                /* Check for unlinked inodes which can be reclaimed */
                if (rs->rs_rbm.rgd->rd_flags & GFS2_RDF_CHECK)
index b104f4af3afdb8c2ef2f3c4f938aeca09c3bc912..68972ecfbb019018f89f233da989a816117d2b01 100644 (file)
@@ -41,7 +41,8 @@ extern void gfs2_rgrp_go_unlock(struct gfs2_holder *gh);
 extern struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip);
 
 #define GFS2_AF_ORLOV 1
-extern int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *ap);
+extern int gfs2_inplace_reserve(struct gfs2_inode *ip,
+                               struct gfs2_alloc_parms *ap);
 extern void gfs2_inplace_release(struct gfs2_inode *ip);
 
 extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n,
index 0b81f783f78724293b174cd997d7f7b7321468b9..fd260ce8869a86ca532f2138900bfc7eb7a70a06 100644 (file)
@@ -732,7 +732,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
        if (error)
                return error;
 
-       error = gfs2_quota_lock_check(ip);
+       error = gfs2_quota_lock_check(ip, &ap);
        if (error)
                return error;
 
index d0929bc817826e012cc829bb0f021832eea24379..98d4ea45bb70aad886641f66d81e0007f0d0e34d 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
 #include <linux/sched.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 #include "hfs_fs.h"
 #include "btree.h"
index 0cf786f2d046f9fbae9b110a2a2d212c008fb3aa..f541196d4ee910a3f9ec6ce26841937c9fa7eb73 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
 #include <linux/sched.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
index c274aca8e8dc231cb4473b964bc3315058910968..db76cec3ce21268bbeffcb45c479bfadf7c33e73 100644 (file)
@@ -319,7 +319,7 @@ static int hugetlbfs_write_end(struct file *file, struct address_space *mapping,
 
 static void truncate_huge_page(struct page *page)
 {
-       cancel_dirty_page(page, /* No IO accounting for huge pages? */0);
+       ClearPageDirty(page);
        ClearPageUptodate(page);
        delete_from_page_cache(page);
 }
index d72817ac51f646e50ea2e6e867a5252b540eb428..762c7a3cf43d1b650757d25e2d38830b2b567f37 100644 (file)
@@ -195,7 +195,7 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat
        /* unchecked xdatum is chained with c->xattr_unchecked */
        list_del_init(&xd->xindex);
 
-       dbg_xattr("success on verfying xdatum (xid=%u, version=%u)\n",
+       dbg_xattr("success on verifying xdatum (xid=%u, version=%u)\n",
                  xd->xid, xd->version);
 
        return 0;
index bd3df1ca3c9b7f955571c056f86f98e97beda7b9..3197aed106148d8b0839b80405ecad125c14e7aa 100644 (file)
@@ -22,8 +22,8 @@
 #include <linux/buffer_head.h>
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
+#include <linux/uio.h>
 #include <linux/writeback.h>
-#include <linux/aio.h>
 #include "jfs_incore.h"
 #include "jfs_inode.h"
 #include "jfs_filsys.h"
index 5d30c56ae07506f09f92d11d02b03a39213a0797..4cd9798f4948c646d065c50dd0f6092fe75197b0 100644 (file)
@@ -102,7 +102,7 @@ void jfs_error(struct super_block *sb, const char *fmt, ...)
        vaf.fmt = fmt;
        vaf.va = &args;
 
-       pr_err("ERROR: (device %s): %pf: %pV\n",
+       pr_err("ERROR: (device %s): %ps: %pV\n",
               sb->s_id, __builtin_return_address(0), &vaf);
 
        va_end(args);
index c83145af4bfc0ea9bb159002e3545e8a8cd65157..76fb76a0818bc274fc67b2d87b582db6690d62a6 100644 (file)
  * PATH_MAX includes the nul terminator --RR.
  */
 
-#define EMBEDDED_NAME_MAX      (PATH_MAX - sizeof(struct filename))
+#define EMBEDDED_NAME_MAX      (PATH_MAX - offsetof(struct filename, iname))
 
 struct filename *
 getname_flags(const char __user *filename, int flags, int *empty)
 {
-       struct filename *result, *err;
-       int len;
-       long max;
+       struct filename *result;
        char *kname;
+       int len;
 
        result = audit_reusename(filename);
        if (result)
@@ -136,22 +135,18 @@ getname_flags(const char __user *filename, int flags, int *empty)
        result = __getname();
        if (unlikely(!result))
                return ERR_PTR(-ENOMEM);
-       result->refcnt = 1;
 
        /*
         * First, try to embed the struct filename inside the names_cache
         * allocation
         */
-       kname = (char *)result + sizeof(*result);
+       kname = (char *)result->iname;
        result->name = kname;
-       result->separate = false;
-       max = EMBEDDED_NAME_MAX;
 
-recopy:
-       len = strncpy_from_user(kname, filename, max);
+       len = strncpy_from_user(kname, filename, EMBEDDED_NAME_MAX);
        if (unlikely(len < 0)) {
-               err = ERR_PTR(len);
-               goto error;
+               __putname(result);
+               return ERR_PTR(len);
        }
 
        /*
@@ -160,43 +155,49 @@ recopy:
         * names_cache allocation for the pathname, and re-do the copy from
         * userland.
         */
-       if (len == EMBEDDED_NAME_MAX && max == EMBEDDED_NAME_MAX) {
+       if (unlikely(len == EMBEDDED_NAME_MAX)) {
+               const size_t size = offsetof(struct filename, iname[1]);
                kname = (char *)result;
 
-               result = kzalloc(sizeof(*result), GFP_KERNEL);
-               if (!result) {
-                       err = ERR_PTR(-ENOMEM);
-                       result = (struct filename *)kname;
-                       goto error;
+               /*
+                * size is chosen that way we to guarantee that
+                * result->iname[0] is within the same object and that
+                * kname can't be equal to result->iname, no matter what.
+                */
+               result = kzalloc(size, GFP_KERNEL);
+               if (unlikely(!result)) {
+                       __putname(kname);
+                       return ERR_PTR(-ENOMEM);
                }
                result->name = kname;
-               result->separate = true;
-               result->refcnt = 1;
-               max = PATH_MAX;
-               goto recopy;
+               len = strncpy_from_user(kname, filename, PATH_MAX);
+               if (unlikely(len < 0)) {
+                       __putname(kname);
+                       kfree(result);
+                       return ERR_PTR(len);
+               }
+               if (unlikely(len == PATH_MAX)) {
+                       __putname(kname);
+                       kfree(result);
+                       return ERR_PTR(-ENAMETOOLONG);
+               }
        }
 
+       result->refcnt = 1;
        /* The empty path is special. */
        if (unlikely(!len)) {
                if (empty)
                        *empty = 1;
-               err = ERR_PTR(-ENOENT);
-               if (!(flags & LOOKUP_EMPTY))
-                       goto error;
+               if (!(flags & LOOKUP_EMPTY)) {
+                       putname(result);
+                       return ERR_PTR(-ENOENT);
+               }
        }
 
-       err = ERR_PTR(-ENAMETOOLONG);
-       if (unlikely(len >= PATH_MAX))
-               goto error;
-
        result->uptr = filename;
        result->aname = NULL;
        audit_getname(result);
        return result;
-
-error:
-       putname(result);
-       return err;
 }
 
 struct filename *
@@ -216,8 +217,7 @@ getname_kernel(const char * filename)
                return ERR_PTR(-ENOMEM);
 
        if (len <= EMBEDDED_NAME_MAX) {
-               result->name = (char *)(result) + sizeof(*result);
-               result->separate = false;
+               result->name = (char *)result->iname;
        } else if (len <= PATH_MAX) {
                struct filename *tmp;
 
@@ -227,7 +227,6 @@ getname_kernel(const char * filename)
                        return ERR_PTR(-ENOMEM);
                }
                tmp->name = (char *)result;
-               tmp->separate = true;
                result = tmp;
        } else {
                __putname(result);
@@ -249,7 +248,7 @@ void putname(struct filename *name)
        if (--name->refcnt > 0)
                return;
 
-       if (name->separate) {
+       if (name->name != name->iname) {
                __putname(name->name);
                kfree(name);
        } else
@@ -1851,10 +1850,11 @@ static int link_path_walk(const char *name, struct nameidata *nd)
        return err;
 }
 
-static int path_init(int dfd, const char *name, unsigned int flags,
+static int path_init(int dfd, const struct filename *name, unsigned int flags,
                     struct nameidata *nd)
 {
        int retval = 0;
+       const char *s = name->name;
 
        nd->last_type = LAST_ROOT; /* if there are only slashes... */
        nd->flags = flags | LOOKUP_JUMPED | LOOKUP_PARENT;
@@ -1863,7 +1863,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
        if (flags & LOOKUP_ROOT) {
                struct dentry *root = nd->root.dentry;
                struct inode *inode = root->d_inode;
-               if (*name) {
+               if (*s) {
                        if (!d_can_lookup(root))
                                return -ENOTDIR;
                        retval = inode_permission(inode, MAY_EXEC);
@@ -1885,7 +1885,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
        nd->root.mnt = NULL;
 
        nd->m_seq = read_seqbegin(&mount_lock);
-       if (*name=='/') {
+       if (*s == '/') {
                if (flags & LOOKUP_RCU) {
                        rcu_read_lock();
                        nd->seq = set_root_rcu(nd);
@@ -1919,7 +1919,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
 
                dentry = f.file->f_path.dentry;
 
-               if (*name) {
+               if (*s) {
                        if (!d_can_lookup(dentry)) {
                                fdput(f);
                                return -ENOTDIR;
@@ -1949,7 +1949,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
        return -ECHILD;
 done:
        current->total_link_count = 0;
-       return link_path_walk(name, nd);
+       return link_path_walk(s, nd);
 }
 
 static void path_cleanup(struct nameidata *nd)
@@ -1972,7 +1972,7 @@ static inline int lookup_last(struct nameidata *nd, struct path *path)
 }
 
 /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
-static int path_lookupat(int dfd, const char *name,
+static int path_lookupat(int dfd, const struct filename *name,
                                unsigned int flags, struct nameidata *nd)
 {
        struct path path;
@@ -2027,31 +2027,17 @@ static int path_lookupat(int dfd, const char *name,
 static int filename_lookup(int dfd, struct filename *name,
                                unsigned int flags, struct nameidata *nd)
 {
-       int retval = path_lookupat(dfd, name->name, flags | LOOKUP_RCU, nd);
+       int retval = path_lookupat(dfd, name, flags | LOOKUP_RCU, nd);
        if (unlikely(retval == -ECHILD))
-               retval = path_lookupat(dfd, name->name, flags, nd);
+               retval = path_lookupat(dfd, name, flags, nd);
        if (unlikely(retval == -ESTALE))
-               retval = path_lookupat(dfd, name->name,
-                                               flags | LOOKUP_REVAL, nd);
+               retval = path_lookupat(dfd, name, flags | LOOKUP_REVAL, nd);
 
        if (likely(!retval))
                audit_inode(name, nd->path.dentry, flags & LOOKUP_PARENT);
        return retval;
 }
 
-static int do_path_lookup(int dfd, const char *name,
-                               unsigned int flags, struct nameidata *nd)
-{
-       struct filename *filename = getname_kernel(name);
-       int retval = PTR_ERR(filename);
-
-       if (!IS_ERR(filename)) {
-               retval = filename_lookup(dfd, filename, flags, nd);
-               putname(filename);
-       }
-       return retval;
-}
-
 /* does lookup, returns the object with parent locked */
 struct dentry *kern_path_locked(const char *name, struct path *path)
 {
@@ -2089,9 +2075,15 @@ out:
 int kern_path(const char *name, unsigned int flags, struct path *path)
 {
        struct nameidata nd;
-       int res = do_path_lookup(AT_FDCWD, name, flags, &nd);
-       if (!res)
-               *path = nd.path;
+       struct filename *filename = getname_kernel(name);
+       int res = PTR_ERR(filename);
+
+       if (!IS_ERR(filename)) {
+               res = filename_lookup(AT_FDCWD, filename, flags, &nd);
+               putname(filename);
+               if (!res)
+                       *path = nd.path;
+       }
        return res;
 }
 EXPORT_SYMBOL(kern_path);
@@ -2108,15 +2100,22 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
                    const char *name, unsigned int flags,
                    struct path *path)
 {
-       struct nameidata nd;
-       int err;
-       nd.root.dentry = dentry;
-       nd.root.mnt = mnt;
+       struct filename *filename = getname_kernel(name);
+       int err = PTR_ERR(filename);
+
        BUG_ON(flags & LOOKUP_PARENT);
-       /* the first argument of do_path_lookup() is ignored with LOOKUP_ROOT */
-       err = do_path_lookup(AT_FDCWD, name, flags | LOOKUP_ROOT, &nd);
-       if (!err)
-               *path = nd.path;
+
+       /* the first argument of filename_lookup() is ignored with LOOKUP_ROOT */
+       if (!IS_ERR(filename)) {
+               struct nameidata nd;
+               nd.root.dentry = dentry;
+               nd.root.mnt = mnt;
+               err = filename_lookup(AT_FDCWD, filename,
+                                     flags | LOOKUP_ROOT, &nd);
+               if (!err)
+                       *path = nd.path;
+               putname(filename);
+       }
        return err;
 }
 EXPORT_SYMBOL(vfs_path_lookup);
@@ -2138,9 +2137,7 @@ static struct dentry *lookup_hash(struct nameidata *nd)
  * @len:       maximum length @len should be interpreted to
  *
  * Note that this routine is purely a helper for filesystem usage and should
- * not be called by generic code.  Also note that by using this function the
- * nameidata argument is passed to the filesystem methods and a filesystem
- * using this helper needs to be prepared for that.
+ * not be called by generic code.
  */
 struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
 {
@@ -2341,7 +2338,8 @@ out:
  * Returns 0 and "path" will be valid on success; Returns error otherwise.
  */
 static int
-path_mountpoint(int dfd, const char *name, struct path *path, unsigned int flags)
+path_mountpoint(int dfd, const struct filename *name, struct path *path,
+               unsigned int flags)
 {
        struct nameidata nd;
        int err;
@@ -2370,20 +2368,20 @@ out:
 }
 
 static int
-filename_mountpoint(int dfd, struct filename *s, struct path *path,
+filename_mountpoint(int dfd, struct filename *name, struct path *path,
                        unsigned int flags)
 {
        int error;
-       if (IS_ERR(s))
-               return PTR_ERR(s);
-       error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_RCU);
+       if (IS_ERR(name))
+               return PTR_ERR(name);
+       error = path_mountpoint(dfd, name, path, flags | LOOKUP_RCU);
        if (unlikely(error == -ECHILD))
-               error = path_mountpoint(dfd, s->name, path, flags);
+               error = path_mountpoint(dfd, name, path, flags);
        if (unlikely(error == -ESTALE))
-               error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_REVAL);
+               error = path_mountpoint(dfd, name, path, flags | LOOKUP_REVAL);
        if (likely(!error))
-               audit_inode(s, path->dentry, 0);
-       putname(s);
+               audit_inode(name, path->dentry, 0);
+       putname(name);
        return error;
 }
 
@@ -3156,7 +3154,7 @@ static int do_tmpfile(int dfd, struct filename *pathname,
        static const struct qstr name = QSTR_INIT("/", 1);
        struct dentry *dentry, *child;
        struct inode *dir;
-       int error = path_lookupat(dfd, pathname->name,
+       int error = path_lookupat(dfd, pathname,
                                  flags | LOOKUP_DIRECTORY, nd);
        if (unlikely(error))
                return error;
@@ -3229,7 +3227,7 @@ static struct file *path_openat(int dfd, struct filename *pathname,
                goto out;
        }
 
-       error = path_init(dfd, pathname->name, flags, nd);
+       error = path_init(dfd, pathname, flags, nd);
        if (unlikely(error))
                goto out;
 
index e907c8cf732e3cff6bc9711ccf0b20c9261cdca2..c3929fb2ab26c2971e2e4a9f09e0f5a88387c144 100644 (file)
@@ -265,7 +265,7 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t
 
        return -EINVAL;
 #else
-       VM_BUG_ON(iocb->ki_nbytes != PAGE_SIZE);
+       VM_BUG_ON(iov_iter_count(iter) != PAGE_SIZE);
 
        if (rw == READ)
                return nfs_file_direct_read(iocb, iter, pos);
@@ -393,7 +393,7 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write)
                long res = (long) dreq->error;
                if (!res)
                        res = (long) dreq->count;
-               aio_complete(dreq->iocb, res, 0);
+               dreq->iocb->ki_complete(dreq->iocb, res, 0);
        }
 
        complete_all(&dreq->completion);
index e679d24c39d3a57d5ef510a22d5ccbe2832c5335..37b15582e0de960a966e80fcda3aa1680caa094d 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/nfs_mount.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
-#include <linux/aio.h>
 #include <linux/gfp.h>
 #include <linux/swap.h>
 
index 849ed784d6ac1fc6b923c32278e089f87575b8db..759931088094940069eecaf4605af0d9f6742581 100644 (file)
@@ -1876,11 +1876,6 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page)
                 * request from the inode / page_private pointer and
                 * release it */
                nfs_inode_remove_request(req);
-               /*
-                * In case nfs_inode_remove_request has marked the
-                * page as being dirty
-                */
-               cancel_dirty_page(page, PAGE_CACHE_SIZE);
                nfs_unlock_and_release_request(req);
        }
 
index 8b5969538f39229cede14416a067d2e056c1a677..ab4987bc637f8b084298086cf48f00e31bfe1298 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/mpage.h>
 #include <linux/pagemap.h>
 #include <linux/writeback.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 #include "nilfs.h"
 #include "btnode.h"
 #include "segment.h"
index 36ae529511c49140417cafe6559a167cd17d92e4..2ff263e6d363dba5f9621ad705c5795aaf855326 100644 (file)
@@ -8,7 +8,7 @@ ntfs-y := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \
 
 ntfs-$(CONFIG_NTFS_RW) += bitmap.o lcnalloc.o logfile.o quota.o usnjrnl.o
 
-ccflags-y := -DNTFS_VERSION=\"2.1.31\"
+ccflags-y := -DNTFS_VERSION=\"2.1.32\"
 ccflags-$(CONFIG_NTFS_DEBUG)   += -DDEBUG
 ccflags-$(CONFIG_NTFS_RW)      += -DNTFS_RW
 
index 1da9b2d184dc4e32d9ac9a95eb0ee2553c5a1e46..c1da78dad1afb389039660aa41064bb6f948fa76 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * file.c - NTFS kernel file operations.  Part of the Linux-NTFS project.
  *
- * Copyright (c) 2001-2014 Anton Altaparmakov and Tuxera Inc.
+ * Copyright (c) 2001-2015 Anton Altaparmakov and Tuxera Inc.
  *
  * This program/include file is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as published
@@ -28,7 +28,6 @@
 #include <linux/swap.h>
 #include <linux/uio.h>
 #include <linux/writeback.h>
-#include <linux/aio.h>
 
 #include <asm/page.h>
 #include <asm/uaccess.h>
@@ -329,62 +328,168 @@ err_out:
        return err;
 }
 
-/**
- * ntfs_fault_in_pages_readable -
- *
- * Fault a number of userspace pages into pagetables.
- *
- * Unlike include/linux/pagemap.h::fault_in_pages_readable(), this one copes
- * with more than two userspace pages as well as handling the single page case
- * elegantly.
- *
- * If you find this difficult to understand, then think of the while loop being
- * the following code, except that we do without the integer variable ret:
- *
- *     do {
- *             ret = __get_user(c, uaddr);
- *             uaddr += PAGE_SIZE;
- *     } while (!ret && uaddr < end);
- *
- * Note, the final __get_user() may well run out-of-bounds of the user buffer,
- * but _not_ out-of-bounds of the page the user buffer belongs to, and since
- * this is only a read and not a write, and since it is still in the same page,
- * it should not matter and this makes the code much simpler.
- */
-static inline void ntfs_fault_in_pages_readable(const char __user *uaddr,
-               int bytes)
+static ssize_t ntfs_prepare_file_for_write(struct file *file, loff_t *ppos,
+               size_t *count)
 {
-       const char __user *end;
-       volatile char c;
-
-       /* Set @end to the first byte outside the last page we care about. */
-       end = (const char __user*)PAGE_ALIGN((unsigned long)uaddr + bytes);
-
-       while (!__get_user(c, uaddr) && (uaddr += PAGE_SIZE, uaddr < end))
-               ;
-}
-
-/**
- * ntfs_fault_in_pages_readable_iovec -
- *
- * Same as ntfs_fault_in_pages_readable() but operates on an array of iovecs.
- */
-static inline void ntfs_fault_in_pages_readable_iovec(const struct iovec *iov,
-               size_t iov_ofs, int bytes)
-{
-       do {
-               const char __user *buf;
-               unsigned len;
+       loff_t pos;
+       s64 end, ll;
+       ssize_t err;
+       unsigned long flags;
+       struct inode *vi = file_inode(file);
+       ntfs_inode *base_ni, *ni = NTFS_I(vi);
+       ntfs_volume *vol = ni->vol;
 
-               buf = iov->iov_base + iov_ofs;
-               len = iov->iov_len - iov_ofs;
-               if (len > bytes)
-                       len = bytes;
-               ntfs_fault_in_pages_readable(buf, len);
-               bytes -= len;
-               iov++;
-               iov_ofs = 0;
-       } while (bytes);
+       ntfs_debug("Entering for i_ino 0x%lx, attribute type 0x%x, pos "
+                       "0x%llx, count 0x%lx.", vi->i_ino,
+                       (unsigned)le32_to_cpu(ni->type),
+                       (unsigned long long)*ppos, (unsigned long)*count);
+       /* We can write back this queue in page reclaim. */
+       current->backing_dev_info = inode_to_bdi(vi);
+       err = generic_write_checks(file, ppos, count, S_ISBLK(vi->i_mode));
+       if (unlikely(err))
+               goto out;
+       /*
+        * All checks have passed.  Before we start doing any writing we want
+        * to abort any totally illegal writes.
+        */
+       BUG_ON(NInoMstProtected(ni));
+       BUG_ON(ni->type != AT_DATA);
+       /* If file is encrypted, deny access, just like NT4. */
+       if (NInoEncrypted(ni)) {
+               /* Only $DATA attributes can be encrypted. */
+               /*
+                * Reminder for later: Encrypted files are _always_
+                * non-resident so that the content can always be encrypted.
+                */
+               ntfs_debug("Denying write access to encrypted file.");
+               err = -EACCES;
+               goto out;
+       }
+       if (NInoCompressed(ni)) {
+               /* Only unnamed $DATA attribute can be compressed. */
+               BUG_ON(ni->name_len);
+               /*
+                * Reminder for later: If resident, the data is not actually
+                * compressed.  Only on the switch to non-resident does
+                * compression kick in.  This is in contrast to encrypted files
+                * (see above).
+                */
+               ntfs_error(vi->i_sb, "Writing to compressed files is not "
+                               "implemented yet.  Sorry.");
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+       if (*count == 0)
+               goto out;
+       base_ni = ni;
+       if (NInoAttr(ni))
+               base_ni = ni->ext.base_ntfs_ino;
+       err = file_remove_suid(file);
+       if (unlikely(err))
+               goto out;
+       /*
+        * Our ->update_time method always succeeds thus file_update_time()
+        * cannot fail either so there is no need to check the return code.
+        */
+       file_update_time(file);
+       pos = *ppos;
+       /* The first byte after the last cluster being written to. */
+       end = (pos + *count + vol->cluster_size_mask) &
+                       ~(u64)vol->cluster_size_mask;
+       /*
+        * If the write goes beyond the allocated size, extend the allocation
+        * to cover the whole of the write, rounded up to the nearest cluster.
+        */
+       read_lock_irqsave(&ni->size_lock, flags);
+       ll = ni->allocated_size;
+       read_unlock_irqrestore(&ni->size_lock, flags);
+       if (end > ll) {
+               /*
+                * Extend the allocation without changing the data size.
+                *
+                * Note we ensure the allocation is big enough to at least
+                * write some data but we do not require the allocation to be
+                * complete, i.e. it may be partial.
+                */
+               ll = ntfs_attr_extend_allocation(ni, end, -1, pos);
+               if (likely(ll >= 0)) {
+                       BUG_ON(pos >= ll);
+                       /* If the extension was partial truncate the write. */
+                       if (end > ll) {
+                               ntfs_debug("Truncating write to inode 0x%lx, "
+                                               "attribute type 0x%x, because "
+                                               "the allocation was only "
+                                               "partially extended.",
+                                               vi->i_ino, (unsigned)
+                                               le32_to_cpu(ni->type));
+                               *count = ll - pos;
+                       }
+               } else {
+                       err = ll;
+                       read_lock_irqsave(&ni->size_lock, flags);
+                       ll = ni->allocated_size;
+                       read_unlock_irqrestore(&ni->size_lock, flags);
+                       /* Perform a partial write if possible or fail. */
+                       if (pos < ll) {
+                               ntfs_debug("Truncating write to inode 0x%lx "
+                                               "attribute type 0x%x, because "
+                                               "extending the allocation "
+                                               "failed (error %d).",
+                                               vi->i_ino, (unsigned)
+                                               le32_to_cpu(ni->type),
+                                               (int)-err);
+                               *count = ll - pos;
+                       } else {
+                               if (err != -ENOSPC)
+                                       ntfs_error(vi->i_sb, "Cannot perform "
+                                                       "write to inode "
+                                                       "0x%lx, attribute "
+                                                       "type 0x%x, because "
+                                                       "extending the "
+                                                       "allocation failed "
+                                                       "(error %ld).",
+                                                       vi->i_ino, (unsigned)
+                                                       le32_to_cpu(ni->type),
+                                                       (long)-err);
+                               else
+                                       ntfs_debug("Cannot perform write to "
+                                                       "inode 0x%lx, "
+                                                       "attribute type 0x%x, "
+                                                       "because there is not "
+                                                       "space left.",
+                                                       vi->i_ino, (unsigned)
+                                                       le32_to_cpu(ni->type));
+                               goto out;
+                       }
+               }
+       }
+       /*
+        * If the write starts beyond the initialized size, extend it up to the
+        * beginning of the write and initialize all non-sparse space between
+        * the old initialized size and the new one.  This automatically also
+        * increments the vfs inode->i_size to keep it above or equal to the
+        * initialized_size.
+        */
+       read_lock_irqsave(&ni->size_lock, flags);
+       ll = ni->initialized_size;
+       read_unlock_irqrestore(&ni->size_lock, flags);
+       if (pos > ll) {
+               /*
+                * Wait for ongoing direct i/o to complete before proceeding.
+                * New direct i/o cannot start as we hold i_mutex.
+                */
+               inode_dio_wait(vi);
+               err = ntfs_attr_extend_initialized(ni, pos);
+               if (unlikely(err < 0))
+                       ntfs_error(vi->i_sb, "Cannot perform write to inode "
+                                       "0x%lx, attribute type 0x%x, because "
+                                       "extending the initialized size "
+                                       "failed (error %d).", vi->i_ino,
+                                       (unsigned)le32_to_cpu(ni->type),
+                                       (int)-err);
+       }
+out:
+       return err;
 }
 
 /**
@@ -421,8 +526,8 @@ static inline int __ntfs_grab_cache_pages(struct address_space *mapping,
                                        goto err_out;
                                }
                        }
-                       err = add_to_page_cache_lru(*cached_page, mapping, index,
-                                       GFP_KERNEL);
+                       err = add_to_page_cache_lru(*cached_page, mapping,
+                                       index, GFP_KERNEL);
                        if (unlikely(err)) {
                                if (err == -EEXIST)
                                        continue;
@@ -1268,180 +1373,6 @@ rl_not_mapped_enoent:
        return err;
 }
 
-/*
- * Copy as much as we can into the pages and return the number of bytes which
- * were successfully copied.  If a fault is encountered then clear the pages
- * out to (ofs + bytes) and return the number of bytes which were copied.
- */
-static inline size_t ntfs_copy_from_user(struct page **pages,
-               unsigned nr_pages, unsigned ofs, const char __user *buf,
-               size_t bytes)
-{
-       struct page **last_page = pages + nr_pages;
-       char *addr;
-       size_t total = 0;
-       unsigned len;
-       int left;
-
-       do {
-               len = PAGE_CACHE_SIZE - ofs;
-               if (len > bytes)
-                       len = bytes;
-               addr = kmap_atomic(*pages);
-               left = __copy_from_user_inatomic(addr + ofs, buf, len);
-               kunmap_atomic(addr);
-               if (unlikely(left)) {
-                       /* Do it the slow way. */
-                       addr = kmap(*pages);
-                       left = __copy_from_user(addr + ofs, buf, len);
-                       kunmap(*pages);
-                       if (unlikely(left))
-                               goto err_out;
-               }
-               total += len;
-               bytes -= len;
-               if (!bytes)
-                       break;
-               buf += len;
-               ofs = 0;
-       } while (++pages < last_page);
-out:
-       return total;
-err_out:
-       total += len - left;
-       /* Zero the rest of the target like __copy_from_user(). */
-       while (++pages < last_page) {
-               bytes -= len;
-               if (!bytes)
-                       break;
-               len = PAGE_CACHE_SIZE;
-               if (len > bytes)
-                       len = bytes;
-               zero_user(*pages, 0, len);
-       }
-       goto out;
-}
-
-static size_t __ntfs_copy_from_user_iovec_inatomic(char *vaddr,
-               const struct iovec *iov, size_t iov_ofs, size_t bytes)
-{
-       size_t total = 0;
-
-       while (1) {
-               const char __user *buf = iov->iov_base + iov_ofs;
-               unsigned len;
-               size_t left;
-
-               len = iov->iov_len - iov_ofs;
-               if (len > bytes)
-                       len = bytes;
-               left = __copy_from_user_inatomic(vaddr, buf, len);
-               total += len;
-               bytes -= len;
-               vaddr += len;
-               if (unlikely(left)) {
-                       total -= left;
-                       break;
-               }
-               if (!bytes)
-                       break;
-               iov++;
-               iov_ofs = 0;
-       }
-       return total;
-}
-
-static inline void ntfs_set_next_iovec(const struct iovec **iovp,
-               size_t *iov_ofsp, size_t bytes)
-{
-       const struct iovec *iov = *iovp;
-       size_t iov_ofs = *iov_ofsp;
-
-       while (bytes) {
-               unsigned len;
-
-               len = iov->iov_len - iov_ofs;
-               if (len > bytes)
-                       len = bytes;
-               bytes -= len;
-               iov_ofs += len;
-               if (iov->iov_len == iov_ofs) {
-                       iov++;
-                       iov_ofs = 0;
-               }
-       }
-       *iovp = iov;
-       *iov_ofsp = iov_ofs;
-}
-
-/*
- * This has the same side-effects and return value as ntfs_copy_from_user().
- * The difference is that on a fault we need to memset the remainder of the
- * pages (out to offset + bytes), to emulate ntfs_copy_from_user()'s
- * single-segment behaviour.
- *
- * We call the same helper (__ntfs_copy_from_user_iovec_inatomic()) both when
- * atomic and when not atomic.  This is ok because it calls
- * __copy_from_user_inatomic() and it is ok to call this when non-atomic.  In
- * fact, the only difference between __copy_from_user_inatomic() and
- * __copy_from_user() is that the latter calls might_sleep() and the former
- * should not zero the tail of the buffer on error.  And on many architectures
- * __copy_from_user_inatomic() is just defined to __copy_from_user() so it
- * makes no difference at all on those architectures.
- */
-static inline size_t ntfs_copy_from_user_iovec(struct page **pages,
-               unsigned nr_pages, unsigned ofs, const struct iovec **iov,
-               size_t *iov_ofs, size_t bytes)
-{
-       struct page **last_page = pages + nr_pages;
-       char *addr;
-       size_t copied, len, total = 0;
-
-       do {
-               len = PAGE_CACHE_SIZE - ofs;
-               if (len > bytes)
-                       len = bytes;
-               addr = kmap_atomic(*pages);
-               copied = __ntfs_copy_from_user_iovec_inatomic(addr + ofs,
-                               *iov, *iov_ofs, len);
-               kunmap_atomic(addr);
-               if (unlikely(copied != len)) {
-                       /* Do it the slow way. */
-                       addr = kmap(*pages);
-                       copied = __ntfs_copy_from_user_iovec_inatomic(addr +
-                                       ofs, *iov, *iov_ofs, len);
-                       if (unlikely(copied != len))
-                               goto err_out;
-                       kunmap(*pages);
-               }
-               total += len;
-               ntfs_set_next_iovec(iov, iov_ofs, len);
-               bytes -= len;
-               if (!bytes)
-                       break;
-               ofs = 0;
-       } while (++pages < last_page);
-out:
-       return total;
-err_out:
-       BUG_ON(copied > len);
-       /* Zero the rest of the target like __copy_from_user(). */
-       memset(addr + ofs + copied, 0, len - copied);
-       kunmap(*pages);
-       total += copied;
-       ntfs_set_next_iovec(iov, iov_ofs, copied);
-       while (++pages < last_page) {
-               bytes -= len;
-               if (!bytes)
-                       break;
-               len = PAGE_CACHE_SIZE;
-               if (len > bytes)
-                       len = bytes;
-               zero_user(*pages, 0, len);
-       }
-       goto out;
-}
-
 static inline void ntfs_flush_dcache_pages(struct page **pages,
                unsigned nr_pages)
 {
@@ -1762,86 +1693,83 @@ err_out:
        return err;
 }
 
-static void ntfs_write_failed(struct address_space *mapping, loff_t to)
+/*
+ * Copy as much as we can into the pages and return the number of bytes which
+ * were successfully copied.  If a fault is encountered then clear the pages
+ * out to (ofs + bytes) and return the number of bytes which were copied.
+ */
+static size_t ntfs_copy_from_user_iter(struct page **pages, unsigned nr_pages,
+               unsigned ofs, struct iov_iter *i, size_t bytes)
 {
-       struct inode *inode = mapping->host;
+       struct page **last_page = pages + nr_pages;
+       size_t total = 0;
+       struct iov_iter data = *i;
+       unsigned len, copied;
 
-       if (to > inode->i_size) {
-               truncate_pagecache(inode, inode->i_size);
-               ntfs_truncate_vfs(inode);
-       }
+       do {
+               len = PAGE_CACHE_SIZE - ofs;
+               if (len > bytes)
+                       len = bytes;
+               copied = iov_iter_copy_from_user_atomic(*pages, &data, ofs,
+                               len);
+               total += copied;
+               bytes -= copied;
+               if (!bytes)
+                       break;
+               iov_iter_advance(&data, copied);
+               if (copied < len)
+                       goto err;
+               ofs = 0;
+       } while (++pages < last_page);
+out:
+       return total;
+err:
+       /* Zero the rest of the target like __copy_from_user(). */
+       len = PAGE_CACHE_SIZE - copied;
+       do {
+               if (len > bytes)
+                       len = bytes;
+               zero_user(*pages, copied, len);
+               bytes -= len;
+               copied = 0;
+               len = PAGE_CACHE_SIZE;
+       } while (++pages < last_page);
+       goto out;
 }
 
 /**
- * ntfs_file_buffered_write -
- *
- * Locking: The vfs is holding ->i_mutex on the inode.
+ * ntfs_perform_write - perform buffered write to a file
+ * @file:      file to write to
+ * @i:         iov_iter with data to write
+ * @pos:       byte offset in file at which to begin writing to
  */
-static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
-               const struct iovec *iov, unsigned long nr_segs,
-               loff_t pos, loff_t *ppos, size_t count)
+static ssize_t ntfs_perform_write(struct file *file, struct iov_iter *i,
+               loff_t pos)
 {
-       struct file *file = iocb->ki_filp;
        struct address_space *mapping = file->f_mapping;
        struct inode *vi = mapping->host;
        ntfs_inode *ni = NTFS_I(vi);
        ntfs_volume *vol = ni->vol;
        struct page *pages[NTFS_MAX_PAGES_PER_CLUSTER];
        struct page *cached_page = NULL;
-       char __user *buf = NULL;
-       s64 end, ll;
        VCN last_vcn;
        LCN lcn;
-       unsigned long flags;
-       size_t bytes, iov_ofs = 0;      /* Offset in the current iovec. */
-       ssize_t status, written;
+       size_t bytes;
+       ssize_t status, written = 0;
        unsigned nr_pages;
-       int err;
 
-       ntfs_debug("Entering for i_ino 0x%lx, attribute type 0x%x, "
-                       "pos 0x%llx, count 0x%lx.",
-                       vi->i_ino, (unsigned)le32_to_cpu(ni->type),
-                       (unsigned long long)pos, (unsigned long)count);
-       if (unlikely(!count))
-               return 0;
-       BUG_ON(NInoMstProtected(ni));
-       /*
-        * If the attribute is not an index root and it is encrypted or
-        * compressed, we cannot write to it yet.  Note we need to check for
-        * AT_INDEX_ALLOCATION since this is the type of both directory and
-        * index inodes.
-        */
-       if (ni->type != AT_INDEX_ALLOCATION) {
-               /* If file is encrypted, deny access, just like NT4. */
-               if (NInoEncrypted(ni)) {
-                       /*
-                        * Reminder for later: Encrypted files are _always_
-                        * non-resident so that the content can always be
-                        * encrypted.
-                        */
-                       ntfs_debug("Denying write access to encrypted file.");
-                       return -EACCES;
-               }
-               if (NInoCompressed(ni)) {
-                       /* Only unnamed $DATA attribute can be compressed. */
-                       BUG_ON(ni->type != AT_DATA);
-                       BUG_ON(ni->name_len);
-                       /*
-                        * Reminder for later: If resident, the data is not
-                        * actually compressed.  Only on the switch to non-
-                        * resident does compression kick in.  This is in
-                        * contrast to encrypted files (see above).
-                        */
-                       ntfs_error(vi->i_sb, "Writing to compressed files is "
-                                       "not implemented yet.  Sorry.");
-                       return -EOPNOTSUPP;
-               }
-       }
+       ntfs_debug("Entering for i_ino 0x%lx, attribute type 0x%x, pos "
+                       "0x%llx, count 0x%lx.", vi->i_ino,
+                       (unsigned)le32_to_cpu(ni->type),
+                       (unsigned long long)pos,
+                       (unsigned long)iov_iter_count(i));
        /*
         * If a previous ntfs_truncate() failed, repeat it and abort if it
         * fails again.
         */
        if (unlikely(NInoTruncateFailed(ni))) {
+               int err;
+
                inode_dio_wait(vi);
                err = ntfs_truncate(vi);
                if (err || NInoTruncateFailed(ni)) {
@@ -1855,81 +1783,6 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
                        return err;
                }
        }
-       /* The first byte after the write. */
-       end = pos + count;
-       /*
-        * If the write goes beyond the allocated size, extend the allocation
-        * to cover the whole of the write, rounded up to the nearest cluster.
-        */
-       read_lock_irqsave(&ni->size_lock, flags);
-       ll = ni->allocated_size;
-       read_unlock_irqrestore(&ni->size_lock, flags);
-       if (end > ll) {
-               /* Extend the allocation without changing the data size. */
-               ll = ntfs_attr_extend_allocation(ni, end, -1, pos);
-               if (likely(ll >= 0)) {
-                       BUG_ON(pos >= ll);
-                       /* If the extension was partial truncate the write. */
-                       if (end > ll) {
-                               ntfs_debug("Truncating write to inode 0x%lx, "
-                                               "attribute type 0x%x, because "
-                                               "the allocation was only "
-                                               "partially extended.",
-                                               vi->i_ino, (unsigned)
-                                               le32_to_cpu(ni->type));
-                               end = ll;
-                               count = ll - pos;
-                       }
-               } else {
-                       err = ll;
-                       read_lock_irqsave(&ni->size_lock, flags);
-                       ll = ni->allocated_size;
-                       read_unlock_irqrestore(&ni->size_lock, flags);
-                       /* Perform a partial write if possible or fail. */
-                       if (pos < ll) {
-                               ntfs_debug("Truncating write to inode 0x%lx, "
-                                               "attribute type 0x%x, because "
-                                               "extending the allocation "
-                                               "failed (error code %i).",
-                                               vi->i_ino, (unsigned)
-                                               le32_to_cpu(ni->type), err);
-                               end = ll;
-                               count = ll - pos;
-                       } else {
-                               ntfs_error(vol->sb, "Cannot perform write to "
-                                               "inode 0x%lx, attribute type "
-                                               "0x%x, because extending the "
-                                               "allocation failed (error "
-                                               "code %i).", vi->i_ino,
-                                               (unsigned)
-                                               le32_to_cpu(ni->type), err);
-                               return err;
-                       }
-               }
-       }
-       written = 0;
-       /*
-        * If the write starts beyond the initialized size, extend it up to the
-        * beginning of the write and initialize all non-sparse space between
-        * the old initialized size and the new one.  This automatically also
-        * increments the vfs inode->i_size to keep it above or equal to the
-        * initialized_size.
-        */
-       read_lock_irqsave(&ni->size_lock, flags);
-       ll = ni->initialized_size;
-       read_unlock_irqrestore(&ni->size_lock, flags);
-       if (pos > ll) {
-               err = ntfs_attr_extend_initialized(ni, pos);
-               if (err < 0) {
-                       ntfs_error(vol->sb, "Cannot perform write to inode "
-                                       "0x%lx, attribute type 0x%x, because "
-                                       "extending the initialized size "
-                                       "failed (error code %i).", vi->i_ino,
-                                       (unsigned)le32_to_cpu(ni->type), err);
-                       status = err;
-                       goto err_out;
-               }
-       }
        /*
         * Determine the number of pages per cluster for non-resident
         * attributes.
@@ -1937,10 +1790,7 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
        nr_pages = 1;
        if (vol->cluster_size > PAGE_CACHE_SIZE && NInoNonResident(ni))
                nr_pages = vol->cluster_size >> PAGE_CACHE_SHIFT;
-       /* Finally, perform the actual write. */
        last_vcn = -1;
-       if (likely(nr_segs == 1))
-               buf = iov->iov_base;
        do {
                VCN vcn;
                pgoff_t idx, start_idx;
@@ -1965,10 +1815,10 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
                                                vol->cluster_size_bits, false);
                                up_read(&ni->runlist.lock);
                                if (unlikely(lcn < LCN_HOLE)) {
-                                       status = -EIO;
                                        if (lcn == LCN_ENOMEM)
                                                status = -ENOMEM;
-                                       else
+                                       else {
+                                               status = -EIO;
                                                ntfs_error(vol->sb, "Cannot "
                                                        "perform write to "
                                                        "inode 0x%lx, "
@@ -1977,6 +1827,7 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
                                                        "is corrupt.",
                                                        vi->i_ino, (unsigned)
                                                        le32_to_cpu(ni->type));
+                                       }
                                        break;
                                }
                                if (lcn == LCN_HOLE) {
@@ -1989,8 +1840,9 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
                                }
                        }
                }
-               if (bytes > count)
-                       bytes = count;
+               if (bytes > iov_iter_count(i))
+                       bytes = iov_iter_count(i);
+again:
                /*
                 * Bring in the user page(s) that we will copy from _first_.
                 * Otherwise there is a nasty deadlock on copying from the same
@@ -1999,10 +1851,10 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
                 * pages being swapped out between us bringing them into memory
                 * and doing the actual copying.
                 */
-               if (likely(nr_segs == 1))
-                       ntfs_fault_in_pages_readable(buf, bytes);
-               else
-                       ntfs_fault_in_pages_readable_iovec(iov, iov_ofs, bytes);
+               if (unlikely(iov_iter_fault_in_multipages_readable(i, bytes))) {
+                       status = -EFAULT;
+                       break;
+               }
                /* Get and lock @do_pages starting at index @start_idx. */
                status = __ntfs_grab_cache_pages(mapping, start_idx, do_pages,
                                pages, &cached_page);
@@ -2018,56 +1870,57 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
                        status = ntfs_prepare_pages_for_non_resident_write(
                                        pages, do_pages, pos, bytes);
                        if (unlikely(status)) {
-                               loff_t i_size;
-
                                do {
                                        unlock_page(pages[--do_pages]);
                                        page_cache_release(pages[do_pages]);
                                } while (do_pages);
-                               /*
-                                * The write preparation may have instantiated
-                                * allocated space outside i_size.  Trim this
-                                * off again.  We can ignore any errors in this
-                                * case as we will just be waisting a bit of
-                                * allocated space, which is not a disaster.
-                                */
-                               i_size = i_size_read(vi);
-                               if (pos + bytes > i_size) {
-                                       ntfs_write_failed(mapping, pos + bytes);
-                               }
                                break;
                        }
                }
                u = (pos >> PAGE_CACHE_SHIFT) - pages[0]->index;
-               if (likely(nr_segs == 1)) {
-                       copied = ntfs_copy_from_user(pages + u, do_pages - u,
-                                       ofs, buf, bytes);
-                       buf += copied;
-               } else
-                       copied = ntfs_copy_from_user_iovec(pages + u,
-                                       do_pages - u, ofs, &iov, &iov_ofs,
-                                       bytes);
+               copied = ntfs_copy_from_user_iter(pages + u, do_pages - u, ofs,
+                                       i, bytes);
                ntfs_flush_dcache_pages(pages + u, do_pages - u);
-               status = ntfs_commit_pages_after_write(pages, do_pages, pos,
-                               bytes);
-               if (likely(!status)) {
-                       written += copied;
-                       count -= copied;
-                       pos += copied;
-                       if (unlikely(copied != bytes))
-                               status = -EFAULT;
+               status = 0;
+               if (likely(copied == bytes)) {
+                       status = ntfs_commit_pages_after_write(pages, do_pages,
+                                       pos, bytes);
+                       if (!status)
+                               status = bytes;
                }
                do {
                        unlock_page(pages[--do_pages]);
                        page_cache_release(pages[do_pages]);
                } while (do_pages);
-               if (unlikely(status))
+               if (unlikely(status < 0))
                        break;
-               balance_dirty_pages_ratelimited(mapping);
+               copied = status;
                cond_resched();
-       } while (count);
-err_out:
-       *ppos = pos;
+               if (unlikely(!copied)) {
+                       size_t sc;
+
+                       /*
+                        * We failed to copy anything.  Fall back to single
+                        * segment length write.
+                        *
+                        * This is needed to avoid possible livelock in the
+                        * case that all segments in the iov cannot be copied
+                        * at once without a pagefault.
+                        */
+                       sc = iov_iter_single_seg_count(i);
+                       if (bytes > sc)
+                               bytes = sc;
+                       goto again;
+               }
+               iov_iter_advance(i, copied);
+               pos += copied;
+               written += copied;
+               balance_dirty_pages_ratelimited(mapping);
+               if (fatal_signal_pending(current)) {
+                       status = -EINTR;
+                       break;
+               }
+       } while (iov_iter_count(i));
        if (cached_page)
                page_cache_release(cached_page);
        ntfs_debug("Done.  Returning %s (written 0x%lx, status %li).",
@@ -2077,59 +1930,56 @@ err_out:
 }
 
 /**
- * ntfs_file_aio_write_nolock -
+ * ntfs_file_write_iter_nolock - write data to a file
+ * @iocb:      IO state structure (file, offset, etc.)
+ * @from:      iov_iter with data to write
+ *
+ * Basically the same as __generic_file_write_iter() except that it ends
+ * up calling ntfs_perform_write() instead of generic_perform_write() and that
+ * O_DIRECT is not implemented.
  */
-static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,
-               const struct iovec *iov, unsigned long nr_segs, loff_t *ppos)
+static ssize_t ntfs_file_write_iter_nolock(struct kiocb *iocb,
+               struct iov_iter *from)
 {
        struct file *file = iocb->ki_filp;
-       struct address_space *mapping = file->f_mapping;
-       struct inode *inode = mapping->host;
-       loff_t pos;
-       size_t count;           /* after file limit checks */
-       ssize_t written, err;
+       loff_t pos = iocb->ki_pos;
+       ssize_t written = 0;
+       ssize_t err;
+       size_t count = iov_iter_count(from);
 
-       count = iov_length(iov, nr_segs);
-       pos = *ppos;
-       /* We can write back this queue in page reclaim. */
-       current->backing_dev_info = inode_to_bdi(inode);
-       written = 0;
-       err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
-       if (err)
-               goto out;
-       if (!count)
-               goto out;
-       err = file_remove_suid(file);
-       if (err)
-               goto out;
-       err = file_update_time(file);
-       if (err)
-               goto out;
-       written = ntfs_file_buffered_write(iocb, iov, nr_segs, pos, ppos,
-                       count);
-out:
+       err = ntfs_prepare_file_for_write(file, &pos, &count);
+       if (count && !err) {
+               iov_iter_truncate(from, count);
+               written = ntfs_perform_write(file, from, pos);
+               if (likely(written >= 0))
+                       iocb->ki_pos = pos + written;
+       }
        current->backing_dev_info = NULL;
        return written ? written : err;
 }
 
 /**
- * ntfs_file_aio_write -
+ * ntfs_file_write_iter - simple wrapper for ntfs_file_write_iter_nolock()
+ * @iocb:      IO state structure
+ * @from:      iov_iter with data to write
+ *
+ * Basically the same as generic_file_write_iter() except that it ends up
+ * calling ntfs_file_write_iter_nolock() instead of
+ * __generic_file_write_iter().
  */
-static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
-               unsigned long nr_segs, loff_t pos)
+static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
        struct file *file = iocb->ki_filp;
-       struct address_space *mapping = file->f_mapping;
-       struct inode *inode = mapping->host;
+       struct inode *vi = file_inode(file);
        ssize_t ret;
 
-       BUG_ON(iocb->ki_pos != pos);
-
-       mutex_lock(&inode->i_mutex);
-       ret = ntfs_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos);
-       mutex_unlock(&inode->i_mutex);
+       mutex_lock(&vi->i_mutex);
+       ret = ntfs_file_write_iter_nolock(iocb, from);
+       mutex_unlock(&vi->i_mutex);
        if (ret > 0) {
-               int err = generic_write_sync(file, iocb->ki_pos - ret, ret);
+               ssize_t err;
+
+               err = generic_write_sync(file, iocb->ki_pos - ret, ret);
                if (err < 0)
                        ret = err;
        }
@@ -2197,37 +2047,17 @@ static int ntfs_file_fsync(struct file *filp, loff_t start, loff_t end,
 #endif /* NTFS_RW */
 
 const struct file_operations ntfs_file_ops = {
-       .llseek         = generic_file_llseek,   /* Seek inside file. */
-       .read           = new_sync_read,         /* Read from file. */
-       .read_iter      = generic_file_read_iter, /* Async read from file. */
+       .llseek         = generic_file_llseek,
+       .read           = new_sync_read,
+       .read_iter      = generic_file_read_iter,
 #ifdef NTFS_RW
-       .write          = do_sync_write,         /* Write to file. */
-       .aio_write      = ntfs_file_aio_write,   /* Async write to file. */
-       /*.release      = ,*/                    /* Last file is closed.  See
-                                                   fs/ext2/file.c::
-                                                   ext2_release_file() for
-                                                   how to use this to discard
-                                                   preallocated space for
-                                                   write opened files. */
-       .fsync          = ntfs_file_fsync,       /* Sync a file to disk. */
-       /*.aio_fsync    = ,*/                    /* Sync all outstanding async
-                                                   i/o operations on a
-                                                   kiocb. */
+       .write          = new_sync_write,
+       .write_iter     = ntfs_file_write_iter,
+       .fsync          = ntfs_file_fsync,
 #endif /* NTFS_RW */
-       /*.ioctl        = ,*/                    /* Perform function on the
-                                                   mounted filesystem. */
-       .mmap           = generic_file_mmap,     /* Mmap file. */
-       .open           = ntfs_file_open,        /* Open file. */
-       .splice_read    = generic_file_splice_read /* Zero-copy data send with
-                                                   the data source being on
-                                                   the ntfs partition.  We do
-                                                   not need to care about the
-                                                   data destination. */
-       /*.sendpage     = ,*/                    /* Zero-copy data send with
-                                                   the data destination being
-                                                   on the ntfs partition.  We
-                                                   do not need to care about
-                                                   the data source. */
+       .mmap           = generic_file_mmap,
+       .open           = ntfs_file_open,
+       .splice_read    = generic_file_splice_read,
 };
 
 const struct inode_operations ntfs_file_inode_ops = {
index 898b9949d36357a8b7998600f3fdbacaa498d08f..1d0c21df0d805cd73248afd42dc05c1108c49700 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/quotaops.h>
 #include <linux/slab.h>
 #include <linux/log2.h>
-#include <linux/aio.h>
 
 #include "aops.h"
 #include "attrib.h"
index 044158bd22be1c307aa046d9863a0684dfde9824..2d7f76e52c379cf04b7f820c610c171e491d4830 100644 (file)
@@ -3370,7 +3370,7 @@ static int ocfs2_merge_rec_right(struct ocfs2_path *left_path,
                ret = ocfs2_get_right_path(et, left_path, &right_path);
                if (ret) {
                        mlog_errno(ret);
-                       goto out;
+                       return ret;
                }
 
                right_el = path_leaf_el(right_path);
@@ -3453,8 +3453,7 @@ static int ocfs2_merge_rec_right(struct ocfs2_path *left_path,
                                           subtree_index);
        }
 out:
-       if (right_path)
-               ocfs2_free_path(right_path);
+       ocfs2_free_path(right_path);
        return ret;
 }
 
@@ -3536,7 +3535,7 @@ static int ocfs2_merge_rec_left(struct ocfs2_path *right_path,
                ret = ocfs2_get_left_path(et, right_path, &left_path);
                if (ret) {
                        mlog_errno(ret);
-                       goto out;
+                       return ret;
                }
 
                left_el = path_leaf_el(left_path);
@@ -3647,8 +3646,7 @@ static int ocfs2_merge_rec_left(struct ocfs2_path *right_path,
                                                   right_path, subtree_index);
        }
 out:
-       if (left_path)
-               ocfs2_free_path(left_path);
+       ocfs2_free_path(left_path);
        return ret;
 }
 
@@ -4334,17 +4332,17 @@ ocfs2_figure_merge_contig_type(struct ocfs2_extent_tree *et,
        } else if (path->p_tree_depth > 0) {
                status = ocfs2_find_cpos_for_left_leaf(sb, path, &left_cpos);
                if (status)
-                       goto out;
+                       goto exit;
 
                if (left_cpos != 0) {
                        left_path = ocfs2_new_path_from_path(path);
                        if (!left_path)
-                               goto out;
+                               goto exit;
 
                        status = ocfs2_find_path(et->et_ci, left_path,
                                                 left_cpos);
                        if (status)
-                               goto out;
+                               goto free_left_path;
 
                        new_el = path_leaf_el(left_path);
 
@@ -4361,7 +4359,7 @@ ocfs2_figure_merge_contig_type(struct ocfs2_extent_tree *et,
                                            le16_to_cpu(new_el->l_next_free_rec),
                                            le16_to_cpu(new_el->l_count));
                                status = -EINVAL;
-                               goto out;
+                               goto free_left_path;
                        }
                        rec = &new_el->l_recs[
                                le16_to_cpu(new_el->l_next_free_rec) - 1];
@@ -4388,18 +4386,18 @@ ocfs2_figure_merge_contig_type(struct ocfs2_extent_tree *et,
                 path->p_tree_depth > 0) {
                status = ocfs2_find_cpos_for_right_leaf(sb, path, &right_cpos);
                if (status)
-                       goto out;
+                       goto free_left_path;
 
                if (right_cpos == 0)
-                       goto out;
+                       goto free_left_path;
 
                right_path = ocfs2_new_path_from_path(path);
                if (!right_path)
-                       goto out;
+                       goto free_left_path;
 
                status = ocfs2_find_path(et->et_ci, right_path, right_cpos);
                if (status)
-                       goto out;
+                       goto free_right_path;
 
                new_el = path_leaf_el(right_path);
                rec = &new_el->l_recs[0];
@@ -4413,7 +4411,7 @@ ocfs2_figure_merge_contig_type(struct ocfs2_extent_tree *et,
                                            (unsigned long long)le64_to_cpu(eb->h_blkno),
                                            le16_to_cpu(new_el->l_next_free_rec));
                                status = -EINVAL;
-                               goto out;
+                               goto free_right_path;
                        }
                        rec = &new_el->l_recs[1];
                }
@@ -4430,12 +4428,11 @@ ocfs2_figure_merge_contig_type(struct ocfs2_extent_tree *et,
                        ret = contig_type;
        }
 
-out:
-       if (left_path)
-               ocfs2_free_path(left_path);
-       if (right_path)
-               ocfs2_free_path(right_path);
-
+free_right_path:
+       ocfs2_free_path(right_path);
+free_left_path:
+       ocfs2_free_path(left_path);
+exit:
        return ret;
 }
 
@@ -6858,13 +6855,13 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
                if (pages == NULL) {
                        ret = -ENOMEM;
                        mlog_errno(ret);
-                       goto out;
+                       return ret;
                }
 
                ret = ocfs2_reserve_clusters(osb, 1, &data_ac);
                if (ret) {
                        mlog_errno(ret);
-                       goto out;
+                       goto free_pages;
                }
        }
 
@@ -6996,9 +6993,8 @@ out_commit:
 out:
        if (data_ac)
                ocfs2_free_alloc_context(data_ac);
-       if (pages)
-               kfree(pages);
-
+free_pages:
+       kfree(pages);
        return ret;
 }
 
index 44db1808cdb598df6b91548410b3634480c06c31..8d2bc840c288743e97df31fe99bce0b00e34a1b6 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/mpage.h>
 #include <linux/quotaops.h>
 #include <linux/blkdev.h>
+#include <linux/uio.h>
 
 #include <cluster/masklog.h>
 
@@ -663,6 +664,117 @@ static int ocfs2_is_overwrite(struct ocfs2_super *osb,
        return 0;
 }
 
+static int ocfs2_direct_IO_zero_extend(struct ocfs2_super *osb,
+               struct inode *inode, loff_t offset,
+               u64 zero_len, int cluster_align)
+{
+       u32 p_cpos = 0;
+       u32 v_cpos = ocfs2_bytes_to_clusters(osb->sb, i_size_read(inode));
+       unsigned int num_clusters = 0;
+       unsigned int ext_flags = 0;
+       int ret = 0;
+
+       if (offset <= i_size_read(inode) || cluster_align)
+               return 0;
+
+       ret = ocfs2_get_clusters(inode, v_cpos, &p_cpos, &num_clusters,
+                       &ext_flags);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       if (p_cpos && !(ext_flags & OCFS2_EXT_UNWRITTEN)) {
+               u64 s = i_size_read(inode);
+               sector_t sector = (p_cpos << (osb->s_clustersize_bits - 9)) +
+                       (do_div(s, osb->s_clustersize) >> 9);
+
+               ret = blkdev_issue_zeroout(osb->sb->s_bdev, sector,
+                               zero_len >> 9, GFP_NOFS, false);
+               if (ret < 0)
+                       mlog_errno(ret);
+       }
+
+       return ret;
+}
+
+static int ocfs2_direct_IO_extend_no_holes(struct ocfs2_super *osb,
+               struct inode *inode, loff_t offset)
+{
+       u64 zero_start, zero_len, total_zero_len;
+       u32 p_cpos = 0, clusters_to_add;
+       u32 v_cpos = ocfs2_bytes_to_clusters(osb->sb, i_size_read(inode));
+       unsigned int num_clusters = 0;
+       unsigned int ext_flags = 0;
+       u32 size_div, offset_div;
+       int ret = 0;
+
+       {
+               u64 o = offset;
+               u64 s = i_size_read(inode);
+
+               offset_div = do_div(o, osb->s_clustersize);
+               size_div = do_div(s, osb->s_clustersize);
+       }
+
+       if (offset <= i_size_read(inode))
+               return 0;
+
+       clusters_to_add = ocfs2_bytes_to_clusters(inode->i_sb, offset) -
+               ocfs2_bytes_to_clusters(inode->i_sb, i_size_read(inode));
+       total_zero_len = offset - i_size_read(inode);
+       if (clusters_to_add)
+               total_zero_len -= offset_div;
+
+       /* Allocate clusters to fill out holes, and this is only needed
+        * when we add more than one clusters. Otherwise the cluster will
+        * be allocated during direct IO */
+       if (clusters_to_add > 1) {
+               ret = ocfs2_extend_allocation(inode,
+                               OCFS2_I(inode)->ip_clusters,
+                               clusters_to_add - 1, 0);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       while (total_zero_len) {
+               ret = ocfs2_get_clusters(inode, v_cpos, &p_cpos, &num_clusters,
+                               &ext_flags);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               zero_start = ocfs2_clusters_to_bytes(osb->sb, p_cpos) +
+                       size_div;
+               zero_len = ocfs2_clusters_to_bytes(osb->sb, num_clusters) -
+                       size_div;
+               zero_len = min(total_zero_len, zero_len);
+
+               if (p_cpos && !(ext_flags & OCFS2_EXT_UNWRITTEN)) {
+                       ret = blkdev_issue_zeroout(osb->sb->s_bdev,
+                                       zero_start >> 9, zero_len >> 9,
+                                       GFP_NOFS, false);
+                       if (ret < 0) {
+                               mlog_errno(ret);
+                               goto out;
+                       }
+               }
+
+               total_zero_len -= zero_len;
+               v_cpos += ocfs2_bytes_to_clusters(osb->sb, zero_len + size_div);
+
+               /* Only at first iteration can be cluster not aligned.
+                * So set size_div to 0 for the rest */
+               size_div = 0;
+       }
+
+out:
+       return ret;
+}
+
 static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb,
                struct iov_iter *iter,
                loff_t offset)
@@ -677,8 +789,8 @@ static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb,
        struct buffer_head *di_bh = NULL;
        size_t count = iter->count;
        journal_t *journal = osb->journal->j_journal;
-       u32 zero_len;
-       int cluster_align;
+       u64 zero_len_head, zero_len_tail;
+       int cluster_align_head, cluster_align_tail;
        loff_t final_size = offset + count;
        int append_write = offset >= i_size_read(inode) ? 1 : 0;
        unsigned int num_clusters = 0;
@@ -686,9 +798,16 @@ static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb,
 
        {
                u64 o = offset;
+               u64 s = i_size_read(inode);
+
+               zero_len_head = do_div(o, 1 << osb->s_clustersize_bits);
+               cluster_align_head = !zero_len_head;
 
-               zero_len = do_div(o, 1 << osb->s_clustersize_bits);
-               cluster_align = !zero_len;
+               zero_len_tail = osb->s_clustersize -
+                       do_div(s, osb->s_clustersize);
+               if ((offset - i_size_read(inode)) < zero_len_tail)
+                       zero_len_tail = offset - i_size_read(inode);
+               cluster_align_tail = !zero_len_tail;
        }
 
        /*
@@ -706,21 +825,23 @@ static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb,
        }
 
        if (append_write) {
-               ret = ocfs2_inode_lock(inode, &di_bh, 1);
+               ret = ocfs2_inode_lock(inode, NULL, 1);
                if (ret < 0) {
                        mlog_errno(ret);
                        goto clean_orphan;
                }
 
+               /* zeroing out the previously allocated cluster tail
+                * that but not zeroed */
                if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)))
-                       ret = ocfs2_zero_extend(inode, di_bh, offset);
+                       ret = ocfs2_direct_IO_zero_extend(osb, inode, offset,
+                                       zero_len_tail, cluster_align_tail);
                else
-                       ret = ocfs2_extend_no_holes(inode, di_bh, offset,
+                       ret = ocfs2_direct_IO_extend_no_holes(osb, inode,
                                        offset);
                if (ret < 0) {
                        mlog_errno(ret);
                        ocfs2_inode_unlock(inode, 1);
-                       brelse(di_bh);
                        goto clean_orphan;
                }
 
@@ -728,13 +849,10 @@ static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb,
                if (is_overwrite < 0) {
                        mlog_errno(is_overwrite);
                        ocfs2_inode_unlock(inode, 1);
-                       brelse(di_bh);
                        goto clean_orphan;
                }
 
                ocfs2_inode_unlock(inode, 1);
-               brelse(di_bh);
-               di_bh = NULL;
        }
 
        written = __blockdev_direct_IO(WRITE, iocb, inode, inode->i_sb->s_bdev,
@@ -771,15 +889,23 @@ static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb,
                        if (ret < 0)
                                mlog_errno(ret);
                }
-       } else if (written < 0 && append_write && !is_overwrite &&
-                       !cluster_align) {
+       } else if (written > 0 && append_write && !is_overwrite &&
+                       !cluster_align_head) {
+               /* zeroing out the allocated cluster head */
                u32 p_cpos = 0;
                u32 v_cpos = ocfs2_bytes_to_clusters(osb->sb, offset);
 
+               ret = ocfs2_inode_lock(inode, NULL, 0);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto clean_orphan;
+               }
+
                ret = ocfs2_get_clusters(inode, v_cpos, &p_cpos,
                                &num_clusters, &ext_flags);
                if (ret < 0) {
                        mlog_errno(ret);
+                       ocfs2_inode_unlock(inode, 0);
                        goto clean_orphan;
                }
 
@@ -787,9 +913,11 @@ static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb,
 
                ret = blkdev_issue_zeroout(osb->sb->s_bdev,
                                p_cpos << (osb->s_clustersize_bits - 9),
-                               zero_len >> 9, GFP_KERNEL, false);
+                               zero_len_head >> 9, GFP_NOFS, false);
                if (ret < 0)
                        mlog_errno(ret);
+
+               ocfs2_inode_unlock(inode, 0);
        }
 
 clean_orphan:
index 6cae155d54df0d68be4f90f4754d15c30302159c..dd59599b022d5ab26dffd82807d048cac170a154 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef OCFS2_AOPS_H
 #define OCFS2_AOPS_H
 
-#include <linux/aio.h>
+#include <linux/fs.h>
 
 handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
                                                         struct page *page,
index 16eff45727eeaa055852c3c50c2febac5d647006..8e19b9d7aba8f31ba528cd0571706718cb52318f 100644 (file)
@@ -1312,7 +1312,9 @@ static int o2hb_debug_init(void)
        int ret = -ENOMEM;
 
        o2hb_debug_dir = debugfs_create_dir(O2HB_DEBUG_DIR, NULL);
-       if (!o2hb_debug_dir) {
+       if (IS_ERR_OR_NULL(o2hb_debug_dir)) {
+               ret = o2hb_debug_dir ?
+                       PTR_ERR(o2hb_debug_dir) : -ENOMEM;
                mlog_errno(ret);
                goto bail;
        }
@@ -1325,7 +1327,9 @@ static int o2hb_debug_init(void)
                                                 sizeof(o2hb_live_node_bitmap),
                                                 O2NM_MAX_NODES,
                                                 o2hb_live_node_bitmap);
-       if (!o2hb_debug_livenodes) {
+       if (IS_ERR_OR_NULL(o2hb_debug_livenodes)) {
+               ret = o2hb_debug_livenodes ?
+                       PTR_ERR(o2hb_debug_livenodes) : -ENOMEM;
                mlog_errno(ret);
                goto bail;
        }
@@ -1338,7 +1342,9 @@ static int o2hb_debug_init(void)
                                                   sizeof(o2hb_live_region_bitmap),
                                                   O2NM_MAX_REGIONS,
                                                   o2hb_live_region_bitmap);
-       if (!o2hb_debug_liveregions) {
+       if (IS_ERR_OR_NULL(o2hb_debug_liveregions)) {
+               ret = o2hb_debug_liveregions ?
+                       PTR_ERR(o2hb_debug_liveregions) : -ENOMEM;
                mlog_errno(ret);
                goto bail;
        }
@@ -1352,7 +1358,9 @@ static int o2hb_debug_init(void)
                                          sizeof(o2hb_quorum_region_bitmap),
                                          O2NM_MAX_REGIONS,
                                          o2hb_quorum_region_bitmap);
-       if (!o2hb_debug_quorumregions) {
+       if (IS_ERR_OR_NULL(o2hb_debug_quorumregions)) {
+               ret = o2hb_debug_quorumregions ?
+                       PTR_ERR(o2hb_debug_quorumregions) : -ENOMEM;
                mlog_errno(ret);
                goto bail;
        }
@@ -1366,7 +1374,9 @@ static int o2hb_debug_init(void)
                                          sizeof(o2hb_failed_region_bitmap),
                                          O2NM_MAX_REGIONS,
                                          o2hb_failed_region_bitmap);
-       if (!o2hb_debug_failedregions) {
+       if (IS_ERR_OR_NULL(o2hb_debug_failedregions)) {
+               ret = o2hb_debug_failedregions ?
+                       PTR_ERR(o2hb_debug_failedregions) : -ENOMEM;
                mlog_errno(ret);
                goto bail;
        }
@@ -2000,7 +2010,8 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
 
        reg->hr_debug_dir =
                debugfs_create_dir(config_item_name(&reg->hr_item), dir);
-       if (!reg->hr_debug_dir) {
+       if (IS_ERR_OR_NULL(reg->hr_debug_dir)) {
+               ret = reg->hr_debug_dir ? PTR_ERR(reg->hr_debug_dir) : -ENOMEM;
                mlog_errno(ret);
                goto bail;
        }
@@ -2013,7 +2024,9 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
                                          O2HB_DB_TYPE_REGION_LIVENODES,
                                          sizeof(reg->hr_live_node_bitmap),
                                          O2NM_MAX_NODES, reg);
-       if (!reg->hr_debug_livenodes) {
+       if (IS_ERR_OR_NULL(reg->hr_debug_livenodes)) {
+               ret = reg->hr_debug_livenodes ?
+                       PTR_ERR(reg->hr_debug_livenodes) : -ENOMEM;
                mlog_errno(ret);
                goto bail;
        }
@@ -2025,7 +2038,9 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
                                          sizeof(*(reg->hr_db_regnum)),
                                          O2HB_DB_TYPE_REGION_NUMBER,
                                          0, O2NM_MAX_NODES, reg);
-       if (!reg->hr_debug_regnum) {
+       if (IS_ERR_OR_NULL(reg->hr_debug_regnum)) {
+               ret = reg->hr_debug_regnum ?
+                       PTR_ERR(reg->hr_debug_regnum) : -ENOMEM;
                mlog_errno(ret);
                goto bail;
        }
@@ -2037,7 +2052,9 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
                                          sizeof(*(reg->hr_db_elapsed_time)),
                                          O2HB_DB_TYPE_REGION_ELAPSED_TIME,
                                          0, 0, reg);
-       if (!reg->hr_debug_elapsed_time) {
+       if (IS_ERR_OR_NULL(reg->hr_debug_elapsed_time)) {
+               ret = reg->hr_debug_elapsed_time ?
+                       PTR_ERR(reg->hr_debug_elapsed_time) : -ENOMEM;
                mlog_errno(ret);
                goto bail;
        }
@@ -2049,13 +2066,16 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
                                          sizeof(*(reg->hr_db_pinned)),
                                          O2HB_DB_TYPE_REGION_PINNED,
                                          0, 0, reg);
-       if (!reg->hr_debug_pinned) {
+       if (IS_ERR_OR_NULL(reg->hr_debug_pinned)) {
+               ret = reg->hr_debug_pinned ?
+                       PTR_ERR(reg->hr_debug_pinned) : -ENOMEM;
                mlog_errno(ret);
                goto bail;
        }
 
-       ret = 0;
+       return 0;
 bail:
+       debugfs_remove_recursive(reg->hr_debug_dir);
        return ret;
 }
 
index 2260fb9e650831fef349ce2c6f6dcd878ffa45d2..7fdc25a4d8c0e76af574c505d83eb86f1f452e31 100644 (file)
@@ -196,13 +196,14 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits;
        }                                                               \
 } while (0)
 
-#define mlog_errno(st) do {                                            \
+#define mlog_errno(st) ({                                              \
        int _st = (st);                                                 \
        if (_st != -ERESTARTSYS && _st != -EINTR &&                     \
            _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC &&              \
            _st != -EDQUOT)                                             \
                mlog(ML_ERROR, "status = %lld\n", (long long)_st);      \
-} while (0)
+       _st;                                                            \
+})
 
 #define mlog_bug_on_msg(cond, fmt, args...) do {                       \
        if (cond) {                                                     \
index b08050bd3f2ef81a2c2f053042ac7e9e763e3718..ccd4dcfc36457c211762e4dc7348949774c7df5b 100644 (file)
@@ -18,7 +18,7 @@
  *
  *   linux/fs/minix/dir.c
  *
- *   Copyright (C) 1991, 1992 Linux Torvalds
+ *   Copyright (C) 1991, 1992 Linus Torvalds
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
@@ -2047,22 +2047,19 @@ int ocfs2_check_dir_for_entry(struct inode *dir,
                              const char *name,
                              int namelen)
 {
-       int ret;
+       int ret = 0;
        struct ocfs2_dir_lookup_result lookup = { NULL, };
 
        trace_ocfs2_check_dir_for_entry(
                (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name);
 
-       ret = -EEXIST;
-       if (ocfs2_find_entry(name, namelen, dir, &lookup) == 0)
-               goto bail;
+       if (ocfs2_find_entry(name, namelen, dir, &lookup) == 0) {
+               ret = -EEXIST;
+               mlog_errno(ret);
+       }
 
-       ret = 0;
-bail:
        ocfs2_free_dir_lookup_result(&lookup);
 
-       if (ret)
-               mlog_errno(ret);
        return ret;
 }
 
index 11849a44dc5a90d7a9a0b7eb389d928a7e9345a7..956edf67be20ba6b1711f6aa4c915aad9cead0a7 100644 (file)
@@ -1391,6 +1391,11 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb,
        int noqueue_attempted = 0;
        int dlm_locked = 0;
 
+       if (!(lockres->l_flags & OCFS2_LOCK_INITIALIZED)) {
+               mlog_errno(-EINVAL);
+               return -EINVAL;
+       }
+
        ocfs2_init_mask_waiter(&mw);
 
        if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB)
@@ -2954,7 +2959,7 @@ static int ocfs2_dlm_init_debug(struct ocfs2_super *osb)
                                                         osb->osb_debug_root,
                                                         osb,
                                                         &ocfs2_dlm_debug_fops);
-       if (!dlm_debug->d_locking_state) {
+       if (IS_ERR_OR_NULL(dlm_debug->d_locking_state)) {
                ret = -EINVAL;
                mlog(ML_ERROR,
                     "Unable to create locking state debugfs file.\n");
index 29651167190dd15032a5aaa71d2fe066a7bbab97..540dc4bdd042a5035f4a05e7fed0bc06548a1244 100644 (file)
@@ -82,7 +82,6 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb,
        }
 
        status = ocfs2_test_inode_bit(osb, blkno, &set);
-       trace_ocfs2_get_dentry_test_bit(status, set);
        if (status < 0) {
                if (status == -EINVAL) {
                        /*
@@ -96,6 +95,7 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb,
                goto unlock_nfs_sync;
        }
 
+       trace_ocfs2_get_dentry_test_bit(status, set);
        /* If the inode allocator bit is clear, this inode must be stale */
        if (!set) {
                status = -ESTALE;
index 46e0d4e857c7f493f512196603d3725ca8d3dfaa..91f03ce981087c59bb6d3921c25b74926638746d 100644 (file)
@@ -2280,7 +2280,7 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
                file->f_path.dentry->d_name.name,
                (unsigned int)from->nr_segs);   /* GRRRRR */
 
-       if (iocb->ki_nbytes == 0)
+       if (count == 0)
                return 0;
 
        appending = file->f_flags & O_APPEND ? 1 : 0;
@@ -2330,8 +2330,7 @@ relock:
        }
 
        can_do_direct = direct_io;
-       ret = ocfs2_prepare_inode_for_write(file, ppos,
-                                           iocb->ki_nbytes, appending,
+       ret = ocfs2_prepare_inode_for_write(file, ppos, count, appending,
                                            &can_do_direct, &has_refcount);
        if (ret < 0) {
                mlog_errno(ret);
@@ -2339,8 +2338,7 @@ relock:
        }
 
        if (direct_io && !is_sync_kiocb(iocb))
-               unaligned_dio = ocfs2_is_io_unaligned(inode, iocb->ki_nbytes,
-                                                     *ppos);
+               unaligned_dio = ocfs2_is_io_unaligned(inode, count, *ppos);
 
        /*
         * We can't complete the direct I/O as requested, fall back to
@@ -2394,7 +2392,6 @@ relock:
                /*
                 * for completing the rest of the request.
                 */
-               *ppos += written;
                count -= written;
                written_buffered = generic_perform_write(file, from, *ppos);
                /*
@@ -2409,7 +2406,6 @@ relock:
                        goto out_dio;
                }
 
-               iocb->ki_pos = *ppos + written_buffered;
                /* We need to ensure that the page cache pages are written to
                 * disk and invalidated to preserve the expected O_DIRECT
                 * semantics.
@@ -2418,6 +2414,7 @@ relock:
                ret = filemap_write_and_wait_range(file->f_mapping, *ppos,
                                endbyte);
                if (ret == 0) {
+                       iocb->ki_pos = *ppos + written_buffered;
                        written += written_buffered;
                        invalidate_mapping_pages(mapping,
                                        *ppos >> PAGE_CACHE_SHIFT,
@@ -2440,10 +2437,14 @@ out_dio:
        /* buffered aio wouldn't have proper lock coverage today */
        BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
 
+       if (unlikely(written <= 0))
+               goto no_sync;
+
        if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) ||
            ((file->f_flags & O_DIRECT) && !direct_io)) {
-               ret = filemap_fdatawrite_range(file->f_mapping, *ppos,
-                                              *ppos + count - 1);
+               ret = filemap_fdatawrite_range(file->f_mapping,
+                                              iocb->ki_pos - written,
+                                              iocb->ki_pos - 1);
                if (ret < 0)
                        written = ret;
 
@@ -2454,10 +2455,12 @@ out_dio:
                }
 
                if (!ret)
-                       ret = filemap_fdatawait_range(file->f_mapping, *ppos,
-                                                     *ppos + count - 1);
+                       ret = filemap_fdatawait_range(file->f_mapping,
+                                                     iocb->ki_pos - written,
+                                                     iocb->ki_pos - 1);
        }
 
+no_sync:
        /*
         * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io
         * function pointer which is called when o_direct io completes so that
index 3025c0da6b8abd6358a60581087a257dd4f24e6f..be71ca0937f742dce3bb4117c0e94fc8e093029c 100644 (file)
@@ -624,7 +624,7 @@ static int ocfs2_remove_inode(struct inode *inode,
                ocfs2_get_system_file_inode(osb, INODE_ALLOC_SYSTEM_INODE,
                                            le16_to_cpu(di->i_suballoc_slot));
        if (!inode_alloc_inode) {
-               status = -EEXIST;
+               status = -ENOENT;
                mlog_errno(status);
                goto bail;
        }
@@ -742,7 +742,7 @@ static int ocfs2_wipe_inode(struct inode *inode,
                                                               ORPHAN_DIR_SYSTEM_INODE,
                                                               orphaned_slot);
                if (!orphan_dir_inode) {
-                       status = -EEXIST;
+                       status = -ENOENT;
                        mlog_errno(status);
                        goto bail;
                }
index 0440134556216d4b12a00168253b9b9446ff7312..857bbbcd39f3b6bbd7c8bc37ef463faa6c2cd77a 100644 (file)
@@ -666,7 +666,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
        if (le32_to_cpu(alloc->id1.bitmap1.i_used) !=
            ocfs2_local_alloc_count_bits(alloc)) {
                ocfs2_error(osb->sb, "local alloc inode %llu says it has "
-                           "%u free bits, but a count shows %u",
+                           "%u used bits, but a count shows %u",
                            (unsigned long long)le64_to_cpu(alloc->i_blkno),
                            le32_to_cpu(alloc->id1.bitmap1.i_used),
                            ocfs2_local_alloc_count_bits(alloc));
@@ -839,7 +839,7 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
                                     u32 *numbits,
                                     struct ocfs2_alloc_reservation *resv)
 {
-       int numfound, bitoff, left, startoff, lastzero;
+       int numfound = 0, bitoff, left, startoff, lastzero;
        int local_resv = 0;
        struct ocfs2_alloc_reservation r;
        void *bitmap = NULL;
index b5c3a5ea3ee60e264cf7523e8626ac3b61f9421b..09f90cbf0e24d39ee0f8b27b2d056273f4bdf879 100644 (file)
@@ -2322,10 +2322,10 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
 
        trace_ocfs2_orphan_del(
             (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno,
-            name, namelen);
+            name, strlen(name));
 
        /* find it's spot in the orphan directory */
-       status = ocfs2_find_entry(name, namelen, orphan_dir_inode,
+       status = ocfs2_find_entry(name, strlen(name), orphan_dir_inode,
                                  &lookup);
        if (status) {
                mlog_errno(status);
@@ -2808,7 +2808,7 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
                                                       ORPHAN_DIR_SYSTEM_INODE,
                                                       osb->slot_num);
        if (!orphan_dir_inode) {
-               status = -EEXIST;
+               status = -ENOENT;
                mlog_errno(status);
                goto leave;
        }
index ee541f92dab40308352f22cc5794056d44beb432..df3a500789c7eb7bfde662e9a391c86b99ef2a11 100644 (file)
@@ -4276,7 +4276,7 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir,
        error = posix_acl_create(dir, &mode, &default_acl, &acl);
        if (error) {
                mlog_errno(error);
-               goto out;
+               return error;
        }
 
        error = ocfs2_create_inode_in_orphan(dir, mode,
index d5493e361a381b12a9d57a779294fb172fb963b3..e78a203d44c832d8d638782984752cfc87e924b8 100644 (file)
@@ -427,7 +427,7 @@ int ocfs2_init_slot_info(struct ocfs2_super *osb)
        if (!si) {
                status = -ENOMEM;
                mlog_errno(status);
-               goto bail;
+               return status;
        }
 
        si->si_extended = ocfs2_uses_extended_slot_map(osb);
@@ -452,7 +452,7 @@ int ocfs2_init_slot_info(struct ocfs2_super *osb)
 
        osb->slot_info = (struct ocfs2_slot_info *)si;
 bail:
-       if (status < 0 && si)
+       if (status < 0)
                __ocfs2_free_slot_info(si);
 
        return status;
index 1724d43d3da1626b517b8deb73cd87c47492fd85..220cae7bbdbcf1e88176505148de97e33645cc66 100644 (file)
@@ -295,7 +295,7 @@ static int o2cb_cluster_check(void)
                set_bit(node_num, netmap);
                if (!memcmp(hbmap, netmap, sizeof(hbmap)))
                        return 0;
-               if (i < O2CB_MAP_STABILIZE_COUNT)
+               if (i < O2CB_MAP_STABILIZE_COUNT - 1)
                        msleep(1000);
        }
 
index 720aa389e0eae60c2b0d01a7038b73c268932d5a..2768eb1da2b865f4afba3c35087da7c477c87309 100644 (file)
@@ -1004,10 +1004,8 @@ static int user_cluster_connect(struct ocfs2_cluster_connection *conn)
        BUG_ON(conn == NULL);
 
        lc = kzalloc(sizeof(struct ocfs2_live_connection), GFP_KERNEL);
-       if (!lc) {
-               rc = -ENOMEM;
-               goto out;
-       }
+       if (!lc)
+               return -ENOMEM;
 
        init_waitqueue_head(&lc->oc_wait);
        init_completion(&lc->oc_sync_wait);
@@ -1063,7 +1061,7 @@ static int user_cluster_connect(struct ocfs2_cluster_connection *conn)
        }
 
 out:
-       if (rc && lc)
+       if (rc)
                kfree(lc);
        return rc;
 }
index 0cb889a17ae14db8ffc7e0688543be132a126ea6..4479029630bb37bb8a6e4880e94ab8633d967df6 100644 (file)
@@ -2499,6 +2499,8 @@ static int _ocfs2_free_suballoc_bits(handle_t *handle,
                                         alloc_bh, OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
+               ocfs2_block_group_set_bits(handle, alloc_inode, group, group_bh,
+                               start_bit, count);
                goto bail;
        }
 
index 26675185b88688c1c8b7571eed45cd06f1d70eca..837ddce4b659fa99816114b07749081872967c8a 100644 (file)
@@ -1112,7 +1112,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
 
        osb->osb_debug_root = debugfs_create_dir(osb->uuid_str,
                                                 ocfs2_debugfs_root);
-       if (!osb->osb_debug_root) {
+       if (IS_ERR_OR_NULL(osb->osb_debug_root)) {
                status = -EINVAL;
                mlog(ML_ERROR, "Unable to create per-mount debugfs root.\n");
                goto read_super_error;
@@ -1122,7 +1122,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
                                            osb->osb_debug_root,
                                            osb,
                                            &ocfs2_osb_debug_fops);
-       if (!osb->osb_ctxt) {
+       if (IS_ERR_OR_NULL(osb->osb_ctxt)) {
                status = -EINVAL;
                mlog_errno(status);
                goto read_super_error;
@@ -1606,8 +1606,9 @@ static int __init ocfs2_init(void)
        }
 
        ocfs2_debugfs_root = debugfs_create_dir("ocfs2", NULL);
-       if (!ocfs2_debugfs_root) {
-               status = -ENOMEM;
+       if (IS_ERR_OR_NULL(ocfs2_debugfs_root)) {
+               status = ocfs2_debugfs_root ?
+                       PTR_ERR(ocfs2_debugfs_root) : -ENOMEM;
                mlog(ML_ERROR, "Unable to create ocfs2 debugfs root.\n");
                goto out4;
        }
@@ -2069,6 +2070,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
        cbits = le32_to_cpu(di->id2.i_super.s_clustersize_bits);
        bbits = le32_to_cpu(di->id2.i_super.s_blocksize_bits);
        sb->s_maxbytes = ocfs2_max_file_offset(bbits, cbits);
+       memcpy(sb->s_uuid, di->id2.i_super.s_uuid,
+              sizeof(di->id2.i_super.s_uuid));
 
        osb->osb_dx_mask = (1 << (cbits - bbits)) - 1;
 
@@ -2333,7 +2336,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
                mlog_errno(status);
                goto bail;
        }
-       cleancache_init_shared_fs((char *)&di->id2.i_super.s_uuid, sb);
+       cleancache_init_shared_fs(sb);
 
 bail:
        return status;
@@ -2563,22 +2566,22 @@ static void ocfs2_handle_error(struct super_block *sb)
        ocfs2_set_ro_flag(osb, 0);
 }
 
-static char error_buf[1024];
-
-void __ocfs2_error(struct super_block *sb,
-                  const char *function,
-                  const char *fmt, ...)
+void __ocfs2_error(struct super_block *sb, const char *function,
+                 const char *fmt, ...)
 {
+       struct va_format vaf;
        va_list args;
 
        va_start(args, fmt);
-       vsnprintf(error_buf, sizeof(error_buf), fmt, args);
-       va_end(args);
+       vaf.fmt = fmt;
+       vaf.va = &args;
 
        /* Not using mlog here because we want to show the actual
         * function the error came from. */
-       printk(KERN_CRIT "OCFS2: ERROR (device %s): %s: %s\n",
-              sb->s_id, function, error_buf);
+       printk(KERN_CRIT "OCFS2: ERROR (device %s): %s: %pV\n",
+              sb->s_id, function, &vaf);
+
+       va_end(args);
 
        ocfs2_handle_error(sb);
 }
@@ -2586,18 +2589,21 @@ void __ocfs2_error(struct super_block *sb,
 /* Handle critical errors. This is intentionally more drastic than
  * ocfs2_handle_error, so we only use for things like journal errors,
  * etc. */
-void __ocfs2_abort(struct super_block* sb,
-                  const char *function,
+void __ocfs2_abort(struct super_block *sb, const char *function,
                   const char *fmt, ...)
 {
+       struct va_format vaf;
        va_list args;
 
        va_start(args, fmt);
-       vsnprintf(error_buf, sizeof(error_buf), fmt, args);
-       va_end(args);
 
-       printk(KERN_CRIT "OCFS2: abort (device %s): %s: %s\n",
-              sb->s_id, function, error_buf);
+       vaf.fmt = fmt;
+       vaf.va = &args;
+
+       printk(KERN_CRIT "OCFS2: abort (device %s): %s: %pV\n",
+              sb->s_id, function, &vaf);
+
+       va_end(args);
 
        /* We don't have the cluster support yet to go straight to
         * hard readonly in here. Until then, we want to keep
index 85b190dc132f3a3cc52dc19eb5a31ab094060aef..4ca7533be479105b51a6952298618f1d73294cf0 100644 (file)
@@ -1238,6 +1238,10 @@ static int ocfs2_xattr_block_get(struct inode *inode,
                                                                i,
                                                                &block_off,
                                                                &name_offset);
+                       if (ret) {
+                               mlog_errno(ret);
+                               goto cleanup;
+                       }
                        xs->base = bucket_block(xs->bucket, block_off);
                }
                if (ocfs2_xattr_is_local(xs->here)) {
@@ -5665,6 +5669,10 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode,
 
                ret = ocfs2_get_xattr_tree_value_root(inode->i_sb, bucket,
                                                      i, &xv, NULL);
+               if (ret) {
+                       mlog_errno(ret);
+                       break;
+               }
 
                ret = ocfs2_lock_xattr_remove_allocators(inode, xv,
                                                         args->ref_ci,
index 33f9cbf2610b39498d416cb8c142fb5ebe4cc790..6a83c47d59040df871d2dac261d71fd32bec5587 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -570,6 +570,7 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
        uid = make_kuid(current_user_ns(), user);
        gid = make_kgid(current_user_ns(), group);
 
+retry_deleg:
        newattrs.ia_valid =  ATTR_CTIME;
        if (user != (uid_t) -1) {
                if (!uid_valid(uid))
@@ -586,7 +587,6 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
        if (!S_ISDIR(inode->i_mode))
                newattrs.ia_valid |=
                        ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
-retry_deleg:
        mutex_lock(&inode->i_mutex);
        error = security_path_chown(path, uid, gid);
        if (!error)
@@ -988,9 +988,6 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
                return ERR_PTR(err);
        if (flags & O_CREAT)
                return ERR_PTR(-EINVAL);
-       if (!filename && (flags & O_DIRECTORY))
-               if (!dentry->d_inode->i_op->lookup)
-                       return ERR_PTR(-ENOTDIR);
        return do_file_open_root(dentry, mnt, filename, &op);
 }
 EXPORT_SYMBOL(file_open_root);
index 21981e58e2a634c09b9ebb9b327860d849fb6b53..2d084f2d0b83c698a7df720c35d2fdbeadb65fcb 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -21,7 +21,6 @@
 #include <linux/audit.h>
 #include <linux/syscalls.h>
 #include <linux/fcntl.h>
-#include <linux/aio.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
index 39d1373128e94a6e2e0f91d53e2d5838e855211b..44a549beeafa1006a8055cbc23ea06c20a06929f 100644 (file)
@@ -539,6 +539,9 @@ static int ramoops_probe(struct platform_device *pdev)
        mem_address = pdata->mem_address;
        record_size = pdata->record_size;
        dump_oops = pdata->dump_oops;
+       ramoops_console_size = pdata->console_size;
+       ramoops_pmsg_size = pdata->pmsg_size;
+       ramoops_ftrace_size = pdata->ftrace_size;
 
        pr_info("attached 0x%lx@0x%llx, ecc: %d/%d\n",
                cxt->size, (unsigned long long)cxt->phys_addr,
index 8e1b68786d663d4be5551efcd7b0bf7d5ed8b192..69128b3786469b807f87763a51c819f4ad076503 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/fcntl.h>
 #include <linux/file.h>
 #include <linux/uio.h>
-#include <linux/aio.h>
 #include <linux/fsnotify.h>
 #include <linux/security.h>
 #include <linux/export.h>
@@ -343,13 +342,10 @@ ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos)
 
        init_sync_kiocb(&kiocb, file);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = iov_iter_count(iter);
 
        iter->type |= READ;
        ret = file->f_op->read_iter(&kiocb, iter);
-       if (ret == -EIOCBQUEUED)
-               ret = wait_on_sync_kiocb(&kiocb);
-
+       BUG_ON(ret == -EIOCBQUEUED);
        if (ret > 0)
                *ppos = kiocb.ki_pos;
        return ret;
@@ -366,13 +362,10 @@ ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos)
 
        init_sync_kiocb(&kiocb, file);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = iov_iter_count(iter);
 
        iter->type |= WRITE;
        ret = file->f_op->write_iter(&kiocb, iter);
-       if (ret == -EIOCBQUEUED)
-               ret = wait_on_sync_kiocb(&kiocb);
-
+       BUG_ON(ret == -EIOCBQUEUED);
        if (ret > 0)
                *ppos = kiocb.ki_pos;
        return ret;
@@ -426,11 +419,9 @@ ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *pp
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = len;
 
        ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&kiocb);
+       BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
@@ -446,12 +437,10 @@ ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *p
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = len;
        iov_iter_init(&iter, READ, &iov, 1, len);
 
        ret = filp->f_op->read_iter(&kiocb, &iter);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&kiocb);
+       BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
@@ -510,11 +499,9 @@ ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, lof
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = len;
 
        ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&kiocb);
+       BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
@@ -530,12 +517,10 @@ ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, lo
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = len;
        iov_iter_init(&iter, WRITE, &iov, 1, len);
 
        ret = filp->f_op->write_iter(&kiocb, &iter);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&kiocb);
+       BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
@@ -710,60 +695,47 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to)
 }
 EXPORT_SYMBOL(iov_shorten);
 
-static ssize_t do_iter_readv_writev(struct file *filp, int rw, const struct iovec *iov,
-               unsigned long nr_segs, size_t len, loff_t *ppos, iter_fn_t fn)
+static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter,
+               loff_t *ppos, iter_fn_t fn)
 {
        struct kiocb kiocb;
-       struct iov_iter iter;
        ssize_t ret;
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = len;
 
-       iov_iter_init(&iter, rw, iov, nr_segs, len);
-       ret = fn(&kiocb, &iter);
-       if (ret == -EIOCBQUEUED)
-               ret = wait_on_sync_kiocb(&kiocb);
+       ret = fn(&kiocb, iter);
+       BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
 
-static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
-               unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
+static ssize_t do_sync_readv_writev(struct file *filp, struct iov_iter *iter,
+               loff_t *ppos, iov_fn_t fn)
 {
        struct kiocb kiocb;
        ssize_t ret;
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_nbytes = len;
 
-       ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
-       if (ret == -EIOCBQUEUED)
-               ret = wait_on_sync_kiocb(&kiocb);
+       ret = fn(&kiocb, iter->iov, iter->nr_segs, kiocb.ki_pos);
+       BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
 
 /* Do it by hand, with file-ops */
-static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
-               unsigned long nr_segs, loff_t *ppos, io_fn_t fn)
+static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter,
+               loff_t *ppos, io_fn_t fn)
 {
-       struct iovec *vector = iov;
        ssize_t ret = 0;
 
-       while (nr_segs > 0) {
-               void __user *base;
-               size_t len;
+       while (iov_iter_count(iter)) {
+               struct iovec iovec = iov_iter_iovec(iter);
                ssize_t nr;
 
-               base = vector->iov_base;
-               len = vector->iov_len;
-               vector++;
-               nr_segs--;
-
-               nr = fn(filp, base, len, ppos);
+               nr = fn(filp, iovec.iov_base, iovec.iov_len, ppos);
 
                if (nr < 0) {
                        if (!ret)
@@ -771,8 +743,9 @@ static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
                        break;
                }
                ret += nr;
-               if (nr != len)
+               if (nr != iovec.iov_len)
                        break;
+               iov_iter_advance(iter, nr);
        }
 
        return ret;
@@ -863,17 +836,20 @@ static ssize_t do_readv_writev(int type, struct file *file,
        size_t tot_len;
        struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov = iovstack;
+       struct iov_iter iter;
        ssize_t ret;
        io_fn_t fn;
        iov_fn_t fnv;
        iter_fn_t iter_fn;
 
-       ret = rw_copy_check_uvector(type, uvector, nr_segs,
-                                   ARRAY_SIZE(iovstack), iovstack, &iov);
-       if (ret <= 0)
-               goto out;
+       ret = import_iovec(type, uvector, nr_segs,
+                          ARRAY_SIZE(iovstack), &iov, &iter);
+       if (ret < 0)
+               return ret;
 
-       tot_len = ret;
+       tot_len = iov_iter_count(&iter);
+       if (!tot_len)
+               goto out;
        ret = rw_verify_area(type, file, pos, tot_len);
        if (ret < 0)
                goto out;
@@ -891,20 +867,17 @@ static ssize_t do_readv_writev(int type, struct file *file,
        }
 
        if (iter_fn)
-               ret = do_iter_readv_writev(file, type, iov, nr_segs, tot_len,
-                                               pos, iter_fn);
+               ret = do_iter_readv_writev(file, &iter, pos, iter_fn);
        else if (fnv)
-               ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
-                                               pos, fnv);
+               ret = do_sync_readv_writev(file, &iter, pos, fnv);
        else
-               ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
+               ret = do_loop_readv_writev(file, &iter, pos, fn);
 
        if (type != READ)
                file_end_write(file);
 
 out:
-       if (iov != iovstack)
-               kfree(iov);
+       kfree(iov);
        if ((ret + (type == READ)) > 0) {
                if (type == READ)
                        fsnotify_access(file);
@@ -1043,17 +1016,20 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
        compat_ssize_t tot_len;
        struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov = iovstack;
+       struct iov_iter iter;
        ssize_t ret;
        io_fn_t fn;
        iov_fn_t fnv;
        iter_fn_t iter_fn;
 
-       ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
-                                              UIO_FASTIOV, iovstack, &iov);
-       if (ret <= 0)
-               goto out;
+       ret = compat_import_iovec(type, uvector, nr_segs,
+                                 UIO_FASTIOV, &iov, &iter);
+       if (ret < 0)
+               return ret;
 
-       tot_len = ret;
+       tot_len = iov_iter_count(&iter);
+       if (!tot_len)
+               goto out;
        ret = rw_verify_area(type, file, pos, tot_len);
        if (ret < 0)
                goto out;
@@ -1071,20 +1047,17 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
        }
 
        if (iter_fn)
-               ret = do_iter_readv_writev(file, type, iov, nr_segs, tot_len,
-                                               pos, iter_fn);
+               ret = do_iter_readv_writev(file, &iter, pos, iter_fn);
        else if (fnv)
-               ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
-                                               pos, fnv);
+               ret = do_sync_readv_writev(file, &iter, pos, fnv);
        else
-               ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
+               ret = do_loop_readv_writev(file, &iter, pos, fn);
 
        if (type != READ)
                file_end_write(file);
 
 out:
-       if (iov != iovstack)
-               kfree(iov);
+       kfree(iov);
        if ((ret + (type == READ)) > 0) {
                if (type == READ)
                        fsnotify_access(file);
index e72401e1f9956238064c91805279233a721bffe1..9312b7842e036f64ac02135102b445f0769e7702 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/writeback.h>
 #include <linux/quotaops.h>
 #include <linux/swap.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 int reiserfs_commit_write(struct file *f, struct page *page,
                          unsigned from, unsigned to);
index 7968da96bebbb5d1cd087cbfa2ece65c09cc8b4a..41cbb16299e0949984eb284887c22f77fff0390f 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/gfp.h>
 #include <linux/socket.h>
 #include <linux/compat.h>
-#include <linux/aio.h>
 #include "internal.h"
 
 /*
@@ -1534,34 +1533,29 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
        struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov = iovstack;
        struct iov_iter iter;
-       ssize_t count;
 
        pipe = get_pipe_info(file);
        if (!pipe)
                return -EBADF;
 
-       ret = rw_copy_check_uvector(READ, uiov, nr_segs,
-                                   ARRAY_SIZE(iovstack), iovstack, &iov);
-       if (ret <= 0)
-               goto out;
-
-       count = ret;
-       iov_iter_init(&iter, READ, iov, nr_segs, count);
+       ret = import_iovec(READ, uiov, nr_segs,
+                          ARRAY_SIZE(iovstack), &iov, &iter);
+       if (ret < 0)
+               return ret;
 
+       sd.total_len = iov_iter_count(&iter);
        sd.len = 0;
-       sd.total_len = count;
        sd.flags = flags;
        sd.u.data = &iter;
        sd.pos = 0;
 
-       pipe_lock(pipe);
-       ret = __splice_from_pipe(pipe, &sd, pipe_to_user);
-       pipe_unlock(pipe);
-
-out:
-       if (iov != iovstack)
-               kfree(iov);
+       if (sd.total_len) {
+               pipe_lock(pipe);
+               ret = __splice_from_pipe(pipe, &sd, pipe_to_user);
+               pipe_unlock(pipe);
+       }
 
+       kfree(iov);
        return ret;
 }
 
index ae0c3cef9927e64fb1f21ccf1848155825fc79ef..19636af5e75cc16614f790519c6111599d906830 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -66,7 +66,7 @@ int vfs_getattr(struct path *path, struct kstat *stat)
 {
        int retval;
 
-       retval = security_inode_getattr(path->mnt, path->dentry);
+       retval = security_inode_getattr(path);
        if (retval)
                return retval;
        return vfs_getattr_nosec(path, stat);
index 2b7dc90ccdbb4ae1ceac7725967cec2a643e21c7..928c20f47af9c1e26906e7e3be7dfa7705e8ca15 100644 (file)
@@ -224,7 +224,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags)
        s->s_maxbytes = MAX_NON_LFS;
        s->s_op = &default_op;
        s->s_time_gran = 1000000000;
-       s->cleancache_poolid = -1;
+       s->cleancache_poolid = CLEANCACHE_NO_POOL;
 
        s->s_shrink.seeks = DEFAULT_SEEKS;
        s->s_shrink.scan_objects = super_cache_scan;
index 2554d8835b480b9706067d1375559defecfbeae1..b400c04371f0d08c980b54183938b36afa47c1ec 100644 (file)
@@ -41,7 +41,7 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
 
        if (grp->attrs) {
                for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
-                       umode_t mode = 0;
+                       umode_t mode = (*attr)->mode;
 
                        /*
                         * In update mode, we're changing the permissions or
@@ -55,9 +55,14 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
                                if (!mode)
                                        continue;
                        }
+
+                       WARN(mode & ~(SYSFS_PREALLOC | 0664),
+                            "Attribute %s: Invalid permissions 0%o\n",
+                            (*attr)->name, mode);
+
+                       mode &= SYSFS_PREALLOC | 0664;
                        error = sysfs_add_file_mode_ns(parent, *attr, false,
-                                                      (*attr)->mode | mode,
-                                                      NULL);
+                                                      mode, NULL);
                        if (unlikely(error))
                                break;
                }
diff --git a/fs/tracefs/Makefile b/fs/tracefs/Makefile
new file mode 100644 (file)
index 0000000..82fa35b
--- /dev/null
@@ -0,0 +1,4 @@
+tracefs-objs   := inode.o
+
+obj-$(CONFIG_TRACING)  += tracefs.o
+
diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
new file mode 100644 (file)
index 0000000..d92bdf3
--- /dev/null
@@ -0,0 +1,650 @@
+/*
+ *  inode.c - part of tracefs, a pseudo file system for activating tracing
+ *
+ * Based on debugfs by: Greg Kroah-Hartman <greg@kroah.com>
+ *
+ *  Copyright (C) 2014 Red Hat Inc, author: Steven Rostedt <srostedt@redhat.com>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License version
+ *     2 as published by the Free Software Foundation.
+ *
+ * tracefs is the file system that is used by the tracing infrastructure.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/kobject.h>
+#include <linux/namei.h>
+#include <linux/tracefs.h>
+#include <linux/fsnotify.h>
+#include <linux/seq_file.h>
+#include <linux/parser.h>
+#include <linux/magic.h>
+#include <linux/slab.h>
+
+#define TRACEFS_DEFAULT_MODE   0700
+
+static struct vfsmount *tracefs_mount;
+static int tracefs_mount_count;
+static bool tracefs_registered;
+
+static ssize_t default_read_file(struct file *file, char __user *buf,
+                                size_t count, loff_t *ppos)
+{
+       return 0;
+}
+
+static ssize_t default_write_file(struct file *file, const char __user *buf,
+                                  size_t count, loff_t *ppos)
+{
+       return count;
+}
+
+static const struct file_operations tracefs_file_operations = {
+       .read =         default_read_file,
+       .write =        default_write_file,
+       .open =         simple_open,
+       .llseek =       noop_llseek,
+};
+
+static struct tracefs_dir_ops {
+       int (*mkdir)(const char *name);
+       int (*rmdir)(const char *name);
+} tracefs_ops;
+
+static char *get_dname(struct dentry *dentry)
+{
+       const char *dname;
+       char *name;
+       int len = dentry->d_name.len;
+
+       dname = dentry->d_name.name;
+       name = kmalloc(len + 1, GFP_KERNEL);
+       if (!name)
+               return NULL;
+       memcpy(name, dname, len);
+       name[len] = 0;
+       return name;
+}
+
+static int tracefs_syscall_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode)
+{
+       char *name;
+       int ret;
+
+       name = get_dname(dentry);
+       if (!name)
+               return -ENOMEM;
+
+       /*
+        * The mkdir call can call the generic functions that create
+        * the files within the tracefs system. It is up to the individual
+        * mkdir routine to handle races.
+        */
+       mutex_unlock(&inode->i_mutex);
+       ret = tracefs_ops.mkdir(name);
+       mutex_lock(&inode->i_mutex);
+
+       kfree(name);
+
+       return ret;
+}
+
+static int tracefs_syscall_rmdir(struct inode *inode, struct dentry *dentry)
+{
+       char *name;
+       int ret;
+
+       name = get_dname(dentry);
+       if (!name)
+               return -ENOMEM;
+
+       /*
+        * The rmdir call can call the generic functions that create
+        * the files within the tracefs system. It is up to the individual
+        * rmdir routine to handle races.
+        * This time we need to unlock not only the parent (inode) but
+        * also the directory that is being deleted.
+        */
+       mutex_unlock(&inode->i_mutex);
+       mutex_unlock(&dentry->d_inode->i_mutex);
+
+       ret = tracefs_ops.rmdir(name);
+
+       mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
+       mutex_lock(&dentry->d_inode->i_mutex);
+
+       kfree(name);
+
+       return ret;
+}
+
+static const struct inode_operations tracefs_dir_inode_operations = {
+       .lookup         = simple_lookup,
+       .mkdir          = tracefs_syscall_mkdir,
+       .rmdir          = tracefs_syscall_rmdir,
+};
+
+static struct inode *tracefs_get_inode(struct super_block *sb)
+{
+       struct inode *inode = new_inode(sb);
+       if (inode) {
+               inode->i_ino = get_next_ino();
+               inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       }
+       return inode;
+}
+
+struct tracefs_mount_opts {
+       kuid_t uid;
+       kgid_t gid;
+       umode_t mode;
+};
+
+enum {
+       Opt_uid,
+       Opt_gid,
+       Opt_mode,
+       Opt_err
+};
+
+static const match_table_t tokens = {
+       {Opt_uid, "uid=%u"},
+       {Opt_gid, "gid=%u"},
+       {Opt_mode, "mode=%o"},
+       {Opt_err, NULL}
+};
+
+struct tracefs_fs_info {
+       struct tracefs_mount_opts mount_opts;
+};
+
+static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts)
+{
+       substring_t args[MAX_OPT_ARGS];
+       int option;
+       int token;
+       kuid_t uid;
+       kgid_t gid;
+       char *p;
+
+       opts->mode = TRACEFS_DEFAULT_MODE;
+
+       while ((p = strsep(&data, ",")) != NULL) {
+               if (!*p)
+                       continue;
+
+               token = match_token(p, tokens, args);
+               switch (token) {
+               case Opt_uid:
+                       if (match_int(&args[0], &option))
+                               return -EINVAL;
+                       uid = make_kuid(current_user_ns(), option);
+                       if (!uid_valid(uid))
+                               return -EINVAL;
+                       opts->uid = uid;
+                       break;
+               case Opt_gid:
+                       if (match_int(&args[0], &option))
+                               return -EINVAL;
+                       gid = make_kgid(current_user_ns(), option);
+                       if (!gid_valid(gid))
+                               return -EINVAL;
+                       opts->gid = gid;
+                       break;
+               case Opt_mode:
+                       if (match_octal(&args[0], &option))
+                               return -EINVAL;
+                       opts->mode = option & S_IALLUGO;
+                       break;
+               /*
+                * We might like to report bad mount options here;
+                * but traditionally tracefs has ignored all mount options
+                */
+               }
+       }
+
+       return 0;
+}
+
+static int tracefs_apply_options(struct super_block *sb)
+{
+       struct tracefs_fs_info *fsi = sb->s_fs_info;
+       struct inode *inode = sb->s_root->d_inode;
+       struct tracefs_mount_opts *opts = &fsi->mount_opts;
+
+       inode->i_mode &= ~S_IALLUGO;
+       inode->i_mode |= opts->mode;
+
+       inode->i_uid = opts->uid;
+       inode->i_gid = opts->gid;
+
+       return 0;
+}
+
+static int tracefs_remount(struct super_block *sb, int *flags, char *data)
+{
+       int err;
+       struct tracefs_fs_info *fsi = sb->s_fs_info;
+
+       sync_filesystem(sb);
+       err = tracefs_parse_options(data, &fsi->mount_opts);
+       if (err)
+               goto fail;
+
+       tracefs_apply_options(sb);
+
+fail:
+       return err;
+}
+
+static int tracefs_show_options(struct seq_file *m, struct dentry *root)
+{
+       struct tracefs_fs_info *fsi = root->d_sb->s_fs_info;
+       struct tracefs_mount_opts *opts = &fsi->mount_opts;
+
+       if (!uid_eq(opts->uid, GLOBAL_ROOT_UID))
+               seq_printf(m, ",uid=%u",
+                          from_kuid_munged(&init_user_ns, opts->uid));
+       if (!gid_eq(opts->gid, GLOBAL_ROOT_GID))
+               seq_printf(m, ",gid=%u",
+                          from_kgid_munged(&init_user_ns, opts->gid));
+       if (opts->mode != TRACEFS_DEFAULT_MODE)
+               seq_printf(m, ",mode=%o", opts->mode);
+
+       return 0;
+}
+
+static const struct super_operations tracefs_super_operations = {
+       .statfs         = simple_statfs,
+       .remount_fs     = tracefs_remount,
+       .show_options   = tracefs_show_options,
+};
+
+static int trace_fill_super(struct super_block *sb, void *data, int silent)
+{
+       static struct tree_descr trace_files[] = {{""}};
+       struct tracefs_fs_info *fsi;
+       int err;
+
+       save_mount_options(sb, data);
+
+       fsi = kzalloc(sizeof(struct tracefs_fs_info), GFP_KERNEL);
+       sb->s_fs_info = fsi;
+       if (!fsi) {
+               err = -ENOMEM;
+               goto fail;
+       }
+
+       err = tracefs_parse_options(data, &fsi->mount_opts);
+       if (err)
+               goto fail;
+
+       err  =  simple_fill_super(sb, TRACEFS_MAGIC, trace_files);
+       if (err)
+               goto fail;
+
+       sb->s_op = &tracefs_super_operations;
+
+       tracefs_apply_options(sb);
+
+       return 0;
+
+fail:
+       kfree(fsi);
+       sb->s_fs_info = NULL;
+       return err;
+}
+
+static struct dentry *trace_mount(struct file_system_type *fs_type,
+                       int flags, const char *dev_name,
+                       void *data)
+{
+       return mount_single(fs_type, flags, data, trace_fill_super);
+}
+
+static struct file_system_type trace_fs_type = {
+       .owner =        THIS_MODULE,
+       .name =         "tracefs",
+       .mount =        trace_mount,
+       .kill_sb =      kill_litter_super,
+};
+MODULE_ALIAS_FS("tracefs");
+
+static struct dentry *start_creating(const char *name, struct dentry *parent)
+{
+       struct dentry *dentry;
+       int error;
+
+       pr_debug("tracefs: creating file '%s'\n",name);
+
+       error = simple_pin_fs(&trace_fs_type, &tracefs_mount,
+                             &tracefs_mount_count);
+       if (error)
+               return ERR_PTR(error);
+
+       /* If the parent is not specified, we create it in the root.
+        * We need the root dentry to do this, which is in the super
+        * block. A pointer to that is in the struct vfsmount that we
+        * have around.
+        */
+       if (!parent)
+               parent = tracefs_mount->mnt_root;
+
+       mutex_lock(&parent->d_inode->i_mutex);
+       dentry = lookup_one_len(name, parent, strlen(name));
+       if (!IS_ERR(dentry) && dentry->d_inode) {
+               dput(dentry);
+               dentry = ERR_PTR(-EEXIST);
+       }
+       if (IS_ERR(dentry))
+               mutex_unlock(&parent->d_inode->i_mutex);
+       return dentry;
+}
+
+static struct dentry *failed_creating(struct dentry *dentry)
+{
+       mutex_unlock(&dentry->d_parent->d_inode->i_mutex);
+       dput(dentry);
+       simple_release_fs(&tracefs_mount, &tracefs_mount_count);
+       return NULL;
+}
+
+static struct dentry *end_creating(struct dentry *dentry)
+{
+       mutex_unlock(&dentry->d_parent->d_inode->i_mutex);
+       return dentry;
+}
+
+/**
+ * tracefs_create_file - create a file in the tracefs filesystem
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have.
+ * @parent: a pointer to the parent dentry for this file.  This should be a
+ *          directory dentry if set.  If this parameter is NULL, then the
+ *          file will be created in the root of the tracefs filesystem.
+ * @data: a pointer to something that the caller will want to get to later
+ *        on.  The inode.i_private pointer will point to this value on
+ *        the open() call.
+ * @fops: a pointer to a struct file_operations that should be used for
+ *        this file.
+ *
+ * This is the basic "create a file" function for tracefs.  It allows for a
+ * wide range of flexibility in creating a file, or a directory (if you want
+ * to create a directory, the tracefs_create_dir() function is
+ * recommended to be used instead.)
+ *
+ * This function will return a pointer to a dentry if it succeeds.  This
+ * pointer must be passed to the tracefs_remove() function when the file is
+ * to be removed (no automatic cleanup happens if your module is unloaded,
+ * you are responsible here.)  If an error occurs, %NULL will be returned.
+ *
+ * If tracefs is not enabled in the kernel, the value -%ENODEV will be
+ * returned.
+ */
+struct dentry *tracefs_create_file(const char *name, umode_t mode,
+                                  struct dentry *parent, void *data,
+                                  const struct file_operations *fops)
+{
+       struct dentry *dentry;
+       struct inode *inode;
+
+       if (!(mode & S_IFMT))
+               mode |= S_IFREG;
+       BUG_ON(!S_ISREG(mode));
+       dentry = start_creating(name, parent);
+
+       if (IS_ERR(dentry))
+               return NULL;
+
+       inode = tracefs_get_inode(dentry->d_sb);
+       if (unlikely(!inode))
+               return failed_creating(dentry);
+
+       inode->i_mode = mode;
+       inode->i_fop = fops ? fops : &tracefs_file_operations;
+       inode->i_private = data;
+       d_instantiate(dentry, inode);
+       fsnotify_create(dentry->d_parent->d_inode, dentry);
+       return end_creating(dentry);
+}
+
+static struct dentry *__create_dir(const char *name, struct dentry *parent,
+                                  const struct inode_operations *ops)
+{
+       struct dentry *dentry = start_creating(name, parent);
+       struct inode *inode;
+
+       if (IS_ERR(dentry))
+               return NULL;
+
+       inode = tracefs_get_inode(dentry->d_sb);
+       if (unlikely(!inode))
+               return failed_creating(dentry);
+
+       inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
+       inode->i_op = ops;
+       inode->i_fop = &simple_dir_operations;
+
+       /* directory inodes start off with i_nlink == 2 (for "." entry) */
+       inc_nlink(inode);
+       d_instantiate(dentry, inode);
+       inc_nlink(dentry->d_parent->d_inode);
+       fsnotify_mkdir(dentry->d_parent->d_inode, dentry);
+       return end_creating(dentry);
+}
+
+/**
+ * tracefs_create_dir - create a directory in the tracefs filesystem
+ * @name: a pointer to a string containing the name of the directory to
+ *        create.
+ * @parent: a pointer to the parent dentry for this file.  This should be a
+ *          directory dentry if set.  If this parameter is NULL, then the
+ *          directory will be created in the root of the tracefs filesystem.
+ *
+ * This function creates a directory in tracefs with the given name.
+ *
+ * This function will return a pointer to a dentry if it succeeds.  This
+ * pointer must be passed to the tracefs_remove() function when the file is
+ * to be removed. If an error occurs, %NULL will be returned.
+ *
+ * If tracing is not enabled in the kernel, the value -%ENODEV will be
+ * returned.
+ */
+struct dentry *tracefs_create_dir(const char *name, struct dentry *parent)
+{
+       return __create_dir(name, parent, &simple_dir_inode_operations);
+}
+
+/**
+ * tracefs_create_instance_dir - create the tracing instances directory
+ * @name: The name of the instances directory to create
+ * @parent: The parent directory that the instances directory will exist
+ * @mkdir: The function to call when a mkdir is performed.
+ * @rmdir: The function to call when a rmdir is performed.
+ *
+ * Only one instances directory is allowed.
+ *
+ * The instances directory is special as it allows for mkdir and rmdir to
+ * to be done by userspace. When a mkdir or rmdir is performed, the inode
+ * locks are released and the methhods passed in (@mkdir and @rmdir) are
+ * called without locks and with the name of the directory being created
+ * within the instances directory.
+ *
+ * Returns the dentry of the instances directory.
+ */
+struct dentry *tracefs_create_instance_dir(const char *name, struct dentry *parent,
+                                         int (*mkdir)(const char *name),
+                                         int (*rmdir)(const char *name))
+{
+       struct dentry *dentry;
+
+       /* Only allow one instance of the instances directory. */
+       if (WARN_ON(tracefs_ops.mkdir || tracefs_ops.rmdir))
+               return NULL;
+
+       dentry = __create_dir(name, parent, &tracefs_dir_inode_operations);
+       if (!dentry)
+               return NULL;
+
+       tracefs_ops.mkdir = mkdir;
+       tracefs_ops.rmdir = rmdir;
+
+       return dentry;
+}
+
+static inline int tracefs_positive(struct dentry *dentry)
+{
+       return dentry->d_inode && !d_unhashed(dentry);
+}
+
+static int __tracefs_remove(struct dentry *dentry, struct dentry *parent)
+{
+       int ret = 0;
+
+       if (tracefs_positive(dentry)) {
+               if (dentry->d_inode) {
+                       dget(dentry);
+                       switch (dentry->d_inode->i_mode & S_IFMT) {
+                       case S_IFDIR:
+                               ret = simple_rmdir(parent->d_inode, dentry);
+                               break;
+                       default:
+                               simple_unlink(parent->d_inode, dentry);
+                               break;
+                       }
+                       if (!ret)
+                               d_delete(dentry);
+                       dput(dentry);
+               }
+       }
+       return ret;
+}
+
+/**
+ * tracefs_remove - removes a file or directory from the tracefs filesystem
+ * @dentry: a pointer to a the dentry of the file or directory to be
+ *          removed.
+ *
+ * This function removes a file or directory in tracefs that was previously
+ * created with a call to another tracefs function (like
+ * tracefs_create_file() or variants thereof.)
+ */
+void tracefs_remove(struct dentry *dentry)
+{
+       struct dentry *parent;
+       int ret;
+
+       if (IS_ERR_OR_NULL(dentry))
+               return;
+
+       parent = dentry->d_parent;
+       if (!parent || !parent->d_inode)
+               return;
+
+       mutex_lock(&parent->d_inode->i_mutex);
+       ret = __tracefs_remove(dentry, parent);
+       mutex_unlock(&parent->d_inode->i_mutex);
+       if (!ret)
+               simple_release_fs(&tracefs_mount, &tracefs_mount_count);
+}
+
+/**
+ * tracefs_remove_recursive - recursively removes a directory
+ * @dentry: a pointer to a the dentry of the directory to be removed.
+ *
+ * This function recursively removes a directory tree in tracefs that
+ * was previously created with a call to another tracefs function
+ * (like tracefs_create_file() or variants thereof.)
+ */
+void tracefs_remove_recursive(struct dentry *dentry)
+{
+       struct dentry *child, *parent;
+
+       if (IS_ERR_OR_NULL(dentry))
+               return;
+
+       parent = dentry->d_parent;
+       if (!parent || !parent->d_inode)
+               return;
+
+       parent = dentry;
+ down:
+       mutex_lock(&parent->d_inode->i_mutex);
+ loop:
+       /*
+        * The parent->d_subdirs is protected by the d_lock. Outside that
+        * lock, the child can be unlinked and set to be freed which can
+        * use the d_u.d_child as the rcu head and corrupt this list.
+        */
+       spin_lock(&parent->d_lock);
+       list_for_each_entry(child, &parent->d_subdirs, d_child) {
+               if (!tracefs_positive(child))
+                       continue;
+
+               /* perhaps simple_empty(child) makes more sense */
+               if (!list_empty(&child->d_subdirs)) {
+                       spin_unlock(&parent->d_lock);
+                       mutex_unlock(&parent->d_inode->i_mutex);
+                       parent = child;
+                       goto down;
+               }
+
+               spin_unlock(&parent->d_lock);
+
+               if (!__tracefs_remove(child, parent))
+                       simple_release_fs(&tracefs_mount, &tracefs_mount_count);
+
+               /*
+                * The parent->d_lock protects agaist child from unlinking
+                * from d_subdirs. When releasing the parent->d_lock we can
+                * no longer trust that the next pointer is valid.
+                * Restart the loop. We'll skip this one with the
+                * tracefs_positive() check.
+                */
+               goto loop;
+       }
+       spin_unlock(&parent->d_lock);
+
+       mutex_unlock(&parent->d_inode->i_mutex);
+       child = parent;
+       parent = parent->d_parent;
+       mutex_lock(&parent->d_inode->i_mutex);
+
+       if (child != dentry)
+               /* go up */
+               goto loop;
+
+       if (!__tracefs_remove(child, parent))
+               simple_release_fs(&tracefs_mount, &tracefs_mount_count);
+       mutex_unlock(&parent->d_inode->i_mutex);
+}
+
+/**
+ * tracefs_initialized - Tells whether tracefs has been registered
+ */
+bool tracefs_initialized(void)
+{
+       return tracefs_registered;
+}
+
+static struct kobject *trace_kobj;
+
+static int __init tracefs_init(void)
+{
+       int retval;
+
+       trace_kobj = kobject_create_and_add("tracing", kernel_kobj);
+       if (!trace_kobj)
+               return -EINVAL;
+
+       retval = register_filesystem(&trace_fs_type);
+       if (!retval)
+               tracefs_registered = true;
+
+       return retval;
+}
+core_initcall(tracefs_init);
index e627c0acf6264f6aabc4b2777ab79214e9c32e64..c3d15fe834033d4d080ea408dbbb961f1e4719c6 100644 (file)
@@ -50,7 +50,6 @@
  */
 
 #include "ubifs.h"
-#include <linux/aio.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/slab.h>
index 08f3555fbeac3f6ceeda033cb8f6ec82557623d0..7f885cc8b0b798dca3239a9f72f87741fd8b023f 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/errno.h>
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
@@ -122,7 +122,7 @@ static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        struct file *file = iocb->ki_filp;
        struct inode *inode = file_inode(file);
        int err, pos;
-       size_t count = iocb->ki_nbytes;
+       size_t count = iov_iter_count(from);
        struct udf_inode_info *iinfo = UDF_I(inode);
 
        mutex_lock(&inode->i_mutex);
index a445d599098d7ad1ccace2a81a86a0bc563af391..9c1fbd23913db541c3facc1342614793b1403bfd 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/slab.h>
 #include <linux/crc-itu-t.h>
 #include <linux/mpage.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
index 3a9b7a1b8704be66439ea797dd2183c035a929e5..4f8cdc59bc38154b45f1adfd69c0a371df4394e3 100644 (file)
@@ -31,7 +31,6 @@
 #include "xfs_bmap.h"
 #include "xfs_bmap_util.h"
 #include "xfs_bmap_btree.h"
-#include <linux/aio.h>
 #include <linux/gfp.h>
 #include <linux/mpage.h>
 #include <linux/pagevec.h>
index a2e1cb8a568bf9d45e32c43539a2e6f8b56d83f4..f44212fae65327347db1ba9f8ec1739d30650f44 100644 (file)
@@ -38,7 +38,6 @@
 #include "xfs_icache.h"
 #include "xfs_pnfs.h"
 
-#include <linux/aio.h>
 #include <linux/dcache.h>
 #include <linux/falloc.h>
 #include <linux/pagevec.h>
index 4d46085c1b901c1bd4b0b2dde897cb7e515a2a6b..39f1d6a2b04d4292f2dbd01b59bc748484824eff 100644 (file)
@@ -6,6 +6,12 @@
 
 #include <linux/mm_types.h>
 #include <linux/bug.h>
+#include <linux/errno.h>
+
+#if 4 - defined(__PAGETABLE_PUD_FOLDED) - defined(__PAGETABLE_PMD_FOLDED) != \
+       CONFIG_PGTABLE_LEVELS
+#error CONFIG_PGTABLE_LEVELS is not consistent with __PAGETABLE_{PUD,PMD}_FOLDED
+#endif
 
 /*
  * On almost all architectures and configurations, 0 can be used as the
@@ -691,6 +697,30 @@ static inline int pmd_protnone(pmd_t pmd)
 
 #endif /* CONFIG_MMU */
 
+#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
+int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot);
+int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot);
+int pud_clear_huge(pud_t *pud);
+int pmd_clear_huge(pmd_t *pmd);
+#else  /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
+static inline int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
+{
+       return 0;
+}
+static inline int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot)
+{
+       return 0;
+}
+static inline int pud_clear_huge(pud_t *pud)
+{
+       return 0;
+}
+static inline int pmd_clear_huge(pmd_t *pmd)
+{
+       return 0;
+}
+#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
+
 #endif /* !__ASSEMBLY__ */
 
 #ifndef io_remap_pfn_range
index ac78910d7416c5f7f2a68cfbde0d950d58ab0d9c..f8e8b34dc4274ee8fd105565fd8d731d3615e109 100644 (file)
 #define FTRACE_EVENTS()        . = ALIGN(8);                                   \
                        VMLINUX_SYMBOL(__start_ftrace_events) = .;      \
                        *(_ftrace_events)                               \
-                       VMLINUX_SYMBOL(__stop_ftrace_events) = .;
+                       VMLINUX_SYMBOL(__stop_ftrace_events) = .;       \
+                       VMLINUX_SYMBOL(__start_ftrace_enum_maps) = .;   \
+                       *(_ftrace_enum_map)                             \
+                       VMLINUX_SYMBOL(__stop_ftrace_enum_maps) = .;
 #else
 #define FTRACE_EVENTS()
 #endif
diff --git a/include/dt-bindings/gpio/meson8b-gpio.h b/include/dt-bindings/gpio/meson8b-gpio.h
new file mode 100644 (file)
index 0000000..c38cb20
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * GPIO definitions for Amlogic Meson8b SoCs
+ *
+ * Copyright (C) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _DT_BINDINGS_MESON8B_GPIO_H
+#define _DT_BINDINGS_MESON8B_GPIO_H
+
+#include <dt-bindings/gpio/meson8-gpio.h>
+
+/* GPIO Bank DIF */
+#define DIF_0_P                120
+#define DIF_0_N                121
+#define DIF_1_P                122
+#define DIF_1_N                123
+#define DIF_2_P                124
+#define DIF_2_N                125
+#define DIF_3_P                126
+#define DIF_3_N                127
+#define DIF_4_P                128
+#define DIF_4_N                129
+
+#endif /* _DT_BINDINGS_MESON8B_GPIO_H */
diff --git a/include/dt-bindings/interrupt-controller/irq-st.h b/include/dt-bindings/interrupt-controller/irq-st.h
new file mode 100644 (file)
index 0000000..4c59ace
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  include/linux/irqchip/irq-st.h
+ *
+ *  Copyright (C) 2014 STMicroelectronics â€“ All Rights Reserved
+ *
+ *  Author: Lee Jones <lee.jones@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.
+ */
+
+#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ST_H
+#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ST_H
+
+#define ST_IRQ_SYSCFG_EXT_0            0
+#define ST_IRQ_SYSCFG_EXT_1            1
+#define ST_IRQ_SYSCFG_EXT_2            2
+#define ST_IRQ_SYSCFG_CTI_0            3
+#define ST_IRQ_SYSCFG_CTI_1            4
+#define ST_IRQ_SYSCFG_PMU_0            5
+#define ST_IRQ_SYSCFG_PMU_1            6
+#define ST_IRQ_SYSCFG_pl310_L2         7
+#define ST_IRQ_SYSCFG_DISABLED         0xFFFFFFFF
+
+#define ST_IRQ_SYSCFG_EXT_1_INV                0x1
+#define ST_IRQ_SYSCFG_EXT_2_INV                0x2
+#define ST_IRQ_SYSCFG_EXT_3_INV                0x4
+
+#endif
diff --git a/include/dt-bindings/mfd/arizona.h b/include/dt-bindings/mfd/arizona.h
new file mode 100644 (file)
index 0000000..c7af7c7
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Device Tree defines for Arizona devices
+ *
+ * Copyright 2015 Cirrus Logic Inc.
+ *
+ * Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DT_BINDINGS_MFD_ARIZONA_H
+#define _DT_BINDINGS_MFD_ARIZONA_H
+
+/* GPIO Function Definitions */
+#define ARIZONA_GP_FN_TXLRCLK                    0x00
+#define ARIZONA_GP_FN_GPIO                       0x01
+#define ARIZONA_GP_FN_IRQ1                       0x02
+#define ARIZONA_GP_FN_IRQ2                       0x03
+#define ARIZONA_GP_FN_OPCLK                      0x04
+#define ARIZONA_GP_FN_FLL1_OUT                   0x05
+#define ARIZONA_GP_FN_FLL2_OUT                   0x06
+#define ARIZONA_GP_FN_PWM1                       0x08
+#define ARIZONA_GP_FN_PWM2                       0x09
+#define ARIZONA_GP_FN_SYSCLK_UNDERCLOCKED        0x0A
+#define ARIZONA_GP_FN_ASYNCCLK_UNDERCLOCKED      0x0B
+#define ARIZONA_GP_FN_FLL1_LOCK                  0x0C
+#define ARIZONA_GP_FN_FLL2_LOCK                  0x0D
+#define ARIZONA_GP_FN_FLL1_CLOCK_OK              0x0F
+#define ARIZONA_GP_FN_FLL2_CLOCK_OK              0x10
+#define ARIZONA_GP_FN_HEADPHONE_DET              0x12
+#define ARIZONA_GP_FN_MIC_DET                    0x13
+#define ARIZONA_GP_FN_WSEQ_STATUS                0x15
+#define ARIZONA_GP_FN_CIF_ADDRESS_ERROR          0x16
+#define ARIZONA_GP_FN_ASRC1_LOCK                 0x1A
+#define ARIZONA_GP_FN_ASRC2_LOCK                 0x1B
+#define ARIZONA_GP_FN_ASRC_CONFIG_ERROR          0x1C
+#define ARIZONA_GP_FN_DRC1_SIGNAL_DETECT         0x1D
+#define ARIZONA_GP_FN_DRC1_ANTICLIP              0x1E
+#define ARIZONA_GP_FN_DRC1_DECAY                 0x1F
+#define ARIZONA_GP_FN_DRC1_NOISE                 0x20
+#define ARIZONA_GP_FN_DRC1_QUICK_RELEASE         0x21
+#define ARIZONA_GP_FN_DRC2_SIGNAL_DETECT         0x22
+#define ARIZONA_GP_FN_DRC2_ANTICLIP              0x23
+#define ARIZONA_GP_FN_DRC2_DECAY                 0x24
+#define ARIZONA_GP_FN_DRC2_NOISE                 0x25
+#define ARIZONA_GP_FN_DRC2_QUICK_RELEASE         0x26
+#define ARIZONA_GP_FN_MIXER_DROPPED_SAMPLE       0x27
+#define ARIZONA_GP_FN_AIF1_CONFIG_ERROR          0x28
+#define ARIZONA_GP_FN_AIF2_CONFIG_ERROR          0x29
+#define ARIZONA_GP_FN_AIF3_CONFIG_ERROR          0x2A
+#define ARIZONA_GP_FN_SPK_TEMP_SHUTDOWN          0x2B
+#define ARIZONA_GP_FN_SPK_TEMP_WARNING           0x2C
+#define ARIZONA_GP_FN_UNDERCLOCKED               0x2D
+#define ARIZONA_GP_FN_OVERCLOCKED                0x2E
+#define ARIZONA_GP_FN_DSP_IRQ1                   0x35
+#define ARIZONA_GP_FN_DSP_IRQ2                   0x36
+#define ARIZONA_GP_FN_ASYNC_OPCLK                0x3D
+#define ARIZONA_GP_FN_BOOT_DONE                  0x44
+#define ARIZONA_GP_FN_DSP1_RAM_READY             0x45
+#define ARIZONA_GP_FN_SYSCLK_ENA_STATUS          0x4B
+#define ARIZONA_GP_FN_ASYNCCLK_ENA_STATUS        0x4C
+
+/* GPIO Configuration Bits */
+#define ARIZONA_GPN_DIR                          0x8000
+#define ARIZONA_GPN_PU                           0x4000
+#define ARIZONA_GPN_PD                           0x2000
+#define ARIZONA_GPN_LVL                          0x0800
+#define ARIZONA_GPN_POL                          0x0400
+#define ARIZONA_GPN_OP_CFG                       0x0200
+#define ARIZONA_GPN_DB                           0x0100
+
+/* Provide some defines for the most common configs */
+#define ARIZONA_GP_DEFAULT             0xffffffff
+#define ARIZONA_GP_OUTPUT              (ARIZONA_GP_FN_GPIO)
+#define ARIZONA_GP_INPUT               (ARIZONA_GP_FN_GPIO | \
+                                       ARIZONA_GPN_DIR)
+
+#define ARIZONA_32KZ_MCLK1 1
+#define ARIZONA_32KZ_MCLK2 2
+#define ARIZONA_32KZ_NONE  3
+
+#define ARIZONA_DMIC_MICVDD   0
+#define ARIZONA_DMIC_MICBIAS1 1
+#define ARIZONA_DMIC_MICBIAS2 2
+#define ARIZONA_DMIC_MICBIAS3 3
+
+#define ARIZONA_INMODE_DIFF 0
+#define ARIZONA_INMODE_SE   1
+#define ARIZONA_INMODE_DMIC 2
+
+#endif
index 388a6f3d6165e841c6098edd7afd42d91f92c36d..13a9d4bf2662a1fa418f7ee358ba2eb929241a11 100644 (file)
 #define QCOM_RPM_SYS_FABRIC_MODE               131
 #define QCOM_RPM_USB_OTG_SWITCH                        132
 #define QCOM_RPM_VDDMIN_GPIO                   133
+#define QCOM_RPM_NSS_FABRIC_0_CLK              134
+#define QCOM_RPM_NSS_FABRIC_1_CLK              135
+#define QCOM_RPM_SMB208_S1a                    136
+#define QCOM_RPM_SMB208_S1b                    137
+#define QCOM_RPM_SMB208_S2a                    138
+#define QCOM_RPM_SMB208_S2b                    139
 
 /*
  * Constants used to select force mode for regulators.
diff --git a/include/dt-bindings/phy/phy-miphy365x.h b/include/dt-bindings/phy/phy-miphy365x.h
deleted file mode 100644 (file)
index 8ef8aba..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * This header provides constants for the phy framework
- * based on the STMicroelectronics MiPHY365x.
- *
- * Author: Lee Jones <lee.jones@linaro.org>
- */
-#ifndef _DT_BINDINGS_PHY_MIPHY
-#define _DT_BINDINGS_PHY_MIPHY
-
-#define MIPHY_TYPE_SATA                1
-#define MIPHY_TYPE_PCIE                2
-#define MIPHY_TYPE_USB         3
-
-#endif /* _DT_BINDINGS_PHY_MIPHY */
diff --git a/include/dt-bindings/pinctrl/mt65xx.h b/include/dt-bindings/pinctrl/mt65xx.h
new file mode 100644 (file)
index 0000000..1198f45
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Hongzhou.Yang <hongzhou.yang@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 _DT_BINDINGS_PINCTRL_MT65XX_H
+#define _DT_BINDINGS_PINCTRL_MT65XX_H
+
+#define MTK_PIN_NO(x) ((x) << 8)
+#define MTK_GET_PIN_NO(x) ((x) >> 8)
+#define MTK_GET_PIN_FUNC(x) ((x) & 0xf)
+
+#define MTK_PUPD_SET_R1R0_00 100
+#define MTK_PUPD_SET_R1R0_01 101
+#define MTK_PUPD_SET_R1R0_10 102
+#define MTK_PUPD_SET_R1R0_11 103
+
+#define MTK_DRIVE_2mA  2
+#define MTK_DRIVE_4mA  4
+#define MTK_DRIVE_6mA  6
+#define MTK_DRIVE_8mA  8
+#define MTK_DRIVE_10mA 10
+#define MTK_DRIVE_12mA 12
+#define MTK_DRIVE_14mA 14
+#define MTK_DRIVE_16mA 16
+#define MTK_DRIVE_20mA 20
+#define MTK_DRIVE_24mA 24
+#define MTK_DRIVE_28mA 28
+#define MTK_DRIVE_32mA 32
+
+#endif /* _DT_BINDINGS_PINCTRL_MT65XX_H */
index fa74d7cc960cbfccd65de7b82aed49842ab55367..aafa76cb569dfc7a0ebe71a53c9b49a01016dea3 100644 (file)
 #define PM8058_GPIO_L5                 6
 #define PM8058_GPIO_L2                 7
 
+/*
+ * Note: PM8916 GPIO1 and GPIO2 are supporting
+ * only L2(1.15V) and L5(1.8V) options
+ */
+#define PM8916_GPIO_VPH                        0
+#define PM8916_GPIO_L2                 2
+#define PM8916_GPIO_L5                 3
+
 #define PM8917_GPIO_VPH                        0
 #define PM8917_GPIO_S4                 2
 #define PM8917_GPIO_L15                        3
 #define PM8058_GPIO39_MP3_CLK          PMIC_GPIO_FUNC_FUNC1
 #define PM8058_GPIO40_EXT_BB_EN                PMIC_GPIO_FUNC_FUNC1
 
+#define PM8916_GPIO1_BAT_ALRM_OUT      PMIC_GPIO_FUNC_FUNC1
+#define PM8916_GPIO1_KEYP_DRV          PMIC_GPIO_FUNC_FUNC2
+#define PM8916_GPIO2_DIV_CLK           PMIC_GPIO_FUNC_FUNC1
+#define PM8916_GPIO2_SLEEP_CLK         PMIC_GPIO_FUNC_FUNC2
+#define PM8916_GPIO3_KEYP_DRV          PMIC_GPIO_FUNC_FUNC1
+#define PM8916_GPIO4_KEYP_DRV          PMIC_GPIO_FUNC_FUNC2
+
 #define PM8917_GPIO9_18_KEYP_DRV       PMIC_GPIO_FUNC_FUNC1
 #define PM8917_GPIO20_BAT_ALRM_OUT     PMIC_GPIO_FUNC_FUNC1
 #define PM8917_GPIO21_23_UART_TX       PMIC_GPIO_FUNC_FUNC2
index d2c7dabe32231661a8e0cbe5d9706a40b89deb56..c10205491f8d6589f3d63ab21eb6d01d7d4ac049 100644 (file)
 #define PM8841_MPP_VPH                 0
 #define PM8841_MPP_S3                  2
 
+#define PM8916_MPP_VPH                 0
+#define PM8916_MPP_L2                  2
+#define PM8916_MPP_L5                  3
+
 #define PM8941_MPP_VPH                 0
 #define PM8941_MPP_L1                  1
 #define PM8941_MPP_S3                  2
index b3f45a578344a90eee8d1c76f724636de24447b1..e5966758c093483cd6027b4e14ea678904be5978 100644 (file)
 #include <linux/workqueue.h>
 
 struct arch_timer_kvm {
-#ifdef CONFIG_KVM_ARM_TIMER
        /* Is the timer enabled */
        bool                    enabled;
 
        /* Virtual offset */
        cycle_t                 cntvoff;
-#endif
 };
 
 struct arch_timer_cpu {
-#ifdef CONFIG_KVM_ARM_TIMER
        /* Registers: control register, timer value */
        u32                             cntv_ctl;       /* Saved/restored */
        cycle_t                         cntv_cval;      /* Saved/restored */
@@ -55,10 +52,8 @@ struct arch_timer_cpu {
 
        /* Timer IRQ */
        const struct kvm_irq_level      *irq;
-#endif
 };
 
-#ifdef CONFIG_KVM_ARM_TIMER
 int kvm_timer_hyp_init(void);
 void kvm_timer_enable(struct kvm *kvm);
 void kvm_timer_init(struct kvm *kvm);
@@ -72,30 +67,6 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu);
 u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid);
 int kvm_arm_timer_set_reg(struct kvm_vcpu *, u64 regid, u64 value);
 
-#else
-static inline int kvm_timer_hyp_init(void)
-{
-       return 0;
-};
-
-static inline void kvm_timer_enable(struct kvm *kvm) {}
-static inline void kvm_timer_init(struct kvm *kvm) {}
-static inline void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
-                                       const struct kvm_irq_level *irq) {}
-static inline void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) {}
-static inline void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) {}
-static inline void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu) {}
-static inline void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu) {}
-
-static inline int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
-{
-       return 0;
-}
-
-static inline u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
-{
-       return 0;
-}
-#endif
+bool kvm_timer_should_fire(struct kvm_vcpu *vcpu);
 
 #endif
index 66203b268984ebedd72d5bd1b2f54440e56011bc..133ea00aa83bc8926137ca8867f28a4ab9469d27 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/irqreturn.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
+#include <kvm/iodev.h>
 
 #define VGIC_NR_IRQS_LEGACY    256
 #define VGIC_NR_SGIS           16
@@ -140,16 +141,21 @@ struct vgic_params {
 };
 
 struct vgic_vm_ops {
-       bool    (*handle_mmio)(struct kvm_vcpu *, struct kvm_run *,
-                              struct kvm_exit_mmio *);
        bool    (*queue_sgi)(struct kvm_vcpu *, int irq);
        void    (*add_sgi_source)(struct kvm_vcpu *, int irq, int source);
        int     (*init_model)(struct kvm *);
        int     (*map_resources)(struct kvm *, const struct vgic_params *);
 };
 
+struct vgic_io_device {
+       gpa_t addr;
+       int len;
+       const struct vgic_io_range *reg_ranges;
+       struct kvm_vcpu *redist_vcpu;
+       struct kvm_io_device dev;
+};
+
 struct vgic_dist {
-#ifdef CONFIG_KVM_ARM_VGIC
        spinlock_t              lock;
        bool                    in_kernel;
        bool                    ready;
@@ -197,6 +203,9 @@ struct vgic_dist {
        /* Level-triggered interrupt queued on VCPU interface */
        struct vgic_bitmap      irq_queued;
 
+       /* Interrupt was active when unqueue from VCPU interface */
+       struct vgic_bitmap      irq_active;
+
        /* Interrupt priority. Not used yet. */
        struct vgic_bytemap     irq_priority;
 
@@ -237,8 +246,12 @@ struct vgic_dist {
        /* Bitmap indicating which CPU has something pending */
        unsigned long           *irq_pending_on_cpu;
 
+       /* Bitmap indicating which CPU has active IRQs */
+       unsigned long           *irq_active_on_cpu;
+
        struct vgic_vm_ops      vm_ops;
-#endif
+       struct vgic_io_device   dist_iodev;
+       struct vgic_io_device   *redist_iodevs;
 };
 
 struct vgic_v2_cpu_if {
@@ -266,13 +279,18 @@ struct vgic_v3_cpu_if {
 };
 
 struct vgic_cpu {
-#ifdef CONFIG_KVM_ARM_VGIC
        /* per IRQ to LR mapping */
        u8              *vgic_irq_lr_map;
 
-       /* Pending interrupts on this VCPU */
+       /* Pending/active/both interrupts on this VCPU */
        DECLARE_BITMAP( pending_percpu, VGIC_NR_PRIVATE_IRQS);
+       DECLARE_BITMAP( active_percpu, VGIC_NR_PRIVATE_IRQS);
+       DECLARE_BITMAP( pend_act_percpu, VGIC_NR_PRIVATE_IRQS);
+
+       /* Pending/active/both shared interrupts, dynamically sized */
        unsigned long   *pending_shared;
+       unsigned long   *active_shared;
+       unsigned long   *pend_act_shared;
 
        /* Bitmap of used/free list registers */
        DECLARE_BITMAP( lr_used, VGIC_V2_MAX_LRS);
@@ -285,7 +303,6 @@ struct vgic_cpu {
                struct vgic_v2_cpu_if   vgic_v2;
                struct vgic_v3_cpu_if   vgic_v3;
        };
-#endif
 };
 
 #define LR_EMPTY       0xff
@@ -295,10 +312,7 @@ struct vgic_cpu {
 
 struct kvm;
 struct kvm_vcpu;
-struct kvm_run;
-struct kvm_exit_mmio;
 
-#ifdef CONFIG_KVM_ARM_VGIC
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
 int kvm_vgic_hyp_init(void);
 int kvm_vgic_map_resources(struct kvm *kvm);
@@ -312,8 +326,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
                        bool level);
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
-bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
-                     struct kvm_exit_mmio *mmio);
+int kvm_vgic_vcpu_active_irq(struct kvm_vcpu *vcpu);
 
 #define irqchip_in_kernel(k)   (!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)    (!!((k)->arch.vgic.nr_cpus))
@@ -335,84 +348,4 @@ static inline int vgic_v3_probe(struct device_node *vgic_node,
 }
 #endif
 
-#else
-static inline int kvm_vgic_hyp_init(void)
-{
-       return 0;
-}
-
-static inline int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr)
-{
-       return 0;
-}
-
-static inline int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
-{
-       return -ENXIO;
-}
-
-static inline int kvm_vgic_map_resources(struct kvm *kvm)
-{
-       return 0;
-}
-
-static inline int kvm_vgic_create(struct kvm *kvm, u32 type)
-{
-       return 0;
-}
-
-static inline void kvm_vgic_destroy(struct kvm *kvm)
-{
-}
-
-static inline void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
-{
-}
-
-static inline int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
-{
-       return 0;
-}
-
-static inline void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu) {}
-static inline void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu) {}
-
-static inline int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid,
-                                     unsigned int irq_num, bool level)
-{
-       return 0;
-}
-
-static inline int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
-{
-       return 0;
-}
-
-static inline bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
-                                   struct kvm_exit_mmio *mmio)
-{
-       return false;
-}
-
-static inline int irqchip_in_kernel(struct kvm *kvm)
-{
-       return 0;
-}
-
-static inline bool vgic_initialized(struct kvm *kvm)
-{
-       return true;
-}
-
-static inline bool vgic_ready(struct kvm *kvm)
-{
-       return true;
-}
-
-static inline int kvm_vgic_get_max_vcpus(void)
-{
-       return KVM_MAX_VCPUS;
-}
-#endif
-
 #endif
diff --git a/include/kvm/iodev.h b/include/kvm/iodev.h
new file mode 100644 (file)
index 0000000..a6d208b
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __KVM_IODEV_H__
+#define __KVM_IODEV_H__
+
+#include <linux/kvm_types.h>
+#include <linux/errno.h>
+
+struct kvm_io_device;
+struct kvm_vcpu;
+
+/**
+ * kvm_io_device_ops are called under kvm slots_lock.
+ * read and write handlers return 0 if the transaction has been handled,
+ * or non-zero to have it passed to the next device.
+ **/
+struct kvm_io_device_ops {
+       int (*read)(struct kvm_vcpu *vcpu,
+                   struct kvm_io_device *this,
+                   gpa_t addr,
+                   int len,
+                   void *val);
+       int (*write)(struct kvm_vcpu *vcpu,
+                    struct kvm_io_device *this,
+                    gpa_t addr,
+                    int len,
+                    const void *val);
+       void (*destructor)(struct kvm_io_device *this);
+};
+
+
+struct kvm_io_device {
+       const struct kvm_io_device_ops *ops;
+};
+
+static inline void kvm_iodevice_init(struct kvm_io_device *dev,
+                                    const struct kvm_io_device_ops *ops)
+{
+       dev->ops = ops;
+}
+
+static inline int kvm_iodevice_read(struct kvm_vcpu *vcpu,
+                                   struct kvm_io_device *dev, gpa_t addr,
+                                   int l, void *v)
+{
+       return dev->ops->read ? dev->ops->read(vcpu, dev, addr, l, v)
+                               : -EOPNOTSUPP;
+}
+
+static inline int kvm_iodevice_write(struct kvm_vcpu *vcpu,
+                                    struct kvm_io_device *dev, gpa_t addr,
+                                    int l, const void *v)
+{
+       return dev->ops->write ? dev->ops->write(vcpu, dev, addr, l, v)
+                                : -EOPNOTSUPP;
+}
+
+static inline void kvm_iodevice_destructor(struct kvm_io_device *dev)
+{
+       if (dev->ops->destructor)
+               dev->ops->destructor(dev);
+}
+
+#endif /* __KVM_IODEV_H__ */
index d9c92daa3944e43a13f285a7baaa1443868cce3d..9eb42dbc5582ace99283629f0905861ac820c7d5 100644 (file)
@@ -1,86 +1,23 @@
 #ifndef __LINUX__AIO_H
 #define __LINUX__AIO_H
 
-#include <linux/list.h>
-#include <linux/workqueue.h>
 #include <linux/aio_abi.h>
-#include <linux/uio.h>
-#include <linux/rcupdate.h>
-
-#include <linux/atomic.h>
 
 struct kioctx;
 struct kiocb;
+struct mm_struct;
 
 #define KIOCB_KEY              0
 
-/*
- * We use ki_cancel == KIOCB_CANCELLED to indicate that a kiocb has been either
- * cancelled or completed (this makes a certain amount of sense because
- * successful cancellation - io_cancel() - does deliver the completion to
- * userspace).
- *
- * And since most things don't implement kiocb cancellation and we'd really like
- * kiocb completion to be lockless when possible, we use ki_cancel to
- * synchronize cancellation and completion - we only set it to KIOCB_CANCELLED
- * with xchg() or cmpxchg(), see batch_complete_aio() and kiocb_cancel().
- */
-#define KIOCB_CANCELLED                ((void *) (~0ULL))
-
 typedef int (kiocb_cancel_fn)(struct kiocb *);
 
-struct kiocb {
-       struct file             *ki_filp;
-       struct kioctx           *ki_ctx;        /* NULL for sync ops */
-       kiocb_cancel_fn         *ki_cancel;
-       void                    *private;
-
-       union {
-               void __user             *user;
-               struct task_struct      *tsk;
-       } ki_obj;
-
-       __u64                   ki_user_data;   /* user's data for completion */
-       loff_t                  ki_pos;
-       size_t                  ki_nbytes;      /* copy of iocb->aio_nbytes */
-
-       struct list_head        ki_list;        /* the aio core uses this
-                                                * for cancellation */
-
-       /*
-        * If the aio_resfd field of the userspace iocb is not zero,
-        * this is the underlying eventfd context to deliver events to.
-        */
-       struct eventfd_ctx      *ki_eventfd;
-};
-
-static inline bool is_sync_kiocb(struct kiocb *kiocb)
-{
-       return kiocb->ki_ctx == NULL;
-}
-
-static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
-{
-       *kiocb = (struct kiocb) {
-                       .ki_ctx = NULL,
-                       .ki_filp = filp,
-                       .ki_obj.tsk = current,
-               };
-}
-
 /* prototypes */
 #ifdef CONFIG_AIO
-extern ssize_t wait_on_sync_kiocb(struct kiocb *iocb);
-extern void aio_complete(struct kiocb *iocb, long res, long res2);
-struct mm_struct;
 extern void exit_aio(struct mm_struct *mm);
 extern long do_io_submit(aio_context_t ctx_id, long nr,
                         struct iocb __user *__user *iocbpp, bool compat);
 void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel);
 #else
-static inline ssize_t wait_on_sync_kiocb(struct kiocb *iocb) { return 0; }
-static inline void aio_complete(struct kiocb *iocb, long res, long res2) { }
-struct mm_struct;
 static inline void exit_aio(struct mm_struct *mm) { }
 static inline long do_io_submit(aio_context_t ctx_id, long nr,
                                struct iocb __user * __user *iocbpp,
@@ -89,11 +26,6 @@ static inline void kiocb_set_cancel_fn(struct kiocb *req,
                                       kiocb_cancel_fn *cancel) { }
 #endif /* CONFIG_AIO */
 
-static inline struct kiocb *list_kiocb(struct list_head *h)
-{
-       return list_entry(h, struct kiocb, ki_list);
-}
-
 /* for sysctl: */
 extern unsigned long aio_nr;
 extern unsigned long aio_max_nr;
index 1648026e06b4d1755e5fae46066e6265180829fb..b666b773e1118bb28171554d7e1846144f07d050 100644 (file)
@@ -94,6 +94,8 @@ enum {
        ATA_ID_SECTOR_SIZE      = 106,
        ATA_ID_WWN              = 108,
        ATA_ID_LOGICAL_SECTOR_SIZE      = 117,  /* and 118 */
+       ATA_ID_COMMAND_SET_3    = 119,
+       ATA_ID_COMMAND_SET_4    = 120,
        ATA_ID_LAST_LUN         = 126,
        ATA_ID_DLF              = 128,
        ATA_ID_CSFO             = 129,
@@ -177,7 +179,7 @@ enum {
        ATA_DSC                 = (1 << 4),     /* drive seek complete */
        ATA_DRQ                 = (1 << 3),     /* data request i/o */
        ATA_CORR                = (1 << 2),     /* corrected data error */
-       ATA_IDX                 = (1 << 1),     /* index */
+       ATA_SENSE               = (1 << 1),     /* sense code available */
        ATA_ERR                 = (1 << 0),     /* have an error */
        ATA_SRST                = (1 << 2),     /* software reset */
        ATA_ICRC                = (1 << 7),     /* interface CRC error */
@@ -382,6 +384,8 @@ 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,
@@ -525,6 +529,8 @@ 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)
 {
@@ -696,6 +702,27 @@ static inline bool ata_id_wcache_enabled(const u16 *id)
        return id[ATA_ID_CFS_ENABLE_1] & (1 << 5);
 }
 
+static inline bool ata_id_has_read_log_dma_ext(const u16 *id)
+{
+       if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15)))
+               return false;
+       return id[ATA_ID_COMMAND_SET_3] & (1 << 3);
+}
+
+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 c294e3e25e37a50a953a4a0bb3cb1aa66ba904d9..a1b25e35ea5f9fc2978b7f62917c6b4e39c3dc75 100644 (file)
@@ -181,7 +181,9 @@ enum rq_flag_bits {
        __REQ_ELVPRIV,          /* elevator private data attached */
        __REQ_FAILED,           /* set if the request failed */
        __REQ_QUIET,            /* don't worry about errors */
-       __REQ_PREEMPT,          /* set for "ide_preempt" requests */
+       __REQ_PREEMPT,          /* set for "ide_preempt" requests and also
+                                  for requests for which the SCSI "quiesce"
+                                  state must be ignored. */
        __REQ_ALLOCED,          /* request came from our alloc pool */
        __REQ_COPY_USER,        /* contains copies of user pages */
        __REQ_FLUSH_SEQ,        /* request for flush sequence */
index bbfceb7564523bc5e17037e25663185aee02311e..c2e21113ecc05379a51ba40abc2ad468e4e2786f 100644 (file)
@@ -113,8 +113,6 @@ struct bpf_prog_type_list {
        enum bpf_prog_type type;
 };
 
-void bpf_register_prog_type(struct bpf_prog_type_list *tl);
-
 struct bpf_prog;
 
 struct bpf_prog_aux {
@@ -129,11 +127,25 @@ struct bpf_prog_aux {
 };
 
 #ifdef CONFIG_BPF_SYSCALL
+void bpf_register_prog_type(struct bpf_prog_type_list *tl);
+
 void bpf_prog_put(struct bpf_prog *prog);
+struct bpf_prog *bpf_prog_get(u32 ufd);
 #else
-static inline void bpf_prog_put(struct bpf_prog *prog) {}
+static inline void bpf_register_prog_type(struct bpf_prog_type_list *tl)
+{
+}
+
+static inline struct bpf_prog *bpf_prog_get(u32 ufd)
+{
+       return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline void bpf_prog_put(struct bpf_prog *prog)
+{
+}
 #endif
-struct bpf_prog *bpf_prog_get(u32 ufd);
+
 /* verify correctness of eBPF program */
 int bpf_check(struct bpf_prog *fp, union bpf_attr *attr);
 
index 4ce9056b31a8d96f5d8b2696555eea2dbffd45a3..bda5ec0b4b4dc26a8431756e468241aad6bdd030 100644 (file)
@@ -5,6 +5,10 @@
 #include <linux/exportfs.h>
 #include <linux/mm.h>
 
+#define CLEANCACHE_NO_POOL             -1
+#define CLEANCACHE_NO_BACKEND          -2
+#define CLEANCACHE_NO_BACKEND_SHARED   -3
+
 #define CLEANCACHE_KEY_MAX 6
 
 /*
@@ -33,10 +37,9 @@ struct cleancache_ops {
        void (*invalidate_fs)(int);
 };
 
-extern struct cleancache_ops *
-       cleancache_register_ops(struct cleancache_ops *ops);
+extern int cleancache_register_ops(struct cleancache_ops *ops);
 extern void __cleancache_init_fs(struct super_block *);
-extern void __cleancache_init_shared_fs(char *, struct super_block *);
+extern void __cleancache_init_shared_fs(struct super_block *);
 extern int  __cleancache_get_page(struct page *);
 extern void __cleancache_put_page(struct page *);
 extern void __cleancache_invalidate_page(struct address_space *, struct page *);
@@ -78,10 +81,10 @@ static inline void cleancache_init_fs(struct super_block *sb)
                __cleancache_init_fs(sb);
 }
 
-static inline void cleancache_init_shared_fs(char *uuid, struct super_block *sb)
+static inline void cleancache_init_shared_fs(struct super_block *sb)
 {
        if (cleancache_enabled)
-               __cleancache_init_shared_fs(uuid, sb);
+               __cleancache_init_shared_fs(sb);
 }
 
 static inline int cleancache_get_page(struct page *page)
index 2e4cb67f6e560094aa719fe75f595dfbb562cf8e..96c280b2c263476c053bdd0c514aa16df3d04212 100644 (file)
@@ -8,64 +8,69 @@
 #ifndef _LINUX_CLOCKCHIPS_H
 #define _LINUX_CLOCKCHIPS_H
 
-/* Clock event notification values */
-enum clock_event_nofitiers {
-       CLOCK_EVT_NOTIFY_ADD,
-       CLOCK_EVT_NOTIFY_BROADCAST_ON,
-       CLOCK_EVT_NOTIFY_BROADCAST_OFF,
-       CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
-       CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
-       CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
-       CLOCK_EVT_NOTIFY_SUSPEND,
-       CLOCK_EVT_NOTIFY_RESUME,
-       CLOCK_EVT_NOTIFY_CPU_DYING,
-       CLOCK_EVT_NOTIFY_CPU_DEAD,
-};
-
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
 
-#include <linux/clocksource.h>
-#include <linux/cpumask.h>
-#include <linux/ktime.h>
-#include <linux/notifier.h>
+# include <linux/clocksource.h>
+# include <linux/cpumask.h>
+# include <linux/ktime.h>
+# include <linux/notifier.h>
 
 struct clock_event_device;
 struct module;
 
-/* Clock event mode commands */
+/* Clock event mode commands for legacy ->set_mode(): OBSOLETE */
 enum clock_event_mode {
-       CLOCK_EVT_MODE_UNUSED = 0,
+       CLOCK_EVT_MODE_UNUSED,
        CLOCK_EVT_MODE_SHUTDOWN,
        CLOCK_EVT_MODE_PERIODIC,
        CLOCK_EVT_MODE_ONESHOT,
        CLOCK_EVT_MODE_RESUME,
 };
 
+/*
+ * Possible states of a clock event device.
+ *
+ * DETACHED:   Device is not used by clockevents core. Initial state or can be
+ *             reached from SHUTDOWN.
+ * SHUTDOWN:   Device is powered-off. Can be reached from PERIODIC or ONESHOT.
+ * PERIODIC:   Device is programmed to generate events periodically. Can be
+ *             reached from DETACHED or SHUTDOWN.
+ * ONESHOT:    Device is programmed to generate event only once. Can be reached
+ *             from DETACHED or SHUTDOWN.
+ */
+enum clock_event_state {
+       CLOCK_EVT_STATE_DETACHED,
+       CLOCK_EVT_STATE_SHUTDOWN,
+       CLOCK_EVT_STATE_PERIODIC,
+       CLOCK_EVT_STATE_ONESHOT,
+};
+
 /*
  * Clock event features
  */
-#define CLOCK_EVT_FEAT_PERIODIC                0x000001
-#define CLOCK_EVT_FEAT_ONESHOT         0x000002
-#define CLOCK_EVT_FEAT_KTIME           0x000004
+# define CLOCK_EVT_FEAT_PERIODIC       0x000001
+# define CLOCK_EVT_FEAT_ONESHOT                0x000002
+# define CLOCK_EVT_FEAT_KTIME          0x000004
+
 /*
- * x86(64) specific misfeatures:
+ * x86(64) specific (mis)features:
  *
  * - Clockevent source stops in C3 State and needs broadcast support.
  * - Local APIC timer is used as a dummy device.
  */
-#define CLOCK_EVT_FEAT_C3STOP          0x000008
-#define CLOCK_EVT_FEAT_DUMMY           0x000010
+# define CLOCK_EVT_FEAT_C3STOP         0x000008
+# define CLOCK_EVT_FEAT_DUMMY          0x000010
 
 /*
  * Core shall set the interrupt affinity dynamically in broadcast mode
  */
-#define CLOCK_EVT_FEAT_DYNIRQ          0x000020
-#define CLOCK_EVT_FEAT_PERCPU          0x000040
+# define CLOCK_EVT_FEAT_DYNIRQ         0x000020
+# define CLOCK_EVT_FEAT_PERCPU         0x000040
 
 /*
  * Clockevent device is based on a hrtimer for broadcast
  */
-#define CLOCK_EVT_FEAT_HRTIMER         0x000080
+# define CLOCK_EVT_FEAT_HRTIMER                0x000080
 
 /**
  * struct clock_event_device - clock event device descriptor
@@ -78,10 +83,15 @@ enum clock_event_mode {
  * @min_delta_ns:      minimum delta value in ns
  * @mult:              nanosecond to cycles multiplier
  * @shift:             nanoseconds to cycles divisor (power of two)
- * @mode:              operating mode assigned by the management code
+ * @mode:              operating mode, relevant only to ->set_mode(), OBSOLETE
+ * @state:             current state of the device, assigned by the core code
  * @features:          features
  * @retries:           number of forced programming retries
- * @set_mode:          set mode function
+ * @set_mode:          legacy set mode function, only for modes <= CLOCK_EVT_MODE_RESUME.
+ * @set_state_periodic:        switch state to periodic, if !set_mode
+ * @set_state_oneshot: switch state to oneshot, if !set_mode
+ * @set_state_shutdown:        switch state to shutdown, if !set_mode
+ * @tick_resume:       resume clkevt device, if !set_mode
  * @broadcast:         function to broadcast events
  * @min_delta_ticks:   minimum delta value in ticks stored for reconfiguration
  * @max_delta_ticks:   maximum delta value in ticks stored for reconfiguration
@@ -95,22 +105,31 @@ enum clock_event_mode {
  */
 struct clock_event_device {
        void                    (*event_handler)(struct clock_event_device *);
-       int                     (*set_next_event)(unsigned long evt,
-                                                 struct clock_event_device *);
-       int                     (*set_next_ktime)(ktime_t expires,
-                                                 struct clock_event_device *);
+       int                     (*set_next_event)(unsigned long evt, struct clock_event_device *);
+       int                     (*set_next_ktime)(ktime_t expires, struct clock_event_device *);
        ktime_t                 next_event;
        u64                     max_delta_ns;
        u64                     min_delta_ns;
        u32                     mult;
        u32                     shift;
        enum clock_event_mode   mode;
+       enum clock_event_state  state;
        unsigned int            features;
        unsigned long           retries;
 
+       /*
+        * State transition callback(s): Only one of the two groups should be
+        * defined:
+        * - set_mode(), only for modes <= CLOCK_EVT_MODE_RESUME.
+        * - set_state_{shutdown|periodic|oneshot}(), tick_resume().
+        */
+       void                    (*set_mode)(enum clock_event_mode mode, struct clock_event_device *);
+       int                     (*set_state_periodic)(struct clock_event_device *);
+       int                     (*set_state_oneshot)(struct clock_event_device *);
+       int                     (*set_state_shutdown)(struct clock_event_device *);
+       int                     (*tick_resume)(struct clock_event_device *);
+
        void                    (*broadcast)(const struct cpumask *mask);
-       void                    (*set_mode)(enum clock_event_mode mode,
-                                           struct clock_event_device *);
        void                    (*suspend)(struct clock_event_device *);
        void                    (*resume)(struct clock_event_device *);
        unsigned long           min_delta_ticks;
@@ -136,18 +155,18 @@ struct clock_event_device {
  *
  * factor = (clock_ticks << shift) / nanoseconds
  */
-static inline unsigned long div_sc(unsigned long ticks, unsigned long nsec,
-                                  int shift)
+static inline unsigned long
+div_sc(unsigned long ticks, unsigned long nsec, int shift)
 {
-       uint64_t tmp = ((uint64_t)ticks) << shift;
+       u64 tmp = ((u64)ticks) << shift;
 
        do_div(tmp, nsec);
+
        return (unsigned long) tmp;
 }
 
 /* Clock event layer functions */
-extern u64 clockevent_delta2ns(unsigned long latch,
-                              struct clock_event_device *evt);
+extern u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt);
 extern void clockevents_register_device(struct clock_event_device *dev);
 extern int clockevents_unbind_device(struct clock_event_device *ced, int cpu);
 
@@ -158,57 +177,42 @@ extern void clockevents_config_and_register(struct clock_event_device *dev,
 
 extern int clockevents_update_freq(struct clock_event_device *ce, u32 freq);
 
-extern void clockevents_exchange_device(struct clock_event_device *old,
-                                       struct clock_event_device *new);
-extern void clockevents_set_mode(struct clock_event_device *dev,
-                                enum clock_event_mode mode);
-extern int clockevents_program_event(struct clock_event_device *dev,
-                                    ktime_t expires, bool force);
-
-extern void clockevents_handle_noop(struct clock_event_device *dev);
-
 static inline void
 clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 minsec)
 {
-       return clocks_calc_mult_shift(&ce->mult, &ce->shift, NSEC_PER_SEC,
-                                     freq, minsec);
+       return clocks_calc_mult_shift(&ce->mult, &ce->shift, NSEC_PER_SEC, freq, minsec);
 }
 
 extern void clockevents_suspend(void);
 extern void clockevents_resume(void);
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-#ifdef CONFIG_ARCH_HAS_TICK_BROADCAST
+# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+#  ifdef CONFIG_ARCH_HAS_TICK_BROADCAST
 extern void tick_broadcast(const struct cpumask *mask);
-#else
-#define tick_broadcast NULL
-#endif
+#  else
+#   define tick_broadcast      NULL
+#  endif
 extern int tick_receive_broadcast(void);
-#endif
+# endif
 
-#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
+# if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
 extern void tick_setup_hrtimer_broadcast(void);
 extern int tick_check_broadcast_expired(void);
-#else
+# else
 static inline int tick_check_broadcast_expired(void) { return 0; }
-static inline void tick_setup_hrtimer_broadcast(void) {};
-#endif
+static inline void tick_setup_hrtimer_broadcast(void) { }
+# endif
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern int clockevents_notify(unsigned long reason, void *arg);
-#else
-static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
-#endif
-
-#else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */
 
-static inline void clockevents_suspend(void) {}
-static inline void clockevents_resume(void) {}
+#else /* !CONFIG_GENERIC_CLOCKEVENTS: */
 
+static inline void clockevents_suspend(void) { }
+static inline void clockevents_resume(void) { }
 static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
 static inline int tick_check_broadcast_expired(void) { return 0; }
-static inline void tick_setup_hrtimer_broadcast(void) {};
+static inline void tick_setup_hrtimer_broadcast(void) { }
 
-#endif
+#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
-#endif
+#endif /* _LINUX_CLOCKCHIPS_H */
index 9c78d15d33e4de979b3d70d6a569064aa5529048..135509821c3994f4083bd2f0eb8f7c05409c026c 100644 (file)
@@ -56,6 +56,7 @@ struct module;
  * @shift:             cycle to nanosecond divisor (power of two)
  * @max_idle_ns:       max idle time permitted by the clocksource (nsecs)
  * @maxadj:            maximum adjustment value to mult (~11%)
+ * @max_cycles:                maximum safe cycle value which won't overflow on multiplication
  * @flags:             flags describing special properties
  * @archdata:          arch-specific data
  * @suspend:           suspend function for the clocksource, if necessary
@@ -76,7 +77,7 @@ struct clocksource {
 #ifdef CONFIG_ARCH_CLOCKSOURCE_DATA
        struct arch_clocksource_data archdata;
 #endif
-
+       u64 max_cycles;
        const char *name;
        struct list_head list;
        int rating;
@@ -178,7 +179,6 @@ static inline s64 clocksource_cyc2ns(cycle_t cycles, u32 mult, u32 shift)
 }
 
 
-extern int clocksource_register(struct clocksource*);
 extern int clocksource_unregister(struct clocksource*);
 extern void clocksource_touch_watchdog(void);
 extern struct clocksource* clocksource_get_next(void);
@@ -189,7 +189,7 @@ extern struct clocksource * __init clocksource_default_clock(void);
 extern void clocksource_mark_unstable(struct clocksource *cs);
 
 extern u64
-clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask);
+clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask, u64 *max_cycles);
 extern void
 clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 minsec);
 
@@ -200,7 +200,16 @@ clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 minsec);
 extern int
 __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq);
 extern void
-__clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq);
+__clocksource_update_freq_scale(struct clocksource *cs, u32 scale, u32 freq);
+
+/*
+ * Don't call this unless you are a default clocksource
+ * (AKA: jiffies) and absolutely have to.
+ */
+static inline int __clocksource_register(struct clocksource *cs)
+{
+       return __clocksource_register_scale(cs, 1, 0);
+}
 
 static inline int clocksource_register_hz(struct clocksource *cs, u32 hz)
 {
@@ -212,14 +221,14 @@ static inline int clocksource_register_khz(struct clocksource *cs, u32 khz)
        return __clocksource_register_scale(cs, 1000, khz);
 }
 
-static inline void __clocksource_updatefreq_hz(struct clocksource *cs, u32 hz)
+static inline void __clocksource_update_freq_hz(struct clocksource *cs, u32 hz)
 {
-       __clocksource_updatefreq_scale(cs, 1, hz);
+       __clocksource_update_freq_scale(cs, 1, hz);
 }
 
-static inline void __clocksource_updatefreq_khz(struct clocksource *cs, u32 khz)
+static inline void __clocksource_update_freq_khz(struct clocksource *cs, u32 khz)
 {
-       __clocksource_updatefreq_scale(cs, 1000, khz);
+       __clocksource_update_freq_scale(cs, 1000, khz);
 }
 
 
index 9384ba66e975969fc84e828590293a0930e5c3bd..f7ef093ec49a2bbdd637aae6ab0f1bf0fa4e1e32 100644 (file)
 struct cma;
 
 extern unsigned long totalcma_pages;
-extern phys_addr_t cma_get_base(struct cma *cma);
-extern unsigned long cma_get_size(struct cma *cma);
+extern phys_addr_t cma_get_base(const struct cma *cma);
+extern unsigned long cma_get_size(const struct cma *cma);
 
 extern int __init cma_declare_contiguous(phys_addr_t base,
                        phys_addr_t size, phys_addr_t limit,
                        phys_addr_t alignment, unsigned int order_per_bit,
                        bool fixed, struct cma **res_cma);
-extern int cma_init_reserved_mem(phys_addr_t base,
-                                       phys_addr_t size, int order_per_bit,
+extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
+                                       unsigned int order_per_bit,
                                        struct cma **res_cma);
-extern struct page *cma_alloc(struct cma *cma, int count, unsigned int align);
-extern bool cma_release(struct cma *cma, struct page *pages, int count);
+extern struct page *cma_alloc(struct cma *cma, unsigned int count, unsigned int align);
+extern bool cma_release(struct cma *cma, const struct page *pages, unsigned int count);
 #endif
index 1b45e4a0519b2c34033db91e37fd1f1f0b367f8c..0e41ca0e59275deb33b7c7220dffd1ff39cbb2f7 100644 (file)
@@ -192,29 +192,16 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
 
 #include <uapi/linux/types.h>
 
-static __always_inline void data_access_exceeds_word_size(void)
-#ifdef __compiletime_warning
-__compiletime_warning("data access exceeds word size and won't be atomic")
-#endif
-;
-
-static __always_inline void data_access_exceeds_word_size(void)
-{
-}
-
 static __always_inline void __read_once_size(const volatile void *p, void *res, int size)
 {
        switch (size) {
        case 1: *(__u8 *)res = *(volatile __u8 *)p; break;
        case 2: *(__u16 *)res = *(volatile __u16 *)p; break;
        case 4: *(__u32 *)res = *(volatile __u32 *)p; break;
-#ifdef CONFIG_64BIT
        case 8: *(__u64 *)res = *(volatile __u64 *)p; break;
-#endif
        default:
                barrier();
                __builtin_memcpy((void *)res, (const void *)p, size);
-               data_access_exceeds_word_size();
                barrier();
        }
 }
@@ -225,13 +212,10 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
        case 1: *(volatile __u8 *)p = *(__u8 *)res; break;
        case 2: *(volatile __u16 *)p = *(__u16 *)res; break;
        case 4: *(volatile __u32 *)p = *(__u32 *)res; break;
-#ifdef CONFIG_64BIT
        case 8: *(volatile __u64 *)p = *(__u64 *)res; break;
-#endif
        default:
                barrier();
                __builtin_memcpy((void *)p, (const void *)res, size);
-               data_access_exceeds_word_size();
                barrier();
        }
 }
index 37b81bd51ec0e48ce7ec9c24608aeca3ca92ad36..2821838256b4f728640819f9f81842954261ec03 100644 (file)
@@ -10,6 +10,8 @@
 #ifdef CONFIG_CONTEXT_TRACKING
 extern void context_tracking_cpu_set(int cpu);
 
+extern void context_tracking_enter(enum ctx_state state);
+extern void context_tracking_exit(enum ctx_state state);
 extern void context_tracking_user_enter(void);
 extern void context_tracking_user_exit(void);
 extern void __context_tracking_task_switch(struct task_struct *prev,
@@ -35,7 +37,8 @@ static inline enum ctx_state exception_enter(void)
                return 0;
 
        prev_ctx = this_cpu_read(context_tracking.state);
-       context_tracking_user_exit();
+       if (prev_ctx != CONTEXT_KERNEL)
+               context_tracking_exit(prev_ctx);
 
        return prev_ctx;
 }
@@ -43,8 +46,8 @@ static inline enum ctx_state exception_enter(void)
 static inline void exception_exit(enum ctx_state prev_ctx)
 {
        if (context_tracking_is_enabled()) {
-               if (prev_ctx == IN_USER)
-                       context_tracking_user_enter();
+               if (prev_ctx != CONTEXT_KERNEL)
+                       context_tracking_enter(prev_ctx);
        }
 }
 
@@ -78,10 +81,16 @@ static inline void guest_enter(void)
                vtime_guest_enter(current);
        else
                current->flags |= PF_VCPU;
+
+       if (context_tracking_is_enabled())
+               context_tracking_enter(CONTEXT_GUEST);
 }
 
 static inline void guest_exit(void)
 {
+       if (context_tracking_is_enabled())
+               context_tracking_exit(CONTEXT_GUEST);
+
        if (vtime_accounting_enabled())
                vtime_guest_exit(current);
        else
index 97a81225d037396fb8faae2fa0b3189ee045f7cb..6b7b96a32b753a614ef36ea8bb6c1d5a83641b21 100644 (file)
@@ -13,8 +13,9 @@ struct context_tracking {
         */
        bool active;
        enum ctx_state {
-               IN_KERNEL = 0,
-               IN_USER,
+               CONTEXT_KERNEL = 0,
+               CONTEXT_USER,
+               CONTEXT_GUEST,
        } state;
 };
 
@@ -34,11 +35,13 @@ static inline bool context_tracking_cpu_is_enabled(void)
 
 static inline bool context_tracking_in_user(void)
 {
-       return __this_cpu_read(context_tracking.state) == IN_USER;
+       return __this_cpu_read(context_tracking.state) == CONTEXT_USER;
 }
 #else
 static inline bool context_tracking_in_user(void) { return false; }
 static inline bool context_tracking_active(void) { return false; }
+static inline bool context_tracking_is_enabled(void) { return false; }
+static inline bool context_tracking_cpu_is_enabled(void) { return false; }
 #endif /* CONFIG_CONTEXT_TRACKING */
 
 #endif
index 4260e8594bd77da8d1978ff7ff670c904e870e0e..c0fb6b1b4712c30bdf9f7749fefead8a5a2be622 100644 (file)
@@ -73,6 +73,7 @@ enum {
        /* migration should happen before other stuff but after perf */
        CPU_PRI_PERF            = 20,
        CPU_PRI_MIGRATION       = 10,
+       CPU_PRI_SMPBOOT         = 9,
        /* bring up workqueues before normal notifiers and down after */
        CPU_PRI_WORKQUEUE_UP    = 5,
        CPU_PRI_WORKQUEUE_DOWN  = -5,
@@ -95,6 +96,10 @@ enum {
                                        * Called on the new cpu, just before
                                        * enabling interrupts. Must not sleep,
                                        * must not fail */
+#define CPU_DYING_IDLE         0x000B /* CPU (unsigned)v dying, reached
+                                       * idle loop. */
+#define CPU_BROKEN             0x000C /* CPU (unsigned)v did not die properly,
+                                       * perhaps due to preemption. */
 
 /* Used for CPU hotplug events occurring while tasks are frozen due to a suspend
  * operation in progress
@@ -161,6 +166,7 @@ static inline void __unregister_cpu_notifier(struct notifier_block *nb)
 }
 #endif
 
+void smpboot_thread_init(void);
 int cpu_up(unsigned int cpu);
 void notify_cpu_starting(unsigned int cpu);
 extern void cpu_maps_update_begin(void);
@@ -208,6 +214,10 @@ static inline void cpu_notifier_register_done(void)
 {
 }
 
+static inline void smpboot_thread_init(void)
+{
+}
+
 #endif /* CONFIG_SMP */
 extern struct bus_type cpu_subsys;
 
@@ -271,4 +281,14 @@ void arch_cpu_idle_enter(void);
 void arch_cpu_idle_exit(void);
 void arch_cpu_idle_dead(void);
 
+DECLARE_PER_CPU(bool, cpu_dead_idle);
+
+int cpu_report_state(int cpu);
+int cpu_check_up_prepare(int cpu);
+void cpu_set_state_online(int cpu);
+#ifdef CONFIG_HOTPLUG_CPU
+bool cpu_wait_death(unsigned int cpu, int seconds);
+bool cpu_report_death(void);
+#endif /* #ifdef CONFIG_HOTPLUG_CPU */
+
 #endif /* _LINUX_CPU_H_ */
index 306178d7309f193cb32443f49c888297ffa9573e..9c5e892547961544eae22a53669ba600e5ad4973 100644 (file)
@@ -77,7 +77,6 @@ struct cpuidle_device {
        unsigned int            cpu;
 
        int                     last_residency;
-       int                     state_count;
        struct cpuidle_state_usage      states_usage[CPUIDLE_STATE_MAX];
        struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
        struct cpuidle_driver_kobj *kobj_driver;
index 0eb8ee2dc6d1d7dcc50c9284d3bac4f60d1f4f74..f3f2c7e38060245e8e40df56d9d924168c795abd 100644 (file)
@@ -916,6 +916,13 @@ static inline void device_lock_assert(struct device *dev)
        lockdep_assert_held(&dev->mutex);
 }
 
+static inline struct device_node *dev_of_node(struct device *dev)
+{
+       if (!IS_ENABLED(CONFIG_OF))
+               return NULL;
+       return dev->of_node;
+}
+
 void driver_init(void);
 
 /*
index 022e34fcbd1bf6b56cb5f0dbb250a28885797f80..52456aa566a05eded5d61eac974b237e00c26ce9 100644 (file)
@@ -14,6 +14,8 @@
 #include <asm/io.h>
 #include <asm/scatterlist.h>
 
+struct device;
+
 struct dma_pool *dma_pool_create(const char *name, struct device *dev, 
                        size_t size, size_t align, size_t allocation);
 
index cf7e431cbc730dff0ef445dc48989bf5156a09ac..af5be0368dec26c934565e634c0dc803958ed2cc 100644 (file)
@@ -942,6 +942,7 @@ extern int __init efi_setup_pcdp_console(char *);
 #define EFI_64BIT              5       /* Is the firmware 64-bit? */
 #define EFI_PARAVIRT           6       /* Access is via a paravirt interface */
 #define EFI_ARCH_1             7       /* First arch-specific bit */
+#define EFI_DBG                        8       /* Print additional debug info at runtime */
 
 #ifdef CONFIG_EFI
 /*
diff --git a/include/linux/elf-randomize.h b/include/linux/elf-randomize.h
new file mode 100644 (file)
index 0000000..b5f0bda
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _ELF_RANDOMIZE_H
+#define _ELF_RANDOMIZE_H
+
+struct mm_struct;
+
+#ifndef CONFIG_ARCH_HAS_ELF_RANDOMIZE
+static inline unsigned long arch_mmap_rnd(void) { return 0; }
+# if defined(arch_randomize_brk) && defined(CONFIG_COMPAT_BRK)
+#  define compat_brk_randomized
+# endif
+# ifndef arch_randomize_brk
+#  define arch_randomize_brk(mm)       (mm->brk)
+# endif
+#else
+extern unsigned long arch_mmap_rnd(void);
+extern unsigned long arch_randomize_brk(struct mm_struct *mm);
+# ifdef CONFIG_COMPAT_BRK
+#  define compat_brk_randomized
+# endif
+#endif
+
+#endif
index f4131e8ead74965a73272949b3a9eae8fa08b5c7..d502e5436c847530e7a7acd476cc85bd24434edf 100644 (file)
@@ -314,6 +314,28 @@ struct page;
 struct address_space;
 struct writeback_control;
 
+#define IOCB_EVENTFD           (1 << 0)
+
+struct kiocb {
+       struct file             *ki_filp;
+       loff_t                  ki_pos;
+       void (*ki_complete)(struct kiocb *iocb, long ret, long ret2);
+       void                    *private;
+       int                     ki_flags;
+};
+
+static inline bool is_sync_kiocb(struct kiocb *kiocb)
+{
+       return kiocb->ki_complete == NULL;
+}
+
+static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
+{
+       *kiocb = (struct kiocb) {
+               .ki_filp = filp,
+       };
+}
+
 /*
  * "descriptor" for what we're up to with a read.
  * This allows us to use the same read code yet
@@ -1549,7 +1571,7 @@ struct file_operations {
        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
        long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
        int (*mmap) (struct file *, struct vm_area_struct *);
-       void (*mremap)(struct file *, struct vm_area_struct *);
+       int (*mremap)(struct file *, struct vm_area_struct *);
        int (*open) (struct inode *, struct file *);
        int (*flush) (struct file *, fl_owner_t id);
        int (*release) (struct inode *, struct file *);
@@ -2145,7 +2167,7 @@ struct filename {
        const __user char       *uptr;  /* original userland pointer */
        struct audit_names      *aname;
        int                     refcnt;
-       bool                    separate; /* should "name" be freed? */
+       const char              iname[];
 };
 
 extern long vfs_truncate(struct path *, loff_t);
index c674ee8f7fca508c24f172a72e8c055b8fc4ec24..46e83c2156c667c785fd869a8626e5df44f9c282 100644 (file)
@@ -13,6 +13,7 @@ struct trace_array;
 struct trace_buffer;
 struct tracer;
 struct dentry;
+struct bpf_prog;
 
 struct trace_print_flags {
        unsigned long           mask;
@@ -202,7 +203,7 @@ enum trace_reg {
 struct ftrace_event_call;
 
 struct ftrace_event_class {
-       char                    *system;
+       const char              *system;
        void                    *probe;
 #ifdef CONFIG_PERF_EVENTS
        void                    *perf_probe;
@@ -252,6 +253,7 @@ enum {
        TRACE_EVENT_FL_WAS_ENABLED_BIT,
        TRACE_EVENT_FL_USE_CALL_FILTER_BIT,
        TRACE_EVENT_FL_TRACEPOINT_BIT,
+       TRACE_EVENT_FL_KPROBE_BIT,
 };
 
 /*
@@ -265,6 +267,7 @@ enum {
  *                     it is best to clear the buffers that used it).
  *  USE_CALL_FILTER - For ftrace internal events, don't use file filter
  *  TRACEPOINT    - Event is a tracepoint
+ *  KPROBE        - Event is a kprobe
  */
 enum {
        TRACE_EVENT_FL_FILTERED         = (1 << TRACE_EVENT_FL_FILTERED_BIT),
@@ -274,6 +277,7 @@ enum {
        TRACE_EVENT_FL_WAS_ENABLED      = (1 << TRACE_EVENT_FL_WAS_ENABLED_BIT),
        TRACE_EVENT_FL_USE_CALL_FILTER  = (1 << TRACE_EVENT_FL_USE_CALL_FILTER_BIT),
        TRACE_EVENT_FL_TRACEPOINT       = (1 << TRACE_EVENT_FL_TRACEPOINT_BIT),
+       TRACE_EVENT_FL_KPROBE           = (1 << TRACE_EVENT_FL_KPROBE_BIT),
 };
 
 struct ftrace_event_call {
@@ -285,7 +289,7 @@ struct ftrace_event_call {
                struct tracepoint       *tp;
        };
        struct trace_event      event;
-       const char              *print_fmt;
+       char                    *print_fmt;
        struct event_filter     *filter;
        void                    *mod;
        void                    *data;
@@ -303,6 +307,7 @@ struct ftrace_event_call {
 #ifdef CONFIG_PERF_EVENTS
        int                             perf_refcount;
        struct hlist_head __percpu      *perf_events;
+       struct bpf_prog                 *prog;
 
        int     (*perf_perm)(struct ftrace_event_call *,
                             struct perf_event *);
@@ -548,6 +553,15 @@ event_trigger_unlock_commit_regs(struct ftrace_event_file *file,
                event_triggers_post_call(file, tt);
 }
 
+#ifdef CONFIG_BPF_SYSCALL
+unsigned int trace_call_bpf(struct bpf_prog *prog, void *ctx);
+#else
+static inline unsigned int trace_call_bpf(struct bpf_prog *prog, void *ctx)
+{
+       return 1;
+}
+#endif
+
 enum {
        FILTER_OTHER = 0,
        FILTER_STATIC_STRING,
index 51bd1e72a91710308184e6fb35c16ec6c2caf906..97a9373e61e80d048ee6259eb4962bd831cac822 100644 (file)
@@ -57,8 +57,10 @@ struct vm_area_struct;
  * _might_ fail.  This depends upon the particular VM implementation.
  *
  * __GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
- * cannot handle allocation failures.  This modifier is deprecated and no new
- * users should be added.
+ * cannot handle allocation failures. New users should be evaluated carefully
+ * (and the flag should be used only when there is no reasonable failure policy)
+ * but it is definitely preferable to use the flag rather than opencode endless
+ * loop around allocator.
  *
  * __GFP_NORETRY: The VM implementation must not retry indefinitely.
  *
@@ -117,16 +119,6 @@ struct vm_area_struct;
                         __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN | \
                         __GFP_NO_KSWAPD)
 
-/*
- * GFP_THISNODE does not perform any reclaim, you most likely want to
- * use __GFP_THISNODE to allocate from a given node without fallback!
- */
-#ifdef CONFIG_NUMA
-#define GFP_THISNODE   (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
-#else
-#define GFP_THISNODE   ((__force gfp_t)0)
-#endif
-
 /* This mask makes up all the page movable related flags */
 #define GFP_MOVABLE_MASK (__GFP_RECLAIMABLE|__GFP_MOVABLE)
 
index cba442ec3c66583a7aceefbbc9ff9eca5fee1563..f4af03404b9789805e06638303a8873aa14fe5a8 100644 (file)
@@ -9,7 +9,7 @@
 
 
 extern void synchronize_irq(unsigned int irq);
-extern void synchronize_hardirq(unsigned int irq);
+extern bool synchronize_hardirq(unsigned int irq);
 
 #if defined(CONFIG_TINY_RCU)
 
index 4173a8fdad9efd052870b8738547ac1fa1962526..0408421d885f9433c61149e2769bdd3c08192522 100644 (file)
@@ -48,20 +48,44 @@ struct hid_sensor_hub_attribute_info {
        s32 logical_maximum;
 };
 
+/**
+ * struct sensor_hub_pending - Synchronous read pending information
+ * @status:            Pending status true/false.
+ * @ready:             Completion synchronization data.
+ * @usage_id:          Usage id for physical device, E.g. Gyro usage id.
+ * @attr_usage_id:     Usage Id of a field, E.g. X-AXIS for a gyro.
+ * @raw_size:          Response size for a read request.
+ * @raw_data:          Place holder for received response.
+ */
+struct sensor_hub_pending {
+       bool status;
+       struct completion ready;
+       u32 usage_id;
+       u32 attr_usage_id;
+       int raw_size;
+       u8  *raw_data;
+};
+
 /**
  * struct hid_sensor_hub_device - Stores the hub instance data
  * @hdev:              Stores the hid instance.
  * @vendor_id:         Vendor id of hub device.
  * @product_id:                Product id of hub device.
+ * @usage:             Usage id for this hub device instance.
  * @start_collection_index: Starting index for a phy type collection
  * @end_collection_index: Last index for a phy type collection
+ * @mutex:             synchronizing mutex.
+ * @pending:           Holds information of pending sync read request.
  */
 struct hid_sensor_hub_device {
        struct hid_device *hdev;
        u32 vendor_id;
        u32 product_id;
+       u32 usage;
        int start_collection_index;
        int end_collection_index;
+       struct mutex mutex;
+       struct sensor_hub_pending pending;
 };
 
 /**
@@ -152,40 +176,51 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
 * @usage_id:   Attribute usage id of parent physical device as per spec
 * @attr_usage_id:      Attribute usage id as per spec
 * @report_id:  Report id to look for
+* @flag:      Synchronous or asynchronous read
 *
-* Issues a synchronous read request for an input attribute. Returns
-* data upto 32 bits. Since client can get events, so this call should
-* not be used for data paths, this will impact performance.
+* Issues a synchronous or asynchronous read request for an input attribute.
+* Returns data upto 32 bits.
 */
 
+enum sensor_hub_read_flags {
+       SENSOR_HUB_SYNC,
+       SENSOR_HUB_ASYNC,
+};
+
 int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
-                       u32 usage_id,
-                       u32 attr_usage_id, u32 report_id);
+                                       u32 usage_id,
+                                       u32 attr_usage_id, u32 report_id,
+                                       enum sensor_hub_read_flags flag
+);
+
 /**
 * sensor_hub_set_feature() - Feature set request
 * @hsdev:      Hub device instance.
 * @report_id:  Report id to look for
 * @field_index:        Field index inside a report
-* @value:      Value to set
+* @buffer_size: size of the buffer
+* @buffer:     buffer to use in the feature set
 *
 * Used to set a field in feature report. For example this can set polling
 * interval, sensitivity, activate/deactivate state.
 */
 int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
-                       u32 field_index, s32 value);
+                          u32 field_index, int buffer_size, void *buffer);
 
 /**
 * sensor_hub_get_feature() - Feature get request
 * @hsdev:      Hub device instance.
 * @report_id:  Report id to look for
 * @field_index:        Field index inside a report
-* @value:      Place holder for return value
+* @buffer_size:        size of the buffer
+* @buffer:     buffer to copy output
 *
 * Used to get a field in feature report. For example this can get polling
-* interval, sensitivity, activate/deactivate state.
+* interval, sensitivity, activate/deactivate state. On success it returns
+* number of bytes copied to buffer. On failure, it returns value < 0.
 */
 int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
-                       u32 field_index, s32 *value);
+                          u32 field_index, int buffer_size, void *buffer);
 
 /* hid-sensor-attributes */
 
index 109f0e633e01f176f4937e3838834cbff2d33b67..f2ee90aed0c2e8f00cdb9d5bbbece61e4b325397 100644 (file)
@@ -21,6 +21,8 @@
 
 #define HID_MAX_PHY_DEVICES                                    0xFF
 
+#define HID_USAGE_SENSOR_COLLECTION                            0x200001
+
 /* Accel 3D (200073) */
 #define HID_USAGE_SENSOR_ACCEL_3D                              0x200073
 #define HID_USAGE_SENSOR_DATA_ACCELERATION                     0x200452
index efc7787a41a8c75db5b89509e8ec4051d019038a..176b43670e5da9f7de6c906a56dfb007f0b160cf 100644 (file)
@@ -159,6 +159,7 @@ struct hid_item {
 #define HID_UP_LED             0x00080000
 #define HID_UP_BUTTON          0x00090000
 #define HID_UP_ORDINAL         0x000a0000
+#define HID_UP_TELEPHONY       0x000b0000
 #define HID_UP_CONSUMER                0x000c0000
 #define HID_UP_DIGITIZER       0x000d0000
 #define HID_UP_PID             0x000f0000
@@ -269,6 +270,7 @@ struct hid_item {
 #define HID_DG_DEVICEINDEX     0x000d0053
 #define HID_DG_CONTACTCOUNT    0x000d0054
 #define HID_DG_CONTACTMAX      0x000d0055
+#define HID_DG_BUTTONTYPE      0x000d0059
 #define HID_DG_BARRELSWITCH2   0x000d005a
 #define HID_DG_TOOLSERIALNUMBER        0x000d005b
 
@@ -514,10 +516,10 @@ struct hid_device {                                                       /* device report descriptor */
 #ifdef CONFIG_HID_BATTERY_STRENGTH
        /*
         * Power supply information for HID devices which report
-        * battery strength. power_supply is registered iff
-        * battery.name is non-NULL.
+        * battery strength. power_supply was successfully registered if
+        * battery is non-NULL.
         */
-       struct power_supply battery;
+       struct power_supply *battery;
        __s32 battery_min;
        __s32 battery_max;
        __s32 battery_report_type;
index f17da50402a4dad6bf4d4aa907a32e8df1d7dea7..898033f41d767dda360b6a1d0a4b8361c8a1a5a3 100644 (file)
@@ -253,10 +253,10 @@ static inline void i2c_set_clientdata(struct i2c_client *dev, void *data)
 
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
 enum i2c_slave_event {
-       I2C_SLAVE_REQ_READ_START,
-       I2C_SLAVE_REQ_READ_END,
-       I2C_SLAVE_REQ_WRITE_START,
-       I2C_SLAVE_REQ_WRITE_END,
+       I2C_SLAVE_READ_REQUESTED,
+       I2C_SLAVE_WRITE_REQUESTED,
+       I2C_SLAVE_READ_PROCESSED,
+       I2C_SLAVE_WRITE_RECEIVED,
        I2C_SLAVE_STOP,
 };
 
@@ -435,8 +435,8 @@ struct i2c_bus_recovery_info {
        void (*set_scl)(struct i2c_adapter *, int val);
        int (*get_sda)(struct i2c_adapter *);
 
-       void (*prepare_recovery)(struct i2c_bus_recovery_info *bri);
-       void (*unprepare_recovery)(struct i2c_bus_recovery_info *bri);
+       void (*prepare_recovery)(struct i2c_adapter *);
+       void (*unprepare_recovery)(struct i2c_adapter *);
 
        /* gpio recovery */
        int scl_gpio;
@@ -449,6 +449,48 @@ int i2c_recover_bus(struct i2c_adapter *adap);
 int i2c_generic_gpio_recovery(struct i2c_adapter *adap);
 int i2c_generic_scl_recovery(struct i2c_adapter *adap);
 
+/**
+ * struct i2c_adapter_quirks - describe flaws of an i2c adapter
+ * @flags: see I2C_AQ_* for possible flags and read below
+ * @max_num_msgs: maximum number of messages per transfer
+ * @max_write_len: maximum length of a write message
+ * @max_read_len: maximum length of a read message
+ * @max_comb_1st_msg_len: maximum length of the first msg in a combined message
+ * @max_comb_2nd_msg_len: maximum length of the second msg in a combined message
+ *
+ * Note about combined messages: Some I2C controllers can only send one message
+ * per transfer, plus something called combined message or write-then-read.
+ * This is (usually) a small write message followed by a read message and
+ * barely enough to access register based devices like EEPROMs. There is a flag
+ * to support this mode. It implies max_num_msg = 2 and does the length checks
+ * with max_comb_*_len because combined message mode usually has its own
+ * limitations. Because of HW implementations, some controllers can actually do
+ * write-then-anything or other variants. To support that, write-then-read has
+ * been broken out into smaller bits like write-first and read-second which can
+ * be combined as needed.
+ */
+
+struct i2c_adapter_quirks {
+       u64 flags;
+       int max_num_msgs;
+       u16 max_write_len;
+       u16 max_read_len;
+       u16 max_comb_1st_msg_len;
+       u16 max_comb_2nd_msg_len;
+};
+
+/* enforce max_num_msgs = 2 and use max_comb_*_len for length checks */
+#define I2C_AQ_COMB                    BIT(0)
+/* first combined message must be write */
+#define I2C_AQ_COMB_WRITE_FIRST                BIT(1)
+/* second combined message must be read */
+#define I2C_AQ_COMB_READ_SECOND                BIT(2)
+/* both combined messages must have the same target address */
+#define I2C_AQ_COMB_SAME_ADDR          BIT(3)
+/* convenience macro for typical write-then read case */
+#define I2C_AQ_COMB_WRITE_THEN_READ    (I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | \
+                                        I2C_AQ_COMB_READ_SECOND | I2C_AQ_COMB_SAME_ADDR)
+
 /*
  * i2c_adapter is the structure used to identify a physical i2c bus along
  * with the access algorithms necessary to access it.
@@ -474,6 +516,7 @@ struct i2c_adapter {
        struct list_head userspace_clients;
 
        struct i2c_bus_recovery_info *bus_recovery_info;
+       const struct i2c_adapter_quirks *quirks;
 };
 #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
 
index b65850a411274b33d2d8aa4430607dd7d45deeae..eb8622b78ec900e130c701a8128865a327c67c90 100644 (file)
@@ -21,8 +21,8 @@ struct iio_buffer;
  * struct iio_buffer_access_funcs - access functions for buffers.
  * @store_to:          actually store stuff to the buffer
  * @read_first_n:      try to get a specified number of bytes (must exist)
- * @data_available:    indicates whether data for reading from the buffer is
- *                     available.
+ * @data_available:    indicates how much data is available for reading from
+ *                     the buffer.
  * @request_update:    if a parameter change has been marked, update underlying
  *                     storage.
  * @set_bytes_per_datum:set number of bytes per datum
@@ -43,7 +43,7 @@ struct iio_buffer_access_funcs {
        int (*read_first_n)(struct iio_buffer *buffer,
                            size_t n,
                            char __user *buf);
-       bool (*data_available)(struct iio_buffer *buffer);
+       size_t (*data_available)(struct iio_buffer *buffer);
 
        int (*request_update)(struct iio_buffer *buffer);
 
@@ -72,6 +72,7 @@ struct iio_buffer_access_funcs {
  * @demux_bounce:      [INTERN] buffer for doing gather from incoming scan.
  * @buffer_list:       [INTERN] entry in the devices list of current buffers.
  * @ref:               [INTERN] reference count of the buffer.
+ * @watermark:         [INTERN] number of datums to wait for poll/read.
  */
 struct iio_buffer {
        int                                     length;
@@ -90,6 +91,7 @@ struct iio_buffer {
        void                                    *demux_bounce;
        struct list_head                        buffer_list;
        struct kref                             ref;
+       unsigned int                            watermark;
 };
 
 /**
index f6d1d252f08d31dadc33279aa1c6219b96f65c32..7668716cd73cb39fb09b993e35e0e3bdb74a7176 100644 (file)
@@ -9,7 +9,7 @@
 #define IIO_DAC_MAX517_H_
 
 struct max517_platform_data {
-       u16                             vref_mv[2];
+       u16                             vref_mv[8];
 };
 
 #endif /* IIO_DAC_MAX517_H_ */
index 03fa332ad2a8cec4e26c212b9333e56f0c6d6169..8ad87d1c5340bedf557bd498fcc03b10a123a8e9 100644 (file)
@@ -9,22 +9,8 @@
 #ifndef _IIO_EVENTS_H_
 #define _IIO_EVENTS_H_
 
-#include <linux/ioctl.h>
-#include <linux/types.h>
 #include <linux/iio/types.h>
-
-/**
- * struct iio_event_data - The actual event being pushed to userspace
- * @id:                event identifier
- * @timestamp: best estimate of time of event occurrence (often from
- *             the interrupt handler)
- */
-struct iio_event_data {
-       __u64   id;
-       __s64   timestamp;
-};
-
-#define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int)
+#include <uapi/linux/iio/events.h>
 
 /**
  * IIO_EVENT_CODE() - create event identifier
@@ -70,18 +56,4 @@ struct iio_event_data {
 #define IIO_UNMOD_EVENT_CODE(chan_type, number, type, direction)       \
        IIO_EVENT_CODE(chan_type, 0, 0, direction, type, number, 0, 0)
 
-#define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF)
-
-#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0x7F)
-
-#define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF)
-
-/* Event code number extraction depends on which type of event we have.
- * Perhaps review this function in the future*/
-#define IIO_EVENT_CODE_EXTRACT_CHAN(mask) ((__s16)(mask & 0xFFFF))
-#define IIO_EVENT_CODE_EXTRACT_CHAN2(mask) ((__s16)(((mask) >> 16) & 0xFFFF))
-
-#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF)
-#define IIO_EVENT_CODE_EXTRACT_DIFF(mask) (((mask) >> 55) & 0x1)
-
 #endif
index 80d8550610646fdc25aef65d93efde6ae9343341..d86b753e9b30166e0c370845145ac59d2b863a32 100644 (file)
@@ -338,6 +338,16 @@ struct iio_dev;
  *                     provide a custom of_xlate function that reads the
  *                     *args* and returns the appropriate index in registered
  *                     IIO channels array.
+ * @hwfifo_set_watermark: function pointer to set the current hardware
+ *                     fifo watermark level; see hwfifo_* entries in
+ *                     Documentation/ABI/testing/sysfs-bus-iio for details on
+ *                     how the hardware fifo operates
+ * @hwfifo_flush_to_buffer: function pointer to flush the samples stored
+ *                     in the hardware fifo to the device buffer. The driver
+ *                     should not flush more than count samples. The function
+ *                     must return the number of samples flushed, 0 if no
+ *                     samples were flushed or a negative integer if no samples
+ *                     were flushed and there was an error.
  **/
 struct iio_info {
        struct module                   *driver_module;
@@ -399,6 +409,9 @@ struct iio_info {
                                  unsigned *readval);
        int (*of_xlate)(struct iio_dev *indio_dev,
                        const struct of_phandle_args *iiospec);
+       int (*hwfifo_set_watermark)(struct iio_dev *indio_dev, unsigned val);
+       int (*hwfifo_flush_to_buffer)(struct iio_dev *indio_dev,
+                                     unsigned count);
 };
 
 /**
index 580ed5bdb3fa9c0cdca4cfc29105f26c5de7ba95..942b6de68e2f3882ec17fbcebfa1e32e27204b0e 100644 (file)
 #ifndef _IIO_TYPES_H_
 #define _IIO_TYPES_H_
 
-enum iio_chan_type {
-       IIO_VOLTAGE,
-       IIO_CURRENT,
-       IIO_POWER,
-       IIO_ACCEL,
-       IIO_ANGL_VEL,
-       IIO_MAGN,
-       IIO_LIGHT,
-       IIO_INTENSITY,
-       IIO_PROXIMITY,
-       IIO_TEMP,
-       IIO_INCLI,
-       IIO_ROT,
-       IIO_ANGL,
-       IIO_TIMESTAMP,
-       IIO_CAPACITANCE,
-       IIO_ALTVOLTAGE,
-       IIO_CCT,
-       IIO_PRESSURE,
-       IIO_HUMIDITYRELATIVE,
-       IIO_ACTIVITY,
-       IIO_STEPS,
-       IIO_ENERGY,
-       IIO_DISTANCE,
-       IIO_VELOCITY,
-};
-
-enum iio_modifier {
-       IIO_NO_MOD,
-       IIO_MOD_X,
-       IIO_MOD_Y,
-       IIO_MOD_Z,
-       IIO_MOD_X_AND_Y,
-       IIO_MOD_X_AND_Z,
-       IIO_MOD_Y_AND_Z,
-       IIO_MOD_X_AND_Y_AND_Z,
-       IIO_MOD_X_OR_Y,
-       IIO_MOD_X_OR_Z,
-       IIO_MOD_Y_OR_Z,
-       IIO_MOD_X_OR_Y_OR_Z,
-       IIO_MOD_LIGHT_BOTH,
-       IIO_MOD_LIGHT_IR,
-       IIO_MOD_ROOT_SUM_SQUARED_X_Y,
-       IIO_MOD_SUM_SQUARED_X_Y_Z,
-       IIO_MOD_LIGHT_CLEAR,
-       IIO_MOD_LIGHT_RED,
-       IIO_MOD_LIGHT_GREEN,
-       IIO_MOD_LIGHT_BLUE,
-       IIO_MOD_QUATERNION,
-       IIO_MOD_TEMP_AMBIENT,
-       IIO_MOD_TEMP_OBJECT,
-       IIO_MOD_NORTH_MAGN,
-       IIO_MOD_NORTH_TRUE,
-       IIO_MOD_NORTH_MAGN_TILT_COMP,
-       IIO_MOD_NORTH_TRUE_TILT_COMP,
-       IIO_MOD_RUNNING,
-       IIO_MOD_JOGGING,
-       IIO_MOD_WALKING,
-       IIO_MOD_STILL,
-       IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z,
-};
-
-enum iio_event_type {
-       IIO_EV_TYPE_THRESH,
-       IIO_EV_TYPE_MAG,
-       IIO_EV_TYPE_ROC,
-       IIO_EV_TYPE_THRESH_ADAPTIVE,
-       IIO_EV_TYPE_MAG_ADAPTIVE,
-       IIO_EV_TYPE_CHANGE,
-};
+#include <uapi/linux/iio/types.h>
 
 enum iio_event_info {
        IIO_EV_INFO_ENABLE,
@@ -88,13 +19,6 @@ enum iio_event_info {
        IIO_EV_INFO_PERIOD,
 };
 
-enum iio_event_direction {
-       IIO_EV_DIR_EITHER,
-       IIO_EV_DIR_RISING,
-       IIO_EV_DIR_FALLING,
-       IIO_EV_DIR_NONE,
-};
-
 #define IIO_VAL_INT 1
 #define IIO_VAL_INT_PLUS_MICRO 2
 #define IIO_VAL_INT_PLUS_NANO 3
index 2df8e8dd10a483d55d723b6ac4875de807ab2044..21b6d768edd7a4e0f1aee98ed9f437000fa1b996 100644 (file)
@@ -253,21 +253,41 @@ struct obs_kernel_param {
  * obs_kernel_param "array" too far apart in .init.setup.
  */
 #define __setup_param(str, unique_id, fn, early)                       \
-       static const char __setup_str_##unique_id[] __initconst \
-               __aligned(1) = str; \
-       static struct obs_kernel_param __setup_##unique_id      \
-               __used __section(.init.setup)                   \
-               __attribute__((aligned((sizeof(long)))))        \
+       static const char __setup_str_##unique_id[] __initconst         \
+               __aligned(1) = str;                                     \
+       static struct obs_kernel_param __setup_##unique_id              \
+               __used __section(.init.setup)                           \
+               __attribute__((aligned((sizeof(long)))))                \
                = { __setup_str_##unique_id, fn, early }
 
-#define __setup(str, fn)                                       \
+#define __setup(str, fn)                                               \
        __setup_param(str, fn, fn, 0)
 
-/* NOTE: fn is as per module_param, not __setup!  Emits warning if fn
- * returns non-zero. */
-#define early_param(str, fn)                                   \
+/*
+ * NOTE: fn is as per module_param, not __setup!
+ * Emits warning if fn returns non-zero.
+ */
+#define early_param(str, fn)                                           \
        __setup_param(str, fn, fn, 1)
 
+#define early_param_on_off(str_on, str_off, var, config)               \
+                                                                       \
+       int var = IS_ENABLED(config);                                   \
+                                                                       \
+       static int __init parse_##var##_on(char *arg)                   \
+       {                                                               \
+               var = 1;                                                \
+               return 0;                                               \
+       }                                                               \
+       __setup_param(str_on, parse_##var##_on, parse_##var##_on, 1);   \
+                                                                       \
+       static int __init parse_##var##_off(char *arg)                  \
+       {                                                               \
+               var = 0;                                                \
+               return 0;                                               \
+       }                                                               \
+       __setup_param(str_off, parse_##var##_off, parse_##var##_off, 1)
+
 /* Relies on boot_command_line being set */
 void __init parse_early_param(void);
 void __init parse_early_options(char *cmdline);
diff --git a/include/linux/intel_mid_dma.h b/include/linux/intel_mid_dma.h
deleted file mode 100644 (file)
index 10496bd..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *  intel_mid_dma.h - Intel MID DMA Drivers
- *
- *  Copyright (C) 2008-10 Intel Corp
- *  Author: Vinod Koul <vinod.koul@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *
- */
-#ifndef __INTEL_MID_DMA_H__
-#define __INTEL_MID_DMA_H__
-
-#include <linux/dmaengine.h>
-
-#define DMA_PREP_CIRCULAR_LIST         (1 << 10)
-
-/*DMA mode configurations*/
-enum intel_mid_dma_mode {
-       LNW_DMA_PER_TO_MEM = 0, /*periphral to memory configuration*/
-       LNW_DMA_MEM_TO_PER,     /*memory to periphral configuration*/
-       LNW_DMA_MEM_TO_MEM,     /*mem to mem confg (testing only)*/
-};
-
-/*DMA handshaking*/
-enum intel_mid_dma_hs_mode {
-       LNW_DMA_HW_HS = 0,      /*HW Handshaking only*/
-       LNW_DMA_SW_HS = 1,      /*SW Handshaking not recommended*/
-};
-
-/*Burst size configuration*/
-enum intel_mid_dma_msize {
-       LNW_DMA_MSIZE_1 = 0x0,
-       LNW_DMA_MSIZE_4 = 0x1,
-       LNW_DMA_MSIZE_8 = 0x2,
-       LNW_DMA_MSIZE_16 = 0x3,
-       LNW_DMA_MSIZE_32 = 0x4,
-       LNW_DMA_MSIZE_64 = 0x5,
-};
-
-/**
- * struct intel_mid_dma_slave - DMA slave structure
- *
- * @dirn: DMA trf direction
- * @src_width: tx register width
- * @dst_width: rx register width
- * @hs_mode: HW/SW handshaking mode
- * @cfg_mode: DMA data transfer mode (per-per/mem-per/mem-mem)
- * @src_msize: Source DMA burst size
- * @dst_msize: Dst DMA burst size
- * @per_addr: Periphral address
- * @device_instance: DMA peripheral device instance, we can have multiple
- *             peripheral device connected to single DMAC
- */
-struct intel_mid_dma_slave {
-       enum intel_mid_dma_hs_mode      hs_mode;  /*handshaking*/
-       enum intel_mid_dma_mode         cfg_mode; /*mode configuration*/
-       unsigned int            device_instance; /*0, 1 for periphral instance*/
-       struct dma_slave_config         dma_slave;
-};
-
-#endif /*__INTEL_MID_DMA_H__*/
index 2e88580194f0238430de1255c5a63f99bf975e0a..950ae45018260224c9138b043f9071ce4d1f9acc 100644 (file)
@@ -39,8 +39,6 @@
  * These flags used only by the kernel as part of the
  * irq handling routines.
  *
- * IRQF_DISABLED - keep irqs disabled when calling the action handler.
- *                 DEPRECATED. This flag is a NOOP and scheduled to be removed
  * IRQF_SHARED - allow sharing the irq among several devices
  * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
  * IRQF_TIMER - Flag to mark this interrupt as timer interrupt
@@ -64,7 +62,6 @@
  *                wakeup devices users need to implement wakeup detection in
  *                their interrupt handlers.
  */
-#define IRQF_DISABLED          0x00000020
 #define IRQF_SHARED            0x00000080
 #define IRQF_PROBE_SHARED      0x00000100
 #define __IRQF_TIMER           0x00000200
@@ -191,6 +188,7 @@ extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id);
 #endif
 
 extern void disable_irq_nosync(unsigned int irq);
+extern bool disable_hardirq(unsigned int irq);
 extern void disable_irq(unsigned int irq);
 extern void disable_percpu_irq(unsigned int irq);
 extern void enable_irq(unsigned int irq);
@@ -363,6 +361,20 @@ static inline int disable_irq_wake(unsigned int irq)
        return irq_set_irq_wake(irq, 0);
 }
 
+/*
+ * irq_get_irqchip_state/irq_set_irqchip_state specific flags
+ */
+enum irqchip_irq_state {
+       IRQCHIP_STATE_PENDING,          /* Is interrupt pending? */
+       IRQCHIP_STATE_ACTIVE,           /* Is interrupt in progress? */
+       IRQCHIP_STATE_MASKED,           /* Is interrupt masked? */
+       IRQCHIP_STATE_LINE_LEVEL,       /* Is IRQ line high? */
+};
+
+extern int irq_get_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
+                                bool *state);
+extern int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
+                                bool state);
 
 #ifdef CONFIG_IRQ_FORCED_THREADING
 extern bool force_irqthreads;
index fa02e55e5a2e1e2ea564829e1025a09d0722e4e2..4cc299c598e0309919fe7e70162efba6a2a355e3 100644 (file)
@@ -38,6 +38,14 @@ static inline int ioremap_page_range(unsigned long addr, unsigned long end,
 }
 #endif
 
+#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
+void __init ioremap_huge_init(void);
+int arch_ioremap_pud_supported(void);
+int arch_ioremap_pmd_supported(void);
+#else
+static inline void ioremap_huge_init(void) { }
+#endif
+
 /*
  * Managed iomap interface
  */
index d09ec7a1243e767dd95df2a4cc1d54775da0eb25..62c6901cab550d7f57039c5b7052fc08bbe0964d 100644 (file)
@@ -30,6 +30,7 @@
 struct seq_file;
 struct module;
 struct msi_msg;
+enum irqchip_irq_state;
 
 /*
  * IRQ line status.
@@ -324,6 +325,8 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
  *                             irq_request_resources
  * @irq_compose_msi_msg:       optional to compose message content for MSI
  * @irq_write_msi_msg: optional to write message content for MSI
+ * @irq_get_irqchip_state:     return the internal state of an interrupt
+ * @irq_set_irqchip_state:     set the internal state of a interrupt
  * @flags:             chip specific flags
  */
 struct irq_chip {
@@ -363,6 +366,9 @@ struct irq_chip {
        void            (*irq_compose_msi_msg)(struct irq_data *data, struct msi_msg *msg);
        void            (*irq_write_msi_msg)(struct irq_data *data, struct msi_msg *msg);
 
+       int             (*irq_get_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool *state);
+       int             (*irq_set_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool state);
+
        unsigned long   flags;
 };
 
@@ -460,6 +466,7 @@ extern void irq_chip_eoi_parent(struct irq_data *data);
 extern int irq_chip_set_affinity_parent(struct irq_data *data,
                                        const struct cpumask *dest,
                                        bool force);
+extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on);
 #endif
 
 /* Handling of unhandled and spurious interrupts: */
index bf3fe719c7ce9d3c0efa3c2449cc0d2a7e5b43ad..47b9ebd4a74fc667601d76476645fefbdb3c36f6 100644 (file)
@@ -38,16 +38,17 @@ bool irq_work_queue(struct irq_work *work);
 bool irq_work_queue_on(struct irq_work *work, int cpu);
 #endif
 
-void irq_work_run(void);
 void irq_work_tick(void);
 void irq_work_sync(struct irq_work *work);
 
 #ifdef CONFIG_IRQ_WORK
 #include <asm/irq_work.h>
 
+void irq_work_run(void);
 bool irq_work_needs_cpu(void);
 #else
 static inline bool irq_work_needs_cpu(void) { return false; }
+static inline void irq_work_run(void) { }
 #endif
 
 #endif /* _LINUX_IRQ_WORK_H */
index 71d706d5f16922a5b95edfd6e6f93971139e7d81..36ec4ae746345aaa9b79698546c3568976e0b2c3 100644 (file)
@@ -97,6 +97,7 @@ struct device_node;
 
 extern struct irq_chip gic_arch_extn;
 
+void gic_set_irqchip_flags(unsigned long flags);
 void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
                    u32 offset, struct device_node *);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
@@ -115,11 +116,5 @@ int gic_get_cpu_id(unsigned int cpu);
 void gic_migrate_target(unsigned int new_cpu_id);
 unsigned long gic_get_sgir_physaddr(void);
 
-extern const struct irq_domain_ops *gic_routable_irq_domain_ops;
-static inline void __init register_routable_domain_ops
-                                       (const struct irq_domain_ops *ops)
-{
-       gic_routable_irq_domain_ops = ops;
-}
 #endif /* __ASSEMBLY */
 #endif
diff --git a/include/linux/irqchip/irq-crossbar.h b/include/linux/irqchip/irq-crossbar.h
deleted file mode 100644 (file)
index e5537b8..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- *  drivers/irqchip/irq-crossbar.h
- *
- *  Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-int irqcrossbar_init(void);
index e6a6aac451db4614df9cc4e58911f9ff6629620d..3ea2e4754c40f2a00090be89735eaac03e82a180 100644 (file)
@@ -240,6 +240,8 @@ extern unsigned int gic_get_count_width(void);
 extern cycle_t gic_read_compare(void);
 extern void gic_write_compare(cycle_t cnt);
 extern void gic_write_cpu_compare(cycle_t cnt, int cpu);
+extern void gic_start_count(void);
+extern void gic_stop_count(void);
 extern void gic_send_ipi(unsigned int intr);
 extern unsigned int plat_ipi_call_int_xlate(unsigned int);
 extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
index d176d658fe25dd6b09b3d03936a4b60ce324367c..5dd1272d1ab2ecb283f588eb95ba1ebd81369dd9 100644 (file)
@@ -85,7 +85,7 @@
  * The local_irq_*() APIs are equal to the raw_local_irq*()
  * if !TRACE_IRQFLAGS.
  */
-#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
+#ifdef CONFIG_TRACE_IRQFLAGS
 #define local_irq_enable() \
        do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
 #define local_irq_disable() \
                        raw_local_irq_restore(flags);   \
                }                                       \
        } while (0)
-#define local_save_flags(flags)                                \
-       do {                                            \
-               raw_local_save_flags(flags);            \
-       } while (0)
-
-#define irqs_disabled_flags(flags)                     \
-       ({                                              \
-               raw_irqs_disabled_flags(flags);         \
-       })
-
-#define irqs_disabled()                                        \
-       ({                                              \
-               unsigned long _flags;                   \
-               raw_local_save_flags(_flags);           \
-               raw_irqs_disabled_flags(_flags);        \
-       })
 
 #define safe_halt()                            \
        do {                                    \
        } while (0)
 
 
-#else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */
+#else /* !CONFIG_TRACE_IRQFLAGS */
 
 #define local_irq_enable()     do { raw_local_irq_enable(); } while (0)
 #define local_irq_disable()    do { raw_local_irq_disable(); } while (0)
                raw_local_irq_save(flags);                      \
        } while (0)
 #define local_irq_restore(flags) do { raw_local_irq_restore(flags); } while (0)
-#define local_save_flags(flags)        do { raw_local_save_flags(flags); } while (0)
-#define irqs_disabled()                (raw_irqs_disabled())
-#define irqs_disabled_flags(flags) (raw_irqs_disabled_flags(flags))
 #define safe_halt()            do { raw_safe_halt(); } while (0)
 
+#endif /* CONFIG_TRACE_IRQFLAGS */
+
+#define local_save_flags(flags)        raw_local_save_flags(flags)
+
+/*
+ * Some architectures don't define arch_irqs_disabled(), so even if either
+ * definition would be fine we need to use different ones for the time being
+ * to avoid build issues.
+ */
+#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
+#define irqs_disabled()                                        \
+       ({                                              \
+               unsigned long _flags;                   \
+               raw_local_save_flags(_flags);           \
+               raw_irqs_disabled_flags(_flags);        \
+       })
+#else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */
+#define irqs_disabled()        raw_irqs_disabled()
 #endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */
 
+#define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags)
+
 #endif
index 98f923b6a0eaa78ee8b4ffdf57c87f146e3c03d6..f4de473f226b8ab5332dabc7083b74c80de8a664 100644 (file)
  * same as using STATIC_KEY_INIT_FALSE.
  */
 
+#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
+# define HAVE_JUMP_LABEL
+#endif
+
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <linux/compiler.h>
 #include <linux/bug.h>
@@ -55,7 +61,7 @@ extern bool static_key_initialized;
                                    "%s used before call to jump_label_init", \
                                    __func__)
 
-#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
+#ifdef HAVE_JUMP_LABEL
 
 struct static_key {
        atomic_t enabled;
@@ -66,13 +72,18 @@ struct static_key {
 #endif
 };
 
-# include <asm/jump_label.h>
-# define HAVE_JUMP_LABEL
 #else
 struct static_key {
        atomic_t enabled;
 };
-#endif /* CC_HAVE_ASM_GOTO && CONFIG_JUMP_LABEL */
+#endif /* HAVE_JUMP_LABEL */
+#endif /* __ASSEMBLY__ */
+
+#ifdef HAVE_JUMP_LABEL
+#include <asm/jump_label.h>
+#endif
+
+#ifndef __ASSEMBLY__
 
 enum jump_label_type {
        JUMP_LABEL_DISABLE = 0,
@@ -203,3 +214,5 @@ static inline bool static_key_enabled(struct static_key *key)
 }
 
 #endif /* _LINUX_JUMP_LABEL_H */
+
+#endif /* __ASSEMBLY__ */
index d12b2104d19b422a9e3357f7186d80702807fa3d..ad45054309a0fcaea6d12392cf02560f3d46ab95 100644 (file)
@@ -165,12 +165,12 @@ enum kvm_bus {
        KVM_NR_BUSES
 };
 
-int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+int kvm_io_bus_write(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
                     int len, const void *val);
-int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
-                           int len, const void *val, long cookie);
-int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len,
-                   void *val);
+int kvm_io_bus_write_cookie(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx,
+                           gpa_t addr, int len, const void *val, long cookie);
+int kvm_io_bus_read(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
+                   int len, void *val);
 int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
                            int len, struct kvm_io_device *dev);
 int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
@@ -658,7 +658,6 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu);
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
 
 void *kvm_kvzalloc(unsigned long size);
-void kvm_kvfree(const void *addr);
 
 #ifndef __KVM_HAVE_ARCH_VM_ALLOC
 static inline struct kvm *kvm_arch_alloc_vm(void)
@@ -700,6 +699,20 @@ static inline wait_queue_head_t *kvm_arch_vcpu_wq(struct kvm_vcpu *vcpu)
 #endif
 }
 
+#ifdef __KVM_HAVE_ARCH_INTC_INITIALIZED
+/*
+ * returns true if the virtual interrupt controller is initialized and
+ * ready to accept virtual IRQ. On some architectures the virtual interrupt
+ * controller is dynamically instantiated and this is not always true.
+ */
+bool kvm_arch_intc_initialized(struct kvm *kvm);
+#else
+static inline bool kvm_arch_intc_initialized(struct kvm *kvm)
+{
+       return true;
+}
+#endif
+
 int kvm_arch_init_vm(struct kvm *kvm, unsigned long type);
 void kvm_arch_destroy_vm(struct kvm *kvm);
 void kvm_arch_sync_events(struct kvm *kvm);
@@ -766,7 +779,8 @@ static inline void kvm_guest_enter(void)
         * one time slice). Lets treat guest mode as quiescent state, just like
         * we do with user-mode execution.
         */
-       rcu_virt_note_context_switch(smp_processor_id());
+       if (!context_tracking_cpu_is_enabled())
+               rcu_virt_note_context_switch(smp_processor_id());
 }
 
 static inline void kvm_guest_exit(void)
@@ -969,11 +983,16 @@ 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_bsp(struct kvm_vcpu *vcpu)
+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
index 6b08cc106c218dc06d60988663c4bcac3eaba5fe..8dad4a307bb8c4b086e8f6f62211d91d8c05a53a 100644 (file)
@@ -231,8 +231,7 @@ enum {
        ATA_FLAG_SW_ACTIVITY    = (1 << 22), /* driver supports sw activity
                                              * led */
        ATA_FLAG_NO_DIPM        = (1 << 23), /* host not happy with DIPM */
-       ATA_FLAG_LOWTAG         = (1 << 24), /* host wants lowest available tag */
-       ATA_FLAG_SAS_HOST       = (1 << 25), /* SAS host */
+       ATA_FLAG_SAS_HOST       = (1 << 24), /* SAS host */
 
        /* bits 24:31 of ap->flags are reserved for LLD specific flags */
 
index 95023fd8b00dd8343896524b31a31a7f1e9451a4..ee6dbb39a809811ca6aa563ea125fc9bb0af4756 100644 (file)
@@ -123,10 +123,10 @@ struct klp_patch {
        enum klp_state state;
 };
 
-extern int klp_register_patch(struct klp_patch *);
-extern int klp_unregister_patch(struct klp_patch *);
-extern int klp_enable_patch(struct klp_patch *);
-extern int klp_disable_patch(struct klp_patch *);
+int klp_register_patch(struct klp_patch *);
+int klp_unregister_patch(struct klp_patch *);
+int klp_enable_patch(struct klp_patch *);
+int klp_disable_patch(struct klp_patch *);
 
 #endif /* CONFIG_LIVEPATCH */
 
index 74ab23176e9b0a34edef8fcf0749d5107521bc90..066ba4157541a94b0bfadf4b9fb2e245fc75ab8e 100644 (file)
@@ -531,8 +531,13 @@ do {                                                                       \
 # define might_lock_read(lock) do { } while (0)
 #endif
 
-#ifdef CONFIG_PROVE_RCU
+#ifdef CONFIG_LOCKDEP
 void lockdep_rcu_suspicious(const char *file, const int line, const char *s);
+#else
+static inline void
+lockdep_rcu_suspicious(const char *file, const int line, const char *s)
+{
+}
 #endif
 
 #endif /* __LINUX_LOCKDEP_H */
index e8cc45307f8f0d0f9897f0eb36d96b3c9fa7655c..9497ec7c77ea1b45d0a48e9d390d292dd6db5153 100644 (file)
@@ -365,6 +365,14 @@ static inline unsigned long memblock_region_reserved_end_pfn(const struct memblo
 #define __initdata_memblock
 #endif
 
+#ifdef CONFIG_MEMTEST
+extern void early_memtest(phys_addr_t start, phys_addr_t end);
+#else
+static inline void early_memtest(phys_addr_t start, phys_addr_t end)
+{
+}
+#endif
+
 #else
 static inline phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align)
 {
index 8f1a41951df9ca96c24f3cdfc540425b7f0cb697..6ffa0ac7f7d62a2521ba40d154f4f5248f882afd 100644 (file)
@@ -192,6 +192,9 @@ extern void get_page_bootmem(unsigned long ingo, struct page *page,
 void get_online_mems(void);
 void put_online_mems(void);
 
+void mem_hotplug_begin(void);
+void mem_hotplug_done(void);
+
 #else /* ! CONFIG_MEMORY_HOTPLUG */
 /*
  * Stub functions for when hotplug is off
@@ -231,6 +234,9 @@ static inline int try_online_node(int nid)
 static inline void get_online_mems(void) {}
 static inline void put_online_mems(void) {}
 
+static inline void mem_hotplug_begin(void) {}
+static inline void mem_hotplug_done(void) {}
+
 #endif /* ! CONFIG_MEMORY_HOTPLUG */
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
index 39ed62ab5b8a38ef3aafa3729767dc7d7c7587ef..b19b3023c88031ef326e773afb7e8ecb6e3cd84a 100644 (file)
@@ -29,7 +29,7 @@ extern mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn,
                        mempool_free_t *free_fn, void *pool_data,
                        gfp_t gfp_mask, int nid);
 
-extern int mempool_resize(mempool_t *pool, int new_min_nr, gfp_t gfp_mask);
+extern int mempool_resize(mempool_t *pool, int new_min_nr);
 extern void mempool_destroy(mempool_t *pool);
 extern void * mempool_alloc(mempool_t *pool, gfp_t gfp_mask);
 extern void mempool_free(void *element, mempool_t *pool);
index 234c99143bf778019c0ef28330c9967530bb7d43..67703f23e7ba2729c307899126422145055d665e 100644 (file)
@@ -9,8 +9,13 @@
 
 #include <linux/power_supply.h>
 
-#define psy_to_ux500_charger(x) container_of((x), \
-               struct ux500_charger, psy)
+/*
+ * Valid only for supplies of type:
+ * - POWER_SUPPLY_TYPE_MAINS,
+ * - POWER_SUPPLY_TYPE_USB,
+ * because only them store as drv_data pointer to struct ux500_charger.
+ */
+#define psy_to_ux500_charger(x) power_supply_get_drvdata(psy)
 
 /* Forward declaration */
 struct ux500_charger;
@@ -35,7 +40,7 @@ struct ux500_charger_ops {
  * @power_path         USB power path support
  */
 struct ux500_charger {
-       struct power_supply psy;
+       struct power_supply *psy;
        struct ux500_charger_ops ops;
        int max_out_volt;
        int max_out_curr;
index 910e3aa1e9652861333a383ef65934b4e6822f69..f97010576f56181be46683434b27d1095c855409 100644 (file)
@@ -24,6 +24,7 @@ enum arizona_type {
        WM5102 = 1,
        WM5110 = 2,
        WM8997 = 3,
+       WM8280 = 4,
 };
 
 #define ARIZONA_IRQ_GP1                    0
diff --git a/include/linux/mfd/arizona/gpio.h b/include/linux/mfd/arizona/gpio.h
deleted file mode 100644 (file)
index d2146bb..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * GPIO configuration for Arizona devices
- *
- * Copyright 2013 Wolfson Microelectronics. PLC.
- *
- * Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _ARIZONA_GPIO_H
-#define _ARIZONA_GPIO_H
-
-#define ARIZONA_GP_FN_TXLRCLK                    0x00
-#define ARIZONA_GP_FN_GPIO                       0x01
-#define ARIZONA_GP_FN_IRQ1                       0x02
-#define ARIZONA_GP_FN_IRQ2                       0x03
-#define ARIZONA_GP_FN_OPCLK                      0x04
-#define ARIZONA_GP_FN_FLL1_OUT                   0x05
-#define ARIZONA_GP_FN_FLL2_OUT                   0x06
-#define ARIZONA_GP_FN_PWM1                       0x08
-#define ARIZONA_GP_FN_PWM2                       0x09
-#define ARIZONA_GP_FN_SYSCLK_UNDERCLOCKED        0x0A
-#define ARIZONA_GP_FN_ASYNCCLK_UNDERCLOCKED      0x0B
-#define ARIZONA_GP_FN_FLL1_LOCK                  0x0C
-#define ARIZONA_GP_FN_FLL2_LOCK                  0x0D
-#define ARIZONA_GP_FN_FLL1_CLOCK_OK              0x0F
-#define ARIZONA_GP_FN_FLL2_CLOCK_OK              0x10
-#define ARIZONA_GP_FN_HEADPHONE_DET              0x12
-#define ARIZONA_GP_FN_MIC_DET                    0x13
-#define ARIZONA_GP_FN_WSEQ_STATUS                0x15
-#define ARIZONA_GP_FN_CIF_ADDRESS_ERROR          0x16
-#define ARIZONA_GP_FN_ASRC1_LOCK                 0x1A
-#define ARIZONA_GP_FN_ASRC2_LOCK                 0x1B
-#define ARIZONA_GP_FN_ASRC_CONFIG_ERROR          0x1C
-#define ARIZONA_GP_FN_DRC1_SIGNAL_DETECT         0x1D
-#define ARIZONA_GP_FN_DRC1_ANTICLIP              0x1E
-#define ARIZONA_GP_FN_DRC1_DECAY                 0x1F
-#define ARIZONA_GP_FN_DRC1_NOISE                 0x20
-#define ARIZONA_GP_FN_DRC1_QUICK_RELEASE         0x21
-#define ARIZONA_GP_FN_DRC2_SIGNAL_DETECT         0x22
-#define ARIZONA_GP_FN_DRC2_ANTICLIP              0x23
-#define ARIZONA_GP_FN_DRC2_DECAY                 0x24
-#define ARIZONA_GP_FN_DRC2_NOISE                 0x25
-#define ARIZONA_GP_FN_DRC2_QUICK_RELEASE         0x26
-#define ARIZONA_GP_FN_MIXER_DROPPED_SAMPLE       0x27
-#define ARIZONA_GP_FN_AIF1_CONFIG_ERROR          0x28
-#define ARIZONA_GP_FN_AIF2_CONFIG_ERROR          0x29
-#define ARIZONA_GP_FN_AIF3_CONFIG_ERROR          0x2A
-#define ARIZONA_GP_FN_SPK_TEMP_SHUTDOWN          0x2B
-#define ARIZONA_GP_FN_SPK_TEMP_WARNING           0x2C
-#define ARIZONA_GP_FN_UNDERCLOCKED               0x2D
-#define ARIZONA_GP_FN_OVERCLOCKED                0x2E
-#define ARIZONA_GP_FN_DSP_IRQ1                   0x35
-#define ARIZONA_GP_FN_DSP_IRQ2                   0x36
-#define ARIZONA_GP_FN_ASYNC_OPCLK                0x3D
-#define ARIZONA_GP_FN_BOOT_DONE                  0x44
-#define ARIZONA_GP_FN_DSP1_RAM_READY             0x45
-#define ARIZONA_GP_FN_SYSCLK_ENA_STATUS          0x4B
-#define ARIZONA_GP_FN_ASYNCCLK_ENA_STATUS        0x4C
-
-#define ARIZONA_GPN_DIR                          0x8000  /* GPN_DIR */
-#define ARIZONA_GPN_DIR_MASK                     0x8000  /* GPN_DIR */
-#define ARIZONA_GPN_DIR_SHIFT                        15  /* GPN_DIR */
-#define ARIZONA_GPN_DIR_WIDTH                         1  /* GPN_DIR */
-#define ARIZONA_GPN_PU                           0x4000  /* GPN_PU */
-#define ARIZONA_GPN_PU_MASK                      0x4000  /* GPN_PU */
-#define ARIZONA_GPN_PU_SHIFT                         14  /* GPN_PU */
-#define ARIZONA_GPN_PU_WIDTH                          1  /* GPN_PU */
-#define ARIZONA_GPN_PD                           0x2000  /* GPN_PD */
-#define ARIZONA_GPN_PD_MASK                      0x2000  /* GPN_PD */
-#define ARIZONA_GPN_PD_SHIFT                         13  /* GPN_PD */
-#define ARIZONA_GPN_PD_WIDTH                          1  /* GPN_PD */
-#define ARIZONA_GPN_LVL                          0x0800  /* GPN_LVL */
-#define ARIZONA_GPN_LVL_MASK                     0x0800  /* GPN_LVL */
-#define ARIZONA_GPN_LVL_SHIFT                        11  /* GPN_LVL */
-#define ARIZONA_GPN_LVL_WIDTH                         1  /* GPN_LVL */
-#define ARIZONA_GPN_POL                          0x0400  /* GPN_POL */
-#define ARIZONA_GPN_POL_MASK                     0x0400  /* GPN_POL */
-#define ARIZONA_GPN_POL_SHIFT                        10  /* GPN_POL */
-#define ARIZONA_GPN_POL_WIDTH                         1  /* GPN_POL */
-#define ARIZONA_GPN_OP_CFG                       0x0200  /* GPN_OP_CFG */
-#define ARIZONA_GPN_OP_CFG_MASK                  0x0200  /* GPN_OP_CFG */
-#define ARIZONA_GPN_OP_CFG_SHIFT                      9  /* GPN_OP_CFG */
-#define ARIZONA_GPN_OP_CFG_WIDTH                      1  /* GPN_OP_CFG */
-#define ARIZONA_GPN_DB                           0x0100  /* GPN_DB */
-#define ARIZONA_GPN_DB_MASK                      0x0100  /* GPN_DB */
-#define ARIZONA_GPN_DB_SHIFT                          8  /* GPN_DB */
-#define ARIZONA_GPN_DB_WIDTH                          1  /* GPN_DB */
-#define ARIZONA_GPN_FN_MASK                      0x007F  /* GPN_DB */
-#define ARIZONA_GPN_FN_SHIFT                          0  /* GPN_DB */
-#define ARIZONA_GPN_FN_WIDTH                          7  /* GPN_DB */
-
-#endif
index 4578c72c9b86c56d045e85002000ddee2dc81147..1789cb0f4f170171d4e37fc20192906a44a4eb44 100644 (file)
 #ifndef _ARIZONA_PDATA_H
 #define _ARIZONA_PDATA_H
 
-#define ARIZONA_GPN_DIR                          0x8000  /* GPN_DIR */
+#include <dt-bindings/mfd/arizona.h>
+
 #define ARIZONA_GPN_DIR_MASK                     0x8000  /* GPN_DIR */
 #define ARIZONA_GPN_DIR_SHIFT                        15  /* GPN_DIR */
 #define ARIZONA_GPN_DIR_WIDTH                         1  /* GPN_DIR */
-#define ARIZONA_GPN_PU                           0x4000  /* GPN_PU */
 #define ARIZONA_GPN_PU_MASK                      0x4000  /* GPN_PU */
 #define ARIZONA_GPN_PU_SHIFT                         14  /* GPN_PU */
 #define ARIZONA_GPN_PU_WIDTH                          1  /* GPN_PU */
-#define ARIZONA_GPN_PD                           0x2000  /* GPN_PD */
 #define ARIZONA_GPN_PD_MASK                      0x2000  /* GPN_PD */
 #define ARIZONA_GPN_PD_SHIFT                         13  /* GPN_PD */
 #define ARIZONA_GPN_PD_WIDTH                          1  /* GPN_PD */
-#define ARIZONA_GPN_LVL                          0x0800  /* GPN_LVL */
 #define ARIZONA_GPN_LVL_MASK                     0x0800  /* GPN_LVL */
 #define ARIZONA_GPN_LVL_SHIFT                        11  /* GPN_LVL */
 #define ARIZONA_GPN_LVL_WIDTH                         1  /* GPN_LVL */
-#define ARIZONA_GPN_POL                          0x0400  /* GPN_POL */
 #define ARIZONA_GPN_POL_MASK                     0x0400  /* GPN_POL */
 #define ARIZONA_GPN_POL_SHIFT                        10  /* GPN_POL */
 #define ARIZONA_GPN_POL_WIDTH                         1  /* GPN_POL */
-#define ARIZONA_GPN_OP_CFG                       0x0200  /* GPN_OP_CFG */
 #define ARIZONA_GPN_OP_CFG_MASK                  0x0200  /* GPN_OP_CFG */
 #define ARIZONA_GPN_OP_CFG_SHIFT                      9  /* GPN_OP_CFG */
 #define ARIZONA_GPN_OP_CFG_WIDTH                      1  /* GPN_OP_CFG */
-#define ARIZONA_GPN_DB                           0x0100  /* GPN_DB */
 #define ARIZONA_GPN_DB_MASK                      0x0100  /* GPN_DB */
 #define ARIZONA_GPN_DB_SHIFT                          8  /* GPN_DB */
 #define ARIZONA_GPN_DB_WIDTH                          1  /* GPN_DB */
 
 #define ARIZONA_MAX_GPIO 5
 
-#define ARIZONA_32KZ_MCLK1 1
-#define ARIZONA_32KZ_MCLK2 2
-#define ARIZONA_32KZ_NONE  3
-
 #define ARIZONA_MAX_INPUT 4
 
-#define ARIZONA_DMIC_MICVDD   0
-#define ARIZONA_DMIC_MICBIAS1 1
-#define ARIZONA_DMIC_MICBIAS2 2
-#define ARIZONA_DMIC_MICBIAS3 3
-
 #define ARIZONA_MAX_MICBIAS 3
 
-#define ARIZONA_INMODE_DIFF 0
-#define ARIZONA_INMODE_SE   1
-#define ARIZONA_INMODE_DMIC 2
-
 #define ARIZONA_MAX_OUTPUT 6
 
 #define ARIZONA_MAX_AIF 3
@@ -112,7 +94,7 @@ struct arizona_pdata {
        int gpio_base;
 
        /** Pin state for GPIO pins */
-       int gpio_defaults[ARIZONA_MAX_GPIO];
+       unsigned int gpio_defaults[ARIZONA_MAX_GPIO];
 
        /**
         * Maximum number of channels clocks will be generated for,
index 955dd990beafaf3e82fab52902e9d35b2e03d4f9..51633ea6f9103cbf8f28b89901fcef48e7a7b57a 100644 (file)
@@ -87,6 +87,7 @@ enum max77693_pmic_reg {
 /* MAX77693 ITORCH register */
 #define TORCH_IOUT1_SHIFT      0
 #define TORCH_IOUT2_SHIFT      4
+#define TORCH_IOUT_MASK(x)     (0xf << (x))
 #define TORCH_IOUT_MIN         15625
 #define TORCH_IOUT_MAX         250000
 #define TORCH_IOUT_STEP                15625
@@ -113,8 +114,8 @@ enum max77693_pmic_reg {
 #define FLASH_EN_FLASH         0x1
 #define FLASH_EN_TORCH         0x2
 #define FLASH_EN_ON            0x3
-#define FLASH_EN_SHIFT(x)      (6 - ((x) - 1) * 2)
-#define TORCH_EN_SHIFT(x)      (2 - ((x) - 1) * 2)
+#define FLASH_EN_SHIFT(x)      (6 - (x) * 2)
+#define TORCH_EN_SHIFT(x)      (2 - (x) * 2)
 
 /* MAX77693 MAX_FLASH1 register */
 #define MAX_FLASH1_MAX_FL_EN   0x80
index f0b6585cd874cd0ecb917e8dccb130460bedbb40..d450f687301bd99676c8bd3284dddf8c3d42481c 100644 (file)
@@ -30,7 +30,7 @@
 #ifndef __LINUX_MFD_MAX77693_H
 #define __LINUX_MFD_MAX77693_H
 
-/* MAX77686 regulator IDs */
+/* MAX77693 regulator IDs */
 enum max77693_regulators {
        MAX77693_ESAFEOUT1 = 0,
        MAX77693_ESAFEOUT2,
@@ -38,12 +38,6 @@ enum max77693_regulators {
        MAX77693_REG_MAX,
 };
 
-struct max77693_regulator_data {
-       int id;
-       struct regulator_init_data *initdata;
-       struct device_node *of_node;
-};
-
 struct max77693_reg_data {
        u8 addr;
        u8 data;
@@ -87,26 +81,9 @@ enum max77693_led_boost_mode {
        MAX77693_LED_BOOST_FIXED,
 };
 
-struct max77693_led_platform_data {
-       u32 fleds[2];
-       u32 iout_torch[2];
-       u32 iout_flash[2];
-       u32 trigger[2];
-       u32 trigger_type[2];
-       u32 num_leds;
-       u32 boost_mode;
-       u32 flash_timeout;
-       u32 boost_vout;
-       u32 low_vsys;
-};
-
 /* MAX77693 */
 
 struct max77693_platform_data {
-       /* regulator data */
-       struct max77693_regulator_data *regulators;
-       int num_regulators;
-
        /* muic data */
        struct max77693_muic_platform_data *muic_data;
        struct max77693_led_platform_data *led_data;
diff --git a/include/linux/mfd/max77843-private.h b/include/linux/mfd/max77843-private.h
new file mode 100644 (file)
index 0000000..7178ace
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+ * Common variables for the Maxim MAX77843 driver
+ *
+ * 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.
+ */
+
+#ifndef __MAX77843_PRIVATE_H_
+#define __MAX77843_PRIVATE_H_
+
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+#define I2C_ADDR_TOPSYS        (0xCC >> 1)
+#define I2C_ADDR_CHG   (0xD2 >> 1)
+#define I2C_ADDR_FG    (0x6C >> 1)
+#define I2C_ADDR_MUIC  (0x4A >> 1)
+
+/* Topsys, Haptic and LED registers */
+enum max77843_sys_reg {
+       MAX77843_SYS_REG_PMICID         = 0x00,
+       MAX77843_SYS_REG_PMICREV        = 0x01,
+       MAX77843_SYS_REG_MAINCTRL1      = 0x02,
+       MAX77843_SYS_REG_INTSRC         = 0x22,
+       MAX77843_SYS_REG_INTSRCMASK     = 0x23,
+       MAX77843_SYS_REG_SYSINTSRC      = 0x24,
+       MAX77843_SYS_REG_SYSINTMASK     = 0x26,
+       MAX77843_SYS_REG_TOPSYS_STAT    = 0x28,
+       MAX77843_SYS_REG_SAFEOUTCTRL    = 0xC6,
+
+       MAX77843_SYS_REG_END,
+};
+
+enum max77843_haptic_reg {
+       MAX77843_HAP_REG_MCONFIG        = 0x10,
+
+       MAX77843_HAP_REG_END,
+};
+
+enum max77843_led_reg {
+       MAX77843_LED_REG_LEDEN          = 0x30,
+       MAX77843_LED_REG_LED0BRT        = 0x31,
+       MAX77843_LED_REG_LED1BRT        = 0x32,
+       MAX77843_LED_REG_LED2BRT        = 0x33,
+       MAX77843_LED_REG_LED3BRT        = 0x34,
+       MAX77843_LED_REG_LEDBLNK        = 0x38,
+       MAX77843_LED_REG_LEDRAMP        = 0x36,
+
+       MAX77843_LED_REG_END,
+};
+
+/* Charger registers */
+enum max77843_charger_reg {
+       MAX77843_CHG_REG_CHG_INT        = 0xB0,
+       MAX77843_CHG_REG_CHG_INT_MASK   = 0xB1,
+       MAX77843_CHG_REG_CHG_INT_OK     = 0xB2,
+       MAX77843_CHG_REG_CHG_DTLS_00    = 0xB3,
+       MAX77843_CHG_REG_CHG_DTLS_01    = 0xB4,
+       MAX77843_CHG_REG_CHG_DTLS_02    = 0xB5,
+       MAX77843_CHG_REG_CHG_CNFG_00    = 0xB7,
+       MAX77843_CHG_REG_CHG_CNFG_01    = 0xB8,
+       MAX77843_CHG_REG_CHG_CNFG_02    = 0xB9,
+       MAX77843_CHG_REG_CHG_CNFG_03    = 0xBA,
+       MAX77843_CHG_REG_CHG_CNFG_04    = 0xBB,
+       MAX77843_CHG_REG_CHG_CNFG_06    = 0xBD,
+       MAX77843_CHG_REG_CHG_CNFG_07    = 0xBE,
+       MAX77843_CHG_REG_CHG_CNFG_09    = 0xC0,
+       MAX77843_CHG_REG_CHG_CNFG_10    = 0xC1,
+       MAX77843_CHG_REG_CHG_CNFG_11    = 0xC2,
+       MAX77843_CHG_REG_CHG_CNFG_12    = 0xC3,
+
+       MAX77843_CHG_REG_END,
+};
+
+/* Fuel gauge registers */
+enum max77843_fuelgauge {
+       MAX77843_FG_REG_STATUS          = 0x00,
+       MAX77843_FG_REG_VALRT_TH        = 0x01,
+       MAX77843_FG_REG_TALRT_TH        = 0x02,
+       MAX77843_FG_REG_SALRT_TH        = 0x03,
+       MAX77843_FG_RATE_AT_RATE        = 0x04,
+       MAX77843_FG_REG_REMCAP_REP      = 0x05,
+       MAX77843_FG_REG_SOCREP          = 0x06,
+       MAX77843_FG_REG_AGE             = 0x07,
+       MAX77843_FG_REG_TEMP            = 0x08,
+       MAX77843_FG_REG_VCELL           = 0x09,
+       MAX77843_FG_REG_CURRENT         = 0x0A,
+       MAX77843_FG_REG_AVG_CURRENT     = 0x0B,
+       MAX77843_FG_REG_SOCMIX          = 0x0D,
+       MAX77843_FG_REG_SOCAV           = 0x0E,
+       MAX77843_FG_REG_REMCAP_MIX      = 0x0F,
+       MAX77843_FG_REG_FULLCAP         = 0x10,
+       MAX77843_FG_REG_AVG_TEMP        = 0x16,
+       MAX77843_FG_REG_CYCLES          = 0x17,
+       MAX77843_FG_REG_AVG_VCELL       = 0x19,
+       MAX77843_FG_REG_CONFIG          = 0x1D,
+       MAX77843_FG_REG_REMCAP_AV       = 0x1F,
+       MAX77843_FG_REG_FULLCAP_NOM     = 0x23,
+       MAX77843_FG_REG_MISCCFG         = 0x2B,
+       MAX77843_FG_REG_RCOMP           = 0x38,
+       MAX77843_FG_REG_FSTAT           = 0x3D,
+       MAX77843_FG_REG_DQACC           = 0x45,
+       MAX77843_FG_REG_DPACC           = 0x46,
+       MAX77843_FG_REG_OCV             = 0xEE,
+       MAX77843_FG_REG_VFOCV           = 0xFB,
+       MAX77843_FG_SOCVF               = 0xFF,
+
+       MAX77843_FG_END,
+};
+
+/* MUIC registers */
+enum max77843_muic_reg {
+       MAX77843_MUIC_REG_ID            = 0x00,
+       MAX77843_MUIC_REG_INT1          = 0x01,
+       MAX77843_MUIC_REG_INT2          = 0x02,
+       MAX77843_MUIC_REG_INT3          = 0x03,
+       MAX77843_MUIC_REG_STATUS1       = 0x04,
+       MAX77843_MUIC_REG_STATUS2       = 0x05,
+       MAX77843_MUIC_REG_STATUS3       = 0x06,
+       MAX77843_MUIC_REG_INTMASK1      = 0x07,
+       MAX77843_MUIC_REG_INTMASK2      = 0x08,
+       MAX77843_MUIC_REG_INTMASK3      = 0x09,
+       MAX77843_MUIC_REG_CDETCTRL1     = 0x0A,
+       MAX77843_MUIC_REG_CDETCTRL2     = 0x0B,
+       MAX77843_MUIC_REG_CONTROL1      = 0x0C,
+       MAX77843_MUIC_REG_CONTROL2      = 0x0D,
+       MAX77843_MUIC_REG_CONTROL3      = 0x0E,
+       MAX77843_MUIC_REG_CONTROL4      = 0x16,
+       MAX77843_MUIC_REG_HVCONTROL1    = 0x17,
+       MAX77843_MUIC_REG_HVCONTROL2    = 0x18,
+
+       MAX77843_MUIC_REG_END,
+};
+
+enum max77843_irq {
+       /* Topsys: SYSTEM */
+       MAX77843_SYS_IRQ_SYSINTSRC_SYSUVLO_INT,
+       MAX77843_SYS_IRQ_SYSINTSRC_SYSOVLO_INT,
+       MAX77843_SYS_IRQ_SYSINTSRC_TSHDN_INT,
+       MAX77843_SYS_IRQ_SYSINTSRC_TM_INT,
+
+       /* Charger: CHG_INT */
+       MAX77843_CHG_IRQ_CHG_INT_BYP_I,
+       MAX77843_CHG_IRQ_CHG_INT_BATP_I,
+       MAX77843_CHG_IRQ_CHG_INT_BAT_I,
+       MAX77843_CHG_IRQ_CHG_INT_CHG_I,
+       MAX77843_CHG_IRQ_CHG_INT_WCIN_I,
+       MAX77843_CHG_IRQ_CHG_INT_CHGIN_I,
+       MAX77843_CHG_IRQ_CHG_INT_AICL_I,
+
+       MAX77843_IRQ_NUM,
+};
+
+enum max77843_irq_muic {
+       /* MUIC: INT1 */
+       MAX77843_MUIC_IRQ_INT1_ADC,
+       MAX77843_MUIC_IRQ_INT1_ADCERROR,
+       MAX77843_MUIC_IRQ_INT1_ADC1K,
+
+       /* MUIC: INT2 */
+       MAX77843_MUIC_IRQ_INT2_CHGTYP,
+       MAX77843_MUIC_IRQ_INT2_CHGDETRUN,
+       MAX77843_MUIC_IRQ_INT2_DCDTMR,
+       MAX77843_MUIC_IRQ_INT2_DXOVP,
+       MAX77843_MUIC_IRQ_INT2_VBVOLT,
+
+       /* MUIC: INT3 */
+       MAX77843_MUIC_IRQ_INT3_VBADC,
+       MAX77843_MUIC_IRQ_INT3_VDNMON,
+       MAX77843_MUIC_IRQ_INT3_DNRES,
+       MAX77843_MUIC_IRQ_INT3_MPNACK,
+       MAX77843_MUIC_IRQ_INT3_MRXBUFOW,
+       MAX77843_MUIC_IRQ_INT3_MRXTRF,
+       MAX77843_MUIC_IRQ_INT3_MRXPERR,
+       MAX77843_MUIC_IRQ_INT3_MRXRDY,
+
+       MAX77843_MUIC_IRQ_NUM,
+};
+
+/* MAX77843 interrupts */
+#define MAX77843_SYS_IRQ_SYSUVLO_INT           BIT(0)
+#define MAX77843_SYS_IRQ_SYSOVLO_INT           BIT(1)
+#define MAX77843_SYS_IRQ_TSHDN_INT             BIT(2)
+#define MAX77843_SYS_IRQ_TM_INT                        BIT(3)
+
+/* MAX77843 MAINCTRL1 register */
+#define MAINCTRL1_BIASEN_SHIFT                 7
+#define MAX77843_MAINCTRL1_BIASEN_MASK         BIT(MAINCTRL1_BIASEN_SHIFT)
+
+/* MAX77843 MCONFIG register */
+#define MCONFIG_MODE_SHIFT                     7
+#define MCONFIG_MEN_SHIFT                      6
+#define MCONFIG_PDIV_SHIFT                     0
+
+#define MAX77843_MCONFIG_MODE_MASK             BIT(MCONFIG_MODE_SHIFT)
+#define MAX77843_MCONFIG_MEN_MASK              BIT(MCONFIG_MEN_SHIFT)
+#define MAX77843_MCONFIG_PDIV_MASK             (0x3 << MCONFIG_PDIV_SHIFT)
+
+/* Max77843 charger insterrupts */
+#define MAX77843_CHG_BYP_I                     BIT(0)
+#define MAX77843_CHG_BATP_I                    BIT(2)
+#define MAX77843_CHG_BAT_I                     BIT(3)
+#define MAX77843_CHG_CHG_I                     BIT(4)
+#define MAX77843_CHG_WCIN_I                    BIT(5)
+#define MAX77843_CHG_CHGIN_I                   BIT(6)
+#define MAX77843_CHG_AICL_I                    BIT(7)
+
+/* MAX77843 CHG_INT_OK register */
+#define MAX77843_CHG_BYP_OK                    BIT(0)
+#define MAX77843_CHG_BATP_OK                   BIT(2)
+#define MAX77843_CHG_BAT_OK                    BIT(3)
+#define MAX77843_CHG_CHG_OK                    BIT(4)
+#define MAX77843_CHG_WCIN_OK                   BIT(5)
+#define MAX77843_CHG_CHGIN_OK                  BIT(6)
+#define MAX77843_CHG_AICL_OK                   BIT(7)
+
+/* MAX77843 CHG_DETAILS_00 register */
+#define MAX77843_CHG_BAT_DTLS                  BIT(0)
+
+/* MAX77843 CHG_DETAILS_01 register */
+#define MAX77843_CHG_DTLS_MASK                 0x0f
+#define MAX77843_CHG_PQ_MODE                   0x00
+#define MAX77843_CHG_CC_MODE                   0x01
+#define MAX77843_CHG_CV_MODE                   0x02
+#define MAX77843_CHG_TO_MODE                   0x03
+#define MAX77843_CHG_DO_MODE                   0x04
+#define MAX77843_CHG_HT_MODE                   0x05
+#define MAX77843_CHG_TF_MODE                   0x06
+#define MAX77843_CHG_TS_MODE                   0x07
+#define MAX77843_CHG_OFF_MODE                  0x08
+
+#define MAX77843_CHG_BAT_DTLS_MASK             0xf0
+#define MAX77843_CHG_NO_BAT                    (0x00 << 4)
+#define MAX77843_CHG_LOW_VOLT_BAT              (0x01 << 4)
+#define MAX77843_CHG_LONG_BAT_TIME             (0x02 << 4)
+#define MAX77843_CHG_OK_BAT                    (0x03 << 4)
+#define MAX77843_CHG_OK_LOW_VOLT_BAT           (0x04 << 4)
+#define MAX77843_CHG_OVER_VOLT_BAT             (0x05 << 4)
+#define MAX77843_CHG_OVER_CURRENT_BAT          (0x06 << 4)
+
+/* MAX77843 CHG_CNFG_00 register */
+#define MAX77843_CHG_DISABLE                   0x00
+#define MAX77843_CHG_ENABLE                    0x05
+#define MAX77843_CHG_MASK                      0x01
+#define MAX77843_CHG_BUCK_MASK                 0x04
+
+/* MAX77843 CHG_CNFG_01 register */
+#define MAX77843_CHG_RESTART_THRESHOLD_100     0x00
+#define MAX77843_CHG_RESTART_THRESHOLD_150     0x10
+#define MAX77843_CHG_RESTART_THRESHOLD_200     0x20
+#define MAX77843_CHG_RESTART_THRESHOLD_DISABLE 0x30
+
+/* MAX77843 CHG_CNFG_02 register */
+#define MAX77843_CHG_FAST_CHG_CURRENT_MIN      100000
+#define MAX77843_CHG_FAST_CHG_CURRENT_MAX      3150000
+#define MAX77843_CHG_FAST_CHG_CURRENT_STEP     50000
+#define MAX77843_CHG_FAST_CHG_CURRENT_MASK     0x3f
+#define MAX77843_CHG_OTG_ILIMIT_500            (0x00 << 6)
+#define MAX77843_CHG_OTG_ILIMIT_900            (0x01 << 6)
+#define MAX77843_CHG_OTG_ILIMIT_1200           (0x02 << 6)
+#define MAX77843_CHG_OTG_ILIMIT_1500           (0x03 << 6)
+#define MAX77843_CHG_OTG_ILIMIT_MASK           0xc0
+
+/* MAX77843 CHG_CNFG_03 register */
+#define MAX77843_CHG_TOP_OFF_CURRENT_MIN       125000
+#define MAX77843_CHG_TOP_OFF_CURRENT_MAX       650000
+#define MAX77843_CHG_TOP_OFF_CURRENT_STEP      75000
+#define MAX77843_CHG_TOP_OFF_CURRENT_MASK      0x07
+
+/* MAX77843 CHG_CNFG_06 register */
+#define MAX77843_CHG_WRITE_CAP_BLOCK           0x10
+#define MAX77843_CHG_WRITE_CAP_UNBLOCK         0x0C
+
+/* MAX77843_CHG_CNFG_09_register */
+#define MAX77843_CHG_INPUT_CURRENT_LIMIT_MIN   100000
+#define MAX77843_CHG_INPUT_CURRENT_LIMIT_MAX   4000000
+#define MAX77843_CHG_INPUT_CURRENT_LIMIT_REF   3367000
+#define MAX77843_CHG_INPUT_CURRENT_LIMIT_STEP  33000
+
+#define MAX77843_MUIC_ADC                      BIT(0)
+#define MAX77843_MUIC_ADCERROR                 BIT(2)
+#define MAX77843_MUIC_ADC1K                    BIT(3)
+
+#define MAX77843_MUIC_CHGTYP                   BIT(0)
+#define MAX77843_MUIC_CHGDETRUN                        BIT(1)
+#define MAX77843_MUIC_DCDTMR                   BIT(2)
+#define MAX77843_MUIC_DXOVP                    BIT(3)
+#define MAX77843_MUIC_VBVOLT                   BIT(4)
+
+#define MAX77843_MUIC_VBADC                    BIT(0)
+#define MAX77843_MUIC_VDNMON                   BIT(1)
+#define MAX77843_MUIC_DNRES                    BIT(2)
+#define MAX77843_MUIC_MPNACK                   BIT(3)
+#define MAX77843_MUIC_MRXBUFOW                 BIT(4)
+#define MAX77843_MUIC_MRXTRF                   BIT(5)
+#define MAX77843_MUIC_MRXPERR                  BIT(6)
+#define MAX77843_MUIC_MRXRDY                   BIT(7)
+
+/* MAX77843 INTSRCMASK register */
+#define MAX77843_INTSRCMASK_CHGR               0
+#define MAX77843_INTSRCMASK_SYS                        1
+#define MAX77843_INTSRCMASK_FG                 2
+#define MAX77843_INTSRCMASK_MUIC               3
+
+#define MAX77843_INTSRCMASK_CHGR_MASK          BIT(MAX77843_INTSRCMASK_CHGR)
+#define MAX77843_INTSRCMASK_SYS_MASK           BIT(MAX77843_INTSRCMASK_SYS)
+#define MAX77843_INTSRCMASK_FG_MASK            BIT(MAX77843_INTSRCMASK_FG)
+#define MAX77843_INTSRCMASK_MUIC_MASK          BIT(MAX77843_INTSRCMASK_MUIC)
+
+#define MAX77843_INTSRC_MASK_MASK \
+       (MAX77843_INTSRCMASK_MUIC_MASK | MAX77843_INTSRCMASK_FG_MASK | \
+       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)
+
+/* 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)
+
+/* MAX77843 switch port */
+#define COM_OPEN                               0
+#define COM_USB                                        1
+#define COM_AUDIO                              2
+#define COM_UART                               3
+#define COM_AUX_USB                            4
+#define COM_AUX_UART                           5
+
+#define 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_DISABLE                       0
+#define MAX77843_ENABLE                                1
+
+#define CONTROL4_AUTO_DISABLE \
+       ((MAX77843_DISABLE << CONTROL4_USBAUTO_SHIFT) | \
+       (MAX77843_DISABLE << CONTROL4_FCTAUTO_SHIFT))
+#define CONTROL4_AUTO_ENABLE \
+       ((MAX77843_ENABLE << CONTROL4_USBAUTO_SHIFT) | \
+       (MAX77843_ENABLE << CONTROL4_FCTAUTO_SHIFT))
+
+/* MAX77843 SAFEOUT LDO Control register */
+#define SAFEOUTCTRL_SAFEOUT1_SHIFT             0
+#define SAFEOUTCTRL_SAFEOUT2_SHIFT             2
+#define SAFEOUTCTRL_ENSAFEOUT1_SHIFT           6
+#define SAFEOUTCTRL_ENSAFEOUT2_SHIFT           7
+
+#define MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT1 \
+               BIT(SAFEOUTCTRL_ENSAFEOUT1_SHIFT)
+#define MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT2 \
+               BIT(SAFEOUTCTRL_ENSAFEOUT2_SHIFT)
+#define MAX77843_REG_SAFEOUTCTRL_SAFEOUT1_MASK \
+               (0x3 << SAFEOUTCTRL_SAFEOUT1_SHIFT)
+#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 f097e89134cbf5d36f04ea88a73f1dc570c2369b..9e85ac06da89d90c266a453ebd9d6c3f283dad53 100644 (file)
@@ -24,7 +24,6 @@ extern int menelaus_set_vaux(unsigned int mV);
 extern int menelaus_set_vdcdc(int dcdc, unsigned int mV);
 extern int menelaus_set_slot_sel(int enable);
 extern int menelaus_get_slot_pin_states(void);
-extern int menelaus_set_vcore_sw(unsigned int mV);
 extern int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV);
 
 #define EN_VPLL_SLEEP  (1 << 7)
@@ -38,10 +37,4 @@ extern int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV);
 
 extern int menelaus_set_regulator_sleep(int enable, u32 val);
 
-#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_MENELAUS)
-#define omap_has_menelaus()    1
-#else
-#define omap_has_menelaus()    0
-#endif
-
 #endif
diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h
new file mode 100644 (file)
index 0000000..cf5265b
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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 __MFD_MT6397_CORE_H__
+#define __MFD_MT6397_CORE_H__
+
+enum mt6397_irq_numbers {
+       MT6397_IRQ_SPKL_AB = 0,
+       MT6397_IRQ_SPKR_AB,
+       MT6397_IRQ_SPKL,
+       MT6397_IRQ_SPKR,
+       MT6397_IRQ_BAT_L,
+       MT6397_IRQ_BAT_H,
+       MT6397_IRQ_FG_BAT_L,
+       MT6397_IRQ_FG_BAT_H,
+       MT6397_IRQ_WATCHDOG,
+       MT6397_IRQ_PWRKEY,
+       MT6397_IRQ_THR_L,
+       MT6397_IRQ_THR_H,
+       MT6397_IRQ_VBATON_UNDET,
+       MT6397_IRQ_BVALID_DET,
+       MT6397_IRQ_CHRDET,
+       MT6397_IRQ_OV,
+       MT6397_IRQ_LDO,
+       MT6397_IRQ_HOMEKEY,
+       MT6397_IRQ_ACCDET,
+       MT6397_IRQ_AUDIO,
+       MT6397_IRQ_RTC,
+       MT6397_IRQ_PWRKEY_RSTB,
+       MT6397_IRQ_HDMI_SIFM,
+       MT6397_IRQ_HDMI_CEC,
+       MT6397_IRQ_VCA15,
+       MT6397_IRQ_VSRMCA15,
+       MT6397_IRQ_VCORE,
+       MT6397_IRQ_VGPU,
+       MT6397_IRQ_VIO18,
+       MT6397_IRQ_VPCA7,
+       MT6397_IRQ_VSRMCA7,
+       MT6397_IRQ_VDRM,
+       MT6397_IRQ_NR,
+};
+
+struct mt6397_chip {
+       struct device *dev;
+       struct regmap *regmap;
+       int irq;
+       struct irq_domain *irq_domain;
+       struct mutex irqlock;
+       u16 irq_masks_cur[2];
+       u16 irq_masks_cache[2];
+};
+
+#endif /* __MFD_MT6397_CORE_H__ */
diff --git a/include/linux/mfd/mt6397/registers.h b/include/linux/mfd/mt6397/registers.h
new file mode 100644 (file)
index 0000000..f23a0a6
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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 __MFD_MT6397_REGISTERS_H__
+#define __MFD_MT6397_REGISTERS_H__
+
+/* PMIC Registers */
+#define MT6397_CID                     0x0100
+#define MT6397_TOP_CKPDN               0x0102
+#define MT6397_TOP_CKPDN_SET           0x0104
+#define MT6397_TOP_CKPDN_CLR           0x0106
+#define MT6397_TOP_CKPDN2              0x0108
+#define MT6397_TOP_CKPDN2_SET          0x010A
+#define MT6397_TOP_CKPDN2_CLR          0x010C
+#define MT6397_TOP_GPIO_CKPDN          0x010E
+#define MT6397_TOP_RST_CON             0x0114
+#define MT6397_WRP_CKPDN               0x011A
+#define MT6397_WRP_RST_CON             0x0120
+#define MT6397_TOP_RST_MISC            0x0126
+#define MT6397_TOP_CKCON1              0x0128
+#define MT6397_TOP_CKCON2              0x012A
+#define MT6397_TOP_CKTST1              0x012C
+#define MT6397_TOP_CKTST2              0x012E
+#define MT6397_OC_DEG_EN               0x0130
+#define MT6397_OC_CTL0                 0x0132
+#define MT6397_OC_CTL1                 0x0134
+#define MT6397_OC_CTL2                 0x0136
+#define MT6397_INT_RSV                 0x0138
+#define MT6397_TEST_CON0               0x013A
+#define MT6397_TEST_CON1               0x013C
+#define MT6397_STATUS0                 0x013E
+#define MT6397_STATUS1                 0x0140
+#define MT6397_PGSTATUS                        0x0142
+#define MT6397_CHRSTATUS               0x0144
+#define MT6397_OCSTATUS0               0x0146
+#define MT6397_OCSTATUS1               0x0148
+#define MT6397_OCSTATUS2               0x014A
+#define MT6397_HDMI_PAD_IE             0x014C
+#define MT6397_TEST_OUT_L              0x014E
+#define MT6397_TEST_OUT_H              0x0150
+#define MT6397_TDSEL_CON               0x0152
+#define MT6397_RDSEL_CON               0x0154
+#define MT6397_GPIO_SMT_CON0           0x0156
+#define MT6397_GPIO_SMT_CON1           0x0158
+#define MT6397_GPIO_SMT_CON2           0x015A
+#define MT6397_GPIO_SMT_CON3           0x015C
+#define MT6397_DRV_CON0                        0x015E
+#define MT6397_DRV_CON1                        0x0160
+#define MT6397_DRV_CON2                        0x0162
+#define MT6397_DRV_CON3                        0x0164
+#define MT6397_DRV_CON4                        0x0166
+#define MT6397_DRV_CON5                        0x0168
+#define MT6397_DRV_CON6                        0x016A
+#define MT6397_DRV_CON7                        0x016C
+#define MT6397_DRV_CON8                        0x016E
+#define MT6397_DRV_CON9                        0x0170
+#define MT6397_DRV_CON10               0x0172
+#define MT6397_DRV_CON11               0x0174
+#define MT6397_DRV_CON12               0x0176
+#define MT6397_INT_CON0                        0x0178
+#define MT6397_INT_CON1                        0x017E
+#define MT6397_INT_STATUS0             0x0184
+#define MT6397_INT_STATUS1             0x0186
+#define MT6397_FQMTR_CON0              0x0188
+#define MT6397_FQMTR_CON1              0x018A
+#define MT6397_FQMTR_CON2              0x018C
+#define MT6397_EFUSE_DOUT_0_15         0x01C4
+#define MT6397_EFUSE_DOUT_16_31                0x01C6
+#define MT6397_EFUSE_DOUT_32_47                0x01C8
+#define MT6397_EFUSE_DOUT_48_63                0x01CA
+#define MT6397_SPI_CON                 0x01CC
+#define MT6397_TOP_CKPDN3              0x01CE
+#define MT6397_TOP_CKCON3              0x01D4
+#define MT6397_EFUSE_DOUT_64_79                0x01D6
+#define MT6397_EFUSE_DOUT_80_95                0x01D8
+#define MT6397_EFUSE_DOUT_96_111       0x01DA
+#define MT6397_EFUSE_DOUT_112_127      0x01DC
+#define MT6397_EFUSE_DOUT_128_143      0x01DE
+#define MT6397_EFUSE_DOUT_144_159      0x01E0
+#define MT6397_EFUSE_DOUT_160_175      0x01E2
+#define MT6397_EFUSE_DOUT_176_191      0x01E4
+#define MT6397_EFUSE_DOUT_192_207      0x01E6
+#define MT6397_EFUSE_DOUT_208_223      0x01E8
+#define MT6397_EFUSE_DOUT_224_239      0x01EA
+#define MT6397_EFUSE_DOUT_240_255      0x01EC
+#define MT6397_EFUSE_DOUT_256_271      0x01EE
+#define MT6397_EFUSE_DOUT_272_287      0x01F0
+#define MT6397_EFUSE_DOUT_288_300      0x01F2
+#define MT6397_EFUSE_DOUT_304_319      0x01F4
+#define MT6397_BUCK_CON0               0x0200
+#define MT6397_BUCK_CON1               0x0202
+#define MT6397_BUCK_CON2               0x0204
+#define MT6397_BUCK_CON3               0x0206
+#define MT6397_BUCK_CON4               0x0208
+#define MT6397_BUCK_CON5               0x020A
+#define MT6397_BUCK_CON6               0x020C
+#define MT6397_BUCK_CON7               0x020E
+#define MT6397_BUCK_CON8               0x0210
+#define MT6397_BUCK_CON9               0x0212
+#define MT6397_VCA15_CON0              0x0214
+#define MT6397_VCA15_CON1              0x0216
+#define MT6397_VCA15_CON2              0x0218
+#define MT6397_VCA15_CON3              0x021A
+#define MT6397_VCA15_CON4              0x021C
+#define MT6397_VCA15_CON5              0x021E
+#define MT6397_VCA15_CON6              0x0220
+#define MT6397_VCA15_CON7              0x0222
+#define MT6397_VCA15_CON8              0x0224
+#define MT6397_VCA15_CON9              0x0226
+#define MT6397_VCA15_CON10             0x0228
+#define MT6397_VCA15_CON11             0x022A
+#define MT6397_VCA15_CON12             0x022C
+#define MT6397_VCA15_CON13             0x022E
+#define MT6397_VCA15_CON14             0x0230
+#define MT6397_VCA15_CON15             0x0232
+#define MT6397_VCA15_CON16             0x0234
+#define MT6397_VCA15_CON17             0x0236
+#define MT6397_VCA15_CON18             0x0238
+#define MT6397_VSRMCA15_CON0           0x023A
+#define MT6397_VSRMCA15_CON1           0x023C
+#define MT6397_VSRMCA15_CON2           0x023E
+#define MT6397_VSRMCA15_CON3           0x0240
+#define MT6397_VSRMCA15_CON4           0x0242
+#define MT6397_VSRMCA15_CON5           0x0244
+#define MT6397_VSRMCA15_CON6           0x0246
+#define MT6397_VSRMCA15_CON7           0x0248
+#define MT6397_VSRMCA15_CON8           0x024A
+#define MT6397_VSRMCA15_CON9           0x024C
+#define MT6397_VSRMCA15_CON10          0x024E
+#define MT6397_VSRMCA15_CON11          0x0250
+#define MT6397_VSRMCA15_CON12          0x0252
+#define MT6397_VSRMCA15_CON13          0x0254
+#define MT6397_VSRMCA15_CON14          0x0256
+#define MT6397_VSRMCA15_CON15          0x0258
+#define MT6397_VSRMCA15_CON16          0x025A
+#define MT6397_VSRMCA15_CON17          0x025C
+#define MT6397_VSRMCA15_CON18          0x025E
+#define MT6397_VSRMCA15_CON19          0x0260
+#define MT6397_VSRMCA15_CON20          0x0262
+#define MT6397_VSRMCA15_CON21          0x0264
+#define MT6397_VCORE_CON0              0x0266
+#define MT6397_VCORE_CON1              0x0268
+#define MT6397_VCORE_CON2              0x026A
+#define MT6397_VCORE_CON3              0x026C
+#define MT6397_VCORE_CON4              0x026E
+#define MT6397_VCORE_CON5              0x0270
+#define MT6397_VCORE_CON6              0x0272
+#define MT6397_VCORE_CON7              0x0274
+#define MT6397_VCORE_CON8              0x0276
+#define MT6397_VCORE_CON9              0x0278
+#define MT6397_VCORE_CON10             0x027A
+#define MT6397_VCORE_CON11             0x027C
+#define MT6397_VCORE_CON12             0x027E
+#define MT6397_VCORE_CON13             0x0280
+#define MT6397_VCORE_CON14             0x0282
+#define MT6397_VCORE_CON15             0x0284
+#define MT6397_VCORE_CON16             0x0286
+#define MT6397_VCORE_CON17             0x0288
+#define MT6397_VCORE_CON18             0x028A
+#define MT6397_VGPU_CON0               0x028C
+#define MT6397_VGPU_CON1               0x028E
+#define MT6397_VGPU_CON2               0x0290
+#define MT6397_VGPU_CON3               0x0292
+#define MT6397_VGPU_CON4               0x0294
+#define MT6397_VGPU_CON5               0x0296
+#define MT6397_VGPU_CON6               0x0298
+#define MT6397_VGPU_CON7               0x029A
+#define MT6397_VGPU_CON8               0x029C
+#define MT6397_VGPU_CON9               0x029E
+#define MT6397_VGPU_CON10              0x02A0
+#define MT6397_VGPU_CON11              0x02A2
+#define MT6397_VGPU_CON12              0x02A4
+#define MT6397_VGPU_CON13              0x02A6
+#define MT6397_VGPU_CON14              0x02A8
+#define MT6397_VGPU_CON15              0x02AA
+#define MT6397_VGPU_CON16              0x02AC
+#define MT6397_VGPU_CON17              0x02AE
+#define MT6397_VGPU_CON18              0x02B0
+#define MT6397_VIO18_CON0              0x0300
+#define MT6397_VIO18_CON1              0x0302
+#define MT6397_VIO18_CON2              0x0304
+#define MT6397_VIO18_CON3              0x0306
+#define MT6397_VIO18_CON4              0x0308
+#define MT6397_VIO18_CON5              0x030A
+#define MT6397_VIO18_CON6              0x030C
+#define MT6397_VIO18_CON7              0x030E
+#define MT6397_VIO18_CON8              0x0310
+#define MT6397_VIO18_CON9              0x0312
+#define MT6397_VIO18_CON10             0x0314
+#define MT6397_VIO18_CON11             0x0316
+#define MT6397_VIO18_CON12             0x0318
+#define MT6397_VIO18_CON13             0x031A
+#define MT6397_VIO18_CON14             0x031C
+#define MT6397_VIO18_CON15             0x031E
+#define MT6397_VIO18_CON16             0x0320
+#define MT6397_VIO18_CON17             0x0322
+#define MT6397_VIO18_CON18             0x0324
+#define MT6397_VPCA7_CON0              0x0326
+#define MT6397_VPCA7_CON1              0x0328
+#define MT6397_VPCA7_CON2              0x032A
+#define MT6397_VPCA7_CON3              0x032C
+#define MT6397_VPCA7_CON4              0x032E
+#define MT6397_VPCA7_CON5              0x0330
+#define MT6397_VPCA7_CON6              0x0332
+#define MT6397_VPCA7_CON7              0x0334
+#define MT6397_VPCA7_CON8              0x0336
+#define MT6397_VPCA7_CON9              0x0338
+#define MT6397_VPCA7_CON10             0x033A
+#define MT6397_VPCA7_CON11             0x033C
+#define MT6397_VPCA7_CON12             0x033E
+#define MT6397_VPCA7_CON13             0x0340
+#define MT6397_VPCA7_CON14             0x0342
+#define MT6397_VPCA7_CON15             0x0344
+#define MT6397_VPCA7_CON16             0x0346
+#define MT6397_VPCA7_CON17             0x0348
+#define MT6397_VPCA7_CON18             0x034A
+#define MT6397_VSRMCA7_CON0            0x034C
+#define MT6397_VSRMCA7_CON1            0x034E
+#define MT6397_VSRMCA7_CON2            0x0350
+#define MT6397_VSRMCA7_CON3            0x0352
+#define MT6397_VSRMCA7_CON4            0x0354
+#define MT6397_VSRMCA7_CON5            0x0356
+#define MT6397_VSRMCA7_CON6            0x0358
+#define MT6397_VSRMCA7_CON7            0x035A
+#define MT6397_VSRMCA7_CON8            0x035C
+#define MT6397_VSRMCA7_CON9            0x035E
+#define MT6397_VSRMCA7_CON10           0x0360
+#define MT6397_VSRMCA7_CON11           0x0362
+#define MT6397_VSRMCA7_CON12           0x0364
+#define MT6397_VSRMCA7_CON13           0x0366
+#define MT6397_VSRMCA7_CON14           0x0368
+#define MT6397_VSRMCA7_CON15           0x036A
+#define MT6397_VSRMCA7_CON16           0x036C
+#define MT6397_VSRMCA7_CON17           0x036E
+#define MT6397_VSRMCA7_CON18           0x0370
+#define MT6397_VSRMCA7_CON19           0x0372
+#define MT6397_VSRMCA7_CON20           0x0374
+#define MT6397_VSRMCA7_CON21           0x0376
+#define MT6397_VDRM_CON0               0x0378
+#define MT6397_VDRM_CON1               0x037A
+#define MT6397_VDRM_CON2               0x037C
+#define MT6397_VDRM_CON3               0x037E
+#define MT6397_VDRM_CON4               0x0380
+#define MT6397_VDRM_CON5               0x0382
+#define MT6397_VDRM_CON6               0x0384
+#define MT6397_VDRM_CON7               0x0386
+#define MT6397_VDRM_CON8               0x0388
+#define MT6397_VDRM_CON9               0x038A
+#define MT6397_VDRM_CON10              0x038C
+#define MT6397_VDRM_CON11              0x038E
+#define MT6397_VDRM_CON12              0x0390
+#define MT6397_VDRM_CON13              0x0392
+#define MT6397_VDRM_CON14              0x0394
+#define MT6397_VDRM_CON15              0x0396
+#define MT6397_VDRM_CON16              0x0398
+#define MT6397_VDRM_CON17              0x039A
+#define MT6397_VDRM_CON18              0x039C
+#define MT6397_BUCK_K_CON0             0x039E
+#define MT6397_BUCK_K_CON1             0x03A0
+#define MT6397_ANALDO_CON0             0x0400
+#define MT6397_ANALDO_CON1             0x0402
+#define MT6397_ANALDO_CON2             0x0404
+#define MT6397_ANALDO_CON3             0x0406
+#define MT6397_ANALDO_CON4             0x0408
+#define MT6397_ANALDO_CON5             0x040A
+#define MT6397_ANALDO_CON6             0x040C
+#define MT6397_ANALDO_CON7             0x040E
+#define MT6397_DIGLDO_CON0             0x0410
+#define MT6397_DIGLDO_CON1             0x0412
+#define MT6397_DIGLDO_CON2             0x0414
+#define MT6397_DIGLDO_CON3             0x0416
+#define MT6397_DIGLDO_CON4             0x0418
+#define MT6397_DIGLDO_CON5             0x041A
+#define MT6397_DIGLDO_CON6             0x041C
+#define MT6397_DIGLDO_CON7             0x041E
+#define MT6397_DIGLDO_CON8             0x0420
+#define MT6397_DIGLDO_CON9             0x0422
+#define MT6397_DIGLDO_CON10            0x0424
+#define MT6397_DIGLDO_CON11            0x0426
+#define MT6397_DIGLDO_CON12            0x0428
+#define MT6397_DIGLDO_CON13            0x042A
+#define MT6397_DIGLDO_CON14            0x042C
+#define MT6397_DIGLDO_CON15            0x042E
+#define MT6397_DIGLDO_CON16            0x0430
+#define MT6397_DIGLDO_CON17            0x0432
+#define MT6397_DIGLDO_CON18            0x0434
+#define MT6397_DIGLDO_CON19            0x0436
+#define MT6397_DIGLDO_CON20            0x0438
+#define MT6397_DIGLDO_CON21            0x043A
+#define MT6397_DIGLDO_CON22            0x043C
+#define MT6397_DIGLDO_CON23            0x043E
+#define MT6397_DIGLDO_CON24            0x0440
+#define MT6397_DIGLDO_CON25            0x0442
+#define MT6397_DIGLDO_CON26            0x0444
+#define MT6397_DIGLDO_CON27            0x0446
+#define MT6397_DIGLDO_CON28            0x0448
+#define MT6397_DIGLDO_CON29            0x044A
+#define MT6397_DIGLDO_CON30            0x044C
+#define MT6397_DIGLDO_CON31            0x044E
+#define MT6397_DIGLDO_CON32            0x0450
+#define MT6397_DIGLDO_CON33            0x045A
+#define MT6397_SPK_CON0                        0x0600
+#define MT6397_SPK_CON1                        0x0602
+#define MT6397_SPK_CON2                        0x0604
+#define MT6397_SPK_CON3                        0x0606
+#define MT6397_SPK_CON4                        0x0608
+#define MT6397_SPK_CON5                        0x060A
+#define MT6397_SPK_CON6                        0x060C
+#define MT6397_SPK_CON7                        0x060E
+#define MT6397_SPK_CON8                        0x0610
+#define MT6397_SPK_CON9                        0x0612
+#define MT6397_SPK_CON10               0x0614
+#define MT6397_SPK_CON11               0x0616
+#define MT6397_AUDDAC_CON0             0x0700
+#define MT6397_AUDBUF_CFG0             0x0702
+#define MT6397_AUDBUF_CFG1             0x0704
+#define MT6397_AUDBUF_CFG2             0x0706
+#define MT6397_AUDBUF_CFG3             0x0708
+#define MT6397_AUDBUF_CFG4             0x070A
+#define MT6397_IBIASDIST_CFG0          0x070C
+#define MT6397_AUDACCDEPOP_CFG0                0x070E
+#define MT6397_AUD_IV_CFG0             0x0710
+#define MT6397_AUDCLKGEN_CFG0          0x0712
+#define MT6397_AUDLDO_CFG0             0x0714
+#define MT6397_AUDLDO_CFG1             0x0716
+#define MT6397_AUDNVREGGLB_CFG0                0x0718
+#define MT6397_AUD_NCP0                        0x071A
+#define MT6397_AUDPREAMP_CON0          0x071C
+#define MT6397_AUDADC_CON0             0x071E
+#define MT6397_AUDADC_CON1             0x0720
+#define MT6397_AUDADC_CON2             0x0722
+#define MT6397_AUDADC_CON3             0x0724
+#define MT6397_AUDADC_CON4             0x0726
+#define MT6397_AUDADC_CON5             0x0728
+#define MT6397_AUDADC_CON6             0x072A
+#define MT6397_AUDDIGMI_CON0           0x072C
+#define MT6397_AUDLSBUF_CON0           0x072E
+#define MT6397_AUDLSBUF_CON1           0x0730
+#define MT6397_AUDENCSPARE_CON0                0x0732
+#define MT6397_AUDENCCLKSQ_CON0                0x0734
+#define MT6397_AUDPREAMPGAIN_CON0      0x0736
+#define MT6397_ZCD_CON0                        0x0738
+#define MT6397_ZCD_CON1                        0x073A
+#define MT6397_ZCD_CON2                        0x073C
+#define MT6397_ZCD_CON3                        0x073E
+#define MT6397_ZCD_CON4                        0x0740
+#define MT6397_ZCD_CON5                        0x0742
+#define MT6397_NCP_CLKDIV_CON0         0x0744
+#define MT6397_NCP_CLKDIV_CON1         0x0746
+
+#endif /* __MFD_MT6397_REGISTERS_H__ */
index ee7b1ce7a6f8f42280abcc3d1411f7bcdebb6ac2..bb270bd03eedc3eb570555b9929b7ba652a38f6e 100644 (file)
@@ -117,6 +117,7 @@ struct palmas_pmic_driver_data {
        int ldo_begin;
        int ldo_end;
        int max_reg;
+       bool has_regen3;
        struct palmas_regs_info *palmas_regs_info;
        struct of_regulator_match *palmas_matches;
        struct palmas_sleep_requestor_info *sleep_req_info;
index fb09312d854bd75bec30f1f29dbd190c4d648151..441b6ee726910cc4ec24e16fe33e8c2fa8f668a0 100644 (file)
@@ -156,6 +156,9 @@ enum rk808_reg {
 #define BUCK2_RATE_MASK                (3 << 3)
 #define MASK_ALL       0xff
 
+#define BUCK_UV_ACT_MASK       0x0f
+#define BUCK_UV_ACT_DISABLE    0
+
 #define SWITCH2_EN     BIT(6)
 #define SWITCH1_EN     BIT(5)
 #define DEV_OFF_RST    BIT(3)
index 010cff49a98eba4f25370488e249dacd8c832552..6cff5cf458d2636d6bb77dd922b078ba3caaa7b7 100644 (file)
@@ -39,7 +39,7 @@ struct rt5033_battery {
        struct i2c_client       *client;
        struct rt5033_dev       *rt5033;
        struct regmap           *regmap;
-       struct power_supply     psy;
+       struct power_supply     *psy;
 };
 
 /* RT5033 charger platform data */
index 0c12628e91c6a9f9af0910f69c77b235f182aa49..ff843e7ca23ddf8fc17e6103986c348763290a48 100644 (file)
 
 #define MAX_RW_REG_CNT                 1024
 
-/* PCI Operation Register Address */
 #define RTSX_HCBAR                     0x00
 #define RTSX_HCBCTLR                   0x04
+#define   STOP_CMD                     (0x01 << 28)
+#define   READ_REG_CMD                 0
+#define   WRITE_REG_CMD                        1
+#define   CHECK_REG_CMD                        2
+
 #define RTSX_HDBAR                     0x08
+#define   SG_INT                       0x04
+#define   SG_END                       0x02
+#define   SG_VALID                     0x01
+#define   SG_NO_OP                     0x00
+#define   SG_TRANS_DATA                        (0x02 << 4)
+#define   SG_LINK_DESC                 (0x03 << 4)
 #define RTSX_HDBCTLR                   0x0C
+#define   SDMA_MODE                    0x00
+#define   ADMA_MODE                    (0x02 << 26)
+#define   STOP_DMA                     (0x01 << 28)
+#define   TRIG_DMA                     (0x01 << 31)
+
 #define RTSX_HAIMR                     0x10
-#define RTSX_BIPR                      0x14
-#define RTSX_BIER                      0x18
+#define   HAIMR_TRANS_START            (0x01 << 31)
+#define   HAIMR_READ                   0x00
+#define   HAIMR_WRITE                  (0x01 << 30)
+#define   HAIMR_READ_START             (HAIMR_TRANS_START | HAIMR_READ)
+#define   HAIMR_WRITE_START            (HAIMR_TRANS_START | HAIMR_WRITE)
+#define   HAIMR_TRANS_END                      (HAIMR_TRANS_START)
 
-/* Host command buffer control register */
-#define STOP_CMD                       (0x01 << 28)
-
-/* Host data buffer control register */
-#define SDMA_MODE                      0x00
-#define ADMA_MODE                      (0x02 << 26)
-#define STOP_DMA                       (0x01 << 28)
-#define TRIG_DMA                       (0x01 << 31)
-
-/* Host access internal memory register */
-#define HAIMR_TRANS_START              (0x01 << 31)
-#define HAIMR_READ                     0x00
-#define HAIMR_WRITE                    (0x01 << 30)
-#define HAIMR_READ_START               (HAIMR_TRANS_START | HAIMR_READ)
-#define HAIMR_WRITE_START              (HAIMR_TRANS_START | HAIMR_WRITE)
-#define HAIMR_TRANS_END                        (HAIMR_TRANS_START)
-
-/* Bus interrupt pending register */
-#define CMD_DONE_INT                   (1 << 31)
-#define DATA_DONE_INT                  (1 << 30)
-#define TRANS_OK_INT                   (1 << 29)
-#define TRANS_FAIL_INT                 (1 << 28)
-#define XD_INT                         (1 << 27)
-#define MS_INT                         (1 << 26)
-#define SD_INT                         (1 << 25)
-#define GPIO0_INT                      (1 << 24)
-#define OC_INT                         (1 << 23)
-#define SD_WRITE_PROTECT               (1 << 19)
-#define XD_EXIST                       (1 << 18)
-#define MS_EXIST                       (1 << 17)
-#define SD_EXIST                       (1 << 16)
-#define DELINK_INT                     GPIO0_INT
-#define MS_OC_INT                      (1 << 23)
-#define SD_OC_INT                      (1 << 22)
+#define RTSX_BIPR                      0x14
+#define   CMD_DONE_INT                 (1 << 31)
+#define   DATA_DONE_INT                        (1 << 30)
+#define   TRANS_OK_INT                 (1 << 29)
+#define   TRANS_FAIL_INT               (1 << 28)
+#define   XD_INT                       (1 << 27)
+#define   MS_INT                       (1 << 26)
+#define   SD_INT                       (1 << 25)
+#define   GPIO0_INT                    (1 << 24)
+#define   OC_INT                       (1 << 23)
+#define   SD_WRITE_PROTECT             (1 << 19)
+#define   XD_EXIST                     (1 << 18)
+#define   MS_EXIST                     (1 << 17)
+#define   SD_EXIST                     (1 << 16)
+#define   DELINK_INT                   GPIO0_INT
+#define   MS_OC_INT                    (1 << 23)
+#define   SD_OC_INT                    (1 << 22)
 
 #define CARD_INT               (XD_INT | MS_INT | SD_INT)
 #define NEED_COMPLETE_INT      (DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT)
 #define RTSX_INT               (CMD_DONE_INT | NEED_COMPLETE_INT | \
                                        CARD_INT | GPIO0_INT | OC_INT)
-
 #define CARD_EXIST             (XD_EXIST | MS_EXIST | SD_EXIST)
 
-/* Bus interrupt enable register */
-#define CMD_DONE_INT_EN                (1 << 31)
-#define DATA_DONE_INT_EN       (1 << 30)
-#define TRANS_OK_INT_EN                (1 << 29)
-#define TRANS_FAIL_INT_EN      (1 << 28)
-#define XD_INT_EN              (1 << 27)
-#define MS_INT_EN              (1 << 26)
-#define SD_INT_EN              (1 << 25)
-#define GPIO0_INT_EN           (1 << 24)
-#define OC_INT_EN              (1 << 23)
-#define DELINK_INT_EN          GPIO0_INT_EN
-#define MS_OC_INT_EN           (1 << 23)
-#define SD_OC_INT_EN           (1 << 22)
-
-#define READ_REG_CMD           0
-#define WRITE_REG_CMD          1
-#define CHECK_REG_CMD          2
+#define RTSX_BIER                      0x18
+#define   CMD_DONE_INT_EN              (1 << 31)
+#define   DATA_DONE_INT_EN             (1 << 30)
+#define   TRANS_OK_INT_EN              (1 << 29)
+#define   TRANS_FAIL_INT_EN            (1 << 28)
+#define   XD_INT_EN                    (1 << 27)
+#define   MS_INT_EN                    (1 << 26)
+#define   SD_INT_EN                    (1 << 25)
+#define   GPIO0_INT_EN                 (1 << 24)
+#define   OC_INT_EN                    (1 << 23)
+#define   DELINK_INT_EN                        GPIO0_INT_EN
+#define   MS_OC_INT_EN                 (1 << 23)
+#define   SD_OC_INT_EN                 (1 << 22)
+
 
 /*
  * macros for easy use
 #define rtsx_pci_write_config_dword(pcr, where, val) \
        pci_write_config_dword((pcr)->pci, where, val)
 
-#define STATE_TRANS_NONE       0
-#define STATE_TRANS_CMD                1
-#define STATE_TRANS_BUF                2
-#define STATE_TRANS_SG         3
-
-#define TRANS_NOT_READY                0
-#define TRANS_RESULT_OK                1
-#define TRANS_RESULT_FAIL      2
-#define TRANS_NO_DEVICE                3
-
-#define RTSX_RESV_BUF_LEN      4096
-#define HOST_CMDS_BUF_LEN      1024
-#define HOST_SG_TBL_BUF_LEN    (RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN)
-#define HOST_SG_TBL_ITEMS      (HOST_SG_TBL_BUF_LEN / 8)
-#define MAX_SG_ITEM_LEN                0x80000
-
-#define HOST_TO_DEVICE         0
-#define DEVICE_TO_HOST         1
-
-#define RTSX_PHASE_MAX         32
-#define RX_TUNING_CNT          3
-
-/* SG descriptor */
-#define SG_INT                 0x04
-#define SG_END                 0x02
-#define SG_VALID               0x01
-
-#define SG_NO_OP               0x00
-#define SG_TRANS_DATA          (0x02 << 4)
-#define SG_LINK_DESC           (0x03 << 4)
-
-/* Output voltage */
-#define OUTPUT_3V3             0
-#define OUTPUT_1V8             1
-
-/* Card Clock Enable Register */
-#define SD_CLK_EN                      0x04
-#define MS_CLK_EN                      0x08
-
-/* Card Select Register */
-#define SD_MOD_SEL                     2
-#define MS_MOD_SEL                     3
-
-/* Card Output Enable Register */
-#define SD_OUTPUT_EN                   0x04
-#define MS_OUTPUT_EN                   0x08
-
-/* CARD_SHARE_MODE */
-#define CARD_SHARE_MASK                        0x0F
-#define CARD_SHARE_MULTI_LUN           0x00
-#define        CARD_SHARE_NORMAL               0x00
-#define        CARD_SHARE_48_SD                0x04
-#define        CARD_SHARE_48_MS                0x08
-/* CARD_SHARE_MODE for barossa */
-#define CARD_SHARE_BAROSSA_SD          0x01
-#define CARD_SHARE_BAROSSA_MS          0x02
-
-/* CARD_DRIVE_SEL */
-#define MS_DRIVE_8mA                   (0x01 << 6)
-#define MMC_DRIVE_8mA                  (0x01 << 4)
-#define XD_DRIVE_8mA                   (0x01 << 2)
-#define GPIO_DRIVE_8mA                 0x01
-#define RTS5209_CARD_DRIVE_DEFAULT     (MS_DRIVE_8mA | MMC_DRIVE_8mA |\
-                                               XD_DRIVE_8mA | GPIO_DRIVE_8mA)
-#define RTL8411_CARD_DRIVE_DEFAULT     (MS_DRIVE_8mA | MMC_DRIVE_8mA |\
-                                               XD_DRIVE_8mA)
-#define RTSX_CARD_DRIVE_DEFAULT                (MS_DRIVE_8mA | GPIO_DRIVE_8mA)
+#define STATE_TRANS_NONE               0
+#define STATE_TRANS_CMD                        1
+#define STATE_TRANS_BUF                        2
+#define STATE_TRANS_SG                 3
 
-/* SD30_DRIVE_SEL */
-#define DRIVER_TYPE_A                  0x05
-#define DRIVER_TYPE_B                  0x03
-#define DRIVER_TYPE_C                  0x02
-#define DRIVER_TYPE_D                  0x01
-#define CFG_DRIVER_TYPE_A              0x02
-#define CFG_DRIVER_TYPE_B              0x03
-#define CFG_DRIVER_TYPE_C              0x01
-#define CFG_DRIVER_TYPE_D              0x00
-
-/* FPDCTL */
-#define SSC_POWER_DOWN                 0x01
-#define SD_OC_POWER_DOWN               0x02
-#define ALL_POWER_DOWN                 0x07
-#define OC_POWER_DOWN                  0x06
-
-/* CLK_CTL */
-#define CHANGE_CLK                     0x01
-
-/* LDO_CTL */
-#define BPP_ASIC_1V7                   0x00
-#define BPP_ASIC_1V8                   0x01
-#define BPP_ASIC_1V9                   0x02
-#define BPP_ASIC_2V0                   0x03
-#define BPP_ASIC_2V7                   0x04
-#define BPP_ASIC_2V8                   0x05
-#define BPP_ASIC_3V2                   0x06
-#define BPP_ASIC_3V3                   0x07
-#define BPP_REG_TUNED18                        0x07
-#define BPP_TUNED18_SHIFT_8402         5
-#define BPP_TUNED18_SHIFT_8411         4
-#define BPP_PAD_MASK                   0x04
-#define BPP_PAD_3V3                    0x04
-#define BPP_PAD_1V8                    0x00
-#define BPP_LDO_POWB                   0x03
-#define BPP_LDO_ON                     0x00
-#define BPP_LDO_SUSPEND                        0x02
-#define BPP_LDO_OFF                    0x03
-
-/* CD_PAD_CTL */
-#define CD_DISABLE_MASK                        0x07
-#define MS_CD_DISABLE                  0x04
-#define SD_CD_DISABLE                  0x02
-#define XD_CD_DISABLE                  0x01
-#define CD_DISABLE                     0x07
-#define CD_ENABLE                      0x00
-#define MS_CD_EN_ONLY                  0x03
-#define SD_CD_EN_ONLY                  0x05
-#define XD_CD_EN_ONLY                  0x06
-#define FORCE_CD_LOW_MASK              0x38
-#define FORCE_CD_XD_LOW                        0x08
-#define FORCE_CD_SD_LOW                        0x10
-#define FORCE_CD_MS_LOW                        0x20
-#define CD_AUTO_DISABLE                        0x40
-
-/* SD_STAT1 */
-#define        SD_CRC7_ERR                     0x80
-#define        SD_CRC16_ERR                    0x40
-#define        SD_CRC_WRITE_ERR                0x20
-#define        SD_CRC_WRITE_ERR_MASK           0x1C
-#define        GET_CRC_TIME_OUT                0x02
-#define        SD_TUNING_COMPARE_ERR           0x01
-
-/* SD_STAT2 */
-#define        SD_RSP_80CLK_TIMEOUT            0x01
-
-/* SD_BUS_STAT */
-#define        SD_CLK_TOGGLE_EN                0x80
-#define        SD_CLK_FORCE_STOP               0x40
-#define        SD_DAT3_STATUS                  0x10
-#define        SD_DAT2_STATUS                  0x08
-#define        SD_DAT1_STATUS                  0x04
-#define        SD_DAT0_STATUS                  0x02
-#define        SD_CMD_STATUS                   0x01
-
-/* SD_PAD_CTL */
-#define        SD_IO_USING_1V8                 0x80
-#define        SD_IO_USING_3V3                 0x7F
-#define        TYPE_A_DRIVING                  0x00
-#define        TYPE_B_DRIVING                  0x01
-#define        TYPE_C_DRIVING                  0x02
-#define        TYPE_D_DRIVING                  0x03
-
-/* SD_SAMPLE_POINT_CTL */
-#define        DDR_FIX_RX_DAT                  0x00
-#define        DDR_VAR_RX_DAT                  0x80
-#define        DDR_FIX_RX_DAT_EDGE             0x00
-#define        DDR_FIX_RX_DAT_14_DELAY         0x40
-#define        DDR_FIX_RX_CMD                  0x00
-#define        DDR_VAR_RX_CMD                  0x20
-#define        DDR_FIX_RX_CMD_POS_EDGE         0x00
-#define        DDR_FIX_RX_CMD_14_DELAY         0x10
-#define        SD20_RX_POS_EDGE                0x00
-#define        SD20_RX_14_DELAY                0x08
-#define SD20_RX_SEL_MASK               0x08
+#define TRANS_NOT_READY                        0
+#define TRANS_RESULT_OK                        1
+#define TRANS_RESULT_FAIL              2
+#define TRANS_NO_DEVICE                        3
 
-/* SD_PUSH_POINT_CTL */
-#define        DDR_FIX_TX_CMD_DAT              0x00
-#define        DDR_VAR_TX_CMD_DAT              0x80
-#define        DDR_FIX_TX_DAT_14_TSU           0x00
-#define        DDR_FIX_TX_DAT_12_TSU           0x40
-#define        DDR_FIX_TX_CMD_NEG_EDGE         0x00
-#define        DDR_FIX_TX_CMD_14_AHEAD         0x20
-#define        SD20_TX_NEG_EDGE                0x00
-#define        SD20_TX_14_AHEAD                0x10
-#define SD20_TX_SEL_MASK               0x10
-#define        DDR_VAR_SDCLK_POL_SWAP          0x01
-
-/* SD_TRANSFER */
-#define        SD_TRANSFER_START               0x80
-#define        SD_TRANSFER_END                 0x40
-#define SD_STAT_IDLE                   0x20
-#define        SD_TRANSFER_ERR                 0x10
-/* SD Transfer Mode definition */
-#define        SD_TM_NORMAL_WRITE              0x00
-#define        SD_TM_AUTO_WRITE_3              0x01
-#define        SD_TM_AUTO_WRITE_4              0x02
-#define        SD_TM_AUTO_READ_3               0x05
-#define        SD_TM_AUTO_READ_4               0x06
-#define        SD_TM_CMD_RSP                   0x08
-#define        SD_TM_AUTO_WRITE_1              0x09
-#define        SD_TM_AUTO_WRITE_2              0x0A
-#define        SD_TM_NORMAL_READ               0x0C
-#define        SD_TM_AUTO_READ_1               0x0D
-#define        SD_TM_AUTO_READ_2               0x0E
-#define        SD_TM_AUTO_TUNING               0x0F
-
-/* SD_VPTX_CTL / SD_VPRX_CTL */
-#define PHASE_CHANGE                   0x80
-#define PHASE_NOT_RESET                        0x40
-
-/* SD_DCMPS_TX_CTL / SD_DCMPS_RX_CTL */
-#define DCMPS_CHANGE                   0x80
-#define DCMPS_CHANGE_DONE              0x40
-#define DCMPS_ERROR                    0x20
-#define DCMPS_CURRENT_PHASE            0x1F
-
-/* SD Configure 1 Register */
-#define SD_CLK_DIVIDE_0                        0x00
-#define        SD_CLK_DIVIDE_256               0xC0
-#define        SD_CLK_DIVIDE_128               0x80
-#define        SD_BUS_WIDTH_1BIT               0x00
-#define        SD_BUS_WIDTH_4BIT               0x01
-#define        SD_BUS_WIDTH_8BIT               0x02
-#define        SD_ASYNC_FIFO_NOT_RST           0x10
-#define        SD_20_MODE                      0x00
-#define        SD_DDR_MODE                     0x04
-#define        SD_30_MODE                      0x08
-
-#define SD_CLK_DIVIDE_MASK             0xC0
-
-/* SD_CMD_STATE */
-#define SD_CMD_IDLE                    0x80
-
-/* SD_DATA_STATE */
-#define SD_DATA_IDLE                   0x80
-
-/* DCM_DRP_CTL */
-#define DCM_RESET                      0x08
-#define DCM_LOCKED                     0x04
-#define DCM_208M                       0x00
-#define DCM_TX                         0x01
-#define DCM_RX                         0x02
-
-/* DCM_DRP_TRIG */
-#define DRP_START                      0x80
-#define DRP_DONE                       0x40
-
-/* DCM_DRP_CFG */
-#define DRP_WRITE                      0x80
-#define DRP_READ                       0x00
-#define DCM_WRITE_ADDRESS_50           0x50
-#define DCM_WRITE_ADDRESS_51           0x51
-#define DCM_READ_ADDRESS_00            0x00
-#define DCM_READ_ADDRESS_51            0x51
-
-/* IRQSTAT0 */
-#define DMA_DONE_INT                   0x80
-#define SUSPEND_INT                    0x40
-#define LINK_RDY_INT                   0x20
-#define LINK_DOWN_INT                  0x10
-
-/* DMACTL */
-#define DMA_RST                                0x80
-#define DMA_BUSY                       0x04
-#define DMA_DIR_TO_CARD                        0x00
-#define DMA_DIR_FROM_CARD              0x02
-#define DMA_EN                         0x01
-#define DMA_128                                (0 << 4)
-#define DMA_256                                (1 << 4)
-#define DMA_512                                (2 << 4)
-#define DMA_1024                       (3 << 4)
-#define DMA_PACK_SIZE_MASK             0x30
-
-/* SSC_CTL1 */
-#define SSC_RSTB                       0x80
-#define SSC_8X_EN                      0x40
-#define SSC_FIX_FRAC                   0x20
-#define SSC_SEL_1M                     0x00
-#define SSC_SEL_2M                     0x08
-#define SSC_SEL_4M                     0x10
-#define SSC_SEL_8M                     0x18
-
-/* SSC_CTL2 */
-#define SSC_DEPTH_MASK                 0x07
-#define SSC_DEPTH_DISALBE              0x00
-#define SSC_DEPTH_4M                   0x01
-#define SSC_DEPTH_2M                   0x02
-#define SSC_DEPTH_1M                   0x03
-#define SSC_DEPTH_500K                 0x04
-#define SSC_DEPTH_250K                 0x05
-
-/* System Clock Control Register */
-#define CLK_LOW_FREQ                   0x01
-
-/* System Clock Divider Register */
-#define CLK_DIV_1                      0x01
-#define CLK_DIV_2                      0x02
-#define CLK_DIV_4                      0x03
-#define CLK_DIV_8                      0x04
-
-/* MS_CFG */
-#define        SAMPLE_TIME_RISING              0x00
-#define        SAMPLE_TIME_FALLING             0x80
-#define        PUSH_TIME_DEFAULT               0x00
-#define        PUSH_TIME_ODD                   0x40
-#define        NO_EXTEND_TOGGLE                0x00
-#define        EXTEND_TOGGLE_CHK               0x20
-#define        MS_BUS_WIDTH_1                  0x00
-#define        MS_BUS_WIDTH_4                  0x10
-#define        MS_BUS_WIDTH_8                  0x18
-#define        MS_2K_SECTOR_MODE               0x04
-#define        MS_512_SECTOR_MODE              0x00
-#define        MS_TOGGLE_TIMEOUT_EN            0x00
-#define        MS_TOGGLE_TIMEOUT_DISEN         0x01
-#define MS_NO_CHECK_INT                        0x02
+#define RTSX_RESV_BUF_LEN              4096
+#define HOST_CMDS_BUF_LEN              1024
+#define HOST_SG_TBL_BUF_LEN            (RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN)
+#define HOST_SG_TBL_ITEMS              (HOST_SG_TBL_BUF_LEN / 8)
+#define MAX_SG_ITEM_LEN                        0x80000
+#define HOST_TO_DEVICE                 0
+#define DEVICE_TO_HOST                 1
 
-/* MS_TRANS_CFG */
-#define        WAIT_INT                        0x80
-#define        NO_WAIT_INT                     0x00
-#define        NO_AUTO_READ_INT_REG            0x00
-#define        AUTO_READ_INT_REG               0x40
-#define        MS_CRC16_ERR                    0x20
-#define        MS_RDY_TIMEOUT                  0x10
-#define        MS_INT_CMDNK                    0x08
-#define        MS_INT_BREQ                     0x04
-#define        MS_INT_ERR                      0x02
-#define        MS_INT_CED                      0x01
-
-/* MS_TRANSFER */
-#define        MS_TRANSFER_START               0x80
-#define        MS_TRANSFER_END                 0x40
-#define        MS_TRANSFER_ERR                 0x20
-#define        MS_BS_STATE                     0x10
-#define        MS_TM_READ_BYTES                0x00
-#define        MS_TM_NORMAL_READ               0x01
-#define        MS_TM_WRITE_BYTES               0x04
-#define        MS_TM_NORMAL_WRITE              0x05
-#define        MS_TM_AUTO_READ                 0x08
-#define        MS_TM_AUTO_WRITE                0x0C
-
-/* SD Configure 2 Register */
-#define        SD_CALCULATE_CRC7               0x00
-#define        SD_NO_CALCULATE_CRC7            0x80
-#define        SD_CHECK_CRC16                  0x00
-#define        SD_NO_CHECK_CRC16               0x40
-#define SD_NO_CHECK_WAIT_CRC_TO                0x20
-#define        SD_WAIT_BUSY_END                0x08
-#define        SD_NO_WAIT_BUSY_END             0x00
-#define        SD_CHECK_CRC7                   0x00
-#define        SD_NO_CHECK_CRC7                0x04
-#define        SD_RSP_LEN_0                    0x00
-#define        SD_RSP_LEN_6                    0x01
-#define        SD_RSP_LEN_17                   0x02
-/* SD/MMC Response Type Definition */
-#define        SD_RSP_TYPE_R0                  0x04
-#define        SD_RSP_TYPE_R1                  0x01
-#define        SD_RSP_TYPE_R1b                 0x09
-#define        SD_RSP_TYPE_R2                  0x02
-#define        SD_RSP_TYPE_R3                  0x05
-#define        SD_RSP_TYPE_R4                  0x05
-#define        SD_RSP_TYPE_R5                  0x01
-#define        SD_RSP_TYPE_R6                  0x01
-#define        SD_RSP_TYPE_R7                  0x01
-
-/* SD_CONFIGURE3 */
-#define        SD_RSP_80CLK_TIMEOUT_EN         0x01
-
-/* Card Transfer Reset Register */
-#define SPI_STOP                       0x01
-#define XD_STOP                                0x02
-#define SD_STOP                                0x04
-#define MS_STOP                                0x08
-#define SPI_CLR_ERR                    0x10
-#define XD_CLR_ERR                     0x20
-#define SD_CLR_ERR                     0x40
-#define MS_CLR_ERR                     0x80
-
-/* Card Data Source Register */
-#define PINGPONG_BUFFER                        0x01
-#define RING_BUFFER                    0x00
-
-/* Card Power Control Register */
-#define PMOS_STRG_MASK                 0x10
-#define PMOS_STRG_800mA                        0x10
-#define PMOS_STRG_400mA                        0x00
-#define SD_POWER_OFF                   0x03
-#define SD_PARTIAL_POWER_ON            0x01
-#define SD_POWER_ON                    0x00
-#define SD_POWER_MASK                  0x03
-#define MS_POWER_OFF                   0x0C
-#define MS_PARTIAL_POWER_ON            0x04
-#define MS_POWER_ON                    0x00
-#define MS_POWER_MASK                  0x0C
-#define BPP_POWER_OFF                  0x0F
-#define BPP_POWER_5_PERCENT_ON         0x0E
-#define BPP_POWER_10_PERCENT_ON                0x0C
-#define BPP_POWER_15_PERCENT_ON                0x08
-#define BPP_POWER_ON                   0x00
-#define BPP_POWER_MASK                 0x0F
-#define SD_VCC_PARTIAL_POWER_ON                0x02
-#define SD_VCC_POWER_ON                        0x00
-
-/* PWR_GATE_CTRL */
-#define PWR_GATE_EN                    0x01
-#define LDO3318_PWR_MASK               0x06
-#define LDO_ON                         0x00
-#define LDO_SUSPEND                    0x04
-#define LDO_OFF                                0x06
-
-/* CARD_CLK_SOURCE */
-#define CRC_FIX_CLK                    (0x00 << 0)
-#define CRC_VAR_CLK0                   (0x01 << 0)
-#define CRC_VAR_CLK1                   (0x02 << 0)
-#define SD30_FIX_CLK                   (0x00 << 2)
-#define SD30_VAR_CLK0                  (0x01 << 2)
-#define SD30_VAR_CLK1                  (0x02 << 2)
-#define SAMPLE_FIX_CLK                 (0x00 << 4)
-#define SAMPLE_VAR_CLK0                        (0x01 << 4)
-#define SAMPLE_VAR_CLK1                        (0x02 << 4)
-
-/* HOST_SLEEP_STATE */
-#define HOST_ENTER_S1                  1
-#define HOST_ENTER_S3                  2
+#define OUTPUT_3V3                     0
+#define OUTPUT_1V8                     1
+
+#define RTSX_PHASE_MAX                 32
+#define RX_TUNING_CNT                  3
 
 #define MS_CFG                         0xFD40
+#define   SAMPLE_TIME_RISING           0x00
+#define   SAMPLE_TIME_FALLING          0x80
+#define   PUSH_TIME_DEFAULT            0x00
+#define   PUSH_TIME_ODD                        0x40
+#define   NO_EXTEND_TOGGLE             0x00
+#define   EXTEND_TOGGLE_CHK            0x20
+#define   MS_BUS_WIDTH_1               0x00
+#define   MS_BUS_WIDTH_4               0x10
+#define   MS_BUS_WIDTH_8               0x18
+#define   MS_2K_SECTOR_MODE            0x04
+#define   MS_512_SECTOR_MODE           0x00
+#define   MS_TOGGLE_TIMEOUT_EN         0x00
+#define   MS_TOGGLE_TIMEOUT_DISEN      0x01
+#define MS_NO_CHECK_INT                        0x02
 #define MS_TPC                         0xFD41
 #define MS_TRANS_CFG                   0xFD42
+#define   WAIT_INT                     0x80
+#define   NO_WAIT_INT                  0x00
+#define   NO_AUTO_READ_INT_REG         0x00
+#define   AUTO_READ_INT_REG            0x40
+#define   MS_CRC16_ERR                 0x20
+#define   MS_RDY_TIMEOUT               0x10
+#define   MS_INT_CMDNK                 0x08
+#define   MS_INT_BREQ                  0x04
+#define   MS_INT_ERR                   0x02
+#define   MS_INT_CED                   0x01
 #define MS_TRANSFER                    0xFD43
+#define   MS_TRANSFER_START            0x80
+#define   MS_TRANSFER_END              0x40
+#define   MS_TRANSFER_ERR              0x20
+#define   MS_BS_STATE                  0x10
+#define   MS_TM_READ_BYTES             0x00
+#define   MS_TM_NORMAL_READ            0x01
+#define   MS_TM_WRITE_BYTES            0x04
+#define   MS_TM_NORMAL_WRITE           0x05
+#define   MS_TM_AUTO_READ              0x08
+#define   MS_TM_AUTO_WRITE             0x0C
 #define MS_INT_REG                     0xFD44
 #define MS_BYTE_CNT                    0xFD45
 #define MS_SECTOR_CNT_L                        0xFD46
 #define MS_DBUS_H                      0xFD48
 
 #define SD_CFG1                                0xFDA0
+#define   SD_CLK_DIVIDE_0              0x00
+#define   SD_CLK_DIVIDE_256            0xC0
+#define   SD_CLK_DIVIDE_128            0x80
+#define   SD_BUS_WIDTH_1BIT            0x00
+#define   SD_BUS_WIDTH_4BIT            0x01
+#define   SD_BUS_WIDTH_8BIT            0x02
+#define   SD_ASYNC_FIFO_NOT_RST                0x10
+#define   SD_20_MODE                   0x00
+#define   SD_DDR_MODE                  0x04
+#define   SD_30_MODE                   0x08
+#define   SD_CLK_DIVIDE_MASK           0xC0
 #define SD_CFG2                                0xFDA1
+#define   SD_CALCULATE_CRC7            0x00
+#define   SD_NO_CALCULATE_CRC7         0x80
+#define   SD_CHECK_CRC16               0x00
+#define   SD_NO_CHECK_CRC16            0x40
+#define   SD_NO_CHECK_WAIT_CRC_TO      0x20
+#define   SD_WAIT_BUSY_END             0x08
+#define   SD_NO_WAIT_BUSY_END          0x00
+#define   SD_CHECK_CRC7                        0x00
+#define   SD_NO_CHECK_CRC7             0x04
+#define   SD_RSP_LEN_0                 0x00
+#define   SD_RSP_LEN_6                 0x01
+#define   SD_RSP_LEN_17                        0x02
+#define   SD_RSP_TYPE_R0               0x04
+#define   SD_RSP_TYPE_R1               0x01
+#define   SD_RSP_TYPE_R1b              0x09
+#define   SD_RSP_TYPE_R2               0x02
+#define   SD_RSP_TYPE_R3               0x05
+#define   SD_RSP_TYPE_R4               0x05
+#define   SD_RSP_TYPE_R5               0x01
+#define   SD_RSP_TYPE_R6               0x01
+#define   SD_RSP_TYPE_R7               0x01
 #define SD_CFG3                                0xFDA2
+#define   SD_RSP_80CLK_TIMEOUT_EN      0x01
+
 #define SD_STAT1                       0xFDA3
+#define   SD_CRC7_ERR                  0x80
+#define   SD_CRC16_ERR                 0x40
+#define   SD_CRC_WRITE_ERR             0x20
+#define   SD_CRC_WRITE_ERR_MASK                0x1C
+#define   GET_CRC_TIME_OUT             0x02
+#define   SD_TUNING_COMPARE_ERR                0x01
 #define SD_STAT2                       0xFDA4
+#define   SD_RSP_80CLK_TIMEOUT         0x01
+
 #define SD_BUS_STAT                    0xFDA5
+#define   SD_CLK_TOGGLE_EN             0x80
+#define   SD_CLK_FORCE_STOP            0x40
+#define   SD_DAT3_STATUS               0x10
+#define   SD_DAT2_STATUS               0x08
+#define   SD_DAT1_STATUS               0x04
+#define   SD_DAT0_STATUS               0x02
+#define   SD_CMD_STATUS                        0x01
 #define SD_PAD_CTL                     0xFDA6
+#define   SD_IO_USING_1V8              0x80
+#define   SD_IO_USING_3V3              0x7F
+#define   TYPE_A_DRIVING               0x00
+#define   TYPE_B_DRIVING               0x01
+#define   TYPE_C_DRIVING               0x02
+#define   TYPE_D_DRIVING               0x03
 #define SD_SAMPLE_POINT_CTL            0xFDA7
+#define   DDR_FIX_RX_DAT               0x00
+#define   DDR_VAR_RX_DAT               0x80
+#define   DDR_FIX_RX_DAT_EDGE          0x00
+#define   DDR_FIX_RX_DAT_14_DELAY      0x40
+#define   DDR_FIX_RX_CMD               0x00
+#define   DDR_VAR_RX_CMD               0x20
+#define   DDR_FIX_RX_CMD_POS_EDGE      0x00
+#define   DDR_FIX_RX_CMD_14_DELAY      0x10
+#define   SD20_RX_POS_EDGE             0x00
+#define   SD20_RX_14_DELAY             0x08
+#define SD20_RX_SEL_MASK               0x08
 #define SD_PUSH_POINT_CTL              0xFDA8
+#define   DDR_FIX_TX_CMD_DAT           0x00
+#define   DDR_VAR_TX_CMD_DAT           0x80
+#define   DDR_FIX_TX_DAT_14_TSU                0x00
+#define   DDR_FIX_TX_DAT_12_TSU                0x40
+#define   DDR_FIX_TX_CMD_NEG_EDGE      0x00
+#define   DDR_FIX_TX_CMD_14_AHEAD      0x20
+#define   SD20_TX_NEG_EDGE             0x00
+#define   SD20_TX_14_AHEAD             0x10
+#define   SD20_TX_SEL_MASK             0x10
+#define   DDR_VAR_SDCLK_POL_SWAP       0x01
 #define SD_CMD0                                0xFDA9
 #define   SD_CMD_START                 0x40
 #define SD_CMD1                                0xFDAA
 #define SD_BLOCK_CNT_L                 0xFDB1
 #define SD_BLOCK_CNT_H                 0xFDB2
 #define SD_TRANSFER                    0xFDB3
+#define   SD_TRANSFER_START            0x80
+#define   SD_TRANSFER_END              0x40
+#define   SD_STAT_IDLE                 0x20
+#define   SD_TRANSFER_ERR              0x10
+#define   SD_TM_NORMAL_WRITE           0x00
+#define   SD_TM_AUTO_WRITE_3           0x01
+#define   SD_TM_AUTO_WRITE_4           0x02
+#define   SD_TM_AUTO_READ_3            0x05
+#define   SD_TM_AUTO_READ_4            0x06
+#define   SD_TM_CMD_RSP                        0x08
+#define   SD_TM_AUTO_WRITE_1           0x09
+#define   SD_TM_AUTO_WRITE_2           0x0A
+#define   SD_TM_NORMAL_READ            0x0C
+#define   SD_TM_AUTO_READ_1            0x0D
+#define   SD_TM_AUTO_READ_2            0x0E
+#define   SD_TM_AUTO_TUNING            0x0F
 #define SD_CMD_STATE                   0xFDB5
+#define   SD_CMD_IDLE                  0x80
+
 #define SD_DATA_STATE                  0xFDB6
+#define   SD_DATA_IDLE                 0x80
 
 #define SRCTL                          0xFC13
 
-#define        DCM_DRP_CTL                     0xFC23
-#define        DCM_DRP_TRIG                    0xFC24
-#define        DCM_DRP_CFG                     0xFC25
-#define        DCM_DRP_WR_DATA_L               0xFC26
-#define        DCM_DRP_WR_DATA_H               0xFC27
-#define        DCM_DRP_RD_DATA_L               0xFC28
-#define        DCM_DRP_RD_DATA_H               0xFC29
+#define DCM_DRP_CTL                    0xFC23
+#define   DCM_RESET                    0x08
+#define   DCM_LOCKED                   0x04
+#define   DCM_208M                     0x00
+#define   DCM_TX                       0x01
+#define   DCM_RX                       0x02
+#define DCM_DRP_TRIG                   0xFC24
+#define   DRP_START                    0x80
+#define   DRP_DONE                     0x40
+#define DCM_DRP_CFG                    0xFC25
+#define   DRP_WRITE                    0x80
+#define   DRP_READ                     0x00
+#define   DCM_WRITE_ADDRESS_50         0x50
+#define   DCM_WRITE_ADDRESS_51         0x51
+#define   DCM_READ_ADDRESS_00          0x00
+#define   DCM_READ_ADDRESS_51          0x51
+#define DCM_DRP_WR_DATA_L              0xFC26
+#define DCM_DRP_WR_DATA_H              0xFC27
+#define DCM_DRP_RD_DATA_L              0xFC28
+#define DCM_DRP_RD_DATA_H              0xFC29
 #define SD_VPCLK0_CTL                  0xFC2A
 #define SD_VPCLK1_CTL                  0xFC2B
 #define SD_DCMPS0_CTL                  0xFC2C
 #define SD_DCMPS1_CTL                  0xFC2D
 #define SD_VPTX_CTL                    SD_VPCLK0_CTL
 #define SD_VPRX_CTL                    SD_VPCLK1_CTL
+#define   PHASE_CHANGE                 0x80
+#define   PHASE_NOT_RESET              0x40
 #define SD_DCMPS_TX_CTL                        SD_DCMPS0_CTL
 #define SD_DCMPS_RX_CTL                        SD_DCMPS1_CTL
+#define   DCMPS_CHANGE                 0x80
+#define   DCMPS_CHANGE_DONE            0x40
+#define   DCMPS_ERROR                  0x20
+#define   DCMPS_CURRENT_PHASE          0x1F
 #define CARD_CLK_SOURCE                        0xFC2E
-
+#define   CRC_FIX_CLK                  (0x00 << 0)
+#define   CRC_VAR_CLK0                 (0x01 << 0)
+#define   CRC_VAR_CLK1                 (0x02 << 0)
+#define   SD30_FIX_CLK                 (0x00 << 2)
+#define   SD30_VAR_CLK0                        (0x01 << 2)
+#define   SD30_VAR_CLK1                        (0x02 << 2)
+#define   SAMPLE_FIX_CLK               (0x00 << 4)
+#define   SAMPLE_VAR_CLK0              (0x01 << 4)
+#define   SAMPLE_VAR_CLK1              (0x02 << 4)
 #define CARD_PWR_CTL                   0xFD50
+#define   PMOS_STRG_MASK               0x10
+#define   PMOS_STRG_800mA              0x10
+#define   PMOS_STRG_400mA              0x00
+#define   SD_POWER_OFF                 0x03
+#define   SD_PARTIAL_POWER_ON          0x01
+#define   SD_POWER_ON                  0x00
+#define   SD_POWER_MASK                        0x03
+#define   MS_POWER_OFF                 0x0C
+#define   MS_PARTIAL_POWER_ON          0x04
+#define   MS_POWER_ON                  0x00
+#define   MS_POWER_MASK                        0x0C
+#define   BPP_POWER_OFF                        0x0F
+#define   BPP_POWER_5_PERCENT_ON       0x0E
+#define   BPP_POWER_10_PERCENT_ON      0x0C
+#define   BPP_POWER_15_PERCENT_ON      0x08
+#define   BPP_POWER_ON                 0x00
+#define   BPP_POWER_MASK               0x0F
+#define   SD_VCC_PARTIAL_POWER_ON      0x02
+#define   SD_VCC_POWER_ON              0x00
 #define CARD_CLK_SWITCH                        0xFD51
 #define RTL8411B_PACKAGE_MODE          0xFD51
 #define CARD_SHARE_MODE                        0xFD52
+#define   CARD_SHARE_MASK              0x0F
+#define   CARD_SHARE_MULTI_LUN         0x00
+#define   CARD_SHARE_NORMAL            0x00
+#define   CARD_SHARE_48_SD             0x04
+#define   CARD_SHARE_48_MS             0x08
+#define   CARD_SHARE_BAROSSA_SD                0x01
+#define   CARD_SHARE_BAROSSA_MS                0x02
 #define CARD_DRIVE_SEL                 0xFD53
+#define   MS_DRIVE_8mA                 (0x01 << 6)
+#define   MMC_DRIVE_8mA                        (0x01 << 4)
+#define   XD_DRIVE_8mA                 (0x01 << 2)
+#define   GPIO_DRIVE_8mA               0x01
+#define RTS5209_CARD_DRIVE_DEFAULT     (MS_DRIVE_8mA | MMC_DRIVE_8mA |\
+                                       XD_DRIVE_8mA | GPIO_DRIVE_8mA)
+#define RTL8411_CARD_DRIVE_DEFAULT     (MS_DRIVE_8mA | MMC_DRIVE_8mA |\
+                                       XD_DRIVE_8mA)
+#define RTSX_CARD_DRIVE_DEFAULT                (MS_DRIVE_8mA | GPIO_DRIVE_8mA)
+
 #define CARD_STOP                      0xFD54
+#define   SPI_STOP                     0x01
+#define   XD_STOP                      0x02
+#define   SD_STOP                      0x04
+#define   MS_STOP                      0x08
+#define   SPI_CLR_ERR                  0x10
+#define   XD_CLR_ERR                   0x20
+#define   SD_CLR_ERR                   0x40
+#define   MS_CLR_ERR                   0x80
 #define CARD_OE                                0xFD55
+#define   SD_OUTPUT_EN                 0x04
+#define   MS_OUTPUT_EN                 0x08
 #define CARD_AUTO_BLINK                        0xFD56
 #define CARD_GPIO_DIR                  0xFD57
 #define CARD_GPIO                      0xFD58
 #define CARD_DATA_SOURCE               0xFD5B
+#define   PINGPONG_BUFFER              0x01
+#define   RING_BUFFER                  0x00
 #define SD30_CLK_DRIVE_SEL             0xFD5A
+#define   DRIVER_TYPE_A                        0x05
+#define   DRIVER_TYPE_B                        0x03
+#define   DRIVER_TYPE_C                        0x02
+#define   DRIVER_TYPE_D                        0x01
 #define CARD_SELECT                    0xFD5C
+#define   SD_MOD_SEL                   2
+#define   MS_MOD_SEL                   3
 #define SD30_DRIVE_SEL                 0xFD5E
+#define   CFG_DRIVER_TYPE_A            0x02
+#define   CFG_DRIVER_TYPE_B            0x03
+#define   CFG_DRIVER_TYPE_C            0x01
+#define   CFG_DRIVER_TYPE_D            0x00
 #define SD30_CMD_DRIVE_SEL             0xFD5E
 #define SD30_DAT_DRIVE_SEL             0xFD5F
 #define CARD_CLK_EN                    0xFD69
+#define   SD_CLK_EN                    0x04
+#define   MS_CLK_EN                    0x08
 #define SDIO_CTRL                      0xFD6B
 #define CD_PAD_CTL                     0xFD73
-
+#define   CD_DISABLE_MASK              0x07
+#define   MS_CD_DISABLE                        0x04
+#define   SD_CD_DISABLE                        0x02
+#define   XD_CD_DISABLE                        0x01
+#define   CD_DISABLE                   0x07
+#define   CD_ENABLE                    0x00
+#define   MS_CD_EN_ONLY                        0x03
+#define   SD_CD_EN_ONLY                        0x05
+#define   XD_CD_EN_ONLY                        0x06
+#define   FORCE_CD_LOW_MASK            0x38
+#define   FORCE_CD_XD_LOW              0x08
+#define   FORCE_CD_SD_LOW              0x10
+#define   FORCE_CD_MS_LOW              0x20
+#define   CD_AUTO_DISABLE              0x40
 #define FPDCTL                         0xFC00
+#define   SSC_POWER_DOWN               0x01
+#define   SD_OC_POWER_DOWN             0x02
+#define   ALL_POWER_DOWN               0x07
+#define   OC_POWER_DOWN                        0x06
 #define PDINFO                         0xFC01
 
 #define CLK_CTL                                0xFC02
+#define   CHANGE_CLK                   0x01
+#define   CLK_LOW_FREQ                 0x01
+
 #define CLK_DIV                                0xFC03
+#define   CLK_DIV_1                    0x01
+#define   CLK_DIV_2                    0x02
+#define   CLK_DIV_4                    0x03
+#define   CLK_DIV_8                    0x04
 #define CLK_SEL                                0xFC04
 
 #define SSC_DIV_N_0                    0xFC0F
 #define SSC_DIV_N_1                    0xFC10
 #define SSC_CTL1                       0xFC11
+#define    SSC_RSTB                    0x80
+#define    SSC_8X_EN                   0x40
+#define    SSC_FIX_FRAC                        0x20
+#define    SSC_SEL_1M                  0x00
+#define    SSC_SEL_2M                  0x08
+#define    SSC_SEL_4M                  0x10
+#define    SSC_SEL_8M                  0x18
 #define SSC_CTL2                       0xFC12
-
+#define    SSC_DEPTH_MASK              0x07
+#define    SSC_DEPTH_DISALBE           0x00
+#define    SSC_DEPTH_4M                        0x01
+#define    SSC_DEPTH_2M                        0x02
+#define    SSC_DEPTH_1M                        0x03
+#define    SSC_DEPTH_500K              0x04
+#define    SSC_DEPTH_250K              0x05
 #define RCCTL                          0xFC14
 
 #define FPGA_PULL_CTL                  0xFC1D
 #define GPIO_CTL                       0xFC1F
 
 #define LDO_CTL                                0xFC1E
+#define   BPP_ASIC_1V7                 0x00
+#define   BPP_ASIC_1V8                 0x01
+#define   BPP_ASIC_1V9                 0x02
+#define   BPP_ASIC_2V0                 0x03
+#define   BPP_ASIC_2V7                 0x04
+#define   BPP_ASIC_2V8                 0x05
+#define   BPP_ASIC_3V2                 0x06
+#define   BPP_ASIC_3V3                 0x07
+#define   BPP_REG_TUNED18              0x07
+#define   BPP_TUNED18_SHIFT_8402       5
+#define   BPP_TUNED18_SHIFT_8411       4
+#define   BPP_PAD_MASK                 0x04
+#define   BPP_PAD_3V3                  0x04
+#define   BPP_PAD_1V8                  0x00
+#define   BPP_LDO_POWB                 0x03
+#define   BPP_LDO_ON                   0x00
+#define   BPP_LDO_SUSPEND              0x02
+#define   BPP_LDO_OFF                  0x03
 #define SYS_VER                                0xFC32
 
 #define CARD_PULL_CTL1                 0xFD60
 /* PCI Express Related Registers */
 #define IRQEN0                         0xFE20
 #define IRQSTAT0                       0xFE21
+#define    DMA_DONE_INT                        0x80
+#define    SUSPEND_INT                 0x40
+#define    LINK_RDY_INT                        0x20
+#define    LINK_DOWN_INT               0x10
 #define IRQEN1                         0xFE22
 #define IRQSTAT1                       0xFE23
 #define TLPRIEN                                0xFE24
 #define DMATC2                         0xFE2A
 #define DMATC3                         0xFE2B
 #define DMACTL                         0xFE2C
+#define   DMA_RST                      0x80
+#define   DMA_BUSY                     0x04
+#define   DMA_DIR_TO_CARD              0x00
+#define   DMA_DIR_FROM_CARD            0x02
+#define   DMA_EN                       0x01
+#define   DMA_128                      (0 << 4)
+#define   DMA_256                      (1 << 4)
+#define   DMA_512                      (2 << 4)
+#define   DMA_1024                     (3 << 4)
+#define   DMA_PACK_SIZE_MASK           0x30
 #define BCTL                           0xFE2D
 #define RBBC0                          0xFE2E
 #define RBBC1                          0xFE2F
 #define MSGTXDATA2                     0xFE46
 #define MSGTXDATA3                     0xFE47
 #define MSGTXCTL                       0xFE48
-#define PETXCFG                                0xFE49
 #define LTR_CTL                                0xFE4A
 #define OBFF_CFG                       0xFE4C
 
 #define CDRESUMECTL                    0xFE52
 #define WAKE_SEL_CTL                   0xFE54
+#define PCLK_CTL                       0xFE55
+#define   PCLK_MODE_SEL                        0x20
 #define PME_FORCE_CTL                  0xFE56
+
 #define ASPM_FORCE_CTL                 0xFE57
+#define   FORCE_ASPM_CTL0              0x10
+#define   FORCE_ASPM_VAL_MASK          0x03
+#define   FORCE_ASPM_L1_EN             0x02
+#define   FORCE_ASPM_L0_EN             0x01
+#define   FORCE_ASPM_NO_ASPM           0x00
 #define PM_CLK_FORCE_CTL               0xFE58
 #define FUNC_FORCE_CTL                 0xFE59
 #define PERST_GLITCH_WIDTH             0xFE5C
 #define RESET_LOAD_REG                 0xFE5E
 #define EFUSE_CONTENT                  0xFE5F
 #define HOST_SLEEP_STATE               0xFE60
-#define SDIO_CFG                       0xFE70
+#define   HOST_ENTER_S1                        1
+#define   HOST_ENTER_S3                        2
 
+#define SDIO_CFG                       0xFE70
+#define PM_EVENT_DEBUG                 0xFE71
+#define   PME_DEBUG_0                  0x08
 #define NFTS_TX_CTRL                   0xFE72
 
 #define PWR_GATE_CTRL                  0xFE75
+#define   PWR_GATE_EN                  0x01
+#define   LDO3318_PWR_MASK             0x06
+#define   LDO_ON                       0x00
+#define   LDO_SUSPEND                  0x04
+#define   LDO_OFF                      0x06
 #define PWD_SUSPEND_EN                 0xFE76
 #define LDO_PWR_SEL                    0xFE78
 
+#define L1SUB_CONFIG1                  0xFE8D
+#define L1SUB_CONFIG2                  0xFE8E
+#define   L1SUB_AUTO_CFG               0x02
+#define L1SUB_CONFIG3                  0xFE8F
+
 #define DUMMY_REG_RESET_0              0xFE90
 
 #define AUTOLOAD_CFG_BASE              0xFF00
+#define PETXCFG                                0xFF03
 
 #define PM_CTRL1                       0xFF44
+#define   CD_RESUME_EN_MASK            0xF0
+
 #define PM_CTRL2                       0xFF45
 #define PM_CTRL3                       0xFF46
 #define   SDIO_SEND_PME_EN             0x80
 #define IMAGE_FLAG_ADDR0               0xCE80
 #define IMAGE_FLAG_ADDR1               0xCE81
 
+#define RREF_CFG                       0xFF6C
+#define   RREF_VBGSEL_MASK             0x38
+#define   RREF_VBGSEL_1V25             0x28
+
+#define OOBS_CONFIG                    0xFF6E
+#define   OOBS_AUTOK_DIS               0x80
+#define   OOBS_VAL_MASK                        0x1F
+
+#define LDO_DV18_CFG                   0xFF70
+#define   LDO_DV18_SR_MASK             0xC0
+#define   LDO_DV18_SR_DF               0x40
+
+#define LDO_CONFIG2                    0xFF71
+#define   LDO_D3318_MASK               0x07
+#define   LDO_D3318_33V                        0x07
+#define   LDO_D3318_18V                        0x02
+
+#define LDO_VCC_CFG0                   0xFF72
+#define   LDO_VCC_LMTVTH_MASK          0x30
+#define   LDO_VCC_LMTVTH_2A            0x10
+
+#define LDO_VCC_CFG1                   0xFF73
+#define   LDO_VCC_REF_TUNE_MASK                0x30
+#define   LDO_VCC_REF_1V2              0x20
+#define   LDO_VCC_TUNE_MASK            0x07
+#define   LDO_VCC_1V8                  0x04
+#define   LDO_VCC_3V3                  0x07
+#define   LDO_VCC_LMT_EN               0x08
+
+#define LDO_VIO_CFG                    0xFF75
+#define   LDO_VIO_SR_MASK              0xC0
+#define   LDO_VIO_SR_DF                        0x40
+#define   LDO_VIO_REF_TUNE_MASK                0x30
+#define   LDO_VIO_REF_1V2              0x20
+#define   LDO_VIO_TUNE_MASK            0x07
+#define   LDO_VIO_1V7                  0x03
+#define   LDO_VIO_1V8                  0x04
+#define   LDO_VIO_3V3                  0x07
+
+#define LDO_DV12S_CFG                  0xFF76
+#define   LDO_REF12_TUNE_MASK          0x18
+#define   LDO_REF12_TUNE_DF            0x10
+#define   LDO_D12_TUNE_MASK            0x07
+#define   LDO_D12_TUNE_DF              0x04
+
+#define LDO_AV12S_CFG                  0xFF77
+#define   LDO_AV12S_TUNE_MASK          0x07
+#define   LDO_AV12S_TUNE_DF            0x04
+
+#define SD40_LDO_CTL1                  0xFE7D
+#define   SD40_VIO_TUNE_MASK           0x70
+#define   SD40_VIO_TUNE_1V7            0x30
+#define   SD_VIO_LDO_1V8               0x40
+#define   SD_VIO_LDO_3V3               0x70
+
 /* Phy register */
 #define PHY_PCR                                0x00
+#define   PHY_PCR_FORCE_CODE           0xB000
+#define   PHY_PCR_OOBS_CALI_50         0x0800
+#define   PHY_PCR_OOBS_VCM_08          0x0200
+#define   PHY_PCR_OOBS_SEN_90          0x0040
+#define   PHY_PCR_RSSI_EN              0x0002
+#define   PHY_PCR_RX10K                        0x0001
+
 #define PHY_RCR0                       0x01
 #define PHY_RCR1                       0x02
+#define   PHY_RCR1_ADP_TIME_4          0x0400
+#define   PHY_RCR1_VCO_COARSE          0x001F
+#define PHY_SSCCR2                     0x02
+#define   PHY_SSCCR2_PLL_NCODE         0x0A00
+#define   PHY_SSCCR2_TIME0             0x001C
+#define   PHY_SSCCR2_TIME2_WIDTH       0x0003
+
 #define PHY_RCR2                       0x03
+#define   PHY_RCR2_EMPHASE_EN          0x8000
+#define   PHY_RCR2_NADJR               0x4000
+#define   PHY_RCR2_CDR_SR_2            0x0100
+#define   PHY_RCR2_FREQSEL_12          0x0040
+#define   PHY_RCR2_CDR_SC_12P          0x0010
+#define   PHY_RCR2_CALIB_LATE          0x0002
+#define PHY_SSCCR3                     0x03
+#define   PHY_SSCCR3_STEP_IN           0x2740
+#define   PHY_SSCCR3_CHECK_DELAY       0x0008
+#define _PHY_ANA03                     0x03
+#define   _PHY_ANA03_TIMER_MAX         0x2700
+#define   _PHY_ANA03_OOBS_DEB_EN       0x0040
+#define   _PHY_CMU_DEBUG_EN            0x0008
+
 #define PHY_RTCR                       0x04
 #define PHY_RDR                                0x05
+#define   PHY_RDR_RXDSEL_1_9           0x4000
+#define   PHY_SSC_AUTO_PWD             0x0600
 #define PHY_TCR0                       0x06
 #define PHY_TCR1                       0x07
 #define PHY_TUNE                       0x08
+#define   PHY_TUNE_TUNEREF_1_0         0x4000
+#define   PHY_TUNE_VBGSEL_1252         0x0C00
+#define   PHY_TUNE_SDBUS_33            0x0200
+#define   PHY_TUNE_TUNED18             0x01C0
+#define   PHY_TUNE_TUNED12             0X0020
+#define   PHY_TUNE_TUNEA12             0x0004
+#define   PHY_TUNE_VOLTAGE_MASK                0xFC3F
+#define   PHY_TUNE_VOLTAGE_3V3         0x03C0
+#define   PHY_TUNE_D18_1V8             0x0100
+#define   PHY_TUNE_D18_1V7             0x0080
+#define PHY_ANA08                      0x08
+#define   PHY_ANA08_RX_EQ_DCGAIN       0x5000
+#define   PHY_ANA08_SEL_RX_EN          0x0400
+#define   PHY_ANA08_RX_EQ_VAL          0x03C0
+#define   PHY_ANA08_SCP                        0x0020
+#define   PHY_ANA08_SEL_IPI            0x0004
+
 #define PHY_IMR                                0x09
 #define PHY_BPCR                       0x0A
+#define   PHY_BPCR_IBRXSEL             0x0400
+#define   PHY_BPCR_IBTXSEL             0x0100
+#define   PHY_BPCR_IB_FILTER           0x0080
+#define   PHY_BPCR_CMIRROR_EN          0x0040
+
 #define PHY_BIST                       0x0B
 #define PHY_RAW_L                      0x0C
 #define PHY_RAW_H                      0x0D
 #define PHY_HOST_CLK_CTRL              0x0F
 #define PHY_DMR                                0x10
 #define PHY_BACR                       0x11
+#define   PHY_BACR_BASIC_MASK          0xFFF3
 #define PHY_IER                                0x12
 #define PHY_BCSR                       0x13
 #define PHY_BPR                                0x14
 #define PHY_BPNR                       0x16
 #define PHY_BRNR2                      0x17
 #define PHY_BENR                       0x18
-#define PHY_REG_REV                    0x19
+#define PHY_REV                                0x19
+#define   PHY_REV_RESV                 0xE000
+#define   PHY_REV_RXIDLE_LATCHED       0x1000
+#define   PHY_REV_P1_EN                        0x0800
+#define   PHY_REV_RXIDLE_EN            0x0400
+#define   PHY_REV_CLKREQ_TX_EN         0x0200
+#define   PHY_REV_CLKREQ_RX_EN         0x0100
+#define   PHY_REV_CLKREQ_DT_1_0                0x0040
+#define   PHY_REV_STOP_CLKRD           0x0020
+#define   PHY_REV_RX_PWST              0x0008
+#define   PHY_REV_STOP_CLKWR           0x0004
+#define _PHY_REV0                      0x19
+#define   _PHY_REV0_FILTER_OUT         0x3800
+#define   _PHY_REV0_CDR_BYPASS_PFD     0x0100
+#define   _PHY_REV0_CDR_RX_IDLE_BYPASS 0x0002
+
 #define PHY_FLD0                       0x1A
+#define PHY_ANA1A                      0x1A
+#define   PHY_ANA1A_TXR_LOOPBACK       0x2000
+#define   PHY_ANA1A_RXT_BIST           0x0500
+#define   PHY_ANA1A_TXR_BIST           0x0040
+#define   PHY_ANA1A_REV                        0x0006
 #define PHY_FLD1                       0x1B
 #define PHY_FLD2                       0x1C
 #define PHY_FLD3                       0x1D
+#define   PHY_FLD3_TIMER_4             0x0800
+#define   PHY_FLD3_TIMER_6             0x0020
+#define   PHY_FLD3_RXDELINK            0x0004
+#define PHY_ANA1D                      0x1D
+#define   PHY_ANA1D_DEBUG_ADDR         0x0004
+#define _PHY_FLD0                      0x1D
+#define   _PHY_FLD0_CLK_REQ_20C                0x8000
+#define   _PHY_FLD0_RX_IDLE_EN         0x1000
+#define   _PHY_FLD0_BIT_ERR_RSTN       0x0800
+#define   _PHY_FLD0_BER_COUNT          0x01E0
+#define   _PHY_FLD0_BER_TIMER          0x001E
+#define   _PHY_FLD0_CHECK_EN           0x0001
+
 #define PHY_FLD4                       0x1E
+#define   PHY_FLD4_FLDEN_SEL           0x4000
+#define   PHY_FLD4_REQ_REF             0x2000
+#define   PHY_FLD4_RXAMP_OFF           0x1000
+#define   PHY_FLD4_REQ_ADDA            0x0800
+#define   PHY_FLD4_BER_COUNT           0x00E0
+#define   PHY_FLD4_BER_TIMER           0x000A
+#define   PHY_FLD4_BER_CHK_EN          0x0001
+#define PHY_DIG1E                      0x1E
+#define   PHY_DIG1E_REV                        0x4000
+#define   PHY_DIG1E_D0_X_D1            0x1000
+#define   PHY_DIG1E_RX_ON_HOST         0x0800
+#define   PHY_DIG1E_RCLK_REF_HOST      0x0400
+#define   PHY_DIG1E_RCLK_TX_EN_KEEP    0x0040
+#define   PHY_DIG1E_RCLK_TX_TERM_KEEP  0x0020
+#define   PHY_DIG1E_RCLK_RX_EIDLE_ON   0x0010
+#define   PHY_DIG1E_TX_TERM_KEEP       0x0008
+#define   PHY_DIG1E_RX_TERM_KEEP       0x0004
+#define   PHY_DIG1E_TX_EN_KEEP         0x0002
+#define   PHY_DIG1E_RX_EN_KEEP         0x0001
 #define PHY_DUM_REG                    0x1F
 
-#define LCTLR                          0x80
-#define   LCTLR_EXT_SYNC               0x80
-#define   LCTLR_COMMON_CLOCK_CFG       0x40
-#define   LCTLR_RETRAIN_LINK           0x20
-#define   LCTLR_LINK_DISABLE           0x10
-#define   LCTLR_RCB                    0x08
-#define   LCTLR_RESERVED               0x04
-#define   LCTLR_ASPM_CTL_MASK          0x03
-
 #define PCR_SETTING_REG1               0x724
 #define PCR_SETTING_REG2               0x814
 #define PCR_SETTING_REG3               0x747
 
-/* Phy bits */
-#define PHY_PCR_FORCE_CODE                     0xB000
-#define PHY_PCR_OOBS_CALI_50                   0x0800
-#define PHY_PCR_OOBS_VCM_08                    0x0200
-#define PHY_PCR_OOBS_SEN_90                    0x0040
-#define PHY_PCR_RSSI_EN                                0x0002
-
-#define PHY_RCR1_ADP_TIME                      0x0100
-#define PHY_RCR1_VCO_COARSE                    0x001F
-
-#define PHY_RCR2_EMPHASE_EN                    0x8000
-#define PHY_RCR2_NADJR                         0x4000
-#define PHY_RCR2_CDR_CP_10                     0x0400
-#define PHY_RCR2_CDR_SR_2                      0x0100
-#define PHY_RCR2_FREQSEL_12                    0x0040
-#define PHY_RCR2_CPADJEN                       0x0020
-#define PHY_RCR2_CDR_SC_8                      0x0008
-#define PHY_RCR2_CALIB_LATE                    0x0002
-
-#define PHY_RDR_RXDSEL_1_9                     0x4000
-
-#define PHY_TUNE_TUNEREF_1_0                   0x4000
-#define PHY_TUNE_VBGSEL_1252                   0x0C00
-#define PHY_TUNE_SDBUS_33                      0x0200
-#define PHY_TUNE_TUNED18                       0x01C0
-#define PHY_TUNE_TUNED12                       0X0020
-
-#define PHY_BPCR_IBRXSEL                       0x0400
-#define PHY_BPCR_IBTXSEL                       0x0100
-#define PHY_BPCR_IB_FILTER                     0x0080
-#define PHY_BPCR_CMIRROR_EN                    0x0040
-
-#define PHY_REG_REV_RESV                       0xE000
-#define PHY_REG_REV_RXIDLE_LATCHED             0x1000
-#define PHY_REG_REV_P1_EN                      0x0800
-#define PHY_REG_REV_RXIDLE_EN                  0x0400
-#define PHY_REG_REV_CLKREQ_DLY_TIMER_1_0       0x0040
-#define PHY_REG_REV_STOP_CLKRD                 0x0020
-#define PHY_REG_REV_RX_PWST                    0x0008
-#define PHY_REG_REV_STOP_CLKWR                 0x0004
-
-#define PHY_FLD3_TIMER_4                       0x7800
-#define PHY_FLD3_TIMER_6                       0x00E0
-#define PHY_FLD3_RXDELINK                      0x0004
-
-#define PHY_FLD4_FLDEN_SEL                     0x4000
-#define PHY_FLD4_REQ_REF                       0x2000
-#define PHY_FLD4_RXAMP_OFF                     0x1000
-#define PHY_FLD4_REQ_ADDA                      0x0800
-#define PHY_FLD4_BER_COUNT                     0x00E0
-#define PHY_FLD4_BER_TIMER                     0x000A
-#define PHY_FLD4_BER_CHK_EN                    0x0001
-
 #define rtsx_pci_init_cmd(pcr)         ((pcr)->ci = 0)
 
 struct rtsx_pcr;
@@ -835,6 +851,8 @@ struct pcr_handle {
 };
 
 struct pcr_ops {
+       int (*write_phy)(struct rtsx_pcr *pcr, u8 addr, u16 val);
+       int (*read_phy)(struct rtsx_pcr *pcr, u8 addr, u16 *val);
        int             (*extra_init_hw)(struct rtsx_pcr *pcr);
        int             (*optimize_phy)(struct rtsx_pcr *pcr);
        int             (*turn_on_led)(struct rtsx_pcr *pcr);
@@ -856,6 +874,7 @@ enum PDEV_STAT  {PDEV_STAT_IDLE, PDEV_STAT_RUN};
 struct rtsx_pcr {
        struct pci_dev                  *pci;
        unsigned int                    id;
+       int                             pcie_cap;
 
        /* pci resources */
        unsigned long                   addr;
@@ -928,6 +947,8 @@ struct rtsx_pcr {
        const struct pcr_ops            *ops;
        enum PDEV_STAT                  state;
 
+       u16                             reg_pm_ctrl3;
+
        int                             num_slots;
        struct rtsx_slot                *slots;
 };
@@ -935,6 +956,10 @@ struct rtsx_pcr {
 #define CHK_PCI_PID(pcr, pid)          ((pcr)->pci->device == (pid))
 #define PCI_VID(pcr)                   ((pcr)->pci->vendor)
 #define PCI_PID(pcr)                   ((pcr)->pci->device)
+#define is_version(pcr, pid, ver)                              \
+       (CHK_PCI_PID(pcr, pid) && (pcr)->ic_version == (ver))
+#define pcr_dbg(pcr, fmt, arg...)                              \
+       dev_dbg(&(pcr)->pci->dev, fmt, ##arg)
 
 #define SDR104_PHASE(val)              ((val) & 0xFF)
 #define SDR50_PHASE(val)               (((val) >> 8) & 0xFF)
@@ -1004,4 +1029,17 @@ static inline void rtsx_pci_write_be32(struct rtsx_pcr *pcr, u16 reg, u32 val)
        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 3, 0xFF, val);
 }
 
+static inline int rtsx_pci_update_phy(struct rtsx_pcr *pcr, u8 addr,
+       u16 mask, u16 append)
+{
+       int err;
+       u16 val;
+
+       err = rtsx_pci_read_phy_register(pcr, addr, &val);
+       if (err < 0)
+               return err;
+
+       return rtsx_pci_write_phy_register(pcr, addr, (val & mask) | append);
+}
+
 #endif
index 3fdb7cfbffb3acf09b133f97f42cf248fb65ee8a..75115384f3fcf7bdf2965317ca94baa372ad0e55 100644 (file)
@@ -58,13 +58,7 @@ enum sec_device_type {
  * @irq_base:          Base IRQ number for device, required for IRQs
  * @irq:               Generic IRQ number for device
  * @irq_data:          Runtime data structure for IRQ controller
- * @ono:               Power onoff IRQ number for s5m87xx
  * @wakeup:            Whether or not this is a wakeup device
- * @wtsr_smpl:         Whether or not to enable in RTC driver the Watchdog
- *                     Timer Software Reset (registers set to default value
- *                     after PWRHOLD falling) and Sudden Momentary Power Loss
- *                     (PMIC will enter power on sequence after short drop in
- *                     VBATT voltage).
  */
 struct sec_pmic_dev {
        struct device *dev;
@@ -77,9 +71,7 @@ struct sec_pmic_dev {
        int irq;
        struct regmap_irq_chip_data *irq_data;
 
-       int ono;
        bool wakeup;
-       bool wtsr_smpl;
 };
 
 int sec_irq_init(struct sec_pmic_dev *sec_pmic);
@@ -95,7 +87,6 @@ struct sec_platform_data {
        int                             irq_base;
        int                             (*cfg_pmic_irq)(void);
 
-       int                             ono;
        bool                            wakeup;
        bool                            buck_voltage_lock;
 
index f35af7361b606f630dee92dc7c28e96df7c71c46..667aa40486dd41ca2e0ade8f2cee7c6e35c470bd 100644 (file)
@@ -74,8 +74,8 @@ enum s2mps11_irq {
        S2MPS11_IRQ_MRB,
 
        S2MPS11_IRQ_RTC60S,
-       S2MPS11_IRQ_RTCA0,
        S2MPS11_IRQ_RTCA1,
+       S2MPS11_IRQ_RTCA0,
        S2MPS11_IRQ_SMPL,
        S2MPS11_IRQ_RTC1S,
        S2MPS11_IRQ_WTSR,
diff --git a/include/linux/mfd/sky81452.h b/include/linux/mfd/sky81452.h
new file mode 100644 (file)
index 0000000..b0925fa
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * sky81452.h  SKY81452 MFD driver
+ *
+ * Copyright 2014 Skyworks Solutions Inc.
+ * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SKY81452_H
+#define _SKY81452_H
+
+#include <linux/platform_data/sky81452-backlight.h>
+#include <linux/regulator/machine.h>
+
+struct sky81452_platform_data {
+       struct sky81452_bl_platform_data *bl_pdata;
+       struct regulator_init_data *regulator_init_data;
+};
+
+#endif
index eda121556e5d3e142c0f3f20797c45ce08a5200f..833074b766bdfb87dbcc07dda912d2d11c0c9697 100644 (file)
 
 /**
  * struct stw481x - state holder for the Stw481x drivers
- * @mutex: mutex to serialize I2C accesses
  * @i2c_client: corresponding I2C client
- * @regulator: regulator device for regulator children
  * @map: regmap handle to access device registers
  */
 struct stw481x {
-       struct mutex            lock;
        struct i2c_client       *client;
-       struct regulator_dev    *vmmc_regulator;
        struct regmap           *map;
 };
 
index 00ef24bf6edea0d64a1de38dd1089f5edf3091b5..9352adc95de6f4115294db75ffac16e376e86f2a 100644 (file)
@@ -36,6 +36,9 @@
 #define EXYNOS5420_MTCADC_PHY_CONTROL          (0x724)
 #define EXYNOS5420_DPTX_PHY_CONTROL            (0x728)
 
+/* Exynos5433 specific register definitions */
+#define EXYNOS5433_USBHOST30_PHY_CONTROL       (0x728)
+
 #define EXYNOS5_PHY_ENABLE                     BIT(0)
 
 #define EXYNOS5_MIPI_PHY_S_RESETN              BIT(1)
index 3f4e994ace2bc92ac90bfad5c3d7f02ae066eab4..1fd50dcfe47c629b75e9d8cfe855cad3aba8a1fa 100644 (file)
 
 /* Sequencer Status */
 #define SEQ_STATUS BIT(5)
+#define CHARGE_STEP            0x11
 
 #define ADC_CLK                        3000000
 #define TOTAL_STEPS            16
index 2b9479310bbd32e81f54af29b51eff7bdf3922d4..8dc93673e34ab2ce379e903037f2de4c54e035ee 100644 (file)
@@ -123,9 +123,9 @@ struct wm8350_charger_policy {
 
 struct wm8350_power {
        struct platform_device *pdev;
-       struct power_supply battery;
-       struct power_supply usb;
-       struct power_supply ac;
+       struct power_supply *battery;
+       struct power_supply *usb;
+       struct power_supply *ac;
        struct wm8350_charger_policy *policy;
 
        int rev_g_coeff;
index 78baed5f29522e2414bc1845293d6f36d69f5853..cac1c0904d5fb40c2a5729ca3eabd47f76a9134e 100644 (file)
@@ -69,7 +69,6 @@ static inline int migrate_huge_page_move_mapping(struct address_space *mapping,
 extern bool pmd_trans_migrating(pmd_t pmd);
 extern int migrate_misplaced_page(struct page *page,
                                  struct vm_area_struct *vma, int node);
-extern bool migrate_ratelimited(int node);
 #else
 static inline bool pmd_trans_migrating(pmd_t pmd)
 {
@@ -80,10 +79,6 @@ static inline int migrate_misplaced_page(struct page *page,
 {
        return -EAGAIN; /* can't migrate now */
 }
-static inline bool migrate_ratelimited(int node)
-{
-       return false;
-}
 #endif /* CONFIG_NUMA_BALANCING */
 
 #if defined(CONFIG_NUMA_BALANCING) && defined(CONFIG_TRANSPARENT_HUGEPAGE)
index 47a93928b90fff85339fd09d47761549db576b58..6571dd78e984e64db0311d747093f696aa4079ce 100644 (file)
@@ -1294,9 +1294,11 @@ int __set_page_dirty_no_writeback(struct page *page);
 int redirty_page_for_writepage(struct writeback_control *wbc,
                                struct page *page);
 void account_page_dirtied(struct page *page, struct address_space *mapping);
+void account_page_cleaned(struct page *page, struct address_space *mapping);
 int set_page_dirty(struct page *page);
 int set_page_dirty_lock(struct page *page);
 int clear_page_dirty_for_io(struct page *page);
+
 int get_cmdline(struct task_struct *task, char *buffer, int buflen);
 
 /* Is the vma a continuation of the stack vma above it? */
@@ -2109,7 +2111,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma,
 #define FOLL_FORCE     0x10    /* get_user_pages read/write w/o permission */
 #define FOLL_NOWAIT    0x20    /* if a disk transfer is needed, start the IO
                                 * and return without waiting upon it */
-#define FOLL_MLOCK     0x40    /* mark page as mlocked */
+#define FOLL_POPULATE  0x40    /* fault in page */
 #define FOLL_SPLIT     0x80    /* don't return transhuge pages, split them */
 #define FOLL_HWPOISON  0x100   /* check page is hwpoisoned */
 #define FOLL_NUMA      0x200   /* force NUMA hinting page fault */
index 199a03aab8dc9c8053f74fd04b99e39a774aa6be..590630eb59ba3c1a2181075d4dd30a26477e05a9 100644 (file)
@@ -364,7 +364,9 @@ struct mm_struct {
        atomic_t mm_users;                      /* How many users with user space? */
        atomic_t mm_count;                      /* How many references to "struct mm_struct" (users count as 1) */
        atomic_long_t nr_ptes;                  /* PTE page table pages */
+#if CONFIG_PGTABLE_LEVELS > 2
        atomic_long_t nr_pmds;                  /* PMD page table pages */
+#endif
        int map_count;                          /* number of VMAs */
 
        spinlock_t page_table_lock;             /* Protects page tables and some counters */
index 160448f920acd443327be8fa4a2c70cd7c736134..de722d4e9d61b9a1e30e4e80f0bb7630acec9459 100644 (file)
@@ -79,7 +79,7 @@ struct mmc_command {
 #define mmc_cmd_type(cmd)      ((cmd)->flags & MMC_CMD_MASK)
 
        unsigned int            retries;        /* max number of retries */
-       unsigned int            error;          /* command error */
+       int                     error;          /* command error */
 
 /*
  * Standard errno values are used for errors, but some have specific
@@ -108,7 +108,7 @@ struct mmc_data {
        unsigned int            timeout_clks;   /* data timeout (in clocks) */
        unsigned int            blksz;          /* data block size */
        unsigned int            blocks;         /* number of blocks */
-       unsigned int            error;          /* data error */
+       int                     error;          /* data error */
        unsigned int            flags;
 
 #define MMC_DATA_WRITE (1 << 8)
index 471fb3116dbee5afb3b9fb89325de6a51699fca3..12111993a3175ede2a43a0c061f5cbaf01b50abf 100644 (file)
@@ -44,6 +44,7 @@ struct mmc_data;
  * struct dw_mci - MMC controller state shared between all slots
  * @lock: Spinlock protecting the queue and associated data.
  * @regs: Pointer to MMIO registers.
+ * @fifo_reg: Pointer to MMIO registers for data FIFO
  * @sg: Scatterlist entry currently being processed by PIO code, if any.
  * @sg_miter: PIO mapping scatterlist iterator.
  * @cur_slot: The slot which is currently using the controller.
@@ -79,7 +80,6 @@ struct mmc_data;
  * @current_speed: Configured rate of the controller.
  * @num_slots: Number of slots available.
  * @verid: Denote Version ID.
- * @data_offset: Set the offset of DATA register according to VERID.
  * @dev: Device associated with the MMC controller.
  * @pdata: Platform data associated with the MMC controller.
  * @drv_data: Driver specific data for identified variant of the controller
@@ -132,6 +132,7 @@ struct dw_mci {
        spinlock_t              lock;
        spinlock_t              irq_lock;
        void __iomem            *regs;
+       void __iomem            *fifo_reg;
 
        struct scatterlist      *sg;
        struct sg_mapping_iter  sg_miter;
@@ -172,7 +173,6 @@ struct dw_mci {
        u32                     num_slots;
        u32                     fifoth_val;
        u16                     verid;
-       u16                     data_offset;
        struct device           *dev;
        struct dw_mci_board     *pdata;
        const struct dw_mci_drv_data    *drv_data;
@@ -202,6 +202,8 @@ struct dw_mci {
        int                     irq;
 
        int                     sdio_id0;
+
+       struct timer_list       cmd11_timer;
 };
 
 /* DMA ops for Internal/External DMAC interface */
index 0c8cbe5d155023358f8fafea9b68caca91802aa2..b5bedaec6223679bc00a25af801c1ae57ff17ad2 100644 (file)
@@ -79,12 +79,6 @@ struct mmc_ios {
 };
 
 struct mmc_host_ops {
-       /*
-        * 'enable' is called when the host is claimed and 'disable' is called
-        * when the host is released. 'enable' and 'disable' are deprecated.
-        */
-       int (*enable)(struct mmc_host *host);
-       int (*disable)(struct mmc_host *host);
        /*
         * It is optional for the host to implement pre_req and post_req in
         * order to support double buffering of requests (prepare one
diff --git a/include/linux/mmc/sdhci-spear.h b/include/linux/mmc/sdhci-spear.h
deleted file mode 100644 (file)
index 8cc095a..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * include/linux/mmc/sdhci-spear.h
- *
- * SDHCI declarations specific to ST SPEAr platform
- *
- * Copyright (C) 2010 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef LINUX_MMC_SDHCI_SPEAR_H
-#define LINUX_MMC_SDHCI_SPEAR_H
-
-#include <linux/platform_device.h>
-/*
- * struct sdhci_plat_data: spear sdhci platform data structure
- *
- * card_int_gpio: gpio pin used for card detection
- */
-struct sdhci_plat_data {
-       int card_int_gpio;
-};
-
-/* This function is used to set platform_data field of pdev->dev */
-static inline void
-sdhci_set_plat_data(struct platform_device *pdev, struct sdhci_plat_data *data)
-{
-       pdev->dev.platform_data = data;
-}
-
-#endif /* LINUX_MMC_SDHCI_SPEAR_H */
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
deleted file mode 100644 (file)
index c3e3db1..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- *  linux/include/linux/mmc/sdhci.h - Secure Digital Host Controller Interface
- *
- *  Copyright (C) 2005-2008 Pierre Ossman, 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.
- */
-#ifndef LINUX_MMC_SDHCI_H
-#define LINUX_MMC_SDHCI_H
-
-#include <linux/scatterlist.h>
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <linux/io.h>
-#include <linux/mmc/host.h>
-
-struct sdhci_host_next {
-       unsigned int    sg_count;
-       s32             cookie;
-};
-
-struct sdhci_host {
-       /* Data set by hardware interface driver */
-       const char *hw_name;    /* Hardware bus name */
-
-       unsigned int quirks;    /* Deviations from spec. */
-
-/* Controller doesn't honor resets unless we touch the clock register */
-#define SDHCI_QUIRK_CLOCK_BEFORE_RESET                 (1<<0)
-/* Controller has bad caps bits, but really supports DMA */
-#define SDHCI_QUIRK_FORCE_DMA                          (1<<1)
-/* Controller doesn't like to be reset when there is no card inserted. */
-#define SDHCI_QUIRK_NO_CARD_NO_RESET                   (1<<2)
-/* Controller doesn't like clearing the power reg before a change */
-#define SDHCI_QUIRK_SINGLE_POWER_WRITE                 (1<<3)
-/* Controller has flaky internal state so reset it on each ios change */
-#define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS              (1<<4)
-/* Controller has an unusable DMA engine */
-#define SDHCI_QUIRK_BROKEN_DMA                         (1<<5)
-/* Controller has an unusable ADMA engine */
-#define SDHCI_QUIRK_BROKEN_ADMA                                (1<<6)
-/* Controller can only DMA from 32-bit aligned addresses */
-#define SDHCI_QUIRK_32BIT_DMA_ADDR                     (1<<7)
-/* Controller can only DMA chunk sizes that are a multiple of 32 bits */
-#define SDHCI_QUIRK_32BIT_DMA_SIZE                     (1<<8)
-/* Controller can only ADMA chunks that are a multiple of 32 bits */
-#define SDHCI_QUIRK_32BIT_ADMA_SIZE                    (1<<9)
-/* Controller needs to be reset after each request to stay stable */
-#define SDHCI_QUIRK_RESET_AFTER_REQUEST                        (1<<10)
-/* Controller needs voltage and power writes to happen separately */
-#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER            (1<<11)
-/* Controller provides an incorrect timeout value for transfers */
-#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL                 (1<<12)
-/* Controller has an issue with buffer bits for small transfers */
-#define SDHCI_QUIRK_BROKEN_SMALL_PIO                   (1<<13)
-/* Controller does not provide transfer-complete interrupt when not busy */
-#define SDHCI_QUIRK_NO_BUSY_IRQ                                (1<<14)
-/* Controller has unreliable card detection */
-#define SDHCI_QUIRK_BROKEN_CARD_DETECTION              (1<<15)
-/* Controller reports inverted write-protect state */
-#define SDHCI_QUIRK_INVERTED_WRITE_PROTECT             (1<<16)
-/* Controller does not like fast PIO transfers */
-#define SDHCI_QUIRK_PIO_NEEDS_DELAY                    (1<<18)
-/* Controller has to be forced to use block size of 2048 bytes */
-#define SDHCI_QUIRK_FORCE_BLK_SZ_2048                  (1<<20)
-/* Controller cannot do multi-block transfers */
-#define SDHCI_QUIRK_NO_MULTIBLOCK                      (1<<21)
-/* Controller can only handle 1-bit data transfers */
-#define SDHCI_QUIRK_FORCE_1_BIT_DATA                   (1<<22)
-/* Controller needs 10ms delay between applying power and clock */
-#define SDHCI_QUIRK_DELAY_AFTER_POWER                  (1<<23)
-/* Controller uses SDCLK instead of TMCLK for data timeouts */
-#define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK            (1<<24)
-/* Controller reports wrong base clock capability */
-#define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN              (1<<25)
-/* Controller cannot support End Attribute in NOP ADMA descriptor */
-#define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC              (1<<26)
-/* Controller is missing device caps. Use caps provided by host */
-#define SDHCI_QUIRK_MISSING_CAPS                       (1<<27)
-/* Controller uses Auto CMD12 command to stop the transfer */
-#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12             (1<<28)
-/* Controller doesn't have HISPD bit field in HI-SPEED SD card */
-#define SDHCI_QUIRK_NO_HISPD_BIT                       (1<<29)
-/* Controller treats ADMA descriptors with length 0000h incorrectly */
-#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC           (1<<30)
-/* The read-only detection via SDHCI_PRESENT_STATE register is unstable */
-#define SDHCI_QUIRK_UNSTABLE_RO_DETECT                 (1<<31)
-
-       unsigned int quirks2;   /* More deviations from spec. */
-
-#define SDHCI_QUIRK2_HOST_OFF_CARD_ON                  (1<<0)
-#define SDHCI_QUIRK2_HOST_NO_CMD23                     (1<<1)
-/* The system physically doesn't support 1.8v, even if the host does */
-#define SDHCI_QUIRK2_NO_1_8_V                          (1<<2)
-#define SDHCI_QUIRK2_PRESET_VALUE_BROKEN               (1<<3)
-#define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON              (1<<4)
-/* Controller has a non-standard host control register */
-#define SDHCI_QUIRK2_BROKEN_HOST_CONTROL               (1<<5)
-/* Controller does not support HS200 */
-#define SDHCI_QUIRK2_BROKEN_HS200                      (1<<6)
-/* Controller does not support DDR50 */
-#define SDHCI_QUIRK2_BROKEN_DDR50                      (1<<7)
-/* Stop command (CMD12) can set Transfer Complete when not using MMC_RSP_BUSY */
-#define SDHCI_QUIRK2_STOP_WITH_TC                      (1<<8)
-/* Controller does not support 64-bit DMA */
-#define SDHCI_QUIRK2_BROKEN_64_BIT_DMA                 (1<<9)
-/* need clear transfer mode register before send cmd */
-#define SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD (1<<10)
-/* Capability register bit-63 indicates HS400 support */
-#define SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400              (1<<11)
-/* forced tuned clock */
-#define SDHCI_QUIRK2_TUNING_WORK_AROUND                        (1<<12)
-/* disable the block count for single block transactions */
-#define SDHCI_QUIRK2_SUPPORT_SINGLE                    (1<<13)
-
-       int irq;                /* Device IRQ */
-       void __iomem *ioaddr;   /* Mapped address */
-
-       const struct sdhci_ops *ops;    /* Low level hw interface */
-
-       /* Internal data */
-       struct mmc_host *mmc;   /* MMC structure */
-       u64 dma_mask;           /* custom DMA mask */
-
-#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
-       struct led_classdev led;        /* LED control */
-       char led_name[32];
-#endif
-
-       spinlock_t lock;        /* Mutex */
-
-       int flags;              /* Host attributes */
-#define SDHCI_USE_SDMA         (1<<0)  /* Host is SDMA capable */
-#define SDHCI_USE_ADMA         (1<<1)  /* Host is ADMA capable */
-#define SDHCI_REQ_USE_DMA      (1<<2)  /* Use DMA for this req. */
-#define SDHCI_DEVICE_DEAD      (1<<3)  /* Device unresponsive */
-#define SDHCI_SDR50_NEEDS_TUNING (1<<4)        /* SDR50 needs tuning */
-#define SDHCI_NEEDS_RETUNING   (1<<5)  /* Host needs retuning */
-#define SDHCI_AUTO_CMD12       (1<<6)  /* Auto CMD12 support */
-#define SDHCI_AUTO_CMD23       (1<<7)  /* Auto CMD23 support */
-#define SDHCI_PV_ENABLED       (1<<8)  /* Preset value enabled */
-#define SDHCI_SDIO_IRQ_ENABLED (1<<9)  /* SDIO irq enabled */
-#define SDHCI_SDR104_NEEDS_TUNING (1<<10)      /* SDR104/HS200 needs tuning */
-#define SDHCI_USING_RETUNING_TIMER (1<<11)     /* Host is using a retuning timer for the card */
-#define SDHCI_USE_64_BIT_DMA   (1<<12) /* Use 64-bit DMA */
-#define SDHCI_HS400_TUNING     (1<<13) /* Tuning for HS400 */
-
-       unsigned int version;   /* SDHCI spec. version */
-
-       unsigned int max_clk;   /* Max possible freq (MHz) */
-       unsigned int timeout_clk;       /* Timeout freq (KHz) */
-       unsigned int clk_mul;   /* Clock Muliplier value */
-
-       unsigned int clock;     /* Current clock (MHz) */
-       u8 pwr;                 /* Current voltage */
-
-       bool runtime_suspended; /* Host is runtime suspended */
-       bool bus_on;            /* Bus power prevents runtime suspend */
-       bool preset_enabled;    /* Preset is enabled */
-
-       struct mmc_request *mrq;        /* Current request */
-       struct mmc_command *cmd;        /* Current command */
-       struct mmc_data *data;  /* Current data request */
-       unsigned int data_early:1;      /* Data finished before cmd */
-       unsigned int busy_handle:1;     /* Handling the order of Busy-end */
-
-       struct sg_mapping_iter sg_miter;        /* SG state for PIO */
-       unsigned int blocks;    /* remaining PIO blocks */
-
-       int sg_count;           /* Mapped sg entries */
-
-       void *adma_table;       /* ADMA descriptor table */
-       void *align_buffer;     /* Bounce buffer */
-
-       size_t adma_table_sz;   /* ADMA descriptor table size */
-       size_t align_buffer_sz; /* Bounce buffer size */
-
-       dma_addr_t adma_addr;   /* Mapped ADMA descr. table */
-       dma_addr_t align_addr;  /* Mapped bounce buffer */
-
-       unsigned int desc_sz;   /* ADMA descriptor size */
-       unsigned int align_sz;  /* ADMA alignment */
-       unsigned int align_mask;        /* ADMA alignment mask */
-
-       struct tasklet_struct finish_tasklet;   /* Tasklet structures */
-
-       struct timer_list timer;        /* Timer for timeouts */
-
-       u32 caps;               /* Alternative CAPABILITY_0 */
-       u32 caps1;              /* Alternative CAPABILITY_1 */
-
-       unsigned int            ocr_avail_sdio; /* OCR bit masks */
-       unsigned int            ocr_avail_sd;
-       unsigned int            ocr_avail_mmc;
-       u32 ocr_mask;           /* available voltages */
-
-       unsigned                timing;         /* Current timing */
-
-       u32                     thread_isr;
-
-       /* cached registers */
-       u32                     ier;
-
-       wait_queue_head_t       buf_ready_int;  /* Waitqueue for Buffer Read Ready interrupt */
-       unsigned int            tuning_done;    /* Condition flag set when CMD19 succeeds */
-
-       unsigned int            tuning_count;   /* Timer count for re-tuning */
-       unsigned int            tuning_mode;    /* Re-tuning mode supported by host */
-#define SDHCI_TUNING_MODE_1    0
-       struct timer_list       tuning_timer;   /* Timer for tuning */
-
-       struct sdhci_host_next  next_data;
-       unsigned long private[0] ____cacheline_aligned;
-};
-#endif /* LINUX_MMC_SDHCI_H */
index f279d9c158cd566d8e3c0bd2777094e553f81be0..2782df47101e0cd3ee6ff199ad97f75d640b9308 100644 (file)
@@ -474,16 +474,15 @@ struct zone {
        unsigned long           wait_table_bits;
 
        ZONE_PADDING(_pad1_)
-
-       /* Write-intensive fields used from the page allocator */
-       spinlock_t              lock;
-
        /* free areas of different sizes */
        struct free_area        free_area[MAX_ORDER];
 
        /* zone flags, see below */
        unsigned long           flags;
 
+       /* Write-intensive fields used from the page allocator */
+       spinlock_t              lock;
+
        ZONE_PADDING(_pad2_)
 
        /* Write-intensive fields used by page reclaim */
index b03485bcb82a0a4d1f6ebbbac8b30f37beb722a2..c883b86ea9649ae62ca485dd3843e51e43edc346 100644 (file)
@@ -338,6 +338,8 @@ struct module {
 #ifdef CONFIG_EVENT_TRACING
        struct ftrace_event_call **trace_events;
        unsigned int num_trace_events;
+       struct trace_enum_map **trace_enums;
+       unsigned int num_trace_enums;
 #endif
 #ifdef CONFIG_FTRACE_MCOUNT_RECORD
        unsigned int num_ftrace_callsites;
index 9b2022ab4d852744e1a558a3877fa8f676611a46..3d46fb4708e051ef78f4be83651f4a707a14b56d 100644 (file)
@@ -25,16 +25,11 @@ static inline void touch_nmi_watchdog(void)
 #endif
 
 #if defined(CONFIG_HARDLOCKUP_DETECTOR)
-extern void watchdog_enable_hardlockup_detector(bool val);
-extern bool watchdog_hardlockup_detector_is_enabled(void);
+extern void hardlockup_detector_disable(void);
 #else
-static inline void watchdog_enable_hardlockup_detector(bool val)
+static inline void hardlockup_detector_disable(void)
 {
 }
-static inline bool watchdog_hardlockup_detector_is_enabled(void)
-{
-       return true;
-}
 #endif
 
 /*
@@ -68,12 +63,20 @@ static inline bool trigger_allbutself_cpu_backtrace(void)
 #ifdef CONFIG_LOCKUP_DETECTOR
 int hw_nmi_is_cpu_stuck(struct pt_regs *);
 u64 hw_nmi_get_sample_period(int watchdog_thresh);
+extern int nmi_watchdog_enabled;
+extern int soft_watchdog_enabled;
 extern int watchdog_user_enabled;
 extern int watchdog_thresh;
 extern int sysctl_softlockup_all_cpu_backtrace;
 struct ctl_table;
-extern int proc_dowatchdog(struct ctl_table *, int ,
-                          void __user *, size_t *, loff_t *);
+extern int proc_watchdog(struct ctl_table *, int ,
+                        void __user *, size_t *, loff_t *);
+extern int proc_nmi_watchdog(struct ctl_table *, int ,
+                            void __user *, size_t *, loff_t *);
+extern int proc_soft_watchdog(struct ctl_table *, int ,
+                             void __user *, size_t *, loff_t *);
+extern int proc_watchdog_thresh(struct ctl_table *, int ,
+                               void __user *, size_t *, loff_t *);
 #endif
 
 #ifdef CONFIG_HAVE_ACPI_APEI_NMI
index dfde07e77a632b3e7868f5aabebf7fe3870cbaeb..9bfcc18ceab3bf70e884ec8fc90a44264a3f83f3 100644 (file)
@@ -332,6 +332,7 @@ extern int of_count_phandle_with_args(const struct device_node *np,
 
 extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
 extern int of_alias_get_id(struct device_node *np, const char *stem);
+extern int of_alias_get_highest_id(const char *stem);
 
 extern int of_machine_is_compatible(const char *compat);
 
@@ -594,6 +595,11 @@ static inline int of_alias_get_id(struct device_node *np, const char *stem)
        return -ENOSYS;
 }
 
+static inline int of_alias_get_highest_id(const char *stem)
+{
+       return -ENOSYS;
+}
+
 static inline int of_machine_is_compatible(const char *compat)
 {
        return 0;
index ef370210ffb25ead579f83591b3ce152d3fc80d8..22801b10cef5dd279ade089b9c10e9aa4f134aeb 100644 (file)
@@ -53,6 +53,7 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
        return of_node_get(cpu_dev->of_node);
 }
 
+void of_dma_configure(struct device *dev, struct device_node *np);
 #else /* CONFIG_OF */
 
 static inline int of_driver_match_device(struct device *dev,
@@ -90,6 +91,8 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
 {
        return NULL;
 }
+static inline void of_dma_configure(struct device *dev, struct device_node *np)
+{}
 #endif /* CONFIG_OF */
 
 #endif /* _LINUX_OF_DEVICE_H */
index 16c75547d7253c579a031ac5e8db83b3e1a4a81a..ffbe4707d4aa82f4ac898c6d0ca214d6a8227805 100644 (file)
@@ -12,7 +12,8 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
                             size_t *size);
 
 extern void of_iommu_init(void);
-extern struct iommu_ops *of_iommu_configure(struct device *dev);
+extern struct iommu_ops *of_iommu_configure(struct device *dev,
+                                       struct device_node *master_np);
 
 #else
 
@@ -24,7 +25,8 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
 }
 
 static inline void of_iommu_init(void) { }
-static inline struct iommu_ops *of_iommu_configure(struct device *dev)
+static inline struct iommu_ops *of_iommu_configure(struct device *dev,
+                                        struct device_node *master_np)
 {
        return NULL;
 }
index ce0e5abeb4549d8fd7ef06ea5c46d6060389472a..29fd3fe1c035d10361e9926ee879d9b6c4c70662 100644 (file)
@@ -16,6 +16,7 @@ int of_pci_get_devfn(struct device_node *np);
 int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
 int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
 int of_get_pci_domain_nr(struct device_node *node);
+void of_pci_dma_configure(struct pci_dev *pci_dev);
 #else
 static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
 {
@@ -50,6 +51,8 @@ of_get_pci_domain_nr(struct device_node *node)
 {
        return -1;
 }
+
+static inline void of_pci_dma_configure(struct pci_dev *pci_dev) { }
 #endif
 
 #if defined(CONFIG_OF_ADDRESS)
index d5771bed59c92d995d7b9b8c97ea5976b42036a7..44b2f6f7bbd8323b6462417f769fc14e7cf37a2c 100644 (file)
@@ -66,7 +66,8 @@ extern bool oom_zonelist_trylock(struct zonelist *zonelist, gfp_t gfp_flags);
 extern void oom_zonelist_unlock(struct zonelist *zonelist, gfp_t gfp_flags);
 
 extern void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask,
-                              int order, const nodemask_t *nodemask);
+                              int order, const nodemask_t *nodemask,
+                              struct mem_cgroup *memcg);
 
 extern enum oom_scan_t oom_scan_process_thread(struct task_struct *task,
                unsigned long totalpages, const nodemask_t *nodemask,
index 5ed7bdaf22d54c273460877f0fb9303376b4622c..c851ff92d5b34d7ecce5d78b381e98fc4e2ee8c2 100644 (file)
@@ -328,8 +328,6 @@ static inline void SetPageUptodate(struct page *page)
 
 CLEARPAGEFLAG(Uptodate, uptodate)
 
-extern void cancel_dirty_page(struct page *page, unsigned int account_size);
-
 int test_clear_page_writeback(struct page *page);
 int __test_set_page_writeback(struct page *page, bool keep_write);
 
index 24c7728ca681f997a3a5b10f78ec7af13fd558d3..a965efa52152ee27b38a7827588610802e4f6079 100644 (file)
@@ -77,6 +77,11 @@ static inline void acpiphp_remove_slots(struct pci_bus *bus) { }
 static inline void acpiphp_check_host_bridge(struct acpi_device *adev) { }
 #endif
 
+extern const u8 pci_acpi_dsm_uuid[];
+#define DEVICE_LABEL_DSM       0x07
+#define RESET_DELAY_DSM                0x08
+#define FUNCTION_DELAY_DSM     0x09
+
 #else  /* CONFIG_ACPI */
 static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
 static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
index 8af4610c2e414963a62e4522b482afa700ec4532..207c561fb40ef000feeda342d1f681349df4b99b 100644 (file)
@@ -29,7 +29,6 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev);
 void pcie_aspm_powersave_config_link(struct pci_dev *pdev);
 void pci_disable_link_state(struct pci_dev *pdev, int state);
 void pci_disable_link_state_locked(struct pci_dev *pdev, int state);
-void pcie_clear_aspm(struct pci_bus *bus);
 void pcie_no_aspm(void);
 #else
 static inline void pcie_aspm_init_link_state(struct pci_dev *pdev)
@@ -47,9 +46,6 @@ static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
 static inline void pci_disable_link_state(struct pci_dev *pdev, int state)
 {
 }
-static inline void pcie_clear_aspm(struct pci_bus *bus)
-{
-}
 static inline void pcie_no_aspm(void)
 {
 }
index 211e9da8a7d79df19261f2887f6d972ef11733b6..e63112fb55becbfcb12c90901c6741a661282378 100644 (file)
@@ -406,6 +406,7 @@ struct pci_host_bridge {
        struct list_head windows;       /* resource_entry */
        void (*release_fn)(struct pci_host_bridge *);
        void *release_data;
+       unsigned int ignore_reset_delay:1;      /* for entire hierarchy */
 };
 
 #define        to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
@@ -510,6 +511,9 @@ static inline struct pci_dev *pci_upstream_bridge(struct pci_dev *dev)
        return dev->bus->self;
 }
 
+struct device *pci_get_host_bridge_device(struct pci_dev *dev);
+void pci_put_host_bridge_device(struct device *dev);
+
 #ifdef CONFIG_PCI_MSI
 static inline bool pci_dev_msi_enabled(struct pci_dev *pci_dev)
 {
index e63c02a93f6be81a0a3c1d3f81cde7e798aa7e6a..38cff8f6716dd7f6532a6ecb39b750844b346692 100644 (file)
 #define PCI_VENDOR_ID_CENATEK          0x16CA
 #define PCI_DEVICE_ID_CENATEK_IDE      0x0001
 
+#define PCI_VENDOR_ID_SYNOPSYS         0x16c3
+
 #define PCI_VENDOR_ID_VITESSE          0x1725
 #define PCI_DEVICE_ID_VITESSE_VSC7174  0x7174
 
index 2b621982938d4653436b3d5cfe7578c1c71e6bb9..61992cf2e9771699ee06595c8fbb1bd39633018a 100644 (file)
@@ -53,6 +53,7 @@ struct perf_guest_info_callbacks {
 #include <linux/sysfs.h>
 #include <linux/perf_regs.h>
 #include <linux/workqueue.h>
+#include <linux/cgroup.h>
 #include <asm/local.h>
 
 struct perf_callchain_entry {
@@ -118,10 +119,19 @@ struct hw_perf_event {
                        struct hrtimer  hrtimer;
                };
                struct { /* tracepoint */
-                       struct task_struct      *tp_target;
                        /* for tp_event->class */
                        struct list_head        tp_list;
                };
+               struct { /* intel_cqm */
+                       int                     cqm_state;
+                       int                     cqm_rmid;
+                       struct list_head        cqm_events_entry;
+                       struct list_head        cqm_groups_entry;
+                       struct list_head        cqm_group_entry;
+               };
+               struct { /* itrace */
+                       int                     itrace_started;
+               };
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
                struct { /* breakpoint */
                        /*
@@ -129,12 +139,12 @@ struct hw_perf_event {
                         * problem hw_breakpoint has with context
                         * creation and event initalization.
                         */
-                       struct task_struct              *bp_target;
                        struct arch_hw_breakpoint       info;
                        struct list_head                bp_list;
                };
 #endif
        };
+       struct task_struct              *target;
        int                             state;
        local64_t                       prev_count;
        u64                             sample_period;
@@ -166,6 +176,11 @@ struct perf_event;
  * pmu::capabilities flags
  */
 #define PERF_PMU_CAP_NO_INTERRUPT              0x01
+#define PERF_PMU_CAP_NO_NMI                    0x02
+#define PERF_PMU_CAP_AUX_NO_SG                 0x04
+#define PERF_PMU_CAP_AUX_SW_DOUBLEBUF          0x08
+#define PERF_PMU_CAP_EXCLUSIVE                 0x10
+#define PERF_PMU_CAP_ITRACE                    0x20
 
 /**
  * struct pmu - generic performance monitoring unit
@@ -186,6 +201,7 @@ struct pmu {
 
        int * __percpu                  pmu_disable_count;
        struct perf_cpu_context * __percpu pmu_cpu_context;
+       atomic_t                        exclusive_cnt; /* < 0: cpu; > 0: tsk */
        int                             task_ctx_nr;
        int                             hrtimer_interval_ms;
 
@@ -262,9 +278,32 @@ struct pmu {
        int (*event_idx)                (struct perf_event *event); /*optional */
 
        /*
-        * flush branch stack on context-switches (needed in cpu-wide mode)
+        * context-switches callback
+        */
+       void (*sched_task)              (struct perf_event_context *ctx,
+                                       bool sched_in);
+       /*
+        * PMU specific data size
+        */
+       size_t                          task_ctx_size;
+
+
+       /*
+        * Return the count value for a counter.
+        */
+       u64 (*count)                    (struct perf_event *event); /*optional*/
+
+       /*
+        * Set up pmu-private data structures for an AUX area
         */
-       void (*flush_branch_stack)      (void);
+       void *(*setup_aux)              (int cpu, void **pages,
+                                        int nr_pages, bool overwrite);
+                                       /* optional */
+
+       /*
+        * Free pmu-private AUX data structures
+        */
+       void (*free_aux)                (void *aux); /* optional */
 };
 
 /**
@@ -300,6 +339,7 @@ struct swevent_hlist {
 #define PERF_ATTACH_CONTEXT    0x01
 #define PERF_ATTACH_GROUP      0x02
 #define PERF_ATTACH_TASK       0x04
+#define PERF_ATTACH_TASK_DATA  0x08
 
 struct perf_cgroup;
 struct ring_buffer;
@@ -438,6 +478,7 @@ struct perf_event {
        struct pid_namespace            *ns;
        u64                             id;
 
+       u64                             (*clock)(void);
        perf_overflow_handler_t         overflow_handler;
        void                            *overflow_handler_context;
 
@@ -504,7 +545,7 @@ struct perf_event_context {
        u64                             generation;
        int                             pin_count;
        int                             nr_cgroups;      /* cgroup evts */
-       int                             nr_branch_stack; /* branch_stack evt */
+       void                            *task_ctx_data; /* pmu specific data */
        struct rcu_head                 rcu_head;
 
        struct delayed_work             orphans_remove;
@@ -536,12 +577,52 @@ struct perf_output_handle {
        struct ring_buffer              *rb;
        unsigned long                   wakeup;
        unsigned long                   size;
-       void                            *addr;
+       union {
+               void                    *addr;
+               unsigned long           head;
+       };
        int                             page;
 };
 
+#ifdef CONFIG_CGROUP_PERF
+
+/*
+ * perf_cgroup_info keeps track of time_enabled for a cgroup.
+ * This is a per-cpu dynamically allocated data structure.
+ */
+struct perf_cgroup_info {
+       u64                             time;
+       u64                             timestamp;
+};
+
+struct perf_cgroup {
+       struct cgroup_subsys_state      css;
+       struct perf_cgroup_info __percpu *info;
+};
+
+/*
+ * Must ensure cgroup is pinned (css_get) before calling
+ * this function. In other words, we cannot call this function
+ * if there is no cgroup event for the current CPU context.
+ */
+static inline struct perf_cgroup *
+perf_cgroup_from_task(struct task_struct *task)
+{
+       return container_of(task_css(task, perf_event_cgrp_id),
+                           struct perf_cgroup, css);
+}
+#endif /* CONFIG_CGROUP_PERF */
+
 #ifdef CONFIG_PERF_EVENTS
 
+extern void *perf_aux_output_begin(struct perf_output_handle *handle,
+                                  struct perf_event *event);
+extern void perf_aux_output_end(struct perf_output_handle *handle,
+                               unsigned long size, bool truncated);
+extern int perf_aux_output_skip(struct perf_output_handle *handle,
+                               unsigned long size);
+extern void *perf_get_aux(struct perf_output_handle *handle);
+
 extern int perf_pmu_register(struct pmu *pmu, const char *name, int type);
 extern void perf_pmu_unregister(struct pmu *pmu);
 
@@ -558,6 +639,8 @@ extern void perf_event_delayed_put(struct task_struct *task);
 extern void perf_event_print_debug(void);
 extern void perf_pmu_disable(struct pmu *pmu);
 extern void perf_pmu_enable(struct pmu *pmu);
+extern void perf_sched_cb_dec(struct pmu *pmu);
+extern void perf_sched_cb_inc(struct pmu *pmu);
 extern int perf_event_task_disable(void);
 extern int perf_event_task_enable(void);
 extern int perf_event_refresh(struct perf_event *event, int refresh);
@@ -731,6 +814,11 @@ static inline void perf_event_task_sched_out(struct task_struct *prev,
                __perf_event_task_sched_out(prev, next);
 }
 
+static inline u64 __perf_event_count(struct perf_event *event)
+{
+       return local64_read(&event->count) + atomic64_read(&event->child_count);
+}
+
 extern void perf_event_mmap(struct vm_area_struct *vma);
 extern struct perf_guest_info_callbacks *perf_guest_cbs;
 extern int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks);
@@ -800,6 +888,16 @@ static inline bool has_branch_stack(struct perf_event *event)
        return event->attr.sample_type & PERF_SAMPLE_BRANCH_STACK;
 }
 
+static inline bool needs_branch_stack(struct perf_event *event)
+{
+       return event->attr.branch_sample_type != 0;
+}
+
+static inline bool has_aux(struct perf_event *event)
+{
+       return event->pmu->setup_aux;
+}
+
 extern int perf_output_begin(struct perf_output_handle *handle,
                             struct perf_event *event, unsigned int size);
 extern void perf_output_end(struct perf_output_handle *handle);
@@ -815,6 +913,17 @@ extern void perf_event_disable(struct perf_event *event);
 extern int __perf_event_disable(void *info);
 extern void perf_event_task_tick(void);
 #else /* !CONFIG_PERF_EVENTS: */
+static inline void *
+perf_aux_output_begin(struct perf_output_handle *handle,
+                     struct perf_event *event)                         { return NULL; }
+static inline void
+perf_aux_output_end(struct perf_output_handle *handle, unsigned long size,
+                   bool truncated)                                     { }
+static inline int
+perf_aux_output_skip(struct perf_output_handle *handle,
+                    unsigned long size)                                { return -EINVAL; }
+static inline void *
+perf_get_aux(struct perf_output_handle *handle)                                { return NULL; }
 static inline void
 perf_event_task_sched_in(struct task_struct *prev,
                         struct task_struct *task)                      { }
index 67bbcf0785f61da1d4a832e016de1cb99dd313a9..8e981be2e2c2ee8c0472e7824300a6178b474640 100644 (file)
@@ -55,9 +55,6 @@ struct omap_hsmmc_platform_data {
        u32 caps;       /* Used for the MMC driver on 2430 and later */
        u32 pm_caps;    /* PM capabilities of the mmc */
 
-       /* switch pin can be for card detect (default) or card cover */
-       unsigned cover:1;
-
        /* use the internal clock */
        unsigned internal_clock:1;
 
@@ -73,7 +70,8 @@ struct omap_hsmmc_platform_data {
 #define HSMMC_HAS_HSPE_SUPPORT (1 << 2)
        unsigned features;
 
-       int switch_pin;                 /* gpio (card detect) */
+       int gpio_cd;                    /* gpio (card detect) */
+       int gpio_cod;                   /* gpio (cover detect) */
        int gpio_wp;                    /* gpio (write protect) */
 
        int (*set_power)(struct device *dev, int power_on, int vdd);
index 2312d197dfb7468a0bf22df2e69d8158597f1433..89fd34727a24a81fb2bc105bde40e6c3f4b536b6 100644 (file)
@@ -18,6 +18,7 @@ struct davinci_i2c_platform_data {
        unsigned int    bus_delay;      /* post-transaction delay (usec) */
        unsigned int    sda_pin;        /* GPIO pin ID to use for SDA */
        unsigned int    scl_pin;        /* GPIO pin ID to use for SCL */
+       bool            has_pfunc;      /*chip has a ICPFUNC register */
 };
 
 /* for board setup code */
diff --git a/include/linux/platform_data/sky81452-backlight.h b/include/linux/platform_data/sky81452-backlight.h
new file mode 100644 (file)
index 0000000..1231e9b
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * sky81452.h  SKY81452 backlight driver
+ *
+ * Copyright 2014 Skyworks Solutions Inc.
+ * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SKY81452_BACKLIGHT_H
+#define _SKY81452_BACKLIGHT_H
+
+/**
+ * struct sky81452_platform_data
+ * @name:      backlight driver name.
+               If it is not defined, default name is lcd-backlight.
+ * @gpio_enable:GPIO number which control EN pin
+ * @enable:    Enable mask for current sink channel 1, 2, 3, 4, 5 and 6.
+ * @ignore_pwm:        true if DPWMI should be ignored.
+ * @dpwm_mode: true is DPWM dimming mode, otherwise Analog dimming mode.
+ * @phase_shift:true is phase shift mode.
+ * @short_detecion_threshold:  It should be one of 4, 5, 6 and 7V.
+ * @boost_current_limit:       It should be one of 2300, 2750mA.
+ */
+struct sky81452_bl_platform_data {
+       const char *name;
+       int gpio_enable;
+       unsigned int enable;
+       bool ignore_pwm;
+       bool dpwm_mode;
+       bool phase_shift;
+       unsigned int short_detection_threshold;
+       unsigned int boost_current_limit;
+};
+
+#endif
index 416ebeb6ee1ee2eeaeec92a7b2f9fcebf4d7019e..eadf28cb2fc91b7cbb732cb93f75979b5d256865 100644 (file)
@@ -242,7 +242,8 @@ struct charger_manager {
        int emergency_stop;
 
        char psy_name_buf[PSY_NAME_MAX + 1];
-       struct power_supply charger_psy;
+       struct power_supply_desc charger_psy_desc;
+       struct power_supply *charger_psy;
 
        u64 charging_start_time;
        u64 charging_end_time;
index 89dd84f47c6ed6041cde8b9259c8e737072a6ffa..cf112b4075c872f81ae87c972d4d823b10d36526 100644 (file)
@@ -126,7 +126,14 @@ enum max17047_register {
        MAX17047_QRTbl30        = 0x42,
 };
 
-enum max170xx_chip_type {MAX17042, MAX17047};
+enum max170xx_chip_type {
+       MAXIM_DEVICE_TYPE_UNKNOWN       = 0,
+       MAXIM_DEVICE_TYPE_MAX17042,
+       MAXIM_DEVICE_TYPE_MAX17047,
+       MAXIM_DEVICE_TYPE_MAX17050,
+
+       MAXIM_DEVICE_TYPE_NUM
+};
 
 /*
  * used for setting a register to a desired value
index 096dbced02ac4b7cb9d18de6a8aa65e0592d78e9..75a1dd8dc56ee19b5dc1ae89ce771851b370d4cd 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef __LINUX_POWER_SUPPLY_H__
 #define __LINUX_POWER_SUPPLY_H__
 
+#include <linux/device.h>
 #include <linux/workqueue.h>
 #include <linux/leds.h>
 #include <linux/spinlock.h>
@@ -173,22 +174,32 @@ union power_supply_propval {
        const char *strval;
 };
 
-struct device;
 struct device_node;
+struct power_supply;
 
-struct power_supply {
-       const char *name;
-       enum power_supply_type type;
-       enum power_supply_property *properties;
-       size_t num_properties;
+/* Run-time specific power supply configuration */
+struct power_supply_config {
+       struct device_node *of_node;
+       /* Driver private data */
+       void *drv_data;
 
        char **supplied_to;
        size_t num_supplicants;
+};
 
-       char **supplied_from;
-       size_t num_supplies;
-       struct device_node *of_node;
+/* Description of power supply */
+struct power_supply_desc {
+       const char *name;
+       enum power_supply_type type;
+       enum power_supply_property *properties;
+       size_t num_properties;
 
+       /*
+        * Functions for drivers implementing power supply class.
+        * These shouldn't be called directly by other drivers for accessing
+        * this power supply. Instead use power_supply_*() functions (for
+        * example power_supply_get_property()).
+        */
        int (*get_property)(struct power_supply *psy,
                            enum power_supply_property psp,
                            union power_supply_propval *val);
@@ -208,12 +219,27 @@ struct power_supply {
        bool no_thermal;
        /* For APM emulation, think legacy userspace. */
        int use_for_apm;
+};
+
+struct power_supply {
+       const struct power_supply_desc *desc;
+
+       char **supplied_to;
+       size_t num_supplicants;
+
+       char **supplied_from;
+       size_t num_supplies;
+       struct device_node *of_node;
+
+       /* Driver private data */
+       void *drv_data;
 
        /* private */
-       struct device *dev;
+       struct device dev;
        struct work_struct changed_work;
        spinlock_t changed_lock;
        bool changed;
+       atomic_t use_cnt;
 #ifdef CONFIG_THERMAL
        struct thermal_zone_device *tzd;
        struct thermal_cooling_device *tcd;
@@ -256,6 +282,7 @@ extern struct atomic_notifier_head power_supply_notifier;
 extern int power_supply_reg_notifier(struct notifier_block *nb);
 extern void power_supply_unreg_notifier(struct notifier_block *nb);
 extern struct power_supply *power_supply_get_by_name(const char *name);
+extern void power_supply_put(struct power_supply *psy);
 #ifdef CONFIG_OF
 extern struct power_supply *power_supply_get_by_phandle(struct device_node *np,
                                                        const char *property);
@@ -274,13 +301,36 @@ extern int power_supply_is_system_supplied(void);
 static inline int power_supply_is_system_supplied(void) { return -ENOSYS; }
 #endif
 
-extern int power_supply_register(struct device *parent,
-                                struct power_supply *psy);
-extern int power_supply_register_no_ws(struct device *parent,
-                                struct power_supply *psy);
+extern int power_supply_get_property(struct power_supply *psy,
+                           enum power_supply_property psp,
+                           union power_supply_propval *val);
+extern int power_supply_set_property(struct power_supply *psy,
+                           enum power_supply_property psp,
+                           const union power_supply_propval *val);
+extern int power_supply_property_is_writeable(struct power_supply *psy,
+                                       enum power_supply_property psp);
+extern void power_supply_external_power_changed(struct power_supply *psy);
+
+extern struct power_supply *__must_check
+power_supply_register(struct device *parent,
+                                const struct power_supply_desc *desc,
+                                const struct power_supply_config *cfg);
+extern struct power_supply *__must_check
+power_supply_register_no_ws(struct device *parent,
+                                const struct power_supply_desc *desc,
+                                const struct power_supply_config *cfg);
+extern struct power_supply *__must_check
+devm_power_supply_register(struct device *parent,
+                                const struct power_supply_desc *desc,
+                                const struct power_supply_config *cfg);
+extern struct power_supply *__must_check
+devm_power_supply_register_no_ws(struct device *parent,
+                                const struct power_supply_desc *desc,
+                                const struct power_supply_config *cfg);
 extern void power_supply_unregister(struct power_supply *psy);
 extern int power_supply_powers(struct power_supply *psy, struct device *dev);
 
+extern void *power_supply_get_drvdata(struct power_supply *psy);
 /* For APM emulation, think legacy userspace. */
 extern struct class *power_supply_class;
 
index 78097491cd99a693f41b45e2b12ea1a4119cb52d..573a5afd5ed884d5bdcfc4af6cf88c3b9d25214d 100644 (file)
 
 extern int rcu_expedited; /* for sysctl */
 
+#ifdef CONFIG_TINY_RCU
+/* Tiny RCU doesn't expedite, as its purpose in life is instead to be tiny. */
+static inline bool rcu_gp_is_expedited(void)  /* Internal RCU use. */
+{
+       return false;
+}
+
+static inline void rcu_expedite_gp(void)
+{
+}
+
+static inline void rcu_unexpedite_gp(void)
+{
+}
+#else /* #ifdef CONFIG_TINY_RCU */
+bool rcu_gp_is_expedited(void);  /* Internal RCU use. */
+void rcu_expedite_gp(void);
+void rcu_unexpedite_gp(void);
+#endif /* #else #ifdef CONFIG_TINY_RCU */
+
 enum rcutorture_type {
        RCU_FLAVOR,
        RCU_BH_FLAVOR,
@@ -195,6 +215,15 @@ void call_rcu_sched(struct rcu_head *head,
 
 void synchronize_sched(void);
 
+/*
+ * Structure allowing asynchronous waiting on RCU.
+ */
+struct rcu_synchronize {
+       struct rcu_head head;
+       struct completion completion;
+};
+void wakeme_after_rcu(struct rcu_head *head);
+
 /**
  * call_rcu_tasks() - Queue an RCU for invocation task-based grace period
  * @head: structure to be used for queueing the RCU updates.
@@ -258,6 +287,7 @@ static inline int rcu_preempt_depth(void)
 
 /* Internal to kernel */
 void rcu_init(void);
+void rcu_end_inkernel_boot(void);
 void rcu_sched_qs(void);
 void rcu_bh_qs(void);
 void rcu_check_callbacks(int user);
@@ -266,6 +296,8 @@ void rcu_idle_enter(void);
 void rcu_idle_exit(void);
 void rcu_irq_enter(void);
 void rcu_irq_exit(void);
+int rcu_cpu_notify(struct notifier_block *self,
+                  unsigned long action, void *hcpu);
 
 #ifdef CONFIG_RCU_STALL_COMMON
 void rcu_sysrq_start(void);
@@ -720,7 +752,7 @@ static inline void rcu_preempt_sleep_check(void)
  * annotated as __rcu.
  */
 #define rcu_dereference_check(p, c) \
-       __rcu_dereference_check((p), rcu_read_lock_held() || (c), __rcu)
+       __rcu_dereference_check((p), (c) || rcu_read_lock_held(), __rcu)
 
 /**
  * rcu_dereference_bh_check() - rcu_dereference_bh with debug checking
@@ -730,7 +762,7 @@ static inline void rcu_preempt_sleep_check(void)
  * This is the RCU-bh counterpart to rcu_dereference_check().
  */
 #define rcu_dereference_bh_check(p, c) \
-       __rcu_dereference_check((p), rcu_read_lock_bh_held() || (c), __rcu)
+       __rcu_dereference_check((p), (c) || rcu_read_lock_bh_held(), __rcu)
 
 /**
  * rcu_dereference_sched_check() - rcu_dereference_sched with debug checking
@@ -740,7 +772,7 @@ static inline void rcu_preempt_sleep_check(void)
  * This is the RCU-sched counterpart to rcu_dereference_check().
  */
 #define rcu_dereference_sched_check(p, c) \
-       __rcu_dereference_check((p), rcu_read_lock_sched_held() || (c), \
+       __rcu_dereference_check((p), (c) || rcu_read_lock_sched_held(), \
                                __rcu)
 
 #define rcu_dereference_raw(p) rcu_dereference_check(p, 1) /*@@@ needed? @@@*/
@@ -933,9 +965,9 @@ static inline void rcu_read_unlock(void)
 {
        rcu_lockdep_assert(rcu_is_watching(),
                           "rcu_read_unlock() used illegally while idle");
-       rcu_lock_release(&rcu_lock_map);
        __release(RCU);
        __rcu_read_unlock();
+       rcu_lock_release(&rcu_lock_map); /* Keep acq info for rls diags. */
 }
 
 /**
index b6c4909b33af8247d685f0a6932dfc73fc352ec5..15fa8f2d35c9a58fc2e563418ee00981eb1da13f 100644 (file)
 
 #include <linux/regulator/machine.h>
 
+enum {
+       ACT8600_ID_DCDC1,
+       ACT8600_ID_DCDC2,
+       ACT8600_ID_DCDC3,
+       ACT8600_ID_SUDCDC4,
+       ACT8600_ID_LDO5,
+       ACT8600_ID_LDO6,
+       ACT8600_ID_LDO7,
+       ACT8600_ID_LDO8,
+       ACT8600_ID_LDO9,
+       ACT8600_ID_LDO10,
+};
+
 enum {
        ACT8865_ID_DCDC1,
        ACT8865_ID_DCDC2,
@@ -46,6 +59,7 @@ enum {
 };
 
 enum {
+       ACT8600,
        ACT8865,
        ACT8846,
 };
index d17e1ff7ad019987d4c4f944dd3a6b20aa571807..f8a689ed62a58753cb3d4863f61d834cdca74f62 100644 (file)
@@ -114,7 +114,7 @@ struct regmap;
 #define REGULATOR_EVENT_OVER_TEMP              0x10
 #define REGULATOR_EVENT_FORCE_DISABLE          0x20
 #define REGULATOR_EVENT_VOLTAGE_CHANGE         0x40
-#define REGULATOR_EVENT_DISABLE                0x80
+#define REGULATOR_EVENT_DISABLE                        0x80
 #define REGULATOR_EVENT_PRE_VOLTAGE_CHANGE     0x100
 #define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE   0x200
 #define REGULATOR_EVENT_PRE_DISABLE            0x400
@@ -238,7 +238,7 @@ int regulator_get_current_limit(struct regulator *regulator);
 
 int regulator_set_mode(struct regulator *regulator, unsigned int mode);
 unsigned int regulator_get_mode(struct regulator *regulator);
-int regulator_set_optimum_mode(struct regulator *regulator, int load_uA);
+int regulator_set_load(struct regulator *regulator, int load_uA);
 
 int regulator_allow_bypass(struct regulator *regulator, bool allow);
 
@@ -252,8 +252,12 @@ int regulator_list_hardware_vsel(struct regulator *regulator,
 /* regulator notifier block */
 int regulator_register_notifier(struct regulator *regulator,
                              struct notifier_block *nb);
+int devm_regulator_register_notifier(struct regulator *regulator,
+                                    struct notifier_block *nb);
 int regulator_unregister_notifier(struct regulator *regulator,
                                struct notifier_block *nb);
+void devm_regulator_unregister_notifier(struct regulator *regulator,
+                                       struct notifier_block *nb);
 
 /* driver data - core doesn't touch */
 void *regulator_get_drvdata(struct regulator *regulator);
@@ -479,8 +483,7 @@ static inline unsigned int regulator_get_mode(struct regulator *regulator)
        return REGULATOR_MODE_NORMAL;
 }
 
-static inline int regulator_set_optimum_mode(struct regulator *regulator,
-                                       int load_uA)
+static inline int regulator_set_load(struct regulator *regulator, int load_uA)
 {
        return REGULATOR_MODE_NORMAL;
 }
@@ -515,12 +518,24 @@ static inline int regulator_register_notifier(struct regulator *regulator,
        return 0;
 }
 
+static inline int devm_regulator_register_notifier(struct regulator *regulator,
+                                                  struct notifier_block *nb)
+{
+       return 0;
+}
+
 static inline int regulator_unregister_notifier(struct regulator *regulator,
                                struct notifier_block *nb)
 {
        return 0;
 }
 
+static inline int devm_regulator_unregister_notifier(struct regulator *regulator,
+                                                    struct notifier_block *nb)
+{
+       return 0;
+}
+
 static inline void *regulator_get_drvdata(struct regulator *regulator)
 {
        return NULL;
index 045f709cb89b52c5e2381635b0bea10101030120..fffa688ac3a7a36c9ecc33e006c52f1c4cf3892c 100644 (file)
@@ -98,6 +98,7 @@ struct regulator_linear_range {
  *     REGULATOR_STATUS value (or negative errno)
  * @get_optimum_mode: Get the most efficient operating mode for the regulator
  *                    when running with the specified parameters.
+ * @set_load: Set the load for the regulator.
  *
  * @set_bypass: Set the regulator in bypass mode.
  * @get_bypass: Get the regulator bypass mode state.
@@ -167,6 +168,8 @@ struct regulator_ops {
        /* get most efficient regulator operating mode for load */
        unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV,
                                          int output_uV, int load_uA);
+       /* set the load on the regulator */
+       int (*set_load)(struct regulator_dev *, int load_uA);
 
        /* control and report on bypass mode */
        int (*set_bypass)(struct regulator_dev *dev, bool enable);
@@ -367,6 +370,7 @@ struct regulator_dev {
        struct device dev;
        struct regulation_constraints *constraints;
        struct regulator *supply;       /* for tree */
+       const char *supply_name;
        struct regmap *regmap;
 
        struct delayed_work disable_work;
index dcad7ee0d7466c8e7ffd7a050e814db551c95cac..8dcf6825fa88bbe25c7936797a4322bfd0e24318 100644 (file)
@@ -77,6 +77,7 @@ struct rtc_class_ops {
        int (*read_alarm)(struct device *, struct rtc_wkalrm *);
        int (*set_alarm)(struct device *, struct rtc_wkalrm *);
        int (*proc)(struct device *, struct seq_file *);
+       int (*set_mmss64)(struct device *, time64_t secs);
        int (*set_mmss)(struct device *, unsigned long secs);
        int (*read_callback)(struct device *, int data);
        int (*alarm_irq_enable)(struct device *, unsigned int enabled);
index a419b65770d669c3a51c88a86a145abbcd3db339..f74d4cc3a3e54f72026449a8f70ff287dc807248 100644 (file)
@@ -176,6 +176,14 @@ extern void get_iowait_load(unsigned long *nr_waiters, unsigned long *load);
 extern void calc_global_load(unsigned long ticks);
 extern void update_cpu_load_nohz(void);
 
+/* Notifier for when a task gets migrated to a new CPU */
+struct task_migration_notifier {
+       struct task_struct *task;
+       int from_cpu;
+       int to_cpu;
+};
+extern void register_task_migration_notifier(struct notifier_block *n);
+
 extern unsigned long get_parent_ip(unsigned long addr);
 
 extern void dump_cpu_task(int cpu);
@@ -329,6 +337,8 @@ extern asmlinkage void schedule_tail(struct task_struct *prev);
 extern void init_idle(struct task_struct *idle, int cpu);
 extern void init_idle_bootup_task(struct task_struct *idle);
 
+extern cpumask_var_t cpu_isolated_map;
+
 extern int runqueue_is_locked(int cpu);
 
 #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
@@ -1115,15 +1125,28 @@ struct load_weight {
 };
 
 struct sched_avg {
+       u64 last_runnable_update;
+       s64 decay_count;
+       /*
+        * utilization_avg_contrib describes the amount of time that a
+        * sched_entity is running on a CPU. It is based on running_avg_sum
+        * and is scaled in the range [0..SCHED_LOAD_SCALE].
+        * load_avg_contrib described the amount of time that a sched_entity
+        * is runnable on a rq. It is based on both runnable_avg_sum and the
+        * weight of the task.
+        */
+       unsigned long load_avg_contrib, utilization_avg_contrib;
        /*
         * These sums represent an infinite geometric series and so are bound
         * above by 1024/(1-y).  Thus we only need a u32 to store them for all
         * choices of y < 1-2^(-32)*1024.
+        * running_avg_sum reflects the time that the sched_entity is
+        * effectively running on the CPU.
+        * runnable_avg_sum represents the amount of time a sched_entity is on
+        * a runqueue which includes the running time that is monitored by
+        * running_avg_sum.
         */
-       u32 runnable_avg_sum, runnable_avg_period;
-       u64 last_runnable_update;
-       s64 decay_count;
-       unsigned long load_avg_contrib;
+       u32 runnable_avg_sum, avg_period, running_avg_sum;
 };
 
 #ifdef CONFIG_SCHEDSTATS
index a1b7dbd127ffc73c1c07f3935ed9cd9118cfec52..4e14e3d6309f2d628e74d81a866177e0f0c30a68 100644 (file)
@@ -1556,7 +1556,7 @@ struct security_operations {
        int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
        int (*inode_permission) (struct inode *inode, int mask);
        int (*inode_setattr)    (struct dentry *dentry, struct iattr *attr);
-       int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
+       int (*inode_getattr) (const struct path *path);
        int (*inode_setxattr) (struct dentry *dentry, const char *name,
                               const void *value, size_t size, int flags);
        void (*inode_post_setxattr) (struct dentry *dentry, const char *name,
@@ -1843,7 +1843,7 @@ int security_inode_readlink(struct dentry *dentry);
 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
 int security_inode_permission(struct inode *inode, int mask);
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
-int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
+int security_inode_getattr(const struct path *path);
 int security_inode_setxattr(struct dentry *dentry, const char *name,
                            const void *value, size_t size, int flags);
 void security_inode_post_setxattr(struct dentry *dentry, const char *name,
@@ -2259,8 +2259,7 @@ static inline int security_inode_setattr(struct dentry *dentry,
        return 0;
 }
 
-static inline int security_inode_getattr(struct vfsmount *mnt,
-                                         struct dentry *dentry)
+static inline int security_inode_getattr(const struct path *path)
 {
        return 0;
 }
index f5df8f687b4d097dd7855e3670a2b790cb380d5d..5f68d0a391cee8506f8e0d94cda72d8bd357b10f 100644 (file)
@@ -108,7 +108,7 @@ static inline unsigned __read_seqcount_begin(const seqcount_t *s)
        unsigned ret;
 
 repeat:
-       ret = ACCESS_ONCE(s->sequence);
+       ret = READ_ONCE(s->sequence);
        if (unlikely(ret & 1)) {
                cpu_relax();
                goto repeat;
@@ -127,7 +127,7 @@ repeat:
  */
 static inline unsigned raw_read_seqcount(const seqcount_t *s)
 {
-       unsigned ret = ACCESS_ONCE(s->sequence);
+       unsigned ret = READ_ONCE(s->sequence);
        smp_rmb();
        return ret;
 }
@@ -179,7 +179,7 @@ static inline unsigned read_seqcount_begin(const seqcount_t *s)
  */
 static inline unsigned raw_seqcount_begin(const seqcount_t *s)
 {
-       unsigned ret = ACCESS_ONCE(s->sequence);
+       unsigned ret = READ_ONCE(s->sequence);
        smp_rmb();
        return ret & ~1;
 }
index 76f1feeabd383300433e31b2cf594fb82df47fba..ffd24c8301513f956c6ede0927e8548f73a131c9 100644 (file)
@@ -18,7 +18,7 @@
 
 /*
  * Flags to pass to kmem_cache_create().
- * The ones marked DEBUG are only valid if CONFIG_SLAB_DEBUG is set.
+ * The ones marked DEBUG are only valid if CONFIG_DEBUG_SLAB is set.
  */
 #define SLAB_DEBUG_FREE                0x00000100UL    /* DEBUG: Perform (expensive) checks on free */
 #define SLAB_RED_ZONE          0x00000400UL    /* DEBUG: Red zone objs in a cache */
index 13e929679550ab4967b72a73e544dbf531f74004..d600afb2192673702a9000d3e64b1788f15ec1af 100644 (file)
@@ -47,6 +47,5 @@ struct smp_hotplug_thread {
 
 int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread);
 void smpboot_unregister_percpu_thread(struct smp_hotplug_thread *plug_thread);
-int smpboot_thread_schedule(void);
 
 #endif
index 856d34dde79bc9d81faae4171fb0c5492829c133..d673072346f2e0415fd4706c7606d5081f87f686 100644 (file)
@@ -162,8 +162,6 @@ struct spi_transfer;
  * @remove: Unbinds this driver from the spi device
  * @shutdown: Standard shutdown callback used during system state
  *     transitions such as powerdown/halt and kexec
- * @suspend: Standard suspend callback used during system state transitions
- * @resume: Standard resume callback used during system state transitions
  * @driver: SPI device drivers should initialize the name and owner
  *     field of this structure.
  *
@@ -184,8 +182,6 @@ struct spi_driver {
        int                     (*probe)(struct spi_device *spi);
        int                     (*remove)(struct spi_device *spi);
        void                    (*shutdown)(struct spi_device *spi);
-       int                     (*suspend)(struct spi_device *spi, pm_message_t mesg);
-       int                     (*resume)(struct spi_device *spi);
        struct device_driver    driver;
 };
 
@@ -294,6 +290,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  *                    transfer_one_message are mutually exclusive; when both
  *                    are set, the generic subsystem does not call your
  *                    transfer_one callback.
+ * @handle_err: the subsystem calls the driver to handle an error that occurs
+ *             in the generic implementation of transfer_one_message().
  * @unprepare_message: undo any work done by prepare_message().
  * @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
@@ -448,6 +446,8 @@ struct spi_master {
        void (*set_cs)(struct spi_device *spi, bool enable);
        int (*transfer_one)(struct spi_master *master, struct spi_device *spi,
                            struct spi_transfer *transfer);
+       void (*handle_err)(struct spi_master *master,
+                          struct spi_message *message);
 
        /* gpio chip select */
        int                     *cs_gpios;
index 9cfd9623fb0325a692c4929cac048912644dc0ac..bdeb4567b71e55edc785d5173f5ccc15ec0cda69 100644 (file)
@@ -182,7 +182,7 @@ static inline int srcu_read_lock_held(struct srcu_struct *sp)
  * lockdep_is_held() calls.
  */
 #define srcu_dereference_check(p, sp, c) \
-       __rcu_dereference_check((p), srcu_read_lock_held(sp) || (c), __rcu)
+       __rcu_dereference_check((p), (c) || srcu_read_lock_held(sp), __rcu)
 
 /**
  * srcu_dereference - fetch SRCU-protected pointer for later dereferencing
index 669045ab73f30d7abbf72da9faa1a3724fe69b25..0a34489a46b62a4c526e27b39b53d3d571db6727 100644 (file)
@@ -7,8 +7,6 @@ struct task_struct;
 struct pt_regs;
 
 #ifdef CONFIG_STACKTRACE
-struct task_struct;
-
 struct stack_trace {
        unsigned int nr_entries, max_entries;
        unsigned long *entries;
index f4aec0e75c3a268cebeecd2dcdc43fc68126a27a..076af437284d59f9b2597e9d6f448804cf56fcb3 100644 (file)
@@ -19,3 +19,12 @@ enum {
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
 #endif
 #endif
+
+/**
+ * offsetofend(TYPE, MEMBER)
+ *
+ * @TYPE: The type of the structure
+ * @MEMBER: The member within the structure to get the end offset of
+ */
+#define offsetofend(TYPE, MEMBER) \
+       (offsetof(TYPE, MEMBER) + sizeof(((TYPE *)0)->MEMBER))
index ddad16148bd69cd2b6d7c4a682864b6d29f7a1dc..99382c0df17eb3fc367e3b3eafd5dca3cb63975a 100644 (file)
@@ -57,6 +57,21 @@ do {                                                 \
 #define sysfs_attr_init(attr) do {} while (0)
 #endif
 
+/**
+ * struct attribute_group - data structure used to declare an attribute group.
+ * @name:      Optional: Attribute group name
+ *             If specified, the attribute group will be created in
+ *             a new subdirectory with this name.
+ * @is_visible:        Optional: Function to return permissions associated with an
+ *             attribute of the group. Will be called repeatedly for each
+ *             attribute in the group. Only read/write permissions as well as
+ *             SYSFS_PREALLOC are accepted. Must return 0 if an attribute is
+ *             not visible. The returned value will replace static permissions
+ *             defined in struct attribute or struct bin_attribute.
+ * @attrs:     Pointer to NULL terminated list of attributes.
+ * @bin_attrs: Pointer to NULL terminated list of binary attributes.
+ *             Either attrs or bin_attrs or both must be provided.
+ */
 struct attribute_group {
        const char              *name;
        umode_t                 (*is_visible)(struct kobject *,
index 9c085dc12ae92626e3d6ae831df435a82f188c08..f8492da57ad32e7607e320510a24ac0165dcd8cd 100644 (file)
@@ -1,7 +1,5 @@
-/*  linux/include/linux/tick.h
- *
- *  This file contains the structure definitions for tick related functions
- *
+/*
+ * Tick related global functions
  */
 #ifndef _LINUX_TICK_H
 #define _LINUX_TICK_H
 #include <linux/clockchips.h>
 #include <linux/irqflags.h>
 #include <linux/percpu.h>
-#include <linux/hrtimer.h>
 #include <linux/context_tracking_state.h>
 #include <linux/cpumask.h>
 #include <linux/sched.h>
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
-
-enum tick_device_mode {
-       TICKDEV_MODE_PERIODIC,
-       TICKDEV_MODE_ONESHOT,
-};
-
-struct tick_device {
-       struct clock_event_device *evtdev;
-       enum tick_device_mode mode;
-};
-
-enum tick_nohz_mode {
-       NOHZ_MODE_INACTIVE,
-       NOHZ_MODE_LOWRES,
-       NOHZ_MODE_HIGHRES,
-};
-
-/**
- * struct tick_sched - sched tick emulation and no idle tick control/stats
- * @sched_timer:       hrtimer to schedule the periodic tick in high
- *                     resolution mode
- * @last_tick:         Store the last tick expiry time when the tick
- *                     timer is modified for nohz sleeps. This is necessary
- *                     to resume the tick timer operation in the timeline
- *                     when the CPU returns from nohz sleep.
- * @tick_stopped:      Indicator that the idle tick has been stopped
- * @idle_jiffies:      jiffies at the entry to idle for idle time accounting
- * @idle_calls:                Total number of idle calls
- * @idle_sleeps:       Number of idle calls, where the sched tick was stopped
- * @idle_entrytime:    Time when the idle call was entered
- * @idle_waketime:     Time when the idle was interrupted
- * @idle_exittime:     Time when the idle state was left
- * @idle_sleeptime:    Sum of the time slept in idle with sched tick stopped
- * @iowait_sleeptime:  Sum of the time slept in idle with sched tick stopped, with IO outstanding
- * @sleep_length:      Duration of the current idle sleep
- * @do_timer_lst:      CPU was the last one doing do_timer before going idle
- */
-struct tick_sched {
-       struct hrtimer                  sched_timer;
-       unsigned long                   check_clocks;
-       enum tick_nohz_mode             nohz_mode;
-       ktime_t                         last_tick;
-       int                             inidle;
-       int                             tick_stopped;
-       unsigned long                   idle_jiffies;
-       unsigned long                   idle_calls;
-       unsigned long                   idle_sleeps;
-       int                             idle_active;
-       ktime_t                         idle_entrytime;
-       ktime_t                         idle_waketime;
-       ktime_t                         idle_exittime;
-       ktime_t                         idle_sleeptime;
-       ktime_t                         iowait_sleeptime;
-       ktime_t                         sleep_length;
-       unsigned long                   last_jiffies;
-       unsigned long                   next_jiffies;
-       ktime_t                         idle_expires;
-       int                             do_timer_last;
-};
-
 extern void __init tick_init(void);
-extern int tick_is_oneshot_available(void);
-extern struct tick_device *tick_get_device(int cpu);
-
 extern void tick_freeze(void);
 extern void tick_unfreeze(void);
+/* Should be core only, but ARM BL switcher requires it */
+extern void tick_suspend_local(void);
+/* Should be core only, but XEN resume magic and ARM BL switcher require it */
+extern void tick_resume_local(void);
+extern void tick_handover_do_timer(void);
+extern void tick_cleanup_dead_cpu(int cpu);
+#else /* CONFIG_GENERIC_CLOCKEVENTS */
+static inline void tick_init(void) { }
+static inline void tick_freeze(void) { }
+static inline void tick_unfreeze(void) { }
+static inline void tick_suspend_local(void) { }
+static inline void tick_resume_local(void) { }
+static inline void tick_handover_do_timer(void) { }
+static inline void tick_cleanup_dead_cpu(int cpu) { }
+#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
-# ifdef CONFIG_HIGH_RES_TIMERS
-extern int tick_init_highres(void);
-extern int tick_program_event(ktime_t expires, int force);
-extern void tick_setup_sched_timer(void);
-# endif
-
-# if defined CONFIG_NO_HZ_COMMON || defined CONFIG_HIGH_RES_TIMERS
-extern void tick_cancel_sched_timer(int cpu);
-# else
-static inline void tick_cancel_sched_timer(int cpu) { }
-# endif
-
-# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-extern struct tick_device *tick_get_broadcast_device(void);
-extern struct cpumask *tick_get_broadcast_mask(void);
-
-#  ifdef CONFIG_TICK_ONESHOT
-extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
-#  endif
-
-# endif /* BROADCAST */
-
-# ifdef CONFIG_TICK_ONESHOT
-extern void tick_clock_notify(void);
-extern int tick_check_oneshot_change(int allow_nohz);
-extern struct tick_sched *tick_get_tick_sched(int cpu);
+#ifdef CONFIG_TICK_ONESHOT
 extern void tick_irq_enter(void);
-extern int tick_oneshot_mode_active(void);
 #  ifndef arch_needs_cpu
 #   define arch_needs_cpu() (0)
 #  endif
 # else
-static inline void tick_clock_notify(void) { }
-static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
 static inline void tick_irq_enter(void) { }
-static inline int tick_oneshot_mode_active(void) { return 0; }
-# endif
+#endif
 
-#else /* CONFIG_GENERIC_CLOCKEVENTS */
-static inline void tick_init(void) { }
-static inline void tick_freeze(void) { }
-static inline void tick_unfreeze(void) { }
-static inline void tick_cancel_sched_timer(int cpu) { }
-static inline void tick_clock_notify(void) { }
-static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
-static inline void tick_irq_enter(void) { }
-static inline int tick_oneshot_mode_active(void) { return 0; }
-#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
+#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
+extern void hotplug_cpu__broadcast_tick_pull(int dead_cpu);
+#else
+static inline void hotplug_cpu__broadcast_tick_pull(int dead_cpu) { }
+#endif
 
-# ifdef CONFIG_NO_HZ_COMMON
-DECLARE_PER_CPU(struct tick_sched, tick_cpu_sched);
+enum tick_broadcast_mode {
+       TICK_BROADCAST_OFF,
+       TICK_BROADCAST_ON,
+       TICK_BROADCAST_FORCE,
+};
+
+enum tick_broadcast_state {
+       TICK_BROADCAST_EXIT,
+       TICK_BROADCAST_ENTER,
+};
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+extern void tick_broadcast_control(enum tick_broadcast_mode mode);
+#else
+static inline void tick_broadcast_control(enum tick_broadcast_mode mode) { }
+#endif /* BROADCAST */
+
+#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
+extern int tick_broadcast_oneshot_control(enum tick_broadcast_state state);
+#else
+static inline int tick_broadcast_oneshot_control(enum tick_broadcast_state state) { return 0; }
+#endif
 
-static inline int tick_nohz_tick_stopped(void)
+static inline void tick_broadcast_enable(void)
+{
+       tick_broadcast_control(TICK_BROADCAST_ON);
+}
+static inline void tick_broadcast_disable(void)
+{
+       tick_broadcast_control(TICK_BROADCAST_OFF);
+}
+static inline void tick_broadcast_force(void)
+{
+       tick_broadcast_control(TICK_BROADCAST_FORCE);
+}
+static inline int tick_broadcast_enter(void)
 {
-       return __this_cpu_read(tick_cpu_sched.tick_stopped);
+       return tick_broadcast_oneshot_control(TICK_BROADCAST_ENTER);
+}
+static inline void tick_broadcast_exit(void)
+{
+       tick_broadcast_oneshot_control(TICK_BROADCAST_EXIT);
 }
 
+#ifdef CONFIG_NO_HZ_COMMON
+extern int tick_nohz_tick_stopped(void);
 extern void tick_nohz_idle_enter(void);
 extern void tick_nohz_idle_exit(void);
 extern void tick_nohz_irq_exit(void);
 extern ktime_t tick_nohz_get_sleep_length(void);
 extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time);
 extern u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time);
-
-# else /* !CONFIG_NO_HZ_COMMON */
-static inline int tick_nohz_tick_stopped(void)
-{
-       return 0;
-}
-
+#else /* !CONFIG_NO_HZ_COMMON */
+static inline int tick_nohz_tick_stopped(void) { return 0; }
 static inline void tick_nohz_idle_enter(void) { }
 static inline void tick_nohz_idle_exit(void) { }
 
@@ -163,7 +111,7 @@ static inline ktime_t tick_nohz_get_sleep_length(void)
 }
 static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; }
 static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; }
-# endif /* !CONFIG_NO_HZ_COMMON */
+#endif /* !CONFIG_NO_HZ_COMMON */
 
 #ifdef CONFIG_NO_HZ_FULL
 extern bool tick_nohz_full_running;
index 05af9a3348934602456ec18b9cd29df84ac5a167..fb86963859c772846dfc531fc9cc8c0825f36ac7 100644 (file)
  * @read:      Read function of @clock
  * @mask:      Bitmask for two's complement subtraction of non 64bit clocks
  * @cycle_last: @clock cycle value at last update
- * @mult:      NTP adjusted multiplier for scaled math conversion
+ * @mult:      (NTP adjusted) multiplier for scaled math conversion
  * @shift:     Shift value for scaled math conversion
  * @xtime_nsec: Shifted (fractional) nano seconds offset for readout
- * @base_mono:  ktime_t (nanoseconds) base time for readout
+ * @base:      ktime_t (nanoseconds) base time for readout
  *
  * This struct has size 56 byte on 64 bit. Together with a seqcount it
  * occupies a single 64byte cache line.
  *
  * The struct is separate from struct timekeeper as it is also used
- * for a fast NMI safe accessor to clock monotonic.
+ * for a fast NMI safe accessors.
  */
 struct tk_read_base {
        struct clocksource      *clock;
@@ -35,12 +35,13 @@ struct tk_read_base {
        u32                     mult;
        u32                     shift;
        u64                     xtime_nsec;
-       ktime_t                 base_mono;
+       ktime_t                 base;
 };
 
 /**
  * struct timekeeper - Structure holding internal timekeeping values.
- * @tkr:               The readout base structure
+ * @tkr_mono:          The readout base structure for CLOCK_MONOTONIC
+ * @tkr_raw:           The readout base structure for CLOCK_MONOTONIC_RAW
  * @xtime_sec:         Current CLOCK_REALTIME time in seconds
  * @ktime_sec:         Current CLOCK_MONOTONIC time in seconds
  * @wall_to_monotonic: CLOCK_REALTIME to CLOCK_MONOTONIC offset
@@ -48,7 +49,6 @@ struct tk_read_base {
  * @offs_boot:         Offset clock monotonic -> clock boottime
  * @offs_tai:          Offset clock monotonic -> clock tai
  * @tai_offset:                The current UTC to TAI offset in seconds
- * @base_raw:          Monotonic raw base time in ktime_t format
  * @raw_time:          Monotonic raw base time in timespec64 format
  * @cycle_interval:    Number of clock cycles in one NTP interval
  * @xtime_interval:    Number of clock shifted nano seconds in one NTP
@@ -76,7 +76,8 @@ struct tk_read_base {
  * used instead.
  */
 struct timekeeper {
-       struct tk_read_base     tkr;
+       struct tk_read_base     tkr_mono;
+       struct tk_read_base     tkr_raw;
        u64                     xtime_sec;
        unsigned long           ktime_sec;
        struct timespec64       wall_to_monotonic;
@@ -84,7 +85,6 @@ struct timekeeper {
        ktime_t                 offs_boot;
        ktime_t                 offs_tai;
        s32                     tai_offset;
-       ktime_t                 base_raw;
        struct timespec64       raw_time;
 
        /* The following members are for timekeeping internal use */
index 3eaae47542751962579a3c6736f18917e4da7ad3..99176af216af449563e3a190b96edc04ea1a1f9e 100644 (file)
@@ -214,12 +214,18 @@ static inline u64 ktime_get_boot_ns(void)
        return ktime_to_ns(ktime_get_boottime());
 }
 
+static inline u64 ktime_get_tai_ns(void)
+{
+       return ktime_to_ns(ktime_get_clocktai());
+}
+
 static inline u64 ktime_get_raw_ns(void)
 {
        return ktime_to_ns(ktime_get_raw());
 }
 
 extern u64 ktime_get_mono_fast_ns(void);
+extern u64 ktime_get_raw_fast_ns(void);
 
 /*
  * Timespec interfaces utilizing the ktime based ones
@@ -242,6 +248,9 @@ static inline void timekeeping_clocktai(struct timespec *ts)
 /*
  * RTC specific
  */
+extern bool timekeeping_rtc_skipsuspend(void);
+extern bool timekeeping_rtc_skipresume(void);
+
 extern void timekeeping_inject_sleeptime64(struct timespec64 *delta);
 
 /*
@@ -253,17 +262,14 @@ extern void getnstime_raw_and_real(struct timespec *ts_raw,
 /*
  * Persistent clock related interfaces
  */
-extern bool persistent_clock_exist;
 extern int persistent_clock_is_local;
 
-static inline bool has_persistent_clock(void)
-{
-       return persistent_clock_exist;
-}
-
 extern void read_persistent_clock(struct timespec *ts);
+extern void read_persistent_clock64(struct timespec64 *ts);
 extern void read_boot_clock(struct timespec *ts);
+extern void read_boot_clock64(struct timespec64 *ts);
 extern int update_persistent_clock(struct timespec now);
+extern int update_persistent_clock64(struct timespec64 now);
 
 
 #endif
diff --git a/include/linux/tracefs.h b/include/linux/tracefs.h
new file mode 100644 (file)
index 0000000..5b727a1
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  tracefs.h - a pseudo file system for activating tracing
+ *
+ * Based on debugfs by: 2004 Greg Kroah-Hartman <greg@kroah.com>
+ *
+ *  Copyright (C) 2014 Red Hat Inc, author: Steven Rostedt <srostedt@redhat.com>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License version
+ *     2 as published by the Free Software Foundation.
+ *
+ * tracefs is the file system that is used by the tracing infrastructure.
+ *
+ */
+
+#ifndef _TRACEFS_H_
+#define _TRACEFS_H_
+
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+
+#include <linux/types.h>
+
+struct file_operations;
+
+#ifdef CONFIG_TRACING
+
+struct dentry *tracefs_create_file(const char *name, umode_t mode,
+                                  struct dentry *parent, void *data,
+                                  const struct file_operations *fops);
+
+struct dentry *tracefs_create_dir(const char *name, struct dentry *parent);
+
+void tracefs_remove(struct dentry *dentry);
+void tracefs_remove_recursive(struct dentry *dentry);
+
+struct dentry *tracefs_create_instance_dir(const char *name, struct dentry *parent,
+                                          int (*mkdir)(const char *name),
+                                          int (*rmdir)(const char *name));
+
+bool tracefs_initialized(void);
+
+#endif /* CONFIG_TRACING */
+
+#endif
index c72851328ca9cc071620cfdef3892ca91db6d96a..a5f7f3ecafa3a77123531ca2a07a01b086906db0 100644 (file)
@@ -36,6 +36,12 @@ struct tracepoint {
        struct tracepoint_func __rcu *funcs;
 };
 
+struct trace_enum_map {
+       const char              *system;
+       const char              *enum_string;
+       unsigned long           enum_value;
+};
+
 extern int
 tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data);
 extern int
@@ -87,6 +93,8 @@ extern void syscall_unregfunc(void);
 
 #define PARAMS(args...) args
 
+#define TRACE_DEFINE_ENUM(x)
+
 #endif /* _LINUX_TRACEPOINT_H */
 
 /*
index 71880299ed487b68dc7b278248a4fb29ddb6b6ec..15f11fb9fff6feb5197f9501777e018f172dda4b 100644 (file)
@@ -76,6 +76,7 @@ size_t iov_iter_copy_from_user_atomic(struct page *page,
                struct iov_iter *i, unsigned long offset, size_t bytes);
 void iov_iter_advance(struct iov_iter *i, size_t bytes);
 int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes);
+int iov_iter_fault_in_multipages_readable(struct iov_iter *i, size_t bytes);
 size_t iov_iter_single_seg_count(const struct iov_iter *i);
 size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
                         struct iov_iter *i);
@@ -139,4 +140,18 @@ static inline void iov_iter_reexpand(struct iov_iter *i, size_t count)
 size_t csum_and_copy_to_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
 size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
 
+int import_iovec(int type, const struct iovec __user * uvector,
+                unsigned nr_segs, unsigned fast_segs,
+                struct iovec **iov, struct iov_iter *i);
+
+#ifdef CONFIG_COMPAT
+struct compat_iovec;
+int compat_import_iovec(int type, const struct compat_iovec __user * uvector,
+                unsigned nr_segs, unsigned fast_segs,
+                struct iovec **iov, struct iov_iter *i);
+#endif
+
+int import_single_range(int type, void __user *buf, size_t len,
+                struct iovec *iov, struct iov_iter *i);
+
 #endif
index 7ee1b5c3b4cbb71f53c9e1d32c3eb92c8c6c6d45..447fe29b55b451148c452b82cb0043d510a26eae 100644 (file)
@@ -205,6 +205,32 @@ void usb_put_intf(struct usb_interface *intf);
 #define USB_MAXINTERFACES      32
 #define USB_MAXIADS            (USB_MAXINTERFACES/2)
 
+/*
+ * USB Resume Timer: Every Host controller driver should drive the resume
+ * signalling on the bus for the amount of time defined by this macro.
+ *
+ * That way we will have a 'stable' behavior among all HCDs supported by Linux.
+ *
+ * Note that the USB Specification states we should drive resume for *at least*
+ * 20 ms, but it doesn't give an upper bound. This creates two possible
+ * situations which we want to avoid:
+ *
+ * (a) sometimes an msleep(20) might expire slightly before 20 ms, which causes
+ * us to fail USB Electrical Tests, thus failing Certification
+ *
+ * (b) Some (many) devices actually need more than 20 ms of resume signalling,
+ * and while we can argue that's against the USB Specification, we don't have
+ * control over which devices a certification laboratory will be using for
+ * certification. If CertLab uses a device which was tested against Windows and
+ * that happens to have relaxed resume signalling rules, we might fall into
+ * situations where we fail interoperability and electrical tests.
+ *
+ * In order to avoid both conditions, we're using a 40 ms resume timeout, which
+ * should cope with both LPJ calibration errors and devices not following every
+ * detail of the USB Specification.
+ */
+#define USB_RESUME_TIMEOUT     40 /* ms */
+
 /**
  * struct usb_interface_cache - long-term representation of a device interface
  * @num_altsetting: number of altsettings defined.
index 535997a6681b90318e37e9fcabc5e4ecae22109b..ab94f78c4dd15ee4554a4eff996c862b7a6fd869 100644 (file)
@@ -19,6 +19,7 @@ struct ci_hdrc_platform_data {
        enum usb_phy_interface phy_mode;
        unsigned long    flags;
 #define CI_HDRC_REGS_SHARED            BIT(0)
+#define CI_HDRC_SUPPORTS_RUNTIME_PM    BIT(2)
 #define CI_HDRC_DISABLE_STREAMING      BIT(3)
        /*
         * Only set it when DCCPARAMS.DC==1 and DCCPARAMS.HC==1,
@@ -27,6 +28,7 @@ struct ci_hdrc_platform_data {
 #define CI_HDRC_DUAL_ROLE_NOT_OTG      BIT(4)
 #define CI_HDRC_IMX28_WRITE_FIX                BIT(5)
 #define CI_HDRC_FORCE_FULLSPEED                BIT(6)
+#define CI_HDRC_TURN_VBUS_EARLY_ON     BIT(7)
        enum usb_dr_mode        dr_mode;
 #define CI_HDRC_CONTROLLER_RESET_EVENT         0
 #define CI_HDRC_CONTROLLER_STOPPED_EVENT       1
index 3d87defcc5270f1659a610a3d126c0156c0c6ce2..2511469a99048996fa53232801fdb6a72bb90d4b 100644 (file)
@@ -148,6 +148,7 @@ struct usb_os_desc_table {
  * @disable: (REQUIRED) Indicates the function should be disabled.  Reasons
  *     include host resetting or reconfiguring the gadget, and disconnection.
  * @setup: Used for interface-specific control requests.
+ * @req_match: Tests if a given class request can be handled by this function.
  * @suspend: Notifies functions when the host stops sending USB traffic.
  * @resume: Notifies functions when the host restarts USB traffic.
  * @get_status: Returns function status as a reply to
@@ -213,6 +214,8 @@ struct usb_function {
        void                    (*disable)(struct usb_function *);
        int                     (*setup)(struct usb_function *,
                                        const struct usb_ctrlrequest *);
+       bool                    (*req_match)(struct usb_function *,
+                                       const struct usb_ctrlrequest *);
        void                    (*suspend)(struct usb_function *);
        void                    (*resume)(struct usb_function *);
 
index e2f00fd8cd47093ff7ca711f295af7ca2b07a649..4f3dfb7d065420d012eeade7154575100473602c 100644 (file)
@@ -190,7 +190,7 @@ struct usb_ep {
  * @ep:the endpoint being configured
  * @maxpacket_limit:value of maximum packet size limit
  *
- * This function shoud be used only in UDC drivers to initialize endpoint
+ * This function should be used only in UDC drivers to initialize endpoint
  * (usually in probe function).
  */
 static inline void usb_ep_set_maxpacket_limit(struct usb_ep *ep,
@@ -474,6 +474,7 @@ struct usb_dcd_config_params {
 
 struct usb_gadget;
 struct usb_gadget_driver;
+struct usb_udc;
 
 /* the rest of the api to the controller hardware: device operations,
  * which don't involve endpoints (or i/o).
@@ -496,6 +497,7 @@ struct usb_gadget_ops {
 /**
  * struct usb_gadget - represents a usb slave device
  * @work: (internal use) Workqueue to be used for sysfs_notify()
+ * @udc: struct usb_udc pointer for this gadget
  * @ops: Function pointers used to access hardware-specific operations.
  * @ep0: Endpoint zero, used when reading or writing responses to
  *     driver setup() requests
@@ -545,6 +547,7 @@ struct usb_gadget_ops {
  */
 struct usb_gadget {
        struct work_struct              work;
+       struct usb_udc                  *udc;
        /* readonly to gadget driver */
        const struct usb_gadget_ops     *ops;
        struct usb_ep                   *ep0;
@@ -1029,6 +1032,10 @@ extern void usb_gadget_udc_reset(struct usb_gadget *gadget,
 extern void usb_gadget_giveback_request(struct usb_ep *ep,
                struct usb_request *req);
 
+/*-------------------------------------------------------------------------*/
+
+/* 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 b0a39243295a326665de913b38b6857c209e7a19..7dbecf9a46561f5de2e9904b3b52c31424fb66b1 100644 (file)
@@ -117,8 +117,6 @@ struct msm_otg_platform_data {
        enum otg_control_type otg_control;
        enum msm_usb_phy_type phy_type;
        void (*setup_gpio)(enum usb_otg_state state);
-       int (*link_clk_reset)(struct clk *link_clk, bool assert);
-       int (*phy_clk_reset)(struct clk *phy_clk);
 };
 
 /**
@@ -128,7 +126,6 @@ struct msm_otg_platform_data {
  * @irq: IRQ number assigned for HSUSB controller.
  * @clk: clock struct of usb_hs_clk.
  * @pclk: clock struct of usb_hs_pclk.
- * @phy_reset_clk: clock struct of usb_phy_clk.
  * @core_clk: clock struct of usb_hs_core_clk.
  * @regs: ioremapped register base address.
  * @inputs: OTG state machine inputs(Id, SessValid etc).
@@ -148,7 +145,6 @@ struct msm_otg {
        int irq;
        struct clk *clk;
        struct clk *pclk;
-       struct clk *phy_reset_clk;
        struct clk *core_clk;
        void __iomem *regs;
 #define ID             0
index b6ba1bfb86f2aa7cfb348bc2e704e48c34796b1b..f728f1854829e01c99663ded8f50973b3e311c80 100644 (file)
@@ -53,6 +53,8 @@ enum otg_fsm_timer {
        B_SE0_SRP,
        B_SRP_FAIL,
        A_WAIT_ENUM,
+       B_DATA_PLS,
+       B_SSEND_SRP,
 
        NUM_OTG_FSM_TIMERS,
 };
index 9fd9e481ea982e7ac08d4d0e5243e2239a7b37a1..f06529c1414102948dcd23ead492feff2f0eb9b4 100644 (file)
@@ -165,6 +165,8 @@ struct renesas_usbhs_driver_param {
         */
        u32 has_otg:1; /* for controlling PWEN/EXTLP */
        u32 has_sudmac:1; /* for SUDMAC */
+       u32 has_usb_dmac:1; /* for USB-DMAC */
+#define USBHS_USB_DMAC_XFER_SIZE       32      /* hardcode the xfer size */
 };
 
 #define USBHS_TYPE_R8A7790 1
index ba82f03d8287f7b5ef2c09a4ddfcf995860d7935..02112299a1d3d3907fc9810efad7bad1ccc0e8a5 100644 (file)
@@ -87,8 +87,6 @@ struct umc_driver {
 
        int  (*probe)(struct umc_dev *);
        void (*remove)(struct umc_dev *);
-       int  (*suspend)(struct umc_dev *, pm_message_t state);
-       int  (*resume)(struct umc_dev *);
        int  (*pre_reset)(struct umc_dev *);
        int  (*post_reset)(struct umc_dev *);
 
index 2d67b8998fd8b49d877d65b0b94a022be47d4e28..ddb44097538245f17e882efff635143ada49e089 100644 (file)
@@ -14,6 +14,8 @@
 
 #include <linux/iommu.h>
 #include <linux/mm.h>
+#include <linux/workqueue.h>
+#include <linux/poll.h>
 #include <uapi/linux/vfio.h>
 
 /**
@@ -78,19 +80,6 @@ extern int vfio_register_iommu_driver(const struct vfio_iommu_driver_ops *ops);
 extern void vfio_unregister_iommu_driver(
                                const struct vfio_iommu_driver_ops *ops);
 
-/**
- * offsetofend(TYPE, MEMBER)
- *
- * @TYPE: The type of the structure
- * @MEMBER: The member within the structure to get the end offset of
- *
- * Simple helper macro for dealing with variable sized structures passed
- * from user space.  This allows us to easily determine if the provided
- * structure is sized to include various fields.
- */
-#define offsetofend(TYPE, MEMBER) \
-       (offsetof(TYPE, MEMBER) + sizeof(((TYPE *)0)->MEMBER))
-
 /*
  * External user API
  */
@@ -123,4 +112,27 @@ static inline long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group,
        return -ENOTTY;
 }
 #endif /* CONFIG_EEH */
+
+/*
+ * IRQfd - generic
+ */
+struct virqfd {
+       void                    *opaque;
+       struct eventfd_ctx      *eventfd;
+       int                     (*handler)(void *, void *);
+       void                    (*thread)(void *, void *);
+       void                    *data;
+       struct work_struct      inject;
+       wait_queue_t            wait;
+       poll_table              pt;
+       struct work_struct      shutdown;
+       struct virqfd           **pvirqfd;
+};
+
+extern int vfio_virqfd_enable(void *opaque,
+                             int (*handler)(void *, void *),
+                             void (*thread)(void *, void *),
+                             void *data, struct virqfd **pvirqfd, int fd);
+extern void vfio_virqfd_disable(struct virqfd **pvirqfd);
+
 #endif /* VFIO_H */
index c37bd4d06739034cf9592305a152f9ed6eb35db3..8c3b412d84df38e37465e841996eee50ecfc50b7 100644 (file)
@@ -65,8 +65,13 @@ struct pci_dev;
  *     out of the arbitration process (and can be safe to take
  *     interrupts at any time.
  */
+#if defined(CONFIG_VGA_ARB)
 extern void vga_set_legacy_decoding(struct pci_dev *pdev,
                                    unsigned int decodes);
+#else
+static inline void vga_set_legacy_decoding(struct pci_dev *pdev,
+                                          unsigned int decodes) { };
+#endif
 
 /**
  *     vga_get         - acquire & locks VGA resources
index 8cd6f19ca518c254a1911b2aa0e1c36dc05951df..79242e9c06b8cdcc11a2742d7280a15b81c80f6b 100644 (file)
@@ -137,6 +137,7 @@ ssize_t vme_master_read(struct vme_resource *, void *, size_t, loff_t);
 ssize_t vme_master_write(struct vme_resource *, void *, size_t, loff_t);
 unsigned int vme_master_rmw(struct vme_resource *, unsigned int, unsigned int,
        unsigned int, loff_t);
+int vme_master_mmap(struct vme_resource *resource, struct vm_area_struct *vma);
 void vme_master_free(struct vme_resource *);
 
 struct vme_resource *vme_dma_request(struct vme_dev *, u32);
index 395b70e0eccf76e0cd31dc1e25afb5d3032fab50..a746bf5216f896c82e191b90078d7ffa92aaadf4 100644 (file)
@@ -137,4 +137,12 @@ extern int watchdog_init_timeout(struct watchdog_device *wdd,
 extern int watchdog_register_device(struct watchdog_device *);
 extern void watchdog_unregister_device(struct watchdog_device *);
 
+#ifdef CONFIG_HARDLOCKUP_DETECTOR
+void watchdog_nmi_disable_all(void);
+void watchdog_nmi_enable_all(void);
+#else
+static inline void watchdog_nmi_disable_all(void) {}
+static inline void watchdog_nmi_enable_all(void) {}
+#endif
+
 #endif  /* ifndef _LINUX_WATCHDOG_H */
index f597846ff605cccaaf36d3cc4e6d603b630af156..deee212af8e0939a6d97189569cf8199fb840124 100644 (file)
@@ -454,6 +454,7 @@ extern bool workqueue_congested(int cpu, struct workqueue_struct *wq);
 extern unsigned int work_busy(struct work_struct *work);
 extern __printf(1, 2) void set_worker_desc(const char *fmt, ...);
 extern void print_worker_info(const char *log_lvl, struct task_struct *task);
+extern void show_workqueue_state(void);
 
 /**
  * queue_work - queue work on a workqueue
index c2e570336269b8e2e3c574c607afc651d8f1a6eb..6008b0985b7b18a5e15c157a487ccfb6b640b312 100644 (file)
 #define                ISI_CFG1_FRATE_DIV_MASK         (7 << 8)
 #define ISI_CFG1_DISCR                         (1 << 11)
 #define ISI_CFG1_FULL_MODE                     (1 << 12)
+/* Definition for THMASK(ISI_V2) */
+#define                ISI_CFG1_THMASK_BEATS_4         (0 << 13)
+#define                ISI_CFG1_THMASK_BEATS_8         (1 << 13)
+#define                ISI_CFG1_THMASK_BEATS_16        (2 << 13)
 
 /* Bitfields in CFG2 */
 #define ISI_CFG2_GRAYSCALE                     (1 << 13)
index e4079c28e6b8588da92a8826d63e07195859a33b..81c81ead9a35c1bd78c6493fe9abc8b33bb85300 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/page_counter.h>
 #include <linux/memcontrol.h>
 #include <linux/static_key.h>
-#include <linux/aio.h>
 #include <linux/sched.h>
 
 #include <linux/filter.h>
index 1e1421b06565ca750b4326683f78a0e8ae276a1e..5a4bb5bb66b3b9e5a7411082178665e4198a2972 100644 (file)
@@ -59,6 +59,7 @@ 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 a0666362c111ae1b597ebda14973826f29f33e75..633ee9ee97782210e74618a89e3187f41920b48e 100644 (file)
@@ -6,76 +6,95 @@
 
 #include <linux/tracepoint.h>
 
+#define P9_MSG_T                                                       \
+               EM( P9_TLERROR,         "P9_TLERROR" )                  \
+               EM( P9_RLERROR,         "P9_RLERROR" )                  \
+               EM( P9_TSTATFS,         "P9_TSTATFS" )                  \
+               EM( P9_RSTATFS,         "P9_RSTATFS" )                  \
+               EM( P9_TLOPEN,          "P9_TLOPEN" )                   \
+               EM( P9_RLOPEN,          "P9_RLOPEN" )                   \
+               EM( P9_TLCREATE,        "P9_TLCREATE" )                 \
+               EM( P9_RLCREATE,        "P9_RLCREATE" )                 \
+               EM( P9_TSYMLINK,        "P9_TSYMLINK" )                 \
+               EM( P9_RSYMLINK,        "P9_RSYMLINK" )                 \
+               EM( P9_TMKNOD,          "P9_TMKNOD" )                   \
+               EM( P9_RMKNOD,          "P9_RMKNOD" )                   \
+               EM( P9_TRENAME,         "P9_TRENAME" )                  \
+               EM( P9_RRENAME,         "P9_RRENAME" )                  \
+               EM( P9_TREADLINK,       "P9_TREADLINK" )                \
+               EM( P9_RREADLINK,       "P9_RREADLINK" )                \
+               EM( P9_TGETATTR,        "P9_TGETATTR" )                 \
+               EM( P9_RGETATTR,        "P9_RGETATTR" )                 \
+               EM( P9_TSETATTR,        "P9_TSETATTR" )                 \
+               EM( P9_RSETATTR,        "P9_RSETATTR" )                 \
+               EM( P9_TXATTRWALK,      "P9_TXATTRWALK" )               \
+               EM( P9_RXATTRWALK,      "P9_RXATTRWALK" )               \
+               EM( P9_TXATTRCREATE,    "P9_TXATTRCREATE" )             \
+               EM( P9_RXATTRCREATE,    "P9_RXATTRCREATE" )             \
+               EM( P9_TREADDIR,        "P9_TREADDIR" )                 \
+               EM( P9_RREADDIR,        "P9_RREADDIR" )                 \
+               EM( P9_TFSYNC,          "P9_TFSYNC" )                   \
+               EM( P9_RFSYNC,          "P9_RFSYNC" )                   \
+               EM( P9_TLOCK,           "P9_TLOCK" )                    \
+               EM( P9_RLOCK,           "P9_RLOCK" )                    \
+               EM( P9_TGETLOCK,        "P9_TGETLOCK" )                 \
+               EM( P9_RGETLOCK,        "P9_RGETLOCK" )                 \
+               EM( P9_TLINK,           "P9_TLINK" )                    \
+               EM( P9_RLINK,           "P9_RLINK" )                    \
+               EM( P9_TMKDIR,          "P9_TMKDIR" )                   \
+               EM( P9_RMKDIR,          "P9_RMKDIR" )                   \
+               EM( P9_TRENAMEAT,       "P9_TRENAMEAT" )                \
+               EM( P9_RRENAMEAT,       "P9_RRENAMEAT" )                \
+               EM( P9_TUNLINKAT,       "P9_TUNLINKAT" )                \
+               EM( P9_RUNLINKAT,       "P9_RUNLINKAT" )                \
+               EM( P9_TVERSION,        "P9_TVERSION" )                 \
+               EM( P9_RVERSION,        "P9_RVERSION" )                 \
+               EM( P9_TAUTH,           "P9_TAUTH" )                    \
+               EM( P9_RAUTH,           "P9_RAUTH" )                    \
+               EM( P9_TATTACH,         "P9_TATTACH" )                  \
+               EM( P9_RATTACH,         "P9_RATTACH" )                  \
+               EM( P9_TERROR,          "P9_TERROR" )                   \
+               EM( P9_RERROR,          "P9_RERROR" )                   \
+               EM( P9_TFLUSH,          "P9_TFLUSH" )                   \
+               EM( P9_RFLUSH,          "P9_RFLUSH" )                   \
+               EM( P9_TWALK,           "P9_TWALK" )                    \
+               EM( P9_RWALK,           "P9_RWALK" )                    \
+               EM( P9_TOPEN,           "P9_TOPEN" )                    \
+               EM( P9_ROPEN,           "P9_ROPEN" )                    \
+               EM( P9_TCREATE,         "P9_TCREATE" )                  \
+               EM( P9_RCREATE,         "P9_RCREATE" )                  \
+               EM( P9_TREAD,           "P9_TREAD" )                    \
+               EM( P9_RREAD,           "P9_RREAD" )                    \
+               EM( P9_TWRITE,          "P9_TWRITE" )                   \
+               EM( P9_RWRITE,          "P9_RWRITE" )                   \
+               EM( P9_TCLUNK,          "P9_TCLUNK" )                   \
+               EM( P9_RCLUNK,          "P9_RCLUNK" )                   \
+               EM( P9_TREMOVE,         "P9_TREMOVE" )                  \
+               EM( P9_RREMOVE,         "P9_RREMOVE" )                  \
+               EM( P9_TSTAT,           "P9_TSTAT" )                    \
+               EM( P9_RSTAT,           "P9_RSTAT" )                    \
+               EM( P9_TWSTAT,          "P9_TWSTAT" )                   \
+               EMe(P9_RWSTAT,          "P9_RWSTAT" )
+
+/* Define EM() to export the enums to userspace via TRACE_DEFINE_ENUM() */
+#undef EM
+#undef EMe
+#define EM(a, b)       TRACE_DEFINE_ENUM(a);
+#define EMe(a, b)      TRACE_DEFINE_ENUM(a);
+
+P9_MSG_T
+
+/*
+ * Now redefine the EM() and EMe() macros to map the enums to the strings
+ * that will be printed in the output.
+ */
+#undef EM
+#undef EMe
+#define EM(a, b)       { a, b },
+#define EMe(a, b)      { a, b }
+
 #define show_9p_op(type)                                               \
-       __print_symbolic(type,                                          \
-                        { P9_TLERROR,          "P9_TLERROR" },         \
-                        { P9_RLERROR,          "P9_RLERROR" },         \
-                        { P9_TSTATFS,          "P9_TSTATFS" },         \
-                        { P9_RSTATFS,          "P9_RSTATFS" },         \
-                        { P9_TLOPEN,           "P9_TLOPEN" },          \
-                        { P9_RLOPEN,           "P9_RLOPEN" },          \
-                        { P9_TLCREATE,         "P9_TLCREATE" },        \
-                        { P9_RLCREATE,         "P9_RLCREATE" },        \
-                        { P9_TSYMLINK,         "P9_TSYMLINK" },        \
-                        { P9_RSYMLINK,         "P9_RSYMLINK" },        \
-                        { P9_TMKNOD,           "P9_TMKNOD" },          \
-                        { P9_RMKNOD,           "P9_RMKNOD" },          \
-                        { P9_TRENAME,          "P9_TRENAME" },         \
-                        { P9_RRENAME,          "P9_RRENAME" },         \
-                        { P9_TREADLINK,        "P9_TREADLINK" },       \
-                        { P9_RREADLINK,        "P9_RREADLINK" },       \
-                        { P9_TGETATTR,         "P9_TGETATTR" },        \
-                        { P9_RGETATTR,         "P9_RGETATTR" },        \
-                        { P9_TSETATTR,         "P9_TSETATTR" },        \
-                        { P9_RSETATTR,         "P9_RSETATTR" },        \
-                        { P9_TXATTRWALK,       "P9_TXATTRWALK" },      \
-                        { P9_RXATTRWALK,       "P9_RXATTRWALK" },      \
-                        { P9_TXATTRCREATE,     "P9_TXATTRCREATE" },    \
-                        { P9_RXATTRCREATE,     "P9_RXATTRCREATE" },    \
-                        { P9_TREADDIR,         "P9_TREADDIR" },        \
-                        { P9_RREADDIR,         "P9_RREADDIR" },        \
-                        { P9_TFSYNC,           "P9_TFSYNC" },          \
-                        { P9_RFSYNC,           "P9_RFSYNC" },          \
-                        { P9_TLOCK,            "P9_TLOCK" },           \
-                        { P9_RLOCK,            "P9_RLOCK" },           \
-                        { P9_TGETLOCK,         "P9_TGETLOCK" },        \
-                        { P9_RGETLOCK,         "P9_RGETLOCK" },        \
-                        { P9_TLINK,            "P9_TLINK" },           \
-                        { P9_RLINK,            "P9_RLINK" },           \
-                        { P9_TMKDIR,           "P9_TMKDIR" },          \
-                        { P9_RMKDIR,           "P9_RMKDIR" },          \
-                        { P9_TRENAMEAT,        "P9_TRENAMEAT" },       \
-                        { P9_RRENAMEAT,        "P9_RRENAMEAT" },       \
-                        { P9_TUNLINKAT,        "P9_TUNLINKAT" },       \
-                        { P9_RUNLINKAT,        "P9_RUNLINKAT" },       \
-                        { P9_TVERSION,         "P9_TVERSION" },        \
-                        { P9_RVERSION,         "P9_RVERSION" },        \
-                        { P9_TAUTH,            "P9_TAUTH" },           \
-                        { P9_RAUTH,            "P9_RAUTH" },           \
-                        { P9_TATTACH,          "P9_TATTACH" },         \
-                        { P9_RATTACH,          "P9_RATTACH" },         \
-                        { P9_TERROR,           "P9_TERROR" },          \
-                        { P9_RERROR,           "P9_RERROR" },          \
-                        { P9_TFLUSH,           "P9_TFLUSH" },          \
-                        { P9_RFLUSH,           "P9_RFLUSH" },          \
-                        { P9_TWALK,            "P9_TWALK" },           \
-                        { P9_RWALK,            "P9_RWALK" },           \
-                        { P9_TOPEN,            "P9_TOPEN" },           \
-                        { P9_ROPEN,            "P9_ROPEN" },           \
-                        { P9_TCREATE,          "P9_TCREATE" },         \
-                        { P9_RCREATE,          "P9_RCREATE" },         \
-                        { P9_TREAD,            "P9_TREAD" },           \
-                        { P9_RREAD,            "P9_RREAD" },           \
-                        { P9_TWRITE,           "P9_TWRITE" },          \
-                        { P9_RWRITE,           "P9_RWRITE" },          \
-                        { P9_TCLUNK,           "P9_TCLUNK" },          \
-                        { P9_RCLUNK,           "P9_RCLUNK" },          \
-                        { P9_TREMOVE,          "P9_TREMOVE" },         \
-                        { P9_RREMOVE,          "P9_RREMOVE" },         \
-                        { P9_TSTAT,            "P9_TSTAT" },           \
-                        { P9_RSTAT,            "P9_RSTAT" },           \
-                        { P9_TWSTAT,           "P9_TWSTAT" },          \
-                        { P9_RWSTAT,           "P9_RWSTAT" })
+       __print_symbolic(type, P9_MSG_T)
 
 TRACE_EVENT(9p_client_req,
            TP_PROTO(struct p9_client *clnt, int8_t type, int tag),
index 1faecea101f3e85a84c247ec997af8216de2523d..572e6503394a4c77bbfadfe1ce33bca134600724 100644 (file)
@@ -962,7 +962,7 @@ TRACE_EVENT(alloc_extent_state,
                __entry->ip     = IP
        ),
 
-       TP_printk("state=%p; mask = %s; caller = %pF", __entry->state,
+       TP_printk("state=%p; mask = %s; caller = %pS", __entry->state,
                  show_gfp_flags(__entry->mask), (void *)__entry->ip)
 );
 
@@ -982,7 +982,7 @@ TRACE_EVENT(free_extent_state,
                __entry->ip = IP
        ),
 
-       TP_printk(" state=%p; caller = %pF", __entry->state,
+       TP_printk(" state=%p; caller = %pS", __entry->state,
                  (void *)__entry->ip)
 );
 
index 6797b9de90edeac929c5c234558434cc16d1d877..7f20707849bbaa76a75f18c9fd99ea78314af249 100644 (file)
@@ -144,7 +144,7 @@ TRACE_EVENT(ext3_mark_inode_dirty,
                __entry->ip     = IP;
        ),
 
-       TP_printk("dev %d,%d ino %lu caller %pF",
+       TP_printk("dev %d,%d ino %lu caller %pS",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino, (void *)__entry->ip)
 );
index 6e5abd6d38a2b7839aca39f961df6818b9330e42..47fca36ee426abb4cf359ceb47a3741fd9ba1393 100644 (file)
@@ -240,7 +240,7 @@ TRACE_EVENT(ext4_mark_inode_dirty,
                __entry->ip     = IP;
        ),
 
-       TP_printk("dev %d,%d ino %lu caller %pF",
+       TP_printk("dev %d,%d ino %lu caller %pS",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino, (void *)__entry->ip)
 );
@@ -1762,7 +1762,7 @@ TRACE_EVENT(ext4_journal_start,
                __entry->rsv_blocks      = rsv_blocks;
        ),
 
-       TP_printk("dev %d,%d blocks, %d rsv_blocks, %d caller %pF",
+       TP_printk("dev %d,%d blocks, %d rsv_blocks, %d caller %pS",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->blocks, __entry->rsv_blocks, (void *)__entry->ip)
 );
@@ -1784,7 +1784,7 @@ TRACE_EVENT(ext4_journal_start_reserved,
                __entry->blocks          = blocks;
        ),
 
-       TP_printk("dev %d,%d blocks, %d caller %pF",
+       TP_printk("dev %d,%d blocks, %d caller %pS",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->blocks, (void *)__entry->ip)
 );
index 5422dbfaf97d651798c6fec1bace15cc3ea31fff..36f4536b6149054bd547223a44fe81c073baad91 100644 (file)
@@ -9,6 +9,36 @@
 #define show_dev(entry)                MAJOR(entry->dev), MINOR(entry->dev)
 #define show_dev_ino(entry)    show_dev(entry), (unsigned long)entry->ino
 
+TRACE_DEFINE_ENUM(NODE);
+TRACE_DEFINE_ENUM(DATA);
+TRACE_DEFINE_ENUM(META);
+TRACE_DEFINE_ENUM(META_FLUSH);
+TRACE_DEFINE_ENUM(CURSEG_HOT_DATA);
+TRACE_DEFINE_ENUM(CURSEG_WARM_DATA);
+TRACE_DEFINE_ENUM(CURSEG_COLD_DATA);
+TRACE_DEFINE_ENUM(CURSEG_HOT_NODE);
+TRACE_DEFINE_ENUM(CURSEG_WARM_NODE);
+TRACE_DEFINE_ENUM(CURSEG_COLD_NODE);
+TRACE_DEFINE_ENUM(NO_CHECK_TYPE);
+TRACE_DEFINE_ENUM(GC_GREEDY);
+TRACE_DEFINE_ENUM(GC_CB);
+TRACE_DEFINE_ENUM(FG_GC);
+TRACE_DEFINE_ENUM(BG_GC);
+TRACE_DEFINE_ENUM(LFS);
+TRACE_DEFINE_ENUM(SSR);
+TRACE_DEFINE_ENUM(__REQ_RAHEAD);
+TRACE_DEFINE_ENUM(__REQ_WRITE);
+TRACE_DEFINE_ENUM(__REQ_SYNC);
+TRACE_DEFINE_ENUM(__REQ_NOIDLE);
+TRACE_DEFINE_ENUM(__REQ_FLUSH);
+TRACE_DEFINE_ENUM(__REQ_FUA);
+TRACE_DEFINE_ENUM(__REQ_PRIO);
+TRACE_DEFINE_ENUM(__REQ_META);
+TRACE_DEFINE_ENUM(CP_UMOUNT);
+TRACE_DEFINE_ENUM(CP_FASTBOOT);
+TRACE_DEFINE_ENUM(CP_SYNC);
+TRACE_DEFINE_ENUM(CP_DISCARD);
+
 #define show_block_type(type)                                          \
        __print_symbolic(type,                                          \
                { NODE,         "NODE" },                               \
index 76c72d3f190297e3c2aa50975cee0cda4bf231f7..edc24e6dea1bab8341b82cf27d42df57e55d29b5 100644 (file)
@@ -1,6 +1,13 @@
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM intel-sst
 
+/*
+ * The TRACE_SYSTEM_VAR defaults to TRACE_SYSTEM, but must be a
+ * legitimate C variable. It is not exported to user space.
+ */
+#undef TRACE_SYSTEM_VAR
+#define TRACE_SYSTEM_VAR intel_sst
+
 #if !defined(_TRACE_INTEL_SST_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_INTEL_SST_H
 
index 3608bebd3d9c5e58a0349c6240a8670bd3d8bbfb..ff8f6c091a1504e3d18937244a07b6432c880fb2 100644 (file)
@@ -9,19 +9,34 @@
 struct irqaction;
 struct softirq_action;
 
-#define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
+#define SOFTIRQ_NAME_LIST                              \
+                        softirq_name(HI)               \
+                        softirq_name(TIMER)            \
+                        softirq_name(NET_TX)           \
+                        softirq_name(NET_RX)           \
+                        softirq_name(BLOCK)            \
+                        softirq_name(BLOCK_IOPOLL)     \
+                        softirq_name(TASKLET)          \
+                        softirq_name(SCHED)            \
+                        softirq_name(HRTIMER)          \
+                        softirq_name_end(RCU)
+
+#undef softirq_name
+#undef softirq_name_end
+
+#define softirq_name(sirq) TRACE_DEFINE_ENUM(sirq##_SOFTIRQ);
+#define softirq_name_end(sirq)  TRACE_DEFINE_ENUM(sirq##_SOFTIRQ);
+
+SOFTIRQ_NAME_LIST
+
+#undef softirq_name
+#undef softirq_name_end
+
+#define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq },
+#define softirq_name_end(sirq) { sirq##_SOFTIRQ, #sirq }
+
 #define show_softirq_name(val)                         \
-       __print_symbolic(val,                           \
-                        softirq_name(HI),              \
-                        softirq_name(TIMER),           \
-                        softirq_name(NET_TX),          \
-                        softirq_name(NET_RX),          \
-                        softirq_name(BLOCK),           \
-                        softirq_name(BLOCK_IOPOLL),    \
-                        softirq_name(TASKLET),         \
-                        softirq_name(SCHED),           \
-                        softirq_name(HRTIMER),         \
-                        softirq_name(RCU))
+       __print_symbolic(val, SOFTIRQ_NAME_LIST)
 
 /**
  * irq_handler_entry - called immediately before the irq action handler
diff --git a/include/trace/events/libata.h b/include/trace/events/libata.h
new file mode 100644 (file)
index 0000000..8b0fbd9
--- /dev/null
@@ -0,0 +1,325 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM libata
+
+#if !defined(_TRACE_LIBATA_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_LIBATA_H
+
+#include <linux/ata.h>
+#include <linux/libata.h>
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+#define ata_opcode_name(opcode)        { opcode, #opcode }
+#define show_opcode_name(val)                                  \
+       __print_symbolic(val,                                   \
+                ata_opcode_name(ATA_CMD_DEV_RESET),            \
+                ata_opcode_name(ATA_CMD_CHK_POWER),            \
+                ata_opcode_name(ATA_CMD_STANDBY),              \
+                ata_opcode_name(ATA_CMD_IDLE),                 \
+                ata_opcode_name(ATA_CMD_EDD),                  \
+                ata_opcode_name(ATA_CMD_DOWNLOAD_MICRO),       \
+                ata_opcode_name(ATA_CMD_DOWNLOAD_MICRO_DMA),   \
+                ata_opcode_name(ATA_CMD_NOP),                  \
+                ata_opcode_name(ATA_CMD_FLUSH),                \
+                ata_opcode_name(ATA_CMD_FLUSH_EXT),            \
+                ata_opcode_name(ATA_CMD_ID_ATA),               \
+                ata_opcode_name(ATA_CMD_ID_ATAPI),             \
+                ata_opcode_name(ATA_CMD_SERVICE),              \
+                ata_opcode_name(ATA_CMD_READ),                 \
+                ata_opcode_name(ATA_CMD_READ_EXT),             \
+                ata_opcode_name(ATA_CMD_READ_QUEUED),          \
+                ata_opcode_name(ATA_CMD_READ_STREAM_EXT),      \
+                ata_opcode_name(ATA_CMD_READ_STREAM_DMA_EXT),  \
+                ata_opcode_name(ATA_CMD_WRITE),                \
+                ata_opcode_name(ATA_CMD_WRITE_EXT),            \
+                ata_opcode_name(ATA_CMD_WRITE_QUEUED),         \
+                ata_opcode_name(ATA_CMD_WRITE_STREAM_EXT),     \
+                ata_opcode_name(ATA_CMD_WRITE_STREAM_DMA_EXT), \
+                ata_opcode_name(ATA_CMD_WRITE_FUA_EXT),        \
+                ata_opcode_name(ATA_CMD_WRITE_QUEUED_FUA_EXT), \
+                ata_opcode_name(ATA_CMD_FPDMA_READ),           \
+                ata_opcode_name(ATA_CMD_FPDMA_WRITE),          \
+                ata_opcode_name(ATA_CMD_FPDMA_SEND),           \
+                ata_opcode_name(ATA_CMD_FPDMA_RECV),           \
+                ata_opcode_name(ATA_CMD_PIO_READ),             \
+                ata_opcode_name(ATA_CMD_PIO_READ_EXT),         \
+                ata_opcode_name(ATA_CMD_PIO_WRITE),            \
+                ata_opcode_name(ATA_CMD_PIO_WRITE_EXT),        \
+                ata_opcode_name(ATA_CMD_READ_MULTI),           \
+                ata_opcode_name(ATA_CMD_READ_MULTI_EXT),       \
+                ata_opcode_name(ATA_CMD_WRITE_MULTI),          \
+                ata_opcode_name(ATA_CMD_WRITE_MULTI_EXT),      \
+                ata_opcode_name(ATA_CMD_WRITE_MULTI_FUA_EXT),  \
+                ata_opcode_name(ATA_CMD_SET_FEATURES),         \
+                ata_opcode_name(ATA_CMD_SET_MULTI),            \
+                ata_opcode_name(ATA_CMD_PACKET),               \
+                ata_opcode_name(ATA_CMD_VERIFY),               \
+                ata_opcode_name(ATA_CMD_VERIFY_EXT),           \
+                ata_opcode_name(ATA_CMD_WRITE_UNCORR_EXT),     \
+                ata_opcode_name(ATA_CMD_STANDBYNOW1),          \
+                ata_opcode_name(ATA_CMD_IDLEIMMEDIATE),        \
+                ata_opcode_name(ATA_CMD_SLEEP),                \
+                ata_opcode_name(ATA_CMD_INIT_DEV_PARAMS),      \
+                ata_opcode_name(ATA_CMD_READ_NATIVE_MAX),      \
+                ata_opcode_name(ATA_CMD_READ_NATIVE_MAX_EXT),  \
+                ata_opcode_name(ATA_CMD_SET_MAX),              \
+                ata_opcode_name(ATA_CMD_SET_MAX_EXT),          \
+                ata_opcode_name(ATA_CMD_READ_LOG_EXT),         \
+                ata_opcode_name(ATA_CMD_WRITE_LOG_EXT),        \
+                ata_opcode_name(ATA_CMD_READ_LOG_DMA_EXT),     \
+                ata_opcode_name(ATA_CMD_WRITE_LOG_DMA_EXT),    \
+                ata_opcode_name(ATA_CMD_TRUSTED_NONDATA),      \
+                ata_opcode_name(ATA_CMD_TRUSTED_RCV),          \
+                ata_opcode_name(ATA_CMD_TRUSTED_RCV_DMA),      \
+                ata_opcode_name(ATA_CMD_TRUSTED_SND),          \
+                ata_opcode_name(ATA_CMD_TRUSTED_SND_DMA),      \
+                ata_opcode_name(ATA_CMD_PMP_READ),             \
+                ata_opcode_name(ATA_CMD_PMP_READ_DMA),         \
+                ata_opcode_name(ATA_CMD_PMP_WRITE),            \
+                ata_opcode_name(ATA_CMD_PMP_WRITE_DMA),        \
+                ata_opcode_name(ATA_CMD_CONF_OVERLAY),         \
+                ata_opcode_name(ATA_CMD_SEC_SET_PASS),         \
+                ata_opcode_name(ATA_CMD_SEC_UNLOCK),           \
+                ata_opcode_name(ATA_CMD_SEC_ERASE_PREP),       \
+                ata_opcode_name(ATA_CMD_SEC_ERASE_UNIT),       \
+                ata_opcode_name(ATA_CMD_SEC_FREEZE_LOCK),      \
+                ata_opcode_name(ATA_CMD_SEC_DISABLE_PASS),     \
+                ata_opcode_name(ATA_CMD_CONFIG_STREAM),        \
+                ata_opcode_name(ATA_CMD_SMART),                \
+                ata_opcode_name(ATA_CMD_MEDIA_LOCK),           \
+                ata_opcode_name(ATA_CMD_MEDIA_UNLOCK),         \
+                ata_opcode_name(ATA_CMD_DSM),                  \
+                ata_opcode_name(ATA_CMD_CHK_MED_CRD_TYP),      \
+                ata_opcode_name(ATA_CMD_CFA_REQ_EXT_ERR),      \
+                ata_opcode_name(ATA_CMD_CFA_WRITE_NE),         \
+                ata_opcode_name(ATA_CMD_CFA_TRANS_SECT),       \
+                ata_opcode_name(ATA_CMD_CFA_ERASE),            \
+                ata_opcode_name(ATA_CMD_CFA_WRITE_MULT_NE),    \
+                ata_opcode_name(ATA_CMD_REQ_SENSE_DATA),       \
+                ata_opcode_name(ATA_CMD_SANITIZE_DEVICE),      \
+                ata_opcode_name(ATA_CMD_RESTORE),              \
+                ata_opcode_name(ATA_CMD_READ_LONG),            \
+                ata_opcode_name(ATA_CMD_READ_LONG_ONCE),       \
+                ata_opcode_name(ATA_CMD_WRITE_LONG),           \
+                ata_opcode_name(ATA_CMD_WRITE_LONG_ONCE))
+
+#define ata_error_name(result) { result, #result }
+#define show_error_name(val)                           \
+       __print_symbolic(val,                           \
+               ata_error_name(ATA_ICRC),               \
+               ata_error_name(ATA_UNC),                \
+               ata_error_name(ATA_MC),                 \
+               ata_error_name(ATA_IDNF),               \
+               ata_error_name(ATA_MCR),                \
+               ata_error_name(ATA_ABORTED),            \
+               ata_error_name(ATA_TRK0NF),             \
+               ata_error_name(ATA_AMNF))
+
+#define ata_protocol_name(proto)       { proto, #proto }
+#define show_protocol_name(val)                                \
+       __print_symbolic(val,                           \
+               ata_protocol_name(ATA_PROT_UNKNOWN),    \
+               ata_protocol_name(ATA_PROT_NODATA),     \
+               ata_protocol_name(ATA_PROT_PIO),        \
+               ata_protocol_name(ATA_PROT_DMA),        \
+               ata_protocol_name(ATA_PROT_NCQ),        \
+               ata_protocol_name(ATAPI_PROT_NODATA),   \
+               ata_protocol_name(ATAPI_PROT_PIO),      \
+               ata_protocol_name(ATAPI_PROT_DMA))
+
+const char *libata_trace_parse_status(struct trace_seq*, unsigned char);
+#define __parse_status(s) libata_trace_parse_status(p, s)
+
+const char *libata_trace_parse_eh_action(struct trace_seq *, unsigned int);
+#define __parse_eh_action(a) libata_trace_parse_eh_action(p, a)
+
+const char *libata_trace_parse_eh_err_mask(struct trace_seq *, unsigned int);
+#define __parse_eh_err_mask(m) libata_trace_parse_eh_err_mask(p, m)
+
+const char *libata_trace_parse_qc_flags(struct trace_seq *, unsigned int);
+#define __parse_qc_flags(f) libata_trace_parse_qc_flags(p, f)
+
+TRACE_EVENT(ata_qc_issue,
+
+       TP_PROTO(struct ata_queued_cmd *qc),
+
+       TP_ARGS(qc),
+
+       TP_STRUCT__entry(
+               __field( unsigned int,  ata_port )
+               __field( unsigned int,  ata_dev )
+               __field( unsigned int,  tag     )
+               __field( unsigned char, cmd     )
+               __field( unsigned char, dev     )
+               __field( unsigned char, lbal    )
+               __field( unsigned char, lbam    )
+               __field( unsigned char, lbah    )
+               __field( unsigned char, nsect   )
+               __field( unsigned char, feature )
+               __field( unsigned char, hob_lbal )
+               __field( unsigned char, hob_lbam )
+               __field( unsigned char, hob_lbah )
+               __field( unsigned char, hob_nsect )
+               __field( unsigned char, hob_feature )
+               __field( unsigned char, ctl )
+               __field( unsigned char, proto )
+               __field( unsigned long, flags )
+       ),
+
+       TP_fast_assign(
+               __entry->ata_port       = qc->ap->print_id;
+               __entry->ata_dev        = qc->dev->link->pmp + qc->dev->devno;
+               __entry->tag            = qc->tag;
+               __entry->proto          = qc->tf.protocol;
+               __entry->cmd            = qc->tf.command;
+               __entry->dev            = qc->tf.device;
+               __entry->lbal           = qc->tf.lbal;
+               __entry->lbam           = qc->tf.lbam;
+               __entry->lbah           = qc->tf.lbah;
+               __entry->hob_lbal       = qc->tf.hob_lbal;
+               __entry->hob_lbam       = qc->tf.hob_lbam;
+               __entry->hob_lbah       = qc->tf.hob_lbah;
+               __entry->feature        = qc->tf.feature;
+               __entry->hob_feature    = qc->tf.hob_feature;
+               __entry->nsect          = qc->tf.nsect;
+               __entry->hob_nsect      = qc->tf.hob_nsect;
+       ),
+
+       TP_printk("ata_port=%u ata_dev=%u tag=%d proto=%s cmd=%s " \
+                 " tf=(%02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x)",
+                 __entry->ata_port, __entry->ata_dev, __entry->tag,
+                 show_protocol_name(__entry->proto),
+                 show_opcode_name(__entry->cmd),
+                 __entry->cmd, __entry->feature, __entry->nsect,
+                 __entry->lbal, __entry->lbam, __entry->lbah,
+                 __entry->hob_feature, __entry->hob_nsect,
+                 __entry->hob_lbal, __entry->hob_lbam, __entry->hob_lbah,
+                 __entry->dev)
+);
+
+DECLARE_EVENT_CLASS(ata_qc_complete_template,
+
+       TP_PROTO(struct ata_queued_cmd *qc),
+
+       TP_ARGS(qc),
+
+       TP_STRUCT__entry(
+               __field( unsigned int,  ata_port )
+               __field( unsigned int,  ata_dev )
+               __field( unsigned int,  tag     )
+               __field( unsigned char, status  )
+               __field( unsigned char, dev     )
+               __field( unsigned char, lbal    )
+               __field( unsigned char, lbam    )
+               __field( unsigned char, lbah    )
+               __field( unsigned char, nsect   )
+               __field( unsigned char, error   )
+               __field( unsigned char, hob_lbal )
+               __field( unsigned char, hob_lbam )
+               __field( unsigned char, hob_lbah )
+               __field( unsigned char, hob_nsect )
+               __field( unsigned char, hob_feature )
+               __field( unsigned char, ctl )
+               __field( unsigned long, flags )
+       ),
+
+       TP_fast_assign(
+               __entry->ata_port       = qc->ap->print_id;
+               __entry->ata_dev        = qc->dev->link->pmp + qc->dev->devno;
+               __entry->tag            = qc->tag;
+               __entry->status         = qc->result_tf.command;
+               __entry->dev            = qc->result_tf.device;
+               __entry->lbal           = qc->result_tf.lbal;
+               __entry->lbam           = qc->result_tf.lbam;
+               __entry->lbah           = qc->result_tf.lbah;
+               __entry->hob_lbal       = qc->result_tf.hob_lbal;
+               __entry->hob_lbam       = qc->result_tf.hob_lbam;
+               __entry->hob_lbah       = qc->result_tf.hob_lbah;
+               __entry->error          = qc->result_tf.feature;
+               __entry->hob_feature    = qc->result_tf.hob_feature;
+               __entry->nsect          = qc->result_tf.nsect;
+               __entry->hob_nsect      = qc->result_tf.hob_nsect;
+       ),
+
+       TP_printk("ata_port=%u ata_dev=%u tag=%d flags=%s status=%s " \
+                 " res=(%02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x)",
+                 __entry->ata_port, __entry->ata_dev, __entry->tag,
+                 __parse_qc_flags(__entry->flags),
+                 __parse_status(__entry->status),
+                 __entry->status, __entry->error, __entry->nsect,
+                 __entry->lbal, __entry->lbam, __entry->lbah,
+                 __entry->hob_feature, __entry->hob_nsect,
+                 __entry->hob_lbal, __entry->hob_lbam, __entry->hob_lbah,
+                 __entry->dev)
+);
+
+DEFINE_EVENT(ata_qc_complete_template, ata_qc_complete_internal,
+            TP_PROTO(struct ata_queued_cmd *qc),
+            TP_ARGS(qc));
+
+DEFINE_EVENT(ata_qc_complete_template, ata_qc_complete_failed,
+            TP_PROTO(struct ata_queued_cmd *qc),
+            TP_ARGS(qc));
+
+DEFINE_EVENT(ata_qc_complete_template, ata_qc_complete_done,
+            TP_PROTO(struct ata_queued_cmd *qc),
+            TP_ARGS(qc));
+
+TRACE_EVENT(ata_eh_link_autopsy,
+
+       TP_PROTO(struct ata_device *dev, unsigned int eh_action, unsigned int eh_err_mask),
+
+       TP_ARGS(dev, eh_action, eh_err_mask),
+
+       TP_STRUCT__entry(
+               __field( unsigned int,  ata_port )
+               __field( unsigned int,  ata_dev )
+               __field( unsigned int,  eh_action )
+               __field( unsigned int,  eh_err_mask)
+       ),
+
+       TP_fast_assign(
+               __entry->ata_port       = dev->link->ap->print_id;
+               __entry->ata_dev        = dev->link->pmp + dev->devno;
+               __entry->eh_action      = eh_action;
+               __entry->eh_err_mask    = eh_err_mask;
+       ),
+
+       TP_printk("ata_port=%u ata_dev=%u eh_action=%s err_mask=%s",
+                 __entry->ata_port, __entry->ata_dev,
+                 __parse_eh_action(__entry->eh_action),
+                 __parse_eh_err_mask(__entry->eh_err_mask))
+);
+
+TRACE_EVENT(ata_eh_link_autopsy_qc,
+
+       TP_PROTO(struct ata_queued_cmd *qc),
+
+       TP_ARGS(qc),
+
+       TP_STRUCT__entry(
+               __field( unsigned int,  ata_port )
+               __field( unsigned int,  ata_dev )
+               __field( unsigned int,  tag     )
+               __field( unsigned int,  qc_flags )
+               __field( unsigned int,  eh_err_mask)
+       ),
+
+       TP_fast_assign(
+               __entry->ata_port       = qc->ap->print_id;
+               __entry->ata_dev        = qc->dev->link->pmp + qc->dev->devno;
+               __entry->tag            = qc->tag;
+               __entry->qc_flags       = qc->flags;
+               __entry->eh_err_mask    = qc->err_mask;
+       ),
+
+       TP_printk("ata_port=%u ata_dev=%u tag=%d flags=%s err_mask=%s",
+                 __entry->ata_port, __entry->ata_dev, __entry->tag,
+                 __parse_qc_flags(__entry->qc_flags),
+                 __parse_eh_err_mask(__entry->eh_err_mask))
+);
+
+#endif /*  _TRACE_LIBATA_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index dd2b5467d905816e72c22026f109e971bbef8724..539b25a76111fc644e1103d744c53ebf78a8fb17 100644 (file)
@@ -7,18 +7,40 @@
 #include <linux/tracepoint.h>
 
 #define MIGRATE_MODE                                           \
-       {MIGRATE_ASYNC,         "MIGRATE_ASYNC"},               \
-       {MIGRATE_SYNC_LIGHT,    "MIGRATE_SYNC_LIGHT"},          \
-       {MIGRATE_SYNC,          "MIGRATE_SYNC"}         
+       EM( MIGRATE_ASYNC,      "MIGRATE_ASYNC")                \
+       EM( MIGRATE_SYNC_LIGHT, "MIGRATE_SYNC_LIGHT")           \
+       EMe(MIGRATE_SYNC,       "MIGRATE_SYNC")
+
 
 #define MIGRATE_REASON                                         \
-       {MR_COMPACTION,         "compaction"},                  \
-       {MR_MEMORY_FAILURE,     "memory_failure"},              \
-       {MR_MEMORY_HOTPLUG,     "memory_hotplug"},              \
-       {MR_SYSCALL,            "syscall_or_cpuset"},           \
-       {MR_MEMPOLICY_MBIND,    "mempolicy_mbind"},             \
-       {MR_NUMA_MISPLACED,     "numa_misplaced"},              \
-       {MR_CMA,                "cma"}
+       EM( MR_COMPACTION,      "compaction")                   \
+       EM( MR_MEMORY_FAILURE,  "memory_failure")               \
+       EM( MR_MEMORY_HOTPLUG,  "memory_hotplug")               \
+       EM( MR_SYSCALL,         "syscall_or_cpuset")            \
+       EM( MR_MEMPOLICY_MBIND, "mempolicy_mbind")              \
+       EM( MR_NUMA_MISPLACED,  "numa_misplaced")               \
+       EMe(MR_CMA,             "cma")
+
+/*
+ * First define the enums in the above macros to be exported to userspace
+ * via TRACE_DEFINE_ENUM().
+ */
+#undef EM
+#undef EMe
+#define EM(a, b)       TRACE_DEFINE_ENUM(a);
+#define EMe(a, b)      TRACE_DEFINE_ENUM(a);
+
+MIGRATE_MODE
+MIGRATE_REASON
+
+/*
+ * Now redefine the EM() and EMe() macros to map the enums to the strings
+ * that will be printed in the output.
+ */
+#undef EM
+#undef EMe
+#define EM(a, b)       {a, b},
+#define EMe(a, b)      {a, b}
 
 TRACE_EVENT(mm_migrate_pages,
 
index 81c4c183d348b03793a2c9d6253846ce54ce4601..28c45997e451f4b2cbfcd3aabab15b3e41e13e45 100644 (file)
@@ -84,7 +84,7 @@ DECLARE_EVENT_CLASS(module_refcnt,
                __assign_str(name, mod->name);
        ),
 
-       TP_printk("%s call_site=%pf refcnt=%d",
+       TP_printk("%s call_site=%ps refcnt=%d",
                  __get_str(name), (void *)__entry->ip, __entry->refcnt)
 );
 
@@ -121,7 +121,7 @@ TRACE_EVENT(module_request,
                __assign_str(name, name);
        ),
 
-       TP_printk("%s wait=%d call_site=%pf",
+       TP_printk("%s wait=%d call_site=%ps",
                  __get_str(name), (int)__entry->wait, (void *)__entry->ip)
 );
 
index 805af6db41cc6091a877d8ddf58742cb2e3fce55..4684de344c5d96d7fb86260d37cadd3d7c76a1fe 100644 (file)
@@ -22,7 +22,7 @@ TRACE_EVENT(add_device_randomness,
                __entry->IP             = IP;
        ),
 
-       TP_printk("bytes %d caller %pF",
+       TP_printk("bytes %d caller %pS",
                __entry->bytes, (void *)__entry->IP)
 );
 
@@ -43,7 +43,7 @@ DECLARE_EVENT_CLASS(random__mix_pool_bytes,
                __entry->IP             = IP;
        ),
 
-       TP_printk("%s pool: bytes %d caller %pF",
+       TP_printk("%s pool: bytes %d caller %pS",
                  __entry->pool_name, __entry->bytes, (void *)__entry->IP)
 );
 
@@ -82,7 +82,7 @@ TRACE_EVENT(credit_entropy_bits,
        ),
 
        TP_printk("%s pool: bits %d entropy_count %d entropy_total %d "
-                 "caller %pF", __entry->pool_name, __entry->bits,
+                 "caller %pS", __entry->pool_name, __entry->bits,
                  __entry->entropy_count, __entry->entropy_total,
                  (void *)__entry->IP)
 );
@@ -207,7 +207,7 @@ DECLARE_EVENT_CLASS(random__get_random_bytes,
                __entry->IP             = IP;
        ),
 
-       TP_printk("nbytes %d caller %pF", __entry->nbytes, (void *)__entry->IP)
+       TP_printk("nbytes %d caller %pS", __entry->nbytes, (void *)__entry->IP)
 );
 
 DEFINE_EVENT(random__get_random_bytes, get_random_bytes,
@@ -242,7 +242,7 @@ DECLARE_EVENT_CLASS(random__extract_entropy,
                __entry->IP             = IP;
        ),
 
-       TP_printk("%s pool: nbytes %d entropy_count %d caller %pF",
+       TP_printk("%s pool: nbytes %d entropy_count %d caller %pS",
                  __entry->pool_name, __entry->nbytes, __entry->entropy_count,
                  (void *)__entry->IP)
 );
diff --git a/include/trace/events/regmap.h b/include/trace/events/regmap.h
deleted file mode 100644 (file)
index 22317d2..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM regmap
-
-#if !defined(_TRACE_REGMAP_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_REGMAP_H
-
-#include <linux/ktime.h>
-#include <linux/tracepoint.h>
-
-#include "../../../drivers/base/regmap/internal.h"
-
-/*
- * Log register events
- */
-DECLARE_EVENT_CLASS(regmap_reg,
-
-       TP_PROTO(struct regmap *map, unsigned int reg,
-                unsigned int val),
-
-       TP_ARGS(map, reg, val),
-
-       TP_STRUCT__entry(
-               __string(       name,           regmap_name(map)        )
-               __field(        unsigned int,   reg                     )
-               __field(        unsigned int,   val                     )
-       ),
-
-       TP_fast_assign(
-               __assign_str(name, regmap_name(map));
-               __entry->reg = reg;
-               __entry->val = val;
-       ),
-
-       TP_printk("%s reg=%x val=%x", __get_str(name),
-                 (unsigned int)__entry->reg,
-                 (unsigned int)__entry->val)
-);
-
-DEFINE_EVENT(regmap_reg, regmap_reg_write,
-
-       TP_PROTO(struct regmap *map, unsigned int reg,
-                unsigned int val),
-
-       TP_ARGS(map, reg, val)
-
-);
-
-DEFINE_EVENT(regmap_reg, regmap_reg_read,
-
-       TP_PROTO(struct regmap *map, unsigned int reg,
-                unsigned int val),
-
-       TP_ARGS(map, reg, val)
-
-);
-
-DEFINE_EVENT(regmap_reg, regmap_reg_read_cache,
-
-       TP_PROTO(struct regmap *map, unsigned int reg,
-                unsigned int val),
-
-       TP_ARGS(map, reg, val)
-
-);
-
-DECLARE_EVENT_CLASS(regmap_block,
-
-       TP_PROTO(struct regmap *map, unsigned int reg, int count),
-
-       TP_ARGS(map, reg, count),
-
-       TP_STRUCT__entry(
-               __string(       name,           regmap_name(map)        )
-               __field(        unsigned int,   reg                     )
-               __field(        int,            count                   )
-       ),
-
-       TP_fast_assign(
-               __assign_str(name, regmap_name(map));
-               __entry->reg = reg;
-               __entry->count = count;
-       ),
-
-       TP_printk("%s reg=%x count=%d", __get_str(name),
-                 (unsigned int)__entry->reg,
-                 (int)__entry->count)
-);
-
-DEFINE_EVENT(regmap_block, regmap_hw_read_start,
-
-       TP_PROTO(struct regmap *map, unsigned int reg, int count),
-
-       TP_ARGS(map, reg, count)
-);
-
-DEFINE_EVENT(regmap_block, regmap_hw_read_done,
-
-       TP_PROTO(struct regmap *map, unsigned int reg, int count),
-
-       TP_ARGS(map, reg, count)
-);
-
-DEFINE_EVENT(regmap_block, regmap_hw_write_start,
-
-       TP_PROTO(struct regmap *map, unsigned int reg, int count),
-
-       TP_ARGS(map, reg, count)
-);
-
-DEFINE_EVENT(regmap_block, regmap_hw_write_done,
-
-       TP_PROTO(struct regmap *map, unsigned int reg, int count),
-
-       TP_ARGS(map, reg, count)
-);
-
-TRACE_EVENT(regcache_sync,
-
-       TP_PROTO(struct regmap *map, const char *type,
-                const char *status),
-
-       TP_ARGS(map, type, status),
-
-       TP_STRUCT__entry(
-               __string(       name,           regmap_name(map)        )
-               __string(       status,         status                  )
-               __string(       type,           type                    )
-               __field(        int,            type                    )
-       ),
-
-       TP_fast_assign(
-               __assign_str(name, regmap_name(map));
-               __assign_str(status, status);
-               __assign_str(type, type);
-       ),
-
-       TP_printk("%s type=%s status=%s", __get_str(name),
-                 __get_str(type), __get_str(status))
-);
-
-DECLARE_EVENT_CLASS(regmap_bool,
-
-       TP_PROTO(struct regmap *map, bool flag),
-
-       TP_ARGS(map, flag),
-
-       TP_STRUCT__entry(
-               __string(       name,           regmap_name(map)        )
-               __field(        int,            flag                    )
-       ),
-
-       TP_fast_assign(
-               __assign_str(name, regmap_name(map));
-               __entry->flag = flag;
-       ),
-
-       TP_printk("%s flag=%d", __get_str(name),
-                 (int)__entry->flag)
-);
-
-DEFINE_EVENT(regmap_bool, regmap_cache_only,
-
-       TP_PROTO(struct regmap *map, bool flag),
-
-       TP_ARGS(map, flag)
-
-);
-
-DEFINE_EVENT(regmap_bool, regmap_cache_bypass,
-
-       TP_PROTO(struct regmap *map, bool flag),
-
-       TP_ARGS(map, flag)
-
-);
-
-DECLARE_EVENT_CLASS(regmap_async,
-
-       TP_PROTO(struct regmap *map),
-
-       TP_ARGS(map),
-
-       TP_STRUCT__entry(
-               __string(       name,           regmap_name(map)        )
-       ),
-
-       TP_fast_assign(
-               __assign_str(name, regmap_name(map));
-       ),
-
-       TP_printk("%s", __get_str(name))
-);
-
-DEFINE_EVENT(regmap_block, regmap_async_write_start,
-
-       TP_PROTO(struct regmap *map, unsigned int reg, int count),
-
-       TP_ARGS(map, reg, count)
-);
-
-DEFINE_EVENT(regmap_async, regmap_async_io_complete,
-
-       TP_PROTO(struct regmap *map),
-
-       TP_ARGS(map)
-
-);
-
-DEFINE_EVENT(regmap_async, regmap_async_complete_start,
-
-       TP_PROTO(struct regmap *map),
-
-       TP_ARGS(map)
-
-);
-
-DEFINE_EVENT(regmap_async, regmap_async_complete_done,
-
-       TP_PROTO(struct regmap *map),
-
-       TP_ARGS(map)
-
-);
-
-TRACE_EVENT(regcache_drop_region,
-
-       TP_PROTO(struct regmap *map, unsigned int from,
-                unsigned int to),
-
-       TP_ARGS(map, from, to),
-
-       TP_STRUCT__entry(
-               __string(       name,           regmap_name(map)        )
-               __field(        unsigned int,   from                    )
-               __field(        unsigned int,   to                      )
-       ),
-
-       TP_fast_assign(
-               __assign_str(name, regmap_name(map));
-               __entry->from = from;
-               __entry->to = to;
-       ),
-
-       TP_printk("%s %u-%u", __get_str(name), (unsigned int)__entry->from,
-                 (unsigned int)__entry->to)
-);
-
-#endif /* _TRACE_REGMAP_H */
-
-/* This part must be outside protection */
-#include <trace/define_trace.h>
index b9c1dc6c825ad1e0135102f3922260c52bc22a7d..fd1a02cb3c8235d08cd6f7f579a96c91d7c21c39 100644 (file)
@@ -179,27 +179,53 @@ DEFINE_EVENT(rpc_task_queued, rpc_task_wakeup,
 
 );
 
+/*
+ * First define the enums in the below macros to be exported to userspace
+ * via TRACE_DEFINE_ENUM().
+ */
+#undef EM
+#undef EMe
+#define EM(a, b)       TRACE_DEFINE_ENUM(a);
+#define EMe(a, b)      TRACE_DEFINE_ENUM(a);
+
+#define RPC_SHOW_SOCKET                                \
+       EM( SS_FREE, "FREE" )                   \
+       EM( SS_UNCONNECTED, "UNCONNECTED" )     \
+       EM( SS_CONNECTING, "CONNECTING," )      \
+       EM( SS_CONNECTED, "CONNECTED," )        \
+       EMe(SS_DISCONNECTING, "DISCONNECTING" )
+
 #define rpc_show_socket_state(state) \
-       __print_symbolic(state, \
-               { SS_FREE, "FREE" }, \
-               { SS_UNCONNECTED, "UNCONNECTED" }, \
-               { SS_CONNECTING, "CONNECTING," }, \
-               { SS_CONNECTED, "CONNECTED," }, \
-               { SS_DISCONNECTING, "DISCONNECTING" })
+       __print_symbolic(state, RPC_SHOW_SOCKET)
+
+RPC_SHOW_SOCKET
+
+#define RPC_SHOW_SOCK                          \
+       EM( TCP_ESTABLISHED, "ESTABLISHED" )    \
+       EM( TCP_SYN_SENT, "SYN_SENT" )          \
+       EM( TCP_SYN_RECV, "SYN_RECV" )          \
+       EM( TCP_FIN_WAIT1, "FIN_WAIT1" )        \
+       EM( TCP_FIN_WAIT2, "FIN_WAIT2" )        \
+       EM( TCP_TIME_WAIT, "TIME_WAIT" )        \
+       EM( TCP_CLOSE, "CLOSE" )                \
+       EM( TCP_CLOSE_WAIT, "CLOSE_WAIT" )      \
+       EM( TCP_LAST_ACK, "LAST_ACK" )          \
+       EM( TCP_LISTEN, "LISTEN" )              \
+       EMe( TCP_CLOSING, "CLOSING" )
 
 #define rpc_show_sock_state(state) \
-       __print_symbolic(state, \
-               { TCP_ESTABLISHED, "ESTABLISHED" }, \
-               { TCP_SYN_SENT, "SYN_SENT" }, \
-               { TCP_SYN_RECV, "SYN_RECV" }, \
-               { TCP_FIN_WAIT1, "FIN_WAIT1" }, \
-               { TCP_FIN_WAIT2, "FIN_WAIT2" }, \
-               { TCP_TIME_WAIT, "TIME_WAIT" }, \
-               { TCP_CLOSE, "CLOSE" }, \
-               { TCP_CLOSE_WAIT, "CLOSE_WAIT" }, \
-               { TCP_LAST_ACK, "LAST_ACK" }, \
-               { TCP_LISTEN, "LISTEN" }, \
-               { TCP_CLOSING, "CLOSING" })
+       __print_symbolic(state, RPC_SHOW_SOCK)
+
+RPC_SHOW_SOCK
+
+/*
+ * Now redefine the EM() and EMe() macros to map the enums to the strings
+ * that will be printed in the output.
+ */
+#undef EM
+#undef EMe
+#define EM(a, b)       {a, b},
+#define EMe(a, b)      {a, b}
 
 DECLARE_EVENT_CLASS(xs_socket_event,
 
index 0e763576515398be7bcbea3e1d4b50a25201c853..4250f364a6caad06a436636bf2a33a05aa442dbf 100644 (file)
@@ -7,11 +7,31 @@
 #include <linux/mm_types.h>
 #include <linux/tracepoint.h>
 
-#define TLB_FLUSH_REASON       \
-       { TLB_FLUSH_ON_TASK_SWITCH,     "flush on task switch" },       \
-       { TLB_REMOTE_SHOOTDOWN,         "remote shootdown" },           \
-       { TLB_LOCAL_SHOOTDOWN,          "local shootdown" },            \
-       { TLB_LOCAL_MM_SHOOTDOWN,       "local mm shootdown" }
+#define TLB_FLUSH_REASON                                               \
+       EM(  TLB_FLUSH_ON_TASK_SWITCH,  "flush on task switch" )        \
+       EM(  TLB_REMOTE_SHOOTDOWN,      "remote shootdown" )            \
+       EM(  TLB_LOCAL_SHOOTDOWN,       "local shootdown" )             \
+       EMe( TLB_LOCAL_MM_SHOOTDOWN,    "local mm shootdown" )
+
+/*
+ * First define the enums in TLB_FLUSH_REASON to be exported to userspace
+ * via TRACE_DEFINE_ENUM().
+ */
+#undef EM
+#undef EMe
+#define EM(a,b)                TRACE_DEFINE_ENUM(a);
+#define EMe(a,b)       TRACE_DEFINE_ENUM(a);
+
+TLB_FLUSH_REASON
+
+/*
+ * Now redefine the EM() and EMe() macros to map the enums to the strings
+ * that will be printed in the output.
+ */
+#undef EM
+#undef EMe
+#define EM(a,b)                { a, b },
+#define EMe(a,b)       { a, b }
 
 TRACE_EVENT_CONDITION(tlb_flush,
 
index b9bb1f2046938d136996de8fd6adfb5420e28486..20112170ff11052a48629bf8d85af4ba35b6fee5 100644 (file)
@@ -6,33 +6,58 @@
 
 #include <linux/tracepoint.h>
 
-#define show_type(type)                                                               \
-       __print_symbolic(type,                                                 \
-               { V4L2_BUF_TYPE_VIDEO_CAPTURE,        "VIDEO_CAPTURE" },       \
-               { V4L2_BUF_TYPE_VIDEO_OUTPUT,         "VIDEO_OUTPUT" },        \
-               { V4L2_BUF_TYPE_VIDEO_OVERLAY,        "VIDEO_OVERLAY" },       \
-               { V4L2_BUF_TYPE_VBI_CAPTURE,          "VBI_CAPTURE" },         \
-               { V4L2_BUF_TYPE_VBI_OUTPUT,           "VBI_OUTPUT" },          \
-               { V4L2_BUF_TYPE_SLICED_VBI_CAPTURE,   "SLICED_VBI_CAPTURE" },  \
-               { V4L2_BUF_TYPE_SLICED_VBI_OUTPUT,    "SLICED_VBI_OUTPUT" },   \
-               { V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY, "VIDEO_OUTPUT_OVERLAY" },\
-               { V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, "VIDEO_CAPTURE_MPLANE" },\
-               { V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,  "VIDEO_OUTPUT_MPLANE" }, \
-               { V4L2_BUF_TYPE_SDR_CAPTURE,          "SDR_CAPTURE" },         \
-               { V4L2_BUF_TYPE_PRIVATE,              "PRIVATE" })
+/* Enums require being exported to userspace, for user tool parsing */
+#undef EM
+#undef EMe
+#define EM(a, b)       TRACE_DEFINE_ENUM(a);
+#define EMe(a, b)      TRACE_DEFINE_ENUM(a);
+
+#define show_type(type)                                                        \
+       __print_symbolic(type, SHOW_TYPE)
+
+#define SHOW_TYPE                                                      \
+       EM( V4L2_BUF_TYPE_VIDEO_CAPTURE,        "VIDEO_CAPTURE" )       \
+       EM( V4L2_BUF_TYPE_VIDEO_OUTPUT,         "VIDEO_OUTPUT" )        \
+       EM( V4L2_BUF_TYPE_VIDEO_OVERLAY,        "VIDEO_OVERLAY" )       \
+       EM( V4L2_BUF_TYPE_VBI_CAPTURE,          "VBI_CAPTURE" )         \
+       EM( V4L2_BUF_TYPE_VBI_OUTPUT,           "VBI_OUTPUT" )          \
+       EM( V4L2_BUF_TYPE_SLICED_VBI_CAPTURE,   "SLICED_VBI_CAPTURE" )  \
+       EM( V4L2_BUF_TYPE_SLICED_VBI_OUTPUT,    "SLICED_VBI_OUTPUT" )   \
+       EM( V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY, "VIDEO_OUTPUT_OVERLAY" ) \
+       EM( V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, "VIDEO_CAPTURE_MPLANE" ) \
+       EM( V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,  "VIDEO_OUTPUT_MPLANE" ) \
+       EM( V4L2_BUF_TYPE_SDR_CAPTURE,          "SDR_CAPTURE" )         \
+       EMe(V4L2_BUF_TYPE_PRIVATE,              "PRIVATE" )
+
+SHOW_TYPE
 
 #define show_field(field)                                              \
-       __print_symbolic(field,                                         \
-               { V4L2_FIELD_ANY,               "ANY" },                \
-               { V4L2_FIELD_NONE,              "NONE" },               \
-               { V4L2_FIELD_TOP,               "TOP" },                \
-               { V4L2_FIELD_BOTTOM,            "BOTTOM" },             \
-               { V4L2_FIELD_INTERLACED,        "INTERLACED" },         \
-               { V4L2_FIELD_SEQ_TB,            "SEQ_TB" },             \
-               { V4L2_FIELD_SEQ_BT,            "SEQ_BT" },             \
-               { V4L2_FIELD_ALTERNATE,         "ALTERNATE" },          \
-               { V4L2_FIELD_INTERLACED_TB,     "INTERLACED_TB" },      \
-               { V4L2_FIELD_INTERLACED_BT,     "INTERLACED_BT" })
+       __print_symbolic(field, SHOW_FIELD)
+
+#define SHOW_FIELD                                                     \
+       EM( V4L2_FIELD_ANY,             "ANY" )                         \
+       EM( V4L2_FIELD_NONE,            "NONE" )                        \
+       EM( V4L2_FIELD_TOP,             "TOP" )                         \
+       EM( V4L2_FIELD_BOTTOM,          "BOTTOM" )                      \
+       EM( V4L2_FIELD_INTERLACED,      "INTERLACED" )                  \
+       EM( V4L2_FIELD_SEQ_TB,          "SEQ_TB" )                      \
+       EM( V4L2_FIELD_SEQ_BT,          "SEQ_BT" )                      \
+       EM( V4L2_FIELD_ALTERNATE,       "ALTERNATE" )                   \
+       EM( V4L2_FIELD_INTERLACED_TB,   "INTERLACED_TB" )               \
+       EMe( V4L2_FIELD_INTERLACED_BT,  "INTERLACED_BT" )
+
+SHOW_FIELD
+
+/*
+ * Now redefine the EM() and EMe() macros to map the enums to the strings
+ * that will be printed in the output.
+ */
+#undef EM
+#undef EMe
+#define EM(a, b)       {a, b},
+#define EMe(a, b)      {a, b}
+
+/* V4L2_TC_TYPE_* are macros, not defines, they do not need processing */
 
 #define show_timecode_type(type)                                       \
        __print_symbolic(type,                                          \
index 5a14ead59696a932400a0ab31c8cebe884b86472..880dd74371729939a0179ef3dfd487e1fa017838 100644 (file)
                {I_REFERENCED,          "I_REFERENCED"}         \
        )
 
+/* enums need to be exported to user space */
+#undef EM
+#undef EMe
+#define EM(a,b)        TRACE_DEFINE_ENUM(a);
+#define EMe(a,b)       TRACE_DEFINE_ENUM(a);
+
 #define WB_WORK_REASON                                                 \
-               {WB_REASON_BACKGROUND,          "background"},          \
-               {WB_REASON_TRY_TO_FREE_PAGES,   "try_to_free_pages"},   \
-               {WB_REASON_SYNC,                "sync"},                \
-               {WB_REASON_PERIODIC,            "periodic"},            \
-               {WB_REASON_LAPTOP_TIMER,        "laptop_timer"},        \
-               {WB_REASON_FREE_MORE_MEM,       "free_more_memory"},    \
-               {WB_REASON_FS_FREE_SPACE,       "fs_free_space"},       \
-               {WB_REASON_FORKER_THREAD,       "forker_thread"}
+       EM( WB_REASON_BACKGROUND,               "background")           \
+       EM( WB_REASON_TRY_TO_FREE_PAGES,        "try_to_free_pages")    \
+       EM( WB_REASON_SYNC,                     "sync")                 \
+       EM( WB_REASON_PERIODIC,                 "periodic")             \
+       EM( WB_REASON_LAPTOP_TIMER,             "laptop_timer")         \
+       EM( WB_REASON_FREE_MORE_MEM,            "free_more_memory")     \
+       EM( WB_REASON_FS_FREE_SPACE,            "fs_free_space")        \
+       EMe(WB_REASON_FORKER_THREAD,            "forker_thread")
+
+WB_WORK_REASON
+
+/*
+ * Now redefine the EM() and EMe() macros to map the enums to the strings
+ * that will be printed in the output.
+ */
+#undef EM
+#undef EMe
+#define EM(a,b)                { a, b },
+#define EMe(a,b)       { a, b }
 
 struct wb_writeback_work;
 
index d06b6da5c1e3e146d500bae9b012b809d831cb25..bce990f5a35d77615bb536009940f6146d1e7d82 100644 (file)
@@ -224,7 +224,7 @@ TRACE_EVENT(xen_mmu_pmd_clear,
            TP_printk("pmdp %p", __entry->pmdp)
        );
 
-#if PAGETABLE_LEVELS >= 4
+#if CONFIG_PGTABLE_LEVELS >= 4
 
 TRACE_EVENT(xen_mmu_set_pud,
            TP_PROTO(pud_t *pudp, pud_t pudval),
index 41bf65f04dd9e501fa4e3066402232553a19fef4..37d4b10b111d816fe6a88517521beffac2472b80 100644 (file)
 
 #include <linux/ftrace_event.h>
 
+#ifndef TRACE_SYSTEM_VAR
+#define TRACE_SYSTEM_VAR TRACE_SYSTEM
+#endif
+
+#define __app__(x, y) str__##x##y
+#define __app(x, y) __app__(x, y)
+
+#define TRACE_SYSTEM_STRING __app(TRACE_SYSTEM_VAR,__trace_system_name)
+
+#define TRACE_MAKE_SYSTEM_STR()                                \
+       static const char TRACE_SYSTEM_STRING[] =       \
+               __stringify(TRACE_SYSTEM)
+
+TRACE_MAKE_SYSTEM_STR();
+
+#undef TRACE_DEFINE_ENUM
+#define TRACE_DEFINE_ENUM(a)                           \
+       static struct trace_enum_map __used __initdata  \
+       __##TRACE_SYSTEM##_##a =                        \
+       {                                               \
+               .system = TRACE_SYSTEM_STRING,          \
+               .enum_string = #a,                      \
+               .enum_value = a                         \
+       };                                              \
+       static struct trace_enum_map __used             \
+       __attribute__((section("_ftrace_enum_map")))    \
+       *TRACE_SYSTEM##_##a = &__##TRACE_SYSTEM##_##a
+
 /*
  * DECLARE_EVENT_CLASS can be used to add a generic function
  * handlers for events. That is, if all events have the same
 
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
-
 /*
  * Stage 2 of the trace events.
  *
  * The size of an array is also encoded, in the higher 16 bits of <item>.
  */
 
+#undef TRACE_DEFINE_ENUM
+#define TRACE_DEFINE_ENUM(a)
+
 #undef __field
 #define __field(type, item)
 
@@ -539,7 +569,7 @@ static inline notrace int ftrace_get_offsets_##call(                        \
  *     .trace                  = ftrace_raw_output_<call>, <-- stage 2
  * };
  *
- * static const char print_fmt_<call>[] = <TP_printk>;
+ * static char print_fmt_<call>[] = <TP_printk>;
  *
  * static struct ftrace_event_class __used event_class_<template> = {
  *     .system                 = "<system>",
@@ -690,9 +720,9 @@ static inline void ftrace_test_probe_##call(void)                   \
 #undef DECLARE_EVENT_CLASS
 #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
 _TRACE_PERF_PROTO(call, PARAMS(proto));                                        \
-static const char print_fmt_##call[] = print;                          \
+static char print_fmt_##call[] = print;                                        \
 static struct ftrace_event_class __used __refdata event_class_##call = { \
-       .system                 = __stringify(TRACE_SYSTEM),            \
+       .system                 = TRACE_SYSTEM_STRING,                  \
        .define_fields          = ftrace_define_fields_##call,          \
        .fields                 = LIST_HEAD_INIT(event_class_##call.fields),\
        .raw_init               = trace_event_raw_init,                 \
@@ -719,7 +749,7 @@ __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call
 #undef DEFINE_EVENT_PRINT
 #define DEFINE_EVENT_PRINT(template, call, proto, args, print)         \
                                                                        \
-static const char print_fmt_##call[] = print;                          \
+static char print_fmt_##call[] = print;                                        \
                                                                        \
 static struct ftrace_event_call __used event_##call = {                        \
        .class                  = &event_class_##template,              \
@@ -735,6 +765,7 @@ __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call
 
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
+#undef TRACE_SYSTEM_VAR
 
 #ifdef CONFIG_PERF_EVENTS
 
index 68ceb97c458c90b96bf484df23a89a485d2b9ff3..38df23435ebbd399489326e649f828c8654878c0 100644 (file)
@@ -6,6 +6,7 @@ header-y += caif/
 header-y += dvb/
 header-y += hdlc/
 header-y += hsi/
+header-y += iio/
 header-y += isdn/
 header-y += mmc/
 header-y += nfsd/
index 45da7ec7d2742235e05b2ea53ab19d80af64794f..cc47ef41076a04039e60fffad990da3443f77729 100644 (file)
@@ -118,6 +118,7 @@ enum bpf_map_type {
 enum bpf_prog_type {
        BPF_PROG_TYPE_UNSPEC,
        BPF_PROG_TYPE_SOCKET_FILTER,
+       BPF_PROG_TYPE_KPROBE,
 };
 
 /* flags for BPF_MAP_UPDATE_ELEM command */
@@ -151,6 +152,7 @@ union bpf_attr {
                __u32           log_level;      /* verbosity level of verifier */
                __u32           log_size;       /* size of user buffer */
                __aligned_u64   log_buf;        /* user supplied buffer */
+               __u32           kern_version;   /* checked when prog_type=kprobe */
        };
 } __attribute__((aligned(8)));
 
@@ -162,6 +164,9 @@ enum bpf_func_id {
        BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */
        BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */
        BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */
+       BPF_FUNC_probe_read,      /* int bpf_probe_read(void *dst, int size, void *src) */
+       BPF_FUNC_ktime_get_ns,    /* u64 bpf_ktime_get_ns(void) */
+       BPF_FUNC_trace_printk,    /* int bpf_trace_printk(const char *fmt, int fmt_size, ...) */
        __BPF_FUNC_MAX_ID,
 };
 
index 30ab3cd3b8a55b7f347eda392cae4578645af9e0..a16a00544258c2e99e46fd1632548f79d875075f 100644 (file)
@@ -1,2 +1,2 @@
 # UAPI Header export list
-header-y += hsi_char.h
+header-y += hsi_char.h cs-protocol.h
diff --git a/include/uapi/linux/hsi/cs-protocol.h b/include/uapi/linux/hsi/cs-protocol.h
new file mode 100644 (file)
index 0000000..4957bba
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * cmt-speech interface definitions
+ *
+ * Copyright (C) 2008,2009,2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Kai Vehmanen <kai.vehmanen@nokia.com>
+ * Original author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef _CS_PROTOCOL_H
+#define _CS_PROTOCOL_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+/* chardev parameters */
+#define CS_DEV_FILE_NAME               "/dev/cmt_speech"
+
+/* user-space API versioning */
+#define CS_IF_VERSION                  2
+
+/* APE kernel <-> user space messages */
+#define CS_CMD_SHIFT                   28
+#define CS_DOMAIN_SHIFT                        24
+
+#define CS_CMD_MASK                    0xff000000
+#define CS_PARAM_MASK                  0xffffff
+
+#define CS_CMD(id, dom) \
+       (((id) << CS_CMD_SHIFT) | ((dom) << CS_DOMAIN_SHIFT))
+
+#define CS_ERROR                       CS_CMD(1, 0)
+#define CS_RX_DATA_RECEIVED            CS_CMD(2, 0)
+#define CS_TX_DATA_READY               CS_CMD(3, 0)
+#define CS_TX_DATA_SENT                        CS_CMD(4, 0)
+
+/* params to CS_ERROR indication */
+#define CS_ERR_PEER_RESET              0
+
+/* ioctl interface */
+
+/* parameters to CS_CONFIG_BUFS ioctl */
+#define CS_FEAT_TSTAMP_RX_CTRL         (1 << 0)
+#define CS_FEAT_ROLLING_RX_COUNTER     (2 << 0)
+
+/* parameters to CS_GET_STATE ioctl */
+#define CS_STATE_CLOSED                        0
+#define CS_STATE_OPENED                        1 /* resource allocated */
+#define CS_STATE_CONFIGURED            2 /* data path active */
+
+/* maximum number of TX/RX buffers */
+#define CS_MAX_BUFFERS_SHIFT           4
+#define CS_MAX_BUFFERS                 (1 << CS_MAX_BUFFERS_SHIFT)
+
+/* Parameters for setting up the data buffers */
+struct cs_buffer_config {
+       __u32 rx_bufs;  /* number of RX buffer slots */
+       __u32 tx_bufs;  /* number of TX buffer slots */
+       __u32 buf_size; /* bytes */
+       __u32 flags;    /* see CS_FEAT_* */
+       __u32 reserved[4];
+};
+
+/*
+ * Struct describing the layout and contents of the driver mmap area.
+ * This information is meant as read-only information for the application.
+ */
+struct cs_mmap_config_block {
+       __u32 reserved1;
+       __u32 buf_size;         /* 0=disabled, otherwise the transfer size */
+       __u32 rx_bufs;          /* # of RX buffers */
+       __u32 tx_bufs;          /* # of TX buffers */
+       __u32 reserved2;
+       /* array of offsets within the mmap area for each RX and TX buffer */
+       __u32 rx_offsets[CS_MAX_BUFFERS];
+       __u32 tx_offsets[CS_MAX_BUFFERS];
+       __u32 rx_ptr;
+       __u32 rx_ptr_boundary;
+       __u32 reserved3[2];
+       /*
+        * if enabled with CS_FEAT_TSTAMP_RX_CTRL, monotonic
+        * timestamp taken when the last control command was received
+        */
+       struct timespec tstamp_rx_ctrl;
+};
+
+#define CS_IO_MAGIC            'C'
+
+#define CS_IOW(num, dtype)     _IOW(CS_IO_MAGIC, num, dtype)
+#define CS_IOR(num, dtype)     _IOR(CS_IO_MAGIC, num, dtype)
+#define CS_IOWR(num, dtype)    _IOWR(CS_IO_MAGIC, num, dtype)
+#define CS_IO(num)             _IO(CS_IO_MAGIC, num)
+
+#define CS_GET_STATE           CS_IOR(21, unsigned int)
+#define CS_SET_WAKELINE                CS_IOW(23, unsigned int)
+#define CS_GET_IF_VERSION      CS_IOR(30, unsigned int)
+#define CS_CONFIG_BUFS         CS_IOW(31, struct cs_buffer_config)
+
+#endif /* _CS_PROTOCOL_H */
diff --git a/include/uapi/linux/iio/Kbuild b/include/uapi/linux/iio/Kbuild
new file mode 100644 (file)
index 0000000..86f76d8
--- /dev/null
@@ -0,0 +1,3 @@
+# UAPI Header export list
+header-y += events.h
+header-y += types.h
diff --git a/include/uapi/linux/iio/events.h b/include/uapi/linux/iio/events.h
new file mode 100644 (file)
index 0000000..00bbdae
--- /dev/null
@@ -0,0 +1,42 @@
+/* The industrial I/O - event passing to userspace
+ *
+ * Copyright (c) 2008-2011 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef _UAPI_IIO_EVENTS_H_
+#define _UAPI_IIO_EVENTS_H_
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/**
+ * struct iio_event_data - The actual event being pushed to userspace
+ * @id:                event identifier
+ * @timestamp: best estimate of time of event occurrence (often from
+ *             the interrupt handler)
+ */
+struct iio_event_data {
+       __u64   id;
+       __s64   timestamp;
+};
+
+#define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int)
+
+#define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF)
+
+#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0x7F)
+
+#define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF)
+
+/* Event code number extraction depends on which type of event we have.
+ * Perhaps review this function in the future*/
+#define IIO_EVENT_CODE_EXTRACT_CHAN(mask) ((__s16)(mask & 0xFFFF))
+#define IIO_EVENT_CODE_EXTRACT_CHAN2(mask) ((__s16)(((mask) >> 16) & 0xFFFF))
+
+#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF)
+#define IIO_EVENT_CODE_EXTRACT_DIFF(mask) (((mask) >> 55) & 0x1)
+
+#endif /* _UAPI_IIO_EVENTS_H_ */
diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
new file mode 100644 (file)
index 0000000..5c46019
--- /dev/null
@@ -0,0 +1,92 @@
+/* industrial I/O data types needed both in and out of kernel
+ *
+ * Copyright (c) 2008 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef _UAPI_IIO_TYPES_H_
+#define _UAPI_IIO_TYPES_H_
+
+enum iio_chan_type {
+       IIO_VOLTAGE,
+       IIO_CURRENT,
+       IIO_POWER,
+       IIO_ACCEL,
+       IIO_ANGL_VEL,
+       IIO_MAGN,
+       IIO_LIGHT,
+       IIO_INTENSITY,
+       IIO_PROXIMITY,
+       IIO_TEMP,
+       IIO_INCLI,
+       IIO_ROT,
+       IIO_ANGL,
+       IIO_TIMESTAMP,
+       IIO_CAPACITANCE,
+       IIO_ALTVOLTAGE,
+       IIO_CCT,
+       IIO_PRESSURE,
+       IIO_HUMIDITYRELATIVE,
+       IIO_ACTIVITY,
+       IIO_STEPS,
+       IIO_ENERGY,
+       IIO_DISTANCE,
+       IIO_VELOCITY,
+};
+
+enum iio_modifier {
+       IIO_NO_MOD,
+       IIO_MOD_X,
+       IIO_MOD_Y,
+       IIO_MOD_Z,
+       IIO_MOD_X_AND_Y,
+       IIO_MOD_X_AND_Z,
+       IIO_MOD_Y_AND_Z,
+       IIO_MOD_X_AND_Y_AND_Z,
+       IIO_MOD_X_OR_Y,
+       IIO_MOD_X_OR_Z,
+       IIO_MOD_Y_OR_Z,
+       IIO_MOD_X_OR_Y_OR_Z,
+       IIO_MOD_LIGHT_BOTH,
+       IIO_MOD_LIGHT_IR,
+       IIO_MOD_ROOT_SUM_SQUARED_X_Y,
+       IIO_MOD_SUM_SQUARED_X_Y_Z,
+       IIO_MOD_LIGHT_CLEAR,
+       IIO_MOD_LIGHT_RED,
+       IIO_MOD_LIGHT_GREEN,
+       IIO_MOD_LIGHT_BLUE,
+       IIO_MOD_QUATERNION,
+       IIO_MOD_TEMP_AMBIENT,
+       IIO_MOD_TEMP_OBJECT,
+       IIO_MOD_NORTH_MAGN,
+       IIO_MOD_NORTH_TRUE,
+       IIO_MOD_NORTH_MAGN_TILT_COMP,
+       IIO_MOD_NORTH_TRUE_TILT_COMP,
+       IIO_MOD_RUNNING,
+       IIO_MOD_JOGGING,
+       IIO_MOD_WALKING,
+       IIO_MOD_STILL,
+       IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z,
+};
+
+enum iio_event_type {
+       IIO_EV_TYPE_THRESH,
+       IIO_EV_TYPE_MAG,
+       IIO_EV_TYPE_ROC,
+       IIO_EV_TYPE_THRESH_ADAPTIVE,
+       IIO_EV_TYPE_MAG_ADAPTIVE,
+       IIO_EV_TYPE_CHANGE,
+};
+
+enum iio_event_direction {
+       IIO_EV_DIR_EITHER,
+       IIO_EV_DIR_RISING,
+       IIO_EV_DIR_FALLING,
+       IIO_EV_DIR_NONE,
+};
+
+#endif /* _UAPI_IIO_TYPES_H_ */
+
index 905d90c53a4fa9a3099ecb0a199b7cdfdda14293..731417c025f6feff03ea257b46abde05c7a06b7d 100644 (file)
@@ -703,6 +703,10 @@ struct input_keymap_entry {
 #define KEY_NUMERIC_9          0x209
 #define KEY_NUMERIC_STAR       0x20a
 #define KEY_NUMERIC_POUND      0x20b
+#define KEY_NUMERIC_A          0x20c   /* Phone key A - HUT Telephony 0xb9 */
+#define KEY_NUMERIC_B          0x20d
+#define KEY_NUMERIC_C          0x20e
+#define KEY_NUMERIC_D          0x20f
 
 #define KEY_CAMERA_FOCUS       0x210
 #define KEY_WPS_BUTTON         0x211   /* WiFi Protected Setup key */
index 805570650062e99dfbb20edbab759e1322462170..f574d7be7631e5795f26a8934391b8b6f1473f8e 100644 (file)
@@ -147,6 +147,16 @@ struct kvm_pit_config {
 
 #define KVM_PIT_SPEAKER_DUMMY     1
 
+struct kvm_s390_skeys {
+       __u64 start_gfn;
+       __u64 count;
+       __u64 skeydata_addr;
+       __u32 flags;
+       __u32 reserved[9];
+};
+#define KVM_S390_GET_SKEYS_NONE   1
+#define KVM_S390_SKEYS_MAX        1048576
+
 #define KVM_EXIT_UNKNOWN          0
 #define KVM_EXIT_EXCEPTION        1
 #define KVM_EXIT_IO               2
@@ -172,6 +182,7 @@ struct kvm_pit_config {
 #define KVM_EXIT_S390_TSCH        22
 #define KVM_EXIT_EPR              23
 #define KVM_EXIT_SYSTEM_EVENT     24
+#define KVM_EXIT_S390_STSI        25
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -309,6 +320,15 @@ struct kvm_run {
                        __u32 type;
                        __u64 flags;
                } system_event;
+               /* KVM_EXIT_S390_STSI */
+               struct {
+                       __u64 addr;
+                       __u8 ar;
+                       __u8 reserved;
+                       __u8 fc;
+                       __u8 sel1;
+                       __u16 sel2;
+               } s390_stsi;
                /* Fix the size of the union. */
                char padding[256];
        };
@@ -324,7 +344,7 @@ struct kvm_run {
        __u64 kvm_dirty_regs;
        union {
                struct kvm_sync_regs regs;
-               char padding[1024];
+               char padding[2048];
        } s;
 };
 
@@ -365,6 +385,24 @@ struct kvm_translation {
        __u8  pad[5];
 };
 
+/* for KVM_S390_MEM_OP */
+struct kvm_s390_mem_op {
+       /* in */
+       __u64 gaddr;            /* the guest address */
+       __u64 flags;            /* flags */
+       __u32 size;             /* amount of bytes */
+       __u32 op;               /* type of operation */
+       __u64 buf;              /* buffer in userspace */
+       __u8 ar;                /* the access register number */
+       __u8 reserved[31];      /* should be set to 0 */
+};
+/* types for kvm_s390_mem_op->op */
+#define KVM_S390_MEMOP_LOGICAL_READ    0
+#define KVM_S390_MEMOP_LOGICAL_WRITE   1
+/* flags for kvm_s390_mem_op->flags */
+#define KVM_S390_MEMOP_F_CHECK_ONLY            (1ULL << 0)
+#define KVM_S390_MEMOP_F_INJECT_EXCEPTION      (1ULL << 1)
+
 /* for KVM_INTERRUPT */
 struct kvm_interrupt {
        /* in */
@@ -520,6 +558,13 @@ struct kvm_s390_irq {
        } u;
 };
 
+struct kvm_s390_irq_state {
+       __u64 buf;
+       __u32 flags;
+       __u32 len;
+       __u32 reserved[4];
+};
+
 /* for KVM_SET_GUEST_DEBUG */
 
 #define KVM_GUESTDBG_ENABLE            0x00000001
@@ -760,6 +805,14 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_PPC_ENABLE_HCALL 104
 #define KVM_CAP_CHECK_EXTENSION_VM 105
 #define KVM_CAP_S390_USER_SIGP 106
+#define KVM_CAP_S390_VECTOR_REGISTERS 107
+#define KVM_CAP_S390_MEM_OP 108
+#define KVM_CAP_S390_USER_STSI 109
+#define KVM_CAP_S390_SKEYS 110
+#define KVM_CAP_MIPS_FPU 111
+#define KVM_CAP_MIPS_MSA 112
+#define KVM_CAP_S390_INJECT_IRQ 113
+#define KVM_CAP_S390_IRQ_STATE 114
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1135,6 +1188,16 @@ struct kvm_s390_ucas_mapping {
 #define KVM_ARM_VCPU_INIT        _IOW(KVMIO,  0xae, struct kvm_vcpu_init)
 #define KVM_ARM_PREFERRED_TARGET  _IOR(KVMIO,  0xaf, struct kvm_vcpu_init)
 #define KVM_GET_REG_LIST         _IOWR(KVMIO, 0xb0, struct kvm_reg_list)
+/* Available with KVM_CAP_S390_MEM_OP */
+#define KVM_S390_MEM_OP                  _IOW(KVMIO,  0xb1, struct kvm_s390_mem_op)
+/* Available with KVM_CAP_S390_SKEYS */
+#define KVM_S390_GET_SKEYS      _IOW(KVMIO, 0xb2, struct kvm_s390_skeys)
+#define KVM_S390_SET_SKEYS      _IOW(KVMIO, 0xb3, struct kvm_s390_skeys)
+/* Available with KVM_CAP_S390_INJECT_IRQ */
+#define KVM_S390_IRQ              _IOW(KVMIO,  0xb4, struct kvm_s390_irq)
+/* Available with KVM_CAP_S390_IRQ_STATE */
+#define KVM_S390_SET_IRQ_STATE   _IOW(KVMIO, 0xb5, struct kvm_s390_irq_state)
+#define KVM_S390_GET_IRQ_STATE   _IOW(KVMIO, 0xb6, struct kvm_s390_irq_state)
 
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU    (1 << 0)
 #define KVM_DEV_ASSIGN_PCI_2_3         (1 << 1)
index 7d664ea85ebd89a67d01851b9a0cbb4aa627d0ea..7b1425a6b370f878b7e08de24a5d901d6187d0e2 100644 (file)
@@ -58,6 +58,8 @@
 
 #define STACK_END_MAGIC                0x57AC6E9D
 
+#define TRACEFS_MAGIC          0x74726163
+
 #define V9FS_MAGIC             0x01021997
 
 #define BDEVFS_MAGIC            0x62646576
index 9b79abbd1ab80f765eb15b2d563f2c30262327d2..309211b3eb672f9449a0fc266ed643ac881196d3 100644 (file)
@@ -152,21 +152,42 @@ enum perf_event_sample_format {
  * The branch types can be combined, however BRANCH_ANY covers all types
  * of branches and therefore it supersedes all the other types.
  */
+enum perf_branch_sample_type_shift {
+       PERF_SAMPLE_BRANCH_USER_SHIFT           = 0, /* user branches */
+       PERF_SAMPLE_BRANCH_KERNEL_SHIFT         = 1, /* kernel branches */
+       PERF_SAMPLE_BRANCH_HV_SHIFT             = 2, /* hypervisor branches */
+
+       PERF_SAMPLE_BRANCH_ANY_SHIFT            = 3, /* any branch types */
+       PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT       = 4, /* any call branch */
+       PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT     = 5, /* any return branch */
+       PERF_SAMPLE_BRANCH_IND_CALL_SHIFT       = 6, /* indirect calls */
+       PERF_SAMPLE_BRANCH_ABORT_TX_SHIFT       = 7, /* transaction aborts */
+       PERF_SAMPLE_BRANCH_IN_TX_SHIFT          = 8, /* in transaction */
+       PERF_SAMPLE_BRANCH_NO_TX_SHIFT          = 9, /* not in transaction */
+       PERF_SAMPLE_BRANCH_COND_SHIFT           = 10, /* conditional branches */
+
+       PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT     = 11, /* call/ret stack */
+
+       PERF_SAMPLE_BRANCH_MAX_SHIFT            /* non-ABI */
+};
+
 enum perf_branch_sample_type {
-       PERF_SAMPLE_BRANCH_USER         = 1U << 0, /* user branches */
-       PERF_SAMPLE_BRANCH_KERNEL       = 1U << 1, /* kernel branches */
-       PERF_SAMPLE_BRANCH_HV           = 1U << 2, /* hypervisor branches */
-
-       PERF_SAMPLE_BRANCH_ANY          = 1U << 3, /* any branch types */
-       PERF_SAMPLE_BRANCH_ANY_CALL     = 1U << 4, /* any call branch */
-       PERF_SAMPLE_BRANCH_ANY_RETURN   = 1U << 5, /* any return branch */
-       PERF_SAMPLE_BRANCH_IND_CALL     = 1U << 6, /* indirect calls */
-       PERF_SAMPLE_BRANCH_ABORT_TX     = 1U << 7, /* transaction aborts */
-       PERF_SAMPLE_BRANCH_IN_TX        = 1U << 8, /* in transaction */
-       PERF_SAMPLE_BRANCH_NO_TX        = 1U << 9, /* not in transaction */
-       PERF_SAMPLE_BRANCH_COND         = 1U << 10, /* conditional branches */
-
-       PERF_SAMPLE_BRANCH_MAX          = 1U << 11, /* non-ABI */
+       PERF_SAMPLE_BRANCH_USER         = 1U << PERF_SAMPLE_BRANCH_USER_SHIFT,
+       PERF_SAMPLE_BRANCH_KERNEL       = 1U << PERF_SAMPLE_BRANCH_KERNEL_SHIFT,
+       PERF_SAMPLE_BRANCH_HV           = 1U << PERF_SAMPLE_BRANCH_HV_SHIFT,
+
+       PERF_SAMPLE_BRANCH_ANY          = 1U << PERF_SAMPLE_BRANCH_ANY_SHIFT,
+       PERF_SAMPLE_BRANCH_ANY_CALL     = 1U << PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT,
+       PERF_SAMPLE_BRANCH_ANY_RETURN   = 1U << PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT,
+       PERF_SAMPLE_BRANCH_IND_CALL     = 1U << PERF_SAMPLE_BRANCH_IND_CALL_SHIFT,
+       PERF_SAMPLE_BRANCH_ABORT_TX     = 1U << PERF_SAMPLE_BRANCH_ABORT_TX_SHIFT,
+       PERF_SAMPLE_BRANCH_IN_TX        = 1U << PERF_SAMPLE_BRANCH_IN_TX_SHIFT,
+       PERF_SAMPLE_BRANCH_NO_TX        = 1U << PERF_SAMPLE_BRANCH_NO_TX_SHIFT,
+       PERF_SAMPLE_BRANCH_COND         = 1U << PERF_SAMPLE_BRANCH_COND_SHIFT,
+
+       PERF_SAMPLE_BRANCH_CALL_STACK   = 1U << PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT,
+
+       PERF_SAMPLE_BRANCH_MAX          = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT,
 };
 
 #define PERF_SAMPLE_BRANCH_PLM_ALL \
@@ -240,6 +261,7 @@ enum perf_event_read_format {
 #define PERF_ATTR_SIZE_VER3    96      /* add: sample_regs_user */
                                        /* add: sample_stack_user */
 #define PERF_ATTR_SIZE_VER4    104     /* add: sample_regs_intr */
+#define PERF_ATTR_SIZE_VER5    112     /* add: aux_watermark */
 
 /*
  * Hardware event_id to monitor via a performance monitoring event:
@@ -305,7 +327,8 @@ struct perf_event_attr {
                                exclude_callchain_user   : 1, /* exclude user callchains */
                                mmap2          :  1, /* include mmap with inode data     */
                                comm_exec      :  1, /* flag comm events that are due to an exec */
-                               __reserved_1   : 39;
+                               use_clockid    :  1, /* use @clockid for time fields */
+                               __reserved_1   : 38;
 
        union {
                __u32           wakeup_events;    /* wakeup every n events */
@@ -334,8 +357,7 @@ struct perf_event_attr {
         */
        __u32   sample_stack_user;
 
-       /* Align to u64. */
-       __u32   __reserved_2;
+       __s32   clockid;
        /*
         * Defines set of regs to dump for each sample
         * state captured on:
@@ -345,6 +367,12 @@ struct perf_event_attr {
         * See asm/perf_regs.h for details.
         */
        __u64   sample_regs_intr;
+
+       /*
+        * Wakeup watermark for AUX area
+        */
+       __u32   aux_watermark;
+       __u32   __reserved_2;   /* align to __u64 */
 };
 
 #define perf_flags(attr)       (*(&(attr)->read_format + 1))
@@ -360,6 +388,7 @@ struct perf_event_attr {
 #define PERF_EVENT_IOC_SET_OUTPUT      _IO ('$', 5)
 #define PERF_EVENT_IOC_SET_FILTER      _IOW('$', 6, char *)
 #define PERF_EVENT_IOC_ID              _IOR('$', 7, __u64 *)
+#define PERF_EVENT_IOC_SET_BPF         _IOW('$', 8, __u32)
 
 enum perf_event_ioc_flags {
        PERF_IOC_FLAG_GROUP             = 1U << 0,
@@ -500,9 +529,30 @@ struct perf_event_mmap_page {
         * In this case the kernel will not over-write unread data.
         *
         * See perf_output_put_handle() for the data ordering.
+        *
+        * data_{offset,size} indicate the location and size of the perf record
+        * buffer within the mmapped area.
         */
        __u64   data_head;              /* head in the data section */
        __u64   data_tail;              /* user-space written tail */
+       __u64   data_offset;            /* where the buffer starts */
+       __u64   data_size;              /* data buffer size */
+
+       /*
+        * AUX area is defined by aux_{offset,size} fields that should be set
+        * by the userspace, so that
+        *
+        *   aux_offset >= data_offset + data_size
+        *
+        * prior to mmap()ing it. Size of the mmap()ed area should be aux_size.
+        *
+        * Ring buffer pointers aux_{head,tail} have the same semantics as
+        * data_{head,tail} and same ordering rules apply.
+        */
+       __u64   aux_head;
+       __u64   aux_tail;
+       __u64   aux_offset;
+       __u64   aux_size;
 };
 
 #define PERF_RECORD_MISC_CPUMODE_MASK          (7 << 0)
@@ -725,6 +775,31 @@ enum perf_event_type {
         */
        PERF_RECORD_MMAP2                       = 10,
 
+       /*
+        * Records that new data landed in the AUX buffer part.
+        *
+        * struct {
+        *      struct perf_event_header        header;
+        *
+        *      u64                             aux_offset;
+        *      u64                             aux_size;
+        *      u64                             flags;
+        *      struct sample_id                sample_id;
+        * };
+        */
+       PERF_RECORD_AUX                         = 11,
+
+       /*
+        * Indicates that instruction trace has started
+        *
+        * struct {
+        *      struct perf_event_header        header;
+        *      u32                             pid;
+        *      u32                             tid;
+        * };
+        */
+       PERF_RECORD_ITRACE_START                = 12,
+
        PERF_RECORD_MAX,                        /* non-ABI */
 };
 
@@ -742,6 +817,12 @@ enum perf_callchain_context {
        PERF_CONTEXT_MAX                = (__u64)-4095,
 };
 
+/**
+ * PERF_RECORD_AUX::flags bits
+ */
+#define PERF_AUX_FLAG_TRUNCATED                0x01    /* record was truncated to fit */
+#define PERF_AUX_FLAG_OVERWRITE                0x02    /* snapshot from overwrite mode */
+
 #define PERF_FLAG_FD_NO_GROUP          (1UL << 0)
 #define PERF_FLAG_FD_OUTPUT            (1UL << 1)
 #define PERF_FLAG_PID_CGROUP           (1UL << 2) /* pid=cgroup id, per-cpu mode only */
index 82889c30f4f5a79fb820c1dd20e1e8a0f99b4bf0..b57b750c222f1d5729b7b171a9131e0e1ed9ccd5 100644 (file)
@@ -160,6 +160,8 @@ struct vfio_device_info {
        __u32   flags;
 #define VFIO_DEVICE_FLAGS_RESET        (1 << 0)        /* Device supports reset */
 #define VFIO_DEVICE_FLAGS_PCI  (1 << 1)        /* vfio-pci device */
+#define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2)    /* vfio-platform device */
+#define VFIO_DEVICE_FLAGS_AMBA  (1 << 3)       /* vfio-amba device */
        __u32   num_regions;    /* Max region index + 1 */
        __u32   num_irqs;       /* Max IRQ index + 1 */
 };
index f5dbc6d4261bcb47e7d7dccfa6385f649ecefa0a..a905b7301e10201103da5832c66edf55d2b4cce4 100644 (file)
@@ -791,6 +791,19 @@ config RCU_NOCB_CPU_ALL
 
 endchoice
 
+config RCU_EXPEDITE_BOOT
+       bool
+       default n
+       help
+         This option enables expedited grace periods at boot time,
+         as if rcu_expedite_gp() had been invoked early in boot.
+         The corresponding rcu_unexpedite_gp() is invoked from
+         rcu_end_inkernel_boot(), which is intended to be invoked
+         at the end of the kernel-only boot sequence, just before
+         init is exec'ed.
+
+         Accept the default if unsure.
+
 endmenu # "RCU Subsystem"
 
 config BUILD_BIN2C
@@ -1513,7 +1526,7 @@ config EVENTFD
 
 # syscall, maps, verifier
 config BPF_SYSCALL
-       bool "Enable bpf() system call" if EXPERT
+       bool "Enable bpf() system call"
        select ANON_INODES
        select BPF
        default n
index 6f0f1c5ff8cc82c41b36f107f68732003c5b1dc3..a7e969d12f51a8a629f74d7bf10920ea7fef967b 100644 (file)
@@ -80,6 +80,7 @@
 #include <linux/list.h>
 #include <linux/integrity.h>
 #include <linux/proc_ns.h>
+#include <linux/io.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -143,7 +144,7 @@ EXPORT_SYMBOL_GPL(static_key_initialized);
  * rely on the BIOS and skip the reset operation.
  *
  * This is useful if kernel is booting in an unreliable environment.
- * For ex. kdump situaiton where previous kernel has crashed, BIOS has been
+ * For ex. kdump situation where previous kernel has crashed, BIOS has been
  * skipped and devices will be in unknown state.
  */
 unsigned int reset_devices;
@@ -384,6 +385,7 @@ static noinline void __init_refok rest_init(void)
        int pid;
 
        rcu_scheduler_starting();
+       smpboot_thread_init();
        /*
         * We need to spawn init first so that it obtains pid 1, however
         * the init task will end up wanting to create kthreads, which, if
@@ -484,6 +486,7 @@ static void __init mm_init(void)
        percpu_init_late();
        pgtable_init();
        vmalloc_init();
+       ioremap_huge_init();
 }
 
 asmlinkage __visible void __init start_kernel(void)
@@ -654,8 +657,8 @@ asmlinkage __visible void __init start_kernel(void)
        page_writeback_init();
        proc_root_init();
        nsfs_init();
-       cgroup_init();
        cpuset_init();
+       cgroup_init();
        taskstats_init_early();
        delayacct_init();
 
index 536edc2be3072e91ab132555fc4f9bc3ce656604..504c10b990efe9c21d32e33f01747e99294f69a1 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/file.h>
 #include <linux/license.h>
 #include <linux/filter.h>
+#include <linux/version.h>
 
 static LIST_HEAD(bpf_map_types);
 
@@ -467,7 +468,7 @@ struct bpf_prog *bpf_prog_get(u32 ufd)
 }
 
 /* last field in 'union bpf_attr' used by this command */
-#define        BPF_PROG_LOAD_LAST_FIELD log_buf
+#define        BPF_PROG_LOAD_LAST_FIELD kern_version
 
 static int bpf_prog_load(union bpf_attr *attr)
 {
@@ -492,6 +493,10 @@ static int bpf_prog_load(union bpf_attr *attr)
        if (attr->insn_cnt >= BPF_MAXINSNS)
                return -EINVAL;
 
+       if (type == BPF_PROG_TYPE_KPROBE &&
+           attr->kern_version != LINUX_VERSION_CODE)
+               return -EINVAL;
+
        /* plain bpf_prog allocation */
        prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
        if (!prog)
index 29a7b2cc593e3f50a425f1dbbf187d5d1fb4542f..a220fdb66568eea7de9768197d2e275a04ee479b 100644 (file)
@@ -3806,10 +3806,7 @@ static void *pidlist_allocate(int count)
 
 static void pidlist_free(void *p)
 {
-       if (is_vmalloc_addr(p))
-               vfree(p);
-       else
-               kfree(p);
+       kvfree(p);
 }
 
 /*
@@ -5040,6 +5037,9 @@ int __init cgroup_init(void)
                        WARN_ON(cgroup_add_dfl_cftypes(ss, ss->dfl_cftypes));
                        WARN_ON(cgroup_add_legacy_cftypes(ss, ss->legacy_cftypes));
                }
+
+               if (ss->bind)
+                       ss->bind(init_css_set.subsys[ssid]);
        }
 
        cgroup_kobj = kobject_create_and_add("cgroup", fs_kobj);
index 937ecdfdf2589cc896522286a4da2e3d4f097bf9..72d59a1a6eb66f54985aa8711e0d55ed46150628 100644 (file)
@@ -39,15 +39,15 @@ void context_tracking_cpu_set(int cpu)
 }
 
 /**
- * context_tracking_user_enter - Inform the context tracking that the CPU is going to
- *                               enter userspace mode.
+ * context_tracking_enter - Inform the context tracking that the CPU is going
+ *                          enter user or guest space mode.
  *
  * This function must be called right before we switch from the kernel
- * to userspace, when it's guaranteed the remaining kernel instructions
- * to execute won't use any RCU read side critical section because this
- * function sets RCU in extended quiescent state.
+ * to user or guest space, when it's guaranteed the remaining kernel
+ * instructions to execute won't use any RCU read side critical section
+ * because this function sets RCU in extended quiescent state.
  */
-void context_tracking_user_enter(void)
+void context_tracking_enter(enum ctx_state state)
 {
        unsigned long flags;
 
@@ -75,9 +75,8 @@ void context_tracking_user_enter(void)
        WARN_ON_ONCE(!current->mm);
 
        local_irq_save(flags);
-       if ( __this_cpu_read(context_tracking.state) != IN_USER) {
+       if ( __this_cpu_read(context_tracking.state) != state) {
                if (__this_cpu_read(context_tracking.active)) {
-                       trace_user_enter(0);
                        /*
                         * At this stage, only low level arch entry code remains and
                         * then we'll run in userspace. We can assume there won't be
@@ -85,7 +84,10 @@ void context_tracking_user_enter(void)
                         * user_exit() or rcu_irq_enter(). Let's remove RCU's dependency
                         * on the tick.
                         */
-                       vtime_user_enter(current);
+                       if (state == CONTEXT_USER) {
+                               trace_user_enter(0);
+                               vtime_user_enter(current);
+                       }
                        rcu_user_enter();
                }
                /*
@@ -101,24 +103,32 @@ void context_tracking_user_enter(void)
                 * OTOH we can spare the calls to vtime and RCU when context_tracking.active
                 * is false because we know that CPU is not tickless.
                 */
-               __this_cpu_write(context_tracking.state, IN_USER);
+               __this_cpu_write(context_tracking.state, state);
        }
        local_irq_restore(flags);
 }
+NOKPROBE_SYMBOL(context_tracking_enter);
+EXPORT_SYMBOL_GPL(context_tracking_enter);
+
+void context_tracking_user_enter(void)
+{
+       context_tracking_enter(CONTEXT_USER);
+}
 NOKPROBE_SYMBOL(context_tracking_user_enter);
 
 /**
- * context_tracking_user_exit - Inform the context tracking that the CPU is
- *                              exiting userspace mode and entering the kernel.
+ * context_tracking_exit - Inform the context tracking that the CPU is
+ *                         exiting user or guest mode and entering the kernel.
  *
- * This function must be called after we entered the kernel from userspace
- * before any use of RCU read side critical section. This potentially include
- * any high level kernel code like syscalls, exceptions, signal handling, etc...
+ * This function must be called after we entered the kernel from user or
+ * guest space before any use of RCU read side critical section. This
+ * potentially include any high level kernel code like syscalls, exceptions,
+ * signal handling, etc...
  *
  * This call supports re-entrancy. This way it can be called from any exception
  * handler without needing to know if we came from userspace or not.
  */
-void context_tracking_user_exit(void)
+void context_tracking_exit(enum ctx_state state)
 {
        unsigned long flags;
 
@@ -129,20 +139,29 @@ void context_tracking_user_exit(void)
                return;
 
        local_irq_save(flags);
-       if (__this_cpu_read(context_tracking.state) == IN_USER) {
+       if (__this_cpu_read(context_tracking.state) == state) {
                if (__this_cpu_read(context_tracking.active)) {
                        /*
                         * We are going to run code that may use RCU. Inform
                         * RCU core about that (ie: we may need the tick again).
                         */
                        rcu_user_exit();
-                       vtime_user_exit(current);
-                       trace_user_exit(0);
+                       if (state == CONTEXT_USER) {
+                               vtime_user_exit(current);
+                               trace_user_exit(0);
+                       }
                }
-               __this_cpu_write(context_tracking.state, IN_KERNEL);
+               __this_cpu_write(context_tracking.state, CONTEXT_KERNEL);
        }
        local_irq_restore(flags);
 }
+NOKPROBE_SYMBOL(context_tracking_exit);
+EXPORT_SYMBOL_GPL(context_tracking_exit);
+
+void context_tracking_user_exit(void)
+{
+       context_tracking_exit(CONTEXT_USER);
+}
 NOKPROBE_SYMBOL(context_tracking_user_exit);
 
 /**
index 1972b161c61e98fbe3e3ce003744cf1d2e8c5b1c..94bbe4695232cd2fa2e9c0def32de7fa27644971 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/gfp.h>
 #include <linux/suspend.h>
 #include <linux/lockdep.h>
+#include <linux/tick.h>
 #include <trace/events/power.h>
 
 #include "smpboot.h"
@@ -338,6 +339,8 @@ static int __ref take_cpu_down(void *_param)
                return err;
 
        cpu_notify(CPU_DYING | param->mod, param->hcpu);
+       /* Give up timekeeping duties */
+       tick_handover_do_timer();
        /* Park the stopper thread */
        kthread_park(current);
        return 0;
@@ -408,13 +411,17 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
         *
         * Wait for the stop thread to go away.
         */
-       while (!idle_cpu(cpu))
+       while (!per_cpu(cpu_dead_idle, cpu))
                cpu_relax();
+       smp_mb(); /* Read from cpu_dead_idle before __cpu_die(). */
+       per_cpu(cpu_dead_idle, cpu) = false;
 
+       hotplug_cpu__broadcast_tick_pull(cpu);
        /* This actually kills the CPU. */
        __cpu_die(cpu);
 
        /* CPU is completely dead: tell everyone.  Too late to complain. */
+       tick_cleanup_dead_cpu(cpu);
        cpu_notify_nofail(CPU_DEAD | mod, hcpu);
 
        check_for_tasks(cpu);
@@ -446,6 +453,37 @@ out:
 EXPORT_SYMBOL(cpu_down);
 #endif /*CONFIG_HOTPLUG_CPU*/
 
+/*
+ * Unpark per-CPU smpboot kthreads at CPU-online time.
+ */
+static int smpboot_thread_call(struct notifier_block *nfb,
+                              unsigned long action, void *hcpu)
+{
+       int cpu = (long)hcpu;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+
+       case CPU_ONLINE:
+               smpboot_unpark_threads(cpu);
+               break;
+
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block smpboot_thread_notifier = {
+       .notifier_call = smpboot_thread_call,
+       .priority = CPU_PRI_SMPBOOT,
+};
+
+void __cpuinit smpboot_thread_init(void)
+{
+       register_cpu_notifier(&smpboot_thread_notifier);
+}
+
 /* Requires cpu_add_remove_lock to be held */
 static int _cpu_up(unsigned int cpu, int tasks_frozen)
 {
@@ -485,9 +523,6 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen)
                goto out_notify;
        BUG_ON(!cpu_online(cpu));
 
-       /* Wake the per cpu threads */
-       smpboot_unpark_threads(cpu);
-
        /* Now call notifier in preparation. */
        cpu_notify(CPU_ONLINE | mod, hcpu);
 
index fc7f4748d34a9fe017bd9a42353db7a4095240d2..ee14e3a35a2994399edf176e7775e778c395e592 100644 (file)
@@ -622,6 +622,7 @@ static int generate_sched_domains(cpumask_var_t **domains,
        int csn;                /* how many cpuset ptrs in csa so far */
        int i, j, k;            /* indices for partition finding loops */
        cpumask_var_t *doms;    /* resulting partition; i.e. sched domains */
+       cpumask_var_t non_isolated_cpus;  /* load balanced CPUs */
        struct sched_domain_attr *dattr;  /* attributes for custom domains */
        int ndoms = 0;          /* number of sched domains in result */
        int nslot;              /* next empty doms[] struct cpumask slot */
@@ -631,6 +632,10 @@ static int generate_sched_domains(cpumask_var_t **domains,
        dattr = NULL;
        csa = NULL;
 
+       if (!alloc_cpumask_var(&non_isolated_cpus, GFP_KERNEL))
+               goto done;
+       cpumask_andnot(non_isolated_cpus, cpu_possible_mask, cpu_isolated_map);
+
        /* Special case for the 99% of systems with one, full, sched domain */
        if (is_sched_load_balance(&top_cpuset)) {
                ndoms = 1;
@@ -643,7 +648,8 @@ static int generate_sched_domains(cpumask_var_t **domains,
                        *dattr = SD_ATTR_INIT;
                        update_domain_attr_tree(dattr, &top_cpuset);
                }
-               cpumask_copy(doms[0], top_cpuset.effective_cpus);
+               cpumask_and(doms[0], top_cpuset.effective_cpus,
+                                    non_isolated_cpus);
 
                goto done;
        }
@@ -666,7 +672,8 @@ static int generate_sched_domains(cpumask_var_t **domains,
                 * the corresponding sched domain.
                 */
                if (!cpumask_empty(cp->cpus_allowed) &&
-                   !is_sched_load_balance(cp))
+                   !(is_sched_load_balance(cp) &&
+                     cpumask_intersects(cp->cpus_allowed, non_isolated_cpus)))
                        continue;
 
                if (is_sched_load_balance(cp))
@@ -748,6 +755,7 @@ restart:
 
                        if (apn == b->pn) {
                                cpumask_or(dp, dp, b->effective_cpus);
+                               cpumask_and(dp, dp, non_isolated_cpus);
                                if (dattr)
                                        update_domain_attr_tree(dattr + nslot, b);
 
@@ -760,6 +768,7 @@ restart:
        BUG_ON(nslot != ndoms);
 
 done:
+       free_cpumask_var(non_isolated_cpus);
        kfree(csa);
 
        /*
@@ -2444,20 +2453,12 @@ static struct cpuset *nearest_hardwall_ancestor(struct cpuset *cs)
  * @node: is this an allowed node?
  * @gfp_mask: memory allocation flags
  *
- * If we're in interrupt, yes, we can always allocate.  If __GFP_THISNODE is
- * set, yes, we can always allocate.  If node is in our task's mems_allowed,
- * yes.  If it's not a __GFP_HARDWALL request and this node is in the nearest
- * hardwalled cpuset ancestor to this task's cpuset, yes.  If the task has been
- * OOM killed and has access to memory reserves as specified by the TIF_MEMDIE
- * flag, yes.
+ * If we're in interrupt, yes, we can always allocate.  If @node is set in
+ * current's mems_allowed, yes.  If it's not a __GFP_HARDWALL request and this
+ * node is set in the nearest hardwalled cpuset ancestor to current's cpuset,
+ * yes.  If current has access to memory reserves due to TIF_MEMDIE, yes.
  * Otherwise, no.
  *
- * The __GFP_THISNODE placement logic is really handled elsewhere,
- * by forcibly using a zonelist starting at a specified node, and by
- * (in get_page_from_freelist()) refusing to consider the zones for
- * any node on the zonelist except the first.  By the time any such
- * calls get to this routine, we should just shut up and say 'yes'.
- *
  * GFP_USER allocations are marked with the __GFP_HARDWALL bit,
  * and do not allow allocations outside the current tasks cpuset
  * unless the task has been OOM killed as is marked TIF_MEMDIE.
@@ -2493,7 +2494,7 @@ int __cpuset_node_allowed(int node, gfp_t gfp_mask)
        int allowed;                    /* is allocation in zone z allowed? */
        unsigned long flags;
 
-       if (in_interrupt() || (gfp_mask & __GFP_THISNODE))
+       if (in_interrupt())
                return 1;
        if (node_isset(node, current->mems_allowed))
                return 1;
index 2fabc062716591e960dbab2c9cfc16a755895773..06917d537302b6de0dca1254d5ef6dabb9c6228d 100644 (file)
 #include <linux/syscalls.h>
 #include <linux/anon_inodes.h>
 #include <linux/kernel_stat.h>
+#include <linux/cgroup.h>
 #include <linux/perf_event.h>
 #include <linux/ftrace_event.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/mm_types.h>
-#include <linux/cgroup.h>
 #include <linux/module.h>
 #include <linux/mman.h>
 #include <linux/compat.h>
+#include <linux/bpf.h>
+#include <linux/filter.h>
 
 #include "internal.h"
 
@@ -153,7 +155,7 @@ enum event_type_t {
  */
 struct static_key_deferred perf_sched_events __read_mostly;
 static DEFINE_PER_CPU(atomic_t, perf_cgroup_events);
-static DEFINE_PER_CPU(atomic_t, perf_branch_stack_events);
+static DEFINE_PER_CPU(int, perf_sched_cb_usages);
 
 static atomic_t nr_mmap_events __read_mostly;
 static atomic_t nr_comm_events __read_mostly;
@@ -327,6 +329,11 @@ static inline u64 perf_clock(void)
        return local_clock();
 }
 
+static inline u64 perf_event_clock(struct perf_event *event)
+{
+       return event->clock();
+}
+
 static inline struct perf_cpu_context *
 __get_cpu_context(struct perf_event_context *ctx)
 {
@@ -351,32 +358,6 @@ static void perf_ctx_unlock(struct perf_cpu_context *cpuctx,
 
 #ifdef CONFIG_CGROUP_PERF
 
-/*
- * perf_cgroup_info keeps track of time_enabled for a cgroup.
- * This is a per-cpu dynamically allocated data structure.
- */
-struct perf_cgroup_info {
-       u64                             time;
-       u64                             timestamp;
-};
-
-struct perf_cgroup {
-       struct cgroup_subsys_state      css;
-       struct perf_cgroup_info __percpu *info;
-};
-
-/*
- * Must ensure cgroup is pinned (css_get) before calling
- * this function. In other words, we cannot call this function
- * if there is no cgroup event for the current CPU context.
- */
-static inline struct perf_cgroup *
-perf_cgroup_from_task(struct task_struct *task)
-{
-       return container_of(task_css(task, perf_event_cgrp_id),
-                           struct perf_cgroup, css);
-}
-
 static inline bool
 perf_cgroup_match(struct perf_event *event)
 {
@@ -905,6 +886,15 @@ static void get_ctx(struct perf_event_context *ctx)
        WARN_ON(!atomic_inc_not_zero(&ctx->refcount));
 }
 
+static void free_ctx(struct rcu_head *head)
+{
+       struct perf_event_context *ctx;
+
+       ctx = container_of(head, struct perf_event_context, rcu_head);
+       kfree(ctx->task_ctx_data);
+       kfree(ctx);
+}
+
 static void put_ctx(struct perf_event_context *ctx)
 {
        if (atomic_dec_and_test(&ctx->refcount)) {
@@ -912,7 +902,7 @@ static void put_ctx(struct perf_event_context *ctx)
                        put_ctx(ctx->parent_ctx);
                if (ctx->task)
                        put_task_struct(ctx->task);
-               kfree_rcu(ctx, rcu_head);
+               call_rcu(&ctx->rcu_head, free_ctx);
        }
 }
 
@@ -1239,9 +1229,6 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)
        if (is_cgroup_event(event))
                ctx->nr_cgroups++;
 
-       if (has_branch_stack(event))
-               ctx->nr_branch_stack++;
-
        list_add_rcu(&event->event_entry, &ctx->event_list);
        ctx->nr_events++;
        if (event->attr.inherit_stat)
@@ -1408,9 +1395,6 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
                        cpuctx->cgrp = NULL;
        }
 
-       if (has_branch_stack(event))
-               ctx->nr_branch_stack--;
-
        ctx->nr_events--;
        if (event->attr.inherit_stat)
                ctx->nr_stat--;
@@ -1847,6 +1831,7 @@ static void perf_set_shadow_time(struct perf_event *event,
 #define MAX_INTERRUPTS (~0ULL)
 
 static void perf_log_throttle(struct perf_event *event, int enable);
+static void perf_log_itrace_start(struct perf_event *event);
 
 static int
 event_sched_in(struct perf_event *event,
@@ -1881,6 +1866,12 @@ 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);
+
        if (event->pmu->add(event, PERF_EF_START)) {
                event->state = PERF_EVENT_STATE_INACTIVE;
                event->oncpu = -1;
@@ -1888,10 +1879,6 @@ event_sched_in(struct perf_event *event,
                goto out;
        }
 
-       event->tstamp_running += tstamp - event->tstamp_stopped;
-
-       perf_set_shadow_time(event, ctx, tstamp);
-
        if (!is_software_event(event))
                cpuctx->active_oncpu++;
        if (!ctx->nr_active++)
@@ -2559,6 +2546,9 @@ static void perf_event_context_sched_out(struct task_struct *task, int ctxn,
                        next->perf_event_ctxp[ctxn] = ctx;
                        ctx->task = next;
                        next_ctx->task = task;
+
+                       swap(ctx->task_ctx_data, next_ctx->task_ctx_data);
+
                        do_switch = 0;
 
                        perf_event_sync_stat(ctx, next_ctx);
@@ -2577,6 +2567,56 @@ unlock:
        }
 }
 
+void perf_sched_cb_dec(struct pmu *pmu)
+{
+       this_cpu_dec(perf_sched_cb_usages);
+}
+
+void perf_sched_cb_inc(struct pmu *pmu)
+{
+       this_cpu_inc(perf_sched_cb_usages);
+}
+
+/*
+ * This function provides the context switch callback to the lower code
+ * layer. It is invoked ONLY when the context switch callback is enabled.
+ */
+static void perf_pmu_sched_task(struct task_struct *prev,
+                               struct task_struct *next,
+                               bool sched_in)
+{
+       struct perf_cpu_context *cpuctx;
+       struct pmu *pmu;
+       unsigned long flags;
+
+       if (prev == next)
+               return;
+
+       local_irq_save(flags);
+
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(pmu, &pmus, entry) {
+               if (pmu->sched_task) {
+                       cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
+
+                       perf_ctx_lock(cpuctx, cpuctx->task_ctx);
+
+                       perf_pmu_disable(pmu);
+
+                       pmu->sched_task(cpuctx->task_ctx, sched_in);
+
+                       perf_pmu_enable(pmu);
+
+                       perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
+               }
+       }
+
+       rcu_read_unlock();
+
+       local_irq_restore(flags);
+}
+
 #define for_each_task_context_nr(ctxn)                                 \
        for ((ctxn) = 0; (ctxn) < perf_nr_task_contexts; (ctxn)++)
 
@@ -2596,6 +2636,9 @@ void __perf_event_task_sched_out(struct task_struct *task,
 {
        int ctxn;
 
+       if (__this_cpu_read(perf_sched_cb_usages))
+               perf_pmu_sched_task(task, next, false);
+
        for_each_task_context_nr(ctxn)
                perf_event_context_sched_out(task, ctxn, next);
 
@@ -2754,64 +2797,6 @@ static void perf_event_context_sched_in(struct perf_event_context *ctx,
        perf_ctx_unlock(cpuctx, ctx);
 }
 
-/*
- * When sampling the branck stack in system-wide, it may be necessary
- * to flush the stack on context switch. This happens when the branch
- * stack does not tag its entries with the pid of the current task.
- * Otherwise it becomes impossible to associate a branch entry with a
- * task. This ambiguity is more likely to appear when the branch stack
- * supports priv level filtering and the user sets it to monitor only
- * at the user level (which could be a useful measurement in system-wide
- * mode). In that case, the risk is high of having a branch stack with
- * branch from multiple tasks. Flushing may mean dropping the existing
- * entries or stashing them somewhere in the PMU specific code layer.
- *
- * This function provides the context switch callback to the lower code
- * layer. It is invoked ONLY when there is at least one system-wide context
- * with at least one active event using taken branch sampling.
- */
-static void perf_branch_stack_sched_in(struct task_struct *prev,
-                                      struct task_struct *task)
-{
-       struct perf_cpu_context *cpuctx;
-       struct pmu *pmu;
-       unsigned long flags;
-
-       /* no need to flush branch stack if not changing task */
-       if (prev == task)
-               return;
-
-       local_irq_save(flags);
-
-       rcu_read_lock();
-
-       list_for_each_entry_rcu(pmu, &pmus, entry) {
-               cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
-
-               /*
-                * check if the context has at least one
-                * event using PERF_SAMPLE_BRANCH_STACK
-                */
-               if (cpuctx->ctx.nr_branch_stack > 0
-                   && pmu->flush_branch_stack) {
-
-                       perf_ctx_lock(cpuctx, cpuctx->task_ctx);
-
-                       perf_pmu_disable(pmu);
-
-                       pmu->flush_branch_stack();
-
-                       perf_pmu_enable(pmu);
-
-                       perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
-               }
-       }
-
-       rcu_read_unlock();
-
-       local_irq_restore(flags);
-}
-
 /*
  * Called from scheduler to add the events of the current task
  * with interrupts disabled.
@@ -2844,9 +2829,8 @@ void __perf_event_task_sched_in(struct task_struct *prev,
        if (atomic_read(this_cpu_ptr(&perf_cgroup_events)))
                perf_cgroup_sched_in(prev, task);
 
-       /* check for system-wide branch_stack events */
-       if (atomic_read(this_cpu_ptr(&perf_branch_stack_events)))
-               perf_branch_stack_sched_in(prev, task);
+       if (__this_cpu_read(perf_sched_cb_usages))
+               perf_pmu_sched_task(prev, task, true);
 }
 
 static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count)
@@ -3220,7 +3204,10 @@ static void __perf_event_read(void *info)
 
 static inline u64 perf_event_count(struct perf_event *event)
 {
-       return local64_read(&event->count) + atomic64_read(&event->child_count);
+       if (event->pmu->count)
+               return event->pmu->count(event);
+
+       return __perf_event_count(event);
 }
 
 static u64 perf_event_read(struct perf_event *event)
@@ -3321,12 +3308,15 @@ errout:
  * Returns a matching context with refcount and pincount.
  */
 static struct perf_event_context *
-find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
+find_get_context(struct pmu *pmu, struct task_struct *task,
+               struct perf_event *event)
 {
        struct perf_event_context *ctx, *clone_ctx = NULL;
        struct perf_cpu_context *cpuctx;
+       void *task_ctx_data = NULL;
        unsigned long flags;
        int ctxn, err;
+       int cpu = event->cpu;
 
        if (!task) {
                /* Must be root to operate on a CPU event: */
@@ -3354,11 +3344,24 @@ find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
        if (ctxn < 0)
                goto errout;
 
+       if (event->attach_state & PERF_ATTACH_TASK_DATA) {
+               task_ctx_data = kzalloc(pmu->task_ctx_size, GFP_KERNEL);
+               if (!task_ctx_data) {
+                       err = -ENOMEM;
+                       goto errout;
+               }
+       }
+
 retry:
        ctx = perf_lock_task_context(task, ctxn, &flags);
        if (ctx) {
                clone_ctx = unclone_ctx(ctx);
                ++ctx->pin_count;
+
+               if (task_ctx_data && !ctx->task_ctx_data) {
+                       ctx->task_ctx_data = task_ctx_data;
+                       task_ctx_data = NULL;
+               }
                raw_spin_unlock_irqrestore(&ctx->lock, flags);
 
                if (clone_ctx)
@@ -3369,6 +3372,11 @@ retry:
                if (!ctx)
                        goto errout;
 
+               if (task_ctx_data) {
+                       ctx->task_ctx_data = task_ctx_data;
+                       task_ctx_data = NULL;
+               }
+
                err = 0;
                mutex_lock(&task->perf_event_mutex);
                /*
@@ -3395,13 +3403,16 @@ retry:
                }
        }
 
+       kfree(task_ctx_data);
        return ctx;
 
 errout:
+       kfree(task_ctx_data);
        return ERR_PTR(err);
 }
 
 static void perf_event_free_filter(struct perf_event *event);
+static void perf_event_free_bpf_prog(struct perf_event *event);
 
 static void free_event_rcu(struct rcu_head *head)
 {
@@ -3411,10 +3422,10 @@ static void free_event_rcu(struct rcu_head *head)
        if (event->ns)
                put_pid_ns(event->ns);
        perf_event_free_filter(event);
+       perf_event_free_bpf_prog(event);
        kfree(event);
 }
 
-static void ring_buffer_put(struct ring_buffer *rb);
 static void ring_buffer_attach(struct perf_event *event,
                               struct ring_buffer *rb);
 
@@ -3423,10 +3434,6 @@ static void unaccount_event_cpu(struct perf_event *event, int cpu)
        if (event->parent)
                return;
 
-       if (has_branch_stack(event)) {
-               if (!(event->attach_state & PERF_ATTACH_TASK))
-                       atomic_dec(&per_cpu(perf_branch_stack_events, cpu));
-       }
        if (is_cgroup_event(event))
                atomic_dec(&per_cpu(perf_cgroup_events, cpu));
 }
@@ -3454,6 +3461,91 @@ static void unaccount_event(struct perf_event *event)
        unaccount_event_cpu(event, event->cpu);
 }
 
+/*
+ * The following implement mutual exclusion of events on "exclusive" pmus
+ * (PERF_PMU_CAP_EXCLUSIVE). Such pmus can only have one event scheduled
+ * at a time, so we disallow creating events that might conflict, namely:
+ *
+ *  1) cpu-wide events in the presence of per-task events,
+ *  2) per-task events in the presence of cpu-wide events,
+ *  3) two matching events on the same context.
+ *
+ * The former two cases are handled in the allocation path (perf_event_alloc(),
+ * __free_event()), the latter -- before the first perf_install_in_context().
+ */
+static int exclusive_event_init(struct perf_event *event)
+{
+       struct pmu *pmu = event->pmu;
+
+       if (!(pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE))
+               return 0;
+
+       /*
+        * Prevent co-existence of per-task and cpu-wide events on the
+        * same exclusive pmu.
+        *
+        * Negative pmu::exclusive_cnt means there are cpu-wide
+        * events on this "exclusive" pmu, positive means there are
+        * per-task events.
+        *
+        * Since this is called in perf_event_alloc() path, event::ctx
+        * doesn't exist yet; it is, however, safe to use PERF_ATTACH_TASK
+        * to mean "per-task event", because unlike other attach states it
+        * never gets cleared.
+        */
+       if (event->attach_state & PERF_ATTACH_TASK) {
+               if (!atomic_inc_unless_negative(&pmu->exclusive_cnt))
+                       return -EBUSY;
+       } else {
+               if (!atomic_dec_unless_positive(&pmu->exclusive_cnt))
+                       return -EBUSY;
+       }
+
+       return 0;
+}
+
+static void exclusive_event_destroy(struct perf_event *event)
+{
+       struct pmu *pmu = event->pmu;
+
+       if (!(pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE))
+               return;
+
+       /* see comment in exclusive_event_init() */
+       if (event->attach_state & PERF_ATTACH_TASK)
+               atomic_dec(&pmu->exclusive_cnt);
+       else
+               atomic_inc(&pmu->exclusive_cnt);
+}
+
+static bool exclusive_event_match(struct perf_event *e1, struct perf_event *e2)
+{
+       if ((e1->pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE) &&
+           (e1->cpu == e2->cpu ||
+            e1->cpu == -1 ||
+            e2->cpu == -1))
+               return true;
+       return false;
+}
+
+/* Called under the same ctx::mutex as perf_install_in_context() */
+static bool exclusive_event_installable(struct perf_event *event,
+                                       struct perf_event_context *ctx)
+{
+       struct perf_event *iter_event;
+       struct pmu *pmu = event->pmu;
+
+       if (!(pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE))
+               return true;
+
+       list_for_each_entry(iter_event, &ctx->event_list, event_entry) {
+               if (exclusive_event_match(iter_event, event))
+                       return false;
+       }
+
+       return true;
+}
+
 static void __free_event(struct perf_event *event)
 {
        if (!event->parent) {
@@ -3467,8 +3559,10 @@ static void __free_event(struct perf_event *event)
        if (event->ctx)
                put_ctx(event->ctx);
 
-       if (event->pmu)
+       if (event->pmu) {
+               exclusive_event_destroy(event);
                module_put(event->pmu->module);
+       }
 
        call_rcu(&event->rcu_head, free_event_rcu);
 }
@@ -3927,6 +4021,7 @@ static inline int perf_fget_light(int fd, struct fd *p)
 static int perf_event_set_output(struct perf_event *event,
                                 struct perf_event *output_event);
 static int perf_event_set_filter(struct perf_event *event, void __user *arg);
+static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd);
 
 static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned long arg)
 {
@@ -3980,6 +4075,9 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
        case PERF_EVENT_IOC_SET_FILTER:
                return perf_event_set_filter(event, (void __user *)arg);
 
+       case PERF_EVENT_IOC_SET_BPF:
+               return perf_event_set_bpf_prog(event, arg);
+
        default:
                return -ENOTTY;
        }
@@ -4096,6 +4194,8 @@ static void perf_event_init_userpage(struct perf_event *event)
        /* Allow new userspace to detect that bit 0 is deprecated */
        userpg->cap_bit0_is_deprecated = 1;
        userpg->size = offsetof(struct perf_event_mmap_page, __reserved);
+       userpg->data_offset = PAGE_SIZE;
+       userpg->data_size = perf_data_size(rb);
 
 unlock:
        rcu_read_unlock();
@@ -4263,7 +4363,7 @@ static void rb_free_rcu(struct rcu_head *rcu_head)
        rb_free(rb);
 }
 
-static struct ring_buffer *ring_buffer_get(struct perf_event *event)
+struct ring_buffer *ring_buffer_get(struct perf_event *event)
 {
        struct ring_buffer *rb;
 
@@ -4278,7 +4378,7 @@ static struct ring_buffer *ring_buffer_get(struct perf_event *event)
        return rb;
 }
 
-static void ring_buffer_put(struct ring_buffer *rb)
+void ring_buffer_put(struct ring_buffer *rb)
 {
        if (!atomic_dec_and_test(&rb->refcount))
                return;
@@ -4295,6 +4395,9 @@ static void perf_mmap_open(struct vm_area_struct *vma)
        atomic_inc(&event->mmap_count);
        atomic_inc(&event->rb->mmap_count);
 
+       if (vma->vm_pgoff)
+               atomic_inc(&event->rb->aux_mmap_count);
+
        if (event->pmu->event_mapped)
                event->pmu->event_mapped(event);
 }
@@ -4319,6 +4422,20 @@ static void perf_mmap_close(struct vm_area_struct *vma)
        if (event->pmu->event_unmapped)
                event->pmu->event_unmapped(event);
 
+       /*
+        * rb->aux_mmap_count will always drop before rb->mmap_count and
+        * event->mmap_count, so it is ok to use event->mmap_mutex to
+        * serialize with perf_mmap here.
+        */
+       if (rb_has_aux(rb) && vma->vm_pgoff == rb->aux_pgoff &&
+           atomic_dec_and_mutex_lock(&rb->aux_mmap_count, &event->mmap_mutex)) {
+               atomic_long_sub(rb->aux_nr_pages, &mmap_user->locked_vm);
+               vma->vm_mm->pinned_vm -= rb->aux_mmap_locked;
+
+               rb_free_aux(rb);
+               mutex_unlock(&event->mmap_mutex);
+       }
+
        atomic_dec(&rb->mmap_count);
 
        if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex))
@@ -4392,7 +4509,7 @@ out_put:
 
 static const struct vm_operations_struct perf_mmap_vmops = {
        .open           = perf_mmap_open,
-       .close          = perf_mmap_close,
+       .close          = perf_mmap_close, /* non mergable */
        .fault          = perf_mmap_fault,
        .page_mkwrite   = perf_mmap_fault,
 };
@@ -4403,10 +4520,10 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
        unsigned long user_locked, user_lock_limit;
        struct user_struct *user = current_user();
        unsigned long locked, lock_limit;
-       struct ring_buffer *rb;
+       struct ring_buffer *rb = NULL;
        unsigned long vma_size;
        unsigned long nr_pages;
-       long user_extra, extra;
+       long user_extra = 0, extra = 0;
        int ret = 0, flags = 0;
 
        /*
@@ -4421,7 +4538,66 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
                return -EINVAL;
 
        vma_size = vma->vm_end - vma->vm_start;
-       nr_pages = (vma_size / PAGE_SIZE) - 1;
+
+       if (vma->vm_pgoff == 0) {
+               nr_pages = (vma_size / PAGE_SIZE) - 1;
+       } else {
+               /*
+                * AUX area mapping: if rb->aux_nr_pages != 0, it's already
+                * mapped, all subsequent mappings should have the same size
+                * and offset. Must be above the normal perf buffer.
+                */
+               u64 aux_offset, aux_size;
+
+               if (!event->rb)
+                       return -EINVAL;
+
+               nr_pages = vma_size / PAGE_SIZE;
+
+               mutex_lock(&event->mmap_mutex);
+               ret = -EINVAL;
+
+               rb = event->rb;
+               if (!rb)
+                       goto aux_unlock;
+
+               aux_offset = ACCESS_ONCE(rb->user_page->aux_offset);
+               aux_size = ACCESS_ONCE(rb->user_page->aux_size);
+
+               if (aux_offset < perf_data_size(rb) + PAGE_SIZE)
+                       goto aux_unlock;
+
+               if (aux_offset != vma->vm_pgoff << PAGE_SHIFT)
+                       goto aux_unlock;
+
+               /* already mapped with a different offset */
+               if (rb_has_aux(rb) && rb->aux_pgoff != vma->vm_pgoff)
+                       goto aux_unlock;
+
+               if (aux_size != vma_size || aux_size != nr_pages * PAGE_SIZE)
+                       goto aux_unlock;
+
+               /* already mapped with a different size */
+               if (rb_has_aux(rb) && rb->aux_nr_pages != nr_pages)
+                       goto aux_unlock;
+
+               if (!is_power_of_2(nr_pages))
+                       goto aux_unlock;
+
+               if (!atomic_inc_not_zero(&rb->mmap_count))
+                       goto aux_unlock;
+
+               if (rb_has_aux(rb)) {
+                       atomic_inc(&rb->aux_mmap_count);
+                       ret = 0;
+                       goto unlock;
+               }
+
+               atomic_set(&rb->aux_mmap_count, 1);
+               user_extra = nr_pages;
+
+               goto accounting;
+       }
 
        /*
         * If we have rb pages ensure they're a power-of-two number, so we
@@ -4433,9 +4609,6 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
        if (vma_size != PAGE_SIZE * (1 + nr_pages))
                return -EINVAL;
 
-       if (vma->vm_pgoff != 0)
-               return -EINVAL;
-
        WARN_ON_ONCE(event->ctx->parent_ctx);
 again:
        mutex_lock(&event->mmap_mutex);
@@ -4459,6 +4632,8 @@ again:
        }
 
        user_extra = nr_pages + 1;
+
+accounting:
        user_lock_limit = sysctl_perf_event_mlock >> (PAGE_SHIFT - 10);
 
        /*
@@ -4468,7 +4643,6 @@ again:
 
        user_locked = atomic_long_read(&user->locked_vm) + user_extra;
 
-       extra = 0;
        if (user_locked > user_lock_limit)
                extra = user_locked - user_lock_limit;
 
@@ -4482,35 +4656,46 @@ again:
                goto unlock;
        }
 
-       WARN_ON(event->rb);
+       WARN_ON(!rb && event->rb);
 
        if (vma->vm_flags & VM_WRITE)
                flags |= RING_BUFFER_WRITABLE;
 
-       rb = rb_alloc(nr_pages, 
-               event->attr.watermark ? event->attr.wakeup_watermark : 0,
-               event->cpu, flags);
-
        if (!rb) {
-               ret = -ENOMEM;
-               goto unlock;
-       }
+               rb = rb_alloc(nr_pages,
+                             event->attr.watermark ? event->attr.wakeup_watermark : 0,
+                             event->cpu, flags);
 
-       atomic_set(&rb->mmap_count, 1);
-       rb->mmap_locked = extra;
-       rb->mmap_user = get_current_user();
+               if (!rb) {
+                       ret = -ENOMEM;
+                       goto unlock;
+               }
 
-       atomic_long_add(user_extra, &user->locked_vm);
-       vma->vm_mm->pinned_vm += extra;
+               atomic_set(&rb->mmap_count, 1);
+               rb->mmap_user = get_current_user();
+               rb->mmap_locked = extra;
 
-       ring_buffer_attach(event, rb);
+               ring_buffer_attach(event, rb);
 
-       perf_event_init_userpage(event);
-       perf_event_update_userpage(event);
+               perf_event_init_userpage(event);
+               perf_event_update_userpage(event);
+       } else {
+               ret = rb_alloc_aux(rb, event, vma->vm_pgoff, nr_pages,
+                                  event->attr.aux_watermark, flags);
+               if (!ret)
+                       rb->aux_mmap_locked = extra;
+       }
 
 unlock:
-       if (!ret)
+       if (!ret) {
+               atomic_long_add(user_extra, &user->locked_vm);
+               vma->vm_mm->pinned_vm += extra;
+
                atomic_inc(&event->mmap_count);
+       } else if (rb) {
+               atomic_dec(&rb->mmap_count);
+       }
+aux_unlock:
        mutex_unlock(&event->mmap_mutex);
 
        /*
@@ -4766,7 +4951,7 @@ static void __perf_event_header__init_id(struct perf_event_header *header,
        }
 
        if (sample_type & PERF_SAMPLE_TIME)
-               data->time = perf_clock();
+               data->time = perf_event_clock(event);
 
        if (sample_type & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER))
                data->id = primary_event_id(event);
@@ -5344,6 +5529,8 @@ static void perf_event_task_output(struct perf_event *event,
        task_event->event_id.tid = perf_event_tid(event, task);
        task_event->event_id.ptid = perf_event_tid(event, current);
 
+       task_event->event_id.time = perf_event_clock(event);
+
        perf_output_put(&handle, task_event->event_id);
 
        perf_event__output_id_sample(event, &handle, &sample);
@@ -5377,7 +5564,7 @@ static void perf_event_task(struct task_struct *task,
                        /* .ppid */
                        /* .tid  */
                        /* .ptid */
-                       .time = perf_clock(),
+                       /* .time */
                },
        };
 
@@ -5732,6 +5919,40 @@ void perf_event_mmap(struct vm_area_struct *vma)
        perf_event_mmap_event(&mmap_event);
 }
 
+void perf_event_aux_event(struct perf_event *event, unsigned long head,
+                         unsigned long size, u64 flags)
+{
+       struct perf_output_handle handle;
+       struct perf_sample_data sample;
+       struct perf_aux_event {
+               struct perf_event_header        header;
+               u64                             offset;
+               u64                             size;
+               u64                             flags;
+       } rec = {
+               .header = {
+                       .type = PERF_RECORD_AUX,
+                       .misc = 0,
+                       .size = sizeof(rec),
+               },
+               .offset         = head,
+               .size           = size,
+               .flags          = flags,
+       };
+       int ret;
+
+       perf_event_header__init_id(&rec.header, &sample, event);
+       ret = perf_output_begin(&handle, event, rec.header.size);
+
+       if (ret)
+               return;
+
+       perf_output_put(&handle, rec);
+       perf_event__output_id_sample(event, &handle, &sample);
+
+       perf_output_end(&handle);
+}
+
 /*
  * IRQ throttle logging
  */
@@ -5753,7 +5974,7 @@ static void perf_log_throttle(struct perf_event *event, int enable)
                        .misc = 0,
                        .size = sizeof(throttle_event),
                },
-               .time           = perf_clock(),
+               .time           = perf_event_clock(event),
                .id             = primary_event_id(event),
                .stream_id      = event->id,
        };
@@ -5773,6 +5994,44 @@ static void perf_log_throttle(struct perf_event *event, int enable)
        perf_output_end(&handle);
 }
 
+static void perf_log_itrace_start(struct perf_event *event)
+{
+       struct perf_output_handle handle;
+       struct perf_sample_data sample;
+       struct perf_aux_event {
+               struct perf_event_header        header;
+               u32                             pid;
+               u32                             tid;
+       } rec;
+       int ret;
+
+       if (event->parent)
+               event = event->parent;
+
+       if (!(event->pmu->capabilities & PERF_PMU_CAP_ITRACE) ||
+           event->hw.itrace_started)
+               return;
+
+       event->hw.itrace_started = 1;
+
+       rec.header.type = PERF_RECORD_ITRACE_START;
+       rec.header.misc = 0;
+       rec.header.size = sizeof(rec);
+       rec.pid = perf_event_pid(event, current);
+       rec.tid = perf_event_tid(event, current);
+
+       perf_event_header__init_id(&rec.header, &sample, event);
+       ret = perf_output_begin(&handle, event, rec.header.size);
+
+       if (ret)
+               return;
+
+       perf_output_put(&handle, rec);
+       perf_event__output_id_sample(event, &handle, &sample);
+
+       perf_output_end(&handle);
+}
+
 /*
  * Generic event overflow handling, sampling.
  */
@@ -6133,6 +6392,7 @@ static int perf_swevent_add(struct perf_event *event, int flags)
        }
 
        hlist_add_head_rcu(&event->hlist_entry, head);
+       perf_event_update_userpage(event);
 
        return 0;
 }
@@ -6296,6 +6556,8 @@ static int perf_swevent_init(struct perf_event *event)
 static struct pmu perf_swevent = {
        .task_ctx_nr    = perf_sw_context,
 
+       .capabilities   = PERF_PMU_CAP_NO_NMI,
+
        .event_init     = perf_swevent_init,
        .add            = perf_swevent_add,
        .del            = perf_swevent_del,
@@ -6449,6 +6711,49 @@ static void perf_event_free_filter(struct perf_event *event)
        ftrace_profile_free_filter(event);
 }
 
+static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd)
+{
+       struct bpf_prog *prog;
+
+       if (event->attr.type != PERF_TYPE_TRACEPOINT)
+               return -EINVAL;
+
+       if (event->tp_event->prog)
+               return -EEXIST;
+
+       if (!(event->tp_event->flags & TRACE_EVENT_FL_KPROBE))
+               /* bpf programs can only be attached to kprobes */
+               return -EINVAL;
+
+       prog = bpf_prog_get(prog_fd);
+       if (IS_ERR(prog))
+               return PTR_ERR(prog);
+
+       if (prog->aux->prog_type != BPF_PROG_TYPE_KPROBE) {
+               /* valid fd, but invalid bpf program type */
+               bpf_prog_put(prog);
+               return -EINVAL;
+       }
+
+       event->tp_event->prog = prog;
+
+       return 0;
+}
+
+static void perf_event_free_bpf_prog(struct perf_event *event)
+{
+       struct bpf_prog *prog;
+
+       if (!event->tp_event)
+               return;
+
+       prog = event->tp_event->prog;
+       if (prog) {
+               event->tp_event->prog = NULL;
+               bpf_prog_put(prog);
+       }
+}
+
 #else
 
 static inline void perf_tp_register(void)
@@ -6464,6 +6769,14 @@ static void perf_event_free_filter(struct perf_event *event)
 {
 }
 
+static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd)
+{
+       return -ENOENT;
+}
+
+static void perf_event_free_bpf_prog(struct perf_event *event)
+{
+}
 #endif /* CONFIG_EVENT_TRACING */
 
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
@@ -6602,6 +6915,7 @@ static int cpu_clock_event_add(struct perf_event *event, int flags)
 {
        if (flags & PERF_EF_START)
                cpu_clock_event_start(event, flags);
+       perf_event_update_userpage(event);
 
        return 0;
 }
@@ -6638,6 +6952,8 @@ static int cpu_clock_event_init(struct perf_event *event)
 static struct pmu perf_cpu_clock = {
        .task_ctx_nr    = perf_sw_context,
 
+       .capabilities   = PERF_PMU_CAP_NO_NMI,
+
        .event_init     = cpu_clock_event_init,
        .add            = cpu_clock_event_add,
        .del            = cpu_clock_event_del,
@@ -6676,6 +6992,7 @@ static int task_clock_event_add(struct perf_event *event, int flags)
 {
        if (flags & PERF_EF_START)
                task_clock_event_start(event, flags);
+       perf_event_update_userpage(event);
 
        return 0;
 }
@@ -6716,6 +7033,8 @@ static int task_clock_event_init(struct perf_event *event)
 static struct pmu perf_task_clock = {
        .task_ctx_nr    = perf_sw_context,
 
+       .capabilities   = PERF_PMU_CAP_NO_NMI,
+
        .event_init     = task_clock_event_init,
        .add            = task_clock_event_add,
        .del            = task_clock_event_del,
@@ -6993,6 +7312,7 @@ got_cpu_context:
                pmu->event_idx = perf_event_idx_default;
 
        list_add_rcu(&pmu->entry, &pmus);
+       atomic_set(&pmu->exclusive_cnt, 0);
        ret = 0;
 unlock:
        mutex_unlock(&pmus_lock);
@@ -7037,12 +7357,23 @@ EXPORT_SYMBOL_GPL(perf_pmu_unregister);
 
 static int perf_try_init_event(struct pmu *pmu, struct perf_event *event)
 {
+       struct perf_event_context *ctx = NULL;
        int ret;
 
        if (!try_module_get(pmu->module))
                return -ENODEV;
+
+       if (event->group_leader != event) {
+               ctx = perf_event_ctx_lock(event->group_leader);
+               BUG_ON(!ctx);
+       }
+
        event->pmu = pmu;
        ret = pmu->event_init(event);
+
+       if (ctx)
+               perf_event_ctx_unlock(event->group_leader, ctx);
+
        if (ret)
                module_put(pmu->module);
 
@@ -7089,10 +7420,6 @@ static void account_event_cpu(struct perf_event *event, int cpu)
        if (event->parent)
                return;
 
-       if (has_branch_stack(event)) {
-               if (!(event->attach_state & PERF_ATTACH_TASK))
-                       atomic_inc(&per_cpu(perf_branch_stack_events, cpu));
-       }
        if (is_cgroup_event(event))
                atomic_inc(&per_cpu(perf_cgroup_events, cpu));
 }
@@ -7131,7 +7458,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
                 struct perf_event *group_leader,
                 struct perf_event *parent_event,
                 perf_overflow_handler_t overflow_handler,
-                void *context)
+                void *context, int cgroup_fd)
 {
        struct pmu *pmu;
        struct perf_event *event;
@@ -7186,18 +7513,18 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
 
        if (task) {
                event->attach_state = PERF_ATTACH_TASK;
-
-               if (attr->type == PERF_TYPE_TRACEPOINT)
-                       event->hw.tp_target = task;
-#ifdef CONFIG_HAVE_HW_BREAKPOINT
                /*
-                * hw_breakpoint is a bit difficult here..
+                * XXX pmu::event_init needs to know what task to account to
+                * and we cannot use the ctx information because we need the
+                * pmu before we get a ctx.
                 */
-               else if (attr->type == PERF_TYPE_BREAKPOINT)
-                       event->hw.bp_target = task;
-#endif
+               event->hw.target = task;
        }
 
+       event->clock = &local_clock;
+       if (parent_event)
+               event->clock = parent_event->clock;
+
        if (!overflow_handler && parent_event) {
                overflow_handler = parent_event->overflow_handler;
                context = parent_event->overflow_handler_context;
@@ -7224,6 +7551,15 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
        if (attr->inherit && (attr->read_format & PERF_FORMAT_GROUP))
                goto err_ns;
 
+       if (!has_branch_stack(event))
+               event->attr.branch_sample_type = 0;
+
+       if (cgroup_fd != -1) {
+               err = perf_cgroup_connect(cgroup_fd, event, attr, group_leader);
+               if (err)
+                       goto err_ns;
+       }
+
        pmu = perf_init_event(event);
        if (!pmu)
                goto err_ns;
@@ -7232,21 +7568,30 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
                goto err_ns;
        }
 
+       err = exclusive_event_init(event);
+       if (err)
+               goto err_pmu;
+
        if (!event->parent) {
                if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
                        err = get_callchain_buffers();
                        if (err)
-                               goto err_pmu;
+                               goto err_per_task;
                }
        }
 
        return event;
 
+err_per_task:
+       exclusive_event_destroy(event);
+
 err_pmu:
        if (event->destroy)
                event->destroy(event);
        module_put(pmu->module);
 err_ns:
+       if (is_cgroup_event(event))
+               perf_detach_cgroup(event);
        if (event->ns)
                put_pid_ns(event->ns);
        kfree(event);
@@ -7409,6 +7754,19 @@ perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
        if (output_event->cpu == -1 && output_event->ctx != event->ctx)
                goto out;
 
+       /*
+        * Mixing clocks in the same buffer is trouble you don't need.
+        */
+       if (output_event->clock != event->clock)
+               goto out;
+
+       /*
+        * If both events generate aux data, they must be on the same PMU
+        */
+       if (has_aux(event) && has_aux(output_event) &&
+           event->pmu != output_event->pmu)
+               goto out;
+
 set:
        mutex_lock(&event->mmap_mutex);
        /* Can't redirect output if we've got an active mmap() */
@@ -7441,6 +7799,43 @@ static void mutex_lock_double(struct mutex *a, struct mutex *b)
        mutex_lock_nested(b, SINGLE_DEPTH_NESTING);
 }
 
+static int perf_event_set_clock(struct perf_event *event, clockid_t clk_id)
+{
+       bool nmi_safe = false;
+
+       switch (clk_id) {
+       case CLOCK_MONOTONIC:
+               event->clock = &ktime_get_mono_fast_ns;
+               nmi_safe = true;
+               break;
+
+       case CLOCK_MONOTONIC_RAW:
+               event->clock = &ktime_get_raw_fast_ns;
+               nmi_safe = true;
+               break;
+
+       case CLOCK_REALTIME:
+               event->clock = &ktime_get_real_ns;
+               break;
+
+       case CLOCK_BOOTTIME:
+               event->clock = &ktime_get_boot_ns;
+               break;
+
+       case CLOCK_TAI:
+               event->clock = &ktime_get_tai_ns;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       if (!nmi_safe && !(event->pmu->capabilities & PERF_PMU_CAP_NO_NMI))
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
  * sys_perf_event_open - open a performance event, associate it to a task/cpu
  *
@@ -7465,6 +7860,7 @@ SYSCALL_DEFINE5(perf_event_open,
        int move_group = 0;
        int err;
        int f_flags = O_RDWR;
+       int cgroup_fd = -1;
 
        /* for future expandability... */
        if (flags & ~PERF_FLAG_ALL)
@@ -7530,21 +7926,16 @@ SYSCALL_DEFINE5(perf_event_open,
 
        get_online_cpus();
 
+       if (flags & PERF_FLAG_PID_CGROUP)
+               cgroup_fd = pid;
+
        event = perf_event_alloc(&attr, cpu, task, group_leader, NULL,
-                                NULL, NULL);
+                                NULL, NULL, cgroup_fd);
        if (IS_ERR(event)) {
                err = PTR_ERR(event);
                goto err_cpus;
        }
 
-       if (flags & PERF_FLAG_PID_CGROUP) {
-               err = perf_cgroup_connect(pid, event, &attr, group_leader);
-               if (err) {
-                       __free_event(event);
-                       goto err_cpus;
-               }
-       }
-
        if (is_sampling_event(event)) {
                if (event->pmu->capabilities & PERF_PMU_CAP_NO_INTERRUPT) {
                        err = -ENOTSUPP;
@@ -7560,6 +7951,12 @@ SYSCALL_DEFINE5(perf_event_open,
         */
        pmu = event->pmu;
 
+       if (attr.use_clockid) {
+               err = perf_event_set_clock(event, attr.clockid);
+               if (err)
+                       goto err_alloc;
+       }
+
        if (group_leader &&
            (is_software_event(event) != is_software_event(group_leader))) {
                if (is_software_event(event)) {
@@ -7586,12 +7983,17 @@ SYSCALL_DEFINE5(perf_event_open,
        /*
         * Get the target context (task or percpu):
         */
-       ctx = find_get_context(pmu, task, event->cpu);
+       ctx = find_get_context(pmu, task, event);
        if (IS_ERR(ctx)) {
                err = PTR_ERR(ctx);
                goto err_alloc;
        }
 
+       if ((pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE) && group_leader) {
+               err = -EBUSY;
+               goto err_context;
+       }
+
        if (task) {
                put_task_struct(task);
                task = NULL;
@@ -7609,6 +8011,11 @@ SYSCALL_DEFINE5(perf_event_open,
                 */
                if (group_leader->group_leader != group_leader)
                        goto err_context;
+
+               /* All events in a group should have the same clock */
+               if (group_leader->clock != event->clock)
+                       goto err_context;
+
                /*
                 * Do not allow to attach to a group in a different
                 * task or CPU context:
@@ -7709,6 +8116,13 @@ SYSCALL_DEFINE5(perf_event_open,
                get_ctx(ctx);
        }
 
+       if (!exclusive_event_installable(event, ctx)) {
+               err = -EBUSY;
+               mutex_unlock(&ctx->mutex);
+               fput(event_file);
+               goto err_context;
+       }
+
        perf_install_in_context(ctx, event, event->cpu);
        perf_unpin_context(ctx);
 
@@ -7781,7 +8195,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
         */
 
        event = perf_event_alloc(attr, cpu, task, NULL, NULL,
-                                overflow_handler, context);
+                                overflow_handler, context, -1);
        if (IS_ERR(event)) {
                err = PTR_ERR(event);
                goto err;
@@ -7792,7 +8206,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
 
        account_event(event);
 
-       ctx = find_get_context(event->pmu, task, cpu);
+       ctx = find_get_context(event->pmu, task, event);
        if (IS_ERR(ctx)) {
                err = PTR_ERR(ctx);
                goto err_free;
@@ -7800,6 +8214,14 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
 
        WARN_ON_ONCE(ctx->parent_ctx);
        mutex_lock(&ctx->mutex);
+       if (!exclusive_event_installable(event, ctx)) {
+               mutex_unlock(&ctx->mutex);
+               perf_unpin_context(ctx);
+               put_ctx(ctx);
+               err = -EBUSY;
+               goto err_free;
+       }
+
        perf_install_in_context(ctx, event, cpu);
        perf_unpin_context(ctx);
        mutex_unlock(&ctx->mutex);
@@ -8142,7 +8564,7 @@ inherit_event(struct perf_event *parent_event,
                                           parent_event->cpu,
                                           child,
                                           group_leader, parent_event,
-                                          NULL, NULL);
+                                          NULL, NULL, -1);
        if (IS_ERR(child_event))
                return child_event;
 
index 9803a6600d499681848290f9eff6254e53364dbf..92ce5f4ccc264e01a5551965d173e39e41392143 100644 (file)
@@ -116,12 +116,12 @@ static unsigned int max_task_bp_pinned(int cpu, enum bp_type_idx type)
  */
 static int task_bp_pinned(int cpu, struct perf_event *bp, enum bp_type_idx type)
 {
-       struct task_struct *tsk = bp->hw.bp_target;
+       struct task_struct *tsk = bp->hw.target;
        struct perf_event *iter;
        int count = 0;
 
        list_for_each_entry(iter, &bp_task_head, hw.bp_list) {
-               if (iter->hw.bp_target == tsk &&
+               if (iter->hw.target == tsk &&
                    find_slot_idx(iter) == type &&
                    (iter->cpu < 0 || cpu == iter->cpu))
                        count += hw_breakpoint_weight(iter);
@@ -153,7 +153,7 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp,
                int nr;
 
                nr = info->cpu_pinned;
-               if (!bp->hw.bp_target)
+               if (!bp->hw.target)
                        nr += max_task_bp_pinned(cpu, type);
                else
                        nr += task_bp_pinned(cpu, bp, type);
@@ -210,7 +210,7 @@ toggle_bp_slot(struct perf_event *bp, bool enable, enum bp_type_idx type,
                weight = -weight;
 
        /* Pinned counter cpu profiling */
-       if (!bp->hw.bp_target) {
+       if (!bp->hw.target) {
                get_bp_info(bp->cpu, type)->cpu_pinned += weight;
                return;
        }
index 569b218782ad6f52053a21495c893935dcde5b10..9f6ce9ba4a04330d689345bc312fc765f0804a31 100644 (file)
@@ -27,6 +27,7 @@ struct ring_buffer {
        local_t                         lost;           /* nr records lost   */
 
        long                            watermark;      /* wakeup watermark  */
+       long                            aux_watermark;
        /* poll crap */
        spinlock_t                      event_lock;
        struct list_head                event_list;
@@ -35,6 +36,20 @@ struct ring_buffer {
        unsigned long                   mmap_locked;
        struct user_struct              *mmap_user;
 
+       /* AUX area */
+       local_t                         aux_head;
+       local_t                         aux_nest;
+       local_t                         aux_wakeup;
+       unsigned long                   aux_pgoff;
+       int                             aux_nr_pages;
+       int                             aux_overwrite;
+       atomic_t                        aux_mmap_count;
+       unsigned long                   aux_mmap_locked;
+       void                            (*free_aux)(void *);
+       atomic_t                        aux_refcount;
+       void                            **aux_pages;
+       void                            *aux_priv;
+
        struct perf_event_mmap_page     *user_page;
        void                            *data_pages[0];
 };
@@ -43,6 +58,19 @@ extern void rb_free(struct ring_buffer *rb);
 extern struct ring_buffer *
 rb_alloc(int nr_pages, long watermark, int cpu, int flags);
 extern void perf_event_wakeup(struct perf_event *event);
+extern int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event,
+                       pgoff_t pgoff, int nr_pages, long watermark, int flags);
+extern void rb_free_aux(struct ring_buffer *rb);
+extern struct ring_buffer *ring_buffer_get(struct perf_event *event);
+extern void ring_buffer_put(struct ring_buffer *rb);
+
+static inline bool rb_has_aux(struct ring_buffer *rb)
+{
+       return !!rb->aux_nr_pages;
+}
+
+void perf_event_aux_event(struct perf_event *event, unsigned long head,
+                         unsigned long size, u64 flags);
 
 extern void
 perf_event_header__init_id(struct perf_event_header *header,
@@ -81,6 +109,11 @@ static inline unsigned long perf_data_size(struct ring_buffer *rb)
        return rb->nr_pages << (PAGE_SHIFT + page_order(rb));
 }
 
+static inline unsigned long perf_aux_size(struct ring_buffer *rb)
+{
+       return rb->aux_nr_pages << PAGE_SHIFT;
+}
+
 #define DEFINE_OUTPUT_COPY(func_name, memcpy_func)                     \
 static inline unsigned long                                            \
 func_name(struct perf_output_handle *handle,                           \
index eadb95ce7aace86925b9639399e29feb5be33323..232f00f273cbe419d2738d5f83465dd96529ee17 100644 (file)
@@ -243,14 +243,317 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
        spin_lock_init(&rb->event_lock);
 }
 
+/*
+ * This is called before hardware starts writing to the AUX area to
+ * obtain an output handle and make sure there's room in the buffer.
+ * When the capture completes, call perf_aux_output_end() to commit
+ * the recorded data to the buffer.
+ *
+ * The ordering is similar to that of perf_output_{begin,end}, with
+ * the exception of (B), which should be taken care of by the pmu
+ * driver, since ordering rules will differ depending on hardware.
+ */
+void *perf_aux_output_begin(struct perf_output_handle *handle,
+                           struct perf_event *event)
+{
+       struct perf_event *output_event = event;
+       unsigned long aux_head, aux_tail;
+       struct ring_buffer *rb;
+
+       if (output_event->parent)
+               output_event = output_event->parent;
+
+       /*
+        * Since this will typically be open across pmu::add/pmu::del, we
+        * grab ring_buffer's refcount instead of holding rcu read lock
+        * to make sure it doesn't disappear under us.
+        */
+       rb = ring_buffer_get(output_event);
+       if (!rb)
+               return NULL;
+
+       if (!rb_has_aux(rb) || !atomic_inc_not_zero(&rb->aux_refcount))
+               goto err;
+
+       /*
+        * Nesting is not supported for AUX area, make sure nested
+        * writers are caught early
+        */
+       if (WARN_ON_ONCE(local_xchg(&rb->aux_nest, 1)))
+               goto err_put;
+
+       aux_head = local_read(&rb->aux_head);
+
+       handle->rb = rb;
+       handle->event = event;
+       handle->head = aux_head;
+       handle->size = 0;
+
+       /*
+        * In overwrite mode, AUX data stores do not depend on aux_tail,
+        * therefore (A) control dependency barrier does not exist. The
+        * (B) <-> (C) ordering is still observed by the pmu driver.
+        */
+       if (!rb->aux_overwrite) {
+               aux_tail = ACCESS_ONCE(rb->user_page->aux_tail);
+               handle->wakeup = local_read(&rb->aux_wakeup) + rb->aux_watermark;
+               if (aux_head - aux_tail < perf_aux_size(rb))
+                       handle->size = CIRC_SPACE(aux_head, aux_tail, perf_aux_size(rb));
+
+               /*
+                * handle->size computation depends on aux_tail load; this forms a
+                * control dependency barrier separating aux_tail load from aux data
+                * store that will be enabled on successful return
+                */
+               if (!handle->size) { /* A, matches D */
+                       event->pending_disable = 1;
+                       perf_output_wakeup(handle);
+                       local_set(&rb->aux_nest, 0);
+                       goto err_put;
+               }
+       }
+
+       return handle->rb->aux_priv;
+
+err_put:
+       rb_free_aux(rb);
+
+err:
+       ring_buffer_put(rb);
+       handle->event = NULL;
+
+       return NULL;
+}
+
+/*
+ * Commit the data written by hardware into the ring buffer by adjusting
+ * aux_head and posting a PERF_RECORD_AUX into the perf buffer. It is the
+ * pmu driver's responsibility to observe ordering rules of the hardware,
+ * so that all the data is externally visible before this is called.
+ */
+void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size,
+                        bool truncated)
+{
+       struct ring_buffer *rb = handle->rb;
+       unsigned long aux_head;
+       u64 flags = 0;
+
+       if (truncated)
+               flags |= PERF_AUX_FLAG_TRUNCATED;
+
+       /* in overwrite mode, driver provides aux_head via handle */
+       if (rb->aux_overwrite) {
+               flags |= PERF_AUX_FLAG_OVERWRITE;
+
+               aux_head = handle->head;
+               local_set(&rb->aux_head, aux_head);
+       } else {
+               aux_head = local_read(&rb->aux_head);
+               local_add(size, &rb->aux_head);
+       }
+
+       if (size || flags) {
+               /*
+                * Only send RECORD_AUX if we have something useful to communicate
+                */
+
+               perf_event_aux_event(handle->event, aux_head, size, flags);
+       }
+
+       aux_head = rb->user_page->aux_head = local_read(&rb->aux_head);
+
+       if (aux_head - local_read(&rb->aux_wakeup) >= rb->aux_watermark) {
+               perf_output_wakeup(handle);
+               local_add(rb->aux_watermark, &rb->aux_wakeup);
+       }
+       handle->event = NULL;
+
+       local_set(&rb->aux_nest, 0);
+       rb_free_aux(rb);
+       ring_buffer_put(rb);
+}
+
+/*
+ * Skip over a given number of bytes in the AUX buffer, due to, for example,
+ * hardware's alignment constraints.
+ */
+int perf_aux_output_skip(struct perf_output_handle *handle, unsigned long size)
+{
+       struct ring_buffer *rb = handle->rb;
+       unsigned long aux_head;
+
+       if (size > handle->size)
+               return -ENOSPC;
+
+       local_add(size, &rb->aux_head);
+
+       aux_head = rb->user_page->aux_head = local_read(&rb->aux_head);
+       if (aux_head - local_read(&rb->aux_wakeup) >= rb->aux_watermark) {
+               perf_output_wakeup(handle);
+               local_add(rb->aux_watermark, &rb->aux_wakeup);
+               handle->wakeup = local_read(&rb->aux_wakeup) +
+                                rb->aux_watermark;
+       }
+
+       handle->head = aux_head;
+       handle->size -= size;
+
+       return 0;
+}
+
+void *perf_get_aux(struct perf_output_handle *handle)
+{
+       /* this is only valid between perf_aux_output_begin and *_end */
+       if (!handle->event)
+               return NULL;
+
+       return handle->rb->aux_priv;
+}
+
+#define PERF_AUX_GFP   (GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY)
+
+static struct page *rb_alloc_aux_page(int node, int order)
+{
+       struct page *page;
+
+       if (order > MAX_ORDER)
+               order = MAX_ORDER;
+
+       do {
+               page = alloc_pages_node(node, PERF_AUX_GFP, order);
+       } while (!page && order--);
+
+       if (page && order) {
+               /*
+                * Communicate the allocation size to the driver
+                */
+               split_page(page, order);
+               SetPagePrivate(page);
+               set_page_private(page, order);
+       }
+
+       return page;
+}
+
+static void rb_free_aux_page(struct ring_buffer *rb, int idx)
+{
+       struct page *page = virt_to_page(rb->aux_pages[idx]);
+
+       ClearPagePrivate(page);
+       page->mapping = NULL;
+       __free_page(page);
+}
+
+int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event,
+                pgoff_t pgoff, int nr_pages, long watermark, int flags)
+{
+       bool overwrite = !(flags & RING_BUFFER_WRITABLE);
+       int node = (event->cpu == -1) ? -1 : cpu_to_node(event->cpu);
+       int ret = -ENOMEM, max_order = 0;
+
+       if (!has_aux(event))
+               return -ENOTSUPP;
+
+       if (event->pmu->capabilities & PERF_PMU_CAP_AUX_NO_SG) {
+               /*
+                * We need to start with the max_order that fits in nr_pages,
+                * not the other way around, hence ilog2() and not get_order.
+                */
+               max_order = ilog2(nr_pages);
+
+               /*
+                * PMU requests more than one contiguous chunks of memory
+                * for SW double buffering
+                */
+               if ((event->pmu->capabilities & PERF_PMU_CAP_AUX_SW_DOUBLEBUF) &&
+                   !overwrite) {
+                       if (!max_order)
+                               return -EINVAL;
+
+                       max_order--;
+               }
+       }
+
+       rb->aux_pages = kzalloc_node(nr_pages * sizeof(void *), GFP_KERNEL, node);
+       if (!rb->aux_pages)
+               return -ENOMEM;
+
+       rb->free_aux = event->pmu->free_aux;
+       for (rb->aux_nr_pages = 0; rb->aux_nr_pages < nr_pages;) {
+               struct page *page;
+               int last, order;
+
+               order = min(max_order, ilog2(nr_pages - rb->aux_nr_pages));
+               page = rb_alloc_aux_page(node, order);
+               if (!page)
+                       goto out;
+
+               for (last = rb->aux_nr_pages + (1 << page_private(page));
+                    last > rb->aux_nr_pages; rb->aux_nr_pages++)
+                       rb->aux_pages[rb->aux_nr_pages] = page_address(page++);
+       }
+
+       rb->aux_priv = event->pmu->setup_aux(event->cpu, rb->aux_pages, nr_pages,
+                                            overwrite);
+       if (!rb->aux_priv)
+               goto out;
+
+       ret = 0;
+
+       /*
+        * aux_pages (and pmu driver's private data, aux_priv) will be
+        * referenced in both producer's and consumer's contexts, thus
+        * we keep a refcount here to make sure either of the two can
+        * reference them safely.
+        */
+       atomic_set(&rb->aux_refcount, 1);
+
+       rb->aux_overwrite = overwrite;
+       rb->aux_watermark = watermark;
+
+       if (!rb->aux_watermark && !rb->aux_overwrite)
+               rb->aux_watermark = nr_pages << (PAGE_SHIFT - 1);
+
+out:
+       if (!ret)
+               rb->aux_pgoff = pgoff;
+       else
+               rb_free_aux(rb);
+
+       return ret;
+}
+
+static void __rb_free_aux(struct ring_buffer *rb)
+{
+       int pg;
+
+       if (rb->aux_priv) {
+               rb->free_aux(rb->aux_priv);
+               rb->free_aux = NULL;
+               rb->aux_priv = NULL;
+       }
+
+       for (pg = 0; pg < rb->aux_nr_pages; pg++)
+               rb_free_aux_page(rb, pg);
+
+       kfree(rb->aux_pages);
+       rb->aux_nr_pages = 0;
+}
+
+void rb_free_aux(struct ring_buffer *rb)
+{
+       if (atomic_dec_and_test(&rb->aux_refcount))
+               __rb_free_aux(rb);
+}
+
 #ifndef CONFIG_PERF_USE_VMALLOC
 
 /*
  * Back perf_mmap() with regular GFP_KERNEL-0 pages.
  */
 
-struct page *
-perf_mmap_to_page(struct ring_buffer *rb, unsigned long pgoff)
+static struct page *
+__perf_mmap_to_page(struct ring_buffer *rb, unsigned long pgoff)
 {
        if (pgoff > rb->nr_pages)
                return NULL;
@@ -340,8 +643,8 @@ static int data_page_nr(struct ring_buffer *rb)
        return rb->nr_pages << page_order(rb);
 }
 
-struct page *
-perf_mmap_to_page(struct ring_buffer *rb, unsigned long pgoff)
+static struct page *
+__perf_mmap_to_page(struct ring_buffer *rb, unsigned long pgoff)
 {
        /* The '>' counts in the user page. */
        if (pgoff > data_page_nr(rb))
@@ -416,3 +719,19 @@ fail:
 }
 
 #endif
+
+struct page *
+perf_mmap_to_page(struct ring_buffer *rb, unsigned long pgoff)
+{
+       if (rb->aux_nr_pages) {
+               /* above AUX space */
+               if (pgoff > rb->aux_pgoff + rb->aux_nr_pages)
+                       return NULL;
+
+               /* AUX space */
+               if (pgoff >= rb->aux_pgoff)
+                       return virt_to_page(rb->aux_pages[pgoff - rb->aux_pgoff]);
+       }
+
+       return __perf_mmap_to_page(rb, pgoff);
+}
index 2a5e3830e953b72cca4aeac4ec537e276f0f355b..2579e407ff67d039106207f78a466f824e515db6 100644 (file)
@@ -900,7 +900,7 @@ static int attach_to_pi_owner(u32 uval, union futex_key *key,
        if (!p)
                return -ESRCH;
 
-       if (!p->mm) {
+       if (unlikely(p->flags & PF_KTHREAD)) {
                put_task_struct(p);
                return -EPERM;
        }
index 6f1c7a566b95d4da4b4ef80a0450c28122915dac..eb9a4ea394ab33fdde25420f11cb9021df384824 100644 (file)
@@ -948,6 +948,22 @@ int irq_chip_retrigger_hierarchy(struct irq_data *data)
 
        return -ENOSYS;
 }
+
+/**
+ * irq_chip_set_wake_parent - Set/reset wake-up on the parent interrupt
+ * @data:      Pointer to interrupt specific data
+ * @on:                Whether to set or reset the wake-up capability of this irq
+ *
+ * Conditional, as the underlying parent chip might not implement it.
+ */
+int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on)
+{
+       data = data->parent_data;
+       if (data->chip->irq_set_wake)
+               return data->chip->irq_set_wake(data, on);
+
+       return -ENOSYS;
+}
 #endif
 
 /**
index 886d09e691d5a8d180826f2d5581c6bfb252d63c..e68932bb308e96e1c6aa184dc7d9972fba8df06e 100644 (file)
@@ -68,14 +68,20 @@ static void __synchronize_hardirq(struct irq_desc *desc)
  *     Do not use this for shutdown scenarios where you must be sure
  *     that all parts (hardirq and threaded handler) have completed.
  *
+ *     Returns: false if a threaded handler is active.
+ *
  *     This function may be called - with care - from IRQ context.
  */
-void synchronize_hardirq(unsigned int irq)
+bool synchronize_hardirq(unsigned int irq)
 {
        struct irq_desc *desc = irq_to_desc(irq);
 
-       if (desc)
+       if (desc) {
                __synchronize_hardirq(desc);
+               return !atomic_read(&desc->threads_active);
+       }
+
+       return true;
 }
 EXPORT_SYMBOL(synchronize_hardirq);
 
@@ -440,6 +446,32 @@ void disable_irq(unsigned int irq)
 }
 EXPORT_SYMBOL(disable_irq);
 
+/**
+ *     disable_hardirq - disables an irq and waits for hardirq completion
+ *     @irq: Interrupt to disable
+ *
+ *     Disable the selected interrupt line.  Enables and Disables are
+ *     nested.
+ *     This function waits for any pending hard IRQ handlers for this
+ *     interrupt to complete before returning. If you use this function while
+ *     holding a resource the hard IRQ handler may need you will deadlock.
+ *
+ *     When used to optimistically disable an interrupt from atomic context
+ *     the return value must be checked.
+ *
+ *     Returns: false if a threaded handler is active.
+ *
+ *     This function may be called - with care - from IRQ context.
+ */
+bool disable_hardirq(unsigned int irq)
+{
+       if (!__disable_irq_nosync(irq))
+               return synchronize_hardirq(irq);
+
+       return false;
+}
+EXPORT_SYMBOL_GPL(disable_hardirq);
+
 void __enable_irq(struct irq_desc *desc, unsigned int irq)
 {
        switch (desc->depth) {
@@ -1766,3 +1798,94 @@ int request_percpu_irq(unsigned int irq, irq_handler_t handler,
 
        return retval;
 }
+
+/**
+ *     irq_get_irqchip_state - returns the irqchip state of a interrupt.
+ *     @irq: Interrupt line that is forwarded to a VM
+ *     @which: One of IRQCHIP_STATE_* the caller wants to know about
+ *     @state: a pointer to a boolean where the state is to be storeed
+ *
+ *     This call snapshots the internal irqchip state of an
+ *     interrupt, returning into @state the bit corresponding to
+ *     stage @which
+ *
+ *     This function should be called with preemption disabled if the
+ *     interrupt controller has per-cpu registers.
+ */
+int irq_get_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
+                         bool *state)
+{
+       struct irq_desc *desc;
+       struct irq_data *data;
+       struct irq_chip *chip;
+       unsigned long flags;
+       int err = -EINVAL;
+
+       desc = irq_get_desc_buslock(irq, &flags, 0);
+       if (!desc)
+               return err;
+
+       data = irq_desc_get_irq_data(desc);
+
+       do {
+               chip = irq_data_get_irq_chip(data);
+               if (chip->irq_get_irqchip_state)
+                       break;
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+               data = data->parent_data;
+#else
+               data = NULL;
+#endif
+       } while (data);
+
+       if (data)
+               err = chip->irq_get_irqchip_state(data, which, state);
+
+       irq_put_desc_busunlock(desc, flags);
+       return err;
+}
+
+/**
+ *     irq_set_irqchip_state - set the state of a forwarded interrupt.
+ *     @irq: Interrupt line that is forwarded to a VM
+ *     @which: State to be restored (one of IRQCHIP_STATE_*)
+ *     @val: Value corresponding to @which
+ *
+ *     This call sets the internal irqchip state of an interrupt,
+ *     depending on the value of @which.
+ *
+ *     This function should be called with preemption disabled if the
+ *     interrupt controller has per-cpu registers.
+ */
+int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
+                         bool val)
+{
+       struct irq_desc *desc;
+       struct irq_data *data;
+       struct irq_chip *chip;
+       unsigned long flags;
+       int err = -EINVAL;
+
+       desc = irq_get_desc_buslock(irq, &flags, 0);
+       if (!desc)
+               return err;
+
+       data = irq_desc_get_irq_data(desc);
+
+       do {
+               chip = irq_data_get_irq_chip(data);
+               if (chip->irq_set_irqchip_state)
+                       break;
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+               data = data->parent_data;
+#else
+               data = NULL;
+#endif
+       } while (data);
+
+       if (data)
+               err = chip->irq_set_irqchip_state(data, which, val);
+
+       irq_put_desc_busunlock(desc, flags);
+       return err;
+}
index 3e18163f336f2457bf999c87386fb12290e9ed6e..474de5cb394d3c2007135c788a5c40c973e34c6a 100644 (file)
@@ -310,8 +310,15 @@ void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
        struct msi_desc *desc;
 
        for_each_msi_entry(desc, dev) {
-               irq_domain_free_irqs(desc->irq, desc->nvec_used);
-               desc->irq = 0;
+               /*
+                * We might have failed to allocate an MSI early
+                * enough that there is no IRQ associated to this
+                * entry. If that's the case, don't do anything.
+                */
+               if (desc->irq) {
+                       irq_domain_free_irqs(desc->irq, desc->nvec_used);
+                       desc->irq = 0;
+               }
        }
 }
 
index 3f9f1d6b4c2e5726217556a40454c46dbe368b89..284e2691e38073d52b00d46010e654e6ff7de9bf 100644 (file)
@@ -335,32 +335,20 @@ unlock:
        rcu_read_unlock();
 }
 
-static int klp_disable_func(struct klp_func *func)
+static void klp_disable_func(struct klp_func *func)
 {
        struct klp_ops *ops;
-       int ret;
-
-       if (WARN_ON(func->state != KLP_ENABLED))
-               return -EINVAL;
 
-       if (WARN_ON(!func->old_addr))
-               return -EINVAL;
+       WARN_ON(func->state != KLP_ENABLED);
+       WARN_ON(!func->old_addr);
 
        ops = klp_find_ops(func->old_addr);
        if (WARN_ON(!ops))
-               return -EINVAL;
+               return;
 
        if (list_is_singular(&ops->func_stack)) {
-               ret = unregister_ftrace_function(&ops->fops);
-               if (ret) {
-                       pr_err("failed to unregister ftrace handler for function '%s' (%d)\n",
-                              func->old_name, ret);
-                       return ret;
-               }
-
-               ret = ftrace_set_filter_ip(&ops->fops, func->old_addr, 1, 0);
-               if (ret)
-                       pr_warn("function unregister succeeded but failed to clear the filter\n");
+               WARN_ON(unregister_ftrace_function(&ops->fops));
+               WARN_ON(ftrace_set_filter_ip(&ops->fops, func->old_addr, 1, 0));
 
                list_del_rcu(&func->stack_node);
                list_del(&ops->node);
@@ -370,8 +358,6 @@ static int klp_disable_func(struct klp_func *func)
        }
 
        func->state = KLP_DISABLED;
-
-       return 0;
 }
 
 static int klp_enable_func(struct klp_func *func)
@@ -432,23 +418,15 @@ err:
        return ret;
 }
 
-static int klp_disable_object(struct klp_object *obj)
+static void klp_disable_object(struct klp_object *obj)
 {
        struct klp_func *func;
-       int ret;
 
-       for (func = obj->funcs; func->old_name; func++) {
-               if (func->state != KLP_ENABLED)
-                       continue;
-
-               ret = klp_disable_func(func);
-               if (ret)
-                       return ret;
-       }
+       for (func = obj->funcs; func->old_name; func++)
+               if (func->state == KLP_ENABLED)
+                       klp_disable_func(func);
 
        obj->state = KLP_DISABLED;
-
-       return 0;
 }
 
 static int klp_enable_object(struct klp_object *obj)
@@ -464,22 +442,19 @@ static int klp_enable_object(struct klp_object *obj)
 
        for (func = obj->funcs; func->old_name; func++) {
                ret = klp_enable_func(func);
-               if (ret)
-                       goto unregister;
+               if (ret) {
+                       klp_disable_object(obj);
+                       return ret;
+               }
        }
        obj->state = KLP_ENABLED;
 
        return 0;
-
-unregister:
-       WARN_ON(klp_disable_object(obj));
-       return ret;
 }
 
 static int __klp_disable_patch(struct klp_patch *patch)
 {
        struct klp_object *obj;
-       int ret;
 
        /* enforce stacking: only the last enabled patch can be disabled */
        if (!list_is_last(&patch->list, &klp_patches) &&
@@ -489,12 +464,8 @@ static int __klp_disable_patch(struct klp_patch *patch)
        pr_notice("disabling patch '%s'\n", patch->mod->name);
 
        for (obj = patch->objs; obj->funcs; obj++) {
-               if (obj->state != KLP_ENABLED)
-                       continue;
-
-               ret = klp_disable_object(obj);
-               if (ret)
-                       return ret;
+               if (obj->state == KLP_ENABLED)
+                       klp_disable_object(obj);
        }
 
        patch->state = KLP_DISABLED;
@@ -553,8 +524,6 @@ static int __klp_enable_patch(struct klp_patch *patch)
        pr_notice("enabling patch '%s'\n", patch->mod->name);
 
        for (obj = patch->objs; obj->funcs; obj++) {
-               klp_find_object_module(obj);
-
                if (!klp_is_object_loaded(obj))
                        continue;
 
@@ -945,7 +914,6 @@ static void klp_module_notify_going(struct klp_patch *patch,
 {
        struct module *pmod = patch->mod;
        struct module *mod = obj->mod;
-       int ret;
 
        if (patch->state == KLP_DISABLED)
                goto disabled;
@@ -953,10 +921,7 @@ static void klp_module_notify_going(struct klp_patch *patch,
        pr_notice("reverting patch '%s' on unloading module '%s'\n",
                  pmod->name, mod->name);
 
-       ret = klp_disable_object(obj);
-       if (ret)
-               pr_warn("failed to revert patch '%s' on module '%s' (%d)\n",
-                       pmod->name, mod->name, ret);
+       klp_disable_object(obj);
 
 disabled:
        klp_free_object_loaded(obj);
index d1fe2ba5bac958bc85da8e8868408d8c6c809dc3..75e114bdf3f26f379c4382dce2bc5c128c06b868 100644 (file)
@@ -78,7 +78,7 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node)
                 */
                return;
        }
-       ACCESS_ONCE(prev->next) = node;
+       WRITE_ONCE(prev->next, node);
 
        /* Wait until the lock holder passes the lock down. */
        arch_mcs_spin_lock_contended(&node->locked);
@@ -91,7 +91,7 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node)
 static inline
 void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *node)
 {
-       struct mcs_spinlock *next = ACCESS_ONCE(node->next);
+       struct mcs_spinlock *next = READ_ONCE(node->next);
 
        if (likely(!next)) {
                /*
@@ -100,7 +100,7 @@ void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *node)
                if (likely(cmpxchg(lock, node, NULL) == node))
                        return;
                /* Wait until the next pointer is set */
-               while (!(next = ACCESS_ONCE(node->next)))
+               while (!(next = READ_ONCE(node->next)))
                        cpu_relax_lowlatency();
        }
 
index 94674e5919cba54e339addf0c7c7cf2b90f75c27..4cccea6b8934f5697fa3dfa609ae4bd10db78b6f 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/debug_locks.h>
-#include "mcs_spinlock.h"
+#include <linux/osq_lock.h>
 
 /*
  * In the DEBUG case we are using the "NULL fastpath" for mutexes,
@@ -217,44 +217,35 @@ ww_mutex_set_context_slowpath(struct ww_mutex *lock,
 }
 
 #ifdef CONFIG_MUTEX_SPIN_ON_OWNER
-static inline bool owner_running(struct mutex *lock, struct task_struct *owner)
-{
-       if (lock->owner != owner)
-               return false;
-
-       /*
-        * Ensure we emit the owner->on_cpu, dereference _after_ checking
-        * lock->owner still matches owner, if that fails, owner might
-        * point to free()d memory, if it still matches, the rcu_read_lock()
-        * ensures the memory stays valid.
-        */
-       barrier();
-
-       return owner->on_cpu;
-}
-
 /*
  * Look out! "owner" is an entirely speculative pointer
  * access and not reliable.
  */
 static noinline
-int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
+bool mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
 {
+       bool ret = true;
+
        rcu_read_lock();
-       while (owner_running(lock, owner)) {
-               if (need_resched())
+       while (lock->owner == owner) {
+               /*
+                * Ensure we emit the owner->on_cpu, dereference _after_
+                * checking lock->owner still matches owner. If that fails,
+                * owner might point to freed memory. If it still matches,
+                * the rcu_read_lock() ensures the memory stays valid.
+                */
+               barrier();
+
+               if (!owner->on_cpu || need_resched()) {
+                       ret = false;
                        break;
+               }
 
                cpu_relax_lowlatency();
        }
        rcu_read_unlock();
 
-       /*
-        * We break out the loop above on need_resched() and when the
-        * owner changed, which is a sign for heavy contention. Return
-        * success only when lock->owner is NULL.
-        */
-       return lock->owner == NULL;
+       return ret;
 }
 
 /*
@@ -269,7 +260,7 @@ static inline int mutex_can_spin_on_owner(struct mutex *lock)
                return 0;
 
        rcu_read_lock();
-       owner = ACCESS_ONCE(lock->owner);
+       owner = READ_ONCE(lock->owner);
        if (owner)
                retval = owner->on_cpu;
        rcu_read_unlock();
@@ -343,7 +334,7 @@ static bool mutex_optimistic_spin(struct mutex *lock,
                         * As such, when deadlock detection needs to be
                         * performed the optimistic spinning cannot be done.
                         */
-                       if (ACCESS_ONCE(ww->ctx))
+                       if (READ_ONCE(ww->ctx))
                                break;
                }
 
@@ -351,7 +342,7 @@ static bool mutex_optimistic_spin(struct mutex *lock,
                 * If there's an owner, wait for it to either
                 * release the lock or go to sleep.
                 */
-               owner = ACCESS_ONCE(lock->owner);
+               owner = READ_ONCE(lock->owner);
                if (owner && !mutex_spin_on_owner(lock, owner))
                        break;
 
@@ -490,7 +481,7 @@ static inline int __sched
 __ww_mutex_lock_check_stamp(struct mutex *lock, struct ww_acquire_ctx *ctx)
 {
        struct ww_mutex *ww = container_of(lock, struct ww_mutex, base);
-       struct ww_acquire_ctx *hold_ctx = ACCESS_ONCE(ww->ctx);
+       struct ww_acquire_ctx *hold_ctx = READ_ONCE(ww->ctx);
 
        if (!hold_ctx)
                return 0;
index c112d00341b05773934ecdb2977c0d2aca1d5c11..dc85ee23a26f79416a140241e3067a5a2ca24d0b 100644 (file)
@@ -98,7 +98,7 @@ bool osq_lock(struct optimistic_spin_queue *lock)
 
        prev = decode_cpu(old);
        node->prev = prev;
-       ACCESS_ONCE(prev->next) = node;
+       WRITE_ONCE(prev->next, node);
 
        /*
         * Normally @prev is untouchable after the above store; because at that
@@ -109,7 +109,7 @@ bool osq_lock(struct optimistic_spin_queue *lock)
         * cmpxchg in an attempt to undo our queueing.
         */
 
-       while (!ACCESS_ONCE(node->locked)) {
+       while (!READ_ONCE(node->locked)) {
                /*
                 * If we need to reschedule bail... so we can block.
                 */
@@ -148,7 +148,7 @@ unqueue:
                 * Or we race against a concurrent unqueue()'s step-B, in which
                 * case its step-C will write us a new @node->prev pointer.
                 */
-               prev = ACCESS_ONCE(node->prev);
+               prev = READ_ONCE(node->prev);
        }
 
        /*
@@ -170,8 +170,8 @@ unqueue:
         * it will wait in Step-A.
         */
 
-       ACCESS_ONCE(next->prev) = prev;
-       ACCESS_ONCE(prev->next) = next;
+       WRITE_ONCE(next->prev, prev);
+       WRITE_ONCE(prev->next, next);
 
        return false;
 }
@@ -193,11 +193,11 @@ void osq_unlock(struct optimistic_spin_queue *lock)
        node = this_cpu_ptr(&osq_node);
        next = xchg(&node->next, NULL);
        if (next) {
-               ACCESS_ONCE(next->locked) = 1;
+               WRITE_ONCE(next->locked, 1);
                return;
        }
 
        next = osq_wait_next(lock, node, NULL);
        if (next)
-               ACCESS_ONCE(next->locked) = 1;
+               WRITE_ONCE(next->locked, 1);
 }
index 6357265a31ad1a34b881aba31abe27ab6d3921ec..b73279367087ca779072b79a784f69224929c149 100644 (file)
@@ -349,7 +349,7 @@ static inline struct rt_mutex *task_blocked_on_lock(struct task_struct *p)
  *
  * @task:      the task owning the mutex (owner) for which a chain walk is
  *             probably needed
- * @deadlock_detect: do we have to carry out deadlock detection?
+ * @chwalk:    do we have to carry out deadlock detection?
  * @orig_lock: the mutex (can be NULL if we are walking the chain to recheck
  *             things for a task that has just got its priority adjusted, and
  *             is waiting on a mutex)
index 2555ae15ec14c78d6c8f5030fea52daa74b5a5c9..3a504857206536f68fda513fecf63841d2979a06 100644 (file)
@@ -85,6 +85,13 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
 
                list_del(&waiter->list);
                tsk = waiter->task;
+               /*
+                * Make sure we do not wakeup the next reader before
+                * setting the nil condition to grant the next reader;
+                * otherwise we could miss the wakeup on the other
+                * side and end up sleeping again. See the pairing
+                * in rwsem_down_read_failed().
+                */
                smp_mb();
                waiter->task = NULL;
                wake_up_process(tsk);
index 2f7cc4076f50aa0c534c22e527ab3d1f11ce9a66..3417d0172a5d2e7cd69460ed4ef96c02f6c578d0 100644 (file)
@@ -14,8 +14,9 @@
 #include <linux/init.h>
 #include <linux/export.h>
 #include <linux/sched/rt.h>
+#include <linux/osq_lock.h>
 
-#include "mcs_spinlock.h"
+#include "rwsem.h"
 
 /*
  * Guide to the rw_semaphore's count field for common values.
@@ -186,6 +187,13 @@ __rwsem_do_wake(struct rw_semaphore *sem, enum rwsem_wake_type wake_type)
                waiter = list_entry(next, struct rwsem_waiter, list);
                next = waiter->list.next;
                tsk = waiter->task;
+               /*
+                * Make sure we do not wakeup the next reader before
+                * setting the nil condition to grant the next reader;
+                * otherwise we could miss the wakeup on the other
+                * side and end up sleeping again. See the pairing
+                * in rwsem_down_read_failed().
+                */
                smp_mb();
                waiter->task = NULL;
                wake_up_process(tsk);
@@ -258,6 +266,7 @@ static inline bool rwsem_try_write_lock(long count, struct rw_semaphore *sem)
                    RWSEM_ACTIVE_WRITE_BIAS) == RWSEM_WAITING_BIAS) {
                if (!list_is_singular(&sem->wait_list))
                        rwsem_atomic_update(RWSEM_WAITING_BIAS, sem);
+               rwsem_set_owner(sem);
                return true;
        }
 
@@ -270,15 +279,17 @@ static inline bool rwsem_try_write_lock(long count, struct rw_semaphore *sem)
  */
 static inline bool rwsem_try_write_lock_unqueued(struct rw_semaphore *sem)
 {
-       long old, count = ACCESS_ONCE(sem->count);
+       long old, count = READ_ONCE(sem->count);
 
        while (true) {
                if (!(count == 0 || count == RWSEM_WAITING_BIAS))
                        return false;
 
                old = cmpxchg(&sem->count, count, count + RWSEM_ACTIVE_WRITE_BIAS);
-               if (old == count)
+               if (old == count) {
+                       rwsem_set_owner(sem);
                        return true;
+               }
 
                count = old;
        }
@@ -287,60 +298,67 @@ static inline bool rwsem_try_write_lock_unqueued(struct rw_semaphore *sem)
 static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem)
 {
        struct task_struct *owner;
-       bool on_cpu = false;
+       bool ret = true;
 
        if (need_resched())
                return false;
 
        rcu_read_lock();
-       owner = ACCESS_ONCE(sem->owner);
-       if (owner)
-               on_cpu = owner->on_cpu;
-       rcu_read_unlock();
-
-       /*
-        * If sem->owner is not set, yet we have just recently entered the
-        * slowpath, then there is a possibility reader(s) may have the lock.
-        * To be safe, avoid spinning in these situations.
-        */
-       return on_cpu;
-}
-
-static inline bool owner_running(struct rw_semaphore *sem,
-                                struct task_struct *owner)
-{
-       if (sem->owner != owner)
-               return false;
-
-       /*
-        * Ensure we emit the owner->on_cpu, dereference _after_ checking
-        * sem->owner still matches owner, if that fails, owner might
-        * point to free()d memory, if it still matches, the rcu_read_lock()
-        * ensures the memory stays valid.
-        */
-       barrier();
+       owner = READ_ONCE(sem->owner);
+       if (!owner) {
+               long count = READ_ONCE(sem->count);
+               /*
+                * If sem->owner is not set, yet we have just recently entered the
+                * slowpath with the lock being active, then there is a possibility
+                * reader(s) may have the lock. To be safe, bail spinning in these
+                * situations.
+                */
+               if (count & RWSEM_ACTIVE_MASK)
+                       ret = false;
+               goto done;
+       }
 
-       return owner->on_cpu;
+       ret = owner->on_cpu;
+done:
+       rcu_read_unlock();
+       return ret;
 }
 
 static noinline
 bool rwsem_spin_on_owner(struct rw_semaphore *sem, struct task_struct *owner)
 {
+       long count;
+
        rcu_read_lock();
-       while (owner_running(sem, owner)) {
-               if (need_resched())
-                       break;
+       while (sem->owner == owner) {
+               /*
+                * Ensure we emit the owner->on_cpu, dereference _after_
+                * checking sem->owner still matches owner, if that fails,
+                * owner might point to free()d memory, if it still matches,
+                * the rcu_read_lock() ensures the memory stays valid.
+                */
+               barrier();
+
+               /* abort spinning when need_resched or owner is not running */
+               if (!owner->on_cpu || need_resched()) {
+                       rcu_read_unlock();
+                       return false;
+               }
 
                cpu_relax_lowlatency();
        }
        rcu_read_unlock();
 
+       if (READ_ONCE(sem->owner))
+               return true; /* new owner, continue spinning */
+
        /*
-        * We break out the loop above on need_resched() or when the
-        * owner changed, which is a sign for heavy contention. Return
-        * success only when sem->owner is NULL.
+        * When the owner is not set, the lock could be free or
+        * held by readers. Check the counter to verify the
+        * state.
         */
-       return sem->owner == NULL;
+       count = READ_ONCE(sem->count);
+       return (count == 0 || count == RWSEM_WAITING_BIAS);
 }
 
 static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
@@ -358,7 +376,7 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
                goto done;
 
        while (true) {
-               owner = ACCESS_ONCE(sem->owner);
+               owner = READ_ONCE(sem->owner);
                if (owner && !rwsem_spin_on_owner(sem, owner))
                        break;
 
@@ -432,7 +450,7 @@ struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem)
 
        /* we're now waiting on the lock, but no longer actively locking */
        if (waiting) {
-               count = ACCESS_ONCE(sem->count);
+               count = READ_ONCE(sem->count);
 
                /*
                 * If there were already threads queued before us and there are
index e2d3bc7f03b41e1c01a7c8fc548ac162cdfa151e..205be0ce34de73e8590f2cd4cdb369526b236540 100644 (file)
@@ -9,29 +9,9 @@
 #include <linux/sched.h>
 #include <linux/export.h>
 #include <linux/rwsem.h>
-
 #include <linux/atomic.h>
 
-#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
-static inline void rwsem_set_owner(struct rw_semaphore *sem)
-{
-       sem->owner = current;
-}
-
-static inline void rwsem_clear_owner(struct rw_semaphore *sem)
-{
-       sem->owner = NULL;
-}
-
-#else
-static inline void rwsem_set_owner(struct rw_semaphore *sem)
-{
-}
-
-static inline void rwsem_clear_owner(struct rw_semaphore *sem)
-{
-}
-#endif
+#include "rwsem.h"
 
 /*
  * lock for reading
diff --git a/kernel/locking/rwsem.h b/kernel/locking/rwsem.h
new file mode 100644 (file)
index 0000000..870ed9a
--- /dev/null
@@ -0,0 +1,20 @@
+#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
+static inline void rwsem_set_owner(struct rw_semaphore *sem)
+{
+       sem->owner = current;
+}
+
+static inline void rwsem_clear_owner(struct rw_semaphore *sem)
+{
+       sem->owner = NULL;
+}
+
+#else
+static inline void rwsem_set_owner(struct rw_semaphore *sem)
+{
+}
+
+static inline void rwsem_clear_owner(struct rw_semaphore *sem)
+{
+}
+#endif
index 99fdf94efce80f432fc4ab203aeb2a918ad5c564..650b038ae52035962cb4fa37b14776225e4ce701 100644 (file)
@@ -2479,6 +2479,23 @@ static int elf_header_check(struct load_info *info)
        return 0;
 }
 
+#define COPY_CHUNK_SIZE (16*PAGE_SIZE)
+
+static int copy_chunked_from_user(void *dst, const void __user *usrc, unsigned long len)
+{
+       do {
+               unsigned long n = min(len, COPY_CHUNK_SIZE);
+
+               if (copy_from_user(dst, usrc, n) != 0)
+                       return -EFAULT;
+               cond_resched();
+               dst += n;
+               usrc += n;
+               len -= n;
+       } while (len);
+       return 0;
+}
+
 /* Sets info->hdr and info->len. */
 static int copy_module_from_user(const void __user *umod, unsigned long len,
                                  struct load_info *info)
@@ -2498,7 +2515,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
        if (!info->hdr)
                return -ENOMEM;
 
-       if (copy_from_user(info->hdr, umod, info->len) != 0) {
+       if (copy_chunked_from_user(info->hdr, umod, info->len) != 0) {
                vfree(info->hdr);
                return -EFAULT;
        }
@@ -2753,6 +2770,9 @@ static int find_module_sections(struct module *mod, struct load_info *info)
        mod->trace_events = section_objs(info, "_ftrace_events",
                                         sizeof(*mod->trace_events),
                                         &mod->num_trace_events);
+       mod->trace_enums = section_objs(info, "_ftrace_enum_map",
+                                       sizeof(*mod->trace_enums),
+                                       &mod->num_trace_enums);
 #endif
 #ifdef CONFIG_TRACING
        mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt",
index c24d5a23bf939be71f75736efdbd3874da157c2d..5235dd4e1e2f68a97fa6836d98854d2e8e46724e 100644 (file)
@@ -955,25 +955,6 @@ static void mark_nosave_pages(struct memory_bitmap *bm)
        }
 }
 
-static bool is_nosave_page(unsigned long pfn)
-{
-       struct nosave_region *region;
-
-       list_for_each_entry(region, &nosave_regions, list) {
-               if (pfn >= region->start_pfn && pfn < region->end_pfn) {
-                       pr_err("PM: %#010llx in e820 nosave region: "
-                              "[mem %#010llx-%#010llx]\n",
-                              (unsigned long long) pfn << PAGE_SHIFT,
-                              (unsigned long long) region->start_pfn << PAGE_SHIFT,
-                              ((unsigned long long) region->end_pfn << PAGE_SHIFT)
-                                       - 1);
-                       return true;
-               }
-       }
-
-       return false;
-}
-
 /**
  *     create_basic_memory_bitmaps - create bitmaps needed for marking page
  *     frames that should not be saved and free page frames.  The pointers
@@ -2042,7 +2023,7 @@ static int mark_unsafe_pages(struct memory_bitmap *bm)
        do {
                pfn = memory_bm_next_pfn(bm);
                if (likely(pfn != BM_END_OF_MAP)) {
-                       if (likely(pfn_valid(pfn)) && !is_nosave_page(pfn))
+                       if (likely(pfn_valid(pfn)))
                                swsusp_set_page_free(pfn_to_page(pfn));
                        else
                                return -EFAULT;
index bb0635bd74f26a2ecb9f651de9e0c4113e4f2476..879edfc5ee52d2985d4fb925ec820ba6b113d6d0 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/security.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
-#include <linux/aio.h>
 #include <linux/syscalls.h>
 #include <linux/kexec.h>
 #include <linux/kdb.h>
@@ -46,6 +45,7 @@
 #include <linux/irq_work.h>
 #include <linux/utsname.h>
 #include <linux/ctype.h>
+#include <linux/uio.h>
 
 #include <asm/uaccess.h>
 
@@ -521,7 +521,7 @@ static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from)
        int i;
        int level = default_message_loglevel;
        int facility = 1;       /* LOG_USER */
-       size_t len = iocb->ki_nbytes;
+       size_t len = iov_iter_count(from);
        ssize_t ret = len;
 
        if (len > LOG_LINE_MAX)
index 30d42aa55d83de9b111bd05945114641409f3596..8dbe27611ec399e42f8912d49708ff4e20bff73f 100644 (file)
@@ -853,6 +853,8 @@ rcu_torture_fqs(void *arg)
 static int
 rcu_torture_writer(void *arg)
 {
+       bool can_expedite = !rcu_gp_is_expedited();
+       int expediting = 0;
        unsigned long gp_snap;
        bool gp_cond1 = gp_cond, gp_exp1 = gp_exp, gp_normal1 = gp_normal;
        bool gp_sync1 = gp_sync;
@@ -865,9 +867,15 @@ rcu_torture_writer(void *arg)
        int nsynctypes = 0;
 
        VERBOSE_TOROUT_STRING("rcu_torture_writer task started");
+       pr_alert("%s" TORTURE_FLAG
+                " Grace periods expedited from boot/sysfs for %s,\n",
+                torture_type, cur_ops->name);
+       pr_alert("%s" TORTURE_FLAG
+                " Testing of dynamic grace-period expediting diabled.\n",
+                torture_type);
 
        /* Initialize synctype[] array.  If none set, take default. */
-       if (!gp_cond1 && !gp_exp1 && !gp_normal1 && !gp_sync)
+       if (!gp_cond1 && !gp_exp1 && !gp_normal1 && !gp_sync1)
                gp_cond1 = gp_exp1 = gp_normal1 = gp_sync1 = true;
        if (gp_cond1 && cur_ops->get_state && cur_ops->cond_sync)
                synctype[nsynctypes++] = RTWS_COND_GET;
@@ -949,9 +957,26 @@ rcu_torture_writer(void *arg)
                        }
                }
                rcutorture_record_progress(++rcu_torture_current_version);
+               /* Cycle through nesting levels of rcu_expedite_gp() calls. */
+               if (can_expedite &&
+                   !(torture_random(&rand) & 0xff & (!!expediting - 1))) {
+                       WARN_ON_ONCE(expediting == 0 && rcu_gp_is_expedited());
+                       if (expediting >= 0)
+                               rcu_expedite_gp();
+                       else
+                               rcu_unexpedite_gp();
+                       if (++expediting > 3)
+                               expediting = -expediting;
+               }
                rcu_torture_writer_state = RTWS_STUTTER;
                stutter_wait("rcu_torture_writer");
        } while (!torture_must_stop());
+       /* Reset expediting back to unexpedited. */
+       if (expediting > 0)
+               expediting = -expediting;
+       while (can_expedite && expediting++ < 0)
+               rcu_unexpedite_gp();
+       WARN_ON_ONCE(can_expedite && rcu_gp_is_expedited());
        rcu_torture_writer_state = RTWS_STOPPING;
        torture_kthread_stopping("rcu_torture_writer");
        return 0;
index 445bf8ffe3fb27dfc58aa411b476ef105bc33645..cad76e76b4e7def42de7c379882c878084c5394c 100644 (file)
@@ -402,23 +402,6 @@ void call_srcu(struct srcu_struct *sp, struct rcu_head *head,
 }
 EXPORT_SYMBOL_GPL(call_srcu);
 
-struct rcu_synchronize {
-       struct rcu_head head;
-       struct completion completion;
-};
-
-/*
- * Awaken the corresponding synchronize_srcu() instance now that a
- * grace period has elapsed.
- */
-static void wakeme_after_rcu(struct rcu_head *head)
-{
-       struct rcu_synchronize *rcu;
-
-       rcu = container_of(head, struct rcu_synchronize, head);
-       complete(&rcu->completion);
-}
-
 static void srcu_advance_batches(struct srcu_struct *sp, int trycount);
 static void srcu_reschedule(struct srcu_struct *sp);
 
@@ -507,7 +490,7 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount)
  */
 void synchronize_srcu(struct srcu_struct *sp)
 {
-       __synchronize_srcu(sp, rcu_expedited
+       __synchronize_srcu(sp, rcu_gp_is_expedited()
                           ? SYNCHRONIZE_SRCU_EXP_TRYCOUNT
                           : SYNCHRONIZE_SRCU_TRYCOUNT);
 }
index cc9ceca7bde1fd5f0036ad841033071e5fec0499..069742d61c68873a3fce7bf5d7df2e77d5a59958 100644 (file)
@@ -103,8 +103,7 @@ EXPORT_SYMBOL(__rcu_is_watching);
 static int rcu_qsctr_help(struct rcu_ctrlblk *rcp)
 {
        RCU_TRACE(reset_cpu_stall_ticks(rcp));
-       if (rcp->rcucblist != NULL &&
-           rcp->donetail != rcp->curtail) {
+       if (rcp->donetail != rcp->curtail) {
                rcp->donetail = rcp->curtail;
                return 1;
        }
@@ -169,17 +168,6 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
        unsigned long flags;
        RCU_TRACE(int cb_count = 0);
 
-       /* If no RCU callbacks ready to invoke, just return. */
-       if (&rcp->rcucblist == rcp->donetail) {
-               RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, 0, -1));
-               RCU_TRACE(trace_rcu_batch_end(rcp->name, 0,
-                                             !!ACCESS_ONCE(rcp->rcucblist),
-                                             need_resched(),
-                                             is_idle_task(current),
-                                             false));
-               return;
-       }
-
        /* Move the ready-to-invoke callbacks to a local list. */
        local_irq_save(flags);
        RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, rcp->qlen, -1));
index 48d640ca1a05b8c0f83fe2b217b925a6dec69fa4..233165da782f51deb88c6373116d9d28a4fec38b 100644 (file)
@@ -91,8 +91,10 @@ static const char *tp_##sname##_varname __used __tracepoint_string = sname##_var
 
 #define RCU_STATE_INITIALIZER(sname, sabbr, cr) \
 DEFINE_RCU_TPS(sname) \
+DEFINE_PER_CPU_SHARED_ALIGNED(struct rcu_data, sname##_data); \
 struct rcu_state sname##_state = { \
        .level = { &sname##_state.node[0] }, \
+       .rda = &sname##_data, \
        .call = cr, \
        .fqs_state = RCU_GP_IDLE, \
        .gpnum = 0UL - 300UL, \
@@ -101,11 +103,9 @@ struct rcu_state sname##_state = { \
        .orphan_nxttail = &sname##_state.orphan_nxtlist, \
        .orphan_donetail = &sname##_state.orphan_donelist, \
        .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \
-       .onoff_mutex = __MUTEX_INITIALIZER(sname##_state.onoff_mutex), \
        .name = RCU_STATE_NAME(sname), \
        .abbr = sabbr, \
-}; \
-DEFINE_PER_CPU_SHARED_ALIGNED(struct rcu_data, sname##_data)
+}
 
 RCU_STATE_INITIALIZER(rcu_sched, 's', call_rcu_sched);
 RCU_STATE_INITIALIZER(rcu_bh, 'b', call_rcu_bh);
@@ -152,6 +152,8 @@ EXPORT_SYMBOL_GPL(rcu_scheduler_active);
  */
 static int rcu_scheduler_fully_active __read_mostly;
 
+static void rcu_init_new_rnp(struct rcu_node *rnp_leaf);
+static void rcu_cleanup_dead_rnp(struct rcu_node *rnp_leaf);
 static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu);
 static void invoke_rcu_core(void);
 static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp);
@@ -160,6 +162,12 @@ static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp);
 static int kthread_prio = CONFIG_RCU_KTHREAD_PRIO;
 module_param(kthread_prio, int, 0644);
 
+/* Delay in jiffies for grace-period initialization delays. */
+static int gp_init_delay = IS_ENABLED(CONFIG_RCU_TORTURE_TEST_SLOW_INIT)
+                               ? CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY
+                               : 0;
+module_param(gp_init_delay, int, 0644);
+
 /*
  * Track the rcutorture test sequence number and the update version
  * number within a given test.  The rcutorture_testseq is incremented
@@ -172,6 +180,17 @@ module_param(kthread_prio, int, 0644);
 unsigned long rcutorture_testseq;
 unsigned long rcutorture_vernum;
 
+/*
+ * Compute the mask of online CPUs for the specified rcu_node structure.
+ * This will not be stable unless the rcu_node structure's ->lock is
+ * held, but the bit corresponding to the current CPU will be stable
+ * in most contexts.
+ */
+unsigned long rcu_rnp_online_cpus(struct rcu_node *rnp)
+{
+       return ACCESS_ONCE(rnp->qsmaskinitnext);
+}
+
 /*
  * Return true if an RCU grace period is in progress.  The ACCESS_ONCE()s
  * permit this function to be invoked without holding the root rcu_node
@@ -292,10 +311,10 @@ void rcu_note_context_switch(void)
 EXPORT_SYMBOL_GPL(rcu_note_context_switch);
 
 /*
- * Register a quiesecent state for all RCU flavors.  If there is an
+ * Register a quiescent state for all RCU flavors.  If there is an
  * emergency, invoke rcu_momentary_dyntick_idle() to do a heavy-weight
  * dyntick-idle quiescent state visible to other CPUs (but only for those
- * RCU flavors in desparate need of a quiescent state, which will normally
+ * RCU flavors in desperate need of a quiescent state, which will normally
  * be none of them).  Either way, do a lightweight quiescent state for
  * all RCU flavors.
  */
@@ -409,6 +428,15 @@ void rcu_bh_force_quiescent_state(void)
 }
 EXPORT_SYMBOL_GPL(rcu_bh_force_quiescent_state);
 
+/*
+ * Force a quiescent state for RCU-sched.
+ */
+void rcu_sched_force_quiescent_state(void)
+{
+       force_quiescent_state(&rcu_sched_state);
+}
+EXPORT_SYMBOL_GPL(rcu_sched_force_quiescent_state);
+
 /*
  * Show the state of the grace-period kthreads.
  */
@@ -482,15 +510,6 @@ void rcutorture_record_progress(unsigned long vernum)
 }
 EXPORT_SYMBOL_GPL(rcutorture_record_progress);
 
-/*
- * Force a quiescent state for RCU-sched.
- */
-void rcu_sched_force_quiescent_state(void)
-{
-       force_quiescent_state(&rcu_sched_state);
-}
-EXPORT_SYMBOL_GPL(rcu_sched_force_quiescent_state);
-
 /*
  * Does the CPU have callbacks ready to be invoked?
  */
@@ -954,7 +973,7 @@ bool rcu_lockdep_current_cpu_online(void)
        preempt_disable();
        rdp = this_cpu_ptr(&rcu_sched_data);
        rnp = rdp->mynode;
-       ret = (rdp->grpmask & rnp->qsmaskinit) ||
+       ret = (rdp->grpmask & rcu_rnp_online_cpus(rnp)) ||
              !rcu_scheduler_fully_active;
        preempt_enable();
        return ret;
@@ -1196,9 +1215,10 @@ static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum)
                } else {
                        j = jiffies;
                        gpa = ACCESS_ONCE(rsp->gp_activity);
-                       pr_err("All QSes seen, last %s kthread activity %ld (%ld-%ld), jiffies_till_next_fqs=%ld\n",
+                       pr_err("All QSes seen, last %s kthread activity %ld (%ld-%ld), jiffies_till_next_fqs=%ld, root ->qsmask %#lx\n",
                               rsp->name, j - gpa, j, gpa,
-                              jiffies_till_next_fqs);
+                              jiffies_till_next_fqs,
+                              rcu_get_root(rsp)->qsmask);
                        /* In this case, the current CPU might be at fault. */
                        sched_show_task(current);
                }
@@ -1328,19 +1348,29 @@ void rcu_cpu_stall_reset(void)
 }
 
 /*
- * Initialize the specified rcu_data structure's callback list to empty.
+ * Initialize the specified rcu_data structure's default callback list
+ * to empty.  The default callback list is the one that is not used by
+ * no-callbacks CPUs.
  */
-static void init_callback_list(struct rcu_data *rdp)
+static void init_default_callback_list(struct rcu_data *rdp)
 {
        int i;
 
-       if (init_nocb_callback_list(rdp))
-               return;
        rdp->nxtlist = NULL;
        for (i = 0; i < RCU_NEXT_SIZE; i++)
                rdp->nxttail[i] = &rdp->nxtlist;
 }
 
+/*
+ * Initialize the specified rcu_data structure's callback list to empty.
+ */
+static void init_callback_list(struct rcu_data *rdp)
+{
+       if (init_nocb_callback_list(rdp))
+               return;
+       init_default_callback_list(rdp);
+}
+
 /*
  * Determine the value that ->completed will have at the end of the
  * next subsequent grace period.  This is used to tag callbacks so that
@@ -1703,11 +1733,11 @@ static void note_gp_changes(struct rcu_state *rsp, struct rcu_data *rdp)
  */
 static int rcu_gp_init(struct rcu_state *rsp)
 {
+       unsigned long oldmask;
        struct rcu_data *rdp;
        struct rcu_node *rnp = rcu_get_root(rsp);
 
        ACCESS_ONCE(rsp->gp_activity) = jiffies;
-       rcu_bind_gp_kthread();
        raw_spin_lock_irq(&rnp->lock);
        smp_mb__after_unlock_lock();
        if (!ACCESS_ONCE(rsp->gp_flags)) {
@@ -1733,9 +1763,54 @@ static int rcu_gp_init(struct rcu_state *rsp)
        trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start"));
        raw_spin_unlock_irq(&rnp->lock);
 
-       /* Exclude any concurrent CPU-hotplug operations. */
-       mutex_lock(&rsp->onoff_mutex);
-       smp_mb__after_unlock_lock(); /* ->gpnum increment before GP! */
+       /*
+        * Apply per-leaf buffered online and offline operations to the
+        * rcu_node tree.  Note that this new grace period need not wait
+        * for subsequent online CPUs, and that quiescent-state forcing
+        * will handle subsequent offline CPUs.
+        */
+       rcu_for_each_leaf_node(rsp, rnp) {
+               raw_spin_lock_irq(&rnp->lock);
+               smp_mb__after_unlock_lock();
+               if (rnp->qsmaskinit == rnp->qsmaskinitnext &&
+                   !rnp->wait_blkd_tasks) {
+                       /* Nothing to do on this leaf rcu_node structure. */
+                       raw_spin_unlock_irq(&rnp->lock);
+                       continue;
+               }
+
+               /* Record old state, apply changes to ->qsmaskinit field. */
+               oldmask = rnp->qsmaskinit;
+               rnp->qsmaskinit = rnp->qsmaskinitnext;
+
+               /* If zero-ness of ->qsmaskinit changed, propagate up tree. */
+               if (!oldmask != !rnp->qsmaskinit) {
+                       if (!oldmask) /* First online CPU for this rcu_node. */
+                               rcu_init_new_rnp(rnp);
+                       else if (rcu_preempt_has_tasks(rnp)) /* blocked tasks */
+                               rnp->wait_blkd_tasks = true;
+                       else /* Last offline CPU and can propagate. */
+                               rcu_cleanup_dead_rnp(rnp);
+               }
+
+               /*
+                * If all waited-on tasks from prior grace period are
+                * done, and if all this rcu_node structure's CPUs are
+                * still offline, propagate up the rcu_node tree and
+                * clear ->wait_blkd_tasks.  Otherwise, if one of this
+                * rcu_node structure's CPUs has since come back online,
+                * simply clear ->wait_blkd_tasks (but rcu_cleanup_dead_rnp()
+                * checks for this, so just call it unconditionally).
+                */
+               if (rnp->wait_blkd_tasks &&
+                   (!rcu_preempt_has_tasks(rnp) ||
+                    rnp->qsmaskinit)) {
+                       rnp->wait_blkd_tasks = false;
+                       rcu_cleanup_dead_rnp(rnp);
+               }
+
+               raw_spin_unlock_irq(&rnp->lock);
+       }
 
        /*
         * Set the quiescent-state-needed bits in all the rcu_node
@@ -1757,8 +1832,8 @@ static int rcu_gp_init(struct rcu_state *rsp)
                rcu_preempt_check_blocked_tasks(rnp);
                rnp->qsmask = rnp->qsmaskinit;
                ACCESS_ONCE(rnp->gpnum) = rsp->gpnum;
-               WARN_ON_ONCE(rnp->completed != rsp->completed);
-               ACCESS_ONCE(rnp->completed) = rsp->completed;
+               if (WARN_ON_ONCE(rnp->completed != rsp->completed))
+                       ACCESS_ONCE(rnp->completed) = rsp->completed;
                if (rnp == rdp->mynode)
                        (void)__note_gp_changes(rsp, rnp, rdp);
                rcu_preempt_boost_start_gp(rnp);
@@ -1768,9 +1843,12 @@ static int rcu_gp_init(struct rcu_state *rsp)
                raw_spin_unlock_irq(&rnp->lock);
                cond_resched_rcu_qs();
                ACCESS_ONCE(rsp->gp_activity) = jiffies;
+               if (IS_ENABLED(CONFIG_RCU_TORTURE_TEST_SLOW_INIT) &&
+                   gp_init_delay > 0 &&
+                   !(rsp->gpnum % (rcu_num_nodes * 10)))
+                       schedule_timeout_uninterruptible(gp_init_delay);
        }
 
-       mutex_unlock(&rsp->onoff_mutex);
        return 1;
 }
 
@@ -1798,7 +1876,7 @@ static int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in)
                fqs_state = RCU_FORCE_QS;
        } else {
                /* Handle dyntick-idle and offline CPUs. */
-               isidle = false;
+               isidle = true;
                force_qs_rnp(rsp, rcu_implicit_dynticks_qs, &isidle, &maxj);
        }
        /* Clear flag to prevent immediate re-entry. */
@@ -1852,6 +1930,8 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
        rcu_for_each_node_breadth_first(rsp, rnp) {
                raw_spin_lock_irq(&rnp->lock);
                smp_mb__after_unlock_lock();
+               WARN_ON_ONCE(rcu_preempt_blocked_readers_cgp(rnp));
+               WARN_ON_ONCE(rnp->qsmask);
                ACCESS_ONCE(rnp->completed) = rsp->gpnum;
                rdp = this_cpu_ptr(rsp->rda);
                if (rnp == rdp->mynode)
@@ -1895,6 +1975,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
        struct rcu_state *rsp = arg;
        struct rcu_node *rnp = rcu_get_root(rsp);
 
+       rcu_bind_gp_kthread();
        for (;;) {
 
                /* Handle grace-period start. */
@@ -2062,25 +2143,32 @@ static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags)
  * Similar to rcu_report_qs_rdp(), for which it is a helper function.
  * Allows quiescent states for a group of CPUs to be reported at one go
  * to the specified rcu_node structure, though all the CPUs in the group
- * must be represented by the same rcu_node structure (which need not be
- * a leaf rcu_node structure, though it often will be).  That structure's
- * lock must be held upon entry, and it is released before return.
+ * must be represented by the same rcu_node structure (which need not be a
+ * leaf rcu_node structure, though it often will be).  The gps parameter
+ * is the grace-period snapshot, which means that the quiescent states
+ * are valid only if rnp->gpnum is equal to gps.  That structure's lock
+ * must be held upon entry, and it is released before return.
  */
 static void
 rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp,
-                 struct rcu_node *rnp, unsigned long flags)
+                 struct rcu_node *rnp, unsigned long gps, unsigned long flags)
        __releases(rnp->lock)
 {
+       unsigned long oldmask = 0;
        struct rcu_node *rnp_c;
 
        /* Walk up the rcu_node hierarchy. */
        for (;;) {
-               if (!(rnp->qsmask & mask)) {
+               if (!(rnp->qsmask & mask) || rnp->gpnum != gps) {
 
-                       /* Our bit has already been cleared, so done. */
+                       /*
+                        * Our bit has already been cleared, or the
+                        * relevant grace period is already over, so done.
+                        */
                        raw_spin_unlock_irqrestore(&rnp->lock, flags);
                        return;
                }
+               WARN_ON_ONCE(oldmask); /* Any child must be all zeroed! */
                rnp->qsmask &= ~mask;
                trace_rcu_quiescent_state_report(rsp->name, rnp->gpnum,
                                                 mask, rnp->qsmask, rnp->level,
@@ -2104,7 +2192,7 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp,
                rnp = rnp->parent;
                raw_spin_lock_irqsave(&rnp->lock, flags);
                smp_mb__after_unlock_lock();
-               WARN_ON_ONCE(rnp_c->qsmask);
+               oldmask = rnp_c->qsmask;
        }
 
        /*
@@ -2115,6 +2203,46 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp,
        rcu_report_qs_rsp(rsp, flags); /* releases rnp->lock. */
 }
 
+/*
+ * Record a quiescent state for all tasks that were previously queued
+ * on the specified rcu_node structure and that were blocking the current
+ * RCU grace period.  The caller must hold the specified rnp->lock with
+ * irqs disabled, and this lock is released upon return, but irqs remain
+ * disabled.
+ */
+static void rcu_report_unblock_qs_rnp(struct rcu_state *rsp,
+                                     struct rcu_node *rnp, unsigned long flags)
+       __releases(rnp->lock)
+{
+       unsigned long gps;
+       unsigned long mask;
+       struct rcu_node *rnp_p;
+
+       if (rcu_state_p == &rcu_sched_state || rsp != rcu_state_p ||
+           rnp->qsmask != 0 || rcu_preempt_blocked_readers_cgp(rnp)) {
+               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               return;  /* Still need more quiescent states! */
+       }
+
+       rnp_p = rnp->parent;
+       if (rnp_p == NULL) {
+               /*
+                * Only one rcu_node structure in the tree, so don't
+                * try to report up to its nonexistent parent!
+                */
+               rcu_report_qs_rsp(rsp, flags);
+               return;
+       }
+
+       /* Report up the rest of the hierarchy, tracking current ->gpnum. */
+       gps = rnp->gpnum;
+       mask = rnp->grpmask;
+       raw_spin_unlock(&rnp->lock);    /* irqs remain disabled. */
+       raw_spin_lock(&rnp_p->lock);    /* irqs already disabled. */
+       smp_mb__after_unlock_lock();
+       rcu_report_qs_rnp(mask, rsp, rnp_p, gps, flags);
+}
+
 /*
  * Record a quiescent state for the specified CPU to that CPU's rcu_data
  * structure.  This must be either called from the specified CPU, or
@@ -2163,7 +2291,8 @@ rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp)
                 */
                needwake = rcu_accelerate_cbs(rsp, rnp, rdp);
 
-               rcu_report_qs_rnp(mask, rsp, rnp, flags); /* rlses rnp->lock */
+               rcu_report_qs_rnp(mask, rsp, rnp, rnp->gpnum, flags);
+               /* ^^^ Released rnp->lock */
                if (needwake)
                        rcu_gp_kthread_wake(rsp);
        }
@@ -2256,8 +2385,12 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
                rsp->orphan_donetail = rdp->nxttail[RCU_DONE_TAIL];
        }
 
-       /* Finally, initialize the rcu_data structure's list to empty.  */
+       /*
+        * Finally, initialize the rcu_data structure's list to empty and
+        * disallow further callbacks on this CPU.
+        */
        init_callback_list(rdp);
+       rdp->nxttail[RCU_NEXT_TAIL] = NULL;
 }
 
 /*
@@ -2355,6 +2488,7 @@ static void rcu_cleanup_dead_rnp(struct rcu_node *rnp_leaf)
                raw_spin_lock(&rnp->lock); /* irqs already disabled. */
                smp_mb__after_unlock_lock(); /* GP memory ordering. */
                rnp->qsmaskinit &= ~mask;
+               rnp->qsmask &= ~mask;
                if (rnp->qsmaskinit) {
                        raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
                        return;
@@ -2363,6 +2497,26 @@ static void rcu_cleanup_dead_rnp(struct rcu_node *rnp_leaf)
        }
 }
 
+/*
+ * The CPU is exiting the idle loop into the arch_cpu_idle_dead()
+ * function.  We now remove it from the rcu_node tree's ->qsmaskinit
+ * bit masks.
+ */
+static void rcu_cleanup_dying_idle_cpu(int cpu, struct rcu_state *rsp)
+{
+       unsigned long flags;
+       unsigned long mask;
+       struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
+       struct rcu_node *rnp = rdp->mynode;  /* Outgoing CPU's rdp & rnp. */
+
+       /* Remove outgoing CPU from mask in the leaf rcu_node structure. */
+       mask = rdp->grpmask;
+       raw_spin_lock_irqsave(&rnp->lock, flags);
+       smp_mb__after_unlock_lock();    /* Enforce GP memory-order guarantee. */
+       rnp->qsmaskinitnext &= ~mask;
+       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+}
+
 /*
  * The CPU has been completely removed, and some other CPU is reporting
  * this fact from process context.  Do the remainder of the cleanup,
@@ -2379,29 +2533,15 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
        /* Adjust any no-longer-needed kthreads. */
        rcu_boost_kthread_setaffinity(rnp, -1);
 
-       /* Exclude any attempts to start a new grace period. */
-       mutex_lock(&rsp->onoff_mutex);
-       raw_spin_lock_irqsave(&rsp->orphan_lock, flags);
-
        /* Orphan the dead CPU's callbacks, and adopt them if appropriate. */
+       raw_spin_lock_irqsave(&rsp->orphan_lock, flags);
        rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp);
        rcu_adopt_orphan_cbs(rsp, flags);
        raw_spin_unlock_irqrestore(&rsp->orphan_lock, flags);
 
-       /* Remove outgoing CPU from mask in the leaf rcu_node structure. */
-       raw_spin_lock_irqsave(&rnp->lock, flags);
-       smp_mb__after_unlock_lock();    /* Enforce GP memory-order guarantee. */
-       rnp->qsmaskinit &= ~rdp->grpmask;
-       if (rnp->qsmaskinit == 0 && !rcu_preempt_has_tasks(rnp))
-               rcu_cleanup_dead_rnp(rnp);
-       rcu_report_qs_rnp(rdp->grpmask, rsp, rnp, flags); /* Rlses rnp->lock. */
        WARN_ONCE(rdp->qlen != 0 || rdp->nxtlist != NULL,
                  "rcu_cleanup_dead_cpu: Callbacks on offline CPU %d: qlen=%lu, nxtlist=%p\n",
                  cpu, rdp->qlen, rdp->nxtlist);
-       init_callback_list(rdp);
-       /* Disallow further callbacks on this CPU. */
-       rdp->nxttail[RCU_NEXT_TAIL] = NULL;
-       mutex_unlock(&rsp->onoff_mutex);
 }
 
 #else /* #ifdef CONFIG_HOTPLUG_CPU */
@@ -2414,6 +2554,10 @@ static void __maybe_unused rcu_cleanup_dead_rnp(struct rcu_node *rnp_leaf)
 {
 }
 
+static void rcu_cleanup_dying_idle_cpu(int cpu, struct rcu_state *rsp)
+{
+}
+
 static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
 {
 }
@@ -2589,26 +2733,47 @@ static void force_qs_rnp(struct rcu_state *rsp,
                        return;
                }
                if (rnp->qsmask == 0) {
-                       rcu_initiate_boost(rnp, flags); /* releases rnp->lock */
-                       continue;
+                       if (rcu_state_p == &rcu_sched_state ||
+                           rsp != rcu_state_p ||
+                           rcu_preempt_blocked_readers_cgp(rnp)) {
+                               /*
+                                * No point in scanning bits because they
+                                * are all zero.  But we might need to
+                                * priority-boost blocked readers.
+                                */
+                               rcu_initiate_boost(rnp, flags);
+                               /* rcu_initiate_boost() releases rnp->lock */
+                               continue;
+                       }
+                       if (rnp->parent &&
+                           (rnp->parent->qsmask & rnp->grpmask)) {
+                               /*
+                                * Race between grace-period
+                                * initialization and task exiting RCU
+                                * read-side critical section: Report.
+                                */
+                               rcu_report_unblock_qs_rnp(rsp, rnp, flags);
+                               /* rcu_report_unblock_qs_rnp() rlses ->lock */
+                               continue;
+                       }
                }
                cpu = rnp->grplo;
                bit = 1;
                for (; cpu <= rnp->grphi; cpu++, bit <<= 1) {
                        if ((rnp->qsmask & bit) != 0) {
-                               if ((rnp->qsmaskinit & bit) != 0)
-                                       *isidle = false;
+                               if ((rnp->qsmaskinit & bit) == 0)
+                                       *isidle = false; /* Pending hotplug. */
                                if (f(per_cpu_ptr(rsp->rda, cpu), isidle, maxj))
                                        mask |= bit;
                        }
                }
                if (mask != 0) {
-
-                       /* rcu_report_qs_rnp() releases rnp->lock. */
-                       rcu_report_qs_rnp(mask, rsp, rnp, flags);
-                       continue;
+                       /* Idle/offline CPUs, report (releases rnp->lock. */
+                       rcu_report_qs_rnp(mask, rsp, rnp, rnp->gpnum, flags);
+               } else {
+                       /* Nothing to do here, so just drop the lock. */
+                       raw_spin_unlock_irqrestore(&rnp->lock, flags);
                }
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
        }
 }
 
@@ -2741,7 +2906,7 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,
         * If called from an extended quiescent state, invoke the RCU
         * core in order to force a re-evaluation of RCU's idleness.
         */
-       if (!rcu_is_watching() && cpu_online(smp_processor_id()))
+       if (!rcu_is_watching())
                invoke_rcu_core();
 
        /* If interrupts were disabled or CPU offline, don't invoke RCU core. */
@@ -2827,11 +2992,22 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
 
                if (cpu != -1)
                        rdp = per_cpu_ptr(rsp->rda, cpu);
-               offline = !__call_rcu_nocb(rdp, head, lazy, flags);
-               WARN_ON_ONCE(offline);
-               /* _call_rcu() is illegal on offline CPU; leak the callback. */
-               local_irq_restore(flags);
-               return;
+               if (likely(rdp->mynode)) {
+                       /* Post-boot, so this should be for a no-CBs CPU. */
+                       offline = !__call_rcu_nocb(rdp, head, lazy, flags);
+                       WARN_ON_ONCE(offline);
+                       /* Offline CPU, _call_rcu() illegal, leak callback.  */
+                       local_irq_restore(flags);
+                       return;
+               }
+               /*
+                * Very early boot, before rcu_init().  Initialize if needed
+                * and then drop through to queue the callback.
+                */
+               BUG_ON(cpu != -1);
+               WARN_ON_ONCE(!rcu_is_watching());
+               if (!likely(rdp->nxtlist))
+                       init_default_callback_list(rdp);
        }
        ACCESS_ONCE(rdp->qlen) = rdp->qlen + 1;
        if (lazy)
@@ -2954,7 +3130,7 @@ void synchronize_sched(void)
                           "Illegal synchronize_sched() in RCU-sched read-side critical section");
        if (rcu_blocking_is_gp())
                return;
-       if (rcu_expedited)
+       if (rcu_gp_is_expedited())
                synchronize_sched_expedited();
        else
                wait_rcu_gp(call_rcu_sched);
@@ -2981,7 +3157,7 @@ void synchronize_rcu_bh(void)
                           "Illegal synchronize_rcu_bh() in RCU-bh read-side critical section");
        if (rcu_blocking_is_gp())
                return;
-       if (rcu_expedited)
+       if (rcu_gp_is_expedited())
                synchronize_rcu_bh_expedited();
        else
                wait_rcu_gp(call_rcu_bh);
@@ -3517,6 +3693,28 @@ void rcu_barrier_sched(void)
 }
 EXPORT_SYMBOL_GPL(rcu_barrier_sched);
 
+/*
+ * Propagate ->qsinitmask bits up the rcu_node tree to account for the
+ * first CPU in a given leaf rcu_node structure coming online.  The caller
+ * must hold the corresponding leaf rcu_node ->lock with interrrupts
+ * disabled.
+ */
+static void rcu_init_new_rnp(struct rcu_node *rnp_leaf)
+{
+       long mask;
+       struct rcu_node *rnp = rnp_leaf;
+
+       for (;;) {
+               mask = rnp->grpmask;
+               rnp = rnp->parent;
+               if (rnp == NULL)
+                       return;
+               raw_spin_lock(&rnp->lock); /* Interrupts already disabled. */
+               rnp->qsmaskinit |= mask;
+               raw_spin_unlock(&rnp->lock); /* Interrupts remain disabled. */
+       }
+}
+
 /*
  * Do boot-time initialization of a CPU's per-CPU RCU data.
  */
@@ -3553,49 +3751,37 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp)
        struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
        struct rcu_node *rnp = rcu_get_root(rsp);
 
-       /* Exclude new grace periods. */
-       mutex_lock(&rsp->onoff_mutex);
-
        /* Set up local state, ensuring consistent view of global state. */
        raw_spin_lock_irqsave(&rnp->lock, flags);
        rdp->beenonline = 1;     /* We have now been online. */
        rdp->qlen_last_fqs_check = 0;
        rdp->n_force_qs_snap = rsp->n_force_qs;
        rdp->blimit = blimit;
-       init_callback_list(rdp);  /* Re-enable callbacks on this CPU. */
+       if (!rdp->nxtlist)
+               init_callback_list(rdp);  /* Re-enable callbacks on this CPU. */
        rdp->dynticks->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
        rcu_sysidle_init_percpu_data(rdp->dynticks);
        atomic_set(&rdp->dynticks->dynticks,
                   (atomic_read(&rdp->dynticks->dynticks) & ~0x1) + 1);
        raw_spin_unlock(&rnp->lock);            /* irqs remain disabled. */
 
-       /* Add CPU to rcu_node bitmasks. */
+       /*
+        * Add CPU to leaf rcu_node pending-online bitmask.  Any needed
+        * propagation up the rcu_node tree will happen at the beginning
+        * of the next grace period.
+        */
        rnp = rdp->mynode;
        mask = rdp->grpmask;
-       do {
-               /* Exclude any attempts to start a new GP on small systems. */
-               raw_spin_lock(&rnp->lock);      /* irqs already disabled. */
-               rnp->qsmaskinit |= mask;
-               mask = rnp->grpmask;
-               if (rnp == rdp->mynode) {
-                       /*
-                        * If there is a grace period in progress, we will
-                        * set up to wait for it next time we run the
-                        * RCU core code.
-                        */
-                       rdp->gpnum = rnp->completed;
-                       rdp->completed = rnp->completed;
-                       rdp->passed_quiesce = 0;
-                       rdp->rcu_qs_ctr_snap = __this_cpu_read(rcu_qs_ctr);
-                       rdp->qs_pending = 0;
-                       trace_rcu_grace_period(rsp->name, rdp->gpnum, TPS("cpuonl"));
-               }
-               raw_spin_unlock(&rnp->lock); /* irqs already disabled. */
-               rnp = rnp->parent;
-       } while (rnp != NULL && !(rnp->qsmaskinit & mask));
-       local_irq_restore(flags);
-
-       mutex_unlock(&rsp->onoff_mutex);
+       raw_spin_lock(&rnp->lock);              /* irqs already disabled. */
+       smp_mb__after_unlock_lock();
+       rnp->qsmaskinitnext |= mask;
+       rdp->gpnum = rnp->completed; /* Make CPU later note any new GP. */
+       rdp->completed = rnp->completed;
+       rdp->passed_quiesce = false;
+       rdp->rcu_qs_ctr_snap = __this_cpu_read(rcu_qs_ctr);
+       rdp->qs_pending = false;
+       trace_rcu_grace_period(rsp->name, rdp->gpnum, TPS("cpuonl"));
+       raw_spin_unlock_irqrestore(&rnp->lock, flags);
 }
 
 static void rcu_prepare_cpu(int cpu)
@@ -3609,15 +3795,14 @@ static void rcu_prepare_cpu(int cpu)
 /*
  * Handle CPU online/offline notification events.
  */
-static int rcu_cpu_notify(struct notifier_block *self,
-                                   unsigned long action, void *hcpu)
+int rcu_cpu_notify(struct notifier_block *self,
+                  unsigned long action, void *hcpu)
 {
        long cpu = (long)hcpu;
        struct rcu_data *rdp = per_cpu_ptr(rcu_state_p->rda, cpu);
        struct rcu_node *rnp = rdp->mynode;
        struct rcu_state *rsp;
 
-       trace_rcu_utilization(TPS("Start CPU hotplug"));
        switch (action) {
        case CPU_UP_PREPARE:
        case CPU_UP_PREPARE_FROZEN:
@@ -3637,6 +3822,11 @@ static int rcu_cpu_notify(struct notifier_block *self,
                for_each_rcu_flavor(rsp)
                        rcu_cleanup_dying_cpu(rsp);
                break;
+       case CPU_DYING_IDLE:
+               for_each_rcu_flavor(rsp) {
+                       rcu_cleanup_dying_idle_cpu(cpu, rsp);
+               }
+               break;
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
        case CPU_UP_CANCELED:
@@ -3649,7 +3839,6 @@ static int rcu_cpu_notify(struct notifier_block *self,
        default:
                break;
        }
-       trace_rcu_utilization(TPS("End CPU hotplug"));
        return NOTIFY_OK;
 }
 
@@ -3660,11 +3849,12 @@ static int rcu_pm_notify(struct notifier_block *self,
        case PM_HIBERNATION_PREPARE:
        case PM_SUSPEND_PREPARE:
                if (nr_cpu_ids <= 256) /* Expediting bad for large systems. */
-                       rcu_expedited = 1;
+                       rcu_expedite_gp();
                break;
        case PM_POST_HIBERNATION:
        case PM_POST_SUSPEND:
-               rcu_expedited = 0;
+               if (nr_cpu_ids <= 256) /* Expediting bad for large systems. */
+                       rcu_unexpedite_gp();
                break;
        default:
                break;
@@ -3734,30 +3924,26 @@ void rcu_scheduler_starting(void)
  * Compute the per-level fanout, either using the exact fanout specified
  * or balancing the tree, depending on CONFIG_RCU_FANOUT_EXACT.
  */
-#ifdef CONFIG_RCU_FANOUT_EXACT
-static void __init rcu_init_levelspread(struct rcu_state *rsp)
-{
-       int i;
-
-       rsp->levelspread[rcu_num_lvls - 1] = rcu_fanout_leaf;
-       for (i = rcu_num_lvls - 2; i >= 0; i--)
-               rsp->levelspread[i] = CONFIG_RCU_FANOUT;
-}
-#else /* #ifdef CONFIG_RCU_FANOUT_EXACT */
 static void __init rcu_init_levelspread(struct rcu_state *rsp)
 {
-       int ccur;
-       int cprv;
        int i;
 
-       cprv = nr_cpu_ids;
-       for (i = rcu_num_lvls - 1; i >= 0; i--) {
-               ccur = rsp->levelcnt[i];
-               rsp->levelspread[i] = (cprv + ccur - 1) / ccur;
-               cprv = ccur;
+       if (IS_ENABLED(CONFIG_RCU_FANOUT_EXACT)) {
+               rsp->levelspread[rcu_num_lvls - 1] = rcu_fanout_leaf;
+               for (i = rcu_num_lvls - 2; i >= 0; i--)
+                       rsp->levelspread[i] = CONFIG_RCU_FANOUT;
+       } else {
+               int ccur;
+               int cprv;
+
+               cprv = nr_cpu_ids;
+               for (i = rcu_num_lvls - 1; i >= 0; i--) {
+                       ccur = rsp->levelcnt[i];
+                       rsp->levelspread[i] = (cprv + ccur - 1) / ccur;
+                       cprv = ccur;
+               }
        }
 }
-#endif /* #else #ifdef CONFIG_RCU_FANOUT_EXACT */
 
 /*
  * Helper function for rcu_init() that initializes one rcu_state structure.
@@ -3833,7 +4019,6 @@ static void __init rcu_init_one(struct rcu_state *rsp,
                }
        }
 
-       rsp->rda = rda;
        init_waitqueue_head(&rsp->gp_wq);
        rnp = rsp->level[rcu_num_lvls - 1];
        for_each_possible_cpu(i) {
@@ -3926,6 +4111,8 @@ void __init rcu_init(void)
 {
        int cpu;
 
+       rcu_early_boot_tests();
+
        rcu_bootup_announce();
        rcu_init_geometry();
        rcu_init_one(&rcu_bh_state, &rcu_bh_data);
@@ -3942,8 +4129,6 @@ void __init rcu_init(void)
        pm_notifier(rcu_pm_notify, 0);
        for_each_online_cpu(cpu)
                rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
-
-       rcu_early_boot_tests();
 }
 
 #include "tree_plugin.h"
index 119de399eb2f7e532f607e85f2d31c1b9e324541..a69d3dab2ec4dbf9dc8c412813c84c27363f9378 100644 (file)
@@ -141,12 +141,20 @@ struct rcu_node {
                                /*  complete (only for PREEMPT_RCU). */
        unsigned long qsmaskinit;
                                /* Per-GP initial value for qsmask & expmask. */
+                               /*  Initialized from ->qsmaskinitnext at the */
+                               /*  beginning of each grace period. */
+       unsigned long qsmaskinitnext;
+                               /* Online CPUs for next grace period. */
        unsigned long grpmask;  /* Mask to apply to parent qsmask. */
                                /*  Only one bit will be set in this mask. */
        int     grplo;          /* lowest-numbered CPU or group here. */
        int     grphi;          /* highest-numbered CPU or group here. */
        u8      grpnum;         /* CPU/group number for next level up. */
        u8      level;          /* root is at level 0. */
+       bool    wait_blkd_tasks;/* Necessary to wait for blocked tasks to */
+                               /*  exit RCU read-side critical sections */
+                               /*  before propagating offline up the */
+                               /*  rcu_node tree? */
        struct rcu_node *parent;
        struct list_head blkd_tasks;
                                /* Tasks blocked in RCU read-side critical */
@@ -448,8 +456,6 @@ struct rcu_state {
        long qlen;                              /* Total number of callbacks. */
        /* End of fields guarded by orphan_lock. */
 
-       struct mutex onoff_mutex;               /* Coordinate hotplug & GPs. */
-
        struct mutex barrier_mutex;             /* Guards barrier fields. */
        atomic_t barrier_cpu_count;             /* # CPUs waiting on. */
        struct completion barrier_completion;   /* Wake at barrier end. */
@@ -559,6 +565,7 @@ static void rcu_prepare_kthreads(int cpu);
 static void rcu_cleanup_after_idle(void);
 static void rcu_prepare_for_idle(void);
 static void rcu_idle_count_callbacks_posted(void);
+static bool rcu_preempt_has_tasks(struct rcu_node *rnp);
 static void print_cpu_stall_info_begin(void);
 static void print_cpu_stall_info(struct rcu_state *rsp, int cpu);
 static void print_cpu_stall_info_end(void);
index 0a571e9a0f1d00868c74c5032912c1a0b24dce94..8c0ec0f5a02702f1a3c5ed5db0bdf346ac7ae140 100644 (file)
@@ -58,38 +58,33 @@ static bool __read_mostly rcu_nocb_poll;    /* Offload kthread are to poll. */
  */
 static void __init rcu_bootup_announce_oddness(void)
 {
-#ifdef CONFIG_RCU_TRACE
-       pr_info("\tRCU debugfs-based tracing is enabled.\n");
-#endif
-#if (defined(CONFIG_64BIT) && CONFIG_RCU_FANOUT != 64) || (!defined(CONFIG_64BIT) && CONFIG_RCU_FANOUT != 32)
-       pr_info("\tCONFIG_RCU_FANOUT set to non-default value of %d\n",
-              CONFIG_RCU_FANOUT);
-#endif
-#ifdef CONFIG_RCU_FANOUT_EXACT
-       pr_info("\tHierarchical RCU autobalancing is disabled.\n");
-#endif
-#ifdef CONFIG_RCU_FAST_NO_HZ
-       pr_info("\tRCU dyntick-idle grace-period acceleration is enabled.\n");
-#endif
-#ifdef CONFIG_PROVE_RCU
-       pr_info("\tRCU lockdep checking is enabled.\n");
-#endif
-#ifdef CONFIG_RCU_TORTURE_TEST_RUNNABLE
-       pr_info("\tRCU torture testing starts during boot.\n");
-#endif
-#if defined(CONFIG_RCU_CPU_STALL_INFO)
-       pr_info("\tAdditional per-CPU info printed with stalls.\n");
-#endif
-#if NUM_RCU_LVL_4 != 0
-       pr_info("\tFour-level hierarchy is enabled.\n");
-#endif
+       if (IS_ENABLED(CONFIG_RCU_TRACE))
+               pr_info("\tRCU debugfs-based tracing is enabled.\n");
+       if ((IS_ENABLED(CONFIG_64BIT) && CONFIG_RCU_FANOUT != 64) ||
+           (!IS_ENABLED(CONFIG_64BIT) && CONFIG_RCU_FANOUT != 32))
+               pr_info("\tCONFIG_RCU_FANOUT set to non-default value of %d\n",
+                      CONFIG_RCU_FANOUT);
+       if (IS_ENABLED(CONFIG_RCU_FANOUT_EXACT))
+               pr_info("\tHierarchical RCU autobalancing is disabled.\n");
+       if (IS_ENABLED(CONFIG_RCU_FAST_NO_HZ))
+               pr_info("\tRCU dyntick-idle grace-period acceleration is enabled.\n");
+       if (IS_ENABLED(CONFIG_PROVE_RCU))
+               pr_info("\tRCU lockdep checking is enabled.\n");
+       if (IS_ENABLED(CONFIG_RCU_TORTURE_TEST_RUNNABLE))
+               pr_info("\tRCU torture testing starts during boot.\n");
+       if (IS_ENABLED(CONFIG_RCU_CPU_STALL_INFO))
+               pr_info("\tAdditional per-CPU info printed with stalls.\n");
+       if (NUM_RCU_LVL_4 != 0)
+               pr_info("\tFour-level hierarchy is enabled.\n");
+       if (CONFIG_RCU_FANOUT_LEAF != 16)
+               pr_info("\tBuild-time adjustment of leaf fanout to %d.\n",
+                       CONFIG_RCU_FANOUT_LEAF);
        if (rcu_fanout_leaf != CONFIG_RCU_FANOUT_LEAF)
                pr_info("\tBoot-time adjustment of leaf fanout to %d.\n", rcu_fanout_leaf);
        if (nr_cpu_ids != NR_CPUS)
                pr_info("\tRCU restricting CPUs from NR_CPUS=%d to nr_cpu_ids=%d.\n", NR_CPUS, nr_cpu_ids);
-#ifdef CONFIG_RCU_BOOST
-       pr_info("\tRCU kthread priority: %d.\n", kthread_prio);
-#endif
+       if (IS_ENABLED(CONFIG_RCU_BOOST))
+               pr_info("\tRCU kthread priority: %d.\n", kthread_prio);
 }
 
 #ifdef CONFIG_PREEMPT_RCU
@@ -180,7 +175,7 @@ static void rcu_preempt_note_context_switch(void)
                 * But first, note that the current CPU must still be
                 * on line!
                 */
-               WARN_ON_ONCE((rdp->grpmask & rnp->qsmaskinit) == 0);
+               WARN_ON_ONCE((rdp->grpmask & rcu_rnp_online_cpus(rnp)) == 0);
                WARN_ON_ONCE(!list_empty(&t->rcu_node_entry));
                if ((rnp->qsmask & rdp->grpmask) && rnp->gp_tasks != NULL) {
                        list_add(&t->rcu_node_entry, rnp->gp_tasks->prev);
@@ -232,43 +227,6 @@ static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp)
        return rnp->gp_tasks != NULL;
 }
 
-/*
- * Record a quiescent state for all tasks that were previously queued
- * on the specified rcu_node structure and that were blocking the current
- * RCU grace period.  The caller must hold the specified rnp->lock with
- * irqs disabled, and this lock is released upon return, but irqs remain
- * disabled.
- */
-static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)
-       __releases(rnp->lock)
-{
-       unsigned long mask;
-       struct rcu_node *rnp_p;
-
-       if (rnp->qsmask != 0 || rcu_preempt_blocked_readers_cgp(rnp)) {
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
-               return;  /* Still need more quiescent states! */
-       }
-
-       rnp_p = rnp->parent;
-       if (rnp_p == NULL) {
-               /*
-                * Either there is only one rcu_node in the tree,
-                * or tasks were kicked up to root rcu_node due to
-                * CPUs going offline.
-                */
-               rcu_report_qs_rsp(&rcu_preempt_state, flags);
-               return;
-       }
-
-       /* Report up the rest of the hierarchy. */
-       mask = rnp->grpmask;
-       raw_spin_unlock(&rnp->lock);    /* irqs remain disabled. */
-       raw_spin_lock(&rnp_p->lock);    /* irqs already disabled. */
-       smp_mb__after_unlock_lock();
-       rcu_report_qs_rnp(mask, &rcu_preempt_state, rnp_p, flags);
-}
-
 /*
  * Advance a ->blkd_tasks-list pointer to the next entry, instead
  * returning NULL if at the end of the list.
@@ -300,7 +258,6 @@ static bool rcu_preempt_has_tasks(struct rcu_node *rnp)
  */
 void rcu_read_unlock_special(struct task_struct *t)
 {
-       bool empty;
        bool empty_exp;
        bool empty_norm;
        bool empty_exp_now;
@@ -334,7 +291,13 @@ void rcu_read_unlock_special(struct task_struct *t)
        }
 
        /* Hardware IRQ handlers cannot block, complain if they get here. */
-       if (WARN_ON_ONCE(in_irq() || in_serving_softirq())) {
+       if (in_irq() || in_serving_softirq()) {
+               lockdep_rcu_suspicious(__FILE__, __LINE__,
+                                      "rcu_read_unlock() from irq or softirq with blocking in critical section!!!\n");
+               pr_alert("->rcu_read_unlock_special: %#x (b: %d, nq: %d)\n",
+                        t->rcu_read_unlock_special.s,
+                        t->rcu_read_unlock_special.b.blocked,
+                        t->rcu_read_unlock_special.b.need_qs);
                local_irq_restore(flags);
                return;
        }
@@ -356,7 +319,6 @@ void rcu_read_unlock_special(struct task_struct *t)
                                break;
                        raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
                }
-               empty = !rcu_preempt_has_tasks(rnp);
                empty_norm = !rcu_preempt_blocked_readers_cgp(rnp);
                empty_exp = !rcu_preempted_readers_exp(rnp);
                smp_mb(); /* ensure expedited fastpath sees end of RCU c-s. */
@@ -376,14 +338,6 @@ void rcu_read_unlock_special(struct task_struct *t)
                drop_boost_mutex = rt_mutex_owner(&rnp->boost_mtx) == t;
 #endif /* #ifdef CONFIG_RCU_BOOST */
 
-               /*
-                * If this was the last task on the list, go see if we
-                * need to propagate ->qsmaskinit bit clearing up the
-                * rcu_node tree.
-                */
-               if (!empty && !rcu_preempt_has_tasks(rnp))
-                       rcu_cleanup_dead_rnp(rnp);
-
                /*
                 * If this was the last task on the current list, and if
                 * we aren't waiting on any CPUs, report the quiescent state.
@@ -399,7 +353,8 @@ void rcu_read_unlock_special(struct task_struct *t)
                                                         rnp->grplo,
                                                         rnp->grphi,
                                                         !!rnp->gp_tasks);
-                       rcu_report_unblock_qs_rnp(rnp, flags);
+                       rcu_report_unblock_qs_rnp(&rcu_preempt_state,
+                                                 rnp, flags);
                } else {
                        raw_spin_unlock_irqrestore(&rnp->lock, flags);
                }
@@ -520,10 +475,6 @@ static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp)
        WARN_ON_ONCE(rnp->qsmask);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-
-#endif /* #ifdef CONFIG_HOTPLUG_CPU */
-
 /*
  * Check for a quiescent state from the current CPU.  When a task blocks,
  * the task is recorded in the corresponding CPU's rcu_node structure,
@@ -585,7 +536,7 @@ void synchronize_rcu(void)
                           "Illegal synchronize_rcu() in RCU read-side critical section");
        if (!rcu_scheduler_active)
                return;
-       if (rcu_expedited)
+       if (rcu_gp_is_expedited())
                synchronize_rcu_expedited();
        else
                wait_rcu_gp(call_rcu);
@@ -630,9 +581,6 @@ static int sync_rcu_preempt_exp_done(struct rcu_node *rnp)
  * recursively up the tree.  (Calm down, calm down, we do the recursion
  * iteratively!)
  *
- * Most callers will set the "wake" flag, but the task initiating the
- * expedited grace period need not wake itself.
- *
  * Caller must hold sync_rcu_preempt_exp_mutex.
  */
 static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,
@@ -667,29 +615,85 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,
 
 /*
  * Snapshot the tasks blocking the newly started preemptible-RCU expedited
- * grace period for the specified rcu_node structure.  If there are no such
- * tasks, report it up the rcu_node hierarchy.
+ * grace period for the specified rcu_node structure, phase 1.  If there
+ * are such tasks, set the ->expmask bits up the rcu_node tree and also
+ * set the ->expmask bits on the leaf rcu_node structures to tell phase 2
+ * that work is needed here.
  *
- * Caller must hold sync_rcu_preempt_exp_mutex and must exclude
- * CPU hotplug operations.
+ * Caller must hold sync_rcu_preempt_exp_mutex.
  */
 static void
-sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp)
+sync_rcu_preempt_exp_init1(struct rcu_state *rsp, struct rcu_node *rnp)
 {
        unsigned long flags;
-       int must_wait = 0;
+       unsigned long mask;
+       struct rcu_node *rnp_up;
 
        raw_spin_lock_irqsave(&rnp->lock, flags);
        smp_mb__after_unlock_lock();
+       WARN_ON_ONCE(rnp->expmask);
+       WARN_ON_ONCE(rnp->exp_tasks);
        if (!rcu_preempt_has_tasks(rnp)) {
+               /* No blocked tasks, nothing to do. */
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
-       } else {
+               return;
+       }
+       /* Call for Phase 2 and propagate ->expmask bits up the tree. */
+       rnp->expmask = 1;
+       rnp_up = rnp;
+       while (rnp_up->parent) {
+               mask = rnp_up->grpmask;
+               rnp_up = rnp_up->parent;
+               if (rnp_up->expmask & mask)
+                       break;
+               raw_spin_lock(&rnp_up->lock); /* irqs already off */
+               smp_mb__after_unlock_lock();
+               rnp_up->expmask |= mask;
+               raw_spin_unlock(&rnp_up->lock); /* irqs still off */
+       }
+       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+}
+
+/*
+ * Snapshot the tasks blocking the newly started preemptible-RCU expedited
+ * grace period for the specified rcu_node structure, phase 2.  If the
+ * leaf rcu_node structure has its ->expmask field set, check for tasks.
+ * If there are some, clear ->expmask and set ->exp_tasks accordingly,
+ * then initiate RCU priority boosting.  Otherwise, clear ->expmask and
+ * invoke rcu_report_exp_rnp() to clear out the upper-level ->expmask bits,
+ * enabling rcu_read_unlock_special() to do the bit-clearing.
+ *
+ * Caller must hold sync_rcu_preempt_exp_mutex.
+ */
+static void
+sync_rcu_preempt_exp_init2(struct rcu_state *rsp, struct rcu_node *rnp)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&rnp->lock, flags);
+       smp_mb__after_unlock_lock();
+       if (!rnp->expmask) {
+               /* Phase 1 didn't do anything, so Phase 2 doesn't either. */
+               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               return;
+       }
+
+       /* Phase 1 is over. */
+       rnp->expmask = 0;
+
+       /*
+        * If there are still blocked tasks, set up ->exp_tasks so that
+        * rcu_read_unlock_special() will wake us and then boost them.
+        */
+       if (rcu_preempt_has_tasks(rnp)) {
                rnp->exp_tasks = rnp->blkd_tasks.next;
                rcu_initiate_boost(rnp, flags);  /* releases rnp->lock */
-               must_wait = 1;
+               return;
        }
-       if (!must_wait)
-               rcu_report_exp_rnp(rsp, rnp, false); /* Don't wake self. */
+
+       /* No longer any blocked tasks, so undo bit setting. */
+       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       rcu_report_exp_rnp(rsp, rnp, false);
 }
 
 /**
@@ -706,7 +710,6 @@ sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp)
  */
 void synchronize_rcu_expedited(void)
 {
-       unsigned long flags;
        struct rcu_node *rnp;
        struct rcu_state *rsp = &rcu_preempt_state;
        unsigned long snap;
@@ -757,19 +760,16 @@ void synchronize_rcu_expedited(void)
        /* force all RCU readers onto ->blkd_tasks lists. */
        synchronize_sched_expedited();
 
-       /* Initialize ->expmask for all non-leaf rcu_node structures. */
-       rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) {
-               raw_spin_lock_irqsave(&rnp->lock, flags);
-               smp_mb__after_unlock_lock();
-               rnp->expmask = rnp->qsmaskinit;
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
-       }
-
-       /* Snapshot current state of ->blkd_tasks lists. */
+       /*
+        * Snapshot current state of ->blkd_tasks lists into ->expmask.
+        * Phase 1 sets bits and phase 2 permits rcu_read_unlock_special()
+        * to start clearing them.  Doing this in one phase leads to
+        * strange races between setting and clearing bits, so just say "no"!
+        */
+       rcu_for_each_leaf_node(rsp, rnp)
+               sync_rcu_preempt_exp_init1(rsp, rnp);
        rcu_for_each_leaf_node(rsp, rnp)
-               sync_rcu_preempt_exp_init(rsp, rnp);
-       if (NUM_RCU_NODES > 1)
-               sync_rcu_preempt_exp_init(rsp, rcu_get_root(rsp));
+               sync_rcu_preempt_exp_init2(rsp, rnp);
 
        put_online_cpus();
 
@@ -859,8 +859,6 @@ static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp)
        return 0;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-
 /*
  * Because there is no preemptible RCU, there can be no readers blocked.
  */
@@ -869,8 +867,6 @@ static bool rcu_preempt_has_tasks(struct rcu_node *rnp)
        return false;
 }
 
-#endif /* #ifdef CONFIG_HOTPLUG_CPU */
-
 /*
  * Because preemptible RCU does not exist, we never have to check for
  * tasks blocked within RCU read-side critical sections.
@@ -1170,7 +1166,7 @@ static void rcu_preempt_boost_start_gp(struct rcu_node *rnp)
  * Returns zero if all is well, a negated errno otherwise.
  */
 static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
-                                                struct rcu_node *rnp)
+                                      struct rcu_node *rnp)
 {
        int rnp_index = rnp - &rsp->node[0];
        unsigned long flags;
@@ -1180,7 +1176,7 @@ static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
        if (&rcu_preempt_state != rsp)
                return 0;
 
-       if (!rcu_scheduler_fully_active || rnp->qsmaskinit == 0)
+       if (!rcu_scheduler_fully_active || rcu_rnp_online_cpus(rnp) == 0)
                return 0;
 
        rsp->boost = 1;
@@ -1273,7 +1269,7 @@ static void rcu_cpu_kthread(unsigned int cpu)
 static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu)
 {
        struct task_struct *t = rnp->boost_kthread_task;
-       unsigned long mask = rnp->qsmaskinit;
+       unsigned long mask = rcu_rnp_online_cpus(rnp);
        cpumask_var_t cm;
        int cpu;
 
@@ -1945,7 +1941,8 @@ static bool rcu_nocb_cpu_needs_barrier(struct rcu_state *rsp, int cpu)
                rhp = ACCESS_ONCE(rdp->nocb_follower_head);
 
        /* Having no rcuo kthread but CBs after scheduler starts is bad! */
-       if (!ACCESS_ONCE(rdp->nocb_kthread) && rhp) {
+       if (!ACCESS_ONCE(rdp->nocb_kthread) && rhp &&
+           rcu_scheduler_fully_active) {
                /* RCU callback enqueued before CPU first came online??? */
                pr_err("RCU: Never-onlined no-CBs CPU %d has CB %p\n",
                       cpu, rhp->func);
@@ -2392,18 +2389,8 @@ void __init rcu_init_nohz(void)
                pr_info("\tPoll for callbacks from no-CBs CPUs.\n");
 
        for_each_rcu_flavor(rsp) {
-               for_each_cpu(cpu, rcu_nocb_mask) {
-                       struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
-
-                       /*
-                        * If there are early callbacks, they will need
-                        * to be moved to the nocb lists.
-                        */
-                       WARN_ON_ONCE(rdp->nxttail[RCU_NEXT_TAIL] !=
-                                    &rdp->nxtlist &&
-                                    rdp->nxttail[RCU_NEXT_TAIL] != NULL);
-                       init_nocb_callback_list(rdp);
-               }
+               for_each_cpu(cpu, rcu_nocb_mask)
+                       init_nocb_callback_list(per_cpu_ptr(rsp->rda, cpu));
                rcu_organize_nocb_kthreads(rsp);
        }
 }
@@ -2540,6 +2527,16 @@ static bool init_nocb_callback_list(struct rcu_data *rdp)
        if (!rcu_is_nocb_cpu(rdp->cpu))
                return false;
 
+       /* If there are early-boot callbacks, move them to nocb lists. */
+       if (rdp->nxtlist) {
+               rdp->nocb_head = rdp->nxtlist;
+               rdp->nocb_tail = rdp->nxttail[RCU_NEXT_TAIL];
+               atomic_long_set(&rdp->nocb_q_count, rdp->qlen);
+               atomic_long_set(&rdp->nocb_q_count_lazy, rdp->qlen_lazy);
+               rdp->nxtlist = NULL;
+               rdp->qlen = 0;
+               rdp->qlen_lazy = 0;
+       }
        rdp->nxttail[RCU_NEXT_TAIL] = NULL;
        return true;
 }
@@ -2763,7 +2760,8 @@ static void rcu_sysidle_exit(int irq)
 
 /*
  * Check to see if the current CPU is idle.  Note that usermode execution
- * does not count as idle.  The caller must have disabled interrupts.
+ * does not count as idle.  The caller must have disabled interrupts,
+ * and must be running on tick_do_timer_cpu.
  */
 static void rcu_sysidle_check_cpu(struct rcu_data *rdp, bool *isidle,
                                  unsigned long *maxj)
@@ -2784,8 +2782,8 @@ static void rcu_sysidle_check_cpu(struct rcu_data *rdp, bool *isidle,
        if (!*isidle || rdp->rsp != rcu_state_p ||
            cpu_is_offline(rdp->cpu) || rdp->cpu == tick_do_timer_cpu)
                return;
-       if (rcu_gp_in_progress(rdp->rsp))
-               WARN_ON_ONCE(smp_processor_id() != tick_do_timer_cpu);
+       /* Verify affinity of current kthread. */
+       WARN_ON_ONCE(smp_processor_id() != tick_do_timer_cpu);
 
        /* Pick up current idle and NMI-nesting counter and check. */
        cur = atomic_read(&rdtp->dynticks_idle);
@@ -3068,11 +3066,10 @@ static void rcu_bind_gp_kthread(void)
                return;
 #ifdef CONFIG_NO_HZ_FULL_SYSIDLE
        cpu = tick_do_timer_cpu;
-       if (cpu >= 0 && cpu < nr_cpu_ids && raw_smp_processor_id() != cpu)
+       if (cpu >= 0 && cpu < nr_cpu_ids)
                set_cpus_allowed_ptr(current, cpumask_of(cpu));
 #else /* #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
-       if (!is_housekeeping_cpu(raw_smp_processor_id()))
-               housekeeping_affine(current);
+       housekeeping_affine(current);
 #endif /* #else #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
 }
 
index fbb6240509ea7768210e989a63d7ee007a793297..f92361efd0f55d970d851604d34800e7d109ecc8 100644 (file)
@@ -283,8 +283,8 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
                        seq_puts(m, "\n");
                        level = rnp->level;
                }
-               seq_printf(m, "%lx/%lx %c%c>%c %d:%d ^%d    ",
-                          rnp->qsmask, rnp->qsmaskinit,
+               seq_printf(m, "%lx/%lx->%lx %c%c>%c %d:%d ^%d    ",
+                          rnp->qsmask, rnp->qsmaskinit, rnp->qsmaskinitnext,
                           ".G"[rnp->gp_tasks != NULL],
                           ".E"[rnp->exp_tasks != NULL],
                           ".T"[!list_empty(&rnp->blkd_tasks)],
index e0d31a345ee6574fa5d7c949a8165f8374a9909f..1f133350da01e360bc6048b3a458e8b8cc0bdefc 100644 (file)
@@ -62,6 +62,63 @@ MODULE_ALIAS("rcupdate");
 
 module_param(rcu_expedited, int, 0);
 
+#ifndef CONFIG_TINY_RCU
+
+static atomic_t rcu_expedited_nesting =
+       ATOMIC_INIT(IS_ENABLED(CONFIG_RCU_EXPEDITE_BOOT) ? 1 : 0);
+
+/*
+ * Should normal grace-period primitives be expedited?  Intended for
+ * use within RCU.  Note that this function takes the rcu_expedited
+ * sysfs/boot variable into account as well as the rcu_expedite_gp()
+ * nesting.  So looping on rcu_unexpedite_gp() until rcu_gp_is_expedited()
+ * returns false is a -really- bad idea.
+ */
+bool rcu_gp_is_expedited(void)
+{
+       return rcu_expedited || atomic_read(&rcu_expedited_nesting);
+}
+EXPORT_SYMBOL_GPL(rcu_gp_is_expedited);
+
+/**
+ * rcu_expedite_gp - Expedite future RCU grace periods
+ *
+ * After a call to this function, future calls to synchronize_rcu() and
+ * friends act as the corresponding synchronize_rcu_expedited() function
+ * had instead been called.
+ */
+void rcu_expedite_gp(void)
+{
+       atomic_inc(&rcu_expedited_nesting);
+}
+EXPORT_SYMBOL_GPL(rcu_expedite_gp);
+
+/**
+ * rcu_unexpedite_gp - Cancel prior rcu_expedite_gp() invocation
+ *
+ * Undo a prior call to rcu_expedite_gp().  If all prior calls to
+ * rcu_expedite_gp() are undone by a subsequent call to rcu_unexpedite_gp(),
+ * and if the rcu_expedited sysfs/boot parameter is not set, then all
+ * subsequent calls to synchronize_rcu() and friends will return to
+ * their normal non-expedited behavior.
+ */
+void rcu_unexpedite_gp(void)
+{
+       atomic_dec(&rcu_expedited_nesting);
+}
+EXPORT_SYMBOL_GPL(rcu_unexpedite_gp);
+
+#endif /* #ifndef CONFIG_TINY_RCU */
+
+/*
+ * Inform RCU of the end of the in-kernel boot sequence.
+ */
+void rcu_end_inkernel_boot(void)
+{
+       if (IS_ENABLED(CONFIG_RCU_EXPEDITE_BOOT))
+               rcu_unexpedite_gp();
+}
+
 #ifdef CONFIG_PREEMPT_RCU
 
 /*
@@ -199,16 +256,13 @@ EXPORT_SYMBOL_GPL(rcu_read_lock_bh_held);
 
 #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
-struct rcu_synchronize {
-       struct rcu_head head;
-       struct completion completion;
-};
-
-/*
- * Awaken the corresponding synchronize_rcu() instance now that a
- * grace period has elapsed.
+/**
+ * wakeme_after_rcu() - Callback function to awaken a task after grace period
+ * @head: Pointer to rcu_head member within rcu_synchronize structure
+ *
+ * Awaken the corresponding task now that a grace period has elapsed.
  */
-static void wakeme_after_rcu(struct rcu_head  *head)
+void wakeme_after_rcu(struct rcu_head *head)
 {
        struct rcu_synchronize *rcu;
 
index 62671f53202ac7d4de8037dce950c934c7a4ddbc..f9123a82cbb614eb26cab55c0f58540a5a3eb24b 100644 (file)
@@ -306,6 +306,9 @@ __read_mostly int scheduler_running;
  */
 int sysctl_sched_rt_runtime = 950000;
 
+/* cpus with isolated domains */
+cpumask_var_t cpu_isolated_map;
+
 /*
  * this_rq_lock - lock this runqueue and disable interrupts.
  */
@@ -689,6 +692,23 @@ static inline bool got_nohz_idle_kick(void)
 #ifdef CONFIG_NO_HZ_FULL
 bool sched_can_stop_tick(void)
 {
+       /*
+        * FIFO realtime policy runs the highest priority task. Other runnable
+        * tasks are of a lower priority. The scheduler tick does nothing.
+        */
+       if (current->policy == SCHED_FIFO)
+               return true;
+
+       /*
+        * Round-robin realtime tasks time slice with other tasks at the same
+        * realtime priority. Is this task the only one at this priority?
+        */
+       if (current->policy == SCHED_RR) {
+               struct sched_rt_entity *rt_se = &current->rt;
+
+               return rt_se->run_list.prev == rt_se->run_list.next;
+       }
+
        /*
         * More than one running task need preemption.
         * nr_running update is assumed to be visible
@@ -996,6 +1016,13 @@ void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
                rq_clock_skip_update(rq, true);
 }
 
+static ATOMIC_NOTIFIER_HEAD(task_migration_notifier);
+
+void register_task_migration_notifier(struct notifier_block *n)
+{
+       atomic_notifier_chain_register(&task_migration_notifier, n);
+}
+
 #ifdef CONFIG_SMP
 void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 {
@@ -1026,10 +1053,18 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
        trace_sched_migrate_task(p, new_cpu);
 
        if (task_cpu(p) != new_cpu) {
+               struct task_migration_notifier tmn;
+
                if (p->sched_class->migrate_task_rq)
                        p->sched_class->migrate_task_rq(p, new_cpu);
                p->se.nr_migrations++;
                perf_sw_event_sched(PERF_COUNT_SW_CPU_MIGRATIONS, 1, 0);
+
+               tmn.task = p;
+               tmn.from_cpu = task_cpu(p);
+               tmn.to_cpu = new_cpu;
+
+               atomic_notifier_call_chain(&task_migration_notifier, 0, &tmn);
        }
 
        __set_task_cpu(p, new_cpu);
@@ -2818,7 +2853,7 @@ asmlinkage __visible void __sched schedule_user(void)
         * we find a better solution.
         *
         * NB: There are buggy callers of this function.  Ideally we
-        * should warn if prev_state != IN_USER, but that will trigger
+        * should warn if prev_state != CONTEXT_USER, but that will trigger
         * too frequently to make sense yet.
         */
        enum ctx_state prev_state = exception_enter();
@@ -5320,36 +5355,13 @@ static int sched_cpu_active(struct notifier_block *nfb,
 static int sched_cpu_inactive(struct notifier_block *nfb,
                                        unsigned long action, void *hcpu)
 {
-       unsigned long flags;
-       long cpu = (long)hcpu;
-       struct dl_bw *dl_b;
-
        switch (action & ~CPU_TASKS_FROZEN) {
        case CPU_DOWN_PREPARE:
-               set_cpu_active(cpu, false);
-
-               /* explicitly allow suspend */
-               if (!(action & CPU_TASKS_FROZEN)) {
-                       bool overflow;
-                       int cpus;
-
-                       rcu_read_lock_sched();
-                       dl_b = dl_bw_of(cpu);
-
-                       raw_spin_lock_irqsave(&dl_b->lock, flags);
-                       cpus = dl_bw_cpus(cpu);
-                       overflow = __dl_overflow(dl_b, cpus, 0, 0);
-                       raw_spin_unlock_irqrestore(&dl_b->lock, flags);
-
-                       rcu_read_unlock_sched();
-
-                       if (overflow)
-                               return notifier_from_errno(-EBUSY);
-               }
+               set_cpu_active((long)hcpu, false);
                return NOTIFY_OK;
+       default:
+               return NOTIFY_DONE;
        }
-
-       return NOTIFY_DONE;
 }
 
 static int __init migration_init(void)
@@ -5430,17 +5442,6 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
                        break;
                }
 
-               /*
-                * Even though we initialize ->capacity to something semi-sane,
-                * we leave capacity_orig unset. This allows us to detect if
-                * domain iteration is still funny without causing /0 traps.
-                */
-               if (!group->sgc->capacity_orig) {
-                       printk(KERN_CONT "\n");
-                       printk(KERN_ERR "ERROR: domain->cpu_capacity not set\n");
-                       break;
-               }
-
                if (!cpumask_weight(sched_group_cpus(group))) {
                        printk(KERN_CONT "\n");
                        printk(KERN_ERR "ERROR: empty group\n");
@@ -5813,9 +5814,6 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
        update_top_cache_domain(cpu);
 }
 
-/* cpus with isolated domains */
-static cpumask_var_t cpu_isolated_map;
-
 /* Setup the mask of cpus configured for isolated domains */
 static int __init isolated_cpu_setup(char *str)
 {
@@ -5924,7 +5922,6 @@ build_overlap_sched_groups(struct sched_domain *sd, int cpu)
                 * die on a /0 trap.
                 */
                sg->sgc->capacity = SCHED_CAPACITY_SCALE * cpumask_weight(sg_span);
-               sg->sgc->capacity_orig = sg->sgc->capacity;
 
                /*
                 * Make sure the first group of this domain contains the
@@ -6235,6 +6232,7 @@ sd_init(struct sched_domain_topology_level *tl, int cpu)
         */
 
        if (sd->flags & SD_SHARE_CPUCAPACITY) {
+               sd->flags |= SD_PREFER_SIBLING;
                sd->imbalance_pct = 110;
                sd->smt_gain = 1178; /* ~15% */
 
@@ -7000,7 +6998,6 @@ static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action,
                 */
 
        case CPU_ONLINE:
-       case CPU_DOWN_FAILED:
                cpuset_update_active_cpus(true);
                break;
        default:
@@ -7012,8 +7009,30 @@ static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action,
 static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action,
                               void *hcpu)
 {
-       switch (action) {
+       unsigned long flags;
+       long cpu = (long)hcpu;
+       struct dl_bw *dl_b;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
        case CPU_DOWN_PREPARE:
+               /* explicitly allow suspend */
+               if (!(action & CPU_TASKS_FROZEN)) {
+                       bool overflow;
+                       int cpus;
+
+                       rcu_read_lock_sched();
+                       dl_b = dl_bw_of(cpu);
+
+                       raw_spin_lock_irqsave(&dl_b->lock, flags);
+                       cpus = dl_bw_cpus(cpu);
+                       overflow = __dl_overflow(dl_b, cpus, 0, 0);
+                       raw_spin_unlock_irqrestore(&dl_b->lock, flags);
+
+                       rcu_read_unlock_sched();
+
+                       if (overflow)
+                               return notifier_from_errno(-EBUSY);
+               }
                cpuset_update_active_cpus(false);
                break;
        case CPU_DOWN_PREPARE_FROZEN:
@@ -7158,8 +7177,8 @@ void __init sched_init(void)
                rq->calc_load_active = 0;
                rq->calc_load_update = jiffies + LOAD_FREQ;
                init_cfs_rq(&rq->cfs);
-               init_rt_rq(&rq->rt, rq);
-               init_dl_rq(&rq->dl, rq);
+               init_rt_rq(&rq->rt);
+               init_dl_rq(&rq->dl);
 #ifdef CONFIG_FAIR_GROUP_SCHED
                root_task_group.shares = ROOT_TASK_GROUP_LOAD;
                INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
@@ -7199,7 +7218,7 @@ void __init sched_init(void)
 #ifdef CONFIG_SMP
                rq->sd = NULL;
                rq->rd = NULL;
-               rq->cpu_capacity = SCHED_CAPACITY_SCALE;
+               rq->cpu_capacity = rq->cpu_capacity_orig = SCHED_CAPACITY_SCALE;
                rq->post_schedule = 0;
                rq->active_balance = 0;
                rq->next_balance = jiffies;
@@ -7798,7 +7817,7 @@ static int sched_rt_global_constraints(void)
 }
 #endif /* CONFIG_RT_GROUP_SCHED */
 
-static int sched_dl_global_constraints(void)
+static int sched_dl_global_validate(void)
 {
        u64 runtime = global_rt_runtime();
        u64 period = global_rt_period();
@@ -7899,11 +7918,11 @@ int sched_rt_handler(struct ctl_table *table, int write,
                if (ret)
                        goto undo;
 
-               ret = sched_rt_global_constraints();
+               ret = sched_dl_global_validate();
                if (ret)
                        goto undo;
 
-               ret = sched_dl_global_constraints();
+               ret = sched_rt_global_constraints();
                if (ret)
                        goto undo;
 
index 3fa8fa6d940300c1fbae721503aad2666f72b4e5..5e95145088fd37b3d07ccac66c3cd58f7effe10a 100644 (file)
@@ -69,7 +69,7 @@ void init_dl_bw(struct dl_bw *dl_b)
        dl_b->total_bw = 0;
 }
 
-void init_dl_rq(struct dl_rq *dl_rq, struct rq *rq)
+void init_dl_rq(struct dl_rq *dl_rq)
 {
        dl_rq->rb_root = RB_ROOT;
 
@@ -218,6 +218,52 @@ static inline void set_post_schedule(struct rq *rq)
        rq->post_schedule = has_pushable_dl_tasks(rq);
 }
 
+static struct rq *find_lock_later_rq(struct task_struct *task, struct rq *rq);
+
+static void dl_task_offline_migration(struct rq *rq, struct task_struct *p)
+{
+       struct rq *later_rq = NULL;
+       bool fallback = false;
+
+       later_rq = find_lock_later_rq(p, rq);
+
+       if (!later_rq) {
+               int cpu;
+
+               /*
+                * If we cannot preempt any rq, fall back to pick any
+                * online cpu.
+                */
+               fallback = true;
+               cpu = cpumask_any_and(cpu_active_mask, tsk_cpus_allowed(p));
+               if (cpu >= nr_cpu_ids) {
+                       /*
+                        * Fail to find any suitable cpu.
+                        * The task will never come back!
+                        */
+                       BUG_ON(dl_bandwidth_enabled());
+
+                       /*
+                        * If admission control is disabled we
+                        * try a little harder to let the task
+                        * run.
+                        */
+                       cpu = cpumask_any(cpu_active_mask);
+               }
+               later_rq = cpu_rq(cpu);
+               double_lock_balance(rq, later_rq);
+       }
+
+       deactivate_task(rq, p, 0);
+       set_task_cpu(p, later_rq->cpu);
+       activate_task(later_rq, p, ENQUEUE_REPLENISH);
+
+       if (!fallback)
+               resched_curr(later_rq);
+
+       double_unlock_balance(rq, later_rq);
+}
+
 #else
 
 static inline
@@ -514,7 +560,7 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
        unsigned long flags;
        struct rq *rq;
 
-       rq = task_rq_lock(current, &flags);
+       rq = task_rq_lock(p, &flags);
 
        /*
         * We need to take care of several possible races here:
@@ -536,6 +582,17 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
        sched_clock_tick();
        update_rq_clock(rq);
 
+#ifdef CONFIG_SMP
+       /*
+        * If we find that the rq the task was on is no longer
+        * available, we need to select a new rq.
+        */
+       if (unlikely(!rq->online)) {
+               dl_task_offline_migration(rq, p);
+               goto unlock;
+       }
+#endif
+
        /*
         * If the throttle happened during sched-out; like:
         *
@@ -569,7 +626,7 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
                push_dl_task(rq);
 #endif
 unlock:
-       task_rq_unlock(rq, current, &flags);
+       task_rq_unlock(rq, p, &flags);
 
        return HRTIMER_NORESTART;
 }
@@ -914,6 +971,12 @@ static void yield_task_dl(struct rq *rq)
        }
        update_rq_clock(rq);
        update_curr_dl(rq);
+       /*
+        * Tell update_rq_clock() that we've just updated,
+        * so we don't do microscopic update in schedule()
+        * and double the fastpath cost.
+        */
+       rq_clock_skip_update(rq, true);
 }
 
 #ifdef CONFIG_SMP
@@ -1659,14 +1722,6 @@ static void switched_to_dl(struct rq *rq, struct task_struct *p)
 {
        int check_resched = 1;
 
-       /*
-        * If p is throttled, don't consider the possibility
-        * of preempting rq->curr, the check will be done right
-        * after its runtime will get replenished.
-        */
-       if (unlikely(p->dl.dl_throttled))
-               return;
-
        if (task_on_rq_queued(p) && rq->curr != p) {
 #ifdef CONFIG_SMP
                if (p->nr_cpus_allowed > 1 && rq->dl.overloaded &&
index 8baaf858d25c49921eaa3d9a83235b9f0d2b8c6c..a245c1fc6f0a610f17e2d13635306d681e2ef821 100644 (file)
@@ -71,7 +71,7 @@ static void print_cfs_group_stats(struct seq_file *m, int cpu, struct task_group
        if (!se) {
                struct sched_avg *avg = &cpu_rq(cpu)->avg;
                P(avg->runnable_avg_sum);
-               P(avg->runnable_avg_period);
+               P(avg->avg_period);
                return;
        }
 
@@ -94,8 +94,10 @@ static void print_cfs_group_stats(struct seq_file *m, int cpu, struct task_group
        P(se->load.weight);
 #ifdef CONFIG_SMP
        P(se->avg.runnable_avg_sum);
-       P(se->avg.runnable_avg_period);
+       P(se->avg.running_avg_sum);
+       P(se->avg.avg_period);
        P(se->avg.load_avg_contrib);
+       P(se->avg.utilization_avg_contrib);
        P(se->avg.decay_count);
 #endif
 #undef PN
@@ -214,6 +216,8 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
                        cfs_rq->runnable_load_avg);
        SEQ_printf(m, "  .%-30s: %ld\n", "blocked_load_avg",
                        cfs_rq->blocked_load_avg);
+       SEQ_printf(m, "  .%-30s: %ld\n", "utilization_load_avg",
+                       cfs_rq->utilization_load_avg);
 #ifdef CONFIG_FAIR_GROUP_SCHED
        SEQ_printf(m, "  .%-30s: %ld\n", "tg_load_contrib",
                        cfs_rq->tg_load_contrib);
@@ -636,8 +640,10 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
        P(se.load.weight);
 #ifdef CONFIG_SMP
        P(se.avg.runnable_avg_sum);
-       P(se.avg.runnable_avg_period);
+       P(se.avg.running_avg_sum);
+       P(se.avg.avg_period);
        P(se.avg.load_avg_contrib);
+       P(se.avg.utilization_avg_contrib);
        P(se.avg.decay_count);
 #endif
        P(policy);
index bcfe32088b3768363c2f37502a953b61a361f7ff..ffeaa4105e48a36105ecaea8967082e1e7a7af98 100644 (file)
@@ -670,6 +670,7 @@ static int select_idle_sibling(struct task_struct *p, int cpu);
 static unsigned long task_h_load(struct task_struct *p);
 
 static inline void __update_task_entity_contrib(struct sched_entity *se);
+static inline void __update_task_entity_utilization(struct sched_entity *se);
 
 /* Give new task start runnable values to heavy its load in infant time */
 void init_task_runnable_average(struct task_struct *p)
@@ -677,9 +678,10 @@ void init_task_runnable_average(struct task_struct *p)
        u32 slice;
 
        slice = sched_slice(task_cfs_rq(p), &p->se) >> 10;
-       p->se.avg.runnable_avg_sum = slice;
-       p->se.avg.runnable_avg_period = slice;
+       p->se.avg.runnable_avg_sum = p->se.avg.running_avg_sum = slice;
+       p->se.avg.avg_period = slice;
        __update_task_entity_contrib(&p->se);
+       __update_task_entity_utilization(&p->se);
 }
 #else
 void init_task_runnable_average(struct task_struct *p)
@@ -1196,9 +1198,11 @@ static void task_numa_assign(struct task_numa_env *env,
 static bool load_too_imbalanced(long src_load, long dst_load,
                                struct task_numa_env *env)
 {
-       long imb, old_imb;
-       long orig_src_load, orig_dst_load;
        long src_capacity, dst_capacity;
+       long orig_src_load;
+       long load_a, load_b;
+       long moved_load;
+       long imb;
 
        /*
         * The load is corrected for the CPU capacity available on each node.
@@ -1211,30 +1215,39 @@ static bool load_too_imbalanced(long src_load, long dst_load,
        dst_capacity = env->dst_stats.compute_capacity;
 
        /* We care about the slope of the imbalance, not the direction. */
-       if (dst_load < src_load)
-               swap(dst_load, src_load);
+       load_a = dst_load;
+       load_b = src_load;
+       if (load_a < load_b)
+               swap(load_a, load_b);
 
        /* Is the difference below the threshold? */
-       imb = dst_load * src_capacity * 100 -
-             src_load * dst_capacity * env->imbalance_pct;
+       imb = load_a * src_capacity * 100 -
+               load_b * dst_capacity * env->imbalance_pct;
        if (imb <= 0)
                return false;
 
        /*
         * The imbalance is above the allowed threshold.
-        * Compare it with the old imbalance.
+        * Allow a move that brings us closer to a balanced situation,
+        * without moving things past the point of balance.
         */
        orig_src_load = env->src_stats.load;
-       orig_dst_load = env->dst_stats.load;
 
-       if (orig_dst_load < orig_src_load)
-               swap(orig_dst_load, orig_src_load);
-
-       old_imb = orig_dst_load * src_capacity * 100 -
-                 orig_src_load * dst_capacity * env->imbalance_pct;
+       /*
+        * In a task swap, there will be one load moving from src to dst,
+        * and another moving back. This is the net sum of both moves.
+        * A simple task move will always have a positive value.
+        * Allow the move if it brings the system closer to a balanced
+        * situation, without crossing over the balance point.
+        */
+       moved_load = orig_src_load - src_load;
 
-       /* Would this change make things worse? */
-       return (imb > old_imb);
+       if (moved_load > 0)
+               /* Moving src -> dst. Did we overshoot balance? */
+               return src_load * dst_capacity < dst_load * src_capacity;
+       else
+               /* Moving dst -> src. Did we overshoot balance? */
+               return dst_load * src_capacity < src_load * dst_capacity;
 }
 
 /*
@@ -1675,7 +1688,7 @@ static u64 numa_get_avg_runtime(struct task_struct *p, u64 *period)
                *period = now - p->last_task_numa_placement;
        } else {
                delta = p->se.avg.runnable_avg_sum;
-               *period = p->se.avg.runnable_avg_period;
+               *period = p->se.avg.avg_period;
        }
 
        p->last_sum_exec_runtime = runtime;
@@ -1765,6 +1778,8 @@ static int preferred_group_nid(struct task_struct *p, int nid)
                        }
                }
                /* Next round, evaluate the nodes within max_group. */
+               if (!max_faults)
+                       break;
                nodes = max_group;
        }
        return nid;
@@ -2165,8 +2180,10 @@ void task_numa_work(struct callback_head *work)
                vma = mm->mmap;
        }
        for (; vma; vma = vma->vm_next) {
-               if (!vma_migratable(vma) || !vma_policy_mof(vma))
+               if (!vma_migratable(vma) || !vma_policy_mof(vma) ||
+                       is_vm_hugetlb_page(vma)) {
                        continue;
+               }
 
                /*
                 * Shared library pages mapped by multiple processes are not
@@ -2501,13 +2518,15 @@ static u32 __compute_runnable_contrib(u64 n)
  *   load_avg = u_0` + y*(u_0 + u_1*y + u_2*y^2 + ... )
  *            = u_0 + u_1*y + u_2*y^2 + ... [re-labeling u_i --> u_{i+1}]
  */
-static __always_inline int __update_entity_runnable_avg(u64 now,
+static __always_inline int __update_entity_runnable_avg(u64 now, int cpu,
                                                        struct sched_avg *sa,
-                                                       int runnable)
+                                                       int runnable,
+                                                       int running)
 {
        u64 delta, periods;
        u32 runnable_contrib;
        int delta_w, decayed = 0;
+       unsigned long scale_freq = arch_scale_freq_capacity(NULL, cpu);
 
        delta = now - sa->last_runnable_update;
        /*
@@ -2529,7 +2548,7 @@ static __always_inline int __update_entity_runnable_avg(u64 now,
        sa->last_runnable_update = now;
 
        /* delta_w is the amount already accumulated against our next period */
-       delta_w = sa->runnable_avg_period % 1024;
+       delta_w = sa->avg_period % 1024;
        if (delta + delta_w >= 1024) {
                /* period roll-over */
                decayed = 1;
@@ -2542,7 +2561,10 @@ static __always_inline int __update_entity_runnable_avg(u64 now,
                delta_w = 1024 - delta_w;
                if (runnable)
                        sa->runnable_avg_sum += delta_w;
-               sa->runnable_avg_period += delta_w;
+               if (running)
+                       sa->running_avg_sum += delta_w * scale_freq
+                               >> SCHED_CAPACITY_SHIFT;
+               sa->avg_period += delta_w;
 
                delta -= delta_w;
 
@@ -2552,20 +2574,28 @@ static __always_inline int __update_entity_runnable_avg(u64 now,
 
                sa->runnable_avg_sum = decay_load(sa->runnable_avg_sum,
                                                  periods + 1);
-               sa->runnable_avg_period = decay_load(sa->runnable_avg_period,
+               sa->running_avg_sum = decay_load(sa->running_avg_sum,
+                                                 periods + 1);
+               sa->avg_period = decay_load(sa->avg_period,
                                                     periods + 1);
 
                /* Efficiently calculate \sum (1..n_period) 1024*y^i */
                runnable_contrib = __compute_runnable_contrib(periods);
                if (runnable)
                        sa->runnable_avg_sum += runnable_contrib;
-               sa->runnable_avg_period += runnable_contrib;
+               if (running)
+                       sa->running_avg_sum += runnable_contrib * scale_freq
+                               >> SCHED_CAPACITY_SHIFT;
+               sa->avg_period += runnable_contrib;
        }
 
        /* Remainder of delta accrued against u_0` */
        if (runnable)
                sa->runnable_avg_sum += delta;
-       sa->runnable_avg_period += delta;
+       if (running)
+               sa->running_avg_sum += delta * scale_freq
+                       >> SCHED_CAPACITY_SHIFT;
+       sa->avg_period += delta;
 
        return decayed;
 }
@@ -2582,6 +2612,8 @@ static inline u64 __synchronize_entity_decay(struct sched_entity *se)
                return 0;
 
        se->avg.load_avg_contrib = decay_load(se->avg.load_avg_contrib, decays);
+       se->avg.utilization_avg_contrib =
+               decay_load(se->avg.utilization_avg_contrib, decays);
 
        return decays;
 }
@@ -2617,7 +2649,7 @@ static inline void __update_tg_runnable_avg(struct sched_avg *sa,
 
        /* The fraction of a cpu used by this cfs_rq */
        contrib = div_u64((u64)sa->runnable_avg_sum << NICE_0_SHIFT,
-                         sa->runnable_avg_period + 1);
+                         sa->avg_period + 1);
        contrib -= cfs_rq->tg_runnable_contrib;
 
        if (abs(contrib) > cfs_rq->tg_runnable_contrib / 64) {
@@ -2670,7 +2702,8 @@ static inline void __update_group_entity_contrib(struct sched_entity *se)
 
 static inline void update_rq_runnable_avg(struct rq *rq, int runnable)
 {
-       __update_entity_runnable_avg(rq_clock_task(rq), &rq->avg, runnable);
+       __update_entity_runnable_avg(rq_clock_task(rq), cpu_of(rq), &rq->avg,
+                       runnable, runnable);
        __update_tg_runnable_avg(&rq->avg, &rq->cfs);
 }
 #else /* CONFIG_FAIR_GROUP_SCHED */
@@ -2688,7 +2721,7 @@ static inline void __update_task_entity_contrib(struct sched_entity *se)
 
        /* avoid overflowing a 32-bit type w/ SCHED_LOAD_SCALE */
        contrib = se->avg.runnable_avg_sum * scale_load_down(se->load.weight);
-       contrib /= (se->avg.runnable_avg_period + 1);
+       contrib /= (se->avg.avg_period + 1);
        se->avg.load_avg_contrib = scale_load(contrib);
 }
 
@@ -2707,6 +2740,30 @@ static long __update_entity_load_avg_contrib(struct sched_entity *se)
        return se->avg.load_avg_contrib - old_contrib;
 }
 
+
+static inline void __update_task_entity_utilization(struct sched_entity *se)
+{
+       u32 contrib;
+
+       /* avoid overflowing a 32-bit type w/ SCHED_LOAD_SCALE */
+       contrib = se->avg.running_avg_sum * scale_load_down(SCHED_LOAD_SCALE);
+       contrib /= (se->avg.avg_period + 1);
+       se->avg.utilization_avg_contrib = scale_load(contrib);
+}
+
+static long __update_entity_utilization_avg_contrib(struct sched_entity *se)
+{
+       long old_contrib = se->avg.utilization_avg_contrib;
+
+       if (entity_is_task(se))
+               __update_task_entity_utilization(se);
+       else
+               se->avg.utilization_avg_contrib =
+                                       group_cfs_rq(se)->utilization_load_avg;
+
+       return se->avg.utilization_avg_contrib - old_contrib;
+}
+
 static inline void subtract_blocked_load_contrib(struct cfs_rq *cfs_rq,
                                                 long load_contrib)
 {
@@ -2723,7 +2780,8 @@ static inline void update_entity_load_avg(struct sched_entity *se,
                                          int update_cfs_rq)
 {
        struct cfs_rq *cfs_rq = cfs_rq_of(se);
-       long contrib_delta;
+       long contrib_delta, utilization_delta;
+       int cpu = cpu_of(rq_of(cfs_rq));
        u64 now;
 
        /*
@@ -2735,18 +2793,22 @@ static inline void update_entity_load_avg(struct sched_entity *se,
        else
                now = cfs_rq_clock_task(group_cfs_rq(se));
 
-       if (!__update_entity_runnable_avg(now, &se->avg, se->on_rq))
+       if (!__update_entity_runnable_avg(now, cpu, &se->avg, se->on_rq,
+                                       cfs_rq->curr == se))
                return;
 
        contrib_delta = __update_entity_load_avg_contrib(se);
+       utilization_delta = __update_entity_utilization_avg_contrib(se);
 
        if (!update_cfs_rq)
                return;
 
-       if (se->on_rq)
+       if (se->on_rq) {
                cfs_rq->runnable_load_avg += contrib_delta;
-       else
+               cfs_rq->utilization_load_avg += utilization_delta;
+       } else {
                subtract_blocked_load_contrib(cfs_rq, -contrib_delta);
+       }
 }
 
 /*
@@ -2821,6 +2883,7 @@ static inline void enqueue_entity_load_avg(struct cfs_rq *cfs_rq,
        }
 
        cfs_rq->runnable_load_avg += se->avg.load_avg_contrib;
+       cfs_rq->utilization_load_avg += se->avg.utilization_avg_contrib;
        /* we force update consideration on load-balancer moves */
        update_cfs_rq_blocked_load(cfs_rq, !wakeup);
 }
@@ -2839,6 +2902,7 @@ static inline void dequeue_entity_load_avg(struct cfs_rq *cfs_rq,
        update_cfs_rq_blocked_load(cfs_rq, !sleep);
 
        cfs_rq->runnable_load_avg -= se->avg.load_avg_contrib;
+       cfs_rq->utilization_load_avg -= se->avg.utilization_avg_contrib;
        if (sleep) {
                cfs_rq->blocked_load_avg += se->avg.load_avg_contrib;
                se->avg.decay_count = atomic64_read(&cfs_rq->decay_counter);
@@ -3176,6 +3240,7 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
                 */
                update_stats_wait_end(cfs_rq, se);
                __dequeue_entity(cfs_rq, se);
+               update_entity_load_avg(se, 1);
        }
 
        update_stats_curr_start(cfs_rq, se);
@@ -4302,6 +4367,11 @@ static unsigned long capacity_of(int cpu)
        return cpu_rq(cpu)->cpu_capacity;
 }
 
+static unsigned long capacity_orig_of(int cpu)
+{
+       return cpu_rq(cpu)->cpu_capacity_orig;
+}
+
 static unsigned long cpu_avg_load_per_task(int cpu)
 {
        struct rq *rq = cpu_rq(cpu);
@@ -4715,6 +4785,33 @@ next:
 done:
        return target;
 }
+/*
+ * get_cpu_usage returns the amount of capacity of a CPU that is used by CFS
+ * tasks. The unit of the return value must be the one of capacity so we can
+ * compare the usage with the capacity of the CPU that is available for CFS
+ * task (ie cpu_capacity).
+ * cfs.utilization_load_avg is the sum of running time of runnable tasks on a
+ * CPU. It represents the amount of utilization of a CPU in the range
+ * [0..SCHED_LOAD_SCALE].  The usage of a CPU can't be higher than the full
+ * capacity of the CPU because it's about the running time on this CPU.
+ * Nevertheless, cfs.utilization_load_avg can be higher than SCHED_LOAD_SCALE
+ * because of unfortunate rounding in avg_period and running_load_avg or just
+ * after migrating tasks until the average stabilizes with the new running
+ * time. So we need to check that the usage stays into the range
+ * [0..cpu_capacity_orig] and cap if necessary.
+ * Without capping the usage, a group could be seen as overloaded (CPU0 usage
+ * at 121% + CPU1 usage at 80%) whereas CPU1 has 20% of available capacity
+ */
+static int get_cpu_usage(int cpu)
+{
+       unsigned long usage = cpu_rq(cpu)->cfs.utilization_load_avg;
+       unsigned long capacity = capacity_orig_of(cpu);
+
+       if (usage >= SCHED_LOAD_SCALE)
+               return capacity;
+
+       return (usage * capacity) >> SCHED_LOAD_SHIFT;
+}
 
 /*
  * select_task_rq_fair: Select target runqueue for the waking task in domains
@@ -5841,12 +5938,12 @@ struct sg_lb_stats {
        unsigned long sum_weighted_load; /* Weighted load of group's tasks */
        unsigned long load_per_task;
        unsigned long group_capacity;
+       unsigned long group_usage; /* Total usage of the group */
        unsigned int sum_nr_running; /* Nr tasks running in the group */
-       unsigned int group_capacity_factor;
        unsigned int idle_cpus;
        unsigned int group_weight;
        enum group_type group_type;
-       int group_has_free_capacity;
+       int group_no_capacity;
 #ifdef CONFIG_NUMA_BALANCING
        unsigned int nr_numa_running;
        unsigned int nr_preferred_running;
@@ -5917,16 +6014,6 @@ static inline int get_sd_load_idx(struct sched_domain *sd,
        return load_idx;
 }
 
-static unsigned long default_scale_capacity(struct sched_domain *sd, int cpu)
-{
-       return SCHED_CAPACITY_SCALE;
-}
-
-unsigned long __weak arch_scale_freq_capacity(struct sched_domain *sd, int cpu)
-{
-       return default_scale_capacity(sd, cpu);
-}
-
 static unsigned long default_scale_cpu_capacity(struct sched_domain *sd, int cpu)
 {
        if ((sd->flags & SD_SHARE_CPUCAPACITY) && (sd->span_weight > 1))
@@ -5943,7 +6030,7 @@ unsigned long __weak arch_scale_cpu_capacity(struct sched_domain *sd, int cpu)
 static unsigned long scale_rt_capacity(int cpu)
 {
        struct rq *rq = cpu_rq(cpu);
-       u64 total, available, age_stamp, avg;
+       u64 total, used, age_stamp, avg;
        s64 delta;
 
        /*
@@ -5959,19 +6046,12 @@ static unsigned long scale_rt_capacity(int cpu)
 
        total = sched_avg_period() + delta;
 
-       if (unlikely(total < avg)) {
-               /* Ensures that capacity won't end up being negative */
-               available = 0;
-       } else {
-               available = total - avg;
-       }
-
-       if (unlikely((s64)total < SCHED_CAPACITY_SCALE))
-               total = SCHED_CAPACITY_SCALE;
+       used = div_u64(avg, total);
 
-       total >>= SCHED_CAPACITY_SHIFT;
+       if (likely(used < SCHED_CAPACITY_SCALE))
+               return SCHED_CAPACITY_SCALE - used;
 
-       return div_u64(available, total);
+       return 1;
 }
 
 static void update_cpu_capacity(struct sched_domain *sd, int cpu)
@@ -5986,14 +6066,7 @@ static void update_cpu_capacity(struct sched_domain *sd, int cpu)
 
        capacity >>= SCHED_CAPACITY_SHIFT;
 
-       sdg->sgc->capacity_orig = capacity;
-
-       if (sched_feat(ARCH_CAPACITY))
-               capacity *= arch_scale_freq_capacity(sd, cpu);
-       else
-               capacity *= default_scale_capacity(sd, cpu);
-
-       capacity >>= SCHED_CAPACITY_SHIFT;
+       cpu_rq(cpu)->cpu_capacity_orig = capacity;
 
        capacity *= scale_rt_capacity(cpu);
        capacity >>= SCHED_CAPACITY_SHIFT;
@@ -6009,7 +6082,7 @@ void update_group_capacity(struct sched_domain *sd, int cpu)
 {
        struct sched_domain *child = sd->child;
        struct sched_group *group, *sdg = sd->groups;
-       unsigned long capacity, capacity_orig;
+       unsigned long capacity;
        unsigned long interval;
 
        interval = msecs_to_jiffies(sd->balance_interval);
@@ -6021,7 +6094,7 @@ void update_group_capacity(struct sched_domain *sd, int cpu)
                return;
        }
 
-       capacity_orig = capacity = 0;
+       capacity = 0;
 
        if (child->flags & SD_OVERLAP) {
                /*
@@ -6041,19 +6114,15 @@ void update_group_capacity(struct sched_domain *sd, int cpu)
                         * Use capacity_of(), which is set irrespective of domains
                         * in update_cpu_capacity().
                         *
-                        * This avoids capacity/capacity_orig from being 0 and
+                        * This avoids capacity from being 0 and
                         * causing divide-by-zero issues on boot.
-                        *
-                        * Runtime updates will correct capacity_orig.
                         */
                        if (unlikely(!rq->sd)) {
-                               capacity_orig += capacity_of(cpu);
                                capacity += capacity_of(cpu);
                                continue;
                        }
 
                        sgc = rq->sd->groups->sgc;
-                       capacity_orig += sgc->capacity_orig;
                        capacity += sgc->capacity;
                }
        } else  {
@@ -6064,39 +6133,24 @@ void update_group_capacity(struct sched_domain *sd, int cpu)
 
                group = child->groups;
                do {
-                       capacity_orig += group->sgc->capacity_orig;
                        capacity += group->sgc->capacity;
                        group = group->next;
                } while (group != child->groups);
        }
 
-       sdg->sgc->capacity_orig = capacity_orig;
        sdg->sgc->capacity = capacity;
 }
 
 /*
- * Try and fix up capacity for tiny siblings, this is needed when
- * things like SD_ASYM_PACKING need f_b_g to select another sibling
- * which on its own isn't powerful enough.
- *
- * See update_sd_pick_busiest() and check_asym_packing().
+ * Check whether the capacity of the rq has been noticeably reduced by side
+ * activity. The imbalance_pct is used for the threshold.
+ * Return true is the capacity is reduced
  */
 static inline int
-fix_small_capacity(struct sched_domain *sd, struct sched_group *group)
+check_cpu_capacity(struct rq *rq, struct sched_domain *sd)
 {
-       /*
-        * Only siblings can have significantly less than SCHED_CAPACITY_SCALE
-        */
-       if (!(sd->flags & SD_SHARE_CPUCAPACITY))
-               return 0;
-
-       /*
-        * If ~90% of the cpu_capacity is still there, we're good.
-        */
-       if (group->sgc->capacity * 32 > group->sgc->capacity_orig * 29)
-               return 1;
-
-       return 0;
+       return ((rq->cpu_capacity * sd->imbalance_pct) <
+                               (rq->cpu_capacity_orig * 100));
 }
 
 /*
@@ -6134,37 +6188,56 @@ static inline int sg_imbalanced(struct sched_group *group)
 }
 
 /*
- * Compute the group capacity factor.
- *
- * Avoid the issue where N*frac(smt_capacity) >= 1 creates 'phantom' cores by
- * first dividing out the smt factor and computing the actual number of cores
- * and limit unit capacity with that.
+ * group_has_capacity returns true if the group has spare capacity that could
+ * be used by some tasks.
+ * We consider that a group has spare capacity if the  * number of task is
+ * smaller than the number of CPUs or if the usage is lower than the available
+ * capacity for CFS tasks.
+ * For the latter, we use a threshold to stabilize the state, to take into
+ * account the variance of the tasks' load and to return true if the available
+ * capacity in meaningful for the load balancer.
+ * As an example, an available capacity of 1% can appear but it doesn't make
+ * any benefit for the load balance.
  */
-static inline int sg_capacity_factor(struct lb_env *env, struct sched_group *group)
+static inline bool
+group_has_capacity(struct lb_env *env, struct sg_lb_stats *sgs)
 {
-       unsigned int capacity_factor, smt, cpus;
-       unsigned int capacity, capacity_orig;
+       if (sgs->sum_nr_running < sgs->group_weight)
+               return true;
 
-       capacity = group->sgc->capacity;
-       capacity_orig = group->sgc->capacity_orig;
-       cpus = group->group_weight;
+       if ((sgs->group_capacity * 100) >
+                       (sgs->group_usage * env->sd->imbalance_pct))
+               return true;
+
+       return false;
+}
 
-       /* smt := ceil(cpus / capacity), assumes: 1 < smt_capacity < 2 */
-       smt = DIV_ROUND_UP(SCHED_CAPACITY_SCALE * cpus, capacity_orig);
-       capacity_factor = cpus / smt; /* cores */
+/*
+ *  group_is_overloaded returns true if the group has more tasks than it can
+ *  handle.
+ *  group_is_overloaded is not equals to !group_has_capacity because a group
+ *  with the exact right number of tasks, has no more spare capacity but is not
+ *  overloaded so both group_has_capacity and group_is_overloaded return
+ *  false.
+ */
+static inline bool
+group_is_overloaded(struct lb_env *env, struct sg_lb_stats *sgs)
+{
+       if (sgs->sum_nr_running <= sgs->group_weight)
+               return false;
 
-       capacity_factor = min_t(unsigned,
-               capacity_factor, DIV_ROUND_CLOSEST(capacity, SCHED_CAPACITY_SCALE));
-       if (!capacity_factor)
-               capacity_factor = fix_small_capacity(env->sd, group);
+       if ((sgs->group_capacity * 100) <
+                       (sgs->group_usage * env->sd->imbalance_pct))
+               return true;
 
-       return capacity_factor;
+       return false;
 }
 
-static enum group_type
-group_classify(struct sched_group *group, struct sg_lb_stats *sgs)
+static enum group_type group_classify(struct lb_env *env,
+               struct sched_group *group,
+               struct sg_lb_stats *sgs)
 {
-       if (sgs->sum_nr_running > sgs->group_capacity_factor)
+       if (sgs->group_no_capacity)
                return group_overloaded;
 
        if (sg_imbalanced(group))
@@ -6202,6 +6275,7 @@ static inline void update_sg_lb_stats(struct lb_env *env,
                        load = source_load(i, load_idx);
 
                sgs->group_load += load;
+               sgs->group_usage += get_cpu_usage(i);
                sgs->sum_nr_running += rq->cfs.h_nr_running;
 
                if (rq->nr_running > 1)
@@ -6224,11 +6298,9 @@ static inline void update_sg_lb_stats(struct lb_env *env,
                sgs->load_per_task = sgs->sum_weighted_load / sgs->sum_nr_running;
 
        sgs->group_weight = group->group_weight;
-       sgs->group_capacity_factor = sg_capacity_factor(env, group);
-       sgs->group_type = group_classify(group, sgs);
 
-       if (sgs->group_capacity_factor > sgs->sum_nr_running)
-               sgs->group_has_free_capacity = 1;
+       sgs->group_no_capacity = group_is_overloaded(env, sgs);
+       sgs->group_type = group_classify(env, group, sgs);
 }
 
 /**
@@ -6350,18 +6422,19 @@ static inline void update_sd_lb_stats(struct lb_env *env, struct sd_lb_stats *sd
 
                /*
                 * In case the child domain prefers tasks go to siblings
-                * first, lower the sg capacity factor to one so that we'll try
+                * first, lower the sg capacity so that we'll try
                 * and move all the excess tasks away. We lower the capacity
                 * of a group only if the local group has the capacity to fit
-                * these excess tasks, i.e. nr_running < group_capacity_factor. The
-                * extra check prevents the case where you always pull from the
-                * heaviest group when it is already under-utilized (possible
-                * with a large weight task outweighs the tasks on the system).
+                * these excess tasks. The extra check prevents the case where
+                * you always pull from the heaviest group when it is already
+                * under-utilized (possible with a large weight task outweighs
+                * the tasks on the system).
                 */
                if (prefer_sibling && sds->local &&
-                   sds->local_stat.group_has_free_capacity) {
-                       sgs->group_capacity_factor = min(sgs->group_capacity_factor, 1U);
-                       sgs->group_type = group_classify(sg, sgs);
+                   group_has_capacity(env, &sds->local_stat) &&
+                   (sgs->sum_nr_running > 1)) {
+                       sgs->group_no_capacity = 1;
+                       sgs->group_type = group_overloaded;
                }
 
                if (update_sd_pick_busiest(env, sds, sg, sgs)) {
@@ -6541,11 +6614,12 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
         */
        if (busiest->group_type == group_overloaded &&
            local->group_type   == group_overloaded) {
-               load_above_capacity =
-                       (busiest->sum_nr_running - busiest->group_capacity_factor);
-
-               load_above_capacity *= (SCHED_LOAD_SCALE * SCHED_CAPACITY_SCALE);
-               load_above_capacity /= busiest->group_capacity;
+               load_above_capacity = busiest->sum_nr_running *
+                                       SCHED_LOAD_SCALE;
+               if (load_above_capacity > busiest->group_capacity)
+                       load_above_capacity -= busiest->group_capacity;
+               else
+                       load_above_capacity = ~0UL;
        }
 
        /*
@@ -6608,6 +6682,7 @@ static struct sched_group *find_busiest_group(struct lb_env *env)
        local = &sds.local_stat;
        busiest = &sds.busiest_stat;
 
+       /* ASYM feature bypasses nice load balance check */
        if ((env->idle == CPU_IDLE || env->idle == CPU_NEWLY_IDLE) &&
            check_asym_packing(env, &sds))
                return sds.busiest;
@@ -6628,8 +6703,8 @@ static struct sched_group *find_busiest_group(struct lb_env *env)
                goto force_balance;
 
        /* SD_BALANCE_NEWIDLE trumps SMP nice when underutilized */
-       if (env->idle == CPU_NEWLY_IDLE && local->group_has_free_capacity &&
-           !busiest->group_has_free_capacity)
+       if (env->idle == CPU_NEWLY_IDLE && group_has_capacity(env, local) &&
+           busiest->group_no_capacity)
                goto force_balance;
 
        /*
@@ -6688,7 +6763,7 @@ static struct rq *find_busiest_queue(struct lb_env *env,
        int i;
 
        for_each_cpu_and(i, sched_group_cpus(group), env->cpus) {
-               unsigned long capacity, capacity_factor, wl;
+               unsigned long capacity, wl;
                enum fbq_type rt;
 
                rq = cpu_rq(i);
@@ -6717,9 +6792,6 @@ static struct rq *find_busiest_queue(struct lb_env *env,
                        continue;
 
                capacity = capacity_of(i);
-               capacity_factor = DIV_ROUND_CLOSEST(capacity, SCHED_CAPACITY_SCALE);
-               if (!capacity_factor)
-                       capacity_factor = fix_small_capacity(env->sd, group);
 
                wl = weighted_cpuload(i);
 
@@ -6727,7 +6799,9 @@ static struct rq *find_busiest_queue(struct lb_env *env,
                 * When comparing with imbalance, use weighted_cpuload()
                 * which is not scaled with the cpu capacity.
                 */
-               if (capacity_factor && rq->nr_running == 1 && wl > env->imbalance)
+
+               if (rq->nr_running == 1 && wl > env->imbalance &&
+                   !check_cpu_capacity(rq, env->sd))
                        continue;
 
                /*
@@ -6775,6 +6849,19 @@ static int need_active_balance(struct lb_env *env)
                        return 1;
        }
 
+       /*
+        * The dst_cpu is idle and the src_cpu CPU has only 1 CFS task.
+        * It's worth migrating the task if the src_cpu's capacity is reduced
+        * because of other sched_class or IRQs if more capacity stays
+        * available on dst_cpu.
+        */
+       if ((env->idle != CPU_NOT_IDLE) &&
+           (env->src_rq->cfs.h_nr_running == 1)) {
+               if ((check_cpu_capacity(env->src_rq, sd)) &&
+                   (capacity_of(env->src_cpu)*sd->imbalance_pct < capacity_of(env->dst_cpu)*100))
+                       return 1;
+       }
+
        return unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2);
 }
 
@@ -6874,6 +6961,9 @@ redo:
 
        schedstat_add(sd, lb_imbalance[idle], env.imbalance);
 
+       env.src_cpu = busiest->cpu;
+       env.src_rq = busiest;
+
        ld_moved = 0;
        if (busiest->nr_running > 1) {
                /*
@@ -6883,8 +6973,6 @@ redo:
                 * correctly treated as an imbalance.
                 */
                env.flags |= LBF_ALL_PINNED;
-               env.src_cpu   = busiest->cpu;
-               env.src_rq    = busiest;
                env.loop_max  = min(sysctl_sched_nr_migrate, busiest->nr_running);
 
 more_balance:
@@ -7584,22 +7672,25 @@ end:
 
 /*
  * Current heuristic for kicking the idle load balancer in the presence
- * of an idle cpu is the system.
+ * of an idle cpu in the system.
  *   - This rq has more than one task.
- *   - At any scheduler domain level, this cpu's scheduler group has multiple
- *     busy cpu's exceeding the group's capacity.
+ *   - This rq has at least one CFS task and the capacity of the CPU is
+ *     significantly reduced because of RT tasks or IRQs.
+ *   - At parent of LLC scheduler domain level, this cpu's scheduler group has
+ *     multiple busy cpu.
  *   - For SD_ASYM_PACKING, if the lower numbered cpu's in the scheduler
  *     domain span are idle.
  */
-static inline int nohz_kick_needed(struct rq *rq)
+static inline bool nohz_kick_needed(struct rq *rq)
 {
        unsigned long now = jiffies;
        struct sched_domain *sd;
        struct sched_group_capacity *sgc;
        int nr_busy, cpu = rq->cpu;
+       bool kick = false;
 
        if (unlikely(rq->idle_balance))
-               return 0;
+               return false;
 
        /*
        * We may be recently in ticked or tickless idle mode. At the first
@@ -7613,38 +7704,46 @@ static inline int nohz_kick_needed(struct rq *rq)
         * balancing.
         */
        if (likely(!atomic_read(&nohz.nr_cpus)))
-               return 0;
+               return false;
 
        if (time_before(now, nohz.next_balance))
-               return 0;
+               return false;
 
        if (rq->nr_running >= 2)
-               goto need_kick;
+               return true;
 
        rcu_read_lock();
        sd = rcu_dereference(per_cpu(sd_busy, cpu));
-
        if (sd) {
                sgc = sd->groups->sgc;
                nr_busy = atomic_read(&sgc->nr_busy_cpus);
 
-               if (nr_busy > 1)
-                       goto need_kick_unlock;
+               if (nr_busy > 1) {
+                       kick = true;
+                       goto unlock;
+               }
+
        }
 
-       sd = rcu_dereference(per_cpu(sd_asym, cpu));
+       sd = rcu_dereference(rq->sd);
+       if (sd) {
+               if ((rq->cfs.h_nr_running >= 1) &&
+                               check_cpu_capacity(rq, sd)) {
+                       kick = true;
+                       goto unlock;
+               }
+       }
 
+       sd = rcu_dereference(per_cpu(sd_asym, cpu));
        if (sd && (cpumask_first_and(nohz.idle_cpus_mask,
-                                 sched_domain_span(sd)) < cpu))
-               goto need_kick_unlock;
-
-       rcu_read_unlock();
-       return 0;
+                                 sched_domain_span(sd)) < cpu)) {
+               kick = true;
+               goto unlock;
+       }
 
-need_kick_unlock:
+unlock:
        rcu_read_unlock();
-need_kick:
-       return 1;
+       return kick;
 }
 #else
 static void nohz_idle_balance(struct rq *this_rq, enum cpu_idle_type idle) { }
@@ -7660,14 +7759,16 @@ static void run_rebalance_domains(struct softirq_action *h)
        enum cpu_idle_type idle = this_rq->idle_balance ?
                                                CPU_IDLE : CPU_NOT_IDLE;
 
-       rebalance_domains(this_rq, idle);
-
        /*
         * If this cpu has a pending nohz_balance_kick, then do the
         * balancing on behalf of the other idle cpus whose ticks are
-        * stopped.
+        * stopped. Do nohz_idle_balance *before* rebalance_domains to
+        * give the idle cpus a chance to load balance. Else we may
+        * load balance only within the local sched_domain hierarchy
+        * and abort nohz_idle_balance altogether if we pull some load.
         */
        nohz_idle_balance(this_rq, idle);
+       rebalance_domains(this_rq, idle);
 }
 
 /*
index 90284d117fe65ffc7ee1de7127995a750c84df92..91e33cd485f6577050672432c02354393887774e 100644 (file)
@@ -56,6 +56,19 @@ SCHED_FEAT(NONTASK_CAPACITY, true)
  */
 SCHED_FEAT(TTWU_QUEUE, true)
 
+#ifdef HAVE_RT_PUSH_IPI
+/*
+ * In order to avoid a thundering herd attack of CPUs that are
+ * lowering their priorities at the same time, and there being
+ * a single CPU that has an RT task that can migrate and is waiting
+ * to run, where the other CPUs will try to take that CPUs
+ * rq lock and possibly create a large contention, sending an
+ * IPI to that CPU and let that CPU push the RT task to where
+ * it should go may be a better scenario.
+ */
+SCHED_FEAT(RT_PUSH_IPI, true)
+#endif
+
 SCHED_FEAT(FORCE_SD_OVERLAP, false)
 SCHED_FEAT(RT_RUNTIME_SHARE, true)
 SCHED_FEAT(LB_MIN, false)
index 80014a17834214fcad51add08b2b171463e84128..deef1caa94c6779ea13e48690ffc2d9de2e7dddc 100644 (file)
@@ -158,8 +158,7 @@ static void cpuidle_idle_call(void)
         * is used from another cpu as a broadcast timer, this call may
         * fail if it is not available
         */
-       if (broadcast &&
-           clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu))
+       if (broadcast && tick_broadcast_enter())
                goto use_default;
 
        /* Take note of the planned idle state. */
@@ -176,7 +175,7 @@ static void cpuidle_idle_call(void)
        idle_set_state(this_rq(), NULL);
 
        if (broadcast)
-               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+               tick_broadcast_exit();
 
        /*
         * Give the governor an opportunity to reflect on the outcome
@@ -210,6 +209,8 @@ use_default:
        goto exit_idle;
 }
 
+DEFINE_PER_CPU(bool, cpu_dead_idle);
+
 /*
  * Generic idle loop implementation
  *
@@ -234,8 +235,13 @@ static void cpu_idle_loop(void)
                        check_pgt_cache();
                        rmb();
 
-                       if (cpu_is_offline(smp_processor_id()))
+                       if (cpu_is_offline(smp_processor_id())) {
+                               rcu_cpu_notify(NULL, CPU_DYING_IDLE,
+                                              (void *)(long)smp_processor_id());
+                               smp_mb(); /* all activity before dead. */
+                               this_cpu_write(cpu_dead_idle, true);
                                arch_cpu_idle_dead();
+                       }
 
                        local_irq_disable();
                        arch_cpu_idle_enter();
index f4d4b077eba0a67a5c55e6a04dee8f6ce78f322c..575da76a3874a8c1b2ddd0f518e5ecea7a805262 100644 (file)
@@ -6,6 +6,7 @@
 #include "sched.h"
 
 #include <linux/slab.h>
+#include <linux/irq_work.h>
 
 int sched_rr_timeslice = RR_TIMESLICE;
 
@@ -59,7 +60,11 @@ static void start_rt_bandwidth(struct rt_bandwidth *rt_b)
        raw_spin_unlock(&rt_b->rt_runtime_lock);
 }
 
-void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq)
+#ifdef CONFIG_SMP
+static void push_irq_work_func(struct irq_work *work);
+#endif
+
+void init_rt_rq(struct rt_rq *rt_rq)
 {
        struct rt_prio_array *array;
        int i;
@@ -78,7 +83,14 @@ void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq)
        rt_rq->rt_nr_migratory = 0;
        rt_rq->overloaded = 0;
        plist_head_init(&rt_rq->pushable_tasks);
+
+#ifdef HAVE_RT_PUSH_IPI
+       rt_rq->push_flags = 0;
+       rt_rq->push_cpu = nr_cpu_ids;
+       raw_spin_lock_init(&rt_rq->push_lock);
+       init_irq_work(&rt_rq->push_work, push_irq_work_func);
 #endif
+#endif /* CONFIG_SMP */
        /* We start is dequeued state, because no RT tasks are queued */
        rt_rq->rt_queued = 0;
 
@@ -193,7 +205,7 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
                if (!rt_se)
                        goto err_free_rq;
 
-               init_rt_rq(rt_rq, cpu_rq(i));
+               init_rt_rq(rt_rq);
                rt_rq->rt_runtime = tg->rt_bandwidth.rt_runtime;
                init_tg_rt_entry(tg, rt_rq, rt_se, i, parent->rt_se[i]);
        }
@@ -1778,6 +1790,164 @@ static void push_rt_tasks(struct rq *rq)
                ;
 }
 
+#ifdef HAVE_RT_PUSH_IPI
+/*
+ * The search for the next cpu always starts at rq->cpu and ends
+ * when we reach rq->cpu again. It will never return rq->cpu.
+ * This returns the next cpu to check, or nr_cpu_ids if the loop
+ * is complete.
+ *
+ * rq->rt.push_cpu holds the last cpu returned by this function,
+ * or if this is the first instance, it must hold rq->cpu.
+ */
+static int rto_next_cpu(struct rq *rq)
+{
+       int prev_cpu = rq->rt.push_cpu;
+       int cpu;
+
+       cpu = cpumask_next(prev_cpu, rq->rd->rto_mask);
+
+       /*
+        * If the previous cpu is less than the rq's CPU, then it already
+        * passed the end of the mask, and has started from the beginning.
+        * We end if the next CPU is greater or equal to rq's CPU.
+        */
+       if (prev_cpu < rq->cpu) {
+               if (cpu >= rq->cpu)
+                       return nr_cpu_ids;
+
+       } else if (cpu >= nr_cpu_ids) {
+               /*
+                * We passed the end of the mask, start at the beginning.
+                * If the result is greater or equal to the rq's CPU, then
+                * the loop is finished.
+                */
+               cpu = cpumask_first(rq->rd->rto_mask);
+               if (cpu >= rq->cpu)
+                       return nr_cpu_ids;
+       }
+       rq->rt.push_cpu = cpu;
+
+       /* Return cpu to let the caller know if the loop is finished or not */
+       return cpu;
+}
+
+static int find_next_push_cpu(struct rq *rq)
+{
+       struct rq *next_rq;
+       int cpu;
+
+       while (1) {
+               cpu = rto_next_cpu(rq);
+               if (cpu >= nr_cpu_ids)
+                       break;
+               next_rq = cpu_rq(cpu);
+
+               /* Make sure the next rq can push to this rq */
+               if (next_rq->rt.highest_prio.next < rq->rt.highest_prio.curr)
+                       break;
+       }
+
+       return cpu;
+}
+
+#define RT_PUSH_IPI_EXECUTING          1
+#define RT_PUSH_IPI_RESTART            2
+
+static void tell_cpu_to_push(struct rq *rq)
+{
+       int cpu;
+
+       if (rq->rt.push_flags & RT_PUSH_IPI_EXECUTING) {
+               raw_spin_lock(&rq->rt.push_lock);
+               /* Make sure it's still executing */
+               if (rq->rt.push_flags & RT_PUSH_IPI_EXECUTING) {
+                       /*
+                        * Tell the IPI to restart the loop as things have
+                        * changed since it started.
+                        */
+                       rq->rt.push_flags |= RT_PUSH_IPI_RESTART;
+                       raw_spin_unlock(&rq->rt.push_lock);
+                       return;
+               }
+               raw_spin_unlock(&rq->rt.push_lock);
+       }
+
+       /* When here, there's no IPI going around */
+
+       rq->rt.push_cpu = rq->cpu;
+       cpu = find_next_push_cpu(rq);
+       if (cpu >= nr_cpu_ids)
+               return;
+
+       rq->rt.push_flags = RT_PUSH_IPI_EXECUTING;
+
+       irq_work_queue_on(&rq->rt.push_work, cpu);
+}
+
+/* Called from hardirq context */
+static void try_to_push_tasks(void *arg)
+{
+       struct rt_rq *rt_rq = arg;
+       struct rq *rq, *src_rq;
+       int this_cpu;
+       int cpu;
+
+       this_cpu = rt_rq->push_cpu;
+
+       /* Paranoid check */
+       BUG_ON(this_cpu != smp_processor_id());
+
+       rq = cpu_rq(this_cpu);
+       src_rq = rq_of_rt_rq(rt_rq);
+
+again:
+       if (has_pushable_tasks(rq)) {
+               raw_spin_lock(&rq->lock);
+               push_rt_task(rq);
+               raw_spin_unlock(&rq->lock);
+       }
+
+       /* Pass the IPI to the next rt overloaded queue */
+       raw_spin_lock(&rt_rq->push_lock);
+       /*
+        * If the source queue changed since the IPI went out,
+        * we need to restart the search from that CPU again.
+        */
+       if (rt_rq->push_flags & RT_PUSH_IPI_RESTART) {
+               rt_rq->push_flags &= ~RT_PUSH_IPI_RESTART;
+               rt_rq->push_cpu = src_rq->cpu;
+       }
+
+       cpu = find_next_push_cpu(src_rq);
+
+       if (cpu >= nr_cpu_ids)
+               rt_rq->push_flags &= ~RT_PUSH_IPI_EXECUTING;
+       raw_spin_unlock(&rt_rq->push_lock);
+
+       if (cpu >= nr_cpu_ids)
+               return;
+
+       /*
+        * It is possible that a restart caused this CPU to be
+        * chosen again. Don't bother with an IPI, just see if we
+        * have more to push.
+        */
+       if (unlikely(cpu == rq->cpu))
+               goto again;
+
+       /* Try the next RT overloaded CPU */
+       irq_work_queue_on(&rt_rq->push_work, cpu);
+}
+
+static void push_irq_work_func(struct irq_work *work)
+{
+       struct rt_rq *rt_rq = container_of(work, struct rt_rq, push_work);
+
+       try_to_push_tasks(rt_rq);
+}
+#endif /* HAVE_RT_PUSH_IPI */
+
 static int pull_rt_task(struct rq *this_rq)
 {
        int this_cpu = this_rq->cpu, ret = 0, cpu;
@@ -1793,6 +1963,13 @@ static int pull_rt_task(struct rq *this_rq)
         */
        smp_rmb();
 
+#ifdef HAVE_RT_PUSH_IPI
+       if (sched_feat(RT_PUSH_IPI)) {
+               tell_cpu_to_push(this_rq);
+               return 0;
+       }
+#endif
+
        for_each_cpu(cpu, this_rq->rd->rto_mask) {
                if (this_cpu == cpu)
                        continue;
index dc0f435a27794657258623ac8a7f53f7326ff7ac..e0e1299939588ac47f08b13b45f1a6e2e9cf4d7f 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/stop_machine.h>
+#include <linux/irq_work.h>
 #include <linux/tick.h>
 #include <linux/slab.h>
 
@@ -362,8 +363,14 @@ struct cfs_rq {
         * Under CFS, load is tracked on a per-entity basis and aggregated up.
         * This allows for the description of both thread and group usage (in
         * the FAIR_GROUP_SCHED case).
+        * runnable_load_avg is the sum of the load_avg_contrib of the
+        * sched_entities on the rq.
+        * blocked_load_avg is similar to runnable_load_avg except that its
+        * the blocked sched_entities on the rq.
+        * utilization_load_avg is the sum of the average running time of the
+        * sched_entities on the rq.
         */
-       unsigned long runnable_load_avg, blocked_load_avg;
+       unsigned long runnable_load_avg, blocked_load_avg, utilization_load_avg;
        atomic64_t decay_counter;
        u64 last_decay;
        atomic_long_t removed_load;
@@ -418,6 +425,11 @@ static inline int rt_bandwidth_enabled(void)
        return sysctl_sched_rt_runtime >= 0;
 }
 
+/* RT IPI pull logic requires IRQ_WORK */
+#ifdef CONFIG_IRQ_WORK
+# define HAVE_RT_PUSH_IPI
+#endif
+
 /* Real-Time classes' related field in a runqueue: */
 struct rt_rq {
        struct rt_prio_array active;
@@ -435,7 +447,13 @@ struct rt_rq {
        unsigned long rt_nr_total;
        int overloaded;
        struct plist_head pushable_tasks;
+#ifdef HAVE_RT_PUSH_IPI
+       int push_flags;
+       int push_cpu;
+       struct irq_work push_work;
+       raw_spinlock_t push_lock;
 #endif
+#endif /* CONFIG_SMP */
        int rt_queued;
 
        int rt_throttled;
@@ -597,6 +615,7 @@ struct rq {
        struct sched_domain *sd;
 
        unsigned long cpu_capacity;
+       unsigned long cpu_capacity_orig;
 
        unsigned char idle_balance;
        /* For active balancing */
@@ -807,7 +826,7 @@ struct sched_group_capacity {
         * CPU capacity of this group, SCHED_LOAD_SCALE being max capacity
         * for a single CPU.
         */
-       unsigned int capacity, capacity_orig;
+       unsigned int capacity;
        unsigned long next_update;
        int imbalance; /* XXX unrelated to capacity but shared group state */
        /*
@@ -1368,9 +1387,18 @@ static inline int hrtick_enabled(struct rq *rq)
 
 #ifdef CONFIG_SMP
 extern void sched_avg_update(struct rq *rq);
+
+#ifndef arch_scale_freq_capacity
+static __always_inline
+unsigned long arch_scale_freq_capacity(struct sched_domain *sd, int cpu)
+{
+       return SCHED_CAPACITY_SCALE;
+}
+#endif
+
 static inline void sched_rt_avg_update(struct rq *rq, u64 rt_delta)
 {
-       rq->rt_avg += rt_delta;
+       rq->rt_avg += rt_delta * arch_scale_freq_capacity(NULL, cpu_of(rq));
        sched_avg_update(rq);
 }
 #else
@@ -1643,8 +1671,8 @@ extern void print_rt_stats(struct seq_file *m, int cpu);
 extern void print_dl_stats(struct seq_file *m, int cpu);
 
 extern void init_cfs_rq(struct cfs_rq *cfs_rq);
-extern void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq);
-extern void init_dl_rq(struct dl_rq *dl_rq, struct rq *rq);
+extern void init_rt_rq(struct rt_rq *rt_rq);
+extern void init_dl_rq(struct dl_rq *dl_rq);
 
 extern void cfs_bandwidth_usage_inc(void);
 extern void cfs_bandwidth_usage_dec(void);
index 40190f28db3590140cb903d3f596883c61faaa74..c697f73d82d6a4157a15ef9b0039b007083f7857 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/cpu.h>
 #include <linux/err.h>
 #include <linux/smp.h>
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/slab.h>
@@ -314,3 +315,158 @@ void smpboot_unregister_percpu_thread(struct smp_hotplug_thread *plug_thread)
        put_online_cpus();
 }
 EXPORT_SYMBOL_GPL(smpboot_unregister_percpu_thread);
+
+static DEFINE_PER_CPU(atomic_t, cpu_hotplug_state) = ATOMIC_INIT(CPU_POST_DEAD);
+
+/*
+ * Called to poll specified CPU's state, for example, when waiting for
+ * a CPU to come online.
+ */
+int cpu_report_state(int cpu)
+{
+       return atomic_read(&per_cpu(cpu_hotplug_state, cpu));
+}
+
+/*
+ * If CPU has died properly, set its state to CPU_UP_PREPARE and
+ * return success.  Otherwise, return -EBUSY if the CPU died after
+ * cpu_wait_death() timed out.  And yet otherwise again, return -EAGAIN
+ * if cpu_wait_death() timed out and the CPU still hasn't gotten around
+ * to dying.  In the latter two cases, the CPU might not be set up
+ * properly, but it is up to the arch-specific code to decide.
+ * Finally, -EIO indicates an unanticipated problem.
+ *
+ * Note that it is permissible to omit this call entirely, as is
+ * done in architectures that do no CPU-hotplug error checking.
+ */
+int cpu_check_up_prepare(int cpu)
+{
+       if (!IS_ENABLED(CONFIG_HOTPLUG_CPU)) {
+               atomic_set(&per_cpu(cpu_hotplug_state, cpu), CPU_UP_PREPARE);
+               return 0;
+       }
+
+       switch (atomic_read(&per_cpu(cpu_hotplug_state, cpu))) {
+
+       case CPU_POST_DEAD:
+
+               /* The CPU died properly, so just start it up again. */
+               atomic_set(&per_cpu(cpu_hotplug_state, cpu), CPU_UP_PREPARE);
+               return 0;
+
+       case CPU_DEAD_FROZEN:
+
+               /*
+                * Timeout during CPU death, so let caller know.
+                * The outgoing CPU completed its processing, but after
+                * cpu_wait_death() timed out and reported the error. The
+                * caller is free to proceed, in which case the state
+                * will be reset properly by cpu_set_state_online().
+                * Proceeding despite this -EBUSY return makes sense
+                * for systems where the outgoing CPUs take themselves
+                * offline, with no post-death manipulation required from
+                * a surviving CPU.
+                */
+               return -EBUSY;
+
+       case CPU_BROKEN:
+
+               /*
+                * The most likely reason we got here is that there was
+                * a timeout during CPU death, and the outgoing CPU never
+                * did complete its processing.  This could happen on
+                * a virtualized system if the outgoing VCPU gets preempted
+                * for more than five seconds, and the user attempts to
+                * immediately online that same CPU.  Trying again later
+                * might return -EBUSY above, hence -EAGAIN.
+                */
+               return -EAGAIN;
+
+       default:
+
+               /* Should not happen.  Famous last words. */
+               return -EIO;
+       }
+}
+
+/*
+ * Mark the specified CPU online.
+ *
+ * Note that it is permissible to omit this call entirely, as is
+ * done in architectures that do no CPU-hotplug error checking.
+ */
+void cpu_set_state_online(int cpu)
+{
+       (void)atomic_xchg(&per_cpu(cpu_hotplug_state, cpu), CPU_ONLINE);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+/*
+ * Wait for the specified CPU to exit the idle loop and die.
+ */
+bool cpu_wait_death(unsigned int cpu, int seconds)
+{
+       int jf_left = seconds * HZ;
+       int oldstate;
+       bool ret = true;
+       int sleep_jf = 1;
+
+       might_sleep();
+
+       /* The outgoing CPU will normally get done quite quickly. */
+       if (atomic_read(&per_cpu(cpu_hotplug_state, cpu)) == CPU_DEAD)
+               goto update_state;
+       udelay(5);
+
+       /* But if the outgoing CPU dawdles, wait increasingly long times. */
+       while (atomic_read(&per_cpu(cpu_hotplug_state, cpu)) != CPU_DEAD) {
+               schedule_timeout_uninterruptible(sleep_jf);
+               jf_left -= sleep_jf;
+               if (jf_left <= 0)
+                       break;
+               sleep_jf = DIV_ROUND_UP(sleep_jf * 11, 10);
+       }
+update_state:
+       oldstate = atomic_read(&per_cpu(cpu_hotplug_state, cpu));
+       if (oldstate == CPU_DEAD) {
+               /* Outgoing CPU died normally, update state. */
+               smp_mb(); /* atomic_read() before update. */
+               atomic_set(&per_cpu(cpu_hotplug_state, cpu), CPU_POST_DEAD);
+       } else {
+               /* Outgoing CPU still hasn't died, set state accordingly. */
+               if (atomic_cmpxchg(&per_cpu(cpu_hotplug_state, cpu),
+                                  oldstate, CPU_BROKEN) != oldstate)
+                       goto update_state;
+               ret = false;
+       }
+       return ret;
+}
+
+/*
+ * Called by the outgoing CPU to report its successful death.  Return
+ * false if this report follows the surviving CPU's timing out.
+ *
+ * A separate "CPU_DEAD_FROZEN" is used when the surviving CPU
+ * timed out.  This approach allows architectures to omit calls to
+ * cpu_check_up_prepare() and cpu_set_state_online() without defeating
+ * the next cpu_wait_death()'s polling loop.
+ */
+bool cpu_report_death(void)
+{
+       int oldstate;
+       int newstate;
+       int cpu = smp_processor_id();
+
+       do {
+               oldstate = atomic_read(&per_cpu(cpu_hotplug_state, cpu));
+               if (oldstate != CPU_BROKEN)
+                       newstate = CPU_DEAD;
+               else
+                       newstate = CPU_DEAD_FROZEN;
+       } while (atomic_cmpxchg(&per_cpu(cpu_hotplug_state, cpu),
+                               oldstate, newstate) != oldstate);
+       return newstate == CPU_DEAD;
+}
+
+#endif /* #ifdef CONFIG_HOTPLUG_CPU */
index ce410bb9f2e103e0fcfda7d7b844948a0a28fbce..8c0eabd418862bcaaebc7b01dcc3ea7ce4951a2b 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/aio.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/slab.h>
@@ -846,7 +847,7 @@ static struct ctl_table kern_table[] = {
                .data           = &watchdog_user_enabled,
                .maxlen         = sizeof (int),
                .mode           = 0644,
-               .proc_handler   = proc_dowatchdog,
+               .proc_handler   = proc_watchdog,
                .extra1         = &zero,
                .extra2         = &one,
        },
@@ -855,10 +856,32 @@ static struct ctl_table kern_table[] = {
                .data           = &watchdog_thresh,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dowatchdog,
+               .proc_handler   = proc_watchdog_thresh,
                .extra1         = &zero,
                .extra2         = &sixty,
        },
+       {
+               .procname       = "nmi_watchdog",
+               .data           = &nmi_watchdog_enabled,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler   = proc_nmi_watchdog,
+               .extra1         = &zero,
+#if defined(CONFIG_HAVE_NMI_WATCHDOG) || defined(CONFIG_HARDLOCKUP_DETECTOR)
+               .extra2         = &one,
+#else
+               .extra2         = &zero,
+#endif
+       },
+       {
+               .procname       = "soft_watchdog",
+               .data           = &soft_watchdog_enabled,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler   = proc_soft_watchdog,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
        {
                .procname       = "softlockup_panic",
                .data           = &softlockup_panic,
@@ -879,15 +902,6 @@ static struct ctl_table kern_table[] = {
                .extra2         = &one,
        },
 #endif /* CONFIG_SMP */
-       {
-               .procname       = "nmi_watchdog",
-               .data           = &watchdog_user_enabled,
-               .maxlen         = sizeof (int),
-               .mode           = 0644,
-               .proc_handler   = proc_dowatchdog,
-               .extra1         = &zero,
-               .extra2         = &one,
-       },
 #endif
 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
        {
index d626dc98e8df952eff1df8ced84b2557475fe6c6..579ce1b929afde343a29fc77e4e7c4997ea18852 100644 (file)
@@ -33,12 +33,6 @@ config ARCH_USES_GETTIMEOFFSET
 config GENERIC_CLOCKEVENTS
        bool
 
-# Migration helper. Builds, but does not invoke
-config GENERIC_CLOCKEVENTS_BUILD
-       bool
-       default y
-       depends on GENERIC_CLOCKEVENTS
-
 # Architecture can handle broadcast in a driver-agnostic way
 config ARCH_HAS_TICK_BROADCAST
        bool
index c09c07817d7a7c854a1b88b12b894f60c547cda9..01f0312419b3cb44d8fa455d8cfaa2ad14d5ef0d 100644 (file)
@@ -2,15 +2,13 @@ obj-y += time.o timer.o hrtimer.o itimer.o posix-timers.o posix-cpu-timers.o
 obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
 obj-y += timeconv.o timecounter.o posix-clock.o alarmtimer.o
 
-obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD)                += clockevents.o
-obj-$(CONFIG_GENERIC_CLOCKEVENTS)              += tick-common.o
+obj-$(CONFIG_GENERIC_CLOCKEVENTS)              += clockevents.o tick-common.o
 ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y)
  obj-y                                         += tick-broadcast.o
  obj-$(CONFIG_TICK_ONESHOT)                    += tick-broadcast-hrtimer.o
 endif
 obj-$(CONFIG_GENERIC_SCHED_CLOCK)              += sched_clock.o
-obj-$(CONFIG_TICK_ONESHOT)                     += tick-oneshot.o
-obj-$(CONFIG_TICK_ONESHOT)                     += tick-sched.o
+obj-$(CONFIG_TICK_ONESHOT)                     += tick-oneshot.o tick-sched.o
 obj-$(CONFIG_TIMER_STATS)                      += timer_stats.o
 obj-$(CONFIG_DEBUG_FS)                         += timekeeping_debug.o
 obj-$(CONFIG_TEST_UDELAY)                      += test_udelay.o
index 55449909f11475372135ac61b33e65114eb151ba..25d942d1da27095e6366d720a0f8de58009cb5f3 100644 (file)
@@ -94,25 +94,76 @@ u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt)
 }
 EXPORT_SYMBOL_GPL(clockevent_delta2ns);
 
+static int __clockevents_set_state(struct clock_event_device *dev,
+                                  enum clock_event_state state)
+{
+       /* Transition with legacy set_mode() callback */
+       if (dev->set_mode) {
+               /* Legacy callback doesn't support new modes */
+               if (state > CLOCK_EVT_STATE_ONESHOT)
+                       return -ENOSYS;
+               /*
+                * 'clock_event_state' and 'clock_event_mode' have 1-to-1
+                * mapping until *_ONESHOT, and so a simple cast will work.
+                */
+               dev->set_mode((enum clock_event_mode)state, dev);
+               dev->mode = (enum clock_event_mode)state;
+               return 0;
+       }
+
+       if (dev->features & CLOCK_EVT_FEAT_DUMMY)
+               return 0;
+
+       /* Transition with new state-specific callbacks */
+       switch (state) {
+       case CLOCK_EVT_STATE_DETACHED:
+               /*
+                * This is an internal state, which is guaranteed to go from
+                * SHUTDOWN to DETACHED. No driver interaction required.
+                */
+               return 0;
+
+       case CLOCK_EVT_STATE_SHUTDOWN:
+               return dev->set_state_shutdown(dev);
+
+       case CLOCK_EVT_STATE_PERIODIC:
+               /* Core internal bug */
+               if (!(dev->features & CLOCK_EVT_FEAT_PERIODIC))
+                       return -ENOSYS;
+               return dev->set_state_periodic(dev);
+
+       case CLOCK_EVT_STATE_ONESHOT:
+               /* Core internal bug */
+               if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT))
+                       return -ENOSYS;
+               return dev->set_state_oneshot(dev);
+
+       default:
+               return -ENOSYS;
+       }
+}
+
 /**
- * clockevents_set_mode - set the operating mode of a clock event device
+ * clockevents_set_state - set the operating state of a clock event device
  * @dev:       device to modify
- * @mode:      new mode
+ * @state:     new state
  *
  * Must be called with interrupts disabled !
  */
-void clockevents_set_mode(struct clock_event_device *dev,
-                                enum clock_event_mode mode)
+void clockevents_set_state(struct clock_event_device *dev,
+                          enum clock_event_state state)
 {
-       if (dev->mode != mode) {
-               dev->set_mode(mode, dev);
-               dev->mode = mode;
+       if (dev->state != state) {
+               if (__clockevents_set_state(dev, state))
+                       return;
+
+               dev->state = state;
 
                /*
                 * A nsec2cyc multiplicator of 0 is invalid and we'd crash
                 * on it, so fix it up and emit a warning:
                 */
-               if (mode == CLOCK_EVT_MODE_ONESHOT) {
+               if (state == CLOCK_EVT_STATE_ONESHOT) {
                        if (unlikely(!dev->mult)) {
                                dev->mult = 1;
                                WARN_ON(1);
@@ -127,10 +178,28 @@ void clockevents_set_mode(struct clock_event_device *dev,
  */
 void clockevents_shutdown(struct clock_event_device *dev)
 {
-       clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
+       clockevents_set_state(dev, CLOCK_EVT_STATE_SHUTDOWN);
        dev->next_event.tv64 = KTIME_MAX;
 }
 
+/**
+ * clockevents_tick_resume -   Resume the tick device before using it again
+ * @dev:                       device to resume
+ */
+int clockevents_tick_resume(struct clock_event_device *dev)
+{
+       int ret = 0;
+
+       if (dev->set_mode) {
+               dev->set_mode(CLOCK_EVT_MODE_RESUME, dev);
+               dev->mode = CLOCK_EVT_MODE_RESUME;
+       } else if (dev->tick_resume) {
+               ret = dev->tick_resume(dev);
+       }
+
+       return ret;
+}
+
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST
 
 /* Limit min_delta to a jiffie */
@@ -183,7 +252,7 @@ static int clockevents_program_min_delta(struct clock_event_device *dev)
                delta = dev->min_delta_ns;
                dev->next_event = ktime_add_ns(ktime_get(), delta);
 
-               if (dev->mode == CLOCK_EVT_MODE_SHUTDOWN)
+               if (dev->state == CLOCK_EVT_STATE_SHUTDOWN)
                        return 0;
 
                dev->retries++;
@@ -220,7 +289,7 @@ static int clockevents_program_min_delta(struct clock_event_device *dev)
        delta = dev->min_delta_ns;
        dev->next_event = ktime_add_ns(ktime_get(), delta);
 
-       if (dev->mode == CLOCK_EVT_MODE_SHUTDOWN)
+       if (dev->state == CLOCK_EVT_STATE_SHUTDOWN)
                return 0;
 
        dev->retries++;
@@ -252,7 +321,7 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
 
        dev->next_event = expires;
 
-       if (dev->mode == CLOCK_EVT_MODE_SHUTDOWN)
+       if (dev->state == CLOCK_EVT_STATE_SHUTDOWN)
                return 0;
 
        /* Shortcut for clockevent devices that can deal with ktime. */
@@ -297,7 +366,7 @@ static int clockevents_replace(struct clock_event_device *ced)
        struct clock_event_device *dev, *newdev = NULL;
 
        list_for_each_entry(dev, &clockevent_devices, list) {
-               if (dev == ced || dev->mode != CLOCK_EVT_MODE_UNUSED)
+               if (dev == ced || dev->state != CLOCK_EVT_STATE_DETACHED)
                        continue;
 
                if (!tick_check_replacement(newdev, dev))
@@ -323,7 +392,7 @@ static int clockevents_replace(struct clock_event_device *ced)
 static int __clockevents_try_unbind(struct clock_event_device *ced, int cpu)
 {
        /* Fast track. Device is unused */
-       if (ced->mode == CLOCK_EVT_MODE_UNUSED) {
+       if (ced->state == CLOCK_EVT_STATE_DETACHED) {
                list_del_init(&ced->list);
                return 0;
        }
@@ -373,6 +442,37 @@ int clockevents_unbind_device(struct clock_event_device *ced, int cpu)
 }
 EXPORT_SYMBOL_GPL(clockevents_unbind);
 
+/* Sanity check of state transition callbacks */
+static int clockevents_sanity_check(struct clock_event_device *dev)
+{
+       /* Legacy set_mode() callback */
+       if (dev->set_mode) {
+               /* We shouldn't be supporting new modes now */
+               WARN_ON(dev->set_state_periodic || dev->set_state_oneshot ||
+                       dev->set_state_shutdown || dev->tick_resume);
+
+               BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
+               return 0;
+       }
+
+       if (dev->features & CLOCK_EVT_FEAT_DUMMY)
+               return 0;
+
+       /* New state-specific callbacks */
+       if (!dev->set_state_shutdown)
+               return -EINVAL;
+
+       if ((dev->features & CLOCK_EVT_FEAT_PERIODIC) &&
+           !dev->set_state_periodic)
+               return -EINVAL;
+
+       if ((dev->features & CLOCK_EVT_FEAT_ONESHOT) &&
+           !dev->set_state_oneshot)
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
  * clockevents_register_device - register a clock event device
  * @dev:       device to register
@@ -381,7 +481,11 @@ void clockevents_register_device(struct clock_event_device *dev)
 {
        unsigned long flags;
 
-       BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
+       BUG_ON(clockevents_sanity_check(dev));
+
+       /* Initialize state to DETACHED */
+       dev->state = CLOCK_EVT_STATE_DETACHED;
+
        if (!dev->cpumask) {
                WARN_ON(num_possible_cpus() > 1);
                dev->cpumask = cpumask_of(smp_processor_id());
@@ -445,11 +549,11 @@ int __clockevents_update_freq(struct clock_event_device *dev, u32 freq)
 {
        clockevents_config(dev, freq);
 
-       if (dev->mode == CLOCK_EVT_MODE_ONESHOT)
+       if (dev->state == CLOCK_EVT_STATE_ONESHOT)
                return clockevents_program_event(dev, dev->next_event, false);
 
-       if (dev->mode == CLOCK_EVT_MODE_PERIODIC)
-               dev->set_mode(CLOCK_EVT_MODE_PERIODIC, dev);
+       if (dev->state == CLOCK_EVT_STATE_PERIODIC)
+               return __clockevents_set_state(dev, CLOCK_EVT_STATE_PERIODIC);
 
        return 0;
 }
@@ -491,30 +595,27 @@ void clockevents_handle_noop(struct clock_event_device *dev)
  * @old:       device to release (can be NULL)
  * @new:       device to request (can be NULL)
  *
- * Called from the notifier chain. clockevents_lock is held already
+ * Called from various tick functions with clockevents_lock held and
+ * interrupts disabled.
  */
 void clockevents_exchange_device(struct clock_event_device *old,
                                 struct clock_event_device *new)
 {
-       unsigned long flags;
-
-       local_irq_save(flags);
        /*
         * Caller releases a clock event device. We queue it into the
         * released list and do a notify add later.
         */
        if (old) {
                module_put(old->owner);
-               clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED);
+               clockevents_set_state(old, CLOCK_EVT_STATE_DETACHED);
                list_del(&old->list);
                list_add(&old->list, &clockevents_released);
        }
 
        if (new) {
-               BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED);
+               BUG_ON(new->state != CLOCK_EVT_STATE_DETACHED);
                clockevents_shutdown(new);
        }
-       local_irq_restore(flags);
 }
 
 /**
@@ -541,74 +642,40 @@ void clockevents_resume(void)
                        dev->resume(dev);
 }
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
+#ifdef CONFIG_HOTPLUG_CPU
 /**
- * clockevents_notify - notification about relevant events
- * Returns 0 on success, any other value on error
+ * tick_cleanup_dead_cpu - Cleanup the tick and clockevents of a dead cpu
  */
-int clockevents_notify(unsigned long reason, void *arg)
+void tick_cleanup_dead_cpu(int cpu)
 {
        struct clock_event_device *dev, *tmp;
        unsigned long flags;
-       int cpu, ret = 0;
 
        raw_spin_lock_irqsave(&clockevents_lock, flags);
 
-       switch (reason) {
-       case CLOCK_EVT_NOTIFY_BROADCAST_ON:
-       case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
-       case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
-               tick_broadcast_on_off(reason, arg);
-               break;
-
-       case CLOCK_EVT_NOTIFY_BROADCAST_ENTER:
-       case CLOCK_EVT_NOTIFY_BROADCAST_EXIT:
-               ret = tick_broadcast_oneshot_control(reason);
-               break;
-
-       case CLOCK_EVT_NOTIFY_CPU_DYING:
-               tick_handover_do_timer(arg);
-               break;
-
-       case CLOCK_EVT_NOTIFY_SUSPEND:
-               tick_suspend();
-               tick_suspend_broadcast();
-               break;
-
-       case CLOCK_EVT_NOTIFY_RESUME:
-               tick_resume();
-               break;
-
-       case CLOCK_EVT_NOTIFY_CPU_DEAD:
-               tick_shutdown_broadcast_oneshot(arg);
-               tick_shutdown_broadcast(arg);
-               tick_shutdown(arg);
-               /*
-                * Unregister the clock event devices which were
-                * released from the users in the notify chain.
-                */
-               list_for_each_entry_safe(dev, tmp, &clockevents_released, list)
+       tick_shutdown_broadcast_oneshot(cpu);
+       tick_shutdown_broadcast(cpu);
+       tick_shutdown(cpu);
+       /*
+        * Unregister the clock event devices which were
+        * released from the users in the notify chain.
+        */
+       list_for_each_entry_safe(dev, tmp, &clockevents_released, list)
+               list_del(&dev->list);
+       /*
+        * Now check whether the CPU has left unused per cpu devices
+        */
+       list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) {
+               if (cpumask_test_cpu(cpu, dev->cpumask) &&
+                   cpumask_weight(dev->cpumask) == 1 &&
+                   !tick_is_broadcast_device(dev)) {
+                       BUG_ON(dev->state != CLOCK_EVT_STATE_DETACHED);
                        list_del(&dev->list);
-               /*
-                * Now check whether the CPU has left unused per cpu devices
-                */
-               cpu = *((int *)arg);
-               list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) {
-                       if (cpumask_test_cpu(cpu, dev->cpumask) &&
-                           cpumask_weight(dev->cpumask) == 1 &&
-                           !tick_is_broadcast_device(dev)) {
-                               BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
-                               list_del(&dev->list);
-                       }
                }
-               break;
-       default:
-               break;
        }
        raw_spin_unlock_irqrestore(&clockevents_lock, flags);
-       return ret;
 }
-EXPORT_SYMBOL_GPL(clockevents_notify);
+#endif
 
 #ifdef CONFIG_SYSFS
 struct bus_type clockevents_subsys = {
@@ -727,5 +794,3 @@ static int __init clockevents_init_sysfs(void)
 }
 device_initcall(clockevents_init_sysfs);
 #endif /* SYSFS */
-
-#endif /* GENERIC_CLOCK_EVENTS */
index 4892352f0e4989c561c5d16ba3b27c063082a8f6..15facb1b9c606c7a5fa5ea3500ea7dd4bf523477 100644 (file)
@@ -142,13 +142,6 @@ static void __clocksource_unstable(struct clocksource *cs)
                schedule_work(&watchdog_work);
 }
 
-static void clocksource_unstable(struct clocksource *cs, int64_t delta)
-{
-       printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
-              cs->name, delta);
-       __clocksource_unstable(cs);
-}
-
 /**
  * clocksource_mark_unstable - mark clocksource unstable via watchdog
  * @cs:                clocksource to be marked unstable
@@ -174,7 +167,7 @@ void clocksource_mark_unstable(struct clocksource *cs)
 static void clocksource_watchdog(unsigned long data)
 {
        struct clocksource *cs;
-       cycle_t csnow, wdnow, delta;
+       cycle_t csnow, wdnow, cslast, wdlast, delta;
        int64_t wd_nsec, cs_nsec;
        int next_cpu, reset_pending;
 
@@ -213,6 +206,8 @@ static void clocksource_watchdog(unsigned long data)
 
                delta = clocksource_delta(csnow, cs->cs_last, cs->mask);
                cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift);
+               wdlast = cs->wd_last; /* save these in case we print them */
+               cslast = cs->cs_last;
                cs->cs_last = csnow;
                cs->wd_last = wdnow;
 
@@ -221,7 +216,12 @@ static void clocksource_watchdog(unsigned long data)
 
                /* Check the deviation from the watchdog clocksource. */
                if ((abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD)) {
-                       clocksource_unstable(cs, cs_nsec - wd_nsec);
+                       pr_warn("timekeeping watchdog: Marking clocksource '%s' as unstable, because the skew is too large:\n", cs->name);
+                       pr_warn("       '%s' wd_now: %llx wd_last: %llx mask: %llx\n",
+                               watchdog->name, wdnow, wdlast, watchdog->mask);
+                       pr_warn("       '%s' cs_now: %llx cs_last: %llx mask: %llx\n",
+                               cs->name, csnow, cslast, cs->mask);
+                       __clocksource_unstable(cs);
                        continue;
                }
 
@@ -469,26 +469,25 @@ static u32 clocksource_max_adjustment(struct clocksource *cs)
  * @shift:     cycle to nanosecond divisor (power of two)
  * @maxadj:    maximum adjustment value to mult (~11%)
  * @mask:      bitmask for two's complement subtraction of non 64 bit counters
+ * @max_cyc:   maximum cycle value before potential overflow (does not include
+ *             any safety margin)
+ *
+ * NOTE: This function includes a safety margin of 50%, in other words, we
+ * return half the number of nanoseconds the hardware counter can technically
+ * cover. This is done so that we can potentially detect problems caused by
+ * delayed timers or bad hardware, which might result in time intervals that
+ * are larger then what the math used can handle without overflows.
  */
-u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask)
+u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask, u64 *max_cyc)
 {
        u64 max_nsecs, max_cycles;
 
        /*
         * Calculate the maximum number of cycles that we can pass to the
-        * cyc2ns function without overflowing a 64-bit signed result. The
-        * maximum number of cycles is equal to ULLONG_MAX/(mult+maxadj)
-        * which is equivalent to the below.
-        * max_cycles < (2^63)/(mult + maxadj)
-        * max_cycles < 2^(log2((2^63)/(mult + maxadj)))
-        * max_cycles < 2^(log2(2^63) - log2(mult + maxadj))
-        * max_cycles < 2^(63 - log2(mult + maxadj))
-        * max_cycles < 1 << (63 - log2(mult + maxadj))
-        * Please note that we add 1 to the result of the log2 to account for
-        * any rounding errors, ensure the above inequality is satisfied and
-        * no overflow will occur.
+        * cyc2ns() function without overflowing a 64-bit result.
         */
-       max_cycles = 1ULL << (63 - (ilog2(mult + maxadj) + 1));
+       max_cycles = ULLONG_MAX;
+       do_div(max_cycles, mult+maxadj);
 
        /*
         * The actual maximum number of cycles we can defer the clocksource is
@@ -499,27 +498,26 @@ u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask)
        max_cycles = min(max_cycles, mask);
        max_nsecs = clocksource_cyc2ns(max_cycles, mult - maxadj, shift);
 
+       /* return the max_cycles value as well if requested */
+       if (max_cyc)
+               *max_cyc = max_cycles;
+
+       /* Return 50% of the actual maximum, so we can detect bad values */
+       max_nsecs >>= 1;
+
        return max_nsecs;
 }
 
 /**
- * clocksource_max_deferment - Returns max time the clocksource can be deferred
- * @cs:         Pointer to clocksource
+ * clocksource_update_max_deferment - Updates the clocksource max_idle_ns & max_cycles
+ * @cs:         Pointer to clocksource to be updated
  *
  */
-static u64 clocksource_max_deferment(struct clocksource *cs)
+static inline void clocksource_update_max_deferment(struct clocksource *cs)
 {
-       u64 max_nsecs;
-
-       max_nsecs = clocks_calc_max_nsecs(cs->mult, cs->shift, cs->maxadj,
-                                         cs->mask);
-       /*
-        * To ensure that the clocksource does not wrap whilst we are idle,
-        * limit the time the clocksource can be deferred by 12.5%. Please
-        * note a margin of 12.5% is used because this can be computed with
-        * a shift, versus say 10% which would require division.
-        */
-       return max_nsecs - (max_nsecs >> 3);
+       cs->max_idle_ns = clocks_calc_max_nsecs(cs->mult, cs->shift,
+                                               cs->maxadj, cs->mask,
+                                               &cs->max_cycles);
 }
 
 #ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
@@ -648,7 +646,7 @@ static void clocksource_enqueue(struct clocksource *cs)
 }
 
 /**
- * __clocksource_updatefreq_scale - Used update clocksource with new freq
+ * __clocksource_update_freq_scale - Used update clocksource with new freq
  * @cs:                clocksource to be registered
  * @scale:     Scale factor multiplied against freq to get clocksource hz
  * @freq:      clocksource frequency (cycles per second) divided by scale
@@ -656,48 +654,64 @@ static void clocksource_enqueue(struct clocksource *cs)
  * This should only be called from the clocksource->enable() method.
  *
  * This *SHOULD NOT* be called directly! Please use the
- * clocksource_updatefreq_hz() or clocksource_updatefreq_khz helper functions.
+ * __clocksource_update_freq_hz() or __clocksource_update_freq_khz() helper
+ * functions.
  */
-void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq)
+void __clocksource_update_freq_scale(struct clocksource *cs, u32 scale, u32 freq)
 {
        u64 sec;
+
        /*
-        * Calc the maximum number of seconds which we can run before
-        * wrapping around. For clocksources which have a mask > 32bit
-        * we need to limit the max sleep time to have a good
-        * conversion precision. 10 minutes is still a reasonable
-        * amount. That results in a shift value of 24 for a
-        * clocksource with mask >= 40bit and f >= 4GHz. That maps to
-        * ~ 0.06ppm granularity for NTP. We apply the same 12.5%
-        * margin as we do in clocksource_max_deferment()
+        * Default clocksources are *special* and self-define their mult/shift.
+        * But, you're not special, so you should specify a freq value.
         */
-       sec = (cs->mask - (cs->mask >> 3));
-       do_div(sec, freq);
-       do_div(sec, scale);
-       if (!sec)
-               sec = 1;
-       else if (sec > 600 && cs->mask > UINT_MAX)
-               sec = 600;
-
-       clocks_calc_mult_shift(&cs->mult, &cs->shift, freq,
-                              NSEC_PER_SEC / scale, sec * scale);
-
+       if (freq) {
+               /*
+                * Calc the maximum number of seconds which we can run before
+                * wrapping around. For clocksources which have a mask > 32-bit
+                * we need to limit the max sleep time to have a good
+                * conversion precision. 10 minutes is still a reasonable
+                * amount. That results in a shift value of 24 for a
+                * clocksource with mask >= 40-bit and f >= 4GHz. That maps to
+                * ~ 0.06ppm granularity for NTP.
+                */
+               sec = cs->mask;
+               do_div(sec, freq);
+               do_div(sec, scale);
+               if (!sec)
+                       sec = 1;
+               else if (sec > 600 && cs->mask > UINT_MAX)
+                       sec = 600;
+
+               clocks_calc_mult_shift(&cs->mult, &cs->shift, freq,
+                                      NSEC_PER_SEC / scale, sec * scale);
+       }
        /*
-        * for clocksources that have large mults, to avoid overflow.
-        * Since mult may be adjusted by ntp, add an safety extra margin
-        *
+        * Ensure clocksources that have large 'mult' values don't overflow
+        * when adjusted.
         */
        cs->maxadj = clocksource_max_adjustment(cs);
-       while ((cs->mult + cs->maxadj < cs->mult)
-               || (cs->mult - cs->maxadj > cs->mult)) {
+       while (freq && ((cs->mult + cs->maxadj < cs->mult)
+               || (cs->mult - cs->maxadj > cs->mult))) {
                cs->mult >>= 1;
                cs->shift--;
                cs->maxadj = clocksource_max_adjustment(cs);
        }
 
-       cs->max_idle_ns = clocksource_max_deferment(cs);
+       /*
+        * Only warn for *special* clocksources that self-define
+        * their mult/shift values and don't specify a freq.
+        */
+       WARN_ONCE(cs->mult + cs->maxadj < cs->mult,
+               "timekeeping: Clocksource %s might overflow on 11%% adjustment\n",
+               cs->name);
+
+       clocksource_update_max_deferment(cs);
+
+       pr_info("clocksource %s: mask: 0x%llx max_cycles: 0x%llx, max_idle_ns: %lld ns\n",
+                       cs->name, cs->mask, cs->max_cycles, cs->max_idle_ns);
 }
-EXPORT_SYMBOL_GPL(__clocksource_updatefreq_scale);
+EXPORT_SYMBOL_GPL(__clocksource_update_freq_scale);
 
 /**
  * __clocksource_register_scale - Used to install new clocksources
@@ -714,7 +728,7 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq)
 {
 
        /* Initialize mult/shift and max_idle_ns */
-       __clocksource_updatefreq_scale(cs, scale, freq);
+       __clocksource_update_freq_scale(cs, scale, freq);
 
        /* Add clocksource to the clocksource list */
        mutex_lock(&clocksource_mutex);
@@ -726,33 +740,6 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq)
 }
 EXPORT_SYMBOL_GPL(__clocksource_register_scale);
 
-
-/**
- * clocksource_register - Used to install new clocksources
- * @cs:                clocksource to be registered
- *
- * Returns -EBUSY if registration fails, zero otherwise.
- */
-int clocksource_register(struct clocksource *cs)
-{
-       /* calculate max adjustment for given mult/shift */
-       cs->maxadj = clocksource_max_adjustment(cs);
-       WARN_ONCE(cs->mult + cs->maxadj < cs->mult,
-               "Clocksource %s might overflow on 11%% adjustment\n",
-               cs->name);
-
-       /* calculate max idle time permitted for this clocksource */
-       cs->max_idle_ns = clocksource_max_deferment(cs);
-
-       mutex_lock(&clocksource_mutex);
-       clocksource_enqueue(cs);
-       clocksource_enqueue_watchdog(cs);
-       clocksource_select();
-       mutex_unlock(&clocksource_mutex);
-       return 0;
-}
-EXPORT_SYMBOL(clocksource_register);
-
 static void __clocksource_change_rating(struct clocksource *cs, int rating)
 {
        list_del(&cs->list);
index bee0c1f780911a97a4598b81089c9bc4d807d037..76d4bd962b19b3bab345460676954ef6f7c14568 100644 (file)
@@ -54,7 +54,7 @@
 
 #include <trace/events/timer.h>
 
-#include "timekeeping.h"
+#include "tick-internal.h"
 
 /*
  * The timer bases:
@@ -1707,17 +1707,10 @@ static int hrtimer_cpu_notify(struct notifier_block *self,
                break;
 
 #ifdef CONFIG_HOTPLUG_CPU
-       case CPU_DYING:
-       case CPU_DYING_FROZEN:
-               clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DYING, &scpu);
-               break;
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
-       {
-               clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DEAD, &scpu);
                migrate_hrtimers(scpu);
                break;
-       }
 #endif
 
        default:
index a6a5bf53e86d25575f90518399407a4fb65a85ed..347fecf86a3fb2242e0a88b63975424f0293dde7 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-#include "tick-internal.h"
+#include "timekeeping.h"
 
 /* The Jiffies based clocksource is the lowest common
  * denominator clock source which should function on
@@ -71,6 +71,7 @@ static struct clocksource clocksource_jiffies = {
        .mask           = 0xffffffff, /*32bits*/
        .mult           = NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */
        .shift          = JIFFIES_SHIFT,
+       .max_cycles     = 10,
 };
 
 __cacheline_aligned_in_smp DEFINE_SEQLOCK(jiffies_lock);
@@ -94,7 +95,7 @@ EXPORT_SYMBOL(jiffies);
 
 static int __init init_jiffies_clocksource(void)
 {
-       return clocksource_register(&clocksource_jiffies);
+       return __clocksource_register(&clocksource_jiffies);
 }
 
 core_initcall(init_jiffies_clocksource);
@@ -130,6 +131,6 @@ int register_refined_jiffies(long cycles_per_second)
 
        refined_jiffies.mult = ((u32)nsec_per_tick) << JIFFIES_SHIFT;
 
-       clocksource_register(&refined_jiffies);
+       __clocksource_register(&refined_jiffies);
        return 0;
 }
index 0f60b08a4f073e9246ced1dc3b5de5f50efd7cf4..7a681003001c0ee75631e2c5c56e528ec0ea98df 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/rtc.h>
 
-#include "tick-internal.h"
 #include "ntp_internal.h"
 
 /*
@@ -459,6 +458,16 @@ out:
        return leap;
 }
 
+#ifdef CONFIG_GENERIC_CMOS_UPDATE
+int __weak update_persistent_clock64(struct timespec64 now64)
+{
+       struct timespec now;
+
+       now = timespec64_to_timespec(now64);
+       return update_persistent_clock(now);
+}
+#endif
+
 #if defined(CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC)
 static void sync_cmos_clock(struct work_struct *work);
 
@@ -494,8 +503,9 @@ static void sync_cmos_clock(struct work_struct *work)
                if (persistent_clock_is_local)
                        adjust.tv_sec -= (sys_tz.tz_minuteswest * 60);
 #ifdef CONFIG_GENERIC_CMOS_UPDATE
-               fail = update_persistent_clock(timespec64_to_timespec(adjust));
+               fail = update_persistent_clock64(adjust);
 #endif
+
 #ifdef CONFIG_RTC_SYSTOHC
                if (fail == -ENODEV)
                        fail = rtc_set_ntp_time(adjust);
index 01d2d15aa66233dc62db43f8e988a0f5519a729b..a26036d37a3895f163a20abdde5c6361d0110cf1 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * sched_clock.c: support for extending counters to full 64-bit ns counter
+ * sched_clock.c: Generic sched_clock() support, to extend low level
+ *                hardware time counters to full 64-bit ns values.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #include <linux/seqlock.h>
 #include <linux/bitops.h>
 
-struct clock_data {
-       ktime_t wrap_kt;
+/**
+ * struct clock_read_data - data required to read from sched_clock()
+ *
+ * @epoch_ns:          sched_clock() value at last update
+ * @epoch_cyc:         Clock cycle value at last update.
+ * @sched_clock_mask:   Bitmask for two's complement subtraction of non 64bit
+ *                     clocks.
+ * @read_sched_clock:  Current clock source (or dummy source when suspended).
+ * @mult:              Multipler for scaled math conversion.
+ * @shift:             Shift value for scaled math conversion.
+ *
+ * Care must be taken when updating this structure; it is read by
+ * some very hot code paths. It occupies <=40 bytes and, when combined
+ * with the seqcount used to synchronize access, comfortably fits into
+ * a 64 byte cache line.
+ */
+struct clock_read_data {
        u64 epoch_ns;
        u64 epoch_cyc;
-       seqcount_t seq;
-       unsigned long rate;
+       u64 sched_clock_mask;
+       u64 (*read_sched_clock)(void);
        u32 mult;
        u32 shift;
-       bool suspended;
+};
+
+/**
+ * struct clock_data - all data needed for sched_clock() (including
+ *                     registration of a new clock source)
+ *
+ * @seq:               Sequence counter for protecting updates. The lowest
+ *                     bit is the index for @read_data.
+ * @read_data:         Data required to read from sched_clock.
+ * @wrap_kt:           Duration for which clock can run before wrapping.
+ * @rate:              Tick rate of the registered clock.
+ * @actual_read_sched_clock: Registered hardware level clock read function.
+ *
+ * The ordering of this structure has been chosen to optimize cache
+ * performance. In particular 'seq' and 'read_data[0]' (combined) should fit
+ * into a single 64-byte cache line.
+ */
+struct clock_data {
+       seqcount_t              seq;
+       struct clock_read_data  read_data[2];
+       ktime_t                 wrap_kt;
+       unsigned long           rate;
+
+       u64 (*actual_read_sched_clock)(void);
 };
 
 static struct hrtimer sched_clock_timer;
@@ -34,12 +73,6 @@ static int irqtime = -1;
 
 core_param(irqtime, irqtime, int, 0400);
 
-static struct clock_data cd = {
-       .mult   = NSEC_PER_SEC / HZ,
-};
-
-static u64 __read_mostly sched_clock_mask;
-
 static u64 notrace jiffy_sched_clock_read(void)
 {
        /*
@@ -49,7 +82,11 @@ static u64 notrace jiffy_sched_clock_read(void)
        return (u64)(jiffies - INITIAL_JIFFIES);
 }
 
-static u64 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read;
+static struct clock_data cd ____cacheline_aligned = {
+       .read_data[0] = { .mult = NSEC_PER_SEC / HZ,
+                         .read_sched_clock = jiffy_sched_clock_read, },
+       .actual_read_sched_clock = jiffy_sched_clock_read,
+};
 
 static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
 {
@@ -58,111 +95,136 @@ static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
 
 unsigned long long notrace sched_clock(void)
 {
-       u64 epoch_ns;
-       u64 epoch_cyc;
-       u64 cyc;
+       u64 cyc, res;
        unsigned long seq;
-
-       if (cd.suspended)
-               return cd.epoch_ns;
+       struct clock_read_data *rd;
 
        do {
-               seq = raw_read_seqcount_begin(&cd.seq);
-               epoch_cyc = cd.epoch_cyc;
-               epoch_ns = cd.epoch_ns;
+               seq = raw_read_seqcount(&cd.seq);
+               rd = cd.read_data + (seq & 1);
+
+               cyc = (rd->read_sched_clock() - rd->epoch_cyc) &
+                     rd->sched_clock_mask;
+               res = rd->epoch_ns + cyc_to_ns(cyc, rd->mult, rd->shift);
        } while (read_seqcount_retry(&cd.seq, seq));
 
-       cyc = read_sched_clock();
-       cyc = (cyc - epoch_cyc) & sched_clock_mask;
-       return epoch_ns + cyc_to_ns(cyc, cd.mult, cd.shift);
+       return res;
+}
+
+/*
+ * Updating the data required to read the clock.
+ *
+ * sched_clock() will never observe mis-matched data even if called from
+ * an NMI. We do this by maintaining an odd/even copy of the data and
+ * steering sched_clock() to one or the other using a sequence counter.
+ * In order to preserve the data cache profile of sched_clock() as much
+ * as possible the system reverts back to the even copy when the update
+ * completes; the odd copy is used *only* during an update.
+ */
+static void update_clock_read_data(struct clock_read_data *rd)
+{
+       /* update the backup (odd) copy with the new data */
+       cd.read_data[1] = *rd;
+
+       /* steer readers towards the odd copy */
+       raw_write_seqcount_latch(&cd.seq);
+
+       /* now its safe for us to update the normal (even) copy */
+       cd.read_data[0] = *rd;
+
+       /* switch readers back to the even copy */
+       raw_write_seqcount_latch(&cd.seq);
 }
 
 /*
- * Atomically update the sched_clock epoch.
+ * Atomically update the sched_clock() epoch.
  */
-static void notrace update_sched_clock(void)
+static void update_sched_clock(void)
 {
-       unsigned long flags;
        u64 cyc;
        u64 ns;
+       struct clock_read_data rd;
+
+       rd = cd.read_data[0];
+
+       cyc = cd.actual_read_sched_clock();
+       ns = rd.epoch_ns + cyc_to_ns((cyc - rd.epoch_cyc) & rd.sched_clock_mask, rd.mult, rd.shift);
+
+       rd.epoch_ns = ns;
+       rd.epoch_cyc = cyc;
 
-       cyc = read_sched_clock();
-       ns = cd.epoch_ns +
-               cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask,
-                         cd.mult, cd.shift);
-
-       raw_local_irq_save(flags);
-       raw_write_seqcount_begin(&cd.seq);
-       cd.epoch_ns = ns;
-       cd.epoch_cyc = cyc;
-       raw_write_seqcount_end(&cd.seq);
-       raw_local_irq_restore(flags);
+       update_clock_read_data(&rd);
 }
 
 static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt)
 {
        update_sched_clock();
        hrtimer_forward_now(hrt, cd.wrap_kt);
+
        return HRTIMER_RESTART;
 }
 
-void __init sched_clock_register(u64 (*read)(void), int bits,
-                                unsigned long rate)
+void __init
+sched_clock_register(u64 (*read)(void), int bits, unsigned long rate)
 {
        u64 res, wrap, new_mask, new_epoch, cyc, ns;
        u32 new_mult, new_shift;
-       ktime_t new_wrap_kt;
        unsigned long r;
        char r_unit;
+       struct clock_read_data rd;
 
        if (cd.rate > rate)
                return;
 
        WARN_ON(!irqs_disabled());
 
-       /* calculate the mult/shift to convert counter ticks to ns. */
+       /* Calculate the mult/shift to convert counter ticks to ns. */
        clocks_calc_mult_shift(&new_mult, &new_shift, rate, NSEC_PER_SEC, 3600);
 
        new_mask = CLOCKSOURCE_MASK(bits);
+       cd.rate = rate;
+
+       /* Calculate how many nanosecs until we risk wrapping */
+       wrap = clocks_calc_max_nsecs(new_mult, new_shift, 0, new_mask, NULL);
+       cd.wrap_kt = ns_to_ktime(wrap);
 
-       /* calculate how many ns until we wrap */
-       wrap = clocks_calc_max_nsecs(new_mult, new_shift, 0, new_mask);
-       new_wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
+       rd = cd.read_data[0];
 
-       /* update epoch for new counter and update epoch_ns from old counter*/
+       /* Update epoch for new counter and update 'epoch_ns' from old counter*/
        new_epoch = read();
-       cyc = read_sched_clock();
-       ns = cd.epoch_ns + cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask,
-                         cd.mult, cd.shift);
+       cyc = cd.actual_read_sched_clock();
+       ns = rd.epoch_ns + cyc_to_ns((cyc - rd.epoch_cyc) & rd.sched_clock_mask, rd.mult, rd.shift);
+       cd.actual_read_sched_clock = read;
 
-       raw_write_seqcount_begin(&cd.seq);
-       read_sched_clock = read;
-       sched_clock_mask = new_mask;
-       cd.rate = rate;
-       cd.wrap_kt = new_wrap_kt;
-       cd.mult = new_mult;
-       cd.shift = new_shift;
-       cd.epoch_cyc = new_epoch;
-       cd.epoch_ns = ns;
-       raw_write_seqcount_end(&cd.seq);
+       rd.read_sched_clock     = read;
+       rd.sched_clock_mask     = new_mask;
+       rd.mult                 = new_mult;
+       rd.shift                = new_shift;
+       rd.epoch_cyc            = new_epoch;
+       rd.epoch_ns             = ns;
+
+       update_clock_read_data(&rd);
 
        r = rate;
        if (r >= 4000000) {
                r /= 1000000;
                r_unit = 'M';
-       } else if (r >= 1000) {
-               r /= 1000;
-               r_unit = 'k';
-       } else
-               r_unit = ' ';
-
-       /* calculate the ns resolution of this counter */
+       } else {
+               if (r >= 1000) {
+                       r /= 1000;
+                       r_unit = 'k';
+               } else {
+                       r_unit = ' ';
+               }
+       }
+
+       /* Calculate the ns resolution of this counter */
        res = cyc_to_ns(1ULL, new_mult, new_shift);
 
        pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n",
                bits, r, r_unit, res, wrap);
 
-       /* Enable IRQ time accounting if we have a fast enough sched_clock */
+       /* Enable IRQ time accounting if we have a fast enough sched_clock() */
        if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
                enable_sched_clock_irqtime();
 
@@ -172,10 +234,10 @@ void __init sched_clock_register(u64 (*read)(void), int bits,
 void __init sched_clock_postinit(void)
 {
        /*
-        * If no sched_clock function has been provided at that point,
+        * If no sched_clock() function has been provided at that point,
         * make it the final one one.
         */
-       if (read_sched_clock == jiffy_sched_clock_read)
+       if (cd.actual_read_sched_clock == jiffy_sched_clock_read)
                sched_clock_register(jiffy_sched_clock_read, BITS_PER_LONG, HZ);
 
        update_sched_clock();
@@ -189,29 +251,53 @@ void __init sched_clock_postinit(void)
        hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL);
 }
 
+/*
+ * Clock read function for use when the clock is suspended.
+ *
+ * This function makes it appear to sched_clock() as if the clock
+ * stopped counting at its last update.
+ *
+ * This function must only be called from the critical
+ * section in sched_clock(). It relies on the read_seqcount_retry()
+ * at the end of the critical section to be sure we observe the
+ * correct copy of 'epoch_cyc'.
+ */
+static u64 notrace suspended_sched_clock_read(void)
+{
+       unsigned long seq = raw_read_seqcount(&cd.seq);
+
+       return cd.read_data[seq & 1].epoch_cyc;
+}
+
 static int sched_clock_suspend(void)
 {
+       struct clock_read_data *rd = &cd.read_data[0];
+
        update_sched_clock();
        hrtimer_cancel(&sched_clock_timer);
-       cd.suspended = true;
+       rd->read_sched_clock = suspended_sched_clock_read;
+
        return 0;
 }
 
 static void sched_clock_resume(void)
 {
-       cd.epoch_cyc = read_sched_clock();
+       struct clock_read_data *rd = &cd.read_data[0];
+
+       rd->epoch_cyc = cd.actual_read_sched_clock();
        hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL);
-       cd.suspended = false;
+       rd->read_sched_clock = cd.actual_read_sched_clock;
 }
 
 static struct syscore_ops sched_clock_ops = {
-       .suspend = sched_clock_suspend,
-       .resume = sched_clock_resume,
+       .suspend        = sched_clock_suspend,
+       .resume         = sched_clock_resume,
 };
 
 static int __init sched_clock_syscore_init(void)
 {
        register_syscore_ops(&sched_clock_ops);
+
        return 0;
 }
 device_initcall(sched_clock_syscore_init);
index 066f0ec05e487396315356df0ea04c8563ffa390..7e8ca4f448a88c5ad5708106bbd889e22715b3ad 100644 (file)
@@ -33,12 +33,14 @@ static cpumask_var_t tick_broadcast_mask;
 static cpumask_var_t tick_broadcast_on;
 static cpumask_var_t tmpmask;
 static DEFINE_RAW_SPINLOCK(tick_broadcast_lock);
-static int tick_broadcast_force;
+static int tick_broadcast_forced;
 
 #ifdef CONFIG_TICK_ONESHOT
 static void tick_broadcast_clear_oneshot(int cpu);
+static void tick_resume_broadcast_oneshot(struct clock_event_device *bc);
 #else
 static inline void tick_broadcast_clear_oneshot(int cpu) { }
+static inline void tick_resume_broadcast_oneshot(struct clock_event_device *bc) { }
 #endif
 
 /*
@@ -303,7 +305,7 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
        /*
         * The device is in periodic mode. No reprogramming necessary:
         */
-       if (dev->mode == CLOCK_EVT_MODE_PERIODIC)
+       if (dev->state == CLOCK_EVT_STATE_PERIODIC)
                goto unlock;
 
        /*
@@ -324,49 +326,54 @@ unlock:
        raw_spin_unlock(&tick_broadcast_lock);
 }
 
-/*
- * Powerstate information: The system enters/leaves a state, where
- * affected devices might stop
+/**
+ * tick_broadcast_control - Enable/disable or force broadcast mode
+ * @mode:      The selected broadcast mode
+ *
+ * Called when the system enters a state where affected tick devices
+ * might stop. Note: TICK_BROADCAST_FORCE cannot be undone.
+ *
+ * Called with interrupts disabled, so clockevents_lock is not
+ * required here because the local clock event device cannot go away
+ * under us.
  */
-static void tick_do_broadcast_on_off(unsigned long *reason)
+void tick_broadcast_control(enum tick_broadcast_mode mode)
 {
        struct clock_event_device *bc, *dev;
        struct tick_device *td;
-       unsigned long flags;
        int cpu, bc_stopped;
 
-       raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
-
-       cpu = smp_processor_id();
-       td = &per_cpu(tick_cpu_device, cpu);
+       td = this_cpu_ptr(&tick_cpu_device);
        dev = td->evtdev;
-       bc = tick_broadcast_device.evtdev;
 
        /*
         * Is the device not affected by the powerstate ?
         */
        if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP))
-               goto out;
+               return;
 
        if (!tick_device_is_functional(dev))
-               goto out;
+               return;
 
+       raw_spin_lock(&tick_broadcast_lock);
+       cpu = smp_processor_id();
+       bc = tick_broadcast_device.evtdev;
        bc_stopped = cpumask_empty(tick_broadcast_mask);
 
-       switch (*reason) {
-       case CLOCK_EVT_NOTIFY_BROADCAST_ON:
-       case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
+       switch (mode) {
+       case TICK_BROADCAST_FORCE:
+               tick_broadcast_forced = 1;
+       case TICK_BROADCAST_ON:
                cpumask_set_cpu(cpu, tick_broadcast_on);
                if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_mask)) {
                        if (tick_broadcast_device.mode ==
                            TICKDEV_MODE_PERIODIC)
                                clockevents_shutdown(dev);
                }
-               if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE)
-                       tick_broadcast_force = 1;
                break;
-       case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
-               if (tick_broadcast_force)
+
+       case TICK_BROADCAST_OFF:
+               if (tick_broadcast_forced)
                        break;
                cpumask_clear_cpu(cpu, tick_broadcast_on);
                if (!tick_device_is_functional(dev))
@@ -388,22 +395,9 @@ static void tick_do_broadcast_on_off(unsigned long *reason)
                else
                        tick_broadcast_setup_oneshot(bc);
        }
-out:
-       raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
-}
-
-/*
- * Powerstate information: The system enters/leaves a state, where
- * affected devices might stop.
- */
-void tick_broadcast_on_off(unsigned long reason, int *oncpu)
-{
-       if (!cpumask_test_cpu(*oncpu, cpu_online_mask))
-               printk(KERN_ERR "tick-broadcast: ignoring broadcast for "
-                      "offline CPU #%d\n", *oncpu);
-       else
-               tick_do_broadcast_on_off(&reason);
+       raw_spin_unlock(&tick_broadcast_lock);
 }
+EXPORT_SYMBOL_GPL(tick_broadcast_control);
 
 /*
  * Set the periodic handler depending on broadcast on/off
@@ -416,14 +410,14 @@ void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast)
                dev->event_handler = tick_handle_periodic_broadcast;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
 /*
  * Remove a CPU from broadcasting
  */
-void tick_shutdown_broadcast(unsigned int *cpup)
+void tick_shutdown_broadcast(unsigned int cpu)
 {
        struct clock_event_device *bc;
        unsigned long flags;
-       unsigned int cpu = *cpup;
 
        raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
@@ -438,6 +432,7 @@ void tick_shutdown_broadcast(unsigned int *cpup)
 
        raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
+#endif
 
 void tick_suspend_broadcast(void)
 {
@@ -453,38 +448,48 @@ void tick_suspend_broadcast(void)
        raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 
-int tick_resume_broadcast(void)
+/*
+ * This is called from tick_resume_local() on a resuming CPU. That's
+ * called from the core resume function, tick_unfreeze() and the magic XEN
+ * resume hackery.
+ *
+ * In none of these cases the broadcast device mode can change and the
+ * bit of the resuming CPU in the broadcast mask is safe as well.
+ */
+bool tick_resume_check_broadcast(void)
+{
+       if (tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT)
+               return false;
+       else
+               return cpumask_test_cpu(smp_processor_id(), tick_broadcast_mask);
+}
+
+void tick_resume_broadcast(void)
 {
        struct clock_event_device *bc;
        unsigned long flags;
-       int broadcast = 0;
 
        raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
        bc = tick_broadcast_device.evtdev;
 
        if (bc) {
-               clockevents_set_mode(bc, CLOCK_EVT_MODE_RESUME);
+               clockevents_tick_resume(bc);
 
                switch (tick_broadcast_device.mode) {
                case TICKDEV_MODE_PERIODIC:
                        if (!cpumask_empty(tick_broadcast_mask))
                                tick_broadcast_start_periodic(bc);
-                       broadcast = cpumask_test_cpu(smp_processor_id(),
-                                                    tick_broadcast_mask);
                        break;
                case TICKDEV_MODE_ONESHOT:
                        if (!cpumask_empty(tick_broadcast_mask))
-                               broadcast = tick_resume_broadcast_oneshot(bc);
+                               tick_resume_broadcast_oneshot(bc);
                        break;
                }
        }
        raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
-
-       return broadcast;
 }
 
-
 #ifdef CONFIG_TICK_ONESHOT
 
 static cpumask_var_t tick_broadcast_oneshot_mask;
@@ -532,8 +537,8 @@ static int tick_broadcast_set_event(struct clock_event_device *bc, int cpu,
 {
        int ret;
 
-       if (bc->mode != CLOCK_EVT_MODE_ONESHOT)
-               clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+       if (bc->state != CLOCK_EVT_STATE_ONESHOT)
+               clockevents_set_state(bc, CLOCK_EVT_STATE_ONESHOT);
 
        ret = clockevents_program_event(bc, expires, force);
        if (!ret)
@@ -541,10 +546,9 @@ static int tick_broadcast_set_event(struct clock_event_device *bc, int cpu,
        return ret;
 }
 
-int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
+static void tick_resume_broadcast_oneshot(struct clock_event_device *bc)
 {
-       clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
-       return 0;
+       clockevents_set_state(bc, CLOCK_EVT_STATE_ONESHOT);
 }
 
 /*
@@ -562,8 +566,8 @@ void tick_check_oneshot_broadcast_this_cpu(void)
                 * switched over, leave the device alone.
                 */
                if (td->mode == TICKDEV_MODE_ONESHOT) {
-                       clockevents_set_mode(td->evtdev,
-                                            CLOCK_EVT_MODE_ONESHOT);
+                       clockevents_set_state(td->evtdev,
+                                             CLOCK_EVT_STATE_ONESHOT);
                }
        }
 }
@@ -666,31 +670,26 @@ static void broadcast_shutdown_local(struct clock_event_device *bc,
                if (dev->next_event.tv64 < bc->next_event.tv64)
                        return;
        }
-       clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
+       clockevents_set_state(dev, CLOCK_EVT_STATE_SHUTDOWN);
 }
 
-static void broadcast_move_bc(int deadcpu)
-{
-       struct clock_event_device *bc = tick_broadcast_device.evtdev;
-
-       if (!bc || !broadcast_needs_cpu(bc, deadcpu))
-               return;
-       /* This moves the broadcast assignment to this cpu */
-       clockevents_program_event(bc, bc->next_event, 1);
-}
-
-/*
- * Powerstate information: The system enters/leaves a state, where
- * affected devices might stop
+/**
+ * tick_broadcast_oneshot_control - Enter/exit broadcast oneshot mode
+ * @state:     The target state (enter/exit)
+ *
+ * The system enters/leaves a state, where affected devices might stop
  * Returns 0 on success, -EBUSY if the cpu is used to broadcast wakeups.
+ *
+ * Called with interrupts disabled, so clockevents_lock is not
+ * required here because the local clock event device cannot go away
+ * under us.
  */
-int tick_broadcast_oneshot_control(unsigned long reason)
+int tick_broadcast_oneshot_control(enum tick_broadcast_state state)
 {
        struct clock_event_device *bc, *dev;
        struct tick_device *td;
-       unsigned long flags;
-       ktime_t now;
        int cpu, ret = 0;
+       ktime_t now;
 
        /*
         * Periodic mode does not care about the enter/exit of power
@@ -703,17 +702,17 @@ int tick_broadcast_oneshot_control(unsigned long reason)
         * We are called with preemtion disabled from the depth of the
         * idle code, so we can't be moved away.
         */
-       cpu = smp_processor_id();
-       td = &per_cpu(tick_cpu_device, cpu);
+       td = this_cpu_ptr(&tick_cpu_device);
        dev = td->evtdev;
 
        if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
                return 0;
 
+       raw_spin_lock(&tick_broadcast_lock);
        bc = tick_broadcast_device.evtdev;
+       cpu = smp_processor_id();
 
-       raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
-       if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
+       if (state == TICK_BROADCAST_ENTER) {
                if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_oneshot_mask)) {
                        WARN_ON_ONCE(cpumask_test_cpu(cpu, tick_broadcast_pending_mask));
                        broadcast_shutdown_local(bc, dev);
@@ -741,7 +740,7 @@ int tick_broadcast_oneshot_control(unsigned long reason)
                        cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask);
        } else {
                if (cpumask_test_and_clear_cpu(cpu, tick_broadcast_oneshot_mask)) {
-                       clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
+                       clockevents_set_state(dev, CLOCK_EVT_STATE_ONESHOT);
                        /*
                         * The cpu which was handling the broadcast
                         * timer marked this cpu in the broadcast
@@ -805,9 +804,10 @@ int tick_broadcast_oneshot_control(unsigned long reason)
                }
        }
 out:
-       raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+       raw_spin_unlock(&tick_broadcast_lock);
        return ret;
 }
+EXPORT_SYMBOL_GPL(tick_broadcast_oneshot_control);
 
 /*
  * Reset the one shot broadcast for a cpu
@@ -842,7 +842,7 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 
        /* Set it up only once ! */
        if (bc->event_handler != tick_handle_oneshot_broadcast) {
-               int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
+               int was_periodic = bc->state == CLOCK_EVT_STATE_PERIODIC;
 
                bc->event_handler = tick_handle_oneshot_broadcast;
 
@@ -858,7 +858,7 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
                           tick_broadcast_oneshot_mask, tmpmask);
 
                if (was_periodic && !cpumask_empty(tmpmask)) {
-                       clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+                       clockevents_set_state(bc, CLOCK_EVT_STATE_ONESHOT);
                        tick_broadcast_init_next_event(tmpmask,
                                                       tick_next_period);
                        tick_broadcast_set_event(bc, cpu, tick_next_period, 1);
@@ -894,14 +894,28 @@ void tick_broadcast_switch_to_oneshot(void)
        raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+void hotplug_cpu__broadcast_tick_pull(int deadcpu)
+{
+       struct clock_event_device *bc;
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
+       bc = tick_broadcast_device.evtdev;
+
+       if (bc && broadcast_needs_cpu(bc, deadcpu)) {
+               /* This moves the broadcast assignment to this CPU: */
+               clockevents_program_event(bc, bc->next_event, 1);
+       }
+       raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+}
 
 /*
  * Remove a dead CPU from broadcasting
  */
-void tick_shutdown_broadcast_oneshot(unsigned int *cpup)
+void tick_shutdown_broadcast_oneshot(unsigned int cpu)
 {
        unsigned long flags;
-       unsigned int cpu = *cpup;
 
        raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
@@ -913,10 +927,9 @@ void tick_shutdown_broadcast_oneshot(unsigned int *cpup)
        cpumask_clear_cpu(cpu, tick_broadcast_pending_mask);
        cpumask_clear_cpu(cpu, tick_broadcast_force_mask);
 
-       broadcast_move_bc(cpu);
-
        raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
+#endif
 
 /*
  * Check, whether the broadcast device is in one shot mode
index f7c515595b42b2bf9794a8f3f4ee1f9a2c17df89..3ae6afa1eb98e71cc82272cd0a79a25101eff429 100644 (file)
@@ -102,7 +102,7 @@ void tick_handle_periodic(struct clock_event_device *dev)
 
        tick_periodic(cpu);
 
-       if (dev->mode != CLOCK_EVT_MODE_ONESHOT)
+       if (dev->state != CLOCK_EVT_STATE_ONESHOT)
                return;
        for (;;) {
                /*
@@ -140,7 +140,7 @@ void tick_setup_periodic(struct clock_event_device *dev, int broadcast)
 
        if ((dev->features & CLOCK_EVT_FEAT_PERIODIC) &&
            !tick_broadcast_oneshot_active()) {
-               clockevents_set_mode(dev, CLOCK_EVT_MODE_PERIODIC);
+               clockevents_set_state(dev, CLOCK_EVT_STATE_PERIODIC);
        } else {
                unsigned long seq;
                ktime_t next;
@@ -150,7 +150,7 @@ void tick_setup_periodic(struct clock_event_device *dev, int broadcast)
                        next = tick_next_period;
                } while (read_seqretry(&jiffies_lock, seq));
 
-               clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
+               clockevents_set_state(dev, CLOCK_EVT_STATE_ONESHOT);
 
                for (;;) {
                        if (!clockevents_program_event(dev, next, false))
@@ -332,14 +332,16 @@ out_bc:
        tick_install_broadcast_device(newdev);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
 /*
  * Transfer the do_timer job away from a dying cpu.
  *
- * Called with interrupts disabled.
+ * Called with interrupts disabled. Not locking required. If
+ * tick_do_timer_cpu is owned by this cpu, nothing can change it.
  */
-void tick_handover_do_timer(int *cpup)
+void tick_handover_do_timer(void)
 {
-       if (*cpup == tick_do_timer_cpu) {
+       if (tick_do_timer_cpu == smp_processor_id()) {
                int cpu = cpumask_first(cpu_online_mask);
 
                tick_do_timer_cpu = (cpu < nr_cpu_ids) ? cpu :
@@ -354,9 +356,9 @@ void tick_handover_do_timer(int *cpup)
  * access the hardware device itself.
  * We just set the mode and remove it from the lists.
  */
-void tick_shutdown(unsigned int *cpup)
+void tick_shutdown(unsigned int cpu)
 {
-       struct tick_device *td = &per_cpu(tick_cpu_device, *cpup);
+       struct tick_device *td = &per_cpu(tick_cpu_device, cpu);
        struct clock_event_device *dev = td->evtdev;
 
        td->mode = TICKDEV_MODE_PERIODIC;
@@ -365,27 +367,42 @@ void tick_shutdown(unsigned int *cpup)
                 * Prevent that the clock events layer tries to call
                 * the set mode function!
                 */
+               dev->state = CLOCK_EVT_STATE_DETACHED;
                dev->mode = CLOCK_EVT_MODE_UNUSED;
                clockevents_exchange_device(dev, NULL);
                dev->event_handler = clockevents_handle_noop;
                td->evtdev = NULL;
        }
 }
+#endif
 
-void tick_suspend(void)
+/**
+ * tick_suspend_local - Suspend the local tick device
+ *
+ * Called from the local cpu for freeze with interrupts disabled.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
+void tick_suspend_local(void)
 {
        struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
 
        clockevents_shutdown(td->evtdev);
 }
 
-void tick_resume(void)
+/**
+ * tick_resume_local - Resume the local tick device
+ *
+ * Called from the local CPU for unfreeze or XEN resume magic.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
+void tick_resume_local(void)
 {
        struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
-       int broadcast = tick_resume_broadcast();
-
-       clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME);
+       bool broadcast = tick_resume_check_broadcast();
 
+       clockevents_tick_resume(td->evtdev);
        if (!broadcast) {
                if (td->mode == TICKDEV_MODE_PERIODIC)
                        tick_setup_periodic(td->evtdev, 0);
@@ -394,6 +411,35 @@ void tick_resume(void)
        }
 }
 
+/**
+ * tick_suspend - Suspend the tick and the broadcast device
+ *
+ * Called from syscore_suspend() via timekeeping_suspend with only one
+ * CPU online and interrupts disabled or from tick_unfreeze() under
+ * tick_freeze_lock.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
+void tick_suspend(void)
+{
+       tick_suspend_local();
+       tick_suspend_broadcast();
+}
+
+/**
+ * tick_resume - Resume the tick and the broadcast device
+ *
+ * Called from syscore_resume() via timekeeping_resume with only one
+ * CPU online and interrupts disabled.
+ *
+ * No locks required. Nothing can change the per cpu device.
+ */
+void tick_resume(void)
+{
+       tick_resume_broadcast();
+       tick_resume_local();
+}
+
 static DEFINE_RAW_SPINLOCK(tick_freeze_lock);
 static unsigned int tick_freeze_depth;
 
@@ -411,12 +457,10 @@ void tick_freeze(void)
        raw_spin_lock(&tick_freeze_lock);
 
        tick_freeze_depth++;
-       if (tick_freeze_depth == num_online_cpus()) {
+       if (tick_freeze_depth == num_online_cpus())
                timekeeping_suspend();
-       } else {
-               tick_suspend();
-               tick_suspend_broadcast();
-       }
+       else
+               tick_suspend_local();
 
        raw_spin_unlock(&tick_freeze_lock);
 }
@@ -437,7 +481,7 @@ void tick_unfreeze(void)
        if (tick_freeze_depth == num_online_cpus())
                timekeeping_resume();
        else
-               tick_resume();
+               tick_resume_local();
 
        tick_freeze_depth--;
 
index 366aeb4f2c6696ee6239e501ea4904f3812cd44c..b64fdd8054c56b042784fdce988ebad64f2ea803 100644 (file)
@@ -5,15 +5,12 @@
 #include <linux/tick.h>
 
 #include "timekeeping.h"
+#include "tick-sched.h"
 
-extern seqlock_t jiffies_lock;
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
 
-#define CS_NAME_LEN    32
-
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
-
-#define TICK_DO_TIMER_NONE     -1
-#define TICK_DO_TIMER_BOOT     -2
+# define TICK_DO_TIMER_NONE    -1
+# define TICK_DO_TIMER_BOOT    -2
 
 DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
 extern ktime_t tick_next_period;
@@ -23,21 +20,72 @@ extern int tick_do_timer_cpu __read_mostly;
 extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast);
 extern void tick_handle_periodic(struct clock_event_device *dev);
 extern void tick_check_new_device(struct clock_event_device *dev);
-extern void tick_handover_do_timer(int *cpup);
-extern void tick_shutdown(unsigned int *cpup);
+extern void tick_shutdown(unsigned int cpu);
 extern void tick_suspend(void);
 extern void tick_resume(void);
 extern bool tick_check_replacement(struct clock_event_device *curdev,
                                   struct clock_event_device *newdev);
 extern void tick_install_replacement(struct clock_event_device *dev);
+extern int tick_is_oneshot_available(void);
+extern struct tick_device *tick_get_device(int cpu);
 
-extern void clockevents_shutdown(struct clock_event_device *dev);
+extern int clockevents_tick_resume(struct clock_event_device *dev);
+/* Check, if the device is functional or a dummy for broadcast */
+static inline int tick_device_is_functional(struct clock_event_device *dev)
+{
+       return !(dev->features & CLOCK_EVT_FEAT_DUMMY);
+}
 
+extern void clockevents_shutdown(struct clock_event_device *dev);
+extern void clockevents_exchange_device(struct clock_event_device *old,
+                                       struct clock_event_device *new);
+extern void clockevents_set_state(struct clock_event_device *dev,
+                                enum clock_event_state state);
+extern int clockevents_program_event(struct clock_event_device *dev,
+                                    ktime_t expires, bool force);
+extern void clockevents_handle_noop(struct clock_event_device *dev);
+extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
 extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
 
-/*
- * NO_HZ / high resolution timer shared code
- */
+/* Broadcasting support */
+# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu);
+extern void tick_install_broadcast_device(struct clock_event_device *dev);
+extern int tick_is_broadcast_device(struct clock_event_device *dev);
+extern void tick_shutdown_broadcast(unsigned int cpu);
+extern void tick_suspend_broadcast(void);
+extern void tick_resume_broadcast(void);
+extern bool tick_resume_check_broadcast(void);
+extern void tick_broadcast_init(void);
+extern void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
+extern int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
+extern struct tick_device *tick_get_broadcast_device(void);
+extern struct cpumask *tick_get_broadcast_mask(void);
+# else /* !CONFIG_GENERIC_CLOCKEVENTS_BROADCAST: */
+static inline void tick_install_broadcast_device(struct clock_event_device *dev) { }
+static inline int tick_is_broadcast_device(struct clock_event_device *dev) { return 0; }
+static inline int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) { return 0; }
+static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { }
+static inline void tick_shutdown_broadcast(unsigned int cpu) { }
+static inline void tick_suspend_broadcast(void) { }
+static inline void tick_resume_broadcast(void) { }
+static inline bool tick_resume_check_broadcast(void) { return false; }
+static inline void tick_broadcast_init(void) { }
+static inline int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) { return -ENODEV; }
+
+/* Set the periodic handler in non broadcast mode */
+static inline void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast)
+{
+       dev->event_handler = tick_handle_periodic;
+}
+# endif /* !CONFIG_GENERIC_CLOCKEVENTS_BROADCAST */
+
+#else /* !GENERIC_CLOCKEVENTS: */
+static inline void tick_suspend(void) { }
+static inline void tick_resume(void) { }
+#endif /* !GENERIC_CLOCKEVENTS */
+
+/* Oneshot related functions */
 #ifdef CONFIG_TICK_ONESHOT
 extern void tick_setup_oneshot(struct clock_event_device *newdev,
                               void (*handler)(struct clock_event_device *),
@@ -46,58 +94,42 @@ extern int tick_program_event(ktime_t expires, int force);
 extern void tick_oneshot_notify(void);
 extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
 extern void tick_resume_oneshot(void);
-# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+static inline bool tick_oneshot_possible(void) { return true; }
+extern int tick_oneshot_mode_active(void);
+extern void tick_clock_notify(void);
+extern int tick_check_oneshot_change(int allow_nohz);
+extern int tick_init_highres(void);
+#else /* !CONFIG_TICK_ONESHOT: */
+static inline
+void tick_setup_oneshot(struct clock_event_device *newdev,
+                       void (*handler)(struct clock_event_device *),
+                       ktime_t nextevt) { BUG(); }
+static inline void tick_resume_oneshot(void) { BUG(); }
+static inline int tick_program_event(ktime_t expires, int force) { return 0; }
+static inline void tick_oneshot_notify(void) { }
+static inline bool tick_oneshot_possible(void) { return false; }
+static inline int tick_oneshot_mode_active(void) { return 0; }
+static inline void tick_clock_notify(void) { }
+static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
+#endif /* !CONFIG_TICK_ONESHOT */
+
+/* Functions related to oneshot broadcasting */
+#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
 extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
-extern int tick_broadcast_oneshot_control(unsigned long reason);
 extern void tick_broadcast_switch_to_oneshot(void);
-extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
-extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
+extern void tick_shutdown_broadcast_oneshot(unsigned int cpu);
 extern int tick_broadcast_oneshot_active(void);
 extern void tick_check_oneshot_broadcast_this_cpu(void);
 bool tick_broadcast_oneshot_available(void);
-# else /* BROADCAST */
-static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
-{
-       BUG();
-}
-static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
+extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
+#else /* !(BROADCAST && ONESHOT): */
+static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
 static inline void tick_broadcast_switch_to_oneshot(void) { }
-static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
+static inline void tick_shutdown_broadcast_oneshot(unsigned int cpu) { }
 static inline int tick_broadcast_oneshot_active(void) { return 0; }
 static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
-static inline bool tick_broadcast_oneshot_available(void) { return true; }
-# endif /* !BROADCAST */
-
-#else /* !ONESHOT */
-static inline
-void tick_setup_oneshot(struct clock_event_device *newdev,
-                       void (*handler)(struct clock_event_device *),
-                       ktime_t nextevt)
-{
-       BUG();
-}
-static inline void tick_resume_oneshot(void)
-{
-       BUG();
-}
-static inline int tick_program_event(ktime_t expires, int force)
-{
-       return 0;
-}
-static inline void tick_oneshot_notify(void) { }
-static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
-{
-       BUG();
-}
-static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
-static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
-static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
-{
-       return 0;
-}
-static inline int tick_broadcast_oneshot_active(void) { return 0; }
-static inline bool tick_broadcast_oneshot_available(void) { return false; }
-#endif /* !TICK_ONESHOT */
+static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); }
+#endif /* !(BROADCAST && ONESHOT) */
 
 /* NO_HZ_FULL internal */
 #ifdef CONFIG_NO_HZ_FULL
@@ -105,68 +137,3 @@ extern void tick_nohz_init(void);
 # else
 static inline void tick_nohz_init(void) { }
 #endif
-
-/*
- * Broadcasting support
- */
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu);
-extern void tick_install_broadcast_device(struct clock_event_device *dev);
-extern int tick_is_broadcast_device(struct clock_event_device *dev);
-extern void tick_broadcast_on_off(unsigned long reason, int *oncpu);
-extern void tick_shutdown_broadcast(unsigned int *cpup);
-extern void tick_suspend_broadcast(void);
-extern int tick_resume_broadcast(void);
-extern void tick_broadcast_init(void);
-extern void
-tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
-int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
-
-#else /* !BROADCAST */
-
-static inline void tick_install_broadcast_device(struct clock_event_device *dev)
-{
-}
-
-static inline int tick_is_broadcast_device(struct clock_event_device *dev)
-{
-       return 0;
-}
-static inline int tick_device_uses_broadcast(struct clock_event_device *dev,
-                                            int cpu)
-{
-       return 0;
-}
-static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { }
-static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { }
-static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
-static inline void tick_suspend_broadcast(void) { }
-static inline int tick_resume_broadcast(void) { return 0; }
-static inline void tick_broadcast_init(void) { }
-static inline int tick_broadcast_update_freq(struct clock_event_device *dev,
-                                            u32 freq) { return -ENODEV; }
-
-/*
- * Set the periodic handler in non broadcast mode
- */
-static inline void tick_set_periodic_handler(struct clock_event_device *dev,
-                                            int broadcast)
-{
-       dev->event_handler = tick_handle_periodic;
-}
-#endif /* !BROADCAST */
-
-/*
- * Check, if the device is functional or a dummy for broadcast
- */
-static inline int tick_device_is_functional(struct clock_event_device *dev)
-{
-       return !(dev->features & CLOCK_EVT_FEAT_DUMMY);
-}
-
-int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
-
-#endif
-
-extern void do_timer(unsigned long ticks);
-extern void update_wall_time(void);
index 7ce740e78e1b506b155c07e3ac50a9a96e6b262d..67a64b1670bfdb984c7d9edec34f7eadd04800ec 100644 (file)
@@ -38,7 +38,7 @@ void tick_resume_oneshot(void)
 {
        struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
 
-       clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
+       clockevents_set_state(dev, CLOCK_EVT_STATE_ONESHOT);
        clockevents_program_event(dev, ktime_get(), true);
 }
 
@@ -50,7 +50,7 @@ void tick_setup_oneshot(struct clock_event_device *newdev,
                        ktime_t next_event)
 {
        newdev->event_handler = handler;
-       clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
+       clockevents_set_state(newdev, CLOCK_EVT_STATE_ONESHOT);
        clockevents_program_event(newdev, next_event, true);
 }
 
@@ -81,7 +81,7 @@ int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
 
        td->mode = TICKDEV_MODE_ONESHOT;
        dev->event_handler = handler;
-       clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
+       clockevents_set_state(dev, CLOCK_EVT_STATE_ONESHOT);
        tick_broadcast_switch_to_oneshot();
        return 0;
 }
index a4c4edac45281b5c25080efd61e19cc10e9d8636..914259128145e2394e65bd36f18aaf9a81f78843 100644 (file)
@@ -34,7 +34,7 @@
 /*
  * Per cpu nohz control structure
  */
-DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
+static DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
 
 /*
  * The time, when the last jiffy update happened. Protected by jiffies_lock.
@@ -416,6 +416,11 @@ static int __init setup_tick_nohz(char *str)
 
 __setup("nohz=", setup_tick_nohz);
 
+int tick_nohz_tick_stopped(void)
+{
+       return __this_cpu_read(tick_cpu_sched.tick_stopped);
+}
+
 /**
  * tick_nohz_update_jiffies - update jiffies when idle was interrupted
  *
diff --git a/kernel/time/tick-sched.h b/kernel/time/tick-sched.h
new file mode 100644 (file)
index 0000000..28b5da3
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef _TICK_SCHED_H
+#define _TICK_SCHED_H
+
+#include <linux/hrtimer.h>
+
+enum tick_device_mode {
+       TICKDEV_MODE_PERIODIC,
+       TICKDEV_MODE_ONESHOT,
+};
+
+struct tick_device {
+       struct clock_event_device *evtdev;
+       enum tick_device_mode mode;
+};
+
+enum tick_nohz_mode {
+       NOHZ_MODE_INACTIVE,
+       NOHZ_MODE_LOWRES,
+       NOHZ_MODE_HIGHRES,
+};
+
+/**
+ * struct tick_sched - sched tick emulation and no idle tick control/stats
+ * @sched_timer:       hrtimer to schedule the periodic tick in high
+ *                     resolution mode
+ * @last_tick:         Store the last tick expiry time when the tick
+ *                     timer is modified for nohz sleeps. This is necessary
+ *                     to resume the tick timer operation in the timeline
+ *                     when the CPU returns from nohz sleep.
+ * @tick_stopped:      Indicator that the idle tick has been stopped
+ * @idle_jiffies:      jiffies at the entry to idle for idle time accounting
+ * @idle_calls:                Total number of idle calls
+ * @idle_sleeps:       Number of idle calls, where the sched tick was stopped
+ * @idle_entrytime:    Time when the idle call was entered
+ * @idle_waketime:     Time when the idle was interrupted
+ * @idle_exittime:     Time when the idle state was left
+ * @idle_sleeptime:    Sum of the time slept in idle with sched tick stopped
+ * @iowait_sleeptime:  Sum of the time slept in idle with sched tick stopped, with IO outstanding
+ * @sleep_length:      Duration of the current idle sleep
+ * @do_timer_lst:      CPU was the last one doing do_timer before going idle
+ */
+struct tick_sched {
+       struct hrtimer                  sched_timer;
+       unsigned long                   check_clocks;
+       enum tick_nohz_mode             nohz_mode;
+       ktime_t                         last_tick;
+       int                             inidle;
+       int                             tick_stopped;
+       unsigned long                   idle_jiffies;
+       unsigned long                   idle_calls;
+       unsigned long                   idle_sleeps;
+       int                             idle_active;
+       ktime_t                         idle_entrytime;
+       ktime_t                         idle_waketime;
+       ktime_t                         idle_exittime;
+       ktime_t                         idle_sleeptime;
+       ktime_t                         iowait_sleeptime;
+       ktime_t                         sleep_length;
+       unsigned long                   last_jiffies;
+       unsigned long                   next_jiffies;
+       ktime_t                         idle_expires;
+       int                             do_timer_last;
+};
+
+extern struct tick_sched *tick_get_tick_sched(int cpu);
+
+extern void tick_setup_sched_timer(void);
+#if defined CONFIG_NO_HZ_COMMON || defined CONFIG_HIGH_RES_TIMERS
+extern void tick_cancel_sched_timer(int cpu);
+#else
+static inline void tick_cancel_sched_timer(int cpu) { }
+#endif
+
+#endif
index 91db94136c1062571ba0d0f1bfd1ed687770af3e..946acb72179facb1c173e54592b3c1c3637f8abd 100644 (file)
@@ -59,17 +59,15 @@ struct tk_fast {
 };
 
 static struct tk_fast tk_fast_mono ____cacheline_aligned;
+static struct tk_fast tk_fast_raw  ____cacheline_aligned;
 
 /* flag for if timekeeping is suspended */
 int __read_mostly timekeeping_suspended;
 
-/* Flag for if there is a persistent clock on this platform */
-bool __read_mostly persistent_clock_exist = false;
-
 static inline void tk_normalize_xtime(struct timekeeper *tk)
 {
-       while (tk->tkr.xtime_nsec >= ((u64)NSEC_PER_SEC << tk->tkr.shift)) {
-               tk->tkr.xtime_nsec -= (u64)NSEC_PER_SEC << tk->tkr.shift;
+       while (tk->tkr_mono.xtime_nsec >= ((u64)NSEC_PER_SEC << tk->tkr_mono.shift)) {
+               tk->tkr_mono.xtime_nsec -= (u64)NSEC_PER_SEC << tk->tkr_mono.shift;
                tk->xtime_sec++;
        }
 }
@@ -79,20 +77,20 @@ static inline struct timespec64 tk_xtime(struct timekeeper *tk)
        struct timespec64 ts;
 
        ts.tv_sec = tk->xtime_sec;
-       ts.tv_nsec = (long)(tk->tkr.xtime_nsec >> tk->tkr.shift);
+       ts.tv_nsec = (long)(tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift);
        return ts;
 }
 
 static void tk_set_xtime(struct timekeeper *tk, const struct timespec64 *ts)
 {
        tk->xtime_sec = ts->tv_sec;
-       tk->tkr.xtime_nsec = (u64)ts->tv_nsec << tk->tkr.shift;
+       tk->tkr_mono.xtime_nsec = (u64)ts->tv_nsec << tk->tkr_mono.shift;
 }
 
 static void tk_xtime_add(struct timekeeper *tk, const struct timespec64 *ts)
 {
        tk->xtime_sec += ts->tv_sec;
-       tk->tkr.xtime_nsec += (u64)ts->tv_nsec << tk->tkr.shift;
+       tk->tkr_mono.xtime_nsec += (u64)ts->tv_nsec << tk->tkr_mono.shift;
        tk_normalize_xtime(tk);
 }
 
@@ -118,6 +116,117 @@ static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta)
        tk->offs_boot = ktime_add(tk->offs_boot, delta);
 }
 
+#ifdef CONFIG_DEBUG_TIMEKEEPING
+#define WARNING_FREQ (HZ*300) /* 5 minute rate-limiting */
+/*
+ * These simple flag variables are managed
+ * without locks, which is racy, but ok since
+ * we don't really care about being super
+ * precise about how many events were seen,
+ * just that a problem was observed.
+ */
+static int timekeeping_underflow_seen;
+static int timekeeping_overflow_seen;
+
+/* last_warning is only modified under the timekeeping lock */
+static long timekeeping_last_warning;
+
+static void timekeeping_check_update(struct timekeeper *tk, cycle_t offset)
+{
+
+       cycle_t max_cycles = tk->tkr_mono.clock->max_cycles;
+       const char *name = tk->tkr_mono.clock->name;
+
+       if (offset > max_cycles) {
+               printk_deferred("WARNING: timekeeping: Cycle offset (%lld) is larger than allowed by the '%s' clock's max_cycles value (%lld): time overflow danger\n",
+                               offset, name, max_cycles);
+               printk_deferred("         timekeeping: Your kernel is sick, but tries to cope by capping time updates\n");
+       } else {
+               if (offset > (max_cycles >> 1)) {
+                       printk_deferred("INFO: timekeeping: Cycle offset (%lld) is larger than the the '%s' clock's 50%% safety margin (%lld)\n",
+                                       offset, name, max_cycles >> 1);
+                       printk_deferred("      timekeeping: Your kernel is still fine, but is feeling a bit nervous\n");
+               }
+       }
+
+       if (timekeeping_underflow_seen) {
+               if (jiffies - timekeeping_last_warning > WARNING_FREQ) {
+                       printk_deferred("WARNING: Underflow in clocksource '%s' observed, time update ignored.\n", name);
+                       printk_deferred("         Please report this, consider using a different clocksource, if possible.\n");
+                       printk_deferred("         Your kernel is probably still fine.\n");
+                       timekeeping_last_warning = jiffies;
+               }
+               timekeeping_underflow_seen = 0;
+       }
+
+       if (timekeeping_overflow_seen) {
+               if (jiffies - timekeeping_last_warning > WARNING_FREQ) {
+                       printk_deferred("WARNING: Overflow in clocksource '%s' observed, time update capped.\n", name);
+                       printk_deferred("         Please report this, consider using a different clocksource, if possible.\n");
+                       printk_deferred("         Your kernel is probably still fine.\n");
+                       timekeeping_last_warning = jiffies;
+               }
+               timekeeping_overflow_seen = 0;
+       }
+}
+
+static inline cycle_t timekeeping_get_delta(struct tk_read_base *tkr)
+{
+       cycle_t now, last, mask, max, delta;
+       unsigned int seq;
+
+       /*
+        * Since we're called holding a seqlock, the data may shift
+        * under us while we're doing the calculation. This can cause
+        * false positives, since we'd note a problem but throw the
+        * results away. So nest another seqlock here to atomically
+        * grab the points we are checking with.
+        */
+       do {
+               seq = read_seqcount_begin(&tk_core.seq);
+               now = tkr->read(tkr->clock);
+               last = tkr->cycle_last;
+               mask = tkr->mask;
+               max = tkr->clock->max_cycles;
+       } while (read_seqcount_retry(&tk_core.seq, seq));
+
+       delta = clocksource_delta(now, last, mask);
+
+       /*
+        * Try to catch underflows by checking if we are seeing small
+        * mask-relative negative values.
+        */
+       if (unlikely((~delta & mask) < (mask >> 3))) {
+               timekeeping_underflow_seen = 1;
+               delta = 0;
+       }
+
+       /* Cap delta value to the max_cycles values to avoid mult overflows */
+       if (unlikely(delta > max)) {
+               timekeeping_overflow_seen = 1;
+               delta = tkr->clock->max_cycles;
+       }
+
+       return delta;
+}
+#else
+static inline void timekeeping_check_update(struct timekeeper *tk, cycle_t offset)
+{
+}
+static inline cycle_t timekeeping_get_delta(struct tk_read_base *tkr)
+{
+       cycle_t cycle_now, delta;
+
+       /* read clocksource */
+       cycle_now = tkr->read(tkr->clock);
+
+       /* calculate the delta since the last update_wall_time */
+       delta = clocksource_delta(cycle_now, tkr->cycle_last, tkr->mask);
+
+       return delta;
+}
+#endif
+
 /**
  * tk_setup_internals - Set up internals to use clocksource clock.
  *
@@ -135,11 +244,16 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
        u64 tmp, ntpinterval;
        struct clocksource *old_clock;
 
-       old_clock = tk->tkr.clock;
-       tk->tkr.clock = clock;
-       tk->tkr.read = clock->read;
-       tk->tkr.mask = clock->mask;
-       tk->tkr.cycle_last = tk->tkr.read(clock);
+       old_clock = tk->tkr_mono.clock;
+       tk->tkr_mono.clock = clock;
+       tk->tkr_mono.read = clock->read;
+       tk->tkr_mono.mask = clock->mask;
+       tk->tkr_mono.cycle_last = tk->tkr_mono.read(clock);
+
+       tk->tkr_raw.clock = clock;
+       tk->tkr_raw.read = clock->read;
+       tk->tkr_raw.mask = clock->mask;
+       tk->tkr_raw.cycle_last = tk->tkr_mono.cycle_last;
 
        /* Do the ns -> cycle conversion first, using original mult */
        tmp = NTP_INTERVAL_LENGTH;
@@ -163,11 +277,14 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
        if (old_clock) {
                int shift_change = clock->shift - old_clock->shift;
                if (shift_change < 0)
-                       tk->tkr.xtime_nsec >>= -shift_change;
+                       tk->tkr_mono.xtime_nsec >>= -shift_change;
                else
-                       tk->tkr.xtime_nsec <<= shift_change;
+                       tk->tkr_mono.xtime_nsec <<= shift_change;
        }
-       tk->tkr.shift = clock->shift;
+       tk->tkr_raw.xtime_nsec = 0;
+
+       tk->tkr_mono.shift = clock->shift;
+       tk->tkr_raw.shift = clock->shift;
 
        tk->ntp_error = 0;
        tk->ntp_error_shift = NTP_SCALE_SHIFT - clock->shift;
@@ -178,7 +295,8 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
         * active clocksource. These value will be adjusted via NTP
         * to counteract clock drifting.
         */
-       tk->tkr.mult = clock->mult;
+       tk->tkr_mono.mult = clock->mult;
+       tk->tkr_raw.mult = clock->mult;
        tk->ntp_err_mult = 0;
 }
 
@@ -193,14 +311,10 @@ static inline u32 arch_gettimeoffset(void) { return 0; }
 
 static inline s64 timekeeping_get_ns(struct tk_read_base *tkr)
 {
-       cycle_t cycle_now, delta;
+       cycle_t delta;
        s64 nsec;
 
-       /* read clocksource: */
-       cycle_now = tkr->read(tkr->clock);
-
-       /* calculate the delta since the last update_wall_time: */
-       delta = clocksource_delta(cycle_now, tkr->cycle_last, tkr->mask);
+       delta = timekeeping_get_delta(tkr);
 
        nsec = delta * tkr->mult + tkr->xtime_nsec;
        nsec >>= tkr->shift;
@@ -209,25 +323,6 @@ static inline s64 timekeeping_get_ns(struct tk_read_base *tkr)
        return nsec + arch_gettimeoffset();
 }
 
-static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
-{
-       struct clocksource *clock = tk->tkr.clock;
-       cycle_t cycle_now, delta;
-       s64 nsec;
-
-       /* read clocksource: */
-       cycle_now = tk->tkr.read(clock);
-
-       /* calculate the delta since the last update_wall_time: */
-       delta = clocksource_delta(cycle_now, tk->tkr.cycle_last, tk->tkr.mask);
-
-       /* convert delta to nanoseconds. */
-       nsec = clocksource_cyc2ns(delta, clock->mult, clock->shift);
-
-       /* If arch requires, add in get_arch_timeoffset() */
-       return nsec + arch_gettimeoffset();
-}
-
 /**
  * update_fast_timekeeper - Update the fast and NMI safe monotonic timekeeper.
  * @tkr: Timekeeping readout base from which we take the update
@@ -267,18 +362,18 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
  * slightly wrong timestamp (a few nanoseconds). See
  * @ktime_get_mono_fast_ns.
  */
-static void update_fast_timekeeper(struct tk_read_base *tkr)
+static void update_fast_timekeeper(struct tk_read_base *tkr, struct tk_fast *tkf)
 {
-       struct tk_read_base *base = tk_fast_mono.base;
+       struct tk_read_base *base = tkf->base;
 
        /* Force readers off to base[1] */
-       raw_write_seqcount_latch(&tk_fast_mono.seq);
+       raw_write_seqcount_latch(&tkf->seq);
 
        /* Update base[0] */
        memcpy(base, tkr, sizeof(*base));
 
        /* Force readers back to base[0] */
-       raw_write_seqcount_latch(&tk_fast_mono.seq);
+       raw_write_seqcount_latch(&tkf->seq);
 
        /* Update base[1] */
        memcpy(base + 1, base, sizeof(*base));
@@ -316,22 +411,33 @@ static void update_fast_timekeeper(struct tk_read_base *tkr)
  * of the following timestamps. Callers need to be aware of that and
  * deal with it.
  */
-u64 notrace ktime_get_mono_fast_ns(void)
+static __always_inline u64 __ktime_get_fast_ns(struct tk_fast *tkf)
 {
        struct tk_read_base *tkr;
        unsigned int seq;
        u64 now;
 
        do {
-               seq = raw_read_seqcount(&tk_fast_mono.seq);
-               tkr = tk_fast_mono.base + (seq & 0x01);
-               now = ktime_to_ns(tkr->base_mono) + timekeeping_get_ns(tkr);
+               seq = raw_read_seqcount(&tkf->seq);
+               tkr = tkf->base + (seq & 0x01);
+               now = ktime_to_ns(tkr->base) + timekeeping_get_ns(tkr);
+       } while (read_seqcount_retry(&tkf->seq, seq));
 
-       } while (read_seqcount_retry(&tk_fast_mono.seq, seq));
        return now;
 }
+
+u64 ktime_get_mono_fast_ns(void)
+{
+       return __ktime_get_fast_ns(&tk_fast_mono);
+}
 EXPORT_SYMBOL_GPL(ktime_get_mono_fast_ns);
 
+u64 ktime_get_raw_fast_ns(void)
+{
+       return __ktime_get_fast_ns(&tk_fast_raw);
+}
+EXPORT_SYMBOL_GPL(ktime_get_raw_fast_ns);
+
 /* Suspend-time cycles value for halted fast timekeeper. */
 static cycle_t cycles_at_suspend;
 
@@ -353,12 +459,17 @@ static cycle_t dummy_clock_read(struct clocksource *cs)
 static void halt_fast_timekeeper(struct timekeeper *tk)
 {
        static struct tk_read_base tkr_dummy;
-       struct tk_read_base *tkr = &tk->tkr;
+       struct tk_read_base *tkr = &tk->tkr_mono;
 
        memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy));
        cycles_at_suspend = tkr->read(tkr->clock);
        tkr_dummy.read = dummy_clock_read;
-       update_fast_timekeeper(&tkr_dummy);
+       update_fast_timekeeper(&tkr_dummy, &tk_fast_mono);
+
+       tkr = &tk->tkr_raw;
+       memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy));
+       tkr_dummy.read = dummy_clock_read;
+       update_fast_timekeeper(&tkr_dummy, &tk_fast_raw);
 }
 
 #ifdef CONFIG_GENERIC_TIME_VSYSCALL_OLD
@@ -369,8 +480,8 @@ static inline void update_vsyscall(struct timekeeper *tk)
 
        xt = timespec64_to_timespec(tk_xtime(tk));
        wm = timespec64_to_timespec(tk->wall_to_monotonic);
-       update_vsyscall_old(&xt, &wm, tk->tkr.clock, tk->tkr.mult,
-                           tk->tkr.cycle_last);
+       update_vsyscall_old(&xt, &wm, tk->tkr_mono.clock, tk->tkr_mono.mult,
+                           tk->tkr_mono.cycle_last);
 }
 
 static inline void old_vsyscall_fixup(struct timekeeper *tk)
@@ -387,11 +498,11 @@ static inline void old_vsyscall_fixup(struct timekeeper *tk)
        * (shifted nanoseconds), and CONFIG_GENERIC_TIME_VSYSCALL_OLD
        * users are removed, this can be killed.
        */
-       remainder = tk->tkr.xtime_nsec & ((1ULL << tk->tkr.shift) - 1);
-       tk->tkr.xtime_nsec -= remainder;
-       tk->tkr.xtime_nsec += 1ULL << tk->tkr.shift;
+       remainder = tk->tkr_mono.xtime_nsec & ((1ULL << tk->tkr_mono.shift) - 1);
+       tk->tkr_mono.xtime_nsec -= remainder;
+       tk->tkr_mono.xtime_nsec += 1ULL << tk->tkr_mono.shift;
        tk->ntp_error += remainder << tk->ntp_error_shift;
-       tk->ntp_error -= (1ULL << tk->tkr.shift) << tk->ntp_error_shift;
+       tk->ntp_error -= (1ULL << tk->tkr_mono.shift) << tk->ntp_error_shift;
 }
 #else
 #define old_vsyscall_fixup(tk)
@@ -456,17 +567,17 @@ static inline void tk_update_ktime_data(struct timekeeper *tk)
         */
        seconds = (u64)(tk->xtime_sec + tk->wall_to_monotonic.tv_sec);
        nsec = (u32) tk->wall_to_monotonic.tv_nsec;
-       tk->tkr.base_mono = ns_to_ktime(seconds * NSEC_PER_SEC + nsec);
+       tk->tkr_mono.base = ns_to_ktime(seconds * NSEC_PER_SEC + nsec);
 
        /* Update the monotonic raw base */
-       tk->base_raw = timespec64_to_ktime(tk->raw_time);
+       tk->tkr_raw.base = timespec64_to_ktime(tk->raw_time);
 
        /*
         * The sum of the nanoseconds portions of xtime and
         * wall_to_monotonic can be greater/equal one second. Take
         * this into account before updating tk->ktime_sec.
         */
-       nsec += (u32)(tk->tkr.xtime_nsec >> tk->tkr.shift);
+       nsec += (u32)(tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift);
        if (nsec >= NSEC_PER_SEC)
                seconds++;
        tk->ktime_sec = seconds;
@@ -489,7 +600,8 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action)
                memcpy(&shadow_timekeeper, &tk_core.timekeeper,
                       sizeof(tk_core.timekeeper));
 
-       update_fast_timekeeper(&tk->tkr);
+       update_fast_timekeeper(&tk->tkr_mono, &tk_fast_mono);
+       update_fast_timekeeper(&tk->tkr_raw,  &tk_fast_raw);
 }
 
 /**
@@ -501,22 +613,23 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action)
  */
 static void timekeeping_forward_now(struct timekeeper *tk)
 {
-       struct clocksource *clock = tk->tkr.clock;
+       struct clocksource *clock = tk->tkr_mono.clock;
        cycle_t cycle_now, delta;
        s64 nsec;
 
-       cycle_now = tk->tkr.read(clock);
-       delta = clocksource_delta(cycle_now, tk->tkr.cycle_last, tk->tkr.mask);
-       tk->tkr.cycle_last = cycle_now;
+       cycle_now = tk->tkr_mono.read(clock);
+       delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask);
+       tk->tkr_mono.cycle_last = cycle_now;
+       tk->tkr_raw.cycle_last  = cycle_now;
 
-       tk->tkr.xtime_nsec += delta * tk->tkr.mult;
+       tk->tkr_mono.xtime_nsec += delta * tk->tkr_mono.mult;
 
        /* If arch requires, add in get_arch_timeoffset() */
-       tk->tkr.xtime_nsec += (u64)arch_gettimeoffset() << tk->tkr.shift;
+       tk->tkr_mono.xtime_nsec += (u64)arch_gettimeoffset() << tk->tkr_mono.shift;
 
        tk_normalize_xtime(tk);
 
-       nsec = clocksource_cyc2ns(delta, clock->mult, clock->shift);
+       nsec = clocksource_cyc2ns(delta, tk->tkr_raw.mult, tk->tkr_raw.shift);
        timespec64_add_ns(&tk->raw_time, nsec);
 }
 
@@ -537,7 +650,7 @@ int __getnstimeofday64(struct timespec64 *ts)
                seq = read_seqcount_begin(&tk_core.seq);
 
                ts->tv_sec = tk->xtime_sec;
-               nsecs = timekeeping_get_ns(&tk->tkr);
+               nsecs = timekeeping_get_ns(&tk->tkr_mono);
 
        } while (read_seqcount_retry(&tk_core.seq, seq));
 
@@ -577,8 +690,8 @@ ktime_t ktime_get(void)
 
        do {
                seq = read_seqcount_begin(&tk_core.seq);
-               base = tk->tkr.base_mono;
-               nsecs = timekeeping_get_ns(&tk->tkr);
+               base = tk->tkr_mono.base;
+               nsecs = timekeeping_get_ns(&tk->tkr_mono);
 
        } while (read_seqcount_retry(&tk_core.seq, seq));
 
@@ -603,8 +716,8 @@ ktime_t ktime_get_with_offset(enum tk_offsets offs)
 
        do {
                seq = read_seqcount_begin(&tk_core.seq);
-               base = ktime_add(tk->tkr.base_mono, *offset);
-               nsecs = timekeeping_get_ns(&tk->tkr);
+               base = ktime_add(tk->tkr_mono.base, *offset);
+               nsecs = timekeeping_get_ns(&tk->tkr_mono);
 
        } while (read_seqcount_retry(&tk_core.seq, seq));
 
@@ -645,8 +758,8 @@ ktime_t ktime_get_raw(void)
 
        do {
                seq = read_seqcount_begin(&tk_core.seq);
-               base = tk->base_raw;
-               nsecs = timekeeping_get_ns_raw(tk);
+               base = tk->tkr_raw.base;
+               nsecs = timekeeping_get_ns(&tk->tkr_raw);
 
        } while (read_seqcount_retry(&tk_core.seq, seq));
 
@@ -674,7 +787,7 @@ void ktime_get_ts64(struct timespec64 *ts)
        do {
                seq = read_seqcount_begin(&tk_core.seq);
                ts->tv_sec = tk->xtime_sec;
-               nsec = timekeeping_get_ns(&tk->tkr);
+               nsec = timekeeping_get_ns(&tk->tkr_mono);
                tomono = tk->wall_to_monotonic;
 
        } while (read_seqcount_retry(&tk_core.seq, seq));
@@ -759,8 +872,8 @@ void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real)
                ts_real->tv_sec = tk->xtime_sec;
                ts_real->tv_nsec = 0;
 
-               nsecs_raw = timekeeping_get_ns_raw(tk);
-               nsecs_real = timekeeping_get_ns(&tk->tkr);
+               nsecs_raw  = timekeeping_get_ns(&tk->tkr_raw);
+               nsecs_real = timekeeping_get_ns(&tk->tkr_mono);
 
        } while (read_seqcount_retry(&tk_core.seq, seq));
 
@@ -943,7 +1056,7 @@ static int change_clocksource(void *data)
         */
        if (try_module_get(new->owner)) {
                if (!new->enable || new->enable(new) == 0) {
-                       old = tk->tkr.clock;
+                       old = tk->tkr_mono.clock;
                        tk_setup_internals(tk, new);
                        if (old->disable)
                                old->disable(old);
@@ -971,11 +1084,11 @@ int timekeeping_notify(struct clocksource *clock)
 {
        struct timekeeper *tk = &tk_core.timekeeper;
 
-       if (tk->tkr.clock == clock)
+       if (tk->tkr_mono.clock == clock)
                return 0;
        stop_machine(change_clocksource, clock, NULL);
        tick_clock_notify();
-       return tk->tkr.clock == clock ? 0 : -1;
+       return tk->tkr_mono.clock == clock ? 0 : -1;
 }
 
 /**
@@ -993,7 +1106,7 @@ void getrawmonotonic64(struct timespec64 *ts)
 
        do {
                seq = read_seqcount_begin(&tk_core.seq);
-               nsecs = timekeeping_get_ns_raw(tk);
+               nsecs = timekeeping_get_ns(&tk->tkr_raw);
                ts64 = tk->raw_time;
 
        } while (read_seqcount_retry(&tk_core.seq, seq));
@@ -1016,7 +1129,7 @@ int timekeeping_valid_for_hres(void)
        do {
                seq = read_seqcount_begin(&tk_core.seq);
 
-               ret = tk->tkr.clock->flags & CLOCK_SOURCE_VALID_FOR_HRES;
+               ret = tk->tkr_mono.clock->flags & CLOCK_SOURCE_VALID_FOR_HRES;
 
        } while (read_seqcount_retry(&tk_core.seq, seq));
 
@@ -1035,7 +1148,7 @@ u64 timekeeping_max_deferment(void)
        do {
                seq = read_seqcount_begin(&tk_core.seq);
 
-               ret = tk->tkr.clock->max_idle_ns;
+               ret = tk->tkr_mono.clock->max_idle_ns;
 
        } while (read_seqcount_retry(&tk_core.seq, seq));
 
@@ -1057,6 +1170,14 @@ void __weak read_persistent_clock(struct timespec *ts)
        ts->tv_nsec = 0;
 }
 
+void __weak read_persistent_clock64(struct timespec64 *ts64)
+{
+       struct timespec ts;
+
+       read_persistent_clock(&ts);
+       *ts64 = timespec_to_timespec64(ts);
+}
+
 /**
  * read_boot_clock -  Return time of the system start.
  *
@@ -1072,6 +1193,20 @@ void __weak read_boot_clock(struct timespec *ts)
        ts->tv_nsec = 0;
 }
 
+void __weak read_boot_clock64(struct timespec64 *ts64)
+{
+       struct timespec ts;
+
+       read_boot_clock(&ts);
+       *ts64 = timespec_to_timespec64(ts);
+}
+
+/* Flag for if timekeeping_resume() has injected sleeptime */
+static bool sleeptime_injected;
+
+/* Flag for if there is a persistent clock on this platform */
+static bool persistent_clock_exists;
+
 /*
  * timekeeping_init - Initializes the clocksource and common timekeeping values
  */
@@ -1081,20 +1216,17 @@ void __init timekeeping_init(void)
        struct clocksource *clock;
        unsigned long flags;
        struct timespec64 now, boot, tmp;
-       struct timespec ts;
 
-       read_persistent_clock(&ts);
-       now = timespec_to_timespec64(ts);
+       read_persistent_clock64(&now);
        if (!timespec64_valid_strict(&now)) {
                pr_warn("WARNING: Persistent clock returned invalid value!\n"
                        "         Check your CMOS/BIOS settings.\n");
                now.tv_sec = 0;
                now.tv_nsec = 0;
        } else if (now.tv_sec || now.tv_nsec)
-               persistent_clock_exist = true;
+               persistent_clock_exists = true;
 
-       read_boot_clock(&ts);
-       boot = timespec_to_timespec64(ts);
+       read_boot_clock64(&boot);
        if (!timespec64_valid_strict(&boot)) {
                pr_warn("WARNING: Boot clock returned invalid value!\n"
                        "         Check your CMOS/BIOS settings.\n");
@@ -1114,7 +1246,6 @@ void __init timekeeping_init(void)
        tk_set_xtime(tk, &now);
        tk->raw_time.tv_sec = 0;
        tk->raw_time.tv_nsec = 0;
-       tk->base_raw.tv64 = 0;
        if (boot.tv_sec == 0 && boot.tv_nsec == 0)
                boot = tk_xtime(tk);
 
@@ -1127,7 +1258,7 @@ void __init timekeeping_init(void)
        raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
 }
 
-/* time in seconds when suspend began */
+/* time in seconds when suspend began for persistent clock */
 static struct timespec64 timekeeping_suspend_time;
 
 /**
@@ -1152,12 +1283,49 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk,
        tk_debug_account_sleep_time(delta);
 }
 
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_RTC_HCTOSYS_DEVICE)
+/**
+ * We have three kinds of time sources to use for sleep time
+ * injection, the preference order is:
+ * 1) non-stop clocksource
+ * 2) persistent clock (ie: RTC accessible when irqs are off)
+ * 3) RTC
+ *
+ * 1) and 2) are used by timekeeping, 3) by RTC subsystem.
+ * If system has neither 1) nor 2), 3) will be used finally.
+ *
+ *
+ * If timekeeping has injected sleeptime via either 1) or 2),
+ * 3) becomes needless, so in this case we don't need to call
+ * rtc_resume(), and this is what timekeeping_rtc_skipresume()
+ * means.
+ */
+bool timekeeping_rtc_skipresume(void)
+{
+       return sleeptime_injected;
+}
+
+/**
+ * 1) can be determined whether to use or not only when doing
+ * timekeeping_resume() which is invoked after rtc_suspend(),
+ * so we can't skip rtc_suspend() surely if system has 1).
+ *
+ * But if system has 2), 2) will definitely be used, so in this
+ * case we don't need to call rtc_suspend(), and this is what
+ * timekeeping_rtc_skipsuspend() means.
+ */
+bool timekeeping_rtc_skipsuspend(void)
+{
+       return persistent_clock_exists;
+}
+
 /**
  * timekeeping_inject_sleeptime64 - Adds suspend interval to timeekeeping values
  * @delta: pointer to a timespec64 delta value
  *
- * This hook is for architectures that cannot support read_persistent_clock
+ * This hook is for architectures that cannot support read_persistent_clock64
  * because their RTC/persistent clock is only accessible when irqs are enabled.
+ * and also don't have an effective nonstop clocksource.
  *
  * This function should only be called by rtc_resume(), and allows
  * a suspend offset to be injected into the timekeeping values.
@@ -1167,13 +1335,6 @@ void timekeeping_inject_sleeptime64(struct timespec64 *delta)
        struct timekeeper *tk = &tk_core.timekeeper;
        unsigned long flags;
 
-       /*
-        * Make sure we don't set the clock twice, as timekeeping_resume()
-        * already did it
-        */
-       if (has_persistent_clock())
-               return;
-
        raw_spin_lock_irqsave(&timekeeper_lock, flags);
        write_seqcount_begin(&tk_core.seq);
 
@@ -1189,26 +1350,21 @@ void timekeeping_inject_sleeptime64(struct timespec64 *delta)
        /* signal hrtimers about time change */
        clock_was_set();
 }
+#endif
 
 /**
  * timekeeping_resume - Resumes the generic timekeeping subsystem.
- *
- * This is for the generic clocksource timekeeping.
- * xtime/wall_to_monotonic/jiffies/etc are
- * still managed by arch specific suspend/resume code.
  */
 void timekeeping_resume(void)
 {
        struct timekeeper *tk = &tk_core.timekeeper;
-       struct clocksource *clock = tk->tkr.clock;
+       struct clocksource *clock = tk->tkr_mono.clock;
        unsigned long flags;
        struct timespec64 ts_new, ts_delta;
-       struct timespec tmp;
        cycle_t cycle_now, cycle_delta;
-       bool suspendtime_found = false;
 
-       read_persistent_clock(&tmp);
-       ts_new = timespec_to_timespec64(tmp);
+       sleeptime_injected = false;
+       read_persistent_clock64(&ts_new);
 
        clockevents_resume();
        clocksource_resume();
@@ -1228,16 +1384,16 @@ void timekeeping_resume(void)
         * The less preferred source will only be tried if there is no better
         * usable source. The rtc part is handled separately in rtc core code.
         */
-       cycle_now = tk->tkr.read(clock);
+       cycle_now = tk->tkr_mono.read(clock);
        if ((clock->flags & CLOCK_SOURCE_SUSPEND_NONSTOP) &&
-               cycle_now > tk->tkr.cycle_last) {
+               cycle_now > tk->tkr_mono.cycle_last) {
                u64 num, max = ULLONG_MAX;
                u32 mult = clock->mult;
                u32 shift = clock->shift;
                s64 nsec = 0;
 
-               cycle_delta = clocksource_delta(cycle_now, tk->tkr.cycle_last,
-                                               tk->tkr.mask);
+               cycle_delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last,
+                                               tk->tkr_mono.mask);
 
                /*
                 * "cycle_delta * mutl" may cause 64 bits overflow, if the
@@ -1253,17 +1409,19 @@ void timekeeping_resume(void)
                nsec += ((u64) cycle_delta * mult) >> shift;
 
                ts_delta = ns_to_timespec64(nsec);
-               suspendtime_found = true;
+               sleeptime_injected = true;
        } else if (timespec64_compare(&ts_new, &timekeeping_suspend_time) > 0) {
                ts_delta = timespec64_sub(ts_new, timekeeping_suspend_time);
-               suspendtime_found = true;
+               sleeptime_injected = true;
        }
 
-       if (suspendtime_found)
+       if (sleeptime_injected)
                __timekeeping_inject_sleeptime(tk, &ts_delta);
 
        /* Re-base the last cycle value */
-       tk->tkr.cycle_last = cycle_now;
+       tk->tkr_mono.cycle_last = cycle_now;
+       tk->tkr_raw.cycle_last  = cycle_now;
+
        tk->ntp_error = 0;
        timekeeping_suspended = 0;
        timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
@@ -1272,9 +1430,7 @@ void timekeeping_resume(void)
 
        touch_softlockup_watchdog();
 
-       clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
-
-       /* Resume hrtimers */
+       tick_resume();
        hrtimers_resume();
 }
 
@@ -1284,10 +1440,8 @@ int timekeeping_suspend(void)
        unsigned long flags;
        struct timespec64               delta, delta_delta;
        static struct timespec64        old_delta;
-       struct timespec tmp;
 
-       read_persistent_clock(&tmp);
-       timekeeping_suspend_time = timespec_to_timespec64(tmp);
+       read_persistent_clock64(&timekeeping_suspend_time);
 
        /*
         * On some systems the persistent_clock can not be detected at
@@ -1295,31 +1449,33 @@ int timekeeping_suspend(void)
         * value returned, update the persistent_clock_exists flag.
         */
        if (timekeeping_suspend_time.tv_sec || timekeeping_suspend_time.tv_nsec)
-               persistent_clock_exist = true;
+               persistent_clock_exists = true;
 
        raw_spin_lock_irqsave(&timekeeper_lock, flags);
        write_seqcount_begin(&tk_core.seq);
        timekeeping_forward_now(tk);
        timekeeping_suspended = 1;
 
-       /*
-        * To avoid drift caused by repeated suspend/resumes,
-        * which each can add ~1 second drift error,
-        * try to compensate so the difference in system time
-        * and persistent_clock time stays close to constant.
-        */
-       delta = timespec64_sub(tk_xtime(tk), timekeeping_suspend_time);
-       delta_delta = timespec64_sub(delta, old_delta);
-       if (abs(delta_delta.tv_sec)  >= 2) {
+       if (persistent_clock_exists) {
                /*
-                * if delta_delta is too large, assume time correction
-                * has occured and set old_delta to the current delta.
+                * To avoid drift caused by repeated suspend/resumes,
+                * which each can add ~1 second drift error,
+                * try to compensate so the difference in system time
+                * and persistent_clock time stays close to constant.
                 */
-               old_delta = delta;
-       } else {
-               /* Otherwise try to adjust old_system to compensate */
-               timekeeping_suspend_time =
-                       timespec64_add(timekeeping_suspend_time, delta_delta);
+               delta = timespec64_sub(tk_xtime(tk), timekeeping_suspend_time);
+               delta_delta = timespec64_sub(delta, old_delta);
+               if (abs(delta_delta.tv_sec) >= 2) {
+                       /*
+                        * if delta_delta is too large, assume time correction
+                        * has occurred and set old_delta to the current delta.
+                        */
+                       old_delta = delta;
+               } else {
+                       /* Otherwise try to adjust old_system to compensate */
+                       timekeeping_suspend_time =
+                               timespec64_add(timekeeping_suspend_time, delta_delta);
+               }
        }
 
        timekeeping_update(tk, TK_MIRROR);
@@ -1327,7 +1483,7 @@ int timekeeping_suspend(void)
        write_seqcount_end(&tk_core.seq);
        raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
 
-       clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
+       tick_suspend();
        clocksource_suspend();
        clockevents_suspend();
 
@@ -1416,15 +1572,15 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,
         *
         * XXX - TODO: Doc ntp_error calculation.
         */
-       if ((mult_adj > 0) && (tk->tkr.mult + mult_adj < mult_adj)) {
+       if ((mult_adj > 0) && (tk->tkr_mono.mult + mult_adj < mult_adj)) {
                /* NTP adjustment caused clocksource mult overflow */
                WARN_ON_ONCE(1);
                return;
        }
 
-       tk->tkr.mult += mult_adj;
+       tk->tkr_mono.mult += mult_adj;
        tk->xtime_interval += interval;
-       tk->tkr.xtime_nsec -= offset;
+       tk->tkr_mono.xtime_nsec -= offset;
        tk->ntp_error -= (interval - offset) << tk->ntp_error_shift;
 }
 
@@ -1486,13 +1642,13 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
                tk->ntp_err_mult = 0;
        }
 
-       if (unlikely(tk->tkr.clock->maxadj &&
-               (abs(tk->tkr.mult - tk->tkr.clock->mult)
-                       > tk->tkr.clock->maxadj))) {
+       if (unlikely(tk->tkr_mono.clock->maxadj &&
+               (abs(tk->tkr_mono.mult - tk->tkr_mono.clock->mult)
+                       > tk->tkr_mono.clock->maxadj))) {
                printk_once(KERN_WARNING
                        "Adjusting %s more than 11%% (%ld vs %ld)\n",
-                       tk->tkr.clock->name, (long)tk->tkr.mult,
-                       (long)tk->tkr.clock->mult + tk->tkr.clock->maxadj);
+                       tk->tkr_mono.clock->name, (long)tk->tkr_mono.mult,
+                       (long)tk->tkr_mono.clock->mult + tk->tkr_mono.clock->maxadj);
        }
 
        /*
@@ -1509,9 +1665,9 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
         * We'll correct this error next time through this function, when
         * xtime_nsec is not as small.
         */
-       if (unlikely((s64)tk->tkr.xtime_nsec < 0)) {
-               s64 neg = -(s64)tk->tkr.xtime_nsec;
-               tk->tkr.xtime_nsec = 0;
+       if (unlikely((s64)tk->tkr_mono.xtime_nsec < 0)) {
+               s64 neg = -(s64)tk->tkr_mono.xtime_nsec;
+               tk->tkr_mono.xtime_nsec = 0;
                tk->ntp_error += neg << tk->ntp_error_shift;
        }
 }
@@ -1526,13 +1682,13 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
  */
 static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk)
 {
-       u64 nsecps = (u64)NSEC_PER_SEC << tk->tkr.shift;
+       u64 nsecps = (u64)NSEC_PER_SEC << tk->tkr_mono.shift;
        unsigned int clock_set = 0;
 
-       while (tk->tkr.xtime_nsec >= nsecps) {
+       while (tk->tkr_mono.xtime_nsec >= nsecps) {
                int leap;
 
-               tk->tkr.xtime_nsec -= nsecps;
+               tk->tkr_mono.xtime_nsec -= nsecps;
                tk->xtime_sec++;
 
                /* Figure out if its a leap sec and apply if needed */
@@ -1577,9 +1733,10 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
 
        /* Accumulate one shifted interval */
        offset -= interval;
-       tk->tkr.cycle_last += interval;
+       tk->tkr_mono.cycle_last += interval;
+       tk->tkr_raw.cycle_last  += interval;
 
-       tk->tkr.xtime_nsec += tk->xtime_interval << shift;
+       tk->tkr_mono.xtime_nsec += tk->xtime_interval << shift;
        *clock_set |= accumulate_nsecs_to_secs(tk);
 
        /* Accumulate raw time */
@@ -1622,14 +1779,17 @@ void update_wall_time(void)
 #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
        offset = real_tk->cycle_interval;
 #else
-       offset = clocksource_delta(tk->tkr.read(tk->tkr.clock),
-                                  tk->tkr.cycle_last, tk->tkr.mask);
+       offset = clocksource_delta(tk->tkr_mono.read(tk->tkr_mono.clock),
+                                  tk->tkr_mono.cycle_last, tk->tkr_mono.mask);
 #endif
 
        /* Check if there's really nothing to do */
        if (offset < real_tk->cycle_interval)
                goto out;
 
+       /* Do some additional sanity checking */
+       timekeeping_check_update(real_tk, offset);
+
        /*
         * With NO_HZ we may have to accumulate many cycle_intervals
         * (think "ticks") worth of time at once. To do this efficiently,
@@ -1784,8 +1944,8 @@ ktime_t ktime_get_update_offsets_tick(ktime_t *offs_real, ktime_t *offs_boot,
        do {
                seq = read_seqcount_begin(&tk_core.seq);
 
-               base = tk->tkr.base_mono;
-               nsecs = tk->tkr.xtime_nsec >> tk->tkr.shift;
+               base = tk->tkr_mono.base;
+               nsecs = tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift;
 
                *offs_real = tk->offs_real;
                *offs_boot = tk->offs_boot;
@@ -1816,8 +1976,8 @@ ktime_t ktime_get_update_offsets_now(ktime_t *offs_real, ktime_t *offs_boot,
        do {
                seq = read_seqcount_begin(&tk_core.seq);
 
-               base = tk->tkr.base_mono;
-               nsecs = timekeeping_get_ns(&tk->tkr);
+               base = tk->tkr_mono.base;
+               nsecs = timekeeping_get_ns(&tk->tkr_mono);
 
                *offs_real = tk->offs_real;
                *offs_boot = tk->offs_boot;
index 1d91416055d5e9f05e5b6d482bc8ab490acdeeb2..ead8794b9a4e470242d37684fd04079ffbd70dec 100644 (file)
@@ -19,4 +19,11 @@ extern void timekeeping_clocktai(struct timespec *ts);
 extern int timekeeping_suspend(void);
 extern void timekeeping_resume(void);
 
+extern void do_timer(unsigned long ticks);
+extern void update_wall_time(void);
+
+extern seqlock_t jiffies_lock;
+
+#define CS_NAME_LEN    32
+
 #endif
index 2d3f5c5049394615912b09ad16a4e639cb6cba9b..2ece3aa5069cade64b8c4982e920a45bea5ba232 100644 (file)
@@ -90,8 +90,18 @@ struct tvec_base {
        struct tvec tv5;
 } ____cacheline_aligned;
 
+/*
+ * __TIMER_INITIALIZER() needs to set ->base to a valid pointer (because we've
+ * made NULL special, hint: lock_timer_base()) and we cannot get a compile time
+ * pointer to per-cpu entries because we don't know where we'll map the section,
+ * even for the boot cpu.
+ *
+ * And so we use boot_tvec_bases for boot CPU and per-cpu __tvec_bases for the
+ * rest of them.
+ */
 struct tvec_base boot_tvec_bases;
 EXPORT_SYMBOL(boot_tvec_bases);
+
 static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases;
 
 /* Functions below help us manage 'deferrable' flag */
@@ -1027,6 +1037,8 @@ int try_to_del_timer_sync(struct timer_list *timer)
 EXPORT_SYMBOL(try_to_del_timer_sync);
 
 #ifdef CONFIG_SMP
+static DEFINE_PER_CPU(struct tvec_base, __tvec_bases);
+
 /**
  * del_timer_sync - deactivate a timer and wait for the handler to finish.
  * @timer: the timer to be deactivated
@@ -1532,64 +1544,6 @@ signed long __sched schedule_timeout_uninterruptible(signed long timeout)
 }
 EXPORT_SYMBOL(schedule_timeout_uninterruptible);
 
-static int init_timers_cpu(int cpu)
-{
-       int j;
-       struct tvec_base *base;
-       static char tvec_base_done[NR_CPUS];
-
-       if (!tvec_base_done[cpu]) {
-               static char boot_done;
-
-               if (boot_done) {
-                       /*
-                        * The APs use this path later in boot
-                        */
-                       base = kzalloc_node(sizeof(*base), GFP_KERNEL,
-                                           cpu_to_node(cpu));
-                       if (!base)
-                               return -ENOMEM;
-
-                       /* Make sure tvec_base has TIMER_FLAG_MASK bits free */
-                       if (WARN_ON(base != tbase_get_base(base))) {
-                               kfree(base);
-                               return -ENOMEM;
-                       }
-                       per_cpu(tvec_bases, cpu) = base;
-               } else {
-                       /*
-                        * This is for the boot CPU - we use compile-time
-                        * static initialisation because per-cpu memory isn't
-                        * ready yet and because the memory allocators are not
-                        * initialised either.
-                        */
-                       boot_done = 1;
-                       base = &boot_tvec_bases;
-               }
-               spin_lock_init(&base->lock);
-               tvec_base_done[cpu] = 1;
-               base->cpu = cpu;
-       } else {
-               base = per_cpu(tvec_bases, cpu);
-       }
-
-
-       for (j = 0; j < TVN_SIZE; j++) {
-               INIT_LIST_HEAD(base->tv5.vec + j);
-               INIT_LIST_HEAD(base->tv4.vec + j);
-               INIT_LIST_HEAD(base->tv3.vec + j);
-               INIT_LIST_HEAD(base->tv2.vec + j);
-       }
-       for (j = 0; j < TVR_SIZE; j++)
-               INIT_LIST_HEAD(base->tv1.vec + j);
-
-       base->timer_jiffies = jiffies;
-       base->next_timer = base->timer_jiffies;
-       base->active_timers = 0;
-       base->all_timers = 0;
-       return 0;
-}
-
 #ifdef CONFIG_HOTPLUG_CPU
 static void migrate_timer_list(struct tvec_base *new_base, struct list_head *head)
 {
@@ -1631,55 +1585,86 @@ static void migrate_timers(int cpu)
                migrate_timer_list(new_base, old_base->tv5.vec + i);
        }
 
+       old_base->active_timers = 0;
+       old_base->all_timers = 0;
+
        spin_unlock(&old_base->lock);
        spin_unlock_irq(&new_base->lock);
        put_cpu_var(tvec_bases);
 }
-#endif /* CONFIG_HOTPLUG_CPU */
 
 static int timer_cpu_notify(struct notifier_block *self,
                                unsigned long action, void *hcpu)
 {
-       long cpu = (long)hcpu;
-       int err;
-
-       switch(action) {
-       case CPU_UP_PREPARE:
-       case CPU_UP_PREPARE_FROZEN:
-               err = init_timers_cpu(cpu);
-               if (err < 0)
-                       return notifier_from_errno(err);
-               break;
-#ifdef CONFIG_HOTPLUG_CPU
+       switch (action) {
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
-               migrate_timers(cpu);
+               migrate_timers((long)hcpu);
                break;
-#endif
        default:
                break;
        }
+
        return NOTIFY_OK;
 }
 
-static struct notifier_block timers_nb = {
-       .notifier_call  = timer_cpu_notify,
-};
+static inline void timer_register_cpu_notifier(void)
+{
+       cpu_notifier(timer_cpu_notify, 0);
+}
+#else
+static inline void timer_register_cpu_notifier(void) { }
+#endif /* CONFIG_HOTPLUG_CPU */
 
+static void __init init_timer_cpu(struct tvec_base *base, int cpu)
+{
+       int j;
 
-void __init init_timers(void)
+       BUG_ON(base != tbase_get_base(base));
+
+       base->cpu = cpu;
+       per_cpu(tvec_bases, cpu) = base;
+       spin_lock_init(&base->lock);
+
+       for (j = 0; j < TVN_SIZE; j++) {
+               INIT_LIST_HEAD(base->tv5.vec + j);
+               INIT_LIST_HEAD(base->tv4.vec + j);
+               INIT_LIST_HEAD(base->tv3.vec + j);
+               INIT_LIST_HEAD(base->tv2.vec + j);
+       }
+       for (j = 0; j < TVR_SIZE; j++)
+               INIT_LIST_HEAD(base->tv1.vec + j);
+
+       base->timer_jiffies = jiffies;
+       base->next_timer = base->timer_jiffies;
+}
+
+static void __init init_timer_cpus(void)
 {
-       int err;
+       struct tvec_base *base;
+       int local_cpu = smp_processor_id();
+       int cpu;
 
+       for_each_possible_cpu(cpu) {
+               if (cpu == local_cpu)
+                       base = &boot_tvec_bases;
+#ifdef CONFIG_SMP
+               else
+                       base = per_cpu_ptr(&__tvec_bases, cpu);
+#endif
+
+               init_timer_cpu(base, cpu);
+       }
+}
+
+void __init init_timers(void)
+{
        /* ensure there are enough low bits for flags in timer->base pointer */
        BUILD_BUG_ON(__alignof__(struct tvec_base) & TIMER_FLAG_MASK);
 
-       err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
-                              (void *)(long)smp_processor_id());
-       BUG_ON(err != NOTIFY_OK);
-
+       init_timer_cpus();
        init_timer_stats();
-       register_cpu_notifier(&timers_nb);
+       timer_register_cpu_notifier();
        open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
 }
 
index 61ed862cdd376222dedfa317301f3d6c3dbd3404..e878c2e0ba45e06c4690646a8853406e11dd1a15 100644 (file)
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/kallsyms.h>
-#include <linux/tick.h>
 
 #include <asm/uaccess.h>
 
+#include "tick-internal.h"
 
 struct timer_list_iter {
        int cpu;
@@ -228,9 +228,35 @@ print_tickdevice(struct seq_file *m, struct tick_device *td, int cpu)
        print_name_offset(m, dev->set_next_event);
        SEQ_printf(m, "\n");
 
-       SEQ_printf(m, " set_mode:       ");
-       print_name_offset(m, dev->set_mode);
-       SEQ_printf(m, "\n");
+       if (dev->set_mode) {
+               SEQ_printf(m, " set_mode:       ");
+               print_name_offset(m, dev->set_mode);
+               SEQ_printf(m, "\n");
+       } else {
+               if (dev->set_state_shutdown) {
+                       SEQ_printf(m, " shutdown: ");
+                       print_name_offset(m, dev->set_state_shutdown);
+                       SEQ_printf(m, "\n");
+               }
+
+               if (dev->set_state_periodic) {
+                       SEQ_printf(m, " periodic: ");
+                       print_name_offset(m, dev->set_state_periodic);
+                       SEQ_printf(m, "\n");
+               }
+
+               if (dev->set_state_oneshot) {
+                       SEQ_printf(m, " oneshot:  ");
+                       print_name_offset(m, dev->set_state_oneshot);
+                       SEQ_printf(m, "\n");
+               }
+
+               if (dev->tick_resume) {
+                       SEQ_printf(m, " resume:   ");
+                       print_name_offset(m, dev->tick_resume);
+                       SEQ_printf(m, "\n");
+               }
+       }
 
        SEQ_printf(m, " event_handler:  ");
        print_name_offset(m, dev->event_handler);
index a5da09c899dd69fde9dce7f783d5a0fdc27a41c1..3b9a48ae153ac85c5f601b03ef64c7e9d49f153c 100644 (file)
@@ -432,6 +432,14 @@ config UPROBE_EVENT
          This option is required if you plan to use perf-probe subcommand
          of perf tools on user space applications.
 
+config BPF_EVENTS
+       depends on BPF_SYSCALL
+       depends on KPROBE_EVENT
+       bool
+       default y
+       help
+         This allows the user to attach BPF programs to kprobe events.
+
 config PROBE_EVENTS
        def_bool n
 
@@ -599,6 +607,34 @@ config RING_BUFFER_STARTUP_TEST
 
         If unsure, say N
 
+config TRACE_ENUM_MAP_FILE
+       bool "Show enum mappings for trace events"
+       depends on TRACING
+       help
+        The "print fmt" of the trace events will show the enum names instead
+       of their values. This can cause problems for user space tools that
+       use this string to parse the raw data as user space does not know
+       how to convert the string to its value.
+
+       To fix this, there's a special macro in the kernel that can be used
+       to convert the enum into its value. If this macro is used, then the
+       print fmt strings will have the enums converted to their values.
+
+       If something does not get converted properly, this option can be
+       used to show what enums the kernel tried to convert.
+
+       This option is for debugging the enum conversions. A file is created
+       in the tracing directory called "enum_map" that will show the enum
+       names matched with their values and what trace event system they
+       belong too.
+
+       Normally, the mapping of the strings to values will be freed after
+       boot up or module load. With this option, they will not be freed, as
+       they are needed for the "enum_map" file. Enabling this option will
+       increase the memory footprint of the running kernel.
+
+       If unsure, say N
+
 endif # FTRACE
 
 endif # TRACING_SUPPORT
index 98f26588255ec7ed18a37b71be71ec2d6405afad..9b1044e936a6fae78c218a4d14782fc77bc90645 100644 (file)
@@ -53,6 +53,7 @@ obj-$(CONFIG_EVENT_TRACING) += trace_event_perf.o
 endif
 obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
 obj-$(CONFIG_EVENT_TRACING) += trace_events_trigger.o
+obj-$(CONFIG_BPF_EVENTS) += bpf_trace.o
 obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o
 obj-$(CONFIG_TRACEPOINTS) += power-traces.o
 ifeq ($(CONFIG_PM),y)
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
new file mode 100644 (file)
index 0000000..2d56ce5
--- /dev/null
@@ -0,0 +1,222 @@
+/* Copyright (c) 2011-2015 PLUMgrid, http://plumgrid.com
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/bpf.h>
+#include <linux/filter.h>
+#include <linux/uaccess.h>
+#include <linux/ctype.h>
+#include "trace.h"
+
+static DEFINE_PER_CPU(int, bpf_prog_active);
+
+/**
+ * trace_call_bpf - invoke BPF program
+ * @prog: BPF program
+ * @ctx: opaque context pointer
+ *
+ * kprobe handlers execute BPF programs via this helper.
+ * Can be used from static tracepoints in the future.
+ *
+ * Return: BPF programs always return an integer which is interpreted by
+ * kprobe handler as:
+ * 0 - return from kprobe (event is filtered out)
+ * 1 - store kprobe event into ring buffer
+ * Other values are reserved and currently alias to 1
+ */
+unsigned int trace_call_bpf(struct bpf_prog *prog, void *ctx)
+{
+       unsigned int ret;
+
+       if (in_nmi()) /* not supported yet */
+               return 1;
+
+       preempt_disable();
+
+       if (unlikely(__this_cpu_inc_return(bpf_prog_active) != 1)) {
+               /*
+                * since some bpf program is already running on this cpu,
+                * don't call into another bpf program (same or different)
+                * and don't send kprobe event into ring-buffer,
+                * so return zero here
+                */
+               ret = 0;
+               goto out;
+       }
+
+       rcu_read_lock();
+       ret = BPF_PROG_RUN(prog, ctx);
+       rcu_read_unlock();
+
+ out:
+       __this_cpu_dec(bpf_prog_active);
+       preempt_enable();
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(trace_call_bpf);
+
+static u64 bpf_probe_read(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
+{
+       void *dst = (void *) (long) r1;
+       int size = (int) r2;
+       void *unsafe_ptr = (void *) (long) r3;
+
+       return probe_kernel_read(dst, unsafe_ptr, size);
+}
+
+static const struct bpf_func_proto bpf_probe_read_proto = {
+       .func           = bpf_probe_read,
+       .gpl_only       = true,
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_STACK,
+       .arg2_type      = ARG_CONST_STACK_SIZE,
+       .arg3_type      = ARG_ANYTHING,
+};
+
+static u64 bpf_ktime_get_ns(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
+{
+       /* NMI safe access to clock monotonic */
+       return ktime_get_mono_fast_ns();
+}
+
+static const struct bpf_func_proto bpf_ktime_get_ns_proto = {
+       .func           = bpf_ktime_get_ns,
+       .gpl_only       = true,
+       .ret_type       = RET_INTEGER,
+};
+
+/*
+ * limited trace_printk()
+ * only %d %u %x %ld %lu %lx %lld %llu %llx %p conversion specifiers allowed
+ */
+static u64 bpf_trace_printk(u64 r1, u64 fmt_size, u64 r3, u64 r4, u64 r5)
+{
+       char *fmt = (char *) (long) r1;
+       int mod[3] = {};
+       int fmt_cnt = 0;
+       int i;
+
+       /*
+        * bpf_check()->check_func_arg()->check_stack_boundary()
+        * guarantees that fmt points to bpf program stack,
+        * fmt_size bytes of it were initialized and fmt_size > 0
+        */
+       if (fmt[--fmt_size] != 0)
+               return -EINVAL;
+
+       /* check format string for allowed specifiers */
+       for (i = 0; i < fmt_size; i++) {
+               if ((!isprint(fmt[i]) && !isspace(fmt[i])) || !isascii(fmt[i]))
+                       return -EINVAL;
+
+               if (fmt[i] != '%')
+                       continue;
+
+               if (fmt_cnt >= 3)
+                       return -EINVAL;
+
+               /* fmt[i] != 0 && fmt[last] == 0, so we can access fmt[i + 1] */
+               i++;
+               if (fmt[i] == 'l') {
+                       mod[fmt_cnt]++;
+                       i++;
+               } else if (fmt[i] == 'p') {
+                       mod[fmt_cnt]++;
+                       i++;
+                       if (!isspace(fmt[i]) && !ispunct(fmt[i]) && fmt[i] != 0)
+                               return -EINVAL;
+                       fmt_cnt++;
+                       continue;
+               }
+
+               if (fmt[i] == 'l') {
+                       mod[fmt_cnt]++;
+                       i++;
+               }
+
+               if (fmt[i] != 'd' && fmt[i] != 'u' && fmt[i] != 'x')
+                       return -EINVAL;
+               fmt_cnt++;
+       }
+
+       return __trace_printk(1/* fake ip will not be printed */, fmt,
+                             mod[0] == 2 ? r3 : mod[0] == 1 ? (long) r3 : (u32) r3,
+                             mod[1] == 2 ? r4 : mod[1] == 1 ? (long) r4 : (u32) r4,
+                             mod[2] == 2 ? r5 : mod[2] == 1 ? (long) r5 : (u32) r5);
+}
+
+static const struct bpf_func_proto bpf_trace_printk_proto = {
+       .func           = bpf_trace_printk,
+       .gpl_only       = true,
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_STACK,
+       .arg2_type      = ARG_CONST_STACK_SIZE,
+};
+
+static const struct bpf_func_proto *kprobe_prog_func_proto(enum bpf_func_id func_id)
+{
+       switch (func_id) {
+       case BPF_FUNC_map_lookup_elem:
+               return &bpf_map_lookup_elem_proto;
+       case BPF_FUNC_map_update_elem:
+               return &bpf_map_update_elem_proto;
+       case BPF_FUNC_map_delete_elem:
+               return &bpf_map_delete_elem_proto;
+       case BPF_FUNC_probe_read:
+               return &bpf_probe_read_proto;
+       case BPF_FUNC_ktime_get_ns:
+               return &bpf_ktime_get_ns_proto;
+
+       case BPF_FUNC_trace_printk:
+               /*
+                * this program might be calling bpf_trace_printk,
+                * so allocate per-cpu printk buffers
+                */
+               trace_printk_init_buffers();
+
+               return &bpf_trace_printk_proto;
+       default:
+               return NULL;
+       }
+}
+
+/* bpf+kprobe programs can access fields of 'struct pt_regs' */
+static bool kprobe_prog_is_valid_access(int off, int size, enum bpf_access_type type)
+{
+       /* check bounds */
+       if (off < 0 || off >= sizeof(struct pt_regs))
+               return false;
+
+       /* only read is allowed */
+       if (type != BPF_READ)
+               return false;
+
+       /* disallow misaligned access */
+       if (off % size != 0)
+               return false;
+
+       return true;
+}
+
+static struct bpf_verifier_ops kprobe_prog_ops = {
+       .get_func_proto  = kprobe_prog_func_proto,
+       .is_valid_access = kprobe_prog_is_valid_access,
+};
+
+static struct bpf_prog_type_list kprobe_tl = {
+       .ops    = &kprobe_prog_ops,
+       .type   = BPF_PROG_TYPE_KPROBE,
+};
+
+static int __init register_kprobe_prog_ops(void)
+{
+       bpf_register_prog_type(&kprobe_tl);
+       return 0;
+}
+late_initcall(register_kprobe_prog_ops);
index 4f228024055b119d93279705ec4c42d7475c72f7..02bece4a99ea36bb835fc45a9aa55c1aedd69f9f 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/kallsyms.h>
 #include <linux/seq_file.h>
 #include <linux/suspend.h>
-#include <linux/debugfs.h>
+#include <linux/tracefs.h>
 #include <linux/hardirq.h>
 #include <linux/kthread.h>
 #include <linux/uaccess.h>
@@ -249,6 +249,19 @@ static void update_function_graph_func(void);
 static inline void update_function_graph_func(void) { }
 #endif
 
+
+static ftrace_func_t ftrace_ops_get_list_func(struct ftrace_ops *ops)
+{
+       /*
+        * If this is a dynamic ops or we force list func,
+        * then it needs to call the list anyway.
+        */
+       if (ops->flags & FTRACE_OPS_FL_DYNAMIC || FTRACE_FORCE_LIST_FUNC)
+               return ftrace_ops_list_func;
+
+       return ftrace_ops_get_func(ops);
+}
+
 static void update_ftrace_function(void)
 {
        ftrace_func_t func;
@@ -270,7 +283,7 @@ static void update_ftrace_function(void)
         * then have the mcount trampoline call the function directly.
         */
        } else if (ftrace_ops_list->next == &ftrace_list_end) {
-               func = ftrace_ops_get_func(ftrace_ops_list);
+               func = ftrace_ops_get_list_func(ftrace_ops_list);
 
        } else {
                /* Just use the default ftrace_ops */
@@ -1008,7 +1021,7 @@ static struct tracer_stat function_stats __initdata = {
        .stat_show      = function_stat_show
 };
 
-static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
+static __init void ftrace_profile_tracefs(struct dentry *d_tracer)
 {
        struct ftrace_profile_stat *stat;
        struct dentry *entry;
@@ -1044,15 +1057,15 @@ static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
                }
        }
 
-       entry = debugfs_create_file("function_profile_enabled", 0644,
+       entry = tracefs_create_file("function_profile_enabled", 0644,
                                    d_tracer, NULL, &ftrace_profile_fops);
        if (!entry)
-               pr_warning("Could not create debugfs "
+               pr_warning("Could not create tracefs "
                           "'function_profile_enabled' entry\n");
 }
 
 #else /* CONFIG_FUNCTION_PROFILER */
-static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
+static __init void ftrace_profile_tracefs(struct dentry *d_tracer)
 {
 }
 #endif /* CONFIG_FUNCTION_PROFILER */
@@ -4712,7 +4725,7 @@ void ftrace_destroy_filter_files(struct ftrace_ops *ops)
        mutex_unlock(&ftrace_lock);
 }
 
-static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
+static __init int ftrace_init_dyn_tracefs(struct dentry *d_tracer)
 {
 
        trace_create_file("available_filter_functions", 0444,
@@ -5020,7 +5033,7 @@ static int __init ftrace_nodyn_init(void)
 }
 core_initcall(ftrace_nodyn_init);
 
-static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; }
+static inline int ftrace_init_dyn_tracefs(struct dentry *d_tracer) { return 0; }
 static inline void ftrace_startup_enable(int command) { }
 static inline void ftrace_startup_all(int command) { }
 /* Keep as macros so we do not need to define the commands */
@@ -5208,13 +5221,6 @@ static void ftrace_ops_recurs_func(unsigned long ip, unsigned long parent_ip,
  */
 ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops)
 {
-       /*
-        * If this is a dynamic ops or we force list func,
-        * then it needs to call the list anyway.
-        */
-       if (ops->flags & FTRACE_OPS_FL_DYNAMIC || FTRACE_FORCE_LIST_FUNC)
-               return ftrace_ops_list_func;
-
        /*
         * If the func handles its own recursion, call it directly.
         * Otherwise call the recursion protected function that
@@ -5473,7 +5479,7 @@ static const struct file_operations ftrace_pid_fops = {
        .release        = ftrace_pid_release,
 };
 
-static __init int ftrace_init_debugfs(void)
+static __init int ftrace_init_tracefs(void)
 {
        struct dentry *d_tracer;
 
@@ -5481,16 +5487,16 @@ static __init int ftrace_init_debugfs(void)
        if (IS_ERR(d_tracer))
                return 0;
 
-       ftrace_init_dyn_debugfs(d_tracer);
+       ftrace_init_dyn_tracefs(d_tracer);
 
        trace_create_file("set_ftrace_pid", 0644, d_tracer,
                            NULL, &ftrace_pid_fops);
 
-       ftrace_profile_debugfs(d_tracer);
+       ftrace_profile_tracefs(d_tracer);
 
        return 0;
 }
-fs_initcall(ftrace_init_debugfs);
+fs_initcall(ftrace_init_tracefs);
 
 /**
  * ftrace_kill - kill ftrace
index 5040d44fe5a3cf422bab79c1395e53703a394733..0315d43176d80d264c37f22ba403a5089a124c48 100644 (file)
@@ -2679,7 +2679,7 @@ static DEFINE_PER_CPU(unsigned int, current_context);
 
 static __always_inline int trace_recursive_lock(void)
 {
-       unsigned int val = this_cpu_read(current_context);
+       unsigned int val = __this_cpu_read(current_context);
        int bit;
 
        if (in_interrupt()) {
@@ -2696,18 +2696,14 @@ static __always_inline int trace_recursive_lock(void)
                return 1;
 
        val |= (1 << bit);
-       this_cpu_write(current_context, val);
+       __this_cpu_write(current_context, val);
 
        return 0;
 }
 
 static __always_inline void trace_recursive_unlock(void)
 {
-       unsigned int val = this_cpu_read(current_context);
-
-       val--;
-       val &= this_cpu_read(current_context);
-       this_cpu_write(current_context, val);
+       __this_cpu_and(current_context, __this_cpu_read(current_context) - 1);
 }
 
 #else
index 62c6506d663fa11e79128759bd03103d12ed7c0f..91eecaaa43e0aeaceea2c513a4decc02cf3e981d 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/notifier.h>
 #include <linux/irqflags.h>
 #include <linux/debugfs.h>
+#include <linux/tracefs.h>
 #include <linux/pagemap.h>
 #include <linux/hardirq.h>
 #include <linux/linkage.h>
@@ -31,6 +32,7 @@
 #include <linux/splice.h>
 #include <linux/kdebug.h>
 #include <linux/string.h>
+#include <linux/mount.h>
 #include <linux/rwsem.h>
 #include <linux/slab.h>
 #include <linux/ctype.h>
@@ -123,6 +125,42 @@ enum ftrace_dump_mode ftrace_dump_on_oops;
 /* When set, tracing will stop when a WARN*() is hit */
 int __disable_trace_on_warning;
 
+#ifdef CONFIG_TRACE_ENUM_MAP_FILE
+/* Map of enums to their values, for "enum_map" file */
+struct trace_enum_map_head {
+       struct module                   *mod;
+       unsigned long                   length;
+};
+
+union trace_enum_map_item;
+
+struct trace_enum_map_tail {
+       /*
+        * "end" is first and points to NULL as it must be different
+        * than "mod" or "enum_string"
+        */
+       union trace_enum_map_item       *next;
+       const char                      *end;   /* points to NULL */
+};
+
+static DEFINE_MUTEX(trace_enum_mutex);
+
+/*
+ * The trace_enum_maps are saved in an array with two extra elements,
+ * one at the beginning, and one at the end. The beginning item contains
+ * the count of the saved maps (head.length), and the module they
+ * belong to if not built in (head.mod). The ending item contains a
+ * pointer to the next array of saved enum_map items.
+ */
+union trace_enum_map_item {
+       struct trace_enum_map           map;
+       struct trace_enum_map_head      head;
+       struct trace_enum_map_tail      tail;
+};
+
+static union trace_enum_map_item *trace_enum_maps;
+#endif /* CONFIG_TRACE_ENUM_MAP_FILE */
+
 static int tracing_set_tracer(struct trace_array *tr, const char *buf);
 
 #define MAX_TRACER_SIZE                100
@@ -3908,6 +3946,182 @@ static const struct file_operations tracing_saved_cmdlines_size_fops = {
        .write          = tracing_saved_cmdlines_size_write,
 };
 
+#ifdef CONFIG_TRACE_ENUM_MAP_FILE
+static union trace_enum_map_item *
+update_enum_map(union trace_enum_map_item *ptr)
+{
+       if (!ptr->map.enum_string) {
+               if (ptr->tail.next) {
+                       ptr = ptr->tail.next;
+                       /* Set ptr to the next real item (skip head) */
+                       ptr++;
+               } else
+                       return NULL;
+       }
+       return ptr;
+}
+
+static void *enum_map_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       union trace_enum_map_item *ptr = v;
+
+       /*
+        * Paranoid! If ptr points to end, we don't want to increment past it.
+        * This really should never happen.
+        */
+       ptr = update_enum_map(ptr);
+       if (WARN_ON_ONCE(!ptr))
+               return NULL;
+
+       ptr++;
+
+       (*pos)++;
+
+       ptr = update_enum_map(ptr);
+
+       return ptr;
+}
+
+static void *enum_map_start(struct seq_file *m, loff_t *pos)
+{
+       union trace_enum_map_item *v;
+       loff_t l = 0;
+
+       mutex_lock(&trace_enum_mutex);
+
+       v = trace_enum_maps;
+       if (v)
+               v++;
+
+       while (v && l < *pos) {
+               v = enum_map_next(m, v, &l);
+       }
+
+       return v;
+}
+
+static void enum_map_stop(struct seq_file *m, void *v)
+{
+       mutex_unlock(&trace_enum_mutex);
+}
+
+static int enum_map_show(struct seq_file *m, void *v)
+{
+       union trace_enum_map_item *ptr = v;
+
+       seq_printf(m, "%s %ld (%s)\n",
+                  ptr->map.enum_string, ptr->map.enum_value,
+                  ptr->map.system);
+
+       return 0;
+}
+
+static const struct seq_operations tracing_enum_map_seq_ops = {
+       .start          = enum_map_start,
+       .next           = enum_map_next,
+       .stop           = enum_map_stop,
+       .show           = enum_map_show,
+};
+
+static int tracing_enum_map_open(struct inode *inode, struct file *filp)
+{
+       if (tracing_disabled)
+               return -ENODEV;
+
+       return seq_open(filp, &tracing_enum_map_seq_ops);
+}
+
+static const struct file_operations tracing_enum_map_fops = {
+       .open           = tracing_enum_map_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static inline union trace_enum_map_item *
+trace_enum_jmp_to_tail(union trace_enum_map_item *ptr)
+{
+       /* Return tail of array given the head */
+       return ptr + ptr->head.length + 1;
+}
+
+static void
+trace_insert_enum_map_file(struct module *mod, struct trace_enum_map **start,
+                          int len)
+{
+       struct trace_enum_map **stop;
+       struct trace_enum_map **map;
+       union trace_enum_map_item *map_array;
+       union trace_enum_map_item *ptr;
+
+       stop = start + len;
+
+       /*
+        * The trace_enum_maps contains the map plus a head and tail item,
+        * where the head holds the module and length of array, and the
+        * tail holds a pointer to the next list.
+        */
+       map_array = kmalloc(sizeof(*map_array) * (len + 2), GFP_KERNEL);
+       if (!map_array) {
+               pr_warning("Unable to allocate trace enum mapping\n");
+               return;
+       }
+
+       mutex_lock(&trace_enum_mutex);
+
+       if (!trace_enum_maps)
+               trace_enum_maps = map_array;
+       else {
+               ptr = trace_enum_maps;
+               for (;;) {
+                       ptr = trace_enum_jmp_to_tail(ptr);
+                       if (!ptr->tail.next)
+                               break;
+                       ptr = ptr->tail.next;
+
+               }
+               ptr->tail.next = map_array;
+       }
+       map_array->head.mod = mod;
+       map_array->head.length = len;
+       map_array++;
+
+       for (map = start; (unsigned long)map < (unsigned long)stop; map++) {
+               map_array->map = **map;
+               map_array++;
+       }
+       memset(map_array, 0, sizeof(*map_array));
+
+       mutex_unlock(&trace_enum_mutex);
+}
+
+static void trace_create_enum_file(struct dentry *d_tracer)
+{
+       trace_create_file("enum_map", 0444, d_tracer,
+                         NULL, &tracing_enum_map_fops);
+}
+
+#else /* CONFIG_TRACE_ENUM_MAP_FILE */
+static inline void trace_create_enum_file(struct dentry *d_tracer) { }
+static inline void trace_insert_enum_map_file(struct module *mod,
+                             struct trace_enum_map **start, int len) { }
+#endif /* !CONFIG_TRACE_ENUM_MAP_FILE */
+
+static void trace_insert_enum_map(struct module *mod,
+                                 struct trace_enum_map **start, int len)
+{
+       struct trace_enum_map **map;
+
+       if (len <= 0)
+               return;
+
+       map = start;
+
+       trace_event_enum_update(map, len);
+
+       trace_insert_enum_map_file(mod, start, len);
+}
+
 static ssize_t
 tracing_set_trace_read(struct file *filp, char __user *ubuf,
                       size_t cnt, loff_t *ppos)
@@ -4105,9 +4319,24 @@ static void tracing_set_nop(struct trace_array *tr)
        tr->current_trace = &nop_trace;
 }
 
-static int tracing_set_tracer(struct trace_array *tr, const char *buf)
+static void update_tracer_options(struct trace_array *tr, struct tracer *t)
 {
        static struct trace_option_dentry *topts;
+
+       /* Only enable if the directory has been created already. */
+       if (!tr->dir)
+               return;
+
+       /* Currently, only the top instance has options */
+       if (!(tr->flags & TRACE_ARRAY_FL_GLOBAL))
+               return;
+
+       destroy_trace_option_files(topts);
+       topts = create_trace_option_files(tr, t);
+}
+
+static int tracing_set_tracer(struct trace_array *tr, const char *buf)
+{
        struct tracer *t;
 #ifdef CONFIG_TRACER_MAX_TRACE
        bool had_max_tr;
@@ -4172,11 +4401,7 @@ static int tracing_set_tracer(struct trace_array *tr, const char *buf)
                free_snapshot(tr);
        }
 #endif
-       /* Currently, only the top instance has options */
-       if (tr->flags & TRACE_ARRAY_FL_GLOBAL) {
-               destroy_trace_option_files(topts);
-               topts = create_trace_option_files(tr, t);
-       }
+       update_tracer_options(tr, t);
 
 #ifdef CONFIG_TRACER_MAX_TRACE
        if (t->use_max_tr && !had_max_tr) {
@@ -5817,6 +6042,14 @@ static inline __init int register_snapshot_cmd(void) { return 0; }
 
 static struct dentry *tracing_get_dentry(struct trace_array *tr)
 {
+       if (WARN_ON(!tr->dir))
+               return ERR_PTR(-ENODEV);
+
+       /* Top directory uses NULL as the parent */
+       if (tr->flags & TRACE_ARRAY_FL_GLOBAL)
+               return NULL;
+
+       /* All sub buffers have a descriptor */
        return tr->dir;
 }
 
@@ -5831,10 +6064,10 @@ static struct dentry *tracing_dentry_percpu(struct trace_array *tr, int cpu)
        if (IS_ERR(d_tracer))
                return NULL;
 
-       tr->percpu_dir = debugfs_create_dir("per_cpu", d_tracer);
+       tr->percpu_dir = tracefs_create_dir("per_cpu", d_tracer);
 
        WARN_ONCE(!tr->percpu_dir,
-                 "Could not create debugfs directory 'per_cpu/%d'\n", cpu);
+                 "Could not create tracefs directory 'per_cpu/%d'\n", cpu);
 
        return tr->percpu_dir;
 }
@@ -5851,7 +6084,7 @@ trace_create_cpu_file(const char *name, umode_t mode, struct dentry *parent,
 }
 
 static void
-tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
+tracing_init_tracefs_percpu(struct trace_array *tr, long cpu)
 {
        struct dentry *d_percpu = tracing_dentry_percpu(tr, cpu);
        struct dentry *d_cpu;
@@ -5861,9 +6094,9 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
                return;
 
        snprintf(cpu_dir, 30, "cpu%ld", cpu);
-       d_cpu = debugfs_create_dir(cpu_dir, d_percpu);
+       d_cpu = tracefs_create_dir(cpu_dir, d_percpu);
        if (!d_cpu) {
-               pr_warning("Could not create debugfs '%s' entry\n", cpu_dir);
+               pr_warning("Could not create tracefs '%s' entry\n", cpu_dir);
                return;
        }
 
@@ -6015,9 +6248,9 @@ struct dentry *trace_create_file(const char *name,
 {
        struct dentry *ret;
 
-       ret = debugfs_create_file(name, mode, parent, data, fops);
+       ret = tracefs_create_file(name, mode, parent, data, fops);
        if (!ret)
-               pr_warning("Could not create debugfs '%s' entry\n", name);
+               pr_warning("Could not create tracefs '%s' entry\n", name);
 
        return ret;
 }
@@ -6034,9 +6267,9 @@ static struct dentry *trace_options_init_dentry(struct trace_array *tr)
        if (IS_ERR(d_tracer))
                return NULL;
 
-       tr->options = debugfs_create_dir("options", d_tracer);
+       tr->options = tracefs_create_dir("options", d_tracer);
        if (!tr->options) {
-               pr_warning("Could not create debugfs directory 'options'\n");
+               pr_warning("Could not create tracefs directory 'options'\n");
                return NULL;
        }
 
@@ -6105,7 +6338,7 @@ destroy_trace_option_files(struct trace_option_dentry *topts)
                return;
 
        for (cnt = 0; topts[cnt].opt; cnt++)
-               debugfs_remove(topts[cnt].entry);
+               tracefs_remove(topts[cnt].entry);
 
        kfree(topts);
 }
@@ -6194,7 +6427,7 @@ static const struct file_operations rb_simple_fops = {
 struct dentry *trace_instance_dir;
 
 static void
-init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer);
+init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer);
 
 static int
 allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int size)
@@ -6271,7 +6504,7 @@ static void free_trace_buffers(struct trace_array *tr)
 #endif
 }
 
-static int new_instance_create(const char *name)
+static int instance_mkdir(const char *name)
 {
        struct trace_array *tr;
        int ret;
@@ -6310,17 +6543,17 @@ static int new_instance_create(const char *name)
        if (allocate_trace_buffers(tr, trace_buf_size) < 0)
                goto out_free_tr;
 
-       tr->dir = debugfs_create_dir(name, trace_instance_dir);
+       tr->dir = tracefs_create_dir(name, trace_instance_dir);
        if (!tr->dir)
                goto out_free_tr;
 
        ret = event_trace_add_tracer(tr->dir, tr);
        if (ret) {
-               debugfs_remove_recursive(tr->dir);
+               tracefs_remove_recursive(tr->dir);
                goto out_free_tr;
        }
 
-       init_tracer_debugfs(tr, tr->dir);
+       init_tracer_tracefs(tr, tr->dir);
 
        list_add(&tr->list, &ftrace_trace_arrays);
 
@@ -6341,7 +6574,7 @@ static int new_instance_create(const char *name)
 
 }
 
-static int instance_delete(const char *name)
+static int instance_rmdir(const char *name)
 {
        struct trace_array *tr;
        int found = 0;
@@ -6382,82 +6615,17 @@ static int instance_delete(const char *name)
        return ret;
 }
 
-static int instance_mkdir (struct inode *inode, struct dentry *dentry, umode_t mode)
-{
-       struct dentry *parent;
-       int ret;
-
-       /* Paranoid: Make sure the parent is the "instances" directory */
-       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
-       if (WARN_ON_ONCE(parent != trace_instance_dir))
-               return -ENOENT;
-
-       /*
-        * The inode mutex is locked, but debugfs_create_dir() will also
-        * take the mutex. As the instances directory can not be destroyed
-        * or changed in any other way, it is safe to unlock it, and
-        * let the dentry try. If two users try to make the same dir at
-        * the same time, then the new_instance_create() will determine the
-        * winner.
-        */
-       mutex_unlock(&inode->i_mutex);
-
-       ret = new_instance_create(dentry->d_iname);
-
-       mutex_lock(&inode->i_mutex);
-
-       return ret;
-}
-
-static int instance_rmdir(struct inode *inode, struct dentry *dentry)
-{
-       struct dentry *parent;
-       int ret;
-
-       /* Paranoid: Make sure the parent is the "instances" directory */
-       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
-       if (WARN_ON_ONCE(parent != trace_instance_dir))
-               return -ENOENT;
-
-       /* The caller did a dget() on dentry */
-       mutex_unlock(&dentry->d_inode->i_mutex);
-
-       /*
-        * The inode mutex is locked, but debugfs_create_dir() will also
-        * take the mutex. As the instances directory can not be destroyed
-        * or changed in any other way, it is safe to unlock it, and
-        * let the dentry try. If two users try to make the same dir at
-        * the same time, then the instance_delete() will determine the
-        * winner.
-        */
-       mutex_unlock(&inode->i_mutex);
-
-       ret = instance_delete(dentry->d_iname);
-
-       mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
-       mutex_lock(&dentry->d_inode->i_mutex);
-
-       return ret;
-}
-
-static const struct inode_operations instance_dir_inode_operations = {
-       .lookup         = simple_lookup,
-       .mkdir          = instance_mkdir,
-       .rmdir          = instance_rmdir,
-};
-
 static __init void create_trace_instances(struct dentry *d_tracer)
 {
-       trace_instance_dir = debugfs_create_dir("instances", d_tracer);
+       trace_instance_dir = tracefs_create_instance_dir("instances", d_tracer,
+                                                        instance_mkdir,
+                                                        instance_rmdir);
        if (WARN_ON(!trace_instance_dir))
                return;
-
-       /* Hijack the dir inode operations, to allow mkdir */
-       trace_instance_dir->d_inode->i_op = &instance_dir_inode_operations;
 }
 
 static void
-init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer)
+init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
 {
        int cpu;
 
@@ -6511,10 +6679,32 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer)
 #endif
 
        for_each_tracing_cpu(cpu)
-               tracing_init_debugfs_percpu(tr, cpu);
+               tracing_init_tracefs_percpu(tr, cpu);
 
 }
 
+static struct vfsmount *trace_automount(void *ingore)
+{
+       struct vfsmount *mnt;
+       struct file_system_type *type;
+
+       /*
+        * To maintain backward compatibility for tools that mount
+        * debugfs to get to the tracing facility, tracefs is automatically
+        * mounted to the debugfs/tracing directory.
+        */
+       type = get_fs_type("tracefs");
+       if (!type)
+               return NULL;
+       mnt = vfs_kern_mount(type, 0, "tracefs", NULL);
+       put_filesystem(type);
+       if (IS_ERR(mnt))
+               return NULL;
+       mntget(mnt);
+
+       return mnt;
+}
+
 /**
  * tracing_init_dentry - initialize top level trace array
  *
@@ -6526,23 +6716,112 @@ struct dentry *tracing_init_dentry(void)
 {
        struct trace_array *tr = &global_trace;
 
+       /* The top level trace array uses  NULL as parent */
        if (tr->dir)
-               return tr->dir;
+               return NULL;
 
        if (WARN_ON(!debugfs_initialized()))
                return ERR_PTR(-ENODEV);
 
-       tr->dir = debugfs_create_dir("tracing", NULL);
-
+       /*
+        * As there may still be users that expect the tracing
+        * files to exist in debugfs/tracing, we must automount
+        * the tracefs file system there, so older tools still
+        * work with the newer kerenl.
+        */
+       tr->dir = debugfs_create_automount("tracing", NULL,
+                                          trace_automount, NULL);
        if (!tr->dir) {
                pr_warn_once("Could not create debugfs directory 'tracing'\n");
                return ERR_PTR(-ENOMEM);
        }
 
-       return tr->dir;
+       return NULL;
+}
+
+extern struct trace_enum_map *__start_ftrace_enum_maps[];
+extern struct trace_enum_map *__stop_ftrace_enum_maps[];
+
+static void __init trace_enum_init(void)
+{
+       int len;
+
+       len = __stop_ftrace_enum_maps - __start_ftrace_enum_maps;
+       trace_insert_enum_map(NULL, __start_ftrace_enum_maps, len);
+}
+
+#ifdef CONFIG_MODULES
+static void trace_module_add_enums(struct module *mod)
+{
+       if (!mod->num_trace_enums)
+               return;
+
+       /*
+        * Modules with bad taint do not have events created, do
+        * not bother with enums either.
+        */
+       if (trace_module_has_bad_taint(mod))
+               return;
+
+       trace_insert_enum_map(mod, mod->trace_enums, mod->num_trace_enums);
 }
 
-static __init int tracer_init_debugfs(void)
+#ifdef CONFIG_TRACE_ENUM_MAP_FILE
+static void trace_module_remove_enums(struct module *mod)
+{
+       union trace_enum_map_item *map;
+       union trace_enum_map_item **last = &trace_enum_maps;
+
+       if (!mod->num_trace_enums)
+               return;
+
+       mutex_lock(&trace_enum_mutex);
+
+       map = trace_enum_maps;
+
+       while (map) {
+               if (map->head.mod == mod)
+                       break;
+               map = trace_enum_jmp_to_tail(map);
+               last = &map->tail.next;
+               map = map->tail.next;
+       }
+       if (!map)
+               goto out;
+
+       *last = trace_enum_jmp_to_tail(map)->tail.next;
+       kfree(map);
+ out:
+       mutex_unlock(&trace_enum_mutex);
+}
+#else
+static inline void trace_module_remove_enums(struct module *mod) { }
+#endif /* CONFIG_TRACE_ENUM_MAP_FILE */
+
+static int trace_module_notify(struct notifier_block *self,
+                              unsigned long val, void *data)
+{
+       struct module *mod = data;
+
+       switch (val) {
+       case MODULE_STATE_COMING:
+               trace_module_add_enums(mod);
+               break;
+       case MODULE_STATE_GOING:
+               trace_module_remove_enums(mod);
+               break;
+       }
+
+       return 0;
+}
+
+static struct notifier_block trace_module_nb = {
+       .notifier_call = trace_module_notify,
+       .priority = 0,
+};
+#endif /* CONFIG_MODULES */
+
+static __init int tracer_init_tracefs(void)
 {
        struct dentry *d_tracer;
 
@@ -6552,7 +6831,7 @@ static __init int tracer_init_debugfs(void)
        if (IS_ERR(d_tracer))
                return 0;
 
-       init_tracer_debugfs(&global_trace, d_tracer);
+       init_tracer_tracefs(&global_trace, d_tracer);
 
        trace_create_file("tracing_thresh", 0644, d_tracer,
                        &global_trace, &tracing_thresh_fops);
@@ -6566,6 +6845,14 @@ static __init int tracer_init_debugfs(void)
        trace_create_file("saved_cmdlines_size", 0644, d_tracer,
                          NULL, &tracing_saved_cmdlines_size_fops);
 
+       trace_enum_init();
+
+       trace_create_enum_file(d_tracer);
+
+#ifdef CONFIG_MODULES
+       register_module_notifier(&trace_module_nb);
+#endif
+
 #ifdef CONFIG_DYNAMIC_FTRACE
        trace_create_file("dyn_ftrace_total_info", 0444, d_tracer,
                        &ftrace_update_tot_cnt, &tracing_dyn_info_fops);
@@ -6575,6 +6862,10 @@ static __init int tracer_init_debugfs(void)
 
        create_trace_options_dir(&global_trace);
 
+       /* If the tracer was started via cmdline, create options for it here */
+       if (global_trace.current_trace != &nop_trace)
+               update_tracer_options(&global_trace, global_trace.current_trace);
+
        return 0;
 }
 
@@ -6888,7 +7179,7 @@ void __init trace_init(void)
                        tracepoint_printk = 0;
        }
        tracer_alloc_buffers();
-       trace_event_init();     
+       trace_event_init();
 }
 
 __init static int clear_boot_tracer(void)
@@ -6910,5 +7201,5 @@ __init static int clear_boot_tracer(void)
        return 0;
 }
 
-fs_initcall(tracer_init_debugfs);
+fs_initcall(tracer_init_tracefs);
 late_initcall(clear_boot_tracer);
index dd8205a35760d7a4b8bf53543f52abd0f1f9a6aa..d2612016de94f6e7c0762b6edbb6db7311b46d30 100644 (file)
@@ -334,7 +334,7 @@ struct tracer_flags {
 
 
 /**
- * struct tracer - a specific tracer and its callbacks to interact with debugfs
+ * struct tracer - a specific tracer and its callbacks to interact with tracefs
  * @name: the name chosen to select it on the available_tracers file
  * @init: called when one switches to this tracer (echo name > current_tracer)
  * @reset: called when one switches to another tracer
@@ -1309,8 +1309,10 @@ static inline void init_ftrace_syscalls(void) { }
 
 #ifdef CONFIG_EVENT_TRACING
 void trace_event_init(void);
+void trace_event_enum_update(struct trace_enum_map **map, int len);
 #else
 static inline void __init trace_event_init(void) { }
+static inlin void trace_event_enum_update(struct trace_enum_map **map, int len) { }
 #endif
 
 extern struct trace_iterator *tracepoint_print_iter;
index e2d027ac66a2d0f79bc1b3959b028a081f1fbc5d..ee7b94a4810af8c85aa4baa246203dc52f588eb6 100644 (file)
@@ -223,7 +223,7 @@ FTRACE_ENTRY(bprint, bprint_entry,
                __dynamic_array(        u32,    buf     )
        ),
 
-       F_printk("%pf: %s",
+       F_printk("%ps: %s",
                 (void *)__entry->ip, __entry->fmt),
 
        FILTER_OTHER
@@ -238,7 +238,7 @@ FTRACE_ENTRY(print, print_entry,
                __dynamic_array(        char,   buf     )
        ),
 
-       F_printk("%pf: %s",
+       F_printk("%ps: %s",
                 (void *)__entry->ip, __entry->buf),
 
        FILTER_OTHER
@@ -253,7 +253,7 @@ FTRACE_ENTRY(bputs, bputs_entry,
                __field(        const char *,   str     )
        ),
 
-       F_printk("%pf: %s",
+       F_printk("%ps: %s",
                 (void *)__entry->ip, __entry->str),
 
        FILTER_OTHER
index db54dda10ccc179f733db8fd8407cc402c11e409..7da1dfeb322e696c3352300982bfc0ad96fdd98f 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/workqueue.h>
 #include <linux/spinlock.h>
 #include <linux/kthread.h>
-#include <linux/debugfs.h>
+#include <linux/tracefs.h>
 #include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/ctype.h>
@@ -480,7 +480,7 @@ static void remove_subsystem(struct ftrace_subsystem_dir *dir)
                return;
 
        if (!--dir->nr_events) {
-               debugfs_remove_recursive(dir->entry);
+               tracefs_remove_recursive(dir->entry);
                list_del(&dir->list);
                __put_system_dir(dir);
        }
@@ -499,7 +499,7 @@ static void remove_event_file_dir(struct ftrace_event_file *file)
                }
                spin_unlock(&dir->d_lock);
 
-               debugfs_remove_recursive(dir);
+               tracefs_remove_recursive(dir);
        }
 
        list_del(&file->list);
@@ -1526,7 +1526,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
        } else
                __get_system(system);
 
-       dir->entry = debugfs_create_dir(name, parent);
+       dir->entry = tracefs_create_dir(name, parent);
        if (!dir->entry) {
                pr_warn("Failed to create system directory %s\n", name);
                __put_system(system);
@@ -1539,12 +1539,12 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
        dir->subsystem = system;
        file->system = dir;
 
-       entry = debugfs_create_file("filter", 0644, dir->entry, dir,
+       entry = tracefs_create_file("filter", 0644, dir->entry, dir,
                                    &ftrace_subsystem_filter_fops);
        if (!entry) {
                kfree(system->filter);
                system->filter = NULL;
-               pr_warn("Could not create debugfs '%s/filter' entry\n", name);
+               pr_warn("Could not create tracefs '%s/filter' entry\n", name);
        }
 
        trace_create_file("enable", 0644, dir->entry, dir,
@@ -1585,9 +1585,9 @@ event_create_dir(struct dentry *parent, struct ftrace_event_file *file)
                d_events = parent;
 
        name = ftrace_event_name(call);
-       file->dir = debugfs_create_dir(name, d_events);
+       file->dir = tracefs_create_dir(name, d_events);
        if (!file->dir) {
-               pr_warn("Could not create debugfs '%s' directory\n", name);
+               pr_warn("Could not create tracefs '%s' directory\n", name);
                return -1;
        }
 
@@ -1704,6 +1704,125 @@ __register_event(struct ftrace_event_call *call, struct module *mod)
        return 0;
 }
 
+static char *enum_replace(char *ptr, struct trace_enum_map *map, int len)
+{
+       int rlen;
+       int elen;
+
+       /* Find the length of the enum value as a string */
+       elen = snprintf(ptr, 0, "%ld", map->enum_value);
+       /* Make sure there's enough room to replace the string with the value */
+       if (len < elen)
+               return NULL;
+
+       snprintf(ptr, elen + 1, "%ld", map->enum_value);
+
+       /* Get the rest of the string of ptr */
+       rlen = strlen(ptr + len);
+       memmove(ptr + elen, ptr + len, rlen);
+       /* Make sure we end the new string */
+       ptr[elen + rlen] = 0;
+
+       return ptr + elen;
+}
+
+static void update_event_printk(struct ftrace_event_call *call,
+                               struct trace_enum_map *map)
+{
+       char *ptr;
+       int quote = 0;
+       int len = strlen(map->enum_string);
+
+       for (ptr = call->print_fmt; *ptr; ptr++) {
+               if (*ptr == '\\') {
+                       ptr++;
+                       /* paranoid */
+                       if (!*ptr)
+                               break;
+                       continue;
+               }
+               if (*ptr == '"') {
+                       quote ^= 1;
+                       continue;
+               }
+               if (quote)
+                       continue;
+               if (isdigit(*ptr)) {
+                       /* skip numbers */
+                       do {
+                               ptr++;
+                               /* Check for alpha chars like ULL */
+                       } while (isalnum(*ptr));
+                       /*
+                        * A number must have some kind of delimiter after
+                        * it, and we can ignore that too.
+                        */
+                       continue;
+               }
+               if (isalpha(*ptr) || *ptr == '_') {
+                       if (strncmp(map->enum_string, ptr, len) == 0 &&
+                           !isalnum(ptr[len]) && ptr[len] != '_') {
+                               ptr = enum_replace(ptr, map, len);
+                               /* Hmm, enum string smaller than value */
+                               if (WARN_ON_ONCE(!ptr))
+                                       return;
+                               /*
+                                * No need to decrement here, as enum_replace()
+                                * returns the pointer to the character passed
+                                * the enum, and two enums can not be placed
+                                * back to back without something in between.
+                                * We can skip that something in between.
+                                */
+                               continue;
+                       }
+               skip_more:
+                       do {
+                               ptr++;
+                       } while (isalnum(*ptr) || *ptr == '_');
+                       /*
+                        * If what comes after this variable is a '.' or
+                        * '->' then we can continue to ignore that string.
+                        */
+                       if (*ptr == '.' || (ptr[0] == '-' && ptr[1] == '>')) {
+                               ptr += *ptr == '.' ? 1 : 2;
+                               goto skip_more;
+                       }
+                       /*
+                        * Once again, we can skip the delimiter that came
+                        * after the string.
+                        */
+                       continue;
+               }
+       }
+}
+
+void trace_event_enum_update(struct trace_enum_map **map, int len)
+{
+       struct ftrace_event_call *call, *p;
+       const char *last_system = NULL;
+       int last_i;
+       int i;
+
+       down_write(&trace_event_sem);
+       list_for_each_entry_safe(call, p, &ftrace_events, list) {
+               /* events are usually grouped together with systems */
+               if (!last_system || call->class->system != last_system) {
+                       last_i = 0;
+                       last_system = call->class->system;
+               }
+
+               for (i = last_i; i < len; i++) {
+                       if (call->class->system == map[i]->system) {
+                               /* Save the first system if need be */
+                               if (!last_i)
+                                       last_i = i;
+                               update_event_printk(call, map[i]);
+                       }
+               }
+       }
+       up_write(&trace_event_sem);
+}
+
 static struct ftrace_event_file *
 trace_create_new_event(struct ftrace_event_call *call,
                       struct trace_array *tr)
@@ -1915,7 +2034,7 @@ static int trace_module_notify(struct notifier_block *self,
 
 static struct notifier_block trace_module_nb = {
        .notifier_call = trace_module_notify,
-       .priority = 0,
+       .priority = 1, /* higher than trace.c module notify */
 };
 #endif /* CONFIG_MODULES */
 
@@ -2228,7 +2347,7 @@ static inline int register_event_cmds(void) { return 0; }
 /*
  * The top level array has already had its ftrace_event_file
  * descriptors created in order to allow for early events to
- * be recorded. This function is called after the debugfs has been
+ * be recorded. This function is called after the tracefs has been
  * initialized, and we now have to create the files associated
  * to the events.
  */
@@ -2311,16 +2430,16 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
        struct dentry *d_events;
        struct dentry *entry;
 
-       entry = debugfs_create_file("set_event", 0644, parent,
+       entry = tracefs_create_file("set_event", 0644, parent,
                                    tr, &ftrace_set_event_fops);
        if (!entry) {
-               pr_warn("Could not create debugfs 'set_event' entry\n");
+               pr_warn("Could not create tracefs 'set_event' entry\n");
                return -ENOMEM;
        }
 
-       d_events = debugfs_create_dir("events", parent);
+       d_events = tracefs_create_dir("events", parent);
        if (!d_events) {
-               pr_warn("Could not create debugfs 'events' directory\n");
+               pr_warn("Could not create tracefs 'events' directory\n");
                return -ENOMEM;
        }
 
@@ -2412,7 +2531,7 @@ int event_trace_del_tracer(struct trace_array *tr)
 
        down_write(&trace_event_sem);
        __trace_remove_event_dirs(tr);
-       debugfs_remove_recursive(tr->event_dir);
+       tracefs_remove_recursive(tr->event_dir);
        up_write(&trace_event_sem);
 
        tr->event_dir = NULL;
@@ -2534,10 +2653,10 @@ static __init int event_trace_init(void)
        if (IS_ERR(d_tracer))
                return 0;
 
-       entry = debugfs_create_file("available_events", 0444, d_tracer,
+       entry = tracefs_create_file("available_events", 0444, d_tracer,
                                    tr, &ftrace_avail_fops);
        if (!entry)
-               pr_warn("Could not create debugfs 'available_events' entry\n");
+               pr_warn("Could not create tracefs 'available_events' entry\n");
 
        if (trace_define_common_fields())
                pr_warn("tracing: Failed to allocate common fields");
index 12e2b99be862f9350c49e9350c4836b3ced68a52..174a6a71146c8867f6ff3e9414a0c85aaf48c7c5 100644 (file)
@@ -177,7 +177,7 @@ struct ftrace_event_call __used event_##call = {                    \
        },                                                              \
        .event.type             = etype,                                \
        .print_fmt              = print,                                \
-       .flags                  = TRACE_EVENT_FL_IGNORE_ENABLE | TRACE_EVENT_FL_USE_CALL_FILTER, \
+       .flags                  = TRACE_EVENT_FL_IGNORE_ENABLE,         \
 };                                                                     \
 struct ftrace_event_call __used                                                \
 __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call;
index 2d25ad1526bb16f28e9f18f1d3b0edf2b7093341..9cfea4c6d314c6153d4986a55a89503671e2b1a4 100644 (file)
@@ -6,7 +6,6 @@
  * is Copyright (c) Steven Rostedt <srostedt@redhat.com>
  *
  */
-#include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <linux/ftrace.h>
 #include <linux/slab.h>
@@ -151,7 +150,7 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
         * The curr_ret_stack is initialized to -1 and get increased
         * in this function.  So it can be less than -1 only if it was
         * filtered out via ftrace_graph_notrace_addr() which can be
-        * set from set_graph_notrace file in debugfs by user.
+        * set from set_graph_notrace file in tracefs by user.
         */
        if (current->curr_ret_stack < -1)
                return -EBUSY;
@@ -1432,7 +1431,7 @@ static const struct file_operations graph_depth_fops = {
        .llseek         = generic_file_llseek,
 };
 
-static __init int init_graph_debugfs(void)
+static __init int init_graph_tracefs(void)
 {
        struct dentry *d_tracer;
 
@@ -1445,7 +1444,7 @@ static __init int init_graph_debugfs(void)
 
        return 0;
 }
-fs_initcall(init_graph_debugfs);
+fs_initcall(init_graph_tracefs);
 
 static __init int init_graph_trace(void)
 {
index d73f565b4e062127789bce243dc9c2e365dbb175..d0ce590f06e17a34c61c3d5c1ab805bb1b633c61 100644 (file)
@@ -250,7 +250,7 @@ DEFINE_FETCH_symbol(string_size)
 #define fetch_file_offset_string_size  NULL
 
 /* Fetch type information table */
-const struct fetch_type kprobes_fetch_type_table[] = {
+static const struct fetch_type kprobes_fetch_type_table[] = {
        /* Special types */
        [FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string,
                                        sizeof(u32), 1, "__data_loc char[]"),
@@ -760,7 +760,8 @@ static int create_trace_kprobe(int argc, char **argv)
 
                /* Parse fetch argument */
                ret = traceprobe_parse_probe_arg(arg, &tk->tp.size, parg,
-                                               is_return, true);
+                                               is_return, true,
+                                               kprobes_fetch_type_table);
                if (ret) {
                        pr_info("Parse error at argument[%d]. (%d)\n", i, ret);
                        goto error;
@@ -1134,11 +1135,15 @@ static void
 kprobe_perf_func(struct trace_kprobe *tk, struct pt_regs *regs)
 {
        struct ftrace_event_call *call = &tk->tp.call;
+       struct bpf_prog *prog = call->prog;
        struct kprobe_trace_entry_head *entry;
        struct hlist_head *head;
        int size, __size, dsize;
        int rctx;
 
+       if (prog && !trace_call_bpf(prog, regs))
+               return;
+
        head = this_cpu_ptr(call->perf_events);
        if (hlist_empty(head))
                return;
@@ -1165,11 +1170,15 @@ kretprobe_perf_func(struct trace_kprobe *tk, struct kretprobe_instance *ri,
                    struct pt_regs *regs)
 {
        struct ftrace_event_call *call = &tk->tp.call;
+       struct bpf_prog *prog = call->prog;
        struct kretprobe_trace_entry_head *entry;
        struct hlist_head *head;
        int size, __size, dsize;
        int rctx;
 
+       if (prog && !trace_call_bpf(prog, regs))
+               return;
+
        head = this_cpu_ptr(call->perf_events);
        if (hlist_empty(head))
                return;
@@ -1286,7 +1295,7 @@ static int register_kprobe_event(struct trace_kprobe *tk)
                kfree(call->print_fmt);
                return -ENODEV;
        }
-       call->flags = 0;
+       call->flags = TRACE_EVENT_FL_KPROBE;
        call->class->reg = kprobe_register;
        call->data = tk;
        ret = trace_add_event_call(call);
@@ -1310,7 +1319,7 @@ static int unregister_kprobe_event(struct trace_kprobe *tk)
        return ret;
 }
 
-/* Make a debugfs interface for controlling probe points */
+/* Make a tracefs interface for controlling probe points */
 static __init int init_kprobe_trace(void)
 {
        struct dentry *d_tracer;
@@ -1323,20 +1332,20 @@ static __init int init_kprobe_trace(void)
        if (IS_ERR(d_tracer))
                return 0;
 
-       entry = debugfs_create_file("kprobe_events", 0644, d_tracer,
+       entry = tracefs_create_file("kprobe_events", 0644, d_tracer,
                                    NULL, &kprobe_events_ops);
 
        /* Event list interface */
        if (!entry)
-               pr_warning("Could not create debugfs "
+               pr_warning("Could not create tracefs "
                           "'kprobe_events' entry\n");
 
        /* Profile interface */
-       entry = debugfs_create_file("kprobe_profile", 0444, d_tracer,
+       entry = tracefs_create_file("kprobe_profile", 0444, d_tracer,
                                    NULL, &kprobe_profile_ops);
 
        if (!entry)
-               pr_warning("Could not create debugfs "
+               pr_warning("Could not create tracefs "
                           "'kprobe_profile' entry\n");
        return 0;
 }
index b983b2fd2ca171343d188739d245f8579eade04c..1769a81da8a783a1331ca6163646c7229b747e61 100644 (file)
@@ -356,17 +356,14 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t,
 
 /* Recursive argument parser */
 static int parse_probe_arg(char *arg, const struct fetch_type *t,
-                    struct fetch_param *f, bool is_return, bool is_kprobe)
+                    struct fetch_param *f, bool is_return, bool is_kprobe,
+                    const struct fetch_type *ftbl)
 {
-       const struct fetch_type *ftbl;
        unsigned long param;
        long offset;
        char *tmp;
        int ret = 0;
 
-       ftbl = is_kprobe ? kprobes_fetch_type_table : uprobes_fetch_type_table;
-       BUG_ON(ftbl == NULL);
-
        switch (arg[0]) {
        case '$':
                ret = parse_probe_vars(arg + 1, t, f, is_return, is_kprobe);
@@ -447,7 +444,7 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t,
                        dprm->fetch_size = get_fetch_size_function(t,
                                                        dprm->fetch, ftbl);
                        ret = parse_probe_arg(arg, t2, &dprm->orig, is_return,
-                                                       is_kprobe);
+                                                       is_kprobe, ftbl);
                        if (ret)
                                kfree(dprm);
                        else {
@@ -505,15 +502,12 @@ static int __parse_bitfield_probe_arg(const char *bf,
 
 /* String length checking wrapper */
 int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
-               struct probe_arg *parg, bool is_return, bool is_kprobe)
+               struct probe_arg *parg, bool is_return, bool is_kprobe,
+               const struct fetch_type *ftbl)
 {
-       const struct fetch_type *ftbl;
        const char *t;
        int ret;
 
-       ftbl = is_kprobe ? kprobes_fetch_type_table : uprobes_fetch_type_table;
-       BUG_ON(ftbl == NULL);
-
        if (strlen(arg) > MAX_ARGSTR_LEN) {
                pr_info("Argument is too long.: %s\n",  arg);
                return -ENOSPC;
@@ -535,7 +529,8 @@ int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
        }
        parg->offset = *size;
        *size += parg->type->size;
-       ret = parse_probe_arg(arg, parg->type, &parg->fetch, is_return, is_kprobe);
+       ret = parse_probe_arg(arg, parg->type, &parg->fetch, is_return,
+                             is_kprobe, ftbl);
 
        if (ret >= 0 && t != NULL)
                ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch);
index 4f815fbce16d26eefbc8e3b572ec9f2fdca7879b..ab283e146b700665b65e8bc1e9b73c273bf86fee 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
-#include <linux/debugfs.h>
+#include <linux/tracefs.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
@@ -229,13 +229,6 @@ ASSIGN_FETCH_FUNC(file_offset, ftype),                     \
 #define FETCH_TYPE_STRING      0
 #define FETCH_TYPE_STRSIZE     1
 
-/*
- * Fetch type information table.
- * It's declared as a weak symbol due to conditional compilation.
- */
-extern __weak const struct fetch_type kprobes_fetch_type_table[];
-extern __weak const struct fetch_type uprobes_fetch_type_table[];
-
 #ifdef CONFIG_KPROBE_EVENT
 struct symbol_cache;
 unsigned long update_symbol_cache(struct symbol_cache *sc);
@@ -333,7 +326,8 @@ find_event_file_link(struct trace_probe *tp, struct ftrace_event_file *file)
 }
 
 extern int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
-                  struct probe_arg *parg, bool is_return, bool is_kprobe);
+                  struct probe_arg *parg, bool is_return, bool is_kprobe,
+                  const struct fetch_type *ftbl);
 
 extern int traceprobe_conflict_field_name(const char *name,
                               struct probe_arg *args, int narg);
index 75e19e86c9548044c3a6a712ca73b9bb02d74e50..6cf935316769630636b447f87e994dc89edf0b01 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/rbtree.h>
-#include <linux/debugfs.h>
+#include <linux/tracefs.h>
 #include "trace_stat.h"
 #include "trace.h"
 
@@ -65,7 +65,7 @@ static void reset_stat_session(struct stat_session *session)
 
 static void destroy_session(struct stat_session *session)
 {
-       debugfs_remove(session->file);
+       tracefs_remove(session->file);
        __reset_stat_session(session);
        mutex_destroy(&session->stat_mutex);
        kfree(session);
@@ -279,9 +279,9 @@ static int tracing_stat_init(void)
        if (IS_ERR(d_tracing))
                return 0;
 
-       stat_dir = debugfs_create_dir("trace_stat", d_tracing);
+       stat_dir = tracefs_create_dir("trace_stat", d_tracing);
        if (!stat_dir)
-               pr_warning("Could not create debugfs "
+               pr_warning("Could not create tracefs "
                           "'trace_stat' entry\n");
        return 0;
 }
@@ -291,7 +291,7 @@ static int init_stat_file(struct stat_session *session)
        if (!stat_dir && tracing_stat_init())
                return -ENODEV;
 
-       session->file = debugfs_create_file(session->ts->name, 0644,
+       session->file = tracefs_create_file(session->ts->name, 0644,
                                            stat_dir,
                                            session, &tracing_stat_fops);
        if (!session->file)
index 7dc1c8abecd6c6fd831a3f952d67454261dc2ab9..d60fe62ec4fa4c99dfc9cf381b9a26d8093f6a16 100644 (file)
@@ -196,7 +196,7 @@ DEFINE_FETCH_file_offset(string)
 DEFINE_FETCH_file_offset(string_size)
 
 /* Fetch type information table */
-const struct fetch_type uprobes_fetch_type_table[] = {
+static const struct fetch_type uprobes_fetch_type_table[] = {
        /* Special types */
        [FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string,
                                        sizeof(u32), 1, "__data_loc char[]"),
@@ -535,7 +535,8 @@ static int create_trace_uprobe(int argc, char **argv)
 
                /* Parse fetch argument */
                ret = traceprobe_parse_probe_arg(arg, &tu->tp.size, parg,
-                                                is_return, false);
+                                                is_return, false,
+                                                uprobes_fetch_type_table);
                if (ret) {
                        pr_info("Parse error at argument[%d]. (%d)\n", i, ret);
                        goto error;
@@ -1005,7 +1006,7 @@ __uprobe_perf_filter(struct trace_uprobe_filter *filter, struct mm_struct *mm)
                return true;
 
        list_for_each_entry(event, &filter->perf_events, hw.tp_list) {
-               if (event->hw.tp_target->mm == mm)
+               if (event->hw.target->mm == mm)
                        return true;
        }
 
@@ -1015,7 +1016,7 @@ __uprobe_perf_filter(struct trace_uprobe_filter *filter, struct mm_struct *mm)
 static inline bool
 uprobe_filter_event(struct trace_uprobe *tu, struct perf_event *event)
 {
-       return __uprobe_perf_filter(&tu->filter, event->hw.tp_target->mm);
+       return __uprobe_perf_filter(&tu->filter, event->hw.target->mm);
 }
 
 static int uprobe_perf_close(struct trace_uprobe *tu, struct perf_event *event)
@@ -1023,10 +1024,10 @@ static int uprobe_perf_close(struct trace_uprobe *tu, struct perf_event *event)
        bool done;
 
        write_lock(&tu->filter.rwlock);
-       if (event->hw.tp_target) {
+       if (event->hw.target) {
                list_del(&event->hw.tp_list);
                done = tu->filter.nr_systemwide ||
-                       (event->hw.tp_target->flags & PF_EXITING) ||
+                       (event->hw.target->flags & PF_EXITING) ||
                        uprobe_filter_event(tu, event);
        } else {
                tu->filter.nr_systemwide--;
@@ -1046,7 +1047,7 @@ static int uprobe_perf_open(struct trace_uprobe *tu, struct perf_event *event)
        int err;
 
        write_lock(&tu->filter.rwlock);
-       if (event->hw.tp_target) {
+       if (event->hw.target) {
                /*
                 * event->parent != NULL means copy_process(), we can avoid
                 * uprobe_apply(). current->mm must be probed and we can rely
index 3174bf8e353852ae886743b8ffbe33e46fb03c02..2316f50b07a456e979603fcee13a66fca03b1baa 100644 (file)
 #include <linux/kvm_para.h>
 #include <linux/perf_event.h>
 
-int watchdog_user_enabled = 1;
+/*
+ * The run state of the lockup detectors is controlled by the content of the
+ * 'watchdog_enabled' variable. Each lockup detector has its dedicated bit -
+ * bit 0 for the hard lockup detector and bit 1 for the soft lockup detector.
+ *
+ * 'watchdog_user_enabled', 'nmi_watchdog_enabled' and 'soft_watchdog_enabled'
+ * are variables that are only used as an 'interface' between the parameters
+ * in /proc/sys/kernel and the internal state bits in 'watchdog_enabled'. The
+ * 'watchdog_thresh' variable is handled differently because its value is not
+ * boolean, and the lockup detectors are 'suspended' while 'watchdog_thresh'
+ * is equal zero.
+ */
+#define NMI_WATCHDOG_ENABLED_BIT   0
+#define SOFT_WATCHDOG_ENABLED_BIT  1
+#define NMI_WATCHDOG_ENABLED      (1 << NMI_WATCHDOG_ENABLED_BIT)
+#define SOFT_WATCHDOG_ENABLED     (1 << SOFT_WATCHDOG_ENABLED_BIT)
+
+#ifdef CONFIG_HARDLOCKUP_DETECTOR
+static unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED|NMI_WATCHDOG_ENABLED;
+#else
+static unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED;
+#endif
+int __read_mostly nmi_watchdog_enabled;
+int __read_mostly soft_watchdog_enabled;
+int __read_mostly watchdog_user_enabled;
 int __read_mostly watchdog_thresh = 10;
+
 #ifdef CONFIG_SMP
 int __read_mostly sysctl_softlockup_all_cpu_backtrace;
 #else
@@ -58,8 +83,6 @@ static unsigned long soft_lockup_nmi_warn;
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
 static int hardlockup_panic =
                        CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE;
-
-static bool hardlockup_detector_enabled = true;
 /*
  * We may not want to enable hard lockup detection by default in all cases,
  * for example when running the kernel as a guest on a hypervisor. In these
@@ -68,14 +91,9 @@ static bool hardlockup_detector_enabled = true;
  * kernel command line parameters are parsed, because otherwise it is not
  * possible to override this in hardlockup_panic_setup().
  */
-void watchdog_enable_hardlockup_detector(bool val)
-{
-       hardlockup_detector_enabled = val;
-}
-
-bool watchdog_hardlockup_detector_is_enabled(void)
+void hardlockup_detector_disable(void)
 {
-       return hardlockup_detector_enabled;
+       watchdog_enabled &= ~NMI_WATCHDOG_ENABLED;
 }
 
 static int __init hardlockup_panic_setup(char *str)
@@ -85,15 +103,9 @@ static int __init hardlockup_panic_setup(char *str)
        else if (!strncmp(str, "nopanic", 7))
                hardlockup_panic = 0;
        else if (!strncmp(str, "0", 1))
-               watchdog_user_enabled = 0;
-       else if (!strncmp(str, "1", 1) || !strncmp(str, "2", 1)) {
-               /*
-                * Setting 'nmi_watchdog=1' or 'nmi_watchdog=2' (legacy option)
-                * has the same effect.
-                */
-               watchdog_user_enabled = 1;
-               watchdog_enable_hardlockup_detector(true);
-       }
+               watchdog_enabled &= ~NMI_WATCHDOG_ENABLED;
+       else if (!strncmp(str, "1", 1))
+               watchdog_enabled |= NMI_WATCHDOG_ENABLED;
        return 1;
 }
 __setup("nmi_watchdog=", hardlockup_panic_setup);
@@ -112,19 +124,18 @@ __setup("softlockup_panic=", softlockup_panic_setup);
 
 static int __init nowatchdog_setup(char *str)
 {
-       watchdog_user_enabled = 0;
+       watchdog_enabled = 0;
        return 1;
 }
 __setup("nowatchdog", nowatchdog_setup);
 
-/* deprecated */
 static int __init nosoftlockup_setup(char *str)
 {
-       watchdog_user_enabled = 0;
+       watchdog_enabled &= ~SOFT_WATCHDOG_ENABLED;
        return 1;
 }
 __setup("nosoftlockup", nosoftlockup_setup);
-/*  */
+
 #ifdef CONFIG_SMP
 static int __init softlockup_all_cpu_backtrace_setup(char *str)
 {
@@ -239,10 +250,11 @@ static int is_softlockup(unsigned long touch_ts)
 {
        unsigned long now = get_timestamp();
 
-       /* Warn about unreasonable delays: */
-       if (time_after(now, touch_ts + get_softlockup_thresh()))
-               return now - touch_ts;
-
+       if (watchdog_enabled & SOFT_WATCHDOG_ENABLED) {
+               /* Warn about unreasonable delays. */
+               if (time_after(now, touch_ts + get_softlockup_thresh()))
+                       return now - touch_ts;
+       }
        return 0;
 }
 
@@ -477,6 +489,21 @@ static void watchdog(unsigned int cpu)
        __this_cpu_write(soft_lockup_hrtimer_cnt,
                         __this_cpu_read(hrtimer_interrupts));
        __touch_watchdog();
+
+       /*
+        * watchdog_nmi_enable() clears the NMI_WATCHDOG_ENABLED bit in the
+        * failure path. Check for failures that can occur asynchronously -
+        * for example, when CPUs are on-lined - and shut down the hardware
+        * perf event on each CPU accordingly.
+        *
+        * The only non-obvious place this bit can be cleared is through
+        * watchdog_nmi_enable(), so a pr_info() is placed there.  Placing a
+        * pr_info here would be too noisy as it would result in a message
+        * every few seconds if the hardlockup was disabled but the softlockup
+        * enabled.
+        */
+       if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
+               watchdog_nmi_disable(cpu);
 }
 
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
@@ -492,14 +519,9 @@ static int watchdog_nmi_enable(unsigned int cpu)
        struct perf_event_attr *wd_attr;
        struct perf_event *event = per_cpu(watchdog_ev, cpu);
 
-       /*
-        * Some kernels need to default hard lockup detection to
-        * 'disabled', for example a guest on a hypervisor.
-        */
-       if (!watchdog_hardlockup_detector_is_enabled()) {
-               event = ERR_PTR(-ENOENT);
-               goto handle_err;
-       }
+       /* nothing to do if the hard lockup detector is disabled */
+       if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
+               goto out;
 
        /* is it already setup and enabled? */
        if (event && event->state > PERF_EVENT_STATE_OFF)
@@ -515,7 +537,6 @@ static int watchdog_nmi_enable(unsigned int cpu)
        /* Try to register using hardware perf events */
        event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL);
 
-handle_err:
        /* save cpu0 error for future comparision */
        if (cpu == 0 && IS_ERR(event))
                cpu0_err = PTR_ERR(event);
@@ -527,6 +548,18 @@ handle_err:
                goto out_save;
        }
 
+       /*
+        * Disable the hard lockup detector if _any_ CPU fails to set up
+        * set up the hardware perf event. The watchdog() function checks
+        * the NMI_WATCHDOG_ENABLED bit periodically.
+        *
+        * The barriers are for syncing up watchdog_enabled across all the
+        * cpus, as clear_bit() does not use barriers.
+        */
+       smp_mb__before_atomic();
+       clear_bit(NMI_WATCHDOG_ENABLED_BIT, &watchdog_enabled);
+       smp_mb__after_atomic();
+
        /* skip displaying the same error again */
        if (cpu > 0 && (PTR_ERR(event) == cpu0_err))
                return PTR_ERR(event);
@@ -540,6 +573,9 @@ handle_err:
        else
                pr_err("disabled (cpu%i): unable to create perf event: %ld\n",
                        cpu, PTR_ERR(event));
+
+       pr_info("Shutting down hard lockup detector on all cpus\n");
+
        return PTR_ERR(event);
 
        /* success path */
@@ -567,9 +603,37 @@ static void watchdog_nmi_disable(unsigned int cpu)
                cpu0_err = 0;
        }
 }
+
+void watchdog_nmi_enable_all(void)
+{
+       int cpu;
+
+       if (!watchdog_user_enabled)
+               return;
+
+       get_online_cpus();
+       for_each_online_cpu(cpu)
+               watchdog_nmi_enable(cpu);
+       put_online_cpus();
+}
+
+void watchdog_nmi_disable_all(void)
+{
+       int cpu;
+
+       if (!watchdog_running)
+               return;
+
+       get_online_cpus();
+       for_each_online_cpu(cpu)
+               watchdog_nmi_disable(cpu);
+       put_online_cpus();
+}
 #else
 static int watchdog_nmi_enable(unsigned int cpu) { return 0; }
 static void watchdog_nmi_disable(unsigned int cpu) { return; }
+void watchdog_nmi_enable_all(void) {}
+void watchdog_nmi_disable_all(void) {}
 #endif /* CONFIG_HARDLOCKUP_DETECTOR */
 
 static struct smp_hotplug_thread watchdog_threads = {
@@ -600,7 +664,7 @@ static void restart_watchdog_hrtimer(void *info)
                                HRTIMER_MODE_REL_PINNED);
 }
 
-static void update_timers(int cpu)
+static void update_watchdog(int cpu)
 {
        /*
         * Make sure that perf event counter will adopt to a new
@@ -615,17 +679,17 @@ static void update_timers(int cpu)
        watchdog_nmi_enable(cpu);
 }
 
-static void update_timers_all_cpus(void)
+static void update_watchdog_all_cpus(void)
 {
        int cpu;
 
        get_online_cpus();
        for_each_online_cpu(cpu)
-               update_timers(cpu);
+               update_watchdog(cpu);
        put_online_cpus();
 }
 
-static int watchdog_enable_all_cpus(bool sample_period_changed)
+static int watchdog_enable_all_cpus(void)
 {
        int err = 0;
 
@@ -635,8 +699,12 @@ static int watchdog_enable_all_cpus(bool sample_period_changed)
                        pr_err("Failed to create watchdog threads, disabled\n");
                else
                        watchdog_running = 1;
-       } else if (sample_period_changed) {
-               update_timers_all_cpus();
+       } else {
+               /*
+                * Enable/disable the lockup detectors or
+                * change the sample period 'on the fly'.
+                */
+               update_watchdog_all_cpus();
        }
 
        return err;
@@ -654,58 +722,159 @@ static void watchdog_disable_all_cpus(void)
 }
 
 /*
- * proc handler for /proc/sys/kernel/nmi_watchdog,watchdog_thresh
+ * Update the run state of the lockup detectors.
  */
+static int proc_watchdog_update(void)
+{
+       int err = 0;
 
-int proc_dowatchdog(struct ctl_table *table, int write,
-                   void __user *buffer, size_t *lenp, loff_t *ppos)
+       /*
+        * Watchdog threads won't be started if they are already active.
+        * The 'watchdog_running' variable in watchdog_*_all_cpus() takes
+        * care of this. If those threads are already active, the sample
+        * period will be updated and the lockup detectors will be enabled
+        * or disabled 'on the fly'.
+        */
+       if (watchdog_enabled && watchdog_thresh)
+               err = watchdog_enable_all_cpus();
+       else
+               watchdog_disable_all_cpus();
+
+       return err;
+
+}
+
+static DEFINE_MUTEX(watchdog_proc_mutex);
+
+/*
+ * common function for watchdog, nmi_watchdog and soft_watchdog parameter
+ *
+ * caller             | table->data points to | 'which' contains the flag(s)
+ * -------------------|-----------------------|-----------------------------
+ * proc_watchdog      | watchdog_user_enabled | NMI_WATCHDOG_ENABLED or'ed
+ *                    |                       | with SOFT_WATCHDOG_ENABLED
+ * -------------------|-----------------------|-----------------------------
+ * proc_nmi_watchdog  | nmi_watchdog_enabled  | NMI_WATCHDOG_ENABLED
+ * -------------------|-----------------------|-----------------------------
+ * proc_soft_watchdog | soft_watchdog_enabled | SOFT_WATCHDOG_ENABLED
+ */
+static int proc_watchdog_common(int which, struct ctl_table *table, int write,
+                               void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-       int err, old_thresh, old_enabled;
-       bool old_hardlockup;
-       static DEFINE_MUTEX(watchdog_proc_mutex);
+       int err, old, new;
+       int *watchdog_param = (int *)table->data;
 
        mutex_lock(&watchdog_proc_mutex);
-       old_thresh = ACCESS_ONCE(watchdog_thresh);
-       old_enabled = ACCESS_ONCE(watchdog_user_enabled);
-       old_hardlockup = watchdog_hardlockup_detector_is_enabled();
 
-       err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
-       if (err || !write)
-               goto out;
-
-       set_sample_period();
        /*
-        * Watchdog threads shouldn't be enabled if they are
-        * disabled. The 'watchdog_running' variable check in
-        * watchdog_*_all_cpus() function takes care of this.
+        * If the parameter is being read return the state of the corresponding
+        * bit(s) in 'watchdog_enabled', else update 'watchdog_enabled' and the
+        * run state of the lockup detectors.
         */
-       if (watchdog_user_enabled && watchdog_thresh) {
+       if (!write) {
+               *watchdog_param = (watchdog_enabled & which) != 0;
+               err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+       } else {
+               err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+               if (err)
+                       goto out;
+
                /*
-                * Prevent a change in watchdog_thresh accidentally overriding
-                * the enablement of the hardlockup detector.
+                * There is a race window between fetching the current value
+                * from 'watchdog_enabled' and storing the new value. During
+                * this race window, watchdog_nmi_enable() can sneak in and
+                * clear the NMI_WATCHDOG_ENABLED bit in 'watchdog_enabled'.
+                * The 'cmpxchg' detects this race and the loop retries.
                 */
-               if (watchdog_user_enabled != old_enabled)
-                       watchdog_enable_hardlockup_detector(true);
-               err = watchdog_enable_all_cpus(old_thresh != watchdog_thresh);
-       } else
-               watchdog_disable_all_cpus();
+               do {
+                       old = watchdog_enabled;
+                       /*
+                        * If the parameter value is not zero set the
+                        * corresponding bit(s), else clear it(them).
+                        */
+                       if (*watchdog_param)
+                               new = old | which;
+                       else
+                               new = old & ~which;
+               } while (cmpxchg(&watchdog_enabled, old, new) != old);
 
-       /* Restore old values on failure */
-       if (err) {
-               watchdog_thresh = old_thresh;
-               watchdog_user_enabled = old_enabled;
-               watchdog_enable_hardlockup_detector(old_hardlockup);
+               /*
+                * Update the run state of the lockup detectors.
+                * Restore 'watchdog_enabled' on failure.
+                */
+               err = proc_watchdog_update();
+               if (err)
+                       watchdog_enabled = old;
        }
 out:
        mutex_unlock(&watchdog_proc_mutex);
        return err;
 }
+
+/*
+ * /proc/sys/kernel/watchdog
+ */
+int proc_watchdog(struct ctl_table *table, int write,
+                 void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       return proc_watchdog_common(NMI_WATCHDOG_ENABLED|SOFT_WATCHDOG_ENABLED,
+                                   table, write, buffer, lenp, ppos);
+}
+
+/*
+ * /proc/sys/kernel/nmi_watchdog
+ */
+int proc_nmi_watchdog(struct ctl_table *table, int write,
+                     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       return proc_watchdog_common(NMI_WATCHDOG_ENABLED,
+                                   table, write, buffer, lenp, ppos);
+}
+
+/*
+ * /proc/sys/kernel/soft_watchdog
+ */
+int proc_soft_watchdog(struct ctl_table *table, int write,
+                       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       return proc_watchdog_common(SOFT_WATCHDOG_ENABLED,
+                                   table, write, buffer, lenp, ppos);
+}
+
+/*
+ * /proc/sys/kernel/watchdog_thresh
+ */
+int proc_watchdog_thresh(struct ctl_table *table, int write,
+                        void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int err, old;
+
+       mutex_lock(&watchdog_proc_mutex);
+
+       old = ACCESS_ONCE(watchdog_thresh);
+       err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+
+       if (err || !write)
+               goto out;
+
+       /*
+        * Update the sample period.
+        * Restore 'watchdog_thresh' on failure.
+        */
+       set_sample_period();
+       err = proc_watchdog_update();
+       if (err)
+               watchdog_thresh = old;
+out:
+       mutex_unlock(&watchdog_proc_mutex);
+       return err;
+}
 #endif /* CONFIG_SYSCTL */
 
 void __init lockup_detector_init(void)
 {
        set_sample_period();
 
-       if (watchdog_user_enabled)
-               watchdog_enable_all_cpus(false);
+       if (watchdog_enabled)
+               watchdog_enable_all_cpus();
 }
index 41ff75b478c60b443cd80626351b1e3f3030f94b..586ad91300b0f3924b41bd417cda9cbb076f1a9d 100644 (file)
@@ -159,6 +159,7 @@ struct worker_pool {
 
        /* see manage_workers() for details on the two manager mutexes */
        struct mutex            manager_arb;    /* manager arbitration */
+       struct worker           *manager;       /* L: purely informational */
        struct mutex            attach_mutex;   /* attach/detach exclusion */
        struct list_head        workers;        /* A: attached workers */
        struct completion       *detach_completion; /* all workers detached */
@@ -230,7 +231,7 @@ struct wq_device;
  */
 struct workqueue_struct {
        struct list_head        pwqs;           /* WR: all pwqs of this wq */
-       struct list_head        list;           /* PL: list of all workqueues */
+       struct list_head        list;           /* PR: list of all workqueues */
 
        struct mutex            mutex;          /* protects this wq */
        int                     work_color;     /* WQ: current work color */
@@ -257,6 +258,13 @@ struct workqueue_struct {
 #endif
        char                    name[WQ_NAME_LEN]; /* I: workqueue name */
 
+       /*
+        * Destruction of workqueue_struct is sched-RCU protected to allow
+        * walking the workqueues list without grabbing wq_pool_mutex.
+        * This is used to dump all workqueues from sysrq.
+        */
+       struct rcu_head         rcu;
+
        /* hot fields used during command issue, aligned to cacheline */
        unsigned int            flags ____cacheline_aligned; /* WQ: WQ_* flags */
        struct pool_workqueue __percpu *cpu_pwqs; /* I: per-cpu pwqs */
@@ -288,7 +296,7 @@ static struct workqueue_attrs *wq_update_unbound_numa_attrs_buf;
 static DEFINE_MUTEX(wq_pool_mutex);    /* protects pools and workqueues list */
 static DEFINE_SPINLOCK(wq_mayday_lock);        /* protects wq->maydays list */
 
-static LIST_HEAD(workqueues);          /* PL: list of all workqueues */
+static LIST_HEAD(workqueues);          /* PR: list of all workqueues */
 static bool workqueue_freezing;                /* PL: have wqs started freezing? */
 
 /* the per-cpu worker pools */
@@ -324,6 +332,7 @@ EXPORT_SYMBOL_GPL(system_freezable_power_efficient_wq);
 static int worker_thread(void *__worker);
 static void copy_workqueue_attrs(struct workqueue_attrs *to,
                                 const struct workqueue_attrs *from);
+static void workqueue_sysfs_unregister(struct workqueue_struct *wq);
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/workqueue.h>
@@ -1911,9 +1920,11 @@ static bool manage_workers(struct worker *worker)
         */
        if (!mutex_trylock(&pool->manager_arb))
                return false;
+       pool->manager = worker;
 
        maybe_create_worker(pool);
 
+       pool->manager = NULL;
        mutex_unlock(&pool->manager_arb);
        return true;
 }
@@ -2303,6 +2314,7 @@ repeat:
 struct wq_barrier {
        struct work_struct      work;
        struct completion       done;
+       struct task_struct      *task;  /* purely informational */
 };
 
 static void wq_barrier_func(struct work_struct *work)
@@ -2351,6 +2363,7 @@ static void insert_wq_barrier(struct pool_workqueue *pwq,
        INIT_WORK_ONSTACK(&barr->work, wq_barrier_func);
        __set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(&barr->work));
        init_completion(&barr->done);
+       barr->task = current;
 
        /*
         * If @target is currently being executed, schedule the
@@ -2989,624 +3002,319 @@ int execute_in_process_context(work_func_t fn, struct execute_work *ew)
 }
 EXPORT_SYMBOL_GPL(execute_in_process_context);
 
-#ifdef CONFIG_SYSFS
-/*
- * Workqueues with WQ_SYSFS flag set is visible to userland via
- * /sys/bus/workqueue/devices/WQ_NAME.  All visible workqueues have the
- * following attributes.
- *
- *  per_cpu    RO bool : whether the workqueue is per-cpu or unbound
- *  max_active RW int  : maximum number of in-flight work items
- *
- * Unbound workqueues have the following extra attributes.
+/**
+ * free_workqueue_attrs - free a workqueue_attrs
+ * @attrs: workqueue_attrs to free
  *
- *  id         RO int  : the associated pool ID
- *  nice       RW int  : nice value of the workers
- *  cpumask    RW mask : bitmask of allowed CPUs for the workers
+ * Undo alloc_workqueue_attrs().
  */
-struct wq_device {
-       struct workqueue_struct         *wq;
-       struct device                   dev;
-};
-
-static struct workqueue_struct *dev_to_wq(struct device *dev)
+void free_workqueue_attrs(struct workqueue_attrs *attrs)
 {
-       struct wq_device *wq_dev = container_of(dev, struct wq_device, dev);
-
-       return wq_dev->wq;
+       if (attrs) {
+               free_cpumask_var(attrs->cpumask);
+               kfree(attrs);
+       }
 }
 
-static ssize_t per_cpu_show(struct device *dev, struct device_attribute *attr,
-                           char *buf)
+/**
+ * alloc_workqueue_attrs - allocate a workqueue_attrs
+ * @gfp_mask: allocation mask to use
+ *
+ * Allocate a new workqueue_attrs, initialize with default settings and
+ * return it.
+ *
+ * Return: The allocated new workqueue_attr on success. %NULL on failure.
+ */
+struct workqueue_attrs *alloc_workqueue_attrs(gfp_t gfp_mask)
 {
-       struct workqueue_struct *wq = dev_to_wq(dev);
+       struct workqueue_attrs *attrs;
 
-       return scnprintf(buf, PAGE_SIZE, "%d\n", (bool)!(wq->flags & WQ_UNBOUND));
+       attrs = kzalloc(sizeof(*attrs), gfp_mask);
+       if (!attrs)
+               goto fail;
+       if (!alloc_cpumask_var(&attrs->cpumask, gfp_mask))
+               goto fail;
+
+       cpumask_copy(attrs->cpumask, cpu_possible_mask);
+       return attrs;
+fail:
+       free_workqueue_attrs(attrs);
+       return NULL;
 }
-static DEVICE_ATTR_RO(per_cpu);
 
-static ssize_t max_active_show(struct device *dev,
-                              struct device_attribute *attr, char *buf)
+static void copy_workqueue_attrs(struct workqueue_attrs *to,
+                                const struct workqueue_attrs *from)
 {
-       struct workqueue_struct *wq = dev_to_wq(dev);
-
-       return scnprintf(buf, PAGE_SIZE, "%d\n", wq->saved_max_active);
+       to->nice = from->nice;
+       cpumask_copy(to->cpumask, from->cpumask);
+       /*
+        * Unlike hash and equality test, this function doesn't ignore
+        * ->no_numa as it is used for both pool and wq attrs.  Instead,
+        * get_unbound_pool() explicitly clears ->no_numa after copying.
+        */
+       to->no_numa = from->no_numa;
 }
 
-static ssize_t max_active_store(struct device *dev,
-                               struct device_attribute *attr, const char *buf,
-                               size_t count)
+/* hash value of the content of @attr */
+static u32 wqattrs_hash(const struct workqueue_attrs *attrs)
 {
-       struct workqueue_struct *wq = dev_to_wq(dev);
-       int val;
-
-       if (sscanf(buf, "%d", &val) != 1 || val <= 0)
-               return -EINVAL;
+       u32 hash = 0;
 
-       workqueue_set_max_active(wq, val);
-       return count;
+       hash = jhash_1word(attrs->nice, hash);
+       hash = jhash(cpumask_bits(attrs->cpumask),
+                    BITS_TO_LONGS(nr_cpumask_bits) * sizeof(long), hash);
+       return hash;
 }
-static DEVICE_ATTR_RW(max_active);
-
-static struct attribute *wq_sysfs_attrs[] = {
-       &dev_attr_per_cpu.attr,
-       &dev_attr_max_active.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(wq_sysfs);
 
-static ssize_t wq_pool_ids_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
+/* content equality test */
+static bool wqattrs_equal(const struct workqueue_attrs *a,
+                         const struct workqueue_attrs *b)
 {
-       struct workqueue_struct *wq = dev_to_wq(dev);
-       const char *delim = "";
-       int node, written = 0;
-
-       rcu_read_lock_sched();
-       for_each_node(node) {
-               written += scnprintf(buf + written, PAGE_SIZE - written,
-                                    "%s%d:%d", delim, node,
-                                    unbound_pwq_by_node(wq, node)->pool->id);
-               delim = " ";
-       }
-       written += scnprintf(buf + written, PAGE_SIZE - written, "\n");
-       rcu_read_unlock_sched();
-
-       return written;
+       if (a->nice != b->nice)
+               return false;
+       if (!cpumask_equal(a->cpumask, b->cpumask))
+               return false;
+       return true;
 }
 
-static ssize_t wq_nice_show(struct device *dev, struct device_attribute *attr,
-                           char *buf)
+/**
+ * init_worker_pool - initialize a newly zalloc'd worker_pool
+ * @pool: worker_pool to initialize
+ *
+ * Initiailize a newly zalloc'd @pool.  It also allocates @pool->attrs.
+ *
+ * Return: 0 on success, -errno on failure.  Even on failure, all fields
+ * inside @pool proper are initialized and put_unbound_pool() can be called
+ * on @pool safely to release it.
+ */
+static int init_worker_pool(struct worker_pool *pool)
 {
-       struct workqueue_struct *wq = dev_to_wq(dev);
-       int written;
+       spin_lock_init(&pool->lock);
+       pool->id = -1;
+       pool->cpu = -1;
+       pool->node = NUMA_NO_NODE;
+       pool->flags |= POOL_DISASSOCIATED;
+       INIT_LIST_HEAD(&pool->worklist);
+       INIT_LIST_HEAD(&pool->idle_list);
+       hash_init(pool->busy_hash);
 
-       mutex_lock(&wq->mutex);
-       written = scnprintf(buf, PAGE_SIZE, "%d\n", wq->unbound_attrs->nice);
-       mutex_unlock(&wq->mutex);
+       init_timer_deferrable(&pool->idle_timer);
+       pool->idle_timer.function = idle_worker_timeout;
+       pool->idle_timer.data = (unsigned long)pool;
 
-       return written;
-}
+       setup_timer(&pool->mayday_timer, pool_mayday_timeout,
+                   (unsigned long)pool);
 
-/* prepare workqueue_attrs for sysfs store operations */
-static struct workqueue_attrs *wq_sysfs_prep_attrs(struct workqueue_struct *wq)
-{
-       struct workqueue_attrs *attrs;
+       mutex_init(&pool->manager_arb);
+       mutex_init(&pool->attach_mutex);
+       INIT_LIST_HEAD(&pool->workers);
 
-       attrs = alloc_workqueue_attrs(GFP_KERNEL);
-       if (!attrs)
-               return NULL;
+       ida_init(&pool->worker_ida);
+       INIT_HLIST_NODE(&pool->hash_node);
+       pool->refcnt = 1;
 
-       mutex_lock(&wq->mutex);
-       copy_workqueue_attrs(attrs, wq->unbound_attrs);
-       mutex_unlock(&wq->mutex);
-       return attrs;
+       /* shouldn't fail above this point */
+       pool->attrs = alloc_workqueue_attrs(GFP_KERNEL);
+       if (!pool->attrs)
+               return -ENOMEM;
+       return 0;
 }
 
-static ssize_t wq_nice_store(struct device *dev, struct device_attribute *attr,
-                            const char *buf, size_t count)
+static void rcu_free_wq(struct rcu_head *rcu)
 {
-       struct workqueue_struct *wq = dev_to_wq(dev);
-       struct workqueue_attrs *attrs;
-       int ret;
-
-       attrs = wq_sysfs_prep_attrs(wq);
-       if (!attrs)
-               return -ENOMEM;
+       struct workqueue_struct *wq =
+               container_of(rcu, struct workqueue_struct, rcu);
 
-       if (sscanf(buf, "%d", &attrs->nice) == 1 &&
-           attrs->nice >= MIN_NICE && attrs->nice <= MAX_NICE)
-               ret = apply_workqueue_attrs(wq, attrs);
+       if (!(wq->flags & WQ_UNBOUND))
+               free_percpu(wq->cpu_pwqs);
        else
-               ret = -EINVAL;
+               free_workqueue_attrs(wq->unbound_attrs);
 
-       free_workqueue_attrs(attrs);
-       return ret ?: count;
+       kfree(wq->rescuer);
+       kfree(wq);
 }
 
-static ssize_t wq_cpumask_show(struct device *dev,
-                              struct device_attribute *attr, char *buf)
+static void rcu_free_pool(struct rcu_head *rcu)
 {
-       struct workqueue_struct *wq = dev_to_wq(dev);
-       int written;
+       struct worker_pool *pool = container_of(rcu, struct worker_pool, rcu);
 
-       mutex_lock(&wq->mutex);
-       written = scnprintf(buf, PAGE_SIZE, "%*pb\n",
-                           cpumask_pr_args(wq->unbound_attrs->cpumask));
-       mutex_unlock(&wq->mutex);
-       return written;
+       ida_destroy(&pool->worker_ida);
+       free_workqueue_attrs(pool->attrs);
+       kfree(pool);
 }
 
-static ssize_t wq_cpumask_store(struct device *dev,
-                               struct device_attribute *attr,
-                               const char *buf, size_t count)
+/**
+ * put_unbound_pool - put a worker_pool
+ * @pool: worker_pool to put
+ *
+ * Put @pool.  If its refcnt reaches zero, it gets destroyed in sched-RCU
+ * safe manner.  get_unbound_pool() calls this function on its failure path
+ * and this function should be able to release pools which went through,
+ * successfully or not, init_worker_pool().
+ *
+ * Should be called with wq_pool_mutex held.
+ */
+static void put_unbound_pool(struct worker_pool *pool)
 {
-       struct workqueue_struct *wq = dev_to_wq(dev);
-       struct workqueue_attrs *attrs;
-       int ret;
+       DECLARE_COMPLETION_ONSTACK(detach_completion);
+       struct worker *worker;
 
-       attrs = wq_sysfs_prep_attrs(wq);
-       if (!attrs)
-               return -ENOMEM;
+       lockdep_assert_held(&wq_pool_mutex);
 
-       ret = cpumask_parse(buf, attrs->cpumask);
-       if (!ret)
-               ret = apply_workqueue_attrs(wq, attrs);
+       if (--pool->refcnt)
+               return;
 
-       free_workqueue_attrs(attrs);
-       return ret ?: count;
-}
+       /* sanity checks */
+       if (WARN_ON(!(pool->cpu < 0)) ||
+           WARN_ON(!list_empty(&pool->worklist)))
+               return;
 
-static ssize_t wq_numa_show(struct device *dev, struct device_attribute *attr,
-                           char *buf)
-{
-       struct workqueue_struct *wq = dev_to_wq(dev);
-       int written;
-
-       mutex_lock(&wq->mutex);
-       written = scnprintf(buf, PAGE_SIZE, "%d\n",
-                           !wq->unbound_attrs->no_numa);
-       mutex_unlock(&wq->mutex);
-
-       return written;
-}
-
-static ssize_t wq_numa_store(struct device *dev, struct device_attribute *attr,
-                            const char *buf, size_t count)
-{
-       struct workqueue_struct *wq = dev_to_wq(dev);
-       struct workqueue_attrs *attrs;
-       int v, ret;
-
-       attrs = wq_sysfs_prep_attrs(wq);
-       if (!attrs)
-               return -ENOMEM;
+       /* release id and unhash */
+       if (pool->id >= 0)
+               idr_remove(&worker_pool_idr, pool->id);
+       hash_del(&pool->hash_node);
 
-       ret = -EINVAL;
-       if (sscanf(buf, "%d", &v) == 1) {
-               attrs->no_numa = !v;
-               ret = apply_workqueue_attrs(wq, attrs);
-       }
+       /*
+        * Become the manager and destroy all workers.  Grabbing
+        * manager_arb prevents @pool's workers from blocking on
+        * attach_mutex.
+        */
+       mutex_lock(&pool->manager_arb);
 
-       free_workqueue_attrs(attrs);
-       return ret ?: count;
-}
+       spin_lock_irq(&pool->lock);
+       while ((worker = first_idle_worker(pool)))
+               destroy_worker(worker);
+       WARN_ON(pool->nr_workers || pool->nr_idle);
+       spin_unlock_irq(&pool->lock);
 
-static struct device_attribute wq_sysfs_unbound_attrs[] = {
-       __ATTR(pool_ids, 0444, wq_pool_ids_show, NULL),
-       __ATTR(nice, 0644, wq_nice_show, wq_nice_store),
-       __ATTR(cpumask, 0644, wq_cpumask_show, wq_cpumask_store),
-       __ATTR(numa, 0644, wq_numa_show, wq_numa_store),
-       __ATTR_NULL,
-};
+       mutex_lock(&pool->attach_mutex);
+       if (!list_empty(&pool->workers))
+               pool->detach_completion = &detach_completion;
+       mutex_unlock(&pool->attach_mutex);
 
-static struct bus_type wq_subsys = {
-       .name                           = "workqueue",
-       .dev_groups                     = wq_sysfs_groups,
-};
+       if (pool->detach_completion)
+               wait_for_completion(pool->detach_completion);
 
-static int __init wq_sysfs_init(void)
-{
-       return subsys_virtual_register(&wq_subsys, NULL);
-}
-core_initcall(wq_sysfs_init);
+       mutex_unlock(&pool->manager_arb);
 
-static void wq_device_release(struct device *dev)
-{
-       struct wq_device *wq_dev = container_of(dev, struct wq_device, dev);
+       /* shut down the timers */
+       del_timer_sync(&pool->idle_timer);
+       del_timer_sync(&pool->mayday_timer);
 
-       kfree(wq_dev);
+       /* sched-RCU protected to allow dereferences from get_work_pool() */
+       call_rcu_sched(&pool->rcu, rcu_free_pool);
 }
 
 /**
- * workqueue_sysfs_register - make a workqueue visible in sysfs
- * @wq: the workqueue to register
+ * get_unbound_pool - get a worker_pool with the specified attributes
+ * @attrs: the attributes of the worker_pool to get
  *
- * Expose @wq in sysfs under /sys/bus/workqueue/devices.
- * alloc_workqueue*() automatically calls this function if WQ_SYSFS is set
- * which is the preferred method.
+ * Obtain a worker_pool which has the same attributes as @attrs, bump the
+ * reference count and return it.  If there already is a matching
+ * worker_pool, it will be used; otherwise, this function attempts to
+ * create a new one.
  *
- * Workqueue user should use this function directly iff it wants to apply
- * workqueue_attrs before making the workqueue visible in sysfs; otherwise,
- * apply_workqueue_attrs() may race against userland updating the
- * attributes.
+ * Should be called with wq_pool_mutex held.
  *
- * Return: 0 on success, -errno on failure.
+ * Return: On success, a worker_pool with the same attributes as @attrs.
+ * On failure, %NULL.
  */
-int workqueue_sysfs_register(struct workqueue_struct *wq)
+static struct worker_pool *get_unbound_pool(const struct workqueue_attrs *attrs)
 {
-       struct wq_device *wq_dev;
-       int ret;
+       u32 hash = wqattrs_hash(attrs);
+       struct worker_pool *pool;
+       int node;
 
-       /*
-        * Adjusting max_active or creating new pwqs by applyting
-        * attributes breaks ordering guarantee.  Disallow exposing ordered
-        * workqueues.
-        */
-       if (WARN_ON(wq->flags & __WQ_ORDERED))
-               return -EINVAL;
+       lockdep_assert_held(&wq_pool_mutex);
 
-       wq->wq_dev = wq_dev = kzalloc(sizeof(*wq_dev), GFP_KERNEL);
-       if (!wq_dev)
-               return -ENOMEM;
+       /* do we already have a matching pool? */
+       hash_for_each_possible(unbound_pool_hash, pool, hash_node, hash) {
+               if (wqattrs_equal(pool->attrs, attrs)) {
+                       pool->refcnt++;
+                       return pool;
+               }
+       }
 
-       wq_dev->wq = wq;
-       wq_dev->dev.bus = &wq_subsys;
-       wq_dev->dev.init_name = wq->name;
-       wq_dev->dev.release = wq_device_release;
+       /* nope, create a new one */
+       pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+       if (!pool || init_worker_pool(pool) < 0)
+               goto fail;
+
+       lockdep_set_subclass(&pool->lock, 1);   /* see put_pwq() */
+       copy_workqueue_attrs(pool->attrs, attrs);
 
        /*
-        * unbound_attrs are created separately.  Suppress uevent until
-        * everything is ready.
+        * no_numa isn't a worker_pool attribute, always clear it.  See
+        * 'struct workqueue_attrs' comments for detail.
         */
-       dev_set_uevent_suppress(&wq_dev->dev, true);
-
-       ret = device_register(&wq_dev->dev);
-       if (ret) {
-               kfree(wq_dev);
-               wq->wq_dev = NULL;
-               return ret;
-       }
-
-       if (wq->flags & WQ_UNBOUND) {
-               struct device_attribute *attr;
+       pool->attrs->no_numa = false;
 
-               for (attr = wq_sysfs_unbound_attrs; attr->attr.name; attr++) {
-                       ret = device_create_file(&wq_dev->dev, attr);
-                       if (ret) {
-                               device_unregister(&wq_dev->dev);
-                               wq->wq_dev = NULL;
-                               return ret;
+       /* if cpumask is contained inside a NUMA node, we belong to that node */
+       if (wq_numa_enabled) {
+               for_each_node(node) {
+                       if (cpumask_subset(pool->attrs->cpumask,
+                                          wq_numa_possible_cpumask[node])) {
+                               pool->node = node;
+                               break;
                        }
                }
        }
 
-       dev_set_uevent_suppress(&wq_dev->dev, false);
-       kobject_uevent(&wq_dev->dev.kobj, KOBJ_ADD);
-       return 0;
-}
+       if (worker_pool_assign_id(pool) < 0)
+               goto fail;
 
-/**
- * workqueue_sysfs_unregister - undo workqueue_sysfs_register()
- * @wq: the workqueue to unregister
- *
- * If @wq is registered to sysfs by workqueue_sysfs_register(), unregister.
- */
-static void workqueue_sysfs_unregister(struct workqueue_struct *wq)
-{
-       struct wq_device *wq_dev = wq->wq_dev;
+       /* create and start the initial worker */
+       if (!create_worker(pool))
+               goto fail;
 
-       if (!wq->wq_dev)
-               return;
+       /* install */
+       hash_add(unbound_pool_hash, &pool->hash_node, hash);
 
-       wq->wq_dev = NULL;
-       device_unregister(&wq_dev->dev);
+       return pool;
+fail:
+       if (pool)
+               put_unbound_pool(pool);
+       return NULL;
 }
-#else  /* CONFIG_SYSFS */
-static void workqueue_sysfs_unregister(struct workqueue_struct *wq)    { }
-#endif /* CONFIG_SYSFS */
 
-/**
- * free_workqueue_attrs - free a workqueue_attrs
- * @attrs: workqueue_attrs to free
- *
- * Undo alloc_workqueue_attrs().
- */
-void free_workqueue_attrs(struct workqueue_attrs *attrs)
+static void rcu_free_pwq(struct rcu_head *rcu)
 {
-       if (attrs) {
-               free_cpumask_var(attrs->cpumask);
-               kfree(attrs);
-       }
+       kmem_cache_free(pwq_cache,
+                       container_of(rcu, struct pool_workqueue, rcu));
 }
 
-/**
- * alloc_workqueue_attrs - allocate a workqueue_attrs
- * @gfp_mask: allocation mask to use
- *
- * Allocate a new workqueue_attrs, initialize with default settings and
- * return it.
- *
- * Return: The allocated new workqueue_attr on success. %NULL on failure.
+/*
+ * Scheduled on system_wq by put_pwq() when an unbound pwq hits zero refcnt
+ * and needs to be destroyed.
  */
-struct workqueue_attrs *alloc_workqueue_attrs(gfp_t gfp_mask)
+static void pwq_unbound_release_workfn(struct work_struct *work)
 {
-       struct workqueue_attrs *attrs;
+       struct pool_workqueue *pwq = container_of(work, struct pool_workqueue,
+                                                 unbound_release_work);
+       struct workqueue_struct *wq = pwq->wq;
+       struct worker_pool *pool = pwq->pool;
+       bool is_last;
 
-       attrs = kzalloc(sizeof(*attrs), gfp_mask);
-       if (!attrs)
-               goto fail;
-       if (!alloc_cpumask_var(&attrs->cpumask, gfp_mask))
-               goto fail;
+       if (WARN_ON_ONCE(!(wq->flags & WQ_UNBOUND)))
+               return;
 
-       cpumask_copy(attrs->cpumask, cpu_possible_mask);
-       return attrs;
-fail:
-       free_workqueue_attrs(attrs);
-       return NULL;
-}
+       mutex_lock(&wq->mutex);
+       list_del_rcu(&pwq->pwqs_node);
+       is_last = list_empty(&wq->pwqs);
+       mutex_unlock(&wq->mutex);
+
+       mutex_lock(&wq_pool_mutex);
+       put_unbound_pool(pool);
+       mutex_unlock(&wq_pool_mutex);
+
+       call_rcu_sched(&pwq->rcu, rcu_free_pwq);
 
-static void copy_workqueue_attrs(struct workqueue_attrs *to,
-                                const struct workqueue_attrs *from)
-{
-       to->nice = from->nice;
-       cpumask_copy(to->cpumask, from->cpumask);
        /*
-        * Unlike hash and equality test, this function doesn't ignore
-        * ->no_numa as it is used for both pool and wq attrs.  Instead,
-        * get_unbound_pool() explicitly clears ->no_numa after copying.
+        * If we're the last pwq going away, @wq is already dead and no one
+        * is gonna access it anymore.  Schedule RCU free.
         */
-       to->no_numa = from->no_numa;
-}
-
-/* hash value of the content of @attr */
-static u32 wqattrs_hash(const struct workqueue_attrs *attrs)
-{
-       u32 hash = 0;
-
-       hash = jhash_1word(attrs->nice, hash);
-       hash = jhash(cpumask_bits(attrs->cpumask),
-                    BITS_TO_LONGS(nr_cpumask_bits) * sizeof(long), hash);
-       return hash;
-}
-
-/* content equality test */
-static bool wqattrs_equal(const struct workqueue_attrs *a,
-                         const struct workqueue_attrs *b)
-{
-       if (a->nice != b->nice)
-               return false;
-       if (!cpumask_equal(a->cpumask, b->cpumask))
-               return false;
-       return true;
-}
-
-/**
- * init_worker_pool - initialize a newly zalloc'd worker_pool
- * @pool: worker_pool to initialize
- *
- * Initiailize a newly zalloc'd @pool.  It also allocates @pool->attrs.
- *
- * Return: 0 on success, -errno on failure.  Even on failure, all fields
- * inside @pool proper are initialized and put_unbound_pool() can be called
- * on @pool safely to release it.
- */
-static int init_worker_pool(struct worker_pool *pool)
-{
-       spin_lock_init(&pool->lock);
-       pool->id = -1;
-       pool->cpu = -1;
-       pool->node = NUMA_NO_NODE;
-       pool->flags |= POOL_DISASSOCIATED;
-       INIT_LIST_HEAD(&pool->worklist);
-       INIT_LIST_HEAD(&pool->idle_list);
-       hash_init(pool->busy_hash);
-
-       init_timer_deferrable(&pool->idle_timer);
-       pool->idle_timer.function = idle_worker_timeout;
-       pool->idle_timer.data = (unsigned long)pool;
-
-       setup_timer(&pool->mayday_timer, pool_mayday_timeout,
-                   (unsigned long)pool);
-
-       mutex_init(&pool->manager_arb);
-       mutex_init(&pool->attach_mutex);
-       INIT_LIST_HEAD(&pool->workers);
-
-       ida_init(&pool->worker_ida);
-       INIT_HLIST_NODE(&pool->hash_node);
-       pool->refcnt = 1;
-
-       /* shouldn't fail above this point */
-       pool->attrs = alloc_workqueue_attrs(GFP_KERNEL);
-       if (!pool->attrs)
-               return -ENOMEM;
-       return 0;
-}
-
-static void rcu_free_pool(struct rcu_head *rcu)
-{
-       struct worker_pool *pool = container_of(rcu, struct worker_pool, rcu);
-
-       ida_destroy(&pool->worker_ida);
-       free_workqueue_attrs(pool->attrs);
-       kfree(pool);
-}
-
-/**
- * put_unbound_pool - put a worker_pool
- * @pool: worker_pool to put
- *
- * Put @pool.  If its refcnt reaches zero, it gets destroyed in sched-RCU
- * safe manner.  get_unbound_pool() calls this function on its failure path
- * and this function should be able to release pools which went through,
- * successfully or not, init_worker_pool().
- *
- * Should be called with wq_pool_mutex held.
- */
-static void put_unbound_pool(struct worker_pool *pool)
-{
-       DECLARE_COMPLETION_ONSTACK(detach_completion);
-       struct worker *worker;
-
-       lockdep_assert_held(&wq_pool_mutex);
-
-       if (--pool->refcnt)
-               return;
-
-       /* sanity checks */
-       if (WARN_ON(!(pool->cpu < 0)) ||
-           WARN_ON(!list_empty(&pool->worklist)))
-               return;
-
-       /* release id and unhash */
-       if (pool->id >= 0)
-               idr_remove(&worker_pool_idr, pool->id);
-       hash_del(&pool->hash_node);
-
-       /*
-        * Become the manager and destroy all workers.  Grabbing
-        * manager_arb prevents @pool's workers from blocking on
-        * attach_mutex.
-        */
-       mutex_lock(&pool->manager_arb);
-
-       spin_lock_irq(&pool->lock);
-       while ((worker = first_idle_worker(pool)))
-               destroy_worker(worker);
-       WARN_ON(pool->nr_workers || pool->nr_idle);
-       spin_unlock_irq(&pool->lock);
-
-       mutex_lock(&pool->attach_mutex);
-       if (!list_empty(&pool->workers))
-               pool->detach_completion = &detach_completion;
-       mutex_unlock(&pool->attach_mutex);
-
-       if (pool->detach_completion)
-               wait_for_completion(pool->detach_completion);
-
-       mutex_unlock(&pool->manager_arb);
-
-       /* shut down the timers */
-       del_timer_sync(&pool->idle_timer);
-       del_timer_sync(&pool->mayday_timer);
-
-       /* sched-RCU protected to allow dereferences from get_work_pool() */
-       call_rcu_sched(&pool->rcu, rcu_free_pool);
-}
-
-/**
- * get_unbound_pool - get a worker_pool with the specified attributes
- * @attrs: the attributes of the worker_pool to get
- *
- * Obtain a worker_pool which has the same attributes as @attrs, bump the
- * reference count and return it.  If there already is a matching
- * worker_pool, it will be used; otherwise, this function attempts to
- * create a new one.
- *
- * Should be called with wq_pool_mutex held.
- *
- * Return: On success, a worker_pool with the same attributes as @attrs.
- * On failure, %NULL.
- */
-static struct worker_pool *get_unbound_pool(const struct workqueue_attrs *attrs)
-{
-       u32 hash = wqattrs_hash(attrs);
-       struct worker_pool *pool;
-       int node;
-
-       lockdep_assert_held(&wq_pool_mutex);
-
-       /* do we already have a matching pool? */
-       hash_for_each_possible(unbound_pool_hash, pool, hash_node, hash) {
-               if (wqattrs_equal(pool->attrs, attrs)) {
-                       pool->refcnt++;
-                       return pool;
-               }
-       }
-
-       /* nope, create a new one */
-       pool = kzalloc(sizeof(*pool), GFP_KERNEL);
-       if (!pool || init_worker_pool(pool) < 0)
-               goto fail;
-
-       lockdep_set_subclass(&pool->lock, 1);   /* see put_pwq() */
-       copy_workqueue_attrs(pool->attrs, attrs);
-
-       /*
-        * no_numa isn't a worker_pool attribute, always clear it.  See
-        * 'struct workqueue_attrs' comments for detail.
-        */
-       pool->attrs->no_numa = false;
-
-       /* if cpumask is contained inside a NUMA node, we belong to that node */
-       if (wq_numa_enabled) {
-               for_each_node(node) {
-                       if (cpumask_subset(pool->attrs->cpumask,
-                                          wq_numa_possible_cpumask[node])) {
-                               pool->node = node;
-                               break;
-                       }
-               }
-       }
-
-       if (worker_pool_assign_id(pool) < 0)
-               goto fail;
-
-       /* create and start the initial worker */
-       if (!create_worker(pool))
-               goto fail;
-
-       /* install */
-       hash_add(unbound_pool_hash, &pool->hash_node, hash);
-
-       return pool;
-fail:
-       if (pool)
-               put_unbound_pool(pool);
-       return NULL;
-}
-
-static void rcu_free_pwq(struct rcu_head *rcu)
-{
-       kmem_cache_free(pwq_cache,
-                       container_of(rcu, struct pool_workqueue, rcu));
-}
-
-/*
- * Scheduled on system_wq by put_pwq() when an unbound pwq hits zero refcnt
- * and needs to be destroyed.
- */
-static void pwq_unbound_release_workfn(struct work_struct *work)
-{
-       struct pool_workqueue *pwq = container_of(work, struct pool_workqueue,
-                                                 unbound_release_work);
-       struct workqueue_struct *wq = pwq->wq;
-       struct worker_pool *pool = pwq->pool;
-       bool is_last;
-
-       if (WARN_ON_ONCE(!(wq->flags & WQ_UNBOUND)))
-               return;
-
-       mutex_lock(&wq->mutex);
-       list_del_rcu(&pwq->pwqs_node);
-       is_last = list_empty(&wq->pwqs);
-       mutex_unlock(&wq->mutex);
-
-       mutex_lock(&wq_pool_mutex);
-       put_unbound_pool(pool);
-       mutex_unlock(&wq_pool_mutex);
-
-       call_rcu_sched(&pwq->rcu, rcu_free_pwq);
-
-       /*
-        * If we're the last pwq going away, @wq is already dead and no one
-        * is gonna access it anymore.  Free it.
-        */
-       if (is_last) {
-               free_workqueue_attrs(wq->unbound_attrs);
-               kfree(wq);
-       }
+       if (is_last)
+               call_rcu_sched(&wq->rcu, rcu_free_wq);
 }
 
 /**
@@ -4143,7 +3851,7 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
                pwq_adjust_max_active(pwq);
        mutex_unlock(&wq->mutex);
 
-       list_add(&wq->list, &workqueues);
+       list_add_tail_rcu(&wq->list, &workqueues);
 
        mutex_unlock(&wq_pool_mutex);
 
@@ -4199,24 +3907,20 @@ void destroy_workqueue(struct workqueue_struct *wq)
         * flushing is complete in case freeze races us.
         */
        mutex_lock(&wq_pool_mutex);
-       list_del_init(&wq->list);
+       list_del_rcu(&wq->list);
        mutex_unlock(&wq_pool_mutex);
 
        workqueue_sysfs_unregister(wq);
 
-       if (wq->rescuer) {
+       if (wq->rescuer)
                kthread_stop(wq->rescuer->task);
-               kfree(wq->rescuer);
-               wq->rescuer = NULL;
-       }
 
        if (!(wq->flags & WQ_UNBOUND)) {
                /*
                 * The base ref is never dropped on per-cpu pwqs.  Directly
-                * free the pwqs and wq.
+                * schedule RCU free.
                 */
-               free_percpu(wq->cpu_pwqs);
-               kfree(wq);
+               call_rcu_sched(&wq->rcu, rcu_free_wq);
        } else {
                /*
                 * We're the sole accessor of @wq at this point.  Directly
@@ -4437,13 +4141,173 @@ void print_worker_info(const char *log_lvl, struct task_struct *task)
        }
 }
 
-/*
- * CPU hotplug.
- *
- * There are two challenges in supporting CPU hotplug.  Firstly, there
- * are a lot of assumptions on strong associations among work, pwq and
- * pool which make migrating pending and scheduled works very
- * difficult to implement without impacting hot paths.  Secondly,
+static void pr_cont_pool_info(struct worker_pool *pool)
+{
+       pr_cont(" cpus=%*pbl", nr_cpumask_bits, pool->attrs->cpumask);
+       if (pool->node != NUMA_NO_NODE)
+               pr_cont(" node=%d", pool->node);
+       pr_cont(" flags=0x%x nice=%d", pool->flags, pool->attrs->nice);
+}
+
+static void pr_cont_work(bool comma, struct work_struct *work)
+{
+       if (work->func == wq_barrier_func) {
+               struct wq_barrier *barr;
+
+               barr = container_of(work, struct wq_barrier, work);
+
+               pr_cont("%s BAR(%d)", comma ? "," : "",
+                       task_pid_nr(barr->task));
+       } else {
+               pr_cont("%s %pf", comma ? "," : "", work->func);
+       }
+}
+
+static void show_pwq(struct pool_workqueue *pwq)
+{
+       struct worker_pool *pool = pwq->pool;
+       struct work_struct *work;
+       struct worker *worker;
+       bool has_in_flight = false, has_pending = false;
+       int bkt;
+
+       pr_info("  pwq %d:", pool->id);
+       pr_cont_pool_info(pool);
+
+       pr_cont(" active=%d/%d%s\n", pwq->nr_active, pwq->max_active,
+               !list_empty(&pwq->mayday_node) ? " MAYDAY" : "");
+
+       hash_for_each(pool->busy_hash, bkt, worker, hentry) {
+               if (worker->current_pwq == pwq) {
+                       has_in_flight = true;
+                       break;
+               }
+       }
+       if (has_in_flight) {
+               bool comma = false;
+
+               pr_info("    in-flight:");
+               hash_for_each(pool->busy_hash, bkt, worker, hentry) {
+                       if (worker->current_pwq != pwq)
+                               continue;
+
+                       pr_cont("%s %d%s:%pf", comma ? "," : "",
+                               task_pid_nr(worker->task),
+                               worker == pwq->wq->rescuer ? "(RESCUER)" : "",
+                               worker->current_func);
+                       list_for_each_entry(work, &worker->scheduled, entry)
+                               pr_cont_work(false, work);
+                       comma = true;
+               }
+               pr_cont("\n");
+       }
+
+       list_for_each_entry(work, &pool->worklist, entry) {
+               if (get_work_pwq(work) == pwq) {
+                       has_pending = true;
+                       break;
+               }
+       }
+       if (has_pending) {
+               bool comma = false;
+
+               pr_info("    pending:");
+               list_for_each_entry(work, &pool->worklist, entry) {
+                       if (get_work_pwq(work) != pwq)
+                               continue;
+
+                       pr_cont_work(comma, work);
+                       comma = !(*work_data_bits(work) & WORK_STRUCT_LINKED);
+               }
+               pr_cont("\n");
+       }
+
+       if (!list_empty(&pwq->delayed_works)) {
+               bool comma = false;
+
+               pr_info("    delayed:");
+               list_for_each_entry(work, &pwq->delayed_works, entry) {
+                       pr_cont_work(comma, work);
+                       comma = !(*work_data_bits(work) & WORK_STRUCT_LINKED);
+               }
+               pr_cont("\n");
+       }
+}
+
+/**
+ * show_workqueue_state - dump workqueue state
+ *
+ * Called from a sysrq handler and prints out all busy workqueues and
+ * pools.
+ */
+void show_workqueue_state(void)
+{
+       struct workqueue_struct *wq;
+       struct worker_pool *pool;
+       unsigned long flags;
+       int pi;
+
+       rcu_read_lock_sched();
+
+       pr_info("Showing busy workqueues and worker pools:\n");
+
+       list_for_each_entry_rcu(wq, &workqueues, list) {
+               struct pool_workqueue *pwq;
+               bool idle = true;
+
+               for_each_pwq(pwq, wq) {
+                       if (pwq->nr_active || !list_empty(&pwq->delayed_works)) {
+                               idle = false;
+                               break;
+                       }
+               }
+               if (idle)
+                       continue;
+
+               pr_info("workqueue %s: flags=0x%x\n", wq->name, wq->flags);
+
+               for_each_pwq(pwq, wq) {
+                       spin_lock_irqsave(&pwq->pool->lock, flags);
+                       if (pwq->nr_active || !list_empty(&pwq->delayed_works))
+                               show_pwq(pwq);
+                       spin_unlock_irqrestore(&pwq->pool->lock, flags);
+               }
+       }
+
+       for_each_pool(pool, pi) {
+               struct worker *worker;
+               bool first = true;
+
+               spin_lock_irqsave(&pool->lock, flags);
+               if (pool->nr_workers == pool->nr_idle)
+                       goto next_pool;
+
+               pr_info("pool %d:", pool->id);
+               pr_cont_pool_info(pool);
+               pr_cont(" workers=%d", pool->nr_workers);
+               if (pool->manager)
+                       pr_cont(" manager: %d",
+                               task_pid_nr(pool->manager->task));
+               list_for_each_entry(worker, &pool->idle_list, entry) {
+                       pr_cont(" %s%d", first ? "idle: " : "",
+                               task_pid_nr(worker->task));
+                       first = false;
+               }
+               pr_cont("\n");
+       next_pool:
+               spin_unlock_irqrestore(&pool->lock, flags);
+       }
+
+       rcu_read_unlock_sched();
+}
+
+/*
+ * CPU hotplug.
+ *
+ * There are two challenges in supporting CPU hotplug.  Firstly, there
+ * are a lot of assumptions on strong associations among work, pwq and
+ * pool which make migrating pending and scheduled works very
+ * difficult to implement without impacting hot paths.  Secondly,
  * worker pools serve mix of short, long and very long running works making
  * blocked draining impractical.
  *
@@ -4637,202 +4501,519 @@ static int workqueue_cpu_up_callback(struct notifier_block *nfb,
                        else if (pool->cpu < 0)
                                restore_unbound_workers_cpumask(pool, cpu);
 
-                       mutex_unlock(&pool->attach_mutex);
-               }
+                       mutex_unlock(&pool->attach_mutex);
+               }
+
+               /* update NUMA affinity of unbound workqueues */
+               list_for_each_entry(wq, &workqueues, list)
+                       wq_update_unbound_numa(wq, cpu, true);
+
+               mutex_unlock(&wq_pool_mutex);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+/*
+ * Workqueues should be brought down after normal priority CPU notifiers.
+ * This will be registered as low priority CPU notifier.
+ */
+static int workqueue_cpu_down_callback(struct notifier_block *nfb,
+                                                unsigned long action,
+                                                void *hcpu)
+{
+       int cpu = (unsigned long)hcpu;
+       struct work_struct unbind_work;
+       struct workqueue_struct *wq;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_DOWN_PREPARE:
+               /* unbinding per-cpu workers should happen on the local CPU */
+               INIT_WORK_ONSTACK(&unbind_work, wq_unbind_fn);
+               queue_work_on(cpu, system_highpri_wq, &unbind_work);
+
+               /* update NUMA affinity of unbound workqueues */
+               mutex_lock(&wq_pool_mutex);
+               list_for_each_entry(wq, &workqueues, list)
+                       wq_update_unbound_numa(wq, cpu, false);
+               mutex_unlock(&wq_pool_mutex);
+
+               /* wait for per-cpu unbinding to finish */
+               flush_work(&unbind_work);
+               destroy_work_on_stack(&unbind_work);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+#ifdef CONFIG_SMP
+
+struct work_for_cpu {
+       struct work_struct work;
+       long (*fn)(void *);
+       void *arg;
+       long ret;
+};
+
+static void work_for_cpu_fn(struct work_struct *work)
+{
+       struct work_for_cpu *wfc = container_of(work, struct work_for_cpu, work);
+
+       wfc->ret = wfc->fn(wfc->arg);
+}
+
+/**
+ * work_on_cpu - run a function in user context on a particular cpu
+ * @cpu: the cpu to run on
+ * @fn: the function to run
+ * @arg: the function arg
+ *
+ * It is up to the caller to ensure that the cpu doesn't go offline.
+ * The caller must not hold any locks which would prevent @fn from completing.
+ *
+ * Return: The value @fn returns.
+ */
+long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
+{
+       struct work_for_cpu wfc = { .fn = fn, .arg = arg };
+
+       INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
+       schedule_work_on(cpu, &wfc.work);
+       flush_work(&wfc.work);
+       destroy_work_on_stack(&wfc.work);
+       return wfc.ret;
+}
+EXPORT_SYMBOL_GPL(work_on_cpu);
+#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_FREEZER
+
+/**
+ * freeze_workqueues_begin - begin freezing workqueues
+ *
+ * Start freezing workqueues.  After this function returns, all freezable
+ * workqueues will queue new works to their delayed_works list instead of
+ * pool->worklist.
+ *
+ * CONTEXT:
+ * Grabs and releases wq_pool_mutex, wq->mutex and pool->lock's.
+ */
+void freeze_workqueues_begin(void)
+{
+       struct workqueue_struct *wq;
+       struct pool_workqueue *pwq;
+
+       mutex_lock(&wq_pool_mutex);
+
+       WARN_ON_ONCE(workqueue_freezing);
+       workqueue_freezing = true;
+
+       list_for_each_entry(wq, &workqueues, list) {
+               mutex_lock(&wq->mutex);
+               for_each_pwq(pwq, wq)
+                       pwq_adjust_max_active(pwq);
+               mutex_unlock(&wq->mutex);
+       }
+
+       mutex_unlock(&wq_pool_mutex);
+}
+
+/**
+ * freeze_workqueues_busy - are freezable workqueues still busy?
+ *
+ * Check whether freezing is complete.  This function must be called
+ * between freeze_workqueues_begin() and thaw_workqueues().
+ *
+ * CONTEXT:
+ * Grabs and releases wq_pool_mutex.
+ *
+ * Return:
+ * %true if some freezable workqueues are still busy.  %false if freezing
+ * is complete.
+ */
+bool freeze_workqueues_busy(void)
+{
+       bool busy = false;
+       struct workqueue_struct *wq;
+       struct pool_workqueue *pwq;
+
+       mutex_lock(&wq_pool_mutex);
+
+       WARN_ON_ONCE(!workqueue_freezing);
+
+       list_for_each_entry(wq, &workqueues, list) {
+               if (!(wq->flags & WQ_FREEZABLE))
+                       continue;
+               /*
+                * nr_active is monotonically decreasing.  It's safe
+                * to peek without lock.
+                */
+               rcu_read_lock_sched();
+               for_each_pwq(pwq, wq) {
+                       WARN_ON_ONCE(pwq->nr_active < 0);
+                       if (pwq->nr_active) {
+                               busy = true;
+                               rcu_read_unlock_sched();
+                               goto out_unlock;
+                       }
+               }
+               rcu_read_unlock_sched();
+       }
+out_unlock:
+       mutex_unlock(&wq_pool_mutex);
+       return busy;
+}
+
+/**
+ * thaw_workqueues - thaw workqueues
+ *
+ * Thaw workqueues.  Normal queueing is restored and all collected
+ * frozen works are transferred to their respective pool worklists.
+ *
+ * CONTEXT:
+ * Grabs and releases wq_pool_mutex, wq->mutex and pool->lock's.
+ */
+void thaw_workqueues(void)
+{
+       struct workqueue_struct *wq;
+       struct pool_workqueue *pwq;
+
+       mutex_lock(&wq_pool_mutex);
+
+       if (!workqueue_freezing)
+               goto out_unlock;
+
+       workqueue_freezing = false;
+
+       /* restore max_active and repopulate worklist */
+       list_for_each_entry(wq, &workqueues, list) {
+               mutex_lock(&wq->mutex);
+               for_each_pwq(pwq, wq)
+                       pwq_adjust_max_active(pwq);
+               mutex_unlock(&wq->mutex);
+       }
+
+out_unlock:
+       mutex_unlock(&wq_pool_mutex);
+}
+#endif /* CONFIG_FREEZER */
+
+#ifdef CONFIG_SYSFS
+/*
+ * Workqueues with WQ_SYSFS flag set is visible to userland via
+ * /sys/bus/workqueue/devices/WQ_NAME.  All visible workqueues have the
+ * following attributes.
+ *
+ *  per_cpu    RO bool : whether the workqueue is per-cpu or unbound
+ *  max_active RW int  : maximum number of in-flight work items
+ *
+ * Unbound workqueues have the following extra attributes.
+ *
+ *  id         RO int  : the associated pool ID
+ *  nice       RW int  : nice value of the workers
+ *  cpumask    RW mask : bitmask of allowed CPUs for the workers
+ */
+struct wq_device {
+       struct workqueue_struct         *wq;
+       struct device                   dev;
+};
+
+static struct workqueue_struct *dev_to_wq(struct device *dev)
+{
+       struct wq_device *wq_dev = container_of(dev, struct wq_device, dev);
+
+       return wq_dev->wq;
+}
+
+static ssize_t per_cpu_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct workqueue_struct *wq = dev_to_wq(dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", (bool)!(wq->flags & WQ_UNBOUND));
+}
+static DEVICE_ATTR_RO(per_cpu);
+
+static ssize_t max_active_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       struct workqueue_struct *wq = dev_to_wq(dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", wq->saved_max_active);
+}
+
+static ssize_t max_active_store(struct device *dev,
+                               struct device_attribute *attr, const char *buf,
+                               size_t count)
+{
+       struct workqueue_struct *wq = dev_to_wq(dev);
+       int val;
+
+       if (sscanf(buf, "%d", &val) != 1 || val <= 0)
+               return -EINVAL;
+
+       workqueue_set_max_active(wq, val);
+       return count;
+}
+static DEVICE_ATTR_RW(max_active);
+
+static struct attribute *wq_sysfs_attrs[] = {
+       &dev_attr_per_cpu.attr,
+       &dev_attr_max_active.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(wq_sysfs);
+
+static ssize_t wq_pool_ids_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct workqueue_struct *wq = dev_to_wq(dev);
+       const char *delim = "";
+       int node, written = 0;
+
+       rcu_read_lock_sched();
+       for_each_node(node) {
+               written += scnprintf(buf + written, PAGE_SIZE - written,
+                                    "%s%d:%d", delim, node,
+                                    unbound_pwq_by_node(wq, node)->pool->id);
+               delim = " ";
+       }
+       written += scnprintf(buf + written, PAGE_SIZE - written, "\n");
+       rcu_read_unlock_sched();
+
+       return written;
+}
+
+static ssize_t wq_nice_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct workqueue_struct *wq = dev_to_wq(dev);
+       int written;
+
+       mutex_lock(&wq->mutex);
+       written = scnprintf(buf, PAGE_SIZE, "%d\n", wq->unbound_attrs->nice);
+       mutex_unlock(&wq->mutex);
+
+       return written;
+}
+
+/* prepare workqueue_attrs for sysfs store operations */
+static struct workqueue_attrs *wq_sysfs_prep_attrs(struct workqueue_struct *wq)
+{
+       struct workqueue_attrs *attrs;
+
+       attrs = alloc_workqueue_attrs(GFP_KERNEL);
+       if (!attrs)
+               return NULL;
+
+       mutex_lock(&wq->mutex);
+       copy_workqueue_attrs(attrs, wq->unbound_attrs);
+       mutex_unlock(&wq->mutex);
+       return attrs;
+}
+
+static ssize_t wq_nice_store(struct device *dev, struct device_attribute *attr,
+                            const char *buf, size_t count)
+{
+       struct workqueue_struct *wq = dev_to_wq(dev);
+       struct workqueue_attrs *attrs;
+       int ret;
+
+       attrs = wq_sysfs_prep_attrs(wq);
+       if (!attrs)
+               return -ENOMEM;
+
+       if (sscanf(buf, "%d", &attrs->nice) == 1 &&
+           attrs->nice >= MIN_NICE && attrs->nice <= MAX_NICE)
+               ret = apply_workqueue_attrs(wq, attrs);
+       else
+               ret = -EINVAL;
+
+       free_workqueue_attrs(attrs);
+       return ret ?: count;
+}
+
+static ssize_t wq_cpumask_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       struct workqueue_struct *wq = dev_to_wq(dev);
+       int written;
+
+       mutex_lock(&wq->mutex);
+       written = scnprintf(buf, PAGE_SIZE, "%*pb\n",
+                           cpumask_pr_args(wq->unbound_attrs->cpumask));
+       mutex_unlock(&wq->mutex);
+       return written;
+}
+
+static ssize_t wq_cpumask_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct workqueue_struct *wq = dev_to_wq(dev);
+       struct workqueue_attrs *attrs;
+       int ret;
+
+       attrs = wq_sysfs_prep_attrs(wq);
+       if (!attrs)
+               return -ENOMEM;
+
+       ret = cpumask_parse(buf, attrs->cpumask);
+       if (!ret)
+               ret = apply_workqueue_attrs(wq, attrs);
+
+       free_workqueue_attrs(attrs);
+       return ret ?: count;
+}
+
+static ssize_t wq_numa_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct workqueue_struct *wq = dev_to_wq(dev);
+       int written;
 
-               /* update NUMA affinity of unbound workqueues */
-               list_for_each_entry(wq, &workqueues, list)
-                       wq_update_unbound_numa(wq, cpu, true);
+       mutex_lock(&wq->mutex);
+       written = scnprintf(buf, PAGE_SIZE, "%d\n",
+                           !wq->unbound_attrs->no_numa);
+       mutex_unlock(&wq->mutex);
 
-               mutex_unlock(&wq_pool_mutex);
-               break;
-       }
-       return NOTIFY_OK;
+       return written;
 }
 
-/*
- * Workqueues should be brought down after normal priority CPU notifiers.
- * This will be registered as low priority CPU notifier.
- */
-static int workqueue_cpu_down_callback(struct notifier_block *nfb,
-                                                unsigned long action,
-                                                void *hcpu)
+static ssize_t wq_numa_store(struct device *dev, struct device_attribute *attr,
+                            const char *buf, size_t count)
 {
-       int cpu = (unsigned long)hcpu;
-       struct work_struct unbind_work;
-       struct workqueue_struct *wq;
-
-       switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_DOWN_PREPARE:
-               /* unbinding per-cpu workers should happen on the local CPU */
-               INIT_WORK_ONSTACK(&unbind_work, wq_unbind_fn);
-               queue_work_on(cpu, system_highpri_wq, &unbind_work);
+       struct workqueue_struct *wq = dev_to_wq(dev);
+       struct workqueue_attrs *attrs;
+       int v, ret;
 
-               /* update NUMA affinity of unbound workqueues */
-               mutex_lock(&wq_pool_mutex);
-               list_for_each_entry(wq, &workqueues, list)
-                       wq_update_unbound_numa(wq, cpu, false);
-               mutex_unlock(&wq_pool_mutex);
+       attrs = wq_sysfs_prep_attrs(wq);
+       if (!attrs)
+               return -ENOMEM;
 
-               /* wait for per-cpu unbinding to finish */
-               flush_work(&unbind_work);
-               destroy_work_on_stack(&unbind_work);
-               break;
+       ret = -EINVAL;
+       if (sscanf(buf, "%d", &v) == 1) {
+               attrs->no_numa = !v;
+               ret = apply_workqueue_attrs(wq, attrs);
        }
-       return NOTIFY_OK;
+
+       free_workqueue_attrs(attrs);
+       return ret ?: count;
 }
 
-#ifdef CONFIG_SMP
+static struct device_attribute wq_sysfs_unbound_attrs[] = {
+       __ATTR(pool_ids, 0444, wq_pool_ids_show, NULL),
+       __ATTR(nice, 0644, wq_nice_show, wq_nice_store),
+       __ATTR(cpumask, 0644, wq_cpumask_show, wq_cpumask_store),
+       __ATTR(numa, 0644, wq_numa_show, wq_numa_store),
+       __ATTR_NULL,
+};
 
-struct work_for_cpu {
-       struct work_struct work;
-       long (*fn)(void *);
-       void *arg;
-       long ret;
+static struct bus_type wq_subsys = {
+       .name                           = "workqueue",
+       .dev_groups                     = wq_sysfs_groups,
 };
 
-static void work_for_cpu_fn(struct work_struct *work)
+static int __init wq_sysfs_init(void)
 {
-       struct work_for_cpu *wfc = container_of(work, struct work_for_cpu, work);
-
-       wfc->ret = wfc->fn(wfc->arg);
+       return subsys_virtual_register(&wq_subsys, NULL);
 }
+core_initcall(wq_sysfs_init);
 
-/**
- * work_on_cpu - run a function in user context on a particular cpu
- * @cpu: the cpu to run on
- * @fn: the function to run
- * @arg: the function arg
- *
- * It is up to the caller to ensure that the cpu doesn't go offline.
- * The caller must not hold any locks which would prevent @fn from completing.
- *
- * Return: The value @fn returns.
- */
-long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
+static void wq_device_release(struct device *dev)
 {
-       struct work_for_cpu wfc = { .fn = fn, .arg = arg };
+       struct wq_device *wq_dev = container_of(dev, struct wq_device, dev);
 
-       INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
-       schedule_work_on(cpu, &wfc.work);
-       flush_work(&wfc.work);
-       destroy_work_on_stack(&wfc.work);
-       return wfc.ret;
+       kfree(wq_dev);
 }
-EXPORT_SYMBOL_GPL(work_on_cpu);
-#endif /* CONFIG_SMP */
-
-#ifdef CONFIG_FREEZER
 
 /**
- * freeze_workqueues_begin - begin freezing workqueues
+ * workqueue_sysfs_register - make a workqueue visible in sysfs
+ * @wq: the workqueue to register
  *
- * Start freezing workqueues.  After this function returns, all freezable
- * workqueues will queue new works to their delayed_works list instead of
- * pool->worklist.
+ * Expose @wq in sysfs under /sys/bus/workqueue/devices.
+ * alloc_workqueue*() automatically calls this function if WQ_SYSFS is set
+ * which is the preferred method.
  *
- * CONTEXT:
- * Grabs and releases wq_pool_mutex, wq->mutex and pool->lock's.
+ * Workqueue user should use this function directly iff it wants to apply
+ * workqueue_attrs before making the workqueue visible in sysfs; otherwise,
+ * apply_workqueue_attrs() may race against userland updating the
+ * attributes.
+ *
+ * Return: 0 on success, -errno on failure.
  */
-void freeze_workqueues_begin(void)
+int workqueue_sysfs_register(struct workqueue_struct *wq)
 {
-       struct workqueue_struct *wq;
-       struct pool_workqueue *pwq;
-
-       mutex_lock(&wq_pool_mutex);
+       struct wq_device *wq_dev;
+       int ret;
 
-       WARN_ON_ONCE(workqueue_freezing);
-       workqueue_freezing = true;
+       /*
+        * Adjusting max_active or creating new pwqs by applyting
+        * attributes breaks ordering guarantee.  Disallow exposing ordered
+        * workqueues.
+        */
+       if (WARN_ON(wq->flags & __WQ_ORDERED))
+               return -EINVAL;
 
-       list_for_each_entry(wq, &workqueues, list) {
-               mutex_lock(&wq->mutex);
-               for_each_pwq(pwq, wq)
-                       pwq_adjust_max_active(pwq);
-               mutex_unlock(&wq->mutex);
-       }
+       wq->wq_dev = wq_dev = kzalloc(sizeof(*wq_dev), GFP_KERNEL);
+       if (!wq_dev)
+               return -ENOMEM;
 
-       mutex_unlock(&wq_pool_mutex);
-}
+       wq_dev->wq = wq;
+       wq_dev->dev.bus = &wq_subsys;
+       wq_dev->dev.init_name = wq->name;
+       wq_dev->dev.release = wq_device_release;
 
-/**
- * freeze_workqueues_busy - are freezable workqueues still busy?
- *
- * Check whether freezing is complete.  This function must be called
- * between freeze_workqueues_begin() and thaw_workqueues().
- *
- * CONTEXT:
- * Grabs and releases wq_pool_mutex.
- *
- * Return:
- * %true if some freezable workqueues are still busy.  %false if freezing
- * is complete.
- */
-bool freeze_workqueues_busy(void)
-{
-       bool busy = false;
-       struct workqueue_struct *wq;
-       struct pool_workqueue *pwq;
+       /*
+        * unbound_attrs are created separately.  Suppress uevent until
+        * everything is ready.
+        */
+       dev_set_uevent_suppress(&wq_dev->dev, true);
 
-       mutex_lock(&wq_pool_mutex);
+       ret = device_register(&wq_dev->dev);
+       if (ret) {
+               kfree(wq_dev);
+               wq->wq_dev = NULL;
+               return ret;
+       }
 
-       WARN_ON_ONCE(!workqueue_freezing);
+       if (wq->flags & WQ_UNBOUND) {
+               struct device_attribute *attr;
 
-       list_for_each_entry(wq, &workqueues, list) {
-               if (!(wq->flags & WQ_FREEZABLE))
-                       continue;
-               /*
-                * nr_active is monotonically decreasing.  It's safe
-                * to peek without lock.
-                */
-               rcu_read_lock_sched();
-               for_each_pwq(pwq, wq) {
-                       WARN_ON_ONCE(pwq->nr_active < 0);
-                       if (pwq->nr_active) {
-                               busy = true;
-                               rcu_read_unlock_sched();
-                               goto out_unlock;
+               for (attr = wq_sysfs_unbound_attrs; attr->attr.name; attr++) {
+                       ret = device_create_file(&wq_dev->dev, attr);
+                       if (ret) {
+                               device_unregister(&wq_dev->dev);
+                               wq->wq_dev = NULL;
+                               return ret;
                        }
                }
-               rcu_read_unlock_sched();
        }
-out_unlock:
-       mutex_unlock(&wq_pool_mutex);
-       return busy;
+
+       dev_set_uevent_suppress(&wq_dev->dev, false);
+       kobject_uevent(&wq_dev->dev.kobj, KOBJ_ADD);
+       return 0;
 }
 
 /**
- * thaw_workqueues - thaw workqueues
- *
- * Thaw workqueues.  Normal queueing is restored and all collected
- * frozen works are transferred to their respective pool worklists.
+ * workqueue_sysfs_unregister - undo workqueue_sysfs_register()
+ * @wq: the workqueue to unregister
  *
- * CONTEXT:
- * Grabs and releases wq_pool_mutex, wq->mutex and pool->lock's.
+ * If @wq is registered to sysfs by workqueue_sysfs_register(), unregister.
  */
-void thaw_workqueues(void)
+static void workqueue_sysfs_unregister(struct workqueue_struct *wq)
 {
-       struct workqueue_struct *wq;
-       struct pool_workqueue *pwq;
-
-       mutex_lock(&wq_pool_mutex);
-
-       if (!workqueue_freezing)
-               goto out_unlock;
-
-       workqueue_freezing = false;
+       struct wq_device *wq_dev = wq->wq_dev;
 
-       /* restore max_active and repopulate worklist */
-       list_for_each_entry(wq, &workqueues, list) {
-               mutex_lock(&wq->mutex);
-               for_each_pwq(pwq, wq)
-                       pwq_adjust_max_active(pwq);
-               mutex_unlock(&wq->mutex);
-       }
+       if (!wq->wq_dev)
+               return;
 
-out_unlock:
-       mutex_unlock(&wq_pool_mutex);
+       wq->wq_dev = NULL;
+       device_unregister(&wq_dev->dev);
 }
-#endif /* CONFIG_FREEZER */
+#else  /* CONFIG_SYSFS */
+static void workqueue_sysfs_unregister(struct workqueue_struct *wq)    { }
+#endif /* CONFIG_SYSFS */
 
 static void __init wq_numa_init(void)
 {
index c5cefb3c009ce9cd51199dc5fef683d7bc9b1bdc..17670573dda82d92a515d4519211e8bbe65b5f63 100644 (file)
@@ -865,6 +865,19 @@ config SCHED_STACK_END_CHECK
          data corruption or a sporadic crash at a later stage once the region
          is examined. The runtime overhead introduced is minimal.
 
+config DEBUG_TIMEKEEPING
+       bool "Enable extra timekeeping sanity checking"
+       help
+         This option will enable additional timekeeping sanity checks
+         which may be helpful when diagnosing issues where timekeeping
+         problems are suspected.
+
+         This may include checks in the timekeeping hotpaths, so this
+         option may have a (very small) performance impact to some
+         workloads.
+
+         If unsure, say N.
+
 config TIMER_STATS
        bool "Collect kernel timers statistics"
        depends on DEBUG_KERNEL && PROC_FS
@@ -1180,16 +1193,7 @@ config DEBUG_CREDENTIALS
 menu "RCU Debugging"
 
 config PROVE_RCU
-       bool "RCU debugging: prove RCU correctness"
-       depends on PROVE_LOCKING
-       default n
-       help
-        This feature enables lockdep extensions that check for correct
-        use of RCU APIs.  This is currently under development.  Say Y
-        if you want to debug RCU usage or help work on the PROVE_RCU
-        feature.
-
-        Say N if you are unsure.
+       def_bool PROVE_LOCKING
 
 config PROVE_RCU_REPEATEDLY
        bool "RCU debugging: don't disable PROVE_RCU on first splat"
@@ -1257,6 +1261,30 @@ config RCU_TORTURE_TEST_RUNNABLE
          Say N here if you want the RCU torture tests to start only
          after being manually enabled via /proc.
 
+config RCU_TORTURE_TEST_SLOW_INIT
+       bool "Slow down RCU grace-period initialization to expose races"
+       depends on RCU_TORTURE_TEST
+       help
+         This option makes grace-period initialization block for a
+         few jiffies between initializing each pair of consecutive
+         rcu_node structures.  This helps to expose races involving
+         grace-period initialization, in other words, it makes your
+         kernel less stable.  It can also greatly increase grace-period
+         latency, especially on systems with large numbers of CPUs.
+         This is useful when torture-testing RCU, but in almost no
+         other circumstance.
+
+         Say Y here if you want your system to crash and hang more often.
+         Say N if you want a sane system.
+
+config RCU_TORTURE_TEST_SLOW_INIT_DELAY
+       int "How much to slow down RCU grace-period initialization"
+       range 0 5
+       default 3
+       help
+         This option specifies the number of jiffies to wait between
+         each rcu_node structure initialization.
+
 config RCU_CPU_STALL_TIMEOUT
        int "RCU CPU stall timeout in seconds"
        depends on RCU_STALL_COMMON
@@ -1732,6 +1760,18 @@ config TEST_UDELAY
 
          If unsure, say N.
 
+config MEMTEST
+       bool "Memtest"
+       depends on HAVE_MEMBLOCK
+       ---help---
+         This option adds a kernel parameter 'memtest', which allows memtest
+         to be set.
+               memtest=0, mean disabled; -- default
+               memtest=1, mean do 1 test pattern;
+               ...
+               memtest=17, mean do 17 test patterns.
+         If you are unsure how to answer this question, answer N.
+
 source "samples/Kconfig"
 
 source "lib/Kconfig.kgdb"
index 4382ad77777ebcb17bc4b25fe606f4371b563a5d..19ea7ed4b948297ae8f03367d3484840ec4456f6 100644 (file)
@@ -127,7 +127,7 @@ EXPORT_SYMBOL(div64_u64_rem);
  * by the book 'Hacker's Delight'.  The original source and full proof
  * can be found here and is available for use without restriction.
  *
- * 'http://www.hackersdelight.org/HDcode/newCode/divDouble.c.txt'
+ * 'http://www.hackersdelight.org/hdcodetxt/divDouble.c.txt'
  */
 #ifndef div64_u64
 u64 div64_u64(u64 dividend, u64 divisor)
index 0c9216c48762a0e941910f8707c0a276f62a91ba..86c8911b0e3a6fff02b9e52faa11816cfe508362 100644 (file)
 #include <asm/cacheflush.h>
 #include <asm/pgtable.h>
 
+#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
+static int __read_mostly ioremap_pud_capable;
+static int __read_mostly ioremap_pmd_capable;
+static int __read_mostly ioremap_huge_disabled;
+
+static int __init set_nohugeiomap(char *str)
+{
+       ioremap_huge_disabled = 1;
+       return 0;
+}
+early_param("nohugeiomap", set_nohugeiomap);
+
+void __init ioremap_huge_init(void)
+{
+       if (!ioremap_huge_disabled) {
+               if (arch_ioremap_pud_supported())
+                       ioremap_pud_capable = 1;
+               if (arch_ioremap_pmd_supported())
+                       ioremap_pmd_capable = 1;
+       }
+}
+
+static inline int ioremap_pud_enabled(void)
+{
+       return ioremap_pud_capable;
+}
+
+static inline int ioremap_pmd_enabled(void)
+{
+       return ioremap_pmd_capable;
+}
+
+#else  /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
+static inline int ioremap_pud_enabled(void) { return 0; }
+static inline int ioremap_pmd_enabled(void) { return 0; }
+#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
+
 static int ioremap_pte_range(pmd_t *pmd, unsigned long addr,
                unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
 {
@@ -43,6 +80,14 @@ static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
                return -ENOMEM;
        do {
                next = pmd_addr_end(addr, end);
+
+               if (ioremap_pmd_enabled() &&
+                   ((next - addr) == PMD_SIZE) &&
+                   IS_ALIGNED(phys_addr + addr, PMD_SIZE)) {
+                       if (pmd_set_huge(pmd, phys_addr + addr, prot))
+                               continue;
+               }
+
                if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, prot))
                        return -ENOMEM;
        } while (pmd++, addr = next, addr != end);
@@ -61,6 +106,14 @@ static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr,
                return -ENOMEM;
        do {
                next = pud_addr_end(addr, end);
+
+               if (ioremap_pud_enabled() &&
+                   ((next - addr) == PUD_SIZE) &&
+                   IS_ALIGNED(phys_addr + addr, PUD_SIZE)) {
+                       if (pud_set_huge(pud, phys_addr + addr, prot))
+                               continue;
+               }
+
                if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, prot))
                        return -ENOMEM;
        } while (pud++, addr = next, addr != end);
index 9d96e283520cc7f3ec27714dfa4abfcb3800e319..75232ad0a5e7ead00e5d8396ed34763d84a0685c 100644 (file)
@@ -317,6 +317,32 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes)
 }
 EXPORT_SYMBOL(iov_iter_fault_in_readable);
 
+/*
+ * Fault in one or more iovecs of the given iov_iter, to a maximum length of
+ * bytes.  For each iovec, fault in each page that constitutes the iovec.
+ *
+ * Return 0 on success, or non-zero if the memory could not be accessed (i.e.
+ * because it is an invalid address).
+ */
+int iov_iter_fault_in_multipages_readable(struct iov_iter *i, size_t bytes)
+{
+       size_t skip = i->iov_offset;
+       const struct iovec *iov;
+       int err;
+       struct iovec v;
+
+       if (!(i->type & (ITER_BVEC|ITER_KVEC))) {
+               iterate_iovec(i, bytes, v, iov, skip, ({
+                       err = fault_in_multipages_readable(v.iov_base,
+                                       v.iov_len);
+                       if (unlikely(err))
+                       return err;
+               0;}))
+       }
+       return 0;
+}
+EXPORT_SYMBOL(iov_iter_fault_in_multipages_readable);
+
 void iov_iter_init(struct iov_iter *i, int direction,
                        const struct iovec *iov, unsigned long nr_segs,
                        size_t count)
@@ -766,3 +792,60 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags)
                                   flags);
 }
 EXPORT_SYMBOL(dup_iter);
+
+int import_iovec(int type, const struct iovec __user * uvector,
+                unsigned nr_segs, unsigned fast_segs,
+                struct iovec **iov, struct iov_iter *i)
+{
+       ssize_t n;
+       struct iovec *p;
+       n = rw_copy_check_uvector(type, uvector, nr_segs, fast_segs,
+                                 *iov, &p);
+       if (n < 0) {
+               if (p != *iov)
+                       kfree(p);
+               *iov = NULL;
+               return n;
+       }
+       iov_iter_init(i, type, p, nr_segs, n);
+       *iov = p == *iov ? NULL : p;
+       return 0;
+}
+EXPORT_SYMBOL(import_iovec);
+
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+
+int compat_import_iovec(int type, const struct compat_iovec __user * uvector,
+                unsigned nr_segs, unsigned fast_segs,
+                struct iovec **iov, struct iov_iter *i)
+{
+       ssize_t n;
+       struct iovec *p;
+       n = compat_rw_copy_check_uvector(type, uvector, nr_segs, fast_segs,
+                                 *iov, &p);
+       if (n < 0) {
+               if (p != *iov)
+                       kfree(p);
+               *iov = NULL;
+               return n;
+       }
+       iov_iter_init(i, type, p, nr_segs, n);
+       *iov = p == *iov ? NULL : p;
+       return 0;
+}
+#endif
+
+int import_single_range(int rw, void __user *buf, size_t len,
+                struct iovec *iov, struct iov_iter *i)
+{
+       if (len > MAX_RW_COUNT)
+               len = MAX_RW_COUNT;
+       if (unlikely(!access_ok(!rw, buf, len)))
+               return -EFAULT;
+
+       iov->iov_base = buf;
+       iov->iov_len = len;
+       iov_iter_init(i, rw, iov, 1, len);
+       return 0;
+}
index 03d4ab349fa749cd907291cc8e36641522d86241..3b841b97fccd89c1925fc17d2a794840937157a5 100644 (file)
@@ -576,8 +576,13 @@ void kobject_del(struct kobject *kobj)
  */
 struct kobject *kobject_get(struct kobject *kobj)
 {
-       if (kobj)
+       if (kobj) {
+               if (!kobj->state_initialized)
+                       WARN(1, KERN_WARNING "kobject: '%s' (%p): is not "
+                              "initialized, yet kobject_get() is being "
+                              "called.\n", kobject_name(kobj), kobj);
                kref_get(&kobj->kref);
+       }
        return kobj;
 }
 
index ecb9a665ec19b5c8b6e062568dffb0c4c0b12d90..494994bf17c8ec9764cbb784cbd88840fa0919c9 100644 (file)
@@ -18,7 +18,7 @@
 #define CMPXCHG_LOOP(CODE, SUCCESS) do {                                       \
        struct lockref old;                                                     \
        BUILD_BUG_ON(sizeof(old) != 8);                                         \
-       old.lock_count = ACCESS_ONCE(lockref->lock_count);                      \
+       old.lock_count = READ_ONCE(lockref->lock_count);                        \
        while (likely(arch_spin_value_unlocked(old.lock.rlock.raw_lock))) {     \
                struct lockref new = old, prev = old;                           \
                CODE                                                            \
index f0f5c5c3de12e1a23b5aeebc7ec05da6e78d3c14..26cc6029b280d18faa53ef930837d88118d58bda 100644 (file)
 
 #include "lz4defs.h"
 
+static const int dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};
+#if LZ4_ARCH64
+static const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
+#endif
+
 static int lz4_uncompress(const char *source, char *dest, int osize)
 {
        const BYTE *ip = (const BYTE *) source;
@@ -56,10 +61,6 @@ static int lz4_uncompress(const char *source, char *dest, int osize)
        BYTE *cpy;
        unsigned token;
        size_t length;
-       size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};
-#if LZ4_ARCH64
-       size_t dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
-#endif
 
        while (1) {
 
@@ -116,7 +117,7 @@ static int lz4_uncompress(const char *source, char *dest, int osize)
                /* copy repeated sequence */
                if (unlikely((op - ref) < STEPSIZE)) {
 #if LZ4_ARCH64
-                       size_t dec64 = dec64table[op - ref];
+                       int dec64 = dec64table[op - ref];
 #else
                        const int dec64 = 0;
 #endif
@@ -177,11 +178,6 @@ static int lz4_uncompress_unknownoutputsize(const char *source, char *dest,
        BYTE * const oend = op + maxoutputsize;
        BYTE *cpy;
 
-       size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};
-#if LZ4_ARCH64
-       size_t dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
-#endif
-
        /* Main Loop */
        while (ip < iend) {
 
@@ -249,7 +245,7 @@ static int lz4_uncompress_unknownoutputsize(const char *source, char *dest,
                /* copy repeated sequence */
                if (unlikely((op - ref) < STEPSIZE)) {
 #if LZ4_ARCH64
-                       size_t dec64 = dec64table[op - ref];
+                       int dec64 = dec64table[op - ref];
 #else
                        const int dec64 = 0;
 #endif
index a03131b6ba8e7877b537a77fa0c21f5cd005e275..390214da45463e0b134709af6f072ddcc9162f7d 100644 (file)
@@ -517,6 +517,12 @@ config CMA_DEBUG
          processing calls such as dma_alloc_from_contiguous().
          This option does not affect warning and error messages.
 
+config CMA_DEBUGFS
+       bool "CMA debugfs interface"
+       depends on CMA && DEBUG_FS
+       help
+         Turns on the DebugFS interface for CMA.
+
 config CMA_AREAS
        int "Maximum count of the CMA areas"
        depends on CMA
index 15dbe9903c273f87c3e7c6a09e3c4a659647bd48..98c4eaeabdcb4592d0b15fd71f3f520aa1bd3d35 100644 (file)
@@ -55,6 +55,7 @@ obj-$(CONFIG_KMEMCHECK) += kmemcheck.o
 obj-$(CONFIG_KASAN)    += kasan/
 obj-$(CONFIG_FAILSLAB) += failslab.o
 obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
+obj-$(CONFIG_MEMTEST)          += memtest.o
 obj-$(CONFIG_MIGRATION) += migrate.o
 obj-$(CONFIG_QUICKLIST) += quicklist.o
 obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += huge_memory.o
@@ -76,3 +77,4 @@ obj-$(CONFIG_GENERIC_EARLY_IOREMAP) += early_ioremap.o
 obj-$(CONFIG_CMA)      += cma.o
 obj-$(CONFIG_MEMORY_BALLOON) += balloon_compaction.o
 obj-$(CONFIG_PAGE_EXTENSION) += page_ext.o
+obj-$(CONFIG_CMA_DEBUGFS) += cma_debug.o
index 053bcd8f12fb352d847b555dd51ef49032543bc5..8fc50811119b28b54f15ac875ddc956217acc570 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/cleancache.h>
 
 /*
- * cleancache_ops is set by cleancache_ops_register to contain the pointers
+ * cleancache_ops is set by cleancache_register_ops to contain the pointers
  * to the cleancache "backend" implementation functions.
  */
 static struct cleancache_ops *cleancache_ops __read_mostly;
@@ -34,145 +34,107 @@ static u64 cleancache_failed_gets;
 static u64 cleancache_puts;
 static u64 cleancache_invalidates;
 
-/*
- * When no backend is registered all calls to init_fs and init_shared_fs
- * are registered and fake poolids (FAKE_FS_POOLID_OFFSET or
- * FAKE_SHARED_FS_POOLID_OFFSET, plus offset in the respective array
- * [shared_|]fs_poolid_map) are given to the respective super block
- * (sb->cleancache_poolid) and no tmem_pools are created. When a backend
- * registers with cleancache the previous calls to init_fs and init_shared_fs
- * are executed to create tmem_pools and set the respective poolids. While no
- * backend is registered all "puts", "gets" and "flushes" are ignored or failed.
- */
-#define MAX_INITIALIZABLE_FS 32
-#define FAKE_FS_POOLID_OFFSET 1000
-#define FAKE_SHARED_FS_POOLID_OFFSET 2000
-
-#define FS_NO_BACKEND (-1)
-#define FS_UNKNOWN (-2)
-static int fs_poolid_map[MAX_INITIALIZABLE_FS];
-static int shared_fs_poolid_map[MAX_INITIALIZABLE_FS];
-static char *uuids[MAX_INITIALIZABLE_FS];
-/*
- * Mutex for the [shared_|]fs_poolid_map to guard against multiple threads
- * invoking umount (and ending in __cleancache_invalidate_fs) and also multiple
- * threads calling mount (and ending up in __cleancache_init_[shared|]fs).
- */
-static DEFINE_MUTEX(poolid_mutex);
-/*
- * When set to false (default) all calls to the cleancache functions, except
- * the __cleancache_invalidate_fs and __cleancache_init_[shared|]fs are guarded
- * by the if (!cleancache_ops) return. This means multiple threads (from
- * different filesystems) will be checking cleancache_ops. The usage of a
- * bool instead of a atomic_t or a bool guarded by a spinlock is OK - we are
- * OK if the time between the backend's have been initialized (and
- * cleancache_ops has been set to not NULL) and when the filesystems start
- * actually calling the backends. The inverse (when unloading) is obviously
- * not good - but this shim does not do that (yet).
- */
-
-/*
- * The backends and filesystems work all asynchronously. This is b/c the
- * backends can be built as modules.
- * The usual sequence of events is:
- *     a) mount /      -> __cleancache_init_fs is called. We set the
- *             [shared_|]fs_poolid_map and uuids for.
- *
- *     b). user does I/Os -> we call the rest of __cleancache_* functions
- *             which return immediately as cleancache_ops is false.
- *
- *     c). modprobe zcache -> cleancache_register_ops. We init the backend
- *             and set cleancache_ops to true, and for any fs_poolid_map
- *             (which is set by __cleancache_init_fs) we initialize the poolid.
- *
- *     d). user does I/Os -> now that cleancache_ops is true all the
- *             __cleancache_* functions can call the backend. They all check
- *             that fs_poolid_map is valid and if so invoke the backend.
- *
- *     e). umount /    -> __cleancache_invalidate_fs, the fs_poolid_map is
- *             reset (which is the second check in the __cleancache_* ops
- *             to call the backend).
- *
- * The sequence of event could also be c), followed by a), and d). and e). The
- * c) would not happen anymore. There is also the chance of c), and one thread
- * doing a) + d), and another doing e). For that case we depend on the
- * filesystem calling __cleancache_invalidate_fs in the proper sequence (so
- * that it handles all I/Os before it invalidates the fs (which is last part
- * of unmounting process).
- *
- * Note: The acute reader will notice that there is no "rmmod zcache" case.
- * This is b/c the functionality for that is not yet implemented and when
- * done, will require some extra locking not yet devised.
- */
+static void cleancache_register_ops_sb(struct super_block *sb, void *unused)
+{
+       switch (sb->cleancache_poolid) {
+       case CLEANCACHE_NO_BACKEND:
+               __cleancache_init_fs(sb);
+               break;
+       case CLEANCACHE_NO_BACKEND_SHARED:
+               __cleancache_init_shared_fs(sb);
+               break;
+       }
+}
 
 /*
- * Register operations for cleancache, returning previous thus allowing
- * detection of multiple backends and possible nesting.
+ * Register operations for cleancache. Returns 0 on success.
  */
-struct cleancache_ops *cleancache_register_ops(struct cleancache_ops *ops)
+int cleancache_register_ops(struct cleancache_ops *ops)
 {
-       struct cleancache_ops *old = cleancache_ops;
-       int i;
+       if (cmpxchg(&cleancache_ops, NULL, ops))
+               return -EBUSY;
 
-       mutex_lock(&poolid_mutex);
-       for (i = 0; i < MAX_INITIALIZABLE_FS; i++) {
-               if (fs_poolid_map[i] == FS_NO_BACKEND)
-                       fs_poolid_map[i] = ops->init_fs(PAGE_SIZE);
-               if (shared_fs_poolid_map[i] == FS_NO_BACKEND)
-                       shared_fs_poolid_map[i] = ops->init_shared_fs
-                                       (uuids[i], PAGE_SIZE);
-       }
        /*
-        * We MUST set cleancache_ops _after_ we have called the backends
-        * init_fs or init_shared_fs functions. Otherwise the compiler might
-        * re-order where cleancache_ops is set in this function.
+        * A cleancache backend can be built as a module and hence loaded after
+        * a cleancache enabled filesystem has called cleancache_init_fs. To
+        * handle such a scenario, here we call ->init_fs or ->init_shared_fs
+        * for each active super block. To differentiate between local and
+        * shared filesystems, we temporarily initialize sb->cleancache_poolid
+        * to CLEANCACHE_NO_BACKEND or CLEANCACHE_NO_BACKEND_SHARED
+        * respectively in case there is no backend registered at the time
+        * cleancache_init_fs or cleancache_init_shared_fs is called.
+        *
+        * Since filesystems can be mounted concurrently with cleancache
+        * backend registration, we have to be careful to guarantee that all
+        * cleancache enabled filesystems that has been mounted by the time
+        * cleancache_register_ops is called has got and all mounted later will
+        * get cleancache_poolid. This is assured by the following statements
+        * tied together:
+        *
+        * a) iterate_supers skips only those super blocks that has started
+        *    ->kill_sb
+        *
+        * b) if iterate_supers encounters a super block that has not finished
+        *    ->mount yet, it waits until it is finished
+        *
+        * c) cleancache_init_fs is called from ->mount and
+        *    cleancache_invalidate_fs is called from ->kill_sb
+        *
+        * d) we call iterate_supers after cleancache_ops has been set
+        *
+        * From a) it follows that if iterate_supers skips a super block, then
+        * either the super block is already dead, in which case we do not need
+        * to bother initializing cleancache for it, or it was mounted after we
+        * initiated iterate_supers. In the latter case, it must have seen
+        * cleancache_ops set according to d) and initialized cleancache from
+        * ->mount by itself according to c). This proves that we call
+        * ->init_fs at least once for each active super block.
+        *
+        * From b) and c) it follows that if iterate_supers encounters a super
+        * block that has already started ->init_fs, it will wait until ->mount
+        * and hence ->init_fs has finished, then check cleancache_poolid, see
+        * that it has already been set and therefore do nothing. This proves
+        * that we call ->init_fs no more than once for each super block.
+        *
+        * Combined together, the last two paragraphs prove the function
+        * correctness.
+        *
+        * Note that various cleancache callbacks may proceed before this
+        * function is called or even concurrently with it, but since
+        * CLEANCACHE_NO_BACKEND is negative, they will all result in a noop
+        * until the corresponding ->init_fs has been actually called and
+        * cleancache_ops has been set.
         */
-       barrier();
-       cleancache_ops = ops;
-       mutex_unlock(&poolid_mutex);
-       return old;
+       iterate_supers(cleancache_register_ops_sb, NULL);
+       return 0;
 }
 EXPORT_SYMBOL(cleancache_register_ops);
 
 /* Called by a cleancache-enabled filesystem at time of mount */
 void __cleancache_init_fs(struct super_block *sb)
 {
-       int i;
+       int pool_id = CLEANCACHE_NO_BACKEND;
 
-       mutex_lock(&poolid_mutex);
-       for (i = 0; i < MAX_INITIALIZABLE_FS; i++) {
-               if (fs_poolid_map[i] == FS_UNKNOWN) {
-                       sb->cleancache_poolid = i + FAKE_FS_POOLID_OFFSET;
-                       if (cleancache_ops)
-                               fs_poolid_map[i] = cleancache_ops->init_fs(PAGE_SIZE);
-                       else
-                               fs_poolid_map[i] = FS_NO_BACKEND;
-                       break;
-               }
+       if (cleancache_ops) {
+               pool_id = cleancache_ops->init_fs(PAGE_SIZE);
+               if (pool_id < 0)
+                       pool_id = CLEANCACHE_NO_POOL;
        }
-       mutex_unlock(&poolid_mutex);
+       sb->cleancache_poolid = pool_id;
 }
 EXPORT_SYMBOL(__cleancache_init_fs);
 
 /* Called by a cleancache-enabled clustered filesystem at time of mount */
-void __cleancache_init_shared_fs(char *uuid, struct super_block *sb)
+void __cleancache_init_shared_fs(struct super_block *sb)
 {
-       int i;
+       int pool_id = CLEANCACHE_NO_BACKEND_SHARED;
 
-       mutex_lock(&poolid_mutex);
-       for (i = 0; i < MAX_INITIALIZABLE_FS; i++) {
-               if (shared_fs_poolid_map[i] == FS_UNKNOWN) {
-                       sb->cleancache_poolid = i + FAKE_SHARED_FS_POOLID_OFFSET;
-                       uuids[i] = uuid;
-                       if (cleancache_ops)
-                               shared_fs_poolid_map[i] = cleancache_ops->init_shared_fs
-                                               (uuid, PAGE_SIZE);
-                       else
-                               shared_fs_poolid_map[i] = FS_NO_BACKEND;
-                       break;
-               }
+       if (cleancache_ops) {
+               pool_id = cleancache_ops->init_shared_fs(sb->s_uuid, PAGE_SIZE);
+               if (pool_id < 0)
+                       pool_id = CLEANCACHE_NO_POOL;
        }
-       mutex_unlock(&poolid_mutex);
+       sb->cleancache_poolid = pool_id;
 }
 EXPORT_SYMBOL(__cleancache_init_shared_fs);
 
@@ -201,19 +163,6 @@ static int cleancache_get_key(struct inode *inode,
        return 0;
 }
 
-/*
- * Returns a pool_id that is associated with a given fake poolid.
- */
-static int get_poolid_from_fake(int fake_pool_id)
-{
-       if (fake_pool_id >= FAKE_SHARED_FS_POOLID_OFFSET)
-               return shared_fs_poolid_map[fake_pool_id -
-                       FAKE_SHARED_FS_POOLID_OFFSET];
-       else if (fake_pool_id >= FAKE_FS_POOLID_OFFSET)
-               return fs_poolid_map[fake_pool_id - FAKE_FS_POOLID_OFFSET];
-       return FS_NO_BACKEND;
-}
-
 /*
  * "Get" data from cleancache associated with the poolid/inode/index
  * that were specified when the data was put to cleanache and, if
@@ -229,7 +178,6 @@ int __cleancache_get_page(struct page *page)
 {
        int ret = -1;
        int pool_id;
-       int fake_pool_id;
        struct cleancache_filekey key = { .u.key = { 0 } };
 
        if (!cleancache_ops) {
@@ -238,17 +186,14 @@ int __cleancache_get_page(struct page *page)
        }
 
        VM_BUG_ON_PAGE(!PageLocked(page), page);
-       fake_pool_id = page->mapping->host->i_sb->cleancache_poolid;
-       if (fake_pool_id < 0)
+       pool_id = page->mapping->host->i_sb->cleancache_poolid;
+       if (pool_id < 0)
                goto out;
-       pool_id = get_poolid_from_fake(fake_pool_id);
 
        if (cleancache_get_key(page->mapping->host, &key) < 0)
                goto out;
 
-       if (pool_id >= 0)
-               ret = cleancache_ops->get_page(pool_id,
-                               key, page->index, page);
+       ret = cleancache_ops->get_page(pool_id, key, page->index, page);
        if (ret == 0)
                cleancache_succ_gets++;
        else
@@ -271,7 +216,6 @@ EXPORT_SYMBOL(__cleancache_get_page);
 void __cleancache_put_page(struct page *page)
 {
        int pool_id;
-       int fake_pool_id;
        struct cleancache_filekey key = { .u.key = { 0 } };
 
        if (!cleancache_ops) {
@@ -280,12 +224,7 @@ void __cleancache_put_page(struct page *page)
        }
 
        VM_BUG_ON_PAGE(!PageLocked(page), page);
-       fake_pool_id = page->mapping->host->i_sb->cleancache_poolid;
-       if (fake_pool_id < 0)
-               return;
-
-       pool_id = get_poolid_from_fake(fake_pool_id);
-
+       pool_id = page->mapping->host->i_sb->cleancache_poolid;
        if (pool_id >= 0 &&
                cleancache_get_key(page->mapping->host, &key) >= 0) {
                cleancache_ops->put_page(pool_id, key, page->index, page);
@@ -306,18 +245,13 @@ void __cleancache_invalidate_page(struct address_space *mapping,
                                        struct page *page)
 {
        /* careful... page->mapping is NULL sometimes when this is called */
-       int pool_id;
-       int fake_pool_id = mapping->host->i_sb->cleancache_poolid;
+       int pool_id = mapping->host->i_sb->cleancache_poolid;
        struct cleancache_filekey key = { .u.key = { 0 } };
 
        if (!cleancache_ops)
                return;
 
-       if (fake_pool_id >= 0) {
-               pool_id = get_poolid_from_fake(fake_pool_id);
-               if (pool_id < 0)
-                       return;
-
+       if (pool_id >= 0) {
                VM_BUG_ON_PAGE(!PageLocked(page), page);
                if (cleancache_get_key(mapping->host, &key) >= 0) {
                        cleancache_ops->invalidate_page(pool_id,
@@ -339,18 +273,12 @@ EXPORT_SYMBOL(__cleancache_invalidate_page);
  */
 void __cleancache_invalidate_inode(struct address_space *mapping)
 {
-       int pool_id;
-       int fake_pool_id = mapping->host->i_sb->cleancache_poolid;
+       int pool_id = mapping->host->i_sb->cleancache_poolid;
        struct cleancache_filekey key = { .u.key = { 0 } };
 
        if (!cleancache_ops)
                return;
 
-       if (fake_pool_id < 0)
-               return;
-
-       pool_id = get_poolid_from_fake(fake_pool_id);
-
        if (pool_id >= 0 && cleancache_get_key(mapping->host, &key) >= 0)
                cleancache_ops->invalidate_inode(pool_id, key);
 }
@@ -363,32 +291,18 @@ EXPORT_SYMBOL(__cleancache_invalidate_inode);
  */
 void __cleancache_invalidate_fs(struct super_block *sb)
 {
-       int index;
-       int fake_pool_id = sb->cleancache_poolid;
-       int old_poolid = fake_pool_id;
+       int pool_id;
 
-       mutex_lock(&poolid_mutex);
-       if (fake_pool_id >= FAKE_SHARED_FS_POOLID_OFFSET) {
-               index = fake_pool_id - FAKE_SHARED_FS_POOLID_OFFSET;
-               old_poolid = shared_fs_poolid_map[index];
-               shared_fs_poolid_map[index] = FS_UNKNOWN;
-               uuids[index] = NULL;
-       } else if (fake_pool_id >= FAKE_FS_POOLID_OFFSET) {
-               index = fake_pool_id - FAKE_FS_POOLID_OFFSET;
-               old_poolid = fs_poolid_map[index];
-               fs_poolid_map[index] = FS_UNKNOWN;
-       }
-       sb->cleancache_poolid = -1;
-       if (cleancache_ops)
-               cleancache_ops->invalidate_fs(old_poolid);
-       mutex_unlock(&poolid_mutex);
+       pool_id = sb->cleancache_poolid;
+       sb->cleancache_poolid = CLEANCACHE_NO_POOL;
+
+       if (cleancache_ops && pool_id >= 0)
+               cleancache_ops->invalidate_fs(pool_id);
 }
 EXPORT_SYMBOL(__cleancache_invalidate_fs);
 
 static int __init init_cleancache(void)
 {
-       int i;
-
 #ifdef CONFIG_DEBUG_FS
        struct dentry *root = debugfs_create_dir("cleancache", NULL);
        if (root == NULL)
@@ -400,10 +314,6 @@ static int __init init_cleancache(void)
        debugfs_create_u64("invalidates", S_IRUGO,
                                root, &cleancache_invalidates);
 #endif
-       for (i = 0; i < MAX_INITIALIZABLE_FS; i++) {
-               fs_poolid_map[i] = FS_UNKNOWN;
-               shared_fs_poolid_map[i] = FS_UNKNOWN;
-       }
        return 0;
 }
 module_init(init_cleancache)
index 68ecb7a42983a589fe4c057f109e327b352c8a0b..47203faaf65e4ec34c777b90646200c47aea276b 100644 (file)
--- a/mm/cma.c
+++ b/mm/cma.c
 #include <linux/highmem.h>
 #include <linux/io.h>
 
-struct cma {
-       unsigned long   base_pfn;
-       unsigned long   count;
-       unsigned long   *bitmap;
-       unsigned int order_per_bit; /* Order of pages represented by one bit */
-       struct mutex    lock;
-};
-
-static struct cma cma_areas[MAX_CMA_AREAS];
-static unsigned cma_area_count;
+#include "cma.h"
+
+struct cma cma_areas[MAX_CMA_AREAS];
+unsigned cma_area_count;
 static DEFINE_MUTEX(cma_mutex);
 
-phys_addr_t cma_get_base(struct cma *cma)
+phys_addr_t cma_get_base(const struct cma *cma)
 {
        return PFN_PHYS(cma->base_pfn);
 }
 
-unsigned long cma_get_size(struct cma *cma)
+unsigned long cma_get_size(const struct cma *cma)
 {
        return cma->count << PAGE_SHIFT;
 }
 
-static unsigned long cma_bitmap_aligned_mask(struct cma *cma, int align_order)
+static unsigned long cma_bitmap_aligned_mask(const struct cma *cma,
+                                            int align_order)
 {
        if (align_order <= cma->order_per_bit)
                return 0;
@@ -68,7 +63,8 @@ static unsigned long cma_bitmap_aligned_mask(struct cma *cma, int align_order)
  * Find a PFN aligned to the specified order and return an offset represented in
  * order_per_bits.
  */
-static unsigned long cma_bitmap_aligned_offset(struct cma *cma, int align_order)
+static unsigned long cma_bitmap_aligned_offset(const struct cma *cma,
+                                              int align_order)
 {
        if (align_order <= cma->order_per_bit)
                return 0;
@@ -77,18 +73,14 @@ static unsigned long cma_bitmap_aligned_offset(struct cma *cma, int align_order)
                - cma->base_pfn) >> cma->order_per_bit;
 }
 
-static unsigned long cma_bitmap_maxno(struct cma *cma)
-{
-       return cma->count >> cma->order_per_bit;
-}
-
-static unsigned long cma_bitmap_pages_to_bits(struct cma *cma,
-                                               unsigned long pages)
+static unsigned long cma_bitmap_pages_to_bits(const struct cma *cma,
+                                             unsigned long pages)
 {
        return ALIGN(pages, 1UL << cma->order_per_bit) >> cma->order_per_bit;
 }
 
-static void cma_clear_bitmap(struct cma *cma, unsigned long pfn, int count)
+static void cma_clear_bitmap(struct cma *cma, unsigned long pfn,
+                            unsigned int count)
 {
        unsigned long bitmap_no, bitmap_count;
 
@@ -134,6 +126,12 @@ static int __init cma_activate_area(struct cma *cma)
        } while (--i);
 
        mutex_init(&cma->lock);
+
+#ifdef CONFIG_CMA_DEBUGFS
+       INIT_HLIST_HEAD(&cma->mem_head);
+       spin_lock_init(&cma->mem_head_lock);
+#endif
+
        return 0;
 
 err:
@@ -167,7 +165,8 @@ core_initcall(cma_init_reserved_areas);
  * This function creates custom contiguous area from already reserved memory.
  */
 int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
-                                int order_per_bit, struct cma **res_cma)
+                                unsigned int order_per_bit,
+                                struct cma **res_cma)
 {
        struct cma *cma;
        phys_addr_t alignment;
@@ -358,7 +357,7 @@ err:
  * This function allocates part of contiguous memory on specific
  * contiguous memory area.
  */
-struct page *cma_alloc(struct cma *cma, int count, unsigned int align)
+struct page *cma_alloc(struct cma *cma, unsigned int count, unsigned int align)
 {
        unsigned long mask, offset, pfn, start = 0;
        unsigned long bitmap_maxno, bitmap_no, bitmap_count;
@@ -429,7 +428,7 @@ struct page *cma_alloc(struct cma *cma, int count, unsigned int align)
  * It returns false when provided pages do not belong to contiguous area and
  * true otherwise.
  */
-bool cma_release(struct cma *cma, struct page *pages, int count)
+bool cma_release(struct cma *cma, const struct page *pages, unsigned int count)
 {
        unsigned long pfn;
 
diff --git a/mm/cma.h b/mm/cma.h
new file mode 100644 (file)
index 0000000..1132d73
--- /dev/null
+++ b/mm/cma.h
@@ -0,0 +1,24 @@
+#ifndef __MM_CMA_H__
+#define __MM_CMA_H__
+
+struct cma {
+       unsigned long   base_pfn;
+       unsigned long   count;
+       unsigned long   *bitmap;
+       unsigned int order_per_bit; /* Order of pages represented by one bit */
+       struct mutex    lock;
+#ifdef CONFIG_CMA_DEBUGFS
+       struct hlist_head mem_head;
+       spinlock_t mem_head_lock;
+#endif
+};
+
+extern struct cma cma_areas[MAX_CMA_AREAS];
+extern unsigned cma_area_count;
+
+static unsigned long cma_bitmap_maxno(struct cma *cma)
+{
+       return cma->count >> cma->order_per_bit;
+}
+
+#endif
diff --git a/mm/cma_debug.c b/mm/cma_debug.c
new file mode 100644 (file)
index 0000000..0b37753
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * CMA DebugFS Interface
+ *
+ * Copyright (c) 2015 Sasha Levin <sasha.levin@oracle.com>
+ */
+
+
+#include <linux/debugfs.h>
+#include <linux/cma.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm_types.h>
+
+#include "cma.h"
+
+struct cma_mem {
+       struct hlist_node node;
+       struct page *p;
+       unsigned long n;
+};
+
+static struct dentry *cma_debugfs_root;
+
+static int cma_debugfs_get(void *data, u64 *val)
+{
+       unsigned long *p = data;
+
+       *val = *p;
+
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(cma_debugfs_fops, cma_debugfs_get, NULL, "%llu\n");
+
+static void cma_add_to_cma_mem_list(struct cma *cma, struct cma_mem *mem)
+{
+       spin_lock(&cma->mem_head_lock);
+       hlist_add_head(&mem->node, &cma->mem_head);
+       spin_unlock(&cma->mem_head_lock);
+}
+
+static struct cma_mem *cma_get_entry_from_list(struct cma *cma)
+{
+       struct cma_mem *mem = NULL;
+
+       spin_lock(&cma->mem_head_lock);
+       if (!hlist_empty(&cma->mem_head)) {
+               mem = hlist_entry(cma->mem_head.first, struct cma_mem, node);
+               hlist_del_init(&mem->node);
+       }
+       spin_unlock(&cma->mem_head_lock);
+
+       return mem;
+}
+
+static int cma_free_mem(struct cma *cma, int count)
+{
+       struct cma_mem *mem = NULL;
+
+       while (count) {
+               mem = cma_get_entry_from_list(cma);
+               if (mem == NULL)
+                       return 0;
+
+               if (mem->n <= count) {
+                       cma_release(cma, mem->p, mem->n);
+                       count -= mem->n;
+                       kfree(mem);
+               } else if (cma->order_per_bit == 0) {
+                       cma_release(cma, mem->p, count);
+                       mem->p += count;
+                       mem->n -= count;
+                       count = 0;
+                       cma_add_to_cma_mem_list(cma, mem);
+               } else {
+                       pr_debug("cma: cannot release partial block when order_per_bit != 0\n");
+                       cma_add_to_cma_mem_list(cma, mem);
+                       break;
+               }
+       }
+
+       return 0;
+
+}
+
+static int cma_free_write(void *data, u64 val)
+{
+       int pages = val;
+       struct cma *cma = data;
+
+       return cma_free_mem(cma, pages);
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(cma_free_fops, NULL, cma_free_write, "%llu\n");
+
+static int cma_alloc_mem(struct cma *cma, int count)
+{
+       struct cma_mem *mem;
+       struct page *p;
+
+       mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+       if (!mem)
+               return -ENOMEM;
+
+       p = cma_alloc(cma, count, 0);
+       if (!p) {
+               kfree(mem);
+               return -ENOMEM;
+       }
+
+       mem->p = p;
+       mem->n = count;
+
+       cma_add_to_cma_mem_list(cma, mem);
+
+       return 0;
+}
+
+static int cma_alloc_write(void *data, u64 val)
+{
+       int pages = val;
+       struct cma *cma = data;
+
+       return cma_alloc_mem(cma, pages);
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(cma_alloc_fops, NULL, cma_alloc_write, "%llu\n");
+
+static void cma_debugfs_add_one(struct cma *cma, int idx)
+{
+       struct dentry *tmp;
+       char name[16];
+       int u32s;
+
+       sprintf(name, "cma-%d", idx);
+
+       tmp = debugfs_create_dir(name, cma_debugfs_root);
+
+       debugfs_create_file("alloc", S_IWUSR, cma_debugfs_root, cma,
+                               &cma_alloc_fops);
+
+       debugfs_create_file("free", S_IWUSR, cma_debugfs_root, cma,
+                               &cma_free_fops);
+
+       debugfs_create_file("base_pfn", S_IRUGO, tmp,
+                               &cma->base_pfn, &cma_debugfs_fops);
+       debugfs_create_file("count", S_IRUGO, tmp,
+                               &cma->count, &cma_debugfs_fops);
+       debugfs_create_file("order_per_bit", S_IRUGO, tmp,
+                               &cma->order_per_bit, &cma_debugfs_fops);
+
+       u32s = DIV_ROUND_UP(cma_bitmap_maxno(cma), BITS_PER_BYTE * sizeof(u32));
+       debugfs_create_u32_array("bitmap", S_IRUGO, tmp, (u32*)cma->bitmap, u32s);
+}
+
+static int __init cma_debugfs_init(void)
+{
+       int i;
+
+       cma_debugfs_root = debugfs_create_dir("cma", NULL);
+       if (!cma_debugfs_root)
+               return -ENOMEM;
+
+       for (i = 0; i < cma_area_count; i++)
+               cma_debugfs_add_one(&cma_areas[i], i);
+
+       return 0;
+}
+late_initcall(cma_debugfs_init);
index 8c0d9459b54a02042dd2caf9489566188d9ea908..a18201a8124e5d0443e8231f8600cb3e2976d55c 100644 (file)
@@ -1174,13 +1174,24 @@ static int __compact_finished(struct zone *zone, struct compact_control *cc,
        /* Direct compactor: Is a suitable page free? */
        for (order = cc->order; order < MAX_ORDER; order++) {
                struct free_area *area = &zone->free_area[order];
+               bool can_steal;
 
                /* Job done if page is free of the right migratetype */
                if (!list_empty(&area->free_list[migratetype]))
                        return COMPACT_PARTIAL;
 
-               /* Job done if allocation would set block type */
-               if (order >= pageblock_order && area->nr_free)
+#ifdef CONFIG_CMA
+               /* MIGRATE_MOVABLE can fallback on MIGRATE_CMA */
+               if (migratetype == MIGRATE_MOVABLE &&
+                       !list_empty(&area->free_list[MIGRATE_CMA]))
+                       return COMPACT_PARTIAL;
+#endif
+               /*
+                * Job done if allocation would steal freepages from
+                * other migratetype buddy lists.
+                */
+               if (find_suitable_fallback(area, order, migratetype,
+                                               true, &can_steal) != -1)
                        return COMPACT_PARTIAL;
        }
 
index ad7242043bdb8b74872e536b61d01ca05a1de6b3..12548d03c11de9e3f114897ddc031dbb525f550c 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/compiler.h>
 #include <linux/fs.h>
 #include <linux/uaccess.h>
-#include <linux/aio.h>
 #include <linux/capability.h>
 #include <linux/kernel_stat.h>
 #include <linux/gfp.h>
@@ -203,16 +202,15 @@ void __delete_from_page_cache(struct page *page, void *shadow)
        BUG_ON(page_mapped(page));
 
        /*
-        * Some filesystems seem to re-dirty the page even after
-        * the VM has canceled the dirty bit (eg ext3 journaling).
+        * At this point page must be either written or cleaned by truncate.
+        * Dirty page here signals a bug and loss of unwritten data.
         *
-        * Fix it up by doing a final dirty accounting check after
-        * having removed the page entirely.
+        * This fixes dirty accounting after removing the page entirely but
+        * leaves PageDirty set: it has no effect for truncated page and
+        * anyway will be cleared before returning page into buddy allocator.
         */
-       if (PageDirty(page) && mapping_cap_account_dirty(mapping)) {
-               dec_zone_page_state(page, NR_FILE_DIRTY);
-               dec_bdi_stat(inode_to_bdi(mapping->host), BDI_RECLAIMABLE);
-       }
+       if (WARN_ON_ONCE(PageDirty(page)))
+               account_page_cleaned(page, mapping);
 }
 
 /**
index a6e24e246f8688af7664966e66d99dbd038b8066..ca7b607ab6710db13d5d4d9bc28bac2d9c0e5d27 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -92,7 +92,7 @@ retry:
                 */
                mark_page_accessed(page);
        }
-       if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) {
+       if ((flags & FOLL_POPULATE) && (vma->vm_flags & VM_LOCKED)) {
                /*
                 * The preliminary mapping check is mainly to avoid the
                 * pointless overhead of lock_page on the ZERO_PAGE
@@ -265,8 +265,8 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma,
        unsigned int fault_flags = 0;
        int ret;
 
-       /* For mlock, just skip the stack guard page. */
-       if ((*flags & FOLL_MLOCK) &&
+       /* For mm_populate(), just skip the stack guard page. */
+       if ((*flags & FOLL_POPULATE) &&
                        (stack_guard_page_start(vma, address) ||
                         stack_guard_page_end(vma, address + PAGE_SIZE)))
                return -ENOENT;
@@ -818,6 +818,124 @@ long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 }
 EXPORT_SYMBOL(get_user_pages);
 
+/**
+ * populate_vma_page_range() -  populate a range of pages in the vma.
+ * @vma:   target vma
+ * @start: start address
+ * @end:   end address
+ * @nonblocking:
+ *
+ * This takes care of mlocking the pages too if VM_LOCKED is set.
+ *
+ * return 0 on success, negative error code on error.
+ *
+ * vma->vm_mm->mmap_sem must be held.
+ *
+ * If @nonblocking is NULL, it may be held for read or write and will
+ * be unperturbed.
+ *
+ * If @nonblocking is non-NULL, it must held for read only and may be
+ * released.  If it's released, *@nonblocking will be set to 0.
+ */
+long populate_vma_page_range(struct vm_area_struct *vma,
+               unsigned long start, unsigned long end, int *nonblocking)
+{
+       struct mm_struct *mm = vma->vm_mm;
+       unsigned long nr_pages = (end - start) / PAGE_SIZE;
+       int gup_flags;
+
+       VM_BUG_ON(start & ~PAGE_MASK);
+       VM_BUG_ON(end   & ~PAGE_MASK);
+       VM_BUG_ON_VMA(start < vma->vm_start, vma);
+       VM_BUG_ON_VMA(end   > vma->vm_end, vma);
+       VM_BUG_ON_MM(!rwsem_is_locked(&mm->mmap_sem), mm);
+
+       gup_flags = FOLL_TOUCH | FOLL_POPULATE;
+       /*
+        * We want to touch writable mappings with a write fault in order
+        * to break COW, except for shared mappings because these don't COW
+        * and we would not want to dirty them for nothing.
+        */
+       if ((vma->vm_flags & (VM_WRITE | VM_SHARED)) == VM_WRITE)
+               gup_flags |= FOLL_WRITE;
+
+       /*
+        * We want mlock to succeed for regions that have any permissions
+        * other than PROT_NONE.
+        */
+       if (vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC))
+               gup_flags |= FOLL_FORCE;
+
+       /*
+        * We made sure addr is within a VMA, so the following will
+        * not result in a stack expansion that recurses back here.
+        */
+       return __get_user_pages(current, mm, start, nr_pages, gup_flags,
+                               NULL, NULL, nonblocking);
+}
+
+/*
+ * __mm_populate - populate and/or mlock pages within a range of address space.
+ *
+ * This is used to implement mlock() and the MAP_POPULATE / MAP_LOCKED mmap
+ * flags. VMAs must be already marked with the desired vm_flags, and
+ * mmap_sem must not be held.
+ */
+int __mm_populate(unsigned long start, unsigned long len, int ignore_errors)
+{
+       struct mm_struct *mm = current->mm;
+       unsigned long end, nstart, nend;
+       struct vm_area_struct *vma = NULL;
+       int locked = 0;
+       long ret = 0;
+
+       VM_BUG_ON(start & ~PAGE_MASK);
+       VM_BUG_ON(len != PAGE_ALIGN(len));
+       end = start + len;
+
+       for (nstart = start; nstart < end; nstart = nend) {
+               /*
+                * We want to fault in pages for [nstart; end) address range.
+                * Find first corresponding VMA.
+                */
+               if (!locked) {
+                       locked = 1;
+                       down_read(&mm->mmap_sem);
+                       vma = find_vma(mm, nstart);
+               } else if (nstart >= vma->vm_end)
+                       vma = vma->vm_next;
+               if (!vma || vma->vm_start >= end)
+                       break;
+               /*
+                * Set [nstart; nend) to intersection of desired address
+                * range with the first VMA. Also, skip undesirable VMA types.
+                */
+               nend = min(end, vma->vm_end);
+               if (vma->vm_flags & (VM_IO | VM_PFNMAP))
+                       continue;
+               if (nstart < vma->vm_start)
+                       nstart = vma->vm_start;
+               /*
+                * Now fault in a range of pages. populate_vma_page_range()
+                * double checks the vma flags, so that it won't mlock pages
+                * if the vma was already munlocked.
+                */
+               ret = populate_vma_page_range(vma, nstart, nend, &locked);
+               if (ret < 0) {
+                       if (ignore_errors) {
+                               ret = 0;
+                               continue;       /* continue at next VMA */
+                       }
+                       break;
+               }
+               nend = nstart + ret * PAGE_SIZE;
+               ret = 0;
+       }
+       if (locked)
+               up_read(&mm->mmap_sem);
+       return ret;     /* 0 or negative error code */
+}
+
 /**
  * get_dump_page() - pin user page in memory while writing it to core dump
  * @addr: user address
index 6817b0350c71c43b0f89a4972ce19c51a2408a2b..3afb5cbe13128b51428d812e9b2d251fa3e8e4e1 100644 (file)
@@ -1231,7 +1231,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
                                          pmd, _pmd,  1))
                        update_mmu_cache_pmd(vma, addr, pmd);
        }
-       if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) {
+       if ((flags & FOLL_POPULATE) && (vma->vm_flags & VM_LOCKED)) {
                if (page->mapping && trylock_page(page)) {
                        lru_add_drain();
                        if (page->mapping)
@@ -2109,7 +2109,7 @@ static void release_pte_pages(pte_t *pte, pte_t *_pte)
 {
        while (--_pte >= pte) {
                pte_t pteval = *_pte;
-               if (!pte_none(pteval))
+               if (!pte_none(pteval) && !is_zero_pfn(pte_pfn(pteval)))
                        release_pte_page(pte_page(pteval));
        }
 }
@@ -2120,13 +2120,13 @@ static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
 {
        struct page *page;
        pte_t *_pte;
-       int none = 0;
+       int none_or_zero = 0;
        bool referenced = false, writable = false;
        for (_pte = pte; _pte < pte+HPAGE_PMD_NR;
             _pte++, address += PAGE_SIZE) {
                pte_t pteval = *_pte;
-               if (pte_none(pteval)) {
-                       if (++none <= khugepaged_max_ptes_none)
+               if (pte_none(pteval) || is_zero_pfn(pte_pfn(pteval))) {
+                       if (++none_or_zero <= khugepaged_max_ptes_none)
                                continue;
                        else
                                goto out;
@@ -2207,9 +2207,21 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page,
                pte_t pteval = *_pte;
                struct page *src_page;
 
-               if (pte_none(pteval)) {
+               if (pte_none(pteval) || is_zero_pfn(pte_pfn(pteval))) {
                        clear_user_highpage(page, address);
                        add_mm_counter(vma->vm_mm, MM_ANONPAGES, 1);
+                       if (is_zero_pfn(pte_pfn(pteval))) {
+                               /*
+                                * ptl mostly unnecessary.
+                                */
+                               spin_lock(ptl);
+                               /*
+                                * paravirt calls inside pte_clear here are
+                                * superfluous.
+                                */
+                               pte_clear(vma->vm_mm, address, _pte);
+                               spin_unlock(ptl);
+                       }
                } else {
                        src_page = pte_page(pteval);
                        copy_user_highpage(page, src_page, address, vma);
@@ -2316,8 +2328,14 @@ static struct page
                       struct vm_area_struct *vma, unsigned long address,
                       int node)
 {
+       gfp_t flags;
+
        VM_BUG_ON_PAGE(*hpage, *hpage);
 
+       /* Only allocate from the target node */
+       flags = alloc_hugepage_gfpmask(khugepaged_defrag(), __GFP_OTHER_NODE) |
+               __GFP_THISNODE;
+
        /*
         * Before allocating the hugepage, release the mmap_sem read lock.
         * The allocation can take potentially a long time if it involves
@@ -2326,8 +2344,7 @@ static struct page
         */
        up_read(&mm->mmap_sem);
 
-       *hpage = alloc_pages_exact_node(node, alloc_hugepage_gfpmask(
-               khugepaged_defrag(), __GFP_OTHER_NODE), HPAGE_PMD_ORDER);
+       *hpage = alloc_pages_exact_node(node, flags, HPAGE_PMD_ORDER);
        if (unlikely(!*hpage)) {
                count_vm_event(THP_COLLAPSE_ALLOC_FAILED);
                *hpage = ERR_PTR(-ENOMEM);
@@ -2543,7 +2560,7 @@ static int khugepaged_scan_pmd(struct mm_struct *mm,
 {
        pmd_t *pmd;
        pte_t *pte, *_pte;
-       int ret = 0, none = 0;
+       int ret = 0, none_or_zero = 0;
        struct page *page;
        unsigned long _address;
        spinlock_t *ptl;
@@ -2561,8 +2578,8 @@ static int khugepaged_scan_pmd(struct mm_struct *mm,
        for (_address = address, _pte = pte; _pte < pte+HPAGE_PMD_NR;
             _pte++, _address += PAGE_SIZE) {
                pte_t pteval = *_pte;
-               if (pte_none(pteval)) {
-                       if (++none <= khugepaged_max_ptes_none)
+               if (pte_none(pteval) || is_zero_pfn(pte_pfn(pteval))) {
+                       if (++none_or_zero <= khugepaged_max_ptes_none)
                                continue;
                        else
                                goto out_unmap;
index c41b2a0ee2736e4f7df74c440ceb90bd5fcceecb..8874c8ad55aaf3ae9e67b3bd8cc5bb5b290f7779 100644 (file)
@@ -3277,6 +3277,15 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                int absent;
                struct page *page;
 
+               /*
+                * If we have a pending SIGKILL, don't keep faulting pages and
+                * potentially allocating memory.
+                */
+               if (unlikely(fatal_signal_pending(current))) {
+                       remainder = 0;
+                       break;
+               }
+
                /*
                 * Some archs (sparc64, sh*) have multiple pte_ts to
                 * each hugepage.  We have to make sure we get the
@@ -3735,8 +3744,7 @@ retry:
        if (!pmd_huge(*pmd))
                goto out;
        if (pmd_present(*pmd)) {
-               page = pte_page(*(pte_t *)pmd) +
-                       ((address & ~PMD_MASK) >> PAGE_SHIFT);
+               page = pmd_page(*pmd) + ((address & ~PMD_MASK) >> PAGE_SHIFT);
                if (flags & FOLL_GET)
                        get_page(page);
        } else {
index a96da5b0029dc4a2837f558534f436990ef42894..edaab69a9c35b985e93d073972042664cb9b96db 100644 (file)
@@ -200,6 +200,8 @@ isolate_freepages_range(struct compact_control *cc,
 unsigned long
 isolate_migratepages_range(struct compact_control *cc,
                           unsigned long low_pfn, unsigned long end_pfn);
+int find_suitable_fallback(struct free_area *area, unsigned int order,
+                       int migratetype, bool only_stealable, bool *can_steal);
 
 #endif
 
@@ -240,7 +242,7 @@ void __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma,
                struct vm_area_struct *prev, struct rb_node *rb_parent);
 
 #ifdef CONFIG_MMU
-extern long __mlock_vma_pages_range(struct vm_area_struct *vma,
+extern long populate_vma_page_range(struct vm_area_struct *vma,
                unsigned long start, unsigned long end, int *nonblocking);
 extern void munlock_vma_pages_range(struct vm_area_struct *vma,
                        unsigned long start, unsigned long end);
index 252b77bdf65ef9ca65334e418e3ea231a3afb90b..3f37a0bca5d5a56eb1acaa1bf576b8121acc64c6 100644 (file)
@@ -699,14 +699,14 @@ static int __init_memblock memblock_reserve_region(phys_addr_t base,
                                                   int nid,
                                                   unsigned long flags)
 {
-       struct memblock_type *_rgn = &memblock.reserved;
+       struct memblock_type *type = &memblock.reserved;
 
        memblock_dbg("memblock_reserve: [%#016llx-%#016llx] flags %#02lx %pF\n",
                     (unsigned long long)base,
                     (unsigned long long)base + size - 1,
                     flags, (void *)_RET_IP_);
 
-       return memblock_add_range(_rgn, base, size, nid, flags);
+       return memblock_add_range(type, base, size, nid, flags);
 }
 
 int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
index b34ef4a32a3b266768248743849e241183e112ed..c3f09b2dda5f9cf00e4250e7b68745575bd806d1 100644 (file)
  * Copyright (C) 2012 Parallels Inc. and Google Inc.
  * Authors: Glauber Costa and Suleiman Souhlal
  *
+ * Native page reclaim
+ * Charge lifetime sanitation
+ * Lockless page tracking & accounting
+ * Unified hierarchy configuration model
+ * Copyright (C) 2015 Red Hat, Inc., Johannes Weiner
+ *
  * 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
@@ -1436,15 +1442,17 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
        struct mem_cgroup *iter;
        unsigned int i;
 
-       if (!p)
-               return;
-
        mutex_lock(&oom_info_lock);
        rcu_read_lock();
 
-       pr_info("Task in ");
-       pr_cont_cgroup_path(task_cgroup(p, memory_cgrp_id));
-       pr_cont(" killed as a result of limit of ");
+       if (p) {
+               pr_info("Task in ");
+               pr_cont_cgroup_path(task_cgroup(p, memory_cgrp_id));
+               pr_cont(" killed as a result of limit of ");
+       } else {
+               pr_info("Memory limit reached of cgroup ");
+       }
+
        pr_cont_cgroup_path(memcg->css.cgroup);
        pr_cont("\n");
 
@@ -1531,7 +1539,7 @@ static void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
                return;
        }
 
-       check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, order, NULL);
+       check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, order, NULL, memcg);
        totalpages = mem_cgroup_get_limit(memcg) ? : 1;
        for_each_mem_cgroup_tree(iter, memcg) {
                struct css_task_iter it;
@@ -2779,92 +2787,6 @@ void mem_cgroup_split_huge_fixup(struct page *head)
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
-/**
- * mem_cgroup_move_account - move account of the page
- * @page: the page
- * @nr_pages: number of regular pages (>1 for huge pages)
- * @from: mem_cgroup which the page is moved from.
- * @to:        mem_cgroup which the page is moved to. @from != @to.
- *
- * The caller must confirm following.
- * - page is not on LRU (isolate_page() is useful.)
- * - compound_lock is held when nr_pages > 1
- *
- * This function doesn't do "charge" to new cgroup and doesn't do "uncharge"
- * from old cgroup.
- */
-static int mem_cgroup_move_account(struct page *page,
-                                  unsigned int nr_pages,
-                                  struct mem_cgroup *from,
-                                  struct mem_cgroup *to)
-{
-       unsigned long flags;
-       int ret;
-
-       VM_BUG_ON(from == to);
-       VM_BUG_ON_PAGE(PageLRU(page), page);
-       /*
-        * The page is isolated from LRU. So, collapse function
-        * will not handle this page. But page splitting can happen.
-        * Do this check under compound_page_lock(). The caller should
-        * hold it.
-        */
-       ret = -EBUSY;
-       if (nr_pages > 1 && !PageTransHuge(page))
-               goto out;
-
-       /*
-        * Prevent mem_cgroup_migrate() from looking at page->mem_cgroup
-        * of its source page while we change it: page migration takes
-        * both pages off the LRU, but page cache replacement doesn't.
-        */
-       if (!trylock_page(page))
-               goto out;
-
-       ret = -EINVAL;
-       if (page->mem_cgroup != from)
-               goto out_unlock;
-
-       spin_lock_irqsave(&from->move_lock, flags);
-
-       if (!PageAnon(page) && page_mapped(page)) {
-               __this_cpu_sub(from->stat->count[MEM_CGROUP_STAT_FILE_MAPPED],
-                              nr_pages);
-               __this_cpu_add(to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED],
-                              nr_pages);
-       }
-
-       if (PageWriteback(page)) {
-               __this_cpu_sub(from->stat->count[MEM_CGROUP_STAT_WRITEBACK],
-                              nr_pages);
-               __this_cpu_add(to->stat->count[MEM_CGROUP_STAT_WRITEBACK],
-                              nr_pages);
-       }
-
-       /*
-        * It is safe to change page->mem_cgroup here because the page
-        * is referenced, charged, and isolated - we can't race with
-        * uncharging, charging, migration, or LRU putback.
-        */
-
-       /* caller should have done css_get */
-       page->mem_cgroup = to;
-       spin_unlock_irqrestore(&from->move_lock, flags);
-
-       ret = 0;
-
-       local_irq_disable();
-       mem_cgroup_charge_statistics(to, page, nr_pages);
-       memcg_check_events(to, page);
-       mem_cgroup_charge_statistics(from, page, -nr_pages);
-       memcg_check_events(from, page);
-       local_irq_enable();
-out_unlock:
-       unlock_page(page);
-out:
-       return ret;
-}
-
 #ifdef CONFIG_MEMCG_SWAP
 static void mem_cgroup_swap_statistics(struct mem_cgroup *memcg,
                                         bool charge)
@@ -4816,6 +4738,92 @@ static struct page *mc_handle_file_pte(struct vm_area_struct *vma,
        return page;
 }
 
+/**
+ * mem_cgroup_move_account - move account of the page
+ * @page: the page
+ * @nr_pages: number of regular pages (>1 for huge pages)
+ * @from: mem_cgroup which the page is moved from.
+ * @to:        mem_cgroup which the page is moved to. @from != @to.
+ *
+ * The caller must confirm following.
+ * - page is not on LRU (isolate_page() is useful.)
+ * - compound_lock is held when nr_pages > 1
+ *
+ * This function doesn't do "charge" to new cgroup and doesn't do "uncharge"
+ * from old cgroup.
+ */
+static int mem_cgroup_move_account(struct page *page,
+                                  unsigned int nr_pages,
+                                  struct mem_cgroup *from,
+                                  struct mem_cgroup *to)
+{
+       unsigned long flags;
+       int ret;
+
+       VM_BUG_ON(from == to);
+       VM_BUG_ON_PAGE(PageLRU(page), page);
+       /*
+        * The page is isolated from LRU. So, collapse function
+        * will not handle this page. But page splitting can happen.
+        * Do this check under compound_page_lock(). The caller should
+        * hold it.
+        */
+       ret = -EBUSY;
+       if (nr_pages > 1 && !PageTransHuge(page))
+               goto out;
+
+       /*
+        * Prevent mem_cgroup_migrate() from looking at page->mem_cgroup
+        * of its source page while we change it: page migration takes
+        * both pages off the LRU, but page cache replacement doesn't.
+        */
+       if (!trylock_page(page))
+               goto out;
+
+       ret = -EINVAL;
+       if (page->mem_cgroup != from)
+               goto out_unlock;
+
+       spin_lock_irqsave(&from->move_lock, flags);
+
+       if (!PageAnon(page) && page_mapped(page)) {
+               __this_cpu_sub(from->stat->count[MEM_CGROUP_STAT_FILE_MAPPED],
+                              nr_pages);
+               __this_cpu_add(to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED],
+                              nr_pages);
+       }
+
+       if (PageWriteback(page)) {
+               __this_cpu_sub(from->stat->count[MEM_CGROUP_STAT_WRITEBACK],
+                              nr_pages);
+               __this_cpu_add(to->stat->count[MEM_CGROUP_STAT_WRITEBACK],
+                              nr_pages);
+       }
+
+       /*
+        * It is safe to change page->mem_cgroup here because the page
+        * is referenced, charged, and isolated - we can't race with
+        * uncharging, charging, migration, or LRU putback.
+        */
+
+       /* caller should have done css_get */
+       page->mem_cgroup = to;
+       spin_unlock_irqrestore(&from->move_lock, flags);
+
+       ret = 0;
+
+       local_irq_disable();
+       mem_cgroup_charge_statistics(to, page, nr_pages);
+       memcg_check_events(to, page);
+       mem_cgroup_charge_statistics(from, page, -nr_pages);
+       memcg_check_events(from, page);
+       local_irq_enable();
+out_unlock:
+       unlock_page(page);
+out:
+       return ret;
+}
+
 static enum mc_target_type get_mctgt_type(struct vm_area_struct *vma,
                unsigned long addr, pte_t ptent, union mc_target *target)
 {
index 97839f5c8c303df324a1cec1dfacadb1b0bfa04c..ac20b2a6a0c35124da70aa2cbbaf5f5ba571f235 100644 (file)
@@ -1983,167 +1983,91 @@ static int do_page_mkwrite(struct vm_area_struct *vma, struct page *page,
 }
 
 /*
- * This routine handles present pages, when users try to write
- * to a shared page. It is done by copying the page to a new address
- * and decrementing the shared-page counter for the old page.
- *
- * Note that this routine assumes that the protection checks have been
- * done by the caller (the low-level page fault routine in most cases).
- * Thus we can safely just mark it writable once we've done any necessary
- * COW.
+ * Handle write page faults for pages that can be reused in the current vma
  *
- * We also mark the page dirty at this point even though the page will
- * change only once the write actually happens. This avoids a few races,
- * and potentially makes it more efficient.
- *
- * We enter with non-exclusive mmap_sem (to exclude vma changes,
- * but allow concurrent faults), with pte both mapped and locked.
- * We return with mmap_sem still held, but pte unmapped and unlocked.
+ * This can happen either due to the mapping being with the VM_SHARED flag,
+ * or due to us being the last reference standing to the page. In either
+ * case, all we need to do here is to mark the page as writable and update
+ * any related book-keeping.
  */
-static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
-               unsigned long address, pte_t *page_table, pmd_t *pmd,
-               spinlock_t *ptl, pte_t orig_pte)
+static inline int wp_page_reuse(struct mm_struct *mm,
+                       struct vm_area_struct *vma, unsigned long address,
+                       pte_t *page_table, spinlock_t *ptl, pte_t orig_pte,
+                       struct page *page, int page_mkwrite,
+                       int dirty_shared)
        __releases(ptl)
 {
-       struct page *old_page, *new_page = NULL;
        pte_t entry;
-       int ret = 0;
-       int page_mkwrite = 0;
-       bool dirty_shared = false;
-       unsigned long mmun_start = 0;   /* For mmu_notifiers */
-       unsigned long mmun_end = 0;     /* For mmu_notifiers */
-       struct mem_cgroup *memcg;
-
-       old_page = vm_normal_page(vma, address, orig_pte);
-       if (!old_page) {
-               /*
-                * VM_MIXEDMAP !pfn_valid() case, or VM_SOFTDIRTY clear on a
-                * VM_PFNMAP VMA.
-                *
-                * We should not cow pages in a shared writeable mapping.
-                * Just mark the pages writable as we can't do any dirty
-                * accounting on raw pfn maps.
-                */
-               if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
-                                    (VM_WRITE|VM_SHARED))
-                       goto reuse;
-               goto gotten;
-       }
-
        /*
-        * Take out anonymous pages first, anonymous shared vmas are
-        * not dirty accountable.
+        * Clear the pages cpupid information as the existing
+        * information potentially belongs to a now completely
+        * unrelated process.
         */
-       if (PageAnon(old_page) && !PageKsm(old_page)) {
-               if (!trylock_page(old_page)) {
-                       page_cache_get(old_page);
-                       pte_unmap_unlock(page_table, ptl);
-                       lock_page(old_page);
-                       page_table = pte_offset_map_lock(mm, pmd, address,
-                                                        &ptl);
-                       if (!pte_same(*page_table, orig_pte)) {
-                               unlock_page(old_page);
-                               goto unlock;
-                       }
-                       page_cache_release(old_page);
-               }
-               if (reuse_swap_page(old_page)) {
-                       /*
-                        * The page is all ours.  Move it to our anon_vma so
-                        * the rmap code will not search our parent or siblings.
-                        * Protected against the rmap code by the page lock.
-                        */
-                       page_move_anon_rmap(old_page, vma, address);
-                       unlock_page(old_page);
-                       goto reuse;
-               }
-               unlock_page(old_page);
-       } else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
-                                       (VM_WRITE|VM_SHARED))) {
-               page_cache_get(old_page);
-               /*
-                * Only catch write-faults on shared writable pages,
-                * read-only shared pages can get COWed by
-                * get_user_pages(.write=1, .force=1).
-                */
-               if (vma->vm_ops && vma->vm_ops->page_mkwrite) {
-                       int tmp;
-
-                       pte_unmap_unlock(page_table, ptl);
-                       tmp = do_page_mkwrite(vma, old_page, address);
-                       if (unlikely(!tmp || (tmp &
-                                       (VM_FAULT_ERROR | VM_FAULT_NOPAGE)))) {
-                               page_cache_release(old_page);
-                               return tmp;
-                       }
-                       /*
-                        * Since we dropped the lock we need to revalidate
-                        * the PTE as someone else may have changed it.  If
-                        * they did, we just return, as we can count on the
-                        * MMU to tell us if they didn't also make it writable.
-                        */
-                       page_table = pte_offset_map_lock(mm, pmd, address,
-                                                        &ptl);
-                       if (!pte_same(*page_table, orig_pte)) {
-                               unlock_page(old_page);
-                               goto unlock;
-                       }
-                       page_mkwrite = 1;
-               }
-
-               dirty_shared = true;
-
-reuse:
-               /*
-                * Clear the pages cpupid information as the existing
-                * information potentially belongs to a now completely
-                * unrelated process.
-                */
-               if (old_page)
-                       page_cpupid_xchg_last(old_page, (1 << LAST_CPUPID_SHIFT) - 1);
-
-               flush_cache_page(vma, address, pte_pfn(orig_pte));
-               entry = pte_mkyoung(orig_pte);
-               entry = maybe_mkwrite(pte_mkdirty(entry), vma);
-               if (ptep_set_access_flags(vma, address, page_table, entry,1))
-                       update_mmu_cache(vma, address, page_table);
-               pte_unmap_unlock(page_table, ptl);
-               ret |= VM_FAULT_WRITE;
+       if (page)
+               page_cpupid_xchg_last(page, (1 << LAST_CPUPID_SHIFT) - 1);
 
-               if (dirty_shared) {
-                       struct address_space *mapping;
-                       int dirtied;
+       flush_cache_page(vma, address, pte_pfn(orig_pte));
+       entry = pte_mkyoung(orig_pte);
+       entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+       if (ptep_set_access_flags(vma, address, page_table, entry, 1))
+               update_mmu_cache(vma, address, page_table);
+       pte_unmap_unlock(page_table, ptl);
 
-                       if (!page_mkwrite)
-                               lock_page(old_page);
+       if (dirty_shared) {
+               struct address_space *mapping;
+               int dirtied;
 
-                       dirtied = set_page_dirty(old_page);
-                       VM_BUG_ON_PAGE(PageAnon(old_page), old_page);
-                       mapping = old_page->mapping;
-                       unlock_page(old_page);
-                       page_cache_release(old_page);
+               if (!page_mkwrite)
+                       lock_page(page);
 
-                       if ((dirtied || page_mkwrite) && mapping) {
-                               /*
-                                * Some device drivers do not set page.mapping
-                                * but still dirty their pages
-                                */
-                               balance_dirty_pages_ratelimited(mapping);
-                       }
+               dirtied = set_page_dirty(page);
+               VM_BUG_ON_PAGE(PageAnon(page), page);
+               mapping = page->mapping;
+               unlock_page(page);
+               page_cache_release(page);
 
-                       if (!page_mkwrite)
-                               file_update_time(vma->vm_file);
+               if ((dirtied || page_mkwrite) && mapping) {
+                       /*
+                        * Some device drivers do not set page.mapping
+                        * but still dirty their pages
+                        */
+                       balance_dirty_pages_ratelimited(mapping);
                }
 
-               return ret;
+               if (!page_mkwrite)
+                       file_update_time(vma->vm_file);
        }
 
-       /*
-        * Ok, we need to copy. Oh, well..
-        */
-       page_cache_get(old_page);
-gotten:
-       pte_unmap_unlock(page_table, ptl);
+       return VM_FAULT_WRITE;
+}
+
+/*
+ * Handle the case of a page which we actually need to copy to a new page.
+ *
+ * Called with mmap_sem locked and the old page referenced, but
+ * without the ptl held.
+ *
+ * High level logic flow:
+ *
+ * - Allocate a page, copy the content of the old page to the new one.
+ * - Handle book keeping and accounting - cgroups, mmu-notifiers, etc.
+ * - Take the PTL. If the pte changed, bail out and release the allocated page
+ * - If the pte is still the way we remember it, update the page table and all
+ *   relevant references. This includes dropping the reference the page-table
+ *   held to the old page, as well as updating the rmap.
+ * - In any case, unlock the PTL and drop the reference we took to the old page.
+ */
+static int wp_page_copy(struct mm_struct *mm, struct vm_area_struct *vma,
+                       unsigned long address, pte_t *page_table, pmd_t *pmd,
+                       pte_t orig_pte, struct page *old_page)
+{
+       struct page *new_page = NULL;
+       spinlock_t *ptl = NULL;
+       pte_t entry;
+       int page_copied = 0;
+       const unsigned long mmun_start = address & PAGE_MASK;   /* For mmu_notifiers */
+       const unsigned long mmun_end = mmun_start + PAGE_SIZE;  /* For mmu_notifiers */
+       struct mem_cgroup *memcg;
 
        if (unlikely(anon_vma_prepare(vma)))
                goto oom;
@@ -2163,8 +2087,6 @@ gotten:
        if (mem_cgroup_try_charge(new_page, mm, GFP_KERNEL, &memcg))
                goto oom_free_new;
 
-       mmun_start  = address & PAGE_MASK;
-       mmun_end    = mmun_start + PAGE_SIZE;
        mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
 
        /*
@@ -2177,8 +2099,9 @@ gotten:
                                dec_mm_counter_fast(mm, MM_FILEPAGES);
                                inc_mm_counter_fast(mm, MM_ANONPAGES);
                        }
-               } else
+               } else {
                        inc_mm_counter_fast(mm, MM_ANONPAGES);
+               }
                flush_cache_page(vma, address, pte_pfn(orig_pte));
                entry = mk_pte(new_page, vma->vm_page_prot);
                entry = maybe_mkwrite(pte_mkdirty(entry), vma);
@@ -2227,29 +2150,29 @@ gotten:
 
                /* Free the old page.. */
                new_page = old_page;
-               ret |= VM_FAULT_WRITE;
-       } else
+               page_copied = 1;
+       } else {
                mem_cgroup_cancel_charge(new_page, memcg);
+       }
 
        if (new_page)
                page_cache_release(new_page);
-unlock:
+
        pte_unmap_unlock(page_table, ptl);
-       if (mmun_end > mmun_start)
-               mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
        if (old_page) {
                /*
                 * Don't let another task, with possibly unlocked vma,
                 * keep the mlocked page.
                 */
-               if ((ret & VM_FAULT_WRITE) && (vma->vm_flags & VM_LOCKED)) {
+               if (page_copied && (vma->vm_flags & VM_LOCKED)) {
                        lock_page(old_page);    /* LRU manipulation */
                        munlock_vma_page(old_page);
                        unlock_page(old_page);
                }
                page_cache_release(old_page);
        }
-       return ret;
+       return page_copied ? VM_FAULT_WRITE : 0;
 oom_free_new:
        page_cache_release(new_page);
 oom:
@@ -2258,6 +2181,144 @@ oom:
        return VM_FAULT_OOM;
 }
 
+static int wp_page_shared(struct mm_struct *mm, struct vm_area_struct *vma,
+                         unsigned long address, pte_t *page_table,
+                         pmd_t *pmd, spinlock_t *ptl, pte_t orig_pte,
+                         struct page *old_page)
+       __releases(ptl)
+{
+       int page_mkwrite = 0;
+
+       page_cache_get(old_page);
+
+       /*
+        * Only catch write-faults on shared writable pages,
+        * read-only shared pages can get COWed by
+        * get_user_pages(.write=1, .force=1).
+        */
+       if (vma->vm_ops && vma->vm_ops->page_mkwrite) {
+               int tmp;
+
+               pte_unmap_unlock(page_table, ptl);
+               tmp = do_page_mkwrite(vma, old_page, address);
+               if (unlikely(!tmp || (tmp &
+                                     (VM_FAULT_ERROR | VM_FAULT_NOPAGE)))) {
+                       page_cache_release(old_page);
+                       return tmp;
+               }
+               /*
+                * Since we dropped the lock we need to revalidate
+                * the PTE as someone else may have changed it.  If
+                * they did, we just return, as we can count on the
+                * MMU to tell us if they didn't also make it writable.
+                */
+               page_table = pte_offset_map_lock(mm, pmd, address,
+                                                &ptl);
+               if (!pte_same(*page_table, orig_pte)) {
+                       unlock_page(old_page);
+                       pte_unmap_unlock(page_table, ptl);
+                       page_cache_release(old_page);
+                       return 0;
+               }
+               page_mkwrite = 1;
+       }
+
+       return wp_page_reuse(mm, vma, address, page_table, ptl,
+                            orig_pte, old_page, page_mkwrite, 1);
+}
+
+/*
+ * This routine handles present pages, when users try to write
+ * to a shared page. It is done by copying the page to a new address
+ * and decrementing the shared-page counter for the old page.
+ *
+ * Note that this routine assumes that the protection checks have been
+ * done by the caller (the low-level page fault routine in most cases).
+ * Thus we can safely just mark it writable once we've done any necessary
+ * COW.
+ *
+ * We also mark the page dirty at this point even though the page will
+ * change only once the write actually happens. This avoids a few races,
+ * and potentially makes it more efficient.
+ *
+ * We enter with non-exclusive mmap_sem (to exclude vma changes,
+ * but allow concurrent faults), with pte both mapped and locked.
+ * We return with mmap_sem still held, but pte unmapped and unlocked.
+ */
+static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
+               unsigned long address, pte_t *page_table, pmd_t *pmd,
+               spinlock_t *ptl, pte_t orig_pte)
+       __releases(ptl)
+{
+       struct page *old_page;
+
+       old_page = vm_normal_page(vma, address, orig_pte);
+       if (!old_page) {
+               /*
+                * VM_MIXEDMAP !pfn_valid() case, or VM_SOFTDIRTY clear on a
+                * VM_PFNMAP VMA.
+                *
+                * We should not cow pages in a shared writeable mapping.
+                * Just mark the pages writable as we can't do any dirty
+                * accounting on raw pfn maps.
+                */
+               if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
+                                    (VM_WRITE|VM_SHARED))
+                       return wp_page_reuse(mm, vma, address, page_table, ptl,
+                                            orig_pte, old_page, 0, 0);
+
+               pte_unmap_unlock(page_table, ptl);
+               return wp_page_copy(mm, vma, address, page_table, pmd,
+                                   orig_pte, old_page);
+       }
+
+       /*
+        * Take out anonymous pages first, anonymous shared vmas are
+        * not dirty accountable.
+        */
+       if (PageAnon(old_page) && !PageKsm(old_page)) {
+               if (!trylock_page(old_page)) {
+                       page_cache_get(old_page);
+                       pte_unmap_unlock(page_table, ptl);
+                       lock_page(old_page);
+                       page_table = pte_offset_map_lock(mm, pmd, address,
+                                                        &ptl);
+                       if (!pte_same(*page_table, orig_pte)) {
+                               unlock_page(old_page);
+                               pte_unmap_unlock(page_table, ptl);
+                               page_cache_release(old_page);
+                               return 0;
+                       }
+                       page_cache_release(old_page);
+               }
+               if (reuse_swap_page(old_page)) {
+                       /*
+                        * The page is all ours.  Move it to our anon_vma so
+                        * the rmap code will not search our parent or siblings.
+                        * Protected against the rmap code by the page lock.
+                        */
+                       page_move_anon_rmap(old_page, vma, address);
+                       unlock_page(old_page);
+                       return wp_page_reuse(mm, vma, address, page_table, ptl,
+                                            orig_pte, old_page, 0, 0);
+               }
+               unlock_page(old_page);
+       } else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
+                                       (VM_WRITE|VM_SHARED))) {
+               return wp_page_shared(mm, vma, address, page_table, pmd,
+                                     ptl, orig_pte, old_page);
+       }
+
+       /*
+        * Ok, we need to copy. Oh, well..
+        */
+       page_cache_get(old_page);
+
+       pte_unmap_unlock(page_table, ptl);
+       return wp_page_copy(mm, vma, address, page_table, pmd,
+                           orig_pte, old_page);
+}
+
 static void unmap_mapping_range_vma(struct vm_area_struct *vma,
                unsigned long start_addr, unsigned long end_addr,
                struct zap_details *details)
index 65842d688b7c9bb5dbfd2440fc07339fa94650f4..e2e8014fb75548bfca8c720e39fd79f5328d9533 100644 (file)
@@ -104,7 +104,7 @@ void put_online_mems(void)
 
 }
 
-static void mem_hotplug_begin(void)
+void mem_hotplug_begin(void)
 {
        mem_hotplug.active_writer = current;
 
@@ -119,7 +119,7 @@ static void mem_hotplug_begin(void)
        }
 }
 
-static void mem_hotplug_done(void)
+void mem_hotplug_done(void)
 {
        mem_hotplug.active_writer = NULL;
        mutex_unlock(&mem_hotplug.lock);
@@ -502,7 +502,7 @@ int __ref __add_pages(int nid, struct zone *zone, unsigned long phys_start_pfn,
        end_sec = pfn_to_section_nr(phys_start_pfn + nr_pages - 1);
 
        for (i = start_sec; i <= end_sec; i++) {
-               err = __add_section(nid, zone, i << PFN_SECTION_SHIFT);
+               err = __add_section(nid, zone, section_nr_to_pfn(i));
 
                /*
                 * EEXIST is finally dealt with by ioresource collision
@@ -959,6 +959,7 @@ static void node_states_set_node(int node, struct memory_notify *arg)
 }
 
 
+/* Must be protected by mem_hotplug_begin() */
 int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_type)
 {
        unsigned long flags;
@@ -969,7 +970,6 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
        int ret;
        struct memory_notify arg;
 
-       mem_hotplug_begin();
        /*
         * This doesn't need a lock to do pfn_to_page().
         * The section can't be removed here because of the
@@ -977,21 +977,20 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
         */
        zone = page_zone(pfn_to_page(pfn));
 
-       ret = -EINVAL;
        if ((zone_idx(zone) > ZONE_NORMAL ||
            online_type == MMOP_ONLINE_MOVABLE) &&
            !can_online_high_movable(zone))
-               goto out;
+               return -EINVAL;
 
        if (online_type == MMOP_ONLINE_KERNEL &&
            zone_idx(zone) == ZONE_MOVABLE) {
                if (move_pfn_range_left(zone - 1, zone, pfn, pfn + nr_pages))
-                       goto out;
+                       return -EINVAL;
        }
        if (online_type == MMOP_ONLINE_MOVABLE &&
            zone_idx(zone) == ZONE_MOVABLE - 1) {
                if (move_pfn_range_right(zone, zone + 1, pfn, pfn + nr_pages))
-                       goto out;
+                       return -EINVAL;
        }
 
        /* Previous code may changed the zone of the pfn range */
@@ -1007,7 +1006,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
        ret = notifier_to_errno(ret);
        if (ret) {
                memory_notify(MEM_CANCEL_ONLINE, &arg);
-               goto out;
+               return ret;
        }
        /*
         * If this zone is not populated, then it is not in zonelist.
@@ -1031,7 +1030,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
                       (((unsigned long long) pfn + nr_pages)
                            << PAGE_SHIFT) - 1);
                memory_notify(MEM_CANCEL_ONLINE, &arg);
-               goto out;
+               return ret;
        }
 
        zone->present_pages += onlined_pages;
@@ -1061,9 +1060,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
 
        if (onlined_pages)
                memory_notify(MEM_ONLINE, &arg);
-out:
-       mem_hotplug_done();
-       return ret;
+       return 0;
 }
 #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
 
@@ -1688,21 +1685,18 @@ static int __ref __offline_pages(unsigned long start_pfn,
        if (!test_pages_in_a_zone(start_pfn, end_pfn))
                return -EINVAL;
 
-       mem_hotplug_begin();
-
        zone = page_zone(pfn_to_page(start_pfn));
        node = zone_to_nid(zone);
        nr_pages = end_pfn - start_pfn;
 
-       ret = -EINVAL;
        if (zone_idx(zone) <= ZONE_NORMAL && !can_offline_normal(zone, nr_pages))
-               goto out;
+               return -EINVAL;
 
        /* set above range as isolated */
        ret = start_isolate_page_range(start_pfn, end_pfn,
                                       MIGRATE_MOVABLE, true);
        if (ret)
-               goto out;
+               return ret;
 
        arg.start_pfn = start_pfn;
        arg.nr_pages = nr_pages;
@@ -1795,7 +1789,6 @@ repeat:
        writeback_set_ratelimit();
 
        memory_notify(MEM_OFFLINE, &arg);
-       mem_hotplug_done();
        return 0;
 
 failed_removal:
@@ -1805,12 +1798,10 @@ failed_removal:
        memory_notify(MEM_CANCEL_OFFLINE, &arg);
        /* pushback to free area */
        undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
-
-out:
-       mem_hotplug_done();
        return ret;
 }
 
+/* Must be protected by mem_hotplug_begin() */
 int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
 {
        return __offline_pages(start_pfn, start_pfn + nr_pages, 120 * HZ);
index 4721046a134a6b8c6ab177c92cebbc67da02dc9d..ede26291d4aa92ad120bfd006786414fd6d45c56 100644 (file)
@@ -945,7 +945,8 @@ static struct page *new_node_page(struct page *page, unsigned long node, int **x
                return alloc_huge_page_node(page_hstate(compound_head(page)),
                                        node);
        else
-               return alloc_pages_exact_node(node, GFP_HIGHUSER_MOVABLE, 0);
+               return alloc_pages_exact_node(node, GFP_HIGHUSER_MOVABLE |
+                                                   __GFP_THISNODE, 0);
 }
 
 /*
@@ -1985,7 +1986,8 @@ retry_cpuset:
                nmask = policy_nodemask(gfp, pol);
                if (!nmask || node_isset(node, *nmask)) {
                        mpol_cond_put(pol);
-                       page = alloc_pages_exact_node(node, gfp, order);
+                       page = alloc_pages_exact_node(node,
+                                               gfp | __GFP_THISNODE, order);
                        goto out;
                }
        }
index e209c98c72039b55afd1b5ca0b518e89094770a8..949970db28741532172ad2c7a65fdeb71c3f7404 100644 (file)
@@ -113,23 +113,24 @@ EXPORT_SYMBOL(mempool_create_node);
  *              mempool_create().
  * @new_min_nr: the new minimum number of elements guaranteed to be
  *              allocated for this pool.
- * @gfp_mask:   the usual allocation bitmask.
  *
  * This function shrinks/grows the pool. In the case of growing,
  * it cannot be guaranteed that the pool will be grown to the new
  * size immediately, but new mempool_free() calls will refill it.
+ * This function may sleep.
  *
  * Note, the caller must guarantee that no mempool_destroy is called
  * while this function is running. mempool_alloc() & mempool_free()
  * might be called (eg. from IRQ contexts) while this function executes.
  */
-int mempool_resize(mempool_t *pool, int new_min_nr, gfp_t gfp_mask)
+int mempool_resize(mempool_t *pool, int new_min_nr)
 {
        void *element;
        void **new_elements;
        unsigned long flags;
 
        BUG_ON(new_min_nr <= 0);
+       might_sleep();
 
        spin_lock_irqsave(&pool->lock, flags);
        if (new_min_nr <= pool->min_nr) {
@@ -145,7 +146,8 @@ int mempool_resize(mempool_t *pool, int new_min_nr, gfp_t gfp_mask)
        spin_unlock_irqrestore(&pool->lock, flags);
 
        /* Grow the pool */
-       new_elements = kmalloc(new_min_nr * sizeof(*new_elements), gfp_mask);
+       new_elements = kmalloc_array(new_min_nr, sizeof(*new_elements),
+                                    GFP_KERNEL);
        if (!new_elements)
                return -ENOMEM;
 
@@ -164,7 +166,7 @@ int mempool_resize(mempool_t *pool, int new_min_nr, gfp_t gfp_mask)
 
        while (pool->curr_nr < pool->min_nr) {
                spin_unlock_irqrestore(&pool->lock, flags);
-               element = pool->alloc(gfp_mask, pool->pool_data);
+               element = pool->alloc(GFP_KERNEL, pool->pool_data);
                if (!element)
                        goto out;
                spin_lock_irqsave(&pool->lock, flags);
diff --git a/mm/memtest.c b/mm/memtest.c
new file mode 100644 (file)
index 0000000..1997d93
--- /dev/null
@@ -0,0 +1,118 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/pfn.h>
+#include <linux/memblock.h>
+
+static u64 patterns[] __initdata = {
+       /* The first entry has to be 0 to leave memtest with zeroed memory */
+       0,
+       0xffffffffffffffffULL,
+       0x5555555555555555ULL,
+       0xaaaaaaaaaaaaaaaaULL,
+       0x1111111111111111ULL,
+       0x2222222222222222ULL,
+       0x4444444444444444ULL,
+       0x8888888888888888ULL,
+       0x3333333333333333ULL,
+       0x6666666666666666ULL,
+       0x9999999999999999ULL,
+       0xccccccccccccccccULL,
+       0x7777777777777777ULL,
+       0xbbbbbbbbbbbbbbbbULL,
+       0xddddddddddddddddULL,
+       0xeeeeeeeeeeeeeeeeULL,
+       0x7a6c7258554e494cULL, /* yeah ;-) */
+};
+
+static void __init reserve_bad_mem(u64 pattern, phys_addr_t start_bad, phys_addr_t end_bad)
+{
+       printk(KERN_INFO "  %016llx bad mem addr %010llx - %010llx reserved\n",
+              (unsigned long long) pattern,
+              (unsigned long long) start_bad,
+              (unsigned long long) end_bad);
+       memblock_reserve(start_bad, end_bad - start_bad);
+}
+
+static void __init memtest(u64 pattern, phys_addr_t start_phys, phys_addr_t size)
+{
+       u64 *p, *start, *end;
+       phys_addr_t start_bad, last_bad;
+       phys_addr_t start_phys_aligned;
+       const size_t incr = sizeof(pattern);
+
+       start_phys_aligned = ALIGN(start_phys, incr);
+       start = __va(start_phys_aligned);
+       end = start + (size - (start_phys_aligned - start_phys)) / incr;
+       start_bad = 0;
+       last_bad = 0;
+
+       for (p = start; p < end; p++)
+               *p = pattern;
+
+       for (p = start; p < end; p++, start_phys_aligned += incr) {
+               if (*p == pattern)
+                       continue;
+               if (start_phys_aligned == last_bad + incr) {
+                       last_bad += incr;
+                       continue;
+               }
+               if (start_bad)
+                       reserve_bad_mem(pattern, start_bad, last_bad + incr);
+               start_bad = last_bad = start_phys_aligned;
+       }
+       if (start_bad)
+               reserve_bad_mem(pattern, start_bad, last_bad + incr);
+}
+
+static void __init do_one_pass(u64 pattern, phys_addr_t start, phys_addr_t end)
+{
+       u64 i;
+       phys_addr_t this_start, this_end;
+
+       for_each_free_mem_range(i, NUMA_NO_NODE, &this_start, &this_end, NULL) {
+               this_start = clamp(this_start, start, end);
+               this_end = clamp(this_end, start, end);
+               if (this_start < this_end) {
+                       printk(KERN_INFO "  %010llx - %010llx pattern %016llx\n",
+                              (unsigned long long)this_start,
+                              (unsigned long long)this_end,
+                              (unsigned long long)cpu_to_be64(pattern));
+                       memtest(pattern, this_start, this_end - this_start);
+               }
+       }
+}
+
+/* default is disabled */
+static int memtest_pattern __initdata;
+
+static int __init parse_memtest(char *arg)
+{
+       if (arg)
+               memtest_pattern = simple_strtoul(arg, NULL, 0);
+       else
+               memtest_pattern = ARRAY_SIZE(patterns);
+
+       return 0;
+}
+
+early_param("memtest", parse_memtest);
+
+void __init early_memtest(phys_addr_t start, phys_addr_t end)
+{
+       unsigned int i;
+       unsigned int idx = 0;
+
+       if (!memtest_pattern)
+               return;
+
+       printk(KERN_INFO "early_memtest: # of tests: %d\n", memtest_pattern);
+       for (i = memtest_pattern-1; i < UINT_MAX; --i) {
+               idx = i % ARRAY_SIZE(patterns);
+               do_one_pass(patterns[idx], start, end);
+       }
+}
index 85e04268603143826e8cd80c533419feb221ad56..a65ff72ab7392e291ab69b45cd1d14ac0c16e27b 100644 (file)
@@ -900,13 +900,24 @@ out:
        return rc;
 }
 
+/*
+ * gcc 4.7 and 4.8 on arm get an ICEs when inlining unmap_and_move().  Work
+ * around it.
+ */
+#if (GCC_VERSION >= 40700 && GCC_VERSION < 40900) && defined(CONFIG_ARM)
+#define ICE_noinline noinline
+#else
+#define ICE_noinline
+#endif
+
 /*
  * Obtain the lock on page, remove all ptes and migrate the page
  * to the newly allocated page in newpage.
  */
-static int unmap_and_move(new_page_t get_new_page, free_page_t put_new_page,
-                       unsigned long private, struct page *page, int force,
-                       enum migrate_mode mode)
+static ICE_noinline int unmap_and_move(new_page_t get_new_page,
+                                  free_page_t put_new_page,
+                                  unsigned long private, struct page *page,
+                                  int force, enum migrate_mode mode)
 {
        int rc = 0;
        int *result = NULL;
@@ -1554,30 +1565,10 @@ static struct page *alloc_misplaced_dst_page(struct page *page,
  * page migration rate limiting control.
  * Do not migrate more than @pages_to_migrate in a @migrate_interval_millisecs
  * window of time. Default here says do not migrate more than 1280M per second.
- * If a node is rate-limited then PTE NUMA updates are also rate-limited. However
- * as it is faults that reset the window, pte updates will happen unconditionally
- * if there has not been a fault since @pteupdate_interval_millisecs after the
- * throttle window closed.
  */
 static unsigned int migrate_interval_millisecs __read_mostly = 100;
-static unsigned int pteupdate_interval_millisecs __read_mostly = 1000;
 static unsigned int ratelimit_pages __read_mostly = 128 << (20 - PAGE_SHIFT);
 
-/* Returns true if NUMA migration is currently rate limited */
-bool migrate_ratelimited(int node)
-{
-       pg_data_t *pgdat = NODE_DATA(node);
-
-       if (time_after(jiffies, pgdat->numabalancing_migrate_next_window +
-                               msecs_to_jiffies(pteupdate_interval_millisecs)))
-               return false;
-
-       if (pgdat->numabalancing_migrate_nr_pages < ratelimit_pages)
-               return false;
-
-       return true;
-}
-
 /* Returns true if the node is migrate rate-limited after the update */
 static bool numamigrate_update_ratelimit(pg_data_t *pgdat,
                                        unsigned long nr_pages)
index 8a54cd214925872a66d4d1cc36b69ec6c6047324..6fd2cf15e8687d32114f8e81516aed0a52997147 100644 (file)
@@ -205,62 +205,6 @@ out:
        return nr_pages - 1;
 }
 
-/**
- * __mlock_vma_pages_range() -  mlock a range of pages in the vma.
- * @vma:   target vma
- * @start: start address
- * @end:   end address
- * @nonblocking:
- *
- * This takes care of making the pages present too.
- *
- * return 0 on success, negative error code on error.
- *
- * vma->vm_mm->mmap_sem must be held.
- *
- * If @nonblocking is NULL, it may be held for read or write and will
- * be unperturbed.
- *
- * If @nonblocking is non-NULL, it must held for read only and may be
- * released.  If it's released, *@nonblocking will be set to 0.
- */
-long __mlock_vma_pages_range(struct vm_area_struct *vma,
-               unsigned long start, unsigned long end, int *nonblocking)
-{
-       struct mm_struct *mm = vma->vm_mm;
-       unsigned long nr_pages = (end - start) / PAGE_SIZE;
-       int gup_flags;
-
-       VM_BUG_ON(start & ~PAGE_MASK);
-       VM_BUG_ON(end   & ~PAGE_MASK);
-       VM_BUG_ON_VMA(start < vma->vm_start, vma);
-       VM_BUG_ON_VMA(end   > vma->vm_end, vma);
-       VM_BUG_ON_MM(!rwsem_is_locked(&mm->mmap_sem), mm);
-
-       gup_flags = FOLL_TOUCH | FOLL_MLOCK;
-       /*
-        * We want to touch writable mappings with a write fault in order
-        * to break COW, except for shared mappings because these don't COW
-        * and we would not want to dirty them for nothing.
-        */
-       if ((vma->vm_flags & (VM_WRITE | VM_SHARED)) == VM_WRITE)
-               gup_flags |= FOLL_WRITE;
-
-       /*
-        * We want mlock to succeed for regions that have any permissions
-        * other than PROT_NONE.
-        */
-       if (vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC))
-               gup_flags |= FOLL_FORCE;
-
-       /*
-        * We made sure addr is within a VMA, so the following will
-        * not result in a stack expansion that recurses back here.
-        */
-       return __get_user_pages(current, mm, start, nr_pages, gup_flags,
-                               NULL, NULL, nonblocking);
-}
-
 /*
  * convert get_user_pages() return value to posix mlock() error
  */
@@ -596,7 +540,7 @@ success:
        /*
         * vm_flags is protected by the mmap_sem held in write mode.
         * It's okay if try_to_unmap_one unmaps a page just after we
-        * set VM_LOCKED, __mlock_vma_pages_range will bring it back.
+        * set VM_LOCKED, populate_vma_page_range will bring it back.
         */
 
        if (lock)
@@ -660,69 +604,6 @@ static int do_mlock(unsigned long start, size_t len, int on)
        return error;
 }
 
-/*
- * __mm_populate - populate and/or mlock pages within a range of address space.
- *
- * This is used to implement mlock() and the MAP_POPULATE / MAP_LOCKED mmap
- * flags. VMAs must be already marked with the desired vm_flags, and
- * mmap_sem must not be held.
- */
-int __mm_populate(unsigned long start, unsigned long len, int ignore_errors)
-{
-       struct mm_struct *mm = current->mm;
-       unsigned long end, nstart, nend;
-       struct vm_area_struct *vma = NULL;
-       int locked = 0;
-       long ret = 0;
-
-       VM_BUG_ON(start & ~PAGE_MASK);
-       VM_BUG_ON(len != PAGE_ALIGN(len));
-       end = start + len;
-
-       for (nstart = start; nstart < end; nstart = nend) {
-               /*
-                * We want to fault in pages for [nstart; end) address range.
-                * Find first corresponding VMA.
-                */
-               if (!locked) {
-                       locked = 1;
-                       down_read(&mm->mmap_sem);
-                       vma = find_vma(mm, nstart);
-               } else if (nstart >= vma->vm_end)
-                       vma = vma->vm_next;
-               if (!vma || vma->vm_start >= end)
-                       break;
-               /*
-                * Set [nstart; nend) to intersection of desired address
-                * range with the first VMA. Also, skip undesirable VMA types.
-                */
-               nend = min(end, vma->vm_end);
-               if (vma->vm_flags & (VM_IO | VM_PFNMAP))
-                       continue;
-               if (nstart < vma->vm_start)
-                       nstart = vma->vm_start;
-               /*
-                * Now fault in a range of pages. __mlock_vma_pages_range()
-                * double checks the vma flags, so that it won't mlock pages
-                * if the vma was already munlocked.
-                */
-               ret = __mlock_vma_pages_range(vma, nstart, nend, &locked);
-               if (ret < 0) {
-                       if (ignore_errors) {
-                               ret = 0;
-                               continue;       /* continue at next VMA */
-                       }
-                       ret = __mlock_posix_error_return(ret);
-                       break;
-               }
-               nend = nstart + ret * PAGE_SIZE;
-               ret = 0;
-       }
-       if (locked)
-               up_read(&mm->mmap_sem);
-       return ret;     /* 0 or negative error code */
-}
-
 SYSCALL_DEFINE2(mlock, unsigned long, start, size_t, len)
 {
        unsigned long locked;
@@ -750,9 +631,13 @@ SYSCALL_DEFINE2(mlock, unsigned long, start, size_t, len)
                error = do_mlock(start, len, 1);
 
        up_write(&current->mm->mmap_sem);
-       if (!error)
-               error = __mm_populate(start, len, 0);
-       return error;
+       if (error)
+               return error;
+
+       error = __mm_populate(start, len, 0);
+       if (error)
+               return __mlock_posix_error_return(error);
+       return 0;
 }
 
 SYSCALL_DEFINE2(munlock, unsigned long, start, size_t, len)
index 9ec50a368634a8d9a0824504d479b03798bdc402..06a6076c92e5e9e159246fbbeaf904072a874270 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2316,7 +2316,7 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr)
        if (!prev || expand_stack(prev, addr))
                return NULL;
        if (prev->vm_flags & VM_LOCKED)
-               __mlock_vma_pages_range(prev, addr, prev->vm_end, NULL);
+               populate_vma_page_range(prev, addr, prev->vm_end, NULL);
        return prev;
 }
 #else
@@ -2351,7 +2351,7 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr)
        if (expand_stack(vma, addr))
                return NULL;
        if (vma->vm_flags & VM_LOCKED)
-               __mlock_vma_pages_range(vma, addr, start, NULL);
+               populate_vma_page_range(vma, addr, start, NULL);
        return vma;
 }
 #endif
index 57dadc025c6444dd1038691d160803745db124f8..2dc44b1cb1dfc2f6d644d2d655155e6cfce2bdeb 100644 (file)
@@ -286,8 +286,14 @@ static unsigned long move_vma(struct vm_area_struct *vma,
                old_len = new_len;
                old_addr = new_addr;
                new_addr = -ENOMEM;
-       } else if (vma->vm_file && vma->vm_file->f_op->mremap)
-               vma->vm_file->f_op->mremap(vma->vm_file, new_vma);
+       } else if (vma->vm_file && vma->vm_file->f_op->mremap) {
+               err = vma->vm_file->f_op->mremap(vma->vm_file, new_vma);
+               if (err < 0) {
+                       move_page_tables(new_vma, new_addr, vma, old_addr,
+                                        moved_len, true);
+                       return err;
+               }
+       }
 
        /* Conceal VM_ACCOUNT so old reservation is not undone */
        if (vm_flags & VM_ACCOUNT) {
index 642f38cb175aa8321ab25d643d449d6cdd94f977..52628c819bf7d4852cc4604b89357e99420e6c74 100644 (file)
@@ -612,7 +612,8 @@ void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
  * Determines whether the kernel must panic because of the panic_on_oom sysctl.
  */
 void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask,
-                       int order, const nodemask_t *nodemask)
+                       int order, const nodemask_t *nodemask,
+                       struct mem_cgroup *memcg)
 {
        if (likely(!sysctl_panic_on_oom))
                return;
@@ -625,7 +626,7 @@ void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask,
                if (constraint != CONSTRAINT_NONE)
                        return;
        }
-       dump_header(NULL, gfp_mask, order, NULL, nodemask);
+       dump_header(NULL, gfp_mask, order, memcg, nodemask);
        panic("Out of memory: %s panic_on_oom is enabled\n",
                sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide");
 }
@@ -740,7 +741,7 @@ static void __out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
        constraint = constrained_alloc(zonelist, gfp_mask, nodemask,
                                                &totalpages);
        mpol_mask = (constraint == CONSTRAINT_MEMORY_POLICY) ? nodemask : NULL;
-       check_panic_on_oom(constraint, gfp_mask, order, mpol_mask);
+       check_panic_on_oom(constraint, gfp_mask, order, mpol_mask, NULL);
 
        if (sysctl_oom_kill_allocating_task && current->mm &&
            !oom_unkillable_task(current, NULL, nodemask) &&
index 644bcb665773f6e53f50fe6599429595b506f0c5..0372411f38fc516dd64cd6432cce29ee613facf4 100644 (file)
@@ -2110,6 +2110,25 @@ void account_page_dirtied(struct page *page, struct address_space *mapping)
 }
 EXPORT_SYMBOL(account_page_dirtied);
 
+/*
+ * Helper function for deaccounting dirty page without writeback.
+ *
+ * Doing this should *normally* only ever be done when a page
+ * is truncated, and is not actually mapped anywhere at all. However,
+ * fs/buffer.c does this when it notices that somebody has cleaned
+ * out all the buffers on a page without actually doing it through
+ * the VM. Can you say "ext3 is horribly ugly"? Thought you could.
+ */
+void account_page_cleaned(struct page *page, struct address_space *mapping)
+{
+       if (mapping_cap_account_dirty(mapping)) {
+               dec_zone_page_state(page, NR_FILE_DIRTY);
+               dec_bdi_stat(inode_to_bdi(mapping->host), BDI_RECLAIMABLE);
+               task_io_account_cancelled_write(PAGE_CACHE_SIZE);
+       }
+}
+EXPORT_SYMBOL(account_page_cleaned);
+
 /*
  * For address_spaces which do not use buffers.  Just tag the page as dirty in
  * its radix tree.
index 40e29429e7b0995bd5799bd6263b18d6ce8261cb..1b849500640c6c0fd109473f518d7a61306b3b11 100644 (file)
@@ -1032,11 +1032,9 @@ struct page *__rmqueue_smallest(struct zone *zone, unsigned int order,
 static int fallbacks[MIGRATE_TYPES][4] = {
        [MIGRATE_UNMOVABLE]   = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE,     MIGRATE_RESERVE },
        [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE,   MIGRATE_MOVABLE,     MIGRATE_RESERVE },
+       [MIGRATE_MOVABLE]     = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE,   MIGRATE_RESERVE },
 #ifdef CONFIG_CMA
-       [MIGRATE_MOVABLE]     = { MIGRATE_CMA,         MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
        [MIGRATE_CMA]         = { MIGRATE_RESERVE }, /* Never used */
-#else
-       [MIGRATE_MOVABLE]     = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE,   MIGRATE_RESERVE },
 #endif
        [MIGRATE_RESERVE]     = { MIGRATE_RESERVE }, /* Never used */
 #ifdef CONFIG_MEMORY_ISOLATION
@@ -1044,6 +1042,17 @@ static int fallbacks[MIGRATE_TYPES][4] = {
 #endif
 };
 
+#ifdef CONFIG_CMA
+static struct page *__rmqueue_cma_fallback(struct zone *zone,
+                                       unsigned int order)
+{
+       return __rmqueue_smallest(zone, order, MIGRATE_CMA);
+}
+#else
+static inline struct page *__rmqueue_cma_fallback(struct zone *zone,
+                                       unsigned int order) { return NULL; }
+#endif
+
 /*
  * Move the free pages in a range to the free lists of the requested type.
  * Note that start_page and end_pages are not aligned on a pageblock
@@ -1136,14 +1145,40 @@ static void change_pageblock_range(struct page *pageblock_page,
  * as fragmentation caused by those allocations polluting movable pageblocks
  * is worse than movable allocations stealing from unmovable and reclaimable
  * pageblocks.
- *
- * If we claim more than half of the pageblock, change pageblock's migratetype
- * as well.
  */
-static void try_to_steal_freepages(struct zone *zone, struct page *page,
-                                 int start_type, int fallback_type)
+static bool can_steal_fallback(unsigned int order, int start_mt)
+{
+       /*
+        * Leaving this order check is intended, although there is
+        * relaxed order check in next check. The reason is that
+        * we can actually steal whole pageblock if this condition met,
+        * but, below check doesn't guarantee it and that is just heuristic
+        * so could be changed anytime.
+        */
+       if (order >= pageblock_order)
+               return true;
+
+       if (order >= pageblock_order / 2 ||
+               start_mt == MIGRATE_RECLAIMABLE ||
+               start_mt == MIGRATE_UNMOVABLE ||
+               page_group_by_mobility_disabled)
+               return true;
+
+       return false;
+}
+
+/*
+ * This function implements actual steal behaviour. If order is large enough,
+ * we can steal whole pageblock. If not, we first move freepages in this
+ * pageblock and check whether half of pages are moved or not. If half of
+ * pages are moved, we can change migratetype of pageblock and permanently
+ * use it's pages as requested migratetype in the future.
+ */
+static void steal_suitable_fallback(struct zone *zone, struct page *page,
+                                                         int start_type)
 {
        int current_order = page_order(page);
+       int pages;
 
        /* Take ownership for orders >= pageblock_order */
        if (current_order >= pageblock_order) {
@@ -1151,19 +1186,49 @@ static void try_to_steal_freepages(struct zone *zone, struct page *page,
                return;
        }
 
-       if (current_order >= pageblock_order / 2 ||
-           start_type == MIGRATE_RECLAIMABLE ||
-           start_type == MIGRATE_UNMOVABLE ||
-           page_group_by_mobility_disabled) {
-               int pages;
+       pages = move_freepages_block(zone, page, start_type);
+
+       /* Claim the whole block if over half of it is free */
+       if (pages >= (1 << (pageblock_order-1)) ||
+                       page_group_by_mobility_disabled)
+               set_pageblock_migratetype(page, start_type);
+}
+
+/*
+ * Check whether there is a suitable fallback freepage with requested order.
+ * If only_stealable is true, this function returns fallback_mt only if
+ * we can steal other freepages all together. This would help to reduce
+ * fragmentation due to mixed migratetype pages in one pageblock.
+ */
+int find_suitable_fallback(struct free_area *area, unsigned int order,
+                       int migratetype, bool only_stealable, bool *can_steal)
+{
+       int i;
+       int fallback_mt;
+
+       if (area->nr_free == 0)
+               return -1;
+
+       *can_steal = false;
+       for (i = 0;; i++) {
+               fallback_mt = fallbacks[migratetype][i];
+               if (fallback_mt == MIGRATE_RESERVE)
+                       break;
+
+               if (list_empty(&area->free_list[fallback_mt]))
+                       continue;
 
-               pages = move_freepages_block(zone, page, start_type);
+               if (can_steal_fallback(order, migratetype))
+                       *can_steal = true;
 
-               /* Claim the whole block if over half of it is free */
-               if (pages >= (1 << (pageblock_order-1)) ||
-                               page_group_by_mobility_disabled)
-                       set_pageblock_migratetype(page, start_type);
+               if (!only_stealable)
+                       return fallback_mt;
+
+               if (*can_steal)
+                       return fallback_mt;
        }
+
+       return -1;
 }
 
 /* Remove an element from the buddy allocator from the fallback list */
@@ -1173,64 +1238,45 @@ __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype)
        struct free_area *area;
        unsigned int current_order;
        struct page *page;
+       int fallback_mt;
+       bool can_steal;
 
        /* Find the largest possible block of pages in the other list */
        for (current_order = MAX_ORDER-1;
                                current_order >= order && current_order <= MAX_ORDER-1;
                                --current_order) {
-               int i;
-               for (i = 0;; i++) {
-                       int migratetype = fallbacks[start_migratetype][i];
-                       int buddy_type = start_migratetype;
-
-                       /* MIGRATE_RESERVE handled later if necessary */
-                       if (migratetype == MIGRATE_RESERVE)
-                               break;
-
-                       area = &(zone->free_area[current_order]);
-                       if (list_empty(&area->free_list[migratetype]))
-                               continue;
-
-                       page = list_entry(area->free_list[migratetype].next,
-                                       struct page, lru);
-                       area->nr_free--;
-
-                       if (!is_migrate_cma(migratetype)) {
-                               try_to_steal_freepages(zone, page,
-                                                       start_migratetype,
-                                                       migratetype);
-                       } else {
-                               /*
-                                * When borrowing from MIGRATE_CMA, we need to
-                                * release the excess buddy pages to CMA
-                                * itself, and we do not try to steal extra
-                                * free pages.
-                                */
-                               buddy_type = migratetype;
-                       }
+               area = &(zone->free_area[current_order]);
+               fallback_mt = find_suitable_fallback(area, current_order,
+                               start_migratetype, false, &can_steal);
+               if (fallback_mt == -1)
+                       continue;
 
-                       /* Remove the page from the freelists */
-                       list_del(&page->lru);
-                       rmv_page_order(page);
+               page = list_entry(area->free_list[fallback_mt].next,
+                                               struct page, lru);
+               if (can_steal)
+                       steal_suitable_fallback(zone, page, start_migratetype);
 
-                       expand(zone, page, order, current_order, area,
-                                       buddy_type);
+               /* Remove the page from the freelists */
+               area->nr_free--;
+               list_del(&page->lru);
+               rmv_page_order(page);
 
-                       /*
-                        * The freepage_migratetype may differ from pageblock's
-                        * migratetype depending on the decisions in
-                        * try_to_steal_freepages(). This is OK as long as it
-                        * does not differ for MIGRATE_CMA pageblocks. For CMA
-                        * we need to make sure unallocated pages flushed from
-                        * pcp lists are returned to the correct freelist.
-                        */
-                       set_freepage_migratetype(page, buddy_type);
+               expand(zone, page, order, current_order, area,
+                                       start_migratetype);
+               /*
+                * The freepage_migratetype may differ from pageblock's
+                * migratetype depending on the decisions in
+                * try_to_steal_freepages(). This is OK as long as it
+                * does not differ for MIGRATE_CMA pageblocks. For CMA
+                * we need to make sure unallocated pages flushed from
+                * pcp lists are returned to the correct freelist.
+                */
+               set_freepage_migratetype(page, start_migratetype);
 
-                       trace_mm_page_alloc_extfrag(page, order, current_order,
-                               start_migratetype, migratetype);
+               trace_mm_page_alloc_extfrag(page, order, current_order,
+                       start_migratetype, fallback_mt);
 
-                       return page;
-               }
+               return page;
        }
 
        return NULL;
@@ -1249,7 +1295,11 @@ retry_reserve:
        page = __rmqueue_smallest(zone, order, migratetype);
 
        if (unlikely(!page) && migratetype != MIGRATE_RESERVE) {
-               page = __rmqueue_fallback(zone, order, migratetype);
+               if (migratetype == MIGRATE_MOVABLE)
+                       page = __rmqueue_cma_fallback(zone, order);
+
+               if (!page)
+                       page = __rmqueue_fallback(zone, order, migratetype);
 
                /*
                 * Use MIGRATE_RESERVE rather than fail an allocation. goto
@@ -2362,13 +2412,7 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
                        *did_some_progress = 1;
                        goto out;
                }
-               /*
-                * GFP_THISNODE contains __GFP_NORETRY and we never hit this.
-                * Sanity check for bare calls of __GFP_THISNODE, not real OOM.
-                * The caller should handle page allocation failure by itself if
-                * it specifies __GFP_THISNODE.
-                * Note: Hugepage uses it but will hit PAGE_ALLOC_COSTLY_ORDER.
-                */
+               /* The OOM killer may not free memory on a specific node */
                if (gfp_mask & __GFP_THISNODE)
                        goto out;
        }
@@ -2623,15 +2667,11 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
        }
 
        /*
-        * GFP_THISNODE (meaning __GFP_THISNODE, __GFP_NORETRY and
-        * __GFP_NOWARN set) should not cause reclaim since the subsystem
-        * (f.e. slab) using GFP_THISNODE may choose to trigger reclaim
-        * using a larger set of nodes after it has established that the
-        * allowed per node queues are empty and that nodes are
-        * over allocated.
+        * If this allocation cannot block and it is for a specific node, then
+        * fail early.  There's no need to wakeup kswapd or retry for a
+        * speculative node-specific allocation.
         */
-       if (IS_ENABLED(CONFIG_NUMA) &&
-           (gfp_mask & GFP_THISNODE) == GFP_THISNODE)
+       if (IS_ENABLED(CONFIG_NUMA) && (gfp_mask & __GFP_THISNODE) && !wait)
                goto nopage;
 
 retry:
@@ -2824,7 +2864,7 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
        /*
         * Check the zones suitable for the gfp_mask contain at least one
         * valid zone. It's possible to have an empty zonelist as a result
-        * of GFP_THISNODE and a memoryless node
+        * of __GFP_THISNODE and a memoryless node
         */
        if (unlikely(!zonelist->_zonerefs->zone))
                return NULL;
@@ -3201,38 +3241,31 @@ static void show_migration_types(unsigned char type)
  * Show free area list (used inside shift_scroll-lock stuff)
  * We also calculate the percentage fragmentation. We do this by counting the
  * memory on each free list with the exception of the first item on the list.
- * Suppresses nodes that are not allowed by current's cpuset if
- * SHOW_MEM_FILTER_NODES is passed.
+ *
+ * Bits in @filter:
+ * SHOW_MEM_FILTER_NODES: suppress nodes that are not allowed by current's
+ *   cpuset.
  */
 void show_free_areas(unsigned int filter)
 {
+       unsigned long free_pcp = 0;
        int cpu;
        struct zone *zone;
 
        for_each_populated_zone(zone) {
                if (skip_free_areas_node(filter, zone_to_nid(zone)))
                        continue;
-               show_node(zone);
-               printk("%s per-cpu:\n", zone->name);
 
-               for_each_online_cpu(cpu) {
-                       struct per_cpu_pageset *pageset;
-
-                       pageset = per_cpu_ptr(zone->pageset, cpu);
-
-                       printk("CPU %4d: hi:%5d, btch:%4d usd:%4d\n",
-                              cpu, pageset->pcp.high,
-                              pageset->pcp.batch, pageset->pcp.count);
-               }
+               for_each_online_cpu(cpu)
+                       free_pcp += per_cpu_ptr(zone->pageset, cpu)->pcp.count;
        }
 
        printk("active_anon:%lu inactive_anon:%lu isolated_anon:%lu\n"
                " active_file:%lu inactive_file:%lu isolated_file:%lu\n"
-               " unevictable:%lu"
-               " dirty:%lu writeback:%lu unstable:%lu\n"
-               " free:%lu slab_reclaimable:%lu slab_unreclaimable:%lu\n"
+               " unevictable:%lu dirty:%lu writeback:%lu unstable:%lu\n"
+               " slab_reclaimable:%lu slab_unreclaimable:%lu\n"
                " mapped:%lu shmem:%lu pagetables:%lu bounce:%lu\n"
-               " free_cma:%lu\n",
+               " free:%lu free_pcp:%lu free_cma:%lu\n",
                global_page_state(NR_ACTIVE_ANON),
                global_page_state(NR_INACTIVE_ANON),
                global_page_state(NR_ISOLATED_ANON),
@@ -3243,13 +3276,14 @@ void show_free_areas(unsigned int filter)
                global_page_state(NR_FILE_DIRTY),
                global_page_state(NR_WRITEBACK),
                global_page_state(NR_UNSTABLE_NFS),
-               global_page_state(NR_FREE_PAGES),
                global_page_state(NR_SLAB_RECLAIMABLE),
                global_page_state(NR_SLAB_UNRECLAIMABLE),
                global_page_state(NR_FILE_MAPPED),
                global_page_state(NR_SHMEM),
                global_page_state(NR_PAGETABLE),
                global_page_state(NR_BOUNCE),
+               global_page_state(NR_FREE_PAGES),
+               free_pcp,
                global_page_state(NR_FREE_CMA_PAGES));
 
        for_each_populated_zone(zone) {
@@ -3257,6 +3291,11 @@ void show_free_areas(unsigned int filter)
 
                if (skip_free_areas_node(filter, zone_to_nid(zone)))
                        continue;
+
+               free_pcp = 0;
+               for_each_online_cpu(cpu)
+                       free_pcp += per_cpu_ptr(zone->pageset, cpu)->pcp.count;
+
                show_node(zone);
                printk("%s"
                        " free:%lukB"
@@ -3283,6 +3322,8 @@ void show_free_areas(unsigned int filter)
                        " pagetables:%lukB"
                        " unstable:%lukB"
                        " bounce:%lukB"
+                       " free_pcp:%lukB"
+                       " local_pcp:%ukB"
                        " free_cma:%lukB"
                        " writeback_tmp:%lukB"
                        " pages_scanned:%lu"
@@ -3314,6 +3355,8 @@ void show_free_areas(unsigned int filter)
                        K(zone_page_state(zone, NR_PAGETABLE)),
                        K(zone_page_state(zone, NR_UNSTABLE_NFS)),
                        K(zone_page_state(zone, NR_BOUNCE)),
+                       K(free_pcp),
+                       K(this_cpu_read(zone->pageset->pcp.count)),
                        K(zone_page_state(zone, NR_FREE_CMA_PAGES)),
                        K(zone_page_state(zone, NR_WRITEBACK_TEMP)),
                        K(zone_page_state(zone, NR_PAGES_SCANNED)),
@@ -5717,7 +5760,7 @@ static void __setup_per_zone_wmarks(void)
                         * value here.
                         *
                         * The WMARK_HIGH-WMARK_LOW and (WMARK_LOW-WMARK_MIN)
-                        * deltas controls asynch page reclaim, and so should
+                        * deltas control asynch page reclaim, and so should
                         * not be capped for highmem.
                         */
                        unsigned long min_pages;
index e6045804c8d876db5c480d6c64e3c5f4e7bb7a84..a96c8562d83567466b6633dd169c84ff63418e66 100644 (file)
@@ -20,8 +20,8 @@
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
 #include <linux/frontswap.h>
-#include <linux/aio.h>
 #include <linux/blkdev.h>
+#include <linux/uio.h>
 #include <asm/pgtable.h>
 
 static struct bio *get_swap_bio(gfp_t gfp_flags,
@@ -274,7 +274,6 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
                iov_iter_bvec(&from, ITER_BVEC | WRITE, &bv, 1, PAGE_SIZE);
                init_sync_kiocb(&kiocb, swap_file);
                kiocb.ki_pos = page_file_offset(page);
-               kiocb.ki_nbytes = PAGE_SIZE;
 
                set_page_writeback(page);
                unlock_page(page);
index 73c97a5f4495c0df39f229972023ba3ec14f01c6..dfd02484e8de10913e4fe1264bde04e00cc1e9b6 100644 (file)
@@ -1310,7 +1310,7 @@ bool is_kernel_percpu_address(unsigned long addr)
  * and, from the second one, the backing allocator (currently either vm or
  * km) provides translation.
  *
- * The addr can be tranlated simply without checking if it falls into the
+ * The addr can be translated simply without checking if it falls into the
  * first chunk. But the current code reflects better how percpu allocator
  * actually works, and the verification can discover both bugs in percpu
  * allocator itself and per_cpu_ptr_to_phys() callers. So we keep current
@@ -1762,7 +1762,7 @@ early_param("percpu_alloc", percpu_alloc_setup);
  * and other parameters considering needed percpu size, allocation
  * atom size and distances between CPUs.
  *
- * Groups are always mutliples of atom size and CPUs which are of
+ * Groups are always multiples of atom size and CPUs which are of
  * LOCAL_DISTANCE both ways are grouped together and share space for
  * units in the same group.  The returned configuration is guaranteed
  * to have CPUs on different nodes on different groups and >=75% usage
index b1597690530ce84644d8e405dab02740298706cd..e88d071648c2dece38b25d3fc8e57091d1fcd1d1 100644 (file)
@@ -257,22 +257,18 @@ static ssize_t process_vm_rw(pid_t pid,
        struct iovec *iov_r = iovstack_r;
        struct iov_iter iter;
        ssize_t rc;
+       int dir = vm_write ? WRITE : READ;
 
        if (flags != 0)
                return -EINVAL;
 
        /* Check iovecs */
-       if (vm_write)
-               rc = rw_copy_check_uvector(WRITE, lvec, liovcnt, UIO_FASTIOV,
-                                          iovstack_l, &iov_l);
-       else
-               rc = rw_copy_check_uvector(READ, lvec, liovcnt, UIO_FASTIOV,
-                                          iovstack_l, &iov_l);
-       if (rc <= 0)
+       rc = import_iovec(dir, lvec, liovcnt, UIO_FASTIOV, &iov_l, &iter);
+       if (rc < 0)
+               return rc;
+       if (!iov_iter_count(&iter))
                goto free_iovecs;
 
-       iov_iter_init(&iter, vm_write ? WRITE : READ, iov_l, liovcnt, rc);
-
        rc = rw_copy_check_uvector(CHECK_IOVEC_ONLY, rvec, riovcnt, UIO_FASTIOV,
                                   iovstack_r, &iov_r);
        if (rc <= 0)
@@ -283,8 +279,7 @@ static ssize_t process_vm_rw(pid_t pid,
 free_iovecs:
        if (iov_r != iovstack_r)
                kfree(iov_r);
-       if (iov_l != iovstack_l)
-               kfree(iov_l);
+       kfree(iov_l);
 
        return rc;
 }
@@ -320,21 +315,16 @@ compat_process_vm_rw(compat_pid_t pid,
        struct iovec *iov_r = iovstack_r;
        struct iov_iter iter;
        ssize_t rc = -EFAULT;
+       int dir = vm_write ? WRITE : READ;
 
        if (flags != 0)
                return -EINVAL;
 
-       if (vm_write)
-               rc = compat_rw_copy_check_uvector(WRITE, lvec, liovcnt,
-                                                 UIO_FASTIOV, iovstack_l,
-                                                 &iov_l);
-       else
-               rc = compat_rw_copy_check_uvector(READ, lvec, liovcnt,
-                                                 UIO_FASTIOV, iovstack_l,
-                                                 &iov_l);
-       if (rc <= 0)
+       rc = compat_import_iovec(dir, lvec, liovcnt, UIO_FASTIOV, &iov_l, &iter);
+       if (rc < 0)
+               return rc;
+       if (!iov_iter_count(&iter))
                goto free_iovecs;
-       iov_iter_init(&iter, vm_write ? WRITE : READ, iov_l, liovcnt, rc);
        rc = compat_rw_copy_check_uvector(CHECK_IOVEC_ONLY, rvec, riovcnt,
                                          UIO_FASTIOV, iovstack_r,
                                          &iov_r);
@@ -346,8 +336,7 @@ compat_process_vm_rw(compat_pid_t pid,
 free_iovecs:
        if (iov_r != iovstack_r)
                kfree(iov_r);
-       if (iov_l != iovstack_l)
-               kfree(iov_l);
+       kfree(iov_l);
        return rc;
 }
 
index cf2d0ca010bc52efd5ea86c7f6ba760a5c3ef286..80b360c7bcd1696a77cf74f44b334ce53d367688 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/mm.h>
 #include <linux/export.h>
 #include <linux/swap.h>
-#include <linux/aio.h>
+#include <linux/uio.h>
 
 static struct vfsmount *shm_mnt;
 
index c4b89eaf4c96416eca9e0e8817628525b5c44a9a..7eb38dd1cefa2f988be6297c1b75b12369e05827 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -857,6 +857,11 @@ static inline void *____cache_alloc_node(struct kmem_cache *cachep,
        return NULL;
 }
 
+static inline gfp_t gfp_exact_node(gfp_t flags)
+{
+       return flags;
+}
+
 #else  /* CONFIG_NUMA */
 
 static void *____cache_alloc_node(struct kmem_cache *, gfp_t, int);
@@ -1023,6 +1028,15 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
 
        return __cache_free_alien(cachep, objp, node, page_node);
 }
+
+/*
+ * Construct gfp mask to allocate from a specific node but do not invoke reclaim
+ * or warn about failures.
+ */
+static inline gfp_t gfp_exact_node(gfp_t flags)
+{
+       return (flags | __GFP_THISNODE | __GFP_NOWARN) & ~__GFP_WAIT;
+}
 #endif
 
 /*
@@ -2825,7 +2839,7 @@ alloc_done:
        if (unlikely(!ac->avail)) {
                int x;
 force_grow:
-               x = cache_grow(cachep, flags | GFP_THISNODE, node, NULL);
+               x = cache_grow(cachep, gfp_exact_node(flags), node, NULL);
 
                /* cache_grow can reenable interrupts, then ac could change. */
                ac = cpu_cache_get(cachep);
@@ -3019,7 +3033,7 @@ retry:
                        get_node(cache, nid) &&
                        get_node(cache, nid)->free_objects) {
                                obj = ____cache_alloc_node(cache,
-                                       flags | GFP_THISNODE, nid);
+                                       gfp_exact_node(flags), nid);
                                if (obj)
                                        break;
                }
@@ -3047,7 +3061,7 @@ retry:
                        nid = page_to_nid(page);
                        if (cache_grow(cache, flags, nid, page)) {
                                obj = ____cache_alloc_node(cache,
-                                       flags | GFP_THISNODE, nid);
+                                       gfp_exact_node(flags), nid);
                                if (!obj)
                                        /*
                                         * Another processor may allocate the
@@ -3118,7 +3132,7 @@ retry:
 
 must_grow:
        spin_unlock(&n->list_lock);
-       x = cache_grow(cachep, flags | GFP_THISNODE, nodeid, NULL);
+       x = cache_grow(cachep, gfp_exact_node(flags), nodeid, NULL);
        if (x)
                goto retry;
 
index 94a7fede6d4878942c3454afbac59210305d7dfb..4765f65019c733a558b2cb6e5063db50e8dcf5ca 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -532,7 +532,7 @@ int __kmem_cache_create(struct kmem_cache *c, unsigned long flags)
        return 0;
 }
 
-void *slob_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
+static void *slob_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
 {
        void *b;
 
@@ -558,7 +558,6 @@ void *slob_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
        kmemleak_alloc_recursive(b, c->size, 1, c->flags, flags);
        return b;
 }
-EXPORT_SYMBOL(slob_alloc_node);
 
 void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
index 82c473780c9188ecf7bfc393703f47793a2fbfe9..0fdd6c1e1f82cf84dc909872e5b6ee3368dee7e4 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -374,7 +374,7 @@ static inline bool __cmpxchg_double_slab(struct kmem_cache *s, struct page *page
                if (cmpxchg_double(&page->freelist, &page->counters,
                                   freelist_old, counters_old,
                                   freelist_new, counters_new))
-                       return 1;
+                       return true;
        } else
 #endif
        {
@@ -384,7 +384,7 @@ static inline bool __cmpxchg_double_slab(struct kmem_cache *s, struct page *page
                        page->freelist = freelist_new;
                        set_page_slub_counters(page, counters_new);
                        slab_unlock(page);
-                       return 1;
+                       return true;
                }
                slab_unlock(page);
        }
@@ -396,7 +396,7 @@ static inline bool __cmpxchg_double_slab(struct kmem_cache *s, struct page *page
        pr_info("%s %s: cmpxchg double redo ", n, s->name);
 #endif
 
-       return 0;
+       return false;
 }
 
 static inline bool cmpxchg_double_slab(struct kmem_cache *s, struct page *page,
@@ -410,7 +410,7 @@ static inline bool cmpxchg_double_slab(struct kmem_cache *s, struct page *page,
                if (cmpxchg_double(&page->freelist, &page->counters,
                                   freelist_old, counters_old,
                                   freelist_new, counters_new))
-                       return 1;
+                       return true;
        } else
 #endif
        {
@@ -424,7 +424,7 @@ static inline bool cmpxchg_double_slab(struct kmem_cache *s, struct page *page,
                        set_page_slub_counters(page, counters_new);
                        slab_unlock(page);
                        local_irq_restore(flags);
-                       return 1;
+                       return true;
                }
                slab_unlock(page);
                local_irq_restore(flags);
@@ -437,7 +437,7 @@ static inline bool cmpxchg_double_slab(struct kmem_cache *s, struct page *page,
        pr_info("%s %s: cmpxchg double redo ", n, s->name);
 #endif
 
-       return 0;
+       return false;
 }
 
 #ifdef CONFIG_SLUB_DEBUG
@@ -1137,15 +1137,6 @@ static int __init setup_slub_debug(char *str)
                 */
                goto check_slabs;
 
-       if (tolower(*str) == 'o') {
-               /*
-                * Avoid enabling debugging on caches if its minimum order
-                * would increase as a result.
-                */
-               disable_higher_order_debug = 1;
-               goto out;
-       }
-
        slub_debug = 0;
        if (*str == '-')
                /*
@@ -1176,6 +1167,13 @@ static int __init setup_slub_debug(char *str)
                case 'a':
                        slub_debug |= SLAB_FAILSLAB;
                        break;
+               case 'o':
+                       /*
+                        * Avoid enabling debugging on caches if its minimum
+                        * order would increase as a result.
+                        */
+                       disable_higher_order_debug = 1;
+                       break;
                default:
                        pr_err("slub_debug option '%c' unknown. skipped\n",
                               *str);
index ddec5a5966d74a90c1e88b53d260e119b0a5f097..7a9d8a3cb143fce1268f9e9a6e3af8576a0986cc 100644 (file)
@@ -92,35 +92,6 @@ void do_invalidatepage(struct page *page, unsigned int offset,
                (*invalidatepage)(page, offset, length);
 }
 
-/*
- * This cancels just the dirty bit on the kernel page itself, it
- * does NOT actually remove dirty bits on any mmap's that may be
- * around. It also leaves the page tagged dirty, so any sync
- * activity will still find it on the dirty lists, and in particular,
- * clear_page_dirty_for_io() will still look at the dirty bits in
- * the VM.
- *
- * Doing this should *normally* only ever be done when a page
- * is truncated, and is not actually mapped anywhere at all. However,
- * fs/buffer.c does this when it notices that somebody has cleaned
- * out all the buffers on a page without actually doing it through
- * the VM. Can you say "ext3 is horribly ugly"? Tought you could.
- */
-void cancel_dirty_page(struct page *page, unsigned int account_size)
-{
-       if (TestClearPageDirty(page)) {
-               struct address_space *mapping = page->mapping;
-               if (mapping && mapping_cap_account_dirty(mapping)) {
-                       dec_zone_page_state(page, NR_FILE_DIRTY);
-                       dec_bdi_stat(inode_to_bdi(mapping->host),
-                                       BDI_RECLAIMABLE);
-                       if (account_size)
-                               task_io_account_cancelled_write(account_size);
-               }
-       }
-}
-EXPORT_SYMBOL(cancel_dirty_page);
-
 /*
  * If truncate cannot remove the fs-private metadata from the page, the page
  * becomes orphaned.  It will be left on the LRU and may even be mapped into
@@ -140,7 +111,13 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
        if (page_has_private(page))
                do_invalidatepage(page, 0, PAGE_CACHE_SIZE);
 
-       cancel_dirty_page(page, PAGE_CACHE_SIZE);
+       /*
+        * Some filesystems seem to re-dirty the page even after
+        * the VM has canceled the dirty bit (eg ext3 journaling).
+        * Hence dirty accounting check is placed after invalidation.
+        */
+       if (TestClearPageDirty(page))
+               account_page_cleaned(page, mapping);
 
        ClearPageMappedToDisk(page);
        delete_from_page_cache(page);
index 49abccf29a29f65c4748a6decec00c27fec23c6d..a5bbdd3b5d6782b3bdb013d0b9698723639d1e78 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/atomic.h>
 #include <linux/compiler.h>
 #include <linux/llist.h>
+#include <linux/bitops.h>
 
 #include <asm/uaccess.h>
 #include <asm/tlbflush.h>
@@ -74,6 +75,8 @@ static void vunmap_pmd_range(pud_t *pud, unsigned long addr, unsigned long end)
        pmd = pmd_offset(pud, addr);
        do {
                next = pmd_addr_end(addr, end);
+               if (pmd_clear_huge(pmd))
+                       continue;
                if (pmd_none_or_clear_bad(pmd))
                        continue;
                vunmap_pte_range(pmd, addr, next);
@@ -88,6 +91,8 @@ static void vunmap_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end)
        pud = pud_offset(pgd, addr);
        do {
                next = pud_addr_end(addr, end);
+               if (pud_clear_huge(pud))
+                       continue;
                if (pud_none_or_clear_bad(pud))
                        continue;
                vunmap_pmd_range(pud, addr, next);
@@ -1314,7 +1319,8 @@ static struct vm_struct *__get_vm_area_node(unsigned long size,
 
        BUG_ON(in_interrupt());
        if (flags & VM_IOREMAP)
-               align = 1ul << clamp(fls(size), PAGE_SHIFT, IOREMAP_MAX_ORDER);
+               align = 1ul << clamp_t(int, fls_long(size),
+                                      PAGE_SHIFT, IOREMAP_MAX_ORDER);
 
        size = PAGE_ALIGN(size);
        if (unlikely(!size))
index 5bdd300db0f717febcca93355f546cd25a215442..2df34eb5d65f4c8a9b190fe7eea6f62bfae0a484 100644 (file)
@@ -272,7 +272,7 @@ static int parse_qos(const char *buff)
        qos.rxtp.max_pcr = rx_pcr;
        qos.rxtp.max_sdu = rx_sdu;
        qos.aal = ATM_AAL5;
-       dprintk("parse_qos(): setting qos paramameters to tx=%d,%d rx=%d,%d\n",
+       dprintk("parse_qos(): setting qos parameters to tx=%d,%d rx=%d,%d\n",
                qos.txtp.max_pcr, qos.txtp.max_sdu,
                qos.rxtp.max_pcr, qos.rxtp.max_sdu);
 
index 6b3f54ed65ba6fc4ff392877f662ef5dddeb8939..a9f4ae45b7fb856295a30a87a6c3701933d2f3f2 100644 (file)
@@ -484,7 +484,7 @@ static int ceph_tcp_connect(struct ceph_connection *con)
                               IPPROTO_TCP, &sock);
        if (ret)
                return ret;
-       sock->sk->sk_allocation = GFP_NOFS | __GFP_MEMALLOC;
+       sock->sk->sk_allocation = GFP_NOFS;
 
 #ifdef CONFIG_LOCKDEP
        lockdep_set_class(&sock->sk->sk_lock, &socket_class);
@@ -520,8 +520,6 @@ static int ceph_tcp_connect(struct ceph_connection *con)
                               ret);
        }
 
-       sk_set_memalloc(sock->sk);
-
        con->sock = sock;
        return 0;
 }
@@ -2808,11 +2806,8 @@ static void con_work(struct work_struct *work)
 {
        struct ceph_connection *con = container_of(work, struct ceph_connection,
                                                   work.work);
-       unsigned long pflags = current->flags;
        bool fault;
 
-       current->flags |= PF_MEMALLOC;
-
        mutex_lock(&con->mutex);
        while (true) {
                int ret;
@@ -2866,8 +2861,6 @@ static void con_work(struct work_struct *work)
                con_fault_finish(con);
 
        con->ops->put(con);
-
-       tsk_restore_flags(current, pflags, PF_MEMALLOC);
 }
 
 /*
index f027a708b7e01029574535e20f7461cfa4b84190..4a356b7c081b9f67c8c9bfaa17d7a9b17a4bcdc4 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/stddef.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
-#include <linux/aio.h>
 #include <linux/kernel.h>
 #include <linux/export.h>
 #include <linux/spinlock.h>
index 386e45d8a95818ba4a447b764288d935b9476638..edfe0c170a1c247c6285e5c5413a2150acf0b9d0 100644 (file)
@@ -8,6 +8,7 @@
 #include "debug.h"
 #define CREATE_TRACE_POINTS
 #include "trace.h"
+#include "trace_msg.h"
 
 #ifdef CONFIG_MAC80211_MESSAGE_TRACING
 void __sdata_info(const char *fmt, ...)
index 263a9561eb2669e636cffd02fb0acc304fede568..755a5388dbcaaf0a4c9d855801b60e18800a2c4f 100644 (file)
@@ -2312,44 +2312,6 @@ TRACE_EVENT(drv_tdls_recv_channel_switch,
        )
 );
 
-#ifdef CONFIG_MAC80211_MESSAGE_TRACING
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM mac80211_msg
-
-#define MAX_MSG_LEN    100
-
-DECLARE_EVENT_CLASS(mac80211_msg_event,
-       TP_PROTO(struct va_format *vaf),
-
-       TP_ARGS(vaf),
-
-       TP_STRUCT__entry(
-               __dynamic_array(char, msg, MAX_MSG_LEN)
-       ),
-
-       TP_fast_assign(
-               WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
-                                      MAX_MSG_LEN, vaf->fmt,
-                                      *vaf->va) >= MAX_MSG_LEN);
-       ),
-
-       TP_printk("%s", __get_str(msg))
-);
-
-DEFINE_EVENT(mac80211_msg_event, mac80211_info,
-       TP_PROTO(struct va_format *vaf),
-       TP_ARGS(vaf)
-);
-DEFINE_EVENT(mac80211_msg_event, mac80211_dbg,
-       TP_PROTO(struct va_format *vaf),
-       TP_ARGS(vaf)
-);
-DEFINE_EVENT(mac80211_msg_event, mac80211_err,
-       TP_PROTO(struct va_format *vaf),
-       TP_ARGS(vaf)
-);
-#endif
-
 #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH
diff --git a/net/mac80211/trace_msg.h b/net/mac80211/trace_msg.h
new file mode 100644 (file)
index 0000000..768f7c2
--- /dev/null
@@ -0,0 +1,53 @@
+#ifdef CONFIG_MAC80211_MESSAGE_TRACING
+
+#if !defined(__MAC80211_MSG_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#define __MAC80211_MSG_DRIVER_TRACE
+
+#include <linux/tracepoint.h>
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mac80211_msg
+
+#define MAX_MSG_LEN    100
+
+DECLARE_EVENT_CLASS(mac80211_msg_event,
+       TP_PROTO(struct va_format *vaf),
+
+       TP_ARGS(vaf),
+
+       TP_STRUCT__entry(
+               __dynamic_array(char, msg, MAX_MSG_LEN)
+       ),
+
+       TP_fast_assign(
+               WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+                                      MAX_MSG_LEN, vaf->fmt,
+                                      *vaf->va) >= MAX_MSG_LEN);
+       ),
+
+       TP_printk("%s", __get_str(msg))
+);
+
+DEFINE_EVENT(mac80211_msg_event, mac80211_info,
+       TP_PROTO(struct va_format *vaf),
+       TP_ARGS(vaf)
+);
+DEFINE_EVENT(mac80211_msg_event, mac80211_dbg,
+       TP_PROTO(struct va_format *vaf),
+       TP_ARGS(vaf)
+);
+DEFINE_EVENT(mac80211_msg_event, mac80211_err,
+       TP_PROTO(struct va_format *vaf),
+       TP_ARGS(vaf)
+);
+#endif /* !__MAC80211_MSG_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace_msg
+#include <trace/define_trace.h>
+
+#endif
index 50ec42f170a06713e086d66abb2ea0d1aa998d74..2dacc7b5af23a14b827785fdbc3eaf5bd6a26883 100644 (file)
@@ -100,7 +100,9 @@ void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags,
 
                                new_stats =
                                        kmem_cache_alloc_node(flow_stats_cache,
-                                                             GFP_THISNODE |
+                                                             GFP_NOWAIT |
+                                                             __GFP_THISNODE |
+                                                             __GFP_NOWARN |
                                                              __GFP_NOMEMALLOC,
                                                              node);
                                if (likely(new_stats)) {
index 245330ca0015c2fd2548ead861d379714151c901..1dbff3e604378716ac73a8ef4b916a3192642e7e 100644 (file)
@@ -633,8 +633,7 @@ static int do_sock_sendmsg(struct socket *sock, struct msghdr *msg,
        init_sync_kiocb(&iocb, NULL);
        ret = nosec ? __sock_sendmsg_nosec(&iocb, sock, msg, size) :
                      __sock_sendmsg(&iocb, sock, msg, size);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&iocb);
+       BUG_ON(ret == -EIOCBQUEUED);
        return ret;
 }
 
@@ -766,8 +765,7 @@ int sock_recvmsg(struct socket *sock, struct msghdr *msg,
 
        init_sync_kiocb(&iocb, NULL);
        ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&iocb);
+       BUG_ON(ret == -EIOCBQUEUED);
        return ret;
 }
 EXPORT_SYMBOL(sock_recvmsg);
@@ -780,8 +778,7 @@ static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
 
        init_sync_kiocb(&iocb, NULL);
        ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&iocb);
+       BUG_ON(ret == -EIOCBQUEUED);
        return ret;
 }
 
@@ -858,11 +855,11 @@ static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
        if (iocb->ki_pos != 0)
                return -ESPIPE;
 
-       if (iocb->ki_nbytes == 0)       /* Match SYS5 behaviour */
+       if (!iov_iter_count(to))        /* Match SYS5 behaviour */
                return 0;
 
        res = __sock_recvmsg(iocb, sock, &msg,
-                            iocb->ki_nbytes, msg.msg_flags);
+                            iov_iter_count(to), msg.msg_flags);
        *to = msg.msg_iter;
        return res;
 }
@@ -883,7 +880,7 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (sock->type == SOCK_SEQPACKET)
                msg.msg_flags |= MSG_EOR;
 
-       res = __sock_sendmsg(iocb, sock, &msg, iocb->ki_nbytes);
+       res = __sock_sendmsg(iocb, sock, &msg, iov_iter_count(from));
        *from = msg.msg_iter;
        return res;
 }
index 124676c1378089e807c3d330da1bd35a465f49ad..e28909fddd30a3c273e4cfcbf5e600d005e916b2 100644 (file)
@@ -1136,7 +1136,7 @@ rpcrdma_init_fmrs(struct rpcrdma_ia *ia, struct rpcrdma_buffer *buf)
        int i, rc;
 
        i = (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS;
-       dprintk("RPC:       %s: initalizing %d FMRs\n", __func__, i);
+       dprintk("RPC:       %s: initializing %d FMRs\n", __func__, i);
 
        while (i--) {
                r = kzalloc(sizeof(*r), GFP_KERNEL);
@@ -1169,7 +1169,7 @@ rpcrdma_init_frmrs(struct rpcrdma_ia *ia, struct rpcrdma_buffer *buf)
        int i, rc;
 
        i = (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS;
-       dprintk("RPC:       %s: initalizing %d FRMRs\n", __func__, i);
+       dprintk("RPC:       %s: initializing %d FRMRs\n", __func__, i);
 
        while (i--) {
                r = kzalloc(sizeof(*r), GFP_KERNEL);
index b5b3600dcdf5d004e01c1a558011519adfc386ba..fe98fb226e6e1af21dae6feb5684ebc30faffb50 100644 (file)
@@ -6,23 +6,39 @@ hostprogs-y := test_verifier test_maps
 hostprogs-y += sock_example
 hostprogs-y += sockex1
 hostprogs-y += sockex2
+hostprogs-y += tracex1
+hostprogs-y += tracex2
+hostprogs-y += tracex3
+hostprogs-y += tracex4
 
 test_verifier-objs := test_verifier.o libbpf.o
 test_maps-objs := test_maps.o libbpf.o
 sock_example-objs := sock_example.o libbpf.o
 sockex1-objs := bpf_load.o libbpf.o sockex1_user.o
 sockex2-objs := bpf_load.o libbpf.o sockex2_user.o
+tracex1-objs := bpf_load.o libbpf.o tracex1_user.o
+tracex2-objs := bpf_load.o libbpf.o tracex2_user.o
+tracex3-objs := bpf_load.o libbpf.o tracex3_user.o
+tracex4-objs := bpf_load.o libbpf.o tracex4_user.o
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
 always += sockex1_kern.o
 always += sockex2_kern.o
+always += tracex1_kern.o
+always += tracex2_kern.o
+always += tracex3_kern.o
+always += tracex4_kern.o
 
 HOSTCFLAGS += -I$(objtree)/usr/include
 
 HOSTCFLAGS_bpf_load.o += -I$(objtree)/usr/include -Wno-unused-variable
 HOSTLOADLIBES_sockex1 += -lelf
 HOSTLOADLIBES_sockex2 += -lelf
+HOSTLOADLIBES_tracex1 += -lelf
+HOSTLOADLIBES_tracex2 += -lelf
+HOSTLOADLIBES_tracex3 += -lelf
+HOSTLOADLIBES_tracex4 += -lelf -lrt
 
 # point this to your LLVM backend with bpf support
 LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc
index ca0333146006af20352ec704d5049085db975206..1c872bcf5a806d96e311a0db02202e58fa152efb 100644 (file)
@@ -15,6 +15,12 @@ static int (*bpf_map_update_elem)(void *map, void *key, void *value,
        (void *) BPF_FUNC_map_update_elem;
 static int (*bpf_map_delete_elem)(void *map, void *key) =
        (void *) BPF_FUNC_map_delete_elem;
+static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr) =
+       (void *) BPF_FUNC_probe_read;
+static unsigned long long (*bpf_ktime_get_ns)(void) =
+       (void *) BPF_FUNC_ktime_get_ns;
+static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
+       (void *) BPF_FUNC_trace_printk;
 
 /* llvm builtin functions that eBPF C program may use to
  * emit BPF_LD_ABS and BPF_LD_IND instructions
index 1831d236382b5e06636245dbc87ed819f227e910..38dac5a53b518bc71743b32a06ad39391c60066b 100644 (file)
@@ -8,29 +8,70 @@
 #include <unistd.h>
 #include <string.h>
 #include <stdbool.h>
+#include <stdlib.h>
 #include <linux/bpf.h>
 #include <linux/filter.h>
+#include <linux/perf_event.h>
+#include <sys/syscall.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <poll.h>
 #include "libbpf.h"
 #include "bpf_helpers.h"
 #include "bpf_load.h"
 
+#define DEBUGFS "/sys/kernel/debug/tracing/"
+
 static char license[128];
+static int kern_version;
 static bool processed_sec[128];
 int map_fd[MAX_MAPS];
 int prog_fd[MAX_PROGS];
+int event_fd[MAX_PROGS];
 int prog_cnt;
 
 static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
 {
-       int fd;
        bool is_socket = strncmp(event, "socket", 6) == 0;
-
-       if (!is_socket)
-               /* tracing events tbd */
+       bool is_kprobe = strncmp(event, "kprobe/", 7) == 0;
+       bool is_kretprobe = strncmp(event, "kretprobe/", 10) == 0;
+       enum bpf_prog_type prog_type;
+       char buf[256];
+       int fd, efd, err, id;
+       struct perf_event_attr attr = {};
+
+       attr.type = PERF_TYPE_TRACEPOINT;
+       attr.sample_type = PERF_SAMPLE_RAW;
+       attr.sample_period = 1;
+       attr.wakeup_events = 1;
+
+       if (is_socket) {
+               prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
+       } else if (is_kprobe || is_kretprobe) {
+               prog_type = BPF_PROG_TYPE_KPROBE;
+       } else {
+               printf("Unknown event '%s'\n", event);
                return -1;
+       }
+
+       if (is_kprobe || is_kretprobe) {
+               if (is_kprobe)
+                       event += 7;
+               else
+                       event += 10;
+
+               snprintf(buf, sizeof(buf),
+                        "echo '%c:%s %s' >> /sys/kernel/debug/tracing/kprobe_events",
+                        is_kprobe ? 'p' : 'r', event, event);
+               err = system(buf);
+               if (err < 0) {
+                       printf("failed to create kprobe '%s' error '%s'\n",
+                              event, strerror(errno));
+                       return -1;
+               }
+       }
 
-       fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER,
-                          prog, size, license);
+       fd = bpf_prog_load(prog_type, prog, size, license, kern_version);
 
        if (fd < 0) {
                printf("bpf_prog_load() err=%d\n%s", errno, bpf_log_buf);
@@ -39,6 +80,41 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
 
        prog_fd[prog_cnt++] = fd;
 
+       if (is_socket)
+               return 0;
+
+       strcpy(buf, DEBUGFS);
+       strcat(buf, "events/kprobes/");
+       strcat(buf, event);
+       strcat(buf, "/id");
+
+       efd = open(buf, O_RDONLY, 0);
+       if (efd < 0) {
+               printf("failed to open event %s\n", event);
+               return -1;
+       }
+
+       err = read(efd, buf, sizeof(buf));
+       if (err < 0 || err >= sizeof(buf)) {
+               printf("read from '%s' failed '%s'\n", event, strerror(errno));
+               return -1;
+       }
+
+       close(efd);
+
+       buf[err] = 0;
+       id = atoi(buf);
+       attr.config = id;
+
+       efd = perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0);
+       if (efd < 0) {
+               printf("event %d fd %d err %s\n", id, efd, strerror(errno));
+               return -1;
+       }
+       event_fd[prog_cnt - 1] = efd;
+       ioctl(efd, PERF_EVENT_IOC_ENABLE, 0);
+       ioctl(efd, PERF_EVENT_IOC_SET_BPF, fd);
+
        return 0;
 }
 
@@ -135,6 +211,9 @@ int load_bpf_file(char *path)
        if (gelf_getehdr(elf, &ehdr) != &ehdr)
                return 1;
 
+       /* clear all kprobes */
+       i = system("echo \"\" > /sys/kernel/debug/tracing/kprobe_events");
+
        /* scan over all elf sections to get license and map info */
        for (i = 1; i < ehdr.e_shnum; i++) {
 
@@ -149,6 +228,14 @@ int load_bpf_file(char *path)
                if (strcmp(shname, "license") == 0) {
                        processed_sec[i] = true;
                        memcpy(license, data->d_buf, data->d_size);
+               } else if (strcmp(shname, "version") == 0) {
+                       processed_sec[i] = true;
+                       if (data->d_size != sizeof(int)) {
+                               printf("invalid size of version section %zd\n",
+                                      data->d_size);
+                               return 1;
+                       }
+                       memcpy(&kern_version, data->d_buf, sizeof(int));
                } else if (strcmp(shname, "maps") == 0) {
                        processed_sec[i] = true;
                        if (load_maps(data->d_buf, data->d_size))
@@ -178,7 +265,8 @@ int load_bpf_file(char *path)
                        if (parse_relo_and_apply(data, symbols, &shdr, insns))
                                continue;
 
-                       if (memcmp(shname_prog, "events/", 7) == 0 ||
+                       if (memcmp(shname_prog, "kprobe/", 7) == 0 ||
+                           memcmp(shname_prog, "kretprobe/", 10) == 0 ||
                            memcmp(shname_prog, "socket", 6) == 0)
                                load_and_attach(shname_prog, insns, data_prog->d_size);
                }
@@ -193,7 +281,8 @@ int load_bpf_file(char *path)
                if (get_sec(elf, i, &ehdr, &shname, &shdr, &data))
                        continue;
 
-               if (memcmp(shname, "events/", 7) == 0 ||
+               if (memcmp(shname, "kprobe/", 7) == 0 ||
+                   memcmp(shname, "kretprobe/", 10) == 0 ||
                    memcmp(shname, "socket", 6) == 0)
                        load_and_attach(shname, data->d_buf, data->d_size);
        }
@@ -201,3 +290,23 @@ int load_bpf_file(char *path)
        close(fd);
        return 0;
 }
+
+void read_trace_pipe(void)
+{
+       int trace_fd;
+
+       trace_fd = open(DEBUGFS "trace_pipe", O_RDONLY, 0);
+       if (trace_fd < 0)
+               return;
+
+       while (1) {
+               static char buf[4096];
+               ssize_t sz;
+
+               sz = read(trace_fd, buf, sizeof(buf));
+               if (sz > 0) {
+                       buf[sz] = 0;
+                       puts(buf);
+               }
+       }
+}
index 27789a34f5e68e93c60b8e2e3226313e265d7464..cbd7c2b532b9a1a8e842c863f91b80d9bc79f42e 100644 (file)
@@ -6,6 +6,7 @@
 
 extern int map_fd[MAX_MAPS];
 extern int prog_fd[MAX_PROGS];
+extern int event_fd[MAX_PROGS];
 
 /* parses elf file compiled by llvm .c->.o
  * . parses 'maps' section and creates maps via BPF syscall
@@ -21,4 +22,6 @@ extern int prog_fd[MAX_PROGS];
  */
 int load_bpf_file(char *path);
 
+void read_trace_pipe(void);
+
 #endif
index 46d50b7ddf796f8c35fbeef48fa6aa8b6871fedc..7e1efa7e2ed7f5b761c7c9bf7ab8a7b2c3c3ab27 100644 (file)
@@ -81,7 +81,7 @@ char bpf_log_buf[LOG_BUF_SIZE];
 
 int bpf_prog_load(enum bpf_prog_type prog_type,
                  const struct bpf_insn *insns, int prog_len,
-                 const char *license)
+                 const char *license, int kern_version)
 {
        union bpf_attr attr = {
                .prog_type = prog_type,
@@ -93,6 +93,11 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
                .log_level = 1,
        };
 
+       /* assign one field outside of struct init to make sure any
+        * padding is zero initialized
+        */
+       attr.kern_version = kern_version;
+
        bpf_log_buf[0] = 0;
 
        return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
@@ -121,3 +126,10 @@ int open_raw_sock(const char *name)
 
        return sock;
 }
+
+int perf_event_open(struct perf_event_attr *attr, int pid, int cpu,
+                   int group_fd, unsigned long flags)
+{
+       return syscall(__NR_perf_event_open, attr, pid, cpu,
+                      group_fd, flags);
+}
index 58c5fe1bdba1f08c278a750e69a7a32f706f819c..ac7b09672b4693aa1d808feba6461a17d2db4b12 100644 (file)
@@ -13,7 +13,7 @@ int bpf_get_next_key(int fd, void *key, void *next_key);
 
 int bpf_prog_load(enum bpf_prog_type prog_type,
                  const struct bpf_insn *insns, int insn_len,
-                 const char *license);
+                 const char *license, int kern_version);
 
 #define LOG_BUF_SIZE 65536
 extern char bpf_log_buf[LOG_BUF_SIZE];
@@ -182,4 +182,7 @@ extern char bpf_log_buf[LOG_BUF_SIZE];
 /* create RAW socket and bind to interface 'name' */
 int open_raw_sock(const char *name);
 
+struct perf_event_attr;
+int perf_event_open(struct perf_event_attr *attr, int pid, int cpu,
+                   int group_fd, unsigned long flags);
 #endif
index c8ad0404416f5da95e318cf4580255abc5174ee0..a0ce251c53900e08617740633cc726b045c8fcc1 100644 (file)
@@ -56,7 +56,7 @@ static int test_sock(void)
        };
 
        prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog, sizeof(prog),
-                               "GPL");
+                               "GPL", 0);
        if (prog_fd < 0) {
                printf("failed to load prog '%s'\n", strerror(errno));
                goto cleanup;
index b96175e903639a2fe2c9b1d4777df0aaa63d6e6e..740ce97cda5e6a19ab86b3370d98e6e9c7e5dc39 100644 (file)
@@ -689,7 +689,7 @@ static int test(void)
 
                prog_fd = bpf_prog_load(BPF_PROG_TYPE_UNSPEC, prog,
                                        prog_len * sizeof(struct bpf_insn),
-                                       "GPL");
+                                       "GPL", 0);
 
                if (tests[i].result == ACCEPT) {
                        if (prog_fd < 0) {
diff --git a/samples/bpf/tracex1_kern.c b/samples/bpf/tracex1_kern.c
new file mode 100644 (file)
index 0000000..3162046
--- /dev/null
@@ -0,0 +1,50 @@
+/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
+ *
+ * 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.
+ */
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <uapi/linux/bpf.h>
+#include <linux/version.h>
+#include "bpf_helpers.h"
+
+#define _(P) ({typeof(P) val = 0; bpf_probe_read(&val, sizeof(val), &P); val;})
+
+/* kprobe is NOT a stable ABI
+ * kernel functions can be removed, renamed or completely change semantics.
+ * Number of arguments and their positions can change, etc.
+ * In such case this bpf+kprobe example will no longer be meaningful
+ */
+SEC("kprobe/__netif_receive_skb_core")
+int bpf_prog1(struct pt_regs *ctx)
+{
+       /* attaches to kprobe netif_receive_skb,
+        * looks for packets on loobpack device and prints them
+        */
+       char devname[IFNAMSIZ] = {};
+       struct net_device *dev;
+       struct sk_buff *skb;
+       int len;
+
+       /* non-portable! works for the given kernel only */
+       skb = (struct sk_buff *) ctx->di;
+
+       dev = _(skb->dev);
+
+       len = _(skb->len);
+
+       bpf_probe_read(devname, sizeof(devname), dev->name);
+
+       if (devname[0] == 'l' && devname[1] == 'o') {
+               char fmt[] = "skb %p len %d\n";
+               /* using bpf_trace_printk() for DEBUG ONLY */
+               bpf_trace_printk(fmt, sizeof(fmt), skb, len);
+       }
+
+       return 0;
+}
+
+char _license[] SEC("license") = "GPL";
+u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/tracex1_user.c b/samples/bpf/tracex1_user.c
new file mode 100644 (file)
index 0000000..31a4818
--- /dev/null
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <linux/bpf.h>
+#include <unistd.h>
+#include "libbpf.h"
+#include "bpf_load.h"
+
+int main(int ac, char **argv)
+{
+       FILE *f;
+       char filename[256];
+
+       snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+
+       if (load_bpf_file(filename)) {
+               printf("%s", bpf_log_buf);
+               return 1;
+       }
+
+       f = popen("taskset 1 ping -c5 localhost", "r");
+       (void) f;
+
+       read_trace_pipe();
+
+       return 0;
+}
diff --git a/samples/bpf/tracex2_kern.c b/samples/bpf/tracex2_kern.c
new file mode 100644 (file)
index 0000000..19ec1cf
--- /dev/null
@@ -0,0 +1,86 @@
+/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
+ *
+ * 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.
+ */
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+#include <uapi/linux/bpf.h>
+#include "bpf_helpers.h"
+
+struct bpf_map_def SEC("maps") my_map = {
+       .type = BPF_MAP_TYPE_HASH,
+       .key_size = sizeof(long),
+       .value_size = sizeof(long),
+       .max_entries = 1024,
+};
+
+/* kprobe is NOT a stable ABI. If kernel internals change this bpf+kprobe
+ * example will no longer be meaningful
+ */
+SEC("kprobe/kfree_skb")
+int bpf_prog2(struct pt_regs *ctx)
+{
+       long loc = 0;
+       long init_val = 1;
+       long *value;
+
+       /* x64 specific: read ip of kfree_skb caller.
+        * non-portable version of __builtin_return_address(0)
+        */
+       bpf_probe_read(&loc, sizeof(loc), (void *)ctx->sp);
+
+       value = bpf_map_lookup_elem(&my_map, &loc);
+       if (value)
+               *value += 1;
+       else
+               bpf_map_update_elem(&my_map, &loc, &init_val, BPF_ANY);
+       return 0;
+}
+
+static unsigned int log2(unsigned int v)
+{
+       unsigned int r;
+       unsigned int shift;
+
+       r = (v > 0xFFFF) << 4; v >>= r;
+       shift = (v > 0xFF) << 3; v >>= shift; r |= shift;
+       shift = (v > 0xF) << 2; v >>= shift; r |= shift;
+       shift = (v > 0x3) << 1; v >>= shift; r |= shift;
+       r |= (v >> 1);
+       return r;
+}
+
+static unsigned int log2l(unsigned long v)
+{
+       unsigned int hi = v >> 32;
+       if (hi)
+               return log2(hi) + 32;
+       else
+               return log2(v);
+}
+
+struct bpf_map_def SEC("maps") my_hist_map = {
+       .type = BPF_MAP_TYPE_ARRAY,
+       .key_size = sizeof(u32),
+       .value_size = sizeof(long),
+       .max_entries = 64,
+};
+
+SEC("kprobe/sys_write")
+int bpf_prog3(struct pt_regs *ctx)
+{
+       long write_size = ctx->dx; /* arg3 */
+       long init_val = 1;
+       long *value;
+       u32 index = log2l(write_size);
+
+       value = bpf_map_lookup_elem(&my_hist_map, &index);
+       if (value)
+               __sync_fetch_and_add(value, 1);
+       return 0;
+}
+char _license[] SEC("license") = "GPL";
+u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/tracex2_user.c b/samples/bpf/tracex2_user.c
new file mode 100644 (file)
index 0000000..91b8d08
--- /dev/null
@@ -0,0 +1,95 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <linux/bpf.h>
+#include "libbpf.h"
+#include "bpf_load.h"
+
+#define MAX_INDEX      64
+#define MAX_STARS      38
+
+static void stars(char *str, long val, long max, int width)
+{
+       int i;
+
+       for (i = 0; i < (width * val / max) - 1 && i < width - 1; i++)
+               str[i] = '*';
+       if (val > max)
+               str[i - 1] = '+';
+       str[i] = '\0';
+}
+
+static void print_hist(int fd)
+{
+       int key;
+       long value;
+       long data[MAX_INDEX] = {};
+       char starstr[MAX_STARS];
+       int i;
+       int max_ind = -1;
+       long max_value = 0;
+
+       for (key = 0; key < MAX_INDEX; key++) {
+               bpf_lookup_elem(fd, &key, &value);
+               data[key] = value;
+               if (value && key > max_ind)
+                       max_ind = key;
+               if (value > max_value)
+                       max_value = value;
+       }
+
+       printf("           syscall write() stats\n");
+       printf("     byte_size       : count     distribution\n");
+       for (i = 1; i <= max_ind + 1; i++) {
+               stars(starstr, data[i - 1], max_value, MAX_STARS);
+               printf("%8ld -> %-8ld : %-8ld |%-*s|\n",
+                      (1l << i) >> 1, (1l << i) - 1, data[i - 1],
+                      MAX_STARS, starstr);
+       }
+}
+static void int_exit(int sig)
+{
+       print_hist(map_fd[1]);
+       exit(0);
+}
+
+int main(int ac, char **argv)
+{
+       char filename[256];
+       long key, next_key, value;
+       FILE *f;
+       int i;
+
+       snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+
+       signal(SIGINT, int_exit);
+
+       /* start 'ping' in the background to have some kfree_skb events */
+       f = popen("ping -c5 localhost", "r");
+       (void) f;
+
+       /* start 'dd' in the background to have plenty of 'write' syscalls */
+       f = popen("dd if=/dev/zero of=/dev/null count=5000000", "r");
+       (void) f;
+
+       if (load_bpf_file(filename)) {
+               printf("%s", bpf_log_buf);
+               return 1;
+       }
+
+       for (i = 0; i < 5; i++) {
+               key = 0;
+               while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) {
+                       bpf_lookup_elem(map_fd[0], &next_key, &value);
+                       printf("location 0x%lx count %ld\n", next_key, value);
+                       key = next_key;
+               }
+               if (key)
+                       printf("\n");
+               sleep(1);
+       }
+       print_hist(map_fd[1]);
+
+       return 0;
+}
diff --git a/samples/bpf/tracex3_kern.c b/samples/bpf/tracex3_kern.c
new file mode 100644 (file)
index 0000000..255ff27
--- /dev/null
@@ -0,0 +1,89 @@
+/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
+ *
+ * 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.
+ */
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+#include <uapi/linux/bpf.h>
+#include "bpf_helpers.h"
+
+struct bpf_map_def SEC("maps") my_map = {
+       .type = BPF_MAP_TYPE_HASH,
+       .key_size = sizeof(long),
+       .value_size = sizeof(u64),
+       .max_entries = 4096,
+};
+
+/* kprobe is NOT a stable ABI. If kernel internals change this bpf+kprobe
+ * example will no longer be meaningful
+ */
+SEC("kprobe/blk_mq_start_request")
+int bpf_prog1(struct pt_regs *ctx)
+{
+       long rq = ctx->di;
+       u64 val = bpf_ktime_get_ns();
+
+       bpf_map_update_elem(&my_map, &rq, &val, BPF_ANY);
+       return 0;
+}
+
+static unsigned int log2l(unsigned long long n)
+{
+#define S(k) if (n >= (1ull << k)) { i += k; n >>= k; }
+       int i = -(n == 0);
+       S(32); S(16); S(8); S(4); S(2); S(1);
+       return i;
+#undef S
+}
+
+#define SLOTS 100
+
+struct bpf_map_def SEC("maps") lat_map = {
+       .type = BPF_MAP_TYPE_ARRAY,
+       .key_size = sizeof(u32),
+       .value_size = sizeof(u64),
+       .max_entries = SLOTS,
+};
+
+SEC("kprobe/blk_update_request")
+int bpf_prog2(struct pt_regs *ctx)
+{
+       long rq = ctx->di;
+       u64 *value, l, base;
+       u32 index;
+
+       value = bpf_map_lookup_elem(&my_map, &rq);
+       if (!value)
+               return 0;
+
+       u64 cur_time = bpf_ktime_get_ns();
+       u64 delta = cur_time - *value;
+
+       bpf_map_delete_elem(&my_map, &rq);
+
+       /* the lines below are computing index = log10(delta)*10
+        * using integer arithmetic
+        * index = 29 ~ 1 usec
+        * index = 59 ~ 1 msec
+        * index = 89 ~ 1 sec
+        * index = 99 ~ 10sec or more
+        * log10(x)*10 = log2(x)*10/log2(10) = log2(x)*3
+        */
+       l = log2l(delta);
+       base = 1ll << l;
+       index = (l * 64 + (delta - base) * 64 / base) * 3 / 64;
+
+       if (index >= SLOTS)
+               index = SLOTS - 1;
+
+       value = bpf_map_lookup_elem(&lat_map, &index);
+       if (value)
+               __sync_fetch_and_add((long *)value, 1);
+
+       return 0;
+}
+char _license[] SEC("license") = "GPL";
+u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/tracex3_user.c b/samples/bpf/tracex3_user.c
new file mode 100644 (file)
index 0000000..0aaa933
--- /dev/null
@@ -0,0 +1,150 @@
+/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
+ *
+ * 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.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <string.h>
+#include <linux/bpf.h>
+#include "libbpf.h"
+#include "bpf_load.h"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
+
+#define SLOTS 100
+
+static void clear_stats(int fd)
+{
+       __u32 key;
+       __u64 value = 0;
+
+       for (key = 0; key < SLOTS; key++)
+               bpf_update_elem(fd, &key, &value, BPF_ANY);
+}
+
+const char *color[] = {
+       "\033[48;5;255m",
+       "\033[48;5;252m",
+       "\033[48;5;250m",
+       "\033[48;5;248m",
+       "\033[48;5;246m",
+       "\033[48;5;244m",
+       "\033[48;5;242m",
+       "\033[48;5;240m",
+       "\033[48;5;238m",
+       "\033[48;5;236m",
+       "\033[48;5;234m",
+       "\033[48;5;232m",
+};
+const int num_colors = ARRAY_SIZE(color);
+
+const char nocolor[] = "\033[00m";
+
+const char *sym[] = {
+       " ",
+       " ",
+       ".",
+       ".",
+       "*",
+       "*",
+       "o",
+       "o",
+       "O",
+       "O",
+       "#",
+       "#",
+};
+
+bool full_range = false;
+bool text_only = false;
+
+static void print_banner(void)
+{
+       if (full_range)
+               printf("|1ns     |10ns     |100ns    |1us      |10us     |100us"
+                      "    |1ms      |10ms     |100ms    |1s       |10s\n");
+       else
+               printf("|1us      |10us     |100us    |1ms      |10ms     "
+                      "|100ms    |1s       |10s\n");
+}
+
+static void print_hist(int fd)
+{
+       __u32 key;
+       __u64 value;
+       __u64 cnt[SLOTS];
+       __u64 max_cnt = 0;
+       __u64 total_events = 0;
+
+       for (key = 0; key < SLOTS; key++) {
+               value = 0;
+               bpf_lookup_elem(fd, &key, &value);
+               cnt[key] = value;
+               total_events += value;
+               if (value > max_cnt)
+                       max_cnt = value;
+       }
+       clear_stats(fd);
+       for (key = full_range ? 0 : 29; key < SLOTS; key++) {
+               int c = num_colors * cnt[key] / (max_cnt + 1);
+
+               if (text_only)
+                       printf("%s", sym[c]);
+               else
+                       printf("%s %s", color[c], nocolor);
+       }
+       printf(" # %lld\n", total_events);
+}
+
+int main(int ac, char **argv)
+{
+       char filename[256];
+       int i;
+
+       snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+
+       if (load_bpf_file(filename)) {
+               printf("%s", bpf_log_buf);
+               return 1;
+       }
+
+       for (i = 1; i < ac; i++) {
+               if (strcmp(argv[i], "-a") == 0) {
+                       full_range = true;
+               } else if (strcmp(argv[i], "-t") == 0) {
+                       text_only = true;
+               } else if (strcmp(argv[i], "-h") == 0) {
+                       printf("Usage:\n"
+                              "  -a display wider latency range\n"
+                              "  -t text only\n");
+                       return 1;
+               }
+       }
+
+       printf("  heatmap of IO latency\n");
+       if (text_only)
+               printf("  %s", sym[num_colors - 1]);
+       else
+               printf("  %s %s", color[num_colors - 1], nocolor);
+       printf(" - many events with this latency\n");
+
+       if (text_only)
+               printf("  %s", sym[0]);
+       else
+               printf("  %s %s", color[0], nocolor);
+       printf(" - few events\n");
+
+       for (i = 0; ; i++) {
+               if (i % 20 == 0)
+                       print_banner();
+               print_hist(map_fd[1]);
+               sleep(2);
+       }
+
+       return 0;
+}
diff --git a/samples/bpf/tracex4_kern.c b/samples/bpf/tracex4_kern.c
new file mode 100644 (file)
index 0000000..126b805
--- /dev/null
@@ -0,0 +1,54 @@
+/* Copyright (c) 2015 PLUMgrid, http://plumgrid.com
+ *
+ * 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.
+ */
+#include <linux/ptrace.h>
+#include <linux/version.h>
+#include <uapi/linux/bpf.h>
+#include "bpf_helpers.h"
+
+struct pair {
+       u64 val;
+       u64 ip;
+};
+
+struct bpf_map_def SEC("maps") my_map = {
+       .type = BPF_MAP_TYPE_HASH,
+       .key_size = sizeof(long),
+       .value_size = sizeof(struct pair),
+       .max_entries = 1000000,
+};
+
+/* kprobe is NOT a stable ABI. If kernel internals change this bpf+kprobe
+ * example will no longer be meaningful
+ */
+SEC("kprobe/kmem_cache_free")
+int bpf_prog1(struct pt_regs *ctx)
+{
+       long ptr = ctx->si;
+
+       bpf_map_delete_elem(&my_map, &ptr);
+       return 0;
+}
+
+SEC("kretprobe/kmem_cache_alloc_node")
+int bpf_prog2(struct pt_regs *ctx)
+{
+       long ptr = ctx->ax;
+       long ip = 0;
+
+       /* get ip address of kmem_cache_alloc_node() caller */
+       bpf_probe_read(&ip, sizeof(ip), (void *)(ctx->bp + sizeof(ip)));
+
+       struct pair v = {
+               .val = bpf_ktime_get_ns(),
+               .ip = ip,
+       };
+
+       bpf_map_update_elem(&my_map, &ptr, &v, BPF_ANY);
+       return 0;
+}
+char _license[] SEC("license") = "GPL";
+u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/tracex4_user.c b/samples/bpf/tracex4_user.c
new file mode 100644 (file)
index 0000000..bc4a3bd
--- /dev/null
@@ -0,0 +1,69 @@
+/* Copyright (c) 2015 PLUMgrid, http://plumgrid.com
+ *
+ * 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.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <string.h>
+#include <time.h>
+#include <linux/bpf.h>
+#include "libbpf.h"
+#include "bpf_load.h"
+
+struct pair {
+       long long val;
+       __u64 ip;
+};
+
+static __u64 time_get_ns(void)
+{
+       struct timespec ts;
+
+       clock_gettime(CLOCK_MONOTONIC, &ts);
+       return ts.tv_sec * 1000000000ull + ts.tv_nsec;
+}
+
+static void print_old_objects(int fd)
+{
+       long long val = time_get_ns();
+       __u64 key, next_key;
+       struct pair v;
+
+       key = write(1, "\e[1;1H\e[2J", 12); /* clear screen */
+
+       key = -1;
+       while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) {
+               bpf_lookup_elem(map_fd[0], &next_key, &v);
+               key = next_key;
+               if (val - v.val < 1000000000ll)
+                       /* object was allocated more then 1 sec ago */
+                       continue;
+               printf("obj 0x%llx is %2lldsec old was allocated at ip %llx\n",
+                      next_key, (val - v.val) / 1000000000ll, v.ip);
+       }
+}
+
+int main(int ac, char **argv)
+{
+       char filename[256];
+       int i;
+
+       snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+
+       if (load_bpf_file(filename)) {
+               printf("%s", bpf_log_buf);
+               return 1;
+       }
+
+       for (i = 0; ; i++) {
+               print_old_objects(map_fd[1]);
+               sleep(1);
+       }
+
+       return 0;
+}
index 382eeae77bd6437f30b2478a349a259e0434b444..a9ab96188fbe011ec3d3337d9dbd936023d0a3ec 100644 (file)
@@ -8,3 +8,5 @@ hostprogs-y := hid-example
 always := $(hostprogs-y)
 
 HOSTCFLAGS_hid-example.o += -I$(objtree)/usr/include
+
+all: hid-example
index 512a7e50bcae19dd3d7dc40edb3741198f0512ac..92e6c1511910d06547a59859827d2b6b0800589e 100644 (file)
@@ -46,10 +46,14 @@ int main(int argc, char **argv)
        char buf[256];
        struct hidraw_report_descriptor rpt_desc;
        struct hidraw_devinfo info;
+       char *device = "/dev/hidraw0";
+
+       if (argc > 1)
+               device = argv[1];
 
        /* Open the Device with non-blocking reads. In real life,
           don't use a hard coded path; use libudev instead. */
-       fd = open("/dev/hidraw0", O_RDWR|O_NONBLOCK);
+       fd = open(device, O_RDWR|O_NONBLOCK);
 
        if (fd < 0) {
                perror("Unable to open device");
index 01562e0d499202a0005c61443f36bdf11a33160c..2e0740f06cd70d7e5837975ced3e2608a203afc1 100644 (file)
@@ -36,7 +36,12 @@ static ssize_t foo_show(struct kobject *kobj, struct kobj_attribute *attr,
 static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr,
                         const char *buf, size_t count)
 {
-       sscanf(buf, "%du", &foo);
+       int ret;
+
+       ret = kstrtoint(buf, 10, &foo);
+       if (ret < 0)
+               return ret;
+
        return count;
 }
 
@@ -63,9 +68,12 @@ static ssize_t b_show(struct kobject *kobj, struct kobj_attribute *attr,
 static ssize_t b_store(struct kobject *kobj, struct kobj_attribute *attr,
                       const char *buf, size_t count)
 {
-       int var;
+       int var, ret;
+
+       ret = kstrtoint(buf, 10, &var);
+       if (ret < 0)
+               return ret;
 
-       sscanf(buf, "%du", &var);
        if (strcmp(attr->attr.name, "baz") == 0)
                baz = var;
        else
@@ -134,5 +142,5 @@ static void __exit example_exit(void)
 
 module_init(example_init);
 module_exit(example_exit);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
index ab5e447ec23871b66b46049129dfaafc6f3f287d..a55bff52bde3f51ff34b25c5a4af46cca4607a28 100644 (file)
@@ -120,7 +120,12 @@ static ssize_t foo_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
 static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
                         const char *buf, size_t count)
 {
-       sscanf(buf, "%du", &foo_obj->foo);
+       int ret;
+
+       ret = kstrtoint(buf, 10, &foo_obj->foo);
+       if (ret < 0)
+               return ret;
+
        return count;
 }
 
@@ -147,9 +152,12 @@ static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
 static ssize_t b_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
                       const char *buf, size_t count)
 {
-       int var;
+       int var, ret;
+
+       ret = kstrtoint(buf, 10, &var);
+       if (ret < 0)
+               return ret;
 
-       sscanf(buf, "%du", &var);
        if (strcmp(attr->attr.name, "baz") == 0)
                foo_obj->baz = var;
        else
@@ -277,5 +285,5 @@ static void __exit example_exit(void)
 
 module_init(example_init);
 module_exit(example_exit);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
index a2c8b02b6359165868c674d3c1ca64a2db914cba..8965d1bb881194685d1af344cbdfd2868c2aa9fd 100644 (file)
  * protection, just like TRACE_INCLUDE_FILE.
  */
 #undef TRACE_SYSTEM
-#define TRACE_SYSTEM sample
+#define TRACE_SYSTEM sample-trace
+
+/*
+ * TRACE_SYSTEM is expected to be a C valid variable (alpha-numeric
+ * and underscore), although it may start with numbers. If for some
+ * reason it is not, you need to add the following lines:
+ */
+#undef TRACE_SYSTEM_VAR
+#define TRACE_SYSTEM_VAR sample_trace
+/*
+ * But the above is only needed if TRACE_SYSTEM is not alpha-numeric
+ * and underscored. By default, TRACE_SYSTEM_VAR will be equal to
+ * TRACE_SYSTEM. As TRACE_SYSTEM_VAR must be alpha-numeric, if
+ * TRACE_SYSTEM is not, then TRACE_SYSTEM_VAR must be defined with
+ * only alpha-numeric and underscores.
+ *
+ * The TRACE_SYSTEM_VAR is only used internally and not visible to
+ * user space.
+ */
 
 /*
  * Notice that this file is not protected like a normal header.
@@ -180,8 +198,30 @@ static inline int __length_of(const int *list)
                ;
        return i;
 }
+
+enum {
+       TRACE_SAMPLE_FOO = 2,
+       TRACE_SAMPLE_BAR = 4,
+       TRACE_SAMPLE_ZOO = 8,
+};
 #endif
 
+/*
+ * If enums are used in the TP_printk(), their names will be shown in
+ * format files and not their values. This can cause problems with user
+ * space programs that parse the format files to know how to translate
+ * the raw binary trace output into human readable text.
+ *
+ * To help out user space programs, any enum that is used in the TP_printk()
+ * should be defined by TRACE_DEFINE_ENUM() macro. All that is needed to
+ * be done is to add this macro with the enum within it in the trace
+ * header file, and it will be converted in the output.
+ */
+
+TRACE_DEFINE_ENUM(TRACE_SAMPLE_FOO);
+TRACE_DEFINE_ENUM(TRACE_SAMPLE_BAR);
+TRACE_DEFINE_ENUM(TRACE_SAMPLE_ZOO);
+
 TRACE_EVENT(foo_bar,
 
        TP_PROTO(const char *foo, int bar, const int *lst,
@@ -206,7 +246,47 @@ TRACE_EVENT(foo_bar,
                __assign_bitmask(cpus, cpumask_bits(mask), num_possible_cpus());
        ),
 
-       TP_printk("foo %s %d %s %s (%s)", __entry->foo, __entry->bar,
+       TP_printk("foo %s %d %s %s %s %s (%s)", __entry->foo, __entry->bar,
+
+/*
+ * Notice here the use of some helper functions. This includes:
+ *
+ *  __print_symbolic( variable, { value, "string" }, ... ),
+ *
+ *    The variable is tested against each value of the { } pair. If
+ *    the variable matches one of the values, then it will print the
+ *    string in that pair. If non are matched, it returns a string
+ *    version of the number (if __entry->bar == 7 then "7" is returned).
+ */
+                 __print_symbolic(__entry->bar,
+                                  { 0, "zero" },
+                                  { TRACE_SAMPLE_FOO, "TWO" },
+                                  { TRACE_SAMPLE_BAR, "FOUR" },
+                                  { TRACE_SAMPLE_ZOO, "EIGHT" },
+                                  { 10, "TEN" }
+                         ),
+
+/*
+ *  __print_flags( variable, "delim", { value, "flag" }, ... ),
+ *
+ *    This is similar to __print_symbolic, except that it tests the bits
+ *    of the value. If ((FLAG & variable) == FLAG) then the string is
+ *    printed. If more than one flag matches, then each one that does is
+ *    also printed with delim in between them.
+ *    If not all bits are accounted for, then the not found bits will be
+ *    added in hex format: 0x506 will show BIT2|BIT4|0x500
+ */
+                 __print_flags(__entry->bar, "|",
+                               { 1, "BIT1" },
+                               { 2, "BIT2" },
+                               { 4, "BIT3" },
+                               { 8, "BIT4" }
+                         ),
+/*
+ *  __print_array( array, len, element_size )
+ *
+ *    This prints out the array that is defined by __array in a nice format.
+ */
                  __print_array(__get_dynamic_array(list),
                                __get_dynamic_array_len(list),
                                sizeof(int)),
index 3b7eec24fb5a2a7cf6b55c4f003e363591888164..27c97f1f2767f6145349752e0500b1c87ad6052e 100644 (file)
@@ -57,6 +57,6 @@ coccilib.org.print_todo(p[0], "WARNING use BUG_ON")
 p << r.p;
 @@
 
-msg="WARNING: Use BUG_ON"
+msg="WARNING: Use BUG_ON instead of if condition followed by BUG.\nPlease make sure the condition has no side effects (see conditional BUG_ON definition in include/asm-generic/bug.h)"
 coccilib.report.print_report(p[0], msg)
 
index 107db88b1d5f9d1d5dda20c0636f229738fec8bd..dd56bffd6500e078b4aa7d4b64c8e04c91802541 100644 (file)
@@ -364,12 +364,12 @@ static int apparmor_path_chown(struct path *path, kuid_t uid, kgid_t gid)
        return common_perm(OP_CHOWN, path, AA_MAY_CHOWN, &cond);
 }
 
-static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int apparmor_inode_getattr(const struct path *path)
 {
-       if (!mediated_filesystem(dentry))
+       if (!mediated_filesystem(path->dentry))
                return 0;
 
-       return common_perm_mnt_dentry(OP_GETATTR, mnt, dentry,
+       return common_perm_mnt_dentry(OP_GETATTR, path->mnt, path->dentry,
                                      AA_MAY_META_READ);
 }
 
index 070dd46f62f4f57c7262211352775e121439e8a2..bdf22034a96118de3833f1913b0a89e8c617c7c4 100644 (file)
@@ -225,7 +225,7 @@ static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr)
        return 0;
 }
 
-static int cap_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int cap_inode_getattr(const struct path *path)
 {
        return 0;
 }
index 347896548ad3159a152186a4c1a27cdf92f1f4ad..25430a3aa7f7b9d6e6b4d10ae9bc72c8669c00fe 100644 (file)
@@ -31,30 +31,21 @@ static long compat_keyctl_instantiate_key_iov(
        key_serial_t ringid)
 {
        struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+       struct iov_iter from;
        long ret;
 
-       if (!_payload_iov || !ioc)
-               goto no_payload;
+       if (!_payload_iov)
+               ioc = 0;
 
-       ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc,
-                                          ARRAY_SIZE(iovstack),
-                                          iovstack, &iov);
+       ret = compat_import_iovec(WRITE, _payload_iov, ioc,
+                                 ARRAY_SIZE(iovstack), &iov,
+                                 &from);
        if (ret < 0)
-               goto err;
-       if (ret == 0)
-               goto no_payload_free;
-
-       ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
-err:
-       if (iov != iovstack)
-               kfree(iov);
-       return ret;
+               return ret;
 
-no_payload_free:
-       if (iov != iovstack)
-               kfree(iov);
-no_payload:
-       return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
+       ret = keyctl_instantiate_key_common(id, &from, ringid);
+       kfree(iov);
+       return ret;
 }
 
 /*
index 200e37867336a3c2903437e97f591fbc302e15b7..5105c2c2da75b0e13dec1196be67c88f4d789e72 100644 (file)
@@ -243,9 +243,10 @@ extern long keyctl_instantiate_key_iov(key_serial_t,
                                       unsigned, key_serial_t);
 extern long keyctl_invalidate_key(key_serial_t);
 
+struct iov_iter;
 extern long keyctl_instantiate_key_common(key_serial_t,
-                                         const struct iovec *,
-                                         unsigned, size_t, key_serial_t);
+                                         struct iov_iter *,
+                                         key_serial_t);
 #ifdef CONFIG_PERSISTENT_KEYRINGS
 extern long keyctl_get_persistent(uid_t, key_serial_t);
 extern unsigned persistent_keyring_expiry;
index 4743d71e4aa6dd12f2456a5f00496c1222775c6a..0b9ec78a7a7ad2b14af1ef0407e051e6dcef29ff 100644 (file)
@@ -997,21 +997,6 @@ static int keyctl_change_reqkey_auth(struct key *key)
        return commit_creds(new);
 }
 
-/*
- * Copy the iovec data from userspace
- */
-static long copy_from_user_iovec(void *buffer, const struct iovec *iov,
-                                unsigned ioc)
-{
-       for (; ioc > 0; ioc--) {
-               if (copy_from_user(buffer, iov->iov_base, iov->iov_len) != 0)
-                       return -EFAULT;
-               buffer += iov->iov_len;
-               iov++;
-       }
-       return 0;
-}
-
 /*
  * Instantiate a key with the specified payload and link the key into the
  * destination keyring if one is given.
@@ -1022,20 +1007,21 @@ static long copy_from_user_iovec(void *buffer, const struct iovec *iov,
  * If successful, 0 will be returned.
  */
 long keyctl_instantiate_key_common(key_serial_t id,
-                                  const struct iovec *payload_iov,
-                                  unsigned ioc,
-                                  size_t plen,
+                                  struct iov_iter *from,
                                   key_serial_t ringid)
 {
        const struct cred *cred = current_cred();
        struct request_key_auth *rka;
        struct key *instkey, *dest_keyring;
+       size_t plen = from ? iov_iter_count(from) : 0;
        void *payload;
        long ret;
-       bool vm = false;
 
        kenter("%d,,%zu,%d", id, plen, ringid);
 
+       if (!plen)
+               from = NULL;
+
        ret = -EINVAL;
        if (plen > 1024 * 1024 - 1)
                goto error;
@@ -1054,20 +1040,19 @@ long keyctl_instantiate_key_common(key_serial_t id,
        /* pull the payload in if one was supplied */
        payload = NULL;
 
-       if (payload_iov) {
+       if (from) {
                ret = -ENOMEM;
                payload = kmalloc(plen, GFP_KERNEL);
                if (!payload) {
                        if (plen <= PAGE_SIZE)
                                goto error;
-                       vm = true;
                        payload = vmalloc(plen);
                        if (!payload)
                                goto error;
                }
 
-               ret = copy_from_user_iovec(payload, payload_iov, ioc);
-               if (ret < 0)
+               ret = -EFAULT;
+               if (copy_from_iter(payload, plen, from) != plen)
                        goto error2;
        }
 
@@ -1089,10 +1074,7 @@ long keyctl_instantiate_key_common(key_serial_t id,
                keyctl_change_reqkey_auth(NULL);
 
 error2:
-       if (!vm)
-               kfree(payload);
-       else
-               vfree(payload);
+       kvfree(payload);
 error:
        return ret;
 }
@@ -1112,15 +1094,19 @@ long keyctl_instantiate_key(key_serial_t id,
                            key_serial_t ringid)
 {
        if (_payload && plen) {
-               struct iovec iov[1] = {
-                       [0].iov_base = (void __user *)_payload,
-                       [0].iov_len  = plen
-               };
+               struct iovec iov;
+               struct iov_iter from;
+               int ret;
 
-               return keyctl_instantiate_key_common(id, iov, 1, plen, ringid);
+               ret = import_single_range(WRITE, (void __user *)_payload, plen,
+                                         &iov, &from);
+               if (unlikely(ret))
+                       return ret;
+
+               return keyctl_instantiate_key_common(id, &from, ringid);
        }
 
-       return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
+       return keyctl_instantiate_key_common(id, NULL, ringid);
 }
 
 /*
@@ -1138,29 +1124,19 @@ long keyctl_instantiate_key_iov(key_serial_t id,
                                key_serial_t ringid)
 {
        struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+       struct iov_iter from;
        long ret;
 
-       if (!_payload_iov || !ioc)
-               goto no_payload;
+       if (!_payload_iov)
+               ioc = 0;
 
-       ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc,
-                                   ARRAY_SIZE(iovstack), iovstack, &iov);
+       ret = import_iovec(WRITE, _payload_iov, ioc,
+                                   ARRAY_SIZE(iovstack), &iov, &from);
        if (ret < 0)
-               goto err;
-       if (ret == 0)
-               goto no_payload_free;
-
-       ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
-err:
-       if (iov != iovstack)
-               kfree(iov);
+               return ret;
+       ret = keyctl_instantiate_key_common(id, &from, ringid);
+       kfree(iov);
        return ret;
-
-no_payload_free:
-       if (iov != iovstack)
-               kfree(iov);
-no_payload:
-       return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
 }
 
 /*
index e81d5bbe7363fc689199ea8db3a1a5fdc3e720e4..ed890c6d31c5c78c502904789736417098cb55a4 100644 (file)
@@ -608,11 +608,11 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
 }
 EXPORT_SYMBOL_GPL(security_inode_setattr);
 
-int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+int security_inode_getattr(const struct path *path)
 {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
                return 0;
-       return security_ops->inode_getattr(mnt, dentry);
+       return security_ops->inode_getattr(path);
 }
 
 int security_inode_setxattr(struct dentry *dentry, const char *name,
index 4d1a54190388df96dddb7ff951c681dc28bab866..e119cdcffc872e1ddd016521a36a9198aa4bc784 100644 (file)
@@ -1623,7 +1623,7 @@ static inline int dentry_has_perm(const struct cred *cred,
    the path to help the auditing code to more easily generate the
    pathname if needed. */
 static inline int path_has_perm(const struct cred *cred,
-                               struct path *path,
+                               const struct path *path,
                                u32 av)
 {
        struct inode *inode = path->dentry->d_inode;
@@ -2954,15 +2954,9 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
        return dentry_has_perm(cred, dentry, av);
 }
 
-static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int selinux_inode_getattr(const struct path *path)
 {
-       const struct cred *cred = current_cred();
-       struct path path;
-
-       path.dentry = dentry;
-       path.mnt = mnt;
-
-       return path_has_perm(cred, &path, FILE__GETATTR);
+       return path_has_perm(current_cred(), path, FILE__GETATTR);
 }
 
 static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
index c934311812f1a777093c44a89543dcae924b8568..1511965549b8232fdd4d3469166023c2d140f908 100644 (file)
@@ -1034,19 +1034,16 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
  *
  * Returns 0 if access is permitted, an error code otherwise
  */
-static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int smack_inode_getattr(const struct path *path)
 {
        struct smk_audit_info ad;
-       struct path path;
+       struct inode *inode = path->dentry->d_inode;
        int rc;
 
-       path.dentry = dentry;
-       path.mnt = mnt;
-
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
-       smk_ad_setfield_u_fs_path(&ad, path);
-       rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
-       rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc);
+       smk_ad_setfield_u_fs_path(&ad, *path);
+       rc = smk_curacc(smk_of_inode(inode), MAY_READ, &ad);
+       rc = smk_bu_inode(inode, MAY_READ, rc);
        return rc;
 }
 
index b897d4862016ce51ba737cee7f86f07d95a28c65..f9c9fb1d56b4bde70d43a21cc22a71e37245dfbc 100644 (file)
@@ -945,7 +945,7 @@ char *tomoyo_encode2(const char *str, int str_len);
 char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt,
                      va_list args);
 char *tomoyo_read_token(struct tomoyo_acl_param *param);
-char *tomoyo_realpath_from_path(struct path *path);
+char *tomoyo_realpath_from_path(const struct path *path);
 char *tomoyo_realpath_nofollow(const char *pathname);
 const char *tomoyo_get_exe(void);
 const char *tomoyo_yesno(const unsigned int value);
@@ -978,7 +978,7 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
                      struct path *path2);
 int tomoyo_path_number_perm(const u8 operation, struct path *path,
                            unsigned long number);
-int tomoyo_path_perm(const u8 operation, struct path *path,
+int tomoyo_path_perm(const u8 operation, const struct path *path,
                     const char *target);
 unsigned int tomoyo_poll_control(struct file *file, poll_table *wait);
 unsigned int tomoyo_poll_log(struct file *file, poll_table *wait);
index c151a1869597f8155a0296f89fafa61cc65f447d..2367b100cc62daccafa80932e4740385612746e9 100644 (file)
@@ -145,7 +145,7 @@ static void tomoyo_add_slash(struct tomoyo_path_info *buf)
  *
  * Returns true on success, false otherwise.
  */
-static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
+static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, const struct path *path)
 {
        buf->name = tomoyo_realpath_from_path(path);
        if (buf->name) {
@@ -782,7 +782,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
  *
  * Returns 0 on success, negative value otherwise.
  */
-int tomoyo_path_perm(const u8 operation, struct path *path, const char *target)
+int tomoyo_path_perm(const u8 operation, const struct path *path, const char *target)
 {
        struct tomoyo_request_info r;
        struct tomoyo_obj_info obj = {
index bed745c8b1a30d47a173fd7d96322aebb2d09c9c..1e0d480ff6a6b653cce9c4af266f5a8420a58c52 100644 (file)
@@ -89,7 +89,7 @@ char *tomoyo_encode(const char *str)
  *
  * If dentry is a directory, trailing '/' is appended.
  */
-static char *tomoyo_get_absolute_path(struct path *path, char * const buffer,
+static char *tomoyo_get_absolute_path(const struct path *path, char * const buffer,
                                      const int buflen)
 {
        char *pos = ERR_PTR(-ENOMEM);
@@ -216,7 +216,7 @@ out:
  *
  * Returns the buffer.
  */
-static char *tomoyo_get_socket_name(struct path *path, char * const buffer,
+static char *tomoyo_get_socket_name(const struct path *path, char * const buffer,
                                    const int buflen)
 {
        struct inode *inode = path->dentry->d_inode;
@@ -247,7 +247,7 @@ static char *tomoyo_get_socket_name(struct path *path, char * const buffer,
  * These functions use kzalloc(), so the caller must call kfree()
  * if these functions didn't return NULL.
  */
-char *tomoyo_realpath_from_path(struct path *path)
+char *tomoyo_realpath_from_path(const struct path *path)
 {
        char *buf = NULL;
        char *name = NULL;
index f0b756e27fed6b143f823d6a7708a408ea630bd8..57c88d52ffa52c3a7e799cba86a07027a5926aae 100644 (file)
@@ -144,10 +144,9 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
  *
  * Returns 0 on success, negative value otherwise.
  */
-static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+static int tomoyo_inode_getattr(const struct path *path)
 {
-       struct path path = { mnt, dentry };
-       return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path, NULL);
+       return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, path, NULL);
 }
 
 /**
index 279e24f613051fddb8ca16375ab9031e6a703b03..a69ebc79bc5008e8251c8837a5ea973eb2c458b9 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/pm_qos.h>
-#include <linux/aio.h>
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
 #include <sound/core.h>
@@ -35,6 +34,7 @@
 #include <sound/pcm_params.h>
 #include <sound/timer.h>
 #include <sound/minors.h>
+#include <linux/uio.h>
 
 /*
  *  Compatibility
index a422aaa3bb0cb6a7ea2f1e0de3b86380a52bf012..9ee25a63f684269c8fc600b1293b9b4421a7f020 100644 (file)
@@ -96,10 +96,10 @@ int snd_bebob_maudio_load_firmware(struct fw_unit *unit)
        struct fw_device *device = fw_parent_device(unit);
        int err, rcode;
        u64 date;
-       __be32 cues[3] = {
-               MAUDIO_BOOTLOADER_CUE1,
-               MAUDIO_BOOTLOADER_CUE2,
-               MAUDIO_BOOTLOADER_CUE3
+       __le32 cues[3] = {
+               cpu_to_le32(MAUDIO_BOOTLOADER_CUE1),
+               cpu_to_le32(MAUDIO_BOOTLOADER_CUE2),
+               cpu_to_le32(MAUDIO_BOOTLOADER_CUE3)
        };
 
        /* check date of software used to build */
index 74382137b9f5abcd67b9c4c44581c9a80f26d17d..f9d12c0a7e5a342f81f6e47c720a2187fd940367 100644 (file)
@@ -2912,6 +2912,8 @@ static void alc283_init(struct hda_codec *codec)
 
        if (!hp_pin)
                return;
+
+       msleep(30);
        hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
 
        /* Index 0x43 Direct Drive HP AMP LPM Control 1 */
@@ -3607,6 +3609,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
 
        switch (codec->vendor_id) {
        case 0x10ec0255:
+       case 0x10ec0256:
                alc_process_coef_fw(codec, coef0255);
                break;
        case 0x10ec0233:
@@ -3662,6 +3665,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
 
        switch (codec->vendor_id) {
        case 0x10ec0255:
+       case 0x10ec0256:
                alc_write_coef_idx(codec, 0x45, 0xc489);
                snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
                alc_process_coef_fw(codec, coef0255);
@@ -3731,6 +3735,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
 
        switch (codec->vendor_id) {
        case 0x10ec0255:
+       case 0x10ec0256:
                alc_process_coef_fw(codec, coef0255);
                break;
        case 0x10ec0233:
@@ -3785,6 +3790,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
 
        switch (codec->vendor_id) {
        case 0x10ec0255:
+       case 0x10ec0256:
                alc_process_coef_fw(codec, coef0255);
                break;
        case 0x10ec0233:
@@ -3839,6 +3845,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
 
        switch (codec->vendor_id) {
        case 0x10ec0255:
+       case 0x10ec0256:
                alc_process_coef_fw(codec, coef0255);
                break;
        case 0x10ec0233:
@@ -3884,6 +3891,7 @@ static void alc_determine_headset_type(struct hda_codec *codec)
 
        switch (codec->vendor_id) {
        case 0x10ec0255:
+       case 0x10ec0256:
                alc_process_coef_fw(codec, coef0255);
                msleep(300);
                val = alc_read_coef_idx(codec, 0x46);
@@ -4364,6 +4372,7 @@ enum {
        ALC269_FIXUP_QUANTA_MUTE,
        ALC269_FIXUP_LIFEBOOK,
        ALC269_FIXUP_LIFEBOOK_EXTMIC,
+       ALC269_FIXUP_LIFEBOOK_HP_PIN,
        ALC269_FIXUP_AMIC,
        ALC269_FIXUP_DMIC,
        ALC269VB_FIXUP_AMIC,
@@ -4517,6 +4526,13 @@ static const struct hda_fixup alc269_fixups[] = {
                        { }
                },
        },
+       [ALC269_FIXUP_LIFEBOOK_HP_PIN] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x21, 0x0221102f }, /* HP out */
+                       { }
+               },
+       },
        [ALC269_FIXUP_AMIC] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -5010,6 +5026,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX),
        SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
+       SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN),
        SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
        SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_BXBT2807_MIC),
@@ -5217,6 +5234,16 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x17, 0x40000000},
                {0x1d, 0x40700001},
                {0x21, 0x02211050}),
+       SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+               {0x12, 0x90a60140},
+               {0x13, 0x40000000},
+               {0x14, 0x90170110},
+               {0x19, 0x411111f0},
+               {0x1a, 0x411111f0},
+               {0x1b, 0x411111f0},
+               {0x1d, 0x40700001},
+               {0x1e, 0x411111f0},
+               {0x21, 0x02211020}),
        SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
                {0x12, 0x90a60130},
                {0x13, 0x40000000},
index 29202610dd0dd90d72329265633844a3d833d640..95d31d6291ac895bc7e22f650af655113c4cbc18 100644 (file)
@@ -19,7 +19,6 @@
 #include <sound/tlv.h>
 
 #include <linux/mfd/arizona/core.h>
-#include <linux/mfd/arizona/gpio.h>
 #include <linux/mfd/arizona/registers.h>
 
 #include "arizona.h"
@@ -281,6 +280,7 @@ int arizona_init_gpio(struct snd_soc_codec *codec)
 
        switch (arizona->type) {
        case WM5110:
+       case WM8280:
                snd_soc_dapm_disable_pin(&codec->dapm, "DRC2 Signal Activity");
                break;
        default:
@@ -1729,6 +1729,7 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
 
        switch (fll->arizona->type) {
        case WM5110:
+       case WM8280:
                if (fll->arizona->rev < 3 || sync)
                        return init_ratio;
                break;
index 9974f201a08f44ee25b109c7ff78e13440146c4b..474cae82a8742704af9875ef7734710ac05d71cf 100644 (file)
@@ -1156,25 +1156,6 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream,
                                ret, pcm512x->pll_out);
                        return ret;
                }
-
-               gpio = PCM512x_G1OE << (4 - 1);
-               ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_EN,
-                                        gpio, gpio);
-               if (ret != 0) {
-                       dev_err(codec->dev, "Failed to enable gpio %d: %d\n",
-                               4, ret);
-                       return ret;
-               }
-
-               gpio = PCM512x_GPIO_OUTPUT_1 + 4 - 1;
-               ret = regmap_update_bits(pcm512x->regmap, gpio,
-                                        PCM512x_GxSL, PCM512x_GxSL_PLLLK);
-               if (ret != 0) {
-                       dev_err(codec->dev,
-                               "Failed to output pll lock on %d: %d\n",
-                               ret, 4);
-                       return ret;
-               }
        }
 
        ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE,
index e5c990889dcc5e6d9a1ecca2682acf4384ab5ae5..10f0886e78ecc02d8a7df36375d48234e5c1ef97 100644 (file)
@@ -2755,7 +2755,7 @@ int snd_soc_register_component(struct device *dev,
 
        ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai, true);
        if (ret < 0) {
-               dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
+               dev_err(dev, "ASoC: Failed to register DAIs: %d\n", ret);
                goto err_cleanup;
        }
 
@@ -3076,7 +3076,7 @@ int snd_soc_register_codec(struct device *dev,
 
        ret = snd_soc_register_dais(&codec->component, dai_drv, num_dai, false);
        if (ret < 0) {
-               dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
+               dev_err(dev, "ASoC: Failed to register DAIs: %d\n", ret);
                goto err_cleanup;
        }
 
index dc9df007d3e33358a51b73bb6446d81f6d427ab1..337c317ead6fbc2fa7e3ae80bcfb7cb64119cf55 100644 (file)
@@ -192,6 +192,7 @@ static const struct rc_config {
        { USB_ID(0x041e, 0x3040), 2, 2, 6, 6,  2,  0x6e91 }, /* Live! 24-bit */
        { USB_ID(0x041e, 0x3042), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 */
        { USB_ID(0x041e, 0x30df), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 Pro */
+       { USB_ID(0x041e, 0x3237), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 Pro */
        { USB_ID(0x041e, 0x3048), 2, 2, 6, 6,  2,  0x6e91 }, /* Toshiba SB0500 */
 };
 
index 753a47de8459b7a0b505e72d2f660793d9ede885..9a28365126f9ab170454e46249348a06df8a2f32 100644 (file)
@@ -1113,8 +1113,13 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
 
 bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
 {
-       /* MS Lifecam HD-5000 doesn't support reading the sample rate. */
-       return chip->usb_id == USB_ID(0x045E, 0x076D);
+       /* devices which do not support reading the sample rate. */
+       switch (chip->usb_id) {
+       case USB_ID(0x045E, 0x076D): /* MS Lifecam HD-5000 */
+       case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
+               return true;
+       }
+       return false;
 }
 
 /* Marantz/Denon USB DACs need a vendor cmd to switch
diff --git a/tools/build/Build.include b/tools/build/Build.include
new file mode 100644 (file)
index 0000000..4c8daac
--- /dev/null
@@ -0,0 +1,81 @@
+###
+# build: Generic definitions
+#
+#  Lots of this code have been borrowed or heavily inspired from parts
+#  of kbuild code, which is not credited, but mostly developed by:
+#
+#  Copyright (C) Sam Ravnborg <sam@mars.ravnborg.org>, 2015
+#  Copyright (C) Linus Torvalds <torvalds@linux-foundation.org>, 2015
+#
+
+###
+# Convenient variables
+comma   := ,
+squote  := '
+
+###
+# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
+dot-target = $(dir $@).$(notdir $@)
+
+###
+# filename of target with directory and extension stripped
+basetarget = $(basename $(notdir $@))
+
+###
+# The temporary file to save gcc -MD generated dependencies must not
+# contain a comma
+depfile = $(subst $(comma),_,$(dot-target).d)
+
+###
+# Check if both arguments has same arguments. Result is empty string if equal.
+arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
+                    $(filter-out $(cmd_$@),   $(cmd_$(1))) )
+
+###
+# Escape single quote for use in echo statements
+escsq = $(subst $(squote),'\$(squote)',$1)
+
+# Echo command
+# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
+echo-cmd = $(if $($(quiet)cmd_$(1)),\
+           echo '  $(call escsq,$($(quiet)cmd_$(1)))';)
+
+###
+# Replace >$< with >$$< to preserve $ when reloading the .cmd file
+# (needed for make)
+# Replace >#< with >\#< to avoid starting a comment in the .cmd file
+# (needed for make)
+# Replace >'< with >'\''< to be able to enclose the whole string in '...'
+# (needed for the shell)
+make-cmd = $(call escsq,$(subst \#,\\\#,$(subst $$,$$$$,$(cmd_$(1)))))
+
+###
+# Find any prerequisites that is newer than target or that does not exist.
+# PHONY targets skipped in both cases.
+any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
+
+###
+# if_changed_dep  - execute command if any prerequisite is newer than
+#                   target, or command line has changed and update
+#                   dependencies in the cmd file
+if_changed_dep = $(if $(strip $(any-prereq) $(arg-check)),         \
+       @set -e;                                                   \
+       $(echo-cmd) $(cmd_$(1));                                   \
+       cat $(depfile) > $(dot-target).cmd;                        \
+       printf '%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)
+
+# if_changed      - execute command if any prerequisite is newer than
+#                   target, or command line has changed
+if_changed = $(if $(strip $(any-prereq) $(arg-check)),             \
+       @set -e;                                                   \
+       $(echo-cmd) $(cmd_$(1));                                   \
+       printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
+
+###
+# C flags to be used in rule definitions, includes:
+# - depfile generation
+# - global $(CFLAGS)
+# - per target C flags
+# - per object C flags
+# - BUILD_STR macro to allow '-D"$(variable)"' constructs
+c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
diff --git a/tools/build/Documentation/Build.txt b/tools/build/Documentation/Build.txt
new file mode 100644 (file)
index 0000000..00ad2d6
--- /dev/null
@@ -0,0 +1,139 @@
+Build Framework
+===============
+
+The perf build framework was adopted from the kernel build system, hence the
+idea and the way how objects are built is the same.
+
+Basically the user provides set of 'Build' files that list objects and
+directories to nest for specific target to be build.
+
+Unlike the kernel we don't have a single build object 'obj-y' list that where
+we setup source objects, but we support more. This allows one 'Build' file to
+carry a sources list for multiple build objects.
+
+a) Build framework makefiles
+----------------------------
+
+The build framework consists of 2 Makefiles:
+
+  Build.include
+  Makefile.build
+
+While the 'Build.include' file contains just some generic definitions, the
+'Makefile.build' file is the makefile used from the outside. It's
+interface/usage is following:
+
+  $ make -f tools/build/Makefile srctree=$(KSRC) dir=$(DIR) obj=$(OBJECT)
+
+where:
+
+  KSRC   - is the path to kernel sources
+  DIR    - is the path to the project to be built
+  OBJECT - is the name of the build object
+
+When succefully finished the $(DIR) directory contains the final object file
+called $(OBJECT)-in.o:
+
+  $ ls $(DIR)/$(OBJECT)-in.o
+
+which includes all compiled sources described in 'Build' makefiles.
+
+a) Build makefiles
+------------------
+
+The user supplies 'Build' makefiles that contains a objects list, and connects
+the build to nested directories.
+
+Assume we have the following project structure:
+
+  ex/a.c
+    /b.c
+    /c.c
+    /d.c
+    /arch/e.c
+    /arch/f.c
+
+Out of which you build the 'ex' binary ' and the 'libex.a' library:
+
+  'ex'      - consists of 'a.o', 'b.o' and libex.a
+  'libex.a' - consists of 'c.o', 'd.o', 'e.o' and 'f.o'
+
+The build framework does not create the 'ex' and 'libex.a' binaries for you, it
+only prepares proper objects to be compiled and grouped together.
+
+To follow the above example, the user provides following 'Build' files:
+
+  ex/Build:
+    ex-y += a.o
+    ex-y += b.o
+
+    libex-y += c.o
+    libex-y += d.o
+    libex-y += arch/
+
+  ex/arch/Build:
+    libex-y += e.o
+    libex-y += f.o
+
+and runs:
+
+  $ make -f tools/build/Makefile.build dir=. obj=ex
+  $ make -f tools/build/Makefile.build dir=. obj=libex
+
+which creates the following objects:
+
+  ex/ex-in.o
+  ex/libex-in.o
+
+that contain request objects names in Build files.
+
+It's only a matter of 2 single commands to create the final binaries:
+
+  $ ar  rcs libex.a libex-in.o
+  $ gcc -o ex ex-in.o libex.a
+
+You can check the 'ex' example in 'tools/build/tests/ex' for more details.
+
+b) Rules
+--------
+
+The build framework provides standard compilation rules to handle .S and .c
+compilation.
+
+It's possible to include special rule if needed (like we do for flex or bison
+code generation).
+
+c) CFLAGS
+---------
+
+It's possible to alter the standard object C flags in the following way:
+
+  CFLAGS_perf.o += '...' - alters CFLAGS for perf.o object
+  CFLAGS_gtk += '...'    - alters CFLAGS for gtk build object
+
+This C flags changes has the scope of the Build makefile they are defined in.
+
+
+d) Dependencies
+---------------
+
+For each built object file 'a.o' the '.a.cmd' is created and holds:
+
+  - Command line used to built that object
+    (for each object)
+
+  - Dependency rules generated by 'gcc -Wp,-MD,...'
+    (for compiled object)
+
+All existing '.cmd' files are included in the Build process to follow properly
+the dependencies and trigger a rebuild when necessary.
+
+
+e) Single rules
+---------------
+
+It's possible to build single object file by choice, like:
+
+  $ make util/map.o    # objects
+  $ make util/map.i    # preprocessor
+  $ make util/map.s    # assembly
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
new file mode 100644 (file)
index 0000000..10df572
--- /dev/null
@@ -0,0 +1,130 @@
+###
+# Main build makefile.
+#
+#  Lots of this code have been borrowed or heavily inspired from parts
+#  of kbuild code, which is not credited, but mostly developed by:
+#
+#  Copyright (C) Sam Ravnborg <sam@mars.ravnborg.org>, 2015
+#  Copyright (C) Linus Torvalds <torvalds@linux-foundation.org>, 2015
+#
+
+PHONY := __build
+__build:
+
+ifeq ($(V),1)
+  quiet =
+  Q =
+else
+  quiet=quiet_
+  Q=@
+endif
+
+build-dir := $(srctree)/tools/build
+
+# Generic definitions
+include $(build-dir)/Build.include
+
+# do not force detected configuration
+-include .config-detected
+
+# Init all relevant variables used in build files so
+# 1) they have correct type
+# 2) they do not inherit any value from the environment
+subdir-y     :=
+obj-y        :=
+subdir-y     :=
+subdir-obj-y :=
+
+# Build definitions
+build-file := $(dir)/Build
+include $(build-file)
+
+quiet_cmd_flex  = FLEX     $@
+quiet_cmd_bison = BISON    $@
+
+# Create directory unless it exists
+quiet_cmd_mkdir = MKDIR    $(dir $@)
+      cmd_mkdir = mkdir -p $(dir $@)
+     rule_mkdir = $(if $(wildcard $(dir $@)),,@$(call echo-cmd,mkdir) $(cmd_mkdir))
+
+# Compile command
+quiet_cmd_cc_o_c = CC       $@
+      cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
+
+quiet_cmd_cc_i_c = CPP      $@
+      cmd_cc_i_c = $(CC) $(c_flags) -E -o $@ $<
+
+quiet_cmd_cc_s_c = AS       $@
+      cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $<
+
+# Link agregate command
+# If there's nothing to link, create empty $@ object.
+quiet_cmd_ld_multi = LD       $@
+      cmd_ld_multi = $(if $(strip $(obj-y)),\
+                      $(LD) -r -o $@ $(obj-y),rm -f $@; $(AR) rcs $@)
+
+# Build rules
+$(OUTPUT)%.o: %.c FORCE
+       $(call rule_mkdir)
+       $(call if_changed_dep,cc_o_c)
+
+$(OUTPUT)%.o: %.S FORCE
+       $(call rule_mkdir)
+       $(call if_changed_dep,cc_o_c)
+
+$(OUTPUT)%.i: %.c FORCE
+       $(call rule_mkdir)
+       $(call if_changed_dep,cc_i_c)
+
+$(OUTPUT)%.i: %.S FORCE
+       $(call rule_mkdir)
+       $(call if_changed_dep,cc_i_c)
+
+$(OUTPUT)%.s: %.c FORCE
+       $(call rule_mkdir)
+       $(call if_changed_dep,cc_s_c)
+
+# Gather build data:
+#   obj-y        - list of build objects
+#   subdir-y     - list of directories to nest
+#   subdir-obj-y - list of directories objects 'dir/$(obj)-in.o'
+obj-y        := $($(obj)-y)
+subdir-y     := $(patsubst %/,%,$(filter %/, $(obj-y)))
+obj-y        := $(patsubst %/, %/$(obj)-in.o, $(obj-y))
+subdir-obj-y := $(filter %/$(obj)-in.o, $(obj-y))
+
+# '$(OUTPUT)/dir' prefix to all objects
+prefix       := $(subst ./,,$(OUTPUT)$(dir)/)
+obj-y        := $(addprefix $(prefix),$(obj-y))
+subdir-obj-y := $(addprefix $(prefix),$(subdir-obj-y))
+
+# Final '$(obj)-in.o' object
+in-target := $(prefix)$(obj)-in.o
+
+PHONY += $(subdir-y)
+
+$(subdir-y):
+       $(Q)$(MAKE) -f $(build-dir)/Makefile.build dir=$(dir)/$@ obj=$(obj)
+
+$(sort $(subdir-obj-y)): $(subdir-y) ;
+
+$(in-target): $(obj-y) FORCE
+       $(call rule_mkdir)
+       $(call if_changed,ld_multi)
+
+__build: $(in-target)
+       @:
+
+PHONY += FORCE
+FORCE:
+
+# Include all cmd files to get all the dependency rules
+# for all objects included
+targets   := $(wildcard $(sort $(obj-y) $(in-target) $(MAKECMDGOALS)))
+cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
+
+ifneq ($(cmd_files),)
+  include $(cmd_files)
+endif
+
+.PHONY: $(PHONY)
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
new file mode 100644 (file)
index 0000000..3a0b0ca
--- /dev/null
@@ -0,0 +1,171 @@
+feature_dir := $(srctree)/tools/build/feature
+
+ifneq ($(OUTPUT),)
+  OUTPUT_FEATURES = $(OUTPUT)feature/
+  $(shell mkdir -p $(OUTPUT_FEATURES))
+endif
+
+feature_check = $(eval $(feature_check_code))
+define feature_check_code
+  feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
+endef
+
+feature_set = $(eval $(feature_set_code))
+define feature_set_code
+  feature-$(1) := 1
+endef
+
+#
+# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output:
+#
+
+#
+# Note that this is not a complete list of all feature tests, just
+# those that are typically built on a fully configured system.
+#
+# [ Feature tests not mentioned here have to be built explicitly in
+#   the rule that uses them - an example for that is the 'bionic'
+#   feature check. ]
+#
+FEATURE_TESTS =                        \
+       backtrace                       \
+       dwarf                           \
+       fortify-source                  \
+       sync-compare-and-swap           \
+       glibc                           \
+       gtk2                            \
+       gtk2-infobar                    \
+       libaudit                        \
+       libbfd                          \
+       libelf                          \
+       libelf-getphdrnum               \
+       libelf-mmap                     \
+       libnuma                         \
+       libperl                         \
+       libpython                       \
+       libpython-version               \
+       libslang                        \
+       libunwind                       \
+       pthread-attr-setaffinity-np     \
+       stackprotector-all              \
+       timerfd                         \
+       libdw-dwarf-unwind              \
+       zlib                            \
+       lzma
+
+FEATURE_DISPLAY =                      \
+       dwarf                           \
+       glibc                           \
+       gtk2                            \
+       libaudit                        \
+       libbfd                          \
+       libelf                          \
+       libnuma                         \
+       libperl                         \
+       libpython                       \
+       libslang                        \
+       libunwind                       \
+       libdw-dwarf-unwind              \
+       zlib                            \
+       lzma
+
+# Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
+# If in the future we need per-feature checks/flags for features not
+# mentioned in this list we need to refactor this ;-).
+set_test_all_flags = $(eval $(set_test_all_flags_code))
+define set_test_all_flags_code
+  FEATURE_CHECK_CFLAGS-all  += $(FEATURE_CHECK_CFLAGS-$(1))
+  FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1))
+endef
+
+$(foreach feat,$(FEATURE_TESTS),$(call set_test_all_flags,$(feat)))
+
+#
+# Special fast-path for the 'all features are available' case:
+#
+$(call feature_check,all,$(MSG))
+
+#
+# Just in case the build freshly failed, make sure we print the
+# feature matrix:
+#
+ifeq ($(feature-all), 1)
+  #
+  # test-all.c passed - just set all the core feature flags to 1:
+  #
+  $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat)))
+else
+  $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C $(feature_dir) $(addsuffix .bin,$(FEATURE_TESTS)) >/dev/null 2>&1)
+  $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat)))
+endif
+
+#
+# Print the result of the feature test:
+#
+feature_print_status = $(eval $(feature_print_status_code)) $(info $(MSG))
+
+define feature_print_status_code
+  ifeq ($(feature-$(1)), 1)
+    MSG = $(shell printf '...%30s: [ \033[32mon\033[m  ]' $(1))
+  else
+    MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
+  endif
+endef
+
+feature_print_text = $(eval $(feature_print_text_code)) $(info $(MSG))
+define feature_print_text_code
+    MSG = $(shell printf '...%30s: %s' $(1) $(2))
+endef
+
+FEATURE_DUMP := $(foreach feat,$(FEATURE_DISPLAY),feature-$(feat)($(feature-$(feat))))
+FEATURE_DUMP_FILE := $(shell touch $(OUTPUT)FEATURE-DUMP; cat $(OUTPUT)FEATURE-DUMP)
+
+ifeq ($(dwarf-post-unwind),1)
+  FEATURE_DUMP += dwarf-post-unwind($(dwarf-post-unwind-text))
+endif
+
+# The $(feature_display) controls the default detection message
+# output. It's set if:
+# - detected features differes from stored features from
+#   last build (in FEATURE-DUMP file)
+# - one of the $(FEATURE_DISPLAY) is not detected
+# - VF is enabled
+
+ifneq ("$(FEATURE_DUMP)","$(FEATURE_DUMP_FILE)")
+  $(shell echo "$(FEATURE_DUMP)" > $(OUTPUT)FEATURE-DUMP)
+  feature_display := 1
+endif
+
+feature_display_check = $(eval $(feature_check_code))
+define feature_display_check_code
+  ifneq ($(feature-$(1)), 1)
+    feature_display := 1
+  endif
+endef
+
+$(foreach feat,$(FEATURE_DISPLAY),$(call feature_display_check,$(feat)))
+
+ifeq ($(VF),1)
+  feature_display := 1
+  feature_verbose := 1
+endif
+
+ifeq ($(feature_display),1)
+  $(info )
+  $(info Auto-detecting system features:)
+  $(foreach feat,$(FEATURE_DISPLAY),$(call feature_print_status,$(feat),))
+
+  ifeq ($(dwarf-post-unwind),1)
+    $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
+  endif
+
+  ifneq ($(feature_verbose),1)
+    $(info )
+  endif
+endif
+
+ifeq ($(feature_verbose),1)
+  TMP := $(filter-out $(FEATURE_DISPLAY),$(FEATURE_TESTS))
+  $(foreach feat,$(TMP),$(call feature_print_status,$(feat),))
+  $(info )
+endif
diff --git a/tools/build/feature/.gitignore b/tools/build/feature/.gitignore
new file mode 100644 (file)
index 0000000..09b335b
--- /dev/null
@@ -0,0 +1,3 @@
+*.d
+*.bin
+*.output
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
new file mode 100644 (file)
index 0000000..463ed8f
--- /dev/null
@@ -0,0 +1,164 @@
+
+FILES=                                 \
+       test-all.bin                    \
+       test-backtrace.bin              \
+       test-bionic.bin                 \
+       test-dwarf.bin                  \
+       test-fortify-source.bin         \
+       test-sync-compare-and-swap.bin  \
+       test-glibc.bin                  \
+       test-gtk2.bin                   \
+       test-gtk2-infobar.bin           \
+       test-hello.bin                  \
+       test-libaudit.bin               \
+       test-libbfd.bin                 \
+       test-liberty.bin                \
+       test-liberty-z.bin              \
+       test-cplus-demangle.bin         \
+       test-libelf.bin                 \
+       test-libelf-getphdrnum.bin      \
+       test-libelf-mmap.bin            \
+       test-libnuma.bin                \
+       test-libperl.bin                \
+       test-libpython.bin              \
+       test-libpython-version.bin      \
+       test-libslang.bin               \
+       test-libunwind.bin              \
+       test-libunwind-debug-frame.bin  \
+       test-pthread-attr-setaffinity-np.bin    \
+       test-stackprotector-all.bin     \
+       test-timerfd.bin                \
+       test-libdw-dwarf-unwind.bin     \
+       test-libbabeltrace.bin          \
+       test-compile-32.bin             \
+       test-compile-x32.bin            \
+       test-zlib.bin                   \
+       test-lzma.bin
+
+CC := $(CROSS_COMPILE)gcc -MD
+PKG_CONFIG := $(CROSS_COMPILE)pkg-config
+
+all: $(FILES)
+
+__BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
+  BUILD = $(__BUILD) > $(OUTPUT)$(@:.bin=.make.output) 2>&1
+
+###############################
+
+test-all.bin:
+       $(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz -llzma
+
+test-hello.bin:
+       $(BUILD)
+
+test-pthread-attr-setaffinity-np.bin:
+       $(BUILD) -D_GNU_SOURCE -lpthread
+
+test-stackprotector-all.bin:
+       $(BUILD) -fstack-protector-all
+
+test-fortify-source.bin:
+       $(BUILD) -O2 -D_FORTIFY_SOURCE=2
+
+test-bionic.bin:
+       $(BUILD)
+
+test-libelf.bin:
+       $(BUILD) -lelf
+
+test-glibc.bin:
+       $(BUILD)
+
+test-dwarf.bin:
+       $(BUILD) -ldw
+
+test-libelf-mmap.bin:
+       $(BUILD) -lelf
+
+test-libelf-getphdrnum.bin:
+       $(BUILD) -lelf
+
+test-libnuma.bin:
+       $(BUILD) -lnuma
+
+test-libunwind.bin:
+       $(BUILD) -lelf
+
+test-libunwind-debug-frame.bin:
+       $(BUILD) -lelf
+
+test-libaudit.bin:
+       $(BUILD) -laudit
+
+test-libslang.bin:
+       $(BUILD) -I/usr/include/slang -lslang
+
+test-gtk2.bin:
+       $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
+
+test-gtk2-infobar.bin:
+       $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
+
+grep-libs  = $(filter -l%,$(1))
+strip-libs = $(filter-out -l%,$(1))
+
+PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null)
+PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS))
+PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
+PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
+FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
+
+test-libperl.bin:
+       $(BUILD) $(FLAGS_PERL_EMBED)
+
+test-libpython.bin:
+       $(BUILD)
+
+test-libpython-version.bin:
+       $(BUILD)
+
+test-libbfd.bin:
+       $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
+
+test-liberty.bin:
+       $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
+
+test-liberty-z.bin:
+       $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz
+
+test-cplus-demangle.bin:
+       $(BUILD) -liberty
+
+test-backtrace.bin:
+       $(BUILD)
+
+test-timerfd.bin:
+       $(BUILD)
+
+test-libdw-dwarf-unwind.bin:
+       $(BUILD) # -ldw provided by $(FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind)
+
+test-libbabeltrace.bin:
+       $(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace)
+
+test-sync-compare-and-swap.bin:
+       $(BUILD)
+
+test-compile-32.bin:
+       $(CC) -m32 -o $(OUTPUT)$@ test-compile.c
+
+test-compile-x32.bin:
+       $(CC) -mx32 -o $(OUTPUT)$@ test-compile.c
+
+test-zlib.bin:
+       $(BUILD) -lz
+
+test-lzma.bin:
+       $(BUILD) -llzma
+
+-include *.d
+
+###############################
+
+clean:
+       rm -f $(FILES) *.d $(FILES:.bin=.make.output)
diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c
new file mode 100644 (file)
index 0000000..84689a6
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * test-all.c: Try to build all the main testcases at once.
+ *
+ * A well-configured system will have all the prereqs installed, so we can speed
+ * up auto-detection on such systems.
+ */
+
+/*
+ * Quirk: Python and Perl headers cannot be in arbitrary places, so keep
+ * these 3 testcases at the top:
+ */
+#define main main_test_libpython
+# include "test-libpython.c"
+#undef main
+
+#define main main_test_libpython_version
+# include "test-libpython-version.c"
+#undef main
+
+#define main main_test_libperl
+# include "test-libperl.c"
+#undef main
+
+#define main main_test_hello
+# include "test-hello.c"
+#undef main
+
+#define main main_test_libelf
+# include "test-libelf.c"
+#undef main
+
+#define main main_test_libelf_mmap
+# include "test-libelf-mmap.c"
+#undef main
+
+#define main main_test_glibc
+# include "test-glibc.c"
+#undef main
+
+#define main main_test_dwarf
+# include "test-dwarf.c"
+#undef main
+
+#define main main_test_libelf_getphdrnum
+# include "test-libelf-getphdrnum.c"
+#undef main
+
+#define main main_test_libunwind
+# include "test-libunwind.c"
+#undef main
+
+#define main main_test_libaudit
+# include "test-libaudit.c"
+#undef main
+
+#define main main_test_libslang
+# include "test-libslang.c"
+#undef main
+
+#define main main_test_gtk2
+# include "test-gtk2.c"
+#undef main
+
+#define main main_test_gtk2_infobar
+# include "test-gtk2-infobar.c"
+#undef main
+
+#define main main_test_libbfd
+# include "test-libbfd.c"
+#undef main
+
+#define main main_test_backtrace
+# include "test-backtrace.c"
+#undef main
+
+#define main main_test_libnuma
+# include "test-libnuma.c"
+#undef main
+
+#define main main_test_timerfd
+# include "test-timerfd.c"
+#undef main
+
+#define main main_test_stackprotector_all
+# include "test-stackprotector-all.c"
+#undef main
+
+#define main main_test_libdw_dwarf_unwind
+# include "test-libdw-dwarf-unwind.c"
+#undef main
+
+#define main main_test_sync_compare_and_swap
+# include "test-sync-compare-and-swap.c"
+#undef main
+
+#define main main_test_zlib
+# include "test-zlib.c"
+#undef main
+
+#define main main_test_pthread_attr_setaffinity_np
+# include "test-pthread-attr-setaffinity-np.c"
+#undef main
+
+# if 0
+/*
+ * Disable libbabeltrace check for test-all, because the requested
+ * library version is not released yet in most distributions. Will
+ * reenable later.
+ */
+
+#define main main_test_libbabeltrace
+# include "test-libbabeltrace.c"
+#undef main
+#endif
+
+#define main main_test_lzma
+# include "test-lzma.c"
+#undef main
+
+int main(int argc, char *argv[])
+{
+       main_test_libpython();
+       main_test_libpython_version();
+       main_test_libperl();
+       main_test_hello();
+       main_test_libelf();
+       main_test_libelf_mmap();
+       main_test_glibc();
+       main_test_dwarf();
+       main_test_libelf_getphdrnum();
+       main_test_libunwind();
+       main_test_libaudit();
+       main_test_libslang();
+       main_test_gtk2(argc, argv);
+       main_test_gtk2_infobar(argc, argv);
+       main_test_libbfd();
+       main_test_backtrace();
+       main_test_libnuma();
+       main_test_timerfd();
+       main_test_stackprotector_all();
+       main_test_libdw_dwarf_unwind();
+       main_test_sync_compare_and_swap(argc, argv);
+       main_test_zlib();
+       main_test_pthread_attr_setaffinity_np();
+       main_test_lzma();
+
+       return 0;
+}
diff --git a/tools/build/feature/test-backtrace.c b/tools/build/feature/test-backtrace.c
new file mode 100644 (file)
index 0000000..7124aa1
--- /dev/null
@@ -0,0 +1,13 @@
+#include <execinfo.h>
+#include <stdio.h>
+
+int main(void)
+{
+       void *backtrace_fns[10];
+       size_t entries;
+
+       entries = backtrace(backtrace_fns, 10);
+       backtrace_symbols_fd(backtrace_fns, entries, 1);
+
+       return 0;
+}
diff --git a/tools/build/feature/test-bionic.c b/tools/build/feature/test-bionic.c
new file mode 100644 (file)
index 0000000..eac24e9
--- /dev/null
@@ -0,0 +1,6 @@
+#include <android/api-level.h>
+
+int main(void)
+{
+       return __ANDROID_API__;
+}
diff --git a/tools/build/feature/test-compile.c b/tools/build/feature/test-compile.c
new file mode 100644 (file)
index 0000000..31dbf45
--- /dev/null
@@ -0,0 +1,4 @@
+int main(void)
+{
+       return 0;
+}
diff --git a/tools/build/feature/test-cplus-demangle.c b/tools/build/feature/test-cplus-demangle.c
new file mode 100644 (file)
index 0000000..610c686
--- /dev/null
@@ -0,0 +1,14 @@
+extern int printf(const char *format, ...);
+extern char *cplus_demangle(const char *, int);
+
+int main(void)
+{
+       char symbol[4096] = "FieldName__9ClassNameFd";
+       char *tmp;
+
+       tmp = cplus_demangle(symbol, 0);
+
+       printf("demangled symbol: {%s}\n", tmp);
+
+       return 0;
+}
diff --git a/tools/build/feature/test-dwarf.c b/tools/build/feature/test-dwarf.c
new file mode 100644 (file)
index 0000000..3fc1801
--- /dev/null
@@ -0,0 +1,10 @@
+#include <dwarf.h>
+#include <elfutils/libdw.h>
+#include <elfutils/version.h>
+
+int main(void)
+{
+       Dwarf *dbg = dwarf_begin(0, DWARF_C_READ);
+
+       return (long)dbg;
+}
diff --git a/tools/build/feature/test-fortify-source.c b/tools/build/feature/test-fortify-source.c
new file mode 100644 (file)
index 0000000..c9f398d
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(void)
+{
+       return puts("hi");
+}
diff --git a/tools/build/feature/test-glibc.c b/tools/build/feature/test-glibc.c
new file mode 100644 (file)
index 0000000..b082034
--- /dev/null
@@ -0,0 +1,8 @@
+#include <gnu/libc-version.h>
+
+int main(void)
+{
+       const char *version = gnu_get_libc_version();
+
+       return (long)version;
+}
diff --git a/tools/build/feature/test-gtk2-infobar.c b/tools/build/feature/test-gtk2-infobar.c
new file mode 100644 (file)
index 0000000..397b464
--- /dev/null
@@ -0,0 +1,11 @@
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#include <gtk/gtk.h>
+#pragma GCC diagnostic error "-Wstrict-prototypes"
+
+int main(int argc, char *argv[])
+{
+       gtk_init(&argc, &argv);
+       gtk_info_bar_new();
+
+       return 0;
+}
diff --git a/tools/build/feature/test-gtk2.c b/tools/build/feature/test-gtk2.c
new file mode 100644 (file)
index 0000000..6bd80e5
--- /dev/null
@@ -0,0 +1,10 @@
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#include <gtk/gtk.h>
+#pragma GCC diagnostic error "-Wstrict-prototypes"
+
+int main(int argc, char *argv[])
+{
+       gtk_init(&argc, &argv);
+
+        return 0;
+}
diff --git a/tools/build/feature/test-hello.c b/tools/build/feature/test-hello.c
new file mode 100644 (file)
index 0000000..c9f398d
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(void)
+{
+       return puts("hi");
+}
diff --git a/tools/build/feature/test-libaudit.c b/tools/build/feature/test-libaudit.c
new file mode 100644 (file)
index 0000000..afc019f
--- /dev/null
@@ -0,0 +1,10 @@
+#include <libaudit.h>
+
+extern int printf(const char *format, ...);
+
+int main(void)
+{
+       printf("error message: %s\n", audit_errno_to_name(0));
+
+       return audit_open();
+}
diff --git a/tools/build/feature/test-libbabeltrace.c b/tools/build/feature/test-libbabeltrace.c
new file mode 100644 (file)
index 0000000..9cf802a
--- /dev/null
@@ -0,0 +1,9 @@
+
+#include <babeltrace/ctf-writer/writer.h>
+#include <babeltrace/ctf-ir/stream-class.h>
+
+int main(void)
+{
+       bt_ctf_stream_class_get_packet_context_type((void *) 0);
+       return 0;
+}
diff --git a/tools/build/feature/test-libbfd.c b/tools/build/feature/test-libbfd.c
new file mode 100644 (file)
index 0000000..2405990
--- /dev/null
@@ -0,0 +1,15 @@
+#include <bfd.h>
+
+extern int printf(const char *format, ...);
+
+int main(void)
+{
+       char symbol[4096] = "FieldName__9ClassNameFd";
+       char *tmp;
+
+       tmp = bfd_demangle(0, symbol, 0);
+
+       printf("demangled symbol: {%s}\n", tmp);
+
+       return 0;
+}
diff --git a/tools/build/feature/test-libdw-dwarf-unwind.c b/tools/build/feature/test-libdw-dwarf-unwind.c
new file mode 100644 (file)
index 0000000..f676a3f
--- /dev/null
@@ -0,0 +1,13 @@
+
+#include <elfutils/libdwfl.h>
+
+int main(void)
+{
+       /*
+        * This function is guarded via: __nonnull_attribute__ (1, 2).
+        * Passing '1' as arguments value. This code is never executed,
+        * only compiled.
+        */
+       dwfl_thread_getframes((void *) 1, (void *) 1, NULL);
+       return 0;
+}
diff --git a/tools/build/feature/test-libelf-getphdrnum.c b/tools/build/feature/test-libelf-getphdrnum.c
new file mode 100644 (file)
index 0000000..d710459
--- /dev/null
@@ -0,0 +1,8 @@
+#include <libelf.h>
+
+int main(void)
+{
+       size_t dst;
+
+       return elf_getphdrnum(0, &dst);
+}
diff --git a/tools/build/feature/test-libelf-mmap.c b/tools/build/feature/test-libelf-mmap.c
new file mode 100644 (file)
index 0000000..564427d
--- /dev/null
@@ -0,0 +1,8 @@
+#include <libelf.h>
+
+int main(void)
+{
+       Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0);
+
+       return (long)elf;
+}
diff --git a/tools/build/feature/test-libelf.c b/tools/build/feature/test-libelf.c
new file mode 100644 (file)
index 0000000..08db322
--- /dev/null
@@ -0,0 +1,8 @@
+#include <libelf.h>
+
+int main(void)
+{
+       Elf *elf = elf_begin(0, ELF_C_READ, 0);
+
+       return (long)elf;
+}
diff --git a/tools/build/feature/test-libnuma.c b/tools/build/feature/test-libnuma.c
new file mode 100644 (file)
index 0000000..4763d9c
--- /dev/null
@@ -0,0 +1,9 @@
+#include <numa.h>
+#include <numaif.h>
+
+int main(void)
+{
+       numa_available();
+
+       return 0;
+}
diff --git a/tools/build/feature/test-libperl.c b/tools/build/feature/test-libperl.c
new file mode 100644 (file)
index 0000000..8871f6a
--- /dev/null
@@ -0,0 +1,9 @@
+#include <EXTERN.h>
+#include <perl.h>
+
+int main(void)
+{
+       perl_alloc();
+
+       return 0;
+}
diff --git a/tools/build/feature/test-libpython-version.c b/tools/build/feature/test-libpython-version.c
new file mode 100644 (file)
index 0000000..facea12
--- /dev/null
@@ -0,0 +1,10 @@
+#include <Python.h>
+
+#if PY_VERSION_HEX >= 0x03000000
+       #error
+#endif
+
+int main(void)
+{
+       return 0;
+}
diff --git a/tools/build/feature/test-libpython.c b/tools/build/feature/test-libpython.c
new file mode 100644 (file)
index 0000000..b24b28a
--- /dev/null
@@ -0,0 +1,8 @@
+#include <Python.h>
+
+int main(void)
+{
+       Py_Initialize();
+
+       return 0;
+}
diff --git a/tools/build/feature/test-libslang.c b/tools/build/feature/test-libslang.c
new file mode 100644 (file)
index 0000000..22ff22e
--- /dev/null
@@ -0,0 +1,6 @@
+#include <slang.h>
+
+int main(void)
+{
+       return SLsmg_init_smg();
+}
diff --git a/tools/build/feature/test-libunwind-debug-frame.c b/tools/build/feature/test-libunwind-debug-frame.c
new file mode 100644 (file)
index 0000000..0ef8087
--- /dev/null
@@ -0,0 +1,16 @@
+#include <libunwind.h>
+#include <stdlib.h>
+
+extern int
+UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
+                                unw_word_t ip, unw_word_t segbase,
+                                const char *obj_name, unw_word_t start,
+                                unw_word_t end);
+
+#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
+
+int main(void)
+{
+       dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
+       return 0;
+}
diff --git a/tools/build/feature/test-libunwind.c b/tools/build/feature/test-libunwind.c
new file mode 100644 (file)
index 0000000..43b9369
--- /dev/null
@@ -0,0 +1,27 @@
+#include <libunwind.h>
+#include <stdlib.h>
+
+extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
+                                      unw_word_t ip,
+                                      unw_dyn_info_t *di,
+                                      unw_proc_info_t *pi,
+                                      int need_unwind_info, void *arg);
+
+
+#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
+
+static unw_accessors_t accessors;
+
+int main(void)
+{
+       unw_addr_space_t addr_space;
+
+       addr_space = unw_create_addr_space(&accessors, 0);
+       if (addr_space)
+               return 0;
+
+       unw_init_remote(NULL, addr_space, NULL);
+       dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
+
+       return 0;
+}
diff --git a/tools/build/feature/test-lzma.c b/tools/build/feature/test-lzma.c
new file mode 100644 (file)
index 0000000..95adc8c
--- /dev/null
@@ -0,0 +1,10 @@
+#include <lzma.h>
+
+int main(void)
+{
+       lzma_stream strm = LZMA_STREAM_INIT;
+       int ret;
+
+       ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
+       return ret ? -1 : 0;
+}
diff --git a/tools/build/feature/test-pthread-attr-setaffinity-np.c b/tools/build/feature/test-pthread-attr-setaffinity-np.c
new file mode 100644 (file)
index 0000000..fdada5e
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdint.h>
+#include <pthread.h>
+#include <sched.h>
+
+int main(void)
+{
+       int ret = 0;
+       pthread_attr_t thread_attr;
+       cpu_set_t cs;
+
+       pthread_attr_init(&thread_attr);
+       CPU_ZERO(&cs);
+
+       ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cs), &cs);
+
+       return ret;
+}
diff --git a/tools/build/feature/test-stackprotector-all.c b/tools/build/feature/test-stackprotector-all.c
new file mode 100644 (file)
index 0000000..c9f398d
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(void)
+{
+       return puts("hi");
+}
diff --git a/tools/build/feature/test-sync-compare-and-swap.c b/tools/build/feature/test-sync-compare-and-swap.c
new file mode 100644 (file)
index 0000000..c34d4ca
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdint.h>
+
+volatile uint64_t x;
+
+int main(int argc, char *argv[])
+{
+       uint64_t old, new = argc;
+
+       argv = argv;
+       do {
+               old = __sync_val_compare_and_swap(&x, 0, 0);
+       } while (!__sync_bool_compare_and_swap(&x, old, new));
+       return old == new;
+}
diff --git a/tools/build/feature/test-timerfd.c b/tools/build/feature/test-timerfd.c
new file mode 100644 (file)
index 0000000..8c5c083
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * test for timerfd functions used by perf-kvm-stat-live
+ */
+#include <sys/timerfd.h>
+
+int main(void)
+{
+       struct itimerspec new_value;
+
+       int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
+       if (fd < 0)
+               return 1;
+
+       if (timerfd_settime(fd, 0, &new_value, NULL) != 0)
+               return 1;
+
+       return 0;
+}
diff --git a/tools/build/feature/test-zlib.c b/tools/build/feature/test-zlib.c
new file mode 100644 (file)
index 0000000..e111fff
--- /dev/null
@@ -0,0 +1,9 @@
+#include <zlib.h>
+
+int main(void)
+{
+       z_stream zs;
+
+       inflateInit(&zs);
+       return 0;
+}
diff --git a/tools/build/tests/ex/Build b/tools/build/tests/ex/Build
new file mode 100644 (file)
index 0000000..0e6c3e6
--- /dev/null
@@ -0,0 +1,8 @@
+ex-y += ex.o
+ex-y += a.o
+ex-y += b.o
+ex-y += empty/
+
+libex-y += c.o
+libex-y += d.o
+libex-y += arch/
diff --git a/tools/build/tests/ex/Makefile b/tools/build/tests/ex/Makefile
new file mode 100644 (file)
index 0000000..52d2476
--- /dev/null
@@ -0,0 +1,23 @@
+export srctree := ../../../..
+export CC      := gcc
+export LD      := ld
+export AR      := ar
+
+build := -f $(srctree)/tools/build/Makefile.build dir=. obj
+ex: ex-in.o libex-in.o
+       gcc -o $@ $^
+
+ex.%: FORCE
+       make -f $(srctree)/tools/build/Makefile.build dir=. $@
+
+ex-in.o: FORCE
+       make $(build)=ex
+
+libex-in.o: FORCE
+       make $(build)=libex
+
+clean:
+       find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
+       rm -f ex ex.i ex.s
+
+.PHONY: FORCE
diff --git a/tools/build/tests/ex/a.c b/tools/build/tests/ex/a.c
new file mode 100644 (file)
index 0000000..8517627
--- /dev/null
@@ -0,0 +1,5 @@
+
+int a(void)
+{
+       return 0;
+}
diff --git a/tools/build/tests/ex/arch/Build b/tools/build/tests/ex/arch/Build
new file mode 100644 (file)
index 0000000..5550618
--- /dev/null
@@ -0,0 +1,2 @@
+libex-y += e.o
+libex-y += f.o
diff --git a/tools/build/tests/ex/arch/e.c b/tools/build/tests/ex/arch/e.c
new file mode 100644 (file)
index 0000000..beaa4a1
--- /dev/null
@@ -0,0 +1,5 @@
+
+int e(void)
+{
+       return 0;
+}
diff --git a/tools/build/tests/ex/arch/f.c b/tools/build/tests/ex/arch/f.c
new file mode 100644 (file)
index 0000000..7c3e9e9
--- /dev/null
@@ -0,0 +1,5 @@
+
+int f(void)
+{
+       return 0;
+}
diff --git a/tools/build/tests/ex/b.c b/tools/build/tests/ex/b.c
new file mode 100644 (file)
index 0000000..c24ff9c
--- /dev/null
@@ -0,0 +1,5 @@
+
+int b(void)
+{
+       return 0;
+}
diff --git a/tools/build/tests/ex/c.c b/tools/build/tests/ex/c.c
new file mode 100644 (file)
index 0000000..e216d02
--- /dev/null
@@ -0,0 +1,5 @@
+
+int c(void)
+{
+       return 0;
+}
diff --git a/tools/build/tests/ex/d.c b/tools/build/tests/ex/d.c
new file mode 100644 (file)
index 0000000..80dc0f0
--- /dev/null
@@ -0,0 +1,5 @@
+
+int d(void)
+{
+       return 0;
+}
diff --git a/tools/build/tests/ex/empty/Build b/tools/build/tests/ex/empty/Build
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/build/tests/ex/ex.c b/tools/build/tests/ex/ex.c
new file mode 100644 (file)
index 0000000..dc42eb2
--- /dev/null
@@ -0,0 +1,19 @@
+
+int a(void);
+int b(void);
+int c(void);
+int d(void);
+int e(void);
+int f(void);
+
+int main(void)
+{
+       a();
+       b();
+       c();
+       d();
+       e();
+       f();
+
+       return 0;
+}
diff --git a/tools/build/tests/run.sh b/tools/build/tests/run.sh
new file mode 100755 (executable)
index 0000000..5494f8e
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+function test_ex {
+       make -C ex V=1 clean > ex.out 2>&1
+       make -C ex V=1 >> ex.out 2>&1
+
+       if [ ! -x ./ex/ex ]; then
+         echo FAILED
+         exit -1
+       fi
+
+       make -C ex V=1 clean > /dev/null 2>&1
+       rm -f ex.out
+}
+
+function test_ex_suffix {
+       make -C ex V=1 clean > ex.out 2>&1
+
+       # use -rR to disable make's builtin rules
+       make -rR -C ex V=1 ex.o >> ex.out 2>&1
+       make -rR -C ex V=1 ex.i >> ex.out 2>&1
+       make -rR -C ex V=1 ex.s >> ex.out 2>&1
+
+       if [ -x ./ex/ex ]; then
+         echo FAILED
+         exit -1
+       fi
+
+       if [ ! -f ./ex/ex.o -o ! -f ./ex/ex.i -o ! -f ./ex/ex.s ]; then
+         echo FAILED
+         exit -1
+       fi
+
+       make -C ex V=1 clean > /dev/null 2>&1
+       rm -f ex.out
+}
+echo -n Testing..
+
+test_ex
+test_ex_suffix
+
+echo OK
diff --git a/tools/iio/Makefile b/tools/iio/Makefile
new file mode 100644 (file)
index 0000000..bf7ae6d
--- /dev/null
@@ -0,0 +1,16 @@
+CC = gcc
+CFLAGS = -Wall -g -D_GNU_SOURCE
+
+all: iio_event_monitor lsiio generic_buffer
+
+iio_event_monitor: iio_event_monitor.o iio_utils.o
+
+lsiio: lsiio.o iio_utils.o
+
+generic_buffer: generic_buffer.o iio_utils.o
+
+%.o: %.c iio_utils.h
+
+.PHONY: clean
+clean:
+       rm -f *.o iio_event_monitor lsiio generic_buffer
diff --git a/tools/iio/generic_buffer.c b/tools/iio/generic_buffer.c
new file mode 100644 (file)
index 0000000..f805493
--- /dev/null
@@ -0,0 +1,359 @@
+/* Industrialio buffer test code.
+ *
+ * Copyright (c) 2008 Jonathan Cameron
+ *
+ * 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 primarily intended as an example application.
+ * Reads the current buffer setup from sysfs and starts a short capture
+ * from the specified device, pretty printing the result after appropriate
+ * conversion.
+ *
+ * Command line parameters
+ * generic_buffer -n <device_name> -t <trigger_name>
+ * If trigger name is not specified the program assumes you want a dataready
+ * trigger associated with the device and goes looking for it.
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include <linux/types.h>
+#include <string.h>
+#include <poll.h>
+#include <endian.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include "iio_utils.h"
+
+/**
+ * size_from_channelarray() - calculate the storage size of a scan
+ * @channels:          the channel info array
+ * @num_channels:      number of channels
+ *
+ * Has the side effect of filling the channels[i].location values used
+ * in processing the buffer output.
+ **/
+int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
+{
+       int bytes = 0;
+       int i = 0;
+
+       while (i < num_channels) {
+               if (bytes % channels[i].bytes == 0)
+                       channels[i].location = bytes;
+               else
+                       channels[i].location = bytes - bytes%channels[i].bytes
+                               + channels[i].bytes;
+               bytes = channels[i].location + channels[i].bytes;
+               i++;
+       }
+       return bytes;
+}
+
+void print2byte(int input, struct iio_channel_info *info)
+{
+       /* First swap if incorrect endian */
+       if (info->be)
+               input = be16toh((uint16_t)input);
+       else
+               input = le16toh((uint16_t)input);
+
+       /*
+        * Shift before conversion to avoid sign extension
+        * of left aligned data
+        */
+       input >>= info->shift;
+       if (info->is_signed) {
+               int16_t val = input;
+
+               val &= (1 << info->bits_used) - 1;
+               val = (int16_t)(val << (16 - info->bits_used)) >>
+                       (16 - info->bits_used);
+               printf("%05f ", ((float)val + info->offset)*info->scale);
+       } else {
+               uint16_t val = input;
+
+               val &= (1 << info->bits_used) - 1;
+               printf("%05f ", ((float)val + info->offset)*info->scale);
+       }
+}
+/**
+ * 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.
+ * @num_channels:      number of channels
+ **/
+void process_scan(char *data,
+                 struct iio_channel_info *channels,
+                 int num_channels)
+{
+       int k;
+
+       for (k = 0; k < num_channels; k++)
+               switch (channels[k].bytes) {
+                       /* only a few cases implemented so far */
+               case 2:
+                       print2byte(*(uint16_t *)(data + channels[k].location),
+                                  &channels[k]);
+                       break;
+               case 4:
+                       if (!channels[k].is_signed) {
+                               uint32_t val = *(uint32_t *)
+                                       (data + channels[k].location);
+                               printf("%05f ", ((float)val +
+                                                channels[k].offset)*
+                                      channels[k].scale);
+
+                       }
+                       break;
+               case 8:
+                       if (channels[k].is_signed) {
+                               int64_t val = *(int64_t *)
+                                       (data +
+                                        channels[k].location);
+                               if ((val >> channels[k].bits_used) & 1)
+                                       val = (val & channels[k].mask) |
+                                               ~channels[k].mask;
+                               /* special case for timestamp */
+                               if (channels[k].scale == 1.0f &&
+                                   channels[k].offset == 0.0f)
+                                       printf("%" PRId64 " ", val);
+                               else
+                                       printf("%05f ", ((float)val +
+                                                        channels[k].offset)*
+                                              channels[k].scale);
+                       }
+                       break;
+               default:
+                       break;
+               }
+       printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+       unsigned long num_loops = 2;
+       unsigned long timedelay = 1000000;
+       unsigned long buf_len = 128;
+
+       int ret, c, i, j, toread;
+       int fp;
+
+       int num_channels;
+       char *trigger_name = NULL, *device_name = NULL;
+       char *dev_dir_name, *buf_dir_name;
+
+       int datardytrigger = 1;
+       char *data;
+       ssize_t read_size;
+       int dev_num, trig_num;
+       char *buffer_access;
+       int scan_size;
+       int noevents = 0;
+       int notrigger = 0;
+       char *dummy;
+
+       struct iio_channel_info *channels;
+
+       while ((c = getopt(argc, argv, "l:w:c:et:n:g")) != -1) {
+               switch (c) {
+               case 'n':
+                       device_name = optarg;
+                       break;
+               case 't':
+                       trigger_name = optarg;
+                       datardytrigger = 0;
+                       break;
+               case 'e':
+                       noevents = 1;
+                       break;
+               case 'c':
+                       num_loops = strtoul(optarg, &dummy, 10);
+                       break;
+               case 'w':
+                       timedelay = strtoul(optarg, &dummy, 10);
+                       break;
+               case 'l':
+                       buf_len = strtoul(optarg, &dummy, 10);
+                       break;
+               case 'g':
+                       notrigger = 1;
+                       break;
+               case '?':
+                       return -1;
+               }
+       }
+
+       if (device_name == NULL)
+               return -1;
+
+       /* 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);
+               ret = -ENODEV;
+               goto error_ret;
+       }
+       printf("iio device number being used is %d\n", dev_num);
+
+       asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
+
+       if (!notrigger) {
+               if (trigger_name == NULL) {
+                       /*
+                        * Build the trigger name. If it is device associated
+                        * its name is <device_name>_dev[n] where n matches
+                        * the device number found above.
+                        */
+                       ret = asprintf(&trigger_name,
+                                      "%s-dev%d", device_name, dev_num);
+                       if (ret < 0) {
+                               ret = -ENOMEM;
+                               goto error_ret;
+                       }
+               }
+
+               /* 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);
+                       ret = -ENODEV;
+                       goto error_free_triggername;
+               }
+               printf("iio trigger number being used is %d\n", trig_num);
+       } else
+               printf("trigger-less mode selected\n");
+
+       /*
+        * Parse the files in scan_elements to identify what channels are
+        * present
+        */
+       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);
+               goto error_free_triggername;
+       }
+
+       /*
+        * Construct the directory name for the associated buffer.
+        * As we know that the lis3l02dq has only one buffer this may
+        * be built rather than found.
+        */
+       ret = asprintf(&buf_dir_name,
+                      "%siio:device%d/buffer", iio_dir, dev_num);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_free_triggername;
+       }
+
+       if (!notrigger) {
+               printf("%s %s\n", dev_dir_name, trigger_name);
+               /* 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");
+                       goto error_free_buf_dir_name;
+               }
+       }
+
+       /* Setup ring buffer parameters */
+       ret = write_sysfs_int("length", buf_dir_name, buf_len);
+       if (ret < 0)
+               goto error_free_buf_dir_name;
+
+       /* Enable the buffer */
+       ret = write_sysfs_int("enable", buf_dir_name, 1);
+       if (ret < 0)
+               goto error_free_buf_dir_name;
+       scan_size = size_from_channelarray(channels, num_channels);
+       data = malloc(scan_size*buf_len);
+       if (!data) {
+               ret = -ENOMEM;
+               goto error_free_buf_dir_name;
+       }
+
+       ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_free_data;
+       }
+
+       /* 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 */
+               printf("Failed to open %s\n", buffer_access);
+               ret = -errno;
+               goto error_free_buffer_access;
+       }
+
+       /* Wait for events 10 times */
+       for (j = 0; j < num_loops; j++) {
+               if (!noevents) {
+                       struct pollfd pfd = {
+                               .fd = fp,
+                               .events = POLLIN,
+                       };
+
+                       poll(&pfd, 1, -1);
+                       toread = buf_len;
+
+               } else {
+                       usleep(timedelay);
+                       toread = 64;
+               }
+
+               read_size = read(fp,
+                                data,
+                                toread*scan_size);
+               if (read_size < 0) {
+                       if (errno == -EAGAIN) {
+                               printf("nothing available\n");
+                               continue;
+                       } else
+                               break;
+               }
+               for (i = 0; i < read_size/scan_size; i++)
+                       process_scan(data + scan_size*i,
+                                    channels,
+                                    num_channels);
+       }
+
+       /* Stop the buffer */
+       ret = write_sysfs_int("enable", buf_dir_name, 0);
+       if (ret < 0)
+               goto error_close_buffer_access;
+
+       if (!notrigger)
+               /* Disconnect the trigger - just write a dummy name. */
+               write_sysfs_string("trigger/current_trigger",
+                                  dev_dir_name, "NULL");
+
+error_close_buffer_access:
+       close(fp);
+error_free_data:
+       free(data);
+error_free_buffer_access:
+       free(buffer_access);
+error_free_buf_dir_name:
+       free(buf_dir_name);
+error_free_triggername:
+       if (datardytrigger)
+               free(trigger_name);
+error_ret:
+       return ret;
+}
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
new file mode 100644 (file)
index 0000000..427c271
--- /dev/null
@@ -0,0 +1,308 @@
+/* Industrialio event test code.
+ *
+ * Copyright (c) 2011-2012 Lars-Peter Clausen <lars@metafoo.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.
+ *
+ * This program is primarily intended as an example application.
+ * Reads the current buffer setup from sysfs and starts a short capture
+ * from the specified device, pretty printing the result after appropriate
+ * conversion.
+ *
+ * Usage:
+ *     iio_event_monitor <device_name>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "iio_utils.h"
+#include <linux/iio/events.h>
+#include <linux/iio/types.h>
+
+static const char * const iio_chan_type_name_spec[] = {
+       [IIO_VOLTAGE] = "voltage",
+       [IIO_CURRENT] = "current",
+       [IIO_POWER] = "power",
+       [IIO_ACCEL] = "accel",
+       [IIO_ANGL_VEL] = "anglvel",
+       [IIO_MAGN] = "magn",
+       [IIO_LIGHT] = "illuminance",
+       [IIO_INTENSITY] = "intensity",
+       [IIO_PROXIMITY] = "proximity",
+       [IIO_TEMP] = "temp",
+       [IIO_INCLI] = "incli",
+       [IIO_ROT] = "rot",
+       [IIO_ANGL] = "angl",
+       [IIO_TIMESTAMP] = "timestamp",
+       [IIO_CAPACITANCE] = "capacitance",
+       [IIO_ALTVOLTAGE] = "altvoltage",
+       [IIO_CCT] = "cct",
+       [IIO_PRESSURE] = "pressure",
+       [IIO_HUMIDITYRELATIVE] = "humidityrelative",
+       [IIO_ACTIVITY] = "activity",
+       [IIO_STEPS] = "steps",
+};
+
+static const char * const iio_ev_type_text[] = {
+       [IIO_EV_TYPE_THRESH] = "thresh",
+       [IIO_EV_TYPE_MAG] = "mag",
+       [IIO_EV_TYPE_ROC] = "roc",
+       [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive",
+       [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive",
+       [IIO_EV_TYPE_CHANGE] = "change",
+};
+
+static const char * const iio_ev_dir_text[] = {
+       [IIO_EV_DIR_EITHER] = "either",
+       [IIO_EV_DIR_RISING] = "rising",
+       [IIO_EV_DIR_FALLING] = "falling"
+};
+
+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_LIGHT_BOTH] = "both",
+       [IIO_MOD_LIGHT_IR] = "ir",
+       [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_CLEAR] = "clear",
+       [IIO_MOD_LIGHT_RED] = "red",
+       [IIO_MOD_LIGHT_GREEN] = "green",
+       [IIO_MOD_LIGHT_BLUE] = "blue",
+       [IIO_MOD_QUATERNION] = "quaternion",
+       [IIO_MOD_TEMP_AMBIENT] = "ambient",
+       [IIO_MOD_TEMP_OBJECT] = "object",
+       [IIO_MOD_NORTH_MAGN] = "from_north_magnetic",
+       [IIO_MOD_NORTH_TRUE] = "from_north_true",
+       [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp",
+       [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp",
+       [IIO_MOD_RUNNING] = "running",
+       [IIO_MOD_JOGGING] = "jogging",
+       [IIO_MOD_WALKING] = "walking",
+       [IIO_MOD_STILL] = "still",
+};
+
+static bool event_is_known(struct iio_event_data *event)
+{
+       enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id);
+       enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id);
+       enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id);
+       enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id);
+
+       switch (type) {
+       case IIO_VOLTAGE:
+       case IIO_CURRENT:
+       case IIO_POWER:
+       case IIO_ACCEL:
+       case IIO_ANGL_VEL:
+       case IIO_MAGN:
+       case IIO_LIGHT:
+       case IIO_INTENSITY:
+       case IIO_PROXIMITY:
+       case IIO_TEMP:
+       case IIO_INCLI:
+       case IIO_ROT:
+       case IIO_ANGL:
+       case IIO_TIMESTAMP:
+       case IIO_CAPACITANCE:
+       case IIO_ALTVOLTAGE:
+       case IIO_CCT:
+       case IIO_PRESSURE:
+       case IIO_HUMIDITYRELATIVE:
+       case IIO_ACTIVITY:
+       case IIO_STEPS:
+               break;
+       default:
+               return false;
+       }
+
+       switch (mod) {
+       case IIO_NO_MOD:
+       case IIO_MOD_X:
+       case IIO_MOD_Y:
+       case IIO_MOD_Z:
+       case IIO_MOD_X_AND_Y:
+       case IIO_MOD_X_AND_Z:
+       case IIO_MOD_Y_AND_Z:
+       case IIO_MOD_X_AND_Y_AND_Z:
+       case IIO_MOD_X_OR_Y:
+       case IIO_MOD_X_OR_Z:
+       case IIO_MOD_Y_OR_Z:
+       case IIO_MOD_X_OR_Y_OR_Z:
+       case IIO_MOD_LIGHT_BOTH:
+       case IIO_MOD_LIGHT_IR:
+       case IIO_MOD_ROOT_SUM_SQUARED_X_Y:
+       case IIO_MOD_SUM_SQUARED_X_Y_Z:
+       case IIO_MOD_LIGHT_CLEAR:
+       case IIO_MOD_LIGHT_RED:
+       case IIO_MOD_LIGHT_GREEN:
+       case IIO_MOD_LIGHT_BLUE:
+       case IIO_MOD_QUATERNION:
+       case IIO_MOD_TEMP_AMBIENT:
+       case IIO_MOD_TEMP_OBJECT:
+       case IIO_MOD_NORTH_MAGN:
+       case IIO_MOD_NORTH_TRUE:
+       case IIO_MOD_NORTH_MAGN_TILT_COMP:
+       case IIO_MOD_NORTH_TRUE_TILT_COMP:
+       case IIO_MOD_RUNNING:
+       case IIO_MOD_JOGGING:
+       case IIO_MOD_WALKING:
+       case IIO_MOD_STILL:
+               break;
+       default:
+               return false;
+       }
+
+       switch (ev_type) {
+       case IIO_EV_TYPE_THRESH:
+       case IIO_EV_TYPE_MAG:
+       case IIO_EV_TYPE_ROC:
+       case IIO_EV_TYPE_THRESH_ADAPTIVE:
+       case IIO_EV_TYPE_MAG_ADAPTIVE:
+       case IIO_EV_TYPE_CHANGE:
+               break;
+       default:
+               return false;
+       }
+
+       switch (dir) {
+       case IIO_EV_DIR_EITHER:
+       case IIO_EV_DIR_RISING:
+       case IIO_EV_DIR_FALLING:
+       case IIO_EV_DIR_NONE:
+               break;
+       default:
+               return false;
+       }
+
+       return true;
+}
+
+static void print_event(struct iio_event_data *event)
+{
+       enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id);
+       enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id);
+       enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id);
+       enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id);
+       int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event->id);
+       int chan2 = IIO_EVENT_CODE_EXTRACT_CHAN2(event->id);
+       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);
+               return;
+       }
+
+       printf("Event: time: %lld, ", event->timestamp);
+
+       if (mod != IIO_NO_MOD) {
+               printf("type: %s(%s), ",
+                       iio_chan_type_name_spec[type],
+                       iio_modifier_names[mod]);
+       } else {
+               printf("type: %s, ",
+                       iio_chan_type_name_spec[type]);
+       }
+
+       if (diff && chan >= 0 && chan2 >= 0)
+               printf("channel: %d-%d, ", chan, chan2);
+       else if (chan >= 0)
+               printf("channel: %d, ", chan);
+
+       printf("evtype: %s", iio_ev_type_text[ev_type]);
+
+       if (dir != IIO_EV_DIR_NONE)
+               printf(", direction: %s", iio_ev_dir_text[dir]);
+       printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+       struct iio_event_data event;
+       const char *device_name;
+       char *chrdev_name;
+       int ret;
+       int dev_num;
+       int fd, event_fd;
+
+       if (argc <= 1) {
+               printf("Usage: %s <device_name>\n", argv[0]);
+               return -1;
+       }
+
+       device_name = argv[1];
+
+       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);
+               ret = asprintf(&chrdev_name, "/dev/iio:device%d", dev_num);
+               if (ret < 0) {
+                       ret = -ENOMEM;
+                       goto error_ret;
+               }
+       } else {
+               /* If we can't find a IIO device by name assume device_name is a
+                  IIO chrdev */
+               chrdev_name = strdup(device_name);
+       }
+
+       fd = open(chrdev_name, 0);
+       if (fd == -1) {
+               fprintf(stdout, "Failed to open %s\n", chrdev_name);
+               ret = -errno;
+               goto error_free_chrdev_name;
+       }
+
+       ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd);
+
+       close(fd);
+
+       if (ret == -1 || event_fd == -1) {
+               fprintf(stdout, "Failed to retrieve event fd\n");
+               ret = -errno;
+               goto error_free_chrdev_name;
+       }
+
+       while (true) {
+               ret = read(event_fd, &event, sizeof(event));
+               if (ret == -1) {
+                       if (errno == EAGAIN) {
+                               printf("nothing available\n");
+                               continue;
+                       } else {
+                               perror("Failed to read event from device");
+                               ret = -errno;
+                               break;
+                       }
+               }
+
+               print_event(&event);
+       }
+
+       close(event_fd);
+error_free_chrdev_name:
+       free(chrdev_name);
+error_ret:
+       return ret;
+}
diff --git a/tools/iio/iio_utils.c b/tools/iio/iio_utils.c
new file mode 100644 (file)
index 0000000..6f64521
--- /dev/null
@@ -0,0 +1,669 @@
+/* IIO - useful set of util functionality
+ *
+ * Copyright (c) 2008 Jonathan Cameron
+ *
+ * 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 _IIO_UTILS_H
+#define _IIO_UTILS_H
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <dirent.h>
+#include <errno.h>
+#include <ctype.h>
+#include "iio_utils.h"
+
+const char *iio_dir = "/sys/bus/iio/devices/";
+
+static char * const iio_direction[] = {
+       "in",
+       "out",
+};
+
+/**
+ * iioutils_break_up_name() - extract generic name from full channel name
+ * @full_name: the full channel name
+ * @generic_name: the output generic channel name
+ **/
+int iioutils_break_up_name(const char *full_name,
+                                 char **generic_name)
+{
+       char *current;
+       char *w, *r;
+       char *working, *prefix = "";
+       int i;
+
+       for (i = 0; i < sizeof(iio_direction) / sizeof(iio_direction[0]); i++)
+               if (!strncmp(full_name, iio_direction[i],
+                            strlen(iio_direction[i]))) {
+                       prefix = iio_direction[i];
+                       break;
+               }
+
+       current = strdup(full_name + strlen(prefix) + 1);
+       working = strtok(current, "_\0");
+
+       w = working;
+       r = working;
+
+       while (*r != '\0') {
+               if (!isdigit(*r)) {
+                       *w = *r;
+                       w++;
+               }
+               r++;
+       }
+       *w = '\0';
+       asprintf(generic_name, "%s_%s", prefix, working);
+       free(current);
+
+       return 0;
+}
+
+/**
+ * iioutils_get_type() - find and process _type attribute data
+ * @is_signed: output whether channel is signed
+ * @bytes: output how many bytes the channel storage occupies
+ * @mask: output a bit mask for the raw data
+ * @be: big endian
+ * @device_dir: the iio device directory
+ * @name: the channel name
+ * @generic_name: the channel type 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;
+       DIR *dp;
+       char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
+       char signchar, endianchar;
+       unsigned padint;
+       const struct dirent *ent;
+
+       ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_ret;
+       }
+       ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_free_scan_el_dir;
+       }
+       ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_free_builtname;
+       }
+
+       dp = opendir(scan_el_dir);
+       if (dp == NULL) {
+               ret = -errno;
+               goto error_free_builtname_generic;
+       }
+       while (ent = readdir(dp), ent != NULL)
+               /*
+                * Do we allow devices to override a generic name with
+                * a specific one?
+                */
+               if ((strcmp(builtname, ent->d_name) == 0) ||
+                   (strcmp(builtname_generic, ent->d_name) == 0)) {
+                       ret = asprintf(&filename,
+                                      "%s/%s", scan_el_dir, ent->d_name);
+                       if (ret < 0) {
+                               ret = -ENOMEM;
+                               goto error_closedir;
+                       }
+                       sysfsfp = fopen(filename, "r");
+                       if (sysfsfp == NULL) {
+                               printf("failed to open %s\n", filename);
+                               ret = -errno;
+                               goto error_free_filename;
+                       }
+
+                       ret = fscanf(sysfsfp,
+                                    "%ce:%c%u/%u>>%u",
+                                    &endianchar,
+                                    &signchar,
+                                    bits_used,
+                                    &padint, shift);
+                       if (ret < 0) {
+                               printf("failed to pass scan type description\n");
+                               ret = -errno;
+                               goto error_close_sysfsfp;
+                       }
+                       *be = (endianchar == 'b');
+                       *bytes = padint / 8;
+                       if (*bits_used == 64)
+                               *mask = ~0;
+                       else
+                               *mask = (1 << *bits_used) - 1;
+                       if (signchar == 's')
+                               *is_signed = 1;
+                       else
+                               *is_signed = 0;
+                       fclose(sysfsfp);
+                       free(filename);
+
+                       filename = 0;
+                       sysfsfp = 0;
+               }
+error_close_sysfsfp:
+       if (sysfsfp)
+               fclose(sysfsfp);
+error_free_filename:
+       if (filename)
+               free(filename);
+error_closedir:
+       closedir(dp);
+error_free_builtname_generic:
+       free(builtname_generic);
+error_free_builtname:
+       free(builtname);
+error_free_scan_el_dir:
+       free(scan_el_dir);
+error_ret:
+       return ret;
+}
+
+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;
+       DIR *dp;
+       char *builtname, *builtname_generic;
+       char *filename = NULL;
+       const struct dirent *ent;
+
+       ret = asprintf(&builtname, "%s_%s", name, param_name);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_ret;
+       }
+       ret = asprintf(&builtname_generic,
+                      "%s_%s", generic_name, param_name);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_free_builtname;
+       }
+       dp = opendir(device_dir);
+       if (dp == NULL) {
+               ret = -errno;
+               goto error_free_builtname_generic;
+       }
+       while (ent = readdir(dp), ent != NULL)
+               if ((strcmp(builtname, ent->d_name) == 0) ||
+                   (strcmp(builtname_generic, ent->d_name) == 0)) {
+                       ret = asprintf(&filename,
+                                      "%s/%s", device_dir, ent->d_name);
+                       if (ret < 0) {
+                               ret = -ENOMEM;
+                               goto error_closedir;
+                       }
+                       sysfsfp = fopen(filename, "r");
+                       if (!sysfsfp) {
+                               ret = -errno;
+                               goto error_free_filename;
+                       }
+                       fscanf(sysfsfp, "%f", output);
+                       break;
+               }
+error_free_filename:
+       if (filename)
+               free(filename);
+error_closedir:
+       closedir(dp);
+error_free_builtname_generic:
+       free(builtname_generic);
+error_free_builtname:
+       free(builtname);
+error_ret:
+       return ret;
+}
+
+/**
+ * bsort_channel_array_by_index() - reorder so that the array is in index order
+ *
+ **/
+
+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;
+                       }
+}
+
+/**
+ * build_channel_array() - function to figure out what channels are present
+ * @device_dir: the IIO device directory in sysfs
+ * @
+ **/
+int build_channel_array(const char *device_dir,
+                             struct iio_channel_info **ci_array,
+                             int *counter)
+{
+       DIR *dp;
+       FILE *sysfsfp;
+       int count, i;
+       struct iio_channel_info *current;
+       int ret;
+       const struct dirent *ent;
+       char *scan_el_dir;
+       char *filename;
+
+       *counter = 0;
+       ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
+       if (ret < 0) {
+               ret = -ENOMEM;
+               goto error_ret;
+       }
+       dp = opendir(scan_el_dir);
+       if (dp == NULL) {
+               ret = -errno;
+               goto error_free_name;
+       }
+       while (ent = readdir(dp), ent != NULL)
+               if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
+                          "_en") == 0) {
+                       ret = asprintf(&filename,
+                                      "%s/%s", scan_el_dir, ent->d_name);
+                       if (ret < 0) {
+                               ret = -ENOMEM;
+                               goto error_close_dir;
+                       }
+                       sysfsfp = fopen(filename, "r");
+                       if (sysfsfp == NULL) {
+                               ret = -errno;
+                               free(filename);
+                               goto error_close_dir;
+                       }
+                       fscanf(sysfsfp, "%i", &ret);
+                       if (ret == 1)
+                               (*counter)++;
+                       fclose(sysfsfp);
+                       free(filename);
+               }
+       *ci_array = malloc(sizeof(**ci_array) * (*counter));
+       if (*ci_array == NULL) {
+               ret = -ENOMEM;
+               goto error_close_dir;
+       }
+       seekdir(dp, 0);
+       count = 0;
+       while (ent = readdir(dp), ent != NULL) {
+               if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
+                          "_en") == 0) {
+                       int current_enabled = 0;
+
+                       current = &(*ci_array)[count++];
+                       ret = asprintf(&filename,
+                                      "%s/%s", scan_el_dir, ent->d_name);
+                       if (ret < 0) {
+                               ret = -ENOMEM;
+                               /* decrement count to avoid freeing name */
+                               count--;
+                               goto error_cleanup_array;
+                       }
+                       sysfsfp = fopen(filename, "r");
+                       if (sysfsfp == NULL) {
+                               free(filename);
+                               ret = -errno;
+                               goto error_cleanup_array;
+                       }
+                       fscanf(sysfsfp, "%i", &current_enabled);
+                       fclose(sysfsfp);
+
+                       if (!current_enabled) {
+                               free(filename);
+                               count--;
+                               continue;
+                       }
+
+                       current->scale = 1.0;
+                       current->offset = 0;
+                       current->name = strndup(ent->d_name,
+                                               strlen(ent->d_name) -
+                                               strlen("_en"));
+                       if (current->name == NULL) {
+                               free(filename);
+                               ret = -ENOMEM;
+                               goto error_cleanup_array;
+                       }
+                       /* Get the generic and specific name elements */
+                       ret = iioutils_break_up_name(current->name,
+                                                    &current->generic_name);
+                       if (ret) {
+                               free(filename);
+                               goto error_cleanup_array;
+                       }
+                       ret = asprintf(&filename,
+                                      "%s/%s_index",
+                                      scan_el_dir,
+                                      current->name);
+                       if (ret < 0) {
+                               free(filename);
+                               ret = -ENOMEM;
+                               goto error_cleanup_array;
+                       }
+                       sysfsfp = fopen(filename, "r");
+                       fscanf(sysfsfp, "%u", &current->index);
+                       fclose(sysfsfp);
+                       free(filename);
+                       /* Find the scale */
+                       ret = iioutils_get_param_float(&current->scale,
+                                                      "scale",
+                                                      device_dir,
+                                                      current->name,
+                                                      current->generic_name);
+                       if (ret < 0)
+                               goto error_cleanup_array;
+                       ret = iioutils_get_param_float(&current->offset,
+                                                      "offset",
+                                                      device_dir,
+                                                      current->name,
+                                                      current->generic_name);
+                       if (ret < 0)
+                               goto error_cleanup_array;
+                       ret = iioutils_get_type(&current->is_signed,
+                                               &current->bytes,
+                                               &current->bits_used,
+                                               &current->shift,
+                                               &current->mask,
+                                               &current->be,
+                                               device_dir,
+                                               current->name,
+                                               current->generic_name);
+               }
+       }
+
+       closedir(dp);
+       /* reorder so that the array is in index order */
+       bsort_channel_array_by_index(ci_array, *counter);
+
+       return 0;
+
+error_cleanup_array:
+       for (i = count - 1;  i >= 0; i--)
+               free((*ci_array)[i].name);
+       free(*ci_array);
+error_close_dir:
+       closedir(dp);
+error_free_name:
+       free(scan_el_dir);
+error_ret:
+       return ret;
+}
+
+/**
+ * find_type_by_name() - function to match top level types by name
+ * @name: top level type instance name
+ * @type: the type of top level instance being sort
+ *
+ * Typical types this is used for are device and trigger.
+ **/
+int find_type_by_name(const char *name, const char *type)
+{
+       const struct dirent *ent;
+       int number, numstrlen;
+
+       FILE *nameFile;
+       DIR *dp;
+       char thisname[IIO_MAX_NAME_LENGTH];
+       char *filename;
+
+       dp = opendir(iio_dir);
+       if (dp == NULL) {
+               printf("No industrialio devices available\n");
+               return -ENODEV;
+       }
+
+       while (ent = readdir(dp), ent != NULL) {
+               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) {
+                       numstrlen = sscanf(ent->d_name + strlen(type),
+                                          "%d",
+                                          &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) {
+                                       closedir(dp);
+                                       return -ENOMEM;
+                               }
+                               sprintf(filename, "%s%s%d/name",
+                                       iio_dir,
+                                       type,
+                                       number);
+                               nameFile = fopen(filename, "r");
+                               if (!nameFile) {
+                                       free(filename);
+                                       continue;
+                               }
+                               free(filename);
+                               fscanf(nameFile, "%s", thisname);
+                               fclose(nameFile);
+                               if (strcmp(name, thisname) == 0) {
+                                       closedir(dp);
+                                       return number;
+                               }
+                       }
+               }
+       }
+       closedir(dp);
+       return -ENODEV;
+}
+
+int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
+{
+       int ret = 0;
+       FILE *sysfsfp;
+       int test;
+       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+
+       if (temp == NULL)
+               return -ENOMEM;
+       sprintf(temp, "%s/%s", basedir, filename);
+       sysfsfp = fopen(temp, "w");
+       if (sysfsfp == NULL) {
+               printf("failed to open %s\n", temp);
+               ret = -errno;
+               goto error_free;
+       }
+       fprintf(sysfsfp, "%d", val);
+       fclose(sysfsfp);
+       if (verify) {
+               sysfsfp = fopen(temp, "r");
+               if (sysfsfp == NULL) {
+                       printf("failed to open %s\n", temp);
+                       ret = -errno;
+                       goto error_free;
+               }
+               fscanf(sysfsfp, "%d", &test);
+               fclose(sysfsfp);
+               if (test != val) {
+                       printf("Possible failure in int write %d to %s%s\n",
+                               val,
+                               basedir,
+                               filename);
+                       ret = -1;
+               }
+       }
+error_free:
+       free(temp);
+       return ret;
+}
+
+int write_sysfs_int(char *filename, char *basedir, int val)
+{
+       return _write_sysfs_int(filename, basedir, val, 0);
+}
+
+int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
+{
+       return _write_sysfs_int(filename, basedir, val, 1);
+}
+
+int _write_sysfs_string(char *filename, char *basedir, char *val, int verify)
+{
+       int ret = 0;
+       FILE  *sysfsfp;
+       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+
+       if (temp == NULL) {
+               printf("Memory allocation failed\n");
+               return -ENOMEM;
+       }
+       sprintf(temp, "%s/%s", basedir, filename);
+       sysfsfp = fopen(temp, "w");
+       if (sysfsfp == NULL) {
+               printf("Could not open %s\n", temp);
+               ret = -errno;
+               goto error_free;
+       }
+       fprintf(sysfsfp, "%s", val);
+       fclose(sysfsfp);
+       if (verify) {
+               sysfsfp = fopen(temp, "r");
+               if (sysfsfp == NULL) {
+                       printf("could not open file to verify\n");
+                       ret = -errno;
+                       goto error_free;
+               }
+               fscanf(sysfsfp, "%s", temp);
+               fclose(sysfsfp);
+               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);
+                       ret = -1;
+               }
+       }
+error_free:
+       free(temp);
+
+       return ret;
+}
+
+/**
+ * write_sysfs_string_and_verify() - string write, readback and verify
+ * @filename: name of file to write to
+ * @basedir: the sysfs directory in which the file is to be found
+ * @val: the string to write
+ **/
+int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
+{
+       return _write_sysfs_string(filename, basedir, val, 1);
+}
+
+int write_sysfs_string(char *filename, char *basedir, char *val)
+{
+       return _write_sysfs_string(filename, basedir, val, 0);
+}
+
+int read_sysfs_posint(char *filename, char *basedir)
+{
+       int ret;
+       FILE  *sysfsfp;
+       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+
+       if (temp == NULL) {
+               printf("Memory allocation failed");
+               return -ENOMEM;
+       }
+       sprintf(temp, "%s/%s", basedir, filename);
+       sysfsfp = fopen(temp, "r");
+       if (sysfsfp == NULL) {
+               ret = -errno;
+               goto error_free;
+       }
+       fscanf(sysfsfp, "%d\n", &ret);
+       fclose(sysfsfp);
+error_free:
+       free(temp);
+       return ret;
+}
+
+int read_sysfs_float(char *filename, char *basedir, float *val)
+{
+       int ret = 0;
+       FILE  *sysfsfp;
+       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+
+       if (temp == NULL) {
+               printf("Memory allocation failed");
+               return -ENOMEM;
+       }
+       sprintf(temp, "%s/%s", basedir, filename);
+       sysfsfp = fopen(temp, "r");
+       if (sysfsfp == NULL) {
+               ret = -errno;
+               goto error_free;
+       }
+       fscanf(sysfsfp, "%f\n", val);
+       fclose(sysfsfp);
+error_free:
+       free(temp);
+       return ret;
+}
+
+int read_sysfs_string(const char *filename, const char *basedir, char *str)
+{
+       int ret = 0;
+       FILE  *sysfsfp;
+       char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
+
+       if (temp == NULL) {
+               printf("Memory allocation failed");
+               return -ENOMEM;
+       }
+       sprintf(temp, "%s/%s", basedir, filename);
+       sysfsfp = fopen(temp, "r");
+       if (sysfsfp == NULL) {
+               ret = -errno;
+               goto error_free;
+       }
+       fscanf(sysfsfp, "%s\n", str);
+       fclose(sysfsfp);
+error_free:
+       free(temp);
+       return ret;
+}
+
+#endif /* _IIO_UTILS_H */
diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h
new file mode 100644 (file)
index 0000000..1bc837b
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef _IIO_UTILS_H_
+#define _IIO_UTILS_H_
+
+/* IIO - useful set of util functionality
+ *
+ * Copyright (c) 2008 Jonathan Cameron
+ *
+ * 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 <stdint.h>
+
+/* Made up value to limit allocation sizes */
+#define IIO_MAX_NAME_LENGTH 30
+
+#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
+#define FORMAT_TYPE_FILE "%s_type"
+
+extern const char *iio_dir;
+
+/**
+ * struct iio_channel_info - information about a given channel
+ * @name: channel name
+ * @generic_name: general name for channel type
+ * @scale: scale factor to be applied for conversion to si units
+ * @offset: offset to be applied for conversion to si units
+ * @index: the channel index in the buffer output
+ * @bytes: number of bytes occupied in buffer output
+ * @mask: a bit mask for the raw output
+ * @is_signed: is the raw value stored signed
+ * @enabled: is this channel enabled
+ **/
+struct iio_channel_info {
+       char *name;
+       char *generic_name;
+       float scale;
+       float offset;
+       unsigned index;
+       unsigned bytes;
+       unsigned bits_used;
+       unsigned shift;
+       uint64_t mask;
+       unsigned be;
+       unsigned is_signed;
+       unsigned location;
+};
+
+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_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);
+int build_channel_array(const char *device_dir,
+                                               struct iio_channel_info **ci_array, int *counter);
+int find_type_by_name(const char *name, const char *type);
+int write_sysfs_int(char *filename, char *basedir, int val);
+int write_sysfs_int_and_verify(char *filename, char *basedir, int val);
+int write_sysfs_string_and_verify(char *filename, char *basedir, char *val);
+int write_sysfs_string(char *filename, char *basedir, char *val);
+int read_sysfs_posint(char *filename, char *basedir);
+int read_sysfs_float(char *filename, char *basedir, float *val);
+int read_sysfs_string(const char *filename, const char *basedir, char *str);
+
+#endif /* _IIO_UTILS_H_ */
diff --git a/tools/iio/lsiio.c b/tools/iio/lsiio.c
new file mode 100644 (file)
index 0000000..c585440
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Industrial I/O utilities - lsiio.c
+ *
+ * Copyright (c) 2010 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <string.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include "iio_utils.h"
+
+
+static enum verbosity {
+       VERBLEVEL_DEFAULT,      /* 0 gives lspci behaviour */
+       VERBLEVEL_SENSORS,      /* 1 lists sensors */
+} verblevel = VERBLEVEL_DEFAULT;
+
+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;
+}
+
+static inline int check_postfix(const char *str, const char *postfix)
+{
+       return strlen(str) > strlen(postfix) &&
+               strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
+}
+
+static int dump_channels(const char *dev_dir_name)
+{
+       DIR *dp;
+       const struct dirent *ent;
+
+       dp = opendir(dev_dir_name);
+       if (dp == NULL)
+               return -errno;
+       while (ent = readdir(dp), ent != NULL)
+               if (check_prefix(ent->d_name, "in_") &&
+                   check_postfix(ent->d_name, "_raw")) {
+                       printf("   %-10s\n", ent->d_name);
+               }
+
+       return 0;
+}
+
+static int dump_one_device(const char *dev_dir_name)
+{
+       char name[IIO_MAX_NAME_LENGTH];
+       int dev_idx;
+       int retval;
+
+       retval = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device),
+                       "%i", &dev_idx);
+       if (retval != 1)
+               return -EINVAL;
+       read_sysfs_string("name", dev_dir_name, name);
+       printf("Device %03d: %s\n", dev_idx, name);
+
+       if (verblevel >= VERBLEVEL_SENSORS)
+               return dump_channels(dev_dir_name);
+       return 0;
+}
+
+static int dump_one_trigger(const char *dev_dir_name)
+{
+       char name[IIO_MAX_NAME_LENGTH];
+       int dev_idx;
+       int retval;
+
+       retval = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger),
+                       "%i", &dev_idx);
+       if (retval != 1)
+               return -EINVAL;
+       read_sysfs_string("name", dev_dir_name, name);
+       printf("Trigger %03d: %s\n", dev_idx, name);
+       return 0;
+}
+
+static void dump_devices(void)
+{
+       const struct dirent *ent;
+       DIR *dp;
+
+       dp = opendir(iio_dir);
+       if (dp == NULL) {
+               printf("No industrial I/O devices available\n");
+               return;
+       }
+
+       while (ent = readdir(dp), ent != NULL) {
+               if (check_prefix(ent->d_name, type_device)) {
+                       char *dev_dir_name;
+
+                       asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name);
+                       dump_one_device(dev_dir_name);
+                       free(dev_dir_name);
+                       if (verblevel >= VERBLEVEL_SENSORS)
+                               printf("\n");
+               }
+       }
+       rewinddir(dp);
+       while (ent = readdir(dp), ent != NULL) {
+               if (check_prefix(ent->d_name, type_trigger)) {
+                       char *dev_dir_name;
+
+                       asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name);
+                       dump_one_trigger(dev_dir_name);
+                       free(dev_dir_name);
+               }
+       }
+       closedir(dp);
+}
+
+int main(int argc, char **argv)
+{
+       int c, err = 0;
+
+       while ((c = getopt(argc, argv, "d:D:v")) != EOF) {
+               switch (c) {
+               case 'v':
+                       verblevel++;
+                       break;
+
+               case '?':
+               default:
+                       err++;
+                       break;
+               }
+       }
+       if (err || argc > optind) {
+               fprintf(stderr, "Usage: lsiio [options]...\n"
+                       "List industrial I/O devices\n"
+                       "  -v, --verbose\n"
+                       "      Increase verbosity (may be given multiple times)\n"
+                       );
+               exit(1);
+       }
+
+       dump_devices();
+
+       return 0;
+}
diff --git a/tools/lib/api/Build b/tools/lib/api/Build
new file mode 100644 (file)
index 0000000..3653965
--- /dev/null
@@ -0,0 +1,2 @@
+libapi-y += fd/
+libapi-y += fs/
index 36c08b1f4afbc9379007c3b49e79fb5f87a3f1c9..d8fe29fc19a41de308141fac73ce05dc80388f39 100644 (file)
@@ -1,49 +1,43 @@
 include ../../scripts/Makefile.include
 include ../../perf/config/utilities.mak                # QUIET_CLEAN
 
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
 CC = $(CROSS_COMPILE)gcc
 AR = $(CROSS_COMPILE)ar
 
-# guard against environment variables
-LIB_H=
-LIB_OBJS=
-
-LIB_H += fs/debugfs.h
-LIB_H += fs/fs.h
-# See comment below about piggybacking...
-LIB_H += fd/array.h
-
-LIB_OBJS += $(OUTPUT)fs/debugfs.o
-LIB_OBJS += $(OUTPUT)fs/fs.o
-# XXX piggybacking here, need to introduce libapikfd, or rename this
-# to plain libapik.a and make it have it all api goodies
-LIB_OBJS += $(OUTPUT)fd/array.o
+MAKEFLAGS += --no-print-directory
 
-LIBFILE = libapikfs.a
+LIBFILE = $(OUTPUT)libapi.a
 
-CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC
-EXTLIBS = -lelf -lpthread -lrt -lm
-ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-ALL_LDFLAGS = $(LDFLAGS)
+CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
+CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 -fPIC
+CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
 
 RM = rm -f
 
-$(LIBFILE): $(LIB_OBJS)
-       $(QUIET_AR)$(RM) $@ && $(AR) rcs $(OUTPUT)$@ $(LIB_OBJS)
+build  := -f $(srctree)/tools/build/Makefile.build dir=. obj
+API_IN := $(OUTPUT)libapi-in.o
 
-$(LIB_OBJS): $(LIB_H)
+export srctree OUTPUT CC LD CFLAGS V
 
-libapi_dirs:
-       $(QUIET_MKDIR)mkdir -p $(OUTPUT)fd $(OUTPUT)fs
+all: $(LIBFILE)
 
-$(OUTPUT)%.o: %.c libapi_dirs
-       $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
-$(OUTPUT)%.s: %.c libapi_dirs
-       $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $<
-$(OUTPUT)%.o: %.S libapi_dirs
-       $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
+$(API_IN): FORCE
+       @$(MAKE) $(build)=libapi
+
+$(LIBFILE): $(API_IN)
+       $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(API_IN)
 
 clean:
-       $(call QUIET_CLEAN, libapi) $(RM) $(LIB_OBJS) $(LIBFILE)
+       $(call QUIET_CLEAN, libapi) $(RM) $(LIBFILE); \
+       find $(if $(OUTPUT),$(OUTPUT),.) -name \*.o | xargs $(RM)
+
+FORCE:
 
-.PHONY: clean
+.PHONY: clean FORCE
diff --git a/tools/lib/api/fd/Build b/tools/lib/api/fd/Build
new file mode 100644 (file)
index 0000000..605d99f
--- /dev/null
@@ -0,0 +1 @@
+libapi-y += array.o
diff --git a/tools/lib/api/fs/Build b/tools/lib/api/fs/Build
new file mode 100644 (file)
index 0000000..6de5a4f
--- /dev/null
@@ -0,0 +1,4 @@
+libapi-y += fs.o
+libapi-y += debugfs.o
+libapi-y += findfs.o
+libapi-y += tracefs.o
index d2b18e88707151551e3f23b4d8f66df6a526b895..8305b3e9d48e29da0152592524af2e364a3b92f9 100644 (file)
@@ -3,75 +3,50 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <stdbool.h>
 #include <sys/vfs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/mount.h>
 #include <linux/kernel.h>
 
 #include "debugfs.h"
 
-char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug";
+#ifndef DEBUGFS_DEFAULT_PATH
+#define DEBUGFS_DEFAULT_PATH           "/sys/kernel/debug"
+#endif
+
+char debugfs_mountpoint[PATH_MAX + 1] = DEBUGFS_DEFAULT_PATH;
 
 static const char * const debugfs_known_mountpoints[] = {
-       "/sys/kernel/debug",
+       DEBUGFS_DEFAULT_PATH,
        "/debug",
        0,
 };
 
 static bool debugfs_found;
 
+bool debugfs_configured(void)
+{
+       return debugfs_find_mountpoint() != NULL;
+}
+
 /* find the path to the mounted debugfs */
 const char *debugfs_find_mountpoint(void)
 {
-       const char * const *ptr;
-       char type[100];
-       FILE *fp;
+       const char *ret;
 
        if (debugfs_found)
                return (const char *)debugfs_mountpoint;
 
-       ptr = debugfs_known_mountpoints;
-       while (*ptr) {
-               if (debugfs_valid_mountpoint(*ptr) == 0) {
-                       debugfs_found = true;
-                       strcpy(debugfs_mountpoint, *ptr);
-                       return debugfs_mountpoint;
-               }
-               ptr++;
-       }
-
-       /* give up and parse /proc/mounts */
-       fp = fopen("/proc/mounts", "r");
-       if (fp == NULL)
-               return NULL;
-
-       while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
-                     debugfs_mountpoint, type) == 2) {
-               if (strcmp(type, "debugfs") == 0)
-                       break;
-       }
-       fclose(fp);
+       ret = find_mountpoint("debugfs", (long) DEBUGFS_MAGIC,
+                             debugfs_mountpoint, PATH_MAX + 1,
+                             debugfs_known_mountpoints);
+       if (ret)
+               debugfs_found = true;
 
-       if (strcmp(type, "debugfs") != 0)
-               return NULL;
-
-       debugfs_found = true;
-
-       return debugfs_mountpoint;
-}
-
-/* verify that a mountpoint is actually a debugfs instance */
-
-int debugfs_valid_mountpoint(const char *debugfs)
-{
-       struct statfs st_fs;
-
-       if (statfs(debugfs, &st_fs) < 0)
-               return -ENOENT;
-       else if ((long)st_fs.f_type != (long)DEBUGFS_MAGIC)
-               return -ENOENT;
-
-       return 0;
+       return ret;
 }
 
 /* mount the debugfs somewhere if it's not mounted */
@@ -87,7 +62,7 @@ char *debugfs_mount(const char *mountpoint)
                mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT);
                /* if no environment variable, use default */
                if (mountpoint == NULL)
-                       mountpoint = "/sys/kernel/debug";
+                       mountpoint = DEBUGFS_DEFAULT_PATH;
        }
 
        if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0)
index 0739881a98977cfcf70f84098b1e876b4a592f67..455023698d2b43770f0de68464b4f244916adca4 100644 (file)
@@ -1,16 +1,7 @@
 #ifndef __API_DEBUGFS_H__
 #define __API_DEBUGFS_H__
 
-#define _STR(x) #x
-#define STR(x) _STR(x)
-
-/*
- * On most systems <limits.h> would have given us this, but  not on some systems
- * (e.g. GNU/Hurd).
- */
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
+#include "findfs.h"
 
 #ifndef DEBUGFS_MAGIC
 #define DEBUGFS_MAGIC          0x64626720
@@ -20,8 +11,8 @@
 #define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
 #endif
 
+bool debugfs_configured(void);
 const char *debugfs_find_mountpoint(void);
-int debugfs_valid_mountpoint(const char *debugfs);
 char *debugfs_mount(const char *mountpoint);
 
 extern char debugfs_mountpoint[];
diff --git a/tools/lib/api/fs/findfs.c b/tools/lib/api/fs/findfs.c
new file mode 100644 (file)
index 0000000..49946cb
--- /dev/null
@@ -0,0 +1,63 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/vfs.h>
+
+#include "findfs.h"
+
+/* verify that a mountpoint is actually the type we want */
+
+int valid_mountpoint(const char *mount, long magic)
+{
+       struct statfs st_fs;
+
+       if (statfs(mount, &st_fs) < 0)
+               return -ENOENT;
+       else if ((long)st_fs.f_type != magic)
+               return -ENOENT;
+
+       return 0;
+}
+
+/* find the path to a mounted file system */
+const char *find_mountpoint(const char *fstype, long magic,
+                           char *mountpoint, int len,
+                           const char * const *known_mountpoints)
+{
+       const char * const *ptr;
+       char format[128];
+       char type[100];
+       FILE *fp;
+
+       if (known_mountpoints) {
+               ptr = known_mountpoints;
+               while (*ptr) {
+                       if (valid_mountpoint(*ptr, magic) == 0) {
+                               strncpy(mountpoint, *ptr, len - 1);
+                               mountpoint[len-1] = 0;
+                               return mountpoint;
+                       }
+                       ptr++;
+               }
+       }
+
+       /* give up and parse /proc/mounts */
+       fp = fopen("/proc/mounts", "r");
+       if (fp == NULL)
+               return NULL;
+
+       snprintf(format, 128, "%%*s %%%ds %%99s %%*s %%*d %%*d\n", len);
+
+       while (fscanf(fp, format, mountpoint, type) == 2) {
+               if (strcmp(type, fstype) == 0)
+                       break;
+       }
+       fclose(fp);
+
+       if (strcmp(type, fstype) != 0)
+               return NULL;
+
+       return mountpoint;
+}
diff --git a/tools/lib/api/fs/findfs.h b/tools/lib/api/fs/findfs.h
new file mode 100644 (file)
index 0000000..b6f5d05
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __API_FINDFS_H__
+#define __API_FINDFS_H__
+
+#include <stdbool.h>
+
+#define _STR(x) #x
+#define STR(x) _STR(x)
+
+/*
+ * On most systems <limits.h> would have given us this, but  not on some systems
+ * (e.g. GNU/Hurd).
+ */
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+const char *find_mountpoint(const char *fstype, long magic,
+                           char *mountpoint, int len,
+                           const char * const *known_mountpoints);
+
+int valid_mountpoint(const char *mount, long magic);
+
+#endif /* __API_FINDFS_H__ */
diff --git a/tools/lib/api/fs/tracefs.c b/tools/lib/api/fs/tracefs.c
new file mode 100644 (file)
index 0000000..e4aa968
--- /dev/null
@@ -0,0 +1,78 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <sys/vfs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <linux/kernel.h>
+
+#include "tracefs.h"
+
+#ifndef TRACEFS_DEFAULT_PATH
+#define TRACEFS_DEFAULT_PATH           "/sys/kernel/tracing"
+#endif
+
+char tracefs_mountpoint[PATH_MAX + 1] = TRACEFS_DEFAULT_PATH;
+
+static const char * const tracefs_known_mountpoints[] = {
+       TRACEFS_DEFAULT_PATH,
+       "/sys/kernel/debug/tracing",
+       "/tracing",
+       "/trace",
+       0,
+};
+
+static bool tracefs_found;
+
+bool tracefs_configured(void)
+{
+       return tracefs_find_mountpoint() != NULL;
+}
+
+/* find the path to the mounted tracefs */
+const char *tracefs_find_mountpoint(void)
+{
+       const char *ret;
+
+       if (tracefs_found)
+               return (const char *)tracefs_mountpoint;
+
+       ret = find_mountpoint("tracefs", (long) TRACEFS_MAGIC,
+                             tracefs_mountpoint, PATH_MAX + 1,
+                             tracefs_known_mountpoints);
+
+       if (ret)
+               tracefs_found = true;
+
+       return ret;
+}
+
+/* mount the tracefs somewhere if it's not mounted */
+char *tracefs_mount(const char *mountpoint)
+{
+       /* see if it's already mounted */
+       if (tracefs_find_mountpoint())
+               goto out;
+
+       /* if not mounted and no argument */
+       if (mountpoint == NULL) {
+               /* see if environment variable set */
+               mountpoint = getenv(PERF_TRACEFS_ENVIRONMENT);
+               /* if no environment variable, use default */
+               if (mountpoint == NULL)
+                       mountpoint = TRACEFS_DEFAULT_PATH;
+       }
+
+       if (mount(NULL, mountpoint, "tracefs", 0, NULL) < 0)
+               return NULL;
+
+       /* save the mountpoint */
+       tracefs_found = true;
+       strncpy(tracefs_mountpoint, mountpoint, sizeof(tracefs_mountpoint));
+out:
+       return tracefs_mountpoint;
+}
diff --git a/tools/lib/api/fs/tracefs.h b/tools/lib/api/fs/tracefs.h
new file mode 100644 (file)
index 0000000..da780ac
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __API_TRACEFS_H__
+#define __API_TRACEFS_H__
+
+#include "findfs.h"
+
+#ifndef TRACEFS_MAGIC
+#define TRACEFS_MAGIC          0x74726163
+#endif
+
+#ifndef PERF_TRACEFS_ENVIRONMENT
+#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
+#endif
+
+bool tracefs_configured(void);
+const char *tracefs_find_mountpoint(void);
+int tracefs_valid_mountpoint(const char *debugfs);
+char *tracefs_mount(const char *mountpoint);
+
+extern char tracefs_mountpoint[];
+
+#endif /* __API_DEBUGFS_H__ */
diff --git a/tools/lib/lockdep/Build b/tools/lib/lockdep/Build
new file mode 100644 (file)
index 0000000..6f66735
--- /dev/null
@@ -0,0 +1 @@
+liblockdep-y += common.o lockdep.o preload.o rbtree.o
index 4b866c54f624bd2adca1b21b241b2937a89494e5..0c356fb650220c6cd5d452d68a22eeb286d40d13 100644 (file)
@@ -35,6 +35,10 @@ bindir = $(prefix)/$(bindir_relative)
 
 export DESTDIR DESTDIR_SQ INSTALL
 
+MAKEFLAGS += --no-print-directory
+
+include ../../scripts/Makefile.include
+
 # copy a bit from Linux kbuild
 
 ifeq ("$(origin V)", "command line")
@@ -44,56 +48,21 @@ ifndef VERBOSE
   VERBOSE = 0
 endif
 
-ifeq ("$(origin O)", "command line")
-  BUILD_OUTPUT := $(O)
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
 endif
 
-ifeq ($(BUILD_SRC),)
-ifneq ($(BUILD_OUTPUT),)
-
-define build_output
-       $(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) \
-       BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
-endef
-
-saved-output := $(BUILD_OUTPUT)
-BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
-$(if $(BUILD_OUTPUT),, \
-     $(error output directory "$(saved-output)" does not exist))
-
-all: sub-make
-
-gui: force
-       $(call build_output, all_cmd)
-
-$(filter-out gui,$(MAKECMDGOALS)): sub-make
-
-sub-make: force
-       $(call build_output, $(MAKECMDGOALS))
-
-
-# Leave processing to above invocation of make
-skip-makefile := 1
-
-endif # BUILD_OUTPUT
-endif # BUILD_SRC
-
-# We process the rest of the Makefile if this is the final invocation of make
-ifeq ($(skip-makefile),)
-
-srctree                := $(realpath $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR)))
-objtree                := $(realpath $(CURDIR))
-src            := $(srctree)
-obj            := $(objtree)
-
-export prefix libdir bindir src obj
-
 # Shell quotes
 libdir_SQ = $(subst ','\'',$(libdir))
 bindir_SQ = $(subst ','\'',$(bindir))
 
-LIB_FILE = liblockdep.a liblockdep.so.$(LIBLOCKDEP_VERSION)
+LIB_IN := $(OUTPUT)liblockdep-in.o
+
 BIN_FILE = lockdep
+LIB_FILE = $(OUTPUT)liblockdep.a $(OUTPUT)liblockdep.so.$(LIBLOCKDEP_VERSION)
 
 CONFIG_INCLUDES =
 CONFIG_LIBS    =
@@ -108,33 +77,23 @@ INCLUDES = -I. -I./uinclude -I./include -I../../include $(CONFIG_INCLUDES)
 
 # Set compile option CFLAGS if not set elsewhere
 CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g
+CFLAGS += -fPIC
 
 override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
 
 ifeq ($(VERBOSE),1)
   Q =
-  print_compile =
-  print_app_build =
-  print_fpic_compile =
   print_shared_lib_compile =
   print_install =
 else
   Q = @
-  print_compile =              echo '  CC                 '$(OBJ);
-  print_app_build =            echo '  BUILD              '$(OBJ);
-  print_fpic_compile =         echo '  CC FPIC            '$(OBJ);
-  print_shared_lib_compile =   echo '  BUILD SHARED LIB   '$(OBJ);
-  print_static_lib_build =     echo '  BUILD STATIC LIB   '$(OBJ);
-  print_install =              echo '  INSTALL     '$1'        to      $(DESTDIR_SQ)$2';
+  print_shared_lib_compile =   echo '  LD       '$(OBJ);
+  print_static_lib_build =     echo '  LD       '$(OBJ);
+  print_install =              echo '  INSTALL  '$1'   to      $(DESTDIR_SQ)$2';
 endif
 
-do_fpic_compile =                                      \
-       ($(print_fpic_compile)                          \
-       $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
-
-do_app_build =                                         \
-       ($(print_app_build)                             \
-       $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
+export srctree OUTPUT CC LD CFLAGS V
+build := -f $(srctree)/tools/build/Makefile.build dir=. obj
 
 do_compile_shared_library =                    \
        ($(print_shared_lib_compile)            \
@@ -144,22 +103,6 @@ do_build_static_lib =                              \
        ($(print_static_lib_build)              \
        $(RM) $@;  $(AR) rcs $@ $^)
 
-
-define do_compile
-       $(print_compile)                                                \
-       $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
-endef
-
-$(obj)/%.o: $(src)/%.c
-       $(Q)$(call do_compile)
-
-%.o: $(src)/%.c
-       $(Q)$(call do_compile)
-
-PEVENT_LIB_OBJS = common.o lockdep.o preload.o rbtree.o
-
-ALL_OBJS = $(PEVENT_LIB_OBJS)
-
 CMD_TARGETS = $(LIB_FILE)
 
 TARGETS = $(CMD_TARGETS)
@@ -169,42 +112,15 @@ all: all_cmd
 
 all_cmd: $(CMD_TARGETS)
 
-liblockdep.so.$(LIBLOCKDEP_VERSION): $(PEVENT_LIB_OBJS)
+$(LIB_IN): force
+       $(Q)$(MAKE) $(build)=liblockdep
+
+liblockdep.so.$(LIBLOCKDEP_VERSION): $(LIB_IN)
        $(Q)$(do_compile_shared_library)
 
-liblockdep.a: $(PEVENT_LIB_OBJS)
+liblockdep.a: $(LIB_IN)
        $(Q)$(do_build_static_lib)
 
-$(PEVENT_LIB_OBJS): %.o: $(src)/%.c
-       $(Q)$(do_fpic_compile)
-
-## make deps
-
-all_objs := $(sort $(ALL_OBJS))
-all_deps := $(all_objs:%.o=.%.d)
-
-# let .d file also depends on the source and header files
-define check_deps
-               @set -e; $(RM) $@; \
-               $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
-               sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
-               $(RM) $@.$$$$
-endef
-
-$(all_deps): .%.d: $(src)/%.c
-       $(Q)$(call check_deps)
-
-$(all_objs) : %.o : .%.d
-
-dep_includes := $(wildcard $(all_deps))
-
-ifneq ($(dep_includes),)
- include $(dep_includes)
-endif
-
-### Detect environment changes
-TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
-
 tags:  force
        $(RM) tags
        find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
@@ -233,8 +149,6 @@ clean:
        $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d
        $(RM) tags TAGS
 
-endif # skip-makefile
-
 PHONY += force
 force:
 
diff --git a/tools/lib/traceevent/Build b/tools/lib/traceevent/Build
new file mode 100644 (file)
index 0000000..c681d05
--- /dev/null
@@ -0,0 +1,17 @@
+libtraceevent-y += event-parse.o
+libtraceevent-y += event-plugin.o
+libtraceevent-y += trace-seq.o
+libtraceevent-y += parse-filter.o
+libtraceevent-y += parse-utils.o
+libtraceevent-y += kbuffer-parse.o
+
+plugin_jbd2-y         += plugin_jbd2.o
+plugin_hrtimer-y      += plugin_hrtimer.o
+plugin_kmem-y         += plugin_kmem.o
+plugin_kvm-y          += plugin_kvm.o
+plugin_mac80211-y     += plugin_mac80211.o
+plugin_sched_switch-y += plugin_sched_switch.o
+plugin_function-y     += plugin_function.o
+plugin_xen-y          += plugin_xen.o
+plugin_scsi-y         += plugin_scsi.o
+plugin_cfg80211-y     += plugin_cfg80211.o
index 005c9cc0693593bf4ca197e13784f59118e2c5c1..d410da335e3daeaeac8da1dbdfdabdc7e23fc38f 100644 (file)
@@ -67,7 +67,7 @@ PLUGIN_DIR = -DPLUGIN_DIR="$(plugin_dir)"
 PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))'
 endif
 
-include $(if $(BUILD_SRC),$(BUILD_SRC)/)../../scripts/Makefile.include
+include ../../scripts/Makefile.include
 
 # copy a bit from Linux kbuild
 
@@ -78,40 +78,13 @@ ifndef VERBOSE
   VERBOSE = 0
 endif
 
-ifeq ("$(origin O)", "command line")
-  BUILD_OUTPUT := $(O)
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
 endif
 
-ifeq ($(BUILD_SRC),)
-ifneq ($(OUTPUT),)
-
-define build_output
-  $(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \
-  BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1
-endef
-
-all: sub-make
-
-$(MAKECMDGOALS): sub-make
-
-sub-make: force
-       $(call build_output, $(MAKECMDGOALS))
-
-
-# Leave processing to above invocation of make
-skip-makefile := 1
-
-endif # OUTPUT
-endif # BUILD_SRC
-
-# We process the rest of the Makefile if this is the final invocation of make
-ifeq ($(skip-makefile),)
-
-srctree                := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR))
-objtree                := $(CURDIR)
-src            := $(srctree)
-obj            := $(objtree)
-
 export prefix bindir src obj
 
 # Shell quotes
@@ -132,16 +105,19 @@ EXTRAVERSION      = $(EP_EXTRAVERSION)
 OBJ            = $@
 N              =
 
-export Q VERBOSE
-
 EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
 
-INCLUDES = -I. -I $(srctree)/../../include $(CONFIG_INCLUDES)
+INCLUDES = -I. -I $(srctree)/tools/include $(CONFIG_INCLUDES)
 
-# Set compile option CFLAGS if not set elsewhere
-CFLAGS ?= -g -Wall
+# Set compile option CFLAGS
+ifdef EXTRA_CFLAGS
+  CFLAGS := $(EXTRA_CFLAGS)
+else
+  CFLAGS := -g -Wall
+endif
 
 # Append required CFLAGS
+override CFLAGS += -fPIC
 override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
 override CFLAGS += $(udis86-flags) -D_GNU_SOURCE
 
@@ -151,74 +127,58 @@ else
   Q = @
 endif
 
-do_compile_shared_library =                    \
-       ($(print_shared_lib_compile)            \
-       $(CC) --shared $^ -o $@)
-
-do_plugin_build =                              \
-       ($(print_plugin_build)                  \
-       $(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<)
-
-do_build_static_lib =                          \
-       ($(print_static_lib_build)              \
-       $(RM) $@;  $(AR) rcs $@ $^)
-
-
-do_compile = $(QUIET_CC)$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
+# Disable command line variables (CFLAGS) overide from top
+# level Makefile (perf), otherwise build Makefile will get
+# the same command line setup.
+MAKEOVERRIDES=
 
-$(obj)/%.o: $(src)/%.c
-       $(call do_compile)
+export srctree OUTPUT CC LD CFLAGS V
+build := -f $(srctree)/tools/build/Makefile.build dir=. obj
 
-%.o: $(src)/%.c
-       $(call do_compile)
+PLUGINS  = plugin_jbd2.so
+PLUGINS += plugin_hrtimer.so
+PLUGINS += plugin_kmem.so
+PLUGINS += plugin_kvm.so
+PLUGINS += plugin_mac80211.so
+PLUGINS += plugin_sched_switch.so
+PLUGINS += plugin_function.so
+PLUGINS += plugin_xen.so
+PLUGINS += plugin_scsi.so
+PLUGINS += plugin_cfg80211.so
 
-PEVENT_LIB_OBJS  = event-parse.o
-PEVENT_LIB_OBJS += event-plugin.o
-PEVENT_LIB_OBJS += trace-seq.o
-PEVENT_LIB_OBJS += parse-filter.o
-PEVENT_LIB_OBJS += parse-utils.o
-PEVENT_LIB_OBJS += kbuffer-parse.o
+PLUGINS    := $(addprefix $(OUTPUT),$(PLUGINS))
+PLUGINS_IN := $(PLUGINS:.so=-in.o)
 
-PLUGIN_OBJS  = plugin_jbd2.o
-PLUGIN_OBJS += plugin_hrtimer.o
-PLUGIN_OBJS += plugin_kmem.o
-PLUGIN_OBJS += plugin_kvm.o
-PLUGIN_OBJS += plugin_mac80211.o
-PLUGIN_OBJS += plugin_sched_switch.o
-PLUGIN_OBJS += plugin_function.o
-PLUGIN_OBJS += plugin_xen.o
-PLUGIN_OBJS += plugin_scsi.o
-PLUGIN_OBJS += plugin_cfg80211.o
-
-PLUGINS := $(PLUGIN_OBJS:.o=.so)
-
-ALL_OBJS = $(PEVENT_LIB_OBJS) $(PLUGIN_OBJS)
+TE_IN    := $(OUTPUT)libtraceevent-in.o
+LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
 
 CMD_TARGETS = $(LIB_FILE) $(PLUGINS)
 
 TARGETS = $(CMD_TARGETS)
 
-
 all: all_cmd
 
 all_cmd: $(CMD_TARGETS)
 
-libtraceevent.so: $(PEVENT_LIB_OBJS)
+$(TE_IN): force
+       $(Q)$(MAKE) $(build)=libtraceevent
+
+$(OUTPUT)libtraceevent.so: $(TE_IN)
        $(QUIET_LINK)$(CC) --shared $^ -o $@
 
-libtraceevent.a: $(PEVENT_LIB_OBJS)
+$(OUTPUT)libtraceevent.a: $(TE_IN)
        $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
 
 plugins: $(PLUGINS)
 
-$(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS
-       $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@
+__plugin_obj = $(notdir $@)
+  plugin_obj = $(__plugin_obj:-in.o=)
 
-$(PLUGIN_OBJS): %.o : $(src)/%.c
-       $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) -fPIC -o $@ $<
+$(PLUGINS_IN): force
+       $(Q)$(MAKE) $(build)=$(plugin_obj)
 
-$(PLUGINS): %.so: %.o
-       $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<
+$(OUTPUT)%.so: $(OUTPUT)%-in.o
+       $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $^
 
 define make_version.h
   (echo '/* This file is automatically generated. Do not modify. */';          \
@@ -255,40 +215,6 @@ define update_dir
    fi);
 endef
 
-## make deps
-
-all_objs := $(sort $(ALL_OBJS))
-all_deps := $(all_objs:%.o=.%.d)
-
-# let .d file also depends on the source and header files
-define check_deps
-  @set -e; $(RM) $@; \
-  $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
-  sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
-  $(RM) $@.$$$$
-endef
-
-$(all_deps): .%.d: $(src)/%.c
-       $(Q)$(call check_deps)
-
-$(all_objs) : %.o : .%.d
-
-dep_includes := $(wildcard $(all_deps))
-
-ifneq ($(dep_includes),)
- include $(dep_includes)
-endif
-
-### Detect environment changes
-TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
-
-TRACEEVENT-CFLAGS: force
-       @FLAGS='$(TRACK_CFLAGS)'; \
-           if test x"$$FLAGS" != x"`cat TRACEEVENT-CFLAGS 2>/dev/null`" ; then \
-               echo 1>&2 "  FLAGS:   * new build flags or cross compiler"; \
-               echo "$$FLAGS" >TRACEEVENT-CFLAGS; \
-            fi
-
 tags:  force
        $(RM) tags
        find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
@@ -327,14 +253,9 @@ clean:
                $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \
                $(RM) TRACEEVENT-CFLAGS tags TAGS
 
-endif # skip-makefile
-
 PHONY += force plugins
 force:
 
-plugins:
-       @echo > /dev/null
-
 # Declare the contents of the .PHONY variable as phony.  We keep that
 # information in a variable so we can use it in if_changed and friends.
 .PHONY: $(PHONY)
index afe20ed9fac83e81d1887b86ad5cf01dd1726bad..e0917c0f5d9f3babf82fc84ece90472a8a321f4e 100644 (file)
@@ -304,7 +304,10 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
        if (!item)
                return -1;
 
-       item->comm = strdup(comm);
+       if (comm)
+               item->comm = strdup(comm);
+       else
+               item->comm = strdup("<...>");
        if (!item->comm) {
                free(item);
                return -1;
@@ -318,9 +321,14 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
        return 0;
 }
 
-void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock)
+int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock)
 {
-       pevent->trace_clock = trace_clock;
+       pevent->trace_clock = strdup(trace_clock);
+       if (!pevent->trace_clock) {
+               errno = ENOMEM;
+               return -1;
+       }
+       return 0;
 }
 
 struct func_map {
@@ -758,6 +766,11 @@ static void free_arg(struct print_arg *arg)
                free_arg(arg->hex.field);
                free_arg(arg->hex.size);
                break;
+       case PRINT_INT_ARRAY:
+               free_arg(arg->int_array.field);
+               free_arg(arg->int_array.count);
+               free_arg(arg->int_array.el_size);
+               break;
        case PRINT_TYPE:
                free(arg->typecast.type);
                free_arg(arg->typecast.item);
@@ -1926,7 +1939,22 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
                        goto out_warn_free;
 
                type = process_arg_token(event, right, tok, type);
-               arg->op.right = right;
+
+               if (right->type == PRINT_OP &&
+                   get_op_prio(arg->op.op) < get_op_prio(right->op.op)) {
+                       struct print_arg tmp;
+
+                       /* rotate ops according to the priority */
+                       arg->op.right = right->op.left;
+
+                       tmp = *arg;
+                       *arg = *right;
+                       *right = tmp;
+
+                       arg->op.left = right;
+               } else {
+                       arg->op.right = right;
+               }
 
        } else if (strcmp(token, "[") == 0) {
 
@@ -2014,6 +2042,38 @@ process_entry(struct event_format *event __maybe_unused, struct print_arg *arg,
        return EVENT_ERROR;
 }
 
+static int alloc_and_process_delim(struct event_format *event, char *next_token,
+                                  struct print_arg **print_arg)
+{
+       struct print_arg *field;
+       enum event_type type;
+       char *token;
+       int ret = 0;
+
+       field = alloc_arg();
+       if (!field) {
+               do_warning_event(event, "%s: not enough memory!", __func__);
+               errno = ENOMEM;
+               return -1;
+       }
+
+       type = process_arg(event, field, &token);
+
+       if (test_type_token(type, token, EVENT_DELIM, next_token)) {
+               errno = EINVAL;
+               ret = -1;
+               free_arg(field);
+               goto out_free_token;
+       }
+
+       *print_arg = field;
+
+out_free_token:
+       free_token(token);
+
+       return ret;
+}
+
 static char *arg_eval (struct print_arg *arg);
 
 static unsigned long long
@@ -2486,49 +2546,46 @@ out_free:
 static enum event_type
 process_hex(struct event_format *event, struct print_arg *arg, char **tok)
 {
-       struct print_arg *field;
-       enum event_type type;
-       char *token = NULL;
-
        memset(arg, 0, sizeof(*arg));
        arg->type = PRINT_HEX;
 
-       field = alloc_arg();
-       if (!field) {
-               do_warning_event(event, "%s: not enough memory!", __func__);
-               goto out_free;
-       }
+       if (alloc_and_process_delim(event, ",", &arg->hex.field))
+               goto out;
 
-       type = process_arg(event, field, &token);
+       if (alloc_and_process_delim(event, ")", &arg->hex.size))
+               goto free_field;
 
-       if (test_type_token(type, token, EVENT_DELIM, ","))
-               goto out_free;
-
-       arg->hex.field = field;
+       return read_token_item(tok);
 
-       free_token(token);
+free_field:
+       free_arg(arg->hex.field);
+out:
+       *tok = NULL;
+       return EVENT_ERROR;
+}
 
-       field = alloc_arg();
-       if (!field) {
-               do_warning_event(event, "%s: not enough memory!", __func__);
-               *tok = NULL;
-               return EVENT_ERROR;
-       }
+static enum event_type
+process_int_array(struct event_format *event, struct print_arg *arg, char **tok)
+{
+       memset(arg, 0, sizeof(*arg));
+       arg->type = PRINT_INT_ARRAY;
 
-       type = process_arg(event, field, &token);
+       if (alloc_and_process_delim(event, ",", &arg->int_array.field))
+               goto out;
 
-       if (test_type_token(type, token, EVENT_DELIM, ")"))
-               goto out_free;
+       if (alloc_and_process_delim(event, ",", &arg->int_array.count))
+               goto free_field;
 
-       arg->hex.size = field;
+       if (alloc_and_process_delim(event, ")", &arg->int_array.el_size))
+               goto free_size;
 
-       free_token(token);
-       type = read_token_item(tok);
-       return type;
+       return read_token_item(tok);
 
- out_free:
-       free_arg(field);
-       free_token(token);
+free_size:
+       free_arg(arg->int_array.count);
+free_field:
+       free_arg(arg->int_array.field);
+out:
        *tok = NULL;
        return EVENT_ERROR;
 }
@@ -2828,6 +2885,10 @@ process_function(struct event_format *event, struct print_arg *arg,
                free_token(token);
                return process_hex(event, arg, tok);
        }
+       if (strcmp(token, "__print_array") == 0) {
+               free_token(token);
+               return process_int_array(event, arg, tok);
+       }
        if (strcmp(token, "__get_str") == 0) {
                free_token(token);
                return process_str(event, arg, tok);
@@ -3356,6 +3417,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
                break;
        case PRINT_FLAGS:
        case PRINT_SYMBOL:
+       case PRINT_INT_ARRAY:
        case PRINT_HEX:
                break;
        case PRINT_TYPE:
@@ -3568,7 +3630,7 @@ static const struct flag flags[] = {
        { "HRTIMER_RESTART", 1 },
 };
 
-static unsigned long long eval_flag(const char *flag)
+static long long eval_flag(const char *flag)
 {
        int i;
 
@@ -3584,7 +3646,7 @@ static unsigned long long eval_flag(const char *flag)
                if (strcmp(flags[i].name, flag) == 0)
                        return flags[i].value;
 
-       return 0;
+       return -1LL;
 }
 
 static void print_str_to_seq(struct trace_seq *s, const char *format,
@@ -3658,7 +3720,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
        struct print_flag_sym *flag;
        struct format_field *field;
        struct printk_map *printk;
-       unsigned long long val, fval;
+       long long val, fval;
        unsigned long addr;
        char *str;
        unsigned char *hex;
@@ -3717,11 +3779,11 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                print = 0;
                for (flag = arg->flags.flags; flag; flag = flag->next) {
                        fval = eval_flag(flag->value);
-                       if (!val && !fval) {
+                       if (!val && fval < 0) {
                                print_str_to_seq(s, format, len_arg, flag->str);
                                break;
                        }
-                       if (fval && (val & fval) == fval) {
+                       if (fval > 0 && (val & fval) == fval) {
                                if (print && arg->flags.delim)
                                        trace_seq_puts(s, arg->flags.delim);
                                print_str_to_seq(s, format, len_arg, flag->str);
@@ -3766,6 +3828,54 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                }
                break;
 
+       case PRINT_INT_ARRAY: {
+               void *num;
+               int el_size;
+
+               if (arg->int_array.field->type == PRINT_DYNAMIC_ARRAY) {
+                       unsigned long offset;
+                       struct format_field *field =
+                               arg->int_array.field->dynarray.field;
+                       offset = pevent_read_number(pevent,
+                                                   data + field->offset,
+                                                   field->size);
+                       num = data + (offset & 0xffff);
+               } else {
+                       field = arg->int_array.field->field.field;
+                       if (!field) {
+                               str = arg->int_array.field->field.name;
+                               field = pevent_find_any_field(event, str);
+                               if (!field)
+                                       goto out_warning_field;
+                               arg->int_array.field->field.field = field;
+                       }
+                       num = data + field->offset;
+               }
+               len = eval_num_arg(data, size, event, arg->int_array.count);
+               el_size = eval_num_arg(data, size, event,
+                                      arg->int_array.el_size);
+               for (i = 0; i < len; i++) {
+                       if (i)
+                               trace_seq_putc(s, ' ');
+
+                       if (el_size == 1) {
+                               trace_seq_printf(s, "%u", *(uint8_t *)num);
+                       } else if (el_size == 2) {
+                               trace_seq_printf(s, "%u", *(uint16_t *)num);
+                       } else if (el_size == 4) {
+                               trace_seq_printf(s, "%u", *(uint32_t *)num);
+                       } else if (el_size == 8) {
+                               trace_seq_printf(s, "%lu", *(uint64_t *)num);
+                       } else {
+                               trace_seq_printf(s, "BAD SIZE:%d 0x%x",
+                                                el_size, *(uint8_t *)num);
+                               el_size = 1;
+                       }
+
+                       num += el_size;
+               }
+               break;
+       }
        case PRINT_TYPE:
                break;
        case PRINT_STRING: {
@@ -3976,7 +4086,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
        if (asprintf(&arg->atom.atom, "%lld", ip) < 0)
                goto out_free;
 
-       /* skip the first "%pf: " */
+       /* skip the first "%ps: " */
        for (ptr = fmt + 5, bptr = data + field->offset;
             bptr < data + size && *ptr; ptr++) {
                int ls = 0;
@@ -3997,6 +4107,10 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
                                goto process_again;
                        case '.':
                                goto process_again;
+                       case 'z':
+                       case 'Z':
+                               ls = 1;
+                               goto process_again;
                        case 'p':
                                ls = 1;
                                /* fall through */
@@ -4939,6 +5053,96 @@ const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
        return comm;
 }
 
+static struct cmdline *
+pid_from_cmdlist(struct pevent *pevent, const char *comm, struct cmdline *next)
+{
+       struct cmdline_list *cmdlist = (struct cmdline_list *)next;
+
+       if (cmdlist)
+               cmdlist = cmdlist->next;
+       else
+               cmdlist = pevent->cmdlist;
+
+       while (cmdlist && strcmp(cmdlist->comm, comm) != 0)
+               cmdlist = cmdlist->next;
+
+       return (struct cmdline *)cmdlist;
+}
+
+/**
+ * pevent_data_pid_from_comm - return the pid from a given comm
+ * @pevent: a handle to the pevent
+ * @comm: the cmdline to find the pid from
+ * @next: the cmdline structure to find the next comm
+ *
+ * This returns the cmdline structure that holds a pid for a given
+ * comm, or NULL if none found. As there may be more than one pid for
+ * a given comm, the result of this call can be passed back into
+ * a recurring call in the @next paramater, and then it will find the
+ * next pid.
+ * Also, it does a linear seach, so it may be slow.
+ */
+struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm,
+                                         struct cmdline *next)
+{
+       struct cmdline *cmdline;
+
+       /*
+        * If the cmdlines have not been converted yet, then use
+        * the list.
+        */
+       if (!pevent->cmdlines)
+               return pid_from_cmdlist(pevent, comm, next);
+
+       if (next) {
+               /*
+                * The next pointer could have been still from
+                * a previous call before cmdlines were created
+                */
+               if (next < pevent->cmdlines ||
+                   next >= pevent->cmdlines + pevent->cmdline_count)
+                       next = NULL;
+               else
+                       cmdline  = next++;
+       }
+
+       if (!next)
+               cmdline = pevent->cmdlines;
+
+       while (cmdline < pevent->cmdlines + pevent->cmdline_count) {
+               if (strcmp(cmdline->comm, comm) == 0)
+                       return cmdline;
+               cmdline++;
+       }
+       return NULL;
+}
+
+/**
+ * pevent_cmdline_pid - return the pid associated to a given cmdline
+ * @cmdline: The cmdline structure to get the pid from
+ *
+ * Returns the pid for a give cmdline. If @cmdline is NULL, then
+ * -1 is returned.
+ */
+int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline)
+{
+       struct cmdline_list *cmdlist = (struct cmdline_list *)cmdline;
+
+       if (!cmdline)
+               return -1;
+
+       /*
+        * If cmdlines have not been created yet, or cmdline is
+        * not part of the array, then treat it as a cmdlist instead.
+        */
+       if (!pevent->cmdlines ||
+           cmdline < pevent->cmdlines ||
+           cmdline >= pevent->cmdlines + pevent->cmdline_count)
+               return cmdlist->pid;
+
+       return cmdline->pid;
+}
+
 /**
  * pevent_data_comm_from_pid - parse the data into the print format
  * @s: the trace_seq to write to
@@ -5256,6 +5460,15 @@ static void print_args(struct print_arg *args)
                print_args(args->hex.size);
                printf(")");
                break;
+       case PRINT_INT_ARRAY:
+               printf("__print_array(");
+               print_args(args->int_array.field);
+               printf(", ");
+               print_args(args->int_array.count);
+               printf(", ");
+               print_args(args->int_array.el_size);
+               printf(")");
+               break;
        case PRINT_STRING:
        case PRINT_BSTRING:
                printf("__get_str(%s)", args->string.string);
@@ -6228,15 +6441,20 @@ void pevent_ref(struct pevent *pevent)
        pevent->ref_count++;
 }
 
+void pevent_free_format_field(struct format_field *field)
+{
+       free(field->type);
+       free(field->name);
+       free(field);
+}
+
 static void free_format_fields(struct format_field *field)
 {
        struct format_field *next;
 
        while (field) {
                next = field->next;
-               free(field->type);
-               free(field->name);
-               free(field);
+               pevent_free_format_field(field);
                field = next;
        }
 }
@@ -6341,6 +6559,7 @@ void pevent_free(struct pevent *pevent)
                free_handler(handle);
        }
 
+       free(pevent->trace_clock);
        free(pevent->events);
        free(pevent->sort_events);
 
index 7a3873ff9a4fb0ebad9018c04b795e061626e1a7..86a5839fb048e87d2f76982ab51231ef4646dfc5 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <stdbool.h>
 #include <stdarg.h>
+#include <stdio.h>
 #include <regex.h>
 #include <string.h>
 
@@ -91,6 +92,7 @@ extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
 
 extern void trace_seq_terminate(struct trace_seq *s);
 
+extern int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp);
 extern int trace_seq_do_printf(struct trace_seq *s);
 
 
@@ -114,7 +116,7 @@ struct pevent_plugin_option {
        char                            *name;
        char                            *plugin_alias;
        char                            *description;
-       char                            *value;
+       const char                      *value;
        void                            *priv;
        int                             set;
 };
@@ -152,6 +154,10 @@ struct pevent_plugin_option {
  *   .plugin_alias is used to give a shorter name to access
  *   the vairable. Useful if a plugin handles more than one event.
  *
+ *   If .value is not set, then it is considered a boolean and only
+ *   .set will be processed. If .value is defined, then it is considered
+ *   a string option and .set will be ignored.
+ *
  * PEVENT_PLUGIN_ALIAS: (optional)
  *   The name to use for finding options (uses filename if not defined)
  */
@@ -245,6 +251,12 @@ struct print_arg_hex {
        struct print_arg        *size;
 };
 
+struct print_arg_int_array {
+       struct print_arg        *field;
+       struct print_arg        *count;
+       struct print_arg        *el_size;
+};
+
 struct print_arg_dynarray {
        struct format_field     *field;
        struct print_arg        *index;
@@ -273,6 +285,7 @@ enum print_arg_type {
        PRINT_FLAGS,
        PRINT_SYMBOL,
        PRINT_HEX,
+       PRINT_INT_ARRAY,
        PRINT_TYPE,
        PRINT_STRING,
        PRINT_BSTRING,
@@ -292,6 +305,7 @@ struct print_arg {
                struct print_arg_flags          flags;
                struct print_arg_symbol         symbol;
                struct print_arg_hex            hex;
+               struct print_arg_int_array      int_array;
                struct print_arg_func           func;
                struct print_arg_string         string;
                struct print_arg_bitmask        bitmask;
@@ -597,7 +611,7 @@ enum trace_flag_type {
 };
 
 int pevent_register_comm(struct pevent *pevent, const char *comm, int pid);
-void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock);
+int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock);
 int pevent_register_function(struct pevent *pevent, char *name,
                             unsigned long long addr, char *mod);
 int pevent_register_print_string(struct pevent *pevent, const char *fmt,
@@ -617,6 +631,7 @@ enum pevent_errno pevent_parse_format(struct pevent *pevent,
                                      const char *buf,
                                      unsigned long size, const char *sys);
 void pevent_free_format(struct event_format *event);
+void pevent_free_format_field(struct format_field *field);
 
 void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
                           const char *name, struct pevent_record *record,
@@ -675,6 +690,11 @@ int pevent_data_type(struct pevent *pevent, struct pevent_record *rec);
 struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type);
 int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec);
 const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid);
+struct cmdline;
+struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm,
+                                         struct cmdline *next);
+int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline);
+
 void pevent_event_info(struct trace_seq *s, struct event_format *event,
                       struct pevent_record *record);
 int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
index 136162c03af1ce25072df0fac41d10d8b93f606f..a16756ae352679a433d4321f79bb083bd8294633 100644 (file)
@@ -18,6 +18,7 @@
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
+#include <ctype.h>
 #include <stdio.h>
 #include <string.h>
 #include <dlfcn.h>
@@ -49,6 +50,52 @@ struct plugin_list {
        void                    *handle;
 };
 
+static void lower_case(char *str)
+{
+       if (!str)
+               return;
+       for (; *str; str++)
+               *str = tolower(*str);
+}
+
+static int update_option_value(struct pevent_plugin_option *op, const char *val)
+{
+       char *op_val;
+
+       if (!val) {
+               /* toggle, only if option is boolean */
+               if (op->value)
+                       /* Warn? */
+                       return 0;
+               op->set ^= 1;
+               return 0;
+       }
+
+       /*
+        * If the option has a value then it takes a string
+        * otherwise the option is a boolean.
+        */
+       if (op->value) {
+               op->value = val;
+               return 0;
+       }
+
+       /* Option is boolean, must be either "1", "0", "true" or "false" */
+
+       op_val = strdup(val);
+       if (!op_val)
+               return -1;
+       lower_case(op_val);
+
+       if (strcmp(val, "1") == 0 || strcmp(val, "true") == 0)
+               op->set = 1;
+       else if (strcmp(val, "0") == 0 || strcmp(val, "false") == 0)
+               op->set = 0;
+       free(op_val);
+
+       return 0;
+}
+
 /**
  * traceevent_plugin_list_options - get list of plugin options
  *
@@ -120,6 +167,7 @@ update_option(const char *file, struct pevent_plugin_option *option)
 {
        struct trace_plugin_options *op;
        char *plugin;
+       int ret = 0;
 
        if (option->plugin_alias) {
                plugin = strdup(option->plugin_alias);
@@ -144,9 +192,10 @@ update_option(const char *file, struct pevent_plugin_option *option)
                if (strcmp(op->option, option->name) != 0)
                        continue;
 
-               option->value = op->value;
-               option->set ^= 1;
-               goto out;
+               ret = update_option_value(option, op->value);
+               if (ret)
+                       goto out;
+               break;
        }
 
        /* first look for unnamed options */
@@ -156,14 +205,13 @@ update_option(const char *file, struct pevent_plugin_option *option)
                if (strcmp(op->option, option->name) != 0)
                        continue;
 
-               option->value = op->value;
-               option->set ^= 1;
+               ret = update_option_value(option, op->value);
                break;
        }
 
  out:
        free(plugin);
-       return 0;
+       return ret;
 }
 
 /**
index dcc665228c71fd09f7b39c2486063d98f7176445..3bcada3ae05abd15d7056847d1e9831cc928d13e 100644 (file)
@@ -372,7 +372,6 @@ translate_data(struct kbuffer *kbuf, void *data, void **rptr,
        switch (type_len) {
        case KBUFFER_TYPE_PADDING:
                *length = read_4(kbuf, data);
-               data += *length;
                break;
 
        case KBUFFER_TYPE_TIME_EXTEND:
@@ -730,3 +729,14 @@ void kbuffer_set_old_format(struct kbuffer *kbuf)
 
        kbuf->next_event = __old_next_event;
 }
+
+/**
+ * kbuffer_start_of_data - return offset of where data starts on subbuffer
+ * @kbuf:      The kbuffer
+ *
+ * Returns the location on the subbuffer where the data starts.
+ */
+int kbuffer_start_of_data(struct kbuffer *kbuf)
+{
+       return kbuf->start;
+}
index c831f64b17a06f70381abf2a3c5b3f9baa54994d..03dce757553f14b123f7f678b42550722e5c9656 100644 (file)
@@ -63,5 +63,6 @@ int kbuffer_missed_events(struct kbuffer *kbuf);
 int kbuffer_subbuffer_size(struct kbuffer *kbuf);
 
 void kbuffer_set_old_format(struct kbuffer *kbuf);
+int kbuffer_start_of_data(struct kbuffer *kbuf);
 
 #endif /* _K_BUFFER_H */
index b50234402fc2b368f39040a92ada39922f6464ee..0144b3d1bb77ac63441c77e1bb24e3405cfe3d8f 100644 (file)
@@ -1058,6 +1058,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                                        *parg = current_op;
                                else
                                        *parg = current_exp;
+                               free(token);
                                return PEVENT_ERRNO__UNBALANCED_PAREN;
                        }
                        break;
@@ -1168,6 +1169,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
 
        *parg = current_op;
 
+       free(token);
        return 0;
 
  fail_alloc:
index ec3bd16a548881252d482e3f09e499a9bd12898d..292dc9f1d2334f2a9cab35d70b1531d74f68fca4 100644 (file)
@@ -231,19 +231,24 @@ void trace_seq_terminate(struct trace_seq *s)
        s->buffer[s->len] = 0;
 }
 
-int trace_seq_do_printf(struct trace_seq *s)
+int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp)
 {
        TRACE_SEQ_CHECK(s);
 
        switch (s->state) {
        case TRACE_SEQ__GOOD:
-               return printf("%.*s", s->len, s->buffer);
+               return fprintf(fp, "%.*s", s->len, s->buffer);
        case TRACE_SEQ__BUFFER_POISONED:
-               puts("Usage of trace_seq after it was destroyed");
+               fprintf(fp, "%s\n", "Usage of trace_seq after it was destroyed");
                break;
        case TRACE_SEQ__MEM_ALLOC_FAILED:
-               puts("Can't allocate trace_seq buffer memory");
+               fprintf(fp, "%s\n", "Can't allocate trace_seq buffer memory");
                break;
        }
        return -1;
 }
+
+int trace_seq_do_printf(struct trace_seq *s)
+{
+       return trace_seq_do_fprintf(s, stdout);
+}
index 40399c3d97d6bcc50396a0961fe90f8309cde9dd..812f904193e8869bf0bd179d5dd36e42d51c35c8 100644 (file)
@@ -1,6 +1,7 @@
 PERF-CFLAGS
 PERF-GUI-VARS
 PERF-VERSION-FILE
+FEATURE-DUMP
 perf
 perf-read-vdso32
 perf-read-vdsox32
diff --git a/tools/perf/Build b/tools/perf/Build
new file mode 100644 (file)
index 0000000..b77370e
--- /dev/null
@@ -0,0 +1,44 @@
+perf-y += builtin-bench.o
+perf-y += builtin-annotate.o
+perf-y += builtin-diff.o
+perf-y += builtin-evlist.o
+perf-y += builtin-help.o
+perf-y += builtin-sched.o
+perf-y += builtin-buildid-list.o
+perf-y += builtin-buildid-cache.o
+perf-y += builtin-list.o
+perf-y += builtin-record.o
+perf-y += builtin-report.o
+perf-y += builtin-stat.o
+perf-y += builtin-timechart.o
+perf-y += builtin-top.o
+perf-y += builtin-script.o
+perf-y += builtin-kmem.o
+perf-y += builtin-lock.o
+perf-y += builtin-kvm.o
+perf-y += builtin-inject.o
+perf-y += builtin-mem.o
+perf-y += builtin-data.o
+
+perf-$(CONFIG_AUDIT) += builtin-trace.o
+perf-$(CONFIG_LIBELF) += builtin-probe.o
+
+perf-y += bench/
+perf-y += tests/
+
+perf-y += perf.o
+
+paths += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))"
+paths += -DPERF_INFO_PATH="BUILD_STR($(infodir_SQ))"
+paths += -DPERF_MAN_PATH="BUILD_STR($(mandir_SQ))"
+
+CFLAGS_builtin-help.o      += $(paths)
+CFLAGS_builtin-timechart.o += $(paths)
+CFLAGS_perf.o              += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" -include $(OUTPUT)PERF-VERSION-FILE
+
+libperf-y += util/
+libperf-y += arch/
+libperf-y += ui/
+libperf-y += scripts/
+
+gtk-y += ui/gtk/
diff --git a/tools/perf/Documentation/Build.txt b/tools/perf/Documentation/Build.txt
new file mode 100644 (file)
index 0000000..f6fc650
--- /dev/null
@@ -0,0 +1,49 @@
+
+1) perf build
+=============
+The perf build process consists of several separated building blocks,
+which are linked together to form the perf binary:
+  - libperf library (static)
+  - perf builtin commands
+  - traceevent library (static)
+  - GTK ui library
+
+Several makefiles govern the perf build:
+
+  - Makefile
+    top level Makefile working as a wrapper that calls the main
+    Makefile.perf with a -j option to do parallel builds.
+
+  - Makefile.perf
+    main makefile that triggers build of all perf objects including
+    installation and documentation processing.
+
+  - tools/build/Makefile.build
+    main makefile of the build framework
+
+  - tools/build/Build.include
+    build framework generic definitions
+
+  - Build makefiles
+    makefiles that defines build objects
+
+Please refer to tools/build/Documentation/Build.txt for more
+information about build framework.
+
+
+2) perf build
+=============
+The Makefile.perf triggers the build framework for build objects:
+   perf, libperf, gtk
+
+resulting in following objects:
+  $ ls  *-in.o
+  gtk-in.o  libperf-in.o  perf-in.o
+
+Those objects are then used in final linking:
+  libperf-gtk.so <- gtk-in.o  libperf-in.o
+  perf           <- perf-in.o libperf-in.o
+
+
+NOTE this description is omitting other libraries involved, only
+     focusing on build framework outcomes
index 0294c57b1f5ed631534672e6888d280e5c7bc5f3..dd07b55f58d8e9990e6f625ab3ebce2bf6bd6bbc 100644 (file)
@@ -12,9 +12,9 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-This command manages the build-id cache. It can add and remove files to/from
-the cache. In the future it should as well purge older entries, set upper
-limits for the space used by the cache, etc.
+This command manages the build-id cache. It can add, remove, update and purge
+files to/from the cache. In the future it should as well set upper limits for
+the space used by the cache, etc.
 
 OPTIONS
 -------
@@ -36,14 +36,24 @@ OPTIONS
         actually made.
 -r::
 --remove=::
-        Remove specified file from the cache.
+        Remove a cached binary which has same build-id of specified file
+        from the cache.
+-p::
+--purge=::
+        Purge all cached binaries including older caches which have specified
+       path from the cache.
 -M::
 --missing=::
        List missing build ids in the cache for the specified file.
 -u::
---update::
-       Update specified file of the cache. It can be used to update kallsyms
-       kernel dso to vmlinux in order to support annotation.
+--update=::
+       Update specified file of the cache. Note that this doesn't remove
+       older entires since those may be still needed for annotating old
+       (or remote) perf.data. Only if there is already a cache which has
+       exactly same build-id, that is replaced by new one. It can be used
+       to update kallsyms and kernel dso to vmlinux in order to support
+       annotation.
+
 -v::
 --verbose::
        Be more verbose.
diff --git a/tools/perf/Documentation/perf-data.txt b/tools/perf/Documentation/perf-data.txt
new file mode 100644 (file)
index 0000000..be8fa1a
--- /dev/null
@@ -0,0 +1,40 @@
+perf-data(1)
+==============
+
+NAME
+----
+perf-data - Data file related processing
+
+SYNOPSIS
+--------
+[verse]
+'perf data' [<common options>] <command> [<options>]",
+
+DESCRIPTION
+-----------
+Data file related processing.
+
+COMMANDS
+--------
+convert::
+       Converts perf data file into another format (only CTF [1] format is support by now).
+       It's possible to set data-convert debug variable to get debug messages from conversion,
+       like:
+         perf --debug data-convert data convert ...
+
+OPTIONS for 'convert'
+---------------------
+--to-ctf::
+       Triggers the CTF conversion, specify the path of CTF data directory.
+
+-i::
+       Specify input perf data file path.
+
+-v::
+--verbose::
+        Be more verbose (show counter open errors, etc).
+
+SEE ALSO
+--------
+linkperf:perf[1]
+[1] Common Trace Format - http://www.efficios.com/ctf
index e463caa3eb49ed125addda7a1ec30b564516809b..d1deb573877fe5d84a8a7a7a63fe700585e4d8d5 100644 (file)
@@ -20,12 +20,20 @@ If no parameters are passed it will assume perf.data.old and perf.data.
 The differential profile is displayed only for events matching both
 specified perf.data files.
 
+If no parameters are passed the samples will be sorted by dso and symbol.
+As the perf.data files could come from different binaries, the symbols addresses
+could vary. So perf diff is based on the comparison of the files and
+symbols name.
+
 OPTIONS
 -------
 -D::
 --dump-raw-trace::
         Dump raw trace in ASCII.
 
+--kallsyms=<file>::
+        kallsyms pathname
+
 -m::
 --modules::
         Load module symbols. WARNING: use only with -k and LIVE kernel
index 7c8fbbf3f61c8a9abbbca3990b1f07ac2ac968c8..150253cc3c97dd9561610ea780b1b83b871346eb 100644 (file)
@@ -25,6 +25,10 @@ OPTIONS
 --input=<file>::
        Select the input file (default: perf.data unless stdin is a fifo)
 
+-v::
+--verbose::
+        Be more verbose. (show symbol address, etc)
+
 --caller::
        Show per-callsite statistics
 
index 3e2aec94f806b5425eca4f961a01e1be077b8901..bada8933fdd4798a2890a13b2fb64d5bf75d9743 100644 (file)
@@ -26,6 +26,7 @@ counted. The following modifiers exist:
  u - user-space counting
  k - kernel counting
  h - hypervisor counting
+ I - non idle counting
  G - guest counting (in KVM guests)
  H - host counting (not in KVM guests)
  p - precise level
@@ -127,6 +128,12 @@ To limit the list use:
 One or more types can be used at the same time, listing the events for the
 types specified.
 
+Support raw format:
+
+. '--raw-dump', shows the raw-dump of all the events.
+. '--raw-dump [hw|sw|cache|tracepoint|pmu|event_glob]', shows the raw-dump of
+  a certain kind of events.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-top[1],
index aaa869be3dc1d48ac5573163d752d08b9152a295..239609c09f83a10ebde91c8254ab94c9b4d15354 100644 (file)
@@ -47,6 +47,12 @@ OPTIONS
 -v::
 --verbose::
         Be more verbose (show parsed arguments, etc).
+       Can not use with -q.
+
+-q::
+--quiet::
+       Be quiet (do not show any messages including errors).
+       Can not use with -v.
 
 -a::
 --add=::
@@ -96,7 +102,7 @@ OPTIONS
        Dry run. With this option, --add and --del doesn't execute actual
        adding and removal operations.
 
---max-probes::
+--max-probes=NUM::
        Set the maximum number of probe points for an event. Default is 128.
 
 -x::
@@ -104,8 +110,13 @@ OPTIONS
        Specify path to the executable or shared library file for user
        space tracing. Can also be used with --funcs option.
 
+--demangle::
+       Demangle application symbols. --no-demangle is also available
+       for disabling demangling.
+
 --demangle-kernel::
-       Demangle kernel symbols.
+       Demangle kernel symbols. --no-demangle-kernel is also available
+       for disabling kernel demangling.
 
 In absence of -m/-x options, perf probe checks if the first argument after
 the options is an absolute path name. If its an absolute path, perf probe
@@ -137,6 +148,7 @@ Each probe argument follows below syntax.
  [NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE]
 
 'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
+'$vars' special argument is also available for NAME, it is expanded to the local variables which can access at given probe point.
 'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type.
 
 On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid.
index 31e977459c519d933473d7a46d4bc1b14263ef7e..4847a793de6516df66dc609478c36724772bb941 100644 (file)
@@ -55,6 +55,11 @@ OPTIONS
           If you want to profile write accesses in [0x1000~1008), just set
           'mem:0x1000/8:w'.
 
+       - a group of events surrounded by a pair of brace ("{event1,event2,...}").
+         Each event is separated by commas and the group should be quoted to
+         prevent the shell interpretation.  You also need to use --group on
+         "perf report" to view group events together.
+
 --filter=<filter>::
         Event filter.
 
@@ -62,9 +67,6 @@ OPTIONS
 --all-cpus::
         System-wide collection from all CPUs.
 
--l::
-        Scale counter values.
-
 -p::
 --pid=::
        Record events on existing process ID (comma separated list).
@@ -107,6 +109,10 @@ OPTIONS
        specification with appended unit character - B/K/M/G. The
        size is rounded up to have nearest pages power of two value.
 
+--group::
+       Put all events in a single event group.  This precedes the --event
+       option and remains only for backward compatibility.  See --event.
+
 -g::
        Enables call-graph (stack chain/backtrace) recording.
 
@@ -115,13 +121,19 @@ OPTIONS
        implies -g.
 
        Allows specifying "fp" (frame pointer) or "dwarf"
-       (DWARF's CFI - Call Frame Information) as the method to collect
+       (DWARF's CFI - Call Frame Information) or "lbr"
+       (Hardware Last Branch Record facility) as the method to collect
        the information used to show the call graphs.
 
        In some systems, where binaries are build with gcc
        --fomit-frame-pointer, using the "fp" method will produce bogus
        call graphs, using "dwarf", if available (perf tools linked to
        the libunwind library) should be used instead.
+       Using the "lbr" method doesn't require any compiler options. It
+       will produce call graphs from the hardware LBR registers. The
+       main limition is that it is only available on new Intel
+       platforms, such as Haswell. It can only get user call chain. It
+       doesn't work with branch stack sampling at the same time.
 
 -q::
 --quiet::
@@ -235,6 +247,16 @@ Capture machine state (registers) at interrupt, i.e., on counter overflows for
 each sample. List of captured registers depends on the architecture. This option
 is off by default.
 
+--running-time::
+Record running and enabled time for read events (:S)
+
+-k::
+--clockid::
+Sets the clock id to use for the various time fields in the perf_event_type
+records. See clock_gettime(). In particular CLOCK_MONOTONIC and
+CLOCK_MONOTONIC_RAW are supported, some events might also allow
+CLOCK_BOOTTIME, CLOCK_REALTIME and CLOCK_TAI.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-list[1]
index dd7cccdde49883d30a6114151935ac4e2850cfc0..4879cf63882482155ffad05a3bc2abc8dff90f14 100644 (file)
@@ -40,6 +40,11 @@ OPTIONS
        Only consider symbols in these comms. CSV that understands
        file://filename entries.  This option will affect the percentage of
        the overhead column.  See --percentage for more info.
+--pid=::
+        Only show events for given process ID (comma separated list).
+
+--tid=::
+        Only show events for given thread ID (comma separated list).
 -d::
 --dsos=::
        Only consider symbols in these dsos. CSV that understands
index a21eec05bc42f8c2e0702e62d9eae965c9855221..79445750fcb322fb323c38b6e9a921500f5241c6 100644 (file)
@@ -193,6 +193,12 @@ OPTIONS
        Only display events for these comms. CSV that understands
        file://filename entries.
 
+--pid=::
+       Only show events for given process ID (comma separated list).
+
+--tid=::
+       Only show events for given thread ID (comma separated list).
+
 -I::
 --show-info::
        Display extended information about the perf.data file. This adds
index 7e1b1f2bb83c1b542425ab3fbd30ecf8fbbdf5fd..ba03fd5d1a5476ce218e6b5c7d36720a9ec26294 100644 (file)
@@ -55,6 +55,9 @@ OPTIONS
 --uid=::
         Record events in threads owned by uid. Name or number.
 
+--filter-pids=::
+       Filter out events for these pids and for 'trace' itself (comma separated list).
+
 -v::
 --verbose=::
         Verbosity level.
@@ -115,6 +118,9 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
 --syscalls::
        Trace system calls. This options is enabled by default.
 
+--event::
+       Trace other events, see 'perf list' for a complete list.
+
 PAGEFAULTS
 ----------
 
index 1e8e400b449375ab8c6b9bba5161d37ea7e1f5fe..2b131776363e3a2498ce1b721440c985d22df7fd 100644 (file)
@@ -13,11 +13,16 @@ SYNOPSIS
 OPTIONS
 -------
 --debug::
-       Setup debug variable (just verbose for now) in value
+       Setup debug variable (see list below) in value
        range (0, 10). Use like:
          --debug verbose   # sets verbose = 1
          --debug verbose=2 # sets verbose = 2
 
+       List of debug variables allowed to set:
+         verbose          - general debug messages
+         ordered-events   - ordered events object debug messages
+         data-convert     - data convert command debug messages
+
 --buildid-dir::
        Setup buildid cache directory. It has higher priority than
        buildid.dir config file option.
index fbbfdc39271dac69bd96aa932d6e62318dbce143..11ccbb22ea2b8f1538f07450504c35b50c10399f 100644 (file)
@@ -1,5 +1,6 @@
 tools/perf
 tools/scripts
+tools/build
 tools/lib/traceevent
 tools/lib/api
 tools/lib/symbol/kallsyms.c
index cb2e5868c8e86404729ed8595a53262cb9e88fd7..c699dc35eef9cbd1bc96427f453acc23a2e9c103 100644 (file)
@@ -24,8 +24,8 @@ unexport MAKEFLAGS
 # (To override it, run 'make JOBS=1' and similar.)
 #
 ifeq ($(JOBS),)
-  JOBS := $(shell grep -c ^processor /proc/cpuinfo 2>/dev/null)
-  ifeq ($(JOBS),)
+  JOBS := $(shell egrep -c '^processor|^CPU' /proc/cpuinfo 2>/dev/null)
+  ifeq ($(JOBS),0)
     JOBS := 1
   endif
 endif
index aa6a50447c32b63fd3f55a5ada5059610d610ec1..c43a2051759157dd6b65118b34b342b149f58861 100644 (file)
@@ -68,7 +68,11 @@ include config/utilities.mak
 # for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode
 #
 # Define NO_ZLIB if you do not want to support compressed kernel modules
-
+#
+# Define LIBBABELTRACE if you DO want libbabeltrace support
+# for CTF data format.
+#
+# Define NO_LZMA if you do not want to support compressed (xz) kernel modules
 
 ifeq ($(srctree),)
 srctree := $(patsubst %/,%,$(dir $(shell pwd)))
@@ -82,13 +86,29 @@ endif
 
 ifneq ($(OUTPUT),)
 #$(info Determined 'OUTPUT' to be $(OUTPUT))
+# Adding $(OUTPUT) as a directory to look for source files,
+# because use generated output files as sources dependency
+# for flex/bison parsers.
+VPATH += $(OUTPUT)
+export VPATH
 endif
 
+ifeq ($(V),1)
+  Q =
+else
+  Q = @
+endif
+
+# Do not use make's built-in rules
+# (this improves performance and avoids hard-to-debug behaviour);
+MAKEFLAGS += -r
+
 $(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD
-       @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
-       @touch $(OUTPUT)PERF-VERSION-FILE
+       $(Q)$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
+       $(Q)touch $(OUTPUT)PERF-VERSION-FILE
 
 CC = $(CROSS_COMPILE)gcc
+LD = $(CROSS_COMPILE)ld
 AR = $(CROSS_COMPILE)ar
 PKG_CONFIG = $(CROSS_COMPILE)pkg-config
 
@@ -127,10 +147,6 @@ export prefix bindir sharedir sysconfdir DESTDIR
 SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
 
 # Guard against environment variables
-BUILTIN_OBJS =
-LIB_H =
-LIB_OBJS =
-GTK_OBJS =
 PYRF_OBJS =
 SCRIPT_SH =
 
@@ -155,8 +171,8 @@ endif
 LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
 export LIBTRACEEVENT
 
-LIBAPIKFS = $(LIB_PATH)libapikfs.a
-export LIBAPIKFS
+LIBAPI = $(LIB_PATH)libapi.a
+export LIBAPI
 
 # python extension build directories
 PYTHON_EXTBUILD     := $(OUTPUT)python_ext_build/
@@ -167,7 +183,7 @@ export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
 python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
 
 PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
-PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPIKFS)
+PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
 
 $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
        $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
@@ -206,297 +222,9 @@ endif
 
 export PERL_PATH
 
-$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
-       $(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l
-
-$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
-       $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
-
-$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
-       $(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
-
-$(OUTPUT)util/pmu-bison.c: util/pmu.y
-       $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
-
-$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
-$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
-
 LIB_FILE=$(OUTPUT)libperf.a
 
-LIB_H += ../lib/symbol/kallsyms.h
-LIB_H += ../../include/uapi/linux/perf_event.h
-LIB_H += ../../include/linux/rbtree.h
-LIB_H += ../../include/linux/list.h
-LIB_H += ../../include/uapi/linux/const.h
-LIB_H += ../include/linux/hash.h
-LIB_H += ../../include/linux/stringify.h
-LIB_H += util/include/linux/bitmap.h
-LIB_H += ../include/linux/bitops.h
-LIB_H += ../include/asm-generic/bitops/arch_hweight.h
-LIB_H += ../include/asm-generic/bitops/atomic.h
-LIB_H += ../include/asm-generic/bitops/const_hweight.h
-LIB_H += ../include/asm-generic/bitops/find.h
-LIB_H += ../include/asm-generic/bitops/fls64.h
-LIB_H += ../include/asm-generic/bitops/fls.h
-LIB_H += ../include/asm-generic/bitops/__ffs.h
-LIB_H += ../include/asm-generic/bitops/__fls.h
-LIB_H += ../include/asm-generic/bitops/hweight.h
-LIB_H += ../include/asm-generic/bitops.h
-LIB_H += ../include/linux/compiler.h
-LIB_H += ../include/linux/log2.h
-LIB_H += util/include/linux/const.h
-LIB_H += util/include/linux/ctype.h
-LIB_H += util/include/linux/kernel.h
-LIB_H += util/include/linux/list.h
-LIB_H += ../include/linux/export.h
-LIB_H += util/include/linux/poison.h
-LIB_H += util/include/linux/rbtree.h
-LIB_H += util/include/linux/rbtree_augmented.h
-LIB_H += util/include/linux/string.h
-LIB_H += ../include/linux/types.h
-LIB_H += util/include/linux/linkage.h
-LIB_H += util/include/asm/asm-offsets.h
-LIB_H += ../include/asm/bug.h
-LIB_H += util/include/asm/byteorder.h
-LIB_H += util/include/asm/swab.h
-LIB_H += util/include/asm/system.h
-LIB_H += util/include/asm/uaccess.h
-LIB_H += util/include/dwarf-regs.h
-LIB_H += util/include/asm/dwarf2.h
-LIB_H += util/include/asm/cpufeature.h
-LIB_H += util/include/asm/unistd_32.h
-LIB_H += util/include/asm/unistd_64.h
-LIB_H += perf.h
-LIB_H += util/annotate.h
-LIB_H += util/cache.h
-LIB_H += util/callchain.h
-LIB_H += util/build-id.h
-LIB_H += util/db-export.h
-LIB_H += util/debug.h
-LIB_H += util/pmu.h
-LIB_H += util/event.h
-LIB_H += util/evsel.h
-LIB_H += util/evlist.h
-LIB_H += util/exec_cmd.h
-LIB_H += util/find-vdso-map.c
-LIB_H += util/levenshtein.h
-LIB_H += util/machine.h
-LIB_H += util/map.h
-LIB_H += util/parse-options.h
-LIB_H += util/parse-events.h
-LIB_H += util/quote.h
-LIB_H += util/util.h
-LIB_H += util/xyarray.h
-LIB_H += util/header.h
-LIB_H += util/help.h
-LIB_H += util/session.h
-LIB_H += util/ordered-events.h
-LIB_H += util/strbuf.h
-LIB_H += util/strlist.h
-LIB_H += util/strfilter.h
-LIB_H += util/svghelper.h
-LIB_H += util/tool.h
-LIB_H += util/run-command.h
-LIB_H += util/sigchain.h
-LIB_H += util/dso.h
-LIB_H += util/symbol.h
-LIB_H += util/color.h
-LIB_H += util/values.h
-LIB_H += util/sort.h
-LIB_H += util/hist.h
-LIB_H += util/comm.h
-LIB_H += util/thread.h
-LIB_H += util/thread_map.h
-LIB_H += util/trace-event.h
-LIB_H += util/probe-finder.h
-LIB_H += util/dwarf-aux.h
-LIB_H += util/probe-event.h
-LIB_H += util/pstack.h
-LIB_H += util/cpumap.h
-LIB_H += util/top.h
-LIB_H += $(ARCH_INCLUDE)
-LIB_H += util/cgroup.h
-LIB_H += $(LIB_INCLUDE)traceevent/event-parse.h
-LIB_H += util/target.h
-LIB_H += util/rblist.h
-LIB_H += util/intlist.h
-LIB_H += util/perf_regs.h
-LIB_H += util/unwind.h
-LIB_H += util/vdso.h
-LIB_H += util/tsc.h
-LIB_H += ui/helpline.h
-LIB_H += ui/progress.h
-LIB_H += ui/util.h
-LIB_H += ui/ui.h
-LIB_H += util/data.h
-LIB_H += util/kvm-stat.h
-LIB_H += util/thread-stack.h
-
-LIB_OBJS += $(OUTPUT)util/abspath.o
-LIB_OBJS += $(OUTPUT)util/alias.o
-LIB_OBJS += $(OUTPUT)util/annotate.o
-LIB_OBJS += $(OUTPUT)util/build-id.o
-LIB_OBJS += $(OUTPUT)util/config.o
-LIB_OBJS += $(OUTPUT)util/ctype.o
-LIB_OBJS += $(OUTPUT)util/db-export.o
-LIB_OBJS += $(OUTPUT)util/pmu.o
-LIB_OBJS += $(OUTPUT)util/environment.o
-LIB_OBJS += $(OUTPUT)util/event.o
-LIB_OBJS += $(OUTPUT)util/evlist.o
-LIB_OBJS += $(OUTPUT)util/evsel.o
-LIB_OBJS += $(OUTPUT)util/exec_cmd.o
-LIB_OBJS += $(OUTPUT)util/find_next_bit.o
-LIB_OBJS += $(OUTPUT)util/help.o
-LIB_OBJS += $(OUTPUT)util/kallsyms.o
-LIB_OBJS += $(OUTPUT)util/levenshtein.o
-LIB_OBJS += $(OUTPUT)util/parse-options.o
-LIB_OBJS += $(OUTPUT)util/parse-events.o
-LIB_OBJS += $(OUTPUT)util/path.o
-LIB_OBJS += $(OUTPUT)util/rbtree.o
-LIB_OBJS += $(OUTPUT)util/bitmap.o
-LIB_OBJS += $(OUTPUT)util/hweight.o
-LIB_OBJS += $(OUTPUT)util/run-command.o
-LIB_OBJS += $(OUTPUT)util/quote.o
-LIB_OBJS += $(OUTPUT)util/strbuf.o
-LIB_OBJS += $(OUTPUT)util/string.o
-LIB_OBJS += $(OUTPUT)util/strlist.o
-LIB_OBJS += $(OUTPUT)util/strfilter.o
-LIB_OBJS += $(OUTPUT)util/top.o
-LIB_OBJS += $(OUTPUT)util/usage.o
-LIB_OBJS += $(OUTPUT)util/wrapper.o
-LIB_OBJS += $(OUTPUT)util/sigchain.o
-LIB_OBJS += $(OUTPUT)util/dso.o
-LIB_OBJS += $(OUTPUT)util/symbol.o
-LIB_OBJS += $(OUTPUT)util/symbol-elf.o
-LIB_OBJS += $(OUTPUT)util/color.o
-LIB_OBJS += $(OUTPUT)util/pager.o
-LIB_OBJS += $(OUTPUT)util/header.o
-LIB_OBJS += $(OUTPUT)util/callchain.o
-LIB_OBJS += $(OUTPUT)util/values.o
-LIB_OBJS += $(OUTPUT)util/debug.o
-LIB_OBJS += $(OUTPUT)util/machine.o
-LIB_OBJS += $(OUTPUT)util/map.o
-LIB_OBJS += $(OUTPUT)util/pstack.o
-LIB_OBJS += $(OUTPUT)util/session.o
-LIB_OBJS += $(OUTPUT)util/ordered-events.o
-LIB_OBJS += $(OUTPUT)util/comm.o
-LIB_OBJS += $(OUTPUT)util/thread.o
-LIB_OBJS += $(OUTPUT)util/thread_map.o
-LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
-LIB_OBJS += $(OUTPUT)util/parse-events-flex.o
-LIB_OBJS += $(OUTPUT)util/parse-events-bison.o
-LIB_OBJS += $(OUTPUT)util/pmu-flex.o
-LIB_OBJS += $(OUTPUT)util/pmu-bison.o
-LIB_OBJS += $(OUTPUT)util/trace-event-read.o
-LIB_OBJS += $(OUTPUT)util/trace-event-info.o
-LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
-LIB_OBJS += $(OUTPUT)util/trace-event.o
-LIB_OBJS += $(OUTPUT)util/svghelper.o
-LIB_OBJS += $(OUTPUT)util/sort.o
-LIB_OBJS += $(OUTPUT)util/hist.o
-LIB_OBJS += $(OUTPUT)util/probe-event.o
-LIB_OBJS += $(OUTPUT)util/util.o
-LIB_OBJS += $(OUTPUT)util/xyarray.o
-LIB_OBJS += $(OUTPUT)util/cpumap.o
-LIB_OBJS += $(OUTPUT)util/cgroup.o
-LIB_OBJS += $(OUTPUT)util/target.o
-LIB_OBJS += $(OUTPUT)util/rblist.o
-LIB_OBJS += $(OUTPUT)util/intlist.o
-LIB_OBJS += $(OUTPUT)util/vdso.o
-LIB_OBJS += $(OUTPUT)util/stat.o
-LIB_OBJS += $(OUTPUT)util/record.o
-LIB_OBJS += $(OUTPUT)util/srcline.o
-LIB_OBJS += $(OUTPUT)util/data.o
-LIB_OBJS += $(OUTPUT)util/tsc.o
-LIB_OBJS += $(OUTPUT)util/cloexec.o
-LIB_OBJS += $(OUTPUT)util/thread-stack.o
-
-LIB_OBJS += $(OUTPUT)ui/setup.o
-LIB_OBJS += $(OUTPUT)ui/helpline.o
-LIB_OBJS += $(OUTPUT)ui/progress.o
-LIB_OBJS += $(OUTPUT)ui/util.o
-LIB_OBJS += $(OUTPUT)ui/hist.o
-LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
-
-LIB_OBJS += $(OUTPUT)arch/common.o
-
-LIB_OBJS += $(OUTPUT)tests/parse-events.o
-LIB_OBJS += $(OUTPUT)tests/dso-data.o
-LIB_OBJS += $(OUTPUT)tests/attr.o
-LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
-LIB_OBJS += $(OUTPUT)tests/open-syscall.o
-LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
-LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
-LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
-LIB_OBJS += $(OUTPUT)tests/perf-record.o
-LIB_OBJS += $(OUTPUT)tests/rdpmc.o
-LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
-LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
-LIB_OBJS += $(OUTPUT)tests/fdarray.o
-LIB_OBJS += $(OUTPUT)tests/pmu.o
-LIB_OBJS += $(OUTPUT)tests/hists_common.o
-LIB_OBJS += $(OUTPUT)tests/hists_link.o
-LIB_OBJS += $(OUTPUT)tests/hists_filter.o
-LIB_OBJS += $(OUTPUT)tests/hists_output.o
-LIB_OBJS += $(OUTPUT)tests/hists_cumulate.o
-LIB_OBJS += $(OUTPUT)tests/python-use.o
-LIB_OBJS += $(OUTPUT)tests/bp_signal.o
-LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
-LIB_OBJS += $(OUTPUT)tests/task-exit.o
-LIB_OBJS += $(OUTPUT)tests/sw-clock.o
-ifeq ($(ARCH),x86)
-LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
-endif
-LIB_OBJS += $(OUTPUT)tests/code-reading.o
-LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
-LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
-ifndef NO_DWARF_UNWIND
-ifeq ($(ARCH),$(filter $(ARCH),x86 arm))
-LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o
-endif
-endif
-LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o
-LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o
-LIB_OBJS += $(OUTPUT)tests/switch-tracking.o
-
-BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
-BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
-# Benchmark modules
-BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
-BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
-ifeq ($(ARCH), x86)
-ifeq ($(IS_64_BIT), 1)
-BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
-BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
-endif
-endif
-BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
-BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o
-BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o
-BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o
-
-BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
-BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
-BUILTIN_OBJS += $(OUTPUT)builtin-help.o
-BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
-BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
-BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o
-BUILTIN_OBJS += $(OUTPUT)builtin-list.o
-BUILTIN_OBJS += $(OUTPUT)builtin-record.o
-BUILTIN_OBJS += $(OUTPUT)builtin-report.o
-BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
-BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
-BUILTIN_OBJS += $(OUTPUT)builtin-top.o
-BUILTIN_OBJS += $(OUTPUT)builtin-script.o
-BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
-BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
-BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
-BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
-BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
-BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
-BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
-
-PERFLIBS = $(LIB_FILE) $(LIBAPIKFS) $(LIBTRACEEVENT)
+PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT)
 
 # We choose to avoid "if .. else if .. else .. endif endif"
 # because maintaining the nesting to match is a pain.  If
@@ -508,67 +236,9 @@ ifneq ($(OUTPUT),)
   CFLAGS += -I$(OUTPUT)
 endif
 
-ifdef NO_LIBELF
-# Remove ELF/DWARF dependent codes
-LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
-LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
-LIB_OBJS := $(filter-out $(OUTPUT)util/probe-event.o,$(LIB_OBJS))
-LIB_OBJS := $(filter-out $(OUTPUT)util/probe-finder.o,$(LIB_OBJS))
-
-BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
-
-# Use minimal symbol handling
-LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
-
-else # NO_LIBELF
-ifndef NO_DWARF
-  LIB_OBJS += $(OUTPUT)util/probe-finder.o
-  LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
-endif # NO_DWARF
-endif # NO_LIBELF
-
-ifndef NO_LIBDW_DWARF_UNWIND
-  LIB_OBJS += $(OUTPUT)util/unwind-libdw.o
-  LIB_H += util/unwind-libdw.h
-endif
-
-ifndef NO_LIBUNWIND
-  LIB_OBJS += $(OUTPUT)util/unwind-libunwind.o
-endif
-LIB_OBJS += $(OUTPUT)tests/keep-tracking.o
-
-ifndef NO_LIBAUDIT
-  BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
-endif
-
-ifndef NO_SLANG
-  LIB_OBJS += $(OUTPUT)ui/browser.o
-  LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
-  LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
-  LIB_OBJS += $(OUTPUT)ui/browsers/map.o
-  LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
-  LIB_OBJS += $(OUTPUT)ui/browsers/header.o
-  LIB_OBJS += $(OUTPUT)ui/tui/setup.o
-  LIB_OBJS += $(OUTPUT)ui/tui/util.o
-  LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
-  LIB_OBJS += $(OUTPUT)ui/tui/progress.o
-  LIB_H += ui/tui/tui.h
-  LIB_H += ui/browser.h
-  LIB_H += ui/browsers/map.h
-  LIB_H += ui/keysyms.h
-  LIB_H += ui/libslang.h
-endif
-
 ifndef NO_GTK2
   ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so
-
-  GTK_OBJS += $(OUTPUT)ui/gtk/browser.o
-  GTK_OBJS += $(OUTPUT)ui/gtk/hists.o
-  GTK_OBJS += $(OUTPUT)ui/gtk/setup.o
-  GTK_OBJS += $(OUTPUT)ui/gtk/util.o
-  GTK_OBJS += $(OUTPUT)ui/gtk/helpline.o
-  GTK_OBJS += $(OUTPUT)ui/gtk/progress.o
-  GTK_OBJS += $(OUTPUT)ui/gtk/annotate.o
+  GTK_IN := $(OUTPUT)gtk-in.o
 
 install-gtk: $(OUTPUT)libperf-gtk.so
        $(call QUIET_INSTALL, 'GTK UI') \
@@ -576,31 +246,6 @@ install-gtk: $(OUTPUT)libperf-gtk.so
                $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)'
 endif
 
-ifndef NO_LIBPERL
-  LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
-  LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
-endif
-
-ifndef NO_LIBPYTHON
-  LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
-  LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
-endif
-
-ifeq ($(NO_PERF_REGS),0)
-  ifeq ($(ARCH),x86)
-    LIB_H += arch/x86/include/perf_regs.h
-  endif
-  LIB_OBJS += $(OUTPUT)util/perf_regs.o
-endif
-
-ifndef NO_LIBNUMA
-  BUILTIN_OBJS += $(OUTPUT)bench/numa.o
-endif
-
-ifndef NO_ZLIB
-  LIB_OBJS += $(OUTPUT)util/zlib.o
-endif
-
 ifdef ASCIIDOC8
   export ASCIIDOC8
 endif
@@ -616,39 +261,29 @@ SHELL = $(SHELL_PATH)
 all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
 
 please_set_SHELL_PATH_to_a_more_modern_shell:
-       @$$(:)
+       $(Q)$$(:)
 
 shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
 
 strip: $(PROGRAMS) $(OUTPUT)perf
        $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
 
-$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \
-               '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
-               $(CFLAGS) -c $(filter %.c,$^) -o $@
+PERF_IN := $(OUTPUT)perf-in.o
 
-$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
-       $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUT)perf.o \
-               $(BUILTIN_OBJS) $(LIBS) -o $@
+export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX
+build := -f $(srctree)/tools/build/Makefile.build dir=. obj
 
-$(GTK_OBJS): $(OUTPUT)%.o: %.c $(LIB_H)
-       $(QUIET_CC)$(CC) -o $@ -c -fPIC $(CFLAGS) $(GTK_CFLAGS) $<
+$(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE
+       $(Q)$(MAKE) $(build)=perf
 
-$(OUTPUT)libperf-gtk.so: $(GTK_OBJS) $(PERFLIBS)
-       $(QUIET_LINK)$(CC) -o $@ -shared $(LDFLAGS) $(filter %.o,$^) $(GTK_LIBS)
+$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN)
+       $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(PERF_IN) $(LIBS) -o $@
 
-$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
-               '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
-               '-DPERF_MAN_PATH="$(mandir_SQ)"' \
-               '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
+$(GTK_IN): FORCE
+       $(Q)$(MAKE) $(build)=gtk
 
-$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
-               '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
-               '-DPERF_MAN_PATH="$(mandir_SQ)"' \
-               '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
+$(OUTPUT)libperf-gtk.so: $(GTK_IN) $(PERFLIBS)
+       $(QUIET_LINK)$(CC) -o $@ -shared $(LDFLAGS) $(filter %.o,$^) $(GTK_LIBS)
 
 $(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
 
@@ -659,8 +294,7 @@ $(SCRIPTS) : % : %.sh
        $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
 
 # These can record PERF_VERSION
-$(OUTPUT)perf.o perf.spec \
-       $(SCRIPTS) \
+perf.spec $(SCRIPTS) \
        : $(OUTPUT)PERF-VERSION-FILE
 
 .SUFFIXES:
@@ -683,90 +317,33 @@ endif
 # These two need to be here so that when O= is not used they take precedence
 # over the general rule for .o
 
-$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -w $<
-
-$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $<
-
-$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
-$(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
-$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -S $(CFLAGS) $<
-$(OUTPUT)%.o: %.S
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
-$(OUTPUT)%.s: %.S
-       $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
-
-$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
-               '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
-               '-DPREFIX="$(prefix_SQ)"' \
-               $<
-
-$(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
-               '-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \
-               $<
-
-$(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
-               -DPYTHONPATH='"$(OUTPUT)python"' \
-               -DPYTHON='"$(PYTHON_WORD)"' \
-               $<
-
-$(OUTPUT)tests/dwarf-unwind.o: tests/dwarf-unwind.c
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -fno-optimize-sibling-calls $<
+# get relative building directory (to $(OUTPUT))
+# and '.' if it's $(OUTPUT) itself
+__build-dir = $(subst $(OUTPUT),,$(dir $@))
+build-dir   = $(if $(__build-dir),$(__build-dir),.)
 
-$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
+single_dep: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
 
-$(OUTPUT)ui/setup.o: ui/setup.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DLIBDIR='"$(libdir_SQ)"' $<
+$(OUTPUT)%.o: %.c single_dep FORCE
+       $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
 
-$(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
+$(OUTPUT)%.i: %.c single_dep FORCE
+       $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
 
-$(OUTPUT)ui/browsers/annotate.o: ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
+$(OUTPUT)%.s: %.c single_dep FORCE
+       $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
 
-$(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
+$(OUTPUT)%-bison.o: %.c single_dep FORCE
+       $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
 
-$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
+$(OUTPUT)%-flex.o: %.c single_dep FORCE
+       $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
 
-$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
+$(OUTPUT)%.o: %.S single_dep FORCE
+       $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
 
-$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
-
-$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
-
-$(OUTPUT)util/hweight.o: ../../lib/hweight.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
-
-$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
-
-$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
-
-$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $<
-
-$(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $<
-
-$(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
-
-$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
-       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
+$(OUTPUT)%.i: %.S single_dep FORCE
+       $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
 
 $(OUTPUT)perf-%: %.o $(PERFLIBS)
        $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
@@ -781,58 +358,34 @@ $(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-vdso-map.c
        $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
 endif
 
-$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
-$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
+$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
 
-# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So
-# we depend the various files onto their directories.
-DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS)
-DIRECTORY_DEPS += $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
-# no need to add flex objects, because they depend on bison ones
-DIRECTORY_DEPS += $(OUTPUT)util/parse-events-bison.c
-DIRECTORY_DEPS += $(OUTPUT)util/pmu-bison.c
+LIBPERF_IN := $(OUTPUT)libperf-in.o
 
-OUTPUT_DIRECTORIES := $(sort $(dir $(DIRECTORY_DEPS)))
+$(LIBPERF_IN): FORCE
+       $(Q)$(MAKE) $(build)=libperf
 
-$(DIRECTORY_DEPS): | $(OUTPUT_DIRECTORIES)
-# In the second step, we make a rule to actually create these directories
-$(OUTPUT_DIRECTORIES):
-       $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
+$(LIB_FILE): $(LIBPERF_IN)
+       $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN) $(LIB_OBJS)
 
-$(LIB_FILE): $(LIB_OBJS)
-       $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
-
-# libtraceevent.a
-TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch])
-
-LIBTRACEEVENT_FLAGS  = $(QUIET_SUBDIR1) O=$(OUTPUT)
-LIBTRACEEVENT_FLAGS += CFLAGS="-g -Wall $(EXTRA_CFLAGS)"
 LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ)
 
-$(LIBTRACEEVENT): $(TE_SOURCES) $(OUTPUT)PERF-CFLAGS
-       $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) libtraceevent.a plugins
+$(LIBTRACEEVENT): FORCE
+       $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a plugins
 
 $(LIBTRACEEVENT)-clean:
        $(call QUIET_CLEAN, libtraceevent)
-       @$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null
+       $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null
 
 install-traceevent-plugins: $(LIBTRACEEVENT)
-       $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins
+       $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins
 
-LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch] $(LIB_PATH)fd/*.[ch])
-
-# if subdir is set, we've been called from above so target has been built
-# already
-$(LIBAPIKFS): $(LIBAPIKFS_SOURCES)
-ifeq ($(subdir),)
-       $(QUIET_SUBDIR0)$(LIB_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libapikfs.a
-endif
+$(LIBAPI): FORCE
+       $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) $(OUTPUT)libapi.a
 
-$(LIBAPIKFS)-clean:
-ifeq ($(subdir),)
-       $(call QUIET_CLEAN, libapikfs)
-       @$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
-endif
+$(LIBAPI)-clean:
+       $(call QUIET_CLEAN, libapi)
+       $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
 
 help:
        @echo 'Perf make targets:'
@@ -888,17 +441,6 @@ cscope:
        $(QUIET_GEN)$(RM) cscope*; \
        $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs cscope -b $(TAG_FILES)
 
-### Detect prefix changes
-TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
-             $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):$(plugindir_SQ)
-
-$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
-       @FLAGS='$(TRACK_CFLAGS)'; \
-           if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \
-               echo 1>&2 "  FLAGS:   * new build flags or prefix"; \
-               echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
-            fi
-
 ### Testing rules
 
 # GNU make supports exporting all variables by "export" without parameters.
@@ -981,12 +523,14 @@ $(INSTALL_DOC_TARGETS):
 #
 config-clean:
        $(call QUIET_CLEAN, config)
-       @$(MAKE) -C config/feature-checks clean >/dev/null
+       $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null
 
-clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
-       $(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
+clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean
+       $(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
+       $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
+       $(Q)$(RM) .config-detected
        $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
-       $(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
+       $(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
        $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
        $(python-clean)
 
@@ -1000,7 +544,9 @@ else
     GIT-HEAD-PHONY =
 endif
 
+FORCE:
+
 .PHONY: all install clean config-clean strip install-gtk
 .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
-.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope .FORCE-PERF-CFLAGS
+.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE single_dep
 
diff --git a/tools/perf/arch/Build b/tools/perf/arch/Build
new file mode 100644 (file)
index 0000000..109eb75
--- /dev/null
@@ -0,0 +1,2 @@
+libperf-y += common.o
+libperf-y += $(ARCH)/
diff --git a/tools/perf/arch/arm/Build b/tools/perf/arch/arm/Build
new file mode 100644 (file)
index 0000000..41bf61d
--- /dev/null
@@ -0,0 +1,2 @@
+libperf-y += util/
+libperf-$(CONFIG_DWARF_UNWIND) += tests/
index 09d62153d38417ce16f747924749cc7d62a390bd..7fbca175099ec917ad69b8025c8249ee6c52a6a4 100644 (file)
@@ -1,14 +1,3 @@
 ifndef NO_DWARF
 PERF_HAVE_DWARF_REGS := 1
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
-endif
-ifndef NO_LIBUNWIND
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
-endif
-ifndef NO_LIBDW_DWARF_UNWIND
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libdw.o
-endif
-ifndef NO_DWARF_UNWIND
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o
 endif
diff --git a/tools/perf/arch/arm/tests/Build b/tools/perf/arch/arm/tests/Build
new file mode 100644 (file)
index 0000000..b30eff9
--- /dev/null
@@ -0,0 +1,2 @@
+libperf-y += regs_load.o
+libperf-y += dwarf-unwind.o
diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build
new file mode 100644 (file)
index 0000000..d22e3d0
--- /dev/null
@@ -0,0 +1,4 @@
+libperf-$(CONFIG_DWARF) += dwarf-regs.o
+
+libperf-$(CONFIG_LIBUNWIND)          += unwind-libunwind.o
+libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
diff --git a/tools/perf/arch/arm64/Build b/tools/perf/arch/arm64/Build
new file mode 100644 (file)
index 0000000..54afe4a
--- /dev/null
@@ -0,0 +1 @@
+libperf-y += util/
index 67e9b3d38e89209dec2810a9ca229127fd49f17c..7fbca175099ec917ad69b8025c8249ee6c52a6a4 100644 (file)
@@ -1,7 +1,3 @@
 ifndef NO_DWARF
 PERF_HAVE_DWARF_REGS := 1
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
-endif
-ifndef NO_LIBUNWIND
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
 endif
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
new file mode 100644 (file)
index 0000000..e58123a
--- /dev/null
@@ -0,0 +1,2 @@
+libperf-$(CONFIG_DWARF)     += dwarf-regs.o
+libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
diff --git a/tools/perf/arch/powerpc/Build b/tools/perf/arch/powerpc/Build
new file mode 100644 (file)
index 0000000..54afe4a
--- /dev/null
@@ -0,0 +1 @@
+libperf-y += util/
index 6f7782bea5dd848c9e31985fb159b0eea11ca9ba..7fbca175099ec917ad69b8025c8249ee6c52a6a4 100644 (file)
@@ -1,6 +1,3 @@
 ifndef NO_DWARF
 PERF_HAVE_DWARF_REGS := 1
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
 endif
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build
new file mode 100644 (file)
index 0000000..0af6e9b
--- /dev/null
@@ -0,0 +1,4 @@
+libperf-y += header.o
+
+libperf-$(CONFIG_DWARF) += dwarf-regs.o
+libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
diff --git a/tools/perf/arch/s390/Build b/tools/perf/arch/s390/Build
new file mode 100644 (file)
index 0000000..54afe4a
--- /dev/null
@@ -0,0 +1 @@
+libperf-y += util/
index 798ac7379c5fa4a1217a75e5e6a1a60ebd58d774..21322e0385b886667d7bbd9a17edddc1ad1b3c8f 100644 (file)
@@ -1,7 +1,4 @@
 ifndef NO_DWARF
 PERF_HAVE_DWARF_REGS := 1
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
 endif
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
 HAVE_KVM_STAT_SUPPORT := 1
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
diff --git a/tools/perf/arch/s390/util/Build b/tools/perf/arch/s390/util/Build
new file mode 100644 (file)
index 0000000..8a61372
--- /dev/null
@@ -0,0 +1,4 @@
+libperf-y += header.o
+libperf-y += kvm-stat.o
+
+libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/arch/sh/Build b/tools/perf/arch/sh/Build
new file mode 100644 (file)
index 0000000..54afe4a
--- /dev/null
@@ -0,0 +1 @@
+libperf-y += util/
index 15130b50dfe3be2fea6a975a102283f6d33e4887..7fbca175099ec917ad69b8025c8249ee6c52a6a4 100644 (file)
@@ -1,4 +1,3 @@
 ifndef NO_DWARF
 PERF_HAVE_DWARF_REGS := 1
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
 endif
diff --git a/tools/perf/arch/sh/util/Build b/tools/perf/arch/sh/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/sparc/Build b/tools/perf/arch/sparc/Build
new file mode 100644 (file)
index 0000000..54afe4a
--- /dev/null
@@ -0,0 +1 @@
+libperf-y += util/
index 15130b50dfe3be2fea6a975a102283f6d33e4887..7fbca175099ec917ad69b8025c8249ee6c52a6a4 100644 (file)
@@ -1,4 +1,3 @@
 ifndef NO_DWARF
 PERF_HAVE_DWARF_REGS := 1
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
 endif
diff --git a/tools/perf/arch/sparc/util/Build b/tools/perf/arch/sparc/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/x86/Build b/tools/perf/arch/x86/Build
new file mode 100644 (file)
index 0000000..41bf61d
--- /dev/null
@@ -0,0 +1,2 @@
+libperf-y += util/
+libperf-$(CONFIG_DWARF_UNWIND) += tests/
index 9b21881db52f9e2b2205b4106e9fba30c57700ed..21322e0385b886667d7bbd9a17edddc1ad1b3c8f 100644 (file)
@@ -1,19 +1,4 @@
 ifndef NO_DWARF
 PERF_HAVE_DWARF_REGS := 1
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
 endif
-ifndef NO_LIBUNWIND
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
-endif
-ifndef NO_LIBDW_DWARF_UNWIND
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libdw.o
-endif
-ifndef NO_DWARF_UNWIND
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o
-endif
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o
-LIB_H += arch/$(ARCH)/util/tsc.h
 HAVE_KVM_STAT_SUPPORT := 1
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
diff --git a/tools/perf/arch/x86/tests/Build b/tools/perf/arch/x86/tests/Build
new file mode 100644 (file)
index 0000000..b30eff9
--- /dev/null
@@ -0,0 +1,2 @@
+libperf-y += regs_load.o
+libperf-y += dwarf-unwind.o
diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build
new file mode 100644 (file)
index 0000000..cfbccc4
--- /dev/null
@@ -0,0 +1,8 @@
+libperf-y += header.o
+libperf-y += tsc.o
+libperf-y += kvm-stat.o
+
+libperf-$(CONFIG_DWARF) += dwarf-regs.o
+
+libperf-$(CONFIG_LIBUNWIND)          += unwind-libunwind.o
+libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
diff --git a/tools/perf/bench/Build b/tools/perf/bench/Build
new file mode 100644 (file)
index 0000000..5ce9802
--- /dev/null
@@ -0,0 +1,11 @@
+perf-y += sched-messaging.o
+perf-y += sched-pipe.o
+perf-y += mem-memcpy.o
+perf-y += futex-hash.o
+perf-y += futex-wake.o
+perf-y += futex-requeue.o
+
+perf-$(CONFIG_X86_64) += mem-memcpy-x86-64-asm.o
+perf-$(CONFIG_X86_64) += mem-memset-x86-64-asm.o
+
+perf-$(CONFIG_NUMA) += numa.o
index d66ab799b35fd5cab83e5486368e40c39c2927ee..8c0c1a2770c8fe01bb479c97847540befe164011 100644 (file)
@@ -1,12 +1,12 @@
 
-MEMCPY_FN(__memcpy,
+MEMCPY_FN(memcpy_orig,
        "x86-64-unrolled",
        "unrolled memcpy() in arch/x86/lib/memcpy_64.S")
 
-MEMCPY_FN(memcpy_c,
+MEMCPY_FN(__memcpy,
        "x86-64-movsq",
        "movsq-based memcpy() in arch/x86/lib/memcpy_64.S")
 
-MEMCPY_FN(memcpy_c_e,
+MEMCPY_FN(memcpy_erms,
        "x86-64-movsb",
        "movsb-based memcpy() in arch/x86/lib/memcpy_64.S")
index fcd9cf00600a970677dd331cfc7f71de0d67d00e..e4c2c30143b95133913a2bc3569b2871b79aa75c 100644 (file)
@@ -1,8 +1,6 @@
 #define memcpy MEMCPY /* don't hide glibc's memcpy() */
 #define altinstr_replacement text
 #define globl p2align 4; .globl
-#define Lmemcpy_c globl memcpy_c; memcpy_c
-#define Lmemcpy_c_e globl memcpy_c_e; memcpy_c_e
 #include "../../../arch/x86/lib/memcpy_64.S"
 /*
  * We need to provide note.GNU-stack section, saying that we want
index db1d3a29d97fec67c47a4dd84eca2f7779ec1865..d3dfb7936dcdfd688d20ae680b3b0c0009cdeb55 100644 (file)
@@ -36,7 +36,7 @@ static const struct option options[] = {
                    "Specify length of memory to copy. "
                    "Available units: B, KB, MB, GB and TB (upper and lower)"),
        OPT_STRING('r', "routine", &routine, "default",
-                   "Specify routine to copy"),
+                   "Specify routine to copy, \"all\" runs all available routines"),
        OPT_INTEGER('i', "iterations", &iterations,
                    "repeat memcpy() invocation this number of times"),
        OPT_BOOLEAN('c', "cycle", &use_cycle,
@@ -135,55 +135,16 @@ struct bench_mem_info {
        const char *const *usage;
 };
 
-static int bench_mem_common(int argc, const char **argv,
-                    const char *prefix __maybe_unused,
-                    struct bench_mem_info *info)
+static void __bench_mem_routine(struct bench_mem_info *info, int r_idx, size_t len, double totallen)
 {
-       int i;
-       size_t len;
-       double totallen;
+       const struct routine *r = &info->routines[r_idx];
        double result_bps[2];
        u64 result_cycle[2];
 
-       argc = parse_options(argc, argv, options,
-                            info->usage, 0);
-
-       if (no_prefault && only_prefault) {
-               fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
-               return 1;
-       }
-
-       if (use_cycle)
-               init_cycle();
-
-       len = (size_t)perf_atoll((char *)length_str);
-       totallen = (double)len * iterations;
-
        result_cycle[0] = result_cycle[1] = 0ULL;
        result_bps[0] = result_bps[1] = 0.0;
 
-       if ((s64)len <= 0) {
-               fprintf(stderr, "Invalid length:%s\n", length_str);
-               return 1;
-       }
-
-       /* same to without specifying either of prefault and no-prefault */
-       if (only_prefault && no_prefault)
-               only_prefault = no_prefault = false;
-
-       for (i = 0; info->routines[i].name; i++) {
-               if (!strcmp(info->routines[i].name, routine))
-                       break;
-       }
-       if (!info->routines[i].name) {
-               printf("Unknown routine:%s\n", routine);
-               printf("Available routines...\n");
-               for (i = 0; info->routines[i].name; i++) {
-                       printf("\t%s ... %s\n",
-                              info->routines[i].name, info->routines[i].desc);
-               }
-               return 1;
-       }
+       printf("Routine %s (%s)\n", r->name, r->desc);
 
        if (bench_format == BENCH_FORMAT_DEFAULT)
                printf("# Copying %s Bytes ...\n\n", length_str);
@@ -191,28 +152,17 @@ static int bench_mem_common(int argc, const char **argv,
        if (!only_prefault && !no_prefault) {
                /* show both of results */
                if (use_cycle) {
-                       result_cycle[0] =
-                               info->do_cycle(&info->routines[i], len, false);
-                       result_cycle[1] =
-                               info->do_cycle(&info->routines[i], len, true);
+                       result_cycle[0] = info->do_cycle(r, len, false);
+                       result_cycle[1] = info->do_cycle(r, len, true);
                } else {
-                       result_bps[0] =
-                               info->do_gettimeofday(&info->routines[i],
-                                               len, false);
-                       result_bps[1] =
-                               info->do_gettimeofday(&info->routines[i],
-                                               len, true);
+                       result_bps[0]   = info->do_gettimeofday(r, len, false);
+                       result_bps[1]   = info->do_gettimeofday(r, len, true);
                }
        } else {
-               if (use_cycle) {
-                       result_cycle[pf] =
-                               info->do_cycle(&info->routines[i],
-                                               len, only_prefault);
-               } else {
-                       result_bps[pf] =
-                               info->do_gettimeofday(&info->routines[i],
-                                               len, only_prefault);
-               }
+               if (use_cycle)
+                       result_cycle[pf] = info->do_cycle(r, len, only_prefault);
+               else
+                       result_bps[pf] = info->do_gettimeofday(r, len, only_prefault);
        }
 
        switch (bench_format) {
@@ -265,6 +215,60 @@ static int bench_mem_common(int argc, const char **argv,
                die("unknown format: %d\n", bench_format);
                break;
        }
+}
+
+static int bench_mem_common(int argc, const char **argv,
+                    const char *prefix __maybe_unused,
+                    struct bench_mem_info *info)
+{
+       int i;
+       size_t len;
+       double totallen;
+
+       argc = parse_options(argc, argv, options,
+                            info->usage, 0);
+
+       if (no_prefault && only_prefault) {
+               fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
+               return 1;
+       }
+
+       if (use_cycle)
+               init_cycle();
+
+       len = (size_t)perf_atoll((char *)length_str);
+       totallen = (double)len * iterations;
+
+       if ((s64)len <= 0) {
+               fprintf(stderr, "Invalid length:%s\n", length_str);
+               return 1;
+       }
+
+       /* same to without specifying either of prefault and no-prefault */
+       if (only_prefault && no_prefault)
+               only_prefault = no_prefault = false;
+
+       if (!strncmp(routine, "all", 3)) {
+               for (i = 0; info->routines[i].name; i++)
+                       __bench_mem_routine(info, i, len, totallen);
+               return 0;
+       }
+
+       for (i = 0; info->routines[i].name; i++) {
+               if (!strcmp(info->routines[i].name, routine))
+                       break;
+       }
+       if (!info->routines[i].name) {
+               printf("Unknown routine:%s\n", routine);
+               printf("Available routines...\n");
+               for (i = 0; info->routines[i].name; i++) {
+                       printf("\t%s ... %s\n",
+                              info->routines[i].name, info->routines[i].desc);
+               }
+               return 1;
+       }
+
+       __bench_mem_routine(info, i, len, totallen);
 
        return 0;
 }
index a71dff97c1f54e87aea5034398534bacc77d6a56..f02d028771d970da5d611c31d1b406179b450d45 100644 (file)
@@ -1,12 +1,12 @@
 
-MEMSET_FN(__memset,
+MEMSET_FN(memset_orig,
        "x86-64-unrolled",
        "unrolled memset() in arch/x86/lib/memset_64.S")
 
-MEMSET_FN(memset_c,
+MEMSET_FN(__memset,
        "x86-64-stosq",
        "movsq-based memset() in arch/x86/lib/memset_64.S")
 
-MEMSET_FN(memset_c_e,
+MEMSET_FN(memset_erms,
        "x86-64-stosb",
        "movsb-based memset() in arch/x86/lib/memset_64.S")
index 9e5af89ed13af64bed89e46e7a8df1e1b6a52298..de278784c866a3804040408454f38c4a4f7ca44e 100644 (file)
@@ -1,8 +1,6 @@
 #define memset MEMSET /* don't hide glibc's memset() */
 #define altinstr_replacement text
 #define globl p2align 4; .globl
-#define Lmemset_c globl memset_c; memset_c
-#define Lmemset_c_e globl memset_c_e; memset_c_e
 #include "../../../arch/x86/lib/memset_64.S"
 
 /*
index 747f86103599826b6555563d25c8be25ae8f3d36..71bf7451c0cad1bf1f43b946631bf949eed96c3c 100644 (file)
@@ -208,7 +208,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
                        goto out;
        }
 
-       ret = perf_session__process_events(session, &ann->tool);
+       ret = perf_session__process_events(session);
        if (ret)
                goto out;
 
index 50e6b66aea1ff9c68a1dd02074e98c0b83d481d8..d47a0cdc71c92a10040e34832886ba8157147349 100644 (file)
@@ -125,8 +125,7 @@ static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
        return ret;
 }
 
-static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
-                                    bool force)
+static int build_id_cache__add_kcore(const char *filename, bool force)
 {
        char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1];
        char from_dir[PATH_MAX], to_dir[PATH_MAX];
@@ -143,7 +142,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
                return -1;
 
        scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s",
-                 debugdir, sbuildid);
+                 buildid_dir, sbuildid);
 
        if (!force &&
            !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) {
@@ -155,7 +154,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
                return -1;
 
        scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s",
-                 debugdir, sbuildid, dir);
+                 buildid_dir, sbuildid, dir);
 
        if (mkdir_p(to_dir, 0755))
                return -1;
@@ -183,7 +182,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
        return 0;
 }
 
-static int build_id_cache__add_file(const char *filename, const char *debugdir)
+static int build_id_cache__add_file(const char *filename)
 {
        char sbuild_id[BUILD_ID_SIZE * 2 + 1];
        u8 build_id[BUILD_ID_SIZE];
@@ -195,16 +194,14 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir)
        }
 
        build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
-       err = build_id_cache__add_s(sbuild_id, debugdir, filename,
+       err = build_id_cache__add_s(sbuild_id, filename,
                                    false, false);
-       if (verbose)
-               pr_info("Adding %s %s: %s\n", sbuild_id, filename,
-                       err ? "FAIL" : "Ok");
+       pr_debug("Adding %s %s: %s\n", sbuild_id, filename,
+                err ? "FAIL" : "Ok");
        return err;
 }
 
-static int build_id_cache__remove_file(const char *filename,
-                                      const char *debugdir)
+static int build_id_cache__remove_file(const char *filename)
 {
        u8 build_id[BUILD_ID_SIZE];
        char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -217,10 +214,34 @@ static int build_id_cache__remove_file(const char *filename,
        }
 
        build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
-       err = build_id_cache__remove_s(sbuild_id, debugdir);
-       if (verbose)
-               pr_info("Removing %s %s: %s\n", sbuild_id, filename,
-                       err ? "FAIL" : "Ok");
+       err = build_id_cache__remove_s(sbuild_id);
+       pr_debug("Removing %s %s: %s\n", sbuild_id, filename,
+                err ? "FAIL" : "Ok");
+
+       return err;
+}
+
+static int build_id_cache__purge_path(const char *pathname)
+{
+       struct strlist *list;
+       struct str_node *pos;
+       int err;
+
+       err = build_id_cache__list_build_ids(pathname, &list);
+       if (err)
+               goto out;
+
+       strlist__for_each(pos, list) {
+               err = build_id_cache__remove_s(pos->s);
+               pr_debug("Removing %s %s: %s\n", pos->s, pathname,
+                        err ? "FAIL" : "Ok");
+               if (err)
+                       break;
+       }
+       strlist__delete(list);
+
+out:
+       pr_debug("Purging %s: %s\n", pathname, err ? "FAIL" : "Ok");
 
        return err;
 }
@@ -252,13 +273,12 @@ static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *f
        return 0;
 }
 
-static int build_id_cache__update_file(const char *filename,
-                                      const char *debugdir)
+static int build_id_cache__update_file(const char *filename)
 {
        u8 build_id[BUILD_ID_SIZE];
        char sbuild_id[BUILD_ID_SIZE * 2 + 1];
 
-       int err;
+       int err = 0;
 
        if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
                pr_debug("Couldn't read a build-id in %s\n", filename);
@@ -266,14 +286,14 @@ static int build_id_cache__update_file(const char *filename,
        }
 
        build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
-       err = build_id_cache__remove_s(sbuild_id, debugdir);
-       if (!err) {
-               err = build_id_cache__add_s(sbuild_id, debugdir, filename,
-                                           false, false);
-       }
-       if (verbose)
-               pr_info("Updating %s %s: %s\n", sbuild_id, filename,
-                       err ? "FAIL" : "Ok");
+       if (build_id_cache__cached(sbuild_id))
+               err = build_id_cache__remove_s(sbuild_id);
+
+       if (!err)
+               err = build_id_cache__add_s(sbuild_id, filename, false, false);
+
+       pr_debug("Updating %s %s: %s\n", sbuild_id, filename,
+                err ? "FAIL" : "Ok");
 
        return err;
 }
@@ -287,6 +307,7 @@ int cmd_buildid_cache(int argc, const char **argv,
        bool force = false;
        char const *add_name_list_str = NULL,
                   *remove_name_list_str = NULL,
+                  *purge_name_list_str = NULL,
                   *missing_filename = NULL,
                   *update_name_list_str = NULL,
                   *kcore_filename = NULL;
@@ -304,6 +325,8 @@ int cmd_buildid_cache(int argc, const char **argv,
                   "file", "kcore file to add"),
        OPT_STRING('r', "remove", &remove_name_list_str, "file list",
                    "file(s) to remove"),
+       OPT_STRING('p', "purge", &purge_name_list_str, "path list",
+                   "path(s) to remove (remove old caches too)"),
        OPT_STRING('M', "missing", &missing_filename, "file",
                   "to find missing build ids in the cache"),
        OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
@@ -320,6 +343,11 @@ int cmd_buildid_cache(int argc, const char **argv,
        argc = parse_options(argc, argv, buildid_cache_options,
                             buildid_cache_usage, 0);
 
+       if (argc || (!add_name_list_str && !kcore_filename &&
+                    !remove_name_list_str && !purge_name_list_str &&
+                    !missing_filename && !update_name_list_str))
+               usage_with_options(buildid_cache_usage, buildid_cache_options);
+
        if (missing_filename) {
                file.path = missing_filename;
                file.force = force;
@@ -338,7 +366,7 @@ int cmd_buildid_cache(int argc, const char **argv,
                list = strlist__new(true, add_name_list_str);
                if (list) {
                        strlist__for_each(pos, list)
-                               if (build_id_cache__add_file(pos->s, buildid_dir)) {
+                               if (build_id_cache__add_file(pos->s)) {
                                        if (errno == EEXIST) {
                                                pr_debug("%s already in the cache\n",
                                                         pos->s);
@@ -356,7 +384,25 @@ int cmd_buildid_cache(int argc, const char **argv,
                list = strlist__new(true, remove_name_list_str);
                if (list) {
                        strlist__for_each(pos, list)
-                               if (build_id_cache__remove_file(pos->s, buildid_dir)) {
+                               if (build_id_cache__remove_file(pos->s)) {
+                                       if (errno == ENOENT) {
+                                               pr_debug("%s wasn't in the cache\n",
+                                                        pos->s);
+                                               continue;
+                                       }
+                                       pr_warning("Couldn't remove %s: %s\n",
+                                                  pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
+                               }
+
+                       strlist__delete(list);
+               }
+       }
+
+       if (purge_name_list_str) {
+               list = strlist__new(true, purge_name_list_str);
+               if (list) {
+                       strlist__for_each(pos, list)
+                               if (build_id_cache__purge_path(pos->s)) {
                                        if (errno == ENOENT) {
                                                pr_debug("%s wasn't in the cache\n",
                                                         pos->s);
@@ -377,7 +423,7 @@ int cmd_buildid_cache(int argc, const char **argv,
                list = strlist__new(true, update_name_list_str);
                if (list) {
                        strlist__for_each(pos, list)
-                               if (build_id_cache__update_file(pos->s, buildid_dir)) {
+                               if (build_id_cache__update_file(pos->s)) {
                                        if (errno == ENOENT) {
                                                pr_debug("%s wasn't in the cache\n",
                                                         pos->s);
@@ -391,8 +437,7 @@ int cmd_buildid_cache(int argc, const char **argv,
                }
        }
 
-       if (kcore_filename &&
-           build_id_cache__add_kcore(kcore_filename, buildid_dir, force))
+       if (kcore_filename && build_id_cache__add_kcore(kcore_filename, force))
                pr_warning("Couldn't add %s\n", kcore_filename);
 
 out:
index ed3873b3e23873ded61f12486d50bb118c9471b2..feb420f74c2d9fd34778a20e93764c2e5eaf47c8 100644 (file)
@@ -74,7 +74,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
         * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
         */
        if (with_hits || perf_data_file__is_pipe(&file))
-               perf_session__process_events(session, &build_id__mark_dso_hit_ops);
+               perf_session__process_events(session);
 
        perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
        perf_session__delete(session);
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
new file mode 100644 (file)
index 0000000..d6525bc
--- /dev/null
@@ -0,0 +1,123 @@
+#include <linux/compiler.h>
+#include "builtin.h"
+#include "perf.h"
+#include "debug.h"
+#include "parse-options.h"
+#include "data-convert-bt.h"
+
+typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix);
+
+struct data_cmd {
+       const char      *name;
+       const char      *summary;
+       data_cmd_fn_t   fn;
+};
+
+static struct data_cmd data_cmds[];
+
+#define for_each_cmd(cmd) \
+       for (cmd = data_cmds; cmd && cmd->name; cmd++)
+
+static const struct option data_options[] = {
+       OPT_END()
+};
+
+static const char * const data_subcommands[] = { "convert", NULL };
+
+static const char *data_usage[] = {
+       "perf data [<common options>] <command> [<options>]",
+       NULL
+};
+
+static void print_usage(void)
+{
+       struct data_cmd *cmd;
+
+       printf("Usage:\n");
+       printf("\t%s\n\n", data_usage[0]);
+       printf("\tAvailable commands:\n");
+
+       for_each_cmd(cmd) {
+               printf("\t %s\t- %s\n", cmd->name, cmd->summary);
+       }
+
+       printf("\n");
+}
+
+static const char * const data_convert_usage[] = {
+       "perf data convert [<options>]",
+       NULL
+};
+
+static int cmd_data_convert(int argc, const char **argv,
+                           const char *prefix __maybe_unused)
+{
+       const char *to_ctf     = NULL;
+       bool force = false;
+       const struct option options[] = {
+               OPT_INCR('v', "verbose", &verbose, "be more verbose"),
+               OPT_STRING('i', "input", &input_name, "file", "input file name"),
+#ifdef HAVE_LIBBABELTRACE_SUPPORT
+               OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"),
+#endif
+               OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
+               OPT_END()
+       };
+
+#ifndef HAVE_LIBBABELTRACE_SUPPORT
+       pr_err("No conversion support compiled in.\n");
+       return -1;
+#endif
+
+       argc = parse_options(argc, argv, options,
+                            data_convert_usage, 0);
+       if (argc) {
+               usage_with_options(data_convert_usage, options);
+               return -1;
+       }
+
+       if (to_ctf) {
+#ifdef HAVE_LIBBABELTRACE_SUPPORT
+               return bt_convert__perf2ctf(input_name, to_ctf, force);
+#else
+               pr_err("The libbabeltrace support is not compiled in.\n");
+               return -1;
+#endif
+       }
+
+       return 0;
+}
+
+static struct data_cmd data_cmds[] = {
+       { "convert", "converts data file between formats", cmd_data_convert },
+       { .name = NULL, },
+};
+
+int cmd_data(int argc, const char **argv, const char *prefix)
+{
+       struct data_cmd *cmd;
+       const char *cmdstr;
+
+       /* No command specified. */
+       if (argc < 2)
+               goto usage;
+
+       argc = parse_options_subcommand(argc, argv, data_options, data_subcommands, data_usage,
+                            PARSE_OPT_STOP_AT_NON_OPTION);
+       if (argc < 1)
+               goto usage;
+
+       cmdstr = argv[0];
+
+       for_each_cmd(cmd) {
+               if (strcmp(cmd->name, cmdstr))
+                       continue;
+
+               return cmd->fn(argc, argv, prefix);
+       }
+
+       pr_err("Unknown command: %s\n", cmdstr);
+usage:
+       print_usage();
+       return -1;
+}
index 74aada554b128ff1f8927d6e340bc0686cc5be2c..df6307b4050aaa2ab7e51403d22563e0a1866279 100644 (file)
@@ -747,7 +747,7 @@ static int __cmd_diff(void)
                        goto out_delete;
                }
 
-               ret = perf_session__process_events(d->session, &tool);
+               ret = perf_session__process_events(d->session);
                if (ret) {
                        pr_err("Failed to process %s\n", d->file.path);
                        goto out_delete;
@@ -791,6 +791,8 @@ static const struct option options[] = {
        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
                    "dump raw trace in ASCII"),
        OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
+       OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
+                  "file", "kallsyms pathname"),
        OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
                    "load module symbols - WARNING: use only with -k and LIVE kernel"),
        OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
@@ -802,7 +804,7 @@ static const struct option options[] = {
        OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
                   "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..."
                   " Please refer the man page for the complete list."),
-       OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
+       OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
                   "separator for columns, no spaces will be added between "
                   "columns '.' is reserved."),
        OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
index 0f93f859b782ba1701b1457cb3f90c9d1ecf5995..695ec5a50cf22c56e72961ae98ae9580a98f2512 100644 (file)
@@ -24,6 +24,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
        struct perf_data_file file = {
                .path = file_name,
                .mode = PERF_DATA_MODE_READ,
+               .force = details->force,
        };
 
        session = perf_session__new(&file, 0, NULL);
@@ -47,6 +48,7 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
                    "Show all event attr details"),
        OPT_BOOLEAN('g', "group", &details.event_group,
                    "Show event group information"),
+       OPT_BOOLEAN('f', "force", &details.force, "don't complain, do it"),
        OPT_END()
        };
        const char * const evlist_usage[] = {
index 25d20628212ed4691ad8ca3cc3c432e5dbffcd13..36486eade1ef4f2d30736c99d7471b86d7dd0ada 100644 (file)
@@ -437,7 +437,18 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
                        HELP_FORMAT_INFO),
        OPT_END(),
        };
-       const char * const builtin_help_usage[] = {
+       const char * const builtin_help_subcommands[] = {
+               "buildid-cache", "buildid-list", "diff", "evlist", "help", "list",
+               "record", "report", "bench", "stat", "timechart", "top", "annotate",
+               "script", "sched", "kmem", "lock", "kvm", "test", "inject", "mem", "data",
+#ifdef HAVE_LIBELF_SUPPORT
+               "probe",
+#endif
+#ifdef HAVE_LIBAUDIT_SUPPORT
+               "trace",
+#endif
+       NULL };
+       const char *builtin_help_usage[] = {
                "perf help [--all] [--man|--web|--info] [command]",
                NULL
        };
@@ -448,8 +459,8 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
 
        perf_config(perf_help_config, &help_format);
 
-       argc = parse_options(argc, argv, builtin_help_options,
-                       builtin_help_usage, 0);
+       argc = parse_options_subcommand(argc, argv, builtin_help_options,
+                       builtin_help_subcommands, builtin_help_usage, 0);
 
        if (show_all) {
                printf("\n usage: %s\n\n", perf_usage_string);
index a13641e066f5608363c7eb1575f7e3414ae6863a..40a33d7334cce224fb0ac8317554189f1821dfcf 100644 (file)
@@ -53,6 +53,13 @@ static int perf_event__repipe_synth(struct perf_tool *tool,
        return 0;
 }
 
+static int perf_event__repipe_oe_synth(struct perf_tool *tool,
+                                      union perf_event *event,
+                                      struct ordered_events *oe __maybe_unused)
+{
+       return perf_event__repipe_synth(tool, event);
+}
+
 static int perf_event__repipe_op2_synth(struct perf_tool *tool,
                                        union perf_event *event,
                                        struct perf_session *session
@@ -359,8 +366,6 @@ static int __cmd_inject(struct perf_inject *inject)
        } else if (inject->sched_stat) {
                struct perf_evsel *evsel;
 
-               inject->tool.ordered_events = true;
-
                evlist__for_each(session->evlist, evsel) {
                        const char *name = perf_evsel__name(evsel);
 
@@ -379,7 +384,7 @@ static int __cmd_inject(struct perf_inject *inject)
        if (!file_out->is_pipe)
                lseek(fd, session->header.data_offset, SEEK_SET);
 
-       ret = perf_session__process_events(session, &inject->tool);
+       ret = perf_session__process_events(session);
 
        if (!file_out->is_pipe) {
                if (inject->build_ids)
@@ -408,7 +413,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
                        .unthrottle     = perf_event__repipe,
                        .attr           = perf_event__repipe_attr,
                        .tracing_data   = perf_event__repipe_op2_synth,
-                       .finished_round = perf_event__repipe_op2_synth,
+                       .finished_round = perf_event__repipe_oe_synth,
                        .build_id       = perf_event__repipe_op2_synth,
                        .id_index       = perf_event__repipe_op2_synth,
                },
@@ -438,6 +443,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
                         "be more verbose (show build ids, etc)"),
                OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
                           "kallsyms pathname"),
+               OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
                OPT_END()
        };
        const char * const inject_usage[] = {
@@ -458,6 +464,8 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
                return -1;
        }
 
+       inject.tool.ordered_events = inject.sched_stat;
+
        file.path = inject.input_name;
        inject.session = perf_session__new(&file, true, &inject.tool);
        if (inject.session == NULL)
index f295141025bcfecdb01c913b94cc3b1ed533d2b4..4ebf65c7943443291db80f3f3cd36aa9f17e85e6 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/rbtree.h>
 #include <linux/string.h>
+#include <locale.h>
 
 struct alloc_stat;
 typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
@@ -275,10 +276,10 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
        struct rb_node *next;
        struct machine *machine = &session->machines.host;
 
-       printf("%.102s\n", graph_dotted_line);
+       printf("%.105s\n", graph_dotted_line);
        printf(" %-34s |",  is_caller ? "Callsite": "Alloc Ptr");
        printf(" Total_alloc/Per | Total_req/Per   | Hit      | Ping-pong | Frag\n");
-       printf("%.102s\n", graph_dotted_line);
+       printf("%.105s\n", graph_dotted_line);
 
        next = rb_first(root);
 
@@ -304,7 +305,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
                        snprintf(buf, sizeof(buf), "%#" PRIx64 "", addr);
                printf(" %-34s |", buf);
 
-               printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %8lu | %6.3f%%\n",
+               printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %9lu | %6.3f%%\n",
                       (unsigned long long)data->bytes_alloc,
                       (unsigned long)data->bytes_alloc / data->hit,
                       (unsigned long long)data->bytes_req,
@@ -317,21 +318,21 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
        }
 
        if (n_lines == -1)
-               printf(" ...                                | ...             | ...             | ...    | ...      | ...   \n");
+               printf(" ...                                | ...             | ...             | ...      | ...       | ...   \n");
 
-       printf("%.102s\n", graph_dotted_line);
+       printf("%.105s\n", graph_dotted_line);
 }
 
 static void print_summary(void)
 {
        printf("\nSUMMARY\n=======\n");
-       printf("Total bytes requested: %lu\n", total_requested);
-       printf("Total bytes allocated: %lu\n", total_allocated);
-       printf("Total bytes wasted on internal fragmentation: %lu\n",
+       printf("Total bytes requested: %'lu\n", total_requested);
+       printf("Total bytes allocated: %'lu\n", total_allocated);
+       printf("Total bytes wasted on internal fragmentation: %'lu\n",
               total_allocated - total_requested);
        printf("Internal fragmentation: %f%%\n",
               fragmentation(total_requested, total_allocated));
-       printf("Cross CPU allocations: %lu/%lu\n", nr_cross_allocs, nr_allocs);
+       printf("Cross CPU allocations: %'lu/%'lu\n", nr_cross_allocs, nr_allocs);
 }
 
 static void print_result(struct perf_session *session)
@@ -426,7 +427,7 @@ static int __cmd_kmem(struct perf_session *session)
        }
 
        setup_pager();
-       err = perf_session__process_events(session, &perf_kmem);
+       err = perf_session__process_events(session);
        if (err != 0)
                goto out;
        sort_result();
@@ -559,6 +560,7 @@ static int setup_sorting(struct list_head *sort_list, const char *arg)
 {
        char *tok;
        char *str = strdup(arg);
+       char *pos = str;
 
        if (!str) {
                pr_err("%s: strdup failed\n", __func__);
@@ -566,7 +568,7 @@ static int setup_sorting(struct list_head *sort_list, const char *arg)
        }
 
        while (true) {
-               tok = strsep(&str, ",");
+               tok = strsep(&pos, ",");
                if (!tok)
                        break;
                if (sort_dimension__add(tok, sort_list) < 0) {
@@ -660,8 +662,13 @@ static int __cmd_record(int argc, const char **argv)
 int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        const char * const default_sort_order = "frag,hit,bytes";
+       struct perf_data_file file = {
+               .mode = PERF_DATA_MODE_READ,
+       };
        const struct option kmem_options[] = {
        OPT_STRING('i', "input", &input_name, "file", "input file name"),
+       OPT_INCR('v', "verbose", &verbose,
+                   "be more verbose (show symbol address, etc)"),
        OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
                           "show per-callsite statistics", parse_caller_opt),
        OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
@@ -671,6 +678,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
                     parse_sort_opt),
        OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt),
        OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
+       OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
        OPT_END()
        };
        const char *const kmem_subcommands[] = { "record", "stat", NULL };
@@ -679,10 +687,6 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
                NULL
        };
        struct perf_session *session;
-       struct perf_data_file file = {
-               .path = input_name,
-               .mode = PERF_DATA_MODE_READ,
-       };
        int ret = -1;
 
        argc = parse_options_subcommand(argc, argv, kmem_options,
@@ -696,6 +700,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
                return __cmd_record(argc, argv);
        }
 
+       file.path = input_name;
+
        session = perf_session__new(&file, false, &perf_kmem);
        if (session == NULL)
                return -1;
@@ -703,6 +709,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
        symbol__init(&session->header.env);
 
        if (!strcmp(argv[0], "stat")) {
+               setlocale(LC_ALL, "");
+
                if (cpu__setup_cpunode_map())
                        goto out_delete;
 
index 0894a817f67e6f5bb8a5d6398c9e2307f010efc6..1f9338f6109cdbe79f8f08e510c00e4a171d1f82 100644 (file)
@@ -18,6 +18,7 @@
 #include "util/stat.h"
 #include "util/top.h"
 #include "util/data.h"
+#include "util/ordered-events.h"
 
 #include <sys/prctl.h>
 #ifdef HAVE_TIMERFD_SUPPORT
@@ -730,9 +731,9 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
                        return -1;
                }
 
-               err = perf_session_queue_event(kvm->session, event, &kvm->tool, &sample, 0);
+               err = perf_session__queue_event(kvm->session, event, &sample, 0);
                /*
-                * FIXME: Here we can't consume the event, as perf_session_queue_event will
+                * FIXME: Here we can't consume the event, as perf_session__queue_event will
                 *        point to it, and it'll get possibly overwritten by the kernel.
                 */
                perf_evlist__mmap_consume(kvm->evlist, idx);
@@ -783,8 +784,10 @@ static int perf_kvm__mmap_read(struct perf_kvm_stat *kvm)
 
        /* flush queue after each round in which we processed events */
        if (ntotal) {
-               kvm->session->ordered_events.next_flush = flush_time;
-               err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session);
+               struct ordered_events *oe = &kvm->session->ordered_events;
+
+               oe->next_flush = flush_time;
+               err = ordered_events__flush(oe, OE_FLUSH__ROUND);
                if (err) {
                        if (kvm->lost_events)
                                pr_info("\nLost events: %" PRIu64 "\n\n",
@@ -1044,6 +1047,7 @@ static int read_events(struct perf_kvm_stat *kvm)
        struct perf_data_file file = {
                .path = kvm->file_name,
                .mode = PERF_DATA_MODE_READ,
+               .force = kvm->force,
        };
 
        kvm->tool = eops;
@@ -1066,7 +1070,7 @@ static int read_events(struct perf_kvm_stat *kvm)
        if (ret < 0)
                return ret;
 
-       return perf_session__process_events(kvm->session, &kvm->tool);
+       return perf_session__process_events(kvm->session);
 }
 
 static int parse_target_str(struct perf_kvm_stat *kvm)
@@ -1201,6 +1205,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
                            " time (sort by avg time)"),
                OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
                           "analyze events only for given process id(s)"),
+               OPT_BOOLEAN('f', "force", &kvm->force, "don't complain, do it"),
                OPT_END()
        };
 
index 198f3c3aff952358766626f5bfea9ce81a996b28..af5bd05141088469d29d2fc7112927be96f2f610 100644 (file)
@@ -36,38 +36,36 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 
        setup_pager();
 
-       if (raw_dump) {
-               print_events(NULL, true);
-               return 0;
-       }
+       if (!raw_dump)
+               printf("\nList of pre-defined events (to be used in -e):\n\n");
 
        if (argc == 0) {
-               print_events(NULL, false);
+               print_events(NULL, raw_dump);
                return 0;
        }
 
        for (i = 0; i < argc; ++i) {
-               if (i)
-                       putchar('\n');
-               if (strncmp(argv[i], "tracepoint", 10) == 0)
-                       print_tracepoint_events(NULL, NULL, false);
+               if (strcmp(argv[i], "tracepoint") == 0)
+                       print_tracepoint_events(NULL, NULL, raw_dump);
                else if (strcmp(argv[i], "hw") == 0 ||
                         strcmp(argv[i], "hardware") == 0)
-                       print_events_type(PERF_TYPE_HARDWARE);
+                       print_symbol_events(NULL, PERF_TYPE_HARDWARE,
+                                       event_symbols_hw, PERF_COUNT_HW_MAX, raw_dump);
                else if (strcmp(argv[i], "sw") == 0 ||
                         strcmp(argv[i], "software") == 0)
-                       print_events_type(PERF_TYPE_SOFTWARE);
+                       print_symbol_events(NULL, PERF_TYPE_SOFTWARE,
+                                       event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump);
                else if (strcmp(argv[i], "cache") == 0 ||
                         strcmp(argv[i], "hwcache") == 0)
-                       print_hwcache_events(NULL, false);
+                       print_hwcache_events(NULL, raw_dump);
                else if (strcmp(argv[i], "pmu") == 0)
-                       print_pmu_events(NULL, false);
+                       print_pmu_events(NULL, raw_dump);
                else {
                        char *sep = strchr(argv[i], ':'), *s;
                        int sep_idx;
 
                        if (sep == NULL) {
-                               print_events(argv[i], false);
+                               print_events(argv[i], raw_dump);
                                continue;
                        }
                        sep_idx = sep - argv[i];
@@ -76,7 +74,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
                                return -1;
 
                        s[sep_idx] = '\0';
-                       print_tracepoint_events(s, s + sep_idx + 1, false);
+                       print_tracepoint_events(s, s + sep_idx + 1, raw_dump);
                        free(s);
                }
        }
index e7ec71589da6dbcc06f5a8367466f953cac99c4c..d49c2ab85fc2dd1e3c6560391b71f7e3269cf31e 100644 (file)
@@ -846,6 +846,8 @@ static const struct perf_evsel_str_handler lock_tracepoints[] = {
        { "lock:lock_release",   perf_evsel__process_lock_release,   }, /* CONFIG_LOCKDEP */
 };
 
+static bool force;
+
 static int __cmd_report(bool display_info)
 {
        int err = -EINVAL;
@@ -857,6 +859,7 @@ static int __cmd_report(bool display_info)
        struct perf_data_file file = {
                .path = input_name,
                .mode = PERF_DATA_MODE_READ,
+               .force = force,
        };
 
        session = perf_session__new(&file, false, &eops);
@@ -878,7 +881,7 @@ static int __cmd_report(bool display_info)
        if (select_key())
                goto out_delete;
 
-       err = perf_session__process_events(session, &eops);
+       err = perf_session__process_events(session);
        if (err)
                goto out_delete;
 
@@ -945,6 +948,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
                    "dump thread list in perf.data"),
        OPT_BOOLEAN('m', "map", &info_map,
                    "map of lock instances (address:name table)"),
+       OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
        OPT_END()
        };
        const struct option lock_options[] = {
@@ -956,6 +960,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
        const struct option report_options[] = {
        OPT_STRING('k', "key", &sort_key, "acquired",
                    "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
+       OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
        /* TODO: type */
        OPT_END()
        };
index 9b5663950a4dd1b11573f9c10da92ac229bbb2f4..675216e08bfcd04baf2336ece7da328e914e21fd 100644 (file)
@@ -15,6 +15,7 @@ struct perf_mem {
        char const              *input_name;
        bool                    hide_unresolved;
        bool                    dump_raw;
+       bool                    force;
        int                     operation;
        const char              *cpu_list;
        DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -120,6 +121,7 @@ static int report_raw_events(struct perf_mem *mem)
        struct perf_data_file file = {
                .path = input_name,
                .mode = PERF_DATA_MODE_READ,
+               .force = mem->force,
        };
        int err = -EINVAL;
        int ret;
@@ -141,7 +143,7 @@ static int report_raw_events(struct perf_mem *mem)
 
        printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
 
-       err = perf_session__process_events(session, &mem->tool);
+       err = perf_session__process_events(session);
        if (err)
                return err;
 
@@ -286,10 +288,11 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
                   "input file name"),
        OPT_STRING('C', "cpu", &mem.cpu_list, "cpu",
                   "list of cpus to profile"),
-       OPT_STRING('x', "field-separator", &symbol_conf.field_sep,
+       OPT_STRING_NOEMPTY('x', "field-separator", &symbol_conf.field_sep,
                   "separator",
                   "separator for columns, no spaces will be added"
                   " between columns '.' is reserved."),
+       OPT_BOOLEAN('f', "force", &mem.force, "don't complain, do it"),
        OPT_END()
        };
        const char *const mem_subcommands[] = { "record", "report", NULL };
index 921bb69425035f08f8cb85bd8933ba26cc9687cf..f7b1af67e9f686d86f8bd1539b96a935b04a4559 100644 (file)
@@ -56,6 +56,7 @@ static struct {
        bool mod_events;
        bool uprobes;
        bool quiet;
+       bool target_used;
        int nevents;
        struct perf_probe_event events[MAX_PROBES];
        struct strlist *dellist;
@@ -78,6 +79,12 @@ static int parse_probe_event(const char *str)
        }
 
        pev->uprobes = params.uprobes;
+       if (params.target) {
+               pev->target = strdup(params.target);
+               if (!pev->target)
+                       return -ENOMEM;
+               params.target_used = true;
+       }
 
        /* Parse a perf-probe command into event */
        ret = parse_perf_probe_command(str, pev);
@@ -102,6 +109,7 @@ static int set_target(const char *ptr)
                params.target = strdup(ptr);
                if (!params.target)
                        return -ENOMEM;
+               params.target_used = false;
 
                found = 1;
                buf = ptr + (strlen(ptr) - 3);
@@ -178,7 +186,7 @@ static int opt_set_target(const struct option *opt, const char *str,
        int ret = -ENOENT;
        char *tmp;
 
-       if  (str && !params.target) {
+       if  (str) {
                if (!strcmp(opt->long_name, "exec"))
                        params.uprobes = true;
 #ifdef HAVE_DWARF_SUPPORT
@@ -200,7 +208,9 @@ static int opt_set_target(const struct option *opt, const char *str,
                        if (!tmp)
                                return -ENOMEM;
                }
+               free(params.target);
                params.target = tmp;
+               params.target_used = false;
                ret = 0;
        }
 
@@ -485,9 +495,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
        }
 
        if (params.nevents) {
+               /* Ensure the last given target is used */
+               if (params.target && !params.target_used) {
+                       pr_warning("  Error: -x/-m must follow the probe definitions.\n");
+                       usage_with_options(probe_usage, options);
+               }
+
                ret = add_perf_probe_events(params.events, params.nevents,
                                            params.max_probe_points,
-                                           params.target,
                                            params.force_add);
                if (ret < 0) {
                        pr_err_with_code("  Error: Failed to add events.", ret);
index 404ab34340523f934abc76fcfc6053907708e4fc..c3efdfb630b5b664349ed9e40c41374d3863752d 100644 (file)
@@ -70,8 +70,8 @@ static int process_synthesized_event(struct perf_tool *tool,
 static int record__mmap_read(struct record *rec, int idx)
 {
        struct perf_mmap *md = &rec->evlist->mmap[idx];
-       unsigned int head = perf_mmap__read_head(md);
-       unsigned int old = md->prev;
+       u64 head = perf_mmap__read_head(md);
+       u64 old = md->prev;
        unsigned char *data = md->base + page_size;
        unsigned long size;
        void *buf;
@@ -161,8 +161,9 @@ try_again:
                }
        }
 
-       if (perf_evlist__apply_filters(evlist)) {
-               error("failed to set filter with %d (%s)\n", errno,
+       if (perf_evlist__apply_filters(evlist, &pos)) {
+               error("failed to set filter \"%s\" on event %s with %d (%s)\n",
+                       pos->filter, perf_evsel__name(pos), errno,
                        strerror_r(errno, msg, sizeof(msg)));
                rc = -1;
                goto out;
@@ -225,7 +226,7 @@ static int process_buildids(struct record *rec)
         */
        symbol_conf.ignore_vmlinux_buildid = true;
 
-       return perf_session__process_events(session, &rec->tool);
+       return perf_session__process_events(session);
 }
 
 static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
@@ -343,7 +344,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
        signal(SIGINT, sig_handler);
        signal(SIGTERM, sig_handler);
 
-       session = perf_session__new(file, false, NULL);
+       session = perf_session__new(file, false, tool);
        if (session == NULL) {
                pr_err("Perf session creation failed.\n");
                return -1;
@@ -658,7 +659,7 @@ error:
 
 static void callchain_debug(void)
 {
-       static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" };
+       static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
 
        pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);
 
@@ -710,6 +711,90 @@ static int perf_record_config(const char *var, const char *value, void *cb)
        return perf_default_config(var, value, cb);
 }
 
+struct clockid_map {
+       const char *name;
+       int clockid;
+};
+
+#define CLOCKID_MAP(n, c)      \
+       { .name = n, .clockid = (c), }
+
+#define CLOCKID_END    { .name = NULL, }
+
+
+/*
+ * Add the missing ones, we need to build on many distros...
+ */
+#ifndef CLOCK_MONOTONIC_RAW
+#define CLOCK_MONOTONIC_RAW 4
+#endif
+#ifndef CLOCK_BOOTTIME
+#define CLOCK_BOOTTIME 7
+#endif
+#ifndef CLOCK_TAI
+#define CLOCK_TAI 11
+#endif
+
+static const struct clockid_map clockids[] = {
+       /* available for all events, NMI safe */
+       CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
+       CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
+
+       /* available for some events */
+       CLOCKID_MAP("realtime", CLOCK_REALTIME),
+       CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
+       CLOCKID_MAP("tai", CLOCK_TAI),
+
+       /* available for the lazy */
+       CLOCKID_MAP("mono", CLOCK_MONOTONIC),
+       CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
+       CLOCKID_MAP("real", CLOCK_REALTIME),
+       CLOCKID_MAP("boot", CLOCK_BOOTTIME),
+
+       CLOCKID_END,
+};
+
+static int parse_clockid(const struct option *opt, const char *str, int unset)
+{
+       struct record_opts *opts = (struct record_opts *)opt->value;
+       const struct clockid_map *cm;
+       const char *ostr = str;
+
+       if (unset) {
+               opts->use_clockid = 0;
+               return 0;
+       }
+
+       /* no arg passed */
+       if (!str)
+               return 0;
+
+       /* no setting it twice */
+       if (opts->use_clockid)
+               return -1;
+
+       opts->use_clockid = true;
+
+       /* if its a number, we're done */
+       if (sscanf(str, "%d", &opts->clockid) == 1)
+               return 0;
+
+       /* allow a "CLOCK_" prefix to the name */
+       if (!strncasecmp(str, "CLOCK_", 6))
+               str += 6;
+
+       for (cm = clockids; cm->name; cm++) {
+               if (!strcasecmp(str, cm->name)) {
+                       opts->clockid = cm->clockid;
+                       return 0;
+               }
+       }
+
+       opts->use_clockid = false;
+       ui__warning("unknown clockid %s, check man page\n", ostr);
+       return -1;
+}
+
 static const char * const __record_usage[] = {
        "perf record [<options>] [<command>]",
        "perf record [<options>] -- <command> [<options>]",
@@ -751,9 +836,9 @@ static struct record record = {
 #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
 
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
-const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf";
+const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr";
 #else
-const char record_callchain_help[] = CALLCHAIN_HELP "fp";
+const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr";
 #endif
 
 /*
@@ -839,6 +924,11 @@ struct option __record_options[] = {
                    "use per-thread mmaps"),
        OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
                    "Sample machine registers on interrupt"),
+       OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
+                   "Record running/enabled time of read (:S) events"),
+       OPT_CALLBACK('k', "clockid", &record.opts,
+       "clockid", "clockid to use for events, see clock_gettime()",
+       parse_clockid),
        OPT_END()
 };
 
index 2f91094e228b6010527c84b66e1172dd616819be..476cdf7afcca3fc7b1135d9973d15886cd7b8988 100644 (file)
@@ -249,6 +249,8 @@ static int report__setup_sample_type(struct report *rep)
                if ((sample_type & PERF_SAMPLE_REGS_USER) &&
                    (sample_type & PERF_SAMPLE_STACK_USER))
                        callchain_param.record_mode = CALLCHAIN_DWARF;
+               else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
+                       callchain_param.record_mode = CALLCHAIN_LBR;
                else
                        callchain_param.record_mode = CALLCHAIN_FP;
        }
@@ -302,7 +304,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
 
        if (rep->mem_mode) {
                ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
-               ret += fprintf(fp, "\n# Sort order   : %s", sort_order);
+               ret += fprintf(fp, "\n# Sort order   : %s", sort_order ? : default_mem_sort_order);
        } else
                ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
        return ret + fprintf(fp, "\n#\n");
@@ -345,7 +347,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
 static void report__warn_kptr_restrict(const struct report *rep)
 {
        struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION];
-       struct kmap *kernel_kmap = map__kmap(kernel_map);
+       struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
 
        if (kernel_map == NULL ||
            (kernel_map->dso->hit &&
@@ -480,7 +482,7 @@ static int __cmd_report(struct report *rep)
        if (ret)
                return ret;
 
-       ret = perf_session__process_events(session, &rep->tool);
+       ret = perf_session__process_events(session);
        if (ret)
                return ret;
 
@@ -667,6 +669,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                   "only consider symbols in these dsos"),
        OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
                   "only consider symbols in these comms"),
+       OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
+                  "only consider symbols in these pids"),
+       OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
+                  "only consider symbols in these tids"),
        OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
                   "only consider these symbols"),
        OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter",
@@ -674,7 +680,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
                   "width[,width...]",
                   "don't try to adjust column width, use these fixed values"),
-       OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
+       OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
                   "separator for columns, no spaces will be added between "
                   "columns '.' is reserved."),
        OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,
@@ -766,7 +772,7 @@ repeat:
         * 0/1 means the user chose a mode.
         */
        if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) &&
-           branch_call_mode == -1) {
+           !branch_call_mode) {
                sort__mode = SORT_MODE__BRANCH;
                symbol_conf.cumulate_callchain = false;
        }
index 891c3930080e3b406282d1c8059635a5e1828e40..5275bab703138cbeb9c40f1ff22174ac52ca2d13 100644 (file)
 #include <semaphore.h>
 #include <pthread.h>
 #include <math.h>
+#include <api/fs/fs.h>
 
 #define PR_SET_NAME            15               /* Set process name */
 #define MAX_CPUS               4096
 #define COMM_LEN               20
 #define SYM_LEN                        129
-#define MAX_PID                        65536
+#define MAX_PID                        1024000
 
 struct sched_atom;
 
@@ -124,7 +125,7 @@ struct perf_sched {
        struct perf_tool tool;
        const char       *sort_order;
        unsigned long    nr_tasks;
-       struct task_desc *pid_to_task[MAX_PID];
+       struct task_desc **pid_to_task;
        struct task_desc **tasks;
        const struct trace_sched_handler *tp_handler;
        pthread_mutex_t  start_work_mutex;
@@ -169,6 +170,7 @@ struct perf_sched {
        u64              cpu_last_switched[MAX_CPUS];
        struct rb_root   atom_root, sorted_atom_root;
        struct list_head sort_list, cmp_pid;
+       bool force;
 };
 
 static u64 get_nsecs(void)
@@ -326,8 +328,19 @@ static struct task_desc *register_pid(struct perf_sched *sched,
                                      unsigned long pid, const char *comm)
 {
        struct task_desc *task;
+       static int pid_max;
 
-       BUG_ON(pid >= MAX_PID);
+       if (sched->pid_to_task == NULL) {
+               if (sysctl__read_int("kernel/pid_max", &pid_max) < 0)
+                       pid_max = MAX_PID;
+               BUG_ON((sched->pid_to_task = calloc(pid_max, sizeof(struct task_desc *))) == NULL);
+       }
+       if (pid >= (unsigned long)pid_max) {
+               BUG_ON((sched->pid_to_task = realloc(sched->pid_to_task, (pid + 1) *
+                       sizeof(struct task_desc *))) == NULL);
+               while (pid >= (unsigned long)pid_max)
+                       sched->pid_to_task[pid_max++] = NULL;
+       }
 
        task = sched->pid_to_task[pid];
 
@@ -346,7 +359,7 @@ static struct task_desc *register_pid(struct perf_sched *sched,
 
        sched->pid_to_task[pid] = task;
        sched->nr_tasks++;
-       sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_task *));
+       sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_desc *));
        BUG_ON(!sched->tasks);
        sched->tasks[task->nr] = task;
 
@@ -425,24 +438,45 @@ static u64 get_cpu_usage_nsec_parent(void)
        return sum;
 }
 
-static int self_open_counters(void)
+static int self_open_counters(struct perf_sched *sched, unsigned long cur_task)
 {
        struct perf_event_attr attr;
-       char sbuf[STRERR_BUFSIZE];
+       char sbuf[STRERR_BUFSIZE], info[STRERR_BUFSIZE];
        int fd;
+       struct rlimit limit;
+       bool need_privilege = false;
 
        memset(&attr, 0, sizeof(attr));
 
        attr.type = PERF_TYPE_SOFTWARE;
        attr.config = PERF_COUNT_SW_TASK_CLOCK;
 
+force_again:
        fd = sys_perf_event_open(&attr, 0, -1, -1,
                                 perf_event_open_cloexec_flag());
 
-       if (fd < 0)
+       if (fd < 0) {
+               if (errno == EMFILE) {
+                       if (sched->force) {
+                               BUG_ON(getrlimit(RLIMIT_NOFILE, &limit) == -1);
+                               limit.rlim_cur += sched->nr_tasks - cur_task;
+                               if (limit.rlim_cur > limit.rlim_max) {
+                                       limit.rlim_max = limit.rlim_cur;
+                                       need_privilege = true;
+                               }
+                               if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
+                                       if (need_privilege && errno == EPERM)
+                                               strcpy(info, "Need privilege\n");
+                               } else
+                                       goto force_again;
+                       } else
+                               strcpy(info, "Have a try with -f option\n");
+               }
                pr_err("Error: sys_perf_event_open() syscall returned "
-                      "with %d (%s)\n", fd,
-                      strerror_r(errno, sbuf, sizeof(sbuf)));
+                      "with %d (%s)\n%s", fd,
+                      strerror_r(errno, sbuf, sizeof(sbuf)), info);
+               exit(EXIT_FAILURE);
+       }
        return fd;
 }
 
@@ -460,6 +494,7 @@ static u64 get_cpu_usage_nsec_self(int fd)
 struct sched_thread_parms {
        struct task_desc  *task;
        struct perf_sched *sched;
+       int fd;
 };
 
 static void *thread_func(void *ctx)
@@ -470,13 +505,12 @@ static void *thread_func(void *ctx)
        u64 cpu_usage_0, cpu_usage_1;
        unsigned long i, ret;
        char comm2[22];
-       int fd;
+       int fd = parms->fd;
 
        zfree(&parms);
 
        sprintf(comm2, ":%s", this_task->comm);
        prctl(PR_SET_NAME, comm2);
-       fd = self_open_counters();
        if (fd < 0)
                return NULL;
 again:
@@ -528,6 +562,7 @@ static void create_tasks(struct perf_sched *sched)
                BUG_ON(parms == NULL);
                parms->task = task = sched->tasks[i];
                parms->sched = sched;
+               parms->fd = self_open_counters(sched, i);
                sem_init(&task->sleep_sem, 0, 0);
                sem_init(&task->ready_for_work, 0, 0);
                sem_init(&task->work_done_sem, 0, 0);
@@ -572,13 +607,13 @@ static void wait_for_tasks(struct perf_sched *sched)
        cpu_usage_1 = get_cpu_usage_nsec_parent();
        if (!sched->runavg_cpu_usage)
                sched->runavg_cpu_usage = sched->cpu_usage;
-       sched->runavg_cpu_usage = (sched->runavg_cpu_usage * 9 + sched->cpu_usage) / 10;
+       sched->runavg_cpu_usage = (sched->runavg_cpu_usage * (sched->replay_repeat - 1) + sched->cpu_usage) / sched->replay_repeat;
 
        sched->parent_cpu_usage = cpu_usage_1 - cpu_usage_0;
        if (!sched->runavg_parent_cpu_usage)
                sched->runavg_parent_cpu_usage = sched->parent_cpu_usage;
-       sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * 9 +
-                                        sched->parent_cpu_usage)/10;
+       sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * (sched->replay_repeat - 1) +
+                                        sched->parent_cpu_usage)/sched->replay_repeat;
 
        ret = pthread_mutex_lock(&sched->start_work_mutex);
        BUG_ON(ret);
@@ -610,7 +645,7 @@ static void run_one_test(struct perf_sched *sched)
        sched->sum_fluct += fluct;
        if (!sched->run_avg)
                sched->run_avg = delta;
-       sched->run_avg = (sched->run_avg * 9 + delta) / 10;
+       sched->run_avg = (sched->run_avg * (sched->replay_repeat - 1) + delta) / sched->replay_repeat;
 
        printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / 1000000.0);
 
@@ -831,7 +866,7 @@ static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread)
                return -1;
        }
 
-       atoms->thread = thread;
+       atoms->thread = thread__get(thread);
        INIT_LIST_HEAD(&atoms->work_list);
        __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid);
        return 0;
@@ -1439,8 +1474,7 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
        return err;
 }
 
-static int perf_sched__read_events(struct perf_sched *sched,
-                                  struct perf_session **psession)
+static int perf_sched__read_events(struct perf_sched *sched)
 {
        const struct perf_evsel_str_handler handlers[] = {
                { "sched:sched_switch",       process_sched_switch_event, },
@@ -1453,7 +1487,9 @@ static int perf_sched__read_events(struct perf_sched *sched,
        struct perf_data_file file = {
                .path = input_name,
                .mode = PERF_DATA_MODE_READ,
+               .force = sched->force,
        };
+       int rc = -1;
 
        session = perf_session__new(&file, false, &sched->tool);
        if (session == NULL) {
@@ -1467,27 +1503,21 @@ static int perf_sched__read_events(struct perf_sched *sched,
                goto out_delete;
 
        if (perf_session__has_traces(session, "record -R")) {
-               int err = perf_session__process_events(session, &sched->tool);
+               int err = perf_session__process_events(session);
                if (err) {
                        pr_err("Failed to process events, error %d", err);
                        goto out_delete;
                }
 
-               sched->nr_events      = session->stats.nr_events[0];
-               sched->nr_lost_events = session->stats.total_lost;
-               sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST];
+               sched->nr_events      = session->evlist->stats.nr_events[0];
+               sched->nr_lost_events = session->evlist->stats.total_lost;
+               sched->nr_lost_chunks = session->evlist->stats.nr_events[PERF_RECORD_LOST];
        }
 
-       if (psession)
-               *psession = session;
-       else
-               perf_session__delete(session);
-
-       return 0;
-
+       rc = 0;
 out_delete:
        perf_session__delete(session);
-       return -1;
+       return rc;
 }
 
 static void print_bad_events(struct perf_sched *sched)
@@ -1515,12 +1545,10 @@ static void print_bad_events(struct perf_sched *sched)
 static int perf_sched__lat(struct perf_sched *sched)
 {
        struct rb_node *next;
-       struct perf_session *session;
 
        setup_pager();
 
-       /* save session -- references to threads are held in work_list */
-       if (perf_sched__read_events(sched, &session))
+       if (perf_sched__read_events(sched))
                return -1;
 
        perf_sched__sort_lat(sched);
@@ -1537,6 +1565,7 @@ static int perf_sched__lat(struct perf_sched *sched)
                work_list = rb_entry(next, struct work_atoms, node);
                output_lat_thread(sched, work_list);
                next = rb_next(next);
+               thread__zput(work_list->thread);
        }
 
        printf(" -----------------------------------------------------------------------------------------------------------------\n");
@@ -1548,7 +1577,6 @@ static int perf_sched__lat(struct perf_sched *sched)
        print_bad_events(sched);
        printf("\n");
 
-       perf_session__delete(session);
        return 0;
 }
 
@@ -1557,7 +1585,7 @@ static int perf_sched__map(struct perf_sched *sched)
        sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF);
 
        setup_pager();
-       if (perf_sched__read_events(sched, NULL))
+       if (perf_sched__read_events(sched))
                return -1;
        print_bad_events(sched);
        return 0;
@@ -1572,7 +1600,7 @@ static int perf_sched__replay(struct perf_sched *sched)
 
        test_calibrations(sched);
 
-       if (perf_sched__read_events(sched, NULL))
+       if (perf_sched__read_events(sched))
                return -1;
 
        printf("nr_run_events:        %ld\n", sched->nr_run_events);
@@ -1693,6 +1721,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
                    "be more verbose (show symbol address, etc)"),
        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
                    "dump raw trace in ASCII"),
+       OPT_BOOLEAN('f', "force", &sched.force, "don't complain, do it"),
        OPT_END()
        };
        const struct option sched_options[] = {
index ce304dfd962a13db6d2f471a1a6baa304a7bd130..58f10b8e6ff20d51429634b8f79628188fbc2dd4 100644 (file)
@@ -446,9 +446,9 @@ static void print_sample_bts(union perf_event *event,
 }
 
 static void process_event(union perf_event *event, struct perf_sample *sample,
-                         struct perf_evsel *evsel, struct thread *thread,
-                         struct addr_location *al)
+                         struct perf_evsel *evsel, struct addr_location *al)
 {
+       struct thread *thread = al->thread;
        struct perf_event_attr *attr = &evsel->attr;
 
        if (output[attr->type].fields == 0)
@@ -549,14 +549,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
                                struct machine *machine)
 {
        struct addr_location al;
-       struct thread *thread = machine__findnew_thread(machine, sample->pid,
-                                                       sample->tid);
-
-       if (thread == NULL) {
-               pr_debug("problem processing %d event, skipping it.\n",
-                        event->header.type);
-               return -1;
-       }
 
        if (debug_mode) {
                if (sample->time < last_timestamp) {
@@ -581,7 +573,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
        if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
                return 0;
 
-       scripting_ops->process_event(event, sample, evsel, thread, &al);
+       scripting_ops->process_event(event, sample, evsel, &al);
 
        return 0;
 }
@@ -800,7 +792,7 @@ static int __cmd_script(struct perf_script *script)
                script->tool.mmap2 = process_mmap2_event;
        }
 
-       ret = perf_session__process_events(script->session, &script->tool);
+       ret = perf_session__process_events(script->session);
 
        if (debug_mode)
                pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -1523,6 +1515,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                        .ordering_requires_timestamps = true,
                },
        };
+       struct perf_data_file file = {
+               .mode = PERF_DATA_MODE_READ,
+       };
        const struct option options[] = {
        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
                    "dump raw trace in ASCII"),
@@ -1550,7 +1545,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                    "When printing symbols do not display call chain"),
        OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
                    "Look for files with symbols relative to this directory"),
-       OPT_CALLBACK('f', "fields", NULL, "str",
+       OPT_CALLBACK('F', "fields", NULL, "str",
                     "comma separated output fields prepend with 'type:'. "
                     "Valid types: hw,sw,trace,raw. "
                     "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
@@ -1562,6 +1557,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
        OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
                   "only display events for these comms"),
+       OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
+                  "only consider symbols in these pids"),
+       OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
+                  "only consider symbols in these tids"),
        OPT_BOOLEAN('I', "show-info", &show_full_info,
                    "display extended information from perf.data file"),
        OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
@@ -1570,9 +1569,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                    "Show the fork/comm/exit events"),
        OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events,
                    "Show the mmap events"),
+       OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
        OPT_END()
        };
-       const char * const script_usage[] = {
+       const char * const script_subcommands[] = { "record", "report", NULL };
+       const char *script_usage[] = {
                "perf script [<options>]",
                "perf script [<options>] record <script> [<record-options>] <command>",
                "perf script [<options>] report <script> [script-args]",
@@ -1580,13 +1581,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                "perf script [<options>] <top-script> [script-args]",
                NULL
        };
-       struct perf_data_file file = {
-               .mode = PERF_DATA_MODE_READ,
-       };
 
        setup_scripting();
 
-       argc = parse_options(argc, argv, options, script_usage,
+       argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
                             PARSE_OPT_STOP_AT_NON_OPTION);
 
        file.path = input_name;
index e598e4e98170fd30a708eed4c8a4629df2b43758..f7b8218785f6fa8911bc9c8544d7eb14ff9e2f2f 100644 (file)
@@ -353,39 +353,40 @@ static struct perf_evsel *nth_evsel(int n)
  * more semantic information such as miss/hit ratios,
  * instruction rates, etc:
  */
-static void update_shadow_stats(struct perf_evsel *counter, u64 *count)
+static void update_shadow_stats(struct perf_evsel *counter, u64 *count,
+                               int cpu)
 {
        if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
-               update_stats(&runtime_nsecs_stats[0], count[0]);
+               update_stats(&runtime_nsecs_stats[cpu], count[0]);
        else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
-               update_stats(&runtime_cycles_stats[0], count[0]);
+               update_stats(&runtime_cycles_stats[cpu], count[0]);
        else if (transaction_run &&
                 perf_evsel__cmp(counter, nth_evsel(T_CYCLES_IN_TX)))
-               update_stats(&runtime_cycles_in_tx_stats[0], count[0]);
+               update_stats(&runtime_cycles_in_tx_stats[cpu], count[0]);
        else if (transaction_run &&
                 perf_evsel__cmp(counter, nth_evsel(T_TRANSACTION_START)))
-               update_stats(&runtime_transaction_stats[0], count[0]);
+               update_stats(&runtime_transaction_stats[cpu], count[0]);
        else if (transaction_run &&
                 perf_evsel__cmp(counter, nth_evsel(T_ELISION_START)))
-               update_stats(&runtime_elision_stats[0], count[0]);
+               update_stats(&runtime_elision_stats[cpu], count[0]);
        else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
-               update_stats(&runtime_stalled_cycles_front_stats[0], count[0]);
+               update_stats(&runtime_stalled_cycles_front_stats[cpu], count[0]);
        else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
-               update_stats(&runtime_stalled_cycles_back_stats[0], count[0]);
+               update_stats(&runtime_stalled_cycles_back_stats[cpu], count[0]);
        else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
-               update_stats(&runtime_branches_stats[0], count[0]);
+               update_stats(&runtime_branches_stats[cpu], count[0]);
        else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES))
-               update_stats(&runtime_cacherefs_stats[0], count[0]);
+               update_stats(&runtime_cacherefs_stats[cpu], count[0]);
        else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D))
-               update_stats(&runtime_l1_dcache_stats[0], count[0]);
+               update_stats(&runtime_l1_dcache_stats[cpu], count[0]);
        else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I))
-               update_stats(&runtime_l1_icache_stats[0], count[0]);
+               update_stats(&runtime_l1_icache_stats[cpu], count[0]);
        else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL))
-               update_stats(&runtime_ll_cache_stats[0], count[0]);
+               update_stats(&runtime_ll_cache_stats[cpu], count[0]);
        else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB))
-               update_stats(&runtime_dtlb_cache_stats[0], count[0]);
+               update_stats(&runtime_dtlb_cache_stats[cpu], count[0]);
        else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
-               update_stats(&runtime_itlb_cache_stats[0], count[0]);
+               update_stats(&runtime_itlb_cache_stats[cpu], count[0]);
 }
 
 static void zero_per_pkg(struct perf_evsel *counter)
@@ -447,7 +448,8 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,
                        perf_evsel__compute_deltas(evsel, cpu, count);
                perf_counts_values__scale(count, scale, NULL);
                evsel->counts->cpu[cpu] = *count;
-               update_shadow_stats(evsel, count->values);
+               if (aggr_mode == AGGR_NONE)
+                       update_shadow_stats(evsel, count->values, cpu);
                break;
        case AGGR_GLOBAL:
                aggr->val += count->val;
@@ -495,7 +497,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
        /*
         * Save the full runtime - to allow normalization during printout:
         */
-       update_shadow_stats(counter, count);
+       update_shadow_stats(counter, count, 0);
 
        return 0;
 }
@@ -510,6 +512,9 @@ static int read_counter(struct perf_evsel *counter)
        int ncpus = perf_evsel__nr_cpus(counter);
        int cpu, thread;
 
+       if (!counter->supported)
+               return -ENOENT;
+
        if (counter->system_wide)
                nthreads = 1;
 
@@ -679,8 +684,9 @@ static int __run_perf_stat(int argc, const char **argv)
                        unit_width = l;
        }
 
-       if (perf_evlist__apply_filters(evsel_list)) {
-               error("failed to set filter with %d (%s)\n", errno,
+       if (perf_evlist__apply_filters(evsel_list, &counter)) {
+               error("failed to set filter \"%s\" on event %s with %d (%s)\n",
+                       counter->filter, perf_evsel__name(counter), errno,
                        strerror_r(errno, msg, sizeof(msg)));
                return -1;
        }
@@ -766,6 +772,19 @@ static int run_perf_stat(int argc, const char **argv)
        return ret;
 }
 
+static void print_running(u64 run, u64 ena)
+{
+       if (csv_output) {
+               fprintf(output, "%s%" PRIu64 "%s%.2f",
+                                       csv_sep,
+                                       run,
+                                       csv_sep,
+                                       ena ? 100.0 * run / ena : 100.0);
+       } else if (run != ena) {
+               fprintf(output, "  (%.2f%%)", 100.0 * run / ena);
+       }
+}
+
 static void print_noise_pct(double total, double avg)
 {
        double pct = rel_stddev_stats(total, avg);
@@ -1076,6 +1095,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
                if (total) {
                        ratio = avg / total;
                        fprintf(output, " #   %5.2f  insns per cycle        ", ratio);
+               } else {
+                       fprintf(output, "                                   ");
                }
                total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]);
                total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
@@ -1145,6 +1166,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
                if (total) {
                        ratio = avg / total;
                        fprintf(output, " # %8.3f GHz                    ", ratio);
+               } else {
+                       fprintf(output, "                                   ");
                }
        } else if (transaction_run &&
                   perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX))) {
@@ -1249,6 +1272,7 @@ static void print_aggr(char *prefix)
                                        fprintf(output, "%s%s",
                                                csv_sep, counter->cgrp->name);
 
+                               print_running(run, ena);
                                fputc('\n', output);
                                continue;
                        }
@@ -1259,13 +1283,10 @@ static void print_aggr(char *prefix)
                        else
                                abs_printout(id, nr, counter, uval);
 
-                       if (!csv_output) {
+                       if (!csv_output)
                                print_noise(counter, 1.0);
 
-                               if (run != ena)
-                                       fprintf(output, "  (%.2f%%)",
-                                               100.0 * run / ena);
-                       }
+                       print_running(run, ena);
                        fputc('\n', output);
                }
        }
@@ -1281,11 +1302,15 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
        double avg = avg_stats(&ps->res_stats[0]);
        int scaled = counter->counts->scaled;
        double uval;
+       double avg_enabled, avg_running;
+
+       avg_enabled = avg_stats(&ps->res_stats[1]);
+       avg_running = avg_stats(&ps->res_stats[2]);
 
        if (prefix)
                fprintf(output, "%s", prefix);
 
-       if (scaled == -1) {
+       if (scaled == -1 || !counter->supported) {
                fprintf(output, "%*s%s",
                        csv_output ? 0 : 18,
                        counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
@@ -1300,6 +1325,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
                if (counter->cgrp)
                        fprintf(output, "%s%s", csv_sep, counter->cgrp->name);
 
+               print_running(avg_running, avg_enabled);
                fputc('\n', output);
                return;
        }
@@ -1313,19 +1339,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 
        print_noise(counter, avg);
 
-       if (csv_output) {
-               fputc('\n', output);
-               return;
-       }
-
-       if (scaled) {
-               double avg_enabled, avg_running;
-
-               avg_enabled = avg_stats(&ps->res_stats[1]);
-               avg_running = avg_stats(&ps->res_stats[2]);
-
-               fprintf(output, " [%5.2f%%]", 100 * avg_running / avg_enabled);
-       }
+       print_running(avg_running, avg_enabled);
        fprintf(output, "\n");
 }
 
@@ -1367,6 +1381,7 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
                                fprintf(output, "%s%s",
                                        csv_sep, counter->cgrp->name);
 
+                       print_running(run, ena);
                        fputc('\n', output);
                        continue;
                }
@@ -1378,13 +1393,10 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
                else
                        abs_printout(cpu, 0, counter, uval);
 
-               if (!csv_output) {
+               if (!csv_output)
                        print_noise(counter, 1.0);
+               print_running(run, ena);
 
-                       if (run != ena)
-                               fprintf(output, "  (%.2f%%)",
-                                       100.0 * run / ena);
-               }
                fputc('\n', output);
        }
 }
index f3bb1a4bf060c4a6ad2347f7f40b321916669533..e50fe1187b0ba2ca808f6c0a0d3effd8156b4982 100644 (file)
@@ -67,6 +67,7 @@ struct timechart {
                                skip_eagain;
        u64                     min_time,
                                merge_dist;
+       bool                    force;
 };
 
 struct per_pidcomm;
@@ -1598,6 +1599,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
        struct perf_data_file file = {
                .path = input_name,
                .mode = PERF_DATA_MODE_READ,
+               .force = tchart->force,
        };
 
        struct perf_session *session = perf_session__new(&file, false,
@@ -1623,7 +1625,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
                goto out_delete;
        }
 
-       ret = perf_session__process_events(session, &tchart->tool);
+       ret = perf_session__process_events(session);
        if (ret)
                goto out_delete;
 
@@ -1956,9 +1958,11 @@ int cmd_timechart(int argc, const char **argv,
        OPT_CALLBACK(0, "io-merge-dist", &tchart.merge_dist, "time",
                     "merge events that are merge-dist us apart",
                     parse_time),
+       OPT_BOOLEAN('f', "force", &tchart.force, "don't complain, do it"),
        OPT_END()
        };
-       const char * const timechart_usage[] = {
+       const char * const timechart_subcommands[] = { "record", NULL };
+       const char *timechart_usage[] = {
                "perf timechart [<options>] {record}",
                NULL
        };
@@ -1976,8 +1980,8 @@ int cmd_timechart(int argc, const char **argv,
                "perf timechart record [<options>]",
                NULL
        };
-       argc = parse_options(argc, argv, timechart_options, timechart_usage,
-                       PARSE_OPT_STOP_AT_NON_OPTION);
+       argc = parse_options_subcommand(argc, argv, timechart_options, timechart_subcommands,
+                       timechart_usage, PARSE_OPT_STOP_AT_NON_OPTION);
 
        if (tchart.power_only && tchart.tasks_only) {
                pr_err("-P and -T options cannot be used at the same time.\n");
index c4c7eac69de46405a6aec8c35aa6e9508c4d249a..1cb3436276d1599ea0f1ffc80d36e655aad690be 100644 (file)
@@ -716,7 +716,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
 
        if (!machine) {
                pr_err("%u unprocessable samples recorded.\r",
-                      top->session->stats.nr_unprocessable_samples++);
+                      top->session->evlist->stats.nr_unprocessable_samples++);
                return;
        }
 
@@ -757,8 +757,10 @@ static void perf_event__process_sample(struct perf_tool *tool,
                    al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
                    RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
                        if (symbol_conf.vmlinux_name) {
-                               ui__warning("The %s file can't be used.\n%s",
-                                           symbol_conf.vmlinux_name, msg);
+                               char serr[256];
+                               dso__strerror_load(al.map->dso, serr, sizeof(serr));
+                               ui__warning("The %s file can't be used: %s\n%s",
+                                           symbol_conf.vmlinux_name, serr, msg);
                        } else {
                                ui__warning("A vmlinux file was not found.\n%s",
                                            msg);
@@ -856,7 +858,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
                        hists__inc_nr_events(evsel__hists(evsel), event->header.type);
                        machine__process_event(machine, event, &sample);
                } else
-                       ++session->stats.nr_unknown_events;
+                       ++session->evlist->stats.nr_unknown_events;
 next_event:
                perf_evlist__mmap_consume(top->evlist, idx);
        }
index 7e935f1083ec64b8ea23b0d870a1241c759b724c..e124741be187ee729a77b088d30f843ee24eefa4 100644 (file)
@@ -52,7 +52,9 @@ struct tp_field {
 #define TP_UINT_FIELD(bits) \
 static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
 { \
-       return *(u##bits *)(sample->raw_data + field->offset); \
+       u##bits value; \
+       memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
+       return value;  \
 }
 
 TP_UINT_FIELD(8);
@@ -63,7 +65,8 @@ TP_UINT_FIELD(64);
 #define TP_UINT_FIELD__SWAPPED(bits) \
 static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
 { \
-       u##bits value = *(u##bits *)(sample->raw_data + field->offset); \
+       u##bits value; \
+       memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
        return bswap_##bits(value);\
 }
 
@@ -1132,6 +1135,8 @@ static struct syscall_fmt *syscall_fmt__find(const char *name)
 
 struct syscall {
        struct event_format *tp_format;
+       int                 nr_args;
+       struct format_field *args;
        const char          *name;
        bool                filtered;
        bool                is_exit;
@@ -1219,7 +1224,9 @@ struct trace {
                struct syscall  *table;
        } syscalls;
        struct record_opts      opts;
+       struct perf_evlist      *evlist;
        struct machine          *host;
+       struct thread           *current;
        u64                     base_time;
        FILE                    *output;
        unsigned long           nr_events;
@@ -1227,6 +1234,10 @@ struct trace {
        const char              *last_vfs_getname;
        struct intlist          *tid_list;
        struct intlist          *pid_list;
+       struct {
+               size_t          nr;
+               pid_t           *entries;
+       }                       filter_pids;
        double                  duration_filter;
        double                  runtime_ms;
        struct {
@@ -1243,6 +1254,7 @@ struct trace {
        bool                    show_comm;
        bool                    show_tool_stats;
        bool                    trace_syscalls;
+       bool                    force;
        int                     trace_pgfaults;
 };
 
@@ -1433,14 +1445,14 @@ static int syscall__set_arg_fmts(struct syscall *sc)
        struct format_field *field;
        int idx = 0;
 
-       sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *));
+       sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
        if (sc->arg_scnprintf == NULL)
                return -1;
 
        if (sc->fmt)
                sc->arg_parm = sc->fmt->arg_parm;
 
-       for (field = sc->tp_format->format.fields->next; field; field = field->next) {
+       for (field = sc->args; field; field = field->next) {
                if (sc->fmt && sc->fmt->arg_scnprintf[idx])
                        sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
                else if (field->flags & FIELD_IS_POINTER)
@@ -1506,18 +1518,37 @@ static int trace__read_syscall_info(struct trace *trace, int id)
        if (sc->tp_format == NULL)
                return -1;
 
+       sc->args = sc->tp_format->format.fields;
+       sc->nr_args = sc->tp_format->format.nr_fields;
+       /* drop nr field - not relevant here; does not exist on older kernels */
+       if (sc->args && strcmp(sc->args->name, "nr") == 0) {
+               sc->args = sc->args->next;
+               --sc->nr_args;
+       }
+
        sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
 
        return syscall__set_arg_fmts(sc);
 }
 
+/*
+ * args is to be interpreted as a series of longs but we need to handle
+ * 8-byte unaligned accesses. args points to raw_data within the event
+ * and raw_data is guaranteed to be 8-byte unaligned because it is
+ * preceded by raw_size which is a u32. So we need to copy args to a temp
+ * variable to read it. Most notably this avoids extended load instructions
+ * on unaligned addresses
+ */
+
 static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
-                                     unsigned long *args, struct trace *trace,
+                                     unsigned char *args, struct trace *trace,
                                      struct thread *thread)
 {
        size_t printed = 0;
+       unsigned char *p;
+       unsigned long val;
 
-       if (sc->tp_format != NULL) {
+       if (sc->args != NULL) {
                struct format_field *field;
                u8 bit = 1;
                struct syscall_arg arg = {
@@ -1527,16 +1558,21 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
                        .thread = thread,
                };
 
-               for (field = sc->tp_format->format.fields->next; field;
+               for (field = sc->args; field;
                     field = field->next, ++arg.idx, bit <<= 1) {
                        if (arg.mask & bit)
                                continue;
+
+                       /* special care for unaligned accesses */
+                       p = args + sizeof(unsigned long) * arg.idx;
+                       memcpy(&val, p, sizeof(val));
+
                        /*
                         * Suppress this argument if its value is zero and
                         * and we don't have a string associated in an
                         * strarray for it.
                         */
-                       if (args[arg.idx] == 0 &&
+                       if (val == 0 &&
                            !(sc->arg_scnprintf &&
                              sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
                              sc->arg_parm[arg.idx]))
@@ -1545,23 +1581,26 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
                        printed += scnprintf(bf + printed, size - printed,
                                             "%s%s: ", printed ? ", " : "", field->name);
                        if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
-                               arg.val = args[arg.idx];
+                               arg.val = val;
                                if (sc->arg_parm)
                                        arg.parm = sc->arg_parm[arg.idx];
                                printed += sc->arg_scnprintf[arg.idx](bf + printed,
                                                                      size - printed, &arg);
                        } else {
                                printed += scnprintf(bf + printed, size - printed,
-                                                    "%ld", args[arg.idx]);
+                                                    "%ld", val);
                        }
                }
        } else {
                int i = 0;
 
                while (i < 6) {
+                       /* special care for unaligned accesses */
+                       p = args + sizeof(unsigned long) * i;
+                       memcpy(&val, p, sizeof(val));
                        printed += scnprintf(bf + printed, size - printed,
                                             "%sarg%d: %ld",
-                                            printed ? ", " : "", i, args[i]);
+                                            printed ? ", " : "", i, val);
                        ++i;
                }
        }
@@ -1642,6 +1681,29 @@ static void thread__update_stats(struct thread_trace *ttrace,
        update_stats(stats, duration);
 }
 
+static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
+{
+       struct thread_trace *ttrace;
+       u64 duration;
+       size_t printed;
+
+       if (trace->current == NULL)
+               return 0;
+
+       ttrace = thread__priv(trace->current);
+
+       if (!ttrace->entry_pending)
+               return 0;
+
+       duration = sample->time - ttrace->entry_time;
+
+       printed  = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
+       printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
+       ttrace->entry_pending = false;
+
+       return printed;
+}
+
 static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
                            union perf_event *event __maybe_unused,
                            struct perf_sample *sample)
@@ -1673,6 +1735,9 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
                        return -1;
        }
 
+       if (!trace->summary_only)
+               trace__printf_interrupted_entry(trace, sample);
+
        ttrace->entry_time = sample->time;
        msg = ttrace->entry_str;
        printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
@@ -1688,6 +1753,11 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
        } else
                ttrace->entry_pending = true;
 
+       if (trace->current != thread) {
+               thread__put(trace->current);
+               trace->current = thread__get(thread);
+       }
+
        return 0;
 }
 
@@ -1805,6 +1875,28 @@ out_dump:
        return 0;
 }
 
+static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
+                               union perf_event *event __maybe_unused,
+                               struct perf_sample *sample)
+{
+       trace__printf_interrupted_entry(trace, sample);
+       trace__fprintf_tstamp(trace, sample->time, trace->output);
+
+       if (trace->trace_syscalls)
+               fprintf(trace->output, "(         ): ");
+
+       fprintf(trace->output, "%s:", evsel->name);
+
+       if (evsel->tp_format) {
+               event_format__fprintf(evsel->tp_format, sample->cpu,
+                                     sample->raw_data, sample->raw_size,
+                                     trace->output);
+       }
+
+       fprintf(trace->output, ")\n");
+       return 0;
+}
+
 static void print_location(FILE *f, struct perf_sample *sample,
                           struct addr_location *al,
                           bool print_dso, bool print_sym)
@@ -2037,10 +2129,39 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
        return 0;
 }
 
-static int trace__run(struct trace *trace, int argc, const char **argv)
+static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
 {
-       struct perf_evlist *evlist = perf_evlist__new();
+       const u32 type = event->header.type;
        struct perf_evsel *evsel;
+
+       if (!trace->full_time && trace->base_time == 0)
+               trace->base_time = sample->time;
+
+       if (type != PERF_RECORD_SAMPLE) {
+               trace__process_event(trace, trace->host, event, sample);
+               return;
+       }
+
+       evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
+       if (evsel == NULL) {
+               fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
+               return;
+       }
+
+       if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
+           sample->raw_data == NULL) {
+               fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
+                      perf_evsel__name(evsel), sample->tid,
+                      sample->cpu, sample->raw_size);
+       } else {
+               tracepoint_handler handler = evsel->handler;
+               handler(trace, evsel, event, sample);
+       }
+}
+
+static int trace__run(struct trace *trace, int argc, const char **argv)
+{
+       struct perf_evlist *evlist = trace->evlist;
        int err = -1, i;
        unsigned long before;
        const bool forks = argc > 0;
@@ -2048,11 +2169,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 
        trace->live = true;
 
-       if (evlist == NULL) {
-               fprintf(trace->output, "Not enough memory to run!\n");
-               goto out;
-       }
-
        if (trace->trace_syscalls &&
            perf_evlist__add_syscall_newtp(evlist, trace__sys_enter,
                                           trace__sys_exit))
@@ -2105,16 +2221,34 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
        if (err < 0)
                goto out_error_open;
 
+       /*
+        * Better not use !target__has_task() here because we need to cover the
+        * case where no threads were specified in the command line, but a
+        * workload was, and in that case we will fill in the thread_map when
+        * we fork the workload in perf_evlist__prepare_workload.
+        */
+       if (trace->filter_pids.nr > 0)
+               err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
+       else if (evlist->threads->map[0] == -1)
+               err = perf_evlist__set_filter_pid(evlist, getpid());
+
+       if (err < 0) {
+               printf("err=%d,%s\n", -err, strerror(-err));
+               exit(1);
+       }
+
        err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
        if (err < 0)
                goto out_error_mmap;
 
-       perf_evlist__enable(evlist);
-
        if (forks)
                perf_evlist__start_workload(evlist);
+       else
+               perf_evlist__enable(evlist);
 
-       trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1;
+       trace->multiple_threads = evlist->threads->map[0] == -1 ||
+                                 evlist->threads->nr > 1 ||
+                                 perf_evlist__first(evlist)->attr.inherit;
 again:
        before = trace->nr_events;
 
@@ -2122,8 +2256,6 @@ again:
                union perf_event *event;
 
                while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
-                       const u32 type = event->header.type;
-                       tracepoint_handler handler;
                        struct perf_sample sample;
 
                        ++trace->nr_events;
@@ -2134,30 +2266,7 @@ again:
                                goto next_event;
                        }
 
-                       if (!trace->full_time && trace->base_time == 0)
-                               trace->base_time = sample.time;
-
-                       if (type != PERF_RECORD_SAMPLE) {
-                               trace__process_event(trace, trace->host, event, &sample);
-                               continue;
-                       }
-
-                       evsel = perf_evlist__id2evsel(evlist, sample.id);
-                       if (evsel == NULL) {
-                               fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
-                               goto next_event;
-                       }
-
-                       if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
-                           sample.raw_data == NULL) {
-                               fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
-                                      perf_evsel__name(evsel), sample.tid,
-                                      sample.cpu, sample.raw_size);
-                               goto next_event;
-                       }
-
-                       handler = evsel->handler;
-                       handler(trace, evsel, event, &sample);
+                       trace__handle_event(trace, event, &sample);
 next_event:
                        perf_evlist__mmap_consume(evlist, i);
 
@@ -2180,6 +2289,8 @@ next_event:
        }
 
 out_disable:
+       thread__zput(trace->current);
+
        perf_evlist__disable(evlist);
 
        if (!err) {
@@ -2197,7 +2308,7 @@ out_disable:
 
 out_delete_evlist:
        perf_evlist__delete(evlist);
-out:
+       trace->evlist = NULL;
        trace->live = false;
        return err;
 {
@@ -2235,6 +2346,7 @@ static int trace__replay(struct trace *trace)
        struct perf_data_file file = {
                .path  = input_name,
                .mode  = PERF_DATA_MODE_READ,
+               .force = trace->force,
        };
        struct perf_session *session;
        struct perf_evsel *evsel;
@@ -2309,7 +2421,7 @@ static int trace__replay(struct trace *trace)
 
        setup_pager();
 
-       err = perf_session__process_events(session, &trace->tool);
+       err = perf_session__process_events(session);
        if (err)
                pr_err("Failed to process events, error %d", err);
 
@@ -2434,6 +2546,38 @@ static int trace__set_duration(const struct option *opt, const char *str,
        return 0;
 }
 
+static int trace__set_filter_pids(const struct option *opt, const char *str,
+                                 int unset __maybe_unused)
+{
+       int ret = -1;
+       size_t i;
+       struct trace *trace = opt->value;
+       /*
+        * FIXME: introduce a intarray class, plain parse csv and create a
+        * { int nr, int entries[] } struct...
+        */
+       struct intlist *list = intlist__new(str);
+
+       if (list == NULL)
+               return -1;
+
+       i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
+       trace->filter_pids.entries = calloc(i, sizeof(pid_t));
+
+       if (trace->filter_pids.entries == NULL)
+               goto out;
+
+       trace->filter_pids.entries[0] = getpid();
+
+       for (i = 1; i < trace->filter_pids.nr; ++i)
+               trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
+
+       intlist__delete(list);
+       ret = 0;
+out:
+       return ret;
+}
+
 static int trace__open_output(struct trace *trace, const char *filename)
 {
        struct stat st;
@@ -2468,9 +2612,17 @@ static int parse_pagefaults(const struct option *opt, const char *str,
        return 0;
 }
 
+static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
+{
+       struct perf_evsel *evsel;
+
+       evlist__for_each(evlist, evsel)
+               evsel->handler = handler;
+}
+
 int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
 {
-       const char * const trace_usage[] = {
+       const char *trace_usage[] = {
                "perf trace [<options>] [<command>]",
                "perf trace [<options>] -- <command> [<options>]",
                "perf trace record [<options>] [<command>]",
@@ -2502,6 +2654,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
        const char *output_name = NULL;
        const char *ev_qualifier_str = NULL;
        const struct option trace_options[] = {
+       OPT_CALLBACK(0, "event", &trace.evlist, "event",
+                    "event selector. use 'perf list' to list available events",
+                    parse_events_option),
        OPT_BOOLEAN(0, "comm", &trace.show_comm,
                    "show the thread COMM next to its id"),
        OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
@@ -2513,6 +2668,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
                    "trace events on existing process id"),
        OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
                    "trace events on existing thread id"),
+       OPT_CALLBACK(0, "filter-pids", &trace, "float",
+                    "show only events with duration > N.M ms", trace__set_filter_pids),
        OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
                    "system-wide collection from all CPUs"),
        OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
@@ -2538,19 +2695,36 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
                     "Trace pagefaults", parse_pagefaults, "maj"),
        OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
+       OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
        OPT_END()
        };
+       const char * const trace_subcommands[] = { "record", NULL };
        int err;
        char bf[BUFSIZ];
 
-       argc = parse_options(argc, argv, trace_options, trace_usage,
-                            PARSE_OPT_STOP_AT_NON_OPTION);
+       signal(SIGSEGV, sighandler_dump_stack);
+       signal(SIGFPE, sighandler_dump_stack);
+
+       trace.evlist = perf_evlist__new();
+       if (trace.evlist == NULL)
+               return -ENOMEM;
+
+       if (trace.evlist == NULL) {
+               pr_err("Not enough memory to run!\n");
+               goto out;
+       }
+
+       argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
+                                trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
 
        if (trace.trace_pgfaults) {
                trace.opts.sample_address = true;
                trace.opts.sample_time = true;
        }
 
+       if (trace.evlist->nr_entries > 0)
+               evlist__set_evsel_handler(trace.evlist, trace__event_handler);
+
        if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
                return trace__record(&trace, argc-1, &argv[1]);
 
@@ -2558,7 +2732,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
        if (trace.summary_only)
                trace.summary = trace.summary_only;
 
-       if (!trace.trace_syscalls && !trace.trace_pgfaults) {
+       if (!trace.trace_syscalls && !trace.trace_pgfaults &&
+           trace.evlist->nr_entries == 0 /* Was --events used? */) {
                pr_err("Please specify something to trace.\n");
                return -1;
        }
index b210d62907e4d87853ce25bdfd86d3eee74c3e09..3688ad29085fa55739cceabad42e34f1413e879f 100644 (file)
@@ -37,6 +37,7 @@ extern int cmd_test(int argc, const char **argv, const char *prefix);
 extern int cmd_trace(int argc, const char **argv, const char *prefix);
 extern int cmd_inject(int argc, const char **argv, const char *prefix);
 extern int cmd_mem(int argc, const char **argv, const char *prefix);
+extern int cmd_data(int argc, const char **argv, const char *prefix);
 
 extern int find_scripts(char **scripts_array, char **scripts_path_array);
 #endif
index 0906fc401c520aa2c49f38f4e54447cd788ee425..00fcaf8a5b8d60535d00981ff67a47094ece0604 100644 (file)
@@ -7,6 +7,7 @@ perf-archive                    mainporcelain common
 perf-bench                     mainporcelain common
 perf-buildid-cache             mainporcelain common
 perf-buildid-list              mainporcelain common
+perf-data                      mainporcelain common
 perf-diff                      mainporcelain common
 perf-evlist                    mainporcelain common
 perf-inject                    mainporcelain common
index cc224080b52560d5b37ed2035b436215a13ea095..59a98c6432403874a564753dd6e790b8632b672e 100644 (file)
@@ -11,19 +11,26 @@ ifneq ($(obj-perf),)
 obj-perf := $(abspath $(obj-perf))/
 endif
 
-LIB_INCLUDE := $(srctree)/tools/lib/
+$(shell echo -n > .config-detected)
+detected     = $(shell echo "$(1)=y"       >> .config-detected)
+detected_var = $(shell echo "$(1)=$($(1))" >> .config-detected)
+
 CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
 
 include $(src-perf)/config/Makefile.arch
 
+$(call detected_var,ARCH)
+
 NO_PERF_REGS := 1
 
 # Additional ARCH settings for x86
 ifeq ($(ARCH),x86)
+  $(call detected,CONFIG_X86)
   ifeq (${IS_64_BIT}, 1)
     CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
     ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
     LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
+    $(call detected,CONFIG_X86_64)
   else
     LIBUNWIND_LIBS = -lunwind -lunwind-x86
   endif
@@ -40,6 +47,10 @@ ifeq ($(ARCH),arm64)
   LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
 endif
 
+ifeq ($(NO_PERF_REGS),0)
+  $(call detected,CONFIG_PERF_REGS)
+endif
+
 # So far there's only x86 and arm libdw unwind support merged in perf.
 # Disable it on all other architectures in case libdw unwind
 # support is detected in system. Add supported architectures
@@ -84,6 +95,17 @@ ifndef NO_LIBELF
   FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
 endif
 
+ifdef LIBBABELTRACE
+  # for linking with debug library, run like:
+  # make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
+  ifdef LIBBABELTRACE_DIR
+    LIBBABELTRACE_CFLAGS  := -I$(LIBBABELTRACE_DIR)/include
+    LIBBABELTRACE_LDFLAGS := -L$(LIBBABELTRACE_DIR)/lib
+  endif
+  FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS)
+  FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
+endif
+
 # include ARCH specific config
 -include $(src-perf)/arch/$(ARCH)/Makefile
 
@@ -114,6 +136,8 @@ ifdef PARSER_DEBUG
   PARSER_DEBUG_BISON := -t
   PARSER_DEBUG_FLEX  := -d
   CFLAGS             += -DPARSER_DEBUG
+  $(call detected_var,PARSER_DEBUG_BISON)
+  $(call detected_var,PARSER_DEBUG_FLEX)
 endif
 
 ifndef NO_LIBPYTHON
@@ -152,121 +176,7 @@ LDFLAGS += -Wl,-z,noexecstack
 
 EXTLIBS = -lpthread -lrt -lm -ldl
 
-ifneq ($(OUTPUT),)
-  OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/
-  $(shell mkdir -p $(OUTPUT_FEATURES))
-endif
-
-feature_check = $(eval $(feature_check_code))
-define feature_check_code
-  feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
-endef
-
-feature_set = $(eval $(feature_set_code))
-define feature_set_code
-  feature-$(1) := 1
-endef
-
-#
-# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output:
-#
-
-#
-# Note that this is not a complete list of all feature tests, just
-# those that are typically built on a fully configured system.
-#
-# [ Feature tests not mentioned here have to be built explicitly in
-#   the rule that uses them - an example for that is the 'bionic'
-#   feature check. ]
-#
-CORE_FEATURE_TESTS =                   \
-       backtrace                       \
-       dwarf                           \
-       fortify-source                  \
-       sync-compare-and-swap           \
-       glibc                           \
-       gtk2                            \
-       gtk2-infobar                    \
-       libaudit                        \
-       libbfd                          \
-       libelf                          \
-       libelf-getphdrnum               \
-       libelf-mmap                     \
-       libnuma                         \
-       libperl                         \
-       libpython                       \
-       libpython-version               \
-       libslang                        \
-       libunwind                       \
-       pthread-attr-setaffinity-np     \
-       stackprotector-all              \
-       timerfd                         \
-       libdw-dwarf-unwind              \
-       zlib
-
-LIB_FEATURE_TESTS =                    \
-       dwarf                           \
-       glibc                           \
-       gtk2                            \
-       libaudit                        \
-       libbfd                          \
-       libelf                          \
-       libnuma                         \
-       libperl                         \
-       libpython                       \
-       libslang                        \
-       libunwind                       \
-       libdw-dwarf-unwind              \
-       zlib
-
-VF_FEATURE_TESTS =                     \
-       backtrace                       \
-       fortify-source                  \
-       sync-compare-and-swap           \
-       gtk2-infobar                    \
-       libelf-getphdrnum               \
-       libelf-mmap                     \
-       libpython-version               \
-       pthread-attr-setaffinity-np     \
-       stackprotector-all              \
-       timerfd                         \
-       libunwind-debug-frame           \
-       bionic                          \
-       liberty                         \
-       liberty-z                       \
-       cplus-demangle                  \
-       compile-32                      \
-       compile-x32
-
-# Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features.
-# If in the future we need per-feature checks/flags for features not
-# mentioned in this list we need to refactor this ;-).
-set_test_all_flags = $(eval $(set_test_all_flags_code))
-define set_test_all_flags_code
-  FEATURE_CHECK_CFLAGS-all  += $(FEATURE_CHECK_CFLAGS-$(1))
-  FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1))
-endef
-
-$(foreach feat,$(CORE_FEATURE_TESTS),$(call set_test_all_flags,$(feat)))
-
-#
-# Special fast-path for the 'all features are available' case:
-#
-$(call feature_check,all,$(MSG))
-
-#
-# Just in case the build freshly failed, make sure we print the
-# feature matrix:
-#
-ifeq ($(feature-all), 1)
-  #
-  # test-all.c passed - just set all the core feature flags to 1:
-  #
-  $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat)))
-else
-  $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(addsuffix .bin,$(CORE_FEATURE_TESTS)) >/dev/null 2>&1)
-  $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
-endif
+include $(srctree)/tools/build/Makefile.feature
 
 ifeq ($(feature-stackprotector-all), 1)
   CFLAGS += -fstack-protector-all
@@ -295,7 +205,7 @@ endif
 
 CFLAGS += -I$(src-perf)/util
 CFLAGS += -I$(src-perf)
-CFLAGS += -I$(LIB_INCLUDE)
+CFLAGS += -I$(srctree)/tools/lib/
 
 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 
@@ -361,6 +271,7 @@ endif # NO_LIBELF
 ifndef NO_LIBELF
   CFLAGS += -DHAVE_LIBELF_SUPPORT
   EXTLIBS += -lelf
+  $(call detected,CONFIG_LIBELF)
 
   ifeq ($(feature-libelf-mmap), 1)
     CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
@@ -381,6 +292,7 @@ ifndef NO_LIBELF
       CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
       LDFLAGS += $(LIBDW_LDFLAGS)
       EXTLIBS += -ldw
+      $(call detected,CONFIG_DWARF)
     endif # PERF_HAVE_DWARF_REGS
   endif # NO_DWARF
 endif # NO_LIBELF
@@ -408,9 +320,11 @@ ifdef NO_LIBUNWIND
     dwarf-post-unwind := 0
   else
     dwarf-post-unwind-text := libdw
+    $(call detected,CONFIG_LIBDW_DWARF_UNWIND)
   endif
 else
   dwarf-post-unwind-text := libunwind
+  $(call detected,CONFIG_LIBUNWIND)
   # Enable libunwind support by default.
   ifndef NO_LIBDW_DWARF_UNWIND
     NO_LIBDW_DWARF_UNWIND := 1
@@ -419,6 +333,7 @@ endif
 
 ifeq ($(dwarf-post-unwind),1)
   CFLAGS += -DHAVE_DWARF_UNWIND_SUPPORT
+  $(call detected,CONFIG_DWARF_UNWIND)
 else
   NO_DWARF_UNWIND := 1
 endif
@@ -447,6 +362,7 @@ ifndef NO_LIBAUDIT
   else
     CFLAGS += -DHAVE_LIBAUDIT_SUPPORT
     EXTLIBS += -laudit
+    $(call detected,CONFIG_AUDIT)
   endif
 endif
 
@@ -463,6 +379,7 @@ ifndef NO_SLANG
     CFLAGS += -I/usr/include/slang
     CFLAGS += -DHAVE_SLANG_SUPPORT
     EXTLIBS += -lslang
+    $(call detected,CONFIG_SLANG)
   endif
 endif
 
@@ -497,10 +414,11 @@ else
   ifneq ($(feature-libperl), 1)
     CFLAGS += -DNO_LIBPERL
     NO_LIBPERL := 1
-    msg := $(warning Missing perl devel files. Disabling perl scripting support, consider installing perl-ExtUtils-Embed);
+    msg := $(warning Missing perl devel files. Disabling perl scripting support, please install perl-ExtUtils-Embed/libperl-dev);
   else
     LDFLAGS += $(PERL_EMBED_LDFLAGS)
     EXTLIBS += $(PERL_EMBED_LIBADD)
+    $(call detected,CONFIG_LIBPERL)
   endif
 endif
 
@@ -513,22 +431,21 @@ endif
 disable-python = $(eval $(disable-python_code))
 define disable-python_code
   CFLAGS += -DNO_LIBPYTHON
-  $(if $(1),$(warning No $(1) was found))
-  $(warning Python support will not be built)
+  $(warning $1)
   NO_LIBPYTHON := 1
 endef
 
 ifdef NO_LIBPYTHON
-  $(call disable-python)
+  $(call disable-python,Python support disabled by user)
 else
 
   ifndef PYTHON
-    $(call disable-python,python interpreter)
+    $(call disable-python,No python interpreter was found: disables Python support - please install python-devel/python-dev)
   else
     PYTHON_WORD := $(call shell-wordify,$(PYTHON))
 
     ifndef PYTHON_CONFIG
-      $(call disable-python,python-config tool)
+      $(call disable-python,No 'python-config' tool was found: disables Python support - please install python-devel/python-dev)
     else
 
       PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
@@ -540,7 +457,7 @@ else
       FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
 
       ifneq ($(feature-libpython), 1)
-        $(call disable-python,Python.h (for Python 2.x))
+        $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev)
       else
 
         ifneq ($(feature-libpython-version), 1)
@@ -560,6 +477,7 @@ else
           LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
           EXTLIBS += $(PYTHON_EMBED_LIBADD)
           LANG_BINDINGS += $(obj-perf)python/perf.so
+          $(call detected,CONFIG_LIBPYTHON)
         endif
       endif
     endif
@@ -600,7 +518,7 @@ else
             EXTLIBS += -liberty
             CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
           else
-            msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling)
+            msg := $(warning No bfd.h/libbfd found, please install binutils-dev[el]/zlib-static/libiberty-dev to gain symbol demangling)
             CFLAGS += -DNO_DEMANGLE
           endif
         endif
@@ -617,11 +535,23 @@ ifndef NO_ZLIB
   ifeq ($(feature-zlib), 1)
     CFLAGS += -DHAVE_ZLIB_SUPPORT
     EXTLIBS += -lz
+    $(call detected,CONFIG_ZLIB)
   else
     NO_ZLIB := 1
   endif
 endif
 
+ifndef NO_LZMA
+  ifeq ($(feature-lzma), 1)
+    CFLAGS += -DHAVE_LZMA_SUPPORT
+    EXTLIBS += -llzma
+    $(call detected,CONFIG_LZMA)
+  else
+    msg := $(warning No liblzma found, disables xz kernel module decompression, please install xz-devel/liblzma-dev);
+    NO_LZMA := 1
+  endif
+endif
+
 ifndef NO_BACKTRACE
   ifeq ($(feature-backtrace), 1)
     CFLAGS += -DHAVE_BACKTRACE_SUPPORT
@@ -635,6 +565,7 @@ ifndef NO_LIBNUMA
   else
     CFLAGS += -DHAVE_LIBNUMA_SUPPORT
     EXTLIBS += -lnuma
+    $(call detected,CONFIG_NUMA)
   endif
 endif
 
@@ -651,7 +582,7 @@ ifeq (${IS_64_BIT}, 1)
       NO_PERF_READ_VDSO32 := 1
     endif
   endif
-  ifneq (${IS_X86_64}, 1)
+  ifneq ($(ARCH), x86)
     NO_PERF_READ_VDSOX32 := 1
   endif
   ifndef NO_PERF_READ_VDSOX32
@@ -667,6 +598,18 @@ else
   NO_PERF_READ_VDSOX32 := 1
 endif
 
+ifdef LIBBABELTRACE
+  $(call feature_check,libbabeltrace)
+  ifeq ($(feature-libbabeltrace), 1)
+    CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS)
+    LDFLAGS += $(LIBBABELTRACE_LDFLAGS)
+    EXTLIBS += -lbabeltrace-ctf
+    $(call detected,CONFIG_LIBBABELTRACE)
+  else
+    msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev);
+  endif
+endif
+
 # Among the variables below, these:
 #   perfexecdir
 #   template_dir
@@ -699,7 +642,7 @@ sysconfdir = $(prefix)/etc
 ETC_PERFCONFIG = etc/perfconfig
 endif
 ifndef lib
-ifeq ($(IS_X86_64),1)
+ifeq ($(ARCH)$(IS_64_BIT), x861)
 lib = lib64
 else
 lib = lib
@@ -735,83 +678,33 @@ plugindir=$(libdir)/traceevent/plugins
 plugindir_SQ= $(subst ','\'',$(plugindir))
 endif
 
-#
-# Print the result of the feature test:
-#
-feature_print_status = $(eval $(feature_print_status_code)) $(info $(MSG))
-
-define feature_print_status_code
-  ifeq ($(feature-$(1)), 1)
-    MSG = $(shell printf '...%30s: [ \033[32mon\033[m  ]' $(1))
-  else
-    MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
-  endif
-endef
-
-feature_print_var = $(eval $(feature_print_var_code)) $(info $(MSG))
-define feature_print_var_code
+print_var = $(eval $(print_var_code)) $(info $(MSG))
+define print_var_code
     MSG = $(shell printf '...%30s: %s' $(1) $($(1)))
 endef
 
-feature_print_text = $(eval $(feature_print_text_code)) $(info $(MSG))
-define feature_print_text_code
-    MSG = $(shell printf '...%30s: %s' $(1) $(2))
-endef
-
-PERF_FEATURES := $(foreach feat,$(LIB_FEATURE_TESTS),feature-$(feat)($(feature-$(feat))))
-PERF_FEATURES_FILE := $(shell touch $(OUTPUT)PERF-FEATURES; cat $(OUTPUT)PERF-FEATURES)
-
-ifeq ($(dwarf-post-unwind),1)
-  PERF_FEATURES += dwarf-post-unwind($(dwarf-post-unwind-text))
-endif
-
-# The $(display_lib) controls the default detection message
-# output. It's set if:
-# - detected features differes from stored features from
-#   last build (in PERF-FEATURES file)
-# - one of the $(LIB_FEATURE_TESTS) is not detected
-# - VF is enabled
-
-ifneq ("$(PERF_FEATURES)","$(PERF_FEATURES_FILE)")
-  $(shell echo "$(PERF_FEATURES)" > $(OUTPUT)PERF-FEATURES)
-  display_lib := 1
-endif
-
-feature_check = $(eval $(feature_check_code))
-define feature_check_code
-  ifneq ($(feature-$(1)), 1)
-    display_lib := 1
-  endif
-endef
-
-$(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_check,$(feat)))
-
 ifeq ($(VF),1)
-  display_lib := 1
-  display_vf := 1
-endif
-
-ifeq ($(display_lib),1)
+  $(call print_var,prefix)
+  $(call print_var,bindir)
+  $(call print_var,libdir)
+  $(call print_var,sysconfdir)
+  $(call print_var,LIBUNWIND_DIR)
+  $(call print_var,LIBDW_DIR)
   $(info )
-  $(info Auto-detecting system features:)
-  $(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_print_status,$(feat),))
-
-  ifeq ($(dwarf-post-unwind),1)
-    $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
-  endif
-endif
-
-ifeq ($(display_vf),1)
-  $(foreach feat,$(VF_FEATURE_TESTS),$(call feature_print_status,$(feat),))
-  $(info )
-  $(call feature_print_var,prefix)
-  $(call feature_print_var,bindir)
-  $(call feature_print_var,libdir)
-  $(call feature_print_var,sysconfdir)
-  $(call feature_print_var,LIBUNWIND_DIR)
-  $(call feature_print_var,LIBDW_DIR)
 endif
 
-ifeq ($(display_lib),1)
-  $(info )
-endif
+$(call detected_var,bindir_SQ)
+$(call detected_var,PYTHON_WORD)
+ifneq ($(OUTPUT),)
+$(call detected_var,OUTPUT)
+endif
+$(call detected_var,htmldir_SQ)
+$(call detected_var,infodir_SQ)
+$(call detected_var,mandir_SQ)
+$(call detected_var,ETC_PERFCONFIG_SQ)
+$(call detected_var,prefix_SQ)
+$(call detected_var,perfexecdir_SQ)
+$(call detected_var,LIBDIR)
+$(call detected_var,GTK_CFLAGS)
+$(call detected_var,PERL_EMBED_CCOPTS)
+$(call detected_var,PYTHON_EMBED_CCOPTS)
index ac8721ffa6c8c681ccdb563607d5b80917062438..e11fbd6fae782e65caadff6e989ead9d0d6871a8 100644 (file)
@@ -1,32 +1,15 @@
+ifndef ARCH
+ARCH := $(shell uname -m 2>/dev/null || echo not)
+endif
 
-uname_M := $(shell uname -m 2>/dev/null || echo not)
-
-RAW_ARCH := $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-                                  -e s/arm.*/arm/ -e s/sa110/arm/ \
+ARCH := $(shell echo $(ARCH) | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
+                                  -e s/sun4u/sparc/ -e s/sparc64/sparc/ \
+                                  -e /arm64/!s/arm.*/arm/ -e s/sa110/arm/ \
                                   -e s/s390x/s390/ -e s/parisc64/parisc/ \
                                   -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
                                   -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
                                   -e s/tile.*/tile/ )
 
-# Additional ARCH settings for x86
-ifeq ($(RAW_ARCH),i386)
-  ARCH ?= x86
-endif
-
-ifeq ($(RAW_ARCH),x86_64)
-  ARCH ?= x86
-
-  ifneq (, $(findstring m32,$(CFLAGS)))
-    RAW_ARCH := x86_32
-  endif
-endif
-
-ifeq ($(RAW_ARCH),sparc64)
-  ARCH ?= sparc
-endif
-
-ARCH ?= $(RAW_ARCH)
-
 LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
 ifeq ($(LP64), 1)
   IS_64_BIT := 1
diff --git a/tools/perf/config/feature-checks/.gitignore b/tools/perf/config/feature-checks/.gitignore
deleted file mode 100644 (file)
index 80f3da0..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-*.d
-*.bin
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
deleted file mode 100644 (file)
index b32ff33..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-
-FILES=                                 \
-       test-all.bin                    \
-       test-backtrace.bin              \
-       test-bionic.bin                 \
-       test-dwarf.bin                  \
-       test-fortify-source.bin         \
-       test-sync-compare-and-swap.bin  \
-       test-glibc.bin                  \
-       test-gtk2.bin                   \
-       test-gtk2-infobar.bin           \
-       test-hello.bin                  \
-       test-libaudit.bin               \
-       test-libbfd.bin                 \
-       test-liberty.bin                \
-       test-liberty-z.bin              \
-       test-cplus-demangle.bin         \
-       test-libelf.bin                 \
-       test-libelf-getphdrnum.bin      \
-       test-libelf-mmap.bin            \
-       test-libnuma.bin                \
-       test-libperl.bin                \
-       test-libpython.bin              \
-       test-libpython-version.bin      \
-       test-libslang.bin               \
-       test-libunwind.bin              \
-       test-libunwind-debug-frame.bin  \
-       test-pthread-attr-setaffinity-np.bin    \
-       test-stackprotector-all.bin     \
-       test-timerfd.bin                \
-       test-libdw-dwarf-unwind.bin     \
-       test-compile-32.bin             \
-       test-compile-x32.bin            \
-       test-zlib.bin
-
-CC := $(CROSS_COMPILE)gcc -MD
-PKG_CONFIG := $(CROSS_COMPILE)pkg-config
-
-all: $(FILES)
-
-BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
-
-###############################
-
-test-all.bin:
-       $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz
-
-test-hello.bin:
-       $(BUILD)
-
-test-pthread-attr-setaffinity-np.bin:
-       $(BUILD) -D_GNU_SOURCE -Werror -lpthread
-
-test-stackprotector-all.bin:
-       $(BUILD) -Werror -fstack-protector-all
-
-test-fortify-source.bin:
-       $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2
-
-test-bionic.bin:
-       $(BUILD)
-
-test-libelf.bin:
-       $(BUILD) -lelf
-
-test-glibc.bin:
-       $(BUILD)
-
-test-dwarf.bin:
-       $(BUILD) -ldw
-
-test-libelf-mmap.bin:
-       $(BUILD) -lelf
-
-test-libelf-getphdrnum.bin:
-       $(BUILD) -lelf
-
-test-libnuma.bin:
-       $(BUILD) -lnuma
-
-test-libunwind.bin:
-       $(BUILD) -lelf
-
-test-libunwind-debug-frame.bin:
-       $(BUILD) -lelf
-
-test-libaudit.bin:
-       $(BUILD) -laudit
-
-test-libslang.bin:
-       $(BUILD) -I/usr/include/slang -lslang
-
-test-gtk2.bin:
-       $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
-
-test-gtk2-infobar.bin:
-       $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
-
-grep-libs  = $(filter -l%,$(1))
-strip-libs = $(filter-out -l%,$(1))
-
-PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null)
-PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS))
-PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
-PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
-FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
-
-test-libperl.bin:
-       $(BUILD) $(FLAGS_PERL_EMBED)
-
-test-libpython.bin:
-       $(BUILD)
-
-test-libpython-version.bin:
-       $(BUILD)
-
-test-libbfd.bin:
-       $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
-
-test-liberty.bin:
-       $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
-
-test-liberty-z.bin:
-       $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz
-
-test-cplus-demangle.bin:
-       $(BUILD) -liberty
-
-test-backtrace.bin:
-       $(BUILD)
-
-test-timerfd.bin:
-       $(BUILD)
-
-test-libdw-dwarf-unwind.bin:
-       $(BUILD)
-
-test-sync-compare-and-swap.bin:
-       $(BUILD) -Werror
-
-test-compile-32.bin:
-       $(CC) -m32 -o $(OUTPUT)$@ test-compile.c
-
-test-compile-x32.bin:
-       $(CC) -mx32 -o $(OUTPUT)$@ test-compile.c
-
-test-zlib.bin:
-       $(BUILD) -lz
-
--include *.d
-
-###############################
-
-clean:
-       rm -f $(FILES) *.d
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
deleted file mode 100644 (file)
index 6d4d093..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * test-all.c: Try to build all the main testcases at once.
- *
- * A well-configured system will have all the prereqs installed, so we can speed
- * up auto-detection on such systems.
- */
-
-/*
- * Quirk: Python and Perl headers cannot be in arbitrary places, so keep
- * these 3 testcases at the top:
- */
-#define main main_test_libpython
-# include "test-libpython.c"
-#undef main
-
-#define main main_test_libpython_version
-# include "test-libpython-version.c"
-#undef main
-
-#define main main_test_libperl
-# include "test-libperl.c"
-#undef main
-
-#define main main_test_hello
-# include "test-hello.c"
-#undef main
-
-#define main main_test_libelf
-# include "test-libelf.c"
-#undef main
-
-#define main main_test_libelf_mmap
-# include "test-libelf-mmap.c"
-#undef main
-
-#define main main_test_glibc
-# include "test-glibc.c"
-#undef main
-
-#define main main_test_dwarf
-# include "test-dwarf.c"
-#undef main
-
-#define main main_test_libelf_getphdrnum
-# include "test-libelf-getphdrnum.c"
-#undef main
-
-#define main main_test_libunwind
-# include "test-libunwind.c"
-#undef main
-
-#define main main_test_libaudit
-# include "test-libaudit.c"
-#undef main
-
-#define main main_test_libslang
-# include "test-libslang.c"
-#undef main
-
-#define main main_test_gtk2
-# include "test-gtk2.c"
-#undef main
-
-#define main main_test_gtk2_infobar
-# include "test-gtk2-infobar.c"
-#undef main
-
-#define main main_test_libbfd
-# include "test-libbfd.c"
-#undef main
-
-#define main main_test_backtrace
-# include "test-backtrace.c"
-#undef main
-
-#define main main_test_libnuma
-# include "test-libnuma.c"
-#undef main
-
-#define main main_test_timerfd
-# include "test-timerfd.c"
-#undef main
-
-#define main main_test_stackprotector_all
-# include "test-stackprotector-all.c"
-#undef main
-
-#define main main_test_libdw_dwarf_unwind
-# include "test-libdw-dwarf-unwind.c"
-#undef main
-
-#define main main_test_sync_compare_and_swap
-# include "test-sync-compare-and-swap.c"
-#undef main
-
-#define main main_test_zlib
-# include "test-zlib.c"
-#undef main
-
-#define main main_test_pthread_attr_setaffinity_np
-# include "test-pthread_attr_setaffinity_np.c"
-#undef main
-
-int main(int argc, char *argv[])
-{
-       main_test_libpython();
-       main_test_libpython_version();
-       main_test_libperl();
-       main_test_hello();
-       main_test_libelf();
-       main_test_libelf_mmap();
-       main_test_glibc();
-       main_test_dwarf();
-       main_test_libelf_getphdrnum();
-       main_test_libunwind();
-       main_test_libaudit();
-       main_test_libslang();
-       main_test_gtk2(argc, argv);
-       main_test_gtk2_infobar(argc, argv);
-       main_test_libbfd();
-       main_test_backtrace();
-       main_test_libnuma();
-       main_test_timerfd();
-       main_test_stackprotector_all();
-       main_test_libdw_dwarf_unwind();
-       main_test_sync_compare_and_swap(argc, argv);
-       main_test_zlib();
-       main_test_pthread_attr_setaffinity_np();
-
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-backtrace.c b/tools/perf/config/feature-checks/test-backtrace.c
deleted file mode 100644 (file)
index 7124aa1..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <execinfo.h>
-#include <stdio.h>
-
-int main(void)
-{
-       void *backtrace_fns[10];
-       size_t entries;
-
-       entries = backtrace(backtrace_fns, 10);
-       backtrace_symbols_fd(backtrace_fns, entries, 1);
-
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-bionic.c b/tools/perf/config/feature-checks/test-bionic.c
deleted file mode 100644 (file)
index eac24e9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <android/api-level.h>
-
-int main(void)
-{
-       return __ANDROID_API__;
-}
diff --git a/tools/perf/config/feature-checks/test-compile.c b/tools/perf/config/feature-checks/test-compile.c
deleted file mode 100644 (file)
index 31dbf45..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-int main(void)
-{
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-cplus-demangle.c b/tools/perf/config/feature-checks/test-cplus-demangle.c
deleted file mode 100644 (file)
index 610c686..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-extern int printf(const char *format, ...);
-extern char *cplus_demangle(const char *, int);
-
-int main(void)
-{
-       char symbol[4096] = "FieldName__9ClassNameFd";
-       char *tmp;
-
-       tmp = cplus_demangle(symbol, 0);
-
-       printf("demangled symbol: {%s}\n", tmp);
-
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-dwarf.c b/tools/perf/config/feature-checks/test-dwarf.c
deleted file mode 100644 (file)
index 3fc1801..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <dwarf.h>
-#include <elfutils/libdw.h>
-#include <elfutils/version.h>
-
-int main(void)
-{
-       Dwarf *dbg = dwarf_begin(0, DWARF_C_READ);
-
-       return (long)dbg;
-}
diff --git a/tools/perf/config/feature-checks/test-fortify-source.c b/tools/perf/config/feature-checks/test-fortify-source.c
deleted file mode 100644 (file)
index c9f398d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <stdio.h>
-
-int main(void)
-{
-       return puts("hi");
-}
diff --git a/tools/perf/config/feature-checks/test-glibc.c b/tools/perf/config/feature-checks/test-glibc.c
deleted file mode 100644 (file)
index b082034..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <gnu/libc-version.h>
-
-int main(void)
-{
-       const char *version = gnu_get_libc_version();
-
-       return (long)version;
-}
diff --git a/tools/perf/config/feature-checks/test-gtk2-infobar.c b/tools/perf/config/feature-checks/test-gtk2-infobar.c
deleted file mode 100644 (file)
index 397b464..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma GCC diagnostic ignored "-Wstrict-prototypes"
-#include <gtk/gtk.h>
-#pragma GCC diagnostic error "-Wstrict-prototypes"
-
-int main(int argc, char *argv[])
-{
-       gtk_init(&argc, &argv);
-       gtk_info_bar_new();
-
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-gtk2.c b/tools/perf/config/feature-checks/test-gtk2.c
deleted file mode 100644 (file)
index 6bd80e5..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma GCC diagnostic ignored "-Wstrict-prototypes"
-#include <gtk/gtk.h>
-#pragma GCC diagnostic error "-Wstrict-prototypes"
-
-int main(int argc, char *argv[])
-{
-       gtk_init(&argc, &argv);
-
-        return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-hello.c b/tools/perf/config/feature-checks/test-hello.c
deleted file mode 100644 (file)
index c9f398d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <stdio.h>
-
-int main(void)
-{
-       return puts("hi");
-}
diff --git a/tools/perf/config/feature-checks/test-libaudit.c b/tools/perf/config/feature-checks/test-libaudit.c
deleted file mode 100644 (file)
index afc019f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <libaudit.h>
-
-extern int printf(const char *format, ...);
-
-int main(void)
-{
-       printf("error message: %s\n", audit_errno_to_name(0));
-
-       return audit_open();
-}
diff --git a/tools/perf/config/feature-checks/test-libbfd.c b/tools/perf/config/feature-checks/test-libbfd.c
deleted file mode 100644 (file)
index 2405990..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <bfd.h>
-
-extern int printf(const char *format, ...);
-
-int main(void)
-{
-       char symbol[4096] = "FieldName__9ClassNameFd";
-       char *tmp;
-
-       tmp = bfd_demangle(0, symbol, 0);
-
-       printf("demangled symbol: {%s}\n", tmp);
-
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c b/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c
deleted file mode 100644 (file)
index f676a3f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-
-#include <elfutils/libdwfl.h>
-
-int main(void)
-{
-       /*
-        * This function is guarded via: __nonnull_attribute__ (1, 2).
-        * Passing '1' as arguments value. This code is never executed,
-        * only compiled.
-        */
-       dwfl_thread_getframes((void *) 1, (void *) 1, NULL);
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c b/tools/perf/config/feature-checks/test-libelf-getphdrnum.c
deleted file mode 100644 (file)
index d710459..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <libelf.h>
-
-int main(void)
-{
-       size_t dst;
-
-       return elf_getphdrnum(0, &dst);
-}
diff --git a/tools/perf/config/feature-checks/test-libelf-mmap.c b/tools/perf/config/feature-checks/test-libelf-mmap.c
deleted file mode 100644 (file)
index 564427d..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <libelf.h>
-
-int main(void)
-{
-       Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0);
-
-       return (long)elf;
-}
diff --git a/tools/perf/config/feature-checks/test-libelf.c b/tools/perf/config/feature-checks/test-libelf.c
deleted file mode 100644 (file)
index 08db322..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <libelf.h>
-
-int main(void)
-{
-       Elf *elf = elf_begin(0, ELF_C_READ, 0);
-
-       return (long)elf;
-}
diff --git a/tools/perf/config/feature-checks/test-libnuma.c b/tools/perf/config/feature-checks/test-libnuma.c
deleted file mode 100644 (file)
index 4763d9c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <numa.h>
-#include <numaif.h>
-
-int main(void)
-{
-       numa_available();
-
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-libperl.c b/tools/perf/config/feature-checks/test-libperl.c
deleted file mode 100644 (file)
index 8871f6a..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <EXTERN.h>
-#include <perl.h>
-
-int main(void)
-{
-       perl_alloc();
-
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-libpython-version.c b/tools/perf/config/feature-checks/test-libpython-version.c
deleted file mode 100644 (file)
index facea12..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <Python.h>
-
-#if PY_VERSION_HEX >= 0x03000000
-       #error
-#endif
-
-int main(void)
-{
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-libpython.c b/tools/perf/config/feature-checks/test-libpython.c
deleted file mode 100644 (file)
index b24b28a..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <Python.h>
-
-int main(void)
-{
-       Py_Initialize();
-
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-libslang.c b/tools/perf/config/feature-checks/test-libslang.c
deleted file mode 100644 (file)
index 22ff22e..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <slang.h>
-
-int main(void)
-{
-       return SLsmg_init_smg();
-}
diff --git a/tools/perf/config/feature-checks/test-libunwind-debug-frame.c b/tools/perf/config/feature-checks/test-libunwind-debug-frame.c
deleted file mode 100644 (file)
index 0ef8087..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <libunwind.h>
-#include <stdlib.h>
-
-extern int
-UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
-                                unw_word_t ip, unw_word_t segbase,
-                                const char *obj_name, unw_word_t start,
-                                unw_word_t end);
-
-#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
-
-int main(void)
-{
-       dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-libunwind.c b/tools/perf/config/feature-checks/test-libunwind.c
deleted file mode 100644 (file)
index 43b9369..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <libunwind.h>
-#include <stdlib.h>
-
-extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
-                                      unw_word_t ip,
-                                      unw_dyn_info_t *di,
-                                      unw_proc_info_t *pi,
-                                      int need_unwind_info, void *arg);
-
-
-#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
-
-static unw_accessors_t accessors;
-
-int main(void)
-{
-       unw_addr_space_t addr_space;
-
-       addr_space = unw_create_addr_space(&accessors, 0);
-       if (addr_space)
-               return 0;
-
-       unw_init_remote(NULL, addr_space, NULL);
-       dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
-
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c b/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c
deleted file mode 100644 (file)
index 2b81b72..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdint.h>
-#include <pthread.h>
-
-int main(void)
-{
-       int ret = 0;
-       pthread_attr_t thread_attr;
-       cpu_set_t cs;
-
-       pthread_attr_init(&thread_attr);
-       /* don't care abt exact args, just the API itself in libpthread */
-       ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cs), &cs);
-
-       return ret;
-}
diff --git a/tools/perf/config/feature-checks/test-stackprotector-all.c b/tools/perf/config/feature-checks/test-stackprotector-all.c
deleted file mode 100644 (file)
index c9f398d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <stdio.h>
-
-int main(void)
-{
-       return puts("hi");
-}
diff --git a/tools/perf/config/feature-checks/test-sync-compare-and-swap.c b/tools/perf/config/feature-checks/test-sync-compare-and-swap.c
deleted file mode 100644 (file)
index c34d4ca..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <stdint.h>
-
-volatile uint64_t x;
-
-int main(int argc, char *argv[])
-{
-       uint64_t old, new = argc;
-
-       argv = argv;
-       do {
-               old = __sync_val_compare_and_swap(&x, 0, 0);
-       } while (!__sync_bool_compare_and_swap(&x, old, new));
-       return old == new;
-}
diff --git a/tools/perf/config/feature-checks/test-timerfd.c b/tools/perf/config/feature-checks/test-timerfd.c
deleted file mode 100644 (file)
index 8c5c083..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * test for timerfd functions used by perf-kvm-stat-live
- */
-#include <sys/timerfd.h>
-
-int main(void)
-{
-       struct itimerspec new_value;
-
-       int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
-       if (fd < 0)
-               return 1;
-
-       if (timerfd_settime(fd, 0, &new_value, NULL) != 0)
-               return 1;
-
-       return 0;
-}
diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/perf/config/feature-checks/test-zlib.c
deleted file mode 100644 (file)
index e111fff..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <zlib.h>
-
-int main(void)
-{
-       z_stream zs;
-
-       inflateInit(&zs);
-       return 0;
-}
index 7076a62d0ff72c094ca0bb2e1eae7308aaaf948f..c16ce833079c0a307642f2ae0e75f9c0d577c4d8 100644 (file)
@@ -175,6 +175,5 @@ _ge-abspath = $(if $(is-executable),$(1))
 define get-executable-or-default
 $(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2)))
 endef
-_ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2)))
-_gea_warn = $(warning The path '$(1)' is not executable.)
+_ge_attempt = $(if $(get-executable),$(get-executable),$(call _gea_err,$(2)))
 _gea_err  = $(if $(1),$(error Please set '$(1)' appropriately))
index 33569847fdcc409a28af4b6d1b4c87b07b7722ab..3ba80b2359cc8c03d51b86b38713cb9f3226f43b 100644 (file)
@@ -47,8 +47,16 @@ __my_reassemble_comp_words_by_ref()
        done
 }
 
-type _get_comp_words_by_ref &>/dev/null ||
-_get_comp_words_by_ref()
+# Define preload_get_comp_words_by_ref="false", if the function
+# __perf_get_comp_words_by_ref() is required instead.
+preload_get_comp_words_by_ref="true"
+
+if [ $preload_get_comp_words_by_ref = "true" ]; then
+       type _get_comp_words_by_ref &>/dev/null ||
+       preload_get_comp_words_by_ref="false"
+fi
+[ $preload_get_comp_words_by_ref = "true" ] ||
+__perf_get_comp_words_by_ref()
 {
        local exclude cur_ words_ cword_
        if [ "$1" = "-n" ]; then
@@ -76,8 +84,16 @@ _get_comp_words_by_ref()
        done
 }
 
-type __ltrim_colon_completions &>/dev/null ||
-__ltrim_colon_completions()
+# Define preload__ltrim_colon_completions="false", if the function
+# __perf__ltrim_colon_completions() is required instead.
+preload__ltrim_colon_completions="true"
+
+if [ $preload__ltrim_colon_completions = "true" ]; then
+       type __ltrim_colon_completions &>/dev/null ||
+       preload__ltrim_colon_completions="false"
+fi
+[ $preload__ltrim_colon_completions = "true" ] ||
+__perf__ltrim_colon_completions()
 {
        if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
                # Remove colon-word prefix from COMPREPLY items
@@ -97,7 +113,32 @@ __perfcomp ()
 __perfcomp_colon ()
 {
        __perfcomp "$1" "$2"
-       __ltrim_colon_completions $cur
+       if [ $preload__ltrim_colon_completions = "true" ]; then
+               __ltrim_colon_completions $cur
+       else
+               __perf__ltrim_colon_completions $cur
+       fi
+}
+
+__perf_prev_skip_opts ()
+{
+       local i cmd_ cmds_
+
+       let i=cword-1
+       cmds_=$($cmd $1 --list-cmds)
+       prev_skip_opts=()
+       while [ $i -ge 0 ]; do
+               if [[ ${words[i]} == $1 ]]; then
+                       return
+               fi
+               for cmd_ in $cmds_; do
+                       if [[ ${words[i]} == $cmd_ ]]; then
+                               prev_skip_opts=${words[i]}
+                               return
+                       fi
+               done
+               ((i--))
+       done
 }
 
 __perf_main ()
@@ -107,29 +148,36 @@ __perf_main ()
        cmd=${words[0]}
        COMPREPLY=()
 
+       # Skip options backward and find the last perf command
+       __perf_prev_skip_opts
        # List perf subcommands or long options
-       if [ $cword -eq 1 ]; then
+       if [ -z $prev_skip_opts ]; then
                if [[ $cur == --* ]]; then
-                       __perfcomp '--help --version \
-                       --exec-path --html-path --paginate --no-pager \
-                       --perf-dir --work-tree --debugfs-dir' -- "$cur"
+                       cmds=$($cmd --list-opts)
                else
                        cmds=$($cmd --list-cmds)
-                       __perfcomp "$cmds" "$cur"
                fi
+               __perfcomp "$cmds" "$cur"
        # List possible events for -e option
-       elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then
+       elif [[ $prev == @("-e"|"--event") &&
+               $prev_skip_opts == @(record|stat|top) ]]; then
                evts=$($cmd list --raw-dump)
                __perfcomp_colon "$evts" "$cur"
-       # List subcommands for perf commands
-       elif [[ $prev == @(kvm|kmem|mem|lock|sched) ]]; then
-               subcmds=$($cmd $prev --list-cmds)
-               __perfcomp_colon "$subcmds" "$cur"
-       # List long option names
-       elif [[ $cur == --* ]];  then
-               subcmd=${words[1]}
-               opts=$($cmd $subcmd --list-opts)
-               __perfcomp "$opts" "$cur"
+       else
+               # List subcommands for perf commands
+               if [[ $prev_skip_opts == @(kvm|kmem|mem|lock|sched|
+                       |data|help|script|test|timechart|trace) ]]; then
+                       subcmds=$($cmd $prev_skip_opts --list-cmds)
+                       __perfcomp_colon "$subcmds" "$cur"
+               fi
+               # List long option names
+               if [[ $cur == --* ]];  then
+                       subcmd=$prev_skip_opts
+                       __perf_prev_skip_opts $subcmd
+                       subcmd=$subcmd" "$prev_skip_opts
+                       opts=$($cmd $subcmd --list-opts)
+                       __perfcomp "$opts" "$cur"
+               fi
        fi
 }
 
@@ -198,7 +246,11 @@ type perf &>/dev/null &&
 _perf()
 {
        local cur words cword prev
-       _get_comp_words_by_ref -n =: cur words cword prev
+       if [ $preload_get_comp_words_by_ref = "true" ]; then
+               _get_comp_words_by_ref -n =: cur words cword prev
+       else
+               __perf_get_comp_words_by_ref -n =: cur words cword prev
+       fi
        __perf_main
 } &&
 
index 3700a7faca6cf4df09be10ebc0b98376b10e84b6..b857fcbd00cf291f9dc7d8473e36cdadeac81987 100644 (file)
@@ -13,6 +13,7 @@
 #include "util/quote.h"
 #include "util/run-command.h"
 #include "util/parse-events.h"
+#include "util/parse-options.h"
 #include "util/debug.h"
 #include <api/fs/debugfs.h>
 #include <pthread.h>
@@ -62,6 +63,7 @@ static struct cmd_struct commands[] = {
 #endif
        { "inject",     cmd_inject,     0 },
        { "mem",        cmd_mem,        0 },
+       { "data",       cmd_data,       0 },
 };
 
 struct pager_config {
@@ -124,6 +126,23 @@ static void commit_pager_choice(void)
        }
 }
 
+struct option options[] = {
+       OPT_ARGUMENT("help", "help"),
+       OPT_ARGUMENT("version", "version"),
+       OPT_ARGUMENT("exec-path", "exec-path"),
+       OPT_ARGUMENT("html-path", "html-path"),
+       OPT_ARGUMENT("paginate", "paginate"),
+       OPT_ARGUMENT("no-pager", "no-pager"),
+       OPT_ARGUMENT("perf-dir", "perf-dir"),
+       OPT_ARGUMENT("work-tree", "work-tree"),
+       OPT_ARGUMENT("debugfs-dir", "debugfs-dir"),
+       OPT_ARGUMENT("buildid-dir", "buildid-dir"),
+       OPT_ARGUMENT("list-cmds", "list-cmds"),
+       OPT_ARGUMENT("list-opts", "list-opts"),
+       OPT_ARGUMENT("debug", "debug"),
+       OPT_END()
+};
+
 static int handle_options(const char ***argv, int *argc, int *envchanged)
 {
        int handled = 0;
@@ -222,6 +241,16 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
                                struct cmd_struct *p = commands+i;
                                printf("%s ", p->cmd);
                        }
+                       putchar('\n');
+                       exit(0);
+               } else if (!strcmp(cmd, "--list-opts")) {
+                       unsigned int i;
+
+                       for (i = 0; i < ARRAY_SIZE(options)-1; i++) {
+                               struct option *p = options+i;
+                               printf("--%s ", p->long_name);
+                       }
+                       putchar('\n');
                        exit(0);
                } else if (!strcmp(cmd, "--debug")) {
                        if (*argc < 2) {
index 1dabb855349978de385f45690499d83f86e10580..e14bb637255cc351ac40850a148eba1461d55cd0 100644 (file)
@@ -29,7 +29,7 @@ static inline unsigned long long rdclock(void)
        return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
 }
 
-#define MAX_NR_CPUS                    256
+#define MAX_NR_CPUS                    1024
 
 extern const char *input_name;
 extern bool perf_host, perf_guest;
@@ -53,6 +53,7 @@ struct record_opts {
        bool         sample_time;
        bool         period;
        bool         sample_intr_regs;
+       bool         running_time;
        unsigned int freq;
        unsigned int mmap_pages;
        unsigned int user_freq;
@@ -61,6 +62,8 @@ struct record_opts {
        u64          user_interval;
        bool         sample_transaction;
        unsigned     initial_delay;
+       bool         use_clockid;
+       clockid_t    clockid;
 };
 
 struct option;
diff --git a/tools/perf/scripts/Build b/tools/perf/scripts/Build
new file mode 100644 (file)
index 0000000..41efd7e
--- /dev/null
@@ -0,0 +1,2 @@
+libperf-$(CONFIG_LIBPERL)   += perl/Perf-Trace-Util/
+libperf-$(CONFIG_LIBPYTHON) += python/Perf-Trace-Util/
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Build b/tools/perf/scripts/perl/Perf-Trace-Util/Build
new file mode 100644 (file)
index 0000000..928e110
--- /dev/null
@@ -0,0 +1,3 @@
+libperf-y += Context.o
+
+CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Build b/tools/perf/scripts/python/Perf-Trace-Util/Build
new file mode 100644 (file)
index 0000000..aefc15c
--- /dev/null
@@ -0,0 +1,3 @@
+libperf-y += Context.o
+
+CFLAGS_Context.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
new file mode 100644 (file)
index 0000000..6a8801b
--- /dev/null
@@ -0,0 +1,43 @@
+perf-y += builtin-test.o
+perf-y += parse-events.o
+perf-y += dso-data.o
+perf-y += attr.o
+perf-y += vmlinux-kallsyms.o
+perf-y += open-syscall.o
+perf-y += open-syscall-all-cpus.o
+perf-y += open-syscall-tp-fields.o
+perf-y += mmap-basic.o
+perf-y += perf-record.o
+perf-y += rdpmc.o
+perf-y += evsel-roundtrip-name.o
+perf-y += evsel-tp-sched.o
+perf-y += fdarray.o
+perf-y += pmu.o
+perf-y += hists_common.o
+perf-y += hists_link.o
+perf-y += hists_filter.o
+perf-y += hists_output.o
+perf-y += hists_cumulate.o
+perf-y += python-use.o
+perf-y += bp_signal.o
+perf-y += bp_signal_overflow.o
+perf-y += task-exit.o
+perf-y += sw-clock.o
+perf-y += mmap-thread-lookup.o
+perf-y += thread-mg-share.o
+perf-y += switch-tracking.o
+perf-y += keep-tracking.o
+perf-y += code-reading.o
+perf-y += sample-parsing.o
+perf-y += parse-no-sample-id-all.o
+perf-y += kmod-path.o
+
+perf-$(CONFIG_X86) += perf-time-to-tsc.o
+
+ifeq ($(ARCH),$(filter $(ARCH),x86 arm))
+perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
+endif
+
+CFLAGS_attr.o         += -DBINDIR="BUILD_STR($(bindir_SQ))" -DPYTHON="BUILD_STR($(PYTHON_WORD))"
+CFLAGS_python-use.o   += -DPYTHONPATH="BUILD_STR($(OUTPUT)python)" -DPYTHON="BUILD_STR($(PYTHON_WORD))"
+CFLAGS_dwarf-unwind.o += -fno-optimize-sibling-calls
index d3095dafed36d23d4e5c8bf1357eff447c187894..7e6d74946e0426c015918203da976d58e8ff4626 100644 (file)
@@ -5,7 +5,7 @@ group_fd=-1
 flags=0|8
 cpu=*
 type=0|1
-size=104
+size=112
 config=0
 sample_period=4000
 sample_type=263
index 872ed7e24c7c5e7bd3f2f7d0da3f42302ef8aae6..f4cf148f14cbd0938075a13e41f08e6f99a11a8e 100644 (file)
@@ -5,7 +5,7 @@ group_fd=-1
 flags=0|8
 cpu=*
 type=0
-size=104
+size=112
 config=0
 sample_period=0
 sample_type=0
index 4b7d9ab0f0492867fa0154ce6da3d6418034cad1..4f409816711249a540c77eb4136ec7d24e94991c 100644 (file)
@@ -166,6 +166,10 @@ static struct test {
                .desc = "Add fd to a fdarray, making it autogrow",
                .func = test__fdarray__add,
        },
+       {
+               .desc = "Test kmod_path__parse function",
+               .func = test__kmod_path__parse,
+       },
        {
                .func = NULL,
        },
@@ -291,7 +295,7 @@ static int perf_test__list(int argc, const char **argv)
 
 int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
 {
-       const char * const test_usage[] = {
+       const char *test_usage[] = {
        "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
        NULL,
        };
@@ -302,13 +306,14 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
                    "be more verbose (show symbol address, etc)"),
        OPT_END()
        };
+       const char * const test_subcommands[] = { "list", NULL };
        struct intlist *skiplist = NULL;
         int ret = hists__init();
 
         if (ret < 0)
                 return ret;
 
-       argc = parse_options(argc, argv, test_options, test_usage, 0);
+       argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0);
        if (argc >= 1 && !strcmp(argv[0], "list"))
                return perf_test__list(argc, argv);
 
index caaf37f079b1c60fb987ca98445b12159135b3d5..513e5febbe5a5016ed5d9a2564bea1e5bc92e4e8 100644 (file)
@@ -112,6 +112,9 @@ int test__dso_data(void)
 
        dso = dso__new((const char *)file);
 
+       TEST_ASSERT_VAL("Failed to access to dso",
+                       dso__data_fd(dso, &machine) >= 0);
+
        /* Basic 10 bytes tests. */
        for (i = 0; i < ARRAY_SIZE(offsets); i++) {
                struct test_data_offset *data = &offsets[i];
@@ -243,8 +246,8 @@ int test__dso_data_cache(void)
        limit = nr * 4;
        TEST_ASSERT_VAL("failed to set file limit", !set_fd_limit(limit));
 
-       /* and this is now our dso open FDs limit + 1 extra */
-       dso_cnt = limit / 2 + 1;
+       /* and this is now our dso open FDs limit */
+       dso_cnt = limit / 2;
        TEST_ASSERT_VAL("failed to create dsos\n",
                !dsos__create(dso_cnt, TEST_FILE_SIZE));
 
@@ -252,13 +255,13 @@ int test__dso_data_cache(void)
                struct dso *dso = dsos[i];
 
                /*
-                * Open dsos via dso__data_fd or dso__data_read_offset.
-                * Both opens the data file and keep it open.
+                * Open dsos via dso__data_fd(), it opens the data
+                * file and keep it open (unless open file limit).
                 */
+               fd = dso__data_fd(dso, &machine);
+               TEST_ASSERT_VAL("failed to get fd", fd > 0);
+
                if (i % 2) {
-                       fd = dso__data_fd(dso, &machine);
-                       TEST_ASSERT_VAL("failed to get fd", fd > 0);
-               } else {
                        #define BUFSIZE 10
                        u8 buf[BUFSIZE];
                        ssize_t n;
@@ -268,7 +271,10 @@ int test__dso_data_cache(void)
                }
        }
 
-       /* open +1 dso over the allowed limit */
+       /* verify the first one is already open */
+       TEST_ASSERT_VAL("dsos[0] is not open", dsos[0]->data.fd != -1);
+
+       /* open +1 dso to reach the allowed limit */
        fd = dso__data_fd(dsos[i], &machine);
        TEST_ASSERT_VAL("failed to get fd", fd > 0);
 
diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c
new file mode 100644 (file)
index 0000000..e8d7cbb
--- /dev/null
@@ -0,0 +1,73 @@
+#include <stdbool.h>
+#include "tests.h"
+#include "dso.h"
+#include "debug.h"
+
+static int test(const char *path, bool alloc_name, bool alloc_ext,
+               bool kmod, bool comp, const char *name, const char *ext)
+{
+       struct kmod_path m;
+
+       memset(&m, 0x0, sizeof(m));
+
+       TEST_ASSERT_VAL("kmod_path__parse",
+                       !__kmod_path__parse(&m, path, alloc_name, alloc_ext));
+
+       pr_debug("%s - alloc name %d, alloc ext %d, kmod %d, comp %d, name '%s', ext '%s'\n",
+                path, alloc_name, alloc_ext, m.kmod, m.comp, m.name, m.ext);
+
+       TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod);
+       TEST_ASSERT_VAL("wrong comp", m.comp == comp);
+
+       if (ext)
+               TEST_ASSERT_VAL("wrong ext", m.ext && !strcmp(ext, m.ext));
+       else
+               TEST_ASSERT_VAL("wrong ext", !m.ext);
+
+       if (name)
+               TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name));
+       else
+               TEST_ASSERT_VAL("wrong name", !m.name);
+
+       free(m.name);
+       free(m.ext);
+       return 0;
+}
+
+#define T(path, an, ae, k, c, n, e) \
+       TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e))
+
+int test__kmod_path__parse(void)
+{
+       /* path                alloc_name  alloc_ext   kmod  comp   name     ext */
+       T("/xxxx/xxxx/x-x.ko", true      , true      , true, false, "[x_x]", NULL);
+       T("/xxxx/xxxx/x-x.ko", false     , true      , true, false, NULL   , NULL);
+       T("/xxxx/xxxx/x-x.ko", true      , false     , true, false, "[x_x]", NULL);
+       T("/xxxx/xxxx/x-x.ko", false     , false     , true, false, NULL   , NULL);
+
+       /* path                alloc_name  alloc_ext   kmod  comp  name   ext */
+       T("/xxxx/xxxx/x.ko.gz", true     , true      , true, true, "[x]", "gz");
+       T("/xxxx/xxxx/x.ko.gz", false    , true      , true, true, NULL , "gz");
+       T("/xxxx/xxxx/x.ko.gz", true     , false     , true, true, "[x]", NULL);
+       T("/xxxx/xxxx/x.ko.gz", false    , false     , true, true, NULL , NULL);
+
+       /* path              alloc_name  alloc_ext  kmod   comp  name    ext */
+       T("/xxxx/xxxx/x.gz", true      , true     , false, true, "x.gz" ,"gz");
+       T("/xxxx/xxxx/x.gz", false     , true     , false, true, NULL   ,"gz");
+       T("/xxxx/xxxx/x.gz", true      , false    , false, true, "x.gz" , NULL);
+       T("/xxxx/xxxx/x.gz", false     , false    , false, true, NULL   , NULL);
+
+       /* path   alloc_name  alloc_ext  kmod   comp  name     ext */
+       T("x.gz", true      , true     , false, true, "x.gz", "gz");
+       T("x.gz", false     , true     , false, true, NULL  , "gz");
+       T("x.gz", true      , false    , false, true, "x.gz", NULL);
+       T("x.gz", false     , false    , false, true, NULL  , NULL);
+
+       /* path      alloc_name  alloc_ext  kmod  comp  name  ext */
+       T("x.ko.gz", true      , true     , true, true, "[x]", "gz");
+       T("x.ko.gz", false     , true     , true, true, NULL , "gz");
+       T("x.ko.gz", true      , false    , true, true, "[x]", NULL);
+       T("x.ko.gz", false     , false    , true, true, NULL , NULL);
+
+       return 0;
+}
index 75709d2b17b477b9320c0d9f69e1fc31e0e5579e..bff85324f799bd1eeba79413ebf1433faac0a2e1 100644 (file)
@@ -5,7 +5,7 @@ include config/Makefile.arch
 
 # FIXME looks like x86 is the only arch running tests ;-)
 # we need some IS_(32/64) flag to make this generic
-ifeq ($(IS_X86_64),1)
+ifeq ($(ARCH)$(IS_64_BIT), x861)
 lib = lib64
 else
 lib = lib
index 8fa82d1700c725f13519ef24ca4a8fbe8b235ea3..3ec885c48f8fbcc77bdeaf0891fa54a2aa3935bc 100644 (file)
@@ -29,7 +29,12 @@ int test__open_syscall_event_on_all_cpus(void)
 
        evsel = perf_evsel__newtp("syscalls", "sys_enter_open");
        if (evsel == NULL) {
-               pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
+               if (tracefs_configured())
+                       pr_debug("is tracefs mounted on /sys/kernel/tracing?\n");
+               else if (debugfs_configured())
+                       pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
+               else
+                       pr_debug("Neither tracefs or debugfs is enabled in this kernel\n");
                goto out_thread_map_delete;
        }
 
index a33b2daae40f5239daa299a9a5335de26b39b420..07aa319bf334f37cc63d5c17efacce2faca54676 100644 (file)
@@ -18,7 +18,12 @@ int test__open_syscall_event(void)
 
        evsel = perf_evsel__newtp("syscalls", "sys_enter_open");
        if (evsel == NULL) {
-               pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
+               if (tracefs_configured())
+                       pr_debug("is tracefs mounted on /sys/kernel/tracing?\n");
+               else if (debugfs_configured())
+                       pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
+               else
+                       pr_debug("Neither tracefs or debugfs is enabled in this kernel\n");
                goto out_thread_map_delete;
        }
 
index 1cdab0ce00e2e4b291750a4dbaeef0229a599733..3de744961739c2c1502e0c0367c357b2f39c90a6 100644 (file)
@@ -3,6 +3,7 @@
 #include "evsel.h"
 #include "evlist.h"
 #include <api/fs/fs.h>
+#include <api/fs/tracefs.h>
 #include <api/fs/debugfs.h>
 #include "tests.h"
 #include "debug.h"
@@ -294,6 +295,36 @@ static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
        return test__checkevent_genhw(evlist);
 }
 
+static int test__checkevent_exclude_idle_modifier(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel = perf_evlist__first(evlist);
+
+       TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle);
+       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
+       TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+       TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+       TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+       TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+
+       return test__checkevent_symbolic_name(evlist);
+}
+
+static int test__checkevent_exclude_idle_modifier_1(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel = perf_evlist__first(evlist);
+
+       TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle);
+       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
+       TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+       TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+       TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+       TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+
+       return test__checkevent_symbolic_name(evlist);
+}
+
 static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel = perf_evlist__first(evlist);
@@ -1192,11 +1223,19 @@ static int count_tracepoints(void)
 {
        char events_path[PATH_MAX];
        struct dirent *events_ent;
+       const char *mountpoint;
        DIR *events_dir;
        int cnt = 0;
 
-       scnprintf(events_path, PATH_MAX, "%s/tracing/events",
-                 debugfs_find_mountpoint());
+       mountpoint = tracefs_find_mountpoint();
+       if (mountpoint) {
+               scnprintf(events_path, PATH_MAX, "%s/events",
+                         mountpoint);
+       } else {
+               mountpoint = debugfs_find_mountpoint();
+               scnprintf(events_path, PATH_MAX, "%s/tracing/events",
+                         mountpoint);
+       }
 
        events_dir = opendir(events_path);
 
@@ -1485,6 +1524,16 @@ static struct evlist_test test__events[] = {
                .id    = 100,
        },
 #endif
+       {
+               .name  = "instructions:I",
+               .check = test__checkevent_exclude_idle_modifier,
+               .id    = 45,
+       },
+       {
+               .name  = "instructions:kIG",
+               .check = test__checkevent_exclude_idle_modifier_1,
+               .id    = 46,
+       },
 };
 
 static struct evlist_test test__events_pmu[] = {
index 00e776a87a9c76e3821953fcd203c1df59189e25..52758a33f64c5679bb39a2a545320d9a3a44d303 100644 (file)
@@ -51,6 +51,7 @@ int test__hists_cumulate(void);
 int test__switch_tracking(void);
 int test__fdarray__filter(void);
 int test__fdarray__add(void);
+int test__kmod_path__parse(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/ui/Build b/tools/perf/ui/Build
new file mode 100644 (file)
index 0000000..0a73538
--- /dev/null
@@ -0,0 +1,14 @@
+libperf-y += setup.o
+libperf-y += helpline.o
+libperf-y += progress.o
+libperf-y += util.o
+libperf-y += hist.o
+libperf-y += stdio/hist.o
+
+CFLAGS_setup.o += -DLIBDIR="BUILD_STR($(LIBDIR))"
+
+libperf-$(CONFIG_SLANG) += browser.o
+libperf-$(CONFIG_SLANG) += browsers/
+libperf-$(CONFIG_SLANG) += tui/
+
+CFLAGS_browser.o += -DENABLE_SLFUTURE_CONST
diff --git a/tools/perf/ui/browsers/Build b/tools/perf/ui/browsers/Build
new file mode 100644 (file)
index 0000000..de223f5
--- /dev/null
@@ -0,0 +1,10 @@
+libperf-y += annotate.o
+libperf-y += hists.o
+libperf-y += map.o
+libperf-y += scripts.o
+libperf-y += header.o
+
+CFLAGS_annotate.o += -DENABLE_SLFUTURE_CONST
+CFLAGS_hists.o    += -DENABLE_SLFUTURE_CONST
+CFLAGS_map.o      += -DENABLE_SLFUTURE_CONST
+CFLAGS_scripts.o  += -DENABLE_SLFUTURE_CONST
index 9d32e3c0cfeedfe4cc60f62babad3fd3e451bf3c..e5250eb2dd57866b1051736767dbe598bb4c78d2 100644 (file)
@@ -829,10 +829,16 @@ out:
        return key;
 }
 
+int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
+                            struct hist_browser_timer *hbt)
+{
+       return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt);
+}
+
 int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
                             struct hist_browser_timer *hbt)
 {
-       return symbol__tui_annotate(he->ms.sym, he->ms.map, evsel, hbt);
+       return map_symbol__tui_annotate(&he->ms, evsel, hbt);
 }
 
 static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
index 788506eef5671da5e64016063569b79d4e060d97..995b7a8596b1420e9764f08f18326d319f2a0a31 100644 (file)
@@ -48,6 +48,24 @@ static bool hist_browser__has_filter(struct hist_browser *hb)
        return hists__has_filter(hb->hists) || hb->min_pcnt;
 }
 
+static int hist_browser__get_folding(struct hist_browser *browser)
+{
+       struct rb_node *nd;
+       struct hists *hists = browser->hists;
+       int unfolded_rows = 0;
+
+       for (nd = rb_first(&hists->entries);
+            (nd = hists__filter_entries(nd, browser->min_pcnt)) != NULL;
+            nd = rb_next(nd)) {
+               struct hist_entry *he =
+                       rb_entry(nd, struct hist_entry, rb_node);
+
+               if (he->ms.unfolded)
+                       unfolded_rows += he->nr_rows;
+       }
+       return unfolded_rows;
+}
+
 static u32 hist_browser__nr_entries(struct hist_browser *hb)
 {
        u32 nr_entries;
@@ -57,6 +75,7 @@ static u32 hist_browser__nr_entries(struct hist_browser *hb)
        else
                nr_entries = hb->hists->nr_entries;
 
+       hb->nr_callchain_rows = hist_browser__get_folding(hb);
        return nr_entries + hb->nr_callchain_rows;
 }
 
@@ -492,6 +511,7 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser,
 {
        int color, width;
        char folded_sign = callchain_list__folded(chain);
+       bool show_annotated = browser->show_dso && chain->ms.sym && symbol__annotation(chain->ms.sym)->src;
 
        color = HE_COLORSET_NORMAL;
        width = browser->b.width - (offset + 2);
@@ -504,7 +524,8 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser,
        ui_browser__set_color(&browser->b, color);
        hist_browser__gotorc(browser, row, 0);
        slsmg_write_nstring(" ", offset);
-       slsmg_printf("%c ", folded_sign);
+       slsmg_printf("%c", folded_sign);
+       ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' ');
        slsmg_write_nstring(str, width);
 }
 
@@ -1467,7 +1488,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                perf_hpp__set_user_width(symbol_conf.col_width_list_str);
 
        while (1) {
-               const struct thread *thread = NULL;
+               struct thread *thread = NULL;
                const struct dso *dso = NULL;
                int choice = 0,
                    annotate = -2, zoom_dso = -2, zoom_thread = -2,
@@ -1593,28 +1614,30 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                if (!sort__has_sym)
                        goto add_exit_option;
 
+               if (browser->selection == NULL)
+                       goto skip_annotation;
+
                if (sort__mode == SORT_MODE__BRANCH) {
                        bi = browser->he_selection->branch_info;
-                       if (browser->selection != NULL &&
-                           bi &&
-                           bi->from.sym != NULL &&
+
+                       if (bi == NULL)
+                               goto skip_annotation;
+
+                       if (bi->from.sym != NULL &&
                            !bi->from.map->dso->annotate_warned &&
-                               asprintf(&options[nr_options], "Annotate %s",
-                                        bi->from.sym->name) > 0)
+                           asprintf(&options[nr_options], "Annotate %s", bi->from.sym->name) > 0) {
                                annotate_f = nr_options++;
+                       }
 
-                       if (browser->selection != NULL &&
-                           bi &&
-                           bi->to.sym != NULL &&
+                       if (bi->to.sym != NULL &&
                            !bi->to.map->dso->annotate_warned &&
                            (bi->to.sym != bi->from.sym ||
                             bi->to.map->dso != bi->from.map->dso) &&
-                               asprintf(&options[nr_options], "Annotate %s",
-                                        bi->to.sym->name) > 0)
+                           asprintf(&options[nr_options], "Annotate %s", bi->to.sym->name) > 0) {
                                annotate_t = nr_options++;
+                       }
                } else {
-                       if (browser->selection != NULL &&
-                           browser->selection->sym != NULL &&
+                       if (browser->selection->sym != NULL &&
                            !browser->selection->map->dso->annotate_warned) {
                                struct annotation *notes;
 
@@ -1622,11 +1645,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 
                                if (notes->src &&
                                    asprintf(&options[nr_options], "Annotate %s",
-                                                browser->selection->sym->name) > 0)
+                                                browser->selection->sym->name) > 0) {
                                        annotate = nr_options++;
+                               }
                        }
                }
-
+skip_annotation:
                if (thread != NULL &&
                    asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
                             (browser->hists->thread_filter ? "out of" : "into"),
@@ -1682,6 +1706,7 @@ retry_popup_menu:
                if (choice == annotate || choice == annotate_t || choice == annotate_f) {
                        struct hist_entry *he;
                        struct annotation *notes;
+                       struct map_symbol ms;
                        int err;
 do_annotate:
                        if (!objdump_path && perf_session_env__lookup_objdump(env))
@@ -1691,30 +1716,21 @@ do_annotate:
                        if (he == NULL)
                                continue;
 
-                       /*
-                        * we stash the branch_info symbol + map into the
-                        * the ms so we don't have to rewrite all the annotation
-                        * code to use branch_info.
-                        * in branch mode, the ms struct is not used
-                        */
                        if (choice == annotate_f) {
-                               he->ms.sym = he->branch_info->from.sym;
-                               he->ms.map = he->branch_info->from.map;
-                       }  else if (choice == annotate_t) {
-                               he->ms.sym = he->branch_info->to.sym;
-                               he->ms.map = he->branch_info->to.map;
+                               ms.map = he->branch_info->from.map;
+                               ms.sym = he->branch_info->from.sym;
+                       } else if (choice == annotate_t) {
+                               ms.map = he->branch_info->to.map;
+                               ms.sym = he->branch_info->to.sym;
+                       } else {
+                               ms = *browser->selection;
                        }
 
-                       notes = symbol__annotation(he->ms.sym);
+                       notes = symbol__annotation(ms.sym);
                        if (!notes->src)
                                continue;
 
-                       /*
-                        * Don't let this be freed, say, by hists__decay_entry.
-                        */
-                       he->used = true;
-                       err = hist_entry__tui_annotate(he, evsel, hbt);
-                       he->used = false;
+                       err = map_symbol__tui_annotate(&ms, evsel, hbt);
                        /*
                         * offer option to annotate the other branch source or target
                         * (if they exists) when returning from annotate
@@ -1754,13 +1770,13 @@ zoom_thread:
                                pstack__remove(fstack, &browser->hists->thread_filter);
 zoom_out_thread:
                                ui_helpline__pop();
-                               browser->hists->thread_filter = NULL;
+                               thread__zput(browser->hists->thread_filter);
                                perf_hpp__set_elide(HISTC_THREAD, false);
                        } else {
                                ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
                                                   thread->comm_set ? thread__comm_str(thread) : "",
                                                   thread->tid);
-                               browser->hists->thread_filter = thread;
+                               browser->hists->thread_filter = thread__get(thread);
                                perf_hpp__set_elide(HISTC_THREAD, false);
                                pstack__push(fstack, &browser->hists->thread_filter);
                        }
diff --git a/tools/perf/ui/gtk/Build b/tools/perf/ui/gtk/Build
new file mode 100644 (file)
index 0000000..ec22e89
--- /dev/null
@@ -0,0 +1,9 @@
+CFLAGS_gtk += -fPIC $(GTK_CFLAGS)
+
+gtk-y += browser.o
+gtk-y += hists.o
+gtk-y += setup.o
+gtk-y += util.o
+gtk-y += helpline.o
+gtk-y += progress.o
+gtk-y += annotate.o
diff --git a/tools/perf/ui/tui/Build b/tools/perf/ui/tui/Build
new file mode 100644 (file)
index 0000000..9e4c6ca
--- /dev/null
@@ -0,0 +1,4 @@
+libperf-y += setup.o
+libperf-y += util.o
+libperf-y += helpline.o
+libperf-y += progress.o
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
new file mode 100644 (file)
index 0000000..797490a
--- /dev/null
@@ -0,0 +1,145 @@
+libperf-y += abspath.o
+libperf-y += alias.o
+libperf-y += annotate.o
+libperf-y += build-id.o
+libperf-y += config.o
+libperf-y += ctype.o
+libperf-y += db-export.o
+libperf-y += environment.o
+libperf-y += event.o
+libperf-y += evlist.o
+libperf-y += evsel.o
+libperf-y += exec_cmd.o
+libperf-y += find_next_bit.o
+libperf-y += help.o
+libperf-y += kallsyms.o
+libperf-y += levenshtein.o
+libperf-y += parse-options.o
+libperf-y += parse-events.o
+libperf-y += path.o
+libperf-y += rbtree.o
+libperf-y += bitmap.o
+libperf-y += hweight.o
+libperf-y += run-command.o
+libperf-y += quote.o
+libperf-y += strbuf.o
+libperf-y += string.o
+libperf-y += strlist.o
+libperf-y += strfilter.o
+libperf-y += top.o
+libperf-y += usage.o
+libperf-y += wrapper.o
+libperf-y += sigchain.o
+libperf-y += dso.o
+libperf-y += symbol.o
+libperf-y += color.o
+libperf-y += pager.o
+libperf-y += header.o
+libperf-y += callchain.o
+libperf-y += values.o
+libperf-y += debug.o
+libperf-y += machine.o
+libperf-y += map.o
+libperf-y += pstack.o
+libperf-y += session.o
+libperf-y += ordered-events.o
+libperf-y += comm.o
+libperf-y += thread.o
+libperf-y += thread_map.o
+libperf-y += trace-event-parse.o
+libperf-y += parse-events-flex.o
+libperf-y += parse-events-bison.o
+libperf-y += pmu.o
+libperf-y += pmu-flex.o
+libperf-y += pmu-bison.o
+libperf-y += trace-event-read.o
+libperf-y += trace-event-info.o
+libperf-y += trace-event-scripting.o
+libperf-y += trace-event.o
+libperf-y += svghelper.o
+libperf-y += sort.o
+libperf-y += hist.o
+libperf-y += util.o
+libperf-y += xyarray.o
+libperf-y += cpumap.o
+libperf-y += cgroup.o
+libperf-y += target.o
+libperf-y += rblist.o
+libperf-y += intlist.o
+libperf-y += vdso.o
+libperf-y += stat.o
+libperf-y += record.o
+libperf-y += srcline.o
+libperf-y += data.o
+libperf-$(CONFIG_X86) += tsc.o
+libperf-y += cloexec.o
+libperf-y += thread-stack.o
+
+libperf-$(CONFIG_LIBELF) += symbol-elf.o
+libperf-$(CONFIG_LIBELF) += probe-event.o
+
+ifndef CONFIG_LIBELF
+libperf-y += symbol-minimal.o
+endif
+
+libperf-$(CONFIG_DWARF) += probe-finder.o
+libperf-$(CONFIG_DWARF) += dwarf-aux.o
+
+libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
+libperf-$(CONFIG_LIBUNWIND)          += unwind-libunwind.o
+
+libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
+
+libperf-y += scripting-engines/
+
+libperf-$(CONFIG_PERF_REGS) += perf_regs.o
+libperf-$(CONFIG_ZLIB) += zlib.o
+libperf-$(CONFIG_LZMA) += lzma.o
+
+CFLAGS_config.o   += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
+CFLAGS_exec_cmd.o += -DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" -DPREFIX="BUILD_STR($(prefix_SQ))"
+
+$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
+       $(call rule_mkdir)
+       @$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l
+
+$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
+       $(call rule_mkdir)
+       @$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_
+
+$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
+       $(call rule_mkdir)
+       @$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
+
+$(OUTPUT)util/pmu-bison.c: util/pmu.y
+       $(call rule_mkdir)
+       @$(call echo-cmd,bison)$(BISON) -v util/pmu.y -d -o $@ -p perf_pmu_
+
+CFLAGS_parse-events-flex.o  += -w
+CFLAGS_pmu-flex.o           += -w
+CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
+CFLAGS_pmu-bison.o          += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
+
+$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
+$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
+
+CFLAGS_find_next_bit.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
+CFLAGS_rbtree.o        += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
+CFLAGS_hweight.o       += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
+CFLAGS_parse-events.o  += -Wno-redundant-decls
+
+$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE
+       $(call rule_mkdir)
+       $(call if_changed_dep,cc_o_c)
+
+$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c FORCE
+       $(call rule_mkdir)
+       $(call if_changed_dep,cc_o_c)
+
+$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c FORCE
+       $(call rule_mkdir)
+       $(call if_changed_dep,cc_o_c)
+
+$(OUTPUT)util/hweight.o: ../../lib/hweight.c FORCE
+       $(call rule_mkdir)
+       $(call if_changed_dep,cc_o_c)
index 9d9db3b296dd6b50ed27e581c0d78aab65dfec49..7f5bdfc9bc87d1d1828efeb9f57755071b378e7a 100644 (file)
@@ -1010,6 +1010,32 @@ fallback:
                        }
                        filename = symfs_filename;
                }
+       } else if (dso__needs_decompress(dso)) {
+               char tmp[PATH_MAX];
+               struct kmod_path m;
+               int fd;
+               bool ret;
+
+               if (kmod_path__parse_ext(&m, symfs_filename))
+                       goto out_free_filename;
+
+               snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX");
+
+               fd = mkstemp(tmp);
+               if (fd < 0) {
+                       free(m.ext);
+                       goto out_free_filename;
+               }
+
+               ret = decompress_to_file(m.ext, symfs_filename, fd);
+
+               free(m.ext);
+               close(fd);
+
+               if (!ret)
+                       goto out_free_filename;
+
+               strcpy(symfs_filename, tmp);
        }
 
        snprintf(command, sizeof(command),
@@ -1029,7 +1055,7 @@ fallback:
 
        file = popen(command, "r");
        if (!file)
-               goto out_free_filename;
+               goto out_remove_tmp;
 
        while (!feof(file))
                if (symbol__parse_objdump_line(sym, map, file, privsize,
@@ -1044,6 +1070,10 @@ fallback:
                delete_last_nop(sym);
 
        pclose(file);
+
+out_remove_tmp:
+       if (dso__needs_decompress(dso))
+               unlink(symfs_filename);
 out_free_filename:
        if (delete_extract)
                kcore_extract__delete(&kce);
index 0c72680a977fb8a5dcf01384720e295384bb9648..61867dff5d5aa6dea4079d060514f1bd57a63630 100644 (file)
@@ -59,11 +59,8 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
        dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
                    event->fork.ppid, event->fork.ptid);
 
-       if (thread) {
-               rb_erase(&thread->rb_node, &machine->threads);
-               machine->last_match = NULL;
-               thread__delete(thread);
-       }
+       if (thread)
+               machine__remove_thread(machine, thread);
 
        return 0;
 }
@@ -93,6 +90,35 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf)
        return raw - build_id;
 }
 
+/* asnprintf consolidates asprintf and snprintf */
+static int asnprintf(char **strp, size_t size, const char *fmt, ...)
+{
+       va_list ap;
+       int ret;
+
+       if (!strp)
+               return -EINVAL;
+
+       va_start(ap, fmt);
+       if (*strp)
+               ret = vsnprintf(*strp, size, fmt, ap);
+       else
+               ret = vasprintf(strp, fmt, ap);
+       va_end(ap);
+
+       return ret;
+}
+
+static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
+{
+       char *tmp = bf;
+       int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
+                           sbuild_id, sbuild_id + 2);
+       if (ret < 0 || (tmp && size < (unsigned int)ret))
+               return NULL;
+       return bf;
+}
+
 char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
 {
        char build_id_hex[BUILD_ID_SIZE * 2 + 1];
@@ -101,14 +127,7 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
                return NULL;
 
        build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex);
-       if (bf == NULL) {
-               if (asprintf(&bf, "%s/.build-id/%.2s/%s", buildid_dir,
-                            build_id_hex, build_id_hex + 2) < 0)
-                       return NULL;
-       } else
-               snprintf(bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
-                        build_id_hex, build_id_hex + 2);
-       return bf;
+       return build_id__filename(build_id_hex, bf, size);
 }
 
 #define dsos__for_each_with_build_id(pos, head)        \
@@ -259,52 +278,113 @@ void disable_buildid_cache(void)
        no_buildid_cache = true;
 }
 
-int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
-                         const char *name, bool is_kallsyms, bool is_vdso)
+static char *build_id_cache__dirname_from_path(const char *name,
+                                              bool is_kallsyms, bool is_vdso)
 {
-       const size_t size = PATH_MAX;
-       char *realname, *filename = zalloc(size),
-            *linkname = zalloc(size), *targetname;
-       int len, err = -1;
+       char *realname = (char *)name, *filename;
        bool slash = is_kallsyms || is_vdso;
 
-       if (is_kallsyms) {
-               if (symbol_conf.kptr_restrict) {
-                       pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
-                       err = 0;
-                       goto out_free;
-               }
-               realname = (char *) name;
-       } else
+       if (!slash) {
                realname = realpath(name, NULL);
+               if (!realname)
+                       return NULL;
+       }
 
-       if (realname == NULL || filename == NULL || linkname == NULL)
+       if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
+                    is_vdso ? DSO__NAME_VDSO : realname) < 0)
+               filename = NULL;
+
+       if (!slash)
+               free(realname);
+
+       return filename;
+}
+
+int build_id_cache__list_build_ids(const char *pathname,
+                                  struct strlist **result)
+{
+       struct strlist *list;
+       char *dir_name;
+       DIR *dir;
+       struct dirent *d;
+       int ret = 0;
+
+       list = strlist__new(true, NULL);
+       dir_name = build_id_cache__dirname_from_path(pathname, false, false);
+       if (!list || !dir_name) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       /* List up all dirents */
+       dir = opendir(dir_name);
+       if (!dir) {
+               ret = -errno;
+               goto out;
+       }
+
+       while ((d = readdir(dir)) != NULL) {
+               if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+                       continue;
+               strlist__add(list, d->d_name);
+       }
+       closedir(dir);
+
+out:
+       free(dir_name);
+       if (ret)
+               strlist__delete(list);
+       else
+               *result = list;
+
+       return ret;
+}
+
+int build_id_cache__add_s(const char *sbuild_id, const char *name,
+                         bool is_kallsyms, bool is_vdso)
+{
+       const size_t size = PATH_MAX;
+       char *realname = NULL, *filename = NULL, *dir_name = NULL,
+            *linkname = zalloc(size), *targetname, *tmp;
+       int err = -1;
+
+       if (!is_kallsyms) {
+               realname = realpath(name, NULL);
+               if (!realname)
+                       goto out_free;
+       }
+
+       dir_name = build_id_cache__dirname_from_path(name, is_kallsyms, is_vdso);
+       if (!dir_name)
                goto out_free;
 
-       len = scnprintf(filename, size, "%s%s%s",
-                      debugdir, slash ? "/" : "",
-                      is_vdso ? DSO__NAME_VDSO : realname);
-       if (mkdir_p(filename, 0755))
+       if (mkdir_p(dir_name, 0755))
                goto out_free;
 
-       snprintf(filename + len, size - len, "/%s", sbuild_id);
+       if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) {
+               filename = NULL;
+               goto out_free;
+       }
 
        if (access(filename, F_OK)) {
                if (is_kallsyms) {
                         if (copyfile("/proc/kallsyms", filename))
                                goto out_free;
-               } else if (link(realname, filename) && copyfile(name, filename))
+               } else if (link(realname, filename) && errno != EEXIST &&
+                               copyfile(name, filename))
                        goto out_free;
        }
 
-       len = scnprintf(linkname, size, "%s/.build-id/%.2s",
-                      debugdir, sbuild_id);
+       if (!build_id__filename(sbuild_id, linkname, size))
+               goto out_free;
+       tmp = strrchr(linkname, '/');
+       *tmp = '\0';
 
        if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
                goto out_free;
 
-       snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
-       targetname = filename + strlen(debugdir) - 5;
+       *tmp = '/';
+       targetname = filename + strlen(buildid_dir) - 5;
        memcpy(targetname, "../..", 5);
 
        if (symlink(targetname, linkname) == 0)
@@ -313,34 +393,46 @@ out_free:
        if (!is_kallsyms)
                free(realname);
        free(filename);
+       free(dir_name);
        free(linkname);
        return err;
 }
 
 static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
-                                const char *name, const char *debugdir,
-                                bool is_kallsyms, bool is_vdso)
+                                const char *name, bool is_kallsyms,
+                                bool is_vdso)
 {
        char sbuild_id[BUILD_ID_SIZE * 2 + 1];
 
        build_id__sprintf(build_id, build_id_size, sbuild_id);
 
-       return build_id_cache__add_s(sbuild_id, debugdir, name,
-                                    is_kallsyms, is_vdso);
+       return build_id_cache__add_s(sbuild_id, name, is_kallsyms, is_vdso);
+}
+
+bool build_id_cache__cached(const char *sbuild_id)
+{
+       bool ret = false;
+       char *filename = build_id__filename(sbuild_id, NULL, 0);
+
+       if (filename && !access(filename, F_OK))
+               ret = true;
+       free(filename);
+
+       return ret;
 }
 
-int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
+int build_id_cache__remove_s(const char *sbuild_id)
 {
        const size_t size = PATH_MAX;
        char *filename = zalloc(size),
-            *linkname = zalloc(size);
+            *linkname = zalloc(size), *tmp;
        int err = -1;
 
        if (filename == NULL || linkname == NULL)
                goto out_free;
 
-       snprintf(linkname, size, "%s/.build-id/%.2s/%s",
-                debugdir, sbuild_id, sbuild_id + 2);
+       if (!build_id__filename(sbuild_id, linkname, size))
+               goto out_free;
 
        if (access(linkname, F_OK))
                goto out_free;
@@ -354,8 +446,8 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
        /*
         * Since the link is relative, we must make it absolute:
         */
-       snprintf(linkname, size, "%s/.build-id/%.2s/%s",
-                debugdir, sbuild_id, filename);
+       tmp = strrchr(linkname, '/') + 1;
+       snprintf(tmp, size - (tmp - linkname), "%s", filename);
 
        if (unlink(linkname))
                goto out_free;
@@ -367,8 +459,7 @@ out_free:
        return err;
 }
 
-static int dso__cache_build_id(struct dso *dso, struct machine *machine,
-                              const char *debugdir)
+static int dso__cache_build_id(struct dso *dso, struct machine *machine)
 {
        bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
        bool is_vdso = dso__is_vdso(dso);
@@ -381,28 +472,26 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine,
                name = nm;
        }
        return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
-                                    debugdir, is_kallsyms, is_vdso);
+                                    is_kallsyms, is_vdso);
 }
 
 static int __dsos__cache_build_ids(struct list_head *head,
-                                  struct machine *machine, const char *debugdir)
+                                  struct machine *machine)
 {
        struct dso *pos;
        int err = 0;
 
        dsos__for_each_with_build_id(pos, head)
-               if (dso__cache_build_id(pos, machine, debugdir))
+               if (dso__cache_build_id(pos, machine))
                        err = -1;
 
        return err;
 }
 
-static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
+static int machine__cache_build_ids(struct machine *machine)
 {
-       int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
-                                         debugdir);
-       ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
-                                      debugdir);
+       int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine);
+       ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine);
        return ret;
 }
 
@@ -417,11 +506,11 @@ int perf_session__cache_build_ids(struct perf_session *session)
        if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST)
                return -1;
 
-       ret = machine__cache_build_ids(&session->machines.host, buildid_dir);
+       ret = machine__cache_build_ids(&session->machines.host);
 
        for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
                struct machine *pos = rb_entry(nd, struct machine, rb_node);
-               ret |= machine__cache_build_ids(pos, buildid_dir);
+               ret |= machine__cache_build_ids(pos);
        }
        return ret ? -1 : 0;
 }
index 8236319514d582090eecc0d9e918ee1e48eb3943..85011222cc14a68f05d2b3451ef381263d293efc 100644 (file)
@@ -4,6 +4,7 @@
 #define BUILD_ID_SIZE 20
 
 #include "tool.h"
+#include "strlist.h"
 #include <linux/types.h>
 
 extern struct perf_tool build_id__mark_dso_hit_ops;
@@ -22,9 +23,12 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
 int perf_session__write_buildid_table(struct perf_session *session, int fd);
 int perf_session__cache_build_ids(struct perf_session *session);
 
-int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
+int build_id_cache__list_build_ids(const char *pathname,
+                                  struct strlist **result);
+bool build_id_cache__cached(const char *sbuild_id);
+int build_id_cache__add_s(const char *sbuild_id,
                          const char *name, bool is_kallsyms, bool is_vdso);
-int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
+int build_id_cache__remove_s(const char *sbuild_id);
 void disable_buildid_cache(void);
 
 #endif
index d04d770d90f6e29bc17d4d5d1299e76278b5ee1c..fbcca21d66ab9b6887f084b19bdff98109201612 100644 (file)
@@ -17,6 +17,7 @@
 #define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH"
 #define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
 #define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
+#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
 
 typedef int (*config_fn_t)(const char *, const char *, void *);
 extern int perf_default_config(const char *, const char *, void *);
index 14e7a123d43b3f4ab4e04a5aba7448bd5d1106cd..9f643ee770010811d83dc88897c57a17861f4317 100644 (file)
@@ -97,6 +97,14 @@ int parse_callchain_record_opt(const char *arg)
                                callchain_param.dump_size = size;
                        }
 #endif /* HAVE_DWARF_UNWIND_SUPPORT */
+               } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
+                       if (!strtok_r(NULL, ",", &saveptr)) {
+                               callchain_param.record_mode = CALLCHAIN_LBR;
+                               ret = 0;
+                       } else
+                               pr_err("callchain: No more arguments "
+                                       "needed for --call-graph lbr\n");
+                       break;
                } else {
                        pr_err("callchain: Unknown --call-graph option "
                               "value: %s\n", arg);
index c0ec1acc38e404aa599b5b6635d004ac2f0e204f..6033a0a212ca5c255434ae2cf34c7370d785d858 100644 (file)
@@ -11,6 +11,7 @@ enum perf_call_graph_mode {
        CALLCHAIN_NONE,
        CALLCHAIN_FP,
        CALLCHAIN_DWARF,
+       CALLCHAIN_LBR,
        CALLCHAIN_MAX
 };
 
index 6da965bdbc2caf8762b5018c6837422a00aac456..85b523885f9d70d3e708cb0688e4933b43a1f388 100644 (file)
@@ -7,6 +7,12 @@
 
 static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
 
+int __weak sched_getcpu(void)
+{
+       errno = ENOSYS;
+       return -1;
+}
+
 static int perf_flag_probe(void)
 {
        /* use 'safest' configuration as used in perf_evsel__fallback() */
index 94a5a7d829d5ba32efe646f9c04729ab363ac593..68888c29b04a3fe2e8a44bd5debd233f191576ab 100644 (file)
@@ -3,4 +3,10 @@
 
 unsigned long perf_event_open_cloexec_flag(void);
 
+#ifdef __GLIBC_PREREQ
+#if !__GLIBC_PREREQ(2, 6)
+extern int sched_getcpu(void) __THROW;
+#endif
+#endif
+
 #endif /* __PERF_CLOEXEC_H */
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
new file mode 100644 (file)
index 0000000..dd17c9a
--- /dev/null
@@ -0,0 +1,857 @@
+/*
+ * CTF writing support via babeltrace.
+ *
+ * Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com>
+ * Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+
+#include <linux/compiler.h>
+#include <babeltrace/ctf-writer/writer.h>
+#include <babeltrace/ctf-writer/clock.h>
+#include <babeltrace/ctf-writer/stream.h>
+#include <babeltrace/ctf-writer/event.h>
+#include <babeltrace/ctf-writer/event-types.h>
+#include <babeltrace/ctf-writer/event-fields.h>
+#include <babeltrace/ctf/events.h>
+#include <traceevent/event-parse.h>
+#include "asm/bug.h"
+#include "data-convert-bt.h"
+#include "session.h"
+#include "util.h"
+#include "debug.h"
+#include "tool.h"
+#include "evlist.h"
+#include "evsel.h"
+#include "machine.h"
+
+#define pr_N(n, fmt, ...) \
+       eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
+
+#define pr(fmt, ...)  pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
+#define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__)
+
+#define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__)
+
+struct evsel_priv {
+       struct bt_ctf_event_class *event_class;
+};
+
+struct ctf_writer {
+       /* writer primitives */
+       struct bt_ctf_writer            *writer;
+       struct bt_ctf_stream            *stream;
+       struct bt_ctf_stream_class      *stream_class;
+       struct bt_ctf_clock             *clock;
+
+       /* data types */
+       union {
+               struct {
+                       struct bt_ctf_field_type        *s64;
+                       struct bt_ctf_field_type        *u64;
+                       struct bt_ctf_field_type        *s32;
+                       struct bt_ctf_field_type        *u32;
+                       struct bt_ctf_field_type        *string;
+                       struct bt_ctf_field_type        *u64_hex;
+               };
+               struct bt_ctf_field_type *array[6];
+       } data;
+};
+
+struct convert {
+       struct perf_tool        tool;
+       struct ctf_writer       writer;
+
+       u64                     events_size;
+       u64                     events_count;
+};
+
+static int value_set(struct bt_ctf_field_type *type,
+                    struct bt_ctf_event *event,
+                    const char *name, u64 val)
+{
+       struct bt_ctf_field *field;
+       bool sign = bt_ctf_field_type_integer_get_signed(type);
+       int ret;
+
+       field = bt_ctf_field_create(type);
+       if (!field) {
+               pr_err("failed to create a field %s\n", name);
+               return -1;
+       }
+
+       if (sign) {
+               ret = bt_ctf_field_signed_integer_set_value(field, val);
+               if (ret) {
+                       pr_err("failed to set field value %s\n", name);
+                       goto err;
+               }
+       } else {
+               ret = bt_ctf_field_unsigned_integer_set_value(field, val);
+               if (ret) {
+                       pr_err("failed to set field value %s\n", name);
+                       goto err;
+               }
+       }
+
+       ret = bt_ctf_event_set_payload(event, name, field);
+       if (ret) {
+               pr_err("failed to set payload %s\n", name);
+               goto err;
+       }
+
+       pr2("  SET [%s = %" PRIu64 "]\n", name, val);
+
+err:
+       bt_ctf_field_put(field);
+       return ret;
+}
+
+#define __FUNC_VALUE_SET(_name, _val_type)                             \
+static __maybe_unused int value_set_##_name(struct ctf_writer *cw,     \
+                            struct bt_ctf_event *event,                \
+                            const char *name,                          \
+                            _val_type val)                             \
+{                                                                      \
+       struct bt_ctf_field_type *type = cw->data._name;                \
+       return value_set(type, event, name, (u64) val);                 \
+}
+
+#define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name)
+
+FUNC_VALUE_SET(s32)
+FUNC_VALUE_SET(u32)
+FUNC_VALUE_SET(s64)
+FUNC_VALUE_SET(u64)
+__FUNC_VALUE_SET(u64_hex, u64)
+
+static struct bt_ctf_field_type*
+get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
+{
+       unsigned long flags = field->flags;
+
+       if (flags & FIELD_IS_STRING)
+               return cw->data.string;
+
+       if (!(flags & FIELD_IS_SIGNED)) {
+               /* unsigned long are mostly pointers */
+               if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
+                       return cw->data.u64_hex;
+       }
+
+       if (flags & FIELD_IS_SIGNED) {
+               if (field->size == 8)
+                       return cw->data.s64;
+               else
+                       return cw->data.s32;
+       }
+
+       if (field->size == 8)
+               return cw->data.u64;
+       else
+               return cw->data.u32;
+}
+
+static int add_tracepoint_field_value(struct ctf_writer *cw,
+                                     struct bt_ctf_event_class *event_class,
+                                     struct bt_ctf_event *event,
+                                     struct perf_sample *sample,
+                                     struct format_field *fmtf)
+{
+       struct bt_ctf_field_type *type;
+       struct bt_ctf_field *array_field;
+       struct bt_ctf_field *field;
+       const char *name = fmtf->name;
+       void *data = sample->raw_data;
+       unsigned long long value_int;
+       unsigned long flags = fmtf->flags;
+       unsigned int n_items;
+       unsigned int i;
+       unsigned int offset;
+       unsigned int len;
+       int ret;
+
+       offset = fmtf->offset;
+       len = fmtf->size;
+       if (flags & FIELD_IS_STRING)
+               flags &= ~FIELD_IS_ARRAY;
+
+       if (flags & FIELD_IS_DYNAMIC) {
+               unsigned long long tmp_val;
+
+               tmp_val = pevent_read_number(fmtf->event->pevent,
+                               data + offset, len);
+               offset = tmp_val;
+               len = offset >> 16;
+               offset &= 0xffff;
+       }
+
+       if (flags & FIELD_IS_ARRAY) {
+
+               type = bt_ctf_event_class_get_field_by_name(
+                               event_class, name);
+               array_field = bt_ctf_field_create(type);
+               bt_ctf_field_type_put(type);
+               if (!array_field) {
+                       pr_err("Failed to create array type %s\n", name);
+                       return -1;
+               }
+
+               len = fmtf->size / fmtf->arraylen;
+               n_items = fmtf->arraylen;
+       } else {
+               n_items = 1;
+               array_field = NULL;
+       }
+
+       type = get_tracepoint_field_type(cw, fmtf);
+
+       for (i = 0; i < n_items; i++) {
+               if (!(flags & FIELD_IS_STRING))
+                       value_int = pevent_read_number(
+                                       fmtf->event->pevent,
+                                       data + offset + i * len, len);
+
+               if (flags & FIELD_IS_ARRAY)
+                       field = bt_ctf_field_array_get_field(array_field, i);
+               else
+                       field = bt_ctf_field_create(type);
+
+               if (!field) {
+                       pr_err("failed to create a field %s\n", name);
+                       return -1;
+               }
+
+               if (flags & FIELD_IS_STRING)
+                       ret = bt_ctf_field_string_set_value(field,
+                                       data + offset + i * len);
+               else if (!(flags & FIELD_IS_SIGNED))
+                       ret = bt_ctf_field_unsigned_integer_set_value(
+                                       field, value_int);
+               else
+                       ret = bt_ctf_field_signed_integer_set_value(
+                                       field, value_int);
+               if (ret) {
+                       pr_err("failed to set file value %s\n", name);
+                       goto err_put_field;
+               }
+               if (!(flags & FIELD_IS_ARRAY)) {
+                       ret = bt_ctf_event_set_payload(event, name, field);
+                       if (ret) {
+                               pr_err("failed to set payload %s\n", name);
+                               goto err_put_field;
+                       }
+               }
+               bt_ctf_field_put(field);
+       }
+       if (flags & FIELD_IS_ARRAY) {
+               ret = bt_ctf_event_set_payload(event, name, array_field);
+               if (ret) {
+                       pr_err("Failed add payload array %s\n", name);
+                       return -1;
+               }
+               bt_ctf_field_put(array_field);
+       }
+       return 0;
+
+err_put_field:
+       bt_ctf_field_put(field);
+       return -1;
+}
+
+static int add_tracepoint_fields_values(struct ctf_writer *cw,
+                                       struct bt_ctf_event_class *event_class,
+                                       struct bt_ctf_event *event,
+                                       struct format_field *fields,
+                                       struct perf_sample *sample)
+{
+       struct format_field *field;
+       int ret;
+
+       for (field = fields; field; field = field->next) {
+               ret = add_tracepoint_field_value(cw, event_class, event, sample,
+                               field);
+               if (ret)
+                       return -1;
+       }
+       return 0;
+}
+
+static int add_tracepoint_values(struct ctf_writer *cw,
+                                struct bt_ctf_event_class *event_class,
+                                struct bt_ctf_event *event,
+                                struct perf_evsel *evsel,
+                                struct perf_sample *sample)
+{
+       struct format_field *common_fields = evsel->tp_format->format.common_fields;
+       struct format_field *fields        = evsel->tp_format->format.fields;
+       int ret;
+
+       ret = add_tracepoint_fields_values(cw, event_class, event,
+                                          common_fields, sample);
+       if (!ret)
+               ret = add_tracepoint_fields_values(cw, event_class, event,
+                                                  fields, sample);
+
+       return ret;
+}
+
+static int add_generic_values(struct ctf_writer *cw,
+                             struct bt_ctf_event *event,
+                             struct perf_evsel *evsel,
+                             struct perf_sample *sample)
+{
+       u64 type = evsel->attr.sample_type;
+       int ret;
+
+       /*
+        * missing:
+        *   PERF_SAMPLE_TIME         - not needed as we have it in
+        *                              ctf event header
+        *   PERF_SAMPLE_READ         - TODO
+        *   PERF_SAMPLE_CALLCHAIN    - TODO
+        *   PERF_SAMPLE_RAW          - tracepoint fields are handled separately
+        *   PERF_SAMPLE_BRANCH_STACK - TODO
+        *   PERF_SAMPLE_REGS_USER    - TODO
+        *   PERF_SAMPLE_STACK_USER   - TODO
+        */
+
+       if (type & PERF_SAMPLE_IP) {
+               ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip);
+               if (ret)
+                       return -1;
+       }
+
+       if (type & PERF_SAMPLE_TID) {
+               ret = value_set_s32(cw, event, "perf_tid", sample->tid);
+               if (ret)
+                       return -1;
+
+               ret = value_set_s32(cw, event, "perf_pid", sample->pid);
+               if (ret)
+                       return -1;
+       }
+
+       if ((type & PERF_SAMPLE_ID) ||
+           (type & PERF_SAMPLE_IDENTIFIER)) {
+               ret = value_set_u64(cw, event, "perf_id", sample->id);
+               if (ret)
+                       return -1;
+       }
+
+       if (type & PERF_SAMPLE_STREAM_ID) {
+               ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id);
+               if (ret)
+                       return -1;
+       }
+
+       if (type & PERF_SAMPLE_CPU) {
+               ret = value_set_u32(cw, event, "perf_cpu", sample->cpu);
+               if (ret)
+                       return -1;
+       }
+
+       if (type & PERF_SAMPLE_PERIOD) {
+               ret = value_set_u64(cw, event, "perf_period", sample->period);
+               if (ret)
+                       return -1;
+       }
+
+       if (type & PERF_SAMPLE_WEIGHT) {
+               ret = value_set_u64(cw, event, "perf_weight", sample->weight);
+               if (ret)
+                       return -1;
+       }
+
+       if (type & PERF_SAMPLE_DATA_SRC) {
+               ret = value_set_u64(cw, event, "perf_data_src",
+                               sample->data_src);
+               if (ret)
+                       return -1;
+       }
+
+       if (type & PERF_SAMPLE_TRANSACTION) {
+               ret = value_set_u64(cw, event, "perf_transaction",
+                               sample->transaction);
+               if (ret)
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int process_sample_event(struct perf_tool *tool,
+                               union perf_event *_event __maybe_unused,
+                               struct perf_sample *sample,
+                               struct perf_evsel *evsel,
+                               struct machine *machine __maybe_unused)
+{
+       struct convert *c = container_of(tool, struct convert, tool);
+       struct evsel_priv *priv = evsel->priv;
+       struct ctf_writer *cw = &c->writer;
+       struct bt_ctf_event_class *event_class;
+       struct bt_ctf_event *event;
+       int ret;
+
+       if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
+               return 0;
+
+       event_class = priv->event_class;
+
+       /* update stats */
+       c->events_count++;
+       c->events_size += _event->header.size;
+
+       pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count);
+
+       event = bt_ctf_event_create(event_class);
+       if (!event) {
+               pr_err("Failed to create an CTF event\n");
+               return -1;
+       }
+
+       bt_ctf_clock_set_time(cw->clock, sample->time);
+
+       ret = add_generic_values(cw, event, evsel, sample);
+       if (ret)
+               return -1;
+
+       if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
+               ret = add_tracepoint_values(cw, event_class, event,
+                                           evsel, sample);
+               if (ret)
+                       return -1;
+       }
+
+       bt_ctf_stream_append_event(cw->stream, event);
+       bt_ctf_event_put(event);
+       return 0;
+}
+
+static int add_tracepoint_fields_types(struct ctf_writer *cw,
+                                      struct format_field *fields,
+                                      struct bt_ctf_event_class *event_class)
+{
+       struct format_field *field;
+       int ret;
+
+       for (field = fields; field; field = field->next) {
+               struct bt_ctf_field_type *type;
+               unsigned long flags = field->flags;
+
+               pr2("  field '%s'\n", field->name);
+
+               type = get_tracepoint_field_type(cw, field);
+               if (!type)
+                       return -1;
+
+               /*
+                * A string is an array of chars. For this we use the string
+                * type and don't care that it is an array. What we don't
+                * support is an array of strings.
+                */
+               if (flags & FIELD_IS_STRING)
+                       flags &= ~FIELD_IS_ARRAY;
+
+               if (flags & FIELD_IS_ARRAY)
+                       type = bt_ctf_field_type_array_create(type, field->arraylen);
+
+               ret = bt_ctf_event_class_add_field(event_class, type,
+                               field->name);
+
+               if (flags & FIELD_IS_ARRAY)
+                       bt_ctf_field_type_put(type);
+
+               if (ret) {
+                       pr_err("Failed to add field '%s\n", field->name);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+static int add_tracepoint_types(struct ctf_writer *cw,
+                               struct perf_evsel *evsel,
+                               struct bt_ctf_event_class *class)
+{
+       struct format_field *common_fields = evsel->tp_format->format.common_fields;
+       struct format_field *fields        = evsel->tp_format->format.fields;
+       int ret;
+
+       ret = add_tracepoint_fields_types(cw, common_fields, class);
+       if (!ret)
+               ret = add_tracepoint_fields_types(cw, fields, class);
+
+       return ret;
+}
+
+static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
+                            struct bt_ctf_event_class *event_class)
+{
+       u64 type = evsel->attr.sample_type;
+
+       /*
+        * missing:
+        *   PERF_SAMPLE_TIME         - not needed as we have it in
+        *                              ctf event header
+        *   PERF_SAMPLE_READ         - TODO
+        *   PERF_SAMPLE_CALLCHAIN    - TODO
+        *   PERF_SAMPLE_RAW          - tracepoint fields are handled separately
+        *   PERF_SAMPLE_BRANCH_STACK - TODO
+        *   PERF_SAMPLE_REGS_USER    - TODO
+        *   PERF_SAMPLE_STACK_USER   - TODO
+        */
+
+#define ADD_FIELD(cl, t, n)                                            \
+       do {                                                            \
+               pr2("  field '%s'\n", n);                               \
+               if (bt_ctf_event_class_add_field(cl, t, n)) {           \
+                       pr_err("Failed to add field '%s;\n", n);        \
+                       return -1;                                      \
+               }                                                       \
+       } while (0)
+
+       if (type & PERF_SAMPLE_IP)
+               ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip");
+
+       if (type & PERF_SAMPLE_TID) {
+               ADD_FIELD(event_class, cw->data.s32, "perf_tid");
+               ADD_FIELD(event_class, cw->data.s32, "perf_pid");
+       }
+
+       if ((type & PERF_SAMPLE_ID) ||
+           (type & PERF_SAMPLE_IDENTIFIER))
+               ADD_FIELD(event_class, cw->data.u64, "perf_id");
+
+       if (type & PERF_SAMPLE_STREAM_ID)
+               ADD_FIELD(event_class, cw->data.u64, "perf_stream_id");
+
+       if (type & PERF_SAMPLE_CPU)
+               ADD_FIELD(event_class, cw->data.u32, "perf_cpu");
+
+       if (type & PERF_SAMPLE_PERIOD)
+               ADD_FIELD(event_class, cw->data.u64, "perf_period");
+
+       if (type & PERF_SAMPLE_WEIGHT)
+               ADD_FIELD(event_class, cw->data.u64, "perf_weight");
+
+       if (type & PERF_SAMPLE_DATA_SRC)
+               ADD_FIELD(event_class, cw->data.u64, "perf_data_src");
+
+       if (type & PERF_SAMPLE_TRANSACTION)
+               ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
+
+#undef ADD_FIELD
+       return 0;
+}
+
+static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
+{
+       struct bt_ctf_event_class *event_class;
+       struct evsel_priv *priv;
+       const char *name = perf_evsel__name(evsel);
+       int ret;
+
+       pr("Adding event '%s' (type %d)\n", name, evsel->attr.type);
+
+       event_class = bt_ctf_event_class_create(name);
+       if (!event_class)
+               return -1;
+
+       ret = add_generic_types(cw, evsel, event_class);
+       if (ret)
+               goto err;
+
+       if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
+               ret = add_tracepoint_types(cw, evsel, event_class);
+               if (ret)
+                       goto err;
+       }
+
+       ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
+       if (ret) {
+               pr("Failed to add event class into stream.\n");
+               goto err;
+       }
+
+       priv = malloc(sizeof(*priv));
+       if (!priv)
+               goto err;
+
+       priv->event_class = event_class;
+       evsel->priv       = priv;
+       return 0;
+
+err:
+       bt_ctf_event_class_put(event_class);
+       pr_err("Failed to add event '%s'.\n", name);
+       return -1;
+}
+
+static int setup_events(struct ctf_writer *cw, struct perf_session *session)
+{
+       struct perf_evlist *evlist = session->evlist;
+       struct perf_evsel *evsel;
+       int ret;
+
+       evlist__for_each(evlist, evsel) {
+               ret = add_event(cw, evsel);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+static int ctf_writer__setup_env(struct ctf_writer *cw,
+                                struct perf_session *session)
+{
+       struct perf_header *header = &session->header;
+       struct bt_ctf_writer *writer = cw->writer;
+
+#define ADD(__n, __v)                                                  \
+do {                                                                   \
+       if (bt_ctf_writer_add_environment_field(writer, __n, __v))      \
+               return -1;                                              \
+} while (0)
+
+       ADD("host",    header->env.hostname);
+       ADD("sysname", "Linux");
+       ADD("release", header->env.os_release);
+       ADD("version", header->env.version);
+       ADD("machine", header->env.arch);
+       ADD("domain", "kernel");
+       ADD("tracer_name", "perf");
+
+#undef ADD
+       return 0;
+}
+
+static int ctf_writer__setup_clock(struct ctf_writer *cw)
+{
+       struct bt_ctf_clock *clock = cw->clock;
+
+       bt_ctf_clock_set_description(clock, "perf clock");
+
+#define SET(__n, __v)                          \
+do {                                           \
+       if (bt_ctf_clock_set_##__n(clock, __v)) \
+               return -1;                      \
+} while (0)
+
+       SET(frequency,   1000000000);
+       SET(offset_s,    0);
+       SET(offset,      0);
+       SET(precision,   10);
+       SET(is_absolute, 0);
+
+#undef SET
+       return 0;
+}
+
+static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex)
+{
+       struct bt_ctf_field_type *type;
+
+       type = bt_ctf_field_type_integer_create(size);
+       if (!type)
+               return NULL;
+
+       if (sign &&
+           bt_ctf_field_type_integer_set_signed(type, 1))
+               goto err;
+
+       if (hex &&
+           bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL))
+               goto err;
+
+       pr2("Created type: INTEGER %d-bit %ssigned %s\n",
+           size, sign ? "un" : "", hex ? "hex" : "");
+       return type;
+
+err:
+       bt_ctf_field_type_put(type);
+       return NULL;
+}
+
+static void ctf_writer__cleanup_data(struct ctf_writer *cw)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(cw->data.array); i++)
+               bt_ctf_field_type_put(cw->data.array[i]);
+}
+
+static int ctf_writer__init_data(struct ctf_writer *cw)
+{
+#define CREATE_INT_TYPE(type, size, sign, hex)         \
+do {                                                   \
+       (type) = create_int_type(size, sign, hex);      \
+       if (!(type))                                    \
+               goto err;                               \
+} while (0)
+
+       CREATE_INT_TYPE(cw->data.s64, 64, true,  false);
+       CREATE_INT_TYPE(cw->data.u64, 64, false, false);
+       CREATE_INT_TYPE(cw->data.s32, 32, true,  false);
+       CREATE_INT_TYPE(cw->data.u32, 32, false, false);
+       CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true);
+
+       cw->data.string  = bt_ctf_field_type_string_create();
+       if (cw->data.string)
+               return 0;
+
+err:
+       ctf_writer__cleanup_data(cw);
+       pr_err("Failed to create data types.\n");
+       return -1;
+}
+
+static void ctf_writer__cleanup(struct ctf_writer *cw)
+{
+       ctf_writer__cleanup_data(cw);
+
+       bt_ctf_clock_put(cw->clock);
+       bt_ctf_stream_put(cw->stream);
+       bt_ctf_stream_class_put(cw->stream_class);
+       bt_ctf_writer_put(cw->writer);
+
+       /* and NULL all the pointers */
+       memset(cw, 0, sizeof(*cw));
+}
+
+static int ctf_writer__init(struct ctf_writer *cw, const char *path)
+{
+       struct bt_ctf_writer            *writer;
+       struct bt_ctf_stream_class      *stream_class;
+       struct bt_ctf_stream            *stream;
+       struct bt_ctf_clock             *clock;
+
+       /* CTF writer */
+       writer = bt_ctf_writer_create(path);
+       if (!writer)
+               goto err;
+
+       cw->writer = writer;
+
+       /* CTF clock */
+       clock = bt_ctf_clock_create("perf_clock");
+       if (!clock) {
+               pr("Failed to create CTF clock.\n");
+               goto err_cleanup;
+       }
+
+       cw->clock = clock;
+
+       if (ctf_writer__setup_clock(cw)) {
+               pr("Failed to setup CTF clock.\n");
+               goto err_cleanup;
+       }
+
+       /* CTF stream class */
+       stream_class = bt_ctf_stream_class_create("perf_stream");
+       if (!stream_class) {
+               pr("Failed to create CTF stream class.\n");
+               goto err_cleanup;
+       }
+
+       cw->stream_class = stream_class;
+
+       /* CTF clock stream setup */
+       if (bt_ctf_stream_class_set_clock(stream_class, clock)) {
+               pr("Failed to assign CTF clock to stream class.\n");
+               goto err_cleanup;
+       }
+
+       if (ctf_writer__init_data(cw))
+               goto err_cleanup;
+
+       /* CTF stream instance */
+       stream = bt_ctf_writer_create_stream(writer, stream_class);
+       if (!stream) {
+               pr("Failed to create CTF stream.\n");
+               goto err_cleanup;
+       }
+
+       cw->stream = stream;
+
+       /* CTF clock writer setup */
+       if (bt_ctf_writer_add_clock(writer, clock)) {
+               pr("Failed to assign CTF clock to writer.\n");
+               goto err_cleanup;
+       }
+
+       return 0;
+
+err_cleanup:
+       ctf_writer__cleanup(cw);
+err:
+       pr_err("Failed to setup CTF writer.\n");
+       return -1;
+}
+
+int bt_convert__perf2ctf(const char *input, const char *path, bool force)
+{
+       struct perf_session *session;
+       struct perf_data_file file = {
+               .path = input,
+               .mode = PERF_DATA_MODE_READ,
+               .force = force,
+       };
+       struct convert c = {
+               .tool = {
+                       .sample          = process_sample_event,
+                       .mmap            = perf_event__process_mmap,
+                       .mmap2           = perf_event__process_mmap2,
+                       .comm            = perf_event__process_comm,
+                       .exit            = perf_event__process_exit,
+                       .fork            = perf_event__process_fork,
+                       .lost            = perf_event__process_lost,
+                       .tracing_data    = perf_event__process_tracing_data,
+                       .build_id        = perf_event__process_build_id,
+                       .ordered_events  = true,
+                       .ordering_requires_timestamps = true,
+               },
+       };
+       struct ctf_writer *cw = &c.writer;
+       int err = -1;
+
+       /* CTF writer */
+       if (ctf_writer__init(cw, path))
+               return -1;
+
+       /* perf.data session */
+       session = perf_session__new(&file, 0, &c.tool);
+       if (!session)
+               goto free_writer;
+
+       /* CTF writer env/clock setup  */
+       if (ctf_writer__setup_env(cw, session))
+               goto free_session;
+
+       /* CTF events setup */
+       if (setup_events(cw, session))
+               goto free_session;
+
+       err = perf_session__process_events(session);
+       if (!err)
+               err = bt_ctf_stream_flush(cw->stream);
+
+       fprintf(stderr,
+               "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
+               file.path, path);
+
+       fprintf(stderr,
+               "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n",
+               (double) c.events_size / 1024.0 / 1024.0,
+               c.events_count);
+
+       /* its all good */
+free_session:
+       perf_session__delete(session);
+
+free_writer:
+       ctf_writer__cleanup(cw);
+       return err;
+}
diff --git a/tools/perf/util/data-convert-bt.h b/tools/perf/util/data-convert-bt.h
new file mode 100644 (file)
index 0000000..4c20434
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __DATA_CONVERT_BT_H
+#define __DATA_CONVERT_BT_H
+#ifdef HAVE_LIBBABELTRACE_SUPPORT
+
+int bt_convert__perf2ctf(const char *input_name, const char *to_ctf, bool force);
+
+#endif /* HAVE_LIBBABELTRACE_SUPPORT */
+#endif /* __DATA_CONVERT_BT_H */
index c81dae3997636ff9626b25debf9fdd0cbcbf7d61..bb39a3ffc70b3951f88f9260f01836cc4e959fc9 100644 (file)
@@ -282,13 +282,13 @@ int db_export__branch_type(struct db_export *dbe, u32 branch_type,
 
 int db_export__sample(struct db_export *dbe, union perf_event *event,
                      struct perf_sample *sample, struct perf_evsel *evsel,
-                     struct thread *thread, struct addr_location *al)
+                     struct addr_location *al)
 {
+       struct thread* thread = al->thread;
        struct export_sample es = {
                .event = event,
                .sample = sample,
                .evsel = evsel,
-               .thread = thread,
                .al = al,
        };
        struct thread *main_thread;
index adbd22d6679837d8a26d4e05ef0a0ea1d62db35b..25e22fd76aca1537813b9278db205993ca45075b 100644 (file)
@@ -34,7 +34,6 @@ struct export_sample {
        union perf_event        *event;
        struct perf_sample      *sample;
        struct perf_evsel       *evsel;
-       struct thread           *thread;
        struct addr_location    *al;
        u64                     db_id;
        u64                     comm_db_id;
@@ -97,7 +96,7 @@ int db_export__branch_type(struct db_export *dbe, u32 branch_type,
                           const char *name);
 int db_export__sample(struct db_export *dbe, union perf_event *event,
                      struct perf_sample *sample, struct perf_evsel *evsel,
-                     struct thread *thread, struct addr_location *al);
+                     struct addr_location *al);
 
 int db_export__branch_types(struct db_export *dbe);
 
index ad60b2f202582c27c3d107540c1d7cca041fb1cf..2da5581ec74d35945dcdf3cb45369284a876976c 100644 (file)
@@ -20,6 +20,7 @@ int verbose;
 bool dump_trace = false, quiet = false;
 int debug_ordered_events;
 static int redirect_to_stderr;
+int debug_data_convert;
 
 static int _eprintf(int level, int var, const char *fmt, va_list args)
 {
@@ -147,6 +148,7 @@ static struct debug_variable {
        { .name = "verbose",            .ptr = &verbose },
        { .name = "ordered-events",     .ptr = &debug_ordered_events},
        { .name = "stderr",             .ptr = &redirect_to_stderr},
+       { .name = "data-convert",       .ptr = &debug_data_convert },
        { .name = NULL, }
 };
 
index be264d6f3b304933988f73fa3790e132bf6d4e2d..caac2fdc6105f7591a225f12e65b6e1ece48d342 100644 (file)
@@ -12,6 +12,7 @@
 extern int verbose;
 extern bool quiet, dump_trace;
 extern int debug_ordered_events;
+extern int debug_data_convert;
 
 #ifndef pr_fmt
 #define pr_fmt(fmt) fmt
index c2f7d3b90966a66fb5d628e933d92fb83325a582..fc0ddd5792a97f884e7ed142ad12fe87c2bfe408 100644 (file)
@@ -45,13 +45,13 @@ int dso__read_binary_type_filename(const struct dso *dso,
        case DSO_BINARY_TYPE__DEBUGLINK: {
                char *debuglink;
 
-               strncpy(filename, dso->long_name, size);
-               debuglink = filename + dso->long_name_len;
+               len = __symbol__join_symfs(filename, size, dso->long_name);
+               debuglink = filename + len;
                while (debuglink != filename && *debuglink != '/')
                        debuglink--;
                if (*debuglink == '/')
                        debuglink++;
-               ret = filename__read_debuglink(dso->long_name, debuglink,
+               ret = filename__read_debuglink(filename, debuglink,
                                               size - (debuglink - filename));
                }
                break;
@@ -147,6 +147,9 @@ static const struct {
 } compressions[] = {
 #ifdef HAVE_ZLIB_SUPPORT
        { "gz", gzip_decompress_to_file },
+#endif
+#ifdef HAVE_LZMA_SUPPORT
+       { "xz", lzma_decompress_to_file },
 #endif
        { NULL, NULL },
 };
@@ -162,32 +165,14 @@ bool is_supported_compression(const char *ext)
        return false;
 }
 
-bool is_kmodule_extension(const char *ext)
-{
-       if (strncmp(ext, "ko", 2))
-               return false;
-
-       if (ext[2] == '\0' || (ext[2] == '.' && is_supported_compression(ext+3)))
-               return true;
-
-       return false;
-}
-
-bool is_kernel_module(const char *pathname, bool *compressed)
+bool is_kernel_module(const char *pathname)
 {
-       const char *ext = strrchr(pathname, '.');
+       struct kmod_path m;
 
-       if (ext == NULL)
-               return false;
-
-       if (is_supported_compression(ext + 1)) {
-               if (compressed)
-                       *compressed = true;
-               ext -= 3;
-       } else if (compressed)
-               *compressed = false;
+       if (kmod_path__parse(&m, pathname))
+               return NULL;
 
-       return is_kmodule_extension(ext + 1);
+       return m.kmod;
 }
 
 bool decompress_to_file(const char *ext, const char *filename, int output_fd)
@@ -208,6 +193,72 @@ bool dso__needs_decompress(struct dso *dso)
                dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
 }
 
+/*
+ * Parses kernel module specified in @path and updates
+ * @m argument like:
+ *
+ *    @comp - true if @path contains supported compression suffix,
+ *            false otherwise
+ *    @kmod - true if @path contains '.ko' suffix in right position,
+ *            false otherwise
+ *    @name - if (@alloc_name && @kmod) is true, it contains strdup-ed base name
+ *            of the kernel module without suffixes, otherwise strudup-ed
+ *            base name of @path
+ *    @ext  - if (@alloc_ext && @comp) is true, it contains strdup-ed string
+ *            the compression suffix
+ *
+ * Returns 0 if there's no strdup error, -ENOMEM otherwise.
+ */
+int __kmod_path__parse(struct kmod_path *m, const char *path,
+                      bool alloc_name, bool alloc_ext)
+{
+       const char *name = strrchr(path, '/');
+       const char *ext  = strrchr(path, '.');
+
+       memset(m, 0x0, sizeof(*m));
+       name = name ? name + 1 : path;
+
+       /* No extension, just return name. */
+       if (ext == NULL) {
+               if (alloc_name) {
+                       m->name = strdup(name);
+                       return m->name ? 0 : -ENOMEM;
+               }
+               return 0;
+       }
+
+       if (is_supported_compression(ext + 1)) {
+               m->comp = true;
+               ext -= 3;
+       }
+
+       /* Check .ko extension only if there's enough name left. */
+       if (ext > name)
+               m->kmod = !strncmp(ext, ".ko", 3);
+
+       if (alloc_name) {
+               if (m->kmod) {
+                       if (asprintf(&m->name, "[%.*s]", (int) (ext - name), name) == -1)
+                               return -ENOMEM;
+               } else {
+                       if (asprintf(&m->name, "%s", name) == -1)
+                               return -ENOMEM;
+               }
+
+               strxfrchar(m->name, '-', '_');
+       }
+
+       if (alloc_ext && m->comp) {
+               m->ext = strdup(ext + 4);
+               if (!m->ext) {
+                       free((void *) m->name);
+                       return -ENOMEM;
+               }
+       }
+
+       return 0;
+}
+
 /*
  * Global list of open DSOs and the counter.
  */
@@ -240,7 +291,7 @@ static int do_open(char *name)
                if (fd >= 0)
                        return fd;
 
-               pr_debug("dso open failed, mmap: %s\n",
+               pr_debug("dso open failed: %s\n",
                         strerror_r(errno, sbuf, sizeof(sbuf)));
                if (!dso__data_open_cnt || errno != EMFILE)
                        break;
@@ -1002,21 +1053,24 @@ struct dso *dsos__find(const struct dsos *dsos, const char *name,
        return dso__find_by_longname(&dsos->root, name);
 }
 
-struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
+struct dso *dsos__addnew(struct dsos *dsos, const char *name)
 {
-       struct dso *dso = dsos__find(dsos, name, false);
+       struct dso *dso = dso__new(name);
 
-       if (!dso) {
-               dso = dso__new(name);
-               if (dso != NULL) {
-                       dsos__add(dsos, dso);
-                       dso__set_basename(dso);
-               }
+       if (dso != NULL) {
+               dsos__add(dsos, dso);
+               dso__set_basename(dso);
        }
-
        return dso;
 }
 
+struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
+{
+       struct dso *dso = dsos__find(dsos, name, false);
+
+       return dso ? dso : dsos__addnew(dsos, name);
+}
+
 size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
                               bool (skip)(struct dso *dso, int parm), int parm)
 {
@@ -1083,3 +1137,36 @@ enum dso_type dso__type(struct dso *dso, struct machine *machine)
 
        return dso__type_fd(fd);
 }
+
+int dso__strerror_load(struct dso *dso, char *buf, size_t buflen)
+{
+       int idx, errnum = dso->load_errno;
+       /*
+        * This must have a same ordering as the enum dso_load_errno.
+        */
+       static const char *dso_load__error_str[] = {
+       "Internal tools/perf/ library error",
+       "Invalid ELF file",
+       "Can not read build id",
+       "Mismatching build id",
+       "Decompression failure",
+       };
+
+       BUG_ON(buflen == 0);
+
+       if (errnum >= 0) {
+               const char *err = strerror_r(errnum, buf, buflen);
+
+               if (err != buf)
+                       scnprintf(buf, buflen, "%s", err);
+
+               return 0;
+       }
+
+       if (errnum <  __DSO_LOAD_ERRNO__START || errnum >= __DSO_LOAD_ERRNO__END)
+               return -1;
+
+       idx = errnum - __DSO_LOAD_ERRNO__START;
+       scnprintf(buf, buflen, "%s", dso_load__error_str[idx]);
+       return 0;
+}
index ced92841ff97d75f2768fae0edba8e5971c93968..e0901b4ed8de0d08b1c6ad93f20ca371b9adef5f 100644 (file)
@@ -60,6 +60,31 @@ enum dso_type {
        DSO__TYPE_X32BIT,
 };
 
+enum dso_load_errno {
+       DSO_LOAD_ERRNO__SUCCESS         = 0,
+
+       /*
+        * Choose an arbitrary negative big number not to clash with standard
+        * errno since SUS requires the errno has distinct positive values.
+        * See 'Issue 6' in the link below.
+        *
+        * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
+        */
+       __DSO_LOAD_ERRNO__START         = -10000,
+
+       DSO_LOAD_ERRNO__INTERNAL_ERROR  = __DSO_LOAD_ERRNO__START,
+
+       /* for symsrc__init() */
+       DSO_LOAD_ERRNO__INVALID_ELF,
+       DSO_LOAD_ERRNO__CANNOT_READ_BUILDID,
+       DSO_LOAD_ERRNO__MISMATCHING_BUILDID,
+
+       /* for decompress_kmodule */
+       DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE,
+
+       __DSO_LOAD_ERRNO__END,
+};
+
 #define DSO__SWAP(dso, type, val)                      \
 ({                                                     \
        type ____r = val;                               \
@@ -113,6 +138,7 @@ struct dso {
        enum dso_swap_type      needs_swap;
        enum dso_binary_type    symtab_type;
        enum dso_binary_type    binary_type;
+       enum dso_load_errno     load_errno;
        u8               adjust_symbols:1;
        u8               has_build_id:1;
        u8               has_srcline:1;
@@ -139,7 +165,8 @@ struct dso {
                u32              status_seen;
                size_t           file_size;
                struct list_head open_entry;
-               u64              frame_offset;
+               u64              debug_frame_offset;
+               u64              eh_frame_hdr_offset;
        } data;
 
        union { /* Tool specific area */
@@ -189,11 +216,24 @@ char dso__symtab_origin(const struct dso *dso);
 int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
                                   char *root_dir, char *filename, size_t size);
 bool is_supported_compression(const char *ext);
-bool is_kmodule_extension(const char *ext);
-bool is_kernel_module(const char *pathname, bool *compressed);
+bool is_kernel_module(const char *pathname);
 bool decompress_to_file(const char *ext, const char *filename, int output_fd);
 bool dso__needs_decompress(struct dso *dso);
 
+struct kmod_path {
+       char *name;
+       char *ext;
+       bool  comp;
+       bool  kmod;
+};
+
+int __kmod_path__parse(struct kmod_path *m, const char *path,
+                    bool alloc_name, bool alloc_ext);
+
+#define kmod_path__parse(__m, __p)      __kmod_path__parse(__m, __p, false, false)
+#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false)
+#define kmod_path__parse_ext(__m, __p)  __kmod_path__parse(__m, __p, false, true)
+
 /*
  * The dso__data_* external interface provides following functions:
  *   dso__data_fd
@@ -249,6 +289,7 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
                                const char *short_name, int dso_type);
 
 void dsos__add(struct dsos *dsos, struct dso *dso);
+struct dso *dsos__addnew(struct dsos *dsos, const char *name);
 struct dso *dsos__find(const struct dsos *dsos, const char *name,
                       bool cmp_short);
 struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
@@ -279,4 +320,6 @@ void dso__free_a2l(struct dso *dso);
 
 enum dso_type dso__type(struct dso *dso, struct machine *machine);
 
+int dso__strerror_load(struct dso *dso, char *buf, size_t buflen);
+
 #endif /* __PERF_DSO */
index cc66c4049e0921ea35910edcebffb89b525c2f57..c34e024020c7c58602a9459f407283faea884b20 100644 (file)
@@ -277,6 +277,21 @@ bool die_is_func_def(Dwarf_Die *dw_die)
                dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL);
 }
 
+/**
+ * die_is_func_instance - Ensure that this DIE is an instance of a subprogram
+ * @dw_die: a DIE
+ *
+ * Ensure that this DIE is an instance (which has an entry address).
+ * This returns true if @dw_die is a function instance. If not, you need to
+ * call die_walk_instances() to find actual instances.
+ **/
+bool die_is_func_instance(Dwarf_Die *dw_die)
+{
+       Dwarf_Addr tmp;
+
+       /* Actually gcc optimizes non-inline as like as inlined */
+       return !dwarf_func_inline(dw_die) && dwarf_entrypc(dw_die, &tmp) == 0;
+}
 /**
  * die_get_data_member_location - Get the data-member offset
  * @mb_die: a DIE of a member of a data structure
@@ -786,10 +801,16 @@ static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
 {
        const char *name = data;
 
-       if ((dwarf_tag(die_mem) == DW_TAG_member) &&
-           die_compare_name(die_mem, name))
-               return DIE_FIND_CB_END;
-
+       if (dwarf_tag(die_mem) == DW_TAG_member) {
+               if (die_compare_name(die_mem, name))
+                       return DIE_FIND_CB_END;
+               else if (!dwarf_diename(die_mem)) {     /* Unnamed structure */
+                       Dwarf_Die type_die, tmp_die;
+                       if (die_get_type(die_mem, &type_die) &&
+                           die_find_member(&type_die, name, &tmp_die))
+                               return DIE_FIND_CB_END;
+               }
+       }
        return DIE_FIND_CB_SIBLING;
 }
 
index b4fe90c6cb2d4413c3ab96f91a346f3f89549932..af7dbcd5f929947cfdd0b146f20ad65d45059bb8 100644 (file)
@@ -41,6 +41,9 @@ extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
 /* Ensure that this DIE is a subprogram and definition (not declaration) */
 extern bool die_is_func_def(Dwarf_Die *dw_die);
 
+/* Ensure that this DIE is an instance of a subprogram */
+extern bool die_is_func_instance(Dwarf_Die *dw_die);
+
 /* Compare diename and tname */
 extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
 
index 6c6d044e959aacf7c4c6515f2e8115d5aea391de..ff866c4d2e2f09ea4abc1650d7c413776b3bb93f 100644 (file)
@@ -49,72 +49,103 @@ static struct perf_sample synth_sample = {
        .period    = 1,
 };
 
-static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
+/*
+ * Assumes that the first 4095 bytes of /proc/pid/stat contains
+ * the comm, tgid and ppid.
+ */
+static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
+                                   pid_t *tgid, pid_t *ppid)
 {
        char filename[PATH_MAX];
-       char bf[BUFSIZ];
-       FILE *fp;
-       size_t size = 0;
-       pid_t tgid = -1;
+       char bf[4096];
+       int fd;
+       size_t size = 0, n;
+       char *nl, *name, *tgids, *ppids;
+
+       *tgid = -1;
+       *ppid = -1;
 
        snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
 
-       fp = fopen(filename, "r");
-       if (fp == NULL) {
+       fd = open(filename, O_RDONLY);
+       if (fd < 0) {
                pr_debug("couldn't open %s\n", filename);
-               return 0;
+               return -1;
        }
 
-       while (!comm[0] || (tgid < 0)) {
-               if (fgets(bf, sizeof(bf), fp) == NULL) {
-                       pr_warning("couldn't get COMM and pgid, malformed %s\n",
-                                  filename);
-                       break;
-               }
+       n = read(fd, bf, sizeof(bf) - 1);
+       close(fd);
+       if (n <= 0) {
+               pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n",
+                          pid);
+               return -1;
+       }
+       bf[n] = '\0';
 
-               if (memcmp(bf, "Name:", 5) == 0) {
-                       char *name = bf + 5;
-                       while (*name && isspace(*name))
-                               ++name;
-                       size = strlen(name) - 1;
-                       if (size >= len)
-                               size = len - 1;
-                       memcpy(comm, name, size);
-                       comm[size] = '\0';
-
-               } else if (memcmp(bf, "Tgid:", 5) == 0) {
-                       char *tgids = bf + 5;
-                       while (*tgids && isspace(*tgids))
-                               ++tgids;
-                       tgid = atoi(tgids);
-               }
+       name = strstr(bf, "Name:");
+       tgids = strstr(bf, "Tgid:");
+       ppids = strstr(bf, "PPid:");
+
+       if (name) {
+               name += 5;  /* strlen("Name:") */
+
+               while (*name && isspace(*name))
+                       ++name;
+
+               nl = strchr(name, '\n');
+               if (nl)
+                       *nl = '\0';
+
+               size = strlen(name);
+               if (size >= len)
+                       size = len - 1;
+               memcpy(comm, name, size);
+               comm[size] = '\0';
+       } else {
+               pr_debug("Name: string not found for pid %d\n", pid);
        }
 
-       fclose(fp);
+       if (tgids) {
+               tgids += 5;  /* strlen("Tgid:") */
+               *tgid = atoi(tgids);
+       } else {
+               pr_debug("Tgid: string not found for pid %d\n", pid);
+       }
 
-       return tgid;
+       if (ppids) {
+               ppids += 5;  /* strlen("PPid:") */
+               *ppid = atoi(ppids);
+       } else {
+               pr_debug("PPid: string not found for pid %d\n", pid);
+       }
+
+       return 0;
 }
 
-static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
-                                        union perf_event *event, pid_t pid,
-                                        perf_event__handler_t process,
-                                        struct machine *machine)
+static int perf_event__prepare_comm(union perf_event *event, pid_t pid,
+                                   struct machine *machine,
+                                   pid_t *tgid, pid_t *ppid)
 {
        size_t size;
-       pid_t tgid;
+
+       *ppid = -1;
 
        memset(&event->comm, 0, sizeof(event->comm));
 
-       if (machine__is_host(machine))
-               tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
-                                                sizeof(event->comm.comm));
-       else
-               tgid = machine->pid;
+       if (machine__is_host(machine)) {
+               if (perf_event__get_comm_ids(pid, event->comm.comm,
+                                            sizeof(event->comm.comm),
+                                            tgid, ppid) != 0) {
+                       return -1;
+               }
+       } else {
+               *tgid = machine->pid;
+       }
 
-       if (tgid < 0)
-               goto out;
+       if (*tgid < 0)
+               return -1;
 
-       event->comm.pid = tgid;
+       event->comm.pid = *tgid;
        event->comm.header.type = PERF_RECORD_COMM;
 
        size = strlen(event->comm.comm) + 1;
@@ -125,23 +156,45 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
                                machine->id_hdr_size);
        event->comm.tid = pid;
 
+       return 0;
+}
+
+static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
+                                        union perf_event *event, pid_t pid,
+                                        perf_event__handler_t process,
+                                        struct machine *machine)
+{
+       pid_t tgid, ppid;
+
+       if (perf_event__prepare_comm(event, pid, machine, &tgid, &ppid) != 0)
+               return -1;
+
        if (process(tool, event, &synth_sample, machine) != 0)
                return -1;
 
-out:
        return tgid;
 }
 
 static int perf_event__synthesize_fork(struct perf_tool *tool,
-                                      union perf_event *event, pid_t pid,
-                                      pid_t tgid, perf_event__handler_t process,
+                                      union perf_event *event,
+                                      pid_t pid, pid_t tgid, pid_t ppid,
+                                      perf_event__handler_t process,
                                       struct machine *machine)
 {
        memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
 
-       /* this is really a clone event but we use fork to synthesize it */
-       event->fork.ppid = tgid;
-       event->fork.ptid = tgid;
+       /*
+        * for main thread set parent to ppid from status file. For other
+        * threads set parent pid to main thread. ie., assume main thread
+        * spawns all threads in a process
+       */
+       if (tgid == pid) {
+               event->fork.ppid = ppid;
+               event->fork.ptid = ppid;
+       } else {
+               event->fork.ppid = tgid;
+               event->fork.ptid = tgid;
+       }
        event->fork.pid  = tgid;
        event->fork.tid  = pid;
        event->fork.header.type = PERF_RECORD_FORK;
@@ -333,7 +386,8 @@ static int __event__synthesize_thread(union perf_event *comm_event,
        char filename[PATH_MAX];
        DIR *tasks;
        struct dirent dirent, *next;
-       pid_t tgid;
+       pid_t tgid, ppid;
+       int rc = 0;
 
        /* special case: only send one comm event using passed in pid */
        if (!full) {
@@ -361,34 +415,38 @@ static int __event__synthesize_thread(union perf_event *comm_event,
 
        while (!readdir_r(tasks, &dirent, &next) && next) {
                char *end;
-               int rc = 0;
                pid_t _pid;
 
                _pid = strtol(dirent.d_name, &end, 10);
                if (*end)
                        continue;
 
-               tgid = perf_event__synthesize_comm(tool, comm_event, _pid,
-                                                  process, machine);
-               if (tgid == -1)
-                       return -1;
+               rc = -1;
+               if (perf_event__prepare_comm(comm_event, _pid, machine,
+                                            &tgid, &ppid) != 0)
+                       break;
 
+               if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
+                                               ppid, process, machine) < 0)
+                       break;
+               /*
+                * Send the prepared comm event
+                */
+               if (process(tool, comm_event, &synth_sample, machine) != 0)
+                       break;
+
+               rc = 0;
                if (_pid == pid) {
                        /* process the parent's maps too */
                        rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
                                                process, machine, mmap_data);
-               } else {
-                       /* only fork the tid's map, to save time */
-                       rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
-                                                process, machine);
+                       if (rc)
+                               break;
                }
-
-               if (rc)
-                       return rc;
        }
 
        closedir(tasks);
-       return 0;
+       return rc;
 }
 
 int perf_event__synthesize_thread_map(struct perf_tool *tool,
@@ -615,7 +673,7 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
        else
                s = "";
 
-       return fprintf(fp, "%s: %s:%d\n", s, event->comm.comm, event->comm.tid);
+       return fprintf(fp, "%s: %s:%d/%d\n", s, event->comm.comm, event->comm.pid, event->comm.tid);
 }
 
 int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
index c4ffe2bd0738df24f7b39854e6c0c25db806aa37..09b9e8d3fcf7fae705afcc0d3ea688f2aca77665 100644 (file)
@@ -242,7 +242,6 @@ struct events_stats {
        u32 nr_invalid_chains;
        u32 nr_unknown_id;
        u32 nr_unprocessable_samples;
-       u32 nr_unordered_events;
 };
 
 struct attr_event {
index 28b8ce86bf120d9f635ab5bcc83032083ebfac0f..080be93eea969f9893bd789cde845bf4a94a37bd 100644 (file)
@@ -7,7 +7,6 @@
  * Released under the GPL v2. (and only v2, not any later version)
  */
 #include "util.h"
-#include <api/fs/debugfs.h>
 #include <api/fs/fs.h>
 #include <poll.h>
 #include "cpumap.h"
@@ -635,8 +634,8 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
 union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
 {
        struct perf_mmap *md = &evlist->mmap[idx];
-       unsigned int head = perf_mmap__read_head(md);
-       unsigned int old = md->prev;
+       u64 head = perf_mmap__read_head(md);
+       u64 old = md->prev;
        unsigned char *data = md->base + page_size;
        union perf_event *event = NULL;
 
@@ -696,7 +695,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
 
 static bool perf_mmap__empty(struct perf_mmap *md)
 {
-       return perf_mmap__read_head(md) != md->prev;
+       return perf_mmap__read_head(md) == md->prev;
 }
 
 static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
@@ -717,7 +716,7 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
        struct perf_mmap *md = &evlist->mmap[idx];
 
        if (!evlist->overwrite) {
-               unsigned int old = md->prev;
+               u64 old = md->prev;
 
                perf_mmap__write_tail(md, old);
        }
@@ -1051,7 +1050,7 @@ out_delete_threads:
        return -1;
 }
 
-int perf_evlist__apply_filters(struct perf_evlist *evlist)
+int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
 {
        struct perf_evsel *evsel;
        int err = 0;
@@ -1063,8 +1062,10 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist)
                        continue;
 
                err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter);
-               if (err)
+               if (err) {
+                       *err_evsel = evsel;
                        break;
+               }
        }
 
        return err;
@@ -1086,6 +1087,38 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
        return err;
 }
 
+int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids)
+{
+       char *filter;
+       int ret = -1;
+       size_t i;
+
+       for (i = 0; i < npids; ++i) {
+               if (i == 0) {
+                       if (asprintf(&filter, "common_pid != %d", pids[i]) < 0)
+                               return -1;
+               } else {
+                       char *tmp;
+
+                       if (asprintf(&tmp, "%s && common_pid != %d", filter, pids[i]) < 0)
+                               goto out_free;
+
+                       free(filter);
+                       filter = tmp;
+               }
+       }
+
+       ret = perf_evlist__set_filter(evlist, filter);
+out_free:
+       free(filter);
+       return ret;
+}
+
+int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid)
+{
+       return perf_evlist__set_filter_pids(evlist, 1, &pid);
+}
+
 bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
 {
        struct perf_evsel *pos;
@@ -1329,7 +1362,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
                 * writing exactly one byte, in workload.cork_fd, usually via
                 * perf_evlist__start_workload().
                 *
-                * For cancelling the workload without actuallin running it,
+                * For cancelling the workload without actually running it,
                 * the parent will just close workload.cork_fd, without writing
                 * anything, i.e. read will return zero and we just exit()
                 * here.
index e99a67632831a8e6548fae8a40b654f01b009d1e..b5cce95d644e0c3af3c04d5edd91cdaf3aabb20d 100644 (file)
@@ -27,7 +27,7 @@ struct perf_mmap {
        void             *base;
        int              mask;
        int              refcnt;
-       unsigned int     prev;
+       u64              prev;
        char             event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
 };
 
@@ -51,6 +51,7 @@ struct perf_evlist {
        struct thread_map *threads;
        struct cpu_map    *cpus;
        struct perf_evsel *selected;
+       struct events_stats stats;
 };
 
 struct perf_evsel_str_handler {
@@ -77,6 +78,8 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
                           const char *sys, const char *name, void *handler);
 
 int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
+int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid);
+int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids);
 
 struct perf_evsel *
 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
@@ -149,7 +152,7 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
 }
 
 int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
-int perf_evlist__apply_filters(struct perf_evlist *evlist);
+int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel);
 
 void __perf_evlist__set_leader(struct list_head *list);
 void perf_evlist__set_leader(struct perf_evlist *evlist);
@@ -186,16 +189,15 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
 int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
 int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size);
 
-static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm)
+static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
 {
        struct perf_event_mmap_page *pc = mm->base;
-       int head = ACCESS_ONCE(pc->data_head);
+       u64 head = ACCESS_ONCE(pc->data_head);
        rmb();
        return head;
 }
 
-static inline void perf_mmap__write_tail(struct perf_mmap *md,
-                                        unsigned long tail)
+static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
 {
        struct perf_event_mmap_page *pc = md->base;
 
index ea51a90e20a0e9daa1a3f57c7dcf289b83299061..33e3fd8c2e682d19c8c8dbda12b9815199ef47bf 100644 (file)
@@ -32,8 +32,12 @@ static struct {
        bool exclude_guest;
        bool mmap2;
        bool cloexec;
+       bool clockid;
+       bool clockid_wrong;
 } perf_missing_features;
 
+static clockid_t clockid;
+
 static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused)
 {
        return 0;
@@ -537,13 +541,30 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
 }
 
 static void
-perf_evsel__config_callgraph(struct perf_evsel *evsel)
+perf_evsel__config_callgraph(struct perf_evsel *evsel,
+                            struct record_opts *opts)
 {
        bool function = perf_evsel__is_function_event(evsel);
        struct perf_event_attr *attr = &evsel->attr;
 
        perf_evsel__set_sample_bit(evsel, CALLCHAIN);
 
+       if (callchain_param.record_mode == CALLCHAIN_LBR) {
+               if (!opts->branch_stack) {
+                       if (attr->exclude_user) {
+                               pr_warning("LBR callstack option is only available "
+                                          "to get user callchain information. "
+                                          "Falling back to framepointers.\n");
+                       } else {
+                               perf_evsel__set_sample_bit(evsel, BRANCH_STACK);
+                               attr->branch_sample_type = PERF_SAMPLE_BRANCH_USER |
+                                                       PERF_SAMPLE_BRANCH_CALL_STACK;
+                       }
+               } else
+                        pr_warning("Cannot use LBR callstack with branch stack. "
+                                   "Falling back to framepointers.\n");
+       }
+
        if (callchain_param.record_mode == CALLCHAIN_DWARF) {
                if (!function) {
                        perf_evsel__set_sample_bit(evsel, REGS_USER);
@@ -667,7 +688,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
                evsel->attr.exclude_callchain_user = 1;
 
        if (callchain_param.enabled && !evsel->no_aux_samples)
-               perf_evsel__config_callgraph(evsel);
+               perf_evsel__config_callgraph(evsel, opts);
 
        if (opts->sample_intr_regs) {
                attr->sample_regs_intr = PERF_REGS_MASK;
@@ -717,6 +738,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
        if (opts->sample_transaction)
                perf_evsel__set_sample_bit(evsel, TRANSACTION);
 
+       if (opts->running_time) {
+               evsel->attr.read_format |=
+                       PERF_FORMAT_TOTAL_TIME_ENABLED |
+                       PERF_FORMAT_TOTAL_TIME_RUNNING;
+       }
+
        /*
         * XXX see the function comment above
         *
@@ -738,6 +765,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
                attr->disabled = 0;
                attr->enable_on_exec = 0;
        }
+
+       clockid = opts->clockid;
+       if (opts->use_clockid) {
+               attr->use_clockid = 1;
+               attr->clockid = opts->clockid;
+       }
 }
 
 static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
@@ -978,67 +1011,126 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
        return fd;
 }
 
-#define __PRINT_ATTR(fmt, cast, field)  \
-       fprintf(fp, "  %-19s "fmt"\n", #field, cast attr->field)
-
-#define PRINT_ATTR_U32(field)  __PRINT_ATTR("%u" , , field)
-#define PRINT_ATTR_X32(field)  __PRINT_ATTR("%#x", , field)
-#define PRINT_ATTR_U64(field)  __PRINT_ATTR("%" PRIu64, (uint64_t), field)
-#define PRINT_ATTR_X64(field)  __PRINT_ATTR("%#"PRIx64, (uint64_t), field)
-
-#define PRINT_ATTR2N(name1, field1, name2, field2)     \
-       fprintf(fp, "  %-19s %u    %-19s %u\n",         \
-       name1, attr->field1, name2, attr->field2)
-
-#define PRINT_ATTR2(field1, field2) \
-       PRINT_ATTR2N(#field1, field1, #field2, field2)
-
-static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
-{
-       size_t ret = 0;
-
-       ret += fprintf(fp, "%.60s\n", graph_dotted_line);
-       ret += fprintf(fp, "perf_event_attr:\n");
-
-       ret += PRINT_ATTR_U32(type);
-       ret += PRINT_ATTR_U32(size);
-       ret += PRINT_ATTR_X64(config);
-       ret += PRINT_ATTR_U64(sample_period);
-       ret += PRINT_ATTR_U64(sample_freq);
-       ret += PRINT_ATTR_X64(sample_type);
-       ret += PRINT_ATTR_X64(read_format);
-
-       ret += PRINT_ATTR2(disabled, inherit);
-       ret += PRINT_ATTR2(pinned, exclusive);
-       ret += PRINT_ATTR2(exclude_user, exclude_kernel);
-       ret += PRINT_ATTR2(exclude_hv, exclude_idle);
-       ret += PRINT_ATTR2(mmap, comm);
-       ret += PRINT_ATTR2(mmap2, comm_exec);
-       ret += PRINT_ATTR2(freq, inherit_stat);
-       ret += PRINT_ATTR2(enable_on_exec, task);
-       ret += PRINT_ATTR2(watermark, precise_ip);
-       ret += PRINT_ATTR2(mmap_data, sample_id_all);
-       ret += PRINT_ATTR2(exclude_host, exclude_guest);
-       ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel,
-                           "excl.callchain_user", exclude_callchain_user);
-
-       ret += PRINT_ATTR_U32(wakeup_events);
-       ret += PRINT_ATTR_U32(wakeup_watermark);
-       ret += PRINT_ATTR_X32(bp_type);
-       ret += PRINT_ATTR_X64(bp_addr);
-       ret += PRINT_ATTR_X64(config1);
-       ret += PRINT_ATTR_U64(bp_len);
-       ret += PRINT_ATTR_X64(config2);
-       ret += PRINT_ATTR_X64(branch_sample_type);
-       ret += PRINT_ATTR_X64(sample_regs_user);
-       ret += PRINT_ATTR_U32(sample_stack_user);
-       ret += PRINT_ATTR_X64(sample_regs_intr);
-
-       ret += fprintf(fp, "%.60s\n", graph_dotted_line);
+struct bit_names {
+       int bit;
+       const char *name;
+};
+
+static void __p_bits(char *buf, size_t size, u64 value, struct bit_names *bits)
+{
+       bool first_bit = true;
+       int i = 0;
+
+       do {
+               if (value & bits[i].bit) {
+                       buf += scnprintf(buf, size, "%s%s", first_bit ? "" : "|", bits[i].name);
+                       first_bit = false;
+               }
+       } while (bits[++i].name != NULL);
+}
+
+static void __p_sample_type(char *buf, size_t size, u64 value)
+{
+#define bit_name(n) { PERF_SAMPLE_##n, #n }
+       struct bit_names bits[] = {
+               bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
+               bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
+               bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
+               bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
+               bit_name(IDENTIFIER), bit_name(REGS_INTR),
+               { .name = NULL, }
+       };
+#undef bit_name
+       __p_bits(buf, size, value, bits);
+}
+
+static void __p_read_format(char *buf, size_t size, u64 value)
+{
+#define bit_name(n) { PERF_FORMAT_##n, #n }
+       struct bit_names bits[] = {
+               bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
+               bit_name(ID), bit_name(GROUP),
+               { .name = NULL, }
+       };
+#undef bit_name
+       __p_bits(buf, size, value, bits);
+}
+
+#define BUF_SIZE               1024
+
+#define p_hex(val)             snprintf(buf, BUF_SIZE, "%"PRIx64, (uint64_t)(val))
+#define p_unsigned(val)                snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val))
+#define p_signed(val)          snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val))
+#define p_sample_type(val)     __p_sample_type(buf, BUF_SIZE, val)
+#define p_read_format(val)     __p_read_format(buf, BUF_SIZE, val)
+
+#define PRINT_ATTRn(_n, _f, _p)                                \
+do {                                                   \
+       if (attr->_f) {                                 \
+               _p(attr->_f);                           \
+               ret += attr__fprintf(fp, _n, buf, priv);\
+       }                                               \
+} while (0)
+
+#define PRINT_ATTRf(_f, _p)    PRINT_ATTRn(#_f, _f, _p)
+
+int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
+                            attr__fprintf_f attr__fprintf, void *priv)
+{
+       char buf[BUF_SIZE];
+       int ret = 0;
+
+       PRINT_ATTRf(type, p_unsigned);
+       PRINT_ATTRf(size, p_unsigned);
+       PRINT_ATTRf(config, p_hex);
+       PRINT_ATTRn("{ sample_period, sample_freq }", sample_period, p_unsigned);
+       PRINT_ATTRf(sample_type, p_sample_type);
+       PRINT_ATTRf(read_format, p_read_format);
+
+       PRINT_ATTRf(disabled, p_unsigned);
+       PRINT_ATTRf(inherit, p_unsigned);
+       PRINT_ATTRf(pinned, p_unsigned);
+       PRINT_ATTRf(exclusive, p_unsigned);
+       PRINT_ATTRf(exclude_user, p_unsigned);
+       PRINT_ATTRf(exclude_kernel, p_unsigned);
+       PRINT_ATTRf(exclude_hv, p_unsigned);
+       PRINT_ATTRf(exclude_idle, p_unsigned);
+       PRINT_ATTRf(mmap, p_unsigned);
+       PRINT_ATTRf(comm, p_unsigned);
+       PRINT_ATTRf(freq, p_unsigned);
+       PRINT_ATTRf(inherit_stat, p_unsigned);
+       PRINT_ATTRf(enable_on_exec, p_unsigned);
+       PRINT_ATTRf(task, p_unsigned);
+       PRINT_ATTRf(watermark, p_unsigned);
+       PRINT_ATTRf(precise_ip, p_unsigned);
+       PRINT_ATTRf(mmap_data, p_unsigned);
+       PRINT_ATTRf(sample_id_all, p_unsigned);
+       PRINT_ATTRf(exclude_host, p_unsigned);
+       PRINT_ATTRf(exclude_guest, p_unsigned);
+       PRINT_ATTRf(exclude_callchain_kernel, p_unsigned);
+       PRINT_ATTRf(exclude_callchain_user, p_unsigned);
+       PRINT_ATTRf(mmap2, p_unsigned);
+       PRINT_ATTRf(comm_exec, p_unsigned);
+       PRINT_ATTRf(use_clockid, p_unsigned);
+
+       PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
+       PRINT_ATTRf(bp_type, p_unsigned);
+       PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex);
+       PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex);
+       PRINT_ATTRf(sample_regs_user, p_hex);
+       PRINT_ATTRf(sample_stack_user, p_unsigned);
+       PRINT_ATTRf(clockid, p_signed);
+       PRINT_ATTRf(sample_regs_intr, p_hex);
 
        return ret;
 }
 
+static int __open_attr__fprintf(FILE *fp, const char *name, const char *val,
+                               void *priv __attribute__((unused)))
+{
+       return fprintf(fp, "  %-32s %s\n", name, val);
+}
+
 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
                              struct thread_map *threads)
 {
@@ -1062,6 +1154,12 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
        }
 
 fallback_missing_features:
+       if (perf_missing_features.clockid_wrong)
+               evsel->attr.clockid = CLOCK_MONOTONIC; /* should always work */
+       if (perf_missing_features.clockid) {
+               evsel->attr.use_clockid = 0;
+               evsel->attr.clockid = 0;
+       }
        if (perf_missing_features.cloexec)
                flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
        if (perf_missing_features.mmap2)
@@ -1072,8 +1170,12 @@ retry_sample_id:
        if (perf_missing_features.sample_id_all)
                evsel->attr.sample_id_all = 0;
 
-       if (verbose >= 2)
-               perf_event_attr__fprintf(&evsel->attr, stderr);
+       if (verbose >= 2) {
+               fprintf(stderr, "%.60s\n", graph_dotted_line);
+               fprintf(stderr, "perf_event_attr:\n");
+               perf_event_attr__fprintf(stderr, &evsel->attr, __open_attr__fprintf, NULL);
+               fprintf(stderr, "%.60s\n", graph_dotted_line);
+       }
 
        for (cpu = 0; cpu < cpus->nr; cpu++) {
 
@@ -1099,6 +1201,17 @@ retry_open:
                                goto try_fallback;
                        }
                        set_rlimit = NO_CHANGE;
+
+                       /*
+                        * If we succeeded but had to kill clockid, fail and
+                        * have perf_evsel__open_strerror() print us a nice
+                        * error.
+                        */
+                       if (perf_missing_features.clockid ||
+                           perf_missing_features.clockid_wrong) {
+                               err = -EINVAL;
+                               goto out_close;
+                       }
                }
        }
 
@@ -1132,7 +1245,17 @@ try_fallback:
        if (err != -EINVAL || cpu > 0 || thread > 0)
                goto out_close;
 
-       if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
+       /*
+        * Must probe features in the order they were added to the
+        * perf_event_attr interface.
+        */
+       if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) {
+               perf_missing_features.clockid_wrong = true;
+               goto fallback_missing_features;
+       } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) {
+               perf_missing_features.clockid = true;
+               goto fallback_missing_features;
+       } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
                perf_missing_features.cloexec = true;
                goto fallback_missing_features;
        } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
@@ -1892,7 +2015,7 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
                value = *(u32 *)ptr;
                break;
        case 8:
-               value = *(u64 *)ptr;
+               memcpy(&value, ptr, sizeof(u64));
                break;
        default:
                return 0;
@@ -1933,62 +2056,9 @@ static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
        return ret;
 }
 
-static int __if_fprintf(FILE *fp, bool *first, const char *field, u64 value)
-{
-       if (value == 0)
-               return 0;
-
-       return comma_fprintf(fp, first, " %s: %" PRIu64, field, value);
-}
-
-#define if_print(field) printed += __if_fprintf(fp, &first, #field, evsel->attr.field)
-
-struct bit_names {
-       int bit;
-       const char *name;
-};
-
-static int bits__fprintf(FILE *fp, const char *field, u64 value,
-                        struct bit_names *bits, bool *first)
-{
-       int i = 0, printed = comma_fprintf(fp, first, " %s: ", field);
-       bool first_bit = true;
-
-       do {
-               if (value & bits[i].bit) {
-                       printed += fprintf(fp, "%s%s", first_bit ? "" : "|", bits[i].name);
-                       first_bit = false;
-               }
-       } while (bits[++i].name != NULL);
-
-       return printed;
-}
-
-static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
-{
-#define bit_name(n) { PERF_SAMPLE_##n, #n }
-       struct bit_names bits[] = {
-               bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
-               bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
-               bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
-               bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
-               bit_name(IDENTIFIER), bit_name(REGS_INTR),
-               { .name = NULL, }
-       };
-#undef bit_name
-       return bits__fprintf(fp, "sample_type", value, bits, first);
-}
-
-static int read_format__fprintf(FILE *fp, bool *first, u64 value)
+static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv)
 {
-#define bit_name(n) { PERF_FORMAT_##n, #n }
-       struct bit_names bits[] = {
-               bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
-               bit_name(ID), bit_name(GROUP),
-               { .name = NULL, }
-       };
-#undef bit_name
-       return bits__fprintf(fp, "read_format", value, bits, first);
+       return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);
 }
 
 int perf_evsel__fprintf(struct perf_evsel *evsel,
@@ -2017,47 +2087,13 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
 
        printed += fprintf(fp, "%s", perf_evsel__name(evsel));
 
-       if (details->verbose || details->freq) {
+       if (details->verbose) {
+               printed += perf_event_attr__fprintf(fp, &evsel->attr,
+                                                   __print_attr__fprintf, &first);
+       } else if (details->freq) {
                printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64,
                                         (u64)evsel->attr.sample_freq);
        }
-
-       if (details->verbose) {
-               if_print(type);
-               if_print(config);
-               if_print(config1);
-               if_print(config2);
-               if_print(size);
-               printed += sample_type__fprintf(fp, &first, evsel->attr.sample_type);
-               if (evsel->attr.read_format)
-                       printed += read_format__fprintf(fp, &first, evsel->attr.read_format);
-               if_print(disabled);
-               if_print(inherit);
-               if_print(pinned);
-               if_print(exclusive);
-               if_print(exclude_user);
-               if_print(exclude_kernel);
-               if_print(exclude_hv);
-               if_print(exclude_idle);
-               if_print(mmap);
-               if_print(mmap2);
-               if_print(comm);
-               if_print(comm_exec);
-               if_print(freq);
-               if_print(inherit_stat);
-               if_print(enable_on_exec);
-               if_print(task);
-               if_print(watermark);
-               if_print(precise_ip);
-               if_print(mmap_data);
-               if_print(sample_id_all);
-               if_print(exclude_host);
-               if_print(exclude_guest);
-               if_print(__reserved_1);
-               if_print(wakeup_events);
-               if_print(bp_type);
-               if_print(branch_sample_type);
-       }
 out:
        fputc('\n', fp);
        return ++printed;
@@ -2135,6 +2171,12 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
        "The PMU counters are busy/taken by another profiler.\n"
        "We found oprofile daemon running, please stop it and try again.");
                break;
+       case EINVAL:
+               if (perf_missing_features.clockid)
+                       return scnprintf(msg, size, "clockid feature not supported.");
+               if (perf_missing_features.clockid_wrong)
+                       return scnprintf(msg, size, "wrong clockid (%d).", clockid);
+               break;
        default:
                break;
        }
index 38622747d13034c3d6f383f56e411a833b18a07b..e486151b03089720eed68436bbae7a454defb3ec 100644 (file)
@@ -335,6 +335,7 @@ struct perf_attr_details {
        bool freq;
        bool verbose;
        bool event_group;
+       bool force;
 };
 
 int perf_evsel__fprintf(struct perf_evsel *evsel,
@@ -355,4 +356,14 @@ for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node);         \
      (_evsel) && (_evsel)->leader == (_leader);                                        \
      (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
 
+static inline bool has_branch_callstack(struct perf_evsel *evsel)
+{
+       return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
+}
+
+typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *);
+
+int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
+                            attr__fprintf_f attr__fprintf, void *priv);
+
 #endif /* __PERF_EVSEL_H */
index 1f407f7352a7fd2bab67ad13e63e5fcd053495ba..918fd8ae2d80bca007a8b6f7e2f8488fed0771a3 100644 (file)
@@ -1055,6 +1055,12 @@ error:
        goto out;
 }
 
+static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val,
+                               void *priv __attribute__((unused)))
+{
+       return fprintf(fp, ", %s = %s", name, val);
+}
+
 static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
 {
        struct perf_evsel *evsel, *events = read_event_desc(ph, fd);
@@ -1069,26 +1075,6 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
        for (evsel = events; evsel->attr.size; evsel++) {
                fprintf(fp, "# event : name = %s, ", evsel->name);
 
-               fprintf(fp, "type = %d, config = 0x%"PRIx64
-                           ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64,
-                               evsel->attr.type,
-                               (u64)evsel->attr.config,
-                               (u64)evsel->attr.config1,
-                               (u64)evsel->attr.config2);
-
-               fprintf(fp, ", excl_usr = %d, excl_kern = %d",
-                               evsel->attr.exclude_user,
-                               evsel->attr.exclude_kernel);
-
-               fprintf(fp, ", excl_host = %d, excl_guest = %d",
-                               evsel->attr.exclude_host,
-                               evsel->attr.exclude_guest);
-
-               fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
-
-               fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2);
-               fprintf(fp, ", attr_mmap  = %d", evsel->attr.mmap);
-               fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data);
                if (evsel->ids) {
                        fprintf(fp, ", id = {");
                        for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
@@ -1099,6 +1085,8 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
                        fprintf(fp, " }");
                }
 
+               perf_event_attr__fprintf(fp, &evsel->attr, __desc_attr__fprintf, NULL);
+
                fputc('\n', fp);
        }
 
@@ -1266,7 +1254,7 @@ static int __event_process_build_id(struct build_id_event *bev,
 
                dso__set_build_id(dso, &bev->build_id);
 
-               if (!is_kernel_module(filename, NULL))
+               if (!is_kernel_module(filename))
                        dso->kernel = dso_type;
 
                build_id__sprintf(dso->build_id, sizeof(dso->build_id),
@@ -2516,8 +2504,11 @@ int perf_session__read_header(struct perf_session *session)
                if (read_attr(fd, header, &f_attr) < 0)
                        goto out_errno;
 
-               if (header->needs_swap)
+               if (header->needs_swap) {
+                       f_attr.ids.size   = bswap_64(f_attr.ids.size);
+                       f_attr.ids.offset = bswap_64(f_attr.ids.offset);
                        perf_event__attr_swap(&f_attr.attr);
+               }
 
                tmp = lseek(fd, 0, SEEK_CUR);
                evsel = perf_evsel__new(&f_attr.attr);
index 70b48a65064cbc85fd30d6777eb1a9ca25ca0098..cc22b9158b93c41fd0d44cd451ba189c56bc19dd 100644 (file)
@@ -263,15 +263,9 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
        while (next) {
                n = rb_entry(next, struct hist_entry, rb_node);
                next = rb_next(&n->rb_node);
-               /*
-                * We may be annotating this, for instance, so keep it here in
-                * case some it gets new samples, we'll eventually free it when
-                * the user stops browsing and it agains gets fully decayed.
-                */
                if (((zap_user && n->level == '.') ||
                     (zap_kernel && n->level != '.') ||
-                    hists__decay_entry(hists, n)) &&
-                   !n->used) {
+                    hists__decay_entry(hists, n))) {
                        hists__delete_entry(hists, n);
                }
        }
@@ -355,6 +349,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
                        callchain_init(he->callchain);
 
                INIT_LIST_HEAD(&he->pairs.node);
+               thread__get(he->thread);
        }
 
        return he;
@@ -941,6 +936,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
 
 void hist_entry__delete(struct hist_entry *he)
 {
+       thread__zput(he->thread);
        zfree(&he->branch_info);
        zfree(&he->mem_info);
        zfree(&he->stat_acc);
@@ -1169,6 +1165,7 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
        /* force fold unfiltered entry for simplicity */
        h->ms.unfolded = false;
        h->row_offset = 0;
+       h->nr_rows = 0;
 
        hists->stats.nr_non_filtered_samples += h->stat.nr_events;
 
index 2b690d02890707f2b916220c1402df3b8f774e98..9f31b89a527a2e8f9d02da1993cdff13709b84c1 100644 (file)
@@ -60,7 +60,7 @@ struct hists {
        struct rb_root          entries_collapsed;
        u64                     nr_entries;
        u64                     nr_non_filtered_entries;
-       const struct thread     *thread_filter;
+       struct thread           *thread_filter;
        const struct dso        *dso_filter;
        const char              *uid_filter_str;
        const char              *symbol_filter_str;
@@ -303,6 +303,9 @@ struct hist_browser_timer {
 
 #ifdef HAVE_SLANG_SUPPORT
 #include "../ui/keysyms.h"
+int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
+                            struct hist_browser_timer *hbt);
+
 int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
                             struct hist_browser_timer *hbt);
 
@@ -321,6 +324,12 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
 {
        return 0;
 }
+static inline int map_symbol__tui_annotate(struct map_symbol *ms __maybe_unused,
+                                          struct perf_evsel *evsel __maybe_unused,
+                                          struct hist_browser_timer *hbt __maybe_unused)
+{
+       return 0;
+}
 
 static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused,
                                           struct perf_evsel *evsel __maybe_unused,
index 6789d788d4947d31f890ca56660d8ef968901b82..3a3a0f16456ae3369cd73faff1d3af9e4e8d4180 100644 (file)
@@ -4,5 +4,6 @@
 /* Just disable it so we can build arch/x86/lib/memcpy_64.S for perf bench: */
 
 #define altinstruction_entry #
+#define ALTERNATIVE_2 #
 
 #endif
index cf1d7913783bbcd89c1aa0e9cb9c818c590fd5ac..ae825d4ec110fcfe6a06ef5e4daf50b03a214a87 100644 (file)
@@ -99,6 +99,7 @@ struct perf_kvm_stat {
        int timerfd;
        unsigned int display_time;
        bool live;
+       bool force;
 };
 
 struct kvm_reg_events_ops {
diff --git a/tools/perf/util/lzma.c b/tools/perf/util/lzma.c
new file mode 100644 (file)
index 0000000..95a1acb
--- /dev/null
@@ -0,0 +1,95 @@
+#include <lzma.h>
+#include <stdio.h>
+#include <linux/compiler.h>
+#include "util.h"
+#include "debug.h"
+
+#define BUFSIZE 8192
+
+static const char *lzma_strerror(lzma_ret ret)
+{
+       switch ((int) ret) {
+       case LZMA_MEM_ERROR:
+               return "Memory allocation failed";
+       case LZMA_OPTIONS_ERROR:
+               return "Unsupported decompressor flags";
+       case LZMA_FORMAT_ERROR:
+               return "The input is not in the .xz format";
+       case LZMA_DATA_ERROR:
+               return "Compressed file is corrupt";
+       case LZMA_BUF_ERROR:
+               return "Compressed file is truncated or otherwise corrupt";
+       default:
+               return "Unknown error, possibly a bug";
+       }
+}
+
+int lzma_decompress_to_file(const char *input, int output_fd)
+{
+       lzma_action action = LZMA_RUN;
+       lzma_stream strm   = LZMA_STREAM_INIT;
+       lzma_ret ret;
+
+       u8 buf_in[BUFSIZE];
+       u8 buf_out[BUFSIZE];
+       FILE *infile;
+
+       infile = fopen(input, "rb");
+       if (!infile) {
+               pr_err("lzma: fopen failed on %s: '%s'\n",
+                      input, strerror(errno));
+               return -1;
+       }
+
+       ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
+       if (ret != LZMA_OK) {
+               pr_err("lzma: lzma_stream_decoder failed %s (%d)\n",
+                       lzma_strerror(ret), ret);
+               return -1;
+       }
+
+       strm.next_in   = NULL;
+       strm.avail_in  = 0;
+       strm.next_out  = buf_out;
+       strm.avail_out = sizeof(buf_out);
+
+       while (1) {
+               if (strm.avail_in == 0 && !feof(infile)) {
+                       strm.next_in  = buf_in;
+                       strm.avail_in = fread(buf_in, 1, sizeof(buf_in), infile);
+
+                       if (ferror(infile)) {
+                               pr_err("lzma: read error: %s\n", strerror(errno));
+                               return -1;
+                       }
+
+                       if (feof(infile))
+                               action = LZMA_FINISH;
+               }
+
+               ret = lzma_code(&strm, action);
+
+               if (strm.avail_out == 0 || ret == LZMA_STREAM_END) {
+                       ssize_t write_size = sizeof(buf_out) - strm.avail_out;
+
+                       if (writen(output_fd, buf_out, write_size) != write_size) {
+                               pr_err("lzma: write error: %s\n", strerror(errno));
+                               return -1;
+                       }
+
+                       strm.next_out  = buf_out;
+                       strm.avail_out = sizeof(buf_out);
+               }
+
+               if (ret != LZMA_OK) {
+                       if (ret == LZMA_STREAM_END)
+                               return 0;
+
+                       pr_err("lzma: failed %s\n", lzma_strerror(ret));
+                       return -1;
+               }
+       }
+
+       fclose(infile);
+       return 0;
+}
index 1bca3a9f2b16bc91670f731e05564680d2f12a10..527e032e24f6e648e258b08b379e55fc6dcf8e5a 100644 (file)
@@ -89,16 +89,6 @@ static void dsos__delete(struct dsos *dsos)
        }
 }
 
-void machine__delete_dead_threads(struct machine *machine)
-{
-       struct thread *n, *t;
-
-       list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
-               list_del(&t->node);
-               thread__delete(t);
-       }
-}
-
 void machine__delete_threads(struct machine *machine)
 {
        struct rb_node *nd = rb_first(&machine->threads);
@@ -106,9 +96,8 @@ void machine__delete_threads(struct machine *machine)
        while (nd) {
                struct thread *t = rb_entry(nd, struct thread, rb_node);
 
-               rb_erase(&t->rb_node, &machine->threads);
                nd = rb_next(nd);
-               thread__delete(t);
+               machine__remove_thread(machine, t);
        }
 }
 
@@ -361,9 +350,13 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
         * the full rbtree:
         */
        th = machine->last_match;
-       if (th && th->tid == tid) {
-               machine__update_thread_pid(machine, th, pid);
-               return th;
+       if (th != NULL) {
+               if (th->tid == tid) {
+                       machine__update_thread_pid(machine, th, pid);
+                       return th;
+               }
+
+               thread__zput(machine->last_match);
        }
 
        while (*p != NULL) {
@@ -371,7 +364,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
                th = rb_entry(parent, struct thread, rb_node);
 
                if (th->tid == tid) {
-                       machine->last_match = th;
+                       machine->last_match = thread__get(th);
                        machine__update_thread_pid(machine, th, pid);
                        return th;
                }
@@ -403,8 +396,11 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
                        thread__delete(th);
                        return NULL;
                }
-
-               machine->last_match = th;
+               /*
+                * It is now in the rbtree, get a ref
+                */
+               thread__get(th);
+               machine->last_match = thread__get(th);
        }
 
        return th;
@@ -462,30 +458,61 @@ int machine__process_lost_event(struct machine *machine __maybe_unused,
        return 0;
 }
 
+static struct dso*
+machine__module_dso(struct machine *machine, struct kmod_path *m,
+                   const char *filename)
+{
+       struct dso *dso;
+
+       dso = dsos__find(&machine->kernel_dsos, m->name, true);
+       if (!dso) {
+               dso = dsos__addnew(&machine->kernel_dsos, m->name);
+               if (dso == NULL)
+                       return NULL;
+
+               if (machine__is_host(machine))
+                       dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
+               else
+                       dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
+
+               /* _KMODULE_COMP should be next to _KMODULE */
+               if (m->kmod && m->comp)
+                       dso->symtab_type++;
+
+               dso__set_short_name(dso, strdup(m->name), true);
+               dso__set_long_name(dso, strdup(filename), true);
+       }
+
+       return dso;
+}
+
 struct map *machine__new_module(struct machine *machine, u64 start,
                                const char *filename)
 {
-       struct map *map;
-       struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
-       bool compressed;
+       struct map *map = NULL;
+       struct dso *dso;
+       struct kmod_path m;
 
-       if (dso == NULL)
+       if (kmod_path__parse_name(&m, filename))
                return NULL;
 
-       map = map__new2(start, dso, MAP__FUNCTION);
-       if (map == NULL)
-               return NULL;
+       map = map_groups__find_by_name(&machine->kmaps, MAP__FUNCTION,
+                                      m.name);
+       if (map)
+               goto out;
 
-       if (machine__is_host(machine))
-               dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
-       else
-               dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
+       dso = machine__module_dso(machine, &m, filename);
+       if (dso == NULL)
+               goto out;
 
-       /* _KMODULE_COMP should be next to _KMODULE */
-       if (is_kernel_module(filename, &compressed) && compressed)
-               dso->symtab_type++;
+       map = map__new2(start, dso, MAP__FUNCTION);
+       if (map == NULL)
+               goto out;
 
        map_groups__insert(&machine->kmaps, map);
+
+out:
+       free(m.name);
        return map;
 }
 
@@ -650,6 +677,9 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
                        machine->vmlinux_maps[type]->unmap_ip =
                                identity__map_ip;
                kmap = map__kmap(machine->vmlinux_maps[type]);
+               if (!kmap)
+                       return -1;
+
                kmap->kmaps = &machine->kmaps;
                map_groups__insert(&machine->kmaps,
                                   machine->vmlinux_maps[type]);
@@ -671,7 +701,7 @@ void machine__destroy_kernel_maps(struct machine *machine)
                kmap = map__kmap(machine->vmlinux_maps[type]);
                map_groups__remove(&machine->kmaps,
                                   machine->vmlinux_maps[type]);
-               if (kmap->ref_reloc_sym) {
+               if (kmap && kmap->ref_reloc_sym) {
                        /*
                         * ref_reloc_sym is shared among all maps, so free just
                         * on one of them.
@@ -827,6 +857,39 @@ static char *get_kernel_version(const char *root_dir)
        return strdup(name);
 }
 
+static bool is_kmod_dso(struct dso *dso)
+{
+       return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
+              dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
+}
+
+static int map_groups__set_module_path(struct map_groups *mg, const char *path,
+                                      struct kmod_path *m)
+{
+       struct map *map;
+       char *long_name;
+
+       map = map_groups__find_by_name(mg, MAP__FUNCTION, m->name);
+       if (map == NULL)
+               return 0;
+
+       long_name = strdup(path);
+       if (long_name == NULL)
+               return -ENOMEM;
+
+       dso__set_long_name(map->dso, long_name, true);
+       dso__kernel_module_get_build_id(map->dso, "");
+
+       /*
+        * Full name could reveal us kmod compression, so
+        * we need to update the symtab_type if needed.
+        */
+       if (m->comp && is_kmod_dso(map->dso))
+               map->dso->symtab_type++;
+
+       return 0;
+}
+
 static int map_groups__set_modules_path_dir(struct map_groups *mg,
                                const char *dir_name, int depth)
 {
@@ -865,35 +928,19 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
                        if (ret < 0)
                                goto out;
                } else {
-                       char *dot = strrchr(dent->d_name, '.'),
-                            dso_name[PATH_MAX];
-                       struct map *map;
-                       char *long_name;
+                       struct kmod_path m;
 
-                       if (dot == NULL)
-                               continue;
-
-                       /* On some system, modules are compressed like .ko.gz */
-                       if (is_supported_compression(dot + 1) &&
-                           is_kmodule_extension(dot - 2))
-                               dot -= 3;
+                       ret = kmod_path__parse_name(&m, dent->d_name);
+                       if (ret)
+                               goto out;
 
-                       snprintf(dso_name, sizeof(dso_name), "[%.*s]",
-                                (int)(dot - dent->d_name), dent->d_name);
+                       if (m.kmod)
+                               ret = map_groups__set_module_path(mg, path, &m);
 
-                       strxfrchar(dso_name, '-', '_');
-                       map = map_groups__find_by_name(mg, MAP__FUNCTION,
-                                                      dso_name);
-                       if (map == NULL)
-                               continue;
+                       free(m.name);
 
-                       long_name = strdup(path);
-                       if (long_name == NULL) {
-                               ret = -1;
+                       if (ret)
                                goto out;
-                       }
-                       dso__set_long_name(map->dso, long_name, true);
-                       dso__kernel_module_get_build_id(map->dso, "");
                }
        }
 
@@ -1046,40 +1093,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
                                strlen(kmmap_prefix) - 1) == 0;
        if (event->mmap.filename[0] == '/' ||
            (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
-
-               char short_module_name[1024];
-               char *name, *dot;
-
-               if (event->mmap.filename[0] == '/') {
-                       name = strrchr(event->mmap.filename, '/');
-                       if (name == NULL)
-                               goto out_problem;
-
-                       ++name; /* skip / */
-                       dot = strrchr(name, '.');
-                       if (dot == NULL)
-                               goto out_problem;
-                       /* On some system, modules are compressed like .ko.gz */
-                       if (is_supported_compression(dot + 1))
-                               dot -= 3;
-                       if (!is_kmodule_extension(dot + 1))
-                               goto out_problem;
-                       snprintf(short_module_name, sizeof(short_module_name),
-                                       "[%.*s]", (int)(dot - name), name);
-                       strxfrchar(short_module_name, '-', '_');
-               } else
-                       strcpy(short_module_name, event->mmap.filename);
-
                map = machine__new_module(machine, event->mmap.start,
                                          event->mmap.filename);
                if (map == NULL)
                        goto out_problem;
 
-               name = strdup(short_module_name);
-               if (name == NULL)
-                       goto out_problem;
-
-               dso__set_short_name(map->dso, name, true);
                map->end = map->start + event->mmap.len;
        } else if (is_kernel_mmap) {
                const char *symbol_name = (event->mmap.filename +
@@ -1092,7 +1110,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
                struct dso *dso;
 
                list_for_each_entry(dso, &machine->kernel_dsos.head, node) {
-                       if (is_kernel_module(dso->long_name, NULL))
+                       if (is_kernel_module(dso->long_name))
                                continue;
 
                        kernel = dso;
@@ -1236,15 +1254,19 @@ out_problem:
        return 0;
 }
 
-static void machine__remove_thread(struct machine *machine, struct thread *th)
+void machine__remove_thread(struct machine *machine, struct thread *th)
 {
-       machine->last_match = NULL;
+       if (machine->last_match == th)
+               thread__zput(machine->last_match);
+
        rb_erase(&th->rb_node, &machine->threads);
        /*
-        * We may have references to this thread, for instance in some hist_entry
-        * instances, so just move them to a separate list.
+        * Move it first to the dead_threads list, then drop the reference,
+        * if this is the last reference, then the thread__delete destructor
+        * will be called and we will remove it from the dead_threads list.
         */
        list_add_tail(&th->node, &machine->dead_threads);
+       thread__put(th);
 }
 
 int machine__process_fork_event(struct machine *machine, union perf_event *event,
@@ -1387,29 +1409,27 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
 static int add_callchain_ip(struct thread *thread,
                            struct symbol **parent,
                            struct addr_location *root_al,
-                           bool branch_history,
+                           u8 *cpumode,
                            u64 ip)
 {
        struct addr_location al;
 
        al.filtered = 0;
        al.sym = NULL;
-       if (branch_history)
+       if (!cpumode) {
                thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
                                                   ip, &al);
-       else {
-               u8 cpumode = PERF_RECORD_MISC_USER;
-
+       } else {
                if (ip >= PERF_CONTEXT_MAX) {
                        switch (ip) {
                        case PERF_CONTEXT_HV:
-                               cpumode = PERF_RECORD_MISC_HYPERVISOR;
+                               *cpumode = PERF_RECORD_MISC_HYPERVISOR;
                                break;
                        case PERF_CONTEXT_KERNEL:
-                               cpumode = PERF_RECORD_MISC_KERNEL;
+                               *cpumode = PERF_RECORD_MISC_KERNEL;
                                break;
                        case PERF_CONTEXT_USER:
-                               cpumode = PERF_RECORD_MISC_USER;
+                               *cpumode = PERF_RECORD_MISC_USER;
                                break;
                        default:
                                pr_debug("invalid callchain context: "
@@ -1423,8 +1443,8 @@ static int add_callchain_ip(struct thread *thread,
                        }
                        return 0;
                }
-               thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
-                                  ip, &al);
+               thread__find_addr_location(thread, *cpumode, MAP__FUNCTION,
+                                          ip, &al);
        }
 
        if (al.sym != NULL) {
@@ -1502,18 +1522,102 @@ static int remove_loops(struct branch_entry *l, int nr)
        return nr;
 }
 
-static int thread__resolve_callchain_sample(struct thread *thread,
-                                            struct ip_callchain *chain,
-                                            struct branch_stack *branch,
-                                            struct symbol **parent,
-                                            struct addr_location *root_al,
-                                            int max_stack)
+/*
+ * Recolve LBR callstack chain sample
+ * Return:
+ * 1 on success get LBR callchain information
+ * 0 no available LBR callchain information, should try fp
+ * negative error code on other errors.
+ */
+static int resolve_lbr_callchain_sample(struct thread *thread,
+                                       struct perf_sample *sample,
+                                       struct symbol **parent,
+                                       struct addr_location *root_al,
+                                       int max_stack)
 {
+       struct ip_callchain *chain = sample->callchain;
        int chain_nr = min(max_stack, (int)chain->nr);
+       u8 cpumode = PERF_RECORD_MISC_USER;
+       int i, j, err;
+       u64 ip;
+
+       for (i = 0; i < chain_nr; i++) {
+               if (chain->ips[i] == PERF_CONTEXT_USER)
+                       break;
+       }
+
+       /* LBR only affects the user callchain */
+       if (i != chain_nr) {
+               struct branch_stack *lbr_stack = sample->branch_stack;
+               int lbr_nr = lbr_stack->nr;
+               /*
+                * LBR callstack can only get user call chain.
+                * The mix_chain_nr is kernel call chain
+                * number plus LBR user call chain number.
+                * i is kernel call chain number,
+                * 1 is PERF_CONTEXT_USER,
+                * lbr_nr + 1 is the user call chain number.
+                * For details, please refer to the comments
+                * in callchain__printf
+                */
+               int mix_chain_nr = i + 1 + lbr_nr + 1;
+
+               if (mix_chain_nr > PERF_MAX_STACK_DEPTH + PERF_MAX_BRANCH_DEPTH) {
+                       pr_warning("corrupted callchain. skipping...\n");
+                       return 0;
+               }
+
+               for (j = 0; j < mix_chain_nr; j++) {
+                       if (callchain_param.order == ORDER_CALLEE) {
+                               if (j < i + 1)
+                                       ip = chain->ips[j];
+                               else if (j > i + 1)
+                                       ip = lbr_stack->entries[j - i - 2].from;
+                               else
+                                       ip = lbr_stack->entries[0].to;
+                       } else {
+                               if (j < lbr_nr)
+                                       ip = lbr_stack->entries[lbr_nr - j - 1].from;
+                               else if (j > lbr_nr)
+                                       ip = chain->ips[i + 1 - (j - lbr_nr)];
+                               else
+                                       ip = lbr_stack->entries[0].to;
+                       }
+
+                       err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);
+                       if (err)
+                               return (err < 0) ? err : 0;
+               }
+               return 1;
+       }
+
+       return 0;
+}
+
+static int thread__resolve_callchain_sample(struct thread *thread,
+                                           struct perf_evsel *evsel,
+                                           struct perf_sample *sample,
+                                           struct symbol **parent,
+                                           struct addr_location *root_al,
+                                           int max_stack)
+{
+       struct branch_stack *branch = sample->branch_stack;
+       struct ip_callchain *chain = sample->callchain;
+       int chain_nr = min(max_stack, (int)chain->nr);
+       u8 cpumode = PERF_RECORD_MISC_USER;
        int i, j, err;
        int skip_idx = -1;
        int first_call = 0;
 
+       callchain_cursor_reset(&callchain_cursor);
+
+       if (has_branch_callstack(evsel)) {
+               err = resolve_lbr_callchain_sample(thread, sample, parent,
+                                                  root_al, max_stack);
+               if (err)
+                       return (err < 0) ? err : 0;
+       }
+
        /*
         * Based on DWARF debug information, some architectures skip
         * a callchain entry saved by the kernel.
@@ -1521,8 +1625,6 @@ static int thread__resolve_callchain_sample(struct thread *thread,
        if (chain->nr < PERF_MAX_STACK_DEPTH)
                skip_idx = arch_skip_callchain_idx(thread, chain);
 
-       callchain_cursor_reset(&callchain_cursor);
-
        /*
         * Add branches to call stack for easier browsing. This gives
         * more context for a sample than just the callers.
@@ -1568,10 +1670,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
 
                for (i = 0; i < nr; i++) {
                        err = add_callchain_ip(thread, parent, root_al,
-                                              true, be[i].to);
+                                              NULL, be[i].to);
                        if (!err)
                                err = add_callchain_ip(thread, parent, root_al,
-                                                      true, be[i].from);
+                                                      NULL, be[i].from);
                        if (err == -EINVAL)
                                break;
                        if (err)
@@ -1600,7 +1702,7 @@ check_calls:
 #endif
                ip = chain->ips[j];
 
-               err = add_callchain_ip(thread, parent, root_al, false, ip);
+               err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);
 
                if (err)
                        return (err < 0) ? err : 0;
@@ -1623,9 +1725,9 @@ int thread__resolve_callchain(struct thread *thread,
                              struct addr_location *root_al,
                              int max_stack)
 {
-       int ret = thread__resolve_callchain_sample(thread, sample->callchain,
-                                                  sample->branch_stack,
-                                                  parent, root_al, max_stack);
+       int ret = thread__resolve_callchain_sample(thread, evsel,
+                                                  sample, parent,
+                                                  root_al, max_stack);
        if (ret)
                return ret;
 
index e8b7779a0a3f85c05e6d01f086a0b56ea8ec1ff2..6d64cedb9d1e8f6fb255068b27761f6c52735b5e 100644 (file)
@@ -118,9 +118,9 @@ void machines__set_comm_exec(struct machines *machines, bool comm_exec);
 struct machine *machine__new_host(void);
 int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
 void machine__exit(struct machine *machine);
-void machine__delete_dead_threads(struct machine *machine);
 void machine__delete_threads(struct machine *machine);
 void machine__delete(struct machine *machine);
+void machine__remove_thread(struct machine *machine, struct thread *th);
 
 struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
                                           struct addr_location *al);
index 62ca9f2607d557804a0bc260e74a5e5c5dbc32e1..a14f08f416863944527412b82a6b3cfaeda3c603 100644 (file)
@@ -778,3 +778,23 @@ struct map *maps__next(struct map *map)
                return rb_entry(next, struct map, rb_node);
        return NULL;
 }
+
+struct kmap *map__kmap(struct map *map)
+{
+       if (!map->dso || !map->dso->kernel) {
+               pr_err("Internal error: map__kmap with a non-kernel map\n");
+               return NULL;
+       }
+       return (struct kmap *)(map + 1);
+}
+
+struct map_groups *map__kmaps(struct map *map)
+{
+       struct kmap *kmap = map__kmap(map);
+
+       if (!kmap || !kmap->kmaps) {
+               pr_err("Internal error: map__kmaps with a non-kernel map\n");
+               return NULL;
+       }
+       return kmap->kmaps;
+}
index 0e42438b1e593c0e6369186d84cc1ccad76a0093..ec19c59ca38e07deba4a8c2c254ec3a4c71c6c91 100644 (file)
@@ -76,10 +76,8 @@ static inline struct map_groups *map_groups__get(struct map_groups *mg)
 
 void map_groups__put(struct map_groups *mg);
 
-static inline struct kmap *map__kmap(struct map *map)
-{
-       return (struct kmap *)(map + 1);
-}
+struct kmap *map__kmap(struct map *map);
+struct map_groups *map__kmaps(struct map *map);
 
 static inline u64 map__map_ip(struct map *map, u64 ip)
 {
index fd4be94125fbc9007bbb11f1c90d8984f31084d5..52be201b9b2559ffde22a0b81d7b6767bef37173 100644 (file)
@@ -2,7 +2,6 @@
 #include <linux/compiler.h>
 #include <linux/string.h>
 #include "ordered-events.h"
-#include "evlist.h"
 #include "session.h"
 #include "asm/bug.h"
 #include "debug.h"
@@ -131,8 +130,8 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
        return new;
 }
 
-struct ordered_event *
-ordered_events__new(struct ordered_events *oe, u64 timestamp,
+static struct ordered_event *
+ordered_events__new_event(struct ordered_events *oe, u64 timestamp,
                    union perf_event *event)
 {
        struct ordered_event *new;
@@ -153,20 +152,47 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
        free_dup_event(oe, event->event);
 }
 
-static int __ordered_events__flush(struct perf_session *s,
-                                  struct perf_tool *tool)
+int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
+                         struct perf_sample *sample, u64 file_offset)
+{
+       u64 timestamp = sample->time;
+       struct ordered_event *oevent;
+
+       if (!timestamp || timestamp == ~0ULL)
+               return -ETIME;
+
+       if (timestamp < oe->last_flush) {
+               pr_oe_time(timestamp,      "out of order event\n");
+               pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
+                          oe->last_flush_type);
+
+               oe->nr_unordered_events++;
+       }
+
+       oevent = ordered_events__new_event(oe, timestamp, event);
+       if (!oevent) {
+               ordered_events__flush(oe, OE_FLUSH__HALF);
+               oevent = ordered_events__new_event(oe, timestamp, event);
+       }
+
+       if (!oevent)
+               return -ENOMEM;
+
+       oevent->file_offset = file_offset;
+       return 0;
+}
+
+static int __ordered_events__flush(struct ordered_events *oe)
 {
-       struct ordered_events *oe = &s->ordered_events;
        struct list_head *head = &oe->events;
        struct ordered_event *tmp, *iter;
-       struct perf_sample sample;
        u64 limit = oe->next_flush;
        u64 last_ts = oe->last ? oe->last->timestamp : 0ULL;
        bool show_progress = limit == ULLONG_MAX;
        struct ui_progress prog;
        int ret;
 
-       if (!tool->ordered_events || !limit)
+       if (!limit)
                return 0;
 
        if (show_progress)
@@ -178,16 +204,9 @@ static int __ordered_events__flush(struct perf_session *s,
 
                if (iter->timestamp > limit)
                        break;
-
-               ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
+               ret = oe->deliver(oe, iter);
                if (ret)
-                       pr_err("Can't parse sample, err = %d\n", ret);
-               else {
-                       ret = perf_session__deliver_event(s, iter->event, &sample, tool,
-                                                         iter->file_offset);
-                       if (ret)
-                               return ret;
-               }
+                       return ret;
 
                ordered_events__delete(oe, iter);
                oe->last_flush = iter->timestamp;
@@ -204,10 +223,8 @@ static int __ordered_events__flush(struct perf_session *s,
        return 0;
 }
 
-int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
-                         enum oe_flush how)
+int ordered_events__flush(struct ordered_events *oe, enum oe_flush how)
 {
-       struct ordered_events *oe = &s->ordered_events;
        static const char * const str[] = {
                "NONE",
                "FINAL",
@@ -216,6 +233,9 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
        };
        int err;
 
+       if (oe->nr_events == 0)
+               return 0;
+
        switch (how) {
        case OE_FLUSH__FINAL:
                oe->next_flush = ULLONG_MAX;
@@ -248,7 +268,7 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
                   str[how], oe->nr_events);
        pr_oe_time(oe->max_timestamp, "max_timestamp\n");
 
-       err = __ordered_events__flush(s, tool);
+       err = __ordered_events__flush(oe);
 
        if (!err) {
                if (how == OE_FLUSH__ROUND)
@@ -264,13 +284,14 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
        return err;
 }
 
-void ordered_events__init(struct ordered_events *oe)
+void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver)
 {
        INIT_LIST_HEAD(&oe->events);
        INIT_LIST_HEAD(&oe->cache);
        INIT_LIST_HEAD(&oe->to_free);
        oe->max_alloc_size = (u64) -1;
        oe->cur_alloc_size = 0;
+       oe->deliver        = deliver;
 }
 
 void ordered_events__free(struct ordered_events *oe)
index 7b8f9b011f38f34ea196b59f0641f86bf8484281..f403991e3bfd8d7c8a8d892344223316890836be 100644 (file)
@@ -2,9 +2,8 @@
 #define __ORDERED_EVENTS_H
 
 #include <linux/types.h>
-#include "tool.h"
 
-struct perf_session;
+struct perf_sample;
 
 struct ordered_event {
        u64                     timestamp;
@@ -20,6 +19,11 @@ enum oe_flush {
        OE_FLUSH__HALF,
 };
 
+struct ordered_events;
+
+typedef int (*ordered_events__deliver_t)(struct ordered_events *oe,
+                                        struct ordered_event *event);
+
 struct ordered_events {
        u64                     last_flush;
        u64                     next_flush;
@@ -31,18 +35,19 @@ struct ordered_events {
        struct list_head        to_free;
        struct ordered_event    *buffer;
        struct ordered_event    *last;
+       ordered_events__deliver_t deliver;
        int                     buffer_idx;
        unsigned int            nr_events;
        enum oe_flush           last_flush_type;
+       u32                     nr_unordered_events;
        bool                    copy_on_queue;
 };
 
-struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp,
-                                         union perf_event *event);
+int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
+                         struct perf_sample *sample, u64 file_offset);
 void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
-int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
-                         enum oe_flush how);
-void ordered_events__init(struct ordered_events *oe);
+int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
+void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver);
 void ordered_events__free(struct ordered_events *oe);
 
 static inline
index 7f8ec6ce2823c4652e04f11618af1b5cfcb4b952..be0655388b38e4238d69782ee0e9c8357276a574 100644 (file)
 
 #define MAX_NAME_LEN 100
 
-struct event_symbol {
-       const char      *symbol;
-       const char      *alias;
-};
-
 #ifdef PARSER_DEBUG
 extern int parse_events_debug;
 #endif
@@ -39,7 +34,7 @@ static struct perf_pmu_event_symbol *perf_pmu_events_list;
  */
 static int perf_pmu_events_list_num;
 
-static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
+struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
        [PERF_COUNT_HW_CPU_CYCLES] = {
                .symbol = "cpu-cycles",
                .alias  = "cycles",
@@ -82,7 +77,7 @@ static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
        },
 };
 
-static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
+struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
        [PERF_COUNT_SW_CPU_CLOCK] = {
                .symbol = "cpu-clock",
                .alias  = "",
@@ -175,9 +170,6 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
        char evt_path[MAXPATHLEN];
        char dir_path[MAXPATHLEN];
 
-       if (debugfs_valid_mountpoint(tracing_events_path))
-               return NULL;
-
        sys_dir = opendir(tracing_events_path);
        if (!sys_dir)
                return NULL;
@@ -473,12 +465,6 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
 int parse_events_add_tracepoint(struct list_head *list, int *idx,
                                char *sys, char *event)
 {
-       int ret;
-
-       ret = debugfs_valid_mountpoint(tracing_events_path);
-       if (ret)
-               return ret;
-
        if (strpbrk(sys, "*?"))
                return add_tracepoint_multi_sys(list, idx, sys, event);
        else
@@ -723,6 +709,7 @@ struct event_modifier {
        int eh;
        int eH;
        int eG;
+       int eI;
        int precise;
        int exclude_GH;
        int sample_read;
@@ -737,6 +724,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
        int eh = evsel ? evsel->attr.exclude_hv : 0;
        int eH = evsel ? evsel->attr.exclude_host : 0;
        int eG = evsel ? evsel->attr.exclude_guest : 0;
+       int eI = evsel ? evsel->attr.exclude_idle : 0;
        int precise = evsel ? evsel->attr.precise_ip : 0;
        int sample_read = 0;
        int pinned = evsel ? evsel->attr.pinned : 0;
@@ -767,6 +755,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
                        if (!exclude_GH)
                                exclude_GH = eG = eH = 1;
                        eH = 0;
+               } else if (*str == 'I') {
+                       eI = 1;
                } else if (*str == 'p') {
                        precise++;
                        /* use of precise requires exclude_guest */
@@ -800,6 +790,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
        mod->eh = eh;
        mod->eH = eH;
        mod->eG = eG;
+       mod->eI = eI;
        mod->precise = precise;
        mod->exclude_GH = exclude_GH;
        mod->sample_read = sample_read;
@@ -817,7 +808,7 @@ static int check_modifier(char *str)
        char *p = str;
 
        /* The sizeof includes 0 byte as well. */
-       if (strlen(str) > (sizeof("ukhGHpppSD") - 1))
+       if (strlen(str) > (sizeof("ukhGHpppSDI") - 1))
                return -1;
 
        while (*p) {
@@ -853,6 +844,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
                evsel->attr.precise_ip     = mod.precise;
                evsel->attr.exclude_host   = mod.eH;
                evsel->attr.exclude_guest  = mod.eG;
+               evsel->attr.exclude_idle   = mod.eI;
                evsel->exclude_GH          = mod.exclude_GH;
                evsel->sample_read         = mod.sample_read;
 
@@ -1098,6 +1090,14 @@ static const char * const event_type_descriptors[] = {
        "Hardware breakpoint",
 };
 
+static int cmp_string(const void *a, const void *b)
+{
+       const char * const *as = a;
+       const char * const *bs = b;
+
+       return strcmp(*as, *bs);
+}
+
 /*
  * Print the events from <debugfs_mount_point>/tracing/events
  */
@@ -1109,18 +1109,21 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
        struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
        char evt_path[MAXPATHLEN];
        char dir_path[MAXPATHLEN];
-       char sbuf[STRERR_BUFSIZE];
-
-       if (debugfs_valid_mountpoint(tracing_events_path)) {
-               printf("  [ Tracepoints not available: %s ]\n",
-                       strerror_r(errno, sbuf, sizeof(sbuf)));
-               return;
-       }
+       char **evt_list = NULL;
+       unsigned int evt_i = 0, evt_num = 0;
+       bool evt_num_known = false;
 
+restart:
        sys_dir = opendir(tracing_events_path);
        if (!sys_dir)
                return;
 
+       if (evt_num_known) {
+               evt_list = zalloc(sizeof(char *) * evt_num);
+               if (!evt_list)
+                       goto out_close_sys_dir;
+       }
+
        for_each_subsystem(sys_dir, sys_dirent, sys_next) {
                if (subsys_glob != NULL &&
                    !strglobmatch(sys_dirent.d_name, subsys_glob))
@@ -1137,19 +1140,56 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
                            !strglobmatch(evt_dirent.d_name, event_glob))
                                continue;
 
-                       if (name_only) {
-                               printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name);
+                       if (!evt_num_known) {
+                               evt_num++;
                                continue;
                        }
 
                        snprintf(evt_path, MAXPATHLEN, "%s:%s",
                                 sys_dirent.d_name, evt_dirent.d_name);
-                       printf("  %-50s [%s]\n", evt_path,
-                               event_type_descriptors[PERF_TYPE_TRACEPOINT]);
+
+                       evt_list[evt_i] = strdup(evt_path);
+                       if (evt_list[evt_i] == NULL)
+                               goto out_close_evt_dir;
+                       evt_i++;
                }
                closedir(evt_dir);
        }
        closedir(sys_dir);
+
+       if (!evt_num_known) {
+               evt_num_known = true;
+               goto restart;
+       }
+       qsort(evt_list, evt_num, sizeof(char *), cmp_string);
+       evt_i = 0;
+       while (evt_i < evt_num) {
+               if (name_only) {
+                       printf("%s ", evt_list[evt_i++]);
+                       continue;
+               }
+               printf("  %-50s [%s]\n", evt_list[evt_i++],
+                               event_type_descriptors[PERF_TYPE_TRACEPOINT]);
+       }
+       if (evt_num)
+               printf("\n");
+
+out_free:
+       evt_num = evt_i;
+       for (evt_i = 0; evt_i < evt_num; evt_i++)
+               zfree(&evt_list[evt_i]);
+       zfree(&evt_list);
+       return;
+
+out_close_evt_dir:
+       closedir(evt_dir);
+out_close_sys_dir:
+       closedir(sys_dir);
+
+       printf("FATAL: not enough memory to print %s\n",
+                       event_type_descriptors[PERF_TYPE_TRACEPOINT]);
+       if (evt_list)
+               goto out_free;
 }
 
 /*
@@ -1163,9 +1203,6 @@ int is_valid_tracepoint(const char *event_string)
        char evt_path[MAXPATHLEN];
        char dir_path[MAXPATHLEN];
 
-       if (debugfs_valid_mountpoint(tracing_events_path))
-               return 0;
-
        sys_dir = opendir(tracing_events_path);
        if (!sys_dir)
                return 0;
@@ -1233,38 +1270,19 @@ static bool is_event_supported(u8 type, unsigned config)
        return ret;
 }
 
-static void __print_events_type(u8 type, struct event_symbol *syms,
-                               unsigned max)
-{
-       char name[64];
-       unsigned i;
-
-       for (i = 0; i < max ; i++, syms++) {
-               if (!is_event_supported(type, i))
-                       continue;
-
-               if (strlen(syms->alias))
-                       snprintf(name, sizeof(name),  "%s OR %s",
-                                syms->symbol, syms->alias);
-               else
-                       snprintf(name, sizeof(name), "%s", syms->symbol);
-
-               printf("  %-50s [%s]\n", name, event_type_descriptors[type]);
-       }
-}
-
-void print_events_type(u8 type)
-{
-       if (type == PERF_TYPE_SOFTWARE)
-               __print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX);
-       else
-               __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
-}
-
 int print_hwcache_events(const char *event_glob, bool name_only)
 {
-       unsigned int type, op, i, printed = 0;
+       unsigned int type, op, i, evt_i = 0, evt_num = 0;
        char name[64];
+       char **evt_list = NULL;
+       bool evt_num_known = false;
+
+restart:
+       if (evt_num_known) {
+               evt_list = zalloc(sizeof(char *) * evt_num);
+               if (!evt_list)
+                       goto out_enomem;
+       }
 
        for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
                for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
@@ -1282,27 +1300,66 @@ int print_hwcache_events(const char *event_glob, bool name_only)
                                                        type | (op << 8) | (i << 16)))
                                        continue;
 
-                               if (name_only)
-                                       printf("%s ", name);
-                               else
-                                       printf("  %-50s [%s]\n", name,
-                                              event_type_descriptors[PERF_TYPE_HW_CACHE]);
-                               ++printed;
+                               if (!evt_num_known) {
+                                       evt_num++;
+                                       continue;
+                               }
+
+                               evt_list[evt_i] = strdup(name);
+                               if (evt_list[evt_i] == NULL)
+                                       goto out_enomem;
+                               evt_i++;
                        }
                }
        }
 
-       if (printed)
+       if (!evt_num_known) {
+               evt_num_known = true;
+               goto restart;
+       }
+       qsort(evt_list, evt_num, sizeof(char *), cmp_string);
+       evt_i = 0;
+       while (evt_i < evt_num) {
+               if (name_only) {
+                       printf("%s ", evt_list[evt_i++]);
+                       continue;
+               }
+               printf("  %-50s [%s]\n", evt_list[evt_i++],
+                               event_type_descriptors[PERF_TYPE_HW_CACHE]);
+       }
+       if (evt_num)
                printf("\n");
-       return printed;
+
+out_free:
+       evt_num = evt_i;
+       for (evt_i = 0; evt_i < evt_num; evt_i++)
+               zfree(&evt_list[evt_i]);
+       zfree(&evt_list);
+       return evt_num;
+
+out_enomem:
+       printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]);
+       if (evt_list)
+               goto out_free;
+       return evt_num;
 }
 
-static void print_symbol_events(const char *event_glob, unsigned type,
+void print_symbol_events(const char *event_glob, unsigned type,
                                struct event_symbol *syms, unsigned max,
                                bool name_only)
 {
-       unsigned i, printed = 0;
+       unsigned int i, evt_i = 0, evt_num = 0;
        char name[MAX_NAME_LEN];
+       char **evt_list = NULL;
+       bool evt_num_known = false;
+
+restart:
+       if (evt_num_known) {
+               evt_list = zalloc(sizeof(char *) * evt_num);
+               if (!evt_list)
+                       goto out_enomem;
+               syms -= max;
+       }
 
        for (i = 0; i < max; i++, syms++) {
 
@@ -1314,23 +1371,49 @@ static void print_symbol_events(const char *event_glob, unsigned type,
                if (!is_event_supported(type, i))
                        continue;
 
-               if (name_only) {
-                       printf("%s ", syms->symbol);
+               if (!evt_num_known) {
+                       evt_num++;
                        continue;
                }
 
-               if (strlen(syms->alias))
+               if (!name_only && strlen(syms->alias))
                        snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
                else
                        strncpy(name, syms->symbol, MAX_NAME_LEN);
 
-               printf("  %-50s [%s]\n", name, event_type_descriptors[type]);
-
-               printed++;
+               evt_list[evt_i] = strdup(name);
+               if (evt_list[evt_i] == NULL)
+                       goto out_enomem;
+               evt_i++;
        }
 
-       if (printed)
+       if (!evt_num_known) {
+               evt_num_known = true;
+               goto restart;
+       }
+       qsort(evt_list, evt_num, sizeof(char *), cmp_string);
+       evt_i = 0;
+       while (evt_i < evt_num) {
+               if (name_only) {
+                       printf("%s ", evt_list[evt_i++]);
+                       continue;
+               }
+               printf("  %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
+       }
+       if (evt_num)
                printf("\n");
+
+out_free:
+       evt_num = evt_i;
+       for (evt_i = 0; evt_i < evt_num; evt_i++)
+               zfree(&evt_list[evt_i]);
+       zfree(&evt_list);
+       return;
+
+out_enomem:
+       printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
+       if (evt_list)
+               goto out_free;
 }
 
 /*
@@ -1338,11 +1421,6 @@ static void print_symbol_events(const char *event_glob, unsigned type,
  */
 void print_events(const char *event_glob, bool name_only)
 {
-       if (!name_only) {
-               printf("\n");
-               printf("List of pre-defined events (to be used in -e):\n");
-       }
-
        print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
                            event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
 
index ff6e1fa4111ec7dca08c4e90da7ef14984e602cb..52a2dda4f954a7682d43376bd3ac2ee91d127447 100644 (file)
@@ -116,12 +116,21 @@ void parse_events_update_lists(struct list_head *list_event,
 void parse_events_error(void *data, void *scanner, char const *msg);
 
 void print_events(const char *event_glob, bool name_only);
-void print_events_type(u8 type);
+
+struct event_symbol {
+       const char      *symbol;
+       const char      *alias;
+};
+extern struct event_symbol event_symbols_hw[];
+extern struct event_symbol event_symbols_sw[];
+void print_symbol_events(const char *event_glob, unsigned type,
+                               struct event_symbol *syms, unsigned max,
+                               bool name_only);
 void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
                             bool name_only);
 int print_hwcache_events(const char *event_glob, bool name_only);
 extern int is_valid_tracepoint(const char *event_string);
 
-extern int valid_debugfs_mount(const char *debugfs);
+int valid_event_mount(const char *eventfs);
 
 #endif /* __PERF_PARSE_EVENTS_H */
index 94eacb6c1ef71e46d0de1bdf2df002c29bbbe118..8895cf3132ab242c078c70c6f7713f52030c9f6a 100644 (file)
@@ -101,7 +101,7 @@ num_raw_hex [a-fA-F0-9]+
 name           [a-zA-Z_*?][a-zA-Z0-9_*?]*
 name_minus     [a-zA-Z_*?][a-zA-Z0-9\-_*?]*
 /* If you add a modifier you need to update check_modifier() */
-modifier_event [ukhpGHSD]+
+modifier_event [ukhpGHSDI]+
 modifier_bp    [rwx]{1,3}
 
 %%
index 4a015f77e2b5bb6ff7f6ab3e8c22ec42bf1b8b67..01626be2a8eb8043135591fcca302213af501e0d 100644 (file)
@@ -37,6 +37,7 @@ static int get_value(struct parse_opt_ctx_t *p,
 {
        const char *s, *arg = NULL;
        const int unset = flags & OPT_UNSET;
+       int err;
 
        if (unset && p->opt)
                return opterror(opt, "takes no value", flags);
@@ -114,13 +115,29 @@ static int get_value(struct parse_opt_ctx_t *p,
                return 0;
 
        case OPTION_STRING:
+               err = 0;
                if (unset)
                        *(const char **)opt->value = NULL;
                else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
                        *(const char **)opt->value = (const char *)opt->defval;
                else
-                       return get_arg(p, opt, flags, (const char **)opt->value);
-               return 0;
+                       err = get_arg(p, opt, flags, (const char **)opt->value);
+
+               /* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */
+               if (opt->flags & PARSE_OPT_NOEMPTY) {
+                       const char *val = *(const char **)opt->value;
+
+                       if (!val)
+                               return err;
+
+                       /* Similar to unset if we are given an empty string. */
+                       if (val[0] == '\0') {
+                               *(const char **)opt->value = NULL;
+                               return 0;
+                       }
+               }
+
+               return err;
 
        case OPTION_CALLBACK:
                if (unset)
@@ -505,13 +522,18 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
                break;
        case PARSE_OPT_LIST_OPTS:
                while (options->type != OPTION_END) {
-                       printf("--%s ", options->long_name);
+                       if (options->long_name)
+                               printf("--%s ", options->long_name);
                        options++;
                }
+               putchar('\n');
                exit(130);
        case PARSE_OPT_LIST_SUBCMDS:
-               for (int i = 0; subcommands[i]; i++)
-                       printf("%s ", subcommands[i]);
+               if (subcommands) {
+                       for (int i = 0; subcommands[i]; i++)
+                               printf("%s ", subcommands[i]);
+               }
+               putchar('\n');
                exit(130);
        default: /* PARSE_OPT_UNKNOWN */
                if (ctx.argv[0][1] == '-') {
index 97b153fb4999099315003da8c981bd5bbfa23838..59561fd86278276040fcde6c075b334008e13d67 100644 (file)
@@ -40,6 +40,7 @@ enum parse_opt_option_flags {
        PARSE_OPT_LASTARG_DEFAULT = 16,
        PARSE_OPT_DISABLED = 32,
        PARSE_OPT_EXCLUSIVE = 64,
+       PARSE_OPT_NOEMPTY  = 128,
 };
 
 struct option;
@@ -122,6 +123,7 @@ struct option {
 #define OPT_LONG(s, l, v, h)        { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
 #define OPT_U64(s, l, v, h)         { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
 #define OPT_STRING(s, l, v, a, h)   { .type = OPTION_STRING,  .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) }
+#define OPT_STRING_NOEMPTY(s, l, v, a, h)   { .type = OPTION_STRING,  .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}
 #define OPT_DATE(s, l, v, h) \
        { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
 #define OPT_CALLBACK(s, l, v, a, h, f) \
index 919937eb0be2b643e93bfe7fc983e7131074deeb..30545ce2c712d699a00b13b2bbcc63d4f2fc5ee3 100644 (file)
@@ -41,6 +41,7 @@
 #include "symbol.h"
 #include "thread.h"
 #include <api/fs/debugfs.h>
+#include <api/fs/tracefs.h>
 #include "trace-event.h"       /* For __maybe_unused */
 #include "probe-event.h"
 #include "probe-finder.h"
@@ -79,6 +80,7 @@ static int init_symbol_maps(bool user_only)
        int ret;
 
        symbol_conf.sort_by_name = true;
+       symbol_conf.allow_aliases = true;
        ret = symbol__init(NULL);
        if (ret < 0) {
                pr_debug("Failed to init symbol map.\n");
@@ -133,6 +135,8 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
                return NULL;
 
        kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]);
+       if (!kmap)
+               return NULL;
        return kmap->ref_reloc_sym;
 }
 
@@ -150,7 +154,7 @@ static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc)
                sym = __find_kernel_function_by_name(name, &map);
                if (sym)
                        return map->unmap_ip(map, sym->start) -
-                               (reloc) ? 0 : map->reloc;
+                               ((reloc) ? 0 : map->reloc);
        }
        return 0;
 }
@@ -177,6 +181,25 @@ static struct map *kernel_get_module_map(const char *module)
        return NULL;
 }
 
+static struct map *get_target_map(const char *target, bool user)
+{
+       /* Init maps of given executable or kernel */
+       if (user)
+               return dso__new_map(target);
+       else
+               return kernel_get_module_map(target);
+}
+
+static void put_target_map(struct map *map, bool user)
+{
+       if (map && user) {
+               /* Only the user map needs to be released */
+               dso__delete(map->dso);
+               map__delete(map);
+       }
+}
+
+
 static struct dso *kernel_get_module_dso(const char *module)
 {
        struct dso *dso;
@@ -248,6 +271,13 @@ out:
        return ret;
 }
 
+static void clear_perf_probe_point(struct perf_probe_point *pp)
+{
+       free(pp->file);
+       free(pp->function);
+       free(pp->lazy_line);
+}
+
 static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
 {
        int i;
@@ -257,6 +287,103 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
 }
 
 #ifdef HAVE_DWARF_SUPPORT
+/*
+ * Some binaries like glibc have special symbols which are on the symbol
+ * table, but not in the debuginfo. If we can find the address of the
+ * symbol from map, we can translate the address back to the probe point.
+ */
+static int find_alternative_probe_point(struct debuginfo *dinfo,
+                                       struct perf_probe_point *pp,
+                                       struct perf_probe_point *result,
+                                       const char *target, bool uprobes)
+{
+       struct map *map = NULL;
+       struct symbol *sym;
+       u64 address = 0;
+       int ret = -ENOENT;
+
+       /* This can work only for function-name based one */
+       if (!pp->function || pp->file)
+               return -ENOTSUP;
+
+       map = get_target_map(target, uprobes);
+       if (!map)
+               return -EINVAL;
+
+       /* Find the address of given function */
+       map__for_each_symbol_by_name(map, pp->function, sym) {
+               if (uprobes)
+                       address = sym->start;
+               else
+                       address = map->unmap_ip(map, sym->start);
+               break;
+       }
+       if (!address) {
+               ret = -ENOENT;
+               goto out;
+       }
+       pr_debug("Symbol %s address found : %" PRIx64 "\n",
+                       pp->function, address);
+
+       ret = debuginfo__find_probe_point(dinfo, (unsigned long)address,
+                                         result);
+       if (ret <= 0)
+               ret = (!ret) ? -ENOENT : ret;
+       else {
+               result->offset += pp->offset;
+               result->line += pp->line;
+               ret = 0;
+       }
+
+out:
+       put_target_map(map, uprobes);
+       return ret;
+
+}
+
+static int get_alternative_probe_event(struct debuginfo *dinfo,
+                                      struct perf_probe_event *pev,
+                                      struct perf_probe_point *tmp,
+                                      const char *target)
+{
+       int ret;
+
+       memcpy(tmp, &pev->point, sizeof(*tmp));
+       memset(&pev->point, 0, sizeof(pev->point));
+       ret = find_alternative_probe_point(dinfo, tmp, &pev->point,
+                                          target, pev->uprobes);
+       if (ret < 0)
+               memcpy(&pev->point, tmp, sizeof(*tmp));
+
+       return ret;
+}
+
+static int get_alternative_line_range(struct debuginfo *dinfo,
+                                     struct line_range *lr,
+                                     const char *target, bool user)
+{
+       struct perf_probe_point pp = { .function = lr->function,
+                                      .file = lr->file,
+                                      .line = lr->start };
+       struct perf_probe_point result;
+       int ret, len = 0;
+
+       memset(&result, 0, sizeof(result));
+
+       if (lr->end != INT_MAX)
+               len = lr->end - lr->start;
+       ret = find_alternative_probe_point(dinfo, &pp, &result,
+                                          target, user);
+       if (!ret) {
+               lr->function = result.function;
+               lr->file = result.file;
+               lr->start = result.line;
+               if (lr->end != INT_MAX)
+                       lr->end = lr->start + len;
+               clear_perf_probe_point(&pp);
+       }
+       return ret;
+}
 
 /* Open new debuginfo of given module */
 static struct debuginfo *open_debuginfo(const char *module, bool silent)
@@ -465,6 +592,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
                                          int max_tevs, const char *target)
 {
        bool need_dwarf = perf_probe_event_need_dwarf(pev);
+       struct perf_probe_point tmp;
        struct debuginfo *dinfo;
        int ntevs, ret = 0;
 
@@ -481,6 +609,20 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
        /* Searching trace events corresponding to a probe event */
        ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
 
+       if (ntevs == 0) {  /* Not found, retry with an alternative */
+               ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
+               if (!ret) {
+                       ntevs = debuginfo__find_trace_events(dinfo, pev,
+                                                            tevs, max_tevs);
+                       /*
+                        * Write back to the original probe_event for
+                        * setting appropriate (user given) event name
+                        */
+                       clear_perf_probe_point(&pev->point);
+                       memcpy(&pev->point, &tmp, sizeof(tmp));
+               }
+       }
+
        debuginfo__delete(dinfo);
 
        if (ntevs > 0) {        /* Succeeded to find trace events */
@@ -495,11 +637,9 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
        }
 
        if (ntevs == 0) {       /* No error but failed to find probe point. */
-               pr_warning("Probe point '%s' not found in debuginfo.\n",
+               pr_warning("Probe point '%s' not found.\n",
                           synthesize_perf_probe_point(&pev->point));
-               if (need_dwarf)
-                       return -ENOENT;
-               return 0;
+               return -ENOENT;
        }
        /* Error path : ntevs < 0 */
        pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
@@ -532,7 +672,7 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
                else {
                        if (access(raw_path, R_OK) == 0) {
                                *new_path = strdup(raw_path);
-                               return 0;
+                               return *new_path ? 0 : -ENOMEM;
                        } else
                                return -errno;
                }
@@ -548,9 +688,11 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
                if (access(*new_path, R_OK) == 0)
                        return 0;
 
-               if (!symbol_conf.source_prefix)
+               if (!symbol_conf.source_prefix) {
                        /* In case of searching comp_dir, don't retry */
+                       zfree(new_path);
                        return -errno;
+               }
 
                switch (errno) {
                case ENAMETOOLONG:
@@ -622,7 +764,8 @@ static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
  * Show line-range always requires debuginfo to find source file and
  * line number.
  */
-static int __show_line_range(struct line_range *lr, const char *module)
+static int __show_line_range(struct line_range *lr, const char *module,
+                            bool user)
 {
        int l = 1;
        struct int_node *ln;
@@ -638,6 +781,11 @@ static int __show_line_range(struct line_range *lr, const char *module)
                return -ENOENT;
 
        ret = debuginfo__find_line_range(dinfo, lr);
+       if (!ret) {     /* Not found, retry with an alternative */
+               ret = get_alternative_line_range(dinfo, lr, module, user);
+               if (!ret)
+                       ret = debuginfo__find_line_range(dinfo, lr);
+       }
        debuginfo__delete(dinfo);
        if (ret == 0 || ret == -ENOENT) {
                pr_warning("Specified source line is not found.\n");
@@ -650,7 +798,11 @@ static int __show_line_range(struct line_range *lr, const char *module)
        /* Convert source file path */
        tmp = lr->path;
        ret = get_real_path(tmp, lr->comp_dir, &lr->path);
-       free(tmp);      /* Free old path */
+
+       /* Free old path when new path is assigned */
+       if (tmp != lr->path)
+               free(tmp);
+
        if (ret < 0) {
                pr_warning("Failed to find source file path.\n");
                return ret;
@@ -707,7 +859,7 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
        ret = init_symbol_maps(user);
        if (ret < 0)
                return ret;
-       ret = __show_line_range(lr, module);
+       ret = __show_line_range(lr, module, user);
        exit_symbol_maps();
 
        return ret;
@@ -716,12 +868,13 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
 static int show_available_vars_at(struct debuginfo *dinfo,
                                  struct perf_probe_event *pev,
                                  int max_vls, struct strfilter *_filter,
-                                 bool externs)
+                                 bool externs, const char *target)
 {
        char *buf;
        int ret, i, nvars;
        struct str_node *node;
        struct variable_list *vls = NULL, *vl;
+       struct perf_probe_point tmp;
        const char *var;
 
        buf = synthesize_perf_probe_point(&pev->point);
@@ -731,6 +884,15 @@ static int show_available_vars_at(struct debuginfo *dinfo,
 
        ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
                                                max_vls, externs);
+       if (!ret) {  /* Not found, retry with an alternative */
+               ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
+               if (!ret) {
+                       ret = debuginfo__find_available_vars_at(dinfo, pev,
+                                               &vls, max_vls, externs);
+                       /* Release the old probe_point */
+                       clear_perf_probe_point(&tmp);
+               }
+       }
        if (ret <= 0) {
                if (ret == 0 || ret == -ENOENT) {
                        pr_err("Failed to find the address of %s\n", buf);
@@ -793,7 +955,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
 
        for (i = 0; i < npevs && ret >= 0; i++)
                ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
-                                            externs);
+                                            externs, module);
 
        debuginfo__delete(dinfo);
 out:
@@ -1739,15 +1901,13 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
 
 void clear_perf_probe_event(struct perf_probe_event *pev)
 {
-       struct perf_probe_point *pp = &pev->point;
        struct perf_probe_arg_field *field, *next;
        int i;
 
        free(pev->event);
        free(pev->group);
-       free(pp->file);
-       free(pp->function);
-       free(pp->lazy_line);
+       free(pev->target);
+       clear_perf_probe_point(&pev->point);
 
        for (i = 0; i < pev->nargs; i++) {
                free(pev->args[i].name);
@@ -1805,7 +1965,7 @@ static void print_open_warning(int err, bool is_kprobe)
                           " - please rebuild kernel with %s.\n",
                           is_kprobe ? 'k' : 'u', config);
        } else if (err == -ENOTSUP)
-               pr_warning("Debugfs is not mounted.\n");
+               pr_warning("Tracefs or debugfs is not mounted.\n");
        else
                pr_warning("Failed to open %cprobe_events: %s\n",
                           is_kprobe ? 'k' : 'u',
@@ -1816,7 +1976,7 @@ static void print_both_open_warning(int kerr, int uerr)
 {
        /* Both kprobes and uprobes are disabled, warn it. */
        if (kerr == -ENOTSUP && uerr == -ENOTSUP)
-               pr_warning("Debugfs is not mounted.\n");
+               pr_warning("Tracefs or debugfs is not mounted.\n");
        else if (kerr == -ENOENT && uerr == -ENOENT)
                pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
                           "or/and CONFIG_UPROBE_EVENTS.\n");
@@ -1833,13 +1993,20 @@ static int open_probe_events(const char *trace_file, bool readwrite)
 {
        char buf[PATH_MAX];
        const char *__debugfs;
+       const char *tracing_dir = "";
        int ret;
 
-       __debugfs = debugfs_find_mountpoint();
-       if (__debugfs == NULL)
-               return -ENOTSUP;
+       __debugfs = tracefs_find_mountpoint();
+       if (__debugfs == NULL) {
+               tracing_dir = "tracing/";
+
+               __debugfs = debugfs_find_mountpoint();
+               if (__debugfs == NULL)
+                       return -ENOTSUP;
+       }
 
-       ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file);
+       ret = e_snprintf(buf, PATH_MAX, "%s/%s%s",
+                        __debugfs, tracing_dir, trace_file);
        if (ret >= 0) {
                pr_debug("Opening %s write=%d\n", buf, readwrite);
                if (readwrite && !probe_event_dry_run)
@@ -1855,12 +2022,12 @@ static int open_probe_events(const char *trace_file, bool readwrite)
 
 static int open_kprobe_events(bool readwrite)
 {
-       return open_probe_events("tracing/kprobe_events", readwrite);
+       return open_probe_events("kprobe_events", readwrite);
 }
 
 static int open_uprobe_events(bool readwrite)
 {
-       return open_probe_events("tracing/uprobe_events", readwrite);
+       return open_probe_events("uprobe_events", readwrite);
 }
 
 /* Get raw string list of current kprobe_events  or uprobe_events */
@@ -1895,6 +2062,95 @@ static struct strlist *get_probe_trace_command_rawlist(int fd)
        return sl;
 }
 
+struct kprobe_blacklist_node {
+       struct list_head list;
+       unsigned long start;
+       unsigned long end;
+       char *symbol;
+};
+
+static void kprobe_blacklist__delete(struct list_head *blacklist)
+{
+       struct kprobe_blacklist_node *node;
+
+       while (!list_empty(blacklist)) {
+               node = list_first_entry(blacklist,
+                                       struct kprobe_blacklist_node, list);
+               list_del(&node->list);
+               free(node->symbol);
+               free(node);
+       }
+}
+
+static int kprobe_blacklist__load(struct list_head *blacklist)
+{
+       struct kprobe_blacklist_node *node;
+       const char *__debugfs = debugfs_find_mountpoint();
+       char buf[PATH_MAX], *p;
+       FILE *fp;
+       int ret;
+
+       if (__debugfs == NULL)
+               return -ENOTSUP;
+
+       ret = e_snprintf(buf, PATH_MAX, "%s/kprobes/blacklist", __debugfs);
+       if (ret < 0)
+               return ret;
+
+       fp = fopen(buf, "r");
+       if (!fp)
+               return -errno;
+
+       ret = 0;
+       while (fgets(buf, PATH_MAX, fp)) {
+               node = zalloc(sizeof(*node));
+               if (!node) {
+                       ret = -ENOMEM;
+                       break;
+               }
+               INIT_LIST_HEAD(&node->list);
+               list_add_tail(&node->list, blacklist);
+               if (sscanf(buf, "0x%lx-0x%lx", &node->start, &node->end) != 2) {
+                       ret = -EINVAL;
+                       break;
+               }
+               p = strchr(buf, '\t');
+               if (p) {
+                       p++;
+                       if (p[strlen(p) - 1] == '\n')
+                               p[strlen(p) - 1] = '\0';
+               } else
+                       p = (char *)"unknown";
+               node->symbol = strdup(p);
+               if (!node->symbol) {
+                       ret = -ENOMEM;
+                       break;
+               }
+               pr_debug2("Blacklist: 0x%lx-0x%lx, %s\n",
+                         node->start, node->end, node->symbol);
+               ret++;
+       }
+       if (ret < 0)
+               kprobe_blacklist__delete(blacklist);
+       fclose(fp);
+
+       return ret;
+}
+
+static struct kprobe_blacklist_node *
+kprobe_blacklist__find_by_address(struct list_head *blacklist,
+                                 unsigned long address)
+{
+       struct kprobe_blacklist_node *node;
+
+       list_for_each_entry(node, blacklist, list) {
+               if (node->start <= address && address <= node->end)
+                       return node;
+       }
+
+       return NULL;
+}
+
 /* Show an event */
 static int show_perf_probe_event(struct perf_probe_event *pev,
                                 const char *module)
@@ -2100,6 +2356,27 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
        return ret;
 }
 
+/* Warn if the current kernel's uprobe implementation is old */
+static void warn_uprobe_event_compat(struct probe_trace_event *tev)
+{
+       int i;
+       char *buf = synthesize_probe_trace_command(tev);
+
+       /* Old uprobe event doesn't support memory dereference */
+       if (!tev->uprobes || tev->nargs == 0 || !buf)
+               goto out;
+
+       for (i = 0; i < tev->nargs; i++)
+               if (strglobmatch(tev->args[i].value, "[$@+-]*")) {
+                       pr_warning("Please upgrade your kernel to at least "
+                                  "3.14 to have access to feature %s\n",
+                                  tev->args[i].value);
+                       break;
+               }
+out:
+       free(buf);
+}
+
 static int __add_probe_trace_events(struct perf_probe_event *pev,
                                     struct probe_trace_event *tevs,
                                     int ntevs, bool allow_suffix)
@@ -2109,6 +2386,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
        char buf[64];
        const char *event, *group;
        struct strlist *namelist;
+       LIST_HEAD(blacklist);
+       struct kprobe_blacklist_node *node;
 
        if (pev->uprobes)
                fd = open_uprobe_events(true);
@@ -2126,11 +2405,25 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
                pr_debug("Failed to get current event list.\n");
                return -EIO;
        }
+       /* Get kprobe blacklist if exists */
+       if (!pev->uprobes) {
+               ret = kprobe_blacklist__load(&blacklist);
+               if (ret < 0)
+                       pr_debug("No kprobe blacklist support, ignored\n");
+       }
 
        ret = 0;
        pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
        for (i = 0; i < ntevs; i++) {
                tev = &tevs[i];
+               /* Ensure that the address is NOT blacklisted */
+               node = kprobe_blacklist__find_by_address(&blacklist,
+                                                        tev->point.address);
+               if (node) {
+                       pr_warning("Warning: Skipped probing on blacklisted function: %s\n", node->symbol);
+                       continue;
+               }
+
                if (pev->event)
                        event = pev->event;
                else
@@ -2180,14 +2473,18 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
                 */
                allow_suffix = true;
        }
+       if (ret == -EINVAL && pev->uprobes)
+               warn_uprobe_event_compat(tev);
 
-       if (ret >= 0) {
+       /* Note that it is possible to skip all events because of blacklist */
+       if (ret >= 0 && tev->event) {
                /* Show how to use the event. */
                pr_info("\nYou can now use it in all perf tools, such as:\n\n");
                pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
                         tev->event);
        }
 
+       kprobe_blacklist__delete(&blacklist);
        strlist__delete(namelist);
        close(fd);
        return ret;
@@ -2199,8 +2496,7 @@ static int find_probe_functions(struct map *map, char *name)
        struct symbol *sym;
 
        map__for_each_symbol_by_name(map, name, sym) {
-               if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL)
-                       found++;
+               found++;
        }
 
        return found;
@@ -2218,7 +2514,6 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
                                            int max_tevs, const char *target)
 {
        struct map *map = NULL;
-       struct kmap *kmap = NULL;
        struct ref_reloc_sym *reloc_sym = NULL;
        struct symbol *sym;
        struct probe_trace_event *tev;
@@ -2227,11 +2522,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
        int num_matched_functions;
        int ret, i;
 
-       /* Init maps of given executable or kernel */
-       if (pev->uprobes)
-               map = dso__new_map(target);
-       else
-               map = kernel_get_module_map(target);
+       map = get_target_map(target, pev->uprobes);
        if (!map) {
                ret = -EINVAL;
                goto out;
@@ -2255,8 +2546,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
        }
 
        if (!pev->uprobes && !pp->retprobe) {
-               kmap = map__kmap(map);
-               reloc_sym = kmap->ref_reloc_sym;
+               reloc_sym = kernel_get_ref_reloc_sym();
                if (!reloc_sym) {
                        pr_warning("Relocated base symbol is not found!\n");
                        ret = -EINVAL;
@@ -2324,11 +2614,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
        }
 
 out:
-       if (map && pev->uprobes) {
-               /* Only when using uprobe(exec) map needs to be released */
-               dso__delete(map->dso);
-               map__delete(map);
-       }
+       put_target_map(map, pev->uprobes);
        return ret;
 
 nomem_out:
@@ -2369,7 +2655,7 @@ struct __event_package {
 };
 
 int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
-                         int max_tevs, const char *target, bool force_add)
+                         int max_tevs, bool force_add)
 {
        int i, j, ret;
        struct __event_package *pkgs;
@@ -2393,7 +2679,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
                ret  = convert_to_probe_trace_events(pkgs[i].pev,
                                                     &pkgs[i].tevs,
                                                     max_tevs,
-                                                    target);
+                                                    pkgs[i].pev->target);
                if (ret < 0)
                        goto end;
                pkgs[i].ntevs = ret;
@@ -2568,8 +2854,7 @@ static struct strfilter *available_func_filter;
 static int filter_available_functions(struct map *map __maybe_unused,
                                      struct symbol *sym)
 {
-       if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) &&
-           strfilter__compare(available_func_filter, sym->name))
+       if (strfilter__compare(available_func_filter, sym->name))
                return 0;
        return 1;
 }
index e01e9943139ff3b828ab8820aad9a5add4f34376..d6b783447be95d6b8764187f05692e0559eed371 100644 (file)
@@ -73,7 +73,8 @@ struct perf_probe_event {
        char                    *group; /* Group name */
        struct perf_probe_point point;  /* Probe point */
        int                     nargs;  /* Number of arguments */
-       bool                    uprobes;
+       bool                    uprobes;        /* Uprobe event flag */
+       char                    *target;        /* Target binary */
        struct perf_probe_arg   *args;  /* Arguments */
 };
 
@@ -124,8 +125,7 @@ extern int line_range__init(struct line_range *lr);
 extern const char *kernel_get_module_path(const char *module);
 
 extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
-                                int max_probe_points, const char *module,
-                                bool force_add);
+                                int max_probe_points, bool force_add);
 extern int del_perf_probe_events(struct strlist *dellist);
 extern int show_perf_probe_events(void);
 extern int show_line_range(struct line_range *lr, const char *module,
index b5247d777f0e9348d1b77e3f33813c5b7713bce4..e3074230f236ef13b077586bdd3678bde6525513 100644 (file)
@@ -456,11 +456,12 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
                        return -EINVAL;
                }
                if (field->name[0] == '[') {
-                       pr_err("Semantic error: %s is not a pointor"
+                       pr_err("Semantic error: %s is not a pointer"
                               " nor array.\n", varname);
                        return -EINVAL;
                }
-               if (field->ref) {
+               /* While prcessing unnamed field, we don't care about this */
+               if (field->ref && dwarf_diename(vr_die)) {
                        pr_err("Semantic error: %s must be referred by '.'\n",
                               field->name);
                        return -EINVAL;
@@ -491,6 +492,11 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
        }
        ref->offset += (long)offs;
 
+       /* If this member is unnamed, we need to reuse this field */
+       if (!dwarf_diename(die_mem))
+               return convert_variable_fields(die_mem, varname, field,
+                                               &ref, die_mem);
+
 next:
        /* Converting next field */
        if (field->next)
@@ -915,17 +921,13 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
                dwarf_decl_line(sp_die, &pf->lno);
                pf->lno += pp->line;
                param->retval = find_probe_point_by_line(pf);
-       } else if (!dwarf_func_inline(sp_die)) {
+       } else if (die_is_func_instance(sp_die)) {
+               /* Instances always have the entry address */
+               dwarf_entrypc(sp_die, &pf->addr);
                /* Real function */
                if (pp->lazy_line)
                        param->retval = find_probe_point_lazy(sp_die, pf);
                else {
-                       if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
-                               pr_warning("Failed to get entry address of "
-                                          "%s.\n", dwarf_diename(sp_die));
-                               param->retval = -ENOENT;
-                               return DWARF_CB_ABORT;
-                       }
                        pf->addr += pp->offset;
                        /* TODO: Check the address in this function */
                        param->retval = call_probe_finder(sp_die, pf);
@@ -1349,11 +1351,8 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
        const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
        int baseline = 0, lineno = 0, ret = 0;
 
-       /* Adjust address with bias */
-       addr += dbg->bias;
-
        /* Find cu die */
-       if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) {
+       if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
                pr_warning("Failed to find debug information for address %lx\n",
                           addr);
                ret = -EINVAL;
@@ -1536,7 +1535,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
                pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
                lr->start = lf->lno_s;
                lr->end = lf->lno_e;
-               if (dwarf_func_inline(sp_die))
+               if (!die_is_func_instance(sp_die))
                        param->retval = die_walk_instances(sp_die,
                                                line_range_inline_cb, lf);
                else
index 6c6a6953fa93fa5b4fe92229df7613bbe996bec9..4d28624a1ecaa6c6dc5d70fb2f0d43e91c56d0cf 100644 (file)
@@ -17,6 +17,5 @@ util/xyarray.c
 util/cgroup.c
 util/rblist.c
 util/strlist.c
-../lib/api/fs/fs.c
 util/trace-event.c
 ../../lib/rbtree.c
diff --git a/tools/perf/util/scripting-engines/Build b/tools/perf/util/scripting-engines/Build
new file mode 100644 (file)
index 0000000..6516e22
--- /dev/null
@@ -0,0 +1,6 @@
+libperf-$(CONFIG_LIBPERL)   += trace-event-perl.o
+libperf-$(CONFIG_LIBPYTHON) += trace-event-python.o
+
+CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default
+
+CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow
index 22ebc46226e7ffe05793fadea8527584c616cb01..430b5d27828ec6715880debf7c795f5bf871e3e0 100644 (file)
@@ -214,6 +214,11 @@ static void define_event_symbols(struct event_format *event,
                define_event_symbols(event, ev_name, args->hex.field);
                define_event_symbols(event, ev_name, args->hex.size);
                break;
+       case PRINT_INT_ARRAY:
+               define_event_symbols(event, ev_name, args->int_array.field);
+               define_event_symbols(event, ev_name, args->int_array.count);
+               define_event_symbols(event, ev_name, args->int_array.el_size);
+               break;
        case PRINT_BSTRING:
        case PRINT_DYNAMIC_ARRAY:
        case PRINT_STRING:
@@ -355,10 +360,9 @@ static void perl_process_event_generic(union perf_event *event,
 static void perl_process_event(union perf_event *event,
                               struct perf_sample *sample,
                               struct perf_evsel *evsel,
-                              struct thread *thread,
-                              struct addr_location *al __maybe_unused)
+                              struct addr_location *al)
 {
-       perl_process_tracepoint(sample, evsel, thread);
+       perl_process_tracepoint(sample, evsel, al->thread);
        perl_process_event_generic(event, sample, evsel);
 }
 
index 0c815a40a6e86bbedf16e3893e2c00c5827419e0..5544b8cdd1ee4b777338b4767df30b080041a33c 100644 (file)
@@ -231,6 +231,11 @@ static void define_event_symbols(struct event_format *event,
                define_event_symbols(event, ev_name, args->hex.field);
                define_event_symbols(event, ev_name, args->hex.size);
                break;
+       case PRINT_INT_ARRAY:
+               define_event_symbols(event, ev_name, args->int_array.field);
+               define_event_symbols(event, ev_name, args->int_array.count);
+               define_event_symbols(event, ev_name, args->int_array.el_size);
+               break;
        case PRINT_STRING:
                break;
        case PRINT_TYPE:
@@ -376,7 +381,6 @@ exit:
 
 static void python_process_tracepoint(struct perf_sample *sample,
                                      struct perf_evsel *evsel,
-                                     struct thread *thread,
                                      struct addr_location *al)
 {
        struct event_format *event = evsel->tp_format;
@@ -390,7 +394,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
        int cpu = sample->cpu;
        void *data = sample->raw_data;
        unsigned long long nsecs = sample->time;
-       const char *comm = thread__comm_str(thread);
+       const char *comm = thread__comm_str(al->thread);
 
        t = PyTuple_New(MAX_FIELDS);
        if (!t)
@@ -675,7 +679,7 @@ static int python_export_sample(struct db_export *dbe,
        tuple_set_u64(t, 0, es->db_id);
        tuple_set_u64(t, 1, es->evsel->db_id);
        tuple_set_u64(t, 2, es->al->machine->db_id);
-       tuple_set_u64(t, 3, es->thread->db_id);
+       tuple_set_u64(t, 3, es->al->thread->db_id);
        tuple_set_u64(t, 4, es->comm_db_id);
        tuple_set_u64(t, 5, es->dso_db_id);
        tuple_set_u64(t, 6, es->sym_db_id);
@@ -761,7 +765,6 @@ static int python_process_call_return(struct call_return *cr, void *data)
 
 static void python_process_general_event(struct perf_sample *sample,
                                         struct perf_evsel *evsel,
-                                        struct thread *thread,
                                         struct addr_location *al)
 {
        PyObject *handler, *t, *dict, *callchain, *dict_sample;
@@ -811,7 +814,7 @@ static void python_process_general_event(struct perf_sample *sample,
        pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
                        (const char *)sample->raw_data, sample->raw_size));
        pydict_set_item_string_decref(dict, "comm",
-                       PyString_FromString(thread__comm_str(thread)));
+                       PyString_FromString(thread__comm_str(al->thread)));
        if (al->map) {
                pydict_set_item_string_decref(dict, "dso",
                        PyString_FromString(al->map->dso->name));
@@ -838,22 +841,20 @@ exit:
 static void python_process_event(union perf_event *event,
                                 struct perf_sample *sample,
                                 struct perf_evsel *evsel,
-                                struct thread *thread,
                                 struct addr_location *al)
 {
        struct tables *tables = &tables_global;
 
        switch (evsel->attr.type) {
        case PERF_TYPE_TRACEPOINT:
-               python_process_tracepoint(sample, evsel, thread, al);
+               python_process_tracepoint(sample, evsel, al);
                break;
        /* Reserve for future process_hw/sw/raw APIs */
        default:
                if (tables->db_export_mode)
-                       db_export__sample(&tables->dbe, event, sample, evsel,
-                                         thread, al);
+                       db_export__sample(&tables->dbe, event, sample, evsel, al);
                else
-                       python_process_general_event(sample, evsel, thread, al);
+                       python_process_general_event(sample, evsel, al);
        }
 }
 
index 0baf75f12b7c4a663544cb6f65b6c001c3ae890e..0c74012575ac925648c3f2eb350d7fb95bd154ce 100644 (file)
 #include "perf_regs.h"
 #include "asm/bug.h"
 
+static int machines__deliver_event(struct machines *machines,
+                                  struct perf_evlist *evlist,
+                                  union perf_event *event,
+                                  struct perf_sample *sample,
+                                  struct perf_tool *tool, u64 file_offset);
+
 static int perf_session__open(struct perf_session *session)
 {
        struct perf_data_file *file = session->file;
@@ -86,6 +92,23 @@ static void perf_session__set_comm_exec(struct perf_session *session)
        machines__set_comm_exec(&session->machines, comm_exec);
 }
 
+static int ordered_events__deliver_event(struct ordered_events *oe,
+                                        struct ordered_event *event)
+{
+       struct perf_sample sample;
+       struct perf_session *session = container_of(oe, struct perf_session,
+                                                   ordered_events);
+       int ret = perf_evlist__parse_sample(session->evlist, event->event, &sample);
+
+       if (ret) {
+               pr_err("Can't parse sample, err = %d\n", ret);
+               return ret;
+       }
+
+       return machines__deliver_event(&session->machines, session->evlist, event->event,
+                                      &sample, session->tool, event->file_offset);
+}
+
 struct perf_session *perf_session__new(struct perf_data_file *file,
                                       bool repipe, struct perf_tool *tool)
 {
@@ -95,8 +118,9 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
                goto out;
 
        session->repipe = repipe;
-       ordered_events__init(&session->ordered_events);
+       session->tool   = tool;
        machines__init(&session->machines);
+       ordered_events__init(&session->ordered_events, ordered_events__deliver_event);
 
        if (file) {
                if (perf_data_file__open(file))
@@ -138,11 +162,6 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
        return NULL;
 }
 
-static void perf_session__delete_dead_threads(struct perf_session *session)
-{
-       machine__delete_dead_threads(&session->machines.host);
-}
-
 static void perf_session__delete_threads(struct perf_session *session)
 {
        machine__delete_threads(&session->machines.host);
@@ -167,7 +186,6 @@ static void perf_session_env__delete(struct perf_session_env *env)
 void perf_session__delete(struct perf_session *session)
 {
        perf_session__destroy_kernel_maps(session);
-       perf_session__delete_dead_threads(session);
        perf_session__delete_threads(session);
        perf_session_env__delete(&session->header.env);
        machines__exit(&session->machines);
@@ -215,10 +233,17 @@ static int process_event_stub(struct perf_tool *tool __maybe_unused,
        return 0;
 }
 
+static int process_build_id_stub(struct perf_tool *tool __maybe_unused,
+                                union perf_event *event __maybe_unused,
+                                struct perf_session *session __maybe_unused)
+{
+       dump_printf(": unhandled!\n");
+       return 0;
+}
+
 static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
                                       union perf_event *event __maybe_unused,
-                                      struct perf_session *perf_session
-                                      __maybe_unused)
+                                      struct ordered_events *oe __maybe_unused)
 {
        dump_printf(": unhandled!\n");
        return 0;
@@ -226,7 +251,7 @@ static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
 
 static int process_finished_round(struct perf_tool *tool,
                                  union perf_event *event,
-                                 struct perf_session *session);
+                                 struct ordered_events *oe);
 
 static int process_id_index_stub(struct perf_tool *tool __maybe_unused,
                                 union perf_event *event __maybe_unused,
@@ -264,7 +289,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
        if (tool->tracing_data == NULL)
                tool->tracing_data = process_event_synth_tracing_data_stub;
        if (tool->build_id == NULL)
-               tool->build_id = process_finished_round_stub;
+               tool->build_id = process_build_id_stub;
        if (tool->finished_round == NULL) {
                if (tool->ordered_events)
                        tool->finished_round = process_finished_round;
@@ -514,54 +539,80 @@ static perf_event__swap_op perf_event__swap_ops[] = {
  *      Flush every events below timestamp 7
  *      etc...
  */
-static int process_finished_round(struct perf_tool *tool,
+static int process_finished_round(struct perf_tool *tool __maybe_unused,
                                  union perf_event *event __maybe_unused,
-                                 struct perf_session *session)
+                                 struct ordered_events *oe)
 {
-       return ordered_events__flush(session, tool, OE_FLUSH__ROUND);
+       return ordered_events__flush(oe, OE_FLUSH__ROUND);
 }
 
-int perf_session_queue_event(struct perf_session *s, union perf_event *event,
-                            struct perf_tool *tool, struct perf_sample *sample,
-                            u64 file_offset)
+int perf_session__queue_event(struct perf_session *s, union perf_event *event,
+                             struct perf_sample *sample, u64 file_offset)
 {
-       struct ordered_events *oe = &s->ordered_events;
-       u64 timestamp = sample->time;
-       struct ordered_event *new;
-
-       if (!timestamp || timestamp == ~0ULL)
-               return -ETIME;
+       return ordered_events__queue(&s->ordered_events, event, sample, file_offset);
+}
 
-       if (timestamp < oe->last_flush) {
-               pr_oe_time(timestamp,      "out of order event\n");
-               pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
-                          oe->last_flush_type);
+static void callchain__lbr_callstack_printf(struct perf_sample *sample)
+{
+       struct ip_callchain *callchain = sample->callchain;
+       struct branch_stack *lbr_stack = sample->branch_stack;
+       u64 kernel_callchain_nr = callchain->nr;
+       unsigned int i;
 
-               s->stats.nr_unordered_events++;
+       for (i = 0; i < kernel_callchain_nr; i++) {
+               if (callchain->ips[i] == PERF_CONTEXT_USER)
+                       break;
        }
 
-       new = ordered_events__new(oe, timestamp, event);
-       if (!new) {
-               ordered_events__flush(s, tool, OE_FLUSH__HALF);
-               new = ordered_events__new(oe, timestamp, event);
-       }
+       if ((i != kernel_callchain_nr) && lbr_stack->nr) {
+               u64 total_nr;
+               /*
+                * LBR callstack can only get user call chain,
+                * i is kernel call chain number,
+                * 1 is PERF_CONTEXT_USER.
+                *
+                * The user call chain is stored in LBR registers.
+                * LBR are pair registers. The caller is stored
+                * in "from" register, while the callee is stored
+                * in "to" register.
+                * For example, there is a call stack
+                * "A"->"B"->"C"->"D".
+                * The LBR registers will recorde like
+                * "C"->"D", "B"->"C", "A"->"B".
+                * So only the first "to" register and all "from"
+                * registers are needed to construct the whole stack.
+                */
+               total_nr = i + 1 + lbr_stack->nr + 1;
+               kernel_callchain_nr = i + 1;
 
-       if (!new)
-               return -ENOMEM;
+               printf("... LBR call chain: nr:%" PRIu64 "\n", total_nr);
 
-       new->file_offset = file_offset;
-       return 0;
+               for (i = 0; i < kernel_callchain_nr; i++)
+                       printf("..... %2d: %016" PRIx64 "\n",
+                              i, callchain->ips[i]);
+
+               printf("..... %2d: %016" PRIx64 "\n",
+                      (int)(kernel_callchain_nr), lbr_stack->entries[0].to);
+               for (i = 0; i < lbr_stack->nr; i++)
+                       printf("..... %2d: %016" PRIx64 "\n",
+                              (int)(i + kernel_callchain_nr + 1), lbr_stack->entries[i].from);
+       }
 }
 
-static void callchain__printf(struct perf_sample *sample)
+static void callchain__printf(struct perf_evsel *evsel,
+                             struct perf_sample *sample)
 {
        unsigned int i;
+       struct ip_callchain *callchain = sample->callchain;
+
+       if (has_branch_callstack(evsel))
+               callchain__lbr_callstack_printf(sample);
 
-       printf("... chain: nr:%" PRIu64 "\n", sample->callchain->nr);
+       printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr);
 
-       for (i = 0; i < sample->callchain->nr; i++)
+       for (i = 0; i < callchain->nr; i++)
                printf("..... %2d: %016" PRIx64 "\n",
-                      i, sample->callchain->ips[i]);
+                      i, callchain->ips[i]);
 }
 
 static void branch_stack__printf(struct perf_sample *sample)
@@ -636,14 +687,14 @@ static void stack_user__printf(struct stack_dump *dump)
               dump->size, dump->offset);
 }
 
-static void perf_session__print_tstamp(struct perf_session *session,
+static void perf_evlist__print_tstamp(struct perf_evlist *evlist,
                                       union perf_event *event,
                                       struct perf_sample *sample)
 {
-       u64 sample_type = __perf_evlist__combined_sample_type(session->evlist);
+       u64 sample_type = __perf_evlist__combined_sample_type(evlist);
 
        if (event->header.type != PERF_RECORD_SAMPLE &&
-           !perf_evlist__sample_id_all(session->evlist)) {
+           !perf_evlist__sample_id_all(evlist)) {
                fputs("-1 -1 ", stdout);
                return;
        }
@@ -685,7 +736,7 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format)
                        sample->read.one.id, sample->read.one.value);
 }
 
-static void dump_event(struct perf_session *session, union perf_event *event,
+static void dump_event(struct perf_evlist *evlist, union perf_event *event,
                       u64 file_offset, struct perf_sample *sample)
 {
        if (!dump_trace)
@@ -697,7 +748,7 @@ static void dump_event(struct perf_session *session, union perf_event *event,
        trace_event(event);
 
        if (sample)
-               perf_session__print_tstamp(session, event, sample);
+               perf_evlist__print_tstamp(evlist, event, sample);
 
        printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset,
               event->header.size, perf_event__name(event->header.type));
@@ -718,9 +769,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
        sample_type = evsel->attr.sample_type;
 
        if (sample_type & PERF_SAMPLE_CALLCHAIN)
-               callchain__printf(sample);
+               callchain__printf(evsel, sample);
 
-       if (sample_type & PERF_SAMPLE_BRANCH_STACK)
+       if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !has_branch_callstack(evsel))
                branch_stack__printf(sample);
 
        if (sample_type & PERF_SAMPLE_REGS_USER)
@@ -745,8 +796,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
                sample_read__printf(sample, evsel->attr.read_format);
 }
 
-static struct machine *
-       perf_session__find_machine_for_cpumode(struct perf_session *session,
+static struct machine *machines__find_for_cpumode(struct machines *machines,
                                               union perf_event *event,
                                               struct perf_sample *sample)
 {
@@ -764,26 +814,24 @@ static struct machine *
                else
                        pid = sample->pid;
 
-               machine = perf_session__find_machine(session, pid);
+               machine = machines__find(machines, pid);
                if (!machine)
-                       machine = perf_session__findnew_machine(session,
-                                               DEFAULT_GUEST_KERNEL_ID);
+                       machine = machines__find(machines, DEFAULT_GUEST_KERNEL_ID);
                return machine;
        }
 
-       return &session->machines.host;
+       return &machines->host;
 }
 
-static int deliver_sample_value(struct perf_session *session,
+static int deliver_sample_value(struct perf_evlist *evlist,
                                struct perf_tool *tool,
                                union perf_event *event,
                                struct perf_sample *sample,
                                struct sample_read_value *v,
                                struct machine *machine)
 {
-       struct perf_sample_id *sid;
+       struct perf_sample_id *sid = perf_evlist__id2sid(evlist, v->id);
 
-       sid = perf_evlist__id2sid(session->evlist, v->id);
        if (sid) {
                sample->id     = v->id;
                sample->period = v->value - sid->period;
@@ -791,14 +839,14 @@ static int deliver_sample_value(struct perf_session *session,
        }
 
        if (!sid || sid->evsel == NULL) {
-               ++session->stats.nr_unknown_id;
+               ++evlist->stats.nr_unknown_id;
                return 0;
        }
 
        return tool->sample(tool, event, sample, sid->evsel, machine);
 }
 
-static int deliver_sample_group(struct perf_session *session,
+static int deliver_sample_group(struct perf_evlist *evlist,
                                struct perf_tool *tool,
                                union  perf_event *event,
                                struct perf_sample *sample,
@@ -808,7 +856,7 @@ static int deliver_sample_group(struct perf_session *session,
        u64 i;
 
        for (i = 0; i < sample->read.group.nr; i++) {
-               ret = deliver_sample_value(session, tool, event, sample,
+               ret = deliver_sample_value(evlist, tool, event, sample,
                                           &sample->read.group.values[i],
                                           machine);
                if (ret)
@@ -819,7 +867,7 @@ static int deliver_sample_group(struct perf_session *session,
 }
 
 static int
-perf_session__deliver_sample(struct perf_session *session,
+ perf_evlist__deliver_sample(struct perf_evlist *evlist,
                             struct perf_tool *tool,
                             union  perf_event *event,
                             struct perf_sample *sample,
@@ -836,41 +884,40 @@ perf_session__deliver_sample(struct perf_session *session,
 
        /* For PERF_SAMPLE_READ we have either single or group mode. */
        if (read_format & PERF_FORMAT_GROUP)
-               return deliver_sample_group(session, tool, event, sample,
+               return deliver_sample_group(evlist, tool, event, sample,
                                            machine);
        else
-               return deliver_sample_value(session, tool, event, sample,
+               return deliver_sample_value(evlist, tool, event, sample,
                                            &sample->read.one, machine);
 }
 
-int perf_session__deliver_event(struct perf_session *session,
-                               union perf_event *event,
-                               struct perf_sample *sample,
-                               struct perf_tool *tool, u64 file_offset)
+static int machines__deliver_event(struct machines *machines,
+                                  struct perf_evlist *evlist,
+                                  union perf_event *event,
+                                  struct perf_sample *sample,
+                                  struct perf_tool *tool, u64 file_offset)
 {
        struct perf_evsel *evsel;
        struct machine *machine;
 
-       dump_event(session, event, file_offset, sample);
+       dump_event(evlist, event, file_offset, sample);
 
-       evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+       evsel = perf_evlist__id2evsel(evlist, sample->id);
 
-       machine = perf_session__find_machine_for_cpumode(session, event,
-                                                        sample);
+       machine = machines__find_for_cpumode(machines, event, sample);
 
        switch (event->header.type) {
        case PERF_RECORD_SAMPLE:
                dump_sample(evsel, event, sample);
                if (evsel == NULL) {
-                       ++session->stats.nr_unknown_id;
+                       ++evlist->stats.nr_unknown_id;
                        return 0;
                }
                if (machine == NULL) {
-                       ++session->stats.nr_unprocessable_samples;
+                       ++evlist->stats.nr_unprocessable_samples;
                        return 0;
                }
-               return perf_session__deliver_sample(session, tool, event,
-                                                   sample, evsel, machine);
+               return perf_evlist__deliver_sample(evlist, tool, event, sample, evsel, machine);
        case PERF_RECORD_MMAP:
                return tool->mmap(tool, event, sample, machine);
        case PERF_RECORD_MMAP2:
@@ -883,7 +930,7 @@ int perf_session__deliver_event(struct perf_session *session,
                return tool->exit(tool, event, sample, machine);
        case PERF_RECORD_LOST:
                if (tool->lost == perf_event__process_lost)
-                       session->stats.total_lost += event->lost.lost;
+                       evlist->stats.total_lost += event->lost.lost;
                return tool->lost(tool, event, sample, machine);
        case PERF_RECORD_READ:
                return tool->read(tool, event, sample, evsel, machine);
@@ -892,20 +939,21 @@ int perf_session__deliver_event(struct perf_session *session,
        case PERF_RECORD_UNTHROTTLE:
                return tool->unthrottle(tool, event, sample, machine);
        default:
-               ++session->stats.nr_unknown_events;
+               ++evlist->stats.nr_unknown_events;
                return -1;
        }
 }
 
 static s64 perf_session__process_user_event(struct perf_session *session,
                                            union perf_event *event,
-                                           struct perf_tool *tool,
                                            u64 file_offset)
 {
+       struct ordered_events *oe = &session->ordered_events;
+       struct perf_tool *tool = session->tool;
        int fd = perf_data_file__fd(session->file);
        int err;
 
-       dump_event(session, event, file_offset, NULL);
+       dump_event(session->evlist, event, file_offset, NULL);
 
        /* These events are processed right away */
        switch (event->header.type) {
@@ -929,7 +977,7 @@ static s64 perf_session__process_user_event(struct perf_session *session,
        case PERF_RECORD_HEADER_BUILD_ID:
                return tool->build_id(tool, event, session);
        case PERF_RECORD_FINISHED_ROUND:
-               return tool->finished_round(tool, event, session);
+               return tool->finished_round(tool, event, oe);
        case PERF_RECORD_ID_INDEX:
                return tool->id_index(tool, event, session);
        default:
@@ -939,15 +987,17 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 
 int perf_session__deliver_synth_event(struct perf_session *session,
                                      union perf_event *event,
-                                     struct perf_sample *sample,
-                                     struct perf_tool *tool)
+                                     struct perf_sample *sample)
 {
-       events_stats__inc(&session->stats, event->header.type);
+       struct perf_evlist *evlist = session->evlist;
+       struct perf_tool *tool = session->tool;
+
+       events_stats__inc(&evlist->stats, event->header.type);
 
        if (event->header.type >= PERF_RECORD_USER_TYPE_START)
-               return perf_session__process_user_event(session, event, tool, 0);
+               return perf_session__process_user_event(session, event, 0);
 
-       return perf_session__deliver_event(session, event, sample, tool, 0);
+       return machines__deliver_event(&session->machines, evlist, event, sample, tool, 0);
 }
 
 static void event_swap(union perf_event *event, bool sample_id_all)
@@ -1015,40 +1065,39 @@ out_parse_sample:
 }
 
 static s64 perf_session__process_event(struct perf_session *session,
-                                      union perf_event *event,
-                                      struct perf_tool *tool,
-                                      u64 file_offset)
+                                      union perf_event *event, u64 file_offset)
 {
+       struct perf_evlist *evlist = session->evlist;
+       struct perf_tool *tool = session->tool;
        struct perf_sample sample;
        int ret;
 
        if (session->header.needs_swap)
-               event_swap(event, perf_evlist__sample_id_all(session->evlist));
+               event_swap(event, perf_evlist__sample_id_all(evlist));
 
        if (event->header.type >= PERF_RECORD_HEADER_MAX)
                return -EINVAL;
 
-       events_stats__inc(&session->stats, event->header.type);
+       events_stats__inc(&evlist->stats, event->header.type);
 
        if (event->header.type >= PERF_RECORD_USER_TYPE_START)
-               return perf_session__process_user_event(session, event, tool, file_offset);
+               return perf_session__process_user_event(session, event, file_offset);
 
        /*
         * For all kernel events we get the sample data
         */
-       ret = perf_evlist__parse_sample(session->evlist, event, &sample);
+       ret = perf_evlist__parse_sample(evlist, event, &sample);
        if (ret)
                return ret;
 
        if (tool->ordered_events) {
-               ret = perf_session_queue_event(session, event, tool, &sample,
-                                              file_offset);
+               ret = perf_session__queue_event(session, event, &sample, file_offset);
                if (ret != -ETIME)
                        return ret;
        }
 
-       return perf_session__deliver_event(session, event, &sample, tool,
-                                          file_offset);
+       return machines__deliver_event(&session->machines, evlist, event,
+                                      &sample, tool, file_offset);
 }
 
 void perf_event_header__bswap(struct perf_event_header *hdr)
@@ -1076,54 +1125,57 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
        return thread;
 }
 
-static void perf_session__warn_about_errors(const struct perf_session *session,
-                                           const struct perf_tool *tool)
+static void perf_session__warn_about_errors(const struct perf_session *session)
 {
-       if (tool->lost == perf_event__process_lost &&
-           session->stats.nr_events[PERF_RECORD_LOST] != 0) {
+       const struct events_stats *stats = &session->evlist->stats;
+       const struct ordered_events *oe = &session->ordered_events;
+
+       if (session->tool->lost == perf_event__process_lost &&
+           stats->nr_events[PERF_RECORD_LOST] != 0) {
                ui__warning("Processed %d events and lost %d chunks!\n\n"
                            "Check IO/CPU overload!\n\n",
-                           session->stats.nr_events[0],
-                           session->stats.nr_events[PERF_RECORD_LOST]);
+                           stats->nr_events[0],
+                           stats->nr_events[PERF_RECORD_LOST]);
        }
 
-       if (session->stats.nr_unknown_events != 0) {
+       if (stats->nr_unknown_events != 0) {
                ui__warning("Found %u unknown events!\n\n"
                            "Is this an older tool processing a perf.data "
                            "file generated by a more recent tool?\n\n"
                            "If that is not the case, consider "
                            "reporting to linux-kernel@vger.kernel.org.\n\n",
-                           session->stats.nr_unknown_events);
+                           stats->nr_unknown_events);
        }
 
-       if (session->stats.nr_unknown_id != 0) {
+       if (stats->nr_unknown_id != 0) {
                ui__warning("%u samples with id not present in the header\n",
-                           session->stats.nr_unknown_id);
+                           stats->nr_unknown_id);
        }
 
-       if (session->stats.nr_invalid_chains != 0) {
-               ui__warning("Found invalid callchains!\n\n"
-                           "%u out of %u events were discarded for this reason.\n\n"
-                           "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
-                           session->stats.nr_invalid_chains,
-                           session->stats.nr_events[PERF_RECORD_SAMPLE]);
-       }
+       if (stats->nr_invalid_chains != 0) {
+               ui__warning("Found invalid callchains!\n\n"
+                           "%u out of %u events were discarded for this reason.\n\n"
+                           "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
+                           stats->nr_invalid_chains,
+                           stats->nr_events[PERF_RECORD_SAMPLE]);
+       }
 
-       if (session->stats.nr_unprocessable_samples != 0) {
+       if (stats->nr_unprocessable_samples != 0) {
                ui__warning("%u unprocessable samples recorded.\n"
                            "Do you have a KVM guest running and not using 'perf kvm'?\n",
-                           session->stats.nr_unprocessable_samples);
+                           stats->nr_unprocessable_samples);
        }
 
-       if (session->stats.nr_unordered_events != 0)
-               ui__warning("%u out of order events recorded.\n", session->stats.nr_unordered_events);
+       if (oe->nr_unordered_events != 0)
+               ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
 }
 
 volatile int session_done;
 
-static int __perf_session__process_pipe_events(struct perf_session *session,
-                                              struct perf_tool *tool)
+static int __perf_session__process_pipe_events(struct perf_session *session)
 {
+       struct ordered_events *oe = &session->ordered_events;
+       struct perf_tool *tool = session->tool;
        int fd = perf_data_file__fd(session->file);
        union perf_event *event;
        uint32_t size, cur_size = 0;
@@ -1187,7 +1239,7 @@ more:
                }
        }
 
-       if ((skip = perf_session__process_event(session, event, tool, head)) < 0) {
+       if ((skip = perf_session__process_event(session, event, head)) < 0) {
                pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
                       head, event->header.size, event->header.type);
                err = -EINVAL;
@@ -1203,10 +1255,10 @@ more:
                goto more;
 done:
        /* do the final flush for ordered samples */
-       err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
+       err = ordered_events__flush(oe, OE_FLUSH__FINAL);
 out_err:
        free(buf);
-       perf_session__warn_about_errors(session, tool);
+       perf_session__warn_about_errors(session);
        ordered_events__free(&session->ordered_events);
        return err;
 }
@@ -1253,8 +1305,10 @@ fetch_mmaped_event(struct perf_session *session,
 
 static int __perf_session__process_events(struct perf_session *session,
                                          u64 data_offset, u64 data_size,
-                                         u64 file_size, struct perf_tool *tool)
+                                         u64 file_size)
 {
+       struct ordered_events *oe = &session->ordered_events;
+       struct perf_tool *tool = session->tool;
        int fd = perf_data_file__fd(session->file);
        u64 head, page_offset, file_offset, file_pos, size;
        int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1323,8 +1377,7 @@ more:
        size = event->header.size;
 
        if (size < sizeof(struct perf_event_header) ||
-           (skip = perf_session__process_event(session, event, tool, file_pos))
-                                                                       < 0) {
+           (skip = perf_session__process_event(session, event, file_pos)) < 0) {
                pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
                       file_offset + head, event->header.size,
                       event->header.type);
@@ -1348,17 +1401,16 @@ more:
 
 out:
        /* do the final flush for ordered samples */
-       err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
+       err = ordered_events__flush(oe, OE_FLUSH__FINAL);
 out_err:
        ui_progress__finish();
-       perf_session__warn_about_errors(session, tool);
+       perf_session__warn_about_errors(session);
        ordered_events__free(&session->ordered_events);
        session->one_mmap = false;
        return err;
 }
 
-int perf_session__process_events(struct perf_session *session,
-                                struct perf_tool *tool)
+int perf_session__process_events(struct perf_session *session)
 {
        u64 size = perf_data_file__size(session->file);
        int err;
@@ -1369,10 +1421,9 @@ int perf_session__process_events(struct perf_session *session,
        if (!perf_data_file__is_pipe(session->file))
                err = __perf_session__process_events(session,
                                                     session->header.data_offset,
-                                                    session->header.data_size,
-                                                    size, tool);
+                                                    session->header.data_size, size);
        else
-               err = __perf_session__process_pipe_events(session, tool);
+               err = __perf_session__process_pipe_events(session);
 
        return err;
 }
@@ -1415,6 +1466,9 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
 
        for (i = 0; i < MAP__NR_TYPES; ++i) {
                struct kmap *kmap = map__kmap(maps[i]);
+
+               if (!kmap)
+                       continue;
                kmap->ref_reloc_sym = ref;
        }
 
@@ -1436,7 +1490,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
 {
        size_t ret = fprintf(fp, "Aggregated stats:\n");
 
-       ret += events_stats__fprintf(&session->stats, fp);
+       ret += events_stats__fprintf(&session->evlist->stats, fp);
        return ret;
 }
 
index 6d663dc76404395ad6231fcf93bd881b9978fab8..d5fa7b7916ef40dd5216e533a5ce04bfdfc8a7d2 100644 (file)
@@ -20,13 +20,13 @@ struct perf_session {
        struct machines         machines;
        struct perf_evlist      *evlist;
        struct trace_event      tevent;
-       struct events_stats     stats;
        bool                    repipe;
        bool                    one_mmap;
        void                    *one_mmap_addr;
        u64                     one_mmap_offset;
        struct ordered_events   ordered_events;
        struct perf_data_file   *file;
+       struct perf_tool        *tool;
 };
 
 #define PRINT_IP_OPT_IP                (1<<0)
@@ -49,20 +49,13 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
                             union perf_event **event_ptr,
                             struct perf_sample *sample);
 
-int perf_session__process_events(struct perf_session *session,
-                                struct perf_tool *tool);
+int perf_session__process_events(struct perf_session *session);
 
-int perf_session_queue_event(struct perf_session *s, union perf_event *event,
-                            struct perf_tool *tool, struct perf_sample *sample,
-                            u64 file_offset);
+int perf_session__queue_event(struct perf_session *s, union perf_event *event,
+                             struct perf_sample *sample, u64 file_offset);
 
 void perf_tool__fill_defaults(struct perf_tool *tool);
 
-int perf_session__deliver_event(struct perf_session *session,
-                               union perf_event *event,
-                               struct perf_sample *sample,
-                               struct perf_tool *tool, u64 file_offset);
-
 int perf_session__resolve_callchain(struct perf_session *session,
                                    struct perf_evsel *evsel,
                                    struct thread *thread,
@@ -126,8 +119,7 @@ extern volatile int session_done;
 
 int perf_session__deliver_synth_event(struct perf_session *session,
                                      union perf_event *event,
-                                     struct perf_sample *sample,
-                                     struct perf_tool *tool);
+                                     struct perf_sample *sample);
 
 int perf_event__process_id_index(struct perf_tool *tool,
                                 union perf_event *event,
index d0aee4b9dfd482ea36c5a50c73e97c1ff9738a95..1833103768cb99fbdbb92ea8910b08488fd2aac3 100644 (file)
@@ -25,7 +25,7 @@ cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter'
 build_lib = getenv('PYTHON_EXTBUILD_LIB')
 build_tmp = getenv('PYTHON_EXTBUILD_TMP')
 libtraceevent = getenv('LIBTRACEEVENT')
-libapikfs = getenv('LIBAPIKFS')
+libapikfs = getenv('LIBAPI')
 
 ext_sources = [f.strip() for f in file('util/python-ext-sources')
                                if len(f.strip()) > 0 and f[0] != '#']
index 7a39c1ed8d37c16cfe24d9dc0a908166658903a4..4593f36ecc4c651bef30112b008979b336894e0c 100644 (file)
@@ -1463,6 +1463,15 @@ int sort_dimension__add(const char *tok)
                        sort__has_parent = 1;
                } else if (sd->entry == &sort_sym) {
                        sort__has_sym = 1;
+                       /*
+                        * perf diff displays the performance difference amongst
+                        * two or more perf.data files. Those files could come
+                        * from different binaries. So we should not compare
+                        * their ips, but the name of symbol.
+                        */
+                       if (sort__mode == SORT_MODE__DIFF)
+                               sd->entry->se_collapse = sort__sym_sort;
+
                } else if (sd->entry == &sort_dso) {
                        sort__has_dso = 1;
                }
index c03e4ff8beffe083ab19769d91a7e57d6f70d126..846036a921dc9152623fd5e70671b5f196e4b3de 100644 (file)
@@ -44,6 +44,7 @@ extern struct sort_entry sort_dso_to;
 extern struct sort_entry sort_sym_from;
 extern struct sort_entry sort_sym_to;
 extern enum sort_type sort__first_dimension;
+extern const char default_mem_sort_order[];
 
 struct he_stat {
        u64                     period;
@@ -102,7 +103,6 @@ struct hist_entry {
 
        bool                    init_have_children;
        char                    level;
-       bool                    used;
        u8                      filtered;
        char                    *srcline;
        struct symbol           *parent;
index 33b7a2aef71322ab88b93e675c070bfc4a7c7da7..a7ab6063e0389488a420680db46b96743366c1c2 100644 (file)
@@ -74,6 +74,10 @@ static inline uint8_t elf_sym__type(const GElf_Sym *sym)
        return GELF_ST_TYPE(sym->st_info);
 }
 
+#ifndef STT_GNU_IFUNC
+#define STT_GNU_IFUNC 10
+#endif
+
 static inline int elf_sym__is_function(const GElf_Sym *sym)
 {
        return (elf_sym__type(sym) == STT_FUNC ||
@@ -575,32 +579,37 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)
 static int decompress_kmodule(struct dso *dso, const char *name,
                              enum dso_binary_type type)
 {
-       int fd;
-       const char *ext = strrchr(name, '.');
+       int fd = -1;
        char tmpbuf[] = "/tmp/perf-kmod-XXXXXX";
+       struct kmod_path m;
 
        if (type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP &&
            type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP &&
            type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
                return -1;
 
-       if (!ext || !is_supported_compression(ext + 1)) {
-               ext = strrchr(dso->name, '.');
-               if (!ext || !is_supported_compression(ext + 1))
-                       return -1;
-       }
+       if (type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
+               name = dso->long_name;
 
-       fd = mkstemp(tmpbuf);
-       if (fd < 0)
+       if (kmod_path__parse_ext(&m, name) || !m.comp)
                return -1;
 
-       if (!decompress_to_file(ext + 1, name, fd)) {
+       fd = mkstemp(tmpbuf);
+       if (fd < 0) {
+               dso->load_errno = errno;
+               goto out;
+       }
+
+       if (!decompress_to_file(m.ext, name, fd)) {
+               dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
                close(fd);
                fd = -1;
        }
 
        unlink(tmpbuf);
 
+out:
+       free(m.ext);
        return fd;
 }
 
@@ -629,37 +638,49 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
        Elf *elf;
        int fd;
 
-       if (dso__needs_decompress(dso))
+       if (dso__needs_decompress(dso)) {
                fd = decompress_kmodule(dso, name, type);
-       else
+               if (fd < 0)
+                       return -1;
+       } else {
                fd = open(name, O_RDONLY);
-
-       if (fd < 0)
-               return -1;
+               if (fd < 0) {
+                       dso->load_errno = errno;
+                       return -1;
+               }
+       }
 
        elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
        if (elf == NULL) {
                pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
+               dso->load_errno = DSO_LOAD_ERRNO__INVALID_ELF;
                goto out_close;
        }
 
        if (gelf_getehdr(elf, &ehdr) == NULL) {
+               dso->load_errno = DSO_LOAD_ERRNO__INVALID_ELF;
                pr_debug("%s: cannot get elf header.\n", __func__);
                goto out_elf_end;
        }
 
-       if (dso__swap_init(dso, ehdr.e_ident[EI_DATA]))
+       if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) {
+               dso->load_errno = DSO_LOAD_ERRNO__INTERNAL_ERROR;
                goto out_elf_end;
+       }
 
        /* Always reject images with a mismatched build-id: */
        if (dso->has_build_id) {
                u8 build_id[BUILD_ID_SIZE];
 
-               if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
+               if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) {
+                       dso->load_errno = DSO_LOAD_ERRNO__CANNOT_READ_BUILDID;
                        goto out_elf_end;
+               }
 
-               if (!dso__build_id_equal(dso, build_id))
+               if (!dso__build_id_equal(dso, build_id)) {
+                       dso->load_errno = DSO_LOAD_ERRNO__MISMATCHING_BUILDID;
                        goto out_elf_end;
+               }
        }
 
        ss->is_64_bit = (gelf_getclass(elf) == ELFCLASS64);
@@ -695,8 +716,10 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
        }
 
        ss->name   = strdup(name);
-       if (!ss->name)
+       if (!ss->name) {
+               dso->load_errno = errno;
                goto out_elf_end;
+       }
 
        ss->elf    = elf;
        ss->fd     = fd;
@@ -753,6 +776,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
                  symbol_filter_t filter, int kmodule)
 {
        struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
+       struct map_groups *kmaps = kmap ? map__kmaps(map) : NULL;
        struct map *curr_map = map;
        struct dso *curr_dso = dso;
        Elf_Data *symstrs, *secstrs;
@@ -768,6 +792,9 @@ int dso__load_sym(struct dso *dso, struct map *map,
        int nr = 0;
        bool remap_kernel = false, adjust_kernel_syms = false;
 
+       if (kmap && !kmaps)
+               return -1;
+
        dso->symtab_type = syms_ss->type;
        dso->is_64_bit = syms_ss->is_64_bit;
        dso->rel = syms_ss->ehdr.e_type == ET_REL;
@@ -864,10 +891,9 @@ int dso__load_sym(struct dso *dso, struct map *map,
                /* Reject ARM ELF "mapping symbols": these aren't unique and
                 * don't identify functions, so will confuse the profile
                 * output: */
-               if (ehdr.e_machine == EM_ARM) {
-                       if (!strcmp(elf_name, "$a") ||
-                           !strcmp(elf_name, "$d") ||
-                           !strcmp(elf_name, "$t"))
+               if (ehdr.e_machine == EM_ARM || ehdr.e_machine == EM_AARCH64) {
+                       if (elf_name[0] == '$' && strchr("adtx", elf_name[1])
+                           && (elf_name[2] == '\0' || elf_name[2] == '.'))
                                continue;
                }
 
@@ -936,8 +962,10 @@ int dso__load_sym(struct dso *dso, struct map *map,
                                        map->map_ip = map__map_ip;
                                        map->unmap_ip = map__unmap_ip;
                                        /* Ensure maps are correctly ordered */
-                                       map_groups__remove(kmap->kmaps, map);
-                                       map_groups__insert(kmap->kmaps, map);
+                                       if (kmaps) {
+                                               map_groups__remove(kmaps, map);
+                                               map_groups__insert(kmaps, map);
+                                       }
                                }
 
                                /*
@@ -961,7 +989,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
                        snprintf(dso_name, sizeof(dso_name),
                                 "%s%s", dso->short_name, section_name);
 
-                       curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name);
+                       curr_map = map_groups__find_by_name(kmaps, map->type, dso_name);
                        if (curr_map == NULL) {
                                u64 start = sym.st_value;
 
@@ -991,7 +1019,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
                                        curr_map->unmap_ip = identity__map_ip;
                                }
                                curr_dso->symtab_type = dso->symtab_type;
-                               map_groups__insert(kmap->kmaps, curr_map);
+                               map_groups__insert(kmaps, curr_map);
                                /*
                                 * The new DSO should go to the kernel DSOS
                                 */
@@ -1045,14 +1073,15 @@ new_symbol:
         * For misannotated, zeroed, ASM function sizes.
         */
        if (nr > 0) {
-               symbols__fixup_duplicate(&dso->symbols[map->type]);
+               if (!symbol_conf.allow_aliases)
+                       symbols__fixup_duplicate(&dso->symbols[map->type]);
                symbols__fixup_end(&dso->symbols[map->type]);
                if (kmap) {
                        /*
                         * We need to fixup this here too because we create new
                         * maps here, for things like vsyscall sections.
                         */
-                       __map_groups__fixup_end(kmap->kmaps, map->type);
+                       __map_groups__fixup_end(kmaps, map->type);
                }
        }
        err = nr;
index d7efb03b3f9aab2d0382afb1d031790109462233..fd8477cacf888f2bdac70fbc71a4f0461fbfc9b5 100644 (file)
@@ -246,13 +246,12 @@ out:
        return ret;
 }
 
-int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused,
-                const char *name,
+int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
                 enum dso_binary_type type)
 {
        int fd = open(name, O_RDONLY);
        if (fd < 0)
-               return -1;
+               goto out_errno;
 
        ss->name = strdup(name);
        if (!ss->name)
@@ -264,6 +263,8 @@ int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused,
        return 0;
 out_close:
        close(fd);
+out_errno:
+       dso->load_errno = errno;
        return -1;
 }
 
index a69066865a555f7b02c50606f3d53f4759a1eecc..201f6c4ca738ddffb46d5270a876cf96e8da9322 100644 (file)
@@ -15,6 +15,7 @@
 #include "machine.h"
 #include "symbol.h"
 #include "strlist.h"
+#include "intlist.h"
 #include "header.h"
 
 #include <elf.h>
@@ -629,13 +630,16 @@ static int dso__load_all_kallsyms(struct dso *dso, const char *filename,
 static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
                                         symbol_filter_t filter)
 {
-       struct map_groups *kmaps = map__kmap(map)->kmaps;
+       struct map_groups *kmaps = map__kmaps(map);
        struct map *curr_map;
        struct symbol *pos;
        int count = 0, moved = 0;
        struct rb_root *root = &dso->symbols[map->type];
        struct rb_node *next = rb_first(root);
 
+       if (!kmaps)
+               return -1;
+
        while (next) {
                char *module;
 
@@ -681,8 +685,8 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
 static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
                               symbol_filter_t filter)
 {
-       struct map_groups *kmaps = map__kmap(map)->kmaps;
-       struct machine *machine = kmaps->machine;
+       struct map_groups *kmaps = map__kmaps(map);
+       struct machine *machine;
        struct map *curr_map = map;
        struct symbol *pos;
        int count = 0, moved = 0;
@@ -690,6 +694,11 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
        struct rb_node *next = rb_first(root);
        int kernel_range = 0;
 
+       if (!kmaps)
+               return -1;
+
+       machine = kmaps->machine;
+
        while (next) {
                char *module;
 
@@ -1024,9 +1033,12 @@ static bool filename_from_kallsyms_filename(char *filename,
 static int validate_kcore_modules(const char *kallsyms_filename,
                                  struct map *map)
 {
-       struct map_groups *kmaps = map__kmap(map)->kmaps;
+       struct map_groups *kmaps = map__kmaps(map);
        char modules_filename[PATH_MAX];
 
+       if (!kmaps)
+               return -EINVAL;
+
        if (!filename_from_kallsyms_filename(modules_filename, "modules",
                                             kallsyms_filename))
                return -EINVAL;
@@ -1042,6 +1054,9 @@ static int validate_kcore_addresses(const char *kallsyms_filename,
 {
        struct kmap *kmap = map__kmap(map);
 
+       if (!kmap)
+               return -EINVAL;
+
        if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) {
                u64 start;
 
@@ -1080,8 +1095,8 @@ static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data)
 static int dso__load_kcore(struct dso *dso, struct map *map,
                           const char *kallsyms_filename)
 {
-       struct map_groups *kmaps = map__kmap(map)->kmaps;
-       struct machine *machine = kmaps->machine;
+       struct map_groups *kmaps = map__kmaps(map);
+       struct machine *machine;
        struct kcore_mapfn_data md;
        struct map *old_map, *new_map, *replacement_map = NULL;
        bool is_64_bit;
@@ -1089,6 +1104,11 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
        char kcore_filename[PATH_MAX];
        struct symbol *sym;
 
+       if (!kmaps)
+               return -EINVAL;
+
+       machine = kmaps->machine;
+
        /* This function requires that the map is the kernel map */
        if (map != machine->vmlinux_maps[map->type])
                return -EINVAL;
@@ -1201,6 +1221,9 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
        struct kmap *kmap = map__kmap(map);
        u64 addr;
 
+       if (!kmap)
+               return -1;
+
        if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
                return 0;
 
@@ -1859,6 +1882,20 @@ int setup_list(struct strlist **list, const char *list_str,
        return 0;
 }
 
+int setup_intlist(struct intlist **list, const char *list_str,
+                 const char *list_name)
+{
+       if (list_str == NULL)
+               return 0;
+
+       *list = intlist__new(list_str);
+       if (!*list) {
+               pr_err("problems parsing %s list\n", list_name);
+               return -1;
+       }
+       return 0;
+}
+
 static bool symbol__read_kptr_restrict(void)
 {
        bool value = false;
@@ -1909,9 +1946,17 @@ int symbol__init(struct perf_session_env *env)
                       symbol_conf.comm_list_str, "comm") < 0)
                goto out_free_dso_list;
 
+       if (setup_intlist(&symbol_conf.pid_list,
+                      symbol_conf.pid_list_str, "pid") < 0)
+               goto out_free_comm_list;
+
+       if (setup_intlist(&symbol_conf.tid_list,
+                      symbol_conf.tid_list_str, "tid") < 0)
+               goto out_free_pid_list;
+
        if (setup_list(&symbol_conf.sym_list,
                       symbol_conf.sym_list_str, "symbol") < 0)
-               goto out_free_comm_list;
+               goto out_free_tid_list;
 
        /*
         * A path to symbols of "/" is identical to ""
@@ -1930,6 +1975,10 @@ int symbol__init(struct perf_session_env *env)
        symbol_conf.initialized = true;
        return 0;
 
+out_free_tid_list:
+       intlist__delete(symbol_conf.tid_list);
+out_free_pid_list:
+       intlist__delete(symbol_conf.pid_list);
 out_free_comm_list:
        strlist__delete(symbol_conf.comm_list);
 out_free_dso_list:
@@ -1944,6 +1993,8 @@ void symbol__exit(void)
        strlist__delete(symbol_conf.sym_list);
        strlist__delete(symbol_conf.dso_list);
        strlist__delete(symbol_conf.comm_list);
+       intlist__delete(symbol_conf.tid_list);
+       intlist__delete(symbol_conf.pid_list);
        vmlinux_path__exit();
        symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
        symbol_conf.initialized = false;
index 1650dcb3a67bc3fddff40c93c6fdf6a1122d185a..09561500164a07997b49ca744f7f557ee200f043 100644 (file)
@@ -78,6 +78,7 @@ static inline size_t symbol__size(const struct symbol *sym)
 }
 
 struct strlist;
+struct intlist;
 
 struct symbol_conf {
        unsigned short  priv_size;
@@ -87,6 +88,7 @@ struct symbol_conf {
                        ignore_vmlinux_buildid,
                        show_kernel_path,
                        use_modules,
+                       allow_aliases,
                        sort_by_name,
                        show_nr_samples,
                        show_total_period,
@@ -114,6 +116,8 @@ struct symbol_conf {
        const char      *guestmount;
        const char      *dso_list_str,
                        *comm_list_str,
+                       *pid_list_str,
+                       *tid_list_str,
                        *sym_list_str,
                        *col_width_list_str;
        struct strlist  *dso_list,
@@ -123,6 +127,8 @@ struct symbol_conf {
                        *dso_to_list,
                        *sym_from_list,
                        *sym_to_list;
+       struct intlist  *pid_list,
+                       *tid_list;
        const char      *symfs;
 };
 
@@ -294,5 +300,7 @@ int compare_proc_modules(const char *from, const char *to);
 
 int setup_list(struct strlist **list, const char *list_str,
               const char *list_name);
+int setup_intlist(struct intlist **list, const char *list_str,
+                 const char *list_name);
 
 #endif /* __PERF_SYMBOL */
index e74c5963dc7a9db7038e4ad3f5f7de1ed490f20f..a53603b27e525864eeb328e934ba696dc3ea7e6e 100644 (file)
@@ -123,11 +123,8 @@ int target__strerror(struct target *target, int errnum,
        if (errnum >= 0) {
                const char *err = strerror_r(errnum, buf, buflen);
 
-               if (err != buf) {
-                       size_t len = strlen(err);
-                       memcpy(buf, err, min(buflen - 1, len));
-                       *(buf + min(buflen - 1, len)) = '\0';
-               }
+               if (err != buf)
+                       scnprintf(buf, buflen, "%s", err);
 
                return 0;
        }
index 9ebc8b1f9be51f82801e305804e4017eaa274db7..1c8fbc9588c5fddc978e8a07562aecc167a2a752 100644 (file)
@@ -82,6 +82,20 @@ void thread__delete(struct thread *thread)
        free(thread);
 }
 
+struct thread *thread__get(struct thread *thread)
+{
+       ++thread->refcnt;
+       return thread;
+}
+
+void thread__put(struct thread *thread)
+{
+       if (thread && --thread->refcnt == 0) {
+               list_del_init(&thread->node);
+               thread__delete(thread);
+       }
+}
+
 struct comm *thread__comm(const struct thread *thread)
 {
        if (list_empty(&thread->comm_list))
@@ -192,7 +206,6 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
                err = thread__set_comm(thread, comm, timestamp);
                if (err)
                        return err;
-               thread->comm_set = true;
        }
 
        thread->ppid = parent->tid;
index 160fd066a7d1efe7a45a9bcfb8012bf0bccfc777..9b8a54dc34a81963d8026e226bcd3334713b1606 100644 (file)
@@ -7,6 +7,7 @@
 #include <sys/types.h>
 #include "symbol.h"
 #include <strlist.h>
+#include <intlist.h>
 
 struct thread_stack;
 
@@ -20,6 +21,7 @@ struct thread {
        pid_t                   tid;
        pid_t                   ppid;
        int                     cpu;
+       int                     refcnt;
        char                    shortname[3];
        bool                    comm_set;
        bool                    dead; /* if set thread has exited */
@@ -37,6 +39,18 @@ struct comm;
 struct thread *thread__new(pid_t pid, pid_t tid);
 int thread__init_map_groups(struct thread *thread, struct machine *machine);
 void thread__delete(struct thread *thread);
+
+struct thread *thread__get(struct thread *thread);
+void thread__put(struct thread *thread);
+
+static inline void __thread__zput(struct thread **thread)
+{
+       thread__put(*thread);
+       *thread = NULL;
+}
+
+#define thread__zput(thread) __thread__zput(&thread)
+
 static inline void thread__exited(struct thread *thread)
 {
        thread->dead = true;
@@ -87,6 +101,16 @@ static inline bool thread__is_filtered(struct thread *thread)
                return true;
        }
 
+       if (symbol_conf.pid_list &&
+           !intlist__has_entry(symbol_conf.pid_list, thread->pid_)) {
+               return true;
+       }
+
+       if (symbol_conf.tid_list &&
+           !intlist__has_entry(symbol_conf.tid_list, thread->tid)) {
+               return true;
+       }
+
        return false;
 }
 
index bb2708bbfaca9565b48657608ff4d9a0e831e3d6..51d9e56c0f841d89f730f00e72e984a867b9f4fc 100644 (file)
@@ -10,6 +10,7 @@ struct perf_evsel;
 struct perf_sample;
 struct perf_tool;
 struct machine;
+struct ordered_events;
 
 typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event,
                            struct perf_sample *sample,
@@ -25,6 +26,9 @@ typedef int (*event_attr_op)(struct perf_tool *tool,
 typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,
                         struct perf_session *session);
 
+typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event,
+                       struct ordered_events *oe);
+
 struct perf_tool {
        event_sample    sample,
                        read;
@@ -38,8 +42,8 @@ struct perf_tool {
                        unthrottle;
        event_attr_op   attr;
        event_op2       tracing_data;
-       event_op2       finished_round,
-                       build_id,
+       event_oe        finished_round;
+       event_op2       build_id,
                        id_index;
        bool            ordered_events;
        bool            ordering_requires_timestamps;
index c36636fd825b46481dfcadbc745014ed94f38650..25d6c737be3e673db1904104a83286c5fbda0b40 100644 (file)
@@ -112,8 +112,8 @@ unsigned long long read_size(struct event_format *event, void *ptr, int size)
        return pevent_read_number(event->pevent, ptr, size);
 }
 
-void event_format__print(struct event_format *event,
-                        int cpu, void *data, int size)
+void event_format__fprintf(struct event_format *event,
+                          int cpu, void *data, int size, FILE *fp)
 {
        struct pevent_record record;
        struct trace_seq s;
@@ -125,10 +125,16 @@ void event_format__print(struct event_format *event,
 
        trace_seq_init(&s);
        pevent_event_info(&s, event, &record);
-       trace_seq_do_printf(&s);
+       trace_seq_do_fprintf(&s, fp);
        trace_seq_destroy(&s);
 }
 
+void event_format__print(struct event_format *event,
+                        int cpu, void *data, int size)
+{
+       return event_format__fprintf(event, cpu, data, size, stdout);
+}
+
 void parse_proc_kallsyms(struct pevent *pevent,
                         char *file, unsigned int size __maybe_unused)
 {
index 5c9bdd1591a975c2d1f7f028701504f228da70a0..9df61059a85d2188f9d0deb5dbf2e8f1f60aed4b 100644 (file)
@@ -43,7 +43,6 @@ static int stop_script_unsupported(void)
 static void process_event_unsupported(union perf_event *event __maybe_unused,
                                      struct perf_sample *sample __maybe_unused,
                                      struct perf_evsel *evsel __maybe_unused,
-                                     struct thread *thread __maybe_unused,
                                      struct addr_location *al __maybe_unused)
 {
 }
index 52aaa19e1eb13125dd30c4c82b6abe2d89de2735..d5168f0be4ec5b3284a825f620886689391e0f66 100644 (file)
@@ -23,6 +23,9 @@ trace_event__tp_format(const char *sys, const char *name);
 
 int bigendian(void);
 
+void event_format__fprintf(struct event_format *event,
+                          int cpu, void *data, int size, FILE *fp);
+
 void event_format__print(struct event_format *event,
                         int cpu, void *data, int size);
 
@@ -69,8 +72,7 @@ struct scripting_ops {
        void (*process_event) (union perf_event *event,
                               struct perf_sample *sample,
                               struct perf_evsel *evsel,
-                              struct thread *thread,
-                                  struct addr_location *al);
+                              struct addr_location *al);
        int (*generate_script) (struct pevent *pevent, const char *outfile);
 };
 
index e3c40a520a253c73cbad3f4e04558f006508cdb7..7b09a443a280429d3de68f03ced731f66b36d3fc 100644 (file)
@@ -266,7 +266,7 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
                                     u64 *fde_count)
 {
        int ret = -EINVAL, fd;
-       u64 offset = dso->data.frame_offset;
+       u64 offset = dso->data.eh_frame_hdr_offset;
 
        if (offset == 0) {
                fd = dso__data_fd(dso, machine);
@@ -275,7 +275,7 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
 
                /* Check the .eh_frame section for unwinding info */
                offset = elf_section_offset(fd, ".eh_frame_hdr");
-               dso->data.frame_offset = offset;
+               dso->data.eh_frame_hdr_offset = offset;
        }
 
        if (offset)
@@ -291,7 +291,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
                                        struct machine *machine, u64 *offset)
 {
        int fd;
-       u64 ofs = dso->data.frame_offset;
+       u64 ofs = dso->data.debug_frame_offset;
 
        if (ofs == 0) {
                fd = dso__data_fd(dso, machine);
@@ -300,7 +300,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
 
                /* Check the .debug_frame section for unwinding info */
                ofs = elf_section_offset(fd, ".debug_frame");
-               dso->data.frame_offset = ofs;
+               dso->data.debug_frame_offset = ofs;
        }
 
        *offset = ofs;
index b86744f29eeffce074d2c11fd11c5330ac72bfaa..4ee6d0d4c9931752e76abe15dd098468c4e0c01f 100644 (file)
@@ -269,6 +269,13 @@ void dump_stack(void)
 void dump_stack(void) {}
 #endif
 
+void sighandler_dump_stack(int sig)
+{
+       psignal(sig, "perf");
+       dump_stack();
+       exit(sig);
+}
+
 void get_term_dimensions(struct winsize *ws)
 {
        char *s = getenv("LINES");
@@ -303,13 +310,26 @@ void set_term_quiet_input(struct termios *old)
        tcsetattr(0, TCSANOW, &tc);
 }
 
-static void set_tracing_events_path(const char *mountpoint)
+static void set_tracing_events_path(const char *tracing, const char *mountpoint)
 {
-       snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
-                mountpoint, "tracing/events");
+       snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
+                mountpoint, tracing, "events");
 }
 
-const char *perf_debugfs_mount(const char *mountpoint)
+static const char *__perf_tracefs_mount(const char *mountpoint)
+{
+       const char *mnt;
+
+       mnt = tracefs_mount(mountpoint);
+       if (!mnt)
+               return NULL;
+
+       set_tracing_events_path("", mnt);
+
+       return mnt;
+}
+
+static const char *__perf_debugfs_mount(const char *mountpoint)
 {
        const char *mnt;
 
@@ -317,7 +337,20 @@ const char *perf_debugfs_mount(const char *mountpoint)
        if (!mnt)
                return NULL;
 
-       set_tracing_events_path(mnt);
+       set_tracing_events_path("tracing/", mnt);
+
+       return mnt;
+}
+
+const char *perf_debugfs_mount(const char *mountpoint)
+{
+       const char *mnt;
+
+       mnt = __perf_tracefs_mount(mountpoint);
+       if (mnt)
+               return mnt;
+
+       mnt = __perf_debugfs_mount(mountpoint);
 
        return mnt;
 }
@@ -325,12 +358,19 @@ const char *perf_debugfs_mount(const char *mountpoint)
 void perf_debugfs_set_path(const char *mntpt)
 {
        snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt);
-       set_tracing_events_path(mntpt);
+       set_tracing_events_path("tracing/", mntpt);
+}
+
+static const char *find_tracefs(void)
+{
+       const char *path = __perf_tracefs_mount(NULL);
+
+       return path;
 }
 
 static const char *find_debugfs(void)
 {
-       const char *path = perf_debugfs_mount(NULL);
+       const char *path = __perf_debugfs_mount(NULL);
 
        if (!path)
                fprintf(stderr, "Your kernel does not support the debugfs filesystem");
@@ -344,6 +384,7 @@ static const char *find_debugfs(void)
  */
 const char *find_tracing_dir(void)
 {
+       const char *tracing_dir = "";
        static char *tracing;
        static int tracing_found;
        const char *debugfs;
@@ -351,11 +392,15 @@ const char *find_tracing_dir(void)
        if (tracing_found)
                return tracing;
 
-       debugfs = find_debugfs();
-       if (!debugfs)
-               return NULL;
+       debugfs = find_tracefs();
+       if (!debugfs) {
+               tracing_dir = "/tracing";
+               debugfs = find_debugfs();
+               if (!debugfs)
+                       return NULL;
+       }
 
-       if (asprintf(&tracing, "%s/tracing", debugfs) < 0)
+       if (asprintf(&tracing, "%s%s", debugfs, tracing_dir) < 0)
                return NULL;
 
        tracing_found = 1;
index 027a5153495c8c9a087b7f624ba00d6e7f309a6f..1ff23e04ad2730b99f78dbeef3af56ba1a45e9ec 100644 (file)
@@ -75,6 +75,7 @@
 #include <linux/types.h>
 #include <sys/ttydefaults.h>
 #include <api/fs/debugfs.h>
+#include <api/fs/tracefs.h>
 #include <termios.h>
 #include <linux/bitops.h>
 #include <termios.h>
@@ -276,6 +277,7 @@ char *ltrim(char *s);
 char *rtrim(char *s);
 
 void dump_stack(void);
+void sighandler_dump_stack(int sig);
 
 extern unsigned int page_size;
 extern int cacheline_size;
@@ -327,4 +329,8 @@ bool find_process(const char *name);
 int gzip_decompress_to_file(const char *input, int output_fd);
 #endif
 
+#ifdef HAVE_LZMA_SUPPORT
+int lzma_decompress_to_file(const char *input, int output_fd);
+#endif
+
 #endif /* GIT_COMPAT_UTIL_H */
index 0db571340edbd94a7042a63f517f410b42c127d7..95abddcd78397fc3b64884f6bec31a5f6005b9e8 100644 (file)
@@ -17,6 +17,7 @@ TARGETS += sysctl
 TARGETS += timers
 TARGETS += user
 TARGETS += vm
+TARGETS += x86
 #Please keep the TARGETS list alphabetically sorted
 
 TARGETS_HOTPLUG = cpu-hotplug
@@ -55,7 +56,40 @@ clean_hotplug:
                make -C $$TARGET clean; \
        done;
 
+INSTALL_PATH ?= install
+INSTALL_PATH := $(abspath $(INSTALL_PATH))
+ALL_SCRIPT := $(INSTALL_PATH)/run_kselftest.sh
+
+install:
+ifdef INSTALL_PATH
+       @# Ask all targets to install their files
+       mkdir -p $(INSTALL_PATH)
+       for TARGET in $(TARGETS); do \
+               mkdir -p $(INSTALL_PATH)/$$TARGET ; \
+               make -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \
+       done;
+
+       @# Ask all targets to emit their test scripts
+       echo "#!/bin/bash" > $(ALL_SCRIPT)
+       echo "cd \$$(dirname \$$0)" >> $(ALL_SCRIPT)
+       echo "ROOT=\$$PWD" >> $(ALL_SCRIPT)
+
+       for TARGET in $(TARGETS); do \
+               echo "echo ; echo Running tests in $$TARGET" >> $(ALL_SCRIPT); \
+               echo "echo ========================================" >> $(ALL_SCRIPT); \
+               echo "cd $$TARGET" >> $(ALL_SCRIPT); \
+               make -s --no-print-directory -C $$TARGET emit_tests >> $(ALL_SCRIPT); \
+               echo "cd \$$ROOT" >> $(ALL_SCRIPT); \
+       done;
+
+       chmod u+x $(ALL_SCRIPT)
+else
+       $(error Error: set INSTALL_PATH to use install)
+endif
+
 clean:
        for TARGET in $(TARGETS); do \
                make -C $$TARGET clean; \
        done;
+
+.PHONY: install
index e18b42b254af814d7eb03f9459a2d24f67397077..1822356402090df03ee6311cb99dd7e2c7db94d7 100644 (file)
@@ -16,8 +16,9 @@ else
        echo "Not an x86 target, can't build breakpoints selftests"
 endif
 
-run_tests:
-       @./breakpoint_test || echo "breakpoints selftests: [FAIL]"
+TEST_PROGS := breakpoint_test
+
+include ../lib.mk
 
 clean:
        rm -fr breakpoint_test
index e9c28d8dc84bf2426e931b063477dd700a95ffab..fe1f99101c5d5023d4687893ed0bf7a5e876f1a9 100644 (file)
@@ -1,9 +1,10 @@
 all:
 
-run_tests:
-       @/bin/bash ./on-off-test.sh || echo "cpu-hotplug selftests: [FAIL]"
+TEST_PROGS := cpu-on-off-test.sh
+
+include ../lib.mk
 
 run_full_test:
-       @/bin/bash ./on-off-test.sh -a || echo "cpu-hotplug selftests: [FAIL]"
+       @/bin/bash ./cpu-on-off-test.sh -a || echo "cpu-hotplug selftests: [FAIL]"
 
 clean:
diff --git a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
new file mode 100755 (executable)
index 0000000..98b1d65
--- /dev/null
@@ -0,0 +1,269 @@
+#!/bin/bash
+
+SYSFS=
+
+prerequisite()
+{
+       msg="skip all tests:"
+
+       if [ $UID != 0 ]; then
+               echo $msg must be run as root >&2
+               exit 0
+       fi
+
+       taskset -p 01 $$
+
+       SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
+
+       if [ ! -d "$SYSFS" ]; then
+               echo $msg sysfs is not mounted >&2
+               exit 0
+       fi
+
+       if ! ls $SYSFS/devices/system/cpu/cpu* > /dev/null 2>&1; then
+               echo $msg cpu hotplug is not supported >&2
+               exit 0
+       fi
+
+       echo "CPU online/offline summary:"
+       online_cpus=`cat $SYSFS/devices/system/cpu/online`
+       online_max=${online_cpus##*-}
+       echo -e "\t Cpus in online state: $online_cpus"
+
+       offline_cpus=`cat $SYSFS/devices/system/cpu/offline`
+       if [[ "a$offline_cpus" = "a" ]]; then
+               offline_cpus=0
+       else
+               offline_max=${offline_cpus##*-}
+       fi
+       echo -e "\t Cpus in offline state: $offline_cpus"
+}
+
+#
+# list all hot-pluggable CPUs
+#
+hotpluggable_cpus()
+{
+       local state=${1:-.\*}
+
+       for cpu in $SYSFS/devices/system/cpu/cpu*; do
+               if [ -f $cpu/online ] && grep -q $state $cpu/online; then
+                       echo ${cpu##/*/cpu}
+               fi
+       done
+}
+
+hotplaggable_offline_cpus()
+{
+       hotpluggable_cpus 0
+}
+
+hotpluggable_online_cpus()
+{
+       hotpluggable_cpus 1
+}
+
+cpu_is_online()
+{
+       grep -q 1 $SYSFS/devices/system/cpu/cpu$1/online
+}
+
+cpu_is_offline()
+{
+       grep -q 0 $SYSFS/devices/system/cpu/cpu$1/online
+}
+
+online_cpu()
+{
+       echo 1 > $SYSFS/devices/system/cpu/cpu$1/online
+}
+
+offline_cpu()
+{
+       echo 0 > $SYSFS/devices/system/cpu/cpu$1/online
+}
+
+online_cpu_expect_success()
+{
+       local cpu=$1
+
+       if ! online_cpu $cpu; then
+               echo $FUNCNAME $cpu: unexpected fail >&2
+       elif ! cpu_is_online $cpu; then
+               echo $FUNCNAME $cpu: unexpected offline >&2
+       fi
+}
+
+online_cpu_expect_fail()
+{
+       local cpu=$1
+
+       if online_cpu $cpu 2> /dev/null; then
+               echo $FUNCNAME $cpu: unexpected success >&2
+       elif ! cpu_is_offline $cpu; then
+               echo $FUNCNAME $cpu: unexpected online >&2
+       fi
+}
+
+offline_cpu_expect_success()
+{
+       local cpu=$1
+
+       if ! offline_cpu $cpu; then
+               echo $FUNCNAME $cpu: unexpected fail >&2
+       elif ! cpu_is_offline $cpu; then
+               echo $FUNCNAME $cpu: unexpected offline >&2
+       fi
+}
+
+offline_cpu_expect_fail()
+{
+       local cpu=$1
+
+       if offline_cpu $cpu 2> /dev/null; then
+               echo $FUNCNAME $cpu: unexpected success >&2
+       elif ! cpu_is_online $cpu; then
+               echo $FUNCNAME $cpu: unexpected offline >&2
+       fi
+}
+
+error=-12
+allcpus=0
+priority=0
+online_cpus=0
+online_max=0
+offline_cpus=0
+offline_max=0
+
+while getopts e:ahp: opt; do
+       case $opt in
+       e)
+               error=$OPTARG
+               ;;
+       a)
+               allcpus=1
+               ;;
+       h)
+               echo "Usage $0 [ -a ] [ -e errno ] [ -p notifier-priority ]"
+               echo -e "\t default offline one cpu"
+               echo -e "\t run with -a option to offline all cpus"
+               exit
+               ;;
+       p)
+               priority=$OPTARG
+               ;;
+       esac
+done
+
+if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then
+       echo "error code must be -4095 <= errno < 0" >&2
+       exit 1
+fi
+
+prerequisite
+
+#
+# Safe test (default) - offline and online one cpu
+#
+if [ $allcpus -eq 0 ]; then
+       echo "Limited scope test: one hotplug cpu"
+       echo -e "\t (leaves cpu in the original state):"
+       echo -e "\t online to offline to online: cpu $online_max"
+       offline_cpu_expect_success $online_max
+       online_cpu_expect_success $online_max
+
+       if [[ $offline_cpus -gt 0 ]]; then
+               echo -e "\t offline to online to offline: cpu $offline_max"
+               online_cpu_expect_success $offline_max
+               offline_cpu_expect_success $offline_max
+       fi
+       exit 0
+else
+       echo "Full scope test: all hotplug cpus"
+       echo -e "\t online all offline cpus"
+       echo -e "\t offline all online cpus"
+       echo -e "\t online all offline cpus"
+fi
+
+#
+# Online all hot-pluggable CPUs
+#
+for cpu in `hotplaggable_offline_cpus`; do
+       online_cpu_expect_success $cpu
+done
+
+#
+# Offline all hot-pluggable CPUs
+#
+for cpu in `hotpluggable_online_cpus`; do
+       offline_cpu_expect_success $cpu
+done
+
+#
+# Online all hot-pluggable CPUs again
+#
+for cpu in `hotplaggable_offline_cpus`; do
+       online_cpu_expect_success $cpu
+done
+
+#
+# Test with cpu notifier error injection
+#
+
+DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'`
+NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/cpu
+
+prerequisite_extra()
+{
+       msg="skip extra tests:"
+
+       /sbin/modprobe -q -r cpu-notifier-error-inject
+       /sbin/modprobe -q cpu-notifier-error-inject priority=$priority
+
+       if [ ! -d "$DEBUGFS" ]; then
+               echo $msg debugfs is not mounted >&2
+               exit 0
+       fi
+
+       if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then
+               echo $msg cpu-notifier-error-inject module is not available >&2
+               exit 0
+       fi
+}
+
+prerequisite_extra
+
+#
+# Offline all hot-pluggable CPUs
+#
+echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
+for cpu in `hotpluggable_online_cpus`; do
+       offline_cpu_expect_success $cpu
+done
+
+#
+# Test CPU hot-add error handling (offline => online)
+#
+echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error
+for cpu in `hotplaggable_offline_cpus`; do
+       online_cpu_expect_fail $cpu
+done
+
+#
+# Online all hot-pluggable CPUs
+#
+echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error
+for cpu in `hotplaggable_offline_cpus`; do
+       online_cpu_expect_success $cpu
+done
+
+#
+# Test CPU hot-remove error handling (online => offline)
+#
+echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
+for cpu in `hotpluggable_online_cpus`; do
+       offline_cpu_expect_fail $cpu
+done
+
+echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
+/sbin/modprobe -q -r cpu-notifier-error-inject
diff --git a/tools/testing/selftests/cpu-hotplug/on-off-test.sh b/tools/testing/selftests/cpu-hotplug/on-off-test.sh
deleted file mode 100644 (file)
index 98b1d65..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-#!/bin/bash
-
-SYSFS=
-
-prerequisite()
-{
-       msg="skip all tests:"
-
-       if [ $UID != 0 ]; then
-               echo $msg must be run as root >&2
-               exit 0
-       fi
-
-       taskset -p 01 $$
-
-       SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
-
-       if [ ! -d "$SYSFS" ]; then
-               echo $msg sysfs is not mounted >&2
-               exit 0
-       fi
-
-       if ! ls $SYSFS/devices/system/cpu/cpu* > /dev/null 2>&1; then
-               echo $msg cpu hotplug is not supported >&2
-               exit 0
-       fi
-
-       echo "CPU online/offline summary:"
-       online_cpus=`cat $SYSFS/devices/system/cpu/online`
-       online_max=${online_cpus##*-}
-       echo -e "\t Cpus in online state: $online_cpus"
-
-       offline_cpus=`cat $SYSFS/devices/system/cpu/offline`
-       if [[ "a$offline_cpus" = "a" ]]; then
-               offline_cpus=0
-       else
-               offline_max=${offline_cpus##*-}
-       fi
-       echo -e "\t Cpus in offline state: $offline_cpus"
-}
-
-#
-# list all hot-pluggable CPUs
-#
-hotpluggable_cpus()
-{
-       local state=${1:-.\*}
-
-       for cpu in $SYSFS/devices/system/cpu/cpu*; do
-               if [ -f $cpu/online ] && grep -q $state $cpu/online; then
-                       echo ${cpu##/*/cpu}
-               fi
-       done
-}
-
-hotplaggable_offline_cpus()
-{
-       hotpluggable_cpus 0
-}
-
-hotpluggable_online_cpus()
-{
-       hotpluggable_cpus 1
-}
-
-cpu_is_online()
-{
-       grep -q 1 $SYSFS/devices/system/cpu/cpu$1/online
-}
-
-cpu_is_offline()
-{
-       grep -q 0 $SYSFS/devices/system/cpu/cpu$1/online
-}
-
-online_cpu()
-{
-       echo 1 > $SYSFS/devices/system/cpu/cpu$1/online
-}
-
-offline_cpu()
-{
-       echo 0 > $SYSFS/devices/system/cpu/cpu$1/online
-}
-
-online_cpu_expect_success()
-{
-       local cpu=$1
-
-       if ! online_cpu $cpu; then
-               echo $FUNCNAME $cpu: unexpected fail >&2
-       elif ! cpu_is_online $cpu; then
-               echo $FUNCNAME $cpu: unexpected offline >&2
-       fi
-}
-
-online_cpu_expect_fail()
-{
-       local cpu=$1
-
-       if online_cpu $cpu 2> /dev/null; then
-               echo $FUNCNAME $cpu: unexpected success >&2
-       elif ! cpu_is_offline $cpu; then
-               echo $FUNCNAME $cpu: unexpected online >&2
-       fi
-}
-
-offline_cpu_expect_success()
-{
-       local cpu=$1
-
-       if ! offline_cpu $cpu; then
-               echo $FUNCNAME $cpu: unexpected fail >&2
-       elif ! cpu_is_offline $cpu; then
-               echo $FUNCNAME $cpu: unexpected offline >&2
-       fi
-}
-
-offline_cpu_expect_fail()
-{
-       local cpu=$1
-
-       if offline_cpu $cpu 2> /dev/null; then
-               echo $FUNCNAME $cpu: unexpected success >&2
-       elif ! cpu_is_online $cpu; then
-               echo $FUNCNAME $cpu: unexpected offline >&2
-       fi
-}
-
-error=-12
-allcpus=0
-priority=0
-online_cpus=0
-online_max=0
-offline_cpus=0
-offline_max=0
-
-while getopts e:ahp: opt; do
-       case $opt in
-       e)
-               error=$OPTARG
-               ;;
-       a)
-               allcpus=1
-               ;;
-       h)
-               echo "Usage $0 [ -a ] [ -e errno ] [ -p notifier-priority ]"
-               echo -e "\t default offline one cpu"
-               echo -e "\t run with -a option to offline all cpus"
-               exit
-               ;;
-       p)
-               priority=$OPTARG
-               ;;
-       esac
-done
-
-if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then
-       echo "error code must be -4095 <= errno < 0" >&2
-       exit 1
-fi
-
-prerequisite
-
-#
-# Safe test (default) - offline and online one cpu
-#
-if [ $allcpus -eq 0 ]; then
-       echo "Limited scope test: one hotplug cpu"
-       echo -e "\t (leaves cpu in the original state):"
-       echo -e "\t online to offline to online: cpu $online_max"
-       offline_cpu_expect_success $online_max
-       online_cpu_expect_success $online_max
-
-       if [[ $offline_cpus -gt 0 ]]; then
-               echo -e "\t offline to online to offline: cpu $offline_max"
-               online_cpu_expect_success $offline_max
-               offline_cpu_expect_success $offline_max
-       fi
-       exit 0
-else
-       echo "Full scope test: all hotplug cpus"
-       echo -e "\t online all offline cpus"
-       echo -e "\t offline all online cpus"
-       echo -e "\t online all offline cpus"
-fi
-
-#
-# Online all hot-pluggable CPUs
-#
-for cpu in `hotplaggable_offline_cpus`; do
-       online_cpu_expect_success $cpu
-done
-
-#
-# Offline all hot-pluggable CPUs
-#
-for cpu in `hotpluggable_online_cpus`; do
-       offline_cpu_expect_success $cpu
-done
-
-#
-# Online all hot-pluggable CPUs again
-#
-for cpu in `hotplaggable_offline_cpus`; do
-       online_cpu_expect_success $cpu
-done
-
-#
-# Test with cpu notifier error injection
-#
-
-DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'`
-NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/cpu
-
-prerequisite_extra()
-{
-       msg="skip extra tests:"
-
-       /sbin/modprobe -q -r cpu-notifier-error-inject
-       /sbin/modprobe -q cpu-notifier-error-inject priority=$priority
-
-       if [ ! -d "$DEBUGFS" ]; then
-               echo $msg debugfs is not mounted >&2
-               exit 0
-       fi
-
-       if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then
-               echo $msg cpu-notifier-error-inject module is not available >&2
-               exit 0
-       fi
-}
-
-prerequisite_extra
-
-#
-# Offline all hot-pluggable CPUs
-#
-echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
-for cpu in `hotpluggable_online_cpus`; do
-       offline_cpu_expect_success $cpu
-done
-
-#
-# Test CPU hot-add error handling (offline => online)
-#
-echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error
-for cpu in `hotplaggable_offline_cpus`; do
-       online_cpu_expect_fail $cpu
-done
-
-#
-# Online all hot-pluggable CPUs
-#
-echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error
-for cpu in `hotplaggable_offline_cpus`; do
-       online_cpu_expect_success $cpu
-done
-
-#
-# Test CPU hot-remove error handling (online => offline)
-#
-echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
-for cpu in `hotpluggable_online_cpus`; do
-       offline_cpu_expect_fail $cpu
-done
-
-echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error
-/sbin/modprobe -q -r cpu-notifier-error-inject
index 29e8c6bc81b04330ee5a360218f0a8fb787ef3c3..736c3ddfc787499a3a114ab87ad173054e5468c2 100644 (file)
@@ -1,12 +1,13 @@
-CC = $(CROSS_COMPILE)gcc
 CFLAGS = -Wall
 
 test_objs = open-unlink create-read
 
 all: $(test_objs)
 
-run_tests: all
-       @/bin/bash ./efivarfs.sh || echo "efivarfs selftests: [FAIL]"
+TEST_PROGS := efivarfs.sh
+TEST_FILES := $(test_objs)
+
+include ../lib.mk
 
 clean:
        rm -f $(test_objs)
old mode 100644 (file)
new mode 100755 (executable)
index 66dfc2ce178896ffe0938b5dc09f1f339d93076c..4edb7d0da29b81aa1b0240ed600a42c42d63df9f 100644 (file)
@@ -1,4 +1,3 @@
-CC = $(CROSS_COMPILE)gcc
 CFLAGS = -Wall
 BINARIES = execveat
 DEPS = execveat.symlink execveat.denatured script subdir
@@ -18,8 +17,12 @@ execveat.denatured: execveat
 %: %.c
        $(CC) $(CFLAGS) -o $@ $^
 
-run_tests: all
-       ./execveat
+TEST_PROGS := execveat
+TEST_FILES := $(DEPS)
+
+include ../lib.mk
+
+override EMIT_TESTS := echo "mkdir -p subdir; (./execveat && echo \"selftests: execveat [PASS]\") || echo \"selftests: execveat [FAIL]\""
 
 clean:
        rm -rf $(BINARIES) $(DEPS) subdir.moved execveat.moved xxxxx*
index e23cce0bbc3a5ee90db9ef01c1a7b44c7d3e41aa..9bf82234855b8f5b0a831ecc97385a5dc5ef4728 100644 (file)
@@ -3,25 +3,9 @@
 # No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
 all:
 
-fw_filesystem:
-       @if /bin/sh ./fw_filesystem.sh ; then \
-                echo "fw_filesystem: ok"; \
-        else \
-                echo "fw_filesystem: [FAIL]"; \
-                exit 1; \
-        fi
+TEST_PROGS := fw_filesystem.sh fw_userhelper.sh
 
-fw_userhelper:
-       @if /bin/sh ./fw_userhelper.sh ; then \
-                echo "fw_userhelper: ok"; \
-        else \
-                echo "fw_userhelper: [FAIL]"; \
-                exit 1; \
-        fi
-
-run_tests: all fw_filesystem fw_userhelper
+include ../lib.mk
 
 # Nothing to clean up.
 clean:
-
-.PHONY: all clean run_tests fw_filesystem fw_userhelper
index 76cc9f1562679dcd48ecd3ab5f4b15228cb92f24..346720639d1d6c6d126379738969e679455ae630 100644 (file)
@@ -1,7 +1,8 @@
 all:
 
-run_tests:
-       @/bin/sh ./ftracetest || echo "ftrace selftests: [FAIL]"
+TEST_PROGS := ftracetest
+
+include ../lib.mk
 
 clean:
        rm -rf logs/*
index fd9c49a13612b2a3334a7f2eab6467e6844c861d..aa51f6c17359e18de0823f125ed7239b5f29c841 100644 (file)
@@ -2,4 +2,4 @@
 # description: Basic event tracing check
 test -f available_events -a -f set_event -a -d events
 # check scheduler events are available
-grep -q sched available_events && exit 0 || exit -1
\ No newline at end of file
+grep -q sched available_events && exit 0 || exit $FAIL
index 668616d9bb0364ce7be40f02a550602cda826b4f..87eb9d6dd4ca0e376faaa4eea161026417b2971f 100644 (file)
@@ -9,7 +9,11 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit -1
+    exit $FAIL
+}
+
+yield() {
+    ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1
 }
 
 if [ ! -f set_event -o ! -d events/sched ]; then
@@ -21,7 +25,8 @@ reset_tracer
 do_reset
 
 echo 'sched:sched_switch' > set_event
-usleep 1
+
+yield
 
 count=`cat trace | grep sched_switch | wc -l`
 if [ $count -eq 0 ]; then
@@ -31,7 +36,8 @@ fi
 do_reset
 
 echo 1 > events/sched/sched_switch/enable
-usleep 1
+
+yield
 
 count=`cat trace | grep sched_switch | wc -l`
 if [ $count -eq 0 ]; then
@@ -41,7 +47,8 @@ fi
 do_reset
 
 echo 0 > events/sched/sched_switch/enable
-usleep 1
+
+yield
 
 count=`cat trace | grep sched_switch | wc -l`
 if [ $count -ne 0 ]; then
index 655c415b6e7ff9b350474951aaff90cbd2727d19..ced27ef0638f2d3f21cd3a4fc436ebdd7bc8b259 100644 (file)
@@ -9,7 +9,11 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit -1
+    exit $FAIL
+}
+
+yield() {
+    ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1
 }
 
 if [ ! -f set_event -o ! -d events/sched ]; then
@@ -21,7 +25,8 @@ reset_tracer
 do_reset
 
 echo 'sched:*' > set_event
-usleep 1
+
+yield
 
 count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
 if [ $count -lt 3 ]; then
@@ -31,7 +36,8 @@ fi
 do_reset
 
 echo 1 > events/sched/enable
-usleep 1
+
+yield
 
 count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
 if [ $count -lt 3 ]; then
@@ -41,7 +47,8 @@ fi
 do_reset
 
 echo 0 > events/sched/enable
-usleep 1
+
+yield
 
 count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
 if [ $count -ne 0 ]; then
index 480845774007f7d9ba9ccf43fa272b9858f5ef53..0bb5df3c00d41701f7392c73c31c95b10867f1d8 100644 (file)
@@ -9,7 +9,11 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit -1
+    exit $FAIL
+}
+
+yield() {
+    ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1
 }
 
 if [ ! -f available_events -o ! -f set_event -o ! -d events ]; then
@@ -21,6 +25,9 @@ reset_tracer
 do_reset
 
 echo '*:*' > set_event
+
+yield
+
 count=`cat trace | grep -v ^# | wc -l`
 if [ $count -eq 0 ]; then
     fail "none of events are recorded"
@@ -29,6 +36,9 @@ fi
 do_reset
 
 echo 1 > events/enable
+
+yield
+
 count=`cat trace | grep -v ^# | wc -l`
 if [ $count -eq 0 ]; then
     fail "none of events are recorded"
@@ -37,6 +47,9 @@ fi
 do_reset
 
 echo 0 > events/enable
+
+yield
+
 count=`cat trace | grep -v ^# | wc -l`
 if [ $count -ne 0 ]; then
     fail "any of events should not be recorded"
index c15e018e022085c7e8e1ed619d5a9de7aaff7470..15c2dba06ea288a9d73652bfdcf001bd52fda936 100644 (file)
@@ -16,7 +16,9 @@ fi
 
 do_reset() {
     reset_tracer
-    echo 0 > /proc/sys/kernel/stack_tracer_enabled
+    if [ -e /proc/sys/kernel/stack_tracer_enabled ]; then
+           echo 0 > /proc/sys/kernel/stack_tracer_enabled
+    fi
     enable_tracing
     clear_trace
     echo > set_ftrace_filter
@@ -25,7 +27,7 @@ do_reset() {
 fail() { # msg
     do_reset
     echo $1
-    exit -1
+    exit $FAIL
 }
 
 disable_tracing
index 6af5f6360b184c32bdee9f8c4d40327909e839c7..0ab2189613efe534b6e443e2ee01d3ecbecd6c2b 100644 (file)
@@ -17,7 +17,7 @@ do_reset() {
 fail() { # msg
     do_reset
     echo $1
-    exit -1
+    exit $FAIL
 }
 
 disable_tracing
index 2e719cb1fc4d91492df00c37562898e68022a4a1..7808336d6f50832a456eca8061c6a88c3ba831b5 100644 (file)
@@ -31,7 +31,7 @@ fail() { # mesg
     reset_tracer
     echo > set_ftrace_filter
     echo $1
-    exit -1
+    exit $FAIL
 }
 
 echo "Testing function tracer with profiler:"
diff --git a/tools/testing/selftests/gen_kselftest_tar.sh b/tools/testing/selftests/gen_kselftest_tar.sh
new file mode 100755 (executable)
index 0000000..17d5bd0
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/bash
+#
+# gen_kselftest_tar
+# Generate kselftest tarball
+# Author: Shuah Khan <shuahkh@osg.samsung.com>
+# Copyright (C) 2015 Samsung Electronics Co., Ltd.
+
+# This software may be freely redistributed under the terms of the GNU
+# General Public License (GPLv2).
+
+# main
+main()
+{
+       if [ "$#" -eq 0 ]; then
+               echo "$0: Generating default compression gzip"
+               copts="cvzf"
+               ext=".tar.gz"
+       else
+               case "$1" in
+                       tar)
+                               copts="cvf"
+                               ext=".tar"
+                               ;;
+                       targz)
+                               copts="cvzf"
+                               ext=".tar.gz"
+                               ;;
+                       tarbz2)
+                               copts="cvjf"
+                               ext=".tar.bz2"
+                               ;;
+                       tarxz)
+                               copts="cvJf"
+                               ext=".tar.xz"
+                               ;;
+                       *)
+                       echo "Unknown tarball format $1"
+                       exit 1
+                       ;;
+       esac
+       fi
+
+       install_dir=./kselftest
+
+# Run install using INSTALL_KSFT_PATH override to generate install
+# directory
+./kselftest_install.sh
+tar $copts kselftest${ext} $install_dir
+echo "Kselftest archive kselftest${ext} created!"
+
+# clean up install directory
+rm -rf kselftest
+}
+
+main "$@"
index 74bbefdeaf4c187b07c02e67fedd74619f6215d6..25d2e702c68a53f7021d47404fd59d69241f430c 100644 (file)
@@ -12,14 +12,11 @@ endif
 CFLAGS += -I../../../../usr/include/
 
 all:
-ifeq ($(ARCH),x86)
-       gcc $(CFLAGS) msgque.c -o msgque_test
-else
-       echo "Not an x86 target, can't build msgque selftest"
-endif
+       $(CC) $(CFLAGS) msgque.c -o msgque_test
+
+TEST_PROGS := msgque_test
 
-run_tests: all
-       ./msgque_test
+include ../lib.mk
 
 clean:
        rm -fr ./msgque_test
index ff0eefdc6ceb92168b298831bf046f01b1ec1bf1..2ae7450a9a8984e2f0ba86a96842010375076757 100644 (file)
@@ -1,10 +1,10 @@
-CC := $(CROSS_COMPILE)$(CC)
 CFLAGS += -I../../../../usr/include/
 
 all: kcmp_test
 
-run_tests: all
-       @./kcmp_test || echo "kcmp_test: [FAIL]"
+TEST_PROGS := kcmp_test
+
+include ../lib.mk
 
 clean:
        $(RM) kcmp_test kcmp-test-file
diff --git a/tools/testing/selftests/kselftest_install.sh b/tools/testing/selftests/kselftest_install.sh
new file mode 100755 (executable)
index 0000000..1555fbd
--- /dev/null
@@ -0,0 +1,37 @@
+#!/bin/bash
+#
+# Kselftest Install
+# Install kselftest tests
+# Author: Shuah Khan <shuahkh@osg.samsung.com>
+# Copyright (C) 2015 Samsung Electronics Co., Ltd.
+
+# This software may be freely redistributed under the terms of the GNU
+# General Public License (GPLv2).
+
+install_loc=`pwd`
+
+main()
+{
+       if [ $(basename $install_loc) !=  "selftests" ]; then
+               echo "$0: Please run it in selftests directory ..."
+               exit 1;
+       fi
+       if [ "$#" -eq 0 ]; then
+               echo "$0: Installing in default location - $install_loc ..."
+       elif [ ! -d "$1" ]; then
+               echo "$0: $1 doesn't exist!!"
+               exit 1;
+       else
+               install_loc=$1
+               echo "$0: Installing in specified location - $install_loc ..."
+       fi
+
+       install_dir=$install_loc/kselftest
+
+# Create install directory
+       mkdir -p $install_dir
+# Build tests
+       INSTALL_PATH=$install_dir make install
+}
+
+main "$@"
diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk
new file mode 100644 (file)
index 0000000..2194155
--- /dev/null
@@ -0,0 +1,35 @@
+# This mimics the top-level Makefile. We do it explicitly here so that this
+# Makefile can operate with or without the kbuild infrastructure.
+CC := $(CROSS_COMPILE)gcc
+
+define RUN_TESTS
+       @for TEST in $(TEST_PROGS); do \
+               (./$$TEST && echo "selftests: $$TEST [PASS]") || echo "selftests: $$TEST [FAIL]"; \
+       done;
+endef
+
+run_tests: all
+       $(RUN_TESTS)
+
+define INSTALL_RULE
+       mkdir -p $(INSTALL_PATH)
+       install -t $(INSTALL_PATH) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES)
+endef
+
+install: all
+ifdef INSTALL_PATH
+       $(INSTALL_RULE)
+else
+       $(error Error: set INSTALL_PATH to use install)
+endif
+
+define EMIT_TESTS
+       @for TEST in $(TEST_PROGS); do \
+               echo "(./$$TEST && echo \"selftests: $$TEST [PASS]\") || echo \"selftests: $$TEST [FAIL]\""; \
+       done;
+endef
+
+emit_tests:
+       $(EMIT_TESTS)
+
+.PHONY: run_tests all clean install emit_tests
index b80cd10d53bac058926758b7df013d1190d6e67f..3e7eb7972511c657af9ca54e6468542a42a5bd33 100644 (file)
@@ -1,17 +1,19 @@
+CC = $(CROSS_COMPILE)gcc
 CFLAGS += -D_FILE_OFFSET_BITS=64
 CFLAGS += -I../../../../include/uapi/
 CFLAGS += -I../../../../include/
+CFLAGS += -I../../../../usr/include/
 
 all:
-       gcc $(CFLAGS) memfd_test.c -o memfd_test
+       $(CC) $(CFLAGS) memfd_test.c -o memfd_test
 
-run_tests: all
-       gcc $(CFLAGS) memfd_test.c -o memfd_test
-       @./memfd_test || echo "memfd_test: [FAIL]"
+TEST_PROGS := memfd_test
+
+include ../lib.mk
 
 build_fuse:
-       gcc $(CFLAGS) fuse_mnt.c `pkg-config fuse --cflags --libs` -o fuse_mnt
-       gcc $(CFLAGS) fuse_test.c -o fuse_test
+       $(CC) $(CFLAGS) fuse_mnt.c `pkg-config fuse --cflags --libs` -o fuse_mnt
+       $(CC) $(CFLAGS) fuse_test.c -o fuse_test
 
 run_fuse: build_fuse
        @./run_fuse_test.sh || echo "fuse_test: [FAIL]"
index d46b8d489cd252f18450b06dad87bb87f672e117..afb2624c704894fc280f553fbad9ac1f9fb07363 100644 (file)
@@ -1,9 +1,12 @@
 all:
 
-run_tests:
-       @/bin/bash ./on-off-test.sh -r 2 || echo "memory-hotplug selftests: [FAIL]"
+include ../lib.mk
+
+TEST_PROGS := mem-on-off-test.sh
+override RUN_TESTS := ./mem-on-off-test.sh -r 2 || echo "selftests: memory-hotplug [FAIL]"
+override EMIT_TESTS := echo "$(RUN_TESTS)"
 
 run_full_test:
-       @/bin/bash ./on-off-test.sh || echo "memory-hotplug selftests: [FAIL]"
+       @/bin/bash ./mem-on-off-test.sh || echo "memory-hotplug selftests: [FAIL]"
 
 clean:
diff --git a/tools/testing/selftests/memory-hotplug/mem-on-off-test.sh b/tools/testing/selftests/memory-hotplug/mem-on-off-test.sh
new file mode 100755 (executable)
index 0000000..6cddde0
--- /dev/null
@@ -0,0 +1,238 @@
+#!/bin/bash
+
+SYSFS=
+
+prerequisite()
+{
+       msg="skip all tests:"
+
+       if [ $UID != 0 ]; then
+               echo $msg must be run as root >&2
+               exit 0
+       fi
+
+       SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
+
+       if [ ! -d "$SYSFS" ]; then
+               echo $msg sysfs is not mounted >&2
+               exit 0
+       fi
+
+       if ! ls $SYSFS/devices/system/memory/memory* > /dev/null 2>&1; then
+               echo $msg memory hotplug is not supported >&2
+               exit 0
+       fi
+}
+
+#
+# list all hot-pluggable memory
+#
+hotpluggable_memory()
+{
+       local state=${1:-.\*}
+
+       for memory in $SYSFS/devices/system/memory/memory*; do
+               if grep -q 1 $memory/removable &&
+                  grep -q $state $memory/state; then
+                       echo ${memory##/*/memory}
+               fi
+       done
+}
+
+hotplaggable_offline_memory()
+{
+       hotpluggable_memory offline
+}
+
+hotpluggable_online_memory()
+{
+       hotpluggable_memory online
+}
+
+memory_is_online()
+{
+       grep -q online $SYSFS/devices/system/memory/memory$1/state
+}
+
+memory_is_offline()
+{
+       grep -q offline $SYSFS/devices/system/memory/memory$1/state
+}
+
+online_memory()
+{
+       echo online > $SYSFS/devices/system/memory/memory$1/state
+}
+
+offline_memory()
+{
+       echo offline > $SYSFS/devices/system/memory/memory$1/state
+}
+
+online_memory_expect_success()
+{
+       local memory=$1
+
+       if ! online_memory $memory; then
+               echo $FUNCNAME $memory: unexpected fail >&2
+       elif ! memory_is_online $memory; then
+               echo $FUNCNAME $memory: unexpected offline >&2
+       fi
+}
+
+online_memory_expect_fail()
+{
+       local memory=$1
+
+       if online_memory $memory 2> /dev/null; then
+               echo $FUNCNAME $memory: unexpected success >&2
+       elif ! memory_is_offline $memory; then
+               echo $FUNCNAME $memory: unexpected online >&2
+       fi
+}
+
+offline_memory_expect_success()
+{
+       local memory=$1
+
+       if ! offline_memory $memory; then
+               echo $FUNCNAME $memory: unexpected fail >&2
+       elif ! memory_is_offline $memory; then
+               echo $FUNCNAME $memory: unexpected offline >&2
+       fi
+}
+
+offline_memory_expect_fail()
+{
+       local memory=$1
+
+       if offline_memory $memory 2> /dev/null; then
+               echo $FUNCNAME $memory: unexpected success >&2
+       elif ! memory_is_online $memory; then
+               echo $FUNCNAME $memory: unexpected offline >&2
+       fi
+}
+
+error=-12
+priority=0
+ratio=10
+
+while getopts e:hp:r: opt; do
+       case $opt in
+       e)
+               error=$OPTARG
+               ;;
+       h)
+               echo "Usage $0 [ -e errno ] [ -p notifier-priority ] [ -r percent-of-memory-to-offline ]"
+               exit
+               ;;
+       p)
+               priority=$OPTARG
+               ;;
+       r)
+               ratio=$OPTARG
+               ;;
+       esac
+done
+
+if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then
+       echo "error code must be -4095 <= errno < 0" >&2
+       exit 1
+fi
+
+prerequisite
+
+echo "Test scope: $ratio% hotplug memory"
+echo -e "\t online all hotplug memory in offline state"
+echo -e "\t offline $ratio% hotplug memory in online state"
+echo -e "\t online all hotplug memory in offline state"
+
+#
+# Online all hot-pluggable memory
+#
+for memory in `hotplaggable_offline_memory`; do
+       echo offline-online $memory
+       online_memory_expect_success $memory
+done
+
+#
+# Offline $ratio percent of hot-pluggable memory
+#
+for memory in `hotpluggable_online_memory`; do
+       if [ $((RANDOM % 100)) -lt $ratio ]; then
+               echo online-offline $memory
+               offline_memory_expect_success $memory
+       fi
+done
+
+#
+# Online all hot-pluggable memory again
+#
+for memory in `hotplaggable_offline_memory`; do
+       echo offline-online $memory
+       online_memory_expect_success $memory
+done
+
+#
+# Test with memory notifier error injection
+#
+
+DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'`
+NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/memory
+
+prerequisite_extra()
+{
+       msg="skip extra tests:"
+
+       /sbin/modprobe -q -r memory-notifier-error-inject
+       /sbin/modprobe -q memory-notifier-error-inject priority=$priority
+
+       if [ ! -d "$DEBUGFS" ]; then
+               echo $msg debugfs is not mounted >&2
+               exit 0
+       fi
+
+       if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then
+               echo $msg memory-notifier-error-inject module is not available >&2
+               exit 0
+       fi
+}
+
+prerequisite_extra
+
+#
+# Offline $ratio percent of hot-pluggable memory
+#
+echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
+for memory in `hotpluggable_online_memory`; do
+       if [ $((RANDOM % 100)) -lt $ratio ]; then
+               offline_memory_expect_success $memory
+       fi
+done
+
+#
+# Test memory hot-add error handling (offline => online)
+#
+echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error
+for memory in `hotplaggable_offline_memory`; do
+       online_memory_expect_fail $memory
+done
+
+#
+# Online all hot-pluggable memory
+#
+echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error
+for memory in `hotplaggable_offline_memory`; do
+       online_memory_expect_success $memory
+done
+
+#
+# Test memory hot-remove error handling (online => offline)
+#
+echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
+for memory in `hotpluggable_online_memory`; do
+       offline_memory_expect_fail $memory
+done
+
+echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
+/sbin/modprobe -q -r memory-notifier-error-inject
diff --git a/tools/testing/selftests/memory-hotplug/on-off-test.sh b/tools/testing/selftests/memory-hotplug/on-off-test.sh
deleted file mode 100644 (file)
index 6cddde0..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-#!/bin/bash
-
-SYSFS=
-
-prerequisite()
-{
-       msg="skip all tests:"
-
-       if [ $UID != 0 ]; then
-               echo $msg must be run as root >&2
-               exit 0
-       fi
-
-       SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
-
-       if [ ! -d "$SYSFS" ]; then
-               echo $msg sysfs is not mounted >&2
-               exit 0
-       fi
-
-       if ! ls $SYSFS/devices/system/memory/memory* > /dev/null 2>&1; then
-               echo $msg memory hotplug is not supported >&2
-               exit 0
-       fi
-}
-
-#
-# list all hot-pluggable memory
-#
-hotpluggable_memory()
-{
-       local state=${1:-.\*}
-
-       for memory in $SYSFS/devices/system/memory/memory*; do
-               if grep -q 1 $memory/removable &&
-                  grep -q $state $memory/state; then
-                       echo ${memory##/*/memory}
-               fi
-       done
-}
-
-hotplaggable_offline_memory()
-{
-       hotpluggable_memory offline
-}
-
-hotpluggable_online_memory()
-{
-       hotpluggable_memory online
-}
-
-memory_is_online()
-{
-       grep -q online $SYSFS/devices/system/memory/memory$1/state
-}
-
-memory_is_offline()
-{
-       grep -q offline $SYSFS/devices/system/memory/memory$1/state
-}
-
-online_memory()
-{
-       echo online > $SYSFS/devices/system/memory/memory$1/state
-}
-
-offline_memory()
-{
-       echo offline > $SYSFS/devices/system/memory/memory$1/state
-}
-
-online_memory_expect_success()
-{
-       local memory=$1
-
-       if ! online_memory $memory; then
-               echo $FUNCNAME $memory: unexpected fail >&2
-       elif ! memory_is_online $memory; then
-               echo $FUNCNAME $memory: unexpected offline >&2
-       fi
-}
-
-online_memory_expect_fail()
-{
-       local memory=$1
-
-       if online_memory $memory 2> /dev/null; then
-               echo $FUNCNAME $memory: unexpected success >&2
-       elif ! memory_is_offline $memory; then
-               echo $FUNCNAME $memory: unexpected online >&2
-       fi
-}
-
-offline_memory_expect_success()
-{
-       local memory=$1
-
-       if ! offline_memory $memory; then
-               echo $FUNCNAME $memory: unexpected fail >&2
-       elif ! memory_is_offline $memory; then
-               echo $FUNCNAME $memory: unexpected offline >&2
-       fi
-}
-
-offline_memory_expect_fail()
-{
-       local memory=$1
-
-       if offline_memory $memory 2> /dev/null; then
-               echo $FUNCNAME $memory: unexpected success >&2
-       elif ! memory_is_online $memory; then
-               echo $FUNCNAME $memory: unexpected offline >&2
-       fi
-}
-
-error=-12
-priority=0
-ratio=10
-
-while getopts e:hp:r: opt; do
-       case $opt in
-       e)
-               error=$OPTARG
-               ;;
-       h)
-               echo "Usage $0 [ -e errno ] [ -p notifier-priority ] [ -r percent-of-memory-to-offline ]"
-               exit
-               ;;
-       p)
-               priority=$OPTARG
-               ;;
-       r)
-               ratio=$OPTARG
-               ;;
-       esac
-done
-
-if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then
-       echo "error code must be -4095 <= errno < 0" >&2
-       exit 1
-fi
-
-prerequisite
-
-echo "Test scope: $ratio% hotplug memory"
-echo -e "\t online all hotplug memory in offline state"
-echo -e "\t offline $ratio% hotplug memory in online state"
-echo -e "\t online all hotplug memory in offline state"
-
-#
-# Online all hot-pluggable memory
-#
-for memory in `hotplaggable_offline_memory`; do
-       echo offline-online $memory
-       online_memory_expect_success $memory
-done
-
-#
-# Offline $ratio percent of hot-pluggable memory
-#
-for memory in `hotpluggable_online_memory`; do
-       if [ $((RANDOM % 100)) -lt $ratio ]; then
-               echo online-offline $memory
-               offline_memory_expect_success $memory
-       fi
-done
-
-#
-# Online all hot-pluggable memory again
-#
-for memory in `hotplaggable_offline_memory`; do
-       echo offline-online $memory
-       online_memory_expect_success $memory
-done
-
-#
-# Test with memory notifier error injection
-#
-
-DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'`
-NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/memory
-
-prerequisite_extra()
-{
-       msg="skip extra tests:"
-
-       /sbin/modprobe -q -r memory-notifier-error-inject
-       /sbin/modprobe -q memory-notifier-error-inject priority=$priority
-
-       if [ ! -d "$DEBUGFS" ]; then
-               echo $msg debugfs is not mounted >&2
-               exit 0
-       fi
-
-       if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then
-               echo $msg memory-notifier-error-inject module is not available >&2
-               exit 0
-       fi
-}
-
-prerequisite_extra
-
-#
-# Offline $ratio percent of hot-pluggable memory
-#
-echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
-for memory in `hotpluggable_online_memory`; do
-       if [ $((RANDOM % 100)) -lt $ratio ]; then
-               offline_memory_expect_success $memory
-       fi
-done
-
-#
-# Test memory hot-add error handling (offline => online)
-#
-echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error
-for memory in `hotplaggable_offline_memory`; do
-       online_memory_expect_fail $memory
-done
-
-#
-# Online all hot-pluggable memory
-#
-echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error
-for memory in `hotplaggable_offline_memory`; do
-       online_memory_expect_success $memory
-done
-
-#
-# Test memory hot-remove error handling (online => offline)
-#
-echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
-for memory in `hotpluggable_online_memory`; do
-       offline_memory_expect_fail $memory
-done
-
-echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
-/sbin/modprobe -q -r memory-notifier-error-inject
diff --git a/tools/testing/selftests/mount/.gitignore b/tools/testing/selftests/mount/.gitignore
new file mode 100644 (file)
index 0000000..856ad41
--- /dev/null
@@ -0,0 +1 @@
+unprivileged-remount-test
index 337d853c2b72e8f434e1ed94e4e0f53fac49bbde..95580a97326e166ce2cd9f267055bbc2cdbc2355 100644 (file)
@@ -1,17 +1,16 @@
 # Makefile for mount selftests.
-
+CFLAGS = -Wall \
+         -O2
 all: unprivileged-remount-test
 
 unprivileged-remount-test: unprivileged-remount-test.c
-       gcc -Wall -O2 unprivileged-remount-test.c -o unprivileged-remount-test
+       $(CC) $(CFLAGS) unprivileged-remount-test.c -o unprivileged-remount-test
 
-# Allow specific tests to be selected.
-test_unprivileged_remount: unprivileged-remount-test
-       @if [ -f /proc/self/uid_map ] ; then ./unprivileged-remount-test ; fi
+include ../lib.mk
 
-run_tests: all test_unprivileged_remount
+TEST_PROGS := unprivileged-remount-test
+override RUN_TESTS := if [ -f /proc/self/uid_map ] ; then ./unprivileged-remount-test ; fi
+override EMIT_TESTS := echo "$(RUN_TESTS)"
 
 clean:
        rm -f unprivileged-remount-test
-
-.PHONY: all test_unprivileged_remount
index 8056e2e68fa4cd56d27e61ba1cab7cc54cf514f9..0e3b41eb85cde2cd553bda36ac0b09f43553ceb8 100644 (file)
@@ -1,10 +1,22 @@
+CFLAGS = -O2
+
 all:
-       gcc -O2 mq_open_tests.c -o mq_open_tests -lrt
-       gcc -O2 -o mq_perf_tests mq_perf_tests.c -lrt -lpthread -lpopt
+       $(CC) $(CFLAGS) mq_open_tests.c -o mq_open_tests -lrt
+       $(CC) $(CFLAGS) -o mq_perf_tests mq_perf_tests.c -lrt -lpthread -lpopt
+
+include ../lib.mk
+
+override define RUN_TESTS
+       @./mq_open_tests /test1 || echo "selftests: mq_open_tests [FAIL]"
+       @./mq_perf_tests || echo "selftests: mq_perf_tests [FAIL]"
+endef
+
+TEST_PROGS := mq_open_tests mq_perf_tests
 
-run_tests:
-       @./mq_open_tests /test1 || echo "mq_open_tests: [FAIL]"
-       @./mq_perf_tests || echo "mq_perf_tests: [FAIL]"
+override define EMIT_TESTS
+       echo "./mq_open_tests /test1 || echo \"selftests: mq_open_tests [FAIL]\""
+       echo "./mq_perf_tests || echo \"selftests: mq_perf_tests [FAIL]\""
+endef
 
 clean:
        rm -f mq_open_tests mq_perf_tests
index 62f22cc9941ce7595d8ff7a085b339adc044eb0e..fac4782c51d8439e524a3675bd6acc5d2df79c21 100644 (file)
@@ -1,6 +1,5 @@
 # Makefile for net selftests
 
-CC = $(CROSS_COMPILE)gcc
 CFLAGS = -Wall -O2 -g
 
 CFLAGS += -I../../../../usr/include/
@@ -11,9 +10,10 @@ all: $(NET_PROGS)
 %: %.c
        $(CC) $(CFLAGS) -o $@ $^
 
-run_tests: all
-       @/bin/sh ./run_netsocktests || echo "sockettests: [FAIL]"
-       @/bin/sh ./run_afpackettests || echo "afpackettests: [FAIL]"
-       ./test_bpf.sh
+TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh
+TEST_FILES := $(NET_PROGS)
+
+include ../lib.mk
+
 clean:
        $(RM) $(NET_PROGS)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 1d5e7ad2c46008590f9b18cd54ca330cf8a81745..2958fe9a74e97b2c86ce1c8e6072f49291cca257 100644 (file)
@@ -8,10 +8,9 @@ ifeq ($(ARCH),powerpc)
 
 GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown")
 
-CC := $(CROSS_COMPILE)$(CC)
 CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS)
 
-export CC CFLAGS
+export CFLAGS
 
 TARGETS = pmu copyloops mm tm primitives stringloops
 
@@ -22,10 +21,25 @@ all: $(TARGETS)
 $(TARGETS):
        $(MAKE) -k -C $@ all
 
-run_tests: all
+include ../lib.mk
+
+override define RUN_TESTS
        @for TARGET in $(TARGETS); do \
                $(MAKE) -C $$TARGET run_tests; \
        done;
+endef
+
+override define INSTALL_RULE
+       @for TARGET in $(TARGETS); do \
+               $(MAKE) -C $$TARGET install; \
+       done;
+endef
+
+override define EMIT_TESTS
+       @for TARGET in $(TARGETS); do \
+               $(MAKE) -s -C $$TARGET emit_tests; \
+       done;
+endef
 
 clean:
        @for TARGET in $(TARGETS); do \
@@ -36,4 +50,4 @@ clean:
 tags:
        find . -name '*.c' -o -name '*.h' | xargs ctags
 
-.PHONY: all run_tests clean tags $(TARGETS)
+.PHONY: tags $(TARGETS)
index 6f2d3be227f9909622876c6215bcf534b88a455c..c05023514ce8a019a33c8af97516ad1d2be015ad 100644 (file)
@@ -6,24 +6,19 @@ CFLAGS += -D SELFTEST
 # Use our CFLAGS for the implicit .S rule
 ASFLAGS = $(CFLAGS)
 
-PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7
+TEST_PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7
 EXTRA_SOURCES := validate.c ../harness.c
 
-all: $(PROGS)
+all: $(TEST_PROGS)
 
 copyuser_64:     CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_base
 copyuser_power7: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_power7
 memcpy_64:       CPPFLAGS += -D COPY_LOOP=test_memcpy
 memcpy_power7:   CPPFLAGS += -D COPY_LOOP=test_memcpy_power7
 
-$(PROGS): $(EXTRA_SOURCES)
+$(TEST_PROGS): $(EXTRA_SOURCES)
 
-run_tests: all
-       @-for PROG in $(PROGS); do \
-               ./$$PROG; \
-       done;
+include ../../lib.mk
 
 clean:
-       rm -f $(PROGS) *.o
-
-.PHONY: all run_tests clean
+       rm -f $(TEST_PROGS) *.o
index a14c538dd7f8d6068fe80bc4427a8e72e0cb94e6..41cc3ed66818bffa72d3bfffcbdecb44123c6ffc 100644 (file)
@@ -1,21 +1,16 @@
 noarg:
        $(MAKE) -C ../
 
-PROGS := hugetlb_vs_thp_test subpage_prot
+TEST_PROGS := hugetlb_vs_thp_test subpage_prot
 
-all: $(PROGS) tempfile
+all: $(TEST_PROGS) tempfile
 
-$(PROGS): ../harness.c
+$(TEST_PROGS): ../harness.c
 
-run_tests: all
-       @-for PROG in $(PROGS); do \
-               ./$$PROG; \
-       done;
+include ../../lib.mk
 
 tempfile:
        dd if=/dev/zero of=tempfile bs=64k count=1
 
 clean:
-       rm -f $(PROGS) tempfile
-
-.PHONY: all run_tests clean
+       rm -f $(TEST_PROGS) tempfile
index c9f4263906a5e67200284006fcae44bec8628065..5a161175bbd4197e907dbeb68f7c5f7003ecdf76 100644 (file)
@@ -1,38 +1,42 @@
 noarg:
        $(MAKE) -C ../
 
-PROGS := count_instructions l3_bank_test per_event_excludes
+TEST_PROGS := count_instructions l3_bank_test per_event_excludes
 EXTRA_SOURCES := ../harness.c event.c lib.c
 
-SUB_TARGETS = ebb
+all: $(TEST_PROGS) ebb
 
-all: $(PROGS) $(SUB_TARGETS)
-
-$(PROGS): $(EXTRA_SOURCES)
+$(TEST_PROGS): $(EXTRA_SOURCES)
 
 # loop.S can only be built 64-bit
 count_instructions: loop.S count_instructions.c $(EXTRA_SOURCES)
        $(CC) $(CFLAGS) -m64 -o $@ $^
 
-run_tests: all sub_run_tests
-       @-for PROG in $(PROGS); do \
-               ./$$PROG; \
-       done;
+include ../../lib.mk
 
-clean: sub_clean
-       rm -f $(PROGS) loop.o
+DEFAULT_RUN_TESTS := $(RUN_TESTS)
+override define RUN_TESTS
+       $(DEFAULT_RUN_TESTS)
+       $(MAKE) -C ebb run_tests
+endef
 
-$(SUB_TARGETS):
-       $(MAKE) -k -C $@ all
+DEFAULT_EMIT_TESTS := $(EMIT_TESTS)
+override define EMIT_TESTS
+       $(DEFAULT_EMIT_TESTS)
+       $(MAKE) -s -C ebb emit_tests
+endef
 
-sub_run_tests: all
-       @for TARGET in $(SUB_TARGETS); do \
-               $(MAKE) -C $$TARGET run_tests; \
-       done;
+DEFAULT_INSTALL := $(INSTALL_RULE)
+override define INSTALL_RULE
+       $(DEFAULT_INSTALL_RULE)
+       $(MAKE) -C ebb install
+endef
 
-sub_clean:
-       @for TARGET in $(SUB_TARGETS); do \
-               $(MAKE) -C $$TARGET clean; \
-       done;
+clean:
+       rm -f $(TEST_PROGS) loop.o
+       $(MAKE) -C ebb clean
+
+ebb:
+       $(MAKE) -k -C $@ all
 
-.PHONY: all run_tests clean sub_run_tests sub_clean $(SUB_TARGETS)
+.PHONY: all run_tests clean ebb
index 3dc4332698cb4f57c7160b22fe3c5fa740be6e79..5cdc9dbf2b279c95cd3f9603759b63bc5c0cfee5 100644 (file)
@@ -4,7 +4,7 @@ noarg:
 # The EBB handler is 64-bit code and everything links against it
 CFLAGS += -m64
 
-PROGS := reg_access_test event_attributes_test cycles_test     \
+TEST_PROGS := reg_access_test event_attributes_test cycles_test        \
         cycles_with_freeze_test pmc56_overflow_test            \
         ebb_vs_cpu_event_test cpu_event_vs_ebb_test            \
         cpu_event_pinned_vs_ebb_test task_event_vs_ebb_test    \
@@ -16,18 +16,15 @@ PROGS := reg_access_test event_attributes_test cycles_test  \
         lost_exception_test no_handler_test                    \
         cycles_with_mmcr2_test
 
-all: $(PROGS)
+all: $(TEST_PROGS)
 
-$(PROGS): ../../harness.c ../event.c ../lib.c ebb.c ebb_handler.S trace.c busy_loop.S
+$(TEST_PROGS): ../../harness.c ../event.c ../lib.c ebb.c ebb_handler.S trace.c busy_loop.S
 
 instruction_count_test: ../loop.S
 
 lost_exception_test: ../lib.c
 
-run_tests: all
-       @-for PROG in $(PROGS); do \
-               ./$$PROG; \
-       done;
+include ../../../lib.mk
 
 clean:
-       rm -f $(PROGS)
+       rm -f $(TEST_PROGS)
index ea737ca01732b2726fa7d149ce40d85c28fb7ccb..b68c6221d3d1bdad82a50356fa5c73083611d948 100644 (file)
@@ -1,17 +1,12 @@
 CFLAGS += -I$(CURDIR)
 
-PROGS := load_unaligned_zeropad
+TEST_PROGS := load_unaligned_zeropad
 
-all: $(PROGS)
+all: $(TEST_PROGS)
 
-$(PROGS): ../harness.c
+$(TEST_PROGS): ../harness.c
 
-run_tests: all
-       @-for PROG in $(PROGS); do \
-               ./$$PROG; \
-       done;
+include ../../lib.mk
 
 clean:
-       rm -f $(PROGS) *.o
-
-.PHONY: all run_tests clean
+       rm -f $(TEST_PROGS) *.o
index 506d7734647764cd077a669678db0eb9626ae23f..2a728f4d2873de636379c277feae38f004c60934 100644 (file)
@@ -2,19 +2,14 @@
 CFLAGS += -m64
 CFLAGS += -I$(CURDIR)
 
-PROGS := memcmp
+TEST_PROGS := memcmp
 EXTRA_SOURCES := memcmp_64.S ../harness.c
 
-all: $(PROGS)
+all: $(TEST_PROGS)
 
-$(PROGS): $(EXTRA_SOURCES)
+$(TEST_PROGS): $(EXTRA_SOURCES)
 
-run_tests: all
-       @-for PROG in $(PROGS); do \
-               ./$$PROG; \
-       done;
+include ../../lib.mk
 
 clean:
-       rm -f $(PROGS) *.o
-
-.PHONY: all run_tests clean
+       rm -f $(TEST_PROGS) *.o
index 2cede239a074dd110aa9ff3a6119b55f9c9d4ff6..34f2ec634b40ac2c8c3a1d2fac06c0257c8e7181 100644 (file)
@@ -1,15 +1,10 @@
-PROGS := tm-resched-dscr
+TEST_PROGS := tm-resched-dscr
 
-all: $(PROGS)
+all: $(TEST_PROGS)
 
-$(PROGS): ../harness.c
+$(TEST_PROGS): ../harness.c
 
-run_tests: all
-       @-for PROG in $(PROGS); do \
-               ./$$PROG; \
-       done;
+include ../../lib.mk
 
 clean:
-       rm -f $(PROGS) *.o
-
-.PHONY: all run_tests clean
+       rm -f $(TEST_PROGS) *.o
index 47ae2d385ce864ad85a7a070f29bd22c34fe3e5b..453927fea90cae7b65005fb661bf7b8254686d32 100644 (file)
@@ -6,5 +6,6 @@ all: peeksiginfo
 clean:
        rm -f peeksiginfo
 
-run_tests: all
-       @./peeksiginfo || echo "peeksiginfo selftests: [FAIL]"
+TEST_PROGS := peeksiginfo
+
+include ../lib.mk
index 368d64ac779e52e1cb787564bc1ddcc880e91ec5..dd2812ceb0baba2bb4f39343e428582e9619179f 100755 (executable)
@@ -310,7 +310,7 @@ function dump(first, pastlast)
                        cfr[jn] = cf[j] "." cfrep[cf[j]];
                }
                if (cpusr[jn] > ncpus && ncpus != 0)
-                       ovf = "(!)";
+                       ovf = "-ovf";
                else
                        ovf = "";
                print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date`";
index d2d2a86139db1ccd661d0ed70fb9feeb353748aa..49701218dc620481ff32344863411413e208da66 100644 (file)
@@ -1,2 +1,3 @@
 CONFIG_RCU_TORTURE_TEST=y
 CONFIG_PRINTK_TIME=y
+CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
index 04dc25e4fa92456597dc9a14862ab4192d84410d..bbd0b5398b613c08ee77eb4fbf9740383d874c0d 100644 (file)
@@ -1,12 +1,11 @@
-CC = $(CROSS_COMPILE)gcc
-
 all: get_size
 
 get_size: get_size.c
        $(CC) -static -ffreestanding -nostartfiles -s $< -o $@
 
-run_tests: all
-       ./get_size
+TEST_PROGS := get_size
+
+include ../lib.mk
 
 clean:
        $(RM) get_size
index 0a92adaf0865510f68d07914bd299c777370fddb..b3c33e071f10069ad01d0029c5d7c0350e413a18 100644 (file)
@@ -4,16 +4,10 @@
 # No binaries, but make sure arg-less "make" doesn't trigger "run_tests".
 all:
 
-# Allow specific tests to be selected.
-test_num:
-       @/bin/sh ./run_numerictests
+TEST_PROGS := run_numerictests run_stringtests
+TEST_FILES := common_tests
 
-test_string:
-       @/bin/sh ./run_stringtests
-
-run_tests: all test_num test_string
+include ../lib.mk
 
 # Nothing to clean up.
 clean:
-
-.PHONY: all run_tests clean test_num test_string
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index eb2859f4ad2113576831e5f8ee420cf514f5194d..89a3f44bf355d65f72ad279c298920d4c0dec260 100644 (file)
@@ -1,8 +1,36 @@
-all:
-       gcc posix_timers.c -o posix_timers -lrt
+CC = $(CROSS_COMPILE)gcc
+BUILD_FLAGS = -DKTEST
+CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS)
+LDFLAGS += -lrt -lpthread
 
-run_tests: all
-       ./posix_timers
+# these are all "safe" tests that don't modify
+# system time or require escalated privledges
+TEST_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
+            inconsistency-check raw_skew threadtest rtctest
+
+TEST_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex change_skew \
+                     skew_consistency clocksource-switch leap-a-day \
+                     leapcrash set-tai set-2038
+
+bins = $(TEST_PROGS) $(TEST_PROGS_EXTENDED)
+
+all: ${bins}
+
+include ../lib.mk
+
+# these tests require escalated privledges
+# and may modify the system time or trigger
+# other behavior like suspend
+run_destructive_tests: run_tests
+       ./alarmtimer-suspend
+       ./valid-adjtimex
+       ./change_skew
+       ./skew_consistency
+       ./clocksource-switch
+       ./leap-a-day -s -i 10
+       ./leapcrash
+       ./set-tai
+       ./set-2038
 
 clean:
-       rm -f ./posix_timers
+       rm -f ${bins}
diff --git a/tools/testing/selftests/timers/alarmtimer-suspend.c b/tools/testing/selftests/timers/alarmtimer-suspend.c
new file mode 100644 (file)
index 0000000..aaffbde
--- /dev/null
@@ -0,0 +1,185 @@
+/* alarmtimer suspend test
+ *             John Stultz (john.stultz@linaro.org)
+ *              (C) Copyright Linaro 2013
+ *              Licensed under the GPLv2
+ *
+ *   This test makes sure the alarmtimer & RTC wakeup code is
+ *   functioning.
+ *
+ *  To build:
+ *     $ gcc alarmtimer-suspend.c -o alarmtimer-suspend -lrt
+ *
+ *   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 <stdio.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <pthread.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+#define CLOCK_REALTIME                 0
+#define CLOCK_MONOTONIC                        1
+#define CLOCK_PROCESS_CPUTIME_ID       2
+#define CLOCK_THREAD_CPUTIME_ID                3
+#define CLOCK_MONOTONIC_RAW            4
+#define CLOCK_REALTIME_COARSE          5
+#define CLOCK_MONOTONIC_COARSE         6
+#define CLOCK_BOOTTIME                 7
+#define CLOCK_REALTIME_ALARM           8
+#define CLOCK_BOOTTIME_ALARM           9
+#define CLOCK_HWSPECIFIC               10
+#define CLOCK_TAI                      11
+#define NR_CLOCKIDS                    12
+
+
+#define NSEC_PER_SEC 1000000000ULL
+#define UNREASONABLE_LAT (NSEC_PER_SEC * 4) /* hopefully we resume in 4secs */
+
+#define SUSPEND_SECS 15
+int alarmcount;
+int alarm_clock_id;
+struct timespec start_time;
+
+
+char *clockstring(int clockid)
+{
+       switch (clockid) {
+       case CLOCK_REALTIME:
+               return "CLOCK_REALTIME";
+       case CLOCK_MONOTONIC:
+               return "CLOCK_MONOTONIC";
+       case CLOCK_PROCESS_CPUTIME_ID:
+               return "CLOCK_PROCESS_CPUTIME_ID";
+       case CLOCK_THREAD_CPUTIME_ID:
+               return "CLOCK_THREAD_CPUTIME_ID";
+       case CLOCK_MONOTONIC_RAW:
+               return "CLOCK_MONOTONIC_RAW";
+       case CLOCK_REALTIME_COARSE:
+               return "CLOCK_REALTIME_COARSE";
+       case CLOCK_MONOTONIC_COARSE:
+               return "CLOCK_MONOTONIC_COARSE";
+       case CLOCK_BOOTTIME:
+               return "CLOCK_BOOTTIME";
+       case CLOCK_REALTIME_ALARM:
+               return "CLOCK_REALTIME_ALARM";
+       case CLOCK_BOOTTIME_ALARM:
+               return "CLOCK_BOOTTIME_ALARM";
+       case CLOCK_TAI:
+               return "CLOCK_TAI";
+       };
+       return "UNKNOWN_CLOCKID";
+}
+
+
+long long timespec_sub(struct timespec a, struct timespec b)
+{
+       long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
+
+       ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
+       return ret;
+}
+
+int final_ret = 0;
+
+void sigalarm(int signo)
+{
+       long long delta_ns;
+       struct timespec ts;
+
+       clock_gettime(alarm_clock_id, &ts);
+       alarmcount++;
+
+       delta_ns = timespec_sub(start_time, ts);
+       delta_ns -= NSEC_PER_SEC * SUSPEND_SECS * alarmcount;
+
+       printf("ALARM(%i): %ld:%ld latency: %lld ns ", alarmcount, ts.tv_sec,
+                                                       ts.tv_nsec, delta_ns);
+
+       if (delta_ns > UNREASONABLE_LAT) {
+               printf("[FAIL]\n");
+               final_ret = -1;
+       } else
+               printf("[OK]\n");
+
+}
+
+int main(void)
+{
+       timer_t tm1;
+       struct itimerspec its1, its2;
+       struct sigevent se;
+       struct sigaction act;
+       int signum = SIGRTMAX;
+
+       /* Set up signal handler: */
+       sigfillset(&act.sa_mask);
+       act.sa_flags = 0;
+       act.sa_handler = sigalarm;
+       sigaction(signum, &act, NULL);
+
+       /* Set up timer: */
+       memset(&se, 0, sizeof(se));
+       se.sigev_notify = SIGEV_SIGNAL;
+       se.sigev_signo = signum;
+       se.sigev_value.sival_int = 0;
+
+       for (alarm_clock_id = CLOCK_REALTIME_ALARM;
+                       alarm_clock_id <= CLOCK_BOOTTIME_ALARM;
+                       alarm_clock_id++) {
+
+               alarmcount = 0;
+               timer_create(alarm_clock_id, &se, &tm1);
+
+               clock_gettime(alarm_clock_id, &start_time);
+               printf("Start time (%s): %ld:%ld\n", clockstring(alarm_clock_id),
+                               start_time.tv_sec, start_time.tv_nsec);
+               printf("Setting alarm for every %i seconds\n", SUSPEND_SECS);
+               its1.it_value = start_time;
+               its1.it_value.tv_sec += SUSPEND_SECS;
+               its1.it_interval.tv_sec = SUSPEND_SECS;
+               its1.it_interval.tv_nsec = 0;
+
+               timer_settime(tm1, TIMER_ABSTIME, &its1, &its2);
+
+               while (alarmcount < 5)
+                       sleep(1); /* First 5 alarms, do nothing */
+
+               printf("Starting suspend loops\n");
+               while (alarmcount < 10) {
+                       int ret;
+
+                       sleep(1);
+                       ret = system("echo mem > /sys/power/state");
+                       if (ret)
+                               break;
+               }
+               timer_delete(tm1);
+       }
+       if (final_ret)
+               return ksft_exit_fail();
+       return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/change_skew.c b/tools/testing/selftests/timers/change_skew.c
new file mode 100644 (file)
index 0000000..cb19689
--- /dev/null
@@ -0,0 +1,107 @@
+/* ADJ_FREQ Skew change test
+ *             by: john stultz (johnstul@us.ibm.com)
+ *             (C) Copyright IBM 2012
+ *             Licensed under the GPLv2
+ *
+ *  NOTE: This is a meta-test which cranks the ADJ_FREQ knob and
+ *  then uses other tests to detect problems. Thus this test requires
+ *  that the raw_skew, inconsistency-check and nanosleep tests be
+ *  present in the same directory it is run from.
+ *
+ *  To build:
+ *     $ gcc change_skew.c -o change_skew -lrt
+ *
+ *   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 <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <time.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+#define NSEC_PER_SEC 1000000000LL
+
+
+int change_skew_test(int ppm)
+{
+       struct timex tx;
+       int ret;
+
+       tx.modes = ADJ_FREQUENCY;
+       tx.freq = ppm << 16;
+
+       ret = adjtimex(&tx);
+       if (ret < 0) {
+               printf("Error adjusting freq\n");
+               return ret;
+       }
+
+       ret = system("./raw_skew");
+       ret |= system("./inconsistency-check");
+       ret |= system("./nanosleep");
+
+       return ret;
+}
+
+
+int main(int argv, char **argc)
+{
+       struct timex tx;
+       int i, ret;
+
+       int ppm[5] = {0, 250, 500, -250, -500};
+
+       /* Kill ntpd */
+       ret = system("killall -9 ntpd");
+
+       /* Make sure there's no offset adjustment going on */
+       tx.modes = ADJ_OFFSET;
+       tx.offset = 0;
+       ret = adjtimex(&tx);
+
+       if (ret < 0) {
+               printf("Maybe you're not running as root?\n");
+               return -1;
+       }
+
+       for (i = 0; i < 5; i++) {
+               printf("Using %i ppm adjustment\n", ppm[i]);
+               ret = change_skew_test(ppm[i]);
+               if (ret)
+                       break;
+       }
+
+       /* Set things back */
+       tx.modes = ADJ_FREQUENCY;
+       tx.offset = 0;
+       adjtimex(&tx);
+
+       if (ret) {
+               printf("[FAIL]");
+               return ksft_exit_fail();
+       }
+       printf("[OK]");
+       return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/clocksource-switch.c b/tools/testing/selftests/timers/clocksource-switch.c
new file mode 100644 (file)
index 0000000..627ec74
--- /dev/null
@@ -0,0 +1,179 @@
+/* Clocksource change test
+ *             by: john stultz (johnstul@us.ibm.com)
+ *             (C) Copyright IBM 2012
+ *             Licensed under the GPLv2
+ *
+ *  NOTE: This is a meta-test which quickly changes the clocksourc and
+ *  then uses other tests to detect problems. Thus this test requires
+ *  that the inconsistency-check and nanosleep tests be present in the
+ *  same directory it is run from.
+ *
+ *  To build:
+ *     $ gcc clocksource-switch.c -o clocksource-switch -lrt
+ *
+ *   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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/wait.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+
+int get_clocksources(char list[][30])
+{
+       int fd, i;
+       size_t size;
+       char buf[512];
+       char *head, *tmp;
+
+       fd = open("/sys/devices/system/clocksource/clocksource0/available_clocksource", O_RDONLY);
+
+       size = read(fd, buf, 512);
+
+       close(fd);
+
+       for (i = 0; i < 30; i++)
+               list[i][0] = '\0';
+
+       head = buf;
+       i = 0;
+       while (head - buf < size) {
+               /* Find the next space */
+               for (tmp = head; *tmp != ' '; tmp++) {
+                       if (*tmp == '\n')
+                               break;
+                       if (*tmp == '\0')
+                               break;
+               }
+               *tmp = '\0';
+               strcpy(list[i], head);
+               head = tmp + 1;
+               i++;
+       }
+
+       return i-1;
+}
+
+int get_cur_clocksource(char *buf, size_t size)
+{
+       int fd;
+
+       fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_RDONLY);
+
+       size = read(fd, buf, size);
+
+       return 0;
+}
+
+int change_clocksource(char *clocksource)
+{
+       int fd;
+       size_t size;
+
+       fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_WRONLY);
+
+       if (fd < 0)
+               return -1;
+
+       size = write(fd, clocksource, strlen(clocksource));
+
+       if (size < 0)
+               return -1;
+
+       close(fd);
+       return 0;
+}
+
+
+int run_tests(int secs)
+{
+       int ret;
+       char buf[255];
+
+       sprintf(buf, "./inconsistency-check -t %i", secs);
+       ret = system(buf);
+       if (ret)
+               return ret;
+       ret = system("./nanosleep");
+       return ret;
+}
+
+
+char clocksource_list[10][30];
+
+int main(int argv, char **argc)
+{
+       char orig_clk[512];
+       int count, i, status;
+       pid_t pid;
+
+       get_cur_clocksource(orig_clk, 512);
+
+       count = get_clocksources(clocksource_list);
+
+       if (change_clocksource(clocksource_list[0])) {
+               printf("Error: You probably need to run this as root\n");
+               return -1;
+       }
+
+       /* Check everything is sane before we start switching asyncrhonously */
+       for (i = 0; i < count; i++) {
+               printf("Validating clocksource %s\n", clocksource_list[i]);
+               if (change_clocksource(clocksource_list[i])) {
+                       status = -1;
+                       goto out;
+               }
+               if (run_tests(5)) {
+                       status = -1;
+                       goto out;
+               }
+       }
+
+
+       printf("Running Asyncrhonous Switching Tests...\n");
+       pid = fork();
+       if (!pid)
+               return run_tests(60);
+
+       while (pid != waitpid(pid, &status, WNOHANG))
+               for (i = 0; i < count; i++)
+                       if (change_clocksource(clocksource_list[i])) {
+                               status = -1;
+                               goto out;
+                       }
+out:
+       change_clocksource(orig_clk);
+
+       if (status)
+               return ksft_exit_fail();
+       return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/inconsistency-check.c b/tools/testing/selftests/timers/inconsistency-check.c
new file mode 100644 (file)
index 0000000..caf1bc9
--- /dev/null
@@ -0,0 +1,204 @@
+/* Time inconsistency check test
+ *             by: john stultz (johnstul@us.ibm.com)
+ *             (C) Copyright IBM 2003, 2004, 2005, 2012
+ *             (C) Copyright Linaro Limited 2015
+ *             Licensed under the GPLv2
+ *
+ *  To build:
+ *     $ gcc inconsistency-check.c -o inconsistency-check -lrt
+ *
+ *   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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <string.h>
+#include <signal.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+#define CALLS_PER_LOOP 64
+#define NSEC_PER_SEC 1000000000ULL
+
+#define CLOCK_REALTIME                 0
+#define CLOCK_MONOTONIC                        1
+#define CLOCK_PROCESS_CPUTIME_ID       2
+#define CLOCK_THREAD_CPUTIME_ID                3
+#define CLOCK_MONOTONIC_RAW            4
+#define CLOCK_REALTIME_COARSE          5
+#define CLOCK_MONOTONIC_COARSE         6
+#define CLOCK_BOOTTIME                 7
+#define CLOCK_REALTIME_ALARM           8
+#define CLOCK_BOOTTIME_ALARM           9
+#define CLOCK_HWSPECIFIC               10
+#define CLOCK_TAI                      11
+#define NR_CLOCKIDS                    12
+
+char *clockstring(int clockid)
+{
+       switch (clockid) {
+       case CLOCK_REALTIME:
+               return "CLOCK_REALTIME";
+       case CLOCK_MONOTONIC:
+               return "CLOCK_MONOTONIC";
+       case CLOCK_PROCESS_CPUTIME_ID:
+               return "CLOCK_PROCESS_CPUTIME_ID";
+       case CLOCK_THREAD_CPUTIME_ID:
+               return "CLOCK_THREAD_CPUTIME_ID";
+       case CLOCK_MONOTONIC_RAW:
+               return "CLOCK_MONOTONIC_RAW";
+       case CLOCK_REALTIME_COARSE:
+               return "CLOCK_REALTIME_COARSE";
+       case CLOCK_MONOTONIC_COARSE:
+               return "CLOCK_MONOTONIC_COARSE";
+       case CLOCK_BOOTTIME:
+               return "CLOCK_BOOTTIME";
+       case CLOCK_REALTIME_ALARM:
+               return "CLOCK_REALTIME_ALARM";
+       case CLOCK_BOOTTIME_ALARM:
+               return "CLOCK_BOOTTIME_ALARM";
+       case CLOCK_TAI:
+               return "CLOCK_TAI";
+       };
+       return "UNKNOWN_CLOCKID";
+}
+
+/* returns 1 if a <= b, 0 otherwise */
+static inline int in_order(struct timespec a, struct timespec b)
+{
+       /* use unsigned to avoid false positives on 2038 rollover */
+       if ((unsigned long)a.tv_sec < (unsigned long)b.tv_sec)
+               return 1;
+       if ((unsigned long)a.tv_sec > (unsigned long)b.tv_sec)
+               return 0;
+       if (a.tv_nsec > b.tv_nsec)
+               return 0;
+       return 1;
+}
+
+
+
+int consistency_test(int clock_type, unsigned long seconds)
+{
+       struct timespec list[CALLS_PER_LOOP];
+       int i, inconsistent;
+       long now, then;
+       time_t t;
+       char *start_str;
+
+       clock_gettime(clock_type, &list[0]);
+       now = then = list[0].tv_sec;
+
+       /* timestamp start of test */
+       t = time(0);
+       start_str = ctime(&t);
+
+       while (seconds == -1 || now - then < seconds) {
+               inconsistent = 0;
+
+               /* Fill list */
+               for (i = 0; i < CALLS_PER_LOOP; i++)
+                       clock_gettime(clock_type, &list[i]);
+
+               /* Check for inconsistencies */
+               for (i = 0; i < CALLS_PER_LOOP - 1; i++)
+                       if (!in_order(list[i], list[i+1]))
+                               inconsistent = i;
+
+               /* display inconsistency */
+               if (inconsistent) {
+                       unsigned long long delta;
+
+                       printf("\%s\n", start_str);
+                       for (i = 0; i < CALLS_PER_LOOP; i++) {
+                               if (i == inconsistent)
+                                       printf("--------------------\n");
+                               printf("%lu:%lu\n", list[i].tv_sec,
+                                                       list[i].tv_nsec);
+                               if (i == inconsistent + 1)
+                                       printf("--------------------\n");
+                       }
+                       delta = list[inconsistent].tv_sec * NSEC_PER_SEC;
+                       delta += list[inconsistent].tv_nsec;
+                       delta -= list[inconsistent+1].tv_sec * NSEC_PER_SEC;
+                       delta -= list[inconsistent+1].tv_nsec;
+                       printf("Delta: %llu ns\n", delta);
+                       fflush(0);
+                       /* timestamp inconsistency*/
+                       t = time(0);
+                       printf("%s\n", ctime(&t));
+                       printf("[FAILED]\n");
+                       return -1;
+               }
+               now = list[0].tv_sec;
+       }
+       printf("[OK]\n");
+       return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
+       int clockid, opt;
+       int userclock = CLOCK_REALTIME;
+       int maxclocks = NR_CLOCKIDS;
+       int runtime = 10;
+       struct timespec ts;
+
+       /* Process arguments */
+       while ((opt = getopt(argc, argv, "t:c:")) != -1) {
+               switch (opt) {
+               case 't':
+                       runtime = atoi(optarg);
+                       break;
+               case 'c':
+                       userclock = atoi(optarg);
+                       maxclocks = userclock + 1;
+                       break;
+               default:
+                       printf("Usage: %s [-t <secs>] [-c <clockid>]\n", argv[0]);
+                       printf("        -t: Number of seconds to run\n");
+                       printf("        -c: clockid to use (default, all clockids)\n");
+                       exit(-1);
+               }
+       }
+
+       setbuf(stdout, NULL);
+
+       for (clockid = userclock; clockid < maxclocks; clockid++) {
+
+               if (clockid == CLOCK_HWSPECIFIC)
+                       continue;
+
+               if (!clock_gettime(clockid, &ts)) {
+                       printf("Consistent %-30s ", clockstring(clockid));
+                       if (consistency_test(clockid, runtime))
+                               return ksft_exit_fail();
+               }
+       }
+       return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/leap-a-day.c b/tools/testing/selftests/timers/leap-a-day.c
new file mode 100644 (file)
index 0000000..b8272e6
--- /dev/null
@@ -0,0 +1,319 @@
+/* Leap second stress test
+ *              by: John Stultz (john.stultz@linaro.org)
+ *              (C) Copyright IBM 2012
+ *              (C) Copyright 2013, 2015 Linaro Limited
+ *              Licensed under the GPLv2
+ *
+ *  This test signals the kernel to insert a leap second
+ *  every day at midnight GMT. This allows for stessing the
+ *  kernel's leap-second behavior, as well as how well applications
+ *  handle the leap-second discontinuity.
+ *
+ *  Usage: leap-a-day [-s] [-i <num>]
+ *
+ *  Options:
+ *     -s:     Each iteration, set the date to 10 seconds before midnight GMT.
+ *             This speeds up the number of leapsecond transitions tested,
+ *             but because it calls settimeofday frequently, advancing the
+ *             time by 24 hours every ~16 seconds, it may cause application
+ *             disruption.
+ *
+ *     -i:     Number of iterations to run (default: infinite)
+ *
+ *  Other notes: Disabling NTP prior to running this is advised, as the two
+ *              may conflict in their commands to the kernel.
+ *
+ *  To build:
+ *     $ gcc leap-a-day.c -o leap-a-day -lrt
+ *
+ *   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 <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+#define NSEC_PER_SEC 1000000000ULL
+#define CLOCK_TAI 11
+
+/* returns 1 if a <= b, 0 otherwise */
+static inline int in_order(struct timespec a, struct timespec b)
+{
+       if (a.tv_sec < b.tv_sec)
+               return 1;
+       if (a.tv_sec > b.tv_sec)
+               return 0;
+       if (a.tv_nsec > b.tv_nsec)
+               return 0;
+       return 1;
+}
+
+struct timespec timespec_add(struct timespec ts, unsigned long long ns)
+{
+       ts.tv_nsec += ns;
+       while (ts.tv_nsec >= NSEC_PER_SEC) {
+               ts.tv_nsec -= NSEC_PER_SEC;
+               ts.tv_sec++;
+       }
+       return ts;
+}
+
+char *time_state_str(int state)
+{
+       switch (state) {
+       case TIME_OK:   return "TIME_OK";
+       case TIME_INS:  return "TIME_INS";
+       case TIME_DEL:  return "TIME_DEL";
+       case TIME_OOP:  return "TIME_OOP";
+       case TIME_WAIT: return "TIME_WAIT";
+       case TIME_BAD:  return "TIME_BAD";
+       }
+       return "ERROR";
+}
+
+/* clear NTP time_status & time_state */
+int clear_time_state(void)
+{
+       struct timex tx;
+       int ret;
+
+       /*
+        * We have to call adjtime twice here, as kernels
+        * prior to 6b1859dba01c7 (included in 3.5 and
+        * -stable), had an issue with the state machine
+        * and wouldn't clear the STA_INS/DEL flag directly.
+        */
+       tx.modes = ADJ_STATUS;
+       tx.status = STA_PLL;
+       ret = adjtimex(&tx);
+
+       /* Clear maxerror, as it can cause UNSYNC to be set */
+       tx.modes = ADJ_MAXERROR;
+       tx.maxerror = 0;
+       ret = adjtimex(&tx);
+
+       /* Clear the status */
+       tx.modes = ADJ_STATUS;
+       tx.status = 0;
+       ret = adjtimex(&tx);
+
+       return ret;
+}
+
+/* Make sure we cleanup on ctrl-c */
+void handler(int unused)
+{
+       clear_time_state();
+       exit(0);
+}
+
+/* Test for known hrtimer failure */
+void test_hrtimer_failure(void)
+{
+       struct timespec now, target;
+
+       clock_gettime(CLOCK_REALTIME, &now);
+       target = timespec_add(now, NSEC_PER_SEC/2);
+       clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &target, NULL);
+       clock_gettime(CLOCK_REALTIME, &now);
+
+       if (!in_order(target, now))
+               printf("ERROR: hrtimer early expiration failure observed.\n");
+}
+
+int main(int argc, char **argv)
+{
+       int settime = 0;
+       int tai_time = 0;
+       int insert = 1;
+       int iterations = -1;
+       int opt;
+
+       /* Process arguments */
+       while ((opt = getopt(argc, argv, "sti:")) != -1) {
+               switch (opt) {
+               case 's':
+                       printf("Setting time to speed up testing\n");
+                       settime = 1;
+                       break;
+               case 'i':
+                       iterations = atoi(optarg);
+                       break;
+               case 't':
+                       tai_time = 1;
+                       break;
+               default:
+                       printf("Usage: %s [-s] [-i <iterations>]\n", argv[0]);
+                       printf("        -s: Set time to right before leap second each iteration\n");
+                       printf("        -i: Number of iterations\n");
+                       printf("        -t: Print TAI time\n");
+                       exit(-1);
+               }
+       }
+
+       /* Make sure TAI support is present if -t was used */
+       if (tai_time) {
+               struct timespec ts;
+
+               if (clock_gettime(CLOCK_TAI, &ts)) {
+                       printf("System doesn't support CLOCK_TAI\n");
+                       ksft_exit_fail();
+               }
+       }
+
+       signal(SIGINT, handler);
+       signal(SIGKILL, handler);
+
+       if (iterations < 0)
+               printf("This runs continuously. Press ctrl-c to stop\n");
+       else
+               printf("Running for %i iterations. Press ctrl-c to stop\n", iterations);
+
+       printf("\n");
+       while (1) {
+               int ret;
+               struct timespec ts;
+               struct timex tx;
+               time_t now, next_leap;
+
+               /* Get the current time */
+               clock_gettime(CLOCK_REALTIME, &ts);
+
+               /* Calculate the next possible leap second 23:59:60 GMT */
+               next_leap = ts.tv_sec;
+               next_leap += 86400 - (next_leap % 86400);
+
+               if (settime) {
+                       struct timeval tv;
+
+                       tv.tv_sec = next_leap - 10;
+                       tv.tv_usec = 0;
+                       settimeofday(&tv, NULL);
+                       printf("Setting time to %s", ctime(&tv.tv_sec));
+               }
+
+               /* Reset NTP time state */
+               clear_time_state();
+
+               /* Set the leap second insert flag */
+               tx.modes = ADJ_STATUS;
+               if (insert)
+                       tx.status = STA_INS;
+               else
+                       tx.status = STA_DEL;
+               ret = adjtimex(&tx);
+               if (ret < 0) {
+                       printf("Error: Problem setting STA_INS/STA_DEL!: %s\n",
+                                                       time_state_str(ret));
+                       return ksft_exit_fail();
+               }
+
+               /* Validate STA_INS was set */
+               tx.modes = 0;
+               ret = adjtimex(&tx);
+               if (tx.status != STA_INS && tx.status != STA_DEL) {
+                       printf("Error: STA_INS/STA_DEL not set!: %s\n",
+                                                       time_state_str(ret));
+                       return ksft_exit_fail();
+               }
+
+               if (tai_time) {
+                       printf("Using TAI time,"
+                               " no inconsistencies should be seen!\n");
+               }
+
+               printf("Scheduling leap second for %s", ctime(&next_leap));
+
+               /* Wake up 3 seconds before leap */
+               ts.tv_sec = next_leap - 3;
+               ts.tv_nsec = 0;
+
+               while (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &ts, NULL))
+                       printf("Something woke us up, returning to sleep\n");
+
+               /* Validate STA_INS is still set */
+               tx.modes = 0;
+               ret = adjtimex(&tx);
+               if (tx.status != STA_INS && tx.status != STA_DEL) {
+                       printf("Something cleared STA_INS/STA_DEL, setting it again.\n");
+                       tx.modes = ADJ_STATUS;
+                       if (insert)
+                               tx.status = STA_INS;
+                       else
+                               tx.status = STA_DEL;
+                       ret = adjtimex(&tx);
+               }
+
+               /* Check adjtimex output every half second */
+               now = tx.time.tv_sec;
+               while (now < next_leap + 2) {
+                       char buf[26];
+                       struct timespec tai;
+
+                       tx.modes = 0;
+                       ret = adjtimex(&tx);
+
+                       if (tai_time) {
+                               clock_gettime(CLOCK_TAI, &tai);
+                               printf("%ld sec, %9ld ns\t%s\n",
+                                               tai.tv_sec,
+                                               tai.tv_nsec,
+                                               time_state_str(ret));
+                       } else {
+                               ctime_r(&tx.time.tv_sec, buf);
+                               buf[strlen(buf)-1] = 0; /*remove trailing\n */
+
+                               printf("%s + %6ld us (%i)\t%s\n",
+                                               buf,
+                                               tx.time.tv_usec,
+                                               tx.tai,
+                                               time_state_str(ret));
+                       }
+                       now = tx.time.tv_sec;
+                       /* Sleep for another half second */
+                       ts.tv_sec = 0;
+                       ts.tv_nsec = NSEC_PER_SEC / 2;
+                       clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
+               }
+               /* Switch to using other mode */
+               insert = !insert;
+
+               /* Note if kernel has known hrtimer failure */
+               test_hrtimer_failure();
+
+               printf("Leap complete\n\n");
+
+               if ((iterations != -1) && !(--iterations))
+                       break;
+       }
+
+       clear_time_state();
+       return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/leapcrash.c b/tools/testing/selftests/timers/leapcrash.c
new file mode 100644 (file)
index 0000000..a1071bd
--- /dev/null
@@ -0,0 +1,120 @@
+/* Demo leapsecond deadlock
+ *              by: John Stultz (john.stultz@linaro.org)
+ *              (C) Copyright IBM 2012
+ *              (C) Copyright 2013, 2015 Linaro Limited
+ *              Licensed under the GPL
+ *
+ * This test demonstrates leapsecond deadlock that is possibe
+ * on kernels from 2.6.26 to 3.3.
+ *
+ * WARNING: THIS WILL LIKELY HARDHANG SYSTEMS AND MAY LOSE DATA
+ * RUN AT YOUR OWN RISK!
+ *  To build:
+ *     $ gcc leapcrash.c -o leapcrash -lrt
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <string.h>
+#include <signal.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+
+
+/* clear NTP time_status & time_state */
+int clear_time_state(void)
+{
+       struct timex tx;
+       int ret;
+
+       /*
+        * We have to call adjtime twice here, as kernels
+        * prior to 6b1859dba01c7 (included in 3.5 and
+        * -stable), had an issue with the state machine
+        * and wouldn't clear the STA_INS/DEL flag directly.
+        */
+       tx.modes = ADJ_STATUS;
+       tx.status = STA_PLL;
+       ret = adjtimex(&tx);
+
+       tx.modes = ADJ_STATUS;
+       tx.status = 0;
+       ret = adjtimex(&tx);
+
+       return ret;
+}
+
+/* Make sure we cleanup on ctrl-c */
+void handler(int unused)
+{
+       clear_time_state();
+       exit(0);
+}
+
+
+int main(void)
+{
+       struct timex tx;
+       struct timespec ts;
+       time_t next_leap;
+       int count = 0;
+
+       setbuf(stdout, NULL);
+
+       signal(SIGINT, handler);
+       signal(SIGKILL, handler);
+       printf("This runs for a few minutes. Press ctrl-c to stop\n");
+
+       clear_time_state();
+
+
+       /* Get the current time */
+       clock_gettime(CLOCK_REALTIME, &ts);
+
+       /* Calculate the next possible leap second 23:59:60 GMT */
+       next_leap = ts.tv_sec;
+       next_leap += 86400 - (next_leap % 86400);
+
+       for (count = 0; count < 20; count++) {
+               struct timeval tv;
+
+
+               /* set the time to 2 seconds before the leap */
+               tv.tv_sec = next_leap - 2;
+               tv.tv_usec = 0;
+               if (settimeofday(&tv, NULL)) {
+                       printf("Error: You're likely not running with proper (ie: root) permissions\n");
+                       return ksft_exit_fail();
+               }
+               tx.modes = 0;
+               adjtimex(&tx);
+
+               /* hammer on adjtime w/ STA_INS */
+               while (tx.time.tv_sec < next_leap + 1) {
+                       /* Set the leap second insert flag */
+                       tx.modes = ADJ_STATUS;
+                       tx.status = STA_INS;
+                       adjtimex(&tx);
+               }
+               clear_time_state();
+               printf(".");
+       }
+       printf("[OK]\n");
+       return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/mqueue-lat.c b/tools/testing/selftests/timers/mqueue-lat.c
new file mode 100644 (file)
index 0000000..a2a3924
--- /dev/null
@@ -0,0 +1,124 @@
+/* Measure mqueue timeout latency
+ *              by: john stultz (john.stultz@linaro.org)
+ *             (C) Copyright Linaro 2013
+ *
+ *             Inspired with permission from example test by:
+ *                     Romain Francoise <romain@orebokech.com>
+ *              Licensed under the GPLv2
+ *
+ *  To build:
+ *     $ gcc mqueue-lat.c -o mqueue-lat -lrt
+ *
+ *   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 <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <mqueue.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+#define NSEC_PER_SEC 1000000000ULL
+
+#define TARGET_TIMEOUT         100000000       /* 100ms in nanoseconds */
+#define UNRESONABLE_LATENCY    40000000        /* 40ms in nanosecs */
+
+
+long long timespec_sub(struct timespec a, struct timespec b)
+{
+       long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
+
+       ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
+       return ret;
+}
+
+struct timespec timespec_add(struct timespec ts, unsigned long long ns)
+{
+       ts.tv_nsec += ns;
+       while (ts.tv_nsec >= NSEC_PER_SEC) {
+               ts.tv_nsec -= NSEC_PER_SEC;
+               ts.tv_sec++;
+       }
+       return ts;
+}
+
+int mqueue_lat_test(void)
+{
+
+       mqd_t q;
+       struct mq_attr attr;
+       struct timespec start, end, now, target;
+       int i, count, ret;
+
+       q = mq_open("/foo", O_CREAT | O_RDONLY, 0666, NULL);
+       if (q < 0) {
+               perror("mq_open");
+               return -1;
+       }
+       mq_getattr(q, &attr);
+
+
+       count = 100;
+       clock_gettime(CLOCK_MONOTONIC, &start);
+
+       for (i = 0; i < count; i++) {
+               char buf[attr.mq_msgsize];
+
+               clock_gettime(CLOCK_REALTIME, &now);
+               target = now;
+               target = timespec_add(now, TARGET_TIMEOUT); /* 100ms */
+
+               ret = mq_timedreceive(q, buf, sizeof(buf), NULL, &target);
+               if (ret < 0 && errno != ETIMEDOUT) {
+                       perror("mq_timedreceive");
+                       return -1;
+               }
+       }
+       clock_gettime(CLOCK_MONOTONIC, &end);
+
+       mq_close(q);
+
+       if ((timespec_sub(start, end)/count) > TARGET_TIMEOUT + UNRESONABLE_LATENCY)
+               return -1;
+
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       int ret;
+
+       printf("Mqueue latency :                          ");
+
+       ret = mqueue_lat_test();
+       if (ret < 0) {
+               printf("[FAILED]\n");
+               return ksft_exit_fail();
+       }
+       printf("[OK]\n");
+       return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/nanosleep.c b/tools/testing/selftests/timers/nanosleep.c
new file mode 100644 (file)
index 0000000..8a3c29d
--- /dev/null
@@ -0,0 +1,174 @@
+/* Make sure timers don't return early
+ *              by: john stultz (johnstul@us.ibm.com)
+ *                 John Stultz (john.stultz@linaro.org)
+ *              (C) Copyright IBM 2012
+ *              (C) Copyright Linaro 2013 2015
+ *              Licensed under the GPLv2
+ *
+ *  To build:
+ *     $ gcc nanosleep.c -o nanosleep -lrt
+ *
+ *   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 <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <string.h>
+#include <signal.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+#define NSEC_PER_SEC 1000000000ULL
+
+#define CLOCK_REALTIME                 0
+#define CLOCK_MONOTONIC                        1
+#define CLOCK_PROCESS_CPUTIME_ID       2
+#define CLOCK_THREAD_CPUTIME_ID                3
+#define CLOCK_MONOTONIC_RAW            4
+#define CLOCK_REALTIME_COARSE          5
+#define CLOCK_MONOTONIC_COARSE         6
+#define CLOCK_BOOTTIME                 7
+#define CLOCK_REALTIME_ALARM           8
+#define CLOCK_BOOTTIME_ALARM           9
+#define CLOCK_HWSPECIFIC               10
+#define CLOCK_TAI                      11
+#define NR_CLOCKIDS                    12
+
+#define UNSUPPORTED 0xf00f
+
+char *clockstring(int clockid)
+{
+       switch (clockid) {
+       case CLOCK_REALTIME:
+               return "CLOCK_REALTIME";
+       case CLOCK_MONOTONIC:
+               return "CLOCK_MONOTONIC";
+       case CLOCK_PROCESS_CPUTIME_ID:
+               return "CLOCK_PROCESS_CPUTIME_ID";
+       case CLOCK_THREAD_CPUTIME_ID:
+               return "CLOCK_THREAD_CPUTIME_ID";
+       case CLOCK_MONOTONIC_RAW:
+               return "CLOCK_MONOTONIC_RAW";
+       case CLOCK_REALTIME_COARSE:
+               return "CLOCK_REALTIME_COARSE";
+       case CLOCK_MONOTONIC_COARSE:
+               return "CLOCK_MONOTONIC_COARSE";
+       case CLOCK_BOOTTIME:
+               return "CLOCK_BOOTTIME";
+       case CLOCK_REALTIME_ALARM:
+               return "CLOCK_REALTIME_ALARM";
+       case CLOCK_BOOTTIME_ALARM:
+               return "CLOCK_BOOTTIME_ALARM";
+       case CLOCK_TAI:
+               return "CLOCK_TAI";
+       };
+       return "UNKNOWN_CLOCKID";
+}
+
+/* returns 1 if a <= b, 0 otherwise */
+static inline int in_order(struct timespec a, struct timespec b)
+{
+       if (a.tv_sec < b.tv_sec)
+               return 1;
+       if (a.tv_sec > b.tv_sec)
+               return 0;
+       if (a.tv_nsec > b.tv_nsec)
+               return 0;
+       return 1;
+}
+
+struct timespec timespec_add(struct timespec ts, unsigned long long ns)
+{
+       ts.tv_nsec += ns;
+       while (ts.tv_nsec >= NSEC_PER_SEC) {
+               ts.tv_nsec -= NSEC_PER_SEC;
+               ts.tv_sec++;
+       }
+       return ts;
+}
+
+int nanosleep_test(int clockid, long long ns)
+{
+       struct timespec now, target, rel;
+
+       /* First check abs time */
+       if (clock_gettime(clockid, &now))
+               return UNSUPPORTED;
+       target = timespec_add(now, ns);
+
+       if (clock_nanosleep(clockid, TIMER_ABSTIME, &target, NULL))
+               return UNSUPPORTED;
+       clock_gettime(clockid, &now);
+
+       if (!in_order(target, now))
+               return -1;
+
+       /* Second check reltime */
+       clock_gettime(clockid, &now);
+       rel.tv_sec = 0;
+       rel.tv_nsec = 0;
+       rel = timespec_add(rel, ns);
+       target = timespec_add(now, ns);
+       clock_nanosleep(clockid, 0, &rel, NULL);
+       clock_gettime(clockid, &now);
+
+       if (!in_order(target, now))
+               return -1;
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       long long length;
+       int clockid, ret;
+
+       for (clockid = CLOCK_REALTIME; clockid < NR_CLOCKIDS; clockid++) {
+
+               /* Skip cputime clockids since nanosleep won't increment cputime */
+               if (clockid == CLOCK_PROCESS_CPUTIME_ID ||
+                               clockid == CLOCK_THREAD_CPUTIME_ID ||
+                               clockid == CLOCK_HWSPECIFIC)
+                       continue;
+
+               printf("Nanosleep %-31s ", clockstring(clockid));
+
+               length = 10;
+               while (length <= (NSEC_PER_SEC * 10)) {
+                       ret = nanosleep_test(clockid, length);
+                       if (ret == UNSUPPORTED) {
+                               printf("[UNSUPPORTED]\n");
+                               goto next;
+                       }
+                       if (ret < 0) {
+                               printf("[FAILED]\n");
+                               return ksft_exit_fail();
+                       }
+                       length *= 100;
+               }
+               printf("[OK]\n");
+next:
+               ret = 0;
+       }
+       return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/nsleep-lat.c b/tools/testing/selftests/timers/nsleep-lat.c
new file mode 100644 (file)
index 0000000..2d7898f
--- /dev/null
@@ -0,0 +1,190 @@
+/* Measure nanosleep timer latency
+ *              by: john stultz (john.stultz@linaro.org)
+ *             (C) Copyright Linaro 2013
+ *              Licensed under the GPLv2
+ *
+ *  To build:
+ *     $ gcc nsleep-lat.c -o nsleep-lat -lrt
+ *
+ *   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 <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <string.h>
+#include <signal.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+#define NSEC_PER_SEC 1000000000ULL
+
+#define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */
+
+
+#define CLOCK_REALTIME                 0
+#define CLOCK_MONOTONIC                        1
+#define CLOCK_PROCESS_CPUTIME_ID       2
+#define CLOCK_THREAD_CPUTIME_ID                3
+#define CLOCK_MONOTONIC_RAW            4
+#define CLOCK_REALTIME_COARSE          5
+#define CLOCK_MONOTONIC_COARSE         6
+#define CLOCK_BOOTTIME                 7
+#define CLOCK_REALTIME_ALARM           8
+#define CLOCK_BOOTTIME_ALARM           9
+#define CLOCK_HWSPECIFIC               10
+#define CLOCK_TAI                      11
+#define NR_CLOCKIDS                    12
+
+#define UNSUPPORTED 0xf00f
+
+char *clockstring(int clockid)
+{
+       switch (clockid) {
+       case CLOCK_REALTIME:
+               return "CLOCK_REALTIME";
+       case CLOCK_MONOTONIC:
+               return "CLOCK_MONOTONIC";
+       case CLOCK_PROCESS_CPUTIME_ID:
+               return "CLOCK_PROCESS_CPUTIME_ID";
+       case CLOCK_THREAD_CPUTIME_ID:
+               return "CLOCK_THREAD_CPUTIME_ID";
+       case CLOCK_MONOTONIC_RAW:
+               return "CLOCK_MONOTONIC_RAW";
+       case CLOCK_REALTIME_COARSE:
+               return "CLOCK_REALTIME_COARSE";
+       case CLOCK_MONOTONIC_COARSE:
+               return "CLOCK_MONOTONIC_COARSE";
+       case CLOCK_BOOTTIME:
+               return "CLOCK_BOOTTIME";
+       case CLOCK_REALTIME_ALARM:
+               return "CLOCK_REALTIME_ALARM";
+       case CLOCK_BOOTTIME_ALARM:
+               return "CLOCK_BOOTTIME_ALARM";
+       case CLOCK_TAI:
+               return "CLOCK_TAI";
+       };
+       return "UNKNOWN_CLOCKID";
+}
+
+struct timespec timespec_add(struct timespec ts, unsigned long long ns)
+{
+       ts.tv_nsec += ns;
+       while (ts.tv_nsec >= NSEC_PER_SEC) {
+               ts.tv_nsec -= NSEC_PER_SEC;
+               ts.tv_sec++;
+       }
+       return ts;
+}
+
+
+long long timespec_sub(struct timespec a, struct timespec b)
+{
+       long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
+
+       ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
+       return ret;
+}
+
+int nanosleep_lat_test(int clockid, long long ns)
+{
+       struct timespec start, end, target;
+       long long latency = 0;
+       int i, count;
+
+       target.tv_sec = ns/NSEC_PER_SEC;
+       target.tv_nsec = ns%NSEC_PER_SEC;
+
+       if (clock_gettime(clockid, &start))
+               return UNSUPPORTED;
+       if (clock_nanosleep(clockid, 0, &target, NULL))
+               return UNSUPPORTED;
+
+       count = 10;
+
+       /* First check relative latency */
+       clock_gettime(clockid, &start);
+       for (i = 0; i < count; i++)
+               clock_nanosleep(clockid, 0, &target, NULL);
+       clock_gettime(clockid, &end);
+
+       if (((timespec_sub(start, end)/count)-ns) > UNRESONABLE_LATENCY) {
+               printf("Large rel latency: %lld ns :", (timespec_sub(start, end)/count)-ns);
+               return -1;
+       }
+
+       /* Next check absolute latency */
+       for (i = 0; i < count; i++) {
+               clock_gettime(clockid, &start);
+               target = timespec_add(start, ns);
+               clock_nanosleep(clockid, TIMER_ABSTIME, &target, NULL);
+               clock_gettime(clockid, &end);
+               latency += timespec_sub(target, end);
+       }
+
+       if (latency/count > UNRESONABLE_LATENCY) {
+               printf("Large abs latency: %lld ns :", latency/count);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+
+int main(int argc, char **argv)
+{
+       long long length;
+       int clockid, ret;
+
+       for (clockid = CLOCK_REALTIME; clockid < NR_CLOCKIDS; clockid++) {
+
+               /* Skip cputime clockids since nanosleep won't increment cputime */
+               if (clockid == CLOCK_PROCESS_CPUTIME_ID ||
+                               clockid == CLOCK_THREAD_CPUTIME_ID ||
+                               clockid == CLOCK_HWSPECIFIC)
+                       continue;
+
+               printf("nsleep latency %-26s ", clockstring(clockid));
+
+               length = 10;
+               while (length <= (NSEC_PER_SEC * 10)) {
+                       ret = nanosleep_lat_test(clockid, length);
+                       if (ret)
+                               break;
+                       length *= 100;
+
+               }
+
+               if (ret == UNSUPPORTED) {
+                       printf("[UNSUPPORTED]\n");
+                       continue;
+               }
+               if (ret < 0) {
+                       printf("[FAILED]\n");
+                       return ksft_exit_fail();
+               }
+               printf("[OK]\n");
+       }
+       return ksft_exit_pass();
+}
index f87d970a485c48b7d10e304e911fd3699c41bb35..5a246a02dff3c6986a1bd06496473ec5be1fd252 100644 (file)
@@ -35,10 +35,11 @@ static void user_loop(void)
 static void kernel_loop(void)
 {
        void *addr = sbrk(0);
+       int err = 0;
 
-       while (!done) {
-               brk(addr + 4096);
-               brk(addr);
+       while (!done && !err) {
+               err = brk(addr + 4096);
+               err |= brk(addr);
        }
 }
 
@@ -190,8 +191,6 @@ static int check_timer_create(int which)
 
 int main(int argc, char **argv)
 {
-       int err;
-
        printf("Testing posix timers. False negative may happen on CPU execution \n");
        printf("based timers if other threads run on the CPU...\n");
 
diff --git a/tools/testing/selftests/timers/raw_skew.c b/tools/testing/selftests/timers/raw_skew.c
new file mode 100644 (file)
index 0000000..30906bf
--- /dev/null
@@ -0,0 +1,154 @@
+/* CLOCK_MONOTONIC vs CLOCK_MONOTONIC_RAW skew test
+ *             by: john stultz (johnstul@us.ibm.com)
+ *                 John Stultz <john.stultz@linaro.org>
+ *             (C) Copyright IBM 2012
+ *             (C) Copyright Linaro Limited 2015
+ *             Licensed under the GPLv2
+ *
+ *  To build:
+ *     $ gcc raw_skew.c -o raw_skew -lrt
+ *
+ *   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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <time.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+
+#define CLOCK_MONOTONIC_RAW            4
+#define NSEC_PER_SEC 1000000000LL
+
+#define shift_right(x, s) ({           \
+       __typeof__(x) __x = (x);        \
+       __typeof__(s) __s = (s);        \
+       __x < 0 ? -(-__x >> __s) : __x >> __s; \
+})
+
+long long llabs(long long val)
+{
+       if (val < 0)
+               val = -val;
+       return val;
+}
+
+unsigned long long ts_to_nsec(struct timespec ts)
+{
+       return ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
+}
+
+struct timespec nsec_to_ts(long long ns)
+{
+       struct timespec ts;
+
+       ts.tv_sec = ns/NSEC_PER_SEC;
+       ts.tv_nsec = ns%NSEC_PER_SEC;
+       return ts;
+}
+
+long long diff_timespec(struct timespec start, struct timespec end)
+{
+       long long start_ns, end_ns;
+
+       start_ns = ts_to_nsec(start);
+       end_ns = ts_to_nsec(end);
+       return end_ns - start_ns;
+}
+
+void get_monotonic_and_raw(struct timespec *mon, struct timespec *raw)
+{
+       struct timespec start, mid, end;
+       long long diff = 0, tmp;
+       int i;
+
+       for (i = 0; i < 3; i++) {
+               long long newdiff;
+
+               clock_gettime(CLOCK_MONOTONIC, &start);
+               clock_gettime(CLOCK_MONOTONIC_RAW, &mid);
+               clock_gettime(CLOCK_MONOTONIC, &end);
+
+               newdiff = diff_timespec(start, end);
+               if (diff == 0 || newdiff < diff) {
+                       diff = newdiff;
+                       *raw = mid;
+                       tmp = (ts_to_nsec(start) + ts_to_nsec(end))/2;
+                       *mon = nsec_to_ts(tmp);
+               }
+       }
+}
+
+int main(int argv, char **argc)
+{
+       struct timespec mon, raw, start, end;
+       long long delta1, delta2, interval, eppm, ppm;
+       struct timex tx1, tx2;
+
+       setbuf(stdout, NULL);
+
+       if (clock_gettime(CLOCK_MONOTONIC_RAW, &raw)) {
+               printf("ERR: NO CLOCK_MONOTONIC_RAW\n");
+               return -1;
+       }
+
+       tx1.modes = 0;
+       adjtimex(&tx1);
+       get_monotonic_and_raw(&mon, &raw);
+       start = mon;
+       delta1 = diff_timespec(mon, raw);
+
+       if (tx1.offset)
+               printf("WARNING: ADJ_OFFSET in progress, this will cause inaccurate results\n");
+
+       printf("Estimating clock drift: ");
+       sleep(120);
+
+       get_monotonic_and_raw(&mon, &raw);
+       end = mon;
+       tx2.modes = 0;
+       adjtimex(&tx2);
+       delta2 = diff_timespec(mon, raw);
+
+       interval = diff_timespec(start, end);
+
+       /* calculate measured ppm between MONOTONIC and MONOTONIC_RAW */
+       eppm = ((delta2-delta1)*NSEC_PER_SEC)/interval;
+       eppm = -eppm;
+       printf("%lld.%i(est)", eppm/1000, abs((int)(eppm%1000)));
+
+       /* Avg the two actual freq samples adjtimex gave us */
+       ppm = (tx1.freq + tx2.freq) * 1000 / 2;
+       ppm = (long long)tx1.freq * 1000;
+       ppm = shift_right(ppm, 16);
+       printf(" %lld.%i(act)", ppm/1000, abs((int)(ppm%1000)));
+
+       if (llabs(eppm - ppm) > 1000) {
+               printf("        [FAILED]\n");
+               return ksft_exit_fail();
+       }
+       printf("        [OK]\n");
+       return  ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/rtctest.c b/tools/testing/selftests/timers/rtctest.c
new file mode 100644 (file)
index 0000000..d80ae85
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ *      Real Time Clock Driver Test/Example Program
+ *
+ *      Compile with:
+ *                  gcc -s -Wall -Wstrict-prototypes rtctest.c -o rtctest
+ *
+ *      Copyright (C) 1996, Paul Gortmaker.
+ *
+ *      Released under the GNU General Public License, version 2,
+ *      included herein by reference.
+ *
+ */
+
+#include <stdio.h>
+#include <linux/rtc.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+
+/*
+ * This expects the new RTC class driver framework, working with
+ * clocks that will often not be clones of what the PC-AT had.
+ * Use the command line to specify another RTC if you need one.
+ */
+static const char default_rtc[] = "/dev/rtc0";
+
+
+int main(int argc, char **argv)
+{
+       int i, fd, retval, irqcount = 0;
+       unsigned long tmp, data;
+       struct rtc_time rtc_tm;
+       const char *rtc = default_rtc;
+       struct timeval start, end, diff;
+
+       switch (argc) {
+       case 2:
+               rtc = argv[1];
+               /* FALLTHROUGH */
+       case 1:
+               break;
+       default:
+               fprintf(stderr, "usage:  rtctest [rtcdev]\n");
+               return 1;
+       }
+
+       fd = open(rtc, O_RDONLY);
+
+       if (fd ==  -1) {
+               perror(rtc);
+               exit(errno);
+       }
+
+       fprintf(stderr, "\n\t\t\tRTC Driver Test Example.\n\n");
+
+       /* Turn on update interrupts (one per second) */
+       retval = ioctl(fd, RTC_UIE_ON, 0);
+       if (retval == -1) {
+               if (errno == ENOTTY) {
+                       fprintf(stderr,
+                               "\n...Update IRQs not supported.\n");
+                       goto test_READ;
+               }
+               perror("RTC_UIE_ON ioctl");
+               exit(errno);
+       }
+
+       fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading %s:",
+                       rtc);
+       fflush(stderr);
+       for (i=1; i<6; i++) {
+               /* This read will block */
+               retval = read(fd, &data, sizeof(unsigned long));
+               if (retval == -1) {
+                       perror("read");
+                       exit(errno);
+               }
+               fprintf(stderr, " %d",i);
+               fflush(stderr);
+               irqcount++;
+       }
+
+       fprintf(stderr, "\nAgain, from using select(2) on /dev/rtc:");
+       fflush(stderr);
+       for (i=1; i<6; i++) {
+               struct timeval tv = {5, 0};     /* 5 second timeout on select */
+               fd_set readfds;
+
+               FD_ZERO(&readfds);
+               FD_SET(fd, &readfds);
+               /* The select will wait until an RTC interrupt happens. */
+               retval = select(fd+1, &readfds, NULL, NULL, &tv);
+               if (retval == -1) {
+                       perror("select");
+                       exit(errno);
+               }
+               /* This read won't block unlike the select-less case above. */
+               retval = read(fd, &data, sizeof(unsigned long));
+               if (retval == -1) {
+                       perror("read");
+                       exit(errno);
+               }
+               fprintf(stderr, " %d",i);
+               fflush(stderr);
+               irqcount++;
+       }
+
+       /* Turn off update interrupts */
+       retval = ioctl(fd, RTC_UIE_OFF, 0);
+       if (retval == -1) {
+               perror("RTC_UIE_OFF ioctl");
+               exit(errno);
+       }
+
+test_READ:
+       /* Read the RTC time/date */
+       retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
+       if (retval == -1) {
+               perror("RTC_RD_TIME ioctl");
+               exit(errno);
+       }
+
+       fprintf(stderr, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
+               rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
+               rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
+
+       /* Set the alarm to 5 sec in the future, and check for rollover */
+       rtc_tm.tm_sec += 5;
+       if (rtc_tm.tm_sec >= 60) {
+               rtc_tm.tm_sec %= 60;
+               rtc_tm.tm_min++;
+       }
+       if (rtc_tm.tm_min == 60) {
+               rtc_tm.tm_min = 0;
+               rtc_tm.tm_hour++;
+       }
+       if (rtc_tm.tm_hour == 24)
+               rtc_tm.tm_hour = 0;
+
+       retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
+       if (retval == -1) {
+               if (errno == ENOTTY) {
+                       fprintf(stderr,
+                               "\n...Alarm IRQs not supported.\n");
+                       goto test_PIE;
+               }
+               perror("RTC_ALM_SET ioctl");
+               exit(errno);
+       }
+
+       /* Read the current alarm settings */
+       retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
+       if (retval == -1) {
+               perror("RTC_ALM_READ ioctl");
+               exit(errno);
+       }
+
+       fprintf(stderr, "Alarm time now set to %02d:%02d:%02d.\n",
+               rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
+
+       /* Enable alarm interrupts */
+       retval = ioctl(fd, RTC_AIE_ON, 0);
+       if (retval == -1) {
+               perror("RTC_AIE_ON ioctl");
+               exit(errno);
+       }
+
+       fprintf(stderr, "Waiting 5 seconds for alarm...");
+       fflush(stderr);
+       /* This blocks until the alarm ring causes an interrupt */
+       retval = read(fd, &data, sizeof(unsigned long));
+       if (retval == -1) {
+               perror("read");
+               exit(errno);
+       }
+       irqcount++;
+       fprintf(stderr, " okay. Alarm rang.\n");
+
+       /* Disable alarm interrupts */
+       retval = ioctl(fd, RTC_AIE_OFF, 0);
+       if (retval == -1) {
+               perror("RTC_AIE_OFF ioctl");
+               exit(errno);
+       }
+
+test_PIE:
+       /* Read periodic IRQ rate */
+       retval = ioctl(fd, RTC_IRQP_READ, &tmp);
+       if (retval == -1) {
+               /* not all RTCs support periodic IRQs */
+               if (errno == ENOTTY) {
+                       fprintf(stderr, "\nNo periodic IRQ support\n");
+                       goto done;
+               }
+               perror("RTC_IRQP_READ ioctl");
+               exit(errno);
+       }
+       fprintf(stderr, "\nPeriodic IRQ rate is %ldHz.\n", tmp);
+
+       fprintf(stderr, "Counting 20 interrupts at:");
+       fflush(stderr);
+
+       /* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */
+       for (tmp=2; tmp<=64; tmp*=2) {
+
+               retval = ioctl(fd, RTC_IRQP_SET, tmp);
+               if (retval == -1) {
+                       /* not all RTCs can change their periodic IRQ rate */
+                       if (errno == ENOTTY) {
+                               fprintf(stderr,
+                                       "\n...Periodic IRQ rate is fixed\n");
+                               goto done;
+                       }
+                       perror("RTC_IRQP_SET ioctl");
+                       exit(errno);
+               }
+
+               fprintf(stderr, "\n%ldHz:\t", tmp);
+               fflush(stderr);
+
+               /* Enable periodic interrupts */
+               retval = ioctl(fd, RTC_PIE_ON, 0);
+               if (retval == -1) {
+                       perror("RTC_PIE_ON ioctl");
+                       exit(errno);
+               }
+
+               for (i=1; i<21; i++) {
+                       gettimeofday(&start, NULL);
+                       /* This blocks */
+                       retval = read(fd, &data, sizeof(unsigned long));
+                       if (retval == -1) {
+                               perror("read");
+                               exit(errno);
+                       }
+                       gettimeofday(&end, NULL);
+                       timersub(&end, &start, &diff);
+                       if (diff.tv_sec > 0 ||
+                           diff.tv_usec > ((1000000L / tmp) * 1.10)) {
+                               fprintf(stderr, "\nPIE delta error: %ld.%06ld should be close to 0.%06ld\n",
+                                      diff.tv_sec, diff.tv_usec,
+                                      (1000000L / tmp));
+                               fflush(stdout);
+                               exit(-1);
+                       }
+
+                       fprintf(stderr, " %d",i);
+                       fflush(stderr);
+                       irqcount++;
+               }
+
+               /* Disable periodic interrupts */
+               retval = ioctl(fd, RTC_PIE_OFF, 0);
+               if (retval == -1) {
+                       perror("RTC_PIE_OFF ioctl");
+                       exit(errno);
+               }
+       }
+
+done:
+       fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n");
+
+       close(fd);
+
+       return 0;
+}
diff --git a/tools/testing/selftests/timers/set-2038.c b/tools/testing/selftests/timers/set-2038.c
new file mode 100644 (file)
index 0000000..c8a7e14
--- /dev/null
@@ -0,0 +1,144 @@
+/* Time bounds setting test
+ *             by: john stultz (johnstul@us.ibm.com)
+ *             (C) Copyright IBM 2012
+ *             Licensed under the GPLv2
+ *
+ *  NOTE: This is a meta-test which sets the time to edge cases then
+ *  uses other tests to detect problems. Thus this test requires that
+ *  the inconsistency-check and nanosleep tests be present in the same
+ *  directory it is run from.
+ *
+ *  To build:
+ *     $ gcc set-2038.c -o set-2038 -lrt
+ *
+ *   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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+#define NSEC_PER_SEC 1000000000LL
+
+#define KTIME_MAX      ((long long)~((unsigned long long)1 << 63))
+#define KTIME_SEC_MAX  (KTIME_MAX / NSEC_PER_SEC)
+
+#define YEAR_1901 (-0x7fffffffL)
+#define YEAR_1970 1
+#define YEAR_2038 0x7fffffffL                  /*overflows 32bit time_t */
+#define YEAR_2262 KTIME_SEC_MAX                        /*overflows 64bit ktime_t */
+#define YEAR_MAX  ((long long)((1ULL<<63)-1))  /*overflows 64bit time_t */
+
+int is32bits(void)
+{
+       return (sizeof(long) == 4);
+}
+
+int settime(long long time)
+{
+       struct timeval now;
+       int ret;
+
+       now.tv_sec = (time_t)time;
+       now.tv_usec  = 0;
+
+       ret = settimeofday(&now, NULL);
+
+       printf("Setting time to 0x%lx: %d\n", (long)time, ret);
+       return ret;
+}
+
+int do_tests(void)
+{
+       int ret;
+
+       ret = system("date");
+       ret = system("./inconsistency-check -c 0 -t 20");
+       ret |= system("./nanosleep");
+       ret |= system("./nsleep-lat");
+       return ret;
+
+}
+
+int main(int argc, char *argv[])
+{
+       int ret = 0;
+       int opt, dangerous = 0;
+       time_t start;
+
+       /* Process arguments */
+       while ((opt = getopt(argc, argv, "d")) != -1) {
+               switch (opt) {
+               case 'd':
+                       dangerous = 1;
+               }
+       }
+
+       start = time(0);
+
+       /* First test that crazy values don't work */
+       if (!settime(YEAR_1901)) {
+               ret = -1;
+               goto out;
+       }
+       if (!settime(YEAR_MAX)) {
+               ret = -1;
+               goto out;
+       }
+       if (!is32bits() && !settime(YEAR_2262)) {
+               ret = -1;
+               goto out;
+       }
+
+       /* Now test behavior near edges */
+       settime(YEAR_1970);
+       ret = do_tests();
+       if (ret)
+               goto out;
+
+       settime(YEAR_2038 - 600);
+       ret = do_tests();
+       if (ret)
+               goto out;
+
+       /* The rest of the tests can blowup on 32bit systems */
+       if (is32bits() && !dangerous)
+               goto out;
+       /* Test rollover behavior 32bit edge */
+       settime(YEAR_2038 - 10);
+       ret = do_tests();
+       if (ret)
+               goto out;
+
+       settime(YEAR_2262 - 600);
+       ret = do_tests();
+
+out:
+       /* restore clock */
+       settime(start);
+       if (ret)
+               return ksft_exit_fail();
+       return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/set-tai.c b/tools/testing/selftests/timers/set-tai.c
new file mode 100644 (file)
index 0000000..dc88dbc
--- /dev/null
@@ -0,0 +1,79 @@
+/* Set tai offset
+ *              by: John Stultz <john.stultz@linaro.org>
+ *              (C) Copyright Linaro 2013
+ *              Licensed under the GPLv2
+ *
+ *   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 <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+int set_tai(int offset)
+{
+       struct timex tx;
+
+       memset(&tx, 0, sizeof(tx));
+
+       tx.modes = ADJ_TAI;
+       tx.constant = offset;
+
+       return adjtimex(&tx);
+}
+
+int get_tai(void)
+{
+       struct timex tx;
+
+       memset(&tx, 0, sizeof(tx));
+
+       adjtimex(&tx);
+       return tx.tai;
+}
+
+int main(int argc, char **argv)
+{
+       int i, ret;
+
+       ret = get_tai();
+       printf("tai offset started at %i\n", ret);
+
+       printf("Checking tai offsets can be properly set: ");
+       for (i = 1; i <= 60; i++) {
+               ret = set_tai(i);
+               ret = get_tai();
+               if (ret != i) {
+                       printf("[FAILED] expected: %i got %i\n", i, ret);
+                       return ksft_exit_fail();
+               }
+       }
+       printf("[OK]\n");
+       return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/set-timer-lat.c b/tools/testing/selftests/timers/set-timer-lat.c
new file mode 100644 (file)
index 0000000..4fc98c5
--- /dev/null
@@ -0,0 +1,216 @@
+/* set_timer latency test
+ *             John Stultz (john.stultz@linaro.org)
+ *              (C) Copyright Linaro 2014
+ *              Licensed under the GPLv2
+ *
+ *   This test makes sure the set_timer api is correct
+ *
+ *  To build:
+ *     $ gcc set-timer-lat.c -o set-timer-lat -lrt
+ *
+ *   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 <stdio.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <pthread.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+#define CLOCK_REALTIME                 0
+#define CLOCK_MONOTONIC                        1
+#define CLOCK_PROCESS_CPUTIME_ID       2
+#define CLOCK_THREAD_CPUTIME_ID                3
+#define CLOCK_MONOTONIC_RAW            4
+#define CLOCK_REALTIME_COARSE          5
+#define CLOCK_MONOTONIC_COARSE         6
+#define CLOCK_BOOTTIME                 7
+#define CLOCK_REALTIME_ALARM           8
+#define CLOCK_BOOTTIME_ALARM           9
+#define CLOCK_HWSPECIFIC               10
+#define CLOCK_TAI                      11
+#define NR_CLOCKIDS                    12
+
+
+#define NSEC_PER_SEC 1000000000ULL
+#define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */
+
+#define TIMER_SECS 1
+int alarmcount;
+int clock_id;
+struct timespec start_time;
+long long max_latency_ns;
+
+char *clockstring(int clockid)
+{
+       switch (clockid) {
+       case CLOCK_REALTIME:
+               return "CLOCK_REALTIME";
+       case CLOCK_MONOTONIC:
+               return "CLOCK_MONOTONIC";
+       case CLOCK_PROCESS_CPUTIME_ID:
+               return "CLOCK_PROCESS_CPUTIME_ID";
+       case CLOCK_THREAD_CPUTIME_ID:
+               return "CLOCK_THREAD_CPUTIME_ID";
+       case CLOCK_MONOTONIC_RAW:
+               return "CLOCK_MONOTONIC_RAW";
+       case CLOCK_REALTIME_COARSE:
+               return "CLOCK_REALTIME_COARSE";
+       case CLOCK_MONOTONIC_COARSE:
+               return "CLOCK_MONOTONIC_COARSE";
+       case CLOCK_BOOTTIME:
+               return "CLOCK_BOOTTIME";
+       case CLOCK_REALTIME_ALARM:
+               return "CLOCK_REALTIME_ALARM";
+       case CLOCK_BOOTTIME_ALARM:
+               return "CLOCK_BOOTTIME_ALARM";
+       case CLOCK_TAI:
+               return "CLOCK_TAI";
+       };
+       return "UNKNOWN_CLOCKID";
+}
+
+
+long long timespec_sub(struct timespec a, struct timespec b)
+{
+       long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
+
+       ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
+       return ret;
+}
+
+
+void sigalarm(int signo)
+{
+       long long delta_ns;
+       struct timespec ts;
+
+       clock_gettime(clock_id, &ts);
+       alarmcount++;
+
+       delta_ns = timespec_sub(start_time, ts);
+       delta_ns -= NSEC_PER_SEC * TIMER_SECS * alarmcount;
+
+       if (delta_ns < 0)
+               printf("%s timer fired early: FAIL\n", clockstring(clock_id));
+
+       if (delta_ns > max_latency_ns)
+               max_latency_ns = delta_ns;
+}
+
+int do_timer(int clock_id, int flags)
+{
+       struct sigevent se;
+       timer_t tm1;
+       struct itimerspec its1, its2;
+       int err;
+
+       /* Set up timer: */
+       memset(&se, 0, sizeof(se));
+       se.sigev_notify = SIGEV_SIGNAL;
+       se.sigev_signo = SIGRTMAX;
+       se.sigev_value.sival_int = 0;
+
+       max_latency_ns = 0;
+       alarmcount = 0;
+
+       err = timer_create(clock_id, &se, &tm1);
+       if (err) {
+               if ((clock_id == CLOCK_REALTIME_ALARM) ||
+                   (clock_id == CLOCK_BOOTTIME_ALARM)) {
+                       printf("%-22s %s missing CAP_WAKE_ALARM?    : [UNSUPPORTED]\n",
+                                       clockstring(clock_id),
+                                       flags ? "ABSTIME":"RELTIME");
+                       return 0;
+               }
+               printf("%s - timer_create() failed\n", clockstring(clock_id));
+               return -1;
+       }
+
+       clock_gettime(clock_id, &start_time);
+       if (flags) {
+               its1.it_value = start_time;
+               its1.it_value.tv_sec += TIMER_SECS;
+       } else {
+               its1.it_value.tv_sec = TIMER_SECS;
+               its1.it_value.tv_nsec = 0;
+       }
+       its1.it_interval.tv_sec = TIMER_SECS;
+       its1.it_interval.tv_nsec = 0;
+
+       err = timer_settime(tm1, flags, &its1, &its2);
+       if (err) {
+               printf("%s - timer_settime() failed\n", clockstring(clock_id));
+               return -1;
+       }
+
+       while (alarmcount < 5)
+               sleep(1);
+
+       printf("%-22s %s max latency: %10lld ns : ",
+                       clockstring(clock_id),
+                       flags ? "ABSTIME":"RELTIME",
+                       max_latency_ns);
+
+       timer_delete(tm1);
+       if (max_latency_ns < UNRESONABLE_LATENCY) {
+               printf("[OK]\n");
+               return 0;
+       }
+       printf("[FAILED]\n");
+       return -1;
+}
+
+int main(void)
+{
+       struct sigaction act;
+       int signum = SIGRTMAX;
+       int ret = 0;
+
+       /* Set up signal handler: */
+       sigfillset(&act.sa_mask);
+       act.sa_flags = 0;
+       act.sa_handler = sigalarm;
+       sigaction(signum, &act, NULL);
+
+       printf("Setting timers for every %i seconds\n", TIMER_SECS);
+       for (clock_id = 0; clock_id < NR_CLOCKIDS; clock_id++) {
+
+               if ((clock_id == CLOCK_PROCESS_CPUTIME_ID) ||
+                               (clock_id == CLOCK_THREAD_CPUTIME_ID) ||
+                               (clock_id == CLOCK_MONOTONIC_RAW) ||
+                               (clock_id == CLOCK_REALTIME_COARSE) ||
+                               (clock_id == CLOCK_MONOTONIC_COARSE) ||
+                               (clock_id == CLOCK_HWSPECIFIC))
+                       continue;
+
+               ret |= do_timer(clock_id, TIMER_ABSTIME);
+               ret |= do_timer(clock_id, 0);
+       }
+       if (ret)
+               return ksft_exit_fail();
+       return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/skew_consistency.c b/tools/testing/selftests/timers/skew_consistency.c
new file mode 100644 (file)
index 0000000..5562f84
--- /dev/null
@@ -0,0 +1,89 @@
+/* ADJ_FREQ Skew consistency test
+ *             by: john stultz (johnstul@us.ibm.com)
+ *             (C) Copyright IBM 2012
+ *             Licensed under the GPLv2
+ *
+ *  NOTE: This is a meta-test which cranks the ADJ_FREQ knob back
+ *  and forth and watches for consistency problems. Thus this test requires
+ *  that the inconsistency-check tests be present in the same directory it
+ *  is run from.
+ *
+ *  To build:
+ *     $ gcc skew_consistency.c -o skew_consistency -lrt
+ *
+ *   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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+#define NSEC_PER_SEC 1000000000LL
+
+int main(int argv, char **argc)
+{
+       struct timex tx;
+       int ret, ppm;
+       pid_t pid;
+
+
+       printf("Running Asyncrhonous Frequency Changing Tests...\n");
+
+       pid = fork();
+       if (!pid)
+               return system("./inconsistency-check -c 1 -t 600");
+
+       ppm = 500;
+       ret = 0;
+
+       while (pid != waitpid(pid, &ret, WNOHANG)) {
+               ppm = -ppm;
+               tx.modes = ADJ_FREQUENCY;
+               tx.freq = ppm << 16;
+               adjtimex(&tx);
+               usleep(500000);
+       }
+
+       /* Set things back */
+       tx.modes = ADJ_FREQUENCY;
+       tx.offset = 0;
+       adjtimex(&tx);
+
+
+       if (ret) {
+               printf("[FAILED]\n");
+               return ksft_exit_fail();
+       }
+       printf("[OK]\n");
+       return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/threadtest.c b/tools/testing/selftests/timers/threadtest.c
new file mode 100644 (file)
index 0000000..e632e11
--- /dev/null
@@ -0,0 +1,204 @@
+/* threadtest.c
+ *             by: john stultz (johnstul@us.ibm.com)
+ *             (C) Copyright IBM 2004, 2005, 2006, 2012
+ *             Licensed under the GPLv2
+ *
+ *  To build:
+ *     $ gcc threadtest.c -o threadtest -lrt
+ *
+ *   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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <pthread.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+
+/* serializes shared list access */
+pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;
+/* serializes console output */
+pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+#define MAX_THREADS 128
+#define LISTSIZE 128
+
+int done = 0;
+
+struct timespec global_list[LISTSIZE];
+int listcount = 0;
+
+
+void checklist(struct timespec *list, int size)
+{
+       int i, j;
+       struct timespec *a, *b;
+
+       /* scan the list */
+       for (i = 0; i < size-1; i++) {
+               a = &list[i];
+               b = &list[i+1];
+
+               /* look for any time inconsistencies */
+               if ((b->tv_sec <= a->tv_sec) &&
+                       (b->tv_nsec < a->tv_nsec)) {
+
+                       /* flag other threads */
+                       done = 1;
+
+                       /*serialize printing to avoid junky output*/
+                       pthread_mutex_lock(&print_lock);
+
+                       /* dump the list */
+                       printf("\n");
+                       for (j = 0; j < size; j++) {
+                               if (j == i)
+                                       printf("---------------\n");
+                               printf("%lu:%lu\n", list[j].tv_sec, list[j].tv_nsec);
+                               if (j == i+1)
+                                       printf("---------------\n");
+                       }
+                       printf("[FAILED]\n");
+
+                       pthread_mutex_unlock(&print_lock);
+               }
+       }
+}
+
+/* The shared thread shares a global list
+ * that each thread fills while holding the lock.
+ * This stresses clock syncronization across cpus.
+ */
+void *shared_thread(void *arg)
+{
+       while (!done) {
+               /* protect the list */
+               pthread_mutex_lock(&list_lock);
+
+               /* see if we're ready to check the list */
+               if (listcount >= LISTSIZE) {
+                       checklist(global_list, LISTSIZE);
+                       listcount = 0;
+               }
+               clock_gettime(CLOCK_MONOTONIC, &global_list[listcount++]);
+
+               pthread_mutex_unlock(&list_lock);
+       }
+       return NULL;
+}
+
+
+/* Each independent thread fills in its own
+ * list. This stresses clock_gettime() lock contention.
+ */
+void *independent_thread(void *arg)
+{
+       struct timespec my_list[LISTSIZE];
+       int count;
+
+       while (!done) {
+               /* fill the list */
+               for (count = 0; count < LISTSIZE; count++)
+                       clock_gettime(CLOCK_MONOTONIC, &my_list[count]);
+               checklist(my_list, LISTSIZE);
+       }
+       return NULL;
+}
+
+#define DEFAULT_THREAD_COUNT 8
+#define DEFAULT_RUNTIME 30
+
+int main(int argc, char **argv)
+{
+       int thread_count, i;
+       time_t start, now, runtime;
+       char buf[255];
+       pthread_t pth[MAX_THREADS];
+       int opt;
+       void *tret;
+       int ret = 0;
+       void *(*thread)(void *) = shared_thread;
+
+       thread_count = DEFAULT_THREAD_COUNT;
+       runtime = DEFAULT_RUNTIME;
+
+       /* Process arguments */
+       while ((opt = getopt(argc, argv, "t:n:i")) != -1) {
+               switch (opt) {
+               case 't':
+                       runtime = atoi(optarg);
+                       break;
+               case 'n':
+                       thread_count = atoi(optarg);
+                       break;
+               case 'i':
+                       thread = independent_thread;
+                       printf("using independent threads\n");
+                       break;
+               default:
+                       printf("Usage: %s [-t <secs>] [-n <numthreads>] [-i]\n", argv[0]);
+                       printf("        -t: time to run\n");
+                       printf("        -n: number of threads\n");
+                       printf("        -i: use independent threads\n");
+                       return -1;
+               }
+       }
+
+       if (thread_count > MAX_THREADS)
+               thread_count = MAX_THREADS;
+
+
+       setbuf(stdout, NULL);
+
+       start = time(0);
+       strftime(buf, 255, "%a, %d %b %Y %T %z", localtime(&start));
+       printf("%s\n", buf);
+       printf("Testing consistency with %i threads for %ld seconds: ", thread_count, runtime);
+
+       /* spawn */
+       for (i = 0; i < thread_count; i++)
+               pthread_create(&pth[i], 0, thread, 0);
+
+       while (time(&now) < start + runtime) {
+               sleep(1);
+               if (done) {
+                       ret = 1;
+                       strftime(buf, 255, "%a, %d %b %Y %T %z", localtime(&now));
+                       printf("%s\n", buf);
+                       goto out;
+               }
+       }
+       printf("[OK]\n");
+       done = 1;
+
+out:
+       /* wait */
+       for (i = 0; i < thread_count; i++)
+               pthread_join(pth[i], &tret);
+
+       /* die */
+       if (ret)
+               ksft_exit_fail();
+       return ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c
new file mode 100644 (file)
index 0000000..e86d937
--- /dev/null
@@ -0,0 +1,202 @@
+/* valid adjtimex test
+ *              by: John Stultz <john.stultz@linaro.org>
+ *              (C) Copyright Linaro 2015
+ *              Licensed under the GPLv2
+ *
+ *  This test validates adjtimex interface with valid
+ *  and invalid test data.
+ *
+ *  Usage: valid-adjtimex
+ *
+ *  To build:
+ *     $ gcc valid-adjtimex.c -o valid-adjtimex -lrt
+ *
+ *   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 <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#ifdef KTEST
+#include "../kselftest.h"
+#else
+static inline int ksft_exit_pass(void)
+{
+       exit(0);
+}
+static inline int ksft_exit_fail(void)
+{
+       exit(1);
+}
+#endif
+
+#define NSEC_PER_SEC 1000000000L
+
+/* clear NTP time_status & time_state */
+int clear_time_state(void)
+{
+       struct timex tx;
+       int ret;
+
+       tx.modes = ADJ_STATUS;
+       tx.status = 0;
+       ret = adjtimex(&tx);
+       return ret;
+}
+
+#define NUM_FREQ_VALID 32
+#define NUM_FREQ_OUTOFRANGE 4
+#define NUM_FREQ_INVALID 2
+
+long valid_freq[NUM_FREQ_VALID] = {
+       -499<<16,
+       -450<<16,
+       -400<<16,
+       -350<<16,
+       -300<<16,
+       -250<<16,
+       -200<<16,
+       -150<<16,
+       -100<<16,
+       -75<<16,
+       -50<<16,
+       -25<<16,
+       -10<<16,
+       -5<<16,
+       -1<<16,
+       -1000,
+       1<<16,
+       5<<16,
+       10<<16,
+       25<<16,
+       50<<16,
+       75<<16,
+       100<<16,
+       150<<16,
+       200<<16,
+       250<<16,
+       300<<16,
+       350<<16,
+       400<<16,
+       450<<16,
+       499<<16,
+};
+
+long outofrange_freq[NUM_FREQ_OUTOFRANGE] = {
+       -1000<<16,
+       -550<<16,
+       550<<16,
+       1000<<16,
+};
+
+#define LONG_MAX (~0UL>>1)
+#define LONG_MIN (-LONG_MAX - 1)
+
+long invalid_freq[NUM_FREQ_INVALID] = {
+       LONG_MAX,
+       LONG_MIN,
+};
+
+int validate_freq(void)
+{
+       struct timex tx;
+       int ret, pass = 0;
+       int i;
+
+       clear_time_state();
+
+       memset(&tx, 0, sizeof(struct timex));
+       /* Set the leap second insert flag */
+
+       printf("Testing ADJ_FREQ... ");
+       for (i = 0; i < NUM_FREQ_VALID; i++) {
+               tx.modes = ADJ_FREQUENCY;
+               tx.freq = valid_freq[i];
+
+               ret = adjtimex(&tx);
+               if (ret < 0) {
+                       printf("[FAIL]\n");
+                       printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n",
+                               valid_freq[i], valid_freq[i]>>16);
+                       pass = -1;
+                       goto out;
+               }
+               tx.modes = 0;
+               ret = adjtimex(&tx);
+               if (tx.freq != valid_freq[i]) {
+                       printf("Warning: freq value %ld not what we set it (%ld)!\n",
+                                       tx.freq, valid_freq[i]);
+               }
+       }
+       for (i = 0; i < NUM_FREQ_OUTOFRANGE; i++) {
+               tx.modes = ADJ_FREQUENCY;
+               tx.freq = outofrange_freq[i];
+
+               ret = adjtimex(&tx);
+               if (ret < 0) {
+                       printf("[FAIL]\n");
+                       printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n",
+                               outofrange_freq[i], outofrange_freq[i]>>16);
+                       pass = -1;
+                       goto out;
+               }
+               tx.modes = 0;
+               ret = adjtimex(&tx);
+               if (tx.freq == outofrange_freq[i]) {
+                       printf("[FAIL]\n");
+                       printf("ERROR: out of range value %ld actually set!\n",
+                                       tx.freq);
+                       pass = -1;
+                       goto out;
+               }
+       }
+
+
+       if (sizeof(long) == 8) { /* this case only applies to 64bit systems */
+               for (i = 0; i < NUM_FREQ_INVALID; i++) {
+                       tx.modes = ADJ_FREQUENCY;
+                       tx.freq = invalid_freq[i];
+                       ret = adjtimex(&tx);
+                       if (ret >= 0) {
+                               printf("[FAIL]\n");
+                               printf("Error: No failure on invalid ADJ_FREQUENCY %ld\n",
+                                       invalid_freq[i]);
+                               pass = -1;
+                               goto out;
+                       }
+               }
+       }
+
+       printf("[OK]\n");
+out:
+       /* reset freq to zero */
+       tx.modes = ADJ_FREQUENCY;
+       tx.freq = 0;
+       ret = adjtimex(&tx);
+
+       return pass;
+}
+
+
+int main(int argc, char **argv)
+{
+       if (validate_freq())
+               return ksft_exit_fail();
+
+       return ksft_exit_pass();
+}
index 12c9d15bab075a6eaaa5f171a0833841c829b470..d401b63c5b1ad09273d2228add75d8635694172f 100644 (file)
@@ -3,5 +3,6 @@
 # No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
 all:
 
-run_tests: all
-       ./test_user_copy.sh
+TEST_PROGS := test_user_copy.sh
+
+include ../lib.mk
index 077828c889f1377886b98c93349919d55ccb57a2..a5ce9534eb15f35335b389ec89f0379bfc45c224 100644 (file)
@@ -1,6 +1,5 @@
 # Makefile for vm selftests
 
-CC = $(CROSS_COMPILE)gcc
 CFLAGS = -Wall
 BINARIES = hugepage-mmap hugepage-shm map_hugetlb thuge-gen hugetlbfstest
 BINARIES += transhuge-stress
@@ -9,8 +8,10 @@ all: $(BINARIES)
 %: %.c
        $(CC) $(CFLAGS) -o $@ $^ -lrt
 
-run_tests: all
-       @/bin/sh ./run_vmtests || (echo "vmtests: [FAIL]"; exit 1)
+TEST_PROGS := run_vmtests
+TEST_FILES := $(BINARIES)
+
+include ../lib.mk
 
 clean:
        $(RM) $(BINARIES)
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/tools/testing/selftests/x86/.gitignore b/tools/testing/selftests/x86/.gitignore
new file mode 100644 (file)
index 0000000..15034fe
--- /dev/null
@@ -0,0 +1,2 @@
+*_32
+*_64
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
new file mode 100644 (file)
index 0000000..f0a7918
--- /dev/null
@@ -0,0 +1,48 @@
+.PHONY: all all_32 all_64 check_build32 clean run_tests
+
+TARGETS_C_BOTHBITS := sigreturn
+
+BINARIES_32 := $(TARGETS_C_BOTHBITS:%=%_32)
+BINARIES_64 := $(TARGETS_C_BOTHBITS:%=%_64)
+
+CFLAGS := -O2 -g -std=gnu99 -pthread -Wall
+
+UNAME_P := $(shell uname -p)
+
+# Always build 32-bit tests
+all: all_32
+
+# If we're on a 64-bit host, build 64-bit tests as well
+ifeq ($(shell uname -p),x86_64)
+all: all_64
+endif
+
+all_32: check_build32 $(BINARIES_32)
+
+all_64: $(BINARIES_64)
+
+clean:
+       $(RM) $(BINARIES_32) $(BINARIES_64)
+
+run_tests:
+       ./run_x86_tests.sh
+
+$(TARGETS_C_BOTHBITS:%=%_32): %_32: %.c
+       $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
+
+$(TARGETS_C_BOTHBITS:%=%_64): %_64: %.c
+       $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
+
+check_build32:
+       @if ! $(CC) -m32 -o /dev/null trivial_32bit_program.c; then     \
+         echo "Warning: you seem to have a broken 32-bit build" 2>&1;  \
+         echo "environment.  If you are using a Debian-like";          \
+         echo " distribution, try:";                                   \
+         echo "";                                                      \
+         echo "  apt-get install gcc-multilib libc6-i386 libc6-dev-i386"; \
+         echo "";                                                      \
+         echo "If you are using a Fedora-like distribution, try:";     \
+         echo "";                                                      \
+         echo "  yum install glibc-devel.*i686";                       \
+         exit 1;                                                       \
+       fi
diff --git a/tools/testing/selftests/x86/run_x86_tests.sh b/tools/testing/selftests/x86/run_x86_tests.sh
new file mode 100644 (file)
index 0000000..3d3ec65
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# This is deliberately minimal.  IMO kselftests should provide a standard
+# script here.
+./sigreturn_32 || exit 1
+
+if [[ "$uname -p" -eq "x86_64" ]]; then
+    ./sigreturn_64 || exit 1
+fi
+
+exit 0
diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c
new file mode 100644 (file)
index 0000000..b5aa1ba
--- /dev/null
@@ -0,0 +1,684 @@
+/*
+ * sigreturn.c - tests for x86 sigreturn(2) and exit-to-userspace
+ * Copyright (c) 2014-2015 Andrew Lutomirski
+ *
+ * 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.
+ *
+ * This is a series of tests that exercises the sigreturn(2) syscall and
+ * the IRET / SYSRET paths in the kernel.
+ *
+ * For now, this focuses on the effects of unusual CS and SS values,
+ * and it has a bunch of tests to make sure that ESP/RSP is restored
+ * properly.
+ *
+ * The basic idea behind these tests is to raise(SIGUSR1) to create a
+ * sigcontext frame, plug in the values to be tested, and then return,
+ * which implicitly invokes sigreturn(2) and programs the user context
+ * as desired.
+ *
+ * For tests for which we expect sigreturn and the subsequent return to
+ * user mode to succeed, we return to a short trampoline that generates
+ * SIGTRAP so that the meat of the tests can be ordinary C code in a
+ * SIGTRAP handler.
+ *
+ * The inner workings of each test is documented below.
+ *
+ * Do not run on outdated, unpatched kernels at risk of nasty crashes.
+ */
+
+#define _GNU_SOURCE
+
+#include <sys/time.h>
+#include <time.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/mman.h>
+#include <sys/signal.h>
+#include <sys/ucontext.h>
+#include <asm/ldt.h>
+#include <err.h>
+#include <setjmp.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <sys/ptrace.h>
+#include <sys/user.h>
+
+/*
+ * In principle, this test can run on Linux emulation layers (e.g.
+ * Illumos "LX branded zones").  Solaris-based kernels reserve LDT
+ * entries 0-5 for their own internal purposes, so start our LDT
+ * allocations above that reservation.  (The tests don't pass on LX
+ * branded zones, but at least this lets them run.)
+ */
+#define LDT_OFFSET 6
+
+/* An aligned stack accessible through some of our segments. */
+static unsigned char stack16[65536] __attribute__((aligned(4096)));
+
+/*
+ * An aligned int3 instruction used as a trampoline.  Some of the tests
+ * want to fish out their ss values, so this trampoline copies ss to eax
+ * before the int3.
+ */
+asm (".pushsection .text\n\t"
+     ".type int3, @function\n\t"
+     ".align 4096\n\t"
+     "int3:\n\t"
+     "mov %ss,%eax\n\t"
+     "int3\n\t"
+     ".size int3, . - int3\n\t"
+     ".align 4096, 0xcc\n\t"
+     ".popsection");
+extern char int3[4096];
+
+/*
+ * At startup, we prepapre:
+ *
+ * - ldt_nonexistent_sel: An LDT entry that doesn't exist (all-zero
+ *   descriptor or out of bounds).
+ * - code16_sel: A 16-bit LDT code segment pointing to int3.
+ * - data16_sel: A 16-bit LDT data segment pointing to stack16.
+ * - npcode32_sel: A 32-bit not-present LDT code segment pointing to int3.
+ * - npdata32_sel: A 32-bit not-present LDT data segment pointing to stack16.
+ * - gdt_data16_idx: A 16-bit GDT data segment pointing to stack16.
+ * - gdt_npdata32_idx: A 32-bit not-present GDT data segment pointing to
+ *   stack16.
+ *
+ * For no particularly good reason, xyz_sel is a selector value with the
+ * RPL and LDT bits filled in, whereas xyz_idx is just an index into the
+ * descriptor table.  These variables will be zero if their respective
+ * segments could not be allocated.
+ */
+static unsigned short ldt_nonexistent_sel;
+static unsigned short code16_sel, data16_sel, npcode32_sel, npdata32_sel;
+
+static unsigned short gdt_data16_idx, gdt_npdata32_idx;
+
+static unsigned short GDT3(int idx)
+{
+       return (idx << 3) | 3;
+}
+
+static unsigned short LDT3(int idx)
+{
+       return (idx << 3) | 7;
+}
+
+/* Our sigaltstack scratch space. */
+static char altstack_data[SIGSTKSZ];
+
+static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
+                      int flags)
+{
+       struct sigaction sa;
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_sigaction = handler;
+       sa.sa_flags = SA_SIGINFO | flags;
+       sigemptyset(&sa.sa_mask);
+       if (sigaction(sig, &sa, 0))
+               err(1, "sigaction");
+}
+
+static void clearhandler(int sig)
+{
+       struct sigaction sa;
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_handler = SIG_DFL;
+       sigemptyset(&sa.sa_mask);
+       if (sigaction(sig, &sa, 0))
+               err(1, "sigaction");
+}
+
+static void add_ldt(const struct user_desc *desc, unsigned short *var,
+                   const char *name)
+{
+       if (syscall(SYS_modify_ldt, 1, desc, sizeof(*desc)) == 0) {
+               *var = LDT3(desc->entry_number);
+       } else {
+               printf("[NOTE]\tFailed to create %s segment\n", name);
+               *var = 0;
+       }
+}
+
+static void setup_ldt(void)
+{
+       if ((unsigned long)stack16 > (1ULL << 32) - sizeof(stack16))
+               errx(1, "stack16 is too high\n");
+       if ((unsigned long)int3 > (1ULL << 32) - sizeof(int3))
+               errx(1, "int3 is too high\n");
+
+       ldt_nonexistent_sel = LDT3(LDT_OFFSET + 2);
+
+       const struct user_desc code16_desc = {
+               .entry_number    = LDT_OFFSET + 0,
+               .base_addr       = (unsigned long)int3,
+               .limit           = 4095,
+               .seg_32bit       = 0,
+               .contents        = 2, /* Code, not conforming */
+               .read_exec_only  = 0,
+               .limit_in_pages  = 0,
+               .seg_not_present = 0,
+               .useable         = 0
+       };
+       add_ldt(&code16_desc, &code16_sel, "code16");
+
+       const struct user_desc data16_desc = {
+               .entry_number    = LDT_OFFSET + 1,
+               .base_addr       = (unsigned long)stack16,
+               .limit           = 0xffff,
+               .seg_32bit       = 0,
+               .contents        = 0, /* Data, grow-up */
+               .read_exec_only  = 0,
+               .limit_in_pages  = 0,
+               .seg_not_present = 0,
+               .useable         = 0
+       };
+       add_ldt(&data16_desc, &data16_sel, "data16");
+
+       const struct user_desc npcode32_desc = {
+               .entry_number    = LDT_OFFSET + 3,
+               .base_addr       = (unsigned long)int3,
+               .limit           = 4095,
+               .seg_32bit       = 1,
+               .contents        = 2, /* Code, not conforming */
+               .read_exec_only  = 0,
+               .limit_in_pages  = 0,
+               .seg_not_present = 1,
+               .useable         = 0
+       };
+       add_ldt(&npcode32_desc, &npcode32_sel, "npcode32");
+
+       const struct user_desc npdata32_desc = {
+               .entry_number    = LDT_OFFSET + 4,
+               .base_addr       = (unsigned long)stack16,
+               .limit           = 0xffff,
+               .seg_32bit       = 1,
+               .contents        = 0, /* Data, grow-up */
+               .read_exec_only  = 0,
+               .limit_in_pages  = 0,
+               .seg_not_present = 1,
+               .useable         = 0
+       };
+       add_ldt(&npdata32_desc, &npdata32_sel, "npdata32");
+
+       struct user_desc gdt_data16_desc = {
+               .entry_number    = -1,
+               .base_addr       = (unsigned long)stack16,
+               .limit           = 0xffff,
+               .seg_32bit       = 0,
+               .contents        = 0, /* Data, grow-up */
+               .read_exec_only  = 0,
+               .limit_in_pages  = 0,
+               .seg_not_present = 0,
+               .useable         = 0
+       };
+
+       if (syscall(SYS_set_thread_area, &gdt_data16_desc) == 0) {
+               /*
+                * This probably indicates vulnerability to CVE-2014-8133.
+                * Merely getting here isn't definitive, though, and we'll
+                * diagnose the problem for real later on.
+                */
+               printf("[WARN]\tset_thread_area allocated data16 at index %d\n",
+                      gdt_data16_desc.entry_number);
+               gdt_data16_idx = gdt_data16_desc.entry_number;
+       } else {
+               printf("[OK]\tset_thread_area refused 16-bit data\n");
+       }
+
+       struct user_desc gdt_npdata32_desc = {
+               .entry_number    = -1,
+               .base_addr       = (unsigned long)stack16,
+               .limit           = 0xffff,
+               .seg_32bit       = 1,
+               .contents        = 0, /* Data, grow-up */
+               .read_exec_only  = 0,
+               .limit_in_pages  = 0,
+               .seg_not_present = 1,
+               .useable         = 0
+       };
+
+       if (syscall(SYS_set_thread_area, &gdt_npdata32_desc) == 0) {
+               /*
+                * As a hardening measure, newer kernels don't allow this.
+                */
+               printf("[WARN]\tset_thread_area allocated npdata32 at index %d\n",
+                      gdt_npdata32_desc.entry_number);
+               gdt_npdata32_idx = gdt_npdata32_desc.entry_number;
+       } else {
+               printf("[OK]\tset_thread_area refused 16-bit data\n");
+       }
+}
+
+/* State used by our signal handlers. */
+static gregset_t initial_regs, requested_regs, resulting_regs;
+
+/* Instructions for the SIGUSR1 handler. */
+static volatile unsigned short sig_cs, sig_ss;
+static volatile sig_atomic_t sig_trapped, sig_err, sig_trapno;
+
+/* Abstractions for some 32-bit vs 64-bit differences. */
+#ifdef __x86_64__
+# define REG_IP REG_RIP
+# define REG_SP REG_RSP
+# define REG_AX REG_RAX
+
+struct selectors {
+       unsigned short cs, gs, fs, ss;
+};
+
+static unsigned short *ssptr(ucontext_t *ctx)
+{
+       struct selectors *sels = (void *)&ctx->uc_mcontext.gregs[REG_CSGSFS];
+       return &sels->ss;
+}
+
+static unsigned short *csptr(ucontext_t *ctx)
+{
+       struct selectors *sels = (void *)&ctx->uc_mcontext.gregs[REG_CSGSFS];
+       return &sels->cs;
+}
+#else
+# define REG_IP REG_EIP
+# define REG_SP REG_ESP
+# define REG_AX REG_EAX
+
+static greg_t *ssptr(ucontext_t *ctx)
+{
+       return &ctx->uc_mcontext.gregs[REG_SS];
+}
+
+static greg_t *csptr(ucontext_t *ctx)
+{
+       return &ctx->uc_mcontext.gregs[REG_CS];
+}
+#endif
+
+/* Number of errors in the current test case. */
+static volatile sig_atomic_t nerrs;
+
+/*
+ * SIGUSR1 handler.  Sets CS and SS as requested and points IP to the
+ * int3 trampoline.  Sets SP to a large known value so that we can see
+ * whether the value round-trips back to user mode correctly.
+ */
+static void sigusr1(int sig, siginfo_t *info, void *ctx_void)
+{
+       ucontext_t *ctx = (ucontext_t*)ctx_void;
+
+       memcpy(&initial_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
+
+       *csptr(ctx) = sig_cs;
+       *ssptr(ctx) = sig_ss;
+
+       ctx->uc_mcontext.gregs[REG_IP] =
+               sig_cs == code16_sel ? 0 : (unsigned long)&int3;
+       ctx->uc_mcontext.gregs[REG_SP] = (unsigned long)0x8badf00d5aadc0deULL;
+       ctx->uc_mcontext.gregs[REG_AX] = 0;
+
+       memcpy(&requested_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
+       requested_regs[REG_AX] = *ssptr(ctx);   /* The asm code does this. */
+
+       return;
+}
+
+/*
+ * Called after a successful sigreturn.  Restores our state so that
+ * the original raise(SIGUSR1) returns.
+ */
+static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
+{
+       ucontext_t *ctx = (ucontext_t*)ctx_void;
+
+       sig_err = ctx->uc_mcontext.gregs[REG_ERR];
+       sig_trapno = ctx->uc_mcontext.gregs[REG_TRAPNO];
+
+       unsigned short ss;
+       asm ("mov %%ss,%0" : "=r" (ss));
+
+       greg_t asm_ss = ctx->uc_mcontext.gregs[REG_AX];
+       if (asm_ss != sig_ss && sig == SIGTRAP) {
+               /* Sanity check failure. */
+               printf("[FAIL]\tSIGTRAP: ss = %hx, frame ss = %hx, ax = %llx\n",
+                      ss, *ssptr(ctx), (unsigned long long)asm_ss);
+               nerrs++;
+       }
+
+       memcpy(&resulting_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
+       memcpy(&ctx->uc_mcontext.gregs, &initial_regs, sizeof(gregset_t));
+
+       sig_trapped = sig;
+}
+
+/*
+ * Checks a given selector for its code bitness or returns -1 if it's not
+ * a usable code segment selector.
+ */
+int cs_bitness(unsigned short cs)
+{
+       uint32_t valid = 0, ar;
+       asm ("lar %[cs], %[ar]\n\t"
+            "jnz 1f\n\t"
+            "mov $1, %[valid]\n\t"
+            "1:"
+            : [ar] "=r" (ar), [valid] "+rm" (valid)
+            : [cs] "r" (cs));
+
+       if (!valid)
+               return -1;
+
+       bool db = (ar & (1 << 22));
+       bool l = (ar & (1 << 21));
+
+       if (!(ar & (1<<11)))
+           return -1;  /* Not code. */
+
+       if (l && !db)
+               return 64;
+       else if (!l && db)
+               return 32;
+       else if (!l && !db)
+               return 16;
+       else
+               return -1;      /* Unknown bitness. */
+}
+
+/* Finds a usable code segment of the requested bitness. */
+int find_cs(int bitness)
+{
+       unsigned short my_cs;
+
+       asm ("mov %%cs,%0" :  "=r" (my_cs));
+
+       if (cs_bitness(my_cs) == bitness)
+               return my_cs;
+       if (cs_bitness(my_cs + (2 << 3)) == bitness)
+               return my_cs + (2 << 3);
+       if (my_cs > (2<<3) && cs_bitness(my_cs - (2 << 3)) == bitness)
+           return my_cs - (2 << 3);
+       if (cs_bitness(code16_sel) == bitness)
+               return code16_sel;
+
+       printf("[WARN]\tCould not find %d-bit CS\n", bitness);
+       return -1;
+}
+
+static int test_valid_sigreturn(int cs_bits, bool use_16bit_ss, int force_ss)
+{
+       int cs = find_cs(cs_bits);
+       if (cs == -1) {
+               printf("[SKIP]\tCode segment unavailable for %d-bit CS, %d-bit SS\n",
+                      cs_bits, use_16bit_ss ? 16 : 32);
+               return 0;
+       }
+
+       if (force_ss != -1) {
+               sig_ss = force_ss;
+       } else {
+               if (use_16bit_ss) {
+                       if (!data16_sel) {
+                               printf("[SKIP]\tData segment unavailable for %d-bit CS, 16-bit SS\n",
+                                      cs_bits);
+                               return 0;
+                       }
+                       sig_ss = data16_sel;
+               } else {
+                       asm volatile ("mov %%ss,%0" : "=r" (sig_ss));
+               }
+       }
+
+       sig_cs = cs;
+
+       printf("[RUN]\tValid sigreturn: %d-bit CS (%hx), %d-bit SS (%hx%s)\n",
+              cs_bits, sig_cs, use_16bit_ss ? 16 : 32, sig_ss,
+              (sig_ss & 4) ? "" : ", GDT");
+
+       raise(SIGUSR1);
+
+       nerrs = 0;
+
+       /*
+        * Check that each register had an acceptable value when the
+        * int3 trampoline was invoked.
+        */
+       for (int i = 0; i < NGREG; i++) {
+               greg_t req = requested_regs[i], res = resulting_regs[i];
+               if (i == REG_TRAPNO || i == REG_IP)
+                       continue;       /* don't care */
+               if (i == REG_SP) {
+                       printf("\tSP: %llx -> %llx\n", (unsigned long long)req,
+                              (unsigned long long)res);
+
+                       /*
+                        * In many circumstances, the high 32 bits of rsp
+                        * are zeroed.  For example, we could be a real
+                        * 32-bit program, or we could hit any of a number
+                        * of poorly-documented IRET or segmented ESP
+                        * oddities.  If this happens, it's okay.
+                        */
+                       if (res == (req & 0xFFFFFFFF))
+                               continue;  /* OK; not expected to work */
+               }
+
+               bool ignore_reg = false;
+#if __i386__
+               if (i == REG_UESP)
+                       ignore_reg = true;
+#else
+               if (i == REG_CSGSFS) {
+                       struct selectors *req_sels =
+                               (void *)&requested_regs[REG_CSGSFS];
+                       struct selectors *res_sels =
+                               (void *)&resulting_regs[REG_CSGSFS];
+                       if (req_sels->cs != res_sels->cs) {
+                               printf("[FAIL]\tCS mismatch: requested 0x%hx; got 0x%hx\n",
+                                      req_sels->cs, res_sels->cs);
+                               nerrs++;
+                       }
+
+                       if (req_sels->ss != res_sels->ss) {
+                               printf("[FAIL]\tSS mismatch: requested 0x%hx; got 0x%hx\n",
+                                      req_sels->ss, res_sels->ss);
+                               nerrs++;
+                       }
+
+                       continue;
+               }
+#endif
+
+               /* Sanity check on the kernel */
+               if (i == REG_AX && requested_regs[i] != resulting_regs[i]) {
+                       printf("[FAIL]\tAX (saved SP) mismatch: requested 0x%llx; got 0x%llx\n",
+                              (unsigned long long)requested_regs[i],
+                              (unsigned long long)resulting_regs[i]);
+                       nerrs++;
+                       continue;
+               }
+
+               if (requested_regs[i] != resulting_regs[i] && !ignore_reg) {
+                       /*
+                        * SP is particularly interesting here.  The
+                        * usual cause of failures is that we hit the
+                        * nasty IRET case of returning to a 16-bit SS,
+                        * in which case bits 16:31 of the *kernel*
+                        * stack pointer persist in ESP.
+                        */
+                       printf("[FAIL]\tReg %d mismatch: requested 0x%llx; got 0x%llx\n",
+                              i, (unsigned long long)requested_regs[i],
+                              (unsigned long long)resulting_regs[i]);
+                       nerrs++;
+               }
+       }
+
+       if (nerrs == 0)
+               printf("[OK]\tall registers okay\n");
+
+       return nerrs;
+}
+
+static int test_bad_iret(int cs_bits, unsigned short ss, int force_cs)
+{
+       int cs = force_cs == -1 ? find_cs(cs_bits) : force_cs;
+       if (cs == -1)
+               return 0;
+
+       sig_cs = cs;
+       sig_ss = ss;
+
+       printf("[RUN]\t%d-bit CS (%hx), bogus SS (%hx)\n",
+              cs_bits, sig_cs, sig_ss);
+
+       sig_trapped = 0;
+       raise(SIGUSR1);
+       if (sig_trapped) {
+               char errdesc[32] = "";
+               if (sig_err) {
+                       const char *src = (sig_err & 1) ? " EXT" : "";
+                       const char *table;
+                       if ((sig_err & 0x6) == 0x0)
+                               table = "GDT";
+                       else if ((sig_err & 0x6) == 0x4)
+                               table = "LDT";
+                       else if ((sig_err & 0x6) == 0x2)
+                               table = "IDT";
+                       else
+                               table = "???";
+
+                       sprintf(errdesc, "%s%s index %d, ",
+                               table, src, sig_err >> 3);
+               }
+
+               char trapname[32];
+               if (sig_trapno == 13)
+                       strcpy(trapname, "GP");
+               else if (sig_trapno == 11)
+                       strcpy(trapname, "NP");
+               else if (sig_trapno == 12)
+                       strcpy(trapname, "SS");
+               else if (sig_trapno == 32)
+                       strcpy(trapname, "IRET");  /* X86_TRAP_IRET */
+               else
+                       sprintf(trapname, "%d", sig_trapno);
+
+               printf("[OK]\tGot #%s(0x%lx) (i.e. %s%s)\n",
+                      trapname, (unsigned long)sig_err,
+                      errdesc, strsignal(sig_trapped));
+               return 0;
+       } else {
+               printf("[FAIL]\tDid not get SIGSEGV\n");
+               return 1;
+       }
+}
+
+int main()
+{
+       int total_nerrs = 0;
+       unsigned short my_cs, my_ss;
+
+       asm volatile ("mov %%cs,%0" : "=r" (my_cs));
+       asm volatile ("mov %%ss,%0" : "=r" (my_ss));
+       setup_ldt();
+
+       stack_t stack = {
+               .ss_sp = altstack_data,
+               .ss_size = SIGSTKSZ,
+       };
+       if (sigaltstack(&stack, NULL) != 0)
+               err(1, "sigaltstack");
+
+       sethandler(SIGUSR1, sigusr1, 0);
+       sethandler(SIGTRAP, sigtrap, SA_ONSTACK);
+
+       /* Easy cases: return to a 32-bit SS in each possible CS bitness. */
+       total_nerrs += test_valid_sigreturn(64, false, -1);
+       total_nerrs += test_valid_sigreturn(32, false, -1);
+       total_nerrs += test_valid_sigreturn(16, false, -1);
+
+       /*
+        * Test easy espfix cases: return to a 16-bit LDT SS in each possible
+        * CS bitness.  NB: with a long mode CS, the SS bitness is irrelevant.
+        *
+        * This catches the original missing-espfix-on-64-bit-kernels issue
+        * as well as CVE-2014-8134.
+        */
+       total_nerrs += test_valid_sigreturn(64, true, -1);
+       total_nerrs += test_valid_sigreturn(32, true, -1);
+       total_nerrs += test_valid_sigreturn(16, true, -1);
+
+       if (gdt_data16_idx) {
+               /*
+                * For performance reasons, Linux skips espfix if SS points
+                * to the GDT.  If we were able to allocate a 16-bit SS in
+                * the GDT, see if it leaks parts of the kernel stack pointer.
+                *
+                * This tests for CVE-2014-8133.
+                */
+               total_nerrs += test_valid_sigreturn(64, true,
+                                                   GDT3(gdt_data16_idx));
+               total_nerrs += test_valid_sigreturn(32, true,
+                                                   GDT3(gdt_data16_idx));
+               total_nerrs += test_valid_sigreturn(16, true,
+                                                   GDT3(gdt_data16_idx));
+       }
+
+       /*
+        * We're done testing valid sigreturn cases.  Now we test states
+        * for which sigreturn itself will succeed but the subsequent
+        * entry to user mode will fail.
+        *
+        * Depending on the failure mode and the kernel bitness, these
+        * entry failures can generate SIGSEGV, SIGBUS, or SIGILL.
+        */
+       clearhandler(SIGTRAP);
+       sethandler(SIGSEGV, sigtrap, SA_ONSTACK);
+       sethandler(SIGBUS, sigtrap, SA_ONSTACK);
+       sethandler(SIGILL, sigtrap, SA_ONSTACK);  /* 32-bit kernels do this */
+
+       /* Easy failures: invalid SS, resulting in #GP(0) */
+       test_bad_iret(64, ldt_nonexistent_sel, -1);
+       test_bad_iret(32, ldt_nonexistent_sel, -1);
+       test_bad_iret(16, ldt_nonexistent_sel, -1);
+
+       /* These fail because SS isn't a data segment, resulting in #GP(SS) */
+       test_bad_iret(64, my_cs, -1);
+       test_bad_iret(32, my_cs, -1);
+       test_bad_iret(16, my_cs, -1);
+
+       /* Try to return to a not-present code segment, triggering #NP(SS). */
+       test_bad_iret(32, my_ss, npcode32_sel);
+
+       /*
+        * Try to return to a not-present but otherwise valid data segment.
+        * This will cause IRET to fail with #SS on the espfix stack.  This
+        * exercises CVE-2014-9322.
+        *
+        * Note that, if espfix is enabled, 64-bit Linux will lose track
+        * of the actual cause of failure and report #GP(0) instead.
+        * This would be very difficult for Linux to avoid, because
+        * espfix64 causes IRET failures to be promoted to #DF, so the
+        * original exception frame is never pushed onto the stack.
+        */
+       test_bad_iret(32, npdata32_sel, -1);
+
+       /*
+        * Try to return to a not-present but otherwise valid data
+        * segment without invoking espfix.  Newer kernels don't allow
+        * this to happen in the first place.  On older kernels, though,
+        * this can trigger CVE-2014-9322.
+        */
+       if (gdt_npdata32_idx)
+               test_bad_iret(32, GDT3(gdt_npdata32_idx), -1);
+
+       return total_nerrs ? 1 : 0;
+}
diff --git a/tools/testing/selftests/x86/trivial_32bit_program.c b/tools/testing/selftests/x86/trivial_32bit_program.c
new file mode 100644 (file)
index 0000000..2e231be
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Trivial program to check that we have a valid 32-bit build environment.
+ * Copyright (c) 2015 Andy Lutomirski
+ * GPL v2
+ */
+
+#include <stdio.h>
+
+int main()
+{
+       printf("\n");
+
+       return 0;
+}
index 6e54f3542126b189be45d2bce32b009721a9d3ab..98c95f2fcba4a63912fb81fbafd3854b08835e00 100644 (file)
@@ -85,13 +85,22 @@ static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+/*
+ * Work function for handling the backup timer that we schedule when a vcpu is
+ * no longer running, but had a timer programmed to fire in the future.
+ */
 static void kvm_timer_inject_irq_work(struct work_struct *work)
 {
        struct kvm_vcpu *vcpu;
 
        vcpu = container_of(work, struct kvm_vcpu, arch.timer_cpu.expired);
        vcpu->arch.timer_cpu.armed = false;
-       kvm_timer_inject_irq(vcpu);
+
+       /*
+        * If the vcpu is blocked we want to wake it up so that it will see
+        * the timer has expired when entering the guest.
+        */
+       kvm_vcpu_kick(vcpu);
 }
 
 static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
@@ -102,6 +111,21 @@ static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
        return HRTIMER_NORESTART;
 }
 
+bool kvm_timer_should_fire(struct kvm_vcpu *vcpu)
+{
+       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+       cycle_t cval, now;
+
+       if ((timer->cntv_ctl & ARCH_TIMER_CTRL_IT_MASK) ||
+               !(timer->cntv_ctl & ARCH_TIMER_CTRL_ENABLE))
+               return false;
+
+       cval = timer->cntv_cval;
+       now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
+
+       return cval <= now;
+}
+
 /**
  * kvm_timer_flush_hwstate - prepare to move the virt timer to the cpu
  * @vcpu: The vcpu pointer
@@ -119,6 +143,13 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
         * populate the CPU timer again.
         */
        timer_disarm(timer);
+
+       /*
+        * If the timer expired while we were not scheduled, now is the time
+        * to inject it.
+        */
+       if (kvm_timer_should_fire(vcpu))
+               kvm_timer_inject_irq(vcpu);
 }
 
 /**
@@ -134,16 +165,9 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
        cycle_t cval, now;
        u64 ns;
 
-       if ((timer->cntv_ctl & ARCH_TIMER_CTRL_IT_MASK) ||
-               !(timer->cntv_ctl & ARCH_TIMER_CTRL_ENABLE))
-               return;
-
-       cval = timer->cntv_cval;
-       now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
-
        BUG_ON(timer_is_armed(timer));
 
-       if (cval <= now) {
+       if (kvm_timer_should_fire(vcpu)) {
                /*
                 * Timer has already expired while we were not
                 * looking. Inject the interrupt and carry on.
@@ -152,6 +176,9 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
                return;
        }
 
+       cval = timer->cntv_cval;
+       now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
+
        ns = cyclecounter_cyc2ns(timecounter->cc, cval - now, timecounter->mask,
                                 &timecounter->frac);
        timer_arm(timer, ns);
index 19c6210f02cf5c2003b96a3ecbb198321114a2a6..13907970d11c3a94b8dc0a5b1848973035cc41cf 100644 (file)
@@ -107,6 +107,22 @@ static bool handle_mmio_clear_pending_reg(struct kvm_vcpu *vcpu,
                                             vcpu->vcpu_id);
 }
 
+static bool handle_mmio_set_active_reg(struct kvm_vcpu *vcpu,
+                                      struct kvm_exit_mmio *mmio,
+                                      phys_addr_t offset)
+{
+       return vgic_handle_set_active_reg(vcpu->kvm, mmio, offset,
+                                         vcpu->vcpu_id);
+}
+
+static bool handle_mmio_clear_active_reg(struct kvm_vcpu *vcpu,
+                                        struct kvm_exit_mmio *mmio,
+                                        phys_addr_t offset)
+{
+       return vgic_handle_clear_active_reg(vcpu->kvm, mmio, offset,
+                                           vcpu->vcpu_id);
+}
+
 static bool handle_mmio_priority_reg(struct kvm_vcpu *vcpu,
                                     struct kvm_exit_mmio *mmio,
                                     phys_addr_t offset)
@@ -303,7 +319,7 @@ static bool handle_mmio_sgi_clear(struct kvm_vcpu *vcpu,
                return write_set_clear_sgi_pend_reg(vcpu, mmio, offset, false);
 }
 
-static const struct kvm_mmio_range vgic_dist_ranges[] = {
+static const struct vgic_io_range vgic_dist_ranges[] = {
        {
                .base           = GIC_DIST_CTRL,
                .len            = 12,
@@ -344,13 +360,13 @@ static const struct kvm_mmio_range vgic_dist_ranges[] = {
                .base           = GIC_DIST_ACTIVE_SET,
                .len            = VGIC_MAX_IRQS / 8,
                .bits_per_irq   = 1,
-               .handle_mmio    = handle_mmio_raz_wi,
+               .handle_mmio    = handle_mmio_set_active_reg,
        },
        {
                .base           = GIC_DIST_ACTIVE_CLEAR,
                .len            = VGIC_MAX_IRQS / 8,
                .bits_per_irq   = 1,
-               .handle_mmio    = handle_mmio_raz_wi,
+               .handle_mmio    = handle_mmio_clear_active_reg,
        },
        {
                .base           = GIC_DIST_PRI,
@@ -388,24 +404,6 @@ static const struct kvm_mmio_range vgic_dist_ranges[] = {
        {}
 };
 
-static bool vgic_v2_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
-                               struct kvm_exit_mmio *mmio)
-{
-       unsigned long base = vcpu->kvm->arch.vgic.vgic_dist_base;
-
-       if (!is_in_range(mmio->phys_addr, mmio->len, base,
-                        KVM_VGIC_V2_DIST_SIZE))
-               return false;
-
-       /* GICv2 does not support accesses wider than 32 bits */
-       if (mmio->len > 4) {
-               kvm_inject_dabt(vcpu, mmio->phys_addr);
-               return true;
-       }
-
-       return vgic_handle_mmio_range(vcpu, run, mmio, vgic_dist_ranges, base);
-}
-
 static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg)
 {
        struct kvm *kvm = vcpu->kvm;
@@ -490,6 +488,7 @@ static bool vgic_v2_queue_sgi(struct kvm_vcpu *vcpu, int irq)
 static int vgic_v2_map_resources(struct kvm *kvm,
                                 const struct vgic_params *params)
 {
+       struct vgic_dist *dist = &kvm->arch.vgic;
        int ret = 0;
 
        if (!irqchip_in_kernel(kvm))
@@ -500,13 +499,17 @@ static int vgic_v2_map_resources(struct kvm *kvm,
        if (vgic_ready(kvm))
                goto out;
 
-       if (IS_VGIC_ADDR_UNDEF(kvm->arch.vgic.vgic_dist_base) ||
-           IS_VGIC_ADDR_UNDEF(kvm->arch.vgic.vgic_cpu_base)) {
+       if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
+           IS_VGIC_ADDR_UNDEF(dist->vgic_cpu_base)) {
                kvm_err("Need to set vgic cpu and dist addresses first\n");
                ret = -ENXIO;
                goto out;
        }
 
+       vgic_register_kvm_io_dev(kvm, dist->vgic_dist_base,
+                                KVM_VGIC_V2_DIST_SIZE,
+                                vgic_dist_ranges, -1, &dist->dist_iodev);
+
        /*
         * Initialize the vgic if this hasn't already been done on demand by
         * accessing the vgic state from userspace.
@@ -514,18 +517,23 @@ static int vgic_v2_map_resources(struct kvm *kvm,
        ret = vgic_init(kvm);
        if (ret) {
                kvm_err("Unable to allocate maps\n");
-               goto out;
+               goto out_unregister;
        }
 
-       ret = kvm_phys_addr_ioremap(kvm, kvm->arch.vgic.vgic_cpu_base,
+       ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base,
                                    params->vcpu_base, KVM_VGIC_V2_CPU_SIZE,
                                    true);
        if (ret) {
                kvm_err("Unable to remap VGIC CPU to VCPU\n");
-               goto out;
+               goto out_unregister;
        }
 
-       kvm->arch.vgic.ready = true;
+       dist->ready = true;
+       goto out;
+
+out_unregister:
+       kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &dist->dist_iodev.dev);
+
 out:
        if (ret)
                kvm_vgic_destroy(kvm);
@@ -554,7 +562,6 @@ void vgic_v2_init_emulation(struct kvm *kvm)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
 
-       dist->vm_ops.handle_mmio = vgic_v2_handle_mmio;
        dist->vm_ops.queue_sgi = vgic_v2_queue_sgi;
        dist->vm_ops.add_sgi_source = vgic_v2_add_sgi_source;
        dist->vm_ops.init_model = vgic_v2_init_model;
@@ -631,7 +638,7 @@ static bool handle_cpu_mmio_ident(struct kvm_vcpu *vcpu,
  * CPU Interface Register accesses - these are not accessed by the VM, but by
  * user space for saving and restoring VGIC state.
  */
-static const struct kvm_mmio_range vgic_cpu_ranges[] = {
+static const struct vgic_io_range vgic_cpu_ranges[] = {
        {
                .base           = GIC_CPU_CTRL,
                .len            = 12,
@@ -658,12 +665,13 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
                                 struct kvm_device_attr *attr,
                                 u32 *reg, bool is_write)
 {
-       const struct kvm_mmio_range *r = NULL, *ranges;
+       const struct vgic_io_range *r = NULL, *ranges;
        phys_addr_t offset;
        int ret, cpuid, c;
        struct kvm_vcpu *vcpu, *tmp_vcpu;
        struct vgic_dist *vgic;
        struct kvm_exit_mmio mmio;
+       u32 data;
 
        offset = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
        cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
@@ -685,6 +693,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 
        mmio.len = 4;
        mmio.is_write = is_write;
+       mmio.data = &data;
        if (is_write)
                mmio_data_write(&mmio, ~0, *reg);
        switch (attr->group) {
@@ -699,7 +708,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
        default:
                BUG();
        }
-       r = vgic_find_range(ranges, &mmio, offset);
+       r = vgic_find_range(ranges, 4, offset);
 
        if (unlikely(!r || !r->handle_mmio)) {
                ret = -ENXIO;
index b3f154631515eda6bccef2a6094757cf0f0b135f..e9c3a7a83833bf2ef058cfd407b92bafe20da073 100644 (file)
@@ -340,7 +340,7 @@ static bool handle_mmio_idregs(struct kvm_vcpu *vcpu,
        return false;
 }
 
-static const struct kvm_mmio_range vgic_v3_dist_ranges[] = {
+static const struct vgic_io_range vgic_v3_dist_ranges[] = {
        {
                .base           = GICD_CTLR,
                .len            = 0x04,
@@ -502,6 +502,43 @@ static const struct kvm_mmio_range vgic_v3_dist_ranges[] = {
        {},
 };
 
+static bool handle_mmio_ctlr_redist(struct kvm_vcpu *vcpu,
+                                   struct kvm_exit_mmio *mmio,
+                                   phys_addr_t offset)
+{
+       /* since we don't support LPIs, this register is zero for now */
+       vgic_reg_access(mmio, NULL, offset,
+                       ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED);
+       return false;
+}
+
+static bool handle_mmio_typer_redist(struct kvm_vcpu *vcpu,
+                                    struct kvm_exit_mmio *mmio,
+                                    phys_addr_t offset)
+{
+       u32 reg;
+       u64 mpidr;
+       struct kvm_vcpu *redist_vcpu = mmio->private;
+       int target_vcpu_id = redist_vcpu->vcpu_id;
+
+       /* the upper 32 bits contain the affinity value */
+       if ((offset & ~3) == 4) {
+               mpidr = kvm_vcpu_get_mpidr_aff(redist_vcpu);
+               reg = compress_mpidr(mpidr);
+
+               vgic_reg_access(mmio, &reg, offset,
+                               ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
+               return false;
+       }
+
+       reg = redist_vcpu->vcpu_id << 8;
+       if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1)
+               reg |= GICR_TYPER_LAST;
+       vgic_reg_access(mmio, &reg, offset,
+                       ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
+       return false;
+}
+
 static bool handle_mmio_set_enable_reg_redist(struct kvm_vcpu *vcpu,
                                              struct kvm_exit_mmio *mmio,
                                              phys_addr_t offset)
@@ -570,186 +607,107 @@ static bool handle_mmio_cfg_reg_redist(struct kvm_vcpu *vcpu,
        return vgic_handle_cfg_reg(reg, mmio, offset);
 }
 
-static const struct kvm_mmio_range vgic_redist_sgi_ranges[] = {
+#define SGI_base(x) ((x) + SZ_64K)
+
+static const struct vgic_io_range vgic_redist_ranges[] = {
+       {
+               .base           = GICR_CTLR,
+               .len            = 0x04,
+               .bits_per_irq   = 0,
+               .handle_mmio    = handle_mmio_ctlr_redist,
+       },
+       {
+               .base           = GICR_TYPER,
+               .len            = 0x08,
+               .bits_per_irq   = 0,
+               .handle_mmio    = handle_mmio_typer_redist,
+       },
+       {
+               .base           = GICR_IIDR,
+               .len            = 0x04,
+               .bits_per_irq   = 0,
+               .handle_mmio    = handle_mmio_iidr,
+       },
+       {
+               .base           = GICR_WAKER,
+               .len            = 0x04,
+               .bits_per_irq   = 0,
+               .handle_mmio    = handle_mmio_raz_wi,
+       },
        {
-               .base           = GICR_IGROUPR0,
+               .base           = GICR_IDREGS,
+               .len            = 0x30,
+               .bits_per_irq   = 0,
+               .handle_mmio    = handle_mmio_idregs,
+       },
+       {
+               .base           = SGI_base(GICR_IGROUPR0),
                .len            = 0x04,
                .bits_per_irq   = 1,
                .handle_mmio    = handle_mmio_rao_wi,
        },
        {
-               .base           = GICR_ISENABLER0,
+               .base           = SGI_base(GICR_ISENABLER0),
                .len            = 0x04,
                .bits_per_irq   = 1,
                .handle_mmio    = handle_mmio_set_enable_reg_redist,
        },
        {
-               .base           = GICR_ICENABLER0,
+               .base           = SGI_base(GICR_ICENABLER0),
                .len            = 0x04,
                .bits_per_irq   = 1,
                .handle_mmio    = handle_mmio_clear_enable_reg_redist,
        },
        {
-               .base           = GICR_ISPENDR0,
+               .base           = SGI_base(GICR_ISPENDR0),
                .len            = 0x04,
                .bits_per_irq   = 1,
                .handle_mmio    = handle_mmio_set_pending_reg_redist,
        },
        {
-               .base           = GICR_ICPENDR0,
+               .base           = SGI_base(GICR_ICPENDR0),
                .len            = 0x04,
                .bits_per_irq   = 1,
                .handle_mmio    = handle_mmio_clear_pending_reg_redist,
        },
        {
-               .base           = GICR_ISACTIVER0,
+               .base           = SGI_base(GICR_ISACTIVER0),
                .len            = 0x04,
                .bits_per_irq   = 1,
                .handle_mmio    = handle_mmio_raz_wi,
        },
        {
-               .base           = GICR_ICACTIVER0,
+               .base           = SGI_base(GICR_ICACTIVER0),
                .len            = 0x04,
                .bits_per_irq   = 1,
                .handle_mmio    = handle_mmio_raz_wi,
        },
        {
-               .base           = GICR_IPRIORITYR0,
+               .base           = SGI_base(GICR_IPRIORITYR0),
                .len            = 0x20,
                .bits_per_irq   = 8,
                .handle_mmio    = handle_mmio_priority_reg_redist,
        },
        {
-               .base           = GICR_ICFGR0,
+               .base           = SGI_base(GICR_ICFGR0),
                .len            = 0x08,
                .bits_per_irq   = 2,
                .handle_mmio    = handle_mmio_cfg_reg_redist,
        },
        {
-               .base           = GICR_IGRPMODR0,
+               .base           = SGI_base(GICR_IGRPMODR0),
                .len            = 0x04,
                .bits_per_irq   = 1,
                .handle_mmio    = handle_mmio_raz_wi,
        },
        {
-               .base           = GICR_NSACR,
+               .base           = SGI_base(GICR_NSACR),
                .len            = 0x04,
                .handle_mmio    = handle_mmio_raz_wi,
        },
        {},
 };
 
-static bool handle_mmio_ctlr_redist(struct kvm_vcpu *vcpu,
-                                   struct kvm_exit_mmio *mmio,
-                                   phys_addr_t offset)
-{
-       /* since we don't support LPIs, this register is zero for now */
-       vgic_reg_access(mmio, NULL, offset,
-                       ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED);
-       return false;
-}
-
-static bool handle_mmio_typer_redist(struct kvm_vcpu *vcpu,
-                                    struct kvm_exit_mmio *mmio,
-                                    phys_addr_t offset)
-{
-       u32 reg;
-       u64 mpidr;
-       struct kvm_vcpu *redist_vcpu = mmio->private;
-       int target_vcpu_id = redist_vcpu->vcpu_id;
-
-       /* the upper 32 bits contain the affinity value */
-       if ((offset & ~3) == 4) {
-               mpidr = kvm_vcpu_get_mpidr_aff(redist_vcpu);
-               reg = compress_mpidr(mpidr);
-
-               vgic_reg_access(mmio, &reg, offset,
-                               ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
-               return false;
-       }
-
-       reg = redist_vcpu->vcpu_id << 8;
-       if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1)
-               reg |= GICR_TYPER_LAST;
-       vgic_reg_access(mmio, &reg, offset,
-                       ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
-       return false;
-}
-
-static const struct kvm_mmio_range vgic_redist_ranges[] = {
-       {
-               .base           = GICR_CTLR,
-               .len            = 0x04,
-               .bits_per_irq   = 0,
-               .handle_mmio    = handle_mmio_ctlr_redist,
-       },
-       {
-               .base           = GICR_TYPER,
-               .len            = 0x08,
-               .bits_per_irq   = 0,
-               .handle_mmio    = handle_mmio_typer_redist,
-       },
-       {
-               .base           = GICR_IIDR,
-               .len            = 0x04,
-               .bits_per_irq   = 0,
-               .handle_mmio    = handle_mmio_iidr,
-       },
-       {
-               .base           = GICR_WAKER,
-               .len            = 0x04,
-               .bits_per_irq   = 0,
-               .handle_mmio    = handle_mmio_raz_wi,
-       },
-       {
-               .base           = GICR_IDREGS,
-               .len            = 0x30,
-               .bits_per_irq   = 0,
-               .handle_mmio    = handle_mmio_idregs,
-       },
-       {},
-};
-
-/*
- * This function splits accesses between the distributor and the two
- * redistributor parts (private/SPI). As each redistributor is accessible
- * from any CPU, we have to determine the affected VCPU by taking the faulting
- * address into account. We then pass this VCPU to the handler function via
- * the private parameter.
- */
-#define SGI_BASE_OFFSET SZ_64K
-static bool vgic_v3_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
-                               struct kvm_exit_mmio *mmio)
-{
-       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
-       unsigned long dbase = dist->vgic_dist_base;
-       unsigned long rdbase = dist->vgic_redist_base;
-       int nrcpus = atomic_read(&vcpu->kvm->online_vcpus);
-       int vcpu_id;
-       const struct kvm_mmio_range *mmio_range;
-
-       if (is_in_range(mmio->phys_addr, mmio->len, dbase, GIC_V3_DIST_SIZE)) {
-               return vgic_handle_mmio_range(vcpu, run, mmio,
-                                             vgic_v3_dist_ranges, dbase);
-       }
-
-       if (!is_in_range(mmio->phys_addr, mmio->len, rdbase,
-           GIC_V3_REDIST_SIZE * nrcpus))
-               return false;
-
-       vcpu_id = (mmio->phys_addr - rdbase) / GIC_V3_REDIST_SIZE;
-       rdbase += (vcpu_id * GIC_V3_REDIST_SIZE);
-       mmio->private = kvm_get_vcpu(vcpu->kvm, vcpu_id);
-
-       if (mmio->phys_addr >= rdbase + SGI_BASE_OFFSET) {
-               rdbase += SGI_BASE_OFFSET;
-               mmio_range = vgic_redist_sgi_ranges;
-       } else {
-               mmio_range = vgic_redist_ranges;
-       }
-       return vgic_handle_mmio_range(vcpu, run, mmio, mmio_range, rdbase);
-}
-
 static bool vgic_v3_queue_sgi(struct kvm_vcpu *vcpu, int irq)
 {
        if (vgic_queue_irq(vcpu, 0, irq)) {
@@ -766,6 +724,9 @@ static int vgic_v3_map_resources(struct kvm *kvm,
 {
        int ret = 0;
        struct vgic_dist *dist = &kvm->arch.vgic;
+       gpa_t rdbase = dist->vgic_redist_base;
+       struct vgic_io_device *iodevs = NULL;
+       int i;
 
        if (!irqchip_in_kernel(kvm))
                return 0;
@@ -791,7 +752,41 @@ static int vgic_v3_map_resources(struct kvm *kvm,
                goto out;
        }
 
-       kvm->arch.vgic.ready = true;
+       ret = vgic_register_kvm_io_dev(kvm, dist->vgic_dist_base,
+                                      GIC_V3_DIST_SIZE, vgic_v3_dist_ranges,
+                                      -1, &dist->dist_iodev);
+       if (ret)
+               goto out;
+
+       iodevs = kcalloc(dist->nr_cpus, sizeof(iodevs[0]), GFP_KERNEL);
+       if (!iodevs) {
+               ret = -ENOMEM;
+               goto out_unregister;
+       }
+
+       for (i = 0; i < dist->nr_cpus; i++) {
+               ret = vgic_register_kvm_io_dev(kvm, rdbase,
+                                              SZ_128K, vgic_redist_ranges,
+                                              i, &iodevs[i]);
+               if (ret)
+                       goto out_unregister;
+               rdbase += GIC_V3_REDIST_SIZE;
+       }
+
+       dist->redist_iodevs = iodevs;
+       dist->ready = true;
+       goto out;
+
+out_unregister:
+       kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &dist->dist_iodev.dev);
+       if (iodevs) {
+               for (i = 0; i < dist->nr_cpus; i++) {
+                       if (iodevs[i].dev.ops)
+                               kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+                                                         &iodevs[i].dev);
+               }
+       }
+
 out:
        if (ret)
                kvm_vgic_destroy(kvm);
@@ -832,7 +827,6 @@ void vgic_v3_init_emulation(struct kvm *kvm)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
 
-       dist->vm_ops.handle_mmio = vgic_v3_handle_mmio;
        dist->vm_ops.queue_sgi = vgic_v3_queue_sgi;
        dist->vm_ops.add_sgi_source = vgic_v3_add_sgi_source;
        dist->vm_ops.init_model = vgic_v3_init_model;
index c9f60f52458802f4a66a3912732d8665bc4a3e32..8d550ff14700c8a628b9c2c6ab55301f6bd0e92b 100644 (file)
@@ -31,6 +31,9 @@
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_arm.h>
 #include <asm/kvm_mmu.h>
+#include <trace/events/kvm.h>
+#include <asm/kvm.h>
+#include <kvm/iodev.h>
 
 /*
  * How the whole thing works (courtesy of Christoffer Dall):
@@ -263,6 +266,13 @@ static int vgic_irq_is_queued(struct kvm_vcpu *vcpu, int irq)
        return vgic_bitmap_get_irq_val(&dist->irq_queued, vcpu->vcpu_id, irq);
 }
 
+static int vgic_irq_is_active(struct kvm_vcpu *vcpu, int irq)
+{
+       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+
+       return vgic_bitmap_get_irq_val(&dist->irq_active, vcpu->vcpu_id, irq);
+}
+
 static void vgic_irq_set_queued(struct kvm_vcpu *vcpu, int irq)
 {
        struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
@@ -277,6 +287,20 @@ static void vgic_irq_clear_queued(struct kvm_vcpu *vcpu, int irq)
        vgic_bitmap_set_irq_val(&dist->irq_queued, vcpu->vcpu_id, irq, 0);
 }
 
+static void vgic_irq_set_active(struct kvm_vcpu *vcpu, int irq)
+{
+       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+
+       vgic_bitmap_set_irq_val(&dist->irq_active, vcpu->vcpu_id, irq, 1);
+}
+
+static void vgic_irq_clear_active(struct kvm_vcpu *vcpu, int irq)
+{
+       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+
+       vgic_bitmap_set_irq_val(&dist->irq_active, vcpu->vcpu_id, irq, 0);
+}
+
 static int vgic_dist_irq_get_level(struct kvm_vcpu *vcpu, int irq)
 {
        struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
@@ -520,6 +544,44 @@ bool vgic_handle_clear_pending_reg(struct kvm *kvm,
        return false;
 }
 
+bool vgic_handle_set_active_reg(struct kvm *kvm,
+                               struct kvm_exit_mmio *mmio,
+                               phys_addr_t offset, int vcpu_id)
+{
+       u32 *reg;
+       struct vgic_dist *dist = &kvm->arch.vgic;
+
+       reg = vgic_bitmap_get_reg(&dist->irq_active, vcpu_id, offset);
+       vgic_reg_access(mmio, reg, offset,
+                       ACCESS_READ_VALUE | ACCESS_WRITE_SETBIT);
+
+       if (mmio->is_write) {
+               vgic_update_state(kvm);
+               return true;
+       }
+
+       return false;
+}
+
+bool vgic_handle_clear_active_reg(struct kvm *kvm,
+                                 struct kvm_exit_mmio *mmio,
+                                 phys_addr_t offset, int vcpu_id)
+{
+       u32 *reg;
+       struct vgic_dist *dist = &kvm->arch.vgic;
+
+       reg = vgic_bitmap_get_reg(&dist->irq_active, vcpu_id, offset);
+       vgic_reg_access(mmio, reg, offset,
+                       ACCESS_READ_VALUE | ACCESS_WRITE_CLEARBIT);
+
+       if (mmio->is_write) {
+               vgic_update_state(kvm);
+               return true;
+       }
+
+       return false;
+}
+
 static u32 vgic_cfg_expand(u16 val)
 {
        u32 res = 0;
@@ -588,16 +650,12 @@ bool vgic_handle_cfg_reg(u32 *reg, struct kvm_exit_mmio *mmio,
 }
 
 /**
- * vgic_unqueue_irqs - move pending IRQs from LRs to the distributor
+ * vgic_unqueue_irqs - move pending/active IRQs from LRs to the distributor
  * @vgic_cpu: Pointer to the vgic_cpu struct holding the LRs
  *
- * Move any pending IRQs that have already been assigned to LRs back to the
+ * Move any IRQs that have already been assigned to LRs back to the
  * emulated distributor state so that the complete emulated state can be read
  * from the main emulation structures without investigating the LRs.
- *
- * Note that IRQs in the active state in the LRs get their pending state moved
- * to the distributor but the active state stays in the LRs, because we don't
- * track the active state on the distributor side.
  */
 void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
 {
@@ -613,12 +671,22 @@ void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
                 * 01: pending
                 * 10: active
                 * 11: pending and active
-                *
-                * If the LR holds only an active interrupt (not pending) then
-                * just leave it alone.
                 */
-               if ((lr.state & LR_STATE_MASK) == LR_STATE_ACTIVE)
-                       continue;
+               BUG_ON(!(lr.state & LR_STATE_MASK));
+
+               /* Reestablish SGI source for pending and active IRQs */
+               if (lr.irq < VGIC_NR_SGIS)
+                       add_sgi_source(vcpu, lr.irq, lr.source);
+
+               /*
+                * If the LR holds an active (10) or a pending and active (11)
+                * interrupt then move the active state to the
+                * distributor tracking bit.
+                */
+               if (lr.state & LR_STATE_ACTIVE) {
+                       vgic_irq_set_active(vcpu, lr.irq);
+                       lr.state &= ~LR_STATE_ACTIVE;
+               }
 
                /*
                 * Reestablish the pending state on the distributor and the
@@ -626,21 +694,19 @@ void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
                 * is fine, then we are only setting a few bits that were
                 * already set.
                 */
-               vgic_dist_irq_set_pending(vcpu, lr.irq);
-               if (lr.irq < VGIC_NR_SGIS)
-                       add_sgi_source(vcpu, lr.irq, lr.source);
-               lr.state &= ~LR_STATE_PENDING;
+               if (lr.state & LR_STATE_PENDING) {
+                       vgic_dist_irq_set_pending(vcpu, lr.irq);
+                       lr.state &= ~LR_STATE_PENDING;
+               }
+
                vgic_set_lr(vcpu, i, lr);
 
                /*
-                * If there's no state left on the LR (it could still be
-                * active), then the LR does not hold any useful info and can
-                * be marked as free for other use.
+                * Mark the LR as free for other use.
                 */
-               if (!(lr.state & LR_STATE_MASK)) {
-                       vgic_retire_lr(i, lr.irq, vcpu);
-                       vgic_irq_clear_queued(vcpu, lr.irq);
-               }
+               BUG_ON(lr.state & LR_STATE_MASK);
+               vgic_retire_lr(i, lr.irq, vcpu);
+               vgic_irq_clear_queued(vcpu, lr.irq);
 
                /* Finally update the VGIC state. */
                vgic_update_state(vcpu->kvm);
@@ -648,24 +714,21 @@ void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
 }
 
 const
-struct kvm_mmio_range *vgic_find_range(const struct kvm_mmio_range *ranges,
-                                      struct kvm_exit_mmio *mmio,
-                                      phys_addr_t offset)
-{
-       const struct kvm_mmio_range *r = ranges;
-
-       while (r->len) {
-               if (offset >= r->base &&
-                   (offset + mmio->len) <= (r->base + r->len))
-                       return r;
-               r++;
+struct vgic_io_range *vgic_find_range(const struct vgic_io_range *ranges,
+                                     int len, gpa_t offset)
+{
+       while (ranges->len) {
+               if (offset >= ranges->base &&
+                   (offset + len) <= (ranges->base + ranges->len))
+                       return ranges;
+               ranges++;
        }
 
        return NULL;
 }
 
 static bool vgic_validate_access(const struct vgic_dist *dist,
-                                const struct kvm_mmio_range *range,
+                                const struct vgic_io_range *range,
                                 unsigned long offset)
 {
        int irq;
@@ -693,9 +756,8 @@ static bool vgic_validate_access(const struct vgic_dist *dist,
 static bool call_range_handler(struct kvm_vcpu *vcpu,
                               struct kvm_exit_mmio *mmio,
                               unsigned long offset,
-                              const struct kvm_mmio_range *range)
+                              const struct vgic_io_range *range)
 {
-       u32 *data32 = (void *)mmio->data;
        struct kvm_exit_mmio mmio32;
        bool ret;
 
@@ -712,91 +774,142 @@ static bool call_range_handler(struct kvm_vcpu *vcpu,
        mmio32.private = mmio->private;
 
        mmio32.phys_addr = mmio->phys_addr + 4;
-       if (mmio->is_write)
-               *(u32 *)mmio32.data = data32[1];
+       mmio32.data = &((u32 *)mmio->data)[1];
        ret = range->handle_mmio(vcpu, &mmio32, offset + 4);
-       if (!mmio->is_write)
-               data32[1] = *(u32 *)mmio32.data;
 
        mmio32.phys_addr = mmio->phys_addr;
-       if (mmio->is_write)
-               *(u32 *)mmio32.data = data32[0];
+       mmio32.data = &((u32 *)mmio->data)[0];
        ret |= range->handle_mmio(vcpu, &mmio32, offset);
-       if (!mmio->is_write)
-               data32[0] = *(u32 *)mmio32.data;
 
        return ret;
 }
 
 /**
- * vgic_handle_mmio_range - handle an in-kernel MMIO access
+ * vgic_handle_mmio_access - handle an in-kernel MMIO access
+ * This is called by the read/write KVM IO device wrappers below.
  * @vcpu:      pointer to the vcpu performing the access
- * @run:       pointer to the kvm_run structure
- * @mmio:      pointer to the data describing the access
- * @ranges:    array of MMIO ranges in a given region
- * @mmio_base: base address of that region
+ * @this:      pointer to the KVM IO device in charge
+ * @addr:      guest physical address of the access
+ * @len:       size of the access
+ * @val:       pointer to the data region
+ * @is_write:  read or write access
  *
  * returns true if the MMIO access could be performed
  */
-bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
-                           struct kvm_exit_mmio *mmio,
-                           const struct kvm_mmio_range *ranges,
-                           unsigned long mmio_base)
+static int vgic_handle_mmio_access(struct kvm_vcpu *vcpu,
+                                  struct kvm_io_device *this, gpa_t addr,
+                                  int len, void *val, bool is_write)
 {
-       const struct kvm_mmio_range *range;
        struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+       struct vgic_io_device *iodev = container_of(this,
+                                                   struct vgic_io_device, dev);
+       struct kvm_run *run = vcpu->run;
+       const struct vgic_io_range *range;
+       struct kvm_exit_mmio mmio;
        bool updated_state;
-       unsigned long offset;
+       gpa_t offset;
 
-       offset = mmio->phys_addr - mmio_base;
-       range = vgic_find_range(ranges, mmio, offset);
+       offset = addr - iodev->addr;
+       range = vgic_find_range(iodev->reg_ranges, len, offset);
        if (unlikely(!range || !range->handle_mmio)) {
-               pr_warn("Unhandled access %d %08llx %d\n",
-                       mmio->is_write, mmio->phys_addr, mmio->len);
-               return false;
+               pr_warn("Unhandled access %d %08llx %d\n", is_write, addr, len);
+               return -ENXIO;
        }
 
-       spin_lock(&vcpu->kvm->arch.vgic.lock);
+       mmio.phys_addr = addr;
+       mmio.len = len;
+       mmio.is_write = is_write;
+       mmio.data = val;
+       mmio.private = iodev->redist_vcpu;
+
+       spin_lock(&dist->lock);
        offset -= range->base;
        if (vgic_validate_access(dist, range, offset)) {
-               updated_state = call_range_handler(vcpu, mmio, offset, range);
+               updated_state = call_range_handler(vcpu, &mmio, offset, range);
        } else {
-               if (!mmio->is_write)
-                       memset(mmio->data, 0, mmio->len);
+               if (!is_write)
+                       memset(val, 0, len);
                updated_state = false;
        }
-       spin_unlock(&vcpu->kvm->arch.vgic.lock);
-       kvm_prepare_mmio(run, mmio);
+       spin_unlock(&dist->lock);
+       run->mmio.is_write      = is_write;
+       run->mmio.len           = len;
+       run->mmio.phys_addr     = addr;
+       memcpy(run->mmio.data, val, len);
+
        kvm_handle_mmio_return(vcpu, run);
 
        if (updated_state)
                vgic_kick_vcpus(vcpu->kvm);
 
-       return true;
+       return 0;
+}
+
+static int vgic_handle_mmio_read(struct kvm_vcpu *vcpu,
+                                struct kvm_io_device *this,
+                                gpa_t addr, int len, void *val)
+{
+       return vgic_handle_mmio_access(vcpu, this, addr, len, val, false);
 }
 
+static int vgic_handle_mmio_write(struct kvm_vcpu *vcpu,
+                                 struct kvm_io_device *this,
+                                 gpa_t addr, int len, const void *val)
+{
+       return vgic_handle_mmio_access(vcpu, this, addr, len, (void *)val,
+                                      true);
+}
+
+struct kvm_io_device_ops vgic_io_ops = {
+       .read   = vgic_handle_mmio_read,
+       .write  = vgic_handle_mmio_write,
+};
+
 /**
- * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
- * @vcpu:      pointer to the vcpu performing the access
- * @run:       pointer to the kvm_run structure
- * @mmio:      pointer to the data describing the access
+ * vgic_register_kvm_io_dev - register VGIC register frame on the KVM I/O bus
+ * @kvm:            The VM structure pointer
+ * @base:           The (guest) base address for the register frame
+ * @len:            Length of the register frame window
+ * @ranges:         Describing the handler functions for each register
+ * @redist_vcpu_id: The VCPU ID to pass on to the handlers on call
+ * @iodev:          Points to memory to be passed on to the handler
  *
- * returns true if the MMIO access has been performed in kernel space,
- * and false if it needs to be emulated in user space.
- * Calls the actual handling routine for the selected VGIC model.
+ * @iodev stores the parameters of this function to be usable by the handler
+ * respectively the dispatcher function (since the KVM I/O bus framework lacks
+ * an opaque parameter). Initialization is done in this function, but the
+ * reference should be valid and unique for the whole VGIC lifetime.
+ * If the register frame is not mapped for a specific VCPU, pass -1 to
+ * @redist_vcpu_id.
  */
-bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
-                     struct kvm_exit_mmio *mmio)
+int vgic_register_kvm_io_dev(struct kvm *kvm, gpa_t base, int len,
+                            const struct vgic_io_range *ranges,
+                            int redist_vcpu_id,
+                            struct vgic_io_device *iodev)
 {
-       if (!irqchip_in_kernel(vcpu->kvm))
-               return false;
+       struct kvm_vcpu *vcpu = NULL;
+       int ret;
 
-       /*
-        * This will currently call either vgic_v2_handle_mmio() or
-        * vgic_v3_handle_mmio(), which in turn will call
-        * vgic_handle_mmio_range() defined above.
-        */
-       return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio);
+       if (redist_vcpu_id >= 0)
+               vcpu = kvm_get_vcpu(kvm, redist_vcpu_id);
+
+       iodev->addr             = base;
+       iodev->len              = len;
+       iodev->reg_ranges       = ranges;
+       iodev->redist_vcpu      = vcpu;
+
+       kvm_iodevice_init(&iodev->dev, &vgic_io_ops);
+
+       mutex_lock(&kvm->slots_lock);
+
+       ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, base, len,
+                                     &iodev->dev);
+       mutex_unlock(&kvm->slots_lock);
+
+       /* Mark the iodev as invalid if registration fails. */
+       if (ret)
+               iodev->dev.ops = NULL;
+
+       return ret;
 }
 
 static int vgic_nr_shared_irqs(struct vgic_dist *dist)
@@ -804,6 +917,36 @@ static int vgic_nr_shared_irqs(struct vgic_dist *dist)
        return dist->nr_irqs - VGIC_NR_PRIVATE_IRQS;
 }
 
+static int compute_active_for_cpu(struct kvm_vcpu *vcpu)
+{
+       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+       unsigned long *active, *enabled, *act_percpu, *act_shared;
+       unsigned long active_private, active_shared;
+       int nr_shared = vgic_nr_shared_irqs(dist);
+       int vcpu_id;
+
+       vcpu_id = vcpu->vcpu_id;
+       act_percpu = vcpu->arch.vgic_cpu.active_percpu;
+       act_shared = vcpu->arch.vgic_cpu.active_shared;
+
+       active = vgic_bitmap_get_cpu_map(&dist->irq_active, vcpu_id);
+       enabled = vgic_bitmap_get_cpu_map(&dist->irq_enabled, vcpu_id);
+       bitmap_and(act_percpu, active, enabled, VGIC_NR_PRIVATE_IRQS);
+
+       active = vgic_bitmap_get_shared_map(&dist->irq_active);
+       enabled = vgic_bitmap_get_shared_map(&dist->irq_enabled);
+       bitmap_and(act_shared, active, enabled, nr_shared);
+       bitmap_and(act_shared, act_shared,
+                  vgic_bitmap_get_shared_map(&dist->irq_spi_target[vcpu_id]),
+                  nr_shared);
+
+       active_private = find_first_bit(act_percpu, VGIC_NR_PRIVATE_IRQS);
+       active_shared = find_first_bit(act_shared, nr_shared);
+
+       return (active_private < VGIC_NR_PRIVATE_IRQS ||
+               active_shared < nr_shared);
+}
+
 static int compute_pending_for_cpu(struct kvm_vcpu *vcpu)
 {
        struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
@@ -835,7 +978,7 @@ static int compute_pending_for_cpu(struct kvm_vcpu *vcpu)
 
 /*
  * Update the interrupt state and determine which CPUs have pending
- * interrupts. Must be called with distributor lock held.
+ * or active interrupts. Must be called with distributor lock held.
  */
 void vgic_update_state(struct kvm *kvm)
 {
@@ -849,10 +992,13 @@ void vgic_update_state(struct kvm *kvm)
        }
 
        kvm_for_each_vcpu(c, vcpu, kvm) {
-               if (compute_pending_for_cpu(vcpu)) {
-                       pr_debug("CPU%d has pending interrupts\n", c);
+               if (compute_pending_for_cpu(vcpu))
                        set_bit(c, dist->irq_pending_on_cpu);
-               }
+
+               if (compute_active_for_cpu(vcpu))
+                       set_bit(c, dist->irq_active_on_cpu);
+               else
+                       clear_bit(c, dist->irq_active_on_cpu);
        }
 }
 
@@ -955,6 +1101,26 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu)
        }
 }
 
+static void vgic_queue_irq_to_lr(struct kvm_vcpu *vcpu, int irq,
+                                int lr_nr, struct vgic_lr vlr)
+{
+       if (vgic_irq_is_active(vcpu, irq)) {
+               vlr.state |= LR_STATE_ACTIVE;
+               kvm_debug("Set active, clear distributor: 0x%x\n", vlr.state);
+               vgic_irq_clear_active(vcpu, irq);
+               vgic_update_state(vcpu->kvm);
+       } else if (vgic_dist_irq_is_pending(vcpu, irq)) {
+               vlr.state |= LR_STATE_PENDING;
+               kvm_debug("Set pending: 0x%x\n", vlr.state);
+       }
+
+       if (!vgic_irq_is_edge(vcpu, irq))
+               vlr.state |= LR_EOI_INT;
+
+       vgic_set_lr(vcpu, lr_nr, vlr);
+       vgic_sync_lr_elrsr(vcpu, lr_nr, vlr);
+}
+
 /*
  * Queue an interrupt to a CPU virtual interface. Return true on success,
  * or false if it wasn't possible to queue it.
@@ -982,9 +1148,7 @@ bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
                if (vlr.source == sgi_source_id) {
                        kvm_debug("LR%d piggyback for IRQ%d\n", lr, vlr.irq);
                        BUG_ON(!test_bit(lr, vgic_cpu->lr_used));
-                       vlr.state |= LR_STATE_PENDING;
-                       vgic_set_lr(vcpu, lr, vlr);
-                       vgic_sync_lr_elrsr(vcpu, lr, vlr);
+                       vgic_queue_irq_to_lr(vcpu, irq, lr, vlr);
                        return true;
                }
        }
@@ -1001,12 +1165,8 @@ bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
 
        vlr.irq = irq;
        vlr.source = sgi_source_id;
-       vlr.state = LR_STATE_PENDING;
-       if (!vgic_irq_is_edge(vcpu, irq))
-               vlr.state |= LR_EOI_INT;
-
-       vgic_set_lr(vcpu, lr, vlr);
-       vgic_sync_lr_elrsr(vcpu, lr, vlr);
+       vlr.state = 0;
+       vgic_queue_irq_to_lr(vcpu, irq, lr, vlr);
 
        return true;
 }
@@ -1038,39 +1198,49 @@ static void __kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 {
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
        struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+       unsigned long *pa_percpu, *pa_shared;
        int i, vcpu_id;
        int overflow = 0;
+       int nr_shared = vgic_nr_shared_irqs(dist);
 
        vcpu_id = vcpu->vcpu_id;
 
+       pa_percpu = vcpu->arch.vgic_cpu.pend_act_percpu;
+       pa_shared = vcpu->arch.vgic_cpu.pend_act_shared;
+
+       bitmap_or(pa_percpu, vgic_cpu->pending_percpu, vgic_cpu->active_percpu,
+                 VGIC_NR_PRIVATE_IRQS);
+       bitmap_or(pa_shared, vgic_cpu->pending_shared, vgic_cpu->active_shared,
+                 nr_shared);
        /*
         * We may not have any pending interrupt, or the interrupts
         * may have been serviced from another vcpu. In all cases,
         * move along.
         */
-       if (!kvm_vgic_vcpu_pending_irq(vcpu)) {
-               pr_debug("CPU%d has no pending interrupt\n", vcpu_id);
+       if (!kvm_vgic_vcpu_pending_irq(vcpu) && !kvm_vgic_vcpu_active_irq(vcpu))
                goto epilog;
-       }
 
        /* SGIs */
-       for_each_set_bit(i, vgic_cpu->pending_percpu, VGIC_NR_SGIS) {
+       for_each_set_bit(i, pa_percpu, VGIC_NR_SGIS) {
                if (!queue_sgi(vcpu, i))
                        overflow = 1;
        }
 
        /* PPIs */
-       for_each_set_bit_from(i, vgic_cpu->pending_percpu, VGIC_NR_PRIVATE_IRQS) {
+       for_each_set_bit_from(i, pa_percpu, VGIC_NR_PRIVATE_IRQS) {
                if (!vgic_queue_hwirq(vcpu, i))
                        overflow = 1;
        }
 
        /* SPIs */
-       for_each_set_bit(i, vgic_cpu->pending_shared, vgic_nr_shared_irqs(dist)) {
+       for_each_set_bit(i, pa_shared, nr_shared) {
                if (!vgic_queue_hwirq(vcpu, i + VGIC_NR_PRIVATE_IRQS))
                        overflow = 1;
        }
 
+
+
+
 epilog:
        if (overflow) {
                vgic_enable_underflow(vcpu);
@@ -1089,7 +1259,9 @@ epilog:
 static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
 {
        u32 status = vgic_get_interrupt_status(vcpu);
+       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
        bool level_pending = false;
+       struct kvm *kvm = vcpu->kvm;
 
        kvm_debug("STATUS = %08x\n", status);
 
@@ -1106,6 +1278,7 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
                        struct vgic_lr vlr = vgic_get_lr(vcpu, lr);
                        WARN_ON(vgic_irq_is_edge(vcpu, vlr.irq));
 
+                       spin_lock(&dist->lock);
                        vgic_irq_clear_queued(vcpu, vlr.irq);
                        WARN_ON(vlr.state & LR_STATE_MASK);
                        vlr.state = 0;
@@ -1124,6 +1297,17 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
                         */
                        vgic_dist_irq_clear_soft_pend(vcpu, vlr.irq);
 
+                       /*
+                        * kvm_notify_acked_irq calls kvm_set_irq()
+                        * to reset the IRQ level. Need to release the
+                        * lock for kvm_set_irq to grab it.
+                        */
+                       spin_unlock(&dist->lock);
+
+                       kvm_notify_acked_irq(kvm, 0,
+                                            vlr.irq - VGIC_NR_PRIVATE_IRQS);
+                       spin_lock(&dist->lock);
+
                        /* Any additional pending interrupt? */
                        if (vgic_dist_irq_get_level(vcpu, vlr.irq)) {
                                vgic_cpu_irq_set(vcpu, vlr.irq);
@@ -1133,6 +1317,8 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
                                vgic_cpu_irq_clear(vcpu, vlr.irq);
                        }
 
+                       spin_unlock(&dist->lock);
+
                        /*
                         * Despite being EOIed, the LR may not have
                         * been marked as empty.
@@ -1155,10 +1341,7 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
        return level_pending;
 }
 
-/*
- * Sync back the VGIC state after a guest run. The distributor lock is
- * needed so we don't get preempted in the middle of the state processing.
- */
+/* Sync back the VGIC state after a guest run */
 static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
 {
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
@@ -1205,14 +1388,10 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 
 void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
 {
-       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
-
        if (!irqchip_in_kernel(vcpu->kvm))
                return;
 
-       spin_lock(&dist->lock);
        __kvm_vgic_sync_hwstate(vcpu);
-       spin_unlock(&dist->lock);
 }
 
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
@@ -1225,6 +1404,17 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
        return test_bit(vcpu->vcpu_id, dist->irq_pending_on_cpu);
 }
 
+int kvm_vgic_vcpu_active_irq(struct kvm_vcpu *vcpu)
+{
+       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+
+       if (!irqchip_in_kernel(vcpu->kvm))
+               return 0;
+
+       return test_bit(vcpu->vcpu_id, dist->irq_active_on_cpu);
+}
+
+
 void vgic_kick_vcpus(struct kvm *kvm)
 {
        struct kvm_vcpu *vcpu;
@@ -1397,8 +1587,12 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
 
        kfree(vgic_cpu->pending_shared);
+       kfree(vgic_cpu->active_shared);
+       kfree(vgic_cpu->pend_act_shared);
        kfree(vgic_cpu->vgic_irq_lr_map);
        vgic_cpu->pending_shared = NULL;
+       vgic_cpu->active_shared = NULL;
+       vgic_cpu->pend_act_shared = NULL;
        vgic_cpu->vgic_irq_lr_map = NULL;
 }
 
@@ -1408,9 +1602,14 @@ static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs)
 
        int sz = (nr_irqs - VGIC_NR_PRIVATE_IRQS) / 8;
        vgic_cpu->pending_shared = kzalloc(sz, GFP_KERNEL);
+       vgic_cpu->active_shared = kzalloc(sz, GFP_KERNEL);
+       vgic_cpu->pend_act_shared = kzalloc(sz, GFP_KERNEL);
        vgic_cpu->vgic_irq_lr_map = kmalloc(nr_irqs, GFP_KERNEL);
 
-       if (!vgic_cpu->pending_shared || !vgic_cpu->vgic_irq_lr_map) {
+       if (!vgic_cpu->pending_shared
+               || !vgic_cpu->active_shared
+               || !vgic_cpu->pend_act_shared
+               || !vgic_cpu->vgic_irq_lr_map) {
                kvm_vgic_vcpu_destroy(vcpu);
                return -ENOMEM;
        }
@@ -1463,10 +1662,12 @@ void kvm_vgic_destroy(struct kvm *kvm)
        kfree(dist->irq_spi_mpidr);
        kfree(dist->irq_spi_target);
        kfree(dist->irq_pending_on_cpu);
+       kfree(dist->irq_active_on_cpu);
        dist->irq_sgi_sources = NULL;
        dist->irq_spi_cpu = NULL;
        dist->irq_spi_target = NULL;
        dist->irq_pending_on_cpu = NULL;
+       dist->irq_active_on_cpu = NULL;
        dist->nr_cpus = 0;
 }
 
@@ -1502,6 +1703,7 @@ int vgic_init(struct kvm *kvm)
        ret |= vgic_init_bitmap(&dist->irq_pending, nr_cpus, nr_irqs);
        ret |= vgic_init_bitmap(&dist->irq_soft_pend, nr_cpus, nr_irqs);
        ret |= vgic_init_bitmap(&dist->irq_queued, nr_cpus, nr_irqs);
+       ret |= vgic_init_bitmap(&dist->irq_active, nr_cpus, nr_irqs);
        ret |= vgic_init_bitmap(&dist->irq_cfg, nr_cpus, nr_irqs);
        ret |= vgic_init_bytemap(&dist->irq_priority, nr_cpus, nr_irqs);
 
@@ -1514,10 +1716,13 @@ int vgic_init(struct kvm *kvm)
                                       GFP_KERNEL);
        dist->irq_pending_on_cpu = kzalloc(BITS_TO_LONGS(nr_cpus) * sizeof(long),
                                           GFP_KERNEL);
+       dist->irq_active_on_cpu = kzalloc(BITS_TO_LONGS(nr_cpus) * sizeof(long),
+                                          GFP_KERNEL);
        if (!dist->irq_sgi_sources ||
            !dist->irq_spi_cpu ||
            !dist->irq_spi_target ||
-           !dist->irq_pending_on_cpu) {
+           !dist->irq_pending_on_cpu ||
+           !dist->irq_active_on_cpu) {
                ret = -ENOMEM;
                goto out;
        }
@@ -1845,12 +2050,9 @@ int vgic_get_common_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
        return r;
 }
 
-int vgic_has_attr_regs(const struct kvm_mmio_range *ranges, phys_addr_t offset)
+int vgic_has_attr_regs(const struct vgic_io_range *ranges, phys_addr_t offset)
 {
-       struct kvm_exit_mmio dev_attr_mmio;
-
-       dev_attr_mmio.len = 4;
-       if (vgic_find_range(ranges, &dev_attr_mmio, offset))
+       if (vgic_find_range(ranges, 4, offset))
                return 0;
        else
                return -ENXIO;
@@ -1883,8 +2085,10 @@ static struct notifier_block vgic_cpu_nb = {
 };
 
 static const struct of_device_id vgic_ids[] = {
-       { .compatible = "arm,cortex-a15-gic", .data = vgic_v2_probe, },
-       { .compatible = "arm,gic-v3", .data = vgic_v3_probe, },
+       { .compatible = "arm,cortex-a15-gic",   .data = vgic_v2_probe, },
+       { .compatible = "arm,cortex-a7-gic",    .data = vgic_v2_probe, },
+       { .compatible = "arm,gic-400",          .data = vgic_v2_probe, },
+       { .compatible = "arm,gic-v3",           .data = vgic_v3_probe, },
        {},
 };
 
@@ -1932,3 +2136,38 @@ out_free_irq:
        free_percpu_irq(vgic->maint_irq, kvm_get_running_vcpus());
        return ret;
 }
+
+int kvm_irq_map_gsi(struct kvm *kvm,
+                   struct kvm_kernel_irq_routing_entry *entries,
+                   int gsi)
+{
+       return gsi;
+}
+
+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin)
+{
+       return pin;
+}
+
+int kvm_set_irq(struct kvm *kvm, int irq_source_id,
+               u32 irq, int level, bool line_status)
+{
+       unsigned int spi = irq + VGIC_NR_PRIVATE_IRQS;
+
+       trace_kvm_set_irq(irq, level, irq_source_id);
+
+       BUG_ON(!vgic_initialized(kvm));
+
+       if (spi > kvm->arch.vgic.nr_irqs)
+               return -EINVAL;
+       return kvm_vgic_inject_irq(kvm, 0, spi, level);
+
+}
+
+/* MSI not implemented yet */
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
+               struct kvm *kvm, int irq_source_id,
+               int level, bool line_status)
+{
+       return 0;
+}
index 1e83bdf5f499b24dd8ea19d5f456fcc740d87bad..0df74cbb6200686ab8cfbc853b11f27cc954b678 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef __KVM_VGIC_H__
 #define __KVM_VGIC_H__
 
+#include <kvm/iodev.h>
+
 #define VGIC_ADDR_UNDEF                (-1)
 #define IS_VGIC_ADDR_UNDEF(_x)  ((_x) == VGIC_ADDR_UNDEF)
 
@@ -57,6 +59,14 @@ void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq);
 void vgic_unqueue_irqs(struct kvm_vcpu *vcpu);
 
+struct kvm_exit_mmio {
+       phys_addr_t     phys_addr;
+       void            *data;
+       u32             len;
+       bool            is_write;
+       void            *private;
+};
+
 void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg,
                     phys_addr_t offset, int mode);
 bool handle_mmio_raz_wi(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
@@ -74,7 +84,7 @@ void mmio_data_write(struct kvm_exit_mmio *mmio, u32 mask, u32 value)
        *((u32 *)mmio->data) = cpu_to_le32(value) & mask;
 }
 
-struct kvm_mmio_range {
+struct vgic_io_range {
        phys_addr_t base;
        unsigned long len;
        int bits_per_irq;
@@ -82,6 +92,11 @@ struct kvm_mmio_range {
                            phys_addr_t offset);
 };
 
+int vgic_register_kvm_io_dev(struct kvm *kvm, gpa_t base, int len,
+                            const struct vgic_io_range *ranges,
+                            int redist_id,
+                            struct vgic_io_device *iodev);
+
 static inline bool is_in_range(phys_addr_t addr, unsigned long len,
                               phys_addr_t baseaddr, unsigned long size)
 {
@@ -89,14 +104,8 @@ static inline bool is_in_range(phys_addr_t addr, unsigned long len,
 }
 
 const
-struct kvm_mmio_range *vgic_find_range(const struct kvm_mmio_range *ranges,
-                                      struct kvm_exit_mmio *mmio,
-                                      phys_addr_t offset);
-
-bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
-                           struct kvm_exit_mmio *mmio,
-                           const struct kvm_mmio_range *ranges,
-                           unsigned long mmio_base);
+struct vgic_io_range *vgic_find_range(const struct vgic_io_range *ranges,
+                                     int len, gpa_t offset);
 
 bool vgic_handle_enable_reg(struct kvm *kvm, struct kvm_exit_mmio *mmio,
                            phys_addr_t offset, int vcpu_id, int access);
@@ -107,12 +116,20 @@ bool vgic_handle_set_pending_reg(struct kvm *kvm, struct kvm_exit_mmio *mmio,
 bool vgic_handle_clear_pending_reg(struct kvm *kvm, struct kvm_exit_mmio *mmio,
                                   phys_addr_t offset, int vcpu_id);
 
+bool vgic_handle_set_active_reg(struct kvm *kvm,
+                               struct kvm_exit_mmio *mmio,
+                               phys_addr_t offset, int vcpu_id);
+
+bool vgic_handle_clear_active_reg(struct kvm *kvm,
+                                 struct kvm_exit_mmio *mmio,
+                                 phys_addr_t offset, int vcpu_id);
+
 bool vgic_handle_cfg_reg(u32 *reg, struct kvm_exit_mmio *mmio,
                         phys_addr_t offset);
 
 void vgic_kick_vcpus(struct kvm *kvm);
 
-int vgic_has_attr_regs(const struct kvm_mmio_range *ranges, phys_addr_t offset);
+int vgic_has_attr_regs(const struct vgic_io_range *ranges, phys_addr_t offset);
 int vgic_set_common_attr(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_get_common_attr(struct kvm_device *dev, struct kvm_device_attr *attr);
 
index 00d86427af0f8bae911c2e41a33303c2d02a3428..571c1ce37d152f86c3690d9e2427f5eeca97cd2c 100644 (file)
@@ -8,7 +8,7 @@
  *
  */
 
-#include "iodev.h"
+#include <kvm/iodev.h>
 
 #include <linux/kvm_host.h>
 #include <linux/slab.h>
@@ -60,8 +60,9 @@ static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev)
        return 1;
 }
 
-static int coalesced_mmio_write(struct kvm_io_device *this,
-                               gpa_t addr, int len, const void *val)
+static int coalesced_mmio_write(struct kvm_vcpu *vcpu,
+                               struct kvm_io_device *this, gpa_t addr,
+                               int len, const void *val)
 {
        struct kvm_coalesced_mmio_dev *dev = to_mmio(this);
        struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring;
index 148b2392c762ba763a6ad09b314699c451b463d0..9ff4193dfa493c3e226c3fd554061b171ca7b9c5 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/seqlock.h>
 #include <trace/events/kvm.h>
 
-#include "iodev.h"
+#include <kvm/iodev.h>
 
 #ifdef CONFIG_HAVE_KVM_IRQFD
 /*
@@ -311,6 +311,9 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
        unsigned int events;
        int idx;
 
+       if (!kvm_arch_intc_initialized(kvm))
+               return -EAGAIN;
+
        irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL);
        if (!irqfd)
                return -ENOMEM;
@@ -712,8 +715,8 @@ ioeventfd_in_range(struct _ioeventfd *p, gpa_t addr, int len, const void *val)
 
 /* MMIO/PIO writes trigger an event if the addr/val match */
 static int
-ioeventfd_write(struct kvm_io_device *this, gpa_t addr, int len,
-               const void *val)
+ioeventfd_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this, gpa_t addr,
+               int len, const void *val)
 {
        struct _ioeventfd *p = to_ioeventfd(this);
 
diff --git a/virt/kvm/iodev.h b/virt/kvm/iodev.h
deleted file mode 100644 (file)
index 12fd3ca..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-#ifndef __KVM_IODEV_H__
-#define __KVM_IODEV_H__
-
-#include <linux/kvm_types.h>
-#include <asm/errno.h>
-
-struct kvm_io_device;
-
-/**
- * kvm_io_device_ops are called under kvm slots_lock.
- * read and write handlers return 0 if the transaction has been handled,
- * or non-zero to have it passed to the next device.
- **/
-struct kvm_io_device_ops {
-       int (*read)(struct kvm_io_device *this,
-                   gpa_t addr,
-                   int len,
-                   void *val);
-       int (*write)(struct kvm_io_device *this,
-                    gpa_t addr,
-                    int len,
-                    const void *val);
-       void (*destructor)(struct kvm_io_device *this);
-};
-
-
-struct kvm_io_device {
-       const struct kvm_io_device_ops *ops;
-};
-
-static inline void kvm_iodevice_init(struct kvm_io_device *dev,
-                                    const struct kvm_io_device_ops *ops)
-{
-       dev->ops = ops;
-}
-
-static inline int kvm_iodevice_read(struct kvm_io_device *dev,
-                                   gpa_t addr, int l, void *v)
-{
-       return dev->ops->read ? dev->ops->read(dev, addr, l, v) : -EOPNOTSUPP;
-}
-
-static inline int kvm_iodevice_write(struct kvm_io_device *dev,
-                                    gpa_t addr, int l, const void *v)
-{
-       return dev->ops->write ? dev->ops->write(dev, addr, l, v) : -EOPNOTSUPP;
-}
-
-static inline void kvm_iodevice_destructor(struct kvm_io_device *dev)
-{
-       if (dev->ops->destructor)
-               dev->ops->destructor(dev);
-}
-
-#endif /* __KVM_IODEV_H__ */
index 7f256f31df102e36da59a8ebed636f1c9615cb00..1d56a901e791788d9f2c855dcf3e96a9b650df77 100644 (file)
@@ -105,7 +105,7 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
        i = kvm_irq_map_gsi(kvm, irq_set, irq);
        srcu_read_unlock(&kvm->irq_srcu, idx);
 
-       while(i--) {
+       while (i--) {
                int r;
                r = irq_set[i].set(&irq_set[i], kvm, irq_source_id, level,
                                   line_status);
index cc6a25d95fbff532bf5b00b0c339bec91ddc5bcf..d3fc9399062a5034b99eaa3d12c855699fdbf608 100644 (file)
@@ -16,7 +16,7 @@
  *
  */
 
-#include "iodev.h"
+#include <kvm/iodev.h>
 
 #include <linux/kvm_host.h>
 #include <linux/kvm.h>
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
-unsigned int halt_poll_ns = 0;
+static unsigned int halt_poll_ns;
 module_param(halt_poll_ns, uint, S_IRUGO | S_IWUSR);
 
 /*
  * Ordering of locks:
  *
- *             kvm->lock --> kvm->slots_lock --> kvm->irq_lock
+ *     kvm->lock --> kvm->slots_lock --> kvm->irq_lock
  */
 
 DEFINE_SPINLOCK(kvm_lock);
@@ -80,7 +80,7 @@ static DEFINE_RAW_SPINLOCK(kvm_count_lock);
 LIST_HEAD(vm_list);
 
 static cpumask_var_t cpus_hardware_enabled;
-static int kvm_usage_count = 0;
+static int kvm_usage_count;
 static atomic_t hardware_enable_failed;
 
 struct kmem_cache *kvm_vcpu_cache;
@@ -539,20 +539,12 @@ void *kvm_kvzalloc(unsigned long size)
                return kzalloc(size, GFP_KERNEL);
 }
 
-void kvm_kvfree(const void *addr)
-{
-       if (is_vmalloc_addr(addr))
-               vfree(addr);
-       else
-               kfree(addr);
-}
-
 static void kvm_destroy_dirty_bitmap(struct kvm_memory_slot *memslot)
 {
        if (!memslot->dirty_bitmap)
                return;
 
-       kvm_kvfree(memslot->dirty_bitmap);
+       kvfree(memslot->dirty_bitmap);
        memslot->dirty_bitmap = NULL;
 }
 
@@ -888,8 +880,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
                 * or moved, memslot will be created.
                 *
                 * validation of sp->gfn happens in:
-                *      - gfn_to_hva (kvm_read_guest, gfn_to_pfn)
-                *      - kvm_is_visible_gfn (mmu_check_roots)
+                *      - gfn_to_hva (kvm_read_guest, gfn_to_pfn)
+                *      - kvm_is_visible_gfn (mmu_check_roots)
                 */
                kvm_arch_flush_shadow_memslot(kvm, slot);
 
@@ -1061,9 +1053,11 @@ int kvm_get_dirty_log_protect(struct kvm *kvm,
                mask = xchg(&dirty_bitmap[i], 0);
                dirty_bitmap_buffer[i] = mask;
 
-               offset = i * BITS_PER_LONG;
-               kvm_arch_mmu_enable_log_dirty_pt_masked(kvm, memslot, offset,
-                                                               mask);
+               if (mask) {
+                       offset = i * BITS_PER_LONG;
+                       kvm_arch_mmu_enable_log_dirty_pt_masked(kvm, memslot,
+                                                               offset, mask);
+               }
        }
 
        spin_unlock(&kvm->mmu_lock);
@@ -1193,16 +1187,6 @@ unsigned long gfn_to_hva_prot(struct kvm *kvm, gfn_t gfn, bool *writable)
        return gfn_to_hva_memslot_prot(slot, gfn, writable);
 }
 
-static int kvm_read_hva(void *data, void __user *hva, int len)
-{
-       return __copy_from_user(data, hva, len);
-}
-
-static int kvm_read_hva_atomic(void *data, void __user *hva, int len)
-{
-       return __copy_from_user_inatomic(data, hva, len);
-}
-
 static int get_user_page_nowait(struct task_struct *tsk, struct mm_struct *mm,
        unsigned long start, int write, struct page **page)
 {
@@ -1481,7 +1465,6 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
 
        return kvm_pfn_to_page(pfn);
 }
-
 EXPORT_SYMBOL_GPL(gfn_to_page);
 
 void kvm_release_page_clean(struct page *page)
@@ -1517,6 +1500,7 @@ void kvm_set_pfn_dirty(pfn_t pfn)
 {
        if (!kvm_is_reserved_pfn(pfn)) {
                struct page *page = pfn_to_page(pfn);
+
                if (!PageReserved(page))
                        SetPageDirty(page);
        }
@@ -1554,7 +1538,7 @@ int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset,
        addr = gfn_to_hva_prot(kvm, gfn, NULL);
        if (kvm_is_error_hva(addr))
                return -EFAULT;
-       r = kvm_read_hva(data, (void __user *)addr + offset, len);
+       r = __copy_from_user(data, (void __user *)addr + offset, len);
        if (r)
                return -EFAULT;
        return 0;
@@ -1593,7 +1577,7 @@ int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data,
        if (kvm_is_error_hva(addr))
                return -EFAULT;
        pagefault_disable();
-       r = kvm_read_hva_atomic(data, (void __user *)addr + offset, len);
+       r = __copy_from_user_inatomic(data, (void __user *)addr + offset, len);
        pagefault_enable();
        if (r)
                return -EFAULT;
@@ -1653,8 +1637,8 @@ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
        ghc->generation = slots->generation;
        ghc->len = len;
        ghc->memslot = gfn_to_memslot(kvm, start_gfn);
-       ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, &nr_pages_avail);
-       if (!kvm_is_error_hva(ghc->hva) && nr_pages_avail >= nr_pages_needed) {
+       ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, NULL);
+       if (!kvm_is_error_hva(ghc->hva) && nr_pages_needed <= 1) {
                ghc->hva += offset;
        } else {
                /*
@@ -1742,7 +1726,7 @@ int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len)
        int offset = offset_in_page(gpa);
        int ret;
 
-        while ((seg = next_segment(len, offset)) != 0) {
+       while ((seg = next_segment(len, offset)) != 0) {
                ret = kvm_clear_guest_page(kvm, gfn, offset, seg);
                if (ret < 0)
                        return ret;
@@ -1800,6 +1784,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
        start = cur = ktime_get();
        if (halt_poll_ns) {
                ktime_t stop = ktime_add_ns(ktime_get(), halt_poll_ns);
+
                do {
                        /*
                         * This sets KVM_REQ_UNHALT if an interrupt
@@ -2118,7 +2103,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
         * Special cases: vcpu ioctls that are asynchronous to vcpu execution,
         * so vcpu_load() would break it.
         */
-       if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_INTERRUPT)
+       if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_S390_IRQ || ioctl == KVM_INTERRUPT)
                return kvm_arch_vcpu_ioctl(filp, ioctl, arg);
 #endif
 
@@ -2135,6 +2120,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
                        /* The thread running this VCPU changed. */
                        struct pid *oldpid = vcpu->pid;
                        struct pid *newpid = get_task_pid(current, PIDTYPE_PID);
+
                        rcu_assign_pointer(vcpu->pid, newpid);
                        if (oldpid)
                                synchronize_rcu();
@@ -2205,7 +2191,7 @@ out_free1:
                if (r)
                        goto out;
                r = -EFAULT;
-               if (copy_to_user(argp, &mp_state, sizeof mp_state))
+               if (copy_to_user(argp, &mp_state, sizeof(mp_state)))
                        goto out;
                r = 0;
                break;
@@ -2214,7 +2200,7 @@ out_free1:
                struct kvm_mp_state mp_state;
 
                r = -EFAULT;
-               if (copy_from_user(&mp_state, argp, sizeof mp_state))
+               if (copy_from_user(&mp_state, argp, sizeof(mp_state)))
                        goto out;
                r = kvm_arch_vcpu_ioctl_set_mpstate(vcpu, &mp_state);
                break;
@@ -2223,13 +2209,13 @@ out_free1:
                struct kvm_translation tr;
 
                r = -EFAULT;
-               if (copy_from_user(&tr, argp, sizeof tr))
+               if (copy_from_user(&tr, argp, sizeof(tr)))
                        goto out;
                r = kvm_arch_vcpu_ioctl_translate(vcpu, &tr);
                if (r)
                        goto out;
                r = -EFAULT;
-               if (copy_to_user(argp, &tr, sizeof tr))
+               if (copy_to_user(argp, &tr, sizeof(tr)))
                        goto out;
                r = 0;
                break;
@@ -2238,7 +2224,7 @@ out_free1:
                struct kvm_guest_debug dbg;
 
                r = -EFAULT;
-               if (copy_from_user(&dbg, argp, sizeof dbg))
+               if (copy_from_user(&dbg, argp, sizeof(dbg)))
                        goto out;
                r = kvm_arch_vcpu_ioctl_set_guest_debug(vcpu, &dbg);
                break;
@@ -2252,14 +2238,14 @@ out_free1:
                if (argp) {
                        r = -EFAULT;
                        if (copy_from_user(&kvm_sigmask, argp,
-                                          sizeof kvm_sigmask))
+                                          sizeof(kvm_sigmask)))
                                goto out;
                        r = -EINVAL;
-                       if (kvm_sigmask.len != sizeof sigset)
+                       if (kvm_sigmask.len != sizeof(sigset))
                                goto out;
                        r = -EFAULT;
                        if (copy_from_user(&sigset, sigmask_arg->sigset,
-                                          sizeof sigset))
+                                          sizeof(sigset)))
                                goto out;
                        p = &sigset;
                }
@@ -2321,14 +2307,14 @@ static long kvm_vcpu_compat_ioctl(struct file *filp,
                if (argp) {
                        r = -EFAULT;
                        if (copy_from_user(&kvm_sigmask, argp,
-                                          sizeof kvm_sigmask))
+                                          sizeof(kvm_sigmask)))
                                goto out;
                        r = -EINVAL;
-                       if (kvm_sigmask.len != sizeof csigset)
+                       if (kvm_sigmask.len != sizeof(csigset))
                                goto out;
                        r = -EFAULT;
                        if (copy_from_user(&csigset, sigmask_arg->sigset,
-                                          sizeof csigset))
+                                          sizeof(csigset)))
                                goto out;
                        sigset_from_compat(&sigset, &csigset);
                        r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
@@ -2525,7 +2511,7 @@ static long kvm_vm_ioctl(struct file *filp,
 
                r = -EFAULT;
                if (copy_from_user(&kvm_userspace_mem, argp,
-                                               sizeof kvm_userspace_mem))
+                                               sizeof(kvm_userspace_mem)))
                        goto out;
 
                r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_userspace_mem);
@@ -2535,7 +2521,7 @@ static long kvm_vm_ioctl(struct file *filp,
                struct kvm_dirty_log log;
 
                r = -EFAULT;
-               if (copy_from_user(&log, argp, sizeof log))
+               if (copy_from_user(&log, argp, sizeof(log)))
                        goto out;
                r = kvm_vm_ioctl_get_dirty_log(kvm, &log);
                break;
@@ -2543,16 +2529,18 @@ static long kvm_vm_ioctl(struct file *filp,
 #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
        case KVM_REGISTER_COALESCED_MMIO: {
                struct kvm_coalesced_mmio_zone zone;
+
                r = -EFAULT;
-               if (copy_from_user(&zone, argp, sizeof zone))
+               if (copy_from_user(&zone, argp, sizeof(zone)))
                        goto out;
                r = kvm_vm_ioctl_register_coalesced_mmio(kvm, &zone);
                break;
        }
        case KVM_UNREGISTER_COALESCED_MMIO: {
                struct kvm_coalesced_mmio_zone zone;
+
                r = -EFAULT;
-               if (copy_from_user(&zone, argp, sizeof zone))
+               if (copy_from_user(&zone, argp, sizeof(zone)))
                        goto out;
                r = kvm_vm_ioctl_unregister_coalesced_mmio(kvm, &zone);
                break;
@@ -2562,7 +2550,7 @@ static long kvm_vm_ioctl(struct file *filp,
                struct kvm_irqfd data;
 
                r = -EFAULT;
-               if (copy_from_user(&data, argp, sizeof data))
+               if (copy_from_user(&data, argp, sizeof(data)))
                        goto out;
                r = kvm_irqfd(kvm, &data);
                break;
@@ -2571,7 +2559,7 @@ static long kvm_vm_ioctl(struct file *filp,
                struct kvm_ioeventfd data;
 
                r = -EFAULT;
-               if (copy_from_user(&data, argp, sizeof data))
+               if (copy_from_user(&data, argp, sizeof(data)))
                        goto out;
                r = kvm_ioeventfd(kvm, &data);
                break;
@@ -2592,7 +2580,7 @@ static long kvm_vm_ioctl(struct file *filp,
                struct kvm_msi msi;
 
                r = -EFAULT;
-               if (copy_from_user(&msi, argp, sizeof msi))
+               if (copy_from_user(&msi, argp, sizeof(msi)))
                        goto out;
                r = kvm_send_userspace_msi(kvm, &msi);
                break;
@@ -2604,7 +2592,7 @@ static long kvm_vm_ioctl(struct file *filp,
                struct kvm_irq_level irq_event;
 
                r = -EFAULT;
-               if (copy_from_user(&irq_event, argp, sizeof irq_event))
+               if (copy_from_user(&irq_event, argp, sizeof(irq_event)))
                        goto out;
 
                r = kvm_vm_ioctl_irq_line(kvm, &irq_event,
@@ -2614,7 +2602,7 @@ static long kvm_vm_ioctl(struct file *filp,
 
                r = -EFAULT;
                if (ioctl == KVM_IRQ_LINE_STATUS) {
-                       if (copy_to_user(argp, &irq_event, sizeof irq_event))
+                       if (copy_to_user(argp, &irq_event, sizeof(irq_event)))
                                goto out;
                }
 
@@ -2647,7 +2635,7 @@ static long kvm_vm_ioctl(struct file *filp,
                        goto out_free_irq_routing;
                r = kvm_set_irq_routing(kvm, entries, routing.nr,
                                        routing.flags);
-       out_free_irq_routing:
+out_free_irq_routing:
                vfree(entries);
                break;
        }
@@ -2822,8 +2810,7 @@ static void hardware_enable_nolock(void *junk)
        if (r) {
                cpumask_clear_cpu(cpu, cpus_hardware_enabled);
                atomic_inc(&hardware_enable_failed);
-               printk(KERN_INFO "kvm: enabling virtualization on "
-                                "CPU%d failed\n", cpu);
+               pr_info("kvm: enabling virtualization on CPU%d failed\n", cpu);
        }
 }
 
@@ -2899,12 +2886,12 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
        val &= ~CPU_TASKS_FROZEN;
        switch (val) {
        case CPU_DYING:
-               printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n",
+               pr_info("kvm: disabling virtualization on CPU%d\n",
                       cpu);
                hardware_disable();
                break;
        case CPU_STARTING:
-               printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n",
+               pr_info("kvm: enabling virtualization on CPU%d\n",
                       cpu);
                hardware_enable();
                break;
@@ -2921,7 +2908,7 @@ static int kvm_reboot(struct notifier_block *notifier, unsigned long val,
         *
         * And Intel TXT required VMX off for all cpu when system shutdown.
         */
-       printk(KERN_INFO "kvm: exiting hardware virtualization\n");
+       pr_info("kvm: exiting hardware virtualization\n");
        kvm_rebooting = true;
        on_each_cpu(hardware_disable_nolock, NULL, 1);
        return NOTIFY_OK;
@@ -2945,7 +2932,7 @@ static void kvm_io_bus_destroy(struct kvm_io_bus *bus)
 }
 
 static inline int kvm_io_bus_cmp(const struct kvm_io_range *r1,
-                                 const struct kvm_io_range *r2)
+                                const struct kvm_io_range *r2)
 {
        if (r1->addr < r2->addr)
                return -1;
@@ -2998,7 +2985,7 @@ static int kvm_io_bus_get_first_dev(struct kvm_io_bus *bus,
        return off;
 }
 
-static int __kvm_io_bus_write(struct kvm_io_bus *bus,
+static int __kvm_io_bus_write(struct kvm_vcpu *vcpu, struct kvm_io_bus *bus,
                              struct kvm_io_range *range, const void *val)
 {
        int idx;
@@ -3009,7 +2996,7 @@ static int __kvm_io_bus_write(struct kvm_io_bus *bus,
 
        while (idx < bus->dev_count &&
                kvm_io_bus_cmp(range, &bus->range[idx]) == 0) {
-               if (!kvm_iodevice_write(bus->range[idx].dev, range->addr,
+               if (!kvm_iodevice_write(vcpu, bus->range[idx].dev, range->addr,
                                        range->len, val))
                        return idx;
                idx++;
@@ -3019,7 +3006,7 @@ static int __kvm_io_bus_write(struct kvm_io_bus *bus,
 }
 
 /* kvm_io_bus_write - called under kvm->slots_lock */
-int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+int kvm_io_bus_write(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
                     int len, const void *val)
 {
        struct kvm_io_bus *bus;
@@ -3031,14 +3018,14 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
                .len = len,
        };
 
-       bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
-       r = __kvm_io_bus_write(bus, &range, val);
+       bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &vcpu->kvm->srcu);
+       r = __kvm_io_bus_write(vcpu, bus, &range, val);
        return r < 0 ? r : 0;
 }
 
 /* kvm_io_bus_write_cookie - called under kvm->slots_lock */
-int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
-                           int len, const void *val, long cookie)
+int kvm_io_bus_write_cookie(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx,
+                           gpa_t addr, int len, const void *val, long cookie)
 {
        struct kvm_io_bus *bus;
        struct kvm_io_range range;
@@ -3048,12 +3035,12 @@ int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
                .len = len,
        };
 
-       bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
+       bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &vcpu->kvm->srcu);
 
        /* First try the device referenced by cookie. */
        if ((cookie >= 0) && (cookie < bus->dev_count) &&
            (kvm_io_bus_cmp(&range, &bus->range[cookie]) == 0))
-               if (!kvm_iodevice_write(bus->range[cookie].dev, addr, len,
+               if (!kvm_iodevice_write(vcpu, bus->range[cookie].dev, addr, len,
                                        val))
                        return cookie;
 
@@ -3061,11 +3048,11 @@ int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
         * cookie contained garbage; fall back to search and return the
         * correct cookie value.
         */
-       return __kvm_io_bus_write(bus, &range, val);
+       return __kvm_io_bus_write(vcpu, bus, &range, val);
 }
 
-static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
-                            void *val)
+static int __kvm_io_bus_read(struct kvm_vcpu *vcpu, struct kvm_io_bus *bus,
+                            struct kvm_io_range *range, void *val)
 {
        int idx;
 
@@ -3075,7 +3062,7 @@ static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
 
        while (idx < bus->dev_count &&
                kvm_io_bus_cmp(range, &bus->range[idx]) == 0) {
-               if (!kvm_iodevice_read(bus->range[idx].dev, range->addr,
+               if (!kvm_iodevice_read(vcpu, bus->range[idx].dev, range->addr,
                                       range->len, val))
                        return idx;
                idx++;
@@ -3086,7 +3073,7 @@ static int __kvm_io_bus_read(struct kvm_io_bus *bus, struct kvm_io_range *range,
 EXPORT_SYMBOL_GPL(kvm_io_bus_write);
 
 /* kvm_io_bus_read - called under kvm->slots_lock */
-int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+int kvm_io_bus_read(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr,
                    int len, void *val)
 {
        struct kvm_io_bus *bus;
@@ -3098,8 +3085,8 @@ int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
                .len = len,
        };
 
-       bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
-       r = __kvm_io_bus_read(bus, &range, val);
+       bus = srcu_dereference(vcpu->kvm->buses[bus_idx], &vcpu->kvm->srcu);
+       r = __kvm_io_bus_read(vcpu, bus, &range, val);
        return r < 0 ? r : 0;
 }
 
@@ -3269,6 +3256,7 @@ struct kvm_vcpu *preempt_notifier_to_vcpu(struct preempt_notifier *pn)
 static void kvm_sched_in(struct preempt_notifier *pn, int cpu)
 {
        struct kvm_vcpu *vcpu = preempt_notifier_to_vcpu(pn);
+
        if (vcpu->preempted)
                vcpu->preempted = false;
 
@@ -3350,7 +3338,7 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
 
        r = misc_register(&kvm_dev);
        if (r) {
-               printk(KERN_ERR "kvm: misc device register failed\n");
+               pr_err("kvm: misc device register failed\n");
                goto out_unreg;
        }
 
@@ -3361,7 +3349,7 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
 
        r = kvm_init_debug();
        if (r) {
-               printk(KERN_ERR "kvm: create debugfs files failed\n");
+               pr_err("kvm: create debugfs files failed\n");
                goto out_undebugfs;
        }